--- linux-2.6.6/arch/alpha/kernel/process.c 2004-05-09 21:07:22.000000000 -0700 +++ 25/arch/alpha/kernel/process.c 2004-05-10 01:19:31.133006120 -0700 @@ -510,12 +510,6 @@ thread_saved_pc(task_t *t) return 0; } -/* - * These bracket the sleeping functions.. - */ -#define first_sched ((unsigned long) scheduling_functions_start_here) -#define last_sched ((unsigned long) scheduling_functions_end_here) - unsigned long get_wchan(struct task_struct *p) { @@ -534,7 +528,7 @@ get_wchan(struct task_struct *p) */ pc = thread_saved_pc(p); - if (pc >= first_sched && pc < last_sched) { + if (in_sched_functions(pc)) { schedule_frame = ((unsigned long *)p->thread_info->pcb.ksp)[6]; return ((unsigned long *)schedule_frame)[12]; } --- linux-2.6.6/arch/alpha/kernel/setup.c 2004-04-03 20:39:10.000000000 -0800 +++ 25/arch/alpha/kernel/setup.c 2004-05-10 01:19:18.562917064 -0700 @@ -122,7 +122,6 @@ static void get_sysnames(unsigned long, static void determine_cpu_caches (unsigned int); static char command_line[COMMAND_LINE_SIZE]; -char saved_command_line[COMMAND_LINE_SIZE]; /* * The format of "screen_info" is strange, and due to early --- linux-2.6.6/arch/alpha/kernel/smp.c 2004-04-03 20:39:10.000000000 -0800 +++ 25/arch/alpha/kernel/smp.c 2004-05-10 01:19:49.903152624 -0700 @@ -820,6 +820,9 @@ smp_call_function_on_cpu (void (*func) ( unsigned long timeout; int num_cpus_to_call; + /* Can deadlock when called with interrupts disabled */ + WARN_ON(irqs_disabled()); + data.func = func; data.info = info; data.wait = wait; --- linux-2.6.6/arch/alpha/kernel/time.c 2004-04-03 20:39:10.000000000 -0800 +++ 25/arch/alpha/kernel/time.c 2004-05-10 01:19:51.561900456 -0700 @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -254,12 +255,11 @@ validate_cc_value(unsigned long cc) * arch/i386/time.c. */ -#define PIC_TICK_RATE 1193180UL #define CALIBRATE_LATCH 0xffff #define TIMEOUT_COUNT 0x100000 static unsigned long __init -calibrate_cc_with_pic(void) +calibrate_cc_with_pit(void) { int cc, count = 0; @@ -287,7 +287,7 @@ calibrate_cc_with_pic(void) if (count <= 1 || count == TIMEOUT_COUNT) return 0; - return ((long)cc * PIC_TICK_RATE) / (CALIBRATE_LATCH + 1); + return ((long)cc * PIT_TICK_RATE) / (CALIBRATE_LATCH + 1); } /* The Linux interpretation of the CMOS clock register contents: @@ -313,7 +313,7 @@ time_init(void) /* Calibrate CPU clock -- attempt #1. */ if (!est_cycle_freq) - est_cycle_freq = validate_cc_value(calibrate_cc_with_pic()); + est_cycle_freq = validate_cc_value(calibrate_cc_with_pit()); cc1 = rpcc_after_update_in_progress(); --- linux-2.6.6/arch/arm26/kernel/process.c 2004-05-09 21:07:22.000000000 -0700 +++ 25/arch/arm26/kernel/process.c 2004-05-10 01:19:31.133006120 -0700 @@ -397,12 +397,6 @@ pid_t kernel_thread(int (*fn)(void *), v return __ret; } -/* - * These bracket the sleeping functions.. - */ -#define first_sched ((unsigned long) scheduling_functions_start_here) -#define last_sched ((unsigned long) scheduling_functions_end_here) - unsigned long get_wchan(struct task_struct *p) { unsigned long fp, lr; @@ -417,7 +411,7 @@ unsigned long get_wchan(struct task_stru if (fp < stack_page || fp > 4092+stack_page) return 0; lr = pc_pointer (((unsigned long *)fp)[-1]); - if (lr < first_sched || lr > last_sched) + if (!in_sched_functions(lr)) return lr; fp = *(unsigned long *) (fp - 12); } while (count ++ < 16); --- linux-2.6.6/arch/arm26/kernel/setup.c 2003-09-27 18:57:43.000000000 -0700 +++ 25/arch/arm26/kernel/setup.c 2004-05-10 01:19:18.563916912 -0700 @@ -76,7 +76,6 @@ struct processor processor; unsigned char aux_device_present; char elf_platform[ELF_PLATFORM_SIZE]; -char saved_command_line[COMMAND_LINE_SIZE]; unsigned long phys_initrd_start __initdata = 0; unsigned long phys_initrd_size __initdata = 0; --- linux-2.6.6/arch/arm/kernel/process.c 2004-05-09 21:07:22.000000000 -0700 +++ 25/arch/arm/kernel/process.c 2004-05-10 01:19:31.134005968 -0700 @@ -411,12 +411,6 @@ pid_t kernel_thread(int (*fn)(void *), v return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); } -/* - * These bracket the sleeping functions.. - */ -#define first_sched ((unsigned long) scheduling_functions_start_here) -#define last_sched ((unsigned long) scheduling_functions_end_here) - unsigned long get_wchan(struct task_struct *p) { unsigned long fp, lr; @@ -431,7 +425,7 @@ unsigned long get_wchan(struct task_stru if (fp < stack_page || fp > 4092+stack_page) return 0; lr = pc_pointer (((unsigned long *)fp)[-1]); - if (lr < first_sched || lr > last_sched) + if (!in_sched_functions(lr)) return lr; fp = *(unsigned long *) (fp - 12); } while (count ++ < 16); --- linux-2.6.6/arch/arm/kernel/setup.c 2004-05-09 21:07:22.000000000 -0700 +++ 25/arch/arm/kernel/setup.c 2004-05-10 01:19:18.564916760 -0700 @@ -81,7 +81,6 @@ struct cpu_cache_fns cpu_cache; unsigned char aux_device_present; char elf_platform[ELF_PLATFORM_SIZE]; -char saved_command_line[COMMAND_LINE_SIZE]; unsigned long phys_initrd_start __initdata = 0; unsigned long phys_initrd_size __initdata = 0; --- linux-2.6.6/arch/arm/mach-integrator/cpu.c 2004-02-17 20:48:42.000000000 -0800 +++ 25/arch/arm/mach-integrator/cpu.c 2004-05-10 01:19:01.778468688 -0700 @@ -152,10 +152,10 @@ static int integrator_set_target(struct return 0; } -static int integrator_cpufreq_init(struct cpufreq_policy *policy) +static unsigned int integrator_get(unsigned int cpu) { unsigned long cpus_allowed; - unsigned int cpu = policy->cpu; + unsigned int current_freq; u_int cm_osc; struct icst525_vco vco; @@ -175,15 +175,22 @@ static int integrator_cpufreq_init(struc vco.v = cm_osc & 255; vco.r = 22; + current_freq = icst525_khz(&cclk_params, vco); /* current freq */ + + set_cpus_allowed(current, cpus_allowed); + + return current_freq; +} + +static int integrator_cpufreq_init(struct cpufreq_policy *policy) +{ + /* set default policy and cpuinfo */ policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.max_freq = 160000; policy->cpuinfo.min_freq = 12000; policy->cpuinfo.transition_latency = 1000000; /* 1 ms, assumed */ - policy->cur = policy->min = policy->max = - icst525_khz(&cclk_params, vco); /* current freq */ - - set_cpus_allowed(current, cpus_allowed); + policy->cur = policy->min = policy->max = integrator_get(policy->cpu); return 0; } @@ -191,6 +198,7 @@ static int integrator_cpufreq_init(struc static struct cpufreq_driver integrator_driver = { .verify = integrator_verify_policy, .target = integrator_set_target, + .get = integrator_get, .init = integrator_cpufreq_init, .name = "integrator", }; --- linux-2.6.6/arch/arm/mach-sa1100/cpu-sa1100.c 2003-10-17 15:58:03.000000000 -0700 +++ 25/arch/arm/mach-sa1100/cpu-sa1100.c 2004-05-10 01:19:01.778468688 -0700 @@ -180,7 +180,7 @@ static int sa1100_target(struct cpufreq_ unsigned int target_freq, unsigned int relation) { - unsigned int cur = sa11x0_getspeed(); + unsigned int cur = sa11x0_getspeed(0); unsigned int new_ppcr; struct cpufreq_freqs freqs; @@ -221,7 +221,7 @@ static int __init sa1100_cpu_init(struct { if (policy->cpu != 0) return -EINVAL; - policy->cur = policy->min = policy->max = sa11x0_getspeed(); + policy->cur = policy->min = policy->max = sa11x0_getspeed(0); policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.min_freq = 59000; policy->cpuinfo.max_freq = 287000; @@ -230,15 +230,17 @@ static int __init sa1100_cpu_init(struct } static struct cpufreq_driver sa1100_driver = { + .flags = (CPUFREQ_PANIC_OUTOFSYNC | + CPUFREQ_PANIC_RESUME_OUTOFSYNC), .verify = sa11x0_verify_speed, .target = sa1100_target, + .get = sa11x0_getspeed, .init = sa1100_cpu_init, .name = "sa1100", }; static int __init sa1100_dram_init(void) { - cpufreq_gov_userspace_init(); if ((processor_id & CPU_SA1100_MASK) == CPU_SA1100_ID) return cpufreq_register_driver(&sa1100_driver); else --- linux-2.6.6/arch/arm/mach-sa1100/cpu-sa1110.c 2003-09-08 13:58:55.000000000 -0700 +++ 25/arch/arm/mach-sa1100/cpu-sa1110.c 2004-05-10 01:19:01.779468536 -0700 @@ -238,7 +238,7 @@ static int sa1110_target(struct cpufreq_ return -EINVAL; } - freqs.old = sa11x0_getspeed(); + freqs.old = sa11x0_getspeed(0); freqs.new = sa11x0_ppcr_to_freq(ppcr); freqs.cpu = 0; @@ -320,7 +320,7 @@ static int __init sa1110_cpu_init(struct { if (policy->cpu != 0) return -EINVAL; - policy->cur = policy->min = policy->max = sa11x0_getspeed(); + policy->cur = policy->min = policy->max = sa11x0_getspeed(0); policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.min_freq = 59000; policy->cpuinfo.max_freq = 287000; @@ -329,8 +329,11 @@ static int __init sa1110_cpu_init(struct } static struct cpufreq_driver sa1110_driver = { + .flags = (CPUFREQ_PANIC_OUTOFSYNC | + CPUFREQ_PANIC_RESUME_OUTOFSYNC), .verify = sa11x0_verify_speed, .target = sa1110_target, + .get = sa11x0_getspeed, .init = sa1110_cpu_init, .name = "sa1110", }; @@ -354,8 +357,6 @@ static int __init sa1110_clk_init(void) sdram->tck, sdram->trcd, sdram->trp, sdram->twr, sdram->refresh, sdram->cas_latency); - cpufreq_gov_userspace_init(); - memcpy(&sdram_params, sdram, sizeof(sdram_params)); return cpufreq_register_driver(&sa1110_driver); --- linux-2.6.6/arch/arm/mach-sa1100/generic.c 2004-04-03 20:39:10.000000000 -0800 +++ 25/arch/arm/mach-sa1100/generic.c 2004-05-10 01:19:01.779468536 -0700 @@ -96,11 +96,13 @@ int sa11x0_verify_speed(struct cpufreq_p return 0; } -unsigned int sa11x0_getspeed(void) +unsigned int sa11x0_getspeed(unsigned int cpu) { + if (cpu) + return 0; return cclk_frequency_100khz[PPCR & 0xf] * 100; } -EXPORT_SYMBOL(sa11x0_getspeed); + #else /* * We still need to provide this so building without cpufreq works. --- linux-2.6.6/arch/arm/mach-sa1100/generic.h 2003-06-14 12:18:25.000000000 -0700 +++ 25/arch/arm/mach-sa1100/generic.h 2004-05-10 01:19:01.780468384 -0700 @@ -22,5 +22,5 @@ struct cpufreq_policy; extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz); extern int sa11x0_verify_speed(struct cpufreq_policy *policy); -extern unsigned int sa11x0_getspeed(void); +extern unsigned int sa11x0_getspeed(unsigned int cpu); extern unsigned int sa11x0_ppcr_to_freq(unsigned int idx); --- linux-2.6.6/arch/arm/mm/fault-armv.c 2004-05-09 21:07:22.000000000 -0700 +++ 25/arch/arm/mm/fault-armv.c 2004-05-10 01:19:13.419698952 -0700 @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -78,7 +79,10 @@ void __flush_dcache_page(struct page *pa { struct address_space *mapping = page_mapping(page); struct mm_struct *mm = current->active_mm; - struct list_head *l; + struct vm_area_struct *mpnt = NULL; + struct prio_tree_iter iter; + unsigned long offset; + pgoff_t pgoff; __cpuc_flush_dcache_page(page_address(page)); @@ -89,36 +93,33 @@ void __flush_dcache_page(struct page *pa * With a VIVT cache, we need to also write back * and invalidate any user data. */ - list_for_each(l, &mapping->i_mmap_shared) { - struct vm_area_struct *mpnt; - unsigned long off; - - mpnt = list_entry(l, struct vm_area_struct, shared); + pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); + flush_dcache_mmap_lock(mapping); + while ((mpnt = vma_prio_tree_next(mpnt, &mapping->i_mmap, + &iter, pgoff, pgoff)) != NULL) { /* * If this VMA is not in our MM, we can ignore it. */ if (mpnt->vm_mm != mm) continue; - - if (page->index < mpnt->vm_pgoff) - continue; - - off = page->index - mpnt->vm_pgoff; - if (off >= (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT) + if (!(mpnt->vm_flags & VM_MAYSHARE)) continue; - - flush_cache_page(mpnt, mpnt->vm_start + (off << PAGE_SHIFT)); + offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT; + flush_cache_page(mpnt, mpnt->vm_start + offset); } + flush_dcache_mmap_unlock(mapping); } static void make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, int dirty) { struct address_space *mapping = page_mapping(page); - struct list_head *l; struct mm_struct *mm = vma->vm_mm; - unsigned long pgoff; + struct vm_area_struct *mpnt = NULL; + struct prio_tree_iter iter; + unsigned long offset; + pgoff_t pgoff; int aliases = 0; if (!mapping) @@ -131,12 +132,9 @@ make_coherent(struct vm_area_struct *vma * space, then we need to handle them specially to maintain * cache coherency. */ - list_for_each(l, &mapping->i_mmap_shared) { - struct vm_area_struct *mpnt; - unsigned long off; - - mpnt = list_entry(l, struct vm_area_struct, shared); - + flush_dcache_mmap_lock(mapping); + while ((mpnt = vma_prio_tree_next(mpnt, &mapping->i_mmap, + &iter, pgoff, pgoff)) != NULL) { /* * If this VMA is not in our MM, we can ignore it. * Note that we intentionally mask out the VMA @@ -144,24 +142,12 @@ make_coherent(struct vm_area_struct *vma */ if (mpnt->vm_mm != mm || mpnt == vma) continue; - - /* - * If the page isn't in this VMA, we can also ignore it. - */ - if (pgoff < mpnt->vm_pgoff) - continue; - - off = pgoff - mpnt->vm_pgoff; - if (off >= (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT) + if (!(mpnt->vm_flags & VM_MAYSHARE)) continue; - - off = mpnt->vm_start + (off << PAGE_SHIFT); - - /* - * Ok, it is within mpnt. Fix it up. - */ - aliases += adjust_pte(mpnt, off); + offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT; + aliases += adjust_pte(mpnt, mpnt->vm_start + offset); } + flush_dcache_mmap_unlock(mapping); if (aliases) adjust_pte(vma, addr); else --- linux-2.6.6/arch/arm/mm/mm-armv.c 2004-05-09 21:07:22.000000000 -0700 +++ 25/arch/arm/mm/mm-armv.c 2004-05-10 01:19:09.101355440 -0700 @@ -18,7 +18,6 @@ #include #include -#include #include #include #include @@ -231,7 +230,7 @@ void free_pgd_slow(pgd_t *pgd) pte = pmd_page(*pmd); pmd_clear(pmd); - pgtable_remove_rmap(pte); + dec_page_state(nr_page_table_pages); pte_free(pte); pmd_free(pmd); free: --- linux-2.6.6/arch/cris/arch-v10/drivers/pcf8563.c 2004-02-03 20:42:34.000000000 -0800 +++ 25/arch/cris/arch-v10/drivers/pcf8563.c 2004-05-10 01:19:57.302027824 -0700 @@ -53,14 +53,10 @@ static const unsigned char days_in_month { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; int pcf8563_ioctl(struct inode *, struct file *, unsigned int, unsigned long); -int pcf8563_open(struct inode *, struct file *); -int pcf8563_release(struct inode *, struct file *); static struct file_operations pcf8563_fops = { .owner = THIS_MODULE, .ioctl = pcf8563_ioctl, - .open = pcf8563_open, - .release = pcf8563_release, }; unsigned char @@ -269,19 +265,5 @@ pcf8563_ioctl(struct inode *inode, struc return 0; } -int -pcf8563_open(struct inode *inode, struct file *filp) -{ - MOD_INC_USE_COUNT; - return 0; -} - -int -pcf8563_release(struct inode *inode, struct file *filp) -{ - MOD_DEC_USE_COUNT; - return 0; -} - module_init(pcf8563_init); module_exit(pcf8563_exit); --- linux-2.6.6/arch/cris/arch-v10/kernel/process.c 2004-05-09 21:07:22.000000000 -0700 +++ 25/arch/cris/arch-v10/kernel/process.c 2004-05-10 01:19:31.135005816 -0700 @@ -217,8 +217,8 @@ asmlinkage int sys_execve(const char *fn * These bracket the sleeping functions.. */ -#define first_sched ((unsigned long) scheduling_functions_start_here) -#define last_sched ((unsigned long) scheduling_functions_end_here) +#define first_sched ((unsigned long)__sched_text_start) +#define last_sched ((unsigned long)__sched_text_end) unsigned long get_wchan(struct task_struct *p) { --- linux-2.6.6/arch/cris/kernel/setup.c 2003-07-10 18:50:30.000000000 -0700 +++ 25/arch/cris/kernel/setup.c 2004-05-10 01:19:18.565916608 -0700 @@ -28,10 +28,7 @@ unsigned char aux_device_present; extern int root_mountflags; extern char _etext, _edata, _end; -#define COMMAND_LINE_SIZE 256 - static char command_line[COMMAND_LINE_SIZE] = { 0, }; - char saved_command_line[COMMAND_LINE_SIZE]; extern const unsigned long text_start, edata; /* set by the linker script */ extern unsigned long dram_start, dram_end; --- linux-2.6.6/arch/h8300/kernel/process.c 2004-05-09 21:07:22.000000000 -0700 +++ 25/arch/h8300/kernel/process.c 2004-05-10 01:19:31.135005816 -0700 @@ -261,12 +261,6 @@ out: return error; } -/* - * These bracket the sleeping functions.. - */ -#define first_sched ((unsigned long) scheduling_functions_start_here) -#define last_sched ((unsigned long) scheduling_functions_end_here) - unsigned long thread_saved_pc(struct task_struct *tsk) { return ((struct pt_regs *)tsk->thread.esp0)->pc; @@ -287,7 +281,7 @@ unsigned long get_wchan(struct task_stru fp >= 8184+stack_page) return 0; pc = ((unsigned long *)fp)[1]; - if (pc < first_sched || pc >= last_sched) + if (!in_sched_functions(pc)) return pc; fp = *(unsigned long *) fp; } while (count++ < 16); --- linux-2.6.6/arch/h8300/kernel/setup.c 2004-05-09 21:07:22.000000000 -0700 +++ 25/arch/h8300/kernel/setup.c 2004-05-10 01:19:18.565916608 -0700 @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -60,8 +61,7 @@ unsigned long memory_end; struct task_struct *_current_task; -char command_line[512]; -char saved_command_line[512]; +char command_line[COMMAND_LINE_SIZE]; extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end; extern int _ramstart, _ramend; --- linux-2.6.6/arch/i386/boot98/setup.S 2003-06-14 12:17:57.000000000 -0700 +++ 25/arch/i386/boot98/setup.S 2004-05-10 01:19:37.064104456 -0700 @@ -146,7 +146,7 @@ ramdisk_image: .long 0 # address of loa ramdisk_size: .long 0 # its size in bytes bootsect_kludge: - .word bootsect_helper, SETUPSEG + .long 0 # obsolete heap_end_ptr: .word modelist+1024 # (Header version 0x0201 or later) # space from here (exclusive) down to @@ -691,91 +691,6 @@ default_switch: # sequence lret -# This routine only gets called, if we get loaded by the simple -# bootsect loader _and_ have a bzImage to load. -# Because there is no place left in the 512 bytes of the boot sector, -# we must emigrate to code space here. -bootsect_helper: - cmpw $0, %cs:bootsect_es - jnz bootsect_second - - movb $0x20, %cs:type_of_loader - movw %es, %ax - shrw $4, %ax - movb %ah, %cs:bootsect_src_base+2 - movw %es, %ax - movw %ax, %cs:bootsect_es - subw $SYSSEG, %ax - lret # nothing else to do for now - -bootsect_second: - pushw %bx - pushw %cx - pushw %si - pushw %di - testw %bp, %bp # 64K full ? - jne bootsect_ex - - xorw %cx, %cx # zero means full 64K - pushw %cs - popw %es - movw $bootsect_gdt, %bx - xorw %si, %si # source address - xorw %di, %di # destination address - movb $0x90, %ah - int $0x1f - jc bootsect_panic # this, if INT1F fails - - movw %cs:bootsect_es, %es # we reset %es to always point - incb %cs:bootsect_dst_base+2 # to 0x10000 -bootsect_ex: - movb %cs:bootsect_dst_base+2, %ah - shlb $4, %ah # we now have the number of - # moved frames in %ax - xorb %al, %al - popw %di - popw %si - popw %cx - popw %bx - lret - -bootsect_gdt: - .word 0, 0, 0, 0 - .word 0, 0, 0, 0 - -bootsect_src: - .word 0xffff - -bootsect_src_base: - .byte 0x00, 0x00, 0x01 # base = 0x010000 - .byte 0x93 # typbyte - .word 0 # limit16,base24 =0 - -bootsect_dst: - .word 0xffff - -bootsect_dst_base: - .byte 0x00, 0x00, 0x10 # base = 0x100000 - .byte 0x93 # typbyte - .word 0 # limit16,base24 =0 - .word 0, 0, 0, 0 # BIOS CS - .word 0, 0, 0, 0 # BIOS DS - -bootsect_es: - .word 0 - -bootsect_panic: - pushw %cs - popw %ds - cld - leaw bootsect_panic_mess, %si - call prtstr - -bootsect_panic_loop: - jmp bootsect_panic_loop - -bootsect_panic_mess: - .string "INT1F refuses to access high mem, giving up." # This routine prints one character (in %al) on console. # PC-9800 doesn't have BIOS-function to do it like IBM PC's INT 10h - 0Eh, --- linux-2.6.6/arch/i386/boot/compressed/misc.c 2004-02-17 20:48:42.000000000 -0800 +++ 25/arch/i386/boot/compressed/misc.c 2004-05-10 01:19:18.973854592 -0700 @@ -87,12 +87,11 @@ static void gzip_release(void **); */ static unsigned char *real_mode; /* Pointer to real-mode data */ -#define EXT_MEM_K (*(unsigned short *)(real_mode + 0x2)) +#define RM_EXT_MEM_K (*(unsigned short *)(real_mode + 0x2)) #ifndef STANDARD_MEMORY_BIOS_CALL -#define ALT_MEM_K (*(unsigned long *)(real_mode + 0x1e0)) +#define RM_ALT_MEM_K (*(unsigned long *)(real_mode + 0x1e0)) #endif -#define SCREEN_INFO (*(struct screen_info *)(real_mode+0)) -#define EDID_INFO (*(struct edid_info *)(real_mode+0x440)) +#define RM_SCREEN_INFO (*(struct screen_info *)(real_mode+0)) extern char input_data[]; extern int input_len; @@ -174,8 +173,8 @@ static void putstr(const char *s) int x,y,pos; char c; - x = SCREEN_INFO.orig_x; - y = SCREEN_INFO.orig_y; + x = RM_SCREEN_INFO.orig_x; + y = RM_SCREEN_INFO.orig_y; while ( ( c = *s++ ) != '\0' ) { if ( c == '\n' ) { @@ -196,8 +195,8 @@ static void putstr(const char *s) } } - SCREEN_INFO.orig_x = x; - SCREEN_INFO.orig_y = y; + RM_SCREEN_INFO.orig_x = x; + RM_SCREEN_INFO.orig_y = y; pos = (x + cols * y) * 2; /* Update cursor position */ outb_p(14, vidport); @@ -306,9 +305,9 @@ struct { static void setup_normal_output_buffer(void) { #ifdef STANDARD_MEMORY_BIOS_CALL - if (EXT_MEM_K < 1024) error("Less than 2MB of memory"); + if (RM_EXT_MEM_K < 1024) error("Less than 2MB of memory"); #else - if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024) error("Less than 2MB of memory"); + if ((RM_ALT_MEM_K > RM_EXT_MEM_K ? RM_ALT_MEM_K : RM_EXT_MEM_K) < 1024) error("Less than 2MB of memory"); #endif output_data = (char *)0x100000; /* Points to 1M */ free_mem_end_ptr = (long)real_mode; @@ -323,9 +322,11 @@ static void setup_output_buffer_if_we_ru { high_buffer_start = (uch *)(((ulg)&end) + HEAP_SIZE); #ifdef STANDARD_MEMORY_BIOS_CALL - if (EXT_MEM_K < (3*1024)) error("Less than 4MB of memory"); + if (RM_EXT_MEM_K < (3*1024)) error("Less than 4MB of memory"); #else - if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory"); + if ((RM_ALT_MEM_K > RM_EXT_MEM_K ? RM_ALT_MEM_K : RM_EXT_MEM_K) < + (3*1024)) + error("Less than 4MB of memory"); #endif mv->low_buffer_start = output_data = (char *)LOW_BUFFER_START; low_buffer_end = ((unsigned int)real_mode > LOW_BUFFER_MAX @@ -358,7 +359,7 @@ asmlinkage int decompress_kernel(struct { real_mode = rmode; - if (SCREEN_INFO.orig_video_mode == 7) { + if (RM_SCREEN_INFO.orig_video_mode == 7) { vidmem = (char *) 0xb0000; vidport = 0x3b4; } else { @@ -366,8 +367,8 @@ asmlinkage int decompress_kernel(struct vidport = 0x3d4; } - lines = SCREEN_INFO.orig_video_lines; - cols = SCREEN_INFO.orig_video_cols; + lines = RM_SCREEN_INFO.orig_video_lines; + cols = RM_SCREEN_INFO.orig_video_cols; if (free_mem_ptr < 0x100000) setup_normal_output_buffer(); else setup_output_buffer_if_we_run_high(mv); --- linux-2.6.6/arch/i386/boot/setup.S 2004-04-03 20:39:10.000000000 -0800 +++ 25/arch/i386/boot/setup.S 2004-05-10 01:19:51.026981776 -0700 @@ -133,7 +133,7 @@ ramdisk_image: .long 0 # address of loa ramdisk_size: .long 0 # its size in bytes bootsect_kludge: - .word bootsect_helper, SETUPSEG + .long 0 # obsolete heap_end_ptr: .word modelist+1024 # (Header version 0x0201 or later) # space from here (exclusive) down to @@ -156,7 +156,8 @@ cmd_line_ptr: .long 0 # (Header versio # can be located anywhere in # low memory 0x10000 or higher. -ramdisk_max: .long MAXMEM-1 # (Header version 0x0203 or later) +ramdisk_max: .long (MAXMEM-1) & 0x7fffffff + # (Header version 0x0203 or later) # The highest safe address for # the contents of an initrd @@ -837,7 +838,7 @@ flush_instr: subw $DELTA_INITSEG, %si shll $4, %esi # Convert to 32-bit pointer -# jump to startup_32 in arch/i386/kernel/head.S +# jump to startup_32 in arch/i386/boot/compressed/head.S # # NOTE: For high loaded big kernels we need a # jmpi 0x100000,__BOOT_CS @@ -872,88 +873,6 @@ default_switch: outb %al, $0x70 lret -# This routine only gets called, if we get loaded by the simple -# bootsect loader _and_ have a bzImage to load. -# Because there is no place left in the 512 bytes of the boot sector, -# we must emigrate to code space here. -bootsect_helper: - cmpw $0, %cs:bootsect_es - jnz bootsect_second - - movb $0x20, %cs:type_of_loader - movw %es, %ax - shrw $4, %ax - movb %ah, %cs:bootsect_src_base+2 - movw %es, %ax - movw %ax, %cs:bootsect_es - subw $SYSSEG, %ax - lret # nothing else to do for now - -bootsect_second: - pushw %cx - pushw %si - pushw %bx - testw %bx, %bx # 64K full? - jne bootsect_ex - - movw $0x8000, %cx # full 64K, INT15 moves words - pushw %cs - popw %es - movw $bootsect_gdt, %si - movw $0x8700, %ax - int $0x15 - jc bootsect_panic # this, if INT15 fails - - movw %cs:bootsect_es, %es # we reset %es to always point - incb %cs:bootsect_dst_base+2 # to 0x10000 -bootsect_ex: - movb %cs:bootsect_dst_base+2, %ah - shlb $4, %ah # we now have the number of - # moved frames in %ax - xorb %al, %al - popw %bx - popw %si - popw %cx - lret - -bootsect_gdt: - .word 0, 0, 0, 0 - .word 0, 0, 0, 0 - -bootsect_src: - .word 0xffff - -bootsect_src_base: - .byte 0x00, 0x00, 0x01 # base = 0x010000 - .byte 0x93 # typbyte - .word 0 # limit16,base24 =0 - -bootsect_dst: - .word 0xffff - -bootsect_dst_base: - .byte 0x00, 0x00, 0x10 # base = 0x100000 - .byte 0x93 # typbyte - .word 0 # limit16,base24 =0 - .word 0, 0, 0, 0 # BIOS CS - .word 0, 0, 0, 0 # BIOS DS - -bootsect_es: - .word 0 - -bootsect_panic: - pushw %cs - popw %ds - cld - leaw bootsect_panic_mess, %si - call prtstr - -bootsect_panic_loop: - jmp bootsect_panic_loop - -bootsect_panic_mess: - .string "INT15 refuses to access high mem, giving up." - #ifndef CONFIG_X86_VOYAGER # This routine tests whether or not A20 is enabled. If so, it --- linux-2.6.6/arch/i386/Kconfig 2004-05-09 21:07:22.000000000 -0700 +++ 25/arch/i386/Kconfig 2004-05-10 01:19:52.005832968 -0700 @@ -102,10 +102,10 @@ config X86_VISWS and vice versa. See for details. config X86_GENERICARCH - bool "Generic architecture (Summit, bigsmp, default)" + bool "Generic architecture (Summit, bigsmp, ES7000, default)" depends on SMP help - This option compiles in the Summit, bigsmp, default subarchitectures. + This option compiles in the Summit, bigsmp, ES7000, default subarchitectures. It is intended for a generic binary kernel. config X86_ES7000 @@ -479,6 +479,16 @@ config NR_CPUS This is purely to save memory - each supported CPU adds approximately eight kilobytes to the kernel image. +config SCHED_SMT + bool "SMT (Hyperthreading) scheduler support" + depends on SMP + default off + help + SMT scheduler support improves the CPU scheduler's decision making + when dealing with Intel Pentium 4 chips with HyperThreading at a + cost of slightly increased overhead in some places. If unsure say + N here. + config PREEMPT bool "Preemptible Kernel" help @@ -709,7 +719,7 @@ config X86_PAE # Common NUMA Features config NUMA - bool "Numa Memory Allocation Support" + bool "Numa Memory Allocation and Scheduler Support" depends on SMP && HIGHMEM64G && (X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI)) default n if X86_PC default y if (X86_NUMAQ || X86_SUMMIT) @@ -839,17 +849,7 @@ config BOOT_IOREMAP default y config REGPARM - bool "Use register arguments (EXPERIMENTAL)" - depends on EXPERIMENTAL - default n - help - Compile the kernel with -mregparm=3. This uses an different ABI - and passes the first three arguments of a function call in registers. - This will probably break binary only modules. - - This feature is only enabled for gcc-3.0 and later - earlier compilers - generate incorrect output with certain kernel constructs when - -mregparm=3 is used. + def_bool y endmenu @@ -1245,6 +1245,15 @@ config DEBUG_PAGEALLOC This results in a large slowdown, but helps to find certain types of memory corruptions. +config SPINLINE + bool "Spinlock inlining" + depends on DEBUG_KERNEL + help + This will change spinlocks from out of line to inline, making them + account cost to the callers in readprofile, rather than the lock + itself (as ".text.lock.filename"). This can be helpful for finding + the callers of locks. + config DEBUG_HIGHMEM bool "Highmem debugging" depends on DEBUG_KERNEL && HIGHMEM @@ -1261,12 +1270,194 @@ config DEBUG_INFO Say Y here only if you plan to use gdb to debug the kernel. If you don't debug the kernel, you can say N. +config LOCKMETER + bool "Kernel lock metering" + depends on SMP + help + Say Y to enable kernel lock metering, which adds overhead to SMP locks, + but allows you to see various statistics using the lockstat command. + config DEBUG_SPINLOCK_SLEEP bool "Sleep-inside-spinlock checking" help If you say Y here, various routines which may sleep will become very noisy if they are called with a spinlock held. +config KGDB + bool "Include kgdb kernel debugger" + depends on DEBUG_KERNEL + help + If you say Y here, the system will be compiled with the debug + option (-g) and a debugging stub will be included in the + kernel. This stub communicates with gdb on another (host) + computer via a serial port. The host computer should have + access to the kernel binary file (vmlinux) and a serial port + that is connected to the target machine. Gdb can be made to + configure the serial port or you can use stty and setserial to + do this. See the 'target' command in gdb. This option also + configures in the ability to request a breakpoint early in the + boot process. To request the breakpoint just include 'kgdb' + as a boot option when booting the target machine. The system + will then break as soon as it looks at the boot options. This + option also installs a breakpoint in panic and sends any + kernel faults to the debugger. For more information see the + Documentation/i386/kgdb/kgdb.txt file. + +choice + depends on KGDB + prompt "Debug serial port BAUD" + default KGDB_115200BAUD + help + Gdb and the kernel stub need to agree on the baud rate to be + used. Some systems (x86 family at this writing) allow this to + be configured. + +config KGDB_9600BAUD + bool "9600" + +config KGDB_19200BAUD + bool "19200" + +config KGDB_38400BAUD + bool "38400" + +config KGDB_57600BAUD + bool "57600" + +config KGDB_115200BAUD + bool "115200" +endchoice + +config KGDB_PORT + hex "hex I/O port address of the debug serial port" + depends on KGDB + default 3f8 + help + Some systems (x86 family at this writing) allow the port + address to be configured. The number entered is assumed to be + hex, don't put 0x in front of it. The standard address are: + COM1 3f8 , irq 4 and COM2 2f8 irq 3. Setserial /dev/ttySx + will tell you what you have. It is good to test the serial + connection with a live system before trying to debug. + +config KGDB_IRQ + int "IRQ of the debug serial port" + depends on KGDB + default 4 + help + This is the irq for the debug port. If everything is working + correctly and the kernel has interrupts on a control C to the + port should cause a break into the kernel debug stub. + +config DEBUG_INFO + bool + depends on KGDB + default y + +config KGDB_MORE + bool "Add any additional compile options" + depends on KGDB + default n + help + Saying yes here turns on the ability to enter additional + compile options. + + +config KGDB_OPTIONS + depends on KGDB_MORE + string "Additional compile arguments" + default "-O1" + help + This option allows you enter additional compile options for + the whole kernel compile. Each platform will have a default + that seems right for it. For example on PPC "-ggdb -O1", and + for i386 "-O1". Note that by configuring KGDB "-g" is already + turned on. In addition, on i386 platforms + "-fomit-frame-pointer" is deleted from the standard compile + options. + +config NO_KGDB_CPUS + int "Number of CPUs" + depends on KGDB && SMP + default NR_CPUS + help + + This option sets the number of cpus for kgdb ONLY. It is used + to prune some internal structures so they look "nice" when + displayed with gdb. This is to overcome possibly larger + numbers that may have been entered above. Enter the real + number to get nice clean kgdb_info displays. + +config KGDB_TS + bool "Enable kgdb time stamp macros?" + depends on KGDB + default n + help + Kgdb event macros allow you to instrument your code with calls + to the kgdb event recording function. The event log may be + examined with gdb at a break point. Turning on this + capability also allows you to choose how many events to + keep. Kgdb always keeps the lastest events. + +choice + depends on KGDB_TS + prompt "Max number of time stamps to save?" + default KGDB_TS_128 + +config KGDB_TS_64 + bool "64" + +config KGDB_TS_128 + bool "128" + +config KGDB_TS_256 + bool "256" + +config KGDB_TS_512 + bool "512" + +config KGDB_TS_1024 + bool "1024" + +endchoice + +config STACK_OVERFLOW_TEST + bool "Turn on kernel stack overflow testing?" + depends on KGDB + default n + help + This option enables code in the front line interrupt handlers + to check for kernel stack overflow on interrupts and system + calls. This is part of the kgdb code on x86 systems. + +config KGDB_CONSOLE + bool "Enable serial console thru kgdb port" + depends on KGDB + default n + help + This option enables the command line "console=kgdb" option. + When the system is booted with this option in the command line + all kernel printk output is sent to gdb (as well as to other + consoles). For this to work gdb must be connected. For this + reason, this command line option will generate a breakpoint if + gdb has not yet connected. After the gdb continue command is + given all pent up console output will be printed by gdb on the + host machine. Neither this option, nor KGDB require the + serial driver to be configured. + +config KGDB_SYSRQ + bool "Turn on SysRq 'G' command to do a break?" + depends on KGDB + default y + help + This option includes an option in the SysRq code that allows + you to enter SysRq G which generates a breakpoint to the KGDB + stub. This will work if the keyboard is alive and can + interrupt the system. Because of constraints on when the + serial port interrupt can be enabled, this code may allow you + to interrupt the system before the serial port control C is + available. Just say yes here. + config FRAME_POINTER bool "Compile the kernel with frame pointers" help @@ -1275,14 +1466,18 @@ config FRAME_POINTER If you don't debug the kernel, you can say N, but we may not be able to solve problems without frame pointers. -config 4KSTACKS - bool "Use 4Kb for kernel stacks instead of 8Kb" +config SCHEDSTATS + bool "Collect scheduler statistics" + depends on PROC_FS + default y help - If you say Y here the kernel will use a 4Kb stacksize for the - kernel stack attached to each process/thread. This facilitates - running more threads on a system and also reduces the pressure - on the VM subsystem for higher order allocations. This option - will also use IRQ stacks to compensate for the reduced stackspace. + If you say Y here, additional code will be inserted into the + scheduler and related routines to collect statistics about + scheduler behavior and provide them in /proc/schedstat. These + stats may be useful for both tuning and debugging the scheduler + If you aren't debugging the scheduler or trying to tune a specific + application, you can say N to avoid the very slight overhead + this adds. config X86_FIND_SMP_CONFIG bool --- linux-2.6.6/arch/i386/kernel/acpi/boot.c 2004-05-09 21:07:22.000000000 -0700 +++ 25/arch/i386/kernel/acpi/boot.c 2004-05-10 01:19:35.822293240 -0700 @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include --- linux-2.6.6/arch/i386/kernel/apic.c 2004-03-10 20:41:25.000000000 -0800 +++ 25/arch/i386/kernel/apic.c 2004-05-10 01:19:35.823293088 -0700 @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include --- linux-2.6.6/arch/i386/kernel/cpu/common.c 2004-05-09 21:07:22.000000000 -0700 +++ 25/arch/i386/kernel/cpu/common.c 2004-05-10 01:19:37.448046088 -0700 @@ -138,8 +138,7 @@ static char __init *table_lookup_model(s } - -void __init get_cpu_vendor(struct cpuinfo_x86 *c) +void __init get_cpu_vendor(struct cpuinfo_x86 *c, int early) { char *v = c->x86_vendor_id; int i; @@ -150,7 +149,8 @@ void __init get_cpu_vendor(struct cpuinf (cpu_devs[i]->c_ident[1] && !strcmp(v,cpu_devs[i]->c_ident[1]))) { c->x86_vendor = i; - this_cpu = cpu_devs[i]; + if (!early) + this_cpu = cpu_devs[i]; break; } } @@ -194,6 +194,44 @@ int __init have_cpuid_p(void) return flag_is_changeable_p(X86_EFLAGS_ID); } +/* Do minimum CPU detection early. + Fields really needed: vendor, cpuid_level, family, model, mask, cache alignment. + The others are not touched to avoid unwanted side effects. */ +void __init early_cpu_detect(void) +{ + struct cpuinfo_x86 *c = &boot_cpu_data; + + if (!have_cpuid_p()) + return; + + /* Get vendor name */ + cpuid(0x00000000, &c->cpuid_level, + (int *)&c->x86_vendor_id[0], + (int *)&c->x86_vendor_id[8], + (int *)&c->x86_vendor_id[4]); + + get_cpu_vendor(c, 1); + + c->x86 = 4; + c->x86_cache_alignment = 32; + + if (c->cpuid_level >= 0x00000001) { + u32 junk, tfms, cap0, misc; + cpuid(0x00000001, &tfms, &misc, &junk, &cap0); + c->x86 = (tfms >> 8) & 15; + c->x86_model = (tfms >> 4) & 15; + if (c->x86 == 0xf) { + c->x86 += (tfms >> 20) & 0xff; + c->x86_model += ((tfms >> 16) & 0xF) << 4; + } + c->x86_mask = tfms & 15; + if (cap0 & (1<<19)) + c->x86_cache_alignment = ((misc >> 8) & 0xff) * 8; + } + + early_intel_workaround(c); +} + void __init generic_identify(struct cpuinfo_x86 * c) { u32 tfms, xlvl; @@ -206,7 +244,7 @@ void __init generic_identify(struct cpui (int *)&c->x86_vendor_id[8], (int *)&c->x86_vendor_id[4]); - get_cpu_vendor(c); + get_cpu_vendor(c, 0); /* Initialize the standard set of capabilities */ /* Note that the vendor-specific code below might override */ @@ -384,7 +422,6 @@ void __init identify_cpu(struct cpuinfo_ void __init dodgy_tsc(void) { - get_cpu_vendor(&boot_cpu_data); if (( boot_cpu_data.x86_vendor == X86_VENDOR_CYRIX ) || ( boot_cpu_data.x86_vendor == X86_VENDOR_NSC )) cpu_devs[X86_VENDOR_CYRIX]->c_init(&boot_cpu_data); @@ -432,9 +469,11 @@ extern int transmeta_init_cpu(void); extern int rise_init_cpu(void); extern int nexgen_init_cpu(void); extern int umc_init_cpu(void); +void early_cpu_detect(void); void __init early_cpu_init(void) { + early_cpu_detect(); intel_cpu_init(); cyrix_init_cpu(); nsc_init_cpu(); --- linux-2.6.6/arch/i386/kernel/cpu/cpufreq/elanfreq.c 2004-05-09 21:07:22.000000000 -0700 +++ 25/arch/i386/kernel/cpu/cpufreq/elanfreq.c 2004-05-10 01:19:01.780468384 -0700 @@ -77,7 +77,7 @@ static struct cpufreq_frequency_table el * and have the rest of the chip running with 33 MHz. */ -static unsigned int elanfreq_get_cpu_frequency(void) +static unsigned int elanfreq_get_cpu_frequency(unsigned int cpu) { u8 clockspeed_reg; /* Clock Speed Register */ @@ -121,7 +121,7 @@ static void elanfreq_set_cpu_state (unsi struct cpufreq_freqs freqs; - freqs.old = elanfreq_get_cpu_frequency(); + freqs.old = elanfreq_get_cpu_frequency(0); freqs.new = elan_multiplier[state].clock; freqs.cpu = 0; /* elanfreq.c is UP only driver */ @@ -209,7 +209,7 @@ static int elanfreq_cpu_init(struct cpuf /* max freq */ if (!max_freq) - max_freq = elanfreq_get_cpu_frequency(); + max_freq = elanfreq_get_cpu_frequency(0); /* table init */ for (i=0; (elanfreq_table[i].frequency != CPUFREQ_TABLE_END); i++) { @@ -220,7 +220,7 @@ static int elanfreq_cpu_init(struct cpuf /* cpuinfo and default policy values */ policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; - policy->cur = elanfreq_get_cpu_frequency(); + policy->cur = elanfreq_get_cpu_frequency(0); result = cpufreq_frequency_table_cpuinfo(policy, elanfreq_table); if (result) @@ -267,6 +267,7 @@ static struct freq_attr* elanfreq_attr[] static struct cpufreq_driver elanfreq_driver = { + .get = elanfreq_get_cpu_frequency, .verify = elanfreq_verify, .target = elanfreq_target, .init = elanfreq_cpu_init, --- linux-2.6.6/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c 2004-02-17 20:48:42.000000000 -0800 +++ 25/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c 2004-05-10 01:19:01.781468232 -0700 @@ -215,7 +215,7 @@ static __init struct pci_dev *gx_detect_ * * Finds out at which efficient frequency the Cyrix MediaGX/NatSemi Geode CPU runs. */ -static int gx_get_cpuspeed(void) +static unsigned int gx_get_cpuspeed(unsigned int cpu) { if ((gx_params->pci_suscfg & SUSMOD) == 0) return stock_freq; @@ -271,7 +271,7 @@ static void gx_set_cpuspeed(unsigned int freqs.cpu = 0; - freqs.old = gx_get_cpuspeed(); + freqs.old = gx_get_cpuspeed(0); new_khz = gx_validate_speed(khz, &gx_params->on_duration, &gx_params->off_duration); @@ -405,7 +405,7 @@ static int cpufreq_gx_target(struct cpuf static int cpufreq_gx_cpu_init(struct cpufreq_policy *policy) { - int maxfreq, curfreq; + unsigned int maxfreq, curfreq; if (!policy || policy->cpu != 0) return -ENODEV; @@ -419,7 +419,7 @@ static int cpufreq_gx_cpu_init(struct cp maxfreq = 30000 * gx_freq_mult[getCx86(CX86_DIR1) & 0x0f]; } stock_freq = maxfreq; - curfreq = gx_get_cpuspeed(); + curfreq = gx_get_cpuspeed(0); dprintk("cpu max frequency is %d.\n", maxfreq); dprintk("cpu current frequency is %dkHz.\n",curfreq); @@ -446,6 +446,7 @@ static int cpufreq_gx_cpu_init(struct cp * MediaGX/Geode GX initialize cpufreq driver */ static struct cpufreq_driver gx_suspmod_driver = { + .get = gx_get_cpuspeed, .verify = cpufreq_gx_verify, .target = cpufreq_gx_target, .init = cpufreq_gx_cpu_init, --- linux-2.6.6/arch/i386/kernel/cpu/cpufreq/longhaul.c 2004-05-09 21:07:22.000000000 -0700 +++ 25/arch/i386/kernel/cpu/cpufreq/longhaul.c 2004-05-10 01:19:01.782468080 -0700 @@ -380,6 +380,13 @@ static int longhaul_target (struct cpufr return 0; } +static unsigned int longhaul_get(unsigned int cpu) +{ + if (cpu) + return 0; + return (calc_speed (longhaul_get_cpu_mult(), fsb)); +} + static int __init longhaul_cpu_init (struct cpufreq_policy *policy) { struct cpuinfo_x86 *c = cpu_data; @@ -472,6 +479,7 @@ static struct freq_attr* longhaul_attr[] static struct cpufreq_driver longhaul_driver = { .verify = longhaul_verify, .target = longhaul_target, + .get = longhaul_get, .init = longhaul_cpu_init, .exit = longhaul_cpu_exit, .name = "longhaul", --- linux-2.6.6/arch/i386/kernel/cpu/cpufreq/longrun.c 2004-05-09 21:07:22.000000000 -0700 +++ 25/arch/i386/kernel/cpu/cpufreq/longrun.c 2004-05-10 01:19:01.782468080 -0700 @@ -128,6 +128,17 @@ static int longrun_verify_policy(struct return 0; } +static unsigned int longrun_get(unsigned int cpu) +{ + u32 eax, ebx, ecx, edx; + + if (cpu) + return 0; + + cpuid(0x80860007, &eax, &ebx, &ecx, &edx); + + return (eax * 1000); +} /** * longrun_determine_freqs - determines the lowest and highest possible core frequency @@ -250,8 +261,10 @@ static int __init longrun_cpu_init(struc static struct cpufreq_driver longrun_driver = { + .flags = CPUFREQ_CONST_LOOPS, .verify = longrun_verify_policy, .setpolicy = longrun_set_policy, + .get = longrun_get, .init = longrun_cpu_init, .name = "longrun", .owner = THIS_MODULE, --- linux-2.6.6/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c 2004-05-09 21:07:22.000000000 -0700 +++ 25/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c 2004-05-10 01:19:19.782731624 -0700 @@ -51,14 +51,14 @@ enum { static int has_N44_O17_errata[NR_CPUS]; static unsigned int stock_freq; +static struct cpufreq_driver p4clockmod_driver; static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate) { u32 l, h; cpumask_t cpus_allowed, affected_cpu_map; struct cpufreq_freqs freqs; - int hyperthreading = 0; - int sibling = 0; + int j; if (!cpu_online(cpu) || (newstate > DC_DISABLE) || (newstate == DC_RESV)) @@ -68,13 +68,10 @@ static int cpufreq_p4_setdc(unsigned int cpus_allowed = current->cpus_allowed; /* only run on CPU to be set, or on its sibling */ - affected_cpu_map = cpumask_of_cpu(cpu); -#ifdef CONFIG_X86_HT - hyperthreading = ((cpu_has_ht) && (smp_num_siblings == 2)); - if (hyperthreading) { - sibling = cpu_sibling_map[cpu]; - cpu_set(sibling, affected_cpu_map); - } +#ifdef CONFIG_SMP + affected_cpu_map = cpu_sibling_map[cpu]; +#else + affected_cpu_map = cpumask_of_cpu(cpu); #endif set_cpus_allowed(current, affected_cpu_map); BUG_ON(!cpu_isset(smp_processor_id(), affected_cpu_map)); @@ -97,11 +94,11 @@ static int cpufreq_p4_setdc(unsigned int /* notifiers */ freqs.old = stock_freq * l / 8; freqs.new = stock_freq * newstate / 8; - freqs.cpu = cpu; - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - if (hyperthreading) { - freqs.cpu = sibling; - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + for_each_cpu(j) { + if (cpu_isset(j, affected_cpu_map)) { + freqs.cpu = j; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + } } rdmsr(MSR_IA32_THERM_STATUS, l, h); @@ -132,10 +129,11 @@ static int cpufreq_p4_setdc(unsigned int set_cpus_allowed(current, cpus_allowed); /* notifiers */ - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - if (hyperthreading) { - freqs.cpu = cpu; - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + for_each_cpu(j) { + if (cpu_isset(j, affected_cpu_map)) { + freqs.cpu = j; + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + } } return 0; @@ -180,11 +178,23 @@ static int cpufreq_p4_verify(struct cpuf static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c) { if ((c->x86 == 0x06) && (c->x86_model == 0x09)) { - /* Pentium M */ + /* Pentium M (Banias) */ + printk(KERN_WARNING PFX "Warning: Pentium M detected. " + "The speedstep_centrino module offers voltage scaling" + " in addition of frequency scaling. You should use " + "that instead of p4-clockmod, if possible.\n"); + return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PM); + } + + if ((c->x86 == 0x06) && (c->x86_model == 0x13)) { + /* Pentium M (Dothan) */ printk(KERN_WARNING PFX "Warning: Pentium M detected. " "The speedstep_centrino module offers voltage scaling" " in addition of frequency scaling. You should use " "that instead of p4-clockmod, if possible.\n"); + /* on P-4s, the TSC runs with constant frequency independent wether + * throttling is active or not. */ + p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS; return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PM); } @@ -193,6 +203,10 @@ static unsigned int cpufreq_p4_get_frequ return 0; } + /* on P-4s, the TSC runs with constant frequency independent wether + * throttling is active or not. */ + p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS; + if (speedstep_detect_processor() == SPEEDSTEP_PROCESSOR_P4M) { printk(KERN_WARNING PFX "Warning: Pentium 4-M detected. " "The speedstep-ich or acpi cpufreq modules offer " @@ -252,6 +266,43 @@ static int cpufreq_p4_cpu_exit(struct cp return 0; } +static unsigned int cpufreq_p4_get(unsigned int cpu) +{ + unsigned int hyperthreading; + cpumask_t cpus_allowed, affected_cpu_map; + u32 l, h; + + hyperthreading = 0; + + /* only run on CPU to be set, or on its sibling */ + cpus_allowed = current->cpus_allowed; + affected_cpu_map = cpumask_of_cpu(cpu); +#ifdef CONFIG_X86_HT + hyperthreading = ((cpu_has_ht) && (smp_num_siblings == 2)); + if (hyperthreading) { + sibling = cpu_sibling_map[cpu]; + cpu_set(sibling, affected_cpu_map); + } +#endif + set_cpus_allowed(current, affected_cpu_map); + BUG_ON(!cpu_isset(smp_processor_id(), affected_cpu_map)); + + rdmsr(MSR_IA32_THERM_CONTROL, l, h); + + set_cpus_allowed(current, cpus_allowed); + + if (l & 0x10) { + l = l >> 1; + l &= 0x7; + } else + l = DC_DISABLE; + + if (l != DC_DISABLE) + return (stock_freq * l / 8); + + return stock_freq; +} + static struct freq_attr* p4clockmod_attr[] = { &cpufreq_freq_attr_scaling_available_freqs, NULL, @@ -262,6 +313,7 @@ static struct cpufreq_driver p4clockmod_ .target = cpufreq_p4_target, .init = cpufreq_p4_cpu_init, .exit = cpufreq_p4_cpu_exit, + .get = cpufreq_p4_get, .name = "p4-clockmod", .owner = THIS_MODULE, .attr = p4clockmod_attr, --- linux-2.6.6/arch/i386/kernel/cpu/cpufreq/powernow-k6.c 2004-05-09 21:07:22.000000000 -0700 +++ 25/arch/i386/kernel/cpu/cpufreq/powernow-k6.c 2004-05-10 01:19:01.783467928 -0700 @@ -185,6 +185,11 @@ static int powernow_k6_cpu_exit(struct c return 0; } +static unsigned int powernow_k6_get(unsigned int cpu) +{ + return busfreq * powernow_k6_get_cpu_multiplier(); +} + static struct freq_attr* powernow_k6_attr[] = { &cpufreq_freq_attr_scaling_available_freqs, NULL, @@ -195,6 +200,7 @@ static struct cpufreq_driver powernow_k6 .target = powernow_k6_target, .init = powernow_k6_cpu_init, .exit = powernow_k6_cpu_exit, + .get = powernow_k6_get, .name = "powernow-k6", .owner = THIS_MODULE, .attr = powernow_k6_attr, --- linux-2.6.6/arch/i386/kernel/cpu/cpufreq/powernow-k7.c 2004-05-09 21:07:22.000000000 -0700 +++ 25/arch/i386/kernel/cpu/cpufreq/powernow-k7.c 2004-05-10 01:19:01.784467776 -0700 @@ -540,6 +540,20 @@ static int __init fixup_sgtc(void) return sgtc; } +static unsigned int powernow_get(unsigned int cpu) +{ + union msr_fidvidstatus fidvidstatus; + unsigned int cfid; + + if (cpu) + return 0; + rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val); + cfid = fidvidstatus.bits.CFID; + + return (fsb * fid_codes[cfid] / 10); +} + + static int __init powernow_cpu_init (struct cpufreq_policy *policy) { union msr_fidvidstatus fidvidstatus; @@ -590,7 +604,7 @@ static int __init powernow_cpu_init (str policy->cpuinfo.transition_latency = 20 * latency / fsb; - policy->cur = maximum_speed; + policy->cur = powernow_get(0); cpufreq_frequency_table_get_attr(powernow_table, policy->cpu); @@ -610,6 +624,7 @@ static struct freq_attr* powernow_table_ static struct cpufreq_driver powernow_driver = { .verify = powernow_verify, .target = powernow_target, + .get = powernow_get, .init = powernow_cpu_init, .exit = powernow_cpu_exit, .name = "powernow-k7", --- linux-2.6.6/arch/i386/kernel/cpu/cpufreq/powernow-k8.c 2004-05-09 21:07:22.000000000 -0700 +++ 25/arch/i386/kernel/cpu/cpufreq/powernow-k8.c 2004-05-10 01:19:01.786467472 -0700 @@ -39,7 +39,7 @@ #define PFX "powernow-k8: " #define BFX PFX "BIOS error: " -#define VERSION "version 1.00.08b" +#define VERSION "version 1.00.09b" #include "powernow-k8.h" /* serialize freq changes */ @@ -450,13 +450,10 @@ static int check_supported_cpu(unsigned goto out; eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE); - if ((eax & CPUID_XFAM_MOD) == ATHLON64_XFAM_MOD) { - dprintk(KERN_DEBUG PFX "AMD Althon 64 Processor found\n"); - } else if ((eax & CPUID_XFAM_MOD) == OPTERON_XFAM_MOD) { - dprintk(KERN_DEBUG PFX "AMD Opteron Processor found\n"); - } else { - printk(KERN_INFO PFX - "AMD Athlon 64 or AMD Opteron processor required\n"); + if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) || + ((eax & CPUID_XFAM) != CPUID_XFAM_K8) || + ((eax & CPUID_XMOD) > CPUID_XMOD_REV_E)) { + printk(KERN_INFO PFX "Processor cpuid %x not supported\n", eax); goto out; } @@ -524,11 +521,12 @@ static void print_basics(struct powernow { int j; for (j = 0; j < data->numps; j++) { - printk(KERN_INFO PFX " %d : fid 0x%x (%d MHz), vid 0x%x (%d mV)\n", j, - data->powernow_table[j].index & 0xff, - data->powernow_table[j].frequency/1000, - data->powernow_table[j].index >> 8, - find_millivolts_from_vid(data, data->powernow_table[j].index >> 8)); + if (data->powernow_table[j].frequency != CPUFREQ_ENTRY_INVALID) + printk(KERN_INFO PFX " %d : fid 0x%x (%d MHz), vid 0x%x (%d mV)\n", j, + data->powernow_table[j].index & 0xff, + data->powernow_table[j].frequency/1000, + data->powernow_table[j].index >> 8, + find_millivolts_from_vid(data, data->powernow_table[j].index >> 8)); } if (data->batps) printk(KERN_INFO PFX "Only %d pstates on battery\n", data->batps); @@ -723,7 +721,14 @@ static int powernow_k8_cpu_init_acpi(str /* verify frequency is OK */ if ((powernow_table[i].frequency > (MAX_FREQ * 1000)) || (powernow_table[i].frequency < (MIN_FREQ * 1000))) { - dprintk(KERN_INFO PFX "invalid freq %u kHz\n", powernow_table[i].frequency); + dprintk(KERN_INFO PFX "invalid freq %u kHz, ignoring\n", powernow_table[i].frequency); + powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID; + continue; + } + + /* verify voltage is OK - BIOSs are using "off" to indicate invalid */ + if (vid == 0x1f) { + dprintk(KERN_INFO PFX "invalid vid %u, ignoring\n", vid); powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID; continue; } @@ -1025,6 +1030,32 @@ static int __exit powernowk8_cpu_exit (s return 0; } +static unsigned int powernowk8_get (unsigned int cpu) +{ + struct powernow_k8_data *data = powernow_data[cpu]; + cpumask_t oldmask = current->cpus_allowed; + unsigned int khz = 0; + + set_cpus_allowed(current, cpumask_of_cpu(cpu)); + if (smp_processor_id() != cpu) { + printk(KERN_ERR PFX "limiting to CPU %d failed in powernowk8_get\n", cpu); + set_cpus_allowed(current, oldmask); + return 0; + } + preempt_disable(); + + if (query_current_values_with_pending_wait(data)) + goto out; + + khz = find_khz_freq_from_fid(data->currfid); + + out: + preempt_enable_no_resched(); + set_cpus_allowed(current, oldmask); + + return khz; +} + static struct freq_attr* powernow_k8_attr[] = { &cpufreq_freq_attr_scaling_available_freqs, NULL, @@ -1035,6 +1066,7 @@ static struct cpufreq_driver cpufreq_amd .target = powernowk8_target, .init = powernowk8_cpu_init, .exit = powernowk8_cpu_exit, + .get = powernowk8_get, .name = "powernow-k8", .owner = THIS_MODULE, .attr = powernow_k8_attr, --- linux-2.6.6/arch/i386/kernel/cpu/cpufreq/powernow-k8.h 2004-05-09 21:07:22.000000000 -0700 +++ 25/arch/i386/kernel/cpu/cpufreq/powernow-k8.h 2004-05-10 01:19:01.786467472 -0700 @@ -38,13 +38,15 @@ struct powernow_k8_data { /* processor's cpuid instruction support */ -#define CPUID_PROCESSOR_SIGNATURE 1 /* function 1 */ -#define CPUID_XFAM_MOD 0x0ff00ff0 /* extended fam, fam + model */ -#define ATHLON64_XFAM_MOD 0x00000f40 /* extended fam, fam + model */ -#define OPTERON_XFAM_MOD 0x00000f50 /* extended fam, fam + model */ -#define CPUID_GET_MAX_CAPABILITIES 0x80000000 -#define CPUID_FREQ_VOLT_CAPABILITIES 0x80000007 -#define P_STATE_TRANSITION_CAPABLE 6 +#define CPUID_PROCESSOR_SIGNATURE 1 /* function 1 */ +#define CPUID_XFAM 0x0ff00000 /* extended family */ +#define CPUID_XFAM_K8 0 +#define CPUID_XMOD 0x000f0000 /* extended model */ +#define CPUID_XMOD_REV_E 0x00020000 +#define CPUID_USE_XFAM_XMOD 0x00000f00 +#define CPUID_GET_MAX_CAPABILITIES 0x80000000 +#define CPUID_FREQ_VOLT_CAPABILITIES 0x80000007 +#define P_STATE_TRANSITION_CAPABLE 6 /* Model Specific Registers for p-state transitions. MSRs are 64-bit. For */ /* writes (wrmsr - opcode 0f 30), the register number is placed in ecx, and */ --- linux-2.6.6/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c 2004-05-09 21:07:22.000000000 -0700 +++ 25/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c 2004-05-10 01:19:01.788467168 -0700 @@ -38,13 +38,37 @@ #define dprintk(msg...) do { } while(0) #endif +struct cpu_id +{ + __u8 x86; /* CPU family */ + __u8 x86_vendor; /* CPU vendor */ + __u8 x86_model; /* model */ + __u8 x86_mask; /* stepping */ +}; + +static const struct cpu_id cpu_id_banias = { + .x86_vendor = X86_VENDOR_INTEL, + .x86 = 6, + .x86_model = 9, + .x86_mask = 5, +}; + +static const struct cpu_id cpu_id_dothan_a1 = { + .x86_vendor = X86_VENDOR_INTEL, + .x86 = 6, + .x86_model = 13, + .x86_mask = 1, +}; + struct cpu_model { + const struct cpu_id *cpu_id; const char *model_name; unsigned max_freq; /* max clock in kHz */ struct cpufreq_frequency_table *op_points; /* clock/voltage pairs */ }; +static int centrino_verify_cpu_id(struct cpuinfo_x86 *c, const struct cpu_id *x); /* Operating points for current CPU */ static struct cpu_model *centrino_model; @@ -67,8 +91,8 @@ static struct cpu_model *centrino_model; * M. */ -/* Ultra Low Voltage Intel Pentium M processor 900MHz */ -static struct cpufreq_frequency_table op_900[] = +/* Ultra Low Voltage Intel Pentium M processor 900MHz (Banias) */ +static struct cpufreq_frequency_table banias_900[] = { OP(600, 844), OP(800, 988), @@ -76,8 +100,8 @@ static struct cpufreq_frequency_table op { .frequency = CPUFREQ_TABLE_END } }; -/* Ultra Low Voltage Intel Pentium M processor 1000MHz */ -static struct cpufreq_frequency_table op_1000[] = +/* Ultra Low Voltage Intel Pentium M processor 1000MHz (Banias) */ +static struct cpufreq_frequency_table banias_1000[] = { OP(600, 844), OP(800, 972), @@ -86,8 +110,8 @@ static struct cpufreq_frequency_table op { .frequency = CPUFREQ_TABLE_END } }; -/* Low Voltage Intel Pentium M processor 1.10GHz */ -static struct cpufreq_frequency_table op_1100[] = +/* Low Voltage Intel Pentium M processor 1.10GHz (Banias) */ +static struct cpufreq_frequency_table banias_1100[] = { OP( 600, 956), OP( 800, 1020), @@ -98,8 +122,8 @@ static struct cpufreq_frequency_table op }; -/* Low Voltage Intel Pentium M processor 1.20GHz */ -static struct cpufreq_frequency_table op_1200[] = +/* Low Voltage Intel Pentium M processor 1.20GHz (Banias) */ +static struct cpufreq_frequency_table banias_1200[] = { OP( 600, 956), OP( 800, 1004), @@ -110,8 +134,8 @@ static struct cpufreq_frequency_table op { .frequency = CPUFREQ_TABLE_END } }; -/* Intel Pentium M processor 1.30GHz */ -static struct cpufreq_frequency_table op_1300[] = +/* Intel Pentium M processor 1.30GHz (Banias) */ +static struct cpufreq_frequency_table banias_1300[] = { OP( 600, 956), OP( 800, 1260), @@ -121,8 +145,8 @@ static struct cpufreq_frequency_table op { .frequency = CPUFREQ_TABLE_END } }; -/* Intel Pentium M processor 1.40GHz */ -static struct cpufreq_frequency_table op_1400[] = +/* Intel Pentium M processor 1.40GHz (Banias) */ +static struct cpufreq_frequency_table banias_1400[] = { OP( 600, 956), OP( 800, 1180), @@ -132,8 +156,8 @@ static struct cpufreq_frequency_table op { .frequency = CPUFREQ_TABLE_END } }; -/* Intel Pentium M processor 1.50GHz */ -static struct cpufreq_frequency_table op_1500[] = +/* Intel Pentium M processor 1.50GHz (Banias) */ +static struct cpufreq_frequency_table banias_1500[] = { OP( 600, 956), OP( 800, 1116), @@ -144,8 +168,8 @@ static struct cpufreq_frequency_table op { .frequency = CPUFREQ_TABLE_END } }; -/* Intel Pentium M processor 1.60GHz */ -static struct cpufreq_frequency_table op_1600[] = +/* Intel Pentium M processor 1.60GHz (Banias) */ +static struct cpufreq_frequency_table banias_1600[] = { OP( 600, 956), OP( 800, 1036), @@ -156,8 +180,8 @@ static struct cpufreq_frequency_table op { .frequency = CPUFREQ_TABLE_END } }; -/* Intel Pentium M processor 1.70GHz */ -static struct cpufreq_frequency_table op_1700[] = +/* Intel Pentium M processor 1.70GHz (Banias) */ +static struct cpufreq_frequency_table banias_1700[] = { OP( 600, 956), OP( 800, 1004), @@ -169,26 +193,31 @@ static struct cpufreq_frequency_table op }; #undef OP -#define _CPU(max, name) \ - { "Intel(R) Pentium(R) M processor " name "MHz", (max)*1000, op_##max } -#define CPU(max) _CPU(max, #max) +#define _BANIAS(cpuid, max, name) \ +{ .cpu_id = cpuid, \ + .model_name = "Intel(R) Pentium(R) M processor " name "MHz", \ + .max_freq = (max)*1000, \ + .op_points = banias_##max, \ +} +#define BANIAS(max) _BANIAS(&cpu_id_banias, max, #max) /* CPU models, their operating frequency range, and freq/voltage operating points */ static struct cpu_model models[] = { - _CPU( 900, " 900"), - CPU(1000), - CPU(1100), - CPU(1200), - CPU(1300), - CPU(1400), - CPU(1500), - CPU(1600), - CPU(1700), + _BANIAS(&cpu_id_banias, 900, " 900"), + BANIAS(1000), + BANIAS(1100), + BANIAS(1200), + BANIAS(1300), + BANIAS(1400), + BANIAS(1500), + BANIAS(1600), + BANIAS(1700), { 0, } }; -#undef CPU +#undef _BANIAS +#undef BANIAS static int centrino_cpu_init_table(struct cpufreq_policy *policy) { @@ -196,7 +225,8 @@ static int centrino_cpu_init_table(struc struct cpu_model *model; for(model = models; model->model_name != NULL; model++) - if (strcmp(cpu->x86_model_id, model->model_name) == 0) + if ((strcmp(cpu->x86_model_id, model->model_name) == 0) && + (!centrino_verify_cpu_id(cpu, model->cpu_id))) break; if (model->model_name == NULL) { printk(KERN_INFO PFX "no support for CPU model \"%s\": " @@ -217,6 +247,16 @@ static int centrino_cpu_init_table(struc static inline int centrino_cpu_init_table(struct cpufreq_policy *policy) { return -ENODEV; } #endif /* CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE */ +static int centrino_verify_cpu_id(struct cpuinfo_x86 *c, const struct cpu_id *x) +{ + if ((c->x86 == x->x86) && + (c->x86_vendor == x->x86_vendor) && + (c->x86_model == x->x86_model) && + (c->x86_mask == x->x86_mask)) + return 0; + return -ENODEV; +} + /* Extract clock in kHz from PERF_CTL value */ static unsigned extract_clock(unsigned msr) { @@ -225,9 +265,11 @@ static unsigned extract_clock(unsigned m } /* Return the current CPU frequency in kHz */ -static unsigned get_cur_freq(void) +static unsigned int get_cur_freq(unsigned int cpu) { unsigned l, h; + if (cpu) + return 0; rdmsr(MSR_IA32_PERF_STATUS, l, h); return extract_clock(l); @@ -322,7 +364,7 @@ static int centrino_cpu_init_acpi(struct goto err_kfree; } - cur_freq = get_cur_freq(); + cur_freq = get_cur_freq(0); for (i=0; iop_points[i].index = p.states[i].control; @@ -357,13 +399,8 @@ static int centrino_cpu_init(struct cpuf if (!cpu_has(cpu, X86_FEATURE_EST)) return -ENODEV; - /* Only Intel Pentium M stepping 5 for now - add new CPUs as - they appear after making sure they use PERF_CTL in the same - way. */ - if (cpu->x86_vendor != X86_VENDOR_INTEL || - cpu->x86 != 6 || - cpu->x86_model != 9 || - cpu->x86_mask != 5) { + if ((centrino_verify_cpu_id(cpu, &cpu_id_banias)) && + (centrino_verify_cpu_id(cpu, &cpu_id_dothan_a1))) { printk(KERN_INFO PFX "found unsupported CPU with Enhanced SpeedStep: " "send /proc/cpuinfo to " MAINTAINER "\n"); return -ENODEV; @@ -391,7 +428,7 @@ static int centrino_cpu_init(struct cpuf } } - freq = get_cur_freq(); + freq = get_cur_freq(0); policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = 10; /* 10uS transition latency */ @@ -516,6 +553,7 @@ static struct cpufreq_driver centrino_dr .exit = centrino_cpu_exit, .verify = centrino_verify, .target = centrino_target, + .get = get_cur_freq, .attr = centrino_attr, .owner = THIS_MODULE, }; --- linux-2.6.6/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c 2004-05-09 21:07:22.000000000 -0700 +++ 25/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c 2004-05-10 01:19:01.788467168 -0700 @@ -322,6 +322,10 @@ static int speedstep_cpu_exit(struct cpu return 0; } +static unsigned int speedstep_get(unsigned int cpu) +{ + return speedstep_get_processor_frequency(speedstep_processor); +} static struct freq_attr* speedstep_attr[] = { &cpufreq_freq_attr_scaling_available_freqs, @@ -335,6 +339,7 @@ static struct cpufreq_driver speedstep_d .target = speedstep_target, .init = speedstep_cpu_init, .exit = speedstep_cpu_exit, + .get = speedstep_get, .owner = THIS_MODULE, .attr = speedstep_attr, }; --- linux-2.6.6/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c 2004-05-09 21:07:22.000000000 -0700 +++ 25/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c 2004-05-10 01:19:01.789467016 -0700 @@ -36,6 +36,8 @@ static int smi_port = 0; static int smi_cmd = 0; static unsigned int smi_sig = 0; +/* info about the processor */ +static unsigned int speedstep_processor = 0; /* * There are only two frequency states for each processor. Values @@ -258,10 +260,11 @@ static int speedstep_cpu_init(struct cpu &speedstep_freqs[SPEEDSTEP_HIGH].frequency); if (result) { /* fall back to speedstep_lib.c dection mechanism: try both states out */ - unsigned int speedstep_processor = speedstep_detect_processor(); - dprintk(KERN_INFO PFX "could not detect low and high frequencies by SMI call.\n"); if (!speedstep_processor) + speedstep_processor = speedstep_detect_processor(); + + if (!speedstep_processor) return -ENODEV; result = speedstep_get_freqs(speedstep_processor, @@ -298,13 +301,23 @@ static int speedstep_cpu_init(struct cpu return 0; } - static int speedstep_cpu_exit(struct cpufreq_policy *policy) { cpufreq_frequency_table_put_attr(policy->cpu); return 0; } +static unsigned int speedstep_get(unsigned int cpu) +{ + if (cpu) + return -ENODEV; + if (!speedstep_processor) + speedstep_processor = speedstep_detect_processor(); + if (!speedstep_processor) + return 0; + return speedstep_get_processor_frequency(speedstep_processor); +} + static int speedstep_resume(struct cpufreq_policy *policy) { @@ -327,6 +340,7 @@ static struct cpufreq_driver speedstep_d .target = speedstep_target, .init = speedstep_cpu_init, .exit = speedstep_cpu_exit, + .get = speedstep_get, .resume = speedstep_resume, .owner = THIS_MODULE, .attr = speedstep_attr, --- linux-2.6.6/arch/i386/kernel/cpu/cpu.h 2003-06-14 12:17:56.000000000 -0700 +++ 25/arch/i386/kernel/cpu/cpu.h 2004-05-10 01:19:37.448046088 -0700 @@ -26,3 +26,6 @@ extern void display_cacheinfo(struct cpu extern void generic_identify(struct cpuinfo_x86 * c); extern int have_cpuid_p(void); + +extern void early_intel_workaround(struct cpuinfo_x86 *c); + --- linux-2.6.6/arch/i386/kernel/cpuid.c 2004-02-17 20:48:42.000000000 -0800 +++ 25/arch/i386/kernel/cpuid.c 2004-05-10 01:19:55.812254304 -0700 @@ -10,7 +10,6 @@ * * ----------------------------------------------------------------------- */ - /* * cpuid.c * @@ -46,131 +45,132 @@ #ifdef CONFIG_SMP struct cpuid_command { - int cpu; - u32 reg; - u32 *data; + int cpu; + u32 reg; + u32 *data; }; static void cpuid_smp_cpuid(void *cmd_block) { - struct cpuid_command *cmd = (struct cpuid_command *) cmd_block; - - if ( cmd->cpu == smp_processor_id() ) - cpuid(cmd->reg, &cmd->data[0], &cmd->data[1], &cmd->data[2], &cmd->data[3]); + struct cpuid_command *cmd = (struct cpuid_command *)cmd_block; + + if (cmd->cpu == smp_processor_id()) + cpuid(cmd->reg, &cmd->data[0], &cmd->data[1], &cmd->data[2], + &cmd->data[3]); } -static inline void do_cpuid(int cpu, u32 reg, u32 *data) +static inline void do_cpuid(int cpu, u32 reg, u32 * data) { - struct cpuid_command cmd; - - preempt_disable(); - if ( cpu == smp_processor_id() ) { - cpuid(reg, &data[0], &data[1], &data[2], &data[3]); - } else { - cmd.cpu = cpu; - cmd.reg = reg; - cmd.data = data; - - smp_call_function(cpuid_smp_cpuid, &cmd, 1, 1); - } - preempt_enable(); + struct cpuid_command cmd; + + preempt_disable(); + if (cpu == smp_processor_id()) { + cpuid(reg, &data[0], &data[1], &data[2], &data[3]); + } else { + cmd.cpu = cpu; + cmd.reg = reg; + cmd.data = data; + + smp_call_function(cpuid_smp_cpuid, &cmd, 1, 1); + } + preempt_enable(); } -#else /* ! CONFIG_SMP */ +#else /* ! CONFIG_SMP */ -static inline void do_cpuid(int cpu, u32 reg, u32 *data) +static inline void do_cpuid(int cpu, u32 reg, u32 * data) { - cpuid(reg, &data[0], &data[1], &data[2], &data[3]); + cpuid(reg, &data[0], &data[1], &data[2], &data[3]); } -#endif /* ! CONFIG_SMP */ +#endif /* ! CONFIG_SMP */ static loff_t cpuid_seek(struct file *file, loff_t offset, int orig) { - loff_t ret; + loff_t ret; + + lock_kernel(); - lock_kernel(); + switch (orig) { + case 0: + file->f_pos = offset; + ret = file->f_pos; + break; + case 1: + file->f_pos += offset; + ret = file->f_pos; + break; + default: + ret = -EINVAL; + } + + unlock_kernel(); + return ret; +} + +static ssize_t cpuid_read(struct file *file, char *buf, + size_t count, loff_t * ppos) +{ + u32 *tmp = (u32 *) buf; + u32 data[4]; + size_t rv; + u32 reg = *ppos; + int cpu = iminor(file->f_dentry->d_inode); + + if (count % 16) + return -EINVAL; /* Invalid chunk size */ + + for (rv = 0; count; count -= 16) { + do_cpuid(cpu, reg, data); + if (copy_to_user(tmp, &data, 16)) + return -EFAULT; + tmp += 4; + *ppos = reg++; + } - switch (orig) { - case 0: - file->f_pos = offset; - ret = file->f_pos; - break; - case 1: - file->f_pos += offset; - ret = file->f_pos; - break; - default: - ret = -EINVAL; - } - - unlock_kernel(); - return ret; -} - -static ssize_t cpuid_read(struct file * file, char * buf, - size_t count, loff_t *ppos) -{ - u32 *tmp = (u32 *)buf; - u32 data[4]; - size_t rv; - u32 reg = *ppos; - int cpu = iminor(file->f_dentry->d_inode); - - if ( count % 16 ) - return -EINVAL; /* Invalid chunk size */ - - for ( rv = 0 ; count ; count -= 16 ) { - do_cpuid(cpu, reg, data); - if ( copy_to_user(tmp,&data,16) ) - return -EFAULT; - tmp += 4; - *ppos = reg++; - } - - return ((char *)tmp) - buf; + return ((char *)tmp) - buf; } static int cpuid_open(struct inode *inode, struct file *file) { - int cpu = iminor(file->f_dentry->d_inode); - struct cpuinfo_x86 *c = &(cpu_data)[cpu]; + int cpu = iminor(file->f_dentry->d_inode); + struct cpuinfo_x86 *c = &(cpu_data)[cpu]; + + if (!cpu_online(cpu)) + return -ENXIO; /* No such CPU */ + if (c->cpuid_level < 0) + return -EIO; /* CPUID not supported */ - if (!cpu_online(cpu)) - return -ENXIO; /* No such CPU */ - if ( c->cpuid_level < 0 ) - return -EIO; /* CPUID not supported */ - - return 0; + return 0; } /* * File operations we support */ static struct file_operations cpuid_fops = { - .owner = THIS_MODULE, - .llseek = cpuid_seek, - .read = cpuid_read, - .open = cpuid_open, + .owner = THIS_MODULE, + .llseek = cpuid_seek, + .read = cpuid_read, + .open = cpuid_open, }; int __init cpuid_init(void) { - if (register_chrdev(CPUID_MAJOR, "cpu/cpuid", &cpuid_fops)) { - printk(KERN_ERR "cpuid: unable to get major %d for cpuid\n", - CPUID_MAJOR); - return -EBUSY; - } + if (register_chrdev(CPUID_MAJOR, "cpu/cpuid", &cpuid_fops)) { + printk(KERN_ERR "cpuid: unable to get major %d for cpuid\n", + CPUID_MAJOR); + return -EBUSY; + } - return 0; + return 0; } void __exit cpuid_exit(void) { - unregister_chrdev(CPUID_MAJOR, "cpu/cpuid"); + unregister_chrdev(CPUID_MAJOR, "cpu/cpuid"); } module_init(cpuid_init); -module_exit(cpuid_exit) +module_exit(cpuid_exit); MODULE_AUTHOR("H. Peter Anvin "); MODULE_DESCRIPTION("x86 generic CPUID driver"); --- linux-2.6.6/arch/i386/kernel/cpu/intel.c 2004-03-10 20:41:25.000000000 -0800 +++ 25/arch/i386/kernel/cpu/intel.c 2004-05-10 01:19:37.449045936 -0700 @@ -28,6 +28,15 @@ extern int trap_init_f00f_bug(void); struct movsl_mask movsl_mask; #endif +void __init early_intel_workaround(struct cpuinfo_x86 *c) +{ + if (c->x86_vendor != X86_VENDOR_INTEL) + return; + /* Netburst reports 64 bytes clflush size, but does IO in 128 bytes */ + if (c->x86 == 15 && c->x86_cache_alignment == 64) + c->x86_cache_alignment = 128; +} + /* * Early probe support logic for ppro memory erratum #50 * @@ -36,42 +45,14 @@ struct movsl_mask movsl_mask; int __init ppro_with_ram_bug(void) { - char vendor_id[16]; - int ident; - - /* Must have CPUID */ - if(!have_cpuid_p()) - return 0; - if(cpuid_eax(0)<1) - return 0; - - /* Must be Intel */ - cpuid(0, &ident, - (int *)&vendor_id[0], - (int *)&vendor_id[8], - (int *)&vendor_id[4]); - - if(memcmp(vendor_id, "IntelInside", 12)) - return 0; - - ident = cpuid_eax(1); - - /* Model 6 */ - - if(((ident>>8)&15)!=6) - return 0; - - /* Pentium Pro */ - - if(((ident>>4)&15)!=1) - return 0; - - if((ident&15) < 8) - { + /* Uses data from early_cpu_detect now */ + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && + boot_cpu_data.x86 == 6 && + boot_cpu_data.x86_model == 1 && + boot_cpu_data.x86_mask < 8) { printk(KERN_INFO "Pentium Pro with Errata#50 detected. Taking evasive action.\n"); return 1; } - printk(KERN_INFO "Your Pentium Pro seems ok.\n"); return 0; } --- linux-2.6.6/arch/i386/kernel/cpu/mcheck/p4.c 2003-10-08 15:07:08.000000000 -0700 +++ 25/arch/i386/kernel/cpu/mcheck/p4.c 2004-05-10 01:19:48.490367400 -0700 @@ -38,7 +38,8 @@ static int mce_num_extended_msrs = 0; #ifdef CONFIG_X86_MCE_P4THERMAL static void unexpected_thermal_interrupt(struct pt_regs *regs) { - printk(KERN_ERR "CPU#%d: Unexpected LVT TMR interrupt!\n", smp_processor_id()); + printk(KERN_ERR "CPU%d: Unexpected LVT TMR interrupt!\n", + smp_processor_id()); } /* P4/Xeon Thermal transition interrupt handler */ @@ -46,15 +47,21 @@ static void intel_thermal_interrupt(stru { u32 l, h; unsigned int cpu = smp_processor_id(); + static unsigned long next[NR_CPUS]; ack_APIC_irq(); - rdmsr (MSR_IA32_THERM_STATUS, l, h); - if (l & 1) { - printk(KERN_EMERG "CPU#%d: Temperature above threshold\n", cpu); - printk(KERN_EMERG "CPU#%d: Running in modulated clock mode\n", cpu); + if (time_after(next[cpu], jiffies)) + return; + + next[cpu] = jiffies + HZ*5; + rdmsr(MSR_IA32_THERM_STATUS, l, h); + if (l & 0x1) { + printk(KERN_EMERG "CPU%d: Temperature above threshold\n", cpu); + printk(KERN_EMERG "CPU%d: Running in modulated clock mode\n", + cpu); } else { - printk(KERN_INFO "CPU#%d: Temperature/speed normal\n", cpu); + printk(KERN_INFO "CPU%d: Temperature/speed normal\n", cpu); } } @@ -89,13 +96,15 @@ static void __init intel_init_thermal(st rdmsr (MSR_IA32_MISC_ENABLE, l, h); h = apic_read(APIC_LVTTHMR); if ((l & (1<<3)) && (h & APIC_DM_SMI)) { - printk(KERN_DEBUG "CPU#%d: Thermal monitoring handled by SMI\n", cpu); + printk(KERN_DEBUG "CPU%d: Thermal monitoring handled by SMI\n", + cpu); return; /* -EBUSY */ } /* check whether a vector already exists, temporarily masked? */ if (h & APIC_VECTOR_MASK) { - printk(KERN_DEBUG "CPU#%d: Thermal LVT vector (%#x) already installed\n", + printk(KERN_DEBUG "CPU%d: Thermal LVT vector (%#x) already " + "installed\n", cpu, (h & APIC_VECTOR_MASK)); return; /* -EBUSY */ } @@ -116,7 +125,7 @@ static void __init intel_init_thermal(st l = apic_read (APIC_LVTTHMR); apic_write_around (APIC_LVTTHMR, l & ~APIC_LVT_MASKED); - printk (KERN_INFO "CPU#%d: Thermal monitoring enabled\n", cpu); + printk (KERN_INFO "CPU%d: Thermal monitoring enabled\n", cpu); return; } #endif /* CONFIG_X86_MCE_P4THERMAL */ @@ -247,7 +256,8 @@ void __init intel_p4_mcheck_init(struct rdmsr (MSR_IA32_MCG_CAP, l, h); if (l & (1<<9)) {/* MCG_EXT_P */ mce_num_extended_msrs = (l >> 16) & 0xff; - printk (KERN_INFO "CPU#%d: Intel P4/Xeon Extended MCE MSRs (%d) available\n", + printk (KERN_INFO "CPU%d: Intel P4/Xeon Extended MCE MSRs (%d)" + " available\n", smp_processor_id(), mce_num_extended_msrs); #ifdef CONFIG_X86_MCE_P4THERMAL --- linux-2.6.6/arch/i386/kernel/efi.c 2004-05-09 21:07:22.000000000 -0700 +++ 25/arch/i386/kernel/efi.c 2004-05-10 01:19:35.824292936 -0700 @@ -37,7 +37,6 @@ #include #include #include -#include #include #define EFI_DEBUG 0 --- linux-2.6.6/arch/i386/kernel/entry.S 2004-05-09 21:07:22.000000000 -0700 +++ 25/arch/i386/kernel/entry.S 2004-05-10 01:19:26.560701216 -0700 @@ -48,6 +48,18 @@ #include #include #include "irq_vectors.h" + /* We do not recover from a stack overflow, but at least + * we know it happened and should be able to track it down. + */ +#ifdef CONFIG_STACK_OVERFLOW_TEST +#define STACK_OVERFLOW_TEST \ + testl $(THREAD_SIZE - 512),%esp; \ + jnz 10f; \ + call stack_overflow; \ +10: +#else +#define STACK_OVERFLOW_TEST +#endif #define nr_syscalls ((syscall_table_size)/4) @@ -100,7 +112,8 @@ TSS_ESP0_OFFSET = (4 - 0x200) pushl %ebx; \ movl $(__USER_DS), %edx; \ movl %edx, %ds; \ - movl %edx, %es; + movl %edx, %es; \ + STACK_OVERFLOW_TEST #define RESTORE_INT_REGS \ popl %ebx; \ @@ -300,6 +313,19 @@ syscall_exit: testw $_TIF_ALLWORK_MASK, %cx # current->work jne syscall_exit_work restore_all: +#ifdef CONFIG_TRAP_BAD_SYSCALL_EXITS + movl EFLAGS(%esp), %eax # mix EFLAGS and CS + movb CS(%esp), %al + testl $(VM_MASK | 3), %eax + jz resume_kernelX # returning to kernel or vm86-space + + cmpl $0,TI_PRE_COUNT(%ebx) # non-zero preempt_count ? + jz resume_kernelX + + int $3 + +resume_kernelX: +#endif RESTORE_ALL # perform work that needs to be done immediately before resumption @@ -882,9 +908,9 @@ ENTRY(sys_call_table) .long sys_utimes .long sys_fadvise64_64 .long sys_ni_syscall /* sys_vserver */ - .long sys_ni_syscall /* sys_mbind */ - .long sys_ni_syscall /* 275 sys_get_mempolicy */ - .long sys_ni_syscall /* sys_set_mempolicy */ + .long sys_mbind + .long sys_get_mempolicy + .long sys_set_mempolicy .long sys_mq_open .long sys_mq_unlink .long sys_mq_timedsend --- linux-2.6.6/arch/i386/kernel/i386_ksyms.c 2004-04-03 20:39:10.000000000 -0800 +++ 25/arch/i386/kernel/i386_ksyms.c 2004-05-10 01:19:35.824292936 -0700 @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include --- linux-2.6.6/arch/i386/kernel/io_apic.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/i386/kernel/io_apic.c 2004-05-10 01:19:19.784731320 -0700 @@ -317,8 +317,7 @@ struct irq_cpu_info { #define IRQ_ALLOWED(cpu, allowed_mask) cpu_isset(cpu, allowed_mask) -#define CPU_TO_PACKAGEINDEX(i) \ - ((physical_balance && i > cpu_sibling_map[i]) ? cpu_sibling_map[i] : i) +#define CPU_TO_PACKAGEINDEX(i) (first_cpu(cpu_sibling_map[i])) #define MAX_BALANCED_IRQ_INTERVAL (5*HZ) #define MIN_BALANCED_IRQ_INTERVAL (HZ/2) @@ -401,6 +400,7 @@ static void do_irq_balance(void) unsigned long max_cpu_irq = 0, min_cpu_irq = (~0); unsigned long move_this_load = 0; int max_loaded = 0, min_loaded = 0; + int load; unsigned long useful_load_threshold = balanced_irq_interval + 10; int selected_irq; int tmp_loaded, first_attempt = 1; @@ -452,7 +452,7 @@ static void do_irq_balance(void) for (i = 0; i < NR_CPUS; i++) { if (!cpu_online(i)) continue; - if (physical_balance && i > cpu_sibling_map[i]) + if (i != CPU_TO_PACKAGEINDEX(i)) continue; if (min_cpu_irq > CPU_IRQ(i)) { min_cpu_irq = CPU_IRQ(i); @@ -471,7 +471,7 @@ tryanothercpu: for (i = 0; i < NR_CPUS; i++) { if (!cpu_online(i)) continue; - if (physical_balance && i > cpu_sibling_map[i]) + if (i != CPU_TO_PACKAGEINDEX(i)) continue; if (max_cpu_irq <= CPU_IRQ(i)) continue; @@ -551,9 +551,14 @@ tryanotherirq: * We seek the least loaded sibling by making the comparison * (A+B)/2 vs B */ - if (physical_balance && (CPU_IRQ(min_loaded) >> 1) > - CPU_IRQ(cpu_sibling_map[min_loaded])) - min_loaded = cpu_sibling_map[min_loaded]; + load = CPU_IRQ(min_loaded) >> 1; + for_each_cpu_mask(j, cpu_sibling_map[min_loaded]) { + if (load > CPU_IRQ(j)) { + /* This won't change cpu_sibling_map[min_loaded] */ + load = CPU_IRQ(j); + min_loaded = j; + } + } cpus_and(allowed_mask, cpu_online_map, irq_affinity[selected_irq]); target_cpu_mask = cpumask_of_cpu(min_loaded); --- linux-2.6.6/arch/i386/kernel/irq.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/i386/kernel/irq.c 2004-05-10 01:19:48.744328792 -0700 @@ -41,7 +41,6 @@ #include #include #include -#include #include #include #include @@ -77,10 +76,8 @@ static void register_irq_proc (unsigned /* * per-CPU IRQ handling stacks */ -#ifdef CONFIG_4KSTACKS union irq_ctx *hardirq_ctx[NR_CPUS]; union irq_ctx *softirq_ctx[NR_CPUS]; -#endif /* * Special irq handlers. @@ -488,8 +485,6 @@ asmlinkage unsigned int do_IRQ(struct pt * useful for irq hardware that does not mask cleanly in an * SMP environment. */ -#ifdef CONFIG_4KSTACKS - for (;;) { irqreturn_t action_ret; u32 *isp; @@ -502,9 +497,10 @@ asmlinkage unsigned int do_IRQ(struct pt spin_unlock(&desc->lock); /* - * this is where we switch to the IRQ stack. However, if we are already using - * the IRQ stack (because we interrupted a hardirq handler) we can't do that - * and just have to keep using the current stack (which is the irq stack already + * this is where we switch to the IRQ stack. However, if we are + * already using the IRQ stack (because we interrupted a + * hardirq handler) we can't do that and just have to keep + * using the current stack (which is the irq stack already * after all) */ @@ -541,23 +537,6 @@ asmlinkage unsigned int do_IRQ(struct pt desc->status &= ~IRQ_PENDING; } -#else - - for (;;) { - irqreturn_t action_ret; - - spin_unlock(&desc->lock); - - action_ret = handle_IRQ_event(irq, ®s, action); - - spin_lock(&desc->lock); - if (!noirqdebug) - note_interrupt(irq, desc, action_ret); - if (likely(!(desc->status & IRQ_PENDING))) - break; - desc->status &= ~IRQ_PENDING; - } -#endif desc->status &= ~IRQ_INPROGRESS; out: @@ -570,6 +549,8 @@ out: irq_exit(); + kgdb_process_breakpoint(); + return 1; } @@ -1116,9 +1097,10 @@ void init_irq_proc (void) } -#ifdef CONFIG_4KSTACKS -static char softirq_stack[NR_CPUS * THREAD_SIZE] __attribute__((__aligned__(THREAD_SIZE))); -static char hardirq_stack[NR_CPUS * THREAD_SIZE] __attribute__((__aligned__(THREAD_SIZE))); +static char softirq_stack[NR_CPUS * THREAD_SIZE] + __attribute__((__aligned__(THREAD_SIZE))); +static char hardirq_stack[NR_CPUS * THREAD_SIZE] + __attribute__((__aligned__(THREAD_SIZE))); /* * allocate per-cpu stacks for hardirq and for softirq processing @@ -1188,6 +1170,4 @@ asmlinkage void do_softirq(void) local_irq_restore(flags); } - EXPORT_SYMBOL(do_softirq); -#endif --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/arch/i386/kernel/kgdb_stub.c 2004-05-10 01:19:31.137005512 -0700 @@ -0,0 +1,2454 @@ +/* + * + * 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, 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. + * + */ + +/* + * Copyright (c) 2000 VERITAS Software Corporation. + * + */ +/**************************************************************************** + * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $ + * + * Module name: remcom.c $ + * Revision: 1.34 $ + * Date: 91/03/09 12:29:49 $ + * Contributor: Lake Stevens Instrument Division$ + * + * Description: low level support for gdb debugger. $ + * + * Considerations: only works on target hardware $ + * + * Written by: Glenn Engel $ + * Updated by: David Grothe + * Updated by: Robert Walsh + * Updated by: wangdi + * ModuleState: Experimental $ + * + * NOTES: See Below $ + * + * Modified for 386 by Jim Kingdon, Cygnus Support. + * Compatibility with 2.1.xx kernel by David Grothe + * + * Changes to allow auto initilization. All that is needed is that it + * be linked with the kernel and a break point (int 3) be executed. + * The header file defines BREAKPOINT to allow one to do + * this. It should also be possible, once the interrupt system is up, to + * call putDebugChar("+"). Once this is done, the remote debugger should + * get our attention by sending a ^C in a packet. George Anzinger + * + * Integrated into 2.2.5 kernel by Tigran Aivazian + * Added thread support, support for multiple processors, + * support for ia-32(x86) hardware debugging. + * Amit S. Kale ( akale@veritas.com ) + * + * Modified to support debugging over ethernet by Robert Walsh + * and wangdi , based on + * code by San Mehat. + * + * + * To enable debugger support, two things need to happen. One, a + * call to set_debug_traps() is necessary in order to allow any breakpoints + * or error conditions to be properly intercepted and reported to gdb. + * Two, a breakpoint needs to be generated to begin communication. This + * is most easily accomplished by a call to breakpoint(). Breakpoint() + * simulates a breakpoint by executing an int 3. + * + ************* + * + * The following gdb commands are supported: + * + * command function Return value + * + * g return the value of the CPU registers hex data or ENN + * G set the value of the CPU registers OK or ENN + * + * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN + * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN + * + * c Resume at current address SNN ( signal NN) + * cAA..AA Continue at address AA..AA SNN + * + * s Step one instruction SNN + * sAA..AA Step one instruction from AA..AA SNN + * + * k kill + * + * ? What was the last sigval ? SNN (signal NN) + * + * All commands and responses are sent with a packet which includes a + * checksum. A packet consists of + * + * $#. + * + * where + * :: + * :: < two hex digits computed as modulo 256 sum of > + * + * When a packet is received, it is first acknowledged with either '+' or '-'. + * '+' indicates a successful transfer. '-' indicates a failed transfer. + * + * Example: + * + * Host: Reply: + * $m0,10#2a +$00010203040506070809101112131415#42 + * + ****************************************************************************/ +#define KGDB_VERSION "<20030915.1651.33>" +#include +#include +#include /* for strcpy */ +#include +#include +#include +#include +#include /* for linux pt_regs struct */ +#include +#include +#include +#include +#include +#include +#include +#include + +/************************************************************************ + * + * external low-level support routines + */ +typedef void (*Function) (void); /* pointer to a function */ + +/* Thread reference */ +typedef unsigned char threadref[8]; + +extern int tty_putDebugChar(int); /* write a single character */ +extern int tty_getDebugChar(void); /* read and return a single char */ +extern void tty_flushDebugChar(void); /* flush pending characters */ +extern int eth_putDebugChar(int); /* write a single character */ +extern int eth_getDebugChar(void); /* read and return a single char */ +extern void eth_flushDebugChar(void); /* flush pending characters */ + +/************************************************************************/ +/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/ +/* at least NUMREGBYTES*2 are needed for register packets */ +/* Longer buffer is needed to list all threads */ +#define BUFMAX 400 + +char *kgdb_version = KGDB_VERSION; + +/* debug > 0 prints ill-formed commands in valid packets & checksum errors */ +int debug_regs = 0; /* set to non-zero to print registers */ + +/* filled in by an external module */ +char *gdb_module_offsets; + +static const char hexchars[] = "0123456789abcdef"; + +/* Number of bytes of registers. */ +#define NUMREGBYTES 64 +/* + * Note that this register image is in a different order than + * the register image that Linux produces at interrupt time. + * + * Linux's register image is defined by struct pt_regs in ptrace.h. + * Just why GDB uses a different order is a historical mystery. + */ +enum regnames { _EAX, /* 0 */ + _ECX, /* 1 */ + _EDX, /* 2 */ + _EBX, /* 3 */ + _ESP, /* 4 */ + _EBP, /* 5 */ + _ESI, /* 6 */ + _EDI, /* 7 */ + _PC /* 8 also known as eip */ , + _PS /* 9 also known as eflags */ , + _CS, /* 10 */ + _SS, /* 11 */ + _DS, /* 12 */ + _ES, /* 13 */ + _FS, /* 14 */ + _GS /* 15 */ +}; + +/*************************** ASSEMBLY CODE MACROS *************************/ +/* + * Put the error code here just in case the user cares. + * Likewise, the vector number here (since GDB only gets the signal + * number through the usual means, and that's not very specific). + * The called_from is the return address so he can tell how we entered kgdb. + * This will allow him to seperate out the various possible entries. + */ +#define REMOTE_DEBUG 0 /* set != to turn on printing (also available in info) */ + +#define PID_MAX PID_MAX_DEFAULT + +#ifdef CONFIG_SMP +void smp_send_nmi_allbutself(void); +#define IF_SMP(x) x +#undef MAX_NO_CPUS +#ifndef CONFIG_NO_KGDB_CPUS +#define CONFIG_NO_KGDB_CPUS 2 +#endif +#if CONFIG_NO_KGDB_CPUS > NR_CPUS +#define MAX_NO_CPUS NR_CPUS +#else +#define MAX_NO_CPUS CONFIG_NO_KGDB_CPUS +#endif +#define hold_init hold_on_sstep: 1, +#define MAX_CPU_MASK (unsigned long)((1LL << MAX_NO_CPUS) - 1LL) +#define NUM_CPUS num_online_cpus() +#else +#define IF_SMP(x) +#define hold_init +#undef MAX_NO_CPUS +#define MAX_NO_CPUS 1 +#define NUM_CPUS 1 +#endif +#define NOCPU (struct task_struct *)0xbad1fbad +/* *INDENT-OFF* */ +struct kgdb_info { + int used_malloc; + void *called_from; + long long entry_tsc; + int errcode; + int vector; + int print_debug_info; +#ifdef CONFIG_SMP + int hold_on_sstep; + struct { + volatile struct task_struct *task; + int pid; + int hold; + struct pt_regs *regs; + } cpus_waiting[MAX_NO_CPUS]; +#endif +} kgdb_info = {hold_init print_debug_info:REMOTE_DEBUG, vector:-1}; + +/* *INDENT-ON* */ + +#define used_m kgdb_info.used_malloc +/* + * This is little area we set aside to contain the stack we + * need to build to allow gdb to call functions. We use one + * per cpu to avoid locking issues. We will do all this work + * with interrupts off so that should take care of the protection + * issues. + */ +#define LOOKASIDE_SIZE 200 /* should be more than enough */ +#define MALLOC_MAX 200 /* Max malloc size */ +struct { + unsigned int esp; + int array[LOOKASIDE_SIZE]; +} fn_call_lookaside[MAX_NO_CPUS]; + +static int trap_cpu; +static unsigned int OLD_esp; + +#define END_OF_LOOKASIDE &fn_call_lookaside[trap_cpu].array[LOOKASIDE_SIZE] +#define IF_BIT 0x200 +#define TF_BIT 0x100 + +#define MALLOC_ROUND 8-1 + +static char malloc_array[MALLOC_MAX]; +IF_SMP(static void to_gdb(const char *mess)); +void * +malloc(int size) +{ + + if (size <= (MALLOC_MAX - used_m)) { + int old_used = used_m; + used_m += ((size + MALLOC_ROUND) & (~MALLOC_ROUND)); + return &malloc_array[old_used]; + } else { + return NULL; + } +} + +/* + * I/O dispatch functions... + * Based upon kgdboe, either call the ethernet + * handler or the serial one.. + */ +void +putDebugChar(int c) +{ + if (!kgdboe) { + tty_putDebugChar(c); + } else { + eth_putDebugChar(c); + } +} + +int +getDebugChar(void) +{ + if (!kgdboe) { + return tty_getDebugChar(); + } else { + return eth_getDebugChar(); + } +} + +void +flushDebugChar(void) +{ + if (!kgdboe) { + tty_flushDebugChar(); + } else { + eth_flushDebugChar(); + } +} + +/* + * Gdb calls functions by pushing agruments, including a return address + * on the stack and the adjusting EIP to point to the function. The + * whole assumption in GDB is that we are on a different stack than the + * one the "user" i.e. code that hit the break point, is on. This, of + * course is not true in the kernel. Thus various dodges are needed to + * do the call without directly messing with EIP (which we can not change + * as it is just a location and not a register. To adjust it would then + * require that we move every thing below EIP up or down as needed. This + * will not work as we may well have stack relative pointer on the stack + * (such as the pointer to regs, for example). + + * So here is what we do: + * We detect gdb attempting to store into the stack area and instead, store + * into the fn_call_lookaside.array at the same relative location as if it + * were the area ESP pointed at. We also trap ESP modifications + * and uses these to adjust fn_call_lookaside.esp. On entry + * fn_call_lookaside.esp will be set to point at the last entry in + * fn_call_lookaside.array. This allows us to check if it has changed, and + * if so, on exit, we add the registers we will use to do the move and a + * trap/ interrupt return exit sequence. We then adjust the eflags in the + * regs array (remember we now have a copy in the fn_call_lookaside.array) to + * kill the interrupt bit, AND we change EIP to point at our set up stub. + * As part of the register set up we preset the registers to point at the + * begining and end of the fn_call_lookaside.array, so all the stub needs to + * do is move words from the array to the stack until ESP= the desired value + * then do the rti. This will then transfer to the desired function with + * all the correct registers. Nifty huh? + */ +extern asmlinkage void fn_call_stub(void); +extern asmlinkage void fn_rtn_stub(void); +/* *INDENT-OFF* */ +__asm__("fn_rtn_stub:\n\t" + "movl %eax,%esp\n\t" + "fn_call_stub:\n\t" + "1:\n\t" + "addl $-4,%ebx\n\t" + "movl (%ebx), %eax\n\t" + "pushl %eax\n\t" + "cmpl %esp,%ecx\n\t" + "jne 1b\n\t" + "popl %eax\n\t" + "popl %ebx\n\t" + "popl %ecx\n\t" + "iret \n\t"); +/* *INDENT-ON* */ +#define gdb_i386vector kgdb_info.vector +#define gdb_i386errcode kgdb_info.errcode +#define waiting_cpus kgdb_info.cpus_waiting +#define remote_debug kgdb_info.print_debug_info +#define hold_cpu(cpu) kgdb_info.cpus_waiting[cpu].hold +/* gdb locks */ + +#ifdef CONFIG_SMP +static int in_kgdb_called; +static spinlock_t waitlocks[MAX_NO_CPUS] = + {[0 ... MAX_NO_CPUS - 1] = SPIN_LOCK_UNLOCKED }; +/* + * The following array has the thread pointer of each of the "other" + * cpus. We make it global so it can be seen by gdb. + */ +volatile int in_kgdb_entry_log[MAX_NO_CPUS]; +volatile struct pt_regs *in_kgdb_here_log[MAX_NO_CPUS]; +/* +static spinlock_t continuelocks[MAX_NO_CPUS]; +*/ +spinlock_t kgdb_spinlock = SPIN_LOCK_UNLOCKED; +/* waiters on our spinlock plus us */ +static atomic_t spinlock_waiters = ATOMIC_INIT(1); +static int spinlock_count = 0; +static int spinlock_cpu = 0; +/* + * Note we use nested spin locks to account for the case where a break + * point is encountered when calling a function by user direction from + * kgdb. Also there is the memory exception recursion to account for. + * Well, yes, but this lets other cpus thru too. Lets add a + * cpu id to the lock. + */ +#define KGDB_SPIN_LOCK(x) if( spinlock_count == 0 || \ + spinlock_cpu != smp_processor_id()){\ + atomic_inc(&spinlock_waiters); \ + while (! spin_trylock(x)) {\ + in_kgdb(®s);\ + }\ + atomic_dec(&spinlock_waiters); \ + spinlock_count = 1; \ + spinlock_cpu = smp_processor_id(); \ + }else{ \ + spinlock_count++; \ + } +#define KGDB_SPIN_UNLOCK(x) if( --spinlock_count == 0) spin_unlock(x) +#else +unsigned kgdb_spinlock = 0; +#define KGDB_SPIN_LOCK(x) --*x +#define KGDB_SPIN_UNLOCK(x) ++*x +#endif + +int +hex(char ch) +{ + if ((ch >= 'a') && (ch <= 'f')) + return (ch - 'a' + 10); + if ((ch >= '0') && (ch <= '9')) + return (ch - '0'); + if ((ch >= 'A') && (ch <= 'F')) + return (ch - 'A' + 10); + return (-1); +} + +/* scan for the sequence $# */ +void +getpacket(char *buffer) +{ + unsigned char checksum; + unsigned char xmitcsum; + int i; + int count; + char ch; + + do { + /* wait around for the start character, ignore all other characters */ + while ((ch = (getDebugChar() & 0x7f)) != '$') ; + checksum = 0; + xmitcsum = -1; + + count = 0; + + /* now, read until a # or end of buffer is found */ + while (count < BUFMAX) { + ch = getDebugChar() & 0x7f; + if (ch == '#') + break; + checksum = checksum + ch; + buffer[count] = ch; + count = count + 1; + } + buffer[count] = 0; + + if (ch == '#') { + xmitcsum = hex(getDebugChar() & 0x7f) << 4; + xmitcsum += hex(getDebugChar() & 0x7f); + if ((remote_debug) && (checksum != xmitcsum)) { + printk + ("bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n", + checksum, xmitcsum, buffer); + } + + if (checksum != xmitcsum) + putDebugChar('-'); /* failed checksum */ + else { + putDebugChar('+'); /* successful transfer */ + /* if a sequence char is present, reply the sequence ID */ + if (buffer[2] == ':') { + putDebugChar(buffer[0]); + putDebugChar(buffer[1]); + /* remove sequence chars from buffer */ + count = strlen(buffer); + for (i = 3; i <= count; i++) + buffer[i - 3] = buffer[i]; + } + } + } + } while (checksum != xmitcsum); + + if (remote_debug) + printk("R:%s\n", buffer); + flushDebugChar(); +} + +/* send the packet in buffer. */ + +void +putpacket(char *buffer) +{ + unsigned char checksum; + int count; + char ch; + + /* $#. */ + + if (!kgdboe) { + do { + if (remote_debug) + printk("T:%s\n", buffer); + putDebugChar('$'); + checksum = 0; + count = 0; + + while ((ch = buffer[count])) { + putDebugChar(ch); + checksum += ch; + count += 1; + } + + putDebugChar('#'); + putDebugChar(hexchars[checksum >> 4]); + putDebugChar(hexchars[checksum % 16]); + flushDebugChar(); + + } while ((getDebugChar() & 0x7f) != '+'); + } else { + /* + * For udp, we can not transfer too much bytes once. + * We only transfer MAX_SEND_COUNT size bytes each time + */ + +#define MAX_SEND_COUNT 30 + + int send_count = 0, i = 0; + char send_buf[MAX_SEND_COUNT]; + + do { + if (remote_debug) + printk("T:%s\n", buffer); + putDebugChar('$'); + checksum = 0; + count = 0; + send_count = 0; + while ((ch = buffer[count])) { + if (send_count >= MAX_SEND_COUNT) { + for(i = 0; i < MAX_SEND_COUNT; i++) { + putDebugChar(send_buf[i]); + } + flushDebugChar(); + send_count = 0; + } else { + send_buf[send_count] = ch; + checksum += ch; + count ++; + send_count++; + } + } + for(i = 0; i < send_count; i++) + putDebugChar(send_buf[i]); + putDebugChar('#'); + putDebugChar(hexchars[checksum >> 4]); + putDebugChar(hexchars[checksum % 16]); + flushDebugChar(); + } while ((getDebugChar() & 0x7f) != '+'); + } +} + +static char remcomInBuffer[BUFMAX]; +static char remcomOutBuffer[BUFMAX]; +static short error; + +void +debug_error(char *format, char *parm) +{ + if (remote_debug) + printk(format, parm); +} + +static void +print_regs(struct pt_regs *regs) +{ + printk("EAX=%08lx ", regs->eax); + printk("EBX=%08lx ", regs->ebx); + printk("ECX=%08lx ", regs->ecx); + printk("EDX=%08lx ", regs->edx); + printk("\n"); + printk("ESI=%08lx ", regs->esi); + printk("EDI=%08lx ", regs->edi); + printk("EBP=%08lx ", regs->ebp); + printk("ESP=%08lx ", (long) ®s->esp); + printk("\n"); + printk(" DS=%08x ", regs->xds); + printk(" ES=%08x ", regs->xes); + printk(" SS=%08x ", __KERNEL_DS); + printk(" FL=%08lx ", regs->eflags); + printk("\n"); + printk(" CS=%08x ", regs->xcs); + printk(" IP=%08lx ", regs->eip); +#if 0 + printk(" FS=%08x ", regs->fs); + printk(" GS=%08x ", regs->gs); +#endif + printk("\n"); + +} /* print_regs */ + +#define NEW_esp fn_call_lookaside[trap_cpu].esp + +static void +regs_to_gdb_regs(int *gdb_regs, struct pt_regs *regs) +{ + gdb_regs[_EAX] = regs->eax; + gdb_regs[_EBX] = regs->ebx; + gdb_regs[_ECX] = regs->ecx; + gdb_regs[_EDX] = regs->edx; + gdb_regs[_ESI] = regs->esi; + gdb_regs[_EDI] = regs->edi; + gdb_regs[_EBP] = regs->ebp; + gdb_regs[_DS] = regs->xds; + gdb_regs[_ES] = regs->xes; + gdb_regs[_PS] = regs->eflags; + gdb_regs[_CS] = regs->xcs; + gdb_regs[_PC] = regs->eip; + /* Note, as we are a debugging the kernel, we will always + * trap in kernel code, this means no priviledge change, + * and so the pt_regs structure is not completely valid. In a non + * privilege change trap, only EFLAGS, CS and EIP are put on the stack, + * SS and ESP are not stacked, this means that the last 2 elements of + * pt_regs is not valid (they would normally refer to the user stack) + * also, using regs+1 is no good because you end up will a value that is + * 2 longs (8) too high. This used to cause stepping over functions + * to fail, so my fix is to use the address of regs->esp, which + * should point at the end of the stack frame. Note I have ignored + * completely exceptions that cause an error code to be stacked, such + * as double fault. Stuart Hughes, Zentropix. + * original code: gdb_regs[_ESP] = (int) (regs + 1) ; + + * this is now done on entry and moved to OLD_esp (as well as NEW_esp). + */ + gdb_regs[_ESP] = NEW_esp; + gdb_regs[_SS] = __KERNEL_DS; + gdb_regs[_FS] = 0xFFFF; + gdb_regs[_GS] = 0xFFFF; +} /* regs_to_gdb_regs */ + +static void +gdb_regs_to_regs(int *gdb_regs, struct pt_regs *regs) +{ + regs->eax = gdb_regs[_EAX]; + regs->ebx = gdb_regs[_EBX]; + regs->ecx = gdb_regs[_ECX]; + regs->edx = gdb_regs[_EDX]; + regs->esi = gdb_regs[_ESI]; + regs->edi = gdb_regs[_EDI]; + regs->ebp = gdb_regs[_EBP]; + regs->xds = gdb_regs[_DS]; + regs->xes = gdb_regs[_ES]; + regs->eflags = gdb_regs[_PS]; + regs->xcs = gdb_regs[_CS]; + regs->eip = gdb_regs[_PC]; + NEW_esp = gdb_regs[_ESP]; /* keep the value */ +#if 0 /* can't change these */ + regs->esp = gdb_regs[_ESP]; + regs->xss = gdb_regs[_SS]; + regs->fs = gdb_regs[_FS]; + regs->gs = gdb_regs[_GS]; +#endif + +} /* gdb_regs_to_regs */ + +int thread_list = 0; + +void +get_gdb_regs(struct task_struct *p, struct pt_regs *regs, int *gdb_regs) +{ + unsigned long stack_page; + int count = 0; + IF_SMP(int i); + if (!p || p == current) { + regs_to_gdb_regs(gdb_regs, regs); + return; + } +#ifdef CONFIG_SMP + for (i = 0; i < MAX_NO_CPUS; i++) { + if (p == kgdb_info.cpus_waiting[i].task) { + regs_to_gdb_regs(gdb_regs, + kgdb_info.cpus_waiting[i].regs); + gdb_regs[_ESP] = + (int) &kgdb_info.cpus_waiting[i].regs->esp; + + return; + } + } +#endif + memset(gdb_regs, 0, NUMREGBYTES); + gdb_regs[_ESP] = p->thread.esp; + gdb_regs[_PC] = p->thread.eip; + gdb_regs[_EBP] = *(int *) gdb_regs[_ESP]; + gdb_regs[_EDI] = *(int *) (gdb_regs[_ESP] + 4); + gdb_regs[_ESI] = *(int *) (gdb_regs[_ESP] + 8); + +/* + * This code is to give a more informative notion of where a process + * is waiting. It is used only when the user asks for a thread info + * list. If he then switches to the thread, s/he will find the task + * is in schedule, but a back trace should show the same info we come + * up with. This code was shamelessly purloined from process.c. It was + * then enhanced to provide more registers than simply the program + * counter. + */ + + if (!thread_list) { + return; + } + + if (p->state == TASK_RUNNING) + return; + stack_page = (unsigned long) p->thread_info; + if (gdb_regs[_ESP] < stack_page || gdb_regs[_ESP] > + THREAD_SIZE - sizeof(long) + stack_page) + return; + /* include/asm-i386/system.h:switch_to() pushes ebp last. */ + do { + if (gdb_regs[_EBP] < stack_page || + gdb_regs[_EBP] > THREAD_SIZE - 2*sizeof(long) + stack_page) + return; + gdb_regs[_PC] = *(unsigned long *) (gdb_regs[_EBP] + 4); + gdb_regs[_ESP] = gdb_regs[_EBP] + 8; + gdb_regs[_EBP] = *(unsigned long *) gdb_regs[_EBP]; + if (!in_sched_functions(gdb_regs[_PC])) + return; + } while (count++ < 16); + return; +} + +/* Indicate to caller of mem2hex or hex2mem that there has been an + error. */ +static volatile int mem_err = 0; +static volatile int mem_err_expected = 0; +static volatile int mem_err_cnt = 0; +static int garbage_loc = -1; + +int +get_char(char *addr) +{ + return *addr; +} + +void +set_char(char *addr, int val, int may_fault) +{ + /* + * This code traps references to the area mapped to the kernel + * stack as given by the regs and, instead, stores to the + * fn_call_lookaside[cpu].array + */ + if (may_fault && + (unsigned int) addr < OLD_esp && + ((unsigned int) addr > (OLD_esp - (unsigned int) LOOKASIDE_SIZE))) { + addr = (char *) END_OF_LOOKASIDE - ((char *) OLD_esp - addr); + } + *addr = val; +} + +/* convert the memory pointed to by mem into hex, placing result in buf */ +/* return a pointer to the last char put in buf (null) */ +/* If MAY_FAULT is non-zero, then we should set mem_err in response to + a fault; if zero treat a fault like any other fault in the stub. */ +char * +mem2hex(char *mem, char *buf, int count, int may_fault) +{ + int i; + unsigned char ch; + + if (may_fault) { + mem_err_expected = 1; + mem_err = 0; + } + for (i = 0; i < count; i++) { + /* printk("%lx = ", mem) ; */ + + ch = get_char(mem++); + + /* printk("%02x\n", ch & 0xFF) ; */ + if (may_fault && mem_err) { + if (remote_debug) + printk("Mem fault fetching from addr %lx\n", + (long) (mem - 1)); + *buf = 0; /* truncate buffer */ + return (buf); + } + *buf++ = hexchars[ch >> 4]; + *buf++ = hexchars[ch % 16]; + } + *buf = 0; + if (may_fault) + mem_err_expected = 0; + return (buf); +} + +/* convert the hex array pointed to by buf into binary to be placed in mem */ +/* return a pointer to the character AFTER the last byte written */ +/* NOTE: We use the may fault flag to also indicate if the write is to + * the registers (0) or "other" memory (!=0) + */ +char * +hex2mem(char *buf, char *mem, int count, int may_fault) +{ + int i; + unsigned char ch; + + if (may_fault) { + mem_err_expected = 1; + mem_err = 0; + } + for (i = 0; i < count; i++) { + ch = hex(*buf++) << 4; + ch = ch + hex(*buf++); + set_char(mem++, ch, may_fault); + + if (may_fault && mem_err) { + if (remote_debug) + printk("Mem fault storing to addr %lx\n", + (long) (mem - 1)); + return (mem); + } + } + if (may_fault) + mem_err_expected = 0; + return (mem); +} + +/**********************************************/ +/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */ +/* RETURN NUMBER OF CHARS PROCESSED */ +/**********************************************/ +int +hexToInt(char **ptr, int *intValue) +{ + int numChars = 0; + int hexValue; + + *intValue = 0; + + while (**ptr) { + hexValue = hex(**ptr); + if (hexValue >= 0) { + *intValue = (*intValue << 4) | hexValue; + numChars++; + } else + break; + + (*ptr)++; + } + + return (numChars); +} + +#define stubhex(h) hex(h) +#ifdef old_thread_list + +static int +stub_unpack_int(char *buff, int fieldlength) +{ + int nibble; + int retval = 0; + + while (fieldlength) { + nibble = stubhex(*buff++); + retval |= nibble; + fieldlength--; + if (fieldlength) + retval = retval << 4; + } + return retval; +} +#endif +static char * +pack_hex_byte(char *pkt, int byte) +{ + *pkt++ = hexchars[(byte >> 4) & 0xf]; + *pkt++ = hexchars[(byte & 0xf)]; + return pkt; +} + +#define BUF_THREAD_ID_SIZE 16 + +static char * +pack_threadid(char *pkt, threadref * id) +{ + char *limit; + unsigned char *altid; + + altid = (unsigned char *) id; + limit = pkt + BUF_THREAD_ID_SIZE; + while (pkt < limit) + pkt = pack_hex_byte(pkt, *altid++); + return pkt; +} + +#ifdef old_thread_list +static char * +unpack_byte(char *buf, int *value) +{ + *value = stub_unpack_int(buf, 2); + return buf + 2; +} + +static char * +unpack_threadid(char *inbuf, threadref * id) +{ + char *altref; + char *limit = inbuf + BUF_THREAD_ID_SIZE; + int x, y; + + altref = (char *) id; + + while (inbuf < limit) { + x = stubhex(*inbuf++); + y = stubhex(*inbuf++); + *altref++ = (x << 4) | y; + } + return inbuf; +} +#endif +void +int_to_threadref(threadref * id, int value) +{ + unsigned char *scan; + + scan = (unsigned char *) id; + { + int i = 4; + while (i--) + *scan++ = 0; + } + *scan++ = (value >> 24) & 0xff; + *scan++ = (value >> 16) & 0xff; + *scan++ = (value >> 8) & 0xff; + *scan++ = (value & 0xff); +} +int +int_to_hex_v(unsigned char * id, int value) +{ + unsigned char *start = id; + int shift; + int ch; + + for (shift = 28; shift >= 0; shift -= 4) { + if ((ch = (value >> shift) & 0xf) || (id != start)) { + *id = hexchars[ch]; + id++; + } + } + if (id == start) + *id++ = '0'; + return id - start; +} +#ifdef old_thread_list + +static int +threadref_to_int(threadref * ref) +{ + int i, value = 0; + unsigned char *scan; + + scan = (char *) ref; + scan += 4; + i = 4; + while (i-- > 0) + value = (value << 8) | ((*scan++) & 0xff); + return value; +} +#endif +static int +cmp_str(char *s1, char *s2, int count) +{ + while (count--) { + if (*s1++ != *s2++) + return 0; + } + return 1; +} + +#if 1 /* this is a hold over from 2.4 where O(1) was "sometimes" */ +extern struct task_struct *kgdb_get_idle(int cpu); +#define idle_task(cpu) kgdb_get_idle(cpu) +#else +#define idle_task(cpu) init_tasks[cpu] +#endif + +extern int kgdb_pid_init_done; + +struct task_struct * +getthread(int pid) +{ + struct task_struct *thread; + if (pid >= PID_MAX && pid <= (PID_MAX + MAX_NO_CPUS)) { + + return idle_task(pid - PID_MAX); + } else { + /* + * find_task_by_pid is relatively safe all the time + * Other pid functions require lock downs which imply + * that we may be interrupting them (as we get here + * in the middle of most any lock down). + * Still we don't want to call until the table exists! + */ + if (kgdb_pid_init_done){ + thread = find_task_by_pid(pid); + if (thread) { + return thread; + } + } + } + return NULL; +} +/* *INDENT-OFF* */ +struct hw_breakpoint { + unsigned enabled; + unsigned type; + unsigned len; + unsigned addr; +} breakinfo[4] = { {enabled:0}, + {enabled:0}, + {enabled:0}, + {enabled:0}}; +/* *INDENT-ON* */ +unsigned hw_breakpoint_status; +void +correct_hw_break(void) +{ + int breakno; + int correctit; + int breakbit; + unsigned dr7; + + asm volatile ("movl %%db7, %0\n":"=r" (dr7) + :); + /* *INDENT-OFF* */ + do { + unsigned addr0, addr1, addr2, addr3; + asm volatile ("movl %%db0, %0\n" + "movl %%db1, %1\n" + "movl %%db2, %2\n" + "movl %%db3, %3\n" + :"=r" (addr0), "=r"(addr1), + "=r"(addr2), "=r"(addr3) + :); + } while (0); + /* *INDENT-ON* */ + correctit = 0; + for (breakno = 0; breakno < 3; breakno++) { + breakbit = 2 << (breakno << 1); + if (!(dr7 & breakbit) && breakinfo[breakno].enabled) { + correctit = 1; + dr7 |= breakbit; + dr7 &= ~(0xf0000 << (breakno << 2)); + dr7 |= (((breakinfo[breakno].len << 2) | + breakinfo[breakno].type) << 16) << + (breakno << 2); + switch (breakno) { + case 0: + asm volatile ("movl %0, %%dr0\n"::"r" + (breakinfo[breakno].addr)); + break; + + case 1: + asm volatile ("movl %0, %%dr1\n"::"r" + (breakinfo[breakno].addr)); + break; + + case 2: + asm volatile ("movl %0, %%dr2\n"::"r" + (breakinfo[breakno].addr)); + break; + + case 3: + asm volatile ("movl %0, %%dr3\n"::"r" + (breakinfo[breakno].addr)); + break; + } + } else if ((dr7 & breakbit) && !breakinfo[breakno].enabled) { + correctit = 1; + dr7 &= ~breakbit; + dr7 &= ~(0xf0000 << (breakno << 2)); + } + } + if (correctit) { + asm volatile ("movl %0, %%db7\n"::"r" (dr7)); + } +} + +int +remove_hw_break(unsigned breakno) +{ + if (!breakinfo[breakno].enabled) { + return -1; + } + breakinfo[breakno].enabled = 0; + return 0; +} + +int +set_hw_break(unsigned breakno, unsigned type, unsigned len, unsigned addr) +{ + if (breakinfo[breakno].enabled) { + return -1; + } + breakinfo[breakno].enabled = 1; + breakinfo[breakno].type = type; + breakinfo[breakno].len = len; + breakinfo[breakno].addr = addr; + return 0; +} + +#ifdef CONFIG_SMP +static int in_kgdb_console = 0; + +int +in_kgdb(struct pt_regs *regs) +{ + unsigned flags; + int cpu = smp_processor_id(); + in_kgdb_called = 1; + if (!spin_is_locked(&kgdb_spinlock)) { + if (in_kgdb_here_log[cpu] || /* we are holding this cpu */ + in_kgdb_console) { /* or we are doing slow i/o */ + return 1; + } + return 0; + } + + /* As I see it the only reason not to let all cpus spin on + * the same spin_lock is to allow selected ones to proceed. + * This would be a good thing, so we leave it this way. + * Maybe someday.... Done ! + + * in_kgdb() is called from an NMI so we don't pretend + * to have any resources, like printk() for example. + */ + + kgdb_local_irq_save(flags); /* only local here, to avoid hanging */ + /* + * log arival of this cpu + * The NMI keeps on ticking. Protect against recurring more + * than once, and ignor the cpu that has the kgdb lock + */ + in_kgdb_entry_log[cpu]++; + in_kgdb_here_log[cpu] = regs; + if (cpu == spinlock_cpu || waiting_cpus[cpu].task) + goto exit_in_kgdb; + + /* + * For protection of the initilization of the spin locks by kgdb + * it locks the kgdb spinlock before it gets the wait locks set + * up. We wait here for the wait lock to be taken. If the + * kgdb lock goes away first?? Well, it could be a slow exit + * sequence where the wait lock is removed prior to the kgdb lock + * so if kgdb gets unlocked, we just exit. + */ + + while (spin_is_locked(&kgdb_spinlock) && + !spin_is_locked(waitlocks + cpu)) ; + if (!spin_is_locked(&kgdb_spinlock)) + goto exit_in_kgdb; + + waiting_cpus[cpu].task = current; + waiting_cpus[cpu].pid = (current->pid) ? : (PID_MAX + cpu); + waiting_cpus[cpu].regs = regs; + + spin_unlock_wait(waitlocks + cpu); + + /* + * log departure of this cpu + */ + waiting_cpus[cpu].task = 0; + waiting_cpus[cpu].pid = 0; + waiting_cpus[cpu].regs = 0; + correct_hw_break(); + exit_in_kgdb: + in_kgdb_here_log[cpu] = 0; + kgdb_local_irq_restore(flags); + return 1; + /* + spin_unlock(continuelocks + smp_processor_id()); + */ +} + +void +smp__in_kgdb(struct pt_regs regs) +{ + ack_APIC_irq(); + in_kgdb(®s); +} +#else +int +in_kgdb(struct pt_regs *regs) +{ + return (kgdb_spinlock); +} +#endif + +void +printexceptioninfo(int exceptionNo, int errorcode, char *buffer) +{ + unsigned dr6; + int i; + switch (exceptionNo) { + case 1: /* debug exception */ + break; + case 3: /* breakpoint */ + sprintf(buffer, "Software breakpoint"); + return; + default: + sprintf(buffer, "Details not available"); + return; + } + asm volatile ("movl %%db6, %0\n":"=r" (dr6) + :); + if (dr6 & 0x4000) { + sprintf(buffer, "Single step"); + return; + } + for (i = 0; i < 4; ++i) { + if (dr6 & (1 << i)) { + sprintf(buffer, "Hardware breakpoint %d", i); + return; + } + } + sprintf(buffer, "Unknown trap"); + return; +} + +/* + * This function does all command procesing for interfacing to gdb. + * + * NOTE: The INT nn instruction leaves the state of the interrupt + * enable flag UNCHANGED. That means that when this routine + * is entered via a breakpoint (INT 3) instruction from code + * that has interrupts enabled, then interrupts will STILL BE + * enabled when this routine is entered. The first thing that + * we do here is disable interrupts so as to prevent recursive + * entries and bothersome serial interrupts while we are + * trying to run the serial port in polled mode. + * + * For kernel version 2.1.xx the kgdb_cli() actually gets a spin lock so + * it is always necessary to do a restore_flags before returning + * so as to let go of that lock. + */ +int +kgdb_handle_exception(int exceptionVector, + int signo, int err_code, struct pt_regs *linux_regs) +{ + struct task_struct *usethread = NULL; + struct task_struct *thread_list_start = 0, *thread = NULL; + int addr, length; + int breakno, breaktype; + char *ptr; + int newPC; + threadref thref; + int threadid; + int thread_min = PID_MAX + MAX_NO_CPUS; +#ifdef old_thread_list + int maxthreads; +#endif + int nothreads; + unsigned long flags; + int gdb_regs[NUMREGBYTES / 4]; + int dr6; + IF_SMP(int entry_state = 0); /* 0, ok, 1, no nmi, 2 sync failed */ +#define NO_NMI 1 +#define NO_SYNC 2 +#define regs (*linux_regs) +#define NUMREGS NUMREGBYTES/4 + /* + * If the entry is not from the kernel then return to the Linux + * trap handler and let it process the interrupt normally. + */ + if ((linux_regs->eflags & VM_MASK) || (3 & linux_regs->xcs)) { + printk("ignoring non-kernel exception\n"); + print_regs(®s); + return (0); + } + /* + * If we're using eth mode, set the 'mode' in the netdevice. + */ + + if (kgdboe) + netpoll_set_trap(1); + + kgdb_local_irq_save(flags); + + /* Get kgdb spinlock */ + + KGDB_SPIN_LOCK(&kgdb_spinlock); + rdtscll(kgdb_info.entry_tsc); + /* + * We depend on this spinlock and the NMI watch dog to control the + * other cpus. They will arrive at "in_kgdb()" as a result of the + * NMI and will wait there for the following spin locks to be + * released. + */ +#ifdef CONFIG_SMP + +#if 0 + if (cpu_callout_map & ~MAX_CPU_MASK) { + printk("kgdb : too many cpus, possibly not mapped" + " in contiguous space, change MAX_NO_CPUS" + " in kgdb_stub and make new kernel.\n" + " cpu_callout_map is %lx\n", cpu_callout_map); + goto exit_just_unlock; + } +#endif + if (spinlock_count == 1) { + int time = 0, end_time, dum = 0; + int i; + int cpu_logged_in[MAX_NO_CPUS] = {[0 ... MAX_NO_CPUS - 1] = (0) + }; + if (remote_debug) { + printk("kgdb : cpu %d entry, syncing others\n", + smp_processor_id()); + } + for (i = 0; i < MAX_NO_CPUS; i++) { + /* + * Use trylock as we may already hold the lock if + * we are holding the cpu. Net result is all + * locked. + */ + spin_trylock(&waitlocks[i]); + } + for (i = 0; i < MAX_NO_CPUS; i++) + cpu_logged_in[i] = 0; + /* + * Wait for their arrival. We know the watch dog is active if + * in_kgdb() has ever been called, as it is always called on a + * watchdog tick. + */ + rdtsc(dum, time); + end_time = time + 2; /* Note: we use the High order bits! */ + i = 1; + if (num_online_cpus() > 1) { + int me_in_kgdb = in_kgdb_entry_log[smp_processor_id()]; + smp_send_nmi_allbutself(); + + while (i < num_online_cpus() && time != end_time) { + int j; + for (j = 0; j < MAX_NO_CPUS; j++) { + if (waiting_cpus[j].task && + waiting_cpus[j].task != NOCPU && + !cpu_logged_in[j]) { + i++; + cpu_logged_in[j] = 1; + if (remote_debug) { + printk + ("kgdb : cpu %d arrived at kgdb\n", + j); + } + break; + } else if (!waiting_cpus[j].task && + !cpu_online(j)) { + waiting_cpus[j].task = NOCPU; + cpu_logged_in[j] = 1; + waiting_cpus[j].hold = 1; + break; + } + if (!waiting_cpus[j].task && + in_kgdb_here_log[j]) { + + int wait = 100000; + while (wait--) ; + if (!waiting_cpus[j].task && + in_kgdb_here_log[j]) { + printk + ("kgdb : cpu %d stall" + " in in_kgdb\n", + j); + i++; + cpu_logged_in[j] = 1; + waiting_cpus[j].task = + (struct task_struct + *) 1; + } + } + } + + if (in_kgdb_entry_log[smp_processor_id()] > + (me_in_kgdb + 10)) { + break; + } + + rdtsc(dum, time); + } + if (i < num_online_cpus()) { + printk + ("kgdb : time out, proceeding without sync\n"); +#if 0 + printk("kgdb : Waiting_cpus: 0 = %d, 1 = %d\n", + waiting_cpus[0].task != 0, + waiting_cpus[1].task != 0); + printk("kgdb : Cpu_logged in: 0 = %d, 1 = %d\n", + cpu_logged_in[0], cpu_logged_in[1]); + printk + ("kgdb : in_kgdb_here_log in: 0 = %d, 1 = %d\n", + in_kgdb_here_log[0] != 0, + in_kgdb_here_log[1] != 0); +#endif + entry_state = NO_SYNC; + } else { +#if 0 + int ent = + in_kgdb_entry_log[smp_processor_id()] - + me_in_kgdb; + printk("kgdb : sync after %d entries\n", ent); +#endif + } + } else { + if (remote_debug) { + printk + ("kgdb : %d cpus, but watchdog not active\n" + "proceeding without locking down other cpus\n", + num_online_cpus()); + entry_state = NO_NMI; + } + } + } +#endif + + if (remote_debug) { + unsigned long *lp = (unsigned long *) &linux_regs; + + printk("handle_exception(exceptionVector=%d, " + "signo=%d, err_code=%d, linux_regs=%p)\n", + exceptionVector, signo, err_code, linux_regs); + if (debug_regs) { + print_regs(®s); + printk("Stk: %8lx %8lx %8lx %8lx" + " %8lx %8lx %8lx %8lx\n", + lp[0], lp[1], lp[2], lp[3], + lp[4], lp[5], lp[6], lp[7]); + printk(" %8lx %8lx %8lx %8lx" + " %8lx %8lx %8lx %8lx\n", + lp[8], lp[9], lp[10], lp[11], + lp[12], lp[13], lp[14], lp[15]); + printk(" %8lx %8lx %8lx %8lx " + "%8lx %8lx %8lx %8lx\n", + lp[16], lp[17], lp[18], lp[19], + lp[20], lp[21], lp[22], lp[23]); + printk(" %8lx %8lx %8lx %8lx " + "%8lx %8lx %8lx %8lx\n", + lp[24], lp[25], lp[26], lp[27], + lp[28], lp[29], lp[30], lp[31]); + } + } + + /* Disable hardware debugging while we are in kgdb */ + /* Get the debug register status register */ +/* *INDENT-OFF* */ + __asm__("movl %0,%%db7" + : /* no output */ + :"r"(0)); + + asm volatile ("movl %%db6, %0\n" + :"=r" (hw_breakpoint_status) + :); + +/* *INDENT-ON* */ + switch (exceptionVector) { + case 0: /* divide error */ + case 1: /* debug exception */ + case 2: /* NMI */ + case 3: /* breakpoint */ + case 4: /* overflow */ + case 5: /* bounds check */ + case 6: /* invalid opcode */ + case 7: /* device not available */ + case 8: /* double fault (errcode) */ + case 10: /* invalid TSS (errcode) */ + case 12: /* stack fault (errcode) */ + case 16: /* floating point error */ + case 17: /* alignment check (errcode) */ + default: /* any undocumented */ + break; + case 11: /* segment not present (errcode) */ + case 13: /* general protection (errcode) */ + case 14: /* page fault (special errcode) */ + case 19: /* cache flush denied */ + if (mem_err_expected) { + /* + * This fault occured because of the + * get_char or set_char routines. These + * two routines use either eax of edx to + * indirectly reference the location in + * memory that they are working with. + * For a page fault, when we return the + * instruction will be retried, so we + * have to make sure that these + * registers point to valid memory. + */ + mem_err = 1; /* set mem error flag */ + mem_err_expected = 0; + mem_err_cnt++; /* helps in debugging */ + /* make valid address */ + regs.eax = (long) &garbage_loc; + /* make valid address */ + regs.edx = (long) &garbage_loc; + if (remote_debug) + printk("Return after memory error: " + "mem_err_cnt=%d\n", mem_err_cnt); + if (debug_regs) + print_regs(®s); + goto exit_kgdb; + } + break; + } + if (remote_debug) + printk("kgdb : entered kgdb on cpu %d\n", smp_processor_id()); + + gdb_i386vector = exceptionVector; + gdb_i386errcode = err_code; + kgdb_info.called_from = __builtin_return_address(0); +#ifdef CONFIG_SMP + /* + * OK, we can now communicate, lets tell gdb about the sync. + * but only if we had a problem. + */ + switch (entry_state) { + case NO_NMI: + to_gdb("NMI not active, other cpus not stopped\n"); + break; + case NO_SYNC: + to_gdb("Some cpus not stopped, see 'kgdb_info' for details\n"); + default:; + } + +#endif +/* + * Set up the gdb function call area. + */ + trap_cpu = smp_processor_id(); + OLD_esp = NEW_esp = (int) (&linux_regs->esp); + + IF_SMP(once_again:) + /* reply to host that an exception has occurred */ + remcomOutBuffer[0] = 'S'; + remcomOutBuffer[1] = hexchars[signo >> 4]; + remcomOutBuffer[2] = hexchars[signo % 16]; + remcomOutBuffer[3] = 0; + + putpacket(remcomOutBuffer); + + while (1 == 1) { + error = 0; + remcomOutBuffer[0] = 0; + getpacket(remcomInBuffer); + switch (remcomInBuffer[0]) { + case '?': + remcomOutBuffer[0] = 'S'; + remcomOutBuffer[1] = hexchars[signo >> 4]; + remcomOutBuffer[2] = hexchars[signo % 16]; + remcomOutBuffer[3] = 0; + break; + case 'd': + remote_debug = !(remote_debug); /* toggle debug flag */ + printk("Remote debug %s\n", + remote_debug ? "on" : "off"); + break; + case 'g': /* return the value of the CPU registers */ + get_gdb_regs(usethread, ®s, gdb_regs); + mem2hex((char *) gdb_regs, + remcomOutBuffer, NUMREGBYTES, 0); + break; + case 'G': /* set the value of the CPU registers - return OK */ + hex2mem(&remcomInBuffer[1], + (char *) gdb_regs, NUMREGBYTES, 0); + if (!usethread || usethread == current) { + gdb_regs_to_regs(gdb_regs, ®s); + strcpy(remcomOutBuffer, "OK"); + } else { + strcpy(remcomOutBuffer, "E00"); + } + break; + + case 'P':{ /* set the value of a single CPU register - + return OK */ + /* + * For some reason, gdb wants to talk about psudo + * registers (greater than 15). These may have + * meaning for ptrace, but for us it is safe to + * ignor them. We do this by dumping them into + * _GS which we also ignor, but do have memory for. + */ + int regno; + + ptr = &remcomInBuffer[1]; + regs_to_gdb_regs(gdb_regs, ®s); + if ((!usethread || usethread == current) && + hexToInt(&ptr, ®no) && + *ptr++ == '=' && (regno >= 0)) { + regno = + (regno >= NUMREGS ? _GS : regno); + hex2mem(ptr, (char *) &gdb_regs[regno], + 4, 0); + gdb_regs_to_regs(gdb_regs, ®s); + strcpy(remcomOutBuffer, "OK"); + break; + } + strcpy(remcomOutBuffer, "E01"); + break; + } + + /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ + case 'm': + /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */ + ptr = &remcomInBuffer[1]; + if (hexToInt(&ptr, &addr) && + (*(ptr++) == ',') && (hexToInt(&ptr, &length))) { + ptr = 0; + /* + * hex doubles the byte count + */ + if (length > (BUFMAX / 2)) + length = BUFMAX / 2; + mem2hex((char *) addr, + remcomOutBuffer, length, 1); + if (mem_err) { + strcpy(remcomOutBuffer, "E03"); + debug_error("memory fault\n", NULL); + } + } + + if (ptr) { + strcpy(remcomOutBuffer, "E01"); + debug_error + ("malformed read memory command: %s\n", + remcomInBuffer); + } + break; + + /* MAA..AA,LLLL: + Write LLLL bytes at address AA.AA return OK */ + case 'M': + /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */ + ptr = &remcomInBuffer[1]; + if (hexToInt(&ptr, &addr) && + (*(ptr++) == ',') && + (hexToInt(&ptr, &length)) && (*(ptr++) == ':')) { + hex2mem(ptr, (char *) addr, length, 1); + + if (mem_err) { + strcpy(remcomOutBuffer, "E03"); + debug_error("memory fault\n", NULL); + } else { + strcpy(remcomOutBuffer, "OK"); + } + + ptr = 0; + } + if (ptr) { + strcpy(remcomOutBuffer, "E02"); + debug_error + ("malformed write memory command: %s\n", + remcomInBuffer); + } + break; + case 'S': + remcomInBuffer[0] = 's'; + case 'C': + /* Csig;AA..AA where ;AA..AA is optional + * continue with signal + * Since signals are meaning less to us, delete that + * part and then fall into the 'c' code. + */ + ptr = &remcomInBuffer[1]; + length = 2; + while (*ptr && *ptr != ';') { + length++; + ptr++; + } + if (*ptr) { + do { + ptr++; + *(ptr - length++) = *ptr; + } while (*ptr); + } else { + remcomInBuffer[1] = 0; + } + + /* cAA..AA Continue at address AA..AA(optional) */ + /* sAA..AA Step one instruction from AA..AA(optional) */ + /* D detach, reply OK and then continue */ + case 'c': + case 's': + case 'D': + + /* try to read optional parameter, + pc unchanged if no parm */ + ptr = &remcomInBuffer[1]; + if (hexToInt(&ptr, &addr)) { + if (remote_debug) + printk("Changing EIP to 0x%x\n", addr); + + regs.eip = addr; + } + + newPC = regs.eip; + + /* clear the trace bit */ + regs.eflags &= 0xfffffeff; + + /* set the trace bit if we're stepping */ + if (remcomInBuffer[0] == 's') + regs.eflags |= 0x100; + + /* detach is a friendly version of continue. Note that + debugging is still enabled (e.g hit control C) + */ + if (remcomInBuffer[0] == 'D') { + strcpy(remcomOutBuffer, "OK"); + putpacket(remcomOutBuffer); + } + + if (remote_debug) { + printk("Resuming execution\n"); + print_regs(®s); + } + asm volatile ("movl %%db6, %0\n":"=r" (dr6) + :); + if (!(dr6 & 0x4000)) { + for (breakno = 0; breakno < 4; ++breakno) { + if (dr6 & (1 << breakno) && + (breakinfo[breakno].type == 0)) { + /* Set restore flag */ + regs.eflags |= 0x10000; + break; + } + } + } + + if (kgdboe) + netpoll_set_trap(0); + + correct_hw_break(); + asm volatile ("movl %0, %%db6\n"::"r" (0)); + goto exit_kgdb; + + /* kill the program */ + case 'k': /* do nothing */ + break; + + /* query */ + case 'q': + nothreads = 0; + switch (remcomInBuffer[1]) { + case 'f': + threadid = 1; + thread_list = 2; + thread_list_start = (usethread ? : current); + case 's': + if (!cmp_str(&remcomInBuffer[2], + "ThreadInfo", 10)) + break; + + remcomOutBuffer[nothreads++] = 'm'; + for (; threadid < PID_MAX + MAX_NO_CPUS; + threadid++) { + thread = getthread(threadid); + if (thread) { + nothreads += int_to_hex_v( + &remcomOutBuffer[ + nothreads], + threadid); + if (thread_min > threadid) + thread_min = threadid; + remcomOutBuffer[ + nothreads] = ','; + nothreads++; + if (nothreads > BUFMAX - 10) + break; + } + } + if (remcomOutBuffer[nothreads - 1] == 'm') { + remcomOutBuffer[nothreads - 1] = 'l'; + } else { + nothreads--; + } + remcomOutBuffer[nothreads] = 0; + break; + +#ifdef old_thread_list /* Old thread info request */ + case 'L': + /* List threads */ + thread_list = 2; + thread_list_start = (usethread ? : current); + unpack_byte(remcomInBuffer + 3, &maxthreads); + unpack_threadid(remcomInBuffer + 5, &thref); + do { + int buf_thread_limit = + (BUFMAX - 22) / BUF_THREAD_ID_SIZE; + if (maxthreads > buf_thread_limit) { + maxthreads = buf_thread_limit; + } + } while (0); + remcomOutBuffer[0] = 'q'; + remcomOutBuffer[1] = 'M'; + remcomOutBuffer[4] = '0'; + pack_threadid(remcomOutBuffer + 5, &thref); + + threadid = threadref_to_int(&thref); + for (nothreads = 0; + nothreads < maxthreads && + threadid < PID_MAX + MAX_NO_CPUS; + threadid++) { + thread = getthread(threadid); + if (thread) { + int_to_threadref(&thref, + threadid); + pack_threadid(remcomOutBuffer + + 21 + + nothreads * 16, + &thref); + nothreads++; + if (thread_min > threadid) + thread_min = threadid; + } + } + + if (threadid == PID_MAX + MAX_NO_CPUS) { + remcomOutBuffer[4] = '1'; + } + pack_hex_byte(remcomOutBuffer + 2, nothreads); + remcomOutBuffer[21 + nothreads * 16] = '\0'; + break; +#endif + case 'C': + /* Current thread id */ + remcomOutBuffer[0] = 'Q'; + remcomOutBuffer[1] = 'C'; + threadid = current->pid; + if (!threadid) { + /* + * idle thread + */ + for (threadid = PID_MAX; + threadid < PID_MAX + MAX_NO_CPUS; + threadid++) { + if (current == + idle_task(threadid - + PID_MAX)) + break; + } + } + int_to_threadref(&thref, threadid); + pack_threadid(remcomOutBuffer + 2, &thref); + remcomOutBuffer[18] = '\0'; + break; + + case 'E': + /* Print exception info */ + printexceptioninfo(exceptionVector, + err_code, remcomOutBuffer); + break; + case 'T':{ + char * nptr; + /* Thread extra info */ + if (!cmp_str(&remcomInBuffer[2], + "hreadExtraInfo,", 15)) { + break; + } + ptr = &remcomInBuffer[17]; + hexToInt(&ptr, &threadid); + thread = getthread(threadid); + nptr = &thread->comm[0]; + length = 0; + ptr = &remcomOutBuffer[0]; + do { + length++; + ptr = pack_hex_byte(ptr, *nptr++); + } while (*nptr && length < 16); + /* + * would like that 16 to be the size of + * task_struct.comm but don't know the + * syntax.. + */ + *ptr = 0; + } + } + break; + + /* task related */ + case 'H': + switch (remcomInBuffer[1]) { + case 'g': + ptr = &remcomInBuffer[2]; + hexToInt(&ptr, &threadid); + thread = getthread(threadid); + if (!thread) { + remcomOutBuffer[0] = 'E'; + remcomOutBuffer[1] = '\0'; + break; + } + /* + * Just in case I forget what this is all about, + * the "thread info" command to gdb causes it + * to ask for a thread list. It then switches + * to each thread and asks for the registers. + * For this (and only this) usage, we want to + * fudge the registers of tasks not on the run + * list (i.e. waiting) to show the routine that + * called schedule. Also, gdb, is a minimalist + * in that if the current thread is the last + * it will not re-read the info when done. + * This means that in this case we must show + * the real registers. So here is how we do it: + * Each entry we keep track of the min + * thread in the list (the last that gdb will) + * get info for. We also keep track of the + * starting thread. + * "thread_list" is cleared when switching back + * to the min thread if it is was current, or + * if it was not current, thread_list is set + * to 1. When the switch to current comes, + * if thread_list is 1, clear it, else do + * nothing. + */ + usethread = thread; + if ((thread_list == 1) && + (thread == thread_list_start)) { + thread_list = 0; + } + if (thread_list && (threadid == thread_min)) { + if (thread == thread_list_start) { + thread_list = 0; + } else { + thread_list = 1; + } + } + /* follow through */ + case 'c': + remcomOutBuffer[0] = 'O'; + remcomOutBuffer[1] = 'K'; + remcomOutBuffer[2] = '\0'; + break; + } + break; + + /* Query thread status */ + case 'T': + ptr = &remcomInBuffer[1]; + hexToInt(&ptr, &threadid); + thread = getthread(threadid); + if (thread) { + remcomOutBuffer[0] = 'O'; + remcomOutBuffer[1] = 'K'; + remcomOutBuffer[2] = '\0'; + if (thread_min > threadid) + thread_min = threadid; + } else { + remcomOutBuffer[0] = 'E'; + remcomOutBuffer[1] = '\0'; + } + break; + + case 'Y': /* set up a hardware breakpoint */ + ptr = &remcomInBuffer[1]; + hexToInt(&ptr, &breakno); + ptr++; + hexToInt(&ptr, &breaktype); + ptr++; + hexToInt(&ptr, &length); + ptr++; + hexToInt(&ptr, &addr); + if (set_hw_break(breakno & 0x3, + breaktype & 0x3, + length & 0x3, addr) == 0) { + strcpy(remcomOutBuffer, "OK"); + } else { + strcpy(remcomOutBuffer, "ERROR"); + } + break; + + /* Remove hardware breakpoint */ + case 'y': + ptr = &remcomInBuffer[1]; + hexToInt(&ptr, &breakno); + if (remove_hw_break(breakno & 0x3) == 0) { + strcpy(remcomOutBuffer, "OK"); + } else { + strcpy(remcomOutBuffer, "ERROR"); + } + break; + + case 'r': /* reboot */ + strcpy(remcomOutBuffer, "OK"); + putpacket(remcomOutBuffer); + /*to_gdb("Rebooting\n"); */ + /* triplefault no return from here */ + { + static long no_idt[2]; + __asm__ __volatile__("lidt %0"::"m"(no_idt[0])); + BREAKPOINT; + } + + } /* switch */ + + /* reply to the request */ + putpacket(remcomOutBuffer); + } /* while(1==1) */ + /* + * reached by goto only. + */ + exit_kgdb: + /* + * Here is where we set up to trap a gdb function call. NEW_esp + * will be changed if we are trying to do this. We handle both + * adding and subtracting, thus allowing gdb to put grung on + * the stack which it removes later. + */ + if (NEW_esp != OLD_esp) { + int *ptr = END_OF_LOOKASIDE; + if (NEW_esp < OLD_esp) + ptr -= (OLD_esp - NEW_esp) / sizeof (int); + *--ptr = linux_regs->eflags; + *--ptr = linux_regs->xcs; + *--ptr = linux_regs->eip; + *--ptr = linux_regs->ecx; + *--ptr = linux_regs->ebx; + *--ptr = linux_regs->eax; + linux_regs->ecx = NEW_esp - (sizeof (int) * 6); + linux_regs->ebx = (unsigned int) END_OF_LOOKASIDE; + if (NEW_esp < OLD_esp) { + linux_regs->eip = (unsigned int) fn_call_stub; + } else { + linux_regs->eip = (unsigned int) fn_rtn_stub; + linux_regs->eax = NEW_esp; + } + linux_regs->eflags &= ~(IF_BIT | TF_BIT); + } +#ifdef CONFIG_SMP + /* + * Release gdb wait locks + * Sanity check time. Must have at least one cpu to run. Also single + * step must not be done if the current cpu is on hold. + */ + if (spinlock_count == 1) { + int ss_hold = (regs.eflags & 0x100) && kgdb_info.hold_on_sstep; + int cpu_avail = 0; + int i; + + for (i = 0; i < MAX_NO_CPUS; i++) { + if (!cpu_online(i)) + break; + if (!hold_cpu(i)) { + cpu_avail = 1; + } + } + /* + * Early in the bring up there will be NO cpus on line... + */ + if (!cpu_avail && !cpus_empty(cpu_online_map)) { + to_gdb("No cpus unblocked, see 'kgdb_info.hold_cpu'\n"); + goto once_again; + } + if (hold_cpu(smp_processor_id()) && (regs.eflags & 0x100)) { + to_gdb + ("Current cpu must be unblocked to single step\n"); + goto once_again; + } + if (!(ss_hold)) { + int i; + for (i = 0; i < MAX_NO_CPUS; i++) { + if (!hold_cpu(i)) { + spin_unlock(&waitlocks[i]); + } + } + } else { + spin_unlock(&waitlocks[smp_processor_id()]); + } + /* Release kgdb spinlock */ + KGDB_SPIN_UNLOCK(&kgdb_spinlock); + /* + * If this cpu is on hold, this is where we + * do it. Note, the NMI will pull us out of here, + * but will return as the above lock is not held. + * We will stay here till another cpu releases the lock for us. + */ + spin_unlock_wait(waitlocks + smp_processor_id()); + kgdb_local_irq_restore(flags); + return (0); + } +#if 0 +exit_just_unlock: +#endif +#endif + /* Release kgdb spinlock */ + KGDB_SPIN_UNLOCK(&kgdb_spinlock); + kgdb_local_irq_restore(flags); + return (0); +} + +/* this function is used to set up exception handlers for tracing and + * breakpoints. + * This function is not needed as the above line does all that is needed. + * We leave it for backward compatitability... + */ +void +set_debug_traps(void) +{ + /* + * linux_debug_hook is defined in traps.c. We store a pointer + * to our own exception handler into it. + + * But really folks, every hear of labeled common, an old Fortran + * concept. Lots of folks can reference it and it is define if + * anyone does. Only one can initialize it at link time. We do + * this with the hook. See the statement above. No need for any + * executable code and it is ready as soon as the kernel is + * loaded. Very desirable in kernel debugging. + + linux_debug_hook = handle_exception ; + */ + + /* In case GDB is started before us, ack any packets (presumably + "$?#xx") sitting there. + putDebugChar ('+'); + + initialized = 1; + */ +} + +/* This function will generate a breakpoint exception. It is used at the + beginning of a program to sync up with a debugger and can be used + otherwise as a quick means to stop program execution and "break" into + the debugger. */ +/* But really, just use the BREAKPOINT macro. We will handle the int stuff + */ + +#ifdef later +/* + * possibly we should not go thru the traps.c code at all? Someday. + */ +void +do_kgdb_int3(struct pt_regs *regs, long error_code) +{ + kgdb_handle_exception(3, 5, error_code, regs); + return; +} +#endif +#undef regs +#ifdef CONFIG_TRAP_BAD_SYSCALL_EXITS +asmlinkage void +bad_sys_call_exit(int stuff) +{ + struct pt_regs *regs = (struct pt_regs *) &stuff; + printk("Sys call %d return with %x preempt_count\n", + (int) regs->orig_eax, preempt_count()); +} +#endif +#ifdef CONFIG_STACK_OVERFLOW_TEST +#include +asmlinkage void +stack_overflow(void) +{ +#ifdef BREAKPOINT + BREAKPOINT; +#else + printk("Kernel stack overflow, looping forever\n"); +#endif + while (1) { + } +} +#endif + +#if defined(CONFIG_SMP) || defined(CONFIG_KGDB_CONSOLE) +char gdbconbuf[BUFMAX]; + +static void +kgdb_gdb_message(const char *s, unsigned count) +{ + int i; + int wcount; + char *bufptr; + /* + * This takes care of NMI while spining out chars to gdb + */ + IF_SMP(in_kgdb_console = 1); + gdbconbuf[0] = 'O'; + bufptr = gdbconbuf + 1; + while (count > 0) { + if ((count << 1) > (BUFMAX - 2)) { + wcount = (BUFMAX - 2) >> 1; + } else { + wcount = count; + } + count -= wcount; + for (i = 0; i < wcount; i++) { + bufptr = pack_hex_byte(bufptr, s[i]); + } + *bufptr = '\0'; + s += wcount; + + putpacket(gdbconbuf); + + } + IF_SMP(in_kgdb_console = 0); +} +#endif +#ifdef CONFIG_SMP +static void +to_gdb(const char *s) +{ + int count = 0; + while (s[count] && (count++ < BUFMAX)) ; + kgdb_gdb_message(s, count); +} +#endif +#ifdef CONFIG_KGDB_CONSOLE +#include +#include +#include +#include +#include + +void +kgdb_console_write(struct console *co, const char *s, unsigned count) +{ + + if (gdb_i386vector == -1) { + /* + * We have not yet talked to gdb. What to do... + * lets break, on continue we can do the write. + * But first tell him whats up. Uh, well no can do, + * as this IS the console. Oh well... + * We do need to wait or the messages will be lost. + * Other option would be to tell the above code to + * ignore this breakpoint and do an auto return, + * but that might confuse gdb. Also this happens + * early enough in boot up that we don't have the traps + * set up yet, so... + */ + breakpoint(); + } + kgdb_gdb_message(s, count); +} + +/* + * ------------------------------------------------------------ + * Serial KGDB driver + * ------------------------------------------------------------ + */ + +static struct console kgdbcons = { + name:"kgdb", + write:kgdb_console_write, +#ifdef CONFIG_KGDB_USER_CONSOLE + device:kgdb_console_device, +#endif + flags:CON_PRINTBUFFER | CON_ENABLED, + index:-1, +}; + +/* + * The trick here is that this file gets linked before printk.o + * That means we get to peer at the console info in the command + * line before it does. If we are up, we register, otherwise, + * do nothing. By returning 0, we allow printk to look also. + */ +static int kgdb_console_enabled; + +int __init +kgdb_console_init(char *str) +{ + if ((strncmp(str, "kgdb", 4) == 0) || (strncmp(str, "gdb", 3) == 0)) { + register_console(&kgdbcons); + kgdb_console_enabled = 1; + } + return 0; /* let others look at the string */ +} + +__setup("console=", kgdb_console_init); + +#ifdef CONFIG_KGDB_USER_CONSOLE +static kdev_t kgdb_console_device(struct console *c); +/* This stuff sort of works, but it knocks out telnet devices + * we are leaving it here in case we (or you) find time to figure it out + * better.. + */ + +/* + * We need a real char device as well for when the console is opened for user + * space activities. + */ + +static int +kgdb_consdev_open(struct inode *inode, struct file *file) +{ + return 0; +} + +static ssize_t +kgdb_consdev_write(struct file *file, const char *buf, + size_t count, loff_t * ppos) +{ + int size, ret = 0; + static char kbuf[128]; + static DECLARE_MUTEX(sem); + + /* We are not reentrant... */ + if (down_interruptible(&sem)) + return -ERESTARTSYS; + + while (count > 0) { + /* need to copy the data from user space */ + size = count; + if (size > sizeof (kbuf)) + size = sizeof (kbuf); + if (copy_from_user(kbuf, buf, size)) { + ret = -EFAULT; + break;; + } + kgdb_console_write(&kgdbcons, kbuf, size); + count -= size; + ret += size; + buf += size; + } + + up(&sem); + + return ret; +} + +struct file_operations kgdb_consdev_fops = { + open:kgdb_consdev_open, + write:kgdb_consdev_write +}; +static kdev_t +kgdb_console_device(struct console *c) +{ + return MKDEV(TTYAUX_MAJOR, 1); +} + +/* + * This routine gets called from the serial stub in the i386/lib + * This is so it is done late in bring up (just before the console open). + */ +void +kgdb_console_finit(void) +{ + if (kgdb_console_enabled) { + char *cptr = cdevname(MKDEV(TTYAUX_MAJOR, 1)); + char *cp = cptr; + while (*cptr && *cptr != '(') + cptr++; + *cptr = 0; + unregister_chrdev(TTYAUX_MAJOR, cp); + register_chrdev(TTYAUX_MAJOR, "kgdb", &kgdb_consdev_fops); + } +} +#endif +#endif +#ifdef CONFIG_KGDB_TS +#include /* time stamp code */ +#include /* in_interrupt */ +#ifdef CONFIG_KGDB_TS_64 +#define DATA_POINTS 64 +#endif +#ifdef CONFIG_KGDB_TS_128 +#define DATA_POINTS 128 +#endif +#ifdef CONFIG_KGDB_TS_256 +#define DATA_POINTS 256 +#endif +#ifdef CONFIG_KGDB_TS_512 +#define DATA_POINTS 512 +#endif +#ifdef CONFIG_KGDB_TS_1024 +#define DATA_POINTS 1024 +#endif +#ifndef DATA_POINTS +#define DATA_POINTS 128 /* must be a power of two */ +#endif +#define INDEX_MASK (DATA_POINTS - 1) +#if (INDEX_MASK & DATA_POINTS) +#error "CONFIG_KGDB_TS_COUNT must be a power of 2" +#endif +struct kgdb_and_then_struct { +#ifdef CONFIG_SMP + int on_cpu; +#endif + struct task_struct *task; + long long at_time; + int from_ln; + char *in_src; + void *from; + int *with_shpf; + int data0; + int data1; +}; +struct kgdb_and_then_struct2 { +#ifdef CONFIG_SMP + int on_cpu; +#endif + struct task_struct *task; + long long at_time; + int from_ln; + char *in_src; + void *from; + int *with_shpf; + struct task_struct *t1; + struct task_struct *t2; +}; +struct kgdb_and_then_struct kgdb_data[DATA_POINTS]; + +struct kgdb_and_then_struct *kgdb_and_then = &kgdb_data[0]; +int kgdb_and_then_count; + +void +kgdb_tstamp(int line, char *source, int data0, int data1) +{ + static spinlock_t ts_spin = SPIN_LOCK_UNLOCKED; + int flags; + kgdb_local_irq_save(flags); + spin_lock(&ts_spin); + rdtscll(kgdb_and_then->at_time); +#ifdef CONFIG_SMP + kgdb_and_then->on_cpu = smp_processor_id(); +#endif + kgdb_and_then->task = current; + kgdb_and_then->from_ln = line; + kgdb_and_then->in_src = source; + kgdb_and_then->from = __builtin_return_address(0); + kgdb_and_then->with_shpf = (int *) (((flags & IF_BIT) >> 9) | + (preempt_count() << 8)); + kgdb_and_then->data0 = data0; + kgdb_and_then->data1 = data1; + kgdb_and_then = &kgdb_data[++kgdb_and_then_count & INDEX_MASK]; + spin_unlock(&ts_spin); + kgdb_local_irq_restore(flags); +#ifdef CONFIG_PREEMPT + +#endif + return; +} +#endif +typedef int gdb_debug_hook(int exceptionVector, + int signo, int err_code, struct pt_regs *linux_regs); +gdb_debug_hook *linux_debug_hook = &kgdb_handle_exception; /* histerical reasons... */ + +static int kgdb_need_breakpoint[NR_CPUS]; + +void kgdb_schedule_breakpoint(void) +{ + kgdb_need_breakpoint[smp_processor_id()] = 1; +} + +void kgdb_process_breakpoint(void) +{ + /* + * Handle a breakpoint queued from inside network driver code + * to avoid reentrancy issues + */ + if (kgdb_need_breakpoint[smp_processor_id()]) { + kgdb_need_breakpoint[smp_processor_id()] = 0; + BREAKPOINT; + } +} + --- linux-2.6.6/arch/i386/kernel/Makefile 2004-05-09 21:07:22.000000000 -0700 +++ 25/arch/i386/kernel/Makefile 2004-05-10 01:19:06.868694856 -0700 @@ -14,6 +14,7 @@ obj-y += timers/ obj-$(CONFIG_ACPI_BOOT) += acpi/ obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.o obj-$(CONFIG_MCA) += mca.o +obj-$(CONFIG_KGDB) += kgdb_stub.o obj-$(CONFIG_X86_MSR) += msr.o obj-$(CONFIG_X86_CPUID) += cpuid.o obj-$(CONFIG_MICROCODE) += microcode.o --- linux-2.6.6/arch/i386/kernel/mpparse.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/i386/kernel/mpparse.c 2004-05-10 01:19:35.826292632 -0700 @@ -28,7 +28,6 @@ #include #include #include -#include #include #include --- linux-2.6.6/arch/i386/kernel/nmi.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/i386/kernel/nmi.c 2004-05-10 01:19:26.193757000 -0700 @@ -31,9 +31,19 @@ #include #include +#ifdef CONFIG_KGDB +#include +#ifdef CONFIG_SMP +unsigned int nmi_watchdog = NMI_IO_APIC; +#else +unsigned int nmi_watchdog = NMI_LOCAL_APIC; +#endif +#else unsigned int nmi_watchdog = NMI_NONE; +#endif static unsigned int nmi_hz = HZ; -unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */ +static unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */ +static unsigned int nmi_p4_cccr_val; extern void show_registers(struct pt_regs *regs); /* @@ -80,7 +90,8 @@ int nmi_active; #define P4_ESCR_EVENT_SELECT(N) ((N)<<25) #define P4_ESCR_OS (1<<3) #define P4_ESCR_USR (1<<2) -#define P4_CCCR_OVF_PMI (1<<26) +#define P4_CCCR_OVF_PMI0 (1<<26) +#define P4_CCCR_OVF_PMI1 (1<<27) #define P4_CCCR_THRESHOLD(N) ((N)<<20) #define P4_CCCR_COMPLEMENT (1<<19) #define P4_CCCR_COMPARE (1<<18) @@ -93,7 +104,7 @@ int nmi_active; #define MSR_P4_IQ_COUNTER0 0x30C #define P4_NMI_CRU_ESCR0 (P4_ESCR_EVENT_SELECT(0x3F)|P4_ESCR_OS|P4_ESCR_USR) #define P4_NMI_IQ_CCCR0 \ - (P4_CCCR_OVF_PMI|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT| \ + (P4_CCCR_OVF_PMI0|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT| \ P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE) int __init check_nmi_watchdog (void) @@ -364,6 +375,11 @@ static int setup_p4_watchdog(void) return 0; nmi_perfctr_msr = MSR_P4_IQ_COUNTER0; + nmi_p4_cccr_val = P4_NMI_IQ_CCCR0; +#ifdef CONFIG_SMP + if (smp_num_siblings == 2) + nmi_p4_cccr_val |= P4_CCCR_OVF_PMI1; +#endif if (!(misc_enable & MSR_P4_MISC_ENABLE_PEBS_UNAVAIL)) clear_msr_range(0x3F1, 2); @@ -381,7 +397,7 @@ static int setup_p4_watchdog(void) Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz/nmi_hz*1000)); wrmsr(MSR_P4_IQ_COUNTER0, -(cpu_khz/nmi_hz*1000), -1); apic_write(APIC_LVTPC, APIC_DM_NMI); - wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0, 0); + wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0); return 1; } @@ -451,6 +467,9 @@ void touch_nmi_watchdog (void) for (i = 0; i < NR_CPUS; i++) alert_counter[i] = 0; } +#ifdef CONFIG_KGDB +int tune_watchdog = 5*HZ; +#endif void nmi_watchdog_tick (struct pt_regs * regs) { @@ -464,12 +483,24 @@ void nmi_watchdog_tick (struct pt_regs * sum = irq_stat[cpu].apic_timer_irqs; +#ifdef CONFIG_KGDB + if (! in_kgdb(regs) && last_irq_sums[cpu] == sum ) { + +#else if (last_irq_sums[cpu] == sum) { +#endif /* * Ayiee, looks like this CPU is stuck ... * wait a few IRQs (5 seconds) before doing the oops ... */ alert_counter[cpu]++; +#ifdef CONFIG_KGDB + if (alert_counter[cpu] == tune_watchdog) { + kgdb_handle_exception(2, SIGPWR, 0, regs); + last_irq_sums[cpu] = sum; + alert_counter[cpu] = 0; + } +#endif if (alert_counter[cpu] == 5*nmi_hz) { spin_lock(&nmi_print_lock); /* @@ -498,7 +529,7 @@ void nmi_watchdog_tick (struct pt_regs * * - LVTPC is masked on interrupt and must be * unmasked by the LVTPC handler. */ - wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0, 0); + wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0); apic_write(APIC_LVTPC, APIC_DM_NMI); } else if (nmi_perfctr_msr == MSR_P6_PERFCTR0) { --- linux-2.6.6/arch/i386/kernel/process.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/i386/kernel/process.c 2004-05-10 01:19:52.450765328 -0700 @@ -633,11 +633,6 @@ out: return error; } -/* - * These bracket the sleeping functions.. - */ -#define first_sched ((unsigned long) scheduling_functions_start_here) -#define last_sched ((unsigned long) scheduling_functions_end_here) #define top_esp (THREAD_SIZE - sizeof(unsigned long)) #define top_ebp (THREAD_SIZE - 2*sizeof(unsigned long)) @@ -658,14 +653,12 @@ unsigned long get_wchan(struct task_stru if (ebp < stack_page || ebp > top_ebp+stack_page) return 0; eip = *(unsigned long *) (ebp+4); - if (eip < first_sched || eip >= last_sched) + if (!in_sched_functions(eip)) return eip; ebp = *(unsigned long *) ebp; } while (count++ < 16); return 0; } -#undef last_sched -#undef first_sched /* * sys_alloc_thread_area: get a yet unused TLS descriptor index. @@ -744,7 +737,7 @@ asmlinkage int sys_set_thread_area(struc ((desc)->a & 0x0ffff) | \ ((desc)->b & 0xf0000) ) -#define GET_32BIT(desc) (((desc)->b >> 23) & 1) +#define GET_32BIT(desc) (((desc)->b >> 22) & 1) #define GET_CONTENTS(desc) (((desc)->b >> 10) & 3) #define GET_WRITABLE(desc) (((desc)->b >> 9) & 1) #define GET_LIMIT_PAGES(desc) (((desc)->b >> 23) & 1) --- linux-2.6.6/arch/i386/kernel/ptrace.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/i386/kernel/ptrace.c 2004-05-10 01:19:52.451765176 -0700 @@ -174,7 +174,7 @@ ptrace_get_thread_area(struct task_struc ((desc)->a & 0x0ffff) | \ ((desc)->b & 0xf0000) ) -#define GET_32BIT(desc) (((desc)->b >> 23) & 1) +#define GET_32BIT(desc) (((desc)->b >> 22) & 1) #define GET_CONTENTS(desc) (((desc)->b >> 10) & 3) #define GET_WRITABLE(desc) (((desc)->b >> 9) & 1) #define GET_LIMIT_PAGES(desc) (((desc)->b >> 23) & 1) --- linux-2.6.6/arch/i386/kernel/setup.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/i386/kernel/setup.c 2004-05-10 01:19:18.566916456 -0700 @@ -128,7 +128,6 @@ unsigned long saved_videomode; #define RAMDISK_LOAD_FLAG 0x4000 static char command_line[COMMAND_LINE_SIZE]; - char saved_command_line[COMMAND_LINE_SIZE]; unsigned char __initdata boot_params[PARAM_SIZE]; --- linux-2.6.6/arch/i386/kernel/smpboot.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/i386/kernel/smpboot.c 2004-05-10 01:19:35.827292480 -0700 @@ -39,6 +39,7 @@ #include #include +#include #include #include #include @@ -46,7 +47,6 @@ #include #include -#include #include #include #include @@ -936,7 +936,7 @@ static int boot_cpu_logical_apicid; /* Where the IO area was mapped on multiquad, always 0 otherwise */ void *xquad_portio; -int cpu_sibling_map[NR_CPUS] __cacheline_aligned; +cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned; static void __init smp_boot_cpus(unsigned int max_cpus) { @@ -955,6 +955,8 @@ static void __init smp_boot_cpus(unsigne current_thread_info()->cpu = 0; smp_tune_scheduling(); + cpus_clear(cpu_sibling_map[0]); + cpu_set(0, cpu_sibling_map[0]); /* * If we couldn't find an SMP configuration at boot time, @@ -1081,34 +1083,39 @@ static void __init smp_boot_cpus(unsigne Dprintk("Boot done.\n"); /* - * If Hyper-Threading is avaialble, construct cpu_sibling_map[], so - * that we can tell the sibling CPU efficiently. + * construct cpu_sibling_map[], so that we can tell sibling CPUs + * efficiently. */ - if (cpu_has_ht && smp_num_siblings > 1) { - for (cpu = 0; cpu < NR_CPUS; cpu++) - cpu_sibling_map[cpu] = NO_PROC_ID; - - for (cpu = 0; cpu < NR_CPUS; cpu++) { - int i; - if (!cpu_isset(cpu, cpu_callout_map)) - continue; + for (cpu = 0; cpu < NR_CPUS; cpu++) + cpus_clear(cpu_sibling_map[cpu]); + + for (cpu = 0; cpu < NR_CPUS; cpu++) { + int siblings = 0; + int i; + if (!cpu_isset(cpu, cpu_callout_map)) + continue; + if (smp_num_siblings > 1) { for (i = 0; i < NR_CPUS; i++) { - if (i == cpu || !cpu_isset(i, cpu_callout_map)) + if (!cpu_isset(i, cpu_callout_map)) continue; if (phys_proc_id[cpu] == phys_proc_id[i]) { - cpu_sibling_map[cpu] = i; - printk("cpu_sibling_map[%d] = %d\n", cpu, cpu_sibling_map[cpu]); - break; + siblings++; + cpu_set(i, cpu_sibling_map[cpu]); } } - if (cpu_sibling_map[cpu] == NO_PROC_ID) { - smp_num_siblings = 1; - printk(KERN_WARNING "WARNING: No sibling found for CPU %d.\n", cpu); - } + } else { + siblings++; + cpu_set(cpu, cpu_sibling_map[cpu]); } + + if (siblings != smp_num_siblings) + printk(KERN_WARNING "WARNING: %d siblings found for CPU%d, should be %d\n", siblings, cpu, smp_num_siblings); } + if (nmi_watchdog == NMI_LOCAL_APIC) + check_nmi_watchdog(); + smpboot_setup_io_apic(); setup_boot_APIC_clock(); @@ -1120,6 +1127,209 @@ static void __init smp_boot_cpus(unsigne synchronize_tsc_bp(); } +#ifdef CONFIG_SCHED_SMT +#ifdef CONFIG_NUMA +static struct sched_group sched_group_cpus[NR_CPUS]; +static struct sched_group sched_group_phys[NR_CPUS]; +static struct sched_group sched_group_nodes[MAX_NUMNODES]; +static DEFINE_PER_CPU(struct sched_domain, cpu_domains); +static DEFINE_PER_CPU(struct sched_domain, phys_domains); +static DEFINE_PER_CPU(struct sched_domain, node_domains); +__init void arch_init_sched_domains(void) +{ + int i; + struct sched_group *first = NULL, *last = NULL; + + /* Set up domains */ + for_each_cpu(i) { + struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); + struct sched_domain *phys_domain = &per_cpu(phys_domains, i); + struct sched_domain *node_domain = &per_cpu(node_domains, i); + int node = cpu_to_node(i); + cpumask_t nodemask = node_to_cpumask(node); + + *cpu_domain = SD_SIBLING_INIT; + cpu_domain->span = cpu_sibling_map[i]; + cpu_domain->parent = phys_domain; + cpu_domain->groups = &sched_group_cpus[i]; + + *phys_domain = SD_CPU_INIT; + phys_domain->span = nodemask; + phys_domain->parent = node_domain; + phys_domain->groups = &sched_group_phys[first_cpu(cpu_domain->span)]; + + *node_domain = SD_NODE_INIT; + node_domain->span = cpu_possible_map; + node_domain->groups = &sched_group_nodes[cpu_to_node(i)]; + } + + /* Set up CPU (sibling) groups */ + for_each_cpu(i) { + struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); + int j; + first = last = NULL; + + if (i != first_cpu(cpu_domain->span)) + continue; + + for_each_cpu_mask(j, cpu_domain->span) { + struct sched_group *cpu = &sched_group_cpus[j]; + + cpu->cpumask = CPU_MASK_NONE; + cpu_set(j, cpu->cpumask); + cpu->cpu_power = SCHED_LOAD_SCALE; + + if (!first) + first = cpu; + if (last) + last->next = cpu; + last = cpu; + } + last->next = first; + } + + for (i = 0; i < MAX_NUMNODES; i++) { + int j; + cpumask_t nodemask; + struct sched_group *node = &sched_group_nodes[i]; + cpus_and(nodemask, node_to_cpumask(i), cpu_possible_map); + + if (cpus_empty(nodemask)) + continue; + + first = last = NULL; + /* Set up physical groups */ + for_each_cpu_mask(j, nodemask) { + struct sched_domain *cpu_domain = &per_cpu(cpu_domains, j); + struct sched_group *cpu = &sched_group_phys[j]; + + if (j != first_cpu(cpu_domain->span)) + continue; + + cpu->cpumask = cpu_domain->span; + /* + * Make each extra sibling increase power by 10% of + * the basic CPU. This is very arbitrary. + */ + cpu->cpu_power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE*(cpus_weight(cpu->cpumask)-1) / 10; + node->cpu_power += cpu->cpu_power; + + if (!first) + first = cpu; + if (last) + last->next = cpu; + last = cpu; + } + last->next = first; + } + + /* Set up nodes */ + first = last = NULL; + for (i = 0; i < MAX_NUMNODES; i++) { + struct sched_group *cpu = &sched_group_nodes[i]; + cpumask_t nodemask; + cpus_and(nodemask, node_to_cpumask(i), cpu_possible_map); + + if (cpus_empty(nodemask)) + continue; + + cpu->cpumask = nodemask; + /* ->cpu_power already setup */ + + if (!first) + first = cpu; + if (last) + last->next = cpu; + last = cpu; + } + last->next = first; + + mb(); + for_each_cpu(i) { + struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); + cpu_attach_domain(cpu_domain, i); + } +} +#else /* !CONFIG_NUMA */ +static struct sched_group sched_group_cpus[NR_CPUS]; +static struct sched_group sched_group_phys[NR_CPUS]; +static DEFINE_PER_CPU(struct sched_domain, cpu_domains); +static DEFINE_PER_CPU(struct sched_domain, phys_domains); +__init void arch_init_sched_domains(void) +{ + int i; + struct sched_group *first = NULL, *last = NULL; + + /* Set up domains */ + for_each_cpu(i) { + struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); + struct sched_domain *phys_domain = &per_cpu(phys_domains, i); + + *cpu_domain = SD_SIBLING_INIT; + cpu_domain->span = cpu_sibling_map[i]; + cpu_domain->parent = phys_domain; + cpu_domain->groups = &sched_group_cpus[i]; + + *phys_domain = SD_CPU_INIT; + phys_domain->span = cpu_possible_map; + phys_domain->groups = &sched_group_phys[first_cpu(cpu_domain->span)]; + } + + /* Set up CPU (sibling) groups */ + for_each_cpu(i) { + struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); + int j; + first = last = NULL; + + if (i != first_cpu(cpu_domain->span)) + continue; + + for_each_cpu_mask(j, cpu_domain->span) { + struct sched_group *cpu = &sched_group_cpus[j]; + + cpus_clear(cpu->cpumask); + cpu_set(j, cpu->cpumask); + cpu->cpu_power = SCHED_LOAD_SCALE; + + if (!first) + first = cpu; + if (last) + last->next = cpu; + last = cpu; + } + last->next = first; + } + + first = last = NULL; + /* Set up physical groups */ + for_each_cpu(i) { + struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); + struct sched_group *cpu = &sched_group_phys[i]; + + if (i != first_cpu(cpu_domain->span)) + continue; + + cpu->cpumask = cpu_domain->span; + /* See SMT+NUMA setup for comment */ + cpu->cpu_power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE*(cpus_weight(cpu->cpumask)-1) / 10; + + if (!first) + first = cpu; + if (last) + last->next = cpu; + last = cpu; + } + last->next = first; + + mb(); + for_each_cpu(i) { + struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); + cpu_attach_domain(cpu_domain, i); + } +} +#endif /* CONFIG_NUMA */ +#endif /* CONFIG_SCHED_SMT */ + /* These are wrappers to interface to the new boot process. Someone who understands all this stuff should rewrite it properly. --RR 15/Jul/02 */ void __init smp_prepare_cpus(unsigned int max_cpus) --- linux-2.6.6/arch/i386/kernel/smp.c 2004-03-10 20:41:25.000000000 -0800 +++ 25/arch/i386/kernel/smp.c 2004-05-10 01:19:49.904152472 -0700 @@ -21,7 +21,6 @@ #include #include -#include #include #include #include @@ -466,7 +465,17 @@ void flush_tlb_all(void) { on_each_cpu(do_flush_tlb_all, 0, 1, 1); } - +#ifdef CONFIG_KGDB +/* + * By using the NMI code instead of a vector we just sneak thru the + * word generator coming out with just what we want. AND it does + * not matter if clustered_apic_mode is set or not. + */ +void smp_send_nmi_allbutself(void) +{ + send_IPI_allbutself(APIC_DM_NMI); +} +#endif /* * this function sends a 'reschedule' IPI to another CPU. * it goes straight through and wastes no time serializing @@ -519,6 +528,9 @@ int smp_call_function (void (*func) (voi if (!cpus) return 0; + /* Can deadlock when called with interrupts disabled */ + WARN_ON(irqs_disabled()); + data.func = func; data.info = info; atomic_set(&data.started, 0); --- linux-2.6.6/arch/i386/kernel/timers/timer_tsc.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/i386/kernel/timers/timer_tsc.c 2004-05-10 01:19:01.790466864 -0700 @@ -27,6 +27,8 @@ static unsigned long hpet_last; struct timer_opts timer_tsc; #endif +static inline void cpufreq_delayed_get(void); + int tsc_disable __initdata = 0; extern spinlock_t i8253_lock; @@ -241,6 +243,9 @@ static void mark_offset_tsc(void) clock_fallback(); } + /* ... but give the TSC a fair chance */ + if (lost_count == 50) + cpufreq_delayed_get(); } else lost_count = 0; /* update the monotonic base value */ @@ -324,15 +329,35 @@ static void mark_offset_tsc_hpet(void) #ifdef CONFIG_CPU_FREQ +#include + +static unsigned int cpufreq_init = 0; +static struct work_struct cpufreq_delayed_get_work; + +static void handle_cpufreq_delayed_get(void *v) +{ + unsigned int cpu; + for_each_online_cpu(cpu) { + cpufreq_get(cpu); + } +} + +/* if we notice lost ticks, schedule a call to cpufreq_get() as it tries + * to verify the CPU frequency the timing core thinks the CPU is running + * at is still correct. + */ +static inline void cpufreq_delayed_get(void) +{ + if (cpufreq_init) + schedule_work(&cpufreq_delayed_get_work); +} + /* If the CPU frequency is scaled, TSC-based delays will need a different - * loops_per_jiffy value to function properly. An exception to this - * are modern Intel Pentium 4 processors, where the TSC runs at a constant - * speed independent of frequency scaling. + * loops_per_jiffy value to function properly. */ static unsigned int ref_freq = 0; static unsigned long loops_per_jiffy_ref = 0; -static unsigned int variable_tsc = 1; #ifndef CONFIG_SMP static unsigned long fast_gettimeoffset_ref = 0; @@ -356,14 +381,15 @@ time_cpufreq_notifier(struct notifier_bl } if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) || - (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) { - if (variable_tsc) + (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) || + (val == CPUFREQ_RESUMECHANGE)) { + if (!freq->flags & CPUFREQ_CONST_LOOPS) cpu_data[freq->cpu].loops_per_jiffy = cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new); #ifndef CONFIG_SMP if (cpu_khz) cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new); if (use_tsc) { - if (variable_tsc) { + if (!freq->flags & CPUFREQ_CONST_LOOPS) { fast_gettimeoffset_quotient = cpufreq_scale(fast_gettimeoffset_ref, freq->new, ref_freq); set_cyc2ns_scale(cpu_khz/1000); } @@ -382,14 +408,17 @@ static struct notifier_block time_cpufre static int __init cpufreq_tsc(void) { - /* P4 and above CPU TSC freq doesn't change when CPU frequency changes*/ - if ((boot_cpu_data.x86 >= 15) && (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)) - variable_tsc = 0; - - return cpufreq_register_notifier(&time_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); + int ret; + INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get, NULL); + ret = cpufreq_register_notifier(&time_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); + if (!ret) + cpufreq_init = 1; + return ret; } core_initcall(cpufreq_tsc); +#else /* CONFIG_CPU_FREQ */ +static inline void cpufreq_delayed_get(void) { return; } #endif --- linux-2.6.6/arch/i386/kernel/traps.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/i386/kernel/traps.c 2004-05-10 01:19:55.061368456 -0700 @@ -47,7 +47,6 @@ #include #include -#include #include #include @@ -94,27 +93,104 @@ asmlinkage void machine_check(void); static int kstack_depth_to_print = 24; -void show_trace(struct task_struct *task, unsigned long * stack) +static int valid_stack_ptr(struct task_struct *task, void *p) +{ + if (p <= (void *)task->thread_info) + return 0; + if (kstack_end(p)) + return 0; + return 1; +} + +#ifdef CONFIG_KGDB +extern void sysenter_entry(void); +#include +#include +void set_intr_gate(unsigned int n, void *addr); +static void set_intr_usr_gate(unsigned int n, void *addr); +/* + * Should be able to call this breakpoint() very early in + * bring up. Just hard code the call where needed. + * The breakpoint() code is here because set_?_gate() functions + * are local (static) to trap.c. They need be done only once, + * but it does not hurt to do them over. + */ +void breakpoint(void) +{ + set_intr_usr_gate(3,&int3); /* disable ints on trap */ + set_intr_gate(1,&debug); + set_intr_gate(14,&page_fault); + + BREAKPOINT; +} +#define CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,after) \ + { \ + if (!user_mode(regs) ) \ + { \ + kgdb_handle_exception(trapnr, signr, error_code, regs); \ + after; \ + } else if ((trapnr == 3) && (regs->eflags &0x200)) local_irq_enable(); \ + } +#else +#define CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,after) +#endif + + +#ifdef CONFIG_FRAME_POINTER +void print_context_stack(struct task_struct *task, unsigned long *stack, + unsigned long ebp) { unsigned long addr; - if (!stack) - stack = (unsigned long*)&stack; + while (valid_stack_ptr(task, (void *)ebp)) { + addr = *(unsigned long *)(ebp + 4); + printk(" [<%08lx>] ", addr); + print_symbol("%s", addr); + printk("\n"); + ebp = *(unsigned long *)ebp; + } +} +#else +void print_context_stack(struct task_struct *task, unsigned long *stack, + unsigned long ebp) +{ + unsigned long addr; - printk("Call Trace:"); -#ifdef CONFIG_KALLSYMS - printk("\n"); + while (!kstack_end(stack)) { + addr = *stack++; + if (kernel_text_address(addr)) { + printk(" [<%08lx>] ", addr); + print_symbol("%s\n", addr); + } + } +} #endif + +void show_trace(struct task_struct *task, unsigned long * stack) +{ + unsigned long ebp; + + if (!task) + task = current; + + if (!valid_stack_ptr(task, stack)) { + printk("Stack pointer is garbage, not printing trace\n"); + return; + } + + if (task == current) { + /* Grab ebp right from our regs */ + asm ("movl %%ebp, %0" : "=r" (ebp) : ); + } else { + /* ebp is the last reg pushed by switch_to */ + ebp = *(unsigned long *) task->thread.esp; + } + while (1) { struct thread_info *context; - context = (struct thread_info*) ((unsigned long)stack & (~(THREAD_SIZE - 1))); - while (!kstack_end(stack)) { - addr = *stack++; - if (kernel_text_address(addr)) { - printk(" [<%08lx>] ", addr); - print_symbol("%s\n", addr); - } - } + context = (struct thread_info *) + ((unsigned long)stack & (~(THREAD_SIZE - 1))); + print_context_stack(task, stack, ebp); stack = (unsigned long*)context->previous_esp; if (!stack) break; @@ -143,7 +219,7 @@ void show_stack(struct task_struct *task printk("\n "); printk("%08lx ", *stack++); } - printk("\n"); + printk("\nCall Trace:\n"); show_trace(task, esp); } @@ -174,7 +250,7 @@ void show_registers(struct pt_regs *regs ss = regs->xss & 0xffff; } print_modules(); - printk("CPU: %d\nEIP: %04x:[<%08lx>] %s\nEFLAGS: %08lx" + printk("CPU: %d\nEIP: %04x:[<%08lx>] %s VLI\nEFLAGS: %08lx" " (%s) \n", smp_processor_id(), 0xffff & regs->xcs, regs->eip, print_tainted(), regs->eflags, UTS_RELEASE); @@ -192,23 +268,25 @@ void show_registers(struct pt_regs *regs * time of the fault.. */ if (in_kernel) { + u8 *eip; printk("\nStack: "); show_stack(NULL, (unsigned long*)esp); printk("Code: "); - if(regs->eip < PAGE_OFFSET) - goto bad; - for(i=0;i<20;i++) - { + eip = (u8 *)regs->eip - 43; + for (i = 0; i < 64; i++, eip++) { unsigned char c; - if(__get_user(c, &((unsigned char*)regs->eip)[i])) { -bad: + + if (eip < (u8 *)PAGE_OFFSET || __get_user(c, eip)) { printk(" Bad EIP value."); break; } - printk("%02x ", c); + if (eip == (u8 *)regs->eip) + printk("<%02x> ", c); + else + printk("%02x ", c); } } printk("\n"); @@ -260,6 +338,14 @@ void die(const char * str, struct pt_reg console_verbose(); spin_lock_irq(&die_lock); bust_spinlocks(1); + printk( + " ___ ______\n" + " 0--,| /OOOOOO\\\n" + " {_o / /OO plop OO\\\n" + " \\__\\_/OO oh dear OOO\\s\n" + " \\OOOOOOOOOOOOOOOO/\n" + " __XXX__ __XXX__\n" + ); handle_BUG(regs); printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); #ifdef CONFIG_PREEMPT @@ -276,6 +362,15 @@ void die(const char * str, struct pt_reg #endif if (nl) printk("\n"); +#ifdef CONFIG_KGDB + /* This is about the only place we want to go to kgdb even if in + * user mode. But we must go in via a trap so within kgdb we will + * always be in kernel mode. + */ + if (user_mode(regs)) + BREAKPOINT; +#endif + CHK_REMOTE_DEBUG(0,SIGTRAP,err,regs,) show_registers(regs); bust_spinlocks(0); spin_unlock_irq(&die_lock); @@ -345,6 +440,7 @@ static inline void do_trap(int trapnr, i #define DO_ERROR(trapnr, signr, str, name) \ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ { \ + CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,)\ do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \ } @@ -362,7 +458,9 @@ asmlinkage void do_##name(struct pt_regs #define DO_VM86_ERROR(trapnr, signr, str, name) \ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ { \ + CHK_REMOTE_DEBUG(trapnr, signr, error_code,regs, return)\ do_trap(trapnr, signr, str, 1, regs, error_code, NULL); \ + return; \ } #define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ @@ -409,8 +507,10 @@ gp_in_vm86: return; gp_in_kernel: - if (!fixup_exception(regs)) + if (!fixup_exception(regs)){ + CHK_REMOTE_DEBUG(13,SIGSEGV,error_code,regs,) die("general protection fault", regs, error_code); + } } static void mem_parity_error(unsigned char reason, struct pt_regs * regs) @@ -572,8 +672,18 @@ asmlinkage void do_debug(struct pt_regs * allowing programs to debug themselves without the ptrace() * interface. */ +#ifdef CONFIG_KGDB + /* + * I think this is the only "real" case of a TF in the kernel + * that really belongs to user space. Others are + * "Ours all ours!" + */ + if (((regs->xcs & 3) == 0) && ((void *)regs->eip == sysenter_entry)) + goto clear_TF_reenable; +#else if ((regs->xcs & 3) == 0) goto clear_TF_reenable; +#endif if ((tsk->ptrace & (PT_DTRACE|PT_PTRACED)) == PT_DTRACE) goto clear_TF; } @@ -585,6 +695,17 @@ asmlinkage void do_debug(struct pt_regs info.si_errno = 0; info.si_code = TRAP_BRKPT; +#ifdef CONFIG_KGDB + /* + * If this is a kernel mode trap, we need to reset db7 to allow us + * to continue sanely ALSO skip the signal delivery + */ + if ((regs->xcs & 3) == 0) + goto clear_dr7; + + /* if not kernel, allow ints but only if they were on */ + if ( regs->eflags & 0x200) local_irq_enable(); +#endif /* If this is a kernel mode trap, save the user PC on entry to * the kernel, that's what the debugger can make sense of. */ @@ -599,6 +720,7 @@ clear_dr7: __asm__("movl %0,%%db7" : /* no output */ : "r" (0)); + CHK_REMOTE_DEBUG(1,SIGTRAP,error_code,regs,) return; debug_vm86: @@ -847,6 +969,12 @@ static void __init set_call_gate(void *a { _set_gate(a,12,3,addr,__KERNEL_CS); } +#ifdef CONFIG_KGDB +void set_intr_usr_gate(unsigned int n, void *addr) +{ + _set_gate(idt_table+n,14,3,addr,__KERNEL_CS); +} +#endif static void __init set_task_gate(unsigned int n, unsigned int gdt_entry) { @@ -869,7 +997,11 @@ void __init trap_init(void) set_trap_gate(0,÷_error); set_intr_gate(1,&debug); set_intr_gate(2,&nmi); +#ifndef CONFIG_KGDB set_system_gate(3,&int3); /* int3-5 can be called from all */ +#else + set_intr_usr_gate(3,&int3); /* int3-5 can be called from all */ +#endif set_system_gate(4,&overflow); set_system_gate(5,&bounds); set_trap_gate(6,&invalid_op); --- linux-2.6.6/arch/i386/kernel/vm86.c 2004-03-10 20:41:25.000000000 -0800 +++ 25/arch/i386/kernel/vm86.c 2004-05-10 01:19:35.829292176 -0700 @@ -44,7 +44,6 @@ #include #include -#include #include #include #include --- linux-2.6.6/arch/i386/lib/dec_and_lock.c 2003-11-09 16:45:04.000000000 -0800 +++ 25/arch/i386/lib/dec_and_lock.c 2004-05-10 01:19:27.996482944 -0700 @@ -10,6 +10,7 @@ #include #include +#ifndef ATOMIC_DEC_AND_LOCK int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) { int counter; @@ -38,3 +39,5 @@ slow_path: spin_unlock(lock); return 0; } +#endif + --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/arch/i386/lib/kgdb_serial.c 2004-05-10 01:19:07.212642568 -0700 @@ -0,0 +1,499 @@ +/* + * Serial interface GDB stub + * + * Written (hacked together) by David Grothe (dave@gcom.com) + * Modified to allow invokation early in boot see also + * kgdb.h for instructions by George Anzinger(george@mvista.com) + * Modified to handle debugging over ethernet by Robert Walsh + * and wangdi , based on + * code by San Mehat. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_KGDB_USER_CONSOLE +extern void kgdb_console_finit(void); +#endif +#define PRNT_off +#define TEST_EXISTANCE +#ifdef PRNT +#define dbprintk(s) printk s +#else +#define dbprintk(s) +#endif +#define TEST_INTERRUPT_off +#ifdef TEST_INTERRUPT +#define intprintk(s) printk s +#else +#define intprintk(s) +#endif + +#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT) + +#define GDB_BUF_SIZE 512 /* power of 2, please */ + +static char gdb_buf[GDB_BUF_SIZE]; +static int gdb_buf_in_inx; +static atomic_t gdb_buf_in_cnt; +static int gdb_buf_out_inx; + +struct async_struct *gdb_async_info; +static int gdb_async_irq; + +#define outb_px(a,b) outb_p(b,a) + +static void program_uart(struct async_struct *info); +static void write_char(struct async_struct *info, int chr); +/* + * Get a byte from the hardware data buffer and return it + */ +static int +read_data_bfr(struct async_struct *info) +{ + char it = inb_p(info->port + UART_LSR); + + if (it & UART_LSR_DR) + return (inb_p(info->port + UART_RX)); + /* + * If we have a framing error assume somebody messed with + * our uart. Reprogram it and send '-' both ways... + */ + if (it & 0xc) { + program_uart(info); + write_char(info, '-'); + return ('-'); + } + return (-1); + +} /* read_data_bfr */ + +/* + * Get a char if available, return -1 if nothing available. + * Empty the receive buffer first, then look at the interface hardware. + + * Locking here is a bit of a problem. We MUST not lock out communication + * if we are trying to talk to gdb about a kgdb entry. ON the other hand + * we can loose chars in the console pass thru if we don't lock. It is also + * possible that we could hold the lock or be waiting for it when kgdb + * NEEDS to talk. Since kgdb locks down the world, it does not need locks. + * We do, of course have possible issues with interrupting a uart operation, + * but we will just depend on the uart status to help keep that straight. + + */ +static spinlock_t uart_interrupt_lock = SPIN_LOCK_UNLOCKED; +#ifdef CONFIG_SMP +extern spinlock_t kgdb_spinlock; +#endif + +static int +read_char(struct async_struct *info) +{ + int chr; + unsigned long flags; + local_irq_save(flags); +#ifdef CONFIG_SMP + if (!spin_is_locked(&kgdb_spinlock)) { + spin_lock(&uart_interrupt_lock); + } +#endif + if (atomic_read(&gdb_buf_in_cnt) != 0) { /* intr routine has q'd chars */ + chr = gdb_buf[gdb_buf_out_inx++]; + gdb_buf_out_inx &= (GDB_BUF_SIZE - 1); + atomic_dec(&gdb_buf_in_cnt); + } else { + chr = read_data_bfr(info); + } +#ifdef CONFIG_SMP + if (!spin_is_locked(&kgdb_spinlock)) { + spin_unlock(&uart_interrupt_lock); + } +#endif + local_irq_restore(flags); + return (chr); +} + +/* + * Wait until the interface can accept a char, then write it. + */ +static void +write_char(struct async_struct *info, int chr) +{ + while (!(inb_p(info->port + UART_LSR) & UART_LSR_THRE)) ; + + outb_p(chr, info->port + UART_TX); + +} /* write_char */ + +/* + * Mostly we don't need a spinlock, but since the console goes + * thru here with interrutps on, well, we need to catch those + * chars. + */ +/* + * This is the receiver interrupt routine for the GDB stub. + * It will receive a limited number of characters of input + * from the gdb host machine and save them up in a buffer. + * + * When the gdb stub routine tty_getDebugChar() is called it + * draws characters out of the buffer until it is empty and + * then reads directly from the serial port. + * + * We do not attempt to write chars from the interrupt routine + * since the stubs do all of that via tty_putDebugChar() which + * writes one byte after waiting for the interface to become + * ready. + * + * The debug stubs like to run with interrupts disabled since, + * after all, they run as a consequence of a breakpoint in + * the kernel. + * + * Perhaps someone who knows more about the tty driver than I + * care to learn can make this work for any low level serial + * driver. + */ +static irqreturn_t +gdb_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct async_struct *info; + unsigned long flags; + + info = gdb_async_info; + if (!info || !info->tty || irq != gdb_async_irq) + return IRQ_NONE; + + local_irq_save(flags); + spin_lock(&uart_interrupt_lock); + do { + int chr = read_data_bfr(info); + intprintk(("Debug char on int: %x hex\n", chr)); + if (chr < 0) + continue; + + if (chr == 3) { /* Ctrl-C means remote interrupt */ + BREAKPOINT; + continue; + } + + if (atomic_read(&gdb_buf_in_cnt) >= GDB_BUF_SIZE) { + /* buffer overflow tosses early char */ + read_char(info); + } + gdb_buf[gdb_buf_in_inx++] = chr; + gdb_buf_in_inx &= (GDB_BUF_SIZE - 1); + } while (inb_p(info->port + UART_IIR) & UART_IIR_RDI); + spin_unlock(&uart_interrupt_lock); + local_irq_restore(flags); + return IRQ_HANDLED; +} /* gdb_interrupt */ + +/* + * Just a NULL routine for testing. + */ +void +gdb_null(void) +{ +} /* gdb_null */ + +/* These structure are filled in with values defined in asm/kgdb_local.h + */ +static struct serial_state state = SB_STATE; +static struct async_struct local_info = SB_INFO; +static int ok_to_enable_ints = 0; +static void kgdb_enable_ints_now(void); + +extern char *kgdb_version; +/* + * Hook an IRQ for KGDB. + * + * This routine is called from tty_putDebugChar, below. + */ +static int ints_disabled = 1; +int +gdb_hook_interrupt(struct async_struct *info, int verb) +{ + struct serial_state *state = info->state; + unsigned long flags; + int port; +#ifdef TEST_EXISTANCE + int scratch, scratch2; +#endif + + /* The above fails if memory managment is not set up yet. + * Rather than fail the set up, just keep track of the fact + * and pick up the interrupt thing later. + */ + gdb_async_info = info; + port = gdb_async_info->port; + gdb_async_irq = state->irq; + if (verb) { + printk("kgdb %s : port =%x, IRQ=%d, divisor =%d\n", + kgdb_version, + port, + gdb_async_irq, gdb_async_info->state->custom_divisor); + } + local_irq_save(flags); +#ifdef TEST_EXISTANCE + /* Existance test */ + /* Should not need all this, but just in case.... */ + + scratch = inb_p(port + UART_IER); + outb_px(port + UART_IER, 0); + outb_px(0xff, 0x080); + scratch2 = inb_p(port + UART_IER); + outb_px(port + UART_IER, scratch); + if (scratch2) { + printk + ("gdb_hook_interrupt: Could not clear IER, not a UART!\n"); + local_irq_restore(flags); + return 1; /* We failed; there's nothing here */ + } + scratch2 = inb_p(port + UART_LCR); + outb_px(port + UART_LCR, 0xBF); /* set up for StarTech test */ + outb_px(port + UART_EFR, 0); /* EFR is the same as FCR */ + outb_px(port + UART_LCR, 0); + outb_px(port + UART_FCR, UART_FCR_ENABLE_FIFO); + scratch = inb_p(port + UART_IIR) >> 6; + if (scratch == 1) { + printk("gdb_hook_interrupt: Undefined UART type!" + " Not a UART! \n"); + local_irq_restore(flags); + return 1; + } else { + dbprintk(("gdb_hook_interrupt: UART type " + "is %d where 0=16450, 2=16550 3=16550A\n", scratch)); + } + scratch = inb_p(port + UART_MCR); + outb_px(port + UART_MCR, UART_MCR_LOOP | scratch); + outb_px(port + UART_MCR, UART_MCR_LOOP | 0x0A); + scratch2 = inb_p(port + UART_MSR) & 0xF0; + outb_px(port + UART_MCR, scratch); + if (scratch2 != 0x90) { + printk("gdb_hook_interrupt: " + "Loop back test failed! Not a UART!\n"); + local_irq_restore(flags); + return scratch2 + 1000; /* force 0 to fail */ + } +#endif /* test existance */ + program_uart(info); + local_irq_restore(flags); + + return (0); + +} /* gdb_hook_interrupt */ + +static void +program_uart(struct async_struct *info) +{ + int port = info->port; + + (void) inb_p(port + UART_RX); + outb_px(port + UART_IER, 0); + + (void) inb_p(port + UART_RX); /* serial driver comments say */ + (void) inb_p(port + UART_IIR); /* this clears the interrupt regs */ + (void) inb_p(port + UART_MSR); + outb_px(port + UART_LCR, UART_LCR_WLEN8 | UART_LCR_DLAB); + outb_px(port + UART_DLL, info->state->custom_divisor & 0xff); /* LS */ + outb_px(port + UART_DLM, info->state->custom_divisor >> 8); /* MS */ + outb_px(port + UART_MCR, info->MCR); + + outb_px(port + UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1 | UART_FCR_CLEAR_XMIT | UART_FCR_CLEAR_RCVR); /* set fcr */ + outb_px(port + UART_LCR, UART_LCR_WLEN8); /* reset DLAB */ + outb_px(port + UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1); /* set fcr */ + if (!ints_disabled) { + intprintk(("KGDB: Sending %d to port %x offset %d\n", + gdb_async_info->IER, + (int) gdb_async_info->port, UART_IER)); + outb_px(gdb_async_info->port + UART_IER, gdb_async_info->IER); + } + return; +} + +/* + * tty_getDebugChar + * + * This is a GDB stub routine. It waits for a character from the + * serial interface and then returns it. If there is no serial + * interface connection then it returns a bogus value which will + * almost certainly cause the system to hang. In the + */ +int kgdb_in_isr = 0; +int kgdb_in_lsr = 0; +extern spinlock_t kgdb_spinlock; + +/* Caller takes needed protections */ + +int +tty_getDebugChar(void) +{ + volatile int chr, dum, time, end_time; + + dbprintk(("tty_getDebugChar(port %x): ", gdb_async_info->port)); + + if (gdb_async_info == NULL) { + gdb_hook_interrupt(&local_info, 0); + } + /* + * This trick says if we wait a very long time and get + * no char, return the -1 and let the upper level deal + * with it. + */ + rdtsc(dum, time); + end_time = time + 2; + while (((chr = read_char(gdb_async_info)) == -1) && + (end_time - time) > 0) { + rdtsc(dum, time); + }; + /* + * This covers our butts if some other code messes with + * our uart, hay, it happens :o) + */ + if (chr == -1) + program_uart(gdb_async_info); + + dbprintk(("%c\n", chr > ' ' && chr < 0x7F ? chr : ' ')); + return (chr); + +} /* tty_getDebugChar */ + +static int count = 3; +static spinlock_t one_at_atime = SPIN_LOCK_UNLOCKED; + +static int __init +kgdb_enable_ints(void) +{ + if (kgdboe) { + return 0; + } + if (gdb_async_info == NULL) { + gdb_hook_interrupt(&local_info, 1); + } + ok_to_enable_ints = 1; + kgdb_enable_ints_now(); +#ifdef CONFIG_KGDB_USER_CONSOLE + kgdb_console_finit(); +#endif + return 0; +} + +#ifdef CONFIG_SERIAL_8250 +void shutdown_for_kgdb(struct async_struct *gdb_async_info); +#endif + +#ifdef CONFIG_DISCONTIGMEM +static inline int kgdb_mem_init_done(void) +{ + return highmem_start_page != NULL; +} +#else +static inline int kgdb_mem_init_done(void) +{ + return max_mapnr != 0; +} +#endif + +static void +kgdb_enable_ints_now(void) +{ + if (!spin_trylock(&one_at_atime)) + return; + if (!ints_disabled) + goto exit; + if (kgdb_mem_init_done() && + ints_disabled) { /* don't try till mem init */ +#ifdef CONFIG_SERIAL_8250 + /* + * The ifdef here allows the system to be configured + * without the serial driver. + * Don't make it a module, however, it will steal the port + */ + shutdown_for_kgdb(gdb_async_info); +#endif + ints_disabled = request_irq(gdb_async_info->state->irq, + gdb_interrupt, + IRQ_T(gdb_async_info), + "KGDB-stub", NULL); + intprintk(("KGDB: request_irq returned %d\n", ints_disabled)); + } + if (!ints_disabled) { + intprintk(("KGDB: Sending %d to port %x offset %d\n", + gdb_async_info->IER, + (int) gdb_async_info->port, UART_IER)); + outb_px(gdb_async_info->port + UART_IER, gdb_async_info->IER); + } + exit: + spin_unlock(&one_at_atime); +} + +/* + * tty_putDebugChar + * + * This is a GDB stub routine. It waits until the interface is ready + * to transmit a char and then sends it. If there is no serial + * interface connection then it simply returns to its caller, having + * pretended to send the char. Caller takes needed protections. + */ +void +tty_putDebugChar(int chr) +{ + dbprintk(("tty_putDebugChar(port %x): chr=%02x '%c', ints_on=%d\n", + gdb_async_info->port, + chr, + chr > ' ' && chr < 0x7F ? chr : ' ', ints_disabled ? 0 : 1)); + + if (gdb_async_info == NULL) { + gdb_hook_interrupt(&local_info, 0); + } + + write_char(gdb_async_info, chr); /* this routine will wait */ + count = (chr == '#') ? 0 : count + 1; + if ((count == 2)) { /* try to enable after */ + if (ints_disabled & ok_to_enable_ints) + kgdb_enable_ints_now(); /* try to enable after */ + + /* We do this a lot because, well we really want to get these + * interrupts. The serial driver will clear these bits when it + * initializes the chip. Every thing else it does is ok, + * but this. + */ + if (!ints_disabled) { + outb_px(gdb_async_info->port + UART_IER, + gdb_async_info->IER); + } + } + +} /* tty_putDebugChar */ + +/* + * This does nothing for the serial port, since it doesn't buffer. + */ + +void tty_flushDebugChar(void) +{ +} + +module_init(kgdb_enable_ints); --- linux-2.6.6/arch/i386/lib/Makefile 2004-04-03 20:39:10.000000000 -0800 +++ 25/arch/i386/lib/Makefile 2004-05-10 01:19:06.873694096 -0700 @@ -9,3 +9,4 @@ lib-y = checksum.o delay.o \ lib-$(CONFIG_X86_USE_3DNOW) += mmx.o lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o +lib-$(CONFIG_KGDB) += kgdb_serial.o --- linux-2.6.6/arch/i386/mach-es7000/es7000.c 2004-02-03 20:42:34.000000000 -0800 +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,279 +0,0 @@ -/* - * Written by: Garry Forsgren, Unisys Corporation - * Natalie Protasevich, Unisys Corporation - * This file contains the code to configure and interface - * with Unisys ES7000 series hardware system manager. - * - * Copyright (c) 2003 Unisys Corporation. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Unisys Corporation, Township Line & Union Meeting - * Roads-A, Unisys Way, Blue Bell, Pennsylvania, 19424, or: - * - * http://www.unisys.com - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "es7000.h" - -/* - * ES7000 Globals - */ - -volatile unsigned long *psai = NULL; -struct mip_reg *mip_reg; -struct mip_reg *host_reg; -int mip_port; -unsigned long mip_addr, host_addr; - -/* - * Parse the OEM Table - */ - -void __init -parse_unisys_oem (char *oemptr, int oem_entries) -{ - int i; - int success = 0; - unsigned char type, size; - unsigned long val; - char *tp = NULL; - struct psai *psaip = NULL; - struct mip_reg_info *mi; - struct mip_reg *host, *mip; - - tp = oemptr; - - tp += 8; - - for (i=0; i <= oem_entries; i++) { - type = *tp++; - size = *tp++; - tp -= 2; - switch (type) { - case MIP_REG: - mi = (struct mip_reg_info *)tp; - val = MIP_RD_LO(mi->host_reg); - host_addr = val; - host = (struct mip_reg *)val; - host_reg = __va(host); - val = MIP_RD_LO(mi->mip_reg); - mip_addr = val; - mip = (struct mip_reg *)val; - mip_reg = __va(mip); - Dprintk("es7000_mipcfg: host_reg = 0x%lx \n", - (unsigned long)host_reg); - Dprintk("es7000_mipcfg: mip_reg = 0x%lx \n", - (unsigned long)mip_reg); - success++; - break; - case MIP_PSAI_REG: - psaip = (struct psai *)tp; - if (tp != NULL) { - if (psaip->addr) - psai = __va(psaip->addr); - else - psai = NULL; - success++; - } - break; - default: - break; - } - if (i == 6) break; - tp += size; - } - - if (success < 2) { - printk("\nNo ES7000 found.\n"); - es7000_plat = 0; - } else { - printk("\nEnabling ES7000 specific features...\n"); - es7000_plat = 1; - } - return; -} - -int __init -find_unisys_acpi_oem_table(unsigned long *oem_addr, int *length) -{ - struct acpi_table_rsdp *rsdp = NULL; - unsigned long rsdp_phys = 0; - struct acpi_table_header *header = NULL; - int i; - struct acpi_table_sdt sdt; - - rsdp_phys = acpi_find_rsdp(); - rsdp = __va(rsdp_phys); - if (rsdp->rsdt_address) { - struct acpi_table_rsdt *mapped_rsdt = NULL; - sdt.pa = rsdp->rsdt_address; - - header = (struct acpi_table_header *) - __acpi_map_table(sdt.pa, sizeof(struct acpi_table_header)); - if (!header) - return -ENODEV; - - sdt.count = (header->length - sizeof(struct acpi_table_header)) >> 3; - mapped_rsdt = (struct acpi_table_rsdt *) - __acpi_map_table(sdt.pa, header->length); - if (!mapped_rsdt) - return -ENODEV; - - header = &mapped_rsdt->header; - - for (i = 0; i < sdt.count; i++) - sdt.entry[i].pa = (unsigned long) mapped_rsdt->entry[i]; - }; - for (i = 0; i < sdt.count; i++) { - - header = (struct acpi_table_header *) - __acpi_map_table(sdt.entry[i].pa, - sizeof(struct acpi_table_header)); - if (!header) - continue; - if (!strncmp((char *) &header->signature, "OEM1", 4)) { - if (!strncmp((char *) &header->oem_id, "UNISYS", 6)) { - void *addr; - struct oem_table *t; - acpi_table_print(header, sdt.entry[i].pa); - t = (struct oem_table *) __acpi_map_table(sdt.entry[i].pa, header->length); - addr = (void *) __acpi_map_table(t->OEMTableAddr, t->OEMTableSize); - *length = header->length; - *oem_addr = (unsigned long) addr; - return 0; - } - } - } - printk("ES7000: did not find Unisys ACPI OEM table!\n"); - return -1; -} - -static void -es7000_spin(int n) -{ - int i = 0; - - while (i++ < n) - rep_nop(); -} - -static int __init -es7000_mip_write(struct mip_reg *mip_reg) -{ - int status = 0; - int spin; - - spin = MIP_SPIN; - while (((unsigned long long)host_reg->off_38 & - (unsigned long long)MIP_VALID) != 0) { - if (--spin <= 0) { - printk("es7000_mip_write: Timeout waiting for Host Valid Flag"); - return -1; - } - es7000_spin(MIP_SPIN); - } - - memcpy(host_reg, mip_reg, sizeof(struct mip_reg)); - outb(1, mip_port); - - spin = MIP_SPIN; - - while (((unsigned long long)mip_reg->off_38 & - (unsigned long long)MIP_VALID) == 0) { - if (--spin <= 0) { - printk("es7000_mip_write: Timeout waiting for MIP Valid Flag"); - return -1; - } - es7000_spin(MIP_SPIN); - } - - status = ((unsigned long long)mip_reg->off_0 & - (unsigned long long)0xffff0000000000) >> 48; - mip_reg->off_38 = ((unsigned long long)mip_reg->off_38 & - (unsigned long long)~MIP_VALID); - return status; -} - -int -es7000_start_cpu(int cpu, unsigned long eip) -{ - unsigned long vect = 0, psaival = 0; - - if (psai == NULL) - return -1; - - vect = ((unsigned long)__pa(eip)/0x1000) << 16; - psaival = (0x1000000 | vect | cpu); - - while (*psai & 0x1000000) - ; - - *psai = psaival; - - return 0; - -} - -int -es7000_stop_cpu(int cpu) -{ - int startup; - - if (psai == NULL) - return -1; - - startup= (0x1000000 | cpu); - - while ((*psai & 0xff00ffff) != startup) - ; - - startup = (*psai & 0xff0000) >> 16; - *psai &= 0xffffff; - - return 0; - -} - -void __init -es7000_sw_apic() -{ - if (es7000_plat) { - int mip_status; - struct mip_reg es7000_mip_reg; - - printk("ES7000: Enabling APIC mode.\n"); - memset(&es7000_mip_reg, 0, sizeof(struct mip_reg)); - es7000_mip_reg.off_0 = MIP_SW_APIC; - es7000_mip_reg.off_38 = (MIP_VALID); - while ((mip_status = es7000_mip_write(&es7000_mip_reg)) != 0) - printk("es7000_sw_apic: command failed, status = %x\n", - mip_status); - return; - } -} --- linux-2.6.6/arch/i386/mach-es7000/es7000.h 2003-06-16 22:32:20.000000000 -0700 +++ 25/arch/i386/mach-es7000/es7000.h 2004-05-10 01:19:52.008832512 -0700 @@ -30,6 +30,7 @@ #define MIP_BUSY 1 #define MIP_SPIN 0xf0000 #define MIP_VALID 0x0100000000000000 +#define MIP_PORT(VALUE) ((VALUE >> 32) & 0xffff) #define MIP_RD_LO(VALUE) (VALUE & 0xffffffff) @@ -103,7 +104,7 @@ struct mip_reg { #define MIP_SW_APIC 0x1020b #define MIP_FUNC(VALUE) (VALUE & 0xff) -extern void parse_unisys_oem (char *oemptr, int oem_entries); +extern int parse_unisys_oem (char *oemptr, int oem_entries); extern int find_unisys_acpi_oem_table(unsigned long *oem_addr, int *length); extern int es7000_start_cpu(int cpu, unsigned long eip); extern void es7000_sw_apic(void); --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/arch/i386/mach-es7000/es7000plat.c 2004-05-10 01:19:52.009832360 -0700 @@ -0,0 +1,280 @@ +/* + * Written by: Garry Forsgren, Unisys Corporation + * Natalie Protasevich, Unisys Corporation + * This file contains the code to configure and interface + * with Unisys ES7000 series hardware system manager. + * + * Copyright (c) 2003 Unisys Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Unisys Corporation, Township Line & Union Meeting + * Roads-A, Unisys Way, Blue Bell, Pennsylvania, 19424, or: + * + * http://www.unisys.com + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "es7000.h" + +/* + * ES7000 Globals + */ + +volatile unsigned long *psai = NULL; +struct mip_reg *mip_reg; +struct mip_reg *host_reg; +int mip_port; +unsigned long mip_addr, host_addr; + +/* + * Parse the OEM Table + */ + +int __init +parse_unisys_oem (char *oemptr, int oem_entries) +{ + int i; + int success = 0; + unsigned char type, size; + unsigned long val; + char *tp = NULL; + struct psai *psaip = NULL; + struct mip_reg_info *mi; + struct mip_reg *host, *mip; + + tp = oemptr; + + tp += 8; + + for (i=0; i <= oem_entries; i++) { + type = *tp++; + size = *tp++; + tp -= 2; + switch (type) { + case MIP_REG: + mi = (struct mip_reg_info *)tp; + val = MIP_RD_LO(mi->host_reg); + host_addr = val; + host = (struct mip_reg *)val; + host_reg = __va(host); + val = MIP_RD_LO(mi->mip_reg); + mip_port = MIP_PORT(mi->mip_info); + mip_addr = val; + mip = (struct mip_reg *)val; + mip_reg = __va(mip); + Dprintk("es7000_mipcfg: host_reg = 0x%lx \n", + (unsigned long)host_reg); + Dprintk("es7000_mipcfg: mip_reg = 0x%lx \n", + (unsigned long)mip_reg); + success++; + break; + case MIP_PSAI_REG: + psaip = (struct psai *)tp; + if (tp != NULL) { + if (psaip->addr) + psai = __va(psaip->addr); + else + psai = NULL; + success++; + } + break; + default: + break; + } + if (i == 6) break; + tp += size; + } + + if (success < 2) { + printk("\nNo ES7000 found.\n"); + es7000_plat = 0; + } else { + printk("\nEnabling ES7000 specific features...\n"); + es7000_plat = 1; + } + return es7000_plat; +} + +int __init +find_unisys_acpi_oem_table(unsigned long *oem_addr, int *length) +{ + struct acpi_table_rsdp *rsdp = NULL; + unsigned long rsdp_phys = 0; + struct acpi_table_header *header = NULL; + int i; + struct acpi_table_sdt sdt; + + rsdp_phys = acpi_find_rsdp(); + rsdp = __va(rsdp_phys); + if (rsdp->rsdt_address) { + struct acpi_table_rsdt *mapped_rsdt = NULL; + sdt.pa = rsdp->rsdt_address; + + header = (struct acpi_table_header *) + __acpi_map_table(sdt.pa, sizeof(struct acpi_table_header)); + if (!header) + return -ENODEV; + + sdt.count = (header->length - sizeof(struct acpi_table_header)) >> 3; + mapped_rsdt = (struct acpi_table_rsdt *) + __acpi_map_table(sdt.pa, header->length); + if (!mapped_rsdt) + return -ENODEV; + + header = &mapped_rsdt->header; + + for (i = 0; i < sdt.count; i++) + sdt.entry[i].pa = (unsigned long) mapped_rsdt->entry[i]; + }; + for (i = 0; i < sdt.count; i++) { + + header = (struct acpi_table_header *) + __acpi_map_table(sdt.entry[i].pa, + sizeof(struct acpi_table_header)); + if (!header) + continue; + if (!strncmp((char *) &header->signature, "OEM1", 4)) { + if (!strncmp((char *) &header->oem_id, "UNISYS", 6)) { + void *addr; + struct oem_table *t; + acpi_table_print(header, sdt.entry[i].pa); + t = (struct oem_table *) __acpi_map_table(sdt.entry[i].pa, header->length); + addr = (void *) __acpi_map_table(t->OEMTableAddr, t->OEMTableSize); + *length = header->length; + *oem_addr = (unsigned long) addr; + return 0; + } + } + } + printk("ES7000: did not find Unisys ACPI OEM table!\n"); + return -1; +} + +static void +es7000_spin(int n) +{ + int i = 0; + + while (i++ < n) + rep_nop(); +} + +static int __init +es7000_mip_write(struct mip_reg *mip_reg) +{ + int status = 0; + int spin; + + spin = MIP_SPIN; + while (((unsigned long long)host_reg->off_38 & + (unsigned long long)MIP_VALID) != 0) { + if (--spin <= 0) { + printk("es7000_mip_write: Timeout waiting for Host Valid Flag"); + return -1; + } + es7000_spin(MIP_SPIN); + } + + memcpy(host_reg, mip_reg, sizeof(struct mip_reg)); + outb(1, mip_port); + + spin = MIP_SPIN; + + while (((unsigned long long)mip_reg->off_38 & + (unsigned long long)MIP_VALID) == 0) { + if (--spin <= 0) { + printk("es7000_mip_write: Timeout waiting for MIP Valid Flag"); + return -1; + } + es7000_spin(MIP_SPIN); + } + + status = ((unsigned long long)mip_reg->off_0 & + (unsigned long long)0xffff0000000000) >> 48; + mip_reg->off_38 = ((unsigned long long)mip_reg->off_38 & + (unsigned long long)~MIP_VALID); + return status; +} + +int +es7000_start_cpu(int cpu, unsigned long eip) +{ + unsigned long vect = 0, psaival = 0; + + if (psai == NULL) + return -1; + + vect = ((unsigned long)__pa(eip)/0x1000) << 16; + psaival = (0x1000000 | vect | cpu); + + while (*psai & 0x1000000) + ; + + *psai = psaival; + + return 0; + +} + +int +es7000_stop_cpu(int cpu) +{ + int startup; + + if (psai == NULL) + return -1; + + startup= (0x1000000 | cpu); + + while ((*psai & 0xff00ffff) != startup) + ; + + startup = (*psai & 0xff0000) >> 16; + *psai &= 0xffffff; + + return 0; + +} + +void __init +es7000_sw_apic() +{ + if (es7000_plat) { + int mip_status; + struct mip_reg es7000_mip_reg; + + printk("ES7000: Enabling APIC mode.\n"); + memset(&es7000_mip_reg, 0, sizeof(struct mip_reg)); + es7000_mip_reg.off_0 = MIP_SW_APIC; + es7000_mip_reg.off_38 = (MIP_VALID); + while ((mip_status = es7000_mip_write(&es7000_mip_reg)) != 0) + printk("es7000_sw_apic: command failed, status = %x\n", + mip_status); + return; + } +} --- linux-2.6.6/arch/i386/mach-es7000/Makefile 2004-04-03 20:39:10.000000000 -0800 +++ 25/arch/i386/mach-es7000/Makefile 2004-05-10 01:19:52.010832208 -0700 @@ -2,4 +2,5 @@ # Makefile for the linux kernel. # -obj-y := setup.o topology.o es7000.o +obj-$(CONFIG_X86_ES7000) := es7000plat.o +obj-$(CONFIG_X86_GENERICARCH) := es7000plat.o --- linux-2.6.6/arch/i386/mach-es7000/setup.c 2004-05-09 21:07:23.000000000 -0700 +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,106 +0,0 @@ -/* - * Machine specific setup for es7000 - */ - -#include -#include -#include -#include -#include -#include -#include - -/** - * pre_intr_init_hook - initialisation prior to setting up interrupt vectors - * - * Description: - * Perform any necessary interrupt initialisation prior to setting up - * the "ordinary" interrupt call gates. For legacy reasons, the ISA - * interrupts should be initialised here if the machine emulates a PC - * in any way. - **/void __init pre_intr_init_hook(void) -{ - init_ISA_irqs(); -} - -/* - * IRQ2 is cascade interrupt to second interrupt controller - */ -static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL}; - -/** - * intr_init_hook - post gate setup interrupt initialisation - * - * Description: - * Fill in any interrupts that may have been left out by the general - * init_IRQ() routine. interrupts having to do with the machine rather - * than the devices on the I/O bus (like APIC interrupts in intel MP - * systems) are started here. - **/ -void __init intr_init_hook(void) -{ -#ifdef CONFIG_X86_LOCAL_APIC - apic_intr_init(); -#endif - - if (!acpi_ioapic) - setup_irq(2, &irq2); -} - -/** - * pre_setup_arch_hook - hook called prior to any setup_arch() execution - * - * Description: - * generally used to activate any machine specific identification - * routines that may be needed before setup_arch() runs. On VISWS - * this is used to get the board revision and type. - **/ -void __init pre_setup_arch_hook(void) -{ -} - -/** - * trap_init_hook - initialise system specific traps - * - * Description: - * Called as the final act of trap_init(). Used in VISWS to initialise - * the various board specific APIC traps. - **/ -void __init trap_init_hook(void) -{ -} - -static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL}; - -/** - * time_init_hook - do any specific initialisations for the system timer. - * - * Description: - * Must plug the system timer interrupt source at HZ into the IRQ listed - * in irq_vectors.h:TIMER_IRQ - **/ -void __init time_init_hook(void) -{ - setup_irq(0, &irq0); -} - -#ifdef CONFIG_MCA -/** - * mca_nmi_hook - hook into MCA specific NMI chain - * - * Description: - * The MCA (Microchannel Arcitecture) has an NMI chain for NMI sources - * along the MCA bus. Use this to hook into that chain if you will need - * it. - **/ -void __init mca_nmi_hook(void) -{ - /* If I recall correctly, there's a whole bunch of other things that - * we can do to check for NMI problems, but that's all I know about - * at the moment. - */ - - printk("NMI generated from unknown source!\n"); -} - -#endif --- linux-2.6.6/arch/i386/mach-es7000/topology.c 2004-02-17 20:48:42.000000000 -0800 +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,64 +0,0 @@ -/* - * arch/i386/mach-generic/topology.c - Populate driverfs with topology information - * - * Written by: Matthew Dobson, IBM Corporation - * Original Code: Paul Dorwin, IBM Corporation, Patrick Mochel, OSDL - * - * Copyright (C) 2002, IBM Corp. - * - * All rights reserved. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Send feedback to - */ -#include -#include -#include - -struct i386_cpu cpu_devices[NR_CPUS]; - -#ifdef CONFIG_NUMA -#include -#include - -struct i386_node node_devices[MAX_NUMNODES]; - -static int __init topology_init(void) -{ - int i; - - for (i = 0; i < num_online_nodes(); i++) - arch_register_node(i); - for (i = 0; i < NR_CPUS; i++) - if (cpu_possible(i)) arch_register_cpu(i); - return 0; -} - -#else /* !CONFIG_NUMA */ - -static int __init topology_init(void) -{ - int i; - - for (i = 0; i < NR_CPUS; i++) - if (cpu_possible(i)) arch_register_cpu(i); - return 0; -} - -#endif /* CONFIG_NUMA */ - -subsys_initcall(topology_init); --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/arch/i386/mach-generic/es7000.c 2004-05-10 01:19:52.011832056 -0700 @@ -0,0 +1,28 @@ +/* + * APIC driver for the Unisys ES7000 chipset. + */ +#define APIC_DEFINITION 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static __init int probe_es7000(void) +{ + /* probed later in mptable/ACPI hooks */ + return 0; +} + +struct genapic apic_es7000 = APIC_INIT("es7000", probe_es7000); --- linux-2.6.6/arch/i386/mach-generic/Makefile 2003-06-14 12:18:22.000000000 -0700 +++ 25/arch/i386/mach-generic/Makefile 2004-05-10 01:19:52.011832056 -0700 @@ -4,15 +4,4 @@ EXTRA_CFLAGS += -I../kernel -obj-y := probe.o summit.o bigsmp.o default.o - - -# -# Makefile for the generic architecture -# - -EXTRA_CFLAGS += -I../kernel - -obj-y := probe.o summit.o bigsmp.o default.o - - +obj-y := probe.o summit.o bigsmp.o es7000.o default.o ../mach-es7000/ --- linux-2.6.6/arch/i386/mach-generic/probe.c 2003-08-22 19:23:40.000000000 -0700 +++ 25/arch/i386/mach-generic/probe.c 2004-05-10 01:19:52.012831904 -0700 @@ -17,6 +17,7 @@ extern struct genapic apic_summit; extern struct genapic apic_bigsmp; +extern struct genapic apic_es7000; extern struct genapic apic_default; struct genapic *genapic = &apic_default; @@ -24,6 +25,7 @@ struct genapic *genapic = &apic_default; struct genapic *apic_probe[] __initdata = { &apic_summit, &apic_bigsmp, + &apic_es7000, &apic_default, /* must be last */ NULL, }; --- linux-2.6.6/arch/i386/mach-visws/traps.c 2003-06-14 12:18:25.000000000 -0700 +++ 25/arch/i386/mach-visws/traps.c 2004-05-10 01:19:35.829292176 -0700 @@ -8,7 +8,6 @@ #include #include -#include #include #include #include "cobalt.h" --- linux-2.6.6/arch/i386/mach-voyager/voyager_basic.c 2003-10-08 15:07:08.000000000 -0700 +++ 25/arch/i386/mach-voyager/voyager_basic.c 2004-05-10 01:19:35.830292024 -0700 @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include --- linux-2.6.6/arch/i386/mach-voyager/voyager_smp.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/i386/mach-voyager/voyager_smp.c 2004-05-10 01:19:49.905152320 -0700 @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -1106,6 +1105,9 @@ smp_call_function (void (*func) (void *i if (!mask) return 0; + /* Can deadlock when called with interrupts disabled */ + WARN_ON(irqs_disabled()); + data.func = func; data.info = info; data.started = mask; --- linux-2.6.6/arch/i386/mach-voyager/voyager_thread.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/i386/mach-voyager/voyager_thread.c 2004-05-10 01:19:35.832291720 -0700 @@ -28,7 +28,6 @@ #include #include #include -#include #include #include --- linux-2.6.6/arch/i386/Makefile 2004-05-09 21:07:22.000000000 -0700 +++ 25/arch/i386/Makefile 2004-05-10 01:19:52.012831904 -0700 @@ -19,7 +19,7 @@ LDFLAGS := -m elf_i386 OBJCOPYFLAGS := -O binary -R .note -R .comment -S LDFLAGS_vmlinux := -CFLAGS += -pipe +CFLAGS += -pipe -msoft-float # prevent gcc from keeping the stack 16 byte aligned CFLAGS += $(call check_gcc,-mpreferred-stack-boundary=2,) @@ -92,11 +92,15 @@ core-$(CONFIG_X86_GENERICARCH) += arch/i # ES7000 subarch support mflags-$(CONFIG_X86_ES7000) := -Iinclude/asm-i386/mach-es7000 -mcore-$(CONFIG_X86_ES7000) := mach-es7000 +mcore-$(CONFIG_X86_ES7000) := mach-default +core-$(CONFIG_X86_ES7000) := arch/i386/mach-es7000/ # default subarch .h files mflags-y += -Iinclude/asm-i386/mach-default +mflags-$(CONFIG_KGDB) += -gdwarf-2 +mflags-$(CONFIG_KGDB_MORE) += $(shell echo $(CONFIG_KGDB_OPTIONS) | sed -e 's/"//g') + head-y := arch/i386/kernel/head.o arch/i386/kernel/init_task.o libs-y += arch/i386/lib/ --- linux-2.6.6/arch/i386/mm/fault.c 2003-12-17 21:20:01.000000000 -0800 +++ 25/arch/i386/mm/fault.c 2004-05-10 01:19:35.832291720 -0700 @@ -24,7 +24,6 @@ #include #include -#include #include #include @@ -403,6 +402,12 @@ no_context: * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice. */ +#ifdef CONFIG_KGDB + if (!user_mode(regs)){ + kgdb_handle_exception(14,SIGBUS, error_code, regs); + return; + } +#endif bust_spinlocks(1); --- linux-2.6.6/arch/i386/mm/hugetlbpage.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/i386/mm/hugetlbpage.c 2004-05-10 01:19:56.316177696 -0700 @@ -15,7 +15,6 @@ #include #include #include -#include #include #include @@ -264,8 +263,9 @@ int hugetlb_prefault(struct address_spac goto out; } ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC); - unlock_page(page); - if (ret) { + if (! ret) { + unlock_page(page); + } else { hugetlb_put_quota(mapping); free_huge_page(page); goto out; --- linux-2.6.6/arch/i386/mm/init.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/i386/mm/init.c 2004-05-10 01:19:35.833291568 -0700 @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include --- linux-2.6.6/arch/i386/mm/ioremap.c 2003-11-23 19:03:00.000000000 -0800 +++ 25/arch/i386/mm/ioremap.c 2004-05-10 01:19:35.834291416 -0700 @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include --- linux-2.6.6/arch/i386/oprofile/op_model_p4.c 2003-08-22 19:23:40.000000000 -0700 +++ 25/arch/i386/oprofile/op_model_p4.c 2004-05-10 01:19:19.786731016 -0700 @@ -382,11 +382,8 @@ static struct p4_event_binding p4_events static unsigned int get_stagger(void) { #ifdef CONFIG_SMP - int cpu; - if (smp_num_siblings > 1) { - cpu = smp_processor_id(); - return (cpu_sibling_map[cpu] > cpu) ? 0 : 1; - } + int cpu = smp_processor_id(); + return (cpu != first_cpu(cpu_sibling_map[cpu])); #endif return 0; } --- linux-2.6.6/arch/ia64/dig/Makefile 2003-06-14 12:18:28.000000000 -0700 +++ 25/arch/ia64/dig/Makefile 2004-05-10 01:19:45.814774152 -0700 @@ -6,4 +6,9 @@ # obj-y := setup.o + +ifndef CONFIG_NUMA +obj-$(CONFIG_IA64_DIG) += topology.o +endif + obj-$(CONFIG_IA64_GENERIC) += machvec.o --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/arch/ia64/dig/topology.c 2004-05-10 01:19:45.814774152 -0700 @@ -0,0 +1,43 @@ +/* + * arch/ia64/dig/topology.c + * Popuate driverfs with topology information. + * Derived entirely from i386/mach-default.c + * Intel Corporation - Ashok Raj + */ +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_PER_CPU(struct ia64_cpu, cpu_devices); + +/* + * First Pass: simply borrowed code for now. Later should hook into + * hotplug notification for node/cpu/memory as applicable + */ + +static int arch_register_cpu(int num) +{ + struct node *parent = NULL; + +#ifdef CONFIG_NUMA + //parent = &node_devices[cpu_to_node(num)].node; +#endif + + return register_cpu(&per_cpu(cpu_devices,num).cpu, num, parent); +} + +static int __init topology_init(void) +{ + int i; + + for_each_cpu(i) { + arch_register_cpu(i); + } + return 0; +} + +subsys_initcall(topology_init); --- linux-2.6.6/arch/ia64/ia32/binfmt_elf32.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/ia64/ia32/binfmt_elf32.c 2004-05-10 01:19:14.238574464 -0700 @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -73,15 +74,13 @@ ia64_elf32_init (struct pt_regs *regs) */ vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); if (vma) { + memset(vma, 0, sizeof(*vma)); vma->vm_mm = current->mm; vma->vm_start = IA32_GDT_OFFSET; vma->vm_end = vma->vm_start + PAGE_SIZE; vma->vm_page_prot = PAGE_SHARED; - vma->vm_flags = VM_READ|VM_MAYREAD; + vma->vm_flags = VM_READ|VM_MAYREAD|VM_RESERVED; vma->vm_ops = &ia32_shared_page_vm_ops; - vma->vm_pgoff = 0; - vma->vm_file = NULL; - vma->vm_private_data = NULL; down_write(¤t->mm->mmap_sem); { insert_vm_struct(current->mm, vma); @@ -95,15 +94,12 @@ ia64_elf32_init (struct pt_regs *regs) */ vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); if (vma) { + memset(vma, 0, sizeof(*vma)); vma->vm_mm = current->mm; vma->vm_start = IA32_LDT_OFFSET; vma->vm_end = vma->vm_start + PAGE_ALIGN(IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE); vma->vm_page_prot = PAGE_SHARED; vma->vm_flags = VM_READ|VM_WRITE|VM_MAYREAD|VM_MAYWRITE; - vma->vm_ops = NULL; - vma->vm_pgoff = 0; - vma->vm_file = NULL; - vma->vm_private_data = NULL; down_write(¤t->mm->mmap_sem); { insert_vm_struct(current->mm, vma); @@ -190,6 +186,7 @@ ia32_setup_arg_pages (struct linux_binpr mpnt->vm_pgoff = 0; mpnt->vm_file = NULL; mpnt->vm_private_data = 0; + mpol_set_vma_default(mpnt); insert_vm_struct(current->mm, mpnt); current->mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT; } --- linux-2.6.6/arch/ia64/ia32/ia32_entry.S 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/ia64/ia32/ia32_entry.S 2004-05-10 01:19:34.916430952 -0700 @@ -350,11 +350,11 @@ ia32_syscall_table: data8 sys_setfsgid /* 16-bit version */ data8 sys_llseek /* 140 */ data8 sys32_getdents - data8 sys32_select + data8 compat_sys_select data8 sys_flock data8 sys32_msync - data8 sys32_readv /* 145 */ - data8 sys32_writev + data8 compat_sys_readv /* 145 */ + data8 compat_sys_writev data8 sys_getsid data8 sys_fdatasync data8 sys32_sysctl --- linux-2.6.6/arch/ia64/ia32/sys_ia32.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/ia64/ia32/sys_ia32.c 2004-05-10 01:19:35.174391736 -0700 @@ -90,58 +90,17 @@ extern unsigned long arch_get_unmapped_a /* XXX make per-mm: */ static DECLARE_MUTEX(ia32_mmap_sem); -static int -nargs (unsigned int arg, char **ap) -{ - unsigned int addr; - int n, err; - - if (!arg) - return 0; - - n = 0; - do { - err = get_user(addr, (unsigned int *)A(arg)); - if (err) - return err; - if (ap) - *ap++ = (char *) A(addr); - arg += sizeof(unsigned int); - n++; - } while (addr); - return n - 1; -} - asmlinkage long -sys32_execve (char *filename, unsigned int argv, unsigned int envp, - struct pt_regs *regs) +sys32_execve (char *name, compat_uptr_t __user *argv, compat_uptr_t __user *envp, struct pt_regs *regs) { + long error; + char *filename; unsigned long old_map_base, old_task_size, tssd; - char **av, **ae; - int na, ne, len; - long r; - - na = nargs(argv, NULL); - if (na < 0) - return na; - ne = nargs(envp, NULL); - if (ne < 0) - return ne; - len = (na + ne + 2) * sizeof(*av); - av = kmalloc(len, GFP_KERNEL); - if (!av) - return -ENOMEM; - ae = av + na + 1; - av[na] = NULL; - ae[ne] = NULL; - - r = nargs(argv, av); - if (r < 0) - goto out; - r = nargs(envp, ae); - if (r < 0) - goto out; + filename = getname(name); + error = PTR_ERR(filename); + if (IS_ERR(filename)) + return error; old_map_base = current->thread.map_base; old_task_size = current->thread.task_size; @@ -153,19 +112,18 @@ sys32_execve (char *filename, unsigned i ia64_set_kr(IA64_KR_IO_BASE, current->thread.old_iob); ia64_set_kr(IA64_KR_TSSD, current->thread.old_k1); - set_fs(KERNEL_DS); - r = sys_execve(filename, av, ae, regs); - if (r < 0) { + error = compat_do_execve(filename, argv, envp, regs); + putname(filename); + + if (error < 0) { /* oops, execve failed, switch back to old values... */ ia64_set_kr(IA64_KR_IO_BASE, IA32_IOBASE); ia64_set_kr(IA64_KR_TSSD, tssd); current->thread.map_base = old_map_base; current->thread.task_size = old_task_size; - set_fs(USER_DS); /* establish new task-size as the address-limit */ } - out: - kfree(av); - return r; + + return error; } int cp_compat_stat(struct kstat *stat, struct compat_stat *ubuf) @@ -818,110 +776,6 @@ out: return error; } -/* - * We can actually return ERESTARTSYS instead of EINTR, but I'd - * like to be certain this leads to no problems. So I return - * EINTR just for safety. - * - * Update: ERESTARTSYS breaks at least the xview clock binary, so - * I'm trying ERESTARTNOHAND which restart only when you want to. - */ -#define MAX_SELECT_SECONDS \ - ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1) -#define ROUND_UP_TIME(x,y) (((x)+(y)-1)/(y)) - -asmlinkage long -sys32_select (int n, fd_set *inp, fd_set *outp, fd_set *exp, struct compat_timeval *tvp32) -{ - fd_set_bits fds; - char *bits; - long timeout; - int ret, size; - - timeout = MAX_SCHEDULE_TIMEOUT; - if (tvp32) { - time_t sec, usec; - - ret = -EFAULT; - if (get_user(sec, &tvp32->tv_sec) || get_user(usec, &tvp32->tv_usec)) - goto out_nofds; - - ret = -EINVAL; - if (sec < 0 || usec < 0) - goto out_nofds; - - if ((unsigned long) sec < MAX_SELECT_SECONDS) { - timeout = ROUND_UP_TIME(usec, 1000000/HZ); - timeout += sec * (unsigned long) HZ; - } - } - - ret = -EINVAL; - if (n < 0) - goto out_nofds; - - if (n > current->files->max_fdset) - n = current->files->max_fdset; - - /* - * We need 6 bitmaps (in/out/ex for both incoming and outgoing), - * since we used fdset we need to allocate memory in units of - * long-words. - */ - ret = -ENOMEM; - size = FDS_BYTES(n); - bits = kmalloc(6 * size, GFP_KERNEL); - if (!bits) - goto out_nofds; - fds.in = (unsigned long *) bits; - fds.out = (unsigned long *) (bits + size); - fds.ex = (unsigned long *) (bits + 2*size); - fds.res_in = (unsigned long *) (bits + 3*size); - fds.res_out = (unsigned long *) (bits + 4*size); - fds.res_ex = (unsigned long *) (bits + 5*size); - - if ((ret = get_fd_set(n, inp, fds.in)) || - (ret = get_fd_set(n, outp, fds.out)) || - (ret = get_fd_set(n, exp, fds.ex))) - goto out; - zero_fd_set(n, fds.res_in); - zero_fd_set(n, fds.res_out); - zero_fd_set(n, fds.res_ex); - - ret = do_select(n, &fds, &timeout); - - if (tvp32 && !(current->personality & STICKY_TIMEOUTS)) { - time_t sec = 0, usec = 0; - if (timeout) { - sec = timeout / HZ; - usec = timeout % HZ; - usec *= (1000000/HZ); - } - if (put_user(sec, &tvp32->tv_sec) || put_user(usec, &tvp32->tv_usec)) { - ret = -EFAULT; - goto out; - } - } - - if (ret < 0) - goto out; - if (!ret) { - ret = -ERESTARTNOHAND; - if (signal_pending(current)) - goto out; - ret = 0; - } - - set_fd_set(n, inp, fds.res_in); - set_fd_set(n, outp, fds.res_out); - set_fd_set(n, exp, fds.res_ex); - -out: - kfree(bits); -out_nofds: - return ret; -} - struct sel_arg_struct { unsigned int n; unsigned int inp; @@ -937,87 +791,8 @@ sys32_old_select (struct sel_arg_struct if (copy_from_user(&a, arg, sizeof(a))) return -EFAULT; - return sys32_select(a.n, (fd_set *) A(a.inp), (fd_set *) A(a.outp), (fd_set *) A(a.exp), - (struct compat_timeval *) A(a.tvp)); -} - -static struct iovec * -get_compat_iovec (struct compat_iovec *iov32, struct iovec *iov_buf, u32 count, int type) -{ - u32 i, buf, len; - struct iovec *ivp, *iov; - - /* Get the "struct iovec" from user memory */ - - if (!count) - return 0; - if (verify_area(VERIFY_READ, iov32, sizeof(struct compat_iovec)*count)) - return NULL; - if (count > UIO_MAXIOV) - return NULL; - if (count > UIO_FASTIOV) { - iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL); - if (!iov) - return NULL; - } else - iov = iov_buf; - - ivp = iov; - for (i = 0; i < count; i++) { - if (__get_user(len, &iov32->iov_len) || __get_user(buf, &iov32->iov_base)) { - if (iov != iov_buf) - kfree(iov); - return NULL; - } - if (verify_area(type, (void *)A(buf), len)) { - if (iov != iov_buf) - kfree(iov); - return((struct iovec *)0); - } - ivp->iov_base = (void *)A(buf); - ivp->iov_len = (__kernel_size_t) len; - iov32++; - ivp++; - } - return iov; -} - -asmlinkage long -sys32_readv (int fd, struct compat_iovec *vector, u32 count) -{ - struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov; - long ret; - mm_segment_t old_fs = get_fs(); - - iov = get_compat_iovec(vector, iovstack, count, VERIFY_WRITE); - if (!iov) - return -EFAULT; - set_fs(KERNEL_DS); - ret = sys_readv(fd, iov, count); - set_fs(old_fs); - if (iov != iovstack) - kfree(iov); - return ret; -} - -asmlinkage long -sys32_writev (int fd, struct compat_iovec *vector, u32 count) -{ - struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov; - long ret; - mm_segment_t old_fs = get_fs(); - - iov = get_compat_iovec(vector, iovstack, count, VERIFY_READ); - if (!iov) - return -EFAULT; - set_fs(KERNEL_DS); - ret = sys_writev(fd, iov, count); - set_fs(old_fs); - if (iov != iovstack) - kfree(iov); - return ret; + return compat_sys_select(a.n, compat_ptr(a.inp), compat_ptr(a.outp), + compat_ptr(a.exp), compat_ptr(a.tvp)); } #define SEMOP 1 @@ -2425,176 +2200,6 @@ sys32_setresgid(compat_gid_t rgid, compa return sys_setresgid(srgid, segid, ssgid); } -/* Stuff for NFS server syscalls... */ -struct nfsctl_svc32 { - u16 svc32_port; - s32 svc32_nthreads; -}; - -struct nfsctl_client32 { - s8 cl32_ident[NFSCLNT_IDMAX+1]; - s32 cl32_naddr; - struct in_addr cl32_addrlist[NFSCLNT_ADDRMAX]; - s32 cl32_fhkeytype; - s32 cl32_fhkeylen; - u8 cl32_fhkey[NFSCLNT_KEYMAX]; -}; - -struct nfsctl_export32 { - s8 ex32_client[NFSCLNT_IDMAX+1]; - s8 ex32_path[NFS_MAXPATHLEN+1]; - compat_dev_t ex32_dev; - compat_ino_t ex32_ino; - s32 ex32_flags; - compat_uid_t ex32_anon_uid; - compat_gid_t ex32_anon_gid; -}; - -struct nfsctl_arg32 { - s32 ca32_version; /* safeguard */ - union { - struct nfsctl_svc32 u32_svc; - struct nfsctl_client32 u32_client; - struct nfsctl_export32 u32_export; - u32 u32_debug; - } u; -#define ca32_svc u.u32_svc -#define ca32_client u.u32_client -#define ca32_export u.u32_export -#define ca32_debug u.u32_debug -}; - -union nfsctl_res32 { - struct knfs_fh cr32_getfh; - u32 cr32_debug; -}; - -static int -nfs_svc32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) -{ - int err; - - err = __get_user(karg->ca_version, &arg32->ca32_version); - err |= __get_user(karg->ca_svc.svc_port, &arg32->ca32_svc.svc32_port); - err |= __get_user(karg->ca_svc.svc_nthreads, - &arg32->ca32_svc.svc32_nthreads); - return err; -} - -static int -nfs_clnt32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) -{ - int err; - - err = __get_user(karg->ca_version, &arg32->ca32_version); - err |= copy_from_user(&karg->ca_client.cl_ident[0], - &arg32->ca32_client.cl32_ident[0], - NFSCLNT_IDMAX); - err |= __get_user(karg->ca_client.cl_naddr, - &arg32->ca32_client.cl32_naddr); - err |= copy_from_user(&karg->ca_client.cl_addrlist[0], - &arg32->ca32_client.cl32_addrlist[0], - (sizeof(struct in_addr) * NFSCLNT_ADDRMAX)); - err |= __get_user(karg->ca_client.cl_fhkeytype, - &arg32->ca32_client.cl32_fhkeytype); - err |= __get_user(karg->ca_client.cl_fhkeylen, - &arg32->ca32_client.cl32_fhkeylen); - err |= copy_from_user(&karg->ca_client.cl_fhkey[0], - &arg32->ca32_client.cl32_fhkey[0], - NFSCLNT_KEYMAX); - return err; -} - -static int -nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) -{ - int err; - - err = __get_user(karg->ca_version, &arg32->ca32_version); - err |= copy_from_user(&karg->ca_export.ex_client[0], - &arg32->ca32_export.ex32_client[0], - NFSCLNT_IDMAX); - err |= copy_from_user(&karg->ca_export.ex_path[0], - &arg32->ca32_export.ex32_path[0], - NFS_MAXPATHLEN); - err |= __get_user(karg->ca_export.ex_dev, - &arg32->ca32_export.ex32_dev); - err |= __get_user(karg->ca_export.ex_ino, - &arg32->ca32_export.ex32_ino); - err |= __get_user(karg->ca_export.ex_flags, - &arg32->ca32_export.ex32_flags); - err |= __get_user(karg->ca_export.ex_anon_uid, - &arg32->ca32_export.ex32_anon_uid); - err |= __get_user(karg->ca_export.ex_anon_gid, - &arg32->ca32_export.ex32_anon_gid); - return err; -} - -static int -nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32) -{ - int err; - - err = copy_to_user(&res32->cr32_getfh, - &kres->cr_getfh, - sizeof(res32->cr32_getfh)); - err |= __put_user(kres->cr_debug, &res32->cr32_debug); - return err; -} - -int asmlinkage -sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32) -{ - struct nfsctl_arg *karg = NULL; - union nfsctl_res *kres = NULL; - mm_segment_t oldfs; - int err; - - karg = kmalloc(sizeof(*karg), GFP_USER); - if(!karg) - return -ENOMEM; - if(res32) { - kres = kmalloc(sizeof(*kres), GFP_USER); - if(!kres) { - kfree(karg); - return -ENOMEM; - } - } - switch(cmd) { - case NFSCTL_SVC: - err = nfs_svc32_trans(karg, arg32); - break; - case NFSCTL_ADDCLIENT: - err = nfs_clnt32_trans(karg, arg32); - break; - case NFSCTL_DELCLIENT: - err = nfs_clnt32_trans(karg, arg32); - break; - case NFSCTL_EXPORT: - err = nfs_exp32_trans(karg, arg32); - break; - default: - err = -EINVAL; - break; - } - if(err) - goto done; - oldfs = get_fs(); - set_fs(KERNEL_DS); - err = sys_nfsservctl(cmd, karg, kres); - set_fs(oldfs); - - if(!err && cmd == NFSCTL_GETFS) - err = nfs_getfh32_res_trans(kres, res32); - -done: - if(karg) - kfree(karg); - if(kres) - kfree(kres); - return err; -} - /* Handle adjtimex compatibility. */ struct timex32 { --- linux-2.6.6/arch/ia64/Kconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/ia64/Kconfig 2004-05-10 01:19:46.530665320 -0700 @@ -78,6 +78,15 @@ config IA64_HP_SIM endchoice +config HOTPLUG_CPU + bool "Support for hot-pluggable CPUs (EXPERIMENTAL)" + depends on SMP && HOTPLUG && EXPERIMENTAL + default n + ---help--- + Say Y here to experiment with turning CPUs off and on. CPUs + can be controlled through /sys/devices/system/cpu/cpu#. + Say N if you want to disable cpu hotplug. + choice prompt "Processor type" default ITANIUM @@ -436,6 +445,19 @@ config MAGIC_SYSRQ keys are documented in . Don't say Y unless you really know what this hack does. +config SCHEDSTATS + bool "Collect scheduler statistics" + depends on PROC_FS + default y + help + If you say Y here, additional code will be inserted into the + scheduler and related routines to collect statistics about + scheduler behavior and provide them in /proc/schedstat. These + stats may be useful for both tuning and debugging the scheduler + If you aren't debugging the scheduler or trying to tune a specific + application, you can say N to avoid the very slight overhead + this adds. + config DEBUG_SLAB bool "Debug memory allocations" depends on DEBUG_KERNEL @@ -485,6 +507,13 @@ config DEBUG_INFO Say Y here only if you plan to use gdb to debug the kernel. If you don't debug the kernel, you can say N. +config LOCKMETER + bool "Kernel lock metering" + depends on SMP + help + Say Y to enable kernel lock metering, which adds overhead to SMP locks, + but allows you to see various statistics using the lockstat command. + config SYSVIPC_COMPAT bool depends on COMPAT && SYSVIPC --- linux-2.6.6/arch/ia64/kernel/entry.S 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/ia64/kernel/entry.S 2004-05-10 01:19:49.626194728 -0700 @@ -463,11 +463,6 @@ GLOBAL_ENTRY(__ia64_syscall) .regstk 6,0,0,0 mov r15=in5 // put syscall number in place break __BREAK_SYSCALL - movl r2=errno - cmp.eq p6,p7=-1,r10 - ;; -(p6) st4 [r2]=r8 -(p6) mov r8=-1 br.ret.sptk.many rp END(__ia64_syscall) @@ -1501,9 +1496,9 @@ sys_call_table: data8 sys_clock_nanosleep data8 sys_fstatfs64 data8 sys_statfs64 - data8 sys_ni_syscall - data8 sys_ni_syscall // 1260 - data8 sys_ni_syscall + data8 sys_mbind + data8 sys_get_mempolicy // 1260 + data8 sys_set_mempolicy data8 sys_mq_open data8 sys_mq_unlink data8 sys_mq_timedsend --- linux-2.6.6/arch/ia64/kernel/head.S 2004-04-03 20:39:10.000000000 -0800 +++ 25/arch/ia64/kernel/head.S 2004-05-10 01:19:44.933908064 -0700 @@ -866,12 +866,14 @@ SET_REG(b5); * Inputs: * ar.pfs - saved CFM of caller * ar.ccv - 0 (and available for use) + * r27 - flags from spin_lock_irqsave or 0. Must be preserved. * r28 - available for use. * r29 - available for use. * r30 - available for use. * r31 - address of lock, available for use. * b6 - return address * p14 - available for use. + * p15 - used to track flag status. * * If you patch this code to use more registers, do not forget to update * the clobber lists for spin_lock() in include/asm-ia64/spinlock.h. @@ -885,22 +887,26 @@ GLOBAL_ENTRY(ia64_spinlock_contention_pr .save rp, r28 .body nop 0 - nop 0 + tbit.nz p15,p0=r27,IA64_PSR_I_BIT .restore sp // pop existing prologue after next insn mov b6 = r28 .prologue .save ar.pfs, r0 .altrp b6 .body + ;; +(p15) ssm psr.i // reenable interrupts if they were on + // DavidM says that srlz.d is slow and is not required in this case .wait: // exponential backoff, kdb, lockmeter etc. go in here hint @pause ld4 r30=[r31] // don't use ld4.bias; if it's contended, we won't write the word nop 0 ;; - cmp4.eq p14,p0=r30,r0 -(p14) br.cond.sptk.few b6 // lock is now free, try to acquire - br.cond.sptk.few .wait + cmp4.ne p14,p0=r30,r0 +(p14) br.cond.sptk.few .wait +(p15) rsm psr.i // disable interrupts if we reenabled them + br.cond.sptk.few b6 // lock is now free, try to acquire END(ia64_spinlock_contention_pre3_4) #else @@ -909,14 +915,20 @@ GLOBAL_ENTRY(ia64_spinlock_contention) .prologue .altrp b6 .body + tbit.nz p15,p0=r27,IA64_PSR_I_BIT + ;; .wait: +(p15) ssm psr.i // reenable interrupts if they were on + // DavidM says that srlz.d is slow and is not required in this case +.wait2: // exponential backoff, kdb, lockmeter etc. go in here hint @pause ld4 r30=[r31] // don't use ld4.bias; if it's contended, we won't write the word ;; cmp4.ne p14,p0=r30,r0 mov r30 = 1 -(p14) br.cond.sptk.few .wait +(p14) br.cond.sptk.few .wait2 +(p15) rsm psr.i // disable interrupts if we reenabled them ;; cmpxchg4.acq r30=[r31], r30, ar.ccv ;; --- linux-2.6.6/arch/ia64/kernel/iosapic.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/ia64/kernel/iosapic.c 2004-05-10 01:19:46.531665168 -0700 @@ -32,6 +32,8 @@ * 03/02/19 B. Helgaas Make pcat_compat system-wide, not per-IOSAPIC. * Remove iosapic_address & gsi_base from external interfaces. * Rationalize __init/__devinit attributes. + * 04/12/04 Ashok Raj Intel Corporation 2004 + * Updated to work with irq migration necessary for CPU Hotplug */ /* * Here is what the interrupt logic between a PCI device and the kernel looks like: @@ -98,6 +100,7 @@ #endif static spinlock_t iosapic_lock = SPIN_LOCK_UNLOCKED; +cpumask_t __cacheline_aligned pending_irq_cpumask[NR_IRQS]; /* These tables map IA-64 vectors to the IOSAPIC pin that generates this vector. */ @@ -188,8 +191,10 @@ set_rte (unsigned int vector, unsigned i pol = iosapic_intr_info[vector].polarity; trigger = iosapic_intr_info[vector].trigger; dmode = iosapic_intr_info[vector].dmode; + vector &= (~IA64_IRQ_REDIRECTED); redir = (dmode == IOSAPIC_LOWEST_PRIORITY) ? 1 : 0; + #ifdef CONFIG_SMP { unsigned int irq; @@ -311,9 +316,8 @@ iosapic_set_affinity (unsigned int irq, spin_lock_irqsave(&iosapic_lock, flags); { - /* get current delivery mode by reading the low32 */ - writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT); low32 = iosapic_intr_info[vec].low32 & ~(7 << IOSAPIC_DELIVERY_SHIFT); + if (redir) /* change delivery mode to lowest priority */ low32 |= (IOSAPIC_LOWEST_PRIORITY << IOSAPIC_DELIVERY_SHIFT); @@ -331,6 +335,21 @@ iosapic_set_affinity (unsigned int irq, #endif } +static inline void move_irq(int irq) +{ + /* note - we hold desc->lock */ + cpumask_t tmp; + irq_desc_t *desc = irq_descp(irq); + + if (!cpus_empty(pending_irq_cpumask[irq])) { + cpus_and(tmp, pending_irq_cpumask[irq], cpu_online_map); + if (unlikely(!cpus_empty(tmp))) { + desc->handler->set_affinity(irq, pending_irq_cpumask[irq]); + } + cpus_clear(pending_irq_cpumask[irq]); + } +} + /* * Handlers for level-triggered interrupts. */ @@ -347,6 +366,7 @@ iosapic_end_level_irq (unsigned int irq) { ia64_vector vec = irq_to_vector(irq); + move_irq(irq); writel(vec, iosapic_intr_info[vec].addr + IOSAPIC_EOI); } @@ -386,6 +406,8 @@ static void iosapic_ack_edge_irq (unsigned int irq) { irq_desc_t *idesc = irq_descp(irq); + + move_irq(irq); /* * Once we have recorded IRQ_PENDING already, we can mask the * interrupt for real. This prevents IRQ storms from unhandled --- linux-2.6.6/arch/ia64/kernel/irq.c 2004-03-10 20:41:25.000000000 -0800 +++ 25/arch/ia64/kernel/irq.c 2004-05-10 01:19:46.532665016 -0700 @@ -8,6 +8,12 @@ * instead of just grabbing them. Thus setups with different IRQ numbers * shouldn't result in any weird surprises, and installing new handlers * should be easier. + * + * Copyright (C) Ashok Raj, Intel Corporation 2004 + * + * 4/14/2004: Added code to handle cpu migration and do safe irq + * migration without lossing interrupts for iosapic + * architecture. */ /* @@ -27,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -35,18 +42,21 @@ #include #include #include +#include #include +#include #include #include #include #include #include #include +#include #include #include - +extern cpumask_t __cacheline_aligned pending_irq_cpumask[NR_IRQS]; /* * Linux has a controller-independent x86 interrupt architecture. @@ -938,7 +948,9 @@ void set_irq_affinity_info (unsigned int static int irq_affinity_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]); + int len = sprintf(page, "%s", irq_redir[(long)data] ? "r " : ""); + + len += cpumask_scnprintf(page+len, count, irq_affinity[(long)data]); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); @@ -956,6 +968,7 @@ static int irq_affinity_write_proc (stru int rlen; int prelen; irq_desc_t *desc = irq_descp(irq); + unsigned long flags; if (!desc->handler->set_affinity) return -EIO; @@ -994,12 +1007,108 @@ static int irq_affinity_write_proc (stru if (cpus_empty(tmp)) return -EINVAL; - desc->handler->set_affinity(irq, new_value); + spin_lock_irqsave(&desc->lock, flags); + pending_irq_cpumask[irq] = new_value; + spin_unlock_irqrestore(&desc->lock, flags); + return full_count; } #endif /* CONFIG_SMP */ +#ifdef CONFIG_HOTPLUG_CPU +unsigned int vectors_in_migration[NR_IRQS]; + +/* + * Since cpu_online_map is already updated, we just need to check for + * affinity that has zeros + */ +static void migrate_irqs(void) +{ + cpumask_t mask; + irq_desc_t *desc; + int irq, new_cpu; + + for (irq=0; irq < NR_IRQS; irq++) { + desc = irq_descp(irq); + + /* + * No handling for now. + * TBD: Implement a disable function so we can now + * tell CPU not to respond to these local intr sources. + * such as ITV,CPEI,MCA etc. + */ + if (desc->status == IRQ_PER_CPU) + continue; + + cpus_and(mask, irq_affinity[irq], cpu_online_map); + if (any_online_cpu(mask) == NR_CPUS) { + /* + * Save it for phase 2 processing + */ + vectors_in_migration[irq] = irq; + + new_cpu = any_online_cpu(cpu_online_map); + mask = cpumask_of_cpu(new_cpu); + + /* + * Al three are essential, currently WARN_ON.. maybe panic? + */ + if (desc->handler && desc->handler->disable && + desc->handler->enable && desc->handler->set_affinity) { + desc->handler->disable(irq); + desc->handler->set_affinity(irq, mask); + desc->handler->enable(irq); + } else { + WARN_ON((!(desc->handler) || !(desc->handler->disable) || + !(desc->handler->enable) || + !(desc->handler->set_affinity))); + } + } + } +} + +void fixup_irqs(void) +{ + unsigned int irq; + extern void ia64_process_pending_intr(void); + + ia64_set_itv(1<<16); + /* + * Phase 1: Locate irq's bound to this cpu and + * relocate them for cpu removal. + */ + migrate_irqs(); + + /* + * Phase 2: Perform interrupt processing for all entries reported in + * local APIC. + */ + ia64_process_pending_intr(); + + /* + * Phase 3: Now handle any interrupts not captured in local APIC. + * This is to account for cases that device interrupted during the time the + * rte was being disabled and re-programmed. + */ + for (irq=0; irq < NR_IRQS; irq++) { + if (vectors_in_migration[irq]) { + vectors_in_migration[irq]=0; + do_IRQ(irq, NULL); + } + } + + /* + * Now let processor die. We do irq disable and max_xtp() to + * ensure there is no more interrupts routed to this processor. + * But the local timer interrupt can have 1 pending which we + * take care in timer_interrupt(). + */ + max_xtp(); + local_irq_disable(); +} +#endif + static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { --- linux-2.6.6/arch/ia64/kernel/irq_ia64.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/ia64/kernel/irq_ia64.c 2004-05-10 01:19:46.533664864 -0700 @@ -10,6 +10,8 @@ * * 09/15/00 Goutham Rao Implemented pci_irq_to_vector * PCI to vector allocation routine. + * 04/14/2004 Ashok Raj + * Added CPU Hotplug handling for IPF. */ #include @@ -85,6 +87,11 @@ assign_irq_vector (int irq) extern unsigned int do_IRQ(unsigned long irq, struct pt_regs *regs); +#ifdef CONFIG_SMP +# define IS_RESCHEDULE(vec) (vec == IA64_IPI_RESCHEDULE) +#else +# define IS_RESCHEDULE(vec) (0) +#endif /* * That's where the IVT branches when we get an external * interrupt. This branches to the correct hardware IRQ handler via @@ -94,11 +101,6 @@ void ia64_handle_irq (ia64_vector vector, struct pt_regs *regs) { unsigned long saved_tpr; -#ifdef CONFIG_SMP -# define IS_RESCHEDULE(vec) (vec == IA64_IPI_RESCHEDULE) -#else -# define IS_RESCHEDULE(vec) (0) -#endif #if IRQ_DEBUG { @@ -162,6 +164,54 @@ ia64_handle_irq (ia64_vector vector, str irq_exit(); } +#ifdef CONFIG_HOTPLUG_CPU +/* + * This function emulates a interrupt processing when a cpu is about to be + * brought down. + */ +void ia64_process_pending_intr(void) +{ + ia64_vector vector; + unsigned long saved_tpr; + extern unsigned int vectors_in_migration[NR_IRQS]; + + vector = ia64_get_ivr(); + + irq_enter(); + saved_tpr = ia64_getreg(_IA64_REG_CR_TPR); + ia64_srlz_d(); + + /* + * Perform normal interrupt style processing + */ + while (vector != IA64_SPURIOUS_INT_VECTOR) { + if (!IS_RESCHEDULE(vector)) { + ia64_setreg(_IA64_REG_CR_TPR, vector); + ia64_srlz_d(); + + /* + * Now try calling normal ia64_handle_irq as it would have got called + * from a real intr handler. Try passing null for pt_regs, hopefully + * it will work. I hope it works!. + * Probably could shared code. + */ + vectors_in_migration[local_vector_to_irq(vector)]=0; + do_IRQ(local_vector_to_irq(vector), NULL); + + /* + * Disable interrupts and send EOI + */ + local_irq_disable(); + ia64_setreg(_IA64_REG_CR_TPR, saved_tpr); + } + ia64_eoi(); + vector = ia64_get_ivr(); + } + irq_exit(); +} +#endif + + #ifdef CONFIG_SMP extern irqreturn_t handle_IPI (int irq, void *dev_id, struct pt_regs *regs); --- linux-2.6.6/arch/ia64/kernel/palinfo.c 2003-06-14 12:17:56.000000000 -0700 +++ 25/arch/ia64/kernel/palinfo.c 2004-05-10 01:19:46.076734328 -0700 @@ -8,11 +8,14 @@ * * Copyright (C) 2000-2001, 2003 Hewlett-Packard Co * Stephane Eranian + * Copyright (C) 2004 Intel Corporation + * Ashok Raj * * 05/26/2000 S.Eranian initial release * 08/21/2000 S.Eranian updated to July 2000 PAL specs * 02/05/2001 S.Eranian fixed module support * 10/23/2001 S.Eranian updated pal_perf_mon_info bug fixes + * 03/24/2004 Ashok Raj updated to work with CPU Hotplug */ #include #include @@ -22,6 +25,9 @@ #include #include #include +#include +#include +#include #include #include @@ -768,13 +774,12 @@ static palinfo_entry_t palinfo_entries[] * does not do recursion of deletion * * Notes: - * - first +1 accounts for the cpuN entry - * - second +1 account for toplevel palinfo - * + * - +1 accounts for the cpuN directory entry in /proc/pal */ -#define NR_PALINFO_PROC_ENTRIES (NR_CPUS*(NR_PALINFO_ENTRIES+1)+1) +#define NR_PALINFO_PROC_ENTRIES (NR_CPUS*(NR_PALINFO_ENTRIES+1)) static struct proc_dir_entry *palinfo_proc_entries[NR_PALINFO_PROC_ENTRIES]; +static struct proc_dir_entry *palinfo_dir; /* * This data structure is used to pass which cpu,function is being requested @@ -888,47 +893,107 @@ palinfo_read_entry(char *page, char **st return len; } -static int __init -palinfo_init(void) +static void +create_palinfo_proc_entries(unsigned int cpu) { # define CPUSTR "cpu%d" pal_func_cpu_u_t f; - struct proc_dir_entry **pdir = palinfo_proc_entries; - struct proc_dir_entry *palinfo_dir, *cpu_dir; - int i, j; + struct proc_dir_entry **pdir; + struct proc_dir_entry *cpu_dir; + int j; char cpustr[sizeof(CPUSTR)]; - printk(KERN_INFO "PAL Information Facility v%s\n", PALINFO_VERSION); - - palinfo_dir = proc_mkdir("pal", NULL); /* * we keep track of created entries in a depth-first order for * cleanup purposes. Each entry is stored into palinfo_proc_entries */ - for (i=0; i < NR_CPUS; i++) { + sprintf(cpustr,CPUSTR, cpu); - if (!cpu_online(i)) continue; + cpu_dir = proc_mkdir(cpustr, palinfo_dir); - sprintf(cpustr,CPUSTR, i); + f.req_cpu = cpu; - cpu_dir = proc_mkdir(cpustr, palinfo_dir); + /* + * Compute the location to store per cpu entries + * We dont store the top level entry in this list, but + * remove it finally after removing all cpu entries. + */ + pdir = &palinfo_proc_entries[cpu*(NR_PALINFO_ENTRIES+1)]; + *pdir++ = cpu_dir; + for (j=0; j < NR_PALINFO_ENTRIES; j++) { + f.func_id = j; + *pdir = create_proc_read_entry( + palinfo_entries[j].name, 0, cpu_dir, + palinfo_read_entry, (void *)f.value); + if (*pdir) + (*pdir)->owner = THIS_MODULE; + pdir++; + } +} - f.req_cpu = i; +static void +remove_palinfo_proc_entries(unsigned int hcpu) +{ + int j; + struct proc_dir_entry *cpu_dir, **pdir; - for (j=0; j < NR_PALINFO_ENTRIES; j++) { - f.func_id = j; - *pdir = create_proc_read_entry( - palinfo_entries[j].name, 0, cpu_dir, - palinfo_read_entry, (void *)f.value); - if (*pdir) - (*pdir)->owner = THIS_MODULE; - pdir++; + pdir = &palinfo_proc_entries[hcpu*(NR_PALINFO_ENTRIES+1)]; + cpu_dir = *pdir; + *pdir++=NULL; + for (j=0; j < (NR_PALINFO_ENTRIES); j++) { + if ((*pdir)) { + remove_proc_entry ((*pdir)->name, cpu_dir); + *pdir ++= NULL; } - *pdir++ = cpu_dir; } - *pdir = palinfo_dir; + + if (cpu_dir) { + remove_proc_entry(cpu_dir->name, palinfo_dir); + } +} + +static int __devinit palinfo_cpu_callback(struct notifier_block *nfb, + unsigned long action, + void *hcpu) +{ + unsigned int hotcpu = (unsigned long)hcpu; + + switch (action) { + case CPU_ONLINE: + create_palinfo_proc_entries(hotcpu); + break; +#ifdef CONFIG_HOTPLUG_CPU + case CPU_DEAD: + remove_palinfo_proc_entries(hotcpu); + break; +#endif + } + return NOTIFY_OK; +} + +static struct notifier_block palinfo_cpu_notifier = +{ + .notifier_call = palinfo_cpu_callback, + .priority = 0, +}; + +static int __init +palinfo_init(void) +{ + int i = 0; + + printk(KERN_INFO "PAL Information Facility v%s\n", PALINFO_VERSION); + palinfo_dir = proc_mkdir("pal", NULL); + + /* Create palinfo dirs in /proc for all online cpus */ + for_each_online_cpu(i) { + create_palinfo_proc_entries(i); + } + + /* Register for future delivery via notify registration */ + register_cpu_notifier(&palinfo_cpu_notifier); return 0; } @@ -939,10 +1004,19 @@ palinfo_exit(void) int i = 0; /* remove all nodes: depth first pass. Could optimize this */ - for (i=0; i< NR_PALINFO_PROC_ENTRIES ; i++) { - if (palinfo_proc_entries[i]) - remove_proc_entry (palinfo_proc_entries[i]->name, NULL); + for_each_online_cpu(i) { + remove_palinfo_proc_entries(i); } + + /* + * Remove the top level entry finally + */ + remove_proc_entry(palinfo_dir->name, NULL); + + /* + * Unregister from cpu notifier callbacks + */ + unregister_cpu_notifier(&palinfo_cpu_notifier); } module_init(palinfo_init); --- linux-2.6.6/arch/ia64/kernel/perfmon.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/ia64/kernel/perfmon.c 2004-05-10 01:19:13.963616264 -0700 @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -2295,6 +2296,8 @@ pfm_smpl_buffer_alloc(struct task_struct DPRINT(("Cannot allocate vma\n")); goto error_kmem; } + memset(vma, 0, sizeof(*vma)); + /* * partially initialize the vma for the sampling buffer * @@ -2305,10 +2308,6 @@ pfm_smpl_buffer_alloc(struct task_struct vma->vm_mm = mm; vma->vm_flags = VM_READ| VM_MAYREAD |VM_RESERVED; vma->vm_page_prot = PAGE_READONLY; /* XXX may need to change */ - vma->vm_ops = NULL; - vma->vm_pgoff = 0; - vma->vm_file = NULL; - vma->vm_private_data = NULL; /* * Now we have everything we need and we can initialize --- linux-2.6.6/arch/ia64/kernel/process.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/ia64/kernel/process.c 2004-05-10 01:19:46.534664712 -0700 @@ -7,6 +7,7 @@ #define __KERNEL_SYSCALLS__ /* see */ #include +#include #include #include #include @@ -14,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -22,13 +24,17 @@ #include #include #include +#include +#include #include #include #include +#include #include #include #include +#include #include #include #include @@ -180,6 +186,40 @@ default_idle (void) safe_halt(); } +#ifdef CONFIG_HOTPLUG_CPU +/* We don't actually take CPU down, just spin without interrupts. */ +static inline void play_dead(void) +{ + extern void ia64_cpu_local_tick (void); + /* Ack it */ + __get_cpu_var(cpu_state) = CPU_DEAD; + + /* We shouldn't have to disable interrupts while dead, but + * some interrupts just don't seem to go away, and this makes + * it "work" for testing purposes. */ + max_xtp(); + local_irq_disable(); + /* Death loop */ + while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE) + cpu_relax(); + + /* + * Enable timer interrupts from now on + * Not required if we put processor in SAL_BOOT_RENDEZ mode. + */ + local_flush_tlb_all(); + cpu_set(smp_processor_id(), cpu_online_map); + wmb(); + ia64_cpu_local_tick (); + local_irq_enable(); +} +#else +static inline void play_dead(void) +{ + BUG(); +} +#endif /* CONFIG_HOTPLUG_CPU */ + void __attribute__((noreturn)) cpu_idle (void *unused) { @@ -195,7 +235,6 @@ cpu_idle (void *unused) if (!need_resched()) min_xtp(); #endif - while (!need_resched()) { if (mark_idle) (*mark_idle)(1); @@ -210,6 +249,8 @@ cpu_idle (void *unused) #endif schedule(); check_pgt_cache(); + if (cpu_is_offline(smp_processor_id())) + play_dead(); } } @@ -657,11 +698,6 @@ get_wchan (struct task_struct *p) struct unw_frame_info info; unsigned long ip; int count = 0; - /* - * These bracket the sleeping functions.. - */ -# define first_sched ((unsigned long) scheduling_functions_start_here) -# define last_sched ((unsigned long) scheduling_functions_end_here) /* * Note: p may not be a blocked task (it could be current or @@ -676,12 +712,10 @@ get_wchan (struct task_struct *p) if (unw_unwind(&info) < 0) return 0; unw_get_ip(&info, &ip); - if (ip < first_sched || ip >= last_sched) + if (!in_sched_functions(ip)) return ip; } while (count++ < 16); return 0; -# undef first_sched -# undef last_sched } void --- linux-2.6.6/arch/ia64/kernel/sal.c 2004-04-03 20:39:10.000000000 -0800 +++ 25/arch/ia64/kernel/sal.c 2004-05-10 01:19:46.534664712 -0700 @@ -122,10 +122,23 @@ sal_desc_entry_point (void *p) static void __init set_smp_redirect (int flag) { +#ifndef CONFIG_HOTPLUG_CPU if (no_int_routing) smp_int_redirect &= ~flag; else smp_int_redirect |= flag; +#else + /* + * For CPU Hotplug we dont want to do any chipset supported + * interrupt redirection. The reason is this would require that + * All interrupts be stopped and hard bind the irq to a cpu. + * Later when the interrupt is fired we need to set the redir hint + * on again in the vector. This is combersome for something that the + * user mode irq balancer will solve anyways. + */ + no_int_routing=1; + smp_int_redirect &= ~flag; +#endif } #else #define set_smp_redirect(flag) do { } while (0) --- linux-2.6.6/arch/ia64/kernel/setup.c 2004-04-03 20:39:10.000000000 -0800 +++ 25/arch/ia64/kernel/setup.c 2004-05-10 01:19:45.667796496 -0700 @@ -88,10 +88,6 @@ unsigned char aux_device_present = 0xaa; unsigned long ia64_max_iommu_merge_mask = ~0UL; EXPORT_SYMBOL(ia64_max_iommu_merge_mask); -#define COMMAND_LINE_SIZE 512 - -char saved_command_line[COMMAND_LINE_SIZE]; /* used in proc filesystem */ - /* * We use a special marker for the end of memory and it uses the extra (+1) slot */ @@ -575,7 +571,7 @@ get_max_cacheline_size (void) void cpu_init (void) { - extern void __init ia64_mmu_init (void *); + extern void __devinit ia64_mmu_init (void *); unsigned long num_phys_stacked; pal_vm_info_2_u_t vmi; unsigned int max_ctx; --- linux-2.6.6/arch/ia64/kernel/smpboot.c 2004-04-03 20:39:10.000000000 -0800 +++ 25/arch/ia64/kernel/smpboot.c 2004-05-10 01:19:46.536664408 -0700 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -22,10 +23,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include @@ -44,6 +47,7 @@ #include #include #include +#include #include #define SMP_DEBUG 0 @@ -69,17 +73,22 @@ static volatile unsigned long go[SLAVE + #define DEBUG_ITC_SYNC 0 -extern void __init calibrate_delay (void); +extern void __devinit calibrate_delay (void); extern void start_ap (void); extern unsigned long ia64_iobase; task_t *task_for_booting_cpu; -/* Bitmask of currently online CPUs */ +/* + * State for each CPU + */ +DEFINE_PER_CPU(int, cpu_state); + +/* Bitmasks of currently online, and possible CPUs */ cpumask_t cpu_online_map; EXPORT_SYMBOL(cpu_online_map); -cpumask_t phys_cpu_present_map; -EXPORT_SYMBOL(phys_cpu_present_map); +cpumask_t cpu_possible_map; +EXPORT_SYMBOL(cpu_possible_map); /* which logical CPU number maps to which CPU (physical APIC ID) */ volatile int ia64_cpu_to_sapicid[NR_CPUS]; @@ -99,6 +108,7 @@ static int __init nointroute (char *str) { no_int_routing = 1; + printk ("no_int_routing on\n"); return 1; } @@ -262,12 +272,12 @@ ia64_sync_itc (unsigned int master) /* * Ideally sets up per-cpu profiling hooks. Doesn't do much now... */ -static inline void __init +static inline void __devinit smp_setup_percpu_timer (void) { } -static void __init +static void __devinit smp_callin (void) { int cpuid, phys_id; @@ -280,12 +290,16 @@ smp_callin (void) cpuid = smp_processor_id(); phys_id = hard_smp_processor_id(); - if (cpu_test_and_set(cpuid, cpu_online_map)) { + if (cpu_online(cpuid)) { printk(KERN_ERR "huh, phys CPU#0x%x, CPU#0x%x already present??\n", phys_id, cpuid); BUG(); } + lock_ipi_calllock(); + cpu_set(cpuid, cpu_online_map); + unlock_ipi_calllock(); + smp_setup_percpu_timer(); /* @@ -333,7 +347,7 @@ smp_callin (void) /* * Activate a secondary processor. head.S calls this. */ -int __init +int __devinit start_secondary (void *unused) { extern int cpu_idle (void); @@ -346,7 +360,7 @@ start_secondary (void *unused) return cpu_idle(); } -static struct task_struct * __init +static struct task_struct * __devinit fork_by_hand (void) { /* @@ -356,29 +370,51 @@ fork_by_hand (void) return copy_process(CLONE_VM|CLONE_IDLETASK, 0, 0, 0, NULL, NULL); } -static int __init +struct create_idle { + struct task_struct *idle; + struct completion done; +}; + +void +do_fork_idle(void *_c_idle) +{ + struct create_idle *c_idle = _c_idle; + + c_idle->idle = fork_by_hand(); + complete(&c_idle->done); +} + +static int __devinit do_boot_cpu (int sapicid, int cpu) { - struct task_struct *idle; int timeout; + struct create_idle c_idle; + DECLARE_WORK(work, do_fork_idle, &c_idle); + init_completion(&c_idle.done); /* * We can't use kernel_thread since we must avoid to reschedule the child. */ - idle = fork_by_hand(); - if (IS_ERR(idle)) + if (!keventd_up() || current_is_keventd()) + work.func(work.data); + else { + schedule_work(&work); + wait_for_completion(&c_idle.done); + } + + if (IS_ERR(c_idle.idle)) panic("failed fork for CPU %d", cpu); - wake_up_forked_process(idle); + wake_up_forked_process(c_idle.idle); /* * We remove it from the pidhash and the runqueue * once we got the process: */ - init_idle(idle, cpu); + init_idle(c_idle.idle, cpu); - unhash_process(idle); + unhash_process(c_idle.idle); - task_for_booting_cpu = idle; + task_for_booting_cpu = c_idle.idle; Dprintk("Sending wakeup vector %lu to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid); @@ -437,18 +473,23 @@ smp_build_cpu_map (void) int sapicid, cpu, i; int boot_cpu_id = hard_smp_processor_id(); - for (cpu = 0; cpu < NR_CPUS; cpu++) + for (cpu = 0; cpu < NR_CPUS; cpu++) { ia64_cpu_to_sapicid[cpu] = -1; +#ifdef CONFIG_HOTPLUG_CPU + cpu_set(cpu, cpu_possible_map); +#endif + } ia64_cpu_to_sapicid[0] = boot_cpu_id; - cpus_clear(phys_cpu_present_map); - cpu_set(0, phys_cpu_present_map); - + cpus_clear(cpu_present_map); + cpu_set(0, cpu_present_map); + cpu_set(0, cpu_possible_map); for (cpu = 1, i = 0; i < smp_boot_data.cpu_count; i++) { sapicid = smp_boot_data.cpu_phys_id[i]; if (sapicid == boot_cpu_id) continue; - cpu_set(cpu, phys_cpu_present_map); + cpu_set(cpu, cpu_present_map); + cpu_set(cpu, cpu_possible_map); ia64_cpu_to_sapicid[cpu] = sapicid; cpu++; } @@ -529,9 +570,11 @@ smp_prepare_cpus (unsigned int max_cpus) if (!max_cpus) { printk(KERN_INFO "SMP mode deactivated.\n"); cpus_clear(cpu_online_map); - cpus_clear(phys_cpu_present_map); + cpus_clear(cpu_present_map); + cpus_clear(cpu_possible_map); cpu_set(0, cpu_online_map); - cpu_set(0, phys_cpu_present_map); + cpu_set(0, cpu_present_map); + cpu_set(0, cpu_possible_map); return; } } @@ -542,6 +585,74 @@ void __devinit smp_prepare_boot_cpu(void cpu_set(smp_processor_id(), cpu_callin_map); } +#ifdef CONFIG_HOTPLUG_CPU +extern void fixup_irqs(void); +/* must be called with cpucontrol mutex held */ +static int __devinit cpu_enable(unsigned int cpu) +{ + per_cpu(cpu_state,cpu) = CPU_UP_PREPARE; + wmb(); + + while (!cpu_online(cpu)) + cpu_relax(); + return 0; +} + +int __cpu_disable(void) +{ + int cpu = smp_processor_id(); + + /* + * dont permit boot processor for now + */ + if (cpu == 0) + return -EBUSY; + + fixup_irqs(); + local_flush_tlb_all(); + printk ("Disabled cpu %u\n", smp_processor_id()); + return 0; +} + +void __cpu_die(unsigned int cpu) +{ + unsigned int i; + + for (i = 0; i < 100; i++) { + /* They ack this in play_dead by setting CPU_DEAD */ + if (per_cpu(cpu_state, cpu) == CPU_DEAD) + { + /* + * TBD: Enable this when physical removal + * or when we put the processor is put in + * SAL_BOOT_RENDEZ mode + * cpu_clear(cpu, cpu_callin_map); + */ + return; + } + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(HZ/10); + } + printk(KERN_ERR "CPU %u didn't die...\n", cpu); +} +#else /* !CONFIG_HOTPLUG_CPU */ +static int __devinit cpu_enable(unsigned int cpu) +{ + return 0; +} + +int __cpu_disable(void) +{ + return -ENOSYS; +} + +void __cpu_die(unsigned int cpu) +{ + /* We said "no" in __cpu_disable */ + BUG(); +} +#endif /* CONFIG_HOTPLUG_CPU */ + void smp_cpus_done (unsigned int dummy) { @@ -570,6 +681,17 @@ __cpu_up (unsigned int cpu) if (sapicid == -1) return -EINVAL; + /* + * Already booted.. just enable and get outa idle lool + */ + if (cpu_isset(cpu, cpu_callin_map)) + { + cpu_enable(cpu); + local_irq_enable(); + while (!cpu_isset(cpu, cpu_online_map)) + mb(); + return 0; + } /* Processor goes to start_secondary(), sets online flag */ ret = do_boot_cpu(sapicid, cpu); if (ret < 0) --- linux-2.6.6/arch/ia64/kernel/smp.c 2004-04-03 20:39:10.000000000 -0800 +++ 25/arch/ia64/kernel/smp.c 2004-05-10 01:19:49.906152168 -0700 @@ -71,10 +71,23 @@ static volatile struct call_data_struct /* This needs to be cacheline aligned because it is written to by *other* CPUs. */ static DEFINE_PER_CPU(u64, ipi_operation) ____cacheline_aligned; +extern void cpu_halt (void); + +void +lock_ipi_calllock(void) +{ + spin_lock_irq(&call_lock); +} + +void +unlock_ipi_calllock(void) +{ + spin_unlock_irq(&call_lock); +} + static void stop_this_cpu (void) { - extern void cpu_halt (void); /* * Remove this CPU: */ @@ -84,6 +97,17 @@ stop_this_cpu (void) cpu_halt(); } +void +cpu_die(void) +{ + max_xtp(); + local_irq_disable(); + cpu_halt(); + /* Should never be here */ + BUG(); + for (;;); +} + irqreturn_t handle_IPI (int irq, void *dev_id, struct pt_regs *regs) { @@ -308,6 +332,9 @@ smp_call_function (void (*func) (void *i if (!cpus) return 0; + /* Can deadlock when called with interrupts disabled */ + WARN_ON(irqs_disabled()); + data.func = func; data.info = info; atomic_set(&data.started, 0); --- linux-2.6.6/arch/ia64/kernel/time.c 2004-04-03 20:39:10.000000000 -0800 +++ 25/arch/ia64/kernel/time.c 2004-05-10 01:19:46.537664256 -0700 @@ -10,6 +10,7 @@ */ #include +#include #include #include #include @@ -244,6 +245,10 @@ timer_interrupt (int irq, void *dev_id, { unsigned long new_itm; + if (unlikely(cpu_is_offline(smp_processor_id()))) { + return IRQ_HANDLED; + } + platform_timer_interrupt(irq, dev_id, regs); new_itm = local_cpu_data->itm_next; @@ -326,7 +331,7 @@ ia64_cpu_local_tick (void) ia64_set_itm(local_cpu_data->itm_next); } -void __init +void __devinit ia64_init_itm (void) { unsigned long platform_base_freq, itc_freq; --- linux-2.6.6/arch/ia64/lib/dec_and_lock.c 2004-01-09 00:04:31.000000000 -0800 +++ 25/arch/ia64/lib/dec_and_lock.c 2004-05-10 01:19:28.014480208 -0700 @@ -13,6 +13,7 @@ #include #include +#ifndef CONFIG_LOCKMETER /* * Decrement REFCOUNT and if the count reaches zero, acquire the spinlock. Both of these * operations have to be done atomically, so that the count doesn't drop to zero without @@ -40,3 +41,4 @@ atomic_dec_and_lock (atomic_t *refcount, } EXPORT_SYMBOL(atomic_dec_and_lock); +#endif --- linux-2.6.6/arch/ia64/mm/hugetlbpage.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/ia64/mm/hugetlbpage.c 2004-05-10 01:19:56.316177696 -0700 @@ -293,8 +293,9 @@ int hugetlb_prefault(struct address_spac goto out; } ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC); - unlock_page(page); - if (ret) { + if (! ret) { + unlock_page(page); + } else { hugetlb_put_quota(mapping); free_huge_page(page); goto out; --- linux-2.6.6/arch/ia64/mm/init.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/ia64/mm/init.c 2004-05-10 01:19:45.669796192 -0700 @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -123,15 +124,12 @@ ia64_init_addr_space (void) */ vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); if (vma) { + memset(vma, 0, sizeof(*vma)); vma->vm_mm = current->mm; vma->vm_start = current->thread.rbs_bot & PAGE_MASK; vma->vm_end = vma->vm_start + PAGE_SIZE; vma->vm_page_prot = protection_map[VM_DATA_DEFAULT_FLAGS & 0x7]; vma->vm_flags = VM_READ|VM_WRITE|VM_MAYREAD|VM_MAYWRITE|VM_GROWSUP; - vma->vm_ops = NULL; - vma->vm_pgoff = 0; - vma->vm_file = NULL; - vma->vm_private_data = NULL; insert_vm_struct(current->mm, vma); } @@ -275,11 +273,11 @@ setup_gate (void) ia64_patch_gate(); } -void __init +void __devinit ia64_mmu_init (void *my_cpu_data) { unsigned long psr, pta, impl_va_bits; - extern void __init tlb_init (void); + extern void __devinit tlb_init (void); int cpu; #ifdef CONFIG_DISABLE_VHPT --- linux-2.6.6/arch/ia64/mm/tlb.c 2004-02-03 20:42:34.000000000 -0800 +++ 25/arch/ia64/mm/tlb.c 2004-05-10 01:19:45.669796192 -0700 @@ -166,7 +166,7 @@ flush_tlb_range (struct vm_area_struct * } EXPORT_SYMBOL(flush_tlb_range); -void __init +void __devinit ia64_tlb_init (void) { ia64_ptce_info_t ptce_info; --- linux-2.6.6/arch/m68k/atari/stram.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/m68k/atari/stram.c 2004-05-10 01:19:11.050059192 -0700 @@ -752,7 +752,7 @@ static int unswap_by_read(unsigned short /* Get a page for the entry, using the existing swap cache page if there is one. Otherwise, get a clean page and read the swap into it. */ - page = read_swap_cache_async(entry); + page = read_swap_cache_async(entry, NULL, 0); if (!page) { swap_free(entry); return -ENOMEM; --- linux-2.6.6/arch/m68k/kernel/process.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/m68k/kernel/process.c 2004-05-10 01:19:31.139005208 -0700 @@ -67,8 +67,7 @@ unsigned long thread_saved_pc(struct tas { struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp; /* Check whether the thread is blocked in resume() */ - if (sw->retpc > (unsigned long)scheduling_functions_start_here && - sw->retpc < (unsigned long)scheduling_functions_end_here) + if (in_sched_functions(sw->retpc)) return ((unsigned long *)sw->a6)[1]; else return sw->retpc; @@ -382,12 +381,6 @@ out: return error; } -/* - * These bracket the sleeping functions.. - */ -#define first_sched ((unsigned long) scheduling_functions_start_here) -#define last_sched ((unsigned long) scheduling_functions_end_here) - unsigned long get_wchan(struct task_struct *p) { unsigned long fp, pc; @@ -403,7 +396,7 @@ unsigned long get_wchan(struct task_stru fp >= 8184+stack_page) return 0; pc = ((unsigned long *)fp)[1]; - if (pc < first_sched || pc >= last_sched) + if (!in_sched_functions(pc)) return pc; fp = *(unsigned long *) fp; } while (count++ < 16); --- linux-2.6.6/arch/m68k/kernel/setup.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/m68k/kernel/setup.c 2004-05-10 01:19:18.567916304 -0700 @@ -62,7 +62,6 @@ struct mem_info m68k_memory[NUM_MEMINFO] static struct mem_info m68k_ramdisk; static char m68k_command_line[CL_SIZE]; -char saved_command_line[CL_SIZE]; char m68k_debug_device[6] = ""; --- linux-2.6.6/arch/m68knommu/kernel/process.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/m68knommu/kernel/process.c 2004-05-10 01:19:31.140005056 -0700 @@ -404,12 +404,6 @@ out: return error; } -/* - * These bracket the sleeping functions.. - */ -#define first_sched ((unsigned long) scheduling_functions_start_here) -#define last_sched ((unsigned long) scheduling_functions_end_here) - unsigned long get_wchan(struct task_struct *p) { unsigned long fp, pc; @@ -425,7 +419,7 @@ unsigned long get_wchan(struct task_stru fp >= 8184+stack_page) return 0; pc = ((unsigned long *)fp)[1]; - if (pc < first_sched || pc >= last_sched) + if (!in_sched_functions(pc)) return pc; fp = *(unsigned long *) fp; } while (count++ < 16); @@ -440,8 +434,7 @@ unsigned long thread_saved_pc(struct tas struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp; /* Check whether the thread is blocked in resume() */ - if (sw->retpc > (unsigned long)scheduling_functions_start_here && - sw->retpc < (unsigned long)scheduling_functions_end_here) + if (in_sched_functions(sw->retpc)) return ((unsigned long *)sw->a6)[1]; else return sw->retpc; --- linux-2.6.6/arch/m68knommu/kernel/setup.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/m68knommu/kernel/setup.c 2004-05-10 01:19:18.568916152 -0700 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -44,8 +45,7 @@ unsigned long rom_length; unsigned long memory_start; unsigned long memory_end; -char command_line[512]; -char saved_command_line[512]; +char command_line[COMMAND_LINE_SIZE]; /* setup some dummy routines */ static void dummy_waitbut(void) --- linux-2.6.6/arch/m68knommu/platform/68360/config.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/m68knommu/platform/68360/config.c 2004-05-10 01:19:49.406228168 -0700 @@ -151,7 +151,6 @@ void BSP_reset (void) } unsigned char *scc1_hwaddr; -static int errno; #if defined (CONFIG_UCQUICC) _bsc0(char *, getserialnum) --- linux-2.6.6/arch/m68knommu/platform/68EZ328/config.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/m68knommu/platform/68EZ328/config.c 2004-05-10 01:19:49.406228168 -0700 @@ -94,7 +94,6 @@ void BSP_reset (void) } unsigned char *cs8900a_hwaddr; -static int errno; #ifdef CONFIG_UCSIMM _bsc0(char *, getserialnum) --- linux-2.6.6/arch/m68knommu/platform/68VZ328/ucdimm/config.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/m68knommu/platform/68VZ328/ucdimm/config.c 2004-05-10 01:19:49.407228016 -0700 @@ -89,7 +89,6 @@ void BSP_reset (void) } unsigned char *cs8900a_hwaddr; -static int errno; _bsc0(char *, getserialnum) _bsc1(unsigned char *, gethwaddr, int, a) --- linux-2.6.6/arch/m68k/q40/config.c 2004-04-03 20:39:10.000000000 -0800 +++ 25/arch/m68k/q40/config.c 2004-05-10 01:19:18.568916152 -0700 @@ -64,7 +64,6 @@ void q40_set_vectors (void); extern void q40_mksound(unsigned int /*freq*/, unsigned int /*ticks*/ ); -extern char *saved_command_line; extern char m68k_debug_device[]; static void q40_mem_console_write(struct console *co, const char *b, unsigned int count); --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/arch/mips/au1000/common/cputable.c 2004-05-10 01:19:15.171432648 -0700 @@ -0,0 +1,56 @@ +/* + * arch/mips/au1000/common/cputable.c + * + * Copyright (C) 2004 Dan Malek (dan@embeddededge.com) + * Copied from PowerPC and updated for Alchemy Au1xxx processors. + * + * Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org) + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + +struct cpu_spec* cur_cpu_spec[NR_CPUS]; + +/* With some thought, we can probably use the mask to reduce the + * size of the table. + */ +struct cpu_spec cpu_specs[] = { + { 0xffffffff, 0x00030100, "Au1000 DA", 1, 0 }, + { 0xffffffff, 0x00030201, "Au1000 HA", 1, 0 }, + { 0xffffffff, 0x00030202, "Au1000 HB", 1, 0 }, + { 0xffffffff, 0x00030203, "Au1000 HC", 1, 1 }, + { 0xffffffff, 0x00030204, "Au1000 HD", 1, 1 }, + { 0xffffffff, 0x01030200, "Au1500 AB", 1, 1 }, + { 0xffffffff, 0x01030201, "Au1500 AC", 0, 1 }, + { 0xffffffff, 0x01030202, "Au1500 AD", 0, 1 }, + { 0xffffffff, 0x02030200, "Au1100 AB", 1, 1 }, + { 0xffffffff, 0x02030201, "Au1100 BA", 1, 1 }, + { 0xffffffff, 0x02030202, "Au1100 BC", 1, 1 }, + { 0xffffffff, 0x02030203, "Au1100 BD", 0, 1 }, + { 0xffffffff, 0x02030204, "Au1100 BE", 0, 1 }, + { 0xffffffff, 0x03030200, "Au1550 AA", 0, 1 }, + { 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0 }, +}; + +void +set_cpuspec(void) +{ + struct cpu_spec *sp; + u32 prid; + + prid = read_c0_prid(); + sp = cpu_specs; + while ((prid & sp->prid_mask) != sp->prid_value) + sp++; + cur_cpu_spec[0] = sp; +} --- linux-2.6.6/arch/mips/au1000/common/Makefile 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/au1000/common/Makefile 2004-05-10 01:19:15.171432648 -0700 @@ -7,7 +7,7 @@ # obj-y += prom.o int-handler.o irq.o puts.o time.o reset.o \ - au1xxx_irqmap.o clocks.o power.o setup.o sleeper.o + au1xxx_irqmap.o clocks.o power.o setup.o sleeper.o cputable.o obj-$(CONFIG_AU1X00_USB_DEVICE) += usbdev.o obj-$(CONFIG_KGDB) += dbg_io.o --- linux-2.6.6/arch/mips/au1000/common/power.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/au1000/common/power.c 2004-05-10 01:19:15.171432648 -0700 @@ -320,7 +320,7 @@ static int pm_do_freq(ctl_table * ctl, i unsigned long val, pll; #define TMPBUFLEN 64 #define MAX_CPU_FREQ 396 - char buf[8], *p; + char buf[TMPBUFLEN], *p; unsigned long flags, intc0_mask, intc1_mask; unsigned long old_baud_base, old_cpu_freq, baud_rate, old_clk, old_refresh; --- linux-2.6.6/arch/mips/au1000/common/setup.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/au1000/common/setup.c 2004-05-10 01:19:15.172432496 -0700 @@ -65,40 +65,20 @@ extern void au1xxx_timer_setup(struct ir static int __init au1x00_setup(void) { + struct cpu_spec *sp; char *argptr; unsigned long prid, cpupll, bclk = 1; - /* Various early Au1000 Errata corrected by this */ - set_c0_config(1<<19); /* Config[OD] */ + set_cpuspec(); + sp = cur_cpu_spec[0]; board_setup(); /* board specific setup */ prid = read_c0_prid(); - switch (prid) - { - case 0x00030100: printk("Au1000 DA "); bclk = 0; break; - case 0x00030201: printk("Au1000 HA "); bclk = 0; break; - case 0x00030202: printk("Au1000 HB "); bclk = 0; break; - case 0x00030203: printk("Au1000 HC "); break; - case 0x00030204: printk("Au1000 HD "); break; - - case 0x01030200: printk("Au1500 AB "); break; - case 0x01030201: printk("Au1500 AC "); break; - case 0x01030202: printk("Au1500 AD "); break; - - case 0x02030200: printk("Au1100 AB "); break; - case 0x02030201: printk("Au1100 BA "); break; - case 0x02030202: printk("Au1100 BC "); break; - case 0x02030203: printk("Au1100 BD "); break; - case 0x02030204: printk("Au1100 BE "); break; - - case 0x03030200: printk("Au1550 AA "); break; - - default: printk("Unknown Au1x00! "); bclk = 0; break; - } cpupll = (au_readl(0xB1900060) & 0x3F) * 12; printk("(PRId %08X) @ %dMHZ\n", prid, cpupll); + bclk = sp->cpu_bclk; if (bclk) { /* Enable BCLK switching */ @@ -107,6 +87,15 @@ static int __init au1x00_setup(void) printk("BCLK switching enabled!\n"); } + if (sp->cpu_od) { + /* Various early Au1000 Errata corrected by this */ + set_c0_config(1<<19); /* Set Config[OD] */ + } + else { + /* Clear to obtain best system bus performance */ + clear_c0_config(1<<19); /* Clear Config[OD] */ + } + argptr = prom_getcmdline(); #ifdef CONFIG_SERIAL_AU1X00_CONSOLE --- linux-2.6.6/arch/mips/configs/atlas_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/atlas_defconfig 2004-05-10 01:19:15.173432344 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -289,8 +292,6 @@ CONFIG_IP_PNP=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -300,7 +301,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -321,12 +324,12 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set @@ -334,6 +337,11 @@ CONFIG_NETDEVICES=y # CONFIG_ETHERTAP is not set # +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y @@ -359,7 +367,6 @@ CONFIG_NET_ETHERNET=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set -# CONFIG_SIS190 is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set @@ -367,10 +374,12 @@ CONFIG_NET_ETHERNET=y # Ethernet (10000 Mbit) # # CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set # # Wireless LAN (non-hamradio) @@ -378,37 +387,19 @@ CONFIG_NET_ETHERNET=y # CONFIG_NET_RADIO is not set # -# Token Ring devices +# Wan interfaces # -# CONFIG_TR is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set # CONFIG_NET_FC is not set # CONFIG_RCPCI is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set # -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set - -# # ISDN subsystem # # CONFIG_ISDN is not set @@ -582,6 +573,7 @@ CONFIG_EXT2_FS=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/bosporus_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/bosporus_defconfig 2004-05-10 01:19:15.174432192 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_HOTPLUG=y # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -231,8 +234,6 @@ CONFIG_IP_PNP_BOOTP=y # # CONFIG_IP_VS is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set @@ -253,7 +254,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -274,6 +277,11 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set @@ -294,31 +302,15 @@ CONFIG_NET_ETHERNET=y # # Ethernet (10000 Mbit) # -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -# CONFIG_PPP_FILTER is not set -CONFIG_PPP_ASYNC=m -# CONFIG_PPP_SYNC_TTY is not set -CONFIG_PPP_DEFLATE=m -# CONFIG_PPP_BSDCOMP is not set -CONFIG_PPPOE=m -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set # # Token Ring devices # -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set # -# Wan interfaces +# Wireless LAN (non-hamradio) # -# CONFIG_WAN is not set +# CONFIG_NET_RADIO is not set # # PCMCIA network device support @@ -334,21 +326,20 @@ CONFIG_PCMCIA_3C589=m # CONFIG_PCMCIA_AXNET is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -531,6 +522,7 @@ CONFIG_AUTOFS4_FS=m # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/capcella_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/capcella_defconfig 2004-05-10 01:19:15.175432040 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -56,6 +59,7 @@ CONFIG_MACH_VR41XX=y # CONFIG_TANBAC_TB0229 is not set # CONFIG_VICTOR_MPC30X is not set CONFIG_ZAO_CAPCELLA=y +# CONFIG_VRC4173 is not set # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set # CONFIG_MACH_DECSTATION is not set @@ -251,8 +255,6 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -262,7 +264,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -283,12 +287,12 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set @@ -296,6 +300,11 @@ CONFIG_NETDEVICES=y # CONFIG_ETHERTAP is not set # +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y @@ -321,7 +330,6 @@ CONFIG_NET_ETHERNET=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set -# CONFIG_SIS190 is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set @@ -329,45 +337,29 @@ CONFIG_NET_ETHERNET=y # Ethernet (10000 Mbit) # # CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set +# CONFIG_S2IO is not set # # Token Ring devices # # CONFIG_TR is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support +# Wireless LAN (non-hamradio) # -# CONFIG_IRDA is not set +# CONFIG_NET_RADIO is not set # -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -555,6 +547,7 @@ CONFIG_AUTOFS4_FS=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/cobalt_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/cobalt_defconfig 2004-05-10 01:19:15.176431888 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -240,8 +243,6 @@ CONFIG_INET=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -251,7 +252,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -272,12 +275,12 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set @@ -285,6 +288,11 @@ CONFIG_NETDEVICES=y # CONFIG_ETHERTAP is not set # +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y @@ -310,7 +318,6 @@ CONFIG_NET_ETHERNET=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set -# CONFIG_SIS190 is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set @@ -318,45 +325,29 @@ CONFIG_NET_ETHERNET=y # Ethernet (10000 Mbit) # # CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set +# CONFIG_S2IO is not set # # Token Ring devices # # CONFIG_TR is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support +# Wireless LAN (non-hamradio) # -# CONFIG_IRDA is not set +# CONFIG_NET_RADIO is not set # -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -535,6 +526,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/db1000_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/db1000_defconfig 2004-05-10 01:19:15.177431736 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_HOTPLUG=y # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -250,8 +253,6 @@ CONFIG_IP_PNP_BOOTP=y # # CONFIG_IP_VS is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set @@ -272,7 +273,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -293,6 +296,11 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set @@ -314,31 +322,15 @@ CONFIG_MIPS_AU1X00_ENET=y # # Ethernet (10000 Mbit) # -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -# CONFIG_PPP_FILTER is not set -CONFIG_PPP_ASYNC=m -# CONFIG_PPP_SYNC_TTY is not set -CONFIG_PPP_DEFLATE=m -# CONFIG_PPP_BSDCOMP is not set -CONFIG_PPPOE=m -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set # # Token Ring devices # -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set # -# Wan interfaces +# Wireless LAN (non-hamradio) # -# CONFIG_WAN is not set +# CONFIG_NET_RADIO is not set # # PCMCIA network device support @@ -354,21 +346,20 @@ CONFIG_PCMCIA_3C589=m # CONFIG_PCMCIA_AXNET is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -557,6 +548,7 @@ CONFIG_AUTOFS4_FS=m # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/db1100_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/db1100_defconfig 2004-05-10 01:19:15.178431584 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_HOTPLUG=y # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -249,8 +252,6 @@ CONFIG_IP_PNP_BOOTP=y # # CONFIG_IP_VS is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set @@ -271,7 +272,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -292,6 +295,11 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set @@ -313,31 +321,15 @@ CONFIG_NET_ETHERNET=y # # Ethernet (10000 Mbit) # -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -# CONFIG_PPP_FILTER is not set -CONFIG_PPP_ASYNC=m -# CONFIG_PPP_SYNC_TTY is not set -CONFIG_PPP_DEFLATE=m -# CONFIG_PPP_BSDCOMP is not set -CONFIG_PPPOE=m -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set # # Token Ring devices # -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set # -# Wan interfaces +# Wireless LAN (non-hamradio) # -# CONFIG_WAN is not set +# CONFIG_NET_RADIO is not set # # PCMCIA network device support @@ -353,21 +345,20 @@ CONFIG_PCMCIA_3C589=m # CONFIG_PCMCIA_AXNET is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -553,6 +544,7 @@ CONFIG_AUTOFS4_FS=m # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/db1500_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/db1500_defconfig 2004-05-10 01:19:15.179431432 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_HOTPLUG=y # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -329,8 +332,6 @@ CONFIG_IP_PNP_BOOTP=y # # CONFIG_IP_VS is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set @@ -351,7 +352,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -372,6 +375,11 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set @@ -393,31 +401,15 @@ CONFIG_MIPS_AU1X00_ENET=y # # Ethernet (10000 Mbit) # -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -# CONFIG_PPP_FILTER is not set -CONFIG_PPP_ASYNC=m -# CONFIG_PPP_SYNC_TTY is not set -CONFIG_PPP_DEFLATE=m -# CONFIG_PPP_BSDCOMP is not set -CONFIG_PPPOE=m -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set # # Token Ring devices # -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set # -# Wan interfaces +# Wireless LAN (non-hamradio) # -# CONFIG_WAN is not set +# CONFIG_NET_RADIO is not set # # PCMCIA network device support @@ -433,21 +425,20 @@ CONFIG_PCMCIA_3C589=m # CONFIG_PCMCIA_AXNET is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -627,6 +618,7 @@ CONFIG_AUTOFS4_FS=m # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/ddb5476_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/ddb5476_defconfig 2004-05-10 01:19:15.180431280 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -251,8 +254,6 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -262,7 +263,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -283,12 +286,12 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set @@ -296,6 +299,11 @@ CONFIG_NETDEVICES=y # CONFIG_ETHERTAP is not set # +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y @@ -328,7 +336,6 @@ CONFIG_NET_ETHERNET=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set -# CONFIG_SIS190 is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set @@ -336,45 +343,29 @@ CONFIG_NET_ETHERNET=y # Ethernet (10000 Mbit) # # CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set +# CONFIG_S2IO is not set # # Token Ring devices # # CONFIG_TR is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support +# Wireless LAN (non-hamradio) # -# CONFIG_IRDA is not set +# CONFIG_NET_RADIO is not set # -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -573,6 +564,7 @@ CONFIG_EXT2_FS=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/ddb5477_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/ddb5477_defconfig 2004-05-10 01:19:15.181431128 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -221,8 +224,6 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -232,7 +233,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -253,12 +256,12 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set @@ -266,6 +269,11 @@ CONFIG_NETDEVICES=y # CONFIG_ETHERTAP is not set # +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y @@ -310,7 +318,6 @@ CONFIG_PCNET32=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set -# CONFIG_SIS190 is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set @@ -318,45 +325,29 @@ CONFIG_PCNET32=y # Ethernet (10000 Mbit) # # CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set +# CONFIG_S2IO is not set # # Token Ring devices # # CONFIG_TR is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support +# Wireless LAN (non-hamradio) # -# CONFIG_IRDA is not set +# CONFIG_NET_RADIO is not set # -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -532,6 +523,7 @@ CONFIG_AUTOFS4_FS=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/decstation_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/decstation_defconfig 2004-05-10 01:19:15.182430976 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -247,8 +250,6 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -258,7 +259,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -279,6 +282,11 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set @@ -300,41 +308,24 @@ CONFIG_DECLANCE=y # # Ethernet (10000 Mbit) # -# CONFIG_PPP is not set -# CONFIG_SLIP is not set # -# Wireless LAN (non-hamradio) +# Token Ring devices # -# CONFIG_NET_RADIO is not set # -# Token Ring devices +# Wireless LAN (non-hamradio) # -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set +# CONFIG_NET_RADIO is not set # # Wan interfaces # # CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -511,6 +502,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/e55_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/e55_defconfig 2004-05-10 01:19:15.183430824 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -56,6 +59,7 @@ CONFIG_CASIO_E55=y # CONFIG_TANBAC_TB0229 is not set # CONFIG_VICTOR_MPC30X is not set # CONFIG_ZAO_CAPCELLA is not set +# CONFIG_VRC4171 is not set # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set # CONFIG_MACH_DECSTATION is not set @@ -246,8 +250,6 @@ CONFIG_IP_MULTICAST=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -257,7 +259,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -278,12 +282,12 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set @@ -291,6 +295,11 @@ CONFIG_NETDEVICES=y # CONFIG_ETHERTAP is not set # +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y @@ -313,42 +322,25 @@ CONFIG_NET_ETHERNET=y # # Ethernet (10000 Mbit) # -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set # # Token Ring devices # # CONFIG_TR is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set # -# IrDA (infrared) support +# Wireless LAN (non-hamradio) # -# CONFIG_IRDA is not set +# CONFIG_NET_RADIO is not set # -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -535,6 +527,7 @@ CONFIG_AUTOFS4_FS=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/eagle_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/eagle_defconfig 2004-05-10 01:19:15.184430672 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_HOTPLUG=y # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -56,6 +59,7 @@ CONFIG_NEC_EAGLE=y # CONFIG_TANBAC_TB0229 is not set # CONFIG_VICTOR_MPC30X is not set # CONFIG_ZAO_CAPCELLA is not set +CONFIG_VRC4173=y # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set # CONFIG_MACH_DECSTATION is not set @@ -88,7 +92,6 @@ CONFIG_DMA_NONCOHERENT=y CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_IRQ_CPU=y CONFIG_DUMMY_KEYB=y -CONFIG_VRC4173=y CONFIG_MIPS_L1_CACHE_SHIFT=5 # CONFIG_FB is not set @@ -329,8 +332,6 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -340,7 +341,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -361,12 +364,12 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set @@ -374,6 +377,11 @@ CONFIG_NETDEVICES=y # CONFIG_ETHERTAP is not set # +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y @@ -399,7 +407,6 @@ CONFIG_NET_ETHERNET=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set -# CONFIG_SIS190 is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set @@ -407,28 +414,17 @@ CONFIG_NET_ETHERNET=y # Ethernet (10000 Mbit) # # CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set +# CONFIG_S2IO is not set # # Token Ring devices # # CONFIG_TR is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set # -# Wan interfaces +# Wireless LAN (non-hamradio) # -# CONFIG_WAN is not set +# CONFIG_NET_RADIO is not set # # PCMCIA network device support @@ -444,21 +440,16 @@ CONFIG_PCMCIA_PCNET=m # CONFIG_PCMCIA_AXNET is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -652,6 +643,7 @@ CONFIG_AUTOFS4_FS=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/ev64120_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/ev64120_defconfig 2004-05-10 01:19:15.185430520 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -227,8 +230,6 @@ CONFIG_IP_PNP=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -238,7 +239,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -259,12 +262,12 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set @@ -272,6 +275,11 @@ CONFIG_NETDEVICES=y # CONFIG_ETHERTAP is not set # +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y @@ -297,7 +305,6 @@ CONFIG_NET_ETHERNET=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set -# CONFIG_SIS190 is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set @@ -305,6 +312,22 @@ CONFIG_NET_ETHERNET=y # Ethernet (10000 Mbit) # # CONFIG_IXGB is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set CONFIG_PPP=y @@ -316,43 +339,11 @@ CONFIG_PPP_ASYNC=y # CONFIG_PPP_BSDCOMP is not set # CONFIG_PPPOE is not set # CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices -# -# CONFIG_TR is not set # CONFIG_RCPCI is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set # -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set - -# # ISDN subsystem # # CONFIG_ISDN is not set @@ -526,6 +517,7 @@ CONFIG_EXT2_FS=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/ev96100_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/ev96100_defconfig 2004-05-10 01:19:15.186430368 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -220,8 +223,6 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -231,7 +232,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -252,6 +255,11 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set @@ -273,41 +281,24 @@ CONFIG_MIPS_GT96100ETH=y # # Ethernet (10000 Mbit) # -# CONFIG_PPP is not set -# CONFIG_SLIP is not set # -# Wireless LAN (non-hamradio) +# Token Ring devices # -# CONFIG_NET_RADIO is not set # -# Token Ring devices +# Wireless LAN (non-hamradio) # -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set +# CONFIG_NET_RADIO is not set # # Wan interfaces # # CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -481,6 +472,7 @@ CONFIG_EXT2_FS=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/ip22_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/ip22_defconfig 2004-05-10 01:19:15.187430216 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set CONFIG_IKCONFIG=y @@ -32,6 +34,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -298,8 +301,6 @@ CONFIG_INET6_AH=m CONFIG_INET6_ESP=m CONFIG_INET6_IPCOMP=m CONFIG_IPV6_TUNNEL=m -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set @@ -359,6 +360,8 @@ CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m CONFIG_IP_NF_COMPAT_IPCHAINS=m CONFIG_IP_NF_COMPAT_IPFWADM=m +CONFIG_IP_NF_TARGET_NOTRACK=m +CONFIG_IP_NF_RAW=m # # IPv6: Netfilter Configuration @@ -382,6 +385,7 @@ CONFIG_IP6_NF_FILTER=m CONFIG_IP6_NF_TARGET_LOG=m CONFIG_IP6_NF_MANGLE=m CONFIG_IP6_NF_TARGET_MARK=m +CONFIG_IP6_NF_RAW=m CONFIG_XFRM=y CONFIG_XFRM_USER=m @@ -395,7 +399,9 @@ CONFIG_IP_SCTP=m # CONFIG_SCTP_HMAC_SHA1 is not set CONFIG_SCTP_HMAC_MD5=y # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -440,6 +446,11 @@ CONFIG_NET_CLS_POLICE=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y CONFIG_DUMMY=m CONFIG_BONDING=m @@ -461,41 +472,24 @@ CONFIG_SGISEEQ=y # # Ethernet (10000 Mbit) # -# CONFIG_PPP is not set -# CONFIG_SLIP is not set # -# Wireless LAN (non-hamradio) +# Token Ring devices # -# CONFIG_NET_RADIO is not set # -# Token Ring devices +# Wireless LAN (non-hamradio) # -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set +# CONFIG_NET_RADIO is not set # # Wan interfaces # # CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -709,6 +703,7 @@ CONFIG_VFAT_FS=m # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/ip27_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/ip27_defconfig 2004-05-10 01:19:15.189429912 -0700 @@ -17,8 +17,10 @@ CONFIG_STANDALONE=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=15 # CONFIG_HOTPLUG is not set CONFIG_IKCONFIG=y @@ -30,6 +32,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -112,6 +115,7 @@ CONFIG_CPU_R10000=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_16KB is not set # CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y @@ -206,7 +210,7 @@ CONFIG_SCSI_LOGGING=y # # SCSI Transport Attributes # -CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_FC_ATTRS is not set # @@ -293,8 +297,6 @@ CONFIG_IP_PNP=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -304,7 +306,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -320,40 +324,40 @@ CONFIG_XFRM=y # QoS and/or fair queueing # CONFIG_NET_SCHED=y -CONFIG_NET_SCH_CBQ=m -CONFIG_NET_SCH_HTB=m -CONFIG_NET_SCH_HFSC=m -CONFIG_NET_SCH_CSZ=m -CONFIG_NET_SCH_PRIO=m -CONFIG_NET_SCH_RED=m -CONFIG_NET_SCH_SFQ=m -CONFIG_NET_SCH_TEQL=m -CONFIG_NET_SCH_TBF=m -CONFIG_NET_SCH_GRED=m -CONFIG_NET_SCH_DSMARK=m -CONFIG_NET_SCH_DELAY=m +CONFIG_NET_SCH_CBQ=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_HFSC=y +CONFIG_NET_SCH_CSZ=y +CONFIG_NET_SCH_PRIO=y +CONFIG_NET_SCH_RED=y +CONFIG_NET_SCH_SFQ=y +CONFIG_NET_SCH_TEQL=y +CONFIG_NET_SCH_TBF=y +CONFIG_NET_SCH_GRED=y +CONFIG_NET_SCH_DSMARK=y +CONFIG_NET_SCH_DELAY=y CONFIG_NET_QOS=y CONFIG_NET_ESTIMATOR=y CONFIG_NET_CLS=y -CONFIG_NET_CLS_TCINDEX=m -CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_TCINDEX=y +CONFIG_NET_CLS_ROUTE4=y CONFIG_NET_CLS_ROUTE=y -CONFIG_NET_CLS_FW=m -CONFIG_NET_CLS_U32=m -CONFIG_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +CONFIG_NET_CLS_RSVP=y +CONFIG_NET_CLS_RSVP6=y CONFIG_NET_CLS_POLICE=y # # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set @@ -361,6 +365,11 @@ CONFIG_NETDEVICES=y # CONFIG_ETHERTAP is not set # +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y @@ -389,7 +398,6 @@ CONFIG_SGI_IOC3_ETH_HW_TX_CSUM=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set -# CONFIG_SIS190 is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set @@ -397,45 +405,29 @@ CONFIG_SGI_IOC3_ETH_HW_TX_CSUM=y # Ethernet (10000 Mbit) # # CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set +# CONFIG_S2IO is not set # # Token Ring devices # # CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support +# Wireless LAN (non-hamradio) # -# CONFIG_IRDA is not set +# CONFIG_NET_RADIO is not set # -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -602,6 +594,7 @@ CONFIG_AUTOFS_FS=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y @@ -691,27 +684,27 @@ CONFIG_CMDLINE="" # CONFIG_CRYPTO=y CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=m -CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_SHA1=m -CONFIG_CRYPTO_SHA256=m -CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_BLOWFISH=m -CONFIG_CRYPTO_TWOFISH=m -CONFIG_CRYPTO_SERPENT=m -CONFIG_CRYPTO_AES=m -CONFIG_CRYPTO_CAST5=m -CONFIG_CRYPTO_CAST6=m -CONFIG_CRYPTO_ARC4=m -CONFIG_CRYPTO_DEFLATE=m -CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_BLOWFISH=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_SERPENT=y +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_CAST5=y +CONFIG_CRYPTO_CAST6=y +CONFIG_CRYPTO_ARC4=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_MICHAEL_MIC=y # CONFIG_CRYPTO_TEST is not set # # Library routines # CONFIG_CRC32=y -CONFIG_ZLIB_INFLATE=m -CONFIG_ZLIB_DEFLATE=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y --- linux-2.6.6/arch/mips/configs/ip32_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/ip32_defconfig 2004-05-10 01:19:15.190429760 -0700 @@ -18,8 +18,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set CONFIG_BSD_PROCESS_ACCT=y CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set @@ -30,6 +32,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -289,8 +292,6 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -300,7 +301,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -321,12 +324,12 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set @@ -334,6 +337,11 @@ CONFIG_NETDEVICES=y # CONFIG_ETHERTAP is not set # +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y @@ -360,7 +368,6 @@ CONFIG_SGI_O2MACE_ETH=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set -# CONFIG_SIS190 is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set @@ -368,45 +375,29 @@ CONFIG_SGI_O2MACE_ETH=y # Ethernet (10000 Mbit) # # CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set +# CONFIG_S2IO is not set # # Token Ring devices # # CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support +# Wireless LAN (non-hamradio) # -# CONFIG_IRDA is not set +# CONFIG_NET_RADIO is not set # -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -583,6 +574,7 @@ CONFIG_EXT2_FS=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/it8172_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/it8172_defconfig 2004-05-10 01:19:15.190429760 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set CONFIG_BSD_PROCESS_ACCT=y CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -294,8 +297,6 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -305,7 +306,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -326,6 +329,11 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set @@ -346,41 +354,24 @@ CONFIG_NET_ETHERNET=y # # Ethernet (10000 Mbit) # -# CONFIG_PPP is not set -# CONFIG_SLIP is not set # -# Wireless LAN (non-hamradio) +# Token Ring devices # -# CONFIG_NET_RADIO is not set # -# Token Ring devices +# Wireless LAN (non-hamradio) # -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set +# CONFIG_NET_RADIO is not set # # Wan interfaces # # CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -580,6 +571,7 @@ CONFIG_EXT2_FS=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/ivr_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/ivr_defconfig 2004-05-10 01:19:15.191429608 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set CONFIG_BSD_PROCESS_ACCT=y CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -245,8 +248,6 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -256,7 +257,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -277,12 +280,12 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set @@ -290,6 +293,11 @@ CONFIG_NETDEVICES=y # CONFIG_ETHERTAP is not set # +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y @@ -315,7 +323,6 @@ CONFIG_NET_ETHERNET=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set -# CONFIG_SIS190 is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set @@ -323,45 +330,29 @@ CONFIG_NET_ETHERNET=y # Ethernet (10000 Mbit) # # CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set +# CONFIG_S2IO is not set # # Token Ring devices # # CONFIG_TR is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support +# Wireless LAN (non-hamradio) # -# CONFIG_IRDA is not set +# CONFIG_NET_RADIO is not set # -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -538,6 +529,7 @@ CONFIG_EXT2_FS=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/jaguar-atx_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/jaguar-atx_defconfig 2004-05-10 01:19:15.192429456 -0700 @@ -21,6 +21,7 @@ CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set CONFIG_IKCONFIG=y @@ -32,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -219,10 +221,10 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -236,16 +238,21 @@ CONFIG_IP_PNP_BOOTP=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set # # ARCnet devices # # CONFIG_ARCNET is not set -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set # # Ethernet (10 or 100Mbit) @@ -299,14 +306,7 @@ CONFIG_MV64340_ETH_2=y # Ethernet (10000 Mbit) # # CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set +# CONFIG_S2IO is not set # # Token Ring devices @@ -314,26 +314,17 @@ CONFIG_MV64340_ETH_2=y # CONFIG_TR is not set # -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support +# Wireless LAN (non-hamradio) # -# CONFIG_IRDA is not set +# CONFIG_NET_RADIO is not set # -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set # # ISDN subsystem @@ -483,6 +474,7 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVPTS_FS_XATTR is not set # CONFIG_TMPFS is not set # CONFIG_HUGETLB_PAGE is not set --- linux-2.6.6/arch/mips/configs/jmr3927_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/jmr3927_defconfig 2004-05-10 01:19:15.193429304 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -219,8 +222,6 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -230,7 +231,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -251,12 +254,12 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set @@ -264,6 +267,11 @@ CONFIG_NETDEVICES=y # CONFIG_ETHERTAP is not set # +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y @@ -289,7 +297,6 @@ CONFIG_NET_ETHERNET=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set -# CONFIG_SIS190 is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set @@ -297,45 +304,29 @@ CONFIG_NET_ETHERNET=y # Ethernet (10000 Mbit) # # CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set +# CONFIG_S2IO is not set # # Token Ring devices # # CONFIG_TR is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support +# Wireless LAN (non-hamradio) # -# CONFIG_IRDA is not set +# CONFIG_NET_RADIO is not set # -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -547,6 +538,7 @@ CONFIG_DUMMY_CONSOLE=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set # CONFIG_TMPFS is not set # CONFIG_HUGETLB_PAGE is not set --- linux-2.6.6/arch/mips/configs/lasat200_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/lasat200_defconfig 2004-05-10 01:19:15.194429152 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -334,8 +337,6 @@ CONFIG_INET=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -345,7 +346,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -366,16 +369,21 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set # # ARCnet devices # # CONFIG_ARCNET is not set -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set # # Ethernet (10 or 100Mbit) @@ -403,7 +411,6 @@ CONFIG_NET_ETHERNET=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set -# CONFIG_SIS190 is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set @@ -411,45 +418,29 @@ CONFIG_NET_ETHERNET=y # Ethernet (10000 Mbit) # # CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set +# CONFIG_S2IO is not set # # Token Ring devices # # CONFIG_TR is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support +# Wireless LAN (non-hamradio) # -# CONFIG_IRDA is not set +# CONFIG_NET_RADIO is not set # -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -630,6 +621,7 @@ CONFIG_FS_MBCACHE=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/malta_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/malta_defconfig 2004-05-10 01:19:15.195429000 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -233,8 +236,6 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -244,7 +245,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -265,12 +268,12 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set @@ -278,6 +281,11 @@ CONFIG_NETDEVICES=y # CONFIG_ETHERTAP is not set # +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y @@ -322,7 +330,6 @@ CONFIG_PCNET32=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set -# CONFIG_SIS190 is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set @@ -330,45 +337,29 @@ CONFIG_PCNET32=y # Ethernet (10000 Mbit) # # CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set +# CONFIG_S2IO is not set # # Token Ring devices # # CONFIG_TR is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support +# Wireless LAN (non-hamradio) # -# CONFIG_IRDA is not set +# CONFIG_NET_RADIO is not set # -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -543,6 +534,7 @@ CONFIG_AUTOFS_FS=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/mirage_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/mirage_defconfig 2004-05-10 01:19:15.196428848 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_HOTPLUG=y # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -231,8 +234,6 @@ CONFIG_IP_PNP_BOOTP=y # # CONFIG_IP_VS is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set @@ -253,7 +254,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -274,6 +277,11 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set @@ -294,31 +302,15 @@ CONFIG_NET_ETHERNET=y # # Ethernet (10000 Mbit) # -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -# CONFIG_PPP_FILTER is not set -CONFIG_PPP_ASYNC=m -# CONFIG_PPP_SYNC_TTY is not set -CONFIG_PPP_DEFLATE=m -# CONFIG_PPP_BSDCOMP is not set -CONFIG_PPPOE=m -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set # # Token Ring devices # -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set # -# Wan interfaces +# Wireless LAN (non-hamradio) # -# CONFIG_WAN is not set +# CONFIG_NET_RADIO is not set # # PCMCIA network device support @@ -334,21 +326,20 @@ CONFIG_PCMCIA_3C589=m # CONFIG_PCMCIA_AXNET is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -531,6 +522,7 @@ CONFIG_AUTOFS4_FS=m # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/mpc30x_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/mpc30x_defconfig 2004-05-10 01:19:15.198428544 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -56,6 +59,7 @@ CONFIG_MACH_VR41XX=y # CONFIG_TANBAC_TB0229 is not set CONFIG_VICTOR_MPC30X=y # CONFIG_ZAO_CAPCELLA is not set +CONFIG_VRC4173=y # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set # CONFIG_MACH_DECSTATION is not set @@ -88,7 +92,6 @@ CONFIG_DMA_NONCOHERENT=y CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_IRQ_CPU=y CONFIG_DUMMY_KEYB=y -CONFIG_VRC4173=y CONFIG_MIPS_L1_CACHE_SHIFT=5 # CONFIG_FB is not set @@ -123,7 +126,9 @@ CONFIG_CPU_HAS_SYNC=y # # Bus options (PCI, PCMCIA, EISA, ISA, TC) # -# CONFIG_PCI is not set +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y CONFIG_MMU=y # @@ -159,8 +164,13 @@ CONFIG_TRAD_SIGNALS=y # Block devices # # CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_CARMEL is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_LBD is not set @@ -182,6 +192,7 @@ CONFIG_TRAD_SIGNALS=y # # Fusion MPT device support # +# CONFIG_FUSION is not set # # IEEE 1394 (FireWire) support @@ -191,6 +202,7 @@ CONFIG_TRAD_SIGNALS=y # # I2O device support # +# CONFIG_I2O is not set # # Networking support @@ -221,8 +233,6 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -232,7 +242,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -253,6 +265,11 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set @@ -261,53 +278,66 @@ CONFIG_NETDEVICES=y # CONFIG_ETHERTAP is not set # +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y # CONFIG_MII is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set # -# Ethernet (1000 Mbit) +# Tulip family network device support # +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set # -# Ethernet (10000 Mbit) +# Ethernet (1000 Mbit) # -# CONFIG_PPP is not set -# CONFIG_SLIP is not set +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set # -# Wireless LAN (non-hamradio) +# Ethernet (10000 Mbit) # -# CONFIG_NET_RADIO is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set # # Token Ring devices # -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set +# CONFIG_TR is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support +# Wireless LAN (non-hamradio) # -# CONFIG_IRDA is not set +# CONFIG_NET_RADIO is not set # -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -345,6 +375,7 @@ CONFIG_SERIO=y CONFIG_SERIO_I8042=y CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set # # Input Device Drivers @@ -442,6 +473,7 @@ CONFIG_DUMMY_CONSOLE=y # # USB support # +# CONFIG_USB is not set # # USB Gadget Support @@ -481,6 +513,7 @@ CONFIG_AUTOFS4_FS=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/mtx1_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/mtx1_defconfig 2004-05-10 01:19:15.199428392 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_HOTPLUG=y # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -231,8 +234,6 @@ CONFIG_IP_PNP_BOOTP=y # # CONFIG_IP_VS is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set @@ -253,7 +254,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -274,6 +277,11 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set @@ -294,31 +302,15 @@ CONFIG_NET_ETHERNET=y # # Ethernet (10000 Mbit) # -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -# CONFIG_PPP_FILTER is not set -CONFIG_PPP_ASYNC=m -# CONFIG_PPP_SYNC_TTY is not set -CONFIG_PPP_DEFLATE=m -# CONFIG_PPP_BSDCOMP is not set -CONFIG_PPPOE=m -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set # # Token Ring devices # -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set # -# Wan interfaces +# Wireless LAN (non-hamradio) # -# CONFIG_WAN is not set +# CONFIG_NET_RADIO is not set # # PCMCIA network device support @@ -334,21 +326,20 @@ CONFIG_PCMCIA_3C589=m # CONFIG_PCMCIA_AXNET is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -531,6 +522,7 @@ CONFIG_AUTOFS4_FS=m # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/ocelot_c_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/ocelot_c_defconfig 2004-05-10 01:19:15.200428240 -0700 @@ -18,8 +18,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set @@ -30,6 +32,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -210,8 +213,6 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -221,7 +222,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -242,6 +245,11 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set @@ -266,41 +274,24 @@ CONFIG_MV64340_ETH_0=y # # Ethernet (10000 Mbit) # -# CONFIG_PPP is not set -# CONFIG_SLIP is not set # -# Wireless LAN (non-hamradio) +# Token Ring devices # -# CONFIG_NET_RADIO is not set # -# Token Ring devices +# Wireless LAN (non-hamradio) # -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set +# CONFIG_NET_RADIO is not set # # Wan interfaces # # CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -474,6 +465,7 @@ CONFIG_EXT2_FS=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/ocelot_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/ocelot_defconfig 2004-05-10 01:19:15.200428240 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -218,8 +221,6 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -229,7 +230,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -250,6 +253,11 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set @@ -270,41 +278,24 @@ CONFIG_NET_ETHERNET=y # # Ethernet (10000 Mbit) # -# CONFIG_PPP is not set -# CONFIG_SLIP is not set # -# Wireless LAN (non-hamradio) +# Token Ring devices # -# CONFIG_NET_RADIO is not set # -# Token Ring devices +# Wireless LAN (non-hamradio) # -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set +# CONFIG_NET_RADIO is not set # # Wan interfaces # # CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -478,6 +469,7 @@ CONFIG_EXT2_FS=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/osprey_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/osprey_defconfig 2004-05-10 01:19:15.201428088 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -212,8 +215,6 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -223,7 +224,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -244,6 +247,11 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set @@ -264,41 +272,24 @@ CONFIG_NET_ETHERNET=y # # Ethernet (10000 Mbit) # -# CONFIG_PPP is not set -# CONFIG_SLIP is not set # -# Wireless LAN (non-hamradio) +# Token Ring devices # -# CONFIG_NET_RADIO is not set # -# Token Ring devices +# Wireless LAN (non-hamradio) # -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set +# CONFIG_NET_RADIO is not set # # Wan interfaces # # CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -472,6 +463,7 @@ CONFIG_EXT2_FS=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/pb1000_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/pb1000_defconfig 2004-05-10 01:19:15.202427936 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_HOTPLUG=y # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -231,8 +234,6 @@ CONFIG_IP_PNP_BOOTP=y # # CONFIG_IP_VS is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set @@ -253,7 +254,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -274,6 +277,11 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set @@ -294,31 +302,15 @@ CONFIG_NET_ETHERNET=y # # Ethernet (10000 Mbit) # -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -# CONFIG_PPP_FILTER is not set -CONFIG_PPP_ASYNC=m -# CONFIG_PPP_SYNC_TTY is not set -CONFIG_PPP_DEFLATE=m -# CONFIG_PPP_BSDCOMP is not set -CONFIG_PPPOE=m -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set # # Token Ring devices # -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set # -# Wan interfaces +# Wireless LAN (non-hamradio) # -# CONFIG_WAN is not set +# CONFIG_NET_RADIO is not set # # PCMCIA network device support @@ -334,21 +326,20 @@ CONFIG_PCMCIA_3C589=m # CONFIG_PCMCIA_AXNET is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -531,6 +522,7 @@ CONFIG_AUTOFS4_FS=m # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/pb1100_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/pb1100_defconfig 2004-05-10 01:19:15.203427784 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_HOTPLUG=y # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -231,8 +234,6 @@ CONFIG_IP_PNP_BOOTP=y # # CONFIG_IP_VS is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set @@ -253,7 +254,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -274,6 +277,11 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set @@ -294,31 +302,15 @@ CONFIG_NET_ETHERNET=y # # Ethernet (10000 Mbit) # -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -# CONFIG_PPP_FILTER is not set -CONFIG_PPP_ASYNC=m -# CONFIG_PPP_SYNC_TTY is not set -CONFIG_PPP_DEFLATE=m -# CONFIG_PPP_BSDCOMP is not set -CONFIG_PPPOE=m -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set # # Token Ring devices # -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set # -# Wan interfaces +# Wireless LAN (non-hamradio) # -# CONFIG_WAN is not set +# CONFIG_NET_RADIO is not set # # PCMCIA network device support @@ -334,21 +326,20 @@ CONFIG_PCMCIA_3C589=m # CONFIG_PCMCIA_AXNET is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -531,6 +522,7 @@ CONFIG_AUTOFS4_FS=m # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/pb1500_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/pb1500_defconfig 2004-05-10 01:19:15.204427632 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_HOTPLUG=y # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -315,8 +318,6 @@ CONFIG_IP_PNP_BOOTP=y # # CONFIG_IP_VS is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set @@ -337,7 +338,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -358,12 +361,12 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set @@ -371,6 +374,11 @@ CONFIG_NETDEVICES=y # CONFIG_ETHERTAP is not set # +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y @@ -397,7 +405,6 @@ CONFIG_MIPS_AU1X00_ENET=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set -# CONFIG_SIS190 is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set @@ -405,35 +412,17 @@ CONFIG_MIPS_AU1X00_ENET=y # Ethernet (10000 Mbit) # # CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -# CONFIG_PPP_FILTER is not set -CONFIG_PPP_ASYNC=m -# CONFIG_PPP_SYNC_TTY is not set -CONFIG_PPP_DEFLATE=m -# CONFIG_PPP_BSDCOMP is not set -CONFIG_PPPOE=m -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set +# CONFIG_S2IO is not set # # Token Ring devices # # CONFIG_TR is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set # -# Wan interfaces +# Wireless LAN (non-hamradio) # -# CONFIG_WAN is not set +# CONFIG_NET_RADIO is not set # # PCMCIA network device support @@ -449,21 +438,23 @@ CONFIG_PCMCIA_3C589=m # CONFIG_PCMCIA_AXNET is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m +# CONFIG_SLIP is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -646,6 +637,7 @@ CONFIG_AUTOFS4_FS=m # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/pb1550_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/pb1550_defconfig 2004-05-10 01:19:15.205427480 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_HOTPLUG=y # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -314,8 +317,6 @@ CONFIG_IP_PNP_BOOTP=y # # CONFIG_IP_VS is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set @@ -336,7 +337,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -357,12 +360,12 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set @@ -370,6 +373,11 @@ CONFIG_NETDEVICES=y # CONFIG_ETHERTAP is not set # +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y @@ -396,7 +404,6 @@ CONFIG_MIPS_AU1X00_ENET=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set -# CONFIG_SIS190 is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set @@ -404,35 +411,17 @@ CONFIG_MIPS_AU1X00_ENET=y # Ethernet (10000 Mbit) # # CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -# CONFIG_PPP_FILTER is not set -CONFIG_PPP_ASYNC=m -# CONFIG_PPP_SYNC_TTY is not set -CONFIG_PPP_DEFLATE=m -# CONFIG_PPP_BSDCOMP is not set -CONFIG_PPPOE=m -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set +# CONFIG_S2IO is not set # # Token Ring devices # # CONFIG_TR is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set # -# Wan interfaces +# Wireless LAN (non-hamradio) # -# CONFIG_WAN is not set +# CONFIG_NET_RADIO is not set # # PCMCIA network device support @@ -448,21 +437,23 @@ CONFIG_PCMCIA_3C589=m # CONFIG_PCMCIA_AXNET is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m +# CONFIG_SLIP is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -645,6 +636,7 @@ CONFIG_AUTOFS4_FS=m # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/rm200_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/rm200_defconfig 2004-05-10 01:19:15.207427176 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set CONFIG_IKCONFIG=y @@ -32,6 +34,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -250,7 +253,7 @@ CONFIG_SCSI_CONSTANTS=y # # SCSI Transport Attributes # -CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_FC_ATTRS is not set # @@ -385,10 +388,6 @@ CONFIG_INET6_AH=m CONFIG_INET6_ESP=m CONFIG_INET6_IPCOMP=m CONFIG_IPV6_TUNNEL=m -CONFIG_DECNET=m -# CONFIG_DECNET_SIOCGIFCONF is not set -# CONFIG_DECNET_ROUTER is not set -CONFIG_BRIDGE=m CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set CONFIG_BRIDGE_NETFILTER=y @@ -450,6 +449,8 @@ CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m CONFIG_IP_NF_COMPAT_IPCHAINS=m CONFIG_IP_NF_COMPAT_IPFWADM=m +CONFIG_IP_NF_TARGET_NOTRACK=m +CONFIG_IP_NF_RAW=m # # IPv6: Netfilter Configuration @@ -473,6 +474,7 @@ CONFIG_IP6_NF_FILTER=m CONFIG_IP6_NF_TARGET_LOG=m CONFIG_IP6_NF_MANGLE=m CONFIG_IP6_NF_TARGET_MARK=m +CONFIG_IP6_NF_RAW=m # # DECnet: Netfilter Configuration @@ -509,7 +511,11 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +CONFIG_BRIDGE=m # CONFIG_VLAN_8021Q is not set +CONFIG_DECNET=m +# CONFIG_DECNET_SIOCGIFCONF is not set +# CONFIG_DECNET_ROUTER is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -554,12 +560,34 @@ CONFIG_NET_CLS_POLICE=y # Network testing # # CONFIG_NET_PKTGEN is not set -CONFIG_NETDEVICES=y +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +CONFIG_HAMRADIO=y # -# ARCnet devices +# Packet Radio protocols # -# CONFIG_ARCNET is not set +CONFIG_AX25=m +CONFIG_AX25_DAMA_SLAVE=y +CONFIG_NETROM=m +CONFIG_ROSE=m + +# +# AX.25 network device drivers +# +CONFIG_MKISS=m +CONFIG_6PACK=m +CONFIG_BPQETHER=m +# CONFIG_DMASCC is not set +# CONFIG_SCC is not set +# CONFIG_BAYCOM_SER_FDX is not set +# CONFIG_BAYCOM_SER_HDX is not set +# CONFIG_BAYCOM_PAR is not set +# CONFIG_BAYCOM_EPP is not set +# CONFIG_YAM is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +CONFIG_NETDEVICES=y CONFIG_DUMMY=m CONFIG_BONDING=m CONFIG_EQUALIZER=m @@ -567,6 +595,11 @@ CONFIG_TUN=m CONFIG_ETHERTAP=m # +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y @@ -633,7 +666,6 @@ CONFIG_EEPRO100=m # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set -# CONFIG_SIS190 is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set @@ -641,11 +673,12 @@ CONFIG_EEPRO100=m # Ethernet (10000 Mbit) # # CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -CONFIG_PLIP=m -# CONFIG_PPP is not set -# CONFIG_SLIP is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set # # Wireless LAN (non-hamradio) @@ -653,59 +686,20 @@ CONFIG_PLIP=m # CONFIG_NET_RADIO is not set # -# Token Ring devices +# Wan interfaces # -# CONFIG_TR is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PLIP=m +# CONFIG_PPP is not set +# CONFIG_SLIP is not set # CONFIG_NET_FC is not set # CONFIG_RCPCI is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set # -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -CONFIG_HAMRADIO=y - -# -# Packet Radio protocols -# -CONFIG_AX25=m -CONFIG_AX25_DAMA_SLAVE=y -CONFIG_NETROM=m -CONFIG_ROSE=m - -# -# AX.25 network device drivers -# -# CONFIG_MKISS is not set -# CONFIG_6PACK is not set -CONFIG_BPQETHER=m -# CONFIG_DMASCC is not set -# CONFIG_SCC is not set -# CONFIG_BAYCOM_SER_FDX is not set -# CONFIG_BAYCOM_SER_HDX is not set -# CONFIG_BAYCOM_PAR is not set -# CONFIG_BAYCOM_EPP is not set -# CONFIG_YAM is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set - -# # ISDN subsystem # # CONFIG_ISDN is not set @@ -873,6 +867,7 @@ CONFIG_USB_DEVICEFS=y # CONFIG_USB_EHCI_HCD=m # CONFIG_USB_EHCI_SPLIT_ISO is not set +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set CONFIG_USB_OHCI_HCD=m CONFIG_USB_UHCI_HCD=m @@ -1019,7 +1014,8 @@ CONFIG_USB_AUERSWALD=m CONFIG_USB_RIO500=m CONFIG_USB_LEGOTOWER=m CONFIG_USB_LCD=m -# CONFIG_USB_LED is not set +CONFIG_USB_LED=m +CONFIG_USB_CYTHERM=m CONFIG_USB_TEST=m # @@ -1031,9 +1027,11 @@ CONFIG_USB_NET2280=m # CONFIG_USB_GADGET_PXA2XX is not set # CONFIG_USB_GADGET_GOKU is not set # CONFIG_USB_GADGET_SA1100 is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set CONFIG_USB_GADGET_DUALSPEED=y CONFIG_USB_ZERO=m CONFIG_USB_ETH=m +# CONFIG_USB_ETH_RNDIS is not set CONFIG_USB_GADGETFS=m # CONFIG_USB_FILE_STORAGE is not set # CONFIG_USB_G_SERIAL is not set @@ -1093,6 +1091,7 @@ CONFIG_NTFS_FS=m # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y @@ -1152,7 +1151,7 @@ CONFIG_NCPFS_NLS=y CONFIG_NCPFS_EXTRAS=y CONFIG_CODA_FS=m CONFIG_CODA_FS_OLD_API=y -# CONFIG_INTERMEZZO_FS is not set +CONFIG_INTERMEZZO_FS=m CONFIG_AFS_FS=m CONFIG_RXRPC=m @@ -1252,7 +1251,7 @@ CONFIG_CRYPTO_CAST5=m CONFIG_CRYPTO_CAST6=m # CONFIG_CRYPTO_ARC4 is not set CONFIG_CRYPTO_DEFLATE=m -CONFIG_CRYPTO_MICHAEL_MIC=y +CONFIG_CRYPTO_MICHAEL_MIC=m CONFIG_CRYPTO_TEST=m # --- linux-2.6.6/arch/mips/configs/sb1250-swarm_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/sb1250-swarm_defconfig 2004-05-10 01:19:15.209426872 -0700 @@ -18,8 +18,10 @@ CONFIG_STANDALONE=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=15 # CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set @@ -30,6 +32,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -265,8 +268,6 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -276,7 +277,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -297,12 +300,12 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set @@ -310,6 +313,11 @@ CONFIG_NETDEVICES=y # CONFIG_ETHERTAP is not set # +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y @@ -336,7 +344,6 @@ CONFIG_NET_SB1250_MAC=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set -# CONFIG_SIS190 is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set @@ -344,45 +351,29 @@ CONFIG_NET_SB1250_MAC=y # Ethernet (10000 Mbit) # # CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set +# CONFIG_S2IO is not set # # Token Ring devices # # CONFIG_TR is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support +# Wireless LAN (non-hamradio) # -# CONFIG_IRDA is not set +# CONFIG_NET_RADIO is not set # -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -424,6 +415,7 @@ CONFIG_SERIO_SERPORT=y # CONFIG_VT is not set CONFIG_SERIAL_NONSTANDARD=y # CONFIG_ROCKETPORT is not set +# CONFIG_CYCLADES is not set # CONFIG_SYNCLINK is not set # CONFIG_SYNCLINKMP is not set # CONFIG_N_HDLC is not set @@ -541,6 +533,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set # CONFIG_DEVPTS_FS_XATTR is not set # CONFIG_TMPFS is not set --- linux-2.6.6/arch/mips/configs/sead_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/sead_defconfig 2004-05-10 01:19:15.209426872 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y # CONFIG_SYSVIPC is not set +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -194,11 +197,6 @@ CONFIG_BLK_DEV_INITRD=y # Networking support # # CONFIG_NET is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set @@ -376,6 +374,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set # CONFIG_TMPFS is not set # CONFIG_HUGETLB_PAGE is not set --- linux-2.6.6/arch/mips/configs/tb0226_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/tb0226_defconfig 2004-05-10 01:19:15.210426720 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -282,8 +285,6 @@ CONFIG_SYN_COOKIES=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set # @@ -291,7 +292,9 @@ CONFIG_SYN_COOKIES=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -312,6 +315,11 @@ CONFIG_SYN_COOKIES=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set @@ -332,48 +340,31 @@ CONFIG_NET_ETHERNET=y # # Ethernet (10000 Mbit) # -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -# CONFIG_PPP_FILTER is not set -CONFIG_PPP_ASYNC=m -CONFIG_PPP_SYNC_TTY=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPPOE=m -# CONFIG_SLIP is not set # -# Wireless LAN (non-hamradio) +# Token Ring devices # -# CONFIG_NET_RADIO is not set # -# Token Ring devices +# Wireless LAN (non-hamradio) # -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set +# CONFIG_NET_RADIO is not set # # Wan interfaces # # CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPPOE=m +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -569,6 +560,7 @@ CONFIG_VFAT_FS=m # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/tb0229_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/tb0229_defconfig 2004-05-10 01:19:15.211426568 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -56,6 +59,7 @@ CONFIG_MACH_VR41XX=y CONFIG_TANBAC_TB0229=y # CONFIG_VICTOR_MPC30X is not set # CONFIG_ZAO_CAPCELLA is not set +# CONFIG_VRC4173 is not set # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set # CONFIG_MACH_DECSTATION is not set @@ -239,8 +243,6 @@ CONFIG_SYN_COOKIES=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -250,7 +252,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -271,12 +275,12 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set CONFIG_DUMMY=m # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set @@ -284,6 +288,11 @@ CONFIG_DUMMY=m # CONFIG_ETHERTAP is not set # +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y @@ -309,7 +318,6 @@ CONFIG_NET_ETHERNET=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set -# CONFIG_SIS190 is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set @@ -317,6 +325,22 @@ CONFIG_NET_ETHERNET=y # Ethernet (10000 Mbit) # # CONFIG_IXGB is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set CONFIG_PPP=m @@ -331,43 +355,11 @@ CONFIG_SLIP=m CONFIG_SLIP_COMPRESSED=y CONFIG_SLIP_SMART=y CONFIG_SLIP_MODE_SLIP6=y - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices -# -# CONFIG_TR is not set # CONFIG_RCPCI is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set # -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set - -# # ISDN subsystem # # CONFIG_ISDN is not set @@ -559,6 +551,7 @@ CONFIG_VFAT_FS=m # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/workpad_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/workpad_defconfig 2004-05-10 01:19:15.212426416 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -56,6 +59,7 @@ CONFIG_IBM_WORKPAD=y # CONFIG_TANBAC_TB0229 is not set # CONFIG_VICTOR_MPC30X is not set # CONFIG_ZAO_CAPCELLA is not set +CONFIG_VRC4171=y # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set # CONFIG_MACH_DECSTATION is not set @@ -87,7 +91,6 @@ CONFIG_HAVE_DEC_LOCK=y CONFIG_DMA_NONCOHERENT=y CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_IRQ_CPU=y -CONFIG_VRC4171=y CONFIG_MIPS_L1_CACHE_SHIFT=5 # CONFIG_FB is not set @@ -246,8 +249,6 @@ CONFIG_IP_MULTICAST=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -257,7 +258,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -278,12 +281,12 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set @@ -291,6 +294,11 @@ CONFIG_NETDEVICES=y # CONFIG_ETHERTAP is not set # +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y @@ -313,42 +321,25 @@ CONFIG_NET_ETHERNET=y # # Ethernet (10000 Mbit) # -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set # # Token Ring devices # # CONFIG_TR is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set # -# IrDA (infrared) support +# Wireless LAN (non-hamradio) # -# CONFIG_IRDA is not set +# CONFIG_NET_RADIO is not set # -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -539,6 +530,7 @@ CONFIG_AUTOFS4_FS=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/xxs1500_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/xxs1500_defconfig 2004-05-10 01:19:15.213426264 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_HOTPLUG=y # CONFIG_IKCONFIG is not set @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -231,8 +234,6 @@ CONFIG_IP_PNP_BOOTP=y # # CONFIG_IP_VS is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set @@ -253,7 +254,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -274,6 +277,11 @@ CONFIG_XFRM=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set @@ -294,31 +302,15 @@ CONFIG_NET_ETHERNET=y # # Ethernet (10000 Mbit) # -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -# CONFIG_PPP_FILTER is not set -CONFIG_PPP_ASYNC=m -# CONFIG_PPP_SYNC_TTY is not set -CONFIG_PPP_DEFLATE=m -# CONFIG_PPP_BSDCOMP is not set -CONFIG_PPPOE=m -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set # # Token Ring devices # -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set # -# Wan interfaces +# Wireless LAN (non-hamradio) # -# CONFIG_WAN is not set +# CONFIG_NET_RADIO is not set # # PCMCIA network device support @@ -334,21 +326,20 @@ CONFIG_PCMCIA_3C589=m # CONFIG_PCMCIA_AXNET is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -531,6 +522,7 @@ CONFIG_AUTOFS4_FS=m # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/configs/yosemite_defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/configs/yosemite_defconfig 2004-05-10 01:19:15.214426112 -0700 @@ -18,8 +18,10 @@ CONFIG_STANDALONE=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=15 # CONFIG_HOTPLUG is not set CONFIG_IKCONFIG=y @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -251,8 +254,6 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set # @@ -260,7 +261,9 @@ CONFIG_IP_PNP_DHCP=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -281,6 +284,11 @@ CONFIG_IP_PNP_DHCP=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set @@ -300,41 +308,24 @@ CONFIG_NET_ETHERNET=y # # Ethernet (10000 Mbit) # -# CONFIG_PPP is not set -# CONFIG_SLIP is not set # -# Wireless LAN (non-hamradio) +# Token Ring devices # -# CONFIG_NET_RADIO is not set # -# Token Ring devices +# Wireless LAN (non-hamradio) # -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set +# CONFIG_NET_RADIO is not set # # Wan interfaces # # CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -375,6 +366,7 @@ CONFIG_SERIO_SERPORT=y # CONFIG_VT is not set CONFIG_SERIAL_NONSTANDARD=y # CONFIG_ROCKETPORT is not set +# CONFIG_CYCLADES is not set # CONFIG_SYNCLINK is not set # CONFIG_SYNCLINKMP is not set # CONFIG_N_HDLC is not set @@ -489,6 +481,7 @@ CONFIG_FS_MBCACHE=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y --- linux-2.6.6/arch/mips/defconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/defconfig 2004-05-10 01:19:15.215425960 -0700 @@ -19,8 +19,10 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set CONFIG_IKCONFIG=y @@ -32,6 +34,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -298,8 +301,6 @@ CONFIG_INET6_AH=m CONFIG_INET6_ESP=m CONFIG_INET6_IPCOMP=m CONFIG_IPV6_TUNNEL=m -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set @@ -359,6 +360,8 @@ CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m CONFIG_IP_NF_COMPAT_IPCHAINS=m CONFIG_IP_NF_COMPAT_IPFWADM=m +CONFIG_IP_NF_TARGET_NOTRACK=m +CONFIG_IP_NF_RAW=m # # IPv6: Netfilter Configuration @@ -382,6 +385,7 @@ CONFIG_IP6_NF_FILTER=m CONFIG_IP6_NF_TARGET_LOG=m CONFIG_IP6_NF_MANGLE=m CONFIG_IP6_NF_TARGET_MARK=m +CONFIG_IP6_NF_RAW=m CONFIG_XFRM=y CONFIG_XFRM_USER=m @@ -395,7 +399,9 @@ CONFIG_IP_SCTP=m # CONFIG_SCTP_HMAC_SHA1 is not set CONFIG_SCTP_HMAC_MD5=y # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -440,6 +446,11 @@ CONFIG_NET_CLS_POLICE=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL 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_NETDEVICES=y CONFIG_DUMMY=m CONFIG_BONDING=m @@ -461,41 +472,24 @@ CONFIG_SGISEEQ=y # # Ethernet (10000 Mbit) # -# CONFIG_PPP is not set -# CONFIG_SLIP is not set # -# Wireless LAN (non-hamradio) +# Token Ring devices # -# CONFIG_NET_RADIO is not set # -# Token Ring devices +# Wireless LAN (non-hamradio) # -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set +# CONFIG_NET_RADIO is not set # # Wan interfaces # # CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -709,6 +703,7 @@ CONFIG_VFAT_FS=m # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y --- linux-2.6.6/arch/mips/gt64120/momenco_ocelot/prom.c 2004-03-10 20:41:25.000000000 -0800 +++ 25/arch/mips/gt64120/momenco_ocelot/prom.c 2004-05-10 01:19:15.216425808 -0700 @@ -14,17 +14,7 @@ #include #include - -struct callvectors { - int (*open) (char*, int, int); - int (*close) (int); - int (*read) (int, void*, int); - int (*write) (int, void*, int); - off_t (*lseek) (int, off_t, int); - int (*printf) (const char*, ...); - void (*cacheflush) (void); - char* (*gets) (char*); -}; +#include struct callvectors* debug_vectors; --- linux-2.6.6/arch/mips/Kconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/Kconfig 2004-05-10 01:19:15.219425352 -0700 @@ -39,6 +39,7 @@ config MACH_JAZZ config ACER_PICA_61 bool "Support for Acer PICA 1 chipset (EXPERIMENTAL)" depends on MACH_JAZZ && EXPERIMENTAL + select DMA_NONCOHERENT help This is a machine with a R4400 133/150 MHz CPU. To compile a Linux kernel that runs on these, say Y here. For details about Linux on @@ -48,6 +49,7 @@ config ACER_PICA_61 config MIPS_MAGNUM_4000 bool "Support for MIPS Magnum 4000" depends on MACH_JAZZ + select DMA_NONCOHERENT help This is a machine with a R4000 100 MHz CPU. To compile a Linux kernel that runs on these, say Y here. For details about Linux on @@ -57,6 +59,7 @@ config MIPS_MAGNUM_4000 config OLIVETTI_M700 bool "Support for Olivetti M700-10" depends on MACH_JAZZ + select DMA_NONCOHERENT help This is a machine with a R4000 100 MHz CPU. To compile a Linux kernel that runs on these, say Y here. For details about Linux on @@ -77,23 +80,27 @@ config MACH_VR41XX config CASIO_E55 bool "Support for CASIO CASSIOPEIA E-10/15/55/65" depends on MACH_VR41XX + select DMA_NONCOHERENT select IRQ_CPU select ISA config IBM_WORKPAD bool "Support for IBM WorkPad z50" depends on MACH_VR41XX + select DMA_NONCOHERENT select IRQ_CPU select ISA config NEC_EAGLE bool "Support for NEC Eagle/Hawk board" + select DMA_NONCOHERENT select IRQ_CPU depends on MACH_VR41XX config TANBAC_TB0226 bool "Support for TANBAC TB0226 (Mbase)" depends on MACH_VR41XX + select DMA_NONCOHERENT select IRQ_CPU help The TANBAC TB0226 (Mbase) is a MIPS-based platform manufactured by TANBAC. @@ -102,6 +109,7 @@ config TANBAC_TB0226 config TANBAC_TB0229 bool "Support for TANBAC TB0229 (VR4131DIMM)" depends on MACH_VR41XX + select DMA_NONCOHERENT select IRQ_CPU help The TANBAC TB0229 (VR4131DIMM) is a MIPS-based platform manufactured by TANBAC. @@ -109,25 +117,42 @@ config TANBAC_TB0229 config VICTOR_MPC30X bool "Support for Victor MP-C303/304" + select DMA_NONCOHERENT select IRQ_CPU depends on MACH_VR41XX config ZAO_CAPCELLA bool "Support for ZAO Networks Capcella" depends on MACH_VR41XX + select DMA_NONCOHERENT select IRQ_CPU +config VRC4171 + tristate "add NEC VRC4171 companion chip support" + depends on MACH_VR41XX && ISA + ---help--- + The NEC VRC4171/4171A is a companion chip for NEC VR4111/VR4121. + +config VRC4173 + tristate "add NEC VRC4173 companion chip support" + depends on MACH_VR41XX && PCI + ---help--- + The NEC VRC4173 is a companion chip for NEC VR4122/VR4131. + config TOSHIBA_JMR3927 bool "Support for Toshiba JMR-TX3927 board" depends on MIPS32 + select DMA_NONCOHERENT config MIPS_COBALT bool "Support for Cobalt Server (EXPERIMENTAL)" depends on EXPERIMENTAL + select DMA_NONCOHERENT select IRQ_CPU config MACH_DECSTATION bool "Support for DECstations" + select DMA_NONCOHERENT select IRQ_CPU depends on MIPS32 || EXPERIMENTAL ---help--- @@ -148,6 +173,7 @@ config MACH_DECSTATION config MIPS_EV64120 bool "Support for Galileo EV64120 Evaluation board (EXPERIMENTAL)" depends on EXPERIMENTAL + select DMA_NONCOHERENT help This is an evaluation board based on the Galileo GT-64120 single-chip system controller that contains a MIPS R5000 compatible @@ -162,6 +188,7 @@ config EVB_PCI1 config MIPS_EV96100 bool "Support for Galileo EV96100 Evaluation board (EXPERIMENTAL)" depends on EXPERIMENTAL + select DMA_NONCOHERENT select IRQ_CPU select MIPS_GT96100 select RM7000_CPU_SCACHE @@ -173,6 +200,7 @@ config MIPS_EV96100 config MIPS_IVR bool "Support for Globespan IVR board" + select DMA_NONCOHERENT help This is an evaluation board built by Globespan to showcase thir iVR (Internet Video Recorder) design. It utilizes a QED RM5231 @@ -182,6 +210,7 @@ config MIPS_IVR config LASAT bool "Support for LASAT Networks platforms" + select DMA_NONCOHERENT select R5000_CPU_SCACHE config PICVUE @@ -203,10 +232,12 @@ config LASAT_SYSCTL config HP_LASERJET bool "Support for Hewlett Packard LaserJet board" depends on BROKEN + select DMA_NONCOHERENT select IRQ_CPU config MIPS_ITE8172 bool "Support for ITE 8172G board" + select DMA_NONCOHERENT help Ths is an evaluation board made by ITE with ATX form factor that utilizes a MIPS R5000 to work with its @@ -225,6 +256,7 @@ config IT8172_REVC config MIPS_ATLAS bool "Support for MIPS Atlas board" + select DMA_NONCOHERENT help This enables support for the QED R5231-based MIPS Atlas evaluation board. @@ -232,17 +264,20 @@ config MIPS_ATLAS config MIPS_MALTA bool "Support for MIPS Malta board" select HAVE_STD_PC_SERIAL_PORT + select DMA_NONCOHERENT help This enables support for the VR5000-based MIPS Malta evaluation board. config MIPS_SEAD bool "Support for MIPS SEAD board (EXPERIMENTAL)" - select IRQ_CPU depends on EXPERIMENTAL + select IRQ_CPU + select DMA_NONCOHERENT config MOMENCO_OCELOT bool "Support for Momentum Ocelot board" + select DMA_NONCOHERENT select IRQ_CPU select IRQ_CPU_RM7K select RM7000_CPU_SCACHE @@ -252,6 +287,7 @@ config MOMENCO_OCELOT config MOMENCO_OCELOT_G bool "Support for Momentum Ocelot-G board" + select DMA_NONCOHERENT select IRQ_CPU select IRQ_CPU_RM7K select RM7000_CPU_SCACHE @@ -261,6 +297,7 @@ config MOMENCO_OCELOT_G config MOMENCO_OCELOT_C bool "Support for Momentum Ocelot-C board" + select DMA_NONCOHERENT select IRQ_CPU select RM7000_CPU_SCACHE help @@ -269,6 +306,7 @@ config MOMENCO_OCELOT_C config MOMENCO_JAGUAR_ATX bool "Support for Momentum Jaguar board" + select DMA_NONCOHERENT select IRQ_CPU select IRQ_CPU_RM7K select LIMITED_DMA @@ -286,6 +324,7 @@ config JAGUAR_DMALOW config PMC_YOSEMITE bool "Support for PMC-Sierra Yosemite eval board" + select DMA_NONCOHERENT help Yosemite is an evaluation board for the RM9000x2 processor manufactured by PMC-Sierra @@ -297,6 +336,7 @@ config HYPERTRANSPORT config DDB5074 bool "Support for NEC DDB Vrc-5074 (EXPERIMENTAL)" depends on EXPERIMENTAL + select DMA_NONCOHERENT select HAVE_STD_PC_SERIAL_PORT select IRQ_CPU select ISA @@ -306,6 +346,7 @@ config DDB5074 config DDB5476 bool "Support for NEC DDB Vrc-5476" + select DMA_NONCOHERENT select HAVE_STD_PC_SERIAL_PORT select IRQ_CPU select ISA @@ -319,6 +360,7 @@ config DDB5476 config DDB5477 bool "Support for NEC DDB Vrc-5477" + select DMA_NONCOHERENT select IRQ_CPU help This enables support for the R5432-based NEC DDB Vrc-5477, @@ -334,10 +376,12 @@ config DDB5477_BUS_FREQUENCY config NEC_OSPREY bool "Support for NEC Osprey board" + select DMA_NONCOHERENT select IRQ_CPU config SGI_IP22 bool "Support for SGI IP22 (Indy/Indigo2)" + select DMA_NONCOHERENT select IP22_CPU_SCACHE select IRQ_CPU help @@ -348,6 +392,7 @@ config SGI_IP22 config SGI_IP27 bool "Support for SGI IP27 (Origin200/2000)" depends on MIPS64 + select DMA_IP27 help This are the SGI Origin 200, Origin 2000 and Onyx 2 Graphics workstations. To compile a Linux kernel that runs on these, say Y @@ -411,6 +456,7 @@ config REPLICATE_EXHANDLERS config SGI_IP32 bool "Support for SGI IP32 (O2) (EXPERIMENTAL)" depends on EXPERIMENTAL + select DMA_NONCOHERENT select R5000_CPU_SCACHE select RM7000_CPU_SCACHE help @@ -452,30 +498,37 @@ choice config MIPS_PB1000 bool "PB1000 board" depends on SOC_AU1000 + select DMA_NONCOHERENT config MIPS_PB1100 bool "PB1100 board" depends on SOC_AU1100 + select DMA_NONCOHERENT config MIPS_PB1500 bool "PB1500 board" depends on SOC_AU1500 + select DMA_NONCOHERENT config MIPS_PB1550 bool "PB1550 board" depends on SOC_AU1550 + select DMA_NONCOHERENT config MIPS_DB1000 bool "DB1000 board" depends on SOC_AU1000 + select DMA_NONCOHERENT config MIPS_DB1100 bool "DB1100 board" depends on SOC_AU1100 + select DMA_NONCOHERENT config MIPS_DB1500 bool "DB1500 board" depends on SOC_AU1500 + select DMA_NONCOHERENT config MIPS_DB1550 bool "DB1550 board" @@ -484,24 +537,29 @@ config MIPS_DB1550 config MIPS_BOSPORUS bool "Bosporus board" depends on SOC_AU1500 + select DMA_NONCOHERENT config MIPS_MIRAGE bool "Mirage board" depends on SOC_AU1500 + select DMA_NONCOHERENT config MIPS_XXS1500 bool "MyCable XXS1500 board" depends on SOC_AU1500 + select DMA_NONCOHERENT config MIPS_MTX1 bool "4G Systems MTX-1 board" depends on SOC_AU1500 + select DMA_NONCOHERENT endchoice config SIBYTE_SB1xxx_SOC bool "Support for Broadcom BCM1xxx SOCs (EXPERIMENTAL)" depends on EXPERIMENTAL + select DMA_COHERENT choice prompt "BCM1xxx SOC-based board" @@ -710,6 +768,7 @@ config SIBYTE_TBPROF config SNI_RM200_PCI bool "Support for SNI RM200 PCI" + select DMA_NONCOHERENT select HAVE_STD_PC_SERIAL_PORT select ISA help @@ -720,8 +779,9 @@ config SNI_RM200_PCI config TOSHIBA_RBTX4927 bool "Support for Toshiba TBTX49[23]7 board" - select ISA depends on MIPS32 + select DMA_NONCOHERENT + select ISA config RWSEM_GENERIC_SPINLOCK bool @@ -744,18 +804,12 @@ config ARC config DMA_COHERENT bool - depends on SIBYTE_SB1xxx_SOC - default y config DMA_IP27 bool - depends on SGI_IP27 - default y config DMA_NONCOHERENT bool - depends on ZAO_CAPCELLA || VICTOR_MPC30X || TOSHIBA_JMR3927 || TOSHIBA_RBTX4927 || SNI_RM200_PCI || SGI_IP32 || SGI_IP22 || NEC_EAGLE || NEC_OSPREY || DDB5477 || DDB5476 || DDB5074 || MOMENCO_OCELOT || MOMENCO_OCELOT_C || MOMENCO_OCELOT_G || MOMENCO_JAGUAR_ATX || MIPS_BOSPORUS || MIPS_DB1000 || MIPS_DB1100 || MIPS_DB1500 || MIPS_SEAD || MIPS_MALTA || MIPS_MAGNUM_4000 || MIPS_MIRAGE || MIPS_MTX1 || MIPS_XXS1500 || OLIVETTI_M700 || MIPS_ATLAS || LASAT || MIPS_ITE8172 || IBM_WORKPAD || HP_LASERJET || MIPS_IVR || MIPS_EV96100 || MIPS_EV64120 || MACH_DECSTATION || MIPS_COBALT || MIPS_PB1500 || MIPS_PB1100 || MIPS_PB1000 || MIPS_PB1550 || CASIO_E55 || ACER_PICA_61 || TANBAC_TB0226 || TANBAC_TB0229 - default y config EARLY_PRINTK bool @@ -811,14 +865,6 @@ config DUMMY_KEYB depends on ZAO_CAPCELLA || VICTOR_MPC30X || SIBYTE_SB1xxx_SOC || NEC_EAGLE || NEC_OSPREY || DDB5477 || CASIO_E55 || TANBAC_TB0226 || TANBAC_TB0229 default y -config VRC4171 - tristate "NEC VRC4171 Support" - depends on IBM_WORKPAD - -config VRC4173 - tristate "NEC VRC4173 Support" - depends on NEC_EAGLE || VICTOR_MPC30X - config DDB5XXX_COMMON bool depends on DDB5074 || DDB5476 || DDB5477 @@ -1170,7 +1216,7 @@ config SIBYTE_DMA_PAGEOPS config CPU_HAS_PREFETCH bool "Enable prefetches" if CPU_SB1 && !CPU_SB1_PASS_2 - default y if CPU_MIPS32 || CPU_MIPS64 || CPU_RM7000 || CPU_RM9000 + default y if CPU_MIPS32 || CPU_MIPS64 || CPU_RM7000 || CPU_RM9000 || CPU_R10000 config VTAG_ICACHE bool "Support for Virtual Tagged I-cache" if CPU_MIPS64 || CPU_MIPS32 --- linux-2.6.6/arch/mips/kernel/entry.S 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/kernel/entry.S 2004-05-10 01:19:15.219425352 -0700 @@ -114,11 +114,13 @@ FEXPORT(syscall_exit_work_partial) SAVE_STATIC FEXPORT(syscall_exit_work) LONG_L t0, TI_FLAGS($28) - li t1, _TIF_SYSCALL_TRACE + li t1, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT and t0, t1 beqz t0, work_pending # trace bit is set local_irq_enable # could let do_syscall_trace() # call schedule() instead + move a0, sp + li a1, 1 jal do_syscall_trace b resume_userspace --- linux-2.6.6/arch/mips/kernel/irixelf.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/kernel/irixelf.c 2004-05-10 01:19:15.220425200 -0700 @@ -1130,7 +1130,7 @@ static int irix_core_dump(long signr, st psinfo.pr_pid = prstatus.pr_pid = current->pid; psinfo.pr_ppid = prstatus.pr_ppid = current->parent->pid; psinfo.pr_pgrp = prstatus.pr_pgrp = process_group(current); - psinfo.pr_sid = prstatus.pr_sid = current->session; + psinfo.pr_sid = prstatus.pr_sid = current->signal->session; prstatus.pr_utime.tv_sec = CT_TO_SECS(current->utime); prstatus.pr_utime.tv_usec = CT_TO_USECS(current->utime); prstatus.pr_stime.tv_sec = CT_TO_SECS(current->stime); --- linux-2.6.6/arch/mips/kernel/irixsig.c 2004-03-10 20:41:25.000000000 -0800 +++ 25/arch/mips/kernel/irixsig.c 2004-05-10 01:19:15.221425048 -0700 @@ -13,12 +13,11 @@ #include #include #include +#include #include #include -extern asmlinkage void do_syscall_trace(void); - #undef DEBUG_SIG #define _S(nr) (1<<((nr)-1)) @@ -177,6 +176,19 @@ asmlinkage int do_irix_signal(sigset_t * siginfo_t info; int signr; + /* + * We want the common case to go fast, which is why we may in certain + * cases get here from kernel mode. Just return without doing anything + * if so. + */ + if (!user_mode(regs)) + return 1; + + if (current->flags & PF_FREEZE) { + refrigerator(0); + goto no_signal; + } + if (!oldset) oldset = ¤t->blocked; @@ -186,6 +198,7 @@ asmlinkage int do_irix_signal(sigset_t * return 1; } +no_signal: /* * Who's code doesn't conform to the restartable syscall convention * dies here!!! The li instruction, a single machine instruction, @@ -263,7 +276,7 @@ irix_sigreturn(struct pt_regs *regs) * Don't let your children do this ... */ if (current_thread_info()->flags & TIF_SYSCALL_TRACE) - do_syscall_trace(); + do_syscall_trace(regs, 1); __asm__ __volatile__( "move\t$29,%0\n\t" "j\tsyscall_exit" --- linux-2.6.6/arch/mips/kernel/linux32.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/kernel/linux32.c 2004-05-10 01:19:34.920430344 -0700 @@ -142,228 +142,6 @@ asmlinkage int sys_ftruncate64(unsigned } /* - * count32() counts the number of arguments/envelopes - */ -static int count32(u32 * argv, int max) -{ - int i = 0; - - if (argv != NULL) { - for (;;) { - u32 p; int error; - - error = get_user(p,argv); - if (error) - return error; - if (!p) - break; - argv++; - if (++i > max) - return -E2BIG; - } - } - return i; -} - - -/* - * 'copy_strings32()' copies argument/envelope strings from user - * memory to free pages in kernel mem. These are in a format ready - * to be put directly into the top of new user memory. - */ -int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm) -{ - struct page *kmapped_page = NULL; - char *kaddr = NULL; - int ret; - - while (argc-- > 0) { - u32 str; - int len; - unsigned long pos; - - if (get_user(str, argv+argc) || !str || - !(len = strnlen_user((char *)A(str), bprm->p))) { - ret = -EFAULT; - goto out; - } - - if (bprm->p < len) { - ret = -E2BIG; - goto out; - } - - bprm->p -= len; - /* XXX: add architecture specific overflow check here. */ - - pos = bprm->p; - while (len > 0) { - int i, new, err; - int offset, bytes_to_copy; - struct page *page; - - offset = pos % PAGE_SIZE; - i = pos/PAGE_SIZE; - page = bprm->page[i]; - new = 0; - if (!page) { - page = alloc_page(GFP_HIGHUSER); - bprm->page[i] = page; - if (!page) { - ret = -ENOMEM; - goto out; - } - new = 1; - } - - if (page != kmapped_page) { - if (kmapped_page) - kunmap(kmapped_page); - kmapped_page = page; - kaddr = kmap(kmapped_page); - } - if (new && offset) - memset(kaddr, 0, offset); - bytes_to_copy = PAGE_SIZE - offset; - if (bytes_to_copy > len) { - bytes_to_copy = len; - if (new) - memset(kaddr+offset+len, 0, - PAGE_SIZE-offset-len); - } - err = copy_from_user(kaddr + offset, (char *)A(str), - bytes_to_copy); - if (err) { - ret = -EFAULT; - goto out; - } - - pos += bytes_to_copy; - str += bytes_to_copy; - len -= bytes_to_copy; - } - } - ret = 0; -out: - if (kmapped_page) - kunmap(kmapped_page); - return ret; -} - -#ifdef CONFIG_MMU - -#define free_arg_pages(bprm) do { } while (0) - -#else - -static inline void free_arg_pages(struct linux_binprm *bprm) -{ - int i; - - for (i = 0; i < MAX_ARG_PAGES; i++) { - if (bprm->page[i]) - __free_page(bprm->page[i]); - bprm->page[i] = NULL; - } -} - -#endif /* CONFIG_MMU */ - -/* - * sys32_execve() executes a new program. - */ -static inline int -do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs) -{ - struct linux_binprm bprm; - struct file * file; - int retval; - - sched_balance_exec(); - - file = open_exec(filename); - - retval = PTR_ERR(file); - if (IS_ERR(file)) - return retval; - - bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); - memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0])); - - bprm.file = file; - bprm.filename = filename; - bprm.interp = filename; - bprm.sh_bang = 0; - bprm.loader = 0; - bprm.exec = 0; - bprm.security = NULL; - bprm.mm = mm_alloc(); - retval = -ENOMEM; - if (!bprm.mm) - goto out_file; - - retval = init_new_context(current, bprm.mm); - if (retval < 0) - goto out_mm; - - bprm.argc = count32(argv, bprm.p / sizeof(u32)); - if ((retval = bprm.argc) < 0) - goto out_mm; - - bprm.envc = count32(envp, bprm.p / sizeof(u32)); - if ((retval = bprm.envc) < 0) - goto out_mm; - - retval = security_bprm_alloc(&bprm); - if (retval) - goto out; - - retval = prepare_binprm(&bprm); - if (retval < 0) - goto out; - - retval = copy_strings_kernel(1, &bprm.filename, &bprm); - if (retval < 0) - goto out; - - bprm.exec = bprm.p; - retval = copy_strings32(bprm.envc, envp, &bprm); - if (retval < 0) - goto out; - - retval = copy_strings32(bprm.argc, argv, &bprm); - if (retval < 0) - goto out; - - retval = search_binary_handler(&bprm, regs); - if (retval >= 0) { - free_arg_pages(&bprm); - - /* execve success */ - security_bprm_free(&bprm); - return retval; - } - -out: - /* Something went wrong, return the inode and free the argument pages*/ - free_arg_pages(&bprm); - - if (bprm.security) - security_bprm_free(&bprm); - -out_mm: - if (bprm.mm) - mmdrop(bprm.mm); - -out_file: - if (bprm.file) { - allow_write_access(bprm.file); - fput(bprm.file); - } - return retval; -} - -/* * sys_execve() executes a new program. */ asmlinkage int sys32_execve(nabi_no_regargs struct pt_regs regs) @@ -371,12 +149,12 @@ asmlinkage int sys32_execve(nabi_no_rega int error; char * filename; - filename = getname((char *) (long)regs.regs[4]); + filename = getname(compat_ptr(regs.regs[4])); error = PTR_ERR(filename); if (IS_ERR(filename)) goto out; - error = do_execve32(filename, (u32 *) (long)regs.regs[5], - (u32 *) (long)regs.regs[6], ®s); + error = compat_do_execve(filename, compat_ptr(regs.regs[5]), + compat_ptr(regs.regs[6]), ®s); putname(filename); out: @@ -671,150 +449,6 @@ asmlinkage int sys32_llseek(unsigned int return sys_llseek(fd, offset_high, offset_low, result, origin); } -typedef ssize_t (*IO_fn_t)(struct file *, char *, size_t, loff_t *); - -static long -do_readv_writev32(int type, struct file *file, const struct compat_iovec *vector, - u32 count) -{ - unsigned long tot_len; - struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov=iovstack, *ivp; - struct inode *inode; - long retval, i; - IO_fn_t fn; - - /* First get the "struct iovec" from user memory and - * verify all the pointers - */ - if (!count) - return 0; - if(verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count)) - return -EFAULT; - if (count > UIO_MAXIOV) - return -EINVAL; - if (count > UIO_FASTIOV) { - iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL); - if (!iov) - return -ENOMEM; - } - - tot_len = 0; - i = count; - ivp = iov; - while (i > 0) { - u32 len; - u32 buf; - - __get_user(len, &vector->iov_len); - __get_user(buf, &vector->iov_base); - tot_len += len; - ivp->iov_base = (void *)A(buf); - ivp->iov_len = (__kernel_size_t) len; - vector++; - ivp++; - i--; - } - - inode = file->f_dentry->d_inode; - /* VERIFY_WRITE actually means a read, as we write to user space */ - retval = locks_verify_area((type == VERIFY_WRITE - ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE), - inode, file, file->f_pos, tot_len); - if (retval) { - if (iov != iovstack) - kfree(iov); - return retval; - } - - /* Then do the actual IO. Note that sockets need to be handled - * specially as they have atomicity guarantees and can handle - * iovec's natively - */ -#ifdef CONFIG_NET - if (inode->i_sock) { - int err; - err = sock_readv_writev(type, inode, file, iov, count, tot_len); - if (iov != iovstack) - kfree(iov); - return err; - } -#endif - - if (!file->f_op) { - if (iov != iovstack) - kfree(iov); - return -EINVAL; - } - /* VERIFY_WRITE actually means a read, as we write to user space */ - fn = file->f_op->read; - if (type == VERIFY_READ) - fn = (IO_fn_t) file->f_op->write; - ivp = iov; - while (count > 0) { - void * base; - int len, nr; - - base = ivp->iov_base; - len = ivp->iov_len; - ivp++; - count--; - nr = fn(file, base, len, &file->f_pos); - if (nr < 0) { - if (retval) - break; - retval = nr; - break; - } - retval += nr; - if (nr != len) - break; - } - if (iov != iovstack) - kfree(iov); - - return retval; -} - -asmlinkage long -sys32_readv(int fd, struct compat_iovec *vector, u32 count) -{ - struct file *file; - ssize_t ret; - - ret = -EBADF; - file = fget(fd); - if (!file) - goto bad_file; - if (file->f_op && (file->f_mode & FMODE_READ) && - (file->f_op->readv || file->f_op->read)) - ret = do_readv_writev32(VERIFY_WRITE, file, vector, count); - - fput(file); - -bad_file: - return ret; -} - -asmlinkage long -sys32_writev(int fd, struct compat_iovec *vector, u32 count) -{ - struct file *file; - ssize_t ret; - - ret = -EBADF; - file = fget(fd); - if(!file) - goto bad_file; - if (file->f_op && (file->f_mode & FMODE_WRITE) && - (file->f_op->writev || file->f_op->write)) - ret = do_readv_writev32(VERIFY_READ, file, vector, count); - fput(file); - -bad_file: - return ret; -} - /* From the Single Unix Spec: pread & pwrite act like lseek to pos + op + lseek back to original location. They fail just like lseek does on non-seekable files. */ @@ -885,167 +519,6 @@ out: bad_file: return ret; } -/* - * Ooo, nasty. We need here to frob 32-bit unsigned longs to - * 64-bit unsigned longs. - */ - -static inline int -get_fd_set32(unsigned long n, unsigned long *fdset, u32 *ufdset) -{ - if (ufdset) { - unsigned long odd; - - if (verify_area(VERIFY_WRITE, ufdset, n*sizeof(u32))) - return -EFAULT; - - odd = n & 1UL; - n &= ~1UL; - while (n) { - unsigned long h, l; - __get_user(l, ufdset); - __get_user(h, ufdset+1); - ufdset += 2; - *fdset++ = h << 32 | l; - n -= 2; - } - if (odd) - __get_user(*fdset, ufdset); - } else { - /* Tricky, must clear full unsigned long in the - * kernel fdset at the end, this makes sure that - * actually happens. - */ - memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32)); - } - return 0; -} - -static inline void -set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset) -{ - unsigned long odd; - - if (!ufdset) - return; - - odd = n & 1UL; - n &= ~1UL; - while (n) { - unsigned long h, l; - l = *fdset++; - h = l >> 32; - __put_user(l, ufdset); - __put_user(h, ufdset+1); - ufdset += 2; - n -= 2; - } - if (odd) - __put_user(*fdset, ufdset); -} - -/* - * We can actually return ERESTARTSYS instead of EINTR, but I'd - * like to be certain this leads to no problems. So I return - * EINTR just for safety. - * - * Update: ERESTARTSYS breaks at least the xview clock binary, so - * I'm trying ERESTARTNOHAND which restart only when you want to. - */ -#define MAX_SELECT_SECONDS \ - ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1) - -asmlinkage int sys32_select(int n, u32 *inp, u32 *outp, u32 *exp, struct compat_timeval *tvp) -{ - fd_set_bits fds; - char *bits; - unsigned long nn; - long timeout; - int ret, size; - - timeout = MAX_SCHEDULE_TIMEOUT; - if (tvp) { - time_t sec, usec; - - if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp))) - || (ret = __get_user(sec, &tvp->tv_sec)) - || (ret = __get_user(usec, &tvp->tv_usec))) - goto out_nofds; - - ret = -EINVAL; - if(sec < 0 || usec < 0) - goto out_nofds; - - if ((unsigned long) sec < MAX_SELECT_SECONDS) { - timeout = (usec + 1000000/HZ - 1) / (1000000/HZ); - timeout += sec * (unsigned long) HZ; - } - } - - ret = -EINVAL; - if (n < 0) - goto out_nofds; - if (n > current->files->max_fdset) - n = current->files->max_fdset; - - /* - * We need 6 bitmaps (in/out/ex for both incoming and outgoing), - * since we used fdset we need to allocate memory in units of - * long-words. - */ - ret = -ENOMEM; - size = FDS_BYTES(n); - bits = kmalloc(6 * size, GFP_KERNEL); - if (!bits) - goto out_nofds; - fds.in = (unsigned long *) bits; - fds.out = (unsigned long *) (bits + size); - fds.ex = (unsigned long *) (bits + 2*size); - fds.res_in = (unsigned long *) (bits + 3*size); - fds.res_out = (unsigned long *) (bits + 4*size); - fds.res_ex = (unsigned long *) (bits + 5*size); - - nn = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32)); - if ((ret = get_fd_set32(nn, fds.in, inp)) || - (ret = get_fd_set32(nn, fds.out, outp)) || - (ret = get_fd_set32(nn, fds.ex, exp))) - goto out; - zero_fd_set(n, fds.res_in); - zero_fd_set(n, fds.res_out); - zero_fd_set(n, fds.res_ex); - - ret = do_select(n, &fds, &timeout); - - if (tvp && !(current->personality & STICKY_TIMEOUTS)) { - time_t sec = 0, usec = 0; - if (timeout) { - sec = timeout / HZ; - usec = timeout % HZ; - usec *= (1000000/HZ); - } - put_user(sec, &tvp->tv_sec); - put_user(usec, &tvp->tv_usec); - } - - if (ret < 0) - goto out; - if (!ret) { - ret = -ERESTARTNOHAND; - if (signal_pending(current)) - goto out; - ret = 0; - } - - set_fd_set32(nn, inp, fds.res_in); - set_fd_set32(nn, outp, fds.res_out); - set_fd_set32(nn, exp, fds.res_ex); - -out: - kfree(bits); -out_nofds: - return ret; -} - asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec *interval) --- linux-2.6.6/arch/mips/kernel/mips_ksyms.c 2004-03-10 20:41:25.000000000 -0800 +++ 25/arch/mips/kernel/mips_ksyms.c 2004-05-10 01:19:15.221425048 -0700 @@ -33,6 +33,9 @@ EXPORT_SYMBOL_NOVERS(memcpy); EXPORT_SYMBOL_NOVERS(memmove); EXPORT_SYMBOL_NOVERS(strcat); EXPORT_SYMBOL_NOVERS(strchr); +#ifdef CONFIG_MIPS64 +EXPORT_SYMBOL_NOVERS(strncmp); +#endif EXPORT_SYMBOL_NOVERS(strlen); EXPORT_SYMBOL_NOVERS(strpbrk); EXPORT_SYMBOL_NOVERS(strncat); --- linux-2.6.6/arch/mips/kernel/process.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/kernel/process.c 2004-05-10 01:19:31.141004904 -0700 @@ -280,12 +280,6 @@ unsigned long thread_saved_pc(struct tas return ((unsigned long *)t->reg29)[schedule_frame.pc_offset]; } -/* - * These bracket the sleeping functions.. - */ -#define first_sched ((unsigned long) scheduling_functions_start_here) -#define last_sched ((unsigned long) scheduling_functions_end_here) - /* get_wchan - a maintenance nightmare^W^Wpain in the ass ... */ unsigned long get_wchan(struct task_struct *p) { @@ -297,7 +291,7 @@ unsigned long get_wchan(struct task_stru if (!mips_frame_info_initialized) return 0; pc = thread_saved_pc(p); - if (pc < first_sched || pc >= last_sched) + if (!in_sched_functions(pc)) goto out; if (pc >= (unsigned long) sleep_on_timeout) @@ -331,7 +325,7 @@ schedule_timeout_caller: */ pc = ((unsigned long *)frame)[schedule_timeout_frame.pc_offset]; - if (pc >= first_sched && pc < last_sched) { + if (in_sched_functions(pc)) { /* schedule_timeout called by [interruptible_]sleep_on_timeout */ frame = ((unsigned long *)frame)[schedule_timeout_frame.frame_offset]; pc = ((unsigned long *)frame)[sleep_on_timeout_frame.pc_offset]; --- linux-2.6.6/arch/mips/kernel/ptrace.c 2004-03-10 20:41:25.000000000 -0800 +++ 25/arch/mips/kernel/ptrace.c 2004-05-10 01:19:15.222424896 -0700 @@ -303,8 +303,17 @@ out: * Notification of system call entry/exit * - triggered by current->work.syscall_trace */ -asmlinkage void do_syscall_trace(void) +asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit) { + if (unlikely(current->audit_context)) { + if (!entryexit) + audit_syscall_entry(current, regs->orig_eax, + regs->regs[4], regs->regs[5], + regs->regs[6], regs->regs[7]); + else + audit_syscall_exit(current, regs->regs[2]); + } + if (!test_thread_flag(TIF_SYSCALL_TRACE)) return; if (!(current->ptrace & PT_PTRACED)) --- linux-2.6.6/arch/mips/kernel/scall32-o32.S 2004-03-10 20:41:25.000000000 -0800 +++ 25/arch/mips/kernel/scall32-o32.S 2004-05-10 01:19:15.222424896 -0700 @@ -33,8 +33,8 @@ NESTED(handle_sys, PT_SIZE, sp) sltiu t0, v0, MAX_SYSCALL_NO + 1 # check syscall number addiu t1, 4 # skip to next instruction - beqz t0, illegal_syscall sw t1, PT_EPC(sp) + beqz t0, illegal_syscall /* XXX Put both in one cacheline, should save a bit. */ sll t0, v0, 2 @@ -49,7 +49,7 @@ NESTED(handle_sys, PT_SIZE, sp) stack_done: sw a3, PT_R26(sp) # save for syscall restart LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? - li t1, _TIF_SYSCALL_TRACE + li t1, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT and t0, t1, t0 bnez t0, syscall_trace_entry # -> yes @@ -84,6 +84,8 @@ o32_syscall_exit_work: syscall_trace_entry: SAVE_STATIC sw t2, PT_R1(sp) + move a0, sp + li a1, 0 jal do_syscall_trace lw t2, PT_R1(sp) @@ -233,13 +235,15 @@ illegal_syscall: /* Success, so skip usual error handling garbage. */ LONG_L a2, TI_FLAGS($28) # syscall tracing enabled? - li t0, _TIF_SYSCALL_TRACE + li t0, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT and t0, a2, t0 bnez t0, 1f b o32_syscall_exit 1: SAVE_STATIC + move a0, sp + li a1, 1 jal do_syscall_trace j syscall_exit @@ -614,6 +618,15 @@ out: jr ra sys sys_clock_nanosleep 4 /* 4265 */ sys sys_tgkill 3 sys sys_utimes 2 + sys sys_ni_syscall 0 /* sys_mbind */ + sys sys_ni_syscall 0 /* sys_get_mempolicy */ + sys sys_ni_syscall 0 /* 4270 sys_set_mempolicy */ + sys sys_mq_open 4 + sys sys_mq_unlink 1 + sys sys_mq_timedsend 5 + sys sys_mq_timedreceive 5 + sys sys_mq_notify 2 /* 4275 */ + sys sys_mq_getsetattr 3 .endm --- linux-2.6.6/arch/mips/kernel/scall64-64.S 2004-03-10 20:41:25.000000000 -0800 +++ 25/arch/mips/kernel/scall64-64.S 2004-05-10 01:19:15.223424744 -0700 @@ -36,14 +36,16 @@ NESTED(handle_sys64, PT_SIZE, sp) STI .set at #endif - ld t1, PT_EPC(sp) # skip syscall on return FEXPORT(__handle_sys64) subu t0, v0, __NR_64_Linux # check syscall number sltiu t0, t0, __NR_64_Linux_syscalls + 1 +#if !defined(CONFIG_MIPS32_O32) && !defined(CONFIG_MIPS32_N32) + ld t1, PT_EPC(sp) # skip syscall on return daddiu t1, 4 # skip to next instruction - beqz t0, illegal_syscall sd t1, PT_EPC(sp) +#endif + beqz t0, illegal_syscall dsll t0, v0, 3 # offset into table ld t2, (sys_call_table - (__NR_64_Linux * 8))(t0) @@ -85,6 +87,8 @@ n64_syscall_exit_work: syscall_trace_entry: SAVE_STATIC sd t2,PT_R1(sp) + move a0, sp + li a1, 0 jal do_syscall_trace ld t2,PT_R1(sp) @@ -165,13 +169,15 @@ illegal_syscall: /* Success, so skip usual error handling garbage. */ LONG_L a2, TI_FLAGS($28) # syscall tracing enabled? - li t0, _TIF_SYSCALL_TRACE + li t0, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT and t0, a2, t0 bnez t0, 1f b syscall_exit 1: SAVE_STATIC + move a0, sp + li a1, 1 jal do_syscall_trace j syscall_exit @@ -432,3 +438,12 @@ sys_call_table: PTR sys_clock_nanosleep PTR sys_tgkill /* 5225 */ PTR sys_utimes + PTR sys_ni_syscall /* sys_mbind */ + PTR sys_ni_syscall /* sys_get_mempolicy */ + PTR sys_ni_syscall /* sys_set_mempolicy */ + PTR sys_mq_open /* 5230 */ + PTR sys_mq_unlink + PTR sys_mq_timedsend + PTR sys_mq_timedreceive + PTR sys_mq_notify + PTR sys_mq_getsetattr /* 5235 */ --- linux-2.6.6/arch/mips/kernel/scall64-n32.S 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/kernel/scall64-n32.S 2004-05-10 01:19:34.920430344 -0700 @@ -36,21 +36,26 @@ NESTED(handle_sysn32, PT_SIZE, sp) STI .set at #endif - ld t1, PT_EPC(sp) # skip syscall on return subu t0, v0, __NR_N32_Linux # check syscall number sltiu t0, t0, __NR_N32_Linux_syscalls + 1 + +#ifndef CONFIG_MIPS32_O32 + ld t1, PT_EPC(sp) # skip syscall on return daddiu t1, 4 # skip to next instruction - beqz t0, not_n32_scall sd t1, PT_EPC(sp) +#endif + beqz t0, not_n32_scall dsll t0, v0, 3 # offset into table ld t2, (sysn32_call_table - (__NR_N32_Linux * 8))(t0) sd a3, PT_R26(sp) # save a3 for syscall restarting + li t1, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? - bltz t0, n32_syscall_trace_entry + and t0, t1, t0 + bnez t0, n32_syscall_trace_entry jalr t2 # Do The Real Thing (TM) @@ -82,6 +87,8 @@ n32_syscall_exit_work: n32_syscall_trace_entry: SAVE_STATIC sd t2,PT_R1(sp) + move a0, sp + li a1, 0 jal do_syscall_trace ld t2,PT_R1(sp) @@ -128,11 +135,11 @@ EXPORT(sysn32_call_table) PTR compat_sys_ioctl /* 6015 */ PTR sys_pread64 PTR sys_pwrite64 - PTR sys32_readv - PTR sys32_writev + PTR compat_sys_readv + PTR compat_sys_writev PTR sys_access /* 6020 */ PTR sys_pipe - PTR sys32_select + PTR compat_sys_select PTR sys_sched_yield PTR sys_mremap PTR sys_msync /* 6025 */ @@ -341,3 +348,12 @@ EXPORT(sysn32_call_table) PTR sys_clock_nanosleep PTR sys_tgkill PTR compat_sys_utimes /* 6230 */ + PTR sys_ni_syscall /* sys_mbind */ + PTR sys_ni_syscall /* sys_get_mempolicy */ + PTR sys_ni_syscall /* sys_set_mempolicy */ + PTR compat_sys_mq_open + PTR sys_mq_unlink /* 6235 */ + PTR compat_sys_mq_timedsend + PTR compat_sys_mq_timedreceive + PTR compat_sys_mq_notify + PTR compat_sys_mq_getsetattr /* 6239 */ --- linux-2.6.6/arch/mips/kernel/scall64-o32.S 2004-03-10 20:41:25.000000000 -0800 +++ 25/arch/mips/kernel/scall64-o32.S 2004-05-10 01:19:34.921430192 -0700 @@ -34,8 +34,8 @@ NESTED(handle_sys, PT_SIZE, sp) subu t0, v0, __NR_O32_Linux # check syscall number sltiu t0, t0, __NR_O32_Linux_syscalls + 1 daddiu t1, 4 # skip to next instruction - beqz t0, not_o32_scall sd t1, PT_EPC(sp) + beqz t0, not_o32_scall #if 0 SAVE_ALL move a1, v0 @@ -58,8 +58,9 @@ NESTED(handle_sys, PT_SIZE, sp) bgez t0, stackargs stack_done: - LONG_L t0, TI_FLAGS($28) - # syscall tracing enabled? + li t1, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT + LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? + and t0, t1, t0 bnez t0, trace_a_syscall jalr t2 # Do The Real Thing (TM) @@ -97,6 +98,8 @@ trace_a_syscall: sd a7, PT_R11(sp) sd t2,PT_R1(sp) + move a0, sp + li a1, 0 jal do_syscall_trace ld t2,PT_R1(sp) @@ -397,11 +400,11 @@ out: jr ra sys sys_setfsgid 1 sys sys32_llseek 5 /* 4140 */ sys sys32_getdents 3 - sys sys32_select 5 + sys compat_sys_select 5 sys sys_flock 2 sys sys_msync 3 - sys sys32_readv 3 /* 4145 */ - sys sys32_writev 3 + sys compat_sys_readv 3 /* 4145 */ + sys compat_sys_writev 3 sys sys_cacheflush 3 sys sys_cachectl 3 sys sys_sysmips 4 @@ -523,6 +526,15 @@ out: jr ra sys sys_clock_nanosleep 4 /* 4265 */ sys sys_tgkill 3 sys compat_sys_utimes 2 + sys sys_ni_syscall 0 /* sys_mbind */ + sys sys_ni_syscall 0 /* sys_get_mempolicy */ + sys sys_ni_syscall 0 /* 4270 sys_set_mempolicy */ + sys compat_sys_mq_open 4 + sys sys_mq_unlink 1 + sys compat_sys_mq_timedsend 5 + sys compat_sys_mq_timedreceive 5 + sys compat_sys_mq_notify 2 /* 4275 */ + sys compat_sys_mq_getsetattr 3 .endm --- linux-2.6.6/arch/mips/kernel/setup.c 2004-03-10 20:41:25.000000000 -0800 +++ 25/arch/mips/kernel/setup.c 2004-05-10 01:19:18.569916000 -0700 @@ -71,7 +71,6 @@ EXPORT_SYMBOL(mips_machgroup); struct boot_mem_map boot_mem_map; static char command_line[CL_SIZE]; - char saved_command_line[CL_SIZE]; char arcs_cmdline[CL_SIZE]=CONFIG_CMDLINE; /* --- linux-2.6.6/arch/mips/kernel/signal32.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/kernel/signal32.c 2004-05-10 01:19:15.226424288 -0700 @@ -18,9 +18,11 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -40,8 +42,6 @@ extern asmlinkage int do_signal32(sigset_t *oldset, struct pt_regs *regs); -extern asmlinkage void do_syscall_trace(void); - /* 32-bit compatibility types */ #define _NSIG_BPW32 32 @@ -392,7 +392,7 @@ asmlinkage void sys32_sigreturn(nabi_no_ * Don't let your children do this ... */ if (current_thread_info()->flags & TIF_SYSCALL_TRACE) - do_syscall_trace(); + do_syscall_trace(®s, 1); __asm__ __volatile__( "move\t$29, %0\n\t" "j\tsyscall_exit" @@ -696,6 +696,19 @@ asmlinkage int do_signal32(sigset_t *old siginfo_t info; int signr; + /* + * We want the common case to go fast, which is why we may in certain + * cases get here from kernel mode. Just return without doing anything + * if so. + */ + if (!user_mode(regs)) + return 1; + + if (current->flags & PF_FREEZE) { + refrigerator(0); + goto no_signal; + } + if (!oldset) oldset = ¤t->blocked; @@ -705,6 +718,7 @@ asmlinkage int do_signal32(sigset_t *old return 1; } +no_signal: /* * Who's code doesn't conform to the restartable syscall convention * dies here!!! The li instruction, a single machine instruction, --- linux-2.6.6/arch/mips/kernel/signal.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/kernel/signal.c 2004-05-10 01:19:15.226424288 -0700 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -34,8 +35,6 @@ extern asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs); -extern asmlinkage void do_syscall_trace(void); - /* * Atomically swap in the new signal mask, and wait for a signal. */ @@ -232,7 +231,7 @@ asmlinkage void sys_sigreturn(struct pt_ * Don't let your children do this ... */ if (current_thread_info()->flags & TIF_SYSCALL_TRACE) - do_syscall_trace(); + do_syscall_trace(®s, 1); __asm__ __volatile__( "move\t$29, %0\n\t" "j\tsyscall_exit" @@ -549,6 +548,19 @@ asmlinkage int do_signal(sigset_t *oldse } #endif + /* + * We want the common case to go fast, which is why we may in certain + * cases get here from kernel mode. Just return without doing anything + * if so. + */ + if (!user_mode(regs)) + return 1; + + if (current->flags & PF_FREEZE) { + refrigerator(0); + goto no_signal; + } + if (!oldset) oldset = ¤t->blocked; @@ -558,6 +570,7 @@ asmlinkage int do_signal(sigset_t *oldse return 1; } +no_signal: /* * Who's code doesn't conform to the restartable syscall convention * dies here!!! The li instruction, a single machine instruction, --- linux-2.6.6/arch/mips/kernel/signal_n32.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/kernel/signal_n32.c 2004-05-10 01:19:15.227424136 -0700 @@ -29,6 +29,7 @@ #include #include +#include #include #include #include --- linux-2.6.6/arch/mips/kernel/smp.c 2004-03-10 20:41:25.000000000 -0800 +++ 25/arch/mips/kernel/smp.c 2004-05-10 01:19:49.907152016 -0700 @@ -151,6 +151,9 @@ int smp_call_function (void (*func) (voi if (!cpus) return 0; + /* Can deadlock when called with interrupts disabled */ + WARN_ON(irqs_disabled()); + data.func = func; data.info = info; atomic_set(&data.started, 0); --- linux-2.6.6/arch/mips/momentum/jaguar_atx/prom.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/momentum/jaguar_atx/prom.c 2004-05-10 01:19:15.227424136 -0700 @@ -25,22 +25,12 @@ #include #include #include +#include #include "jaguar_atx_fpga.h" extern void ja_setup_console(void); -struct callvectors { - int (*open) (char*, int, int); /* 0 */ - int (*close) (int); /* 4 */ - int (*read) (int, void*, int); /* 8 */ - int (*write) (int, void*, int); /* 12 */ - off_t (*lseek) (int, off_t, int); /* 16 */ - int (*printf) (const char*, ...); /* 20 */ - void (*cacheflush) (void); /* 24 */ - char* (*gets) (char*); /* 28 */ -}; - struct callvectors *debug_vectors; extern unsigned long mv64340_base; --- linux-2.6.6/arch/mips/momentum/ocelot_c/prom.c 2004-03-10 20:41:26.000000000 -0800 +++ 25/arch/mips/momentum/ocelot_c/prom.c 2004-05-10 01:19:15.228423984 -0700 @@ -23,20 +23,10 @@ #include #include #include +#include #include "ocelot_c_fpga.h" -struct callvectors { - int (*open) (char*, int, int); - int (*close) (int); - int (*read) (int, void*, int); - int (*write) (int, void*, int); - off_t (*lseek) (int, off_t, int); - int (*printf) (const char*, ...); - void (*cacheflush) (void); - char* (*gets) (char*); -}; - struct callvectors* debug_vectors; extern unsigned long mv64340_base; --- linux-2.6.6/arch/mips/momentum/ocelot_g/prom.c 2004-03-10 20:41:26.000000000 -0800 +++ 25/arch/mips/momentum/ocelot_g/prom.c 2004-05-10 01:19:15.228423984 -0700 @@ -19,21 +19,11 @@ #include #include +#include #include "gt64240.h" #include "ocelot_pld.h" -struct callvectors { - int (*open) (char*, int, int); - int (*close) (int); - int (*read) (int, void*, int); - int (*write) (int, void*, int); - off_t (*lseek) (int, off_t, int); - int (*printf) (const char*, ...); - void (*cacheflush) (void); - char* (*gets) (char*); -}; - struct callvectors* debug_vectors; extern unsigned long gt64240_base; --- linux-2.6.6/arch/mips/pci/fixup-au1000.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/pci/fixup-au1000.c 2004-05-10 01:19:15.229423832 -0700 @@ -37,22 +37,72 @@ /* * Shortcut */ -#define INTA AU1000_PCI_INTA -#define INTB AU1000_PCI_INTB +#ifdef CONFIG_SOC_AU1500 +#define INTA AU1000_PCI_INTA +#define INTB AU1000_PCI_INTB +#define INTC AU1000_PCI_INTC +#define INTD AU1000_PCI_INTD +#endif + +#ifdef CONFIG_SOC_AU1550 +#define INTA AU1550_PCI_INTA +#define INTB AU1550_PCI_INTB +#define INTC AU1550_PCI_INTC +#define INTD AU1550_PCI_INTD +#endif + +#define INTX 0xFF /* not valid */ + +#ifdef CONFIG_MIPS_DB1500 +static char irq_tab_alchemy[][5] __initdata = { + [12] = { -1, INTA, INTX, INTX, INTX}, /* IDSEL 12 - HPT371 */ + [13] = { -1, INTA, INTB, INTC, INTD}, /* IDSEL 13 - PCI slot */ +}; +#endif + +#ifdef CONFIG_MIPS_BOSPORUS +static char irq_tab_alchemy[][5] __initdata = { + [11] = { -1, INTA, INTB, INTX, INTX}, /* IDSEL 11 - miniPCI */ + [12] = { -1, INTA, INTX, INTX, INTX}, /* IDSEL 12 - SN1741 */ + [13] = { -1, INTA, INTB, INTC, INTD}, /* IDSEL 13 - PCI slot */ +}; +#endif +#ifdef CONFIG_MIPS_MIRAGE static char irq_tab_alchemy[][5] __initdata = { - [11] = { -1, INTA, INTA, INTA, INTA }, - [12] = { -1, INTA, INTA, INTA, INTA }, -#if defined( CONFIG_SOC_AU1550 ) - [13] = { -1, INTB, INTB, INTB, INTB } + [11] = { -1, INTD, INTX, INTX, INTX}, /* IDSEL 11 - SMI VGX */ + [12] = { -1, INTX, INTX, INTC, INTX}, /* IDSEL 12 - PNX1300 */ + [13] = { -1, INTA, INTB, INTX, INTX}, /* IDSEL 13 - miniPCI */ +}; +#endif + +#ifdef CONFIG_MIPS_DB1550 +static char irq_tab_alchemy[][5] __initdata = { + [11] = { -1, INTC, INTX, INTX, INTX}, /* IDSEL 11 - on-board HPT371 */ + [12] = { -1, INTB, INTC, INTD, INTA}, /* IDSEL 12 - PCI slot 2 (left) */ + [13] = { -1, INTA, INTB, INTC, INTD}, /* IDSEL 13 - PCI slot 1 (right) */ +}; +#endif + +#ifdef CONFIG_MIPS_PB1500 +static char irq_tab_alchemy[][5] __initdata = { + [12] = { -1, INTA, INTX, INTX, INTX}, /* IDSEL 12 - HPT370 */ + [13] = { -1, INTA, INTB, INTC, INTD}, /* IDSEL 13 - PCI slot */ +}; #endif + +#ifdef CONFIG_MIPS_PB1550 +static char irq_tab_alchemy[][5] __initdata = { + [12] = { -1, INTB, INTC, INTD, INTA}, /* IDSEL 12 - PCI slot 2 (left) */ + [13] = { -1, INTA, INTB, INTC, INTD}, /* IDSEL 13 - PCI slot 1 (right) */ }; +#endif int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { - return irq_tab_alchemy[slot][pin]; +return irq_tab_alchemy[slot][pin]; } struct pci_fixup pcibios_fixups[] __initdata = { - { 0 } +{ 0 } }; --- linux-2.6.6/arch/mips/pci/ops-au1000.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/pci/ops-au1000.c 2004-05-10 01:19:15.230423680 -0700 @@ -33,89 +33,170 @@ #include #include #include +#include #include +#undef DEBUG +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + #define PCI_ACCESS_READ 0 #define PCI_ACCESS_WRITE 1 +int (*board_pci_idsel)(unsigned int devsel, int assert); + +/* CP0 hazard avoidance. */ +#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ + "nop; nop; nop; nop;\t" \ + ".set reorder\n\t") + +void mod_wired_entry(int entry, unsigned long entrylo0, + unsigned long entrylo1, unsigned long entryhi, + unsigned long pagemask) +{ + unsigned long old_pagemask; + unsigned long old_ctx; + + /* Save old context and create impossible VPN2 value */ + old_ctx = read_c0_entryhi() & 0xff; + old_pagemask = read_c0_pagemask(); + write_c0_index(entry); + BARRIER; + write_c0_pagemask(pagemask); + write_c0_entryhi(entryhi); + write_c0_entrylo0(entrylo0); + write_c0_entrylo1(entrylo1); + BARRIER; + tlb_write_indexed(); + BARRIER; + write_c0_entryhi(old_ctx); + BARRIER; + write_c0_pagemask(old_pagemask); +} + +struct vm_struct *pci_cfg_vm; +static int pci_cfg_wired_entry; +static int first_cfg = 1; +unsigned long last_entryLo0, last_entryLo1; + static int config_access(unsigned char access_type, struct pci_bus *bus, - unsigned int devfn, unsigned char where, + unsigned int dev_fn, unsigned char where, u32 * data) { - unsigned int device = PCI_SLOT(devfn); - unsigned int function = PCI_FUNC(devfn); - unsigned long config, status; - unsigned long cfg_addr; +#if defined( CONFIG_SOC_AU1500 ) || defined( CONFIG_SOC_AU1550 ) + unsigned int device = PCI_SLOT(dev_fn); + unsigned int function = PCI_FUNC(dev_fn); + unsigned long offset, status; + unsigned long cfg_base; + unsigned long flags; + int error = PCIBIOS_SUCCESSFUL; + unsigned long entryLo0, entryLo1; if (device > 19) { *data = 0xffffffff; return -1; } - au_writel(((0x2000 << 16) | - (au_readl(Au1500_PCI_STATCMD) & 0xffff)), - Au1500_PCI_STATCMD); - //au_writel(au_readl(Au1500_PCI_CFG) & ~PCI_ERROR, Au1500_PCI_CFG); + local_irq_save(flags); + au_writel(((0x2000 << 16) | (au_readl(Au1500_PCI_STATCMD) & 0xffff)), + Au1500_PCI_STATCMD); au_sync_udelay(1); - /* setup the config window */ - if (bus->number == 0) { - cfg_addr = (unsigned long) ioremap(Au1500_EXT_CFG | - ((1 << device) << 11), - 0x00100000); - } else { - cfg_addr = (unsigned long) ioremap(Au1500_EXT_CFG_TYPE1 | - (bus-> - number << 16) | (device - << - 11), - 0x00100000); + /* + * We can't ioremap the entire pci config space because it's + * too large. Nor can we call ioremap dynamically because some + * device drivers use the pci config routines from within + * interrupt handlers and that becomes a problem in get_vm_area(). + * We use one wired tlb to handle all config accesses for all + * busses. To improve performance, if the current device + * is the same as the last device accessed, we don't touch the + * tlb. + */ + if (first_cfg) { + /* reserve a wired entry for pci config accesses */ + first_cfg = 0; + pci_cfg_vm = get_vm_area(0x2000, 0); + if (!pci_cfg_vm) + panic (KERN_ERR "PCI unable to get vm area\n"); + pci_cfg_wired_entry = read_c0_wired(); + add_wired_entry(0, 0, (unsigned long)pci_cfg_vm->addr, PM_4K); + last_entryLo0 = last_entryLo1 = 0xffffffff; } - if (!cfg_addr) - panic(KERN_ERR "PCI unable to ioremap cfg space\n"); - - /* setup the lower bits of the 36 bit address */ - config = cfg_addr | (function << 8) | (where & ~0x3); - -#if 1 - if (access_type == PCI_ACCESS_WRITE) { - printk("cfg write: "); - } else { - printk("cfg read: "); + /* Since the Au1xxx doesn't do the idsel timing exactly to spec, + * many board vendors implement their own off-chip idsel, so call + * it now. If it doesn't succeed, may as well bail out at this point. + */ + if (board_pci_idsel) { + if (board_pci_idsel(device, 1) == 0) { + *data = 0xffffffff; + local_irq_restore(flags); + return -1; + } } - printk("devfn %x, device %x func %x \n", devfn, device, function); - if (access_type == PCI_ACCESS_WRITE) { - printk("data %x\n", *data); + + /* setup the config window */ + if (bus->number == 0) { + cfg_base = ((1<number<<16) | (device<<11); + } + + /* setup the lower bits of the 36 bit address */ + offset = (function << 8) | (where & ~0x3); + /* pick up any address that falls below the page mask */ + offset |= cfg_base & ~PAGE_MASK; + + /* page boundary */ + cfg_base = cfg_base & PAGE_MASK; + + entryLo0 = (6 << 26) | (cfg_base >> 6) | (2 << 3) | 7; + entryLo1 = (6 << 26) | (cfg_base >> 6) | (0x1000 >> 6) | (2 << 3) | 7; + + if ((entryLo0 != last_entryLo0) || (entryLo1 != last_entryLo1)) { + mod_wired_entry(pci_cfg_wired_entry, entryLo0, entryLo1, + (unsigned long)pci_cfg_vm->addr, PM_4K); + last_entryLo0 = entryLo0; + last_entryLo1 = entryLo1; } -#endif if (access_type == PCI_ACCESS_WRITE) { - au_writel(*data, config); + au_writel(*data, (int)(pci_cfg_vm->addr + offset)); } else { - *data = au_readl(config); + *data = au_readl((int)(pci_cfg_vm->addr + offset)); } au_sync_udelay(2); - /* unmap io space */ - iounmap((void *) cfg_addr); + DBG("cfg_access %d bus->number %d dev %d at %x *data %x conf %x\n", + access_type, bus->number, device, where, *data, offset); /* check master abort */ status = au_readl(Au1500_PCI_STATCMD); - if (status & (1 << 29)) { - printk("master abort\n"); + + if (status & (1<<29)) { *data = 0xffffffff; - return -1; + error = -1; + DBG("Au1x Master Abort\n"); } else if ((status >> 28) & 0xf) { - printk("PCI ERR detected: status %x\n", status); + DBG("PCI ERR detected: status %x\n", status); *data = 0xffffffff; - return -1; - } else { - printk("bios_successful: %x\n", *data); - return PCIBIOS_SUCCESSFUL; + error = -1; + } + + /* Take away the idsel. + */ + if (board_pci_idsel) { + (void)board_pci_idsel(device, 0); } + + local_irq_restore(flags); + return error; +#endif } static int read_config_byte(struct pci_bus *bus, unsigned int devfn, --- linux-2.6.6/arch/mips/sgi-ip27/ip27-hubio.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/sgi-ip27/ip27-hubio.c 2004-05-10 01:19:15.230423680 -0700 @@ -166,18 +166,18 @@ static void hub_set_piomode(nasid_t nasi REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, ii_iowa); } -/** +/* * hub_pio_init - PIO-related hub initalization * * @hub: hubinfo structure for our hub - **/ + */ void hub_pio_init(cnodeid_t cnode) { nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); unsigned i; /* initialize big window piomaps for this hub */ - CLEAR_BITMAP(HUB_DATA(cnode)->h_bigwin_used, HUB_NUM_BIG_WINDOW); + bitmap_zero(HUB_DATA(cnode)->h_bigwin_used, HUB_NUM_BIG_WINDOW); for (i = 0; i < HUB_NUM_BIG_WINDOW; i++) IIO_ITTE_DISABLE(nasid, i); --- linux-2.6.6/arch/mips/vr41xx/casio-e55/setup.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/vr41xx/casio-e55/setup.c 2004-05-10 01:19:15.231423528 -0700 @@ -35,7 +35,8 @@ static int casio_e55_setup(void) ioport_resource.end = IO_PORT_RESOURCE_END; #ifdef CONFIG_SERIAL_8250 - vr41xx_siu_init(SIU_RS232C, 0); + vr41xx_select_siu_interface(SIU_RS232C, IRDA_NONE); + vr41xx_siu_init(); #endif return 0; --- linux-2.6.6/arch/mips/vr41xx/common/icu.c 2004-03-10 20:41:26.000000000 -0800 +++ 25/arch/mips/vr41xx/common/icu.c 2004-05-10 01:19:15.232423376 -0700 @@ -1,34 +1,23 @@ /* - * FILE NAME - * arch/mips/vr41xx/common/icu.c + * icu.c, Interrupt Control Unit routines for the NEC VR4100 series. * - * BRIEF MODULE DESCRIPTION - * Interrupt Control Unit routines for the NEC VR4100 series. + * Copyright (C) 2001-2002 MontaVista Software Inc. + * Author: Yoichi Yuasa + * Copyright (C) 2003-2004 Yoichi Yuasa * - * Author: Yoichi Yuasa - * yyuasa@mvista.com or source@mvista.com + * 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. * - * Copyright 2001,2002 MontaVista Software Inc. + * 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. * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. + * 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 */ /* * Changes: @@ -90,6 +79,9 @@ static unsigned char sysint2_assign[16] #define MSYSINT2REG 0x06 #define MGIUINTHREG 0x08 +#define MDSIUINTREG KSEG1ADDR(0x0f000096) + #define INTDSIU 0x0800 + #define SYSINT1_IRQ_TO_PIN(x) ((x) - SYSINT1_IRQ_BASE) /* Pin 0-15 */ #define SYSINT2_IRQ_TO_PIN(x) ((x) - SYSINT2_IRQ_BASE) /* Pin 0-15 */ @@ -148,6 +140,18 @@ static inline uint16_t clear_icu2(uint8_ /*=======================================================================*/ +void vr41xx_enable_dsiuint(void) +{ + writew(INTDSIU, MDSIUINTREG); +} + +void vr41xx_disable_dsiuint(void) +{ + writew(0, MDSIUINTREG); +} + +/*=======================================================================*/ + static void enable_sysint1_irq(unsigned int irq) { set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq)); --- linux-2.6.6/arch/mips/vr41xx/common/serial.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/vr41xx/common/serial.c 2004-05-10 01:19:15.233423224 -0700 @@ -40,14 +40,8 @@ #include #include -/* VR4111 and VR4121 SIU Registers */ -#define SIURB_TYPE1 KSEG1ADDR(0x0c000000) #define SIUIRSEL_TYPE1 KSEG1ADDR(0x0c000008) - -/* VR4122, VR4131 and VR4133 SIU Registers */ -#define SIURB_TYPE2 KSEG1ADDR(0x0f000800) #define SIUIRSEL_TYPE2 KSEG1ADDR(0x0f000808) - #define USE_RS232C 0x00 #define USE_IRDA 0x01 #define SIU_USES_IRDA 0x00 @@ -58,21 +52,24 @@ #define TMICTX 0x10 #define TMICMODE 0x20 -#define SIU_BASE_BAUD 1152000 +#define SIU_BASE_TYPE1 0x0c000000UL /* VR4111 and VR4121 */ +#define SIU_BASE_TYPE2 0x0f000800UL /* VR4122, VR4131 and VR4133 */ +#define SIU_SIZE 0x8UL -/* VR4122 and VR4131 DSIU Registers */ -#define DSIURB KSEG1ADDR(0x0f000820) +#define SIU_BASE_BAUD 1152000 -#define MDSIUINTREG KSEG1ADDR(0x0f000096) - #define INTDSIU 0x0800 +/* VR4122, VR4131 and VR4133 DSIU Registers */ +#define DSIU_BASE 0x0f000820UL +#define DSIU_SIZE 0x8UL #define DSIU_BASE_BAUD 1152000 int vr41xx_serial_ports = 0; -void vr41xx_siu_ifselect(int interface, int module) +void vr41xx_select_siu_interface(siu_interface_t interface, + irda_module_t module) { - u16 val = USE_RS232C; /* Select RS-232C */ + uint16_t val = USE_RS232C; /* Select RS-232C */ /* Select IrDA */ if (interface == SIU_IRDA) { @@ -86,6 +83,9 @@ void vr41xx_siu_ifselect(int interface, case IRDA_HP: val = IRDA_MODULE_HP; break; + default: + printk(KERN_ERR "SIU: unknown IrDA module\n"); + return; } val |= USE_IRDA | SIU_USES_IRDA; } @@ -101,45 +101,47 @@ void vr41xx_siu_ifselect(int interface, writew(val, SIUIRSEL_TYPE2); break; default: - printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n"); + printk(KERN_ERR "SIU: unsupported CPU of NEC VR4100 series\n"); break; } } -void __init vr41xx_siu_init(int interface, int module) +void __init vr41xx_siu_init(void) { struct uart_port port; - vr41xx_siu_ifselect(interface, module); - memset(&port, 0, sizeof(port)); port.line = vr41xx_serial_ports; - port.uartclk = SIU_BASE_BAUD; + port.uartclk = SIU_BASE_BAUD * 16; port.irq = SIU_IRQ; - port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; + port.flags = UPF_RESOURCES | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; switch (current_cpu_data.cputype) { case CPU_VR4111: case CPU_VR4121: - port.membase = (char *)SIURB_TYPE1; + port.mapbase = SIU_BASE_TYPE1; break; case CPU_VR4122: case CPU_VR4131: case CPU_VR4133: - port.membase = (char *)SIURB_TYPE2; + port.mapbase = SIU_BASE_TYPE2; break; default: - panic("Unexpected CPU of NEC VR4100 series"); - break; + printk(KERN_ERR "SIU: unsupported CPU of NEC VR4100 series\n"); + return; } port.regshift = 0; port.iotype = UPIO_MEM; - if (early_serial_setup(&port) != 0) - printk(KERN_ERR "SIU setup failed!\n"); - - vr41xx_supply_clock(SIU_CLOCK); + port.membase = ioremap(port.mapbase, SIU_SIZE); + if (port.membase != NULL) { + if (early_serial_setup(&port) == 0) { + vr41xx_supply_clock(SIU_CLOCK); + vr41xx_serial_ports++; + return; + } + } - vr41xx_serial_ports++; + printk(KERN_ERR "SIU: setup failed!\n"); } void __init vr41xx_dsiu_init(void) @@ -148,24 +150,29 @@ void __init vr41xx_dsiu_init(void) if (current_cpu_data.cputype != CPU_VR4122 && current_cpu_data.cputype != CPU_VR4131 && - current_cpu_data.cputype != CPU_VR4133) + current_cpu_data.cputype != CPU_VR4133) { + printk(KERN_ERR "DSIU: unsupported CPU of NEC VR4100 series\n"); return; + } memset(&port, 0, sizeof(port)); port.line = vr41xx_serial_ports; - port.uartclk = DSIU_BASE_BAUD; + port.uartclk = DSIU_BASE_BAUD * 16; port.irq = DSIU_IRQ; - port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; - port.membase = (char *)DSIURB; + port.flags = UPF_RESOURCES | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; + port.mapbase = DSIU_BASE; port.regshift = 0; port.iotype = UPIO_MEM; - if (early_serial_setup(&port) != 0) - printk(KERN_ERR "DSIU setup failed!\n"); - - vr41xx_supply_clock(DSIU_CLOCK); - - writew(INTDSIU, MDSIUINTREG); + port.membase = ioremap(port.mapbase, DSIU_SIZE); + if (port.membase != NULL) { + if (early_serial_setup(&port) == 0) { + vr41xx_supply_clock(DSIU_CLOCK); + vr41xx_enable_dsiuint(); + vr41xx_serial_ports++; + return; + } + } - vr41xx_serial_ports++; + printk(KERN_ERR "DSIU: setup failed!\n"); } --- linux-2.6.6/arch/mips/vr41xx/ibm-workpad/setup.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/vr41xx/ibm-workpad/setup.c 2004-05-10 01:19:15.233423224 -0700 @@ -35,7 +35,8 @@ static int ibm_workpad_setup(void) ioport_resource.end = IO_PORT_RESOURCE_END; #ifdef CONFIG_SERIAL_8250 - vr41xx_siu_init(SIU_RS232C, 0); + vr41xx_select_siu_interface(SIU_RS232C, IRDA_NONE); + vr41xx_siu_init(); #endif return 0; --- linux-2.6.6/arch/mips/vr41xx/nec-eagle/setup.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/vr41xx/nec-eagle/setup.c 2004-05-10 01:19:15.233423224 -0700 @@ -80,8 +80,9 @@ static int nec_eagle_setup(void) ioport_resource.end = IO_PORT_RESOURCE_END; #ifdef CONFIG_SERIAL_8250 + vr41xx_select_siu_interface(SIU_RS232C, IRDA_NONE); + vr41xx_siu_init(); vr41xx_dsiu_init(); - vr41xx_siu_init(SIU_RS232C, 0); #endif #ifdef CONFIG_PCI --- linux-2.6.6/arch/mips/vr41xx/tanbac-tb0226/setup.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/vr41xx/tanbac-tb0226/setup.c 2004-05-10 01:19:15.234423072 -0700 @@ -83,7 +83,10 @@ static int tanbac_tb0226_setup(void) ioport_resource.start = IO_PORT_RESOURCE_START; ioport_resource.end = IO_PORT_RESOURCE_END; - vr41xx_siu_init(SIU_RS232C, 0); +#ifdef CONFIG_SERIAL_8250 + vr41xx_select_siu_interface(SIU_RS232C, IRDA_NONE); + vr41xx_siu_init(); +#endif #ifdef CONFIG_PCI vr41xx_pciu_init(&pci_address_map); --- linux-2.6.6/arch/mips/vr41xx/tanbac-tb0229/setup.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/vr41xx/tanbac-tb0229/setup.c 2004-05-10 01:19:15.234423072 -0700 @@ -87,8 +87,11 @@ static int tanbac_tb0229_setup(void) ioport_resource.start = IO_PORT_RESOURCE_START; ioport_resource.end = IO_PORT_RESOURCE_END; - vr41xx_siu_init(SIU_RS232C, 0); +#ifdef CONFIG_SERIAL_8250 + vr41xx_select_siu_interface(SIU_RS232C, IRDA_NONE); + vr41xx_siu_init(); vr41xx_dsiu_init(); +#endif #ifdef CONFIG_PCI vr41xx_pciu_init(&pci_address_map); --- linux-2.6.6/arch/mips/vr41xx/victor-mpc30x/setup.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/vr41xx/victor-mpc30x/setup.c 2004-05-10 01:19:15.234423072 -0700 @@ -84,7 +84,8 @@ static int victor_mpc30x_setup(void) ioport_resource.end = IO_PORT_RESOURCE_END; #ifdef CONFIG_SERIAL_8250 - vr41xx_siu_init(SIU_RS232C, 0); + vr41xx_select_siu_interface(SIU_RS232C, IRDA_NONE); + vr41xx_siu_init(); #endif #ifdef CONFIG_PCI --- linux-2.6.6/arch/mips/vr41xx/zao-capcella/setup.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/mips/vr41xx/zao-capcella/setup.c 2004-05-10 01:19:15.235422920 -0700 @@ -84,7 +84,8 @@ static int zao_capcella_setup(void) ioport_resource.end = IO_PORT_RESOURCE_END; #ifdef CONFIG_SERIAL_8250 - vr41xx_siu_init(SIU_RS232C, 0); + vr41xx_select_siu_interface(SIU_RS232C, IRDA_NONE); + vr41xx_siu_init(); vr41xx_dsiu_init(); #endif --- linux-2.6.6/arch/parisc/kernel/cache.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/parisc/kernel/cache.c 2004-05-10 01:19:13.420698800 -0700 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -231,67 +232,38 @@ void __flush_dcache_page(struct page *pa { struct address_space *mapping = page_mapping(page); struct mm_struct *mm = current->active_mm; - struct list_head *l; + struct vm_area_struct *mpnt = NULL; + struct prio_tree_iter iter; + unsigned long offset; + pgoff_t pgoff; flush_kernel_dcache_page(page_address(page)); if (!mapping) return; - /* check shared list first if it's not empty...it's usually - * the shortest */ - list_for_each(l, &mapping->i_mmap_shared) { - struct vm_area_struct *mpnt; - unsigned long off; - mpnt = list_entry(l, struct vm_area_struct, shared); + pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); + flush_dcache_mmap_lock(mapping); + while ((mpnt = vma_prio_tree_next(mpnt, &mapping->i_mmap, + &iter, pgoff, pgoff)) != NULL) { /* * If this VMA is not in our MM, we can ignore it. */ if (mpnt->vm_mm != mm) continue; - - if (page->index < mpnt->vm_pgoff) - continue; - - off = page->index - mpnt->vm_pgoff; - if (off >= (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT) - continue; - - flush_cache_page(mpnt, mpnt->vm_start + (off << PAGE_SHIFT)); - - /* All user shared mappings should be equivalently mapped, - * so once we've flushed one we should be ok - */ - return; - } - - /* then check private mapping list for read only shared mappings - * which are flagged by VM_MAYSHARE */ - list_for_each(l, &mapping->i_mmap) { - struct vm_area_struct *mpnt; - unsigned long off; - - mpnt = list_entry(l, struct vm_area_struct, shared); - - - if (mpnt->vm_mm != mm || !(mpnt->vm_flags & VM_MAYSHARE)) - continue; - - if (page->index < mpnt->vm_pgoff) - continue; - - off = page->index - mpnt->vm_pgoff; - if (off >= (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT) + if (!(mpnt->vm_flags & VM_MAYSHARE)) continue; - flush_cache_page(mpnt, mpnt->vm_start + (off << PAGE_SHIFT)); + offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT; + flush_cache_page(mpnt, mpnt->vm_start + offset); /* All user shared mappings should be equivalently mapped, * so once we've flushed one we should be ok */ break; } + flush_dcache_mmap_unlock(mapping); } EXPORT_SYMBOL(__flush_dcache_page); --- linux-2.6.6/arch/parisc/kernel/setup.c 2003-10-08 15:07:08.000000000 -0700 +++ 25/arch/parisc/kernel/setup.c 2004-05-10 01:19:18.569916000 -0700 @@ -45,8 +45,6 @@ #include #include -#define COMMAND_LINE_SIZE 1024 -char saved_command_line[COMMAND_LINE_SIZE]; char command_line[COMMAND_LINE_SIZE]; /* Intended for ccio/sba/cpu statistics under /proc/bus/{runway|gsc} */ --- linux-2.6.6/arch/parisc/kernel/smp.c 2004-04-03 20:39:10.000000000 -0800 +++ 25/arch/parisc/kernel/smp.c 2004-05-10 01:19:49.907152016 -0700 @@ -327,6 +327,9 @@ smp_call_function (void (*func) (void *i struct smp_call_struct data; unsigned long timeout; static spinlock_t lock = SPIN_LOCK_UNLOCKED; + + /* Can deadlock when called with interrupts disabled */ + WARN_ON(irqs_disabled()); data.func = func; data.info = info; --- linux-2.6.6/arch/parisc/kernel/syscall_table.S 2004-04-03 20:39:10.000000000 -0800 +++ 25/arch/parisc/kernel/syscall_table.S 2004-05-10 01:19:35.175391584 -0700 @@ -232,12 +232,12 @@ ENTRY_DIFF(getdents) /* it is POSSIBLE that select will be OK because even though fd_set * contains longs, the macros and sizes are clever. */ - ENTRY_DIFF(select) + ENTRY_COMP(select) ENTRY_SAME(flock) ENTRY_SAME(msync) /* struct iovec contains pointers */ - ENTRY_DIFF(readv) /* 145 */ - ENTRY_DIFF(writev) + ENTRY_COMP(readv) /* 145 */ + ENTRY_COMP(writev) ENTRY_SAME(getsid) ENTRY_SAME(fdatasync) /* struct __sysctl_args is a mess */ @@ -266,7 +266,7 @@ ENTRY_SAME(ni_syscall) /* query_module */ ENTRY_SAME(poll) /* structs contain pointers and an in_addr... */ - ENTRY_DIFF(nfsservctl) + ENTRY_COMP(nfsservctl) ENTRY_SAME(setresgid) /* 170 */ ENTRY_SAME(getresgid) ENTRY_SAME(prctl) --- linux-2.6.6/arch/parisc/kernel/sys_parisc32.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/parisc/kernel/sys_parisc32.c 2004-05-10 01:19:35.176391432 -0700 @@ -65,189 +65,6 @@ #endif /* - * count32() counts the number of arguments/envelopes. It is basically - * a copy of count() from fs/exec.c, except that it works - * with 32 bit argv and envp pointers. - */ - -static int count32(u32 *argv, int max) -{ - int i = 0; - - if (argv != NULL) { - for (;;) { - u32 p; - int error; - - error = get_user(p,argv); - if (error) - return error; - if (!p) - break; - argv++; - if(++i > max) - return -E2BIG; - } - } - return i; -} - - -/* - * copy_strings32() is basically a copy of copy_strings() from fs/exec.c - * except that it works with 32 bit argv and envp pointers. - */ - - -static int copy_strings32(int argc, u32 *argv, struct linux_binprm *bprm) -{ - while (argc-- > 0) { - u32 str; - int len; - unsigned long pos; - - if (get_user(str, argv + argc) || - !str || - !(len = strnlen_user((char *)compat_ptr(str), bprm->p))) - return -EFAULT; - - if (bprm->p < len) - return -E2BIG; - - bprm->p -= len; - - pos = bprm->p; - while (len > 0) { - char *kaddr; - int i, new, err; - struct page *page; - int offset, bytes_to_copy; - - offset = pos % PAGE_SIZE; - i = pos/PAGE_SIZE; - page = bprm->page[i]; - new = 0; - if (!page) { - page = alloc_page(GFP_HIGHUSER); - bprm->page[i] = page; - if (!page) - return -ENOMEM; - new = 1; - } - kaddr = (char *)kmap(page); - - if (new && offset) - memset(kaddr, 0, offset); - bytes_to_copy = PAGE_SIZE - offset; - if (bytes_to_copy > len) { - bytes_to_copy = len; - if (new) - memset(kaddr+offset+len, 0, PAGE_SIZE-offset-len); - } - err = copy_from_user(kaddr + offset, (char *)compat_ptr(str), bytes_to_copy); - flush_dcache_page(page); - kunmap(page); - - if (err) - return -EFAULT; - - pos += bytes_to_copy; - str += bytes_to_copy; - len -= bytes_to_copy; - } - } - return 0; -} - -/* - * do_execve32() is mostly a copy of do_execve(), with the exception - * that it processes 32 bit argv and envp pointers. - */ - -static inline int -do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs) -{ - struct linux_binprm bprm; - struct file *file; - int retval; - int i; - - file = open_exec(filename); - - retval = PTR_ERR(file); - if (IS_ERR(file)) - return retval; - - bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); - memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0])); - - DBG(("do_execve32(%s, %p, %p, %p)\n", filename, argv, envp, regs)); - - bprm.file = file; - bprm.filename = filename; - bprm.interp = filename; - bprm.sh_bang = 0; - bprm.loader = 0; - bprm.exec = 0; - - bprm.mm = mm_alloc(); - retval = -ENOMEM; - if (!bprm.mm) - goto out_file; - - retval = init_new_context(current, bprm.mm); - if (retval < 0) - goto out_mm; - - if ((bprm.argc = count32(argv, bprm.p / sizeof(u32))) < 0) - goto out_mm; - - if ((bprm.envc = count32(envp, bprm.p / sizeof(u32))) < 0) - goto out_mm; - - retval = prepare_binprm(&bprm); - if (retval < 0) - goto out; - - retval = copy_strings_kernel(1, &bprm.filename, &bprm); - if (retval < 0) - goto out; - - bprm.exec = bprm.p; - retval = copy_strings32(bprm.envc, envp, &bprm); - if (retval < 0) - goto out; - - retval = copy_strings32(bprm.argc, argv, &bprm); - if (retval < 0) - goto out; - - retval = search_binary_handler(&bprm,regs); - if (retval >= 0) - /* execve success */ - return retval; - -out: - /* Something went wrong, return the inode and free the argument pages*/ - for (i = 0; i < MAX_ARG_PAGES; i++) { - struct page *page = bprm.page[i]; - if (page) - __free_page(page); - } - -out_mm: - mmdrop(bprm.mm); - -out_file: - if (bprm.file) { - allow_write_access(bprm.file); - fput(bprm.file); - } - - return retval; -} - -/* * sys32_execve() executes a new program. */ @@ -261,8 +78,8 @@ asmlinkage int sys32_execve(struct pt_re error = PTR_ERR(filename); if (IS_ERR(filename)) goto out; - error = do_execve32(filename, (u32 *) regs->gr[25], - (u32 *) regs->gr[24], regs); + error = compat_do_execve(filename, compat_ptr(regs->gr[25]), + compat_ptr(regs->gr[24]), regs); if (error == 0) current->ptrace &= ~PT_DTRACE; putname(filename); @@ -609,149 +426,6 @@ out: return error; } -/* readv/writev stolen from mips64 */ -typedef ssize_t (*IO_fn_t)(struct file *, char *, size_t, loff_t *); - -static long -do_readv_writev32(int type, struct file *file, const struct compat_iovec *vector, - u32 count) -{ - unsigned long tot_len; - struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov=iovstack, *ivp; - struct inode *inode; - long retval, i; - IO_fn_t fn; - - /* First get the "struct iovec" from user memory and - * verify all the pointers - */ - if (!count) - return 0; - if(verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count)) - return -EFAULT; - if (count > UIO_MAXIOV) - return -EINVAL; - if (count > UIO_FASTIOV) { - iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL); - if (!iov) - return -ENOMEM; - } - - tot_len = 0; - i = count; - ivp = iov; - while (i > 0) { - u32 len; - u32 buf; - - __get_user(len, &vector->iov_len); - __get_user(buf, &vector->iov_base); - tot_len += len; - ivp->iov_base = compat_ptr(buf); - ivp->iov_len = (compat_size_t) len; - vector++; - ivp++; - i--; - } - - inode = file->f_dentry->d_inode; - /* VERIFY_WRITE actually means a read, as we write to user space */ - retval = locks_verify_area((type == VERIFY_WRITE - ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE), - inode, file, file->f_pos, tot_len); - if (retval) { - if (iov != iovstack) - kfree(iov); - return retval; - } - - /* Then do the actual IO. Note that sockets need to be handled - * specially as they have atomicity guarantees and can handle - * iovec's natively - */ - if (inode->i_sock) { - int err; - err = sock_readv_writev(type, inode, file, iov, count, tot_len); - if (iov != iovstack) - kfree(iov); - return err; - } - - if (!file->f_op) { - if (iov != iovstack) - kfree(iov); - return -EINVAL; - } - /* VERIFY_WRITE actually means a read, as we write to user space */ - fn = file->f_op->read; - if (type == VERIFY_READ) - fn = (IO_fn_t) file->f_op->write; - ivp = iov; - while (count > 0) { - void * base; - int len, nr; - - base = ivp->iov_base; - len = ivp->iov_len; - ivp++; - count--; - nr = fn(file, base, len, &file->f_pos); - if (nr < 0) { - if (retval) - break; - retval = nr; - break; - } - retval += nr; - if (nr != len) - break; - } - if (iov != iovstack) - kfree(iov); - - return retval; -} - -asmlinkage long -sys32_readv(int fd, struct compat_iovec *vector, u32 count) -{ - struct file *file; - ssize_t ret; - - ret = -EBADF; - file = fget(fd); - if (!file) - goto bad_file; - if (file->f_op && (file->f_mode & FMODE_READ) && - (file->f_op->readv || file->f_op->read)) - ret = do_readv_writev32(VERIFY_WRITE, file, vector, count); - - fput(file); - -bad_file: - return ret; -} - -asmlinkage long -sys32_writev(int fd, struct compat_iovec *vector, u32 count) -{ - struct file *file; - ssize_t ret; - - ret = -EBADF; - file = fget(fd); - if(!file) - goto bad_file; - if (file->f_op && (file->f_mode & FMODE_WRITE) && - (file->f_op->writev || file->f_op->write)) - ret = do_readv_writev32(VERIFY_READ, file, vector, count); - fput(file); - -bad_file: - return ret; -} - /*** copied from mips64 ***/ /* * Ooo, nasty. We need here to frob 32-bit unsigned longs to @@ -814,126 +488,6 @@ set_fd_set32(unsigned long n, u32 *ufdse __put_user(*fdset, ufdset); } -/*** This is a virtual copy of sys_select from fs/select.c and probably - *** should be compared to it from time to time - ***/ -static inline void *select_bits_alloc(int size) -{ - return kmalloc(6 * size, GFP_KERNEL); -} - -static inline void select_bits_free(void *bits, int size) -{ - kfree(bits); -} - -/* - * We can actually return ERESTARTSYS instead of EINTR, but I'd - * like to be certain this leads to no problems. So I return - * EINTR just for safety. - * - * Update: ERESTARTSYS breaks at least the xview clock binary, so - * I'm trying ERESTARTNOHAND which restart only when you want to. - */ -#define MAX_SELECT_SECONDS \ - ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1) -#define DIVIDE_ROUND_UP(x,y) (((x)+(y)-1)/(y)) - -asmlinkage long -sys32_select(int n, u32 *inp, u32 *outp, u32 *exp, struct compat_timeval *tvp) -{ - fd_set_bits fds; - char *bits; - long timeout; - int ret, size, err; - - timeout = MAX_SCHEDULE_TIMEOUT; - if (tvp) { - struct compat_timeval tv32; - time_t sec, usec; - - if ((ret = copy_from_user(&tv32, tvp, sizeof tv32))) - goto out_nofds; - - sec = tv32.tv_sec; - usec = tv32.tv_usec; - - ret = -EINVAL; - if (sec < 0 || usec < 0) - goto out_nofds; - - if ((unsigned long) sec < MAX_SELECT_SECONDS) { - timeout = DIVIDE_ROUND_UP(usec, 1000000/HZ); - timeout += sec * (unsigned long) HZ; - } - } - - ret = -EINVAL; - if (n < 0) - goto out_nofds; - - if (n > current->files->max_fdset) - n = current->files->max_fdset; - - /* - * We need 6 bitmaps (in/out/ex for both incoming and outgoing), - * since we used fdset we need to allocate memory in units of - * long-words. - */ - ret = -ENOMEM; - size = FDS_BYTES(n); - bits = select_bits_alloc(size); - if (!bits) - goto out_nofds; - fds.in = (unsigned long *) bits; - fds.out = (unsigned long *) (bits + size); - fds.ex = (unsigned long *) (bits + 2*size); - fds.res_in = (unsigned long *) (bits + 3*size); - fds.res_out = (unsigned long *) (bits + 4*size); - fds.res_ex = (unsigned long *) (bits + 5*size); - - if ((ret = get_fd_set32(n, inp, fds.in)) || - (ret = get_fd_set32(n, outp, fds.out)) || - (ret = get_fd_set32(n, exp, fds.ex))) - goto out; - zero_fd_set(n, fds.res_in); - zero_fd_set(n, fds.res_out); - zero_fd_set(n, fds.res_ex); - - ret = do_select(n, &fds, &timeout); - - if (tvp && !(current->personality & STICKY_TIMEOUTS)) { - time_t sec = 0, usec = 0; - if (timeout) { - sec = timeout / HZ; - usec = timeout % HZ; - usec *= (1000000/HZ); - } - err = put_user(sec, &tvp->tv_sec); - err |= __put_user(usec, &tvp->tv_usec); - if (err) - ret = -EFAULT; - } - - if (ret < 0) - goto out; - if (!ret) { - ret = -ERESTARTNOHAND; - if (signal_pending(current)) - goto out; - ret = 0; - } - - set_fd_set32(n, inp, fds.res_in); - set_fd_set32(n, outp, fds.res_out); - set_fd_set32(n, exp, fds.res_ex); - -out: - select_bits_free(bits, size); -out_nofds: - return ret; -} - struct msgbuf32 { int mtype; char mtext[1]; @@ -991,7 +545,6 @@ asmlinkage long sys32_msgrcv(int msqid, return err; } - asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, s32 count) { mm_segment_t old_fs = get_fs(); @@ -1011,94 +564,6 @@ asmlinkage int sys32_sendfile(int out_fd return ret; } -/* EXPORT/UNEXPORT */ -struct nfsctl_export32 { - char ex_client[NFSCLNT_IDMAX+1]; - char ex_path[NFS_MAXPATHLEN+1]; - __kernel_old_dev_t ex_dev; - compat_ino_t ex_ino; - int ex_flags; - __kernel_uid_t ex_anon_uid; - __kernel_gid_t ex_anon_gid; -}; - -struct nfsctl_arg32 { - int ca_version; /* safeguard */ - /* wide kernel places this union on 8-byte boundary, narrow on 4 */ - union { - struct nfsctl_svc u_svc; - struct nfsctl_client u_client; - struct nfsctl_export32 u_export; - struct nfsctl_fdparm u_getfd; - struct nfsctl_fsparm u_getfs; - } u; -}; - -asmlinkage int sys32_nfsservctl(int cmd, void *argp, void *resp) -{ - int ret, tmp; - struct nfsctl_arg32 n32; - struct nfsctl_arg n; - - ret = copy_from_user(&n, argp, sizeof n.ca_version); - if (ret != 0) - return ret; - - /* adjust argp to point at the union inside the user's n32 struct */ - tmp = (unsigned long)&n32.u - (unsigned long)&n32; - argp = (void *)((unsigned long)argp + tmp); - switch(cmd) { - case NFSCTL_SVC: - ret = copy_from_user(&n.u, argp, sizeof n.u.u_svc); - break; - - case NFSCTL_ADDCLIENT: - case NFSCTL_DELCLIENT: - ret = copy_from_user(&n.u, argp, sizeof n.u.u_client); - break; - - case NFSCTL_GETFD: - ret = copy_from_user(&n.u, argp, sizeof n.u.u_getfd); - break; - - case NFSCTL_GETFS: - ret = copy_from_user(&n.u, argp, sizeof n.u.u_getfs); - break; - - case NFSCTL_UNEXPORT: /* nfsctl_export */ - case NFSCTL_EXPORT: /* nfsctl_export */ - ret = copy_from_user(&n32.u, argp, sizeof n32.u.u_export); -#undef CP -#define CP(x) n.u.u_export.ex_##x = n32.u.u_export.ex_##x - memcpy(n.u.u_export.ex_client, n32.u.u_export.ex_client, sizeof n32.u.u_export.ex_client); - memcpy(n.u.u_export.ex_path, n32.u.u_export.ex_path, sizeof n32.u.u_export.ex_path); - CP(dev); - CP(ino); - CP(flags); - CP(anon_uid); - CP(anon_gid); - break; - - default: - /* lockd probes for some other values (0x10000); - * so don't BUG() */ - ret = -EINVAL; - break; - } - - if (ret == 0) { - unsigned char rbuf[NFS_FHSIZE + sizeof (struct knfsd_fh)]; - KERNEL_SYSCALL(ret, sys_nfsservctl, cmd, &n, &rbuf); - if (cmd == NFSCTL_GETFD) { - ret = copy_to_user(resp, rbuf, NFS_FHSIZE); - } else if (cmd == NFSCTL_GETFS) { - ret = copy_to_user(resp, rbuf, sizeof (struct knfsd_fh)); - } - } - - return ret; -} - typedef long __kernel_loff_t32; /* move this to asm/posix_types.h? */ asmlinkage int sys32_sendfile64(int out_fd, int in_fd, __kernel_loff_t32 *offset, s32 count) --- linux-2.6.6/arch/parisc/kernel/sys_parisc.c 2004-04-03 20:39:10.000000000 -0800 +++ 25/arch/parisc/kernel/sys_parisc.c 2004-05-10 01:19:12.688810064 -0700 @@ -68,17 +68,8 @@ static unsigned long get_unshared_area(u * existing mapping and use the same offset. New scheme is to use the * address of the kernel data structure as the seed for the offset. * We'll see how that works... - */ -#if 0 -static int get_offset(struct address_space *mapping) -{ - struct vm_area_struct *vma = list_entry(mapping->i_mmap_shared.next, - struct vm_area_struct, shared); - return (vma->vm_start + ((pgoff - vma->vm_pgoff) << PAGE_SHIFT)) & - (SHMLBA - 1); -} -#else -/* The mapping is cacheline aligned, so there's no information in the bottom + * + * The mapping is cacheline aligned, so there's no information in the bottom * few bits of the address. We're looking for 10 bits (4MB / 4k), so let's * drop the bottom 8 bits and use bits 8-17. */ @@ -87,7 +78,6 @@ static int get_offset(struct address_spa int offset = (unsigned long) mapping << (PAGE_SHIFT - 8); return offset & 0x3FF000; } -#endif static unsigned long get_shared_area(struct address_space *mapping, unsigned long addr, unsigned long len, unsigned long pgoff) --- linux-2.6.6/arch/ppc64/Kconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/ppc64/Kconfig 2004-05-10 01:19:50.883003664 -0700 @@ -49,6 +49,10 @@ config FORCE_MAX_ZONEORDER source "init/Kconfig" +config SYSVIPC_COMPAT + bool + depends on COMPAT && SYSVIPC + default y menu "Platform support" @@ -173,6 +177,15 @@ config NUMA bool "NUMA support" depends on DISCONTIGMEM +config SCHED_SMT + bool "SMT (Hyperthreading) scheduler support" + depends on SMP + default off + help + SMT scheduler support improves the CPU scheduler's decision making + when dealing with POWER5 cpus at a cost of slightly increased + overhead in some places. If unsure say N here. + config PREEMPT bool "Preemptible Kernel" depends on BROKEN @@ -394,7 +407,20 @@ config DEBUG_INFO debugging info resulting in a larger kernel image. Say Y here only if you plan to use gdb to debug the kernel. If you don't debug the kernel, you can say N. - + +config SCHEDSTATS + bool "Collect scheduler statistics" + depends on PROC_FS + default y + help + If you say Y here, additional code will be inserted into the + scheduler and related routines to collect statistics about + scheduler behavior and provide them in /proc/schedstat. These + stats may be useful for both tuning and debugging the scheduler + If you aren't debugging the scheduler or trying to tune a specific + application, you can say N to avoid the very slight overhead + this adds. + endmenu source "security/Kconfig" --- linux-2.6.6/arch/ppc64/kernel/head.S 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/ppc64/kernel/head.S 2004-05-10 01:19:18.571915696 -0700 @@ -35,6 +35,7 @@ #include #include #include +#include #ifdef CONFIG_PPC_ISERIES #define DO_SOFT_DISABLE @@ -2285,4 +2286,4 @@ stab_array: */ .globl cmd_line cmd_line: - .space 512 /* COMMAND_LINE_SIZE */ + .space COMMAND_LINE_SIZE --- linux-2.6.6/arch/ppc64/kernel/misc.S 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/ppc64/kernel/misc.S 2004-05-10 01:19:35.176391432 -0700 @@ -717,8 +717,8 @@ _GLOBAL(sys_call_table32) .llong .ppc32_select .llong .sys_flock .llong .sys_msync - .llong .sys32_readv /* 145 */ - .llong .sys32_writev + .llong .compat_sys_readv /* 145 */ + .llong .compat_sys_writev .llong .sys32_getsid .llong .sys_fdatasync .llong .sys32_sysctl @@ -740,7 +740,7 @@ _GLOBAL(sys_call_table32) .llong .sys_getresuid /* 165 */ .llong .sys_ni_syscall /* old query_module syscall */ .llong .sys_poll - .llong .sys32_nfsservctl + .llong .compat_sys_nfsservctl .llong .sys_setresgid .llong .sys_getresgid /* 170 */ .llong .sys32_prctl --- linux-2.6.6/arch/ppc64/kernel/module.c 2004-02-03 20:42:34.000000000 -0800 +++ 25/arch/ppc64/kernel/module.c 2004-05-10 01:20:02.396253384 -0700 @@ -138,6 +138,16 @@ static unsigned long get_stubs_size(cons return relocs * sizeof(struct ppc64_stub_entry); } +static void dedotify_versions(struct modversion_info *vers, + unsigned long size) +{ + struct modversion_info *end; + + for (end = (void *)vers + size; vers < end; vers++) + if (vers->name[0] == '.') + memmove(vers->name, vers->name+1, strlen(vers->name)); +} + /* Undefined symbols which refer to .funcname, hack to funcname */ static void dedotify(Elf64_Sym *syms, unsigned int numsyms, char *strtab) { @@ -166,6 +176,9 @@ int module_frob_arch_sections(Elf64_Ehdr me->arch.stubs_section = i; else if (strcmp(secstrings + sechdrs[i].sh_name, ".toc") == 0) me->arch.toc_section = i; + else if (strcmp(secstrings+sechdrs[i].sh_name,"__versions")==0) + dedotify_versions((void *)hdr + sechdrs[i].sh_offset, + sechdrs[i].sh_size); /* We don't handle .init for the moment: rename to _init */ while ((p = strstr(secstrings + sechdrs[i].sh_name, ".init"))) --- linux-2.6.6/arch/ppc64/kernel/pacaData.c 2004-02-03 20:42:34.000000000 -0800 +++ 25/arch/ppc64/kernel/pacaData.c 2004-05-10 01:19:45.259858512 -0700 @@ -36,6 +36,7 @@ struct systemcfg *systemcfg; { \ .xLpPacaPtr = &paca[number].xLpPaca, \ .xLpRegSavePtr = &paca[number].xRegSav, \ + .lock_token = 0x8000, \ .xPacaIndex = (number), /* Paca Index */ \ .default_decr = 0x00ff0000, /* Initial Decr */ \ .xStab_data = { \ --- linux-2.6.6/arch/ppc64/kernel/process.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/ppc64/kernel/process.c 2004-05-10 01:19:31.141004904 -0700 @@ -469,12 +469,6 @@ static inline int validate_sp(unsigned l return 1; } -/* - * These bracket the sleeping functions.. - */ -#define first_sched (*(unsigned long *)scheduling_functions_start_here) -#define last_sched (*(unsigned long *)scheduling_functions_end_here) - unsigned long get_wchan(struct task_struct *p) { unsigned long ip, sp; @@ -493,7 +487,7 @@ unsigned long get_wchan(struct task_stru return 0; if (count > 0) { ip = *(unsigned long *)(sp + 16); - if (ip < first_sched || ip >= last_sched) + if (!in_sched_functions(ip)) return ip; } } while (count++ < 16); --- linux-2.6.6/arch/ppc64/kernel/setup.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/ppc64/kernel/setup.c 2004-05-10 01:19:18.571915696 -0700 @@ -82,7 +82,6 @@ unsigned long decr_overclock_proc0_set = int powersave_nap; -char saved_command_line[COMMAND_LINE_SIZE]; unsigned char aux_device_present; void parse_cmd_line(unsigned long r3, unsigned long r4, unsigned long r5, --- linux-2.6.6/arch/ppc64/kernel/smp.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/ppc64/kernel/smp.c 2004-05-10 01:19:49.908151864 -0700 @@ -692,6 +692,9 @@ int smp_call_function (void (*func) (voi int ret = -1, cpus; unsigned long timeout; + /* Can deadlock when called with interrupts disabled */ + WARN_ON(irqs_disabled()); + data.func = func; data.info = info; atomic_set(&data.started, 0); @@ -834,11 +837,6 @@ void __init smp_prepare_cpus(unsigned in paca[boot_cpuid].prof_counter = 1; paca[boot_cpuid].prof_multiplier = 1; - /* - * XXX very rough. - */ - cache_decay_ticks = HZ/100; - #ifndef CONFIG_PPC_ISERIES paca[boot_cpuid].next_jiffy_update_tb = tb_last_stamp = get_tb(); @@ -992,3 +990,218 @@ void __init smp_cpus_done(unsigned int m set_cpus_allowed(current, old_mask); } + +#ifdef CONFIG_SCHED_SMT +#ifdef CONFIG_NUMA +static struct sched_group sched_group_cpus[NR_CPUS]; +static struct sched_group sched_group_phys[NR_CPUS]; +static struct sched_group sched_group_nodes[MAX_NUMNODES]; +static DEFINE_PER_CPU(struct sched_domain, cpu_domains); +static DEFINE_PER_CPU(struct sched_domain, phys_domains); +static DEFINE_PER_CPU(struct sched_domain, node_domains); +__init void arch_init_sched_domains(void) +{ + int i; + struct sched_group *first = NULL, *last = NULL; + + /* Set up domains */ + for_each_cpu(i) { + struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); + struct sched_domain *phys_domain = &per_cpu(phys_domains, i); + struct sched_domain *node_domain = &per_cpu(node_domains, i); + int node = cpu_to_node(i); + cpumask_t nodemask = node_to_cpumask(node); + cpumask_t my_cpumask = cpumask_of_cpu(i); + cpumask_t sibling_cpumask = cpumask_of_cpu(i ^ 0x1); + + *cpu_domain = SD_SIBLING_INIT; + if (cur_cpu_spec->cpu_features & CPU_FTR_SMT) + cpus_or(cpu_domain->span, my_cpumask, sibling_cpumask); + else + cpu_domain->span = my_cpumask; + cpu_domain->parent = phys_domain; + cpu_domain->groups = &sched_group_cpus[i]; + + *phys_domain = SD_CPU_INIT; + phys_domain->span = nodemask; + phys_domain->parent = node_domain; + phys_domain->groups = &sched_group_phys[first_cpu(cpu_domain->span)]; + + *node_domain = SD_NODE_INIT; + node_domain->span = cpu_possible_map; + node_domain->groups = &sched_group_nodes[node]; + } + + /* Set up CPU (sibling) groups */ + for_each_cpu(i) { + struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); + int j; + first = last = NULL; + + if (i != first_cpu(cpu_domain->span)) + continue; + + for_each_cpu_mask(j, cpu_domain->span) { + struct sched_group *cpu = &sched_group_cpus[j]; + + cpus_clear(cpu->cpumask); + cpu_set(j, cpu->cpumask); + cpu->cpu_power = SCHED_LOAD_SCALE; + + if (!first) + first = cpu; + if (last) + last->next = cpu; + last = cpu; + } + last->next = first; + } + + for (i = 0; i < MAX_NUMNODES; i++) { + int j; + cpumask_t nodemask; + struct sched_group *node = &sched_group_nodes[i]; + cpumask_t node_cpumask = node_to_cpumask(i); + cpus_and(nodemask, node_cpumask, cpu_possible_map); + + if (cpus_empty(nodemask)) + continue; + + first = last = NULL; + /* Set up physical groups */ + for_each_cpu_mask(j, nodemask) { + struct sched_domain *cpu_domain = &per_cpu(cpu_domains, j); + struct sched_group *cpu = &sched_group_phys[j]; + + if (j != first_cpu(cpu_domain->span)) + continue; + + cpu->cpumask = cpu_domain->span; + /* + * Make each extra sibling increase power by 10% of + * the basic CPU. This is very arbitrary. + */ + cpu->cpu_power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE*(cpus_weight(cpu->cpumask)-1) / 10; + node->cpu_power += cpu->cpu_power; + + if (!first) + first = cpu; + if (last) + last->next = cpu; + last = cpu; + } + last->next = first; + } + + /* Set up nodes */ + first = last = NULL; + for (i = 0; i < MAX_NUMNODES; i++) { + struct sched_group *cpu = &sched_group_nodes[i]; + cpumask_t nodemask; + cpumask_t node_cpumask = node_to_cpumask(i); + cpus_and(nodemask, node_cpumask, cpu_possible_map); + + if (cpus_empty(nodemask)) + continue; + + cpu->cpumask = nodemask; + /* ->cpu_power already setup */ + + if (!first) + first = cpu; + if (last) + last->next = cpu; + last = cpu; + } + last->next = first; + + mb(); + for_each_cpu(i) { + struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); + cpu_attach_domain(cpu_domain, i); + } +} +#else /* !CONFIG_NUMA */ +static struct sched_group sched_group_cpus[NR_CPUS]; +static struct sched_group sched_group_phys[NR_CPUS]; +static DEFINE_PER_CPU(struct sched_domain, cpu_domains); +static DEFINE_PER_CPU(struct sched_domain, phys_domains); +__init void arch_init_sched_domains(void) +{ + int i; + struct sched_group *first = NULL, *last = NULL; + + /* Set up domains */ + for_each_cpu(i) { + struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); + struct sched_domain *phys_domain = &per_cpu(phys_domains, i); + cpumask_t my_cpumask = cpumask_of_cpu(i); + cpumask_t sibling_cpumask = cpumask_of_cpu(i ^ 0x1); + + *cpu_domain = SD_SIBLING_INIT; + if (cur_cpu_spec->cpu_features & CPU_FTR_SMT) + cpus_or(cpu_domain->span, my_cpumask, sibling_cpumask); + else + cpu_domain->span = my_cpumask; + cpu_domain->parent = phys_domain; + cpu_domain->groups = &sched_group_cpus[i]; + + *phys_domain = SD_CPU_INIT; + phys_domain->span = cpu_possible_map; + phys_domain->groups = &sched_group_phys[first_cpu(cpu_domain->span)]; + } + + /* Set up CPU (sibling) groups */ + for_each_cpu(i) { + struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); + int j; + first = last = NULL; + + if (i != first_cpu(cpu_domain->span)) + continue; + + for_each_cpu_mask(j, cpu_domain->span) { + struct sched_group *cpu = &sched_group_cpus[j]; + + cpus_clear(cpu->cpumask); + cpu_set(j, cpu->cpumask); + cpu->cpu_power = SCHED_LOAD_SCALE; + + if (!first) + first = cpu; + if (last) + last->next = cpu; + last = cpu; + } + last->next = first; + } + + first = last = NULL; + /* Set up physical groups */ + for_each_cpu(i) { + struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); + struct sched_group *cpu = &sched_group_phys[i]; + + if (i != first_cpu(cpu_domain->span)) + continue; + + cpu->cpumask = cpu_domain->span; + /* See SMT+NUMA setup for comment */ + cpu->cpu_power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE*(cpus_weight(cpu->cpumask)-1) / 10; + + if (!first) + first = cpu; + if (last) + last->next = cpu; + last = cpu; + } + last->next = first; + + mb(); + for_each_cpu(i) { + struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); + cpu_attach_domain(cpu_domain, i); + } +} +#endif /* CONFIG_NUMA */ +#endif /* CONFIG_SCHED_SMT */ --- linux-2.6.6/arch/ppc64/kernel/sys_ppc32.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/ppc64/kernel/sys_ppc32.c 2004-05-10 01:19:50.887003056 -0700 @@ -15,7 +15,6 @@ */ #include -#include #include #include #include @@ -60,17 +59,17 @@ #include #include #include +#include + +#include +#include +#include #include #include #include #include - #include - -#include -#include -#include #include #include #include @@ -78,178 +77,6 @@ #include "pci.h" -typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *); -typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *); - -static long do_readv_writev32(int type, struct file *file, - const struct compat_iovec *vector, u32 count) -{ - compat_ssize_t tot_len; - struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov=iovstack, *ivp; - struct inode *inode; - long retval, i; - io_fn_t fn; - iov_fn_t fnv; - - /* - * SuS says "The readv() function *may* fail if the iovcnt argument - * was less than or equal to 0, or greater than {IOV_MAX}. Linux has - * traditionally returned zero for zero segments, so... - */ - retval = 0; - if (count == 0) - goto out; - - /* First get the "struct iovec" from user memory and - * verify all the pointers - */ - retval = -EINVAL; - if (count > UIO_MAXIOV) - goto out; - if (!file->f_op) - goto out; - if (count > UIO_FASTIOV) { - retval = -ENOMEM; - iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL); - if (!iov) - goto out; - } - retval = -EFAULT; - if (verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count)) - goto out; - - /* - * Single unix specification: - * We should -EINVAL if an element length is not >= 0 and fitting an - * ssize_t. The total length is fitting an ssize_t - * - * Be careful here because iov_len is a size_t not an ssize_t - */ - tot_len = 0; - i = count; - ivp = iov; - retval = -EINVAL; - while(i > 0) { - compat_ssize_t tmp = tot_len; - compat_ssize_t len; - u32 buf; - - if (__get_user(len, &vector->iov_len) || - __get_user(buf, &vector->iov_base)) { - retval = -EFAULT; - goto out; - } - if (len < 0) /* size_t not fitting an compat_ssize_t .. */ - goto out; - tot_len += len; - if (tot_len < tmp) /* maths overflow on the compat_ssize_t */ - goto out; - ivp->iov_base = (void *)A(buf); - ivp->iov_len = (__kernel_size_t) len; - vector++; - ivp++; - i--; - } - if (tot_len == 0) { - retval = 0; - goto out; - } - - inode = file->f_dentry->d_inode; - /* VERIFY_WRITE actually means a read, as we write to user space */ - retval = locks_verify_area((type == READ - ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE), - inode, file, file->f_pos, tot_len); - if (retval) - goto out; - - if (type == READ) { - fn = file->f_op->read; - fnv = file->f_op->readv; - } else { - fn = (io_fn_t)file->f_op->write; - fnv = file->f_op->writev; - } - if (fnv) { - retval = fnv(file, iov, count, &file->f_pos); - goto out; - } - - /* Do it by hand, with file-ops */ - ivp = iov; - while (count > 0) { - void * base; - int len, nr; - - base = ivp->iov_base; - len = ivp->iov_len; - ivp++; - count--; - - nr = fn(file, base, len, &file->f_pos); - - if (nr < 0) { - if (!retval) - retval = nr; - break; - } - retval += nr; - if (nr != len) - break; - } -out: - if (iov != iovstack) - kfree(iov); - if ((retval + (type == READ)) > 0) - dnotify_parent(file->f_dentry, - (type == READ) ? DN_ACCESS : DN_MODIFY); - - return retval; -} - -asmlinkage long sys32_readv(int fd, struct compat_iovec *vector, u32 count) -{ - struct file *file; - int ret = -EBADF; - - file = fget(fd); - if (!file || !(file->f_mode & FMODE_READ)) - goto out; - - ret = -EINVAL; - if (!file->f_op || (!file->f_op->readv && !file->f_op->read)) - goto out; - - ret = do_readv_writev32(READ, file, vector, count); - -out: - if (file) - fput(file); - return ret; -} - -asmlinkage long sys32_writev(int fd, struct compat_iovec *vector, u32 count) -{ - struct file *file; - int ret = -EBADF; - - file = fget(fd); - if (!file || !(file->f_mode & FMODE_WRITE)) - goto out; - - ret = -EINVAL; - if (!file->f_op || (!file->f_op->writev && !file->f_op->write)) - goto out; - - ret = do_readv_writev32(WRITE, file, vector, count); - -out: - if (file) - fput(file); - return ret; -} - /* readdir & getdents */ #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) #define ROUND_UP(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1)) @@ -398,167 +225,12 @@ out: return error; } -/* - * Ooo, nasty. We need here to frob 32-bit unsigned longs to - * 64-bit unsigned longs. - */ -static inline int -get_fd_set32(unsigned long n, unsigned long *fdset, u32 *ufdset) -{ - if (ufdset) { - unsigned long odd; - - if (verify_area(VERIFY_WRITE, ufdset, n*sizeof(u32))) - return -EFAULT; - - odd = n & 1UL; - n &= ~1UL; - while (n) { - unsigned long h, l; - __get_user(l, ufdset); - __get_user(h, ufdset+1); - ufdset += 2; - *fdset++ = h << 32 | l; - n -= 2; - } - if (odd) - __get_user(*fdset, ufdset); - } else { - /* Tricky, must clear full unsigned long in the - * kernel fdset at the end, this makes sure that - * actually happens. - */ - memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32)); - } - return 0; -} - -static inline void -set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset) -{ - unsigned long odd; - - if (!ufdset) - return; - - odd = n & 1UL; - n &= ~1UL; - while (n) { - unsigned long h, l; - l = *fdset++; - h = l >> 32; - __put_user(l, ufdset); - __put_user(h, ufdset+1); - ufdset += 2; - n -= 2; - } - if (odd) - __put_user(*fdset, ufdset); -} - - - -#define MAX_SELECT_SECONDS ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1) - -asmlinkage long sys32_select(int n, u32 *inp, u32 *outp, u32 *exp, u32 tvp_x) -{ - fd_set_bits fds; - struct compat_timeval *tvp = (struct compat_timeval *)AA(tvp_x); - char *bits; - unsigned long nn; - long timeout; - int ret, size, max_fdset; - - timeout = MAX_SCHEDULE_TIMEOUT; - if (tvp) { - time_t sec, usec; - if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp))) - || (ret = __get_user(sec, &tvp->tv_sec)) - || (ret = __get_user(usec, &tvp->tv_usec))) - goto out_nofds; - - ret = -EINVAL; - if(sec < 0 || usec < 0) - goto out_nofds; - - if ((unsigned long) sec < MAX_SELECT_SECONDS) { - timeout = (usec + 1000000/HZ - 1) / (1000000/HZ); - timeout += sec * (unsigned long) HZ; - } - } - - ret = -EINVAL; - if (n < 0) - goto out_nofds; - - /* max_fdset can increase, so grab it once to avoid race */ - max_fdset = current->files->max_fdset; - if (n > max_fdset) - n = max_fdset; - - /* - * We need 6 bitmaps (in/out/ex for both incoming and outgoing), - * since we used fdset we need to allocate memory in units of - * long-words. - */ - ret = -ENOMEM; - size = FDS_BYTES(n); - bits = kmalloc(6 * size, GFP_KERNEL); - if (!bits) - goto out_nofds; - fds.in = (unsigned long *) bits; - fds.out = (unsigned long *) (bits + size); - fds.ex = (unsigned long *) (bits + 2*size); - fds.res_in = (unsigned long *) (bits + 3*size); - fds.res_out = (unsigned long *) (bits + 4*size); - fds.res_ex = (unsigned long *) (bits + 5*size); - - nn = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32)); - if ((ret = get_fd_set32(nn, fds.in, inp)) || - (ret = get_fd_set32(nn, fds.out, outp)) || - (ret = get_fd_set32(nn, fds.ex, exp))) - goto out; - zero_fd_set(n, fds.res_in); - zero_fd_set(n, fds.res_out); - zero_fd_set(n, fds.res_ex); - - ret = do_select(n, &fds, &timeout); - - if (tvp && !(current->personality & STICKY_TIMEOUTS)) { - time_t sec = 0, usec = 0; - if (timeout) { - sec = timeout / HZ; - usec = timeout % HZ; - usec *= (1000000/HZ); - } - put_user(sec, &tvp->tv_sec); - put_user(usec, &tvp->tv_usec); - } - - if (ret < 0) - goto out; - if (!ret) { - ret = -ERESTARTNOHAND; - if (signal_pending(current)) - goto out; - ret = 0; - } - - set_fd_set32(nn, inp, fds.res_in); - set_fd_set32(nn, outp, fds.res_out); - set_fd_set32(nn, exp, fds.res_ex); - -out: - kfree(bits); - -out_nofds: - return ret; -} - -int ppc32_select(u32 n, u32* inp, u32* outp, u32* exp, u32 tvp_x) +asmlinkage long ppc32_select(u32 n, compat_ulong_t __user *inp, + compat_ulong_t __user *outp, compat_ulong_t __user *exp, + compat_uptr_t tvp_x) { /* sign extend n */ - return sys32_select((int)n, inp, outp, exp, tvp_x); + return compat_sys_select((int)n, inp, outp, exp, compat_ptr(tvp_x)); } int cp_compat_stat(struct kstat *stat, struct compat_stat *statbuf) @@ -678,245 +350,6 @@ asmlinkage long sys32_adjtimex(struct ti return ret; } -/* Stuff for NFS server syscalls... */ -struct nfsctl_svc32 { - u16 svc32_port; - s32 svc32_nthreads; -}; - -struct nfsctl_client32 { - s8 cl32_ident[NFSCLNT_IDMAX+1]; - s32 cl32_naddr; - struct in_addr cl32_addrlist[NFSCLNT_ADDRMAX]; - s32 cl32_fhkeytype; - s32 cl32_fhkeylen; - u8 cl32_fhkey[NFSCLNT_KEYMAX]; -}; - -struct nfsctl_export32 { - s8 ex32_client[NFSCLNT_IDMAX+1]; - s8 ex32_path[NFS_MAXPATHLEN+1]; - compat_dev_t ex32_dev; - compat_ino_t ex32_ino; - s32 ex32_flags; - compat_uid_t ex32_anon_uid; - compat_gid_t ex32_anon_gid; -}; - -struct nfsctl_fdparm32 { - struct sockaddr gd32_addr; - s8 gd32_path[NFS_MAXPATHLEN+1]; - s32 gd32_version; -}; - -struct nfsctl_fsparm32 { - struct sockaddr gd32_addr; - s8 gd32_path[NFS_MAXPATHLEN+1]; - s32 gd32_maxlen; -}; - -struct nfsctl_arg32 { - s32 ca32_version; /* safeguard */ - union { - struct nfsctl_svc32 u32_svc; - struct nfsctl_client32 u32_client; - struct nfsctl_export32 u32_export; - struct nfsctl_fdparm32 u32_getfd; - struct nfsctl_fsparm32 u32_getfs; - } u; -#define ca32_svc u.u32_svc -#define ca32_client u.u32_client -#define ca32_export u.u32_export -#define ca32_getfd u.u32_getfd -#define ca32_getfs u.u32_getfs -}; - -union nfsctl_res32 { - __u8 cr32_getfh[NFS_FHSIZE]; - struct knfsd_fh cr32_getfs; -}; - -static int nfs_svc32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) -{ - int err; - - err = __get_user(karg->ca_version, &arg32->ca32_version); - err |= __get_user(karg->ca_svc.svc_port, &arg32->ca32_svc.svc32_port); - err |= __get_user(karg->ca_svc.svc_nthreads, &arg32->ca32_svc.svc32_nthreads); - return err; -} - -static int nfs_clnt32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) -{ - int err; - - err = __get_user(karg->ca_version, &arg32->ca32_version); - err |= copy_from_user(&karg->ca_client.cl_ident[0], - &arg32->ca32_client.cl32_ident[0], - NFSCLNT_IDMAX); - err |= __get_user(karg->ca_client.cl_naddr, &arg32->ca32_client.cl32_naddr); - err |= copy_from_user(&karg->ca_client.cl_addrlist[0], - &arg32->ca32_client.cl32_addrlist[0], - (sizeof(struct in_addr) * NFSCLNT_ADDRMAX)); - err |= __get_user(karg->ca_client.cl_fhkeytype, - &arg32->ca32_client.cl32_fhkeytype); - err |= __get_user(karg->ca_client.cl_fhkeylen, - &arg32->ca32_client.cl32_fhkeylen); - err |= copy_from_user(&karg->ca_client.cl_fhkey[0], - &arg32->ca32_client.cl32_fhkey[0], - NFSCLNT_KEYMAX); - - if(err) return -EFAULT; - return 0; -} - -static int nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) -{ - int err; - - err = __get_user(karg->ca_version, &arg32->ca32_version); - err |= copy_from_user(&karg->ca_export.ex_client[0], - &arg32->ca32_export.ex32_client[0], - NFSCLNT_IDMAX); - err |= copy_from_user(&karg->ca_export.ex_path[0], - &arg32->ca32_export.ex32_path[0], - NFS_MAXPATHLEN); - err |= __get_user(karg->ca_export.ex_dev, - &arg32->ca32_export.ex32_dev); - err |= __get_user(karg->ca_export.ex_ino, - &arg32->ca32_export.ex32_ino); - err |= __get_user(karg->ca_export.ex_flags, - &arg32->ca32_export.ex32_flags); - err |= __get_user(karg->ca_export.ex_anon_uid, - &arg32->ca32_export.ex32_anon_uid); - err |= __get_user(karg->ca_export.ex_anon_gid, - &arg32->ca32_export.ex32_anon_gid); - karg->ca_export.ex_anon_uid = karg->ca_export.ex_anon_uid; - karg->ca_export.ex_anon_gid = karg->ca_export.ex_anon_gid; - - if(err) return -EFAULT; - return 0; -} - -static int nfs_getfd32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) -{ - int err; - - err = __get_user(karg->ca_version, &arg32->ca32_version); - err |= copy_from_user(&karg->ca_getfd.gd_addr, - &arg32->ca32_getfd.gd32_addr, - (sizeof(struct sockaddr))); - err |= copy_from_user(&karg->ca_getfd.gd_path, - &arg32->ca32_getfd.gd32_path, - (NFS_MAXPATHLEN+1)); - err |= __get_user(karg->ca_getfd.gd_version, - &arg32->ca32_getfd.gd32_version); - - if(err) return -EFAULT; - return 0; -} - -static int nfs_getfs32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) -{ - int err; - - err = __get_user(karg->ca_version, &arg32->ca32_version); - err |= copy_from_user(&karg->ca_getfs.gd_addr, - &arg32->ca32_getfs.gd32_addr, - (sizeof(struct sockaddr))); - err |= copy_from_user(&karg->ca_getfs.gd_path, - &arg32->ca32_getfs.gd32_path, - (NFS_MAXPATHLEN+1)); - err |= __get_user(karg->ca_getfs.gd_maxlen, - &arg32->ca32_getfs.gd32_maxlen); - - if(err) return -EFAULT; - return 0; -} - -/* This really doesn't need translations, we are only passing - * back a union which contains opaque nfs file handle data. - */ -static int nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32) -{ - int err; - - err = copy_to_user(res32, kres, sizeof(*res32)); - - if(err) return -EFAULT; - return 0; -} - -/* Note: it is necessary to treat cmd_parm 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) - * and the register representation of a signed int (msr in 64-bit mode) is performed. - */ -int asmlinkage sys32_nfsservctl(u32 cmd_parm, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32) -{ - int cmd = (int)cmd_parm; - struct nfsctl_arg *karg = NULL; - union nfsctl_res *kres = NULL; - mm_segment_t oldfs; - int err; - - karg = kmalloc(sizeof(*karg), GFP_USER); - if(!karg) - return -ENOMEM; - if(res32) { - kres = kmalloc(sizeof(*kres), GFP_USER); - if(!kres) { - kfree(karg); - return -ENOMEM; - } - } - switch(cmd) { - case NFSCTL_SVC: - err = nfs_svc32_trans(karg, arg32); - break; - case NFSCTL_ADDCLIENT: - err = nfs_clnt32_trans(karg, arg32); - break; - case NFSCTL_DELCLIENT: - err = nfs_clnt32_trans(karg, arg32); - break; - case NFSCTL_EXPORT: - case NFSCTL_UNEXPORT: - err = nfs_exp32_trans(karg, arg32); - break; - case NFSCTL_GETFD: - err = nfs_getfd32_trans(karg, arg32); - break; - case NFSCTL_GETFS: - err = nfs_getfs32_trans(karg, arg32); - break; - default: - err = -EINVAL; - break; - } - if(err) - goto done; - oldfs = get_fs(); - set_fs(KERNEL_DS); - err = sys_nfsservctl(cmd, karg, kres); - set_fs(oldfs); - - if (err) - goto done; - - if((cmd == NFSCTL_GETFD) || - (cmd == NFSCTL_GETFS)) - err = nfs_getfh32_res_trans(kres, res32); - -done: - if(karg) - kfree(karg); - if(kres) - kfree(kres); - return err; -} - - /* These are here just in case some old sparc32 binary calls it. */ asmlinkage long sys32_pause(void) @@ -1057,625 +490,69 @@ asmlinkage long sys32_settimeofday(struc return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); } - -struct msgbuf32 { - compat_long_t mtype; - char mtext[1]; -}; - -struct semid_ds32 { - struct ipc_perm sem_perm; - compat_time_t sem_otime; - compat_time_t sem_ctime; - compat_uptr_t sem_base; - compat_uptr_t sem_pending; - compat_uptr_t sem_pending_last; - compat_uptr_t undo; - unsigned short sem_nsems; -}; - -struct semid64_ds32 { - struct ipc64_perm sem_perm; - unsigned int __unused1; - compat_time_t sem_otime; - unsigned int __unused2; - compat_time_t sem_ctime; - compat_ulong_t sem_nsems; - compat_ulong_t __unused3; - compat_ulong_t __unused4; -}; - -struct msqid_ds32 { - struct ipc_perm msg_perm; - compat_uptr_t msg_first; - compat_uptr_t msg_last; - compat_time_t msg_stime; - compat_time_t msg_rtime; - compat_time_t msg_ctime; - compat_ulong_t msg_lcbytes; - compat_ulong_t msg_lqbytes; - unsigned short msg_cbytes; - unsigned short msg_qnum; - unsigned short msg_qbytes; - compat_ipc_pid_t msg_lspid; - compat_ipc_pid_t msg_lrpid; -}; - -struct msqid64_ds32 { - struct ipc64_perm msg_perm; - unsigned int __unused1; - compat_time_t msg_stime; - unsigned int __unused2; - compat_time_t msg_rtime; - unsigned int __unused3; - compat_time_t msg_ctime; - compat_ulong_t msg_cbytes; - compat_ulong_t msg_qnum; - compat_ulong_t msg_qbytes; - compat_pid_t msg_lspid; - compat_pid_t msg_lrpid; - compat_ulong_t __unused4; - compat_ulong_t __unused5; -}; - -struct shmid_ds32 { - struct ipc_perm shm_perm; - int shm_segsz; - compat_time_t shm_atime; - compat_time_t shm_dtime; - compat_time_t shm_ctime; - compat_ipc_pid_t shm_cpid; - compat_ipc_pid_t shm_lpid; - unsigned short shm_nattch; - unsigned short __unused; - compat_uptr_t __unused2; - compat_uptr_t __unused3; -}; - -struct shmid64_ds32 { - struct ipc64_perm shm_perm; - unsigned int __unused1; - compat_time_t shm_atime; - unsigned int __unused2; - compat_time_t shm_dtime; - unsigned int __unused3; - compat_time_t shm_ctime; - unsigned int __unused4; - compat_size_t shm_segsz; - compat_pid_t shm_cpid; - compat_pid_t shm_lpid; - compat_ulong_t shm_nattch; - compat_ulong_t __unused5; - compat_ulong_t __unused6; -}; - -/* - * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit - * emulation.. - * - * This is really horribly ugly. - */ -static long do_sys32_semctl(int first, int second, int third, void *uptr) -{ - union semun fourth; - u32 pad; - int err, err2; - mm_segment_t old_fs; - - if (!uptr) - return -EINVAL; - err = -EFAULT; - if (get_user(pad, (u32 *)uptr)) - return err; - if ((third & ~IPC_64) == SETVAL) - fourth.val = (int)pad; - else - fourth.__pad = (void *)A(pad); - switch (third & (~IPC_64)) { - - case IPC_INFO: - case IPC_RMID: - case SEM_INFO: - case GETVAL: - case GETPID: - case GETNCNT: - case GETZCNT: - case GETALL: - case SETALL: - case SETVAL: - err = sys_semctl(first, second, third, fourth); - break; - - case IPC_STAT: - case SEM_STAT: - if (third & IPC_64) { - struct semid64_ds s64; - struct semid64_ds32 *usp; - - usp = (struct semid64_ds32 *)A(pad); - fourth.__pad = &s64; - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_semctl(first, second, third, fourth); - set_fs(old_fs); - err2 = copy_to_user(&usp->sem_perm, &s64.sem_perm, - sizeof(struct ipc64_perm)); - err2 |= __put_user(s64.sem_otime, &usp->sem_otime); - err2 |= __put_user(s64.sem_ctime, &usp->sem_ctime); - err2 |= __put_user(s64.sem_nsems, &usp->sem_nsems); - if (err2) - err = -EFAULT; - } else { - struct semid_ds s; - struct semid_ds32 *usp; - - usp = (struct semid_ds32 *)A(pad); - fourth.__pad = &s; - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_semctl(first, second, third, fourth); - set_fs(old_fs); - err2 = copy_to_user(&usp->sem_perm, &s.sem_perm, - sizeof(struct ipc_perm)); - err2 |= __put_user(s.sem_otime, &usp->sem_otime); - err2 |= __put_user(s.sem_ctime, &usp->sem_ctime); - err2 |= __put_user(s.sem_nsems, &usp->sem_nsems); - if (err2) - err = -EFAULT; - } - break; - - case IPC_SET: - if (third & IPC_64) { - struct semid64_ds s64; - struct semid64_ds32 *usp; - - usp = (struct semid64_ds32 *)A(pad); - - err = get_user(s64.sem_perm.uid, &usp->sem_perm.uid); - err |= __get_user(s64.sem_perm.gid, - &usp->sem_perm.gid); - err |= __get_user(s64.sem_perm.mode, - &usp->sem_perm.mode); - if (err) - goto out; - fourth.__pad = &s64; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_semctl(first, second, third, fourth); - set_fs(old_fs); - - } else { - struct semid_ds s; - struct semid_ds32 *usp; - - usp = (struct semid_ds32 *)A(pad); - - err = get_user(s.sem_perm.uid, &usp->sem_perm.uid); - err |= __get_user(s.sem_perm.gid, - &usp->sem_perm.gid); - err |= __get_user(s.sem_perm.mode, - &usp->sem_perm.mode); - if (err) - goto out; - fourth.__pad = &s; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_semctl(first, second, third, fourth); - set_fs(old_fs); - } - break; - default: - err = -EINVAL; - } -out: - return err; -} - -#define MAXBUF (64*1024) - -static int -do_sys32_msgsnd(int first, int second, int third, void *uptr) -{ - struct msgbuf *p; - struct msgbuf32 *up = (struct msgbuf32 *)uptr; - mm_segment_t old_fs; - int err; - - if (second < 0 || (second >= MAXBUF-sizeof(struct msgbuf))) - return -EINVAL; - - p = kmalloc(second + sizeof(struct msgbuf), GFP_USER); - if (!p) - return -ENOMEM; - err = get_user(p->mtype, &up->mtype); - err |= copy_from_user(p->mtext, &up->mtext, second); - if (err) { - err = -EFAULT; - goto out; - } - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_msgsnd(first, p, second, third); - set_fs(old_fs); -out: - kfree(p); - return err; -} - -static int -do_sys32_msgrcv(int first, int second, int msgtyp, int third, - int version, void *uptr) +long sys32_ipc(u32 call, u32 first, u32 second, u32 third, compat_uptr_t ptr, + u32 fifth) { - struct msgbuf32 *up; - struct msgbuf *p; - mm_segment_t old_fs; - int err; - - if (second < 0 || (second >= MAXBUF-sizeof(struct msgbuf))) - return -EINVAL; - - if (!version) { - struct ipc_kludge_32 *uipck = (struct ipc_kludge_32 *)uptr; - struct ipc_kludge_32 ipck; - - err = -EINVAL; - if (!uptr) - goto out; - err = -EFAULT; - if (copy_from_user(&ipck, uipck, sizeof(struct ipc_kludge_32))) - goto out; - uptr = (void *)A(ipck.msgp); - msgtyp = ipck.msgtyp; - } - err = -ENOMEM; - p = kmalloc(second + sizeof (struct msgbuf), GFP_USER); - if (!p) - goto out; - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_msgrcv(first, p, second, msgtyp, third); - set_fs(old_fs); - if (err < 0) - goto free_then_out; - up = (struct msgbuf32 *)uptr; - if (put_user(p->mtype, &up->mtype) || - copy_to_user(&up->mtext, p->mtext, err)) - err = -EFAULT; -free_then_out: - kfree(p); -out: - return err; -} - -static int -do_sys32_msgctl(int first, int second, void *uptr) -{ - int err = -EINVAL, err2; - mm_segment_t old_fs; - - switch (second & (~IPC_64)) { - - case IPC_INFO: - case IPC_RMID: - case MSG_INFO: - err = sys_msgctl(first, second, (struct msqid_ds *)uptr); - break; - - case IPC_SET: - if (second & IPC_64) { - struct msqid64_ds m64; - struct msqid64_ds32 *up = (struct msqid64_ds32 *)uptr; - - err2 = copy_from_user(&m64.msg_perm, &up->msg_perm, - sizeof(struct ipc64_perm)); - err2 |= __get_user(m64.msg_qbytes, &up->msg_qbytes); - if (err2) { - err = -EFAULT; - break; - } - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_msgctl(first, second, - (struct msqid_ds *)&m64); - set_fs(old_fs); - } else { - struct msqid_ds m; - struct msqid_ds32 *up = (struct msqid_ds32 *)uptr; - - err2 = copy_from_user(&m.msg_perm, &up->msg_perm, - sizeof(struct ipc_perm)); - err2 |= __get_user(m.msg_qbytes, &up->msg_qbytes); - if (err2) { - err = -EFAULT; - break; - } - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_msgctl(first, second, &m); - set_fs(old_fs); - } - break; - - case IPC_STAT: - case MSG_STAT: - if (second & IPC_64) { - struct msqid64_ds m64; - struct msqid64_ds32 *up = (struct msqid64_ds32 *)uptr; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_msgctl(first, second, - (struct msqid_ds *)&m64); - set_fs(old_fs); - - err2 = copy_to_user(&up->msg_perm, &m64.msg_perm, - sizeof(struct ipc64_perm)); - err2 |= __put_user(m64.msg_stime, &up->msg_stime); - err2 |= __put_user(m64.msg_rtime, &up->msg_rtime); - err2 |= __put_user(m64.msg_ctime, &up->msg_ctime); - err2 |= __put_user(m64.msg_cbytes, &up->msg_cbytes); - err2 |= __put_user(m64.msg_qnum, &up->msg_qnum); - err2 |= __put_user(m64.msg_qbytes, &up->msg_qbytes); - err2 |= __put_user(m64.msg_lspid, &up->msg_lspid); - err2 |= __put_user(m64.msg_lrpid, &up->msg_lrpid); - if (err2) - err = -EFAULT; - } else { - struct msqid64_ds m; - struct msqid_ds32 *up = (struct msqid_ds32 *)uptr; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_msgctl(first, second, (struct msqid_ds *)&m); - set_fs(old_fs); - - err2 = copy_to_user(&up->msg_perm, &m.msg_perm, - sizeof(struct ipc_perm)); - err2 |= __put_user(m.msg_stime, &up->msg_stime); - err2 |= __put_user(m.msg_rtime, &up->msg_rtime); - err2 |= __put_user(m.msg_ctime, &up->msg_ctime); - err2 |= __put_user(m.msg_cbytes, &up->msg_cbytes); - err2 |= __put_user(m.msg_qnum, &up->msg_qnum); - err2 |= __put_user(m.msg_qbytes, &up->msg_qbytes); - err2 |= __put_user(m.msg_lspid, &up->msg_lspid); - err2 |= __put_user(m.msg_lrpid, &up->msg_lrpid); - if (err2) - err = -EFAULT; - } - break; - } - return err; -} + int version; -static int -do_sys32_shmat(int first, int second, int third, int version, void *uptr) -{ - unsigned long raddr; - u32 *uaddr = (u32 *)A((u32)third); - int err = -EINVAL; - - if (version == 1) - return err; - err = do_shmat(first, uptr, second, &raddr); - if (err) - return err; - err = put_user(raddr, uaddr); - return err; -} - -static int -do_sys32_shmctl(int first, int second, void *uptr) -{ - int err = -EINVAL, err2; - mm_segment_t old_fs; - - switch (second & (~IPC_64)) { - - case IPC_INFO: - case IPC_RMID: - case SHM_LOCK: - case SHM_UNLOCK: - err = sys_shmctl(first, second, (struct shmid_ds *)uptr); - break; - case IPC_SET: - if (second & IPC_64) { - struct shmid64_ds32 *up = (struct shmid64_ds32 *)uptr; - struct shmid64_ds s64; - - err = get_user(s64.shm_perm.uid, &up->shm_perm.uid); - err |= __get_user(s64.shm_perm.gid, &up->shm_perm.gid); - err |= __get_user(s64.shm_perm.mode, - &up->shm_perm.mode); - if (err) - break; - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_shmctl(first, second, - (struct shmid_ds *)&s64); - set_fs(old_fs); - } else { - struct shmid_ds32 *up = (struct shmid_ds32 *)uptr; - struct shmid_ds s; - - err = get_user(s.shm_perm.uid, &up->shm_perm.uid); - err |= __get_user(s.shm_perm.gid, &up->shm_perm.gid); - err |= __get_user(s.shm_perm.mode, &up->shm_perm.mode); - if (err) - break; - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_shmctl(first, second, &s); - set_fs(old_fs); - } - break; - - case IPC_STAT: - case SHM_STAT: - if (second & IPC_64) { - struct shmid64_ds32 *up = (struct shmid64_ds32 *)uptr; - struct shmid64_ds s64; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_shmctl(first, second, - (struct shmid_ds *)&s64); - set_fs(old_fs); - if (err < 0) - break; - - err2 = copy_to_user(&up->shm_perm, &s64.shm_perm, - sizeof(struct ipc64_perm)); - err2 |= __put_user(s64.shm_atime, &up->shm_atime); - err2 |= __put_user(s64.shm_dtime, &up->shm_dtime); - err2 |= __put_user(s64.shm_ctime, &up->shm_ctime); - err2 |= __put_user(s64.shm_segsz, &up->shm_segsz); - err2 |= __put_user(s64.shm_nattch, &up->shm_nattch); - err2 |= __put_user(s64.shm_cpid, &up->shm_cpid); - err2 |= __put_user(s64.shm_lpid, &up->shm_lpid); - if (err2) - err = -EFAULT; - } else { - struct shmid_ds32 *up = (struct shmid_ds32 *)uptr; - struct shmid_ds s; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_shmctl(first, second, &s); - set_fs(old_fs); - if (err < 0) - break; - - err2 = copy_to_user(&up->shm_perm, &s.shm_perm, - sizeof(struct ipc_perm)); - err2 |= __put_user (s.shm_atime, &up->shm_atime); - err2 |= __put_user (s.shm_dtime, &up->shm_dtime); - err2 |= __put_user (s.shm_ctime, &up->shm_ctime); - err2 |= __put_user (s.shm_segsz, &up->shm_segsz); - err2 |= __put_user (s.shm_nattch, &up->shm_nattch); - err2 |= __put_user (s.shm_cpid, &up->shm_cpid); - err2 |= __put_user (s.shm_lpid, &up->shm_lpid); - if (err2) - err = -EFAULT; - } - break; - - case SHM_INFO: { - struct shm_info si; - struct shm_info32 { - int used_ids; - u32 shm_tot, shm_rss, shm_swp; - u32 swap_attempts, swap_successes; - } *uip = (struct shm_info32 *)uptr; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_shmctl(first, second, (struct shmid_ds *)&si); - set_fs(old_fs); - if (err < 0) - break; - err2 = put_user(si.used_ids, &uip->used_ids); - err2 |= __put_user(si.shm_tot, &uip->shm_tot); - err2 |= __put_user(si.shm_rss, &uip->shm_rss); - err2 |= __put_user(si.shm_swp, &uip->shm_swp); - err2 |= __put_user(si.swap_attempts, &uip->swap_attempts); - err2 |= __put_user(si.swap_successes, &uip->swap_successes); - if (err2) - err = -EFAULT; - break; - } - } - return err; -} - -static int sys32_semtimedop(int semid, struct sembuf *tsems, int nsems, - const struct compat_timespec *timeout32) -{ - struct compat_timespec t32; - struct timespec *t64 = compat_alloc_user_space(sizeof(*t64)); - - if (copy_from_user(&t32, timeout32, sizeof(t32))) - return -EFAULT; - - if (put_user(t32.tv_sec, &t64->tv_sec) || - put_user(t32.tv_nsec, &t64->tv_nsec)) - return -EFAULT; - - return sys_semtimedop(semid, tsems, nsems, t64); -} - -/* - * Note: it is necessary to treat first_parm, second_parm, and - * third_parm 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_ipc(u32 call, u32 first_parm, u32 second_parm, u32 third_parm, u32 ptr, u32 fifth) -{ - int first = (int)first_parm; - int second = (int)second_parm; - int third = (int)third_parm; - int version, err; - version = call >> 16; /* hack for backward compatibility */ call &= 0xffff; switch (call) { + case SEMTIMEDOP: + if (third) + /* sign extend semid */ + return compat_sys_semtimedop((int)first, + compat_ptr(ptr), second, + compat_ptr(third)); + /* else fall through for normal semop() */ case SEMOP: /* struct sembuf is the same on 32 and 64bit :)) */ - err = sys_semtimedop(first, (struct sembuf *)AA(ptr), - second, NULL); - break; - case SEMTIMEDOP: - err = sys32_semtimedop(first, (struct sembuf *)AA(ptr), second, - (const struct compat_timespec *)AA(fifth)); - break; + /* sign extend semid */ + return sys_semtimedop((int)first, compat_ptr(ptr), second, + NULL); case SEMGET: - err = sys_semget(first, second, third); - break; + /* sign extend key, nsems */ + return sys_semget((int)first, (int)second, third); case SEMCTL: - err = do_sys32_semctl(first, second, third, - (void *)AA(ptr)); - break; + /* sign extend semid, semnum */ + return compat_sys_semctl((int)first, (int)second, third, + compat_ptr(ptr)); case MSGSND: - err = do_sys32_msgsnd(first, second, third, - (void *)AA(ptr)); - break; + /* sign extend msqid */ + return compat_sys_msgsnd((int)first, (int)second, third, + compat_ptr(ptr)); case MSGRCV: - err = do_sys32_msgrcv(first, second, fifth, third, - version, (void *)AA(ptr)); - break; + /* sign extend msqid, msgtyp */ + return compat_sys_msgrcv((int)first, second, (int)fifth, + third, version, compat_ptr(ptr)); case MSGGET: - err = sys_msgget((key_t)first, second); - break; + /* sign extend key */ + return sys_msgget((int)first, second); case MSGCTL: - err = do_sys32_msgctl(first, second, (void *)AA(ptr)); - break; + /* sign extend msqid */ + return compat_sys_msgctl((int)first, second, compat_ptr(ptr)); case SHMAT: - err = do_sys32_shmat(first, second, third, - version, (void *)AA(ptr)); - break; - case SHMDT: - err = sys_shmdt((char *)AA(ptr)); - break; + /* sign extend shmid */ + return compat_sys_shmat((int)first, second, third, version, + compat_ptr(ptr)); + case SHMDT: + return sys_shmdt(compat_ptr(ptr)); case SHMGET: - err = sys_shmget(first, second_parm, third); - break; + /* sign extend key_t */ + return sys_shmget((int)first, second, third); case SHMCTL: - err = do_sys32_shmctl(first, second, (void *)AA(ptr)); - break; + /* sign extend shmid */ + return compat_sys_shmctl((int)first, second, compat_ptr(ptr)); + default: - err = -ENOSYS; - break; + return -ENOSYS; } - return err; + + return -ENOSYS; } /* Note: it is necessary to treat out_fd and in_fd as unsigned ints, @@ -1721,191 +598,6 @@ asmlinkage int sys32_sendfile64(int out_ return ret; } -/* - * count32() counts the number of arguments/envelopes - */ -static int count32(u32 * argv, int max) -{ - int i = 0; - - if (argv != NULL) { - for (;;) { - u32 p; int error; - - error = get_user(p,argv); - if (error) - return error; - if (!p) - break; - argv++; - if (++i > max) - return -E2BIG; - } - } - return i; -} - -/* - * 'copy_string32()' copies argument/envelope strings from user - * memory to free pages in kernel mem. These are in a format ready - * to be put directly into the top of new user memory. - */ -static int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm) -{ - while (argc-- > 0) { - u32 str; - int len; - unsigned long pos; - - if (get_user(str, argv + argc) || - !str || - !(len = strnlen_user((char *)A(str), bprm->p))) - return -EFAULT; - - if (bprm->p < len) - return -E2BIG; - - bprm->p -= len; - - pos = bprm->p; - while (len) { - char *kaddr; - struct page *page; - int offset, bytes_to_copy, new, err; - - offset = pos % PAGE_SIZE; - page = bprm->page[pos / PAGE_SIZE]; - new = 0; - if (!page) { - page = alloc_page(GFP_USER); - bprm->page[pos / PAGE_SIZE] = page; - if (!page) - return -ENOMEM; - new = 1; - } - kaddr = (char *)kmap(page); - - if (new && offset) - memset(kaddr, 0, offset); - bytes_to_copy = PAGE_SIZE - offset; - if (bytes_to_copy > len) { - bytes_to_copy = len; - if (new) - memset(kaddr+offset+len, 0, - PAGE_SIZE-offset-len); - } - - err = copy_from_user(kaddr + offset, (char *)A(str), - bytes_to_copy); - kunmap((unsigned long)kaddr); - - if (err) - return -EFAULT; - - pos += bytes_to_copy; - str += bytes_to_copy; - len -= bytes_to_copy; - } - } - return 0; -} - -/* - * sys32_execve() executes a new program. - */ -static int do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs) -{ - struct linux_binprm bprm; - struct file * file; - int retval; - int i; - - sched_balance_exec(); - - file = open_exec(filename); - - retval = PTR_ERR(file); - if (IS_ERR(file)) - return retval; - - bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); - memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0])); - - bprm.file = file; - bprm.filename = filename; - bprm.interp = filename; - bprm.sh_bang = 0; - bprm.loader = 0; - bprm.exec = 0; - bprm.security = NULL; - bprm.mm = mm_alloc(); - retval = -ENOMEM; - if (!bprm.mm) - goto out_file; - - retval = init_new_context(current, bprm.mm); - if (retval < 0) - goto out_mm; - - bprm.argc = count32(argv, bprm.p / sizeof(u32)); - if ((retval = bprm.argc) < 0) - goto out_mm; - - bprm.envc = count32(envp, bprm.p / sizeof(u32)); - if ((retval = bprm.envc) < 0) - goto out_mm; - - retval = security_bprm_alloc(&bprm); - if (retval) - goto out; - - retval = prepare_binprm(&bprm); - if (retval < 0) - goto out; - - retval = copy_strings_kernel(1, &bprm.filename, &bprm); - if (retval < 0) - goto out; - - bprm.exec = bprm.p; - retval = copy_strings32(bprm.envc, envp, &bprm); - if (retval < 0) - goto out; - - retval = copy_strings32(bprm.argc, argv, &bprm); - if (retval < 0) - goto out; - - retval = search_binary_handler(&bprm,regs); - if (retval >= 0) { - /* execve success */ - security_bprm_free(&bprm); - return retval; - } - -out: - /* Something went wrong, return the inode and free the argument pages*/ - for (i = 0 ; i < MAX_ARG_PAGES ; i++) { - struct page * page = bprm.page[i]; - if (page) - __free_page(page); - } - - if (bprm.security) - security_bprm_free(&bprm); - -out_mm: - if (bprm.mm) - mmdrop(bprm.mm); - -out_file: - if (bprm.file) { - allow_write_access(bprm.file); - fput(bprm.file); - } - return retval; -} - long sys32_execve(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3, unsigned long a4, unsigned long a5, struct pt_regs *regs) @@ -1924,7 +616,7 @@ long sys32_execve(unsigned long a0, unsi giveup_altivec(current); #endif /* CONFIG_ALTIVEC */ - error = do_execve32(filename, (u32*) a1, (u32*) a2, regs); + error = compat_do_execve(filename, compat_ptr(a1), compat_ptr(a2), regs); if (error == 0) current->ptrace &= ~PT_DTRACE; --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/arch/ppc64/lib/locks.c 2004-05-10 01:19:45.260858360 -0700 @@ -0,0 +1,285 @@ +/* + * Spin and read/write lock operations. + * + * Copyright (C) 2001-2004 Paul Mackerras , IBM + * Copyright (C) 2001 Anton Blanchard , IBM + * Copyright (C) 2002 Dave Engebretsen , IBM + * Rework to support virtual processors + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + +#ifndef CONFIG_SPINLINE + +/* + * On a system with shared processors (that is, where a physical + * processor is multiplexed between several virtual processors), + * there is no point spinning on a lock if the holder of the lock + * isn't currently scheduled on a physical processor. Instead + * we detect this situation and ask the hypervisor to give the + * rest of our timeslice to the lock holder. + * + * So that we can tell which virtual processor is holding a lock, + * we put 0x80000000 | smp_processor_id() in the lock when it is + * held. Conveniently, we have a word in the paca that holds this + * value. + */ + +/* waiting for a spinlock... */ +#if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES) +void __spin_yield(spinlock_t *lock) +{ + unsigned int lock_value, holder_cpu, yield_count; + struct paca_struct *holder_paca; + + lock_value = lock->lock; + if (lock_value == 0) + return; + holder_cpu = lock_value & 0xffff; + BUG_ON(holder_cpu >= NR_CPUS); + holder_paca = &paca[holder_cpu]; + yield_count = holder_paca->xLpPaca.xYieldCount; + if ((yield_count & 1) == 0) + return; /* virtual cpu is currently running */ + rmb(); + if (lock->lock != lock_value) + return; /* something has changed */ +#ifdef CONFIG_PPC_ISERIES + HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc, + ((u64)holder_cpu << 32) | yield_count); +#else + plpar_hcall_norets(H_CONFER, holder_cpu, yield_count); +#endif +} + +#else /* SPLPAR || ISERIES */ +#define __spin_yield(x) barrier() +#endif + +/* + * This returns the old value in the lock, so we succeeded + * in getting the lock if the return value is 0. + */ +static __inline__ unsigned long __spin_trylock(spinlock_t *lock) +{ + unsigned long tmp, tmp2; + + __asm__ __volatile__( +" lwz %1,24(13) # __spin_trylock\n\ +1: lwarx %0,0,%2\n\ + cmpwi 0,%0,0\n\ + bne- 2f\n\ + stwcx. %1,0,%2\n\ + bne- 1b\n\ + isync\n\ +2:" : "=&r" (tmp), "=&r" (tmp2) + : "r" (&lock->lock) + : "cr0", "memory"); + + return tmp; +} + +int _raw_spin_trylock(spinlock_t *lock) +{ + return __spin_trylock(lock) == 0; +} + +EXPORT_SYMBOL(_raw_spin_trylock); + +void _raw_spin_lock(spinlock_t *lock) +{ + while (1) { + if (likely(__spin_trylock(lock) == 0)) + break; + do { + HMT_low(); + __spin_yield(lock); + } while (likely(lock->lock != 0)); + HMT_medium(); + } +} + +EXPORT_SYMBOL(_raw_spin_lock); + +void _raw_spin_lock_flags(spinlock_t *lock, unsigned long flags) +{ + unsigned long flags_dis; + + while (1) { + if (likely(__spin_trylock(lock) == 0)) + break; + local_save_flags(flags_dis); + local_irq_restore(flags); + do { + HMT_low(); + __spin_yield(lock); + } while (likely(lock->lock != 0)); + HMT_medium(); + local_irq_restore(flags_dis); + } +} + +EXPORT_SYMBOL(_raw_spin_lock_flags); + +void spin_unlock_wait(spinlock_t *lock) +{ + while (lock->lock) + __spin_yield(lock); +} + +EXPORT_SYMBOL(spin_unlock_wait); + +/* + * Waiting for a read lock or a write lock on a rwlock... + * This turns out to be the same for read and write locks, since + * we only know the holder if it is write-locked. + */ +#if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES) +void __rw_yield(rwlock_t *rw) +{ + int lock_value; + unsigned int holder_cpu, yield_count; + struct paca_struct *holder_paca; + + lock_value = rw->lock; + if (lock_value >= 0) + return; /* no write lock at present */ + holder_cpu = lock_value & 0xffff; + BUG_ON(holder_cpu >= NR_CPUS); + holder_paca = &paca[holder_cpu]; + yield_count = holder_paca->xLpPaca.xYieldCount; + if ((yield_count & 1) == 0) + return; /* virtual cpu is currently running */ + rmb(); + if (rw->lock != lock_value) + return; /* something has changed */ +#ifdef CONFIG_PPC_ISERIES + HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc, + ((u64)holder_cpu << 32) | yield_count); +#else + plpar_hcall_norets(H_CONFER, holder_cpu, yield_count); +#endif +} + +#else /* SPLPAR || ISERIES */ +#define __rw_yield(x) barrier() +#endif + +/* + * This returns the old value in the lock + 1, + * so we got a read lock if the return value is > 0. + */ +static __inline__ long __read_trylock(rwlock_t *rw) +{ + long tmp; + + __asm__ __volatile__( +"1: lwarx %0,0,%1 # read_trylock\n\ + extsw %0,%0\n\ + addic. %0,%0,1\n\ + ble- 2f\n\ + stwcx. %0,0,%1\n\ + bne- 1b\n\ + isync\n\ +2:" : "=&r" (tmp) + : "r" (&rw->lock) + : "cr0", "xer", "memory"); + + return tmp; +} + +int _raw_read_trylock(rwlock_t *rw) +{ + return __read_trylock(rw) > 0; +} + +EXPORT_SYMBOL(_raw_read_trylock); + +void _raw_read_lock(rwlock_t *rw) +{ + while (1) { + if (likely(__read_trylock(rw) > 0)) + break; + do { + HMT_low(); + __rw_yield(rw); + } while (likely(rw->lock < 0)); + HMT_medium(); + } +} + +EXPORT_SYMBOL(_raw_read_lock); + +void _raw_read_unlock(rwlock_t *rw) +{ + long tmp; + + __asm__ __volatile__( + "eieio # read_unlock\n\ +1: lwarx %0,0,%1\n\ + addic %0,%0,-1\n\ + stwcx. %0,0,%1\n\ + bne- 1b" + : "=&r"(tmp) + : "r"(&rw->lock) + : "cr0", "memory"); +} + +EXPORT_SYMBOL(_raw_read_unlock); + +/* + * This returns the old value in the lock, + * so we got the write lock if the return value is 0. + */ +static __inline__ long __write_trylock(rwlock_t *rw) +{ + long tmp, tmp2; + + __asm__ __volatile__( +" lwz %1,24(13) # write_trylock\n\ +1: lwarx %0,0,%2\n\ + cmpwi 0,%0,0\n\ + bne- 2f\n\ + stwcx. %1,0,%2\n\ + bne- 1b\n\ + isync\n\ +2:" : "=&r" (tmp), "=&r" (tmp2) + : "r" (&rw->lock) + : "cr0", "memory"); + + return tmp; +} + +int _raw_write_trylock(rwlock_t *rw) +{ + return __write_trylock(rw) == 0; +} + +EXPORT_SYMBOL(_raw_write_trylock); + +void _raw_write_lock(rwlock_t *rw) +{ + while (1) { + if (likely(__write_trylock(rw) == 0)) + break; + do { + HMT_low(); + __rw_yield(rw); + } while (likely(rw->lock != 0)); + HMT_medium(); + } +} + +EXPORT_SYMBOL(_raw_write_lock); + +#endif /* CONFIG_SPINLINE */ --- linux-2.6.6/arch/ppc64/lib/Makefile 2003-06-14 12:17:55.000000000 -0700 +++ 25/arch/ppc64/lib/Makefile 2004-05-10 01:19:45.260858360 -0700 @@ -3,4 +3,4 @@ # lib-y := checksum.o dec_and_lock.o string.o strcase.o -lib-y += copypage.o memcpy.o copyuser.o +lib-y += copypage.o memcpy.o copyuser.o locks.o --- linux-2.6.6/arch/ppc64/mm/hugetlbpage.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/ppc64/mm/hugetlbpage.c 2004-05-10 01:19:56.317177544 -0700 @@ -24,7 +24,6 @@ #include #include #include -#include #include @@ -214,7 +213,7 @@ static int prepare_low_seg_for_htlb(stru } page = pmd_page(*pmd); pmd_clear(pmd); - pgtable_remove_rmap(page); + dec_page_state(nr_page_table_pages); pte_free_tlb(tlb, page); } tlb_finish_mmu(tlb, start, end); @@ -452,8 +451,9 @@ int hugetlb_prefault(struct address_spac goto out; } ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC); - unlock_page(page); - if (ret) { + if (! ret) { + unlock_page(page); + } else { hugetlb_put_quota(mapping); free_huge_page(page); goto out; --- linux-2.6.6/arch/ppc64/mm/tlb.c 2004-03-10 20:41:26.000000000 -0800 +++ 25/arch/ppc64/mm/tlb.c 2004-05-10 01:19:36.038260408 -0700 @@ -31,7 +31,6 @@ #include #include #include -#include DEFINE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch); @@ -42,6 +41,33 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_ga DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur); unsigned long pte_freelist_forced_free; +void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage) +{ + /* This is safe as we are holding page_table_lock */ + cpumask_t local_cpumask = cpumask_of_cpu(smp_processor_id()); + struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur); + + if (atomic_read(&tlb->mm->mm_users) < 2 || + cpus_equal(tlb->mm->cpu_vm_mask, local_cpumask)) { + pte_free(ptepage); + return; + } + + if (*batchp == NULL) { + *batchp = (struct pte_freelist_batch *)__get_free_page(GFP_ATOMIC); + if (*batchp == NULL) { + pte_free_now(ptepage); + return; + } + (*batchp)->index = 0; + } + (*batchp)->pages[(*batchp)->index++] = ptepage; + if ((*batchp)->index == PTE_FREELIST_SIZE) { + pte_free_submit(*batchp); + *batchp = NULL; + } +} + /* * Update the MMU hash table to correspond with a change to * a Linux PTE. If wrprot is true, it is permissible to @@ -59,7 +85,8 @@ void hpte_update(pte_t *ptep, unsigned l ptepage = virt_to_page(ptep); mm = (struct mm_struct *) ptepage->mapping; - addr = ptep_to_address(ptep); + addr = ptepage->index + + (((unsigned long)ptep & ~PAGE_MASK) * PTRS_PER_PTE); if (REGION_ID(addr) == USER_REGION_ID) context = mm->context.id; --- linux-2.6.6/arch/ppc/8xx_io/commproc.c 2003-06-14 12:18:22.000000000 -0700 +++ 25/arch/ppc/8xx_io/commproc.c 2004-05-10 01:19:36.800144584 -0700 @@ -33,6 +33,7 @@ #include #include #include +#include extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep); @@ -55,11 +56,10 @@ static void alloc_host_memory(void); #if 1 void -m8xx_cpm_reset() +m8xx_cpm_reset(void) { volatile immap_t *imp; volatile cpm8xx_t *commproc; - pte_t *pte; imp = (immap_t *)IMAP_ADDR; commproc = (cpm8xx_t *)&imp->im_cpm; --- linux-2.6.6/arch/ppc/Kconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/ppc/Kconfig 2004-05-10 01:19:24.523010992 -0700 @@ -1227,6 +1227,19 @@ config DEBUG_INFO debug the kernel. If you don't debug the kernel, you can say N. +config SCHEDSTATS + bool "Collect scheduler statistics" + depends on PROC_FS + default y + help + If you say Y here, additional code will be inserted into the + scheduler and related routines to collect statistics about + scheduler behavior and provide them in /proc/schedstat. These + stats may be useful for both tuning and debugging the scheduler + If you aren't debugging the scheduler or trying to tune a specific + application, you can say N to avoid the very slight overhead + this adds. + config BOOTX_TEXT bool "Support for early boot text console (BootX or OpenFirmware only)" depends PPC_OF --- linux-2.6.6/arch/ppc/kernel/misc.S 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/ppc/kernel/misc.S 2004-05-10 01:19:49.412227256 -0700 @@ -1105,10 +1105,6 @@ _GLOBAL(__main) _GLOBAL(name) \ li r0,__NR_##name; \ sc; \ - bnslr; \ - lis r4,errno@ha; \ - stw r3,errno@l(r4); \ - li r3,-1; \ blr SYSCALL(execve) --- linux-2.6.6/arch/ppc/kernel/process.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/ppc/kernel/process.c 2004-05-10 01:19:31.142004752 -0700 @@ -668,12 +668,6 @@ void __init ll_puts(const char *s) } #endif -/* - * These bracket the sleeping functions.. - */ -#define first_sched ((unsigned long) scheduling_functions_start_here) -#define last_sched ((unsigned long) scheduling_functions_end_here) - unsigned long get_wchan(struct task_struct *p) { unsigned long ip, sp; @@ -688,7 +682,7 @@ unsigned long get_wchan(struct task_stru return 0; if (count > 0) { ip = *(unsigned long *)(sp + 4); - if (ip < first_sched || ip >= last_sched) + if (!in_sched_functions(ip)) return ip; } } while (count++ < 16); --- linux-2.6.6/arch/ppc/kernel/setup.c 2004-03-10 20:41:26.000000000 -0800 +++ 25/arch/ppc/kernel/setup.c 2004-05-10 01:19:18.572915544 -0700 @@ -53,7 +53,6 @@ extern void ppc6xx_idle(void); extern void power4_idle(void); extern boot_infos_t *boot_infos; -char saved_command_line[COMMAND_LINE_SIZE]; unsigned char aux_device_present; struct ide_machdep_calls ppc_ide_md; char *sysmap; --- linux-2.6.6/arch/ppc/kernel/smp.c 2004-04-03 20:39:10.000000000 -0800 +++ 25/arch/ppc/kernel/smp.c 2004-05-10 01:19:49.909151712 -0700 @@ -211,6 +211,8 @@ int smp_call_function(void (*func) (void bitmask. --RR */ if (num_online_cpus() <= 1) return 0; + /* Can deadlock when called with interrupts disabled */ + WARN_ON(irqs_disabled()); return __smp_call_function(func, info, wait, MSG_ALL_BUT_SELF); } --- linux-2.6.6/arch/ppc/mm/pgtable.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/ppc/mm/pgtable.c 2004-05-10 01:19:09.103355136 -0700 @@ -86,9 +86,14 @@ pte_t *pte_alloc_one_kernel(struct mm_st extern int mem_init_done; extern void *early_get_page(void); - if (mem_init_done) + if (mem_init_done) { pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT); - else + if (pte) { + struct page *ptepage = virt_to_page(pte); + ptepage->mapping = (void *) mm; + ptepage->index = address & PMD_MASK; + } + } else pte = (pte_t *)early_get_page(); if (pte) clear_page(pte); @@ -97,7 +102,7 @@ pte_t *pte_alloc_one_kernel(struct mm_st struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) { - struct page *pte; + struct page *ptepage; #ifdef CONFIG_HIGHPTE int flags = GFP_KERNEL | __GFP_HIGHMEM | __GFP_REPEAT; @@ -105,10 +110,13 @@ struct page *pte_alloc_one(struct mm_str int flags = GFP_KERNEL | __GFP_REPEAT; #endif - pte = alloc_pages(flags, 0); - if (pte) - clear_highpage(pte); - return pte; + ptepage = alloc_pages(flags, 0); + if (ptepage) { + ptepage->mapping = (void *) mm; + ptepage->index = address & PMD_MASK; + clear_highpage(ptepage); + } + return ptepage; } void pte_free_kernel(pte_t *pte) @@ -116,15 +124,17 @@ void pte_free_kernel(pte_t *pte) #ifdef CONFIG_SMP hash_page_sync(); #endif + virt_to_page(pte)->mapping = NULL; free_page((unsigned long)pte); } -void pte_free(struct page *pte) +void pte_free(struct page *ptepage) { #ifdef CONFIG_SMP hash_page_sync(); #endif - __free_page(pte); + ptepage->mapping = NULL; + __free_page(ptepage); } #ifndef CONFIG_44x --- linux-2.6.6/arch/ppc/platforms/lopec_setup.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/ppc/platforms/lopec_setup.c 2004-05-10 01:19:18.573915392 -0700 @@ -33,7 +33,6 @@ #include #include -extern char saved_command_line[]; extern void lopec_find_bridges(void); /* --- linux-2.6.6/arch/ppc/platforms/pmac_setup.c 2004-02-17 20:48:42.000000000 -0800 +++ 25/arch/ppc/platforms/pmac_setup.c 2004-05-10 01:19:18.573915392 -0700 @@ -103,8 +103,6 @@ int has_l2cache = 0; static int current_root_goodness = -1; -extern char saved_command_line[]; - extern int pmac_newworld; #define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */ --- linux-2.6.6/arch/ppc/platforms/pplus.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/ppc/platforms/pplus.c 2004-05-10 01:19:18.574915240 -0700 @@ -48,8 +48,6 @@ TODC_ALLOC(); -extern char saved_command_line[]; - extern void pplus_setup_hose(void); extern void pplus_set_VIA_IDE_native(void); --- linux-2.6.6/arch/ppc/platforms/prep_setup.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/ppc/platforms/prep_setup.c 2004-05-10 01:19:18.575915088 -0700 @@ -76,7 +76,6 @@ extern void rs_nvram_write_val(int addr, extern void ibm_prep_init(void); extern void prep_find_bridges(void); -extern char saved_command_line[]; int _prep_type; --- linux-2.6.6/arch/ppc/syslib/m8xx_setup.c 2003-09-27 18:57:44.000000000 -0700 +++ 25/arch/ppc/syslib/m8xx_setup.c 2004-05-10 01:19:36.801144432 -0700 @@ -214,14 +214,13 @@ static void m8xx_restart(char *cmd) { __volatile__ unsigned char dummy; - uint msr; cli(); ((immap_t *)IMAP_ADDR)->im_clkrst.car_plprcr |= 0x00000080; /* Clear the ME bit in MSR to cause checkstop on machine check */ - mtmsr(mfmsr(msr) & ~0x1000); + mtmsr(mfmsr() & ~0x1000); dummy = ((immap_t *)IMAP_ADDR)->im_clkrst.res[0]; printk("Restart failed\n"); @@ -248,8 +247,8 @@ m8xx_show_percpuinfo(struct seq_file *m, bp = (bd_t *)__res; - seq_printf(m, "clock\t\t: %dMHz\n" - "bus clock\t: %dMHz\n", + seq_printf(m, "clock\t\t: %ldMHz\n" + "bus clock\t: %ldMHz\n", bp->bi_intfreq / 1000000, bp->bi_busfreq / 1000000); --- linux-2.6.6/arch/ppc/syslib/ppc8xx_pic.h 2003-06-14 12:18:08.000000000 -0700 +++ 25/arch/ppc/syslib/ppc8xx_pic.h 2004-05-10 01:19:36.801144432 -0700 @@ -3,6 +3,7 @@ #include #include +#include extern struct hw_interrupt_type ppc8xx_pic; --- linux-2.6.6/arch/s390/kernel/compat_exec.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/s390/kernel/compat_exec.c 2004-05-10 01:19:12.688810064 -0700 @@ -72,7 +72,7 @@ int setup_arg_pages32(struct linux_binpr mpnt->vm_ops = NULL; mpnt->vm_pgoff = 0; mpnt->vm_file = NULL; - INIT_LIST_HEAD(&mpnt->shared); + mpol_set_vma_default(mpnt); mpnt->vm_private_data = (void *) 0; insert_vm_struct(mm, mpnt); mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT; --- linux-2.6.6/arch/s390/kernel/compat_linux.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/s390/kernel/compat_linux.c 2004-05-10 01:19:35.181390672 -0700 @@ -355,144 +355,6 @@ asmlinkage long sys32_ftruncate64(unsign return sys_ftruncate(fd, (high << 32) | low); } -typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *); -typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *); - -static long do_readv_writev32(int type, struct file *file, - const struct compat_iovec *vector, u32 count) -{ - unsigned long tot_len; - struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov=iovstack, *ivp; - struct inode *inode; - long retval, i; - io_fn_t fn; - iov_fn_t fnv; - - /* First get the "struct iovec" from user memory and - * verify all the pointers - */ - if (!count) - return 0; - if (verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count)) - return -EFAULT; - if (count > UIO_MAXIOV) - return -EINVAL; - if (count > UIO_FASTIOV) { - iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL); - if (!iov) - return -ENOMEM; - } - - tot_len = 0; - i = count; - ivp = iov; - retval = -EINVAL; - while(i > 0) { - compat_ssize_t tmp = tot_len; - compat_ssize_t len; - u32 buf; - - if (__get_user(len, &vector->iov_len) || - __get_user(buf, &vector->iov_base)) { - retval = -EFAULT; - goto out; - } - if (len < 0) /* size_t not fitting an ssize_t32 .. */ - goto out; - tot_len += len; - if (tot_len < tmp) /* maths overflow on the compat_ssize_t */ - goto out; - ivp->iov_base = (void *)A(buf); - ivp->iov_len = (__kernel_size_t) len; - vector++; - ivp++; - i--; - } - if (tot_len == 0) { - retval = 0; - goto out; - } - - inode = file->f_dentry->d_inode; - /* VERIFY_WRITE actually means a read, as we write to user space */ - retval = locks_verify_area((type == VERIFY_WRITE - ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE), - inode, file, file->f_pos, tot_len); - if (retval) - goto out; - - /* VERIFY_WRITE actually means a read, as we write to user space */ - fnv = (type == VERIFY_WRITE ? file->f_op->readv : file->f_op->writev); - if (fnv) { - retval = fnv(file, iov, count, &file->f_pos); - goto out; - } - - fn = (type == VERIFY_WRITE ? file->f_op->read : - (io_fn_t) file->f_op->write); - - ivp = iov; - while (count > 0) { - void * base; - int len, nr; - - base = ivp->iov_base; - len = ivp->iov_len; - ivp++; - count--; - nr = fn(file, base, len, &file->f_pos); - if (nr < 0) { - if (!retval) - retval = nr; - break; - } - retval += nr; - if (nr != len) - break; - } -out: - if (iov != iovstack) - kfree(iov); - - return retval; -} - -asmlinkage long sys32_readv(int fd, struct compat_iovec *vector, unsigned long count) -{ - struct file *file; - long ret = -EBADF; - - file = fget(fd); - if(!file) - goto bad_file; - - if (file->f_op && (file->f_mode & FMODE_READ) && - (file->f_op->readv || file->f_op->read)) - ret = do_readv_writev32(VERIFY_WRITE, file, vector, count); - fput(file); - -bad_file: - return ret; -} - -asmlinkage long sys32_writev(int fd, struct compat_iovec *vector, unsigned long count) -{ - struct file *file; - int ret = -EBADF; - - file = fget(fd); - if(!file) - goto bad_file; - if (file->f_op && (file->f_mode & FMODE_WRITE) && - (file->f_op->writev || file->f_op->write)) - ret = do_readv_writev32(VERIFY_READ, file, vector, count); - fput(file); - -bad_file: - return ret; -} - /* readdir & getdents */ #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) @@ -623,160 +485,6 @@ out: /* end of readdir & getdents */ -/* - * Ooo, nasty. We need here to frob 32-bit unsigned longs to - * 64-bit unsigned longs. - */ - -static inline int -get_fd_set32(unsigned long n, unsigned long *fdset, u32 *ufdset) -{ - if (ufdset) { - unsigned long odd; - - if (verify_area(VERIFY_WRITE, ufdset, n*sizeof(u32))) - return -EFAULT; - - odd = n & 1UL; - n &= ~1UL; - while (n) { - unsigned long h, l; - __get_user(l, ufdset); - __get_user(h, ufdset+1); - ufdset += 2; - *fdset++ = h << 32 | l; - n -= 2; - } - if (odd) - __get_user(*fdset, ufdset); - } else { - /* Tricky, must clear full unsigned long in the - * kernel fdset at the end, this makes sure that - * actually happens. - */ - memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32)); - } - return 0; -} - -static inline void -set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset) -{ - unsigned long odd; - - if (!ufdset) - return; - - odd = n & 1UL; - n &= ~1UL; - while (n) { - unsigned long h, l; - l = *fdset++; - h = l >> 32; - __put_user(l, ufdset); - __put_user(h, ufdset+1); - ufdset += 2; - n -= 2; - } - if (odd) - __put_user(*fdset, ufdset); -} - -#define MAX_SELECT_SECONDS \ - ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1) - -asmlinkage long sys32_select(int n, u32 *inp, u32 *outp, u32 *exp, - struct compat_timeval *tvp) -{ - fd_set_bits fds; - char *bits; - unsigned long nn; - long timeout; - int ret, size; - - timeout = MAX_SCHEDULE_TIMEOUT; - if (tvp) { - int sec, usec; - - if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp))) - || (ret = __get_user(sec, &tvp->tv_sec)) - || (ret = __get_user(usec, &tvp->tv_usec))) - goto out_nofds; - - ret = -EINVAL; - if(sec < 0 || usec < 0) - goto out_nofds; - - if ((unsigned long) sec < MAX_SELECT_SECONDS) { - timeout = (usec + 1000000/HZ - 1) / (1000000/HZ); - timeout += sec * (unsigned long) HZ; - } - } - - ret = -EINVAL; - if (n < 0) - goto out_nofds; - if (n > current->files->max_fdset) - n = current->files->max_fdset; - - /* - * We need 6 bitmaps (in/out/ex for both incoming and outgoing), - * since we used fdset we need to allocate memory in units of - * long-words. - */ - ret = -ENOMEM; - size = FDS_BYTES(n); - bits = kmalloc(6 * size, GFP_KERNEL); - if (!bits) - goto out_nofds; - fds.in = (unsigned long *) bits; - fds.out = (unsigned long *) (bits + size); - fds.ex = (unsigned long *) (bits + 2*size); - fds.res_in = (unsigned long *) (bits + 3*size); - fds.res_out = (unsigned long *) (bits + 4*size); - fds.res_ex = (unsigned long *) (bits + 5*size); - - nn = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32)); - if ((ret = get_fd_set32(nn, fds.in, inp)) || - (ret = get_fd_set32(nn, fds.out, outp)) || - (ret = get_fd_set32(nn, fds.ex, exp))) - goto out; - zero_fd_set(n, fds.res_in); - zero_fd_set(n, fds.res_out); - zero_fd_set(n, fds.res_ex); - - ret = do_select(n, &fds, &timeout); - - if (tvp && !(current->personality & STICKY_TIMEOUTS)) { - int sec = 0, usec = 0; - if (timeout) { - sec = timeout / HZ; - usec = timeout % HZ; - usec *= (1000000/HZ); - } - put_user(sec, &tvp->tv_sec); - put_user(usec, &tvp->tv_usec); - } - - if (ret < 0) - goto out; - if (!ret) { - ret = -ERESTARTNOHAND; - if (signal_pending(current)) - goto out; - ret = 0; - } - - set_fd_set32(nn, inp, fds.res_in); - set_fd_set32(nn, outp, fds.res_out); - set_fd_set32(nn, exp, fds.res_ex); - -out: - kfree(bits); -out_nofds: - return ret; -} - int cp_compat_stat(struct kstat *stat, struct compat_stat *statbuf) { int err; @@ -1026,188 +734,6 @@ sys32_rt_sigqueueinfo(int pid, int sig, return ret; } -extern void check_pending(int signum); - -/* - * count32() counts the number of arguments/envelopes - */ -static int count32(u32 * argv) -{ - int i = 0; - - if (argv != NULL) { - for (;;) { - u32 p; int error; - - error = get_user(p,argv); - if (error) return error; - if (!p) break; - argv++; i++; - } - } - return i; -} - -/* - * 'copy_string32()' copies argument/envelope strings from user - * memory to free pages in kernel mem. These are in a format ready - * to be put directly into the top of new user memory. - */ -static int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm) -{ - while (argc-- > 0) { - u32 str; - int len; - unsigned long pos; - - if (get_user(str, argv + argc) || - !str || - !(len = strnlen_user((char *)A(str), bprm->p))) - return -EFAULT; - - if (bprm->p < len) - return -E2BIG; - - bprm->p -= len; - - pos = bprm->p; - while (len) { - char *kaddr; - struct page *page; - int offset, bytes_to_copy, new, err; - - offset = pos % PAGE_SIZE; - page = bprm->page[pos / PAGE_SIZE]; - new = 0; - if (!page) { - page = alloc_page(GFP_USER); - bprm->page[pos / PAGE_SIZE] = page; - if (!page) - return -ENOMEM; - new = 1; - } - kaddr = (char *)kmap(page); - - if (new && offset) - memset(kaddr, 0, offset); - bytes_to_copy = PAGE_SIZE - offset; - if (bytes_to_copy > len) { - bytes_to_copy = len; - if (new) - memset(kaddr+offset+len, 0, - PAGE_SIZE-offset-len); - } - - err = copy_from_user(kaddr + offset, (char *)A(str), - bytes_to_copy); - kunmap(page); - - if (err) - return -EFAULT; - - pos += bytes_to_copy; - str += bytes_to_copy; - len -= bytes_to_copy; - } - } - return 0; -} - -/* - * sys32_execve() executes a new program. - */ -static inline int -do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs) -{ - struct linux_binprm bprm; - struct file * file; - int retval; - int i; - - sched_balance_exec(); - - file = open_exec(filename); - - retval = PTR_ERR(file); - if (IS_ERR(file)) - return retval; - - bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); - memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0])); - - bprm.file = file; - bprm.filename = filename; - bprm.interp = filename; - bprm.sh_bang = 0; - bprm.loader = 0; - bprm.exec = 0; - bprm.mm = mm_alloc(); - retval = -ENOMEM; - if (!bprm.mm) - goto out_file; - - /* init_new_context is empty for s390x. */ - - bprm.argc = count32(argv); - if ((retval = bprm.argc) < 0) - goto out_mm; - - bprm.envc = count32(envp); - if ((retval = bprm.envc) < 0) - goto out_mm; - - retval = security_bprm_alloc(&bprm); - if (retval) - goto out; - - retval = prepare_binprm(&bprm); - if (retval < 0) - goto out; - - retval = copy_strings_kernel(1, &bprm.filename, &bprm); - if (retval < 0) - goto out; - - bprm.exec = bprm.p; - retval = copy_strings32(bprm.envc, envp, &bprm); - if (retval < 0) - goto out; - - retval = copy_strings32(bprm.argc, argv, &bprm); - if (retval < 0) - goto out; - - retval = search_binary_handler(&bprm, regs); - if (retval >= 0) { - /* execve success */ - security_bprm_free(&bprm); - return retval; - } - -out: - /* Something went wrong, return the inode and free the argument pages*/ - for (i=0 ; iptrace &= ~PT_DTRACE; @@ -1270,226 +797,6 @@ sys32_delete_module(const char __user *n #endif /* CONFIG_MODULES */ -/* Stuff for NFS server syscalls... */ -struct nfsctl_svc32 { - u16 svc32_port; - s32 svc32_nthreads; -}; - -struct nfsctl_client32 { - s8 cl32_ident[NFSCLNT_IDMAX+1]; - s32 cl32_naddr; - struct in_addr cl32_addrlist[NFSCLNT_ADDRMAX]; - s32 cl32_fhkeytype; - s32 cl32_fhkeylen; - u8 cl32_fhkey[NFSCLNT_KEYMAX]; -}; - -struct nfsctl_export32 { - s8 ex32_client[NFSCLNT_IDMAX+1]; - s8 ex32_path[NFS_MAXPATHLEN+1]; - compat_dev_t ex32_dev; - compat_ino_t ex32_ino; - s32 ex32_flags; - compat_uid_t ex32_anon_uid; - compat_gid_t ex32_anon_gid; -}; - -struct nfsctl_fdparm32 { - struct sockaddr gd32_addr; - s8 gd32_path[NFS_MAXPATHLEN+1]; - s32 gd32_version; -}; - -struct nfsctl_fsparm32 { - struct sockaddr gd32_addr; - s8 gd32_path[NFS_MAXPATHLEN+1]; - s32 gd32_maxlen; -}; - -struct nfsctl_arg32 { - s32 ca32_version; /* safeguard */ - union { - struct nfsctl_svc32 u32_svc; - struct nfsctl_client32 u32_client; - struct nfsctl_export32 u32_export; - struct nfsctl_fdparm32 u32_getfd; - struct nfsctl_fsparm32 u32_getfs; - } u; -#define ca32_svc u.u32_svc -#define ca32_client u.u32_client -#define ca32_export u.u32_export -#define ca32_getfd u.u32_getfd -#define ca32_getfs u.u32_getfs -#define ca32_authd u.u32_authd -}; - -union nfsctl_res32 { - __u8 cr32_getfh[NFS_FHSIZE]; - struct knfsd_fh cr32_getfs; -}; - -static int nfs_svc32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) -{ - int err; - - err = __get_user(karg->ca_version, &arg32->ca32_version); - err |= __get_user(karg->ca_svc.svc_port, &arg32->ca32_svc.svc32_port); - err |= __get_user(karg->ca_svc.svc_nthreads, &arg32->ca32_svc.svc32_nthreads); - return err; -} - -static int nfs_clnt32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) -{ - int err; - - err = __get_user(karg->ca_version, &arg32->ca32_version); - err |= copy_from_user(&karg->ca_client.cl_ident[0], - &arg32->ca32_client.cl32_ident[0], - NFSCLNT_IDMAX); - err |= __get_user(karg->ca_client.cl_naddr, &arg32->ca32_client.cl32_naddr); - err |= copy_from_user(&karg->ca_client.cl_addrlist[0], - &arg32->ca32_client.cl32_addrlist[0], - (sizeof(struct in_addr) * NFSCLNT_ADDRMAX)); - err |= __get_user(karg->ca_client.cl_fhkeytype, - &arg32->ca32_client.cl32_fhkeytype); - err |= __get_user(karg->ca_client.cl_fhkeylen, - &arg32->ca32_client.cl32_fhkeylen); - err |= copy_from_user(&karg->ca_client.cl_fhkey[0], - &arg32->ca32_client.cl32_fhkey[0], - NFSCLNT_KEYMAX); - return err; -} - -static int nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) -{ - int err; - - err = __get_user(karg->ca_version, &arg32->ca32_version); - err |= copy_from_user(&karg->ca_export.ex_client[0], - &arg32->ca32_export.ex32_client[0], - NFSCLNT_IDMAX); - err |= copy_from_user(&karg->ca_export.ex_path[0], - &arg32->ca32_export.ex32_path[0], - NFS_MAXPATHLEN); - err |= __get_user(karg->ca_export.ex_dev, - &arg32->ca32_export.ex32_dev); - err |= __get_user(karg->ca_export.ex_ino, - &arg32->ca32_export.ex32_ino); - err |= __get_user(karg->ca_export.ex_flags, - &arg32->ca32_export.ex32_flags); - err |= __get_user(karg->ca_export.ex_anon_uid, - &arg32->ca32_export.ex32_anon_uid); - err |= __get_user(karg->ca_export.ex_anon_gid, - &arg32->ca32_export.ex32_anon_gid); - karg->ca_export.ex_anon_uid = high2lowuid(karg->ca_export.ex_anon_uid); - karg->ca_export.ex_anon_gid = high2lowgid(karg->ca_export.ex_anon_gid); - return err; -} - -static int nfs_getfd32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) -{ - int err; - - err = __get_user(karg->ca_version, &arg32->ca32_version); - err |= copy_from_user(&karg->ca_getfd.gd_addr, - &arg32->ca32_getfd.gd32_addr, - (sizeof(struct sockaddr))); - err |= copy_from_user(&karg->ca_getfd.gd_path, - &arg32->ca32_getfd.gd32_path, - (NFS_MAXPATHLEN+1)); - err |= __get_user(karg->ca_getfd.gd_version, - &arg32->ca32_getfd.gd32_version); - return err; -} - -static int nfs_getfs32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) -{ - int err; - - err = __get_user(karg->ca_version, &arg32->ca32_version); - err |= copy_from_user(&karg->ca_getfs.gd_addr, - &arg32->ca32_getfs.gd32_addr, - (sizeof(struct sockaddr))); - err |= copy_from_user(&karg->ca_getfs.gd_path, - &arg32->ca32_getfs.gd32_path, - (NFS_MAXPATHLEN+1)); - err |= __get_user(karg->ca_getfs.gd_maxlen, - &arg32->ca32_getfs.gd32_maxlen); - return err; -} - -/* This really doesn't need translations, we are only passing - * back a union which contains opaque nfs file handle data. - */ -static int nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32) -{ - return copy_to_user(res32, kres, sizeof(*res32)) ? -EFAULT : 0; -} - -long asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32) -{ - struct nfsctl_arg *karg = NULL; - union nfsctl_res *kres = NULL; - mm_segment_t oldfs; - int err; - - karg = kmalloc(sizeof(*karg), GFP_USER); - if(!karg) - return -ENOMEM; - if(res32) { - kres = kmalloc(sizeof(*kres), GFP_USER); - if(!kres) { - kfree(karg); - return -ENOMEM; - } - } - switch(cmd) { - case NFSCTL_SVC: - err = nfs_svc32_trans(karg, arg32); - break; - case NFSCTL_ADDCLIENT: - err = nfs_clnt32_trans(karg, arg32); - break; - case NFSCTL_DELCLIENT: - err = nfs_clnt32_trans(karg, arg32); - break; - case NFSCTL_EXPORT: - case NFSCTL_UNEXPORT: - err = nfs_exp32_trans(karg, arg32); - break; - case NFSCTL_GETFD: - err = nfs_getfd32_trans(karg, arg32); - break; - case NFSCTL_GETFS: - err = nfs_getfs32_trans(karg, arg32); - break; - default: - err = -EINVAL; - break; - } - if(err) - goto done; - oldfs = get_fs(); - set_fs(KERNEL_DS); - err = sys_nfsservctl(cmd, karg, kres); - set_fs(oldfs); - - if (err) - goto done; - - if((cmd == NFSCTL_GETFD) || - (cmd == NFSCTL_GETFS)) - err = nfs_getfh32_res_trans(kres, res32); - -done: - if(karg) - kfree(karg); - if(kres) - kfree(kres); - return err; -} - /* Translations due to time_t size differences. Which affects all sorts of things, like timeval and itimerval. */ --- linux-2.6.6/arch/s390/kernel/compat_wrapper.S 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/s390/kernel/compat_wrapper.S 2004-05-10 01:19:35.182390520 -0700 @@ -641,14 +641,14 @@ sys32_getdents_wrapper: llgfr %r4,%r4 # unsigned int jg sys32_getdents # branch to system call - .globl sys32_select_wrapper -sys32_select_wrapper: + .globl compat_sys_select_wrapper +compat_sys_select_wrapper: lgfr %r2,%r2 # int - llgtr %r3,%r3 # fd_set * - llgtr %r4,%r4 # fd_set * - llgtr %r5,%r5 # fd_set * - llgtr %r6,%r6 # struct timeval_emu31 * - jg sys32_select # branch to system call + llgtr %r3,%r3 # compat_fd_set * + llgtr %r4,%r4 # compat_fd_set * + llgtr %r5,%r5 # compat_fd_set * + llgtr %r6,%r6 # struct compat_timeval * + jg compat_sys_select # branch to system call .globl sys32_flock_wrapper sys32_flock_wrapper: @@ -663,19 +663,19 @@ sys32_msync_wrapper: lgfr %r4,%r4 # int jg sys_msync # branch to system call - .globl sys32_readv_wrapper -sys32_readv_wrapper: + .globl compat_sys_readv_wrapper +compat_sys_readv_wrapper: lgfr %r2,%r2 # int - llgtr %r3,%r3 # const struct iovec_emu31 * + llgtr %r3,%r3 # const struct compat_iovec * llgfr %r4,%r4 # unsigned long - jg sys32_readv # branch to system call + jg compat_sys_readv # branch to system call - .globl sys32_writev_wrapper -sys32_writev_wrapper: + .globl compat_sys_writev_wrapper +compat_sys_writev_wrapper: lgfr %r2,%r2 # int - llgtr %r3,%r3 # const struct iovec_emu31 * + llgtr %r3,%r3 # const struct compat_iovec * llgfr %r4,%r4 # unsigned long - jg sys32_writev # branch to system call + jg compat_sys_writev # branch to system call .globl sys32_getsid_wrapper sys32_getsid_wrapper: @@ -786,12 +786,12 @@ sys32_poll_wrapper: lgfr %r4,%r4 # long jg sys_poll # branch to system call - .globl sys32_nfsservctl_wrapper -sys32_nfsservctl_wrapper: + .globl compat_sys_nfsservctl_wrapper +compat_sys_nfsservctl_wrapper: lgfr %r2,%r2 # int - llgtr %r3,%r3 # struct nfsctl_arg_emu31 * - llgtr %r4,%r4 # union nfsctl_res_emu31 * - jg sys32_nfsservctl # branch to system call + llgtr %r3,%r3 # struct compat_nfsctl_arg* + llgtr %r4,%r4 # union compat_nfsctl_res* + jg compat_sys_nfsservctl # branch to system call .globl sys32_setresgid16_wrapper sys32_setresgid16_wrapper: --- linux-2.6.6/arch/s390/kernel/process.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/s390/kernel/process.c 2004-05-10 01:19:31.143004600 -0700 @@ -385,12 +385,6 @@ void dump_thread(struct pt_regs * regs, dump->regs.per_info = current->thread.per_info; } -/* - * These bracket the sleeping functions.. - */ -#define first_sched ((unsigned long) scheduling_functions_start_here) -#define last_sched ((unsigned long) scheduling_functions_end_here) - unsigned long get_wchan(struct task_struct *p) { unsigned long r14, r15, bc; @@ -413,12 +407,10 @@ unsigned long get_wchan(struct task_stru #else r14 = *(unsigned long *) (bc+112); #endif - if (r14 < first_sched || r14 >= last_sched) + if (!in_sched_functions(r14)) return r14; bc = (*(unsigned long *) bc) & PSW_ADDR_INSN; } while (count++ < 16); return 0; } -#undef last_sched -#undef first_sched --- linux-2.6.6/arch/s390/kernel/setup.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/s390/kernel/setup.c 2004-05-10 01:19:18.576914936 -0700 @@ -74,7 +74,6 @@ extern int _text,_etext, _edata, _end; #include static char command_line[COMMAND_LINE_SIZE] = { 0, }; - char saved_command_line[COMMAND_LINE_SIZE]; static struct resource code_resource = { "Kernel code", 0x100000, 0 }; static struct resource data_resource = { "Kernel data", 0, 0 }; --- linux-2.6.6/arch/s390/kernel/smp.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/s390/kernel/smp.c 2004-05-10 01:19:49.909151712 -0700 @@ -127,6 +127,9 @@ int smp_call_function (void (*func) (voi if (cpus <= 0) return 0; + /* Can deadlock when called with interrupts disabled */ + WARN_ON(irqs_disabled()); + data.func = func; data.info = info; atomic_set(&data.started, 0); --- linux-2.6.6/arch/s390/kernel/syscalls.S 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/s390/kernel/syscalls.S 2004-05-10 01:19:35.183390368 -0700 @@ -150,11 +150,11 @@ SYSCALL(sys_setfsuid16,sys_ni_syscall,sy SYSCALL(sys_setfsgid16,sys_ni_syscall,sys32_setfsgid16_wrapper) /* old setfsgid16 syscall */ SYSCALL(sys_llseek,sys_llseek,sys32_llseek_wrapper) /* 140 */ SYSCALL(sys_getdents,sys_getdents,sys32_getdents_wrapper) -SYSCALL(sys_select,sys_select,sys32_select_wrapper) +SYSCALL(sys_select,sys_select,compat_sys_select_wrapper) SYSCALL(sys_flock,sys_flock,sys32_flock_wrapper) SYSCALL(sys_msync,sys_msync,sys32_msync_wrapper) -SYSCALL(sys_readv,sys_readv,sys32_readv_wrapper) /* 145 */ -SYSCALL(sys_writev,sys_writev,sys32_writev_wrapper) +SYSCALL(sys_readv,sys_readv,compat_sys_readv_wrapper) /* 145 */ +SYSCALL(sys_writev,sys_writev,compat_sys_writev_wrapper) SYSCALL(sys_getsid,sys_getsid,sys32_getsid_wrapper) SYSCALL(sys_fdatasync,sys_fdatasync,sys32_fdatasync_wrapper) SYSCALL(sys_sysctl,sys_sysctl,sys32_sysctl_wrapper) @@ -177,7 +177,7 @@ SYSCALL(sys_getresuid16,sys_ni_syscall,s NI_SYSCALL /* for vm86 */ NI_SYSCALL /* old sys_query_module */ SYSCALL(sys_poll,sys_poll,sys32_poll_wrapper) -SYSCALL(sys_nfsservctl,sys_nfsservctl,sys32_nfsservctl_wrapper) +SYSCALL(sys_nfsservctl,sys_nfsservctl,compat_sys_nfsservctl_wrapper) SYSCALL(sys_setresgid16,sys_ni_syscall,sys32_setresgid16_wrapper) /* 170 old setresgid16 syscall */ SYSCALL(sys_getresgid16,sys_ni_syscall,sys32_getresgid16_wrapper) /* old getresgid16 syscall */ SYSCALL(sys_prctl,sys_prctl,sys32_prctl_wrapper) --- linux-2.6.6/arch/sh/kernel/process.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/sh/kernel/process.c 2004-05-10 01:19:31.143004600 -0700 @@ -461,12 +461,6 @@ out: return error; } -/* - * These bracket the sleeping functions.. - */ -#define first_sched ((unsigned long) scheduling_functions_start_here) -#define last_sched ((unsigned long) scheduling_functions_end_here) - unsigned long get_wchan(struct task_struct *p) { unsigned long schedule_frame; @@ -479,7 +473,7 @@ unsigned long get_wchan(struct task_stru * The same comment as on the Alpha applies here, too ... */ pc = thread_saved_pc(p); - if (pc >= first_sched && pc < last_sched) { + if (in_sched_functions(pc)) { schedule_frame = ((unsigned long *)(long)p->thread.sp)[1]; return (unsigned long)((unsigned long *)schedule_frame)[1]; } --- linux-2.6.6/arch/sh/kernel/setup.c 2004-02-03 20:42:35.000000000 -0800 +++ 25/arch/sh/kernel/setup.c 2004-05-10 01:19:18.576914936 -0700 @@ -85,14 +85,12 @@ static struct sh_machine_vector* __init #define INITRD_SIZE (*(unsigned long *) (PARAM+0x014)) /* ... */ #define COMMAND_LINE ((char *) (PARAM+0x100)) -#define COMMAND_LINE_SIZE 256 #define RAMDISK_IMAGE_START_MASK 0x07FF #define RAMDISK_PROMPT_FLAG 0x8000 #define RAMDISK_LOAD_FLAG 0x4000 static char command_line[COMMAND_LINE_SIZE] = { 0, }; - char saved_command_line[COMMAND_LINE_SIZE]; struct resource standard_io_resources[] = { { "dma1", 0x00, 0x1f }, --- linux-2.6.6/arch/sh/kernel/smp.c 2004-02-03 20:42:35.000000000 -0800 +++ 25/arch/sh/kernel/smp.c 2004-05-10 01:19:49.910151560 -0700 @@ -181,6 +181,9 @@ int smp_call_function(void (*func)(void if (nr_cpus < 2) return 0; + /* Can deadlock when called with interrupts disabled */ + WARN_ON(irqs_disabled()); + spin_lock(&smp_fn_call.lock); atomic_set(&smp_fn_call.finished, 0); --- linux-2.6.6/arch/sh/mm/hugetlbpage.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/sh/mm/hugetlbpage.c 2004-05-10 01:19:56.317177544 -0700 @@ -248,8 +248,9 @@ int hugetlb_prefault(struct address_spac goto out; } ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC); - unlock_page(page); - if (ret) { + if (! ret) { + unlock_page(page); + } else { hugetlb_put_quota(mapping); free_huge_page(page); goto out; --- linux-2.6.6/arch/sparc64/Kconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/sparc64/Kconfig 2004-05-10 01:19:27.997482792 -0700 @@ -687,12 +687,19 @@ config DEBUG_BOOTMEM depends on DEBUG_KERNEL bool "Debug BOOTMEM initialization" +config LOCKMETER + bool "Kernel lock metering" + depends on SMP && !PREEMPT + help + Say Y to enable kernel lock metering, which adds overhead to SMP locks, + but allows you to see various statistics using the lockstat command. + # We have a custom atomic_dec_and_lock() implementation but it's not # compatible with spinlock debugging so we need to fall back on # the generic version in that case. config HAVE_DEC_LOCK bool - depends on SMP && !DEBUG_SPINLOCK + depends on SMP && !DEBUG_SPINLOCK && !LOCKMETER default y config MCOUNT --- linux-2.6.6/arch/sparc64/kernel/process.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/sparc64/kernel/process.c 2004-05-10 01:19:31.144004448 -0700 @@ -847,8 +847,7 @@ unsigned long get_wchan(struct task_stru break; rw = (struct reg_window *) fp; pc = rw->ins[7]; - if (pc < ((unsigned long) scheduling_functions_start_here) || - pc >= ((unsigned long) scheduling_functions_end_here)) { + if (!in_sched_functions(pc)) { ret = pc; goto out; } --- linux-2.6.6/arch/sparc64/kernel/setup.c 2004-04-03 20:39:11.000000000 -0800 +++ 25/arch/sparc64/kernel/setup.c 2004-05-10 01:19:18.577914784 -0700 @@ -451,8 +451,7 @@ extern unsigned short ram_flags; extern int root_mountflags; -char saved_command_line[256]; -char reboot_command[256]; +char reboot_command[COMMAND_LINE_SIZE]; static struct pt_regs fake_swapper_regs = { { 0, }, 0, 0, 0, 0 }; --- linux-2.6.6/arch/sparc64/kernel/smp.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/sparc64/kernel/smp.c 2004-05-10 01:19:49.911151408 -0700 @@ -598,6 +598,9 @@ int smp_call_function(void (*func)(void if (!cpus) return 0; + /* Can deadlock when called with interrupts disabled */ + WARN_ON(irqs_disabled()); + data.func = func; data.info = info; atomic_set(&data.finished, 0); --- linux-2.6.6/arch/sparc64/kernel/sparc64_ksyms.c 2004-04-03 20:39:11.000000000 -0800 +++ 25/arch/sparc64/kernel/sparc64_ksyms.c 2004-05-10 01:19:18.578914632 -0700 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -76,7 +77,6 @@ extern int __memcmp(const void *, const extern int __strncmp(const char *, const char *, __kernel_size_t); extern __kernel_size_t __strlen(const char *); extern __kernel_size_t strlen(const char *); -extern char saved_command_line[]; extern void linux_sparc_syscall(void); extern void rtrap(void); extern void show_regs(struct pt_regs *); --- linux-2.6.6/arch/sparc64/kernel/sys_sparc32.c 2004-04-03 20:39:11.000000000 -0800 +++ 25/arch/sparc64/kernel/sys_sparc32.c 2004-05-10 01:19:35.185390064 -0700 @@ -832,182 +832,6 @@ asmlinkage int sys32_ftruncate64(unsigne return sys_ftruncate(fd, (high << 32) | low); } -typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *); -typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *); - -static long do_readv_writev32(int type, struct file *file, - const struct compat_iovec *vector, u32 count) -{ - compat_ssize_t tot_len; - struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov=iovstack, *ivp; - struct inode *inode; - long retval, i; - io_fn_t fn; - iov_fn_t fnv; - - /* - * SuS says "The readv() function *may* fail if the iovcnt argument - * was less than or equal to 0, or greater than {IOV_MAX}. Linux has - * traditionally returned zero for zero segments, so... - */ - retval = 0; - if (count == 0) - goto out; - - /* First get the "struct iovec" from user memory and - * verify all the pointers - */ - retval = -EINVAL; - if (count > UIO_MAXIOV) - goto out; - if (!file->f_op) - goto out; - if (count > UIO_FASTIOV) { - retval = -ENOMEM; - iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL); - if (!iov) - goto out; - } - retval = -EFAULT; - if (verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count)) - goto out; - - /* - * Single unix specification: - * We should -EINVAL if an element length is not >= 0 and fitting an - * ssize_t. The total length is fitting an ssize_t - * - * Be careful here because iov_len is a size_t not an ssize_t - */ - tot_len = 0; - i = count; - ivp = iov; - retval = -EINVAL; - while(i > 0) { - compat_ssize_t tmp = tot_len; - compat_ssize_t len; - u32 buf; - - if (__get_user(len, &vector->iov_len) || - __get_user(buf, &vector->iov_base)) { - retval = -EFAULT; - goto out; - } - if (len < 0) /* size_t not fitting an ssize_t32 .. */ - goto out; - tot_len += len; - if (tot_len < tmp) /* maths overflow on the compat_ssize_t */ - goto out; - ivp->iov_base = (void *)A(buf); - ivp->iov_len = (__kernel_size_t) len; - vector++; - ivp++; - i--; - } - if (tot_len == 0) { - retval = 0; - goto out; - } - - inode = file->f_dentry->d_inode; - /* VERIFY_WRITE actually means a read, as we write to user space */ - retval = locks_verify_area((type == READ - ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE), - inode, file, file->f_pos, tot_len); - if (retval) - goto out; - - if (type == READ) { - fn = file->f_op->read; - fnv = file->f_op->readv; - } else { - fn = (io_fn_t)file->f_op->write; - fnv = file->f_op->writev; - } - if (fnv) { - retval = fnv(file, iov, count, &file->f_pos); - goto out; - } - - /* Do it by hand, with file-ops */ - ivp = iov; - while (count > 0) { - void * base; - int len, nr; - - base = ivp->iov_base; - len = ivp->iov_len; - ivp++; - count--; - - nr = fn(file, base, len, &file->f_pos); - - if (nr < 0) { - if (!retval) - retval = nr; - break; - } - retval += nr; - if (nr != len) - break; - } -out: - if (iov != iovstack) - kfree(iov); - if ((retval + (type == READ)) > 0) - dnotify_parent(file->f_dentry, - (type == READ) ? DN_ACCESS : DN_MODIFY); - - return retval; -} - -asmlinkage long sys32_readv(int fd, struct compat_iovec *vector, u32 count) -{ - struct file *file; - int ret; - - file = fget(fd); - if(!file) - return -EBADF; - - ret = -EBADF; - if (!(file->f_mode & FMODE_READ)) - goto out; - ret = -EINVAL; - if (!file->f_op || (!file->f_op->readv && !file->f_op->read)) - goto out; - - ret = do_readv_writev32(READ, file, vector, count); - -out: - fput(file); - return ret; -} - -asmlinkage long sys32_writev(int fd, struct compat_iovec *vector, u32 count) -{ - struct file *file; - int ret; - - file = fget(fd); - if(!file) - return -EBADF; - - ret = -EBADF; - if (!(file->f_mode & FMODE_WRITE)) - goto out; - ret = -EINVAL; - if (!file->f_op || (!file->f_op->writev && !file->f_op->write)) - goto out; - - ret = do_readv_writev32(WRITE, file, vector, count); - -out: - fput(file); - return ret; -} - /* readdir & getdents */ #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) @@ -1140,158 +964,6 @@ out: /* end of readdir & getdents */ -/* - * Ooo, nasty. We need here to frob 32-bit unsigned longs to - * 64-bit unsigned longs. - */ - -static int get_fd_set32(unsigned long n, unsigned long *fdset, u32 *ufdset) -{ - if (ufdset) { - unsigned long odd; - - if (verify_area(VERIFY_WRITE, ufdset, n*sizeof(u32))) - return -EFAULT; - - odd = n & 1UL; - n &= ~1UL; - while (n) { - unsigned long h, l; - __get_user(l, ufdset); - __get_user(h, ufdset+1); - ufdset += 2; - *fdset++ = h << 32 | l; - n -= 2; - } - if (odd) - __get_user(*fdset, ufdset); - } else { - /* Tricky, must clear full unsigned long in the - * kernel fdset at the end, this makes sure that - * actually happens. - */ - memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32)); - } - return 0; -} - -static void set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset) -{ - unsigned long odd; - - if (!ufdset) - return; - - odd = n & 1UL; - n &= ~1UL; - while (n) { - unsigned long h, l; - l = *fdset++; - h = l >> 32; - __put_user(l, ufdset); - __put_user(h, ufdset+1); - ufdset += 2; - n -= 2; - } - if (odd) - __put_user(*fdset, ufdset); -} - -#define MAX_SELECT_SECONDS \ - ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1) - -asmlinkage int sys32_select(int n, u32 *inp, u32 *outp, u32 *exp, u32 tvp_x) -{ - fd_set_bits fds; - struct compat_timeval *tvp = (struct compat_timeval *)AA(tvp_x); - char *bits; - unsigned long nn; - long timeout; - int ret, size; - - timeout = MAX_SCHEDULE_TIMEOUT; - if (tvp) { - time_t sec, usec; - - if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp))) - || (ret = __get_user(sec, &tvp->tv_sec)) - || (ret = __get_user(usec, &tvp->tv_usec))) - goto out_nofds; - - ret = -EINVAL; - if(sec < 0 || usec < 0) - goto out_nofds; - - if ((unsigned long) sec < MAX_SELECT_SECONDS) { - timeout = (usec + 1000000/HZ - 1) / (1000000/HZ); - timeout += sec * (unsigned long) HZ; - } - } - - ret = -EINVAL; - if (n < 0) - goto out_nofds; - if (n > current->files->max_fdset) - n = current->files->max_fdset; - - /* - * We need 6 bitmaps (in/out/ex for both incoming and outgoing), - * since we used fdset we need to allocate memory in units of - * long-words. - */ - ret = -ENOMEM; - size = FDS_BYTES(n); - bits = kmalloc(6 * size, GFP_KERNEL); - if (!bits) - goto out_nofds; - fds.in = (unsigned long *) bits; - fds.out = (unsigned long *) (bits + size); - fds.ex = (unsigned long *) (bits + 2*size); - fds.res_in = (unsigned long *) (bits + 3*size); - fds.res_out = (unsigned long *) (bits + 4*size); - fds.res_ex = (unsigned long *) (bits + 5*size); - - nn = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32)); - if ((ret = get_fd_set32(nn, fds.in, inp)) || - (ret = get_fd_set32(nn, fds.out, outp)) || - (ret = get_fd_set32(nn, fds.ex, exp))) - goto out; - zero_fd_set(n, fds.res_in); - zero_fd_set(n, fds.res_out); - zero_fd_set(n, fds.res_ex); - - ret = do_select(n, &fds, &timeout); - - if (tvp && !(current->personality & STICKY_TIMEOUTS)) { - time_t sec = 0, usec = 0; - if (timeout) { - sec = timeout / HZ; - usec = timeout % HZ; - usec *= (1000000/HZ); - } - put_user(sec, &tvp->tv_sec); - put_user(usec, &tvp->tv_usec); - } - - if (ret < 0) - goto out; - if (!ret) { - ret = -ERESTARTNOHAND; - if (signal_pending(current)) - goto out; - ret = 0; - } - - set_fd_set32(nn, inp, fds.res_in); - set_fd_set32(nn, outp, fds.res_out); - set_fd_set32(nn, exp, fds.res_ex); - -out: - kfree(bits); -out_nofds: - return ret; -} - int cp_compat_stat(struct kstat *stat, struct compat_stat *statbuf) { int err; @@ -1562,8 +1234,6 @@ sys32_rt_sigqueueinfo(int pid, int sig, return ret; } -extern void check_pending(int signum); - asmlinkage int sys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact) { struct k_sigaction new_ka, old_ka; @@ -1659,193 +1329,6 @@ sys32_rt_sigaction(int sig, struct sigac return ret; } - -/* - * count32() counts the number of arguments/envelopes - */ -static int count32(u32 * argv, int max) -{ - int i = 0; - - if (argv != NULL) { - for (;;) { - u32 p; int error; - - error = get_user(p,argv); - if (error) - return error; - if (!p) - break; - argv++; - if (++i > max) - return -E2BIG; - } - } - return i; -} - -/* - * 'copy_string32()' copies argument/envelope strings from user - * memory to free pages in kernel mem. These are in a format ready - * to be put directly into the top of new user memory. - */ -static int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm) -{ - while (argc-- > 0) { - u32 str; - int len; - unsigned long pos; - - if (get_user(str, argv + argc) || - !str || - !(len = strnlen_user((char *)A(str), bprm->p))) - return -EFAULT; - - if (bprm->p < len) - return -E2BIG; - - bprm->p -= len; - - pos = bprm->p; - while (len) { - char *kaddr; - struct page *page; - int offset, bytes_to_copy, new, err; - - offset = pos % PAGE_SIZE; - page = bprm->page[pos / PAGE_SIZE]; - new = 0; - if (!page) { - page = alloc_page(GFP_USER); - bprm->page[pos / PAGE_SIZE] = page; - if (!page) - return -ENOMEM; - new = 1; - } - kaddr = kmap(page); - - if (new && offset) - memset(kaddr, 0, offset); - bytes_to_copy = PAGE_SIZE - offset; - if (bytes_to_copy > len) { - bytes_to_copy = len; - if (new) - memset(kaddr+offset+len, 0, - PAGE_SIZE-offset-len); - } - - err = copy_from_user(kaddr + offset, (char *)A(str), - bytes_to_copy); - kunmap(page); - - if (err) - return -EFAULT; - - pos += bytes_to_copy; - str += bytes_to_copy; - len -= bytes_to_copy; - } - } - return 0; -} - -/* - * sys32_execve() executes a new program. - */ -static inline int -do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs) -{ - struct linux_binprm bprm; - struct file * file; - int retval; - int i; - - sched_balance_exec(); - - file = open_exec(filename); - - retval = PTR_ERR(file); - if (IS_ERR(file)) - return retval; - - bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); - memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0])); - - bprm.file = file; - bprm.filename = filename; - bprm.interp = filename; - bprm.sh_bang = 0; - bprm.loader = 0; - bprm.exec = 0; - bprm.security = NULL; - bprm.mm = mm_alloc(); - retval = -ENOMEM; - if (!bprm.mm) - goto out_file; - - retval = init_new_context(current, bprm.mm); - if (retval < 0) - goto out_mm; - - bprm.argc = count32(argv, bprm.p / sizeof(u32)); - if ((retval = bprm.argc) < 0) - goto out_mm; - - bprm.envc = count32(envp, bprm.p / sizeof(u32)); - if ((retval = bprm.envc) < 0) - goto out_mm; - - retval = security_bprm_alloc(&bprm); - if (retval) - goto out; - - retval = prepare_binprm(&bprm); - if (retval < 0) - goto out; - - retval = copy_strings_kernel(1, &bprm.filename, &bprm); - if (retval < 0) - goto out; - - bprm.exec = bprm.p; - retval = copy_strings32(bprm.envc, envp, &bprm); - if (retval < 0) - goto out; - - retval = copy_strings32(bprm.argc, argv, &bprm); - if (retval < 0) - goto out; - - retval = search_binary_handler(&bprm, regs); - if (retval >= 0) { - /* execve success */ - security_bprm_free(&bprm); - return retval; - } - -out: - /* Something went wrong, return the inode and free the argument pages*/ - for (i = 0 ; i < MAX_ARG_PAGES ; i++) { - struct page * page = bprm.page[i]; - if (page) - __free_page(page); - } - - if (bprm.security) - security_bprm_free(&bprm); - -out_mm: - if (bprm.mm) - mmdrop(bprm.mm); - -out_file: - if (bprm.file) { - allow_write_access(bprm.file); - fput(bprm.file); - } - return retval; -} - /* * sparc32_execve() executes a new program after the asm stub has set * things up for us. This should basically do what I want it to. @@ -1865,9 +1348,9 @@ asmlinkage int sparc32_execve(struct pt_ error = PTR_ERR(filename); if(IS_ERR(filename)) goto out; - error = do_execve32(filename, - (u32 *)AA((u32)regs->u_regs[base + UREG_I1]), - (u32 *)AA((u32)regs->u_regs[base + UREG_I2]), regs); + error = compat_do_execve(filename, + compat_ptr((u32)regs->u_regs[base + UREG_I1]), + compat_ptr((u32)regs->u_regs[base + UREG_I2]), regs); putname(filename); if(!error) { @@ -1909,232 +1392,6 @@ sys32_delete_module(const char *name_use #endif /* CONFIG_MODULES */ -#if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE) -/* Stuff for NFS server syscalls... */ -struct nfsctl_svc32 { - u16 svc32_port; - s32 svc32_nthreads; -}; - -struct nfsctl_client32 { - s8 cl32_ident[NFSCLNT_IDMAX+1]; - s32 cl32_naddr; - struct in_addr cl32_addrlist[NFSCLNT_ADDRMAX]; - s32 cl32_fhkeytype; - s32 cl32_fhkeylen; - u8 cl32_fhkey[NFSCLNT_KEYMAX]; -}; - -struct nfsctl_export32 { - s8 ex32_client[NFSCLNT_IDMAX+1]; - s8 ex32_path[NFS_MAXPATHLEN+1]; - compat_dev_t ex32_dev; - compat_ino_t ex32_ino; - s32 ex32_flags; - compat_uid_t ex32_anon_uid; - compat_gid_t ex32_anon_gid; -}; - -struct nfsctl_fdparm32 { - struct sockaddr gd32_addr; - s8 gd32_path[NFS_MAXPATHLEN+1]; - s32 gd32_version; -}; - -struct nfsctl_fsparm32 { - struct sockaddr gd32_addr; - s8 gd32_path[NFS_MAXPATHLEN+1]; - s32 gd32_maxlen; -}; - -struct nfsctl_arg32 { - s32 ca32_version; /* safeguard */ - union { - struct nfsctl_svc32 u32_svc; - struct nfsctl_client32 u32_client; - struct nfsctl_export32 u32_export; - struct nfsctl_fdparm32 u32_getfd; - struct nfsctl_fsparm32 u32_getfs; - } u; -#define ca32_svc u.u32_svc -#define ca32_client u.u32_client -#define ca32_export u.u32_export -#define ca32_getfd u.u32_getfd -#define ca32_getfs u.u32_getfs -}; - -union nfsctl_res32 { - __u8 cr32_getfh[NFS_FHSIZE]; - struct knfsd_fh cr32_getfs; -}; - -static int nfs_svc32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) -{ - int err; - - err = __get_user(karg->ca_version, &arg32->ca32_version); - err |= __get_user(karg->ca_svc.svc_port, &arg32->ca32_svc.svc32_port); - err |= __get_user(karg->ca_svc.svc_nthreads, &arg32->ca32_svc.svc32_nthreads); - return err; -} - -static int nfs_clnt32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) -{ - int err; - - err = __get_user(karg->ca_version, &arg32->ca32_version); - err |= copy_from_user(&karg->ca_client.cl_ident[0], - &arg32->ca32_client.cl32_ident[0], - NFSCLNT_IDMAX); - err |= __get_user(karg->ca_client.cl_naddr, &arg32->ca32_client.cl32_naddr); - err |= copy_from_user(&karg->ca_client.cl_addrlist[0], - &arg32->ca32_client.cl32_addrlist[0], - (sizeof(struct in_addr) * NFSCLNT_ADDRMAX)); - err |= __get_user(karg->ca_client.cl_fhkeytype, - &arg32->ca32_client.cl32_fhkeytype); - err |= __get_user(karg->ca_client.cl_fhkeylen, - &arg32->ca32_client.cl32_fhkeylen); - err |= copy_from_user(&karg->ca_client.cl_fhkey[0], - &arg32->ca32_client.cl32_fhkey[0], - NFSCLNT_KEYMAX); - return (err ? -EFAULT : 0); -} - -static int nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) -{ - int err; - - err = __get_user(karg->ca_version, &arg32->ca32_version); - err |= copy_from_user(&karg->ca_export.ex_client[0], - &arg32->ca32_export.ex32_client[0], - NFSCLNT_IDMAX); - err |= copy_from_user(&karg->ca_export.ex_path[0], - &arg32->ca32_export.ex32_path[0], - NFS_MAXPATHLEN); - err |= __get_user(karg->ca_export.ex_dev, - &arg32->ca32_export.ex32_dev); - err |= __get_user(karg->ca_export.ex_ino, - &arg32->ca32_export.ex32_ino); - err |= __get_user(karg->ca_export.ex_flags, - &arg32->ca32_export.ex32_flags); - err |= __get_user(karg->ca_export.ex_anon_uid, - &arg32->ca32_export.ex32_anon_uid); - err |= __get_user(karg->ca_export.ex_anon_gid, - &arg32->ca32_export.ex32_anon_gid); - karg->ca_export.ex_anon_uid = high2lowuid(karg->ca_export.ex_anon_uid); - karg->ca_export.ex_anon_gid = high2lowgid(karg->ca_export.ex_anon_gid); - return (err ? -EFAULT : 0); -} - -static int nfs_getfd32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) -{ - int err; - - err = __get_user(karg->ca_version, &arg32->ca32_version); - err |= copy_from_user(&karg->ca_getfd.gd_addr, - &arg32->ca32_getfd.gd32_addr, - (sizeof(struct sockaddr))); - err |= copy_from_user(&karg->ca_getfd.gd_path, - &arg32->ca32_getfd.gd32_path, - (NFS_MAXPATHLEN+1)); - err |= __get_user(karg->ca_getfd.gd_version, - &arg32->ca32_getfd.gd32_version); - return (err ? -EFAULT : 0); -} - -static int nfs_getfs32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) -{ - int err; - - err = __get_user(karg->ca_version, &arg32->ca32_version); - err |= copy_from_user(&karg->ca_getfs.gd_addr, - &arg32->ca32_getfs.gd32_addr, - (sizeof(struct sockaddr))); - err |= copy_from_user(&karg->ca_getfs.gd_path, - &arg32->ca32_getfs.gd32_path, - (NFS_MAXPATHLEN+1)); - err |= __get_user(karg->ca_getfs.gd_maxlen, - &arg32->ca32_getfs.gd32_maxlen); - return (err ? -EFAULT : 0); -} - -/* This really doesn't need translations, we are only passing - * back a union which contains opaque nfs file handle data. - */ -static int nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32) -{ - return (copy_to_user(res32, kres, sizeof(*res32)) ? -EFAULT : 0); -} - -int asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32) -{ - struct nfsctl_arg *karg = NULL; - union nfsctl_res *kres = NULL; - mm_segment_t oldfs; - int err; - - karg = kmalloc(sizeof(*karg), GFP_USER); - if(!karg) - return -ENOMEM; - if(res32) { - kres = kmalloc(sizeof(*kres), GFP_USER); - if(!kres) { - kfree(karg); - return -ENOMEM; - } - } - switch(cmd) { - case NFSCTL_SVC: - err = nfs_svc32_trans(karg, arg32); - break; - case NFSCTL_ADDCLIENT: - err = nfs_clnt32_trans(karg, arg32); - break; - case NFSCTL_DELCLIENT: - err = nfs_clnt32_trans(karg, arg32); - break; - case NFSCTL_EXPORT: - case NFSCTL_UNEXPORT: - err = nfs_exp32_trans(karg, arg32); - break; - case NFSCTL_GETFD: - err = nfs_getfd32_trans(karg, arg32); - break; - case NFSCTL_GETFS: - err = nfs_getfs32_trans(karg, arg32); - break; - default: - err = -EINVAL; - break; - } - if(err) - goto done; - oldfs = get_fs(); - set_fs(KERNEL_DS); - err = sys_nfsservctl(cmd, karg, kres); - set_fs(oldfs); - - if (err) - goto done; - - if((cmd == NFSCTL_GETFD) || - (cmd == NFSCTL_GETFS)) - err = nfs_getfh32_res_trans(kres, res32); - -done: - if(karg) - kfree(karg); - if(kres) - kfree(kres); - return err; -} -#else /* !NFSD */ -int asmlinkage sys32_nfsservctl(int cmd, void *notused, void *notused2) -{ - return sys_ni_syscall(); -} -#endif - /* Translations due to time_t size differences. Which affects all sorts of things, like timeval and itimerval. */ --- linux-2.6.6/arch/sparc64/kernel/sys_sunos32.c 2004-04-03 20:39:11.000000000 -0800 +++ 25/arch/sparc64/kernel/sys_sunos32.c 2004-05-10 01:19:34.932428520 -0700 @@ -528,18 +528,15 @@ asmlinkage int sunos_pathconf(u32 u_path return ret; } -/* SunOS mount system call emulation */ -extern asmlinkage int -sys32_select(int n, u32 inp, u32 outp, u32 exp, u32 tvp); - asmlinkage int sunos_select(int width, u32 inp, u32 outp, u32 exp, u32 tvp_x) { int ret; /* SunOS binaries expect that select won't change the tvp contents */ - ret = sys32_select (width, inp, outp, exp, tvp_x); + ret = compat_sys_select(width, compat_ptr(inp), compat_ptr(outp), + compat_ptr(exp), compat_ptr(tvp_x)); if (ret == -EINTR && tvp_x) { - struct compat_timeval *tvp = (struct compat_timeval *)A(tvp_x); + struct compat_timeval *tvp = compat_ptr(tvp_x); time_t sec, usec; __get_user(sec, &tvp->tv_sec); @@ -1203,9 +1200,6 @@ static inline int check_nonblock(int ret return ret; } -extern asmlinkage int sys32_readv(u32 fd, u32 vector, s32 count); -extern asmlinkage int sys32_writev(u32 fd, u32 vector, s32 count); - asmlinkage int sunos_read(unsigned int fd, u32 buf, u32 count) { int ret; @@ -1218,7 +1212,7 @@ asmlinkage int sunos_readv(u32 fd, u32 v { int ret; - ret = check_nonblock(sys32_readv(fd, vector, count), fd); + ret = check_nonblock(compat_sys_readv(fd, (void*)A(vector), count), fd); return ret; } @@ -1234,7 +1228,7 @@ asmlinkage int sunos_writev(u32 fd, u32 { int ret; - ret = check_nonblock(sys32_writev(fd, vector, count), fd); + ret = check_nonblock(compat_sys_writev(fd, (void*)A(vector), count), fd); return ret; } --- linux-2.6.6/arch/sparc64/kernel/systbls.S 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/sparc64/kernel/systbls.S 2004-05-10 01:19:35.185390064 -0700 @@ -37,13 +37,13 @@ sys_call_table32: .word sys_madvise, sys_vhangup, sys32_truncate64, sys_mincore, sys32_getgroups16 /*80*/ .word sys32_setgroups16, sys_getpgrp, sys_setgroups, compat_sys_setitimer, sys32_ftruncate64 .word sys_swapon, compat_sys_getitimer, sys_setuid, sys_sethostname, sys_setgid -/*90*/ .word sys_dup2, sys_setfsuid, compat_sys_fcntl, sys32_select, sys_setfsgid +/*90*/ .word sys_dup2, sys_setfsuid, compat_sys_fcntl, compat_sys_select, sys_setfsgid .word sys_fsync, sys_setpriority32, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall /*100*/ .word sys_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending .word sys32_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys_setresuid, sys_getresuid /*110*/ .word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall .word sys_getgroups, sys32_gettimeofday, compat_sys_getrusage, sys_nis_syscall, sys_getcwd -/*120*/ .word sys32_readv, sys32_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod +/*120*/ .word compat_sys_readv, compat_sys_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod .word sys_nis_syscall, sys32_setreuid16, sys32_setregid16, sys_rename, sys_truncate /*130*/ .word sys_ftruncate, sys_flock, sys_lstat64, sys_nis_syscall, sys_nis_syscall .word sys_nis_syscall, sys_mkdir, sys_rmdir, sys32_utimes, sys_stat64 @@ -65,11 +65,11 @@ sys_call_table32: .word sys32_ipc, sys32_sigreturn, sys_clone, sys_nis_syscall, sys32_adjtimex /*220*/ .word compat_sys_sigprocmask, sys_ni_syscall, sys32_delete_module, sys_ni_syscall, sys_getpgid .word sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys32_setfsuid16, sys32_setfsgid16 -/*230*/ .word sys32_select, sys_time, sys_nis_syscall, sys_stime, compat_statfs64 +/*230*/ .word compat_sys_select, sys_time, sys_nis_syscall, sys_stime, compat_statfs64 .word compat_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall /*240*/ .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler .word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep -/*250*/ .word sys32_mremap, sys32_sysctl, sys_getsid, sys_fdatasync, sys32_nfsservctl +/*250*/ .word sys32_mremap, sys32_sysctl, sys_getsid, sys_fdatasync, compat_sys_nfsservctl .word sys_ni_syscall, compat_clock_settime, compat_clock_gettime, compat_clock_getres, compat_clock_nanosleep /*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, compat_timer_settime, compat_timer_gettime, sys_timer_getoverrun .word sys_timer_delete, sys32_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy --- linux-2.6.6/arch/sparc64/kernel/time.c 2004-03-10 20:41:26.000000000 -0800 +++ 25/arch/sparc64/kernel/time.c 2004-05-10 01:19:01.791466712 -0700 @@ -1035,7 +1035,8 @@ static int sparc64_cpufreq_notifier(stru ft->clock_tick_ref = cpu_data(cpu).clock_tick; } if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) || - (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) { + (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) || + (val == CPUFREQ_RESUMECHANGE)) { cpu_data(cpu).udelay_val = cpufreq_scale(ft->udelay_val_ref, ft->ref_freq, --- linux-2.6.6/arch/sparc64/lib/rwlock.S 2003-11-23 19:03:00.000000000 -0800 +++ 25/arch/sparc64/lib/rwlock.S 2004-05-10 01:19:27.997482792 -0700 @@ -85,5 +85,20 @@ __write_trylock_succeed: __write_trylock_fail: retl mov 0, %o0 + + .globl __read_trylock +__read_trylock: /* %o0 = lock_ptr */ + ldsw [%o0], %g5 + brlz,pn %g5, 100f + add %g5, 1, %g7 + cas [%o0], %g5, %g7 + cmp %g5, %g7 + bne,pn %icc, __read_trylock + membar #StoreLoad | #StoreStore + retl + mov 1, %o0 +100: retl + mov 0, %o0 + rwlock_impl_end: --- linux-2.6.6/arch/sparc64/mm/hugetlbpage.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/sparc64/mm/hugetlbpage.c 2004-05-10 01:19:56.318177392 -0700 @@ -245,8 +245,9 @@ int hugetlb_prefault(struct address_spac goto out; } ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC); - unlock_page(page); - if (ret) { + if (! ret) { + unlock_page(page); + } else { hugetlb_put_quota(mapping); free_huge_page(page); goto out; --- linux-2.6.6/arch/sparc/kernel/process.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/sparc/kernel/process.c 2004-05-10 01:19:31.145004296 -0700 @@ -721,8 +721,7 @@ unsigned long get_wchan(struct task_stru break; rw = (struct reg_window *) fp; pc = rw->ins[7]; - if (pc < ((unsigned long) scheduling_functions_start_here) || - pc >= ((unsigned long) scheduling_functions_end_here)) { + if (!in_sched_functions(pc)) { ret = pc; goto out; } --- linux-2.6.6/arch/sparc/kernel/setup.c 2004-04-03 20:39:11.000000000 -0800 +++ 25/arch/sparc/kernel/setup.c 2004-05-10 01:19:18.578914632 -0700 @@ -244,8 +244,7 @@ extern unsigned short ram_flags; extern int root_mountflags; -char saved_command_line[256]; -char reboot_command[256]; +char reboot_command[COMMAND_LINE_SIZE]; enum sparc_cpu sparc_cpu_model; struct tt_entry *sparc_ttable; --- linux-2.6.6/arch/sparc/kernel/sparc_ksyms.c 2004-04-03 20:39:11.000000000 -0800 +++ 25/arch/sparc/kernel/sparc_ksyms.c 2004-05-10 01:19:18.579914480 -0700 @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -74,7 +75,6 @@ extern void *__memscan_zero(void *, size extern void *__memscan_generic(void *, int, size_t); extern int __memcmp(const void *, const void *, __kernel_size_t); extern int __strncmp(const char *, const char *, __kernel_size_t); -extern char saved_command_line[]; extern void bcopy (const char *, char *, int); extern int __ashrdi3(int, int); --- linux-2.6.6/arch/um/drivers/harddog_kern.c 2003-06-14 12:18:24.000000000 -0700 +++ 25/arch/um/drivers/harddog_kern.c 2004-05-10 01:19:57.839946048 -0700 @@ -71,7 +71,7 @@ static int harddog_open(struct inode *in if(timer_alive) return -EBUSY; #ifdef CONFIG_HARDDOG_NOWAYOUT - MOD_INC_USE_COUNT; + __module_get(THIS_MODULE); #endif #ifdef CONFIG_MCONSOLE --- linux-2.6.6/arch/um/drivers/net_kern.c 2004-03-10 20:41:26.000000000 -0800 +++ 25/arch/um/drivers/net_kern.c 2004-05-10 01:19:57.425009128 -0700 @@ -124,7 +124,6 @@ static int uml_net_open(struct net_devic spin_lock(&opened_lock); list_add(&lp->list, &opened); spin_unlock(&opened_lock); - MOD_INC_USE_COUNT; out: spin_unlock(&lp->lock); return(err); @@ -144,7 +143,6 @@ static int uml_net_close(struct net_devi list_del(&lp->list); spin_unlock(&opened_lock); - MOD_DEC_USE_COUNT; spin_unlock(&lp->lock); return 0; } --- linux-2.6.6/arch/um/kernel/smp.c 2003-10-08 15:07:08.000000000 -0700 +++ 25/arch/um/kernel/smp.c 2004-05-10 01:19:49.911151408 -0700 @@ -266,6 +266,9 @@ int smp_call_function(void (*_func)(void if (!cpus) return 0; + /* Can deadlock when called with interrupts disabled */ + WARN_ON(irqs_disabled()); + spin_lock_bh(&call_lock); atomic_set(&scf_started, 0); atomic_set(&scf_finished, 0); --- linux-2.6.6/arch/um/kernel/user_util.c 2003-06-14 12:17:59.000000000 -0700 +++ 25/arch/um/kernel/user_util.c 2004-05-10 01:19:18.579914480 -0700 @@ -34,7 +34,6 @@ #define COMMAND_LINE_SIZE _POSIX_ARG_MAX /* Changed in linux_main and setup_arch, which run before SMP is started */ -char saved_command_line[COMMAND_LINE_SIZE] = { 0 }; char command_line[COMMAND_LINE_SIZE] = { 0 }; void add_arg(char *cmd_line, char *arg) --- linux-2.6.6/arch/v850/kernel/process.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/v850/kernel/process.c 2004-05-10 01:19:31.145004296 -0700 @@ -203,8 +203,8 @@ int sys_execve (char *name, char **argv, /* * These bracket the sleeping functions.. */ -#define first_sched ((unsigned long) scheduling_functions_start_here) -#define last_sched ((unsigned long) scheduling_functions_end_here) +#define first_sched ((unsigned long)__sched_text_start) +#define last_sched ((unsigned long)__sched_text_end) unsigned long get_wchan (struct task_struct *p) { --- linux-2.6.6/arch/v850/kernel/setup.c 2004-02-17 20:48:42.000000000 -0800 +++ 25/arch/v850/kernel/setup.c 2004-05-10 01:19:18.580914328 -0700 @@ -20,6 +20,7 @@ #include #include #include +#include #include @@ -40,8 +41,7 @@ extern char _root_fs_image_start __attri extern char _root_fs_image_end __attribute__ ((__weak__)); -char command_line[512]; -char saved_command_line[512]; +char command_line[COMMAND_LINE_SIZE]; /* Memory not used by the kernel. */ static unsigned long total_ram_pages; --- linux-2.6.6/arch/x86_64/boot/compressed/misc.c 2003-11-09 16:45:05.000000000 -0800 +++ 25/arch/x86_64/boot/compressed/misc.c 2004-05-10 01:19:50.731026768 -0700 @@ -92,7 +92,7 @@ static unsigned long output_ptr = 0; static void *malloc(int size); static void free(void *where); -static void puts(const char *); +static void putstr(const char *); extern int end; static long free_mem_ptr = (long)&end; @@ -153,7 +153,7 @@ static void scroll(void) vidmem[i] = ' '; } -static void puts(const char *s) +static void putstr(const char *s) { int x,y,pos; char c; @@ -270,9 +270,9 @@ static void flush_window(void) static void error(char *x) { - puts("\n\n"); - puts(x); - puts("\n\n -- System halted"); + putstr("\n\n"); + putstr(x); + putstr("\n\n -- System halted"); while(1); } @@ -346,9 +346,9 @@ int decompress_kernel(struct moveparams else setup_output_buffer_if_we_run_high(mv); makecrc(); - puts(".\nDecompressing Linux..."); + putstr(".\nDecompressing Linux..."); gunzip(); - puts("done.\nBooting the kernel.\n"); + putstr("done.\nBooting the kernel.\n"); if (high_loaded) close_output_buffer_if_we_run_high(mv); return high_loaded; } --- linux-2.6.6/arch/x86_64/boot/setup.S 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/x86_64/boot/setup.S 2004-05-10 01:19:37.065104304 -0700 @@ -132,7 +132,7 @@ ramdisk_image: .long 0 # address of loa ramdisk_size: .long 0 # its size in bytes bootsect_kludge: - .word bootsect_helper, SETUPSEG + .long 0 # obsolete heap_end_ptr: .word modelist+1024 # (Header version 0x0201 or later) # space from here (exclusive) down to @@ -759,87 +759,6 @@ default_switch: outb %al, $0x70 lret -# This routine only gets called, if we get loaded by the simple -# bootsect loader _and_ have a bzImage to load. -# Because there is no place left in the 512 bytes of the boot sector, -# we must emigrate to code space here. -bootsect_helper: - cmpw $0, %cs:bootsect_es - jnz bootsect_second - - movb $0x20, %cs:type_of_loader - movw %es, %ax - shrw $4, %ax - movb %ah, %cs:bootsect_src_base+2 - movw %es, %ax - movw %ax, %cs:bootsect_es - subw $SYSSEG, %ax - lret # nothing else to do for now - -bootsect_second: - pushw %cx - pushw %si - pushw %bx - testw %bx, %bx # 64K full? - jne bootsect_ex - - movw $0x8000, %cx # full 64K, INT15 moves words - pushw %cs - popw %es - movw $bootsect_gdt, %si - movw $0x8700, %ax - int $0x15 - jc bootsect_panic # this, if INT15 fails - - movw %cs:bootsect_es, %es # we reset %es to always point - incb %cs:bootsect_dst_base+2 # to 0x10000 -bootsect_ex: - movb %cs:bootsect_dst_base+2, %ah - shlb $4, %ah # we now have the number of - # moved frames in %ax - xorb %al, %al - popw %bx - popw %si - popw %cx - lret - -bootsect_gdt: - .word 0, 0, 0, 0 - .word 0, 0, 0, 0 - -bootsect_src: - .word 0xffff - -bootsect_src_base: - .byte 0x00, 0x00, 0x01 # base = 0x010000 - .byte 0x93 # typbyte - .word 0 # limit16,base24 =0 - -bootsect_dst: - .word 0xffff - -bootsect_dst_base: - .byte 0x00, 0x00, 0x10 # base = 0x100000 - .byte 0x93 # typbyte - .word 0 # limit16,base24 =0 - .word 0, 0, 0, 0 # BIOS CS - .word 0, 0, 0, 0 # BIOS DS - -bootsect_es: - .word 0 - -bootsect_panic: - pushw %cs - popw %ds - cld - leaw bootsect_panic_mess, %si - call prtstr - -bootsect_panic_loop: - jmp bootsect_panic_loop - -bootsect_panic_mess: - .string "INT15 refuses to access high mem, giving up." # This routine checks that the keyboard command queue is empty # (after emptying the output buffers) --- linux-2.6.6/arch/x86_64/ia32/ia32_binfmt.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/x86_64/ia32/ia32_binfmt.c 2004-05-10 01:19:12.689809912 -0700 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -365,7 +366,7 @@ int setup_arg_pages(struct linux_binprm mpnt->vm_ops = NULL; mpnt->vm_pgoff = 0; mpnt->vm_file = NULL; - INIT_LIST_HEAD(&mpnt->shared); + mpol_set_vma_default(mpnt); mpnt->vm_private_data = (void *) 0; insert_vm_struct(mm, mpnt); mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT; --- linux-2.6.6/arch/x86_64/ia32/ia32entry.S 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/x86_64/ia32/ia32entry.S 2004-05-10 01:19:35.186389912 -0700 @@ -447,11 +447,11 @@ ia32_sys_call_table: .quad sys_setfsgid16 .quad sys_llseek /* 140 */ .quad sys32_getdents - .quad sys32_select + .quad compat_sys_select .quad sys_flock .quad sys_msync - .quad sys32_readv /* 145 */ - .quad sys32_writev + .quad compat_sys_readv /* 145 */ + .quad compat_sys_writev .quad sys_getsid .quad sys_fdatasync .quad sys32_sysctl /* sysctl */ @@ -474,7 +474,7 @@ ia32_sys_call_table: .quad sys32_vm86_warning /* vm86 */ .quad quiet_ni_syscall /* query_module */ .quad sys_poll - .quad sys32_nfsservctl + .quad compat_sys_nfsservctl .quad sys_setresgid16 /* 170 */ .quad sys_getresgid16 .quad sys_prctl --- linux-2.6.6/arch/x86_64/ia32/ia32_signal.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/x86_64/ia32/ia32_signal.c 2004-05-10 01:19:50.732026616 -0700 @@ -98,6 +98,7 @@ int ia32_copy_siginfo_to_user(siginfo_t3 int ia32_copy_siginfo_from_user(siginfo_t *to, siginfo_t32 __user *from) { int err; + u32 ptr32; if (!access_ok (VERIFY_READ, from, sizeof(siginfo_t32))) return -EFAULT; @@ -107,7 +108,8 @@ int ia32_copy_siginfo_from_user(siginfo_ err |= __get_user(to->si_pid, &from->si_pid); err |= __get_user(to->si_uid, &from->si_uid); - err |= __get_user((u32)(u64)to->si_ptr, &from->si_ptr); + err |= __get_user(ptr32, &from->si_ptr); + to->si_ptr = (void*)(u64)ptr32; return err; } --- linux-2.6.6/arch/x86_64/ia32/sys_ia32.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/x86_64/ia32/sys_ia32.c 2004-05-10 01:19:35.188389608 -0700 @@ -606,107 +606,6 @@ out: return error; } -/* - * We can actually return ERESTARTSYS instead of EINTR, but I'd - * like to be certain this leads to no problems. So I return - * EINTR just for safety. - * - * Update: ERESTARTSYS breaks at least the xview clock binary, so - * I'm trying ERESTARTNOHAND which restart only when you want to. - */ -#define MAX_SELECT_SECONDS \ - ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1) -#define ROUND_UP_TIME(x,y) (((x)+(y)-1)/(y)) - -asmlinkage long -sys32_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct compat_timeval *tvp32) -{ - fd_set_bits fds; - char *bits; - long timeout; - int ret, size; - - timeout = MAX_SCHEDULE_TIMEOUT; - if (tvp32) { - time_t sec, usec; - - get_user(sec, &tvp32->tv_sec); - get_user(usec, &tvp32->tv_usec); - - ret = -EINVAL; - if (sec < 0 || usec < 0) - goto out_nofds; - - if ((unsigned long) sec < MAX_SELECT_SECONDS) { - timeout = ROUND_UP_TIME(usec, 1000000/HZ); - timeout += sec * (unsigned long) HZ; - } - } - - ret = -EINVAL; - if (n < 0) - goto out_nofds; - - if (n > current->files->max_fdset) - n = current->files->max_fdset; - - /* - * We need 6 bitmaps (in/out/ex for both incoming and outgoing), - * since we used fdset we need to allocate memory in units of - * long-words. - */ - ret = -ENOMEM; - size = FDS_BYTES(n); - bits = kmalloc(6 * size, GFP_KERNEL); - if (!bits) - goto out_nofds; - fds.in = (unsigned long *) bits; - fds.out = (unsigned long *) (bits + size); - fds.ex = (unsigned long *) (bits + 2*size); - fds.res_in = (unsigned long *) (bits + 3*size); - fds.res_out = (unsigned long *) (bits + 4*size); - fds.res_ex = (unsigned long *) (bits + 5*size); - - if ((ret = get_fd_set(n, inp, fds.in)) || - (ret = get_fd_set(n, outp, fds.out)) || - (ret = get_fd_set(n, exp, fds.ex))) - goto out; - zero_fd_set(n, fds.res_in); - zero_fd_set(n, fds.res_out); - zero_fd_set(n, fds.res_ex); - - ret = do_select(n, &fds, &timeout); - - if (tvp32 && !(current->personality & STICKY_TIMEOUTS)) { - time_t sec = 0, usec = 0; - if (timeout) { - sec = timeout / HZ; - usec = timeout % HZ; - usec *= (1000000/HZ); - } - put_user(sec, (int *)&tvp32->tv_sec); - put_user(usec, (int *)&tvp32->tv_usec); - } - - if (ret < 0) - goto out; - if (!ret) { - ret = -ERESTARTNOHAND; - if (signal_pending(current)) - goto out; - ret = 0; - } - - set_fd_set(n, inp, fds.res_in); - set_fd_set(n, outp, fds.res_out); - set_fd_set(n, exp, fds.res_ex); - -out: - kfree(bits); -out_nofds: - return ret; -} - struct sel_arg_struct { unsigned int n; unsigned int inp; @@ -722,106 +621,8 @@ sys32_old_select(struct sel_arg_struct * if (copy_from_user(&a, arg, sizeof(a))) return -EFAULT; - return sys32_select(a.n, (fd_set *)A(a.inp), (fd_set *)A(a.outp), (fd_set *)A(a.exp), - (struct compat_timeval *)A(a.tvp)); -} - -static struct iovec * -get_compat_iovec(struct compat_iovec *iov32, struct iovec *iov_buf, u32 *count, int type, int *errp) -{ - int i; - u32 buf, len; - struct iovec *ivp, *iov; - unsigned long totlen; - - /* Get the "struct iovec" from user memory */ - - *errp = 0; - if (!*count) - return 0; - *errp = -EINVAL; - if (*count > UIO_MAXIOV) - return(struct iovec *)0; - *errp = -EFAULT; - if(verify_area(VERIFY_READ, iov32, sizeof(struct compat_iovec)*(*count))) - return(struct iovec *)0; - if (*count > UIO_FASTIOV) { - *errp = -ENOMEM; - iov = kmalloc(*count*sizeof(struct iovec), GFP_KERNEL); - if (!iov) - return((struct iovec *)0); - } else - iov = iov_buf; - - ivp = iov; - totlen = 0; - for (i = 0; i < *count; i++) { - *errp = __get_user(len, &iov32->iov_len) | - __get_user(buf, &iov32->iov_base); - if (*errp) - goto error; - *errp = verify_area(type, (void *)A(buf), len); - if (*errp) { - if (i > 0) { - *count = i; - break; - } - goto error; - } - /* SuS checks: */ - *errp = -EINVAL; - if ((int)len < 0) - goto error; - if ((totlen += len) >= 0x7fffffff) - goto error; - ivp->iov_base = (void *)A(buf); - ivp->iov_len = (__kernel_size_t)len; - iov32++; - ivp++; - } - *errp = 0; - return(iov); - -error: - if (iov != iov_buf) - kfree(iov); - return NULL; -} - -asmlinkage long -sys32_readv(int fd, struct compat_iovec *vector, u32 count) -{ - struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov; - int ret; - mm_segment_t old_fs = get_fs(); - - if ((iov = get_compat_iovec(vector, iovstack, &count, VERIFY_WRITE, &ret)) == NULL) - return ret; - set_fs(KERNEL_DS); - ret = sys_readv(fd, iov, count); - set_fs(old_fs); - if (iov != iovstack) - kfree(iov); - return ret; -} - -asmlinkage long -sys32_writev(int fd, struct compat_iovec *vector, u32 count) -{ - struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov; - int ret; - mm_segment_t old_fs = get_fs(); - - if ((iov = get_compat_iovec(vector, iovstack, &count, VERIFY_READ, &ret)) == NULL) - return ret; - set_fs(KERNEL_DS); - ret = sys_writev(fd, iov, count); - set_fs(old_fs); - if (iov != iovstack) - kfree(iov); - return ret; + return compat_sys_select(a.n, compat_ptr(a.inp), compat_ptr(a.outp), + compat_ptr(a.exp), compat_ptr(a.tvp)); } /* @@ -1323,93 +1124,22 @@ long sys32_ustat(unsigned dev, struct us return ret; } -static int nargs(u32 src, char **dst) -{ - int cnt; - u32 val; - - cnt = 0; - do { - int ret = get_user(val, (__u32 *)(u64)src); - if (ret) - return ret; - if (dst) - dst[cnt] = (char *)(u64)val; - cnt++; - src += 4; - if (cnt >= (MAX_ARG_PAGES*PAGE_SIZE)/sizeof(void*)) - return -E2BIG; - } while(val); - if (dst) - dst[cnt-1] = 0; - return cnt; -} - -asmlinkage long sys32_execve(char *name, u32 argv, u32 envp, struct pt_regs regs) -{ - mm_segment_t oldseg; - char **buf = NULL; - int na = 0,ne = 0; - int ret; - unsigned sz = 0; - - if (argv) { - na = nargs(argv, NULL); - if (na < 0) - return -EFAULT; - } - if (envp) { - ne = nargs(envp, NULL); - if (ne < 0) - return -EFAULT; - } - - if (argv || envp) { - sz = (na+ne)*sizeof(void *); - if (sz > PAGE_SIZE) - buf = vmalloc(sz); - else - buf = kmalloc(sz, GFP_KERNEL); - if (!buf) - return -ENOMEM; - } - - if (argv) { - ret = nargs(argv, buf); - if (ret < 0) - goto free; - } - - if (envp) { - ret = nargs(envp, buf + na); - if (ret < 0) - goto free; - } - - name = getname(name); - ret = PTR_ERR(name); - if (IS_ERR(name)) - goto free; - - oldseg = get_fs(); - set_fs(KERNEL_DS); - ret = do_execve(name, argv ? buf : NULL, envp ? buf+na : NULL, ®s); - set_fs(oldseg); +asmlinkage long sys32_execve(char *name, compat_uptr_t __user *argv, + compat_uptr_t __user *envp, struct pt_regs regs) +{ + long error; + char * filename; - if (ret == 0) + filename = getname(name); + error = PTR_ERR(filename); + if (IS_ERR(filename)) + return error; + error = compat_do_execve(filename, argv, envp, ®s); + if (error == 0) current->ptrace &= ~PT_DTRACE; - - putname(name); - -free: - if (argv || envp) { - if (sz > PAGE_SIZE) - vfree(buf); - else - kfree(buf); - } - return ret; -} + putname(filename); + return error; +} asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp, struct pt_regs regs) { @@ -1436,233 +1166,6 @@ long sys32_kill(int pid, int sig) } -#if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE) -/* Stuff for NFS server syscalls... */ -struct nfsctl_svc32 { - u16 svc32_port; - s32 svc32_nthreads; -}; - -struct nfsctl_client32 { - s8 cl32_ident[NFSCLNT_IDMAX+1]; - s32 cl32_naddr; - struct in_addr cl32_addrlist[NFSCLNT_ADDRMAX]; - s32 cl32_fhkeytype; - s32 cl32_fhkeylen; - u8 cl32_fhkey[NFSCLNT_KEYMAX]; -}; - -struct nfsctl_export32 { - s8 ex32_client[NFSCLNT_IDMAX+1]; - s8 ex32_path[NFS_MAXPATHLEN+1]; - compat_dev_t ex32_dev; - compat_ino_t ex32_ino; - s32 ex32_flags; - compat_pid_t ex32_anon_uid; - compat_gid_t ex32_anon_gid; -}; - -struct nfsctl_fdparm32 { - struct sockaddr gd32_addr; - s8 gd32_path[NFS_MAXPATHLEN+1]; - s32 gd32_version; -}; - -struct nfsctl_fsparm32 { - struct sockaddr gd32_addr; - s8 gd32_path[NFS_MAXPATHLEN+1]; - s32 gd32_maxlen; -}; - -struct nfsctl_arg32 { - s32 ca32_version; /* safeguard */ - union { - struct nfsctl_svc32 u32_svc; - struct nfsctl_client32 u32_client; - struct nfsctl_export32 u32_export; - struct nfsctl_fdparm32 u32_getfd; - struct nfsctl_fsparm32 u32_getfs; - } u; -#define ca32_svc u.u32_svc -#define ca32_client u.u32_client -#define ca32_export u.u32_export -#define ca32_getfd u.u32_getfd -#define ca32_getfs u.u32_getfs -}; - -union nfsctl_res32 { - __u8 cr32_getfh[NFS_FHSIZE]; - struct knfsd_fh cr32_getfs; -}; - -static int nfs_svc32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) -{ - int err; - - err = get_user(karg->ca_version, &arg32->ca32_version); - err |= __get_user(karg->ca_svc.svc_port, &arg32->ca32_svc.svc32_port); - err |= __get_user(karg->ca_svc.svc_nthreads, &arg32->ca32_svc.svc32_nthreads); - return err; -} - -static int nfs_clnt32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) -{ - int err; - - err = get_user(karg->ca_version, &arg32->ca32_version); - err |= copy_from_user(&karg->ca_client.cl_ident[0], - &arg32->ca32_client.cl32_ident[0], - NFSCLNT_IDMAX); - err |= __get_user(karg->ca_client.cl_naddr, &arg32->ca32_client.cl32_naddr); - err |= copy_from_user(&karg->ca_client.cl_addrlist[0], - &arg32->ca32_client.cl32_addrlist[0], - (sizeof(struct in_addr) * NFSCLNT_ADDRMAX)); - err |= __get_user(karg->ca_client.cl_fhkeytype, - &arg32->ca32_client.cl32_fhkeytype); - err |= __get_user(karg->ca_client.cl_fhkeylen, - &arg32->ca32_client.cl32_fhkeylen); - err |= copy_from_user(&karg->ca_client.cl_fhkey[0], - &arg32->ca32_client.cl32_fhkey[0], - NFSCLNT_KEYMAX); - return err; -} - -static int nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) -{ - int err; - - err = get_user(karg->ca_version, &arg32->ca32_version); - err |= copy_from_user(&karg->ca_export.ex_client[0], - &arg32->ca32_export.ex32_client[0], - NFSCLNT_IDMAX); - err |= copy_from_user(&karg->ca_export.ex_path[0], - &arg32->ca32_export.ex32_path[0], - NFS_MAXPATHLEN); - err |= __get_user(karg->ca_export.ex_dev, - &arg32->ca32_export.ex32_dev); - err |= __get_user(karg->ca_export.ex_ino, - &arg32->ca32_export.ex32_ino); - err |= __get_user(karg->ca_export.ex_flags, - &arg32->ca32_export.ex32_flags); - err |= __get_user(karg->ca_export.ex_anon_uid, - &arg32->ca32_export.ex32_anon_uid); - err |= __get_user(karg->ca_export.ex_anon_gid, - &arg32->ca32_export.ex32_anon_gid); - SET_UID(karg->ca_export.ex_anon_uid, karg->ca_export.ex_anon_uid); - SET_GID(karg->ca_export.ex_anon_gid, karg->ca_export.ex_anon_gid); - return err; -} - - -static int nfs_getfd32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) -{ - int err; - - err = get_user(karg->ca_version, &arg32->ca32_version); - err |= copy_from_user(&karg->ca_getfd.gd_addr, - &arg32->ca32_getfd.gd32_addr, - (sizeof(struct sockaddr))); - err |= copy_from_user(&karg->ca_getfd.gd_path, - &arg32->ca32_getfd.gd32_path, - (NFS_MAXPATHLEN+1)); - err |= get_user(karg->ca_getfd.gd_version, - &arg32->ca32_getfd.gd32_version); - return err; -} - -static int nfs_getfs32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) -{ - int err; - - err = get_user(karg->ca_version, &arg32->ca32_version); - err |= copy_from_user(&karg->ca_getfs.gd_addr, - &arg32->ca32_getfs.gd32_addr, - (sizeof(struct sockaddr))); - err |= copy_from_user(&karg->ca_getfs.gd_path, - &arg32->ca32_getfs.gd32_path, - (NFS_MAXPATHLEN+1)); - err |= get_user(karg->ca_getfs.gd_maxlen, - &arg32->ca32_getfs.gd32_maxlen); - return err; -} - -/* This really doesn't need translations, we are only passing - * back a union which contains opaque nfs file handle data. - */ -static int nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32) -{ - return copy_to_user(res32, kres, sizeof(*res32)) ? -EFAULT : 0; -} - -long asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32) -{ - struct nfsctl_arg *karg = NULL; - union nfsctl_res *kres = NULL; - mm_segment_t oldfs; - int err; - - karg = kmalloc(sizeof(*karg), GFP_USER); - if(!karg) - return -ENOMEM; - if(res32) { - kres = kmalloc(sizeof(*kres), GFP_USER); - if(!kres) { - kfree(karg); - return -ENOMEM; - } - } - switch(cmd) { - case NFSCTL_SVC: - err = nfs_svc32_trans(karg, arg32); - break; - case NFSCTL_ADDCLIENT: - err = nfs_clnt32_trans(karg, arg32); - break; - case NFSCTL_DELCLIENT: - err = nfs_clnt32_trans(karg, arg32); - break; - case NFSCTL_EXPORT: - case NFSCTL_UNEXPORT: - err = nfs_exp32_trans(karg, arg32); - break; - case NFSCTL_GETFD: - err = nfs_getfd32_trans(karg, arg32); - break; - case NFSCTL_GETFS: - err = nfs_getfs32_trans(karg, arg32); - break; - default: - err = -EINVAL; - break; - } - if(err) - goto done; - oldfs = get_fs(); - set_fs(KERNEL_DS); - err = sys_nfsservctl(cmd, karg, kres); - set_fs(oldfs); - - if (err) - goto done; - - if((cmd == NFSCTL_GETFD) || - (cmd == NFSCTL_GETFS)) - err = nfs_getfh32_res_trans(kres, res32); - -done: - if(karg) - kfree(karg); - if(kres) - kfree(kres); - return err; -} -#else /* !NFSD */ -long asmlinkage sys32_nfsservctl(int cmd, void *notused, void *notused2) -{ - return sys_ni_syscall(); -} -#endif - long sys32_io_setup(unsigned nr_reqs, u32 *ctx32p) { long ret; --- linux-2.6.6/arch/x86_64/Kconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/x86_64/Kconfig 2004-05-10 01:19:24.524010840 -0700 @@ -239,6 +239,16 @@ config PREEMPT Say Y here if you are feeling brave and building a kernel for a desktop, embedded or real-time system. Say N if you are unsure. +config SCHED_SMT + bool "SMT (Hyperthreading) scheduler support" + depends on SMP + default off + help + SMT scheduler support improves the CPU scheduler's decision making + when dealing with Intel Pentium 4 chips with HyperThreading at a + cost of slightly increased overhead in some places. If unsure say + N here. + # someone write a better help text please. config K8_NUMA bool "K8 NUMA support" @@ -446,12 +456,26 @@ config INIT_DEBUG config DEBUG_INFO bool "Compile the kernel with debug info" depends on DEBUG_KERNEL + default n help If you say Y here the resulting kernel image will include debugging info resulting in a larger kernel image. Say Y here only if you plan to use gdb to debug the kernel. Please note that this option requires new binutils. If you don't debug the kernel, you can say N. + +config SCHEDSTATS + bool "Collect scheduler statistics" + depends on PROC_FS + default y + help + If you say Y here, additional code will be inserted into the + scheduler and related routines to collect statistics about + scheduler behavior and provide them in /proc/schedstat. These + stats may be useful for both tuning and debugging the scheduler + If you aren't debugging the scheduler or trying to tune a specific + application, you can say N to avoid the very slight overhead + this adds. config FRAME_POINTER bool "Compile the kernel with frame pointers" @@ -484,9 +508,8 @@ config IOMMU_LEAK help Add a simple leak tracer to the IOMMU code. This is useful when you are debugging a buggy device driver that leaks IOMMU mappings. - -#config X86_REMOTE_DEBUG -# bool "kgdb debugging stub" + +source "arch/x86_64/Kconfig.kgdb" endmenu --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/arch/x86_64/Kconfig.kgdb 2004-05-10 01:19:07.411612320 -0700 @@ -0,0 +1,176 @@ +config KGDB + bool "Include kgdb kernel debugger" + depends on DEBUG_KERNEL + select DEBUG_INFO + help + If you say Y here, the system will be compiled with the debug + option (-g) and a debugging stub will be included in the + kernel. This stub communicates with gdb on another (host) + computer via a serial port. The host computer should have + access to the kernel binary file (vmlinux) and a serial port + that is connected to the target machine. Gdb can be made to + configure the serial port or you can use stty and setserial to + do this. See the 'target' command in gdb. This option also + configures in the ability to request a breakpoint early in the + boot process. To request the breakpoint just include 'kgdb' + as a boot option when booting the target machine. The system + will then break as soon as it looks at the boot options. This + option also installs a breakpoint in panic and sends any + kernel faults to the debugger. For more information see the + Documentation/i386/kgdb.txt file. + +choice + depends on KGDB + prompt "Debug serial port BAUD" + default KGDB_115200BAUD + help + Gdb and the kernel stub need to agree on the baud rate to be + used. Some systems (x86 family at this writing) allow this to + be configured. + +config KGDB_9600BAUD + bool "9600" + +config KGDB_19200BAUD + bool "19200" + +config KGDB_38400BAUD + bool "38400" + +config KGDB_57600BAUD + bool "57600" + +config KGDB_115200BAUD + bool "115200" +endchoice + +config KGDB_PORT + hex "hex I/O port address of the debug serial port" + depends on KGDB + default 3f8 + help + Some systems (x86 family at this writing) allow the port + address to be configured. The number entered is assumed to be + hex, don't put 0x in front of it. The standard address are: + COM1 3f8 , irq 4 and COM2 2f8 irq 3. Setserial /dev/ttySx + will tell you what you have. It is good to test the serial + connection with a live system before trying to debug. + +config KGDB_IRQ + int "IRQ of the debug serial port" + depends on KGDB + default 4 + help + This is the irq for the debug port. If everything is working + correctly and the kernel has interrupts on a control C to the + port should cause a break into the kernel debug stub. + +config DEBUG_INFO + bool + depends on KGDB + default y + +config KGDB_MORE + bool "Add any additional compile options" + depends on KGDB + default n + help + Saying yes here turns on the ability to enter additional + compile options. + + +config KGDB_OPTIONS + depends on KGDB_MORE + string "Additional compile arguments" + default "-O1" + help + This option allows you enter additional compile options for + the whole kernel compile. Each platform will have a default + that seems right for it. For example on PPC "-ggdb -O1", and + for i386 "-O1". Note that by configuring KGDB "-g" is already + turned on. In addition, on i386 platforms + "-fomit-frame-pointer" is deleted from the standard compile + options. + +config NO_KGDB_CPUS + int "Number of CPUs" + depends on KGDB && SMP + default NR_CPUS + help + + This option sets the number of cpus for kgdb ONLY. It is used + to prune some internal structures so they look "nice" when + displayed with gdb. This is to overcome possibly larger + numbers that may have been entered above. Enter the real + number to get nice clean kgdb_info displays. + +config KGDB_TS + bool "Enable kgdb time stamp macros?" + depends on KGDB + default n + help + Kgdb event macros allow you to instrument your code with calls + to the kgdb event recording function. The event log may be + examined with gdb at a break point. Turning on this + capability also allows you to choose how many events to + keep. Kgdb always keeps the lastest events. + +choice + depends on KGDB_TS + prompt "Max number of time stamps to save?" + default KGDB_TS_128 + +config KGDB_TS_64 + bool "64" + +config KGDB_TS_128 + bool "128" + +config KGDB_TS_256 + bool "256" + +config KGDB_TS_512 + bool "512" + +config KGDB_TS_1024 + bool "1024" + +endchoice + +config STACK_OVERFLOW_TEST + bool "Turn on kernel stack overflow testing?" + depends on KGDB + default n + help + This option enables code in the front line interrupt handlers + to check for kernel stack overflow on interrupts and system + calls. This is part of the kgdb code on x86 systems. + +config KGDB_CONSOLE + bool "Enable serial console thru kgdb port" + depends on KGDB + default n + help + This option enables the command line "console=kgdb" option. + When the system is booted with this option in the command line + all kernel printk output is sent to gdb (as well as to other + consoles). For this to work gdb must be connected. For this + reason, this command line option will generate a breakpoint if + gdb has not yet connected. After the gdb continue command is + given all pent up console output will be printed by gdb on the + host machine. Neither this option, nor KGDB require the + serial driver to be configured. + +config KGDB_SYSRQ + bool "Turn on SysRq 'G' command to do a break?" + depends on KGDB + default y + help + This option includes an option in the SysRq code that allows + you to enter SysRq G which generates a breakpoint to the KGDB + stub. This will work if the keyboard is alive and can + interrupt the system. Because of constraints on when the + serial port interrupt can be enabled, this code may allow you + to interrupt the system before the serial port control C is + available. Just say yes here. + --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/arch/x86_64/kernel/domain.c 2004-05-10 01:19:24.365035008 -0700 @@ -0,0 +1,89 @@ +#include +#include + +/* Don't do any NUMA setup on Opteron right now. They seem to be + better off with flat scheduling. This is just for SMT. */ + +#ifdef CONFIG_SCHED_SMT + +static struct sched_group sched_group_cpus[NR_CPUS]; +static struct sched_group sched_group_phys[NR_CPUS]; +static DEFINE_PER_CPU(struct sched_domain, cpu_domains); +static DEFINE_PER_CPU(struct sched_domain, phys_domains); +__init void arch_init_sched_domains(void) +{ + int i; + struct sched_group *first = NULL, *last = NULL; + + /* Set up domains */ + for_each_cpu(i) { + struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); + struct sched_domain *phys_domain = &per_cpu(phys_domains, i); + + *cpu_domain = SD_SIBLING_INIT; + cpu_domain->span = cpu_sibling_map[i]; + cpu_domain->parent = phys_domain; + cpu_domain->groups = &sched_group_cpus[i]; + + *phys_domain = SD_CPU_INIT; + phys_domain->span = cpu_possible_map; + phys_domain->groups = &sched_group_phys[first_cpu(cpu_domain->span)]; + } + + /* Set up CPU (sibling) groups */ + for_each_cpu(i) { + struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); + int j; + first = last = NULL; + + if (i != first_cpu(cpu_domain->span)) + continue; + + for_each_cpu_mask(j, cpu_domain->span) { + struct sched_group *cpu = &sched_group_cpus[j]; + + cpus_clear(cpu->cpumask); + cpu_set(j, cpu->cpumask); + cpu->cpu_power = SCHED_LOAD_SCALE; + + if (!first) + first = cpu; + if (last) + last->next = cpu; + last = cpu; + } + last->next = first; + } + + first = last = NULL; + /* Set up physical groups */ + for_each_cpu(i) { + struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); + struct sched_group *cpu = &sched_group_phys[i]; + + if (i != first_cpu(cpu_domain->span)) + continue; + + cpu->cpumask = cpu_domain->span; + /* + * Make each extra sibling increase power by 10% of + * the basic CPU. This is very arbitrary. + */ + cpu->cpu_power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE*(cpus_weight(cpu->cpumask)-1) / 10; + + if (!first) + first = cpu; + if (last) + last->next = cpu; + last = cpu; + } + last->next = first; + + mb(); + for_each_cpu(i) { + struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); + cpu_attach_domain(cpu_domain, i); + } +} + +#endif --- linux-2.6.6/arch/x86_64/kernel/io_apic.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/x86_64/kernel/io_apic.c 2004-05-10 01:19:50.733026464 -0700 @@ -237,6 +237,7 @@ void __init check_ioapic(void) for (func = 0; func < 8; func++) { u32 class; u32 vendor; + u8 type; class = read_pci_config(num,slot,func, PCI_CLASS_REVISION); if (class == 0xffffffff) @@ -270,8 +271,8 @@ void __init check_ioapic(void) } /* No multi-function device? */ - u8 type = read_pci_config_byte(num,slot,func, - PCI_HEADER_TYPE); + type = read_pci_config_byte(num,slot,func, + PCI_HEADER_TYPE); if (!(type & 0x80)) break; } --- linux-2.6.6/arch/x86_64/kernel/irq.c 2004-03-10 20:41:27.000000000 -0800 +++ 25/arch/x86_64/kernel/irq.c 2004-05-10 01:19:07.412612168 -0700 @@ -405,6 +405,9 @@ out: spin_unlock(&desc->lock); irq_exit(); + + kgdb_process_breakpoint(); + return 1; } --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/arch/x86_64/kernel/kgdb_stub.c 2004-05-10 01:19:31.147003992 -0700 @@ -0,0 +1,2591 @@ +/* + * + * 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, 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. + * + */ + +/* + * Copyright (c) 2000 VERITAS Software Corporation. + * + */ +/**************************************************************************** + * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $ + * + * Module name: remcom.c $ + * Revision: 1.34 $ + * Date: 91/03/09 12:29:49 $ + * Contributor: Lake Stevens Instrument Division$ + * + * Description: low level support for gdb debugger. $ + * + * Considerations: only works on target hardware $ + * + * Written by: Glenn Engel $ + * Updated by: David Grothe + * Updated by: Robert Walsh + * Updated by: wangdi + * ModuleState: Experimental $ + * + * NOTES: See Below $ + * + * Modified for 386 by Jim Kingdon, Cygnus Support. + * Compatibility with 2.1.xx kernel by David Grothe + * + * Changes to allow auto initilization. All that is needed is that it + * be linked with the kernel and a break point (int 3) be executed. + * The header file defines BREAKPOINT to allow one to do + * this. It should also be possible, once the interrupt system is up, to + * call putDebugChar("+"). Once this is done, the remote debugger should + * get our attention by sending a ^C in a packet. George Anzinger + * + * Integrated into 2.2.5 kernel by Tigran Aivazian + * Added thread support, support for multiple processors, + * support for ia-32(x86) hardware debugging. + * Amit S. Kale ( akale@veritas.com ) + * + * Modified to support debugging over ethernet by Robert Walsh + * and wangdi , based on + * code by San Mehat. + * + * X86_64 changes from Andi Kleen's patch merged by Jim Houston + * (jim.houston@ccur.com). If it works thank Andi if its broken + * blame me. + * + * To enable debugger support, two things need to happen. One, a + * call to set_debug_traps() is necessary in order to allow any breakpoints + * or error conditions to be properly intercepted and reported to gdb. + * Two, a breakpoint needs to be generated to begin communication. This + * is most easily accomplished by a call to breakpoint(). Breakpoint() + * simulates a breakpoint by executing an int 3. + * + ************* + * + * The following gdb commands are supported: + * + * command function Return value + * + * g return the value of the CPU registers hex data or ENN + * G set the value of the CPU registers OK or ENN + * + * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN + * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN + * + * c Resume at current address SNN ( signal NN) + * cAA..AA Continue at address AA..AA SNN + * + * s Step one instruction SNN + * sAA..AA Step one instruction from AA..AA SNN + * + * k kill + * + * ? What was the last sigval ? SNN (signal NN) + * + * All commands and responses are sent with a packet which includes a + * checksum. A packet consists of + * + * $#. + * + * where + * :: + * :: < two hex digits computed as modulo 256 sum of > + * + * When a packet is received, it is first acknowledged with either '+' or '-'. + * '+' indicates a successful transfer. '-' indicates a failed transfer. + * + * Example: + * + * Host: Reply: + * $m0,10#2a +$00010203040506070809101112131415#42 + * + ****************************************************************************/ +#define KGDB_VERSION "<20030915.1651.33>" +#include +#include +#include /* for strcpy */ +#include +#include +#include +#include /* for linux pt_regs struct */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define Dearly_printk(x...) +int kgdb_enabled = 0; + +/************************************************************************ + * + * external low-level support routines + */ +typedef void (*Function) (void); /* pointer to a function */ + +/* Thread reference */ +typedef unsigned char threadref[8]; + +extern int tty_putDebugChar(int); /* write a single character */ +extern int tty_getDebugChar(void); /* read and return a single char */ +extern void tty_flushDebugChar(void); /* flush pending characters */ +extern int eth_putDebugChar(int); /* write a single character */ +extern int eth_getDebugChar(void); /* read and return a single char */ +extern void eth_flushDebugChar(void); /* flush pending characters */ + +/************************************************************************/ +/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/ +/* at least NUMREGBYTES*2 are needed for register packets */ +/* Longer buffer is needed to list all threads */ +#define BUFMAX 400 + +char *kgdb_version = KGDB_VERSION; + +/* debug > 0 prints ill-formed commands in valid packets & checksum errors */ +int debug_regs = 0; /* set to non-zero to print registers */ + +/* filled in by an external module */ +char *gdb_module_offsets; + +static const char hexchars[] = "0123456789abcdef"; + +/* Number of bytes of registers. */ +#define NUMREGBYTES (NUMREGS * sizeof(unsigned long)) +/* + * Note that this register image is in a different order than + * the register image that Linux produces at interrupt time. + * + * Linux's register image is defined by struct pt_regs in ptrace.h. + * Just why GDB uses a different order is a historical mystery. + * + * Could add XMM and segment registers here. + */ +enum regnames {_RAX, + _RBX, + _RCX, + _RDX, + _RSI, + _RDI, + _RBP, + _RSP, + _R8, + _R9, + _R10, + _R11, + _R12, + _R13, + _R14, + _R15, + _PC, + _PS, + NUMREGS }; + + +/*************************** ASSEMBLY CODE MACROS *************************/ +/* + * Put the error code here just in case the user cares. + * Likewise, the vector number here (since GDB only gets the signal + * number through the usual means, and that's not very specific). + * The called_from is the return address so he can tell how we entered kgdb. + * This will allow him to seperate out the various possible entries. + */ +#define REMOTE_DEBUG 0 /* set != to turn on printing (also available in info) */ + +#define PID_MAX PID_MAX_DEFAULT + +#ifdef CONFIG_SMP +void smp_send_nmi_allbutself(void); +#define IF_SMP(x) x +#undef MAX_NO_CPUS +#ifndef CONFIG_NO_KGDB_CPUS +#define CONFIG_NO_KGDB_CPUS 2 +#endif +#if CONFIG_NO_KGDB_CPUS > NR_CPUS +#define MAX_NO_CPUS NR_CPUS +#else +#define MAX_NO_CPUS CONFIG_NO_KGDB_CPUS +#endif +#define hold_init hold_on_sstep: 1, +#define MAX_CPU_MASK (unsigned long)((1LL << MAX_NO_CPUS) - 1LL) +#define NUM_CPUS num_online_cpus() +#else +#define IF_SMP(x) +#define hold_init +#undef MAX_NO_CPUS +#define MAX_NO_CPUS 1 +#define NUM_CPUS 1 +#endif +#define NOCPU (struct task_struct *)0xbad1fbad +/* *INDENT-OFF* */ +struct kgdb_info { + int used_malloc; + void *called_from; + long long entry_tsc; + int errcode; + int vector; + int print_debug_info; +#ifdef CONFIG_SMP + int hold_on_sstep; + struct { + volatile struct task_struct *task; + int pid; + int hold; + struct pt_regs *regs; + } cpus_waiting[MAX_NO_CPUS]; +#endif +} kgdb_info = {hold_init print_debug_info:REMOTE_DEBUG, vector:-1}; + +/* *INDENT-ON* */ + +#define used_m kgdb_info.used_malloc +/* + * This is little area we set aside to contain the stack we + * need to build to allow gdb to call functions. We use one + * per cpu to avoid locking issues. We will do all this work + * with interrupts off so that should take care of the protection + * issues. + */ +#define LOOKASIDE_SIZE 200 /* should be more than enough */ +#define MALLOC_MAX 200 /* Max malloc size */ +struct { + unsigned long rsp; + unsigned long array[LOOKASIDE_SIZE]; +} fn_call_lookaside[MAX_NO_CPUS]; + +static int trap_cpu; +static unsigned long OLD_esp; + +#define END_OF_LOOKASIDE &fn_call_lookaside[trap_cpu].array[LOOKASIDE_SIZE] +#define IF_BIT 0x200 +#define TF_BIT 0x100 + +#define MALLOC_ROUND 8-1 + +static char malloc_array[MALLOC_MAX]; +IF_SMP(static void to_gdb(const char *mess)); +void * +malloc(int size) +{ + + if (size <= (MALLOC_MAX - used_m)) { + int old_used = used_m; + used_m += ((size + MALLOC_ROUND) & (~MALLOC_ROUND)); + return &malloc_array[old_used]; + } else { + return NULL; + } +} + +/* + * I/O dispatch functions... + * Based upon kgdboe, either call the ethernet + * handler or the serial one.. + */ +void +putDebugChar(int c) +{ + if (!kgdboe) { + tty_putDebugChar(c); + } else { + eth_putDebugChar(c); + } +} + +int +getDebugChar(void) +{ + if (!kgdboe) { + return tty_getDebugChar(); + } else { + return eth_getDebugChar(); + } +} + +void +flushDebugChar(void) +{ + if (!kgdboe) { + tty_flushDebugChar(); + } else { + eth_flushDebugChar(); + } +} + +/* + * Gdb calls functions by pushing agruments, including a return address + * on the stack and the adjusting EIP to point to the function. The + * whole assumption in GDB is that we are on a different stack than the + * one the "user" i.e. code that hit the break point, is on. This, of + * course is not true in the kernel. Thus various dodges are needed to + * do the call without directly messing with EIP (which we can not change + * as it is just a location and not a register. To adjust it would then + * require that we move every thing below EIP up or down as needed. This + * will not work as we may well have stack relative pointer on the stack + * (such as the pointer to regs, for example). + + * So here is what we do: + * We detect gdb attempting to store into the stack area and instead, store + * into the fn_call_lookaside.array at the same relative location as if it + * were the area ESP pointed at. We also trap ESP modifications + * and uses these to adjust fn_call_lookaside.esp. On entry + * fn_call_lookaside.esp will be set to point at the last entry in + * fn_call_lookaside.array. This allows us to check if it has changed, and + * if so, on exit, we add the registers we will use to do the move and a + * trap/ interrupt return exit sequence. We then adjust the eflags in the + * regs array (remember we now have a copy in the fn_call_lookaside.array) to + * kill the interrupt bit, AND we change EIP to point at our set up stub. + * As part of the register set up we preset the registers to point at the + * begining and end of the fn_call_lookaside.array, so all the stub needs to + * do is move words from the array to the stack until ESP= the desired value + * then do the rti. This will then transfer to the desired function with + * all the correct registers. Nifty huh? + */ +extern asmlinkage void fn_call_stub(void); +extern asmlinkage void fn_rtn_stub(void); +/* *INDENT-OFF* */ +__asm__("fn_rtn_stub:\n\t" + "movq %rax,%rsp\n\t" + "fn_call_stub:\n\t" + "1:\n\t" + "addq $-8,%rbx\n\t" + "movq (%rbx), %rax\n\t" + "pushq %rax\n\t" + "cmpq %rsp,%rcx\n\t" + "jne 1b\n\t" + "popq %rax\n\t" + "popq %rbx\n\t" + "popq %rcx\n\t" + "iret \n\t"); +/* *INDENT-ON* */ +#define gdb_i386vector kgdb_info.vector +#define gdb_i386errcode kgdb_info.errcode +#define waiting_cpus kgdb_info.cpus_waiting +#define remote_debug kgdb_info.print_debug_info +#define hold_cpu(cpu) kgdb_info.cpus_waiting[cpu].hold +/* gdb locks */ + +#ifdef CONFIG_SMP +static int in_kgdb_called; +static spinlock_t waitlocks[MAX_NO_CPUS] = + {[0 ... MAX_NO_CPUS - 1] = SPIN_LOCK_UNLOCKED }; +/* + * The following array has the thread pointer of each of the "other" + * cpus. We make it global so it can be seen by gdb. + */ +volatile int in_kgdb_entry_log[MAX_NO_CPUS]; +volatile struct pt_regs *in_kgdb_here_log[MAX_NO_CPUS]; +/* +static spinlock_t continuelocks[MAX_NO_CPUS]; +*/ +spinlock_t kgdb_spinlock = SPIN_LOCK_UNLOCKED; +/* waiters on our spinlock plus us */ +static atomic_t spinlock_waiters = ATOMIC_INIT(1); +static int spinlock_count = 0; +static int spinlock_cpu = 0; +/* + * Note we use nested spin locks to account for the case where a break + * point is encountered when calling a function by user direction from + * kgdb. Also there is the memory exception recursion to account for. + * Well, yes, but this lets other cpus thru too. Lets add a + * cpu id to the lock. + */ +#define KGDB_SPIN_LOCK(x) if( spinlock_count == 0 || \ + spinlock_cpu != smp_processor_id()){\ + atomic_inc(&spinlock_waiters); \ + while (! spin_trylock(x)) {\ + in_kgdb(®s);\ + }\ + atomic_dec(&spinlock_waiters); \ + spinlock_count = 1; \ + spinlock_cpu = smp_processor_id(); \ + }else{ \ + spinlock_count++; \ + } +#define KGDB_SPIN_UNLOCK(x) if( --spinlock_count == 0) spin_unlock(x) +#else +unsigned kgdb_spinlock = 0; +#define KGDB_SPIN_LOCK(x) --*x +#define KGDB_SPIN_UNLOCK(x) ++*x +#endif + +int +hex(char ch) +{ + if ((ch >= 'a') && (ch <= 'f')) + return (ch - 'a' + 10); + if ((ch >= '0') && (ch <= '9')) + return (ch - '0'); + if ((ch >= 'A') && (ch <= 'F')) + return (ch - 'A' + 10); + return (-1); +} + +/* scan for the sequence $# */ +void +getpacket(char *buffer) +{ + unsigned char checksum; + unsigned char xmitcsum; + int i; + int count; + char ch; + + do { + /* wait around for the start character, ignore all other characters */ + while ((ch = (getDebugChar() & 0x7f)) != '$') ; + checksum = 0; + xmitcsum = -1; + + count = 0; + + /* now, read until a # or end of buffer is found */ + while (count < BUFMAX) { + ch = getDebugChar() & 0x7f; + if (ch == '#') + break; + checksum = checksum + ch; + buffer[count] = ch; + count = count + 1; + } + buffer[count] = 0; + + if (ch == '#') { + xmitcsum = hex(getDebugChar() & 0x7f) << 4; + xmitcsum += hex(getDebugChar() & 0x7f); + if ((remote_debug) && (checksum != xmitcsum)) { + printk + ("bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n", + checksum, xmitcsum, buffer); + } + + if (checksum != xmitcsum) + putDebugChar('-'); /* failed checksum */ + else { + putDebugChar('+'); /* successful transfer */ + /* if a sequence char is present, reply the sequence ID */ + if (buffer[2] == ':') { + putDebugChar(buffer[0]); + putDebugChar(buffer[1]); + /* remove sequence chars from buffer */ + count = strlen(buffer); + for (i = 3; i <= count; i++) + buffer[i - 3] = buffer[i]; + } + } + } + } while (checksum != xmitcsum); + + if (remote_debug) + printk("R:%s\n", buffer); + flushDebugChar(); +} + +/* send the packet in buffer. */ + +void +putpacket(char *buffer) +{ + unsigned char checksum; + int count; + char ch; + + /* $#. */ + + if (!kgdboe) { + do { + if (remote_debug) + printk("T:%s\n", buffer); + putDebugChar('$'); + checksum = 0; + count = 0; + + while ((ch = buffer[count])) { + putDebugChar(ch); + checksum += ch; + count += 1; + } + + putDebugChar('#'); + putDebugChar(hexchars[checksum >> 4]); + putDebugChar(hexchars[checksum % 16]); + flushDebugChar(); + + } while ((getDebugChar() & 0x7f) != '+'); + } else { + /* + * For udp, we can not transfer too much bytes once. + * We only transfer MAX_SEND_COUNT size bytes each time + */ + +#define MAX_SEND_COUNT 30 + + int send_count = 0, i = 0; + char send_buf[MAX_SEND_COUNT]; + + do { + if (remote_debug) + printk("T:%s\n", buffer); + putDebugChar('$'); + checksum = 0; + count = 0; + send_count = 0; + while ((ch = buffer[count])) { + if (send_count >= MAX_SEND_COUNT) { + for(i = 0; i < MAX_SEND_COUNT; i++) { + putDebugChar(send_buf[i]); + } + flushDebugChar(); + send_count = 0; + } else { + send_buf[send_count] = ch; + checksum += ch; + count ++; + send_count++; + } + } + for(i = 0; i < send_count; i++) + putDebugChar(send_buf[i]); + putDebugChar('#'); + putDebugChar(hexchars[checksum >> 4]); + putDebugChar(hexchars[checksum % 16]); + flushDebugChar(); + } while ((getDebugChar() & 0x7f) != '+'); + } +} + +static char remcomInBuffer[BUFMAX]; +static char remcomOutBuffer[BUFMAX]; +static char lbuf[BUFMAX]; +static short error; + +void +debug_error(char *format, char *parm) +{ + if (remote_debug) + printk(format, parm); +} + +static void +print_regs(struct pt_regs *regs) +{ + printk("RAX=%016lx RBX=%016lx RCX=%016lx\n", + regs->rax, regs->rbx, regs->rcx); + printk("RDX=%016lx RSI=%016lx RDI=%016lx\n", + regs->rdx, regs->rsi, regs->rdi); + printk("RBP=%016lx PS=%016lx PC=%016lx\n", + regs->rbp, regs->eflags, regs->rip); + printk("R8=%016lx R9=%016lx R10=%016lx\n", + regs->r8, regs->r9, regs->r10); + printk("R11=%016lx R12=%016lx R13=%016lx\n", + regs->r11, regs->r12, regs->r13); + printk("R14=%016lx R15=%016lx RSP=%016lx\n", + regs->r14, regs->r15, regs->rsp); +} + +#define NEW_esp fn_call_lookaside[trap_cpu].rsp + +static void +regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) +{ + gdb_regs[_RAX] = regs->rax; + gdb_regs[_RBX] = regs->rbx; + gdb_regs[_RCX] = regs->rcx; + gdb_regs[_RDX] = regs->rdx; + gdb_regs[_RSI] = regs->rsi; + gdb_regs[_RDI] = regs->rdi; + gdb_regs[_RBP] = regs->rbp; + gdb_regs[ _PS] = regs->eflags; + gdb_regs[ _PC] = regs->rip; + gdb_regs[ _R8] = regs->r8; + gdb_regs[ _R9] = regs->r9; + gdb_regs[_R10] = regs->r10; + gdb_regs[_R11] = regs->r11; + gdb_regs[_R12] = regs->r12; + gdb_regs[_R13] = regs->r13; + gdb_regs[_R14] = regs->r14; + gdb_regs[_R15] = regs->r15; + gdb_regs[_RSP] = regs->rsp; + + /* Note, as we are a debugging the kernel, we will always + * trap in kernel code, this means no priviledge change, + * and so the pt_regs structure is not completely valid. In a non + * privilege change trap, only EFLAGS, CS and EIP are put on the stack, + * SS and ESP are not stacked, this means that the last 2 elements of + * pt_regs is not valid (they would normally refer to the user stack) + * also, using regs+1 is no good because you end up will a value that is + * 2 longs (8) too high. This used to cause stepping over functions + * to fail, so my fix is to use the address of regs->esp, which + * should point at the end of the stack frame. Note I have ignored + * completely exceptions that cause an error code to be stacked, such + * as double fault. Stuart Hughes, Zentropix. + * original code: gdb_regs[_ESP] = (int) (regs + 1) ; + + * this is now done on entry and moved to OLD_esp (as well as NEW_esp). + */ +} + +static void +gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs) +{ + regs->rax = gdb_regs[_RAX] ; + regs->rbx = gdb_regs[_RBX] ; + regs->rcx = gdb_regs[_RCX] ; + regs->rdx = gdb_regs[_RDX] ; + regs->rsi = gdb_regs[_RSI] ; + regs->rdi = gdb_regs[_RDI] ; + regs->rbp = gdb_regs[_RBP] ; + regs->eflags = gdb_regs[ _PS] ; + regs->rip = gdb_regs[ _PC] ; + regs->r8 = gdb_regs[ _R8] ; + regs->r9 = gdb_regs[ _R9] ; + regs->r10 = gdb_regs[ _R10] ; + regs->r11 = gdb_regs[ _R11] ; + regs->r12 = gdb_regs[ _R12] ; + regs->r13 = gdb_regs[ _R13] ; + regs->r14 = gdb_regs[ _R14] ; + regs->r15 = gdb_regs[ _R15] ; + #if 0 /* can't change these */ + regs->rsp = gdb_regs[_RSP] ; + regs->ss = gdb_regs[ _SS] ; + regs->fs = gdb_regs[_FS]; + regs->gs = gdb_regs[_GS]; +#endif +} /* gdb_regs_to_regs */ + +int thread_list = 0; +extern void thread_return(void); + +void +get_gdb_regs(struct task_struct *p, struct pt_regs *regs, unsigned long *gdb_regs) +{ + unsigned long **rbp, *rsp, *rsp0, pc; + int count = 0; + IF_SMP(int i); + if (!p || p == current) { + regs_to_gdb_regs(gdb_regs, regs); + return; + } +#ifdef CONFIG_SMP + for (i = 0; i < MAX_NO_CPUS; i++) { + if (p == kgdb_info.cpus_waiting[i].task) { + regs_to_gdb_regs(gdb_regs, + kgdb_info.cpus_waiting[i].regs); + gdb_regs[_RSP] = + (unsigned long)&kgdb_info.cpus_waiting[i].regs->rsp; + + return; + } + } +#endif + memset(gdb_regs, 0, NUMREGBYTES); + rsp = (unsigned long *)p->thread.rsp; + rbp = (unsigned long **)rsp[0]; + rsp += 2; + gdb_regs[_PC] = (unsigned long)thread_return; + gdb_regs[_RBP] = (unsigned long)rbp; + gdb_regs[_RSP] = (unsigned long)rsp; + +/* + * This code is to give a more informative notion of where a process + * is waiting. It is used only when the user asks for a thread info + * list. If he then switches to the thread, s/he will find the task + * is in schedule, but a back trace should show the same info we come + * up with. This code was shamelessly purloined from process.c. It was + * then enhanced to provide more registers than simply the program + * counter. + */ + + if (!thread_list) { + return; + } + + if (p->state == TASK_RUNNING) + return; + rsp0 = (unsigned long *)p->thread.rsp0; + if (rsp < (unsigned long *) p->thread_info || rsp > rsp0) + return; + /* include/asm-i386/system.h:switch_to() pushes ebp last. */ + do { + if (*rbp < rsp || *rbp > rsp0) + break; + rbp = (unsigned long **)*rbp; + rsp = (unsigned long *)rbp; + pc = rsp[1]; + + if (!in_sched_functions(pc)) + break; + gdb_regs[_PC] = (unsigned long)pc; + gdb_regs[_RSP] = (unsigned long)rsp; + gdb_regs[_RBP] = (unsigned long)rbp; + } while (count++ < 16); + return; +} + +/* convert the memory pointed to by mem into hex, placing result in buf */ +/* returns nonzero if any memory access fails. */ +int mem2hex( char* mem, char* buf, int count) +{ + int i; + unsigned char ch; + int ret = 0; + + for (i=0;i> 4]; + *buf++ = hexchars[ch % 16]; + } + *buf = 0; + if (ret) { + Dearly_printk("mem2hex: fault at accessing %p\n", mem); + } + return(ret); +} + +/* convert the hex array pointed to by buf into binary to be placed in mem */ +/* return nonzero if any memory access fails. */ +int hex2mem( char* buf, char* mem, int count) +{ + int i; + unsigned char ch; + int ret = 0; + + for (i=0;i (OLD_esp - (unsigned int) LOOKASIDE_SIZE))) { + addr = (char *) END_OF_LOOKASIDE - ((char *) OLD_esp - addr); + } + *addr = val; +} + +/* convert the memory pointed to by mem into hex, placing result in buf */ +/* return a pointer to the last char put in buf (null) */ +/* If MAY_FAULT is non-zero, then we should set mem_err in response to + a fault; if zero treat a fault like any other fault in the stub. */ +char * +mem2hex(char *mem, char *buf, int count, int may_fault) +{ + int i; + unsigned char ch; + + if (may_fault) { + mem_err_expected = 1; + mem_err = 0; + } + for (i = 0; i < count; i++) { + /* printk("%lx = ", mem) ; */ + + ch = get_char(mem++); + + /* printk("%02x\n", ch & 0xFF) ; */ + if (may_fault && mem_err) { + if (remote_debug) + printk("Mem fault fetching from addr %lx\n", + (long) (mem - 1)); + *buf = 0; /* truncate buffer */ + return (buf); + } + *buf++ = hexchars[ch >> 4]; + *buf++ = hexchars[ch % 16]; + } + *buf = 0; + if (may_fault) + mem_err_expected = 0; + return (buf); +} + +/* convert the hex array pointed to by buf into binary to be placed in mem */ +/* return a pointer to the character AFTER the last byte written */ +/* NOTE: We use the may fault flag to also indicate if the write is to + * the registers (0) or "other" memory (!=0) + */ +char * +hex2mem(char *buf, char *mem, int count, int may_fault) +{ + int i; + unsigned char ch; + + if (may_fault) { + mem_err_expected = 1; + mem_err = 0; + } + for (i = 0; i < count; i++) { + ch = hex(*buf++) << 4; + ch = ch + hex(*buf++); + set_char(mem++, ch, may_fault); + + if (may_fault && mem_err) { + if (remote_debug) + printk("Mem fault storing to addr %lx\n", + (long) (mem - 1)); + return (mem); + } + } + if (may_fault) + mem_err_expected = 0; + return (mem); +} +#endif + +/**********************************************/ +/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */ +/* RETURN NUMBER OF CHARS PROCESSED */ +/**********************************************/ +int +hexToLong(char **ptr, unsigned long *value) +{ + int numChars = 0; + int hexValue; + + *value = 0; + + while (**ptr) { + hexValue = hex(**ptr); + if (hexValue >= 0) { + *value = (*value << 4) | hexValue; + numChars++; + } else + break; + + (*ptr)++; + } + + return (numChars); +} + +#define stubhex(h) hex(h) +#ifdef old_thread_list + +static int +stub_unpack_int(char *buff, int fieldlength) +{ + int nibble; + int retval = 0; + + while (fieldlength) { + nibble = stubhex(*buff++); + retval |= nibble; + fieldlength--; + if (fieldlength) + retval = retval << 4; + } + return retval; +} +#endif +static char * +pack_hex_byte(char *pkt, int byte) +{ + *pkt++ = hexchars[(byte >> 4) & 0xf]; + *pkt++ = hexchars[(byte & 0xf)]; + return pkt; +} + +#define BUF_THREAD_ID_SIZE 16 + +static char * +pack_threadid(char *pkt, threadref * id) +{ + char *limit; + unsigned char *altid; + + altid = (unsigned char *) id; + limit = pkt + BUF_THREAD_ID_SIZE; + while (pkt < limit) + pkt = pack_hex_byte(pkt, *altid++); + return pkt; +} + +#ifdef old_thread_list +static char * +unpack_byte(char *buf, int *value) +{ + *value = stub_unpack_int(buf, 2); + return buf + 2; +} + +static char * +unpack_threadid(char *inbuf, threadref * id) +{ + char *altref; + char *limit = inbuf + BUF_THREAD_ID_SIZE; + int x, y; + + altref = (char *) id; + + while (inbuf < limit) { + x = stubhex(*inbuf++); + y = stubhex(*inbuf++); + *altref++ = (x << 4) | y; + } + return inbuf; +} +#endif +void +int_to_threadref(threadref * id, int value) +{ + unsigned char *scan; + + scan = (unsigned char *) id; + { + int i = 4; + while (i--) + *scan++ = 0; + } + *scan++ = (value >> 24) & 0xff; + *scan++ = (value >> 16) & 0xff; + *scan++ = (value >> 8) & 0xff; + *scan++ = (value & 0xff); +} +int +int_to_hex_v(unsigned char * id, int value) +{ + unsigned char *start = id; + int shift; + int ch; + + for (shift = 28; shift >= 0; shift -= 4) { + if ((ch = (value >> shift) & 0xf) || (id != start)) { + *id = hexchars[ch]; + id++; + } + } + if (id == start) + *id++ = '0'; + return id - start; +} +#ifdef old_thread_list + +static int +threadref_to_int(threadref * ref) +{ + int i, value = 0; + unsigned char *scan; + + scan = (char *) ref; + scan += 4; + i = 4; + while (i-- > 0) + value = (value << 8) | ((*scan++) & 0xff); + return value; +} +#endif +static int +cmp_str(char *s1, char *s2, int count) +{ + while (count--) { + if (*s1++ != *s2++) + return 0; + } + return 1; +} + +#if 1 /* this is a hold over from 2.4 where O(1) was "sometimes" */ +extern struct task_struct *kgdb_get_idle(int cpu); +#define idle_task(cpu) kgdb_get_idle(cpu) +#else +#define idle_task(cpu) init_tasks[cpu] +#endif + +extern int kgdb_pid_init_done; + +struct task_struct * +getthread(int pid) +{ + struct task_struct *thread; + if (pid >= PID_MAX && pid <= (PID_MAX + MAX_NO_CPUS)) { + if (!cpu_online(pid - PID_MAX)) + return NULL; + + return idle_task(pid - PID_MAX); + } else { + /* + * find_task_by_pid is relatively safe all the time + * Other pid functions require lock downs which imply + * that we may be interrupting them (as we get here + * in the middle of most any lock down). + * Still we don't want to call until the table exists! + */ + if (kgdb_pid_init_done){ + thread = find_task_by_pid(pid); + if (thread) { + return thread; + } + } + } + return NULL; +} +/* *INDENT-OFF* */ +struct hw_breakpoint { + unsigned enabled; + unsigned type; + unsigned len; + unsigned long addr; +} breakinfo[4] = { {enabled:0}, + {enabled:0}, + {enabled:0}, + {enabled:0}}; +/* *INDENT-ON* */ +unsigned long hw_breakpoint_status; +void +correct_hw_break(void) +{ + int breakno; + int correctit; + int breakbit; + unsigned long dr7; + + asm volatile ("movq %%db7, %0\n":"=r" (dr7) + :); + /* *INDENT-OFF* */ + do { + unsigned long addr0, addr1, addr2, addr3; + asm volatile ("movq %%db0, %0\n" + "movq %%db1, %1\n" + "movq %%db2, %2\n" + "movq %%db3, %3\n" + :"=r" (addr0), "=r"(addr1), + "=r"(addr2), "=r"(addr3) + :); + } while (0); + /* *INDENT-ON* */ + correctit = 0; + for (breakno = 0; breakno < 3; breakno++) { + breakbit = 2 << (breakno << 1); + if (!(dr7 & breakbit) && breakinfo[breakno].enabled) { + correctit = 1; + dr7 |= breakbit; + dr7 &= ~(0xf0000 << (breakno << 2)); + dr7 |= (((breakinfo[breakno].len << 2) | + breakinfo[breakno].type) << 16) << + (breakno << 2); + switch (breakno) { + case 0: + asm volatile ("movq %0, %%dr0\n"::"r" + (breakinfo[breakno].addr)); + break; + + case 1: + asm volatile ("movq %0, %%dr1\n"::"r" + (breakinfo[breakno].addr)); + break; + + case 2: + asm volatile ("movq %0, %%dr2\n"::"r" + (breakinfo[breakno].addr)); + break; + + case 3: + asm volatile ("movq %0, %%dr3\n"::"r" + (breakinfo[breakno].addr)); + break; + } + } else if ((dr7 & breakbit) && !breakinfo[breakno].enabled) { + correctit = 1; + dr7 &= ~breakbit; + dr7 &= ~(0xf0000 << (breakno << 2)); + } + } + if (correctit) { + asm volatile ("movq %0, %%db7\n"::"r" (dr7)); + } +} + +int +remove_hw_break(unsigned breakno) +{ + if (!breakinfo[breakno].enabled) { + return -1; + } + breakinfo[breakno].enabled = 0; + return 0; +} + +int +set_hw_break(unsigned breakno, unsigned type, unsigned len, unsigned addr) +{ + if (breakinfo[breakno].enabled) { + return -1; + } + breakinfo[breakno].enabled = 1; + breakinfo[breakno].type = type; + breakinfo[breakno].len = len; + breakinfo[breakno].addr = addr; + return 0; +} + +#ifdef CONFIG_SMP +static int in_kgdb_console = 0; + +int +in_kgdb(struct pt_regs *regs) +{ + unsigned long flags; + int cpu; + if (!kgdb_enabled) + return 0; + cpu = smp_processor_id(); + in_kgdb_called = 1; + if (!spin_is_locked(&kgdb_spinlock)) { + if (in_kgdb_here_log[cpu] || /* we are holding this cpu */ + in_kgdb_console) { /* or we are doing slow i/o */ + return 1; + } + return 0; + } + + /* As I see it the only reason not to let all cpus spin on + * the same spin_lock is to allow selected ones to proceed. + * This would be a good thing, so we leave it this way. + * Maybe someday.... Done ! + + * in_kgdb() is called from an NMI so we don't pretend + * to have any resources, like printk() for example. + */ + + local_irq_save(flags); /* only local here, to avoid hanging */ + /* + * log arival of this cpu + * The NMI keeps on ticking. Protect against recurring more + * than once, and ignor the cpu that has the kgdb lock + */ + in_kgdb_entry_log[cpu]++; + in_kgdb_here_log[cpu] = regs; + if (cpu == spinlock_cpu || waiting_cpus[cpu].task) + goto exit_in_kgdb; + + /* + * For protection of the initilization of the spin locks by kgdb + * it locks the kgdb spinlock before it gets the wait locks set + * up. We wait here for the wait lock to be taken. If the + * kgdb lock goes away first?? Well, it could be a slow exit + * sequence where the wait lock is removed prior to the kgdb lock + * so if kgdb gets unlocked, we just exit. + */ + + while (spin_is_locked(&kgdb_spinlock) && + !spin_is_locked(waitlocks + cpu)) ; + if (!spin_is_locked(&kgdb_spinlock)) + goto exit_in_kgdb; + + waiting_cpus[cpu].task = current; + waiting_cpus[cpu].pid = (current->pid) ? : (PID_MAX + cpu); + waiting_cpus[cpu].regs = regs; + + spin_unlock_wait(waitlocks + cpu); + + /* + * log departure of this cpu + */ + waiting_cpus[cpu].task = 0; + waiting_cpus[cpu].pid = 0; + waiting_cpus[cpu].regs = 0; + correct_hw_break(); + exit_in_kgdb: + in_kgdb_here_log[cpu] = 0; + local_irq_restore(flags); + return 1; + /* + spin_unlock(continuelocks + smp_processor_id()); + */ +} + +void +smp__in_kgdb(struct pt_regs regs) +{ + ack_APIC_irq(); + in_kgdb(®s); +} +#else +int +in_kgdb(struct pt_regs *regs) +{ + return (kgdb_spinlock); +} +#endif + +void +printexceptioninfo(int exceptionNo, int errorcode, char *buffer) +{ + unsigned long dr6; + int i; + switch (exceptionNo) { + case 1: /* debug exception */ + break; + case 3: /* breakpoint */ + sprintf(buffer, "Software breakpoint"); + return; + default: + sprintf(buffer, "Details not available"); + return; + } + asm volatile ("movq %%db6, %0\n":"=r" (dr6) + :); + if (dr6 & 0x4000) { + sprintf(buffer, "Single step"); + return; + } + for (i = 0; i < 4; ++i) { + if (dr6 & (1 << i)) { + sprintf(buffer, "Hardware breakpoint %d", i); + return; + } + } + sprintf(buffer, "Unknown trap"); + return; +} + +/* + * The ThreadExtraInfo query allows us to pass an arbitrary string + * for display with the "info threads" command. + */ + +void +print_extra_info(task_t *p, char *buf) +{ + if (!p) { + sprintf(buf, "Invalid thread"); + return; + } + sprintf(buf, "0x%p %8d %4d %c %s", + (void *)p, p->parent->pid, + task_cpu(p), + (p->state == 0) ? (task_curr(p)?'R':'r') : + (p->state < 0) ? 'U' : + (p->state & TASK_UNINTERRUPTIBLE) ? 'D' : + (p->state & TASK_STOPPED || p->ptrace & PT_PTRACED) ? 'T' : + (p->state & (TASK_ZOMBIE | TASK_DEAD)) ? 'Z' : + (p->state & TASK_INTERRUPTIBLE) ? 'S' : '?', + p->comm); +} + +/* + * This function does all command procesing for interfacing to gdb. + * + * NOTE: The INT nn instruction leaves the state of the interrupt + * enable flag UNCHANGED. That means that when this routine + * is entered via a breakpoint (INT 3) instruction from code + * that has interrupts enabled, then interrupts will STILL BE + * enabled when this routine is entered. The first thing that + * we do here is disable interrupts so as to prevent recursive + * entries and bothersome serial interrupts while we are + * trying to run the serial port in polled mode. + * + * For kernel version 2.1.xx the kgdb_cli() actually gets a spin lock so + * it is always necessary to do a restore_flags before returning + * so as to let go of that lock. + */ +int +kgdb_handle_exception(int exceptionVector, + int signo, int err_code, struct pt_regs *linux_regs) +{ + struct task_struct *usethread = NULL; + struct task_struct *thread_list_start = 0, *thread = NULL; + struct task_struct *p; + unsigned long addr, length; + unsigned long breakno, breaktype; + char *ptr; + unsigned long newPC; + threadref thref; + unsigned long threadid, tmpid; + int thread_min = PID_MAX + MAX_NO_CPUS; +#ifdef old_thread_list + int maxthreads; +#endif + int nothreads; + unsigned long flags; + unsigned long gdb_regs[NUMREGS]; + unsigned long dr6; + IF_SMP(int entry_state = 0); /* 0, ok, 1, no nmi, 2 sync failed */ +#define NO_NMI 1 +#define NO_SYNC 2 +#define regs (*linux_regs) + /* + * If the entry is not from the kernel then return to the Linux + * trap handler and let it process the interrupt normally. + */ + if ((linux_regs->eflags & VM_MASK) || (3 & linux_regs->cs)) { + printk("ignoring non-kernel exception\n"); + print_regs(®s); + return (0); + } + /* + * If we're using eth mode, set the 'mode' in the netdevice. + */ + + if (kgdboe) + netpoll_set_trap(1); + + local_irq_save(flags); + + /* Get kgdb spinlock */ + + KGDB_SPIN_LOCK(&kgdb_spinlock); + rdtscll(kgdb_info.entry_tsc); + /* + * We depend on this spinlock and the NMI watch dog to control the + * other cpus. They will arrive at "in_kgdb()" as a result of the + * NMI and will wait there for the following spin locks to be + * released. + */ +#ifdef CONFIG_SMP + +#if 0 + if (cpu_callout_map & ~MAX_CPU_MASK) { + printk("kgdb : too many cpus, possibly not mapped" + " in contiguous space, change MAX_NO_CPUS" + " in kgdb_stub and make new kernel.\n" + " cpu_callout_map is %lx\n", cpu_callout_map); + goto exit_just_unlock; + } +#endif + if (spinlock_count == 1) { + int time, end_time, dum; + int i; + int cpu_logged_in[MAX_NO_CPUS] = {[0 ... MAX_NO_CPUS - 1] = (0) + }; + if (remote_debug) { + printk("kgdb : cpu %d entry, syncing others\n", + smp_processor_id()); + } + for (i = 0; i < MAX_NO_CPUS; i++) { + /* + * Use trylock as we may already hold the lock if + * we are holding the cpu. Net result is all + * locked. + */ + spin_trylock(&waitlocks[i]); + } + for (i = 0; i < MAX_NO_CPUS; i++) + cpu_logged_in[i] = 0; + /* + * Wait for their arrival. We know the watch dog is active if + * in_kgdb() has ever been called, as it is always called on a + * watchdog tick. + */ + rdtsc(dum, time); + end_time = time + 2; /* Note: we use the High order bits! */ + i = 1; + if (num_online_cpus() > 1) { + int me_in_kgdb = in_kgdb_entry_log[smp_processor_id()]; + smp_send_nmi_allbutself(); + + while (i < num_online_cpus() && time != end_time) { + int j; + for (j = 0; j < MAX_NO_CPUS; j++) { + if (waiting_cpus[j].task && + waiting_cpus[j].task != NOCPU && + !cpu_logged_in[j]) { + i++; + cpu_logged_in[j] = 1; + if (remote_debug) { + printk + ("kgdb : cpu %d arrived at kgdb\n", + j); + } + break; + } else if (!waiting_cpus[j].task && + !cpu_online(j)) { + waiting_cpus[j].task = NOCPU; + cpu_logged_in[j] = 1; + waiting_cpus[j].hold = 1; + break; + } + if (!waiting_cpus[j].task && + in_kgdb_here_log[j]) { + + int wait = 100000; + while (wait--) ; + if (!waiting_cpus[j].task && + in_kgdb_here_log[j]) { + printk + ("kgdb : cpu %d stall" + " in in_kgdb\n", + j); + i++; + cpu_logged_in[j] = 1; + waiting_cpus[j].task = + (struct task_struct + *) 1; + } + } + } + + if (in_kgdb_entry_log[smp_processor_id()] > + (me_in_kgdb + 10)) { + break; + } + + rdtsc(dum, time); + } + if (i < num_online_cpus()) { + printk + ("kgdb : time out, proceeding without sync\n"); +#if 0 + printk("kgdb : Waiting_cpus: 0 = %d, 1 = %d\n", + waiting_cpus[0].task != 0, + waiting_cpus[1].task != 0); + printk("kgdb : Cpu_logged in: 0 = %d, 1 = %d\n", + cpu_logged_in[0], cpu_logged_in[1]); + printk + ("kgdb : in_kgdb_here_log in: 0 = %d, 1 = %d\n", + in_kgdb_here_log[0] != 0, + in_kgdb_here_log[1] != 0); +#endif + entry_state = NO_SYNC; + } else { +#if 0 + int ent = + in_kgdb_entry_log[smp_processor_id()] - + me_in_kgdb; + printk("kgdb : sync after %d entries\n", ent); +#endif + } + } else { + if (remote_debug) { + printk + ("kgdb : %d cpus, but watchdog not active\n" + "proceeding without locking down other cpus\n", + (int)num_online_cpus()); + entry_state = NO_NMI; + } + } + } +#endif + + if (remote_debug) { + unsigned long *lp = (unsigned long *) &linux_regs; + + printk("handle_exception(exceptionVector=%d, " + "signo=%d, err_code=%d, linux_regs=%p)\n", + exceptionVector, signo, err_code, linux_regs); + if (debug_regs) { + print_regs(®s); + printk("Stk: %8lx %8lx %8lx %8lx" + " %8lx %8lx %8lx %8lx\n", + lp[0], lp[1], lp[2], lp[3], + lp[4], lp[5], lp[6], lp[7]); + printk(" %8lx %8lx %8lx %8lx" + " %8lx %8lx %8lx %8lx\n", + lp[8], lp[9], lp[10], lp[11], + lp[12], lp[13], lp[14], lp[15]); + printk(" %8lx %8lx %8lx %8lx " + "%8lx %8lx %8lx %8lx\n", + lp[16], lp[17], lp[18], lp[19], + lp[20], lp[21], lp[22], lp[23]); + printk(" %8lx %8lx %8lx %8lx " + "%8lx %8lx %8lx %8lx\n", + lp[24], lp[25], lp[26], lp[27], + lp[28], lp[29], lp[30], lp[31]); + } + } + + /* Disable hardware debugging while we are in kgdb */ + /* Get the debug register status register */ +/* *INDENT-OFF* */ + __asm__("movq %0,%%db7" + : /* no output */ + :"r"(0UL)); + + asm volatile ("movq %%db6, %0\n" + :"=r" (hw_breakpoint_status) + :); + +#if 0 +/* *INDENT-ON* */ + switch (exceptionVector) { + case 0: /* divide error */ + case 1: /* debug exception */ + case 2: /* NMI */ + case 3: /* breakpoint */ + case 4: /* overflow */ + case 5: /* bounds check */ + case 6: /* invalid opcode */ + case 7: /* device not available */ + case 8: /* double fault (errcode) */ + case 10: /* invalid TSS (errcode) */ + case 12: /* stack fault (errcode) */ + case 16: /* floating point error */ + case 17: /* alignment check (errcode) */ + default: /* any undocumented */ + break; + case 11: /* segment not present (errcode) */ + case 13: /* general protection (errcode) */ + case 14: /* page fault (special errcode) */ + case 19: /* cache flush denied */ + if (mem_err_expected) { + /* + * This fault occured because of the + * get_char or set_char routines. These + * two routines use either eax of edx to + * indirectly reference the location in + * memory that they are working with. + * For a page fault, when we return the + * instruction will be retried, so we + * have to make sure that these + * registers point to valid memory. + */ + mem_err = 1; /* set mem error flag */ + mem_err_expected = 0; + mem_err_cnt++; /* helps in debugging */ + /* make valid address */ + regs.eax = (long) &garbage_loc; + /* make valid address */ + regs.edx = (long) &garbage_loc; + if (remote_debug) + printk("Return after memory error: " + "mem_err_cnt=%d\n", mem_err_cnt); + if (debug_regs) + print_regs(®s); + goto exit_kgdb; + } + break; + } +#endif + if (remote_debug) + printk("kgdb : entered kgdb on cpu %d\n", smp_processor_id()); + + gdb_i386vector = exceptionVector; + gdb_i386errcode = err_code; + kgdb_info.called_from = __builtin_return_address(0); +#ifdef CONFIG_SMP + /* + * OK, we can now communicate, lets tell gdb about the sync. + * but only if we had a problem. + */ + switch (entry_state) { + case NO_NMI: + to_gdb("NMI not active, other cpus not stopped\n"); + break; + case NO_SYNC: + to_gdb("Some cpus not stopped, see 'kgdb_info' for details\n"); + default:; + } + +#endif +/* + * Set up the gdb function call area. + */ + trap_cpu = smp_processor_id(); + OLD_esp = NEW_esp = (unsigned long) (&linux_regs->rsp); + + IF_SMP(once_again:) + /* reply to host that an exception has occurred */ + remcomOutBuffer[0] = 'S'; + remcomOutBuffer[1] = hexchars[signo >> 4]; + remcomOutBuffer[2] = hexchars[signo % 16]; + remcomOutBuffer[3] = 0; + + putpacket(remcomOutBuffer); + + while (1 == 1) { + error = 0; + remcomOutBuffer[0] = 0; + getpacket(remcomInBuffer); + switch (remcomInBuffer[0]) { + case '?': + remcomOutBuffer[0] = 'S'; + remcomOutBuffer[1] = hexchars[signo >> 4]; + remcomOutBuffer[2] = hexchars[signo % 16]; + remcomOutBuffer[3] = 0; + break; + case 'd': + remote_debug = !(remote_debug); /* toggle debug flag */ + printk("Remote debug %s\n", + remote_debug ? "on" : "off"); + break; + case 'g': /* return the value of the CPU registers */ + get_gdb_regs(usethread, ®s, gdb_regs); + mem2hex((char *) gdb_regs, + remcomOutBuffer, NUMREGBYTES); + break; + case 'G': /* set the value of the CPU registers - return OK */ + hex2mem(&remcomInBuffer[1], + (char *) gdb_regs, NUMREGBYTES); + if (!usethread || usethread == current) { + gdb_regs_to_regs(gdb_regs, ®s); + strcpy(remcomOutBuffer, "OK"); + } else { + strcpy(remcomOutBuffer, "E00"); + } + break; + + case 'P':{ /* set the value of a single CPU register - + return OK */ + /* + * For some reason, gdb wants to talk about psudo + * registers (greater than 15). + */ + unsigned long regno; + + ptr = &remcomInBuffer[1]; + regs_to_gdb_regs(gdb_regs, ®s); + if ((!usethread || usethread == current) && + hexToLong(&ptr, ®no) && + *ptr++ == '=' && (regno >= 0)) { + if (regno >= NUMREGS) + break; + hex2mem(ptr, (char *) &gdb_regs[regno], + 8); + gdb_regs_to_regs(gdb_regs, ®s); + strcpy(remcomOutBuffer, "OK"); + break; + } + strcpy(remcomOutBuffer, "E01"); + break; + } + + /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ + case 'm': + /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */ + ptr = &remcomInBuffer[1]; + if (hexToLong(&ptr, &addr) && + (*(ptr++) == ',') && (hexToLong(&ptr, &length))) { + ptr = 0; + /* + * hex doubles the byte count + */ + if (length > (BUFMAX / 2)) + length = BUFMAX / 2; + if (mem2hex((char *) addr, + remcomOutBuffer, length)) { + strcpy(remcomOutBuffer, "E03"); + debug_error("memory fault\n", NULL); + } + } + + if (ptr) { + strcpy(remcomOutBuffer, "E01"); + debug_error + ("malformed read memory command: %s\n", + remcomInBuffer); + } + break; + + /* MAA..AA,LLLL: + Write LLLL bytes at address AA.AA return OK */ + case 'M': + /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */ + ptr = &remcomInBuffer[1]; + if (hexToLong(&ptr, &addr) && + (*(ptr++) == ',') && + (hexToLong(&ptr, &length)) && (*(ptr++) == ':')) { + if (hex2mem(ptr, (char *) addr, length)) { + strcpy(remcomOutBuffer, "E03"); + debug_error("memory fault\n", NULL); + } else { + strcpy(remcomOutBuffer, "OK"); + } + + ptr = 0; + } + if (ptr) { + strcpy(remcomOutBuffer, "E02"); + debug_error + ("malformed write memory command: %s\n", + remcomInBuffer); + } + break; + case 'S': + remcomInBuffer[0] = 's'; + case 'C': + /* Csig;AA..AA where ;AA..AA is optional + * continue with signal + * Since signals are meaning less to us, delete that + * part and then fall into the 'c' code. + */ + ptr = &remcomInBuffer[1]; + length = 2; + while (*ptr && *ptr != ';') { + length++; + ptr++; + } + if (*ptr) { + do { + ptr++; + *(ptr - length++) = *ptr; + } while (*ptr); + } else { + remcomInBuffer[1] = 0; + } + + /* cAA..AA Continue at address AA..AA(optional) */ + /* sAA..AA Step one instruction from AA..AA(optional) */ + /* D detach, reply OK and then continue */ + case 'c': + case 's': + case 'D': + + /* try to read optional parameter, + pc unchanged if no parm */ + ptr = &remcomInBuffer[1]; + if (hexToLong(&ptr, &addr)) { + if (remote_debug) + printk("Changing EIP to 0x%lx\n", addr); + + regs.rip = addr; + } + + newPC = regs.rip; + + /* clear the trace bit */ + regs.eflags &= 0xfffffeff; + + /* set the trace bit if we're stepping */ + if (remcomInBuffer[0] == 's') + regs.eflags |= 0x100; + + /* detach is a friendly version of continue. Note that + debugging is still enabled (e.g hit control C) + */ + if (remcomInBuffer[0] == 'D') { + strcpy(remcomOutBuffer, "OK"); + putpacket(remcomOutBuffer); + } + + if (remote_debug) { + printk("Resuming execution\n"); + print_regs(®s); + } + asm volatile ("movq %%db6, %0\n":"=r" (dr6) + :); + if (!(dr6 & 0x4000)) { + for (breakno = 0; breakno < 4; ++breakno) { + if (dr6 & (1 << breakno) && + (breakinfo[breakno].type == 0)) { + /* Set restore flag */ + regs.eflags |= 0x10000; + break; + } + } + } + + if (kgdboe) + netpoll_set_trap(0); + + correct_hw_break(); + asm volatile ("movq %0, %%db6\n"::"r" (0UL)); + goto exit_kgdb; + + /* kill the program */ + case 'k': /* do nothing */ + break; + + /* query */ + case 'q': + nothreads = 0; + switch (remcomInBuffer[1]) { + case 'f': + threadid = 1; + thread_list = 2; + thread_list_start = (usethread ? : current); + case 's': + if (!cmp_str(&remcomInBuffer[2], + "ThreadInfo", 10)) + break; + + remcomOutBuffer[nothreads++] = 'm'; + for (; threadid < PID_MAX + MAX_NO_CPUS; + threadid++) { + thread = getthread(threadid); + if (thread) { + nothreads += int_to_hex_v( + &remcomOutBuffer[ + nothreads], + threadid); + if (thread_min > threadid) + thread_min = threadid; + remcomOutBuffer[ + nothreads] = ','; + nothreads++; + if (nothreads > BUFMAX - 10) + break; + } + } + if (remcomOutBuffer[nothreads - 1] == 'm') { + remcomOutBuffer[nothreads - 1] = 'l'; + } else { + nothreads--; + } + remcomOutBuffer[nothreads] = 0; + break; + +#ifdef old_thread_list /* Old thread info request */ + case 'L': + /* List threads */ + thread_list = 2; + thread_list_start = (usethread ? : current); + unpack_byte(remcomInBuffer + 3, &maxthreads); + unpack_threadid(remcomInBuffer + 5, &thref); + do { + int buf_thread_limit = + (BUFMAX - 22) / BUF_THREAD_ID_SIZE; + if (maxthreads > buf_thread_limit) { + maxthreads = buf_thread_limit; + } + } while (0); + remcomOutBuffer[0] = 'q'; + remcomOutBuffer[1] = 'M'; + remcomOutBuffer[4] = '0'; + pack_threadid(remcomOutBuffer + 5, &thref); + + /* If start flag set start at 0. */ + if (remcomInBuffer[2] == '1') + threadid = 0; + else + threadid = threadref_to_int(&thref); + for (nothreads = 0; + nothreads < maxthreads && + threadid < PID_MAX + MAX_NO_CPUS; + threadid++) { + thread = getthread(threadid); + if (thread) { + int_to_threadref(&thref, + threadid); + pack_threadid(remcomOutBuffer + + 21 + + nothreads * 16, + &thref); + nothreads++; + if (thread_min > threadid) + thread_min = threadid; + } + } + + if (threadid == PID_MAX + MAX_NO_CPUS) { + remcomOutBuffer[4] = '1'; + } + pack_hex_byte(remcomOutBuffer + 2, nothreads); + remcomOutBuffer[21 + nothreads * 16] = '\0'; + break; +#endif + case 'C': + /* Current thread id */ + remcomOutBuffer[0] = 'Q'; + remcomOutBuffer[1] = 'C'; + threadid = current->pid; + if (!threadid) { + /* + * idle thread + */ + for (threadid = PID_MAX; + threadid < PID_MAX + MAX_NO_CPUS; + threadid++) { + if (current == + idle_task(threadid - + PID_MAX)) + break; + } + } + int_to_threadref(&thref, threadid); + pack_threadid(remcomOutBuffer + 2, &thref); + remcomOutBuffer[18] = '\0'; + break; + + case 'E': + /* Print exception info */ + printexceptioninfo(exceptionVector, + err_code, remcomOutBuffer); + break; + case 'T': + ptr = &remcomInBuffer[0]; + if (strncmp(ptr, "qThreadExtraInfo,", + strlen("qThreadExtraInfo,")) == 0) { + ptr += strlen("qThreadExtraInfo,"); + hexToLong(&ptr, &tmpid); + p = getthread(tmpid); + print_extra_info(p, lbuf); + mem2hex(lbuf, remcomOutBuffer, + strlen(lbuf)); + } + break; +#if 0 + case 'T':{ + char * nptr; + /* Thread extra info */ + if (!cmp_str(&remcomInBuffer[2], + "hreadExtraInfo,", 15)) { + break; + } + ptr = &remcomInBuffer[17]; + hexToLong(&ptr, &threadid); + thread = getthread(threadid); + nptr = &thread->comm[0]; + length = 0; + ptr = &remcomOutBuffer[0]; + do { + length++; + ptr = pack_hex_byte(ptr, *nptr++); + } while (*nptr && length < 16); + /* + * would like that 16 to be the size of + * task_struct.comm but don't know the + * syntax.. + */ + *ptr = 0; + } +#endif + } + break; + + /* task related */ + case 'H': + switch (remcomInBuffer[1]) { + case 'g': + ptr = &remcomInBuffer[2]; + hexToLong(&ptr, &threadid); + thread = getthread(threadid); + if (!thread) { + remcomOutBuffer[0] = 'E'; + remcomOutBuffer[1] = '\0'; + break; + } + /* + * Just in case I forget what this is all about, + * the "thread info" command to gdb causes it + * to ask for a thread list. It then switches + * to each thread and asks for the registers. + * For this (and only this) usage, we want to + * fudge the registers of tasks not on the run + * list (i.e. waiting) to show the routine that + * called schedule. Also, gdb, is a minimalist + * in that if the current thread is the last + * it will not re-read the info when done. + * This means that in this case we must show + * the real registers. So here is how we do it: + * Each entry we keep track of the min + * thread in the list (the last that gdb will) + * get info for. We also keep track of the + * starting thread. + * "thread_list" is cleared when switching back + * to the min thread if it is was current, or + * if it was not current, thread_list is set + * to 1. When the switch to current comes, + * if thread_list is 1, clear it, else do + * nothing. + */ + usethread = thread; + if ((thread_list == 1) && + (thread == thread_list_start)) { + thread_list = 0; + } + if (thread_list && (threadid == thread_min)) { + if (thread == thread_list_start) { + thread_list = 0; + } else { + thread_list = 1; + } + } + /* follow through */ + case 'c': + remcomOutBuffer[0] = 'O'; + remcomOutBuffer[1] = 'K'; + remcomOutBuffer[2] = '\0'; + break; + } + break; + + /* Query thread status */ + case 'T': + ptr = &remcomInBuffer[1]; + hexToLong(&ptr, &threadid); + thread = getthread(threadid); + if (thread) { + remcomOutBuffer[0] = 'O'; + remcomOutBuffer[1] = 'K'; + remcomOutBuffer[2] = '\0'; + if (thread_min > threadid) + thread_min = threadid; + } else { + remcomOutBuffer[0] = 'E'; + remcomOutBuffer[1] = '\0'; + } + break; + + case 'Y': /* set up a hardware breakpoint */ + ptr = &remcomInBuffer[1]; + hexToLong(&ptr, &breakno); + ptr++; + hexToLong(&ptr, &breaktype); + ptr++; + hexToLong(&ptr, &length); + ptr++; + hexToLong(&ptr, &addr); + if (set_hw_break(breakno & 0x3, + breaktype & 0x3, + length & 0x3, addr) == 0) { + strcpy(remcomOutBuffer, "OK"); + } else { + strcpy(remcomOutBuffer, "ERROR"); + } + break; + + /* Remove hardware breakpoint */ + case 'y': + ptr = &remcomInBuffer[1]; + hexToLong(&ptr, &breakno); + if (remove_hw_break(breakno & 0x3) == 0) { + strcpy(remcomOutBuffer, "OK"); + } else { + strcpy(remcomOutBuffer, "ERROR"); + } + break; + + case 'r': /* reboot */ + strcpy(remcomOutBuffer, "OK"); + putpacket(remcomOutBuffer); + /*to_gdb("Rebooting\n"); */ + /* triplefault no return from here */ + { + static long no_idt[2]; + __asm__ __volatile__("lidt %0"::"m"(no_idt[0])); + BREAKPOINT; + } + + } /* switch */ + + /* reply to the request */ + putpacket(remcomOutBuffer); + } /* while(1==1) */ + /* + * reached by goto only. + */ + exit_kgdb: + /* + * Here is where we set up to trap a gdb function call. NEW_esp + * will be changed if we are trying to do this. We handle both + * adding and subtracting, thus allowing gdb to put grung on + * the stack which it removes later. + */ + if (NEW_esp != OLD_esp) { + unsigned long *ptr = END_OF_LOOKASIDE; + if (NEW_esp < OLD_esp) + ptr -= (OLD_esp - NEW_esp) / sizeof (unsigned long); + *--ptr = linux_regs->eflags; + *--ptr = linux_regs->cs; + *--ptr = linux_regs->rip; + *--ptr = linux_regs->rcx; + *--ptr = linux_regs->rbx; + *--ptr = linux_regs->rax; + linux_regs->rcx = NEW_esp - (sizeof (unsigned long) * 6); + linux_regs->rbx = (unsigned long) END_OF_LOOKASIDE; + if (NEW_esp < OLD_esp) { + linux_regs->rip = (unsigned long) fn_call_stub; + } else { + linux_regs->rip = (unsigned long) fn_rtn_stub; + linux_regs->rax = NEW_esp; + } + linux_regs->eflags &= ~(IF_BIT | TF_BIT); + } +#ifdef CONFIG_SMP + /* + * Release gdb wait locks + * Sanity check time. Must have at least one cpu to run. Also single + * step must not be done if the current cpu is on hold. + */ + if (spinlock_count == 1) { + int ss_hold = (regs.eflags & 0x100) && kgdb_info.hold_on_sstep; + int cpu_avail = 0; + int i; + + for (i = 0; i < MAX_NO_CPUS; i++) { + if (!cpu_online(i)) + break; + if (!hold_cpu(i)) { + cpu_avail = 1; + } + } + /* + * Early in the bring up there will be NO cpus on line... + */ + if (!cpu_avail && !cpus_empty(cpu_online_map)) { + to_gdb("No cpus unblocked, see 'kgdb_info.hold_cpu'\n"); + goto once_again; + } + if (hold_cpu(smp_processor_id()) && (regs.eflags & 0x100)) { + to_gdb + ("Current cpu must be unblocked to single step\n"); + goto once_again; + } + if (!(ss_hold)) { + int i; + for (i = 0; i < MAX_NO_CPUS; i++) { + if (!hold_cpu(i)) { + spin_unlock(&waitlocks[i]); + } + } + } else { + spin_unlock(&waitlocks[smp_processor_id()]); + } + /* Release kgdb spinlock */ + KGDB_SPIN_UNLOCK(&kgdb_spinlock); + /* + * If this cpu is on hold, this is where we + * do it. Note, the NMI will pull us out of here, + * but will return as the above lock is not held. + * We will stay here till another cpu releases the lock for us. + */ + spin_unlock_wait(waitlocks + smp_processor_id()); + local_irq_restore(flags); + return (1); + } +#if 0 +exit_just_unlock: +#endif +#endif + /* Release kgdb spinlock */ + KGDB_SPIN_UNLOCK(&kgdb_spinlock); + local_irq_restore(flags); + return (1); +} + +#undef regs +static int kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr) +{ + struct die_args *d = ptr; + + if (!kgdb_enabled || (cmd == DIE_DEBUG && user_mode(d->regs))) + return NOTIFY_DONE; + if (cmd == DIE_NMI_IPI) { + if (in_kgdb(d->regs)) + return NOTIFY_BAD; + } else if (kgdb_handle_exception(d->trapnr, d->signr, d->err, d->regs)) + return NOTIFY_BAD; /* skip */ + + return NOTIFY_DONE; +} + +static struct notifier_block kgdb_notifier = { + .notifier_call = kgdb_notify, + .priority = 0, +}; + +void set_debug_traps(void) +{ + static int initialized = 0; + + if (!initialized) { + initialized = 1; + notifier_chain_register(&die_chain, &kgdb_notifier); + } +} + +/* + * Provide the command line "gdb" initial break + */ +int __init kgdb_initial_break(char * str) +{ + if (*str == '\0'){ + breakpoint(); + return 1; + } + return 0; +} +__setup("gdb",kgdb_initial_break); + +/* This function will generate a breakpoint exception. It is used at the + beginning of a program to sync up with a debugger and can be used + otherwise as a quick means to stop program execution and "break" into + the debugger. */ +/* But really, just use the BREAKPOINT macro. We will handle the int stuff + */ + +void breakpoint(void) +{ + + set_debug_traps(); + kgdb_enabled = 1; +#if 0 + /* + * These calls were not enough to allow breakpoint to be + * called before trap_init(). I moved the argument parsing + * after trap_init() and it seems to work. + */ + set_intr_usr_gate(3,&int3); /* disable ints on trap */ + set_intr_gate(1,&debug); + set_intr_gate(14,&page_fault); +#endif + + BREAKPOINT; +} + +#ifdef later +/* + * possibly we should not go thru the traps.c code at all? Someday. + */ +void +do_kgdb_int3(struct pt_regs *regs, long error_code) +{ + kgdb_handle_exception(3, 5, error_code, regs); + return; +} +#endif +#undef regs +#ifdef CONFIG_TRAP_BAD_SYSCALL_EXITS +asmlinkage void +bad_sys_call_exit(int stuff) +{ + struct pt_regs *regs = (struct pt_regs *) &stuff; + printk("Sys call %d return with %x preempt_count\n", + (int) regs->orig_eax, preempt_count()); +} +#endif +#ifdef CONFIG_STACK_OVERFLOW_TEST +#include +asmlinkage void +stack_overflow(void) +{ +#ifdef BREAKPOINT + BREAKPOINT; +#else + printk("Kernel stack overflow, looping forever\n"); +#endif + while (1) { + } +} +#endif + +#if defined(CONFIG_SMP) || defined(CONFIG_KGDB_CONSOLE) +char gdbconbuf[BUFMAX]; + +static void +kgdb_gdb_message(const char *s, unsigned count) +{ + int i; + int wcount; + char *bufptr; + /* + * This takes care of NMI while spining out chars to gdb + */ + IF_SMP(in_kgdb_console = 1); + gdbconbuf[0] = 'O'; + bufptr = gdbconbuf + 1; + while (count > 0) { + if ((count << 1) > (BUFMAX - 2)) { + wcount = (BUFMAX - 2) >> 1; + } else { + wcount = count; + } + count -= wcount; + for (i = 0; i < wcount; i++) { + bufptr = pack_hex_byte(bufptr, s[i]); + } + *bufptr = '\0'; + s += wcount; + + putpacket(gdbconbuf); + + } + IF_SMP(in_kgdb_console = 0); +} +#endif +#ifdef CONFIG_SMP +static void +to_gdb(const char *s) +{ + int count = 0; + while (s[count] && (count++ < BUFMAX)) ; + kgdb_gdb_message(s, count); +} +#endif +#ifdef CONFIG_KGDB_CONSOLE +#include +#include +#include +#include + +void +kgdb_console_write(struct console *co, const char *s, unsigned count) +{ + + if (gdb_i386vector == -1) { + /* + * We have not yet talked to gdb. What to do... + * lets break, on continue we can do the write. + * But first tell him whats up. Uh, well no can do, + * as this IS the console. Oh well... + * We do need to wait or the messages will be lost. + * Other option would be to tell the above code to + * ignore this breakpoint and do an auto return, + * but that might confuse gdb. Also this happens + * early enough in boot up that we don't have the traps + * set up yet, so... + */ + breakpoint(); + } + kgdb_gdb_message(s, count); +} + +/* + * ------------------------------------------------------------ + * Serial KGDB driver + * ------------------------------------------------------------ + */ + +static struct console kgdbcons = { + name:"kgdb", + write:kgdb_console_write, +#ifdef CONFIG_KGDB_USER_CONSOLE + device:kgdb_console_device, +#endif + flags:CON_PRINTBUFFER | CON_ENABLED, + index:-1, +}; + +/* + * The trick here is that this file gets linked before printk.o + * That means we get to peer at the console info in the command + * line before it does. If we are up, we register, otherwise, + * do nothing. By returning 0, we allow printk to look also. + */ +static int kgdb_console_enabled; + +int __init +kgdb_console_init(char *str) +{ + if ((strncmp(str, "kgdb", 4) == 0) || (strncmp(str, "gdb", 3) == 0)) { + register_console(&kgdbcons); + kgdb_console_enabled = 1; + } + return 0; /* let others look at the string */ +} + +__setup("console=", kgdb_console_init); + +#ifdef CONFIG_KGDB_USER_CONSOLE +static kdev_t kgdb_console_device(struct console *c); +/* This stuff sort of works, but it knocks out telnet devices + * we are leaving it here in case we (or you) find time to figure it out + * better.. + */ + +/* + * We need a real char device as well for when the console is opened for user + * space activities. + */ + +static int +kgdb_consdev_open(struct inode *inode, struct file *file) +{ + return 0; +} + +static ssize_t +kgdb_consdev_write(struct file *file, const char *buf, + size_t count, loff_t * ppos) +{ + int size, ret = 0; + static char kbuf[128]; + static DECLARE_MUTEX(sem); + + /* We are not reentrant... */ + if (down_interruptible(&sem)) + return -ERESTARTSYS; + + while (count > 0) { + /* need to copy the data from user space */ + size = count; + if (size > sizeof (kbuf)) + size = sizeof (kbuf); + if (copy_from_user(kbuf, buf, size)) { + ret = -EFAULT; + break;; + } + kgdb_console_write(&kgdbcons, kbuf, size); + count -= size; + ret += size; + buf += size; + } + + up(&sem); + + return ret; +} + +struct file_operations kgdb_consdev_fops = { + open:kgdb_consdev_open, + write:kgdb_consdev_write +}; +static kdev_t +kgdb_console_device(struct console *c) +{ + return MKDEV(TTYAUX_MAJOR, 1); +} + +/* + * This routine gets called from the serial stub in the i386/lib + * This is so it is done late in bring up (just before the console open). + */ +void +kgdb_console_finit(void) +{ + if (kgdb_console_enabled) { + char *cptr = cdevname(MKDEV(TTYAUX_MAJOR, 1)); + char *cp = cptr; + while (*cptr && *cptr != '(') + cptr++; + *cptr = 0; + unregister_chrdev(TTYAUX_MAJOR, cp); + register_chrdev(TTYAUX_MAJOR, "kgdb", &kgdb_consdev_fops); + } +} +#endif +#endif +#ifdef CONFIG_KGDB_TS +#include /* time stamp code */ +#include /* in_interrupt */ +#ifdef CONFIG_KGDB_TS_64 +#define DATA_POINTS 64 +#endif +#ifdef CONFIG_KGDB_TS_128 +#define DATA_POINTS 128 +#endif +#ifdef CONFIG_KGDB_TS_256 +#define DATA_POINTS 256 +#endif +#ifdef CONFIG_KGDB_TS_512 +#define DATA_POINTS 512 +#endif +#ifdef CONFIG_KGDB_TS_1024 +#define DATA_POINTS 1024 +#endif +#ifndef DATA_POINTS +#define DATA_POINTS 128 /* must be a power of two */ +#endif +#define INDEX_MASK (DATA_POINTS - 1) +#if (INDEX_MASK & DATA_POINTS) +#error "CONFIG_KGDB_TS_COUNT must be a power of 2" +#endif +struct kgdb_and_then_struct { +#ifdef CONFIG_SMP + int on_cpu; +#endif + struct task_struct *task; + long long at_time; + int from_ln; + char *in_src; + void *from; + int *with_shpf; + int data0; + int data1; +}; +struct kgdb_and_then_struct2 { +#ifdef CONFIG_SMP + int on_cpu; +#endif + struct task_struct *task; + long long at_time; + int from_ln; + char *in_src; + void *from; + int *with_shpf; + struct task_struct *t1; + struct task_struct *t2; +}; +struct kgdb_and_then_struct kgdb_data[DATA_POINTS]; + +struct kgdb_and_then_struct *kgdb_and_then = &kgdb_data[0]; +int kgdb_and_then_count; + +void +kgdb_tstamp(int line, char *source, int data0, int data1) +{ + static spinlock_t ts_spin = SPIN_LOCK_UNLOCKED; + unsigned long flags; + + local_irq_save(flags); + spin_lock(&ts_spin); + rdtscll(kgdb_and_then->at_time); +#ifdef CONFIG_SMP + kgdb_and_then->on_cpu = smp_processor_id(); +#endif + kgdb_and_then->task = current; + kgdb_and_then->from_ln = line; + kgdb_and_then->in_src = source; + kgdb_and_then->from = __builtin_return_address(0); + kgdb_and_then->with_shpf = (int *)(long)(((flags & IF_BIT) >> 9) | + (preempt_count() << 8)); + kgdb_and_then->data0 = data0; + kgdb_and_then->data1 = data1; + kgdb_and_then = &kgdb_data[++kgdb_and_then_count & INDEX_MASK]; + spin_unlock(&ts_spin); + local_irq_restore(flags); +#ifdef CONFIG_PREEMPT + +#endif + return; +} +#endif +typedef int gdb_debug_hook(int exceptionVector, + int signo, int err_code, struct pt_regs *linux_regs); +gdb_debug_hook *linux_debug_hook = &kgdb_handle_exception; /* histerical reasons... */ + +static int kgdb_need_breakpoint[NR_CPUS]; + +void kgdb_schedule_breakpoint(void) +{ + kgdb_need_breakpoint[smp_processor_id()] = 1; +} + +void kgdb_process_breakpoint(void) +{ + /* + * Handle a breakpoint queued from inside network driver code + * to avoid reentrancy issues + */ + if (kgdb_need_breakpoint[smp_processor_id()]) { + kgdb_need_breakpoint[smp_processor_id()] = 0; + kgdb_enabled = 1; + BREAKPOINT; + } +} + --- linux-2.6.6/arch/x86_64/kernel/Makefile 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/x86_64/kernel/Makefile 2004-05-10 01:19:24.366034856 -0700 @@ -25,8 +25,10 @@ obj-$(CONFIG_EARLY_PRINTK) += early_prin obj-$(CONFIG_GART_IOMMU) += pci-gart.o aperture.o obj-$(CONFIG_DUMMY_IOMMU) += pci-nommu.o pci-dma.o obj-$(CONFIG_SWIOTLB) += swiotlb.o +obj-$(CONFIG_SCHED_SMT) += domain.o obj-$(CONFIG_MODULES) += module.o +obj-$(CONFIG_KGDB) += kgdb_stub.o obj-y += topology.o --- linux-2.6.6/arch/x86_64/kernel/process.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/x86_64/kernel/process.c 2004-05-10 01:19:31.148003840 -0700 @@ -574,12 +574,6 @@ asmlinkage long sys_vfork(struct pt_regs NULL, NULL); } -/* - * These bracket the sleeping functions.. - */ -#define first_sched ((unsigned long) scheduling_functions_start_here) -#define last_sched ((unsigned long) scheduling_functions_end_here) - unsigned long get_wchan(struct task_struct *p) { unsigned long stack; @@ -596,14 +590,12 @@ unsigned long get_wchan(struct task_stru if (fp < (unsigned long)stack || fp > (unsigned long)stack+THREAD_SIZE) return 0; rip = *(u64 *)(fp+8); - if (rip < first_sched || rip >= last_sched) + if (!in_sched_functions(rip)) return rip; fp = *(u64 *)fp; } while (count++ < 16); return 0; } -#undef last_sched -#undef first_sched long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) { --- linux-2.6.6/arch/x86_64/kernel/setup.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/x86_64/kernel/setup.c 2004-05-10 01:19:18.580914328 -0700 @@ -100,7 +100,6 @@ extern int root_mountflags; extern char _text, _etext, _edata, _end; char command_line[COMMAND_LINE_SIZE]; -char saved_command_line[COMMAND_LINE_SIZE]; struct resource standard_io_resources[] = { { "dma1", 0x00, 0x1f, IORESOURCE_BUSY | IORESOURCE_IO }, --- linux-2.6.6/arch/x86_64/kernel/smpboot.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/x86_64/kernel/smpboot.c 2004-05-10 01:19:24.222056744 -0700 @@ -73,7 +73,7 @@ struct cpuinfo_x86 cpu_data[NR_CPUS] __c /* Set when the idlers are all forked */ int smp_threads_ready; -char cpu_sibling_map[NR_CPUS] __cacheline_aligned; +cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned; /* * Trampoline 80x86 program as an array. @@ -874,31 +874,36 @@ static void __init smp_boot_cpus(unsigne } /* - * If Hyper-Threading is avaialble, construct cpu_sibling_map[], so - * that we can tell the sibling CPU efficiently. + * Construct cpu_sibling_map[], so that we can tell the + * sibling CPU efficiently. */ - if (cpu_has_ht && smp_num_siblings > 1) { - for (cpu = 0; cpu < NR_CPUS; cpu++) - cpu_sibling_map[cpu] = NO_PROC_ID; - - for (cpu = 0; cpu < NR_CPUS; cpu++) { - int i; - if (!cpu_isset(cpu, cpu_callout_map)) - continue; + for (cpu = 0; cpu < NR_CPUS; cpu++) + cpus_clear(cpu_sibling_map[cpu]); + + for (cpu = 0; cpu < NR_CPUS; cpu++) { + int siblings = 0; + int i; + if (!cpu_isset(cpu, cpu_callout_map)) + continue; + if (smp_num_siblings > 1) { for (i = 0; i < NR_CPUS; i++) { - if (i == cpu || !cpu_isset(i, cpu_callout_map)) + if (!cpu_isset(i, cpu_callout_map)) continue; if (phys_proc_id[cpu] == phys_proc_id[i]) { - cpu_sibling_map[cpu] = i; - break; + siblings++; + cpu_set(i, cpu_sibling_map[cpu]); } } - if (cpu_sibling_map[cpu] == (char)NO_PROC_ID) { - smp_num_siblings = 1; - printk(KERN_WARNING "WARNING: No sibling found for CPU %d.\n", cpu); - } + } else { + siblings++; + cpu_set(cpu, cpu_sibling_map[cpu]); } + + if (siblings != smp_num_siblings) + printk(KERN_WARNING + "WARNING: %d siblings found for CPU%d, should be %d\n", + siblings, cpu, smp_num_siblings); } Dprintk("Boot done.\n"); --- linux-2.6.6/arch/x86_64/kernel/smp.c 2003-11-23 19:03:00.000000000 -0800 +++ 25/arch/x86_64/kernel/smp.c 2004-05-10 01:19:49.912151256 -0700 @@ -362,6 +362,18 @@ void smp_send_reschedule(int cpu) send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR); } +#ifdef CONFIG_KGDB +/* + * By using the NMI code instead of a vector we just sneak thru the + * word generator coming out with just what we want. AND it does + * not matter if clustered_apic_mode is set or not. + */ +void smp_send_nmi_allbutself(void) +{ + send_IPI_allbutself(APIC_DM_NMI); +} +#endif + /* * Structure and data for smp_call_function(). This is designed to minimise * static memory requirements. It also looks cleaner. @@ -404,6 +416,9 @@ int smp_call_function (void (*func) (voi if (!cpus) return 0; + /* Can deadlock when called with interrupts disabled */ + WARN_ON(irqs_disabled()); + data.func = func; data.info = info; atomic_set(&data.started, 0); --- linux-2.6.6/arch/x86_64/kernel/time.c 2004-03-10 20:41:27.000000000 -0800 +++ 25/arch/x86_64/kernel/time.c 2004-05-10 01:19:51.714877200 -0700 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -54,7 +55,7 @@ static int nohpet __initdata = 0; unsigned int cpu_khz; /* TSC clocks / usec, not used here */ unsigned long hpet_period; /* fsecs / HPET clock */ unsigned long hpet_tick; /* HPET clocks / interrupt */ -unsigned long vxtime_hz = 1193182; +unsigned long vxtime_hz = PIT_TICK_RATE; int report_lost_ticks; /* command line option */ unsigned long long monotonic_base; @@ -531,7 +532,8 @@ static int time_cpufreq_notifier(struct cpu_khz_ref = cpu_khz; } if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) || - (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) { + (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) || + (val == CPUFREQ_RESUMECHANGE)) { *lpj = cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new); @@ -600,8 +602,8 @@ static unsigned int __init pit_calibrate outb((inb(0x61) & ~0x02) | 0x01, 0x61); outb(0xb0, 0x43); - outb((1193182 / (1000 / 50)) & 0xff, 0x42); - outb((1193182 / (1000 / 50)) >> 8, 0x42); + outb((PIT_TICK_RATE / (1000 / 50)) & 0xff, 0x42); + outb((PIT_TICK_RATE / (1000 / 50)) >> 8, 0x42); rdtscll(start); sync_core(); while ((inb(0x61) & 0x20) == 0); --- linux-2.6.6/arch/x86_64/kernel/traps.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/arch/x86_64/kernel/traps.c 2004-05-10 01:19:07.425610192 -0700 @@ -45,6 +45,9 @@ #include #include +#ifdef CONFIG_KGDB +#include +#endif extern struct gate_struct idt_table[256]; --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/arch/x86_64/lib/kgdb_serial.c 2004-05-10 01:19:07.427609888 -0700 @@ -0,0 +1,490 @@ +/* + * Serial interface GDB stub + * + * Written (hacked together) by David Grothe (dave@gcom.com) + * Modified to allow invokation early in boot see also + * kgdb.h for instructions by George Anzinger(george@mvista.com) + * Modified to handle debugging over ethernet by Robert Walsh + * and wangdi , based on + * code by San Mehat. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_KGDB_USER_CONSOLE +extern void kgdb_console_finit(void); +#endif +#define PRNT_off +#define TEST_EXISTANCE +#ifdef PRNT +#define dbprintk(s) printk s +#else +#define dbprintk(s) +#endif +#define TEST_INTERRUPT_off +#ifdef TEST_INTERRUPT +#define intprintk(s) printk s +#else +#define intprintk(s) +#endif + +#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT) + +#define GDB_BUF_SIZE 512 /* power of 2, please */ + +static char gdb_buf[GDB_BUF_SIZE]; +static int gdb_buf_in_inx; +static atomic_t gdb_buf_in_cnt; +static int gdb_buf_out_inx; + +struct async_struct *gdb_async_info; +static int gdb_async_irq; + +#define outb_px(a,b) outb_p(b,a) + +static void program_uart(struct async_struct *info); +static void write_char(struct async_struct *info, int chr); +/* + * Get a byte from the hardware data buffer and return it + */ +static int +read_data_bfr(struct async_struct *info) +{ + char it = inb_p(info->port + UART_LSR); + + if (it & UART_LSR_DR) + return (inb_p(info->port + UART_RX)); + /* + * If we have a framing error assume somebody messed with + * our uart. Reprogram it and send '-' both ways... + */ + if (it & 0xc) { + program_uart(info); + write_char(info, '-'); + return ('-'); + } + return (-1); + +} /* read_data_bfr */ + +/* + * Get a char if available, return -1 if nothing available. + * Empty the receive buffer first, then look at the interface hardware. + + * Locking here is a bit of a problem. We MUST not lock out communication + * if we are trying to talk to gdb about a kgdb entry. ON the other hand + * we can loose chars in the console pass thru if we don't lock. It is also + * possible that we could hold the lock or be waiting for it when kgdb + * NEEDS to talk. Since kgdb locks down the world, it does not need locks. + * We do, of course have possible issues with interrupting a uart operation, + * but we will just depend on the uart status to help keep that straight. + + */ +static spinlock_t uart_interrupt_lock = SPIN_LOCK_UNLOCKED; +#ifdef CONFIG_SMP +extern spinlock_t kgdb_spinlock; +#endif + +static int +read_char(struct async_struct *info) +{ + int chr; + unsigned long flags; + local_irq_save(flags); +#ifdef CONFIG_SMP + if (!spin_is_locked(&kgdb_spinlock)) { + spin_lock(&uart_interrupt_lock); + } +#endif + if (atomic_read(&gdb_buf_in_cnt) != 0) { /* intr routine has q'd chars */ + chr = gdb_buf[gdb_buf_out_inx++]; + gdb_buf_out_inx &= (GDB_BUF_SIZE - 1); + atomic_dec(&gdb_buf_in_cnt); + } else { + chr = read_data_bfr(info); + } +#ifdef CONFIG_SMP + if (!spin_is_locked(&kgdb_spinlock)) { + spin_unlock(&uart_interrupt_lock); + } +#endif + local_irq_restore(flags); + return (chr); +} + +/* + * Wait until the interface can accept a char, then write it. + */ +static void +write_char(struct async_struct *info, int chr) +{ + while (!(inb_p(info->port + UART_LSR) & UART_LSR_THRE)) ; + + outb_p(chr, info->port + UART_TX); + +} /* write_char */ + +/* + * Mostly we don't need a spinlock, but since the console goes + * thru here with interrutps on, well, we need to catch those + * chars. + */ +/* + * This is the receiver interrupt routine for the GDB stub. + * It will receive a limited number of characters of input + * from the gdb host machine and save them up in a buffer. + * + * When the gdb stub routine tty_getDebugChar() is called it + * draws characters out of the buffer until it is empty and + * then reads directly from the serial port. + * + * We do not attempt to write chars from the interrupt routine + * since the stubs do all of that via tty_putDebugChar() which + * writes one byte after waiting for the interface to become + * ready. + * + * The debug stubs like to run with interrupts disabled since, + * after all, they run as a consequence of a breakpoint in + * the kernel. + * + * Perhaps someone who knows more about the tty driver than I + * care to learn can make this work for any low level serial + * driver. + */ +static irqreturn_t +gdb_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct async_struct *info; + unsigned long flags; + + info = gdb_async_info; + if (!info || !info->tty || irq != gdb_async_irq) + return IRQ_NONE; + + local_irq_save(flags); + spin_lock(&uart_interrupt_lock); + do { + int chr = read_data_bfr(info); + intprintk(("Debug char on int: %x hex\n", chr)); + if (chr < 0) + continue; + + if (chr == 3) { /* Ctrl-C means remote interrupt */ + BREAKPOINT; + continue; + } + + if (atomic_read(&gdb_buf_in_cnt) >= GDB_BUF_SIZE) { + /* buffer overflow tosses early char */ + read_char(info); + } + gdb_buf[gdb_buf_in_inx++] = chr; + gdb_buf_in_inx &= (GDB_BUF_SIZE - 1); + } while (inb_p(info->port + UART_IIR) & UART_IIR_RDI); + spin_unlock(&uart_interrupt_lock); + local_irq_restore(flags); + return IRQ_HANDLED; +} /* gdb_interrupt */ + +/* + * Just a NULL routine for testing. + */ +void +gdb_null(void) +{ +} /* gdb_null */ + +/* These structure are filled in with values defined in asm/kgdb_local.h + */ +static struct serial_state state = SB_STATE; +static struct async_struct local_info = SB_INFO; +static int ok_to_enable_ints = 0; +static void kgdb_enable_ints_now(void); + +extern char *kgdb_version; +/* + * Hook an IRQ for KGDB. + * + * This routine is called from tty_putDebugChar, below. + */ +static int ints_disabled = 1; +int +gdb_hook_interrupt(struct async_struct *info, int verb) +{ + struct serial_state *state = info->state; + unsigned long flags; + int port; +#ifdef TEST_EXISTANCE + int scratch, scratch2; +#endif + + /* The above fails if memory managment is not set up yet. + * Rather than fail the set up, just keep track of the fact + * and pick up the interrupt thing later. + */ + gdb_async_info = info; + port = gdb_async_info->port; + gdb_async_irq = state->irq; + if (verb) { + printk("kgdb %s : port =%x, IRQ=%d, divisor =%d\n", + kgdb_version, + port, + gdb_async_irq, gdb_async_info->state->custom_divisor); + } + local_irq_save(flags); +#ifdef TEST_EXISTANCE + /* Existance test */ + /* Should not need all this, but just in case.... */ + + scratch = inb_p(port + UART_IER); + outb_px(port + UART_IER, 0); + outb_px(0xff, 0x080); + scratch2 = inb_p(port + UART_IER); + outb_px(port + UART_IER, scratch); + if (scratch2) { + printk + ("gdb_hook_interrupt: Could not clear IER, not a UART!\n"); + local_irq_restore(flags); + return 1; /* We failed; there's nothing here */ + } + scratch2 = inb_p(port + UART_LCR); + outb_px(port + UART_LCR, 0xBF); /* set up for StarTech test */ + outb_px(port + UART_EFR, 0); /* EFR is the same as FCR */ + outb_px(port + UART_LCR, 0); + outb_px(port + UART_FCR, UART_FCR_ENABLE_FIFO); + scratch = inb_p(port + UART_IIR) >> 6; + if (scratch == 1) { + printk("gdb_hook_interrupt: Undefined UART type!" + " Not a UART! \n"); + local_irq_restore(flags); + return 1; + } else { + dbprintk(("gdb_hook_interrupt: UART type " + "is %d where 0=16450, 2=16550 3=16550A\n", scratch)); + } + scratch = inb_p(port + UART_MCR); + outb_px(port + UART_MCR, UART_MCR_LOOP | scratch); + outb_px(port + UART_MCR, UART_MCR_LOOP | 0x0A); + scratch2 = inb_p(port + UART_MSR) & 0xF0; + outb_px(port + UART_MCR, scratch); + if (scratch2 != 0x90) { + printk("gdb_hook_interrupt: " + "Loop back test failed! Not a UART!\n"); + local_irq_restore(flags); + return scratch2 + 1000; /* force 0 to fail */ + } +#endif /* test existance */ + program_uart(info); + local_irq_restore(flags); + + return (0); + +} /* gdb_hook_interrupt */ + +static void +program_uart(struct async_struct *info) +{ + int port = info->port; + + (void) inb_p(port + UART_RX); + outb_px(port + UART_IER, 0); + + (void) inb_p(port + UART_RX); /* serial driver comments say */ + (void) inb_p(port + UART_IIR); /* this clears the interrupt regs */ + (void) inb_p(port + UART_MSR); + outb_px(port + UART_LCR, UART_LCR_WLEN8 | UART_LCR_DLAB); + outb_px(port + UART_DLL, info->state->custom_divisor & 0xff); /* LS */ + outb_px(port + UART_DLM, info->state->custom_divisor >> 8); /* MS */ + outb_px(port + UART_MCR, info->MCR); + + outb_px(port + UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1 | UART_FCR_CLEAR_XMIT | UART_FCR_CLEAR_RCVR); /* set fcr */ + outb_px(port + UART_LCR, UART_LCR_WLEN8); /* reset DLAB */ + outb_px(port + UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1); /* set fcr */ + if (!ints_disabled) { + intprintk(("KGDB: Sending %d to port %x offset %d\n", + gdb_async_info->IER, + (int) gdb_async_info->port, UART_IER)); + outb_px(gdb_async_info->port + UART_IER, gdb_async_info->IER); + } + return; +} + +/* + * tty_getDebugChar + * + * This is a GDB stub routine. It waits for a character from the + * serial interface and then returns it. If there is no serial + * interface connection then it returns a bogus value which will + * almost certainly cause the system to hang. In the + */ +int kgdb_in_isr = 0; +int kgdb_in_lsr = 0; +extern spinlock_t kgdb_spinlock; + +/* Caller takes needed protections */ + +int +tty_getDebugChar(void) +{ + volatile int chr, dum, time, end_time; + + dbprintk(("tty_getDebugChar(port %x): ", gdb_async_info->port)); + + if (gdb_async_info == NULL) { + gdb_hook_interrupt(&local_info, 0); + } + /* + * This trick says if we wait a very long time and get + * no char, return the -1 and let the upper level deal + * with it. + */ + rdtsc(dum, time); + end_time = time + 2; + while (((chr = read_char(gdb_async_info)) == -1) && + (end_time - time) > 0) { + rdtsc(dum, time); + }; + /* + * This covers our butts if some other code messes with + * our uart, hay, it happens :o) + */ + if (chr == -1) + program_uart(gdb_async_info); + + dbprintk(("%c\n", chr > ' ' && chr < 0x7F ? chr : ' ')); + return (chr); + +} /* tty_getDebugChar */ + +static int count = 3; +static spinlock_t one_at_atime = SPIN_LOCK_UNLOCKED; + +static int __init +kgdb_enable_ints(void) +{ + set_debug_traps(); + if (kgdboe) { + return 0; + } + if (gdb_async_info == NULL) { + gdb_hook_interrupt(&local_info, 1); + } + ok_to_enable_ints = 1; + kgdb_enable_ints_now(); +#ifdef CONFIG_KGDB_USER_CONSOLE + kgdb_console_finit(); +#endif + return 0; +} + +#ifdef CONFIG_SERIAL_8250 +void shutdown_for_kgdb(struct async_struct *gdb_async_info); +#endif + +#define kgdb_mem_init_done() (1) + +static void +kgdb_enable_ints_now(void) +{ + if (!spin_trylock(&one_at_atime)) + return; + if (!ints_disabled) + goto exit; + if (kgdb_mem_init_done() && + ints_disabled) { /* don't try till mem init */ +#ifdef CONFIG_SERIAL_8250 + /* + * The ifdef here allows the system to be configured + * without the serial driver. + * Don't make it a module, however, it will steal the port + */ + shutdown_for_kgdb(gdb_async_info); +#endif + ints_disabled = request_irq(gdb_async_info->state->irq, + gdb_interrupt, + IRQ_T(gdb_async_info), + "KGDB-stub", NULL); + intprintk(("KGDB: request_irq returned %d\n", ints_disabled)); + } + if (!ints_disabled) { + intprintk(("KGDB: Sending %d to port %x offset %d\n", + gdb_async_info->IER, + (int) gdb_async_info->port, UART_IER)); + outb_px(gdb_async_info->port + UART_IER, gdb_async_info->IER); + } + exit: + spin_unlock(&one_at_atime); +} + +/* + * tty_putDebugChar + * + * This is a GDB stub routine. It waits until the interface is ready + * to transmit a char and then sends it. If there is no serial + * interface connection then it simply returns to its caller, having + * pretended to send the char. Caller takes needed protections. + */ +void +tty_putDebugChar(int chr) +{ + dbprintk(("tty_putDebugChar(port %x): chr=%02x '%c', ints_on=%d\n", + gdb_async_info->port, + chr, + chr > ' ' && chr < 0x7F ? chr : ' ', ints_disabled ? 0 : 1)); + + if (gdb_async_info == NULL) { + gdb_hook_interrupt(&local_info, 0); + } + + write_char(gdb_async_info, chr); /* this routine will wait */ + count = (chr == '#') ? 0 : count + 1; + if ((count == 2)) { /* try to enable after */ + if (ints_disabled & ok_to_enable_ints) + kgdb_enable_ints_now(); /* try to enable after */ + + /* We do this a lot because, well we really want to get these + * interrupts. The serial driver will clear these bits when it + * initializes the chip. Every thing else it does is ok, + * but this. + */ + if (!ints_disabled) { + outb_px(gdb_async_info->port + UART_IER, + gdb_async_info->IER); + } + } + +} /* tty_putDebugChar */ + +/* + * This does nothing for the serial port, since it doesn't buffer. + */ + +void tty_flushDebugChar(void) +{ +} + +module_init(kgdb_enable_ints); --- linux-2.6.6/arch/x86_64/lib/Makefile 2004-04-03 20:39:11.000000000 -0800 +++ 25/arch/x86_64/lib/Makefile 2004-05-10 01:19:07.428609736 -0700 @@ -10,3 +10,4 @@ lib-y := csum-partial.o csum-copy.o csum lib-y += memcpy.o memmove.o memset.o copy_user.o lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o +lib-$(CONFIG_KGDB) += kgdb_serial.o --- linux-2.6.6/arch/x86_64/mm/ioremap.c 2003-10-08 15:07:08.000000000 -0700 +++ 25/arch/x86_64/mm/ioremap.c 2004-05-10 01:19:50.734026312 -0700 @@ -132,13 +132,13 @@ void * __ioremap(unsigned long phys_addr * Don't allow anybody to remap normal RAM that we're using.. */ if (phys_addr < virt_to_phys(high_memory)) { +#ifndef CONFIG_DISCONTIGMEM char *t_addr, *t_end; + struct page *page; t_addr = __va(phys_addr); t_end = t_addr + (size - 1); -#ifndef CONFIG_DISCONTIGMEM - struct page *page; for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++) if(!PageReserved(page)) return NULL; --- linux-2.6.6/CREDITS 2004-05-09 21:07:22.000000000 -0700 +++ 25/CREDITS 2004-05-10 01:19:03.986133072 -0700 @@ -1284,8 +1284,8 @@ P: 1024D/77D4FC9B F5C5 1C20 1DFC DEC3 31 D: National Language Support D: Linux Internationalization Project D: German Localization for Linux and GNU software -S: Helenenstrasse 18 -S: 65183 Wiesbaden +S: Kriemhildring 12a +S: 65795 Hattersheim am Main S: Germany N: Christoph Hellwig --- linux-2.6.6/Documentation/binfmt_misc.txt 2003-10-08 15:07:08.000000000 -0700 +++ 25/Documentation/binfmt_misc.txt 2004-05-10 01:19:25.439871608 -0700 @@ -15,7 +15,7 @@ First you must mount binfmt_misc: mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc To actually register a new binary type, you have to set up a string looking like -:name:type:offset:magic:mask:interpreter: (where you can choose the ':' upon +:name:type:offset:magic:mask:interpreter:flags (where you can choose the ':' upon your needs) and echo it to /proc/sys/fs/binfmt_misc/register. Here is what the fields mean: - 'name' is an identifier string. A new /proc file will be created with this @@ -34,6 +34,28 @@ Here is what the fields mean: The mask is anded with the byte sequence of the file. - 'interpreter' is the program that should be invoked with the binary as first argument (specify the full path) + - 'flags' is an optional field that controls several aspects of the invocation + of the interpreter. It is a string of capital letters, each controls a certain + aspect. The following flags are supported - + 'P' - preserve-argv[0]. Legacy behavior of binfmt_misc is to overwrite the + original argv[0] with the full path to the binary. When this flag is + included, binfmt_misc will add an argument to the argument vector for + this purpose, thus preserving the original argv[0]. + 'O' - open-binary. Legacy behavior of binfmt_misc is to pass the full path + of the binary to the interpreter as an argument. When this flag is + included, binfmt_misc will open the file for reading and pass its + descriptor as an argument, instead of the full path, thus allowing + the interpreter to execute non-readable binaries. This feature should + be used with care - the interpreter has to be trusted not to emit + the contents of the non-readable binary. + 'C' - credentials. Currently, the behavior of binfmt_misc is to calculate + the credentials and security token of the new process according to + the interpreter. When this flag is included, these attributes are + calculated according to the binary. It also implies the 'O' flag. + This feature should be used with care as the interpreter + will run with root permissions when a setuid binary owned by root + is run with binfmt_misc. + There are some restrictions: - the whole register string may not exceed 255 characters @@ -83,9 +105,9 @@ If you want to pass special arguments to write a wrapper script for it. See Documentation/java.txt for an example. -Your interpreter should NOT look in the PATH for the filename; the -kernel passes it the full filename to use. Using the PATH can cause -unexpected behaviour and be a security hazard. +Your interpreter should NOT look in the PATH for the filename; the kernel +passes it the full filename (or the file descriptor) to use. Using $PATH can +cause unexpected behaviour and can be a security hazard. There is a web page about binfmt_misc at --- linux-2.6.6/Documentation/cachetlb.txt 2003-10-08 15:07:08.000000000 -0700 +++ 25/Documentation/cachetlb.txt 2004-05-10 01:19:13.099747592 -0700 @@ -322,10 +322,10 @@ maps this page at its virtual address. about doing this. The idea is, first at flush_dcache_page() time, if - page->mapping->i_mmap{,_shared} are empty lists, just mark the - architecture private page flag bit. Later, in - update_mmu_cache(), a check is made of this flag bit, and if - set the flush is done and the flag bit is cleared. + page->mapping->i_mmap is an empty tree and ->i_mmap_nonlinear + an empty list, just mark the architecture private page flag bit. + Later, in update_mmu_cache(), a check is made of this flag bit, + and if set the flush is done and the flag bit is cleared. IMPORTANT NOTE: It is often important, if you defer the flush, that the actual flush occurs on the same CPU --- linux-2.6.6/Documentation/cpu-freq/core.txt 2003-08-08 22:55:10.000000000 -0700 +++ 25/Documentation/cpu-freq/core.txt 2004-05-10 01:19:01.777468840 -0700 @@ -92,3 +92,7 @@ values: cpu - number of the affected CPU old - old frequency new - new frequency + +If the cpufreq core detects the frequency has changed while the system +was suspended, these notifiers are called with CPUFREQ_RESUMECHANGE as +second argument. --- linux-2.6.6/Documentation/filesystems/proc.txt 2004-05-09 21:07:22.000000000 -0700 +++ 25/Documentation/filesystems/proc.txt 2004-05-10 01:19:56.646127536 -0700 @@ -1208,6 +1208,20 @@ On the other hand, enabling this feat and thrash the system to death, so large and/or important servers will want to set this value to 0. +nr_hugepages and hugetlb_shm_group +---------------------------------- + +nr_hugepages configures number of hugetlb page reserved for the system. + +hugetlb_shm_group contains group id that is allowed to create SysV shared +memory segment using hugetlb page. + +mlock_group +----------- + +Specifies a group ID. Users who belong to this supplementary group are able +to use mlock() without restrictions. + 2.5 /proc/sys/dev - Device specific parameters ---------------------------------------------- @@ -1848,10 +1862,3 @@ need to recompile the kernel, or even command to write value into these files, thereby changing the default settings of the kernel. ------------------------------------------------------------------------------ - - - - - - - --- linux-2.6.6/Documentation/i2c/porting-clients 2004-05-09 21:07:22.000000000 -0700 +++ 25/Documentation/i2c/porting-clients 2004-05-10 01:19:02.902297840 -0700 @@ -62,9 +62,9 @@ Technical changes: patch to the Documentation/i2c/sysfs-interface file. * [Attach] For I2C drivers, the attach function should make sure - that the adapter's class has I2C_ADAP_CLASS_SMBUS, using the + that the adapter's class has I2C_CLASS_SMBUS, using the following construct: - if (!(adapter->class & I2C_ADAP_CLASS_SMBUS)) + if (!(adapter->class & I2C_CLASS_SMBUS)) return 0; ISA-only drivers of course don't need this. --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/Documentation/i386/kgdb/andthen 2004-05-10 01:19:06.876693640 -0700 @@ -0,0 +1,100 @@ + +define set_andthen + set var $thp=0 + set var $thp=(struct kgdb_and_then_struct *)&kgdb_data[0] + set var $at_size = (sizeof kgdb_data)/(sizeof *$thp) + set var $at_oc=kgdb_and_then_count + set var $at_cc=$at_oc +end + +define andthen_next + set var $at_cc=$arg0 +end + +define andthen + andthen_set_edge + if ($at_cc >= $at_oc) + printf "Outside window. Window size is %d\n",($at_oc-$at_low) + else + printf "%d: ",$at_cc + output *($thp+($at_cc++ % $at_size )) + printf "\n" + end +end +define andthen_set_edge + set var $at_oc=kgdb_and_then_count + set var $at_low = $at_oc - $at_size + if ($at_low < 0 ) + set var $at_low = 0 + end + if (( $at_cc > $at_oc) || ($at_cc < $at_low)) + printf "Count outside of window, setting count to " + if ($at_cc >= $at_oc) + set var $at_cc = $at_oc + else + set var $at_cc = $at_low + end + printf "%d\n",$at_cc + end +end + +define beforethat + andthen_set_edge + if ($at_cc <= $at_low) + printf "Outside window. Window size is %d\n",($at_oc-$at_low) + else + printf "%d: ",$at_cc-1 + output *($thp+(--$at_cc % $at_size )) + printf "\n" + end +end + +document andthen_next + andthen_next + . sets the number of the event to display next. If this event + . is not in the event pool, either andthen or beforethat will + . correct it to the nearest event pool edge. The event pool + . ends at the last event recorded and begins + . prior to that. If beforethat is used next, it will display + . event -1. +. + andthen commands are: set_andthen, andthen_next, andthen and beforethat +end + + +document andthen + andthen +. displays the next event in the list. sets up to display +. the oldest saved event first. +. (optional) count of the event to display. +. note the number of events saved is specified at configure time. +. if events are saved between calls to andthen the index will change +. but the displayed event will be the next one (unless the event buffer +. is overrun). +. +. andthen commands are: set_andthen, andthen_next, andthen and beforethat +end + +document set_andthen + set_andthen +. sets up to use the and commands. +. if you have defined your own struct, use the above and +. then enter the following: +. p $thp=(struct kgdb_and_then_structX *)&kgdb_data[0] +. where is the name of your structure. +. +. andthen commands are: set_andthen, andthen_next, andthen and beforethat +end + +document beforethat + beforethat +. displays the next prior event in the list. sets up to +. display the last occuring event first. +. +. note the number of events saved is specified at configure time. +. if events are saved between calls to beforethat the index will change +. but the displayed event will be the next one (unless the event buffer +. is overrun). +. +. andthen commands are: set_andthen, andthen_next, andthen and beforethat +end --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/Documentation/i386/kgdb/debug-nmi.txt 2004-05-10 01:19:06.876693640 -0700 @@ -0,0 +1,37 @@ +Subject: Debugging with NMI +Date: Mon, 12 Jul 1999 11:28:31 -0500 +From: David Grothe +Organization: Gcom, Inc +To: David Grothe + +Kernel hackers: + +Maybe this is old hat, but it is new to me -- + +On an ISA bus machine, if you short out the A1 and B1 pins of an ISA +slot you will generate an NMI to the CPU. This interrupts even a +machine that is hung in a loop with interrupts disabled. Used in +conjunction with kgdb < +ftp://ftp.gcom.com/pub/linux/src/kgdb-2.3.35/kgdb-2.3.35.tgz > you can +gain debugger control of a machine that is hung in the kernel! Even +without kgdb the kernel will print a stack trace so you can find out +where it was hung. + +The A1/B1 pins are directly opposite one another and the farthest pins +towards the bracket end of the ISA bus socket. You can stick a paper +clip or multi-meter probe between them to short them out. + +I had a spare ISA bus to PC104 bus adapter around. The PC104 end of the +board consists of two rows of wire wrap pins. So I wired a push button +between the A1/B1 pins and now have an ISA board that I can stick into +any ISA bus slot for debugger entry. + +Microsoft has a circuit diagram of a PCI card at +http://www.microsoft.com/hwdev/DEBUGGING/DMPSW.HTM. If you want to +build one you will have to mail them and ask for the PAL equations. +Nobody makes one comercially. + +[THIS TIP COMES WITH NO WARRANTY WHATSOEVER. It works for me, but if +your machine catches fire, it is your problem, not mine.] + +-- Dave (the kgdb guy) --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/Documentation/i386/kgdb/gdb-globals.txt 2004-05-10 01:19:06.877693488 -0700 @@ -0,0 +1,71 @@ +Sender: akale@veritas.com +Date: Fri, 23 Jun 2000 19:26:35 +0530 +From: "Amit S. Kale" +Organization: Veritas Software (India) +To: Dave Grothe , linux-kernel@vger.rutgers.edu +CC: David Milburn , + "Edouard G. Parmelan" , + ezannoni@cygnus.com, Keith Owens +Subject: Re: Module debugging using kgdb + +Dave Grothe wrote: +> +> Amit: +> +> There is a 2.4.0 version of kgdb on our ftp site: +> ftp://ftp.gcom.com/pub/linux/src/kgdb. I mirrored your version of gdb +> and loadmodule.sh there. +> +> Have a look at the README file and see if I go it right. If not, send +> me some corrections and I will update it. +> +> Does your version of gdb solve the global variable problem? + +Yes. +Thanks to Elena Zanoni, gdb (developement version) can now calculate +correctly addresses of dynamically loaded object files. I have not been +following gdb developement for sometime and am not sure when symbol +address calculation fix is going to appear in a gdb stable version. + +Elena, any idea when the fix will make it to a prebuilt gdb from a +redhat release? + +For the time being I have built a gdb developement version. It can be +used for module debugging with loadmodule.sh script. + +The problem with calculating of module addresses with previous versions +of gdb was as follows: +gdb did not use base address of a section while calculating address of +a symbol in the section in an object file loaded via 'add-symbol-file'. +It used address of .text segment instead. Due to this addresses of +symbols in .data, .bss etc. (e.g. global variables) were calculated incorrectly. + +Above mentioned fix allow gdb to use base address of a segment while +calculating address of a symbol in it. It adds a parameter '-s' to +'add-symbol-file' command for specifying base address of a segment. + +loadmodule.sh script works as follows. + +1. Copy a module file to target machine. +2. Load the module on the target machine using insmod with -m parameter. +insmod produces a module load map which contains base addresses of all +sections in the module and addresses of symbols in the module file. +3. Find all sections and their base addresses in the module from +the module map. +4. Generate a script that loads the module file. The script uses +'add-symbol-file' and specifies address of text segment followed by +addresses of all segments in the module. + +Here is an example gdb script produced by loadmodule.sh script. + +add-symbol-file foo 0xd082c060 -s .text.lock 0xd08cbfb5 +-s .fixup 0xd08cfbdf -s .rodata 0xd08cfde0 -s __ex_table 0xd08e3b38 +-s .data 0xd08e3d00 -s .bss 0xd08ec8c0 -s __ksymtab 0xd08ee838 + +With this command gdb can calculate addresses of symbols in ANY segment +in a module file. + +Regards. +-- +Amit Kale +Veritas Software ( http://www.veritas.com ) --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/Documentation/i386/kgdb/gdbinit 2004-05-10 01:19:06.877693488 -0700 @@ -0,0 +1,14 @@ +shell echo -e "\003" >/dev/ttyS0 +set remotebaud 38400 +target remote /dev/ttyS0 +define si +stepi +printf "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n", $eax, $ebx, $ecx, $edx +printf "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n", $esi, $edi, $ebp, $esp +x/i $eip +end +define ni +nexti +printf "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n", $eax, $ebx, $ecx, $edx +printf "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n", $esi, $edi, $ebp, $esp +x/i $eip --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/Documentation/i386/kgdb/gdbinit.hw 2004-05-10 01:19:06.878693336 -0700 @@ -0,0 +1,117 @@ + +#Using ia-32 hardware breakpoints. +# +#4 hardware breakpoints are available in ia-32 processors. These breakpoints +#do not need code modification. They are set using debug registers. +# +#Each hardware breakpoint can be of one of the +#three types: execution, write, access. +#1. An Execution breakpoint is triggered when code at the breakpoint address is +#executed. +#2. A write breakpoint ( aka watchpoints ) is triggered when memory location +#at the breakpoint address is written. +#3. An access breakpoint is triggered when memory location at the breakpoint +#address is either read or written. +# +#As hardware breakpoints are available in limited number, use software +#breakpoints ( br command in gdb ) instead of execution hardware breakpoints. +# +#Length of an access or a write breakpoint defines length of the datatype to +#be watched. Length is 1 for char, 2 short , 3 int. +# +#For placing execution, write and access breakpoints, use commands +#hwebrk, hwwbrk, hwabrk +#To remove a breakpoint use hwrmbrk command. +# +#These commands take following types of arguments. For arguments associated +#with each command, use help command. +#1. breakpointno: 0 to 3 +#2. length: 1 to 3 +#3. address: Memory location in hex ( without 0x ) e.g c015e9bc +# +#Use the command exinfo to find which hardware breakpoint occured. + +#hwebrk breakpointno address +define hwebrk + maintenance packet Y$arg0,0,0,$arg1 +end +document hwebrk + hwebrk
+ Places a hardware execution breakpoint + = 0 - 3 +
= Hex digits without leading "0x". +end + +#hwwbrk breakpointno length address +define hwwbrk + maintenance packet Y$arg0,1,$arg1,$arg2 +end +document hwwbrk + hwwbrk
+ Places a hardware write breakpoint + = 0 - 3 + = 1 (1 byte), 2 (2 byte), 3 (4 byte) +
= Hex digits without leading "0x". +end + +#hwabrk breakpointno length address +define hwabrk + maintenance packet Y$arg0,1,$arg1,$arg2 +end +document hwabrk + hwabrk
+ Places a hardware access breakpoint + = 0 - 3 + = 1 (1 byte), 2 (2 byte), 3 (4 byte) +
= Hex digits without leading "0x". +end + +#hwrmbrk breakpointno +define hwrmbrk + maintenance packet y$arg0 +end +document hwrmbrk + hwrmbrk + = 0 - 3 + Removes a hardware breakpoint +end + +define reboot + maintenance packet r +end +#exinfo +define exinfo + maintenance packet qE +end +document exinfo + exinfo + Gives information about a breakpoint. +end +define get_th + p $th=(struct thread_info *)((int)$esp & ~8191) +end +document get_th + get_tu + Gets and prints the current thread_info pointer, Defines th to be it. +end +define get_cu + p $cu=((struct thread_info *)((int)$esp & ~8191))->task +end +document get_cu + get_cu + Gets and print the "current" value. Defines $cu to be it. +end +define int_off + set var $flags=$eflags + set $eflags=$eflags&~0x200 + end +define int_on + set var $eflags|=$flags&0x200 + end +document int_off + saves the current interrupt state and clears the processor interrupt + flag. Use int_on to restore the saved flag. +end +document int_on + Restores the interrupt flag saved by int_off. +end --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/Documentation/i386/kgdb/gdbinit-modules 2004-05-10 01:19:06.879693184 -0700 @@ -0,0 +1,146 @@ +# +# Usefull GDB user-command to debug Linux Kernel Modules with gdbstub. +# +# This don't work for Linux-2.0 or older. +# +# Author Edouard G. Parmelan +# +# +# Fri Apr 30 20:33:29 CEST 1999 +# First public release. +# +# Major cleanup after experiment Linux-2.0 kernel without success. +# Symbols of a module are not in the correct order, I can't explain +# why :( +# +# Fri Mar 19 15:41:40 CET 1999 +# Initial version. +# +# Thu Jan 6 16:29:03 CST 2000 +# A little fixing by Dave Grothe +# +# Mon Jun 19 09:33:13 CDT 2000 +# Alignment changes from Edouard Parmelan +# +# The basic idea is to find where insmod load the module and inform +# GDB to load the symbol table of the module with the GDB command +# ``add-symbol-file
''. +# +# The Linux kernel holds the list of all loaded modules in module_list, +# this list end with &kernel_module (exactly with module->next == NULL, +# but the last module is not a real module). +# +# Insmod allocates the struct module before the object file. Since +# Linux-2.1, this structure contain his size. The real address of +# the object file is then (char*)module + module->size_of_struct. +# +# You can use three user functions ``mod-list'', ``mod-print-symbols'' +# and ``add-module-symbols''. +# +# mod-list list all loaded modules with the format: +# +# +# As soon as you have found the address of your module, you can +# print its exported symbols (mod-print-symbols) or inform GDB to add +# symbols from your module file (mod-add-symbols). +# +# The argument that you give to mod-print-symbols or mod-add-symbols +# is the from the mod-list command. +# +# When using the mod-add-symbols command you must also give the full +# pathname of the modules object code file. +# +# The command mod-add-lis is an example of how to make this easier. +# You can edit this macro to contain the path name of your own +# favorite module and then use it as a shorthand to load it. You +# still need the module-address, however. +# +# The internal function ``mod-validate'' set the GDB variable $mod +# as a ``struct module*'' if the kernel known the module otherwise +# $mod is set to NULL. This ensure to not add symbols for a wrong +# address. +# +# Have a nice hacking day ! +# +# +define mod-list + set $mod = (struct module*)module_list + # the last module is the kernel, ignore it + while $mod != &kernel_module + printf "%p\t%s\n", (long)$mod, ($mod)->name + set $mod = $mod->next + end +end +document mod-list +List all modules in the form: +Use the as the argument for the other +mod-commands: mod-print-symbols, mod-add-symbols. +end + +define mod-validate + set $mod = (struct module*)module_list + while ($mod != $arg0) && ($mod != &kernel_module) + set $mod = $mod->next + end + if $mod == &kernel_module + set $mod = 0 + printf "%p is not a module\n", $arg0 + end +end +document mod-validate +mod-validate +Internal user-command used to validate the module parameter. +If is a real loaded module, set $mod to it otherwise set $mod to 0. +end + + +define mod-print-symbols + mod-validate $arg0 + if $mod != 0 + set $i = 0 + while $i < $mod->nsyms + set $sym = $mod->syms[$i] + printf "%p\t%s\n", $sym->value, $sym->name + set $i = $i + 1 + end + end +end +document mod-print-symbols +mod-print-symbols +Print all exported symbols of the module. see mod-list +end + + +define mod-add-symbols-align + mod-validate $arg0 + if $mod != 0 + set $mod_base = ($mod->size_of_struct + (long)$mod) + if ($arg2 != 0) && (($mod_base & ($arg2 - 1)) != 0) + set $mod_base = ($mod_base | ($arg2 - 1)) + 1 + end + add-symbol-file $arg1 $mod_base + end +end +document mod-add-symbols-align +mod-add-symbols-align +Load the symbols table of the module from the object file where +first section aligment is . +To retreive alignment, use `objdump -h '. +end + +define mod-add-symbols + mod-add-symbols-align $arg0 $arg1 sizeof(long) +end +document mod-add-symbols +mod-add-symbols +Load the symbols table of the module from the object file. +Default alignment is 4. See mod-add-symbols-align. +end + +define mod-add-lis + mod-add-symbols-align $arg0 /usr/src/LiS/streams.o 16 +end +document mod-add-lis +mod-add-lis +Does mod-add-symbols /usr/src/LiS/streams.o +end --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/Documentation/i386/kgdb/kgdbeth.txt 2004-05-10 01:19:07.213642416 -0700 @@ -0,0 +1,92 @@ +KGDB over ethernet +================== + +Authors +------- + +Robert Walsh (2.6 port) +wangdi (2.6 port) +Matt Mackall (netpoll api) +San Mehat (original 2.4 code) + + +Introduction +------------ + +KGDB supports debugging over ethernet (kgdboe) via polling of a given +network interface. Most cards should be supported automatically. +Debugging facilities are available as soon as the network driver and +kgdboe have initialized. Unfortunately, this is too late in the boot +process for debugging some issues, but works quite well for many +others. This should not interfere with normal network usage and +doesn't require a dedicated NIC. + +Terminology +----------- + +This document uses the following terms: + + TARGET: the machine being debugged. + HOST: the machine running gdb. + + +Usage +----- + +You need to use the following command-line option on the TARGET kernel: + + kgdboe=[tgt-port]@/[dev],[host-port]@/[host-macaddr] + + where + tgt-port source for UDP packets (defaults to 6443) + tgt-ip source IP to use (interface address) + dev network interface (eth0) + host-port HOST UDP port (6442) (not really used) + host-ip IP address for HOST machine + host-macaddr ethernet MAC address for HOST (ff:ff:ff:ff:ff:ff) + + examples: + + kgdboe=7000@192.168.0.1/eth1,7001@192.168.0.2/00:05:3C:04:47:5D + this machine is 192.168.0.1 on eth1 + remote machine is 192.168.0.2 with MAC address 00:05:3C:04:47:5D + listen for gdb packets on port 7000 + send unsolicited gdb packets to port 7001 + + kgdboe=@192.168.0.1/,@192.168.0.2/ + this machine is 192.168.0.1 on default interface eth0 + remote machine is 192.168.0.2, use default broadcast MAC address + listen for gdb packets on default port 6443 + send unsolicited gdb packets to port 6442 + +Only packets originating from the configured HOST IP address will be +accepted by the debugger. + +On the HOST side, run gdb as normal and use a remote UDP host as the +target: + + % gdb ./vmlinux + GNU gdb Red Hat Linux (5.3post-0.20021129.18rh) + Copyright 2003 Free Software Foundation, Inc. + GDB is free software, covered by the GNU General Public License, and you are + welcome to change it and/or distribute copies of it under certain conditions. + Type "show copying" to see the conditions. + There is absolutely no warranty for GDB. Type "show warranty" for details. + This GDB was configured as "i386-redhat-linux-gnu"... + (gdb) target remote udp:HOSTNAME:6443 + +You can now continue as if you were debugging over a serial line. + +Limitations +----------- + +The current release of this code is exclusive of using kgdb on a +serial interface, so you must boot without the kgdboe option to use +serial debugging. Trying to debug the network driver while using it +will prove interesting. + +Bug reports +----------- + +Send bug reports to Robert Walsh and Matt +Mackall . --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/Documentation/i386/kgdb/kgdb.txt 2004-05-10 01:19:06.884692424 -0700 @@ -0,0 +1,775 @@ +Last edit: <20030806.1637.12> +This file has information specific to the i386 kgdb option. Other +platforms with the kgdb option may behave in a similar fashion. + +New features: +============ +20030806.1557.37 +This version was made against the 2.6.0-test2 kernel. We have made the +following changes: + +- The getthread() code in the stub calls find_task_by_pid(). It fails + if we are early in the bring up such that the pid arrays have yet to + be allocated. We have added a line to kernel/pid.c to make + "kgdb_pid_init_done" true once the arrays are allocated. This way the + getthread() code knows not to call. This is only used by the thread + debugging stuff and threads will not yet exist at this point in the + boot. + +- For some reason, gdb was not asking for a new thread list when the + "info thread" command was given. We changed to the newer version of + the thread info command and gdb now seems to ask when needed. Result, + we now get all threads in the thread list. + +- We now respond to the ThreadExtraInfo request from gdb with the thread + name from task_struct .comm. This then appears in the thread list. + Thoughts on additional options for this are welcome. Things such as + "has BKL" and "Preempted" come to mind. I think we could have a flag + word that could enable different bits of info here. + +- We now honor, sort of, the C and S commands. These are continue and + single set after delivering a signal. We ignore the signal and do the + requested action. This only happens when we told gdb that a signal + was the reason for entry, which is only done on memory faults. The + result is that you can now continue into the Oops. + +- We changed the -g to -gdwarf-2. This seems to be the same as -ggdb, + but it is more exact on what language to use. + +- We added two dwarf2 include files and a bit of code at the end of + entry.S. This does not yet work, so it is disabled. Still we want to + keep track of the code and "maybe" someone out there can fix it. + +- Randy Dunlap sent some fix ups for this file which are now merged. + +- Hugh Dickins sent a fix to a bit of code in traps.c that prevents a + compiler warning if CONFIG_KGDB is off (now who would do that :). + +- Andrew Morton sent a fix for the serial driver which is now merged. + +- Andrew also sent a change to the stub around the cpu managment code + which is also merged. + +- Andrew also sent a patch to make "f" as well as "g" work as SysRq + commands to enter kgdb, merged. + +- If CONFIG_KGDB and CONFIG_DEBUG_SPINLOCKS are both set we added a + "who" field to the spinlock data struct. This is filled with + "current" when ever the spinlock suceeds. Useful if you want to know + who has the lock. + +_ And last, but not least, we fixed the "get_cu" macro to properly get + the current value of "current". + +New features: +============ +20030505.1827.27 +We are starting to align with the sourceforge version, at least in +commands. To this end, the boot command string to start kgdb at +boot time has been changed from "kgdb" to "gdb". + +Andrew Morton sent a couple of patches which are now included as follows: +1.) We now return a flag to the interrupt handler. +2.) We no longer use smp_num_cpus (a conflict with the lock meter). +3.) And from William Lee Irwin III code to make + sure high-mem is set up before we attempt to register our interrupt + handler. +We now include asm/kgdb.h from config.h so you will most likely never +have to include it. It also 'NULLS' the kgdb macros you might have in +your code when CONFIG_KGDB is not defined. This allows you to just +turn off CONFIG_KGDB to turn off all the kgdb_ts() calls and such. +This include is conditioned on the machine being an x86 so as to not +mess with other archs. + +20020801.1129.03 +This is currently the version for the 2.4.18 (and beyond?) kernel. + +We have several new "features" beginning with this version: + +1.) Kgdb now syncs the "other" CPUs with a cross-CPU NMI. No more + waiting and it will pull that guy out of an IRQ off spin lock :) + +2.) We doctored up the code that tells where a task is waiting and + included it so that the "info thread" command will show a bit more + than "schedule()". Try it... + +3.) Added the ability to call a function from gdb. All the standard gdb + issues apply, i.e. if you hit a breakpoint in the function, you are + not allowed to call another (gdb limitation, not kgdb). To help + this capability we added a memory allocation function. Gdb does not + return this memory (it is used for strings that you pass to that function + you are calling from gdb) so we fixed up a way to allow you to + manually return the memory (see below). + +4.) Kgdb time stamps (kgdb_ts()) are enhanced to expand what was the + interrupt flag to now also include the preemption count and the + "in_interrupt" info. The flag is now called "with_pif" to indicate + the order, preempt_count, in_interrupt, flag. The preempt_count is + shifted left by 4 bits so you can read the count in hex by dropping + the low order digit. In_interrupt is in bit 1, and the flag is in + bit 0. + +5.) The command: "p kgdb_info" is now expanded and prints something + like: +(gdb) p kgdb_info +$2 = {used_malloc = 0, called_from = 0xc0107506, entry_tsc = 67468627259, + errcode = 0, vector = 3, print_debug_info = 0, hold_on_sstep = 1, + cpus_waiting = {{task = 0xc027a000, pid = 32768, hold = 0, + regs = 0xc027bf84}, {task = 0x0, pid = 0, hold = 0, regs = 0x0}}} + + Things to note here: a.) used_malloc is the amount of memory that + has been malloc'ed to do calls from gdb. You can reclaim this + memory like this: "p kgdb_info.used_malloc=0" Cool, huh? b.) + cpus_waiting is now "sized" by the number of CPUs you enter at + configure time in the kgdb configure section. This is NOT used + anywhere else in the system, but it is "nice" here. c.) The task's + "pid" is now in the structure. This is the pid you will need to use + to decode to the thread id to get gdb to look at that thread. + Remember that the "info thread" command prints a list of threads + wherein it numbers each thread with its reference number followed + by the thread's pid. Note that the per-CPU idle threads actually + have pids of 0 (yes, there is more than one pid 0 in an SMP system). + To avoid confusion, kgdb numbers these threads with numbers beyond + the MAX_PID. That is why you see 32768 and above. + +6.) A subtle change, we now provide the complete register set for tasks + that are active on the other CPUs. This allows better trace back on + those tasks. + + And, let's mention what we could not fix. Back-trace from all but the + thread that we trapped will, most likely, have a bogus entry in it. + The problem is that gdb does not recognize the entry code for + functions that use "current" near (at all?) the entry. The compiler + is putting the "current" decode as the first two instructions of the + function where gdb expects to find %ebp changing code. Back trace + also has trouble with interrupt frames. I am talking with Daniel + Jacobowitz about some way to fix this, but don't hold your breath. + +20011220.0050.35 +Major enhancement with this version is the ability to hold one or more +CPUs in an SMP system while allowing the others to continue. Also, by +default only the current CPU is enabled on single-step commands (please +note that gdb issues single-step commands at times other than when you +use the si command). + +Another change is to collect some useful information in +a global structure called "kgdb_info". You should be able to just: + +p kgdb_info + +although I have seen cases where the first time this is done gdb just +prints the first member but prints the whole structure if you then enter +CR (carriage return or enter). This also works: + +p *&kgdb_info + +Here is a sample: +(gdb) p kgdb_info +$4 = {called_from = 0xc010732c, entry_tsc = 32804123790856, errcode = 0, + vector = 3, print_debug_info = 0} + +"Called_from" is the return address from the current entry into kgdb. +Sometimes it is useful to know why you are in kgdb, for example, was +it an NMI or a real breakpoint? The simple way to interrogate this +return address is: + +l *0xc010732c + +which will print the surrounding few lines of source code. + +"Entry_tsc" is the CPU TSC on entry to kgdb (useful to compare to the +kgdb_ts entries). + +"errcode" and "vector" are other entry parameters which may be helpful on +some traps. + +"print_debug_info" is the internal debugging kgdb print enable flag. Yes, +you can modify it. + +In SMP systems kgdb_info also includes the "cpus_waiting" structure and +"hold_on_step": + +(gdb) p kgdb_info +$7 = {called_from = 0xc0112739, entry_tsc = 1034936624074, errcode = 0, + vector = 2, print_debug_info = 0, hold_on_sstep = 1, cpus_waiting = {{ + task = 0x0, hold = 0, regs = 0x0}, {task = 0xc71b8000, hold = 0, + regs = 0xc71b9f70}, {task = 0x0, hold = 0, regs = 0x0}, {task = 0x0, + hold = 0, regs = 0x0}, {task = 0x0, hold = 0, regs = 0x0}, {task = 0x0, + hold = 0, regs = 0x0}, {task = 0x0, hold = 0, regs = 0x0}, {task = 0x0, + hold = 0, regs = 0x0}}} + +"Cpus_waiting" has an entry for each CPU other than the current one that +has been stopped. Each entry contains the task_struct address for that +CPU, the address of the regs for that task and a hold flag. All these +have the proper typing so that, for example: + +p *kgdb_info.cpus_waiting[1].regs + +will print the registers for CPU 1. + +"Hold_on_sstep" is a new feature with this version and comes up set or +true. What this means is that whenever kgdb is asked to single-step all +other CPUs are held (i.e. not allowed to execute). The flag applies to +all but the current CPU and, again, can be changed: + +p kgdb_info.hold_on_sstep=0 + +restores the old behavior of letting all CPUs run during single-stepping. + +Likewise, each CPU has a "hold" flag, which if set, locks that CPU out +of execution. Note that this has some risk in cases where the CPUs need +to communicate with each other. If kgdb finds no CPU available on exit, +it will push a message thru gdb and stay in kgdb. Note that it is legal +to hold the current CPU as long as at least one CPU can execute. + +20010621.1117.09 +This version implements an event queue. Events are signaled by calling +a function in the kgdb stub and may be examined from gdb. See EVENTS +below for details. This version also tightens up the interrupt and SMP +handling to not allow interrupts on the way to kgdb from a breakpoint +trap. It is fine to allow these interrupts for user code, but not +system debugging. + +Version +======= + +This version of the kgdb package was developed and tested on +kernel version 2.4.16. It will not install on any earlier kernels. +It is possible that it will continue to work on later versions +of 2.4 and then versions of 2.5 (I hope). + + +Debugging Setup +=============== + +Designate one machine as the "development" machine. This is the +machine on which you run your compiles and which has your source +code for the kernel. Designate a second machine as the "target" +machine. This is the machine that will run your experimental +kernel. + +The two machines will be connected together via a serial line out +one or the other of the COM ports of the PC. You will need the +appropriate modem eliminator (null modem) cable(s) for this. + +Decide on which tty port you want the machines to communicate, then +connect them up back-to-back using the null modem cable. COM1 is +/dev/ttyS0 and COM2 is /dev/ttyS1. You should test this connection +with the two machines prior to trying to debug a kernel. Once you +have it working, on the TARGET machine, enter: + +setserial /dev/ttyS0 (or what ever tty you are using) + +and record the port address and the IRQ number. + +On the DEVELOPMENT machine you need to apply the patch for the kgdb +hooks. You have probably already done that if you are reading this +file. + +On your DEVELOPMENT machine, go to your kernel source directory and do +"make Xconfig" where X is one of "x", "menu", or "". If you are +configuring in the standard serial driver, it must not be a module. +Either yes or no is ok, but making the serial driver a module means it +will initialize after kgdb has set up the UART interrupt code and may +cause a failure of the control-C option discussed below. The configure +question for the serial driver is under the "Character devices" heading +and is: + +"Standard/generic (8250/16550 and compatible UARTs) serial support" + +Go down to the kernel debugging menu item and open it up. Enable the +kernel kgdb stub code by selecting that item. You can also choose to +turn on the "-ggdb -O1" compile options. The -ggdb causes the compiler +to put more debug info (like local symbols) in the object file. On the +i386 -g and -ggdb are the same so this option just reduces to "O1". The +-O1 reduces the optimization level. This may be helpful in some cases, +be aware, however, that this may also mask the problem you are looking +for. + +The baud rate. Default is 115200. What ever you choose be sure that +the host machine is set to the same speed. I recommend the default. + +The port. This is the I/O address of the serial UART that you should +have gotten using setserial as described above. The standard COM1 port +(3f8) using IRQ 4 is default. COM2 is 2f8 which by convention uses IRQ +3. + +The port IRQ (see above). + +Stack overflow test. This option makes a minor change in the trap, +system call and interrupt code to detect stack overflow and transfer +control to kgdb if it happens. (Some platforms have this in the +baseline code, but the i386 does not.) + +You can also configure the system to recognize the boot option +"console=kgdb" which if given will cause all console output during +booting to be put thru gdb as well as other consoles. This option +requires that gdb and kgdb be connected prior to sending console output +so, if they are not, a breakpoint is executed to force the connection. +This will happen before any kernel output (it is going thru gdb, right), +and will stall the boot until the connection is made. + +You can also configure in a patch to SysRq to enable the kGdb SysRq. +This request generates a breakpoint. Since the serial port IRQ line is +set up after any serial drivers, it is possible that this command will +work when the control-C will not. + +Save and exit the Xconfig program. Then do "make clean" , "make dep" +and "make bzImage" (or whatever target you want to make). This gets the +kernel compiled with the "-g" option set -- necessary for debugging. + +You have just built the kernel on your DEVELOPMENT machine that you +intend to run on your TARGET machine. + +To install this new kernel, use the following installation procedure. +Remember, you are on the DEVELOPMENT machine patching the kernel source +for the kernel that you intend to run on the TARGET machine. + +Copy this kernel to your target machine using your usual procedures. I +usually arrange to copy development: +/usr/src/linux/arch/i386/boot/bzImage to /vmlinuz on the TARGET machine +via a LAN based NFS access. That is, I run the cp command on the target +and copy from the development machine via the LAN. Run Lilo (see "man +lilo" for details on how to set this up) on the new kernel on the target +machine so that it will boot! Then boot the kernel on the target +machine. + +On the DEVELOPMENT machine, create a file called .gdbinit in the +directory /usr/src/linux. An example .gdbinit file looks like this: + +shell echo -e "\003" >/dev/ttyS0 +set remotebaud 38400 (or what ever speed you have chosen) +target remote /dev/ttyS0 + + +Change the "echo" and "target" definition so that it specifies the tty +port that you intend to use. Change the "remotebaud" definition to +match the data rate that you are going to use for the com line. + +You are now ready to try it out. + +Boot your target machine with "kgdb" in the boot command i.e. something +like: + +lilo> test kgdb + +or if you also want console output thru gdb: + +lilo> test kgdb console=kgdb + +You should see the lilo message saying it has loaded the kernel and then +all output stops. The kgdb stub is trying to connect with gdb. Start +gdb something like this: + + +On your DEVELOPMENT machine, cd /usr/src/linux and enter "gdb vmlinux". +When gdb gets the symbols loaded it will read your .gdbinit file and, if +everything is working correctly, you should see gdb print out a few +lines indicating that a breakpoint has been taken. It will actually +show a line of code in the target kernel inside the kgdb activation +code. + +The gdb interaction should look something like this: + + linux-dev:/usr/src/linux# gdb vmlinux + GDB is free software and you are welcome to distribute copies of it + under certain conditions; type "show copying" to see the conditions. + There is absolutely no warranty for GDB; type "show warranty" for details. + GDB 4.15.1 (i486-slackware-linux), + Copyright 1995 Free Software Foundation, Inc... + breakpoint () at i386-stub.c:750 + 750 } + (gdb) + +You can now use whatever gdb commands you like to set breakpoints. +Enter "continue" to start your target machine executing again. At this +point the target system will run at full speed until it encounters +your breakpoint or gets a segment violation in the kernel, or whatever. + +If you have the kgdb console enabled when you continue, gdb will print +out all the console messages. + +The above example caused a breakpoint relatively early in the boot +process. For the i386 kgdb it is possible to code a break instruction +as the first C-language point in init/main.c, i.e. as the first instruction +in start_kernel(). This could be done as follows: + +#include + breakpoint(); + +This breakpoint() is really a function that sets up the breakpoint and +single-step hardware trap cells and then executes a breakpoint. Any +early hard coded breakpoint will need to use this function. Once the +trap cells are set up they need not be set again, but doing it again +does not hurt anything, so you don't need to be concerned about which +breakpoint is hit first. Once the trap cells are set up (and the kernel +sets them up in due course even if breakpoint() is never called) the +macro: + +BREAKPOINT; + +will generate an inline breakpoint. This may be more useful as it stops +the processor at the instruction instead of in a function a step removed +from the location of interest. In either case must be +included to define both breakpoint() and BREAKPOINT. + +Triggering kgdbstub at other times +================================== + +Often you don't need to enter the debugger until much later in the boot +or even after the machine has been running for some time. Once the +kernel is booted and interrupts are on, you can force the system to +enter the debugger by sending a control-C to the debug port. This is +what the first line of the recommended .gdbinit file does. This allows +you to start gdb any time after the system is up as well as when the +system is already at a breakpoint. (In the case where the system is +already at a breakpoint the control-C is not needed, however, it will +be ignored by the target so no harm is done. Also note the the echo +command assumes that the port speed is already set. This will be true +once gdb has connected, but it is best to set the port speed before you +run gdb.) + +Another simple way to do this is to put the following file in you ~/bin +directory: + +#!/bin/bash +echo -e "\003" > /dev/ttyS0 + +Here, the ttyS0 should be replaced with what ever port you are using. +The "\003" is control-C. Once you are connected with gdb, you can enter +control-C at the command prompt. + +An alternative way to get control to the debugger is to enable the kGdb +SysRq command. Then you would enter Alt-SysRq-g (all three keys at the +same time, but push them down in the order given). To refresh your +memory of the available SysRq commands try Alt-SysRq-=. Actually any +undefined command could replace the "=", but I like to KNOW that what I +am pushing will never be defined. + +Debugging hints +=============== + +You can break into the target machine at any time from the development +machine by typing ^C (see above paragraph). If the target machine has +interrupts enabled this will stop it in the kernel and enter the +debugger. + +There is unfortunately no way of breaking into the kernel if it is +in a loop with interrupts disabled, so if this happens to you then +you need to place exploratory breakpoints or printk's into the kernel +to find out where it is looping. The exploratory breakpoints can be +entered either thru gdb or hard coded into the source. This is very +handy if you do something like: + +if () BREAKPOINT; + + +There is a copy of an e-mail in the Documentation/i386/kgdb/ directory +(debug-nmi.txt) which describes how to create an NMI on an ISA bus +machine using a paper clip. I have a sophisticated version of this made +by wiring a push button switch into a PC104/ISA bus adapter card. The +adapter card nicely furnishes wire wrap pins for all the ISA bus +signals. + +When you are done debugging the kernel on the target machine it is a +good idea to leave it in a running state. This makes reboots faster, +bypassing the fsck. So do a gdb "continue" as the last gdb command if +this is possible. To terminate gdb itself on the development machine +and leave the target machine running, first clear all breakpoints and +continue, then type ^Z to suspend gdb and then kill it with "kill %1" or +something similar. + +If gdbstub Does Not Work +======================== + +If it doesn't work, you will have to troubleshoot it. Do the easy +things first like double checking your cabling and data rates. You +might try some non-kernel based programs to see if the back-to-back +connection works properly. Just something simple like cat /etc/hosts +>/dev/ttyS0 on one machine and cat /dev/ttyS0 on the other will tell you +if you can send data from one machine to the other. Make sure it works +in both directions. There is no point in tearing out your hair in the +kernel if the line doesn't work. + +All of the real action takes place in the file +/usr/src/linux/arch/i386/kernel/kgdb_stub.c. That is the code on the target +machine that interacts with gdb on the development machine. In gdb you can +turn on a debug switch with the following command: + + set remotedebug + +This will print out the protocol messages that gdb is exchanging with +the target machine. + +Another place to look is /usr/src/arch/i386/lib/kgdb_serial.c. This is +the code that talks to the serial port on the target side. There might +be a problem there. In particular there is a section of this code that +tests the UART which will tell you what UART you have if you define +"PRNT" (just remove "_off" from the #define PRNT_off). To view this +report you will need to boot the system without any beakpoints. This +allows the kernel to run to the point where it calls kgdb to set up +interrupts. At this time kgdb will test the UART and print out the type +it finds. (You need to wait so that the printks are actually being +printed. Early in the boot they are cached, waiting for the console to +be enabled. Also, if kgdb is entered thru a breakpoint it is possible +to cause a dead lock by calling printk when the console is locked. The +stub thus avoids doing printks from breakpoints, especially in the +serial code.) At this time, if the UART fails to do the expected thing, +kgdb will print out (using printk) information on what failed. (These +messages will be buried in all the other boot up messages. Look for +lines that start with "gdb_hook_interrupt:". You may want to use dmesg +once the system is up to view the log. If this fails or if you still +don't connect, review your answers for the port address. Use: + +setserial /dev/ttyS0 + +to get the current port and IRQ information. This command will also +tell you what the system found for the UART type. The stub recognizes +the following UART types: + +16450, 16550, and 16550A + +If you are really desperate you can use printk debugging in the +kgdbstub code in the target kernel until you get it working. In particular, +there is a global variable in /usr/src/linux/arch/i386/kernel/kgdb_stub.c +named "remote_debug". Compile your kernel with this set to 1, rather +than 0 and the debug stub will print out lots of stuff as it does +what it does. Likewise there are debug printks in the kgdb_serial.c +code that can be turned on with simple changes in the macro defines. + + +Debugging Loadable Modules +========================== + +This technique comes courtesy of Edouard Parmelan + + +When you run gdb, enter the command + +source gdbinit-modules + +This will read in a file of gdb macros that was installed in your +kernel source directory when kgdb was installed. This file implements +the following commands: + +mod-list + Lists the loaded modules in the form + +mod-print-symbols + Prints all the symbols in the indicated module. + +mod-add-symbols + Loads the symbols from the object file and associates them + with the indicated module. + +After you have loaded the module that you want to debug, use the command +mod-list to find the of your module. Then use that +address in the mod-add-symbols command to load your module's symbols. +From that point onward you can debug your module as if it were a part +of the kernel. + +The file gdbinit-modules also contains a command named mod-add-lis as +an example of how to construct a command of your own to load your +favorite module. The idea is to "can" the pathname of the module +in the command so you don't have to type so much. + +Threads +======= + +Each process in a target machine is seen as a gdb thread. gdb thread +related commands (info threads, thread n) can be used. + +ia-32 hardware breakpoints +========================== + +kgdb stub contains support for hardware breakpoints using debugging features +of ia-32(x86) processors. These breakpoints do not need code modification. +They use debugging registers. 4 hardware breakpoints are available in ia-32 +processors. + +Each hardware breakpoint can be of one of the following three types. + +1. Execution breakpoint - An Execution breakpoint is triggered when code + at the breakpoint address is executed. + + As limited number of hardware breakpoints are available, it is + advisable to use software breakpoints ( break command ) instead + of execution hardware breakpoints, unless modification of code + is to be avoided. + +2. Write breakpoint - A write breakpoint is triggered when memory + location at the breakpoint address is written. + + A write or can be placed for data of variable length. Length of + a write breakpoint indicates length of the datatype to be + watched. Length is 1 for 1 byte data , 2 for 2 byte data, 3 for + 4 byte data. + +3. Access breakpoint - An access breakpoint is triggered when memory + location at the breakpoint address is either read or written. + + Access breakpoints also have lengths similar to write breakpoints. + +IO breakpoints in ia-32 are not supported. + +Since gdb stub at present does not use the protocol used by gdb for hardware +breakpoints, hardware breakpoints are accessed through gdb macros. gdb macros +for hardware breakpoints are described below. + +hwebrk - Places an execution breakpoint + hwebrk breakpointno address +hwwbrk - Places a write breakpoint + hwwbrk breakpointno length address +hwabrk - Places an access breakpoint + hwabrk breakpointno length address +hwrmbrk - Removes a breakpoint + hwrmbrk breakpointno +exinfo - Tells whether a software or hardware breakpoint has occurred. + Prints number of the hardware breakpoint if a hardware breakpoint has + occurred. + +Arguments required by these commands are as follows +breakpointno - 0 to 3 +length - 1 to 3 +address - Memory location in hex digits ( without 0x ) e.g c015e9bc + +SMP support +========== + +When a breakpoint occurs or user issues a break ( Ctrl + C ) to gdb +client, all the processors are forced to enter the debugger. Current +thread corresponds to the thread running on the processor where +breakpoint occurred. Threads running on other processor(s) appear +similar to other non-running threads in the 'info threads' output. +Within the kgdb stub there is a structure "waiting_cpus" in which kgdb +records the values of "current" and "regs" for each CPU other than the +one that hit the breakpoint. "current" is a pointer to the task +structure for the task that CPU is running, while "regs" points to the +saved registers for the task. This structure can be examined with the +gdb "p" command. + +ia-32 hardware debugging registers on all processors are set to same +values. Hence any hardware breakpoints may occur on any processor. + +gdb troubleshooting +=================== + +1. gdb hangs +Kill it. restart gdb. Connect to target machine. + +2. gdb cannot connect to target machine (after killing a gdb and +restarting another) If the target machine was not inside debugger when +you killed gdb, gdb cannot connect because the target machine won't +respond. In this case echo "Ctrl+C"(ASCII 3) to the serial line. +e.g. echo -e "\003" > /dev/ttyS1 +This forces that target machine into the debugger, after which you +can connect. + +3. gdb cannot connect even after echoing Ctrl+C into serial line +Try changing serial line settings min to 1 and time to 0 +e.g. stty min 1 time 0 < /dev/ttyS1 +Try echoing again + +Check serial line speed and set it to correct value if required +e.g. stty ispeed 115200 ospeed 115200 < /dev/ttyS1 + +EVENTS +====== + +Ever want to know the order of things happening? Which CPU did what and +when? How did the spinlock get the way it is? Then events are for +you. Events are defined by calls to an event collection interface and +saved for later examination. In this case, kgdb events are saved by a +very fast bit of code in kgdb which is fully SMP and interrupt protected +and they are examined by using gdb to display them. Kgdb keeps only +the last N events, where N must be a power of two and is defined at +configure time. + + +Events are signaled to kgdb by calling: + +kgdb_ts(data0,data1) + +For each call kgdb records each call in an array along with other info. +Here is the array definition: + +struct kgdb_and_then_struct { +#ifdef CONFIG_SMP + int on_cpu; +#endif + long long at_time; + int from_ln; + char * in_src; + void *from; + int with_if; + int data0; + int data1; +}; + +For SMP machines the CPU is recorded, for all machines the TSC is +recorded (gets a time stamp) as well as the line number and source file +the call was made from. The address of the (from), the "if" (interrupt +flag) and the two data items are also recorded. The macro kgdb_ts casts +the types to int, so you can put any 32-bit values here. There is a +configure option to select the number of events you want to keep. A +nice number might be 128, but you can keep up to 1024 if you want. The +number must be a power of two. An "andthen" macro library is provided +for gdb to help you look at these events. It is also possible to define +a different structure for the event storage and cast the data to this +structure. For example the following structure is defined in kgdb: + +struct kgdb_and_then_struct2 { +#ifdef CONFIG_SMP + int on_cpu; +#endif + long long at_time; + int from_ln; + char * in_src; + void *from; + int with_if; + struct task_struct *t1; + struct task_struct *t2; +}; + +If you use this for display, the data elements will be displayed as +pointers to task_struct entries. You may want to define your own +structure to use in casting. You should only change the last two items +and you must keep the structure size the same. Kgdb will handle these +as 32-bit ints, but within that constraint you can define a structure to +cast to any 32-bit quantity. This need only be available to gdb and is +only used for casting in the display code. + +Final Items +=========== + +I picked up this code from Amit S. Kale and enhanced it. + +If you make some really cool modification to this stuff, or if you +fix a bug, please let me know. + +George Anzinger + + +Amit S. Kale + + +(First kgdb by David Grothe ) + +(modified by Tigran Aivazian ) + Putting gdbstub into the kernel config menu. + +(modified by Scott Foehner ) + Hooks for entering gdbstub at boot time. + +(modified by Amit S. Kale ) + Threads, ia-32 hw debugging, mp support, console support, + nmi watchdog handling. + +(modified by George Anzinger ) + Extended threads to include the idle threads. + Enhancements to allow breakpoint() at first C code. + Use of module_init() and __setup() to automate the configure. + Enhanced the cpu "collection" code to work in early bring-up. + Added ability to call functions from gdb + Print info thread stuff without going back to schedule() + Now collect the "other" cpus with an IPI/ NMI. --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/Documentation/i386/kgdb/loadmodule.sh 2004-05-10 01:19:06.885692272 -0700 @@ -0,0 +1,78 @@ +#/bin/sh +# This script loads a module on a target machine and generates a gdb script. +# source generated gdb script to load the module file at appropriate addresses +# in gdb. +# +# Usage: +# Loading the module on target machine and generating gdb script) +# [foo]$ loadmodule.sh +# +# Loading the module file into gdb +# (gdb) source +# +# Modify following variables according to your setup. +# TESTMACHINE - Name of the target machine +# GDBSCRIPTS - The directory where a gdb script will be generated +# +# Author: Amit S. Kale (akale@veritas.com). +# +# If you run into problems, please check files pointed to by following +# variables. +# ERRFILE - /tmp/.errs contains stderr output of insmod +# MAPFILE - /tmp/.map contains stdout output of insmod +# GDBSCRIPT - $GDBSCRIPTS/load gdb script. + +TESTMACHINE=foo +GDBSCRIPTS=/home/bar + +if [ $# -lt 1 ] ; then { + echo Usage: $0 modulefile + exit +} ; fi + +MODULEFILE=$1 +MODULEFILEBASENAME=`basename $1` + +if [ $MODULEFILE = $MODULEFILEBASENAME ] ; then { + MODULEFILE=`pwd`/$MODULEFILE +} fi + +ERRFILE=/tmp/$MODULEFILEBASENAME.errs +MAPFILE=/tmp/$MODULEFILEBASENAME.map +GDBSCRIPT=$GDBSCRIPTS/load$MODULEFILEBASENAME + +function findaddr() { + local ADDR=0x$(echo "$SEGMENTS" | \ + grep "$1" | sed 's/^[^ ]*[ ]*[^ ]*[ ]*//' | \ + sed 's/[ ]*[^ ]*$//') + echo $ADDR +} + +function checkerrs() { + if [ "`cat $ERRFILE`" != "" ] ; then { + cat $ERRFILE + exit + } fi +} + +#load the module +echo Copying $MODULEFILE to $TESTMACHINE +rcp $MODULEFILE root@${TESTMACHINE}: + +echo Loading module $MODULEFILE +rsh -l root $TESTMACHINE /sbin/insmod -m ./`basename $MODULEFILE` \ + > $MAPFILE 2> $ERRFILE +checkerrs + +SEGMENTS=`head -n 11 $MAPFILE | tail -n 10` +TEXTADDR=$(findaddr "\\.text[^.]") +LOADSTRING="add-symbol-file $MODULEFILE $TEXTADDR" +SEGADDRS=`echo "$SEGMENTS" | awk '//{ + if ($1 != ".text" && $1 != ".this" && + $1 != ".kstrtab" && $1 != ".kmodtab") { + print " -s " $1 " 0x" $3 " " + } +}'` +LOADSTRING="$LOADSTRING $SEGADDRS" +echo Generating script $GDBSCRIPT +echo $LOADSTRING > $GDBSCRIPT --- linux-2.6.6/Documentation/laptop-mode.txt 2004-05-09 21:07:22.000000000 -0700 +++ 25/Documentation/laptop-mode.txt 2004-05-10 01:19:34.142548600 -0700 @@ -76,6 +76,11 @@ Caveats variables in centisecs (like most other subsystems do) but in "jiffies", which is an internal kernel measure. Once this is fixed things will get better. +* It has been reported that some versions of the mutt mail client use file access + times to determine whether a folder contains new mail. If you use mutt and + experience this, you must disable the noatime remounting in the control script + by setting DO_REMOUNT_NOATIME=0. + The details ----------- @@ -295,6 +300,9 @@ esac # Shall we remount journaled fs. with appropiate commit interval? (1=yes) DO_REMOUNTS=1 +# And shall we add the "noatime" option to that as well? (1=yes) +DO_REMOUNT_NOATIME=1 + # age time, in seconds. should be put into a sysconfig file MAX_AGE=600 @@ -335,6 +343,10 @@ if [ ! -w /proc/sys/vm/laptop_mode ]; th exit 1 fi +if [ $DO_REMOUNT_NOATIME -eq 1 ]; then + NOATIME_OPT=",noatime" +fi + case "$1" in start) AGE=$((100*$MAX_AGE)) @@ -376,10 +388,10 @@ case "$1" in case "$FST" in "ext3"|"reiserfs") PARSEDOPTS="$(parse_mount_opts commit "$OPTS")" - mount $DEV -t $FST $MP -o remount,$PARSEDOPTS,commit=$MAX_AGE,noatime + mount $DEV -t $FST $MP -o remount,$PARSEDOPTS,commit=$MAX_AGE$NOATIME_OPT ;; "xfs") - mount $DEV -t $FST $MP -o remount,$OPTS,noatime + mount $DEV -t $FST $MP -o remount,$OPTS$NOATIME_OPT ;; esac if [ -b $DEV ] ; then --- linux-2.6.6/Documentation/md.txt 2003-06-14 12:18:25.000000000 -0700 +++ 25/Documentation/md.txt 2004-05-10 01:19:52.579745720 -0700 @@ -2,6 +2,8 @@ Tools that manage md devices can be foun http://www..kernel.org/pub/linux/utils/raid/.... +Boot time assembly of RAID arrays +--------------------------------- You can boot with your md device with the following kernel command lines: @@ -11,6 +13,8 @@ for old raid arrays without persistent s for raid arrays with persistent superblocks md=,dev0,dev1,...,devn +or, to assemble a partitionable array: + md=d,dev0,dev1,...,devn md device no. = the number of the md device ... 0 means md0, @@ -34,7 +38,22 @@ A possible loadlin line (Harald Hoyer +#include + +#define LINUX_REBOOT_MAGIC1 0xfee1dead +#define LINUX_REBOOT_MAGIC2 672274793 +#define LINUX_REBOOT_CMD_SW_SUSPEND 0xD000FCE2 + +int main() +{ + syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, + LINUX_REBOOT_CMD_SW_SUSPEND, 0); + return 0; +} --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/Documentation/sched-domains.txt 2004-05-10 01:19:19.516772056 -0700 @@ -0,0 +1,55 @@ +Each CPU has a "base" scheduling domain (struct sched_domain). These are +accessed via cpu_sched_domain(i) and this_sched_domain() macros. The domain +hierarchy is built from these base domains via the ->parent pointer. ->parent +MUST be NULL terminated, and domain structures should be per-CPU as they +are locklessly updated. + +Each scheduling domain spans a number of CPUs (stored in the ->span field). +A domain's span MUST be a superset of it child's span, and a base domain +for CPU i MUST span at least i. The top domain for each CPU will generally +span all CPUs in the system although strictly it doesn't have to, but this +could lead to a case where some CPUs will never be given tasks to run unless +the CPUs allowed mask is explicitly set. A sched domain's span means "balance +process load among these CPUs". + +Each scheduling domain must have one or more CPU groups (struct sched_group) +which are organised as a circular one way linked list from the ->groups +pointer. The union of cpumasks of these groups MUST be the same as the +domain's span. The intersection of cpumasks from any two of these groups +MUST be the empty set. The group pointed to by the ->groups pointer MUST +contain the CPU to which the domain belongs. Groups may be shared among +CPUs as they contain read only data after they have been set up. + +Balancing within a sched domain occurs between groups. That is, each group +is treated as one entity. The load of a group is defined as the sum of the +load of each of its member CPUs, and only when the load of a group becomes +out of balance are tasks moved between groups. + +In kernel/sched.c, rebalance_tick is run periodically on each CPU. This +function takes its CPU's base sched domain and checks to see if has reached +its rebalance interval. If so, then it will run load_balance on that domain. +rebalance_tick then checks the parent sched_domain (if it exists), and the +parent of the parent and so forth. + +*** Implementing sched domains *** +The "base" domain will "span" the first level of the hierarchy. In the case +of SMT, you'll span all siblings of the physical CPU, with each group being +a single virtual CPU. + +In SMP, the parent of the base domain will span all physical CPUs in the +node. Each group being a single physical CPU. Then with NUMA, the parent +of the SMP domain will span the entire machine, with each group having the +cpumask of a node. Or, you could do multi-level NUMA or Opteron, for example, +might have just one domain covering its one NUMA level. + +The implementor should read comments in include/linux/sched.h: +struct sched_domain fields, SD_FLAG_*, SD_*_INIT to get an idea of +the specifics and what to tune. + +Implementors should change the line +#undef SCHED_DOMAIN_DEBUG +to +#define SCHED_DOMAIN_DEBUG +in kernel/sched.c as this enables an error checking parse of the sched domains +which should catch most possible errors (described above). It also prints out +the domain structure in a visual format. --- linux-2.6.6/Documentation/scsi/00-INDEX 2003-06-14 12:18:22.000000000 -0700 +++ 25/Documentation/scsi/00-INDEX 2004-05-10 01:19:04.505054184 -0700 @@ -62,6 +62,8 @@ scsi_mid_low_api.txt - info on API between SCSI layer and low level drivers st.txt - info on scsi tape driver +sym53c500_cs.txt + - info on PCMCIA driver for Symbios Logic 53c500 based adapters sym53c8xx_2.txt - info on second generation driver for sym53c8xx based adapters tmscsim.txt --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/Documentation/scsi/sym53c500_cs.txt 2004-05-10 01:19:04.505054184 -0700 @@ -0,0 +1,23 @@ +The sym53c500_cs driver originated as an add-on to David Hinds' pcmcia-cs +package, and was written by Tom Corner (tcorner@via.at). A rewrite was +long overdue, and the current version addresses the following concerns: + + (1) extensive kernel changes between 2.4 and 2.6. + (2) deprecated PCMCIA support outside the kernel. + +All the USE_BIOS code has been ripped out. It was never used, and could +not have worked anyway. The USE_DMA code is likewise gone. Many thanks +to YOKOTA Hiroshi (nsp_cs driver) and David Hinds (qlogic_cs driver) for +the code fragments I shamelessly adapted for this work. Thanks also to +Christoph Hellwig for his patient tutelage while I stumbled about. + +The Symbios Logic 53c500 chip was used in the "newer" (circa 1997) version +of the New Media Bus Toaster PCMCIA SCSI controller. Presumably there are +other products using this chip, but I've never laid eyes (much less hands) +on one. + +Through the years, there have been a number of downloads of the pcmcia-cs +version of this driver, and I guess it worked for those users. It worked +for Tom Corner, and it works for me. Your mileage will probably vary. + +--Bob Tracy (rct@frus.com) --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/Documentation/should-fix.txt 2004-05-10 01:19:17.081142328 -0700 @@ -0,0 +1,545 @@ +Not-ready features and speedups +=============================== + +Legend: + +PRI1: We're totally lame if this doesn't get in +PRI2: Would be nice +PRI3: Not very important + +drivers/block/ +~~~~~~~~~~~~~~ + +o viro: paride drivers need a big cleanup. Partially done, but ATAPI drivers + need serious work and bug fixing. + + PRI2 + +drivers/char/rtc/ +~~~~~~~~~~~~~~~~~ + +o rmk, trini: add support for alarms to the existing generic rtc driver. + + PRI2 + +console drivers +~~~~~~~~~~~~~~~ + (Pavel Machek ) + +o There are few must-fix bugs in cursor handling. + +o Play with gpm selection for a while and your cursor gets corrupted with + random dots. Ouch. + +device mapper +~~~~~~~~~~~~~ + +o ioctl interface cleanup patch is ready (redo the structure layouts) + + PRI1 + +o A port of the 2.4 snapshot and mirror targets is in progress + + PRI1 + +o the fs interface to dm needs to be redone. gregkh was going to work on + this. viro is interested in seeing work thus-far. + + PRI2 + +drivers/net/wireless/ +~~~~~~~~~~~~~~~~~~~~~ + + (Jean Tourrilhes ) + +o get HostAP driver in the kernel. No consolidation of the 802.11 + management across driver can happen until this one is in (which is probably + 2.7.X material). I think Jouni is mostly ready but didn't find time for + it. + + PRI2 + +o get more wireless drivers into the kernel. The most "integrable" drivers + at this point seem the NWN driver, Pavel's Spectrum driver. + + PRI1 + +drivers/usb/gadget/ +~~~~~~~~~~~~~~~~~~~ + +o rmk: SA11xx USB client/gadget code (David B has been doing some work on + this, and keeps trying to prod me, but unfortunately I haven't had the time + to look at his work, sorry David.) + + PRI3 + +fs/ +~~~ + +o ext3 and ext2 block allocators have serious failure modes - interleaved + allocations. + + PRI3 + +o Integrate Chris Mason's 2.4 reiserfs ordered data and data journaling + patches. They make reiserfs a lot safer. + + Ordered: PRI2 + data journalled: PRI3 + +o viro: convert more filesystems to use lib/parser.c for options. + + PRI2 + +o aio: fs IO isn't async at present. suparna has restart patches, they're + in -mm. Need to get Ben to review/comment. + + PRI1. + +o drepper: various filesystems use ->pid wrongly + + PRI1 + +o hch: devfs: there's a fundamental lookup vs devfsd race that's only + fixable by introducing a lookup vs devfs deadlock. I can't see how this is + fixable without getting rid of the current devfsd design. Mandrake seems + to have a workaround for this so this is at least not triggered so easily, + but that's not what I'd consider a fix.. + + PRI2 + +kernel/ +~~~~~~~ + +o rusty: Zippel's Reference count simplification. Tricky code, but cuts + about 120 lines from module.c. Patch exists, needs stressing. + + PRI3 + +o rusty: Fix module-failed-init races by starting module "disabled". Patch + exists, requires some subsystems (ie. add_partition) to explicitly say + "make module live now". Without patch we are no worse off than 2.4 etc. + + PRI1 + +o Integrate userspace irq balancing daemon. + + PRI2 + +o kexec. Seems to work, was in -mm. + + PRI3 + +o rmk: lib/inflate.c must not use static variables (causes these to be + referenced via GOTOFF relocations in PIC decompressor. We have a PIC + decompressor to avoid having to hard code a per platform zImage link + address into the makefiles.) + + PRI2 + +o klibc merge? + + PRI2 + +mm/ +~~~ + +o dropbehind for large files + + PRI2 + +net/ +~~~~ + + (davem) + +o Real serious use of IPSEC is hampered by lack of MPLS support. MPLS is a + switching technology that works by switching based upon fixed length labels + prepended to packets. Many people use this and IPSEC to implement VPNs + over public networks, it is also used for things like traffic engineering. + + A good reference site is: + + http://www.mplsrc.com/ + + Anyways, an existing (crappy) implementation exists. I've almost + completed a rewrite, I should have something in the tree next week. + + PRI1 + +o Sometimes we generate IP fragments when it truly isn't necessary. + + The way IP fragmentation is specified, each fragment must be modulo 8 + bytes in length. So suppose the device has an MTU that is not 0 modulo 8, + ethernet even classifies in this way. 1500 == (8 * 187) + 4 + + Our IP fragmenting engine can fragment on packets that are sized within + the last modulo 8 bytes of the MTU. This happens in obscure cases, but it + does happen. + + I've proposed a fix to Alexey, whereby very late in the output path we + check the packet, if we fragmented but the data length would fit into the + MTU we unfragment the packet. + + This is low priority, because technically it creates suboptimal behavior + rather than mis-operation. + + PRI1 + +net/*/netfilter/ +~~~~~~~~~~~~~~~~ + +o Lots of misc. cleanups, which are happening slowly. + + PRI2 + +power management +~~~~~~~~~~~~~~~~ + +o Pat and Pavel disagree over swsusp. Need to sort that out. + + PRI2 + +o Frame buffer restore codepaths (that requires some deep PCI magic) + + PRI2 + +o XFree86 hooks + + PRI2 + +o AGP restoration + + PRI2 + +o DRI restoration + + (davej/Alan: not super-critical, can crash laptop on restore. davej + looking into it.) + + PRI2 + +o IDE suspend/resume without races (Ben is looking at this a little) + + PRI2 + +o Pat: There are already CPU device structures; MTRRs should be a + dynamically registered interface of CPUs, which implies there needs + to be some other glue to know that there are MTRRs that need to be + saved/restored. + + PRI1 + +global +~~~~~~ + +o We need a kernel side API for reporting error events to userspace (could + be async to 2.6 itself) + + (Prototype core based on netlink exists) + + PRI2 + +o Kai: Introduce a sane, easy and standard way to build external modules + - make clean and make modules_install are both broken + + PRI2 + +drivers +~~~~~~~ + +o Alan: Cardbus/PCMCIA requires all Russell's stuff is merged to do + multiheader right and so on + + PRI1 + +drivers/acpi/ +~~~~~~~~~~~~~ + +o Fix acpi for all newer IBM Thinkpads see + http://bugme.osdl.org/show_bug.cgi?id=1038 for more information + +o alan: VIA APIC stuff is one bit of this, there are also some other + reports that were caused by ACPI not setting level v edge trigger some + times + + PRI1 + +o mochel: it seems the acpi irq routing code could use a serious rewrite. + + grover: The problem is the ACPI irq routing code is trying to piggyback + on the existing MPS-specific data structures, and it's generally a hack. + So yes mochel is right, but it is also purging MPS-ities from common code + as well. I've done some preliminary work in this area and it doesn't seem + to break anything (yet) but a rewrite in this area imho should not be + rushed out the door. And, I think the above bugs can be fixed w/o the + rewrite. + + PRI2 + +o mochel: ACPI suspend doesn't work. Important, not cricital. Pat is + working it. + + PRI2 + +drivers/block/ +~~~~~~~~~~~~~~ + +o More testing of floppy + + PRI3 + +drivers/char/ +~~~~~~~~~~~~~ + + +drivers/ide/ +~~~~~~~~~~~~ + + (Alan) + +o IDE PIO has occasional unexplained PIO disk eating reports + + PRI1 + +o IDE has multiple zillions of races/hangs in 2.5 still + + PRI1 + +o IDE scsi needs rewriting + + PRI2 + +o IDE needs significant reworking to handle Simplex right + + PRI2 + +o IDE hotplug handling for 2.5 is completely broken still + + PRI2 + +o There are lots of other IDE bugs that wont go away until the taskfile + stuff is included, the locking bugs that allow any user to hang the IDE + layer in 2.5, and some other updates are forward ported. (esp. HPT372N). + + PRI1 + +drivers/isdn/ +~~~~~~~~~~~~~ + + (Kai, rmk) + +o isdn_tty locking is completely broken (cli() and friends) + + PRI2 + +o fix other drivers + + PRI2 + +o lots more cleanups, adaption to recent APIs etc + + PRI3 + +o fixup tty-based ISDN drivers which provide TIOCM* ioctls (see my recent + 3-set patch for serial stuff) + + Alternatively, we could re-introduce the fallback to driver ioctl parsing + for these if not enough drivers get updated. + + PRI3 + +drivers/net/ +~~~~~~~~~~~~ + +o davej: Either Wireless network drivers or PCMCIA broke somewhen. A + configuration that worked fine under 2.4 doesn't receive any packets. Need + to look into this more to make sure I don't have any misconfiguration that + just 'happened to work' under 2.4 + + PRI1 + +drivers/scsi/ +~~~~~~~~~~~~~ + +o jejb: qlogic - + + o Merge the feral driver. It covers all qlogic chips: 1020 all the way + up to 23xxx. http://linux-scsi.bkbits.net/scsi-isp-2.5 + + o qla2xxx: only for FC chips. Has significant build issues. hch + promises to send me a "must fix" list for this. + http://linux-scsi.bkbits.net/scsi-qla2xxx-2.5 + + PRI2 + +o hch, Mike Anderson, Badari Pulavarty: scsi locking issues + + o there are lots of members of struct Scsi_Host/scsi_device/scsi_cmnd + with very unclear locking, many of them probably want to become + atomic_t's or bitmaps (for the 1bit bitfields). + + o there's lots of volatile abuse in the scsi code that needs to be + thought about. + + o there's some global variables incremented without any locks + + PRI2 + +sound/ +~~~~~~ + +o rmk: several OSS drivers for SA11xx-based hardware in need of + ALSA-ification and L3 bus support code for these. + +o rmk: need to complete ALSA-ification of the WaveArtist driver for both + NetWinder and other stuff (there's some fairly fundamental differences in + the way the mixer needs to be handled for the NetWinder.) + + (Issues with forward-porting 2.4 bugfixes.) + (Killing off OSS is 2.7 material) + +PRI2 + +arch/i386/ +~~~~~~~~~~ + +o Also PC9800 merge needs finishing to the point we want for 2.6 (not all). + + PRI3 + +o davej: PAT support (for mtrr exhaustion w/ AGP) + + PRI2 + +o 2.5.x won't boot on some 440GX + + alan: Problem understood now, feasible fix in 2.4/2.4-ac. (440GX has two + IRQ routers, we use the $PIR table with the PIIX, but the 440GX doesnt use + the PIIX for its IRQ routing). Fall back to BIOS for 440GX works and Intel + concurs. + + PRI1 + +o 2.5.x doesn't handle VIA APIC right yet. + + 1. We must write the PCI_INTERRUPT_LINE + + 2. We have quirk handlers that seem to trash it. + + PRI1 + +o ECC driver questions are not yet sorted (DaveJ is working on this) (Dan + Hollis) + + alan: ECC - I have some test bits from Dan's stuff - they need no kernel + core changes for most platforms. That means we can treat it as a random + driver merge. + + PRI3 + +o alan: 2.4 has some fixes for tsc handling bugs. One where some bioses in + SMM mode mess up our toggle on the time high/low or mangle the counter and + one where a few chips need religious use of _p for timer access and we + don't do that. This is forward porting little bits of fixup. + + ACPI HZ stuff we can't trap - a lot of ACPI is implemented as outb's + triggering SMM traps + + PRI1 + +arch/x86_64/ +~~~~~~~~~~~~ + + (Andi) + +o time handling is broken. Need to move up 2.4 time.c code. + + PRI1 + +o NMI watchdog seems to tick too fast + + PRI2 + +o need to coredump 64bit vsyscall code with dwarf2 + + PRI2 + +o move 64bit signal trampolines into vsyscall code and add dwarf2 for it. + (in progress) + + PRI1 + +o describe kernel assembly with dwarf2 annotations for kgdb + + PRI3 + +arch/alpha/ +~~~~~~~~~~~ + +o rth: Ptrace writes are broken. This means we can't (reliably) set + breakpoints or modify variables from gdb. + + PRI1 + +arch/arm/ +~~~~~~~~~ + +o rmk: missing raw keyboard translation tables for all ARM machines. + Haven't even looked into this at all. This could be messy since there + isn't an ARM architecture standard. I'm presently hoping that it won't be + an issue. If it does, I guess we'll see drivers/char/keyboard.c explode. + + PRI2 + +arch/others/ +~~~~~~~~~~~~ + +o SH needs resyncing, as do some other ports. SH64 needs merging. + No impact on mainstream platforms hopefully. + + PRI2 + +arch/s390/ +~~~~~~~~~ + +o A nastly memory management problem causes random crashes. These appear + to be fixed/hidden by the objrmap patch, more investigation is needed. + + PRI1 + +drivers/s390/ +~~~~~~~~~~~~~ + +o Early userspace and 64 bit dev_t will allow the removal of most of + dasd_devmap.c and dasd_genhd.c. + + PRI2 + +o The 3270 console driver needs to be replaced with a working one + (prototype is there, needs to be finished). + + PRI2 + +o Minor interface changes are pending in cio/ when the z990 machines are + out. + + PRI2 + +o Jan Glauber is working on a fix for the timer issues related to running + on virtualized CPUs (wall-clock vs. cpu time). + + PRI1 + +o a block device driver for ramdisks shared among virtual machines + + PRI3 + +o driver for crypto hardware + + PRI3 + +o 'claw' network device driver + + PRI3 + --- linux-2.6.6/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl 2004-04-03 20:39:10.000000000 -0800 +++ 25/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl 2004-05-10 01:19:00.611646072 -0700 @@ -511,7 +511,7 @@ } // (7) - pci_set_drvdata(pci, chip); + pci_set_drvdata(pci, card); dev++; return 0; } @@ -519,10 +519,7 @@ // destructor -- see "Destructor" sub-section static void __devexit snd_mychip_remove(struct pci_dev *pci) { - mychip_t *chip = snd_magic_cast(mychip_t, - pci_get_drvdata(pci), return); - if (chip) - snd_card_free(chip->card); + snd_card_free(pci_get_drvdata(pci)); pci_set_drvdata(pci, NULL); } ]]> @@ -691,21 +688,16 @@ - In the above, the chip record is stored. This pointer is + In the above, the card record is stored. This pointer is referred in the remove callback and power-management callbacks, too. - If the card doesn't support the suspend/resume, you can store - the card pointer instead of the chip pointer, so that - snd_card_free can be called directly - without cast in the remove callback. But anyway, be sure - which pointer is used. @@ -726,21 +718,15 @@ card); + snd_card_free(pci_get_drvdata(pci)); pci_set_drvdata(pci, NULL); } ]]> - The above code assumes that the chip is allocated - with snd_magic stuff and - has the field to hold the card pointer (see the next - section). + The above code assumes that the card pointer is set to the PCI + driver data. @@ -1355,16 +1341,7 @@ // initialization of the module static int __init alsa_card_mychip_init(void) { - int err; - - if ((err = pci_module_init(&driver)) < 0) { - #ifdef MODULE - printk(KERN_ERR "My chip soundcard not found " - "or device busy\n"); - #endif - return err; - } - return 0; + return pci_module_init(&driver); } // clean up the module @@ -1781,16 +1758,7 @@ - Basic jobs of suspend/resume are done in - suspend and - resume callbacks of - pci_driver struct. Unfortunately, the - API of these callbacks was changed at the middle time of Linux - 2.4.x, if you want to keep the support for older kernels, you - have to write two different callbacks. The example below is the - skeleton callbacks which just call the real suspend and resume - functions. + ALSA provides the common power-management layer. Each card driver + needs to have only low-level suspend and resume callbacks. @@ -5302,17 +5246,10 @@ struct _snd_pcm_runtime { - For keeping the readability of 2.6 source code, it's recommended to - separate the above ifdef condition as the patch file in alsa-driver - directory. - See alsa-driver/pci/ali5451.c for example. - - - The scheme of the real suspend job is as following. - Check whether the power-state is already D3hot. If yes, skip the job. + Retrieve the chip data from pm_private_data field. Call snd_pcm_suspend_all() to suspend the running PCM streams. Save the register values if necessary. Stop the hardware if necessary. @@ -5326,12 +5263,11 @@ struct _snd_pcm_runtime { card; // (1) - if (card->power_state == SNDRV_CTL_POWER_D3hot) - return; + mychip_t *chip = snd_magic_cast(mychip_t, card->pm_private_data, + return -ENXIO); // (2) snd_pcm_suspend_all(chip->pcm); // (3) @@ -5340,6 +5276,7 @@ struct _snd_pcm_runtime { snd_mychip_stop_hardware(chip); // (5) snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); + return 0; } ]]> @@ -5350,8 +5287,7 @@ struct _snd_pcm_runtime { The scheme of the real resume job is as following. - Check whether the power-state is already D0. - If yes, skip the job. + Retrieve the chip data from pm_private_data field. Enable the pci device again by calling pci_enable_device(). Re-initialize the chip. @@ -5372,10 +5308,9 @@ struct _snd_pcm_runtime { card; // (1) - if (card->power_state == SNDRV_CTL_POWER_D0) - return; + mychip_t *chip = snd_magic_cast(mychip_t, card->pm_private_data, + return -ENXIO); // (2) pci_enable_device(chip->pci); // (3) @@ -5388,38 +5323,6 @@ struct _snd_pcm_runtime { snd_mychip_restart_chip(chip); // (7) snd_power_change_state(card, SNDRV_CTL_POWER_D0); - } -]]> - - - - - - In addition to the callbacks above, you should define a callback - for the changes via the ALSA control interface. It's defined - like below: - - - -power_state_private_data, return -ENXIO); - switch (power_state) { - case SNDRV_CTL_POWER_D0: - case SNDRV_CTL_POWER_D1: - case SNDRV_CTL_POWER_D2: - mychip_resume(chip); - break; - case SNDRV_CTL_POWER_D3hot: - case SNDRV_CTL_POWER_D3cold: - mychip_suspend(chip); - break; - default: - return -EINVAL; - } return 0; } ]]> @@ -5439,41 +5342,42 @@ struct _snd_pcm_runtime { { .... snd_card_t *card; + mychip_t *chip; .... - #ifdef CONFIG_PM - card->set_power_state = snd_mychip_set_power_state; - card->power_state_private_data = chip; - #endif + snd_card_set_pm_callback(card, snd_my_suspend, snd_my_resume, chip); .... } ]]> + + Here you don't have to put ifdef CONFIG_PM around, since it's already + checked in the header and expanded to empty if not needed. If you need a space for saving the registers, you'll need to - allocate the buffer for it here, too, since you cannot call - kmalloc() with - GFP_KERNEL flag or - vmalloc() in the suspend callback. + allocate the buffer for it here, too, since it would be fatal + if you cannot allocate a memory in the suspend phase. The allocated buffer should be released in the corresponding destructor. And next, set suspend/resume callbacks to the pci_driver, + This can be done by passing a macro SND_PCI_PM_CALLBACKS + in the pci_driver struct. This macro is expanded to the correct + (global) callbacks if CONFIG_PM is set. @@ -5521,7 +5425,8 @@ struct _snd_pcm_runtime { The module parameters must be declared with the standard - MODULE_PARM() and + module_param()(), + module_param_array()() and MODULE_PARM_DESC() macros. The ALSA provides an additional macro, MODULE_PARM_SYNTAX(), for describing its syntax. The strings will be written to @@ -5545,18 +5450,22 @@ struct _snd_pcm_runtime { + + Here boot_devs is passed but simply ignored since we don't care + the number of parsed parameters. @@ -5577,39 +5486,6 @@ struct _snd_pcm_runtime { - - For building the driver into kernel, you should define the - setup() function in addition, too. - ALSA provides get_id() function to retrieve - a string argument from the kernel boot parameters. - - - -= SNDRV_CARDS) - return 0; - (void)(get_option(&str,&enable[nr_dev]) == 2 && - get_option(&str,&index[nr_dev]) == 2 && - get_id(&str,&id[nr_dev]) == 2); - nr_dev++; - return 1; - } - - __setup("snd-mychip=", alsa_card_mychip_setup); - - #endif /* ifndef MODULE */ -]]> - - - --- linux-2.6.6/Documentation/sound/alsa/Procfile.txt 2004-04-03 20:39:10.000000000 -0800 +++ 25/Documentation/sound/alsa/Procfile.txt 2004-05-10 01:19:00.611646072 -0700 @@ -131,6 +131,12 @@ card*/codec97#*/ac97#?-? card*/codec97#0/ac97#?-?+regs Shows the AC97 register dump. Useful for debugging. + When CONFIG_SND_DEBUG is enabled, you can write to this file for + changing an AC97 register directly. Pass two hex numbers. + For example, + + # echo 02 9f1f > /proc/asound/card0/codec97#0/ac97#0-0+regs + Sequencer Information --------------------- --- linux-2.6.6/Documentation/sound/oss/OPL3-SA 2003-06-14 12:18:22.000000000 -0700 +++ 25/Documentation/sound/oss/OPL3-SA 2004-05-10 01:20:01.887330752 -0700 @@ -34,7 +34,7 @@ Module options in detail: mpu_irq: This is the MPU401's IRQ. If you'd like to use the OPL3 FM Synthesizer, make sure you enable -CONFIG_YM3812 (in 'make config'). That'll build the opl3.o module. +CONFIG_SOUND_YM3812 (in 'make config'). That'll build the opl3.o module. Then a simple 'insmod opl3 io=0x388', and you now have FM Synth. --- linux-2.6.6/Documentation/sound/oss/VIBRA16 2003-06-14 12:18:00.000000000 -0700 +++ 25/Documentation/sound/oss/VIBRA16 2004-05-10 01:20:01.887330752 -0700 @@ -62,12 +62,12 @@ modprobe sb io=0x220 irq=5 dma=1 dma16=3 Or, take the hard way: -insmod souncore -insmod sound -insmod uart401 -insmod sb io=0x220 irq=5 dma=1 dma16=3 +modprobe soundcore +modprobe sound +modprobe uart401 +modprobe sb io=0x220 irq=5 dma=1 dma16=3 # do you need MIDI? -insmod opl3=0x388 +modprobe opl3=0x388 Just in case, the kernel sound support should be: --- linux-2.6.6/Documentation/usb/mtouchusb.txt 2004-04-03 20:39:10.000000000 -0800 +++ 25/Documentation/usb/mtouchusb.txt 2004-05-10 01:19:05.754864184 -0700 @@ -1,26 +1,38 @@ CHANGES -- Created based off of scanner & INSTALL from the original touchscreen +- 0.3 - Created based off of scanner & INSTALL from the original touchscreen driver on freshmeat (http://freshmeat.net/projects/3mtouchscreendriver) - Amended for linux-2.4.18, then 2.4.19 -- Complete rewrite using Linux Input in 2.6.3 +- 0.5 - Complete rewrite using Linux Input in 2.6.3 Unfortunately no calibration support at this time +- 1.4 - Multiple changes to support the EXII 5000UC and house cleaning + Changed reset from standard USB dev reset to vendor reset + Changed data sent to host from compensated to raw coordinates + Eliminated vendor/product module params + Performed multiple successfull tests with an EXII-5010UC -DRIVER NOTES: +SUPPORTED HARDWARE: + + All controllers have the Vendor: 0x0596 & Product: 0x0001 -Installation is simple, you only need to add Linux Input, Linux USB, and the -driver to the kernel. The driver can also be optionally built as a module. -If you have another MicroTouch device that you wish to experiment with -or try using this driver with, but the Vendor and Product ID's are not -coded in, don't despair. If the driver was compiled as a module, you can -pass options to the driver. Simply try: + Controller Description Part Number + ------------------------------------------------------ - /sbin/modprobe mtouchusb vendor=0x#### product=0x**** + USB Capacitive - Pearl Case 14-205 (Discontinued) + USB Capacitive - Black Case 14-124 (Discontinued) + USB Capacitive - No Case 14-206 (Discontinued) + + USB Capacitive - Pearl Case EXII-5010UC + USB Capacitive - Black Case EXII-5030UC + USB Capacitive - No Case EXII-5050UC + +DRIVER NOTES: -If it works, send me the iVendor & iProduct (or a patch) and I will add... +Installation is simple, you only need to add Linux Input, Linux USB, and the +driver to the kernel. The driver can also be optionally built as a module. This driver appears to be one of possible 2 Linux USB Input Touchscreen drivers. Although 3M produces a binary only driver available for @@ -28,53 +40,28 @@ download, I persist in updating this dri touchscreen for embedded apps using QTEmbedded, DirectFB, etc. So I feel the logical choice is to use Linux Imput. -A little info about the MicroTouch USB controller (14-206): - -Y is inverted, and the device has a total possible resolution of 0 - 65535. - -Y is inverted by the driver by: +Currently there is no way to calibrate the device via this driver. Even if +the device could be calibrated, the driver pulls to raw coordinate data from +the controller. This means calibration must be performed within the +userspace. + +The controller screen resolution is now 0 to 16384 for both X and Y reporting +the raw touch data. This is the same for the old and new capacitive USB +controllers. + +Perhaps at some point an abstract function will be placed into evdev so +generic functions like calibrations, resets, and vendor information can be +requested from the userspace (And the drivers would handle the vendor specific +tasks). - input.absmin[ABS_Y] = MTOUCHUSB_MAX_YC; - input.absmax[ABS_Y] = MTOUCHUSB_MIN_YC; - -absmin & absmax are also used to scale the data, sine it is rather high -resolution. - - ---------------touch screen area----------------- - I MicroTouch (xmax,ymax) @I - I X I - I ########visible monitor area############## I - I #@ (xmin,ymin) # I - I # # I - I # # I - I # # I - I # # I - I # # I - I Y # # I - I # # I - I # # I - I # # I - I # # I - I # # I - I # (xmax,ymax) @# I - I ########################################## I - I I - I@ MicroTouch (xmin,ymin) I - ------------------------------------------------- - -Currently there is no way to calibrate the device via this driver. Perhaps -at some point an abstract function will be placed into evdev so generic -functions like calibrations, resets, and vendor information can be requested -(And the drivers would handle the vendor specific tasks). - -ADDITIONAL INFORMATION/UPDATES: +ADDITIONAL INFORMATION/UPDATES/X CONFIGURATION EXAMPLE: http://groomlakelabs.com/grandamp/code/microtouch/ TODO: Implement a control urb again to handle requests to and from the device -such as calibration, etc. +such as calibration, etc once/if it becomes available. DISCLAMER: @@ -83,3 +70,7 @@ this driver! If you want touch drivers http://www.3m.com/3MTouchSystems/downloads/ +THANKS: + +A huge thank you to 3M Touch Systems for the EXII-5010UC controllers for +testing! --- linux-2.6.6/Documentation/vm/hugetlbpage.txt 2003-10-08 15:07:08.000000000 -0700 +++ 25/Documentation/vm/hugetlbpage.txt 2004-05-10 01:19:56.472153984 -0700 @@ -91,9 +91,12 @@ A regular chown, chgrp and chmod command used to change the file attributes on hugetlbfs. Also, it is important to note that no such mount command is required if the -applications are going to use only shmat/shmget system calls. It is possible -for same or different applications to use any combination of mmaps and shm* -calls. Though the mount of filesystem will be required for using mmaps. +applications are going to use only shmat/shmget system calls. Users who +wish to use hugetlb page via shared memory segment should be a member of +a supplementary group and system admin needs to configure that gid into +/proc/sys/vm/hugetlb_shm_group. It is possible for same or different +applications to use any combination of mmaps and shm* calls. Though the +mount of filesystem will be required for using mmaps. /* Example of using hugepage in user application using Sys V shared memory * system calls. In this example, app is requesting memory of size 256MB that --- linux-2.6.6/Documentation/vm/locking 2003-10-08 15:07:08.000000000 -0700 +++ 25/Documentation/vm/locking 2004-05-10 01:19:09.771253600 -0700 @@ -66,7 +66,7 @@ in some cases it is not really needed. E expand_stack(), it is hard to come up with a destructive scenario without having the vmlist protection in this case. -The page_table_lock nests with the inode i_shared_sem and the kmem cache +The page_table_lock nests with the inode i_shared_lock and the kmem cache c_spinlock spinlocks. This is okay, since the kmem code asks for pages after dropping c_spinlock. The page_table_lock also nests with pagecache_lock and pagemap_lru_lock spinlocks, and no code asks for memory with these locks --- linux-2.6.6/drivers/atm/firestream.c 2003-10-08 15:07:08.000000000 -0700 +++ 25/drivers/atm/firestream.c 2004-05-10 01:19:28.783363320 -0700 @@ -576,7 +576,7 @@ static inline void write_fs (struct fs_d } -static inline u32 read_fs (struct fs_dev *dev, int offset) +static inline u32 read_fs (struct fs_dev *dev, int offset) { return readl (dev->base + offset); } @@ -1380,7 +1380,7 @@ static void __devinit *aligned_kmalloc ( if (alignment <= 0x10) { t = kmalloc (size, flags); - if ((unsigned int)t & (alignment-1)) { + if ((unsigned long)t & (alignment-1)) { printk ("Kmalloc doesn't align things correctly! %p\n", t); kfree (t); return aligned_kmalloc (size, flags, alignment * 4); @@ -1496,7 +1496,7 @@ static void top_off_fp (struct fs_dev *d ne->skb = skb; ne->fp = fp; - qe = (struct FS_BPENTRY *) (read_fs (dev, FP_EA(fp->offset))); + qe = (struct FS_BPENTRY *)(long)(read_fs (dev, FP_EA(fp->offset))); fs_dprintk (FS_DEBUG_QUEUE, "link at %p\n", qe); if (qe) { qe = bus_to_virt ((long) qe); --- linux-2.6.6/drivers/base/bus.c 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/base/bus.c 2004-05-10 01:19:02.077423240 -0700 @@ -555,21 +555,36 @@ struct bus_type * find_bus(char * name) */ int bus_register(struct bus_type * bus) { + int retval; + kobject_set_name(&bus->subsys.kset.kobj,bus->name); subsys_set_kset(bus,bus_subsys); - subsystem_register(&bus->subsys); + retval = subsystem_register(&bus->subsys); + if (retval) + goto out; kobject_set_name(&bus->devices.kobj, "devices"); bus->devices.subsys = &bus->subsys; - kset_register(&bus->devices); + retval = kset_register(&bus->devices); + if (retval) + goto bus_devices_fail; kobject_set_name(&bus->drivers.kobj, "drivers"); bus->drivers.subsys = &bus->subsys; bus->drivers.ktype = &ktype_driver; - kset_register(&bus->drivers); + retval = kset_register(&bus->drivers); + if (retval) + goto bus_drivers_fail; pr_debug("bus type '%s' registered\n",bus->name); return 0; + +bus_drivers_fail: + kset_unregister(&bus->devices); +bus_devices_fail: + subsystem_unregister(&bus->subsys); +out: + return retval; } --- linux-2.6.6/drivers/base/map.c 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/base/map.c 2004-05-10 01:19:02.078423088 -0700 @@ -138,6 +138,13 @@ struct kobj_map *kobj_map_init(kobj_prob struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL); struct probe *base = kmalloc(sizeof(struct probe), GFP_KERNEL); int i; + + if ((p == NULL) || (base == NULL)) { + kfree(p); + kfree(base); + return NULL; + } + memset(base, 0, sizeof(struct probe)); base->dev = 1; base->range = ~0; --- linux-2.6.6/drivers/base/node.c 2004-03-10 20:41:27.000000000 -0800 +++ 25/drivers/base/node.c 2004-05-10 01:19:10.900081992 -0700 @@ -30,13 +30,20 @@ static ssize_t node_read_cpumap(struct s static SYSDEV_ATTR(cpumap,S_IRUGO,node_read_cpumap,NULL); +/* Can be overwritten by architecture specific code. */ +int __attribute__((weak)) hugetlb_report_node_meminfo(int node, char *buf) +{ + return 0; +} + #define K(x) ((x) << (PAGE_SHIFT - 10)) static ssize_t node_read_meminfo(struct sys_device * dev, char * buf) { + int n; int nid = dev->id; struct sysinfo i; si_meminfo_node(&i, nid); - return sprintf(buf, "\n" + n = sprintf(buf, "\n" "Node %d MemTotal: %8lu kB\n" "Node %d MemFree: %8lu kB\n" "Node %d MemUsed: %8lu kB\n" @@ -51,10 +58,52 @@ static ssize_t node_read_meminfo(struct nid, K(i.freehigh), nid, K(i.totalram-i.totalhigh), nid, K(i.freeram-i.freehigh)); + n += hugetlb_report_node_meminfo(nid, buf + n); + return n; } + #undef K static SYSDEV_ATTR(meminfo,S_IRUGO,node_read_meminfo,NULL); +static ssize_t node_read_numastat(struct sys_device * dev, char * buf) +{ + unsigned long numa_hit, numa_miss, interleave_hit, numa_foreign; + unsigned long local_node, other_node; + int i, cpu; + pg_data_t *pg = NODE_DATA(dev->id); + numa_hit = 0; + numa_miss = 0; + interleave_hit = 0; + numa_foreign = 0; + local_node = 0; + other_node = 0; + for (i = 0; i < MAX_NR_ZONES; i++) { + struct zone *z = &pg->node_zones[i]; + for (cpu = 0; cpu < NR_CPUS; cpu++) { + struct per_cpu_pageset *ps = &z->pageset[cpu]; + numa_hit += ps->numa_hit; + numa_miss += ps->numa_miss; + numa_foreign += ps->numa_foreign; + interleave_hit += ps->interleave_hit; + local_node += ps->local_node; + other_node += ps->other_node; + } + } + return sprintf(buf, + "numa_hit %lu\n" + "numa_miss %lu\n" + "numa_foreign %lu\n" + "interleave_hit %lu\n" + "local_node %lu\n" + "other_node %lu\n", + numa_hit, + numa_miss, + numa_foreign, + interleave_hit, + local_node, + other_node); +} +static SYSDEV_ATTR(numastat,S_IRUGO,node_read_numastat,NULL); /* * register_node - Setup a driverfs device for a node. @@ -74,6 +123,7 @@ int __init register_node(struct node *no if (!error){ sysdev_create_file(&node->sysdev, &attr_cpumap); sysdev_create_file(&node->sysdev, &attr_meminfo); + sysdev_create_file(&node->sysdev, &attr_numastat); } return error; } --- linux-2.6.6/drivers/base/platform.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/base/platform.c 2004-05-10 01:19:02.078423088 -0700 @@ -57,8 +57,9 @@ void platform_device_unregister(struct p * type of device, like "pci" or "floppy", and is the * enumerated instance of the device, like '0' or '42'. * Driver IDs are simply "". - * So, extract the from the device, and compare it against - * the name of the driver. Return whether they match or not. + * So, extract the from the platform_device structure, + * and compare it against the name of the driver. Return whether + * they match or not. */ static int platform_match(struct device * dev, struct device_driver * drv) --- linux-2.6.6/drivers/block/as-iosched.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/block/as-iosched.c 2004-05-10 01:19:55.436311456 -0700 @@ -43,7 +43,7 @@ * read_batch_expire describes how long we will allow a stream of reads to * persist before looking to see whether it is time to switch over to writes. */ -#define default_read_batch_expire (HZ / 4) +#define default_read_batch_expire (HZ / 2) /* * write_batch_expire describes how long we want a stream of writes to run for. @@ -51,7 +51,7 @@ * See, the problem is: we can send a lot of writes to disk cache / TCQ in * a short amount of time... */ -#define default_write_batch_expire (HZ / 16) +#define default_write_batch_expire (HZ / 8) /* * max time we may wait to anticipate a read (default around 6ms) @@ -1216,13 +1216,12 @@ static void as_move_to_dispatch(struct a } as_remove_queued_request(ad->q, rq); + WARN_ON(arq->state != AS_RQ_QUEUED); + list_add(&rq->queuelist, insert); + arq->state = AS_RQ_DISPATCHED; if (arq->io_context && arq->io_context->aic) atomic_inc(&arq->io_context->aic->nr_dispatched); - - WARN_ON(arq->state != AS_RQ_QUEUED); - arq->state = AS_RQ_DISPATCHED; - ad->nr_dispatched++; } @@ -1492,6 +1491,21 @@ static void as_requeue_request(request_q as_antic_stop(ad); } +/* + * Account a request that is inserted directly onto the dispatch queue. + * arq->io_context->aic->nr_dispatched should not need to be incremented + * because only new requests should come through here: requeues go through + * our explicit requeue handler. + */ +static void as_account_queued_request(struct as_data *ad, struct request *rq) +{ + if (blk_fs_request(rq)) { + struct as_rq *arq = RQ_DATA(rq); + arq->state = AS_RQ_DISPATCHED; + ad->nr_dispatched++; + } +} + static void as_insert_request(request_queue_t *q, struct request *rq, int where) { @@ -1522,10 +1536,12 @@ as_insert_request(request_queue_t *q, st as_move_to_dispatch(ad, ad->next_arq[REQ_ASYNC]); list_add_tail(&rq->queuelist, ad->dispatch); + as_account_queued_request(ad, rq); as_antic_stop(ad); break; case ELEVATOR_INSERT_FRONT: list_add(&rq->queuelist, ad->dispatch); + as_account_queued_request(ad, rq); as_antic_stop(ad); break; case ELEVATOR_INSERT_SORT: --- linux-2.6.6/drivers/block/cciss.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/block/cciss.c 2004-05-10 01:19:28.289438408 -0700 @@ -994,7 +994,7 @@ static int revalidate_allvol(ctlr_info_t drive_info_struct *drv = &(host->drv[i]); if (!drv->nr_blocks) continue; - blk_queue_hardsect_size(host->queue, drv->block_size); + blk_queue_hardsect_size(drv->queue, drv->block_size); set_capacity(disk, drv->nr_blocks); add_disk(disk); } @@ -2019,7 +2019,7 @@ static irqreturn_t do_cciss_intr(int irq CommandList_struct *c; unsigned long flags; __u32 a, a1; - + int j; /* Is this interrupt for us? */ if (( h->access.intr_pending(h) == 0) || (h->interrupts_enabled == 0)) @@ -2065,11 +2065,18 @@ static irqreturn_t do_cciss_intr(int irq } } } - /* * See if we can queue up some more IO + * check every disk that exists on this controller + * and start it's IO */ - blk_start_queue(h->queue); + for(j=0;j < NWD; j++) { + /* make sure the disk has been added and the drive is real */ + /* because this can be called from the middle of init_one */ + if(!(h->gendisk[j]->queue) || !(h->drv[j].nr_blocks) ) + continue; + blk_start_queue(h->gendisk[j]->queue); + } spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); return IRQ_HANDLED; } @@ -2516,7 +2523,6 @@ static void free_hba(int i) static int __devinit cciss_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - request_queue_t *q; int i; int j; @@ -2574,13 +2580,6 @@ static int __devinit cciss_init_one(stru } spin_lock_init(&hba[i]->lock); - q = blk_init_queue(do_cciss_request, &hba[i]->lock); - if (!q) - goto clean4; - - q->backing_dev_info.ra_pages = READ_AHEAD; - hba[i]->queue = q; - q->queuedata = hba[i]; /* Initialize the pdev driver private data. have it point to hba[i]. */ @@ -2602,6 +2601,19 @@ static int __devinit cciss_init_one(stru cciss_procinit(i); + for(j=0; jdrv[j]); + struct gendisk *disk = hba[i]->gendisk[j]; + request_queue_t *q; + + q = blk_init_queue(do_cciss_request, &hba[i]->lock); + if (!q) { + printk(KERN_ERR + "cciss: unable to allocate queue for disk %d\n", + j); + break; + } + drv->queue = q; blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask); /* This is a hardware imposed limit. */ @@ -2612,21 +2624,17 @@ static int __devinit cciss_init_one(stru blk_queue_max_sectors(q, 512); - - for(j=0; jdrv[j]); - struct gendisk *disk = hba[i]->gendisk[j]; - + q->queuedata = hba[i]; sprintf(disk->disk_name, "cciss/c%dd%d", i, j); sprintf(disk->devfs_name, "cciss/host%d/target%d", i, j); disk->major = COMPAQ_CISS_MAJOR + i; disk->first_minor = j << NWD_SHIFT; disk->fops = &cciss_fops; - disk->queue = hba[i]->queue; + disk->queue = q; disk->private_data = drv; if( !(drv->nr_blocks)) continue; - blk_queue_hardsect_size(hba[i]->queue, drv->block_size); + blk_queue_hardsect_size(q, drv->block_size); set_capacity(disk, drv->nr_blocks); add_disk(disk); } @@ -2696,9 +2704,9 @@ static void __devexit cciss_remove_one ( struct gendisk *disk = hba[i]->gendisk[j]; if (disk->flags & GENHD_FL_UP) del_gendisk(disk); + blk_cleanup_queue(disk->queue); } - blk_cleanup_queue(hba[i]->queue); pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct), hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle); pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof( ErrorInfo_struct), --- linux-2.6.6/drivers/block/cciss.h 2004-02-17 20:48:42.000000000 -0800 +++ 25/drivers/block/cciss.h 2004-05-10 01:19:28.290438256 -0700 @@ -27,6 +27,7 @@ typedef struct _drive_info_struct { __u32 LunID; int usage_count; + struct request_queue *queue; sector_t nr_blocks; int block_size; int heads; @@ -69,7 +70,6 @@ struct ctlr_info unsigned int maxQsinceinit; unsigned int maxSG; spinlock_t lock; - struct request_queue *queue; //* pointers to command and error info pool */ CommandList_struct *cmd_pool; @@ -252,7 +252,7 @@ struct board_type { struct access_method *access; }; -#define CCISS_LOCK(i) (hba[i]->queue->queue_lock) +#define CCISS_LOCK(i) (&(hba[i]->lock)) #endif /* CCISS_H */ --- linux-2.6.6/drivers/block/cpqarray.c 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/block/cpqarray.c 2004-05-10 01:19:56.928084672 -0700 @@ -1193,7 +1193,7 @@ static int ida_ioctl(struct inode *inode if (error) goto out_passthru; error = -EFAULT; - if (copy_to_user(io, &my_io, sizeof(*my_io))) + if (copy_to_user(io, my_io, sizeof(*my_io))) goto out_passthru; error = 0; out_passthru: --- linux-2.6.6/drivers/block/elevator.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/block/elevator.c 2004-05-10 01:19:55.436311456 -0700 @@ -169,6 +169,13 @@ void elv_requeue_request(request_queue_t void __elv_add_request(request_queue_t *q, struct request *rq, int where, int plug) { + /* + * barriers implicitly indicate back insertion + */ + if (rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER) && + where == ELEVATOR_INSERT_SORT) + where = ELEVATOR_INSERT_BACK; + if (plug) blk_plug_device(q); --- linux-2.6.6/drivers/block/ida_cmd.h 2003-06-14 12:18:06.000000000 -0700 +++ 25/drivers/block/ida_cmd.h 2004-05-10 01:19:56.928084672 -0700 @@ -67,7 +67,7 @@ typedef struct { __u8 reserved; } rhdr_t; -#define SG_MAX 31 +#define SG_MAX 32 typedef struct { rhdr_t hdr; sg_t sg[SG_MAX]; --- linux-2.6.6/drivers/block/ll_rw_blk.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/block/ll_rw_blk.c 2004-05-10 01:19:54.667428344 -0700 @@ -70,14 +70,7 @@ EXPORT_SYMBOL(blk_max_pfn); */ static inline int queue_congestion_on_threshold(struct request_queue *q) { - int ret; - - ret = q->nr_requests - (q->nr_requests / 8) + 1; - - if (ret > q->nr_requests) - ret = q->nr_requests; - - return ret; + return q->nr_congestion_on; } /* @@ -85,32 +78,46 @@ static inline int queue_congestion_on_th */ static inline int queue_congestion_off_threshold(struct request_queue *q) { - int ret; + return q->nr_congestion_off; +} - ret = q->nr_requests - (q->nr_requests / 8) - 1; +static void blk_queue_congestion_threshold(struct request_queue *q) +{ + int nr; - if (ret < 1) - ret = 1; + nr = q->nr_requests - (q->nr_requests / 8) + 1; + if (nr > q->nr_requests) + nr = q->nr_requests; + q->nr_congestion_on = nr; - return ret; + nr = q->nr_requests - (q->nr_requests / 8) - 1; + if (nr < 1) + nr = 1; + q->nr_congestion_off = nr; } -/* - * A queue has just exitted congestion. Note this in the global counter of - * congested queues, and wake up anyone who was waiting for requests to be - * put back. - */ -static void clear_queue_congested(request_queue_t *q, int rw) +void clear_backing_dev_congested(struct backing_dev_info *bdi, int rw) { enum bdi_state bit; wait_queue_head_t *wqh = &congestion_wqh[rw]; bit = (rw == WRITE) ? BDI_write_congested : BDI_read_congested; - clear_bit(bit, &q->backing_dev_info.state); + clear_bit(bit, &bdi->state); smp_mb__after_clear_bit(); if (waitqueue_active(wqh)) wake_up(wqh); } +EXPORT_SYMBOL(clear_backing_dev_congested); + +/* + * A queue has just exitted congestion. Note this in the global counter of + * congested queues, and wake up anyone who was waiting for requests to be + * put back. + */ +static void clear_queue_congested(request_queue_t *q, int rw) +{ + clear_backing_dev_congested(&q->backing_dev_info, rw); +} /* * A queue has just entered congestion. Flag that in the queue's VM-visible @@ -229,6 +236,7 @@ void blk_queue_make_request(request_queu blk_queue_max_sectors(q, MAX_SECTORS); blk_queue_hardsect_size(q, 512); blk_queue_dma_alignment(q, 511); + blk_queue_congestion_threshold(q); q->unplug_thresh = 4; /* hmm */ q->unplug_delay = (3 * HZ) / 1000; /* 3 milliseconds */ @@ -265,8 +273,6 @@ EXPORT_SYMBOL(blk_queue_make_request); void blk_queue_bounce_limit(request_queue_t *q, u64 dma_addr) { unsigned long bounce_pfn = dma_addr >> PAGE_SHIFT; - unsigned long mb = dma_addr >> 20; - static request_queue_t *last_q; /* * set appropriate bounce gfp mask -- unfortunately we don't have a @@ -280,19 +286,7 @@ void blk_queue_bounce_limit(request_queu } else q->bounce_gfp = GFP_NOIO; - /* - * keep this for debugging for now... - */ - if (dma_addr != BLK_BOUNCE_HIGH && q != last_q) { - printk("blk: queue %p, ", q); - if (dma_addr == BLK_BOUNCE_ANY) - printk("no I/O memory limit\n"); - else - printk("I/O limit %luMb (mask 0x%Lx)\n", mb, (long long) dma_addr); - } - q->bounce_pfn = bounce_pfn; - last_q = q; } EXPORT_SYMBOL(blk_queue_bounce_limit); @@ -1142,7 +1136,7 @@ static inline void __generic_unplug_devi /** * generic_unplug_device - fire a request queue - * @data: The &request_queue_t in question + * @q: The &request_queue_t in question * * Description: * Linux uses plugging to build bigger requests queues before letting @@ -1153,6 +1147,7 @@ static inline void __generic_unplug_devi **/ void generic_unplug_device(request_queue_t *q) { + might_sleep(); spin_lock_irq(q->queue_lock); __generic_unplug_device(q); spin_unlock_irq(q->queue_lock); @@ -1206,7 +1201,7 @@ void blk_start_queue(request_queue_t *q) clear_bit(QUEUE_FLAG_REENTER, &q->queue_flags); } else { blk_plug_device(q); - schedule_work(&q->unplug_work); + kblockd_schedule_work(&q->unplug_work); } } @@ -2444,7 +2439,7 @@ void submit_bio(int rw, struct bio *bio) if (unlikely(block_dump)) { char b[BDEVNAME_SIZE]; - printk("%s(%d): %s block %Lu on %s\n", + printk(KERN_DEBUG "%s(%d): %s block %Lu on %s\n", current->comm, current->pid, (rw & WRITE) ? "WRITE" : "READ", (unsigned long long)bio->bi_sector, @@ -2960,6 +2955,7 @@ queue_requests_store(struct request_queu int ret = queue_var_store(&q->nr_requests, page, count); if (q->nr_requests < BLKDEV_MIN_RQ) q->nr_requests = BLKDEV_MIN_RQ; + blk_queue_congestion_threshold(q); if (rl->count[READ] >= queue_congestion_on_threshold(q)) set_queue_congested(q, READ); --- linux-2.6.6/drivers/block/paride/pg.c 2003-09-08 13:58:56.000000000 -0700 +++ 25/drivers/block/paride/pg.c 2004-05-10 01:19:02.079422936 -0700 @@ -161,6 +161,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, #include #include #include +#include #include @@ -240,6 +241,8 @@ static int pg_identify(struct pg *dev, i static char pg_scratch[512]; /* scratch block buffer */ +static struct class_simple *pg_class; + /* kernel glue structures */ static struct file_operations pg_fops = { @@ -658,15 +661,19 @@ static ssize_t pg_read(struct file *filp static int __init pg_init(void) { - int unit; + int unit, err = 0; - if (disable) - return -1; + if (disable){ + err = -1; + goto out; + } pg_init_units(); - if (pg_detect()) - return -1; + if (pg_detect()) { + err = -1; + goto out; + } if (register_chrdev(major, name, &pg_fops)) { printk("pg_init: unable to get major number %d\n", major); @@ -675,18 +682,37 @@ static int __init pg_init(void) if (dev->present) pi_release(dev->pi); } - return -1; + err = -1; + goto out; + } + pg_class = class_simple_create(THIS_MODULE, "pg"); + if (IS_ERR(pg_class)) { + err = PTR_ERR(pg_class); + goto out_chrdev; } devfs_mk_dir("pg"); for (unit = 0; unit < PG_UNITS; unit++) { struct pg *dev = &devices[unit]; if (dev->present) { - devfs_mk_cdev(MKDEV(major, unit), + class_simple_device_add(pg_class, MKDEV(major, unit), + NULL, "pg%u", unit); + err = devfs_mk_cdev(MKDEV(major, unit), S_IFCHR | S_IRUSR | S_IWUSR, "pg/%u", unit); + if (err) + goto out_class; } } - return 0; + err = 0; + goto out; + +out_class: + class_simple_device_remove(MKDEV(major, unit)); + class_simple_destroy(pg_class); +out_chrdev: + unregister_chrdev(major, "pg"); +out: + return err; } static void __exit pg_exit(void) @@ -695,10 +721,12 @@ static void __exit pg_exit(void) for (unit = 0; unit < PG_UNITS; unit++) { struct pg *dev = &devices[unit]; - if (dev->present) + if (dev->present) { + class_simple_device_remove(MKDEV(major, unit)); devfs_remove("pg/%u", unit); + } } - + class_simple_destroy(pg_class); devfs_remove("pg"); unregister_chrdev(major, name); --- linux-2.6.6/drivers/block/paride/pt.c 2003-09-08 13:58:56.000000000 -0700 +++ 25/drivers/block/paride/pt.c 2004-05-10 01:19:02.080422784 -0700 @@ -145,6 +145,7 @@ static int (*drives[4])[6] = {&drive0, & #include #include #include +#include #include @@ -260,6 +261,9 @@ static struct file_operations pt_fops = .release = pt_release, }; +/* sysfs class support */ +static struct class_simple *pt_class; + static inline int status_reg(struct pi_adapter *pi) { return pi_read_regr(pi, 1, 6); @@ -959,33 +963,62 @@ static ssize_t pt_write(struct file *fil static int __init pt_init(void) { - int unit; + int unit, err = 0; - if (disable) - return -1; + if (disable) { + err = -1; + goto out; + } - if (pt_detect()) - return -1; + if (pt_detect()) { + err = -1; + goto out; + } if (register_chrdev(major, name, &pt_fops)) { printk("pt_init: unable to get major number %d\n", major); for (unit = 0; unit < PT_UNITS; unit++) if (pt[unit].present) pi_release(pt[unit].pi); - return -1; + err = -1; + goto out; + } + pt_class = class_simple_create(THIS_MODULE, "pt"); + if (IS_ERR(pt_class)) { + err = PTR_ERR(pt_class); + goto out_chrdev; } devfs_mk_dir("pt"); for (unit = 0; unit < PT_UNITS; unit++) if (pt[unit].present) { - devfs_mk_cdev(MKDEV(major, unit), + class_simple_device_add(pt_class, MKDEV(major, unit), + NULL, "pt%d", unit); + err = devfs_mk_cdev(MKDEV(major, unit), S_IFCHR | S_IRUSR | S_IWUSR, "pt/%d", unit); - devfs_mk_cdev(MKDEV(major, unit + 128), + if (err) { + class_simple_device_remove(MKDEV(major, unit)); + goto out_class; + } + class_simple_device_add(pt_class, MKDEV(major, unit + 128), + NULL, "pt%dn", unit); + err = devfs_mk_cdev(MKDEV(major, unit + 128), S_IFCHR | S_IRUSR | S_IWUSR, "pt/%dn", unit); + if (err) { + class_simple_device_remove(MKDEV(major, unit + 128)); + goto out_class; + } } - return 0; + goto out; + +out_class: + class_simple_destroy(pt_class); +out_chrdev: + unregister_chrdev(major, "pt"); +out: + return err; } static void __exit pt_exit(void) @@ -993,9 +1026,12 @@ static void __exit pt_exit(void) int unit; for (unit = 0; unit < PT_UNITS; unit++) if (pt[unit].present) { + class_simple_device_remove(MKDEV(major, unit)); devfs_remove("pt/%d", unit); + class_simple_device_remove(MKDEV(major, unit + 128)); devfs_remove("pt/%dn", unit); } + class_simple_destroy(pt_class); devfs_remove("pt"); unregister_chrdev(major, name); for (unit = 0; unit < PT_UNITS; unit++) --- linux-2.6.6/drivers/bluetooth/bfusb.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/bluetooth/bfusb.c 2004-05-10 01:19:05.757863728 -0700 @@ -98,14 +98,6 @@ struct bfusb_scb { static void bfusb_tx_complete(struct urb *urb, struct pt_regs *regs); static void bfusb_rx_complete(struct urb *urb, struct pt_regs *regs); -static inline void bfusb_wait_for_urb(struct urb *urb) -{ - while (atomic_read(&urb->count) > 1) { - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout((5 * HZ + 999) / 1000); - } -} - static struct urb *bfusb_get_completed(struct bfusb *bfusb) { struct sk_buff *skb; @@ -132,7 +124,6 @@ static void bfusb_unlink_urbs(struct bfu while ((skb = skb_dequeue(&bfusb->pending_q))) { urb = ((struct bfusb_scb *) skb->cb)->urb; usb_unlink_urb(urb); - bfusb_wait_for_urb(urb); skb_queue_tail(&bfusb->completed_q, skb); } --- linux-2.6.6/drivers/bluetooth/hci_usb.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/bluetooth/hci_usb.c 2004-05-10 01:19:05.758863576 -0700 @@ -342,7 +342,7 @@ static int hci_usb_flush(struct hci_dev static inline void hci_usb_wait_for_urb(struct urb *urb) { - while (atomic_read(&urb->count) > 1) { + while (atomic_read(&urb->kref.refcount) > 1) { current->state = TASK_UNINTERRUPTIBLE; schedule_timeout((5 * HZ + 999) / 1000); } --- linux-2.6.6/drivers/char/agp/ati-agp.c 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/char/agp/ati-agp.c 2004-05-10 01:18:59.977742440 -0700 @@ -131,6 +131,7 @@ static int ati_create_gatt_pages(int nr_ i--; } kfree (tables); + tables = NULL; retval = -ENOMEM; break; } --- linux-2.6.6/drivers/char/agp/sis-agp.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/char/agp/sis-agp.c 2004-05-10 01:19:42.998202336 -0700 @@ -13,6 +13,8 @@ #define SIS_TLBCNTRL 0x97 #define SIS_TLBFLUSH 0x98 +static int __devinitdata agp_sis_force_delay = 0; +static int __devinitdata agp_sis_agp_spec = -1; static int sis_fetch_size(void) { @@ -67,7 +69,7 @@ static void sis_cleanup(void) (previous_size->size_value & ~(0x03))); } -static void sis_648_enable(u32 mode) +static void sis_delayed_enable(u32 mode) { struct pci_dev *device = NULL; u32 command; @@ -94,13 +96,12 @@ static void sis_648_enable(u32 mode) pci_write_config_dword(device, agp + PCI_AGP_COMMAND, command); /* - * Weird: on 648(fx) and 746(fx) chipsets any rate change in the target + * Weird: on some sis chipsets any rate change in the target * command register triggers a 5ms screwup during which the master * cannot be configured */ - if (device->device == PCI_DEVICE_ID_SI_648 || - device->device == PCI_DEVICE_ID_SI_746) { - printk(KERN_INFO PFX "SiS chipset with AGP problems detected. Giving bridge time to recover.\n"); + if (device->device == agp_bridge->dev->device) { + printk(KERN_INFO PFX "SiS delay workaround: giving bridge time to recover.\n"); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout (1+(HZ*10)/1000); } @@ -223,28 +224,35 @@ static struct agp_device_ids sis_agp_dev }; +// chipsets that require the 'delay hack' +static int sis_broken_chipsets[] __devinitdata = { + PCI_DEVICE_ID_SI_648, + PCI_DEVICE_ID_SI_746, + 0 // terminator +}; + static void __devinit sis_get_driver(struct agp_bridge_data *bridge) { - if (bridge->dev->device == PCI_DEVICE_ID_SI_648) { - sis_driver.agp_enable=sis_648_enable; - if (agp_bridge->major_version == 3) { - sis_driver.aperture_sizes = agp3_generic_sizes; - sis_driver.size_type = U16_APER_SIZE; - sis_driver.num_aperture_sizes = AGP_GENERIC_SIZES_ENTRIES; - sis_driver.configure = agp3_generic_configure; - sis_driver.fetch_size = agp3_generic_fetch_size; - sis_driver.cleanup = agp3_generic_cleanup; - sis_driver.tlb_flush = agp3_generic_tlbflush; - } - } + int i; - if (bridge->dev->device == PCI_DEVICE_ID_SI_746) { - /* - * We don't know enough about the 746 to enable it properly. - * Though we do know that it needs the 'delay' hack to settle - * after changing modes. - */ - sis_driver.agp_enable=sis_648_enable; + for(i=0; sis_broken_chipsets[i]!=0; ++i) + if(bridge->dev->device==sis_broken_chipsets[i]) + break; + + if(sis_broken_chipsets[i] || agp_sis_force_delay) + sis_driver.agp_enable=sis_delayed_enable; + + // sis chipsets that indicate less than agp3.5 + // are not actually fully agp3 compliant + if ((agp_bridge->major_version == 3 && agp_bridge->minor_version >= 5 + && agp_sis_agp_spec!=0) || agp_sis_agp_spec==1) { + sis_driver.aperture_sizes = agp3_generic_sizes; + sis_driver.size_type = U16_APER_SIZE; + sis_driver.num_aperture_sizes = AGP_GENERIC_SIZES_ENTRIES; + sis_driver.configure = agp3_generic_configure; + sis_driver.fetch_size = agp3_generic_fetch_size; + sis_driver.cleanup = agp3_generic_cleanup; + sis_driver.tlb_flush = agp3_generic_tlbflush; } } @@ -335,4 +343,8 @@ static void __exit agp_sis_cleanup(void) module_init(agp_sis_init); module_exit(agp_sis_cleanup); +MODULE_PARM(agp_sis_force_delay,"i"); +MODULE_PARM_DESC(agp_sis_force_delay,"forces sis delay hack"); +MODULE_PARM(agp_sis_agp_spec,"i"); +MODULE_PARM_DESC(agp_sis_agp_spec,"0=force sis init, 1=force generic agp3 init, default: autodetect"); MODULE_LICENSE("GPL and additional rights"); --- linux-2.6.6/drivers/char/consolemap.c 2003-06-14 12:18:28.000000000 -0700 +++ 25/drivers/char/consolemap.c 2004-05-10 01:20:01.131445664 -0700 @@ -577,6 +577,7 @@ con_set_default_unimap(int con) dflt = p; return err; } +EXPORT_SYMBOL(con_set_default_unimap); int con_copy_unimap(int dstcon, int srccon) --- linux-2.6.6/drivers/char/cyclades.c 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/char/cyclades.c 2004-05-10 01:19:51.159961560 -0700 @@ -681,20 +681,6 @@ static char rcsid[] = static void cy_throttle (struct tty_struct *tty); static void cy_send_xchar (struct tty_struct *tty, char ch); -static unsigned long -cy_get_user(unsigned long *addr) -{ - unsigned long result = 0; - int error = get_user (result, addr); - if (error) - printk ("cyclades: cy_get_user: error == %d\n", error); - return result; -} - -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - #define IS_CYC_Z(card) ((card).num_chips == -1) #define Z_FPGA_CHECK(card) \ @@ -708,7 +694,7 @@ cy_get_user(unsigned long *addr) ((card).base_addr+ID_ADDRESS))->signature))) #ifndef SERIAL_XMIT_SIZE -#define SERIAL_XMIT_SIZE (MIN(PAGE_SIZE, 4096)) +#define SERIAL_XMIT_SIZE (min(PAGE_SIZE, 4096)) #endif #define WAKEUP_CHARS 256 @@ -2680,7 +2666,7 @@ cy_wait_until_sent(struct tty_struct *tt unsigned char *base_addr; int card,chip,channel,index; unsigned long orig_jiffies; - signed long char_time; + int char_time; if (serial_paranoia_check(info, tty->name, "cy_wait_until_sent")) return; @@ -2705,7 +2691,7 @@ cy_wait_until_sent(struct tty_struct *tt if (timeout < 0) timeout = 0; if (timeout) - char_time = MIN(char_time, timeout); + char_time = min(char_time, timeout); /* * If the transmitter hasn't cleared in twice the approximate * amount of time to send the entire FIFO, it probably won't @@ -2932,8 +2918,8 @@ cy_write(struct tty_struct * tty, int fr while (1) { int c1; - c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); + c = min(count, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1), + (int)(SERIAL_XMIT_SIZE - info->xmit_head))); if (c <= 0) break; @@ -2945,8 +2931,8 @@ cy_write(struct tty_struct * tty, int fr break; } CY_LOCK(info, flags); - c1 = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); + c1 = min(c, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1), + (int)(SERIAL_XMIT_SIZE - info->xmit_head))); if (c1 < c) c = c1; @@ -2962,8 +2948,8 @@ cy_write(struct tty_struct * tty, int fr } else { CY_LOCK(info, flags); while (1) { - c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); + c = min(count, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1), + (int)(SERIAL_XMIT_SIZE - info->xmit_head))); if (c <= 0) break; --- linux-2.6.6/drivers/char/drm/drm_agpsupport.h 2003-11-09 16:45:05.000000000 -0800 +++ 25/drivers/char/drm/drm_agpsupport.h 2004-05-10 01:19:02.401373992 -0700 @@ -103,7 +103,13 @@ int DRM(agp_acquire)(struct inode *inode drm_device_t *dev = priv->dev; int retcode; - if (!dev->agp || dev->agp->acquired || !drm_agp->acquire) + if (!dev->agp) + return -ENODEV; + if (dev->agp->acquired) + return -EBUSY; + if (!drm_agp->acquire) + return -EINVAL; + if ( dev->agp->cant_use_aperture ) return -EINVAL; if ((retcode = drm_agp->acquire())) return retcode; --- linux-2.6.6/drivers/char/drm/drm_bufs.h 2003-07-13 21:44:34.000000000 -0700 +++ 25/drivers/char/drm/drm_bufs.h 2004-05-10 01:19:02.402373840 -0700 @@ -147,7 +147,9 @@ int DRM(addmap)( struct inode *inode, st MTRR_TYPE_WRCOMB, 1 ); } #endif - map->handle = DRM(ioremap)( map->offset, map->size, dev ); + if (map->type == _DRM_REGISTERS) + map->handle = DRM(ioremap)( map->offset, map->size, + dev ); break; case _DRM_SHM: @@ -160,6 +162,12 @@ int DRM(addmap)( struct inode *inode, st } map->offset = (unsigned long)map->handle; if ( map->flags & _DRM_CONTAINS_LOCK ) { + /* Prevent a 2nd X Server from creating a 2nd lock */ + if (dev->lock.hw_lock != NULL) { + vfree( map->handle ); + DRM(free)( map, sizeof(*map), DRM_MEM_MAPS ); + return -EBUSY; + } dev->sigdata.lock = dev->lock.hw_lock = map->handle; /* Pointer to lock */ } @@ -767,7 +775,7 @@ int DRM(addbufs_pci)( struct inode *inod } #endif /* __HAVE_PCI_DMA */ -#ifdef __HAVE_SG +#if __HAVE_SG int DRM(addbufs_sg)( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ) { --- linux-2.6.6/drivers/char/drm/drm_context.h 2003-07-13 21:44:34.000000000 -0700 +++ 25/drivers/char/drm/drm_context.h 2004-05-10 01:19:02.403373688 -0700 @@ -401,6 +401,7 @@ int DRM(addctx)( struct inode *inode, st { drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; + drm_ctx_list_t * ctx_entry; drm_ctx_t ctx; if ( copy_from_user( &ctx, (drm_ctx_t *)arg, sizeof(ctx) ) ) @@ -421,6 +422,20 @@ int DRM(addctx)( struct inode *inode, st if ( ctx.handle != DRM_KERNEL_CONTEXT ) DRIVER_CTX_CTOR(ctx.handle); /* XXX: also pass dev ? */ #endif + ctx_entry = DRM(alloc)( sizeof(*ctx_entry), DRM_MEM_CTXLIST ); + if ( !ctx_entry ) { + DRM_DEBUG("out of memory\n"); + return -ENOMEM; + } + + INIT_LIST_HEAD( &ctx_entry->head ); + ctx_entry->handle = ctx.handle; + ctx_entry->tag = priv; + + down( &dev->ctxlist_sem ); + list_add( &ctx_entry->head, &dev->ctxlist->head ); + ++dev->ctx_count; + up( &dev->ctxlist_sem ); if ( copy_to_user( (drm_ctx_t *)arg, &ctx, sizeof(ctx) ) ) return -EFAULT; @@ -543,6 +558,20 @@ int DRM(rmctx)( struct inode *inode, str DRM(ctxbitmap_free)( dev, ctx.handle ); } + down( &dev->ctxlist_sem ); + if ( !list_empty( &dev->ctxlist->head ) ) { + drm_ctx_list_t *pos, *n; + + list_for_each_entry_safe( pos, n, &dev->ctxlist->head, head ) { + if ( pos->handle == ctx.handle ) { + list_del( &pos->head ); + DRM(free)( pos, sizeof(*pos), DRM_MEM_CTXLIST ); + --dev->ctx_count; + } + } + } + up( &dev->ctxlist_sem ); + return 0; } --- linux-2.6.6/drivers/char/drm/drm_dma.h 2003-07-13 21:44:34.000000000 -0700 +++ 25/drivers/char/drm/drm_dma.h 2004-05-10 01:19:02.405373384 -0700 @@ -35,7 +35,6 @@ #include "drmP.h" -#include /* For task queue support */ #ifndef __HAVE_DMA_WAITQUEUE #define __HAVE_DMA_WAITQUEUE 0 @@ -43,15 +42,6 @@ #ifndef __HAVE_DMA_RECLAIM #define __HAVE_DMA_RECLAIM 0 #endif -#ifndef __HAVE_SHARED_IRQ -#define __HAVE_SHARED_IRQ 0 -#endif - -#if __HAVE_SHARED_IRQ -#define DRM_IRQ_TYPE SA_SHIRQ -#else -#define DRM_IRQ_TYPE 0 -#endif #if __HAVE_DMA @@ -214,293 +204,11 @@ void DRM(reclaim_buffers)( struct file * } #endif - - - -#if __HAVE_DMA_IRQ - -/** - * Install IRQ handler. - * - * \param dev DRM device. - * \param irq IRQ number. - * - * Initializes the IRQ related data, and setups drm_device::vbl_queue. Installs the handler, calling the driver - * \c DRM(driver_irq_preinstall)() and \c DRM(driver_irq_postinstall)() functions - * before and after the installation. - */ -int DRM(irq_install)( drm_device_t *dev, int irq ) -{ - int ret; - - if ( !irq ) - return -EINVAL; - - down( &dev->struct_sem ); - - /* Driver must have been initialized */ - if ( !dev->dev_private ) { - up( &dev->struct_sem ); - return -EINVAL; - } - - if ( dev->irq ) { - up( &dev->struct_sem ); - return -EBUSY; - } - dev->irq = irq; - up( &dev->struct_sem ); - - DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq ); - - dev->context_flag = 0; - dev->interrupt_flag = 0; - dev->dma_flag = 0; - - dev->dma->next_buffer = NULL; - dev->dma->next_queue = NULL; - dev->dma->this_buffer = NULL; - -#if __HAVE_DMA_IRQ_BH - INIT_WORK(&dev->work, DRM(dma_immediate_bh), dev); -#endif - -#if __HAVE_VBL_IRQ - init_waitqueue_head(&dev->vbl_queue); - - spin_lock_init( &dev->vbl_lock ); - - INIT_LIST_HEAD( &dev->vbl_sigs.head ); - - dev->vbl_pending = 0; -#endif - - /* Before installing handler */ - DRM(driver_irq_preinstall)(dev); - - /* Install handler */ - ret = request_irq( dev->irq, DRM(dma_service), - DRM_IRQ_TYPE, dev->devname, dev ); - if ( ret < 0 ) { - down( &dev->struct_sem ); - dev->irq = 0; - up( &dev->struct_sem ); - return ret; - } - - /* After installing handler */ - DRM(driver_irq_postinstall)(dev); - - return 0; -} - -/** - * Uninstall the IRQ handler. - * - * \param dev DRM device. - * - * Calls the driver's \c DRM(driver_irq_uninstall)() function, and stops the irq. - */ -int DRM(irq_uninstall)( drm_device_t *dev ) -{ - int irq; - - down( &dev->struct_sem ); - irq = dev->irq; - dev->irq = 0; - up( &dev->struct_sem ); - - if ( !irq ) - return -EINVAL; - - DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq ); - - DRM(driver_irq_uninstall)( dev ); - - free_irq( irq, dev ); - - return 0; -} - -/** - * IRQ control ioctl. - * - * \param inode device inode. - * \param filp file pointer. - * \param cmd command. - * \param arg user argument, pointing to a drm_control structure. - * \return zero on success or a negative number on failure. - * - * Calls irq_install() or irq_uninstall() according to \p arg. - */ -int DRM(control)( struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg ) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - drm_control_t ctl; - - if ( copy_from_user( &ctl, (drm_control_t *)arg, sizeof(ctl) ) ) - return -EFAULT; - - switch ( ctl.func ) { - case DRM_INST_HANDLER: - return DRM(irq_install)( dev, ctl.irq ); - case DRM_UNINST_HANDLER: - return DRM(irq_uninstall)( dev ); - default: - return -EINVAL; - } -} - -#if __HAVE_VBL_IRQ - -/** - * Wait for VBLANK. - * - * \param inode device inode. - * \param filp file pointer. - * \param cmd command. - * \param data user argument, pointing to a drm_wait_vblank structure. - * \return zero on success or a negative number on failure. - * - * Verifies the IRQ is installed. - * - * If a signal is requested checks if this task has already scheduled the same signal - * for the same vblank sequence number - nothing to be done in - * that case. If the number of tasks waiting for the interrupt exceeds 100 the - * function fails. Otherwise adds a new entry to drm_device::vbl_sigs for this - * task. - * - * If a signal is not requested, then calls vblank_wait(). - */ -int DRM(wait_vblank)( DRM_IOCTL_ARGS ) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - drm_wait_vblank_t vblwait; - struct timeval now; - int ret = 0; - unsigned int flags; - - if (!dev->irq) - return -EINVAL; - - DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data, - sizeof(vblwait) ); - - switch ( vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK ) { - case _DRM_VBLANK_RELATIVE: - vblwait.request.sequence += atomic_read( &dev->vbl_received ); - vblwait.request.type &= ~_DRM_VBLANK_RELATIVE; - case _DRM_VBLANK_ABSOLUTE: - break; - default: - return -EINVAL; - } - - flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK; - - if ( flags & _DRM_VBLANK_SIGNAL ) { - unsigned long irqflags; - drm_vbl_sig_t *vbl_sig; - - vblwait.reply.sequence = atomic_read( &dev->vbl_received ); - - spin_lock_irqsave( &dev->vbl_lock, irqflags ); - - /* Check if this task has already scheduled the same signal - * for the same vblank sequence number; nothing to be done in - * that case - */ - list_for_each_entry( vbl_sig, &dev->vbl_sigs.head, head ) { - if (vbl_sig->sequence == vblwait.request.sequence - && vbl_sig->info.si_signo == vblwait.request.signal - && vbl_sig->task == current) - { - spin_unlock_irqrestore( &dev->vbl_lock, irqflags ); - goto done; - } - } - - if ( dev->vbl_pending >= 100 ) { - spin_unlock_irqrestore( &dev->vbl_lock, irqflags ); - return -EBUSY; - } - - dev->vbl_pending++; - - spin_unlock_irqrestore( &dev->vbl_lock, irqflags ); - - if ( !( vbl_sig = DRM_MALLOC( sizeof( drm_vbl_sig_t ) ) ) ) { - return -ENOMEM; - } - - memset( (void *)vbl_sig, 0, sizeof(*vbl_sig) ); - - vbl_sig->sequence = vblwait.request.sequence; - vbl_sig->info.si_signo = vblwait.request.signal; - vbl_sig->task = current; - - spin_lock_irqsave( &dev->vbl_lock, irqflags ); - - list_add_tail( (struct list_head *) vbl_sig, &dev->vbl_sigs.head ); - - spin_unlock_irqrestore( &dev->vbl_lock, irqflags ); - } else { - ret = DRM(vblank_wait)( dev, &vblwait.request.sequence ); - - do_gettimeofday( &now ); - vblwait.reply.tval_sec = now.tv_sec; - vblwait.reply.tval_usec = now.tv_usec; - } - -done: - DRM_COPY_TO_USER_IOCTL( (drm_wait_vblank_t *)data, vblwait, - sizeof(vblwait) ); - - return ret; -} - -/** - * Send the VBLANK signals. - * - * \param dev DRM device. - * - * Sends a signal for each task in drm_device::vbl_sigs and empties the list. - * - * If a signal is not requested, then calls vblank_wait(). +#if !__HAVE_IRQ +/* This stub DRM_IOCTL_CONTROL handler is for the drivers that used to require + * IRQs for DMA but no longer do. It maintains compatibility with the X Servers + * that try to use the control ioctl by simply returning success. */ -void DRM(vbl_send_signals)( drm_device_t *dev ) -{ - struct list_head *list, *tmp; - drm_vbl_sig_t *vbl_sig; - unsigned int vbl_seq = atomic_read( &dev->vbl_received ); - unsigned long flags; - - spin_lock_irqsave( &dev->vbl_lock, flags ); - - list_for_each_safe( list, tmp, &dev->vbl_sigs.head ) { - vbl_sig = list_entry( list, drm_vbl_sig_t, head ); - if ( ( vbl_seq - vbl_sig->sequence ) <= (1<<23) ) { - vbl_sig->info.si_code = vbl_seq; - send_sig_info( vbl_sig->info.si_signo, &vbl_sig->info, vbl_sig->task ); - - list_del( list ); - - DRM_FREE( vbl_sig, sizeof(*vbl_sig) ); - - dev->vbl_pending--; - } - } - - spin_unlock_irqrestore( &dev->vbl_lock, flags ); -} - -#endif /* __HAVE_VBL_IRQ */ - -#else - int DRM(control)( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ) { @@ -517,7 +225,6 @@ int DRM(control)( struct inode *inode, s return -EINVAL; } } - -#endif /* __HAVE_DMA_IRQ */ +#endif #endif /* __HAVE_DMA */ --- linux-2.6.6/drivers/char/drm/drm_drv.h 2003-10-25 14:45:44.000000000 -0700 +++ 25/drivers/char/drm/drm_drv.h 2004-05-10 01:19:02.407373080 -0700 @@ -58,8 +58,8 @@ #ifndef __HAVE_CTX_BITMAP #define __HAVE_CTX_BITMAP 0 #endif -#ifndef __HAVE_DMA_IRQ -#define __HAVE_DMA_IRQ 0 +#ifndef __HAVE_IRQ +#define __HAVE_IRQ 0 #endif #ifndef __HAVE_DMA_QUEUE #define __HAVE_DMA_QUEUE 0 @@ -126,6 +126,9 @@ #ifndef DRIVER_IOCTLS #define DRIVER_IOCTLS #endif +#ifndef DRIVER_OPEN_HELPER +#define DRIVER_OPEN_HELPER( priv, dev ) +#endif #ifndef DRIVER_FOPS #define DRIVER_FOPS \ static struct file_operations DRM(fops) = { \ @@ -159,15 +162,8 @@ __setup( DRIVER_NAME "=", DRM_OPTIONS_FU #undef DRM_OPTIONS_FUNC #endif -/** - * The default number of instances (minor numbers) to initialize. - */ -#ifndef DRIVER_NUM_CARDS -#define DRIVER_NUM_CARDS 1 -#endif - -static drm_device_t *DRM(device); -static int *DRM(minor); +#define MAX_DEVICES 4 +static drm_device_t DRM(device)[MAX_DEVICES]; static int DRM(numdevs) = 0; DRIVER_FOPS; @@ -177,10 +173,13 @@ static drm_ioctl_desc_t DRM(ioctls)[] [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { DRM(version), 0, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { DRM(getunique), 0, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { DRM(getmagic), 0, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { DRM(irq_busid), 0, 1 }, +#if __HAVE_IRQ + [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { DRM(irq_by_busid), 0, 1 }, +#endif [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = { DRM(getmap), 0, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = { DRM(getclient), 0, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = { DRM(getstats), 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] = { DRM(setversion), 0, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { DRM(setunique), 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { DRM(noop), 1, 1 }, @@ -222,9 +221,9 @@ static drm_ioctl_desc_t DRM(ioctls)[] [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { DRM(infobufs), 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { DRM(mapbufs), 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { DRM(freebufs), 1, 0 }, - - /* The DRM_IOCTL_DMA ioctl should be defined by the driver. - */ + /* The DRM_IOCTL_DMA ioctl should be defined by the driver. */ +#endif +#if __HAVE_IRQ || __HAVE_DMA [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { DRM(control), 1, 1 }, #endif @@ -330,6 +329,12 @@ static int DRM(setup)( drm_device_t *dev memset(dev->maplist, 0, sizeof(*dev->maplist)); INIT_LIST_HEAD(&dev->maplist->head); + dev->ctxlist = DRM(alloc)(sizeof(*dev->ctxlist), + DRM_MEM_CTXLIST); + if(dev->ctxlist == NULL) return -ENOMEM; + memset(dev->ctxlist, 0, sizeof(*dev->ctxlist)); + INIT_LIST_HEAD(&dev->ctxlist->head); + dev->vmalist = NULL; dev->sigdata.lock = dev->lock.hw_lock = NULL; init_waitqueue_head( &dev->lock.lock_queue ); @@ -337,7 +342,7 @@ static int DRM(setup)( drm_device_t *dev dev->queue_reserved = 0; dev->queue_slots = 0; dev->queuelist = NULL; - dev->irq = 0; + dev->irq_enabled = 0; dev->context_flag = 0; dev->interrupt_flag = 0; dev->dma_flag = 0; @@ -345,6 +350,7 @@ static int DRM(setup)( drm_device_t *dev dev->last_switch = 0; dev->last_checked = 0; init_waitqueue_head( &dev->context_wait ); + dev->if_version = 0; dev->ctx_start = 0; dev->lck_start = 0; @@ -391,8 +397,8 @@ static int DRM(takedown)( drm_device_t * DRM_DEBUG( "\n" ); DRIVER_PRETAKEDOWN(); -#if __HAVE_DMA_IRQ - if ( dev->irq ) DRM(irq_uninstall)( dev ); +#if __HAVE_IRQ + if ( dev->irq_enabled ) DRM(irq_uninstall)( dev ); #endif down( &dev->struct_sem ); @@ -534,43 +540,104 @@ static int DRM(takedown)( drm_device_t * return 0; } -/** - * Figure out how many instances to initialize. - * - * \return number of cards found. - * - * Searches for every PCI card in \c DRIVER_CARD_LIST with matching vendor and device ids. - */ -static int drm_count_cards(void) +#include "drm_pciids.h" + +static struct pci_device_id DRM(pciidlist)[] = { + DRM(PCI_IDS) +}; + +static int DRM(probe)(struct pci_dev *pdev) { - int num = 0; -#if defined(DRIVER_CARD_LIST) - int i; - drm_pci_list_t *l; - u16 device, vendor; - struct pci_dev *pdev = NULL; + drm_device_t *dev; +#if __HAVE_CTX_BITMAP + int retcode; #endif + int i; + int is_compat = 0; DRM_DEBUG( "\n" ); -#if defined(DRIVER_COUNT_CARDS) - num = DRIVER_COUNT_CARDS(); -#elif defined(DRIVER_CARD_LIST) - for (i = 0, l = DRIVER_CARD_LIST; l[i].vendor != 0; i++) { - pdev = NULL; - vendor = l[i].vendor; - device = l[i].device; - if(device == 0xffff) device = PCI_ANY_ID; - if(vendor == 0xffff) vendor = PCI_ANY_ID; - while ((pdev = pci_find_device(vendor, device, pdev))) { - num++; + for (i = 0; DRM(pciidlist)[i].vendor != 0; i++) { + if ((DRM(pciidlist)[i].vendor == pdev->vendor) && + (DRM(pciidlist)[i].device == pdev->device)) { + is_compat = 1; } } + if (is_compat == 0) + return -ENODEV; + + if (DRM(numdevs) >= MAX_DEVICES) + return -ENODEV; + + dev = &(DRM(device)[DRM(numdevs)]); + + memset( (void *)dev, 0, sizeof(*dev) ); + dev->count_lock = SPIN_LOCK_UNLOCKED; + init_timer( &dev->timer ); + sema_init( &dev->struct_sem, 1 ); + sema_init( &dev->ctxlist_sem, 1 ); + + if ((dev->minor = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0) + return -EPERM; + dev->device = MKDEV(DRM_MAJOR, dev->minor ); + dev->name = DRIVER_NAME; + + dev->pdev = pdev; +#ifdef __alpha__ + dev->hose = pdev->sysdata; + dev->pci_domain = dev->hose->bus->number; #else - num = DRIVER_NUM_CARDS; + dev->pci_domain = 0; +#endif + dev->pci_bus = pdev->bus->number; + dev->pci_slot = PCI_SLOT(pdev->devfn); + dev->pci_func = PCI_FUNC(pdev->devfn); + dev->irq = pdev->irq; + + DRIVER_PREINIT(); + +#if __REALLY_HAVE_AGP + dev->agp = DRM(agp_init)(); +#if __MUST_HAVE_AGP + if ( dev->agp == NULL ) { + DRM_ERROR( "Cannot initialize the agpgart module.\n" ); + DRM(stub_unregister)(dev->minor); + DRM(takedown)( dev ); + return -EINVAL; + } +#endif +#if __REALLY_HAVE_MTRR + if (dev->agp) + dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base, + dev->agp->agp_info.aper_size*1024*1024, + MTRR_TYPE_WRCOMB, + 1 ); +#endif +#endif + +#if __HAVE_CTX_BITMAP + retcode = DRM(ctxbitmap_init)( dev ); + if( retcode ) { + DRM_ERROR( "Cannot allocate memory for context bitmap.\n" ); + DRM(stub_unregister)(dev->minor); + DRM(takedown)( dev ); + return retcode; + } #endif - DRM_DEBUG("numdevs = %d\n", num); - return num; + DRM(numdevs)++; /* no errors, mark it reserved */ + + DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n", + DRIVER_NAME, + DRIVER_MAJOR, + DRIVER_MINOR, + DRIVER_PATCHLEVEL, + DRIVER_DATE, + dev->minor, + pci_pretty_name(pdev)); + + DRIVER_POSTINIT(); + + return 0; } /** @@ -579,7 +646,7 @@ static int drm_count_cards(void) * * \return zero on success or a negative number on failure. * - * Allocates and initialize an array of drm_device structures, and attempts to + * Initializes an array of drm_device structures, and attempts to * initialize all available devices, using consecutive minors, registering the * stubs and initializing the AGP device. * @@ -588,88 +655,19 @@ static int drm_count_cards(void) */ static int __init drm_init( void ) { + struct pci_dev *pdev = NULL; - drm_device_t *dev; - int i; -#if __HAVE_CTX_BITMAP - int retcode; -#endif DRM_DEBUG( "\n" ); #ifdef MODULE DRM(parse_options)( drm_opts ); #endif - DRM(numdevs) = drm_count_cards(); - /* Force at least one instance. */ - if (DRM(numdevs) <= 0) - DRM(numdevs) = 1; - - DRM(device) = kmalloc(sizeof(*DRM(device)) * DRM(numdevs), GFP_KERNEL); - if (!DRM(device)) { - return -ENOMEM; - } - DRM(minor) = kmalloc(sizeof(*DRM(minor)) * DRM(numdevs), GFP_KERNEL); - if (!DRM(minor)) { - kfree(DRM(device)); - return -ENOMEM; - } - - DRIVER_PREINIT(); - DRM(mem_init)(); - for (i = 0; i < DRM(numdevs); i++) { - dev = &(DRM(device)[i]); - memset( (void *)dev, 0, sizeof(*dev) ); - dev->count_lock = SPIN_LOCK_UNLOCKED; - init_timer( &dev->timer ); - sema_init( &dev->struct_sem, 1 ); - - if ((DRM(minor)[i] = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0) - return -EPERM; - dev->device = MKDEV(DRM_MAJOR, DRM(minor)[i] ); - dev->name = DRIVER_NAME; - -#if __REALLY_HAVE_AGP - dev->agp = DRM(agp_init)(); -#if __MUST_HAVE_AGP - if ( dev->agp == NULL ) { - DRM_ERROR( "Cannot initialize the agpgart module.\n" ); - DRM(stub_unregister)(DRM(minor)[i]); - DRM(takedown)( dev ); - return -EINVAL; - } -#endif -#if __REALLY_HAVE_MTRR - if (dev->agp) - dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base, - dev->agp->agp_info.aper_size*1024*1024, - MTRR_TYPE_WRCOMB, - 1 ); -#endif -#endif - -#if __HAVE_CTX_BITMAP - retcode = DRM(ctxbitmap_init)( dev ); - if( retcode ) { - DRM_ERROR( "Cannot allocate memory for context bitmap.\n" ); - DRM(stub_unregister)(DRM(minor)[i]); - DRM(takedown)( dev ); - return retcode; - } -#endif - DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n", - DRIVER_NAME, - DRIVER_MAJOR, - DRIVER_MINOR, - DRIVER_PATCHLEVEL, - DRIVER_DATE, - DRM(minor)[i] ); + while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) { + DRM(probe)(pdev); } - - DRIVER_POSTINIT(); - return 0; } @@ -689,10 +687,10 @@ static void __exit drm_cleanup( void ) for (i = DRM(numdevs) - 1; i >= 0; i--) { dev = &(DRM(device)[i]); - if ( DRM(stub_unregister)(DRM(minor)[i]) ) { + if ( DRM(stub_unregister)(dev->minor) ) { DRM_ERROR( "Cannot unload module\n" ); } else { - DRM_DEBUG("minor %d unregistered\n", DRM(minor)[i]); + DRM_DEBUG("minor %d unregistered\n", dev->minor); if (i == 0) { DRM_INFO( "Module unloaded\n" ); } @@ -722,8 +720,6 @@ static void __exit drm_cleanup( void ) #endif } DRIVER_POSTCLEANUP(); - kfree(DRM(minor)); - kfree(DRM(device)); DRM(numdevs) = 0; } @@ -795,7 +791,7 @@ int DRM(open)( struct inode *inode, stru int i; for (i = 0; i < DRM(numdevs); i++) { - if (iminor(inode) == DRM(minor)[i]) { + if (iminor(inode) == DRM(device)[i].minor) { dev = &(DRM(device)[i]); break; } @@ -908,6 +904,26 @@ int DRM(release)( struct inode *inode, s DRM(fasync)( -1, filp, 0 ); + down( &dev->ctxlist_sem ); + if ( !list_empty( &dev->ctxlist->head ) ) { + drm_ctx_list_t *pos, *n; + + list_for_each_entry_safe( pos, n, &dev->ctxlist->head, head ) { + if ( pos->tag == priv && + pos->handle != DRM_KERNEL_CONTEXT ) { +#ifdef DRIVER_CTX_DTOR + DRIVER_CTX_DTOR(pos->handle); +#endif +#if __HAVE_CTX_BITMAP + DRM(ctxbitmap_free)( dev, pos->handle ); +#endif + list_del( &pos->head ); + DRM(free)( pos, sizeof(*pos), DRM_MEM_CTXLIST ); + } + } + } + up( &dev->ctxlist_sem ); + down( &dev->struct_sem ); if ( priv->remove_auth_on_close == 1 ) { drm_file_t *temp = dev->file_first; --- linux-2.6.6/drivers/char/drm/drm_fops.h 2003-09-27 18:57:44.000000000 -0700 +++ 25/drivers/char/drm/drm_fops.h 2004-05-10 01:19:02.407373080 -0700 @@ -72,6 +72,8 @@ int DRM(open_helper)(struct inode *inode priv->authenticated = capable(CAP_SYS_ADMIN); priv->lock_count = 0; + DRIVER_OPEN_HELPER( priv, dev ); + down(&dev->struct_sem); if (!dev->file_last) { priv->next = NULL; --- linux-2.6.6/drivers/char/drm/drm.h 2003-07-13 21:44:34.000000000 -0700 +++ 25/drivers/char/drm/drm.h 2004-05-10 01:19:02.399374296 -0700 @@ -46,8 +46,8 @@ #define DRM_IOC_WRITE _IOC_WRITE #define DRM_IOC_READWRITE _IOC_READ|_IOC_WRITE #define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size) -#elif defined(__FreeBSD__) || defined(__NetBSD__) -#if defined(__FreeBSD__) && defined(XFree86Server) +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) +#if defined(__FreeBSD__) && defined(IN_MODULE) /* Prevent name collision when including sys/ioccom.h */ #undef ioctl #include @@ -130,6 +130,18 @@ typedef struct drm_tex_region { unsigned int age; } drm_tex_region_t; +/** + * Hardware lock. + * + * The lock structure is a simple cache-line aligned integer. To avoid + * processor bus contention on a multiprocessor system, there should not be any + * other data stored in the same cache line. + */ +typedef struct drm_hw_lock { + __volatile__ unsigned int lock; /**< lock variable */ + char padding[60]; /**< Pad to cache line */ +} drm_hw_lock_t; + /** * DRM_IOCTL_VERSION ioctl argument type. @@ -580,6 +592,16 @@ typedef struct drm_scatter_gather { unsigned long handle; /**< Used for mapping / unmapping */ } drm_scatter_gather_t; +/** + * DRM_IOCTL_SET_VERSION ioctl argument type. + */ +typedef struct drm_set_version { + int drm_di_major; + int drm_di_minor; + int drm_dd_major; + int drm_dd_minor; +} drm_set_version_t; + #define DRM_IOCTL_BASE 'd' #define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr) @@ -594,6 +616,7 @@ typedef struct drm_scatter_gather { #define DRM_IOCTL_GET_MAP DRM_IOWR(0x04, drm_map_t) #define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, drm_client_t) #define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, drm_stats_t) +#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, drm_set_version_t) #define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm_unique_t) #define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, drm_auth_t) --- linux-2.6.6/drivers/char/drm/drm_ioctl.h 2003-07-13 21:44:34.000000000 -0700 +++ 25/drivers/char/drm/drm_ioctl.h 2004-05-10 01:19:02.409372776 -0700 @@ -35,69 +35,7 @@ #include "drmP.h" - -/** - * Get interrupt from bus id. - * - * \param inode device inode. - * \param filp file pointer. - * \param cmd command. - * \param arg user argument, pointing to a drm_irq_busid structure. - * \return zero on success or a negative number on failure. - * - * Finds the PCI device with the specified bus id and gets its IRQ number. - */ -int DRM(irq_busid)(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) -{ - drm_irq_busid_t p; - struct pci_dev *dev; - - if (copy_from_user(&p, (drm_irq_busid_t *)arg, sizeof(p))) - return -EFAULT; -#ifdef __alpha__ - { - int domain = p.busnum >> 8; - p.busnum &= 0xff; - - /* - * Find the hose the device is on (the domain number is the - * hose index) and offset the bus by the root bus of that - * hose. - */ - for(dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,NULL); - dev; - dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,dev)) { - struct pci_controller *hose = dev->sysdata; - - if (hose->index == domain) { - p.busnum += hose->bus->number; - break; - } - } - } -#endif - dev = pci_find_slot(p.busnum, PCI_DEVFN(p.devnum, p.funcnum)); - if (!dev) { - DRM_ERROR("pci_find_slot failed for %d:%d:%d\n", - p.busnum, p.devnum, p.funcnum); - p.irq = 0; - goto out; - } - if (pci_enable_device(dev) != 0) { - DRM_ERROR("pci_enable_device failed for %d:%d:%d\n", - p.busnum, p.devnum, p.funcnum); - p.irq = 0; - goto out; - } - p.irq = dev->irq; - out: - DRM_DEBUG("%d:%d:%d => IRQ %d\n", - p.busnum, p.devnum, p.funcnum, p.irq); - if (copy_to_user((drm_irq_busid_t *)arg, &p, sizeof(p))) - return -EFAULT; - return 0; -} +#include "linux/pci.h" /** * Get the bus id. @@ -138,8 +76,10 @@ int DRM(getunique)(struct inode *inode, * \param arg user argument, pointing to a drm_unique structure. * \return zero on success or a negative number on failure. * - * Copies the bus id from userspace into drm_device::unique, and searches for - * the respective PCI device, updating drm_device::pdev. + * Copies the bus id from userspace into drm_device::unique, and verifies that + * it matches the device this DRM is attached to (EINVAL otherwise). Deprecated + * in interface version 1.1 and will return EBUSY when setversion has requested + * version 1.1 or greater. */ int DRM(setunique)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) @@ -147,6 +87,7 @@ int DRM(setunique)(struct inode *inode, drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_unique_t u; + int domain, bus, slot, func, ret; if (dev->unique_len || dev->unique) return -EBUSY; @@ -164,55 +105,42 @@ int DRM(setunique)(struct inode *inode, dev->devname = DRM(alloc)(strlen(dev->name) + strlen(dev->unique) + 2, DRM_MEM_DRIVER); - if(!dev->devname) { - DRM(free)(dev->devname, sizeof(*dev->devname), DRM_MEM_DRIVER); + if (!dev->devname) return -ENOMEM; - } + sprintf(dev->devname, "%s@%s", dev->name, dev->unique); - do { - struct pci_dev *pci_dev; - int domain, b, d, f; - char *p; - - for(p = dev->unique; p && *p && *p != ':'; p++); - if (!p || !*p) break; - b = (int)simple_strtoul(p+1, &p, 10); - if (*p != ':') break; - d = (int)simple_strtoul(p+1, &p, 10); - if (*p != ':') break; - f = (int)simple_strtoul(p+1, &p, 10); - if (*p) break; - - domain = b >> 8; - b &= 0xff; - -#ifdef __alpha__ - /* - * Find the hose the device is on (the domain number is the - * hose index) and offset the bus by the root bus of that - * hose. - */ - for(pci_dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,NULL); - pci_dev; - pci_dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,pci_dev)) { - struct pci_controller *hose = pci_dev->sysdata; - - if (hose->index == domain) { - b += hose->bus->number; - break; - } - } -#endif + /* Return error if the busid submitted doesn't match the device's actual + * busid. + */ + ret = sscanf(dev->unique, "PCI:%d:%d:%d", &bus, &slot, &func); + if (ret != 3) + return DRM_ERR(EINVAL); + domain = bus >> 8; + bus &= 0xff; + + if ((domain != dev->pci_domain) || + (bus != dev->pci_bus) || + (slot != dev->pci_slot) || + (func != dev->pci_func)) + return -EINVAL; - pci_dev = pci_find_slot(b, PCI_DEVFN(d,f)); - if (pci_dev) { - dev->pdev = pci_dev; -#ifdef __alpha__ - dev->hose = pci_dev->sysdata; -#endif - } - } while(0); + return 0; +} + +static int +DRM(set_busid)(drm_device_t *dev) +{ + if (dev->unique != NULL) + return EBUSY; + + dev->unique_len = 20; + dev->unique = DRM(alloc)(dev->unique_len + 1, DRM_MEM_DRIVER); + if (dev->unique == NULL) + return ENOMEM; + + snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d", + dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func); return 0; } @@ -363,3 +291,47 @@ int DRM(getstats)( struct inode *inode, return -EFAULT; return 0; } + +#define DRM_IF_MAJOR 1 +#define DRM_IF_MINOR 2 + +int DRM(setversion)(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + drm_set_version_t sv; + drm_set_version_t retv; + int if_version; + + DRM_COPY_FROM_USER_IOCTL(sv, (drm_set_version_t *)data, sizeof(sv)); + + retv.drm_di_major = DRM_IF_MAJOR; + retv.drm_di_minor = DRM_IF_MINOR; + retv.drm_dd_major = DRIVER_MAJOR; + retv.drm_dd_minor = DRIVER_MINOR; + + DRM_COPY_TO_USER_IOCTL((drm_set_version_t *)data, retv, sizeof(sv)); + + if (sv.drm_di_major != -1) { + if (sv.drm_di_major != DRM_IF_MAJOR || + sv.drm_di_minor < 0 || sv.drm_di_minor > DRM_IF_MINOR) + return EINVAL; + if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_dd_minor); + dev->if_version = DRM_MAX(if_version, dev->if_version); + if (sv.drm_di_minor >= 1) { + /* + * Version 1.1 includes tying of DRM to specific device + */ + DRM(set_busid)(dev); + } + } + + if (sv.drm_dd_major != -1) { + if (sv.drm_dd_major != DRIVER_MAJOR || + sv.drm_dd_minor < 0 || sv.drm_dd_minor > DRIVER_MINOR) + return EINVAL; +#ifdef DRIVER_SETVERSION + DRIVER_SETVERSION(dev, &sv); +#endif + } + return 0; +} --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/drivers/char/drm/drm_irq.h 2004-05-10 01:19:02.411372472 -0700 @@ -0,0 +1,371 @@ +/** + * \file drm_irq.h + * IRQ support + * + * \author Rickard E. (Rik) Faith + * \author Gareth Hughes + */ + +/* + * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com + * + * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "drmP.h" + +#include /* For task queue support */ + +#ifndef __HAVE_SHARED_IRQ +#define __HAVE_SHARED_IRQ 0 +#endif + +#if __HAVE_SHARED_IRQ +#define DRM_IRQ_TYPE SA_SHIRQ +#else +#define DRM_IRQ_TYPE 0 +#endif + +/** + * Get interrupt from bus id. + * + * \param inode device inode. + * \param filp file pointer. + * \param cmd command. + * \param arg user argument, pointing to a drm_irq_busid structure. + * \return zero on success or a negative number on failure. + * + * Finds the PCI device with the specified bus id and gets its IRQ number. + * This IOCTL is deprecated, and will now return EINVAL for any busid not equal + * to that of the device that this DRM instance attached to. + */ +int DRM(irq_by_busid)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_irq_busid_t p; + + if (copy_from_user(&p, (drm_irq_busid_t *)arg, sizeof(p))) + return -EFAULT; + + if ((p.busnum >> 8) != dev->pci_domain || + (p.busnum & 0xff) != dev->pci_bus || + p.devnum != dev->pci_slot || + p.funcnum != dev->pci_func) + return -EINVAL; + + p.irq = dev->irq; + + DRM_DEBUG("%d:%d:%d => IRQ %d\n", + p.busnum, p.devnum, p.funcnum, p.irq); + if (copy_to_user((drm_irq_busid_t *)arg, &p, sizeof(p))) + return -EFAULT; + return 0; +} + +#if __HAVE_IRQ + +/** + * Install IRQ handler. + * + * \param dev DRM device. + * \param irq IRQ number. + * + * Initializes the IRQ related data, and setups drm_device::vbl_queue. Installs the handler, calling the driver + * \c DRM(driver_irq_preinstall)() and \c DRM(driver_irq_postinstall)() functions + * before and after the installation. + */ +int DRM(irq_install)( drm_device_t *dev ) +{ + int ret; + + if ( dev->irq == 0 ) + return -EINVAL; + + down( &dev->struct_sem ); + + /* Driver must have been initialized */ + if ( !dev->dev_private ) { + up( &dev->struct_sem ); + return -EINVAL; + } + + if ( dev->irq_enabled ) { + up( &dev->struct_sem ); + return -EBUSY; + } + dev->irq_enabled = 1; + up( &dev->struct_sem ); + + DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq ); + +#if __HAVE_DMA + dev->dma->next_buffer = NULL; + dev->dma->next_queue = NULL; + dev->dma->this_buffer = NULL; +#endif + +#if __HAVE_IRQ_BH + INIT_WORK(&dev->work, DRM(irq_immediate_bh), dev); +#endif + +#if __HAVE_VBL_IRQ + init_waitqueue_head(&dev->vbl_queue); + + spin_lock_init( &dev->vbl_lock ); + + INIT_LIST_HEAD( &dev->vbl_sigs.head ); + + dev->vbl_pending = 0; +#endif + + /* Before installing handler */ + DRM(driver_irq_preinstall)(dev); + + /* Install handler */ + ret = request_irq( dev->irq, DRM(irq_handler), + DRM_IRQ_TYPE, dev->devname, dev ); + if ( ret < 0 ) { + down( &dev->struct_sem ); + dev->irq_enabled = 0; + up( &dev->struct_sem ); + return ret; + } + + /* After installing handler */ + DRM(driver_irq_postinstall)(dev); + + return 0; +} + +/** + * Uninstall the IRQ handler. + * + * \param dev DRM device. + * + * Calls the driver's \c DRM(driver_irq_uninstall)() function, and stops the irq. + */ +int DRM(irq_uninstall)( drm_device_t *dev ) +{ + int irq_enabled; + + down( &dev->struct_sem ); + irq_enabled = dev->irq_enabled; + dev->irq_enabled = 0; + up( &dev->struct_sem ); + + if ( !irq_enabled ) + return -EINVAL; + + DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq ); + + DRM(driver_irq_uninstall)( dev ); + + free_irq( dev->irq, dev ); + + return 0; +} + +/** + * IRQ control ioctl. + * + * \param inode device inode. + * \param filp file pointer. + * \param cmd command. + * \param arg user argument, pointing to a drm_control structure. + * \return zero on success or a negative number on failure. + * + * Calls irq_install() or irq_uninstall() according to \p arg. + */ +int DRM(control)( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_control_t ctl; + + if ( copy_from_user( &ctl, (drm_control_t *)arg, sizeof(ctl) ) ) + return -EFAULT; + + switch ( ctl.func ) { + case DRM_INST_HANDLER: + if (dev->if_version < DRM_IF_VERSION(1, 2) && + ctl.irq != dev->irq) + return -EINVAL; + return DRM(irq_install)( dev ); + case DRM_UNINST_HANDLER: + return DRM(irq_uninstall)( dev ); + default: + return -EINVAL; + } +} + +#if __HAVE_VBL_IRQ + +/** + * Wait for VBLANK. + * + * \param inode device inode. + * \param filp file pointer. + * \param cmd command. + * \param data user argument, pointing to a drm_wait_vblank structure. + * \return zero on success or a negative number on failure. + * + * Verifies the IRQ is installed. + * + * If a signal is requested checks if this task has already scheduled the same signal + * for the same vblank sequence number - nothing to be done in + * that case. If the number of tasks waiting for the interrupt exceeds 100 the + * function fails. Otherwise adds a new entry to drm_device::vbl_sigs for this + * task. + * + * If a signal is not requested, then calls vblank_wait(). + */ +int DRM(wait_vblank)( DRM_IOCTL_ARGS ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_wait_vblank_t vblwait; + struct timeval now; + int ret = 0; + unsigned int flags; + + if (!dev->irq) + return -EINVAL; + + DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data, + sizeof(vblwait) ); + + switch ( vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK ) { + case _DRM_VBLANK_RELATIVE: + vblwait.request.sequence += atomic_read( &dev->vbl_received ); + vblwait.request.type &= ~_DRM_VBLANK_RELATIVE; + case _DRM_VBLANK_ABSOLUTE: + break; + default: + return -EINVAL; + } + + flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK; + + if ( flags & _DRM_VBLANK_SIGNAL ) { + unsigned long irqflags; + drm_vbl_sig_t *vbl_sig; + + vblwait.reply.sequence = atomic_read( &dev->vbl_received ); + + spin_lock_irqsave( &dev->vbl_lock, irqflags ); + + /* Check if this task has already scheduled the same signal + * for the same vblank sequence number; nothing to be done in + * that case + */ + list_for_each_entry( vbl_sig, &dev->vbl_sigs.head, head ) { + if (vbl_sig->sequence == vblwait.request.sequence + && vbl_sig->info.si_signo == vblwait.request.signal + && vbl_sig->task == current) + { + spin_unlock_irqrestore( &dev->vbl_lock, irqflags ); + goto done; + } + } + + if ( dev->vbl_pending >= 100 ) { + spin_unlock_irqrestore( &dev->vbl_lock, irqflags ); + return -EBUSY; + } + + dev->vbl_pending++; + + spin_unlock_irqrestore( &dev->vbl_lock, irqflags ); + + if ( !( vbl_sig = DRM_MALLOC( sizeof( drm_vbl_sig_t ) ) ) ) { + return -ENOMEM; + } + + memset( (void *)vbl_sig, 0, sizeof(*vbl_sig) ); + + vbl_sig->sequence = vblwait.request.sequence; + vbl_sig->info.si_signo = vblwait.request.signal; + vbl_sig->task = current; + + spin_lock_irqsave( &dev->vbl_lock, irqflags ); + + list_add_tail( (struct list_head *) vbl_sig, &dev->vbl_sigs.head ); + + spin_unlock_irqrestore( &dev->vbl_lock, irqflags ); + } else { + ret = DRM(vblank_wait)( dev, &vblwait.request.sequence ); + + do_gettimeofday( &now ); + vblwait.reply.tval_sec = now.tv_sec; + vblwait.reply.tval_usec = now.tv_usec; + } + +done: + DRM_COPY_TO_USER_IOCTL( (drm_wait_vblank_t *)data, vblwait, + sizeof(vblwait) ); + + return ret; +} + +/** + * Send the VBLANK signals. + * + * \param dev DRM device. + * + * Sends a signal for each task in drm_device::vbl_sigs and empties the list. + * + * If a signal is not requested, then calls vblank_wait(). + */ +void DRM(vbl_send_signals)( drm_device_t *dev ) +{ + struct list_head *list, *tmp; + drm_vbl_sig_t *vbl_sig; + unsigned int vbl_seq = atomic_read( &dev->vbl_received ); + unsigned long flags; + + spin_lock_irqsave( &dev->vbl_lock, flags ); + + list_for_each_safe( list, tmp, &dev->vbl_sigs.head ) { + vbl_sig = list_entry( list, drm_vbl_sig_t, head ); + if ( ( vbl_seq - vbl_sig->sequence ) <= (1<<23) ) { + vbl_sig->info.si_code = vbl_seq; + send_sig_info( vbl_sig->info.si_signo, &vbl_sig->info, vbl_sig->task ); + + list_del( list ); + + DRM_FREE( vbl_sig, sizeof(*vbl_sig) ); + + dev->vbl_pending--; + } + } + + spin_unlock_irqrestore( &dev->vbl_lock, flags ); +} + +#endif /* __HAVE_VBL_IRQ */ + +#endif /* __HAVE_IRQ */ --- linux-2.6.6/drivers/char/drm/drm_memory_debug.h 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/char/drm/drm_memory_debug.h 2004-05-10 01:19:02.411372472 -0700 @@ -67,6 +67,7 @@ static drm_mem_stats_t DRM(mem_stats)[ [DRM_MEM_TOTALAGP] = { "totalagp" }, [DRM_MEM_BOUNDAGP] = { "boundagp" }, [DRM_MEM_CTXBITMAP] = { "ctxbitmap"}, + [DRM_MEM_CTXLIST] = { "ctxlist" }, [DRM_MEM_STUB] = { "stub" }, { NULL, 0, } /* Last entry must be null */ }; --- linux-2.6.6/drivers/char/drm/drm_os_linux.h 2003-09-27 18:57:44.000000000 -0700 +++ 25/drivers/char/drm/drm_os_linux.h 2004-05-10 01:19:02.411372472 -0700 @@ -62,8 +62,12 @@ verify_area( VERIFY_READ, uaddr, size ) #define DRM_COPY_FROM_USER_UNCHECKED(arg1, arg2, arg3) \ __copy_from_user(arg1, arg2, arg3) +#define DRM_COPY_TO_USER_UNCHECKED(arg1, arg2, arg3) \ + __copy_to_user(arg1, arg2, arg3) #define DRM_GET_USER_UNCHECKED(val, uaddr) \ __get_user(val, uaddr) +#define DRM_PUT_USER_UNCHECKED(uaddr, val) \ + __put_user(val, uaddr) /** 'malloc' without the overhead of DRM(alloc)() */ @@ -71,6 +75,8 @@ /** 'free' without the overhead of DRM(free)() */ #define DRM_FREE(x,size) kfree(x) +#define DRM_GET_PRIV_WITH_RETURN(_priv, _filp) _priv = _filp->private_data + /** * Get the pointer to the SAREA. * --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/drivers/char/drm/drm_pciids.h 2004-05-10 01:19:02.413372168 -0700 @@ -0,0 +1,203 @@ +/* + This file is auto-generated from the drm_pciids.txt in the DRM CVS + Please contact dri-devel@lists.sf.net to add new cards to this list +*/ +#define radeon_PCI_IDS \ + {0x1002, 0x4136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4336, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4337, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4966, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4967, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4C57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4C58, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4C59, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4C5A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4C65, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5148, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x514A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x514B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x514C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x514D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x514E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x514F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5158, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5159, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x515A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5168, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5169, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x516A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x516B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x516C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5836, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5837, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5960, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5961, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5962, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5963, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5968, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x596A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x596B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5c62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5c64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0, 0, 0} + +#define r128_PCI_IDS \ + {0x1002, 0x4c45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4c46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4d46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4d4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5041, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5042, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5043, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5044, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5045, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5046, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5047, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5048, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5049, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x504A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x504B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x504C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x504D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x504E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x504F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5052, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5054, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5056, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5245, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5246, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5247, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x524b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x524c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x534d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5446, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x544C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x5452, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0, 0, 0} + +#define mga_PCI_IDS \ + {0x102b, 0x0521, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x102b, 0x0525, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x102b, 0x2527, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0, 0, 0} + +#define mach64_PCI_IDS \ + {0x1002, 0x4749, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4750, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4751, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4742, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4744, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4c49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4c50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4c51, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4c42, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4c44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x474c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x474f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4752, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4753, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x474d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x474e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4c52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4c53, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4c4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1002, 0x4c4e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0, 0, 0} + +#define sisdrv_PCI_IDS \ + {0x1039, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1039, 0x5300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1039, 0x6300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1039, 0x7300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0, 0, 0} + +#define tdfx_PCI_IDS \ + {0x121a, 0x0003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x121a, 0x0004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x121a, 0x0005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x121a, 0x0007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x121a, 0x0009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x121a, 0x000b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0, 0, 0} + +#define viadrv_PCI_IDS \ + {0x1106, 0x3022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x1106, 0x7204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0, 0, 0} + +#define i810_PCI_IDS \ + {0x8086, 0x7121, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x8086, 0x7123, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x8086, 0x7125, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x8086, 0x1132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0, 0, 0} + +#define i830_PCI_IDS \ + {0x8086, 0x3577, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x8086, 0x2562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x8086, 0x3582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0, 0, 0} + +#define gamma_PCI_IDS \ + {0x3d3d, 0x0008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0, 0, 0} + +#define savage_PCI_IDS \ + {0x5333, 0x8a22, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x5333, 0x8a23, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x5333, 0x8c10, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x5333, 0x8c11, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x5333, 0x8c12, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x5333, 0x8c13, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x5333, 0x8c20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x5333, 0x8c21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x5333, 0x8c22, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x5333, 0x8c24, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x5333, 0x8c26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x5333, 0x8c2a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x5333, 0x8c2b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x5333, 0x8c2c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x5333, 0x8c2d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x5333, 0x8c2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x5333, 0x8c2f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x5333, 0x8a25, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x5333, 0x8a26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x5333, 0x8d01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x5333, 0x8d02, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x5333, 0x8d04, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0, 0, 0} + +#define ffb_PCI_IDS \ + {0, 0, 0} + --- linux-2.6.6/drivers/char/drm/drmP.h 2004-01-09 00:04:31.000000000 -0800 +++ 25/drivers/char/drm/drmP.h 2004-05-10 01:19:02.401373992 -0700 @@ -92,8 +92,8 @@ #ifndef __HAVE_DMA #define __HAVE_DMA 0 #endif -#ifndef __HAVE_DMA_IRQ -#define __HAVE_DMA_IRQ 0 +#ifndef __HAVE_IRQ +#define __HAVE_IRQ 0 #endif #ifndef __HAVE_DMA_WAITLIST #define __HAVE_DMA_WAITLIST 0 @@ -148,6 +148,7 @@ #define DRM_MEM_CTXBITMAP 18 #define DRM_MEM_STUB 19 #define DRM_MEM_SGLISTS 20 +#define DRM_MEM_CTXLIST 21 #define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8) @@ -324,6 +325,7 @@ do { \ #define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x)) #define DRM_WAITCOUNT(dev,idx) DRM_BUFCOUNT(&dev->queuelist[idx]->waitlist) +#define DRM_IF_VERSION(maj, min) (maj << 16 | min) /** * Get the private SAREA mapping. * @@ -362,11 +364,6 @@ do { \ typedef int drm_ioctl_t( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); -typedef struct drm_pci_list { - u16 vendor; - u16 device; -} drm_pci_list_t; - typedef struct drm_ioctl_desc { drm_ioctl_t *func; int auth_needed; @@ -463,18 +460,6 @@ typedef struct drm_buf_entry { drm_freelist_t freelist; } drm_buf_entry_t; -/** - * Hardware lock. - * - * The lock structure is a simple cache-line aligned integer. To avoid - * processor bus contention on a multiprocessor system, there should not be any - * other data stored in the same cache line. - */ -typedef struct drm_hw_lock { - __volatile__ unsigned int lock; /**< lock variable */ - char padding[60]; /**< Pad to cache line */ -} drm_hw_lock_t; - /** File private data */ typedef struct drm_file { int authenticated; @@ -488,6 +473,9 @@ typedef struct drm_file { struct drm_device *dev; int remove_auth_on_close; unsigned long lock_count; +#ifdef DRIVER_FILE_FIELDS + DRIVER_FILE_FIELDS; +#endif } drm_file_t; /** Wait queue */ @@ -602,6 +590,15 @@ typedef struct drm_map_list { typedef drm_map_t drm_local_map_t; +/** + * Context handle list + */ +typedef struct drm_ctx_list { + struct list_head head; /**< list head */ + drm_context_t handle; /**< context handle */ + drm_file_t *tag; /**< associated fd private data */ +} drm_ctx_list_t; + #if __HAVE_VBL_IRQ typedef struct drm_vbl_sig { @@ -622,6 +619,8 @@ typedef struct drm_device { int unique_len; /**< Length of unique field */ dev_t device; /**< Device number for mknod */ char *devname; /**< For /proc/interrupts */ + int minor; /**< Minor device number */ + int if_version; /**< Highest interface version set */ int blocked; /**< Blocked due to VC switch? */ struct proc_dir_entry *root; /**< Root for this device's entries */ @@ -660,6 +659,12 @@ typedef struct drm_device { drm_map_list_t *maplist; /**< Linked list of regions */ int map_count; /**< Number of mappable regions */ + /** \name Context handle management */ + /*@{*/ + drm_ctx_list_t *ctxlist; /**< Linked list of context handles */ + int ctx_count; /**< Number of context handles */ + struct semaphore ctxlist_sem; /**< For ctxlist */ + drm_map_t **context_sareas; /**< per-context SAREA's */ int max_context; @@ -679,6 +684,7 @@ typedef struct drm_device { /** \name Context support */ /*@{*/ int irq; /**< Interrupt used by board */ + int irq_enabled; /**< True if irq handler is enabled */ __volatile__ long context_flag; /**< Context swapping flag */ __volatile__ long interrupt_flag; /**< Interruption handler flag */ __volatile__ long dma_flag; /**< DMA dispatch flag */ @@ -714,7 +720,12 @@ typedef struct drm_device { #if __REALLY_HAVE_AGP drm_agp_head_t *agp; /**< AGP data */ #endif - struct pci_dev *pdev; /**< PCI device structure */ + + struct pci_dev *pdev; /**< PCI device structure */ + int pci_domain; /**< PCI bus domain number */ + int pci_bus; /**< PCI bus number */ + int pci_slot; /**< PCI slot number */ + int pci_func; /**< PCI function number */ #ifdef __alpha__ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3) struct pci_controler *hose; @@ -758,18 +769,6 @@ extern int DRM(flush)(struct file * extern int DRM(fasync)(int fd, struct file *filp, int on); /* Mapping support (drm_vm.h) */ -extern struct page *DRM(vm_nopage)(struct vm_area_struct *vma, - unsigned long address, - int *type); -extern struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma, - unsigned long address, - int *type); -extern struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma, - unsigned long address, - int *type); -extern struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma, - unsigned long address, - int *type); extern void DRM(vm_open)(struct vm_area_struct *vma); extern void DRM(vm_close)(struct vm_area_struct *vma); extern void DRM(vm_shm_close)(struct vm_area_struct *vma); @@ -804,8 +803,8 @@ extern int DRM(unbind_agp)(DRM #endif /* Misc. IOCTL support (drm_ioctl.h) */ -extern int DRM(irq_busid)(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +extern int DRM(irq_by_busid)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); extern int DRM(getunique)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); extern int DRM(setunique)(struct inode *inode, struct file *filp, @@ -816,6 +815,8 @@ extern int DRM(getclient)(struct in unsigned int cmd, unsigned long arg); extern int DRM(getstats)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +extern int DRM(setversion)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); /* Context IOCTL support (drm_context.h) */ extern int DRM(resctx)( struct inode *inode, struct file *filp, @@ -900,12 +901,17 @@ extern int DRM(dma_setup)(drm_devic extern void DRM(dma_takedown)(drm_device_t *dev); extern void DRM(free_buffer)(drm_device_t *dev, drm_buf_t *buf); extern void DRM(reclaim_buffers)( struct file *filp ); -#if __HAVE_DMA_IRQ +#endif /* __HAVE_DMA */ + + /* IRQ support (drm_irq.h) */ +#if __HAVE_IRQ || __HAVE_DMA extern int DRM(control)( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); -extern int DRM(irq_install)( drm_device_t *dev, int irq ); +#endif +#if __HAVE_IRQ +extern int DRM(irq_install)( drm_device_t *dev ); extern int DRM(irq_uninstall)( drm_device_t *dev ); -extern irqreturn_t DRM(dma_service)( DRM_IRQ_ARGS ); +extern irqreturn_t DRM(irq_handler)( DRM_IRQ_ARGS ); extern void DRM(driver_irq_preinstall)( drm_device_t *dev ); extern void DRM(driver_irq_postinstall)( drm_device_t *dev ); extern void DRM(driver_irq_uninstall)( drm_device_t *dev ); @@ -915,12 +921,11 @@ extern int DRM(wait_vblank)(st extern int DRM(vblank_wait)(drm_device_t *dev, unsigned int *vbl_seq); extern void DRM(vbl_send_signals)( drm_device_t *dev ); #endif -#if __HAVE_DMA_IRQ_BH -extern void DRM(dma_immediate_bh)( void *dev ); +#if __HAVE_IRQ_BH +extern void DRM(irq_immediate_bh)( void *dev ); #endif #endif -#endif /* __HAVE_DMA */ #if __REALLY_HAVE_AGP /* AGP/GART support (drm_agpsupport.h) */ --- linux-2.6.6/drivers/char/drm/drm_sarea.h 2003-07-13 21:44:34.000000000 -0700 +++ 25/drivers/char/drm/drm_sarea.h 2004-05-10 01:19:02.413372168 -0700 @@ -32,9 +32,23 @@ #ifndef _DRM_SAREA_H_ #define _DRM_SAREA_H_ +#include "drm.h" + +/* SAREA area needs to be at least a page */ +#if defined(__alpha__) +#define SAREA_MAX 0x2000 +#elif defined(__ia64__) +#define SAREA_MAX 0x10000 /* 64kB */ +#else +/* Intel 830M driver needs at least 8k SAREA */ +#define SAREA_MAX 0x2000 +#endif + /** Maximum number of drawables in the SAREA */ #define SAREA_MAX_DRAWABLES 256 +#define SAREA_DRAWABLE_CLAIMED_ENTRY 0x80000000 + /** SAREA drawable */ typedef struct drm_sarea_drawable { unsigned int stamp; --- linux-2.6.6/drivers/char/drm/drm_stub.h 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/char/drm/drm_stub.h 2004-05-10 01:19:02.414372016 -0700 @@ -209,8 +209,8 @@ int DRM(stub_register)(const char *name, ret2 = DRM(stub_info).info_register(name, fops, dev); if (ret2) { if (!ret1) { - unregister_chrdev(DRM_MAJOR, "drm"); - class_simple_destroy(drm_class); + unregister_chrdev(DRM_MAJOR, "drm"); + class_simple_destroy(drm_class); } if (!i) inter_module_unregister("drm"); --- linux-2.6.6/drivers/char/drm/drm_vm.h 2004-01-09 00:04:31.000000000 -0800 +++ 25/drivers/char/drm/drm_vm.h 2004-05-10 01:19:02.415371864 -0700 @@ -35,48 +35,19 @@ #include "drmP.h" -/** AGP virtual memory operations */ -struct vm_operations_struct DRM(vm_ops) = { - .nopage = DRM(vm_nopage), - .open = DRM(vm_open), - .close = DRM(vm_close), -}; - -/** Shared virtual memory operations */ -struct vm_operations_struct DRM(vm_shm_ops) = { - .nopage = DRM(vm_shm_nopage), - .open = DRM(vm_open), - .close = DRM(vm_shm_close), -}; - -/** DMA virtual memory operations */ -struct vm_operations_struct DRM(vm_dma_ops) = { - .nopage = DRM(vm_dma_nopage), - .open = DRM(vm_open), - .close = DRM(vm_close), -}; - -/** Scatter-gather virtual memory operations */ -struct vm_operations_struct DRM(vm_sg_ops) = { - .nopage = DRM(vm_sg_nopage), - .open = DRM(vm_open), - .close = DRM(vm_close), -}; /** * \c nopage method for AGP virtual memory. * * \param vma virtual memory area. * \param address access address. - * \param write_access sharing. * \return pointer to the page structure. * * Find the right map and if it's AGP memory find the real physical page to * map, get the page, increment the use count and return it. */ -struct page *DRM(vm_nopage)(struct vm_area_struct *vma, - unsigned long address, - int *type) +static __inline__ struct page *DRM(do_vm_nopage)(struct vm_area_struct *vma, + unsigned long address) { #if __REALLY_HAVE_AGP drm_file_t *priv = vma->vm_file->private_data; @@ -133,8 +104,6 @@ struct page *DRM(vm_nopage)(struct vm_ar baddr, __va(agpmem->memory->memory[offset]), offset, atomic_read(&page->count)); - if (type) - *type = VM_FAULT_MINOR; return page; } vm_nopage_error: @@ -148,15 +117,13 @@ vm_nopage_error: * * \param vma virtual memory area. * \param address access address. - * \param write_access sharing. * \return pointer to the page structure. * * Get the the mapping, find the real physical page to map, get the page, and * return it. */ -struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma, - unsigned long address, - int *type) +static __inline__ struct page *DRM(do_vm_shm_nopage)(struct vm_area_struct *vma, + unsigned long address) { drm_map_t *map = (drm_map_t *)vma->vm_private_data; unsigned long offset; @@ -172,8 +139,6 @@ struct page *DRM(vm_shm_nopage)(struct v if (!page) return NOPAGE_OOM; get_page(page); - if (type) - *type = VM_FAULT_MINOR; DRM_DEBUG("shm_nopage 0x%lx\n", address); return page; @@ -265,14 +230,12 @@ void DRM(vm_shm_close)(struct vm_area_st * * \param vma virtual memory area. * \param address access address. - * \param write_access sharing. * \return pointer to the page structure. * * Determine the page number from the page offset and get it from drm_device_dma::pagelist. */ -struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma, - unsigned long address, - int *type) +static __inline__ struct page *DRM(do_vm_dma_nopage)(struct vm_area_struct *vma, + unsigned long address) { drm_file_t *priv = vma->vm_file->private_data; drm_device_t *dev = priv->dev; @@ -291,8 +254,6 @@ struct page *DRM(vm_dma_nopage)(struct v (offset & (~PAGE_MASK)))); get_page(page); - if (type) - *type = VM_FAULT_MINOR; DRM_DEBUG("dma_nopage 0x%lx (page %lu)\n", address, page_nr); return page; @@ -303,14 +264,12 @@ struct page *DRM(vm_dma_nopage)(struct v * * \param vma virtual memory area. * \param address access address. - * \param write_access sharing. * \return pointer to the page structure. * * Determine the map offset from the page offset and get it from drm_sg_mem::pagelist. */ -struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma, - unsigned long address, - int *type) +static __inline__ struct page *DRM(do_vm_sg_nopage)(struct vm_area_struct *vma, + unsigned long address) { drm_map_t *map = (drm_map_t *)vma->vm_private_data; drm_file_t *priv = vma->vm_file->private_data; @@ -331,12 +290,99 @@ struct page *DRM(vm_sg_nopage)(struct vm page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT); page = entry->pagelist[page_offset]; get_page(page); - if (type) - *type = VM_FAULT_MINOR; return page; } + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + +static struct page *DRM(vm_nopage)(struct vm_area_struct *vma, + unsigned long address, + int *type) { + if (type) *type = VM_FAULT_MINOR; + return DRM(do_vm_nopage)(vma, address); +} + +static struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma, + unsigned long address, + int *type) { + if (type) *type = VM_FAULT_MINOR; + return DRM(do_vm_shm_nopage)(vma, address); +} + +static struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma, + unsigned long address, + int *type) { + if (type) *type = VM_FAULT_MINOR; + return DRM(do_vm_dma_nopage)(vma, address); +} + +static struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma, + unsigned long address, + int *type) { + if (type) *type = VM_FAULT_MINOR; + return DRM(do_vm_sg_nopage)(vma, address); +} + +#else /* LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,0) */ + +static struct page *DRM(vm_nopage)(struct vm_area_struct *vma, + unsigned long address, + int unused) { + return DRM(do_vm_nopage)(vma, address); +} + +static struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma, + unsigned long address, + int unused) { + return DRM(do_vm_shm_nopage)(vma, address); +} + +static struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma, + unsigned long address, + int unused) { + return DRM(do_vm_dma_nopage)(vma, address); +} + +static struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma, + unsigned long address, + int unused) { + return DRM(do_vm_sg_nopage)(vma, address); +} + +#endif + + +/** AGP virtual memory operations */ +static struct vm_operations_struct DRM(vm_ops) = { + .nopage = DRM(vm_nopage), + .open = DRM(vm_open), + .close = DRM(vm_close), +}; + +/** Shared virtual memory operations */ +static struct vm_operations_struct DRM(vm_shm_ops) = { + .nopage = DRM(vm_shm_nopage), + .open = DRM(vm_open), + .close = DRM(vm_shm_close), +}; + +/** DMA virtual memory operations */ +static struct vm_operations_struct DRM(vm_dma_ops) = { + .nopage = DRM(vm_dma_nopage), + .open = DRM(vm_open), + .close = DRM(vm_close), +}; + +/** Scatter-gather virtual memory operations */ +static struct vm_operations_struct DRM(vm_sg_ops) = { + .nopage = DRM(vm_sg_nopage), + .open = DRM(vm_open), + .close = DRM(vm_close), +}; + + /** * \c open method for shared virtual memory. * --- linux-2.6.6/drivers/char/drm/ffb.h 2003-06-14 12:18:23.000000000 -0700 +++ 25/drivers/char/drm/ffb.h 2004-05-10 01:19:02.416371712 -0700 @@ -13,3 +13,4 @@ #define __HAVE_KERNEL_CTX_SWITCH 1 #define __HAVE_RELEASE 1 #endif + --- linux-2.6.6/drivers/char/drm/gamma_dma.c 2003-09-27 18:57:44.000000000 -0700 +++ 25/drivers/char/drm/gamma_dma.c 2004-05-10 01:19:02.417371560 -0700 @@ -116,7 +116,7 @@ static inline int gamma_dma_is_ready(drm return (!GAMMA_READ(GAMMA_DMACOUNT)); } -irqreturn_t gamma_dma_service( DRM_IRQ_ARGS ) +irqreturn_t gamma_irq_handler( DRM_IRQ_ARGS ) { drm_device_t *dev = (drm_device_t *)arg; drm_device_dma_t *dma = dev->dma; @@ -262,7 +262,7 @@ static void gamma_dma_timer_bh(unsigned gamma_dma_schedule((drm_device_t *)dev, 0); } -void gamma_dma_immediate_bh(void *dev) +void gamma_irq_immediate_bh(void *dev) { gamma_dma_schedule(dev, 0); } @@ -656,12 +656,12 @@ int gamma_do_cleanup_dma( drm_device_t * { DRM_DEBUG( "%s\n", __FUNCTION__ ); -#if _HAVE_DMA_IRQ +#if __HAVE_IRQ /* Make sure interrupts are disabled here because the uninstall ioctl * may not have been called from userspace and after dev_private * is freed, it's too late. */ - if ( dev->irq ) DRM(irq_uninstall)(dev); + if ( dev->irq_enabled ) DRM(irq_uninstall)(dev); #endif if ( dev->dev_private ) { --- linux-2.6.6/drivers/char/drm/gamma_drv.c 2003-06-14 12:18:33.000000000 -0700 +++ 25/drivers/char/drm/gamma_drv.c 2004-05-10 01:19:02.417371560 -0700 @@ -48,6 +48,7 @@ #include "drm_fops.h" #include "drm_init.h" #include "drm_ioctl.h" +#include "drm_irq.h" #include "gamma_lists.h" /* NOTE */ #include "drm_lock.h" #include "gamma_lock.h" /* NOTE */ --- linux-2.6.6/drivers/char/drm/gamma.h 2003-06-14 12:17:55.000000000 -0700 +++ 25/drivers/char/drm/gamma.h 2004-05-10 01:19:02.416371712 -0700 @@ -104,8 +104,8 @@ return 0; \ } while (0) -#define __HAVE_DMA_IRQ 1 -#define __HAVE_DMA_IRQ_BH 1 +#define __HAVE_IRQ 1 +#define __HAVE_IRQ_BH 1 #define DRIVER_AGP_BUFFERS_MAP( dev ) \ ((drm_gamma_private_t *)((dev)->dev_private))->buffers --- linux-2.6.6/drivers/char/drm/i810_dma.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/char/drm/i810_dma.c 2004-05-10 01:19:02.418371408 -0700 @@ -232,12 +232,12 @@ int i810_dma_cleanup(drm_device_t *dev) { drm_device_dma_t *dma = dev->dma; -#if _HAVE_DMA_IRQ +#if __HAVE_IRQ /* Make sure interrupts are disabled here because the uninstall ioctl * may not have been called from userspace and after dev_private * is freed, it's too late. */ - if (dev->irq) DRM(irq_uninstall)(dev); + if ( dev->irq_enabled ) DRM(irq_uninstall)(dev); #endif if (dev->dev_private) { --- linux-2.6.6/drivers/char/drm/i810.h 2003-08-22 19:23:40.000000000 -0700 +++ 25/drivers/char/drm/i810.h 2004-05-10 01:19:02.417371560 -0700 @@ -77,7 +77,6 @@ [DRM_IOCTL_NR(DRM_IOCTL_I810_MC)] = { i810_dma_mc, 1, 1 }, \ [DRM_IOCTL_NR(DRM_IOCTL_I810_RSTATUS)] = { i810_rstatus, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_I810_FLIP)] = { i810_flip_bufs, 1, 0 } - #define __HAVE_COUNTERS 4 #define __HAVE_COUNTER6 _DRM_STAT_IRQ @@ -112,7 +111,7 @@ * a noop stub is generated for compatibility. */ /* XXX: Add vblank support? */ -#define __HAVE_DMA_IRQ 0 +#define __HAVE_IRQ 0 /* Buffer customization: */ --- linux-2.6.6/drivers/char/drm/i830_dma.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/char/drm/i830_dma.c 2004-05-10 01:19:02.420371104 -0700 @@ -232,12 +232,12 @@ int i830_dma_cleanup(drm_device_t *dev) { drm_device_dma_t *dma = dev->dma; -#if _HAVE_DMA_IRQ +#if __HAVE_IRQ /* Make sure interrupts are disabled here because the uninstall ioctl * may not have been called from userspace and after dev_private * is freed, it's too late. */ - if (dev->irq) DRM(irq_uninstall)(dev); + if ( dev->irq_enabled ) DRM(irq_uninstall)(dev); #endif if (dev->dev_private) { @@ -1540,7 +1540,7 @@ int i830_getparam( struct inode *inode, switch( param.param ) { case I830_PARAM_IRQ_ACTIVE: - value = dev->irq ? 1 : 0; + value = dev->irq_enabled; break; default: return -EINVAL; --- linux-2.6.6/drivers/char/drm/i830_drv.c 2003-06-14 12:18:06.000000000 -0700 +++ 25/drivers/char/drm/i830_drv.c 2004-05-10 01:19:02.420371104 -0700 @@ -50,6 +50,7 @@ #include "drm_fops.h" #include "drm_init.h" #include "drm_ioctl.h" +#include "drm_irq.h" #include "drm_lock.h" #include "drm_memory.h" #include "drm_proc.h" --- linux-2.6.6/drivers/char/drm/i830.h 2003-06-14 12:18:06.000000000 -0700 +++ 25/drivers/char/drm/i830.h 2004-05-10 01:19:02.419371256 -0700 @@ -115,10 +115,10 @@ #define USE_IRQS 0 #if USE_IRQS -#define __HAVE_DMA_IRQ 1 +#define __HAVE_IRQ 1 #define __HAVE_SHARED_IRQ 1 #else -#define __HAVE_DMA_IRQ 0 +#define __HAVE_IRQ 0 #endif --- linux-2.6.6/drivers/char/drm/i830_irq.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/char/drm/i830_irq.c 2004-05-10 01:19:02.421370952 -0700 @@ -35,7 +35,7 @@ #include -irqreturn_t DRM(dma_service)( DRM_IRQ_ARGS ) +irqreturn_t DRM(irq_handler)( DRM_IRQ_ARGS ) { drm_device_t *dev = (drm_device_t *)arg; drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private; --- linux-2.6.6/drivers/char/drm/mga_dma.c 2003-06-14 12:18:32.000000000 -0700 +++ 25/drivers/char/drm/mga_dma.c 2004-05-10 01:19:02.422370800 -0700 @@ -500,14 +500,6 @@ static int mga_do_init_dma( drm_device_t return DRM_ERR(EINVAL); } - DRM_FIND_MAP( dev_priv->fb, init->fb_offset ); - if(!dev_priv->fb) { - DRM_ERROR( "failed to find framebuffer!\n" ); - /* Assign dev_private so we can do cleanup. */ - dev->dev_private = (void *)dev_priv; - mga_do_cleanup_dma( dev ); - return DRM_ERR(EINVAL); - } DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset ); if(!dev_priv->mmio) { DRM_ERROR( "failed to find mmio region!\n" ); @@ -639,12 +631,12 @@ int mga_do_cleanup_dma( drm_device_t *de { DRM_DEBUG( "\n" ); -#if _HAVE_DMA_IRQ +#if __HAVE_IRQ /* Make sure interrupts are disabled here because the uninstall ioctl * may not have been called from userspace and after dev_private * is freed, it's too late. */ - if ( dev->irq ) DRM(irq_uninstall)(dev); + if ( dev->irq_enabled ) DRM(irq_uninstall)(dev); #endif if ( dev->dev_private ) { --- linux-2.6.6/drivers/char/drm/mga_drm.h 2003-06-14 12:18:28.000000000 -0700 +++ 25/drivers/char/drm/mga_drm.h 2004-05-10 01:19:02.423370648 -0700 @@ -117,6 +117,8 @@ #define MGA_NR_TEX_REGIONS 16 #define MGA_LOG_MIN_TEX_REGION_SIZE 16 +#define DRM_MGA_IDLE_RETRY 2048 + #endif /* __MGA_SAREA_DEFINES__ */ @@ -230,16 +232,27 @@ typedef struct _drm_mga_sarea { /* MGA specific ioctls * The device specific ioctl range is 0x40 to 0x79. */ -#define DRM_IOCTL_MGA_INIT DRM_IOW( 0x40, drm_mga_init_t) -#define DRM_IOCTL_MGA_FLUSH DRM_IOW( 0x41, drm_lock_t) -#define DRM_IOCTL_MGA_RESET DRM_IO( 0x42) -#define DRM_IOCTL_MGA_SWAP DRM_IO( 0x43) -#define DRM_IOCTL_MGA_CLEAR DRM_IOW( 0x44, drm_mga_clear_t) -#define DRM_IOCTL_MGA_VERTEX DRM_IOW( 0x45, drm_mga_vertex_t) -#define DRM_IOCTL_MGA_INDICES DRM_IOW( 0x46, drm_mga_indices_t) -#define DRM_IOCTL_MGA_ILOAD DRM_IOW( 0x47, drm_mga_iload_t) -#define DRM_IOCTL_MGA_BLIT DRM_IOW( 0x48, drm_mga_blit_t) -#define DRM_IOCTL_MGA_GETPARAM DRM_IOWR(0x49, drm_mga_getparam_t) +#define DRM_MGA_INIT 0x00 +#define DRM_MGA_FLUSH 0x01 +#define DRM_MGA_RESET 0x02 +#define DRM_MGA_SWAP 0x03 +#define DRM_MGA_CLEAR 0x04 +#define DRM_MGA_VERTEX 0x05 +#define DRM_MGA_INDICES 0x06 +#define DRM_MGA_ILOAD 0x07 +#define DRM_MGA_BLIT 0x08 +#define DRM_MGA_GETPARAM 0x09 + +#define DRM_IOCTL_MGA_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INIT, drm_mga_init_t) +#define DRM_IOCTL_MGA_FLUSH DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, drm_lock_t) +#define DRM_IOCTL_MGA_RESET DRM_IO( DRM_COMMAND_BASE + DRM_MGA_RESET) +#define DRM_IOCTL_MGA_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_MGA_SWAP) +#define DRM_IOCTL_MGA_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_CLEAR, drm_mga_clear_t) +#define DRM_IOCTL_MGA_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_VERTEX, drm_mga_vertex_t) +#define DRM_IOCTL_MGA_INDICES DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INDICES, drm_mga_indices_t) +#define DRM_IOCTL_MGA_ILOAD DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_ILOAD, drm_mga_iload_t) +#define DRM_IOCTL_MGA_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_BLIT, drm_mga_blit_t) +#define DRM_IOCTL_MGA_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_GETPARAM, drm_mga_getparam_t) typedef struct _drm_mga_warp_index { int installed; @@ -330,7 +343,7 @@ typedef struct _drm_mga_blit { typedef struct drm_mga_getparam { int param; - int *value; + void *value; } drm_mga_getparam_t; #endif --- linux-2.6.6/drivers/char/drm/mga_drv.c 2003-06-14 12:18:08.000000000 -0700 +++ 25/drivers/char/drm/mga_drv.c 2004-05-10 01:19:02.423370648 -0700 @@ -45,6 +45,7 @@ #include "drm_fops.h" #include "drm_init.h" #include "drm_ioctl.h" +#include "drm_irq.h" #include "drm_lock.h" #include "drm_memory.h" #include "drm_proc.h" --- linux-2.6.6/drivers/char/drm/mga_drv.h 2003-06-14 12:18:33.000000000 -0700 +++ 25/drivers/char/drm/mga_drv.h 2004-05-10 01:19:02.423370648 -0700 @@ -91,7 +91,6 @@ typedef struct drm_mga_private { unsigned int texture_size; drm_local_map_t *sarea; - drm_local_map_t *fb; drm_local_map_t *mmio; drm_local_map_t *status; drm_local_map_t *warp; --- linux-2.6.6/drivers/char/drm/mga.h 2003-06-14 12:17:55.000000000 -0700 +++ 25/drivers/char/drm/mga.h 2004-05-10 01:19:02.421370952 -0700 @@ -78,7 +78,7 @@ /* DMA customization: */ #define __HAVE_DMA 1 -#define __HAVE_DMA_IRQ 1 +#define __HAVE_IRQ 1 #define __HAVE_VBL_IRQ 1 #define __HAVE_SHARED_IRQ 1 --- linux-2.6.6/drivers/char/drm/mga_irq.c 2003-06-14 12:17:55.000000000 -0700 +++ 25/drivers/char/drm/mga_irq.c 2004-05-10 01:19:02.424370496 -0700 @@ -36,7 +36,7 @@ #include "mga_drm.h" #include "mga_drv.h" -irqreturn_t mga_dma_service( DRM_IRQ_ARGS ) +irqreturn_t mga_irq_handler( DRM_IRQ_ARGS ) { drm_device_t *dev = (drm_device_t *) arg; drm_mga_private_t *dev_priv = --- linux-2.6.6/drivers/char/drm/r128_cce.c 2003-09-27 18:57:44.000000000 -0700 +++ 25/drivers/char/drm/r128_cce.c 2004-05-10 01:19:02.425370344 -0700 @@ -212,7 +212,7 @@ int r128_do_cce_idle( drm_r128_private_t int i; for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { - if ( GET_RING_HEAD( &dev_priv->ring ) == dev_priv->ring.tail ) { + if ( GET_RING_HEAD( dev_priv ) == dev_priv->ring.tail ) { int pm4stat = R128_READ( R128_PM4_STAT ); if ( ( (pm4stat & R128_PM4_FIFOCNT_MASK) >= dev_priv->cce_fifo_size ) && @@ -238,7 +238,8 @@ static void r128_do_cce_start( drm_r128_ r128_do_wait_for_idle( dev_priv ); R128_WRITE( R128_PM4_BUFFER_CNTL, - dev_priv->cce_mode | dev_priv->ring.size_l2qw ); + dev_priv->cce_mode | dev_priv->ring.size_l2qw + | R128_PM4_BUFFER_CNTL_NOUPDATE ); R128_READ( R128_PM4_BUFFER_ADDR ); /* as per the sample code */ R128_WRITE( R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN ); @@ -253,7 +254,6 @@ static void r128_do_cce_reset( drm_r128_ { R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 ); R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 ); - SET_RING_HEAD( &dev_priv->ring, 0 ); dev_priv->ring.tail = 0; } @@ -264,7 +264,8 @@ static void r128_do_cce_reset( drm_r128_ static void r128_do_cce_stop( drm_r128_private_t *dev_priv ) { R128_WRITE( R128_PM4_MICRO_CNTL, 0 ); - R128_WRITE( R128_PM4_BUFFER_CNTL, R128_PM4_NONPM4 ); + R128_WRITE( R128_PM4_BUFFER_CNTL, + R128_PM4_NONPM4 | R128_PM4_BUFFER_CNTL_NOUPDATE ); dev_priv->cce_running = 0; } @@ -333,26 +334,6 @@ static void r128_cce_init_ring_buffer( d R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 ); R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 ); - /* DL_RPTR_ADDR is a physical address in AGP space. */ - SET_RING_HEAD( &dev_priv->ring, 0 ); - - if ( !dev_priv->is_pci ) { - R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR, - dev_priv->ring_rptr->offset ); - } else { - drm_sg_mem_t *entry = dev->sg; - unsigned long tmp_ofs, page_ofs; - - tmp_ofs = dev_priv->ring_rptr->offset - dev->sg->handle; - page_ofs = tmp_ofs >> PAGE_SHIFT; - - R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR, - entry->busaddr[page_ofs]); - DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n", - (unsigned long) entry->busaddr[page_ofs], - entry->handle + tmp_ofs ); - } - /* Set watermark control */ R128_WRITE( R128_PM4_BUFFER_WM_CNTL, ((R128_WATERMARK_L/4) << R128_WMA_SHIFT) @@ -486,13 +467,6 @@ static int r128_do_init_cce( drm_device_ return DRM_ERR(EINVAL); } - DRM_FIND_MAP( dev_priv->fb, init->fb_offset ); - if(!dev_priv->fb) { - DRM_ERROR("could not find framebuffer!\n"); - dev->dev_private = (void *)dev_priv; - r128_do_cleanup_cce( dev ); - return DRM_ERR(EINVAL); - } DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset ); if(!dev_priv->mmio) { DRM_ERROR("could not find mmio region!\n"); @@ -567,9 +541,6 @@ static int r128_do_init_cce( drm_device_ #endif dev_priv->cce_buffers_offset = dev->sg->handle; - dev_priv->ring.head = ((__volatile__ u32 *) - dev_priv->ring_rptr->handle); - dev_priv->ring.start = (u32 *)dev_priv->cce_ring->handle; dev_priv->ring.end = ((u32 *)dev_priv->cce_ring->handle + init->ring_size / sizeof(u32)); @@ -580,7 +551,6 @@ static int r128_do_init_cce( drm_device_ (dev_priv->ring.size / sizeof(u32)) - 1; dev_priv->ring.high_mark = 128; - dev_priv->ring.ring_rptr = dev_priv->ring_rptr; dev_priv->sarea_priv->last_frame = 0; R128_WRITE( R128_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame ); @@ -589,8 +559,9 @@ static int r128_do_init_cce( drm_device_ R128_WRITE( R128_LAST_DISPATCH_REG, dev_priv->sarea_priv->last_dispatch ); -#if __REALLY_HAVE_SG +#if __REALLY_HAVE_AGP if ( dev_priv->is_pci ) { +#endif if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart, &dev_priv->bus_pci_gart) ) { DRM_ERROR( "failed to init PCI GART!\n" ); @@ -599,6 +570,7 @@ static int r128_do_init_cce( drm_device_ return DRM_ERR(ENOMEM); } R128_WRITE( R128_PCI_GART_PAGE, dev_priv->bus_pci_gart ); +#if __REALLY_HAVE_AGP } #endif @@ -615,12 +587,12 @@ static int r128_do_init_cce( drm_device_ int r128_do_cleanup_cce( drm_device_t *dev ) { -#if _HAVE_DMA_IRQ +#if __HAVE_IRQ /* Make sure interrupts are disabled here because the uninstall ioctl * may not have been called from userspace and after dev_private * is freed, it's too late. */ - if ( dev->irq ) DRM(irq_uninstall)(dev); + if ( dev->irq_enabled ) DRM(irq_uninstall)(dev); #endif if ( dev->dev_private ) { @@ -901,7 +873,7 @@ int r128_wait_ring( drm_r128_private_t * int i; for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { - r128_update_ring_snapshot( ring ); + r128_update_ring_snapshot( dev_priv ); if ( ring->space >= n ) return 0; DRM_UDELAY( 1 ); --- linux-2.6.6/drivers/char/drm/r128_drm.h 2003-08-08 22:55:11.000000000 -0700 +++ 25/drivers/char/drm/r128_drm.h 2004-05-10 01:19:02.426370192 -0700 @@ -176,24 +176,47 @@ typedef struct drm_r128_sarea { /* Rage 128 specific ioctls * The device specific ioctl range is 0x40 to 0x79. */ -#define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t) -#define DRM_IOCTL_R128_CCE_START DRM_IO( 0x41) -#define DRM_IOCTL_R128_CCE_STOP DRM_IOW( 0x42, drm_r128_cce_stop_t) -#define DRM_IOCTL_R128_CCE_RESET DRM_IO( 0x43) -#define DRM_IOCTL_R128_CCE_IDLE DRM_IO( 0x44) -#define DRM_IOCTL_R128_RESET DRM_IO( 0x46) -#define DRM_IOCTL_R128_SWAP DRM_IO( 0x47) -#define DRM_IOCTL_R128_CLEAR DRM_IOW( 0x48, drm_r128_clear_t) -#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x49, drm_r128_vertex_t) -#define DRM_IOCTL_R128_INDICES DRM_IOW( 0x4a, drm_r128_indices_t) -#define DRM_IOCTL_R128_BLIT DRM_IOW( 0x4b, drm_r128_blit_t) -#define DRM_IOCTL_R128_DEPTH DRM_IOW( 0x4c, drm_r128_depth_t) -#define DRM_IOCTL_R128_STIPPLE DRM_IOW( 0x4d, drm_r128_stipple_t) -#define DRM_IOCTL_R128_INDIRECT DRM_IOWR(0x4f, drm_r128_indirect_t) -#define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( 0x50, drm_r128_fullscreen_t) -#define DRM_IOCTL_R128_CLEAR2 DRM_IOW( 0x51, drm_r128_clear2_t) -#define DRM_IOCTL_R128_GETPARAM DRM_IOW( 0x52, drm_r128_getparam_t) -#define DRM_IOCTL_R128_FLIP DRM_IO( 0x53) +#define DRM_R128_INIT 0x00 +#define DRM_R128_CCE_START 0x01 +#define DRM_R128_CCE_STOP 0x02 +#define DRM_R128_CCE_RESET 0x03 +#define DRM_R128_CCE_IDLE 0x04 +/* 0x05 not used */ +#define DRM_R128_RESET 0x06 +#define DRM_R128_SWAP 0x07 +#define DRM_R128_CLEAR 0x08 +#define DRM_R128_VERTEX 0x09 +#define DRM_R128_INDICES 0x0a +#define DRM_R128_BLIT 0x0b +#define DRM_R128_DEPTH 0x0c +#define DRM_R128_STIPPLE 0x0d +/* 0x0e not used */ +#define DRM_R128_INDIRECT 0x0f +#define DRM_R128_FULLSCREEN 0x10 +#define DRM_R128_CLEAR2 0x11 +#define DRM_R128_GETPARAM 0x12 +#define DRM_R128_FLIP 0x13 + +#define DRM_IOCTL_R128_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_R128_INIT, drm_r128_init_t) +#define DRM_IOCTL_R128_CCE_START DRM_IO( DRM_COMMAND_BASE + DRM_R128_CCE_START) +#define DRM_IOCTL_R128_CCE_STOP DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CCE_STOP, drm_r128_cce_stop_t) +#define DRM_IOCTL_R128_CCE_RESET DRM_IO( DRM_COMMAND_BASE + DRM_R128_CCE_RESET) +#define DRM_IOCTL_R128_CCE_IDLE DRM_IO( DRM_COMMAND_BASE + DRM_R128_CCE_IDLE) +/* 0x05 not used */ +#define DRM_IOCTL_R128_RESET DRM_IO( DRM_COMMAND_BASE + DRM_R128_RESET) +#define DRM_IOCTL_R128_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_R128_SWAP) +#define DRM_IOCTL_R128_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CLEAR, drm_r128_clear_t) +#define DRM_IOCTL_R128_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_R128_VERTEX, drm_r128_vertex_t) +#define DRM_IOCTL_R128_INDICES DRM_IOW( DRM_COMMAND_BASE + DRM_R128_INDICES, drm_r128_indices_t) +#define DRM_IOCTL_R128_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_R128_BLIT, drm_r128_blit_t) +#define DRM_IOCTL_R128_DEPTH DRM_IOW( DRM_COMMAND_BASE + DRM_R128_DEPTH, drm_r128_depth_t) +#define DRM_IOCTL_R128_STIPPLE DRM_IOW( DRM_COMMAND_BASE + DRM_R128_STIPPLE, drm_r128_stipple_t) +/* 0x0e not used */ +#define DRM_IOCTL_R128_INDIRECT DRM_IOWR(DRM_COMMAND_BASE + DRM_R128_INDIRECT, drm_r128_indirect_t) +#define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( DRM_COMMAND_BASE + DRM_R128_FULLSCREEN, drm_r128_fullscreen_t) +#define DRM_IOCTL_R128_CLEAR2 DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CLEAR2, drm_r128_clear2_t) +#define DRM_IOCTL_R128_GETPARAM DRM_IOW( DRM_COMMAND_BASE + DRM_R128_GETPARAM, drm_r128_getparam_t) +#define DRM_IOCTL_R128_FLIP DRM_IO( DRM_COMMAND_BASE + DRM_R128_FLIP) typedef struct drm_r128_init { enum { @@ -316,7 +339,7 @@ typedef struct drm_r128_fullscreen { typedef struct drm_r128_getparam { int param; - int *value; + void *value; } drm_r128_getparam_t; #endif --- linux-2.6.6/drivers/char/drm/r128_drv.c 2003-06-14 12:18:05.000000000 -0700 +++ 25/drivers/char/drm/r128_drv.c 2004-05-10 01:19:02.427370040 -0700 @@ -47,6 +47,7 @@ #include "drm_fops.h" #include "drm_init.h" #include "drm_ioctl.h" +#include "drm_irq.h" #include "drm_lock.h" #include "drm_memory.h" #include "drm_proc.h" --- linux-2.6.6/drivers/char/drm/r128_drv.h 2003-08-08 22:55:11.000000000 -0700 +++ 25/drivers/char/drm/r128_drv.h 2004-05-10 01:19:02.428369888 -0700 @@ -34,8 +34,7 @@ #ifndef __R128_DRV_H__ #define __R128_DRV_H__ -#define GET_RING_HEAD(ring) DRM_READ32( (ring)->ring_rptr, 0 ) /* (ring)->head */ -#define SET_RING_HEAD(ring,val) DRM_WRITE32( (ring)->ring_rptr, 0, (val) ) /* (ring)->head */ +#define GET_RING_HEAD(dev_priv) R128_READ( R128_PM4_BUFFER_DL_RPTR ) typedef struct drm_r128_freelist { unsigned int age; @@ -50,13 +49,11 @@ typedef struct drm_r128_ring_buffer { int size; int size_l2qw; - volatile u32 *head; u32 tail; u32 tail_mask; int space; int high_mark; - drm_local_map_t *ring_rptr; } drm_r128_ring_buffer_t; typedef struct drm_r128_private { @@ -100,7 +97,6 @@ typedef struct drm_r128_private { u32 span_pitch_offset_c; drm_local_map_t *sarea; - drm_local_map_t *fb; drm_local_map_t *mmio; drm_local_map_t *cce_ring; drm_local_map_t *ring_rptr; @@ -132,14 +128,6 @@ extern drm_buf_t *r128_freelist_get( drm extern int r128_wait_ring( drm_r128_private_t *dev_priv, int n ); -static __inline__ void -r128_update_ring_snapshot( drm_r128_ring_buffer_t *ring ) -{ - ring->space = (GET_RING_HEAD( ring ) - ring->tail) * sizeof(u32); - if ( ring->space <= 0 ) - ring->space += ring->size; -} - extern int r128_do_cce_idle( drm_r128_private_t *dev_priv ); extern int r128_do_cleanup_cce( drm_device_t *dev ); extern int r128_do_cleanup_pageflip( drm_device_t *dev ); @@ -279,6 +267,7 @@ extern int r128_cce_indirect( DRM_IOCTL_ # define R128_PM4_64PIO_64VCBM_64INDBM (7 << 28) # define R128_PM4_64BM_64VCBM_64INDBM (8 << 28) # define R128_PM4_64PIO_64VCPIO_64INDPIO (15 << 28) +# define R128_PM4_BUFFER_CNTL_NOUPDATE (1 << 27) #define R128_PM4_BUFFER_WM_CNTL 0x0708 # define R128_WMA_SHIFT 0 @@ -403,6 +392,15 @@ extern int R128_READ_PLL(drm_device_t *d (pkt) | ((n) << 16)) +static __inline__ void +r128_update_ring_snapshot( drm_r128_private_t *dev_priv ) +{ + drm_r128_ring_buffer_t *ring = &dev_priv->ring; + ring->space = (GET_RING_HEAD( dev_priv ) - ring->tail) * sizeof(u32); + if ( ring->space <= 0 ) + ring->space += ring->size; +} + /* ================================================================ * Misc helper macros */ @@ -412,7 +410,7 @@ do { \ drm_r128_ring_buffer_t *ring = &dev_priv->ring; int i; \ if ( ring->space < ring->high_mark ) { \ for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { \ - r128_update_ring_snapshot( ring ); \ + r128_update_ring_snapshot( dev_priv ); \ if ( ring->space >= ring->high_mark ) \ goto __ring_space_done; \ DRM_UDELAY(1); \ @@ -445,17 +443,10 @@ do { \ * Ring control */ -#if defined(__powerpc__) -#define r128_flush_write_combine() (void) GET_RING_HEAD( &dev_priv->ring ) -#else -#define r128_flush_write_combine() DRM_WRITEMEMORYBARRIER() -#endif - - #define R128_VERBOSE 0 #define RING_LOCALS \ - int write; unsigned int tail_mask; volatile u32 *ring; + int write, _nr; unsigned int tail_mask; volatile u32 *ring; #define BEGIN_RING( n ) do { \ if ( R128_VERBOSE ) { \ @@ -463,9 +454,10 @@ do { \ (n), __FUNCTION__ ); \ } \ if ( dev_priv->ring.space <= (n) * sizeof(u32) ) { \ + COMMIT_RING(); \ r128_wait_ring( dev_priv, (n) * sizeof(u32) ); \ } \ - dev_priv->ring.space -= (n) * sizeof(u32); \ + _nr = n; dev_priv->ring.space -= (n) * sizeof(u32); \ ring = dev_priv->ring.start; \ write = dev_priv->ring.tail; \ tail_mask = dev_priv->ring.tail_mask; \ @@ -488,9 +480,23 @@ do { \ dev_priv->ring.start, \ write * sizeof(u32) ); \ } \ - r128_flush_write_combine(); \ - dev_priv->ring.tail = write; \ - R128_WRITE( R128_PM4_BUFFER_DL_WPTR, write ); \ + if (((dev_priv->ring.tail + _nr) & tail_mask) != write) { \ + DRM_ERROR( \ + "ADVANCE_RING(): mismatch: nr: %x write: %x line: %d\n", \ + ((dev_priv->ring.tail + _nr) & tail_mask), \ + write, __LINE__); \ + } else \ + dev_priv->ring.tail = write; \ +} while (0) + +#define COMMIT_RING() do { \ + if ( R128_VERBOSE ) { \ + DRM_INFO( "COMMIT_RING() tail=0x%06x\n", \ + dev_priv->ring.tail ); \ + } \ + DRM_MEMORYBARRIER(); \ + R128_WRITE( R128_PM4_BUFFER_DL_WPTR, dev_priv->ring.tail ); \ + R128_READ( R128_PM4_BUFFER_DL_WPTR ); \ } while (0) #define OUT_RING( x ) do { \ --- linux-2.6.6/drivers/char/drm/r128.h 2003-08-22 19:23:40.000000000 -0700 +++ 25/drivers/char/drm/r128.h 2004-05-10 01:19:02.424370496 -0700 @@ -97,7 +97,7 @@ /* DMA customization: */ #define __HAVE_DMA 1 -#define __HAVE_DMA_IRQ 1 +#define __HAVE_IRQ 1 #define __HAVE_VBL_IRQ 1 #define __HAVE_SHARED_IRQ 1 --- linux-2.6.6/drivers/char/drm/r128_irq.c 2003-06-14 12:18:52.000000000 -0700 +++ 25/drivers/char/drm/r128_irq.c 2004-05-10 01:19:02.428369888 -0700 @@ -36,7 +36,7 @@ #include "r128_drm.h" #include "r128_drv.h" -irqreturn_t r128_dma_service( DRM_IRQ_ARGS ) +irqreturn_t r128_irq_handler( DRM_IRQ_ARGS ) { drm_device_t *dev = (drm_device_t *) arg; drm_r128_private_t *dev_priv = --- linux-2.6.6/drivers/char/drm/r128_state.c 2004-03-10 20:41:27.000000000 -0800 +++ 25/drivers/char/drm/r128_state.c 2004-05-10 01:19:02.430369584 -0700 @@ -45,7 +45,7 @@ static void r128_emit_clip_rects( drm_r1 RING_LOCALS; DRM_DEBUG( " %s\n", __FUNCTION__ ); - BEGIN_RING( 17 ); + BEGIN_RING( (count < 3? count: 3) * 5 + 2 ); if ( count >= 1 ) { OUT_RING( CCE_PACKET0( R128_AUX1_SC_LEFT, 3 ) ); @@ -1011,7 +1011,7 @@ static int r128_cce_dispatch_write_pixel DRM_DEBUG( "\n" ); count = depth->n; - if (count > 4096 || count <= 0) + if (count > 4096 || count <= 0) return -EMSGSIZE; xbuf_size = count * sizeof(*x); @@ -1280,6 +1280,7 @@ int r128_cce_clear( DRM_IOCTL_ARGS ) sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS; r128_cce_dispatch_clear( dev, &clear ); + COMMIT_RING(); /* Make sure we restore the 3D state next time. */ @@ -1315,8 +1316,10 @@ int r128_do_cleanup_pageflip( drm_device R128_WRITE( R128_CRTC_OFFSET, dev_priv->crtc_offset ); R128_WRITE( R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl ); - if (dev_priv->current_page != 0) + if (dev_priv->current_page != 0) { r128_cce_dispatch_flip( dev ); + COMMIT_RING(); + } dev_priv->page_flipping = 0; return 0; @@ -1341,6 +1344,7 @@ int r128_cce_flip( DRM_IOCTL_ARGS ) r128_cce_dispatch_flip( dev ); + COMMIT_RING(); return 0; } @@ -1362,6 +1366,7 @@ int r128_cce_swap( DRM_IOCTL_ARGS ) dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS); + COMMIT_RING(); return 0; } @@ -1421,6 +1426,7 @@ int r128_cce_vertex( DRM_IOCTL_ARGS ) r128_cce_dispatch_vertex( dev, buf ); + COMMIT_RING(); return 0; } @@ -1492,6 +1498,7 @@ int r128_cce_indices( DRM_IOCTL_ARGS ) r128_cce_dispatch_indices( dev, buf, elts.start, elts.end, count ); + COMMIT_RING(); return 0; } @@ -1501,6 +1508,7 @@ int r128_cce_blit( DRM_IOCTL_ARGS ) drm_device_dma_t *dma = dev->dma; drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_blit_t blit; + int ret; LOCK_TEST_WITH_RETURN( dev, filp ); @@ -1518,7 +1526,10 @@ int r128_cce_blit( DRM_IOCTL_ARGS ) RING_SPACE_TEST_WITH_RETURN( dev_priv ); VB_AGE_TEST_WITH_RETURN( dev_priv ); - return r128_cce_dispatch_blit( filp, dev, &blit ); + ret = r128_cce_dispatch_blit( filp, dev, &blit ); + + COMMIT_RING(); + return ret; } int r128_cce_depth( DRM_IOCTL_ARGS ) @@ -1526,6 +1537,7 @@ int r128_cce_depth( DRM_IOCTL_ARGS ) DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_depth_t depth; + int ret; LOCK_TEST_WITH_RETURN( dev, filp ); @@ -1534,18 +1546,20 @@ int r128_cce_depth( DRM_IOCTL_ARGS ) RING_SPACE_TEST_WITH_RETURN( dev_priv ); + ret = DRM_ERR(EINVAL); switch ( depth.func ) { case R128_WRITE_SPAN: - return r128_cce_dispatch_write_span( dev, &depth ); + ret = r128_cce_dispatch_write_span( dev, &depth ); case R128_WRITE_PIXELS: - return r128_cce_dispatch_write_pixels( dev, &depth ); + ret = r128_cce_dispatch_write_pixels( dev, &depth ); case R128_READ_SPAN: - return r128_cce_dispatch_read_span( dev, &depth ); + ret = r128_cce_dispatch_read_span( dev, &depth ); case R128_READ_PIXELS: - return r128_cce_dispatch_read_pixels( dev, &depth ); + ret = r128_cce_dispatch_read_pixels( dev, &depth ); } - return DRM_ERR(EINVAL); + COMMIT_RING(); + return ret; } int r128_cce_stipple( DRM_IOCTL_ARGS ) @@ -1568,6 +1582,7 @@ int r128_cce_stipple( DRM_IOCTL_ARGS ) r128_cce_dispatch_stipple( dev, mask ); + COMMIT_RING(); return 0; } @@ -1643,6 +1658,7 @@ int r128_cce_indirect( DRM_IOCTL_ARGS ) */ r128_cce_dispatch_indirect( dev, buf, indirect.start, indirect.end ); + COMMIT_RING(); return 0; } --- linux-2.6.6/drivers/char/drm/radeon_cp.c 2003-09-27 18:57:44.000000000 -0700 +++ 25/drivers/char/drm/radeon_cp.c 2004-05-10 01:19:02.432369280 -0700 @@ -855,7 +855,8 @@ static void radeon_cp_init_ring_buffer( /* Initialize the memory controller */ RADEON_WRITE( RADEON_MC_FB_LOCATION, - (dev_priv->gart_vm_start - 1) & 0xffff0000 ); + ( ( dev_priv->gart_vm_start - 1 ) & 0xffff0000 ) + | ( dev_priv->fb_location >> 16 ) ); #if __REALLY_HAVE_AGP if ( !dev_priv->is_pci ) { @@ -1071,13 +1072,6 @@ static int radeon_do_init_cp( drm_device dev_priv->depth_offset = init->depth_offset; dev_priv->depth_pitch = init->depth_pitch; - dev_priv->front_pitch_offset = (((dev_priv->front_pitch/64) << 22) | - (dev_priv->front_offset >> 10)); - dev_priv->back_pitch_offset = (((dev_priv->back_pitch/64) << 22) | - (dev_priv->back_offset >> 10)); - dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch/64) << 22) | - (dev_priv->depth_offset >> 10)); - /* Hardware state for depth clears. Remove this if/when we no * longer clear the depth buffer with a 3D rectangle. Hard-code * all values to prevent unwanted 3D state from slipping through @@ -1124,13 +1118,6 @@ static int radeon_do_init_cp( drm_device return DRM_ERR(EINVAL); } - DRM_FIND_MAP( dev_priv->fb, init->fb_offset ); - if(!dev_priv->fb) { - DRM_ERROR("could not find framebuffer!\n"); - dev->dev_private = (void *)dev_priv; - radeon_do_cleanup_cp(dev); - return DRM_ERR(EINVAL); - } DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset ); if(!dev_priv->mmio) { DRM_ERROR("could not find mmio region!\n"); @@ -1204,9 +1191,26 @@ static int radeon_do_init_cp( drm_device dev_priv->buffers->handle ); } + dev_priv->fb_location = ( RADEON_READ( RADEON_MC_FB_LOCATION ) + & 0xffff ) << 16; + + dev_priv->front_pitch_offset = (((dev_priv->front_pitch/64) << 22) | + ( ( dev_priv->front_offset + + dev_priv->fb_location ) >> 10 ) ); + + dev_priv->back_pitch_offset = (((dev_priv->back_pitch/64) << 22) | + ( ( dev_priv->back_offset + + dev_priv->fb_location ) >> 10 ) ); + + dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch/64) << 22) | + ( ( dev_priv->depth_offset + + dev_priv->fb_location ) >> 10 ) ); + dev_priv->gart_size = init->gart_size; - dev_priv->gart_vm_start = RADEON_READ( RADEON_CONFIG_APER_SIZE ); + dev_priv->gart_vm_start = dev_priv->fb_location + + RADEON_READ( RADEON_CONFIG_APER_SIZE ); + #if __REALLY_HAVE_AGP if ( !dev_priv->is_pci ) dev_priv->gart_buffers_offset = (dev_priv->buffers->offset @@ -1271,12 +1275,12 @@ int radeon_do_cleanup_cp( drm_device_t * { DRM_DEBUG( "\n" ); -#if _HAVE_DMA_IRQ +#if __HAVE_IRQ /* Make sure interrupts are disabled here because the uninstall ioctl * may not have been called from userspace and after dev_private * is freed, it's too late. */ - if ( dev->irq ) DRM(irq_uninstall)(dev); + if ( dev->irq_enabled ) DRM(irq_uninstall)(dev); #endif if ( dev->dev_private ) { --- linux-2.6.6/drivers/char/drm/radeon_drm.h 2003-09-27 18:57:44.000000000 -0700 +++ 25/drivers/char/drm/radeon_drm.h 2004-05-10 01:19:02.434368976 -0700 @@ -226,6 +226,13 @@ typedef union { #define RADEON_MAX_TEXTURE_LEVELS 12 #define RADEON_MAX_TEXTURE_UNITS 3 +/* Blits have strict offset rules. All blit offset must be aligned on + * a 1K-byte boundary. + */ +#define RADEON_OFFSET_SHIFT 10 +#define RADEON_OFFSET_ALIGN (1 << RADEON_OFFSET_SHIFT) +#define RADEON_OFFSET_MASK (RADEON_OFFSET_ALIGN - 1) + #endif /* __RADEON_SAREA_DEFINES__ */ typedef struct { @@ -365,31 +372,58 @@ typedef struct { /* Radeon specific ioctls * The device specific ioctl range is 0x40 to 0x79. */ -#define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( 0x40, drm_radeon_init_t) -#define DRM_IOCTL_RADEON_CP_START DRM_IO( 0x41) -#define DRM_IOCTL_RADEON_CP_STOP DRM_IOW( 0x42, drm_radeon_cp_stop_t) -#define DRM_IOCTL_RADEON_CP_RESET DRM_IO( 0x43) -#define DRM_IOCTL_RADEON_CP_IDLE DRM_IO( 0x44) -#define DRM_IOCTL_RADEON_RESET DRM_IO( 0x45) -#define DRM_IOCTL_RADEON_FULLSCREEN DRM_IOW( 0x46, drm_radeon_fullscreen_t) -#define DRM_IOCTL_RADEON_SWAP DRM_IO( 0x47) -#define DRM_IOCTL_RADEON_CLEAR DRM_IOW( 0x48, drm_radeon_clear_t) -#define DRM_IOCTL_RADEON_VERTEX DRM_IOW( 0x49, drm_radeon_vertex_t) -#define DRM_IOCTL_RADEON_INDICES DRM_IOW( 0x4a, drm_radeon_indices_t) -#define DRM_IOCTL_RADEON_STIPPLE DRM_IOW( 0x4c, drm_radeon_stipple_t) -#define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(0x4d, drm_radeon_indirect_t) -#define DRM_IOCTL_RADEON_TEXTURE DRM_IOWR(0x4e, drm_radeon_texture_t) -#define DRM_IOCTL_RADEON_VERTEX2 DRM_IOW( 0x4f, drm_radeon_vertex2_t) -#define DRM_IOCTL_RADEON_CMDBUF DRM_IOW( 0x50, drm_radeon_cmd_buffer_t) -#define DRM_IOCTL_RADEON_GETPARAM DRM_IOWR(0x51, drm_radeon_getparam_t) -#define DRM_IOCTL_RADEON_FLIP DRM_IO( 0x52) -#define DRM_IOCTL_RADEON_ALLOC DRM_IOWR( 0x53, drm_radeon_mem_alloc_t) -#define DRM_IOCTL_RADEON_FREE DRM_IOW( 0x54, drm_radeon_mem_free_t) -#define DRM_IOCTL_RADEON_INIT_HEAP DRM_IOW( 0x55, drm_radeon_mem_init_heap_t) -#define DRM_IOCTL_RADEON_IRQ_EMIT DRM_IOWR( 0x56, drm_radeon_irq_emit_t) -#define DRM_IOCTL_RADEON_IRQ_WAIT DRM_IOW( 0x57, drm_radeon_irq_wait_t) -/* added by Charl P. Botha - see radeon_cp.c for details */ -#define DRM_IOCTL_RADEON_CP_RESUME DRM_IO(0x58) +#define DRM_RADEON_CP_INIT 0x00 +#define DRM_RADEON_CP_START 0x01 +#define DRM_RADEON_CP_STOP 0x02 +#define DRM_RADEON_CP_RESET 0x03 +#define DRM_RADEON_CP_IDLE 0x04 +#define DRM_RADEON_RESET 0x05 +#define DRM_RADEON_FULLSCREEN 0x06 +#define DRM_RADEON_SWAP 0x07 +#define DRM_RADEON_CLEAR 0x08 +#define DRM_RADEON_VERTEX 0x09 +#define DRM_RADEON_INDICES 0x0A +#define DRM_RADEON_NOT_USED +#define DRM_RADEON_STIPPLE 0x0C +#define DRM_RADEON_INDIRECT 0x0D +#define DRM_RADEON_TEXTURE 0x0E +#define DRM_RADEON_VERTEX2 0x0F +#define DRM_RADEON_CMDBUF 0x10 +#define DRM_RADEON_GETPARAM 0x11 +#define DRM_RADEON_FLIP 0x12 +#define DRM_RADEON_ALLOC 0x13 +#define DRM_RADEON_FREE 0x14 +#define DRM_RADEON_INIT_HEAP 0x15 +#define DRM_RADEON_IRQ_EMIT 0x16 +#define DRM_RADEON_IRQ_WAIT 0x17 +#define DRM_RADEON_CP_RESUME 0x18 +#define DRM_RADEON_SETPARAM 0x19 + +#define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t) +#define DRM_IOCTL_RADEON_CP_START DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_START) +#define DRM_IOCTL_RADEON_CP_STOP DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_STOP, drm_radeon_cp_stop_t) +#define DRM_IOCTL_RADEON_CP_RESET DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_RESET) +#define DRM_IOCTL_RADEON_CP_IDLE DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_IDLE) +#define DRM_IOCTL_RADEON_RESET DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_RESET) +#define DRM_IOCTL_RADEON_FULLSCREEN DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_FULLSCREEN, drm_radeon_fullscreen_t) +#define DRM_IOCTL_RADEON_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_SWAP) +#define DRM_IOCTL_RADEON_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CLEAR, drm_radeon_clear_t) +#define DRM_IOCTL_RADEON_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_VERTEX, drm_radeon_vertex_t) +#define DRM_IOCTL_RADEON_INDICES DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_INDICES, drm_radeon_indices_t) +#define DRM_IOCTL_RADEON_STIPPLE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_STIPPLE, drm_radeon_stipple_t) +#define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_INDIRECT, drm_radeon_indirect_t) +#define DRM_IOCTL_RADEON_TEXTURE DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_TEXTURE, drm_radeon_texture_t) +#define DRM_IOCTL_RADEON_VERTEX2 DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_VERTEX2, drm_radeon_vertex2_t) +#define DRM_IOCTL_RADEON_CMDBUF DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CMDBUF, drm_radeon_cmd_buffer_t) +#define DRM_IOCTL_RADEON_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GETPARAM, drm_radeon_getparam_t) +#define DRM_IOCTL_RADEON_FLIP DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_FLIP) +#define DRM_IOCTL_RADEON_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_ALLOC, drm_radeon_mem_alloc_t) +#define DRM_IOCTL_RADEON_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_FREE, drm_radeon_mem_free_t) +#define DRM_IOCTL_RADEON_INIT_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_INIT_HEAP, drm_radeon_mem_init_heap_t) +#define DRM_IOCTL_RADEON_IRQ_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_IRQ_EMIT, drm_radeon_irq_emit_t) +#define DRM_IOCTL_RADEON_IRQ_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_IRQ_WAIT, drm_radeon_irq_wait_t) +#define DRM_IOCTL_RADEON_CP_RESUME DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_RESUME) +#define DRM_IOCTL_RADEON_SETPARAM DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SETPARAM, drm_radeon_setparam_t) typedef struct drm_radeon_init { enum { @@ -502,7 +536,7 @@ typedef struct drm_radeon_tex_image { } drm_radeon_tex_image_t; typedef struct drm_radeon_texture { - int offset; + unsigned int offset; int pitch; int format; int width; /* Texture image coordinates */ @@ -537,10 +571,11 @@ typedef struct drm_radeon_indirect { #define RADEON_PARAM_STATUS_HANDLE 8 #define RADEON_PARAM_SAREA_HANDLE 9 #define RADEON_PARAM_GART_TEX_HANDLE 10 +#define RADEON_PARAM_SCRATCH_OFFSET 11 typedef struct drm_radeon_getparam { int param; - int *value; + void *value; } drm_radeon_getparam_t; /* 1.6: Set up a memory manager for regions of shared memory: @@ -578,4 +613,16 @@ typedef struct drm_radeon_irq_wait { } drm_radeon_irq_wait_t; +/* 1.10: Clients tell the DRM where they think the framebuffer is located in + * the card's address space, via a new generic ioctl to set parameters + */ + +typedef struct drm_radeon_setparam { + unsigned int param; + int64_t value; +} drm_radeon_setparam_t; + +#define RADEON_SETPARAM_FB_LOCATION 1 /* determined framebuffer location */ + + #endif --- linux-2.6.6/drivers/char/drm/radeon_drv.c 2003-07-13 21:44:34.000000000 -0700 +++ 25/drivers/char/drm/radeon_drv.c 2004-05-10 01:19:02.434368976 -0700 @@ -48,6 +48,7 @@ #include "drm_fops.h" #include "drm_init.h" #include "drm_ioctl.h" +#include "drm_irq.h" #include "drm_lock.h" #include "drm_memory.h" #include "drm_proc.h" --- linux-2.6.6/drivers/char/drm/radeon_drv.h 2003-09-27 18:57:44.000000000 -0700 +++ 25/drivers/char/drm/radeon_drv.h 2004-05-10 01:19:02.435368824 -0700 @@ -73,6 +73,8 @@ typedef struct drm_radeon_private { drm_radeon_ring_buffer_t ring; drm_radeon_sarea_t *sarea_priv; + u32 fb_location; + int gart_size; u32 gart_vm_start; unsigned long gart_buffers_offset; @@ -133,7 +135,6 @@ typedef struct drm_radeon_private { unsigned long gart_textures_offset; drm_local_map_t *sarea; - drm_local_map_t *fb; drm_local_map_t *mmio; drm_local_map_t *cp_ring; drm_local_map_t *ring_rptr; @@ -184,6 +185,7 @@ extern int radeon_cp_indirect( DRM_IOCTL extern int radeon_cp_vertex2( DRM_IOCTL_ARGS ); extern int radeon_cp_cmdbuf( DRM_IOCTL_ARGS ); extern int radeon_cp_getparam( DRM_IOCTL_ARGS ); +extern int radeon_cp_setparam( DRM_IOCTL_ARGS ); extern int radeon_cp_flip( DRM_IOCTL_ARGS ); extern int radeon_mem_alloc( DRM_IOCTL_ARGS ); @@ -239,6 +241,7 @@ extern void radeon_do_release(drm_device #define RADEON_CRTC2_OFFSET 0x0324 #define RADEON_CRTC2_OFFSET_CNTL 0x0328 +#define RADEON_RB3D_COLOROFFSET 0x1c40 #define RADEON_RB3D_COLORPITCH 0x1c48 #define RADEON_DP_GUI_MASTER_CNTL 0x146c @@ -332,6 +335,7 @@ extern void radeon_do_release(drm_device #define RADEON_PP_MISC 0x1c14 #define RADEON_PP_ROT_MATRIX_0 0x1d58 #define RADEON_PP_TXFILTER_0 0x1c54 +#define RADEON_PP_TXOFFSET_0 0x1c5c #define RADEON_PP_TXFILTER_1 0x1c6c #define RADEON_PP_TXFILTER_2 0x1c84 --- linux-2.6.6/drivers/char/drm/radeon.h 2003-09-27 18:57:44.000000000 -0700 +++ 25/drivers/char/drm/radeon.h 2004-05-10 01:19:02.430369584 -0700 @@ -51,7 +51,7 @@ #define DRIVER_DATE "20020828" #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 9 +#define DRIVER_MINOR 10 #define DRIVER_PATCHLEVEL 0 /* Interface history: @@ -81,6 +81,9 @@ * Add 'GET' queries for starting additional clients on different VT's. * 1.9 - Add DRM_IOCTL_RADEON_CP_RESUME ioctl. * Add texture rectangle support for r100. + * 1.10- Add SETPARAM ioctl; first parameter to set is FB_LOCATION, which + * clients use to tell the DRM where they think the framebuffer is + * located in the card's address space */ #define DRIVER_IOCTLS \ [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { radeon_cp_buffers, 1, 0 }, \ @@ -106,10 +109,21 @@ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_ALLOC)] = { radeon_mem_alloc, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_FREE)] = { radeon_mem_free, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INIT_HEAP)] = { radeon_mem_init_heap, 1, 1 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_EMIT)] = { radeon_irq_emit, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_WAIT)] = { radeon_irq_wait, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_EMIT)] = { radeon_irq_emit, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_WAIT)] = { radeon_irq_wait, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_SETPARAM)] = { radeon_cp_setparam, 1, 0 }, \ +#define DRIVER_FILE_FIELDS \ + int64_t radeon_fb_delta; \ +#define DRIVER_OPEN_HELPER( filp_priv, dev ) \ +do { \ + drm_radeon_private_t *dev_priv = dev->dev_private; \ + if ( dev_priv ) \ + filp_priv->radeon_fb_delta = dev_priv->fb_location; \ + else \ + filp_priv->radeon_fb_delta = 0; \ +} while( 0 ) /* When a client dies: * - Check for and clean up flipped page state @@ -142,7 +156,7 @@ do { \ /* DMA customization: */ #define __HAVE_DMA 1 -#define __HAVE_DMA_IRQ 1 +#define __HAVE_IRQ 1 #define __HAVE_VBL_IRQ 1 #define __HAVE_SHARED_IRQ 1 --- linux-2.6.6/drivers/char/drm/radeon_irq.c 2003-06-14 12:18:34.000000000 -0700 +++ 25/drivers/char/drm/radeon_irq.c 2004-05-10 01:19:02.436368672 -0700 @@ -54,7 +54,7 @@ * tied to dma at all, this is just a hangover from dri prehistory. */ -irqreturn_t DRM(dma_service)( DRM_IRQ_ARGS ) +irqreturn_t DRM(irq_handler)( DRM_IRQ_ARGS ) { drm_device_t *dev = (drm_device_t *) arg; drm_radeon_private_t *dev_priv = --- linux-2.6.6/drivers/char/drm/radeon_state.c 2004-02-17 20:48:42.000000000 -0800 +++ 25/drivers/char/drm/radeon_state.c 2004-05-10 01:19:02.440368064 -0700 @@ -36,6 +36,240 @@ /* ================================================================ + * Helper functions for client state checking and fixup + */ + +static __inline__ int radeon_check_and_fixup_offset( drm_radeon_private_t *dev_priv, + drm_file_t *filp_priv, + u32 *offset ) { + u32 off = *offset; + + if ( off >= dev_priv->fb_location && + off < ( dev_priv->gart_vm_start + dev_priv->gart_size ) ) + return 0; + + off += filp_priv->radeon_fb_delta; + + DRM_DEBUG( "offset fixed up to 0x%x\n", off ); + + if ( off < dev_priv->fb_location || + off >= ( dev_priv->gart_vm_start + dev_priv->gart_size ) ) + return DRM_ERR( EINVAL ); + + *offset = off; + + return 0; +} + +static __inline__ int radeon_check_and_fixup_offset_user( drm_radeon_private_t *dev_priv, + drm_file_t *filp_priv, + u32 *offset ) { + u32 off; + + DRM_GET_USER_UNCHECKED( off, offset ); + + if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &off ) ) + return DRM_ERR( EINVAL ); + + DRM_PUT_USER_UNCHECKED( offset, off ); + + return 0; +} + +static __inline__ int radeon_check_and_fixup_packets( drm_radeon_private_t *dev_priv, + drm_file_t *filp_priv, + int id, + u32 *data ) { + switch ( id ) { + + case RADEON_EMIT_PP_MISC: + if ( radeon_check_and_fixup_offset_user( dev_priv, filp_priv, + &data[( RADEON_RB3D_DEPTHOFFSET + - RADEON_PP_MISC ) / 4] ) ) { + DRM_ERROR( "Invalid depth buffer offset\n" ); + return DRM_ERR( EINVAL ); + } + break; + + case RADEON_EMIT_PP_CNTL: + if ( radeon_check_and_fixup_offset_user( dev_priv, filp_priv, + &data[( RADEON_RB3D_COLOROFFSET + - RADEON_PP_CNTL ) / 4] ) ) { + DRM_ERROR( "Invalid colour buffer offset\n" ); + return DRM_ERR( EINVAL ); + } + break; + + case R200_EMIT_PP_TXOFFSET_0: + case R200_EMIT_PP_TXOFFSET_1: + case R200_EMIT_PP_TXOFFSET_2: + case R200_EMIT_PP_TXOFFSET_3: + case R200_EMIT_PP_TXOFFSET_4: + case R200_EMIT_PP_TXOFFSET_5: + if ( radeon_check_and_fixup_offset_user( dev_priv, filp_priv, + &data[0] ) ) { + DRM_ERROR( "Invalid R200 texture offset\n" ); + return DRM_ERR( EINVAL ); + } + break; + + case RADEON_EMIT_PP_TXFILTER_0: + case RADEON_EMIT_PP_TXFILTER_1: + case RADEON_EMIT_PP_TXFILTER_2: + if ( radeon_check_and_fixup_offset_user( dev_priv, filp_priv, + &data[( RADEON_PP_TXOFFSET_0 + - RADEON_PP_TXFILTER_0 ) / 4] ) ) { + DRM_ERROR( "Invalid R100 texture offset\n" ); + return DRM_ERR( EINVAL ); + } + break; + + case R200_EMIT_PP_CUBIC_OFFSETS_0: + case R200_EMIT_PP_CUBIC_OFFSETS_1: + case R200_EMIT_PP_CUBIC_OFFSETS_2: + case R200_EMIT_PP_CUBIC_OFFSETS_3: + case R200_EMIT_PP_CUBIC_OFFSETS_4: + case R200_EMIT_PP_CUBIC_OFFSETS_5: { + int i; + for ( i = 0; i < 5; i++ ) { + if ( radeon_check_and_fixup_offset_user( dev_priv, + filp_priv, + &data[i] ) ) { + DRM_ERROR( "Invalid R200 cubic texture offset\n" ); + return DRM_ERR( EINVAL ); + } + } + break; + } + + case RADEON_EMIT_RB3D_COLORPITCH: + case RADEON_EMIT_RE_LINE_PATTERN: + case RADEON_EMIT_SE_LINE_WIDTH: + case RADEON_EMIT_PP_LUM_MATRIX: + case RADEON_EMIT_PP_ROT_MATRIX_0: + case RADEON_EMIT_RB3D_STENCILREFMASK: + case RADEON_EMIT_SE_VPORT_XSCALE: + case RADEON_EMIT_SE_CNTL: + case RADEON_EMIT_SE_CNTL_STATUS: + case RADEON_EMIT_RE_MISC: + case RADEON_EMIT_PP_BORDER_COLOR_0: + case RADEON_EMIT_PP_BORDER_COLOR_1: + case RADEON_EMIT_PP_BORDER_COLOR_2: + case RADEON_EMIT_SE_ZBIAS_FACTOR: + case RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT: + case RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED: + case R200_EMIT_PP_TXCBLEND_0: + case R200_EMIT_PP_TXCBLEND_1: + case R200_EMIT_PP_TXCBLEND_2: + case R200_EMIT_PP_TXCBLEND_3: + case R200_EMIT_PP_TXCBLEND_4: + case R200_EMIT_PP_TXCBLEND_5: + case R200_EMIT_PP_TXCBLEND_6: + case R200_EMIT_PP_TXCBLEND_7: + case R200_EMIT_TCL_LIGHT_MODEL_CTL_0: + case R200_EMIT_TFACTOR_0: + case R200_EMIT_VTX_FMT_0: + case R200_EMIT_VAP_CTL: + case R200_EMIT_MATRIX_SELECT_0: + case R200_EMIT_TEX_PROC_CTL_2: + case R200_EMIT_TCL_UCP_VERT_BLEND_CTL: + case R200_EMIT_PP_TXFILTER_0: + case R200_EMIT_PP_TXFILTER_1: + case R200_EMIT_PP_TXFILTER_2: + case R200_EMIT_PP_TXFILTER_3: + case R200_EMIT_PP_TXFILTER_4: + case R200_EMIT_PP_TXFILTER_5: + case R200_EMIT_VTE_CNTL: + case R200_EMIT_OUTPUT_VTX_COMP_SEL: + case R200_EMIT_PP_TAM_DEBUG3: + case R200_EMIT_PP_CNTL_X: + case R200_EMIT_RB3D_DEPTHXY_OFFSET: + case R200_EMIT_RE_AUX_SCISSOR_CNTL: + case R200_EMIT_RE_SCISSOR_TL_0: + case R200_EMIT_RE_SCISSOR_TL_1: + case R200_EMIT_RE_SCISSOR_TL_2: + case R200_EMIT_SE_VAP_CNTL_STATUS: + case R200_EMIT_SE_VTX_STATE_CNTL: + case R200_EMIT_RE_POINTSIZE: + case R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0: + case R200_EMIT_PP_CUBIC_FACES_0: + case R200_EMIT_PP_CUBIC_FACES_1: + case R200_EMIT_PP_CUBIC_FACES_2: + case R200_EMIT_PP_CUBIC_FACES_3: + case R200_EMIT_PP_CUBIC_FACES_4: + case R200_EMIT_PP_CUBIC_FACES_5: + case RADEON_EMIT_PP_TEX_SIZE_0: + case RADEON_EMIT_PP_TEX_SIZE_1: + case RADEON_EMIT_PP_TEX_SIZE_2: + /* These packets don't contain memory offsets */ + break; + + default: + DRM_ERROR( "Unknown state packet ID %d\n", id ); + return DRM_ERR( EINVAL ); + } + + return 0; +} + +static __inline__ int radeon_check_and_fixup_packet3( drm_radeon_private_t *dev_priv, + drm_file_t *filp_priv, + drm_radeon_cmd_buffer_t *cmdbuf, + unsigned int *cmdsz ) { + u32 tmp[4], *cmd = ( u32* )cmdbuf->buf; + + if ( DRM_COPY_FROM_USER_UNCHECKED( tmp, cmd, sizeof( tmp ) ) ) { + DRM_ERROR( "Failed to copy data from user space\n" ); + return DRM_ERR( EFAULT ); + } + + *cmdsz = 2 + ( ( tmp[0] & RADEON_CP_PACKET_COUNT_MASK ) >> 16 ); + + if ( ( tmp[0] & 0xc0000000 ) != RADEON_CP_PACKET3 ) { + DRM_ERROR( "Not a type 3 packet\n" ); + return DRM_ERR( EINVAL ); + } + + if ( 4 * *cmdsz > cmdbuf->bufsz ) { + DRM_ERROR( "Packet size larger than size of data provided\n" ); + return DRM_ERR( EINVAL ); + } + + /* Check client state and fix it up if necessary */ + if ( tmp[0] & 0x8000 ) { /* MSB of opcode: next DWORD GUI_CNTL */ + u32 offset; + + if ( tmp[1] & ( RADEON_GMC_SRC_PITCH_OFFSET_CNTL + | RADEON_GMC_DST_PITCH_OFFSET_CNTL ) ) { + offset = tmp[2] << 10; + if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &offset ) ) { + DRM_ERROR( "Invalid first packet offset\n" ); + return DRM_ERR( EINVAL ); + } + tmp[2] = ( tmp[2] & 0xffc00000 ) | offset >> 10; + } + + if ( ( tmp[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL ) && + ( tmp[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL ) ) { + offset = tmp[3] << 10; + if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &offset ) ) { + DRM_ERROR( "Invalid second packet offset\n" ); + return DRM_ERR( EINVAL ); + } + tmp[3] = ( tmp[3] & 0xffc00000 ) | offset >> 10; + } + + if ( DRM_COPY_TO_USER_UNCHECKED( cmd, tmp, sizeof( tmp ) ) ) { + DRM_ERROR( "Failed to copy data to user space\n" ); + return DRM_ERR( EFAULT ); + } + } + + return 0; +} + + +/* ================================================================ * CP hardware state programming functions */ @@ -57,15 +291,28 @@ static __inline__ void radeon_emit_clip_ /* Emit 1.1 state */ -static void radeon_emit_state( drm_radeon_private_t *dev_priv, - drm_radeon_context_regs_t *ctx, - drm_radeon_texture_regs_t *tex, - unsigned int dirty ) +static int radeon_emit_state( drm_radeon_private_t *dev_priv, + drm_file_t *filp_priv, + drm_radeon_context_regs_t *ctx, + drm_radeon_texture_regs_t *tex, + unsigned int dirty ) { RING_LOCALS; DRM_DEBUG( "dirty=0x%08x\n", dirty ); if ( dirty & RADEON_UPLOAD_CONTEXT ) { + if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, + &ctx->rb3d_depthoffset ) ) { + DRM_ERROR( "Invalid depth buffer offset\n" ); + return DRM_ERR( EINVAL ); + } + + if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, + &ctx->rb3d_coloroffset ) ) { + DRM_ERROR( "Invalid depth buffer offset\n" ); + return DRM_ERR( EINVAL ); + } + BEGIN_RING( 14 ); OUT_RING( CP_PACKET0( RADEON_PP_MISC, 6 ) ); OUT_RING( ctx->pp_misc ); @@ -149,6 +396,12 @@ static void radeon_emit_state( drm_radeo } if ( dirty & RADEON_UPLOAD_TEX0 ) { + if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, + &tex[0].pp_txoffset ) ) { + DRM_ERROR( "Invalid texture offset for unit 0\n" ); + return DRM_ERR( EINVAL ); + } + BEGIN_RING( 9 ); OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_0, 5 ) ); OUT_RING( tex[0].pp_txfilter ); @@ -163,6 +416,12 @@ static void radeon_emit_state( drm_radeo } if ( dirty & RADEON_UPLOAD_TEX1 ) { + if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, + &tex[1].pp_txoffset ) ) { + DRM_ERROR( "Invalid texture offset for unit 1\n" ); + return DRM_ERR( EINVAL ); + } + BEGIN_RING( 9 ); OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_1, 5 ) ); OUT_RING( tex[1].pp_txfilter ); @@ -177,6 +436,12 @@ static void radeon_emit_state( drm_radeo } if ( dirty & RADEON_UPLOAD_TEX2 ) { + if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, + &tex[2].pp_txoffset ) ) { + DRM_ERROR( "Invalid texture offset for unit 2\n" ); + return DRM_ERR( EINVAL ); + } + BEGIN_RING( 9 ); OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_2, 5 ) ); OUT_RING( tex[2].pp_txfilter ); @@ -189,12 +454,15 @@ static void radeon_emit_state( drm_radeo OUT_RING( tex[2].pp_border_color ); ADVANCE_RING(); } + + return 0; } /* Emit 1.2 state */ -static void radeon_emit_state2( drm_radeon_private_t *dev_priv, - drm_radeon_state_t *state ) +static int radeon_emit_state2( drm_radeon_private_t *dev_priv, + drm_file_t *filp_priv, + drm_radeon_state_t *state ) { RING_LOCALS; @@ -206,7 +474,7 @@ static void radeon_emit_state2( drm_rade ADVANCE_RING(); } - radeon_emit_state( dev_priv, &state->context, + return radeon_emit_state( dev_priv, filp_priv, &state->context, state->tex, state->dirty ); } @@ -1065,6 +1333,7 @@ static int radeon_cp_dispatch_texture( D drm_radeon_tex_image_t *image ) { drm_radeon_private_t *dev_priv = dev->dev_private; + drm_file_t *filp_priv; drm_buf_t *buf; u32 format; u32 *buffer; @@ -1074,6 +1343,13 @@ static int radeon_cp_dispatch_texture( D int i; RING_LOCALS; + DRM_GET_PRIV_WITH_RETURN( filp_priv, filp ); + + if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &tex->offset ) ) { + DRM_ERROR( "Invalid destination offset\n" ); + return DRM_ERR( EINVAL ); + } + dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD; /* Flush the pixel cache. This ensures no pixel data gets mixed @@ -1377,6 +1653,7 @@ int radeon_cp_vertex( DRM_IOCTL_ARGS ) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; + drm_file_t *filp_priv; drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; @@ -1390,6 +1667,8 @@ int radeon_cp_vertex( DRM_IOCTL_ARGS ) return DRM_ERR(EINVAL); } + DRM_GET_PRIV_WITH_RETURN( filp_priv, filp ); + DRM_COPY_FROM_USER_IOCTL( vertex, (drm_radeon_vertex_t *)data, sizeof(vertex) ); @@ -1429,11 +1708,14 @@ int radeon_cp_vertex( DRM_IOCTL_ARGS ) buf->used = vertex.count; /* not used? */ if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) { - radeon_emit_state( dev_priv, - &sarea_priv->context_state, - sarea_priv->tex_state, - sarea_priv->dirty ); - + if ( radeon_emit_state( dev_priv, filp_priv, + &sarea_priv->context_state, + sarea_priv->tex_state, + sarea_priv->dirty ) ) { + DRM_ERROR( "radeon_emit_state failed\n" ); + return DRM_ERR( EINVAL ); + } + sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES | RADEON_UPLOAD_TEX1IMAGES | RADEON_UPLOAD_TEX2IMAGES | @@ -1461,6 +1743,7 @@ int radeon_cp_indices( DRM_IOCTL_ARGS ) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; + drm_file_t *filp_priv; drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; @@ -1475,6 +1758,8 @@ int radeon_cp_indices( DRM_IOCTL_ARGS ) return DRM_ERR(EINVAL); } + DRM_GET_PRIV_WITH_RETURN( filp_priv, filp ); + DRM_COPY_FROM_USER_IOCTL( elts, (drm_radeon_indices_t *)data, sizeof(elts) ); @@ -1523,10 +1808,13 @@ int radeon_cp_indices( DRM_IOCTL_ARGS ) buf->used = elts.end; if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) { - radeon_emit_state( dev_priv, - &sarea_priv->context_state, - sarea_priv->tex_state, - sarea_priv->dirty ); + if ( radeon_emit_state( dev_priv, filp_priv, + &sarea_priv->context_state, + sarea_priv->tex_state, + sarea_priv->dirty ) ) { + DRM_ERROR( "radeon_emit_state failed\n" ); + return DRM_ERR( EINVAL ); + } sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES | RADEON_UPLOAD_TEX1IMAGES | @@ -1686,6 +1974,7 @@ int radeon_cp_vertex2( DRM_IOCTL_ARGS ) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; + drm_file_t *filp_priv; drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; @@ -1700,6 +1989,8 @@ int radeon_cp_vertex2( DRM_IOCTL_ARGS ) return DRM_ERR(EINVAL); } + DRM_GET_PRIV_WITH_RETURN( filp_priv, filp ); + DRM_COPY_FROM_USER_IOCTL( vertex, (drm_radeon_vertex2_t *)data, sizeof(vertex) ); @@ -1747,7 +2038,10 @@ int radeon_cp_vertex2( DRM_IOCTL_ARGS ) sizeof(state) ) ) return DRM_ERR(EFAULT); - radeon_emit_state2( dev_priv, &state ); + if ( radeon_emit_state2( dev_priv, filp_priv, &state ) ) { + DRM_ERROR( "radeon_emit_state2 failed\n" ); + return DRM_ERR( EINVAL ); + } laststate = prim.stateidx; } @@ -1784,6 +2078,7 @@ int radeon_cp_vertex2( DRM_IOCTL_ARGS ) static int radeon_emit_packets( drm_radeon_private_t *dev_priv, + drm_file_t *filp_priv, drm_radeon_cmd_header_t header, drm_radeon_cmd_buffer_t *cmdbuf ) { @@ -1798,8 +2093,15 @@ static int radeon_emit_packets( sz = packet[id].len; reg = packet[id].start; - if (sz * sizeof(int) > cmdbuf->bufsz) + if (sz * sizeof(int) > cmdbuf->bufsz) { + DRM_ERROR( "Packet size provided larger than data provided\n" ); return DRM_ERR(EINVAL); + } + + if ( radeon_check_and_fixup_packets( dev_priv, filp_priv, id, data ) ) { + DRM_ERROR( "Packet verification failed\n" ); + return DRM_ERR( EINVAL ); + } BEGIN_RING(sz+1); OUT_RING( CP_PACKET0( reg, (sz-1) ) ); @@ -1882,24 +2184,21 @@ static __inline__ int radeon_emit_vector static int radeon_emit_packet3( drm_device_t *dev, + drm_file_t *filp_priv, drm_radeon_cmd_buffer_t *cmdbuf ) { drm_radeon_private_t *dev_priv = dev->dev_private; - int cmdsz, tmp; - int *cmd = (int *)cmdbuf->buf; + unsigned int cmdsz; + int *cmd = (int *)cmdbuf->buf, ret; RING_LOCALS; - DRM_DEBUG("\n"); - if (DRM_GET_USER_UNCHECKED( tmp, &cmd[0])) - return DRM_ERR(EFAULT); - - cmdsz = 2 + ((tmp & RADEON_CP_PACKET_COUNT_MASK) >> 16); - - if ((tmp & 0xc0000000) != RADEON_CP_PACKET3 || - cmdsz * 4 > cmdbuf->bufsz) - return DRM_ERR(EINVAL); + if ( ( ret = radeon_check_and_fixup_packet3( dev_priv, filp_priv, + cmdbuf, &cmdsz ) ) ) { + DRM_ERROR( "Packet verification failed\n" ); + return ret; + } BEGIN_RING( cmdsz ); OUT_RING_USER_TABLE( cmd, cmdsz ); @@ -1912,27 +2211,25 @@ static int radeon_emit_packet3( drm_devi static int radeon_emit_packet3_cliprect( drm_device_t *dev, + drm_file_t *filp_priv, drm_radeon_cmd_buffer_t *cmdbuf, int orig_nbox ) { drm_radeon_private_t *dev_priv = dev->dev_private; drm_clip_rect_t box; - int cmdsz, tmp; - int *cmd = (int *)cmdbuf->buf; + unsigned int cmdsz; + int *cmd = (int *)cmdbuf->buf, ret; drm_clip_rect_t *boxes = cmdbuf->boxes; int i = 0; RING_LOCALS; DRM_DEBUG("\n"); - if (DRM_GET_USER_UNCHECKED( tmp, &cmd[0])) - return DRM_ERR(EFAULT); - - cmdsz = 2 + ((tmp & RADEON_CP_PACKET_COUNT_MASK) >> 16); - - if ((tmp & 0xc0000000) != RADEON_CP_PACKET3 || - cmdsz * 4 > cmdbuf->bufsz) - return DRM_ERR(EINVAL); + if ( ( ret = radeon_check_and_fixup_packet3( dev_priv, filp_priv, + cmdbuf, &cmdsz ) ) ) { + DRM_ERROR( "Packet verification failed\n" ); + return ret; + } if (!orig_nbox) goto out; @@ -2009,6 +2306,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS ) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; + drm_file_t *filp_priv; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf = 0; int idx; @@ -2023,6 +2321,8 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS ) return DRM_ERR(EINVAL); } + DRM_GET_PRIV_WITH_RETURN( filp_priv, filp ); + DRM_COPY_FROM_USER_IOCTL( cmdbuf, (drm_radeon_cmd_buffer_t *)data, sizeof(cmdbuf) ); @@ -2053,7 +2353,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS ) switch (header.header.cmd_type) { case RADEON_CMD_PACKET: DRM_DEBUG("RADEON_CMD_PACKET\n"); - if (radeon_emit_packets( dev_priv, header, &cmdbuf )) { + if (radeon_emit_packets( dev_priv, filp_priv, header, &cmdbuf )) { DRM_ERROR("radeon_emit_packets failed\n"); return DRM_ERR(EINVAL); } @@ -2096,7 +2396,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS ) case RADEON_CMD_PACKET3: DRM_DEBUG("RADEON_CMD_PACKET3\n"); - if (radeon_emit_packet3( dev, &cmdbuf )) { + if (radeon_emit_packet3( dev, filp_priv, &cmdbuf )) { DRM_ERROR("radeon_emit_packet3 failed\n"); return DRM_ERR(EINVAL); } @@ -2104,7 +2404,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS ) case RADEON_CMD_PACKET3_CLIP: DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n"); - if (radeon_emit_packet3_cliprect( dev, &cmdbuf, orig_nbox )) { + if (radeon_emit_packet3_cliprect( dev, filp_priv, &cmdbuf, orig_nbox )) { DRM_ERROR("radeon_emit_packet3_clip failed\n"); return DRM_ERR(EINVAL); } @@ -2214,3 +2514,31 @@ int radeon_cp_getparam( DRM_IOCTL_ARGS ) return 0; } + +int radeon_cp_setparam( DRM_IOCTL_ARGS ) { + DRM_DEVICE; + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_file_t *filp_priv; + drm_radeon_setparam_t sp; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR( EINVAL ); + } + + DRM_GET_PRIV_WITH_RETURN( filp_priv, filp ); + + DRM_COPY_FROM_USER_IOCTL( sp, ( drm_radeon_setparam_t* )data, + sizeof( sp ) ); + + switch( sp.param ) { + case RADEON_SETPARAM_FB_LOCATION: + filp_priv->radeon_fb_delta = dev_priv->fb_location - sp.value; + break; + default: + DRM_DEBUG( "Invalid parameter %d\n", sp.param ); + return DRM_ERR( EINVAL ); + } + + return 0; +} --- linux-2.6.6/drivers/char/drm/tdfx_drv.c 2003-06-14 12:18:21.000000000 -0700 +++ 25/drivers/char/drm/tdfx_drv.c 2004-05-10 01:19:02.441367912 -0700 @@ -34,47 +34,6 @@ #include "tdfx.h" #include "drmP.h" -#define DRIVER_AUTHOR "VA Linux Systems Inc." - -#define DRIVER_NAME "tdfx" -#define DRIVER_DESC "3dfx Banshee/Voodoo3+" -#define DRIVER_DATE "20010216" - -#define DRIVER_MAJOR 1 -#define DRIVER_MINOR 0 -#define DRIVER_PATCHLEVEL 0 - -#ifndef PCI_VENDOR_ID_3DFX -#define PCI_VENDOR_ID_3DFX 0x121A -#endif -#ifndef PCI_DEVICE_ID_3DFX_VOODOO5 -#define PCI_DEVICE_ID_3DFX_VOODOO5 0x0009 -#endif -#ifndef PCI_DEVICE_ID_3DFX_VOODOO4 -#define PCI_DEVICE_ID_3DFX_VOODOO4 0x0007 -#endif -#ifndef PCI_DEVICE_ID_3DFX_VOODOO3_3000 /* Voodoo3 3000 */ -#define PCI_DEVICE_ID_3DFX_VOODOO3_3000 0x0005 -#endif -#ifndef PCI_DEVICE_ID_3DFX_VOODOO3_2000 /* Voodoo3 3000 */ -#define PCI_DEVICE_ID_3DFX_VOODOO3_2000 0x0004 -#endif -#ifndef PCI_DEVICE_ID_3DFX_BANSHEE -#define PCI_DEVICE_ID_3DFX_BANSHEE 0x0003 -#endif - -static drm_pci_list_t DRM(idlist)[] = { - { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_BANSHEE }, - { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3_2000 }, - { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3_3000 }, - { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO4 }, - { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO5 }, - { 0, 0 } -}; - -#define DRIVER_CARD_LIST DRM(idlist) - - #include "drm_auth.h" #include "drm_bufs.h" #include "drm_context.h" --- linux-2.6.6/drivers/char/drm/tdfx.h 2003-06-14 12:18:22.000000000 -0700 +++ 25/drivers/char/drm/tdfx.h 2004-05-10 01:19:02.441367912 -0700 @@ -39,4 +39,14 @@ #define __HAVE_MTRR 1 #define __HAVE_CTX_BITMAP 1 +#define DRIVER_AUTHOR "VA Linux Systems Inc." + +#define DRIVER_NAME "tdfx" +#define DRIVER_DESC "3dfx Banshee/Voodoo3+" +#define DRIVER_DATE "20010216" + +#define DRIVER_MAJOR 1 +#define DRIVER_MINOR 0 +#define DRIVER_PATCHLEVEL 0 + #endif --- linux-2.6.6/drivers/char/dz.c 2004-04-03 20:39:12.000000000 -0800 +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,1540 +0,0 @@ -/* - * dz.c: Serial port driver for DECStations equiped - * with the DZ chipset. - * - * Copyright (C) 1998 Olivier A. D. Lebaillif - * - * Email: olivier.lebaillif@ifrsys.com - * - * [31-AUG-98] triemer - * Changed IRQ to use Harald's dec internals interrupts.h - * removed base_addr code - moving address assignment to setup.c - * Changed name of dz_init to rs_init to be consistent with tc code - * [13-NOV-98] triemer fixed code to receive characters - * after patches by harald to irq code. - * [09-JAN-99] triemer minor fix for schedule - due to removal of timeout - * field from "current" - somewhere between 2.1.121 and 2.1.131 -Qua Jun 27 15:02:26 BRT 2001 - * [27-JUN-2001] Arnaldo Carvalho de Melo - cleanups - * - * Parts (C) 1999 David Airlie, airlied@linux.ie - * [07-SEP-99] Bugfixes - */ - -/* #define DEBUG_DZ 1 */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* for definition of SERIAL */ - -/* for definition of struct console */ -#ifdef CONFIG_SERIAL_CONSOLE -#define CONSOLE_LINE (3) -#endif /* ifdef CONFIG_SERIAL_CONSOLE */ -#if defined(CONFIG_SERIAL_CONSOLE) || defined(DEBUG_DZ) -#include -#endif /* if defined(CONFIG_SERIAL_CONSOLE) || defined(DEBUG_DZ) */ - -#include -#include - -#include -#include -#include -#include -#include - -#ifdef DEBUG_DZ -#include -#include -#include - -extern int (*prom_printf) (char *,...); -#endif - - - -#include "dz.h" - -#define DZ_INTR_DEBUG 1 - -DECLARE_TASK_QUEUE(tq_serial); - -static struct dz_serial *lines[4]; -static unsigned char tmp_buffer[256]; - - - -#ifdef DEBUG_DZ -/* - * debugging code to send out chars via prom - */ -static void debug_console( const char *s,int count) -{ - unsigned i; - - for (i = 0; i < count; i++) { - if (*s == 10) - prom_printf("%c", 13); - prom_printf("%c", *s++); - } -} -#endif - -/* - * ------------------------------------------------------------ - * dz_in () and dz_out () - * - * These routines are used to access the registers of the DZ - * chip, hiding relocation differences between implementation. - * ------------------------------------------------------------ - */ - -static inline unsigned short dz_in (struct dz_serial *info, unsigned offset) -{ - volatile u16 *addr = (volatile u16 *)(info->port + offset); - - return *addr; -} - -static inline void dz_out (struct dz_serial *info, unsigned offset, - unsigned short value) -{ - volatile u16 *addr = (volatile u16 *)(info->port + offset); - *addr = value; -} - -/* - * ------------------------------------------------------------ - * rs_stop () and rs_start () - * - * These routines are called before setting or resetting - * tty->stopped. They enable or disable transmitter interrupts, - * as necessary. - * ------------------------------------------------------------ - */ - -static void dz_stop (struct tty_struct *tty) -{ - struct dz_serial *info; - unsigned short mask, tmp; - - if (!tty) - return; - - info = (struct dz_serial *)tty->driver_data; - - mask = 1 << info->line; - tmp = dz_in (info, DZ_TCR); /* read the TX flag */ - - tmp &= ~mask; /* clear the TX flag */ - dz_out (info, DZ_TCR, tmp); -} - -static void dz_start (struct tty_struct *tty) -{ - struct dz_serial *info = (struct dz_serial *)tty->driver_data; - unsigned short mask, tmp; - - mask = 1 << info->line; - tmp = dz_in (info, DZ_TCR); /* read the TX flag */ - - tmp |= mask; /* set the TX flag */ - dz_out (info, DZ_TCR, tmp); -} - -/* - * ------------------------------------------------------------ - * Here starts the interrupt handling routines. All of the - * following subroutines are declared as inline and are folded - * into dz_interrupt. They were separated out for readability's - * sake. - * - * Note: rs_interrupt() is a "fast" interrupt, which means that it - * runs with interrupts turned off. People who may want to modify - * rs_interrupt() should try to keep the interrupt handler as fast as - * possible. After you are done making modifications, it is not a bad - * idea to do: - * - * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer dz.c - * - * and look at the resulting assemble code in serial.s. - * - * ------------------------------------------------------------ - */ - -/* - * ------------------------------------------------------------ - * dz_sched_event () - * - * This routine is used by the interrupt handler to schedule - * processing in the software interrupt portion of the driver. - * ------------------------------------------------------------ - */ -static inline void dz_sched_event (struct dz_serial *info, int event) -{ - info->event |= 1 << event; - queue_task(&info->tqueue, &tq_serial); - mark_bh(SERIAL_BH); -} - -/* - * ------------------------------------------------------------ - * receive_char () - * - * This routine deals with inputs from any lines. - * ------------------------------------------------------------ - */ -static inline void receive_chars (struct dz_serial *info_in) -{ - struct dz_serial *info; - struct tty_struct *tty = 0; - struct async_icount *icount; - int ignore = 0; - unsigned short status, tmp; - unsigned char ch; - - /* - * This code is going to be a problem... the call to tty_flip_buffer - * is going to need to be rethought... - */ - do { - status = dz_in (info_in, DZ_RBUF); - info = lines[LINE(status)]; - - /* punt so we don't get duplicate characters */ - if (!(status & DZ_DVAL)) - goto ignore_char; - - ch = UCHAR(status); /* grab the char */ - -#if 0 - if (info->is_console) { - if (ch == 0) - return; /* it's a break ... */ - } -#endif - - tty = info->tty; /* now tty points to the proper dev */ - icount = &info->icount; - - if (!tty) - break; - if (tty->flip.count >= TTY_FLIPBUF_SIZE) break; - - *tty->flip.char_buf_ptr = ch; - *tty->flip.flag_buf_ptr = 0; - icount->rx++; - - /* keep track of the statistics */ - if (status & (DZ_OERR | DZ_FERR | DZ_PERR)) { - if (status & DZ_PERR) /* parity error */ - icount->parity++; - else if (status & DZ_FERR) /* frame error */ - icount->frame++; - if (status & DZ_OERR) /* overrun error */ - icount->overrun++; - - /* - * Check to see if we should ignore the character and - * mask off conditions that should be ignored - */ - - if (status & info->ignore_status_mask) { - if (++ignore > 100) - break; - goto ignore_char; - } - - /* mask off the error conditions we want to ignore */ - tmp = status & info->read_status_mask; - - if (tmp & DZ_PERR) { - *tty->flip.flag_buf_ptr = TTY_PARITY; -#ifdef DEBUG_DZ - debug_console("PERR\n",5); -#endif /* DEBUG_DZ */ - } else if (tmp & DZ_FERR) { - *tty->flip.flag_buf_ptr = TTY_FRAME; -#ifdef DEBUG_DZ - debug_console("FERR\n",5); -#endif /* DEBUG_DZ */ - } if (tmp & DZ_OERR) { -#ifdef DEBUG_DZ - debug_console("OERR\n",5); -#endif /* DEBUG_DZ */ - if (tty->flip.count < TTY_FLIPBUF_SIZE) { - tty->flip.count++; - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - *tty->flip.flag_buf_ptr = TTY_OVERRUN; - } - } - } - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; -ignore_char: - ; - } while (status & DZ_DVAL); - - if (tty) - tty_flip_buffer_push(tty); -} - -/* - * ------------------------------------------------------------ - * transmit_char () - * - * This routine deals with outputs to any lines. - * ------------------------------------------------------------ - */ -static inline void transmit_chars (struct dz_serial *info) -{ - unsigned char tmp; - - if (info->x_char) { /* XON/XOFF chars */ - dz_out(info, DZ_TDR, info->x_char); - info->icount.tx++; - info->x_char = 0; - return; - } - - /* if nothing to do or stopped or hardware stopped */ - if ((info->xmit_cnt <= 0) || info->tty->stopped || - info->tty->hw_stopped) { - dz_stop(info->tty); - return; - } - - /* - * If something to do ... (rember the dz has no output fifo so we go - * one char at a time :-< - */ - tmp = (unsigned short) info->xmit_buf[info->xmit_tail++]; - dz_out(info, DZ_TDR, tmp); - info->xmit_tail = info->xmit_tail & (DZ_XMIT_SIZE - 1); - info->icount.tx++; - - if (--info->xmit_cnt < WAKEUP_CHARS) - dz_sched_event(info, DZ_EVENT_WRITE_WAKEUP); - - /* Are we done */ - if (info->xmit_cnt <= 0) - dz_stop(info->tty); -} - -/* - * ------------------------------------------------------------ - * check_modem_status () - * - * Only valid for the MODEM line duh ! - * ------------------------------------------------------------ - */ -static inline void check_modem_status (struct dz_serial *info) -{ - unsigned short status; - - /* if not ne modem line just return */ - if (info->line != DZ_MODEM) - return; - - status = dz_in(info, DZ_MSR); - - /* it's easy, since DSR2 is the only bit in the register */ - if (status) - info->icount.dsr++; -} - -/* - * ------------------------------------------------------------ - * dz_interrupt () - * - * this is the main interrupt routine for the DZ chip. - * It deals with the multiple ports. - * ------------------------------------------------------------ - */ -static void dz_interrupt (int irq, void *dev, struct pt_regs *regs) -{ - struct dz_serial *info; - unsigned short status; - - /* get the reason why we just got an irq */ - status = dz_in((struct dz_serial *)dev, DZ_CSR); - info = lines[LINE(status)]; /* re-arrange info the proper port */ - - if (status & DZ_RDONE) - receive_chars(info); /* the receive function */ - - if (status & DZ_TRDY) - transmit_chars (info); -} - -/* - * ------------------------------------------------------------------- - * Here ends the DZ interrupt routines. - * ------------------------------------------------------------------- - */ - -/* - * This routine is used to handle the "bottom half" processing for the - * serial driver, known also the "software interrupt" processing. - * This processing is done at the kernel interrupt level, after the - * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This - * is where time-consuming activities which can not be done in the - * interrupt driver proper are done; the interrupt driver schedules - * them using rs_sched_event(), and they get done here. - */ -static void do_serial_bh (void) -{ - run_task_queue (&tq_serial); -} - -static void do_softint (void *private_data) -{ - struct dz_serial *info = (struct dz_serial *) private_data; - struct tty_struct *tty = info->tty; - - if (!tty) - return; - - if (test_and_clear_bit(DZ_EVENT_WRITE_WAKEUP, &info->event)) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup) (tty); - wake_up_interruptible (&tty->write_wait); - } -} - -/* - * ------------------------------------------------------------------- - * This routine is called from the scheduler tqueue when the interrupt - * routine has signalled that a hangup has occurred. The path of - * hangup processing is: - * - * serial interrupt routine -> (scheduler tqueue) -> - * do_serial_hangup() -> tty->hangup() -> rs_hangup() - * ------------------------------------------------------------------- - */ -static void do_serial_hangup (void *private_data) -{ - struct dz_serial *info = (struct dz_serial *) private_data; - struct tty_struct *tty = info->tty; - - if (!tty) - return; - - tty_hangup(tty); -} - -/* - * ------------------------------------------------------------------- - * startup () - * - * various initialization tasks - * ------------------------------------------------------------------- - */ -static int startup (struct dz_serial *info) -{ - unsigned long page, flags; - unsigned short tmp; - - if (info->is_initialized) - return 0; - - save_and_cli(flags); - - if (!info->port) { - if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); - restore_flags(flags); - return -ENODEV; - } - - if (!info->xmit_buf) { - page = get_zeroed_page(GFP_KERNEL); - if (!page) { - restore_flags (flags); - return -ENOMEM; - } - info->xmit_buf = (unsigned char *)page; - } - - if (info->tty) - clear_bit(TTY_IO_ERROR, &info->tty->flags); - - /* enable the interrupt and the scanning */ - tmp = dz_in(info, DZ_CSR); - tmp |= (DZ_RIE | DZ_TIE | DZ_MSE); - dz_out(info, DZ_CSR, tmp); - - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - - change_speed(info); /* set up the speed */ - - /* - * Clear the line transmitter buffer I can't figure out why I need to - * do this - but its necessary - in order for the console portion and - * the interrupt portion to live happily side by side. - */ - - info->is_initialized = 1; - - restore_flags(flags); - - return 0; -} - -/* - * ------------------------------------------------------------------- - * shutdown () - * - * This routine will shutdown a serial port; interrupts are disabled, and - * DTR is dropped if the hangup on close termio flag is on. - * ------------------------------------------------------------------- - */ -static void shutdown (struct dz_serial *info) -{ - unsigned long flags; - unsigned short tmp; - - if (!info->is_initialized) - return; - - save_and_cli(flags); - - dz_stop (info->tty); - - info->cflags &= ~DZ_CREAD; /* turn off receive enable flag */ - dz_out(info, DZ_LPR, info->cflags); - - if (info->xmit_buf) { /* free Tx buffer */ - free_page((unsigned long)info->xmit_buf); - info->xmit_buf = 0; - } - - if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { - tmp = dz_in(info, DZ_TCR); - if (tmp & DZ_MODEM_DTR) { - tmp &= ~DZ_MODEM_DTR; - dz_out(info, DZ_TCR, tmp); - } - } - - if (info->tty) - set_bit (TTY_IO_ERROR, &info->tty->flags); - - info->is_initialized = 0; - - restore_flags (flags); -} - -/* - * ------------------------------------------------------------------- - * change_speed () - * - * set the baud rate. - * ------------------------------------------------------------------- - */ -static void change_speed (struct dz_serial *info) -{ - unsigned long flags; - unsigned cflag; - int baud; - - if (!info->tty || !info->tty->termios) - return; - - save_and_cli(flags); - - info->cflags = info->line; - - cflag = info->tty->termios->c_cflag; - - switch (cflag & CSIZE) { - case CS5: - info->cflags |= DZ_CS5; - break; - case CS6: - info->cflags |= DZ_CS6; - break; - case CS7: - info->cflags |= DZ_CS7; - break; - case CS8: - default: - info->cflags |= DZ_CS8; - } - - if (cflag & CSTOPB) - info->cflags |= DZ_CSTOPB; - if (cflag & PARENB) - info->cflags |= DZ_PARENB; - if (cflag & PARODD) - info->cflags |= DZ_PARODD; - - baud = tty_get_baud_rate(info->tty); - switch (baud) { - case 50: - info->cflags |= DZ_B50; - break; - case 75: - info->cflags |= DZ_B75; - break; - case 110: - info->cflags |= DZ_B110; - break; - case 134: - info->cflags |= DZ_B134; - break; - case 150: - info->cflags |= DZ_B150; - break; - case 300: - info->cflags |= DZ_B300; - break; - case 600: - info->cflags |= DZ_B600; - break; - case 1200: - info->cflags |= DZ_B1200; - break; - case 1800: - info->cflags |= DZ_B1800; - break; - case 2000: - info->cflags |= DZ_B2000; - break; - case 2400: - info->cflags |= DZ_B2400; - break; - case 3600: - info->cflags |= DZ_B3600; - break; - case 4800: - info->cflags |= DZ_B4800; - break; - case 7200: - info->cflags |= DZ_B7200; - break; - case 9600: - default: - info->cflags |= DZ_B9600; - } - - info->cflags |= DZ_RXENAB; - dz_out(info, DZ_LPR, info->cflags); - - /* setup accept flag */ - info->read_status_mask = DZ_OERR; - if (I_INPCK(info->tty)) - info->read_status_mask |= (DZ_FERR | DZ_PERR); - - /* characters to ignore */ - info->ignore_status_mask = 0; - if (I_IGNPAR(info->tty)) - info->ignore_status_mask |= (DZ_FERR | DZ_PERR); - - restore_flags(flags); -} - -/* - * ------------------------------------------------------------------- - * dz_flush_char () - * - * Flush the buffer. - * ------------------------------------------------------------------- - */ -static void dz_flush_chars (struct tty_struct *tty) -{ - struct dz_serial *info = (struct dz_serial *)tty->driver_data; - unsigned long flags; - - if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || - !info->xmit_buf) - return; - - save_and_cli(flags); - dz_start (info->tty); - restore_flags(flags); -} - - -/* - * ------------------------------------------------------------------- - * dz_write () - * - * main output routine. - * ------------------------------------------------------------------- - */ -static int dz_write (struct tty_struct *tty, int from_user, - const unsigned char *buf, int count) -{ - struct dz_serial *info = (struct dz_serial *)tty->driver_data; - unsigned long flags; - int c, ret = 0; - - if (!tty ) - return ret; - if (!info->xmit_buf) - return ret; - if (!tmp_buf) - tmp_buf = tmp_buffer; - - if (from_user) { - down (&tmp_buf_sem); - while (1) { - c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, - DZ_XMIT_SIZE - info->xmit_head)); - if (c <= 0) - break; - - c -= copy_from_user (tmp_buf, buf, c); - if (!c) { - if (!ret) - ret = -EFAULT; - break; - } - - save_and_cli(flags); - - c = MIN(c, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, - DZ_XMIT_SIZE - info->xmit_head)); - memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); - info->xmit_head = ((info->xmit_head + c) & - (DZ_XMIT_SIZE - 1)); - info->xmit_cnt += c; - restore_flags(flags); - - buf += c; - count -= c; - ret += c; - } - up(&tmp_buf_sem); - } else { - while (1) { - save_and_cli(flags); - - c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, - DZ_XMIT_SIZE - info->xmit_head)); - if (c <= 0) { - restore_flags (flags); - break; - } - memcpy(info->xmit_buf + info->xmit_head, buf, c); - info->xmit_head = ((info->xmit_head + c) & - (DZ_XMIT_SIZE-1)); - info->xmit_cnt += c; - restore_flags(flags); - - buf += c; - count -= c; - ret += c; - } - } - - if (info->xmit_cnt) { - if (!tty->stopped) { - if (!tty->hw_stopped) { - dz_start (info->tty); - } - } - } - - return ret; -} - -/* - * ------------------------------------------------------------------- - * dz_write_room () - * - * compute the amount of space available for writing. - * ------------------------------------------------------------------- - */ -static int dz_write_room (struct tty_struct *tty) -{ - struct dz_serial *info = (struct dz_serial *)tty->driver_data; - int ret; - - ret = DZ_XMIT_SIZE - info->xmit_cnt - 1; - if (ret < 0) - ret = 0; - - return ret; -} - -/* - * ------------------------------------------------------------------- - * dz_chars_in_buffer () - * - * compute the amount of char left to be transmitted - * ------------------------------------------------------------------- - */ -static int dz_chars_in_buffer (struct tty_struct *tty) -{ - struct dz_serial *info = (struct dz_serial *)tty->driver_data; - - return info->xmit_cnt; -} - -/* - * ------------------------------------------------------------------- - * dz_flush_buffer () - * - * Empty the output buffer - * ------------------------------------------------------------------- - */ -static void dz_flush_buffer (struct tty_struct *tty) -{ - struct dz_serial *info = (struct dz_serial *)tty->driver_data; - - cli(); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - sti(); - - wake_up_interruptible (&tty->write_wait); - - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - tty->ldisc.write_wakeup(tty); -} - -/* - * ------------------------------------------------------------ - * dz_throttle () and dz_unthrottle () - * - * This routine is called by the upper-layer tty layer to signal that - * incoming characters should be throttled (or not). - * ------------------------------------------------------------ - */ -static void dz_throttle (struct tty_struct *tty) -{ - struct dz_serial *info = (struct dz_serial *)tty->driver_data; - - if (I_IXOFF(tty)) - info->x_char = STOP_CHAR(tty); -} - -static void dz_unthrottle (struct tty_struct *tty) -{ - struct dz_serial *info = (struct dz_serial *)tty->driver_data; - - if (I_IXOFF(tty)) { - if (info->x_char) - info->x_char = 0; - else - info->x_char = START_CHAR(tty); - } -} - -static void dz_send_xchar (struct tty_struct *tty, char ch) -{ - struct dz_serial *info = (struct dz_serial *)tty->driver_data; - - info->x_char = ch; - - if (ch) - dz_start(info->tty); -} - -/* - * ------------------------------------------------------------ - * rs_ioctl () and friends - * ------------------------------------------------------------ - */ -static int get_serial_info(struct dz_serial *info, - struct serial_struct *retinfo) -{ - struct serial_struct tmp; - - if (!retinfo) - return -EFAULT; - - memset (&tmp, 0, sizeof(tmp)); - - tmp.type = info->type; - tmp.line = info->line; - tmp.port = info->port; - tmp.irq = SERIAL; - tmp.flags = info->flags; - tmp.baud_base = info->baud_base; - tmp.close_delay = info->close_delay; - tmp.closing_wait = info->closing_wait; - - return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0; -} - -static int set_serial_info (struct dz_serial *info, - struct serial_struct *new_info) -{ - struct serial_struct new_serial; - struct dz_serial old_info; - int retval = 0; - - if (!new_info) - return -EFAULT; - - if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) - return -EFAULT; - - old_info = *info; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - if (info->count > 1) - return -EBUSY; - - /* - * OK, past this point, all the error checking has been done. - * At this point, we start making changes..... - */ - - info->baud_base = new_serial.baud_base; - info->type = new_serial.type; - info->close_delay = new_serial.close_delay; - info->closing_wait = new_serial.closing_wait; - - retval = startup(info); - - return retval; -} - -/* - * get_lsr_info - get line status register info - * - * Purpose: Let user call ioctl() to get info when the UART physically - * is emptied. On bus types like RS485, the transmitter must - * release the bus after transmitting. This must be done when - * the transmit shift register is empty, not be done when the - * transmit holding register is empty. This functionality - * allows an RS485 driver to be written in user space. - */ -static int get_lsr_info (struct dz_serial *info, unsigned int *value) -{ - unsigned short status = dz_in (info, DZ_LPR); - - return put_user (status, value); -} - -/* - * This routine sends a break character out the serial port. - */ -static void send_break (struct dz_serial *info, int duration) -{ - unsigned long flags; - unsigned short tmp, mask; - - if (!info->port) - return; - - mask = 1 << info->line; - tmp = dz_in (info, DZ_TCR); - tmp |= mask; - - current->state = TASK_INTERRUPTIBLE; - - save_and_cli(flags); - dz_out(info, DZ_TCR, tmp); - schedule_timeout(duration); - tmp &= ~mask; - dz_out(info, DZ_TCR, tmp); - restore_flags(flags); -} - -static int dz_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int error; - struct dz_serial * info = (struct dz_serial *)tty->driver_data; - int retval; - - if (cmd != TIOCGSERIAL && cmd != TIOCSSERIAL && - cmd != TIOCSERCONFIG && cmd != TIOCSERGWILD && - cmd != TIOCSERSWILD && cmd != TIOCSERGSTRUCT) { - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - } - - switch (cmd) { - case TCSBRK: /* SVID version: non-zero arg --> no break */ - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - if (!arg) - send_break(info, HZ/4); /* 1/4 second */ - return 0; - - case TCSBRKP: /* support for POSIX tcsendbreak() */ - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - send_break(info, arg ? arg*(HZ/10) : HZ/4); - return 0; - - case TIOCGSOFTCAR: - return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *)arg); - - case TIOCSSOFTCAR: - if (get_user (arg, (unsigned long *)arg)) - return -EFAULT; - - tty->termios->c_cflag = (tty->termios->c_cflag & ~CLOCAL) | - (arg ? CLOCAL : 0); - return 0; - - case TIOCGSERIAL: - return get_serial_info(info, (struct serial_struct *)arg); - - case TIOCSSERIAL: - return set_serial_info(info, (struct serial_struct *) arg); - - case TIOCSERGETLSR: /* Get line status register */ - return get_lsr_info (info, (unsigned int *)arg); - - case TIOCSERGSTRUCT: - return copy_to_user((struct dz_serial *)arg, info, - sizeof(struct dz_serial)) ? -EFAULT : 0; - - default: - return -ENOIOCTLCMD; - } - - return 0; -} - -static void dz_set_termios (struct tty_struct *tty, - struct termios *old_termios) -{ - struct dz_serial *info = (struct dz_serial *)tty->driver_data; - - if (tty->termios->c_cflag == old_termios->c_cflag) - return; - - change_speed (info); - - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios->c_cflag & CRTSCTS)) { - tty->hw_stopped = 0; - dz_start(tty); - } -} - -/* - * ------------------------------------------------------------ - * dz_close() - * - * This routine is called when the serial port gets closed. First, we - * wait for the last remaining data to be sent. Then, we turn off - * the transmit enable and receive enable flags. - * ------------------------------------------------------------ - */ -static void dz_close(struct tty_struct *tty, struct file *filp) -{ - struct dz_serial * info = (struct dz_serial *)tty->driver_data; - unsigned long flags; - - if (!info) - return; - - save_and_cli(flags); - - if (tty_hung_up_p(filp)) { - restore_flags(flags); - return; - } - - if ((tty->count == 1) && (info->count != 1)) { - /* - * Uh, oh. tty->count is 1, which means that the tty structure - * will be freed. Info->count should always be one in these - * conditions. If it's greater than one, we've got real - * problems, since it means the serial port won't be shutdown. - */ - printk("dz_close: bad serial port count; tty->count is 1, " - "info->count is %d\n", info->count); - info->count = 1; - } - - if (--info->count < 0) { - printk("ds_close: bad serial port count for ttyS%02d: %d\n", - info->line, info->count); - info->count = 0; - } - - if (info->count) { - restore_flags(flags); - return; - } - info->flags |= DZ_CLOSING; - /* - * Now we wait for the transmit buffer to clear; and we notify the line - * discipline to only process XON/XOFF characters. - */ - tty->closing = 1; - - if (info->closing_wait != DZ_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, info->closing_wait); - - /* - * At this point we stop accepting input. To do this, we disable the - * receive line status interrupts. - */ - shutdown(info); - - if (tty->driver->flush_buffer) - tty->driver->flush_buffer (tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer (tty); - tty->closing = 0; - info->event = 0; - info->tty = 0; - - if (tty->ldisc.num != ldiscs[N_TTY].num) { - if (tty->ldisc.close) - tty->ldisc.close(tty); - tty->ldisc = ldiscs[N_TTY]; - tty->termios->c_line = N_TTY; - if (tty->ldisc.open) - tty->ldisc.open(tty); - } - if (info->blocked_open) { - if (info->close_delay) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(info->close_delay); - } - wake_up_interruptible(&info->open_wait); - } - - info->flags &= ~(DZ_NORMAL_ACTIVE | DZ_CLOSING); - wake_up_interruptible(&info->close_wait); - - restore_flags(flags); -} - -/* - * dz_hangup () --- called by tty_hangup() when a hangup is signaled. - */ -static void dz_hangup (struct tty_struct *tty) -{ - struct dz_serial *info = (struct dz_serial *) tty->driver_data; - - dz_flush_buffer(tty); - shutdown(info); - info->event = 0; - info->count = 0; - info->flags &= ~DZ_NORMAL_ACTIVE; - info->tty = 0; - wake_up_interruptible(&info->open_wait); -} - -/* - * ------------------------------------------------------------ - * rs_open() and friends - * ------------------------------------------------------------ - */ -static int block_til_ready(struct tty_struct *tty, struct file *filp, - struct dz_serial *info) -{ - DECLARE_WAITQUEUE(wait, current); - int retval; - int do_clocal = 0; - - /* - * If the device is in the middle of being closed, then block - * until it's done, and then try again. - */ - if (info->flags & DZ_CLOSING) { - interruptible_sleep_on(&info->close_wait); - return -EAGAIN; - } - - /* - * If non-blocking mode is set, or the port is not enabled, then make - * the check up front and then exit. - */ - if ((filp->f_flags & O_NONBLOCK) || - (tty->flags & (1 << TTY_IO_ERROR))) { - info->flags |= DZ_NORMAL_ACTIVE; - - return 0; - } - - if (tty->termios->c_cflag & CLOCAL) - do_clocal = 1; - - /* - * Block waiting for the carrier detect and the line to become free - * (i.e., not in use by the callout). While we are in this loop, - * info->count is dropped by one, so that dz_close() knows when to free - * things. We restore it upon exit, either normal or abnormal. - */ - retval = 0; - add_wait_queue(&info->open_wait, &wait); - - info->count--; - info->blocked_open++; - while (1) { - set_current_state(TASK_INTERRUPTIBLE); - if (tty_hung_up_p (filp) || !(info->is_initialized)) { - retval = -EAGAIN; - break; - } - if (!(info->flags & DZ_CLOSING) && do_clocal) - break; - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - schedule(); - } - - current->state = TASK_RUNNING; - remove_wait_queue (&info->open_wait, &wait); - if (!tty_hung_up_p(filp)) - info->count++; - info->blocked_open--; - - if (retval) - return retval; - info->flags |= DZ_NORMAL_ACTIVE; - return 0; -} - -/* - * This routine is called whenever a serial port is opened. It - * enables interrupts for a serial port. It also performs the - * serial-specific initialization for the tty structure. - */ -static int dz_open (struct tty_struct *tty, struct file *filp) -{ - struct dz_serial *info; - int retval, line; - - line = tty->index; - - /* - * The dz lines for the mouse/keyboard must be opened using their - * respective drivers. - */ - if ((line < 0) || (line >= DZ_NB_PORT)) - return -ENODEV; - - if ((line == DZ_KEYBOARD) || (line == DZ_MOUSE)) - return -ENODEV; - - info = lines[line]; - info->count++; - - tty->driver_data = info; - info->tty = tty; - - /* - * Start up serial port - */ - retval = startup (info); - if (retval) - return retval; - - retval = block_til_ready (tty, filp, info); - if (retval) - return retval; - - return 0; -} - -static void show_serial_version (void) -{ - printk("%s%s\n", dz_name, dz_version); -} - -static struct tty_driver *serial_driver; - -static struct tty_operations serial_ops = { - .open = dz_open, - .close = dz_close, - .write = dz_write, - .flush_chars = dz_flush_chars, - .write_room = dz_write_room, - .chars_in_buffer = dz_chars_in_buffer, - .flush_buffer = dz_flush_buffer, - .ioctl = dz_ioctl, - .throttle = dz_throttle, - .unthrottle = dz_unthrottle, - .send_xchar = dz_send_xchar, - .set_termios = dz_set_termios, - .stop = dz_stop, - .start = dz_start, - .hangup = dz_hangup, -}; - -int __init dz_init(void) -{ - int i, flags; - struct dz_serial *info; - - serial_driver = alloc_tty_driver(DZ_NB_PORT); - if (!serial_driver) - return -ENOMEM; - - /* Setup base handler, and timer table. */ - init_bh(SERIAL_BH, do_serial_bh); - - show_serial_version(); - - serial_driver->owner = THIS_MODULE; - serial_driver->devfs_name = "tts/"; - serial_driver->name = "ttyS"; - serial_driver->major = TTY_MAJOR; - serial_driver->minor_start = 64; - serial_driver->type = TTY_DRIVER_TYPE_SERIAL; - serial_driver->subtype = SERIAL_TYPE_NORMAL; - serial_driver->init_termios = tty_std_termios; - serial_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | - CLOCAL; - serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS; - tty_set_operations(serial_driver, &serial_ops); - - if (tty_register_driver(serial_driver)) - panic("Couldn't register serial driver\n"); - - save_flags(flags); cli(); - for (i=0; i < DZ_NB_PORT; i++) { - info = &multi[i]; - lines[i] = info; - info->magic = SERIAL_MAGIC; - - if ((mips_machtype == MACH_DS23100) || - (mips_machtype == MACH_DS5100)) - info->port = (unsigned long) KN01_DZ11_BASE; - else - info->port = (unsigned long) KN02_DZ11_BASE; - - info->line = i; - info->tty = 0; - info->close_delay = 50; - info->closing_wait = 3000; - info->x_char = 0; - info->event = 0; - info->count = 0; - info->blocked_open = 0; - info->tqueue.routine = do_softint; - info->tqueue.data = info; - info->tqueue_hangup.routine = do_serial_hangup; - info->tqueue_hangup.data = info; - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); - - /* - * If we are pointing to address zero then punt - not correctly - * set up in setup.c to handle this. - */ - if (! info->port) - return 0; - - printk("ttyS%02d at 0x%08x (irq = %d)\n", info->line, - info->port, SERIAL); - - tty_register_device(serial_driver, info->line, NULL); - } - - /* Reset the chip */ -#ifndef CONFIG_SERIAL_CONSOLE - { - int tmp; - dz_out(info, DZ_CSR, DZ_CLR); - while ((tmp = dz_in(info,DZ_CSR)) & DZ_CLR); - wbflush(); - - /* Enable scanning */ - dz_out(info, DZ_CSR, DZ_MSE); - } -#endif - - /* - * Order matters here... the trick is that flags is updated... in - * request_irq - to immediatedly obliterate it is unwise. - */ - restore_flags(flags); - - if (request_irq(SERIAL, dz_interrupt, SA_INTERRUPT, "DZ", lines[0])) - panic("Unable to register DZ interrupt\n"); - - return 0; -} - -#ifdef CONFIG_SERIAL_CONSOLE -static void dz_console_put_char (unsigned char ch) -{ - unsigned long flags; - int loops = 2500; - unsigned short tmp = ch; - /* - * this code sends stuff out to serial device - spinning its wheels and - * waiting. - */ - - /* force the issue - point it at lines[3]*/ - dz_console = &multi[CONSOLE_LINE]; - - save_and_cli(flags); - - /* spin our wheels */ - while (((dz_in(dz_console, DZ_CSR) & DZ_TRDY) != DZ_TRDY) && loops--) - ; - - /* Actually transmit the character. */ - dz_out(dz_console, DZ_TDR, tmp); - - restore_flags(flags); -} - -/* - * ------------------------------------------------------------------- - * dz_console_print () - * - * dz_console_print is registered for printk. - * The console must be locked when we get here. - * ------------------------------------------------------------------- - */ -static void dz_console_print (struct console *cons, - const char *str, - unsigned int count) -{ -#ifdef DEBUG_DZ - prom_printf((char *)str); -#endif - while (count--) { - if (*str == '\n') - dz_console_put_char('\r'); - dz_console_put_char(*str++); - } -} - -static struct tty_driver *dz_console_device(struct console *c, int *index) -{ - *index = c->index; - return serial_driver; -} - -static int __init dz_console_setup(struct console *co, char *options) -{ - int baud = 9600; - int bits = 8; - int parity = 'n'; - int cflag = CREAD | HUPCL | CLOCAL; - char *s; - unsigned short mask,tmp; - - if (options) { - baud = simple_strtoul(options, NULL, 10); - s = options; - while (*s >= '0' && *s <= '9') - s++; - if (*s) - parity = *s++; - if (*s) - bits = *s - '0'; - } - - /* - * Now construct a cflag setting. - */ - switch (baud) { - case 1200: - cflag |= DZ_B1200; - break; - case 2400: - cflag |= DZ_B2400; - break; - case 4800: - cflag |= DZ_B4800; - break; - case 9600: - default: - cflag |= DZ_B9600; - break; - } - switch (bits) { - case 7: - cflag |= DZ_CS7; - break; - default: - case 8: - cflag |= DZ_CS8; - break; - } - switch (parity) { - case 'o': - case 'O': - cflag |= DZ_PARODD; - break; - case 'e': - case 'E': - cflag |= DZ_PARENB; - break; - } - co->cflag = cflag; - - /* TOFIX: force to console line */ - dz_console = &multi[CONSOLE_LINE]; - if ((mips_machtype == MACH_DS23100) || (mips_machtype == MACH_DS5100)) - dz_console->port = KN01_DZ11_BASE; - else - dz_console->port = KN02_DZ11_BASE; - dz_console->line = CONSOLE_LINE; - - dz_out(dz_console, DZ_CSR, DZ_CLR); - while ((tmp = dz_in(dz_console,DZ_CSR)) & DZ_CLR) - ; - - /* enable scanning */ - dz_out(dz_console, DZ_CSR, DZ_MSE); - - /* Set up flags... */ - dz_console->cflags = 0; - dz_console->cflags |= DZ_B9600; - dz_console->cflags |= DZ_CS8; - dz_console->cflags |= DZ_PARENB; - dz_out(dz_console, DZ_LPR, dz_console->cflags); - - mask = 1 << dz_console->line; - tmp = dz_in (dz_console, DZ_TCR); /* read the TX flag */ - if (!(tmp & mask)) { - tmp |= mask; /* set the TX flag */ - dz_out (dz_console, DZ_TCR, tmp); - } - - return 0; -} - -static struct console dz_sercons = { - .name = "ttyS", - .write = dz_console_print, - .device = dz_console_device, - .setup = dz_console_setup, - .flags = CON_CONSDEV | CON_PRINTBUFFER, - .index = CONSOLE_LINE, -}; - -void __init dz_serial_console_init(void) -{ - register_console(&dz_sercons); -} - -#endif /* ifdef CONFIG_SERIAL_CONSOLE */ - -MODULE_LICENSE("GPL"); --- linux-2.6.6/drivers/char/dz.h 2003-06-14 12:18:01.000000000 -0700 +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,230 +0,0 @@ -/* - * dz.h: Serial port driver for DECStations equiped - * with the DZ chipset. - * - * Copyright (C) 1998 Olivier A. D. Lebaillif - * - * Email: olivier.lebaillif@ifrsys.com - * - */ -#ifndef DZ_SERIAL_H -#define DZ_SERIAL_H - -/* - * Definitions for the Control and Status Received. - */ -#define DZ_TRDY 0x8000 /* Transmitter empty */ -#define DZ_TIE 0x4000 /* Transmitter Interrupt Enable */ -#define DZ_RDONE 0x0080 /* Receiver data ready */ -#define DZ_RIE 0x0040 /* Receive Interrupt Enable */ -#define DZ_MSE 0x0020 /* Master Scan Enable */ -#define DZ_CLR 0x0010 /* Master reset */ -#define DZ_MAINT 0x0008 /* Loop Back Mode */ - -/* - * Definitions for the Received buffer. - */ -#define DZ_RBUF_MASK 0x00FF /* Data Mask in the Receive Buffer */ -#define DZ_LINE_MASK 0x0300 /* Line Mask in the Receive Buffer */ -#define DZ_DVAL 0x8000 /* Valid Data indicator */ -#define DZ_OERR 0x4000 /* Overrun error indicator */ -#define DZ_FERR 0x2000 /* Frame error indicator */ -#define DZ_PERR 0x1000 /* Parity error indicator */ - -#define LINE(x) (x & DZ_LINE_MASK) >> 8 /* Get the line number from the input buffer */ -#define UCHAR(x) (unsigned char)(x & DZ_RBUF_MASK) - -/* - * Definitions for the Transmit Register. - */ -#define DZ_LINE_KEYBOARD 0x0001 -#define DZ_LINE_MOUSE 0x0002 -#define DZ_LINE_MODEM 0x0004 -#define DZ_LINE_PRINTER 0x0008 - -#define DZ_MODEM_DTR 0x0400 /* DTR for the modem line (2) */ - -/* - * Definitions for the Modem Status Register. - */ -#define DZ_MODEM_DSR 0x0200 /* DSR for the modem line (2) */ - -/* - * Definitions for the Transmit Data Register. - */ -#define DZ_BRK0 0x0100 /* Break assertion for line 0 */ -#define DZ_BRK1 0x0200 /* Break assertion for line 1 */ -#define DZ_BRK2 0x0400 /* Break assertion for line 2 */ -#define DZ_BRK3 0x0800 /* Break assertion for line 3 */ - -/* - * Definitions for the Line Parameter Register. - */ -#define DZ_KEYBOARD 0x0000 /* line 0 = keyboard */ -#define DZ_MOUSE 0x0001 /* line 1 = mouse */ -#define DZ_MODEM 0x0002 /* line 2 = modem */ -#define DZ_PRINTER 0x0003 /* line 3 = printer */ - -#define DZ_CSIZE 0x0018 /* Number of bits per byte (mask) */ -#define DZ_CS5 0x0000 /* 5 bits per byte */ -#define DZ_CS6 0x0008 /* 6 bits per byte */ -#define DZ_CS7 0x0010 /* 7 bits per byte */ -#define DZ_CS8 0x0018 /* 8 bits per byte */ - -#define DZ_CSTOPB 0x0020 /* 2 stop bits instead of one */ - -#define DZ_PARENB 0x0040 /* Parity enable */ -#define DZ_PARODD 0x0080 /* Odd parity instead of even */ - -#define DZ_CBAUD 0x0E00 /* Baud Rate (mask) */ -#define DZ_B50 0x0000 -#define DZ_B75 0x0100 -#define DZ_B110 0x0200 -#define DZ_B134 0x0300 -#define DZ_B150 0x0400 -#define DZ_B300 0x0500 -#define DZ_B600 0x0600 -#define DZ_B1200 0x0700 -#define DZ_B1800 0x0800 -#define DZ_B2000 0x0900 -#define DZ_B2400 0x0A00 -#define DZ_B3600 0x0B00 -#define DZ_B4800 0x0C00 -#define DZ_B7200 0x0D00 -#define DZ_B9600 0x0E00 - -#define DZ_CREAD 0x1000 /* Enable receiver */ -#define DZ_RXENAB 0x1000 /* enable receive char */ -/* - * Addresses for the DZ registers - */ -#define DZ_CSR 0x00 /* Control and Status Register */ -#define DZ_RBUF 0x08 /* Receive Buffer */ -#define DZ_LPR 0x08 /* Line Parameters Register */ -#define DZ_TCR 0x10 /* Transmitter Control Register */ -#define DZ_MSR 0x18 /* Modem Status Register */ -#define DZ_TDR 0x18 /* Transmit Data Register */ - - -#define DZ_NB_PORT 4 - -#define DZ_XMIT_SIZE 4096 /* buffer size */ -#define WAKEUP_CHARS DZ_XMIT_SIZE/4 - -#define DZ_EVENT_WRITE_WAKEUP 0 - -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) - -#define DZ_INITIALIZED 0x80000000 /* Serial port was initialized */ -#define DZ_CALLOUT_ACTIVE 0x40000000 /* Call out device is active */ -#define DZ_NORMAL_ACTIVE 0x20000000 /* Normal device is active */ -#define DZ_BOOT_AUTOCONF 0x10000000 /* Autoconfigure port on bootup */ -#define DZ_CLOSING 0x08000000 /* Serial port is closing */ -#define DZ_CTS_FLOW 0x04000000 /* Do CTS flow control */ -#define DZ_CHECK_CD 0x02000000 /* i.e., CLOCAL */ - -#define DZ_CLOSING_WAIT_INF 0 -#define DZ_CLOSING_WAIT_NONE 65535 - -#define DZ_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */ -#define DZ_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */ -#define DZ_PGRP_LOCKOUT 0x0200 /* Lock out cua opens based on pgrp */ - -struct dz_serial { - unsigned port; /* base address for the port */ - int type; - int flags; - int baud_base; - int blocked_open; - unsigned short close_delay; - unsigned short closing_wait; - unsigned short line; /* port/line number */ - unsigned short cflags; /* line configuration flag */ - unsigned short x_char; /* xon/xoff character */ - unsigned short read_status_mask; /* mask for read condition */ - unsigned short ignore_status_mask; /* mask for ignore condition */ - unsigned long event; /* mask used in BH */ - unsigned char *xmit_buf; /* Transmit buffer */ - int xmit_head; /* Position of the head */ - int xmit_tail; /* Position of the tail */ - int xmit_cnt; /* Count of the chars in the buffer */ - int count; /* indicates how many times it has been opened */ - int magic; - - struct async_icount icount; /* keep track of things ... */ - struct tty_struct *tty; /* tty associated */ - struct tq_struct tqueue; /* Queue for BH */ - struct tq_struct tqueue_hangup; - wait_queue_head_t open_wait; - wait_queue_head_t close_wait; - - unsigned char is_console; /* flag indicating a serial console */ - unsigned char is_initialized; -}; - -static struct dz_serial multi[DZ_NB_PORT]; /* Four serial lines in the DZ chip */ -static struct dz_serial *dz_console; - -/* - * tmp_buf is used as a temporary buffer by serial_write. We need to - * lock it in case the copy_from_user blocks while swapping in a page, - * and some other program tries to do a serial write at the same time. - * Since the lock will only come under contention when the system is - * swapping and available memory is low, it makes sense to share one - * buffer across all the serial ports, since it significantly saves - * memory if large numbers of serial ports are open. - */ -static unsigned char *tmp_buf; -static DECLARE_MUTEX(tmp_buf_sem); - -static char *dz_name = "DECstation DZ serial driver version "; -static char *dz_version = "1.02"; - -static inline unsigned short dz_in (struct dz_serial *, unsigned); -static inline void dz_out (struct dz_serial *, unsigned, unsigned short); - -static inline void dz_sched_event (struct dz_serial *, int); -static inline void receive_chars (struct dz_serial *); -static inline void transmit_chars (struct dz_serial *); -static inline void check_modem_status (struct dz_serial *); - -static void dz_stop (struct tty_struct *); -static void dz_start (struct tty_struct *); -static void dz_interrupt (int, void *, struct pt_regs *); -static void do_serial_bh (void); -static void do_softint (void *); -static void do_serial_hangup (void *); -static void change_speed (struct dz_serial *); -static void dz_flush_chars (struct tty_struct *); -static void dz_console_print (struct console *, const char *, unsigned int); -static void dz_flush_buffer (struct tty_struct *); -static void dz_throttle (struct tty_struct *); -static void dz_unthrottle (struct tty_struct *); -static void dz_send_xchar (struct tty_struct *, char); -static void shutdown (struct dz_serial *); -static void send_break (struct dz_serial *, int); -static void dz_set_termios (struct tty_struct *, struct termios *); -static void dz_close (struct tty_struct *, struct file *); -static void dz_hangup (struct tty_struct *); -static void show_serial_version (void); - -static int dz_write (struct tty_struct *, int, const unsigned char *, int); -static int dz_write_room (struct tty_struct *); -static int dz_chars_in_buffer (struct tty_struct *); -static int startup (struct dz_serial *); -static int get_serial_info (struct dz_serial *, struct serial_struct *); -static int set_serial_info (struct dz_serial *, struct serial_struct *); -static int get_lsr_info (struct dz_serial *, unsigned int *); -static int dz_ioctl (struct tty_struct *, struct file *, unsigned int, unsigned long); -static int block_til_ready (struct tty_struct *, struct file *, struct dz_serial *); -static int dz_open (struct tty_struct *, struct file *); - -#ifdef MODULE -int init_module (void) -void cleanup_module (void) -#endif - -#endif - -#endif /* DZ_SERIAL_H */ --- linux-2.6.6/drivers/char/ip2main.c 2004-03-10 20:41:27.000000000 -0800 +++ 25/drivers/char/ip2main.c 2004-05-10 01:19:02.083422328 -0700 @@ -99,6 +99,7 @@ #include #include #include +#include #include #include @@ -301,6 +302,9 @@ static int iindx; static char rirqs[IP2_MAX_BOARDS]; static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0}; +/* for sysfs class support */ +static struct class_simple *ip2_class; + // Some functions to keep track of what irq's we have static int __init @@ -411,7 +415,9 @@ cleanup_module(void) iiResetDelay( i2BoardPtrTable[i] ); /* free io addresses and Tibet */ release_region( ip2config.addr[i], 8 ); + class_simple_device_remove(MKDEV(IP2_IPL_MAJOR, 4 * i)); devfs_remove("ip2/ipl%d", i); + class_simple_device_remove(MKDEV(IP2_IPL_MAJOR, 4 * i + 1)); devfs_remove("ip2/stat%d", i); } /* Disable and remove interrupt handler. */ @@ -420,6 +426,7 @@ cleanup_module(void) clear_requested_irq( ip2config.irq[i]); } } + class_simple_destroy(ip2_class); devfs_remove("ip2"); if ( ( err = tty_unregister_driver ( ip2_tty_driver ) ) ) { printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", err); @@ -494,7 +501,7 @@ int ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize) { int i, j, box; - int err; + int err = 0; int status = 0; static int loaded; i2eBordStrPtr pB = NULL; @@ -683,7 +690,14 @@ ip2_loadmain(int *iop, int *irqp, unsign /* Register the IPL driver. */ if ( ( err = register_chrdev ( IP2_IPL_MAJOR, pcIpl, &ip2_ipl ) ) ) { printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", err ); - } else + } else { + /* create the sysfs class */ + ip2_class = class_simple_create(THIS_MODULE, "ip2"); + if (IS_ERR(ip2_class)) { + err = PTR_ERR(ip2_class); + goto out_chrdev; + } + } /* Register the read_procmem thing */ if (!create_proc_info_entry("ip2mem",0,&proc_root,ip2_read_procmem)) { printk(KERN_ERR "IP2: failed to register read_procmem\n"); @@ -700,13 +714,27 @@ ip2_loadmain(int *iop, int *irqp, unsign } if ( NULL != ( pB = i2BoardPtrTable[i] ) ) { - devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i), + class_simple_device_add(ip2_class, MKDEV(IP2_IPL_MAJOR, + 4 * i), NULL, "ipl%d", i); + err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i), S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR, "ip2/ipl%d", i); + if (err) { + class_simple_device_remove(MKDEV(IP2_IPL_MAJOR, + 4 * i)); + goto out_class; + } - devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i + 1), + class_simple_device_add(ip2_class, MKDEV(IP2_IPL_MAJOR, + 4 * i + 1), NULL, "stat%d", i); + err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i + 1), S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR, "ip2/stat%d", i); + if (err) { + class_simple_device_remove(MKDEV(IP2_IPL_MAJOR, + 4 * i + 1)); + goto out_class; + } for ( box = 0; box < ABS_MAX_BOXES; ++box ) { @@ -759,8 +787,14 @@ retry: } } ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0 ); + goto out; - return 0; +out_class: + class_simple_destroy(ip2_class); +out_chrdev: + unregister_chrdev(IP2_IPL_MAJOR, "ip2"); +out: + return err; } EXPORT_SYMBOL(ip2_loadmain); --- linux-2.6.6/drivers/char/Kconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/char/Kconfig 2004-05-10 01:19:51.160961408 -0700 @@ -112,15 +112,13 @@ config CYCLADES tristate "Cyclades async mux support" depends on SERIAL_NONSTANDARD ---help--- - This is a driver for a card that gives you many serial ports. You - would need something like this to connect more than two modems to + This driver supports Cyclades Z and Y multiserial boards. + You would need something like this to connect more than two modems to your Linux box, for instance in order to become a dial-in server. + For information about the Cyclades-Z card, read . - As of 1.3.9x kernels, this driver's minor numbers start at 0 instead - of 32. - To compile this driver as a module, choose M here: the module will be called cyclades. --- linux-2.6.6/drivers/char/keyboard.c 2004-02-17 20:48:42.000000000 -0800 +++ 25/drivers/char/keyboard.c 2004-05-10 01:19:06.886692120 -0700 @@ -1066,6 +1066,9 @@ void kbd_keycode(unsigned int keycode, i } if (sysrq_down && down && !rep) { handle_sysrq(kbd_sysrq_xlate[keycode], regs, tty); +#ifdef CONFIG_KGDB_SYSRQ + sysrq_down = 0; /* in case we miss the "up" event */ +#endif return; } #endif --- linux-2.6.6/drivers/char/Makefile 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/char/Makefile 2004-05-10 01:19:16.680203280 -0700 @@ -70,7 +70,6 @@ obj-$(CONFIG_QIC02_TAPE) += tpqic02.o obj-$(CONFIG_FTAPE) += ftape/ obj-$(CONFIG_H8) += h8.o obj-$(CONFIG_PPDEV) += ppdev.o -obj-$(CONFIG_DZ) += dz.o obj-$(CONFIG_NWBUTTON) += nwbutton.o obj-$(CONFIG_NWFLASH) += nwflash.o obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o --- linux-2.6.6/drivers/char/mem.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/char/mem.c 2004-05-10 01:19:35.623323488 -0700 @@ -26,7 +26,6 @@ #include #include -#include #ifdef CONFIG_IA64 # include @@ -39,6 +38,7 @@ extern void fbmem_init(void); extern void tapechar_init(void); #endif +#ifdef pgprot_noncached /* * Architectures vary in how they handle caching for addresses * outside of main memory. @@ -64,7 +64,8 @@ static inline int uncached_access(struct && addr >= __pa(high_memory); #elif defined(CONFIG_IA64) /* - * On ia64, we ignore O_SYNC because we cannot tolerate memory attribute aliases. + * On ia64, we ignore O_SYNC because we cannot tolerate memory + * attribute aliases. */ return !(efi_mem_attributes(addr) & EFI_MEMORY_WB); #elif defined(CONFIG_PPC64) @@ -77,14 +78,15 @@ static inline int uncached_access(struct return !page_is_ram(addr); #else /* - * Accessing memory above the top the kernel knows about or through a file pointer - * that was marked O_SYNC will be done non-cached. + * Accessing memory above the top the kernel knows about or through a + * file pointer that was marked O_SYNC will be done non-cached. */ if (file->f_flags & O_SYNC) return 1; return addr >= __pa(high_memory); #endif } +#endif #ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE static inline int valid_phys_addr_range(unsigned long addr, size_t *count) @@ -181,28 +183,24 @@ static ssize_t write_mem(struct file * f return do_write_mem(__va(p), p, buf, count, ppos); } -static int mmap_mem(struct file * file, struct vm_area_struct * vma) +static int mmap_mem(struct file *file, struct vm_area_struct *vma) { unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; - int uncached; - uncached = uncached_access(file, offset); #ifdef pgprot_noncached - if (uncached) + if (uncached_access(file, offset)) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); #endif - /* Don't try to swap out physical pages.. */ - vma->vm_flags |= VM_RESERVED; - /* - * Don't dump addresses that are not real memory to a core file. + * Don't try to swap out physical pages.. + * And treat /dev/mem mappings as "IO" regions: they may not + * describe valid pageframes. */ - if (uncached) - vma->vm_flags |= VM_IO; + vma->vm_flags |= VM_RESERVED|VM_IO; - if (remap_page_range(vma, vma->vm_start, offset, vma->vm_end-vma->vm_start, - vma->vm_page_prot)) + if (remap_page_range(vma, vma->vm_start, offset, + vma->vm_end-vma->vm_start, vma->vm_page_prot)) return -EAGAIN; return 0; } --- linux-2.6.6/drivers/char/ppdev.c 2004-01-09 00:04:31.000000000 -0800 +++ 25/drivers/char/ppdev.c 2004-05-10 01:19:02.084422176 -0700 @@ -59,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -739,6 +740,8 @@ static unsigned int pp_poll (struct file return mask; } +static struct class_simple *ppdev_class; + static struct file_operations pp_fops = { .owner = THIS_MODULE, .llseek = no_llseek, @@ -750,23 +753,59 @@ static struct file_operations pp_fops = .release = pp_release, }; +static void pp_attach(struct parport *port) +{ + class_simple_device_add(ppdev_class, MKDEV(PP_MAJOR, port->number), + NULL, "parport%d", port->number); +} + +static void pp_detach(struct parport *port) +{ + class_simple_device_remove(MKDEV(PP_MAJOR, port->number)); +} + +static struct parport_driver pp_driver = { + .name = CHRDEV, + .attach = pp_attach, + .detach = pp_detach, +}; + static int __init ppdev_init (void) { - int i; + int i, err = 0; if (register_chrdev (PP_MAJOR, CHRDEV, &pp_fops)) { printk (KERN_WARNING CHRDEV ": unable to get major %d\n", PP_MAJOR); return -EIO; } + ppdev_class = class_simple_create(THIS_MODULE, CHRDEV); + if (IS_ERR(ppdev_class)) { + err = PTR_ERR(ppdev_class); + goto out_chrdev; + } devfs_mk_dir("parports"); for (i = 0; i < PARPORT_MAX; i++) { devfs_mk_cdev(MKDEV(PP_MAJOR, i), S_IFCHR | S_IRUGO | S_IWUGO, "parports/%d", i); } + if (parport_register_driver(&pp_driver)) { + printk (KERN_WARNING CHRDEV ": unable to register with parport\n"); + goto out_class; + } printk (KERN_INFO PP_VERSION "\n"); - return 0; + goto out; + +out_class: + for (i = 0; i < PARPORT_MAX; i++) + devfs_remove("parports/%d", i); + devfs_remove("parports"); + class_simple_destroy(ppdev_class); +out_chrdev: + unregister_chrdev(PP_MAJOR, CHRDEV); +out: + return err; } static void __exit ppdev_cleanup (void) @@ -775,7 +814,9 @@ static void __exit ppdev_cleanup (void) /* Clean up all parport stuff */ for (i = 0; i < PARPORT_MAX; i++) devfs_remove("parports/%d", i); + parport_unregister_driver(&pp_driver); devfs_remove("parports"); + class_simple_destroy(ppdev_class); unregister_chrdev (PP_MAJOR, CHRDEV); } --- linux-2.6.6/drivers/char/sh-sci.c 2004-03-10 20:41:27.000000000 -0800 +++ 25/drivers/char/sh-sci.c 2004-05-10 01:19:01.793466408 -0700 @@ -1239,7 +1239,8 @@ static int sci_notifier(struct notifier_ struct cpufreq_freqs *freqs = p; int i; - if (phase == CPUFREQ_POSTCHANGE) { + if ((phase == CPUFREQ_POSTCHANGE) || + (phase == CPUFREQ_RESUMECHANGE)) { for (i = 0; i < SCI_NPORTS; i++) { /* * This will force a baud rate change in hardware. --- linux-2.6.6/drivers/char/sysrq.c 2004-02-03 20:42:35.000000000 -0800 +++ 25/drivers/char/sysrq.c 2004-05-10 01:19:06.886692120 -0700 @@ -35,6 +35,25 @@ #include #include +#ifdef CONFIG_KGDB_SYSRQ + +#define GDB_OP &kgdb_op +static void kgdb_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty) +{ + printk("kgdb sysrq\n"); + breakpoint(); +} + +static struct sysrq_key_op kgdb_op = { + .handler = kgdb_sysrq, + .help_msg = "kGdb|Fgdb", + .action_msg = "Debug breakpoint\n", +}; + +#else +#define GDB_OP NULL +#endif + extern void reset_vc(unsigned int); @@ -238,8 +257,8 @@ static struct sysrq_key_op *sysrq_key_ta /* c */ NULL, /* d */ NULL, /* e */ &sysrq_term_op, -/* f */ NULL, -/* g */ NULL, +/* f */ GDB_OP, +/* g */ GDB_OP, /* h */ NULL, /* i */ &sysrq_kill_op, /* j */ NULL, --- linux-2.6.6/drivers/char/tipar.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/char/tipar.c 2004-05-10 01:19:02.085422024 -0700 @@ -58,6 +58,7 @@ #include #include /* DevFs support */ #include /* Our code depend on parport */ +#include /* * TI definitions @@ -92,6 +93,8 @@ static int timeout = TIMAXTIME; /* timeo static unsigned int tp_count; /* tipar count */ static unsigned long opened; /* opened devices */ +static struct class_simple *tipar_class; + /* --- macros for parport access -------------------------------------- */ #define r_dtr(x) (parport_read_data(table[(x)].dev->port)) @@ -424,18 +427,26 @@ tipar_setup(char *str) static int tipar_register(int nr, struct parport *port) { + int err = 0; + /* Register our module into parport */ table[nr].dev = parport_register_device(port, "tipar", NULL, NULL, NULL, 0, (void *) &table[nr]); - if (table[nr].dev == NULL) - return 1; + if (table[nr].dev == NULL) { + err = 1; + goto out; + } + class_simple_device_add(tipar_class, MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr), + NULL, "par%d", nr); /* Use devfs, tree: /dev/ticables/par/[0..2] */ - devfs_mk_cdev(MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr), + err = devfs_mk_cdev(MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr), S_IFCHR | S_IRUGO | S_IWUGO, "ticables/par/%d", nr); + if (err) + goto out_class; /* Display informations */ printk(KERN_INFO "tipar%d: using %s (%s).\n", nr, port->name, @@ -447,7 +458,14 @@ tipar_register(int nr, struct parport *p else printk("tipar%d: link cable not found.\n", nr); - return 0; + err = 0; + goto out; + +out_class: + class_simple_device_remove(MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr)); + class_simple_destroy(tipar_class); +out: + return err; } static void @@ -477,23 +495,38 @@ static struct parport_driver tipar_drive int __init tipar_init_module(void) { + int err = 0; + printk("tipar: parallel link cable driver, version %s\n", DRIVER_VERSION); if (register_chrdev(TIPAR_MAJOR, "tipar", &tipar_fops)) { printk("tipar: unable to get major %d\n", TIPAR_MAJOR); - return -EIO; + err = -EIO; + goto out; } /* Use devfs with tree: /dev/ticables/par/[0..2] */ devfs_mk_dir("ticables/par"); + tipar_class = class_simple_create(THIS_MODULE, "ticables"); + if (IS_ERR(tipar_class)) { + err = PTR_ERR(tipar_class); + goto out_chrdev; + } if (parport_register_driver(&tipar_driver)) { printk("tipar: unable to register with parport\n"); - return -EIO; + err = -EIO; + goto out; } - return 0; + err = 0; + goto out; + +out_chrdev: + unregister_chrdev(TIPAR_MAJOR, "tipar"); +out: + return err; } void __exit @@ -510,8 +543,10 @@ tipar_cleanup_module(void) if (table[i].dev == NULL) continue; parport_unregister_device(table[i].dev); + class_simple_device_remove(MKDEV(TIPAR_MAJOR, i)); devfs_remove("ticables/par/%d", i); } + class_simple_destroy(tipar_class); devfs_remove("ticables/par"); printk("tipar: module unloaded !\n"); --- linux-2.6.6/drivers/char/tty_io.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/char/tty_io.c 2004-05-10 01:19:54.939387000 -0700 @@ -1267,6 +1267,18 @@ static void release_dev(struct file * fi #endif /* + * Prevent flush_to_ldisc() from rescheduling the work for later. Then + * kill any delayed work. + */ + clear_bit(TTY_DONT_FLIP, &tty->flags); + cancel_delayed_work(&tty->flip.work); + + /* + * Wait for ->hangup_work and ->flip.work handlers to terminate + */ + flush_scheduled_work(); + + /* * Shutdown the current line discipline, and reset it to N_TTY. * N.B. why reset ldisc when we're releasing the memory?? */ @@ -1282,18 +1294,6 @@ static void release_dev(struct file * fi module_put(o_tty->ldisc.owner); o_tty->ldisc = ldiscs[N_TTY]; } - - /* - * Prevent flush_to_ldisc() from rescheduling the work for later. Then - * kill any delayed work. - */ - clear_bit(TTY_DONT_FLIP, &tty->flags); - cancel_delayed_work(&tty->flip.work); - - /* - * Wait for ->hangup_work and ->flip.work handlers to terminate - */ - flush_scheduled_work(); /* * The release_mem function takes care of the details of clearing --- linux-2.6.6/drivers/char/vt.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/char/vt.c 2004-05-10 01:19:46.845617440 -0700 @@ -661,11 +661,14 @@ int vc_cons_allocated(unsigned int i) static void visual_init(int currcons, int init) { /* ++Geert: sw->con_init determines console size */ + if (sw) + module_put(sw->owner); sw = conswitchp; #ifndef VT_SINGLE_DRIVER if (con_driver_map[currcons]) sw = con_driver_map[currcons]; #endif + __module_get(sw->owner); cons_num = currcons; display_fg = &master_display_fg; vc_cons[currcons].d->vc_uni_pagedir_loc = &vc_cons[currcons].d->vc_uni_pagedir; @@ -2668,25 +2671,38 @@ static void clear_buffer_attributes(int * and become default driver for newly opened ones. */ -void take_over_console(const struct consw *csw, int first, int last, int deflt) +int take_over_console(const struct consw *csw, int first, int last, int deflt) { int i, j = -1; const char *desc; + struct module *owner; + + owner = csw->owner; + if (!try_module_get(owner)) + return -ENODEV; acquire_console_sem(); desc = csw->con_startup(); if (!desc) { release_console_sem(); - return; + module_put(owner); + return -ENODEV; } - if (deflt) + if (deflt) { + if (conswitchp) + module_put(conswitchp->owner); + __module_get(owner); conswitchp = csw; + } for (i = first; i <= last; i++) { int old_was_color; int currcons = i; + if (con_driver_map[i]) + module_put(con_driver_map[i]->owner); + __module_get(owner); con_driver_map[i] = csw; if (!vc_cons[i].d || !vc_cons[i].d->vc_sw) @@ -2721,6 +2737,9 @@ void take_over_console(const struct cons printk("to %s\n", desc); release_console_sem(); + + module_put(owner); + return 0; } void give_up_console(const struct consw *csw) @@ -2728,8 +2747,10 @@ void give_up_console(const struct consw int i; for(i = 0; i < MAX_NR_CONSOLES; i++) - if (con_driver_map[i] == csw) + if (con_driver_map[i] == csw) { + module_put(csw->owner); con_driver_map[i] = NULL; + } } #endif --- linux-2.6.6/drivers/cpufreq/cpufreq.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/cpufreq/cpufreq.c 2004-05-10 01:19:01.795466104 -0700 @@ -33,9 +33,10 @@ static struct cpufreq_driver *cpufreq static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS]; static spinlock_t cpufreq_driver_lock = SPIN_LOCK_UNLOCKED; -/* internal prototype */ +/* internal prototypes */ static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event); - +static void handle_update(void *data); +static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci); /** * Two notifier lists: the "policy" list is involved in the @@ -161,6 +162,7 @@ show_one(cpuinfo_min_freq, cpuinfo.min_f show_one(cpuinfo_max_freq, cpuinfo.max_freq); show_one(scaling_min_freq, min); show_one(scaling_max_freq, max); +show_one(scaling_cur_freq, cur); /** * cpufreq_per_cpu_attr_write() / store_##file_name() - sysfs write access @@ -189,6 +191,18 @@ store_one(scaling_min_freq,min); store_one(scaling_max_freq,max); /** + * show_cpuinfo_cur_freq - current CPU frequency as detected by hardware + */ +static ssize_t show_cpuinfo_cur_freq (struct cpufreq_policy * policy, char *buf) +{ + unsigned int cur_freq = cpufreq_get(policy->cpu); + if (!cur_freq) + return sprintf(buf, ""); + return sprintf(buf, "%u\n", cur_freq); +} + + +/** * show_scaling_governor - show the current policy for the specified CPU */ static ssize_t show_scaling_governor (struct cpufreq_policy * policy, char *buf) @@ -268,6 +282,12 @@ struct freq_attr _name = { \ .show = show_##_name, \ } +#define define_one_ro0400(_name) \ +struct freq_attr _name = { \ + .attr = { .name = __stringify(_name), .mode = 0400 }, \ + .show = show_##_name, \ +} + #define define_one_rw(_name) \ struct freq_attr _name = { \ .attr = { .name = __stringify(_name), .mode = 0644 }, \ @@ -275,10 +295,12 @@ struct freq_attr _name = { \ .store = store_##_name, \ } +define_one_ro0400(cpuinfo_cur_freq); define_one_ro(cpuinfo_min_freq); define_one_ro(cpuinfo_max_freq); define_one_ro(scaling_available_governors); define_one_ro(scaling_driver); +define_one_ro(scaling_cur_freq); define_one_rw(scaling_min_freq); define_one_rw(scaling_max_freq); define_one_rw(scaling_governor); @@ -369,6 +391,7 @@ static int cpufreq_add_dev (struct sys_d policy->cpu = cpu; init_MUTEX_LOCKED(&policy->lock); init_completion(&policy->kobj_unregister); + INIT_WORK(&policy->update, handle_update, (void *) cpu); /* call driver. From then on the cpufreq must be able * to accept all calls to ->verify and ->setpolicy for this CPU @@ -394,6 +417,10 @@ static int cpufreq_add_dev (struct sys_d sysfs_create_file(&policy->kobj, &((*drv_attr)->attr)); drv_attr++; } + if (cpufreq_driver->get) + sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr); + if (cpufreq_driver->target) + sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr); spin_lock_irqsave(&cpufreq_driver_lock, flags); cpufreq_cpu_data[cpu] = policy; @@ -474,11 +501,86 @@ static int cpufreq_remove_dev (struct sy return 0; } + +static void handle_update(void *data) +{ + unsigned int cpu = (unsigned int) data; + cpufreq_update_policy(cpu); +} + /** - * cpufreq_resume - restore the CPU clock frequency after resume + * cpufreq_out_of_sync - If actual and saved CPU frequency differs, we're in deep trouble. + * @cpu: cpu number + * @old_freq: CPU frequency the kernel thinks the CPU runs at + * @new_freq: CPU frequency the CPU actually runs at * - * Restore the CPU clock frequency so that our idea of the current - * frequency reflects the actual hardware. + * We adjust to current frequency first, and need to clean up later. So either call + * to cpufreq_update_policy() or schedule handle_update()). + */ +static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, unsigned int new_freq) +{ + struct cpufreq_freqs freqs; + + if (cpufreq_driver->flags & CPUFREQ_PANIC_OUTOFSYNC) + panic("CPU Frequency is out of sync."); + + printk(KERN_WARNING "Warning: CPU frequency out of sync: cpufreq and timing " + "core thinks of %u, is %u kHz.\n", old_freq, new_freq); + + freqs.cpu = cpu; + freqs.old = old_freq; + freqs.new = new_freq; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); +} + + +/** + * cpufreq_get - get the current CPU frequency (in kHz) + * @cpu: CPU number + * + * Get the CPU current (static) CPU frequency + */ +unsigned int cpufreq_get(unsigned int cpu) +{ + struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); + unsigned int ret = 0; + + if (!policy) + return 0; + + if (!cpufreq_driver->get) + goto out; + + down(&policy->lock); + + ret = cpufreq_driver->get(cpu); + + if (ret && policy->cur && !(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) + { + /* verify no discrepancy between actual and saved value exists */ + if (unlikely(ret != policy->cur)) { + cpufreq_out_of_sync(cpu, policy->cur, ret); + schedule_work(&policy->update); + } + } + + up(&policy->lock); + + out: + cpufreq_cpu_put(policy); + + return (ret); +} +EXPORT_SYMBOL(cpufreq_get); + + +/** + * cpufreq_resume - restore proper CPU frequency handling after resume + * + * 1.) resume CPUfreq hardware support (cpufreq_driver->resume()) + * 2.) if ->target and !CPUFREQ_CONST_LOOPS: verify we're in sync + * 3.) schedule call cpufreq_update_policy() ASAP as interrupts are restored. */ static int cpufreq_resume(struct sys_device * sysdev) { @@ -498,25 +600,37 @@ static int cpufreq_resume(struct sys_dev if (!cpu_policy) return -EINVAL; - if (cpufreq_driver->resume) - ret = cpufreq_driver->resume(cpu_policy); - if (ret) { - printk(KERN_ERR "cpufreq: resume failed in ->resume step on CPU %u\n", cpu_policy->cpu); - goto out; - } + if (!cpufreq_driver->flags & CPUFREQ_CONST_LOOPS) { + unsigned int cur_freq = 0; - if (cpufreq_driver->setpolicy) - ret = cpufreq_driver->setpolicy(cpu_policy); - else - /* CPUFREQ_RELATION_H or CPUFREQ_RELATION_L have the same effect here, as cpu_policy->cur is known - * to be a valid and exact target frequency - */ - ret = cpufreq_driver->target(cpu_policy, cpu_policy->cur, CPUFREQ_RELATION_H); + if (cpufreq_driver->get) + cur_freq = cpufreq_driver->get(cpu_policy->cpu); - if (ret) - printk(KERN_ERR "cpufreq: resume failed in ->setpolicy/target step on CPU %u\n", cpu_policy->cpu); + if (!cur_freq || !cpu_policy->cur) { + printk(KERN_ERR "cpufreq: resume failed to assert current frequency is what timing core thinks it is.\n"); + goto out; + } + + if (unlikely(cur_freq != cpu_policy->cur)) { + struct cpufreq_freqs freqs; + + if (cpufreq_driver->flags & CPUFREQ_PANIC_RESUME_OUTOFSYNC) + panic("CPU Frequency is out of sync."); + + printk(KERN_WARNING "Warning: CPU frequency out of sync: cpufreq and timing" + "core thinks of %u, is %u kHz.\n", cpu_policy->cur, cur_freq); + + freqs.cpu = cpu; + freqs.old = cpu_policy->cur; + freqs.new = cur_freq; + + notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_RESUMECHANGE, &freqs); + adjust_jiffies(CPUFREQ_RESUMECHANGE, &freqs); + } + } out: + schedule_work(&cpu_policy->update); cpufreq_cpu_put(cpu_policy); return ret; } @@ -904,16 +1018,20 @@ static unsigned int l_p_j_ref_freq; static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) { + if (ci->flags & CPUFREQ_CONST_LOOPS) + return; + if (!l_p_j_ref_freq) { l_p_j_ref = loops_per_jiffy; l_p_j_ref_freq = ci->old; } if ((val == CPUFREQ_PRECHANGE && ci->old < ci->new) || - (val == CPUFREQ_POSTCHANGE && ci->old > ci->new)) + (val == CPUFREQ_POSTCHANGE && ci->old > ci->new) || + (val == CPUFREQ_RESUMECHANGE)) loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new); } #else -#define adjust_jiffies(x...) do {} while (0) +static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) { return; } #endif @@ -925,13 +1043,29 @@ static inline void adjust_jiffies(unsign */ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) { - if (irqs_disabled()) - return; /* Only valid if we're in the resume process where - * everyone knows what CPU frequency we are at */ + BUG_ON(irqs_disabled()); + + freqs->flags = cpufreq_driver->flags; down_read(&cpufreq_notifier_rwsem); switch (state) { case CPUFREQ_PRECHANGE: + /* detect if the driver reported a value as "old frequency" which + * is not equal to what the cpufreq core thinks is "old frequency". + */ + if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { + if ((likely(cpufreq_cpu_data[freqs->cpu]->cur)) && + (unlikely(freqs->old != cpufreq_cpu_data[freqs->cpu]->cur))) + { + if (cpufreq_driver->flags & CPUFREQ_PANIC_OUTOFSYNC) + panic("CPU Frequency is out of sync."); + + printk(KERN_WARNING "Warning: CPU frequency out of sync: " + "cpufreq and timing core thinks of %u, is %u kHz.\n", + cpufreq_cpu_data[freqs->cpu]->cur, freqs->old); + freqs->old = cpufreq_cpu_data[freqs->cpu]->cur; + } + } notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs); adjust_jiffies(CPUFREQ_PRECHANGE, freqs); break; @@ -970,6 +1104,9 @@ int cpufreq_register_driver(struct cpufr ((!driver_data->setpolicy) && (!driver_data->target))) return -EINVAL; + if (driver_data->setpolicy) + driver_data->flags |= CPUFREQ_CONST_LOOPS; + spin_lock_irqsave(&cpufreq_driver_lock, flags); if (cpufreq_driver) { spin_unlock_irqrestore(&cpufreq_driver_lock, flags); --- linux-2.6.6/drivers/cpufreq/cpufreq_userspace.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/cpufreq/cpufreq_userspace.c 2004-05-10 01:19:01.796465952 -0700 @@ -145,19 +145,6 @@ int cpufreq_setmax(unsigned int cpu) EXPORT_SYMBOL_GPL(cpufreq_setmax); -/** - * cpufreq_get - get the current CPU frequency (in kHz) - * @cpu: CPU number - * - * Get the CPU current (static) CPU frequency - */ -unsigned int cpufreq_get(unsigned int cpu) -{ - return cpu_cur_freq[cpu]; -} -EXPORT_SYMBOL(cpufreq_get); - - #ifdef CONFIG_CPU_FREQ_24_API @@ -542,20 +529,6 @@ static int cpufreq_governor_userspace(st return 0; } -/* on ARM SA1100 we need to rely on the values of cpufreq_get() - because - * of this, cpu_cur_freq[] needs to be set early. - */ -#if defined(CONFIG_ARM) && defined(CONFIG_ARCH_SA1100) -extern unsigned int sa11x0_getspeed(void); - -static void cpufreq_sa11x0_compat(void) -{ - cpu_cur_freq[0] = sa11x0_getspeed(); -} -#else -#define cpufreq_sa11x0_compat() do {} while(0) -#endif - struct cpufreq_governor cpufreq_gov_userspace = { .name = "userspace", @@ -564,21 +537,12 @@ struct cpufreq_governor cpufreq_gov_user }; EXPORT_SYMBOL(cpufreq_gov_userspace); -static int already_init = 0; - -int cpufreq_gov_userspace_init(void) +static int __init cpufreq_gov_userspace_init(void) { - if (!already_init) { - down(&userspace_sem); - cpufreq_sa11x0_compat(); - cpufreq_sysctl_init(); - cpufreq_register_notifier(&userspace_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); - already_init = 1; - up(&userspace_sem); - } + cpufreq_sysctl_init(); + cpufreq_register_notifier(&userspace_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); return cpufreq_register_governor(&cpufreq_gov_userspace); } -EXPORT_SYMBOL(cpufreq_gov_userspace_init); static void __exit cpufreq_gov_userspace_exit(void) --- linux-2.6.6/drivers/firmware/edd.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/firmware/edd.c 2004-05-10 01:19:47.016591448 -0700 @@ -15,9 +15,8 @@ * made in setup.S, copied to safe structures in setup.c, * and presents it in sysfs. * - * Please see http://domsch.com/linux/edd30/results.html for + * Please see http://linux.dell.com/edd30/results.html for * the list of BIOSs which have been reported to implement EDD. - * If you don't see yours listed, please send a report as described there. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License v2.0 as published by @@ -30,15 +29,6 @@ * */ -/* - * Known issues: - * - refcounting of struct device objects could be improved. - * - * TODO: - * - Add IDE and USB disk device support - * - move edd.[ch] to better locations if/when one is decided - */ - #include #include #include @@ -57,13 +47,13 @@ #include <../drivers/scsi/scsi.h> #include <../drivers/scsi/hosts.h> +#define EDD_VERSION "0.14" +#define EDD_DATE "2004-Apr-28" + MODULE_AUTHOR("Matt Domsch "); MODULE_DESCRIPTION("sysfs interface to BIOS EDD information"); MODULE_LICENSE("GPL"); - -#define EDD_VERSION "0.13 2004-Mar-09" -#define EDD_DEVICE_NAME_SIZE 16 -#define REPORT_URL "http://linux.dell.com/edd/results.html" +MODULE_VERSION(EDD_VERSION); #define left (PAGE_SIZE - (p - buf) - 1) @@ -690,103 +680,6 @@ edd_create_symlink_to_pcidev(struct edd_ return sysfs_create_link(&edev->kobj,&pci_dev->dev.kobj,"pci_dev"); } -/* - * FIXME - as of 15-Jan-2003, there are some non-"scsi_device"s on the - * scsi_bus list. The following functions could possibly mis-access - * memory in that case. This is actually a problem with the SCSI - * layer, which is being addressed there. Until then, don't use the - * SCSI functions. - */ - -#undef CONFIG_SCSI -#undef CONFIG_SCSI_MODULE -#if defined(CONFIG_SCSI) || defined(CONFIG_SCSI_MODULE) - -struct edd_match_data { - struct edd_device * edev; - struct scsi_device * sd; -}; - -/** - * edd_match_scsidev() - * @edev - EDD device is a known SCSI device - * @sd - scsi_device with host who's parent is a PCI controller - * - * returns 1 if a match is found, 0 if not. - */ -static int edd_match_scsidev(struct device * dev, void * d) -{ - struct edd_match_data * data = (struct edd_match_data *)d; - struct edd_info *info = edd_dev_get_info(data->edev); - struct scsi_device * sd = to_scsi_device(dev); - - if (info) { - if ((sd->channel == info->params.interface_path.pci.channel) && - (sd->id == info->params.device_path.scsi.id) && - (sd->lun == info->params.device_path.scsi.lun)) { - data->sd = sd; - return 1; - } - } - return 0; -} - -/** - * edd_find_matching_device() - * @edev - edd_device to match - * - * Search the SCSI devices for a drive that matches the EDD - * device descriptor we have. If we find a match, return it, - * otherwise, return NULL. - */ - -static struct scsi_device * -edd_find_matching_scsi_device(struct edd_device *edev) -{ - struct edd_match_data data; - struct bus_type * scsi_bus = find_bus("scsi"); - - if (!scsi_bus) { - return NULL; - } - - data.edev = edev; - - if (edd_dev_is_type(edev, "SCSI")) { - if (bus_for_each_dev(scsi_bus,NULL,&data,edd_match_scsidev)) - return data.sd; - } - return NULL; -} - -static int -edd_create_symlink_to_scsidev(struct edd_device *edev) -{ - struct pci_dev *pci_dev; - int rc = -EINVAL; - - pci_dev = edd_get_pci_dev(edev); - if (pci_dev) { - struct scsi_device * sdev = edd_find_matching_scsi_device(edev); - if (sdev && get_device(&sdev->sdev_driverfs_dev)) { - rc = sysfs_create_link(&edev->kobj, - &sdev->sdev_driverfs_dev.kobj, - "disc"); - put_device(&sdev->sdev_driverfs_dev); - } - } - return rc; -} - -#else -static int -edd_create_symlink_to_scsidev(struct edd_device *edev) -{ - return -ENOSYS; -} -#endif - - static inline void edd_device_unregister(struct edd_device *edev) { @@ -807,7 +700,6 @@ static void edd_populate_dir(struct edd_ if (!error) { edd_create_symlink_to_pcidev(edev); - edd_create_symlink_to_scsidev(edev); } } @@ -820,8 +712,8 @@ edd_device_register(struct edd_device *e return 1; memset(edev, 0, sizeof (*edev)); edd_dev_set_info(edev, &edd[i]); - snprintf(edev->kobj.name, EDD_DEVICE_NAME_SIZE, "int13_dev%02x", - edd[i].device); + kobject_set_name(&edev->kobj, "int13_dev%02x", + edd[i].device); kobj_set_kset_s(edev,edd_subsys); error = kobject_register(&edev->kobj); if (!error) @@ -842,9 +734,8 @@ edd_init(void) int rc=0; struct edd_device *edev; - printk(KERN_INFO "BIOS EDD facility v%s, %d devices found\n", - EDD_VERSION, eddnr); - printk(KERN_INFO "Please report your BIOS at %s\n", REPORT_URL); + printk(KERN_INFO "BIOS EDD facility v%s %s, %d devices found\n", + EDD_VERSION, EDD_DATE, eddnr); if (!eddnr) { printk(KERN_INFO "EDD information not available.\n"); --- linux-2.6.6/drivers/firmware/Kconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/firmware/Kconfig 2004-05-10 01:19:47.016591448 -0700 @@ -12,7 +12,7 @@ config EDD help Say Y or M here if you want to enable BIOS Enhanced Disk Drive Services real mode BIOS calls to determine which disk - BIOS tries boot from. This information is then exported via driverfs. + BIOS tries boot from. This information is then exported via sysfs. This option is experimental, but believed to be safe, and most disk controller BIOS vendors do not yet implement this feature. @@ -34,4 +34,12 @@ config EFI_VARS Subsequent efibootmgr releases may be found at: http://linux.dell.com/efibootmgr +config SMBIOS + tristate "BIOS SMBIOS table access driver." + help + Say Y or M here if you want to enable access to the SMBIOS table + via driverfs. It exposes /sys/firmware/smbios/ subdirectory tree + containing a binary dump of the SMBIOS table header as well as the SMBIOS + table. + endmenu --- linux-2.6.6/drivers/firmware/Makefile 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/firmware/Makefile 2004-05-10 01:19:02.085422024 -0700 @@ -3,3 +3,4 @@ # obj-$(CONFIG_EDD) += edd.o obj-$(CONFIG_EFI_VARS) += efivars.o +obj-$(CONFIG_SMBIOS) += smbios.o --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/drivers/firmware/smbios.c 2004-05-10 01:19:50.349084832 -0700 @@ -0,0 +1,248 @@ +/* + * linux/drivers/firmware/smbios.c + * Copyright (C) 2004 Dell Inc. + * by Michael Brown + * vim:noet:ts=8:sw=8:filetype=c:textwidth=80: + * + * BIOS SMBIOS Table access + * conformant to DMTF SMBIOS definition + * at http://www.dmtf.org/standards/smbios + * + * This code takes information provided by SMBIOS tables + * and presents it in sysfs as: + * /sys/firmware/smbios + * |--> /table_entry_point + * |--> /table + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License v2.0 as published by + * the Free Software Foundation + * + * 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. + * + */ + + +#include +#include +#include +#include +#include +#include "smbios.h" + +MODULE_AUTHOR("Michael Brown "); +MODULE_DESCRIPTION("sysfs interface to SMBIOS information"); +MODULE_LICENSE("GPL"); + +#define SMBIOS_VERSION "1.0 2004-04-19" + +struct smbios_device { + struct smbios_table_entry_point table_eps; + unsigned int smbios_table_real_length; +}; + +/* there shall be only one */ +static struct smbios_device the_smbios_device; + +#define to_smbios_device(obj) container_of(obj,struct smbios_device,kobj) + +/* don't currently have any "normal" attributes, so we don't need a way to + * show them. */ +static struct sysfs_ops smbios_attr_ops = { }; + +static __init int +checksum_eps(struct smbios_table_entry_point *table_eps) +{ + u8 *p = (u8 *)table_eps; + u8 checksum = 0; + int i=0; + for (i=0; i < table_eps->eps_length && i < sizeof(*table_eps); ++i) { + checksum += p[i]; + } + return( checksum == 0 ); +} + +static __init int +find_table_entry_point(struct smbios_device *sdev) +{ + struct smbios_table_entry_point *table_eps = &(sdev->table_eps); + u32 fp = 0xF0000; + while (fp < 0xFFFFF) { + isa_memcpy_fromio(table_eps, fp, sizeof(*table_eps)); + if (memcmp(table_eps->anchor, "_SM_", 4)==0 && + checksum_eps(table_eps)) { + return 0; + } + fp += 16; + } + + printk(KERN_INFO "SMBIOS table entry point not found in " + "0xF0000 - 0xFFFFF\n"); + return -ENODEV; +} + +static __init int +find_table_max_address(struct smbios_device *sdev) +{ + /* break out on one of three conditions: + * -- hit table_eps.table_length + * -- hit number of items that table claims we have + * -- hit structure type 127 + */ + + u8 *buf = ioremap(sdev->table_eps.table_address, + sdev->table_eps.table_length); + u8 *ptr = buf; + int count = 0, keep_going = 1; + int max_count = sdev->table_eps.table_num_structs; + int max_length = sdev->table_eps.table_length; + while(keep_going && ((ptr - buf) <= max_length) && count < max_count){ + if( ptr[0] == 0x7F ) /* ptr[0] is type */ + keep_going = 0; + + ptr += ptr[1]; /* ptr[1] is length, skip structure */ + /* skip strings at end of structure */ + while((ptr-buf) < max_length && (ptr[0] || ptr[1])) + ++ptr; + + /* string area ends in double-null. skip it. */ + ptr += 2; + ++count; + } + sdev->smbios_table_real_length = (ptr - buf); + iounmap(buf); + + if( count != max_count ) + printk(KERN_INFO "Warning: SMBIOS table structure count" + " does not match count specified in the" + " table entry point.\n" + " Table entry point count: %d\n" + " Actual count: %d\n", + max_count, count ); + + if(keep_going != 0) + printk(KERN_INFO "Warning: SMBIOS table does not end with a" + " structure type 127. This may indicate a" + " truncated table.\n"); + + if(sdev->smbios_table_real_length != max_length) + printk(KERN_INFO "Warning: BIOS specified SMBIOS table length" + " does not match calculated length.\n" + " BIOS specified: %d\n" + " calculated length: %d\n", + max_length, sdev->smbios_table_real_length); + + return sdev->smbios_table_real_length; +} + +static ssize_t +smbios_read_table_entry_point(struct kobject *kobj, char *buffer, + loff_t pos, size_t size) +{ + struct smbios_device *sdev = &the_smbios_device; + const char *p = (const char *)&(sdev->table_eps); + unsigned int count = + size > sizeof(sdev->table_eps) ? + sizeof(sdev->table_eps) : size; + memcpy( buffer, p, count ); + return count; +} + +static ssize_t +smbios_read_table(struct kobject *kobj, char *buffer, + loff_t pos, size_t size) +{ + struct smbios_device *sdev = &the_smbios_device; + u8 *buf; + unsigned int count = sdev->smbios_table_real_length - pos; + int i = 0; + count = count < size ? count : size; + + if (pos > sdev->smbios_table_real_length) + return 0; + + buf = ioremap(sdev->table_eps.table_address, sdev->smbios_table_real_length); + if (buf == NULL) + return -ENXIO; + + /* memcpy( buffer, buf+pos, count ); */ + for (i = 0; i < count; ++i) { + buffer[i] = readb( buf+pos+i ); + } + + iounmap(buf); + + return count; +} + +static struct bin_attribute tep_attr = { + .attr = {.name = "table_entry_point", .owner = THIS_MODULE, .mode = 0444}, + .size = sizeof(struct smbios_table_entry_point), + .read = smbios_read_table_entry_point, + /* not writeable */ +}; + +static struct bin_attribute table_attr = { + .attr = { .name = "table", .owner = THIS_MODULE, .mode = 0444 }, + /* size set later, we don't know it here. */ + .read = smbios_read_table, + /* not writeable */ +}; + +/* no default attributes yet. */ +static struct attribute * def_attrs[] = { NULL, }; + +static struct kobj_type ktype_smbios = { + .sysfs_ops = &smbios_attr_ops, + .default_attrs = def_attrs, + /* statically allocated, no release method necessary */ +}; + +static decl_subsys(smbios,&ktype_smbios,NULL); + +static void smbios_device_unregister(void) +{ + sysfs_remove_bin_file(&smbios_subsys.kset.kobj, &tep_attr ); + sysfs_remove_bin_file(&smbios_subsys.kset.kobj, &table_attr ); +} + +static void __init smbios_device_register(void) +{ + sysfs_create_bin_file(&smbios_subsys.kset.kobj, &tep_attr ); + sysfs_create_bin_file(&smbios_subsys.kset.kobj, &table_attr ); +} + +static int __init +smbios_init(void) +{ + int rc=0; + + printk(KERN_INFO "SMBIOS facility v%s\n", SMBIOS_VERSION ); + + rc = find_table_entry_point(&the_smbios_device); + if (rc) + return rc; + + table_attr.size = find_table_max_address(&the_smbios_device); + + rc = firmware_register(&smbios_subsys); + if (rc) + return rc; + + smbios_device_register(); + + return rc; +} + +static void __exit +smbios_exit(void) +{ + smbios_device_unregister(); + firmware_unregister(&smbios_subsys); +} + +late_initcall(smbios_init); +module_exit(smbios_exit); --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/drivers/firmware/smbios.h 2004-05-10 01:19:02.087421720 -0700 @@ -0,0 +1,53 @@ +/* + * linux/drivers/firmware/smbios.c + * Copyright (C) 2002, 2003, 2004 Dell Inc. + * by Michael Brown + * vim:noet:ts=8:sw=8:filetype=c:textwidth=80: + * + * BIOS SMBIOS Table access + * conformant to DMTF SMBIOS definition + * at http://www.dmtf.org/standards/smbios + * + * This code takes information provided by SMBIOS tables + * and presents it in sysfs. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License v2.0 as published by + * the Free Software Foundation + * + * 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. + * + */ + +#ifndef _LINUX_SMBIOS_H +#define _LINUX_SMBIOS_H + +#include + +struct smbios_table_entry_point { + u8 anchor[4]; + u8 checksum; + u8 eps_length; + u8 major_ver; + u8 minor_ver; + u16 max_struct_size; + u8 revision; + u8 formatted_area[5]; + u8 dmi_anchor[5]; + u8 intermediate_checksum; + u16 table_length; + u32 table_address; + u16 table_num_structs; + u8 smbios_bcd_revision; +} __attribute__ ((packed)); + +struct smbios_structure_header { + u8 type; + u8 length; + u16 handle; +} __attribute__ ((packed)); + +#endif /* _LINUX_SMBIOS_H */ --- linux-2.6.6/drivers/i2c/algos/i2c-algo-bit.c 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/i2c/algos/i2c-algo-bit.c 2004-05-10 01:19:02.903297688 -0700 @@ -381,7 +381,13 @@ static inline int readbytes(struct i2c_a break; } - if ( count > 1 ) { /* send ack */ + temp++; + count--; + + if (msg->flags & I2C_M_NO_RD_ACK) + continue; + + if ( count > 0 ) { /* send ack */ sdalo(adap); DEBPROTO(printk(" Am ")); } else { @@ -395,8 +401,6 @@ static inline int readbytes(struct i2c_a }; scllo(adap); sdahi(adap); - temp++; - count--; } return rdcount; } --- linux-2.6.6/drivers/i2c/busses/i2c-ali1535.c 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/i2c/busses/i2c-ali1535.c 2004-05-10 01:19:02.904297536 -0700 @@ -480,7 +480,7 @@ static struct i2c_algorithm smbus_algori static struct i2c_adapter ali1535_adapter = { .owner = THIS_MODULE, - .class = I2C_ADAP_CLASS_SMBUS, + .class = I2C_CLASS_SMBUS, .algo = &smbus_algorithm, .name = "unset", }; --- linux-2.6.6/drivers/i2c/busses/i2c-ali1563.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/i2c/busses/i2c-ali1563.c 2004-05-10 01:19:02.905297384 -0700 @@ -357,7 +357,7 @@ static struct i2c_algorithm ali1563_algo static struct i2c_adapter ali1563_adapter = { .owner = THIS_MODULE, - .class = I2C_ADAP_CLASS_SMBUS, + .class = I2C_CLASS_SMBUS, .algo = &ali1563_algorithm, }; --- linux-2.6.6/drivers/i2c/busses/i2c-ali15x3.c 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/i2c/busses/i2c-ali15x3.c 2004-05-10 01:19:02.905297384 -0700 @@ -470,7 +470,7 @@ static struct i2c_algorithm smbus_algori static struct i2c_adapter ali15x3_adapter = { .owner = THIS_MODULE, - .class = I2C_ADAP_CLASS_SMBUS, + .class = I2C_CLASS_SMBUS, .algo = &smbus_algorithm, .name = "unset", }; --- linux-2.6.6/drivers/i2c/busses/i2c-amd756.c 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/i2c/busses/i2c-amd756.c 2004-05-10 01:19:02.906297232 -0700 @@ -303,7 +303,7 @@ static struct i2c_algorithm smbus_algori static struct i2c_adapter amd756_adapter = { .owner = THIS_MODULE, - .class = I2C_ADAP_CLASS_SMBUS, + .class = I2C_CLASS_SMBUS, .algo = &smbus_algorithm, .name = "unset", }; --- linux-2.6.6/drivers/i2c/busses/i2c-amd8111.c 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/i2c/busses/i2c-amd8111.c 2004-05-10 01:19:02.906297232 -0700 @@ -359,7 +359,7 @@ static int __devinit amd8111_probe(struc smbus->adapter.owner = THIS_MODULE; snprintf(smbus->adapter.name, I2C_NAME_SIZE, "SMBus2 AMD8111 adapter at %04x", smbus->base); - smbus->adapter.class = I2C_ADAP_CLASS_SMBUS; + smbus->adapter.class = I2C_CLASS_SMBUS; smbus->adapter.algo = &smbus_algorithm; smbus->adapter.algo_data = smbus; --- linux-2.6.6/drivers/i2c/busses/i2c-i801.c 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/i2c/busses/i2c-i801.c 2004-05-10 01:19:02.907297080 -0700 @@ -539,7 +539,7 @@ static struct i2c_algorithm smbus_algori static struct i2c_adapter i801_adapter = { .owner = THIS_MODULE, - .class = I2C_ADAP_CLASS_SMBUS, + .class = I2C_CLASS_SMBUS, .algo = &smbus_algorithm, .name = "unset", }; --- linux-2.6.6/drivers/i2c/busses/i2c-isa.c 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/i2c/busses/i2c-isa.c 2004-05-10 01:19:02.907297080 -0700 @@ -43,7 +43,7 @@ static struct i2c_algorithm isa_algorith /* There can only be one... */ static struct i2c_adapter isa_adapter = { .owner = THIS_MODULE, - .class = I2C_ADAP_CLASS_SMBUS, + .class = I2C_CLASS_SMBUS, .algo = &isa_algorithm, .name = "ISA main adapter", }; --- linux-2.6.6/drivers/i2c/busses/i2c-ixp42x.c 2004-04-03 20:39:12.000000000 -0800 +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,176 +0,0 @@ -/* - * drivers/i2c/i2c-adap-ixp42x.c - * - * Intel's IXP42x XScale NPU chipsets (IXP420, 421, 422, 425) do not have - * an on board I2C controller but provide 16 GPIO pins that are often - * used to create an I2C bus. This driver provides an i2c_adapter - * interface that plugs in under algo_bit and drives the GPIO pins - * as instructed by the alogorithm driver. - * - * Author: Deepak Saxena - * - * Copyright (c) 2003-2004 MontaVista Software Inc. - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - * - * NOTE: Since different platforms will use different GPIO pins for - * I2C, this driver uses an IXP42x-specific platform_data - * pointer to pass the GPIO numbers to the driver. This - * allows us to support all the different IXP42x platforms - * w/o having to put #ifdefs in this driver. - * - * See arch/arm/mach-ixp42x/ixdp425.c for an example of building a - * device list and filling in the ixp42x_i2c_pins data structure - * that is passed as the platform_data to this driver. - */ - -#include -#include -#include -#include -#include -#include - -#include /* Pick up IXP42x-specific bits */ - -static inline int ixp42x_scl_pin(void *data) -{ - return ((struct ixp42x_i2c_pins*)data)->scl_pin; -} - -static inline int ixp42x_sda_pin(void *data) -{ - return ((struct ixp42x_i2c_pins*)data)->sda_pin; -} - -static void ixp42x_bit_setscl(void *data, int val) -{ - gpio_line_set(ixp42x_scl_pin(data), 0); - gpio_line_config(ixp42x_scl_pin(data), - val ? IXP425_GPIO_IN : IXP425_GPIO_OUT ); -} - -static void ixp42x_bit_setsda(void *data, int val) -{ - gpio_line_set(ixp42x_sda_pin(data), 0); - gpio_line_config(ixp42x_sda_pin(data), - val ? IXP425_GPIO_IN : IXP425_GPIO_OUT ); -} - -static int ixp42x_bit_getscl(void *data) -{ - int scl; - - gpio_line_config(ixp42x_scl_pin(data), IXP425_GPIO_IN ); - gpio_line_get(ixp42x_scl_pin(data), &scl); - - return scl; -} - -static int ixp42x_bit_getsda(void *data) -{ - int sda; - - gpio_line_config(ixp42x_sda_pin(data), IXP425_GPIO_IN ); - gpio_line_get(ixp42x_sda_pin(data), &sda); - - return sda; -} - -struct ixp42x_i2c_data { - struct ixp42x_i2c_pins *gpio_pins; - struct i2c_adapter adapter; - struct i2c_algo_bit_data algo_data; -}; - -static int ixp42x_i2c_remove(struct device *dev) -{ - struct platform_device *plat_dev = to_platform_device(dev); - struct ixp42x_i2c_data *drv_data = dev_get_drvdata(&plat_dev->dev); - - dev_set_drvdata(&plat_dev->dev, NULL); - - i2c_bit_del_bus(&drv_data->adapter); - - kfree(drv_data); - - return 0; -} - -static int ixp42x_i2c_probe(struct device *dev) -{ - int err; - struct platform_device *plat_dev = to_platform_device(dev); - struct ixp42x_i2c_pins *gpio = plat_dev->dev.platform_data; - struct ixp42x_i2c_data *drv_data = - kmalloc(sizeof(struct ixp42x_i2c_data), GFP_KERNEL); - - if(!drv_data) - return -ENOMEM; - - memzero(drv_data, sizeof(struct ixp42x_i2c_data)); - drv_data->gpio_pins = gpio; - - /* - * We could make a lot of these structures static, but - * certain platforms may have multiple GPIO-based I2C - * buses for various device domains, so we need per-device - * algo_data->data. - */ - drv_data->algo_data.data = gpio; - drv_data->algo_data.setsda = ixp42x_bit_setsda; - drv_data->algo_data.setscl = ixp42x_bit_setscl; - drv_data->algo_data.getsda = ixp42x_bit_getsda; - drv_data->algo_data.getscl = ixp42x_bit_getscl; - drv_data->algo_data.udelay = 10; - drv_data->algo_data.mdelay = 10; - drv_data->algo_data.timeout = 100; - - drv_data->adapter.id = I2C_HW_B_IXP425, - drv_data->adapter.algo_data = &drv_data->algo_data, - - drv_data->adapter.dev.parent = &plat_dev->dev; - - gpio_line_config(gpio->scl_pin, IXP425_GPIO_IN); - gpio_line_config(gpio->sda_pin, IXP425_GPIO_IN); - gpio_line_set(gpio->scl_pin, 0); - gpio_line_set(gpio->sda_pin, 0); - - if ((err = i2c_bit_add_bus(&drv_data->adapter) != 0)) { - printk(KERN_ERR "ERROR: Could not install %s\n", dev->bus_id); - - kfree(drv_data); - return err; - } - - dev_set_drvdata(&plat_dev->dev, drv_data); - - return 0; -} - -static struct device_driver ixp42x_i2c_driver = { - .name = "IXP42X-I2C", - .bus = &platform_bus_type, - .probe = ixp42x_i2c_probe, - .remove = ixp42x_i2c_remove, -}; - -static int __init ixp42x_i2c_init(void) -{ - return driver_register(&ixp42x_i2c_driver); -} - -static void __exit ixp42x_i2c_exit(void) -{ - driver_unregister(&ixp42x_i2c_driver); -} - -module_init(ixp42x_i2c_init); -module_exit(ixp42x_i2c_exit); - -MODULE_DESCRIPTION("GPIO-based I2C driver for IXP42x systems"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Deepak Saxena "); - --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/drivers/i2c/busses/i2c-ixp4xx.c 2004-05-10 01:19:02.910296624 -0700 @@ -0,0 +1,181 @@ +/* + * drivers/i2c/i2c-adap-ixp4xx.c + * + * Intel's IXP4xx XScale NPU chipsets (IXP420, 421, 422, 425) do not have + * an on board I2C controller but provide 16 GPIO pins that are often + * used to create an I2C bus. This driver provides an i2c_adapter + * interface that plugs in under algo_bit and drives the GPIO pins + * as instructed by the alogorithm driver. + * + * Author: Deepak Saxena + * + * Copyright (c) 2003-2004 MontaVista Software Inc. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + * + * NOTE: Since different platforms will use different GPIO pins for + * I2C, this driver uses an IXP4xx-specific platform_data + * pointer to pass the GPIO numbers to the driver. This + * allows us to support all the different IXP4xx platforms + * w/o having to put #ifdefs in this driver. + * + * See arch/arm/mach-ixp4xx/ixdp425.c for an example of building a + * device list and filling in the ixp4xx_i2c_pins data structure + * that is passed as the platform_data to this driver. + */ + +#include +#ifdef CONFIG_I2C_DEBUG_BUS +#define DEBUG 1 +#endif + +#include +#include +#include +#include +#include +#include + +#include /* Pick up IXP4xx-specific bits */ + +static inline int ixp4xx_scl_pin(void *data) +{ + return ((struct ixp4xx_i2c_pins*)data)->scl_pin; +} + +static inline int ixp4xx_sda_pin(void *data) +{ + return ((struct ixp4xx_i2c_pins*)data)->sda_pin; +} + +static void ixp4xx_bit_setscl(void *data, int val) +{ + gpio_line_set(ixp4xx_scl_pin(data), 0); + gpio_line_config(ixp4xx_scl_pin(data), + val ? IXP4XX_GPIO_IN : IXP4XX_GPIO_OUT ); +} + +static void ixp4xx_bit_setsda(void *data, int val) +{ + gpio_line_set(ixp4xx_sda_pin(data), 0); + gpio_line_config(ixp4xx_sda_pin(data), + val ? IXP4XX_GPIO_IN : IXP4XX_GPIO_OUT ); +} + +static int ixp4xx_bit_getscl(void *data) +{ + int scl; + + gpio_line_config(ixp4xx_scl_pin(data), IXP4XX_GPIO_IN ); + gpio_line_get(ixp4xx_scl_pin(data), &scl); + + return scl; +} + +static int ixp4xx_bit_getsda(void *data) +{ + int sda; + + gpio_line_config(ixp4xx_sda_pin(data), IXP4XX_GPIO_IN ); + gpio_line_get(ixp4xx_sda_pin(data), &sda); + + return sda; +} + +struct ixp4xx_i2c_data { + struct ixp4xx_i2c_pins *gpio_pins; + struct i2c_adapter adapter; + struct i2c_algo_bit_data algo_data; +}; + +static int ixp4xx_i2c_remove(struct device *dev) +{ + struct platform_device *plat_dev = to_platform_device(dev); + struct ixp4xx_i2c_data *drv_data = dev_get_drvdata(&plat_dev->dev); + + dev_set_drvdata(&plat_dev->dev, NULL); + + i2c_bit_del_bus(&drv_data->adapter); + + kfree(drv_data); + + return 0; +} + +static int ixp4xx_i2c_probe(struct device *dev) +{ + int err; + struct platform_device *plat_dev = to_platform_device(dev); + struct ixp4xx_i2c_pins *gpio = plat_dev->dev.platform_data; + struct ixp4xx_i2c_data *drv_data = + kmalloc(sizeof(struct ixp4xx_i2c_data), GFP_KERNEL); + + if(!drv_data) + return -ENOMEM; + + memzero(drv_data, sizeof(struct ixp4xx_i2c_data)); + drv_data->gpio_pins = gpio; + + /* + * We could make a lot of these structures static, but + * certain platforms may have multiple GPIO-based I2C + * buses for various device domains, so we need per-device + * algo_data->data. + */ + drv_data->algo_data.data = gpio; + drv_data->algo_data.setsda = ixp4xx_bit_setsda; + drv_data->algo_data.setscl = ixp4xx_bit_setscl; + drv_data->algo_data.getsda = ixp4xx_bit_getsda; + drv_data->algo_data.getscl = ixp4xx_bit_getscl; + drv_data->algo_data.udelay = 10; + drv_data->algo_data.mdelay = 10; + drv_data->algo_data.timeout = 100; + + drv_data->adapter.id = I2C_HW_B_IXP4XX, + drv_data->adapter.algo_data = &drv_data->algo_data, + + drv_data->adapter.dev.parent = &plat_dev->dev; + + gpio_line_config(gpio->scl_pin, IXP4XX_GPIO_IN); + gpio_line_config(gpio->sda_pin, IXP4XX_GPIO_IN); + gpio_line_set(gpio->scl_pin, 0); + gpio_line_set(gpio->sda_pin, 0); + + if ((err = i2c_bit_add_bus(&drv_data->adapter) != 0)) { + printk(KERN_ERR "ERROR: Could not install %s\n", dev->bus_id); + + kfree(drv_data); + return err; + } + + dev_set_drvdata(&plat_dev->dev, drv_data); + + return 0; +} + +static struct device_driver ixp4xx_i2c_driver = { + .name = "IXP4XX-I2C", + .bus = &platform_bus_type, + .probe = ixp4xx_i2c_probe, + .remove = ixp4xx_i2c_remove, +}; + +static int __init ixp4xx_i2c_init(void) +{ + return driver_register(&ixp4xx_i2c_driver); +} + +static void __exit ixp4xx_i2c_exit(void) +{ + driver_unregister(&ixp4xx_i2c_driver); +} + +module_init(ixp4xx_i2c_init); +module_exit(ixp4xx_i2c_exit); + +MODULE_DESCRIPTION("GPIO-based I2C adapter for IXP4xx systems"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Deepak Saxena "); + --- linux-2.6.6/drivers/i2c/busses/i2c-nforce2.c 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/i2c/busses/i2c-nforce2.c 2004-05-10 01:19:02.910296624 -0700 @@ -119,7 +119,7 @@ static struct i2c_algorithm smbus_algori static struct i2c_adapter nforce2_adapter = { .owner = THIS_MODULE, - .class = I2C_ADAP_CLASS_SMBUS, + .class = I2C_CLASS_SMBUS, .algo = &smbus_algorithm, .name = "unset", }; --- linux-2.6.6/drivers/i2c/busses/i2c-parport.c 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/i2c/busses/i2c-parport.c 2004-05-10 01:19:02.911296472 -0700 @@ -147,7 +147,7 @@ static struct i2c_algo_bit_data parport_ static struct i2c_adapter parport_adapter = { .owner = THIS_MODULE, - .class = I2C_ADAP_CLASS_SMBUS, + .class = I2C_CLASS_SMBUS, .id = I2C_HW_B_LP, .name = "Parallel port adapter", }; --- linux-2.6.6/drivers/i2c/busses/i2c-parport-light.c 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/i2c/busses/i2c-parport-light.c 2004-05-10 01:19:02.911296472 -0700 @@ -112,7 +112,7 @@ static struct i2c_algo_bit_data parport_ static struct i2c_adapter parport_adapter = { .owner = THIS_MODULE, - .class = I2C_ADAP_CLASS_SMBUS, + .class = I2C_CLASS_SMBUS, .id = I2C_HW_B_LP, .algo_data = &parport_algo_data, .name = "Parallel port adapter (light)", --- linux-2.6.6/drivers/i2c/busses/i2c-piix4.c 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/i2c/busses/i2c-piix4.c 2004-05-10 01:19:02.912296320 -0700 @@ -410,7 +410,7 @@ static struct i2c_algorithm smbus_algori static struct i2c_adapter piix4_adapter = { .owner = THIS_MODULE, - .class = I2C_ADAP_CLASS_SMBUS, + .class = I2C_CLASS_SMBUS, .algo = &smbus_algorithm, .name = "unset", }; --- linux-2.6.6/drivers/i2c/busses/i2c-sis5595.c 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/i2c/busses/i2c-sis5595.c 2004-05-10 01:19:02.912296320 -0700 @@ -360,7 +360,7 @@ static struct i2c_algorithm smbus_algori static struct i2c_adapter sis5595_adapter = { .owner = THIS_MODULE, - .class = I2C_ADAP_CLASS_SMBUS, + .class = I2C_CLASS_SMBUS, .name = "unset", .algo = &smbus_algorithm, }; --- linux-2.6.6/drivers/i2c/busses/i2c-sis630.c 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/i2c/busses/i2c-sis630.c 2004-05-10 01:19:02.913296168 -0700 @@ -456,7 +456,7 @@ static struct i2c_algorithm smbus_algori static struct i2c_adapter sis630_adapter = { .owner = THIS_MODULE, - .class = I2C_ADAP_CLASS_SMBUS, + .class = I2C_CLASS_SMBUS, .name = "unset", .algo = &smbus_algorithm, }; --- linux-2.6.6/drivers/i2c/busses/i2c-sis96x.c 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/i2c/busses/i2c-sis96x.c 2004-05-10 01:19:02.913296168 -0700 @@ -260,7 +260,7 @@ static struct i2c_algorithm smbus_algori static struct i2c_adapter sis96x_adapter = { .owner = THIS_MODULE, - .class = I2C_ADAP_CLASS_SMBUS, + .class = I2C_CLASS_SMBUS, .algo = &smbus_algorithm, .name = "unset", }; --- linux-2.6.6/drivers/i2c/busses/i2c-via.c 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/i2c/busses/i2c-via.c 2004-05-10 01:19:02.913296168 -0700 @@ -88,7 +88,7 @@ static struct i2c_algo_bit_data bit_data static struct i2c_adapter vt586b_adapter = { .owner = THIS_MODULE, - .class = I2C_ADAP_CLASS_SMBUS, + .class = I2C_CLASS_SMBUS, .name = "VIA i2c", .algo_data = &bit_data, }; --- linux-2.6.6/drivers/i2c/busses/i2c-viapro.c 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/i2c/busses/i2c-viapro.c 2004-05-10 01:19:02.914296016 -0700 @@ -289,7 +289,7 @@ static struct i2c_algorithm smbus_algori static struct i2c_adapter vt596_adapter = { .owner = THIS_MODULE, - .class = I2C_ADAP_CLASS_SMBUS, + .class = I2C_CLASS_SMBUS, .algo = &smbus_algorithm, .name = "unset", }; --- linux-2.6.6/drivers/i2c/busses/i2c-voodoo3.c 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/i2c/busses/i2c-voodoo3.c 2004-05-10 01:19:02.914296016 -0700 @@ -167,7 +167,7 @@ static struct i2c_algo_bit_data voo_i2c_ static struct i2c_adapter voodoo3_i2c_adapter = { .owner = THIS_MODULE, - .class = I2C_ADAP_CLASS_TV_ANALOG, + .class = I2C_CLASS_TV_ANALOG, .name = "I2C Voodoo3/Banshee adapter", .algo_data = &voo_i2c_bit_data, }; @@ -184,7 +184,7 @@ static struct i2c_algo_bit_data voo_ddc_ static struct i2c_adapter voodoo3_ddc_adapter = { .owner = THIS_MODULE, - .class = I2C_ADAP_CLASS_DDC, + .class = I2C_CLASS_DDC, .name = "DDC Voodoo3/Banshee adapter", .algo_data = &voo_ddc_bit_data, }; --- linux-2.6.6/drivers/i2c/busses/Kconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/i2c/busses/Kconfig 2004-05-10 01:19:02.903297688 -0700 @@ -145,16 +145,16 @@ config I2C_ITE This support is also available as a module. If so, the module will be called i2c-ite. -config I2C_IXP42X - tristate "IXP42x GPIO-Based I2C Interface" - depends on I2C && ARCH_IXP425 +config I2C_IXP4XX + tristate "IXP4xx GPIO-Based I2C Interface" + depends on I2C && ARCH_IXP4XX select I2C_ALGOBIT help - Say Y here if you have an Intel IXP42x(420,421,422,425) based + Say Y here if you have an Intel IXP4xx(420,421,422,425) based system and are using GPIO lines for an I2C bus. This support is also available as a module. If so, the module - will be called i2c-ixp42x. + will be called i2c-ixp4xx. config I2C_KEYWEST tristate "Powermac Keywest I2C interface" --- linux-2.6.6/drivers/i2c/busses/Makefile 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/i2c/busses/Makefile 2004-05-10 01:19:02.904297536 -0700 @@ -15,7 +15,7 @@ obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o obj-$(CONFIG_I2C_ISA) += i2c-isa.o obj-$(CONFIG_I2C_ITE) += i2c-ite.o -obj-$(CONFIG_I2C_IXP42X) += i2c-ixp42x.o +obj-$(CONFIG_I2C_IXP4XX) += i2c-ixp4xx.o obj-$(CONFIG_I2C_KEYWEST) += i2c-keywest.o obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o --- linux-2.6.6/drivers/i2c/chips/adm1021.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/i2c/chips/adm1021.c 2004-05-10 01:19:02.916295712 -0700 @@ -200,7 +200,7 @@ static DEVICE_ATTR(die_code, S_IRUGO, sh static int adm1021_attach_adapter(struct i2c_adapter *adapter) { - if (!(adapter->class & I2C_ADAP_CLASS_SMBUS)) + if (!(adapter->class & I2C_CLASS_SMBUS)) return 0; return i2c_detect(adapter, &addr_data, adm1021_detect); } --- linux-2.6.6/drivers/i2c/chips/asb100.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/i2c/chips/asb100.c 2004-05-10 01:19:02.917295560 -0700 @@ -609,7 +609,7 @@ static DEVICE_ATTR(fan1_pwm_enable, S_IR */ static int asb100_attach_adapter(struct i2c_adapter *adapter) { - if (!(adapter->class & I2C_ADAP_CLASS_SMBUS)) + if (!(adapter->class & I2C_CLASS_SMBUS)) return 0; return i2c_detect(adapter, &addr_data, asb100_detect); } @@ -855,7 +855,13 @@ static int asb100_detach_client(struct i return err; } - kfree(i2c_get_clientdata(client)); + if (i2c_get_clientdata(client)==NULL) { + /* subclients */ + kfree(client); + } else { + /* main client */ + kfree(i2c_get_clientdata(client)); + } return 0; } --- linux-2.6.6/drivers/i2c/chips/fscher.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/i2c/chips/fscher.c 2004-05-10 01:19:02.918295408 -0700 @@ -293,7 +293,7 @@ do { \ static int fscher_attach_adapter(struct i2c_adapter *adapter) { - if (!(adapter->class & I2C_ADAP_CLASS_SMBUS)) + if (!(adapter->class & I2C_CLASS_SMBUS)) return 0; return i2c_detect(adapter, &addr_data, fscher_detect); } --- linux-2.6.6/drivers/i2c/chips/gl518sm.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/i2c/chips/gl518sm.c 2004-05-10 01:19:02.918295408 -0700 @@ -335,7 +335,7 @@ static DEVICE_ATTR(beep_mask, S_IWUSR|S_ static int gl518_attach_adapter(struct i2c_adapter *adapter) { - if (!(adapter->class & I2C_ADAP_CLASS_SMBUS)) + if (!(adapter->class & I2C_CLASS_SMBUS)) return 0; return i2c_detect(adapter, &addr_data, gl518_detect); } --- linux-2.6.6/drivers/i2c/chips/it87.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/i2c/chips/it87.c 2004-05-10 01:19:02.919295256 -0700 @@ -500,7 +500,7 @@ static DEVICE_ATTR(alarms, S_IRUGO | S_I * when a new adapter is inserted (and it87_driver is still present) */ static int it87_attach_adapter(struct i2c_adapter *adapter) { - if (!(adapter->class & I2C_ADAP_CLASS_SMBUS)) + if (!(adapter->class & I2C_CLASS_SMBUS)) return 0; return i2c_detect(adapter, &addr_data, it87_detect); } --- linux-2.6.6/drivers/i2c/chips/Kconfig 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/i2c/chips/Kconfig 2004-05-10 01:19:02.915295864 -0700 @@ -136,11 +136,11 @@ config SENSORS_LM85 config SENSORS_LM90 tristate "National Semiconductor LM90 and compatibles" - depends on I2C && EXPERIMENTAL + depends on I2C select I2C_SENSOR help - If you say yes here you get support for National Semiconductor LM90 - and Analog Devices ADM1032 sensor chips. + If you say yes here you get support for National Semiconductor LM90, + LM89 and LM99, and Analog Devices ADM1032 sensor chips. This driver can also be built as a module. If so, the module will be called lm90. @@ -163,7 +163,7 @@ config SENSORS_W83781D select I2C_SENSOR help If you say yes here you get support for the Winbond W8378x series - of sensor chips: the W83781D, W83782D, W83783S and W83682HF, + of sensor chips: the W83781D, W83782D, W83783S and W83627HF, and the similar Asus AS99127F. This driver can also be built as a module. If so, the module @@ -230,4 +230,14 @@ config SENSORS_PCF8591 This driver can also be built as a module. If so, the module will be called pcf8591. +config SENSORS_RTC8564 + tristate "Epson 8564 RTC chip" + depends on I2C && EXPERIMENTAL + select I2C_SENSOR + help + If you say yes here you get support for the Epson 8564 RTC chip. + + This driver can also be built as a module. If so, the module + will be called i2c-rtc8564. + endmenu --- linux-2.6.6/drivers/i2c/chips/lm75.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/i2c/chips/lm75.c 2004-05-10 01:19:02.919295256 -0700 @@ -105,7 +105,7 @@ static DEVICE_ATTR(temp1_input, S_IRUGO, static int lm75_attach_adapter(struct i2c_adapter *adapter) { - if (!(adapter->class & I2C_ADAP_CLASS_SMBUS)) + if (!(adapter->class & I2C_CLASS_SMBUS)) return 0; return i2c_detect(adapter, &addr_data, lm75_detect); } --- linux-2.6.6/drivers/i2c/chips/lm78.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/i2c/chips/lm78.c 2004-05-10 01:19:02.920295104 -0700 @@ -488,7 +488,7 @@ static DEVICE_ATTR(alarms, S_IRUGO, show * when a new adapter is inserted (and lm78_driver is still present) */ static int lm78_attach_adapter(struct i2c_adapter *adapter) { - if (!(adapter->class & I2C_ADAP_CLASS_SMBUS)) + if (!(adapter->class & I2C_CLASS_SMBUS)) return 0; return i2c_detect(adapter, &addr_data, lm78_detect); } --- linux-2.6.6/drivers/i2c/chips/lm80.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/i2c/chips/lm80.c 2004-05-10 01:19:02.921294952 -0700 @@ -376,7 +376,7 @@ static DEVICE_ATTR(alarms, S_IRUGO, show static int lm80_attach_adapter(struct i2c_adapter *adapter) { - if (!(adapter->class & I2C_ADAP_CLASS_SMBUS)) + if (!(adapter->class & I2C_CLASS_SMBUS)) return 0; return i2c_detect(adapter, &addr_data, lm80_detect); } --- linux-2.6.6/drivers/i2c/chips/lm83.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/i2c/chips/lm83.c 2004-05-10 01:19:02.922294800 -0700 @@ -216,7 +216,7 @@ static DEVICE_ATTR(alarms, S_IRUGO, show static int lm83_attach_adapter(struct i2c_adapter *adapter) { - if (!(adapter->class & I2C_ADAP_CLASS_SMBUS)) + if (!(adapter->class & I2C_CLASS_SMBUS)) return 0; return i2c_detect(adapter, &addr_data, lm83_detect); } --- linux-2.6.6/drivers/i2c/chips/lm90.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/i2c/chips/lm90.c 2004-05-10 01:19:02.923294648 -0700 @@ -1,7 +1,7 @@ /* * lm90.c - Part of lm_sensors, Linux kernel modules for hardware * monitoring - * Copyright (C) 2003 Jean Delvare + * Copyright (C) 2003-2004 Jean Delvare * * Based on the lm83 driver. The LM90 is a sensor chip made by National * Semiconductor. It reports up to two temperatures (its own plus up to @@ -10,6 +10,17 @@ * obtained from National's website at: * http://www.national.com/pf/LM/LM90.html * + * This driver also supports the LM89 and LM99, two other sensor chips + * made by National Semiconductor. Both have an increased remote + * temperature measurement accuracy (1 degree), and the LM99 + * additionally shifts remote temperatures (measured and limits) by 16 + * degrees, which allows for higher temperatures measurement. The + * driver doesn't handle it since it can be done easily in user-space. + * Complete datasheets can be obtained from National's website at: + * http://www.national.com/pf/LM/LM89.html + * http://www.national.com/pf/LM/LM99.html + * Note that there is no way to differenciate between both chips. + * * This driver also supports the ADM1032, a sensor chip made by Analog * Devices. That chip is similar to the LM90, with a few differences * that are not handled by this driver. Complete datasheet can be @@ -45,9 +56,11 @@ /* * Addresses to scan * Address is fully defined internally and cannot be changed. + * LM89, LM90, LM99 and ADM1032 have address 0x4c. + * LM89-1, and LM99-1 have address 0x4d. */ -static unsigned short normal_i2c[] = { 0x4c, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x4c, 0x4d, I2C_CLIENT_END }; static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END }; @@ -56,7 +69,7 @@ static unsigned int normal_isa_range[] = * Insmod parameters */ -SENSORS_INSMOD_2(lm90, adm1032); +SENSORS_INSMOD_3(lm90, adm1032, lm99); /* * The LM90 registers @@ -261,7 +274,7 @@ static DEVICE_ATTR(alarms, S_IRUGO, show static int lm90_attach_adapter(struct i2c_adapter *adapter) { - if (!(adapter->class & I2C_ADAP_CLASS_SMBUS)) + if (!(adapter->class & I2C_CLASS_SMBUS)) return 0; return i2c_detect(adapter, &addr_data, lm90_detect); } @@ -330,16 +343,26 @@ static int lm90_detect(struct i2c_adapte LM90_REG_R_CHIP_ID); if (man_id == 0x01) { /* National Semiconductor */ - if (chip_id >= 0x21 && chip_id < 0x30 /* LM90 */ - && (kind == 0 /* skip detection */ - || ((i2c_smbus_read_byte_data(new_client, - LM90_REG_R_CONFIG2) & 0xF8) == 0x00 - && reg_convrate <= 0x09))) { - kind = lm90; + u8 reg_config2; + + reg_config2 = i2c_smbus_read_byte_data(new_client, + LM90_REG_R_CONFIG2); + + if (kind == 0 /* skip detection */ + || ((reg_config2 & 0xF8) == 0x00 + && reg_convrate <= 0x09)) { + if (address == 0x4C + && (chip_id & 0xF0) == 0x20) { /* LM90 */ + kind = lm90; + } else + if ((chip_id & 0xF0) == 0x30) { /* LM89/LM99 */ + kind = lm99; + } } - } - else if (man_id == 0x41) { /* Analog Devices */ - if ((chip_id & 0xF0) == 0x40 /* ADM1032 */ + } else + if (man_id == 0x41) { /* Analog Devices */ + if (address == 0x4C + && (chip_id & 0xF0) == 0x40 /* ADM1032 */ && (kind == 0 /* skip detection */ || (reg_config1 & 0x3F) == 0x00)) { kind = adm1032; @@ -358,6 +381,8 @@ static int lm90_detect(struct i2c_adapte name = "lm90"; } else if (kind == adm1032) { name = "adm1032"; + } else if (kind == lm99) { + name = "lm99"; } /* We can fill in the remaining client fields */ --- linux-2.6.6/drivers/i2c/chips/Makefile 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/i2c/chips/Makefile 2004-05-10 01:19:02.915295864 -0700 @@ -21,6 +21,7 @@ obj-$(CONFIG_SENSORS_LM85) += lm85.o obj-$(CONFIG_SENSORS_LM90) += lm90.o obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o +obj-$(CONFIG_SENSORS_RTC8564) += rtc8564.o obj-$(CONFIG_SENSORS_VIA686A) += via686a.o obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/drivers/i2c/chips/rtc8564.c 2004-05-10 01:19:02.925294344 -0700 @@ -0,0 +1,396 @@ +/* + * linux/drivers/i2c/chips/rtc8564.c + * + * Copyright (C) 2002-2004 Stefan Eletzhofer + * + * based on linux/drivers/acron/char/pcf8583.c + * Copyright (C) 2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Driver for system3's EPSON RTC 8564 chip + */ +#include +#include +#include +#include +#include +#include /* get the user-level API */ +#include +#include + +#include "rtc8564.h" + +#ifdef DEBUG +# define _DBG(x, fmt, args...) do{ if (debug>=x) printk(KERN_DEBUG"%s: " fmt "\n", __FUNCTION__, ##args); } while(0); +#else +# define _DBG(x, fmt, args...) do { } while(0); +#endif + +#define _DBGRTCTM(x, rtctm) if (debug>=x) printk("%s: secs=%d, mins=%d, hours=%d, mday=%d, " \ + "mon=%d, year=%d, wday=%d VL=%d\n", __FUNCTION__, \ + (rtctm).secs, (rtctm).mins, (rtctm).hours, (rtctm).mday, \ + (rtctm).mon, (rtctm).year, (rtctm).wday, (rtctm).vl); + +struct rtc8564_data { + struct i2c_client client; + u16 ctrl; +}; + +static inline u8 _rtc8564_ctrl1(struct i2c_client *client) +{ + struct rtc8564_data *data = i2c_get_clientdata(client); + return data->ctrl & 0xff; +} +static inline u8 _rtc8564_ctrl2(struct i2c_client *client) +{ + struct rtc8564_data *data = i2c_get_clientdata(client); + return (data->ctrl & 0xff00) >> 8; +} + +#define CTRL1(c) _rtc8564_ctrl1(c) +#define CTRL2(c) _rtc8564_ctrl2(c) + +#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10) +#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10) + +static int debug = 0; +MODULE_PARM(debug, "i"); + +static struct i2c_driver rtc8564_driver; + +static unsigned short ignore[] = { I2C_CLIENT_END }; +static unsigned short normal_addr[] = { 0x51, I2C_CLIENT_END }; + +static struct i2c_client_address_data addr_data = { + .normal_i2c = normal_addr, + .normal_i2c_range = ignore, + .probe = ignore, + .probe_range = ignore, + .ignore = ignore, + .ignore_range = ignore, + .force = ignore, +}; + +static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem); +static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem); + +static int rtc8564_read(struct i2c_client *client, unsigned char adr, + unsigned char *buf, unsigned char len) +{ + int ret = -EIO; + unsigned char addr[1] = { adr }; + struct i2c_msg msgs[2] = { + {client->addr, 0, 1, addr}, + {client->addr, I2C_M_RD, len, buf} + }; + + _DBG(1, "client=%p, adr=%d, buf=%p, len=%d", client, adr, buf, len); + + if (!buf || !client) { + ret = -EINVAL; + goto done; + } + + ret = i2c_transfer(client->adapter, msgs, 2); + if (ret == 2) { + ret = 0; + } + +done: + return ret; +} + +static int rtc8564_write(struct i2c_client *client, unsigned char adr, + unsigned char *data, unsigned char len) +{ + int ret = 0; + unsigned char _data[16]; + struct i2c_msg wr; + int i; + + if (!client || !data || len > 15) { + ret = -EINVAL; + goto done; + } + + _DBG(1, "client=%p, adr=%d, buf=%p, len=%d", client, adr, data, len); + + _data[0] = adr; + for (i = 0; i < len; i++) { + _data[i + 1] = data[i]; + _DBG(5, "data[%d] = 0x%02x (%d)", i, data[i], data[i]); + } + + wr.addr = client->addr; + wr.flags = 0; + wr.len = len + 1; + wr.buf = _data; + + ret = i2c_transfer(client->adapter, &wr, 1); + if (ret == 1) { + ret = 0; + } + +done: + return ret; +} + +static int rtc8564_attach(struct i2c_adapter *adap, int addr, int kind) +{ + int ret; + struct i2c_client *new_client; + struct rtc8564_data *d; + unsigned char data[10]; + unsigned char ad[1] = { 0 }; + struct i2c_msg ctrl_wr[1] = { + {addr, 0, 2, data} + }; + struct i2c_msg ctrl_rd[2] = { + {addr, 0, 1, ad}, + {addr, I2C_M_RD, 2, data} + }; + + d = kmalloc(sizeof(struct rtc8564_data), GFP_KERNEL); + if (!d) { + ret = -ENOMEM; + goto done; + } + memset(d, 0, sizeof(struct rtc8564_data)); + new_client = &d->client; + + strlcpy(new_client->name, "RTC8564", I2C_NAME_SIZE); + i2c_set_clientdata(new_client, d); + new_client->id = rtc8564_driver.id; + new_client->flags = I2C_CLIENT_ALLOW_USE | I2C_DF_NOTIFY; + new_client->addr = addr; + new_client->adapter = adap; + new_client->driver = &rtc8564_driver; + + _DBG(1, "client=%p", new_client); + _DBG(1, "client.id=%d", new_client->id); + + /* init ctrl1 reg */ + data[0] = 0; + data[1] = 0; + ret = i2c_transfer(new_client->adapter, ctrl_wr, 1); + if (ret != 1) { + printk(KERN_INFO "rtc8564: cant init ctrl1\n"); + ret = -ENODEV; + goto done; + } + + /* read back ctrl1 and ctrl2 */ + ret = i2c_transfer(new_client->adapter, ctrl_rd, 2); + if (ret != 2) { + printk(KERN_INFO "rtc8564: cant read ctrl\n"); + ret = -ENODEV; + goto done; + } + + d->ctrl = data[0] | (data[1] << 8); + + _DBG(1, "RTC8564_REG_CTRL1=%02x, RTC8564_REG_CTRL2=%02x", + data[0], data[1]); + + ret = i2c_attach_client(new_client); +done: + if (ret) { + kfree(d); + } + return ret; +} + +static int rtc8564_probe(struct i2c_adapter *adap) +{ + return i2c_probe(adap, &addr_data, rtc8564_attach); +} + +static int rtc8564_detach(struct i2c_client *client) +{ + i2c_detach_client(client); + kfree(i2c_get_clientdata(client)); + return 0; +} + +static int rtc8564_get_datetime(struct i2c_client *client, struct rtc_tm *dt) +{ + int ret = -EIO; + unsigned char buf[15]; + + _DBG(1, "client=%p, dt=%p", client, dt); + + if (!dt || !client) + return -EINVAL; + + memset(buf, 0, sizeof(buf)); + + ret = rtc8564_read(client, 0, buf, 15); + if (ret) + return ret; + + /* century stored in minute alarm reg */ + dt->year = BCD_TO_BIN(buf[RTC8564_REG_YEAR]); + dt->year += 100 * BCD_TO_BIN(buf[RTC8564_REG_AL_MIN] & 0x3f); + dt->mday = BCD_TO_BIN(buf[RTC8564_REG_DAY] & 0x3f); + dt->wday = BCD_TO_BIN(buf[RTC8564_REG_WDAY] & 7); + dt->mon = BCD_TO_BIN(buf[RTC8564_REG_MON_CENT] & 0x1f); + + dt->secs = BCD_TO_BIN(buf[RTC8564_REG_SEC] & 0x7f); + dt->vl = (buf[RTC8564_REG_SEC] & 0x80) == 0x80; + dt->mins = BCD_TO_BIN(buf[RTC8564_REG_MIN] & 0x7f); + dt->hours = BCD_TO_BIN(buf[RTC8564_REG_HR] & 0x3f); + + _DBGRTCTM(2, *dt); + + return 0; +} + +static int +rtc8564_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo) +{ + int ret, len = 5; + unsigned char buf[15]; + + _DBG(1, "client=%p, dt=%p", client, dt); + + if (!dt || !client) + return -EINVAL; + + _DBGRTCTM(2, *dt); + + buf[RTC8564_REG_CTRL1] = CTRL1(client) | RTC8564_CTRL1_STOP; + buf[RTC8564_REG_CTRL2] = CTRL2(client); + buf[RTC8564_REG_SEC] = BIN_TO_BCD(dt->secs); + buf[RTC8564_REG_MIN] = BIN_TO_BCD(dt->mins); + buf[RTC8564_REG_HR] = BIN_TO_BCD(dt->hours); + + if (datetoo) { + len += 5; + buf[RTC8564_REG_DAY] = BIN_TO_BCD(dt->mday); + buf[RTC8564_REG_WDAY] = BIN_TO_BCD(dt->wday); + buf[RTC8564_REG_MON_CENT] = BIN_TO_BCD(dt->mon) & 0x1f; + /* century stored in minute alarm reg */ + buf[RTC8564_REG_YEAR] = BIN_TO_BCD(dt->year % 100); + buf[RTC8564_REG_AL_MIN] = BIN_TO_BCD(dt->year / 100); + } + + ret = rtc8564_write(client, 0, buf, len); + if (ret) { + _DBG(1, "error writing data! %d", ret); + } + + buf[RTC8564_REG_CTRL1] = CTRL1(client); + ret = rtc8564_write(client, 0, buf, 1); + if (ret) { + _DBG(1, "error writing data! %d", ret); + } + + return ret; +} + +static int rtc8564_get_ctrl(struct i2c_client *client, unsigned int *ctrl) +{ + struct rtc8564_data *data = i2c_get_clientdata(client); + + if (!ctrl || !client) + return -1; + + *ctrl = data->ctrl; + return 0; +} + +static int rtc8564_set_ctrl(struct i2c_client *client, unsigned int *ctrl) +{ + struct rtc8564_data *data = i2c_get_clientdata(client); + unsigned char buf[2]; + + if (!ctrl || !client) + return -1; + + buf[0] = *ctrl & 0xff; + buf[1] = (*ctrl & 0xff00) >> 8; + data->ctrl = *ctrl; + + return rtc8564_write(client, 0, buf, 2); +} + +static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem) +{ + + if (!mem || !client) + return -EINVAL; + + return rtc8564_read(client, mem->loc, mem->data, mem->nr); +} + +static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem) +{ + + if (!mem || !client) + return -EINVAL; + + return rtc8564_write(client, mem->loc, mem->data, mem->nr); +} + +static int +rtc8564_command(struct i2c_client *client, unsigned int cmd, void *arg) +{ + + _DBG(1, "cmd=%d", cmd); + + switch (cmd) { + case RTC_GETDATETIME: + return rtc8564_get_datetime(client, arg); + + case RTC_SETTIME: + return rtc8564_set_datetime(client, arg, 0); + + case RTC_SETDATETIME: + return rtc8564_set_datetime(client, arg, 1); + + case RTC_GETCTRL: + return rtc8564_get_ctrl(client, arg); + + case RTC_SETCTRL: + return rtc8564_set_ctrl(client, arg); + + case MEM_READ: + return rtc8564_read_mem(client, arg); + + case MEM_WRITE: + return rtc8564_write_mem(client, arg); + + default: + return -EINVAL; + } +} + +static struct i2c_driver rtc8564_driver = { + .owner = THIS_MODULE, + .name = "RTC8564", + .id = I2C_DRIVERID_RTC8564, + .flags = I2C_DF_NOTIFY, + .attach_adapter = rtc8564_probe, + .detach_client = rtc8564_detach, + .command = rtc8564_command +}; + +static __init int rtc8564_init(void) +{ + return i2c_add_driver(&rtc8564_driver); +} + +static __exit void rtc8564_exit(void) +{ + i2c_del_driver(&rtc8564_driver); +} + +MODULE_AUTHOR("Stefan Eletzhofer "); +MODULE_DESCRIPTION("EPSON RTC8564 Driver"); +MODULE_LICENSE("GPL"); + +module_init(rtc8564_init); +module_exit(rtc8564_exit); --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/drivers/i2c/chips/rtc8564.h 2004-05-10 01:19:02.926294192 -0700 @@ -0,0 +1,78 @@ +/* + * linux/drivers/i2c/chips/rtc8564.h + * + * Copyright (C) 2002-2004 Stefan Eletzhofer + * + * based on linux/drivers/acron/char/pcf8583.h + * Copyright (C) 2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +struct rtc_tm { + unsigned char secs; + unsigned char mins; + unsigned char hours; + unsigned char mday; + unsigned char mon; + unsigned short year; /* xxxx 4 digits :) */ + unsigned char wday; + unsigned char vl; +}; + +struct mem { + unsigned int loc; + unsigned int nr; + unsigned char *data; +}; + +#define RTC_GETDATETIME 0 +#define RTC_SETTIME 1 +#define RTC_SETDATETIME 2 +#define RTC_GETCTRL 3 +#define RTC_SETCTRL 4 +#define MEM_READ 5 +#define MEM_WRITE 6 + +#define RTC8564_REG_CTRL1 0x0 /* T 0 S 0 | T 0 0 0 */ +#define RTC8564_REG_CTRL2 0x1 /* 0 0 0 TI/TP | AF TF AIE TIE */ +#define RTC8564_REG_SEC 0x2 /* VL 4 2 1 | 8 4 2 1 */ +#define RTC8564_REG_MIN 0x3 /* x 4 2 1 | 8 4 2 1 */ +#define RTC8564_REG_HR 0x4 /* x x 2 1 | 8 4 2 1 */ +#define RTC8564_REG_DAY 0x5 /* x x 2 1 | 8 4 2 1 */ +#define RTC8564_REG_WDAY 0x6 /* x x x x | x 4 2 1 */ +#define RTC8564_REG_MON_CENT 0x7 /* C x x 1 | 8 4 2 1 */ +#define RTC8564_REG_YEAR 0x8 /* 8 4 2 1 | 8 4 2 1 */ +#define RTC8564_REG_AL_MIN 0x9 /* AE 4 2 1 | 8 4 2 1 */ +#define RTC8564_REG_AL_HR 0xa /* AE 4 2 1 | 8 4 2 1 */ +#define RTC8564_REG_AL_DAY 0xb /* AE x 2 1 | 8 4 2 1 */ +#define RTC8564_REG_AL_WDAY 0xc /* AE x x x | x 4 2 1 */ +#define RTC8564_REG_CLKOUT 0xd /* FE x x x | x x FD1 FD0 */ +#define RTC8564_REG_TCTL 0xe /* TE x x x | x x FD1 FD0 */ +#define RTC8564_REG_TIMER 0xf /* 8 bit binary */ + +/* Control reg */ +#define RTC8564_CTRL1_TEST1 (1<<3) +#define RTC8564_CTRL1_STOP (1<<5) +#define RTC8564_CTRL1_TEST2 (1<<7) + +#define RTC8564_CTRL2_TIE (1<<0) +#define RTC8564_CTRL2_AIE (1<<1) +#define RTC8564_CTRL2_TF (1<<2) +#define RTC8564_CTRL2_AF (1<<3) +#define RTC8564_CTRL2_TI_TP (1<<4) + +/* CLKOUT frequencies */ +#define RTC8564_FD_32768HZ (0x0) +#define RTC8564_FD_1024HZ (0x1) +#define RTC8564_FD_32 (0x2) +#define RTC8564_FD_1HZ (0x3) + +/* Timer CTRL */ +#define RTC8564_TD_4096HZ (0x0) +#define RTC8564_TD_64HZ (0x1) +#define RTC8564_TD_1HZ (0x2) +#define RTC8564_TD_1_60HZ (0x3) + +#define I2C_DRIVERID_RTC8564 0xf000 --- linux-2.6.6/drivers/i2c/chips/via686a.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/i2c/chips/via686a.c 2004-05-10 01:19:02.928293888 -0700 @@ -108,7 +108,7 @@ static const u8 reghyst[] = { 0x3a, 0x3e #define VIA686A_TEMP_MODE_MASK 0x3F #define VIA686A_TEMP_MODE_CONTINUOUS (0x00) -/* Conversions. Rounding and limit checking is only done on the TO_REG +/* Conversions. Limit checking is only done on the TO_REG variants. ********* VOLTAGE CONVERSIONS (Bob Dougherty) ******** @@ -123,49 +123,41 @@ static const u8 reghyst[] = { 0x3a, 0x3e volts = (25*regVal+133)*factor regVal = (volts/factor-133)/25 (These conversions were contributed by Jonathan Teh Soon Yew - ) - - These get us close, but they don't completely agree with what my BIOS - says- they are all a bit low. But, it all we have to go on... */ + ) */ static inline u8 IN_TO_REG(long val, int inNum) { - /* to avoid floating point, we multiply everything by 100. - val is guaranteed to be positive, so we can achieve the effect of - rounding by (...*10+5)/10. Note that the *10 is hidden in the - /250 (which should really be /2500). - At the end, we need to /100 because we *100 everything and we need - to /10 because of the rounding thing, so we /1000. */ + /* To avoid floating point, we multiply constants by 10 (100 for +12V). + Rounding is done (120500 is actually 133000 - 12500). + Remember that val is expressed in 0.001V/bit, which is why we divide + by an additional 10000 (100000 for +12V): 1000 for val and 10 (100) + for the constants. */ if (inNum <= 1) return (u8) - SENSORS_LIMIT(((val * 210240 - 13300) / 250 + 5) / 1000, - 0, 255); + SENSORS_LIMIT((val * 21024 - 1205000) / 250000, 0, 255); else if (inNum == 2) return (u8) - SENSORS_LIMIT(((val * 157370 - 13300) / 250 + 5) / 1000, - 0, 255); + SENSORS_LIMIT((val * 15737 - 1205000) / 250000, 0, 255); else if (inNum == 3) return (u8) - SENSORS_LIMIT(((val * 101080 - 13300) / 250 + 5) / 1000, - 0, 255); + SENSORS_LIMIT((val * 10108 - 1205000) / 250000, 0, 255); else - return (u8) SENSORS_LIMIT(((val * 41714 - 13300) / 250 + 5) - / 1000, 0, 255); + return (u8) + SENSORS_LIMIT((val * 41714 - 12050000) / 2500000, 0, 255); } static inline long IN_FROM_REG(u8 val, int inNum) { - /* to avoid floating point, we multiply everything by 100. - val is guaranteed to be positive, so we can achieve the effect of - rounding by adding 0.5. Or, to avoid fp math, we do (...*10+5)/10. - We need to scale with *100 anyway, so no need to /100 at the end. */ + /* To avoid floating point, we multiply constants by 10 (100 for +12V). + We also multiply them by 1000 because we want 0.001V/bit for the + output value. Rounding is done. */ if (inNum <= 1) - return (long) (((250000 * val + 13300) / 210240 * 10 + 5) /10); + return (long) ((250000 * val + 1330000 + 21024 / 2) / 21024); else if (inNum == 2) - return (long) (((250000 * val + 13300) / 157370 * 10 + 5) /10); + return (long) ((250000 * val + 1330000 + 15737 / 2) / 15737); else if (inNum == 3) - return (long) (((250000 * val + 13300) / 101080 * 10 + 5) /10); + return (long) ((250000 * val + 1330000 + 10108 / 2) / 10108); else - return (long) (((250000 * val + 13300) / 41714 * 10 + 5) /10); + return (long) ((2500000 * val + 13300000 + 41714 / 2) / 41714); } /********* FAN RPM CONVERSIONS ********/ @@ -276,52 +268,31 @@ static const u8 viaLUT[] = 239, 240 }; -/* Converting temps to (8-bit) hyst and over registers - No interpolation here. Just check the limits and go. - The +5 effectively rounds off properly and the +50 is because - the temps start at -50 */ +/* Converting temps to (8-bit) hyst and over registers + No interpolation here. + The +50 is because the temps start at -50 */ static inline u8 TEMP_TO_REG(long val) { - return (u8) - SENSORS_LIMIT(viaLUT[((val <= -500) ? 0 : (val >= 1100) ? 160 : - ((val + 5) / 10 + 50))], 0, 255); + return viaLUT[val <= -50000 ? 0 : val >= 110000 ? 160 : + (val < 0 ? val - 500 : val + 500) / 1000 + 50]; } -/* for 8-bit temperature hyst and over registers - The temp values are already *10, so we don't need to do that. - But we _will_ round these off to the nearest degree with (...*10+5)/10 */ -#define TEMP_FROM_REG(val) ((tempLUT[(val)]*10+5)/10) - -/* for 10-bit temperature readings - You might _think_ this is too long to inline, but's it's really only - called once... */ +/* for 8-bit temperature hyst and over registers */ +#define TEMP_FROM_REG(val) (tempLUT[(val)] * 100) + +/* for 10-bit temperature readings */ static inline long TEMP_FROM_REG10(u16 val) { - /* the temp values are already *10, so we don't need to do that. */ - long temp; u16 eightBits = val >> 2; u16 twoBits = val & 3; - /* handle the extremes first (they won't interpolate well! ;-) */ - if (val == 0) - return (long) tempLUT[0]; - if (val == 1023) - return (long) tempLUT[255]; - - if (twoBits == 0) - return (long) tempLUT[eightBits]; - else { - /* do some interpolation by multipying the lower and upper - bounds by 25, 50 or 75, then /100. */ - temp = ((25 * (4 - twoBits)) * tempLUT[eightBits] - + (25 * twoBits) * tempLUT[eightBits + 1]); - /* increase the magnitude by 50 to achieve rounding. */ - if (temp > 0) - temp += 50; - else - temp -= 50; - return (temp / 100); - } + /* no interpolation for these */ + if (twoBits == 0 || eightBits == 255) + return TEMP_FROM_REG(eightBits); + + /* do some linear interpolation */ + return (tempLUT[eightBits] * (4 - twoBits) + + tempLUT[eightBits + 1] * twoBits) * 25; } #define ALARMS_FROM_REG(val) (val) @@ -375,24 +346,24 @@ static void via686a_init_client(struct i /* 7 voltage sensors */ static ssize_t show_in(struct device *dev, char *buf, int nr) { struct via686a_data *data = via686a_update_device(dev); - return sprintf(buf, "%ld\n", IN_FROM_REG(data->in[nr], nr)*10 ); + return sprintf(buf, "%ld\n", IN_FROM_REG(data->in[nr], nr)); } static ssize_t show_in_min(struct device *dev, char *buf, int nr) { struct via686a_data *data = via686a_update_device(dev); - return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_min[nr], nr)*10 ); + return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_min[nr], nr)); } static ssize_t show_in_max(struct device *dev, char *buf, int nr) { struct via686a_data *data = via686a_update_device(dev); - return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_max[nr], nr)*10 ); + return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_max[nr], nr)); } static ssize_t set_in_min(struct device *dev, const char *buf, size_t count, int nr) { struct i2c_client *client = to_i2c_client(dev); struct via686a_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10)/10; + unsigned long val = simple_strtoul(buf, NULL, 10); data->in_min[nr] = IN_TO_REG(val,nr); via686a_write_value(client, VIA686A_REG_IN_MIN(nr), data->in_min[nr]); @@ -402,7 +373,7 @@ static ssize_t set_in_max(struct device size_t count, int nr) { struct i2c_client *client = to_i2c_client(dev); struct via686a_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10)/10; + unsigned long val = simple_strtoul(buf, NULL, 10); data->in_max[nr] = IN_TO_REG(val,nr); via686a_write_value(client, VIA686A_REG_IN_MAX(nr), data->in_max[nr]); @@ -449,21 +420,21 @@ show_in_offset(4); /* 3 temperatures */ static ssize_t show_temp(struct device *dev, char *buf, int nr) { struct via686a_data *data = via686a_update_device(dev); - return sprintf(buf, "%ld\n", TEMP_FROM_REG10(data->temp[nr])*100 ); + return sprintf(buf, "%ld\n", TEMP_FROM_REG10(data->temp[nr])); } static ssize_t show_temp_over(struct device *dev, char *buf, int nr) { struct via686a_data *data = via686a_update_device(dev); - return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_over[nr])*100); + return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_over[nr])); } static ssize_t show_temp_hyst(struct device *dev, char *buf, int nr) { struct via686a_data *data = via686a_update_device(dev); - return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_hyst[nr])*100); + return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_hyst[nr])); } static ssize_t set_temp_over(struct device *dev, const char *buf, size_t count, int nr) { struct i2c_client *client = to_i2c_client(dev); struct via686a_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10)/100; + int val = simple_strtol(buf, NULL, 10); data->temp_over[nr] = TEMP_TO_REG(val); via686a_write_value(client, VIA686A_REG_TEMP_OVER(nr), data->temp_over[nr]); return count; @@ -472,7 +443,7 @@ static ssize_t set_temp_hyst(struct devi size_t count, int nr) { struct i2c_client *client = to_i2c_client(dev); struct via686a_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10)/100; + int val = simple_strtol(buf, NULL, 10); data->temp_hyst[nr] = TEMP_TO_REG(val); via686a_write_value(client, VIA686A_REG_TEMP_HYST(nr), data->temp_hyst[nr]); return count; @@ -602,7 +573,7 @@ static struct i2c_driver via686a_driver /* This is called when the module is loaded */ static int via686a_attach_adapter(struct i2c_adapter *adapter) { - if (!(adapter->class & I2C_ADAP_CLASS_SMBUS)) + if (!(adapter->class & I2C_CLASS_SMBUS)) return 0; return i2c_detect(adapter, &addr_data, via686a_detect); } --- linux-2.6.6/drivers/i2c/chips/w83781d.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/i2c/chips/w83781d.c 2004-05-10 01:19:02.930293584 -0700 @@ -183,8 +183,10 @@ FAN_TO_REG(long rpm, int div) #define ALARMS_FROM_REG(val) (val) #define PWM_FROM_REG(val) (val) #define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255)) -#define BEEP_MASK_FROM_REG(val) (val) -#define BEEP_MASK_TO_REG(val) ((val) & 0xffffff) +#define BEEP_MASK_FROM_REG(val,type) ((type) == as99127f ? \ + (val) ^ 0x7fff : (val)) +#define BEEP_MASK_TO_REG(val,type) ((type) == as99127f ? \ + (~(val)) & 0x7fff : (val) & 0xffffff) #define BEEP_ENABLE_TO_REG(val) ((val) ? 1 : 0) #define BEEP_ENABLE_FROM_REG(val) ((val) ? 1 : 0) @@ -539,14 +541,18 @@ static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL) #define device_create_file_alarms(client) \ device_create_file(&client->dev, &dev_attr_alarms); -#define show_beep_reg(REG, reg) \ -static ssize_t show_beep_##reg (struct device *dev, char *buf) \ -{ \ - struct w83781d_data *data = w83781d_update_device(dev); \ - return sprintf(buf,"%ld\n", (long)BEEP_##REG##_FROM_REG(data->beep_##reg)); \ +static ssize_t show_beep_mask (struct device *dev, char *buf) +{ + struct w83781d_data *data = w83781d_update_device(dev); + return sprintf(buf, "%ld\n", + (long)BEEP_MASK_FROM_REG(data->beep_mask, data->type)); +} +static ssize_t show_beep_enable (struct device *dev, char *buf) +{ + struct w83781d_data *data = w83781d_update_device(dev); + return sprintf(buf, "%ld\n", + (long)BEEP_ENABLE_FROM_REG(data->beep_enable)); } -show_beep_reg(ENABLE, enable); -show_beep_reg(MASK, mask); #define BEEP_ENABLE 0 /* Store beep_enable */ #define BEEP_MASK 1 /* Store beep_mask */ @@ -562,7 +568,7 @@ store_beep_reg(struct device *dev, const val = simple_strtoul(buf, NULL, 10); if (update_mask == BEEP_MASK) { /* We are storing beep_mask */ - data->beep_mask = BEEP_MASK_TO_REG(val); + data->beep_mask = BEEP_MASK_TO_REG(val, data->type); w83781d_write_value(client, W83781D_REG_BEEP_INTS1, data->beep_mask & 0xff); @@ -905,7 +911,7 @@ device_create_file(&client->dev, &dev_at static int w83781d_attach_adapter(struct i2c_adapter *adapter) { - if (!(adapter->class & I2C_ADAP_CLASS_SMBUS)) + if (!(adapter->class & I2C_CLASS_SMBUS)) return 0; return i2c_detect(adapter, &addr_data, w83781d_detect); } @@ -1330,7 +1336,13 @@ w83781d_detach_client(struct i2c_client return err; } - kfree(i2c_get_clientdata(client)); + if (i2c_get_clientdata(client)==NULL) { + /* subclients */ + kfree(client); + } else { + /* main client */ + kfree(i2c_get_clientdata(client)); + } return 0; } --- linux-2.6.6/drivers/i2c/chips/w83l785ts.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/i2c/chips/w83l785ts.c 2004-05-10 01:19:02.930293584 -0700 @@ -145,7 +145,7 @@ static DEVICE_ATTR(temp1_max, S_IRUGO, s static int w83l785ts_attach_adapter(struct i2c_adapter *adapter) { - if (!(adapter->class & I2C_ADAP_CLASS_SMBUS)) + if (!(adapter->class & I2C_CLASS_SMBUS)) return 0; return i2c_detect(adapter, &addr_data, w83l785ts_detect); } --- linux-2.6.6/drivers/ide/ide.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/ide/ide.c 2004-05-10 01:19:36.552182280 -0700 @@ -608,18 +608,24 @@ EXPORT_SYMBOL(ide_hwif_release_regions); * Unregister restores the hwif structures to the default state. * This is raving bonkers. */ - -void ide_unregister (unsigned int index) +/* XXX(cw) this needs to be able to return an exit code here and the + * callers need to check for this. */ +void ide_unregister(unsigned int index) { ide_drive_t *drive; ide_hwif_t *hwif, *g; ide_hwgroup_t *hwgroup; int irq_count = 0, unit, i; - ide_hwif_t old_hwif; + ide_hwif_t *old_hwif; + + BUG_ON(index >= MAX_HWIFS); + + old_hwif = kmalloc(sizeof(*old_hwif), GFP_KERNEL|__GFP_NOFAIL); + if (!old_hwif) { + printk(KERN_ERR "ide_unregister: unable to allocate memory\n"); + return; + } - if (index >= MAX_HWIFS) - BUG(); - BUG_ON(in_interrupt()); BUG_ON(irqs_disabled()); down(&ide_cfg_sem); @@ -765,122 +771,124 @@ void ide_unregister (unsigned int index) hwif->dma_prdtable = 0; } - old_hwif = *hwif; + *old_hwif = *hwif; init_hwif_data(hwif, index); /* restore hwif data to pristine status */ init_hwif_default(hwif, index); - hwif->hwgroup = old_hwif.hwgroup; + hwif->hwgroup = old_hwif->hwgroup; - hwif->gendev.parent = old_hwif.gendev.parent; + hwif->gendev.parent = old_hwif->gendev.parent; - hwif->proc = old_hwif.proc; + hwif->proc = old_hwif->proc; - hwif->major = old_hwif.major; -// hwif->index = old_hwif.index; -// hwif->channel = old_hwif.channel; - hwif->straight8 = old_hwif.straight8; - hwif->bus_state = old_hwif.bus_state; + hwif->major = old_hwif->major; +// hwif->index = old_hwif->index; +// hwif->channel = old_hwif->channel; + hwif->straight8 = old_hwif->straight8; + hwif->bus_state = old_hwif->bus_state; - hwif->atapi_dma = old_hwif.atapi_dma; - hwif->ultra_mask = old_hwif.ultra_mask; - hwif->mwdma_mask = old_hwif.mwdma_mask; - hwif->swdma_mask = old_hwif.swdma_mask; + hwif->atapi_dma = old_hwif->atapi_dma; + hwif->ultra_mask = old_hwif->ultra_mask; + hwif->mwdma_mask = old_hwif->mwdma_mask; + hwif->swdma_mask = old_hwif->swdma_mask; - hwif->chipset = old_hwif.chipset; - hwif->hold = old_hwif.hold; + hwif->chipset = old_hwif->chipset; + hwif->hold = old_hwif->hold; #ifdef CONFIG_BLK_DEV_IDEPCI - hwif->pci_dev = old_hwif.pci_dev; - hwif->cds = old_hwif.cds; + hwif->pci_dev = old_hwif->pci_dev; + hwif->cds = old_hwif->cds; #endif /* CONFIG_BLK_DEV_IDEPCI */ #if 0 - hwif->hwifops = old_hwif.hwifops; + hwif->hwifops = old_hwif->hwifops; #else - hwif->identify = old_hwif.identify; - hwif->tuneproc = old_hwif.tuneproc; - hwif->speedproc = old_hwif.speedproc; - hwif->selectproc = old_hwif.selectproc; - hwif->reset_poll = old_hwif.reset_poll; - hwif->pre_reset = old_hwif.pre_reset; - hwif->resetproc = old_hwif.resetproc; - hwif->intrproc = old_hwif.intrproc; - hwif->maskproc = old_hwif.maskproc; - hwif->quirkproc = old_hwif.quirkproc; - hwif->busproc = old_hwif.busproc; + hwif->identify = old_hwif->identify; + hwif->tuneproc = old_hwif->tuneproc; + hwif->speedproc = old_hwif->speedproc; + hwif->selectproc = old_hwif->selectproc; + hwif->reset_poll = old_hwif->reset_poll; + hwif->pre_reset = old_hwif->pre_reset; + hwif->resetproc = old_hwif->resetproc; + hwif->intrproc = old_hwif->intrproc; + hwif->maskproc = old_hwif->maskproc; + hwif->quirkproc = old_hwif->quirkproc; + hwif->busproc = old_hwif->busproc; #endif #if 0 - hwif->pioops = old_hwif.pioops; + hwif->pioops = old_hwif->pioops; #else - hwif->ata_input_data = old_hwif.ata_input_data; - hwif->ata_output_data = old_hwif.ata_output_data; - hwif->atapi_input_bytes = old_hwif.atapi_input_bytes; - hwif->atapi_output_bytes = old_hwif.atapi_output_bytes; + hwif->ata_input_data = old_hwif->ata_input_data; + hwif->ata_output_data = old_hwif->ata_output_data; + hwif->atapi_input_bytes = old_hwif->atapi_input_bytes; + hwif->atapi_output_bytes = old_hwif->atapi_output_bytes; #endif #if 0 - hwif->dmaops = old_hwif.dmaops; + hwif->dmaops = old_hwif->dmaops; #else - hwif->ide_dma_read = old_hwif.ide_dma_read; - hwif->ide_dma_write = old_hwif.ide_dma_write; - hwif->ide_dma_begin = old_hwif.ide_dma_begin; - hwif->ide_dma_end = old_hwif.ide_dma_end; - hwif->ide_dma_check = old_hwif.ide_dma_check; - hwif->ide_dma_on = old_hwif.ide_dma_on; - hwif->ide_dma_off_quietly = old_hwif.ide_dma_off_quietly; - hwif->ide_dma_test_irq = old_hwif.ide_dma_test_irq; - hwif->ide_dma_host_on = old_hwif.ide_dma_host_on; - hwif->ide_dma_host_off = old_hwif.ide_dma_host_off; - hwif->ide_dma_verbose = old_hwif.ide_dma_verbose; - hwif->ide_dma_lostirq = old_hwif.ide_dma_lostirq; - hwif->ide_dma_timeout = old_hwif.ide_dma_timeout; + hwif->ide_dma_read = old_hwif->ide_dma_read; + hwif->ide_dma_write = old_hwif->ide_dma_write; + hwif->ide_dma_begin = old_hwif->ide_dma_begin; + hwif->ide_dma_end = old_hwif->ide_dma_end; + hwif->ide_dma_check = old_hwif->ide_dma_check; + hwif->ide_dma_on = old_hwif->ide_dma_on; + hwif->ide_dma_off_quietly = old_hwif->ide_dma_off_quietly; + hwif->ide_dma_test_irq = old_hwif->ide_dma_test_irq; + hwif->ide_dma_host_on = old_hwif->ide_dma_host_on; + hwif->ide_dma_host_off = old_hwif->ide_dma_host_off; + hwif->ide_dma_verbose = old_hwif->ide_dma_verbose; + hwif->ide_dma_lostirq = old_hwif->ide_dma_lostirq; + hwif->ide_dma_timeout = old_hwif->ide_dma_timeout; #endif #if 0 - hwif->iops = old_hwif.iops; + hwif->iops = old_hwif->iops; #else - hwif->OUTB = old_hwif.OUTB; - hwif->OUTBSYNC = old_hwif.OUTBSYNC; - hwif->OUTW = old_hwif.OUTW; - hwif->OUTL = old_hwif.OUTL; - hwif->OUTSW = old_hwif.OUTSW; - hwif->OUTSL = old_hwif.OUTSL; - - hwif->INB = old_hwif.INB; - hwif->INW = old_hwif.INW; - hwif->INL = old_hwif.INL; - hwif->INSW = old_hwif.INSW; - hwif->INSL = old_hwif.INSL; -#endif - - hwif->mmio = old_hwif.mmio; - hwif->rqsize = old_hwif.rqsize; - hwif->no_lba48 = old_hwif.no_lba48; + hwif->OUTB = old_hwif->OUTB; + hwif->OUTBSYNC = old_hwif->OUTBSYNC; + hwif->OUTW = old_hwif->OUTW; + hwif->OUTL = old_hwif->OUTL; + hwif->OUTSW = old_hwif->OUTSW; + hwif->OUTSL = old_hwif->OUTSL; + + hwif->INB = old_hwif->INB; + hwif->INW = old_hwif->INW; + hwif->INL = old_hwif->INL; + hwif->INSW = old_hwif->INSW; + hwif->INSL = old_hwif->INSL; +#endif + + hwif->mmio = old_hwif->mmio; + hwif->rqsize = old_hwif->rqsize; + hwif->no_lba48 = old_hwif->no_lba48; #ifndef CONFIG_BLK_DEV_IDECS - hwif->irq = old_hwif.irq; + hwif->irq = old_hwif->irq; #endif /* CONFIG_BLK_DEV_IDECS */ - hwif->dma_base = old_hwif.dma_base; - hwif->dma_master = old_hwif.dma_master; - hwif->dma_command = old_hwif.dma_command; - hwif->dma_vendor1 = old_hwif.dma_vendor1; - hwif->dma_status = old_hwif.dma_status; - hwif->dma_vendor3 = old_hwif.dma_vendor3; - hwif->dma_prdtable = old_hwif.dma_prdtable; - - hwif->dma_extra = old_hwif.dma_extra; - hwif->config_data = old_hwif.config_data; - hwif->select_data = old_hwif.select_data; - hwif->autodma = old_hwif.autodma; - hwif->udma_four = old_hwif.udma_four; - hwif->no_dsc = old_hwif.no_dsc; + hwif->dma_base = old_hwif->dma_base; + hwif->dma_master = old_hwif->dma_master; + hwif->dma_command = old_hwif->dma_command; + hwif->dma_vendor1 = old_hwif->dma_vendor1; + hwif->dma_status = old_hwif->dma_status; + hwif->dma_vendor3 = old_hwif->dma_vendor3; + hwif->dma_prdtable = old_hwif->dma_prdtable; + + hwif->dma_extra = old_hwif->dma_extra; + hwif->config_data = old_hwif->config_data; + hwif->select_data = old_hwif->select_data; + hwif->autodma = old_hwif->autodma; + hwif->udma_four = old_hwif->udma_four; + hwif->no_dsc = old_hwif->no_dsc; - hwif->hwif_data = old_hwif.hwif_data; + hwif->hwif_data = old_hwif->hwif_data; abort: spin_unlock_irq(&ide_lock); up(&ide_cfg_sem); + + kfree(old_hwif); } EXPORT_SYMBOL(ide_unregister); --- linux-2.6.6/drivers/ide/ide-disk.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/ide/ide-disk.c 2004-05-10 01:19:55.311330456 -0700 @@ -1835,6 +1835,24 @@ static int idedisk_revalidate_disk(struc return 0; } +static void ide_drive_shutdown(struct device * dev) +{ + ide_drive_t * drive = container_of(dev,ide_drive_t,gendev); + + /* safety checks */ + if (!drive->present) + return; + if (drive->media != ide_disk) + return; + printk("Flushing cache: %s \n", drive->name); + ide_cacheflush_p(drive); + /* + * give the hardware time to finish; it may return prematurely to cheat + */ + mdelay(300); +} + + static struct block_device_operations idedisk_ops = { .owner = THIS_MODULE, .open = idedisk_open, @@ -1896,6 +1914,7 @@ static void __exit idedisk_exit (void) static int idedisk_init (void) { + idedisk_driver.gen_driver.shutdown = ide_drive_shutdown; return ide_register_driver(&idedisk_driver); } --- linux-2.6.6/drivers/ide/ide-probe.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/ide/ide-probe.c 2004-05-10 01:19:26.060777216 -0700 @@ -917,8 +917,12 @@ static int ide_init_queue(ide_drive_t *d q->queuedata = HWGROUP(drive); blk_queue_segment_boundary(q, 0xffff); - if (!hwif->rqsize) - hwif->rqsize = hwif->no_lba48 ? 256 : 65536; + if (!hwif->rqsize) { + if (hwif->max_rqsize) + hwif->rqsize = hwif->max_rqsize(drive); + else + hwif->rqsize = hwif->no_lba48 ? 256 : 65536; + } if (hwif->rqsize < max_sectors) max_sectors = hwif->rqsize; blk_queue_max_sectors(q, max_sectors); --- linux-2.6.6/drivers/ide/pci/siimage.c 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/ide/pci/siimage.c 2004-05-10 01:19:26.061777064 -0700 @@ -203,13 +203,12 @@ static byte siimage_ratemask (ide_drive_ else pci_read_config_byte(hwif->pci_dev, 0x8A, &scsc); - if(is_sata(hwif)) - { - if(strstr(drive->id->model, "Maxtor")) + if (is_sata(hwif)) { + if (strstr(drive->id->model, "Maxtor 4D060H3")) return 3; return 4; } - + if ((scsc & 0x30) == 0x10) /* 133 */ mode = 4; else if ((scsc & 0x30) == 0x20) /* 2xPCI */ @@ -1046,25 +1045,34 @@ static void __init init_mmio_iops_siimag hwif->mmio = 2; } -static int is_dev_seagate_sata(ide_drive_t *drive) +/* TODO firmware versions should be added - eric */ +static const char * sil_blacklist [] = { + "ST320012AS", + "ST330013AS", + "ST340017AS", + "ST360015AS", + "ST380023AS", + "ST3120023AS", + "ST340014ASL", + "ST360014ASL", + "ST380011ASL", + "ST3120022ASL", + "ST3160021ASL", +}; + +static unsigned int siimage_sata_max_rqsize(ide_drive_t *drive) { const char *s = &drive->id->model[0]; - unsigned len; + unsigned int n; - if (!drive->present) - return 0; - - len = strnlen(s, sizeof(drive->id->model)); - - if ((len > 4) && (!memcmp(s, "ST", 2))) { - if ((!memcmp(s + len - 2, "AS", 2)) || - (!memcmp(s + len - 3, "ASL", 3))) { - printk(KERN_INFO "%s: applying pessimistic Seagate " - "errata fix\n", drive->name); - return 1; + for (n = 0; n < ARRAY_SIZE(sil_blacklist); n++) + if (!memcmp(sil_blacklist[n], s, strlen(sil_blacklist[n]))) { + printk(KERN_INFO "%s: applying Seagate errata fix\n", + drive->name); + return 15; } - } - return 0; + + return 128; } /** @@ -1087,9 +1095,10 @@ static void __init init_iops_siimage (id hwif->hwif_data = 0; - hwif->rqsize = 128; - if (is_sata(hwif) && is_dev_seagate_sata(&hwif->drives[0])) - hwif->rqsize = 15; + if (is_sata(hwif) && (class_rev <= 0x01)) + hwif->max_rqsize = siimage_sata_max_rqsize; + else + hwif->rqsize = 128; if (pci_get_drvdata(dev) == NULL) return; --- linux-2.6.6/drivers/input/joystick/analog.c 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/input/joystick/analog.c 2004-05-10 01:19:51.853856072 -0700 @@ -142,7 +142,7 @@ struct analog_port { #ifdef __i386__ #define GET_TIME(x) do { if (cpu_has_tsc) rdtscl(x); else x = get_time_pit(); } while (0) -#define DELTA(x,y) (cpu_has_tsc?((y)-(x)):((x)-(y)+((x)<(y)?1193182L/HZ:0))) +#define DELTA(x,y) (cpu_has_tsc ? ((y) - (x)) : ((x) - (y) + ((x) < (y) ? CLOCK_TICK_RATE / HZ : 0))) #define TIME_NAME (cpu_has_tsc?"TSC":"PIT") static unsigned int get_time_pit(void) { --- linux-2.6.6/drivers/input/keyboard/atkbd.c 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/input/keyboard/atkbd.c 2004-05-10 01:19:40.743545096 -0700 @@ -81,13 +81,13 @@ static unsigned char atkbd_set2_keycode[ 82, 83, 80, 76, 77, 72, 1, 69, 87, 78, 81, 74, 55, 73, 70, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 217,100,255, 0, 97,165, 0, 0,156, 0, 0, 0, 0, 0, 0,125, - 173,114, 0,113, 0, 0, 0,126,128, 0, 0,140, 0, 0, 0,127, + 217,100,255, 0, 97,165,172, 0,156, 0, 0, 0, 0, 0,187,125, + 173,114, 0,113, 0, 0,189,126,128, 0, 0,140, 0, 0, 0,127, 159, 0,115, 0,164, 0, 0,116,158, 0,150,166, 0, 0, 0,142, 157, 0, 0, 0, 0, 0, 0, 0,155, 0, 98, 0, 0,163, 0, 0, 226, 0, 0, 0, 0, 0, 0, 0, 0,255, 96, 0, 0, 0,143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0,105,102, 0, 0,112, - 110,111,108,112,106,103, 0,119, 0,118,109, 0, 99,104,119, 0, + 110,111,108,112,106,103,171,119, 0,118,109, 0, 99,104,119, 0, 0, 0, 0, 65, 99, }; @@ -243,7 +243,7 @@ static irqreturn_t atkbd_interrupt(struc goto out; } - if (atkbd->cmdcnt) { + if (atkbd->cmdcnt && atkbd->ack == 1) { atkbd->cmdbuf[--atkbd->cmdcnt] = code; goto out; } @@ -365,10 +365,12 @@ out: * replacement anyway, and they only make a mess in the protocol. */ -static int atkbd_sendbyte(struct atkbd *atkbd, unsigned char byte) +static int atkbd_sendbyte(struct atkbd *atkbd, unsigned char byte, int cmdcnt) { int timeout = 20000; /* 200 msec */ atkbd->ack = 0; + wmb(); /* First clear ACK, then write how many reply bytes we want... though maybe it would want real spinlock */ + atkbd->cmdcnt = cmdcnt; #ifdef ATKBD_DEBUG printk(KERN_DEBUG "atkbd.c: Sent: %02x\n", byte); @@ -393,8 +395,6 @@ static int atkbd_command(struct atkbd *a int receive = (command >> 8) & 0xf; int i; - atkbd->cmdcnt = receive; - if (command == ATKBD_CMD_RESET_BAT) timeout = 2000000; /* 2 sec */ @@ -403,11 +403,11 @@ static int atkbd_command(struct atkbd *a atkbd->cmdbuf[(receive - 1) - i] = param[i]; if (command & 0xff) - if (atkbd_sendbyte(atkbd, command & 0xff)) + if (atkbd_sendbyte(atkbd, command & 0xff, send ? 0 : receive)) return (atkbd->cmdcnt = 0) - 1; for (i = 0; i < send; i++) - if (atkbd_sendbyte(atkbd, param[i])) + if (atkbd_sendbyte(atkbd, param[i], (i != send - 1) ? 0 : receive)) return (atkbd->cmdcnt = 0) - 1; while (atkbd->cmdcnt && timeout--) { --- linux-2.6.6/drivers/input/misc/98spkr.c 2003-06-14 12:17:59.000000000 -0700 +++ 25/drivers/input/misc/98spkr.c 2004-05-10 01:19:51.715877048 -0700 @@ -17,6 +17,7 @@ #include #include #include +#include #include MODULE_AUTHOR("Osamu Tomita "); @@ -44,7 +45,7 @@ static int spkr98_event(struct input_dev } if (value > 20 && value < 32767) - count = CLOCK_TICK_RATE / value; + count = PIT_TICK_RATE / value; spin_lock_irqsave(&i8253_beep_lock, flags); --- linux-2.6.6/drivers/input/misc/Kconfig 2004-04-03 20:39:12.000000000 -0800 +++ 25/drivers/input/misc/Kconfig 2004-05-10 01:19:51.715877048 -0700 @@ -14,7 +14,7 @@ config INPUT_MISC config INPUT_PCSPKR tristate "PC Speaker support" - depends on INPUT && INPUT_MISC + depends on (ALPHA || X86 || X86_64 || MIPS) && INPUT && INPUT_MISC help Say Y here if you want the standard PC Speaker to be used for bells and whistles. --- linux-2.6.6/drivers/input/misc/pcspkr.c 2003-06-16 22:32:21.000000000 -0700 +++ 25/drivers/input/misc/pcspkr.c 2004-05-10 01:19:51.715877048 -0700 @@ -16,6 +16,7 @@ #include #include #include +#include #include MODULE_AUTHOR("Vojtech Pavlik "); @@ -43,7 +44,7 @@ static int pcspkr_event(struct input_dev } if (value > 20 && value < 32767) - count = CLOCK_TICK_RATE / value; + count = PIT_TICK_RATE / value; spin_lock_irqsave(&i8253_beep_lock, flags); --- linux-2.6.6/drivers/input/mouse/psmouse-base.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/input/mouse/psmouse-base.c 2004-05-10 01:19:36.674163736 -0700 @@ -470,7 +470,7 @@ static int psmouse_probe(struct psmouse * Then we reset and disable the mouse so that it doesn't generate events. */ - if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_RESET_DIS)) + if (psmouse_reset(psmouse)) printk(KERN_WARNING "psmouse.c: Failed to reset mouse on %s\n", psmouse->serio->phys); /* --- linux-2.6.6/drivers/input/serio/i8042.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/input/serio/i8042.c 2004-05-10 01:19:57.056065216 -0700 @@ -997,10 +997,14 @@ void __exit i8042_exit(void) sysdev_class_unregister(&kbc_sysclass); } - del_timer_sync(&i8042_timer); - i8042_controller_cleanup(); + /* we must delete the timer AFTER the i8042 chip is cleaned up, + so as to prevent any more interrupts to invoke i8042_interrupt() + which then schedules newer timer events. + */ + del_timer_sync(&i8042_timer); + if (i8042_kbd_values.exists) serio_unregister_port(&i8042_kbd_port); --- linux-2.6.6/drivers/input/serio/serio.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/input/serio/serio.c 2004-05-10 01:19:26.804664128 -0700 @@ -195,9 +195,6 @@ irqreturn_t serio_interrupt(struct serio ret = serio->dev->interrupt(serio, data, flags, regs); } else { if (!flags) { - if ((serio->type == SERIO_8042 || - serio->type == SERIO_8042_XL) && (data != 0xaa)) - return ret; serio_rescan(serio); ret = IRQ_HANDLED; } --- linux-2.6.6/drivers/input/tsdev.c 2004-02-03 20:42:35.000000000 -0800 +++ 25/drivers/input/tsdev.c 2004-05-10 01:19:36.303220128 -0700 @@ -3,9 +3,17 @@ * * Copyright (c) 2001 "Crazy" james Simmons * - * Input driver to Touchscreen device driver module. + * Compaq touchscreen protocol driver. The protocol emulated by this driver + * is obsolete; for new programs use the tslib library which can read directly + * from evdev and perform dejittering, variance filtering and calibration - + * all in user space, not at kernel level. The meaning of this driver is + * to allow usage of newer input drivers with old applications that use the + * old /dev/h3600_ts and /dev/h3600_tsraw devices. * - * Sponsored by Transvirtual Technology + * 09-Apr-2004: Andrew Zabolotny + * Fixed to actually work, not just output random numbers. + * Added support for both h3600_ts and h3600_tsraw protocol + * emulation. */ /* @@ -24,11 +32,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to . + * e-mail - mail your message to . */ #define TSDEV_MINOR_BASE 128 #define TSDEV_MINORS 32 +/* First 16 devices are h3600_ts compatible; second 16 are h3600_tsraw */ +#define TSDEV_MINOR_MASK 15 #define TSDEV_BUFFER_SIZE 64 #include @@ -52,48 +62,84 @@ #define CONFIG_INPUT_TSDEV_SCREEN_Y 320 #endif +/* This driver emulates both protocols of the old h3600_ts and h3600_tsraw + * devices. The first one must output X/Y data in 'cooked' format, e.g. + * filtered, dejittered and calibrated. Second device just outputs raw + * data received from the hardware. + * + * This driver doesn't support filtering and dejittering; it supports only + * calibration. Filtering and dejittering must be done in the low-level + * driver, if needed, because it may gain additional benefits from knowing + * the low-level details, the nature of noise and so on. + * + * The driver precomputes a calibration matrix given the initial xres and + * yres values (quite innacurate for most touchscreens) that will result + * in a more or less expected range of output values. The driver supports + * the TS_SET_CAL ioctl, which will replace the calibration matrix with a + * new one, supposedly generated from the values taken from the raw device. + */ + MODULE_AUTHOR("James Simmons "); MODULE_DESCRIPTION("Input driver to touchscreen converter"); MODULE_LICENSE("GPL"); static int xres = CONFIG_INPUT_TSDEV_SCREEN_X; module_param(xres, uint, 0); -MODULE_PARM_DESC(xres, "Horizontal screen resolution"); +MODULE_PARM_DESC(xres, "Horizontal screen resolution (can be negative for X-mirror)"); static int yres = CONFIG_INPUT_TSDEV_SCREEN_Y; module_param(yres, uint, 0); -MODULE_PARM_DESC(yres, "Vertical screen resolution"); +MODULE_PARM_DESC(yres, "Vertical screen resolution (can be negative for Y-mirror)"); + +/* From Compaq's Touch Screen Specification version 0.2 (draft) */ +struct ts_event { + short pressure; + short x; + short y; + short millisecs; +}; + +struct ts_calibration { + int xscale; + int xtrans; + int yscale; + int ytrans; + int xyswap; +}; struct tsdev { int exist; int open; int minor; - char name[16]; + char name[8]; wait_queue_head_t wait; struct list_head list; struct input_handle handle; + int x, y, pressure; + struct ts_calibration cal; }; -/* From Compaq's Touch Screen Specification version 0.2 (draft) */ -typedef struct { - short pressure; - short x; - short y; - short millisecs; -} TS_EVENT; - struct tsdev_list { struct fasync_struct *fasync; struct list_head node; struct tsdev *tsdev; int head, tail; - int oldx, oldy, pendown; - TS_EVENT event[TSDEV_BUFFER_SIZE]; + struct ts_event event[TSDEV_BUFFER_SIZE]; + int raw; }; +/* The following ioctl codes are defined ONLY for backward compatibility. + * Don't use tsdev for new developement; use the tslib library instead. + * Touchscreen calibration is a fully userspace task. + */ +/* Use 'f' as magic number */ +#define IOC_H3600_TS_MAGIC 'f' +#define TS_GET_CAL _IOR(IOC_H3600_TS_MAGIC, 10, struct ts_calibration) +#define TS_SET_CAL _IOW(IOC_H3600_TS_MAGIC, 11, struct ts_calibration) + static struct input_handler tsdev_handler; -static struct tsdev *tsdev_table[TSDEV_MINORS]; +static struct tsdev *tsdev_table[TSDEV_MINORS/2]; static int tsdev_fasync(int fd, struct file *file, int on) { @@ -109,13 +155,16 @@ static int tsdev_open(struct inode *inod int i = iminor(inode) - TSDEV_MINOR_BASE; struct tsdev_list *list; - if (i >= TSDEV_MINORS || !tsdev_table[i]) + if (i >= TSDEV_MINORS || !tsdev_table[i & TSDEV_MINOR_MASK]) return -ENODEV; if (!(list = kmalloc(sizeof(struct tsdev_list), GFP_KERNEL))) return -ENOMEM; memset(list, 0, sizeof(struct tsdev_list)); + list->raw = (i >= TSDEV_MINORS/2) ? 1 : 0; + + i &= TSDEV_MINOR_MASK; list->tsdev = tsdev_table[i]; list_add_tail(&list->node, &tsdev_table[i]->list); file->private_data = list; @@ -169,11 +218,13 @@ static ssize_t tsdev_read(struct file *f if (!list->tsdev->exist) return -ENODEV; - while (list->head != list->tail && retval + sizeof(TS_EVENT) <= count) { - if (copy_to_user (buffer + retval, list->event + list->tail, sizeof(TS_EVENT))) + while (list->head != list->tail && + retval + sizeof (struct ts_event) <= count) { + if (copy_to_user (buffer + retval, list->event + list->tail, + sizeof (struct ts_event))) return -EFAULT; list->tail = (list->tail + 1) & (TSDEV_BUFFER_SIZE - 1); - retval += sizeof(TS_EVENT); + retval += sizeof (struct ts_event); } return retval; @@ -193,22 +244,27 @@ static unsigned int tsdev_poll(struct fi static int tsdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { -/* struct tsdev_list *list = file->private_data; - struct tsdev *evdev = list->tsdev; - struct input_dev *dev = tsdev->handle.dev; - int retval; - + struct tsdev *tsdev = list->tsdev; + int retval = 0; + switch (cmd) { - case HHEHE: - return 0; - case hjff: - return 0; - default: - return 0; + case TS_GET_CAL: + if (copy_to_user ((void *)arg, &tsdev->cal, + sizeof (struct ts_calibration))) + retval = -EFAULT; + break; + case TS_SET_CAL: + if (copy_from_user (&tsdev->cal, (void *)arg, + sizeof (struct ts_calibration))) + retval = -EFAULT; + break; + default: + retval = -EINVAL; + break; } -*/ - return -EINVAL; + + return retval; } struct file_operations tsdev_fops = { @@ -227,82 +283,85 @@ static void tsdev_event(struct input_han struct tsdev *tsdev = handle->private; struct tsdev_list *list; struct timeval time; - int size; - list_for_each_entry(list, &tsdev->list, node) { - switch (type) { - case EV_ABS: - switch (code) { - case ABS_X: - if (!list->pendown) - return; - size = handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X]; - if (size > 0) - list->oldx = ((value - handle->dev->absmin[ABS_X]) * xres / size); - else - list->oldx = ((value - handle->dev->absmin[ABS_X])); - break; - case ABS_Y: - if (!list->pendown) - return; - size = handle->dev->absmax[ABS_Y] - handle->dev->absmin[ABS_Y]; - if (size > 0) - list->oldy = ((value - handle->dev->absmin[ABS_Y]) * yres / size); - else - list->oldy = ((value - handle->dev->absmin[ABS_Y])); - break; - case ABS_PRESSURE: - list->pendown = ((value > handle->dev-> absmin[ABS_PRESSURE])) ? - value - handle->dev->absmin[ABS_PRESSURE] : 0; - break; - } + switch (type) { + case EV_ABS: + switch (code) { + case ABS_X: + tsdev->x = value; + break; + case ABS_Y: + tsdev->y = value; + break; + case ABS_PRESSURE: + if (value > handle->dev->absmax[ABS_PRESSURE]) + value = handle->dev->absmax[ABS_PRESSURE]; + value -= handle->dev->absmin[ABS_PRESSURE]; + if (value < 0) + value = 0; + tsdev->pressure = value; + break; + } + break; + + case EV_REL: + switch (code) { + case REL_X: + tsdev->x += value; + if (tsdev->x < 0) + tsdev->x = 0; + else if (tsdev->x > xres) + tsdev->x = xres; + break; + case REL_Y: + tsdev->y += value; + if (tsdev->y < 0) + tsdev->y = 0; + else if (tsdev->y > yres) + tsdev->y = yres; break; + } + break; - case EV_REL: - switch (code) { - case REL_X: - if (!list->pendown) - return; - list->oldx += value; - if (list->oldx < 0) - list->oldx = 0; - else if (list->oldx > xres) - list->oldx = xres; + case EV_KEY: + if (code == BTN_TOUCH || code == BTN_MOUSE) { + switch (value) { + case 0: + tsdev->pressure = 0; break; - case REL_Y: - if (!list->pendown) - return; - list->oldy += value; - if (list->oldy < 0) - list->oldy = 0; - else if (list->oldy > xres) - list->oldy = xres; + case 1: + if (!tsdev->pressure) + tsdev->pressure = 1; break; } - break; - - case EV_KEY: - if (code == BTN_TOUCH || code == BTN_MOUSE) { - switch (value) { - case 0: - list->pendown = 0; - break; - case 1: - if (!list->pendown) - list->pendown = 1; - break; - case 2: - return; - } - } else - return; - break; } + break; + } + + if (type != EV_SYN || code != SYN_REPORT) + return; + + list_for_each_entry(list, &tsdev->list, node) { + int x, y, tmp; + do_gettimeofday(&time); list->event[list->head].millisecs = time.tv_usec / 100; - list->event[list->head].pressure = list->pendown; - list->event[list->head].x = list->oldx; - list->event[list->head].y = list->oldy; + list->event[list->head].pressure = tsdev->pressure; + + x = tsdev->x; + y = tsdev->y; + + /* Calibration */ + if (!list->raw) { + x = ((x * tsdev->cal.xscale) >> 8) + tsdev->cal.xtrans; + y = ((y * tsdev->cal.yscale) >> 8) + tsdev->cal.ytrans; + if (tsdev->cal.xyswap) { + tmp = x; x = y; y = tmp; + } + } + + list->event[list->head].x = x; + list->event[list->head].y = y; list->head = (list->head + 1) & (TSDEV_BUFFER_SIZE - 1); kill_fasync(&list->fasync, SIGIO, POLL_IN); } @@ -314,11 +373,11 @@ static struct input_handle *tsdev_connec struct input_device_id *id) { struct tsdev *tsdev; - int minor; + int minor, delta; - for (minor = 0; minor < TSDEV_MINORS && tsdev_table[minor]; + for (minor = 0; minor < TSDEV_MINORS/2 && tsdev_table[minor]; minor++); - if (minor == TSDEV_MINORS) { + if (minor >= TSDEV_MINORS/2) { printk(KERN_ERR "tsdev: You have way too many touchscreens\n"); return NULL; @@ -340,10 +399,25 @@ static struct input_handle *tsdev_connec tsdev->handle.handler = handler; tsdev->handle.private = tsdev; + /* Precompute the rough calibration matrix */ + delta = dev->absmax [ABS_X] - dev->absmin [ABS_X] + 1; + if (delta == 0) + delta = 1; + tsdev->cal.xscale = (xres << 8) / delta; + tsdev->cal.xtrans = - ((dev->absmin [ABS_X] * tsdev->cal.xscale) >> 8); + + delta = dev->absmax [ABS_Y] - dev->absmin [ABS_Y] + 1; + if (delta == 0) + delta = 1; + tsdev->cal.yscale = (yres << 8) / delta; + tsdev->cal.ytrans = - ((dev->absmin [ABS_Y] * tsdev->cal.yscale) >> 8); + tsdev_table[minor] = tsdev; - + devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor), S_IFCHR|S_IRUGO|S_IWUSR, "input/ts%d", minor); + devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor + TSDEV_MINORS/2), + S_IFCHR|S_IRUGO|S_IWUSR, "input/tsraw%d", minor); class_simple_device_add(input_class, MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor), dev->dev, "ts%d", minor); @@ -362,6 +436,7 @@ static void tsdev_disconnect(struct inpu wake_up_interruptible(&tsdev->wait); } else tsdev_free(tsdev); + devfs_remove("input/tsraw%d", tsdev->minor); } static struct input_device_id tsdev_ids[] = { @@ -379,6 +454,12 @@ static struct input_device_id tsdev_ids[ .absbit = { BIT(ABS_X) | BIT(ABS_Y) }, },/* A tablet like device, at least touch detection, two absolute axes */ + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, + .evbit = { BIT(EV_ABS) }, + .absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) }, + },/* A tablet like device with several gradations of pressure */ + {},/* Terminating entry */ }; --- linux-2.6.6/drivers/isdn/hisax/st5481_b.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/isdn/hisax/st5481_b.c 2004-05-10 01:19:05.758863576 -0700 @@ -257,13 +257,18 @@ static void st5481B_mode(struct st5481_b static int st5481_setup_b_out(struct st5481_bcs *bcs) { struct usb_device *dev = bcs->adapter->usb_dev; - struct usb_host_interface *altsetting; + struct usb_interface *intf; + struct usb_host_interface *altsetting = NULL; struct usb_host_endpoint *endpoint; struct st5481_b_out *b_out = &bcs->b_out; DBG(4,""); - altsetting = &(dev->config->interface[0]->altsetting[3]); + intf = usb_ifnum_to_if(dev, 0); + if (intf) + altsetting = usb_altnum_to_altsetting(intf, 3); + if (!altsetting) + return -ENXIO; // Allocate URBs and buffers for the B channel out endpoint = &altsetting->endpoint[EP_B1_OUT - 1 + bcs->channel * 2]; --- linux-2.6.6/drivers/isdn/hisax/st5481_d.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/isdn/hisax/st5481_d.c 2004-05-10 01:19:05.759863424 -0700 @@ -652,13 +652,18 @@ static void ph_disconnect(struct st5481_ static int st5481_setup_d_out(struct st5481_adapter *adapter) { struct usb_device *dev = adapter->usb_dev; - struct usb_host_interface *altsetting; + struct usb_interface *intf; + struct usb_host_interface *altsetting = NULL; struct usb_host_endpoint *endpoint; struct st5481_d_out *d_out = &adapter->d_out; DBG(2,""); - altsetting = &(dev->config->interface[0]->altsetting[3]); + intf = usb_ifnum_to_if(dev, 0); + if (intf) + altsetting = usb_altnum_to_altsetting(intf, 3); + if (!altsetting) + return -ENXIO; // Allocate URBs and buffers for the D channel out endpoint = &altsetting->endpoint[EP_D_OUT-1]; --- linux-2.6.6/drivers/isdn/hisax/st5481_usb.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/isdn/hisax/st5481_usb.c 2004-05-10 01:19:05.760863272 -0700 @@ -244,7 +244,8 @@ int st5481_setup_usb(struct st5481_adapt struct usb_device *dev = adapter->usb_dev; struct st5481_ctrl *ctrl = &adapter->ctrl; struct st5481_intr *intr = &adapter->intr; - struct usb_host_interface *altsetting; + struct usb_interface *intf; + struct usb_host_interface *altsetting = NULL; struct usb_host_endpoint *endpoint; int status; struct urb *urb; @@ -257,8 +258,11 @@ int st5481_setup_usb(struct st5481_adapt return status; } - - altsetting = &(dev->config->interface[0]->altsetting[3]); + intf = usb_ifnum_to_if(dev, 0); + if (intf) + altsetting = usb_altnum_to_altsetting(intf, 3); + if (!altsetting) + return -ENXIO; // Check if the config is sane if ( altsetting->desc.bNumEndpoints != 7 ) { --- linux-2.6.6/drivers/macintosh/adb.c 2004-02-17 20:48:43.000000000 -0800 +++ 25/drivers/macintosh/adb.c 2004-05-10 01:19:02.088421568 -0700 @@ -10,7 +10,7 @@ * * To do: * - * - /proc/adb to list the devices and infos + * - /sys/bus/adb to list the devices and infos * - more /dev/adb to allow userland to receive the * flow of auto-polling datas from a given device. * - move bus probe to a kernel thread @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -36,6 +35,7 @@ #include #include #include +#include #include #include #ifdef CONFIG_PPC @@ -75,6 +75,8 @@ static struct adb_driver *adb_driver_lis NULL }; +static struct class_simple *adb_dev_class; + struct adb_driver *adb_controller; struct notifier_block *adb_client_list = NULL; static int adb_got_sleep; @@ -883,6 +885,7 @@ out: } static struct file_operations adb_fops = { + .owner = THIS_MODULE, .llseek = no_llseek, .read = adb_read, .write = adb_write, @@ -893,9 +896,13 @@ static struct file_operations adb_fops = static void adbdev_init(void) { - if (register_chrdev(ADB_MAJOR, "adb", &adb_fops)) + if (register_chrdev(ADB_MAJOR, "adb", &adb_fops)) { printk(KERN_ERR "adb: unable to get major %d\n", ADB_MAJOR); - else - devfs_mk_cdev(MKDEV(ADB_MAJOR, 0), - S_IFCHR | S_IRUSR | S_IWUSR, "adb"); + return; + } + adb_dev_class = class_simple_create(THIS_MODULE, "adb"); + if (IS_ERR(adb_dev_class)) { + return; + } + class_simple_device_add(adb_dev_class, MKDEV(ADB_MAJOR, 0), NULL, "adb"); } --- linux-2.6.6/drivers/macintosh/Kconfig 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/macintosh/Kconfig 2004-05-10 01:19:40.986508160 -0700 @@ -127,7 +127,7 @@ config MAC_FLOPPY config MAC_SERIAL tristate "Support for PowerMac serial ports (OBSOLETE DRIVER)" - depends on PPC_PMAC + depends on PPC_PMAC && BROKEN help This driver is obsolete. Use CONFIG_SERIAL_PMACZILOG in "Character devices --> Serial drivers --> PowerMac z85c30" option. --- linux-2.6.6/drivers/media/dvb/frontends/alps_tdlb7.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/media/dvb/frontends/alps_tdlb7.c 2004-05-10 01:19:49.407228016 -0700 @@ -57,8 +57,6 @@ static int debug = 0; #define SP8870_FIRMWARE_OFFSET 0x0A -static int errno; - static struct dvb_frontend_info tdlb7_info = { .name = "Alps TDLB7", .type = FE_OFDM, --- linux-2.6.6/drivers/media/dvb/frontends/sp887x.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/media/dvb/frontends/sp887x.c 2004-05-10 01:19:49.408227864 -0700 @@ -68,8 +68,6 @@ struct dvb_frontend_info sp887x_info = { FE_CAN_RECOVER }; -static int errno; - static int i2c_writebytes (struct dvb_frontend *fe, u8 addr, u8 *buf, u8 len) { --- linux-2.6.6/drivers/media/video/bt832.c 2003-11-23 19:03:00.000000000 -0800 +++ 25/drivers/media/video/bt832.c 2004-05-10 01:19:02.931293432 -0700 @@ -197,7 +197,7 @@ static int bt832_attach(struct i2c_adapt static int bt832_probe(struct i2c_adapter *adap) { - if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) + if (adap->class & I2C_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, bt832_attach); return 0; } --- linux-2.6.6/drivers/media/video/bttv-i2c.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/media/video/bttv-i2c.c 2004-05-10 01:19:02.931293432 -0700 @@ -108,8 +108,8 @@ static struct i2c_adapter bttv_i2c_adap_ .inc_use = bttv_inc_use, .dec_use = bttv_dec_use, #endif -#ifdef I2C_ADAP_CLASS_TV_ANALOG - .class = I2C_ADAP_CLASS_TV_ANALOG, +#ifdef I2C_CLASS_TV_ANALOG + .class = I2C_CLASS_TV_ANALOG, #endif I2C_DEVNAME("bt848"), .id = I2C_HW_B_BT848, @@ -291,8 +291,8 @@ static struct i2c_adapter bttv_i2c_adap_ .inc_use = bttv_inc_use, .dec_use = bttv_dec_use, #endif -#ifdef I2C_ADAP_CLASS_TV_ANALOG - .class = I2C_ADAP_CLASS_TV_ANALOG, +#ifdef I2C_CLASS_TV_ANALOG + .class = I2C_CLASS_TV_ANALOG, #endif I2C_DEVNAME("bt878"), .id = I2C_ALGO_BIT | I2C_HW_B_BT848 /* FIXME */, --- linux-2.6.6/drivers/media/video/cpia_usb.c 2003-08-08 22:55:12.000000000 -0700 +++ 25/drivers/media/video/cpia_usb.c 2004-05-10 01:19:05.760863272 -0700 @@ -499,7 +499,7 @@ static int cpia_probe(struct usb_interfa if (udev->descriptor.bNumConfigurations != 1) return -ENODEV; - interface = &intf->altsetting[0]; + interface = intf->cur_altsetting; printk(KERN_INFO "USB CPiA camera found\n"); @@ -620,8 +620,6 @@ static void cpia_disconnect(struct usb_i wake_up_interruptible(&ucpia->wq_stream); udev = interface_to_usbdev(intf); - usb_driver_release_interface(&cpia_driver, - udev->actconfig->interface[0]); ucpia->curbuff = ucpia->workbuff = NULL; --- linux-2.6.6/drivers/media/video/cx88/cx88-i2c.c 2004-05-09 21:07:23.000000000 -0700 +++ 25/drivers/media/video/cx88/cx88-i2c.c 2004-05-10 01:19:02.932293280 -0700 @@ -128,8 +128,8 @@ static struct i2c_adapter cx8800_i2c_ada .inc_use = cx8800_inc_use, .dec_use = cx8800_dec_use, #endif -#ifdef I2C_ADAP_CLASS_TV_ANALOG - .class = I2C_ADAP_CLASS_TV_ANALOG, +#ifdef I2C_CLASS_TV_ANALOG + .class = I2C_CLASS_TV_ANALOG, #endif I2C_DEVNAME("cx2388x"), .id = I2C_HW_B_BT848, --- linux-2.6.6/drivers/media/video/dpc7146.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/media/video/dpc7146.c 2004-05-10 01:19:02.932293280 -0700 @@ -106,7 +106,7 @@ static int dpc_probe(struct saa7146_dev* video port pins should be enabled here ?! */ saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26)); - saa7146_i2c_adapter_prepare(dev, &dpc->i2c_adapter, I2C_ADAP_CLASS_TV_ANALOG, SAA7146_I2C_BUS_BIT_RATE_480); + saa7146_i2c_adapter_prepare(dev, &dpc->i2c_adapter, I2C_CLASS_TV_ANALOG, SAA7146_I2C_BUS_BIT_RATE_480); if(i2c_add_adapter(&dpc->i2c_adapter) < 0) { DEB_S(("cannot register i2c-device. skipping.\n")); kfree(dpc); --- linux-2.6.6/drivers/media/video/hexium_gemini.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/media/video/hexium_gemini.c 2004-05-10 01:19:02.933293128 -0700 @@ -250,7 +250,7 @@ static int hexium_attach(struct saa7146_ /* enable i2c-port pins */ saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26)); - saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, I2C_ADAP_CLASS_TV_ANALOG, SAA7146_I2C_BUS_BIT_RATE_480); + saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, I2C_CLASS_TV_ANALOG, SAA7146_I2C_BUS_BIT_RATE_480); if (i2c_add_adapter(&hexium->i2c_adapter) < 0) { DEB_S(("cannot register i2c-device. skipping.\n")); kfree(hexium); --- linux-2.6.6/drivers/media/video/hexium_orion.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/media/video/hexium_orion.c 2004-05-10 01:19:02.933293128 -0700 @@ -237,7 +237,7 @@ static int hexium_probe(struct saa7146_d saa7146_write(dev, DD1_STREAM_B, 0x00000000); saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26)); - saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, I2C_ADAP_CLASS_TV_ANALOG, SAA7146_I2C_BUS_BIT_RATE_480); + saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, I2C_CLASS_TV_ANALOG, SAA7146_I2C_BUS_BIT_RATE_480); if (i2c_add_adapter(&hexium->i2c_adapter) < 0) { DEB_S(("cannot register i2c-device. skipping.\n")); kfree(hexium); --- linux-2.6.6/drivers/media/video/msp3400.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/media/video/msp3400.c 2004-05-10 01:19:02.935292824 -0700 @@ -1353,8 +1353,8 @@ static int msp_detach(struct i2c_client static int msp_probe(struct i2c_adapter *adap) { -#ifdef I2C_ADAP_CLASS_TV_ANALOG - if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) +#ifdef I2C_CLASS_TV_ANALOG + if (adap->class & I2C_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, msp_attach); #else switch (adap->id) { --- linux-2.6.6/drivers/media/video/mxb.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/media/video/mxb.c 2004-05-10 01:19:02.935292824 -0700 @@ -223,7 +223,7 @@ static int mxb_probe(struct saa7146_dev* video port pins should be enabled here ?! */ saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26)); - saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, I2C_ADAP_CLASS_TV_ANALOG, SAA7146_I2C_BUS_BIT_RATE_480); + saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, I2C_CLASS_TV_ANALOG, SAA7146_I2C_BUS_BIT_RATE_480); if(i2c_add_adapter(&mxb->i2c_adapter) < 0) { DEB_S(("cannot register i2c-device. skipping.\n")); kfree(mxb); --- linux-2.6.6/drivers/media/video/saa5246a.c 2004-03-10 20:41:28.000000000 -0800 +++ 25/drivers/media/video/saa5246a.c 2004-05-10 01:19:02.936292672 -0700 @@ -143,7 +143,7 @@ static int saa5246a_attach(struct i2c_ad */ static int saa5246a_probe(struct i2c_adapter *adap) { - if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) + if (adap->class & I2C_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, saa5246a_attach); return 0; } --- linux-2.6.6/drivers/media/video/saa5249.c 2004-03-10 20:41:28.000000000 -0800 +++ 25/drivers/media/video/saa5249.c 2004-05-10 01:19:02.937292520 -0700 @@ -219,7 +219,7 @@ static int saa5249_attach(struct i2c_ada static int saa5249_probe(struct i2c_adapter *adap) { - if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) + if (adap->class & I2C_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, saa5249_attach); return 0; } --- linux-2.6.6/drivers/media/video/saa7111.c 2003-10-08 15:07:09.000000000 -0700 +++ 25/drivers/media/video/saa7111.c 2004-05-10 01:19:52.326784176 -0700 @@ -9,6 +9,9 @@ * Changes by Ronald Bultje * - moved over to linux>=2.4.x i2c protocol (1/1/2003) * + * Changes by Michael Hunold + * - implemented DECODER_SET_GPIO, DECODER_INIT, DECODER_SET_VBI_BYPASS + * * 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 @@ -112,7 +115,7 @@ saa7111_write_block (struct i2c_client * u8 block_data[32]; msg.addr = client->addr; - msg.flags = client->flags; + msg.flags = 0; while (len >= 2) { msg.buf = (char *) block_data; msg.len = 0; @@ -142,6 +145,13 @@ saa7111_write_block (struct i2c_client * return ret; } +static int +saa7111_init_decoder (struct i2c_client *client, + struct video_decoder_init *init) +{ + return saa7111_write_block(client, init->data, init->len); +} + static inline int saa7111_read (struct i2c_client *client, u8 reg) @@ -151,7 +161,7 @@ saa7111_read (struct i2c_client *client, /* ----------------------------------------------------------------------- */ -static const unsigned char init[] = { +static const unsigned char saa7111_i2c_init[] = { 0x00, 0x00, /* 00 - ID byte */ 0x01, 0x00, /* 01 - reserved */ @@ -201,8 +211,18 @@ saa7111_command (struct i2c_client *clie switch (cmd) { case 0: - //saa7111_write_block(client, init, sizeof(init)); - break; + case DECODER_INIT: + { + struct video_decoder_init *init = arg; + if (NULL != init) + return saa7111_init_decoder(client, init); + else { + struct video_decoder_init vdi; + vdi.data = saa7111_i2c_init; + vdi.len = sizeof(saa7111_i2c_init); + return saa7111_init_decoder(client, &vdi); + } + } case DECODER_DUMP: { @@ -274,6 +294,32 @@ saa7111_command (struct i2c_client *clie } break; + case DECODER_SET_GPIO: + { + int *iarg = arg; + if (0 != *iarg) { + saa7111_write(client, 0x11, + (decoder->reg[0x11] | 0x80)); + } else { + saa7111_write(client, 0x11, + (decoder->reg[0x11] & 0x7f)); + } + break; + } + + case DECODER_SET_VBI_BYPASS: + { + int *iarg = arg; + if (0 != *iarg) { + saa7111_write(client, 0x13, + (decoder->reg[0x13] & 0xf0) | 0x0a); + } else { + saa7111_write(client, 0x13, + (decoder->reg[0x13] & 0xf0)); + } + break; + } + case DECODER_SET_NORM: { int *iarg = arg; @@ -465,6 +511,7 @@ saa7111_detect_client (struct i2c_adapte int i; struct i2c_client *client; struct saa7111 *decoder; + struct video_decoder_init vdi; dprintk(1, KERN_INFO @@ -509,7 +556,9 @@ saa7111_detect_client (struct i2c_adapte return i; } - i = saa7111_write_block(client, init, sizeof(init)); + vdi.data = saa7111_i2c_init; + vdi.len = sizeof(saa7111_i2c_init); + i = saa7111_init_decoder(client, &vdi); if (i < 0) { dprintk(1, KERN_ERR "%s_attach error: init status %d\n", I2C_NAME(client), i); --- linux-2.6.6/drivers/media/video/saa7134/saa6752hs.c 2004-02-03 20:42:36.000000000 -0800 +++ 25/drivers/media/video/saa7134/saa6752hs.c 2004-05-10 01:19:02.937292520 -0700 @@ -335,7 +335,7 @@ static int saa6752hs_attach(struct i2c_a static int saa6752hs_probe(struct i2c_adapter *adap) { - if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) + if (adap->class & I2C_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, saa6752hs_attach); return 0; --- linux-2.6.6/drivers/media/video/saa7134/saa7134-i2c.c 2003-10-08 15:07:09.000000000 -0700 +++ 25/drivers/media/video/saa7134/saa7134-i2c.c 2004-05-10 01:19:02.938292368 -0700 @@ -347,8 +347,8 @@ static struct i2c_adapter saa7134_adap_t .inc_use = inc_use, .dec_use = dec_use, #endif -#ifdef I2C_ADAP_CLASS_TV_ANALOG - .class = I2C_ADAP_CLASS_TV_ANALOG, +#ifdef I2C_CLASS_TV_ANALOG + .class = I2C_CLASS_TV_ANALOG, #endif I2C_DEVNAME("saa7134"), .id = I2C_ALGO_SAA7134, --- linux-2.6.6/drivers/media/video/tda7432.c 2004-02-03 20:42:36.000000000 -0800 +++ 25/drivers/media/video/tda7432.c 2004-05-10 01:19:02.938292368 -0700 @@ -338,8 +338,8 @@ static int tda7432_attach(struct i2c_ada static int tda7432_probe(struct i2c_adapter *adap) { -#ifdef I2C_ADAP_CLASS_TV_ANALOG - if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) +#ifdef I2C_CLASS_TV_ANALOG + if (adap->class & I2C_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, tda7432_attach); #else if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) --- linux-2.6.6/drivers/media/video/tda9875.c 2004-02-03 20:42:36.000000000 -0800 +++ 25/drivers/media/video/tda9875.c 2004-05-10 01:19:02.939292216 -0700 @@ -272,8 +272,8 @@ static int tda9875_attach(struct i2c_ada static int tda9875_probe(struct i2c_adapter *adap) { -#ifdef I2C_ADAP_CLASS_TV_ANALOG - if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) +#ifdef I2C_CLASS_TV_ANALOG + if (adap->class & I2C_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, tda9875_attach); #else if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) --- linux-2.6.6/drivers/media/video/tda9887.c 2004-02-17 20:48:43.000000000 -0800 +++ 25/drivers/media/video/tda9887.c 2004-05-10 01:19:02.940292064 -0700 @@ -370,8 +370,8 @@ static int tda9887_attach(struct i2c_ada static int tda9887_probe(struct i2c_adapter *adap) { -#ifdef I2C_ADAP_CLASS_TV_ANALOG - if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) +#ifdef I2C_CLASS_TV_ANALOG + if (adap->class & I2C_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, tda9887_attach); #else switch (adap->id) { --- linux-2.6.6/drivers/media/video/tuner.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/media/video/tuner.c 2004-05-10 01:19:02.941291912 -0700 @@ -1067,8 +1067,8 @@ static int tuner_probe(struct i2c_adapte } this_adap = 0; -#ifdef I2C_ADAP_CLASS_TV_ANALOG - if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) +#ifdef I2C_CLASS_TV_ANALOG + if (adap->class & I2C_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, tuner_attach); #else switch (adap->id) { --- linux-2.6.6/drivers/media/video/tvaudio.c 2004-02-17 20:48:43.000000000 -0800 +++ 25/drivers/media/video/tvaudio.c 2004-05-10 01:19:02.942291760 -0700 @@ -1497,8 +1497,8 @@ static int chip_attach(struct i2c_adapte static int chip_probe(struct i2c_adapter *adap) { -#ifdef I2C_ADAP_CLASS_TV_ANALOG - if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) +#ifdef I2C_CLASS_TV_ANALOG + if (adap->class & I2C_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, chip_attach); #else switch (adap->id) { --- linux-2.6.6/drivers/media/video/tvmixer.c 2004-02-17 20:48:43.000000000 -0800 +++ 25/drivers/media/video/tvmixer.c 2004-05-10 01:19:02.942291760 -0700 @@ -263,8 +263,8 @@ static int tvmixer_clients(struct i2c_cl struct video_audio va; int i,minor; -#ifdef I2C_ADAP_CLASS_TV_ANALOG - if (!(client->adapter->class & I2C_ADAP_CLASS_TV_ANALOG)) +#ifdef I2C_CLASS_TV_ANALOG + if (!(client->adapter->class & I2C_CLASS_TV_ANALOG)) return -1; #else /* TV card ??? */ --- linux-2.6.6/drivers/media/video/video-buf.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/media/video/video-buf.c 2004-05-10 01:19:14.240574160 -0700 @@ -1176,7 +1176,7 @@ int videobuf_mmap_mapper(struct vm_area_ map->end = vma->vm_end; map->q = q; vma->vm_ops = &videobuf_vm_ops; - vma->vm_flags |= VM_DONTEXPAND; + vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED; vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */ vma->vm_private_data = map; dprintk(1,"mmap %p: %08lx-%08lx pgoff %08lx bufs %d-%d\n", --- linux-2.6.6/drivers/media/video/videodev.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/media/video/videodev.c 2004-05-10 01:19:43.382143968 -0700 @@ -397,12 +397,21 @@ static struct file_operations video_fops static int __init videodev_init(void) { + int ret; + printk(KERN_INFO "Linux video capture interface: v1.00\n"); - if (register_chrdev(VIDEO_MAJOR,VIDEO_NAME, &video_fops)) { - printk("video_dev: unable to get major %d\n", VIDEO_MAJOR); + if (register_chrdev(VIDEO_MAJOR, VIDEO_NAME, &video_fops)) { + printk(KERN_WARNING "video_dev: unable to get major %d\n", VIDEO_MAJOR); return -EIO; } - class_register(&video_class); + + ret = class_register(&video_class); + if (ret < 0) { + unregister_chrdev(VIDEO_MAJOR, VIDEO_NAME); + printk(KERN_WARNING "video_dev: class_register failed\n"); + return -EIO; + } + return 0; } --- linux-2.6.6/drivers/message/fusion/Kconfig 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/message/fusion/Kconfig 2004-05-10 01:19:40.865526552 -0700 @@ -3,7 +3,7 @@ menu "Fusion MPT device support" config FUSION tristate "Fusion MPT (base + ScsiHost) drivers" - depends on PCI + depends on PCI && SCSI ---help--- LSI Logic Fusion(TM) Message Passing Technology (MPT) device support provides high performance SCSI host initiator, and LAN [1] interface --- linux-2.6.6/drivers/message/fusion/mptbase.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/message/fusion/mptbase.c 2004-05-10 01:19:04.512053120 -0700 @@ -223,6 +223,7 @@ static void mpt_get_fw_exp_ver(char *buf //int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag); static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers); +static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf); static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info); static void mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info); @@ -263,6 +264,8 @@ struct _mpt_ioc_proc_list { */ static struct pci_device_id mptbase_pci_table[] = { + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC909, + PCI_ANY_ID, PCI_ANY_ID }, { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929, PCI_ANY_ID, PCI_ANY_ID }, { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919, @@ -389,6 +392,12 @@ mpt_interrupt(int irq, void *bus_id, str else mpt_sp_log_info(ioc, log_info); } + if (ioc_stat & MPI_IOCSTATUS_MASK) { + if ((int)ioc->chip_type <= (int)FC929) + ; + else + mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf); + } } else { /* * Process turbo (context) reply... @@ -1350,6 +1359,10 @@ mptbase_probe(struct pci_dev *pdev, cons } ioc->chip_type = FCUNK; + if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) { + ioc->chip_type = FC909; + ioc->prod_name = "LSIFC909"; + } if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) { ioc->chip_type = FC929; ioc->prod_name = "LSIFC929"; @@ -6086,12 +6099,156 @@ mpt_sp_log_info(MPT_ADAPTER *ioc, u32 lo case 0x00080000: desc = "Outbound DMA Overrun"; break; + + case 0x00090000: + desc = "Task Management"; + break; + + case 0x000A0000: + desc = "Device Problem"; + break; + + case 0x000B0000: + desc = "Invalid Phase Change"; + break; + + case 0x000C0000: + desc = "Untagged Table Size"; + break; + } printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc); } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* + * mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC. + * @ioc: Pointer to MPT_ADAPTER structure + * @ioc_status: U32 IOCStatus word from IOC + * @mf: Pointer to MPT request frame + * + * Refer to lsi/mpi.h. + */ +static void +mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) +{ + u32 status = ioc_status & MPI_IOCSTATUS_MASK; + char *desc = ""; + + switch (status) { + case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */ + desc = "Invalid Function"; + break; + + case MPI_IOCSTATUS_BUSY: /* 0x0002 */ + desc = "Busy"; + break; + + case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */ + desc = "Invalid SGL"; + break; + + case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */ + desc = "Internal Error"; + break; + + case MPI_IOCSTATUS_RESERVED: /* 0x0005 */ + desc = "Reserved"; + break; + + case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */ + desc = "Insufficient Resources"; + break; + + case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */ + desc = "Invalid Field"; + break; + + case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */ + desc = "Invalid State"; + break; + + case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */ + case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */ + case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */ + case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */ + case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */ + case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */ + /* No message for Config IOCStatus values */ + break; + + case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ + /* No message for recovered error + desc = "SCSI Recovered Error"; + */ + break; + + case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */ + desc = "SCSI Invalid Bus"; + break; + + case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */ + desc = "SCSI Invalid TargetID"; + break; + + case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */ + { + SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf; + U8 cdb = pScsiReq->CDB[0]; + if (cdb != 0x12) { /* Inquiry is issued for device scanning */ + desc = "SCSI Device Not There"; + } + break; + } + + case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */ + desc = "SCSI Data Overrun"; + break; + + case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ + /* This error is checked in scsi_io_done(). Skip. + desc = "SCSI Data Underrun"; + */ + break; + + case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */ + desc = "SCSI I/O Data Error"; + break; + + case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */ + desc = "SCSI Protocol Error"; + break; + + case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ + desc = "SCSI Task Terminated"; + break; + + case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ + desc = "SCSI Residual Mismatch"; + break; + + case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */ + desc = "SCSI Task Management Failed"; + break; + + case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ + desc = "SCSI IOC Terminated"; + break; + + case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ + desc = "SCSI Ext Terminated"; + break; + + default: + desc = "Others"; + break; + } + if (desc != "") + printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc); +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_register_ascqops_strings - Register SCSI ASC/ASCQ and SCSI * OpCode strings from the (optional) isense module. --- linux-2.6.6/drivers/message/fusion/mptbase.h 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/message/fusion/mptbase.h 2004-05-10 01:19:04.513052968 -0700 @@ -81,8 +81,8 @@ #define COPYRIGHT "Copyright (c) 1999-2004 " MODULEAUTHOR #endif -#define MPT_LINUX_VERSION_COMMON "3.01.03" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.01.03" +#define MPT_LINUX_VERSION_COMMON "3.01.05" +#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.01.05" #define WHAT_MAGIC_STRING "@" "(" "#" ")" #define show_mptmod_ver(s,ver) \ --- linux-2.6.6/drivers/message/fusion/mptctl.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/message/fusion/mptctl.c 2004-05-10 01:19:04.516052512 -0700 @@ -1199,7 +1199,7 @@ static int mptctl_getiocinfo (unsigned long arg, unsigned int data_size) { struct mpt_ioctl_iocinfo *uarg = (struct mpt_ioctl_iocinfo *) arg; - struct mpt_ioctl_iocinfo karg; + struct mpt_ioctl_iocinfo *karg; MPT_ADAPTER *ioc; struct pci_dev *pdev; struct Scsi_Host *sh; @@ -1219,34 +1219,46 @@ mptctl_getiocinfo (unsigned long arg, un */ if (data_size == sizeof(struct mpt_ioctl_iocinfo_rev0)) cim_rev = 0; - else if (data_size == sizeof(struct mpt_ioctl_iocinfo)) + else if (data_size == sizeof(struct mpt_ioctl_iocinfo_rev1)) cim_rev = 1; + else if (data_size == sizeof(struct mpt_ioctl_iocinfo)) + cim_rev = 2; else if (data_size == (sizeof(struct mpt_ioctl_iocinfo_rev0)+12)) cim_rev = 0; /* obsolete */ else return -EFAULT; - - if (copy_from_user(&karg, uarg, data_size)) { + + karg = kmalloc(data_size, GFP_KERNEL); + if (karg == NULL) { + printk(KERN_ERR "%s::mpt_ioctl_iocinfo() @%d - no memory available!\n", + __FILE__, __LINE__); + return -ENOMEM; + } + + if (copy_from_user(karg, uarg, data_size)) { printk(KERN_ERR "%s@%d::mptctl_getiocinfo - " "Unable to read in mpt_ioctl_iocinfo struct @ %p\n", __FILE__, __LINE__, (void*)uarg); + kfree(karg); return -EFAULT; } - if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || + if (((iocnum = mpt_verify_adapter(karg->hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { dctlprintk((KERN_ERR "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); + kfree(karg); return -ENODEV; } /* Verify the data transfer size is correct. * Ignore the port setting. */ - if (karg.hdr.maxDataSize != data_size) { + if (karg->hdr.maxDataSize != data_size) { printk(KERN_ERR "%s@%d::mptctl_getiocinfo - " "Structure size mismatch. Command not completed.\n", __FILE__, __LINE__); + kfree(karg); return -EFAULT; } @@ -1254,29 +1266,37 @@ mptctl_getiocinfo (unsigned long arg, un * program */ if ((int)ioc->chip_type <= (int) FC929) - karg.adapterType = MPT_IOCTL_INTERFACE_FC; + karg->adapterType = MPT_IOCTL_INTERFACE_FC; else - karg.adapterType = MPT_IOCTL_INTERFACE_SCSI; + karg->adapterType = MPT_IOCTL_INTERFACE_SCSI; - port = karg.hdr.port; + port = karg->hdr.port; - karg.port = port; + karg->port = port; pdev = (struct pci_dev *) ioc->pcidev; - karg.pciId = pdev->device; + karg->pciId = pdev->device; pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); - karg.hwRev = revision; + karg->hwRev = revision; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - karg.subSystemDevice = pdev->subsystem_device; - karg.subSystemVendor = pdev->subsystem_vendor; + karg->subSystemDevice = pdev->subsystem_device; + karg->subSystemVendor = pdev->subsystem_vendor; #endif if (cim_rev == 1) { /* Get the PCI bus, device, and function numbers for the IOC */ - karg.pciInfo.u.bits.busNumber = pdev->bus->number; - karg.pciInfo.u.bits.deviceNumber = PCI_SLOT( pdev->devfn ); - karg.pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn ); + karg->pciInfo.u.bits.busNumber = pdev->bus->number; + karg->pciInfo.u.bits.deviceNumber = PCI_SLOT( pdev->devfn ); + karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn ); + } else if (cim_rev == 2) { + /* Get the PCI bus, device, function and segment ID numbers + for the IOC */ + karg->pciInfo.u.bits.busNumber = pdev->bus->number; + karg->pciInfo.u.bits.deviceNumber = PCI_SLOT( pdev->devfn ); + karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn ); + karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn ); + karg->pciInfo.segmentID = pci_domain_nr(pdev->bus); } /* Get number of devices @@ -1297,31 +1317,33 @@ mptctl_getiocinfo (unsigned long arg, un } } } - karg.numDevices = numDevices; + karg->numDevices = numDevices; /* Set the BIOS and FW Version */ - karg.FWVersion = ioc->facts.FWVersion.Word; - karg.BIOSVersion = ioc->biosVersion; + karg->FWVersion = ioc->facts.FWVersion.Word; + karg->BIOSVersion = ioc->biosVersion; /* Set the Version Strings. */ - strncpy (karg.driverVersion, MPT_LINUX_PACKAGE_NAME, MPT_IOCTL_VERSION_LENGTH); - karg.driverVersion[MPT_IOCTL_VERSION_LENGTH-1]='\0'; + strncpy (karg->driverVersion, MPT_LINUX_PACKAGE_NAME, MPT_IOCTL_VERSION_LENGTH); + karg->driverVersion[MPT_IOCTL_VERSION_LENGTH-1]='\0'; - karg.busChangeEvent = 0; - karg.hostId = ioc->pfacts[port].PortSCSIID; - karg.rsvd[0] = karg.rsvd[1] = 0; + karg->busChangeEvent = 0; + karg->hostId = ioc->pfacts[port].PortSCSIID; + karg->rsvd[0] = karg->rsvd[1] = 0; /* Copy the data from kernel memory to user memory */ - if (copy_to_user((char *)arg, &karg, data_size)) { + if (copy_to_user((char *)arg, karg, data_size)) { printk(KERN_ERR "%s@%d::mptctl_getiocinfo - " "Unable to write out mpt_ioctl_iocinfo struct @ %p\n", __FILE__, __LINE__, (void*)uarg); + kfree(karg); return -EFAULT; } + kfree(karg); return 0; } @@ -2909,6 +2931,8 @@ int __init mptctl_init(void) if (++where && err) goto out_fail; err = register_ioctl32_conversion(MPTIOCINFO1, compat_mptctl_ioctl); if (++where && err) goto out_fail; + err = register_ioctl32_conversion(MPTIOCINFO2, compat_mptctl_ioctl); + if (++where && err) goto out_fail; err = register_ioctl32_conversion(MPTTARGETINFO, compat_mptctl_ioctl); if (++where && err) goto out_fail; err = register_ioctl32_conversion(MPTTEST, compat_mptctl_ioctl); @@ -2968,6 +2992,7 @@ out_fail: " (%d:err=%d)\n", where, err); unregister_ioctl32_conversion(MPTIOCINFO); unregister_ioctl32_conversion(MPTIOCINFO1); + unregister_ioctl32_conversion(MPTIOCINFO2); unregister_ioctl32_conversion(MPTTARGETINFO); unregister_ioctl32_conversion(MPTTEST); unregister_ioctl32_conversion(MPTEVENTQUERY); @@ -3018,6 +3043,7 @@ void mptctl_exit(void) #ifdef CONFIG_COMPAT unregister_ioctl32_conversion(MPTIOCINFO); unregister_ioctl32_conversion(MPTIOCINFO1); + unregister_ioctl32_conversion(MPTIOCINFO2); unregister_ioctl32_conversion(MPTTARGETINFO); unregister_ioctl32_conversion(MPTTEST); unregister_ioctl32_conversion(MPTEVENTQUERY); --- linux-2.6.6/drivers/message/fusion/mptctl.h 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/message/fusion/mptctl.h 2004-05-10 01:19:04.517052360 -0700 @@ -91,6 +91,7 @@ #define MPTIOCINFO _IOWR(MPT_MAGIC_NUMBER,17,struct mpt_ioctl_iocinfo) #define MPTIOCINFO1 _IOWR(MPT_MAGIC_NUMBER,17,struct mpt_ioctl_iocinfo_rev0) +#define MPTIOCINFO2 _IOWR(MPT_MAGIC_NUMBER,17,struct mpt_ioctl_iocinfo_rev1) #define MPTTARGETINFO _IOWR(MPT_MAGIC_NUMBER,18,struct mpt_ioctl_targetinfo) #define MPTTEST _IOWR(MPT_MAGIC_NUMBER,19,struct mpt_ioctl_test) #define MPTEVENTQUERY _IOWR(MPT_MAGIC_NUMBER,21,struct mpt_ioctl_eventquery) @@ -165,6 +166,18 @@ struct mpt_ioctl_pci_info { } u; }; +struct mpt_ioctl_pci_info2 { + union { + struct { + unsigned int deviceNumber : 5; + unsigned int functionNumber : 3; + unsigned int busNumber : 24; + } bits; + unsigned int asUlong; + } u; + int segmentID; +}; + /* * Adapter Information Page * Read only. @@ -189,6 +202,24 @@ struct mpt_ioctl_iocinfo { char busChangeEvent; char hostId; char rsvd[2]; + struct mpt_ioctl_pci_info2 pciInfo; /* Added Rev 2 */ +}; + +struct mpt_ioctl_iocinfo_rev1 { + mpt_ioctl_header hdr; + int adapterType; /* SCSI or FCP */ + int port; /* port number */ + int pciId; /* PCI Id. */ + int hwRev; /* hardware revision */ + int subSystemDevice; /* PCI subsystem Device ID */ + int subSystemVendor; /* PCI subsystem Vendor ID */ + int numDevices; /* number of devices */ + int FWVersion; /* FW Version (integer) */ + int BIOSVersion; /* BIOS Version (integer) */ + char driverVersion[MPT_IOCTL_VERSION_LENGTH]; /* Driver Version (string) */ + char busChangeEvent; + char hostId; + char rsvd[2]; struct mpt_ioctl_pci_info pciInfo; /* Added Rev 1 */ }; --- linux-2.6.6/drivers/message/fusion/mptscsih.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/message/fusion/mptscsih.c 2004-05-10 01:19:04.522051600 -0700 @@ -805,6 +805,14 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) copy_sense_data(sc, hd, mf, pScsiReply); + + /* + * Look for + dump FCP ResponseInfo[]! + */ + if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID) { + printk(KERN_NOTICE " FCP_ResponseInfo=%08xh\n", + le32_to_cpu(pScsiReply->ResponseInfo)); + } switch(status) { case MPI_IOCSTATUS_BUSY: /* 0x0002 */ @@ -1106,16 +1114,21 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOS * Do OS callback * Free driver resources (chain, msg buffers) */ - if (SCpnt->use_sg) { - pci_unmap_sg(hd->ioc->pcidev, (struct scatterlist *) SCpnt->request_buffer, - SCpnt->use_sg, scsi_to_pci_dma_dir(SCpnt->sc_data_direction)); - } else if (SCpnt->request_bufflen) { - scPrivate *my_priv; - - my_priv = (scPrivate *) &SCpnt->SCp; - pci_unmap_single(hd->ioc->pcidev, (dma_addr_t)(ulong)my_priv->p1, - SCpnt->request_bufflen, - scsi_to_pci_dma_dir(SCpnt->sc_data_direction)); + if (scsi_device_online(SCpnt->device)) { + if (SCpnt->use_sg) { + pci_unmap_sg(hd->ioc->pcidev, + (struct scatterlist *) SCpnt->request_buffer, + SCpnt->use_sg, + scsi_to_pci_dma_dir(SCpnt->sc_data_direction)); + } else if (SCpnt->request_bufflen) { + scPrivate *my_priv; + + my_priv = (scPrivate *) &SCpnt->SCp; + pci_unmap_single(hd->ioc->pcidev, + (dma_addr_t)(ulong)my_priv->p1, + SCpnt->request_bufflen, + scsi_to_pci_dma_dir(SCpnt->sc_data_direction)); + } } SCpnt->result = DID_RESET << 16; SCpnt->host_scribble = NULL; --- linux-2.6.6/drivers/message/i2o/i2o_block.c 2004-03-10 20:41:28.000000000 -0800 +++ 25/drivers/message/i2o/i2o_block.c 2004-05-10 01:19:47.588504504 -0700 @@ -83,7 +83,6 @@ #include #include #include -#include #include #include @@ -111,16 +110,12 @@ I2O_EVT_IND_BSA_SCSI_SMART ) -#define I2O_LOCK(unit) (i2ob_dev[(unit)].req_queue->queue_lock) - /* * Some of these can be made smaller later */ -static int i2ob_media_change_flag[MAX_I2OB]; -static u32 i2ob_max_sectors[MAX_I2OB<<4]; - static int i2ob_context; +static struct block_device_operations i2ob_fops; /* * I2O Block device descriptor @@ -143,6 +138,9 @@ struct i2ob_device int wcache; int power; int index; + int media_change_flag; + u32 max_sectors; + struct gendisk *gd; }; /* @@ -162,16 +160,16 @@ struct i2ob_request }; /* - * Per IOP requst queue information + * Per IOP request queue information * - * We have a separate requeust_queue_t per IOP so that a heavilly + * We have a separate request_queue_t per IOP so that a heavilly * loaded I2O block device on an IOP does not starve block devices * across all I2O controllers. * */ struct i2ob_iop_queue { - atomic_t queue_depth; + unsigned int queue_depth; struct i2ob_request request_queue[MAX_I2OB_DEPTH]; struct i2ob_request *i2ob_qhead; request_queue_t *req_queue; @@ -183,9 +181,8 @@ static struct i2ob_iop_queue *i2ob_queue * Each I2O disk is one of these. */ -static struct i2ob_device i2ob_dev[MAX_I2OB<<4]; +static struct i2ob_device i2ob_dev[MAX_I2OB]; static int i2ob_dev_count = 0; -static struct gendisk *i2ob_disk[MAX_I2OB]; /* * Mutex and spin lock for event handling synchronization @@ -312,7 +309,6 @@ static int i2ob_send(u32 m, struct i2ob_ /* * Mask out partitions from now on */ - unit &= 0xF0; /* This can be optimised later - just want to be sure its right for starters */ @@ -402,7 +398,7 @@ static int i2ob_send(u32 m, struct i2ob_ } i2o_post_message(c,m); - atomic_inc(&i2ob_queues[c->unit]->queue_depth); + i2ob_queues[c->unit]->queue_depth ++; return 0; } @@ -453,8 +449,8 @@ static void i2o_block_reply(struct i2o_h struct i2ob_request *ireq = NULL; u8 st; u32 *m = (u32 *)msg; - u8 unit = (m[2]>>8)&0xF0; /* low 4 bits are partition */ - struct i2ob_device *dev = &i2ob_dev[(unit&0xF0)]; + u8 unit = m[2]>>8; + struct i2ob_device *dev = &i2ob_dev[unit]; /* * FAILed message @@ -475,10 +471,10 @@ static void i2o_block_reply(struct i2o_h ireq=&i2ob_queues[c->unit]->request_queue[m[3]]; ireq->req->errors++; - spin_lock_irqsave(I2O_LOCK(c->unit), flags); + spin_lock_irqsave(dev->req_queue->queue_lock, flags); i2ob_unhook_request(ireq, c->unit); i2ob_end_request(ireq->req); - spin_unlock_irqrestore(I2O_LOCK(c->unit), flags); + spin_unlock_irqrestore(dev->req_queue->queue_lock, flags); /* Now flush the message by making it a NOP */ m[0]&=0x00FFFFFF; @@ -509,10 +505,10 @@ static void i2o_block_reply(struct i2o_h ireq=&i2ob_queues[c->unit]->request_queue[m[3]]; ireq->req->errors++; printk(KERN_WARNING "I2O Block: Data transfer to deleted device!\n"); - spin_lock_irqsave(I2O_LOCK(c->unit), flags); + spin_lock_irqsave(dev->req_queue->queue_lock, flags); i2ob_unhook_request(ireq, c->unit); i2ob_end_request(ireq->req); - spin_unlock_irqrestore(I2O_LOCK(c->unit), flags); + spin_unlock_irqrestore(dev->req_queue->queue_lock, flags); return; } @@ -576,17 +572,17 @@ static void i2o_block_reply(struct i2o_h */ i2ob_free_sglist(dev, ireq); - spin_lock_irqsave(I2O_LOCK(c->unit), flags); + spin_lock_irqsave(dev->req_queue->queue_lock, flags); i2ob_unhook_request(ireq, c->unit); i2ob_end_request(ireq->req); - atomic_dec(&i2ob_queues[c->unit]->queue_depth); + i2ob_queues[c->unit]->queue_depth --; /* * We may be able to do more I/O */ - i2ob_request(dev->req_queue); - spin_unlock_irqrestore(I2O_LOCK(c->unit), flags); + i2ob_request(dev->gd->queue); + spin_unlock_irqrestore(dev->req_queue->queue_lock, flags); } /* @@ -598,8 +594,8 @@ static int i2ob_evt(void *dummy) { unsigned int evt; unsigned long flags; + struct i2ob_device *dev; int unit; - int i; //The only event that has data is the SCSI_SMART event. struct i2o_reply { u32 header[4]; @@ -638,6 +634,7 @@ static int i2ob_evt(void *dummy) unit = le32_to_cpu(evt_local->header[3]); evt = le32_to_cpu(evt_local->evt_indicator); + dev = &i2ob_dev[unit]; switch(evt) { /* @@ -648,10 +645,9 @@ static int i2ob_evt(void *dummy) */ case I2O_EVT_IND_BSA_VOLUME_LOAD: { - struct gendisk *p = i2ob_disk[unit>>4]; - i2ob_install_device(i2ob_dev[unit].i2odev->controller, - i2ob_dev[unit].i2odev, unit); - add_disk(p); + i2ob_install_device(dev->i2odev->controller, + dev->i2odev, unit); + add_disk(dev->gd); break; } @@ -663,17 +659,18 @@ static int i2ob_evt(void *dummy) */ case I2O_EVT_IND_BSA_VOLUME_UNLOAD: { - struct gendisk *p = i2ob_disk[unit>>4]; + struct gendisk *p = dev->gd; + blk_queue_max_sectors(dev->gd->queue, 0); del_gendisk(p); - for(i = unit; i <= unit+15; i++) - blk_queue_max_sectors(i2ob_dev[i].req_queue, 0); - i2ob_media_change_flag[unit] = 1; + put_disk(p); + dev->gd = NULL; + dev->media_change_flag = 1; break; } case I2O_EVT_IND_BSA_VOLUME_UNLOAD_REQ: printk(KERN_WARNING "%s: Attempt to eject locked media\n", - i2ob_dev[unit].i2odev->dev_name); + dev->i2odev->dev_name); break; /* @@ -691,12 +688,12 @@ static int i2ob_evt(void *dummy) { u64 size; - if(i2ob_query_device(&i2ob_dev[unit], 0x0004, 0, &size, 8) !=0 ) - i2ob_query_device(&i2ob_dev[unit], 0x0000, 4, &size, 8); + if(i2ob_query_device(dev, 0x0004, 0, &size, 8) !=0 ) + i2ob_query_device(dev, 0x0000, 4, &size, 8); - spin_lock_irqsave(I2O_LOCK(unit), flags); - set_capacity(i2ob_disk[unit>>4], size>>9); - spin_unlock_irqrestore(I2O_LOCK(unit), flags); + spin_lock_irqsave(dev->req_queue->queue_lock, flags); + set_capacity(dev->gd, size>>9); + spin_unlock_irqrestore(dev->req_queue->queue_lock, flags); break; } @@ -708,7 +705,7 @@ static int i2ob_evt(void *dummy) case I2O_EVT_IND_BSA_SCSI_SMART: { char buf[16]; - printk(KERN_INFO "I2O Block: %s received a SCSI SMART Event\n",i2ob_dev[unit].i2odev->dev_name); + printk(KERN_INFO "I2O Block: %s received a SCSI SMART Event\n",dev->i2odev->dev_name); evt_local->data[16]='\0'; sprintf(buf,"%s",&evt_local->data[0]); printk(KERN_INFO " Disk Serial#:%s\n",buf); @@ -735,12 +732,12 @@ static int i2ob_evt(void *dummy) * hit the fan big time. The card seems to recover but loses * the pending writes. Deeply ungood except for testing fsck */ - if(i2ob_dev[unit].i2odev->controller->promise) + if(dev->i2odev->controller->promise) panic("I2O controller firmware failed. Reboot and force a filesystem check.\n"); default: printk(KERN_INFO "%s: Received event 0x%X we didn't register for\n" KERN_INFO " Blame the I2O card manufacturer 8)\n", - i2ob_dev[unit].i2odev->dev_name, evt); + dev->i2odev->dev_name, evt); break; } }; @@ -765,14 +762,6 @@ static void i2ob_request(request_queue_t u32 m; while ((req = elv_next_request(q)) != NULL) { - /* - * On an IRQ completion if there is an inactive - * request on the queue head it means it isnt yet - * ready to dispatch. - */ - if(req->rq_status == RQ_INACTIVE) - return; - dev = req->rq_disk->private_data; /* @@ -780,7 +769,7 @@ static void i2ob_request(request_queue_t * generic IOP commit control. Certainly it's not right * its global! */ - if(atomic_read(&i2ob_queues[dev->unit]->queue_depth) >= dev->depth) + if(i2ob_queues[dev->unit]->queue_depth >= dev->depth) break; /* Get a message */ @@ -788,7 +777,7 @@ static void i2ob_request(request_queue_t if(m==0xFFFFFFFF) { - if(atomic_read(&i2ob_queues[dev->unit]->queue_depth) == 0) + if(i2ob_queues[dev->unit]->queue_depth == 0) printk(KERN_ERR "i2o_block: message queue and request queue empty!!\n"); break; } @@ -797,13 +786,12 @@ static void i2ob_request(request_queue_t */ req->errors = 0; blkdev_dequeue_request(req); - req->waiting = NULL; ireq = i2ob_queues[dev->unit]->i2ob_qhead; i2ob_queues[dev->unit]->i2ob_qhead = ireq->next; ireq->req = req; - i2ob_send(m, dev, ireq, (dev->unit&0xF0)); + i2ob_send(m, dev, ireq, dev->index); } } @@ -1065,7 +1053,10 @@ static int i2ob_install_device(struct i2 u16 power; u32 flags, status; struct i2ob_device *dev=&i2ob_dev[unit]; - int i; + struct gendisk *disk; + request_queue_t *q; + int segments; + /* * For logging purposes... @@ -1079,21 +1070,35 @@ static int i2ob_install_device(struct i2 * before any I/O can be performed. If it fails, this * device is useless. */ - if(!i2ob_queues[unit]) { - if(i2ob_init_iop(unit)) + if(!i2ob_queues[c->unit]) { + if(i2ob_init_iop(c->unit)) return 1; } + q = i2ob_queues[c->unit]->req_queue; + /* * This will save one level of lookup/indirection in critical * code so that we can directly get the queue ptr from the * device instead of having to go the IOP data structure. */ - dev->req_queue = i2ob_queues[unit]->req_queue; + dev->req_queue = q; + /* + * Allocate a gendisk structure and initialize it + */ + disk = alloc_disk(16); + if (!disk) + return 1; + + dev->gd = disk; /* initialize gendik structure */ - i2ob_disk[unit>>4]->private_data = dev; - i2ob_disk[unit>>4]->queue = dev->req_queue; + disk->major = MAJOR_NR; + disk->first_minor = unit<<4; + disk->queue = q; + disk->fops = &i2ob_fops; + sprintf(disk->disk_name, "i2o/hd%c", 'a' + unit); + disk->private_data = dev; /* * Ask for the current media data. If that isn't supported @@ -1110,53 +1115,49 @@ static int i2ob_install_device(struct i2 power = 0; i2ob_query_device(dev, 0x0000, 5, &flags, 4); i2ob_query_device(dev, 0x0000, 6, &status, 4); - set_capacity(i2ob_disk[unit>>4], size>>9); + set_capacity(disk, size>>9); /* * Max number of Scatter-Gather Elements */ - i2ob_dev[unit].power = power; /* Save power state in device proper */ - i2ob_dev[unit].flags = flags; + dev->power = power; /* Save power state in device proper */ + dev->flags = flags; - for(i=unit;i<=unit+15;i++) - { - request_queue_t *q = i2ob_dev[unit].req_queue; - int segments = (d->controller->status_block->inbound_frame_size - 7) / 2; + segments = (d->controller->status_block->inbound_frame_size - 7) / 2; + + if(segments > 16) + segments = 16; - if(segments > 16) - segments = 16; - - i2ob_dev[i].power = power; /* Save power state */ - i2ob_dev[unit].flags = flags; /* Keep the type info */ + dev->power = power; /* Save power state */ + dev->flags = flags; /* Keep the type info */ - blk_queue_max_sectors(q, 96); /* 256 might be nicer but many controllers + blk_queue_max_sectors(q, 96); /* 256 might be nicer but many controllers explode on 65536 or higher */ - blk_queue_max_phys_segments(q, segments); - blk_queue_max_hw_segments(q, segments); + blk_queue_max_phys_segments(q, segments); + blk_queue_max_hw_segments(q, segments); - i2ob_dev[i].rcache = CACHE_SMARTFETCH; - i2ob_dev[i].wcache = CACHE_WRITETHROUGH; + dev->rcache = CACHE_SMARTFETCH; + dev->wcache = CACHE_WRITETHROUGH; - if(d->controller->battery == 0) - i2ob_dev[i].wcache = CACHE_WRITETHROUGH; + if(d->controller->battery == 0) + dev->wcache = CACHE_WRITETHROUGH; - if(d->controller->promise) - i2ob_dev[i].wcache = CACHE_WRITETHROUGH; + if(d->controller->promise) + dev->wcache = CACHE_WRITETHROUGH; - if(d->controller->short_req) - { - blk_queue_max_sectors(q, 8); - blk_queue_max_phys_segments(q, 8); - blk_queue_max_hw_segments(q, 8); - } + if(d->controller->short_req) + { + blk_queue_max_sectors(q, 8); + blk_queue_max_phys_segments(q, 8); + blk_queue_max_hw_segments(q, 8); } - strcpy(d->dev_name, i2ob_disk[unit>>4]->disk_name); - strcpy(i2ob_disk[unit>>4]->devfs_name, i2ob_disk[unit>>4]->disk_name); + strcpy(d->dev_name, disk->disk_name); + strcpy(disk->devfs_name, disk->disk_name); printk(KERN_INFO "%s: Max segments %d, queue depth %d, byte limit %d.\n", - d->dev_name, i2ob_dev[unit].max_segments, i2ob_dev[unit].depth, i2ob_max_sectors[unit]<<9); + d->dev_name, dev->max_segments, dev->depth, dev->max_sectors<<9); i2ob_query_device(dev, 0x0000, 0, &type, 1); @@ -1197,7 +1198,7 @@ static int i2ob_install_device(struct i2 } printk(".\n"); printk(KERN_INFO "%s: Maximum sectors/read set to %d.\n", - d->dev_name, i2ob_max_sectors[unit]); + d->dev_name, dev->max_sectors); /* * Register for the events we're interested in and that the @@ -1233,7 +1234,7 @@ static int i2ob_init_iop(unsigned int un /* Queue is MAX_I2OB + 1... */ i2ob_queues[unit]->request_queue[i].next = NULL; i2ob_queues[unit]->i2ob_qhead = &i2ob_queues[unit]->request_queue[0]; - atomic_set(&i2ob_queues[unit]->queue_depth, 0); + i2ob_queues[unit]->queue_depth = 0; i2ob_queues[unit]->lock = SPIN_LOCK_UNLOCKED; i2ob_queues[unit]->req_queue = blk_init_queue(i2ob_request, &i2ob_queues[unit]->lock); @@ -1257,7 +1258,6 @@ static void i2ob_scan(int bios) struct i2o_device *d, *b=NULL; struct i2o_controller *c; - struct i2ob_device *dev; for(i=0; i< MAX_I2O_CONTROLLERS; i++) { @@ -1313,44 +1313,12 @@ static void i2ob_scan(int bios) continue; /*Already claimed on pass 1 */ } - if(i2o_claim_device(d, &i2o_block_handler)) - { - printk(KERN_WARNING "i2o_block: Controller %d, TID %d\n", c->unit, - d->lct_data.tid); - printk(KERN_WARNING "\t%sevice refused claim! Skipping installation\n", bios?"Boot d":"D"); - continue; - } - - i2o_release_device(d, &i2o_block_handler); - - if(scan_uniti2odev = d; - dev->controller = c; - dev->unit = c->unit; - dev->tid = d->lct_data.tid; - - if(i2ob_install_device(c,d,scan_unit)) - printk(KERN_WARNING "Could not install I2O block device\n"); - else - { - add_disk(i2ob_disk[scan_unit>>4]); - scan_unit+=16; - i2ob_dev_count++; - - /* We want to know when device goes away */ - i2o_device_notify_on(d, &i2o_block_handler); - } - } + if(scan_unit>4); + printk(KERN_WARNING "i2o_block: too many device, registering only %d.\n", scan_unit); } } i2o_unlock_controller(c); @@ -1399,12 +1367,12 @@ void i2ob_new_device(struct i2o_controll printk(KERN_INFO " Controller %d Tid %d\n",c->unit, d->lct_data.tid); /* Check for available space */ - if(i2ob_dev_count>=MAX_I2OB<<4) + if(i2ob_dev_count>=MAX_I2OB) { printk(KERN_ERR "i2o_block: No more devices allowed!\n"); return; } - for(unit = 0; unit < (MAX_I2OB<<4); unit += 16) + for(unit = 0; unit < MAX_I2OB; unit ++) { if(!i2ob_dev[unit].i2odev) break; @@ -1420,18 +1388,20 @@ void i2ob_new_device(struct i2o_controll dev->i2odev = d; dev->controller = c; dev->tid = d->lct_data.tid; + dev->unit = c->unit; - if(i2ob_install_device(c,d,unit)) + if(i2ob_install_device(c,d,unit)) { + i2o_release_device(d, &i2o_block_handler); printk(KERN_ERR "i2o_block: Could not install new device\n"); + } else { - add_disk(i2ob_disk[unit>>4]); + i2o_release_device(d, &i2o_block_handler); + add_disk(dev->gd); i2ob_dev_count++; i2o_device_notify_on(d, &i2o_block_handler); } - i2o_release_device(d, &i2o_block_handler); - return; } @@ -1443,64 +1413,58 @@ void i2ob_new_device(struct i2o_controll void i2ob_del_device(struct i2o_controller *c, struct i2o_device *d) { int unit = 0; - int i = 0; unsigned long flags; + struct i2ob_device *dev; - spin_lock_irqsave(I2O_LOCK(c->unit), flags); - - /* - * Need to do this...we somtimes get two events from the IRTOS - * in a row and that causes lots of problems. - */ - i2o_device_notify_off(d, &i2o_block_handler); - - printk(KERN_INFO "I2O Block Device Deleted\n"); - - for(unit = 0; unit < MAX_I2OB<<4; unit += 16) + for(unit = 0; unit < MAX_I2OB; unit ++) { - if(i2ob_dev[unit].i2odev == d) + dev = &i2ob_dev[unit]; + if(dev->i2odev == d) { printk(KERN_INFO " /dev/%s: Controller %d Tid %d\n", d->dev_name, c->unit, d->lct_data.tid); break; } } - if(unit >= MAX_I2OB<<4) + + printk(KERN_INFO "I2O Block Device Deleted\n"); + + if(unit >= MAX_I2OB) { printk(KERN_ERR "i2ob_del_device called, but not in dev table!\n"); - spin_unlock_irqrestore(I2O_LOCK(c->unit), flags); return; } + spin_lock_irqsave(dev->req_queue->queue_lock, flags); + + /* + * Need to do this...we somtimes get two events from the IRTOS + * in a row and that causes lots of problems. + */ + i2o_device_notify_off(d, &i2o_block_handler); + /* * This will force errors when i2ob_get_queue() is called * by the kenrel. */ - del_gendisk(i2ob_disk[unit>>4]); - i2ob_dev[unit].req_queue = NULL; - for(i = unit; i <= unit+15; i++) - { - i2ob_dev[i].i2odev = NULL; - blk_queue_max_sectors(i2ob_dev[i].req_queue, 0); - } - spin_unlock_irqrestore(I2O_LOCK(c->unit), flags); - - /* - * Decrease usage count for module - */ - - while(i2ob_dev[unit].refcnt--) - MOD_DEC_USE_COUNT; - - i2ob_dev[unit].refcnt = 0; - - i2ob_dev[i].tid = 0; + if(dev->gd) { + struct gendisk *gd = dev->gd; + gd->queue = NULL; + del_gendisk(gd); + put_disk(gd); + dev->gd = NULL; + } + spin_unlock_irqrestore(dev->req_queue->queue_lock, flags); + dev->req_queue = NULL; + dev->i2odev = NULL; + dev->refcnt = 0; + dev->tid = 0; /* * Do we need this? * The media didn't really change...the device is just gone */ - i2ob_media_change_flag[unit] = 1; + dev->media_change_flag = 1; i2ob_dev_count--; } @@ -1511,10 +1475,9 @@ void i2ob_del_device(struct i2o_controll static int i2ob_media_change(struct gendisk *disk) { struct i2ob_device *p = disk->private_data; - int i = p->index; - if(i2ob_media_change_flag[i]) + if(p->media_change_flag) { - i2ob_media_change_flag[i]=0; + p->media_change_flag=0; return 1; } return 0; @@ -1523,7 +1486,7 @@ static int i2ob_media_change(struct gend static int i2ob_revalidate(struct gendisk *disk) { struct i2ob_device *p = disk->private_data; - return i2ob_install_device(p->controller, p->i2odev, p->index<<4); + return i2ob_install_device(p->controller, p->i2odev, p->index); } /* @@ -1536,7 +1499,7 @@ static void i2ob_reboot_event(void) for(i=0;irefcnt!=0) { @@ -1598,51 +1561,36 @@ static int i2o_block_init(void) if (register_blkdev(MAJOR_NR, "i2o_block")) return -EIO; - for (i = 0; i < MAX_I2OB; i++) { - struct gendisk *disk = alloc_disk(16); - if (!disk) - goto oom; - i2ob_dev[i<<4].index = i; - disk->queue = i2ob_dev[i<<4].req_queue; - i2ob_disk[i] = disk; - } #ifdef MODULE printk(KERN_INFO "i2o_block: registered device at major %d\n", MAJOR_NR); #endif /* + * Set up the queue + */ + for(i = 0; i < MAX_I2O_CONTROLLERS; i++) + i2ob_queues[i] = NULL; + + /* * Now fill in the boiler plate */ - for (i = 0; i < MAX_I2OB << 4; i++) { - i2ob_dev[i].refcnt = 0; - i2ob_dev[i].flags = 0; - i2ob_dev[i].controller = NULL; - i2ob_dev[i].i2odev = NULL; - i2ob_dev[i].tid = 0; - i2ob_dev[i].head = NULL; - i2ob_dev[i].tail = NULL; - i2ob_dev[i].depth = MAX_I2OB_DEPTH; - i2ob_max_sectors[i] = 2; - } - for (i = 0; i < MAX_I2OB; i++) { - struct gendisk *disk = i2ob_disk[i]; - disk->major = MAJOR_NR; - disk->first_minor = i<<4; - disk->fops = &i2ob_fops; - sprintf(disk->disk_name, "i2o/hd%c", 'a' + i); + struct i2ob_device *dev = &i2ob_dev[i]; + dev->index = i; + dev->refcnt = 0; + dev->flags = 0; + dev->controller = NULL; + dev->i2odev = NULL; + dev->tid = 0; + dev->head = NULL; + dev->tail = NULL; + dev->depth = MAX_I2OB_DEPTH; + dev->max_sectors = 2; + dev->gd = NULL; } /* - * Set up the queue - */ - for(i = 0; i < MAX_I2O_CONTROLLERS; i++) - { - i2ob_queues[i] = NULL; - } - - /* * Register the OSM handler as we will need this to probe for * drives, geometry and other goodies. */ @@ -1671,9 +1619,6 @@ static int i2o_block_init(void) return 0; -oom: - while (i--) - put_disk(i2ob_disk[i]); unregister_blkdev(MAJOR_NR, "i2o_block"); return -ENOMEM; } @@ -1701,11 +1646,8 @@ static void i2o_block_exit(void) if(i2ob_dev_count) { struct i2o_device *d; for(i = 0; i < MAX_I2OB; i++) - if((d=i2ob_dev[i<<4].i2odev)) { - i2o_device_notify_off(d, &i2o_block_handler); - i2o_event_register(d->controller, d->lct_data.tid, - i2ob_context, i<<4, 0); - } + if((d = i2ob_dev[i].i2odev)) + i2ob_del_device(d->controller, d); } /* @@ -1725,15 +1667,21 @@ static void i2o_block_exit(void) */ i2o_remove_handler(&i2o_block_handler); - - for (i = 0; i < MAX_I2OB; i++) - put_disk(i2ob_disk[i]); /* * Return the block device */ if (unregister_blkdev(MAJOR_NR, "i2o_block") != 0) printk("i2o_block: cleanup_module failed\n"); + + /* + * release request queue + */ + for (i = 0; i < MAX_I2O_CONTROLLERS; i ++) + if(i2ob_queues[i]) { + blk_cleanup_queue(i2ob_queues[i]->req_queue); + kfree(i2ob_queues[i]); + } } MODULE_AUTHOR("Red Hat"); --- linux-2.6.6/drivers/message/i2o/i2o_config.c 2003-06-14 12:18:33.000000000 -0700 +++ 25/drivers/message/i2o/i2o_config.c 2004-05-10 01:19:47.447525936 -0700 @@ -5,21 +5,24 @@ * * Written by Alan Cox, Building Number Three Ltd * - * Modified 04/20/1999 by Deepak Saxena - * - Added basic ioctl() support - * Modified 06/07/1999 by Deepak Saxena - * - Added software download ioctl (still testing) - * Modified 09/10/1999 by Auvo Häkkinen - * - Changes to i2o_cfg_reply(), ioctl_parms() - * - Added ioct_validate() - * Modified 09/30/1999 by Taneli Vähäkangas - * - Fixed ioctl_swdl() - * Modified 10/04/1999 by Taneli Vähäkangas - * - Changed ioctl_swdl(), implemented ioctl_swul() and ioctl_swdel() - * Modified 11/18/1999 by Deepak Saxena - * - Added event managmenet support - * - * 2.4 rewrite ported to 2.5 - Alan Cox + * Fixes/additions: + * Deepak Saxena (04/20/1999): + * Added basic ioctl() support + * Deepak Saxena (06/07/1999): + * Added software download ioctl (still testing) + * Auvo Häkkinen (09/10/1999): + * Changes to i2o_cfg_reply(), ioctl_parms() + * Added ioct_validate() + * Taneli Vähäkangas (09/30/1999): + * Fixed ioctl_swdl() + * Taneli Vähäkangas (10/04/1999): + * Changed ioctl_swdl(), implemented ioctl_swul() and ioctl_swdel() + * Deepak Saxena (11/18/1999): + * Added event managmenet support + * Alan Cox : + * 2.4 rewrite ported to 2.5 + * Markus Lidel : + * Added pass-thru support for Adaptec's raidutils * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -49,6 +52,11 @@ struct wait_queue *i2o_wait_queue; #define MODINC(x,y) ((x) = ((x) + 1) % (y)) +struct sg_simple_element { + u32 flag_count; + u32 addr_bus; +}; + struct i2o_cfg_info { struct file* fp; @@ -75,6 +83,7 @@ static int ioctl_swdel(unsigned long); static int ioctl_validate(unsigned long); static int ioctl_evt_reg(unsigned long, struct file *); static int ioctl_evt_get(unsigned long, struct file *); +static int ioctl_passthru(unsigned long); static int cfg_fasync(int, struct file*, int); /* @@ -256,6 +265,10 @@ static int cfg_ioctl(struct inode *inode ret = ioctl_evt_get(arg, fp); break; + case I2OPASSTHRU: + ret = ioctl_passthru(arg); + break; + default: ret = -EINVAL; } @@ -827,6 +840,157 @@ static int ioctl_evt_get(unsigned long a return 0; } +static int ioctl_passthru(unsigned long arg) +{ + struct i2o_cmd_passthru *cmd = (struct i2o_cmd_passthru *) arg; + struct i2o_controller *c; + u32 msg[MSG_FRAME_SIZE]; + u32 *user_msg = (u32*)cmd->msg; + u32 *reply = NULL; + u32 *user_reply = NULL; + u32 size = 0; + u32 reply_size = 0; + u32 rcode = 0; + ulong sg_list[SG_TABLESIZE]; + u32 sg_offset = 0; + u32 sg_count = 0; + int sg_index = 0; + u32 i = 0; + ulong p = 0; + + c = i2o_find_controller(cmd->iop); + if(!c) + return -ENXIO; + + memset(&msg, 0, MSG_FRAME_SIZE*4); + if(get_user(size, &user_msg[0])) + return -EFAULT; + size = size>>16; + + user_reply = &user_msg[size]; + if(size > MSG_FRAME_SIZE) + return -EFAULT; + size *= 4; // Convert to bytes + + /* Copy in the user's I2O command */ + if(copy_from_user((void*)msg, (void*)user_msg, size)) + return -EFAULT; + get_user(reply_size, &user_reply[0]); + reply_size = reply_size>>16; + reply = kmalloc(REPLY_FRAME_SIZE*4, GFP_KERNEL); + if(!reply) { + printk(KERN_WARNING"%s: Could not allocate reply buffer\n",c->name); + return -ENOMEM; + } + memset(reply, 0, REPLY_FRAME_SIZE*4); + sg_offset = (msg[0]>>4)&0x0f; + msg[2] = (u32)i2o_cfg_context; + msg[3] = (u32)reply; + + memset(sg_list,0, sizeof(sg_list[0])*SG_TABLESIZE); + if(sg_offset) { + // TODO 64bit fix + struct sg_simple_element *sg = (struct sg_simple_element*) (msg+sg_offset); + sg_count = (size - sg_offset*4) / sizeof(struct sg_simple_element); + if (sg_count > SG_TABLESIZE) { + printk(KERN_DEBUG"%s:IOCTL SG List too large (%u)\n", c->name,sg_count); + kfree (reply); + return -EINVAL; + } + + for(i = 0; i < sg_count; i++) { + int sg_size; + + if (!(sg[i].flag_count & 0x10000000 /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT*/)) { + printk(KERN_DEBUG"%s:Bad SG element %d - not simple (%x)\n",c->name,i, sg[i].flag_count); + rcode = -EINVAL; + goto cleanup; + } + sg_size = sg[i].flag_count & 0xffffff; + /* Allocate memory for the transfer */ + p = (ulong)kmalloc(sg_size, GFP_KERNEL); + if (!p) { + printk(KERN_DEBUG"%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", c->name,sg_size,i,sg_count); + rcode = -ENOMEM; + goto cleanup; + } + sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame. + /* Copy in the user's SG buffer if necessary */ + if(sg[i].flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR*/) { + // TODO 64bit fix + if (copy_from_user((void*)p,(void*)sg[i].addr_bus, sg_size)) { + printk(KERN_DEBUG"%s: Could not copy SG buf %d FROM user\n",c->name,i); + rcode = -EFAULT; + goto cleanup; + } + } + //TODO 64bit fix + sg[i].addr_bus = (u32)virt_to_bus((void*)p); + } + } + + rcode = i2o_post_wait(c, msg, size, 60); + if(rcode) + goto cleanup; + + if(sg_offset) { + /* Copy back the Scatter Gather buffers back to user space */ + u32 j; + // TODO 64bit fix + struct sg_simple_element* sg; + int sg_size; + + // re-acquire the original message to handle correctly the sg copy operation + memset(&msg, 0, MSG_FRAME_SIZE*4); + // get user msg size in u32s + if (get_user(size, &user_msg[0])) { + rcode = -EFAULT; + goto cleanup; + } + size = size>>16; + size *= 4; + /* Copy in the user's I2O command */ + if (copy_from_user ((void*)msg, (void*)user_msg, size)) { + rcode = -EFAULT; + goto cleanup; + } + sg_count = (size - sg_offset*4) / sizeof(struct sg_simple_element); + + // TODO 64bit fix + sg = (struct sg_simple_element*)(msg + sg_offset); + for (j = 0; j < sg_count; j++) { + /* Copy out the SG list to user's buffer if necessary */ + if (!(sg[j].flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR*/)) { + sg_size = sg[j].flag_count & 0xffffff; + // TODO 64bit fix + if (copy_to_user((void*)sg[j].addr_bus,(void*)sg_list[j], sg_size)) { + printk(KERN_WARNING"%s: Could not copy %lx TO user %x\n",c->name, sg_list[j], sg[j].addr_bus); + rcode = -EFAULT; + goto cleanup; + } + } + } + } + + /* Copy back the reply to user space */ + if (reply_size) { + // we wrote our own values for context - now restore the user supplied ones + if(copy_from_user(reply+2, user_msg+2, sizeof(u32)*2)) { + printk(KERN_WARNING"%s: Could not copy message context FROM user\n",c->name); + rcode = -EFAULT; + } + if(copy_to_user(user_reply, reply, reply_size)) { + printk(KERN_WARNING"%s: Could not copy reply TO user\n",c->name); + rcode = -EFAULT; + } + } + +cleanup: + kfree(reply); + i2o_unlock_controller(c); + return rcode; +} + static int cfg_open(struct inode *inode, struct file *file) { struct i2o_cfg_info *tmp = --- linux-2.6.6/drivers/message/i2o/i2o_core.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/message/i2o/i2o_core.c 2004-05-10 01:19:47.721484288 -0700 @@ -213,6 +213,135 @@ static struct notifier_block i2o_reboot_ static int verbose; +#if BITS_PER_LONG == 64 +/** + * i2o_context_list_add - append an ptr to the context list and return a + * matching context id. + * @ptr: pointer to add to the context list + * @c: controller to which the context list belong + * returns context id, which could be used in the transaction context + * field. + * + * Because the context field in I2O is only 32-bit large, on 64-bit the + * pointer is to large to fit in the context field. The i2o_context_list + * functiones map pointers to context fields. + */ +u32 i2o_context_list_add(void *ptr, struct i2o_controller *c) { + u32 context = 1; + struct i2o_context_list_element **entry = &c->context_list; + struct i2o_context_list_element *element; + unsigned long flags; + + spin_lock_irqsave(&c->context_list_lock, flags); + while(*entry && ((*entry)->flags & I2O_CONTEXT_LIST_USED)) { + if((*entry)->context >= context) + context = (*entry)->context + 1; + entry = &((*entry)->next); + } + + if(!*entry) { + if(unlikely(!context)) { + spin_unlock_irqrestore(&c->context_list_lock, flags); + printk(KERN_EMERG "i2o_core: context list overflow\n"); + return 0; + } + + element = kmalloc(sizeof(struct i2o_context_list_element), GFP_KERNEL); + if(!element) { + printk(KERN_EMERG "i2o_core: could not allocate memory for context list element\n"); + return 0; + } + element->context = context; + element->next = NULL; + *entry = element; + } else + element = *entry; + + element->ptr = ptr; + element->flags = I2O_CONTEXT_LIST_USED; + + spin_unlock_irqrestore(&c->context_list_lock, flags); + dprintk(KERN_DEBUG "i2o_core: add context to list %p -> %d\n", ptr, context); + return context; +} + +/** + * i2o_context_list_remove - remove a ptr from the context list and return + * the matching context id. + * @ptr: pointer to be removed from the context list + * @c: controller to which the context list belong + * returns context id, which could be used in the transaction context + * field. + */ +u32 i2o_context_list_remove(void *ptr, struct i2o_controller *c) { + struct i2o_context_list_element **entry = &c->context_list; + struct i2o_context_list_element *element; + u32 context; + unsigned long flags; + + spin_lock_irqsave(&c->context_list_lock, flags); + while(*entry && ((*entry)->ptr != ptr)) + entry = &((*entry)->next); + + if(unlikely(!*entry)) { + spin_unlock_irqrestore(&c->context_list_lock, flags); + printk(KERN_WARNING "i2o_core: could not remove nonexistent ptr %p\n", ptr); + return 0; + } + + element = *entry; + + context = element->context; + element->ptr = NULL; + element->flags |= I2O_CONTEXT_LIST_DELETED; + + spin_unlock_irqrestore(&c->context_list_lock, flags); + dprintk(KERN_DEBUG "i2o_core: markt as deleted in context list %p -> %d\n", ptr, context); + return context; +} + +/** + * i2o_context_list_get - get a ptr from the context list and remove it + * from the list. + * @context: context id to which the pointer belong + * @c: controller to which the context list belong + * returns pointer to the matching context id + */ +void *i2o_context_list_get(u32 context, struct i2o_controller *c) { + struct i2o_context_list_element **entry = &c->context_list; + struct i2o_context_list_element *element; + void *ptr; + int count = 0; + unsigned long flags; + + spin_lock_irqsave(&c->context_list_lock, flags); + while(*entry && ((*entry)->context != context)) { + entry = &((*entry)->next); + count ++; + } + + if(unlikely(!*entry)) { + spin_unlock_irqrestore(&c->context_list_lock, flags); + printk(KERN_WARNING "i2o_core: context id %d not found\n", context); + return NULL; + } + + element = *entry; + ptr = element->ptr; + if(count >= I2O_CONTEXT_LIST_MIN_LENGTH) { + *entry = (*entry)->next; + kfree(element); + } else { + element->ptr = NULL; + element->flags &= !I2O_CONTEXT_LIST_USED; + } + + spin_unlock_irqrestore(&c->context_list_lock, flags); + dprintk(KERN_DEBUG "i2o_core: get ptr from context list %d -> %p\n", context, ptr); + return ptr; +} +#endif + /* * I2O Core reply handler */ @@ -3551,6 +3680,10 @@ int __init i2o_pci_install(struct pci_de c->short_req = 0; c->pdev = dev; +#if BITS_PER_LONG == 64 + c->context_list_lock = SPIN_LOCK_UNLOCKED; +#endif + c->irq_mask = mem+0x34; c->post_port = mem+0x40; c->reply_port = mem+0x44; @@ -3788,3 +3921,6 @@ EXPORT_SYMBOL(i2o_event_ack); EXPORT_SYMBOL(i2o_report_status); EXPORT_SYMBOL(i2o_dump_message); EXPORT_SYMBOL(i2o_get_class_name); +EXPORT_SYMBOL(i2o_context_list_add); +EXPORT_SYMBOL(i2o_context_list_get); +EXPORT_SYMBOL(i2o_context_list_remove); --- linux-2.6.6/drivers/message/i2o/i2o_proc.c 2003-06-14 12:18:24.000000000 -0700 +++ 25/drivers/message/i2o/i2o_proc.c 2004-05-10 01:20:01.515387296 -0700 @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -64,13 +65,14 @@ typedef struct _i2o_proc_entry_t mode_t mode; /* mode */ read_proc_t *read_proc; /* read func */ write_proc_t *write_proc; /* write func */ + struct file_operations *fops_proc; /* file operations func */ } i2o_proc_entry; // #define DRIVERDEBUG -static int i2o_proc_read_lct(char *, char **, off_t, int, int *, void *); -static int i2o_proc_read_hrt(char *, char **, off_t, int, int *, void *); -static int i2o_proc_read_status(char *, char **, off_t, int, int *, void *); +static int i2o_seq_show_lct(struct seq_file *, void *); +static int i2o_seq_show_hrt(struct seq_file *, void *); +static int i2o_seq_show_status(struct seq_file *, void *); static int i2o_proc_read_hw(char *, char **, off_t, int, int *, void *); static int i2o_proc_read_ddm_table(char *, char **, off_t, int, int *, void *); @@ -151,20 +153,56 @@ static struct i2o_handler i2o_proc_handl 0xffffffff // All classes }; +static int i2o_seq_open_hrt(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_hrt, PDE(inode)->data); +}; + +struct file_operations i2o_seq_fops_hrt = { + .open = i2o_seq_open_hrt, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release +}; + +static int i2o_seq_open_lct(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_lct, PDE(inode)->data); +}; + +struct file_operations i2o_seq_fops_lct = { + .open = i2o_seq_open_lct, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release +}; + +static int i2o_seq_open_status(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_status, PDE(inode)->data); +}; + +struct file_operations i2o_seq_fops_status = { + .open = i2o_seq_open_status, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release +}; + /* * IOP specific entries...write field just in case someone * ever wants one. */ static i2o_proc_entry generic_iop_entries[] = { - {"hrt", S_IFREG|S_IRUGO, i2o_proc_read_hrt, NULL}, - {"lct", S_IFREG|S_IRUGO, i2o_proc_read_lct, NULL}, - {"status", S_IFREG|S_IRUGO, i2o_proc_read_status, NULL}, - {"hw", S_IFREG|S_IRUGO, i2o_proc_read_hw, NULL}, - {"ddm_table", S_IFREG|S_IRUGO, i2o_proc_read_ddm_table, NULL}, - {"driver_store", S_IFREG|S_IRUGO, i2o_proc_read_driver_store, NULL}, - {"drivers_stored", S_IFREG|S_IRUGO, i2o_proc_read_drivers_stored, NULL}, - {NULL, 0, NULL, NULL} + {"hrt", S_IFREG|S_IRUGO, NULL, NULL, &i2o_seq_fops_hrt}, + {"lct", S_IFREG|S_IRUGO, NULL, NULL, &i2o_seq_fops_lct}, + {"status", S_IFREG|S_IRUGO, NULL, NULL, &i2o_seq_fops_status}, + {"hw", S_IFREG|S_IRUGO, i2o_proc_read_hw, NULL, NULL}, + {"ddm_table", S_IFREG|S_IRUGO, i2o_proc_read_ddm_table, NULL, NULL}, + {"driver_store", S_IFREG|S_IRUGO, i2o_proc_read_driver_store, NULL, NULL}, + {"drivers_stored", S_IFREG|S_IRUGO, i2o_proc_read_drivers_stored, NULL, NULL}, + {NULL, 0, NULL, NULL, NULL} }; /* @@ -172,18 +210,18 @@ static i2o_proc_entry generic_iop_entrie */ static i2o_proc_entry generic_dev_entries[] = { - {"groups", S_IFREG|S_IRUGO, i2o_proc_read_groups, NULL}, - {"phys_dev", S_IFREG|S_IRUGO, i2o_proc_read_phys_device, NULL}, - {"claimed", S_IFREG|S_IRUGO, i2o_proc_read_claimed, NULL}, - {"users", S_IFREG|S_IRUGO, i2o_proc_read_users, NULL}, - {"priv_msgs", S_IFREG|S_IRUGO, i2o_proc_read_priv_msgs, NULL}, - {"authorized_users", S_IFREG|S_IRUGO, i2o_proc_read_authorized_users, NULL}, - {"dev_identity", S_IFREG|S_IRUGO, i2o_proc_read_dev_identity, NULL}, - {"ddm_identity", S_IFREG|S_IRUGO, i2o_proc_read_ddm_identity, NULL}, - {"user_info", S_IFREG|S_IRUGO, i2o_proc_read_uinfo, NULL}, - {"sgl_limits", S_IFREG|S_IRUGO, i2o_proc_read_sgl_limits, NULL}, - {"sensors", S_IFREG|S_IRUGO, i2o_proc_read_sensors, NULL}, - {NULL, 0, NULL, NULL} + {"groups", S_IFREG|S_IRUGO, i2o_proc_read_groups, NULL, NULL}, + {"phys_dev", S_IFREG|S_IRUGO, i2o_proc_read_phys_device, NULL, NULL}, + {"claimed", S_IFREG|S_IRUGO, i2o_proc_read_claimed, NULL, NULL}, + {"users", S_IFREG|S_IRUGO, i2o_proc_read_users, NULL, NULL}, + {"priv_msgs", S_IFREG|S_IRUGO, i2o_proc_read_priv_msgs, NULL, NULL}, + {"authorized_users", S_IFREG|S_IRUGO, i2o_proc_read_authorized_users, NULL, NULL}, + {"dev_identity", S_IFREG|S_IRUGO, i2o_proc_read_dev_identity, NULL, NULL}, + {"ddm_identity", S_IFREG|S_IRUGO, i2o_proc_read_ddm_identity, NULL, NULL}, + {"user_info", S_IFREG|S_IRUGO, i2o_proc_read_uinfo, NULL, NULL}, + {"sgl_limits", S_IFREG|S_IRUGO, i2o_proc_read_sgl_limits, NULL, NULL}, + {"sensors", S_IFREG|S_IRUGO, i2o_proc_read_sensors, NULL, NULL}, + {NULL, 0, NULL, NULL, NULL} }; /* @@ -191,7 +229,7 @@ static i2o_proc_entry generic_dev_entrie */ static i2o_proc_entry rbs_dev_entries[] = { - {"dev_name", S_IFREG|S_IRUGO, i2o_proc_read_dev_name, NULL}, + {"dev_name", S_IFREG|S_IRUGO, i2o_proc_read_dev_name, NULL, NULL}, {NULL, 0, NULL, NULL} }; @@ -223,21 +261,21 @@ static char *scsi_devices[] = */ static i2o_proc_entry lan_entries[] = { - {"lan_dev_info", S_IFREG|S_IRUGO, i2o_proc_read_lan_dev_info, NULL}, - {"lan_mac_addr", S_IFREG|S_IRUGO, i2o_proc_read_lan_mac_addr, NULL}, + {"lan_dev_info", S_IFREG|S_IRUGO, i2o_proc_read_lan_dev_info, NULL, NULL}, + {"lan_mac_addr", S_IFREG|S_IRUGO, i2o_proc_read_lan_mac_addr, NULL, NULL}, {"lan_mcast_addr", S_IFREG|S_IRUGO|S_IWUSR, - i2o_proc_read_lan_mcast_addr, NULL}, + i2o_proc_read_lan_mcast_addr, NULL, NULL}, {"lan_batch_ctrl", S_IFREG|S_IRUGO|S_IWUSR, - i2o_proc_read_lan_batch_control, NULL}, - {"lan_operation", S_IFREG|S_IRUGO, i2o_proc_read_lan_operation, NULL}, + i2o_proc_read_lan_batch_control, NULL, NULL}, + {"lan_operation", S_IFREG|S_IRUGO, i2o_proc_read_lan_operation, NULL, NULL}, {"lan_media_operation", S_IFREG|S_IRUGO, - i2o_proc_read_lan_media_operation, NULL}, - {"lan_alt_addr", S_IFREG|S_IRUGO, i2o_proc_read_lan_alt_addr, NULL}, - {"lan_tx_info", S_IFREG|S_IRUGO, i2o_proc_read_lan_tx_info, NULL}, - {"lan_rx_info", S_IFREG|S_IRUGO, i2o_proc_read_lan_rx_info, NULL}, + i2o_proc_read_lan_media_operation, NULL, NULL}, + {"lan_alt_addr", S_IFREG|S_IRUGO, i2o_proc_read_lan_alt_addr, NULL, NULL}, + {"lan_tx_info", S_IFREG|S_IRUGO, i2o_proc_read_lan_tx_info, NULL, NULL}, + {"lan_rx_info", S_IFREG|S_IRUGO, i2o_proc_read_lan_rx_info, NULL, NULL}, - {"lan_hist_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_hist_stats, NULL}, - {NULL, 0, NULL, NULL} + {"lan_hist_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_hist_stats, NULL, NULL}, + {NULL, 0, NULL, NULL, NULL} }; /* @@ -246,20 +284,20 @@ static i2o_proc_entry lan_entries[] = */ static i2o_proc_entry lan_eth_entries[] = { - {"lan_eth_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_eth_stats, NULL}, - {NULL, 0, NULL, NULL} + {"lan_eth_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_eth_stats, NULL, NULL}, + {NULL, 0, NULL, NULL, NULL} }; static i2o_proc_entry lan_tr_entries[] = { - {"lan_tr_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_tr_stats, NULL}, - {NULL, 0, NULL, NULL} + {"lan_tr_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_tr_stats, NULL, NULL}, + {NULL, 0, NULL, NULL, NULL} }; static i2o_proc_entry lan_fddi_entries[] = { - {"lan_fddi_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_fddi_stats, NULL}, - {NULL, 0, NULL, NULL} + {"lan_fddi_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_fddi_stats, NULL, NULL}, + {NULL, 0, NULL, NULL, NULL} }; @@ -300,116 +338,98 @@ static char* bus_strings[] = static spinlock_t i2o_proc_lock = SPIN_LOCK_UNLOCKED; -int i2o_proc_read_hrt(char *buf, char **start, off_t offset, int count, - int *eof, void *data) +int i2o_seq_show_hrt(struct seq_file *seq, void *v) { - struct i2o_controller *c = (struct i2o_controller *)data; + struct i2o_controller *c = (struct i2o_controller *)seq->private; i2o_hrt *hrt = (i2o_hrt *)c->hrt; u32 bus; - int len, i; - - spin_lock(&i2o_proc_lock); - - len = 0; + int i; if(hrt->hrt_version) { - len += sprintf(buf+len, - "HRT table for controller is too new a version.\n"); - spin_unlock(&i2o_proc_lock); - return len; + seq_printf(seq, "HRT table for controller is too new a version.\n"); + return 0; } - if((hrt->num_entries * hrt->entry_len + 8) > 2048) { - printk(KERN_WARNING "i2o_proc: HRT does not fit into buffer\n"); - len += sprintf(buf+len, - "HRT table too big to fit in buffer.\n"); - spin_unlock(&i2o_proc_lock); - return len; - } - - len += sprintf(buf+len, "HRT has %d entries of %d bytes each.\n", + seq_printf(seq, "HRT has %d entries of %d bytes each.\n", hrt->num_entries, hrt->entry_len << 2); - for(i = 0; i < hrt->num_entries && len < count; i++) + for(i = 0; i < hrt->num_entries; i++) { - len += sprintf(buf+len, "Entry %d:\n", i); - len += sprintf(buf+len, " Adapter ID: %0#10x\n", + seq_printf(seq, "Entry %d:\n", i); + seq_printf(seq, " Adapter ID: %0#10x\n", hrt->hrt_entry[i].adapter_id); - len += sprintf(buf+len, " Controlling tid: %0#6x\n", + seq_printf(seq, " Controlling tid: %0#6x\n", hrt->hrt_entry[i].parent_tid); if(hrt->hrt_entry[i].bus_type != 0x80) { bus = hrt->hrt_entry[i].bus_type; - len += sprintf(buf+len, " %s Information\n", bus_strings[bus]); + seq_printf(seq, " %s Information\n", bus_strings[bus]); switch(bus) { case I2O_BUS_LOCAL: - len += sprintf(buf+len, " IOBase: %0#6x,", + seq_printf(seq, " IOBase: %0#6x,", hrt->hrt_entry[i].bus.local_bus.LbBaseIOPort); - len += sprintf(buf+len, " MemoryBase: %0#10x\n", + seq_printf(seq, " MemoryBase: %0#10x\n", hrt->hrt_entry[i].bus.local_bus.LbBaseMemoryAddress); break; case I2O_BUS_ISA: - len += sprintf(buf+len, " IOBase: %0#6x,", + seq_printf(seq, " IOBase: %0#6x,", hrt->hrt_entry[i].bus.isa_bus.IsaBaseIOPort); - len += sprintf(buf+len, " MemoryBase: %0#10x,", + seq_printf(seq, " MemoryBase: %0#10x,", hrt->hrt_entry[i].bus.isa_bus.IsaBaseMemoryAddress); - len += sprintf(buf+len, " CSN: %0#4x,", + seq_printf(seq, " CSN: %0#4x,", hrt->hrt_entry[i].bus.isa_bus.CSN); break; case I2O_BUS_EISA: - len += sprintf(buf+len, " IOBase: %0#6x,", + seq_printf(seq, " IOBase: %0#6x,", hrt->hrt_entry[i].bus.eisa_bus.EisaBaseIOPort); - len += sprintf(buf+len, " MemoryBase: %0#10x,", + seq_printf(seq, " MemoryBase: %0#10x,", hrt->hrt_entry[i].bus.eisa_bus.EisaBaseMemoryAddress); - len += sprintf(buf+len, " Slot: %0#4x,", + seq_printf(seq, " Slot: %0#4x,", hrt->hrt_entry[i].bus.eisa_bus.EisaSlotNumber); break; case I2O_BUS_MCA: - len += sprintf(buf+len, " IOBase: %0#6x,", + seq_printf(seq, " IOBase: %0#6x,", hrt->hrt_entry[i].bus.mca_bus.McaBaseIOPort); - len += sprintf(buf+len, " MemoryBase: %0#10x,", + seq_printf(seq, " MemoryBase: %0#10x,", hrt->hrt_entry[i].bus.mca_bus.McaBaseMemoryAddress); - len += sprintf(buf+len, " Slot: %0#4x,", + seq_printf(seq, " Slot: %0#4x,", hrt->hrt_entry[i].bus.mca_bus.McaSlotNumber); break; case I2O_BUS_PCI: - len += sprintf(buf+len, " Bus: %0#4x", + seq_printf(seq, " Bus: %0#4x", hrt->hrt_entry[i].bus.pci_bus.PciBusNumber); - len += sprintf(buf+len, " Dev: %0#4x", + seq_printf(seq, " Dev: %0#4x", hrt->hrt_entry[i].bus.pci_bus.PciDeviceNumber); - len += sprintf(buf+len, " Func: %0#4x", + seq_printf(seq, " Func: %0#4x", hrt->hrt_entry[i].bus.pci_bus.PciFunctionNumber); - len += sprintf(buf+len, " Vendor: %0#6x", + seq_printf(seq, " Vendor: %0#6x", hrt->hrt_entry[i].bus.pci_bus.PciVendorID); - len += sprintf(buf+len, " Device: %0#6x\n", + seq_printf(seq, " Device: %0#6x\n", hrt->hrt_entry[i].bus.pci_bus.PciDeviceID); break; default: - len += sprintf(buf+len, " Unsupported Bus Type\n"); + seq_printf(seq, " Unsupported Bus Type\n"); } } else - len += sprintf(buf+len, " Unknown Bus Type\n"); + seq_printf(seq, " Unknown Bus Type\n"); } - - spin_unlock(&i2o_proc_lock); - return len; + return 0; } -int i2o_proc_read_lct(char *buf, char **start, off_t offset, int len, - int *eof, void *data) +int i2o_seq_show_lct(struct seq_file *seq, void *v) { - struct i2o_controller *c = (struct i2o_controller*)data; + struct i2o_controller *c = (struct i2o_controller*)seq->private; i2o_lct *lct = (i2o_lct *)c->lct; int entries; int i; @@ -422,23 +442,19 @@ int i2o_proc_read_lct(char *buf, char ** "Fibre Channel Bus" }; - spin_lock(&i2o_proc_lock); - len = 0; - entries = (lct->table_size - 3)/9; - len += sprintf(buf, "LCT contains %d %s\n", entries, + seq_printf(seq, "LCT contains %d %s\n", entries, entries == 1 ? "entry" : "entries"); if(lct->boot_tid) - len += sprintf(buf+len, "Boot Device @ ID %d\n", lct->boot_tid); + seq_printf(seq, "Boot Device @ ID %d\n", lct->boot_tid); - len += - sprintf(buf+len, "Current Change Indicator: %#10x\n", lct->change_ind); + seq_printf(seq, "Current Change Indicator: %#10x\n", lct->change_ind); for(i = 0; i < entries; i++) { - len += sprintf(buf+len, "Entry %d\n", i); - len += sprintf(buf+len, " Class, SubClass : %s", i2o_get_class_name(lct->lct_entry[i].class_id)); + seq_printf(seq, "Entry %d\n", i); + seq_printf(seq, " Class, SubClass : %s", i2o_get_class_name(lct->lct_entry[i].class_id)); /* * Classes which we'll print subclass info for @@ -449,23 +465,23 @@ int i2o_proc_read_lct(char *buf, char ** switch(lct->lct_entry[i].sub_class) { case 0x00: - len += sprintf(buf+len, ", Direct-Access Read/Write"); + seq_printf(seq, ", Direct-Access Read/Write"); break; case 0x04: - len += sprintf(buf+len, ", WORM Drive"); + seq_printf(seq, ", WORM Drive"); break; case 0x05: - len += sprintf(buf+len, ", CD-ROM Drive"); + seq_printf(seq, ", CD-ROM Drive"); break; case 0x07: - len += sprintf(buf+len, ", Optical Memory Device"); + seq_printf(seq, ", Optical Memory Device"); break; default: - len += sprintf(buf+len, ", Unknown (0x%02x)", + seq_printf(seq, ", Unknown (0x%02x)", lct->lct_entry[i].sub_class); break; } @@ -475,27 +491,27 @@ int i2o_proc_read_lct(char *buf, char ** switch(lct->lct_entry[i].sub_class & 0xFF) { case 0x30: - len += sprintf(buf+len, ", Ethernet"); + seq_printf(seq, ", Ethernet"); break; case 0x40: - len += sprintf(buf+len, ", 100base VG"); + seq_printf(seq, ", 100base VG"); break; case 0x50: - len += sprintf(buf+len, ", IEEE 802.5/Token-Ring"); + seq_printf(seq, ", IEEE 802.5/Token-Ring"); break; case 0x60: - len += sprintf(buf+len, ", ANSI X3T9.5 FDDI"); + seq_printf(seq, ", ANSI X3T9.5 FDDI"); break; case 0x70: - len += sprintf(buf+len, ", Fibre Channel"); + seq_printf(seq, ", Fibre Channel"); break; default: - len += sprintf(buf+len, ", Unknown Sub-Class (0x%02x)", + seq_printf(seq, ", Unknown Sub-Class (0x%02x)", lct->lct_entry[i].sub_class & 0xFF); break; } @@ -503,27 +519,27 @@ int i2o_proc_read_lct(char *buf, char ** case I2O_CLASS_SCSI_PERIPHERAL: if(lct->lct_entry[i].sub_class < SCSI_TABLE_SIZE) - len += sprintf(buf+len, ", %s", + seq_printf(seq, ", %s", scsi_devices[lct->lct_entry[i].sub_class]); else - len += sprintf(buf+len, ", Unknown Device Type"); + seq_printf(seq, ", Unknown Device Type"); break; case I2O_CLASS_BUS_ADAPTER_PORT: if(lct->lct_entry[i].sub_class < BUS_TABLE_SIZE) - len += sprintf(buf+len, ", %s", + seq_printf(seq, ", %s", bus_ports[lct->lct_entry[i].sub_class]); else - len += sprintf(buf+len, ", Unknown Bus Type"); + seq_printf(seq, ", Unknown Bus Type"); break; } - len += sprintf(buf+len, "\n"); + seq_printf(seq, "\n"); - len += sprintf(buf+len, " Local TID : 0x%03x\n", lct->lct_entry[i].tid); - len += sprintf(buf+len, " User TID : 0x%03x\n", lct->lct_entry[i].user_tid); - len += sprintf(buf+len, " Parent TID : 0x%03x\n", + seq_printf(seq, " Local TID : 0x%03x\n", lct->lct_entry[i].tid); + seq_printf(seq, " User TID : 0x%03x\n", lct->lct_entry[i].user_tid); + seq_printf(seq, " Parent TID : 0x%03x\n", lct->lct_entry[i].parent_tid); - len += sprintf(buf+len, " Identity Tag : 0x%x%x%x%x%x%x%x%x\n", + seq_printf(seq, " Identity Tag : 0x%x%x%x%x%x%x%x%x\n", lct->lct_entry[i].identity_tag[0], lct->lct_entry[i].identity_tag[1], lct->lct_entry[i].identity_tag[2], @@ -532,214 +548,207 @@ int i2o_proc_read_lct(char *buf, char ** lct->lct_entry[i].identity_tag[5], lct->lct_entry[i].identity_tag[6], lct->lct_entry[i].identity_tag[7]); - len += sprintf(buf+len, " Change Indicator : %0#10x\n", + seq_printf(seq, " Change Indicator : %0#10x\n", lct->lct_entry[i].change_ind); - len += sprintf(buf+len, " Event Capab Mask : %0#10x\n", + seq_printf(seq, " Event Capab Mask : %0#10x\n", lct->lct_entry[i].device_flags); } - spin_unlock(&i2o_proc_lock); - return len; + return 0; } -int i2o_proc_read_status(char *buf, char **start, off_t offset, int len, - int *eof, void *data) +int i2o_seq_show_status(struct seq_file *seq, void *v) { - struct i2o_controller *c = (struct i2o_controller*)data; + struct i2o_controller *c = (struct i2o_controller*)seq->private; char prodstr[25]; int version; - spin_lock(&i2o_proc_lock); - len = 0; - i2o_status_get(c); // reread the status block - len += sprintf(buf+len,"Organization ID : %0#6x\n", + seq_printf(seq, "Organization ID : %0#6x\n", c->status_block->org_id); version = c->status_block->i2o_version; /* FIXME for Spec 2.0 if (version == 0x02) { - len += sprintf(buf+len,"Lowest I2O version supported: "); + seq_printf(seq, "Lowest I2O version supported: "); switch(workspace[2]) { case 0x00: - len += sprintf(buf+len,"1.0\n"); + seq_printf(seq, "1.0\n"); break; case 0x01: - len += sprintf(buf+len,"1.5\n"); + seq_printf(seq, "1.5\n"); break; case 0x02: - len += sprintf(buf+len,"2.0\n"); + seq_printf(seq, "2.0\n"); break; } - len += sprintf(buf+len, "Highest I2O version supported: "); + seq_printf(seq, "Highest I2O version supported: "); switch(workspace[3]) { case 0x00: - len += sprintf(buf+len,"1.0\n"); + seq_printf(seq, "1.0\n"); break; case 0x01: - len += sprintf(buf+len,"1.5\n"); + seq_printf(seq, "1.5\n"); break; case 0x02: - len += sprintf(buf+len,"2.0\n"); + seq_printf(seq, "2.0\n"); break; } } */ - len += sprintf(buf+len,"IOP ID : %0#5x\n", + seq_printf(seq, "IOP ID : %0#5x\n", c->status_block->iop_id); - len += sprintf(buf+len,"Host Unit ID : %0#6x\n", + seq_printf(seq, "Host Unit ID : %0#6x\n", c->status_block->host_unit_id); - len += sprintf(buf+len,"Segment Number : %0#5x\n", + seq_printf(seq, "Segment Number : %0#5x\n", c->status_block->segment_number); - len += sprintf(buf+len, "I2O version : "); + seq_printf(seq, "I2O version : "); switch (version) { case 0x00: - len += sprintf(buf+len,"1.0\n"); + seq_printf(seq, "1.0\n"); break; case 0x01: - len += sprintf(buf+len,"1.5\n"); + seq_printf(seq, "1.5\n"); break; case 0x02: - len += sprintf(buf+len,"2.0\n"); + seq_printf(seq, "2.0\n"); break; default: - len += sprintf(buf+len,"Unknown version\n"); + seq_printf(seq, "Unknown version\n"); } - len += sprintf(buf+len, "IOP State : "); + seq_printf(seq, "IOP State : "); switch (c->status_block->iop_state) { case 0x01: - len += sprintf(buf+len,"INIT\n"); + seq_printf(seq, "INIT\n"); break; case 0x02: - len += sprintf(buf+len,"RESET\n"); + seq_printf(seq, "RESET\n"); break; case 0x04: - len += sprintf(buf+len,"HOLD\n"); + seq_printf(seq, "HOLD\n"); break; case 0x05: - len += sprintf(buf+len,"READY\n"); + seq_printf(seq, "READY\n"); break; case 0x08: - len += sprintf(buf+len,"OPERATIONAL\n"); + seq_printf(seq, "OPERATIONAL\n"); break; case 0x10: - len += sprintf(buf+len,"FAILED\n"); + seq_printf(seq, "FAILED\n"); break; case 0x11: - len += sprintf(buf+len,"FAULTED\n"); + seq_printf(seq, "FAULTED\n"); break; default: - len += sprintf(buf+len,"Unknown\n"); + seq_printf(seq, "Unknown\n"); break; } - len += sprintf(buf+len,"Messenger Type : "); + seq_printf(seq, "Messenger Type : "); switch (c->status_block->msg_type) { case 0x00: - len += sprintf(buf+len,"Memory mapped\n"); + seq_printf(seq, "Memory mapped\n"); break; case 0x01: - len += sprintf(buf+len,"Memory mapped only\n"); + seq_printf(seq, "Memory mapped only\n"); break; case 0x02: - len += sprintf(buf+len,"Remote only\n"); + seq_printf(seq,"Remote only\n"); break; case 0x03: - len += sprintf(buf+len,"Memory mapped and remote\n"); + seq_printf(seq, "Memory mapped and remote\n"); break; default: - len += sprintf(buf+len,"Unknown\n"); + seq_printf(seq, "Unknown\n"); } - len += sprintf(buf+len,"Inbound Frame Size : %d bytes\n", + seq_printf(seq, "Inbound Frame Size : %d bytes\n", c->status_block->inbound_frame_size<<2); - len += sprintf(buf+len,"Max Inbound Frames : %d\n", + seq_printf(seq, "Max Inbound Frames : %d\n", c->status_block->max_inbound_frames); - len += sprintf(buf+len,"Current Inbound Frames : %d\n", + seq_printf(seq, "Current Inbound Frames : %d\n", c->status_block->cur_inbound_frames); - len += sprintf(buf+len,"Max Outbound Frames : %d\n", + seq_printf(seq, "Max Outbound Frames : %d\n", c->status_block->max_outbound_frames); /* Spec doesn't say if NULL terminated or not... */ memcpy(prodstr, c->status_block->product_id, 24); prodstr[24] = '\0'; - len += sprintf(buf+len,"Product ID : %s\n", prodstr); - len += sprintf(buf+len,"Expected LCT Size : %d bytes\n", + seq_printf(seq, "Product ID : %s\n", prodstr); + seq_printf(seq, "Expected LCT Size : %d bytes\n", c->status_block->expected_lct_size); - len += sprintf(buf+len,"IOP Capabilities\n"); - len += sprintf(buf+len," Context Field Size Support : "); + seq_printf(seq, "IOP Capabilities\n"); + seq_printf(seq, " Context Field Size Support : "); switch (c->status_block->iop_capabilities & 0x0000003) { case 0: - len += sprintf(buf+len,"Supports only 32-bit context fields\n"); + seq_printf(seq, "Supports only 32-bit context fields\n"); break; case 1: - len += sprintf(buf+len,"Supports only 64-bit context fields\n"); + seq_printf(seq, "Supports only 64-bit context fields\n"); break; case 2: - len += sprintf(buf+len,"Supports 32-bit and 64-bit context fields, " + seq_printf(seq, "Supports 32-bit and 64-bit context fields, " "but not concurrently\n"); break; case 3: - len += sprintf(buf+len,"Supports 32-bit and 64-bit context fields " + seq_printf(seq, "Supports 32-bit and 64-bit context fields " "concurrently\n"); break; default: - len += sprintf(buf+len,"0x%08x\n",c->status_block->iop_capabilities); + seq_printf(seq, "0x%08x\n",c->status_block->iop_capabilities); } - len += sprintf(buf+len," Current Context Field Size : "); + seq_printf(seq, " Current Context Field Size : "); switch (c->status_block->iop_capabilities & 0x0000000C) { case 0: - len += sprintf(buf+len,"not configured\n"); + seq_printf(seq, "not configured\n"); break; case 4: - len += sprintf(buf+len,"Supports only 32-bit context fields\n"); + seq_printf(seq, "Supports only 32-bit context fields\n"); break; case 8: - len += sprintf(buf+len,"Supports only 64-bit context fields\n"); + seq_printf(seq, "Supports only 64-bit context fields\n"); break; case 12: - len += sprintf(buf+len,"Supports both 32-bit or 64-bit context fields " + seq_printf(seq, "Supports both 32-bit or 64-bit context fields " "concurrently\n"); break; default: - len += sprintf(buf+len,"\n"); + seq_printf(seq, "\n"); } - len += sprintf(buf+len," Inbound Peer Support : %s\n", + seq_printf(seq, " Inbound Peer Support : %s\n", (c->status_block->iop_capabilities & 0x00000010) ? "Supported" : "Not supported"); - len += sprintf(buf+len," Outbound Peer Support : %s\n", + seq_printf(seq, " Outbound Peer Support : %s\n", (c->status_block->iop_capabilities & 0x00000020) ? "Supported" : "Not supported"); - len += sprintf(buf+len," Peer to Peer Support : %s\n", + seq_printf(seq, " Peer to Peer Support : %s\n", (c->status_block->iop_capabilities & 0x00000040) ? "Supported" : "Not supported"); - len += sprintf(buf+len, "Desired private memory size : %d kB\n", + seq_printf(seq, "Desired private memory size : %d kB\n", c->status_block->desired_mem_size>>10); - len += sprintf(buf+len, "Allocated private memory size : %d kB\n", + seq_printf(seq, "Allocated private memory size : %d kB\n", c->status_block->current_mem_size>>10); - len += sprintf(buf+len, "Private memory base address : %0#10x\n", + seq_printf(seq, "Private memory base address : %0#10x\n", c->status_block->current_mem_base); - len += sprintf(buf+len, "Desired private I/O size : %d kB\n", + seq_printf(seq, "Desired private I/O size : %d kB\n", c->status_block->desired_io_size>>10); - len += sprintf(buf+len, "Allocated private I/O size : %d kB\n", + seq_printf(seq, "Allocated private I/O size : %d kB\n", c->status_block->current_io_size>>10); - len += sprintf(buf+len, "Private I/O base address : %0#10x\n", + seq_printf(seq, "Private I/O base address : %0#10x\n", c->status_block->current_io_base); - spin_unlock(&i2o_proc_lock); - - return len; + return 0; } int i2o_proc_read_hw(char *buf, char **start, off_t offset, int len, @@ -3146,6 +3155,9 @@ static int i2o_proc_create_entries(void ent->data = data; ent->read_proc = pentry->read_proc; ent->write_proc = pentry->write_proc; + if(pentry->fops_proc) + ent->proc_fops = pentry->fops_proc; + ent->nlink = 1; pentry++; @@ -3266,7 +3278,6 @@ static void i2o_proc_remove_controller(s sprintf(buff, "iop%d", pctrl->unit); i2o_proc_remove_entries(generic_iop_entries, pctrl->proc_entry); - remove_proc_entry(buff, parent); pctrl->proc_entry = NULL; } @@ -3306,8 +3317,8 @@ void i2o_proc_remove_device(struct i2o_d break; } } - remove_proc_entry(dev_id, dev->controller->proc_entry); } + remove_proc_entry(dev_id, dev->controller->proc_entry); } } @@ -3329,6 +3340,7 @@ static int create_i2o_procfs(void) i2o_proc_dir_root = proc_mkdir("i2o", 0); if(!i2o_proc_dir_root) return -1; + i2o_proc_dir_root->owner = THIS_MODULE; for(i = 0; i < MAX_I2O_CONTROLLERS; i++) { --- linux-2.6.6/drivers/message/i2o/i2o_scsi.c 2004-03-10 20:41:28.000000000 -0800 +++ 25/drivers/message/i2o/i2o_scsi.c 2004-05-10 01:19:47.723483984 -0700 @@ -62,9 +62,6 @@ #include "../../scsi/scsi.h" #include "../../scsi/hosts.h" -#if BITS_PER_LONG == 64 -#error FIXME: driver does not support 64-bit platforms -#endif #define VERSION_STRING "Version 0.1.2" @@ -233,7 +230,10 @@ static void i2o_scsi_reply(struct i2o_ha { spin_unlock_irqrestore(&retry_lock, flags); /* Create a scsi error for this */ - current_command = (Scsi_Cmnd *)m[3]; + current_command = (Scsi_Cmnd *)i2o_context_list_get(m[3], c); + if(!current_command) + return; + lock = current_command->device->host->host_lock; printk("Aborted %ld\n", current_command->serial_number); @@ -276,16 +276,15 @@ static void i2o_scsi_reply(struct i2o_ha printk(KERN_INFO "i2o_scsi: bus reset completed.\n"); return; } - /* - * FIXME: 64bit breakage - */ - current_command = (Scsi_Cmnd *)m[3]; + current_command = (Scsi_Cmnd *)i2o_context_list_get(m[3], c); /* * Is this a control request coming back - eg an abort ? */ + atomic_dec(&queue_depth); + if(current_command==NULL) { if(st) @@ -296,8 +295,6 @@ static void i2o_scsi_reply(struct i2o_ha dprintk(KERN_INFO "Completed %ld\n", current_command->serial_number); - atomic_dec(&queue_depth); - if(st == 0x06) { if(le32_to_cpu(m[5]) < current_command->underflow) @@ -647,9 +644,7 @@ static int i2o_scsi_queuecommand(Scsi_Cm if(tid == -1) { SCpnt->result = DID_NO_CONNECT << 16; - spin_lock_irqsave(host->host_lock, flags); done(SCpnt); - spin_unlock_irqrestore(host->host_lock, flags); return 0; } @@ -699,8 +694,7 @@ static int i2o_scsi_queuecommand(Scsi_Cm i2o_raw_writel(I2O_CMD_SCSI_EXEC<<24|HOST_TID<<12|tid, &msg[1]); i2o_raw_writel(scsi_context, &msg[2]); /* So the I2O layer passes to us */ - /* Sorry 64bit folks. FIXME */ - i2o_raw_writel((u32)SCpnt, &msg[3]); /* We want the SCSI control block back */ + i2o_raw_writel(i2o_context_list_add(SCpnt, c), &msg[3]); /* We want the SCSI control block back */ /* LSI_920_PCI_QUIRK * @@ -883,7 +877,7 @@ static int i2o_scsi_queuecommand(Scsi_Cm * @SCpnt: command to abort * * Ask the I2O controller to abort a command. This is an asynchrnous - * process and oru callback handler will see the command complete + * process and our callback handler will see the command complete * with an aborted message if it succeeds. * * Locks: no locks are held or needed @@ -894,10 +888,9 @@ int i2o_scsi_abort(Scsi_Cmnd * SCpnt) struct i2o_controller *c; struct Scsi_Host *host; struct i2o_scsi_host *hostdata; - unsigned long msg; - u32 m; + u32 msg[5]; int tid; - unsigned long timeout; + int status = FAILED; printk(KERN_WARNING "i2o_scsi: Aborting command block.\n"); @@ -907,37 +900,22 @@ int i2o_scsi_abort(Scsi_Cmnd * SCpnt) if(tid==-1) { printk(KERN_ERR "i2o_scsi: Impossible command to abort!\n"); - return FAILED; + return status; } c = hostdata->controller; spin_unlock_irq(host->host_lock); - timeout = jiffies+2*HZ; - do - { - m = le32_to_cpu(I2O_POST_READ32(c)); - if(m != 0xFFFFFFFF) - break; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); - mb(); - } - while(time_before(jiffies, timeout)); - - msg = c->mem_offset + m; - - i2o_raw_writel(FIVE_WORD_MSG_SIZE, msg); - i2o_raw_writel(I2O_CMD_SCSI_ABORT<<24|HOST_TID<<12|tid, msg+4); - i2o_raw_writel(scsi_context, msg+8); - i2o_raw_writel(0, msg+12); /* Not needed for an abort */ - i2o_raw_writel((u32)SCpnt, msg+16); - wmb(); - i2o_post_message(c,m); - wmb(); - + msg[0] = FIVE_WORD_MSG_SIZE; + msg[1] = I2O_CMD_SCSI_ABORT<<24|HOST_TID<<12|tid; + msg[2] = scsi_context; + msg[3] = 0; + msg[4] = i2o_context_list_remove(SCpnt, c); + if(i2o_post_wait(c, msg, sizeof(msg), 240)) + status = SUCCESS; + spin_lock_irq(host->host_lock); - return SUCCESS; + return status; } /** --- linux-2.6.6/drivers/message/i2o/Kconfig 2004-03-10 20:41:28.000000000 -0800 +++ 25/drivers/message/i2o/Kconfig 2004-05-10 01:19:47.857463616 -0700 @@ -3,7 +3,7 @@ menu "I2O device support" config I2O tristate "I2O support" - depends on PCI && !64BIT + depends on PCI ---help--- The Intelligent Input/Output (I2O) architecture allows hardware drivers to be split into two parts: an operating system specific @@ -20,19 +20,20 @@ config I2O drivers and OSM's with the following questions. To compile this support as a module, choose M here: the - modules will be called i2o_core and i2o_config. + modules will be called i2o_core. If unsure, say N. -config I2O_PCI - tristate "I2O PCI support" +config I2O_CONFIG + tristate "I2O Configuration support" depends on PCI && I2O help - Say Y for support of PCI bus I2O interface adapters. Currently this - is the only variety supported, so you should say Y. + Say Y for support of the configuration interface for the I2O adapters. + If you have a RAID controller from Adaptec and you want to use the + raidutils to manage your RAID array, you have to say Y here. To compile this support as a module, choose M here: the - module will be called i2o_pci. + module will be called i2o_config. config I2O_BLOCK tristate "I2O Block OSM" --- linux-2.6.6/drivers/message/i2o/Makefile 2003-06-14 12:18:25.000000000 -0700 +++ 25/drivers/message/i2o/Makefile 2004-05-10 01:19:47.857463616 -0700 @@ -5,7 +5,8 @@ # In the future, some of these should be built conditionally. # -obj-$(CONFIG_I2O) += i2o_core.o i2o_config.o +obj-$(CONFIG_I2O) += i2o_core.o +obj-$(CONFIG_I2O_CONFIG)+= i2o_config.o obj-$(CONFIG_I2O_BLOCK) += i2o_block.o obj-$(CONFIG_I2O_SCSI) += i2o_scsi.o obj-$(CONFIG_I2O_PROC) += i2o_proc.o --- linux-2.6.6/drivers/mtd/chips/amd_flash.c 2003-07-02 14:53:14.000000000 -0700 +++ 25/drivers/mtd/chips/amd_flash.c 2004-05-10 01:19:57.712965352 -0700 @@ -780,8 +780,8 @@ static struct mtd_info *amd_flash_probe( map->fldrv_priv = private; map->fldrv = &amd_flash_chipdrv; - MOD_INC_USE_COUNT; + __module_get(THIS_MODULE); return mtd; } --- linux-2.6.6/drivers/mtd/chips/cfi_cmdset_0001.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/mtd/chips/cfi_cmdset_0001.c 2004-05-10 01:19:48.121423488 -0700 @@ -431,6 +431,7 @@ static void put_chip(struct map_info *ma break; case FL_READY: + case FL_STATUS: /* We should really make set_vpp() count, rather than doing this */ DISABLE_VPP(map); break; --- linux-2.6.6/drivers/mtd/chips/sharp.c 2003-10-08 15:07:09.000000000 -0700 +++ 25/drivers/mtd/chips/sharp.c 2004-05-10 01:19:57.712965352 -0700 @@ -154,7 +154,7 @@ struct mtd_info *sharp_probe(struct map_ map->fldrv = &sharp_chipdrv; map->fldrv_priv = sharp; - MOD_INC_USE_COUNT; + __module_get(THIS_MODULE); return mtd; } --- linux-2.6.6/drivers/mtd/maps/tqm8xxl.c 2003-07-02 14:53:14.000000000 -0700 +++ 25/drivers/mtd/maps/tqm8xxl.c 2004-05-10 01:19:36.801144432 -0700 @@ -105,7 +105,7 @@ static struct mtd_partition tqm8xxl_fs_p .name = "jffs", .offset = 0x00200000, .size = 0x00200000, - .//size = MTDPART_SIZ_FULL, + //.size = MTDPART_SIZ_FULL, } }; #endif --- linux-2.6.6/drivers/net/3c59x.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/net/3c59x.c 2004-05-10 01:19:37.841986200 -0700 @@ -520,7 +520,7 @@ static struct vortex_chip_info { {"3c905B-FX Cyclone 100baseFx", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, }, {"3c905C Tornado", - PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM, 128, }, + PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, }, {"3c980 Cyclone", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, }, {"3c980C Python-T", --- linux-2.6.6/drivers/net/8139too.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/net/8139too.c 2004-05-10 01:19:43.628106576 -0700 @@ -1677,11 +1677,17 @@ static void rtl8139_tx_timeout (struct n u8 tmp8; unsigned long flags; - DPRINTK ("%s: Transmit timeout, status %2.2x %4.4x " - "media %2.2x.\n", dev->name, - RTL_R8 (ChipCmd), - RTL_R16 (IntrStatus), - RTL_R8 (MediaStatus)); + printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " + "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), + RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); + /* Emit info to figure out what went wrong. */ + printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", + dev->name, tp->cur_tx, tp->dirty_tx); + for (i = 0; i < NUM_TX_DESC; i++) + printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", + dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), + i == tp->dirty_tx % NUM_TX_DESC ? + " (queue head)" : ""); tp->xstats.tx_timeouts++; @@ -1694,15 +1700,6 @@ static void rtl8139_tx_timeout (struct n /* Disable interrupts by clearing the interrupt mask. */ RTL_W16 (IntrMask, 0x0000); - /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - /* Stop a shared interrupt from scavenging while we are. */ spin_lock_irqsave (&tp->lock, flags); rtl8139_tx_clear (tp); @@ -1714,7 +1711,6 @@ static void rtl8139_tx_timeout (struct n netif_wake_queue (dev); } spin_unlock(&tp->rx_lock); - } @@ -2558,6 +2554,8 @@ static int rtl8139_suspend (struct pci_d void *ioaddr = tp->mmio_addr; unsigned long flags; + pci_save_state (pdev, tp->pci_state); + if (!netif_running (dev)) return 0; @@ -2576,7 +2574,6 @@ static int rtl8139_suspend (struct pci_d spin_unlock_irqrestore (&tp->lock, flags); pci_set_power_state (pdev, 3); - pci_save_state (pdev, tp->pci_state); return 0; } @@ -2587,9 +2584,9 @@ static int rtl8139_resume (struct pci_de struct net_device *dev = pci_get_drvdata (pdev); struct rtl8139_private *tp = dev->priv; + pci_restore_state (pdev, tp->pci_state); if (!netif_running (dev)) return 0; - pci_restore_state (pdev, tp->pci_state); pci_set_power_state (pdev, 0); rtl8139_init_ring (dev); rtl8139_hw_start (dev); --- linux-2.6.6/drivers/net/82596.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/net/82596.c 2004-05-10 01:19:35.624323336 -0700 @@ -58,7 +58,6 @@ #include #include #include -#include static char version[] __initdata = "82596.c $Revision: 1.5 $\n"; --- linux-2.6.6/drivers/net/acenic.c 2004-03-10 20:41:28.000000000 -0800 +++ 25/drivers/net/acenic.c 2004-05-10 01:19:03.642185360 -0700 @@ -131,7 +131,6 @@ #define PCI_DEVICE_ID_SGI_ACENIC 0x0009 #endif -#if LINUX_VERSION_CODE >= 0x20400 static struct pci_device_id acenic_pci_tbl[] = { { PCI_VENDOR_ID_ALTEON, PCI_DEVICE_ID_ALTEON_ACENIC_FIBRE, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, }, @@ -156,37 +155,6 @@ static struct pci_device_id acenic_pci_t { } }; MODULE_DEVICE_TABLE(pci, acenic_pci_tbl); -#endif - - -#ifndef MODULE_LICENSE -#define MODULE_LICENSE(a) -#endif - -#ifndef wmb -#define wmb() mb() -#endif - -#ifndef __exit -#define __exit -#endif - -#ifndef __devinit -#define __devinit __init -#endif - -#ifndef SMP_CACHE_BYTES -#define SMP_CACHE_BYTES L1_CACHE_BYTES -#endif - -#ifndef SET_MODULE_OWNER -#define SET_MODULE_OWNER(dev) do{} while(0) -#define ACE_MOD_INC_USE_COUNT MOD_INC_USE_COUNT -#define ACE_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT -#else -#define ACE_MOD_INC_USE_COUNT do{} while(0) -#define ACE_MOD_DEC_USE_COUNT do{} while(0) -#endif #ifndef SET_NETDEV_DEV #define SET_NETDEV_DEV(net, pdev) do{} while(0) @@ -198,151 +166,8 @@ MODULE_DEVICE_TABLE(pci, acenic_pci_tbl) #define ace_sync_irq(irq) synchronize_irq() #endif -#if LINUX_VERSION_CODE < 0x2051e -#define local_irq_save(flags) do{__save_flags(flags) ; \ - __cli();} while(0) -#define local_irq_restore(flags) __restore_flags(flags) -#endif - -#if (LINUX_VERSION_CODE < 0x02030d) -#define pci_resource_start(dev, bar) dev->base_address[bar] -#elif (LINUX_VERSION_CODE < 0x02032c) -#define pci_resource_start(dev, bar) dev->resource[bar].start -#endif - -#if (LINUX_VERSION_CODE < 0x02030e) -#define net_device device -#endif - - -#if (LINUX_VERSION_CODE < 0x02032a) -typedef u32 dma_addr_t; - -static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, - dma_addr_t *dma_handle) -{ - void *virt_ptr; - - virt_ptr = kmalloc(size, GFP_KERNEL); - if (!virt_ptr) - return NULL; - *dma_handle = virt_to_bus(virt_ptr); - return virt_ptr; -} - -#define pci_free_consistent(cookie, size, ptr, dma_ptr) kfree(ptr) -#define pci_map_page(cookie, page, off, size, dir) \ - virt_to_bus(page_address(page)+(off)) -#define pci_unmap_page(cookie, address, size, dir) -#define pci_set_dma_mask(dev, mask) \ - (((u64)(mask) & 0xffffffff00000000) == 0 ? 0 : -EIO) -#define pci_dma_supported(dev, mask) \ - (((u64)(mask) & 0xffffffff00000000) == 0 ? 1 : 0) - -#elif (LINUX_VERSION_CODE < 0x02040d) - -/* - * 2.4.13 introduced pci_map_page()/pci_unmap_page() - for 2.4.12 and prior, - * fall back on pci_map_single()/pci_unnmap_single(). - * - * We are guaranteed that the page is mapped at this point since - * pci_map_page() is only used upon valid struct skb's. - */ -static inline dma_addr_t -pci_map_page(struct pci_dev *cookie, struct page *page, unsigned long off, - size_t size, int dir) -{ - void *page_virt; - - page_virt = page_address(page); - if (!page_virt) - BUG(); - return pci_map_single(cookie, (page_virt + off), size, dir); -} -#define pci_unmap_page(cookie, dma_addr, size, dir) \ - pci_unmap_single(cookie, dma_addr, size, dir) -#endif - -#if (LINUX_VERSION_CODE < 0x020412) -#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) -#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) -#define pci_unmap_addr(PTR, ADDR_NAME) 0 -#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do{} while(0) -#define pci_unmap_len(PTR, LEN_NAME) 0 -#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do{} while(0) -#endif - - -#if (LINUX_VERSION_CODE < 0x02032b) -/* - * SoftNet - * - * For pre-softnet kernels we need to tell the upper layer not to - * re-enter start_xmit() while we are in there. However softnet - * guarantees not to enter while we are in there so there is no need - * to do the netif_stop_queue() dance unless the transmit queue really - * gets stuck. This should also improve performance according to tests - * done by Aman Singla. - */ -#define dev_kfree_skb_irq(a) dev_kfree_skb(a) -#define netif_wake_queue(dev) clear_bit(0, &dev->tbusy) -#define netif_stop_queue(dev) set_bit(0, &dev->tbusy) -#define late_stop_netif_stop_queue(dev) do{} while(0) -#define early_stop_netif_stop_queue(dev) test_and_set_bit(0,&dev->tbusy) -#define early_stop_netif_wake_queue(dev) netif_wake_queue(dev) - -static inline void netif_start_queue(struct net_device *dev) -{ - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; -} - -#define ace_mark_net_bh() mark_bh(NET_BH) -#define netif_queue_stopped(dev) dev->tbusy -#define netif_running(dev) dev->start -#define ace_if_down(dev) do{dev->start = 0;} while(0) - -#define tasklet_struct tq_struct -static inline void tasklet_schedule(struct tasklet_struct *tasklet) -{ - queue_task(tasklet, &tq_immediate); - mark_bh(IMMEDIATE_BH); -} - -static inline void tasklet_init(struct tasklet_struct *tasklet, - void (*func)(unsigned long), - unsigned long data) -{ - tasklet->next = NULL; - tasklet->sync = 0; - tasklet->routine = (void (*)(void *))func; - tasklet->data = (void *)data; -} -#define tasklet_kill(tasklet) do{} while(0) -#else -#define late_stop_netif_stop_queue(dev) netif_stop_queue(dev) -#define early_stop_netif_stop_queue(dev) 0 -#define early_stop_netif_wake_queue(dev) do{} while(0) -#define ace_mark_net_bh() do{} while(0) -#define ace_if_down(dev) do{} while(0) -#endif - -#if (LINUX_VERSION_CODE >= 0x02031b) -#define NEW_NETINIT -#define ACE_PROBE_ARG void -#else -#define ACE_PROBE_ARG struct net_device *dev -#endif - -#ifndef min_t -#define min_t(type,a,b) (((a)<(b))?(a):(b)) -#endif - -#ifndef ARCH_HAS_PREFETCHW -#ifndef prefetchw -#define prefetchw(x) do{} while(0) -#endif +#ifndef offset_in_page +#define offset_in_page(ptr) ((unsigned long)(ptr) & ~PAGE_MASK) #endif #define ACE_MAX_MOD_PARMS 8 @@ -595,407 +420,323 @@ static int max_rx_desc[ACE_MAX_MOD_PARMS static int tx_ratio[ACE_MAX_MOD_PARMS]; static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1}; +MODULE_AUTHOR("Jes Sorensen "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver"); +MODULE_PARM(link, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(trace, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(tx_coal_tick, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(max_tx_desc, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(rx_coal_tick, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(max_rx_desc, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(tx_ratio, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM_DESC(link, "AceNIC/3C985/NetGear link state"); +MODULE_PARM_DESC(trace, "AceNIC/3C985/NetGear firmware trace level"); +MODULE_PARM_DESC(tx_coal_tick, "AceNIC/3C985/GA620 max clock ticks to wait from first tx descriptor arrives"); +MODULE_PARM_DESC(max_tx_desc, "AceNIC/3C985/GA620 max number of transmit descriptors to wait"); +MODULE_PARM_DESC(rx_coal_tick, "AceNIC/3C985/GA620 max clock ticks to wait from first rx descriptor arrives"); +MODULE_PARM_DESC(max_rx_desc, "AceNIC/3C985/GA620 max number of receive descriptors to wait"); +MODULE_PARM_DESC(tx_ratio, "AceNIC/3C985/GA620 ratio of NIC memory used for TX/RX descriptors (range 0-63)"); + + static char version[] __initdata = "acenic.c: v0.92 08/05/2002 Jes Sorensen, linux-acenic@SunSITE.dk\n" " http://home.cern.ch/~jes/gige/acenic.html\n"; -static struct net_device *root_dev; - -static int probed __initdata = 0; - - -int __devinit acenic_probe (ACE_PROBE_ARG) +static int __devinit acenic_probe_one(struct pci_dev *pdev, + const struct pci_device_id *id) { -#ifdef NEW_NETINIT struct net_device *dev; -#endif struct ace_private *ap; - struct pci_dev *pdev = NULL; - int boards_found = 0; - int version_disp; - - if (probed) - return -ENODEV; - probed++; - - version_disp = 0; - - while ((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET<<8, pdev))) { - - if (!((pdev->vendor == PCI_VENDOR_ID_ALTEON) && - ((pdev->device == PCI_DEVICE_ID_ALTEON_ACENIC_FIBRE) || - (pdev->device == PCI_DEVICE_ID_ALTEON_ACENIC_COPPER)))&& - !((pdev->vendor == PCI_VENDOR_ID_3COM) && - (pdev->device == PCI_DEVICE_ID_3COM_3C985)) && - !((pdev->vendor == PCI_VENDOR_ID_NETGEAR) && - ((pdev->device == PCI_DEVICE_ID_NETGEAR_GA620) || - (pdev->device == PCI_DEVICE_ID_NETGEAR_GA620T))) && - /* - * Farallon used the DEC vendor ID on their cards by - * mistake for a while - */ - !((pdev->vendor == PCI_VENDOR_ID_DEC) && - (pdev->device == PCI_DEVICE_ID_FARALLON_PN9000SX)) && - !((pdev->vendor == PCI_VENDOR_ID_ALTEON) && - (pdev->device == PCI_DEVICE_ID_FARALLON_PN9100T)) && - !((pdev->vendor == PCI_VENDOR_ID_SGI) && - (pdev->device == PCI_DEVICE_ID_SGI_ACENIC))) - continue; - - dev = alloc_etherdev(sizeof(struct ace_private)); - if (dev == NULL) { - printk(KERN_ERR "acenic: Unable to allocate " - "net_device structure!\n"); - break; - } + static int boards_found; - SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &pdev->dev); + dev = alloc_etherdev(sizeof(struct ace_private)); + if (dev == NULL) { + printk(KERN_ERR "acenic: Unable to allocate " + "net_device structure!\n"); + return -ENOMEM; + } - ap = dev->priv; - ap->pdev = pdev; + SET_MODULE_OWNER(dev); + SET_NETDEV_DEV(dev, &pdev->dev); - dev->open = &ace_open; - dev->hard_start_xmit = &ace_start_xmit; - dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; + ap = dev->priv; + ap->pdev = pdev; + + dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; #if ACENIC_DO_VLAN - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - dev->vlan_rx_register = ace_vlan_rx_register; - dev->vlan_rx_kill_vid = ace_vlan_rx_kill_vid; -#endif - if (1) { - static void ace_watchdog(struct net_device *dev); - dev->tx_timeout = &ace_watchdog; - dev->watchdog_timeo = 5*HZ; - } - dev->stop = &ace_close; - dev->get_stats = &ace_get_stats; - dev->set_multicast_list = &ace_set_multicast_list; - dev->do_ioctl = &ace_ioctl; - dev->set_mac_address = &ace_set_mac_addr; - dev->change_mtu = &ace_change_mtu; + dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + dev->vlan_rx_register = ace_vlan_rx_register; + dev->vlan_rx_kill_vid = ace_vlan_rx_kill_vid; +#endif + if (1) { + static void ace_watchdog(struct net_device *dev); + dev->tx_timeout = &ace_watchdog; + dev->watchdog_timeo = 5*HZ; + } - /* display version info if adapter is found */ - if (!version_disp) - { - /* set display flag to TRUE so that */ - /* we only display this string ONCE */ - version_disp = 1; - printk(version); - } + dev->open = &ace_open; + dev->stop = &ace_close; + dev->hard_start_xmit = &ace_start_xmit; + dev->get_stats = &ace_get_stats; + dev->set_multicast_list = &ace_set_multicast_list; + dev->do_ioctl = &ace_ioctl; + dev->set_mac_address = &ace_set_mac_addr; + dev->change_mtu = &ace_change_mtu; - if (pci_enable_device(pdev)) { - free_netdev(dev); - continue; - } + /* we only display this string ONCE */ + if (!boards_found) + printk(version); - /* - * Enable master mode before we start playing with the - * pci_command word since pci_set_master() will modify - * it. - */ - pci_set_master(pdev); + if (pci_enable_device(pdev)) + goto fail_free_netdev; - pci_read_config_word(pdev, PCI_COMMAND, &ap->pci_command); + /* + * Enable master mode before we start playing with the + * pci_command word since pci_set_master() will modify + * it. + */ + pci_set_master(pdev); - /* OpenFirmware on Mac's does not set this - DOH.. */ - if (!(ap->pci_command & PCI_COMMAND_MEMORY)) { - printk(KERN_INFO "%s: Enabling PCI Memory Mapped " - "access - was not enabled by BIOS/Firmware\n", - dev->name); - ap->pci_command = ap->pci_command | PCI_COMMAND_MEMORY; - pci_write_config_word(ap->pdev, PCI_COMMAND, - ap->pci_command); - wmb(); - } + pci_read_config_word(pdev, PCI_COMMAND, &ap->pci_command); - pci_read_config_byte(pdev, PCI_LATENCY_TIMER, - &ap->pci_latency); - if (ap->pci_latency <= 0x40) { - ap->pci_latency = 0x40; - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, - ap->pci_latency); - } + /* OpenFirmware on Mac's does not set this - DOH.. */ + if (!(ap->pci_command & PCI_COMMAND_MEMORY)) { + printk(KERN_INFO "%s: Enabling PCI Memory Mapped " + "access - was not enabled by BIOS/Firmware\n", + dev->name); + ap->pci_command = ap->pci_command | PCI_COMMAND_MEMORY; + pci_write_config_word(ap->pdev, PCI_COMMAND, + ap->pci_command); + wmb(); + } - /* - * Remap the regs into kernel space - this is abuse of - * dev->base_addr since it was means for I/O port - * addresses but who gives a damn. - */ - dev->base_addr = pci_resource_start(pdev, 0); - ap->regs = (struct ace_regs *)ioremap(dev->base_addr, 0x4000); - if (!ap->regs) { - printk(KERN_ERR "%s: Unable to map I/O register, " - "AceNIC %i will be disabled.\n", - dev->name, boards_found); - break; - } + pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &ap->pci_latency); + if (ap->pci_latency <= 0x40) { + ap->pci_latency = 0x40; + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, ap->pci_latency); + } - switch(pdev->vendor) { - case PCI_VENDOR_ID_ALTEON: - if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9100T) { - strncpy(ap->name, "Farallon PN9100-T " - "Gigabit Ethernet", sizeof (ap->name)); - printk(KERN_INFO "%s: Farallon PN9100-T ", - dev->name); - } else { - strncpy(ap->name, "AceNIC Gigabit Ethernet", - sizeof (ap->name)); - printk(KERN_INFO "%s: Alteon AceNIC ", - dev->name); - } - break; - case PCI_VENDOR_ID_3COM: - strncpy(ap->name, "3Com 3C985 Gigabit Ethernet", - sizeof (ap->name)); - printk(KERN_INFO "%s: 3Com 3C985 ", dev->name); - break; - case PCI_VENDOR_ID_NETGEAR: - strncpy(ap->name, "NetGear GA620 Gigabit Ethernet", - sizeof (ap->name)); - printk(KERN_INFO "%s: NetGear GA620 ", dev->name); - break; - case PCI_VENDOR_ID_DEC: - if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9000SX) { - strncpy(ap->name, "Farallon PN9000-SX " - "Gigabit Ethernet", sizeof (ap->name)); - printk(KERN_INFO "%s: Farallon PN9000-SX ", - dev->name); - break; - } - case PCI_VENDOR_ID_SGI: - strncpy(ap->name, "SGI AceNIC Gigabit Ethernet", + /* + * Remap the regs into kernel space - this is abuse of + * dev->base_addr since it was means for I/O port + * addresses but who gives a damn. + */ + dev->base_addr = pci_resource_start(pdev, 0); + ap->regs = (struct ace_regs *)ioremap(dev->base_addr, 0x4000); + if (!ap->regs) { + printk(KERN_ERR "%s: Unable to map I/O register, " + "AceNIC %i will be disabled.\n", + dev->name, boards_found); + goto fail_free_netdev; + } + + switch(pdev->vendor) { + case PCI_VENDOR_ID_ALTEON: + if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9100T) { + strncpy(ap->name, "Farallon PN9100-T " + "Gigabit Ethernet", sizeof (ap->name)); + printk(KERN_INFO "%s: Farallon PN9100-T ", + dev->name); + } else { + strncpy(ap->name, "AceNIC Gigabit Ethernet", sizeof (ap->name)); - printk(KERN_INFO "%s: SGI AceNIC ", dev->name); - break; - default: - strncpy(ap->name, "Unknown AceNIC based Gigabit " - "Ethernet", sizeof (ap->name)); - printk(KERN_INFO "%s: Unknown AceNIC ", dev->name); + printk(KERN_INFO "%s: Alteon AceNIC ", + dev->name); + } + break; + case PCI_VENDOR_ID_3COM: + strncpy(ap->name, "3Com 3C985 Gigabit Ethernet", + sizeof (ap->name)); + printk(KERN_INFO "%s: 3Com 3C985 ", dev->name); + break; + case PCI_VENDOR_ID_NETGEAR: + strncpy(ap->name, "NetGear GA620 Gigabit Ethernet", + sizeof (ap->name)); + printk(KERN_INFO "%s: NetGear GA620 ", dev->name); + break; + case PCI_VENDOR_ID_DEC: + if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9000SX) { + strncpy(ap->name, "Farallon PN9000-SX " + "Gigabit Ethernet", sizeof (ap->name)); + printk(KERN_INFO "%s: Farallon PN9000-SX ", + dev->name); break; } - ap->name [sizeof (ap->name) - 1] = '\0'; - printk("Gigabit Ethernet at 0x%08lx, ", dev->base_addr); + case PCI_VENDOR_ID_SGI: + strncpy(ap->name, "SGI AceNIC Gigabit Ethernet", + sizeof (ap->name)); + printk(KERN_INFO "%s: SGI AceNIC ", dev->name); + break; + default: + strncpy(ap->name, "Unknown AceNIC based Gigabit " + "Ethernet", sizeof (ap->name)); + printk(KERN_INFO "%s: Unknown AceNIC ", dev->name); + break; + } + + ap->name [sizeof (ap->name) - 1] = '\0'; + printk("Gigabit Ethernet at 0x%08lx, ", dev->base_addr); #ifdef __sparc__ - printk("irq %s\n", __irq_itoa(pdev->irq)); + printk("irq %s\n", __irq_itoa(pdev->irq)); #else - printk("irq %i\n", pdev->irq); + printk("irq %i\n", pdev->irq); #endif #ifdef CONFIG_ACENIC_OMIT_TIGON_I - if ((readl(&ap->regs->HostCtrl) >> 28) == 4) { - printk(KERN_ERR "%s: Driver compiled without Tigon I" - " support - NIC disabled\n", dev->name); - ace_init_cleanup(dev); - free_netdev(dev); - continue; - } + if ((readl(&ap->regs->HostCtrl) >> 28) == 4) { + printk(KERN_ERR "%s: Driver compiled without Tigon I" + " support - NIC disabled\n", dev->name); + goto fail_uninit; + } #endif - if (ace_allocate_descriptors(dev)) { - /* - * ace_allocate_descriptors() calls - * ace_init_cleanup() on error. - */ - free_netdev(dev); - continue; - } + if (ace_allocate_descriptors(dev)) + goto fail_free_netdev; #ifdef MODULE - if (boards_found >= ACE_MAX_MOD_PARMS) - ap->board_idx = BOARD_IDX_OVERFLOW; - else - ap->board_idx = boards_found; + if (boards_found >= ACE_MAX_MOD_PARMS) + ap->board_idx = BOARD_IDX_OVERFLOW; + else + ap->board_idx = boards_found; #else - ap->board_idx = BOARD_IDX_STATIC; + ap->board_idx = BOARD_IDX_STATIC; #endif - if (ace_init(dev)) { - /* - * ace_init() calls ace_init_cleanup() on error. - */ - free_netdev(dev); - continue; - } + if (ace_init(dev)) + goto fail_free_netdev; - if (register_netdev(dev)) { - printk(KERN_ERR "acenic: device registration failed\n"); - ace_init_cleanup(dev); - free_netdev(dev); - continue; - } - - if (ap->pci_using_dac) - dev->features |= NETIF_F_HIGHDMA; - - boards_found++; + if (register_netdev(dev)) { + printk(KERN_ERR "acenic: device registration failed\n"); + goto fail_uninit; } - /* - * If we're at this point we're going through ace_probe() for - * the first time. Return success (0) if we've initialized 1 - * or more boards. Otherwise, return failure (-ENODEV). - */ - - if (boards_found > 0) - return 0; - else - return -ENODEV; -} + if (ap->pci_using_dac) + dev->features |= NETIF_F_HIGHDMA; + pci_set_drvdata(pdev, dev); -#ifdef MODULE -MODULE_AUTHOR("Jes Sorensen "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver"); -MODULE_PARM(link, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(trace, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(tx_coal_tick, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(max_tx_desc, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(rx_coal_tick, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(max_rx_desc, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(tx_ratio, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM_DESC(link, "AceNIC/3C985/NetGear link state"); -MODULE_PARM_DESC(trace, "AceNIC/3C985/NetGear firmware trace level"); -MODULE_PARM_DESC(tx_coal_tick, "AceNIC/3C985/GA620 max clock ticks to wait from first tx descriptor arrives"); -MODULE_PARM_DESC(max_tx_desc, "AceNIC/3C985/GA620 max number of transmit descriptors to wait"); -MODULE_PARM_DESC(rx_coal_tick, "AceNIC/3C985/GA620 max clock ticks to wait from first rx descriptor arrives"); -MODULE_PARM_DESC(max_rx_desc, "AceNIC/3C985/GA620 max number of receive descriptors to wait"); -MODULE_PARM_DESC(tx_ratio, "AceNIC/3C985/GA620 ratio of NIC memory used for TX/RX descriptors (range 0-63)"); -#endif + boards_found++; + return 0; + fail_uninit: + ace_init_cleanup(dev); + fail_free_netdev: + free_netdev(dev); + return -ENODEV; +} -static void __exit ace_module_cleanup(void) +static void __devexit acenic_remove_one(struct pci_dev *pdev) { - struct ace_private *ap; - struct ace_regs *regs; - struct net_device *next; + struct net_device *dev = pci_get_drvdata(pdev); + struct ace_private *ap = dev->priv; + struct ace_regs *regs = ap->regs; short i; - while (root_dev) { - ap = root_dev->priv; - next = ap->next; - unregister_netdev(root_dev); + unregister_netdev(dev); - regs = ap->regs; - - writel(readl(®s->CpuCtrl) | CPU_HALT, ®s->CpuCtrl); - if (ap->version >= 2) - writel(readl(®s->CpuBCtrl) | CPU_HALT, - ®s->CpuBCtrl); - /* - * This clears any pending interrupts - */ - writel(1, ®s->Mb0Lo); - readl(®s->CpuCtrl); /* flush */ + writel(readl(®s->CpuCtrl) | CPU_HALT, ®s->CpuCtrl); + if (ap->version >= 2) + writel(readl(®s->CpuBCtrl) | CPU_HALT, ®s->CpuBCtrl); + + /* + * This clears any pending interrupts + */ + writel(1, ®s->Mb0Lo); + readl(®s->CpuCtrl); /* flush */ - /* - * Make sure no other CPUs are processing interrupts - * on the card before the buffers are being released. - * Otherwise one might experience some `interesting' - * effects. - * - * Then release the RX buffers - jumbo buffers were - * already released in ace_close(). - */ - ace_sync_irq(root_dev->irq); + /* + * Make sure no other CPUs are processing interrupts + * on the card before the buffers are being released. + * Otherwise one might experience some `interesting' + * effects. + * + * Then release the RX buffers - jumbo buffers were + * already released in ace_close(). + */ + ace_sync_irq(dev->irq); - for (i = 0; i < RX_STD_RING_ENTRIES; i++) { - struct sk_buff *skb = ap->skb->rx_std_skbuff[i].skb; + for (i = 0; i < RX_STD_RING_ENTRIES; i++) { + struct sk_buff *skb = ap->skb->rx_std_skbuff[i].skb; - if (skb) { - struct ring_info *ringp; - dma_addr_t mapping; + if (skb) { + struct ring_info *ringp; + dma_addr_t mapping; - ringp = &ap->skb->rx_std_skbuff[i]; - mapping = pci_unmap_addr(ringp, mapping); - pci_unmap_page(ap->pdev, mapping, - ACE_STD_BUFSIZE - (2 + 16), - PCI_DMA_FROMDEVICE); + ringp = &ap->skb->rx_std_skbuff[i]; + mapping = pci_unmap_addr(ringp, mapping); + pci_unmap_page(ap->pdev, mapping, + ACE_STD_BUFSIZE - (2 + 16), + PCI_DMA_FROMDEVICE); - ap->rx_std_ring[i].size = 0; - ap->skb->rx_std_skbuff[i].skb = NULL; - dev_kfree_skb(skb); - } - } - if (ap->version >= 2) { - for (i = 0; i < RX_MINI_RING_ENTRIES; i++) { - struct sk_buff *skb = ap->skb->rx_mini_skbuff[i].skb; - - if (skb) { - struct ring_info *ringp; - dma_addr_t mapping; - - ringp = &ap->skb->rx_mini_skbuff[i]; - mapping = pci_unmap_addr(ringp,mapping); - pci_unmap_page(ap->pdev, mapping, - ACE_MINI_BUFSIZE - (2 + 16), - PCI_DMA_FROMDEVICE); - - ap->rx_mini_ring[i].size = 0; - ap->skb->rx_mini_skbuff[i].skb = NULL; - dev_kfree_skb(skb); - } - } + ap->rx_std_ring[i].size = 0; + ap->skb->rx_std_skbuff[i].skb = NULL; + dev_kfree_skb(skb); } - for (i = 0; i < RX_JUMBO_RING_ENTRIES; i++) { - struct sk_buff *skb = ap->skb->rx_jumbo_skbuff[i].skb; + } + + if (ap->version >= 2) { + for (i = 0; i < RX_MINI_RING_ENTRIES; i++) { + struct sk_buff *skb = ap->skb->rx_mini_skbuff[i].skb; + if (skb) { struct ring_info *ringp; dma_addr_t mapping; - ringp = &ap->skb->rx_jumbo_skbuff[i]; - mapping = pci_unmap_addr(ringp, mapping); + ringp = &ap->skb->rx_mini_skbuff[i]; + mapping = pci_unmap_addr(ringp,mapping); pci_unmap_page(ap->pdev, mapping, - ACE_JUMBO_BUFSIZE - (2 + 16), + ACE_MINI_BUFSIZE - (2 + 16), PCI_DMA_FROMDEVICE); - ap->rx_jumbo_ring[i].size = 0; - ap->skb->rx_jumbo_skbuff[i].skb = NULL; + ap->rx_mini_ring[i].size = 0; + ap->skb->rx_mini_skbuff[i].skb = NULL; dev_kfree_skb(skb); } } - - ace_init_cleanup(root_dev); - free_netdev(root_dev); - root_dev = next; } -} + for (i = 0; i < RX_JUMBO_RING_ENTRIES; i++) { + struct sk_buff *skb = ap->skb->rx_jumbo_skbuff[i].skb; + if (skb) { + struct ring_info *ringp; + dma_addr_t mapping; -int __init ace_module_init(void) -{ - int status; + ringp = &ap->skb->rx_jumbo_skbuff[i]; + mapping = pci_unmap_addr(ringp, mapping); + pci_unmap_page(ap->pdev, mapping, + ACE_JUMBO_BUFSIZE - (2 + 16), + PCI_DMA_FROMDEVICE); - root_dev = NULL; + ap->rx_jumbo_ring[i].size = 0; + ap->skb->rx_jumbo_skbuff[i].skb = NULL; + dev_kfree_skb(skb); + } + } -#ifdef NEW_NETINIT - status = acenic_probe(); -#else - status = acenic_probe(NULL); -#endif - return status; + ace_init_cleanup(dev); + free_netdev(dev); } +static struct pci_driver acenic_pci_driver = { + .name = "acenic", + .id_table = acenic_pci_tbl, + .probe = acenic_probe_one, + .remove = __devexit_p(acenic_remove_one), +}; -#if (LINUX_VERSION_CODE < 0x02032a) -#ifdef MODULE -int init_module(void) +static int __init acenic_init(void) { - return ace_module_init(); + return pci_module_init(&acenic_pci_driver); } - -void cleanup_module(void) +static void __exit acenic_exit(void) { - ace_module_cleanup(); + pci_unregister_driver(&acenic_pci_driver); } -#endif -#else -module_init(ace_module_init); -module_exit(ace_module_cleanup); -#endif +module_init(acenic_init); +module_exit(acenic_exit); static void ace_free_descriptors(struct net_device *dev) { @@ -1462,13 +1203,6 @@ static int __init ace_init(struct net_de } else dev->irq = pdev->irq; - /* - * Register the device here to be able to catch allocated - * interrupt handlers in case the firmware doesn't come up. - */ - ap->next = root_dev; - root_dev = dev; - #ifdef INDEX_DEBUG spin_lock_init(&ap->debug_lock); ap->last_tx = ACE_TX_RING_ENTRIES(ap) - 1; @@ -2642,8 +2376,6 @@ static int ace_open(struct net_device *d netif_start_queue(dev); - ACE_MOD_INC_USE_COUNT; - /* * Setup the bottom half rx ring refill handler */ @@ -2660,8 +2392,6 @@ static int ace_close(struct net_device * unsigned long flags; short i; - ace_if_down(dev); - /* * Without (or before) releasing irq and stopping hardware, this * is an absolute non-sense, by the way. It will be reset instantly @@ -2733,7 +2463,6 @@ static int ace_close(struct net_device * ace_unmask_irq(dev); local_irq_restore(flags); - ACE_MOD_DEC_USE_COUNT; return 0; } @@ -2790,12 +2519,6 @@ static int ace_start_xmit(struct sk_buff struct tx_desc *desc; u32 idx, flagsize; - /* - * This only happens with pre-softnet, ie. 2.2.x kernels. - */ - if (early_stop_netif_stop_queue(dev)) - return 1; - restart: idx = ap->tx_prd; --- linux-2.6.6/drivers/net/arcnet/com90xx.c 2004-02-17 20:48:43.000000000 -0800 +++ 25/drivers/net/arcnet/com90xx.c 2004-05-10 01:19:44.525970080 -0700 @@ -155,7 +155,7 @@ static void __init com90xx_probe(void) ioaddr = *port; if (!request_region(*port, ARCNET_TOTAL_SIZE, "arcnet (90xx)")) { - BUGMSG2(D_INIT_REASONS, "(check_region)\n"); + BUGMSG2(D_INIT_REASONS, "(request_region)\n"); BUGMSG2(D_INIT_REASONS, "S1: "); BUGLVL(D_INIT_REASONS) numprint = 0; *port-- = ports[--numports]; @@ -214,7 +214,7 @@ static void __init com90xx_probe(void) BUGMSG2(D_INIT, "%lXh ", *p); if (!request_mem_region(*p, BUFFER_SIZE, "arcnet (90xx)")) { - BUGMSG2(D_INIT_REASONS, "(check_mem_region)\n"); + BUGMSG2(D_INIT_REASONS, "(request_mem_region)\n"); BUGMSG2(D_INIT_REASONS, "Stage 3: "); BUGLVL(D_INIT_REASONS) numprint = 0; *p-- = shmems[--numshmems]; --- linux-2.6.6/drivers/net/b44.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/net/b44.c 2004-05-10 01:19:03.646184752 -0700 @@ -27,8 +27,8 @@ #define DRV_MODULE_NAME "b44" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "0.93" -#define DRV_MODULE_RELDATE "Mar, 2004" +#define DRV_MODULE_VERSION "0.94" +#define DRV_MODULE_RELDATE "May 4, 2004" #define B44_DEF_MSG_ENABLE \ (NETIF_MSG_DRV | \ @@ -96,7 +96,7 @@ MODULE_DEVICE_TABLE(pci, b44_pci_tbl); static void b44_halt(struct b44 *); static void b44_init_rings(struct b44 *); -static int b44_init_hw(struct b44 *); +static void b44_init_hw(struct b44 *); static int b44_wait_bit(struct b44 *bp, unsigned long reg, u32 bit, unsigned long timeout, const int clear) @@ -331,6 +331,29 @@ static int b44_writephy(struct b44 *bp, return b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0); } +/* miilib interface */ +/* FIXME FIXME: phy_id is ignored, bp->phy_addr use is unconditional + * due to code existing before miilib use was added to this driver. + * Someone should remove this artificial driver limitation in + * b44_{read,write}phy. bp->phy_addr itself is fine (and needed). + */ +static int b44_mii_read(struct net_device *dev, int phy_id, int location) +{ + u32 val; + struct b44 *bp = netdev_priv(dev); + int rc = b44_readphy(bp, location, &val); + if (rc) + return 0xffffffff; + return val; +} + +static void b44_mii_write(struct net_device *dev, int phy_id, int location, + int val) +{ + struct b44 *bp = netdev_priv(dev); + b44_writephy(bp, location, val); +} + static int b44_phy_reset(struct b44 *bp) { u32 val; @@ -771,7 +794,7 @@ static int b44_rx(struct b44 *bp, int bu static int b44_poll(struct net_device *netdev, int *budget) { - struct b44 *bp = netdev->priv; + struct b44 *bp = netdev_priv(netdev); int done; spin_lock_irq(&bp->lock); @@ -821,7 +844,7 @@ static int b44_poll(struct net_device *n static irqreturn_t b44_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = dev_id; - struct b44 *bp = dev->priv; + struct b44 *bp = netdev_priv(dev); unsigned long flags; u32 istat, imask; int handled = 0; @@ -858,7 +881,7 @@ static irqreturn_t b44_interrupt(int irq static void b44_tx_timeout(struct net_device *dev) { - struct b44 *bp = dev->priv; + struct b44 *bp = netdev_priv(dev); printk(KERN_ERR PFX "%s: transmit timed out, resetting\n", dev->name); @@ -878,7 +901,7 @@ static void b44_tx_timeout(struct net_de static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct b44 *bp = dev->priv; + struct b44 *bp = netdev_priv(dev); dma_addr_t mapping; u32 len, entry, ctrl; @@ -932,7 +955,7 @@ static int b44_start_xmit(struct sk_buff static int b44_change_mtu(struct net_device *dev, int new_mtu) { - struct b44 *bp = dev->priv; + struct b44 *bp = netdev_priv(dev); if (new_mtu < B44_MIN_MTU || new_mtu > B44_MAX_MTU) return -EINVAL; @@ -1161,7 +1184,7 @@ static void __b44_set_mac_addr(struct b4 static int b44_set_mac_addr(struct net_device *dev, void *p) { - struct b44 *bp = dev->priv; + struct b44 *bp = netdev_priv(dev); struct sockaddr *addr = p; if (netif_running(dev)) @@ -1180,7 +1203,7 @@ static int b44_set_mac_addr(struct net_d * packet processing. Invoked with bp->lock held. */ static void __b44_set_rx_mode(struct net_device *); -static int b44_init_hw(struct b44 *bp) +static void b44_init_hw(struct b44 *bp) { u32 val; @@ -1212,13 +1235,11 @@ static int b44_init_hw(struct b44 *bp) val = br32(B44_ENET_CTRL); bw32(B44_ENET_CTRL, (val | ENET_CTRL_ENABLE)); - - return 0; } static int b44_open(struct net_device *dev) { - struct b44 *bp = dev->priv; + struct b44 *bp = netdev_priv(dev); int err; err = b44_alloc_consistent(bp); @@ -1232,9 +1253,7 @@ static int b44_open(struct net_device *d spin_lock_irq(&bp->lock); b44_init_rings(bp); - err = b44_init_hw(bp); - if (err) - goto err_out_noinit; + b44_init_hw(bp); bp->flags |= B44_FLAG_INIT_COMPLETE; spin_unlock_irq(&bp->lock); @@ -1249,11 +1268,6 @@ static int b44_open(struct net_device *d return 0; -err_out_noinit: - b44_halt(bp); - b44_free_rings(bp); - spin_unlock_irq(&bp->lock); - free_irq(dev->irq, dev); err_out_free: b44_free_consistent(bp); return err; @@ -1273,7 +1287,7 @@ err_out_free: static int b44_close(struct net_device *dev) { - struct b44 *bp = dev->priv; + struct b44 *bp = netdev_priv(dev); netif_stop_queue(dev); @@ -1300,7 +1314,7 @@ static int b44_close(struct net_device * static struct net_device_stats *b44_get_stats(struct net_device *dev) { - struct b44 *bp = dev->priv; + struct b44 *bp = netdev_priv(dev); struct net_device_stats *nstat = &bp->stats; struct b44_hw_stats *hwstat = &bp->hw_stats; @@ -1351,7 +1365,7 @@ static void __b44_load_mcast(struct b44 static void __b44_set_rx_mode(struct net_device *dev) { - struct b44 *bp = dev->priv; + struct b44 *bp = netdev_priv(dev); u32 val; val = br32(B44_RXCONFIG); @@ -1375,295 +1389,252 @@ static void __b44_set_rx_mode(struct net static void b44_set_rx_mode(struct net_device *dev) { - struct b44 *bp = dev->priv; + struct b44 *bp = netdev_priv(dev); spin_lock_irq(&bp->lock); __b44_set_rx_mode(dev); spin_unlock_irq(&bp->lock); } -static int b44_ethtool_ioctl (struct net_device *dev, void __user *useraddr) +static u32 b44_get_msglevel(struct net_device *dev) { - struct b44 *bp = dev->priv; - struct pci_dev *pci_dev = bp->pdev; - u32 ethcmd; + struct b44 *bp = netdev_priv(dev); + return bp->msg_enable; +} - if (copy_from_user (ðcmd, useraddr, sizeof (ethcmd))) - return -EFAULT; +static void b44_set_msglevel(struct net_device *dev, u32 value) +{ + struct b44 *bp = netdev_priv(dev); + bp->msg_enable = value; +} - switch (ethcmd) { - case ETHTOOL_GDRVINFO:{ - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - strcpy (info.driver, DRV_MODULE_NAME); - strcpy (info.version, DRV_MODULE_VERSION); - memset(&info.fw_version, 0, sizeof(info.fw_version)); - strcpy (info.bus_info, pci_name(pci_dev)); - info.eedump_len = 0; - info.regdump_len = 0; - if (copy_to_user (useraddr, &info, sizeof (info))) - return -EFAULT; - return 0; - } +static void b44_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *info) +{ + struct b44 *bp = netdev_priv(dev); + struct pci_dev *pci_dev = bp->pdev; - case ETHTOOL_GSET: { - struct ethtool_cmd cmd = { ETHTOOL_GSET }; + strcpy (info->driver, DRV_MODULE_NAME); + strcpy (info->version, DRV_MODULE_VERSION); + strcpy (info->bus_info, pci_name(pci_dev)); +} - if (!(bp->flags & B44_FLAG_INIT_COMPLETE)) - return -EAGAIN; - cmd.supported = (SUPPORTED_Autoneg); - cmd.supported |= (SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_MII); +static int b44_nway_reset(struct net_device *dev) +{ + struct b44 *bp = netdev_priv(dev); + u32 bmcr; + int r; - cmd.advertising = 0; - if (bp->flags & B44_FLAG_ADV_10HALF) - cmd.advertising |= ADVERTISE_10HALF; - if (bp->flags & B44_FLAG_ADV_10FULL) - cmd.advertising |= ADVERTISE_10FULL; - if (bp->flags & B44_FLAG_ADV_100HALF) - cmd.advertising |= ADVERTISE_100HALF; - if (bp->flags & B44_FLAG_ADV_100FULL) - cmd.advertising |= ADVERTISE_100FULL; - cmd.advertising |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - cmd.speed = (bp->flags & B44_FLAG_100_BASE_T) ? - SPEED_100 : SPEED_10; - cmd.duplex = (bp->flags & B44_FLAG_FULL_DUPLEX) ? - DUPLEX_FULL : DUPLEX_HALF; - cmd.port = 0; - cmd.phy_address = bp->phy_addr; - cmd.transceiver = (bp->flags & B44_FLAG_INTERNAL_PHY) ? - XCVR_INTERNAL : XCVR_EXTERNAL; - cmd.autoneg = (bp->flags & B44_FLAG_FORCE_LINK) ? - AUTONEG_DISABLE : AUTONEG_ENABLE; - cmd.maxtxpkt = 0; - cmd.maxrxpkt = 0; - if (copy_to_user(useraddr, &cmd, sizeof(cmd))) - return -EFAULT; - return 0; + spin_lock_irq(&bp->lock); + b44_readphy(bp, MII_BMCR, &bmcr); + b44_readphy(bp, MII_BMCR, &bmcr); + r = -EINVAL; + if (bmcr & BMCR_ANENABLE) { + b44_writephy(bp, MII_BMCR, + bmcr | BMCR_ANRESTART); + r = 0; } - case ETHTOOL_SSET: { - struct ethtool_cmd cmd; + spin_unlock_irq(&bp->lock); - if (!(bp->flags & B44_FLAG_INIT_COMPLETE)) - return -EAGAIN; + return r; +} - if (copy_from_user(&cmd, useraddr, sizeof(cmd))) - return -EFAULT; +static int b44_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct b44 *bp = netdev_priv(dev); - /* We do not support gigabit. */ - if (cmd.autoneg == AUTONEG_ENABLE) { - if (cmd.advertising & - (ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full)) - return -EINVAL; - } else if ((cmd.speed != SPEED_100 && - cmd.speed != SPEED_10) || - (cmd.duplex != DUPLEX_HALF && - cmd.duplex != DUPLEX_FULL)) { - return -EINVAL; - } + if (!(bp->flags & B44_FLAG_INIT_COMPLETE)) + return -EAGAIN; + cmd->supported = (SUPPORTED_Autoneg); + cmd->supported |= (SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_MII); + + cmd->advertising = 0; + if (bp->flags & B44_FLAG_ADV_10HALF) + cmd->advertising |= ADVERTISE_10HALF; + if (bp->flags & B44_FLAG_ADV_10FULL) + cmd->advertising |= ADVERTISE_10FULL; + if (bp->flags & B44_FLAG_ADV_100HALF) + cmd->advertising |= ADVERTISE_100HALF; + if (bp->flags & B44_FLAG_ADV_100FULL) + cmd->advertising |= ADVERTISE_100FULL; + cmd->advertising |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; + cmd->speed = (bp->flags & B44_FLAG_100_BASE_T) ? + SPEED_100 : SPEED_10; + cmd->duplex = (bp->flags & B44_FLAG_FULL_DUPLEX) ? + DUPLEX_FULL : DUPLEX_HALF; + cmd->port = 0; + cmd->phy_address = bp->phy_addr; + cmd->transceiver = (bp->flags & B44_FLAG_INTERNAL_PHY) ? + XCVR_INTERNAL : XCVR_EXTERNAL; + cmd->autoneg = (bp->flags & B44_FLAG_FORCE_LINK) ? + AUTONEG_DISABLE : AUTONEG_ENABLE; + cmd->maxtxpkt = 0; + cmd->maxrxpkt = 0; + return 0; +} - spin_lock_irq(&bp->lock); +static int b44_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct b44 *bp = netdev_priv(dev); - if (cmd.autoneg == AUTONEG_ENABLE) { - bp->flags &= ~B44_FLAG_FORCE_LINK; - bp->flags &= ~(B44_FLAG_ADV_10HALF | - B44_FLAG_ADV_10FULL | - B44_FLAG_ADV_100HALF | - B44_FLAG_ADV_100FULL); - if (cmd.advertising & ADVERTISE_10HALF) - bp->flags |= B44_FLAG_ADV_10HALF; - if (cmd.advertising & ADVERTISE_10FULL) - bp->flags |= B44_FLAG_ADV_10FULL; - if (cmd.advertising & ADVERTISE_100HALF) - bp->flags |= B44_FLAG_ADV_100HALF; - if (cmd.advertising & ADVERTISE_100FULL) - bp->flags |= B44_FLAG_ADV_100FULL; - } else { - bp->flags |= B44_FLAG_FORCE_LINK; - if (cmd.speed == SPEED_100) - bp->flags |= B44_FLAG_100_BASE_T; - if (cmd.duplex == DUPLEX_FULL) - bp->flags |= B44_FLAG_FULL_DUPLEX; - } + if (!(bp->flags & B44_FLAG_INIT_COMPLETE)) + return -EAGAIN; - b44_setup_phy(bp); + /* We do not support gigabit. */ + if (cmd->autoneg == AUTONEG_ENABLE) { + if (cmd->advertising & + (ADVERTISED_1000baseT_Half | + ADVERTISED_1000baseT_Full)) + return -EINVAL; + } else if ((cmd->speed != SPEED_100 && + cmd->speed != SPEED_10) || + (cmd->duplex != DUPLEX_HALF && + cmd->duplex != DUPLEX_FULL)) { + return -EINVAL; + } - spin_unlock_irq(&bp->lock); + spin_lock_irq(&bp->lock); - return 0; + if (cmd->autoneg == AUTONEG_ENABLE) { + bp->flags &= ~B44_FLAG_FORCE_LINK; + bp->flags &= ~(B44_FLAG_ADV_10HALF | + B44_FLAG_ADV_10FULL | + B44_FLAG_ADV_100HALF | + B44_FLAG_ADV_100FULL); + if (cmd->advertising & ADVERTISE_10HALF) + bp->flags |= B44_FLAG_ADV_10HALF; + if (cmd->advertising & ADVERTISE_10FULL) + bp->flags |= B44_FLAG_ADV_10FULL; + if (cmd->advertising & ADVERTISE_100HALF) + bp->flags |= B44_FLAG_ADV_100HALF; + if (cmd->advertising & ADVERTISE_100FULL) + bp->flags |= B44_FLAG_ADV_100FULL; + } else { + bp->flags |= B44_FLAG_FORCE_LINK; + if (cmd->speed == SPEED_100) + bp->flags |= B44_FLAG_100_BASE_T; + if (cmd->duplex == DUPLEX_FULL) + bp->flags |= B44_FLAG_FULL_DUPLEX; } - case ETHTOOL_GMSGLVL: { - struct ethtool_value edata = { ETHTOOL_GMSGLVL }; - edata.data = bp->msg_enable; - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - case ETHTOOL_SMSGLVL: { - struct ethtool_value edata; - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - bp->msg_enable = edata.data; - return 0; - } - case ETHTOOL_NWAY_RST: { - u32 bmcr; - int r; + b44_setup_phy(bp); - spin_lock_irq(&bp->lock); - b44_readphy(bp, MII_BMCR, &bmcr); - b44_readphy(bp, MII_BMCR, &bmcr); - r = -EINVAL; - if (bmcr & BMCR_ANENABLE) { - b44_writephy(bp, MII_BMCR, - bmcr | BMCR_ANRESTART); - r = 0; - } - spin_unlock_irq(&bp->lock); + spin_unlock_irq(&bp->lock); - return r; - } - case ETHTOOL_GLINK: { - struct ethtool_value edata = { ETHTOOL_GLINK }; - edata.data = netif_carrier_ok(bp->dev) ? 1 : 0; - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - case ETHTOOL_GRINGPARAM: { - struct ethtool_ringparam ering = { ETHTOOL_GRINGPARAM }; + return 0; +} - ering.rx_max_pending = B44_RX_RING_SIZE - 1; - ering.rx_pending = bp->rx_pending; +static void b44_get_ringparam(struct net_device *dev, + struct ethtool_ringparam *ering) +{ + struct b44 *bp = netdev_priv(dev); - /* XXX ethtool lacks a tx_max_pending, oops... */ + ering->rx_max_pending = B44_RX_RING_SIZE - 1; + ering->rx_pending = bp->rx_pending; - if (copy_to_user(useraddr, &ering, sizeof(ering))) - return -EFAULT; - return 0; - } - case ETHTOOL_SRINGPARAM: { - struct ethtool_ringparam ering; + /* XXX ethtool lacks a tx_max_pending, oops... */ +} - if (copy_from_user(&ering, useraddr, sizeof(ering))) - return -EFAULT; +static int b44_set_ringparam(struct net_device *dev, + struct ethtool_ringparam *ering) +{ + struct b44 *bp = netdev_priv(dev); - if ((ering.rx_pending > B44_RX_RING_SIZE - 1) || - (ering.rx_mini_pending != 0) || - (ering.rx_jumbo_pending != 0) || - (ering.tx_pending > B44_TX_RING_SIZE - 1)) - return -EINVAL; + if ((ering->rx_pending > B44_RX_RING_SIZE - 1) || + (ering->rx_mini_pending != 0) || + (ering->rx_jumbo_pending != 0) || + (ering->tx_pending > B44_TX_RING_SIZE - 1)) + return -EINVAL; - spin_lock_irq(&bp->lock); + spin_lock_irq(&bp->lock); - bp->rx_pending = ering.rx_pending; - bp->tx_pending = ering.tx_pending; + bp->rx_pending = ering->rx_pending; + bp->tx_pending = ering->tx_pending; - b44_halt(bp); - b44_init_rings(bp); - b44_init_hw(bp); - netif_wake_queue(bp->dev); - spin_unlock_irq(&bp->lock); + b44_halt(bp); + b44_init_rings(bp); + b44_init_hw(bp); + netif_wake_queue(bp->dev); + spin_unlock_irq(&bp->lock); - b44_enable_ints(bp); - - return 0; - } - case ETHTOOL_GPAUSEPARAM: { - struct ethtool_pauseparam epause = { ETHTOOL_GPAUSEPARAM }; + b44_enable_ints(bp); + + return 0; +} - epause.autoneg = - (bp->flags & B44_FLAG_PAUSE_AUTO) != 0; - epause.rx_pause = - (bp->flags & B44_FLAG_RX_PAUSE) != 0; - epause.tx_pause = - (bp->flags & B44_FLAG_TX_PAUSE) != 0; - if (copy_to_user(useraddr, &epause, sizeof(epause))) - return -EFAULT; - return 0; - } - case ETHTOOL_SPAUSEPARAM: { - struct ethtool_pauseparam epause; +static void b44_get_pauseparam(struct net_device *dev, + struct ethtool_pauseparam *epause) +{ + struct b44 *bp = netdev_priv(dev); - if (copy_from_user(&epause, useraddr, sizeof(epause))) - return -EFAULT; + epause->autoneg = + (bp->flags & B44_FLAG_PAUSE_AUTO) != 0; + epause->rx_pause = + (bp->flags & B44_FLAG_RX_PAUSE) != 0; + epause->tx_pause = + (bp->flags & B44_FLAG_TX_PAUSE) != 0; +} - spin_lock_irq(&bp->lock); - if (epause.autoneg) - bp->flags |= B44_FLAG_PAUSE_AUTO; - else - bp->flags &= ~B44_FLAG_PAUSE_AUTO; - if (epause.rx_pause) - bp->flags |= B44_FLAG_RX_PAUSE; - else - bp->flags &= ~B44_FLAG_RX_PAUSE; - if (epause.tx_pause) - bp->flags |= B44_FLAG_TX_PAUSE; - else - bp->flags &= ~B44_FLAG_TX_PAUSE; - if (bp->flags & B44_FLAG_PAUSE_AUTO) { - b44_halt(bp); - b44_init_rings(bp); - b44_init_hw(bp); - } else { - __b44_set_flow_ctrl(bp, bp->flags); - } - spin_unlock_irq(&bp->lock); +static int b44_set_pauseparam(struct net_device *dev, + struct ethtool_pauseparam *epause) +{ + struct b44 *bp = netdev_priv(dev); - b44_enable_ints(bp); - - return 0; + spin_lock_irq(&bp->lock); + if (epause->autoneg) + bp->flags |= B44_FLAG_PAUSE_AUTO; + else + bp->flags &= ~B44_FLAG_PAUSE_AUTO; + if (epause->rx_pause) + bp->flags |= B44_FLAG_RX_PAUSE; + else + bp->flags &= ~B44_FLAG_RX_PAUSE; + if (epause->tx_pause) + bp->flags |= B44_FLAG_TX_PAUSE; + else + bp->flags &= ~B44_FLAG_TX_PAUSE; + if (bp->flags & B44_FLAG_PAUSE_AUTO) { + b44_halt(bp); + b44_init_rings(bp); + b44_init_hw(bp); + } else { + __b44_set_flow_ctrl(bp, bp->flags); } - }; + spin_unlock_irq(&bp->lock); - return -EOPNOTSUPP; + b44_enable_ints(bp); + + return 0; } +static struct ethtool_ops b44_ethtool_ops = { + .get_drvinfo = b44_get_drvinfo, + .get_settings = b44_get_settings, + .set_settings = b44_set_settings, + .nway_reset = b44_nway_reset, + .get_link = ethtool_op_get_link, + .get_ringparam = b44_get_ringparam, + .set_ringparam = b44_set_ringparam, + .get_pauseparam = b44_get_pauseparam, + .set_pauseparam = b44_set_pauseparam, + .get_msglevel = b44_get_msglevel, + .set_msglevel = b44_set_msglevel, +}; + static int b44_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct mii_ioctl_data __user *data = (struct mii_ioctl_data __user *)&ifr->ifr_data; - struct b44 *bp = dev->priv; + struct b44 *bp = netdev_priv(dev); int err; - switch (cmd) { - case SIOCETHTOOL: - return b44_ethtool_ioctl(dev, (void __user*) ifr->ifr_data); - - case SIOCGMIIPHY: - data->phy_id = bp->phy_addr; - - /* fallthru */ - case SIOCGMIIREG: { - u32 mii_regval; - - spin_lock_irq(&bp->lock); - err = b44_readphy(bp, data->reg_num & 0x1f, &mii_regval); - spin_unlock_irq(&bp->lock); - - data->val_out = mii_regval; - - return err; - } - - case SIOCSMIIREG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irq(&bp->lock); - err = b44_writephy(bp, data->reg_num & 0x1f, data->val_in); - spin_unlock_irq(&bp->lock); - - return err; + spin_lock_irq(&bp->lock); + err = generic_mii_ioctl(&bp->mii_if, data, cmd, NULL); + spin_unlock_irq(&bp->lock); - default: - /* do nothing */ - break; - }; - return -EOPNOTSUPP; + return err; } /* Read 128-bytes of EEPROM. */ @@ -1772,7 +1743,7 @@ static int __devinit b44_init_one(struct /* No interesting netdevice features in this card... */ dev->features |= 0; - bp = dev->priv; + bp = netdev_priv(dev); bp->pdev = pdev; bp->dev = dev; if (b44_debug >= 0) @@ -1806,6 +1777,7 @@ static int __devinit b44_init_one(struct dev->watchdog_timeo = B44_TX_TIMEOUT; dev->change_mtu = b44_change_mtu; dev->irq = pdev->irq; + SET_ETHTOOL_OPS(dev, &b44_ethtool_ops); err = b44_get_invariants(bp); if (err) { @@ -1814,6 +1786,13 @@ static int __devinit b44_init_one(struct goto err_out_iounmap; } + bp->mii_if.dev = dev; + bp->mii_if.mdio_read = b44_mii_read; + bp->mii_if.mdio_write = b44_mii_write; + bp->mii_if.phy_id = bp->phy_addr; + bp->mii_if.phy_id_mask = 0x1f; + bp->mii_if.reg_num_mask = 0x1f; + /* By default, advertise all speed/duplex settings. */ bp->flags |= (B44_FLAG_ADV_10HALF | B44_FLAG_ADV_10FULL | B44_FLAG_ADV_100HALF | B44_FLAG_ADV_100FULL); @@ -1859,8 +1838,10 @@ static void __devexit b44_remove_one(str struct net_device *dev = pci_get_drvdata(pdev); if (dev) { + struct b44 *bp = netdev_priv(dev); + unregister_netdev(dev); - iounmap((void *) ((struct b44 *)(dev->priv))->regs); + iounmap((void *) bp->regs); free_netdev(dev); pci_release_regions(pdev); pci_disable_device(pdev); --- linux-2.6.6/drivers/net/b44.h 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/net/b44.h 2004-05-10 01:19:03.647184600 -0700 @@ -542,6 +542,8 @@ struct b44 { u8 phy_addr; u8 mdc_port; u8 core_unit; + + struct mii_if_info mii_if; }; #endif /* _B44_H */ --- linux-2.6.6/drivers/net/e1000/e1000_ethtool.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/net/e1000/e1000_ethtool.c 2004-05-10 01:19:03.652183840 -0700 @@ -53,7 +53,7 @@ struct e1000_stats { #define E1000_STAT(m) sizeof(((struct e1000_adapter *)0)->m), \ offsetof(struct e1000_adapter, m) -static struct e1000_stats e1000_gstrings_stats[] = { +static const struct e1000_stats e1000_gstrings_stats[] = { { "rx_packets", E1000_STAT(net_stats.rx_packets) }, { "tx_packets", E1000_STAT(net_stats.tx_packets) }, { "rx_bytes", E1000_STAT(net_stats.rx_bytes) }, @@ -100,9 +100,10 @@ static char e1000_gstrings_test[][ETH_GS }; #define E1000_TEST_LEN sizeof(e1000_gstrings_test) / ETH_GSTRING_LEN -static void -e1000_ethtool_gset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd) +static int +e1000_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { + struct e1000_adapter *adapter = netdev_priv(dev); struct e1000_hw *hw = &adapter->hw; if(hw->media_type == e1000_media_type_copper) { @@ -169,11 +170,13 @@ e1000_ethtool_gset(struct e1000_adapter } ecmd->autoneg = (hw->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); + return 0; } static int -e1000_ethtool_sset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd) +e1000_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { + struct e1000_adapter *adapter = netdev_priv(dev); struct e1000_hw *hw = &adapter->hw; if(ecmd->autoneg == AUTONEG_ENABLE) { @@ -195,10 +198,11 @@ e1000_ethtool_sset(struct e1000_adapter return 0; } -static int -e1000_ethtool_gpause(struct e1000_adapter *adapter, +static void +e1000_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *epause) { + struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; epause->autoneg = @@ -212,14 +216,13 @@ e1000_ethtool_gpause(struct e1000_adapte epause->rx_pause = 1; epause->tx_pause = 1; } - - return 0; } static int -e1000_ethtool_spause(struct e1000_adapter *adapter, +e1000_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *epause) { + struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; adapter->fc_autoneg = epause->autoneg; @@ -248,28 +251,95 @@ e1000_ethtool_spause(struct e1000_adapte return 0; } +static u32 +e1000_get_rx_csum(struct net_device *netdev) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + return adapter->rx_csum; +} + +static int +e1000_set_rx_csum(struct net_device *netdev, u32 data) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + + adapter->rx_csum = data; + if(netif_running(netdev)) { + e1000_down(adapter); + e1000_up(adapter); + } else + e1000_reset(adapter); + return 0; +} + +static u32 +e1000_get_tx_csum(struct net_device *netdev) +{ + return (netdev->features & NETIF_F_HW_CSUM) != 0; +} + +static int +e1000_set_tx_csum(struct net_device *netdev, u32 data) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + + if(adapter->hw.mac_type < e1000_82543) + return data ? -EINVAL : 0; + + if (data) + netdev->features |= NETIF_F_HW_CSUM; + else + netdev->features &= ~NETIF_F_HW_CSUM; + return 0; +} + +static int +e1000_set_tso(struct net_device *netdev, u32 data) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + + if (adapter->hw.mac_type < e1000_82544 || + adapter->hw.mac_type == e1000_82547) + return data ? -EINVAL : 0; + + if (data) + netdev->features |= NETIF_F_TSO; + else + netdev->features &= ~NETIF_F_TSO; + return 0; +} + + static void -e1000_ethtool_gdrvinfo(struct e1000_adapter *adapter, - struct ethtool_drvinfo *drvinfo) +e1000_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *drvinfo) { + struct e1000_adapter *adapter = netdev_priv(dev); + strncpy(drvinfo->driver, e1000_driver_name, 32); strncpy(drvinfo->version, e1000_driver_version, 32); strncpy(drvinfo->fw_version, "N/A", 32); strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32); - drvinfo->n_stats = E1000_STATS_LEN; - drvinfo->testinfo_len = E1000_TEST_LEN; +} + +static int +e1000_get_regs_len(struct net_device *dev) +{ #define E1000_REGS_LEN 32 - drvinfo->regdump_len = E1000_REGS_LEN * sizeof(uint32_t); - drvinfo->eedump_len = adapter->hw.eeprom.word_size * 2; + return E1000_REGS_LEN * sizeof(uint32_t); } static void -e1000_ethtool_gregs(struct e1000_adapter *adapter, - struct ethtool_regs *regs, uint32_t *regs_buff) +e1000_get_regs(struct net_device *dev, + struct ethtool_regs *regs, void *p) { + struct e1000_adapter *adapter = netdev_priv(dev); struct e1000_hw *hw = &adapter->hw; + u32 *regs_buff = p; uint16_t phy_data; + memset(p, 0, E1000_REGS_LEN * sizeof(uint32_t)); + regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id; regs_buff[0] = E1000_READ_REG(hw, CTRL); @@ -342,30 +412,36 @@ e1000_ethtool_gregs(struct e1000_adapter e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data); regs_buff[24] = (uint32_t)phy_data; /* phy local receiver status */ regs_buff[25] = regs_buff[24]; /* phy remote receiver status */ +} - return; +static int +e1000_get_eeprom_len(struct net_device *dev) +{ + struct e1000_adapter *adapter = netdev_priv(dev); + + return adapter->hw.eeprom.word_size * 2; } static int -e1000_ethtool_geeprom(struct e1000_adapter *adapter, - struct ethtool_eeprom *eeprom, uint16_t *eeprom_buff) +e1000_get_eeprom(struct net_device *dev, + struct ethtool_eeprom *eeprom, u8 *bytes) { + struct e1000_adapter *adapter = netdev_priv(dev); struct e1000_hw *hw = &adapter->hw; + uint16_t *eeprom_buff = (uint16_t *) bytes; int first_word, last_word; int ret_val = 0; uint16_t i; - if(eeprom->len == 0) { - ret_val = -EINVAL; - goto geeprom_error; - } + if(eeprom->len == 0) + return -EINVAL; eeprom->magic = hw->vendor_id | (hw->device_id << 16); - if(eeprom->offset > eeprom->offset + eeprom->len) { - ret_val = -EINVAL; - goto geeprom_error; - } + if(eeprom->offset > eeprom->offset + eeprom->len) + return -EINVAL; + + memset(bytes, 0, adapter->hw.eeprom.word_size*2); if((eeprom->offset + eeprom->len) > (hw->eeprom.word_size * 2)) eeprom->len = ((hw->eeprom.word_size * 2) - eeprom->offset); @@ -388,14 +464,14 @@ e1000_ethtool_geeprom(struct e1000_adapt for (i = 0; i < last_word - first_word + 1; i++) le16_to_cpus(&eeprom_buff[i]); -geeprom_error: return ret_val; } static int -e1000_ethtool_seeprom(struct e1000_adapter *adapter, - struct ethtool_eeprom *eeprom, void *user_data) +e1000_set_eeprom(struct net_device *netdev, + struct ethtool_eeprom *eeprom, u8 *bytes) { + struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; uint16_t *eeprom_buff; void *ptr; @@ -439,11 +515,7 @@ e1000_ethtool_seeprom(struct e1000_adapt for (i = 0; i < last_word - first_word + 1; i++) le16_to_cpus(&eeprom_buff[i]); - if((ret_val != 0) || copy_from_user(ptr, user_data, eeprom->len)) { - ret_val = -EFAULT; - goto seeprom_error; - } - + memcpy(ptr, bytes, eeprom->len); for (i = 0; i < last_word - first_word + 1; i++) eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]); @@ -454,15 +526,15 @@ e1000_ethtool_seeprom(struct e1000_adapt if((ret_val == 0) && first_word <= EEPROM_CHECKSUM_REG) e1000_update_eeprom_checksum(hw); -seeprom_error: kfree(eeprom_buff); return ret_val; } -static int -e1000_ethtool_gring(struct e1000_adapter *adapter, +static void +e1000_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { + struct e1000_adapter *adapter = netdev_priv(netdev); e1000_mac_type mac_type = adapter->hw.mac_type; struct e1000_desc_ring *txdr = &adapter->tx_ring; struct e1000_desc_ring *rxdr = &adapter->rx_ring; @@ -477,13 +549,12 @@ e1000_ethtool_gring(struct e1000_adapter ring->tx_pending = txdr->count; ring->rx_mini_pending = 0; ring->rx_jumbo_pending = 0; - - return 0; } + static int -e1000_ethtool_sring(struct e1000_adapter *adapter, - struct ethtool_ringparam *ring) +e1000_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { + struct e1000_adapter *adapter = netdev_priv(netdev); int err; e1000_mac_type mac_type = adapter->hw.mac_type; struct e1000_desc_ring *txdr = &adapter->tx_ring; @@ -806,8 +877,6 @@ e1000_free_desc_rings(struct e1000_adapt kfree(txdr->buffer_info); if(rxdr->buffer_info) kfree(rxdr->buffer_info); - - return; } static int @@ -939,8 +1008,6 @@ e1000_phy_disable_receiver(struct e1000_ e1000_write_phy_reg(&adapter->hw, 30, 0x8FFC); e1000_write_phy_reg(&adapter->hw, 29, 0x001A); e1000_write_phy_reg(&adapter->hw, 30, 0x8FF0); - - return; } static void @@ -1257,11 +1324,19 @@ e1000_link_test(struct e1000_adapter *ad return *data; } + static int -e1000_ethtool_test(struct e1000_adapter *adapter, - struct ethtool_test *eth_test, uint64_t *data) +e1000_diag_test_count(struct net_device *dev) { - boolean_t if_running = netif_running(adapter->netdev); + return E1000_TEST_LEN; +} + +static void +e1000_diag_test(struct net_device *netdev, + struct ethtool_test *eth_test, u64 *data) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + boolean_t if_running = netif_running(netdev); if(eth_test->flags == ETH_TEST_FL_OFFLINE) { /* Offline tests */ @@ -1305,12 +1380,12 @@ e1000_ethtool_test(struct e1000_adapter data[2] = 0; data[3] = 0; } - return 0; } static void -e1000_ethtool_gwol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol) +e1000_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { + struct e1000_adapter *adapter = netdev_priv(dev); struct e1000_hw *hw = &adapter->hw; switch(adapter->hw.device_id) { @@ -1348,10 +1423,10 @@ e1000_ethtool_gwol(struct e1000_adapter return; } } - static int -e1000_ethtool_swol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol) +e1000_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { + struct e1000_adapter *adapter = netdev_priv(dev); struct e1000_hw *hw = &adapter->hw; switch(adapter->hw.device_id) { @@ -1408,8 +1483,13 @@ e1000_led_blink_callback(unsigned long d } static int -e1000_ethtool_led_blink(struct e1000_adapter *adapter, struct ethtool_value *id) +e1000_phys_id(struct net_device *netdev, u32 data) { + struct e1000_adapter *adapter = netdev_priv(netdev); + + if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) + data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); + if(!adapter->blink_timer.function) { init_timer(&adapter->blink_timer); adapter->blink_timer.function = e1000_led_blink_callback; @@ -1420,11 +1500,7 @@ e1000_ethtool_led_blink(struct e1000_ada mod_timer(&adapter->blink_timer, jiffies); set_current_state(TASK_INTERRUPTIBLE); - if(id->data) - schedule_timeout(id->data * HZ); - else - schedule_timeout(MAX_SCHEDULE_TIMEOUT); - + schedule_timeout(data * HZ); del_timer_sync(&adapter->blink_timer); e1000_led_off(&adapter->hw); clear_bit(E1000_LED_ON, &adapter->led_status); @@ -1433,345 +1509,89 @@ e1000_ethtool_led_blink(struct e1000_ada return 0; } -int -e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr) +static int +e1000_nway_reset(struct net_device *netdev) { - struct e1000_adapter *adapter = netdev->priv; - void *addr = ifr->ifr_data; - uint32_t cmd; - - if(get_user(cmd, (uint32_t *) addr)) - return -EFAULT; - - switch(cmd) { - case ETHTOOL_GSET: { - struct ethtool_cmd ecmd = {ETHTOOL_GSET}; - e1000_ethtool_gset(adapter, &ecmd); - if(copy_to_user(addr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } - case ETHTOOL_SSET: { - struct ethtool_cmd ecmd; - if(copy_from_user(&ecmd, addr, sizeof(ecmd))) - return -EFAULT; - return e1000_ethtool_sset(adapter, &ecmd); - } - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo drvinfo = {ETHTOOL_GDRVINFO}; - e1000_ethtool_gdrvinfo(adapter, &drvinfo); - if(copy_to_user(addr, &drvinfo, sizeof(drvinfo))) - return -EFAULT; - return 0; - } - case ETHTOOL_GSTRINGS: { - struct ethtool_gstrings gstrings = { ETHTOOL_GSTRINGS }; - char *strings = NULL; - int err = 0; - - if(copy_from_user(&gstrings, addr, sizeof(gstrings))) - return -EFAULT; - switch(gstrings.string_set) { - case ETH_SS_TEST: - gstrings.len = E1000_TEST_LEN; - strings = kmalloc(E1000_TEST_LEN * ETH_GSTRING_LEN, - GFP_KERNEL); - if(!strings) - return -ENOMEM; - memcpy(strings, e1000_gstrings_test, E1000_TEST_LEN * - ETH_GSTRING_LEN); - break; - case ETH_SS_STATS: { - int i; - gstrings.len = E1000_STATS_LEN; - strings = kmalloc(E1000_STATS_LEN * ETH_GSTRING_LEN, - GFP_KERNEL); - if(!strings) - return -ENOMEM; - for(i=0; i < E1000_STATS_LEN; i++) { - memcpy(&strings[i * ETH_GSTRING_LEN], - e1000_gstrings_stats[i].stat_string, - ETH_GSTRING_LEN); - } - break; - } - default: - return -EOPNOTSUPP; - } - if(copy_to_user(addr, &gstrings, sizeof(gstrings))) - err = -EFAULT; - addr += offsetof(struct ethtool_gstrings, data); - if(!err && copy_to_user(addr, strings, - gstrings.len * ETH_GSTRING_LEN)) - err = -EFAULT; - - kfree(strings); - return err; - } - case ETHTOOL_GREGS: { - struct ethtool_regs regs = {ETHTOOL_GREGS}; - uint32_t regs_buff[E1000_REGS_LEN]; - - if(copy_from_user(®s, addr, sizeof(regs))) - return -EFAULT; - memset(regs_buff, 0, sizeof(regs_buff)); - if (regs.len > E1000_REGS_LEN) - regs.len = E1000_REGS_LEN; - e1000_ethtool_gregs(adapter, ®s, regs_buff); - if(copy_to_user(addr, ®s, sizeof(regs))) - return -EFAULT; - - addr += offsetof(struct ethtool_regs, data); - if(copy_to_user(addr, regs_buff, regs.len)) - return -EFAULT; - - return 0; - } - case ETHTOOL_NWAY_RST: { - if(netif_running(netdev)) { - e1000_down(adapter); - e1000_up(adapter); - } - return 0; - } - case ETHTOOL_PHYS_ID: { - struct ethtool_value id; - if(copy_from_user(&id, addr, sizeof(id))) - return -EFAULT; - return e1000_ethtool_led_blink(adapter, &id); - } - case ETHTOOL_GLINK: { - struct ethtool_value link = {ETHTOOL_GLINK}; - link.data = netif_carrier_ok(netdev); - if(copy_to_user(addr, &link, sizeof(link))) - return -EFAULT; - return 0; - } - case ETHTOOL_GWOL: { - struct ethtool_wolinfo wol = {ETHTOOL_GWOL}; - e1000_ethtool_gwol(adapter, &wol); - if(copy_to_user(addr, &wol, sizeof(wol)) != 0) - return -EFAULT; - return 0; - } - case ETHTOOL_SWOL: { - struct ethtool_wolinfo wol; - if(copy_from_user(&wol, addr, sizeof(wol)) != 0) - return -EFAULT; - return e1000_ethtool_swol(adapter, &wol); - } - case ETHTOOL_GEEPROM: { - struct ethtool_eeprom eeprom = {ETHTOOL_GEEPROM}; - struct e1000_hw *hw = &adapter->hw; - uint16_t *eeprom_buff; - void *ptr; - int err = 0; - - if(copy_from_user(&eeprom, addr, sizeof(eeprom))) - return -EFAULT; - - eeprom_buff = kmalloc(hw->eeprom.word_size * 2, GFP_KERNEL); - - if(!eeprom_buff) - return -ENOMEM; - - if((err = e1000_ethtool_geeprom(adapter, &eeprom, - eeprom_buff))) - goto err_geeprom_ioctl; - - if(copy_to_user(addr, &eeprom, sizeof(eeprom))) { - err = -EFAULT; - goto err_geeprom_ioctl; - } - - addr += offsetof(struct ethtool_eeprom, data); - ptr = ((void *)eeprom_buff) + (eeprom.offset & 1); - - if(copy_to_user(addr, ptr, eeprom.len)) - err = -EFAULT; - -err_geeprom_ioctl: - kfree(eeprom_buff); - return err; - } - case ETHTOOL_SEEPROM: { - struct ethtool_eeprom eeprom; - - if(copy_from_user(&eeprom, addr, sizeof(eeprom))) - return -EFAULT; - - addr += offsetof(struct ethtool_eeprom, data); - return e1000_ethtool_seeprom(adapter, &eeprom, addr); - } - case ETHTOOL_GRINGPARAM: { - struct ethtool_ringparam ering = {ETHTOOL_GRINGPARAM}; - e1000_ethtool_gring(adapter, &ering); - if(copy_to_user(addr, &ering, sizeof(ering))) - return -EFAULT; - return 0; - } - case ETHTOOL_SRINGPARAM: { - struct ethtool_ringparam ering; - if(copy_from_user(&ering, addr, sizeof(ering))) - return -EFAULT; - return e1000_ethtool_sring(adapter, &ering); - } - case ETHTOOL_GPAUSEPARAM: { - struct ethtool_pauseparam epause = {ETHTOOL_GPAUSEPARAM}; - e1000_ethtool_gpause(adapter, &epause); - if(copy_to_user(addr, &epause, sizeof(epause))) - return -EFAULT; - return 0; - } - case ETHTOOL_SPAUSEPARAM: { - struct ethtool_pauseparam epause; - if(copy_from_user(&epause, addr, sizeof(epause))) - return -EFAULT; - return e1000_ethtool_spause(adapter, &epause); - } - case ETHTOOL_GSTATS: { - struct { - struct ethtool_stats eth_stats; - uint64_t data[E1000_STATS_LEN]; - } stats = { {ETHTOOL_GSTATS, E1000_STATS_LEN} }; - int i; - - e1000_update_stats(adapter); - for(i = 0; i < E1000_STATS_LEN; i++) - stats.data[i] = (e1000_gstrings_stats[i].sizeof_stat == - sizeof(uint64_t)) ? - *(uint64_t *)((char *)adapter + - e1000_gstrings_stats[i].stat_offset) : - *(uint32_t *)((char *)adapter + - e1000_gstrings_stats[i].stat_offset); - if(copy_to_user(addr, &stats, sizeof(stats))) - return -EFAULT; - return 0; - } - case ETHTOOL_TEST: { - struct { - struct ethtool_test eth_test; - uint64_t data[E1000_TEST_LEN]; - } test = { {ETHTOOL_TEST} }; - int err; - - if(copy_from_user(&test.eth_test, addr, sizeof(test.eth_test))) - return -EFAULT; - - test.eth_test.len = E1000_TEST_LEN; - - if((err = e1000_ethtool_test(adapter, &test.eth_test, - test.data))) - return err; - - if(copy_to_user(addr, &test, sizeof(test)) != 0) - return -EFAULT; - return 0; - } - case ETHTOOL_GRXCSUM: { - struct ethtool_value edata = { ETHTOOL_GRXCSUM }; - - edata.data = adapter->rx_csum; - if (copy_to_user(addr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - case ETHTOOL_SRXCSUM: { - struct ethtool_value edata; - - if (copy_from_user(&edata, addr, sizeof(edata))) - return -EFAULT; - adapter->rx_csum = edata.data; - if(netif_running(netdev)) { - e1000_down(adapter); - e1000_up(adapter); - } else - e1000_reset(adapter); - return 0; - } - case ETHTOOL_GTXCSUM: { - struct ethtool_value edata = { ETHTOOL_GTXCSUM }; + struct e1000_adapter *adapter = netdev_priv(netdev); - edata.data = - (netdev->features & NETIF_F_HW_CSUM) != 0; - if (copy_to_user(addr, &edata, sizeof(edata))) - return -EFAULT; - return 0; + if(netif_running(netdev)) { + e1000_down(adapter); + e1000_up(adapter); } - case ETHTOOL_STXCSUM: { - struct ethtool_value edata; - - if (copy_from_user(&edata, addr, sizeof(edata))) - return -EFAULT; - - if(adapter->hw.mac_type < e1000_82543) { - if (edata.data != 0) - return -EINVAL; - return 0; - } + return 0; +} - if (edata.data) - netdev->features |= NETIF_F_HW_CSUM; - else - netdev->features &= ~NETIF_F_HW_CSUM; +static int +e1000_get_stats_count(struct net_device *dev) +{ + return E1000_STATS_LEN; +} - return 0; - } - case ETHTOOL_GSG: { - struct ethtool_value edata = { ETHTOOL_GSG }; +static void +e1000_get_ethtool_stats(struct net_device *netdev, + struct ethtool_stats *stats, u64 *data) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + int i; - edata.data = - (netdev->features & NETIF_F_SG) != 0; - if (copy_to_user(addr, &edata, sizeof(edata))) - return -EFAULT; - return 0; + e1000_update_stats(adapter); + for(i = 0; i < E1000_STATS_LEN; i++) { + char *p = (char *) adapter + e1000_gstrings_stats[i].stat_offset; + data[i] = (e1000_gstrings_stats[i].sizeof_stat == sizeof(uint64_t)) + ? *(uint64_t *)p : *(uint32_t *)p; } - case ETHTOOL_SSG: { - struct ethtool_value edata; - - if (copy_from_user(&edata, addr, sizeof(edata))) - return -EFAULT; - - if (edata.data) - netdev->features |= NETIF_F_SG; - else - netdev->features &= ~NETIF_F_SG; +} - return 0; - } -#ifdef NETIF_F_TSO - case ETHTOOL_GTSO: { - struct ethtool_value edata = { ETHTOOL_GTSO }; - - edata.data = (netdev->features & NETIF_F_TSO) != 0; - if (copy_to_user(addr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - case ETHTOOL_STSO: { - struct ethtool_value edata; +static void +e1000_get_strings(struct net_device *netdev, u32 string_set, u8 *data) +{ + int i; - if (copy_from_user(&edata, addr, sizeof(edata))) - return -EFAULT; + switch(string_set) { + case ETH_SS_TEST: + memcpy(data, e1000_gstrings_test, E1000_TEST_LEN * ETH_GSTRING_LEN); + break; - if ((adapter->hw.mac_type < e1000_82544) || - (adapter->hw.mac_type == e1000_82547)) { - if (edata.data != 0) - return -EINVAL; - return 0; + case ETH_SS_STATS: + for(i=0; i < E1000_STATS_LEN; i++) { + memcpy(data + i * ETH_GSTRING_LEN, + e1000_gstrings_stats[i].stat_string, + ETH_GSTRING_LEN); } - - if (edata.data) - netdev->features |= NETIF_F_TSO; - else - netdev->features &= ~NETIF_F_TSO; - - return 0; - } -#endif - default: - return -EOPNOTSUPP; + break; } } +struct ethtool_ops e1000_ethtool_ops = { + .get_settings = e1000_get_settings, + .set_settings = e1000_set_settings, + .get_drvinfo = e1000_get_drvinfo, + .get_regs_len = e1000_get_regs_len, + .get_regs = e1000_get_regs, + .get_wol = e1000_get_wol, + .set_wol = e1000_set_wol, + .nway_reset = e1000_nway_reset, + .get_link = ethtool_op_get_link, + .get_eeprom_len = e1000_get_eeprom_len, + .get_eeprom = e1000_get_eeprom, + .set_eeprom = e1000_set_eeprom, + .get_ringparam = e1000_get_ringparam, + .set_ringparam = e1000_set_ringparam, + .get_pauseparam = e1000_get_pauseparam, + .set_pauseparam = e1000_set_pauseparam, + .get_rx_csum = e1000_get_rx_csum, + .set_rx_csum = e1000_set_rx_csum, + .get_tx_csum = e1000_get_tx_csum, + .set_tx_csum = e1000_set_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, + .get_tso = ethtool_op_get_tso, + .set_tso = e1000_set_tso, + .self_test_count = e1000_diag_test_count, + .self_test = e1000_diag_test, + .get_strings = e1000_get_strings, + .phys_id = e1000_phys_id, + .get_stats_count = e1000_get_stats_count, + .get_ethtool_stats = e1000_get_ethtool_stats, +}; --- linux-2.6.6/drivers/net/e1000/e1000_main.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/net/e1000/e1000_main.c 2004-05-10 01:19:03.654183536 -0700 @@ -167,9 +167,9 @@ static boolean_t e1000_clean_rx_irq(stru static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter); #endif static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter); -static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); -static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, - int cmd); + +static int e1000_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); +extern struct ethtool_ops e1000_ethtool_ops; static void e1000_enter_82542_rst(struct e1000_adapter *adapter); static void e1000_leave_82542_rst(struct e1000_adapter *adapter); static inline void e1000_rx_checksum(struct e1000_adapter *adapter, @@ -206,7 +206,6 @@ struct notifier_block e1000_notifier_reb /* Exported from other modules */ extern void e1000_check_options(struct e1000_adapter *adapter); -extern int e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr); static struct pci_driver e1000_driver = { .name = e1000_driver_name, @@ -445,7 +444,8 @@ e1000_probe(struct pci_dev *pdev, netdev->set_multicast_list = &e1000_set_multi; netdev->set_mac_address = &e1000_set_mac; netdev->change_mtu = &e1000_change_mtu; - netdev->do_ioctl = &e1000_ioctl; + netdev->do_ioctl = &e1000_do_ioctl; + SET_ETHTOOL_OPS(netdev, &e1000_ethtool_ops); netdev->tx_timeout = &e1000_tx_timeout; netdev->watchdog_timeo = 5 * HZ; #ifdef CONFIG_E1000_NAPI @@ -2498,37 +2498,16 @@ e1000_smartspeed(struct e1000_adapter *a adapter->smartspeed = 0; } -/** - * e1000_ioctl - - * @netdev: - * @ifreq: - * @cmd: - **/ - -static int -e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - case SIOCGMIIREG: - case SIOCSMIIREG: - return e1000_mii_ioctl(netdev, ifr, cmd); - case SIOCETHTOOL: - return e1000_ethtool_ioctl(netdev, ifr); - default: - return -EOPNOTSUPP; - } -} /** - * e1000_mii_ioctl - + * e1000_do_ioctl - * @netdev: * @ifreq: * @cmd: **/ static int -e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) +e1000_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { struct e1000_adapter *adapter = netdev->priv; struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data; --- linux-2.6.6/drivers/net/epic100.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/net/epic100.c 2004-05-10 01:19:03.658182928 -0700 @@ -77,8 +77,6 @@ These may be modified when a driver module is loaded.*/ static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */ -/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -static int max_interrupt_work = 32; /* Used to pass the full-duplex flag, etc. */ #define MAX_UNITS 8 /* More are supported, limit only on options */ @@ -96,9 +94,9 @@ static int rx_copybreak; Making the Tx ring too large decreases the effectiveness of channel bonding and packet priority. There are no ill effects from too-large receive rings. */ -#define TX_RING_SIZE 16 -#define TX_QUEUE_LEN 10 /* Limit ring entries actually used. */ -#define RX_RING_SIZE 32 +#define TX_RING_SIZE 256 +#define TX_QUEUE_LEN 240 /* Limit ring entries actually used. */ +#define RX_RING_SIZE 256 #define TX_TOTAL_SIZE TX_RING_SIZE*sizeof(struct epic_tx_desc) #define RX_TOTAL_SIZE RX_RING_SIZE*sizeof(struct epic_rx_desc) @@ -155,12 +153,10 @@ MODULE_DESCRIPTION("SMC 83c170 EPIC seri MODULE_LICENSE("GPL"); MODULE_PARM(debug, "i"); -MODULE_PARM(max_interrupt_work, "i"); MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM_DESC(debug, "EPIC/100 debug level (0-5)"); -MODULE_PARM_DESC(max_interrupt_work, "EPIC/100 maximum events handled per interrupt"); MODULE_PARM_DESC(options, "EPIC/100: Bits 0-3: media type, bit 4: full duplex"); MODULE_PARM_DESC(rx_copybreak, "EPIC/100 copy breakpoint for copy-only-tiny-frames"); MODULE_PARM_DESC(full_duplex, "EPIC/100 full duplex setting(s) (1)"); @@ -292,6 +288,12 @@ enum CommandBits { StopTxDMA=0x20, StopRxDMA=0x40, RestartTx=0x80, }; +#define EpicRemoved 0xffffffff /* Chip failed or removed (CardBus) */ + +#define EpicNapiEvent (TxEmpty | TxDone | \ + RxDone | RxStarted | RxEarlyWarn | RxOverflow | RxFull) +#define EpicNormalEvent (0x0000ffff & ~EpicNapiEvent) + static u16 media2miictl[16] = { 0, 0x0C00, 0x0C00, 0x2000, 0x0100, 0x2100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -330,9 +332,12 @@ struct epic_private { /* Ring pointers. */ spinlock_t lock; /* Group with Tx control cache line. */ + spinlock_t napi_lock; + unsigned int reschedule_in_poll; unsigned int cur_tx, dirty_tx; unsigned int cur_rx, dirty_rx; + u32 irq_mask; unsigned int rx_buf_sz; /* Based on MTU+slack. */ struct pci_dev *pci_dev; /* PCI bus location. */ @@ -359,7 +364,8 @@ static void epic_timer(unsigned long dat static void epic_tx_timeout(struct net_device *dev); static void epic_init_ring(struct net_device *dev); static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev); -static int epic_rx(struct net_device *dev); +static int epic_rx(struct net_device *dev, int budget); +static int epic_poll(struct net_device *dev, int *budget); static irqreturn_t epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs); static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static struct ethtool_ops netdev_ethtool_ops; @@ -378,7 +384,7 @@ static int __devinit epic_init_one (stru int irq; struct net_device *dev; struct epic_private *ep; - int i, option = 0, duplex = 0; + int i, ret, option = 0, duplex = 0; void *ring_space; dma_addr_t ring_dma; @@ -392,29 +398,33 @@ static int __devinit epic_init_one (stru card_idx++; - i = pci_enable_device(pdev); - if (i) - return i; + ret = pci_enable_device(pdev); + if (ret) + goto out; irq = pdev->irq; if (pci_resource_len(pdev, 0) < pci_id_tbl[chip_idx].io_size) { printk (KERN_ERR "card %d: no PCI region space\n", card_idx); - return -ENODEV; + ret = -ENODEV; + goto err_out_disable; } pci_set_master(pdev); + ret = pci_request_regions(pdev, DRV_NAME); + if (ret < 0) + goto err_out_disable; + + ret = -ENOMEM; + dev = alloc_etherdev(sizeof (*ep)); if (!dev) { printk (KERN_ERR "card %d: no memory for eth device\n", card_idx); - return -ENOMEM; + goto err_out_free_res; } SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); - if (pci_request_regions(pdev, DRV_NAME)) - goto err_out_free_netdev; - #ifdef USE_IO_OPS ioaddr = pci_resource_start (pdev, 0); #else @@ -422,7 +432,7 @@ static int __devinit epic_init_one (stru ioaddr = (long) ioremap (ioaddr, pci_resource_len (pdev, 1)); if (!ioaddr) { printk (KERN_ERR DRV_NAME " %d: ioremap failed\n", card_idx); - goto err_out_free_res; + goto err_out_free_netdev; } #endif @@ -459,7 +469,9 @@ static int __devinit epic_init_one (stru dev->base_addr = ioaddr; dev->irq = irq; - spin_lock_init (&ep->lock); + spin_lock_init(&ep->lock); + spin_lock_init(&ep->napi_lock); + ep->reschedule_in_poll = 0; /* Bring the chip out of low-power mode. */ outl(0x4200, ioaddr + GENCTL); @@ -489,6 +501,9 @@ static int __devinit epic_init_one (stru ep->pci_dev = pdev; ep->chip_id = chip_idx; ep->chip_flags = pci_id_tbl[chip_idx].drv_flags; + ep->irq_mask = + (ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170) + | CntFull | TxUnderrun | EpicNapiEvent; /* Find the connected MII xcvrs. Doing this in open() would allow detecting external xcvrs later, but @@ -543,10 +558,12 @@ static int __devinit epic_init_one (stru dev->ethtool_ops = &netdev_ethtool_ops; dev->watchdog_timeo = TX_TIMEOUT; dev->tx_timeout = &epic_tx_timeout; + dev->poll = epic_poll; + dev->weight = 64; - i = register_netdev(dev); - if (i) - goto err_out_unmap_tx; + ret = register_netdev(dev); + if (ret < 0) + goto err_out_unmap_rx; printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ", dev->name, pci_id_tbl[chip_idx].name, ioaddr, dev->irq); @@ -554,19 +571,24 @@ static int __devinit epic_init_one (stru printk("%2.2x:", dev->dev_addr[i]); printk("%2.2x.\n", dev->dev_addr[i]); - return 0; +out: + return ret; +err_out_unmap_rx: + pci_free_consistent(pdev, RX_TOTAL_SIZE, ep->rx_ring, ep->rx_ring_dma); err_out_unmap_tx: pci_free_consistent(pdev, TX_TOTAL_SIZE, ep->tx_ring, ep->tx_ring_dma); err_out_iounmap: #ifndef USE_IO_OPS iounmap(ioaddr); -err_out_free_res: -#endif - pci_release_regions(pdev); err_out_free_netdev: +#endif free_netdev(dev); - return -ENODEV; +err_out_free_res: + pci_release_regions(pdev); +err_out_disable: + pci_disable_device(pdev); + goto out; } /* Serial EEPROM section. */ @@ -592,6 +614,38 @@ err_out_free_netdev: #define EE_READ256_CMD (6 << 8) #define EE_ERASE_CMD (7 << 6) +static void epic_disable_int(struct net_device *dev, struct epic_private *ep) +{ + long ioaddr = dev->base_addr; + + outl(0x00000000, ioaddr + INTMASK); +} + +static inline void __epic_pci_commit(long ioaddr) +{ +#ifndef USE_IO_OPS + inl(ioaddr + INTMASK); +#endif +} + +static inline void epic_napi_irq_off(struct net_device *dev, + struct epic_private *ep) +{ + long ioaddr = dev->base_addr; + + outl(ep->irq_mask & ~EpicNapiEvent, ioaddr + INTMASK); + __epic_pci_commit(ioaddr); +} + +static inline void epic_napi_irq_on(struct net_device *dev, + struct epic_private *ep) +{ + long ioaddr = dev->base_addr; + + /* No need to commit possible posted write */ + outl(ep->irq_mask | EpicNapiEvent, ioaddr + INTMASK); +} + static int __devinit read_eeprom(long ioaddr, int location) { int i; @@ -752,9 +806,8 @@ static int epic_open(struct net_device * /* Enable interrupts by setting the interrupt mask. */ outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170) - | CntFull | TxUnderrun | TxDone | TxEmpty - | RxError | RxOverflow | RxFull | RxHeader | RxDone, - ioaddr + INTMASK); + | CntFull | TxUnderrun + | RxError | RxHeader | EpicNapiEvent, ioaddr + INTMASK); if (debug > 1) printk(KERN_DEBUG "%s: epic_open() ioaddr %lx IRQ %d status %4.4x " @@ -795,7 +848,7 @@ static void epic_pause(struct net_device } /* Remove the packets on the Rx queue. */ - epic_rx(dev); + epic_rx(dev, RX_RING_SIZE); } static void epic_restart(struct net_device *dev) @@ -841,9 +894,9 @@ static void epic_restart(struct net_devi /* Enable interrupts by setting the interrupt mask. */ outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170) - | CntFull | TxUnderrun | TxDone | TxEmpty - | RxError | RxOverflow | RxFull | RxHeader | RxDone, - ioaddr + INTMASK); + | CntFull | TxUnderrun + | RxError | RxHeader | EpicNapiEvent, ioaddr + INTMASK); + printk(KERN_DEBUG "%s: epic_restart() done, cmd status %4.4x, ctl %4.4x" " interrupt %4.4x.\n", dev->name, (int)inl(ioaddr + COMMAND), (int)inl(ioaddr + GENCTL), @@ -929,7 +982,6 @@ static void epic_init_ring(struct net_de int i; ep->tx_full = 0; - ep->lock = (spinlock_t) SPIN_LOCK_UNLOCKED; ep->dirty_tx = ep->cur_tx = 0; ep->cur_rx = ep->dirty_rx = 0; ep->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32); @@ -1029,6 +1081,76 @@ static int epic_start_xmit(struct sk_buf return 0; } +static void epic_tx_error(struct net_device *dev, struct epic_private *ep, + int status) +{ + struct net_device_stats *stats = &ep->stats; + +#ifndef final_version + /* There was an major error, log it. */ + if (debug > 1) + printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", + dev->name, status); +#endif + stats->tx_errors++; + if (status & 0x1050) + stats->tx_aborted_errors++; + if (status & 0x0008) + stats->tx_carrier_errors++; + if (status & 0x0040) + stats->tx_window_errors++; + if (status & 0x0010) + stats->tx_fifo_errors++; +} + +static void epic_tx(struct net_device *dev, struct epic_private *ep) +{ + unsigned int dirty_tx, cur_tx; + + /* + * Note: if this lock becomes a problem we can narrow the locked + * region at the cost of occasionally grabbing the lock more times. + */ + cur_tx = ep->cur_tx; + for (dirty_tx = ep->dirty_tx; cur_tx - dirty_tx > 0; dirty_tx++) { + struct sk_buff *skb; + int entry = dirty_tx % TX_RING_SIZE; + int txstatus = le32_to_cpu(ep->tx_ring[entry].txstatus); + + if (txstatus & DescOwn) + break; /* It still hasn't been Txed */ + + if (likely(txstatus & 0x0001)) { + ep->stats.collisions += (txstatus >> 8) & 15; + ep->stats.tx_packets++; + ep->stats.tx_bytes += ep->tx_skbuff[entry]->len; + } else + epic_tx_error(dev, ep, txstatus); + + /* Free the original skb. */ + skb = ep->tx_skbuff[entry]; + pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr, + skb->len, PCI_DMA_TODEVICE); + dev_kfree_skb_irq(skb); + ep->tx_skbuff[entry] = 0; + } + +#ifndef final_version + if (cur_tx - dirty_tx > TX_RING_SIZE) { + printk(KERN_WARNING + "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n", + dev->name, dirty_tx, cur_tx, ep->tx_full); + dirty_tx += TX_RING_SIZE; + } +#endif + ep->dirty_tx = dirty_tx; + if (ep->tx_full && cur_tx - dirty_tx < TX_QUEUE_LEN - 4) { + /* The ring is no longer full, allow new TX entries. */ + ep->tx_full = 0; + netif_wake_queue(dev); + } +} + /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ static irqreturn_t epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs) @@ -1036,135 +1158,71 @@ static irqreturn_t epic_interrupt(int ir struct net_device *dev = dev_instance; struct epic_private *ep = dev->priv; long ioaddr = dev->base_addr; - int status, boguscnt = max_interrupt_work; unsigned int handled = 0; + int status; - do { - status = inl(ioaddr + INTSTAT); - /* Acknowledge all of the current interrupt sources ASAP. */ - outl(status & 0x00007fff, ioaddr + INTSTAT); - - if (debug > 4) - printk(KERN_DEBUG "%s: Interrupt, status=%#8.8x new " - "intstat=%#8.8x.\n", - dev->name, status, (int)inl(ioaddr + INTSTAT)); - - if ((status & IntrSummary) == 0) - break; - handled = 1; + status = inl(ioaddr + INTSTAT); + /* Acknowledge all of the current interrupt sources ASAP. */ + outl(status & EpicNormalEvent, ioaddr + INTSTAT); - if (status & (RxDone | RxStarted | RxEarlyWarn | RxOverflow)) - epic_rx(dev); + if (debug > 4) { + printk(KERN_DEBUG "%s: Interrupt, status=%#8.8x new " + "intstat=%#8.8x.\n", dev->name, status, + (int)inl(ioaddr + INTSTAT)); + } - if (status & (TxEmpty | TxDone)) { - unsigned int dirty_tx, cur_tx; + if ((status & IntrSummary) == 0) + goto out; - /* Note: if this lock becomes a problem we can narrow the locked - region at the cost of occasionally grabbing the lock more - times. */ - spin_lock(&ep->lock); - cur_tx = ep->cur_tx; - dirty_tx = ep->dirty_tx; - for (; cur_tx - dirty_tx > 0; dirty_tx++) { - struct sk_buff *skb; - int entry = dirty_tx % TX_RING_SIZE; - int txstatus = le32_to_cpu(ep->tx_ring[entry].txstatus); + handled = 1; - if (txstatus & DescOwn) - break; /* It still hasn't been Txed */ + if ((status & EpicNapiEvent) && !ep->reschedule_in_poll) { + spin_lock(&ep->napi_lock); + if (netif_rx_schedule_prep(dev)) { + epic_napi_irq_off(dev, ep); + __netif_rx_schedule(dev); + } else + ep->reschedule_in_poll++; + spin_unlock(&ep->napi_lock); + } + status &= ~EpicNapiEvent; - if ( ! (txstatus & 0x0001)) { - /* There was an major error, log it. */ -#ifndef final_version - if (debug > 1) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); -#endif - ep->stats.tx_errors++; - if (txstatus & 0x1050) ep->stats.tx_aborted_errors++; - if (txstatus & 0x0008) ep->stats.tx_carrier_errors++; - if (txstatus & 0x0040) ep->stats.tx_window_errors++; - if (txstatus & 0x0010) ep->stats.tx_fifo_errors++; - } else { - ep->stats.collisions += (txstatus >> 8) & 15; - ep->stats.tx_packets++; - ep->stats.tx_bytes += ep->tx_skbuff[entry]->len; - } - - /* Free the original skb. */ - skb = ep->tx_skbuff[entry]; - pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr, - skb->len, PCI_DMA_TODEVICE); - dev_kfree_skb_irq(skb); - ep->tx_skbuff[entry] = 0; - } + /* Check uncommon events all at once. */ + if (status & (CntFull | TxUnderrun | PCIBusErr170 | PCIBusErr175)) { + if (status == EpicRemoved) + goto out; -#ifndef final_version - if (cur_tx - dirty_tx > TX_RING_SIZE) { - printk(KERN_WARNING "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n", - dev->name, dirty_tx, cur_tx, ep->tx_full); - dirty_tx += TX_RING_SIZE; - } -#endif - ep->dirty_tx = dirty_tx; - if (ep->tx_full - && cur_tx - dirty_tx < TX_QUEUE_LEN - 4) { - /* The ring is no longer full, allow new TX entries. */ - ep->tx_full = 0; - spin_unlock(&ep->lock); - netif_wake_queue(dev); - } else - spin_unlock(&ep->lock); - } + /* Always update the error counts to avoid overhead later. */ + ep->stats.rx_missed_errors += inb(ioaddr + MPCNT); + ep->stats.rx_frame_errors += inb(ioaddr + ALICNT); + ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT); - /* Check uncommon events all at once. */ - if (status & (CntFull | TxUnderrun | RxOverflow | RxFull | - PCIBusErr170 | PCIBusErr175)) { - if (status == 0xffffffff) /* Chip failed or removed (CardBus). */ - break; - /* Always update the error counts to avoid overhead later. */ - ep->stats.rx_missed_errors += inb(ioaddr + MPCNT); - ep->stats.rx_frame_errors += inb(ioaddr + ALICNT); - ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT); - - if (status & TxUnderrun) { /* Tx FIFO underflow. */ - ep->stats.tx_fifo_errors++; - outl(ep->tx_threshold += 128, ioaddr + TxThresh); - /* Restart the transmit process. */ - outl(RestartTx, ioaddr + COMMAND); - } - if (status & RxOverflow) { /* Missed a Rx frame. */ - ep->stats.rx_errors++; - } - if (status & (RxOverflow | RxFull)) - outw(RxQueued, ioaddr + COMMAND); - if (status & PCIBusErr170) { - printk(KERN_ERR "%s: PCI Bus Error! EPIC status %4.4x.\n", - dev->name, status); - epic_pause(dev); - epic_restart(dev); - } - /* Clear all error sources. */ - outl(status & 0x7f18, ioaddr + INTSTAT); + if (status & TxUnderrun) { /* Tx FIFO underflow. */ + ep->stats.tx_fifo_errors++; + outl(ep->tx_threshold += 128, ioaddr + TxThresh); + /* Restart the transmit process. */ + outl(RestartTx, ioaddr + COMMAND); } - if (--boguscnt < 0) { - printk(KERN_ERR "%s: Too much work at interrupt, " - "IntrStatus=0x%8.8x.\n", - dev->name, status); - /* Clear all interrupt sources. */ - outl(0x0001ffff, ioaddr + INTSTAT); - break; + if (status & PCIBusErr170) { + printk(KERN_ERR "%s: PCI Bus Error! status %4.4x.\n", + dev->name, status); + epic_pause(dev); + epic_restart(dev); } - } while (1); + /* Clear all error sources. */ + outl(status & 0x7f18, ioaddr + INTSTAT); + } - if (debug > 3) - printk(KERN_DEBUG "%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, status); +out: + if (debug > 3) { + printk(KERN_DEBUG "%s: exit interrupt, intr_status=%#4.4x.\n", + dev->name, status); + } return IRQ_RETVAL(handled); } -static int epic_rx(struct net_device *dev) +static int epic_rx(struct net_device *dev, int budget) { struct epic_private *ep = dev->priv; int entry = ep->cur_rx % RX_RING_SIZE; @@ -1174,6 +1232,10 @@ static int epic_rx(struct net_device *de if (debug > 4) printk(KERN_DEBUG " In epic_rx(), entry %d %8.8x.\n", entry, ep->rx_ring[entry].rxstatus); + + if (rx_work_limit > budget) + rx_work_limit = budget; + /* If we own the next entry, it's a new packet. Send it up. */ while ((ep->rx_ring[entry].rxstatus & cpu_to_le32(DescOwn)) == 0) { int status = le32_to_cpu(ep->rx_ring[entry].rxstatus); @@ -1234,7 +1296,7 @@ static int epic_rx(struct net_device *de ep->rx_skbuff[entry] = NULL; } skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); + netif_receive_skb(skb); dev->last_rx = jiffies; ep->stats.rx_packets++; ep->stats.rx_bytes += pkt_len; @@ -1262,6 +1324,65 @@ static int epic_rx(struct net_device *de return work_done; } +static void epic_rx_err(struct net_device *dev, struct epic_private *ep) +{ + long ioaddr = dev->base_addr; + int status; + + status = inl(ioaddr + INTSTAT); + + if (status == EpicRemoved) + return; + if (status & RxOverflow) /* Missed a Rx frame. */ + ep->stats.rx_errors++; + if (status & (RxOverflow | RxFull)) + outw(RxQueued, ioaddr + COMMAND); +} + +static int epic_poll(struct net_device *dev, int *budget) +{ + struct epic_private *ep = dev->priv; + int work_done, orig_budget; + long ioaddr = dev->base_addr; + + orig_budget = (*budget > dev->quota) ? dev->quota : *budget; + +rx_action: + + epic_tx(dev, ep); + + work_done = epic_rx(dev, *budget); + + epic_rx_err(dev, ep); + + *budget -= work_done; + dev->quota -= work_done; + + if (netif_running(dev) && (work_done < orig_budget)) { + unsigned long flags; + int more; + + /* A bit baroque but it avoids a (space hungry) spin_unlock */ + + spin_lock_irqsave(&ep->napi_lock, flags); + + more = ep->reschedule_in_poll; + if (!more) { + __netif_rx_complete(dev); + outl(EpicNapiEvent, ioaddr + INTSTAT); + epic_napi_irq_on(dev, ep); + } else + ep->reschedule_in_poll--; + + spin_unlock_irqrestore(&ep->napi_lock, flags); + + if (more) + goto rx_action; + } + + return (work_done >= orig_budget); +} + static int epic_close(struct net_device *dev) { long ioaddr = dev->base_addr; @@ -1276,9 +1397,13 @@ static int epic_close(struct net_device dev->name, (int)inl(ioaddr + INTSTAT)); del_timer_sync(&ep->timer); - epic_pause(dev); + + epic_disable_int(dev, ep); + free_irq(dev->irq, dev); + epic_pause(dev); + /* Free all the skbuffs in the Rx queue. */ for (i = 0; i < RX_RING_SIZE; i++) { skb = ep->rx_skbuff[i]; @@ -1476,6 +1601,7 @@ static void __devexit epic_remove_one (s #endif pci_release_regions(pdev); free_netdev(dev); + pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); /* pci_power_off(pdev, -1); */ } --- linux-2.6.6/drivers/net/fealnx.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/net/fealnx.c 2004-05-10 01:19:37.195084544 -0700 @@ -84,6 +84,7 @@ static int full_duplex[MAX_UNITS] = { -1 #include #include #include +#include #include /* Processor type for cache alignment. */ #include @@ -233,15 +234,29 @@ enum intr_status_bits { RxErr = 0x00000002, /* receive error */ }; -/* Bits in the NetworkConfig register. */ +/* Bits in the NetworkConfig register, W for writing, R for reading */ +/* FIXME: some names are invented by me. Marked with (name?) */ +/* If you have docs and know bit names, please fix 'em */ enum rx_mode_bits { - RxModeMask = 0xe0, - PROM = 0x80, /* promiscuous mode */ - AB = 0x40, /* accept broadcast */ - AM = 0x20, /* accept mutlicast */ - ARP = 0x08, /* receive runt pkt */ - ALP = 0x04, /* receive long pkt */ - SEP = 0x02, /* receive error pkt */ + CR_W_ENH = 0x02000000, /* enhanced mode (name?) */ + CR_W_FD = 0x00100000, /* full duplex */ + CR_W_PS10 = 0x00080000, /* 10 mbit */ + CR_W_TXEN = 0x00040000, /* tx enable (name?) */ + CR_W_PS1000 = 0x00010000, /* 1000 mbit */ + /* CR_W_RXBURSTMASK= 0x00000e00, Im unsure about this */ + CR_W_RXMODEMASK = 0x000000e0, + CR_W_PROM = 0x00000080, /* promiscuous mode */ + CR_W_AB = 0x00000040, /* accept broadcast */ + CR_W_AM = 0x00000020, /* accept mutlicast */ + CR_W_ARP = 0x00000008, /* receive runt pkt */ + CR_W_ALP = 0x00000004, /* receive long pkt */ + CR_W_SEP = 0x00000002, /* receive error pkt */ + CR_W_RXEN = 0x00000001, /* rx enable (unicast?) (name?) */ + + CR_R_TXSTOP = 0x04000000, /* tx stopped (name?) */ + CR_R_FD = 0x00100000, /* full duplex detected */ + CR_R_PS10 = 0x00080000, /* 10 mbit detected */ + CR_R_RXSTOP = 0x00008000, /* rx stopped (name?) */ }; /* The Tulip Rx and Tx buffer descriptors. */ @@ -375,10 +390,7 @@ enum tx_desc_control_bits { #define LXT1000_Full 0x200 // 89/12/29 add, for phy specific status register, levelone phy, (end) -/* for 3-in-1 case */ -#define PS10 0x00080000 -#define FD 0x00100000 -#define PS1000 0x00010000 +/* for 3-in-1 case, BMCRSR register */ #define LinkIsUp2 0x00040000 /* for PHY */ @@ -400,6 +412,12 @@ struct netdev_private { /* Media monitoring timer. */ struct timer_list timer; + /* Reset timer */ + struct timer_list reset_timer; + int reset_timer_armed; + unsigned long crvalue_sv; + unsigned long imrvalue_sv; + /* Frequently used values: keep some adjacent for cache effect. */ int flags; struct pci_dev *pci_dev; @@ -435,49 +453,44 @@ static int netdev_open(struct net_device static void getlinktype(struct net_device *dev); static void getlinkstatus(struct net_device *dev); static void netdev_timer(unsigned long data); +static void reset_timer(unsigned long data); static void tx_timeout(struct net_device *dev); static void init_ring(struct net_device *dev); static int start_tx(struct sk_buff *skb, struct net_device *dev); static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *regs); static int netdev_rx(struct net_device *dev); static void set_rx_mode(struct net_device *dev); +static void __set_rx_mode(struct net_device *dev); static struct net_device_stats *get_stats(struct net_device *dev); static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static struct ethtool_ops netdev_ethtool_ops; static int netdev_close(struct net_device *dev); static void reset_rx_descriptors(struct net_device *dev); +static void reset_tx_descriptors(struct net_device *dev); -void stop_nic_tx(long ioaddr, long crvalue) +static void stop_nic_rx(long ioaddr, long crvalue) { - writel(crvalue & (~0x40000), ioaddr + TCRRCR); - - /* wait for tx stop */ - { - int i = 0, delay = 0x1000; - - while ((!(readl(ioaddr + TCRRCR) & 0x04000000)) && (i < delay)) { - ++i; - } + int delay = 0x1000; + writel(crvalue & ~(CR_W_RXEN), ioaddr + TCRRCR); + while (--delay) { + if ( (readl(ioaddr + TCRRCR) & CR_R_RXSTOP) == CR_R_RXSTOP) + break; } } -void stop_nic_rx(long ioaddr, long crvalue) +static void stop_nic_rxtx(long ioaddr, long crvalue) { - writel(crvalue & (~0x1), ioaddr + TCRRCR); - - /* wait for rx stop */ - { - int i = 0, delay = 0x1000; - - while ((!(readl(ioaddr + TCRRCR) & 0x00008000)) && (i < delay)) { - ++i; - } + int delay = 0x1000; + writel(crvalue & ~(CR_W_RXEN+CR_W_TXEN), ioaddr + TCRRCR); + while (--delay) { + if ( (readl(ioaddr + TCRRCR) & (CR_R_RXSTOP+CR_R_TXSTOP)) + == (CR_R_RXSTOP+CR_R_TXSTOP) ) + break; } } - static int __devinit fealnx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -495,7 +508,7 @@ static int __devinit fealnx_init_one(str #ifndef MODULE static int printed_version; if (!printed_version++) - printk (version); + printk(version); #endif card_idx++; @@ -622,7 +635,7 @@ static int __devinit fealnx_init_one(str np->phys[0] = 32; /* 89/6/23 add, (begin) */ /* get phy type */ - if (readl(dev->base_addr + PHYIDENTIFIER) == MysonPHYID) + if (readl(ioaddr + PHYIDENTIFIER) == MysonPHYID) np->PHYType = MysonPHY; else np->PHYType = OtherPHY; @@ -657,7 +670,7 @@ static int __devinit fealnx_init_one(str if (np->flags == HAS_MII_XCVR) mdio_write(dev, np->phys[0], MII_ADVERTISE, ADVERTISE_FULL); else - writel(ADVERTISE_FULL, dev->base_addr + ANARANLPAR); + writel(ADVERTISE_FULL, ioaddr + ANARANLPAR); np->mii.force_media = 1; } @@ -669,7 +682,7 @@ static int __devinit fealnx_init_one(str dev->set_multicast_list = &set_rx_mode; dev->do_ioctl = &mii_ioctl; dev->ethtool_ops = &netdev_ethtool_ops; - dev->tx_timeout = tx_timeout; + dev->tx_timeout = &tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; err = register_netdev(dev); @@ -699,6 +712,7 @@ err_out_res: return err; } + static void __devexit fealnx_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); @@ -721,42 +735,6 @@ static void __devexit fealnx_remove_one( printk(KERN_ERR "fealnx: remove for unknown device\n"); } -unsigned int m80x_read_tick(void) -/* function: Reads the Timer tick count register which decrements by 2 from */ -/* 65536 to 0 every 1/36.414 of a second. Each 2 decrements of the *//* count represents 838 nsec's. */ -/* input : none. */ -/* output : none. */ -{ - unsigned char tmp; - int value; - - writeb((char) 0x06, 0x43); // Command 8254 to latch T0's count - - // now read the count. - tmp = (unsigned char) readb(0x40); - value = ((int) tmp) << 8; - tmp = (unsigned char) readb(0x40); - value |= (((int) tmp) & 0xff); - return (value); -} - - -void m80x_delay(unsigned int interval) -/* function: to wait for a specified time. */ -/* input : interval ... the specified time. */ -/* output : none. */ -{ - unsigned int interval1, interval2, i = 0; - - interval1 = m80x_read_tick(); // get initial value - do { - interval2 = m80x_read_tick(); - if (interval1 < interval2) - interval1 = interval2; - ++i; - } while (((interval1 - interval2) < (ushort) interval) && (i < 65535)); -} - static ulong m80x_send_cmd_to_phy(long miiport, int opcode, int phyad, int regad) { @@ -796,7 +774,7 @@ static ulong m80x_send_cmd_to_phy(long m /* high MDC */ miir |= MASK_MIIR_MII_MDC; writel(miir, miiport); - m80x_delay(30); + udelay(30); /* next */ mask >>= 1; @@ -831,7 +809,7 @@ static int mdio_read(struct net_device * /* high MDC, and wait */ miir |= MASK_MIIR_MII_MDC; writel(miir, miiport); - m80x_delay((int) 30); + udelay(30); /* next */ mask >>= 1; @@ -873,8 +851,6 @@ static void mdio_write(struct net_device /* low MDC */ miir &= ~MASK_MIIR_MII_MDC; writel(miir, miiport); - - return; } @@ -882,12 +858,17 @@ static int netdev_open(struct net_device { struct netdev_private *np = dev->priv; long ioaddr = dev->base_addr; + int i; writel(0x00000001, ioaddr + BCR); /* Reset */ if (request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev)) return -EAGAIN; + for (i = 0; i < 3; i++) + writew(((unsigned short*)dev->dev_addr)[i], + ioaddr + PAR0 + i*2); + init_ring(dev); writel(np->rx_ring_dma, ioaddr + RXLBA); @@ -949,7 +930,7 @@ static int netdev_open(struct net_device np->imrvalue = TUNF | CNTOVF | RBU | TI | RI; if (np->pci_dev->device == 0x891) { np->bcrvalue |= 0x200; /* set PROG bit */ - np->crvalue |= 0x02000000; /* set enhanced bit */ + np->crvalue |= CR_W_ENH; /* set enhanced bit */ np->imrvalue |= ETI; } writel(np->bcrvalue, ioaddr + BCR); @@ -957,7 +938,7 @@ static int netdev_open(struct net_device if (dev->if_port == 0) dev->if_port = np->default_port; - writel(0, dev->base_addr + RXPDR); + writel(0, ioaddr + RXPDR); // 89/9/1 modify, // np->crvalue = 0x00e40001; /* tx store and forward, tx/rx enable */ np->crvalue |= 0x00e40001; /* tx store and forward, tx/rx enable */ @@ -965,7 +946,7 @@ static int netdev_open(struct net_device getlinkstatus(dev); if (np->linkok) getlinktype(dev); - set_rx_mode(dev); + __set_rx_mode(dev); netif_start_queue(dev); @@ -985,6 +966,11 @@ static int netdev_open(struct net_device /* timer handler */ add_timer(&np->timer); + init_timer(&np->reset_timer); + np->reset_timer.data = (unsigned long) dev; + np->reset_timer.function = &reset_timer; + np->reset_timer_armed = 0; + return 0; } @@ -1005,8 +991,7 @@ static void getlinkstatus(struct net_dev np->linkok = 1; return; } - // delay - m80x_delay(100); + udelay(100); } } else { for (i = 0; i < DelayTime; ++i) { @@ -1014,8 +999,7 @@ static void getlinkstatus(struct net_dev np->linkok = 1; return; } - // delay - m80x_delay(100); + udelay(100); } } } @@ -1026,11 +1010,11 @@ static void getlinktype(struct net_devic struct netdev_private *np = dev->priv; if (np->PHYType == MysonPHY) { /* 3-in-1 case */ - if (readl(dev->base_addr + TCRRCR) & FD) + if (readl(dev->base_addr + TCRRCR) & CR_R_FD) np->duplexmode = 2; /* full duplex */ else np->duplexmode = 1; /* half duplex */ - if (readl(dev->base_addr + TCRRCR) & PS10) + if (readl(dev->base_addr + TCRRCR) & CR_R_PS10) np->line_speed = 1; /* 10M */ else np->line_speed = 2; /* 100M */ @@ -1112,19 +1096,18 @@ static void getlinktype(struct net_devic else np->line_speed = 1; /* 10M */ } - // chage crvalue - // np->crvalue&=(~PS10)&(~FD); - np->crvalue &= (~PS10) & (~FD) & (~PS1000); + np->crvalue &= (~CR_W_PS10) & (~CR_W_FD) & (~CR_W_PS1000); if (np->line_speed == 1) - np->crvalue |= PS10; + np->crvalue |= CR_W_PS10; else if (np->line_speed == 3) - np->crvalue |= PS1000; + np->crvalue |= CR_W_PS1000; if (np->duplexmode == 2) - np->crvalue |= FD; + np->crvalue |= CR_W_FD; } } +/* Take lock before calling this */ static void allocate_rx_buffers(struct net_device *dev) { struct netdev_private *np = dev->priv; @@ -1134,15 +1117,17 @@ static void allocate_rx_buffers(struct n struct sk_buff *skb; skb = dev_alloc_skb(np->rx_buf_sz); - np->lack_rxbuf->skbuff = skb; - if (skb == NULL) break; /* Better luck next round. */ + while (np->lack_rxbuf->skbuff) + np->lack_rxbuf = np->lack_rxbuf->next_desc_logical; + skb->dev = dev; /* Mark as being used by this device. */ + np->lack_rxbuf->skbuff = skb; np->lack_rxbuf->buffer = pci_map_single(np->pci_dev, skb->tail, np->rx_buf_sz, PCI_DMA_FROMDEVICE); - np->lack_rxbuf = np->lack_rxbuf->next_desc_logical; + np->lack_rxbuf->status = RXOWN; ++np->really_rx_count; } } @@ -1153,22 +1138,23 @@ static void netdev_timer(unsigned long d struct net_device *dev = (struct net_device *) data; struct netdev_private *np = dev->priv; long ioaddr = dev->base_addr; - int next_tick = 10 * HZ; int old_crvalue = np->crvalue; unsigned int old_linkok = np->linkok; + unsigned long flags; if (debug) printk(KERN_DEBUG "%s: Media selection timer tick, status %8.8x " "config %8.8x.\n", dev->name, readl(ioaddr + ISR), readl(ioaddr + TCRRCR)); + spin_lock_irqsave(&np->lock, flags); + if (np->flags == HAS_MII_XCVR) { getlinkstatus(dev); if ((old_linkok == 0) && (np->linkok == 1)) { /* we need to detect the media type again */ getlinktype(dev); if (np->crvalue != old_crvalue) { - stop_nic_tx(ioaddr, np->crvalue); - stop_nic_rx(ioaddr, np->crvalue & (~0x40000)); + stop_nic_rxtx(ioaddr, np->crvalue); writel(np->crvalue, ioaddr + TCRRCR); } } @@ -1176,69 +1162,120 @@ static void netdev_timer(unsigned long d allocate_rx_buffers(dev); - np->timer.expires = RUN_AT(next_tick); + spin_unlock_irqrestore(&np->lock, flags); + + np->timer.expires = RUN_AT(10 * HZ); add_timer(&np->timer); } -static void tx_timeout(struct net_device *dev) +/* Take lock before calling */ +/* Reset chip and disable rx, tx and interrupts */ +static void reset_and_disable_rxtx(struct net_device *dev) { - struct netdev_private *np = dev->priv; long ioaddr = dev->base_addr; - int i; - - printk(KERN_WARNING "%s: Transmit timed out, status %8.8x," - " resetting...\n", dev->name, readl(ioaddr + ISR)); - - { - - printk(KERN_DEBUG " Rx ring %p: ", np->rx_ring); - for (i = 0; i < RX_RING_SIZE; i++) - printk(" %8.8x", (unsigned int) np->rx_ring[i].status); - printk("\n" KERN_DEBUG " Tx ring %p: ", np->tx_ring); - for (i = 0; i < TX_RING_SIZE; i++) - printk(" %4.4x", np->tx_ring[i].status); - printk("\n"); - } - - /* Reinit. Gross */ + int delay=51; /* Reset the chip's Tx and Rx processes. */ - stop_nic_tx(ioaddr, 0); - reset_rx_descriptors(dev); + stop_nic_rxtx(ioaddr, 0); /* Disable interrupts by clearing the interrupt mask. */ - writel(0x0000, ioaddr + IMR); + writel(0, ioaddr + IMR); /* Reset the chip to erase previous misconfiguration. */ writel(0x00000001, ioaddr + BCR); /* Ueimor: wait for 50 PCI cycles (and flush posted writes btw). - We surely wait too long (address+data phase). Who cares ? */ - for (i = 0; i < 50; i++) { + We surely wait too long (address+data phase). Who cares? */ + while (--delay) { readl(ioaddr + BCR); rmb(); } +} + + +/* Take lock before calling */ +/* Restore chip after reset */ +static void enable_rxtx(struct net_device *dev) +{ + struct netdev_private *np = dev->priv; + long ioaddr = dev->base_addr; + + reset_rx_descriptors(dev); - writel((np->cur_tx - np->tx_ring)*sizeof(struct fealnx_desc) + - np->tx_ring_dma, ioaddr + TXLBA); - writel((np->cur_rx - np->rx_ring)*sizeof(struct fealnx_desc) + - np->rx_ring_dma, ioaddr + RXLBA); + writel(np->tx_ring_dma + ((char*)np->cur_tx - (char*)np->tx_ring), + ioaddr + TXLBA); + writel(np->rx_ring_dma + ((char*)np->cur_rx - (char*)np->rx_ring), + ioaddr + RXLBA); writel(np->bcrvalue, ioaddr + BCR); - writel(0, dev->base_addr + RXPDR); - set_rx_mode(dev); + writel(0, ioaddr + RXPDR); + __set_rx_mode(dev); /* changes np->crvalue, writes it into TCRRCR */ + /* Clear and Enable interrupts by setting the interrupt mask. */ writel(FBE | TUNF | CNTOVF | RBU | TI | RI, ioaddr + ISR); writel(np->imrvalue, ioaddr + IMR); - writel(0, dev->base_addr + TXPDR); + writel(0, ioaddr + TXPDR); +} + + +static void reset_timer(unsigned long data) +{ + struct net_device *dev = (struct net_device *) data; + struct netdev_private *np = dev->priv; + unsigned long flags; + + printk(KERN_WARNING "%s: resetting tx and rx machinery\n", dev->name); + + spin_lock_irqsave(&np->lock, flags); + np->crvalue = np->crvalue_sv; + np->imrvalue = np->imrvalue_sv; + + reset_and_disable_rxtx(dev); + /* works for me without this: + reset_tx_descriptors(dev); */ + enable_rxtx(dev); + netif_start_queue(dev); /* FIXME: or netif_wake_queue(dev); ? */ + + np->reset_timer_armed = 0; + + spin_unlock_irqrestore(&np->lock, flags); +} + + +static void tx_timeout(struct net_device *dev) +{ + struct netdev_private *np = dev->priv; + long ioaddr = dev->base_addr; + unsigned long flags; + int i; + + printk(KERN_WARNING "%s: Transmit timed out, status %8.8x," + " resetting...\n", dev->name, readl(ioaddr + ISR)); + + { + printk(KERN_DEBUG " Rx ring %p: ", np->rx_ring); + for (i = 0; i < RX_RING_SIZE; i++) + printk(" %8.8x", (unsigned int) np->rx_ring[i].status); + printk("\n" KERN_DEBUG " Tx ring %p: ", np->tx_ring); + for (i = 0; i < TX_RING_SIZE; i++) + printk(" %4.4x", np->tx_ring[i].status); + printk("\n"); + } + + spin_lock_irqsave(&np->lock, flags); + + reset_and_disable_rxtx(dev); + reset_tx_descriptors(dev); + enable_rxtx(dev); + + spin_unlock_irqrestore(&np->lock, flags); dev->trans_start = jiffies; np->stats.tx_errors++; - - return; + netif_wake_queue(dev); /* or .._start_.. ?? */ } @@ -1251,7 +1288,7 @@ static void init_ring(struct net_device /* initialize rx variables */ np->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32); np->cur_rx = &np->rx_ring[0]; - np->lack_rxbuf = NULL; + np->lack_rxbuf = np->rx_ring; np->really_rx_count = 0; /* initial rx descriptors. */ @@ -1294,6 +1331,7 @@ static void init_ring(struct net_device for (i = 0; i < TX_RING_SIZE; i++) { np->tx_ring[i].status = 0; + /* do we need np->tx_ring[i].control = XXX; ?? */ np->tx_ring[i].next_desc = np->tx_ring_dma + (i + 1)*sizeof(struct fealnx_desc); np->tx_ring[i].next_desc_logical = &np->tx_ring[i + 1]; @@ -1341,7 +1379,7 @@ static int start_tx(struct sk_buff *skb, np->cur_tx_copy->control |= (BPT << TBSShift); /* buffer size */ /* for the last descriptor */ - next = (struct fealnx *) np->cur_tx_copy.next_desc_logical; + next = np->cur_tx_copy->next_desc_logical; next->skbuff = skb; next->control = TXIC | TXLD | CRCEnable | PADEnable; next->control |= (skb->len << PKTSShift); /* pkt size */ @@ -1383,35 +1421,59 @@ static int start_tx(struct sk_buff *skb, } -void free_one_rx_descriptor(struct netdev_private *np) +/* Take lock before calling */ +/* Chip probably hosed tx ring. Clean up. */ +static void reset_tx_descriptors(struct net_device *dev) { - if (np->really_rx_count == RX_RING_SIZE) - np->cur_rx->status = RXOWN; - else { - np->lack_rxbuf->skbuff = np->cur_rx->skbuff; - np->lack_rxbuf->buffer = np->cur_rx->buffer; - np->lack_rxbuf->status = RXOWN; - ++np->really_rx_count; - np->lack_rxbuf = np->lack_rxbuf->next_desc_logical; + struct netdev_private *np = dev->priv; + struct fealnx_desc *cur; + int i; + + /* initialize tx variables */ + np->cur_tx = &np->tx_ring[0]; + np->cur_tx_copy = &np->tx_ring[0]; + np->really_tx_count = 0; + np->free_tx_count = TX_RING_SIZE; + + for (i = 0; i < TX_RING_SIZE; i++) { + cur = &np->tx_ring[i]; + if (cur->skbuff) { + pci_unmap_single(np->pci_dev, cur->buffer, + cur->skbuff->len, PCI_DMA_TODEVICE); + dev_kfree_skb(cur->skbuff); + /* or dev_kfree_skb_irq(cur->skbuff); ? */ + cur->skbuff = NULL; + } + cur->status = 0; + cur->control = 0; /* needed? */ + /* probably not needed. We do it for purely paranoid reasons */ + cur->next_desc = np->tx_ring_dma + + (i + 1)*sizeof(struct fealnx_desc); + cur->next_desc_logical = &np->tx_ring[i + 1]; } - np->cur_rx = np->cur_rx->next_desc_logical; + /* for the last tx descriptor */ + np->tx_ring[TX_RING_SIZE - 1].next_desc = np->tx_ring_dma; + np->tx_ring[TX_RING_SIZE - 1].next_desc_logical = &np->tx_ring[0]; } -void reset_rx_descriptors(struct net_device *dev) +/* Take lock and stop rx before calling this */ +static void reset_rx_descriptors(struct net_device *dev) { struct netdev_private *np = dev->priv; - - stop_nic_rx(dev->base_addr, np->crvalue); - - while (!(np->cur_rx->status & RXOWN)) - free_one_rx_descriptor(np); + struct fealnx_desc *cur = np->cur_rx; + int i; allocate_rx_buffers(dev); - writel(np->rx_ring_dma + (np->cur_rx - np->rx_ring), + for (i = 0; i < RX_RING_SIZE; i++) { + if (cur->skbuff) + cur->status = RXOWN; + cur = cur->next_desc_logical; + } + + writel(np->rx_ring_dma + ((char*)np->cur_rx - (char*)np->rx_ring), dev->base_addr + RXLBA); - writel(np->crvalue, dev->base_addr + TCRRCR); } @@ -1421,16 +1483,14 @@ static irqreturn_t intr_handler(int irq, { struct net_device *dev = (struct net_device *) dev_instance; struct netdev_private *np = dev->priv; - long ioaddr, boguscnt = max_interrupt_work; + long ioaddr = dev->base_addr; + long boguscnt = max_interrupt_work; unsigned int num_tx = 0; int handled = 0; spin_lock(&np->lock); - writel(0, dev->base_addr + IMR); - - ioaddr = dev->base_addr; - np = dev->priv; + writel(0, ioaddr + IMR); do { u32 intr_status = readl(ioaddr + ISR); @@ -1471,8 +1531,11 @@ static irqreturn_t intr_handler(int irq, if (intr_status & (RI | RBU)) { if (intr_status & RI) netdev_rx(dev); - else + else { + stop_nic_rx(ioaddr, np->crvalue); reset_rx_descriptors(dev); + writel(np->crvalue, ioaddr + TCRRCR); + } } while (np->really_tx_count) { @@ -1490,7 +1553,7 @@ static irqreturn_t intr_handler(int irq, if (tx_status & TXOWN) break; - if (!(np->crvalue & 0x02000000)) { + if (!(np->crvalue & CR_W_ENH)) { if (tx_status & (CSL | LC | EC | UDF | HF)) { np->stats.tx_errors++; if (tx_status & EC) @@ -1539,7 +1602,7 @@ static irqreturn_t intr_handler(int irq, netif_wake_queue(dev); /* read transmit status for enhanced mode only */ - if (np->crvalue & 0x02000000) { + if (np->crvalue & CR_W_ENH) { long data; data = readl(ioaddr + TSR); @@ -1552,6 +1615,20 @@ static irqreturn_t intr_handler(int irq, if (--boguscnt < 0) { printk(KERN_WARNING "%s: Too much work at interrupt, " "status=0x%4.4x.\n", dev->name, intr_status); + if (!np->reset_timer_armed) { + np->reset_timer_armed = 1; + np->reset_timer.expires = RUN_AT(HZ/2); + add_timer(&np->reset_timer); + stop_nic_rxtx(ioaddr, 0); + netif_stop_queue(dev); + /* or netif_tx_disable(dev); ?? */ + /* Prevent other paths from enabling tx,rx,intrs */ + np->crvalue_sv = np->crvalue; + np->imrvalue_sv = np->imrvalue; + np->crvalue &= ~(CR_W_TXEN | CR_W_RXEN); /* or simply = 0? */ + np->imrvalue = 0; + } + break; } } while (1); @@ -1580,9 +1657,10 @@ static irqreturn_t intr_handler(int irq, static int netdev_rx(struct net_device *dev) { struct netdev_private *np = dev->priv; + long ioaddr = dev->base_addr; /* If EOP is set on the next entry, it's a new packet. Send it up. */ - while (!(np->cur_rx->status & RXOWN)) { + while (!(np->cur_rx->status & RXOWN) && np->cur_rx->skbuff) { s32 rx_status = np->cur_rx->status; if (np->really_rx_count == 0) @@ -1634,11 +1712,20 @@ static int netdev_rx(struct net_device * np->stats.rx_length_errors++; /* free all rx descriptors related this long pkt */ - for (i = 0; i < desno; ++i) - free_one_rx_descriptor(np); + for (i = 0; i < desno; ++i) { + if (!np->cur_rx->skbuff) { + printk(KERN_DEBUG + "%s: I'm scared\n", dev->name); + break; + } + np->cur_rx->status = RXOWN; + np->cur_rx = np->cur_rx->next_desc_logical; + } continue; - } else { /* something error, need to reset this chip */ + } else { /* rx error, need to reset this chip */ + stop_nic_rx(ioaddr, np->crvalue); reset_rx_descriptors(dev); + writel(np->crvalue, ioaddr + TCRRCR); } break; /* exit the while loop */ } @@ -1685,8 +1772,6 @@ static int netdev_rx(struct net_device * PCI_DMA_FROMDEVICE); skb_put(skb = np->cur_rx->skbuff, pkt_len); np->cur_rx->skbuff = NULL; - if (np->really_rx_count == RX_RING_SIZE) - np->lack_rxbuf = np->cur_rx; --np->really_rx_count; } skb->protocol = eth_type_trans(skb, dev); @@ -1696,24 +1781,7 @@ static int netdev_rx(struct net_device * np->stats.rx_bytes += pkt_len; } - if (np->cur_rx->skbuff == NULL) { - struct sk_buff *skb; - - skb = dev_alloc_skb(np->rx_buf_sz); - - if (skb != NULL) { - skb->dev = dev; /* Mark as being used by this device. */ - np->cur_rx->buffer = pci_map_single(np->pci_dev, - skb->tail, - np->rx_buf_sz, - PCI_DMA_FROMDEVICE); - np->cur_rx->skbuff = skb; - ++np->really_rx_count; - } - } - - if (np->cur_rx->skbuff != NULL) - free_one_rx_descriptor(np); + np->cur_rx = np->cur_rx->next_desc_logical; } /* end of while loop */ /* allocate skb for rx buffers */ @@ -1737,8 +1805,21 @@ static struct net_device_stats *get_stat return &np->stats; } + +/* for dev->set_multicast_list */ static void set_rx_mode(struct net_device *dev) { + spinlock_t *lp = &((struct netdev_private *)dev->priv)->lock; + unsigned long flags; + spin_lock_irqsave(lp, flags); + __set_rx_mode(dev); + spin_unlock_irqrestore(lp, flags); +} + + +/* Take lock before calling */ +static void __set_rx_mode(struct net_device *dev) +{ struct netdev_private *np = dev->priv; long ioaddr = dev->base_addr; u32 mc_filter[2]; /* Multicast hash filter */ @@ -1748,12 +1829,12 @@ static void set_rx_mode(struct net_devic /* Unconditionally log net taps. */ printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name); memset(mc_filter, 0xff, sizeof(mc_filter)); - rx_mode = PROM | AB | AM; + rx_mode = CR_W_PROM | CR_W_AB | CR_W_AM; } else if ((dev->mc_count > multicast_filter_limit) || (dev->flags & IFF_ALLMULTI)) { /* Too many to match, or accept all multicasts. */ memset(mc_filter, 0xff, sizeof(mc_filter)); - rx_mode = AB | AM; + rx_mode = CR_W_AB | CR_W_AM; } else { struct dev_mc_list *mclist; int i; @@ -1765,26 +1846,25 @@ static void set_rx_mode(struct net_devic bit = (ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26) ^ 0x3F; mc_filter[bit >> 5] |= (1 << bit); } - rx_mode = AB | AM; + rx_mode = CR_W_AB | CR_W_AM; } - stop_nic_tx(ioaddr, np->crvalue); - stop_nic_rx(ioaddr, np->crvalue & (~0x40000)); + stop_nic_rxtx(ioaddr, np->crvalue); writel(mc_filter[0], ioaddr + MAR0); writel(mc_filter[1], ioaddr + MAR1); - np->crvalue &= ~RxModeMask; + np->crvalue &= ~CR_W_RXMODEMASK; np->crvalue |= rx_mode; writel(np->crvalue, ioaddr + TCRRCR); } -static void netdev_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *info) +static void netdev_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { struct netdev_private *np = dev->priv; - strcpy (info->driver, DRV_NAME); - strcpy (info->version, DRV_VERSION); - strcpy (info->bus_info, pci_name(np->pci_dev)); + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->bus_info, pci_name(np->pci_dev)); } static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) @@ -1874,10 +1954,10 @@ static int netdev_close(struct net_devic writel(0x0000, ioaddr + IMR); /* Stop the chip's Tx and Rx processes. */ - stop_nic_tx(ioaddr, 0); - stop_nic_rx(ioaddr, 0); + stop_nic_rxtx(ioaddr, 0); del_timer_sync(&np->timer); + del_timer_sync(&np->reset_timer); free_irq(dev->irq, dev); @@ -1928,7 +2008,7 @@ static int __init fealnx_init(void) { /* when a module, this is printed whether or not devices are found in probe */ #ifdef MODULE - printk (version); + printk(version); #endif return pci_module_init(&fealnx_driver); --- linux-2.6.6/drivers/net/hamradio/dmascc.c 2004-02-17 20:48:43.000000000 -0800 +++ 25/drivers/net/hamradio/dmascc.c 2004-05-10 01:20:01.640368296 -0700 @@ -48,21 +48,6 @@ #include "z8530.h" -/* Linux 2.2 and 2.3 compatibility */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,14) -#define net_device device -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43) -#define netif_start_queue(dev) { dev->tbusy = 0; } -#define netif_stop_queue(dev) { dev->tbusy = 1; } -#define netif_wake_queue(dev) { dev->tbusy = 0; mark_bh(NET_BH); } -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,47) -#define netif_running(dev) (dev->flags & IFF_UP) -#endif - - /* Number of buffers per channel */ #define NUM_TX_BUF 2 /* NUM_TX_BUF >= 1 (min. 2 recommended) */ @@ -210,9 +195,6 @@ struct scc_hardware { }; struct scc_priv { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) - char name[IFNAMSIZ]; -#endif int type; int chip; struct net_device *dev; --- linux-2.6.6/drivers/net/irda/irda-usb.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/net/irda/irda-usb.c 2004-05-10 01:19:05.762862968 -0700 @@ -1421,7 +1421,7 @@ static int irda_usb_probe(struct usb_int } /* Find our endpoints */ - interface = &intf->altsetting[0]; + interface = intf->cur_altsetting; if(!irda_usb_parse_endpoints(self, interface->endpoint, interface->desc.bNumEndpoints)) { ERROR("%s(), Bogus endpoints...\n", __FUNCTION__); --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/drivers/net/kgdb_eth.c 2004-05-10 01:19:07.213642416 -0700 @@ -0,0 +1,132 @@ +/* + * Network interface GDB stub + * + * Written by San Mehat (nettwerk@biodome.org) + * Based upon 'gdbserial' by David Grothe (dave@gcom.com) + * and Scott Foehner (sfoehner@engr.sgi.com) + * + * Twiddled for 2.6 by Robert Walsh + * and wangdi . + * + * Refactored for netpoll API by Matt Mackall + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define IN_BUF_SIZE 512 /* power of 2, please */ +#define OUT_BUF_SIZE 256 + +static char in_buf[IN_BUF_SIZE], out_buf[OUT_BUF_SIZE]; +static int in_head, in_tail, out_count; +static atomic_t in_count; +int kgdboe = 0; /* Default to tty mode */ + +extern void set_debug_traps(void); +extern void breakpoint(void); +static void rx_hook(struct netpoll *np, int port, char *msg, int len); + +static struct netpoll np = { + .name = "kgdboe", + .dev_name = "eth0", + .rx_hook = rx_hook, + .local_port = 6443, + .remote_port = 6442, + .remote_mac = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, +}; +static int configured; + +int eth_getDebugChar(void) +{ + int chr; + + while (atomic_read(&in_count) == 0) + netpoll_poll(&np); + + chr = in_buf[in_tail++]; + in_tail &= (IN_BUF_SIZE - 1); + atomic_dec(&in_count); + return chr; +} + +void eth_flushDebugChar(void) +{ + if(out_count && np.dev) { + netpoll_send_udp(&np, out_buf, out_count); + out_count = 0; + } +} + +void eth_putDebugChar(int chr) +{ + out_buf[out_count++] = chr; + if(out_count == OUT_BUF_SIZE) + eth_flushDebugChar(); +} + +static void rx_hook(struct netpoll *np, int port, char *msg, int len) +{ + int i; + + np->remote_port = port; + + /* Is this gdb trying to attach? */ + if (!netpoll_trap() && len == 8 && !strncmp(msg, "$Hc-1#09", 8)) + kgdb_schedule_breakpoint(); + + for (i = 0; i < len; i++) { + if (msg[i] == 3) + kgdb_schedule_breakpoint(); + + if (atomic_read(&in_count) >= IN_BUF_SIZE) { + /* buffer overflow, clear it */ + in_head = in_tail = 0; + atomic_set(&in_count, 0); + break; + } + in_buf[in_head++] = msg[i]; + in_head &= (IN_BUF_SIZE - 1); + atomic_inc(&in_count); + } +} + +static int option_setup(char *opt) +{ + configured = !netpoll_parse_options(&np, opt); + return 0; +} +__setup("kgdboe=", option_setup); + +static int init_kgdboe(void) +{ +#ifdef CONFIG_SMP + if (num_online_cpus() > CONFIG_NO_KGDB_CPUS) { + printk("kgdb: too manu cpus. Cannot enable debugger with more than %d cpus\n", CONFIG_NO_KGDB_CPUS); + return -1; + } +#endif + + set_debug_traps(); + + if(!configured || netpoll_setup(&np)) + return 1; + + kgdboe = 1; + printk(KERN_INFO "kgdb: debugging over ethernet enabled\n"); + + return 0; +} + +module_init(init_kgdboe); --- linux-2.6.6/drivers/net/lance.c 2004-02-17 20:48:43.000000000 -0800 +++ 25/drivers/net/lance.c 2004-05-10 01:19:50.600046680 -0700 @@ -37,6 +37,9 @@ Get rid of check_region, check kmalloc return in lance_probe1 Arnaldo Carvalho de Melo - 11/01/2001 + + Reworked detection, added support for Racal InterLan EtherBlaster cards + Vesselin Kostadinov - 22/4/2004 */ static const char version[] = "lance.c:v1.15ac 1999/11/13 dplatt@3do.com, becker@cesdis.gsfc.nasa.gov\n"; @@ -62,6 +65,26 @@ static unsigned int lance_portlist[] __i static int lance_probe1(struct net_device *dev, int ioaddr, int irq, int options); static int __init do_lance_probe(struct net_device *dev); + +static struct card { + char id_offset14; + char id_offset15; +} cards[] = { + { //"normal" + .id_offset14 = 0x57, + .id_offset15 = 0x57, + }, + { //NI6510EB + .id_offset14 = 0x52, + .id_offset15 = 0x44, + }, + { //Racal InterLan EtherBlaster + .id_offset14 = 0x52, + .id_offset15 = 0x49, + }, +}; +#define NUM_CARDS 3 + #ifdef LANCE_DEBUG static int lance_debug = LANCE_DEBUG; #else @@ -380,13 +403,20 @@ static int __init do_lance_probe(struct "lance-probe"); if (r) { - /* Detect "normal" 0x57 0x57 and the NI6510EB 0x52 0x44 - signatures w/ minimal I/O reads */ - char offset15, offset14 = inb(ioaddr + 14); - - if ((offset14 == 0x52 || offset14 == 0x57) && - ((offset15 = inb(ioaddr + 15)) == 0x57 || - offset15 == 0x44)) { + /* Detect the card with minimal I/O reads */ + char offset14 = inb(ioaddr + 14); + int card; + for (card = 0; card < NUM_CARDS; ++card) + if (cards[card].id_offset14 == offset14) + break; + if (card < NUM_CARDS) {/*yes, the first byte matches*/ + char offset15 = inb(ioaddr + 15); + for (card = 0; card < NUM_CARDS; ++card) + if ((cards[card].id_offset14 == offset14) && + (cards[card].id_offset15 == offset15)) + break; + } + if (card < NUM_CARDS) { /*Signature OK*/ result = lance_probe1(dev, ioaddr, 0, 0); if (!result) { struct lance_private *lp = dev->priv; --- linux-2.6.6/drivers/net/lasi_82596.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/net/lasi_82596.c 2004-05-10 01:19:35.626323032 -0700 @@ -87,7 +87,6 @@ #include #include #include -#include #include #include #include --- linux-2.6.6/drivers/net/macsonic.c 2004-02-17 20:48:43.000000000 -0800 +++ 25/drivers/net/macsonic.c 2004-05-10 01:19:35.626323032 -0700 @@ -53,7 +53,6 @@ #include #include #include -#include #define SREGS_PAD(n) u16 n; --- linux-2.6.6/drivers/net/Makefile 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/net/Makefile 2004-05-10 01:19:07.214642264 -0700 @@ -189,4 +189,6 @@ obj-$(CONFIG_NET_TULIP) += tulip/ obj-$(CONFIG_HAMRADIO) += hamradio/ obj-$(CONFIG_IRDA) += irda/ +# Must come after all NICs that might use them obj-$(CONFIG_NETCONSOLE) += netconsole.o +obj-$(CONFIG_KGDB) += kgdb_eth.o --- linux-2.6.6/drivers/net/pcnet32.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/net/pcnet32.c 2004-05-10 01:19:03.667181560 -0700 @@ -132,6 +132,8 @@ static const char pcnet32_gstrings_test[ }; #define PCNET32_TEST_LEN (sizeof(pcnet32_gstrings_test) / ETH_GSTRING_LEN) +#define PCNET32_NUM_REGS 146 + #define MAX_UNITS 8 /* More are supported, limit only on options */ static int options[MAX_UNITS]; static int full_duplex[MAX_UNITS]; @@ -234,7 +236,9 @@ static int full_duplex[MAX_UNITS]; * Jim Lewis added ethernet loopback test. * Thomas Munck Steenholdt non-mii ioctl corrections. * v1.29 6 Apr 2004 Jim Lewis added physical - * identification code (blink led's). + * identification code (blink led's) and register dump. + * Don Fry added timer for 971/972 so skbufs don't remain on tx ring + * forever. */ @@ -372,6 +376,9 @@ static void pcnet32_ethtool_test(struct static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1); static int pcnet32_phys_id(struct net_device *dev, u32 data); static void pcnet32_led_blink_callback(struct net_device *dev); +static int pcnet32_get_regs_len(struct net_device *dev); +static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs, + void *ptr); enum pci_flags_bit { PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4, @@ -492,9 +499,9 @@ static struct pcnet32_access pcnet32_dwi #ifdef CONFIG_NET_POLL_CONTROLLER static void pcnet32_poll_controller(struct net_device *dev) { - disable_irq(dev->irq); - pcnet32_interrupt(0, dev, NULL); - enable_irq(dev->irq); + disable_irq(dev->irq); + pcnet32_interrupt(0, dev, NULL); + enable_irq(dev->irq); } #endif @@ -681,7 +688,7 @@ static int pcnet32_loopback_test(struct for (i=0; i<6; i++) *packet++ = dev->dev_addr[i]; for (i=0; i<6; i++) - *packet++ = dev->dev_addr[i]; + *packet++ = dev->dev_addr[i]; /* type */ *packet++ = 0x08; *packet++ = 0x06; @@ -837,6 +844,72 @@ static int pcnet32_phys_id(struct net_de return 0; } +int pcnet32_get_regs_len(struct net_device *dev) +{ + return(PCNET32_NUM_REGS * sizeof(u16)); +} + +void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs, + void *ptr) +{ + int i, csr0; + u16 *buff = ptr; + struct pcnet32_private *lp = dev->priv; + struct pcnet32_access *a = &lp->a; + ulong ioaddr = dev->base_addr; + int ticks; + unsigned long flags; + + spin_lock_irqsave(&lp->lock, flags); + + csr0 = a->read_csr(ioaddr, 0); + if (!(csr0 & 0x0004)) { /* If not stopped */ + /* set SUSPEND (SPND) - CSR5 bit 0 */ + a->write_csr(ioaddr, 5, 0x0001); + + /* poll waiting for bit to be set */ + ticks = 0; + while (!(a->read_csr(ioaddr, 5) & 0x0001)) { + spin_unlock_irqrestore(&lp->lock, flags); + mdelay(1); + spin_lock_irqsave(&lp->lock, flags); + ticks++; + if (ticks > 200) { + if (netif_msg_hw(lp)) + printk(KERN_DEBUG "%s: Error getting into suspend!\n", + dev->name); + break; + } + } + } + + /* read address PROM */ + for (i=0; i<16; i += 2) + *buff++ = inw(ioaddr + i); + + for (i = 0; i <= 89; i++) { + *buff++ = a->read_csr(ioaddr, i); + } + + *buff++ = a->read_csr(ioaddr, 112); + *buff++ = a->read_csr(ioaddr, 114); + + for (i = 0; i <= 35; i++) { + *buff++ = a->read_bcr(ioaddr, i); + } + + if (!(csr0 & 0x0004)) { /* If not stopped */ + /* clear SUSPEND (SPND) - CSR5 bit 0 */ + a->write_csr(ioaddr, 5, 0x0000); + } + + i = buff - (u16 *)ptr; + for (; i < PCNET32_NUM_REGS; i++) + *buff++ = 0; + + spin_unlock_irqrestore(&lp->lock, flags); +} + static struct ethtool_ops pcnet32_ethtool_ops = { .get_settings = pcnet32_get_settings, .set_settings = pcnet32_set_settings, @@ -853,6 +926,8 @@ static struct ethtool_ops pcnet32_ethtoo .self_test_count = pcnet32_self_test_count, .self_test = pcnet32_ethtool_test, .phys_id = pcnet32_phys_id, + .get_regs_len = pcnet32_get_regs_len, + .get_regs = pcnet32_get_regs, }; /* only probes for non-PCI devices, the rest are handled by @@ -1032,6 +1107,13 @@ pcnet32_probe1(unsigned long ioaddr, uns ltint = 1; } + if (ltint) { + /* Enable timer to prevent skbuffs from remaining on the tx ring + * forever if no other tx being done. Set timer period to about + * 122 ms */ + a->write_bcr(ioaddr, 31, 0x253b); + } + dev = alloc_etherdev(0); if (!dev) { if (pcnet32_debug & NETIF_MSG_PROBE) @@ -1371,13 +1453,18 @@ pcnet32_open(struct net_device *dev) /* Re-initialize the PCNET32, and start it when done. */ lp->a.write_csr (ioaddr, 1, (lp->dma_addr + - offsetof(struct pcnet32_private, init_block)) & 0xffff); + offsetof(struct pcnet32_private, init_block)) & 0xffff); lp->a.write_csr (ioaddr, 2, (lp->dma_addr + offsetof(struct pcnet32_private, init_block)) >> 16); lp->a.write_csr (ioaddr, 4, 0x0915); lp->a.write_csr (ioaddr, 0, 0x0001); + if (lp->ltint) { + /* start the software timer */ + lp->a.write_csr(ioaddr, 7, 0x0400); /* set STINTE */ + } + netif_start_queue(dev); /* If we have mii, print the link status and start the watchdog */ @@ -1579,13 +1666,13 @@ pcnet32_start_xmit(struct sk_buff *skb, int entry; unsigned long flags; + spin_lock_irqsave(&lp->lock, flags); + if (netif_msg_tx_queued(lp)) { printk(KERN_DEBUG "%s: pcnet32_start_xmit() called, csr0 %4.4x.\n", dev->name, lp->a.read_csr(ioaddr, 0)); } - spin_lock_irqsave(&lp->lock, flags); - /* Default status -- will not enable Successful-TxDone * interrupt when that option is available to us. */ @@ -1646,7 +1733,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct net_device *dev = dev_id; struct pcnet32_private *lp; unsigned long ioaddr; - u16 csr0,rap; + u16 csr0, csr7, rap; int boguscnt = max_interrupt_work; int must_restart; @@ -1663,13 +1750,19 @@ pcnet32_interrupt(int irq, void *dev_id, spin_lock(&lp->lock); rap = lp->a.read_rap(ioaddr); - while ((csr0 = lp->a.read_csr (ioaddr, 0)) & 0x8600 && --boguscnt >= 0) { + csr0 = lp->a.read_csr (ioaddr, 0); + csr7 = lp->ltint ? lp->a.read_csr(ioaddr, 7) : 0; + + while ((csr0 & 0x8600 || csr7 & 0x0800) && --boguscnt >= 0) { if (csr0 == 0xffff) { break; /* PCMCIA remove happened */ } /* Acknowledge all of the current interrupt sources ASAP. */ lp->a.write_csr (ioaddr, 0, csr0 & ~0x004f); + if (csr7 & 0x0800) + lp->a.write_csr(ioaddr, 7, csr7); + must_restart = 0; if (netif_msg_intr(lp)) @@ -1679,7 +1772,7 @@ pcnet32_interrupt(int irq, void *dev_id, if (csr0 & 0x0400) /* Rx interrupt */ pcnet32_rx(dev); - if (csr0 & 0x0200) { /* Tx-done interrupt */ + if (csr0 & 0x0200 || csr7 & 0x0800) { /* Tx-done or Timer interrupt */ unsigned int dirty_tx = lp->dirty_tx; int delta; @@ -1786,6 +1879,9 @@ pcnet32_interrupt(int irq, void *dev_id, lp->a.write_csr (ioaddr, 0, 0x0004); pcnet32_restart(dev, 0x0002); } + + csr0 = lp->a.read_csr (ioaddr, 0); + csr7 = lp->ltint ? lp->a.read_csr(ioaddr, 7) : 0; } /* Clear any other interrupt, and set interrupt enable. */ @@ -1872,6 +1968,7 @@ pcnet32_rx(struct net_device *dev) if (i > RX_RING_SIZE -2) { lp->stats.rx_dropped++; lp->rx_ring[entry].status |= le16_to_cpu(0x8000); + wmb(); /* Make sure adapter sees owner change */ lp->cur_rx++; } break; @@ -1935,6 +2032,10 @@ pcnet32_close(struct net_device *dev) /* We stop the PCNET32 here -- it occasionally polls memory if we don't. */ lp->a.write_csr (ioaddr, 0, 0x0004); + if (lp->ltint) { /* Disable timer interrupts */ + lp->a.write_csr(ioaddr, 7, 0x0000); + } + /* * Switch back to 16bit mode to avoid problems with dumb * DOS packet driver after a warm reboot @@ -1945,9 +2046,12 @@ pcnet32_close(struct net_device *dev) free_irq(dev->irq, dev); + spin_lock_irqsave(&lp->lock, flags); + /* free all allocated skbuffs */ for (i = 0; i < RX_RING_SIZE; i++) { lp->rx_ring[i].status = 0; + wmb(); /* Make sure adapter sees owner change */ if (lp->rx_skbuff[i]) { pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE); @@ -1958,6 +2062,8 @@ pcnet32_close(struct net_device *dev) } for (i = 0; i < TX_RING_SIZE; i++) { + lp->tx_ring[i].status = 0; /* CPU owns buffer */ + wmb(); /* Make sure adapter sees owner change */ if (lp->tx_skbuff[i]) { pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i], lp->tx_skbuff[i]->len, PCI_DMA_TODEVICE); @@ -1967,6 +2073,8 @@ pcnet32_close(struct net_device *dev) lp->tx_dma_addr[i] = 0; } + spin_unlock_irqrestore(&lp->lock, flags); + return 0; } --- linux-2.6.6/drivers/net/s2io.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/net/s2io.c 2004-05-10 01:19:37.321065392 -0700 @@ -2339,9 +2339,6 @@ static irqreturn_t s2io_isr(int irq, voi struct net_device *dev = (struct net_device *) dev_id; nic_t *sp = dev->priv; XENA_dev_config_t *bar0 = (XENA_dev_config_t *) sp->bar0; -#ifndef CONFIG_S2IO_NAPI - int i, ret; -#endif u64 reason = 0, general_mask = 0; mac_info_t *mac_control; struct config_param *config; --- linux-2.6.6/drivers/net/sk98lin/skvpd.c 2004-03-10 20:41:29.000000000 -0800 +++ 25/drivers/net/sk98lin/skvpd.c 2004-05-10 01:19:28.476409984 -0700 @@ -468,6 +468,17 @@ SK_IOC IoC) /* IO Context */ pAC->vpd.vpd_size = vpd_size; + /* Asus K8V Se Deluxe bugfix. Correct VPD content */ + /* MBo April 2004 */ + if (((unsigned char)pAC->vpd.vpd_buf[0x3f] == 0x38) && + ((unsigned char)pAC->vpd.vpd_buf[0x40] == 0x3c) && + ((unsigned char)pAC->vpd.vpd_buf[0x41] == 0x45)) { + printk("sk98lin: Asus mainboard with buggy VPD?" + "Correcting data.\n"); + pAC->vpd.vpd_buf[0x40] = 0x38; + } + + /* find the end tag of the RO area */ if (!(r = vpd_find_para(pAC, VPD_RV, &rp))) { SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, --- linux-2.6.6/drivers/net/sun3lance.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/net/sun3lance.c 2004-05-10 01:19:35.627322880 -0700 @@ -42,7 +42,6 @@ static char *version = "sun3lance.c: v1. #include #include #include -#include #include #include #include --- linux-2.6.6/drivers/net/tulip/tulip_core.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/net/tulip/tulip_core.c 2004-05-10 01:19:24.929949128 -0700 @@ -1513,7 +1513,7 @@ static int __devinit tulip_init_one (str } } /* Lite-On boards have the address byte-swapped. */ - if ((dev->dev_addr[0] == 0xA0 || dev->dev_addr[0] == 0xC0) + if ((dev->dev_addr[0] == 0xA0 || dev->dev_addr[0] == 0xC0 || dev->dev_addr[0] == 0x02) && dev->dev_addr[1] == 0x00) for (i = 0; i < 6; i+=2) { char tmp = dev->dev_addr[i]; --- linux-2.6.6/drivers/net/tulip/winbond-840.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/net/tulip/winbond-840.c 2004-05-10 01:19:55.566291696 -0700 @@ -146,7 +146,7 @@ static int full_duplex[MAX_UNITS] = {-1, #include /* These identify the driver base version and may not be removed. */ -static char version[] __devinitdata = +static const char version[] __devinitdata = KERN_INFO DRV_NAME ".c:v" DRV_VERSION " (2.4 port) " DRV_RELDATE " Donald Becker \n" KERN_INFO " http://www.scyld.com/network/drivers.html\n"; --- linux-2.6.6/drivers/parisc/ccio-dma.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/parisc/ccio-dma.c 2004-05-10 01:19:35.628322728 -0700 @@ -44,7 +44,6 @@ #include #include /* for L1_CACHE_BYTES */ #include -#include #include #include #include --- linux-2.6.6/drivers/parisc/ccio-rm-dma.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/parisc/ccio-rm-dma.c 2004-05-10 01:19:35.629322576 -0700 @@ -40,7 +40,6 @@ #include #include -#include #include #include --- linux-2.6.6/drivers/parport/share.c 2004-03-10 20:41:29.000000000 -0800 +++ 25/drivers/parport/share.c 2004-05-10 01:19:44.648951384 -0700 @@ -169,7 +169,7 @@ int parport_register_driver (struct parp /** * parport_unregister_driver - deregister a parallel port device driver - * @arg: structure describing the driver that was given to + * @drv: structure describing the driver that was given to * parport_register_driver() * * This should be called by a parallel port device driver that --- linux-2.6.6/drivers/pci/hotplug/acpiphp_core.c 2004-02-17 20:48:44.000000000 -0800 +++ 25/drivers/pci/hotplug/acpiphp_core.c 2004-05-10 01:19:03.989132616 -0700 @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -43,11 +44,7 @@ static LIST_HEAD(slot_list); -#if !defined(CONFIG_HOTPLUG_PCI_ACPI_MODULE) - #define MY_NAME "acpiphp" -#else - #define MY_NAME THIS_MODULE->name -#endif +#define MY_NAME "acpiphp" static int debug; int acpiphp_debug; @@ -62,72 +59,28 @@ static int num_slots; MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); +module_param(debug, bool, 644); static int enable_slot (struct hotplug_slot *slot); static int disable_slot (struct hotplug_slot *slot); static int set_attention_status (struct hotplug_slot *slot, u8 value); -static int hardware_test (struct hotplug_slot *slot, u32 value); static int get_power_status (struct hotplug_slot *slot, u8 *value); -static int get_attention_status (struct hotplug_slot *slot, u8 *value); static int get_address (struct hotplug_slot *slot, u32 *value); static int get_latch_status (struct hotplug_slot *slot, u8 *value); static int get_adapter_status (struct hotplug_slot *slot, u8 *value); -static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value); -static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value); static struct hotplug_slot_ops acpi_hotplug_slot_ops = { .owner = THIS_MODULE, .enable_slot = enable_slot, .disable_slot = disable_slot, .set_attention_status = set_attention_status, - .hardware_test = hardware_test, .get_power_status = get_power_status, - .get_attention_status = get_attention_status, .get_latch_status = get_latch_status, .get_adapter_status = get_adapter_status, .get_address = get_address, - .get_max_bus_speed = get_max_bus_speed, - .get_cur_bus_speed = get_cur_bus_speed, }; - -/* Inline functions to check the sanity of a pointer that is passed to us */ -static inline int slot_paranoia_check (struct slot *slot, const char *function) -{ - if (!slot) { - dbg("%s - slot == NULL\n", function); - return -1; - } - if (slot->magic != SLOT_MAGIC) { - dbg("%s - bad magic number for slot\n", function); - return -1; - } - if (!slot->hotplug_slot) { - dbg("%s - slot->hotplug_slot == NULL!\n", function); - return -1; - } - return 0; -} - - -static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const char *function) -{ - struct slot *slot; - - if (!hotplug_slot) { - dbg("%s - hotplug_slot == NULL\n", function); - return NULL; - } - - slot = (struct slot *)hotplug_slot->private; - if (slot_paranoia_check(slot, function)) - return NULL; - return slot; -} - - /** * enable_slot - power on and enable a slot * @hotplug_slot: slot to enable @@ -135,20 +88,14 @@ static inline struct slot *get_slot (str * Actual tasks are done in acpiphp_enable_slot() * */ -static int enable_slot (struct hotplug_slot *hotplug_slot) +static int enable_slot(struct hotplug_slot *hotplug_slot) { - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); - int retval = 0; - - if (slot == NULL) - return -ENODEV; + struct slot *slot = hotplug_slot->private; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); /* enable the specified slot */ - retval = acpiphp_enable_slot(slot->acpi_slot); - - return retval; + return acpiphp_enable_slot(slot->acpi_slot); } @@ -159,20 +106,14 @@ static int enable_slot (struct hotplug_s * Actual tasks are done in acpiphp_disable_slot() * */ -static int disable_slot (struct hotplug_slot *hotplug_slot) +static int disable_slot(struct hotplug_slot *hotplug_slot) { - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); - int retval = 0; - - if (slot == NULL) - return -ENODEV; + struct slot *slot = hotplug_slot->private; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); /* disable the specified slot */ - retval = acpiphp_disable_slot(slot->acpi_slot); - - return retval; + return acpiphp_disable_slot(slot->acpi_slot); } @@ -184,10 +125,8 @@ static int disable_slot (struct hotplug_ * attention status LED. * */ -static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) +static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) { - int retval = 0; - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); switch (status) { @@ -203,33 +142,9 @@ static int set_attention_status (struct break; } - return retval; -} - - -/** - * hardware_test - hardware test - * - * We have nothing to do for now... - * - */ -static int hardware_test (struct hotplug_slot *hotplug_slot, u32 value) -{ - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); - int retval = 0; - - if (slot == NULL) - return -ENODEV; - - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - - err("No hardware tests are defined for this driver\n"); - retval = -ENODEV; - - return retval; + return 0; } - /** * get_power_status - get power status of a slot * @hotplug_slot: slot to get status @@ -239,41 +154,17 @@ static int hardware_test (struct hotplug * In that case, the value returned may not be reliable. * */ -static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) +static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); - int retval = 0; - - if (slot == NULL) - return -ENODEV; + struct slot *slot = hotplug_slot->private; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); *value = acpiphp_get_power_status(slot->acpi_slot); - return retval; -} - - -/** - * get_attention_status - get attention LED status - * - * TBD: - * ACPI doesn't provide any formal means to access attention LED status. - * - */ -static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) -{ - int retval = 0; - - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - - *value = hotplug_slot->info->attention_status; - - return retval; + return 0; } - /** * get_latch_status - get latch status of a slot * @hotplug_slot: slot to get status @@ -283,19 +174,15 @@ static int get_attention_status (struct * Instead, we fake latch status from _STA * */ -static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) +static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); - int retval = 0; - - if (slot == NULL) - return -ENODEV; + struct slot *slot = hotplug_slot->private; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); *value = acpiphp_get_latch_status(slot->acpi_slot); - return retval; + return 0; } @@ -308,19 +195,15 @@ static int get_latch_status (struct hotp * Instead, we fake adapter status from _STA * */ -static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) +static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); - int retval = 0; - - if (slot == NULL) - return -ENODEV; + struct slot *slot = hotplug_slot->private; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); *value = acpiphp_get_adapter_status(slot->acpi_slot); - return retval; + return 0; } @@ -330,51 +213,18 @@ static int get_adapter_status (struct ho * @busdev: pointer to struct pci_busdev (seg, bus, dev) * */ -static int get_address (struct hotplug_slot *hotplug_slot, u32 *value) +static int get_address(struct hotplug_slot *hotplug_slot, u32 *value) { - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); - int retval = 0; - - if (slot == NULL) - return -ENODEV; + struct slot *slot = hotplug_slot->private; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); *value = acpiphp_get_address(slot->acpi_slot); - return retval; -} - - -/* return dummy value because ACPI doesn't provide any method... */ -static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) -{ - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); - - if (slot == NULL) - return -ENODEV; - - *value = PCI_SPEED_UNKNOWN; - - return 0; -} - - -/* return dummy value because ACPI doesn't provide any method... */ -static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) -{ - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); - - if (slot == NULL) - return -ENODEV; - - *value = PCI_SPEED_UNKNOWN; - return 0; } - -static int __init init_acpi (void) +static int __init init_acpi(void) { int retval; @@ -397,7 +247,7 @@ static int __init init_acpi (void) * @slot: slot to name * */ -static void make_slot_name (struct slot *slot) +static void make_slot_name(struct slot *slot) { snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%u", slot->acpi_slot->sun); @@ -409,10 +259,7 @@ static void make_slot_name (struct slot */ static void release_slot(struct hotplug_slot *hotplug_slot) { - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); - - if (slot == NULL) - return; + struct slot *slot = hotplug_slot->private; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -426,42 +273,32 @@ static void release_slot(struct hotplug_ * init_slots - initialize 'struct slot' structures for each slot * */ -static int __init init_slots (void) +static int __init init_slots(void) { struct slot *slot; - int retval = 0; + int retval = -ENOMEM; int i; for (i = 0; i < num_slots; ++i) { slot = kmalloc(sizeof(struct slot), GFP_KERNEL); if (!slot) - return -ENOMEM; + goto error; memset(slot, 0, sizeof(struct slot)); slot->hotplug_slot = kmalloc(sizeof(struct hotplug_slot), GFP_KERNEL); - if (!slot->hotplug_slot) { - kfree(slot); - return -ENOMEM; - } + if (!slot->hotplug_slot) + goto error_slot; memset(slot->hotplug_slot, 0, sizeof(struct hotplug_slot)); slot->hotplug_slot->info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); - if (!slot->hotplug_slot->info) { - kfree(slot->hotplug_slot); - kfree(slot); - return -ENOMEM; - } + if (!slot->hotplug_slot->info) + goto error_hpslot; memset(slot->hotplug_slot->info, 0, sizeof(struct hotplug_slot_info)); slot->hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); - if (!slot->hotplug_slot->name) { - kfree(slot->hotplug_slot->info); - kfree(slot->hotplug_slot); - kfree(slot); - return -ENOMEM; - } + if (!slot->hotplug_slot->name) + goto error_info; - slot->magic = SLOT_MAGIC; slot->number = i; slot->hotplug_slot->private = slot; @@ -473,14 +310,15 @@ static int __init init_slots (void) slot->hotplug_slot->info->attention_status = acpiphp_get_attention_status(slot->acpi_slot); slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot); slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot); + slot->hotplug_slot->info->max_bus_speed = PCI_SPEED_UNKNOWN; + slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN; make_slot_name(slot); retval = pci_hp_register(slot->hotplug_slot); if (retval) { err("pci_hp_register failed with error %d\n", retval); - release_slot(slot->hotplug_slot); - return retval; + goto error_name; } /* add slot to our internal list */ @@ -488,6 +326,16 @@ static int __init init_slots (void) info("Slot [%s] registered\n", slot->hotplug_slot->name); } + return 0; +error_name: + kfree(slot->hotplug_slot->name); +error_info: + kfree(slot->hotplug_slot->info); +error_hpslot: + kfree(slot->hotplug_slot); +error_slot: + kfree(slot); +error: return retval; } @@ -503,8 +351,6 @@ static void __exit cleanup_slots (void) list_del(&slot->slot_list); pci_hp_deregister(slot->hotplug_slot); } - - return; } @@ -521,11 +367,7 @@ static int __init acpiphp_init(void) if (retval) return retval; - retval = init_slots(); - if (retval) - return retval; - - return 0; + return init_slots(); } --- linux-2.6.6/drivers/pci/hotplug/acpiphp_glue.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/pci/hotplug/acpiphp_glue.c 2004-05-10 01:19:43.749088184 -0700 @@ -66,7 +66,7 @@ static void handle_hotplug_event_func (a * 4. .. * */ -static int is_ejectable (acpi_handle handle) +static int is_ejectable(acpi_handle handle) { acpi_status status; acpi_handle tmp; @@ -326,10 +326,10 @@ static void decode_hpp(struct acpiphp_br bridge->hpp.enable_PERR = package->package.elements[3].integer.value; dbg("_HPP parameter = (%02x, %02x, %02x, %02x)\n", - bridge->hpp.cache_line_size, - bridge->hpp.latency_timer, - bridge->hpp.enable_SERR, - bridge->hpp.enable_PERR); + bridge->hpp.cache_line_size, + bridge->hpp.latency_timer, + bridge->hpp.enable_SERR, + bridge->hpp.enable_PERR); bridge->flags |= BRIDGE_HAS_HPP; @@ -1113,6 +1113,8 @@ void __exit acpiphp_glue_exit(void) kfree(bridge); } + + acpi_pci_unregister_driver(&acpi_pci_hp_driver); } @@ -1180,7 +1182,8 @@ struct acpiphp_slot *get_slot_from_id(in } /* should never happen! */ - err("%s: no object for id %d\n",__FUNCTION__, id); + err("%s: no object for id %d\n", __FUNCTION__, id); + WARN_ON(1); return 0; } --- linux-2.6.6/drivers/pci/hotplug/acpiphp.h 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/pci/hotplug/acpiphp.h 2004-05-10 01:19:03.986133072 -0700 @@ -47,7 +47,6 @@ #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) -#define SLOT_MAGIC 0x67267322 /* name size which is used for entries in pcihpfs */ #define SLOT_NAME_SIZE KOBJ_NAME_LEN /* {_SUN} */ @@ -59,7 +58,6 @@ struct pci_resource; * struct slot - slot information for each *physical* slot */ struct slot { - u32 magic; u8 number; struct hotplug_slot *hotplug_slot; struct list_head slot_list; --- linux-2.6.6/drivers/pci/hotplug/cpci_hotplug_core.c 2003-09-27 18:57:45.000000000 -0700 +++ 25/drivers/pci/hotplug/cpci_hotplug_core.c 2004-05-10 01:19:03.991132312 -0700 @@ -94,10 +94,6 @@ slot_paranoia_check(struct slot *slot, c dbg("%s - slot == NULL", function); return -1; } - if(slot->magic != SLOT_MAGIC) { - dbg("%s - bad magic number for slot", function); - return -1; - } if(!slot->hotplug_slot) { dbg("%s - slot->hotplug_slot == NULL!", function); return -1; @@ -353,7 +349,6 @@ cpci_hp_register_bus(struct pci_bus *bus } hotplug_slot->name = name; - slot->magic = SLOT_MAGIC; slot->bus = bus; slot->number = i; slot->devfn = PCI_DEVFN(i, 0); --- linux-2.6.6/drivers/pci/hotplug/cpci_hotplug.h 2003-09-27 18:57:45.000000000 -0700 +++ 25/drivers/pci/hotplug/cpci_hotplug.h 2004-05-10 01:19:03.990132464 -0700 @@ -40,9 +40,7 @@ #define HS_CSR_EIM 0x0002 #define HS_CSR_DHA 0x0001 -#define SLOT_MAGIC 0x67267322 struct slot { - u32 magic; u8 number; unsigned int devfn; struct pci_bus *bus; --- linux-2.6.6/drivers/pci/hotplug/cpcihp_generic.c 2003-06-14 12:18:22.000000000 -0700 +++ 25/drivers/pci/hotplug/cpcihp_generic.c 2004-05-10 01:19:03.991132312 -0700 @@ -76,73 +76,6 @@ static u8 enum_mask; static struct cpci_hp_controller_ops generic_hpc_ops; static struct cpci_hp_controller generic_hpc; -/* The following allows configuring the driver when it's compiled into the kernel */ -#ifndef MODULE -static int __init cpcihp_generic_setup(char* str) -{ - char* p; - unsigned long tmp; - - if(!str) - return -EINVAL; - bridge = str; - - p = strchr(str, ','); - str = p + 1; - if(!(p && *str && *p == ',')) - goto setup_error; - tmp = simple_strtoul(str, &p, 0); - if(p == str || tmp > 0xff) { - err("hotplug bus first slot number out of range"); - goto setup_error; - } - first_slot = (u8) tmp; - - str = p + 1; - if(!(*str && *p == ',')) - return -EINVAL; - tmp = simple_strtoul(str, &p, 0); - if(p == str || tmp > 0xff) { - err("hotplug bus last slot number out of range"); - goto setup_error; - } - last_slot = (u8) tmp; - - str = p + 1; - if(!(*str && *p == ',')) - goto setup_error; - tmp = simple_strtoul(str, &p, 0); - if(p == str || tmp > 0xffff) { - err("port number out of range"); - goto setup_error; - } - port = (u16) tmp; - - str = p + 1; - if(!(*str && *p == ',')) - goto setup_error; - tmp = simple_strtoul(str, &p, 0); - if(p == str) { - err("invalid #ENUM bit number"); - goto setup_error; - } - enum_bit = (u8) tmp; - - str = p + 1; - if(*str && *p == ',') { - tmp = simple_strtoul(str, &p, 0); - if(p != str) - debug = (int) tmp; - } - return 0; -setup_error: - bridge = NULL; - return -EINVAL; -} - -__setup("cpcihp_generic=", cpcihp_generic_setup); -#endif - static int __init validate_parameters(void) { char* str; --- linux-2.6.6/drivers/pci/hotplug/cpcihp_zt5550.c 2004-02-03 20:42:36.000000000 -0800 +++ 25/drivers/pci/hotplug/cpcihp_zt5550.c 2004-05-10 01:19:03.992132160 -0700 @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -42,11 +43,7 @@ #define DRIVER_AUTHOR "Scott Murray " #define DRIVER_DESC "ZT5550 CompactPCI Hot Plug Driver" -#if !defined(CONFIG_HOTPLUG_PCI_CPCI_ZT5550_MODULE) #define MY_NAME "cpcihp_zt5550" -#else -#define MY_NAME THIS_MODULE->name -#endif #define dbg(format, arg...) \ do { \ @@ -301,7 +298,7 @@ module_exit(zt5550_exit); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -MODULE_PARM(debug, "i"); +module_param(debug, bool, 644); MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); -MODULE_PARM(poll, "i"); +module_param(poll, bool, 644); MODULE_PARM_DESC(poll, "#ENUM polling mode enabled or not"); --- linux-2.6.6/drivers/pci/hotplug/cpqphp_core.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/pci/hotplug/cpqphp_core.c 2004-05-10 01:19:04.000130944 -0700 @@ -2,7 +2,7 @@ * Compaq Hot Plug Controller Driver * * Copyright (C) 1995,2001 Compaq Computer Corporation - * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 Greg Kroah-Hartman * Copyright (C) 2001 IBM Corp. * * All rights reserved. @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -57,10 +58,10 @@ struct pci_func *cpqhp_slot_list[256]; static void *smbios_table; static void *smbios_start; static void *cpqhp_rom_start; -static u8 power_mode; +static int power_mode; static int debug; -#define DRIVER_VERSION "0.9.7" +#define DRIVER_VERSION "0.9.8" #define DRIVER_AUTHOR "Dan Zink , Greg Kroah-Hartman " #define DRIVER_DESC "Compaq Hot Plug PCI Controller Driver" @@ -68,16 +69,16 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -MODULE_PARM(power_mode, "b"); +module_param(power_mode, bool, 644); MODULE_PARM_DESC(power_mode, "Power mode enabled or not"); -MODULE_PARM(debug, "i"); +module_param(debug, bool, 644); MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); #define CPQHPC_MODULE_MINOR 208 -static int one_time_init (void); -static int set_attention_status (struct hotplug_slot *slot, u8 value); +static int one_time_init (void); +static int set_attention_status (struct hotplug_slot *slot, u8 value); static int process_SI (struct hotplug_slot *slot); static int process_SS (struct hotplug_slot *slot); static int hardware_test (struct hotplug_slot *slot, u32 value); @@ -103,30 +104,18 @@ static struct hotplug_slot_ops cpqphp_ho }; -static inline int is_slot64bit (struct slot *slot) +static inline int is_slot64bit(struct slot *slot) { - if (!slot || !slot->p_sm_slot) - return 0; - - if (readb(slot->p_sm_slot + SMBIOS_SLOT_WIDTH) == 0x06) - return 1; - - return 0; + return (readb(slot->p_sm_slot + SMBIOS_SLOT_WIDTH) == 0x06) ? 1 : 0; } -static inline int is_slot66mhz (struct slot *slot) +static inline int is_slot66mhz(struct slot *slot) { - if (!slot || !slot->p_sm_slot) - return 0; - - if (readb(slot->p_sm_slot + SMBIOS_SLOT_TYPE) == 0x0E) - return 1; - - return 0; + return (readb(slot->p_sm_slot + SMBIOS_SLOT_TYPE) == 0x0E) ? 1 : 0; } /** - * detect_SMBIOS_pointer - find the system Management BIOS Table in the specified region of memory. + * detect_SMBIOS_pointer - find the System Management BIOS Table in mem region. * * @begin: begin pointer for region to be scanned. * @end: end pointer for region to be scanned. @@ -210,7 +199,8 @@ static int pci_print_IRQ_route (void) return -ENOMEM; } - len = (routing_table->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info); + len = (routing_table->size - sizeof(struct irq_routing_table)) / + sizeof(struct irq_info); // Make sure I got at least one entry if (len == 0) { kfree(routing_table); @@ -231,8 +221,8 @@ static int pci_print_IRQ_route (void) } -/* - * get_subsequent_smbios_entry +/** + * get_subsequent_smbios_entry: get the next entry from bios table. * * Gets the first entry if previous == NULL * Otherwise, returns the next entry @@ -242,7 +232,8 @@ static int pci_print_IRQ_route (void) * * returns a pointer to an SMBIOS structure or NULL if none found */ -static void * get_subsequent_smbios_entry(void *smbios_start, void *smbios_table, void *curr) +static void *get_subsequent_smbios_entry(void *smbios_start, + void *smbios_table, void *curr) { u8 bail = 0; u8 previous_byte = 1; @@ -259,8 +250,9 @@ static void * get_subsequent_smbios_entr p_temp += readb(curr + SMBIOS_GENERIC_LENGTH); while ((p_temp < p_max) && !bail) { - // Look for the double NULL terminator - // The first condition is the previous byte and the second is the curr + /* Look for the double NULL terminator + * The first condition is the previous byte + * and the second is the curr */ if (!previous_byte && !(readb(p_temp))) { bail = 1; } @@ -290,7 +282,8 @@ static void * get_subsequent_smbios_entr * * returns a pointer to an SMBIOS structure or %NULL if none found */ -static void *get_SMBIOS_entry (void *smbios_start, void *smbios_table, u8 type, void * previous) +static void *get_SMBIOS_entry(void *smbios_start, void *smbios_table, u8 type, + void * previous) { if (!smbios_table) return NULL; @@ -298,12 +291,14 @@ static void *get_SMBIOS_entry (void *smb if (!previous) { previous = smbios_start; } else { - previous = get_subsequent_smbios_entry(smbios_start, smbios_table, previous); + previous = get_subsequent_smbios_entry(smbios_start, + smbios_table, previous); } while (previous) { if (readb(previous + SMBIOS_GENERIC_TYPE) != type) { - previous = get_subsequent_smbios_entry(smbios_start, smbios_table, previous); + previous = get_subsequent_smbios_entry(smbios_start, + smbios_table, previous); } else { break; } @@ -314,11 +309,8 @@ static void *get_SMBIOS_entry (void *smb static void release_slot(struct hotplug_slot *hotplug_slot) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); - - if (slot == NULL) - return; - + struct slot *slot = hotplug_slot->private; + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); kfree(slot->hotplug_slot->info); @@ -327,7 +319,8 @@ static void release_slot(struct hotplug_ kfree(slot); } -static int ctrl_slot_setup (struct controller * ctrl, void *smbios_start, void *smbios_table) +static int ctrl_slot_setup(struct controller * ctrl, void *smbios_start, + void *smbios_table) { struct slot *new_slot; u8 number_of_slots; @@ -336,7 +329,7 @@ static int ctrl_slot_setup (struct contr u8 ctrl_slot; u32 tempdword; void *slot_entry= NULL; - int result; + int result = -ENOMEM; dbg("%s\n", __FUNCTION__); @@ -347,44 +340,40 @@ static int ctrl_slot_setup (struct contr slot_number = ctrl->first_slot; while (number_of_slots) { - new_slot = (struct slot *) kmalloc(sizeof(struct slot), GFP_KERNEL); + new_slot = kmalloc(sizeof(*new_slot), GFP_KERNEL); if (!new_slot) - return -ENOMEM; + goto error; memset(new_slot, 0, sizeof(struct slot)); - new_slot->hotplug_slot = kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL); - if (!new_slot->hotplug_slot) { - kfree (new_slot); - return -ENOMEM; - } - memset(new_slot->hotplug_slot, 0, sizeof (struct hotplug_slot)); + new_slot->hotplug_slot = kmalloc(sizeof(*(new_slot->hotplug_slot)), + GFP_KERNEL); + if (!new_slot->hotplug_slot) + goto error_slot; + memset(new_slot->hotplug_slot, 0, sizeof(struct hotplug_slot)); + + new_slot->hotplug_slot->info = + kmalloc(sizeof(*(new_slot->hotplug_slot->info)), + GFP_KERNEL); + if (!new_slot->hotplug_slot->info) + goto error_hpslot; + memset(new_slot->hotplug_slot->info, 0, + sizeof(struct hotplug_slot_info)); + new_slot->hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); + if (!new_slot->hotplug_slot->name) + goto error_info; - new_slot->hotplug_slot->info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL); - if (!new_slot->hotplug_slot->info) { - kfree (new_slot->hotplug_slot); - kfree (new_slot); - return -ENOMEM; - } - memset(new_slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info)); - new_slot->hotplug_slot->name = kmalloc (SLOT_NAME_SIZE, GFP_KERNEL); - if (!new_slot->hotplug_slot->name) { - kfree (new_slot->hotplug_slot->info); - kfree (new_slot->hotplug_slot); - kfree (new_slot); - return -ENOMEM; - } - - new_slot->magic = SLOT_MAGIC; new_slot->ctrl = ctrl; new_slot->bus = ctrl->bus; new_slot->device = slot_device; new_slot->number = slot_number; dbg("slot->number = %d\n",new_slot->number); - slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9, slot_entry); + slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9, + slot_entry); while (slot_entry && (readw(slot_entry + SMBIOS_SLOT_NUMBER) != new_slot->number)) { - slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9, slot_entry); + slot_entry = get_SMBIOS_entry(smbios_start, + smbios_table, 9, slot_entry); } new_slot->p_sm_slot = slot_entry; @@ -417,7 +406,7 @@ static int ctrl_slot_setup (struct contr /* register this slot with the hotplug pci core */ new_slot->hotplug_slot->release = &release_slot; new_slot->hotplug_slot->private = new_slot; - make_slot_name (new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot); + make_slot_name(new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot); new_slot->hotplug_slot->ops = &cpqphp_hotplug_slot_ops; new_slot->hotplug_slot->info->power_status = get_slot_enabled(ctrl, new_slot); @@ -425,13 +414,15 @@ static int ctrl_slot_setup (struct contr new_slot->hotplug_slot->info->latch_status = cpq_get_latch_status(ctrl, new_slot); new_slot->hotplug_slot->info->adapter_status = get_presence_status(ctrl, new_slot); - dbg ("registering bus %d, dev %d, number %d, ctrl->slot_device_offset %d, slot %d\n", - new_slot->bus, new_slot->device, new_slot->number, ctrl->slot_device_offset, slot_number); + dbg ("registering bus %d, dev %d, number %d, " + "ctrl->slot_device_offset %d, slot %d\n", + new_slot->bus, new_slot->device, + new_slot->number, ctrl->slot_device_offset, + slot_number); result = pci_hp_register (new_slot->hotplug_slot); if (result) { err ("pci_hp_register failed with error %d\n", result); - release_slot(new_slot->hotplug_slot); - return result; + goto error_name; } new_slot->next = ctrl->slot; @@ -443,6 +434,17 @@ static int ctrl_slot_setup (struct contr } return 0; + +error_name: + kfree(new_slot->hotplug_slot->name); +error_info: + kfree(new_slot->hotplug_slot->info); +error_hpslot: + kfree(new_slot->hotplug_slot); +error_slot: + kfree(new_slot); +error: + return result; } static int ctrl_slot_cleanup (struct controller * ctrl) @@ -485,7 +487,8 @@ static int ctrl_slot_cleanup (struct con // // Output: SUCCESS or FAILURE //============================================================================= -static int get_slot_mapping (struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *slot) +static int +get_slot_mapping(struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *slot) { struct irq_routing_table *PCIIRQRoutingInfoLength; u32 work; @@ -520,17 +523,22 @@ static int get_slot_mapping (struct pci_ kfree(PCIIRQRoutingInfoLength); return 0; } else { - // Didn't get a match on the target PCI device. Check if the - // current IRQ table entry is a PCI-to-PCI bridge device. If so, - // and it's secondary bus matches the bus number for the target - // device, I need to save the bridge's slot number. If I can't - // find an entry for the target device, I will have to assume it's - // on the other side of the bridge, and assign it the bridge's slot. + /* Did not get a match on the target PCI device. Check + * if the current IRQ table entry is a PCI-to-PCI bridge + * device. If so, and it's secondary bus matches the + * bus number for the target device, I need to save the + * bridge's slot number. If I can not find an entry for + * the target device, I will have to assume it's on the + * other side of the bridge, and assign it the bridge's + * slot. */ bus->number = tbus; - pci_bus_read_config_dword (bus, PCI_DEVFN(tdevice, 0), PCI_REVISION_ID, &work); + pci_bus_read_config_dword(bus, PCI_DEVFN(tdevice, 0), + PCI_REVISION_ID, &work); if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) { - pci_bus_read_config_dword (bus, PCI_DEVFN(tdevice, 0), PCI_PRIMARY_BUS, &work); + pci_bus_read_config_dword(bus, + PCI_DEVFN(tdevice, 0), + PCI_PRIMARY_BUS, &work); // See if bridge's secondary bus matches target bus. if (((work >> 8) & 0x000000FF) == (long) bus_num) { bridgeSlot = tslot; @@ -559,7 +567,9 @@ static int get_slot_mapping (struct pci_ * cpqhp_set_attention_status - Turns the Amber LED for a slot on or off * */ -static int cpqhp_set_attention_status (struct controller *ctrl, struct pci_func *func, u32 status) +static int +cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func, + u32 status) { u8 hp_slot; @@ -600,22 +610,15 @@ static int cpqhp_set_attention_status (s static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) { struct pci_func *slot_func; - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); - struct controller *ctrl; + struct slot *slot = hotplug_slot->private; + struct controller *ctrl = slot->ctrl; u8 bus; u8 devfn; u8 device; u8 function; - - if (slot == NULL) - return -ENODEV; - + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - ctrl = slot->ctrl; - if (ctrl == NULL) - return -ENODEV; - if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1) return -ENODEV; @@ -624,33 +627,25 @@ static int set_attention_status (struct dbg("bus, dev, fn = %d, %d, %d\n", bus, device, function); slot_func = cpqhp_slot_find(bus, device, function); - if (!slot_func) { + if (!slot_func) return -ENODEV; - } return cpqhp_set_attention_status(ctrl, slot_func, status); } -static int process_SI (struct hotplug_slot *hotplug_slot) +static int process_SI(struct hotplug_slot *hotplug_slot) { struct pci_func *slot_func; - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); - struct controller *ctrl; + struct slot *slot = hotplug_slot->private; + struct controller *ctrl = slot->ctrl; u8 bus; u8 devfn; u8 device; u8 function; - - if (slot == NULL) - return -ENODEV; - + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - ctrl = slot->ctrl; - if (ctrl == NULL) - return -ENODEV; - if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1) return -ENODEV; @@ -659,9 +654,8 @@ static int process_SI (struct hotplug_sl dbg("bus, dev, fn = %d, %d, %d\n", bus, device, function); slot_func = cpqhp_slot_find(bus, device, function); - if (!slot_func) { + if (!slot_func) return -ENODEV; - } slot_func->bus = bus; slot_func->device = device; @@ -672,25 +666,18 @@ static int process_SI (struct hotplug_sl } -static int process_SS (struct hotplug_slot *hotplug_slot) +static int process_SS(struct hotplug_slot *hotplug_slot) { struct pci_func *slot_func; - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); - struct controller *ctrl; + struct slot *slot = hotplug_slot->private; + struct controller *ctrl = slot->ctrl; u8 bus; u8 devfn; u8 device; u8 function; - - if (slot == NULL) - return -ENODEV; - + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - ctrl = slot->ctrl; - if (ctrl == NULL) - return -ENODEV; - if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1) return -ENODEV; @@ -699,121 +686,78 @@ static int process_SS (struct hotplug_sl dbg("bus, dev, fn = %d, %d, %d\n", bus, device, function); slot_func = cpqhp_slot_find(bus, device, function); - if (!slot_func) { + if (!slot_func) return -ENODEV; - } - - dbg("In power_down_board, slot_func = %p, ctrl = %p\n", slot_func, ctrl); + + dbg("In %s, slot_func = %p, ctrl = %p\n", __FUNCTION__, slot_func, ctrl); return cpqhp_process_SS(ctrl, slot_func); } -static int hardware_test (struct hotplug_slot *hotplug_slot, u32 value) +static int hardware_test(struct hotplug_slot *hotplug_slot, u32 value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); - struct controller *ctrl; + struct slot *slot = hotplug_slot->private; + struct controller *ctrl = slot->ctrl; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - if (slot == NULL) - return -ENODEV; - - ctrl = slot->ctrl; - if (ctrl == NULL) - return -ENODEV; - - return cpqhp_hardware_test (ctrl, value); + return cpqhp_hardware_test(ctrl, value); } -static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) +static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); - struct controller *ctrl; - - if (slot == NULL) - return -ENODEV; - + struct slot *slot = hotplug_slot->private; + struct controller *ctrl = slot->ctrl; + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - ctrl = slot->ctrl; - if (ctrl == NULL) - return -ENODEV; - *value = get_slot_enabled(ctrl, slot); return 0; } -static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) +static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); - struct controller *ctrl; - - if (slot == NULL) - return -ENODEV; + struct slot *slot = hotplug_slot->private; + struct controller *ctrl = slot->ctrl; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - ctrl = slot->ctrl; - if (ctrl == NULL) - return -ENODEV; - *value = cpq_get_attention_status(ctrl, slot); return 0; } -static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) +static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); - struct controller *ctrl; - - if (slot == NULL) - return -ENODEV; - + struct slot *slot = hotplug_slot->private; + struct controller *ctrl = slot->ctrl; + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - ctrl = slot->ctrl; - if (ctrl == NULL) - return -ENODEV; - - *value = cpq_get_latch_status (ctrl, slot); + *value = cpq_get_latch_status(ctrl, slot); return 0; } -static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) +static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); - struct controller *ctrl; - - if (slot == NULL) - return -ENODEV; + struct slot *slot = hotplug_slot->private; + struct controller *ctrl = slot->ctrl; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - ctrl = slot->ctrl; - if (ctrl == NULL) - return -ENODEV; - - *value = get_presence_status (ctrl, slot); + *value = get_presence_status(ctrl, slot); return 0; } static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); - struct controller *ctrl; - - if (slot == NULL) - return -ENODEV; + struct slot *slot = hotplug_slot->private; + struct controller *ctrl = slot->ctrl; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - ctrl = slot->ctrl; - if (ctrl == NULL) - return -ENODEV; - *value = ctrl->speed_capability; return 0; @@ -821,18 +765,11 @@ static int get_max_bus_speed (struct hot static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); - struct controller *ctrl; - - if (slot == NULL) - return -ENODEV; + struct slot *slot = hotplug_slot->private; + struct controller *ctrl = slot->ctrl; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - ctrl = slot->ctrl; - if (ctrl == NULL) - return -ENODEV; - *value = ctrl->speed; return 0; @@ -908,11 +845,11 @@ static int cpqhpc_probe(struct pci_dev * case PCI_VENDOR_ID_COMPAQ: if (rev >= 0x13) { /* CIOBX */ ctrl->push_flag = 1; - ctrl->slot_switch_type = 1; // Switch is present - ctrl->push_button = 1; // Pushbutton is present - ctrl->pci_config_space = 1; // Index/data access to working registers 0 = not supported, 1 = supported - ctrl->defeature_PHP = 1; // PHP is supported - ctrl->pcix_support = 1; // PCI-X supported + ctrl->slot_switch_type = 1; + ctrl->push_button = 1; + ctrl->pci_config_space = 1; + ctrl->defeature_PHP = 1; + ctrl->pcix_support = 1; ctrl->pcix_speed_capability = 1; pci_read_config_byte(pdev, 0x41, &bus_cap); if (bus_cap & 0x80) { @@ -942,55 +879,55 @@ static int cpqhpc_probe(struct pci_dev * switch (subsystem_deviceid) { case PCI_SUB_HPC_ID: /* Original 6500/7000 implementation */ - ctrl->slot_switch_type = 1; // Switch is present + ctrl->slot_switch_type = 1; ctrl->speed_capability = PCI_SPEED_33MHz; - ctrl->push_button = 0; // No pushbutton - ctrl->pci_config_space = 1; // Index/data access to working registers 0 = not supported, 1 = supported - ctrl->defeature_PHP = 1; // PHP is supported - ctrl->pcix_support = 0; // PCI-X not supported - ctrl->pcix_speed_capability = 0; // N/A since PCI-X not supported + ctrl->push_button = 0; + ctrl->pci_config_space = 1; + ctrl->defeature_PHP = 1; + ctrl->pcix_support = 0; + ctrl->pcix_speed_capability = 0; break; case PCI_SUB_HPC_ID2: /* First Pushbutton implementation */ ctrl->push_flag = 1; - ctrl->slot_switch_type = 1; // Switch is present + ctrl->slot_switch_type = 1; ctrl->speed_capability = PCI_SPEED_33MHz; - ctrl->push_button = 1; // Pushbutton is present - ctrl->pci_config_space = 1; // Index/data access to working registers 0 = not supported, 1 = supported - ctrl->defeature_PHP = 1; // PHP is supported - ctrl->pcix_support = 0; // PCI-X not supported - ctrl->pcix_speed_capability = 0; // N/A since PCI-X not supported + ctrl->push_button = 1; + ctrl->pci_config_space = 1; + ctrl->defeature_PHP = 1; + ctrl->pcix_support = 0; + ctrl->pcix_speed_capability = 0; break; case PCI_SUB_HPC_ID_INTC: /* Third party (6500/7000) */ - ctrl->slot_switch_type = 1; // Switch is present + ctrl->slot_switch_type = 1; ctrl->speed_capability = PCI_SPEED_33MHz; - ctrl->push_button = 0; // No pushbutton - ctrl->pci_config_space = 1; // Index/data access to working registers 0 = not supported, 1 = supported - ctrl->defeature_PHP = 1; // PHP is supported - ctrl->pcix_support = 0; // PCI-X not supported - ctrl->pcix_speed_capability = 0; // N/A since PCI-X not supported + ctrl->push_button = 0; + ctrl->pci_config_space = 1; + ctrl->defeature_PHP = 1; + ctrl->pcix_support = 0; + ctrl->pcix_speed_capability = 0; break; case PCI_SUB_HPC_ID3: /* First 66 Mhz implementation */ ctrl->push_flag = 1; - ctrl->slot_switch_type = 1; // Switch is present + ctrl->slot_switch_type = 1; ctrl->speed_capability = PCI_SPEED_66MHz; - ctrl->push_button = 1; // Pushbutton is present - ctrl->pci_config_space = 1; // Index/data access to working registers 0 = not supported, 1 = supported - ctrl->defeature_PHP = 1; // PHP is supported - ctrl->pcix_support = 0; // PCI-X not supported - ctrl->pcix_speed_capability = 0; // N/A since PCI-X not supported + ctrl->push_button = 1; + ctrl->pci_config_space = 1; + ctrl->defeature_PHP = 1; + ctrl->pcix_support = 0; + ctrl->pcix_speed_capability = 0; break; case PCI_SUB_HPC_ID4: /* First PCI-X implementation, 100MHz */ ctrl->push_flag = 1; - ctrl->slot_switch_type = 1; // Switch is present + ctrl->slot_switch_type = 1; ctrl->speed_capability = PCI_SPEED_100MHz_PCIX; - ctrl->push_button = 1; // Pushbutton is present - ctrl->pci_config_space = 1; // Index/data access to working registers 0 = not supported, 1 = supported - ctrl->defeature_PHP = 1; // PHP is supported - ctrl->pcix_support = 1; // PCI-X supported + ctrl->push_button = 1; + ctrl->pci_config_space = 1; + ctrl->defeature_PHP = 1; + ctrl->pcix_support = 1; ctrl->pcix_speed_capability = 0; break; default: @@ -1079,33 +1016,41 @@ static int cpqhpc_probe(struct pci_dev * } // Tell the user that we found one. - info("Initializing the PCI hot plug controller residing on PCI bus %d\n", pdev->bus->number); + info("Initializing the PCI hot plug controller residing on PCI bus %d\n", + pdev->bus->number); - dbg ("Hotplug controller capabilities:\n"); - dbg (" speed_capability %d\n", ctrl->speed_capability); - dbg (" slot_switch_type %s\n", ctrl->slot_switch_type == 0 ? "no switch" : "switch present"); - dbg (" defeature_PHP %s\n", ctrl->defeature_PHP == 0 ? "PHP not supported" : "PHP supported"); - dbg (" alternate_base_address %s\n", ctrl->alternate_base_address == 0 ? "not supported" : "supported"); - dbg (" pci_config_space %s\n", ctrl->pci_config_space == 0 ? "not supported" : "supported"); - dbg (" pcix_speed_capability %s\n", ctrl->pcix_speed_capability == 0 ? "not supported" : "supported"); - dbg (" pcix_support %s\n", ctrl->pcix_support == 0 ? "not supported" : "supported"); + dbg("Hotplug controller capabilities:\n"); + dbg(" speed_capability %d\n", ctrl->speed_capability); + dbg(" slot_switch_type %s\n", ctrl->slot_switch_type ? + "switch present" : "no switch"); + dbg(" defeature_PHP %s\n", ctrl->defeature_PHP ? + "PHP supported" : "PHP not supported"); + dbg(" alternate_base_address %s\n", ctrl->alternate_base_address ? + "supported" : "not supported"); + dbg(" pci_config_space %s\n", ctrl->pci_config_space ? + "supported" : "not supported"); + dbg(" pcix_speed_capability %s\n", ctrl->pcix_speed_capability ? + "supported" : "not supported"); + dbg(" pcix_support %s\n", ctrl->pcix_support ? + "supported" : "not supported"); ctrl->pci_dev = pdev; pci_set_drvdata(pdev, ctrl); - /* make our own copy of the pci bus structure, as we like tweaking it a lot */ - ctrl->pci_bus = kmalloc (sizeof (*ctrl->pci_bus), GFP_KERNEL); + /* make our own copy of the pci bus structure, + * as we like tweaking it a lot */ + ctrl->pci_bus = kmalloc(sizeof(*ctrl->pci_bus), GFP_KERNEL); if (!ctrl->pci_bus) { err("out of memory\n"); rc = -ENOMEM; goto err_free_ctrl; } - memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus)); + memcpy(ctrl->pci_bus, pdev->bus, sizeof(*ctrl->pci_bus)); ctrl->bus = pdev->bus->number; ctrl->rev = rev; dbg("bus device function rev: %d %d %d %d\n", ctrl->bus, - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), ctrl->rev); + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), ctrl->rev); init_MUTEX(&ctrl->crit_sect); init_waitqueue_head(&ctrl->queue); @@ -1127,9 +1072,12 @@ static int cpqhpc_probe(struct pci_dev * goto err_free_bus; } - ctrl->hpc_reg = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); + ctrl->hpc_reg = ioremap(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); if (!ctrl->hpc_reg) { - err("cannot remap MMIO region %lx @ %lx\n", pci_resource_len(pdev, 0), pci_resource_start(pdev, 0)); + err("cannot remap MMIO region %lx @ %lx\n", + pci_resource_len(pdev, 0), + pci_resource_start(pdev, 0)); rc = -ENODEV; goto err_free_mem_region; } @@ -1138,21 +1086,25 @@ static int cpqhpc_probe(struct pci_dev * ctrl->speed = get_controller_speed(ctrl); - //************************************************** - // - // Save configuration headers for this and - // subordinate PCI buses - // - //************************************************** + /******************************************************** + * + * Save configuration headers for this and + * subordinate PCI buses + * + ********************************************************/ // find the physical slot number of the first hot plug slot - // Get slot won't work for devices behind bridges, but - // in this case it will always be called for the "base" - // bus/dev/func of a slot. - // CS: this is leveraging the PCIIRQ routing code from the kernel (pci-pc.c: get_irq_routing_table) - rc = get_slot_mapping(ctrl->pci_bus, pdev->bus->number, (readb(ctrl->hpc_reg + SLOT_MASK) >> 4), &(ctrl->first_slot)); - dbg("get_slot_mapping: first_slot = %d, returned = %d\n", ctrl->first_slot, rc); + /* Get slot won't work for devices behind bridges, but + * in this case it will always be called for the "base" + * bus/dev/func of a slot. + * CS: this is leveraging the PCIIRQ routing code from the kernel + * (pci-pc.c: get_irq_routing_table) */ + rc = get_slot_mapping(ctrl->pci_bus, pdev->bus->number, + (readb(ctrl->hpc_reg + SLOT_MASK) >> 4), + &(ctrl->first_slot)); + dbg("get_slot_mapping: first_slot = %d, returned = %d\n", + ctrl->first_slot, rc); if (rc) { err(msg_initialization_err, rc); goto err_iounmap; @@ -1161,7 +1113,8 @@ static int cpqhpc_probe(struct pci_dev * // Store PCI Config Space for all devices on this bus rc = cpqhp_save_config(ctrl, ctrl->bus, readb(ctrl->hpc_reg + SLOT_MASK)); if (rc) { - err("%s: unable to save PCI configuration data, error %d\n", __FUNCTION__, rc); + err("%s: unable to save PCI configuration data, error %d\n", + __FUNCTION__, rc); goto err_iounmap; } @@ -1198,7 +1151,8 @@ static int cpqhpc_probe(struct pci_dev * rc = ctrl_slot_setup(ctrl, smbios_start, smbios_table); if (rc) { err(msg_initialization_err, 6); - err("%s: unable to save PCI configuration data, error %d\n", __FUNCTION__, rc); + err("%s: unable to save PCI configuration data, error %d\n", + __FUNCTION__, rc); goto err_iounmap; } @@ -1209,7 +1163,8 @@ static int cpqhpc_probe(struct pci_dev * dbg("HPC interrupt = %d \n", ctrl->interrupt); if (request_irq(ctrl->interrupt, cpqhp_ctrl_intr, SA_SHIRQ, MY_NAME, ctrl)) { - err("Can't get irq %d for the hotplug pci controller\n", ctrl->interrupt); + err("Can't get irq %d for the hotplug pci controller\n", + ctrl->interrupt); rc = -ENODEV; goto err_iounmap; } @@ -1265,8 +1220,8 @@ static int cpqhpc_probe(struct pci_dev * if (!power_mode) { if (!func->is_a_board) { - green_LED_off (ctrl, hp_slot); - slot_disable (ctrl, hp_slot); + green_LED_off(ctrl, hp_slot); + slot_disable(ctrl, hp_slot); } } @@ -1277,7 +1232,7 @@ static int cpqhpc_probe(struct pci_dev * if (!power_mode) { set_SOGO(ctrl); // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); + wait_for_ctrl_irq(ctrl); } rc = init_SERR(ctrl); @@ -1290,7 +1245,7 @@ static int cpqhpc_probe(struct pci_dev * // Done with exclusive hardware access up(&ctrl->crit_sect); - cpqhp_create_ctrl_files (ctrl); + cpqhp_create_ctrl_files(ctrl); return 0; @@ -1350,35 +1305,36 @@ static int one_time_init(void) compaq_nvram_init(cpqhp_rom_start); /* Map smbios table entry point structure */ - smbios_table = detect_SMBIOS_pointer(cpqhp_rom_start, cpqhp_rom_start + ROM_PHY_LEN); + smbios_table = detect_SMBIOS_pointer(cpqhp_rom_start, + cpqhp_rom_start + ROM_PHY_LEN); if (!smbios_table) { err ("Could not find the SMBIOS pointer in memory\n"); retval = -EIO; - goto error; + goto error_rom_start; } - smbios_start = ioremap(readl(smbios_table + ST_ADDRESS), readw(smbios_table + ST_LENGTH)); + smbios_start = ioremap(readl(smbios_table + ST_ADDRESS), + readw(smbios_table + ST_LENGTH)); if (!smbios_start) { err ("Could not ioremap memory region taken from SMBIOS values\n"); retval = -EIO; - goto error; + goto error_smbios_start; } initialized = 1; return retval; +error_smbios_start: + iounmap(smbios_start); +error_rom_start: + iounmap(cpqhp_rom_start); error: - if (cpqhp_rom_start) - iounmap(cpqhp_rom_start); - if (smbios_start) - iounmap(smbios_start); - return retval; } -static void unload_cpqphpd(void) +static void __exit unload_cpqphpd(void) { struct pci_func *next; struct pci_func *TempSlot; @@ -1512,7 +1468,7 @@ MODULE_DEVICE_TABLE(pci, hpcd_pci_tbl); static struct pci_driver cpqhpc_driver = { - .name = "pci_hotplug", + .name = "compaq_pci_hotplug", .id_table = hpcd_pci_tbl, .probe = cpqhpc_probe, /* remove: cpqhpc_remove_one, */ @@ -1526,12 +1482,10 @@ static int __init cpqhpc_init(void) cpqhp_debug = debug; + info (DRIVER_DESC " version: " DRIVER_VERSION "\n"); result = pci_module_init(&cpqhpc_driver); dbg("pci_module_init = %d\n", result); - if (result) - return result; - info (DRIVER_DESC " version: " DRIVER_VERSION "\n"); - return 0; + return result; } --- linux-2.6.6/drivers/pci/hotplug/cpqphp_ctrl.c 2004-03-10 20:41:29.000000000 -0800 +++ 25/drivers/pci/hotplug/cpqphp_ctrl.c 2004-05-10 01:19:04.017128360 -0700 @@ -39,8 +39,10 @@ #include #include "cpqphp.h" -static u32 configure_new_device(struct controller* ctrl, struct pci_func *func,u8 behind_bridge, struct resource_lists *resources); -static int configure_new_function(struct controller* ctrl, struct pci_func *func,u8 behind_bridge, struct resource_lists *resources); +static u32 configure_new_device(struct controller* ctrl, struct pci_func *func, + u8 behind_bridge, struct resource_lists *resources); +static int configure_new_function(struct controller* ctrl, struct pci_func *func, + u8 behind_bridge, struct resource_lists *resources); static void interrupt_event_handler(struct controller *ctrl); static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */ @@ -53,7 +55,7 @@ static struct semaphore delay_sem; static wait_queue_head_t delay_wait; /* delay is in jiffies to wait for */ -static void long_delay (int delay) +static void long_delay(int delay) { DECLARE_WAITQUEUE(wait, current); @@ -64,7 +66,7 @@ static void long_delay (int delay) */ down (&delay_sem); - init_waitqueue_head (&delay_wait); + init_waitqueue_head(&delay_wait); add_wait_queue(&delay_wait, &wait); set_current_state(TASK_INTERRUPTIBLE); @@ -72,11 +74,11 @@ static void long_delay (int delay) remove_wait_queue(&delay_wait, &wait); set_current_state(TASK_RUNNING); - up (&delay_sem); + up(&delay_sem); } -//FIXME: The following line needs to be somewhere else... +/* FIXME: The following line needs to be somewhere else... */ #define WRONG_BUS_FREQUENCY 0x07 static u8 handle_switch_change(u8 change, struct controller * ctrl) { @@ -89,18 +91,19 @@ static u8 handle_switch_change(u8 change if (!change) return 0; - // Switch Change + /* Switch Change */ dbg("cpqsbd: Switch interrupt received.\n"); for (hp_slot = 0; hp_slot < 6; hp_slot++) { if (change & (0x1L << hp_slot)) { - //********************************* - // this one changed. - //********************************* - func = cpqhp_slot_find(ctrl->bus, (hp_slot + ctrl->slot_device_offset), 0); + /********************************** + * this one changed. + **********************************/ + func = cpqhp_slot_find(ctrl->bus, + (hp_slot + ctrl->slot_device_offset), 0); - //this is the structure that tells the worker thread - //what to do + /* this is the structure that tells the worker thread + *what to do */ taskInfo = &(ctrl->event_queue[ctrl->next_event]); ctrl->next_event = (ctrl->next_event + 1) % 10; taskInfo->hp_slot = hp_slot; @@ -112,17 +115,17 @@ static u8 handle_switch_change(u8 change func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02; if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) { - //********************************* - // Switch opened - //********************************* + /********************************** + * Switch opened + **********************************/ func->switch_save = 0; taskInfo->event_type = INT_SWITCH_OPEN; } else { - //********************************* - // Switch closed - //********************************* + /********************************** + * Switch closed + **********************************/ func->switch_save = 0x10; @@ -134,18 +137,14 @@ static u8 handle_switch_change(u8 change return rc; } - -/* - * cpqhp_find_slot +/** + * cpqhp_find_slot: find the struct slot of given device + * @ctrl: scan lots of this controller + * @device: the device id to find */ -struct slot *cpqhp_find_slot (struct controller * ctrl, u8 device) +struct slot *cpqhp_find_slot(struct controller *ctrl, u8 device) { - struct slot *slot; - - if (!ctrl) - return NULL; - - slot = ctrl->slot; + struct slot *slot = ctrl->slot; while (slot && (slot->device != device)) { slot = slot->next; @@ -168,18 +167,19 @@ static u8 handle_presence_change(u16 cha if (!change) return 0; - //********************************* - // Presence Change - //********************************* + /********************************** + * Presence Change + **********************************/ dbg("cpqsbd: Presence/Notify input change.\n"); dbg(" Changed bits are 0x%4.4x\n", change ); for (hp_slot = 0; hp_slot < 6; hp_slot++) { if (change & (0x0101 << hp_slot)) { - //********************************* - // this one changed. - //********************************* - func = cpqhp_slot_find(ctrl->bus, (hp_slot + ctrl->slot_device_offset), 0); + /********************************** + * this one changed. + **********************************/ + func = cpqhp_slot_find(ctrl->bus, + (hp_slot + ctrl->slot_device_offset), 0); taskInfo = &(ctrl->event_queue[ctrl->next_event]); ctrl->next_event = (ctrl->next_event + 1) % 10; @@ -191,55 +191,51 @@ static u8 handle_presence_change(u16 cha if (!p_slot) return 0; - // If the switch closed, must be a button - // If not in button mode, nevermind + /* If the switch closed, must be a button + * If not in button mode, nevermind */ if (func->switch_save && (ctrl->push_button == 1)) { temp_word = ctrl->ctrl_int_comp >> 16; temp_byte = (temp_word >> hp_slot) & 0x01; temp_byte |= (temp_word >> (hp_slot + 7)) & 0x02; if (temp_byte != func->presence_save) { - //********************************* - // button Pressed (doesn't do anything) - //********************************* + /************************************** + * button Pressed (doesn't do anything) + **************************************/ dbg("hp_slot %d button pressed\n", hp_slot); taskInfo->event_type = INT_BUTTON_PRESS; } else { - //********************************* - // button Released - TAKE ACTION!!!! - //********************************* + /********************************** + * button Released - TAKE ACTION!!!! + **********************************/ dbg("hp_slot %d button released\n", hp_slot); taskInfo->event_type = INT_BUTTON_RELEASE; - // Cancel if we are still blinking + /* Cancel if we are still blinking */ if ((p_slot->state == BLINKINGON_STATE) || (p_slot->state == BLINKINGOFF_STATE)) { taskInfo->event_type = INT_BUTTON_CANCEL; dbg("hp_slot %d button cancel\n", hp_slot); } else if ((p_slot->state == POWERON_STATE) || (p_slot->state == POWEROFF_STATE)) { - //info(msg_button_ignore, p_slot->number); + /* info(msg_button_ignore, p_slot->number); */ taskInfo->event_type = INT_BUTTON_IGNORE; dbg("hp_slot %d button ignore\n", hp_slot); } } } else { - // Switch is open, assume a presence change - // Save the presence state + /* Switch is open, assume a presence change + * Save the presence state */ temp_word = ctrl->ctrl_int_comp >> 16; func->presence_save = (temp_word >> hp_slot) & 0x01; func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02; if ((!(ctrl->ctrl_int_comp & (0x010000 << hp_slot))) || (!(ctrl->ctrl_int_comp & (0x01000000 << hp_slot)))) { - //********************************* - // Present - //********************************* + /* Present */ taskInfo->event_type = INT_PRESENCE_ON; } else { - //********************************* - // Not Present - //********************************* + /* Not Present */ taskInfo->event_type = INT_PRESENCE_OFF; } } @@ -260,18 +256,19 @@ static u8 handle_power_fault(u8 change, if (!change) return 0; - //********************************* - // power fault - //********************************* + /********************************** + * power fault + **********************************/ info("power fault interrupt\n"); for (hp_slot = 0; hp_slot < 6; hp_slot++) { if (change & (0x01 << hp_slot)) { - //********************************* - // this one changed. - //********************************* - func = cpqhp_slot_find(ctrl->bus, (hp_slot + ctrl->slot_device_offset), 0); + /********************************** + * this one changed. + **********************************/ + func = cpqhp_slot_find(ctrl->bus, + (hp_slot + ctrl->slot_device_offset), 0); taskInfo = &(ctrl->event_queue[ctrl->next_event]); ctrl->next_event = (ctrl->next_event + 1) % 10; @@ -280,16 +277,16 @@ static u8 handle_power_fault(u8 change, rc++; if (ctrl->ctrl_int_comp & (0x00000100 << hp_slot)) { - //********************************* - // power fault Cleared - //********************************* + /********************************** + * power fault Cleared + **********************************/ func->status = 0x00; taskInfo->event_type = INT_POWER_FAULT_CLEAR; } else { - //********************************* - // power fault - //********************************* + /********************************** + * power fault + **********************************/ taskInfo->event_type = INT_POWER_FAULT; if (ctrl->rev < 4) { @@ -297,18 +294,20 @@ static u8 handle_power_fault(u8 change, green_LED_off (ctrl, hp_slot); set_SOGO (ctrl); - // this is a fatal condition, we want to crash the - // machine to protect from data corruption - // simulated_NMI shouldn't ever return - //FIXME - //simulated_NMI(hp_slot, ctrl); - - //The following code causes a software crash just in - //case simulated_NMI did return - //FIXME - //panic(msg_power_fault); + /* this is a fatal condition, we want + * to crash the machine to protect from + * data corruption. simulated_NMI + * shouldn't ever return */ + /* FIXME + simulated_NMI(hp_slot, ctrl); */ + + /* The following code causes a software + * crash just in case simulated_NMI did + * return */ + /*FIXME + panic(msg_power_fault); */ } else { - // set power fault status for this board + /* set power fault status for this board */ func->status = 0xFF; info("power fault bit %x set\n", hp_slot); } @@ -320,11 +319,9 @@ static u8 handle_power_fault(u8 change, } -/* - * sort_by_size - * - * Sorts nodes on the list by their length. - * Smallest first. +/** + * sort_by_size: sort nodes on the list by their length, smallest first. + * @head: list to sort * */ static int sort_by_size(struct pci_resource **head) @@ -334,15 +331,15 @@ static int sort_by_size(struct pci_resou int out_of_order = 1; if (!(*head)) - return(1); + return 1; if (!((*head)->next)) - return(0); + return 0; while (out_of_order) { out_of_order = 0; - // Special case for swapping list head + /* Special case for swapping list head */ if (((*head)->next) && ((*head)->length > (*head)->next->length)) { out_of_order++; @@ -365,17 +362,15 @@ static int sort_by_size(struct pci_resou } else current_res = current_res->next; } - } // End of out_of_order loop + } /* End of out_of_order loop */ - return(0); + return 0; } -/* - * sort_by_max_size - * - * Sorts nodes on the list by their length. - * Largest first. +/** + * sort_by_max_size: sort nodes on the list by their length, largest first. + * @head: list to sort * */ static int sort_by_max_size(struct pci_resource **head) @@ -385,15 +380,15 @@ static int sort_by_max_size(struct pci_r int out_of_order = 1; if (!(*head)) - return(1); + return 1; if (!((*head)->next)) - return(0); + return 0; while (out_of_order) { out_of_order = 0; - // Special case for swapping list head + /* Special case for swapping list head */ if (((*head)->next) && ((*head)->length < (*head)->next->length)) { out_of_order++; @@ -416,19 +411,18 @@ static int sort_by_max_size(struct pci_r } else current_res = current_res->next; } - } // End of out_of_order loop + } /* End of out_of_order loop */ - return(0); + return 0; } -/* - * do_pre_bridge_resource_split - * - * Returns zero or one node of resources that aren't in use +/** + * do_pre_bridge_resource_split: find node of resources that are unused * */ -static struct pci_resource *do_pre_bridge_resource_split (struct pci_resource **head, struct pci_resource **orig_head, u32 alignment) +static struct pci_resource *do_pre_bridge_resource_split(struct pci_resource **head, + struct pci_resource **orig_head, u32 alignment) { struct pci_resource *prevnode = NULL; struct pci_resource *node; @@ -438,32 +432,32 @@ static struct pci_resource *do_pre_bridg dbg("do_pre_bridge_resource_split\n"); if (!(*head) || !(*orig_head)) - return(NULL); + return NULL; rc = cpqhp_resource_sort_and_combine(head); if (rc) - return(NULL); + return NULL; if ((*head)->base != (*orig_head)->base) - return(NULL); + return NULL; if ((*head)->length == (*orig_head)->length) - return(NULL); + return NULL; - // If we got here, there the bridge requires some of the resource, but - // we may be able to split some off of the front + /* If we got here, there the bridge requires some of the resource, but + * we may be able to split some off of the front */ node = *head; if (node->length & (alignment -1)) { - // this one isn't an aligned length, so we'll make a new entry - // and split it up. - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + /* this one isn't an aligned length, so we'll make a new entry + * and split it up. */ + split_node = kmalloc(sizeof(*split_node), GFP_KERNEL); if (!split_node) - return(NULL); + return NULL; temp_dword = (node->length | (alignment-1)) + 1 - alignment; @@ -473,52 +467,45 @@ static struct pci_resource *do_pre_bridg node->length -= temp_dword; node->base += split_node->length; - // Put it in the list + /* Put it in the list */ *head = split_node; split_node->next = node; } - if (node->length < alignment) { - return(NULL); - } + if (node->length < alignment) + return NULL; - // Now unlink it + /* Now unlink it */ if (*head == node) { *head = node->next; - node->next = NULL; } else { prevnode = *head; while (prevnode->next != node) prevnode = prevnode->next; prevnode->next = node->next; - node->next = NULL; } + node->next = NULL; - return(node); + return node; } -/* - * do_bridge_resource_split - * - * Returns zero or one node of resources that aren't in use +/** + * do_bridge_resource_split: find one node of resources that aren't in use * */ -static struct pci_resource *do_bridge_resource_split (struct pci_resource **head, u32 alignment) +static struct pci_resource *do_bridge_resource_split(struct pci_resource **head, u32 alignment) { struct pci_resource *prevnode = NULL; struct pci_resource *node; u32 rc; u32 temp_dword; - if (!(*head)) - return(NULL); - rc = cpqhp_resource_sort_and_combine(head); if (rc) - return(NULL); + return NULL; node = *head; @@ -528,44 +515,41 @@ static struct pci_resource *do_bridge_re kfree(prevnode); } - if (node->length < alignment) { - kfree(node); - return(NULL); - } + if (node->length < alignment) + goto error; if (node->base & (alignment - 1)) { - // Short circuit if adjusted size is too small + /* Short circuit if adjusted size is too small */ temp_dword = (node->base | (alignment-1)) + 1; - if ((node->length - (temp_dword - node->base)) < alignment) { - kfree(node); - return(NULL); - } + if ((node->length - (temp_dword - node->base)) < alignment) + goto error; node->length -= (temp_dword - node->base); node->base = temp_dword; } - if (node->length & (alignment - 1)) { - // There's stuff in use after this node - kfree(node); - return(NULL); - } - - return(node); + if (node->length & (alignment - 1)) + /* There's stuff in use after this node */ + goto error; + + return node; +error: + kfree(node); + return NULL; } -/* - * get_io_resource +/** + * get_io_resource: find first node of given size not in ISA aliasing window. + * @head: list to search + * @size: size of node to find, must be a power of two. * - * this function sorts the resource list by size and then - * returns the first node of "size" length that is not in the - * ISA aliasing window. If it finds a node larger than "size" - * it will split it up. + * Description: this function sorts the resource list by size and then returns + * returns the first node of "size" length that is not in the ISA aliasing + * window. If it finds a node larger than "size" it will split it up. * - * size must be a power of two. */ -static struct pci_resource *get_io_resource (struct pci_resource **head, u32 size) +static struct pci_resource *get_io_resource(struct pci_resource **head, u32 size) { struct pci_resource *prevnode; struct pci_resource *node; @@ -573,66 +557,66 @@ static struct pci_resource *get_io_resou u32 temp_dword; if (!(*head)) - return(NULL); + return NULL; if ( cpqhp_resource_sort_and_combine(head) ) - return(NULL); + return NULL; if ( sort_by_size(head) ) - return(NULL); + return NULL; for (node = *head; node; node = node->next) { if (node->length < size) continue; if (node->base & (size - 1)) { - // this one isn't base aligned properly - // so we'll make a new entry and split it up + /* this one isn't base aligned properly + * so we'll make a new entry and split it up */ temp_dword = (node->base | (size-1)) + 1; - // Short circuit if adjusted size is too small + /* Short circuit if adjusted size is too small */ if ((node->length - (temp_dword - node->base)) < size) continue; - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + split_node = kmalloc(sizeof(*split_node), GFP_KERNEL); if (!split_node) - return(NULL); + return NULL; split_node->base = node->base; split_node->length = temp_dword - node->base; node->base = temp_dword; node->length -= split_node->length; - // Put it in the list + /* Put it in the list */ split_node->next = node->next; node->next = split_node; - } // End of non-aligned base + } /* End of non-aligned base */ - // Don't need to check if too small since we already did + /* Don't need to check if too small since we already did */ if (node->length > size) { - // this one is longer than we need - // so we'll make a new entry and split it up - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + /* this one is longer than we need + * so we'll make a new entry and split it up */ + split_node = kmalloc(sizeof(*split_node), GFP_KERNEL); if (!split_node) - return(NULL); + return NULL; split_node->base = node->base + size; split_node->length = node->length - size; node->length = size; - // Put it in the list + /* Put it in the list */ split_node->next = node->next; node->next = split_node; - } // End of too big on top end + } /* End of too big on top end */ - // For IO make sure it's not in the ISA aliasing space + /* For IO make sure it's not in the ISA aliasing space */ if (node->base & 0x300L) continue; - // If we got here, then it is the right size - // Now take it out of the list + /* If we got here, then it is the right size + * Now take it out of the list and break */ if (*head == node) { *head = node->next; } else { @@ -643,92 +627,87 @@ static struct pci_resource *get_io_resou prevnode->next = node->next; } node->next = NULL; - // Stop looping break; } - return(node); + return node; } -/* - * get_max_resource +/** + * get_max_resource: get largest node which has at least the given size. + * @head: the list to search the node in + * @size: the minimum size of the node to find * - * Gets the largest node that is at least "size" big from the + * Description: Gets the largest node that is at least "size" big from the * list pointed to by head. It aligns the node on top and bottom * to "size" alignment before returning it. */ -static struct pci_resource *get_max_resource (struct pci_resource **head, u32 size) +static struct pci_resource *get_max_resource(struct pci_resource **head, u32 size) { struct pci_resource *max; struct pci_resource *temp; struct pci_resource *split_node; u32 temp_dword; - if (!(*head)) - return(NULL); - if (cpqhp_resource_sort_and_combine(head)) - return(NULL); + return NULL; if (sort_by_max_size(head)) - return(NULL); - - for (max = *head;max; max = max->next) { + return NULL; - // If not big enough we could probably just bail, - // instead we'll continue to the next. + for (max = *head; max; max = max->next) { + /* If not big enough we could probably just bail, + * instead we'll continue to the next. */ if (max->length < size) continue; if (max->base & (size - 1)) { - // this one isn't base aligned properly - // so we'll make a new entry and split it up + /* this one isn't base aligned properly + * so we'll make a new entry and split it up */ temp_dword = (max->base | (size-1)) + 1; - // Short circuit if adjusted size is too small + /* Short circuit if adjusted size is too small */ if ((max->length - (temp_dword - max->base)) < size) continue; - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + split_node = kmalloc(sizeof(*split_node), GFP_KERNEL); if (!split_node) - return(NULL); + return NULL; split_node->base = max->base; split_node->length = temp_dword - max->base; max->base = temp_dword; max->length -= split_node->length; - // Put it next in the list split_node->next = max->next; max->next = split_node; } if ((max->base + max->length) & (size - 1)) { - // this one isn't end aligned properly at the top - // so we'll make a new entry and split it up - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + /* this one isn't end aligned properly at the top + * so we'll make a new entry and split it up */ + split_node = kmalloc(sizeof(*split_node), GFP_KERNEL); if (!split_node) - return(NULL); + return NULL; temp_dword = ((max->base + max->length) & ~(size - 1)); split_node->base = temp_dword; split_node->length = max->length + max->base - split_node->base; max->length -= split_node->length; - // Put it in the list split_node->next = max->next; max->next = split_node; } - // Make sure it didn't shrink too much when we aligned it + /* Make sure it didn't shrink too much when we aligned it */ if (max->length < size) continue; - // Now take it out of the list - temp = (struct pci_resource*) *head; + /* Now take it out of the list */ + temp = *head; if (temp == max) { *head = max->next; } else { @@ -740,38 +719,36 @@ static struct pci_resource *get_max_reso } max->next = NULL; - return(max); + break; } - // If we get here, we couldn't find one - return(NULL); + return max; } -/* - * get_resource +/** + * get_resource: find resource of given size and split up larger ones. + * @head: the list to search for resources + * @size: the size limit to use * - * this function sorts the resource list by size and then + * Description: This function sorts the resource list by size and then * returns the first node of "size" length. If it finds a node * larger than "size" it will split it up. * * size must be a power of two. */ -static struct pci_resource *get_resource (struct pci_resource **head, u32 size) +static struct pci_resource *get_resource(struct pci_resource **head, u32 size) { struct pci_resource *prevnode; struct pci_resource *node; struct pci_resource *split_node; u32 temp_dword; - if (!(*head)) - return(NULL); - - if ( cpqhp_resource_sort_and_combine(head) ) - return(NULL); + if (cpqhp_resource_sort_and_combine(head)) + return NULL; - if ( sort_by_size(head) ) - return(NULL); + if (sort_by_size(head)) + return NULL; for (node = *head; node; node = node->next) { dbg("%s: req_size =%x node=%p, base=%x, length=%x\n", @@ -781,51 +758,50 @@ static struct pci_resource *get_resource if (node->base & (size - 1)) { dbg("%s: not aligned\n", __FUNCTION__); - // this one isn't base aligned properly - // so we'll make a new entry and split it up + /* this one isn't base aligned properly + * so we'll make a new entry and split it up */ temp_dword = (node->base | (size-1)) + 1; - // Short circuit if adjusted size is too small + /* Short circuit if adjusted size is too small */ if ((node->length - (temp_dword - node->base)) < size) continue; - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + split_node = kmalloc(sizeof(*split_node), GFP_KERNEL); if (!split_node) - return(NULL); + return NULL; split_node->base = node->base; split_node->length = temp_dword - node->base; node->base = temp_dword; node->length -= split_node->length; - // Put it in the list split_node->next = node->next; node->next = split_node; - } // End of non-aligned base + } /* End of non-aligned base */ - // Don't need to check if too small since we already did + /* Don't need to check if too small since we already did */ if (node->length > size) { dbg("%s: too big\n", __FUNCTION__); - // this one is longer than we need - // so we'll make a new entry and split it up - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + /* this one is longer than we need + * so we'll make a new entry and split it up */ + split_node = kmalloc(sizeof(*split_node), GFP_KERNEL); if (!split_node) - return(NULL); + return NULL; split_node->base = node->base + size; split_node->length = node->length - size; node->length = size; - // Put it in the list + /* Put it in the list */ split_node->next = node->next; node->next = split_node; - } // End of too big on top end + } /* End of too big on top end */ dbg("%s: got one!!!\n", __FUNCTION__); - // If we got here, then it is the right size - // Now take it out of the list + /* If we got here, then it is the right size + * Now take it out of the list */ if (*head == node) { *head = node->next; } else { @@ -836,17 +812,17 @@ static struct pci_resource *get_resource prevnode->next = node->next; } node->next = NULL; - // Stop looping break; } - return(node); + return node; } -/* - * cpqhp_resource_sort_and_combine +/** + * cpqhp_resource_sort_and_combine: sort nodes by base addresses and clean up. + * @head: the list to sort and clean up * - * Sorts all of the nodes in the list in ascending order by + * Description: Sorts all of the nodes in the list in ascending order by * their base addresses. Also does garbage collection by * combining adjacent nodes. * @@ -861,19 +837,19 @@ int cpqhp_resource_sort_and_combine(stru dbg("%s: head = %p, *head = %p\n", __FUNCTION__, head, *head); if (!(*head)) - return(1); + return 1; dbg("*head->next = %p\n",(*head)->next); if (!(*head)->next) - return(0); /* only one item on the list, already sorted! */ + return 0; /* only one item on the list, already sorted! */ dbg("*head->base = 0x%x\n",(*head)->base); dbg("*head->next->base = 0x%x\n",(*head)->next->base); while (out_of_order) { out_of_order = 0; - // Special case for swapping list head + /* Special case for swapping list head */ if (((*head)->next) && ((*head)->base > (*head)->next->base)) { node1 = *head; @@ -896,13 +872,13 @@ int cpqhp_resource_sort_and_combine(stru } else node1 = node1->next; } - } // End of out_of_order loop + } /* End of out_of_order loop */ node1 = *head; while (node1 && node1->next) { if ((node1->base + node1->length) == node1->next->base) { - // Combine + /* Combine */ dbg("8..\n"); node1->length += node1->next->length; node2 = node1->next; @@ -912,7 +888,7 @@ int cpqhp_resource_sort_and_combine(stru node1 = node1->next; } - return(0); + return 0; } @@ -927,23 +903,23 @@ irqreturn_t cpqhp_ctrl_intr(int IRQ, voi misc = readw(ctrl->hpc_reg + MISC); - //********************************* - // Check to see if it was our interrupt - //********************************* + /*************************************** + * Check to see if it was our interrupt + ***************************************/ if (!(misc & 0x000C)) { return IRQ_NONE; } if (misc & 0x0004) { - //********************************* - // Serial Output interrupt Pending - //********************************* + /********************************** + * Serial Output interrupt Pending + **********************************/ - // Clear the interrupt + /* Clear the interrupt */ misc |= 0x0004; writew(misc, ctrl->hpc_reg + MISC); - // Read to clear posted writes + /* Read to clear posted writes */ misc = readw(ctrl->hpc_reg + MISC); dbg ("%s - waking up\n", __FUNCTION__); @@ -951,21 +927,20 @@ irqreturn_t cpqhp_ctrl_intr(int IRQ, voi } if (misc & 0x0008) { - // General-interrupt-input interrupt Pending + /* General-interrupt-input interrupt Pending */ Diff = readl(ctrl->hpc_reg + INT_INPUT_CLEAR) ^ ctrl->ctrl_int_comp; ctrl->ctrl_int_comp = readl(ctrl->hpc_reg + INT_INPUT_CLEAR); - // Clear the interrupt + /* Clear the interrupt */ writel(Diff, ctrl->hpc_reg + INT_INPUT_CLEAR); - // Read it back to clear any posted writes + /* Read it back to clear any posted writes */ temp_dword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR); - if (!Diff) { - // Clear all interrupts + if (!Diff) + /* Clear all interrupts */ writel(0xFFFFFFFF, ctrl->hpc_reg + INT_INPUT_CLEAR); - } schedule_flag += handle_switch_change((u8)(Diff & 0xFFL), ctrl); schedule_flag += handle_presence_change((u16)((Diff & 0xFFFF0000L) >> 16), ctrl); @@ -1000,12 +975,12 @@ struct pci_func *cpqhp_slot_create(u8 bu struct pci_func *new_slot; struct pci_func *next; - new_slot = (struct pci_func *) kmalloc(sizeof(struct pci_func), GFP_KERNEL); + new_slot = kmalloc(sizeof(*new_slot), GFP_KERNEL); if (new_slot == NULL) { - // I'm not dead yet! - // You will be. - return(new_slot); + /* I'm not dead yet! + * You will be. */ + return new_slot; } memset(new_slot, 0, sizeof(struct pci_func)); @@ -1021,11 +996,11 @@ struct pci_func *cpqhp_slot_create(u8 bu next = next->next; next->next = new_slot; } - return(new_slot); + return new_slot; } -/* +/** * slot_remove - Removes a node from the linked list of slots. * @old_slot: slot to remove * @@ -1036,19 +1011,19 @@ static int slot_remove(struct pci_func * struct pci_func *next; if (old_slot == NULL) - return(1); + return 1; next = cpqhp_slot_list[old_slot->bus]; if (next == NULL) { - return(1); + return 1; } if (next == old_slot) { cpqhp_slot_list[old_slot->bus] = old_slot->next; cpqhp_destroy_board_resources(old_slot); kfree(old_slot); - return(0); + return 0; } while ((next->next != old_slot) && (next->next != NULL)) { @@ -1059,9 +1034,9 @@ static int slot_remove(struct pci_func * next->next = old_slot->next; cpqhp_destroy_board_resources(old_slot); kfree(old_slot); - return(0); + return 0; } else - return(2); + return 2; } @@ -1077,9 +1052,6 @@ static int bridge_slot_remove(struct pci u8 tempBus; struct pci_func *next; - if (bridge == NULL) - return(1); - secondaryBus = (bridge->config_space[0x06] >> 8) & 0xFF; subordinateBus = (bridge->config_space[0x06] >> 16) & 0xFF; @@ -1093,26 +1065,23 @@ static int bridge_slot_remove(struct pci next = cpqhp_slot_list[bridge->bus]; - if (next == NULL) { - return(1); - } + if (next == NULL) + return 1; if (next == bridge) { cpqhp_slot_list[bridge->bus] = bridge->next; - kfree(bridge); - return(0); + goto out; } - while ((next->next != bridge) && (next->next != NULL)) { + while ((next->next != bridge) && (next->next != NULL)) next = next->next; - } - if (next->next == bridge) { - next->next = bridge->next; - kfree(bridge); - return(0); - } else - return(2); + if (next->next != bridge) + return 2; + next->next = bridge->next; +out: + kfree(bridge); + return 0; } @@ -1132,7 +1101,7 @@ struct pci_func *cpqhp_slot_find(u8 bus, func = cpqhp_slot_list[bus]; if ((func == NULL) || ((func->device == device) && (index == 0))) - return(func); + return func; if (func->device == device) found++; @@ -1144,18 +1113,18 @@ struct pci_func *cpqhp_slot_find(u8 bus, found++; if (found == index) - return(func); + return func; } - return(NULL); + return NULL; } -// DJZ: I don't think is_bridge will work as is. -//FIXME +/* DJZ: I don't think is_bridge will work as is. + * FIXME */ static int is_bridge(struct pci_func * func) { - // Check the header type + /* Check the header type */ if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01) return 1; else @@ -1163,6 +1132,138 @@ static int is_bridge(struct pci_func * f } +/** + * set_controller_speed - set the frequency and/or mode of a specific + * controller segment. + * + * @ctrl: controller to change frequency/mode for. + * @adapter_speed: the speed of the adapter we want to match. + * @hp_slot: the slot number where the adapter is installed. + * + * Returns 0 if we successfully change frequency and/or mode to match the + * adapter speed. + * + */ +static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_slot) +{ + struct slot *slot; + u8 reg; + u8 slot_power = readb(ctrl->hpc_reg + SLOT_POWER); + u16 reg16; + u32 leds = readl(ctrl->hpc_reg + LED_CONTROL); + + if (ctrl->speed == adapter_speed) + return 0; + + /* We don't allow freq/mode changes if we find another adapter running + * in another slot on this controller */ + for(slot = ctrl->slot; slot; slot = slot->next) { + if (slot->device == (hp_slot + ctrl->slot_device_offset)) + continue; + if (!slot->hotplug_slot && !slot->hotplug_slot->info) + continue; + if (slot->hotplug_slot->info->adapter_status == 0) + continue; + /* If another adapter is running on the same segment but at a + * lower speed/mode, we allow the new adapter to function at + * this rate if supported */ + if (ctrl->speed < adapter_speed) + return 0; + + return 1; + } + + /* If the controller doesn't support freq/mode changes and the + * controller is running at a higher mode, we bail */ + if ((ctrl->speed > adapter_speed) && (!ctrl->pcix_speed_capability)) + return 1; + + /* But we allow the adapter to run at a lower rate if possible */ + if ((ctrl->speed < adapter_speed) && (!ctrl->pcix_speed_capability)) + return 0; + + /* We try to set the max speed supported by both the adapter and + * controller */ + if (ctrl->speed_capability < adapter_speed) { + if (ctrl->speed == ctrl->speed_capability) + return 0; + adapter_speed = ctrl->speed_capability; + } + + writel(0x0L, ctrl->hpc_reg + LED_CONTROL); + writeb(0x00, ctrl->hpc_reg + SLOT_ENABLE); + + set_SOGO(ctrl); + wait_for_ctrl_irq(ctrl); + + if (adapter_speed != PCI_SPEED_133MHz_PCIX) + reg = 0xF5; + else + reg = 0xF4; + pci_write_config_byte(ctrl->pci_dev, 0x41, reg); + + reg16 = readw(ctrl->hpc_reg + NEXT_CURR_FREQ); + reg16 &= ~0x000F; + switch(adapter_speed) { + case(PCI_SPEED_133MHz_PCIX): + reg = 0x75; + reg16 |= 0xB; + break; + case(PCI_SPEED_100MHz_PCIX): + reg = 0x74; + reg16 |= 0xA; + break; + case(PCI_SPEED_66MHz_PCIX): + reg = 0x73; + reg16 |= 0x9; + break; + case(PCI_SPEED_66MHz): + reg = 0x73; + reg16 |= 0x1; + break; + default: /* 33MHz PCI 2.2 */ + reg = 0x71; + break; + + } + reg16 |= 0xB << 12; + writew(reg16, ctrl->hpc_reg + NEXT_CURR_FREQ); + + mdelay(5); + + /* Reenable interrupts */ + writel(0, ctrl->hpc_reg + INT_MASK); + + pci_write_config_byte(ctrl->pci_dev, 0x41, reg); + + /* Restart state machine */ + reg = ~0xF; + pci_read_config_byte(ctrl->pci_dev, 0x43, ®); + pci_write_config_byte(ctrl->pci_dev, 0x43, reg); + + /* Only if mode change...*/ + if (((ctrl->speed == PCI_SPEED_66MHz) && (adapter_speed == PCI_SPEED_66MHz_PCIX)) || + ((ctrl->speed == PCI_SPEED_66MHz_PCIX) && (adapter_speed == PCI_SPEED_66MHz))) + set_SOGO(ctrl); + + wait_for_ctrl_irq(ctrl); + mdelay(1100); + + /* Restore LED/Slot state */ + writel(leds, ctrl->hpc_reg + LED_CONTROL); + writeb(slot_power, ctrl->hpc_reg + SLOT_ENABLE); + + set_SOGO(ctrl); + wait_for_ctrl_irq(ctrl); + + ctrl->speed = adapter_speed; + slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); + + info("Successfully changed frequency/mode for adapter in slot %d\n", + slot->number); + return 0; +} + /* the following routines constitute the bulk of the hotplug controller logic */ @@ -1178,7 +1279,7 @@ static int is_bridge(struct pci_func * f * If board isn't same, turns it back off. * */ -static u32 board_replaced(struct pci_func * func, struct controller * ctrl) +static u32 board_replaced(struct pci_func *func, struct controller *ctrl) { u8 hp_slot; u8 temp_byte; @@ -1190,36 +1291,35 @@ static u32 board_replaced(struct pci_fun hp_slot = func->device - ctrl->slot_device_offset; if (readl(ctrl->hpc_reg + INT_INPUT_CLEAR) & (0x01L << hp_slot)) { - //********************************* - // The switch is open. - //********************************* + /********************************** + * The switch is open. + **********************************/ rc = INTERLOCK_OPEN; } else if (is_slot_enabled (ctrl, hp_slot)) { - //********************************* - // The board is already on - //********************************* + /********************************** + * The board is already on + **********************************/ rc = CARD_FUNCTIONING; } else { - // Wait for exclusive access to hardware down(&ctrl->crit_sect); - // turn on board without attaching to the bus + /* turn on board without attaching to the bus */ enable_slot_power (ctrl, hp_slot); set_SOGO(ctrl); - // Wait for SOBS to be unset + /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - // Change bits in slot power register to force another shift out - // NOTE: this is to work around the timer bug + /* Change bits in slot power register to force another shift out + * NOTE: this is to work around the timer bug */ temp_byte = readb(ctrl->hpc_reg + SLOT_POWER); writeb(0x00, ctrl->hpc_reg + SLOT_POWER); writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER); set_SOGO(ctrl); - // Wait for SOBS to be unset + /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); adapter_speed = get_adapter_speed(ctrl, hp_slot); @@ -1227,21 +1327,19 @@ static u32 board_replaced(struct pci_fun if (set_controller_speed(ctrl, adapter_speed, hp_slot)) rc = WRONG_BUS_FREQUENCY; - // turn off board without attaching to the bus + /* turn off board without attaching to the bus */ disable_slot_power (ctrl, hp_slot); set_SOGO(ctrl); - // Wait for SOBS to be unset + /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - // Done with exclusive hardware access up(&ctrl->crit_sect); if (rc) - return(rc); + return rc; - // Wait for exclusive access to hardware down(&ctrl->crit_sect); slot_enable (ctrl, hp_slot); @@ -1251,35 +1349,34 @@ static u32 board_replaced(struct pci_fun set_SOGO(ctrl); - // Wait for SOBS to be unset + /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - // Done with exclusive hardware access up(&ctrl->crit_sect); - // Wait for ~1 second because of hot plug spec + /* Wait for ~1 second because of hot plug spec */ long_delay(1*HZ); - // Check for a power fault + /* Check for a power fault */ if (func->status == 0xFF) { - // power fault occurred, but it was benign + /* power fault occurred, but it was benign */ rc = POWER_FAILURE; func->status = 0; } else rc = cpqhp_valid_replace(ctrl, func); if (!rc) { - // It must be the same board + /* It must be the same board */ rc = cpqhp_configure_board(ctrl, func); if (rc || src) { - // If configuration fails, turn it off - // Get slot won't work for devices behind bridges, but - // in this case it will always be called for the "base" - // bus/dev/func of an adapter. + /* If configuration fails, turn it off + * Get slot won't work for devices behind + * bridges, but in this case it will always be + * called for the "base" bus/dev/func of an + * adapter. */ - // Wait for exclusive access to hardware down(&ctrl->crit_sect); amber_LED_on (ctrl, hp_slot); @@ -1288,16 +1385,15 @@ static u32 board_replaced(struct pci_fun set_SOGO(ctrl); - // Wait for SOBS to be unset + /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - // Done with exclusive hardware access up(&ctrl->crit_sect); if (rc) - return(rc); + return rc; else - return(1); + return 1; } func->status = 0; @@ -1310,12 +1406,12 @@ static u32 board_replaced(struct pci_fun } if (rc) { - // If configuration fails, turn it off - // Get slot won't work for devices behind bridges, but - // in this case it will always be called for the "base" - // bus/dev/func of an adapter. + /* If configuration fails, turn it off + * Get slot won't work for devices behind + * bridges, but in this case it will always be + * called for the "base" bus/dev/func of an + * adapter. */ - // Wait for exclusive access to hardware down(&ctrl->crit_sect); amber_LED_on (ctrl, hp_slot); @@ -1324,37 +1420,33 @@ static u32 board_replaced(struct pci_fun set_SOGO(ctrl); - // Wait for SOBS to be unset + /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - // Done with exclusive hardware access up(&ctrl->crit_sect); - return(rc); + return rc; } - // Done configuring so turn LED on full time + /* Done configuring so turn LED on full time */ - // Wait for exclusive access to hardware down(&ctrl->crit_sect); green_LED_on (ctrl, hp_slot); set_SOGO(ctrl); - // Wait for SOBS to be unset + /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - // Done with exclusive hardware access up(&ctrl->crit_sect); rc = 0; } else { - // Something is wrong + /* Something is wrong - // Get slot won't work for devices behind bridges, but - // in this case it will always be called for the "base" - // bus/dev/func of an adapter. + * Get slot won't work for devices behind bridges, but + * in this case it will always be called for the "base" + * bus/dev/func of an adapter. */ - // Wait for exclusive access to hardware down(&ctrl->crit_sect); amber_LED_on (ctrl, hp_slot); @@ -1363,15 +1455,14 @@ static u32 board_replaced(struct pci_fun set_SOGO(ctrl); - // Wait for SOBS to be unset + /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - // Done with exclusive hardware access up(&ctrl->crit_sect); } } - return(rc); + return rc; } @@ -1383,7 +1474,7 @@ static u32 board_replaced(struct pci_fun * Configures board * */ -static u32 board_added(struct pci_func * func, struct controller * ctrl) +static u32 board_added(struct pci_func *func, struct controller *ctrl) { u8 hp_slot; u8 temp_byte; @@ -1399,26 +1490,25 @@ static u32 board_added(struct pci_func * dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot); - // Wait for exclusive access to hardware down(&ctrl->crit_sect); - // turn on board without attaching to the bus - enable_slot_power (ctrl, hp_slot); + /* turn on board without attaching to the bus */ + enable_slot_power(ctrl, hp_slot); set_SOGO(ctrl); - // Wait for SOBS to be unset + /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - // Change bits in slot power register to force another shift out - // NOTE: this is to work around the timer bug + /* Change bits in slot power register to force another shift out + * NOTE: this is to work around the timer bug */ temp_byte = readb(ctrl->hpc_reg + SLOT_POWER); writeb(0x00, ctrl->hpc_reg + SLOT_POWER); writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER); set_SOGO(ctrl); - // Wait for SOBS to be unset + /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); adapter_speed = get_adapter_speed(ctrl, hp_slot); @@ -1426,25 +1516,23 @@ static u32 board_added(struct pci_func * if (set_controller_speed(ctrl, adapter_speed, hp_slot)) rc = WRONG_BUS_FREQUENCY; - // turn off board without attaching to the bus + /* turn off board without attaching to the bus */ disable_slot_power (ctrl, hp_slot); set_SOGO(ctrl); - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); + /* Wait for SOBS to be unset */ + wait_for_ctrl_irq(ctrl); - // Done with exclusive hardware access up(&ctrl->crit_sect); if (rc) - return(rc); + return rc; p_slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); - // turn on board and blink green LED + /* turn on board and blink green LED */ - // Wait for exclusive access to hardware dbg("%s: before down\n", __FUNCTION__); down(&ctrl->crit_sect); dbg("%s: after down\n", __FUNCTION__); @@ -1461,47 +1549,46 @@ static u32 board_added(struct pci_func * dbg("%s: before set_SOGO\n", __FUNCTION__); set_SOGO(ctrl); - // Wait for SOBS to be unset + /* Wait for SOBS to be unset */ dbg("%s: before wait_for_ctrl_irq\n", __FUNCTION__); wait_for_ctrl_irq (ctrl); dbg("%s: after wait_for_ctrl_irq\n", __FUNCTION__); - // Done with exclusive hardware access dbg("%s: before up\n", __FUNCTION__); up(&ctrl->crit_sect); dbg("%s: after up\n", __FUNCTION__); - // Wait for ~1 second because of hot plug spec + /* Wait for ~1 second because of hot plug spec */ dbg("%s: before long_delay\n", __FUNCTION__); long_delay(1*HZ); dbg("%s: after long_delay\n", __FUNCTION__); dbg("%s: func status = %x\n", __FUNCTION__, func->status); - // Check for a power fault + /* Check for a power fault */ if (func->status == 0xFF) { - // power fault occurred, but it was benign + /* power fault occurred, but it was benign */ temp_register = 0xFFFFFFFF; dbg("%s: temp register set to %x by power fault\n", __FUNCTION__, temp_register); rc = POWER_FAILURE; func->status = 0; } else { - // Get vendor/device ID u32 + /* Get vendor/device ID u32 */ ctrl->pci_bus->number = func->bus; rc = pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(func->device, func->function), PCI_VENDOR_ID, &temp_register); dbg("%s: pci_read_config_dword returns %d\n", __FUNCTION__, rc); dbg("%s: temp_register is %x\n", __FUNCTION__, temp_register); if (rc != 0) { - // Something's wrong here + /* Something's wrong here */ temp_register = 0xFFFFFFFF; dbg("%s: temp register set to %x by error\n", __FUNCTION__, temp_register); } - // Preset return code. It will be changed later if things go okay. + /* Preset return code. It will be changed later if things go okay. */ rc = NO_ADAPTER_PRESENT; } - // All F's is an empty slot or an invalid board - if (temp_register != 0xFFFFFFFF) { // Check for a board in the slot + /* All F's is an empty slot or an invalid board */ + if (temp_register != 0xFFFFFFFF) { /* Check for a board in the slot */ res_lists.io_head = ctrl->io_head; res_lists.mem_head = ctrl->mem_head; res_lists.p_mem_head = ctrl->p_mem_head; @@ -1522,7 +1609,6 @@ static u32 board_added(struct pci_func * cpqhp_resource_sort_and_combine(&(ctrl->bus_head)); if (rc) { - // Wait for exclusive access to hardware down(&ctrl->crit_sect); amber_LED_on (ctrl, hp_slot); @@ -1531,12 +1617,11 @@ static u32 board_added(struct pci_func * set_SOGO(ctrl); - // Wait for SOBS to be unset + /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - // Done with exclusive hardware access up(&ctrl->crit_sect); - return(rc); + return rc; } else { cpqhp_save_slot_config(ctrl, func); } @@ -1546,7 +1631,8 @@ static u32 board_added(struct pci_func * func->switch_save = 0x10; func->is_a_board = 0x01; - //next, we will instantiate the linux pci_dev structures (with appropriate driver notification, if already present) + /* next, we will instantiate the linux pci_dev structures (with + * appropriate driver notification, if already present) */ dbg("%s: configure linux pci_dev structure\n", __FUNCTION__); index = 0; do { @@ -1556,20 +1642,17 @@ static u32 board_added(struct pci_func * } } while (new_slot); - // Wait for exclusive access to hardware down(&ctrl->crit_sect); green_LED_on (ctrl, hp_slot); set_SOGO(ctrl); - // Wait for SOBS to be unset + /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - // Done with exclusive hardware access up(&ctrl->crit_sect); } else { - // Wait for exclusive access to hardware down(&ctrl->crit_sect); amber_LED_on (ctrl, hp_slot); @@ -1578,13 +1661,12 @@ static u32 board_added(struct pci_func * set_SOGO(ctrl); - // Wait for SOBS to be unset + /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - // Done with exclusive hardware access up(&ctrl->crit_sect); - return(rc); + return rc; } return 0; } @@ -1605,26 +1687,23 @@ static u32 remove_board(struct pci_func struct resource_lists res_lists; struct pci_func *temp_func; - if (func == NULL) - return(1); - if (cpqhp_unconfigure_device(func)) - return(1); + return 1; device = func->device; hp_slot = func->device - ctrl->slot_device_offset; dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); - // When we get here, it is safe to change base Address Registers. - // We will attempt to save the base Address Register Lengths + /* When we get here, it is safe to change base address registers. + * We will attempt to save the base address register lengths */ if (replace_flag || !ctrl->add_support) rc = cpqhp_save_base_addr_length(ctrl, func); else if (!func->bus_head && !func->mem_head && !func->p_mem_head && !func->io_head) { - // Here we check to see if we've saved any of the board's - // resources already. If so, we'll skip the attempt to - // determine what's being used. + /* Here we check to see if we've saved any of the board's + * resources already. If so, we'll skip the attempt to + * determine what's being used. */ index = 0; temp_func = cpqhp_slot_find(func->bus, func->device, index++); while (temp_func) { @@ -1639,12 +1718,11 @@ static u32 remove_board(struct pci_func if (!skip) rc = cpqhp_save_used_resources(ctrl, func); } - // Change status to shutdown + /* Change status to shutdown */ if (func->is_a_board) func->status = 0x01; func->configured = 0; - // Wait for exclusive access to hardware down(&ctrl->crit_sect); green_LED_off (ctrl, hp_slot); @@ -1652,15 +1730,14 @@ static u32 remove_board(struct pci_func set_SOGO(ctrl); - // turn off SERR for slot + /* turn off SERR for slot */ temp_byte = readb(ctrl->hpc_reg + SLOT_SERR); temp_byte &= ~(0x01 << hp_slot); writeb(temp_byte, ctrl->hpc_reg + SLOT_SERR); - // Wait for SOBS to be unset + /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - // Done with exclusive hardware access up(&ctrl->crit_sect); if (!replace_flag && ctrl->add_support) { @@ -1690,13 +1767,11 @@ static u32 remove_board(struct pci_func func = cpqhp_slot_find(ctrl->bus, device, 0); } - // Setup slot structure with entry for empty slot + /* Setup slot structure with entry for empty slot */ func = cpqhp_slot_create(ctrl->bus); - if (func == NULL) { - // Out of memory - return(1); - } + if (func == NULL) + return 1; func->bus = ctrl->bus; func->device = device; @@ -1710,15 +1785,14 @@ static u32 remove_board(struct pci_func return 0; } - -static void pushbutton_helper_thread (unsigned long data) +static void pushbutton_helper_thread(unsigned long data) { pushbutton_pending = data; up(&event_semaphore); } -// this is the main worker thread +/* this is the main worker thread */ static int event_thread(void* data) { struct controller *ctrl; @@ -1745,7 +1819,7 @@ static int event_thread(void* data) } -int cpqhp_event_start_thread (void) +int cpqhp_event_start_thread(void) { int pid; @@ -1765,7 +1839,7 @@ int cpqhp_event_start_thread (void) } -void cpqhp_event_stop_thread (void) +void cpqhp_event_stop_thread(void) { event_finished = 1; dbg("event_thread finish command given\n"); @@ -1775,12 +1849,12 @@ void cpqhp_event_stop_thread (void) } -static int update_slot_info (struct controller *ctrl, struct slot *slot) +static int update_slot_info(struct controller *ctrl, struct slot *slot) { struct hotplug_slot_info *info; int result; - info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL); + info = kmalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; @@ -1805,7 +1879,7 @@ static void interrupt_event_handler(stru change = 0; for (loop = 0; loop < 10; loop++) { - //dbg("loop %d\n", loop); + /* dbg("loop %d\n", loop); */ if (ctrl->event_queue[loop].event_type != 0) { hp_slot = ctrl->event_queue[loop].hp_slot; @@ -1827,17 +1901,14 @@ static void interrupt_event_handler(stru dbg("button cancel\n"); del_timer(&p_slot->task_event); - // Wait for exclusive access to hardware down(&ctrl->crit_sect); if (p_slot->state == BLINKINGOFF_STATE) { - // slot is on - // turn on green LED + /* slot is on */ dbg("turn on green LED\n"); green_LED_on (ctrl, hp_slot); } else if (p_slot->state == BLINKINGON_STATE) { - // slot is off - // turn off green LED + /* slot is off */ dbg("turn off green LED\n"); green_LED_off (ctrl, hp_slot); } @@ -1850,28 +1921,24 @@ static void interrupt_event_handler(stru set_SOGO(ctrl); - // Wait for SOBS to be unset + /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - // Done with exclusive hardware access up(&ctrl->crit_sect); } - // ***********button Released (No action on press...) + /*** button Released (No action on press...) */ else if (ctrl->event_queue[loop].event_type == INT_BUTTON_RELEASE) { dbg("button release\n"); if (is_slot_enabled (ctrl, hp_slot)) { - // slot is on dbg("slot is on\n"); p_slot->state = BLINKINGOFF_STATE; info(msg_button_off, p_slot->number); } else { - // slot is off dbg("slot is off\n"); p_slot->state = BLINKINGON_STATE; info(msg_button_on, p_slot->number); } - // Wait for exclusive access to hardware down(&ctrl->crit_sect); dbg("blink green LED and turn off amber\n"); @@ -1881,23 +1948,22 @@ static void interrupt_event_handler(stru set_SOGO(ctrl); - // Wait for SOBS to be unset + /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - // Done with exclusive hardware access up(&ctrl->crit_sect); init_timer(&p_slot->task_event); p_slot->hp_slot = hp_slot; p_slot->ctrl = ctrl; -// p_slot->physical_slot = physical_slot; - p_slot->task_event.expires = jiffies + 5 * HZ; // 5 second delay +/* p_slot->physical_slot = physical_slot; */ + p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ p_slot->task_event.function = pushbutton_helper_thread; p_slot->task_event.data = (u32) p_slot; dbg("add_timer p_slot = %p\n", p_slot); add_timer(&p_slot->task_event); } - // ***********POWER FAULT + /***********POWER FAULT */ else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) { dbg("power fault\n"); } else { @@ -1910,7 +1976,7 @@ static void interrupt_event_handler(stru change = 1; } - } // End of FOR loop + } /* End of FOR loop */ } return; @@ -1924,7 +1990,7 @@ static void interrupt_event_handler(stru * Handles all pending events and exits. * */ -void cpqhp_pushbutton_thread (unsigned long slot) +void cpqhp_pushbutton_thread(unsigned long slot) { u8 hp_slot; u8 device; @@ -1937,9 +2003,9 @@ void cpqhp_pushbutton_thread (unsigned l device = p_slot->device; - if (is_slot_enabled (ctrl, hp_slot)) { + if (is_slot_enabled(ctrl, hp_slot)) { p_slot->state = POWEROFF_STATE; - // power Down board + /* power Down board */ func = cpqhp_slot_find(p_slot->bus, p_slot->device, 0); dbg("In power_down_board, func = %p, ctrl = %p\n", func, ctrl); if (!func) { @@ -1954,7 +2020,7 @@ void cpqhp_pushbutton_thread (unsigned l set_SOGO(ctrl); - // Wait for SOBS to be unset + /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); } } @@ -1962,7 +2028,7 @@ void cpqhp_pushbutton_thread (unsigned l p_slot->state = STATIC_STATE; } else { p_slot->state = POWERON_STATE; - // slot is off + /* slot is off */ func = cpqhp_slot_find(p_slot->bus, p_slot->device, 0); dbg("In add_board, func = %p, ctrl = %p\n", func, ctrl); @@ -1973,12 +2039,12 @@ void cpqhp_pushbutton_thread (unsigned l if (func != NULL && ctrl != NULL) { if (cpqhp_process_SI(ctrl, func) != 0) { - amber_LED_on (ctrl, hp_slot); - green_LED_off (ctrl, hp_slot); + amber_LED_on(ctrl, hp_slot); + green_LED_off(ctrl, hp_slot); set_SOGO(ctrl); - // Wait for SOBS to be unset + /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); } } @@ -1990,7 +2056,7 @@ void cpqhp_pushbutton_thread (unsigned l } -int cpqhp_process_SI (struct controller *ctrl, struct pci_func *func) +int cpqhp_process_SI(struct controller *ctrl, struct pci_func *func) { u8 device, hp_slot; u16 temp_word; @@ -1999,35 +2065,30 @@ int cpqhp_process_SI (struct controller struct slot* p_slot; int physical_slot = 0; - if (!ctrl) - return(1); - tempdword = 0; device = func->device; hp_slot = device - ctrl->slot_device_offset; p_slot = cpqhp_find_slot(ctrl, device); - if (p_slot) { + if (p_slot) physical_slot = p_slot->number; - } - // Check to see if the interlock is closed + /* Check to see if the interlock is closed */ tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR); if (tempdword & (0x01 << hp_slot)) { - return(1); + return 1; } if (func->is_a_board) { rc = board_replaced(func, ctrl); } else { - // add board + /* add board */ slot_remove(func); func = cpqhp_slot_create(ctrl->bus); - if (func == NULL) { - return(1); - } + if (func == NULL) + return 1; func->bus = ctrl->bus; func->device = device; @@ -2035,7 +2096,7 @@ int cpqhp_process_SI (struct controller func->configured = 0; func->is_a_board = 1; - // We have to save the presence info for these slots + /* We have to save the presence info for these slots */ temp_word = ctrl->ctrl_int_comp >> 16; func->presence_save = (temp_word >> hp_slot) & 0x01; func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02; @@ -2053,13 +2114,11 @@ int cpqhp_process_SI (struct controller } else slot_remove(func); - // Setup slot structure with entry for empty slot + /* Setup slot structure with entry for empty slot */ func = cpqhp_slot_create(ctrl->bus); - if (func == NULL) { - // Out of memory - return(1); - } + if (func == NULL) + return 1; func->bus = ctrl->bus; func->device = device; @@ -2067,7 +2126,7 @@ int cpqhp_process_SI (struct controller func->configured = 0; func->is_a_board = 0; - // We have to save the presence info for these slots + /* We have to save the presence info for these slots */ temp_word = ctrl->ctrl_int_comp >> 16; func->presence_save = (temp_word >> hp_slot) & 0x01; func->presence_save |= @@ -2092,7 +2151,7 @@ int cpqhp_process_SI (struct controller } -int cpqhp_process_SS (struct controller *ctrl, struct pci_func *func) +int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func) { u8 device, class_code, header_type, BCR; u8 index = 0; @@ -2110,12 +2169,12 @@ int cpqhp_process_SS (struct controller physical_slot = p_slot->number; } - // Make sure there are no video controllers here + /* Make sure there are no video controllers here */ while (func && !rc) { pci_bus->number = func->bus; devfn = PCI_DEVFN(func->device, func->function); - // Check the Class Code + /* Check the Class Code */ rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code); if (rc) return rc; @@ -2124,18 +2183,19 @@ int cpqhp_process_SS (struct controller /* Display/Video adapter (not supported) */ rc = REMOVE_NOT_SUPPORTED; } else { - // See if it's a bridge + /* See if it's a bridge */ rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type); if (rc) return rc; - // If it's a bridge, check the VGA Enable bit + /* If it's a bridge, check the VGA Enable bit */ if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR); if (rc) return rc; - // If the VGA Enable bit is set, remove isn't supported + /* If the VGA Enable bit is set, remove isn't + * supported */ if (BCR & PCI_BRIDGE_CTL_VGA) { rc = REMOVE_NOT_SUPPORTED; } @@ -2147,7 +2207,7 @@ int cpqhp_process_SS (struct controller func = cpqhp_slot_find(ctrl->bus, device, 0); if ((func != NULL) && !rc) { - //FIXME: Replace flag should be passed into process_SS + /* FIXME: Replace flag should be passed into process_SS */ replace_flag = !(ctrl->add_support); rc = remove_board(func, replace_flag, ctrl); } else if (!rc) { @@ -2157,16 +2217,42 @@ int cpqhp_process_SS (struct controller if (p_slot) update_slot_info(ctrl, p_slot); - return(rc); + return rc; } +/** + * switch_leds: switch the leds, go from one site to the other. + * @ctrl: controller to use + * @num_of_slots: number of slots to use + * @direction: 1 to start from the left side, 0 to start right. + */ +void switch_leds(struct controller *ctrl, const int num_of_slots, + u32 *work_LED, const int direction) +{ + int loop; + for (loop = 0; loop < num_of_slots; loop++) { + if (direction) + *work_LED = *work_LED >> 1; + else + *work_LED = *work_LED << 1; + writel(*work_LED, ctrl->hpc_reg + LED_CONTROL); + + set_SOGO(ctrl); + + /* Wait for SOGO interrupt */ + wait_for_ctrl_irq(ctrl); + + /* Get ready for next iteration */ + long_delay((2*HZ)/10); + } +} /** * hardware_test - runs hardware tests * * For hot plug ctrl folks to play with. - * test_num is the number entered in the GUI + * test_num is the number written to the "test" file in sysfs * */ int cpqhp_hardware_test(struct controller *ctrl, int test_num) @@ -2180,132 +2266,45 @@ int cpqhp_hardware_test(struct controlle switch (test_num) { case 1: - // Do stuff here! + /* Do stuff here! */ - // Do that funky LED thing - save_LED = readl(ctrl->hpc_reg + LED_CONTROL); // so we can restore them later + /* Do that funky LED thing */ + /* so we can restore them later */ + save_LED = readl(ctrl->hpc_reg + LED_CONTROL); work_LED = 0x01010101; - writel(work_LED, ctrl->hpc_reg + LED_CONTROL); - for (loop = 0; loop < num_of_slots; loop++) { - set_SOGO(ctrl); - - // Wait for SOGO interrupt - wait_for_ctrl_irq (ctrl); - - // Get ready for next iteration - work_LED = work_LED << 1; - writel(work_LED, ctrl->hpc_reg + LED_CONTROL); - long_delay((2*HZ)/10); - } - for (loop = 0; loop < num_of_slots; loop++) { - work_LED = work_LED >> 1; - writel(work_LED, ctrl->hpc_reg + LED_CONTROL); - - set_SOGO(ctrl); - - // Wait for SOGO interrupt - wait_for_ctrl_irq (ctrl); - - // Get ready for next iteration - long_delay((2*HZ)/10); - } - for (loop = 0; loop < num_of_slots; loop++) { - work_LED = work_LED << 1; - writel(work_LED, ctrl->hpc_reg + LED_CONTROL); - - set_SOGO(ctrl); - - // Wait for SOGO interrupt - wait_for_ctrl_irq (ctrl); - - // Get ready for next iteration - long_delay((2*HZ)/10); - } - for (loop = 0; loop < num_of_slots; loop++) { - work_LED = work_LED >> 1; - writel(work_LED, ctrl->hpc_reg + LED_CONTROL); - - set_SOGO(ctrl); - - // Wait for SOGO interrupt - wait_for_ctrl_irq (ctrl); - - // Get ready for next iteration - long_delay((2*HZ)/10); - } + switch_leds(ctrl, num_of_slots, &work_LED, 0); + switch_leds(ctrl, num_of_slots, &work_LED, 1); + switch_leds(ctrl, num_of_slots, &work_LED, 0); + switch_leds(ctrl, num_of_slots, &work_LED, 1); work_LED = 0x01010000; writel(work_LED, ctrl->hpc_reg + LED_CONTROL); - for (loop = 0; loop < num_of_slots; loop++) { - set_SOGO(ctrl); - - // Wait for SOGO interrupt - wait_for_ctrl_irq (ctrl); - - // Get ready for next iteration - work_LED = work_LED << 1; - writel(work_LED, ctrl->hpc_reg + LED_CONTROL); - long_delay((2*HZ)/10); - } - for (loop = 0; loop < num_of_slots; loop++) { - work_LED = work_LED >> 1; - writel(work_LED, ctrl->hpc_reg + LED_CONTROL); - - set_SOGO(ctrl); - - // Wait for SOGO interrupt - wait_for_ctrl_irq (ctrl); - - // Get ready for next iteration - long_delay((2*HZ)/10); - } + switch_leds(ctrl, num_of_slots, &work_LED, 0); + switch_leds(ctrl, num_of_slots, &work_LED, 1); work_LED = 0x00000101; writel(work_LED, ctrl->hpc_reg + LED_CONTROL); - for (loop = 0; loop < num_of_slots; loop++) { - work_LED = work_LED << 1; - writel(work_LED, ctrl->hpc_reg + LED_CONTROL); - - set_SOGO(ctrl); - - // Wait for SOGO interrupt - wait_for_ctrl_irq (ctrl); - - // Get ready for next iteration - long_delay((2*HZ)/10); - } - for (loop = 0; loop < num_of_slots; loop++) { - work_LED = work_LED >> 1; - writel(work_LED, ctrl->hpc_reg + LED_CONTROL); - - set_SOGO(ctrl); - - // Wait for SOGO interrupt - wait_for_ctrl_irq (ctrl); - - // Get ready for next iteration - long_delay((2*HZ)/10); - } - + switch_leds(ctrl, num_of_slots, &work_LED, 0); + switch_leds(ctrl, num_of_slots, &work_LED, 1); work_LED = 0x01010000; writel(work_LED, ctrl->hpc_reg + LED_CONTROL); for (loop = 0; loop < num_of_slots; loop++) { set_SOGO(ctrl); - // Wait for SOGO interrupt + /* Wait for SOGO interrupt */ wait_for_ctrl_irq (ctrl); - // Get ready for next iteration + /* Get ready for next iteration */ long_delay((3*HZ)/10); work_LED = work_LED >> 16; writel(work_LED, ctrl->hpc_reg + LED_CONTROL); set_SOGO(ctrl); - // Wait for SOGO interrupt + /* Wait for SOGO interrupt */ wait_for_ctrl_irq (ctrl); - // Get ready for next iteration + /* Get ready for next iteration */ long_delay((3*HZ)/10); work_LED = work_LED << 16; writel(work_LED, ctrl->hpc_reg + LED_CONTROL); @@ -2313,18 +2312,19 @@ int cpqhp_hardware_test(struct controlle writel(work_LED, ctrl->hpc_reg + LED_CONTROL); } - writel (save_LED, ctrl->hpc_reg + LED_CONTROL); // put it back the way it was + /* put it back the way it was */ + writel(save_LED, ctrl->hpc_reg + LED_CONTROL); set_SOGO(ctrl); - // Wait for SOBS to be unset + /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); break; case 2: - // Do other stuff here! + /* Do other stuff here! */ break; case 3: - // and more... + /* and more... */ break; } return 0; @@ -2342,7 +2342,7 @@ int cpqhp_hardware_test(struct controlle * Returns 0 if success * */ -static u32 configure_new_device (struct controller * ctrl, struct pci_func * func, +static u32 configure_new_device(struct controller * ctrl, struct pci_func * func, u8 behind_bridge, struct resource_lists * resources) { u8 temp_byte, function, max_functions, stop_it; @@ -2354,7 +2354,7 @@ static u32 configure_new_device (struct new_slot = func; dbg("%s\n", __FUNCTION__); - // Check for Multi-function device + /* Check for Multi-function device */ ctrl->pci_bus->number = func->bus; rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(func->device, func->function), 0x0E, &temp_byte); if (rc) { @@ -2362,7 +2362,7 @@ static u32 configure_new_device (struct return rc; } - if (temp_byte & 0x80) // Multi-function device + if (temp_byte & 0x80) /* Multi-function device */ max_functions = 8; else max_functions = 1; @@ -2383,29 +2383,27 @@ static u32 configure_new_device (struct cpqhp_return_board_resources(new_slot, resources); } - return(rc); + return rc; } function++; stop_it = 0; - // The following loop skips to the next present function - // and creates a board structure + /* The following loop skips to the next present function + * and creates a board structure */ while ((function < max_functions) && (!stop_it)) { pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(func->device, function), 0x00, &ID); - if (ID == 0xFFFFFFFF) { // There's nothing there. + if (ID == 0xFFFFFFFF) { /* There's nothing there. */ function++; - } else { // There's something there - // Setup slot structure. + } else { /* There's something there */ + /* Setup slot structure. */ new_slot = cpqhp_slot_create(func->bus); - if (new_slot == NULL) { - // Out of memory - return(1); - } + if (new_slot == NULL) + return 1; new_slot->bus = func->bus; new_slot->device = func->device; @@ -2442,8 +2440,9 @@ static u32 configure_new_device (struct * Returns 0 if success * */ -static int configure_new_function (struct controller * ctrl, struct pci_func * func, - u8 behind_bridge, struct resource_lists * resources) +static int configure_new_function(struct controller *ctrl, struct pci_func *func, + u8 behind_bridge, + struct resource_lists *resources) { int cloop; u8 IRQ = 0; @@ -2475,57 +2474,56 @@ static int configure_new_function (struc pci_bus->number = func->bus; devfn = PCI_DEVFN(func->device, func->function); - // Check for Bridge - rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &temp_byte); + /* Check for Bridge */ + rc = pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &temp_byte); if (rc) return rc; - if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge - // set Primary bus + if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */ + /* set Primary bus */ dbg("set Primary bus = %d\n", func->bus); - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_PRIMARY_BUS, func->bus); + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_PRIMARY_BUS, func->bus); if (rc) return rc; - // find range of busses to use + /* find range of busses to use */ dbg("find ranges of buses to use\n"); - bus_node = get_max_resource(&resources->bus_head, 1); + bus_node = get_max_resource(&(resources->bus_head), 1); - // If we don't have any busses to allocate, we can't continue + /* If we don't have any busses to allocate, we can't continue */ if (!bus_node) return -ENOMEM; - // set Secondary bus + /* set Secondary bus */ temp_byte = bus_node->base; dbg("set Secondary bus = %d\n", bus_node->base); - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, temp_byte); + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, temp_byte); if (rc) return rc; - // set subordinate bus + /* set subordinate bus */ temp_byte = bus_node->base + bus_node->length - 1; dbg("set subordinate bus = %d\n", bus_node->base + bus_node->length - 1); - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte); + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte); if (rc) return rc; - // set subordinate Latency Timer and base Latency Timer + /* set subordinate Latency Timer and base Latency Timer */ temp_byte = 0x40; - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte); + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte); if (rc) return rc; - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte); + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte); if (rc) return rc; - // set Cache Line size + /* set Cache Line size */ temp_byte = 0x08; - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte); + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte); if (rc) return rc; - // Setup the IO, memory, and prefetchable windows - + /* Setup the IO, memory, and prefetchable windows */ io_node = get_max_resource(&(resources->io_head), 0x1000); if (!io_node) return -ENOMEM; @@ -2537,13 +2535,16 @@ static int configure_new_function (struc return -ENOMEM; dbg("Setup the IO, memory, and prefetchable windows\n"); dbg("io_node\n"); - dbg("(base, len, next) (%x, %x, %p)\n", io_node->base, io_node->length, io_node->next); + dbg("(base, len, next) (%x, %x, %p)\n", io_node->base, + io_node->length, io_node->next); dbg("mem_node\n"); - dbg("(base, len, next) (%x, %x, %p)\n", mem_node->base, mem_node->length, mem_node->next); + dbg("(base, len, next) (%x, %x, %p)\n", mem_node->base, + mem_node->length, mem_node->next); dbg("p_mem_node\n"); - dbg("(base, len, next) (%x, %x, %p)\n", p_mem_node->base, p_mem_node->length, p_mem_node->next); + dbg("(base, len, next) (%x, %x, %p)\n", p_mem_node->base, + p_mem_node->length, p_mem_node->next); - // set up the IRQ info + /* set up the IRQ info */ if (!resources->irqs) { irqs.barber_pole = 0; irqs.interrupt[0] = 0; @@ -2560,32 +2561,28 @@ static int configure_new_function (struc irqs.valid_INT = resources->irqs->valid_INT; } - // set up resource lists that are now aligned on top and bottom - // for anything behind the bridge. + /* set up resource lists that are now aligned on top and bottom + * for anything behind the bridge. */ temp_resources.bus_head = bus_node; temp_resources.io_head = io_node; temp_resources.mem_head = mem_node; temp_resources.p_mem_head = p_mem_node; temp_resources.irqs = &irqs; - // Make copies of the nodes we are going to pass down so that - // if there is a problem,we can just use these to free resources - hold_bus_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - hold_IO_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - hold_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - hold_p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + /* Make copies of the nodes we are going to pass down so that + * if there is a problem,we can just use these to free resources */ + hold_bus_node = kmalloc(sizeof(*hold_bus_node), GFP_KERNEL); + hold_IO_node = kmalloc(sizeof(*hold_IO_node), GFP_KERNEL); + hold_mem_node = kmalloc(sizeof(*hold_mem_node), GFP_KERNEL); + hold_p_mem_node = kmalloc(sizeof(*hold_p_mem_node), GFP_KERNEL); if (!hold_bus_node || !hold_IO_node || !hold_mem_node || !hold_p_mem_node) { - if (hold_bus_node) - kfree(hold_bus_node); - if (hold_IO_node) - kfree(hold_IO_node); - if (hold_mem_node) - kfree(hold_mem_node); - if (hold_p_mem_node) - kfree(hold_p_mem_node); + kfree(hold_bus_node); + kfree(hold_IO_node); + kfree(hold_mem_node); + kfree(hold_p_mem_node); - return(1); + return 1; } memcpy(hold_bus_node, bus_node, sizeof(struct pci_resource)); @@ -2594,55 +2591,55 @@ static int configure_new_function (struc bus_node->length -= 1; bus_node->next = NULL; - // If we have IO resources copy them and fill in the bridge's - // IO range registers + /* If we have IO resources copy them and fill in the bridge's + * IO range registers */ if (io_node) { memcpy(hold_IO_node, io_node, sizeof(struct pci_resource)); io_node->next = NULL; - // set IO base and Limit registers + /* set IO base and Limit registers */ temp_byte = io_node->base >> 8; - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte); + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_BASE, temp_byte); temp_byte = (io_node->base + io_node->length - 1) >> 8; - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte); + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte); } else { kfree(hold_IO_node); hold_IO_node = NULL; } - // If we have memory resources copy them and fill in the bridge's - // memory range registers. Otherwise, fill in the range - // registers with values that disable them. + /* If we have memory resources copy them and fill in the + * bridge's memory range registers. Otherwise, fill in the + * range registers with values that disable them. */ if (mem_node) { memcpy(hold_mem_node, mem_node, sizeof(struct pci_resource)); mem_node->next = NULL; - // set Mem base and Limit registers + /* set Mem base and Limit registers */ temp_word = mem_node->base >> 16; - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word); + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word); temp_word = (mem_node->base + mem_node->length - 1) >> 16; - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); } else { temp_word = 0xFFFF; - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word); + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word); temp_word = 0x0000; - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); kfree(hold_mem_node); hold_mem_node = NULL; } - // If we have prefetchable memory resources copy them and - // fill in the bridge's memory range registers. Otherwise, - // fill in the range registers with values that disable them. + /* If we have prefetchable memory resources copy them and + * fill in the bridge's memory range registers. Otherwise, + * fill in the range registers with values that disable them. */ if (p_mem_node) { memcpy(hold_p_mem_node, p_mem_node, sizeof(struct pci_resource)); p_mem_node->next = NULL; - // set Pre Mem base and Limit registers + /* set Pre Mem base and Limit registers */ temp_word = p_mem_node->base >> 16; rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word); @@ -2659,12 +2656,12 @@ static int configure_new_function (struc hold_p_mem_node = NULL; } - // Adjust this to compensate for extra adjustment in first loop + /* Adjust this to compensate for extra adjustment in first loop */ irqs.barber_pole--; rc = 0; - // Here we actually find the devices and configure them + /* Here we actually find the devices and configure them */ for (device = 0; (device <= 0x1F) && !rc; device++) { irqs.barber_pole = (irqs.barber_pole + 1) & 0x03; @@ -2673,12 +2670,11 @@ static int configure_new_function (struc pci_bus_read_config_dword (pci_bus, PCI_DEVFN(device, 0), 0x00, &ID); pci_bus->number = func->bus; - if (ID != 0xFFFFFFFF) { // device Present - // Setup slot structure. + if (ID != 0xFFFFFFFF) { /* device present */ + /* Setup slot structure. */ new_slot = cpqhp_slot_create(hold_bus_node->base); if (new_slot == NULL) { - // Out of memory rc = -ENOMEM; continue; } @@ -2691,19 +2687,12 @@ static int configure_new_function (struc rc = configure_new_device(ctrl, new_slot, 1, &temp_resources); dbg("configure_new_device rc=0x%x\n",rc); - } // End of IF (device in slot?) - } // End of FOR loop - - if (rc) { - cpqhp_destroy_resource_list(&temp_resources); + } /* End of IF (device in slot?) */ + } /* End of FOR loop */ - return_resource(&(resources->bus_head), hold_bus_node); - return_resource(&(resources->io_head), hold_IO_node); - return_resource(&(resources->mem_head), hold_mem_node); - return_resource(&(resources->p_mem_head), hold_p_mem_node); - return(rc); - } - // save the interrupt routing information + if (rc) + goto free_and_out; + /* save the interrupt routing information */ if (resources->irqs) { resources->irqs->interrupt[0] = irqs.interrupt[0]; resources->irqs->interrupt[1] = irqs.interrupt[1]; @@ -2711,25 +2700,19 @@ static int configure_new_function (struc resources->irqs->interrupt[3] = irqs.interrupt[3]; resources->irqs->valid_INT = irqs.valid_INT; } else if (!behind_bridge) { - // We need to hook up the interrupts here + /* We need to hook up the interrupts here */ for (cloop = 0; cloop < 4; cloop++) { if (irqs.valid_INT & (0x01 << cloop)) { rc = cpqhp_set_irq(func->bus, func->device, 0x0A + cloop, irqs.interrupt[cloop]); - if (rc) { - cpqhp_destroy_resource_list (&temp_resources); - - return_resource(&(resources-> bus_head), hold_bus_node); - return_resource(&(resources-> io_head), hold_IO_node); - return_resource(&(resources-> mem_head), hold_mem_node); - return_resource(&(resources-> p_mem_head), hold_p_mem_node); - return rc; - } + if (rc) + goto free_and_out; } - } // end of for loop + } /* end of for loop */ } - // Return unused bus resources - // First use the temporary node to store information for the board + /* Return unused bus resources + * First use the temporary node to store information for + * the board */ if (hold_bus_node && bus_node && temp_resources.bus_head) { hold_bus_node->length = bus_node->base - hold_bus_node->base; @@ -2738,7 +2721,7 @@ static int configure_new_function (struc temp_byte = temp_resources.bus_head->base - 1; - // set subordinate bus + /* set subordinate bus */ rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte); if (temp_resources.bus_head->length == 0) { @@ -2749,13 +2732,13 @@ static int configure_new_function (struc } } - // If we have IO space available and there is some left, - // return the unused portion + /* If we have IO space available and there is some left, + * return the unused portion */ if (hold_IO_node && temp_resources.io_head) { io_node = do_pre_bridge_resource_split(&(temp_resources.io_head), &hold_IO_node, 0x1000); - // Check if we were able to split something off + /* Check if we were able to split something off */ if (io_node) { hold_IO_node->base = io_node->base + io_node->length; @@ -2767,12 +2750,13 @@ static int configure_new_function (struc io_node = do_bridge_resource_split(&(temp_resources.io_head), 0x1000); - // Check if we were able to split something off + /* Check if we were able to split something off */ if (io_node) { - // First use the temporary node to store information for the board + /* First use the temporary node to store + * information for the board */ hold_IO_node->length = io_node->base - hold_IO_node->base; - // If we used any, add it to the board's list + /* If we used any, add it to the board's list */ if (hold_IO_node->length) { hold_IO_node->next = func->io_head; func->io_head = hold_IO_node; @@ -2782,7 +2766,7 @@ static int configure_new_function (struc return_resource(&(resources->io_head), io_node); } else { - // it doesn't need any IO + /* it doesn't need any IO */ temp_word = 0x0000; rc = pci_bus_write_config_word (pci_bus, devfn, PCI_IO_LIMIT, temp_word); @@ -2790,22 +2774,22 @@ static int configure_new_function (struc kfree(hold_IO_node); } } else { - // it used most of the range + /* it used most of the range */ hold_IO_node->next = func->io_head; func->io_head = hold_IO_node; } } else if (hold_IO_node) { - // it used the whole range + /* it used the whole range */ hold_IO_node->next = func->io_head; func->io_head = hold_IO_node; } - // If we have memory space available and there is some left, - // return the unused portion + /* If we have memory space available and there is some left, + * return the unused portion */ if (hold_mem_node && temp_resources.mem_head) { mem_node = do_pre_bridge_resource_split(&(temp_resources. mem_head), &hold_mem_node, 0x100000); - // Check if we were able to split something off + /* Check if we were able to split something off */ if (mem_node) { hold_mem_node->base = mem_node->base + mem_node->length; @@ -2817,23 +2801,24 @@ static int configure_new_function (struc mem_node = do_bridge_resource_split(&(temp_resources.mem_head), 0x100000); - // Check if we were able to split something off + /* Check if we were able to split something off */ if (mem_node) { - // First use the temporary node to store information for the board + /* First use the temporary node to store + * information for the board */ hold_mem_node->length = mem_node->base - hold_mem_node->base; if (hold_mem_node->length) { hold_mem_node->next = func->mem_head; func->mem_head = hold_mem_node; - // configure end address + /* configure end address */ temp_word = (mem_node->base - 1) >> 16; rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); - // Return unused resources to the pool + /* Return unused resources to the pool */ return_resource(&(resources->mem_head), mem_node); } else { - // it doesn't need any Mem + /* it doesn't need any Mem */ temp_word = 0x0000; rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); @@ -2841,22 +2826,22 @@ static int configure_new_function (struc kfree(hold_mem_node); } } else { - // it used most of the range + /* it used most of the range */ hold_mem_node->next = func->mem_head; func->mem_head = hold_mem_node; } } else if (hold_mem_node) { - // it used the whole range + /* it used the whole range */ hold_mem_node->next = func->mem_head; func->mem_head = hold_mem_node; } - // If we have prefetchable memory space available and there is some - // left at the end, return the unused portion + /* If we have prefetchable memory space available and there + * is some left at the end, return the unused portion */ if (hold_p_mem_node && temp_resources.p_mem_head) { p_mem_node = do_pre_bridge_resource_split(&(temp_resources.p_mem_head), &hold_p_mem_node, 0x100000); - // Check if we were able to split something off + /* Check if we were able to split something off */ if (p_mem_node) { hold_p_mem_node->base = p_mem_node->base + p_mem_node->length; @@ -2868,12 +2853,13 @@ static int configure_new_function (struc p_mem_node = do_bridge_resource_split(&(temp_resources.p_mem_head), 0x100000); - // Check if we were able to split something off + /* Check if we were able to split something off */ if (p_mem_node) { - // First use the temporary node to store information for the board + /* First use the temporary node to store + * information for the board */ hold_p_mem_node->length = p_mem_node->base - hold_p_mem_node->base; - // If we used any, add it to the board's list + /* If we used any, add it to the board's list */ if (hold_p_mem_node->length) { hold_p_mem_node->next = func->p_mem_head; func->p_mem_head = hold_p_mem_node; @@ -2883,7 +2869,7 @@ static int configure_new_function (struc return_resource(&(resources->p_mem_head), p_mem_node); } else { - // it doesn't need any PMem + /* it doesn't need any PMem */ temp_word = 0x0000; rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); @@ -2891,35 +2877,42 @@ static int configure_new_function (struc kfree(hold_p_mem_node); } } else { - // it used the most of the range + /* it used the most of the range */ hold_p_mem_node->next = func->p_mem_head; func->p_mem_head = hold_p_mem_node; } } else if (hold_p_mem_node) { - // it used the whole range + /* it used the whole range */ hold_p_mem_node->next = func->p_mem_head; func->p_mem_head = hold_p_mem_node; } - // We should be configuring an IRQ and the bridge's base address - // registers if it needs them. Although we have never seen such - // a device - - // enable card - command = 0x0157; // = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR + /* We should be configuring an IRQ and the bridge's base address + * registers if it needs them. Although we have never seen such + * a device */ + + /* enable card */ + command = 0x0157; /* = PCI_COMMAND_IO | + * PCI_COMMAND_MEMORY | + * PCI_COMMAND_MASTER | + * PCI_COMMAND_INVALIDATE | + * PCI_COMMAND_PARITY | + * PCI_COMMAND_SERR */ rc = pci_bus_write_config_word (pci_bus, devfn, PCI_COMMAND, command); - // set Bridge Control Register - command = 0x07; // = PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR | PCI_BRIDGE_CTL_NO_ISA + /* set Bridge Control Register */ + command = 0x07; /* = PCI_BRIDGE_CTL_PARITY | + * PCI_BRIDGE_CTL_SERR | + * PCI_BRIDGE_CTL_NO_ISA */ rc = pci_bus_write_config_word (pci_bus, devfn, PCI_BRIDGE_CONTROL, command); } else if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_NORMAL) { - // Standard device + /* Standard device */ rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code); if (class_code == PCI_BASE_CLASS_DISPLAY) { - // Display (video) adapter (not supported) - return(DEVICE_TYPE_NOT_SUPPORTED); + /* Display (video) adapter (not supported) */ + return DEVICE_TYPE_NOT_SUPPORTED; } - // Figure out IO and memory needs + /* Figure out IO and memory needs */ for (cloop = 0x10; cloop <= 0x24; cloop += 4) { temp_register = 0xFFFFFFFF; @@ -2929,11 +2922,11 @@ static int configure_new_function (struc rc = pci_bus_read_config_dword (pci_bus, devfn, cloop, &temp_register); dbg("CND: base = 0x%x\n", temp_register); - if (temp_register) { // If this register is implemented + if (temp_register) { /* If this register is implemented */ if ((temp_register & 0x03L) == 0x01) { - // Map IO + /* Map IO */ - // set base = amount of IO space + /* set base = amount of IO space */ base = temp_register & 0xFFFFFFFC; base = ~base + 1; @@ -2943,7 +2936,7 @@ static int configure_new_function (struc io_node->base, io_node->length, io_node->next); dbg("func (%p) io_head (%p)\n", func, func->io_head); - // allocate the resource to the board + /* allocate the resource to the board */ if (io_node) { base = io_node->base; @@ -2952,14 +2945,14 @@ static int configure_new_function (struc } else return -ENOMEM; } else if ((temp_register & 0x0BL) == 0x08) { - // Map prefetchable memory + /* Map prefetchable memory */ base = temp_register & 0xFFFFFFF0; base = ~base + 1; dbg("CND: length = 0x%x\n", base); p_mem_node = get_resource(&(resources->p_mem_head), base); - // allocate the resource to the board + /* allocate the resource to the board */ if (p_mem_node) { base = p_mem_node->base; @@ -2968,14 +2961,14 @@ static int configure_new_function (struc } else return -ENOMEM; } else if ((temp_register & 0x0BL) == 0x00) { - // Map memory + /* Map memory */ base = temp_register & 0xFFFFFFF0; base = ~base + 1; dbg("CND: length = 0x%x\n", base); mem_node = get_resource(&(resources->mem_head), base); - // allocate the resource to the board + /* allocate the resource to the board */ if (mem_node) { base = mem_node->base; @@ -2984,14 +2977,14 @@ static int configure_new_function (struc } else return -ENOMEM; } else if ((temp_register & 0x0BL) == 0x04) { - // Map memory + /* Map memory */ base = temp_register & 0xFFFFFFF0; base = ~base + 1; dbg("CND: length = 0x%x\n", base); mem_node = get_resource(&(resources->mem_head), base); - // allocate the resource to the board + /* allocate the resource to the board */ if (mem_node) { base = mem_node->base; @@ -3000,42 +2993,44 @@ static int configure_new_function (struc } else return -ENOMEM; } else if ((temp_register & 0x0BL) == 0x06) { - // Those bits are reserved, we can't handle this - return(1); + /* Those bits are reserved, we can't handle this */ + return 1; } else { - // Requesting space below 1M - return(NOT_ENOUGH_RESOURCES); + /* Requesting space below 1M */ + return NOT_ENOUGH_RESOURCES; } - rc = pci_bus_write_config_dword (pci_bus, devfn, cloop, base); + rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, base); - // Check for 64-bit base + /* Check for 64-bit base */ if ((temp_register & 0x07L) == 0x04) { cloop += 4; - // Upper 32 bits of address always zero on today's systems - // FIXME this is probably not true on Alpha and ia64??? + /* Upper 32 bits of address always zero + * on today's systems */ + /* FIXME this is probably not true on + * Alpha and ia64??? */ base = 0; - rc = pci_bus_write_config_dword (pci_bus, devfn, cloop, base); + rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, base); } } - } // End of base register loop + } /* End of base register loop */ if (cpqhp_legacy_mode) { - // Figure out which interrupt pin this function uses + /* Figure out which interrupt pin this function uses */ rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_INTERRUPT_PIN, &temp_byte); - // If this function needs an interrupt and we are behind a bridge - // and the pin is tied to something that's alread mapped, - // set this one the same + /* If this function needs an interrupt and we are behind + * a bridge and the pin is tied to something that's + * alread mapped, set this one the same */ if (temp_byte && resources->irqs && (resources->irqs->valid_INT & (0x01 << ((temp_byte + resources->irqs->barber_pole - 1) & 0x03)))) { - // We have to share with something already set up + /* We have to share with something already set up */ IRQ = resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03]; } else { - // Program IRQ based on card type + /* Program IRQ based on card type */ rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code); if (class_code == PCI_BASE_CLASS_STORAGE) { @@ -3045,43 +3040,59 @@ static int configure_new_function (struc } } - // IRQ Line + /* IRQ Line */ rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_INTERRUPT_LINE, IRQ); } if (!behind_bridge) { rc = cpqhp_set_irq(func->bus, func->device, temp_byte + 0x09, IRQ); if (rc) - return(1); + return 1; } else { - //TBD - this code may also belong in the other clause of this If statement + /* TBD - this code may also belong in the other clause + * of this If statement */ resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03] = IRQ; resources->irqs->valid_INT |= 0x01 << (temp_byte + resources->irqs->barber_pole - 1) & 0x03; } - // Latency Timer + /* Latency Timer */ temp_byte = 0x40; - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte); + rc = pci_bus_write_config_byte(pci_bus, devfn, + PCI_LATENCY_TIMER, temp_byte); - // Cache Line size + /* Cache Line size */ temp_byte = 0x08; - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte); + rc = pci_bus_write_config_byte(pci_bus, devfn, + PCI_CACHE_LINE_SIZE, temp_byte); - // disable ROM base Address + /* disable ROM base Address */ temp_dword = 0x00L; - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_ROM_ADDRESS, temp_dword); + rc = pci_bus_write_config_word(pci_bus, devfn, + PCI_ROM_ADDRESS, temp_dword); - // enable card - temp_word = 0x0157; // = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_COMMAND, temp_word); - } // End of Not-A-Bridge else - else { - // It's some strange type of PCI adapter (Cardbus?) - return(DEVICE_TYPE_NOT_SUPPORTED); + /* enable card */ + temp_word = 0x0157; /* = PCI_COMMAND_IO | + * PCI_COMMAND_MEMORY | + * PCI_COMMAND_MASTER | + * PCI_COMMAND_INVALIDATE | + * PCI_COMMAND_PARITY | + * PCI_COMMAND_SERR */ + rc = pci_bus_write_config_word (pci_bus, devfn, + PCI_COMMAND, temp_word); + } else { /* End of Not-A-Bridge else */ + /* It's some strange type of PCI adapter (Cardbus?) */ + return DEVICE_TYPE_NOT_SUPPORTED; } func->configured = 1; return 0; -} +free_and_out: + cpqhp_destroy_resource_list (&temp_resources); + return_resource(&(resources-> bus_head), hold_bus_node); + return_resource(&(resources-> io_head), hold_IO_node); + return_resource(&(resources-> mem_head), hold_mem_node); + return_resource(&(resources-> p_mem_head), hold_p_mem_node); + return rc; +} --- linux-2.6.6/drivers/pci/hotplug/cpqphp.h 2004-03-10 20:41:29.000000000 -0800 +++ 25/drivers/pci/hotplug/cpqphp.h 2004-05-10 01:19:03.994131856 -0700 @@ -33,11 +33,7 @@ #include /* for read? and write? functions */ #include /* for delays */ -#if !defined(CONFIG_HOTPLUG_PCI_COMPAQ_MODULE) - #define MY_NAME "cpqphp.o" -#else - #define MY_NAME THIS_MODULE->name -#endif +#define MY_NAME "cpqphp" #define dbg(fmt, arg...) do { if (cpqhp_debug) printk(KERN_DEBUG "%s: " fmt , MY_NAME , ## arg); } while (0) #define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg) @@ -257,9 +253,7 @@ struct pci_func { struct pci_dev* pci_dev; }; -#define SLOT_MAGIC 0x67267321 struct slot { - u32 magic; struct slot *next; u8 bus; u8 device; @@ -377,11 +371,8 @@ struct resource_lists { #define PCISLOT_66_MHZ_SUPPORTED 0x00000100 #define PCISLOT_64_BIT_SUPPORTED 0x00000200 - - #define PCI_TO_PCI_BRIDGE_CLASS 0x00060400 - #define INTERLOCK_OPEN 0x00000002 #define ADD_NOT_SUPPORTED 0x00000003 #define CARD_FUNCTIONING 0x00000005 @@ -453,50 +444,15 @@ extern u8 cpqhp_nic_irq; extern u8 cpqhp_disk_irq; - /* inline functions */ - -/* Inline functions to check the sanity of a pointer that is passed to us */ -static inline int slot_paranoia_check (struct slot *slot, const char *function) -{ - if (!slot) { - dbg("%s - slot == NULL", function); - return -1; - } - if (slot->magic != SLOT_MAGIC) { - dbg("%s - bad magic number for slot", function); - return -1; - } - if (!slot->hotplug_slot) { - dbg("%s - slot->hotplug_slot == NULL!", function); - return -1; - } - return 0; -} - -static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const char *function) -{ - struct slot *slot; - - if (!hotplug_slot) { - dbg("%s - hotplug_slot == NULL\n", function); - return NULL; - } - - slot = (struct slot *)hotplug_slot->private; - if (slot_paranoia_check (slot, function)) - return NULL; - return slot; -} - /* * return_resource * * Puts node back in the resource list pointed to by head * */ -static inline void return_resource (struct pci_resource **head, struct pci_resource *node) +static inline void return_resource(struct pci_resource **head, struct pci_resource *node) { if (!node || !head) return; @@ -504,7 +460,7 @@ static inline void return_resource (stru *head = node; } -static inline void set_SOGO (struct controller *ctrl) +static inline void set_SOGO(struct controller *ctrl) { u16 misc; @@ -514,7 +470,7 @@ static inline void set_SOGO (struct cont } -static inline void amber_LED_on (struct controller *ctrl, u8 slot) +static inline void amber_LED_on(struct controller *ctrl, u8 slot) { u32 led_control; @@ -524,7 +480,7 @@ static inline void amber_LED_on (struct } -static inline void amber_LED_off (struct controller *ctrl, u8 slot) +static inline void amber_LED_off(struct controller *ctrl, u8 slot) { u32 led_control; @@ -534,7 +490,7 @@ static inline void amber_LED_off (struct } -static inline int read_amber_LED (struct controller *ctrl, u8 slot) +static inline int read_amber_LED(struct controller *ctrl, u8 slot) { u32 led_control; @@ -545,7 +501,7 @@ static inline int read_amber_LED (struct } -static inline void green_LED_on (struct controller *ctrl, u8 slot) +static inline void green_LED_on(struct controller *ctrl, u8 slot) { u32 led_control; @@ -554,7 +510,7 @@ static inline void green_LED_on (struct writel(led_control, ctrl->hpc_reg + LED_CONTROL); } -static inline void green_LED_off (struct controller *ctrl, u8 slot) +static inline void green_LED_off(struct controller *ctrl, u8 slot) { u32 led_control; @@ -564,7 +520,7 @@ static inline void green_LED_off (struct } -static inline void green_LED_blink (struct controller *ctrl, u8 slot) +static inline void green_LED_blink(struct controller *ctrl, u8 slot) { u32 led_control; @@ -575,7 +531,7 @@ static inline void green_LED_blink (stru } -static inline void slot_disable (struct controller *ctrl, u8 slot) +static inline void slot_disable(struct controller *ctrl, u8 slot) { u8 slot_enable; @@ -585,7 +541,7 @@ static inline void slot_disable (struct } -static inline void slot_enable (struct controller *ctrl, u8 slot) +static inline void slot_enable(struct controller *ctrl, u8 slot) { u8 slot_enable; @@ -595,7 +551,7 @@ static inline void slot_enable (struct c } -static inline u8 is_slot_enabled (struct controller *ctrl, u8 slot) +static inline u8 is_slot_enabled(struct controller *ctrl, u8 slot) { u8 slot_enable; @@ -605,7 +561,7 @@ static inline u8 is_slot_enabled (struct } -static inline u8 read_slot_enable (struct controller *ctrl) +static inline u8 read_slot_enable(struct controller *ctrl) { return readb(ctrl->hpc_reg + SLOT_ENABLE); } @@ -619,7 +575,7 @@ static inline u8 read_slot_enable (struc * Returns controller speed. * */ -static inline u8 get_controller_speed (struct controller *ctrl) +static inline u8 get_controller_speed(struct controller *ctrl) { u8 curr_freq; u16 misc; @@ -652,7 +608,7 @@ static inline u8 get_controller_speed (s * Returns adapter speed. * */ -static inline u8 get_adapter_speed (struct controller *ctrl, u8 hp_slot) +static inline u8 get_adapter_speed(struct controller *ctrl, u8 hp_slot) { u32 temp_dword = readl(ctrl->hpc_reg + NON_INT_INPUT); dbg("slot: %d, PCIXCAP: %8x\n", hp_slot, temp_dword); @@ -669,7 +625,7 @@ static inline u8 get_adapter_speed (stru return PCI_SPEED_33MHz; } -static inline void enable_slot_power (struct controller *ctrl, u8 slot) +static inline void enable_slot_power(struct controller *ctrl, u8 slot) { u8 slot_power; @@ -678,7 +634,7 @@ static inline void enable_slot_power (st writeb(slot_power, ctrl->hpc_reg + SLOT_POWER); } -static inline void disable_slot_power (struct controller *ctrl, u8 slot) +static inline void disable_slot_power(struct controller *ctrl, u8 slot) { u8 slot_power; @@ -688,40 +644,31 @@ static inline void disable_slot_power (s } -static inline int cpq_get_attention_status (struct controller *ctrl, struct slot *slot) +static inline int cpq_get_attention_status(struct controller *ctrl, struct slot *slot) { u8 hp_slot; - if (slot == NULL) - return 1; - hp_slot = slot->device - ctrl->slot_device_offset; - return read_amber_LED (ctrl, hp_slot); + return read_amber_LED(ctrl, hp_slot); } -static inline int get_slot_enabled (struct controller *ctrl, struct slot *slot) +static inline int get_slot_enabled(struct controller *ctrl, struct slot *slot) { u8 hp_slot; - if (slot == NULL) - return 1; - hp_slot = slot->device - ctrl->slot_device_offset; - return is_slot_enabled (ctrl, hp_slot); + return is_slot_enabled(ctrl, hp_slot); } -static inline int cpq_get_latch_status (struct controller *ctrl, struct slot *slot) +static inline int cpq_get_latch_status(struct controller *ctrl, struct slot *slot) { u32 status; u8 hp_slot; - if (slot == NULL) - return 1; - hp_slot = slot->device - ctrl->slot_device_offset; dbg("%s: slot->device = %d, ctrl->slot_device_offset = %d \n", __FUNCTION__, slot->device, ctrl->slot_device_offset); @@ -732,15 +679,12 @@ static inline int cpq_get_latch_status ( } -static inline int get_presence_status (struct controller *ctrl, struct slot *slot) +static inline int get_presence_status(struct controller *ctrl, struct slot *slot) { int presence_save = 0; u8 hp_slot; u32 tempdword; - if (slot == NULL) - return 0; - hp_slot = slot->device - ctrl->slot_device_offset; tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR); @@ -751,13 +695,13 @@ static inline int get_presence_status (s #define SLOT_NAME_SIZE 10 -static inline void make_slot_name (char *buffer, int buffer_size, struct slot *slot) +static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot) { - snprintf (buffer, buffer_size, "%d", slot->number); + snprintf(buffer, buffer_size, "%d", slot->number); } -static inline int wait_for_ctrl_irq (struct controller *ctrl) +static inline int wait_for_ctrl_irq(struct controller *ctrl) { DECLARE_WAITQUEUE(wait, current); int retval = 0; @@ -775,138 +719,5 @@ static inline int wait_for_ctrl_irq (str return retval; } - -/** - * set_controller_speed - set the frequency and/or mode of a specific - * controller segment. - * - * @ctrl: controller to change frequency/mode for. - * @adapter_speed: the speed of the adapter we want to match. - * @hp_slot: the slot number where the adapter is installed. - * - * Returns 0 if we successfully change frequency and/or mode to match the - * adapter speed. - * - */ -static inline u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_slot) -{ - struct slot *slot; - u8 reg; - u8 slot_power = readb(ctrl->hpc_reg + SLOT_POWER); - u16 reg16; - u32 leds = readl(ctrl->hpc_reg + LED_CONTROL); - - if (ctrl->speed == adapter_speed) - return 0; - - /* We don't allow freq/mode changes if we find another adapter running - * in another slot on this controller */ - for(slot = ctrl->slot; slot; slot = slot->next) { - if (slot->device == (hp_slot + ctrl->slot_device_offset)) - continue; - if (!slot->hotplug_slot && !slot->hotplug_slot->info) - continue; - if (slot->hotplug_slot->info->adapter_status == 0) - continue; - /* If another adapter is running on the same segment but at a - * lower speed/mode, we allow the new adapter to function at - * this rate if supported */ - if (ctrl->speed < adapter_speed) - return 0; - - return 1; - } - - /* If the controller doesn't support freq/mode changes and the - * controller is running at a higher mode, we bail */ - if ((ctrl->speed > adapter_speed) && (!ctrl->pcix_speed_capability)) - return 1; - - /* But we allow the adapter to run at a lower rate if possible */ - if ((ctrl->speed < adapter_speed) && (!ctrl->pcix_speed_capability)) - return 0; - - /* We try to set the max speed supported by both the adapter and - * controller */ - if (ctrl->speed_capability < adapter_speed) { - if (ctrl->speed == ctrl->speed_capability) - return 0; - adapter_speed = ctrl->speed_capability; - } - - writel(0x0L, ctrl->hpc_reg + LED_CONTROL); - writeb(0x00, ctrl->hpc_reg + SLOT_ENABLE); - - set_SOGO(ctrl); - wait_for_ctrl_irq(ctrl); - - if (adapter_speed != PCI_SPEED_133MHz_PCIX) - reg = 0xF5; - else - reg = 0xF4; - pci_write_config_byte(ctrl->pci_dev, 0x41, reg); - - reg16 = readw(ctrl->hpc_reg + NEXT_CURR_FREQ); - reg16 &= ~0x000F; - switch(adapter_speed) { - case(PCI_SPEED_133MHz_PCIX): - reg = 0x75; - reg16 |= 0xB; - break; - case(PCI_SPEED_100MHz_PCIX): - reg = 0x74; - reg16 |= 0xA; - break; - case(PCI_SPEED_66MHz_PCIX): - reg = 0x73; - reg16 |= 0x9; - break; - case(PCI_SPEED_66MHz): - reg = 0x73; - reg16 |= 0x1; - break; - default: /* 33MHz PCI 2.2 */ - reg = 0x71; - break; - - } - reg16 |= 0xB << 12; - writew(reg16, ctrl->hpc_reg + NEXT_CURR_FREQ); - - mdelay(5); - - /* Reenable interrupts */ - writel(0, ctrl->hpc_reg + INT_MASK); - - pci_write_config_byte(ctrl->pci_dev, 0x41, reg); - - /* Restart state machine */ - reg = ~0xF; - pci_read_config_byte(ctrl->pci_dev, 0x43, ®); - pci_write_config_byte(ctrl->pci_dev, 0x43, reg); - - /* Only if mode change...*/ - if (((ctrl->speed == PCI_SPEED_66MHz) && (adapter_speed == PCI_SPEED_66MHz_PCIX)) || - ((ctrl->speed == PCI_SPEED_66MHz_PCIX) && (adapter_speed == PCI_SPEED_66MHz))) - set_SOGO(ctrl); - - wait_for_ctrl_irq(ctrl); - mdelay(1100); - - /* Restore LED/Slot state */ - writel(leds, ctrl->hpc_reg + LED_CONTROL); - writeb(slot_power, ctrl->hpc_reg + SLOT_ENABLE); - - set_SOGO(ctrl); - wait_for_ctrl_irq(ctrl); - - ctrl->speed = adapter_speed; - slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); - - info("Successfully changed frequency/mode for adapter in slot %d\n", - slot->number); - return 0; -} - #endif --- linux-2.6.6/drivers/pci/hotplug/cpqphp_pci.c 2004-03-10 20:41:29.000000000 -0800 +++ 25/drivers/pci/hotplug/cpqphp_pci.c 2004-05-10 01:19:04.019128056 -0700 @@ -722,23 +722,23 @@ int cpqhp_save_used_resources (struct co devfn = PCI_DEVFN(func->device, func->function); // Save the command register - pci_bus_read_config_word (pci_bus, devfn, PCI_COMMAND, &save_command); + pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &save_command); // disable card command = 0x00; - pci_bus_write_config_word (pci_bus, devfn, PCI_COMMAND, command); + pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command); // Check for Bridge - pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type); + pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type); if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge // Clear Bridge Control Register command = 0x00; - pci_bus_write_config_word (pci_bus, devfn, PCI_BRIDGE_CONTROL, command); - pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus); - pci_bus_read_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte); + pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command); + pci_bus_read_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus); + pci_bus_read_config_byte(pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte); - bus_node =(struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + bus_node = kmalloc(sizeof(*bus_node), GFP_KERNEL); if (!bus_node) return -ENOMEM; @@ -749,11 +749,11 @@ int cpqhp_save_used_resources (struct co func->bus_head = bus_node; // Save IO base and Limit registers - pci_bus_read_config_byte (pci_bus, devfn, PCI_IO_BASE, &b_base); - pci_bus_read_config_byte (pci_bus, devfn, PCI_IO_LIMIT, &b_length); + pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_BASE, &b_base); + pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_LIMIT, &b_length); if ((b_base <= b_length) && (save_command & 0x01)) { - io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + io_node = kmalloc(sizeof(*io_node), GFP_KERNEL); if (!io_node) return -ENOMEM; @@ -765,11 +765,11 @@ int cpqhp_save_used_resources (struct co } // Save memory base and Limit registers - pci_bus_read_config_word (pci_bus, devfn, PCI_MEMORY_BASE, &w_base); - pci_bus_read_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length); + pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_BASE, &w_base); + pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length); if ((w_base <= w_length) && (save_command & 0x02)) { - mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + mem_node = kmalloc(sizeof(*mem_node), GFP_KERNEL); if (!mem_node) return -ENOMEM; @@ -781,11 +781,11 @@ int cpqhp_save_used_resources (struct co } // Save prefetchable memory base and Limit registers - pci_bus_read_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base); - pci_bus_read_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length); + pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base); + pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length); if ((w_base <= w_length) && (save_command & 0x02)) { - p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + p_mem_node = kmalloc(sizeof(*p_mem_node), GFP_KERNEL); if (!p_mem_node) return -ENOMEM; @@ -800,8 +800,8 @@ int cpqhp_save_used_resources (struct co pci_bus_read_config_dword (pci_bus, devfn, cloop, &save_base); temp_register = 0xFFFFFFFF; - pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register); - pci_bus_read_config_dword (pci_bus, devfn, cloop, &base); + pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register); + pci_bus_read_config_dword(pci_bus, devfn, cloop, &base); temp_register = base; @@ -813,7 +813,8 @@ int cpqhp_save_used_resources (struct co temp_register = base & 0xFFFFFFFE; temp_register = (~temp_register) + 1; - io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + io_node = kmalloc(sizeof(*io_node), + GFP_KERNEL); if (!io_node) return -ENOMEM; @@ -830,7 +831,8 @@ int cpqhp_save_used_resources (struct co temp_register = base & 0xFFFFFFF0; temp_register = (~temp_register) + 1; - p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + p_mem_node = kmalloc(sizeof(*p_mem_node), + GFP_KERNEL); if (!p_mem_node) return -ENOMEM; @@ -846,7 +848,8 @@ int cpqhp_save_used_resources (struct co temp_register = base & 0xFFFFFFF0; temp_register = (~temp_register) + 1; - mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + mem_node = kmalloc(sizeof(*mem_node), + GFP_KERNEL); if (!mem_node) return -ENOMEM; @@ -862,11 +865,11 @@ int cpqhp_save_used_resources (struct co } else if ((header_type & 0x7F) == 0x00) { // Standard header // Figure out IO and memory base lengths for (cloop = 0x10; cloop <= 0x24; cloop += 4) { - pci_bus_read_config_dword (pci_bus, devfn, cloop, &save_base); + pci_bus_read_config_dword(pci_bus, devfn, cloop, &save_base); temp_register = 0xFFFFFFFF; - pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register); - pci_bus_read_config_dword (pci_bus, devfn, cloop, &base); + pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register); + pci_bus_read_config_dword(pci_bus, devfn, cloop, &base); temp_register = base; @@ -878,7 +881,8 @@ int cpqhp_save_used_resources (struct co temp_register = base & 0xFFFFFFFE; temp_register = (~temp_register) + 1; - io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + io_node = kmalloc(sizeof(*io_node), + GFP_KERNEL); if (!io_node) return -ENOMEM; @@ -894,7 +898,8 @@ int cpqhp_save_used_resources (struct co temp_register = base & 0xFFFFFFF0; temp_register = (~temp_register) + 1; - p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + p_mem_node = kmalloc(sizeof(*p_mem_node), + GFP_KERNEL); if (!p_mem_node) return -ENOMEM; @@ -910,7 +915,8 @@ int cpqhp_save_used_resources (struct co temp_register = base & 0xFFFFFFF0; temp_register = (~temp_register) + 1; - mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + mem_node = kmalloc(sizeof(*mem_node), + GFP_KERNEL); if (!mem_node) return -ENOMEM; @@ -1293,14 +1299,15 @@ int cpqhp_find_available_resources (stru temp_dword = io_base + io_length; if ((io_base) && (temp_dword < 0x10000)) { - io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + io_node = kmalloc(sizeof(*io_node), GFP_KERNEL); if (!io_node) return -ENOMEM; io_node->base = io_base; io_node->length = io_length; - dbg("found io_node(base, length) = %x, %x\n", io_node->base, io_node->length); + dbg("found io_node(base, length) = %x, %x\n", + io_node->base, io_node->length); dbg("populated slot =%d \n", populated_slot); if (!populated_slot) { io_node->next = ctrl->io_head; @@ -1314,7 +1321,7 @@ int cpqhp_find_available_resources (stru // If we've got a valid memory base, use it temp_dword = mem_base + mem_length; if ((mem_base) && (temp_dword < 0x10000)) { - mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + mem_node = kmalloc(sizeof(*mem_node), GFP_KERNEL); if (!mem_node) return -ENOMEM; @@ -1322,7 +1329,8 @@ int cpqhp_find_available_resources (stru mem_node->length = mem_length << 16; - dbg("found mem_node(base, length) = %x, %x\n", mem_node->base, mem_node->length); + dbg("found mem_node(base, length) = %x, %x\n", + mem_node->base, mem_node->length); dbg("populated slot =%d \n", populated_slot); if (!populated_slot) { mem_node->next = ctrl->mem_head; @@ -1337,14 +1345,15 @@ int cpqhp_find_available_resources (stru // the base + length isn't greater than 0xFFFF temp_dword = pre_mem_base + pre_mem_length; if ((pre_mem_base) && (temp_dword < 0x10000)) { - p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + p_mem_node = kmalloc(sizeof(*p_mem_node), GFP_KERNEL); if (!p_mem_node) return -ENOMEM; p_mem_node->base = pre_mem_base << 16; p_mem_node->length = pre_mem_length << 16; - dbg("found p_mem_node(base, length) = %x, %x\n", p_mem_node->base, p_mem_node->length); + dbg("found p_mem_node(base, length) = %x, %x\n", + p_mem_node->base, p_mem_node->length); dbg("populated slot =%d \n", populated_slot); if (!populated_slot) { @@ -1360,13 +1369,14 @@ int cpqhp_find_available_resources (stru // The second condition is to ignore bus numbers on // populated slots that don't have PCI-PCI bridges if (secondary_bus && (secondary_bus != primary_bus)) { - bus_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + bus_node = kmalloc(sizeof(*bus_node), GFP_KERNEL); if (!bus_node) return -ENOMEM; bus_node->base = secondary_bus; bus_node->length = max_bus - secondary_bus + 1; - dbg("found bus_node(base, length) = %x, %x\n", bus_node->base, bus_node->length); + dbg("found bus_node(base, length) = %x, %x\n", + bus_node->base, bus_node->length); dbg("populated slot =%d \n", populated_slot); if (!populated_slot) { bus_node->next = ctrl->bus_head; --- linux-2.6.6/drivers/pci/hotplug/pciehp_core.c 2004-03-10 20:41:29.000000000 -0800 +++ 25/drivers/pci/hotplug/pciehp_core.c 2004-05-10 01:19:04.024127296 -0700 @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -45,7 +46,7 @@ int pciehp_debug; int pciehp_poll_mode; int pciehp_poll_time; -struct controller *pciehp_ctrl_list; /* = NULL */ +struct controller *pciehp_ctrl_list; struct pci_func *pciehp_slot_list[256]; #define DRIVER_VERSION "0.4" @@ -56,9 +57,9 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -MODULE_PARM(pciehp_debug, "i"); -MODULE_PARM(pciehp_poll_mode, "i"); -MODULE_PARM(pciehp_poll_time, "i"); +module_param(pciehp_debug, bool, 644); +module_param(pciehp_poll_mode, bool, 644); +module_param(pciehp_poll_time, int, 644); MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not"); MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not"); MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds"); @@ -69,7 +70,6 @@ static int pcie_start_thread (void); static int set_attention_status (struct hotplug_slot *slot, u8 value); static int enable_slot (struct hotplug_slot *slot); static int disable_slot (struct hotplug_slot *slot); -static int hardware_test (struct hotplug_slot *slot, u32 value); static int get_power_status (struct hotplug_slot *slot, u8 *value); static int get_attention_status (struct hotplug_slot *slot, u8 *value); static int get_latch_status (struct hotplug_slot *slot, u8 *value); @@ -82,7 +82,6 @@ static struct hotplug_slot_ops pciehp_ho .set_attention_status = set_attention_status, .enable_slot = enable_slot, .disable_slot = disable_slot, - .hardware_test = hardware_test, .get_power_status = get_power_status, .get_attention_status = get_attention_status, .get_latch_status = get_latch_status, @@ -97,7 +96,7 @@ static int init_slots(struct controller u8 number_of_slots; u8 slot_device; u32 slot_number; - int result; + int result = -ENOMEM; dbg("%s\n",__FUNCTION__); @@ -106,34 +105,30 @@ static int init_slots(struct controller slot_number = ctrl->first_slot; while (number_of_slots) { - new_slot = (struct slot *) kmalloc(sizeof(struct slot), GFP_KERNEL); + new_slot = kmalloc(sizeof(*new_slot), GFP_KERNEL); if (!new_slot) - return -ENOMEM; + goto error; memset(new_slot, 0, sizeof(struct slot)); - new_slot->hotplug_slot = kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL); - if (!new_slot->hotplug_slot) { - kfree (new_slot); - return -ENOMEM; - } - memset(new_slot->hotplug_slot, 0, sizeof (struct hotplug_slot)); - - new_slot->hotplug_slot->info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL); - if (!new_slot->hotplug_slot->info) { - kfree (new_slot->hotplug_slot); - kfree (new_slot); - return -ENOMEM; - } - memset(new_slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info)); - new_slot->hotplug_slot->name = kmalloc (SLOT_NAME_SIZE, GFP_KERNEL); - if (!new_slot->hotplug_slot->name) { - kfree (new_slot->hotplug_slot->info); - kfree (new_slot->hotplug_slot); - kfree (new_slot); - return -ENOMEM; - } + new_slot->hotplug_slot = + kmalloc(sizeof(*(new_slot->hotplug_slot)), + GFP_KERNEL); + if (!new_slot->hotplug_slot) + goto error_slot; + memset(new_slot->hotplug_slot, 0, sizeof(struct hotplug_slot)); + + new_slot->hotplug_slot->info = + kmalloc(sizeof(*(new_slot->hotplug_slot->info)), + GFP_KERNEL); + if (!new_slot->hotplug_slot->info) + goto error_hpslot; + memset(new_slot->hotplug_slot->info, 0, + sizeof(struct hotplug_slot_info)); + new_slot->hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, + GFP_KERNEL); + if (!new_slot->hotplug_slot->name) + goto error_info; - new_slot->magic = SLOT_MAGIC; new_slot->ctrl = ctrl; new_slot->bus = ctrl->slot_bus; new_slot->device = slot_device; @@ -157,11 +152,7 @@ static int init_slots(struct controller result = pci_hp_register (new_slot->hotplug_slot); if (result) { err ("pci_hp_register failed with error %d\n", result); - kfree (new_slot->hotplug_slot->info); - kfree (new_slot->hotplug_slot->name); - kfree (new_slot->hotplug_slot); - kfree (new_slot); - return result; + goto error_name; } new_slot->next = ctrl->slot; @@ -172,7 +163,18 @@ static int init_slots(struct controller slot_number += ctrl->slot_num_inc; } - return(0); + return 0; + +error_name: + kfree(new_slot->hotplug_slot->name); +error_info: + kfree(new_slot->hotplug_slot->info); +error_hpslot: + kfree(new_slot->hotplug_slot); +error_slot: + kfree(new_slot); +error: + return result; } @@ -228,13 +230,10 @@ static int get_ctlr_slot_config(struct c /* * set_attention_status - Turns the Amber LED for a slot on, off or blink */ -static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) +static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = hotplug_slot->private; - if (slot == NULL) - return -ENODEV; - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); hotplug_slot->info->attention_status = status; @@ -244,12 +243,9 @@ static int set_attention_status (struct } -static int enable_slot (struct hotplug_slot *hotplug_slot) +static int enable_slot(struct hotplug_slot *hotplug_slot) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); - - if (slot == NULL) - return -ENODEV; + struct slot *slot = hotplug_slot->private; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -257,33 +253,20 @@ static int enable_slot (struct hotplug_s } -static int disable_slot (struct hotplug_slot *hotplug_slot) +static int disable_slot(struct hotplug_slot *hotplug_slot) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); - - if (slot == NULL) - return -ENODEV; + struct slot *slot = hotplug_slot->private; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); return pciehp_disable_slot(slot); } - -static int hardware_test (struct hotplug_slot *hotplug_slot, u32 value) +static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) { - return 0; -} - - -static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) -{ - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = hotplug_slot->private; int retval; - - if (slot == NULL) - return -ENODEV; - + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); retval = slot->hpc_ops->get_power_status(slot, value); @@ -293,14 +276,11 @@ static int get_power_status (struct hotp return 0; } -static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) +static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = hotplug_slot->private; int retval; - - if (slot == NULL) - return -ENODEV; - + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); retval = slot->hpc_ops->get_attention_status(slot, value); @@ -310,14 +290,11 @@ static int get_attention_status (struct return 0; } -static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) +static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = hotplug_slot->private; int retval; - - if (slot == NULL) - return -ENODEV; - + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); retval = slot->hpc_ops->get_latch_status(slot, value); @@ -327,31 +304,24 @@ static int get_latch_status (struct hotp return 0; } -static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) +static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = hotplug_slot->private; int retval; - - if (slot == NULL) - return -ENODEV; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); retval = slot->hpc_ops->get_adapter_status(slot, value); - if (retval < 0) *value = hotplug_slot->info->adapter_status; return 0; } -static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) +static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = hotplug_slot->private; int retval; - - if (slot == NULL) - return -ENODEV; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -362,13 +332,10 @@ static int get_max_bus_speed (struct hot return 0; } -static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) +static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = hotplug_slot->private; int retval; - - if (slot == NULL) - return -ENODEV; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -388,7 +355,7 @@ static int pcie_probe(struct pci_dev *pd int num_ctlr_slots; /* number of slots supported by this HPC */ u8 value; - ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL); + ctrl = kmalloc(sizeof(*ctrl), GFP_KERNEL); if (!ctrl) { err("%s : out of memory\n", __FUNCTION__); goto err_out_none; @@ -411,7 +378,7 @@ static int pcie_probe(struct pci_dev *pd pci_set_drvdata(pdev, ctrl); - ctrl->pci_bus = kmalloc (sizeof (*ctrl->pci_bus), GFP_KERNEL); + ctrl->pci_bus = kmalloc(sizeof(*ctrl->pci_bus), GFP_KERNEL); if (!ctrl->pci_bus) { err("%s: out of memory\n", __FUNCTION__); rc = -ENOMEM; @@ -535,49 +502,35 @@ static int pcie_start_thread(void) return retval; } +static inline void __exit +free_pciehp_res(struct pci_resource *res) +{ + struct pci_resource *tres; + + while (res) { + tres = res; + res = res->next; + kfree(tres); + } +} -static void unload_pciehpd(void) +static void __exit unload_pciehpd(void) { struct pci_func *next; struct pci_func *TempSlot; int loop; struct controller *ctrl; struct controller *tctrl; - struct pci_resource *res; - struct pci_resource *tres; ctrl = pciehp_ctrl_list; while (ctrl) { cleanup_slots(ctrl); - res = ctrl->io_head; - while (res) { - tres = res; - res = res->next; - kfree(tres); - } - - res = ctrl->mem_head; - while (res) { - tres = res; - res = res->next; - kfree(tres); - } - - res = ctrl->p_mem_head; - while (res) { - tres = res; - res = res->next; - kfree(tres); - } - - res = ctrl->bus_head; - while (res) { - tres = res; - res = res->next; - kfree(tres); - } + free_pciehp_res(ctrl->io_head); + free_pciehp_res(ctrl->mem_head); + free_pciehp_res(ctrl->p_mem_head); + free_pciehp_res(ctrl->bus_head); kfree (ctrl->pci_bus); @@ -592,33 +545,10 @@ static void unload_pciehpd(void) for (loop = 0; loop < 256; loop++) { next = pciehp_slot_list[loop]; while (next != NULL) { - res = next->io_head; - while (res) { - tres = res; - res = res->next; - kfree(tres); - } - - res = next->mem_head; - while (res) { - tres = res; - res = res->next; - kfree(tres); - } - - res = next->p_mem_head; - while (res) { - tres = res; - res = res->next; - kfree(tres); - } - - res = next->bus_head; - while (res) { - tres = res; - res = res->next; - kfree(tres); - } + free_pciehp_res(ctrl->io_head); + free_pciehp_res(ctrl->mem_head); + free_pciehp_res(ctrl->p_mem_head); + free_pciehp_res(ctrl->bus_head); TempSlot = next; next = next->next; @@ -700,8 +630,5 @@ static void __exit pcied_cleanup(void) info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); } - module_init(pcied_init); module_exit(pcied_cleanup); - - --- linux-2.6.6/drivers/pci/hotplug/pciehp_ctrl.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/pci/hotplug/pciehp_ctrl.c 2004-05-10 01:19:04.034125776 -0700 @@ -251,12 +251,10 @@ u8 pciehp_handle_power_fault(u8 hp_slot, } -/* - * sort_by_size - * - * Sorts nodes on the list by their length. - * Smallest first. +/** + * sort_by_size: sort nodes by their length, smallest first. * + * @head: list to sort */ static int sort_by_size(struct pci_resource **head) { @@ -265,10 +263,10 @@ static int sort_by_size(struct pci_resou int out_of_order = 1; if (!(*head)) - return(1); + return 1; if (!((*head)->next)) - return(0); + return 0; while (out_of_order) { out_of_order = 0; @@ -298,7 +296,7 @@ static int sort_by_size(struct pci_resou } } /* End of out_of_order loop */ - return(0); + return 0; } @@ -316,10 +314,10 @@ static int sort_by_max_size(struct pci_r int out_of_order = 1; if (!(*head)) - return(1); + return 1; if (!((*head)->next)) - return(0); + return 0; while (out_of_order) { out_of_order = 0; @@ -349,17 +347,18 @@ static int sort_by_max_size(struct pci_r } } /* End of out_of_order loop */ - return(0); + return 0; } -/* - * do_pre_bridge_resource_split - * - * Returns zero or one node of resources that aren't in use +/** + * do_pre_bridge_resource_split: return one unused resource node + * @head: list to scan * */ -static struct pci_resource *do_pre_bridge_resource_split (struct pci_resource **head, struct pci_resource **orig_head, u32 alignment) +static struct pci_resource * +do_pre_bridge_resource_split(struct pci_resource **head, + struct pci_resource **orig_head, u32 alignment) { struct pci_resource *prevnode = NULL; struct pci_resource *node; @@ -369,18 +368,18 @@ static struct pci_resource *do_pre_bridg dbg("do_pre_bridge_resource_split\n"); if (!(*head) || !(*orig_head)) - return(NULL); + return NULL; rc = pciehp_resource_sort_and_combine(head); if (rc) - return(NULL); + return NULL; if ((*head)->base != (*orig_head)->base) - return(NULL); + return NULL; if ((*head)->length == (*orig_head)->length) - return(NULL); + return NULL; /* If we got here, there the bridge requires some of the resource, but @@ -392,10 +391,10 @@ static struct pci_resource *do_pre_bridg /* this one isn't an aligned length, so we'll make a new entry * and split it up. */ - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + split_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); if (!split_node) - return(NULL); + return NULL; temp_dword = (node->length | (alignment-1)) + 1 - alignment; @@ -410,34 +409,32 @@ static struct pci_resource *do_pre_bridg split_node->next = node; } - if (node->length < alignment) { - return(NULL); - } + if (node->length < alignment) + return NULL; /* Now unlink it */ if (*head == node) { *head = node->next; - node->next = NULL; } else { prevnode = *head; while (prevnode->next != node) prevnode = prevnode->next; prevnode->next = node->next; - node->next = NULL; } + node->next = NULL; - return(node); + return node; } -/* - * do_bridge_resource_split - * - * Returns zero or one node of resources that aren't in use +/** + * do_bridge_resource_split: return one unused resource node + * @head: list to scan * */ -static struct pci_resource *do_bridge_resource_split (struct pci_resource **head, u32 alignment) +static struct pci_resource * +do_bridge_resource_split(struct pci_resource **head, u32 alignment) { struct pci_resource *prevnode = NULL; struct pci_resource *node; @@ -445,12 +442,12 @@ static struct pci_resource *do_bridge_re u32 temp_dword; if (!(*head)) - return(NULL); + return NULL; rc = pciehp_resource_sort_and_combine(head); if (rc) - return(NULL); + return NULL; node = *head; @@ -462,7 +459,7 @@ static struct pci_resource *do_bridge_re if (node->length < alignment) { kfree(node); - return(NULL); + return NULL; } if (node->base & (alignment - 1)) { @@ -470,7 +467,7 @@ static struct pci_resource *do_bridge_re temp_dword = (node->base | (alignment-1)) + 1; if ((node->length - (temp_dword - node->base)) < alignment) { kfree(node); - return(NULL); + return NULL; } node->length -= (temp_dword - node->base); @@ -480,10 +477,10 @@ static struct pci_resource *do_bridge_re if (node->length & (alignment - 1)) { /* There's stuff in use after this node */ kfree(node); - return(NULL); + return NULL; } - return(node); + return node; } @@ -497,7 +494,7 @@ static struct pci_resource *do_bridge_re * * size must be a power of two. */ -static struct pci_resource *get_io_resource (struct pci_resource **head, u32 size) +static struct pci_resource *get_io_resource(struct pci_resource **head, u32 size) { struct pci_resource *prevnode; struct pci_resource *node; @@ -505,13 +502,13 @@ static struct pci_resource *get_io_resou u32 temp_dword; if (!(*head)) - return(NULL); + return NULL; if ( pciehp_resource_sort_and_combine(head) ) - return(NULL); + return NULL; if ( sort_by_size(head) ) - return(NULL); + return NULL; for (node = *head; node; node = node->next) { if (node->length < size) @@ -526,10 +523,11 @@ static struct pci_resource *get_io_resou if ((node->length - (temp_dword - node->base)) < size) continue; - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + split_node = kmalloc(sizeof(struct pci_resource), + GFP_KERNEL); if (!split_node) - return(NULL); + return NULL; split_node->base = node->base; split_node->length = temp_dword - node->base; @@ -545,10 +543,11 @@ static struct pci_resource *get_io_resou if (node->length > size) { /* this one is longer than we need so we'll make a new entry and split it up */ - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + split_node = kmalloc(sizeof(struct pci_resource), + GFP_KERNEL); if (!split_node) - return(NULL); + return NULL; split_node->base = node->base + size; split_node->length = node->length - size; @@ -579,7 +578,7 @@ static struct pci_resource *get_io_resou break; } - return(node); + return node; } @@ -592,7 +591,7 @@ static struct pci_resource *get_io_resou * J.I. modified to put max size limits of; 64M->32M->16M->8M->4M->1M * This is needed to avoid allocating entire ACPI _CRS res to one child bridge/slot. */ -static struct pci_resource *get_max_resource (struct pci_resource **head, u32 size) +static struct pci_resource *get_max_resource(struct pci_resource **head, u32 size) { struct pci_resource *max; struct pci_resource *temp; @@ -602,13 +601,13 @@ static struct pci_resource *get_max_reso int i; if (!(*head)) - return(NULL); + return NULL; if (pciehp_resource_sort_and_combine(head)) - return(NULL); + return NULL; if (sort_by_max_size(head)) - return(NULL); + return NULL; for (max = *head;max; max = max->next) { @@ -626,10 +625,11 @@ static struct pci_resource *get_max_reso if ((max->length - (temp_dword - max->base)) < size) continue; - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + split_node = kmalloc(sizeof(struct pci_resource), + GFP_KERNEL); if (!split_node) - return(NULL); + return NULL; split_node->base = max->base; split_node->length = temp_dword - max->base; @@ -644,10 +644,11 @@ static struct pci_resource *get_max_reso if ((max->base + max->length) & (size - 1)) { /* this one isn't end aligned properly at the top so we'll make a new entry and split it up */ - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + split_node = kmalloc(sizeof(struct pci_resource), + GFP_KERNEL); if (!split_node) - return(NULL); + return NULL; temp_dword = ((max->base + max->length) & ~(size - 1)); split_node->base = temp_dword; split_node->length = max->length + max->base @@ -665,9 +666,10 @@ static struct pci_resource *get_max_reso for ( i = 0; max_size[i] > size; i++) { if (max->length > max_size[i]) { - split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + split_node = kmalloc(sizeof(struct pci_resource), + GFP_KERNEL); if (!split_node) - break; /* return (NULL); */ + break; /* return NULL; */ split_node->base = max->base + max_size[i]; split_node->length = max->length - max_size[i]; max->length = max_size[i]; @@ -691,11 +693,11 @@ static struct pci_resource *get_max_reso } max->next = NULL; - return(max); + return max; } /* If we get here, we couldn't find one */ - return(NULL); + return NULL; } @@ -708,7 +710,7 @@ static struct pci_resource *get_max_reso * * size must be a power of two. */ -static struct pci_resource *get_resource (struct pci_resource **head, u32 size) +static struct pci_resource *get_resource(struct pci_resource **head, u32 size) { struct pci_resource *prevnode; struct pci_resource *node; @@ -716,13 +718,13 @@ static struct pci_resource *get_resource u32 temp_dword; if (!(*head)) - return(NULL); + return NULL; if ( pciehp_resource_sort_and_combine(head) ) - return(NULL); + return NULL; if ( sort_by_size(head) ) - return(NULL); + return NULL; for (node = *head; node; node = node->next) { dbg("%s: req_size =0x%x node=%p, base=0x%x, length=0x%x\n", @@ -740,10 +742,11 @@ static struct pci_resource *get_resource if ((node->length - (temp_dword - node->base)) < size) continue; - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + split_node = kmalloc(sizeof(struct pci_resource), + GFP_KERNEL); if (!split_node) - return(NULL); + return NULL; split_node->base = node->base; split_node->length = temp_dword - node->base; @@ -760,10 +763,11 @@ static struct pci_resource *get_resource dbg("%s: too big\n", __FUNCTION__); /* this one is longer than we need so we'll make a new entry and split it up */ - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + split_node = kmalloc(sizeof(struct pci_resource), + GFP_KERNEL); if (!split_node) - return(NULL); + return NULL; split_node->base = node->base + size; split_node->length = node->length - size; @@ -790,7 +794,7 @@ static struct pci_resource *get_resource /* Stop looping */ break; } - return(node); + return node; } @@ -812,12 +816,12 @@ int pciehp_resource_sort_and_combine(str dbg("%s: head = %p, *head = %p\n", __FUNCTION__, head, *head); if (!(*head)) - return(1); + return 1; dbg("*head->next = %p\n",(*head)->next); if (!(*head)->next) - return(0); /* only one item on the list, already sorted! */ + return 0; /* only one item on the list, already sorted! */ dbg("*head->base = 0x%x\n",(*head)->base); dbg("*head->next->base = 0x%x\n",(*head)->next->base); @@ -863,7 +867,7 @@ int pciehp_resource_sort_and_combine(str node1 = node1->next; } - return(0); + return 0; } @@ -878,11 +882,10 @@ struct pci_func *pciehp_slot_create(u8 b struct pci_func *new_slot; struct pci_func *next; dbg("%s: busnumber %x\n", __FUNCTION__, busnumber); - new_slot = (struct pci_func *) kmalloc(sizeof(struct pci_func), GFP_KERNEL); + new_slot = kmalloc(sizeof(struct pci_func), GFP_KERNEL); - if (new_slot == NULL) { - return(new_slot); - } + if (new_slot == NULL) + return new_slot; memset(new_slot, 0, sizeof(struct pci_func)); @@ -897,11 +900,11 @@ struct pci_func *pciehp_slot_create(u8 b next = next->next; next->next = new_slot; } - return(new_slot); + return new_slot; } -/* +/** * slot_remove - Removes a node from the linked list of slots. * @old_slot: slot to remove * @@ -912,19 +915,18 @@ static int slot_remove(struct pci_func * struct pci_func *next; if (old_slot == NULL) - return(1); + return 1; next = pciehp_slot_list[old_slot->bus]; - if (next == NULL) { - return(1); - } + if (next == NULL) + return 1; if (next == old_slot) { pciehp_slot_list[old_slot->bus] = old_slot->next; pciehp_destroy_board_resources(old_slot); kfree(old_slot); - return(0); + return 0; } while ((next->next != old_slot) && (next->next != NULL)) { @@ -935,9 +937,9 @@ static int slot_remove(struct pci_func * next->next = old_slot->next; pciehp_destroy_board_resources(old_slot); kfree(old_slot); - return(0); + return 0; } else - return(2); + return 2; } @@ -954,7 +956,7 @@ static int bridge_slot_remove(struct pci struct pci_func *next; if (bridge == NULL) - return(1); + return 1; secondaryBus = (bridge->config_space[0x06] >> 8) & 0xFF; subordinateBus = (bridge->config_space[0x06] >> 16) & 0xFF; @@ -970,13 +972,13 @@ static int bridge_slot_remove(struct pci next = pciehp_slot_list[bridge->bus]; if (next == NULL) { - return(1); + return 1; } if (next == bridge) { pciehp_slot_list[bridge->bus] = bridge->next; kfree(bridge); - return(0); + return 0; } while ((next->next != bridge) && (next->next != NULL)) { @@ -986,9 +988,9 @@ static int bridge_slot_remove(struct pci if (next->next == bridge) { next->next = bridge->next; kfree(bridge); - return(0); + return 0; } else - return(2); + return 2; } @@ -1016,7 +1018,7 @@ struct pci_func *pciehp_slot_find(u8 bus dbg("%s: func == NULL\n", __FUNCTION__); if ((func == NULL) || ((func->device == device) && (index == 0))) - return(func); + return func; if (func->device == device) found++; @@ -1035,11 +1037,11 @@ struct pci_func *pciehp_slot_find(u8 bus if ((found == index) || (func->function == index)) { dbg("%s: Found bus %x dev %x func %x\n", __FUNCTION__, func->bus, func->device, func->function); - return(func); + return func; } } - return(NULL); + return NULL; } static int is_bridge(struct pci_func * func) @@ -1187,7 +1189,7 @@ static u32 board_added(struct pci_func * /* Done with exclusive hardware access */ up(&ctrl->crit_sect); - return(rc); + return rc; } pciehp_save_slot_config(ctrl, func); @@ -1251,7 +1253,7 @@ static u32 board_added(struct pci_func * /* Done with exclusive hardware access */ up(&ctrl->crit_sect); - return(rc); + return rc; } return 0; } @@ -1273,10 +1275,10 @@ static u32 remove_board(struct pci_func struct slot *p_slot; if (func == NULL) - return(1); + return 1; if (pciehp_unconfigure_device(func)) - return(1); + return 1; device = func->device; @@ -1370,7 +1372,7 @@ static u32 remove_board(struct pci_func func = pciehp_slot_create(ctrl->slot_bus); if (func == NULL) { - return(1); + return 1; } func->bus = ctrl->slot_bus; @@ -1385,7 +1387,7 @@ static u32 remove_board(struct pci_func } -static void pushbutton_helper_thread (unsigned long data) +static void pushbutton_helper_thread(unsigned long data) { pushbutton_pending = data; @@ -1420,7 +1422,7 @@ static int event_thread(void* data) return 0; } -int pciehp_event_start_thread (void) +int pciehp_event_start_thread(void) { int pid; @@ -1440,7 +1442,7 @@ int pciehp_event_start_thread (void) } -void pciehp_event_stop_thread (void) +void pciehp_event_stop_thread(void) { event_finished = 1; dbg("event_thread finish command given\n"); @@ -1450,13 +1452,13 @@ void pciehp_event_stop_thread (void) } -static int update_slot_info (struct slot *slot) +static int update_slot_info(struct slot *slot) { struct hotplug_slot_info *info; /* char buffer[SLOT_NAME_SIZE]; */ int result; - info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL); + info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); if (!info) return -ENOMEM; @@ -1603,8 +1605,6 @@ static void interrupt_event_handler(stru } } /* End of FOR loop */ } - - return; } @@ -1615,7 +1615,7 @@ static void interrupt_event_handler(stru * Handles all pending events and exits. * */ -void pciehp_pushbutton_thread (unsigned long slot) +void pciehp_pushbutton_thread(unsigned long slot) { struct slot *p_slot = (struct slot *) slot; u8 getstatus; @@ -1683,7 +1683,7 @@ void pciehp_pushbutton_thread (unsigned } -int pciehp_enable_slot (struct slot *p_slot) +int pciehp_enable_slot(struct slot *p_slot) { u8 getstatus = 0; int rc; @@ -1692,7 +1692,7 @@ int pciehp_enable_slot (struct slot *p_s func = pciehp_slot_find(p_slot->bus, p_slot->device, 0); if (!func) { dbg("%s: Error! slot NULL\n", __FUNCTION__); - return (1); + return 1; } /* Check to see if (latch closed, card present, power off) */ @@ -1701,21 +1701,21 @@ int pciehp_enable_slot (struct slot *p_s if (rc || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return (0); + return 0; } rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return (0); + return 0; } rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return (0); + return 0; } up(&p_slot->ctrl->crit_sect); @@ -1723,7 +1723,7 @@ int pciehp_enable_slot (struct slot *p_s func = pciehp_slot_create(p_slot->bus); if (func == NULL) - return (1); + return 1; func->bus = p_slot->bus; func->device = p_slot->device; @@ -1746,7 +1746,7 @@ int pciehp_enable_slot (struct slot *p_s /* Setup slot structure with entry for empty slot */ func = pciehp_slot_create(p_slot->bus); if (func == NULL) - return (1); /* Out of memory */ + return 1; /* Out of memory */ func->bus = p_slot->bus; func->device = p_slot->device; @@ -1767,7 +1767,7 @@ int pciehp_enable_slot (struct slot *p_s } -int pciehp_disable_slot (struct slot *p_slot) +int pciehp_disable_slot(struct slot *p_slot) { u8 class_code, header_type, BCR; u8 index = 0; @@ -1779,7 +1779,7 @@ int pciehp_disable_slot (struct slot *p_ struct pci_func *func; if (!p_slot->ctrl) - return (1); + return 1; /* Check to see if (latch closed, card present, power on) */ down(&p_slot->ctrl->crit_sect); @@ -1788,21 +1788,21 @@ int pciehp_disable_slot (struct slot *p_ if (ret || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return (0); + return 0; } ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (ret || getstatus) { info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return (0); + return 0; } ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (ret || !getstatus) { info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return (0); + return 0; } up(&p_slot->ctrl->crit_sect); @@ -1854,7 +1854,7 @@ int pciehp_disable_slot (struct slot *p_ if (p_slot) update_slot_info(p_slot); - return(rc); + return rc; } @@ -1869,7 +1869,7 @@ int pciehp_disable_slot (struct slot *p_ * Returns 0 if success * */ -static u32 configure_new_device (struct controller * ctrl, struct pci_func * func, +static u32 configure_new_device(struct controller * ctrl, struct pci_func * func, u8 behind_bridge, struct resource_lists * resources, u8 bridge_bus, u8 bridge_dev) { u8 temp_byte, function, max_functions, stop_it; @@ -1901,20 +1901,23 @@ static u32 configure_new_device (struct function = 0; do { - rc = configure_new_function(ctrl, new_slot, behind_bridge, resources, bridge_bus, bridge_dev); + rc = configure_new_function(ctrl, new_slot, behind_bridge, + resources, bridge_bus, bridge_dev); if (rc) { - dbg("configure_new_function failed %d\n",rc); + dbg("configure_new_function failed: %d\n", rc); index = 0; while (new_slot) { - new_slot = pciehp_slot_find(new_slot->bus, new_slot->device, index++); + new_slot = pciehp_slot_find(new_slot->bus, + new_slot->device, index++); if (new_slot) - pciehp_return_board_resources(new_slot, resources); + pciehp_return_board_resources(new_slot, + resources); } - return(rc); + return rc; } function++; @@ -1936,7 +1939,7 @@ static u32 configure_new_device (struct if (new_slot == NULL) { /* Out of memory */ - return(1); + return 1; } new_slot->bus = func->bus; @@ -1950,41 +1953,63 @@ static u32 configure_new_device (struct } } while (function < max_functions); - dbg("returning from configure_new_device\n"); + dbg("returning from %s\n", __FUNCTION__); return 0; } - /* * Configuration logic that involves the hotplug data structures and * their bookkeeping */ - /** - * configure_new_function - Configures the PCI header information of one device - * - * @ctrl: pointer to controller structure - * @func: pointer to function structure - * @behind_bridge: 1 if this is a recursive call, 0 if not - * @resources: pointer to set of resource lists - * - * Calls itself recursively for bridged devices. - * Returns 0 if success - * + * configure_bridge: fill bridge's registers, either configure or disable it. */ -static int configure_new_function (struct controller * ctrl, struct pci_func * func, - u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev) +static int +configure_bridge(struct pci_bus *pci_bus, unsigned int devfn, + struct pci_resource *mem_node, + struct pci_resource **hold_mem_node, + int base_addr, int limit_addr) +{ + u16 temp_word; + u32 rc; + + if (mem_node) { + memcpy(*hold_mem_node, mem_node, sizeof(struct pci_resource)); + mem_node->next = NULL; + + /* set Mem base and Limit registers */ + RES_CHECK(mem_node->base, 16); + temp_word = (u16)(mem_node->base >> 16); + rc = pci_bus_write_config_word(pci_bus, devfn, base_addr, temp_word); + + RES_CHECK(mem_node->base + mem_node->length - 1, 16); + temp_word = (u16)((mem_node->base + mem_node->length - 1) >> 16); + rc = pci_bus_write_config_word(pci_bus, devfn, limit_addr, temp_word); + } else { + temp_word = 0xFFFF; + rc = pci_bus_write_config_word(pci_bus, devfn, base_addr, temp_word); + + temp_word = 0x0000; + rc = pci_bus_write_config_word(pci_bus, devfn, limit_addr, temp_word); + + kfree(*hold_mem_node); + *hold_mem_node = NULL; + } + return rc; +} + +static int +configure_new_bridge(struct controller *ctrl, struct pci_func *func, + u8 behind_bridge, struct resource_lists *resources, + struct pci_bus *pci_bus) { int cloop; u8 temp_byte; u8 device; - u8 class_code; u16 temp_word; u32 rc; - u32 temp_register; - u32 base; u32 ID; unsigned int devfn; struct pci_resource *mem_node; @@ -1997,486 +2022,483 @@ static int configure_new_function (struc struct pci_resource *hold_bus_node; struct irq_mapping irqs; struct pci_func *new_slot; - struct pci_bus lpci_bus, *pci_bus; struct resource_lists temp_resources; - memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); - pci_bus = &lpci_bus; - pci_bus->number = func->bus; devfn = PCI_DEVFN(func->device, func->function); - /* Check for Bridge */ - rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &temp_byte); + /* set Primary bus */ + dbg("set Primary bus = 0x%x\n", func->bus); + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_PRIMARY_BUS, func->bus); if (rc) return rc; - dbg("%s: bus %x dev %x func %x temp_byte = %x\n", __FUNCTION__, - func->bus, func->device, func->function, temp_byte); - if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */ - /* set Primary bus */ - dbg("set Primary bus = 0x%x\n", func->bus); - rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_PRIMARY_BUS, func->bus); - if (rc) - return rc; - - /* find range of busses to use */ - bus_node = get_max_resource(&resources->bus_head, 1L); - - /* If we don't have any busses to allocate, we can't continue */ - if (!bus_node) { - err("Got NO bus resource to use\n"); - return -ENOMEM; - } - dbg("Got ranges of buses to use: base:len=0x%x:%x\n", bus_node->base, bus_node->length); - - /* set Secondary bus */ - dbg("set Secondary bus = 0x%x\n", temp_byte); - dbg("func->bus %x\n", func->bus); - - temp_byte = (u8)bus_node->base; - dbg("set Secondary bus = 0x%x\n", temp_byte); - rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, temp_byte); - if (rc) - return rc; + /* find range of busses to use */ + bus_node = get_max_resource(&resources->bus_head, 1L); - /* set subordinate bus */ - temp_byte = (u8)(bus_node->base + bus_node->length - 1); - dbg("set subordinate bus = 0x%x\n", temp_byte); - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte); - if (rc) - return rc; - - /* Set HP parameters (Cache Line Size, Latency Timer) */ - rc = pciehprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_BRIDGE); - if (rc) - return rc; + /* If we don't have any busses to allocate, we can't continue */ + if (!bus_node) { + err("Got NO bus resource to use\n"); + return -ENOMEM; + } + dbg("Got ranges of buses to use: base:len=0x%x:%x\n", bus_node->base, bus_node->length); - /* Setup the IO, memory, and prefetchable windows */ + /* set Secondary bus */ + temp_byte = (u8)bus_node->base; + dbg("set Secondary bus = 0x%x\n", temp_byte); + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, temp_byte); + if (rc) + return rc; - io_node = get_max_resource(&(resources->io_head), 0x1000L); - if (io_node) { - dbg("io_node(base, len, next) (%x, %x, %p)\n", io_node->base, io_node->length, io_node->next); - } + /* set subordinate bus */ + temp_byte = (u8)(bus_node->base + bus_node->length - 1); + dbg("set subordinate bus = 0x%x\n", temp_byte); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte); + if (rc) + return rc; - mem_node = get_max_resource(&(resources->mem_head), 0x100000L); - if (mem_node) { - dbg("mem_node(base, len, next) (%x, %x, %p)\n", mem_node->base, mem_node->length, mem_node->next); - } + /* Set HP parameters (Cache Line Size, Latency Timer) */ + rc = pciehprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_BRIDGE); + if (rc) + return rc; - if (resources->p_mem_head) - p_mem_node = get_max_resource(&(resources->p_mem_head), 0x100000L); - else { - /* - * In some platform implementation, MEM and PMEM are not - * distinguished, and hence ACPI _CRS has only MEM entries - * for both MEM and PMEM. - */ - dbg("using MEM for PMEM\n"); - p_mem_node = get_max_resource(&(resources->mem_head), 0x100000L); - } - if (p_mem_node) { - dbg("p_mem_node(base, len, next) (%x, %x, %p)\n", p_mem_node->base, p_mem_node->length, p_mem_node->next); - } + /* Setup the IO, memory, and prefetchable windows */ - /* set up the IRQ info */ - if (!resources->irqs) { - irqs.barber_pole = 0; - irqs.interrupt[0] = 0; - irqs.interrupt[1] = 0; - irqs.interrupt[2] = 0; - irqs.interrupt[3] = 0; - irqs.valid_INT = 0; - } else { - irqs.barber_pole = resources->irqs->barber_pole; - irqs.interrupt[0] = resources->irqs->interrupt[0]; - irqs.interrupt[1] = resources->irqs->interrupt[1]; - irqs.interrupt[2] = resources->irqs->interrupt[2]; - irqs.interrupt[3] = resources->irqs->interrupt[3]; - irqs.valid_INT = resources->irqs->valid_INT; - } + io_node = get_max_resource(&(resources->io_head), 0x1000L); + if (io_node) { + dbg("io_node(base, len, next) (%x, %x, %p)\n", io_node->base, + io_node->length, io_node->next); + } - /* set up resource lists that are now aligned on top and bottom - * for anything behind the bridge. - */ - temp_resources.bus_head = bus_node; - temp_resources.io_head = io_node; - temp_resources.mem_head = mem_node; - temp_resources.p_mem_head = p_mem_node; - temp_resources.irqs = &irqs; + mem_node = get_max_resource(&(resources->mem_head), 0x100000L); + if (mem_node) { + dbg("mem_node(base, len, next) (%x, %x, %p)\n", mem_node->base, + mem_node->length, mem_node->next); + } - /* Make copies of the nodes we are going to pass down so that - * if there is a problem,we can just use these to free resources + if (resources->p_mem_head) + p_mem_node = get_max_resource(&(resources->p_mem_head), 0x100000L); + else { + /* + * In some platform implementation, MEM and PMEM are not + * distinguished, and hence ACPI _CRS has only MEM entries + * for both MEM and PMEM. */ - hold_bus_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - hold_IO_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - hold_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - hold_p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - - if (!hold_bus_node || !hold_IO_node || !hold_mem_node || !hold_p_mem_node) { - if (hold_bus_node) - kfree(hold_bus_node); - if (hold_IO_node) - kfree(hold_IO_node); - if (hold_mem_node) - kfree(hold_mem_node); - if (hold_p_mem_node) - kfree(hold_p_mem_node); + dbg("using MEM for PMEM\n"); + p_mem_node = get_max_resource(&(resources->mem_head), 0x100000L); + } + if (p_mem_node) { + dbg("p_mem_node(base, len, next) (%x, %x, %p)\n", p_mem_node->base, + p_mem_node->length, p_mem_node->next); + } + + /* set up the IRQ info */ + if (!resources->irqs) { + irqs.barber_pole = 0; + irqs.interrupt[0] = 0; + irqs.interrupt[1] = 0; + irqs.interrupt[2] = 0; + irqs.interrupt[3] = 0; + irqs.valid_INT = 0; + } else { + irqs.barber_pole = resources->irqs->barber_pole; + irqs.interrupt[0] = resources->irqs->interrupt[0]; + irqs.interrupt[1] = resources->irqs->interrupt[1]; + irqs.interrupt[2] = resources->irqs->interrupt[2]; + irqs.interrupt[3] = resources->irqs->interrupt[3]; + irqs.valid_INT = resources->irqs->valid_INT; + } - return(1); - } + /* set up resource lists that are now aligned on top and bottom + * for anything behind the bridge. + */ + temp_resources.bus_head = bus_node; + temp_resources.io_head = io_node; + temp_resources.mem_head = mem_node; + temp_resources.p_mem_head = p_mem_node; + temp_resources.irqs = &irqs; - memcpy(hold_bus_node, bus_node, sizeof(struct pci_resource)); + /* Make copies of the nodes we are going to pass down so that + * if there is a problem,we can just use these to free resources + */ + hold_bus_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + hold_IO_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + hold_mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + hold_p_mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + + if (!hold_bus_node || !hold_IO_node || !hold_mem_node || !hold_p_mem_node) { + kfree(hold_bus_node); + kfree(hold_IO_node); + kfree(hold_mem_node); + kfree(hold_p_mem_node); - bus_node->base += 1; - bus_node->length -= 1; - bus_node->next = NULL; + return 1; + } - /* If we have IO resources copy them and fill in the bridge's - * IO range registers - */ - if (io_node) { - memcpy(hold_IO_node, io_node, sizeof(struct pci_resource)); - io_node->next = NULL; + memcpy(hold_bus_node, bus_node, sizeof(struct pci_resource)); - /* set IO base and Limit registers */ - RES_CHECK(io_node->base, 8); - temp_byte = (u8)(io_node->base >> 8); - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte); + bus_node->base += 1; + bus_node->length -= 1; + bus_node->next = NULL; - RES_CHECK(io_node->base + io_node->length - 1, 8); - temp_byte = (u8)((io_node->base + io_node->length - 1) >> 8); - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte); - } else { - kfree(hold_IO_node); - hold_IO_node = NULL; - } + /* If we have IO resources copy them and fill in the bridge's + * IO range registers + */ + if (io_node) { + memcpy(hold_IO_node, io_node, sizeof(struct pci_resource)); + io_node->next = NULL; + + /* set IO base and Limit registers */ + RES_CHECK(io_node->base, 8); + temp_byte = (u8)(io_node->base >> 8); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte); + + RES_CHECK(io_node->base + io_node->length - 1, 8); + temp_byte = (u8)((io_node->base + io_node->length - 1) >> 8); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte); + } else { + kfree(hold_IO_node); + hold_IO_node = NULL; + } - /* If we have memory resources copy them and fill in the bridge's - * memory range registers. Otherwise, fill in the range - * registers with values that disable them. - */ - if (mem_node) { - memcpy(hold_mem_node, mem_node, sizeof(struct pci_resource)); - mem_node->next = NULL; + /* If we have memory resources copy them and fill in the bridge's + * memory range registers. Otherwise, fill in the range + * registers with values that disable them. + */ + rc = configure_bridge(pci_bus, devfn, mem_node, &hold_mem_node, + PCI_MEMORY_BASE, PCI_MEMORY_LIMIT); - /* set Mem base and Limit registers */ - RES_CHECK(mem_node->base, 16); - temp_word = (u32)(mem_node->base >> 16); - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word); + /* If we have prefetchable memory resources copy them and + * fill in the bridge's memory range registers. Otherwise, + * fill in the range registers with values that disable them. + */ + rc = configure_bridge(pci_bus, devfn, p_mem_node, &hold_p_mem_node, + PCI_PREF_MEMORY_BASE, PCI_PREF_MEMORY_LIMIT); - RES_CHECK(mem_node->base + mem_node->length - 1, 16); - temp_word = (u32)((mem_node->base + mem_node->length - 1) >> 16); - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); - } else { - temp_word = 0xFFFF; - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word); + /* Adjust this to compensate for extra adjustment in first loop */ + irqs.barber_pole--; - temp_word = 0x0000; - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); + rc = 0; - kfree(hold_mem_node); - hold_mem_node = NULL; - } + /* Here we actually find the devices and configure them */ + for (device = 0; (device <= 0x1F) && !rc; device++) { + irqs.barber_pole = (irqs.barber_pole + 1) & 0x03; - /* If we have prefetchable memory resources copy them and - * fill in the bridge's memory range registers. Otherwise, - * fill in the range registers with values that disable them. - */ - if (p_mem_node) { - memcpy(hold_p_mem_node, p_mem_node, sizeof(struct pci_resource)); - p_mem_node->next = NULL; + ID = 0xFFFFFFFF; + pci_bus->number = hold_bus_node->base; + pci_bus_read_config_dword (pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID); + pci_bus->number = func->bus; - /* set Pre Mem base and Limit registers */ - RES_CHECK(p_mem_node->base, 16); - temp_word = (u32)(p_mem_node->base >> 16); - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word); + if (ID != 0xFFFFFFFF) { /* device Present */ + /* Setup slot structure. */ + new_slot = pciehp_slot_create(hold_bus_node->base); + + if (new_slot == NULL) { + /* Out of memory */ + rc = -ENOMEM; + continue; + } - RES_CHECK(p_mem_node->base + p_mem_node->length - 1, 16); - temp_word = (u32)((p_mem_node->base + p_mem_node->length - 1) >> 16); - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); - } else { - temp_word = 0xFFFF; - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word); + new_slot->bus = hold_bus_node->base; + new_slot->device = device; + new_slot->function = 0; + new_slot->is_a_board = 1; + new_slot->status = 0; + + rc = configure_new_device(ctrl, new_slot, 1, + &temp_resources, func->bus, + func->device); + dbg("configure_new_device rc=0x%x\n",rc); + } /* End of IF (device in slot?) */ + } /* End of FOR loop */ - temp_word = 0x0000; - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); + if (rc) { + pciehp_destroy_resource_list(&temp_resources); - kfree(hold_p_mem_node); - hold_p_mem_node = NULL; - } + return_resource(&(resources->bus_head), hold_bus_node); + return_resource(&(resources->io_head), hold_IO_node); + return_resource(&(resources->mem_head), hold_mem_node); + return_resource(&(resources->p_mem_head), hold_p_mem_node); + return(rc); + } - /* Adjust this to compensate for extra adjustment in first loop */ - irqs.barber_pole--; + /* save the interrupt routing information */ + if (resources->irqs) { + resources->irqs->interrupt[0] = irqs.interrupt[0]; + resources->irqs->interrupt[1] = irqs.interrupt[1]; + resources->irqs->interrupt[2] = irqs.interrupt[2]; + resources->irqs->interrupt[3] = irqs.interrupt[3]; + resources->irqs->valid_INT = irqs.valid_INT; + } else if (!behind_bridge) { + /* We need to hook up the interrupts here */ + for (cloop = 0; cloop < 4; cloop++) { + if (irqs.valid_INT & (0x01 << cloop)) { + rc = pciehp_set_irq(func->bus, func->device, + 0x0A + cloop, irqs.interrupt[cloop]); + if (rc) { + pciehp_destroy_resource_list (&temp_resources); + return_resource(&(resources->bus_head), hold_bus_node); + return_resource(&(resources->io_head), hold_IO_node); + return_resource(&(resources->mem_head), hold_mem_node); + return_resource(&(resources->p_mem_head), hold_p_mem_node); + return rc; + } + } + } /* end of for loop */ + } - rc = 0; + /* Return unused bus resources + * First use the temporary node to store information for the board + */ + if (hold_bus_node && bus_node && temp_resources.bus_head) { + hold_bus_node->length = bus_node->base - hold_bus_node->base; - /* Here we actually find the devices and configure them */ - for (device = 0; (device <= 0x1F) && !rc; device++) { - irqs.barber_pole = (irqs.barber_pole + 1) & 0x03; + hold_bus_node->next = func->bus_head; + func->bus_head = hold_bus_node; - ID = 0xFFFFFFFF; - pci_bus->number = hold_bus_node->base; - pci_bus_read_config_dword (pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID); - pci_bus->number = func->bus; + temp_byte = (u8)(temp_resources.bus_head->base - 1); - if (ID != 0xFFFFFFFF) { /* device Present */ - /* Setup slot structure. */ - new_slot = pciehp_slot_create(hold_bus_node->base); + /* set subordinate bus */ + dbg("re-set subordinate bus = 0x%x\n", temp_byte); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte); - if (new_slot == NULL) { - /* Out of memory */ - rc = -ENOMEM; - continue; - } + if (temp_resources.bus_head->length == 0) { + kfree(temp_resources.bus_head); + temp_resources.bus_head = NULL; + } else { + dbg("return bus res of b:d(0x%x:%x) base:len(0x%x:%x)\n", + func->bus, func->device, temp_resources.bus_head->base, temp_resources.bus_head->length); + return_resource(&(resources->bus_head), temp_resources.bus_head); + } + } - new_slot->bus = hold_bus_node->base; - new_slot->device = device; - new_slot->function = 0; - new_slot->is_a_board = 1; - new_slot->status = 0; + /* If we have IO space available and there is some left, + * return the unused portion + */ + if (hold_IO_node && temp_resources.io_head) { + io_node = do_pre_bridge_resource_split(&(temp_resources.io_head), + &hold_IO_node, 0x1000); - rc = configure_new_device(ctrl, new_slot, 1, &temp_resources, func->bus, func->device); - dbg("configure_new_device rc=0x%x\n",rc); - } /* End of IF (device in slot?) */ - } /* End of FOR loop */ + /* Check if we were able to split something off */ + if (io_node) { + hold_IO_node->base = io_node->base + io_node->length; - if (rc) { - pciehp_destroy_resource_list(&temp_resources); + RES_CHECK(hold_IO_node->base, 8); + temp_byte = (u8)((hold_IO_node->base) >> 8); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte); - return_resource(&(resources->bus_head), hold_bus_node); - return_resource(&(resources->io_head), hold_IO_node); - return_resource(&(resources->mem_head), hold_mem_node); - return_resource(&(resources->p_mem_head), hold_p_mem_node); - return(rc); - } - - /* save the interrupt routing information */ - if (resources->irqs) { - resources->irqs->interrupt[0] = irqs.interrupt[0]; - resources->irqs->interrupt[1] = irqs.interrupt[1]; - resources->irqs->interrupt[2] = irqs.interrupt[2]; - resources->irqs->interrupt[3] = irqs.interrupt[3]; - resources->irqs->valid_INT = irqs.valid_INT; - } else if (!behind_bridge) { - /* We need to hook up the interrupts here */ - for (cloop = 0; cloop < 4; cloop++) { - if (irqs.valid_INT & (0x01 << cloop)) { - rc = pciehp_set_irq(func->bus, func->device, - 0x0A + cloop, irqs.interrupt[cloop]); - if (rc) { - pciehp_destroy_resource_list (&temp_resources); - return_resource(&(resources->bus_head), hold_bus_node); - return_resource(&(resources->io_head), hold_IO_node); - return_resource(&(resources->mem_head), hold_mem_node); - return_resource(&(resources->p_mem_head), hold_p_mem_node); - return rc; - } - } - } /* end of for loop */ + return_resource(&(resources->io_head), io_node); } - /* Return unused bus resources - * First use the temporary node to store information for the board - */ - if (hold_bus_node && bus_node && temp_resources.bus_head) { - hold_bus_node->length = bus_node->base - hold_bus_node->base; + io_node = do_bridge_resource_split(&(temp_resources.io_head), 0x1000); - hold_bus_node->next = func->bus_head; - func->bus_head = hold_bus_node; + /* Check if we were able to split something off */ + if (io_node) { + /* First use the temporary node to store information for the board */ + hold_IO_node->length = io_node->base - hold_IO_node->base; - temp_byte = (u8)(temp_resources.bus_head->base - 1); + /* If we used any, add it to the board's list */ + if (hold_IO_node->length) { + hold_IO_node->next = func->io_head; + func->io_head = hold_IO_node; - /* set subordinate bus */ - dbg("re-set subordinate bus = 0x%x\n", temp_byte); - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte); + RES_CHECK(io_node->base - 1, 8); + temp_byte = (u8)((io_node->base - 1) >> 8); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte); - if (temp_resources.bus_head->length == 0) { - kfree(temp_resources.bus_head); - temp_resources.bus_head = NULL; + return_resource(&(resources->io_head), io_node); } else { - dbg("return bus res of b:d(0x%x:%x) base:len(0x%x:%x)\n", - func->bus, func->device, temp_resources.bus_head->base, temp_resources.bus_head->length); - return_resource(&(resources->bus_head), temp_resources.bus_head); - } - } - - /* If we have IO space available and there is some left, - * return the unused portion - */ - if (hold_IO_node && temp_resources.io_head) { - io_node = do_pre_bridge_resource_split(&(temp_resources.io_head), - &hold_IO_node, 0x1000); - - /* Check if we were able to split something off */ - if (io_node) { - hold_IO_node->base = io_node->base + io_node->length; - - RES_CHECK(hold_IO_node->base, 8); - temp_byte = (u8)((hold_IO_node->base) >> 8); - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte); + /* it doesn't need any IO */ + temp_byte = 0x00; + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte); return_resource(&(resources->io_head), io_node); + kfree(hold_IO_node); } - - io_node = do_bridge_resource_split(&(temp_resources.io_head), 0x1000); - - /* Check if we were able to split something off */ - if (io_node) { - /* First use the temporary node to store information for the board */ - hold_IO_node->length = io_node->base - hold_IO_node->base; - - /* If we used any, add it to the board's list */ - if (hold_IO_node->length) { - hold_IO_node->next = func->io_head; - func->io_head = hold_IO_node; - - RES_CHECK(io_node->base - 1, 8); - temp_byte = (u8)((io_node->base - 1) >> 8); - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte); - - return_resource(&(resources->io_head), io_node); - } else { - /* it doesn't need any IO */ - temp_byte = 0x00; - rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte); - - return_resource(&(resources->io_head), io_node); - kfree(hold_IO_node); - } - } else { - /* it used most of the range */ - hold_IO_node->next = func->io_head; - func->io_head = hold_IO_node; - } - } else if (hold_IO_node) { - /* it used the whole range */ + } else { + /* it used most of the range */ hold_IO_node->next = func->io_head; func->io_head = hold_IO_node; } + } else if (hold_IO_node) { + /* it used the whole range */ + hold_IO_node->next = func->io_head; + func->io_head = hold_IO_node; + } - /* If we have memory space available and there is some left, - * return the unused portion - */ - if (hold_mem_node && temp_resources.mem_head) { - mem_node = do_pre_bridge_resource_split(&(temp_resources.mem_head), &hold_mem_node, 0x100000L); + /* If we have memory space available and there is some left, + * return the unused portion + */ + if (hold_mem_node && temp_resources.mem_head) { + mem_node = do_pre_bridge_resource_split(&(temp_resources.mem_head), &hold_mem_node, 0x100000L); - /* Check if we were able to split something off */ - if (mem_node) { - hold_mem_node->base = mem_node->base + mem_node->length; - - RES_CHECK(hold_mem_node->base, 16); - temp_word = (u32)((hold_mem_node->base) >> 16); - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word); + /* Check if we were able to split something off */ + if (mem_node) { + hold_mem_node->base = mem_node->base + mem_node->length; - return_resource(&(resources->mem_head), mem_node); - } + RES_CHECK(hold_mem_node->base, 16); + temp_word = (u16)((hold_mem_node->base) >> 16); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word); - mem_node = do_bridge_resource_split(&(temp_resources.mem_head), 0x100000L); + return_resource(&(resources->mem_head), mem_node); + } - /* Check if we were able to split something off */ - if (mem_node) { - /* First use the temporary node to store information for the board */ - hold_mem_node->length = mem_node->base - hold_mem_node->base; - - if (hold_mem_node->length) { - hold_mem_node->next = func->mem_head; - func->mem_head = hold_mem_node; - - /* configure end address */ - RES_CHECK(mem_node->base - 1, 16); - temp_word = (u32)((mem_node->base - 1) >> 16); - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); + mem_node = do_bridge_resource_split(&(temp_resources.mem_head), 0x100000L); - /* Return unused resources to the pool */ - return_resource(&(resources->mem_head), mem_node); - } else { - /* it doesn't need any Mem */ - temp_word = 0x0000; - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); + /* Check if we were able to split something off */ + if (mem_node) { + /* First use the temporary node to store information for the board */ + hold_mem_node->length = mem_node->base - hold_mem_node->base; - return_resource(&(resources->mem_head), mem_node); - kfree(hold_mem_node); - } - } else { - /* it used most of the range */ + if (hold_mem_node->length) { hold_mem_node->next = func->mem_head; func->mem_head = hold_mem_node; + + /* configure end address */ + RES_CHECK(mem_node->base - 1, 16); + temp_word = (u16)((mem_node->base - 1) >> 16); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); + + /* Return unused resources to the pool */ + return_resource(&(resources->mem_head), mem_node); + } else { + /* it doesn't need any Mem */ + temp_word = 0x0000; + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); + + return_resource(&(resources->mem_head), mem_node); + kfree(hold_mem_node); } - } else if (hold_mem_node) { - /* it used the whole range */ + } else { + /* it used most of the range */ hold_mem_node->next = func->mem_head; func->mem_head = hold_mem_node; } + } else if (hold_mem_node) { + /* it used the whole range */ + hold_mem_node->next = func->mem_head; + func->mem_head = hold_mem_node; + } - /* If we have prefetchable memory space available and there is some - * left at the end, return the unused portion - */ - if (hold_p_mem_node && temp_resources.p_mem_head) { - p_mem_node = do_pre_bridge_resource_split(&(temp_resources.p_mem_head), - &hold_p_mem_node, 0x100000L); - - /* Check if we were able to split something off */ - if (p_mem_node) { - hold_p_mem_node->base = p_mem_node->base + p_mem_node->length; - - RES_CHECK(hold_p_mem_node->base, 16); - temp_word = (u32)((hold_p_mem_node->base) >> 16); - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word); + /* If we have prefetchable memory space available and there is some + * left at the end, return the unused portion + */ + if (hold_p_mem_node && temp_resources.p_mem_head) { + p_mem_node = do_pre_bridge_resource_split(&(temp_resources.p_mem_head), + &hold_p_mem_node, 0x100000L); - return_resource(&(resources->p_mem_head), p_mem_node); - } + /* Check if we were able to split something off */ + if (p_mem_node) { + hold_p_mem_node->base = p_mem_node->base + p_mem_node->length; - p_mem_node = do_bridge_resource_split(&(temp_resources.p_mem_head), 0x100000L); + RES_CHECK(hold_p_mem_node->base, 16); + temp_word = (u16)((hold_p_mem_node->base) >> 16); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word); - /* Check if we were able to split something off */ - if (p_mem_node) { - /* First use the temporary node to store information for the board */ - hold_p_mem_node->length = p_mem_node->base - hold_p_mem_node->base; - - /* If we used any, add it to the board's list */ - if (hold_p_mem_node->length) { - hold_p_mem_node->next = func->p_mem_head; - func->p_mem_head = hold_p_mem_node; - - RES_CHECK(p_mem_node->base - 1, 16); - temp_word = (u32)((p_mem_node->base - 1) >> 16); - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); + return_resource(&(resources->p_mem_head), p_mem_node); + } - return_resource(&(resources->p_mem_head), p_mem_node); - } else { - /* it doesn't need any PMem */ - temp_word = 0x0000; - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); + p_mem_node = do_bridge_resource_split(&(temp_resources.p_mem_head), 0x100000L); - return_resource(&(resources->p_mem_head), p_mem_node); - kfree(hold_p_mem_node); - } - } else { - /* it used the most of the range */ + /* Check if we were able to split something off */ + if (p_mem_node) { + /* First use the temporary node to store information for the board */ + hold_p_mem_node->length = p_mem_node->base - hold_p_mem_node->base; + + /* If we used any, add it to the board's list */ + if (hold_p_mem_node->length) { hold_p_mem_node->next = func->p_mem_head; func->p_mem_head = hold_p_mem_node; + + RES_CHECK(p_mem_node->base - 1, 16); + temp_word = (u16)((p_mem_node->base - 1) >> 16); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); + + return_resource(&(resources->p_mem_head), p_mem_node); + } else { + /* it doesn't need any PMem */ + temp_word = 0x0000; + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); + + return_resource(&(resources->p_mem_head), p_mem_node); + kfree(hold_p_mem_node); } - } else if (hold_p_mem_node) { - /* it used the whole range */ + } else { + /* it used the most of the range */ hold_p_mem_node->next = func->p_mem_head; func->p_mem_head = hold_p_mem_node; } + } else if (hold_p_mem_node) { + /* it used the whole range */ + hold_p_mem_node->next = func->p_mem_head; + func->p_mem_head = hold_p_mem_node; + } - /* We should be configuring an IRQ and the bridge's base address - * registers if it needs them. Although we have never seen such - * a device - */ + /* We should be configuring an IRQ and the bridge's base address + * registers if it needs them. Although we have never seen such + * a device + */ + + pciehprm_enable_card(ctrl, func, PCI_HEADER_TYPE_BRIDGE); + + dbg("PCI Bridge Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function); + + return rc; +} + +/** + * configure_new_function - Configures the PCI header information of one device + * + * @ctrl: pointer to controller structure + * @func: pointer to function structure + * @behind_bridge: 1 if this is a recursive call, 0 if not + * @resources: pointer to set of resource lists + * + * Calls itself recursively for bridged devices. + * Returns 0 if success + * + */ +static int +configure_new_function(struct controller *ctrl, struct pci_func *func, + u8 behind_bridge, struct resource_lists *resources, + u8 bridge_bus, u8 bridge_dev) +{ + int cloop; + u8 temp_byte; + u8 class_code; + u16 temp_word; + u32 rc; + u32 temp_register; + u32 base; + unsigned int devfn; + struct pci_resource *mem_node; + struct pci_resource *io_node; + struct pci_bus lpci_bus, *pci_bus; + + memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); + pci_bus = &lpci_bus; + pci_bus->number = func->bus; + devfn = PCI_DEVFN(func->device, func->function); + + /* Check for Bridge */ + rc = pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &temp_byte); + if (rc) + return rc; + dbg("%s: bus %x dev %x func %x temp_byte = %x\n", __FUNCTION__, + func->bus, func->device, func->function, temp_byte); - pciehprm_enable_card(ctrl, func, PCI_HEADER_TYPE_BRIDGE); + if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */ + rc = configure_new_bridge(ctrl, func, behind_bridge, resources, + pci_bus); - dbg("PCI Bridge Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function); + if (rc) + return rc; } else if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_NORMAL) { /* Standard device */ u64 base64; - rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code); + rc = pci_bus_read_config_byte(pci_bus, devfn, 0x0B, &class_code); if (class_code == PCI_BASE_CLASS_DISPLAY) - return (DEVICE_TYPE_NOT_SUPPORTED); + return DEVICE_TYPE_NOT_SUPPORTED; /* Figure out IO and memory needs */ for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) { @@ -2535,7 +2557,7 @@ static int configure_new_function (struc else { if (prefetchable) dbg("using MEM for PMEM\n"); - mem_node=get_resource(&(resources->mem_head), (ulong)base); + mem_node = get_resource(&(resources->mem_head), (ulong)base); } /* allocate the resource to the board */ @@ -2614,11 +2636,10 @@ static int configure_new_function (struc } /* End of Not-A-Bridge else */ else { /* It's some strange type of PCI adapter (Cardbus?) */ - return(DEVICE_TYPE_NOT_SUPPORTED); + return DEVICE_TYPE_NOT_SUPPORTED; } func->configured = 1; return 0; } - --- linux-2.6.6/drivers/pci/hotplug/pciehp.h 2004-03-10 20:41:29.000000000 -0800 +++ 25/drivers/pci/hotplug/pciehp.h 2004-05-10 01:19:04.021127752 -0700 @@ -35,11 +35,7 @@ #include #include "pci_hotplug.h" -#if !defined(CONFIG_HOTPLUG_PCI_PCIE_MODULE) - #define MY_NAME "pciehp" -#else - #define MY_NAME THIS_MODULE->name -#endif +#define MY_NAME "pciehp" extern int pciehp_poll_mode; extern int pciehp_poll_time; @@ -72,9 +68,7 @@ struct pci_func { struct pci_dev* pci_dev; }; -#define SLOT_MAGIC 0x67267321 struct slot { - u32 magic; struct slot *next; u8 bus; u8 device; @@ -108,9 +102,9 @@ struct event_info { struct controller { struct controller *next; struct semaphore crit_sect; /* critical section semaphore */ - void * hpc_ctlr_handle; /* HPC controller handle */ + void *hpc_ctlr_handle; /* HPC controller handle */ int num_slots; /* Number of slots on ctlr */ - int slot_num_inc; /* 1 or -1 */ + int slot_num_inc; /* 1 or -1 */ struct pci_resource *mem_head; struct pci_resource *p_mem_head; struct pci_resource *io_head; @@ -191,7 +185,7 @@ struct resource_lists { #define msg_initialization_err "Initialization failure, error=%d\n" #define msg_HPC_rev_error "Unsupported revision of the PCI hot plug controller found.\n" #define msg_HPC_non_pcie "The PCI hot plug controller is not supported by this driver.\n" -#define msg_HPC_not_supported "This system is not supported by this version of pciephd mdoule. Upgrade to a newer version of pciehpd\n" +#define msg_HPC_not_supported "This system is not supported by this version of pciephd module. Upgrade to a newer version of pciehpd\n" #define msg_unable_to_save "Unable to store PCI hot plug add resource information. This system must be rebooted before adding any PCI devices.\n" #define msg_button_on "PCI slot #%d - powering on due to button press.\n" #define msg_button_off "PCI slot #%d - powering off due to button press.\n" @@ -239,47 +233,10 @@ extern struct pci_func *pciehp_slot_list /* Inline functions */ - -/* Inline functions to check the sanity of a pointer that is passed to us */ -static inline int slot_paranoia_check (struct slot *slot, const char *function) -{ - if (!slot) { - dbg("%s - slot == NULL", function); - return -1; - } - if (slot->magic != SLOT_MAGIC) { - dbg("%s - bad magic number for slot", function); - return -1; - } - if (!slot->hotplug_slot) { - dbg("%s - slot->hotplug_slot == NULL!", function); - return -1; - } - return 0; -} - -static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const char *function) -{ - struct slot *slot; - - if (!hotplug_slot) { - dbg("%s - hotplug_slot == NULL\n", function); - return NULL; - } - - slot = (struct slot *)hotplug_slot->private; - if (slot_paranoia_check (slot, function)) - return NULL; - return slot; -} - -static inline struct slot *pciehp_find_slot (struct controller *ctrl, u8 device) +static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device) { struct slot *p_slot, *tmp_slot = NULL; - if (!ctrl) - return NULL; - p_slot = ctrl->slot; dbg("p_slot = %p\n", p_slot); @@ -294,10 +251,10 @@ static inline struct slot *pciehp_find_s p_slot = tmp_slot; } - return (p_slot); + return p_slot; } -static inline int wait_for_ctrl_irq (struct controller *ctrl) +static inline int wait_for_ctrl_irq(struct controller *ctrl) { int retval = 0; @@ -345,7 +302,7 @@ enum php_ctlr_type { typedef u8(*php_intr_callback_t) (unsigned int change_id, void *instance_id); -int pcie_init( struct controller *ctrl, struct pci_dev *pdev, +int pcie_init(struct controller *ctrl, struct pci_dev *pdev, php_intr_callback_t attention_button_callback, php_intr_callback_t switch_change_callback, php_intr_callback_t presence_change_callback, @@ -353,7 +310,7 @@ int pcie_init( struct controller *ctrl, /* This has no meaning for PCI Express, as there is only 1 slot per port */ -int pcie_get_ctlr_slot_config( struct controller *ctrl, +int pcie_get_ctlr_slot_config(struct controller *ctrl, int *num_ctlr_slots, int *first_device_num, int *physical_slot_num, @@ -361,12 +318,12 @@ int pcie_get_ctlr_slot_config( struct co int *flags); struct hpc_ops { - int (*power_on_slot ) (struct slot *slot); - int (*power_off_slot ) (struct slot *slot); - int (*get_power_status) (struct slot *slot, u8 *status); + int (*power_on_slot) (struct slot *slot); + int (*power_off_slot) (struct slot *slot); + int (*get_power_status) (struct slot *slot, u8 *status); int (*get_attention_status) (struct slot *slot, u8 *status); int (*set_attention_status) (struct slot *slot, u8 status); - int (*get_latch_status) (struct slot *slot, u8 *status); + int (*get_latch_status) (struct slot *slot, u8 *status); int (*get_adapter_status) (struct slot *slot, u8 *status); int (*get_max_bus_speed) (struct slot *slot, enum pci_bus_speed *speed); @@ -380,7 +337,7 @@ struct hpc_ops { void (*green_led_off) (struct slot *slot); void (*green_led_blink) (struct slot *slot); void (*release_ctlr) (struct controller *ctrl); - int (*check_lnk_status) (struct controller *ctrl); + int (*check_lnk_status) (struct controller *ctrl); }; #endif /* _PCIEHP_H */ --- linux-2.6.6/drivers/pci/hotplug/pciehp_hpc.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/pci/hotplug/pciehp_hpc.c 2004-05-10 01:19:04.037125320 -0700 @@ -291,14 +291,14 @@ static void start_int_poll_timer(struct static int pcie_write_cmd(struct slot *slot, u16 cmd) { - struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; int retval = 0; u16 slot_status; DBG_ENTER_ROUTINE dbg("%s : Enter\n", __FUNCTION__); - if (!slot->ctrl->hpc_ctlr_handle) { + if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return -1; } @@ -331,13 +331,13 @@ static int pcie_write_cmd(struct slot *s static int hpc_check_lnk_status(struct controller *ctrl) { - struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle; + struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; u16 lnk_status; int retval = 0; DBG_ENTER_ROUTINE - if (!ctrl->hpc_ctlr_handle) { + if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return -1; } @@ -362,14 +362,14 @@ static int hpc_check_lnk_status(struct c static int hpc_get_attention_status(struct slot *slot, u8 *status) { - struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_ctrl; u8 atten_led_state; int retval = 0; DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { + if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return -1; } @@ -409,14 +409,14 @@ static int hpc_get_attention_status(stru static int hpc_get_power_status(struct slot * slot, u8 *status) { - struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_ctrl; u8 pwr_state; int retval = 0; DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { + if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return -1; } @@ -450,13 +450,13 @@ static int hpc_get_power_status(struct s static int hpc_get_latch_status(struct slot *slot, u8 *status) { - struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_status; int retval = 0; DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { + if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return -1; } @@ -476,14 +476,14 @@ static int hpc_get_latch_status(struct s static int hpc_get_adapter_status(struct slot *slot, u8 *status) { - struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_status; u8 card_state; int retval = 0; DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { + if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return -1; } @@ -503,7 +503,7 @@ static int hpc_get_adapter_status(struct static int hpc_query_power_fault(struct slot * slot) { - struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_status; u8 pwr_fault; int retval = 0; @@ -511,7 +511,7 @@ static int hpc_query_power_fault(struct DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { + if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return -1; } @@ -532,13 +532,13 @@ static int hpc_query_power_fault(struct static int hpc_set_attention_status(struct slot *slot, u8 value) { - struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_cmd = 0; u16 slot_ctrl; int rc = 0; dbg("%s: \n", __FUNCTION__); - if (!slot->ctrl->hpc_ctlr_handle) { + if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return -1; } @@ -580,13 +580,13 @@ static int hpc_set_attention_status(stru static void hpc_set_green_led_on(struct slot *slot) { - struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_cmd; u16 slot_ctrl; int rc = 0; dbg("%s: \n", __FUNCTION__); - if (!slot->ctrl->hpc_ctlr_handle) { + if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return ; } @@ -615,13 +615,13 @@ static void hpc_set_green_led_on(struct static void hpc_set_green_led_off(struct slot *slot) { - struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_cmd; u16 slot_ctrl; int rc = 0; dbg("%s: \n", __FUNCTION__); - if (!slot->ctrl->hpc_ctlr_handle) { + if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return ; } @@ -651,13 +651,13 @@ static void hpc_set_green_led_off(struct static void hpc_set_green_led_blink(struct slot *slot) { - struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_cmd; u16 slot_ctrl; int rc = 0; dbg("%s: \n", __FUNCTION__); - if (!slot->ctrl->hpc_ctlr_handle) { + if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return ; } @@ -692,13 +692,13 @@ int pcie_get_ctlr_slot_config(struct con int *updown, /* physical_slot_num increament: 1 or -1 */ int *flags) { - struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle; + struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; u32 slot_cap; int rc = 0; DBG_ENTER_ROUTINE - if (!ctrl->hpc_ctlr_handle) { + if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return -1; } @@ -723,12 +723,12 @@ int pcie_get_ctlr_slot_config(struct con static void hpc_release_ctlr(struct controller *ctrl) { - struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle; + struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; struct php_ctlr_state_s *p, *p_prev; DBG_ENTER_ROUTINE - if (!ctrl->hpc_ctlr_handle) { + if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return ; } @@ -769,7 +769,7 @@ static void hpc_release_ctlr(struct cont static int hpc_power_on_slot(struct slot * slot) { - struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_cmd; u16 slot_ctrl; @@ -778,7 +778,7 @@ static int hpc_power_on_slot(struct slot DBG_ENTER_ROUTINE dbg("%s: \n", __FUNCTION__); - if (!slot->ctrl->hpc_ctlr_handle) { + if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return -1; } @@ -818,7 +818,7 @@ static int hpc_power_on_slot(struct slot static int hpc_power_off_slot(struct slot * slot) { - struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_cmd; u16 slot_ctrl; @@ -827,7 +827,7 @@ static int hpc_power_off_slot(struct slo DBG_ENTER_ROUTINE dbg("%s: \n", __FUNCTION__); - if (!slot->ctrl->hpc_ctlr_handle) { + if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return -1; } @@ -879,10 +879,10 @@ static irqreturn_t pcie_isr(int IRQ, voi return IRQ_NONE; if (!pciehp_poll_mode) { - ctrl = (struct controller *)dev_id; + ctrl = dev_id; php_ctlr = ctrl->hpc_ctlr_handle; } else { - php_ctlr = (struct php_ctlr_state_s *) dev_id; + php_ctlr = dev_id; ctrl = (struct controller *)php_ctlr->callback_instance_id; } @@ -1017,14 +1017,14 @@ static irqreturn_t pcie_isr(int IRQ, voi static int hpc_get_max_lnk_speed (struct slot *slot, enum pcie_link_speed *value) { - struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; enum pcie_link_speed lnk_speed; u32 lnk_cap; int retval = 0; DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { + if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return -1; } @@ -1058,14 +1058,14 @@ static int hpc_get_max_lnk_speed (struct static int hpc_get_max_lnk_width (struct slot *slot, enum pcie_link_width *value) { - struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; enum pcie_link_width lnk_wdth; u32 lnk_cap; int retval = 0; DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { + if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return -1; } @@ -1120,14 +1120,14 @@ static int hpc_get_max_lnk_width (struct static int hpc_get_cur_lnk_speed (struct slot *slot, enum pcie_link_speed *value) { - struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; enum pcie_link_speed lnk_speed = PCI_SPEED_UNKNOWN; int retval = 0; u16 lnk_status; DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { + if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return -1; } @@ -1161,14 +1161,14 @@ static int hpc_get_cur_lnk_speed (struct static int hpc_get_cur_lnk_width (struct slot *slot, enum pcie_link_width *value) { - struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; enum pcie_link_width lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN; int retval = 0; u16 lnk_status; DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { + if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return -1; } @@ -1245,7 +1245,7 @@ static struct hpc_ops pciehp_hpc_ops = { }; int pcie_init(struct controller * ctrl, - struct pci_dev * pdev, + struct pci_dev *pdev, php_intr_callback_t attention_button_callback, php_intr_callback_t switch_change_callback, php_intr_callback_t presence_change_callback, --- linux-2.6.6/drivers/pci/hotplug/pciehp_pci.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/pci/hotplug/pciehp_pci.c 2004-05-10 01:19:04.041124712 -0700 @@ -69,7 +69,7 @@ int pciehp_configure_device (struct cont if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus); - child = (struct pci_bus*) pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus); + child = pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus); pci_do_scan_bus(child); } @@ -83,10 +83,12 @@ int pciehp_unconfigure_device(struct pci int rc = 0; int j; - dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus, func->device, func->function); + dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus, + func->device, func->function); for (j=0; j<8 ; j++) { - struct pci_dev* temp = pci_find_slot(func->bus, (func->device << 3) | j); + struct pci_dev* temp = pci_find_slot(func->bus, + (func->device << 3) | j); if (temp) { pci_remove_bus_device(temp); } @@ -169,7 +171,8 @@ int pciehp_save_config(struct controller memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); pci_bus = &lpci_bus; - dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__, num_ctlr_slots, first_device_num); + dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__, + num_ctlr_slots, first_device_num); /* Decide which slots are supported */ if (is_hot_plug) { @@ -183,7 +186,8 @@ int pciehp_save_config(struct controller LastSupported = 0x1F; } - dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported, LastSupported); + dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported, + LastSupported); /* Save PCI configuration space for all devices in supported slots */ dbg("%s: pci_bus->number = %x\n", __FUNCTION__, pci_bus->number); @@ -191,15 +195,18 @@ int pciehp_save_config(struct controller dbg("%s: bus = %x, dev = %x\n", __FUNCTION__, busnumber, device); for (device = FirstSupported; device <= LastSupported; device++) { ID = 0xFFFFFFFF; - rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID); + rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0), + PCI_VENDOR_ID, &ID); if (ID != 0xFFFFFFFF) { /* device in slot */ dbg("%s: ID = %x\n", __FUNCTION__, ID); - rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), 0x0B, &class_code); + rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), + 0x0B, &class_code); if (rc) return rc; - rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), PCI_HEADER_TYPE, &header_type); + rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), + PCI_HEADER_TYPE, &header_type); if (rc) return rc; @@ -221,7 +228,8 @@ int pciehp_save_config(struct controller /* Recurse the subordinate bus * get the subordinate bus number */ - rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, function), + rc = pci_bus_read_config_byte(pci_bus, + PCI_DEVFN(device, function), PCI_SECONDARY_BUS, &secondary_bus); if (rc) { return rc; @@ -263,13 +271,17 @@ int pciehp_save_config(struct controller new_slot->switch_save = 0x10; /* In case of unsupported board */ new_slot->status = DevError; - new_slot->pci_dev = pci_find_slot(new_slot->bus, (new_slot->device << 3) | new_slot->function); + new_slot->pci_dev = pci_find_slot(new_slot->bus, + (new_slot->device << 3) | new_slot->function); dbg("new_slot->pci_dev = %p\n", new_slot->pci_dev); for (cloop = 0; cloop < 0x20; cloop++) { - rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, function), cloop << 2, - (u32 *) & (new_slot->config_space [cloop])); - /* dbg("new_slot->config_space[%x] = %x\n", cloop, new_slot->config_space[cloop]); */ + rc = pci_bus_read_config_dword(pci_bus, + PCI_DEVFN(device, function), + cloop << 2, + (u32 *) &(new_slot->config_space [cloop])); + /* dbg("new_slot->config_space[%x] = %x\n", + cloop, new_slot->config_space[cloop]); */ if (rc) return rc; } @@ -284,19 +296,23 @@ int pciehp_save_config(struct controller while ((function < max_functions)&&(!stop_it)) { dbg("%s: In while loop \n", __FUNCTION__); - rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, function), PCI_VENDOR_ID, &ID); + rc = pci_bus_read_config_dword(pci_bus, + PCI_DEVFN(device, function), + PCI_VENDOR_ID, &ID); if (ID == 0xFFFFFFFF) { /* nothing there. */ function++; dbg("Nothing there\n"); } else { /* Something there */ - rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, function), 0x0B, - &class_code); + rc = pci_bus_read_config_byte(pci_bus, + PCI_DEVFN(device, function), + 0x0B, &class_code); if (rc) return rc; - rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, function), PCI_HEADER_TYPE, - &header_type); + rc = pci_bus_read_config_byte(pci_bus, + PCI_DEVFN(device, function), + PCI_HEADER_TYPE, &header_type); if (rc) return rc; @@ -306,8 +322,8 @@ int pciehp_save_config(struct controller } } while (function < max_functions); - } /* End of IF (device in slot?) */ - else if (is_hot_plug) { + /* End of IF (device in slot?) */ + } else if (is_hot_plug) { /* Setup slot structure with entry for empty slot */ new_slot = pciehp_slot_create(busnumber); @@ -339,7 +355,7 @@ int pciehp_save_config(struct controller * * returns 0 if success */ -int pciehp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot) +int pciehp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot) { int rc; u8 class_code; @@ -358,12 +374,15 @@ int pciehp_save_slot_config (struct cont ID = 0xFFFFFFFF; - pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_VENDOR_ID, &ID); + pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, 0), + PCI_VENDOR_ID, &ID); if (ID != 0xFFFFFFFF) { /* device in slot */ - pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), 0x0B, &class_code); + pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), + 0x0B, &class_code); - pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_HEADER_TYPE, &header_type); + pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), + PCI_HEADER_TYPE, &header_type); if (header_type & 0x80) /* Multi-function device */ max_functions = 8; @@ -375,7 +394,8 @@ int pciehp_save_slot_config (struct cont do { if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */ /* Recurse the subordinate bus */ - pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, function), + pci_bus_read_config_byte(pci_bus, + PCI_DEVFN(new_slot->device, function), PCI_SECONDARY_BUS, &secondary_bus); sub_bus = (int) secondary_bus; @@ -384,15 +404,17 @@ int pciehp_save_slot_config (struct cont rc = pciehp_save_config(ctrl, sub_bus, 0, 0); if (rc) - return(rc); + return rc; } /* End of IF */ new_slot->status = 0; for (cloop = 0; cloop < 0x20; cloop++) { - pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, function), - cloop << 2, (u32 *) & (new_slot->config_space [cloop])); + pci_bus_read_config_dword(pci_bus, + PCI_DEVFN(new_slot->device, function), + cloop << 2, + (u32 *) &(new_slot->config_space [cloop])); } function++; @@ -404,15 +426,20 @@ int pciehp_save_slot_config (struct cont */ while ((function < max_functions) && (!stop_it)) { - pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, function), PCI_VENDOR_ID, &ID); + pci_bus_read_config_dword(pci_bus, + PCI_DEVFN(new_slot->device, function), + PCI_VENDOR_ID, &ID); if (ID == 0xFFFFFFFF) { /* nothing there. */ function++; } else { /* Something there */ - pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, function), 0x0B, &class_code); - - pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, function), PCI_HEADER_TYPE, - &header_type); + pci_bus_read_config_byte(pci_bus, + PCI_DEVFN(new_slot->device, function), + 0x0B, &class_code); + + pci_bus_read_config_byte(pci_bus, + PCI_DEVFN(new_slot->device, function), + PCI_HEADER_TYPE, &header_type); stop_it++; } @@ -421,10 +448,10 @@ int pciehp_save_slot_config (struct cont } while (function < max_functions); } /* End of IF (device in slot?) */ else { - return(2); + return 2; } - return(0); + return 0; } @@ -440,7 +467,7 @@ int pciehp_save_slot_config (struct cont * it loops for all functions of the slot and disables them. * else, it just get resources of the function and return. */ -int pciehp_save_used_resources (struct controller *ctrl, struct pci_func *func, int disable) +int pciehp_save_used_resources(struct controller *ctrl, struct pci_func *func, int disable) { u8 cloop; u8 header_type; @@ -472,7 +499,7 @@ int pciehp_save_used_resources (struct c devfn = PCI_DEVFN(func->device, func->function); /* Save the command register */ - pci_bus_read_config_word (pci_bus, devfn, PCI_COMMAND, &save_command); + pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &save_command); if (disable) { /* disable card */ @@ -481,20 +508,22 @@ int pciehp_save_used_resources (struct c } /* Check for Bridge */ - pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type); + pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type); if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */ - dbg("Save_used_res of PCI bridge b:d=0x%x:%x, sc=0x%x\n", func->bus, func->device, save_command); + dbg("Save_used_res of PCI bridge b:d=0x%x:%x, sc=0x%x\n", + func->bus, func->device, save_command); if (disable) { /* Clear Bridge Control Register */ command = 0x00; pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command); } - pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus); - pci_bus_read_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte); + pci_bus_read_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus); + pci_bus_read_config_byte(pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte); - bus_node =(struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + bus_node = kmalloc(sizeof(struct pci_resource), + GFP_KERNEL); if (!bus_node) return -ENOMEM; @@ -505,13 +534,14 @@ int pciehp_save_used_resources (struct c func->bus_head = bus_node; /* Save IO base and Limit registers */ - pci_bus_read_config_byte (pci_bus, devfn, PCI_IO_BASE, &temp_byte); + pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_BASE, &temp_byte); base = temp_byte; - pci_bus_read_config_byte (pci_bus, devfn, PCI_IO_LIMIT, &temp_byte); + pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_LIMIT, &temp_byte); length = temp_byte; if ((base <= length) && (!disable || (save_command & PCI_COMMAND_IO))) { - io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + io_node = kmalloc(sizeof(struct pci_resource), + GFP_KERNEL); if (!io_node) return -ENOMEM; @@ -523,11 +553,12 @@ int pciehp_save_used_resources (struct c } /* Save memory base and Limit registers */ - pci_bus_read_config_word (pci_bus, devfn, PCI_MEMORY_BASE, &w_base); - pci_bus_read_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length); + pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_BASE, &w_base); + pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length); if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) { - mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + mem_node = kmalloc(sizeof(struct pci_resource), + GFP_KERNEL); if (!mem_node) return -ENOMEM; @@ -538,11 +569,12 @@ int pciehp_save_used_resources (struct c func->mem_head = mem_node; } /* Save prefetchable memory base and Limit registers */ - pci_bus_read_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base); - pci_bus_read_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length); + pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base); + pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length); if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) { - p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + p_mem_node = kmalloc(sizeof(struct pci_resource), + GFP_KERNEL); if (!p_mem_node) return -ENOMEM; @@ -553,38 +585,41 @@ int pciehp_save_used_resources (struct c func->p_mem_head = p_mem_node; } } else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) { - dbg("Save_used_res of PCI adapter b:d=0x%x:%x, sc=0x%x\n", func->bus, func->device, save_command); + dbg("Save_used_res of PCI adapter b:d=0x%x:%x, sc=0x%x\n", + func->bus, func->device, save_command); /* Figure out IO and memory base lengths */ for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) { - pci_bus_read_config_dword (pci_bus, devfn, cloop, &save_base); + pci_bus_read_config_dword(pci_bus, devfn, cloop, &save_base); temp_register = 0xFFFFFFFF; - pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register); - pci_bus_read_config_dword (pci_bus, devfn, cloop, &temp_register); + pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register); + pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register); - if (!disable) { - pci_bus_write_config_dword (pci_bus, devfn, cloop, save_base); - } + if (!disable) + pci_bus_write_config_dword(pci_bus, devfn, cloop, save_base); if (!temp_register) continue; base = temp_register; - if ((base & PCI_BASE_ADDRESS_SPACE_IO) && (!disable || (save_command & PCI_COMMAND_IO))) { + if ((base & PCI_BASE_ADDRESS_SPACE_IO) && + (!disable || (save_command & PCI_COMMAND_IO))) { /* IO base */ /* set temp_register = amount of IO space requested */ base = base & 0xFFFFFFFCL; base = (~base) + 1; - io_node = (struct pci_resource *) kmalloc(sizeof (struct pci_resource), GFP_KERNEL); + io_node = kmalloc(sizeof (struct pci_resource), + GFP_KERNEL); if (!io_node) return -ENOMEM; io_node->base = (ulong)save_base & PCI_BASE_ADDRESS_IO_MASK; io_node->length = (ulong)base; - dbg("sur adapter: IO bar=0x%x(length=0x%x)\n", io_node->base, io_node->length); + dbg("sur adapter: IO bar=0x%x(length=0x%x)\n", + io_node->base, io_node->length); io_node->next = func->io_head; func->io_head = io_node; @@ -594,11 +629,13 @@ int pciehp_save_used_resources (struct c char *res_type_str = "PMEM"; u32 temp_register2; - t_mem_node = (struct pci_resource *) kmalloc(sizeof (struct pci_resource), GFP_KERNEL); + t_mem_node = kmalloc(sizeof (struct pci_resource), + GFP_KERNEL); if (!t_mem_node) return -ENOMEM; - if (!(base & PCI_BASE_ADDRESS_MEM_PREFETCH) && (!disable || (save_command & PCI_COMMAND_MEMORY))) { + if (!(base & PCI_BASE_ADDRESS_MEM_PREFETCH) && + (!disable || (save_command & PCI_COMMAND_MEMORY))) { prefetchable = 0; mem_node = t_mem_node; res_type_str++; @@ -613,16 +650,20 @@ int pciehp_save_used_resources (struct c if (prefetchable) { p_mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK; p_mem_node->length = (ulong)base; - dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n", res_type_str, - p_mem_node->base, p_mem_node->length); + dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n", + res_type_str, + p_mem_node->base, + p_mem_node->length); p_mem_node->next = func->p_mem_head; func->p_mem_head = p_mem_node; } else { mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK; mem_node->length = (ulong)base; - dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n", res_type_str, - mem_node->base, mem_node->length); + dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n", + res_type_str, + mem_node->base, + mem_node->length); mem_node->next = func->mem_head; func->mem_head = mem_node; @@ -642,16 +683,20 @@ int pciehp_save_used_resources (struct c if (prefetchable) { p_mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK; p_mem_node->length = base; - dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n", res_type_str, - p_mem_node->base, p_mem_node->length); + dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n", + res_type_str, + p_mem_node->base, + p_mem_node->length); p_mem_node->next = func->p_mem_head; func->p_mem_head = p_mem_node; } else { mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK; mem_node->length = base; - dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n", res_type_str, - mem_node->base, mem_node->length); + dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n", + res_type_str, + mem_node->base, + mem_node->length); mem_node->next = func->mem_head; func->mem_head = mem_node; @@ -659,13 +704,15 @@ int pciehp_save_used_resources (struct c cloop += 4; break; default: - dbg("asur: reserved BAR type=0x%x\n", temp_register); + dbg("asur: reserved BAR type=0x%x\n", + temp_register); break; } } } /* End of base register loop */ } else { /* Some other unknown header type */ - dbg("Save_used_res of PCI unknown type b:d=0x%x:%x. skip.\n", func->bus, func->device); + dbg("Save_used_res of PCI unknown type b:d=0x%x:%x. skip.\n", + func->bus, func->device); } /* find the next device in this slot */ @@ -674,10 +721,29 @@ int pciehp_save_used_resources (struct c func = pciehp_slot_find(func->bus, func->device, index++); } - return(0); + return 0; } +/** + * kfree_resource_list: release memory of all list members + * @res: resource list to free + */ +static inline void +return_resource_list(struct pci_resource **func, struct pci_resource **res) +{ + struct pci_resource *node; + struct pci_resource *t_node; + + node = *func; + *func = NULL; + while (node) { + t_node = node->next; + return_resource(res, node); + node = t_node; + } +} + /* * pciehp_return_board_resources * @@ -686,95 +752,40 @@ int pciehp_save_used_resources (struct c * * returns 0 if success */ -int pciehp_return_board_resources(struct pci_func * func, struct resource_lists * resources) +int pciehp_return_board_resources(struct pci_func * func, + struct resource_lists * resources) { - int rc = 0; - struct pci_resource *node; - struct pci_resource *t_node; + int rc; + dbg("%s\n", __FUNCTION__); if (!func) - return(1); + return 1; - node = func->io_head; - func->io_head = NULL; - while (node) { - t_node = node->next; - return_resource(&(resources->io_head), node); - node = t_node; - } + return_resource_list(&(func->io_head),&(resources->io_head)); + return_resource_list(&(func->mem_head),&(resources->mem_head)); + return_resource_list(&(func->p_mem_head),&(resources->p_mem_head)); + return_resource_list(&(func->bus_head),&(resources->bus_head)); - node = func->mem_head; - func->mem_head = NULL; - while (node) { - t_node = node->next; - return_resource(&(resources->mem_head), node); - node = t_node; - } - - node = func->p_mem_head; - func->p_mem_head = NULL; - while (node) { - t_node = node->next; - return_resource(&(resources->p_mem_head), node); - node = t_node; - } - - node = func->bus_head; - func->bus_head = NULL; - while (node) { - t_node = node->next; - return_resource(&(resources->bus_head), node); - node = t_node; - } - - rc |= pciehp_resource_sort_and_combine(&(resources->mem_head)); + rc = pciehp_resource_sort_and_combine(&(resources->mem_head)); rc |= pciehp_resource_sort_and_combine(&(resources->p_mem_head)); rc |= pciehp_resource_sort_and_combine(&(resources->io_head)); rc |= pciehp_resource_sort_and_combine(&(resources->bus_head)); - return(rc); + return rc; } - -/* - * pciehp_destroy_resource_list - * - * Puts node back in the resource list pointed to by head +/** + * kfree_resource_list: release memory of all list members + * @res: resource list to free */ -void pciehp_destroy_resource_list (struct resource_lists * resources) +static inline void +kfree_resource_list(struct pci_resource **r) { struct pci_resource *res, *tres; - res = resources->io_head; - resources->io_head = NULL; - - while (res) { - tres = res; - res = res->next; - kfree(tres); - } - - res = resources->mem_head; - resources->mem_head = NULL; - - while (res) { - tres = res; - res = res->next; - kfree(tres); - } - - res = resources->p_mem_head; - resources->p_mem_head = NULL; - - while (res) { - tres = res; - res = res->next; - kfree(tres); - } - - res = resources->bus_head; - resources->bus_head = NULL; + res = *r; + *r = NULL; while (res) { tres = res; @@ -783,50 +794,26 @@ void pciehp_destroy_resource_list (struc } } - -/* - * pciehp_destroy_board_resources - * - * Puts node back in the resource list pointed to by head +/** + * pciehp_destroy_resource_list: put node back in the resource list + * @resources: list to put nodes back */ -void pciehp_destroy_board_resources (struct pci_func * func) +void pciehp_destroy_resource_list(struct resource_lists * resources) { - struct pci_resource *res, *tres; - - res = func->io_head; - func->io_head = NULL; - - while (res) { - tres = res; - res = res->next; - kfree(tres); - } - - res = func->mem_head; - func->mem_head = NULL; - - while (res) { - tres = res; - res = res->next; - kfree(tres); - } - - res = func->p_mem_head; - func->p_mem_head = NULL; - - while (res) { - tres = res; - res = res->next; - kfree(tres); - } - - res = func->bus_head; - func->bus_head = NULL; - - while (res) { - tres = res; - res = res->next; - kfree(tres); - } + kfree_resource_list(&(resources->io_head)); + kfree_resource_list(&(resources->mem_head)); + kfree_resource_list(&(resources->p_mem_head)); + kfree_resource_list(&(resources->bus_head)); } +/** + * pciehp_destroy_board_resources: put node back in the resource list + * @resources: list to put nodes back + */ +void pciehp_destroy_board_resources(struct pci_func * func) +{ + kfree_resource_list(&(func->io_head)); + kfree_resource_list(&(func->mem_head)); + kfree_resource_list(&(func->p_mem_head)); + kfree_resource_list(&(func->bus_head)); +} --- linux-2.6.6/drivers/pci/hotplug/pci_hotplug_core.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/pci/hotplug/pci_hotplug_core.c 2004-05-10 01:19:04.020127904 -0700 @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -45,11 +46,7 @@ #include "pci_hotplug.h" -#if !defined(CONFIG_HOTPLUG_PCI_MODULE) - #define MY_NAME "pci_hotplug" -#else - #define MY_NAME THIS_MODULE->name -#endif +#define MY_NAME "pci_hotplug" #define dbg(fmt, arg...) do { if (debug) printk(KERN_DEBUG "%s: %s: " fmt , MY_NAME , __FUNCTION__ , ## arg); } while (0) #define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg) @@ -704,7 +701,7 @@ module_exit(pci_hotplug_exit); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -MODULE_PARM(debug, "i"); +module_param(debug, bool, 644); MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); EXPORT_SYMBOL_GPL(pci_hotplug_slots_subsys); --- linux-2.6.6/drivers/pci/hotplug/pcihp_skeleton.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/pci/hotplug/pcihp_skeleton.c 2004-05-10 01:19:04.043124408 -0700 @@ -30,16 +30,14 @@ #include #include +#include #include #include #include #include #include "pci_hotplug.h" - -#define SLOT_MAGIC 0x67267322 struct slot { - u32 magic; u8 number; struct hotplug_slot *hotplug_slot; struct list_head slot_list; @@ -47,11 +45,7 @@ struct slot { static LIST_HEAD(slot_list); -#if !defined(CONFIG_HOTPLUG_PCI_SKELETON_MODULE) - #define MY_NAME "pcihp_skeleton" -#else - #define MY_NAME THIS_MODULE->name -#endif +#define MY_NAME "pcihp_skeleton" #define dbg(format, arg...) \ do { \ @@ -69,14 +63,14 @@ static LIST_HEAD(slot_list); static int debug; static int num_slots; -#define DRIVER_VERSION "0.2" +#define DRIVER_VERSION "0.3" #define DRIVER_AUTHOR "Greg Kroah-Hartman " #define DRIVER_DESC "Hot Plug PCI Controller Skeleton Driver" MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -MODULE_PARM(debug, "i"); +module_param(debug, bool, 644); MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); static int enable_slot (struct hotplug_slot *slot); @@ -100,50 +94,12 @@ static struct hotplug_slot_ops skel_hotp .get_adapter_status = get_adapter_status, }; - -/* Inline functions to check the sanity of a pointer that is passed to us */ -static inline int slot_paranoia_check (struct slot *slot, const char *function) -{ - if (!slot) { - dbg("%s - slot == NULL", function); - return -1; - } - if (slot->magic != SLOT_MAGIC) { - dbg("%s - bad magic number for slot", function); - return -1; - } - if (!slot->hotplug_slot) { - dbg("%s - slot->hotplug_slot == NULL!", function); - return -1; - } - return 0; -} - -static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const char *function) -{ - struct slot *slot; - - if (!hotplug_slot) { - dbg("%s - hotplug_slot == NULL\n", function); - return NULL; - } - - slot = (struct slot *)hotplug_slot->private; - if (slot_paranoia_check (slot, function)) - return NULL; - return slot; -} - - -static int enable_slot (struct hotplug_slot *hotplug_slot) +static int enable_slot(struct hotplug_slot *hotplug_slot) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = hotplug_slot->private; int retval = 0; - - if (slot == NULL) - return -ENODEV; - - dbg ("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); /* * Fill in code here to enable the specified slot @@ -153,15 +109,12 @@ static int enable_slot (struct hotplug_s } -static int disable_slot (struct hotplug_slot *hotplug_slot) +static int disable_slot(struct hotplug_slot *hotplug_slot) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = hotplug_slot->private; int retval = 0; - - if (slot == NULL) - return -ENODEV; - - dbg ("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); /* * Fill in code here to disable the specified slot @@ -170,15 +123,12 @@ static int disable_slot (struct hotplug_ return retval; } -static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) +static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = hotplug_slot->private; int retval = 0; - - if (slot == NULL) - return -ENODEV; - - dbg ("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); switch (status) { case 0: @@ -198,32 +148,30 @@ static int set_attention_status (struct return retval; } -static int hardware_test (struct hotplug_slot *hotplug_slot, u32 value) +static int hardware_test(struct hotplug_slot *hotplug_slot, u32 value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = hotplug_slot->private; int retval = 0; - - if (slot == NULL) - return -ENODEV; - - dbg ("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - err ("No hardware tests are defined for this driver"); - retval = -ENODEV; + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + switch (value) { + case 0: + /* Specify a test here */ + break; + case 1: + /* Specify another test here */ + break; + } - /* Or you can specify a test if you want to */ - return retval; } -static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) +static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = hotplug_slot->private; int retval = 0; - - if (slot == NULL) - return -ENODEV; - + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); /* @@ -234,14 +182,11 @@ static int get_power_status (struct hotp return retval; } -static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) +static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = hotplug_slot->private; int retval = 0; - - if (slot == NULL) - return -ENODEV; - + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); /* @@ -252,14 +197,11 @@ static int get_attention_status (struct return retval; } -static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) +static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = hotplug_slot->private; int retval = 0; - - if (slot == NULL) - return -ENODEV; - + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); /* @@ -270,14 +212,11 @@ static int get_latch_status (struct hotp return retval; } -static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) +static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = hotplug_slot->private; int retval = 0; - - if (slot == NULL) - return -ENODEV; - + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); /* @@ -288,13 +227,9 @@ static int get_adapter_status (struct ho return retval; } -static void release_slots(struct hotplug_slot *hotplug_slot) +static void release_slot(struct hotplug_slot *hotplug_slot) { - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); - int retval = 0; - - if (slot == NULL) - return -ENODEV; + struct slot *slot = hotplug_slot->private; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); kfree(slot->hotplug_slot->info); @@ -304,22 +239,26 @@ static void release_slots(struct hotplug } #define SLOT_NAME_SIZE 10 -static void make_slot_name (struct slot *slot) +static void make_slot_name(struct slot *slot) { /* * Stupid way to make a filename out of the slot name. * replace this if your hardware provides a better way to name slots. */ - snprintf (slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d", slot->number); + snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d", slot->number); } -static int init_slots (void) +/** + * init_slots - initialize 'struct slot' structures for each slot + * + */ +static int __init init_slots(void) { struct slot *slot; struct hotplug_slot *hotplug_slot; struct hotplug_slot_info *info; char *name; - int retval = 0; + int retval = -ENOMEM; int i; /* @@ -327,43 +266,34 @@ static int init_slots (void) * with the pci_hotplug subsystem. */ for (i = 0; i < num_slots; ++i) { - slot = kmalloc (sizeof (struct slot), GFP_KERNEL); + slot = kmalloc(sizeof(struct slot), GFP_KERNEL); if (!slot) - return -ENOMEM; + goto error; memset(slot, 0, sizeof(struct slot)); - hotplug_slot = kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL); - if (!hotplug_slot) { - kfree (slot); - return -ENOMEM; - } + hotplug_slot = kmalloc(sizeof(struct hotplug_slot), + GFP_KERNEL); + if (!hotplug_slot) + goto error_slot; memset(hotplug_slot, 0, sizeof (struct hotplug_slot)); slot->hotplug_slot = hotplug_slot; - info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL); - if (!info) { - kfree (hotplug_slot); - kfree (slot); - return -ENOMEM; - } + info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); + if (!info) + goto error_hpslot; memset(info, 0, sizeof (struct hotplug_slot_info)); hotplug_slot->info = info; - name = kmalloc (SLOT_NAME_SIZE, GFP_KERNEL); - if (!name) { - kfree (info); - kfree (hotplug_slot); - kfree (slot); - return -ENOMEM; - } + name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); + if (!name) + goto error_info; hotplug_slot->name = name; - slot->magic = SLOT_MAGIC; slot->number = i; hotplug_slot->private = slot; hotplug_slot->release = &release_slot; - make_slot_name (slot); + make_slot_name(slot); hotplug_slot->ops = &skel_hotplug_slot_ops; /* @@ -375,25 +305,31 @@ static int init_slots (void) info->latch_status = get_latch_status(slot); info->adapter_status = get_adapter_status(slot); - dbg ("registering slot %d\n", i); - retval = pci_hp_register (slot->hotplug_slot); + dbg("registering slot %d\n", i); + retval = pci_hp_register(slot->hotplug_slot); if (retval) { - err ("pci_hp_register failed with error %d\n", retval); - kfree (info); - kfree (name); - kfree (hotplug_slot); - kfree (slot); - return retval; + err("pci_hp_register failed with error %d\n", retval); + goto error_name; } /* add slot to our internal list */ - list_add (&slot->slot_list, &slot_list); + list_add(&slot->slot_list, &slot_list); } + return 0; +error_name: + kfree(name); +error_info: + kfree(info); +error_hpslot: + kfree(hotplug_slot); +error_slot: + kfree(slot); +error: return retval; } -static void cleanup_slots(void) +static void __exit cleanup_slots(void) { struct list_head *tmp; struct list_head *next; @@ -404,10 +340,10 @@ static void cleanup_slots(void) * Memory will be freed in release_slot() callback after slot's * lifespan is finished. */ - list_for_each_safe (tmp, next, &slot_list) { - slot = list_entry (tmp, struct slot, slot_list); - list_del (&slot->slot_list); - pci_hp_deregister (slot->hotplug_slot); + list_for_each_safe(tmp, next, &slot_list) { + slot = list_entry(tmp, struct slot, slot_list); + list_del(&slot->slot_list); + pci_hp_deregister(slot->hotplug_slot); } } @@ -415,20 +351,16 @@ static int __init pcihp_skel_init(void) { int retval; + info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); /* * Do specific initialization stuff for your driver here - * Like initilizing your controller hardware (if any) and + * Like initializing your controller hardware (if any) and * determining the number of slots you have in the system * right now. */ num_slots = 5; - retval = init_slots(); - if (retval) - return retval; - - info (DRIVER_DESC " version: " DRIVER_VERSION "\n"); - return 0; + return init_slots(); } static void __exit pcihp_skel_exit(void) @@ -441,4 +373,3 @@ static void __exit pcihp_skel_exit(void) module_init(pcihp_skel_init); module_exit(pcihp_skel_exit); - --- linux-2.6.6/drivers/pci/hotplug/rpadlpar_core.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/pci/hotplug/rpadlpar_core.c 2004-05-10 01:19:04.044124256 -0700 @@ -47,15 +47,13 @@ static struct device_node *find_php_slot { struct device_node *child; struct device_node *parent = of_find_node_by_name(NULL, "vdevice"); + char *loc_code; if (!parent) return NULL; - for (child = of_get_next_child(parent, NULL); + for (child = of_get_next_child(parent, NULL); child; child = of_get_next_child(parent, child)) { - - char *loc_code; - loc_code = get_property(child, "ibm,loc-code", NULL); if (loc_code && !strcmp(loc_code, drc_name)) return child; @@ -309,12 +307,8 @@ int dlpar_remove_vio_slot(struct slot *s */ int dlpar_remove_pci_slot(struct slot *slot, char *drc_name) { - struct device_node *dn = find_php_slot_pci_node(drc_name); struct pci_dev *bridge_dev; - if (!dn) - return -ENODEV; - bridge_dev = slot->bridge; if (!bridge_dev) { printk(KERN_ERR "%s: unexpected null bridge device\n", @@ -358,13 +352,19 @@ int dlpar_remove_slot(char *drc_name) if (down_interruptible(&rpadlpar_sem)) return -ERESTARTSYS; - + + if (!find_php_slot_vio_node(drc_name) && + !find_php_slot_pci_node(drc_name)) { + rc = -ENODEV; + goto exit; + } + slot = find_slot(drc_name); if (!slot) { rc = -EINVAL; goto exit; } - + switch (slot->dev_type) { case PCI_DEV: rc = dlpar_remove_pci_slot(slot, drc_name); --- linux-2.6.6/drivers/pci/hotplug/rpaphp_core.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/pci/hotplug/rpaphp_core.c 2004-05-10 01:19:04.046123952 -0700 @@ -54,7 +54,7 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -module_param(debug, int, 0644); +module_param(debug, bool, 0644); static int enable_slot(struct hotplug_slot *slot); static int disable_slot(struct hotplug_slot *slot); @@ -63,7 +63,6 @@ static int get_power_status(struct hotpl static int get_attention_status(struct hotplug_slot *slot, u8 * value); static int get_adapter_status(struct hotplug_slot *slot, u8 * value); static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value); -static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value); struct hotplug_slot_ops rpaphp_hotplug_slot_ops = { .owner = THIS_MODULE, @@ -74,18 +73,8 @@ struct hotplug_slot_ops rpaphp_hotplug_s .get_attention_status = get_attention_status, .get_adapter_status = get_adapter_status, .get_max_bus_speed = get_max_bus_speed, - .get_cur_bus_speed = get_cur_bus_speed, }; -static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const char *function) -{ - if (!hotplug_slot) { - dbg("%s - hotplug_slot == NULL\n", function); - return NULL; - } - return (struct slot *)hotplug_slot->private; -} - static int rpaphp_get_attention_status(struct slot *slot) { return slot->hotplug_slot->info->attention_status; @@ -100,11 +89,8 @@ static int rpaphp_get_attention_status(s */ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value) { - int retval = 0; - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); - - if (slot == NULL) - return -ENODEV; + int retval; + struct slot *slot = (struct slot *)hotplug_slot->private; down(&rpaphp_sem); switch (value) { @@ -136,10 +122,7 @@ static int set_attention_status(struct h static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value) { int retval; - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); - - if (slot == NULL) - return -ENODEV; + struct slot *slot = (struct slot *)hotplug_slot->private; down(&rpaphp_sem); retval = rpaphp_get_power_status(slot, value); @@ -155,10 +138,7 @@ static int get_power_status(struct hotpl static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value) { int retval = 0; - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); - - if (slot == NULL) - return -ENODEV; + struct slot *slot = (struct slot *)hotplug_slot->private; down(&rpaphp_sem); *value = rpaphp_get_attention_status(slot); @@ -168,11 +148,9 @@ static int get_attention_status(struct h static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value) { - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); + struct slot *slot = (struct slot *)hotplug_slot->private; int retval = 0; - if (slot == NULL) - return -ENODEV; down(&rpaphp_sem); /* have to go through this */ switch (slot->dev_type) { @@ -191,10 +169,7 @@ static int get_adapter_status(struct hot static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) { - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); - - if (slot == NULL) - return -ENODEV; + struct slot *slot = (struct slot *)hotplug_slot->private; down(&rpaphp_sem); switch (slot->type) { @@ -231,18 +206,6 @@ static int get_max_bus_speed(struct hotp return 0; } -/* return dummy value because not sure if PRA provides any method... */ -static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) -{ - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); - - if (slot == NULL) - return -ENODEV; - - *value = PCI_SPEED_UNKNOWN; - return 0; -} - int rpaphp_remove_slot(struct slot *slot) { int retval = 0; @@ -268,24 +231,24 @@ static int is_php_dn(struct device_node { *indexes = (int *) get_property(dn, "ibm,drc-indexes", NULL); if (!*indexes) - return (0); + return 0; /* &names[1] contains NULL terminated slot names */ *names = (int *) get_property(dn, "ibm,drc-names", NULL); if (!*names) - return (0); + return 0; /* &types[1] contains NULL terminated slot types */ *types = (int *) get_property(dn, "ibm,drc-types", NULL); if (!*types) - return (0); + return 0; /* power_domains[1...n] are the slot power domains */ *power_domains = (int *) get_property(dn, "ibm,drc-power-domains", NULL); if (!*power_domains) - return (0); + return 0; if (strcmp(dn->name, "pci") == 0 && - !get_property(dn, "ibm,fw-pci-hot-plug-ctrl", NULL)) - return (0); - return (1); + !get_property(dn, "ibm,fw-pci-hot-plug-ctrl", NULL)) + return 0; + return 1; } static inline int is_vdevice_root(struct device_node *dn) @@ -293,10 +256,10 @@ static inline int is_vdevice_root(struct return !strcmp(dn->name, "vdevice"); } -/************************************* - * Add Hot Plug slot(s) to sysfs +/** + * rpaphp_add_slot: Add Hot Plug slot(s) to sysfs * - ************************************/ + */ int rpaphp_add_slot(struct device_node *dn) { struct slot *slot; @@ -320,8 +283,9 @@ int rpaphp_add_slot(struct device_node * name = (char *) &names[1]; type = (char *) &types[1]; for (i = 0; i < indexes[0]; - i++, - name += (strlen(name) + 1), type += (strlen(type) + 1)) { + i++, + name += (strlen(name) + 1), + type += (strlen(type) + 1)) { if (!(slot = alloc_slot_struct(dn, indexes[i + 1], name, power_domains[i + 1]))) { retval = -ENOMEM; @@ -334,38 +298,28 @@ int rpaphp_add_slot(struct device_node * } /* for indexes */ } /* end of PCI device_node */ - exit: +exit: dbg("%s - Exit: num_slots=%d rc[%d]\n", __FUNCTION__, num_slots, retval); return retval; } -/* - * init_slots - initialize 'struct slot' structures for each slot - * - */ -static void init_slots(void) +static int __init init_rpa(void) { struct device_node *dn; - for (dn = find_all_nodes(); dn; dn = dn->next) - rpaphp_add_slot(dn); -} - -static int init_rpa(void) -{ - init_MUTEX(&rpaphp_sem); /* initialize internal data structure etc. */ - init_slots(); + for (dn = find_all_nodes(); dn; dn = dn->next) + rpaphp_add_slot(dn); if (!num_slots) return -ENODEV; return 0; } -static void cleanup_slots(void) +static void __exit cleanup_slots(void) { struct list_head *tmp, *n; struct slot *slot; @@ -400,10 +354,7 @@ static void __exit rpaphp_exit(void) static int enable_slot(struct hotplug_slot *hotplug_slot) { int retval = 0; - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); - - if (slot == NULL) - return -ENODEV; + struct slot *slot = (struct slot *)hotplug_slot->private; if (slot->state == CONFIGURED) { dbg("%s: %s is already enabled\n", __FUNCTION__, slot->name); @@ -431,10 +382,7 @@ static int enable_slot(struct hotplug_sl static int disable_slot(struct hotplug_slot *hotplug_slot) { int retval; - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); - - if (slot == NULL) - return -ENODEV; + struct slot *slot = (struct slot *)hotplug_slot->private; dbg("%s - Entry: slot[%s]\n", __FUNCTION__, slot->name); --- linux-2.6.6/drivers/pci/hotplug/rpaphp.h 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/pci/hotplug/rpaphp.h 2004-05-10 01:19:04.044124256 -0700 @@ -62,8 +62,6 @@ extern int debug; #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) -#define SLOT_MAGIC 0x67267322 - /* slot types */ #define VIO_DEV 1 #define PCI_DEV 2 @@ -79,7 +77,6 @@ extern int debug; * struct slot - slot information for each *physical* slot */ struct slot { - u32 magic; int state; u32 index; u32 type; --- linux-2.6.6/drivers/pci/hotplug/rpaphp_pci.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/pci/hotplug/rpaphp_pci.c 2004-05-10 01:19:04.047123800 -0700 @@ -30,7 +30,7 @@ struct pci_dev *rpaphp_find_pci_dev(struct device_node *dn) { - struct pci_dev *retval_dev = NULL, *dev = NULL; + struct pci_dev *retval_dev = NULL, *dev; char bus_id[BUS_ID_SIZE]; sprintf(bus_id, "%04x:%02x:%02x.%d",dn->phb->global_number, @@ -57,9 +57,8 @@ int rpaphp_claim_resource(struct pci_dev struct resource *res = &dev->resource[resource]; struct resource *root = pci_find_parent_resource(dev, res); char *dtype = resource < PCI_BRIDGE_RESOURCES ? "device" : "bridge"; - int err; + int err = -EINVAL; - err = -EINVAL; if (root != NULL) { err = request_resource(root, res); } @@ -117,8 +116,8 @@ static int rpaphp_get_sensor_state(struc return rc; } -/* - * get_pci_adapter_status - get the status of a slot +/** + * get_pci_adapter_status - get the status of a slot * * 0-- slot is empty * 1-- adapter is configured @@ -136,7 +135,7 @@ int rpaphp_get_pci_adapter_status(struct if (state == PRESENT) { if (!is_init) /* at run-time slot->state can be changed by */ - /* config/unconfig adapter */ + /* config/unconfig adapter */ *value = slot->state; else { if (!slot->dn->child) @@ -154,7 +153,7 @@ int rpaphp_get_pci_adapter_status(struct *value = state; } - exit: +exit: return rc; } @@ -175,6 +174,7 @@ static void rpaphp_fixup_new_pci_devices pci_read_irq_line(dev); for (i = 0; i < PCI_NUM_RESOURCES; i++) { struct resource *r = &dev->resource[i]; + if (r->parent || !r->start || !r->flags) continue; rpaphp_claim_resource(dev, i); @@ -183,7 +183,8 @@ static void rpaphp_fixup_new_pci_devices } } -static void rpaphp_pci_config_device(struct pci_bus *pci_bus, struct device_node *dn) +static void +rpaphp_pci_config_device(struct pci_bus *pci_bus, struct device_node *dn) { int num; @@ -192,7 +193,6 @@ static void rpaphp_pci_config_device(str rpaphp_fixup_new_pci_devices(pci_bus); pci_bus_add_devices(pci_bus); } - return; } static int rpaphp_pci_config_bridge(struct pci_dev *dev, struct device_node *dn); @@ -201,7 +201,8 @@ static int rpaphp_pci_config_bridge(stru rpaphp_pci_config_dn() will recursively configure all devices under the given slot->dn and return the dn's pci_dev. *****************************************************************************/ -static struct pci_dev *rpaphp_pci_config_dn(struct device_node *dn, struct pci_bus *bus) +static struct pci_dev * +rpaphp_pci_config_dn(struct device_node *dn, struct pci_bus *bus) { struct device_node *local; struct pci_dev *dev; @@ -256,16 +257,16 @@ static struct pci_dev *rpaphp_config_pci goto exit; } + eeh_add_device_early(slot->dn->child); dev = rpaphp_pci_config_dn(slot->dn, pci_bus); - eeh_add_device(dev); + eeh_add_device_late(dev); } else { /* slot is not enabled */ err("slot doesn't have pci_dev structure\n"); dev = NULL; - goto exit; } - exit: +exit: dbg("Exit %s: pci_dev %s\n", __FUNCTION__, dev ? "found" : "not found"); return dev; } @@ -304,9 +305,9 @@ static int setup_pci_hotplug_slot_info(s if (slot->hotplug_slot->info->adapter_status == NOT_VALID) { dbg("%s: NOT_VALID: skip dn->full_name=%s\n", __FUNCTION__, slot->dn->full_name); - return (-1); + return -1; } - return (0); + return 0; } static int setup_pci_slot(struct slot *slot) @@ -317,7 +318,8 @@ static int setup_pci_slot(struct slot *s dealloc_slot_struct(slot); return 1; } - + + strcpy(slot->name, pci_name(slot->bridge)); /* find slot's pci_dev if it's not empty */ if (slot->hotplug_slot->info->adapter_status == EMPTY) { slot->state = EMPTY; /* slot is empty */ @@ -353,7 +355,7 @@ int register_pci_slot(struct slot *slot) if (setup_pci_slot(slot)) goto exit_rc; rc = register_slot(slot); - exit_rc: +exit_rc: if (rc) dealloc_slot_struct(slot); return rc; @@ -389,7 +391,7 @@ int rpaphp_enable_pci_slot(struct slot * slot->state = NOT_VALID; retval = -EINVAL; } - exit: +exit: if (slot->state != NOT_VALID) rpaphp_set_attention_status(slot, LED_ON); else --- linux-2.6.6/drivers/pci/hotplug/rpaphp_slot.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/pci/hotplug/rpaphp_slot.c 2004-05-10 01:19:04.048123648 -0700 @@ -58,13 +58,10 @@ void rpaphp_sysfs_remove_attr_location ( sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_location.attr); } -/* free up the memory user by a slot */ +/* free up the memory used by a slot */ static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot) { - struct slot *slot = hotplug_slot? (struct slot *) hotplug_slot->private:NULL; - - if (slot == NULL) - return; + struct slot *slot = (struct slot *) hotplug_slot->private; dealloc_slot_struct(slot); } @@ -83,54 +80,47 @@ struct slot *alloc_slot_struct(struct de { struct slot *slot; - dbg("Enter alloc_slot_struct(): dn->full_name=%s drc_index=0x%x drc_name=%s\n", - dn->full_name, drc_index, drc_name); - slot = kmalloc(sizeof (struct slot), GFP_KERNEL); if (!slot) - return (NULL); + goto error_nomem; memset(slot, 0, sizeof (struct slot)); slot->hotplug_slot = kmalloc(sizeof (struct hotplug_slot), GFP_KERNEL); - if (!slot->hotplug_slot) { - kfree(slot); - return (NULL); - } + if (!slot->hotplug_slot) + goto error_slot; memset(slot->hotplug_slot, 0, sizeof (struct hotplug_slot)); slot->hotplug_slot->info = kmalloc(sizeof (struct hotplug_slot_info), GFP_KERNEL); - if (!slot->hotplug_slot->info) { - kfree(slot->hotplug_slot); - kfree(slot); - return (NULL); - } + if (!slot->hotplug_slot->info) + goto error_hpslot; memset(slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info)); slot->hotplug_slot->name = kmalloc(BUS_ID_SIZE + 1, GFP_KERNEL); - if (!slot->hotplug_slot->name) { - kfree(slot->hotplug_slot->info); - kfree(slot->hotplug_slot); - kfree(slot); - return (NULL); - } + if (!slot->hotplug_slot->name) + goto error_info; slot->location = kmalloc(strlen(drc_name) + 1, GFP_KERNEL); - if (!slot->location) { - kfree(slot->hotplug_slot->info); - kfree(slot->hotplug_slot->name); - kfree(slot->hotplug_slot); - kfree(slot); - return (NULL); - } + if (!slot->location) + goto error_name; slot->name = slot->hotplug_slot->name; slot->dn = dn; slot->index = drc_index; strcpy(slot->location, drc_name); slot->power_domain = power_domain; - slot->magic = SLOT_MAGIC; slot->hotplug_slot->private = slot; slot->hotplug_slot->ops = &rpaphp_hotplug_slot_ops; slot->hotplug_slot->release = &rpaphp_release_slot; - dbg("Exit alloc_slot_struct(): slot->dn->full_name=%s drc_index=0x%x drc_name=%s\n", - slot->dn->full_name, slot->index, slot->name); - return (slot); + slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN; + + return slot; + +error_name: + kfree(slot->hotplug_slot->name); +error_info: + kfree(slot->hotplug_slot->info); +error_hpslot: + kfree(slot->hotplug_slot); +error_slot: + kfree(slot); +error_nomem: + return NULL; } int register_slot(struct slot *slot) @@ -138,13 +128,15 @@ int register_slot(struct slot *slot) int retval; char *vio_uni_addr = NULL; - dbg("%s registering slot:path[%s] index[%x], name[%s] pdomain[%x] type[%d]\n", __FUNCTION__, slot->dn->full_name, slot->index, slot->name, slot->power_domain, slot->type); + dbg("%s registering slot:path[%s] index[%x], name[%s] pdomain[%x] type[%d]\n", + __FUNCTION__, slot->dn->full_name, slot->index, slot->name, + slot->power_domain, slot->type); retval = pci_hp_register(slot->hotplug_slot); if (retval) { err("pci_hp_register failed with error %d\n", retval); rpaphp_release_slot(slot->hotplug_slot); - return (retval); + return retval; } /* create "phy_locatoin" file */ @@ -163,7 +155,7 @@ int register_slot(struct slot *slot) info("Slot [%s](bus_id=%s) registered\n", slot->name, pci_name(slot->bridge)); num_slots++; - return (0); + return 0; } int rpaphp_get_power_status(struct slot *slot, u8 * value) --- linux-2.6.6/drivers/pci/hotplug/rpaphp_vio.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/pci/hotplug/rpaphp_vio.c 2004-05-10 01:19:04.048123648 -0700 @@ -94,6 +94,7 @@ int register_vio_slot(struct device_node slot->state = NOT_CONFIGURED; if (setup_vio_hotplug_slot_info(slot)) goto exit_rc; + strcpy(slot->name, slot->dev.vio_dev->dev.bus_id); info("%s: registered VIO device[name=%s vio_dev=%p]\n", __FUNCTION__, slot->name, slot->dev.vio_dev); rc = register_slot(slot); --- linux-2.6.6/drivers/pci/hotplug/shpchp_core.c 2004-03-10 20:41:29.000000000 -0800 +++ 25/drivers/pci/hotplug/shpchp_core.c 2004-05-10 01:19:04.050123344 -0700 @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -56,9 +57,9 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -MODULE_PARM(shpchp_debug, "i"); -MODULE_PARM(shpchp_poll_mode, "i"); -MODULE_PARM(shpchp_poll_time, "i"); +module_param(shpchp_debug, bool, 644); +module_param(shpchp_poll_mode, bool, 644); +module_param(shpchp_poll_time, int, 644); MODULE_PARM_DESC(shpchp_debug, "Debugging mode enabled or not"); MODULE_PARM_DESC(shpchp_poll_mode, "Using polling mechanism for hot-plug events or not"); MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds"); @@ -69,7 +70,6 @@ static int shpc_start_thread (void); static int set_attention_status (struct hotplug_slot *slot, u8 value); static int enable_slot (struct hotplug_slot *slot); static int disable_slot (struct hotplug_slot *slot); -static int hardware_test (struct hotplug_slot *slot, u32 value); static int get_power_status (struct hotplug_slot *slot, u8 *value); static int get_attention_status (struct hotplug_slot *slot, u8 *value); static int get_latch_status (struct hotplug_slot *slot, u8 *value); @@ -82,22 +82,37 @@ static struct hotplug_slot_ops shpchp_ho .set_attention_status = set_attention_status, .enable_slot = enable_slot, .disable_slot = disable_slot, - .hardware_test = hardware_test, .get_power_status = get_power_status, .get_attention_status = get_attention_status, - .get_latch_status = get_latch_status, + .get_latch_status = get_latch_status, .get_adapter_status = get_adapter_status, - .get_max_bus_speed = get_max_bus_speed, - .get_cur_bus_speed = get_cur_bus_speed, + .get_max_bus_speed = get_max_bus_speed, + .get_cur_bus_speed = get_cur_bus_speed, }; +/** + * release_slot - free up the memory used by a slot + * @hotplug_slot: slot to free + */ +static void release_slot(struct hotplug_slot *hotplug_slot) +{ + struct slot *slot = (struct slot *)hotplug_slot->private; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + kfree(slot->hotplug_slot->info); + kfree(slot->hotplug_slot->name); + kfree(slot->hotplug_slot); + kfree(slot); +} + static int init_slots(struct controller *ctrl) { struct slot *new_slot; u8 number_of_slots; u8 slot_device; u32 slot_number, sun; - int result; + int result = -ENOMEM; dbg("%s\n",__FUNCTION__); @@ -108,30 +123,21 @@ static int init_slots(struct controller while (number_of_slots) { new_slot = (struct slot *) kmalloc(sizeof(struct slot), GFP_KERNEL); if (!new_slot) - return -ENOMEM; + goto error; memset(new_slot, 0, sizeof(struct slot)); new_slot->hotplug_slot = kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL); - if (!new_slot->hotplug_slot) { - kfree (new_slot); - return -ENOMEM; - } + if (!new_slot->hotplug_slot) + goto error_slot; memset(new_slot->hotplug_slot, 0, sizeof (struct hotplug_slot)); new_slot->hotplug_slot->info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL); - if (!new_slot->hotplug_slot->info) { - kfree (new_slot->hotplug_slot); - kfree (new_slot); - return -ENOMEM; - } + if (!new_slot->hotplug_slot->info) + goto error_hpslot; memset(new_slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info)); new_slot->hotplug_slot->name = kmalloc (SLOT_NAME_SIZE, GFP_KERNEL); - if (!new_slot->hotplug_slot->name) { - kfree (new_slot->hotplug_slot->info); - kfree (new_slot->hotplug_slot); - kfree (new_slot); - return -ENOMEM; - } + if (!new_slot->hotplug_slot->name) + goto error_info; new_slot->magic = SLOT_MAGIC; new_slot->ctrl = ctrl; @@ -139,19 +145,17 @@ static int init_slots(struct controller new_slot->device = slot_device; new_slot->hpc_ops = ctrl->hpc_ops; - if (shpchprm_get_physical_slot_number(ctrl, &sun, new_slot->bus, new_slot->device)) { - kfree (new_slot->hotplug_slot->info); - kfree (new_slot->hotplug_slot); - kfree (new_slot); - return -ENOMEM; - } + if (shpchprm_get_physical_slot_number(ctrl, &sun, + new_slot->bus, new_slot->device)) + goto error_name; new_slot->number = sun; new_slot->hp_slot = slot_device - ctrl->slot_device_offset; /* register this slot with the hotplug pci core */ new_slot->hotplug_slot->private = new_slot; - make_slot_name (new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot); + new_slot->hotplug_slot->release = &release_slot; + make_slot_name(new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot); new_slot->hotplug_slot->ops = &shpchp_hotplug_slot_ops; new_slot->hpc_ops->get_power_status(new_slot, &(new_slot->hotplug_slot->info->power_status)); @@ -164,11 +168,7 @@ static int init_slots(struct controller result = pci_hp_register (new_slot->hotplug_slot); if (result) { err ("pci_hp_register failed with error %d\n", result); - kfree (new_slot->hotplug_slot->info); - kfree (new_slot->hotplug_slot->name); - kfree (new_slot->hotplug_slot); - kfree (new_slot); - return result; + goto error_name; } new_slot->next = ctrl->slot; @@ -179,29 +179,31 @@ static int init_slots(struct controller slot_number += ctrl->slot_num_inc; } - return(0); -} + return 0; +error_name: + kfree(new_slot->hotplug_slot->name); +error_info: + kfree(new_slot->hotplug_slot->info); +error_hpslot: + kfree(new_slot->hotplug_slot); +error_slot: + kfree(new_slot); +error: + return result; +} -static int cleanup_slots (struct controller * ctrl) +static void cleanup_slots(struct controller *ctrl) { - struct slot *old_slot, *next_slot; + struct slot *old_slot; old_slot = ctrl->slot; ctrl->slot = NULL; while (old_slot) { - next_slot = old_slot->next; - pci_hp_deregister (old_slot->hotplug_slot); - kfree(old_slot->hotplug_slot->info); - kfree(old_slot->hotplug_slot->name); - kfree(old_slot->hotplug_slot); - kfree(old_slot); - old_slot = next_slot; + pci_hp_deregister(old_slot->hotplug_slot); + old_slot = old_slot->next; } - - - return(0); } static int get_ctlr_slot_config(struct controller *ctrl) @@ -216,7 +218,7 @@ static int get_ctlr_slot_config(struct c rc = shpc_get_ctlr_slot_config(ctrl, &num_ctlr_slots, &first_device_num, &physical_slot_num, &updown, &flags); if (rc) { err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n", __FUNCTION__, ctrl->bus, ctrl->device); - return (-1); + return -1; } ctrl->num_slots = num_ctlr_slots; @@ -227,7 +229,7 @@ static int get_ctlr_slot_config(struct c dbg("%s: num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) updown(%d) for b:d (%x:%x)\n", __FUNCTION__, num_ctlr_slots, first_device_num, physical_slot_num, updown, ctrl->bus, ctrl->device); - return (0); + return 0; } @@ -238,15 +240,11 @@ static int set_attention_status (struct { struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); - if (slot == NULL) - return -ENODEV; - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); hotplug_slot->info->attention_status = status; slot->hpc_ops->set_attention_status(slot, status); - return 0; } @@ -254,9 +252,6 @@ static int set_attention_status (struct static int enable_slot (struct hotplug_slot *hotplug_slot) { struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); - - if (slot == NULL) - return -ENODEV; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -267,30 +262,17 @@ static int enable_slot (struct hotplug_s static int disable_slot (struct hotplug_slot *hotplug_slot) { struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); - - if (slot == NULL) - return -ENODEV; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); return shpchp_disable_slot(slot); } - -static int hardware_test (struct hotplug_slot *hotplug_slot, u32 value) -{ - return 0; -} - - static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) { struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); int retval; - - if (slot == NULL) - return -ENODEV; - + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); retval = slot->hpc_ops->get_power_status(slot, value); @@ -304,10 +286,7 @@ static int get_attention_status (struct { struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); int retval; - - if (slot == NULL) - return -ENODEV; - + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); retval = slot->hpc_ops->get_attention_status(slot, value); @@ -321,10 +300,7 @@ static int get_latch_status (struct hotp { struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); int retval; - - if (slot == NULL) - return -ENODEV; - + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); retval = slot->hpc_ops->get_latch_status(slot, value); @@ -338,14 +314,10 @@ static int get_adapter_status (struct ho { struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); int retval; - - if (slot == NULL) - return -ENODEV; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); retval = slot->hpc_ops->get_adapter_status(slot, value); - if (retval < 0) *value = hotplug_slot->info->adapter_status; @@ -356,9 +328,6 @@ static int get_max_bus_speed (struct hot { struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); int retval; - - if (slot == NULL) - return -ENODEV; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -373,9 +342,6 @@ static int get_cur_bus_speed (struct hot { struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); int retval; - - if (slot == NULL) - return -ENODEV; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -531,49 +497,35 @@ static int shpc_start_thread(void) return retval; } +static inline void __exit +free_shpchp_res(struct pci_resource *res) +{ + struct pci_resource *tres; + + while (res) { + tres = res; + res = res->next; + kfree(tres); + } +} -static void unload_shpchpd(void) +static void __exit unload_shpchpd(void) { struct pci_func *next; struct pci_func *TempSlot; int loop; struct controller *ctrl; struct controller *tctrl; - struct pci_resource *res; - struct pci_resource *tres; ctrl = shpchp_ctrl_list; while (ctrl) { cleanup_slots(ctrl); - res = ctrl->io_head; - while (res) { - tres = res; - res = res->next; - kfree(tres); - } - - res = ctrl->mem_head; - while (res) { - tres = res; - res = res->next; - kfree(tres); - } - - res = ctrl->p_mem_head; - while (res) { - tres = res; - res = res->next; - kfree(tres); - } - - res = ctrl->bus_head; - while (res) { - tres = res; - res = res->next; - kfree(tres); - } + free_shpchp_res(ctrl->io_head); + free_shpchp_res(ctrl->mem_head); + free_shpchp_res(ctrl->p_mem_head); + free_shpchp_res(ctrl->bus_head); kfree (ctrl->pci_bus); @@ -589,33 +541,10 @@ static void unload_shpchpd(void) for (loop = 0; loop < 256; loop++) { next = shpchp_slot_list[loop]; while (next != NULL) { - res = next->io_head; - while (res) { - tres = res; - res = res->next; - kfree(tres); - } - - res = next->mem_head; - while (res) { - tres = res; - res = res->next; - kfree(tres); - } - - res = next->p_mem_head; - while (res) { - tres = res; - res = res->next; - kfree(tres); - } - - res = next->bus_head; - while (res) { - tres = res; - res = res->next; - kfree(tres); - } + free_shpchp_res(ctrl->io_head); + free_shpchp_res(ctrl->mem_head); + free_shpchp_res(ctrl->p_mem_head); + free_shpchp_res(ctrl->bus_head); TempSlot = next; next = next->next; @@ -697,8 +626,5 @@ static void __exit shpcd_cleanup(void) info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); } - module_init(shpcd_init); module_exit(shpcd_cleanup); - - --- linux-2.6.6/drivers/pci/hotplug/shpchp_ctrl.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/pci/hotplug/shpchp_ctrl.c 2004-05-10 01:19:56.187197304 -0700 @@ -396,7 +396,7 @@ static struct pci_resource *do_pre_bridg /* This one isn't an aligned length, so we'll make a new entry * and split it up. */ - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + split_node = kmalloc(sizeof(*split_node), GFP_KERNEL); if (!split_node) return(NULL); @@ -530,7 +530,7 @@ static struct pci_resource *get_io_resou if ((node->length - (temp_dword - node->base)) < size) continue; - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + split_node = kmalloc(sizeof(*split_node), GFP_KERNEL); if (!split_node) return(NULL); @@ -549,7 +549,7 @@ static struct pci_resource *get_io_resou if (node->length > size) { /* This one is longer than we need so we'll make a new entry and split it up */ - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + split_node = kmalloc(sizeof(*split_node), GFP_KERNEL); if (!split_node) return(NULL); @@ -630,7 +630,7 @@ static struct pci_resource *get_max_reso if ((max->length - (temp_dword - max->base)) < size) continue; - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + split_node = kmalloc(sizeof(*split_node), GFP_KERNEL); if (!split_node) return(NULL); @@ -648,7 +648,7 @@ static struct pci_resource *get_max_reso if ((max->base + max->length) & (size - 1)) { /* This one isn't end aligned properly at the top so we'll make a new entry and split it up */ - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + split_node = kmalloc(sizeof(*split_node), GFP_KERNEL); if (!split_node) return(NULL); @@ -669,7 +669,8 @@ static struct pci_resource *get_max_reso for ( i = 0; max_size[i] > size; i++) { if (max->length > max_size[i]) { - split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + split_node = kmalloc(sizeof(*split_node), + GFP_KERNEL); if (!split_node) break; /* return (NULL); */ split_node->base = max->base + max_size[i]; @@ -744,7 +745,7 @@ static struct pci_resource *get_resource if ((node->length - (temp_dword - node->base)) < size) continue; - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + split_node = kmalloc(sizeof(*split_node), GFP_KERNEL); if (!split_node) return(NULL); @@ -764,7 +765,7 @@ static struct pci_resource *get_resource dbg("%s: too big\n", __FUNCTION__); /* this one is longer than we need so we'll make a new entry and split it up */ - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + split_node = kmalloc(sizeof(*split_node), GFP_KERNEL); if (!split_node) return(NULL); @@ -882,7 +883,7 @@ struct pci_func *shpchp_slot_create(u8 b struct pci_func *new_slot; struct pci_func *next; - new_slot = (struct pci_func *) kmalloc(sizeof(struct pci_func), GFP_KERNEL); + new_slot = kmalloc(sizeof(*new_slot), GFP_KERNEL); if (new_slot == NULL) { return(new_slot); @@ -1572,7 +1573,7 @@ static u32 board_added(struct pci_func * retval = p_slot->hpc_ops->check_cmd_status(ctrl); if (retval) { - err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc); + err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, retval); /* Done with exclusive hardware access */ up(&ctrl->crit_sect); return retval; @@ -1856,7 +1857,7 @@ static int update_slot_info (struct slot struct hotplug_slot_info *info; int result; - info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL); + info = kmalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; @@ -2504,22 +2505,18 @@ static int configure_new_function (struc /* Make copies of the nodes we are going to pass down so that * if there is a problem,we can just use these to free resources */ - hold_bus_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - hold_IO_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - hold_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - hold_p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + hold_bus_node = kmalloc(sizeof(*hold_bus_node), GFP_KERNEL); + hold_IO_node = kmalloc(sizeof(*hold_IO_node), GFP_KERNEL); + hold_mem_node = kmalloc(sizeof(*hold_mem_node), GFP_KERNEL); + hold_p_mem_node = kmalloc(sizeof(*hold_p_mem_node), GFP_KERNEL); if (!hold_bus_node || !hold_IO_node || !hold_mem_node || !hold_p_mem_node) { - if (hold_bus_node) - kfree(hold_bus_node); - if (hold_IO_node) - kfree(hold_IO_node); - if (hold_mem_node) - kfree(hold_mem_node); - if (hold_p_mem_node) - kfree(hold_p_mem_node); + kfree(hold_bus_node); + kfree(hold_IO_node); + kfree(hold_mem_node); + kfree(hold_p_mem_node); - return(1); + return 1; } memcpy(hold_bus_node, bus_node, sizeof(struct pci_resource)); @@ -2538,11 +2535,11 @@ static int configure_new_function (struc /* set IO base and Limit registers */ RES_CHECK(io_node->base, 8); temp_byte = (u8)(io_node->base >> 8); - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte); + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_BASE, temp_byte); RES_CHECK(io_node->base + io_node->length - 1, 8); temp_byte = (u8)((io_node->base + io_node->length - 1) >> 8); - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte); + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte); } else { kfree(hold_IO_node); hold_IO_node = NULL; @@ -2559,17 +2556,17 @@ static int configure_new_function (struc /* set Mem base and Limit registers */ RES_CHECK(mem_node->base, 16); temp_word = (u32)(mem_node->base >> 16); - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word); + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word); RES_CHECK(mem_node->base + mem_node->length - 1, 16); temp_word = (u32)((mem_node->base + mem_node->length - 1) >> 16); - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); } else { temp_word = 0xFFFF; - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word); + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word); temp_word = 0x0000; - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); kfree(hold_mem_node); hold_mem_node = NULL; @@ -2586,17 +2583,17 @@ static int configure_new_function (struc /* set Pre Mem base and Limit registers */ RES_CHECK(p_mem_node->base, 16); temp_word = (u32)(p_mem_node->base >> 16); - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word); + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word); RES_CHECK(p_mem_node->base + p_mem_node->length - 1, 16); temp_word = (u32)((p_mem_node->base + p_mem_node->length - 1) >> 16); - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); } else { temp_word = 0xFFFF; - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word); + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word); temp_word = 0x0000; - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); kfree(hold_p_mem_node); hold_p_mem_node = NULL; @@ -2613,7 +2610,8 @@ static int configure_new_function (struc ID = 0xFFFFFFFF; pci_bus->number = hold_bus_node->base; - pci_bus_read_config_dword (pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID); + pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0), + PCI_VENDOR_ID, &ID); pci_bus->number = func->bus; if (ID != 0xFFFFFFFF) { /* device Present */ --- linux-2.6.6/drivers/pci/hotplug/shpchp_pci.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/pci/hotplug/shpchp_pci.c 2004-05-10 01:19:04.058122128 -0700 @@ -53,10 +53,11 @@ int shpchp_configure_device (struct cont /* Still NULL ? Well then scan for it ! */ if (func->pci_dev == NULL) { num = pci_scan_slot(ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function)); - if (num) + if (num) { dbg("%s: subordiante %p number %x\n", __FUNCTION__, ctrl->pci_dev->subordinate, ctrl->pci_dev->subordinate->number); - pci_bus_add_devices(ctrl->pci_dev->subordinate); + pci_bus_add_devices(ctrl->pci_dev->subordinate); + } func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function)); if (func->pci_dev == NULL) { @@ -67,7 +68,7 @@ int shpchp_configure_device (struct cont if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus); - child = (struct pci_bus*) pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus); + child = pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus); pci_do_scan_bus(child); } @@ -81,10 +82,12 @@ int shpchp_unconfigure_device(struct pci int rc = 0; int j; - dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus, func->device, func->function); + dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus, + func->device, func->function); for (j=0; j<8 ; j++) { - struct pci_dev* temp = pci_find_slot(func->bus, (func->device << 3) | j); + struct pci_dev* temp = pci_find_slot(func->bus, + (func->device << 3) | j); if (temp) { pci_remove_bus_device(temp); } @@ -163,12 +166,14 @@ int shpchp_save_config(struct controller int is_hot_plug = num_ctlr_slots || first_device_num; struct pci_bus lpci_bus, *pci_bus; - dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__, num_ctlr_slots, first_device_num); + dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__, + num_ctlr_slots, first_device_num); memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); pci_bus = &lpci_bus; - dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__, num_ctlr_slots, first_device_num); + dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__, + num_ctlr_slots, first_device_num); /* Decide which slots are supported */ if (is_hot_plug) { @@ -182,20 +187,24 @@ int shpchp_save_config(struct controller LastSupported = 0x1F; } - dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported, LastSupported); + dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported, + LastSupported); /* Save PCI configuration space for all devices in supported slots */ pci_bus->number = busnumber; for (device = FirstSupported; device <= LastSupported; device++) { ID = 0xFFFFFFFF; - rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID); + rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0), + PCI_VENDOR_ID, &ID); if (ID != 0xFFFFFFFF) { /* device in slot */ - rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), 0x0B, &class_code); + rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), + 0x0B, &class_code); if (rc) return rc; - rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), PCI_HEADER_TYPE, &header_type); + rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), + PCI_HEADER_TYPE, &header_type); if (rc) return rc; @@ -216,7 +225,8 @@ int shpchp_save_config(struct controller /* Recurse the subordinate bus * get the subordinate bus number */ - rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, function), + rc = pci_bus_read_config_byte(pci_bus, + PCI_DEVFN(device, function), PCI_SECONDARY_BUS, &secondary_bus); if (rc) { return rc; @@ -255,13 +265,17 @@ int shpchp_save_config(struct controller new_slot->switch_save = 0x10; /* In case of unsupported board */ new_slot->status = DevError; - new_slot->pci_dev = pci_find_slot(new_slot->bus, (new_slot->device << 3) | new_slot->function); + new_slot->pci_dev = pci_find_slot(new_slot->bus, + (new_slot->device << 3) | new_slot->function); dbg("new_slot->pci_dev = %p\n", new_slot->pci_dev); for (cloop = 0; cloop < 0x20; cloop++) { - rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, function), - cloop << 2, (u32 *) & (new_slot->config_space [cloop])); - /* dbg("new_slot->config_space[%x] = %x\n", cloop, new_slot->config_space[cloop]); */ + rc = pci_bus_read_config_dword(pci_bus, + PCI_DEVFN(device, function), + cloop << 2, + (u32 *) &(new_slot->config_space [cloop])); + /* dbg("new_slot->config_space[%x] = %x\n", + cloop, new_slot->config_space[cloop]); */ if (rc) return rc; } @@ -275,23 +289,28 @@ int shpchp_save_config(struct controller */ while ((function < max_functions)&&(!stop_it)) { - rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, function), PCI_VENDOR_ID, &ID); + rc = pci_bus_read_config_dword(pci_bus, + PCI_DEVFN(device, function), + PCI_VENDOR_ID, &ID); if (ID == 0xFFFFFFFF) { /* nothing there. */ function++; dbg("Nothing there\n"); } else { /* Something there */ - rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, function), + rc = pci_bus_read_config_byte(pci_bus, + PCI_DEVFN(device, function), 0x0B, &class_code); if (rc) return rc; - rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, function), + rc = pci_bus_read_config_byte(pci_bus, + PCI_DEVFN(device, function), PCI_HEADER_TYPE, &header_type); if (rc) return rc; - dbg("class_code = %x, header_type = %x\n", class_code, header_type); + dbg("class_code = %x, header_type = %x\n", + class_code, header_type); stop_it++; } } @@ -328,7 +347,7 @@ int shpchp_save_config(struct controller * * returns 0 if success */ -int shpchp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot) +int shpchp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot) { int rc; u8 class_code; @@ -347,12 +366,15 @@ int shpchp_save_slot_config (struct cont ID = 0xFFFFFFFF; - pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_VENDOR_ID, &ID); + pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, 0), + PCI_VENDOR_ID, &ID); if (ID != 0xFFFFFFFF) { /* device in slot */ - pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), 0x0B, &class_code); + pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), + 0x0B, &class_code); - pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_HEADER_TYPE, &header_type); + pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), + PCI_HEADER_TYPE, &header_type); if (header_type & 0x80) /* Multi-function device */ max_functions = 8; @@ -364,7 +386,8 @@ int shpchp_save_slot_config (struct cont do { if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */ /* Recurse the subordinate bus */ - pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, function), + pci_bus_read_config_byte(pci_bus, + PCI_DEVFN(new_slot->device, function), PCI_SECONDARY_BUS, &secondary_bus); sub_bus = (int) secondary_bus; @@ -373,15 +396,17 @@ int shpchp_save_slot_config (struct cont rc = shpchp_save_config(ctrl, sub_bus, 0, 0); if (rc) - return(rc); + return rc; } /* End of IF */ new_slot->status = 0; for (cloop = 0; cloop < 0x20; cloop++) { - pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, function), - cloop << 2, (u32 *) & (new_slot->config_space [cloop])); + pci_bus_read_config_dword(pci_bus, + PCI_DEVFN(new_slot->device, function), + cloop << 2, + (u32 *) &(new_slot->config_space [cloop])); } function++; @@ -393,15 +418,20 @@ int shpchp_save_slot_config (struct cont */ while ((function < max_functions) && (!stop_it)) { - pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, function), PCI_VENDOR_ID, &ID); + pci_bus_read_config_dword(pci_bus, + PCI_DEVFN(new_slot->device, function), + PCI_VENDOR_ID, &ID); if (ID == 0xFFFFFFFF) { /* nothing there. */ function++; } else { /* Something there */ - pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, function), 0x0B, &class_code); - - pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, function), PCI_HEADER_TYPE, - &header_type); + pci_bus_read_config_byte(pci_bus, + PCI_DEVFN(new_slot->device, function), + 0x0B, &class_code); + + pci_bus_read_config_byte(pci_bus, + PCI_DEVFN(new_slot->device, function), + PCI_HEADER_TYPE, &header_type); stop_it++; } @@ -410,10 +440,10 @@ int shpchp_save_slot_config (struct cont } while (function < max_functions); } /* End of IF (device in slot?) */ else { - return(2); + return 2; } - return(0); + return 0; } @@ -429,7 +459,7 @@ int shpchp_save_slot_config (struct cont * it loops for all functions of the slot and disables them. * else, it just get resources of the function and return. */ -int shpchp_save_used_resources (struct controller *ctrl, struct pci_func *func, int disable) +int shpchp_save_used_resources(struct controller *ctrl, struct pci_func *func, int disable) { u8 cloop; u8 header_type; @@ -461,7 +491,7 @@ int shpchp_save_used_resources (struct c devfn = PCI_DEVFN(func->device, func->function); /* Save the command register */ - pci_bus_read_config_word (pci_bus, devfn, PCI_COMMAND, &save_command); + pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &save_command); if (disable) { /* disable card */ @@ -470,20 +500,22 @@ int shpchp_save_used_resources (struct c } /* Check for Bridge */ - pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type); + pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type); if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */ - dbg("Save_used_res of PCI bridge b:d=0x%x:%x, sc=0x%x\n", func->bus, func->device, save_command); + dbg("Save_used_res of PCI bridge b:d=0x%x:%x, sc=0x%x\n", + func->bus, func->device, save_command); if (disable) { /* Clear Bridge Control Register */ command = 0x00; pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command); } - pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus); - pci_bus_read_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte); + pci_bus_read_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus); + pci_bus_read_config_byte(pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte); - bus_node =(struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + bus_node = kmalloc(sizeof(struct pci_resource), + GFP_KERNEL); if (!bus_node) return -ENOMEM; @@ -494,13 +526,14 @@ int shpchp_save_used_resources (struct c func->bus_head = bus_node; /* Save IO base and Limit registers */ - pci_bus_read_config_byte (pci_bus, devfn, PCI_IO_BASE, &temp_byte); + pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_BASE, &temp_byte); base = temp_byte; - pci_bus_read_config_byte (pci_bus, devfn, PCI_IO_LIMIT, &temp_byte); + pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_LIMIT, &temp_byte); length = temp_byte; if ((base <= length) && (!disable || (save_command & PCI_COMMAND_IO))) { - io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + io_node = kmalloc(sizeof(struct pci_resource), + GFP_KERNEL); if (!io_node) return -ENOMEM; @@ -512,11 +545,12 @@ int shpchp_save_used_resources (struct c } /* Save memory base and Limit registers */ - pci_bus_read_config_word (pci_bus, devfn, PCI_MEMORY_BASE, &w_base); - pci_bus_read_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length); + pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_BASE, &w_base); + pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length); if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) { - mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + mem_node = kmalloc(sizeof(struct pci_resource), + GFP_KERNEL); if (!mem_node) return -ENOMEM; @@ -527,11 +561,12 @@ int shpchp_save_used_resources (struct c func->mem_head = mem_node; } /* Save prefetchable memory base and Limit registers */ - pci_bus_read_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base); - pci_bus_read_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length); + pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base); + pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length); if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) { - p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + p_mem_node = kmalloc(sizeof(struct pci_resource), + GFP_KERNEL); if (!p_mem_node) return -ENOMEM; @@ -542,38 +577,41 @@ int shpchp_save_used_resources (struct c func->p_mem_head = p_mem_node; } } else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) { - dbg("Save_used_res of PCI adapter b:d=0x%x:%x, sc=0x%x\n", func->bus, func->device, save_command); + dbg("Save_used_res of PCI adapter b:d=0x%x:%x, sc=0x%x\n", + func->bus, func->device, save_command); /* Figure out IO and memory base lengths */ for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) { - pci_bus_read_config_dword (pci_bus, devfn, cloop, &save_base); + pci_bus_read_config_dword(pci_bus, devfn, cloop, &save_base); temp_register = 0xFFFFFFFF; - pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register); - pci_bus_read_config_dword (pci_bus, devfn, cloop, &temp_register); + pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register); + pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register); - if (!disable) { - pci_bus_write_config_dword (pci_bus, devfn, cloop, save_base); - } + if (!disable) + pci_bus_write_config_dword(pci_bus, devfn, cloop, save_base); if (!temp_register) continue; base = temp_register; - if ((base & PCI_BASE_ADDRESS_SPACE_IO) && (!disable || (save_command & PCI_COMMAND_IO))) { + if ((base & PCI_BASE_ADDRESS_SPACE_IO) && + (!disable || (save_command & PCI_COMMAND_IO))) { /* IO base */ /* set temp_register = amount of IO space requested */ base = base & 0xFFFFFFFCL; base = (~base) + 1; - io_node = (struct pci_resource *) kmalloc(sizeof (struct pci_resource), GFP_KERNEL); + io_node = kmalloc(sizeof (struct pci_resource), + GFP_KERNEL); if (!io_node) return -ENOMEM; io_node->base = (ulong)save_base & PCI_BASE_ADDRESS_IO_MASK; io_node->length = (ulong)base; - dbg("sur adapter: IO bar=0x%x(length=0x%x)\n", io_node->base, io_node->length); + dbg("sur adapter: IO bar=0x%x(length=0x%x)\n", + io_node->base, io_node->length); io_node->next = func->io_head; func->io_head = io_node; @@ -583,11 +621,13 @@ int shpchp_save_used_resources (struct c char *res_type_str = "PMEM"; u32 temp_register2; - t_mem_node = (struct pci_resource *) kmalloc(sizeof (struct pci_resource), GFP_KERNEL); + t_mem_node = kmalloc(sizeof (struct pci_resource), + GFP_KERNEL); if (!t_mem_node) return -ENOMEM; - if (!(base & PCI_BASE_ADDRESS_MEM_PREFETCH) && (!disable || (save_command & PCI_COMMAND_MEMORY))) { + if (!(base & PCI_BASE_ADDRESS_MEM_PREFETCH) && + (!disable || (save_command & PCI_COMMAND_MEMORY))) { prefetchable = 0; mem_node = t_mem_node; res_type_str++; @@ -602,16 +642,20 @@ int shpchp_save_used_resources (struct c if (prefetchable) { p_mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK; p_mem_node->length = (ulong)base; - dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n", res_type_str, - p_mem_node->base, p_mem_node->length); + dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n", + res_type_str, + p_mem_node->base, + p_mem_node->length); p_mem_node->next = func->p_mem_head; func->p_mem_head = p_mem_node; } else { mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK; mem_node->length = (ulong)base; - dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n", res_type_str, - mem_node->base, mem_node->length); + dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n", + res_type_str, + mem_node->base, + mem_node->length); mem_node->next = func->mem_head; func->mem_head = mem_node; @@ -631,16 +675,20 @@ int shpchp_save_used_resources (struct c if (prefetchable) { p_mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK; p_mem_node->length = base; - dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n", res_type_str, - p_mem_node->base, p_mem_node->length); + dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n", + res_type_str, + p_mem_node->base, + p_mem_node->length); p_mem_node->next = func->p_mem_head; func->p_mem_head = p_mem_node; } else { mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK; mem_node->length = base; - dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n", res_type_str, - mem_node->base, mem_node->length); + dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n", + res_type_str, + mem_node->base, + mem_node->length); mem_node->next = func->mem_head; func->mem_head = mem_node; @@ -648,13 +696,15 @@ int shpchp_save_used_resources (struct c cloop += 4; break; default: - dbg("asur: reserved BAR type=0x%x\n", temp_register); + dbg("asur: reserved BAR type=0x%x\n", + temp_register); break; } } } /* End of base register loop */ } else { /* Some other unknown header type */ - dbg("Save_used_res of PCI unknown type b:d=0x%x:%x. skip.\n", func->bus, func->device); + dbg("Save_used_res of PCI unknown type b:d=0x%x:%x. skip.\n", + func->bus, func->device); } /* find the next device in this slot */ @@ -663,9 +713,27 @@ int shpchp_save_used_resources (struct c func = shpchp_slot_find(func->bus, func->device, index++); } - return(0); + return 0; } +/** + * kfree_resource_list: release memory of all list members + * @res: resource list to free + */ +static inline void +return_resource_list(struct pci_resource **func, struct pci_resource **res) +{ + struct pci_resource *node; + struct pci_resource *t_node; + + node = *func; + *func = NULL; + while (node) { + t_node = node->next; + return_resource(res, node); + node = t_node; + } +} /* * shpchp_return_board_resources @@ -675,95 +743,39 @@ int shpchp_save_used_resources (struct c * * returns 0 if success */ -int shpchp_return_board_resources(struct pci_func * func, struct resource_lists * resources) +int shpchp_return_board_resources(struct pci_func * func, + struct resource_lists * resources) { - int rc = 0; - struct pci_resource *node; - struct pci_resource *t_node; + int rc; dbg("%s\n", __FUNCTION__); if (!func) - return(1); - - node = func->io_head; - func->io_head = NULL; - while (node) { - t_node = node->next; - return_resource(&(resources->io_head), node); - node = t_node; - } + return 1; - node = func->mem_head; - func->mem_head = NULL; - while (node) { - t_node = node->next; - return_resource(&(resources->mem_head), node); - node = t_node; - } + return_resource_list(&(func->io_head),&(resources->io_head)); + return_resource_list(&(func->mem_head),&(resources->mem_head)); + return_resource_list(&(func->p_mem_head),&(resources->p_mem_head)); + return_resource_list(&(func->bus_head),&(resources->bus_head)); - node = func->p_mem_head; - func->p_mem_head = NULL; - while (node) { - t_node = node->next; - return_resource(&(resources->p_mem_head), node); - node = t_node; - } - - node = func->bus_head; - func->bus_head = NULL; - while (node) { - t_node = node->next; - return_resource(&(resources->bus_head), node); - node = t_node; - } - - rc |= shpchp_resource_sort_and_combine(&(resources->mem_head)); + rc = shpchp_resource_sort_and_combine(&(resources->mem_head)); rc |= shpchp_resource_sort_and_combine(&(resources->p_mem_head)); rc |= shpchp_resource_sort_and_combine(&(resources->io_head)); rc |= shpchp_resource_sort_and_combine(&(resources->bus_head)); - return(rc); + return rc; } - -/* - * shpchp_destroy_resource_list - * - * Puts node back in the resource list pointed to by head +/** + * kfree_resource_list: release memory of all list members + * @res: resource list to free */ -void shpchp_destroy_resource_list (struct resource_lists * resources) +static inline void +kfree_resource_list(struct pci_resource **r) { struct pci_resource *res, *tres; - res = resources->io_head; - resources->io_head = NULL; - - while (res) { - tres = res; - res = res->next; - kfree(tres); - } - - res = resources->mem_head; - resources->mem_head = NULL; - - while (res) { - tres = res; - res = res->next; - kfree(tres); - } - - res = resources->p_mem_head; - resources->p_mem_head = NULL; - - while (res) { - tres = res; - res = res->next; - kfree(tres); - } - - res = resources->bus_head; - resources->bus_head = NULL; + res = *r; + *r = NULL; while (res) { tres = res; @@ -772,50 +784,26 @@ void shpchp_destroy_resource_list (struc } } - -/* - * shpchp_destroy_board_resources - * - * Puts node back in the resource list pointed to by head +/** + * shpchp_destroy_resource_list: put node back in the resource list + * @resources: list to put nodes back */ -void shpchp_destroy_board_resources (struct pci_func * func) +void shpchp_destroy_resource_list(struct resource_lists *resources) { - struct pci_resource *res, *tres; - - res = func->io_head; - func->io_head = NULL; - - while (res) { - tres = res; - res = res->next; - kfree(tres); - } - - res = func->mem_head; - func->mem_head = NULL; - - while (res) { - tres = res; - res = res->next; - kfree(tres); - } - - res = func->p_mem_head; - func->p_mem_head = NULL; - - while (res) { - tres = res; - res = res->next; - kfree(tres); - } - - res = func->bus_head; - func->bus_head = NULL; - - while (res) { - tres = res; - res = res->next; - kfree(tres); - } + kfree_resource_list(&(resources->io_head)); + kfree_resource_list(&(resources->mem_head)); + kfree_resource_list(&(resources->p_mem_head)); + kfree_resource_list(&(resources->bus_head)); } +/** + * shpchp_destroy_board_resources: put node back in the resource list + * @resources: list to put nodes back + */ +void shpchp_destroy_board_resources(struct pci_func * func) +{ + kfree_resource_list(&(func->io_head)); + kfree_resource_list(&(func->mem_head)); + kfree_resource_list(&(func->p_mem_head)); + kfree_resource_list(&(func->bus_head)); +} --- linux-2.6.6/drivers/pci/pci.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/pci/pci.c 2004-05-10 01:19:17.986004768 -0700 @@ -247,6 +247,8 @@ pci_set_power_state(struct pci_dev *dev, int pm; u16 pmcsr; + might_sleep(); + /* bound the state we're entering */ if (state > 3) state = 3; @@ -640,7 +642,7 @@ pci_generic_prep_mwi(struct pci_dev *dev if (cacheline_size == pci_cache_line_size) return 0; - printk(KERN_WARNING "PCI: cache line size of %d is not supported " + printk(KERN_DEBUG "PCI: cache line size of %d is not supported " "by device %s\n", pci_cache_line_size << 2, pci_name(dev)); return -EINVAL; --- linux-2.6.6/drivers/pci/pci.ids 2004-03-10 20:41:29.000000000 -0800 +++ 25/drivers/pci/pci.ids 2004-05-10 01:19:04.083118328 -0700 @@ -7,7 +7,7 @@ # so if you have anything to contribute, please visit the home page or # send a diff -u against the most recent pci.ids to pci-ids@ucw.cz. # -# Daily snapshot on Wed 2004-01-14 11:00:17 +# Daily snapshot on Thu 2004-04-15 10:00:04 # # Vendors, devices and subsystems. Please keep sorted. @@ -24,7 +24,23 @@ # Real TJN ID is e159, but they got it wrong several times --mj 0059 Tiger Jet Network Inc. (Wrong ID) 0070 Hauppauge computer works Inc. + 4000 WinTV PVR-350 + 4001 WinTV PVR-250 (v1) + 4009 WinTV PVR-250 + 4801 WinTV PVR-250 MCE 0100 Ncipher Corp Ltd +# 018a is not LevelOne but there is a board misprogrammed +018a LevelOne + 0106 FPC-0106TX misprogrammed [RTL81xx] +# 021b is not Compaq but there is a board misprogrammed +021b Compaq Computer Corporation + 8139 HNE-300 (RealTek RTL8139c) [iPaq Networking] +# http://www.davicom.com.tw/ +0291 Davicom Semiconductor, Inc. + 8212 DM9102A(DM9102AE, SM9102AF) Ethernet 100/10 MBit(Rev 40) +# SpeedStream is Efficient Networks, Inc, a Siemens Company +02ac SpeedStream + 1012 1012 PCMCIA 10/100 Ethernet Card [RTL81xx] 0675 Dynalink 1700 IS64PH ISDN Adapter 1702 IS64PH ISDN Adapter @@ -36,8 +52,23 @@ 0e11 Compaq Computer Corporation 0001 PCI to EISA Bridge 0002 PCI to ISA Bridge + 0046 Smart Array 64xx + 0e11 409a Smart Array 641 + 0e11 409b Smart Array 642 + 0e11 409c Smart Array 6400 + 0e11 409d Smart Array 6400 EM 0049 NC7132 Gigabit Upgrade Module 004a NC6136 Gigabit Server Adapter + 007c NC7770 1000BaseTX + 007d NC6770 1000BaseTX + 0085 NC7780 1000BaseTX + 00bb NC7760 + 00ca NC7771 + 00cb NC7781 + 00cf NC7772 + 00d0 NC7782 + 00d1 NC7783 + 00e3 NC7761 0508 Netelligent 4/16 Token Ring 1000 Triflex/Pentium Bridge, Model 1000 2000 Triflex/Pentium Bridge, Model 2000 @@ -45,6 +76,25 @@ 3033 QVision 1280/p 3034 QVision 1280/p 4000 4000 [Triflex] + 4030 SMART-2/P + 4031 SMART-2SL + 4032 Smart Array 3200 + 4033 Smart Array 3100ES + 4034 Smart Array 221 + 4040 Integrated Array + 4048 Compaq Raid LC2 + 4050 Smart Array 4200 + 4051 Smart Array 4250ES + 4058 Smart Array 431 + 4070 Smart Array 5300 + 4080 Smart Array 5i + 4082 Smart Array 532 + 4083 Smart Array 5312 + 4091 Smart Array 6i + 409a Smart Array 641 + 409b Smart Array 642 + 409c Smart Array 6400 + 409d Smart Array 6400 EM 6010 HotPlug PCI Bridge 6010 7020 USB Controller a0ec Fibre Channel Host Controller @@ -54,7 +104,7 @@ 8086 002a PCI Hotplug Controller A 8086 002b PCI Hotplug Controller B a0f8 ZFMicro Chipset USB - a0fc Fibre Channel Host Controller + a0fc FibreChannel HBA Tachyon ae10 Smart-2/P RAID Controller 0e11 4030 Smart-2/P Array Controller 0e11 4031 Smart-2SL Array Controller @@ -64,21 +114,21 @@ ae2a MPC ae2b MIS-E ae31 System Management Controller - ae32 Netelligent 10/100 + ae32 Netelligent 10/100 TX PCI UTP ae33 Triflex Dual EIDE Controller - ae34 Netelligent 10 + ae34 Netelligent 10 T PCI UTP ae35 Integrated NetFlex-3/P - ae40 Netelligent 10/100 Dual - ae43 ProLiant Integrated Netelligent 10/100 + ae40 Netelligent Dual 10/100 TX PCI UTP + ae43 Netelligent Integrated 10/100 TX UTP ae69 CETUS-L ae6c Northstar ae6d NorthStar CPU to PCI Bridge - b011 Integrated Netelligent 10/100 - b012 Netelligent 10 T/2 + b011 Netelligent 10/100 TX Embedded UTP + b012 Netelligent 10 T/2 PCI UTP/Coax b01e NC3120 Fast Ethernet NIC b01f NC3122 Fast Ethernet NIC b02f NC1120 Ethernet NIC - b030 Netelligent WS 5100 + b030 Netelligent 10/100 TX UTP b04a 10/100 TX PCI Intel WOL UTP Controller b060 Smart Array 5300 Controller b0c6 NC3161 Fast Ethernet NIC @@ -96,6 +146,9 @@ b163 NC3134 Fast Ethernet NIC b164 NC3165 Fast Ethernet Upgrade Module b178 Smart Array 5i/532 + 0e11 4080 Smart Array 5i + 0e11 4082 Smart Array 532 + 0e11 4083 Smart Array 5312 b1a4 NC7131 Gigabit Server Adapter f130 NetFlex-3/P ThunderLAN 1.0 f150 NetFlex-3/P ThunderLAN 2.3 @@ -128,32 +181,59 @@ 0020 53c1010 Ultra3 SCSI Adapter 1de1 1020 DC-390U3W 0021 53c1010 66MHz Ultra3 SCSI Adapter + 124b 1070 PMC-USCSI3 4c53 1080 CT8 mainboard 4c53 1300 P017 mezzanine (32-bit PMC) 4c53 1310 P017 mezzanine (64-bit PMC) 0030 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI + 1028 0123 PowerEdge 2600 + 1028 014a PowerEdge 1750 1028 1010 LSI U320 SCSI Controller - 0040 53c1035 + 0031 53c1030ZC PCI-X Fusion-MPT Dual Ultra320 SCSI + 0032 53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI + 0033 1030ZC_53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI + 0040 53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI + 1000 0033 MegaRAID SCSI 320-2XR + 1000 0066 MegaRAID SCSI 320-2XRWS + 0041 53C1035ZC PCI-X Fusion-MPT Dual Ultra320 SCSI 008f 53c875J 1092 8000 FirePort 40 SCSI Controller 1092 8760 FirePort 40 Dual SCSI Host Adapter - 0621 FC909 - 0622 FC929 + 0407 MegaRAID + 1000 0530 MegaRAID 530 SCSI 320-0X RAID Controller + 1000 0531 MegaRAID 531 SCSI 320-4X RAID Controller + 1000 0532 MegaRAID 532 SCSI 320-2X RAID Controller + 1028 0533 PowerEgde Expandable RAID Controller 4/QC + 8086 0532 Storage RAID Controller SRCU42X + 0621 FC909 Fibre Channel Adapter + 0622 FC929 Fibre Channel Adapter + 1000 1020 44929 O Dual Fibre Channel card 0623 FC929 LAN - 0624 FC919 + 0624 FC919 Fibre Channel Adapter 0625 FC919 LAN - 0626 FC929X + 0626 FC929X Fibre Channel Adapter + 1000 1010 7202-XP-LC Dual Fibre Channel card 0627 FC929X LAN - 0628 FC919X + 0628 FC919X Fibre Channel Adapter 0629 FC919X LAN 0701 83C885 NT50 DigitalScape Fast Ethernet 0702 Yellowfin G-NIC gigabit ethernet 1318 0000 PEI100X + 0804 SA2010 + 0805 SA2010ZC + 0806 SA2020 + 0807 SA2020ZC 0901 61C102 1000 63C815 - 1960 PowerEdge Expandable RAID Controller 4 - 1028 0518 PowerEdge Expandable RAID Controller 4/DC - 1028 0520 PowerEdge Expandable RAID Controller 4/SC + 1960 MegaRAID + 1000 0518 MegaRAID 518 SCSI 320-2 Controller + 1000 0520 MegaRAID 520 SCSI 320-1 Controller + 1000 0522 MegaRAID 522 i4133 RAID Controller + 1000 0523 MegaRAID SATA 150-6 RAID Controller + 1000 4523 MegaRAID SATA 150-4 RAID Controller + 1000 a520 MegaRAID ZCR SCSI 320-0 Controller + 1028 0518 MegaRAID 518 DELL PERC 4/DC RAID Controller + 1028 0520 MegaRAID 520 DELL PERC 4/SC RAID Controller 1028 0531 PowerEdge Expandable RAID Controller 4/QC 1001 Kolter Electronic 0010 PCI 1616 Measurement card with 32 digital I/O lines @@ -167,16 +247,57 @@ 9100 INI-9100/9100W SCSI Host 1002 ATI Technologies Inc 4136 Radeon IGP 320 M - 4144 Radeon R300 AD [Radeon 9500 Pro] - 4145 Radeon R300 AE [Radeon 9500 Pro] - 4146 Radeon R300 AF [Radeon 9500 Pro] - 4147 Radeon R300 AG [FireGL Z1/X1] + 4144 R300 AD [Radeon 9500 Pro] +# New PCI ID provided by ATI developer relations (correction to above) + 4145 R300 AE [Radeon 9700 Pro] +# New PCI ID provided by ATI developer relations (oops, correction to above) + 4146 R300 AF [Radeon 9700 Pro] + 4147 R300 AG [FireGL Z1/X1] + 4148 R350 AH [Radeon 9800] + 4149 R350 AI [Radeon 9800] + 414b R350 AK [Fire GL ??] +# New PCI ID provided by ATI developer relations + 4150 RV350 AP [Radeon 9600] + 1458 4024 Giga-Byte GV-R96128D Primary + 148c 2064 PowerColor R96A-C3N + 148c 2066 PowerColor R96A-C3N + 174b 7c19 Sapphire Atlantis Radeon 9600 Pro + 174b 7c29 GC-R9600PRO Primary [Sapphire] + 18bc 0101 GC-R9600PRO Primary +# New PCI ID provided by ATI developer relations + 4151 RV350 AQ [Radeon 9600] +# New PCI ID provided by ATI developer relations + 4152 RV350 AR [Radeon 9600] + 4154 RV350 AT [Fire GL T2] + 4155 RV350 AU [Fire GL T2] + 4156 RV350 AV [Fire GL T2] + 4157 RV350 AW [Fire GL T2] 4158 68800AX [Mach32] - 4164 Radeon R300 Secondary (DVI) output - 4242 Radeon R200 BB [Radeon All in Wonder 8500DV] +# The PCI ID is unrelated to any DVI output. + 4164 R300 AD [Radeon 9500 Pro] (Secondary) +# New PCI ID info provided by ATI developer relations + 4165 R300 AE [Radeon 9700 Pro] (Secondary) +# New PCI ID info provided by ATI developer relations + 4166 R300 AF [Radeon 9700 Pro] (Secondary) +# New PCI ID provided by ATI developer relations + 4168 Radeon R350 [Radeon 9800] (Secondary) +# New PCI ID provided by ATI developer relations (correction to above) + 4170 RV350 AP [Radeon 9600] (Secondary) + 1458 4025 Giga-Byte GV-R96128D Secondary + 148c 2067 PowerColor R96A-C3N (Secondary) + 174b 7c28 GC-R9600PRO Secondary [Sapphire] + 18bc 0100 GC-R9600PRO Secondary +# New PCI ID provided by ATI developer relations (correction to above) + 4171 RV350 AQ [Radeon 9600] (Secondary) +# New PCI ID provided by ATI developer relations (correction to above) + 4172 RV350 AR [Radeon 9600] (Secondary) + 4242 R200 BB [Radeon All in Wonder 8500DV] 1002 02aa Radeon 8500 AIW DV Edition 4336 Radeon Mobility U1 4337 Radeon IGP 340M + 4341 IXP150 AC'97 Audio Controller +# Radeon 9100 IGP integrated + 4353 ATI SMBus 4354 215CT [Mach64 CT] 4358 210888CX [Mach64 CX] 4554 210888ET [Mach64 ET] @@ -246,21 +367,22 @@ 475a 3D Rage IIC AGP 1002 0087 Rage 3D IIC 1002 475a Rage IIC AGP - 4964 Radeon R250 Id [Radeon 9000] - 4965 Radeon R250 Ie [Radeon 9000] - 4966 Radeon R250 If [Radeon 9000] - 10f1 0002 R250 If [Tachyon G9000 PRO] - 148c 2039 R250 If [Radeon 9000 Pro "Evil Commando"] - 1509 9a00 R250 If [Radeon 9000 "AT009"] -# New subdevice - 3D Prophet 9000 PCI by Hercules. AGP version probably would have same ID, so not specified. - 1681 0040 R250 If [3D prophet 9000] - 174b 7176 R250 If [Sapphire Radeon 9000 Pro] - 174b 7192 R250 If [Radeon 9000 "Atlantis"] - 17af 2005 R250 If [Excalibur Radeon 9000 Pro] - 17af 2006 R250 If [Excalibur Radeon 9000] - 4967 Radeon R250 Ig [Radeon 9000] - 496e Radeon R250 [Radeon 9000] (Secondary) + 4964 Radeon RV250 Id [Radeon 9000] + 4965 Radeon RV250 Ie [Radeon 9000] + 4966 Radeon RV250 If [Radeon 9000] + 10f1 0002 RV250 If [Tachyon G9000 PRO] + 148c 2039 RV250 If [Radeon 9000 Pro "Evil Commando"] + 1509 9a00 RV250 If [Radeon 9000 "AT009"] +# New subdevice - 3D Prophet 9000 PCI by Hercules. AGP version probably would have same ID, so not specified. + 1681 0040 RV250 If [3D prophet 9000] + 174b 7176 RV250 If [Sapphire Radeon 9000 Pro] + 174b 7192 RV250 If [Radeon 9000 "Atlantis"] + 17af 2005 RV250 If [Excalibur Radeon 9000 Pro] + 17af 2006 RV250 If [Excalibur Radeon 9000] + 4967 Radeon RV250 Ig [Radeon 9000] + 496e Radeon RV250 [Radeon 9000] (Secondary) 4c42 3D Rage LT Pro AGP-133 + 0e11 b0e7 Rage LT Pro (Compaq Presario 5240) 0e11 b0e8 Rage 3D LT Pro 0e11 b10e 3D Rage LT Pro (Compaq Armada 1750) 1002 0040 Rage LT Pro AGP 2X @@ -294,10 +416,11 @@ 4c57 Radeon Mobility M7 LW [Radeon Mobility 7500] 1014 0517 ThinkPad T30 1028 00e6 Radeon Mobility M7 LW (Dell Inspiron 8100) + 1028 012a Latitude C640 144d c006 Radeon Mobility M7 LW in vpr Matrix 170B4 4c58 Radeon RV200 LX [Mobility FireGL 7800 M7] 4c59 Radeon Mobility M6 LY - 1014 0235 ThinkPad A30p (2653-64G) + 1014 0235 ThinkPad A30/A30p (2652/2653) 1014 0239 ThinkPad X22/X23/X24 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP 4c5a Radeon Mobility M6 LZ @@ -312,15 +435,29 @@ 4e44 Radeon R300 ND [Radeon 9700 Pro] 4e45 Radeon R300 NE [Radeon 9500 Pro] 1002 0002 Radeon R300 NE [Radeon 9500 Pro] - 4e46 Radeon R300 NF [Radeon 9700] +# New PCI ID provided by ATI developer relations (correction to above) + 4e46 RV350 NF [Radeon 9600] 4e47 Radeon R300 NG [FireGL X1] 4e48 Radeon R350 [Radeon 9800] +# New PCI ID provided by ATI developer relations + 4e49 Radeon R350 [Radeon 9800] + 4e4a RV350 NJ [Radeon 9800 XT] + 4e4b R350 NK [Fire GL X2] +# New PCI ID provided by ATI developer relations + 4e50 RV350 [Mobility Radeon 9600 M10] +# New PCI ID provided by ATI developer relations + 4e52 RV350 [Mobility Radeon 9600 M10] + 4e54 M10 NT [FireGL Mobility T2] 4e64 Radeon R300 [Radeon 9700 Pro] (Secondary) 4e65 Radeon R300 [Radeon 9500 Pro] (Secondary) 1002 0003 Radeon R300 NE [Radeon 9500 Pro] - 4e66 Radeon R300 [Radeon 9700] (Secondary) +# New PCI ID provided by ATI developer relations (correction to above) + 4e66 RV350 NF [Radeon 9600] (Secondary) 4e67 Radeon R300 [FireGL X1] (Secondary) 4e68 Radeon R350 [Radeon 9800] (Secondary) +# New PCI ID provided by ATI developer relations + 4e69 Radeon R350 [Radeon 9800] (Secondary) + 4e6a RV350 NJ [Radeon 9800 XT] (Secondary) 5041 Rage 128 PA/PRO 5042 Rage 128 PB/PRO AGP 2x 5043 Rage 128 PC/PRO AGP 4x @@ -390,6 +527,8 @@ 514d Radeon R200 QM [Radeon 9100] 514e Radeon R200 QN [Radeon 8500LE] 514f Radeon R200 QO [Radeon 8500LE] + 5154 R200 QT [Radeon 8500] + 5155 R200 QU [Radeon 9100] 5157 Radeon RV200 QW [Radeon 7500] 1002 013a Radeon 7500 1458 4000 RV200 QW [RADEON 7500 PRO MAYA AR] @@ -469,7 +608,20 @@ 1002 5654 Mach64VT Reference 5655 264VT3 [Mach64 VT3] 5656 264VT4 [Mach64 VT4] - 5961 Radeon RV280 [Radeon 9200] + 5941 RV280 [Radeon 9200] (Secondary) +# http://www.hightech.com.hk/html/9200.htm + 17af 200d Excalibur Radeon 9200 + 18bc 0050 GeXcube GC-R9200-C3 (Secondary) + 5960 RV280 [Radeon 9200 PRO] + 5961 RV280 [Radeon 9200] +# http://www.hightech.com.hk/html/9200.htm + 17af 200c Excalibur Radeon 9200 + 18bc 0051 GeXcube GC-R9200-C3 + 5964 RV280 [Radeon 9200 SE] + 148c 2073 CN-AG92E + 5c61 RV250 5c61 [Radeon Mobility 9200 M9+] + 5c63 RV250 5c63 [Radeon Mobility 9200 M9+] + 5d44 RV280 [Radeon 9200 SE] (Secondary) 700f PCI Bridge [IGP 320M] 7010 PCI Bridge [IGP 340M] cab0 AGP Bridge [IGP 320M] @@ -610,6 +762,7 @@ 1186 1100 DFE-500TX Fast Ethernet 1186 1101 DFE-500TX Fast Ethernet 1186 1102 DFE-500TX Fast Ethernet + 1186 1112 DFE-570TX Quad Fast Ethernet 1259 2800 AT-2800Tx Fast Ethernet 1266 0004 Eagle Fast EtherMAX 12af 0019 NetFlyer Cardbus Fast Ethernet @@ -621,7 +774,7 @@ 1395 0001 10/100 Ethernet CardBus PC Card 13d1 ab01 EtherFast 10/100 Cardbus (PCMPC200) 8086 0001 EtherExpress PRO/100 Mobile CardBus 32 - 001a Farallon PN9000SX + 001a Farallon PN9000SX Gigabit Ethernet 0021 DECchip 21052 0022 DECchip 21150 0023 DECchip 21150 @@ -639,7 +792,8 @@ 12d9 000a IP Telephony card 4c53 1050 CT7 mainboard 4c53 1051 CE7 mainboard - 9005 0365 Adaptec 5400S + 9005 0364 5400S (Mustang) + 9005 0365 5400S (Mustang) 9005 1364 Dell PowerEdge RAID Controller 2 9005 1365 Dell PowerEdge RAID Controller 2 e4bf 1000 CC8-1-BLUES @@ -818,8 +972,13 @@ 101e American Megatrends Inc. 1960 MegaRAID 101e 0471 MegaRAID 471 Enterprise 1600 RAID Controller - 101e 0475 MegaRAID 475 Express 500 RAID Controller + 101e 0475 MegaRAID 475 Express 500/500LC RAID Controller + 101e 0477 MegaRAID 477 Elite 3100 RAID Controller 101e 0493 MegaRAID 493 Elite 1600 RAID Controller + 101e 0494 MegaRAID 494 Elite 1650 RAID Controller + 101e 0503 MegaRAID 503 Enterprise 1650 RAID Controller + 101e 0511 MegaRAID 511 i4 IDE RAID Controller + 101e 0522 MegaRAID 522 i4133 RAID Controller 1028 0471 PowerEdge RAID Controller 3/QC 1028 0475 PowerEdge RAID Controller 3/SC 1028 0493 PowerEdge RAID Controller 3/DC @@ -843,6 +1002,7 @@ 1103 K8 NorthBridge 2000 79c970 [PCnet32 LANCE] 1014 2000 NetFinity 10/100 Fast Ethernet + 1022 2000 PCnet - Fast 79C971 103c 104c Ethernet with LAN remote power Adapter 103c 1064 Ethernet with LAN remote power Adapter 103c 1065 Ethernet with LAN remote power Adapter @@ -913,6 +1073,7 @@ 0194 82C194 2000 4DWave DX 2001 4DWave NX + 2100 CyberBlade XP4m32 8400 CyberBlade/i7 1023 8400 CyberBlade i7 AGP 8420 CyberBlade/i7d @@ -1029,7 +1190,6 @@ 1028 0003 PowerEdge Expandable RAID Controller 3/Si 0004 PowerEdge Expandable RAID Controller 3/Si 1028 00d0 PowerEdge Expandable RAID Controller 3/Si - 0005 PowerEdge Expandable RAID Controller 3/Di 0006 PowerEdge Expandable RAID Controller 3/Di 0007 Remote Access Controller:DRAC III 0008 Remote Access Controller @@ -1040,12 +1200,26 @@ 1028 0121 PowerEdge Expandable RAID Controller 3/Di 000c Remote Access Controller:ERA or ERA/O 000d BMC/SMIC device - 000e PowerEdge Expandable RAID Controller - 000f PowerEdge Expandable RAID Controller 4/Di + 000e PowerEdge Expandable RAID controller 4 + 1028 0123 PowerEdge Expandable RAID Controller 4/Di + 000f PowerEdge Expandable RAID controller 4 + 1028 013b MegaRAID DELL PERC 4/Di RAID On Motherboard + 1028 014a PowerEdge Expandable RAID Controller 4/Di + 1028 014c MegaRAID DELL PERC 4/Di RAID On Motherboard + 1028 014d MegaRAID DELL PERC 4/Di RAID On Motherboard 1029 Siemens Nixdorf IS 102a LSI Logic 0000 HYDRA 0010 ASPEN + 001f AHA-2940U2/U2W /7890/7891 SCSI Controllers + 9005 000f 2940U2W SCSI Controller + 9005 0106 2940U2W SCSI Controller + 9005 a180 2940U2W SCSI Controller + 00c5 AIC-7899 U160/m SCSI Controller + 1028 00c5 PowerEdge 2550/2650/4600 + 00cf AIC-7899P U160/m + 1028 0106 PowerEdge 4600 + 1028 0121 PowerEdge 2650 102b Matrox Graphics, Inc. # DJ: I've a suspicion that 0010 is a duplicate of 0d10. 0010 MGA-I [Impression?] @@ -1171,6 +1345,7 @@ 102b 0f83 Millennium G550 102b 0f84 Millennium G550 Dual Head DDR 32Mb 102b 1e41 Millennium G550 + 2537 MGA G650 AGP 4536 VIA Framegrabber 6573 Shark 10/100 Multiport SwitchNIC 102c Chips and Technologies @@ -1206,6 +1381,11 @@ 0009 r4x00 0020 ATM Meteor 155 102f 00f8 ATM Meteor 155 + 0105 TC86C001 [goku-s] IDE + 0106 TC86C001 [goku-s] USB 1.1 Host + 0107 TC86C001 [goku-s] USB Device Controller + 0108 TC86C001 [goku-s] I2C/SIO/GPIO Controller + 0180 TX4927 1030 TMC Research 1031 Miro Computer Products AG 5601 DC20 ASIC @@ -1235,6 +1415,7 @@ 1179 0001 USB 12ee 7000 Root Hub 1799 0001 Root Hub + 807d 0035 PCI-USB2 (OHCI subsystem) 003b PCI to C-bus Bridge 003e NAPCCARD Cardbus Controller 0046 PowerVR PCX2 [midas] @@ -1252,14 +1433,21 @@ 0074 56k Voice Modem 1033 8014 RCV56ACF 56k Voice Modem 009b Vrc5476 + 00a5 VRC4173 00a6 VRC5477 AC97 00cd IEEE 1394 [OrangeLink] Host Controller 12ee 8011 Root hub + 00ce IEEE 1394 Host Controller 00df Vr4131 00e0 USB 2.0 + 0ee4 3383 Sitecom IEEE 1394 / USB2.0 Combo Card 12ee 7001 Root hub 1799 0002 Root Hub + 807d 1043 PCI-USB2 (EHCI subsystem) + 00e7 IEEE 1394 Host Controller + 00f2 uPD72874 IEEE1394 OHCI 1.1 3-port PHY-Link Ctrlr 00f3 uPD6113x Multimedia Decoder/Processor [EMMA2] + 010c VR7701 1034 Framatome Connectors USA Inc. 1035 Comp. & Comm. Research Lab 1036 Future Domain Corp. @@ -1267,27 +1455,27 @@ 1037 Hitachi Micro Systems 1038 AMP, Inc 1039 Silicon Integrated Systems [SiS] -# This is what all my tests report. I don't know if this is equivalent to "5591/5592 AGP". - 0001 SiS 530 Virtual PCI-to-PCI bridge (AGP) + 0001 Virtual PCI-to-PCI bridge (AGP) 0002 SG86C202 0006 85C501/2/3 - 0008 85C503/5513 + 0008 SiS85C503/5513 (LPC Bridge) 0009 ACPI 0018 SiS85C503/5513 (LPC Bridge) 0200 5597/5598/6326 VGA 1039 0000 SiS5597 SVGA (Shared RAM) 0204 82C204 0205 SG86C205 - 0300 SiS300/305 PCI/AGP VGA Display Adapter + 0300 300/305 PCI/AGP VGA Display Adapter 107d 2720 Leadtek WinFast VR300 - 0310 SiS315H PCI/AGP VGA Display Adapter - 0315 SiS315 PCI/AGP VGA Display Adapter - 0325 SiS315PRO PCI/AGP VGA Display Adapter - 0330 SiS330 [Xabre] PCI/AGP VGA Display Adapter + 0310 315H PCI/AGP VGA Display Adapter + 0315 315 PCI/AGP VGA Display Adapter + 0325 315PRO PCI/AGP VGA Display Adapter + 0330 330 [Xabre] PCI/AGP VGA Display Adapter 0406 85C501/2 0496 85C496 0530 530 Host 0540 540 Host + 0550 550 Host 0597 5513C 0601 85C601 0620 620 Host @@ -1297,24 +1485,32 @@ 0645 SiS645 Host & Memory & AGP Controller 0646 SiS645DX Host & Memory & AGP Controller 0648 SiS 645xx - 0650 650 Host - 0651 SiS651 Host + 0650 650/M650 Host + 0651 651 Host + 0655 655 Host + 0660 660 Host + 0661 661FX/M661FX/M661MX Host 0730 730 Host 0733 733 Host 0735 735 Host 0740 740 Host + 0741 741/741GX/M741 Host 0745 745 Host 0746 746 Host - 0755 SiS 755 Host Bridge - 0900 SiS900 10/100 Ethernet + 0755 755 Host + 0760 760/M760 Host + 0900 SiS900 PCI Fast Ethernet 1039 0900 SiS900 10/100 Ethernet Adapter 1043 8035 CUSI-FX motherboard 0961 SiS961 [MuTIOL Media IO] 0962 SiS962 [MuTIOL Media IO] + 0963 SiS963 [MuTIOL Media IO] + 0964 SiS964 [MuTIOL Media IO] + 0965 SiS965 [MuTIOL Media IO] 3602 83C602 5107 5107 5300 SiS540 PCI Display Adapter - 5315 SiS550 AGP/VGA VGA Display Adapter + 5315 550 PCI/AGP VGA Display Adapter 5401 486 PCI Chipset 5511 5511/5512 5513 5513 [IDE] @@ -1332,12 +1528,12 @@ 6204 Video decoder & MPEG interface 6205 VGA Controller 6236 6236 3D-AGP - 6300 SiS630 GUI Accelerator+3D + 6300 630/730 PCI/AGP VGA Display Adapter 1019 0970 P6STP-FL motherboard 1043 8035 CUSI-FX motherboard - 6306 SiS530 3D PCI/AGP + 6306 530/620 PCI/AGP VGA Display Adapter 1039 6306 SiS530,620 GUI Accelerator+3D - 6325 SiS650/651/M650/740 PCI/AGP VGA Display Adapter + 6325 65x/M650/740 PCI/AGP VGA Display Adapter 6326 86C326 5598/6326 1039 6326 SiS6326 GUI Accelerator 1092 0a50 SpeedStar A50 @@ -1345,14 +1541,16 @@ 1092 4910 SpeedStar A70 1092 4920 SpeedStar A70 1569 6326 SiS6326 GUI Accelerator + 6330 661FX/M661FX/M661MX/741/M741/760/M760 PCI/AGP 7001 USB 1.0 Controller 1039 7000 Onboard USB Controller 7002 USB 2.0 Controller 1509 7002 Onboard USB Controller 7007 FireWire Controller 7012 Sound Controller - 7013 Intel 537 [56k Winmodem] - 7016 10/100 Ethernet Adapter +# There are may be different modem codecs here (Intel537 compatible and incompatible) + 7013 AC'97 Modem Controller + 7016 SiS7016 PCI Fast Ethernet Adapter 1039 7016 SiS7016 10/100 Ethernet Adapter 7018 SiS PCI Audio Accelerator 1014 01b6 SiS PCI Audio Accelerator @@ -1410,6 +1608,7 @@ 103c 1226 Keystone SP2 103c 1227 Powerbar SP2 103c 1282 Everest SP2 + 1054 PCI Local Bus Adapter 1064 79C970 PCnet Ethernet Controller 108b Visualize FXe 10c1 NetServer Smart IRQ Router @@ -1422,6 +1621,7 @@ 1229 zx1 System Bus Adapter 122a zx1 I/O Controller 122e zx1 Local Bus Adapter + 127c sx1000 I/O Controller 1290 Auxiliary Diva Serial Port 2910 E2910A PCIBus Exerciser 2925 E2925A 32 Bit, 33 MHzPCI Exerciser & Analyzer @@ -1437,8 +1637,11 @@ 3020 Samurai_IDE 1043 Asustek Computer, Inc. 0675 ISDNLink P-IN100-ST-D + 4015 v7100 SDRAM [GeForce2 MX] 4021 v7100 Combo Deluxe [GeForce2 MX + TV tuner] 4057 v8200 GeForce 3 + 8043 v8240 PAL 128M [P4T] Motherboard + 807b v9280/TD [Geforce4 TI4200 8X With TV-Out and DVI] 1044 Distributed Processing Technology 1012 Domino RAID Engine a400 SmartCache/Raid I-IV Controller @@ -1523,9 +1726,9 @@ 021b STPC Consumer IIA Southbridge 0500 ST70137 [Unicorn] ADSL DMT Transceiver 0564 STPC Client Northbridge - 0981 DEC-Tulip compatible 10/100 Ethernet + 0981 21x4x DEC-Tulip compatible 10/100 Ethernet 1746 STG 1764X - 2774 DEC-Tulip compatible 10/100 Ethernet + 2774 21x4x DEC-Tulip compatible 10/100 Ethernet 3520 MPEG-II decoder card 55cc STPC Client Southbridge 104b BusLogic @@ -1577,24 +1780,33 @@ 8022 TSB43AB22 IEEE-1394a-2000 Controller (PHY/Link) 8023 TSB43AB22/A IEEE-1394a-2000 Controller (PHY/Link) 8024 TSB43AB23 IEEE-1394a-2000 Controller (PHY/Link) + 8025 TSB82AA2 IEEE-1394b Link Layer Controller 8026 TSB43AB21 IEEE-1394a-2000 Controller (PHY/Link) 8027 PCI4451 IEEE-1394 Controller 1028 00e6 PCI4451 IEEE-1394 Controller (Dell Inspiron 8100) 8029 PCI4510 IEEE-1394 Controller + 1071 8160 MIM2900 8400 ACX 100 22Mbps Wireless Interface + 00fc 16ec U.S. Robotics 22 Mbps Wireless PC Card (model 2210) + 00fd 16ec U.S. Robotics 22Mbps Wireless PCI Adapter (model 2216) + 1186 3b01 DWL-520+ 22Mbps PCI Wireless Adapter 8401 ACX 100 22Mbps Wireless Interface # OK, this info is almost useless as is, but at least it's known that it's a wireless card. More info requested from reporter (whi 9000 Wireless Interface (of unknown type) + 9066 ACX 111 54Mbps Wireless Interface a001 TDC1570 a100 TDC1561 a102 TNETA1575 HyperSAR Plus w/PCI Host i/f & UTOPIA i/f - a106 TMS320C6205 + a106 TMS320C6205 Fixed Point DSP + 175c 5000 ASI50xx Audio Adapter + 175c 8700 ASI87xx Radio Tuner card ac10 PCI1050 ac11 PCI1053 ac12 PCI1130 ac13 PCI1031 ac15 PCI1131 ac16 PCI1250 + 1014 0092 ThinkPad 600 ac17 PCI1220 ac18 PCI1260 ac19 PCI1221 @@ -1603,6 +1815,7 @@ 0e11 b113 Armada M700 ac1c PCI1225 0e11 b121 Armada E500 + 1028 0088 Dell Computer Corporation Latitude CPi A400XT ac1d PCI1251A ac1e PCI1211 ac1f PCI1251B @@ -1617,18 +1830,27 @@ ac42 PCI4451 PC card Cardbus Controller 1028 00e6 PCI4451 PC card CardBus Controller (Dell Inspiron 8100) ac44 PCI4510 PC card Cardbus Controller + 1071 8160 MIM2000 + ac46 PCI4520 PC card Cardbus Controller ac50 PCI1410 PC card Cardbus Controller ac51 PCI1420 1014 023b ThinkPad T23 (2647-4MG) 1028 00b1 Latitude C600 + 1028 012a Latitude C640 10cf 1095 Lifebook C6155 e4bf 1000 CP2-2-HIPHOP ac52 PCI1451 PC card Cardbus Controller ac53 PCI1421 PC card Cardbus Controller - ac55 PCI1250 PC card Cardbus Controller - 1014 0512 ThinkPad T30 + ac55 PCI1520 PC card Cardbus Controller + 1014 0512 ThinkPad T30/T40 ac56 PCI1510 PC card Cardbus Controller ac60 PCI2040 PCI to DSP Bridge Controller + 175c 5100 ASI51xx Audio Adapter + 175c 6100 ASI61xx Audio Adapter + 175c 6200 ASI62xx Audio Adapter + ac8d PCI 7620 + ac8e PCI7420 CardBus Controller + ac8f PCI7420 Flash Media Controller fe00 FireWire Host Controller fe03 12C01A FireWire Host Controller 104d Sony Corporation @@ -1674,7 +1896,20 @@ 0006 MPC8245 [Unity] 0100 MC145575 [HFC-PCI] 0431 KTI829c 100VG - 1801 Audio I/O Controller (MIDI) + 1801 DSP56301 Digital Signal Processor + 14fb 0101 Transas Radar Imitator Board [RIM] + 14fb 0102 Transas Radar Imitator Board [RIM-2] + 14fb 0202 Transas Radar Integrator Board [RIB-2] + 14fb 0611 1 channel CAN bus Controller [CanPci-1] + 14fb 0612 2 channels CAN bus Controller [CanPci-2] + 14fb 0613 3 channels CAN bus Controller [CanPci-3] + 14fb 0614 4 channels CAN bus Controller [CanPci-4] + 14fb 0621 1 channel CAN bus Controller [CanPci2-1] + 14fb 0622 2 channels CAN bus Controller [CanPci2-2] + 14fb 0810 Transas VTS Radar Integrator Board [RIB-4] + 175c 4200 ASI4215 Audio Adapter + 175c 4300 ASI43xx Audio Adapter + 175c 4400 ASI4401 Audio Adapter ecc0 0030 Layla 18c0 MPC8265A/MPC8266 4801 Raven @@ -1710,6 +1945,10 @@ 105a 4d39 Fasttrak66 1275 20275 3318 PDC20318 (SATA150 TX4) + 3319 PDC20319 (SATA150 TX4) + 3373 PDC20378 (SATA150 TX) + 1462 702e K8T NEO FIS2R motherboard + 3375 PDC20375 (SATA150 TX2plus) 3376 PDC20376 1043 809e A7V8X motherboard 4d30 20267 @@ -1727,11 +1966,15 @@ 105a 4d68 Ultra133TX2 5275 PDC20276 IDE 105a 0275 SuperTrak SX6000 IDE + 105a 1275 MBFastTrak133 Lite (tm) Controller (RAID mode) + 1458 b001 MBUltra 133 5300 DC5300 6268 20268R 6269 PDC20271 105a 6269 FastTrak TX2/TX2000 6621 PDC20621 [SX4000] 4 Channel IDE RAID Controller + 6622 PDC20621 [SATA150 SX4] 4 Channel IDE RAID Controller + 6626 PDC20618 Ultra 618 6629 PDC20619 FastTrak TX4000 RAID 7275 PDC20277 105b Foxconn International, Inc. @@ -1812,14 +2055,21 @@ 0005 National PC87550 System Controller 8002 PT86C523 [Vesuvius v3] PCI-ISA Bridge Slave 1067 Mitsubishi Electric + 0301 AccelGraphics AccelECLIPSE + 0304 AccelGALAXY A2100 [OEM Evans & Sutherland] + 0308 Tornado 3000 [OEM Evans & Sutherland] 1002 VG500 [VolumePro Volume Rendering Accelerator] 1068 Diversified Technology 1069 Mylex Corporation 0001 DAC960P 0002 DAC960PD - 0010 DAC960PX + 0010 DAC960PG + 0020 DAC960LA 0050 AcceleRAID 352/170/160 support Device b166 Gemstone chipset SCSI controller + 1014 0242 iSeries 2872 DASD IOA + 1014 0266 Dual Channel PCI-X U320 SCSI Adapter + 1014 0278 Dual Channel PCI-X U320 SCSI RAID Adapter ba55 eXtremeRAID 1100 support Device ba56 eXtremeRAID 2000/3000 support Device 106a Aten Research Inc @@ -1853,6 +2103,22 @@ 0032 UniNorth 2 GMAC (Sun GEM) 0033 UniNorth 2 ATA/100 0034 UniNorth 2 AGP + 0035 UniNorth 2 PCI + 0036 UniNorth 2 Internal PCI + 003b UniNorth/Intrepid ATA/100 + 003e KeyLargo/Intrepid Mac I/O + 003f KeyLargo/Intrepid USB + 0040 K2 KeyLargo USB + 0041 K2 KeyLargo Mac/IO + 0042 K2 FireWire + 0043 K2 ATA/100 + 0045 K2 HT-PCI Bridge + 0046 K2 HT-PCI Bridge + 0047 K2 HT-PCI Bridge + 0048 K2 HT-PCI Bridge + 0049 K2 HT-PCI Bridge + 004b U3 AGP + 004c K2 GMAC (Sun GEM) 1645 Tigon3 Gigabit Ethernet NIC (BCM5701) 106c Hyundai Electronics America 8801 Dual Pentium ISA/PCI Motherboard @@ -1865,6 +2131,7 @@ 106f City Gate Development Ltd 1070 Daewoo Telecom Ltd 1071 Mitac + 8160 Mitac 8060B Mobile Platform 1072 GIT Co Ltd 1073 Yamaha Corporation 0001 3D GUI Accelerator @@ -1905,13 +2172,13 @@ 101e 8471 QLA12160 on AMI MegaRAID 101e 8493 QLA12160 on AMI MegaRAID 1240 ISP1240 SCSI Host Adapter - 1280 ISP1280 + 1280 ISP1280 SCSI Host Adapter 2020 ISP2020A Fast!SCSI Basic Adapter 2100 QLA2100 64-bit Fibre Channel Adapter 1077 0001 QLA2100 64-bit Fibre Channel Adapter - 2200 QLA2200 + 2200 QLA2200 64-bit Fibre Channel Adapter 1077 0002 QLA2200 - 2300 QLA2300 64-bit FC-AL Adapter + 2300 QLA2300 64-bit Fibre Channel Adapter 2312 QLA2312 Fibre Channel Adapter 1078 Cyrix Corporation 0000 5510 [Grappa] @@ -2008,6 +2275,7 @@ 8001 Schizo PCI Bus Module a000 Ultra IIi a001 Ultra IIe + a801 Tomatillo PCI Bus Module 108f Systemsoft 1090 Encore Computer Corporation 1091 Intergraph Corporation @@ -2063,7 +2331,7 @@ c801 PCI-GPIB c831 PCI-GPIB bridge 1094 First International Computers [FIC] -1095 CMD Technology Inc +1095 Silicon Image, Inc. (formerly CMD Technology Inc) 0240 Adaptec AAR-1210SA SATA HostRAID Controller 0640 PCI0640 0643 PCI0643 @@ -2078,8 +2346,12 @@ 0670 USB0670 1095 0670 USB0670 0673 USB0673 - 0680 PCI0680 - 3112 Silicon Image SiI 3112 SATARaid Controller + 0680 PCI0680 Ultra ATA-133 Host Controller + 1095 3680 Winic W-680 (Silicon Image 680 based) + 3112 Silicon Image Serial ATARaid Controller [ CMD/Sil 3112/3112A ] + 1095 6112 Asus A7N8X + 3114 Silicon Image SiI 3114 SATARaid Controller + 3512 Silicon Image Serial ATARaid Controller [ CMD/Sil 3512 ] 1096 Alacron 1097 Appian Technology 1098 Quantum Designs (H.K.) Ltd @@ -2109,11 +2381,13 @@ 127a 0003 Bt878a Mediastream Controller PAL BG 127a 0048 Bt878/832 Mediastream Controller 144f 3000 MagicTView CPH060 - Video + 1461 0002 TV98 Series (TV/No FM/Remote) 1461 0004 AVerTV WDM Video Capture 14f1 0001 Bt878 Mediastream Controller NTSC 14f1 0002 Bt878 Mediastream Controller PAL BG 14f1 0003 Bt878a Mediastream Controller PAL BG 14f1 0048 Bt878/832 Mediastream Controller + 1822 0001 VisionPlus DVB card 1851 1850 FlyVideo'98 - Video 1851 1851 FlyVideo II 1852 1852 FlyVideo'98 - Video (with FM Tuner) @@ -2170,6 +2444,7 @@ 14f1 0002 Bt878 Video Capture (Audio Section) 14f1 0003 Bt878 Video Capture (Audio Section) 14f1 0048 Bt878 Video Capture (Audio Section) + 1822 0001 VisionPlus DVB Card bd11 1200 PCTV pro (TV + FM stereo receiver, audio section) 0879 Bt879 Audio Capture 127a 0044 Bt879 Video Capture (Audio Section) @@ -2228,8 +2503,8 @@ 0006 HPCEX 0007 RPCEX 0008 DiVO VIP - 0009 Alteon Gigabit Ethernet - 10a9 8002 Acenic Gigabit Ethernet + 0009 AceNIC Gigabit Ethernet + 10a9 8002 AceNIC Gigabit Ethernet 0010 AMP Video I/O 0011 GRIP 0012 SGH PSHAC GSN @@ -2278,12 +2553,18 @@ 1147 VScom 020 2 port parallel adaptor 2724 Thales PCSM Security Card 9030 PCI <-> IOBus Bridge Hot Swap + 10b5 2862 Alpermann+Velte PCL PCI LV (3V/5V): Timecode Reader Board + 10b5 2906 Alpermann+Velte PCI TS (3V/5V): Time Synchronisation Board + 10b5 2940 Alpermann+Velte PCL PCI D (3V/5V): Timecode Reader Board 15ed 1002 MCCS 8-port Serial Hot Swap 15ed 1003 MCCS 16-port Serial Hot Swap 9036 9036 9050 PCI <-> IOBus Bridge 10b5 2036 SatPak GPS + 10b5 2221 Alpermann+Velte PCL PCI LV: Timecode Reader Board 10b5 2273 SH-ARC SoHard ARCnet card + 10b5 2431 Alpermann+Velte PCL PCI D: Timecode Reader Board + 10b5 2905 Alpermann+Velte PCI TS: Time Synchronisation Board 10b5 9050 MP9050 1522 0001 RockForce 4 Port V.90 Data/Fax/Voice Modem 1522 0002 RockForce 2 Port V.90 Data/Fax/Voice Modem @@ -2295,6 +2576,10 @@ 15ed 1001 Macrolink MCCS 16-port Serial 15ed 1002 Macrolink MCCS 8-port Serial Hot Swap 15ed 1003 Macrolink MCCS 16-port Serial Hot Swap +# Sorry, there was a typo + 5654 2036 OpenSwitch 6 Telephony card +# Sorry, there was a typo + 5654 3132 OpenSwitch 12 Telephony card 5654 5634 OpenLine4 Telephony Card d531 c002 PCIntelliCAN 2xSJA1000 CAN bus d84d 4006 EX-4006 1P @@ -2317,7 +2602,17 @@ 9054 PCI <-> IOBus Bridge 10b5 2455 Wessex Techology PHIL-PCI 10b5 2696 Innes Corp AM Radcap card + 10b5 2717 Innes Corp Auricon card + 10b5 2844 Innes Corp TVS Encoder card 12d9 0002 PCI Prosody Card rev 1.5 + 16df 0011 PIKA PrimeNet MM PCI + 16df 0012 PIKA PrimeNet MM cPCI 8 + 16df 0013 PIKA PrimeNet MM cPCI 8 (without CAS Signaling Option) + 16df 0014 PIKA PrimeNet MM cPCI 4 + 16df 0015 PIKA Daytona MM + 16df 0016 PIKA InLine MM + 9056 Francois + 10b5 2979 CellinkBlade 11 - CPCI board VoATM AAL1 9060 9060 906d 9060SD 125c 0640 Aries 16000P @@ -2326,6 +2621,7 @@ 10b5 9080 9080 [real subsystem ID not set] 129d 0002 Aculab PCI Prosidy card 12d9 0002 PCI Prosody Card + 12df 4422 4422PCI ["Do-All" Telemetry Data Aquisition System] bb04 B&B 3PCIOSD1A Isolated PCI Serial 10b6 Madge Networks 0001 Smart 16/4 PCI Ringnode @@ -2358,17 +2654,22 @@ 1006 MINI PCI type 3B Data Fax Modem 1007 Mini PCI 56k Winmodem 10b7 615c Mini PCI 56K Modem - 1700 3c940 1000Base? + 1201 3c982-TXM 10/100baseTX Dual Port A [Hydra] + 1202 3c982-TXM 10/100baseTX Dual Port B [Hydra] + 1700 3c940 10/100/1000Base-T [Marvell] + 1043 80eb P4P800 Mainboard + 10b7 0010 3C940 Gigabit LOM Ethernet Adapter + 10b7 0020 3C941 Gigabit LOM Ethernet Adapter 3390 3c339 TokenLink Velocity 3590 3c359 TokenLink Velocity XL 10b7 3590 TokenLink Velocity XL Adapter (3C359/359B) - 4500 3c450 Cyclone/unknown + 4500 3c450 HomePNA [Tornado] 5055 3c555 Laptop Hurricane - 5057 3c575 [Megahertz] 10/100 LAN CardBus + 5057 3c575 Megahertz 10/100 LAN CardBus [Boomerang] 10b7 5a57 3C575 Megahertz 10/100 LAN Cardbus PC Card - 5157 3c575 [Megahertz] 10/100 LAN CardBus + 5157 3cCFE575BT Megahertz 10/100 LAN CardBus [Cyclone] 10b7 5b57 3C575 Megahertz 10/100 LAN Cardbus PC Card - 5257 3CCFE575CT Cyclone CardBus + 5257 3cCFE575CT CardBus [Cyclone] 10b7 5c57 FE575C-3Com 10/100 LAN CardBus-Fast Ethernet 5900 3c590 10BaseT [Vortex] 5920 3c592 EISA 10mbps Demon/Vortex @@ -2376,20 +2677,22 @@ 5951 3c595 100BaseT4 [Vortex] 5952 3c595 100Base-MII [Vortex] 5970 3c597 EISA Fast Demon/Vortex - 5b57 3c595 [Megahertz] 10/100 LAN CardBus + 5b57 3c595 Megahertz 10/100 LAN CardBus [Boomerang] 10b7 5b57 3C575 Megahertz 10/100 LAN Cardbus PC Card - 6055 3c556 Hurricane CardBus - 6056 3c556B Hurricane CardBus + 6000 3CRSHPW796 [OfficeConnect Wireless CardBus] + 6001 3com 3CRWE154G72 [Office Connect Wireless LAN Adapter] + 6055 3c556 Hurricane CardBus [Cyclone] + 6056 3c556B CardBus [Tornado] 10b7 6556 10/100 Mini PCI Ethernet Adapter - 6560 3CCFE656 Cyclone CardBus + 6560 3cCFE656 CardBus [Cyclone] 10b7 656a 3CCFEM656 10/100 LAN+56K Modem CardBus - 6561 3CCFEM656 10/100 LAN+56K Modem CardBus + 6561 3cCFEM656 10/100 LAN+56K Modem CardBus 10b7 656b 3CCFEM656 10/100 LAN+56K Modem CardBus - 6562 3CCFEM656 [id 6562] Cyclone CardBus + 6562 3cCFEM656B 10/100 LAN+Winmodem CardBus [Cyclone] 10b7 656b 3CCFEM656B 10/100 LAN+56K Modem CardBus - 6563 3CCFEM656B 10/100 LAN+56K Modem CardBus + 6563 3cCFEM656B 10/100 LAN+56K Modem CardBus 10b7 656b 3CCFEM656 10/100 LAN+56K Modem CardBus - 6564 3CCFEM656 [id 6564] Cyclone CardBus + 6564 3cXFEM656C 10/100 LAN+Winmodem CardBus [Tornado] 7646 3cSOHO100-TX Hurricane 7770 3CRWE777 PCI(PLX) Wireless Adaptor [Airconnect] 7940 3c803 FDDILink UTP Controller @@ -2397,13 +2700,13 @@ 7990 3c805 FDDILink DAS Controller 8811 Token ring 9000 3c900 10BaseT [Boomerang] - 9001 3c900 Combo [Boomerang] - 9004 3c900B-TPO [Etherlink XL TPO] + 9001 3c900 10Mbps Combo [Boomerang] + 9004 3c900B-TPO Etherlink XL [Cyclone] 10b7 9004 3C900B-TPO Etherlink XL TPO 10Mb - 9005 3c900B-Combo [Etherlink XL Combo] + 9005 3c900B-Combo Etherlink XL [Cyclone] 10b7 9005 3C900B-Combo Etherlink XL Combo - 9006 3c900B-TPC [Etherlink XL TPC] - 900a 3c900B-FL [Etherlink XL FL] + 9006 3c900B-TPC Etherlink XL [Cyclone] + 900a 3c900B-FL 10base-FL [Cyclone] 9050 3c905 100BaseTX [Boomerang] 9051 3c905 100BaseT4 [Boomerang] 9055 3c905B 100BaseTX [Cyclone] @@ -2428,21 +2731,23 @@ 1028 0098 3C905B Fast Etherlink XL 10/100 1028 0099 3C905B Fast Etherlink XL 10/100 10b7 9055 3C905B Fast Etherlink XL 10/100 - 9056 3c905B-T4 [Fast EtherLink XL 10/100] - 9058 3c905B-Combo [Deluxe Etherlink XL 10/100] - 905a 3c905B-FX [Fast Etherlink XL FX 10/100] + 9056 3c905B-T4 Fast EtherLink XL [Cyclone] + 9058 3c905B Deluxe Etherlink 10/100/BNC [Cyclone] + 905a 3c905B-FX Fast Etherlink XL FX 100baseFx [Cyclone] 9200 3c905C-TX/TX-M [Tornado] 1028 0095 3C920 Integrated Fast Ethernet Controller 1028 0097 3C920 Integrated Fast Ethernet Controller + 1028 012a 3C920 Integrated Fast Ethernet Controller [Latitude C640] 10b7 1000 3C905C-TX Fast Etherlink for PC Management NIC 10b7 7000 10/100 Mini PCI Ethernet Adapter - 9201 3C920B-EMB Integrated Fast Ethernet Controller - 9300 3CSOHO100B-TX [910-A01] - 9800 3c980-TX [Fast Etherlink XL Server Adapter] + 10f1 2466 Tiger MPX S2466 (3C920 Integrated Fast Ethernet Controller) + 9201 3C920B-EMB Integrated Fast Ethernet Controller [Tornado] + 9202 3Com 3C920B-EMB-WNM Integrated Fast Ethernet Controller + 9210 3C920B-EMB-WNM Integrated Fast Ethernet Controller + 9300 3CSOHO100B-TX 910-A01 [tulip] + 9800 3c980-TX Fast Etherlink XL Server Adapter [Cyclone] 10b7 9800 3c980-TX Fast Etherlink XL Server Adapter - 9805 3c980-TX 10/100baseTX NIC [Python-T] - 10b7 1201 3c982-TXM 10/100baseTX Dual Port A [Hydra] - 10b7 1202 3c982-TXM 10/100baseTX Dual Port B [Hydra] + 9805 3c980-C 10/100baseTX NIC [Python-T] 10b7 9805 3c980 10/100baseTX NIC [Python-T] 10f1 2462 Thunder K7 S2462 9900 3C990-TX [Typhoon] @@ -2458,9 +2763,10 @@ 10b7 2102 3CR990-FX-97 Server [Typhoon Fiber 168-bit] 9908 3CR990SVR95 [Typhoon Server 56-bit] 9909 3CR990SVR97 [Typhoon Server 168-bit] + 990a 3C990SVR [Typhoon Server] 990b 3C990SVR [Typhoon Server] 10b8 Standard Microsystems Corp [SMC] - 0005 83C170QF + 0005 83c170 EPIC/100 Fast Ethernet Adapter 1055 e000 LANEPIC 10/100 [EVB171Q-PCI] 1055 e002 LANEPIC 10/100 [EVB171G-PCI] 10b8 a011 EtherPower II 10/100 @@ -2468,7 +2774,7 @@ 10b8 a015 EtherPower II 10/100 10b8 a016 EtherPower II 10/100 10b8 a017 EtherPower II 10/100 - 0006 LANEPIC + 0006 83c175 EPIC/100 Fast Ethernet Adapter 1055 e100 LANEPIC Cardbus Fast Ethernet Adapter 1055 e102 LANEPIC Cardbus Fast Ethernet Adapter 1055 e300 LANEPIC Cardbus Fast Ethernet Adapter @@ -2478,6 +2784,8 @@ 13a2 8006 LANEPIC Cardbus Fast Ethernet Adapter 1000 FDC 37c665 1001 FDC 37C922 +# 802.11g card + 2802 SMC2802W [EZ Connect g] a011 83C170QF b106 SMC34C90 10b9 ALi Corporation @@ -2522,6 +2830,7 @@ 3151 M3151 3307 M3307 3309 M3309 + 3323 M3325 Video/Audio Decoder 5212 M4803 5215 MS4803 5217 M5217H @@ -2543,7 +2852,7 @@ 1014 0506 ThinkPad R30 5453 M5453 PCI AC-Link Controller Modem Device 5455 M5455 PCI AC-Link Controller Audio Device - 5457 Intel 537 [M5457 AC-Link Modem] + 5457 M5457 AC'97 Modem Controller # Same but more usefull for driver's lookup 5459 SmartLink SmartPCI561 56K Modem # SmartLink PCI SoftModem @@ -2554,6 +2863,9 @@ 10b9 7101 ALI M7101 Power Management Controller 10ba Mitsubishi Electric Corp. 0301 AccelGraphics AccelECLIPSE + 0304 AccelGALAXY A2100 [OEM Evans & Sutherland] + 0308 Tornado 3000 [OEM Evans & Sutherland] + 1002 VG500 [VolumePro Volume Rendering Accelerator] 10bb Dapha Electronics Corporation 10bc Advanced Logic Research 10bd Surecom Technology @@ -2594,6 +2906,7 @@ 10f7 8312 MagicGraph 128XD 0005 NM2200 [MagicGraph 256AV] 1014 00dd ThinkPad 570 + 1028 0088 Latitude CPi A400XT 0006 NM2360 [MagicMedia 256ZX] 0016 NM2380 [MagicMedia 256XL+] 10c8 0016 MagicMedia 256XL+ @@ -2725,7 +3038,7 @@ 1102 1024 CT6932 RIVA TNT2 Value 32Mb 1102 102c CT6931 RIVA TNT2 Value [Jumper] 1462 8808 MSI-8808 - 1554 1041 PixelView RIVA TNT2 M64 32MB + 1554 1041 Pixelview RIVA TNT2 M64 002e NV6 [Vanta] 002f NV6 [Vanta] 0060 nForce2 ISA Bridge @@ -2781,9 +3094,11 @@ 0150 NV15 [GeForce2 GTS/Pro] 1043 4016 V7700 AGP Video Card 107d 2840 WinFast GeForce2 GTS with TV output + 107d 2842 WinFast GeForce 2 Pro 1462 8831 Creative GeForce2 Pro 0151 NV15DDR [GeForce2 Ti] 1043 405f V7700Ti + 1462 5506 Creative 3D Blaster Geforce2 Titanium 0152 NV15BR [GeForce2 Ultra, Bladerunner] 1048 0c56 GLADIAC Ultra 0153 NV15GL [Quadro2 Pro] @@ -2798,16 +3113,23 @@ 0174 NV17 [GeForce4 440 Go] 0175 NV17 [GeForce4 420 Go] 0176 NV17 [GeForce4 420 Go 32M] + 4c53 1090 Cx9 / Vx9 mainboard + 0177 NV17 [GeForce4 460 Go] 0178 NV17GL [Quadro4 550 XGL] 0179 NV17 [GeForce4 440 Go 64M] + 10de 0179 GeForce4 MX (Mac) 017a NV17GL [Quadro4 200/400 NVS] 017b NV17GL [Quadro4 550 XGL] 017c NV17GL [Quadro4 550 GoGL] 0181 NV18 [GeForce4 MX 440 AGP 8x] 1043 806f V9180 Magic 1462 8880 MS-StarForce GeForce4 MX 440 with AGP8X + 1462 8900 MS-8890 GeForce 4 MX440 AGP8X + 1462 9350 MSI Geforce4 MX T8X with AGP8X + 147b 8f0d Siluro GF4 MX-8X 0182 NV18 [GeForce4 MX 440SE AGP 8x] 0183 NV18 [GeForce4 MX 420 AGP 8x] + 0185 NV18 [GeForce4 MX 4000 AGP 8x] 0188 NV18GL [Quadro4 580 XGL] 018a NV18GL [Quadro4 NVS AGP 8x] 018b NV18GL [Quadro4 380 XGL] @@ -2822,7 +3144,7 @@ 01b7 nForce AGP to PCI Bridge 01b8 nForce PCI-to-PCI bridge 01bc nForce IDE - 01c1 Intel 537 [nForce MC97 Modem] + 01c1 nForce AC'97 Modem Controller 01c2 nForce USB Controller 01c3 nForce Ethernet Controller 01e0 nForce2 AGP (different version?) @@ -2863,21 +3185,42 @@ 0309 NV30GL [Quadro FX 1000] 0311 NV31 [GeForce FX 5600 Ultra] 0312 NV31 [GeForce FX 5600] + 0314 NV31 [GeForce FX 5600XT] + 031a NV31M [GeForce FX Go 5600] + 031c NVIDIA Quadro FX 700 Go 0321 NV34 [GeForce FX 5200 Ultra] 0322 NV34 [GeForce FX 5200] + 1462 9171 MS-8917 (FX5200-T128) + 0324 NV34M [GeForce FX Go 5200] + 1071 8160 MIM2000 + 0328 NV34M [GeForce FX Go 5200] + 0329 NV34M [GeForce FX Go5200] 032b NV34GL [Quadro FX 500] + 032c NV34GLM [GeForce FX Go 5300] 0330 NV35 [GeForce FX 5900 Ultra] 0331 NV35 [GeForce FX 5900] + 0332 NV35 [GeForce FX 5900XT] + 0333 NV38 [GeForce FX 5950 Ultra] 0338 NV35GL [Quadro FX 3000] + 0341 NV 36 [GeForce 5700 Ultra] + 0342 NV 36 [GeForce 5700] 10df Emulex Corporation 1ae5 LP6000 Fibre Channel Host Adapter + 1ae6 LP 8000 Fibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:1-2) + 1ae7 LP 8000 Fibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:2-3) f085 LP850 Fibre Channel Adapter f095 LP952 Fibre Channel Adapter f098 LP982 Fibre Channel Adapter f700 LP7000 Fibre Channel Host Adapter + f701 LP 7000EFibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:1-2) f800 LP8000 Fibre Channel Host Adapter + f801 LP 8000 Fibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:1-2) f900 LP9000 Fibre Channel Host Adapter + f901 LP 9000 Fibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:1-2) f980 LP9802 Fibre Channel Adapter + f981 LP 9802 Fibre Channel Host Adapter Alternate ID + f982 LP 9802 Fibre Channel Host Adapter Alternate ID + fa00 LP10000 Fibre Channel Host Adapter 10e0 Integrated Micro Solutions Inc. 5026 IMS5026/27/28 5027 IMS5027 @@ -2900,6 +3243,7 @@ 10e6 Gainbery Computer Products Inc. 10e7 Vadem 10e8 Applied Micro Circuits Corp. + 1072 INES GPIB-PCI (AMCC5920 based) 2011 Q-Motion Video Capture/Edit board 4750 S5930 [Matchmaker] 5920 S5920 @@ -2926,6 +3270,8 @@ 5000 CyberPro 5000 5050 CyberPro 5050 5202 CyberPro 5202 +# CyberPro5202 Audio Function + 5252 CyberPro5252 10eb Artists Graphics 0101 3GA 8111 Twist3 Frame Grabber @@ -2943,6 +3289,7 @@ 8139 RTL-8139/8139C/8139C+ 1025 8920 ALN-325 1025 8921 ALN-325 + 1071 8160 MIM2000 10bd 0320 EP-320X-R 10ec 8139 RT8139 1186 1300 DFE-538TX @@ -2954,17 +3301,20 @@ 1429 d010 ND010 1432 9130 EN-9130TX 1436 8139 RT8139 + 1458 e000 GA-7VM400M Motherboard 146c 1439 FE-1439TX 1489 6001 GF100TXRII 1489 6002 GF100TXRA 149c 139a LFE-8139ATX 149c 8139 LFE-8139TX + 1799 5000 F5D5000 PCI Card/Desktop Network PCI Card 2646 0001 EtheRx 8e2e 7000 KF-230TX 8e2e 7100 KF-230TX/2 a0a0 0007 ALN-325C - 8169 RTL-8169 + 8169 RTL-8169 Gigabit Ethernet 1371 434e ProG-2000L + 8180 RTL8180L 802.11b MAC 8197 SmartLAN56 56K Modem 10ed Ascii Corporation 7310 V7310 @@ -2975,6 +3325,7 @@ 3fc3 RME Digi96/8 Pad 3fc4 RME Digi9652 (Hammerfall) 3fc5 RME Hammerfall DSP + 3fc6 RME Hammerfall DSP MADI 8381 Ellips Santos Frame Grabber 10ef Racore Computer Products, Inc. 8154 M815x Token Ring Adapter @@ -3029,7 +3380,10 @@ 0004 SB Audigy 1102 0051 SB0090 Audigy Player 1102 0053 SB0090 Audigy Player/OEM + 1102 0058 SB0090 Audigy Player/OEM + 1102 2002 SB Audigy 2 ZS (SB0350) 0006 [SB Live! Value] EMU10k1X + 0007 SB Audigy LS 4001 SB Audigy FireWire Port 1102 0010 SB Audigy FireWire Port 7002 SB Live! MIDI/Game Port @@ -3037,6 +3391,7 @@ 7003 SB Audigy MIDI/Game port 1102 0040 SB Audigy MIDI/Game Port 7004 [SB Live! Value] Input device controller + 7005 SB Audigy LS MIDI/Game port 8064 SB0100 [SBLive! 5.1 OEM] 8938 Ectiva EV1938 1103 Triones Technologies, Inc. @@ -3055,6 +3410,13 @@ 1105 REALmagic Xcard MPEG 1/2/3/4 DVD Decoder 8300 REALmagic Hollywood Plus DVD Decoder 8400 EM840x REALmagic DVD/MPEG-2 Audio/Video Decoder + 8401 EM8401 REALmagic DVD/MPEG-2 A/V Decoder + 8470 EM8470 REALmagic DVD/MPEG-4 A/V Decoder + 8471 EM8471 REALmagic DVD/MPEG-4 A/V Decoder + 8475 EM8475 REALmagic DVD/MPEG-4 A/V Decoder + 8476 EM8476 REALmagic DVD/MPEG-4 A/V Decoder + 8485 EM8485 REALmagic DVD/MPEG-4 A/V Decoder + 8486 EM8486 REALmagic DVD/MPEG-4 A/V Decoder 1106 VIA Technologies, Inc. 0102 Embedded VIA Ethernet Controller 0130 VT6305 1394.A Controller @@ -3068,10 +3430,13 @@ 0505 VT82C505 # Shares chip with :0576. The VT82C576M has :1571 instead of :0561. 0561 VT82C576MV - 0571 VT82C586A/B/VT82C686/A/B/VT8233/A/C/VT8235 PIPC Bus Master IDE + 0571 VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE 1019 0985 P6VXA Motherboard + 1019 0a81 L7VTA v1.0 Motherboard (KT400-8235) 1043 8052 VT8233A Bus Master ATA100/66/33 IDE 1043 808c A7V8X motherboard + 1043 80a1 A7V8X-X motherboard rev. 1.01 + 1043 80ed A7V600 motherboard 1106 0571 VT82C586/B/VT82C686/A/B/VT8233/A/C/VT8235 PIPC Bus Master IDE 1179 0001 Magnia Z310 1297 f641 FX41 motherboard @@ -3112,10 +3477,14 @@ 1106 VT82C570MV 1571 VT82C576M/VT82C586 1595 VT82C595/97 [Apollo VP2/97] - 3038 USB +# This is *not* USB 2.0 as the existing entry suggests + 3038 VT82xxxxx UHCI USB 1.1 Controller 0925 1234 USB Controller 1019 0985 P6VXA Motherboard - 1043 808c A7V8X motherboard + 1019 0a81 L7VTA v1.0 Motherboard (KT400-8235) + 1043 808c VT6202 USB2.0 4 port controller + 1043 80a1 A7V8X-X motherboard + 1043 80ed A7V600 motherboard 1179 0001 Magnia Z310 1458 5004 GA-7VAX Mainboard 3040 VT82C586B ACPI @@ -3126,6 +3495,7 @@ 3044 IEEE 1394 Host Controller 3050 VT82C596 Power Management 3051 VT82C596 Power Management + 3053 VT6105M [Rhine-III] 3057 VT82C686 [Apollo Super ACPI] 1019 0985 P6VXA Motherboard 1043 8033 A7V Mainboard @@ -3134,17 +3504,23 @@ 1043 8042 A7V133/A7V133-C Mainboard 1179 0001 Magnia Z310 3058 VT82C686 AC97 Audio Controller + 0e11 0097 SoundMax Digital Integrated Audio 0e11 b194 Soundmax integrated digital audio 1019 0985 P6VXA Motherboard 1106 4511 Onboard Audio on EP7KXA 1458 7600 Onboard Audio 1462 3091 MS-6309 Onboard Audio 15dd 7609 Onboard Audio - 3059 VT8233/A/8235 AC97 Audio Controller + 3059 VT8233/A/8235/8237 AC97 Audio Controller + 1019 0a81 L7VTA v1.0 Motherboard (KT400-8235) 1043 8095 A7V8X Motherboard (Realtek ALC650 codec) + 1043 80b0 A7V600 motherboard (ADI AD1980 codec [SoundMAX]) + 1106 3059 L7VMM2 Motherboard 1297 c160 FX41 motherboard (Realtek ALC650 codec) 1458 a002 GA-7VAX Onboard Audio (Realtek ALC650) + 1462 3800 KT266 onboard audio 3065 VT6102 [Rhine-II] + 1043 80a1 A7V8X-X Motherboard 1106 0102 VT6102 [Rhine II] Embeded Ethernet Controller on VT8235 1186 1400 DFE-530TX rev A 1186 1401 DFE-530TX rev B @@ -3160,10 +3536,14 @@ 3102 VT8662 Host Bridge 3103 VT8615 Host Bridge 3104 USB 2.0 + 1019 0a81 L7VTA v1.0 Motherboard (KT400-8235) 1043 808c A7V8X motherboard + 1043 80a1 A7V8X-X motherboard rev 1.01 + 1043 80ed A7V600 motherboard 1297 f641 FX41 motherboard 1458 5004 GA-7VAX Mainboard 3106 VT6105 [Rhine-III] + 1186 1403 DFE-530TX rev C 3109 VT8233C PCI to ISA Bridge 3112 VT8361 [KLE133] Host Bridge 3116 VT8375 [KM266/KL266] Host Bridge @@ -3176,17 +3556,33 @@ 3133 VT3133 Host Bridge 3147 VT8233A ISA Bridge 3148 P4M266 Host Bridge + 3149 VIA VT6420 SATA RAID Controller + 1043 80ed A7V600 motherboard + 1462 7020 MSI Neo K8T FIS2R mainboard 3156 P/KN266 Host Bridge +# on ASUS P4P800 + 3164 VT6410 ATA133 RAID controller 3168 VT8374 P4X400 Host Controller/AGP Bridge 3177 VT8235 ISA Bridge + 1019 0a81 L7VTA v1.0 Motherboard (KT400-8235) 1043 808c A7V8X motherboard + 1043 80a1 A7V8X-X motherboard 1297 f641 FX41 motherboard 1458 5001 GA-7VAX Mainboard - 3189 VT8377 [KT400 AGP] Host Bridge + 3188 VT8385 [K8T800 AGP] Host Bridge + 3189 VT8377 [KT400/KT600 AGP] Host Bridge 1043 807f A7V8X motherboard 1458 5000 GA-7VAX Mainboard +# Updated the entry to the proper "chip [name] desc" format + 3205 VT8378 [KM400] Chipset Host Bridge + 1458 5000 GA-7VM400M Motherboard + 3227 VT8237 ISA bridge [K8T800 South] + 1043 80ed A7V600 motherboard 5030 VT82C596 ACPI [Apollo PRO] 6100 VT85C100A [Rhine II] +# S3 Graphics UniChromeâ„¢ 2D/3D Graphics with motion compensation + 7205 VT8378 [S3 UniChrome] Integrated Video + 1458 d000 GA-7VM400M Motherboard 8231 VT8231 [PCI-to-ISA Bridge] 8235 VT8235 ACPI 8305 VT8363/8365 [KT133/KM133 AGP] @@ -3207,7 +3603,10 @@ b103 VT8615 AGP Bridge b112 VT8361 [KLE133] AGP Bridge b168 VT8235 PCI Bridge + b188 VT8237 PCI bridge [K8T800 South] b198 VT8237 PCI Bridge +# 32-Bit PCI bus master Ethernet MAC with standard MII interface + d104 VT8237 Integrated Fast Ethernet Controller 1107 Stratus Computers 0576 VIA VT82C570MV [Apollo] (Wrong vendor ID!) 1108 Proteon, Inc. @@ -3231,6 +3630,7 @@ 007c FSC Remote Service Controller, shared memory device 007d FSC Remote Service Controller, SMIC device 2102 DSCC4 WAN adapter + 2104 Eicon Diva 2.02 compatible passive ISDN card 4021 SIMATIC NET CP 5512 (Profibus and MPI Cardbus Adapter) 4942 FPGA I-Bus Tracer for MBD 6120 SZB6120 @@ -3256,13 +3656,15 @@ 103c 1207 EN-1207D Fast Ethernet Adapter 1113 1211 EN-1207D Fast Ethernet Adapter 1216 EN-1216 Ethernet Adapter + 1113 2242 EN2242 10/100 Ethernet Mini-PCI Card 111a 1020 SpeedStream 1020 PCI 10/100 Ethernet Adaptor [EN-1207F-TX ?] 1217 EN-1217 Ethernet Adapter 5105 10Mbps Network card 9211 EN-1207D Fast Ethernet Adapter 1113 9211 EN-1207D Fast Ethernet Adapter - 9511 Fast Ethernet Adapter + 9511 21x4x DEC-Tulip compatible Fast Ethernet 1114 Atmel Corporation + 0506 802.11b Wireless Network Adaptor (at76c506) 1115 3D Labs 1116 Data Translation 0022 DT3001 @@ -3283,14 +3685,18 @@ 0003 GDT 6120/6520 0004 GDT 6530 0005 GDT 6550 - 0006 GDT 6x17 - 0007 GDT 6x27 + 0006 GDT 6117/6517 + 0007 GDT 6127/6527 0008 GDT 6537 - 0009 GDT 6557 + 0009 GDT 6557/6557-ECC 000a GDT 6115/6515 000b GDT 6125/6525 000c GDT 6535 000d GDT 6555 + 0010 GDT 6115/6515 + 0011 GDT 6125/6525 + 0012 GDT 6535 + 0013 GDT 6555/6555-ECC 0100 GDT 6117RP/6517RP 0101 GDT 6127RP/6527RP 0102 GDT 6537RP @@ -3345,7 +3751,8 @@ 0211 GDT 6529RD/6629RD 0260 GDT 7519RN/7619RN 0261 GDT 7529RN/7629RN - 0300 GDT Raid Controller + 02ff GDT MAXRP + 0300 GDT NEWRX 111a Efficient Networks, Inc 0000 155P-MF1 (FPGA) 0002 155P-MF1 (ASIC) @@ -3361,6 +3768,7 @@ 111a 0a09 ENI-3060 ADSL (VPI=<0..15>) 0007 SpeedStream ADSL 111a 1001 ENI-3061 ADSL [ASIC] + 1203 SpeedStream 1023 Wireless PCI Adapter 111b Teledyne Electronic Systems 111c Tricord Systems Inc. 0001 Powerbis Bridge @@ -3409,11 +3817,32 @@ 7135 SAA7135 Audio+video broadcast decoder 7145 SAA7145 7146 SAA7146 + 110a 0000 Fujitsu/Siemens DVB-C card rev1.5 + 110a ffff Fujitsu/Siemens DVB-C card rev1.5 + 1131 4f56 KNC1 DVB-S Budget + 1131 4f61 Fujitsu-Siemens Activy DVB-S Budget 114b 2003 DVRaptor Video Edit/Capture Card 11bd 0006 DV500 Overlay 11bd 000a DV500 Overlay + 13c2 0000 Siemens/Technotrend/Hauppauge DVB card rev1.3 + 13c2 0001 Technotrend/Hauppauge DVB card rev1.3 or rev1.6 + 13c2 0002 Technotrend/Hauppauge DVB card rev2.1 + 13c2 0003 Technotrend/Hauppauge DVB card rev2.1 + 13c2 0004 Technotrend/Hauppauge DVB card rev2.1 + 13c2 0006 Technotrend/Hauppauge DVB card rev1.3 or rev1.6 + 13c2 0008 Technotrend/Hauppauge DVB-T + 13c2 000a Octal/Technotrend DVB-C for iTV + 13c2 1003 Technotrend-Budget / Hauppauge WinTV-NOVA-S DVB card + 13c2 1004 Technotrend-Budget / Hauppauge WinTV-NOVA-C DVB card + 13c2 1005 Technotrend-Budget / Hauppauge WinTV-NOVA-T DVB card + 13c2 100c Technotrend-Budget / Hauppauge WinTV-NOVA-CI DVB card + 13c2 100f Technotrend-Budget / Hauppauge WinTV-NOVA-CI DVB card + 13c2 1011 Technotrend-Budget / Hauppauge WinTV-NOVA-T DVB card + 13c2 1013 SATELCO Multimedia DVB + 13c2 1102 Technotrend/Hauppauge DVB card rev2.1 1132 Mitel Corp. -1133 Eicon Technology Corporation +# This is the new official company name. See disclaimer on www.eicon.com for details! +1133 Eicon Networks Corporation 7901 EiconCard S90 7902 EiconCard S90 7911 EiconCard S91 @@ -3478,6 +3907,8 @@ 1133 1c0c Diva Server V-PRI/E1-30 Cornet NQ 3 e01e Diva Server 2PRI e020 Diva Server 4PRI + e024 Diva Server Analog-4P + e028 Diva Server Analog-8P 1134 Mercury Computer Systems 0001 Raceway Bridge 1135 Fuji Xerox Co Ltd @@ -3545,24 +3976,37 @@ 1148 5843 FDDI SK-5843 (SK-NET FDDI-LP64) 1148 5844 FDDI SK-5844 (SK-NET FDDI-LP64 DAS) 4200 Token Ring adapter - 4300 Gigabit Ethernet - 1148 9821 SK-9821 (1000Base-T single link) - 1148 9822 SK-9822 (1000Base-T dual link) - 1148 9841 SK-9841 (1000Base-LX single link) - 1148 9842 SK-9842 (1000Base-LX dual link) - 1148 9843 SK-9843 (1000Base-SX single link) - 1148 9844 SK-9844 (1000Base-SX dual link) - 1148 9861 SK-9861 (1000Base-SX VF45 single link) - 1148 9862 SK-9862 (1000Base-SX VF45 dual link) -# Information got from SysKonnekt - 1148 9871 SK-9871 (1000Base-ZX single link) -# Information got from SysKonnekt - 1148 9872 SK-9872 (1000Base-ZX dual link) - 1259 2970 AT-2970SX [Allied Telesyn] - 1259 2972 AT-2970T [Allied Telesyn] - 1259 2975 AT-2970SX [Allied Telesyn] - 1259 2977 AT-2970T [Allied Telesyn] - 4320 SK-98xx Gigabit Ethernet Server Adapter + 4300 SK-98xx Gigabit Ethernet Server Adapter + 1148 9821 SK-9821 Gigabit Ethernet Server Adapter (SK-NET GE-T) + 1148 9822 SK-9822 Gigabit Ethernet Server Adapter (SK-NET GE-T dual link) + 1148 9841 SK-9841 Gigabit Ethernet Server Adapter (SK-NET GE-LX) + 1148 9842 SK-9842 Gigabit Ethernet Server Adapter (SK-NET GE-LX dual link) + 1148 9843 SK-9843 Gigabit Ethernet Server Adapter (SK-NET GE-SX) + 1148 9844 SK-9844 Gigabit Ethernet Server Adapter (SK-NET GE-SX dual link) + 1148 9861 SK-9861 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition) + 1148 9862 SK-9862 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition dual link) + 1148 9871 SK-9871 Gigabit Ethernet Server Adapter (SK-NET GE-ZX) + 1148 9872 SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) + 1259 2970 AT-2970SX Gigabit Ethernet Adapter + 1259 2971 AT-2970LX Gigabit Ethernet Adapter + 1259 2972 AT-2970TX Gigabit Ethernet Adapter + 1259 2973 AT-2971SX Gigabit Ethernet Adapter + 1259 2974 AT-2971T Gigabit Ethernet Adapter + 1259 2975 AT-2970SX/2SC Gigabit Ethernet Adapter + 1259 2976 AT-2970LX/2SC Gigabit Ethernet Adapter + 1259 2977 AT-2970TX/2TX Gigabit Ethernet Adapter + 4320 SK-98xx V2.0 Gigabit Ethernet Adapter + 1148 0121 Marvell RDK-8001 Adapter + 1148 0221 Marvell RDK-8002 Adapter + 1148 0321 Marvell RDK-8003 Adapter + 1148 0421 Marvell RDK-8004 Adapter + 1148 0621 Marvell RDK-8006 Adapter + 1148 0721 Marvell RDK-8007 Adapter + 1148 0821 Marvell RDK-8008 Adapter + 1148 0921 Marvell RDK-8009 Adapter + 1148 1121 Marvell RDK-8011 Adapter + 1148 1221 Marvell RDK-8012 Adapter + 1148 3221 SK-9521 V2.0 10/100/1000Base-T Adapter 1148 5021 SK-9821 V2.0 Gigabit Ethernet 10/100/1000Base-T Adapter 1148 5041 SK-9841 V2.0 Gigabit Ethernet 1000Base-LX Adapter 1148 5043 SK-9843 V2.0 Gigabit Ethernet 1000Base-SX Adapter @@ -3570,7 +4014,8 @@ 1148 5061 SK-9861 V2.0 Gigabit Ethernet 1000Base-SX Adapter 1148 5071 SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter 1148 9521 SK-9521 10/100/1000Base-T Adapter - 4400 Gigabit Ethernet + 4400 SK-9Dxx Gigabit Ethernet Adapter + 4500 SK-9Mxx Gigabit Ethernet Adapter 1149 Win System Corporation 114a VMIC 5579 VMIPCI-5579 (Reflective Memory Card) @@ -3611,14 +4056,28 @@ 114f 0031 DataFire RAS BRI S/T Adapter 0026 AccelePort 4r 920 0027 AccelePort Xr 920 + 0028 ClassicBoard 4 + 0029 ClassicBoard 8 0034 AccelePort 2r 920 0035 DataFire DSP T1/E1/PRI cPCI 0040 AccelePort Xp - 0042 AccelePort 2p PCI + 0042 AccelePort 2p + 0043 AccelePort 4p + 0044 AccelePort 8p + 0045 AccelePort 16p + 004e AccelePort 32p 0070 Datafire Micro V IOM2 (Europe) 0071 Datafire Micro V (Europe) 0072 Datafire Micro V IOM2 (North America) 0073 Datafire Micro V (North America) + 00b0 Digi Neo 4 + 00b1 Digi Neo 8 + 00c8 Digi Neo 2 DB9 + 00c9 Digi Neo 2 DB9 PRI + 00ca Digi Neo 2 RJ45 + 00cb Digi Neo 2 RJ45 PRI + 00d0 ClassicBoard 4 422 + 00d1 ClassicBoard 8 422 6001 Avanstar 1150 Thinking Machines Corp 1151 JAE Electronics Inc. @@ -3665,6 +4124,7 @@ 000f Cardbus Ethernet 10/100 1014 0183 10/100 EtherJet Cardbus Adapter 115d 0183 Cardbus Ethernet 10/100 + 00d4 Mini-PCI K56Flex Modem 0101 Cardbus 56k modem 115d 1081 Cardbus 56k Modem 0103 Cardbus Ethernet + 56k Modem @@ -3698,6 +4158,8 @@ 0015 CMIC-GC Host Bridge 0016 CMIC-GC Host Bridge 0017 GCNB-LE Host Bridge + 0101 CIOB-X2 + 0110 CIOB-E I/O Bridge with Gigabit Ethernet 0200 OSB4 South Bridge 0201 CSB5 South Bridge 4c53 1080 CT8 mainboard @@ -3709,10 +4171,11 @@ 0220 OSB4/CSB5 OHCI USB Controller 4c53 1080 CT8 mainboard 0221 CSB6 OHCI USB Controller - 0225 GCLE Host Bridge + 0225 CSB5 LPC bridge # cancelled 4c53 1080 CT8 mainboard 0227 GCLE-2 Host Bridge + 0230 CSB5 LPC bridge 4c53 1080 CT8 mainboard 1167 Mutoh Industries Inc 1168 Thine Electronics Inc @@ -3769,6 +4232,7 @@ 1014 0185 ThinkPad A/T/X Series 104d 80df Vaio PCG-FX403 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP + 14ef 0220 PCD-RP-220S 0477 RL5c477 0478 RL5c478 1014 0184 ThinkPad A30p (2653-64G) @@ -3792,7 +4256,11 @@ 1186 1301 DFE-530TX+ 10/100 Ethernet Adapter 1340 DFE-690TXD CardBus PC Card 1561 DRP-32TXD Cardbus PC Card - 4000 DL2K Ethernet + 3300 DWL-510 2.4GHz Wireless PCI Adapter + 3b05 DWL-G650+ CardBus PC Card + 4000 DL2000-based Gigabit Ethernet + 4c00 Gigabit Ethernet Adapter + 8400 D-Link DWL-650+ CardBus PC Card 1187 Advanced Technology Laboratories, Inc. 1188 Shima Seiki Manufacturing Ltd. 1189 Matsushita Electronics Co Ltd @@ -3845,6 +4313,7 @@ 1195 Ratoc System Inc 1196 Hytec Electronics Ltd 1197 Gage Applied Sciences, Inc. + 010c CompuScope 82G 8bit 2GS/s Analog Input Card 1198 Lambda Systems Inc 1199 Attachmate Corporation 119a Mind Share, Inc. @@ -3868,11 +4337,20 @@ 11a9 InnoSys Inc. 4240 AMCC S933Q Intelligent Serial Card 11aa Actel -11ab Galileo Technology Ltd. +# (formerly Galileo technologies) +11ab Marvell 0146 GT-64010/64010A System Controller + 4320 Yukon Gigabit Ethernet 10/100/1000Base-T Adapter 4611 GT-64115 System Controller 4620 GT-64120/64120A/64121A System Controller 4801 GT-48001 + 5040 MV88SX5040 4-port SATA I PCI-X Controller + 5041 MV88SX5041 4-port SATA I PCI-X Controller + 5080 MV88SX5080 8-port SATA I PCI-X Controller + 5081 MV88SX5081 8-port SATA I PCI-X Controller + 6041 MV88SX6041 4-port SATA II PCI-X Controller + 6081 MV88SX6081 8-port SATA II PCI-X Controller + 6460 MV64360/64361/64362 System Controller f003 GT-64010 Primary Image Piranha Image Generator 11ac Canon Information Systems Research Aust. 11ad Lite-On Communications Inc @@ -3886,6 +4364,7 @@ 11ad c001 LNE100TX [ver 2.0] 11ae Aztech System Ltd 11af Avid Technology Inc. + 0001 [Cinema] 11b0 V3 Semiconductor Inc. 0002 V300PSC 0292 V292PBC [Am29030/40 Bridge] @@ -3966,6 +4445,7 @@ 0444 LT WinModem 0445 LT WinModem 8086 2203 PRO/100+ MiniPCI (probably an Ambit U98.003.C.00 combo card) + 8086 2204 PRO/100+ MiniPCI on Armada E500 0446 LT WinModem 0447 LT WinModem 0448 WinModem 56k @@ -4011,6 +4491,7 @@ 0461 V90 WildWire Modem 0462 V90 WildWire Modem 0480 Venus Modem (V90, 56KFlex) + 048c V.92 56K WinModem 5801 USB 5802 USS-312 USB Controller # 4 port PCI USB Controller made by Agere (formely Lucent) @@ -4047,6 +4528,7 @@ 11d2 Intercom Inc. 11d3 Trancell Systems Inc 11d4 Analog Devices + 1535 Blackfin BF535 processor 1805 SM56 PCI modem 1889 AD1889 sound chip 11d5 Ikon Corporation @@ -4107,7 +4589,7 @@ 11f6 2011 RL100-ATX 2201 ReadyLink 100TX (Winbond W89C840) 11f6 2011 ReadyLink 100TX - 9881 RL100TX + 9881 RL100TX Fast Ethernet 11f7 Scientific Atlanta 11f8 PMC-Sierra Inc. 7375 PM7375 [LASAR-155 ATM SAR] @@ -4117,18 +4599,28 @@ 11fc Silicon Magic 11fd High Street Consultants 11fe Comtrol Corporation - 0001 RocketPort 8 Oct - 0002 RocketPort 8 Intf - 0003 RocketPort 16 Intf - 0004 RocketPort 32 Intf - 0005 RocketPort Octacable - 0006 RocketPort 8J - 0007 RocketPort 4-port - 0008 RocketPort 8-port - 0009 RocketPort 16-port - 000a RocketPort Plus Quadcable - 000b RocketPort Plus Octacable - 000c RocketPort 8-port Modem + 0001 RocketPort 32 port w/external I/F + 0002 RocketPort 8 port w/external I/F + 0003 RocketPort 16 port w/external I/F + 0004 RocketPort 4 port w/quad cable + 0005 RocketPort 8 port w/octa cable + 0006 RocketPort 8 port w/RJ11 connectors + 0007 RocketPort 4 port w/RJ11 connectors + 0008 RocketPort 8 port w/ DB78 SNI (Siemens) connector + 0009 RocketPort 16 port w/ DB78 SNI (Siemens) connector + 000a RocketPort Plus 4 port + 000b RocketPort Plus 8 port + 000c RocketModem 6 port + 000d RocketModem 4-port + 000e RocketPort Plus 2 port RS232 + 000f RocketPort Plus 2 port RS422 + 0801 RocketPort UPCI 32 port w/external I/F + 0802 RocketPort UPCI 8 port w/external I/F + 0803 RocketPort UPCI 16 port w/external I/F + 0805 RocketPort UPCI 8 port w/octa cable + 080c RocketModem III 8 port + 080d RocketModem III 4 port + 0903 RocketPort Compact PCI 16 port w/external I/F 8015 RocketPort 4-port UART 16954 11ff Scion Corporation 1200 CSS Corporation @@ -4186,6 +4678,14 @@ 1025 1016 Travelmate 612 TX 6972 OZ6912 Cardbus Controller 1179 0001 Magnia Z310 + 7110 OZ711Mx MultiMediaBay Accelerator + 7112 OZ711EC1/M1 SmartCardBus MultiMediaBay Controller + 7113 OZ711EC1 SmartCardBus Controller + 7114 OZ711M1 SmartCardBus MultiMediaBay Controller + 71e2 OZ711E2 SmartCardBus Controller + 7212 OZ711M2 SmartCardBus MultiMediaBay Controller + 7213 OZ6933E CardBus Controller + 7223 OZ711M3 SmartCardBus MultiMediaBay Controller 1218 Hybricon Corp. 1219 First Virtual Corporation 121a 3Dfx Interactive, Inc. @@ -4228,6 +4728,7 @@ 121a 0061 Voodoo3 3500 TV (PAL) 121a 0062 Voodoo3 3500 TV (SECAM) 0009 Voodoo 4 / Voodoo 5 + 121a 0003 Voodoo5 PCI 5500 121a 0009 Voodoo5 AGP 5500/6000 0057 Voodoo 3/3000 [Avenger] 121b Advanced Telecommunications Modules @@ -4253,6 +4754,7 @@ 1224 Interactive Images 1225 Power I/O, Inc. 1227 Tech-Source + 0006 Raptor GFX 8P 1228 Norsk Elektro Optikk A/S 1229 Data Kinesis Inc. 122a Integrated Telecom @@ -4314,6 +4816,7 @@ 0e00 Fritz!PCI v2.0 ISDN 1100 C2 ISDN 1200 T1 ISDN + 2700 Fritz!Card DSL SL 1245 A.P.D., S.A. 1246 Dipix Technologies, Inc. 1247 Xylon Research, Inc. @@ -4350,10 +4853,13 @@ 1258 Gilbarco, Inc. 1259 Allied Telesyn International 2560 AT-2560 Fast Ethernet Adapter (i82557B) + a117 RTL81xx Fast Ethernet + a120 21x4x DEC-Tulip compatible 10/100 Ethernet 125a ABB Power Systems 125b Asix Electronics Corporation - 1400 ALFA GFC2204 + 1400 ALFA GFC2204 Fast Ethernet 125c Aurora Technologies, Inc. + 0101 Saturn 4520P 0640 Aries 16000P 125d ESS Technology 0000 ES336H Fax Modem (Early Model) @@ -4395,13 +4901,16 @@ 14fe 0429 ES56-PI Data Fax Modem 125e Specialvideo Engineering SRL 125f Concurrent Technologies, Inc. -1260 Harris Semiconductor +1260 Intersil Corporation 3873 Prism 2.5 Wavelan chipset 1186 3501 DWL-520 Wireless PCI Adapter + 1186 3700 DWL-520 Wireless PCI Adapter, Rev E1 1668 0414 HWP01170-01 802.11b PCI Wireless Adapter + 16a5 1601 AIR.mate PC-400 PCI Wireless LAN Adapter 1737 3874 WMP11 Wireless 802.11b PCI Adapter 8086 2513 Wireless 802.11b MiniPCI Adapter - 3890 D-Links DWL-g650 A1 + 3890 Intersil ISL3890 [Prism GT/Prism Duette] + 17cf 0014 Ovislink WL-5400PCM, Prism GT 8130 HMP8130 NTSC/PAL Video Decoder 8131 HMP8131 NTSC/PAL Video Decoder 1261 Matsushita-Kotobuki Electronics Industries, Ltd. @@ -4421,9 +4930,12 @@ 126a Lexmark International, Inc. 126b Adax, Inc. 126c Northern Telecom + 1211 10/100BaseTX [RTL81xx] + 126c 802.11b Wireless Ethernet Adapter 126d Splash Technology, Inc. 126e Sumitomo Metal Industries, Ltd. 126f Silicon Motion, Inc. + 0501 SM501 VoyagerGX 0710 SM710 LynxEM 0712 SM712 LynxEM+ 0720 SM720 Lynx3DM @@ -4498,6 +5010,7 @@ 1274 2000 Creative Sound Blaster AudioPCI128 1274 2003 Creative SoundBlaster AudioPCI 128 1274 5880 Creative Sound Blaster AudioPCI128 + 1274 8001 Sound Blaster 16PCI 4.1ch 1458 a000 5880 AudioPCI On Motherboard 6OXET 1462 6880 5880 AudioPCI On Motherboard MS-6188 1.00 270f 2001 5880 AudioPCI On Motherboard 6CTR @@ -4637,12 +5150,14 @@ 1281 Yokogawa Electric Corporation 1282 Davicom Semiconductor, Inc. 9009 Ethernet 100/10 MBit - 9100 Ethernet 100/10 MBit - 9102 Ethernet 100/10 MBit + 9100 21x4x DEC-Tulip compatible 10/100 Ethernet + 9102 21x4x DEC-Tulip compatible 10/100 Ethernet 9132 Ethernet 100/10 MBit 1283 Integrated Technology Express, Inc. 673a IT8330G + 8212 IT/ITE8212 Dual channel ATA RAID controller (PCI version seems to be IT8212, embedded seems to be ITE8212) 8330 IT8330G + 8872 IT8874F PCI Dual Serial Port Controller 8888 IT8888F PCI to ISA Bridge with SMB 8889 IT8889F PCI to ISA Bridge e886 IT8330G @@ -4688,6 +5203,7 @@ 12a1 Simpact Associates, Inc. 12a2 Newgen Systems Corporation 12a3 Lucent Technologies + 8105 T8105 H100 Digital Switch 12a4 NTT Electronics Technology Company 12a5 Vision Dynamics Ltd. 12a6 Scalable Networks, Inc. @@ -4706,6 +5222,7 @@ 0002 AceNIC Gigabit Ethernet (Copper) 10a9 8002 Acenic Gigabit Ethernet 12ae 0002 Gigabit Ethernet-T (3C986-T) + 00fa Farallon PN9100-T Gigabit Ethernet 12af TDK USA Corp 12b0 Jorge Scientific Corp 12b1 GammaLink @@ -4807,6 +5324,7 @@ 12d9 Aculab PLC 0002 PCI Prosody 0004 cPCI Prosody + 0005 Aculab E1/T1 PCI card 12da True Time Inc. 12db Annapolis Micro Systems, Inc 12dc Symicron Computer Communication Ltd. @@ -4889,7 +5407,8 @@ 1304 Juniper Networks 1305 Netphone, Inc 1306 Duet Technologies -1307 Computer Boards +# Formerly ComputerBoards +1307 Measurement Computing 0001 PCI-DAS1602/16 000b PCI-DIO48H 000c PCI-PDISO8 @@ -4926,6 +5445,7 @@ 0037 PCI-DAS64/M3/16 004c PCI-DAS1000 004d PCI-QUAD04 + 0052 PCI-DAS4020/12 1308 Jato Technologies Inc. 0001 NetCelerator Adapter 1308 0001 NetCelerator Adapter @@ -4942,11 +5462,15 @@ 1313 Yaskawa Electric Co. 1316 Teradyne Inc 1317 Linksys - 0981 Fast Ethernet 10/100 - 0985 Network Everywhere Fast Ethernet 10/100 model NC100 - 1985 Fast Ethernet 10/100 + 0981 21x4x DEC-Tulip compatible 10/100 Ethernet + 0985 NC100 Network Everywhere Fast Ethernet 10/100 + 1985 21x4x DEC-Tulip compatible 10/100 Ethernet + 2850 HSP MicroModem 56 + 8201 [ADMtek] SP906B_V2 Wireless LAN adapter + 1317 8201 SMC2635W 802.11b (11mbps) wireless lan pcmcia (cardbus) card + 9511 21x4x DEC-Tulip compatible 10/100 Ethernet 1318 Packet Engines Inc. - 0911 PCI Ethernet Adapter + 0911 GNIC-II PCI Gigabit Ethernet [Hamachi] 1319 Fortemedia, Inc 0801 Xwave QS3000A [FM801] 0802 Xwave QS3000A [FM801 game port] @@ -5083,6 +5607,7 @@ 01c0 SSCLP-200/300 135d ABB Network Partner AB 135e Sealevel Systems Inc + 5101 Route 56.PCI - Multi-Protocol Serial Interface (Zilog Z16C32) 7101 Single Port RS-232/422/485/530 7201 Dual Port RS-232/422/485 Interface 7202 Dual Port RS-232 Interface @@ -5109,6 +5634,7 @@ 136f Applied Magic Inc 1370 ATL Products 1371 CNet Technology Inc + 434e GigaCard Network Adapter 1373 Silicon Vision Inc 1374 Silicom Ltd 1375 Argosystems Inc @@ -5117,6 +5643,7 @@ 1378 Telemann Co. Ltd 1379 Asahi Kasei Microsystems Co Ltd 137a Mark of the Unicorn Inc + 0001 PCI-324 Audiowire Interface 137b PPT Vision 137c Iwatsu Electric Co Ltd 137d Dynachip Corporation @@ -5125,15 +5652,15 @@ 1380 Sanritz Automation Co Ltd 1381 Brains Co. Ltd 1382 Marian - Electronic & Software + 2088 Marc-8 MIDI 8 channel audio card 1383 Controlnet Inc 1384 Reality Simulation Systems Inc 1385 Netgear 4100 802.11b Wireless Adapter (MA301) 4105 MA311 802.11b wireless adapter - 620a GA620 + 620a GA620 Gigabit Ethernet 622a GA622 - 630a GA630 - f311 FA311 + 630a GA630 Gigabit Ethernet 1386 Video Domain Technologies 1387 Systran Corp 1388 Hitachi Information Technology Co Ltd @@ -5150,6 +5677,7 @@ 1392 Medialight Inc 1393 Moxa Technologies Co Ltd 1040 Smartio C104H/PCI + 1141 Industrio CP-114 1680 Smartio C168H/PCI 2040 Intellio CP-204J 2180 Intellio C218 Turbo PCI @@ -5229,6 +5757,9 @@ 13c4 Phase Metrics 13c5 Alphi Technology Corp 13c6 Condor Engineering Inc + 0520 CEI-520 A429 Card + 0620 CEI-620 A429 Card + 0820 CEI-820 A429 Card 13c7 Blue Chip Technology Ltd 13c8 Apptech Inc 13c9 Eaton Corporation @@ -5239,11 +5770,13 @@ 13ce Cocom A/S 13cf Studio Audio & Video Ltd 13d0 Techsan Electronics Co Ltd -# http://www.b2c2inc.com/products/pc-specs.html - 2103 B2C2 Sky2PC PCI [SkyStar2] + 2103 B2C2 FlexCopII DVB chip / Technisat SkyStar2 DVB card + 2200 B2C2 FlexCopIII DVB chip / Technisat SkyStar2 DVB card 13d1 Abocom Systems Inc ab02 ADMtek Centaur-C rev 17 [D-Link DFE-680TX] CardBus Fast Ethernet Adapter + ab03 21x4x DEC-Tulip compatible 10/100 Ethernet ab06 RTL8139 [FE2000VX] CardBus Fast Ethernet Attached Port Adapter + ab08 21x4x DEC-Tulip compatible 10/100 Ethernet 13d2 Shark Multimedia Inc 13d3 IMC Networks 13d4 Graphics Microsystems Inc @@ -5285,6 +5818,7 @@ 1401 Zentai Fibre Channel Adapter 13f5 Kansai Electric Co. Ltd 13f6 C-Media Electronics Inc + 0011 CMI8738 0100 CM8338A 13f6 ffff CMI8338/C3DX PCI Audio Device 0101 CM8338B @@ -5305,6 +5839,9 @@ 13fc Computer Peripherals International 13fd Micro Science Inc 13fe Advantech Co. Ltd + 1600 PCI-1612 4-port RS-232/422/485 PCI Communication Card + 1752 PCI-1752 + 1754 PCI-1754 1756 PCI-1756 13ff Silicon Spice Inc 1400 Artx Inc @@ -5319,9 +5856,15 @@ 0100 Lava Dual Serial 0101 Lava Quatro A 0102 Lava Quatro B + 0120 Quattro-PCI A + 0121 Quattro-PCI B + 0180 Lava Octo A + 0181 Lava Octo B 0200 Lava Port Plus 0201 Lava Quad A 0202 Lava Quad B + 0220 Lava Quattro PCI Ports A/B + 0221 Lava Quattro PCI Ports C/D 0500 Lava Single Serial 0600 Lava Port 650 8000 Lava Parallel @@ -5342,6 +5885,7 @@ 1411 Ikos Systems Inc 1412 IC Ensemble Inc 1712 ICE1712 [Envy24] + 1412 d638 M-Audio Delta 410 1724 ICE1724 [Envy24HT] 1413 Addonics 1414 Microsoft Corporation @@ -5382,10 +5926,12 @@ 142c Minton Optic Industry Co Ltd 142d Pix stream Inc 142e Vitec Multimedia + 4020 VM2-2 [Video Maker 2] MPEG1/2 Encoder 142f Radicom Research Inc 1430 ITT Aerospace/Communications Division 1431 Gilat Satellite Networks 1432 Edimax Computer Co. + 9130 RTL81xx Fast Ethernet 1433 Eltec Elektronik GmbH 1435 Real Time Devices US Inc. 1436 CIS Technology Inc @@ -5443,6 +5989,10 @@ 1460 DYNARC INC 1461 Avermedia Technologies Inc 1462 Micro-Star International Co., Ltd. + 8725 NVIDIA NV25 [GeForce4 Ti 4600] VGA Adapter +# MSI G4Ti4800, 128MB DDR SDRAM, TV-Out, DVI-I + 9000 NVIDIA NV28 [GeForce4 Ti 4800] VGA Adapter + 9119 NVIDIA NV31 [GeForce FX 5600XT] VGA Adapter 1463 Fast Corporation 1464 Interactive Circuits & Systems Ltd 1465 GN NETTEST Telecom DIV. @@ -5533,7 +6083,7 @@ 14b5 Creamware GmBH 0200 Scope 0300 Pulsar - 0400 Pulsar2 + 0400 PulsarSRB 0600 Pulsar2 0800 DSP-Board 0900 DSP-Board @@ -5548,8 +6098,9 @@ 0340 PC4800 0350 PC4800 4500 PC4500 - 4800 PC4800 + 4800 Cisco Aironet 340 802.11b Wireless LAN Adapter/Aironet PC4800 a504 Cisco Aironet Wireless 802.11b + a505 Cisco Aironet CB20a 802.11a Wireless LAN Adapter 14ba INTERNIX Inc. 14bb SEMTECH Corporation 14bc Globespan Semiconductor Inc. @@ -5558,6 +6109,7 @@ 14bf SPIDER Communications Inc. 14c0 COMPAL Electronics Inc 14c1 MYRICOM Inc. + 8043 Myrinet 2000 Scalable Cluster Interconnect 14c2 DTK Computer 14c3 MEDIATEK Corp. 14c4 IWASAKI Information Systems Co Ltd @@ -5598,11 +6150,10 @@ 14d7 Hirakawa Hewtech Corp 14d8 HOPF Elektronik GmBH 14d9 Alpha Processor Inc + 0010 AP1011 HyperTransport-PCI Bridge [Sturgeon] 14da National Aerospace Laboratories 14db AFAVLAB Technology Inc 2120 TK9902 - 2180 P028 - 2182 P030 14dc Amplicon Liveline Ltd 0000 PCI230 0001 PCI242 @@ -5649,6 +6200,10 @@ 0e11 009a NC7770 Gigabit Server Adapter (PCI-X, 10/100/1000-T) 0e11 00c1 NC6770 Gigabit Server Adapter (PCI-X, 1000-SX) 1028 0121 Broadcom BCM5701 1000Base-T + 103c 128a HP 1000Base-T (PCI) [A7061A] + 103c 128b HP 1000Base-SX (PCI) [A7073A] + 103c 12a4 HP Core Lan 1000Base-T + 103c 12c1 HP IOX Core Lan 1000Base-T [A7109AX] 10a9 8010 SGI IO9 Gigabit Ethernet (Copper) 10a9 8011 SGI Gigabit Ethernet (Copper) 10a9 8012 SGI Gigabit Ethernet (Fiber) @@ -5684,16 +6239,19 @@ 1166 1648 NetXtreme CIOB-E 1000Base-T 164d NetXtreme BCM5702FE Gigabit Ethernet 1653 NetXtreme BCM5705 Gigabit Ethernet + 1654 NetXtreme BCM5705_2 Gigabit Ethernet 165d NetXtreme BCM5705M Gigabit Ethernet + 165e NetXtreme BCM5705M_2 Gigabit Ethernet 1696 NetXtreme BCM5782 Gigabit Ethernet + 103c 12bc HP d530 CMT (DG746A) 14e4 000d NetXtreme BCM5782 1000Base-T 169c NetXtreme BCM5788 Gigabit Ethernet - 16a6 NetXtreme BCM5702 Gigabit Ethernet + 16a6 NetXtreme BCM5702X Gigabit Ethernet 0e11 00bb NC7760 Gigabit Server Adapter (PCI-X, 10/100/1000-T) 1028 0126 BCM5702 1000Base-T 14e4 000c BCM5702 1000Base-T 14e4 8009 BCM5702 1000Base-T - 16a7 NetXtreme BCM5703 Gigabit Ethernet + 16a7 NetXtreme BCM5703X Gigabit Ethernet 0e11 00ca NC7771 Gigabit Server Adapter (PCI-X, 10,100,1000-T) 0e11 00cb NC7781 Gigabit Server Adapter (PCI-X, 10,100,1000-T) 14e4 0009 NetXtreme BCM5703 1000Base-T @@ -5702,25 +6260,35 @@ 14e4 800a NetXtreme BCM5703 1000Base-T 16a8 NetXtreme BCM5704S Gigabit Ethernet 10b7 2001 3C998-SX Dual Port 1000-SX PCI-X - 16c6 NetXtreme BCM5702 Gigabit Ethernet + 16c6 NetXtreme BCM5702A3 Gigabit Ethernet 10b7 1100 3C1000B-T 10/100/1000 PCI 14e4 000c BCM5702 1000Base-T 14e4 8009 BCM5702 1000Base-T 16c7 NetXtreme BCM5703 Gigabit Ethernet + 103c 12c3 HP Combo FC/GigE-SX [A9782A] + 103c 12ca HP Combo FC/GigE-T [A9784A] 14e4 0009 NetXtreme BCM5703 1000Base-T 14e4 000a NetXtreme BCM5703 1000Base-SX +# it's 5705, 5707 was a typo, sorry + 170c BCM5705M 10/100/1000Base T + 170d NetXtreme BCM5901 100Base-TX + 170e NetXtreme BCM5901 100Base-TX 4210 BCM4210 iLine10 HomePNA 2.0 4211 BCM4211 iLine10 HomePNA 2.0 + V.90 56k modem 4212 BCM4212 v.90 56k modem 4301 BCM4301 802.11b 4320 BCM94306 802.11g + 1028 0001 TrueMobile 1300 WLAN Mini-PCI Card 1737 4320 WPC54G + 4324 BCM4309 802.11a/b/g + 1028 0001 Truemobile 1400 4401 BCM4401 100Base-T 1043 80a8 A7V8X motherboard 4402 BCM4402 Integrated 10/100BaseT 4410 BCM4413 iLine32 HomePNA 2.0 4411 BCM4413 V.90 56k modem 4412 BCM4413 10/100BaseT + 5690 BCM5690 12-port Multi-Layer Gigabit Ethernet Switch 5820 BCM5820 Crypto Accelerator 5821 BCM5821 Crypto Accelerator 14e5 Pixelfusion Ltd @@ -5730,6 +6298,7 @@ 14e9 GARNETS System CO Ltd 14ea Planex Communications, Inc ab06 FNW-3603-TX CardBus Fast Ethernet + ab07 RTL81xx RealTek Ethernet 14eb SEIKO EPSON Corp 14ec ACQIRIS 14ed DATAKINETICS Ltd @@ -5872,6 +6441,7 @@ 13e0 8d85 Compaq Stinger 14f1 2004 Dynalink 56PMi 8234 RS8234 ATM SAR Controller [ServiceSAR Plus] + 8800 Winfast TV2000 XP 14f2 MOBILITY Electronics 0120 EV1000 bridge 0121 EV1000 Parallel port @@ -5894,6 +6464,7 @@ 14fe ARCHTEK TELECOM Corp 14ff TWINHEAD INTERNATIONAL Corp 1500 DELTA Electronics, Inc + 1360 RTL81xx RealTek Ethernet 1501 BANKSOFT CANADA Ltd 1502 MITSUBISHI ELECTRIC LOGISTICS SUPPORT Co Ltd 1503 KAWASAKI LSI USA Inc @@ -5926,8 +6497,10 @@ 1514 TFL LAN Inc 1515 Advent design 1516 MYSON Technology Inc + 0800 MTD-8xx 100/10M Ethernet PCI Adapter 0803 SURECOM EP-320X-S 100/10M Ethernet PCI Adapter 1320 10bd SURECOM EP-320X-S 100/10M Ethernet PCI Adapter + 0891 MTD-8xx 100/10M Ethernet PCI Adapter 1517 ECHOTEK Corp 1518 PEP MODULAR Computers GmbH 1519 TELEFON AKTIEBOLAGET LM Ericsson @@ -5952,12 +6525,19 @@ 1522 0600 RockForce+ 2 Port V.90 Data/Fax/Voice Modem 1522 0700 RockForce+ 4 Port V.90 Data/Fax/Voice Modem 1522 0800 RockForceOCTO+ 8 Port V.92/V.44 Data/Fax/Voice Modem + 1522 0c00 RockForceDUO+ 2 Port V.92/V.44 Data, V.34 Super-G3 Fax, Voice Modem + 1522 0d00 RockForceQUATRO+ 4 Port V.92/V.44 Data, V.34 Super-G3 Fax, Voice Modem +# this is a correction to a recent entry. 1522:0E00 should be 1522:1D00 + 1522 1d00 RockForceOCTO+ 8 Port V.92/V.44 Data, V.34 Super-G3 Fax, Voice Modem 1523 MUSIC Semiconductors 1524 ENE Technology Inc + 0510 CB710 Memory Card Reader Controller 1211 CB1211 Cardbus Controller 1225 CB1225 Cardbus Controller 1410 CB1410 Cardbus Controller + 1411 CB710 Cardbus Controller 1420 CB1420 Cardbus Controller + 1421 CB720 Cardbus Controller 1525 IMPACT Technologies 1526 ISS, Inc 1527 SOLECTRON @@ -5977,9 +6557,11 @@ 1535 EVERGREEN Technologies Inc 1537 DATALEX COMMUNCATIONS 1538 ARALION Inc + 0303 ARS106S Ultra ATA 133/100/66 Host Controller 1539 ATELIER INFORMATIQUES et ELECTRONIQUE ETUDES S.A. 153a ONO SOKKI 153b TERRATEC Electronic GmbH + 1144 Aureon 5.1 153c ANTAL Electronic 153d FILANET Corp 153e TECHWELL Inc @@ -6123,6 +6705,7 @@ 15ab Bluesteel Networks Inc 15ac North Atlantic Instruments 15ad VMWare Inc + 0405 [VMWare SVGA II] PCI Display Adapter 0710 Virtual SVGA 15ae Amersham Pharmacia Biotech 15b0 Zoltrix International Ltd @@ -6130,6 +6713,9 @@ 15b2 Mosaid Technologies Inc 15b3 Mellanox Technology 5274 MT21108 InfiniBridge + 5a44 MT23108 InfiniHost + 5a45 MT23108 InfiniHost (Tavor) + 5a46 MT23108 PCI Bridge 15b4 CCI/TRIAD 15b5 Cimetrics Inc 15b6 Texas Memory Systems Inc @@ -6139,7 +6725,9 @@ 15ba Impacct Technology Corp 15bb Portwell Inc 15bc Agilent Technologies - 2929 E2929A PCI/PCI-X Bus Analyzer + 2922 64 Bit, 133MHz PCI-X Exerciser & Protocol Checker + 2928 64 Bit, 66MHz PCI Exerciser & Analyzer + 2929 64 Bit, 133MHz PCI-X Analyzer & Exerciser 15bd DFI Inc 15be Sola Electronics 15bf High Tech Computer Corp (HTC) @@ -6149,6 +6737,7 @@ 15c3 Taiwan Mycomp Co Ltd 15c4 EVSX Inc 15c5 Procomp Informatics Ltd + 8010 1394b - 1394 Firewire 3-Port Host Adapter Card 15c6 Technical University of Budapest 15c7 Tateyama System Laboratory Co Ltd 0349 Tateyama C-PCI PLC/NC card Rev.01A @@ -6187,9 +6776,12 @@ 15e8 National Datacomm Corp 0130 Wireless PCI Card 15e9 Pacific Digital Corp + 1841 ADMA-100 DiscStaQ ATA Controller 15ea Tokyo Denshi Sekei K.K. 15eb Drsearch GmbH 15ec Beckhoff GmbH + 3101 FC3101 Profibus DP 1 Channel PCI + 5102 FC5102 15ed Macrolink Inc 15ee In Win Development Inc 15ef Intelligent Paradigm Inc @@ -6223,11 +6815,13 @@ 1619 FarSite Communications Ltd 0400 FarSync T2P (2 port X.21/V.35/V.24) 0440 FarSync T4P (4 port X.21/V.35/V.24) +1626 TDK Semiconductor Corp. + 8410 RTL81xx Fast Ethernet 1629 Kongsberg Spacetec AS 1003 Format synchronizer v3.0 2002 Fast Universal Data Output 1638 Standard Microsystems Corp [SMC] - 1100 SMC2602W EZConnect / Addtron AWA-100 + 1100 SMC2602W EZConnect / Addtron AWA-100 / Eumitcom PCI WL11000 163c Smart Link Ltd. 3052 SmartLink SmartPCI562 56K Modem 5449 SmartPCI561 Modem @@ -6239,27 +6833,69 @@ 165d Hsing Tech. Enterprise Co., Ltd. 1661 Worldspace Corp. 1668 Actiontec Electronics Inc + 0100 Mini-PCI bridge +# Formerly SiByte, Inc. +166d Broadcom Corporation + 0001 SiByte BCM1125/1125H/1250 System-on-a-Chip PCI + 0002 SiByte BCM1125H/1250 System-on-a-Chip HyperTransport 1681 Hercules +# More specs, more accurate desc. + 0010 Hercules 3d Prophet II Ultra 64MB [ 350 MHz NV15BR core, 128-bit DDR @ 460 MHz, 1.5v AGP4x ] +1688 CastleNet Technology Inc. + 1170 WLAN 802.11b card +168c Atheros Communications, Inc. + 0007 AR5000 802.11a Wireless Adapter + 0011 AR5210 802.11a NIC + 0012 AR5211 802.11ab NIC + 0013 AR5212 802.11abg NIC + 1186 3202 D-link DWL-G650 B3 Wireless cardbus adapter + 1186 3203 DWL-G520 Wireless PCI Adapter + 1186 3a94 C54C Wireless 801.11g cardbus + 168c 0013 WG511T Wireless CardBus Adapter + 168c 1025 DWL-G650B2 Wireless CardBus Adapter + 1014 AR5212 802.11abg NIC 16ab Global Sun Technology Inc + 1100 GL24110P + 1101 PLX9052 PCMCIA-to-PCI Wireless LAN 1102 PCMCIA-to-PCI Wireless Network Bridge +16ae Safenet Inc + 1141 SafeXcel-1141 16be Creatix Polymedia GmbH 16ca CENATEK Inc 0001 Rocket Drive DL +16cd Densitron Technologies +# www.pikatechnologies.com +16df PIKA Technologies Inc. 16ec U.S. Robotics + 00ff USR997900 10/100 Mbps PCI Network Card 3685 Wireless Access PCI Adapter Model 022415 16f6 VideoTele.com, Inc. +# www.internetmachines.com +1702 Internet Machines Corporation (IMC) 1705 Digital First, Inc. -170b NetOctave Inc +170b NetOctave + 0100 NSP2000-SSL crypto accelerator 170c YottaYotta Inc. 172a Accelerated Encryption 1737 Linksys + 1032 Gigabit Network Adapter + 1737 0015 EG1032 v2 Instant Gigabit Network Adapter + 1064 Gigabit Network Adapter + 1737 0016 EG1064 v2 Instant Gigabit Network Adapter + ab08 21x4x DEC-Tulip compatible 10/100 Ethernet + ab09 21x4x DEC-Tulip compatible 10/100 Ethernet 173b Altima (nee Broadcom) 03e8 AC1000 Gigabit Ethernet + 03e9 AC1001 Gigabit Ethernet 03ea AC9100 Gigabit Ethernet 173b 0001 AC1002 + 03eb AC1003 Gigabit Ethernet 1743 Peppercon AG 8139 ROL/F-100 Fast Ethernet Adapter with ROL +1749 RLX Technologies 174b PC Partner Limited +174d WellX Telecom SA +175c AudioScience Inc 175e Sanera Systems, Inc. 1787 Hightech Information System Ltd. # also used by Struck Innovative Systeme for joint developments @@ -6271,21 +6907,48 @@ 0005 PROFIBUS 0006 AMCC HOTlink 1799 Belkin + 6001 Wireless PCI Card - F5D6001 + 6020 Wireless PCMCIA Card - F5D6020 + 6060 Wireless PDA Card - F5D6060 17af Hightech Information System Ltd. +17b3 Hawking Technologies + ab08 PN672TX 10/100 Ethernet +17b4 Indra Networks, Inc. + 0011 WebEnhance 100 GZIP Compression Card +17c0 Wistron Corp. +17c2 Newisys, Inc. 17cc NetChip Technology, Inc 2280 USB 2.0 +# S2io ships 10Gb PCI-X Ethernet adapters www.s2io.com +17d5 S2io Inc. 1813 Ambient Technologies Inc 4000 HaM controllerless modem 16be 0001 V9x HAM Data Fax Modem 4100 HaM plus Data Fax Modem 16be 0002 V9x HAM 1394 +1814 RaLink + 0101 Wireless PCI Adpator RT2400 / RT2460 + 0201 Ralink RT2500 802.11 Cardbus Reference Card +1830 Credence Systems Corporation 1851 Microtune, Inc. 1852 Anritsu Corp. +1867 Topspin Communications + 5a44 MT23108 PCI-X HCA + 5a45 MT23108 PCI-X HCA flash recovery + 5a46 MT23108 PCI-X HCA bridge 1888 Varisys Ltd 0301 VMFX1 FPGA PMC module 0601 VSM2 dual PMC carrier 0710 VS14x series PowerPC PCI board 0720 VS24x series PowerPC PCI board +# found e.g. on KNC DVB-S card +1894 KNC One +18a1 Astute Networks Inc. +18ca XGI - Xabre Graphics Inc + 0040 Volari V8 +18e6 MPL AG + 0001 OSCI [Octal Serial Communication Interface] +18fb Resilience Corporation 1a08 Sierra semiconductor 0000 SC15064 1b13 Jaton Corp @@ -6321,7 +6984,10 @@ 0021 HB6 Universal PCI-PCI bridge (non-transparent mode) 4c53 1050 CT7 mainboard 4c53 1080 CT8 mainboard + 4c53 10a0 CA3/CR3 mainboard 4c53 3010 PPCI mezzanine (32-bit PMC) + 4c53 3011 PPCI mezzanine (64-bit PMC) + 0026 HB2 PCI-PCI Bridge 101a E.Band [AudioTrak Inca88] 101b E.Band [AudioTrak Inca88] 8011 VXPro II Chipset @@ -6356,7 +7022,17 @@ 3d3d 0121 Oxygen VX1 000c GLINT R3 [Oxygen VX1] 3d3d 0144 Oxygen VX1-4X AGP [Permedia 4] + 000d GLint R4 rev A + 0011 GLint R4 rev B + 0012 GLint R5 rev A + 0013 GLint R5 rev B + 0020 VP10 visual processor +# P10 generic II + 0022 VP10 visual processor + 0024 VP9 visual processor 0100 Permedia II 2D+3D + 07a1 Wildcat III 6210 + 07a3 Wildcat IV 7210 1004 Permedia 3d04 Permedia ffff Glint VGA @@ -6379,11 +7055,16 @@ 4033 Addtron Technology Co, Inc. 1360 RTL8139 Ethernet 4143 Digital Equipment Corp +4144 Alpha Data 416c Aladdin Knowledge Systems 0100 AladdinCARD 0200 CPC 4444 Internext Compression Inc + 0016 iTVC16 (CX23416) MPEG-2 Encoder + 0070 4009 WinTV PVR 250 0803 iTVC15 MPEG-2 Encoder + 0070 4000 WinTV PVR-350 + 0070 4001 WinTV PVR-250 4468 Bridgeport machines 4594 Cogetec Informatique Inc 45fb Baldor Electric Company @@ -6399,6 +7080,11 @@ 4b10 Buslogic Inc. 4c48 LUNG HWA Electronics 4c53 SBS Technologies + 0000 PLUSTEST device + 4c53 3000 PLUSTEST card (PC104+) + 4c53 3001 PLUSTEST card (PMC) + 0001 PLUSTEST-MM device + 4c53 3002 PLUSTEST-MM card (PMC) 4ca1 Seanix Technology Inc 4d51 MediaQ Inc. 0200 MQ-200 @@ -6576,6 +7262,7 @@ 0003 TURBOstor HFP-832 [HiPPI NIC] 5654 VoiceTronix Pty Ltd 5700 Netpower +5851 Exacq Technologies 6356 UltraStor 6374 c't Magazin für Computertechnik 6773 GPPCI @@ -6589,11 +7276,37 @@ 8008 Quancom Electronic GmbH 0010 WDOG1 [PCI-Watchdog 1] 0011 PWDOG2 [PCI-Watchdog 2] +# Wrong ID used in subsystem ID of AsusTek PCI-USB2 PCI card. +807d Asustek Computer, Inc. 8086 Intel Corp. 0007 82379AB 0008 Extended Express System Support Controller - 0039 21145 + 0008 1000 WorldMark 4300 INCA ASIC + 0039 21145 Fast Ethernet 0122 82437FX + 0326 PCI Bridge Hub I/OxAPIC Interrupt Controller A + 0327 PCI Bridge Hub I/OxAPIC Interrupt Controller B + 0329 PCI Bridge Hub A + 032a PCI Bridge Hub B + 032c PCI Bridge Hub +# A-segment bridge + 0330 80332 [Dobson] I/O processor +# A-segment IOAPIC + 0331 80332 [Dobson] I/O processor +# B-segment bridge + 0332 80332 [Dobson] I/O processor +# B-segment IOAPIC + 0333 80332 [Dobson] I/O processor +# Address Translation Unit (ATU) + 0334 80332 [Dobson] I/O processor +# PCI-X bridge + 0335 80331 [Lindsay] I/O processor +# Address Translation Unit (ATU) + 0336 80331 [Lindsay] I/O processor +# A-segment bridge + 0340 41210 [Lanai] Serial to Parallel PCI Bridge +# B-segment bridge + 0341 41210 [Lanai] Serial to Parallel PCI Bridge 0482 82375EB 0483 82424ZX [Saturn] 0484 82378IB [SIO ISA Bridge] @@ -6625,28 +7338,84 @@ 8086 1004 PRO/1000 T Server Adapter 8086 2004 PRO/1000 T Server Adapter 1008 82544EI Gigabit Ethernet Controller (Copper) + 1014 0269 iSeries 1000/100/10 Ethernet Adapter + 1028 011c PRO/1000 XT Network Connection 8086 1107 PRO/1000 XT Server Adapter 8086 2107 PRO/1000 XT Server Adapter 8086 2110 PRO/1000 XT Server Adapter + 8086 3108 PRO/1000 XT Network Connection 1009 82544EI Gigabit Ethernet Controller (Fiber) + 1014 0268 iSeries Gigabit Ethernet Adapter 8086 1109 PRO/1000 XF Server Adapter 8086 2109 PRO/1000 XF Server Adapter 100c 82544GC Gigabit Ethernet Controller (Copper) 8086 1112 PRO/1000 T Desktop Adapter 8086 2112 PRO/1000 T Desktop Adapter 100d 82544GC Gigabit Ethernet Controller (LOM) + 1028 0123 PRO/1000 XT Network Connection + 1079 891f 82544GC Based Network Connection + 4c53 1080 CT8 mainboard + 8086 110d 82544GC Based Network Connection 100e 82540EM Gigabit Ethernet Controller + 1014 0265 PRO/1000 MT Network Connection + 1014 0267 PRO/1000 MT Network Connection + 1014 026a PRO/1000 MT Network Connection + 107b 8920 PRO/1000 MT Desktop Adapter 8086 001e PRO/1000 MT Desktop Adapter 8086 002e PRO/1000 MT Desktop Adapter 100f 82545EM Gigabit Ethernet Controller (Copper) + 1014 0269 iSeries 1000/100/10 Ethernet Adapter + 1014 028e PRO/1000 MT Network Connection + 8086 1000 PRO/1000 MT Network Connection 8086 1001 PRO/1000 MT Server Adapter 1010 82546EB Gigabit Ethernet Controller (Copper) + 1014 027c PRO/1000 MT Dual Port Network Adapter + 18fb 7872 RESlink-X + 4c53 1080 CT8 mainboard + 4c53 10a0 CA3/CR3 mainboard 8086 1011 PRO/1000 MT Dual Port Server Adapter + 8086 101a PRO/1000 MT Dual Port Network Adapter 1011 82545EM Gigabit Ethernet Controller (Fiber) + 1014 0268 iSeries Gigabit Ethernet Adapter 8086 1002 PRO/1000 MF Server Adapter + 8086 1003 PRO/1000 MF Server Adapter (LX) 1012 82546EB Gigabit Ethernet Controller (Fiber) 8086 1012 PRO/1000 MF Dual Port Server Adapter + 1013 82541EI Gigabit Ethernet Controller (Copper) + 8086 0013 PRO/1000 MT Network Connection + 8086 1113 PRO/1000 MT Desktop Adapter + 1014 82541ER Gigabit Ethernet Controller 1015 82540EM Gigabit Ethernet Controller (LOM) + 1016 82540EP Gigabit Ethernet Controller (LOM) + 1014 052c PRO/1000 MT Mobile Connection + 1179 0001 PRO/1000 MT Mobile Connection + 8086 1016 PRO/1000 MT Mobile Connection + 1017 82540EP Gigabit Ethernet Controller (LOM) + 8086 1017 PR0/1000 MT Desktop Connection +# Update controller name from 82541EP to 82541EI + 1018 82541EI Gigabit Ethernet Controller + 8086 1018 PRO/1000 MT Desktop Adapter + 1019 82547EI Gigabit Ethernet Controller (LOM) + 1458 1019 GA-8IPE1000 Pro2 motherboard (865PE) + 8086 1019 PRO/1000 CT Desktop Connection + 101d 82546EB Gigabit Ethernet Controller + 8086 1000 PRO/1000 MT Quad Port Server Adapter + 101e 82540EP Gigabit Ethernet Controller (Mobile) + 1014 0549 PRO/1000 MT Mobile Connection + 1179 0001 PRO/1000 MT Mobile Connection + 8086 101e PRO/1000 MT Mobile Connection + 1026 82545GM Gigabit Ethernet Controller + 8086 1000 PRO/1000 MT Server Connection + 8086 1001 PRO/1000 MT Server Adapter + 8086 1002 PRO/1000 MT Server Adapter + 8086 1026 PRO/1000 MT Server Connection + 1027 82545GM Gigabit Ethernet Controller + 8086 1001 PRO/1000 MF Server Adapter(LX) + 8086 1002 PRO/1000 MF Server Adapter(LX) + 8086 1003 PRO/1000 MF Server Adapter(LX) + 8086 1027 PRO/1000 MF Server Adapter + 1028 82545GM Gigabit Ethernet Controller + 8086 1028 PRO/1000 MB Server Adapter 1029 82559 Ethernet Controller 1030 82559 InBusiness 10/100 1031 82801CAM (ICH3) PRO/100 VE (LOM) Ethernet Controller @@ -6666,6 +7435,7 @@ 1037 82801CAM (ICH3) Chipset Ethernet Controller 1038 82801CAM (ICH3) PRO/100 VM (KM) Ethernet Controller 1039 82801BD PRO/100 VE (LOM) Ethernet Controller + 1014 0267 NetVista A30p 103a 82801BD PRO/100 VE (CNR) Ethernet Controller 103b 82801BD PRO/100 VM (LOM) Ethernet Controller 103c 82801BD PRO/100 VM (CNR) Ethernet Controller @@ -6674,10 +7444,49 @@ 1040 536EP Data Fax Modem 16be 1040 V.9X DSP Data Fax Modem 1043 PRO/Wireless LAN 2100 3B Mini PCI Adapter - 1048 82597EX 10GbE Ethernet Controller + 8086 2527 MIM2000/Centrino + 1048 Intel(R) PRO/10GbE LR Server Adapter 8086 a01f PRO/10GbE LR Server Adapter 8086 a11f PRO/10GbE LR Server Adapter + 1050 82562EZ 10/100 Ethernet Controller + 1462 728c 865PE Neo2 (MS-6728) + 1051 82801EB/ER (ICH5/ICH5R) integrated LAN Controller 1059 82551QM Ethernet Controller +# Updated controller name from 82547EI to 82547GI + 1075 82547GI Gigabit Ethernet Controller + 8086 0075 PRO/1000 CT Network Connection + 8086 1075 PRO/1000 CT Network Connection +# Added PI to part name. Previous part name was 82541GI + 1076 82541GI/PI Gigabit Ethernet Controller + 8086 0076 PRO/1000 MT Network Connection + 8086 1076 PRO/1000 MT Network Connection + 8086 1176 PRO/1000 MT Desktop Adapter + 8086 1276 PRO/1000 MT Desktop Adapter +# Update controller name from 82541EI to 82541GI + 1077 82541GI Gigabit Ethernet Controller + 1179 0001 PRO/1000 MT Mobile Connection + 8086 0077 PRO/1000 MT Mobile Connection + 8086 1077 PRO/1000 MT Mobile Connection + 1078 82541EI Gigabit Ethernet Controller + 8086 1078 PRO/1000 MT Network Connection +# Update from mistaken ID of 82546EB + 1079 82546GB Gigabit Ethernet Controller + 103c 12a6 HP Dual Port 1000Base-T [A9900A] + 103c 12cf HP Core Dual Port 1000Base-T [AB352A] + 4c53 1090 Cx9 / Vx9 mainboard + 8086 0079 PRO/1000 MT Dual Port Network Connection + 8086 1079 PRO/1000 MT Dual Port Network Connection + 8086 1179 PRO/1000 MT Dual Port Network Connection + 8086 117a PRO/1000 MT Dual Port Server Adapter +# Update from mistaken ID of 82546EB + 107a 82546GB Gigabit Ethernet Controller + 103c 12a8 HP Dual Port 1000base-SX [A9899A] + 8086 107a PRO/1000 MF Dual Port Server Adapter + 8086 127a PRO/1000 MF Dual Port Server Adapter +# Update from mistaken ID of 82546EB + 107b 82546GB Gigabit Ethernet Controller + 8086 007b PRO/1000 MB Dual Port Server Connection + 8086 107b PRO/1000 MB Dual Port Server Connection 1130 82815 815 Chipset Host Bridge and Memory Controller Hub 1025 1016 Travelmate 612 TX 1043 8027 TUSL2-C Mainboard @@ -6696,6 +7505,9 @@ 1200 Intel IXP1200 Network Processor 172a 0000 AEP SSL Accelerator 1209 82559ER + 4c53 1050 CT7 mainboard + 4c53 1051 CE7 mainboard + 4c53 1070 PC6 mainboard 1221 82092AA_0 1222 82092AA_1 1223 SAA7116 @@ -6744,6 +7556,7 @@ 1014 705c 10/100 Netfinity 10/100 Ethernet Security Adapter 1014 805c 10/100 Netfinity 10/100 Ethernet Security Adapter 1028 009b PowerEdge 2550 + 1028 00ce PowerEdge 1400 1033 8000 PC-9821X-B06 1033 8016 PK-UG-X006 1033 801f PK-UG-X006 @@ -6769,6 +7582,7 @@ 144d 2501 SEM-2000 MiniPCI LAN Adapter 144d 2502 SEM-2100IL MiniPCI LAN Adapter 1668 1100 EtherExpress PRO/100B (TX) (MiniPCI Ethernet+Modem) + 4c53 1080 CT8 mainboard 8086 0001 EtherExpress PRO/100B (TX) 8086 0002 EtherExpress PRO/100B (T4) 8086 0003 EtherExpress PRO/10+ @@ -6875,6 +7689,7 @@ 1460 82870P2 P64H2 Hub PCI Bridge 1461 82870P2 P64H2 I/OxAPIC 15d9 3480 P4DP6 + 4c53 1090 Cx9 / Vx9 mainboard 1462 82870P2 P64H2 Hot Plug Controller 1960 80960RP [i960RP Microprocessor] 101e 0431 MegaRAID 431 RAID Controller @@ -6897,6 +7712,10 @@ 1111 1111 MegaRAID 466, PowerEdge Expandable RAID Controller 2/SC 1111 1112 PowerEdge Expandable RAID Controller 2/SC 113c 03a2 MegaRAID + e4bf 1010 CG1-RADIO + e4bf 1020 CU2-QUARTET + e4bf 1040 CU1-CHORUS + e4bf 3100 CX1-BAND 1962 80960RM [i960RM Microprocessor] 105a 0000 SuperTrak SX6000 I2O CPU 1a21 82840 840 (Carmel) Chipset Host Bridge (Hub A) @@ -6997,7 +7816,8 @@ 8086 4532 D815EEA2 mainboard 8086 4557 D815EGEW Mainboard 244c 82801BAM ISA Bridge (LPC) - 244e 82801BA/CA/DB/EB PCI Bridge + 244e 82801BA/CA/DB/EB/ER Hub interface to PCI Bridge + 1014 0267 NetVista A30p 2450 82801E ISA Bridge (LPC) 2452 82801E USB 2453 82801E SMBus @@ -7011,6 +7831,7 @@ 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP 15d9 3480 P4DP6 8086 1958 vpr Matrix 170B4 + 8086 4541 Latitude C640 2483 82801CA/CAM SMBus Controller 1014 0220 ThinkPad A/T/X Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP @@ -7022,7 +7843,7 @@ 15d9 3480 P4DP6 8086 1958 vpr Matrix 170B4 2485 82801CA/CAM AC'97 Audio Controller - 1014 0222 ThinkPad T23 (2647-4MG) or A30p (2653-64G) + 1014 0222 ThinkPad T23 (2647-4MG) or A30/A30p (2652/2653) 1014 0508 ThinkPad T30 1014 051c ThinkPad A/T/X Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP @@ -7031,6 +7852,7 @@ 1014 0223 ThinkPad A/T/X Series 1014 0503 ThinkPad R31 2656BBG 1014 051a ThinkPad A/T/X Series + 101f 1025 Acer 620 Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP 1179 0001 Toshiba Satellite 1110 Z15 internal Modem 134d 4c21 Dell Inspiron 2100 internal modem @@ -7045,40 +7867,98 @@ 1014 0220 ThinkPad A/T/X Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP 8086 1958 vpr Matrix 170B4 + 8086 4541 Latitude C640 248b 82801CA Ultra ATA Storage Controller 15d9 3480 P4DP6 248c 82801CAM ISA Bridge (LPC) - 24c0 82801DB LPC Interface Controller + 24c0 82801DB (ICH4) LPC Bridge + 1014 0267 NetVista A30p 1462 5800 845PE Max (MS-6580) - 24c2 82801DB USB (Hub #1) + 24c2 82801DB (ICH4) USB UHCI #1 + 1014 0267 NetVista A30p + 1071 8160 MIM2000 1462 5800 845PE Max (MS-6580) - 24c3 82801DB/DBM SMBus Controller + 24c3 82801DB/DBM (ICH4) SMBus Controller + 1014 0267 NetVista A30p + 1071 8160 MIM2000 + 1458 24c2 GA-8PE667 Ultra 1462 5800 845PE Max (MS-6580) - 24c4 82801DB USB (Hub #2) + 4c53 1090 Cx9 / Vx9 mainboard + 24c4 82801DB (ICH4) USB UHCI #2 + 1014 0267 NetVista A30p + 1071 8160 MIM2000 1462 5800 845PE Max (MS-6580) - 24c5 82801DB AC'97 Audio Controller + 4c53 1090 Cx9 / Vx9 mainboard + 24c5 82801DB (ICH4) AC'97 Audio Controller + 0e11 00b8 Analog Devices Inc. codec [SoundMAX] + 1014 0267 NetVista A30p + 1071 8160 MIM2000 + 1458 a002 GA-8PE667 Ultra 1462 5800 845PE Max (MS-6580) - 24c6 82801DB AC'97 Modem Controller - 24c7 82801DB USB (Hub #3) + 24c6 82801DB (ICH4) AC'97 Modem Controller + 1071 8160 MIM2000 + 24c7 82801DB (ICH4) USB UHCI #3 + 1014 0267 NetVista A30p + 1071 8160 MIM2000 1462 5800 845PE Max (MS-6580) - 24ca 82801DBM Ultra ATA Storage Controller - 24cb 82801DB Ultra ATA Storage Controller + 24ca 82801DBM (ICH4) Ultra ATA Storage Controller + 1071 8160 MIM2000 + 24cb 82801DB (ICH4) Ultra ATA 100 Storage Controller + 1014 0267 NetVista A30p + 1458 24c2 GA-8PE667 Ultra 1462 5800 845PE Max (MS-6580) + 4c53 1090 Cx9 / Vx9 mainboard 24cc 82801DBM LPC Interface Controller - 24cd 82801DB USB2 - 1462 3981 845PE Max (MS-6580) Onboard USB EHCI Controller - 24d0 82801EB LPC Interface Controller - 24d1 82801EB Ultra ATA Storage Controller - 24d2 82801EB USB - 24d3 82801EB SMBus Controller - 24d4 82801EB USB - 24d5 82801EB AC'97 Audio Controller - 24d6 82801EB AC'97 Modem Controller - 24d7 82801EB USB - 24db 82801EB Ultra ATA Storage Controller + 24cd 82801DB (ICH4) USB2 EHCI Controller + 1014 0267 NetVista A30p + 1071 8160 MIM2000 + 1462 3981 845PE Max (MS-6580) + 4c53 1090 Cx9 / Vx9 mainboard + 24d0 82801EB/ER (ICH5/ICH5R) LPC Bridge + 24d1 82801EB (ICH5) Serial ATA 150 Storage Controller + 103c 12bc d530 CMT (DG746A) + 1458 24d1 GA-8IPE1000 Pro2 motherboard (865PE) + 1462 7280 865PE Neo2 (MS-6728) + 24d2 82801EB/ER (ICH5/ICH5R) USB UHCI #1 + 103c 12bc d530 CMT (DG746A) + 1043 80a6 P4P800 Mainboard + 1462 7280 865PE Neo2 (MS-6728) + 24d3 82801EB/ER (ICH5/ICH5R) SMBus Controller + 1043 80a6 P4P800 Mainboard + 1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE) + 1462 7280 865PE Neo2 (MS-6728) + 24d4 82801EB/ER (ICH5/ICH5R) USB UHCI #2 + 103c 12bc d530 CMT (DG746A) + 1043 80a6 P4P800 Mainboard + 1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE) + 1462 7280 865PE Neo2 (MS-6728) + 24d5 82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller + 103c 12bc Analog Devices codec [SoundMAX Integrated Digital Audio] + 1043 80f3 P4P800 Mainboard + 1462 7280 865PE Neo2 (MS-6728) + 24d6 82801EB/ER (ICH5/ICH5R) AC'97 Modem Controller + 24d7 82801EB/ER (ICH5/ICH5R) USB UHCI #3 + 103c 12bc d530 CMT (DG746A) + 1043 80a6 P4P800 Mainboard + 1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE) + 1462 7280 865PE Neo2 (MS-6728) + 24db 82801EB/ER (ICH5/ICH5R) Ultra ATA 100 Storage Controller + 103c 12bc d530 CMT (DG746A) + 1043 80a6 P4P800 Mainboard + 1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE) + 1462 7280 865PE Neo2 (MS-6728) + 1462 7580 MSI 875P 24dc 82801EB LPC Interface Controller - 24dd 82801EB USB2 - 24de 82801EB USB + 24dd 82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller + 103c 12bc d530 CMT (DG746A) + 1043 80a6 P4P800 Mainboard + 1458 5006 GA-8IPE1000 Pro2 motherboard (865PE) + 1462 7280 865PE Neo2 (MS-6728) + 24de 82801EB/ER (ICH5/ICH5R) USB UHCI #4 + 1043 80a6 P4P800 Mainboard + 1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE) + 1462 7280 865PE Neo2 (MS-6728) + 24df 82801EB (ICH5R) SATA (cc=RAID) 2500 82820 820 (Camino) Chipset Host Bridge (MCH) 1028 0095 Precision Workstation 220 Chipset 1043 801c P3C-2000 system chipset @@ -7098,33 +7978,85 @@ 15d9 3480 P4DP6 2541 E7000 Series Host RASUM Controller 15d9 3480 P4DP6 + 4c53 1090 Cx9 / Vx9 mainboard 2543 E7000 Series Hub Interface B PCI-to-PCI Bridge 2544 E7000 Series Hub Interface B RASUM Controller + 4c53 1090 Cx9 / Vx9 mainboard 2545 E7000 Series Hub Interface C PCI-to-PCI Bridge 2546 E7000 Series Hub Interface C RASUM Controller 2547 E7000 Series Hub Interface D PCI-to-PCI Bridge 2548 E7000 Series Hub Interface D RASUM Controller 254c E7501 Memory Controller Hub + 4c53 1090 Cx9 / Vx9 mainboard 2550 E7505 Memory Controller Hub 2551 E7000 Series RAS Controller 2552 E7000 Series Processor to AGP Controller 2553 E7000 Series Hub Interface B PCI-to-PCI Bridge 2554 E7000 Series Hub Interface B PCI-to-PCI Bridge RAS Controller 255d E7205 Memory Controller Hub - 2560 82845G/GL [Brookdale-G] Chipset Host Bridge + 2560 82845G/GL[Brookdale-G]/GE/PE DRAM Controller/Host-Hub Interface + 1458 2560 GA-8PE667 Ultra 1462 5800 845PE Max (MS-6580) - 2561 82845G/GL [Brookdale-G] Chipset AGP Bridge - 2562 82845G/GL [Brookdale-G] Chipset Integrated Graphics Device - 2570 82865G/PE/P Processor to I/O Controller - 2571 82865G/PE/P Processor to AGP Controller + 2561 82845G/GL[Brookdale-G]/GE/PE Host-to-AGP Bridge + 2562 82845G/GL[Brookdale-G]/GE Chipset Integrated Graphics Device + 1014 0267 NetVista A30p + 2570 82865G/PE/P DRAM Controller/Host-Hub Interface + 1043 80f2 P4P800 Mainboard + 1458 2570 GA-8IPE1000 Pro2 motherboard (865PE) + 2571 82865G/PE/P PCI to AGP Controller 2572 82865G Integrated Graphics Device - 2573 82865G/PE/P Processor to PCI to CSA Bridge - 2576 82864G/PE/P Processor to I/O Memory Interface + 2573 82865G/PE/P PCI to CSA Bridge + 2576 82865G/PE/P Processor to I/O Memory Interface 2578 82875P Memory Controller Hub + 1462 7580 MS-6758 (875P Neo) +# Motherboard P4SCE + 15d9 4580 Super Micro Computer Inc. P4SCE 2579 82875P Processor to AGP Controller 257b 82875P Processor to PCI to CSA Bridge 257e 82875P Processor to I/O Memory Interface + 2580 Memory Controller Hub + 2581 Memory Controller Hub PCI Express Port + 2582 Graphics Controller + 2584 Workstation Memory Controller Hub + 2585 Workstation Memory Controller Hub PCI Express Port + 2588 Server Memory Controller Hub + 2589 Server Memory Controller Hub PCI Express Port + 258a Graphics Controller + 25a1 6300ESB LPC Interface Controller + 25a2 6300ESB PATA Storage Controller + 25a3 6300ESB SATA Storage Controller + 25a4 6300ESB SMBus Controller + 25a6 6300ESB AC'97 Audio Controller + 25a7 6300ESB AC'97 Modem Controller + 25a9 6300ESB USB Universal Host Controller + 25aa 6300ESB USB Universal Host Controller + 25ab 6300ESB Watchdog Timer + 25ac 6300ESB I/O Advanced Programmable Interrupt Controller + 25ad 6300ESB USB2 Enhanced Host Controller + 25ae 6300ESB 64-bit PCI-X Bridge + 25b0 6300ESB SATA RAID Controller + 2640 I/O Controller Hub LPC + 2641 I/O Controller Hub LPC + 2642 I/O Controller Hub LPC + 2651 I/O Controller Hub SATA cc=ide + 2652 I/O Controller Hub SATA cc=raid + 2658 I/O Controller Hub USB + 2659 I/O Controller Hub USB + 265a I/O Controller Hub USB + 265b I/O Controller Hub USB + 265c I/O Controller Hub USB2 + 2660 I/O Controller Hub PCI Express Port 0 + 2662 I/O Controller Hub PCI Express Port 1 + 2664 I/O Controller Hub PCI Express Port 2 + 2666 I/O Controller Hub PCI Express Port 3 + 2668 I/O Controller Hub Audio + 266a I/O Controller Hub SMBus + 266d I/O Controller Hub Modem + 266e I/O Controller Hub Audio + 266f I/O Controller Hub PATA + 2782 Graphics Controller 3092 Integrated RAID + 3200 GD31244 PCI-X SATA HBA 3340 82855PM Processor to I/O Controller 3341 82855PM Processor to AGP Controller 3575 82830 830 Chipset Host Bridge @@ -7135,7 +8067,24 @@ 1014 0513 ThinkPad A/T/X Series 3578 82830 830 Chipset Host Bridge 3580 82852/855GM Host Bridge + 3581 855GME GMCH Host-to-AGP Bridge (Virtual PCI-to-PCI) 3582 82852/855GM Integrated Graphics Device + 3584 855GM/GME GMCH Memory I/O Control Registers + 3585 855GM/GME GMCH Configuration Process Registers + 3590 Server Memory Controller Hub + 3591 Memory Controller Hub Error Reporting Register + 3592 Server Memory Controller Hub + 3593 Memory Controller Hub Error Reporting Register + 3594 Memory Controller Hub DMA Controller + 3595 Memory Controller Hub PCI Express Port A0 + 3596 Memory Controller Hub PCI Express Port A1 + 3597 Memory Controller Hub PCI Express Port B0 + 3598 Memory Controller Hub PCI Express Port B1 + 3599 Memory Controller Hub PCI Express Port C0 + 359a Memory Controller Hub PCI Express Port C1 + 359b Memory Controller Hub Extended Configuration Registers + 359e Workstation Memory Controller Hub + 4220 Intel(R) PRO/Wireless 2200BG 5200 EtherExpress PRO/100 Intelligent Server 5201 EtherExpress PRO/100 Intelligent Server 8086 0001 EtherExpress PRO/100 Server Ethernet Adapter @@ -7144,13 +8093,18 @@ 7010 82371SB PIIX3 IDE [Natoma/Triton II] 7020 82371SB PIIX3 USB [Natoma/Triton II] 7030 430VX - 82437VX TVX [Triton VX] + 7050 Intel Intercast Video Capture Card 7100 430TX - 82439TX MTXC 7110 82371AB/EB/MB PIIX4 ISA 7111 82371AB/EB/MB PIIX4 IDE 7112 82371AB/EB/MB PIIX4 USB 7113 82371AB/EB/MB PIIX4 ACPI 7120 82810 GMCH [Graphics Memory Controller Hub] + 4c53 1040 CL7 mainboard + 4c53 1060 PC7 mainboard 7121 82810 CGC [Chipset Graphics Controller] + 4c53 1040 CL7 mainboard + 4c53 1060 PC7 mainboard 8086 4341 Cayman (CA810) Mainboard 7122 82810 DC-100 GMCH [Graphics Memory Controller Hub] 7123 82810 DC-100 CGC [Chipset Graphics Controller] @@ -7163,12 +8117,17 @@ 7181 440LX/EX - 82443LX/EX AGP bridge 7190 440BX/ZX/DX - 82443BX/ZX/DX Host bridge 0e11 0500 Armada 1750 Laptop System Chipset - 0e11 b110 Armada M700 + 0e11 b110 Armada M700/E500 1179 0001 Toshiba Tecra 8100 Laptop System Chipset + 4c53 1050 CT7 mainboard + 4c53 1051 CE7 mainboard 7191 440BX/ZX/DX - 82443BX/ZX/DX AGP bridge 7192 440BX/ZX/DX - 82443BX/ZX/DX Host bridge (AGP disabled) 0e11 0460 Armada 1700 Laptop System Chipset + 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard 7194 82440MX Host Bridge + 1033 0000 Versa Note Vxi + 4c53 10a0 CA3/CR3 mainboard 7195 82440MX AC'97 Audio Controller 10cf 1099 QSound_SigmaTel Stac97 PCI Audio 11d4 0040 SoundMAX Integrated Digital Audio @@ -7179,8 +8138,11 @@ 719a 82440MX USB Universal Host Controller 719b 82440MX Power Management Controller 71a0 440GX - 82443GX Host bridge + 4c53 1050 CT7 mainboard + 4c53 1051 CE7 mainboard 71a1 440GX - 82443GX AGP bridge 71a2 440GX - 82443GX Host bridge (AGP disabled) + 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard 7600 82372FB PIIX5 ISA 7601 82372FB PIIX5 IDE 7602 82372FB PIIX5 USB @@ -7204,6 +8166,8 @@ 84e4 460GX - 84460GX Memory Data Controller (MDC) 84e6 460GX - 82466GX Wide and fast PCI eXpander Bridge (WXB) 84ea 460GX - 84460GX AGP Bridge (GXB function 1) + 8500 IXP4xx Family Network Processor (IXP420, 421, 422, 425 and IXC1100) + 9000 Intel IXP2000 Familly Network Processor 9621 Integrated RAID 9622 Integrated RAID 9641 Integrated RAID @@ -7212,16 +8176,22 @@ # observed, and documented in Intel revision note; new mask of 1011:0026 b154 21154 PCI-to-PCI Bridge b555 21555 Non transparent PCI-to-PCI Bridge + 4c53 1050 CT7 mainboard + 4c53 1051 CE7 mainboard e4bf 1000 CC8-1-BLUES ffff 450NX/GX [Orion] - 82453KX/GX Memory controller [BUG] 8800 Trigem Computer Inc. 2008 Video assistent component 8866 T-Square Design Inc. 8888 Silicon Magic +# 8c4a is not Winbond but there is a board misprogrammed +8c4a Winbond + 1980 W89C940 misprogrammed [ne2k] 8e0e Computone Corporation 8e2e KTI 3000 ET32P2 9004 Adaptec + 0078 AHA-2940U_CN 1078 AIC-7810 1160 AIC-1160 [Family Fibre Channel Adapter] 2178 AIC-7821 @@ -7240,6 +8210,9 @@ 5478 AIC-7850 5575 AVA-2930 5578 AIC-7855 + 5647 ANA-7711 TCP Offload Engine + 9004 7710 ANA-7711F TCP Offload Engine - Optical + 9004 7711 ANA-7711LP TCP Offload Engine - Copper 5675 AIC-755x 5678 AIC-7856 5775 AIC-755x @@ -7331,11 +8304,13 @@ 0010 AHA-2940U2/U2W 9005 2180 AHA-2940U2 SCSI Controller 9005 8100 AHA-2940U2B SCSI Controller + 9005 a100 AHA-2940U2B SCSI Controller 9005 a180 AHA-2940U2W SCSI Controller 9005 e100 AHA-2950U2B SCSI Controller 0011 AHA-2930U2 0013 78902 9005 0003 AAA-131U2 Array1000 1 Channel RAID Controller + 9005 000f AIC7890_ARO 001f AHA-2940U2/U2W / 7890/7891 9005 000f 2940U2W SCSI Controller 9005 a180 2940U2W SCSI Controller @@ -7345,6 +8320,7 @@ 003f AIC-7890 0050 AHA-3940U2x/395U2x 9005 f500 AHA-3950U2B + 9005 ffff AHA-3950U2B 0051 AHA-3950U2D 9005 b500 AHA-3950U2D 0053 AIC-7896 SCSI Controller @@ -7352,6 +8328,7 @@ 005f AIC-7896U2/7897U2 0080 AIC-7892A U160/m 0e11 e2a0 Compaq 64-Bit/66MHz Wide Ultra3 SCSI Adapter + 9005 6220 AHA-29160C 9005 62a0 29160N Ultra160 SCSI Controller 9005 e220 29160LP Low Profile Ultra160 SCSI Controller 9005 e2a0 29160 Ultra160 SCSI Controller @@ -7369,23 +8346,50 @@ 00c5 RAID subsystem HBA 1028 00c5 PowerEdge 2550 00cf AIC-7899P U160/m + 1028 00ce PowerEdge 1400 1028 00d1 PowerEdge 2550 10f1 2462 Thunder K7 S2462 15d9 9005 Onboard SCSI Host Adapter 0250 ServeRAID Controller 1014 0279 ServeRAID-xx 1014 028c ServeRAID-xx + 0283 AAC-RAID + 9005 0283 Catapult + 0284 AAC-RAID + 9005 0284 Tomcat 0285 AAC-RAID + 0e11 0295 SATA 6Ch (Bearcat) 1028 0287 PowerEdge Expandable RAID Controller 320/DC + 1028 0291 CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) + 17aa 0286 Legend S220 (Legend Crusader) + 17aa 0287 Legend S230 (Legend Vulcan) + 9005 0285 2200S (Vulcan) + 9005 0286 2120S (Crusader) + 9005 0287 2200S (Vulcan-2m) + 9005 0288 3230S (Harrier) + 9005 0289 3240S (Tornado) + 9005 028a ASR-2020S PCI-X ZCR (Skyhawk) + 9005 028b ASR-2020S SO-DIMM PCI-X ZCR (Terminator) + 9005 0290 AAR-2410SA PCI SATA 4ch (Jaguar II) + 9005 0292 AAR-2810SA PCI SATA 8ch (Corsair-8) + 9005 0293 AAR-21610SA PCI SATA 16ch (Corsair-16) + 9005 0294 ESD SO-DIMM PCI-X SATA ZCR (Prowler) + 0286 AAC-RAID (Rocket) + 9005 028c ASR-2230S + ASR-2230SLP PCI-X (Lancer) 8000 ASC-29320A U320 800f AIC-7901 U320 8010 ASC-39320 U320 8011 ASC-32320D U320 - 0e11 00ac U320 + 0e11 00ac ASC-39320D U320 9005 0041 ASC-39320D U320 8012 ASC-29320 U320 8013 ASC-29320B U320 8014 ASC-29320LP U320 + 8015 ASC-39320B U320 + 8016 ASC-39320A U320 + 8017 ASC-29320ALP U320 + 801c ASC-39320D U320 + 801d AIC-7902B U320 801e AIC-7901A U320 801f AIC-7902 U320 8080 ASC-29320A U320 w/HostRAID @@ -7410,8 +8414,19 @@ 9699 Omni Media Technology Inc 6565 6565 9710 NetMos Technology - 9815 VScom 021H-EP2 2 port parallel adaptor - 9835 222N-2 I/O Card (2S+1P) + 9815 PCI 9815 Multi-I/O Controller + 1000 0020 2P0S (2 port parallel adaptor) + 9835 PCI 9835 Multi-I/O Controller + 1000 0002 2S (16C550 UART) + 1000 0012 1P2S + 9845 PCI 9845 Multi-I/O Controller + 1000 0006 0P6S (6 port 16550a serial card) + 9855 PCI 9855 Multi-I/O Controller 4 Serial 1 Parallel + 1000 0014 1P4S +9902 Stargen Inc. + 0001 SG2010 PCI over Starfabric Bridge + 0002 SG2010 PCI to Starfabric Gateway + 0003 SG1010 Starfabric Switch and PCI Bridge a0a0 AOPEN Inc. a0f1 UNISYS Corporation a200 NEC Corporation @@ -7441,12 +8456,15 @@ d84d Exsys dead Indigita Corporation e000 Winbond e000 W89C940 -e159 Tiger Jet Network Inc. +# see : http://www.schoenfeld.de/inside/Inside_CWMK3.txt +e159 Individual Computers - Jens Schoenfeld 0001 Intel 537 0059 0001 128k ISDN-S/T Adapter 0059 0003 128k ISDN-U Adapter 0002 Tiger100APC ISDN chipset e4bf EKF Elektronik GmbH +# Innovative and scalable network IC vendor +e55e Essence Technology, Inc. ea01 Eagle Technology # The main chip of all these devices is by Xilinx -> It could also be a Xilinx ID. ea60 RME @@ -7486,12 +8504,17 @@ f1d0 AJA Video cafe KONA SD SMPTE 259M I/O efac KONA SD SMPTE 259M I/O facd KONA HD SMPTE 292M I/O -fa57 Fast Search & Transfer ASA +fa57 Interagon AS + 0001 PMC [Pattern Matching Chip] febd Ultraview Corp. feda Broadcom Inc (nee Epigram) a0fa BCM4210 iLine10 HomePNA 2.0 a10e BCM4230 iLine10 HomePNA 2.0 +# IT & Telecom company, develops PCI Trunk cards +fede Fedetec Inc. + 0003 TABIC PCI v3 fffe VMWare Inc + 0405 Virtual SVGA 4.0 0710 Virtual SVGA ffff Illegal Vendor ID --- linux-2.6.6/drivers/pci/probe.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/pci/probe.c 2004-05-10 01:19:04.084118176 -0700 @@ -193,7 +193,7 @@ void __devinit pci_read_bridge_bases(str return; if (dev->transparent) { - printk("Transparent bridge - %s\n", pci_name(dev)); + printk(KERN_INFO "PCI: Transparent bridge - %s\n", pci_name(dev)); for(i = 0; i < PCI_BUS_NUM_RESOURCES; i++) child->resource[i] = child->parent->resource[i]; return; --- linux-2.6.6/drivers/pcmcia/i82365.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/pcmcia/i82365.c 2004-05-10 01:19:48.612348856 -0700 @@ -68,7 +68,7 @@ #include "o2micro.h" #ifdef DEBUG -static const char *version = +static const char version[] = "i82365.c 1.265 1999/11/10 18:36:21 (David Hinds)"; static int pc_debug; --- linux-2.6.6/drivers/pcmcia/sa11xx_core.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/pcmcia/sa11xx_core.c 2004-05-10 01:19:01.797465800 -0700 @@ -933,6 +933,8 @@ sa1100_pcmcia_notifier(struct notifier_b if (freqs->new < freqs->old) sa1100_pcmcia_update_mecr(freqs->new); break; + case CPUFREQ_RESUMECHANGE: + sa1100_pcmcia_update_mecr(freqs->new); } return 0; --- linux-2.6.6/drivers/pcmcia/tcic.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/pcmcia/tcic.c 2004-05-10 01:19:55.689273000 -0700 @@ -60,7 +60,7 @@ static int pc_debug; module_param(pc_debug, int, 0644); -static const char *version = +static const char version[] = "tcic.c 1.111 2000/02/15 04:13:12 (David Hinds)"; #define debug(lvl, fmt, arg...) do { \ --- linux-2.6.6/drivers/sbus/char/bbc_envctrl.c 2003-10-08 15:07:09.000000000 -0700 +++ 25/drivers/sbus/char/bbc_envctrl.c 2004-05-10 01:19:49.409227712 -0700 @@ -10,7 +10,6 @@ #include #include #define __KERNEL_SYSCALLS__ -static int errno; #include #include "bbc_i2c.h" --- linux-2.6.6/drivers/sbus/char/envctrl.c 2003-10-08 15:07:09.000000000 -0700 +++ 25/drivers/sbus/char/envctrl.c 2004-05-10 01:19:49.410227560 -0700 @@ -36,7 +36,6 @@ #include #define __KERNEL_SYSCALLS__ -static int errno; #include #define ENVCTRL_MINOR 162 --- linux-2.6.6/drivers/sbus/char/openprom.c 2003-06-14 12:18:28.000000000 -0700 +++ 25/drivers/sbus/char/openprom.c 2004-05-10 01:19:18.581914176 -0700 @@ -149,7 +149,6 @@ static int openprom_sunos_ioctl(struct i char buffer[OPROMMAXPARAM+1], *buf; struct openpromio *opp; int bufsize, len, error = 0; - extern char saved_command_line[]; static int cnt; if (cmd == OPROMSETOPT) --- linux-2.6.6/drivers/scsi/3w-xxxx.c 2003-09-27 18:57:45.000000000 -0700 +++ 25/drivers/scsi/3w-xxxx.c 2004-05-10 01:19:04.526050992 -0700 @@ -1,12 +1,12 @@ /* 3w-xxxx.c -- 3ware Storage Controller device driver for Linux. - Written By: Adam Radford + Written By: Adam Radford Modifications By: Joel Jacobson Arnaldo Carvalho de Melo Brad Strand - Copyright (C) 1999-2003 3ware Inc. + Copyright (C) 1999-2004 3ware Inc. Kernel compatiblity By: Andre Hedrick Non-Copyright (C) 2000 Andre Hedrick @@ -47,10 +47,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Bugs/Comments/Suggestions should be mailed to: - linux@3ware.com + linuxraid@amcc.com For more information, goto: - http://www.3ware.com + http://www.amcc.com History ------- @@ -179,6 +179,11 @@ 1.02.00.036 - Increase character ioctl timeout to 60 seconds. 1.02.00.037 - Fix tw_ioctl() to handle all non-data ATA passthru cmds for 'smartmontools' support. + 1.26.00.038 - Roll driver minor version to 26 to denote kernel 2.6. + Add support for cmds_per_lun module parameter. + 1.26.00.039 - Fix bug in tw_chrdev_ioctl() polling code. + Fix data_buffer_length usage in tw_chrdev_ioctl(). + Update contact information. */ #include @@ -205,6 +210,7 @@ MODULE_LICENSE("GPL"); #include #include #include +#include #include #include @@ -242,10 +248,15 @@ static struct file_operations tw_fops = }; /* Globals */ -char *tw_driver_version="1.02.00.037"; +char *tw_driver_version="1.26.00.039"; TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT]; int tw_device_extension_count = 0; static int twe_major = -1; +static int cmds_per_lun; + +/* Module parameters */ +module_param(cmds_per_lun, int, 0); +MODULE_PARM_DESC(cmds_per_lun, "Maximum commands per LUN"); /* Functions */ @@ -683,7 +694,7 @@ static int tw_chrdev_ioctl(struct inode break; case TW_OP_AEN_LISTEN: dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): caught TW_AEN_LISTEN.\n"); - memset(tw_ioctl->data_buffer, 0, tw_ioctl->data_buffer_length); + memset(tw_ioctl->data_buffer, 0, data_buffer_length); spin_lock_irqsave(tw_dev->host->host_lock, flags); if (tw_dev->aen_head == tw_dev->aen_tail) { @@ -738,7 +749,7 @@ static int tw_chrdev_ioctl(struct inode timeout = TW_IOCTL_CHRDEV_TIMEOUT*HZ; /* Now wait for the command to complete */ - wait_event_interruptible_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout); + timeout = wait_event_interruptible_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout); /* Check if we timed out, got a signal, or didn't get an interrupt */ @@ -777,7 +788,7 @@ static int tw_chrdev_ioctl(struct inode } /* Now copy the response to userspace */ - error = copy_to_user((void *)arg, tw_ioctl, sizeof(TW_New_Ioctl) + tw_ioctl->data_buffer_length - 1); + error = copy_to_user((void *)arg, tw_ioctl, sizeof(TW_New_Ioctl) + data_buffer_length - 1); if (error == 0) retval = 0; out2: @@ -1141,14 +1152,6 @@ int tw_findcards(Scsi_Host_Template *tw_ /* Set card status as online */ tw_dev->online = 1; -#ifdef CONFIG_3W_XXXX_CMD_PER_LUN - tw_host->cmd_per_lun = CONFIG_3W_XXXX_CMD_PER_LUN; - if (tw_host->cmd_per_lun > TW_MAX_CMDS_PER_LUN) - tw_host->cmd_per_lun = TW_MAX_CMDS_PER_LUN; -#else - /* Use SHT cmd_per_lun here */ - tw_host->cmd_per_lun = TW_MAX_CMDS_PER_LUN; -#endif tw_dev->free_head = TW_Q_START; tw_dev->free_tail = TW_Q_START; tw_dev->free_wrap = TW_Q_LENGTH - 1; @@ -3386,13 +3389,13 @@ int tw_slave_configure(Scsi_Device *SDpt dprintk(KERN_WARNING "3w-xxxx: tw_slave_configure()\n"); -#ifdef CONFIG_3W_XXXX_CMD_PER_LUN - max_cmds = CONFIG_3W_XXXX_CMD_PER_LUN; - if (max_cmds > TW_MAX_CMDS_PER_LUN) + if (cmds_per_lun) { + max_cmds = cmds_per_lun; + if (max_cmds > TW_MAX_CMDS_PER_LUN) + max_cmds = TW_MAX_CMDS_PER_LUN; + } else { max_cmds = TW_MAX_CMDS_PER_LUN; -#else - max_cmds = TW_MAX_CMDS_PER_LUN; -#endif + } scsi_adjust_queue_depth(SDptr, MSG_ORDERED_TAG, max_cmds); return 0; @@ -3488,6 +3491,7 @@ static Scsi_Host_Template driver_templat .eh_abort_handler = tw_scsi_eh_abort, .eh_host_reset_handler = tw_scsi_eh_reset, .bios_param = tw_scsi_biosparam, + .slave_configure = tw_slave_configure, .can_queue = TW_Q_LENGTH-2, .this_id = -1, .sg_tablesize = TW_MAX_SGL_LENGTH, --- linux-2.6.6/drivers/scsi/3w-xxxx.h 2003-09-27 18:57:45.000000000 -0700 +++ 25/drivers/scsi/3w-xxxx.h 2004-05-10 01:19:04.527050840 -0700 @@ -1,12 +1,12 @@ /* 3w-xxxx.h -- 3ware Storage Controller device driver for Linux. - Written By: Adam Radford + Written By: Adam Radford Modifications By: Joel Jacobson Arnaldo Carvalho de Melo Brad Strand - Copyright (C) 1999-2003 3ware Inc. + Copyright (C) 1999-2004 3ware Inc. Kernel compatiblity By: Andre Hedrick Non-Copyright (C) 2000 Andre Hedrick @@ -45,10 +45,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Bugs/Comments/Suggestions should be mailed to: - linux@3ware.com + linuxraid@amcc.com For more information, goto: - http://www.3ware.com + http://www.amcc.com */ #ifndef _3W_XXXX_H --- linux-2.6.6/drivers/scsi/advansys.c 2004-02-17 20:48:44.000000000 -0800 +++ 25/drivers/scsi/advansys.c 2004-05-10 01:19:27.207602872 -0700 @@ -4619,7 +4619,7 @@ advansys_detect(Scsi_Host_Template *tpnt ASC_DBG1(1, "advansys_detect: probing I/O port 0x%x...\n", iop); - if (check_region(iop, ASC_IOADR_GAP) != 0) { + if (!request_region(iop, ASC_IOADR_GAP,"advansys")) { printk( "AdvanSys SCSI: specified I/O Port 0x%X is busy\n", iop); /* Don't try this I/O port twice. */ @@ -4630,6 +4630,7 @@ advansys_detect(Scsi_Host_Template *tpnt "AdvanSys SCSI: specified I/O Port 0x%X has no adapter\n", iop); /* Don't try this I/O port twice. */ asc_ioport[ioport] = 0; + release_region(iop, ASC_IOADR_GAP); goto ioport_try_again; } else { /* @@ -4647,6 +4648,7 @@ advansys_detect(Scsi_Host_Template *tpnt * 'ioport' past this board. */ ioport++; + release_region(iop,ASC_IOADR_GAP); goto ioport_try_again; } } @@ -10003,9 +10005,9 @@ AscSearchIOPortAddr11( } for (; i < ASC_IOADR_TABLE_MAX_IX; i++) { iop_base = _asc_def_iop_base[i]; - if (check_region(iop_base, ASC_IOADR_GAP) != 0) { + if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) { ASC_DBG1(1, - "AscSearchIOPortAddr11: check_region() failed I/O port 0x%x\n", + "AscSearchIOPortAddr11: request_region() failed I/O port 0x%x\n", iop_base); continue; } --- linux-2.6.6/drivers/scsi/aic7xxx/aic7770_osm.c 2004-01-09 00:04:32.000000000 -0800 +++ 25/drivers/scsi/aic7xxx/aic7770_osm.c 2004-05-10 01:19:04.850001744 -0700 @@ -73,7 +73,7 @@ typedef void *aic7770_dev_t; static int aic7770_linux_config(struct aic7770_identity *entry, aic7770_dev_t dev, u_int eisaBase); -void +int ahc_linux_eisa_init(void) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) @@ -82,7 +82,7 @@ ahc_linux_eisa_init(void) int i; if (aic7xxx_probe_eisa_vl == 0) - return; + return -ENODEV; /* * Linux requires the EISA IDs to be specified in @@ -93,7 +93,7 @@ ahc_linux_eisa_init(void) (ahc_num_aic7770_devs + 1), M_DEVBUF, M_NOWAIT); if (aic7770_driver.id_table == NULL) - return; + return -ENOMEM; for (eid = (struct eisa_device_id *)aic7770_driver.id_table, id = aic7770_ident_table, i = 0; @@ -109,15 +109,16 @@ ahc_linux_eisa_init(void) } eid->sig[0] = 0; - eisa_driver_register(&aic7770_driver); + return eisa_driver_register(&aic7770_driver); #else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) */ struct aic7770_identity *entry; u_int slot; u_int eisaBase; u_int i; + int ret = -ENODEV; if (aic7xxx_probe_eisa_vl == 0) - return; + return ret; eisaBase = 0x1000 + AHC_EISA_SLOT_OFFSET; for (slot = 1; slot < NUMSLOTS; eisaBase+=0x1000, slot++) { @@ -146,24 +147,22 @@ ahc_linux_eisa_init(void) continue; /* no EISA card in slot */ entry = aic7770_find_device(eisa_id); - if (entry != NULL) + if (entry != NULL) { aic7770_linux_config(entry, NULL, eisaBase); + ret = 0; + } } + return ret; #endif } void ahc_linux_eisa_exit(void) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - if (aic7xxx_probe_eisa_vl == 0) - return; - - if (aic7770_driver.id_table != NULL) { + if(aic7xxx_probe_eisa_vl != 0 && aic7770_driver.id_table != NULL) { eisa_driver_unregister(&aic7770_driver); free(aic7770_driver.id_table, M_DEVBUF); } -#endif } static int --- linux-2.6.6/drivers/scsi/aic7xxx/aic79xx_osm.c 2004-03-10 20:41:29.000000000 -0800 +++ 25/drivers/scsi/aic7xxx/aic79xx_osm.c 2004-05-10 01:19:04.854001136 -0700 @@ -2591,6 +2591,7 @@ ahd_linux_dv_thread(void *data) sprintf(current->comm, "ahd_dv_%d", ahd->unit); #else daemonize("ahd_dv_%d", ahd->unit); + current->flags |= PF_FREEZE; #endif unlock_kernel(); --- linux-2.6.6/drivers/scsi/aic7xxx/aic7xxx_osm.c 2004-03-10 20:41:29.000000000 -0800 +++ 25/drivers/scsi/aic7xxx/aic7xxx_osm.c 2004-05-10 01:19:04.858000528 -0700 @@ -843,7 +843,8 @@ static int ahc_linux_detect(Scsi_Host_Template *template) { struct ahc_softc *ahc; - int found; + int found = 0; + int eisa_err, pci_err; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* @@ -891,28 +892,29 @@ ahc_linux_detect(Scsi_Host_Template *tem */ ahc_list_lockinit(); -#ifdef CONFIG_PCI - ahc_linux_pci_init(); -#endif + pci_err = ahc_linux_pci_init(); + eisa_err = ahc_linux_eisa_init(); + + if(pci_err && eisa_err) + goto out; -#ifdef CONFIG_EISA - ahc_linux_eisa_init(); -#endif /* * Register with the SCSI layer all * controllers we've found. */ - found = 0; TAILQ_FOREACH(ahc, &ahc_tailq, links) { if (ahc_linux_register_host(ahc, template) == 0) found++; } +out: + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) spin_lock_irq(&io_request_lock); #endif aic7xxx_detect_complete++; + return (found); } @@ -1534,6 +1536,7 @@ ahc_softc_comp(struct ahc_softc *lahc, s /* Still equal. Sort by BIOS address, ioport, or bus/slot/func. */ switch (rvalue) { +#ifdef CONFIG_PCI case AHC_PCI: { char primary_channel; @@ -1566,6 +1569,7 @@ ahc_softc_comp(struct ahc_softc *lahc, s value = 1; break; } +#endif case AHC_EISA: if ((rahc->flags & AHC_BIOS_ENABLED) != 0) { value = rahc->platform_data->bios_address @@ -2296,6 +2300,7 @@ ahc_linux_dv_thread(void *data) sprintf(current->comm, "ahc_dv_%d", ahc->unit); #else daemonize("ahc_dv_%d", ahc->unit); + current->flags |= PF_FREEZE; #endif unlock_kernel(); @@ -3969,11 +3974,10 @@ ahc_linux_alloc_device(struct ahc_softc } static void -ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev) +__ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev) { struct ahc_linux_target *targ; - del_timer_sync(&dev->timer); targ = dev->target; targ->devices[dev->lun] = NULL; free(dev, M_DEVBUF); @@ -3983,6 +3987,13 @@ ahc_linux_free_device(struct ahc_softc * ahc_linux_free_target(ahc, targ); } +static void +ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev) +{ + del_timer_sync(&dev->timer); + __ahc_linux_free_device(ahc, dev); +} + void ahc_send_async(struct ahc_softc *ahc, char channel, u_int target, u_int lun, ac_code code, void *arg) @@ -4693,7 +4704,7 @@ ahc_linux_dev_timed_unfreeze(u_long arg) ahc_linux_run_device_queue(ahc, dev); if (TAILQ_EMPTY(&dev->busyq) && dev->active == 0) - ahc_linux_free_device(ahc, dev); + __ahc_linux_free_device(ahc, dev); ahc_unlock(ahc, &s); } @@ -5067,11 +5078,17 @@ ahc_platform_dump_card_state(struct ahc_ } } +static void ahc_linux_exit(void); + static int __init ahc_linux_init(void) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - return (ahc_linux_detect(&aic7xxx_driver_template) ? 0 : -ENODEV); + int rc = ahc_linux_detect(&aic7xxx_driver_template); + if (rc) + return rc; + ahc_linux_exit(); + return -ENODEV; #else scsi_register_module(MODULE_SCSI_HA, &aic7xxx_driver_template); if (aic7xxx_driver_template.present == 0) { @@ -5084,7 +5101,7 @@ ahc_linux_init(void) #endif } -static void __exit +static void ahc_linux_exit(void) { struct ahc_softc *ahc; @@ -5111,12 +5128,8 @@ ahc_linux_exit(void) */ scsi_unregister_module(MODULE_SCSI_HA, &aic7xxx_driver_template); #endif -#ifdef CONFIG_PCI ahc_linux_pci_exit(); -#endif -#ifdef CONFIG_EISA ahc_linux_eisa_exit(); -#endif } module_init(ahc_linux_init); --- linux-2.6.6/drivers/scsi/aic7xxx/aic7xxx_osm.h 2004-01-09 00:04:32.000000000 -0800 +++ 25/drivers/scsi/aic7xxx/aic7xxx_osm.h 2004-05-10 01:19:04.859000376 -0700 @@ -840,11 +840,17 @@ typedef enum #ifdef CONFIG_EISA extern uint32_t aic7xxx_probe_eisa_vl; -void ahc_linux_eisa_init(void); +int ahc_linux_eisa_init(void); void ahc_linux_eisa_exit(void); int aic7770_map_registers(struct ahc_softc *ahc, u_int port); int aic7770_map_int(struct ahc_softc *ahc, u_int irq); +#else +static inline int ahc_linux_eisa_init(void) { + return -ENODEV; +} +static inline void ahc_linux_eisa_exit(void) { +} #endif /******************************* PCI Routines *********************************/ @@ -932,6 +938,12 @@ ahc_get_pci_bus(ahc_dev_softc_t pci) { return (pci->bus->number); } +#else +static inline int ahc_linux_pci_init(void) { + return -ENODEV; +} +static inline void ahc_linux_pci_exit(void) { +} #endif static __inline void ahc_flush_device_writes(struct ahc_softc *); --- linux-2.6.6/drivers/scsi/aic7xxx_old/aic7xxx_proc.c 2004-02-03 20:42:37.000000000 -0800 +++ 25/drivers/scsi/aic7xxx_old/aic7xxx_proc.c 2004-05-10 01:19:04.860000224 -0700 @@ -319,13 +319,13 @@ aic7xxx_proc_info ( struct Scsi_Host *HB aic_dev->r_total+aic_dev->w_total, aic_dev->r_total, aic_dev->w_total); size += sprintf(BLS, "%s\n", HDRB); size += sprintf(BLS, " Reads:"); - for (i = 0; i < NUMBER(aic_dev->r_bins); i++) + for (i = 0; i < ARRAY_SIZE(aic_dev->r_bins); i++) { size += sprintf(BLS, " %10ld", aic_dev->r_bins[i]); } size += sprintf(BLS, "\n"); size += sprintf(BLS, " Writes:"); - for (i = 0; i < NUMBER(aic_dev->w_bins); i++) + for (i = 0; i < ARRAY_SIZE(aic_dev->w_bins); i++) { size += sprintf(BLS, " %10ld", aic_dev->w_bins[i]); } @@ -347,7 +347,7 @@ aic7xxx_proc_info ( struct Scsi_Host *HB else { *start = buffer; - length = MIN(length, size - offset); + length = min_t(int, length, size - offset); memcpy(buffer, &aic7xxx_buffer[offset], length); } --- linux-2.6.6/drivers/scsi/aic7xxx_old.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/scsi/aic7xxx_old.c 2004-05-10 01:19:04.868998856 -0700 @@ -254,9 +254,6 @@ #define AIC7XXX_C_VERSION "5.2.6" -#define NUMBER(arr) (sizeof(arr) / sizeof(arr[0])) -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) #define ALL_TARGETS -1 #define ALL_CHANNELS -1 #define ALL_LUNS -1 @@ -1376,7 +1373,7 @@ aic7xxx_setup(char *s) while ((p = strsep(&s, ",.")) != NULL) { - for (i = 0; i < NUMBER(options); i++) + for (i = 0; i < ARRAY_SIZE(options); i++) { n = strlen(options[i].name); if (!strncmp(options[i].name, p, n)) @@ -1423,7 +1420,7 @@ aic7xxx_setup(char *s) else if (instance >= 0) instance++; if ( (device >= MAX_TARGETS) || - (instance >= NUMBER(aic7xxx_tag_info)) ) + (instance >= ARRAY_SIZE(aic7xxx_tag_info)) ) done = TRUE; tok++; if (!done) @@ -1447,7 +1444,7 @@ aic7xxx_setup(char *s) } } if ( (instance >= 0) && (device >= 0) && - (instance < NUMBER(aic7xxx_tag_info)) && + (instance < ARRAY_SIZE(aic7xxx_tag_info)) && (device < MAX_TARGETS) ) aic7xxx_tag_info[instance].tag_commands[device] = simple_strtoul(tok, NULL, 0) & 0xff; @@ -1658,7 +1655,7 @@ aic7xxx_download_instr(struct aic7xxx_ho { int end_addr; - end_addr = MIN(address, skip_addr); + end_addr = min_t(int, address, skip_addr); address_offset += end_addr - i; i = skip_addr; } @@ -1884,7 +1881,7 @@ aic7xxx_find_syncrate(struct aic7xxx_hos if(!(p->features & AHC_ULTRA3)) { *options = 0; - maxsync = MAX(maxsync, AHC_SYNCRATE_ULTRA2); + maxsync = max_t(unsigned int, maxsync, AHC_SYNCRATE_ULTRA2); } break; case MSG_EXT_PPR_OPTION_DT_CRC_QUICK: @@ -1892,7 +1889,7 @@ aic7xxx_find_syncrate(struct aic7xxx_hos if(!(p->features & AHC_ULTRA3)) { *options = 0; - maxsync = MAX(maxsync, AHC_SYNCRATE_ULTRA2); + maxsync = max_t(unsigned int, maxsync, AHC_SYNCRATE_ULTRA2); } else { @@ -1916,7 +1913,7 @@ aic7xxx_find_syncrate(struct aic7xxx_hos break; default: *options = 0; - maxsync = MAX(maxsync, AHC_SYNCRATE_ULTRA2); + maxsync = max_t(unsigned int, maxsync, AHC_SYNCRATE_ULTRA2); break; } syncrate = &aic7xxx_syncrates[maxsync]; @@ -2057,7 +2054,7 @@ aic7xxx_validate_offset(struct aic7xxx_h else maxoffset = MAX_OFFSET_8BIT; } - *offset = MIN(*offset, maxoffset); + *offset = min(*offset, maxoffset); } /*+F************************************************************************* @@ -2570,7 +2567,7 @@ aic7xxx_allocate_scb(struct aic7xxx_host break; } } - scb_count = MIN( (i-1), p->scb_data->maxscbs - p->scb_data->numscbs); + scb_count = min( (i-1), p->scb_data->maxscbs - p->scb_data->numscbs); scb_ap = (struct aic7xxx_scb *)kmalloc(sizeof (struct aic7xxx_scb) * scb_count + sizeof(struct aic7xxx_scb_dma), GFP_ATOMIC); if (scb_ap == NULL) @@ -5042,7 +5039,7 @@ aic7xxx_parse_msg(struct aic7xxx_host *p if(p->user[tindex].offset) { aic_dev->needsdtr_copy = 1; - aic_dev->goal.period = MAX(10,p->user[tindex].period); + aic_dev->goal.period = max_t(unsigned char, 10,p->user[tindex].period); if(p->features & AHC_ULTRA2) { aic_dev->goal.offset = MAX_OFFSET_ULTRA2; @@ -5086,8 +5083,8 @@ aic7xxx_parse_msg(struct aic7xxx_host *p * the device isn't allowed to send values greater than the ones * we first sent to it. */ - new_period = MAX(period, aic_dev->goal.period); - new_offset = MIN(offset, aic_dev->goal.offset); + new_period = max_t(unsigned int, period, aic_dev->goal.period); + new_offset = min_t(unsigned int, offset, aic_dev->goal.offset); } /* @@ -5208,7 +5205,7 @@ aic7xxx_parse_msg(struct aic7xxx_host *p if(p->user[tindex].offset) { aic_dev->needsdtr_copy = 1; - aic_dev->goal.period = MAX(10,p->user[tindex].period); + aic_dev->goal.period = max_t(unsigned char, 10, p->user[tindex].period); if(p->features & AHC_ULTRA2) { aic_dev->goal.offset = MAX_OFFSET_ULTRA2; @@ -6413,7 +6410,7 @@ aic7xxx_isr(int irq, void *dev_id, struc unsigned char errno = aic_inb(p, ERROR); printk(KERN_ERR "(scsi%d) BRKADRINT error(0x%x):\n", p->host_no, errno); - for (i = 0; i < NUMBER(hard_error); i++) + for (i = 0; i < ARRAY_SIZE(hard_error); i++) { if (errno & hard_error[i].errno) { @@ -6562,7 +6559,7 @@ aic7xxx_init_transinfo(struct aic7xxx_ho else { aic_dev->needsdtr = aic_dev->needsdtr_copy = 1; - aic_dev->goal.period = MAX(10, aic_dev->goal.period); + aic_dev->goal.period = max_t(unsigned char, 10, aic_dev->goal.period); aic_dev->goal.options = 0; } } @@ -6673,7 +6670,7 @@ aic7xxx_device_queue_depth(struct aic7xx } else { - if (p->instance >= NUMBER(aic7xxx_tag_info)) + if (p->instance >= ARRAY_SIZE(aic7xxx_tag_info)) { static int print_warning = TRUE; if(print_warning) @@ -6850,7 +6847,7 @@ aic7xxx_probe(int slot, int base, ahc_fl buf[i] = inb(base + i); } - for (i = 0; i < NUMBER(AIC7xxx); i++) + for (i = 0; i < ARRAY_SIZE(AIC7xxx); i++) { /* * Signature match on enabled card? @@ -9199,7 +9196,7 @@ aic7xxx_detect(Scsi_Host_Template *templ unsigned int devconfig, i, oldverbose; struct pci_dev *pdev = NULL; - for (i = 0; i < NUMBER(aic_pdevs); i++) + for (i = 0; i < ARRAY_SIZE(aic_pdevs); i++) { pdev = NULL; while ((pdev = pci_find_device(aic_pdevs[i].vendor_id, @@ -9698,7 +9695,7 @@ skip_pci_controller: * EISA/VL-bus card signature probe. */ slot = MINSLOT; - while ( (slot <= MAXSLOT) && + while ( (slot <= MAXSLOT) && !(aic7xxx_no_probe) ) { base = SLOTBASE(slot) + MINREG; @@ -10097,7 +10094,7 @@ skip_pci_controller: int i; left = found; - for (i=0; i + - Support 2.6 kernel and DMA-mapping + - ioctl fix for raid tools + - use schedule_timeout in long long loop + **************************************************************************/ -//#define DEBUG 1 -//#define UARTDELAY 1 +/*#define DEBUG 1 */ +/*#define UARTDELAY 1 */ -// On the real kernel ADDR32 should always be zero for 2.4. GFP_HIGH allocates -// high pages. Keep the macro around because of the broken unmerged ia64 tree +/* On the real kernel ADDR32 should always be zero for 2.4. GFP_HIGH allocates + high pages. Keep the macro around because of the broken unmerged ia64 tree */ #define ADDR32 (0) -#error Please convert me to Documentation/DMA-mapping.txt - #include #include @@ -53,6 +57,7 @@ MODULE_DESCRIPTION("Adaptec I2O RAID Dri #include /* for printk */ #include #include +#include #include #include @@ -86,7 +91,7 @@ static dpt_sig_S DPTI_sig = { #elif defined(__alpha__) PROC_ALPHA , #else - (-1),(-1) + (-1),(-1), #endif FT_HBADRVR, 0, OEM_DPT, OS_LINUX, CAP_OVERLAP, DEV_ALL, ADF_ALL_SC5, 0, 0, DPT_VERSION, DPT_REVISION, DPT_SUBREVISION, @@ -227,7 +232,7 @@ rebuild_sys_tab: /* Active IOPs now in OPERATIONAL state */ PDEBUG("HBA's in OPERATIONAL state\n"); - printk(KERN_INFO"dpti: If you have a lot of devices this could take a few minutes.\n"); + printk("dpti: If you have a lot of devices this could take a few minutes.\n"); for (pHba = hba_chain; pHba; pHba = pHba->next) { printk(KERN_INFO"%s: Reading the hardware resource table.\n", pHba->name); if (adpt_i2o_lct_get(pHba) < 0){ @@ -270,6 +275,7 @@ static int adpt_release(struct Scsi_Host adpt_hba* pHba = (adpt_hba*) host->hostdata[0]; // adpt_i2o_quiesce_hba(pHba); adpt_i2o_delete_hba(pHba); + scsi_unregister(host); return 0; } @@ -340,6 +346,8 @@ static void adpt_inquiry(adpt_hba* pHba) if (rcode != 0) { sprintf(pHba->detail, "Adaptec I2O RAID"); printk(KERN_INFO "%s: Inquiry Error (%d)\n",pHba->name,rcode); + if (rcode != -ETIME && rcode != -EINTR) + kfree(buf); } else { memset(pHba->detail, 0, sizeof(pHba->detail)); memcpy(&(pHba->detail), "Vendor: Adaptec ", 16); @@ -348,8 +356,8 @@ static void adpt_inquiry(adpt_hba* pHba) memcpy(&(pHba->detail[40]), " FW: ", 4); memcpy(&(pHba->detail[44]), (u8*) &buf[32], 4); pHba->detail[48] = '\0'; /* precautionary */ + kfree(buf); } - kfree(buf); adpt_i2o_status_get(pHba); return ; } @@ -479,7 +487,7 @@ static int adpt_bios_param(struct scsi_d heads = 255; sectors = 63; } - cylinders = capacity / (heads * sectors); + cylinders = sector_div(capacity, heads * sectors); // Special case if CDROM if(sdev->type == 5) { // CDROM @@ -872,6 +880,9 @@ static int adpt_install_hba(Scsi_Host_Te return -EINVAL; } pci_set_master(pDev); + if (pci_set_dma_mask(pDev, 0xffffffffffffffffULL) && + pci_set_dma_mask(pDev, 0xffffffffULL)) + return -EINVAL; base_addr0_phys = pci_resource_start(pDev,0); hba_map0_area_size = pci_resource_len(pDev,0); @@ -964,6 +975,7 @@ static int adpt_install_hba(Scsi_Host_Te // Initializing the spinlocks spin_lock_init(&pHba->state_lock); + spin_lock_init(&adpt_post_wait_lock); if(raptorFlag == 0){ printk(KERN_INFO"Adaptec I2O RAID controller %d at %lx size=%x irq=%d\n", @@ -1065,7 +1077,7 @@ static int adpt_init(void) { int i; - printk(KERN_INFO"Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n"); + printk("Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n"); for (i = 0; i < DPTI_MAX_HBA; i++) { hbas[i] = NULL; } @@ -1153,12 +1165,22 @@ static int adpt_i2o_post_wait(adpt_hba* timeout *= HZ; if((status = adpt_i2o_post_this(pHba, msg, len)) == 0){ set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irq(pHba->host->host_lock); + if(pHba->host) + spin_unlock_irq(pHba->host->host_lock); if (!timeout) schedule(); - else + else{ + timeout = schedule_timeout(timeout); + if (timeout == 0) { + // I/O issued, but cannot get result in + // specified time. Freeing resorces is + // dangerous. + status = -ETIME; + } schedule_timeout(timeout*HZ); - spin_lock_irq(pHba->host->host_lock); + } + if(pHba->host) + spin_lock_irq(pHba->host->host_lock); } spin_lock_irq(&adpt_wq_i2o_post.lock); __remove_wait_queue(&adpt_wq_i2o_post, &wait); @@ -1210,6 +1232,8 @@ static s32 adpt_i2o_post_this(adpt_hba* printk(KERN_WARNING"dpti%d: Timeout waiting for message frame!\n", pHba->unit); return -ETIMEDOUT; } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); } while(m == EMPTY_QUEUE); msg = (u32*) (pHba->msg_addr_virt + m); @@ -1284,6 +1308,8 @@ static s32 adpt_i2o_reset_hba(adpt_hba* printk(KERN_WARNING"Timeout waiting for message!\n"); return -ETIMEDOUT; } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); } while (m == EMPTY_QUEUE); status = (u8*)kmalloc(4, GFP_KERNEL|ADDR32); @@ -1315,6 +1341,8 @@ static s32 adpt_i2o_reset_hba(adpt_hba* return -ETIMEDOUT; } rmb(); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); } if(*status == 0x01 /*I2O_EXEC_IOP_RESET_IN_PROGRESS*/) { @@ -1331,6 +1359,8 @@ static s32 adpt_i2o_reset_hba(adpt_hba* printk(KERN_ERR "%s:Timeout waiting for IOP Reset.\n",pHba->name); return -ETIMEDOUT; } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); } while (m == EMPTY_QUEUE); // Flush the offset adpt_send_nop(pHba, m); @@ -1696,15 +1726,20 @@ static int adpt_i2o_passthru(adpt_hba* p } do { - spin_lock_irqsave(pHba->host->host_lock, flags); + if(pHba->host) + spin_lock_irqsave(pHba->host->host_lock, flags); // This state stops any new commands from enterring the // controller while processing the ioctl // pHba->state |= DPTI_STATE_IOCTL; // We can't set this now - The scsi subsystem sets host_blocked and // the queue empties and stops. We need a way to restart the queue rcode = adpt_i2o_post_wait(pHba, msg, size, FOREVER); + if (rcode != 0) + printk("adpt_i2o_passthru: post wait failed %d %p\n", + rcode, reply); // pHba->state &= ~DPTI_STATE_IOCTL; - spin_unlock_irqrestore(pHba->host->host_lock, flags); + if(pHba->host) + spin_unlock_irqrestore(pHba->host->host_lock, flags); } while(rcode == -ETIMEDOUT); if(rcode){ @@ -1765,10 +1800,12 @@ static int adpt_i2o_passthru(adpt_hba* p cleanup: - kfree (reply); + if (rcode != -ETIME && rcode != -EINTR) + kfree (reply); while(sg_index) { if(sg_list[--sg_index]) { - kfree((void*)(sg_list[sg_index])); + if (rcode != -ETIME && rcode != -EINTR) + kfree((void*)(sg_list[sg_index])); } } return rcode; @@ -1876,7 +1913,7 @@ static int adpt_ioctl(struct inode *inod int minor; int error = 0; adpt_hba* pHba; - ulong flags; + ulong flags = 0; minor = iminor(inode); if (minor >= DPTI_MAX_HBA){ @@ -1942,9 +1979,11 @@ static int adpt_ioctl(struct inode *inod break; } case I2ORESETCMD: - spin_lock_irqsave(pHba->host->host_lock, flags); + if(pHba->host) + spin_lock_irqsave(pHba->host->host_lock, flags); adpt_hba_reset(pHba); - spin_unlock_irqrestore(pHba->host->host_lock, flags); + if(pHba->host) + spin_unlock_irqrestore(pHba->host->host_lock, flags); break; case I2ORESCANCMD: adpt_rescan(pHba); @@ -1957,7 +1996,7 @@ static int adpt_ioctl(struct inode *inod } -static void adpt_isr(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t adpt_isr(int irq, void *dev_id, struct pt_regs *regs) { Scsi_Cmnd* cmd; adpt_hba* pHba = dev_id; @@ -1966,12 +2005,15 @@ static void adpt_isr(int irq, void *dev_ u32 status=0; u32 context; ulong flags = 0; + int handled = 0; - if (pHba == NULL ){ + if (pHba == NULL){ printk(KERN_WARNING"adpt_isr: NULL dev_id\n"); - return; + return IRQ_NONE; } - spin_lock_irqsave(pHba->host->host_lock, flags); + if(pHba->host) + spin_lock_irqsave(pHba->host->host_lock, flags); + while( readl(pHba->irq_mask) & I2O_INTERRUPT_PENDING_B) { m = readl(pHba->reply_port); if(m == EMPTY_QUEUE){ @@ -2036,7 +2078,10 @@ static void adpt_isr(int irq, void *dev_ wmb(); rmb(); } -out: spin_unlock_irqrestore(pHba->host->host_lock, flags); + handled = 1; +out: if(pHba->host) + spin_unlock_irqrestore(pHba->host->host_lock, flags); + return IRQ_RETVAL(handled); } static s32 adpt_scsi_to_i2o(adpt_hba* pHba, Scsi_Cmnd* cmd, struct adpt_device* d) @@ -2111,15 +2156,19 @@ static s32 adpt_scsi_to_i2o(adpt_hba* pH /* Now fill in the SGList and command */ if(cmd->use_sg) { struct scatterlist *sg = (struct scatterlist *)cmd->request_buffer; + int sg_count = pci_map_sg(pHba->pDev, sg, cmd->use_sg, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); + + len = 0; - for(i = 0 ; i < cmd->use_sg; i++) { - *mptr++ = direction|0x10000000|sg->length; - len+=sg->length; - *mptr++ = virt_to_bus(sg->address); + for(i = 0 ; i < sg_count; i++) { + *mptr++ = direction|0x10000000|sg_dma_len(sg); + len+=sg_dma_len(sg); + *mptr++ = sg_dma_address(sg); sg++; } /* Make this an end of list */ - mptr[-2] = direction|0xD0000000|(sg-1)->length; + mptr[-2] = direction|0xD0000000|sg_dma_len(sg-1); reqlen = mptr - msg; *lenptr = len; @@ -2133,7 +2182,10 @@ static s32 adpt_scsi_to_i2o(adpt_hba* pH reqlen = 12; } else { *mptr++ = 0xD0000000|direction|cmd->request_bufflen; - *mptr++ = virt_to_bus(cmd->request_buffer); + *mptr++ = pci_map_single(pHba->pDev, + cmd->request_buffer, + cmd->request_bufflen, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); } } @@ -2306,15 +2358,17 @@ static s32 adpt_i2o_to_scsi(ulong reply, static s32 adpt_rescan(adpt_hba* pHba) { s32 rcode; - ulong flags; + ulong flags = 0; - spin_lock_irqsave(pHba->host->host_lock, flags); + if(pHba->host) + spin_lock_irqsave(pHba->host->host_lock, flags); if ((rcode=adpt_i2o_lct_get(pHba)) < 0) goto out; if ((rcode=adpt_i2o_reparse_lct(pHba)) < 0) goto out; rcode = 0; -out: spin_unlock_irqrestore(pHba->host->host_lock, flags); +out: if(pHba->host) + spin_unlock_irqrestore(pHba->host->host_lock, flags); return rcode; } @@ -2596,6 +2650,8 @@ static s32 adpt_send_nop(adpt_hba*pHba,u printk(KERN_ERR "%s: Timeout waiting for message frame!\n",pHba->name); return 2; } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); } msg = (u32*)(pHba->msg_addr_virt + m); writel( THREE_WORD_MSG_SIZE | SGL_OFFSET_0,&msg[0]); @@ -2629,6 +2685,8 @@ static s32 adpt_i2o_init_outbound_q(adpt printk(KERN_WARNING"%s: Timeout waiting for message frame\n",pHba->name); return -ETIMEDOUT; } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); } while(m == EMPTY_QUEUE); msg=(u32 *)(pHba->msg_addr_virt+m); @@ -2664,9 +2722,10 @@ static s32 adpt_i2o_init_outbound_q(adpt rmb(); if(time_after(jiffies,timeout)){ printk(KERN_WARNING"%s: Timeout Initializing\n",pHba->name); - kfree((void*)status); return -ETIMEDOUT; } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); } while (1); // If the command was successful, fill the fifo with our reply @@ -2744,6 +2803,8 @@ static s32 adpt_i2o_status_get(adpt_hba* pHba->name); return -ETIMEDOUT; } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); } while(m==EMPTY_QUEUE); @@ -2770,6 +2831,8 @@ static s32 adpt_i2o_status_get(adpt_hba* return -ETIMEDOUT; } rmb(); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); } // Set up our number of outbound and inbound messages @@ -3095,17 +3158,33 @@ static int adpt_i2o_query_scalar(adpt_hb int group, int field, void *buf, int buflen) { u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field }; - u8 resblk[8+buflen]; /* 8 bytes for header */ + u8 *resblk; + int size; + /* 8 bytes for header */ + resblk = kmalloc(sizeof(u8) * (8+buflen), GFP_KERNEL|ADDR32); + if (resblk == NULL) { + printk(KERN_CRIT "%s: query scalar failed; Out of memory.\n", pHba->name); + return -ENOMEM; + } + if (field == -1) /* whole group */ opblk[4] = -1; size = adpt_i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET, pHba, tid, - opblk, sizeof(opblk), resblk, sizeof(resblk)); + opblk, sizeof(opblk), resblk, sizeof(u8)*(8+buflen)); + if (size == -ETIME) { + printk(KERN_WARNING "%s: issue params failed; Timed out.\n", pHba->name); + return -ETIME; + } else if (size == -EINTR) { + printk(KERN_WARNING "%s: issue params failed; Interrupted.\n", pHba->name); + return -EINTR; + } memcpy(buf, resblk+8, buflen); /* cut off header */ + kfree(resblk); if (size < 0) return size; @@ -3139,6 +3218,7 @@ static int adpt_i2o_issue_params(int cmd msg[8] = virt_to_bus(resblk); if ((wait_status = adpt_i2o_post_wait(pHba, msg, sizeof(msg), 20))) { + printk("adpt_i2o_issue_params: post_wait failed (%p)\n", resblk); return wait_status; /* -DetailedStatus */ } --- linux-2.6.6/drivers/scsi/dpti.h 2003-06-14 12:17:55.000000000 -0700 +++ 25/drivers/scsi/dpti.h 2004-05-10 01:19:44.014047904 -0700 @@ -65,7 +65,7 @@ static int adpt_device_reset(Scsi_Cmnd* #include "dpt/dpti_i2o.h" #include "dpt/dpti_ioctl.h" -#define DPT_I2O_VERSION "2.4 Build 5" +#define DPT_I2O_VERSION "2.4 Build 5go" #define DPT_VERSION 2 #define DPT_REVISION '4' #define DPT_SUBREVISION '5' @@ -272,7 +272,7 @@ struct sg_simple_element { static void adpt_i2o_sys_shutdown(void); static int adpt_init(void); static int adpt_i2o_build_sys_table(void); -static void adpt_isr(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t adpt_isr(int irq, void *dev_id, struct pt_regs *regs); #ifdef REBOOT_NOTIFIER static int adpt_reboot_event(struct notifier_block *n, ulong code, void *p); #endif --- linux-2.6.6/drivers/scsi/ini9100u.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/scsi/ini9100u.c 2004-05-10 01:19:50.096123288 -0700 @@ -106,6 +106,8 @@ * - Changed the assumption that HZ = 100 * 10/17/03 mc - v1.04 * - added new DMA API support + * 06/01/04 jmd - v1.04a + * - Re-add reset_bus support **************************************************************************/ #define CVT_LINUX_VERSION(V,P,S) (V * 65536 + P * 256 + S) @@ -149,6 +151,7 @@ static Scsi_Host_Template driver_templat .queuecommand = i91u_queue, // .abort = i91u_abort, // .reset = i91u_reset, + .eh_bus_reset_handler = i91u_bus_reset, .bios_param = i91u_biosparam, .can_queue = 1, .this_id = 1, @@ -161,7 +164,7 @@ static Scsi_Host_Template driver_templat char *i91uCopyright = "Copyright (C) 1996-98"; char *i91uInitioName = "by Initio Corporation"; char *i91uProductName = "INI-9X00U/UW"; -char *i91uVersion = "v1.04"; +char *i91uVersion = "v1.04a"; #define TULSZ(sz) (sizeof(sz) / sizeof(sz[0])) #define TUL_RDWORD(x,y) (short)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) )) @@ -550,6 +553,15 @@ int i91u_reset(Scsi_Cmnd * SCpnt, unsign return tul_device_reset(pHCB, (ULONG) SCpnt, SCpnt->device->id, reset_flags); } +int i91u_bus_reset(Scsi_Cmnd * SCpnt) +{ + HCS *pHCB; + + pHCB = (HCS *) SCpnt->device->host->base; + tul_reset_scsi(pHCB, 0); + return SUCCESS; +} + /* * Return the "logical geometry" */ --- linux-2.6.6/drivers/scsi/ini9100u.h 2003-09-08 13:58:58.000000000 -0700 +++ 25/drivers/scsi/ini9100u.h 2004-05-10 01:19:50.096123288 -0700 @@ -82,10 +82,11 @@ extern int i91u_command(Scsi_Cmnd *); extern int i91u_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); extern int i91u_abort(Scsi_Cmnd *); extern int i91u_reset(Scsi_Cmnd *, unsigned int); +extern int i91u_bus_reset(Scsi_Cmnd *); extern int i91u_biosparam(struct scsi_device *, struct block_device *, sector_t, int *); -#define i91u_REVID "Initio INI-9X00U/UW SCSI device driver; Revision: 1.03g" +#define i91u_REVID "Initio INI-9X00U/UW SCSI device driver; Revision: 1.04a" #define VIRT_TO_BUS(i) (unsigned int) virt_to_bus((void *)(i)) #define ULONG unsigned long --- linux-2.6.6/drivers/scsi/Kconfig 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/scsi/Kconfig 2004-05-10 01:19:44.015047752 -0700 @@ -363,7 +363,7 @@ source "drivers/scsi/aic7xxx/Kconfig.aic # All the I2O code and drivers do not seem to be 64bit safe. config SCSI_DPT_I2O tristate "Adaptec I2O RAID support " - depends on !64BIT && SCSI && BROKEN + depends on !64BIT && SCSI help This driver supports all of Adaptec's I2O based RAID controllers as well as the DPT SmartRaid V cards. This is an Adaptec maintained @@ -434,10 +434,18 @@ config SCSI_ATA_PIIX If unsure, say N. config SCSI_SATA_PROMISE - tristate "Promise SATA support" + tristate "Promise SATA TX2/TX4 support" + depends on SCSI_SATA && PCI + help + This option enables support for Promise Serial ATA TX2/TX4. + + If unsure, say N. + +config SCSI_SATA_SX4 + tristate "Promise SATA SX4 support" depends on SCSI_SATA && PCI && EXPERIMENTAL help - This option enables support for Promise Serial ATA. + This option enables support for Promise Serial ATA SX4. If unsure, say N. --- linux-2.6.6/drivers/scsi/libata-core.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/scsi/libata-core.c 2004-05-10 01:19:03.399222296 -0700 @@ -34,7 +34,9 @@ #include #include #include +#include #include +#include #include #include "scsi.h" #include "hosts.h" @@ -44,14 +46,10 @@ #include "libata.h" -static void atapi_cdb_send(struct ata_port *ap); static unsigned int ata_busy_sleep (struct ata_port *ap, unsigned long tmout_pat, unsigned long tmout); static void __ata_dev_select (struct ata_port *ap, unsigned int device); -#if 0 /* to be used eventually */ -static void ata_qc_push (struct ata_queued_cmd *qc, unsigned int append); -#endif static void ata_dma_complete(struct ata_port *ap, u8 host_stat, unsigned int done_late); static void ata_host_set_pio(struct ata_port *ap); @@ -59,8 +57,10 @@ static void ata_host_set_udma(struct ata static void ata_dev_set_pio(struct ata_port *ap, unsigned int device); static void ata_dev_set_udma(struct ata_port *ap, unsigned int device); static void ata_set_mode(struct ata_port *ap); +static int ata_qc_issue_prot(struct ata_queued_cmd *qc); static unsigned int ata_unique_id = 1; +static struct workqueue_struct *ata_wq; MODULE_AUTHOR("Jeff Garzik"); MODULE_DESCRIPTION("Library module for ATA devices"); @@ -74,13 +74,6 @@ static const char * thr_state_name[] = { "THR_IDLE", "THR_PROBE_SUCCESS", "THR_PROBE_START", - "THR_PIO_POLL", - "THR_PIO_TMOUT", - "THR_PIO", - "THR_PIO_LAST", - "THR_PIO_LAST_POLL", - "THR_PIO_ERR", - "THR_PACKET", }; /** @@ -315,8 +308,6 @@ static inline void ata_exec(struct ata_p static void ata_tf_to_host(struct ata_port *ap, struct ata_taskfile *tf) { - init_MUTEX_LOCKED(&ap->sem); - ap->ops->tf_load(ap, tf); ata_exec(ap, tf); @@ -337,8 +328,6 @@ static void ata_tf_to_host(struct ata_po void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf) { - init_MUTEX_LOCKED(&ap->sem); - ap->ops->tf_load(ap, tf); ap->ops->exec_command(ap, tf); } @@ -440,6 +429,77 @@ u8 ata_check_status_mmio(struct ata_port } /** + * ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure + * @tf: Taskfile to convert + * @fis: Buffer into which data will output + * + * Converts a standard ATA taskfile to a Serial ATA + * FIS structure (Register - Host to Device). + * + * LOCKING: + * Inherited from caller. + */ + +void ata_tf_to_fis(struct ata_taskfile *tf, u8 *fis, u8 pmp) +{ + fis[0] = 0x27; /* Register - Host to Device FIS */ + fis[1] = (pmp & 0xf) | (1 << 7); /* Port multiplier number, + bit 7 indicates Command FIS */ + fis[2] = tf->command; + fis[3] = tf->feature; + + fis[4] = tf->lbal; + fis[5] = tf->lbam; + fis[6] = tf->lbah; + fis[7] = tf->device; + + fis[8] = tf->hob_lbal; + fis[9] = tf->hob_lbam; + fis[10] = tf->hob_lbah; + fis[11] = tf->hob_feature; + + fis[12] = tf->nsect; + fis[13] = tf->hob_nsect; + fis[14] = 0; + fis[15] = tf->ctl; + + fis[16] = 0; + fis[17] = 0; + fis[18] = 0; + fis[19] = 0; +} + +/** + * ata_tf_from_fis - Convert SATA FIS to ATA taskfile + * @fis: Buffer from which data will be input + * @tf: Taskfile to output + * + * Converts a standard ATA taskfile to a Serial ATA + * FIS structure (Register - Host to Device). + * + * LOCKING: + * Inherited from caller. + */ + +void ata_tf_from_fis(u8 *fis, struct ata_taskfile *tf) +{ + tf->command = fis[2]; /* status */ + tf->feature = fis[3]; /* error */ + + tf->lbal = fis[4]; + tf->lbam = fis[5]; + tf->lbah = fis[6]; + tf->device = fis[7]; + + tf->hob_lbal = fis[8]; + tf->hob_lbam = fis[9]; + tf->hob_lbah = fis[10]; + + tf->nsect = fis[12]; + tf->hob_nsect = fis[13]; +} + +/** * ata_prot_to_cmd - determine which read/write opcodes to use * @protocol: ATA_PROT_xxx taskfile protocol * @lba48: true is lba48 is present @@ -1928,20 +1988,20 @@ static int ata_sg_setup(struct ata_queue static unsigned long ata_pio_poll(struct ata_port *ap) { u8 status; - unsigned int poll_state = THR_UNKNOWN; - unsigned int reg_state = THR_UNKNOWN; - const unsigned int tmout_state = THR_PIO_TMOUT; - - switch (ap->thr_state) { - case THR_PIO: - case THR_PIO_POLL: - poll_state = THR_PIO_POLL; - reg_state = THR_PIO; - break; - case THR_PIO_LAST: - case THR_PIO_LAST_POLL: - poll_state = THR_PIO_LAST_POLL; - reg_state = THR_PIO_LAST; + unsigned int poll_state = PIO_ST_UNKNOWN; + unsigned int reg_state = PIO_ST_UNKNOWN; + const unsigned int tmout_state = PIO_ST_TMOUT; + + switch (ap->pio_task_state) { + case PIO_ST: + case PIO_ST_POLL: + poll_state = PIO_ST_POLL; + reg_state = PIO_ST; + break; + case PIO_ST_LAST: + case PIO_ST_LAST_POLL: + poll_state = PIO_ST_LAST_POLL; + reg_state = PIO_ST_LAST; break; default: BUG(); @@ -1950,39 +2010,19 @@ static unsigned long ata_pio_poll(struct status = ata_chk_status(ap); if (status & ATA_BUSY) { - if (time_after(jiffies, ap->thr_timeout)) { - ap->thr_state = tmout_state; + if (time_after(jiffies, ap->pio_task_timeout)) { + ap->pio_task_state = tmout_state; return 0; } - ap->thr_state = poll_state; + ap->pio_task_state = poll_state; return ATA_SHORT_PAUSE; } - ap->thr_state = reg_state; + ap->pio_task_state = reg_state; return 0; } /** - * ata_pio_start - - * @qc: - * - * LOCKING: - * spin_lock_irqsave(host_set lock) - */ - -static void ata_pio_start (struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - - assert(qc->tf.protocol == ATA_PROT_PIO); - - qc->flags |= ATA_QCFLAG_POLL; - qc->tf.ctl |= ATA_NIEN; /* disable interrupts */ - ata_tf_to_host_nolock(ap, &qc->tf); - ata_thread_wake(ap, THR_PIO); -} - -/** * ata_pio_complete - * @ap: * @@ -1992,7 +2032,6 @@ static void ata_pio_start (struct ata_qu static void ata_pio_complete (struct ata_port *ap) { struct ata_queued_cmd *qc; - unsigned long flags; u8 drv_stat; /* @@ -2001,31 +2040,29 @@ static void ata_pio_complete (struct ata * a chk-status or two. If not, the drive is probably seeking * or something. Snooze for a couple msecs, then * chk-status again. If still busy, fall back to - * THR_PIO_POLL state. + * PIO_ST_POLL state. */ drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10); if (drv_stat & (ATA_BUSY | ATA_DRQ)) { msleep(2); drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10); if (drv_stat & (ATA_BUSY | ATA_DRQ)) { - ap->thr_state = THR_PIO_LAST_POLL; - ap->thr_timeout = jiffies + ATA_TMOUT_PIO; + ap->pio_task_state = PIO_ST_LAST_POLL; + ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO; return; } } drv_stat = ata_wait_idle(ap); if (drv_stat & (ATA_BUSY | ATA_DRQ)) { - ap->thr_state = THR_PIO_ERR; + ap->pio_task_state = PIO_ST_ERR; return; } qc = ata_qc_from_tag(ap, ap->active_tag); assert(qc != NULL); - spin_lock_irqsave(&ap->host_set->lock, flags); - ap->thr_state = THR_IDLE; - spin_unlock_irqrestore(&ap->host_set->lock, flags); + ap->pio_task_state = PIO_ST_IDLE; ata_irq_on(ap); @@ -2053,22 +2090,22 @@ static void ata_pio_sector(struct ata_po * a chk-status or two. If not, the drive is probably seeking * or something. Snooze for a couple msecs, then * chk-status again. If still busy, fall back to - * THR_PIO_POLL state. + * PIO_ST_POLL state. */ status = ata_busy_wait(ap, ATA_BUSY, 5); if (status & ATA_BUSY) { msleep(2); status = ata_busy_wait(ap, ATA_BUSY, 10); if (status & ATA_BUSY) { - ap->thr_state = THR_PIO_POLL; - ap->thr_timeout = jiffies + ATA_TMOUT_PIO; + ap->pio_task_state = PIO_ST_POLL; + ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO; return; } } /* handle BSY=0, DRQ=0 as error */ if ((status & ATA_DRQ) == 0) { - ap->thr_state = THR_PIO_ERR; + ap->pio_task_state = PIO_ST_ERR; return; } @@ -2079,7 +2116,7 @@ static void ata_pio_sector(struct ata_po sg = qc->sg; if (qc->cursect == (qc->nsect - 1)) - ap->thr_state = THR_PIO_LAST; + ap->pio_task_state = PIO_ST_LAST; buf = kmap(sg[qc->cursg].page) + sg[qc->cursg].offset + (qc->cursg_ofs * ATA_SECT_SIZE); @@ -2107,20 +2144,48 @@ static void ata_pio_sector(struct ata_po kunmap(sg[qc->cursg].page); } -#if 0 /* to be used eventually */ -/** - * ata_eng_schedule - run an iteration of the pio/dma/whatever engine - * @ap: port on which activity will occur - * @eng: instance of engine - * - * LOCKING: - * spin_lock_irqsave(host_set lock) - */ -static void ata_eng_schedule (struct ata_port *ap, struct ata_engine *eng) +static void ata_pio_task(void *_data) { - /* FIXME */ + struct ata_port *ap = _data; + unsigned long timeout = 0; + + switch (ap->pio_task_state) { + case PIO_ST: + ata_pio_sector(ap); + break; + + case PIO_ST_LAST: + ata_pio_complete(ap); + break; + + case PIO_ST_POLL: + case PIO_ST_LAST_POLL: + timeout = ata_pio_poll(ap); + break; + + case PIO_ST_TMOUT: + printk(KERN_ERR "ata%d: FIXME: PIO_ST_TMOUT\n", /* FIXME */ + ap->id); + timeout = 11 * HZ; + break; + + case PIO_ST_ERR: + printk(KERN_ERR "ata%d: FIXME: PIO_ST_ERR\n", /* FIXME */ + ap->id); + timeout = 11 * HZ; + break; + } + + if ((ap->pio_task_state != PIO_ST_IDLE) && + (ap->pio_task_state != PIO_ST_TMOUT) && + (ap->pio_task_state != PIO_ST_ERR)) { + if (timeout) + queue_delayed_work(ata_wq, &ap->pio_task, + timeout); + else + queue_work(ata_wq, &ap->pio_task); + } } -#endif /** * ata_eng_timeout - Handle timeout of queued command @@ -2246,8 +2311,6 @@ struct ata_queued_cmd *ata_qc_new_init(s qc->ap = ap; qc->dev = dev; qc->cursect = qc->cursg = qc->cursg_ofs = 0; - INIT_LIST_HEAD(&qc->node); - init_MUTEX_LOCKED(&qc->sem); ata_tf_init(ap, &qc->tf, dev->devno); @@ -2304,52 +2367,33 @@ void ata_qc_complete(struct ata_queued_c do_clear = 1; } - up(&qc->sem); + if (qc->waiting) + complete(qc->waiting); if (likely(do_clear)) clear_bit(tag, &ap->qactive); } -#if 0 /* to be used eventually */ /** - * ata_qc_push - - * @qc: - * @append: + * ata_qc_issue - issue taskfile to device + * @qc: command to issue to device * - * LOCKING: - * spin_lock_irqsave(host_set lock) - */ -static void ata_qc_push (struct ata_queued_cmd *qc, unsigned int append) -{ - struct ata_port *ap = qc->ap; - struct ata_engine *eng = &ap->eng; - - if (likely(append)) - list_add_tail(&qc->node, &eng->q); - else - list_add(&qc->node, &eng->q); - - if (!test_and_set_bit(ATA_EFLG_ACTIVE, &eng->flags)) - ata_eng_schedule(ap, eng); -} -#endif - -/** - * ata_qc_issue - - * @qc: + * Prepare an ATA command to submission to device. + * This includes mapping the data into a DMA-able + * area, filling in the S/G table, and finally + * writing the taskfile to hardware, starting the command. * * LOCKING: + * spin_lock_irqsave(host_set lock) * * RETURNS: - * + * Zero on success, negative on error. */ + int ata_qc_issue(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; struct scsi_cmnd *cmd = qc->scsicmd; - unsigned int dma = qc->flags & ATA_QCFLAG_DMA; - - ata_dev_select(ap, qc->dev->devno, 1, 0); /* set up SG table */ if (cmd->use_sg) { @@ -2365,20 +2409,61 @@ int ata_qc_issue(struct ata_queued_cmd * qc->ap->active_tag = qc->tag; qc->flags |= ATA_QCFLAG_ACTIVE; - if (likely(dma)) { - ap->ops->tf_load(ap, &qc->tf); /* load tf registers */ - ap->ops->bmdma_start(qc); /* initiate bmdma */ - } else - /* load tf registers, initiate polling pio */ - ata_pio_start(qc); - - return 0; + return ata_qc_issue_prot(qc); err_out: return -1; } /** + * ata_qc_issue_prot - issue taskfile to device in proto-dependent manner + * @qc: command to issue to device + * + * Using various libata functions and hooks, this function + * starts an ATA command. ATA commands are grouped into + * classes called "protocols", and issuing each type of protocol + * is slightly different. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * Zero on success, negative on error. + */ + +static int ata_qc_issue_prot(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + + ata_dev_select(ap, qc->dev->devno, 1, 0); + + switch (qc->tf.protocol) { + case ATA_PROT_NODATA: + ata_tf_to_host_nolock(ap, &qc->tf); + break; + + case ATA_PROT_DMA: + ap->ops->tf_load(ap, &qc->tf); /* load tf registers */ + ap->ops->bmdma_start(qc); /* initiate bmdma */ + break; + + case ATA_PROT_PIO: /* load tf registers, initiate polling pio */ + qc->flags |= ATA_QCFLAG_POLL; + qc->tf.ctl |= ATA_NIEN; /* disable interrupts */ + ata_tf_to_host_nolock(ap, &qc->tf); + ap->pio_task_state = PIO_ST; + queue_work(ata_wq, &ap->pio_task); + break; + + default: + WARN_ON(1); + return -1; + } + + return 0; +} + +/** * ata_bmdma_start_mmio - * @qc: * @@ -2614,36 +2699,6 @@ irqreturn_t ata_interrupt (int irq, void } /** - * ata_thread_wake - - * @ap: - * @thr_state: - * - * LOCKING: - * spin_lock_irqsave(host_set lock) - */ - -void ata_thread_wake(struct ata_port *ap, unsigned int thr_state) -{ - assert(ap->thr_state == THR_IDLE); - ap->thr_state = thr_state; - up(&ap->thr_sem); -} - -/** - * ata_thread_timer - - * @opaque: - * - * LOCKING: - */ - -static void ata_thread_timer(unsigned long opaque) -{ - struct ata_port *ap = (struct ata_port *) opaque; - - up(&ap->thr_sem); -} - -/** * ata_thread_iter - * @ap: * @@ -2666,7 +2721,6 @@ static unsigned long ata_thread_iter(str break; case THR_PROBE_START: - down(&ap->sem); ap->thr_state = THR_PORT_RESET; break; @@ -2685,40 +2739,8 @@ static unsigned long ata_thread_iter(str break; case THR_AWAIT_DEATH: - timeout = -1; - break; - case THR_IDLE: - timeout = 30 * HZ; - break; - - case THR_PIO: - ata_pio_sector(ap); - break; - - case THR_PIO_LAST: - ata_pio_complete(ap); - break; - - case THR_PIO_POLL: - case THR_PIO_LAST_POLL: - timeout = ata_pio_poll(ap); - break; - - case THR_PIO_TMOUT: - printk(KERN_ERR "ata%d: FIXME: THR_PIO_TMOUT\n", /* FIXME */ - ap->id); - timeout = 11 * HZ; - break; - - case THR_PIO_ERR: - printk(KERN_ERR "ata%d: FIXME: THR_PIO_ERR\n", /* FIXME */ - ap->id); - timeout = 11 * HZ; - break; - - case THR_PACKET: - atapi_cdb_send(ap); + timeout = -1; break; default: @@ -2732,87 +2754,23 @@ static unsigned long ata_thread_iter(str return timeout; } -/** - * ata_thread - - * @data: - * - * LOCKING: - * - * RETURNS: - * - */ - -static int ata_thread (void *data) +void atapi_start(struct ata_queued_cmd *qc) { - struct ata_port *ap = data; - long timeout; - - daemonize ("katad-%u", ap->id); - allow_signal(SIGTERM); - - while (1) { - cond_resched(); - - timeout = ata_thread_iter(ap); - - if (signal_pending (current)) - flush_signals(current); - - if (current->flags & PF_FREEZE) - refrigerator(PF_FREEZE); - - - if ((timeout < 0) || (ap->time_to_die)) - break; - - /* note sleeping for full timeout not guaranteed (that's ok) */ - if (timeout) { - mod_timer(&ap->thr_timer, jiffies + timeout); - down_interruptible(&ap->thr_sem); - - if (signal_pending (current)) - flush_signals(current); - - if (ap->time_to_die) - break; - } - } - - printk(KERN_DEBUG "ata%u: thread exiting\n", ap->id); - ap->thr_pid = -1; - del_timer_sync(&ap->thr_timer); - complete_and_exit (&ap->thr_exited, 0); -} - -/** - * ata_thread_kill - kill per-port kernel thread - * @ap: port those thread is to be killed - * - * LOCKING: - * - */ + struct ata_port *ap = qc->ap; -static int ata_thread_kill(struct ata_port *ap) -{ - int ret = 0; + qc->flags |= ATA_QCFLAG_ACTIVE; + ap->active_tag = qc->tag; - if (ap->thr_pid >= 0) { - ap->time_to_die = 1; - wmb(); - ret = kill_proc(ap->thr_pid, SIGTERM, 1); - if (ret) - printk(KERN_ERR "ata%d: unable to kill kernel thread\n", - ap->id); - else - wait_for_completion(&ap->thr_exited); - } + ata_dev_select(ap, qc->dev->devno, 1, 0); + ata_tf_to_host_nolock(ap, &qc->tf); + queue_work(ata_wq, &ap->packet_task); - return ret; + VPRINTK("EXIT\n"); } /** - * atapi_cdb_send - Write CDB bytes to hardware - * @ap: Port to which ATAPI device is attached. + * atapi_packet_task - Write CDB bytes to hardware + * @_data: Port to which ATAPI device is attached. * * When device has indicated its readiness to accept * a CDB, this function is called. Send the CDB. @@ -2824,8 +2782,9 @@ static int ata_thread_kill(struct ata_po * Kernel thread context (may sleep) */ -static void atapi_cdb_send(struct ata_port *ap) +static void atapi_packet_task(void *_data) { + struct ata_port *ap = _data; struct ata_queued_cmd *qc; u8 status; @@ -2850,30 +2809,17 @@ static void atapi_cdb_send(struct ata_po qc->scsicmd->cmnd, ap->host->max_cmd_len / 4); /* if we are DMA'ing, irq handler takes over from here */ - if (qc->tf.feature == ATAPI_PKT_DMA) - goto out; - - /* sleep-wait for BSY to clear */ - DPRINTK("busy wait 2\n"); - if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB)) - goto err_out; - - /* wait for BSY,DRQ to clear */ - status = ata_wait_idle(ap); - if (status & (ATA_BUSY | ATA_DRQ)) - goto err_out; - - /* transaction completed, indicate such to scsi stack */ - ata_qc_complete(qc, status, 0); - ata_irq_on(ap); + if (qc->tf.protocol == ATA_PROT_ATAPI_DMA) { + /* FIXME: start DMA here */ + } else { + ap->pio_task_state = PIO_ST; + queue_work(ata_wq, &ap->pio_task); + } -out: - ap->thr_state = THR_IDLE; return; err_out: ata_qc_complete(qc, ATA_ERR, 0); - goto out; } int ata_port_start (struct ata_port *ap) @@ -2883,7 +2829,7 @@ int ata_port_start (struct ata_port *ap) ap->prd = pci_alloc_consistent(pdev, ATA_PRD_TBL_SZ, &ap->prd_dma); if (!ap->prd) return -ENOMEM; - + DPRINTK("prd alloc, virt %p, dma %llx\n", ap->prd, (unsigned long long) ap->prd_dma); return 0; @@ -2896,6 +2842,21 @@ void ata_port_stop (struct ata_port *ap) pci_free_consistent(pdev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma); } +static void ata_probe_task(void *_data) +{ + struct ata_port *ap = _data; + long timeout; + + timeout = ata_thread_iter(ap); + if (timeout < 0) + return; + + if (timeout > 0) + queue_delayed_work(ata_wq, &ap->probe_task, timeout); + else + queue_work(ata_wq, &ap->probe_task); +} + /** * ata_host_remove - * @ap: @@ -2913,8 +2874,6 @@ static void ata_host_remove(struct ata_p if (do_unregister) scsi_remove_host(sh); - ata_thread_kill(ap); /* FIXME: check return val */ - ap->ops->port_stop(ap); } @@ -2958,21 +2917,14 @@ static void ata_host_init(struct ata_por ap->active_tag = ATA_TAG_POISON; ap->last_ctl = 0xFF; - /* ata_engine init */ - ap->eng.flags = 0; - INIT_LIST_HEAD(&ap->eng.q); + INIT_WORK(&ap->packet_task, atapi_packet_task, ap); + INIT_WORK(&ap->pio_task, ata_pio_task, ap); + INIT_WORK(&ap->probe_task, ata_probe_task, ap); for (i = 0; i < ATA_MAX_DEVICES; i++) ap->device[i].devno = i; - init_completion(&ap->thr_exited); init_MUTEX_LOCKED(&ap->probe_sem); - init_MUTEX_LOCKED(&ap->sem); - init_MUTEX_LOCKED(&ap->thr_sem); - - init_timer(&ap->thr_timer); - ap->thr_timer.function = ata_thread_timer; - ap->thr_timer.data = (unsigned long) ap; #ifdef ATA_IRQ_TRAP ap->stats.unhandled_irq = 1; @@ -3015,18 +2967,8 @@ static struct ata_port * ata_host_add(st if (rc) goto err_out; - ap->thr_pid = kernel_thread(ata_thread, ap, CLONE_FS | CLONE_FILES); - if (ap->thr_pid < 0) { - printk(KERN_ERR "ata%d: unable to start kernel thread\n", - ap->id); - goto err_out_free; - } - return ap; -err_out_free: - ap->ops->port_stop(ap); - err_out: scsi_host_put(host); return NULL; @@ -3106,7 +3048,7 @@ int ata_device_add(struct ata_probe_ent ap = host_set->ports[i]; DPRINTK("ata%u: probe begin\n", ap->id); - up(&ap->sem); /* start probe */ + queue_work(ata_wq, &ap->probe_task); /* start probe */ DPRINTK("ata%u: probe-wait begin\n", ap->id); down(&ap->probe_sem); /* wait for end */ @@ -3489,11 +3431,21 @@ int pci_test_config_bits(struct pci_dev static int __init ata_init(void) { + ata_wq = create_workqueue("ata"); + if (!ata_wq) + return -ENOMEM; + printk(KERN_DEBUG "libata version " DRV_VERSION " loaded.\n"); return 0; } +static void __exit ata_exit(void) +{ + destroy_workqueue(ata_wq); +} + module_init(ata_init); +module_exit(ata_exit); /* * libata is essentially a library of internal helper functions for @@ -3512,6 +3464,8 @@ EXPORT_SYMBOL_GPL(ata_tf_load_pio); EXPORT_SYMBOL_GPL(ata_tf_load_mmio); EXPORT_SYMBOL_GPL(ata_tf_read_pio); EXPORT_SYMBOL_GPL(ata_tf_read_mmio); +EXPORT_SYMBOL_GPL(ata_tf_to_fis); +EXPORT_SYMBOL_GPL(ata_tf_from_fis); EXPORT_SYMBOL_GPL(ata_check_status_pio); EXPORT_SYMBOL_GPL(ata_check_status_mmio); EXPORT_SYMBOL_GPL(ata_exec_command_pio); --- linux-2.6.6/drivers/scsi/libata.h 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/scsi/libata.h 2004-05-10 01:19:03.401221992 -0700 @@ -35,7 +35,6 @@ struct ata_scsi_args { void (*done)(struct scsi_cmnd *); }; - /* libata-core.c */ extern void ata_dev_id_string(struct ata_device *dev, unsigned char *s, unsigned int ofs, unsigned int len); @@ -45,7 +44,7 @@ extern int ata_qc_issue(struct ata_queue extern void ata_dev_select(struct ata_port *ap, unsigned int device, unsigned int wait, unsigned int can_sleep); extern void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf); -extern void ata_thread_wake(struct ata_port *ap, unsigned int thr_state); +extern void atapi_start(struct ata_queued_cmd *qc); /* libata-scsi.c */ --- linux-2.6.6/drivers/scsi/libata-scsi.c 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/scsi/libata-scsi.c 2004-05-10 01:19:27.053626280 -0700 @@ -167,8 +167,44 @@ int ata_scsi_slave_config(struct scsi_de { sdev->use_10_for_rw = 1; sdev->use_10_for_ms = 1; + blk_queue_max_phys_segments(sdev->request_queue, LIBATA_MAX_PRD); + if (sdev->id < ATA_MAX_DEVICES) { + struct ata_port *ap; + struct ata_device *dev; + + ap = (struct ata_port *) &sdev->host->hostdata[0]; + dev = &ap->device[sdev->id]; + + /* TODO: 1024 is an arbitrary number, not the + * hardware maximum. This should be increased to + * 65534 when Jens Axboe's patch for dynamically + * determining max_sectors is merged. + */ + if (dev->flags & ATA_DFLAG_LBA48) { + sdev->host->max_sectors = 2048; + blk_queue_max_sectors(sdev->request_queue, 2048); + } + } + + if (sdev->id < ATA_MAX_DEVICES) { + struct ata_port *ap; + struct ata_device *dev; + + ap = (struct ata_port *) &sdev->host->hostdata[0]; + dev = &ap->device[sdev->id]; + + if (dev->flags & ATA_DFLAG_LBA48) { + sdev->host->max_sectors = 65534; + blk_queue_max_sectors(sdev->request_queue, 65534); + printk(KERN_INFO "ata%u: dev %u max request 32MB (lba48)\n", + ap->id, sdev->id); + } else + printk(KERN_INFO "ata%u: dev %u max request 128K\n", + ap->id, sdev->id); + } + return 0; /* scsi layer doesn't check return value, sigh */ } @@ -884,8 +920,7 @@ static void atapi_scsi_queuecmd(struct a struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { struct ata_queued_cmd *qc; - u8 *scsicmd = cmd->cmnd, status; - unsigned int doing_dma = 0; + u8 *scsicmd = cmd->cmnd; VPRINTK("ENTER, drv_stat = 0x%x\n", ata_chk_status(ap)); @@ -925,52 +960,17 @@ static void atapi_scsi_queuecmd(struct a qc->tf.command = ATA_CMD_PACKET; - /* set up SG table */ if (cmd->sc_data_direction == SCSI_DATA_NONE) { - ap->active_tag = qc->tag; - qc->flags |= ATA_QCFLAG_ACTIVE | ATA_QCFLAG_POLL; qc->tf.protocol = ATA_PROT_ATAPI; - - ata_dev_select(ap, dev->devno, 1, 0); - - DPRINTK("direction: none\n"); + qc->flags |= ATA_QCFLAG_POLL; qc->tf.ctl |= ATA_NIEN; /* disable interrupts */ - ata_tf_to_host_nolock(ap, &qc->tf); } else { - qc->flags |= ATA_QCFLAG_SG; /* data is present; dma-map it */ - qc->tf.feature = ATAPI_PKT_DMA; qc->tf.protocol = ATA_PROT_ATAPI_DMA; - - doing_dma = 1; - - /* select device, send command to hardware */ - if (ata_qc_issue(qc)) - goto err_out; - } - - status = ata_busy_wait(ap, ATA_BUSY, 1000); - if (status & ATA_BUSY) { - ata_thread_wake(ap, THR_PACKET); - return; + qc->flags |= ATA_QCFLAG_SG; /* data is present; dma-map it */ + qc->tf.feature |= ATAPI_PKT_DMA; } - if ((status & ATA_DRQ) == 0) - goto err_out; - - /* FIXME: mmio-ize */ - DPRINTK("writing cdb\n"); - outsl(ap->ioaddr.data_addr, scsicmd, ap->host->max_cmd_len / 4); - - if (!doing_dma) - ata_thread_wake(ap, THR_PACKET); - VPRINTK("EXIT\n"); - return; - -err_out: - if (!doing_dma) - ata_irq_on(ap); /* re-enable interrupts */ - ata_bad_cdb(cmd, done); - DPRINTK("EXIT - badcmd\n"); + atapi_start(qc); } /** --- linux-2.6.6/drivers/scsi/Makefile 2004-05-09 21:07:24.000000000 -0700 +++ 25/drivers/scsi/Makefile 2004-05-10 01:19:04.849001896 -0700 @@ -75,7 +75,8 @@ obj-$(CONFIG_SCSI_NCR53C406A) += NCR53c4 obj-$(CONFIG_SCSI_NCR_D700) += 53c700.o NCR_D700.o obj-$(CONFIG_SCSI_NCR_Q720) += NCR_Q720_mod.o obj-$(CONFIG_SCSI_SYM53C416) += sym53c416.o -obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas.o +obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas408.o qlogicfas.o +obj-$(CONFIG_PCMCIA_QLOGIC) += qlogicfas408.o obj-$(CONFIG_SCSI_QLOGIC_ISP) += qlogicisp.o obj-$(CONFIG_SCSI_QLOGIC_FC) += qlogicfc.o obj-$(CONFIG_SCSI_QLOGIC_1280) += qla1280.o @@ -124,6 +125,7 @@ obj-$(CONFIG_SCSI_SATA_SIL) += libata.o obj-$(CONFIG_SCSI_SATA_VIA) += libata.o sata_via.o obj-$(CONFIG_SCSI_SATA_VITESSE) += libata.o sata_vsc.o obj-$(CONFIG_SCSI_SATA_SIS) += libata.o sata_sis.o +obj-$(CONFIG_SCSI_SATA_SX4) += libata.o sata_sx4.o obj-$(CONFIG_ARM) += arm/ --- linux-2.6.6/drivers/scsi/ncr53c8xx.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/scsi/ncr53c8xx.c 2004-05-10 01:19:04.874997944 -0700 @@ -307,7 +307,7 @@ typedef u32 tagmap_t; ** The maximum number of segments a transfer is split into. ** We support up to 127 segments for both read and write. ** The data scripts are broken into 2 sub-scripts. -** 80 (MAX_SCATTERL) segments are moved from a sub-script +** 80 (MAX_SCATTERL) segments are moved from a sub-script ** in on-chip RAM. This makes data transfers shorter than ** 80k (assuming 1k fs) as fast as possible. */ @@ -4542,7 +4542,7 @@ static int ncr_queue_command (ncb_p np, /* ** command */ - memcpy(cp->cdb_buf, cmd->cmnd, MIN(cmd->cmd_len, sizeof(cp->cdb_buf))); + memcpy(cp->cdb_buf, cmd->cmnd, min_t(int, cmd->cmd_len, sizeof(cp->cdb_buf))); cp->phys.cmd.addr = cpu_to_scr(CCB_PHYS (cp, cdb_buf[0])); cp->phys.cmd.size = cpu_to_scr(cmd->cmd_len); @@ -5172,7 +5172,7 @@ void ncr_complete (ncb_p np, ccb_p cp) ** Copy back sense data to caller's buffer. */ memcpy(cmd->sense_buffer, cp->sense_buf, - MIN(sizeof(cmd->sense_buffer), sizeof(cp->sense_buf))); + min(sizeof(cmd->sense_buffer), sizeof(cp->sense_buf))); if (DEBUG_FLAGS & (DEBUG_RESULT|DEBUG_TINY)) { u_char * p = (u_char*) & cmd->sense_buffer; --- linux-2.6.6/drivers/scsi/nsp32.c 2003-10-08 15:07:09.000000000 -0700 +++ 25/drivers/scsi/nsp32.c 2004-05-10 01:19:04.878997336 -0700 @@ -859,7 +859,7 @@ static int nsp32_reselection(Scsi_Cmnd * * or current nexus is not existed, unexpected * reselection is occurred. Send reject message. */ - if (newid >= NUMBER(data->lunt) || newlun >= NUMBER(data->lunt[0])) { + if (newid >= ARRAY_SIZE(data->lunt) || newlun >= ARRAY_SIZE(data->lunt[0])) { nsp32_msg(KERN_WARNING, "unknown id/lun"); return FALSE; } else if(data->lunt[newid][newlun].SCpnt == NULL) { @@ -1568,7 +1568,7 @@ static int nsp32_proc_info( SPRINTF("SDTR status\n"); - for(id = 0; id < NUMBER(data->target); id++) { + for (id = 0; id < ARRAY_SIZE(data->target); id++) { SPRINTF("id %d: ", id); @@ -1610,7 +1610,7 @@ static int nsp32_proc_info( } - thislength = MIN(thislength, length); + thislength = min(thislength, length); *start = buffer + offset; return thislength; @@ -2753,17 +2753,17 @@ static int nsp32_detect(Scsi_Host_Templa case CLOCK_4: /* If data->clock is CLOCK_4, then select 40M sync table. */ data->synct = nsp32_sync_table_40M; - data->syncnum = NUMBER(nsp32_sync_table_40M); + data->syncnum = ARRAY_SIZE(nsp32_sync_table_40M); break; case CLOCK_2: /* If data->clock is CLOCK_2, then select 20M sync table. */ data->synct = nsp32_sync_table_20M; - data->syncnum = NUMBER(nsp32_sync_table_20M); + data->syncnum = ARRAY_SIZE(nsp32_sync_table_20M); break; case PCICLK: /* If data->clock is PCICLK, then select pci sync table. */ data->synct = nsp32_sync_table_pci; - data->syncnum = NUMBER(nsp32_sync_table_pci); + data->syncnum = ARRAY_SIZE(nsp32_sync_table_pci); break; default: nsp32_msg(KERN_WARNING, @@ -2771,7 +2771,7 @@ static int nsp32_detect(Scsi_Host_Templa /* Use default value CLOCK_4 */ data->clock = CLOCK_4; data->synct = nsp32_sync_table_40M; - data->syncnum = NUMBER(nsp32_sync_table_40M); + data->syncnum = ARRAY_SIZE(nsp32_sync_table_40M); } /* @@ -2805,9 +2805,9 @@ static int nsp32_detect(Scsi_Host_Templa goto free_autoparam; } - for (i = 0; i < NUMBER(data->lunt); i++) { - for (j = 0; j < NUMBER(data->lunt[0]); j++) { - int offset = i * NUMBER(data->lunt[0]) + j; + for (i = 0; i < ARRAY_SIZE(data->lunt); i++) { + for (j = 0; j < ARRAY_SIZE(data->lunt[0]); j++) { + int offset = i * ARRAY_SIZE(data->lunt[0]) + j; nsp32_lunt tmp = { .SCpnt = NULL, .save_datp = 0, @@ -2825,7 +2825,7 @@ static int nsp32_detect(Scsi_Host_Templa /* * setup target */ - for (i = 0; i < NUMBER(data->target); i++) { + for (i = 0; i < ARRAY_SIZE(data->target); i++) { nsp32_target *target = &(data->target[i]); target->limit_entry = 0; @@ -3021,7 +3021,7 @@ static void nsp32_do_bus_reset(nsp32_hw_ * fall back to asynchronous transfer mode * initialize SDTR negotiation flag */ - for (i = 0; i < NUMBER(data->target); i++) { + for (i = 0; i < ARRAY_SIZE(data->target); i++) { nsp32_target *target = &data->target[i]; target->sync_flag = 0; --- linux-2.6.6/drivers/scsi/nsp32.h 2004-02-03 20:42:37.000000000 -0800 +++ 25/drivers/scsi/nsp32.h 2004-05-10 01:19:04.878997336 -0700 @@ -70,11 +70,7 @@ typedef u16 u16_le; /* * MACRO */ -#define NUMBER(arr) ((int) (sizeof(arr) / sizeof(arr[0]))) #define BIT(x) (1UL << (x)) -#ifndef MIN -# define MIN(a,b) ((a) > (b) ? (b) : (a)) -#endif /* * BASIC Definitions --- linux-2.6.6/drivers/scsi/pcmcia/Kconfig 2004-01-09 00:04:32.000000000 -0800 +++ 25/drivers/scsi/pcmcia/Kconfig 2004-05-10 01:19:04.879997184 -0700 @@ -69,4 +69,14 @@ config PCMCIA_QLOGIC To compile this driver as a module, choose M here: the module will be called qlogic_cs. +config PCMCIA_SYM53C500 + tristate "Symbios 53c500 PCMCIA support" + depends on m + help + Say Y here if you have a New Media Bus Toaster or other PCMCIA + SCSI adapter based on the Symbios 53c500 controller. + + To compile this driver as a module, choose M here: the + module will be called sym53c500_cs. + endmenu --- linux-2.6.6/drivers/scsi/pcmcia/Makefile 2003-06-14 12:18:09.000000000 -0700 +++ 25/drivers/scsi/pcmcia/Makefile 2004-05-10 01:19:04.879997184 -0700 @@ -6,7 +6,8 @@ obj-$(CONFIG_PCMCIA_QLOGIC) += qlogic_cs obj-$(CONFIG_PCMCIA_FDOMAIN) += fdomain_cs.o obj-$(CONFIG_PCMCIA_AHA152X) += aha152x_cs.o obj-$(CONFIG_PCMCIA_NINJA_SCSI) += nsp_cs.o +obj-$(CONFIG_PCMCIA_SYM53C500) += sym53c500_cs.o aha152x_cs-objs := aha152x_stub.o aha152x_core.o fdomain_cs-objs := fdomain_stub.o fdomain_core.o -qlogic_cs-objs := qlogic_stub.o qlogic_core.o +qlogic_cs-objs := qlogic_stub.o --- linux-2.6.6/drivers/scsi/pcmcia/nsp_cs.c 2004-02-03 20:42:37.000000000 -0800 +++ 25/drivers/scsi/pcmcia/nsp_cs.c 2004-05-10 01:19:04.881996880 -0700 @@ -315,7 +315,7 @@ static void nsphw_init_sync(nsp_hw_data int i; /* setup sync data */ - for ( i = 0; i < NUMBER(data->Sync); i++ ) { + for ( i = 0; i < ARRAY_SIZE(data->Sync); i++ ) { data->Sync[i] = tmp_sync; } } @@ -600,7 +600,7 @@ static int nsp_xfer(Scsi_Cmnd *SCpnt, in unsigned int base = SCpnt->device->host->io_port; nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; char *buf = data->MsgBuffer; - int len = MIN(MSGBUF_SIZE, data->MsgLen); + int len = min(MSGBUF_SIZE, data->MsgLen); int ptr; int ret; @@ -774,7 +774,7 @@ static void nsp_pio_read(Scsi_Cmnd *SCpn continue; } - res = MIN(res, SCpnt->SCp.this_residual); + res = min(res, SCpnt->SCp.this_residual); switch (data->TransferMode) { case MODE_IO32: @@ -868,7 +868,7 @@ static void nsp_pio_write(Scsi_Cmnd *SCp continue; } - res = MIN(SCpnt->SCp.this_residual, WFIFO_CRIT); + res = min(SCpnt->SCp.this_residual, WFIFO_CRIT); //nsp_dbg(NSP_DEBUG_DATA_IO, "ptr=0x%p this=0x%x res=0x%x", SCpnt->SCp.ptr, SCpnt->SCp.this_residual, res); switch (data->TransferMode) { @@ -1490,7 +1490,7 @@ nsp_proc_info( spin_unlock_irqrestore(&(data->Lock), flags); SPRINTF("SDTR status\n"); - for(id = 0; id < NUMBER(data->Sync); id++) { + for(id = 0; id < ARRAY_SIZE(data->Sync); id++) { SPRINTF("id %d: ", id); @@ -1534,7 +1534,7 @@ nsp_proc_info( } - thislength = MIN(thislength, length); + thislength = min(thislength, length); *start = buffer + offset; return thislength; --- linux-2.6.6/drivers/scsi/pcmcia/nsp_cs.h 2004-02-03 20:42:37.000000000 -0800 +++ 25/drivers/scsi/pcmcia/nsp_cs.h 2004-05-10 01:19:04.881996880 -0700 @@ -26,9 +26,7 @@ /************************************ * Some useful macros... */ -#define NUMBER(arr) ((int) (sizeof(arr) / sizeof(arr[0]))) /* from XtNumber() in /usr/X11R6/include/X11/Intrinsic.h */ #define BIT(x) (1L << (x)) -#define MIN(a,b) ((a) > (b) ? (b) : (a)) /* SCSI initiator must be ID 7 */ #define NSP_INITIATOR_ID 7 --- linux-2.6.6/drivers/scsi/pcmcia/qlogic_core.c 2003-06-14 12:18:52.000000000 -0700 +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,2 +0,0 @@ -#define PCMCIA 1 -#include "qlogicfas.c" --- linux-2.6.6/drivers/scsi/pcmcia/qlogic_stub.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/scsi/pcmcia/qlogic_stub.c 2004-05-10 01:19:04.883996576 -0700 @@ -47,7 +47,7 @@ #include "scsi.h" #include "hosts.h" -#include "../qlogicfas.h" +#include "../qlogicfas408.h" #include #include @@ -56,13 +56,13 @@ #include #include +/* Set the following to 2 to use normal interrupt (active high/totempole- + * tristate), otherwise use 0 (REQUIRED FOR PCMCIA) for active low, open + * drain + */ +#define INT_TYPE 0 -extern Scsi_Host_Template qlogicfas_driver_template; -extern void qlogicfas_preset(int port, int irq); -extern int qlogicfas_bus_reset(Scsi_Cmnd *); -extern irqreturn_t do_ql_ihandl(int irq, void *dev_id, struct pt_regs *regs); - -static char *qlogic_name = "qlogic_cs"; +static char qlogic_name[] = "qlogic_cs"; #ifdef PCMCIA_DEBUG static int pc_debug = PCMCIA_DEBUG; @@ -73,6 +73,24 @@ static char *version = "qlogic_cs.c 1.79 #define DEBUG(n, args...) #endif +static Scsi_Host_Template qlogicfas_driver_template = { + .module = THIS_MODULE, + .name = qlogic_name, + .proc_name = qlogic_name, + .info = qlogicfas408_info, + .queuecommand = qlogicfas408_queuecommand, + .eh_abort_handler = qlogicfas408_abort, + .eh_bus_reset_handler = qlogicfas408_bus_reset, + .eh_device_reset_handler= qlogicfas408_device_reset, + .eh_host_reset_handler = qlogicfas408_host_reset, + .bios_param = qlogicfas408_biosparam, + .can_queue = 1, + .this_id = -1, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 1, + .use_clustering = DISABLE_CLUSTERING, +}; + /*====================================================================*/ /* Parameters that can be set with 'insmod' */ @@ -110,29 +128,17 @@ static struct Scsi_Host *qlogic_detect(S int qltyp; /* type of chip */ int qinitid; struct Scsi_Host *shost; /* registered host structure */ - qlogicfas_priv_t priv; + struct qlogicfas408_priv *priv; - qltyp = inb(qbase + 0xe) & 0xf8; + qltyp = qlogicfas408_get_chip_type(qbase, INT_TYPE); qinitid = host->this_id; if (qinitid < 0) qinitid = 7; /* if no ID, use 7 */ - outb(1, qbase + 8); /* set for PIO pseudo DMA */ - REG0; - outb(0x40 | qlcfg8 | qinitid, qbase + 8); /* (ini) bus id, disable scsi rst */ - outb(qlcfg5, qbase + 5); /* select timer */ - outb(qlcfg9, qbase + 9); /* prescaler */ - -#if QL_RESET_AT_START - outb(3, qbase + 3); - REG1; - /* FIXME: timeout */ - while (inb(qbase + 0xf) & 4) - cpu_relax(); - REG0; -#endif + + qlogicfas408_setup(qbase, qinitid, INT_TYPE); host->name = qlogic_name; - shost = scsi_host_alloc(host, sizeof(struct qlogicfas_priv)); + shost = scsi_host_alloc(host, sizeof(struct qlogicfas408_priv)); if (!shost) goto err; shost->io_port = qbase; @@ -141,12 +147,14 @@ static struct Scsi_Host *qlogic_detect(S if (qlirq != -1) shost->irq = qlirq; - priv = (qlogicfas_priv_t)&(shost->hostdata[0]); + priv = get_priv_by_host(shost); priv->qlirq = qlirq; priv->qbase = qbase; priv->qinitid = qinitid; + priv->shost = shost; + priv->int_type = INT_TYPE; - if (request_irq(qlirq, do_ql_ihandl, 0, qlogic_name, shost)) + if (request_irq(qlirq, qlogicfas408_ihandl, 0, qlogic_name, shost)) goto free_scsi_host; sprintf(priv->qinfo, @@ -307,9 +315,6 @@ static void qlogic_config(dev_link_t * l outb(0x04, link->io.BasePort1 + 0xd); } - qlogicfas_driver_template.name = qlogic_name; - qlogicfas_driver_template.proc_name = qlogic_name; - /* The KXL-810AN has a bigger IO port window */ if (link->io.NumPorts1 == 32) host = qlogic_detect(&qlogicfas_driver_template, link, @@ -402,7 +407,7 @@ static int qlogic_event(event_t event, i outb(0x04, link->io.BasePort1 + 0xd); } /* Ugggglllyyyy!!! */ - qlogicfas_bus_reset(NULL); + qlogicfas408_bus_reset(NULL); } break; } --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/drivers/scsi/pcmcia/sym53c500_cs.c 2004-05-10 01:19:04.888995816 -0700 @@ -0,0 +1,1076 @@ +/* +* sym53c500_cs.c Bob Tracy (rct@frus.com) +* +* A rewrite of the pcmcia-cs add-on driver for newer (circa 1997) +* New Media Bus Toaster PCMCIA SCSI cards using the Symbios Logic +* 53c500 controller: intended for use with 2.6 and later kernels. +* The pcmcia-cs add-on version of this driver is not supported +* beyond 2.4. It consisted of three files with history/copyright +* information as follows: +* +* SYM53C500.h +* Bob Tracy (rct@frus.com) +* Original by Tom Corner (tcorner@via.at). +* Adapted from NCR53c406a.h which is Copyrighted (C) 1994 +* Normunds Saumanis (normunds@rx.tech.swh.lv) +* +* SYM53C500.c +* Bob Tracy (rct@frus.com) +* Original driver by Tom Corner (tcorner@via.at) was adapted +* from NCR53c406a.c which is Copyrighted (C) 1994, 1995, 1996 +* Normunds Saumanis (normunds@fi.ibm.com) +* +* sym53c500.c +* Bob Tracy (rct@frus.com) +* Original by Tom Corner (tcorner@via.at) was adapted from a +* driver for the Qlogic SCSI card written by +* David Hinds (dhinds@allegro.stanford.edu). +* +* 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, 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. +*/ + +#define SYM53C500_DEBUG 0 +#define VERBOSE_SYM53C500_DEBUG 0 + +/* +* Set this to 0 if you encounter kernel lockups while transferring +* data in PIO mode. Note this can be changed via "sysfs". +*/ +#define USE_FAST_PIO 1 + +/* =============== End of user configurable parameters ============== */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* ================================================================== */ + +#ifdef PCMCIA_DEBUG +static int pc_debug = PCMCIA_DEBUG; +module_param(pc_debug, int, 0); +#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) +static char *version = +"sym53c500_cs.c 0.9a 2004/05/04 (Bob Tracy)"; +#else +#define DEBUG(n, args...) +#endif + +/* ================================================================== */ + +/* Parameters that can be set with 'insmod' */ + +/* Bit map of interrupts to choose from */ +static unsigned int irq_mask = 0xdeb8; /* 3, 6, 7, 9-12, 14, 15 */ +static int irq_list[4] = { -1 }; +static int num_irqs = 1; + +module_param(irq_mask, int, 0); +MODULE_PARM_DESC(irq_mask, "IRQ mask bits (default: 0xdeb8)"); +module_param_array(irq_list, int, num_irqs, 0); +MODULE_PARM_DESC(irq_list, "Comma-separated list of up to 4 IRQs to try (default: auto select)."); + +/* ================================================================== */ + +#define SYNC_MODE 0 /* Synchronous transfer mode */ + +/* Default configuration */ +#define C1_IMG 0x07 /* ID=7 */ +#define C2_IMG 0x48 /* FE SCSI2 */ +#define C3_IMG 0x20 /* CDB */ +#define C4_IMG 0x04 /* ANE */ +#define C5_IMG 0xa4 /* ? changed from b6= AA PI SIE POL */ +#define C7_IMG 0x80 /* added for SYM53C500 t. corner */ + +/* Hardware Registers: offsets from io_port (base) */ + +/* Control Register Set 0 */ +#define TC_LSB 0x00 /* transfer counter lsb */ +#define TC_MSB 0x01 /* transfer counter msb */ +#define SCSI_FIFO 0x02 /* scsi fifo register */ +#define CMD_REG 0x03 /* command register */ +#define STAT_REG 0x04 /* status register */ +#define DEST_ID 0x04 /* selection/reselection bus id */ +#define INT_REG 0x05 /* interrupt status register */ +#define SRTIMOUT 0x05 /* select/reselect timeout reg */ +#define SEQ_REG 0x06 /* sequence step register */ +#define SYNCPRD 0x06 /* synchronous transfer period */ +#define FIFO_FLAGS 0x07 /* indicates # of bytes in fifo */ +#define SYNCOFF 0x07 /* synchronous offset register */ +#define CONFIG1 0x08 /* configuration register */ +#define CLKCONV 0x09 /* clock conversion register */ +/* #define TESTREG 0x0A */ /* test mode register */ +#define CONFIG2 0x0B /* configuration 2 register */ +#define CONFIG3 0x0C /* configuration 3 register */ +#define CONFIG4 0x0D /* configuration 4 register */ +#define TC_HIGH 0x0E /* transfer counter high */ +/* #define FIFO_BOTTOM 0x0F */ /* reserve FIFO byte register */ + +/* Control Register Set 1 */ +/* #define JUMPER_SENSE 0x00 */ /* jumper sense port reg (r/w) */ +/* #define SRAM_PTR 0x01 */ /* SRAM address pointer reg (r/w) */ +/* #define SRAM_DATA 0x02 */ /* SRAM data register (r/w) */ +#define PIO_FIFO 0x04 /* PIO FIFO registers (r/w) */ +/* #define PIO_FIFO1 0x05 */ /* */ +/* #define PIO_FIFO2 0x06 */ /* */ +/* #define PIO_FIFO3 0x07 */ /* */ +#define PIO_STATUS 0x08 /* PIO status (r/w) */ +/* #define ATA_CMD 0x09 */ /* ATA command/status reg (r/w) */ +/* #define ATA_ERR 0x0A */ /* ATA features/error reg (r/w) */ +#define PIO_FLAG 0x0B /* PIO flag interrupt enable (r/w) */ +#define CONFIG5 0x09 /* configuration 5 register */ +/* #define SIGNATURE 0x0E */ /* signature register (r) */ +/* #define CONFIG6 0x0F */ /* configuration 6 register (r) */ +#define CONFIG7 0x0d + +/* select register set 0 */ +#define REG0(x) (outb(C4_IMG, (x) + CONFIG4)) +/* select register set 1 */ +#define REG1(x) outb(C7_IMG, (x) + CONFIG7); outb(C5_IMG, (x) + CONFIG5) + +#if SYM53C500_DEBUG +#define DEB(x) x +#else +#define DEB(x) +#endif + +#if VERBOSE_SYM53C500_DEBUG +#define VDEB(x) x +#else +#define VDEB(x) +#endif + +#define LOAD_DMA_COUNT(x, count) \ + outb(count & 0xff, (x) + TC_LSB); \ + outb((count >> 8) & 0xff, (x) + TC_MSB); \ + outb((count >> 16) & 0xff, (x) + TC_HIGH); + +/* Chip commands */ +#define DMA_OP 0x80 + +#define SCSI_NOP 0x00 +#define FLUSH_FIFO 0x01 +#define CHIP_RESET 0x02 +#define SCSI_RESET 0x03 +#define RESELECT 0x40 +#define SELECT_NO_ATN 0x41 +#define SELECT_ATN 0x42 +#define SELECT_ATN_STOP 0x43 +#define ENABLE_SEL 0x44 +#define DISABLE_SEL 0x45 +#define SELECT_ATN3 0x46 +#define RESELECT3 0x47 +#define TRANSFER_INFO 0x10 +#define INIT_CMD_COMPLETE 0x11 +#define MSG_ACCEPT 0x12 +#define TRANSFER_PAD 0x18 +#define SET_ATN 0x1a +#define RESET_ATN 0x1b +#define SEND_MSG 0x20 +#define SEND_STATUS 0x21 +#define SEND_DATA 0x22 +#define DISCONN_SEQ 0x23 +#define TERMINATE_SEQ 0x24 +#define TARG_CMD_COMPLETE 0x25 +#define DISCONN 0x27 +#define RECV_MSG 0x28 +#define RECV_CMD 0x29 +#define RECV_DATA 0x2a +#define RECV_CMD_SEQ 0x2b +#define TARGET_ABORT_DMA 0x04 + +/* ================================================================== */ + +struct scsi_info_t { + dev_link_t link; + dev_node_t node; + struct Scsi_Host *host; + unsigned short manf_id; +}; + +/* +* Repository for per-instance host data. +*/ +struct sym53c500_data { + struct scsi_cmnd *current_SC; + int fast_pio; +}; + +enum Phase { + idle, + data_out, + data_in, + command_ph, + status_ph, + message_out, + message_in +}; + +/* ================================================================== */ + +/* +* Global (within this module) variables other than +* sym53c500_driver_template (the scsi_host_template). +*/ +static dev_link_t *dev_list; +static dev_info_t dev_info = "sym53c500_cs"; + +/* ================================================================== */ + +static void +chip_init(int io_port) +{ + REG1(io_port); + outb(0x01, io_port + PIO_STATUS); + outb(0x00, io_port + PIO_FLAG); + + outb(C4_IMG, io_port + CONFIG4); /* REG0(io_port); */ + outb(C3_IMG, io_port + CONFIG3); + outb(C2_IMG, io_port + CONFIG2); + outb(C1_IMG, io_port + CONFIG1); + + outb(0x05, io_port + CLKCONV); /* clock conversion factor */ + outb(0x9C, io_port + SRTIMOUT); /* Selection timeout */ + outb(0x05, io_port + SYNCPRD); /* Synchronous transfer period */ + outb(SYNC_MODE, io_port + SYNCOFF); /* synchronous mode */ +} + +static void +SYM53C500_int_host_reset(int io_port) +{ + outb(C4_IMG, io_port + CONFIG4); /* REG0(io_port); */ + outb(CHIP_RESET, io_port + CMD_REG); + outb(SCSI_NOP, io_port + CMD_REG); /* required after reset */ + outb(SCSI_RESET, io_port + CMD_REG); + chip_init(io_port); +} + +static __inline__ int +SYM53C500_pio_read(int fast_pio, int base, unsigned char *request, unsigned int reqlen) +{ + int i; + int len; /* current scsi fifo size */ + + REG1(base); + while (reqlen) { + i = inb(base + PIO_STATUS); + /* VDEB(printk("pio_status=%x\n", i)); */ + if (i & 0x80) + return 0; + + switch (i & 0x1e) { + default: + case 0x10: /* fifo empty */ + len = 0; + break; + case 0x0: + len = 1; + break; + case 0x8: /* fifo 1/3 full */ + len = 42; + break; + case 0xc: /* fifo 2/3 full */ + len = 84; + break; + case 0xe: /* fifo full */ + len = 128; + break; + } + + if ((i & 0x40) && len == 0) { /* fifo empty and interrupt occurred */ + return 0; + } + + if (len) { + if (len > reqlen) + len = reqlen; + + if (fast_pio && len > 3) { + insl(base + PIO_FIFO, request, len >> 2); + request += len & 0xfc; + reqlen -= len & 0xfc; + } else { + while (len--) { + *request++ = inb(base + PIO_FIFO); + reqlen--; + } + } + } + } + return 0; +} + +static __inline__ int +SYM53C500_pio_write(int fast_pio, int base, unsigned char *request, unsigned int reqlen) +{ + int i = 0; + int len; /* current scsi fifo size */ + + REG1(base); + while (reqlen && !(i & 0x40)) { + i = inb(base + PIO_STATUS); + /* VDEB(printk("pio_status=%x\n", i)); */ + if (i & 0x80) /* error */ + return 0; + + switch (i & 0x1e) { + case 0x10: + len = 128; + break; + case 0x0: + len = 84; + break; + case 0x8: + len = 42; + break; + case 0xc: + len = 1; + break; + default: + case 0xe: + len = 0; + break; + } + + if (len) { + if (len > reqlen) + len = reqlen; + + if (fast_pio && len > 3) { + outsl(base + PIO_FIFO, request, len >> 2); + request += len & 0xfc; + reqlen -= len & 0xfc; + } else { + while (len--) { + outb(*request++, base + PIO_FIFO); + reqlen--; + } + } + } + } + return 0; +} + +static irqreturn_t +SYM53C500_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long flags; + struct Scsi_Host *dev = dev_id; + DEB(unsigned char fifo_size;) + DEB(unsigned char seq_reg;) + unsigned char status, int_reg; + unsigned char pio_status; + struct scatterlist *sglist; + unsigned int sgcount; + int port_base = dev->io_port; + struct sym53c500_data *data = + (struct sym53c500_data *)dev->hostdata; + struct scsi_cmnd *curSC = data->current_SC; + int fast_pio = data->fast_pio; + + spin_lock_irqsave(dev->host_lock, flags); + + VDEB(printk("SYM53C500_intr called\n")); + + REG1(port_base); + pio_status = inb(port_base + PIO_STATUS); + REG0(port_base); + status = inb(port_base + STAT_REG); + DEB(seq_reg = inb(port_base + SEQ_REG)); + int_reg = inb(port_base + INT_REG); + DEB(fifo_size = inb(port_base + FIFO_FLAGS) & 0x1f); + +#if SYM53C500_DEBUG + printk("status=%02x, seq_reg=%02x, int_reg=%02x, fifo_size=%02x", + status, seq_reg, int_reg, fifo_size); + printk(", pio=%02x\n", pio_status); +#endif /* SYM53C500_DEBUG */ + + if (int_reg & 0x80) { /* SCSI reset intr */ + DEB(printk("SYM53C500: reset intr received\n")); + curSC->result = DID_RESET << 16; + goto idle_out; + } + + if (pio_status & 0x80) { + printk("SYM53C500: Warning: PIO error!\n"); + curSC->result = DID_ERROR << 16; + goto idle_out; + } + + if (status & 0x20) { /* Parity error */ + printk("SYM53C500: Warning: parity error!\n"); + curSC->result = DID_PARITY << 16; + goto idle_out; + } + + if (status & 0x40) { /* Gross error */ + printk("SYM53C500: Warning: gross error!\n"); + curSC->result = DID_ERROR << 16; + goto idle_out; + } + + if (int_reg & 0x20) { /* Disconnect */ + DEB(printk("SYM53C500: disconnect intr received\n")); + if (curSC->SCp.phase != message_in) { /* Unexpected disconnect */ + curSC->result = DID_NO_CONNECT << 16; + } else { /* Command complete, return status and message */ + curSC->result = (curSC->SCp.Status & 0xff) + | ((curSC->SCp.Message & 0xff) << 8) | (DID_OK << 16); + } + goto idle_out; + } + + switch (status & 0x07) { /* scsi phase */ + case 0x00: /* DATA-OUT */ + if (int_reg & 0x10) { /* Target requesting info transfer */ + curSC->SCp.phase = data_out; + VDEB(printk("SYM53C500: Data-Out phase\n")); + outb(FLUSH_FIFO, port_base + CMD_REG); + LOAD_DMA_COUNT(port_base, curSC->request_bufflen); /* Max transfer size */ + outb(TRANSFER_INFO | DMA_OP, port_base + CMD_REG); + if (!curSC->use_sg) /* Don't use scatter-gather */ + SYM53C500_pio_write(fast_pio, port_base, curSC->request_buffer, curSC->request_bufflen); + else { /* use scatter-gather */ + sgcount = curSC->use_sg; + sglist = curSC->request_buffer; + while (sgcount--) { + SYM53C500_pio_write(fast_pio, port_base, page_address(sglist->page) + sglist->offset, sglist->length); + sglist++; + } + } + REG0(port_base); + } + break; + + case 0x01: /* DATA-IN */ + if (int_reg & 0x10) { /* Target requesting info transfer */ + curSC->SCp.phase = data_in; + VDEB(printk("SYM53C500: Data-In phase\n")); + outb(FLUSH_FIFO, port_base + CMD_REG); + LOAD_DMA_COUNT(port_base, curSC->request_bufflen); /* Max transfer size */ + outb(TRANSFER_INFO | DMA_OP, port_base + CMD_REG); + if (!curSC->use_sg) /* Don't use scatter-gather */ + SYM53C500_pio_read(fast_pio, port_base, curSC->request_buffer, curSC->request_bufflen); + else { /* Use scatter-gather */ + sgcount = curSC->use_sg; + sglist = curSC->request_buffer; + while (sgcount--) { + SYM53C500_pio_read(fast_pio, port_base, page_address(sglist->page) + sglist->offset, sglist->length); + sglist++; + } + } + REG0(port_base); + } + break; + + case 0x02: /* COMMAND */ + curSC->SCp.phase = command_ph; + printk("SYM53C500: Warning: Unknown interrupt occurred in command phase!\n"); + break; + + case 0x03: /* STATUS */ + curSC->SCp.phase = status_ph; + VDEB(printk("SYM53C500: Status phase\n")); + outb(FLUSH_FIFO, port_base + CMD_REG); + outb(INIT_CMD_COMPLETE, port_base + CMD_REG); + break; + + case 0x04: /* Reserved */ + case 0x05: /* Reserved */ + printk("SYM53C500: WARNING: Reserved phase!!!\n"); + break; + + case 0x06: /* MESSAGE-OUT */ + DEB(printk("SYM53C500: Message-Out phase\n")); + curSC->SCp.phase = message_out; + outb(SET_ATN, port_base + CMD_REG); /* Reject the message */ + outb(MSG_ACCEPT, port_base + CMD_REG); + break; + + case 0x07: /* MESSAGE-IN */ + VDEB(printk("SYM53C500: Message-In phase\n")); + curSC->SCp.phase = message_in; + + curSC->SCp.Status = inb(port_base + SCSI_FIFO); + curSC->SCp.Message = inb(port_base + SCSI_FIFO); + + VDEB(printk("SCSI FIFO size=%d\n", inb(port_base + FIFO_FLAGS) & 0x1f)); + DEB(printk("Status = %02x Message = %02x\n", curSC->SCp.Status, curSC->SCp.Message)); + + if (curSC->SCp.Message == SAVE_POINTERS || curSC->SCp.Message == DISCONNECT) { + outb(SET_ATN, port_base + CMD_REG); /* Reject message */ + DEB(printk("Discarding SAVE_POINTERS message\n")); + } + outb(MSG_ACCEPT, port_base + CMD_REG); + break; + } +out: + spin_unlock_irqrestore(dev->host_lock, flags); + return IRQ_HANDLED; + +idle_out: + curSC->SCp.phase = idle; + curSC->scsi_done(curSC); + goto out; +} + +static void +SYM53C500_release(dev_link_t *link) +{ + struct scsi_info_t *info = link->priv; + struct Scsi_Host *shost = info->host; + + DEBUG(0, "SYM53C500_release(0x%p)\n", link); + + /* + * Do this before releasing/freeing resources. + */ + scsi_remove_host(shost); + + /* + * Interrupts getting hosed on card removal. Try + * the following code, mostly from qlogicfas.c. + */ + if (shost->irq) + free_irq(shost->irq, shost); + if (shost->dma_channel != 0xff) + free_dma(shost->dma_channel); + if (shost->io_port && shost->n_io_port) + release_region(shost->io_port, shost->n_io_port); + + link->dev = NULL; + + pcmcia_release_configuration(link->handle); + pcmcia_release_io(link->handle, &link->io); + pcmcia_release_irq(link->handle, &link->irq); + + link->state &= ~DEV_CONFIG; + + scsi_host_put(shost); +} /* SYM53C500_release */ + +static const char* +SYM53C500_info(struct Scsi_Host *SChost) +{ + static char info_msg[256]; + struct sym53c500_data *data = + (struct sym53c500_data *)SChost->hostdata; + + DEB(printk("SYM53C500_info called\n")); + (void)snprintf(info_msg, sizeof(info_msg), + "SYM53C500 at 0x%lx, IRQ %d, %s PIO mode.", + SChost->io_port, SChost->irq, data->fast_pio ? "fast" : "slow"); + return (info_msg); +} + +static int +SYM53C500_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) +{ + int i; + int port_base = SCpnt->device->host->io_port; + struct sym53c500_data *data = + (struct sym53c500_data *)SCpnt->device->host->hostdata; + + VDEB(printk("SYM53C500_queue called\n")); + + DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", + SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->device->id, + SCpnt->device->lun, SCpnt->request_bufflen)); + + VDEB(for (i = 0; i < SCpnt->cmd_len; i++) + printk("cmd[%d]=%02x ", i, SCpnt->cmnd[i])); + VDEB(printk("\n")); + + data->current_SC = SCpnt; + data->current_SC->scsi_done = done; + data->current_SC->SCp.phase = command_ph; + data->current_SC->SCp.Status = 0; + data->current_SC->SCp.Message = 0; + + /* We are locked here already by the mid layer */ + REG0(port_base); + outb(SCpnt->device->id, port_base + DEST_ID); /* set destination */ + outb(FLUSH_FIFO, port_base + CMD_REG); /* reset the fifos */ + + for (i = 0; i < SCpnt->cmd_len; i++) { + outb(SCpnt->cmnd[i], port_base + SCSI_FIFO); + } + outb(SELECT_NO_ATN, port_base + CMD_REG); + + return 0; +} + +static int +SYM53C500_host_reset(struct scsi_cmnd *SCpnt) +{ + int port_base = SCpnt->device->host->io_port; + + DEB(printk("SYM53C500_host_reset called\n")); + SYM53C500_int_host_reset(port_base); + + return SUCCESS; +} + +static int +SYM53C500_biosparm(struct scsi_device *disk, + struct block_device *dev, + sector_t capacity, int *info_array) +{ + int size; + + DEB(printk("SYM53C500_biosparm called\n")); + + size = capacity; + info_array[0] = 64; /* heads */ + info_array[1] = 32; /* sectors */ + info_array[2] = size >> 11; /* cylinders */ + if (info_array[2] > 1024) { /* big disk */ + info_array[0] = 255; + info_array[1] = 63; + info_array[2] = size / (255 * 63); + } + return 0; +} + +static ssize_t +SYM53C500_show_irq(struct class_device *cdev, char *buf) +{ + struct Scsi_Host *SHp = class_to_shost(cdev); + + return snprintf(buf, 4, "%d\n", SHp->irq); +} + +static ssize_t +SYM53C500_show_ioport(struct class_device *cdev, char *buf) +{ + struct Scsi_Host *SHp = class_to_shost(cdev); + + return snprintf(buf, 8, "0x%lx\n", SHp->io_port); +} + +static ssize_t +SYM53C500_show_pio(struct class_device *cdev, char *buf) +{ + struct Scsi_Host *SHp = class_to_shost(cdev); + struct sym53c500_data *data = + (struct sym53c500_data *)SHp->hostdata; + + return snprintf(buf, 4, "%d\n", data->fast_pio); +} + +static ssize_t +SYM53C500_store_pio(struct class_device *cdev, const char *buf, size_t count) +{ + int pio; + struct Scsi_Host *SHp = class_to_shost(cdev); + struct sym53c500_data *data = + (struct sym53c500_data *)SHp->hostdata; + + pio = simple_strtoul(buf, NULL, 0); + if (pio == 0 || pio == 1) { + data->fast_pio = pio; + return count; + } + else + return -EINVAL; +} + +/* +* SCSI HBA device attributes we want to +* make available via sysfs. +*/ +static struct class_device_attribute SYM53C500_irq_attr = { + .attr = { + .name = "irq", + .mode = S_IRUGO, + }, + .show = SYM53C500_show_irq, +}; + +static struct class_device_attribute SYM53C500_ioport_attr = { + .attr = { + .name = "ioport", + .mode = S_IRUGO, + }, + .show = SYM53C500_show_ioport, +}; + +static struct class_device_attribute SYM53C500_pio_attr = { + .attr = { + .name = "fast_pio", + .mode = (S_IRUGO | S_IWUSR), + }, + .show = SYM53C500_show_pio, + .store = SYM53C500_store_pio, +}; + +static struct class_device_attribute *SYM53C500_shost_attrs[] = { + &SYM53C500_irq_attr, + &SYM53C500_ioport_attr, + &SYM53C500_pio_attr, + NULL, +}; + +/* +* scsi_host_template initializer +*/ +static struct scsi_host_template sym53c500_driver_template = { + .module = THIS_MODULE, + .name = "SYM53C500", + .info = SYM53C500_info, + .queuecommand = SYM53C500_queue, + .eh_host_reset_handler = SYM53C500_host_reset, + .bios_param = SYM53C500_biosparm, + .proc_name = "SYM53C500", + .can_queue = 1, + .this_id = 7, + .sg_tablesize = 32, + .cmd_per_lun = 1, + .use_clustering = ENABLE_CLUSTERING, + .shost_attrs = SYM53C500_shost_attrs +}; + +#define CS_CHECK(fn, ret) \ +do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) + +static void +SYM53C500_config(dev_link_t *link) +{ + client_handle_t handle = link->handle; + struct scsi_info_t *info = link->priv; + tuple_t tuple; + cisparse_t parse; + int i, last_ret, last_fn; + int irq_level, port_base; + unsigned short tuple_data[32]; + struct Scsi_Host *host; + struct scsi_host_template *tpnt = &sym53c500_driver_template; + struct sym53c500_data *data; + + DEBUG(0, "SYM53C500_config(0x%p)\n", link); + + tuple.TupleData = (cisdata_t *)tuple_data; + tuple.TupleDataMax = 64; + tuple.TupleOffset = 0; + tuple.DesiredTuple = CISTPL_CONFIG; + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + link->conf.ConfigBase = parse.config.base; + + tuple.DesiredTuple = CISTPL_MANFID; + if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) && + (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS)) + info->manf_id = le16_to_cpu(tuple.TupleData[0]); + + /* Configure card */ + link->state |= DEV_CONFIG; + + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + while (1) { + if (pcmcia_get_tuple_data(handle, &tuple) != 0 || + pcmcia_parse_tuple(handle, &tuple, &parse) != 0) + goto next_entry; + link->conf.ConfigIndex = parse.cftable_entry.index; + link->io.BasePort1 = parse.cftable_entry.io.win[0].base; + link->io.NumPorts1 = parse.cftable_entry.io.win[0].len; + + if (link->io.BasePort1 != 0) { + i = pcmcia_request_io(handle, &link->io); + if (i == CS_SUCCESS) + break; + } +next_entry: + CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); + } + + CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); + + /* + * That's the trouble with copying liberally from another driver. + * Some things probably aren't relevant, and I suspect this entire + * section dealing with manufacturer IDs can be scrapped. --rct + */ + if ((info->manf_id == MANFID_MACNICA) || + (info->manf_id == MANFID_PIONEER) || + (info->manf_id == 0x0098)) { + /* set ATAcmd */ + outb(0xb4, link->io.BasePort1 + 0xd); + outb(0x24, link->io.BasePort1 + 0x9); + outb(0x04, link->io.BasePort1 + 0xd); + } + + /* + * irq_level == 0 implies tpnt->can_queue == 0, which + * is not supported in 2.6. Thus, only irq_level > 0 + * will be allowed. + * + * Possible port_base values are as follows: + * + * 0x130, 0x230, 0x280, 0x290, + * 0x320, 0x330, 0x340, 0x350 + */ + port_base = link->io.BasePort1; + irq_level = link->irq.AssignedIRQ; + + DEB(printk("SYM53C500: port_base=0x%x, irq=%d, fast_pio=%d\n", + port_base, irq_level, USE_FAST_PIO);) + + chip_init(port_base); + + host = scsi_host_alloc(tpnt, sizeof(struct sym53c500_data)); + if (!host) { + printk("SYM53C500: Unable to register host, giving up.\n"); + goto err_release; + } + + data = (struct sym53c500_data *)host->hostdata; + + if (irq_level > 0) { + if (request_irq(irq_level, SYM53C500_intr, 0, "SYM53C500", host)) { + printk("SYM53C500: unable to allocate IRQ %d\n", irq_level); + goto err_free_scsi; + } + DEB(printk("SYM53C500: allocated IRQ %d\n", irq_level)); + } else if (irq_level == 0) { + DEB(printk("SYM53C500: No interrupts detected\n")); + goto err_free_scsi; + } else { + DEB(printk("SYM53C500: Shouldn't get here!\n")); + goto err_free_scsi; + } + + host->unique_id = port_base; + host->irq = irq_level; + host->io_port = port_base; + host->n_io_port = 0x10; + host->dma_channel = -1; + + /* + * Note fast_pio is set to USE_FAST_PIO by + * default, but can be changed via "sysfs". + */ + data->fast_pio = USE_FAST_PIO; + + sprintf(info->node.dev_name, "scsi%d", host->host_no); + link->dev = &info->node; + info->host = host; + + if (scsi_add_host(host, NULL)) + goto err_free_irq; + + scsi_scan_host(host); + + goto out; /* SUCCESS */ + +err_free_irq: + free_irq(irq_level, host); +err_free_scsi: + scsi_host_put(host); +err_release: + release_region(port_base, 0x10); + printk(KERN_INFO "sym53c500_cs: no SCSI devices found\n"); + +out: + link->state &= ~DEV_CONFIG_PENDING; + return; + +cs_failed: + cs_error(link->handle, last_fn, last_ret); + SYM53C500_release(link); + return; +} /* SYM53C500_config */ + +static int +SYM53C500_event(event_t event, int priority, event_callback_args_t *args) +{ + dev_link_t *link = args->client_data; + struct scsi_info_t *info = link->priv; + + DEBUG(1, "SYM53C500_event(0x%06x)\n", event); + + switch (event) { + case CS_EVENT_CARD_REMOVAL: + link->state &= ~DEV_PRESENT; + if (link->state & DEV_CONFIG) + SYM53C500_release(link); + break; + case CS_EVENT_CARD_INSERTION: + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + SYM53C500_config(link); + break; + case CS_EVENT_PM_SUSPEND: + link->state |= DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_RESET_PHYSICAL: + if (link->state & DEV_CONFIG) + pcmcia_release_configuration(link->handle); + break; + case CS_EVENT_PM_RESUME: + link->state &= ~DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_CARD_RESET: + if (link->state & DEV_CONFIG) { + pcmcia_request_configuration(link->handle, &link->conf); + /* See earlier comment about manufacturer IDs. */ + if ((info->manf_id == MANFID_MACNICA) || + (info->manf_id == MANFID_PIONEER) || + (info->manf_id == 0x0098)) { + outb(0x80, link->io.BasePort1 + 0xd); + outb(0x24, link->io.BasePort1 + 0x9); + outb(0x04, link->io.BasePort1 + 0xd); + } + /* + * If things don't work after a "resume", + * this is a good place to start looking. + */ + SYM53C500_int_host_reset(link->io.BasePort1); + } + break; + } + return 0; +} /* SYM53C500_event */ + +static void +SYM53C500_detach(dev_link_t *link) +{ + dev_link_t **linkp; + + DEBUG(0, "SYM53C500_detach(0x%p)\n", link); + + /* Locate device structure */ + for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) + if (*linkp == link) + break; + if (*linkp == NULL) + return; + + if (link->state & DEV_CONFIG) + SYM53C500_release(link); + + if (link->handle) + pcmcia_deregister_client(link->handle); + + /* Unlink device structure, free bits. */ + *linkp = link->next; + kfree(link->priv); + link->priv = NULL; +} /* SYM53C500_detach */ + +static dev_link_t * +SYM53C500_attach(void) +{ + struct scsi_info_t *info; + client_reg_t client_reg; + dev_link_t *link; + int i, ret; + + DEBUG(0, "SYM53C500_attach()\n"); + + /* Create new SCSI device */ + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return NULL; + memset(info, 0, sizeof(*info)); + link = &info->link; + link->priv = info; + link->io.NumPorts1 = 16; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; + link->io.IOAddrLines = 10; + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID; + if (irq_list[0] == -1) + link->irq.IRQInfo2 = irq_mask; + else + for (i = 0; i < 4; i++) + link->irq.IRQInfo2 |= 1 << irq_list[i]; + link->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.Vcc = 50; + link->conf.IntType = INT_MEMORY_AND_IO; + link->conf.Present = PRESENT_OPTION; + + /* Register with Card Services */ + link->next = dev_list; + dev_list = link; + client_reg.dev_info = &dev_info; + client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; + 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); + if (ret != 0) { + cs_error(link->handle, RegisterClient, ret); + SYM53C500_detach(link); + return NULL; + } + + return link; +} /* SYM53C500_attach */ + +MODULE_AUTHOR("Bob Tracy "); +MODULE_DESCRIPTION("SYM53C500 PCMCIA SCSI driver"); +MODULE_LICENSE("GPL"); + +static struct pcmcia_driver sym53c500_cs_driver = { + .owner = THIS_MODULE, + .drv = { + .name = "sym53c500_cs", + }, + .attach = SYM53C500_attach, + .detach = SYM53C500_detach, +}; + +static int __init +init_sym53c500_cs(void) +{ + return pcmcia_register_driver(&sym53c500_cs_driver); +} + +static void __exit +exit_sym53c500_cs(void) +{ + pcmcia_unregister_driver(&sym53c500_cs_driver); +} + +module_init(init_sym53c500_cs); +module_exit(exit_sym53c500_cs); --- linux-2.6.6/drivers/scsi/qla1280.c 2004-03-10 20:41:29.000000000 -0800 +++ 25/drivers/scsi/qla1280.c 2004-05-10 01:19:04.892995208 -0700 @@ -3371,6 +3371,7 @@ qla1280_64bit_start_scsi(struct scsi_qla sp->flags |= SRB_SENT; ha->actthreads++; WRT_REG_WORD(®->mailbox4, ha->req_ring_index); + (void) RD_REG_WORD(®->mailbox4); /* PCI posted write flush */ out: if (status) @@ -3639,6 +3640,7 @@ qla1280_32bit_start_scsi(struct scsi_qla sp->flags |= SRB_SENT; ha->actthreads++; WRT_REG_WORD(®->mailbox4, ha->req_ring_index); + (void) RD_REG_WORD(®->mailbox4); /* PCI posted write flush */ out: if (status) @@ -3750,6 +3752,7 @@ qla1280_isp_cmd(struct scsi_qla_host *ha /* Set chip new ring index. */ WRT_REG_WORD(®->mailbox4, ha->req_ring_index); + (void) RD_REG_WORD(®->mailbox4); /* PCI posted write flush */ LEAVE("qla1280_isp_cmd"); } @@ -3788,7 +3791,7 @@ qla1280_isr(struct scsi_qla_host *ha, st /* Check for mailbox interrupt. */ - mailbox[0] = RD_REG_WORD(®->semaphore); + mailbox[0] = RD_REG_WORD_dmasync(®->semaphore); if (mailbox[0] & BIT_0) { /* Get mailbox data. */ --- linux-2.6.6/drivers/scsi/qla1280.h 2004-02-03 20:42:37.000000000 -0800 +++ 25/drivers/scsi/qla1280.h 2004-05-10 01:19:04.893995056 -0700 @@ -57,7 +57,8 @@ #define BIT_31 0x80000000 #if MEMORY_MAPPED_IO -#define RD_REG_WORD(addr) readw(addr) +#define RD_REG_WORD(addr) readw_relaxed(addr) +#define RD_REG_WORD_dmasync(addr) readw(addr) #define WRT_REG_WORD(addr, data) writew(data, addr) #else /* MEMORY_MAPPED_IO */ #define RD_REG_WORD(addr) inw((unsigned long)addr) --- linux-2.6.6/drivers/scsi/qla2xxx/qla_init.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/scsi/qla2xxx/qla_init.c 2004-05-10 01:19:04.896994600 -0700 @@ -946,7 +946,7 @@ qla2x00_fw_ready(scsi_qla_host_t *ha) break; /* Delay for a while */ - set_current_state(TASK_INTERRUPTIBLE); + set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ / 2); DEBUG3(printk("scsi(%ld): fw_state=%x curr time=%lx.\n", --- linux-2.6.6/drivers/scsi/qla2xxx/qla_os.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/scsi/qla2xxx/qla_os.c 2004-05-10 01:19:04.899994144 -0700 @@ -914,7 +914,7 @@ qla2x00_eh_wait_on_command(scsi_qla_host spin_unlock_irq(ha->host->host_lock); - set_current_state(TASK_INTERRUPTIBLE); + set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(2*HZ); spin_lock_irq(ha->host->host_lock); @@ -962,7 +962,7 @@ qla2x00_wait_for_hba_online(scsi_qla_hos test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) && time_before(jiffies, wait_online)) { - set_current_state(TASK_INTERRUPTIBLE); + set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ); } if (ha->flags.online == TRUE) @@ -1005,7 +1005,7 @@ qla2x00_wait_for_loop_ready(scsi_qla_hos atomic_read(&ha->loop_state) == LOOP_DOWN) || test_bit(CFG_ACTIVE, &ha->cfg_flags) || atomic_read(&ha->loop_state) != LOOP_READY) { - set_current_state(TASK_INTERRUPTIBLE); + set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ); if (time_after_eq(jiffies, loop_timeout)) { return_status = QLA_FUNCTION_FAILED; @@ -2125,8 +2125,8 @@ int qla2x00_probe_one(struct pci_dev *pd qla2x00_check_fabric_devices(ha); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(5); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ/100); } pci_set_drvdata(pdev, ha); @@ -2868,7 +2868,7 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) "Memory Allocation failed - request_ring\n"); qla2x00_mem_free(ha); - set_current_state(TASK_INTERRUPTIBLE); + set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/10); continue; @@ -2882,7 +2882,7 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) "Memory Allocation failed - response_ring\n"); qla2x00_mem_free(ha); - set_current_state(TASK_INTERRUPTIBLE); + set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/10); continue; @@ -2896,7 +2896,7 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) "Memory Allocation failed - init_cb\n"); qla2x00_mem_free(ha); - set_current_state(TASK_INTERRUPTIBLE); + set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/10); continue; @@ -2909,7 +2909,7 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) "Memory Allocation failed - ioctl_mem\n"); qla2x00_mem_free(ha); - set_current_state(TASK_INTERRUPTIBLE); + set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/10); continue; @@ -2921,7 +2921,7 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) "qla2x00_allocate_sp_pool()\n"); qla2x00_mem_free(ha); - set_current_state(TASK_INTERRUPTIBLE); + set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/10); continue; @@ -2938,7 +2938,7 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) "Memory Allocation failed - sns_cmd\n"); qla2x00_mem_free(ha); - set_current_state(TASK_INTERRUPTIBLE); + set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/10); continue; @@ -2954,7 +2954,7 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) "Memory Allocation failed - ms_iocb\n"); qla2x00_mem_free(ha); - set_current_state(TASK_INTERRUPTIBLE); + set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/10); continue; @@ -2973,7 +2973,7 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) "Memory Allocation failed - ct_sns\n"); qla2x00_mem_free(ha); - set_current_state(TASK_INTERRUPTIBLE); + set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/10); continue; @@ -2990,7 +2990,7 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) "Memory Allocation failed - iodesc_pd\n"); qla2x00_mem_free(ha); - set_current_state(TASK_INTERRUPTIBLE); + set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/10); continue; --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/drivers/scsi/qlogicfas408.c 2004-05-10 01:19:04.907992928 -0700 @@ -0,0 +1,637 @@ +/*----------------------------------------------------------------*/ +/* + Qlogic linux driver - work in progress. No Warranty express or implied. + Use at your own risk. Support Tort Reform so you won't have to read all + these silly disclaimers. + + Copyright 1994, Tom Zerucha. + tz@execpc.com + + Additional Code, and much appreciated help by + Michael A. Griffith + grif@cs.ucr.edu + + Thanks to Eric Youngdale and Dave Hinds for loadable module and PCMCIA + help respectively, and for suffering through my foolishness during the + debugging process. + + Reference Qlogic FAS408 Technical Manual, 53408-510-00A, May 10, 1994 + (you can reference it, but it is incomplete and inaccurate in places) + + Version 0.46 1/30/97 - kernel 1.2.0+ + + Functions as standalone, loadable, and PCMCIA driver, the latter from + Dave Hinds' PCMCIA package. + + Cleaned up 26/10/2002 by Alan Cox as part of the 2.5 + SCSI driver cleanup and audit. This driver still needs work on the + following + - Non terminating hardware waits + - Some layering violations with its pcmcia stub + + Redistributable under terms of the GNU General Public License + + For the avoidance of doubt the "preferred form" of this code is one which + is in an open non patent encumbered format. Where cryptographic key signing + forms part of the process of creating an executable the information + including keys needed to generate an equivalently functional executable + are deemed to be part of the source code. + +*/ + +#include +#include /* to get disk capacity */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "scsi.h" +#include "hosts.h" +#include "qlogicfas408.h" + +/*----------------------------------------------------------------*/ +static int qlcfg5 = (XTALFREQ << 5); /* 15625/512 */ +static int qlcfg6 = SYNCXFRPD; +static int qlcfg7 = SYNCOFFST; +static int qlcfg8 = (SLOWCABLE << 7) | (QL_ENABLE_PARITY << 4); +static int qlcfg9 = ((XTALFREQ + 4) / 5); +static int qlcfgc = (FASTCLK << 3) | (FASTSCSI << 4); + +/*----------------------------------------------------------------*/ + +/*----------------------------------------------------------------*/ +/* local functions */ +/*----------------------------------------------------------------*/ + +/* error recovery - reset everything */ + +static void ql_zap(struct qlogicfas408_priv *priv) +{ + int x; + int qbase = priv->qbase; + int int_type = priv->int_type; + + x = inb(qbase + 0xd); + REG0; + outb(3, qbase + 3); /* reset SCSI */ + outb(2, qbase + 3); /* reset chip */ + if (x & 0x80) + REG1; +} + +/* + * Do a pseudo-dma tranfer + */ + +static int ql_pdma(struct qlogicfas408_priv *priv, int phase, char *request, int reqlen) +{ + int j; + int qbase = priv->qbase; + j = 0; + if (phase & 1) { /* in */ +#if QL_TURBO_PDMA + rtrc(4) + /* empty fifo in large chunks */ + if (reqlen >= 128 && (inb(qbase + 8) & 2)) { /* full */ + insl(qbase + 4, request, 32); + reqlen -= 128; + request += 128; + } + while (reqlen >= 84 && !(j & 0xc0)) /* 2/3 */ + if ((j = inb(qbase + 8)) & 4) + { + insl(qbase + 4, request, 21); + reqlen -= 84; + request += 84; + } + if (reqlen >= 44 && (inb(qbase + 8) & 8)) { /* 1/3 */ + insl(qbase + 4, request, 11); + reqlen -= 44; + request += 44; + } +#endif + /* until both empty and int (or until reclen is 0) */ + rtrc(7) + j = 0; + while (reqlen && !((j & 0x10) && (j & 0xc0))) + { + /* while bytes to receive and not empty */ + j &= 0xc0; + while (reqlen && !((j = inb(qbase + 8)) & 0x10)) + { + *request++ = inb(qbase + 4); + reqlen--; + } + if (j & 0x10) + j = inb(qbase + 8); + + } + } else { /* out */ +#if QL_TURBO_PDMA + rtrc(4) + if (reqlen >= 128 && inb(qbase + 8) & 0x10) { /* empty */ + outsl(qbase + 4, request, 32); + reqlen -= 128; + request += 128; + } + while (reqlen >= 84 && !(j & 0xc0)) /* 1/3 */ + if (!((j = inb(qbase + 8)) & 8)) { + outsl(qbase + 4, request, 21); + reqlen -= 84; + request += 84; + } + if (reqlen >= 40 && !(inb(qbase + 8) & 4)) { /* 2/3 */ + outsl(qbase + 4, request, 10); + reqlen -= 40; + request += 40; + } +#endif + /* until full and int (or until reclen is 0) */ + rtrc(7) + j = 0; + while (reqlen && !((j & 2) && (j & 0xc0))) { + /* while bytes to send and not full */ + while (reqlen && !((j = inb(qbase + 8)) & 2)) + { + outb(*request++, qbase + 4); + reqlen--; + } + if (j & 2) + j = inb(qbase + 8); + } + } + /* maybe return reqlen */ + return inb(qbase + 8) & 0xc0; +} + +/* + * Wait for interrupt flag (polled - not real hardware interrupt) + */ + +static int ql_wai(struct qlogicfas408_priv *priv) +{ + int k; + int qbase = priv->qbase; + unsigned long i; + + k = 0; + i = jiffies + WATCHDOG; + while (time_before(jiffies, i) && !priv->qabort && + !((k = inb(qbase + 4)) & 0xe0)) { + barrier(); + cpu_relax(); + } + if (time_after_eq(jiffies, i)) + return (DID_TIME_OUT); + if (priv->qabort) + return (priv->qabort == 1 ? DID_ABORT : DID_RESET); + if (k & 0x60) + ql_zap(priv); + if (k & 0x20) + return (DID_PARITY); + if (k & 0x40) + return (DID_ERROR); + return 0; +} + +/* + * Initiate scsi command - queueing handler + * caller must hold host lock + */ + +static void ql_icmd(Scsi_Cmnd * cmd) +{ + struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd); + int qbase = priv->qbase; + int int_type = priv->int_type; + unsigned int i; + + priv->qabort = 0; + + REG0; + /* clearing of interrupts and the fifo is needed */ + + inb(qbase + 5); /* clear interrupts */ + if (inb(qbase + 5)) /* if still interrupting */ + outb(2, qbase + 3); /* reset chip */ + else if (inb(qbase + 7) & 0x1f) + outb(1, qbase + 3); /* clear fifo */ + while (inb(qbase + 5)); /* clear ints */ + REG1; + outb(1, qbase + 8); /* set for PIO pseudo DMA */ + outb(0, qbase + 0xb); /* disable ints */ + inb(qbase + 8); /* clear int bits */ + REG0; + outb(0x40, qbase + 0xb); /* enable features */ + + /* configurables */ + outb(qlcfgc, qbase + 0xc); + /* config: no reset interrupt, (initiator) bus id */ + outb(0x40 | qlcfg8 | priv->qinitid, qbase + 8); + outb(qlcfg7, qbase + 7); + outb(qlcfg6, qbase + 6); + /**/ outb(qlcfg5, qbase + 5); /* select timer */ + outb(qlcfg9 & 7, qbase + 9); /* prescaler */ +/* outb(0x99, qbase + 5); */ + outb(cmd->device->id, qbase + 4); + + for (i = 0; i < cmd->cmd_len; i++) + outb(cmd->cmnd[i], qbase + 2); + + priv->qlcmd = cmd; + outb(0x41, qbase + 3); /* select and send command */ +} + +/* + * Process scsi command - usually after interrupt + */ + +static unsigned int ql_pcmd(Scsi_Cmnd * cmd) +{ + unsigned int i, j; + unsigned long k; + unsigned int result; /* ultimate return result */ + unsigned int status; /* scsi returned status */ + unsigned int message; /* scsi returned message */ + unsigned int phase; /* recorded scsi phase */ + unsigned int reqlen; /* total length of transfer */ + struct scatterlist *sglist; /* scatter-gather list pointer */ + unsigned int sgcount; /* sg counter */ + char *buf; + struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd); + int qbase = priv->qbase; + int int_type = priv->int_type; + + rtrc(1) + j = inb(qbase + 6); + i = inb(qbase + 5); + if (i == 0x20) { + return (DID_NO_CONNECT << 16); + } + i |= inb(qbase + 5); /* the 0x10 bit can be set after the 0x08 */ + if (i != 0x18) { + printk(KERN_ERR "Ql:Bad Interrupt status:%02x\n", i); + ql_zap(priv); + return (DID_BAD_INTR << 16); + } + j &= 7; /* j = inb( qbase + 7 ) >> 5; */ + + /* correct status is supposed to be step 4 */ + /* it sometimes returns step 3 but with 0 bytes left to send */ + /* We can try stuffing the FIFO with the max each time, but we will get a + sequence of 3 if any bytes are left (but we do flush the FIFO anyway */ + + if (j != 3 && j != 4) { + printk(KERN_ERR "Ql:Bad sequence for command %d, int %02X, cmdleft = %d\n", + j, i, inb(qbase + 7) & 0x1f); + ql_zap(priv); + return (DID_ERROR << 16); + } + result = DID_OK; + if (inb(qbase + 7) & 0x1f) /* if some bytes in fifo */ + outb(1, qbase + 3); /* clear fifo */ + /* note that request_bufflen is the total xfer size when sg is used */ + reqlen = cmd->request_bufflen; + /* note that it won't work if transfers > 16M are requested */ + if (reqlen && !((phase = inb(qbase + 4)) & 6)) { /* data phase */ + rtrc(2) + outb(reqlen, qbase); /* low-mid xfer cnt */ + outb(reqlen >> 8, qbase + 1); /* low-mid xfer cnt */ + outb(reqlen >> 16, qbase + 0xe); /* high xfer cnt */ + outb(0x90, qbase + 3); /* command do xfer */ + /* PIO pseudo DMA to buffer or sglist */ + REG1; + if (!cmd->use_sg) + ql_pdma(priv, phase, cmd->request_buffer, + cmd->request_bufflen); + else { + sgcount = cmd->use_sg; + sglist = cmd->request_buffer; + while (sgcount--) { + if (priv->qabort) { + REG0; + return ((priv->qabort == 1 ? + DID_ABORT : DID_RESET) << 16); + } + buf = page_address(sglist->page) + sglist->offset; + if (ql_pdma(priv, phase, buf, sglist->length)) + break; + sglist++; + } + } + REG0; + rtrc(2) + /* + * Wait for irq (split into second state of irq handler + * if this can take time) + */ + if ((k = ql_wai(priv))) + return (k << 16); + k = inb(qbase + 5); /* should be 0x10, bus service */ + } + + /* + * Enter Status (and Message In) Phase + */ + + k = jiffies + WATCHDOG; + + while (time_before(jiffies, k) && !priv->qabort && + !(inb(qbase + 4) & 6)) + cpu_relax(); /* wait for status phase */ + + if (time_after_eq(jiffies, k)) { + ql_zap(priv); + return (DID_TIME_OUT << 16); + } + + /* FIXME: timeout ?? */ + while (inb(qbase + 5)) + cpu_relax(); /* clear pending ints */ + + if (priv->qabort) + return ((priv->qabort == 1 ? DID_ABORT : DID_RESET) << 16); + + outb(0x11, qbase + 3); /* get status and message */ + if ((k = ql_wai(priv))) + return (k << 16); + i = inb(qbase + 5); /* get chip irq stat */ + j = inb(qbase + 7) & 0x1f; /* and bytes rec'd */ + status = inb(qbase + 2); + message = inb(qbase + 2); + + /* + * Should get function complete int if Status and message, else + * bus serv if only status + */ + if (!((i == 8 && j == 2) || (i == 0x10 && j == 1))) { + printk(KERN_ERR "Ql:Error during status phase, int=%02X, %d bytes recd\n", i, j); + result = DID_ERROR; + } + outb(0x12, qbase + 3); /* done, disconnect */ + rtrc(1) + if ((k = ql_wai(priv))) + return (k << 16); + + /* + * Should get bus service interrupt and disconnect interrupt + */ + + i = inb(qbase + 5); /* should be bus service */ + while (!priv->qabort && ((i & 0x20) != 0x20)) { + barrier(); + cpu_relax(); + i |= inb(qbase + 5); + } + rtrc(0) + + if (priv->qabort) + return ((priv->qabort == 1 ? DID_ABORT : DID_RESET) << 16); + + return (result << 16) | (message << 8) | (status & STATUS_MASK); +} + +/* + * Interrupt handler + */ + +static void ql_ihandl(int irq, void *dev_id, struct pt_regs *regs) +{ + Scsi_Cmnd *icmd; + struct Scsi_Host *host = (struct Scsi_Host *)dev_id; + struct qlogicfas408_priv *priv = get_priv_by_host(host); + int qbase = priv->qbase; + REG0; + + if (!(inb(qbase + 4) & 0x80)) /* false alarm? */ + return; + + if (priv->qlcmd == NULL) { /* no command to process? */ + int i; + i = 16; + while (i-- && inb(qbase + 5)); /* maybe also ql_zap() */ + return; + } + icmd = priv->qlcmd; + icmd->result = ql_pcmd(icmd); + priv->qlcmd = NULL; + /* + * If result is CHECK CONDITION done calls qcommand to request + * sense + */ + (icmd->scsi_done) (icmd); +} + +irqreturn_t qlogicfas408_ihandl(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long flags; + struct Scsi_Host *host = dev_id; + + spin_lock_irqsave(host->host_lock, flags); + ql_ihandl(irq, dev_id, regs); + spin_unlock_irqrestore(host->host_lock, flags); + return IRQ_HANDLED; +} + +/* + * Queued command + */ + +int qlogicfas408_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) +{ + struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd); + if (cmd->device->id == priv->qinitid) { + cmd->result = DID_BAD_TARGET << 16; + done(cmd); + return 0; + } + + cmd->scsi_done = done; + /* wait for the last command's interrupt to finish */ + while (priv->qlcmd != NULL) { + barrier(); + cpu_relax(); + } + ql_icmd(cmd); + return 0; +} + +/* + * Return bios parameters + */ + +int qlogicfas408_biosparam(struct scsi_device * disk, + struct block_device *dev, + sector_t capacity, int ip[]) +{ +/* This should mimic the DOS Qlogic driver's behavior exactly */ + ip[0] = 0x40; + ip[1] = 0x20; + ip[2] = (unsigned long) capacity / (ip[0] * ip[1]); + if (ip[2] > 1024) { + ip[0] = 0xff; + ip[1] = 0x3f; + ip[2] = (unsigned long) capacity / (ip[0] * ip[1]); +#if 0 + if (ip[2] > 1023) + ip[2] = 1023; +#endif + } + return 0; +} + +/* + * Abort a command in progress + */ + +int qlogicfas408_abort(Scsi_Cmnd * cmd) +{ + struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd); + priv->qabort = 1; + ql_zap(priv); + return SUCCESS; +} + +/* + * Reset SCSI bus + * FIXME: This function is invoked with cmd = NULL directly by + * the PCMCIA qlogic_stub code. This wants fixing + */ + +int qlogicfas408_bus_reset(Scsi_Cmnd * cmd) +{ + struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd); + priv->qabort = 2; + ql_zap(priv); + return SUCCESS; +} + +/* + * Reset SCSI host controller + */ + +int qlogicfas408_host_reset(Scsi_Cmnd * cmd) +{ + return FAILED; +} + +/* + * Reset SCSI device + */ + +int qlogicfas408_device_reset(Scsi_Cmnd * cmd) +{ + return FAILED; +} + +/* + * Return info string + */ + +char *qlogicfas408_info(struct Scsi_Host *host) +{ + struct qlogicfas408_priv *priv = get_priv_by_host(host); + return priv->qinfo; +} + +/* + * Get type of chip + */ + +int qlogicfas408_get_chip_type(int qbase, int int_type) +{ + REG1; + return inb(qbase + 0xe) & 0xf8; +} + +/* + * Perform initialization tasks + */ + +void qlogicfas408_setup(int qbase, int id, int int_type) +{ + outb(1, qbase + 8); /* set for PIO pseudo DMA */ + REG0; + outb(0x40 | qlcfg8 | id, qbase + 8); /* (ini) bus id, disable scsi rst */ + outb(qlcfg5, qbase + 5); /* select timer */ + outb(qlcfg9, qbase + 9); /* prescaler */ + +#if QL_RESET_AT_START + outb(3, qbase + 3); + + REG1; + /* FIXME: timeout */ + while (inb(qbase + 0xf) & 4) + cpu_relax(); + + REG0; +#endif +} + +/* + * Checks if this is a QLogic FAS 408 + */ + +int qlogicfas408_detect(int qbase, int int_type) +{ + REG1; + return (((inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7) && + ((inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7)); +} + +/* + * Disable interrupts + */ + +void qlogicfas408_disable_ints(struct qlogicfas408_priv *priv) +{ + int qbase = priv->qbase; + int int_type = priv->int_type; + + REG1; + outb(0, qbase + 0xb); /* disable ints */ +} + +/* + * Init and exit functions + */ + +static int __init qlogicfas408_init(void) +{ + return 0; +} + +static void __exit qlogicfas408_exit(void) +{ + +} + +MODULE_AUTHOR("Tom Zerucha, Michael Griffith"); +MODULE_DESCRIPTION("Driver for the Qlogic FAS SCSI controllers"); +MODULE_LICENSE("GPL"); +module_init(qlogicfas408_init); +module_exit(qlogicfas408_exit); + +EXPORT_SYMBOL(qlogicfas408_info); +EXPORT_SYMBOL(qlogicfas408_queuecommand); +EXPORT_SYMBOL(qlogicfas408_abort); +EXPORT_SYMBOL(qlogicfas408_bus_reset); +EXPORT_SYMBOL(qlogicfas408_device_reset); +EXPORT_SYMBOL(qlogicfas408_host_reset); +EXPORT_SYMBOL(qlogicfas408_biosparam); +EXPORT_SYMBOL(qlogicfas408_ihandl); +EXPORT_SYMBOL(qlogicfas408_get_chip_type); +EXPORT_SYMBOL(qlogicfas408_setup); +EXPORT_SYMBOL(qlogicfas408_detect); +EXPORT_SYMBOL(qlogicfas408_disable_ints); + --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/drivers/scsi/qlogicfas408.h 2004-05-10 01:19:04.908992776 -0700 @@ -0,0 +1,120 @@ +/* to be used by qlogicfas and qlogic_cs */ +#ifndef __QLOGICFAS408_H +#define __QLOGICFAS408_H + +/*----------------------------------------------------------------*/ +/* Configuration */ + +/* Set the following to max out the speed of the PIO PseudoDMA transfers, + again, 0 tends to be slower, but more stable. */ + +#define QL_TURBO_PDMA 1 + +/* This should be 1 to enable parity detection */ + +#define QL_ENABLE_PARITY 1 + +/* This will reset all devices when the driver is initialized (during bootup). + The other linux drivers don't do this, but the DOS drivers do, and after + using DOS or some kind of crash or lockup this will bring things back + without requiring a cold boot. It does take some time to recover from a + reset, so it is slower, and I have seen timeouts so that devices weren't + recognized when this was set. */ + +#define QL_RESET_AT_START 0 + +/* crystal frequency in megahertz (for offset 5 and 9) + Please set this for your card. Most Qlogic cards are 40 Mhz. The + Control Concepts ISA (not VLB) is 24 Mhz */ + +#define XTALFREQ 40 + +/**********/ +/* DANGER! modify these at your own risk */ +/* SLOWCABLE can usually be reset to zero if you have a clean setup and + proper termination. The rest are for synchronous transfers and other + advanced features if your device can transfer faster than 5Mb/sec. + If you are really curious, email me for a quick howto until I have + something official */ +/**********/ + +/*****/ +/* config register 1 (offset 8) options */ +/* This needs to be set to 1 if your cabling is long or noisy */ +#define SLOWCABLE 1 + +/*****/ +/* offset 0xc */ +/* This will set fast (10Mhz) synchronous timing when set to 1 + For this to have an effect, FASTCLK must also be 1 */ +#define FASTSCSI 0 + +/* This when set to 1 will set a faster sync transfer rate */ +#define FASTCLK 0 /*(XTALFREQ>25?1:0)*/ + +/*****/ +/* offset 6 */ +/* This is the sync transfer divisor, XTALFREQ/X will be the maximum + achievable data rate (assuming the rest of the system is capable + and set properly) */ +#define SYNCXFRPD 5 /*(XTALFREQ/5)*/ + +/*****/ +/* offset 7 */ +/* This is the count of how many synchronous transfers can take place + i.e. how many reqs can occur before an ack is given. + The maximum value for this is 15, the upper bits can modify + REQ/ACK assertion and deassertion during synchronous transfers + If this is 0, the bus will only transfer asynchronously */ +#define SYNCOFFST 0 +/* for the curious, bits 7&6 control the deassertion delay in 1/2 cycles + of the 40Mhz clock. If FASTCLK is 1, specifying 01 (1/2) will + cause the deassertion to be early by 1/2 clock. Bits 5&4 control + the assertion delay, also in 1/2 clocks (FASTCLK is ignored here). */ + +/*----------------------------------------------------------------*/ + +struct qlogicfas408_priv { + int qbase; /* Port */ + int qinitid; /* initiator ID */ + int qabort; /* Flag to cause an abort */ + int qlirq; /* IRQ being used */ + int int_type; /* type of irq, 2 for ISA board, 0 for PCMCIA */ + char qinfo[80]; /* description */ + Scsi_Cmnd *qlcmd; /* current command being processed */ + struct Scsi_Host *shost; /* pointer back to host */ + struct qlogicfas408_priv *next; /* next private struct */ +}; + +/* The qlogic card uses two register maps - These macros select which one */ +#define REG0 ( outb( inb( qbase + 0xd ) & 0x7f , qbase + 0xd ), outb( 4 , qbase + 0xd )) +#define REG1 ( outb( inb( qbase + 0xd ) | 0x80 , qbase + 0xd ), outb( 0xb4 | int_type, qbase + 0xd )) + +/* following is watchdog timeout in microseconds */ +#define WATCHDOG 5000000 + +/*----------------------------------------------------------------*/ +/* the following will set the monitor border color (useful to find + where something crashed or gets stuck at and as a simple profiler) */ + +#define rtrc(i) {} + +#define get_priv_by_cmd(x) (struct qlogicfas408_priv *)&((x)->device->host->hostdata[0]) +#define get_priv_by_host(x) (struct qlogicfas408_priv *)&((x)->hostdata[0]) + +irqreturn_t qlogicfas408_ihandl(int irq, void *dev_id, struct pt_regs *regs); +int qlogicfas408_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)); +int qlogicfas408_biosparam(struct scsi_device * disk, + struct block_device *dev, + sector_t capacity, int ip[]); +int qlogicfas408_abort(Scsi_Cmnd * cmd); +int qlogicfas408_bus_reset(Scsi_Cmnd * cmd); +int qlogicfas408_host_reset(Scsi_Cmnd * cmd); +int qlogicfas408_device_reset(Scsi_Cmnd * cmd); +char *qlogicfas408_info(struct Scsi_Host *host); +int qlogicfas408_get_chip_type(int qbase, int int_type); +void qlogicfas408_setup(int qbase, int id, int int_type); +int qlogicfas408_detect(int qbase, int int_type); +void qlogicfas408_disable_ints(struct qlogicfas408_priv *priv); +#endif /* __QLOGICFAS408_H */ + --- linux-2.6.6/drivers/scsi/qlogicfas.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/scsi/qlogicfas.c 2004-05-10 01:19:04.903993536 -0700 @@ -1,43 +1,19 @@ -/*----------------------------------------------------------------*/ /* - Qlogic linux driver - work in progress. No Warranty express or implied. - Use at your own risk. Support Tort Reform so you won't have to read all - these silly disclaimers. - - Copyright 1994, Tom Zerucha. - tz@execpc.com - - Additional Code, and much appreciated help by - Michael A. Griffith - grif@cs.ucr.edu - - Thanks to Eric Youngdale and Dave Hinds for loadable module and PCMCIA - help respectively, and for suffering through my foolishness during the - debugging process. - - Reference Qlogic FAS408 Technical Manual, 53408-510-00A, May 10, 1994 - (you can reference it, but it is incomplete and inaccurate in places) - - Version 0.46 1/30/97 - kernel 1.2.0+ - - Functions as standalone, loadable, and PCMCIA driver, the latter from - Dave Hinds' PCMCIA package. - - Cleaned up 26/10/2002 by Alan Cox as part of the 2.5 - SCSI driver cleanup and audit. This driver still needs work on the - following - - Non terminating hardware waits - - Some layering violations with its pcmcia stub - - Redistributable under terms of the GNU General Public License - - For the avoidance of doubt the "preferred form" of this code is one which - is in an open non patent encumbered format. Where cryptographic key signing - forms part of the process of creating an executable the information - including keys needed to generate an equivalently functional executable - are deemed to be part of the source code. - -*/ + * Qlogic FAS408 ISA card driver + * + * Copyright 1994, Tom Zerucha. + * tz@execpc.com + * + * Redistributable under terms of the GNU General Public License + * + * For the avoidance of doubt the "preferred form" of this code is one which + * is in an open non patent encumbered format. Where cryptographic key signing + * forms part of the process of creating an executable the information + * including keys needed to generate an equivalently functional executable + * are deemed to be part of the source code. + * + * Check qlogicfas408.c for more credits and info. + */ #include #include /* to get disk capacity */ @@ -57,429 +33,28 @@ #include "scsi.h" #include "hosts.h" -#include "qlogicfas.h" - -/*----------------------------------------------------------------*/ -int qlcfg5 = (XTALFREQ << 5); /* 15625/512 */ -int qlcfg6 = SYNCXFRPD; -int qlcfg7 = SYNCOFFST; -int qlcfg8 = (SLOWCABLE << 7) | (QL_ENABLE_PARITY << 4); -int qlcfg9 = ((XTALFREQ + 4) / 5); -int qlcfgc = (FASTCLK << 3) | (FASTSCSI << 4); - -static char qlogicfas_name[] = "qlogicfas"; - -int qlogicfas_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)); - -/*----------------------------------------------------------------*/ - -/*----------------------------------------------------------------*/ -/* local functions */ -/*----------------------------------------------------------------*/ - -/* error recovery - reset everything */ - -static void ql_zap(qlogicfas_priv_t priv) -{ - int x; - int qbase = priv->qbase; - - x = inb(qbase + 0xd); - REG0; - outb(3, qbase + 3); /* reset SCSI */ - outb(2, qbase + 3); /* reset chip */ - if (x & 0x80) - REG1; -} - -/* - * Do a pseudo-dma tranfer - */ - -static int ql_pdma(qlogicfas_priv_t priv, int phase, char *request, int reqlen) -{ - int j; - int qbase = priv->qbase; - j = 0; - if (phase & 1) { /* in */ -#if QL_TURBO_PDMA - rtrc(4) - /* empty fifo in large chunks */ - if (reqlen >= 128 && (inb(qbase + 8) & 2)) { /* full */ - insl(qbase + 4, request, 32); - reqlen -= 128; - request += 128; - } - while (reqlen >= 84 && !(j & 0xc0)) /* 2/3 */ - if ((j = inb(qbase + 8)) & 4) - { - insl(qbase + 4, request, 21); - reqlen -= 84; - request += 84; - } - if (reqlen >= 44 && (inb(qbase + 8) & 8)) { /* 1/3 */ - insl(qbase + 4, request, 11); - reqlen -= 44; - request += 44; - } -#endif - /* until both empty and int (or until reclen is 0) */ - rtrc(7) - j = 0; - while (reqlen && !((j & 0x10) && (j & 0xc0))) - { - /* while bytes to receive and not empty */ - j &= 0xc0; - while (reqlen && !((j = inb(qbase + 8)) & 0x10)) - { - *request++ = inb(qbase + 4); - reqlen--; - } - if (j & 0x10) - j = inb(qbase + 8); - - } - } else { /* out */ -#if QL_TURBO_PDMA - rtrc(4) - if (reqlen >= 128 && inb(qbase + 8) & 0x10) { /* empty */ - outsl(qbase + 4, request, 32); - reqlen -= 128; - request += 128; - } - while (reqlen >= 84 && !(j & 0xc0)) /* 1/3 */ - if (!((j = inb(qbase + 8)) & 8)) { - outsl(qbase + 4, request, 21); - reqlen -= 84; - request += 84; - } - if (reqlen >= 40 && !(inb(qbase + 8) & 4)) { /* 2/3 */ - outsl(qbase + 4, request, 10); - reqlen -= 40; - request += 40; - } -#endif - /* until full and int (or until reclen is 0) */ - rtrc(7) - j = 0; - while (reqlen && !((j & 2) && (j & 0xc0))) { - /* while bytes to send and not full */ - while (reqlen && !((j = inb(qbase + 8)) & 2)) - { - outb(*request++, qbase + 4); - reqlen--; - } - if (j & 2) - j = inb(qbase + 8); - } - } - /* maybe return reqlen */ - return inb(qbase + 8) & 0xc0; -} - -/* - * Wait for interrupt flag (polled - not real hardware interrupt) - */ - -static int ql_wai(qlogicfas_priv_t priv) -{ - int k; - int qbase = priv->qbase; - unsigned long i; - - k = 0; - i = jiffies + WATCHDOG; - while (time_before(jiffies, i) && !priv->qabort && - !((k = inb(qbase + 4)) & 0xe0)) { - barrier(); - cpu_relax(); - } - if (time_after_eq(jiffies, i)) - return (DID_TIME_OUT); - if (priv->qabort) - return (priv->qabort == 1 ? DID_ABORT : DID_RESET); - if (k & 0x60) - ql_zap(priv); - if (k & 0x20) - return (DID_PARITY); - if (k & 0x40) - return (DID_ERROR); - return 0; -} - -/* - * Initiate scsi command - queueing handler - * caller must hold host lock - */ - -static void ql_icmd(Scsi_Cmnd * cmd) -{ - qlogicfas_priv_t priv = (qlogicfas_priv_t)&(cmd->device->host->hostdata[0]); - int qbase = priv->qbase; - unsigned int i; - - priv->qabort = 0; - - REG0; - /* clearing of interrupts and the fifo is needed */ - - inb(qbase + 5); /* clear interrupts */ - if (inb(qbase + 5)) /* if still interrupting */ - outb(2, qbase + 3); /* reset chip */ - else if (inb(qbase + 7) & 0x1f) - outb(1, qbase + 3); /* clear fifo */ - while (inb(qbase + 5)); /* clear ints */ - REG1; - outb(1, qbase + 8); /* set for PIO pseudo DMA */ - outb(0, qbase + 0xb); /* disable ints */ - inb(qbase + 8); /* clear int bits */ - REG0; - outb(0x40, qbase + 0xb); /* enable features */ - - /* configurables */ - outb(qlcfgc, qbase + 0xc); - /* config: no reset interrupt, (initiator) bus id */ - outb(0x40 | qlcfg8 | priv->qinitid, qbase + 8); - outb(qlcfg7, qbase + 7); - outb(qlcfg6, qbase + 6); - /**/ outb(qlcfg5, qbase + 5); /* select timer */ - outb(qlcfg9 & 7, qbase + 9); /* prescaler */ -/* outb(0x99, qbase + 5); */ - outb(cmd->device->id, qbase + 4); - - for (i = 0; i < cmd->cmd_len; i++) - outb(cmd->cmnd[i], qbase + 2); - - priv->qlcmd = cmd; - outb(0x41, qbase + 3); /* select and send command */ -} - -/* - * Process scsi command - usually after interrupt - */ - -static unsigned int ql_pcmd(Scsi_Cmnd * cmd) -{ - unsigned int i, j; - unsigned long k; - unsigned int result; /* ultimate return result */ - unsigned int status; /* scsi returned status */ - unsigned int message; /* scsi returned message */ - unsigned int phase; /* recorded scsi phase */ - unsigned int reqlen; /* total length of transfer */ - struct scatterlist *sglist; /* scatter-gather list pointer */ - unsigned int sgcount; /* sg counter */ - char *buf; - qlogicfas_priv_t priv = (qlogicfas_priv_t)&(cmd->device->host->hostdata[0]); - int qbase = priv->qbase; - - rtrc(1) - j = inb(qbase + 6); - i = inb(qbase + 5); - if (i == 0x20) { - return (DID_NO_CONNECT << 16); - } - i |= inb(qbase + 5); /* the 0x10 bit can be set after the 0x08 */ - if (i != 0x18) { - printk(KERN_ERR "Ql:Bad Interrupt status:%02x\n", i); - ql_zap(priv); - return (DID_BAD_INTR << 16); - } - j &= 7; /* j = inb( qbase + 7 ) >> 5; */ - - /* correct status is supposed to be step 4 */ - /* it sometimes returns step 3 but with 0 bytes left to send */ - /* We can try stuffing the FIFO with the max each time, but we will get a - sequence of 3 if any bytes are left (but we do flush the FIFO anyway */ - - if (j != 3 && j != 4) { - printk(KERN_ERR "Ql:Bad sequence for command %d, int %02X, cmdleft = %d\n", - j, i, inb(qbase + 7) & 0x1f); - ql_zap(priv); - return (DID_ERROR << 16); - } - result = DID_OK; - if (inb(qbase + 7) & 0x1f) /* if some bytes in fifo */ - outb(1, qbase + 3); /* clear fifo */ - /* note that request_bufflen is the total xfer size when sg is used */ - reqlen = cmd->request_bufflen; - /* note that it won't work if transfers > 16M are requested */ - if (reqlen && !((phase = inb(qbase + 4)) & 6)) { /* data phase */ - rtrc(2) - outb(reqlen, qbase); /* low-mid xfer cnt */ - outb(reqlen >> 8, qbase + 1); /* low-mid xfer cnt */ - outb(reqlen >> 16, qbase + 0xe); /* high xfer cnt */ - outb(0x90, qbase + 3); /* command do xfer */ - /* PIO pseudo DMA to buffer or sglist */ - REG1; - if (!cmd->use_sg) - ql_pdma(priv, phase, cmd->request_buffer, - cmd->request_bufflen); - else { - sgcount = cmd->use_sg; - sglist = cmd->request_buffer; - while (sgcount--) { - if (priv->qabort) { - REG0; - return ((priv->qabort == 1 ? - DID_ABORT : DID_RESET) << 16); - } - buf = page_address(sglist->page) + sglist->offset; - if (ql_pdma(priv, phase, buf, sglist->length)) - break; - sglist++; - } - } - REG0; - rtrc(2) - /* - * Wait for irq (split into second state of irq handler - * if this can take time) - */ - if ((k = ql_wai(priv))) - return (k << 16); - k = inb(qbase + 5); /* should be 0x10, bus service */ - } - - /* - * Enter Status (and Message In) Phase - */ - - k = jiffies + WATCHDOG; - - while (time_before(jiffies, k) && !priv->qabort && - !(inb(qbase + 4) & 6)) - cpu_relax(); /* wait for status phase */ - - if (time_after_eq(jiffies, k)) { - ql_zap(priv); - return (DID_TIME_OUT << 16); - } - - /* FIXME: timeout ?? */ - while (inb(qbase + 5)) - cpu_relax(); /* clear pending ints */ - - if (priv->qabort) - return ((priv->qabort == 1 ? DID_ABORT : DID_RESET) << 16); - - outb(0x11, qbase + 3); /* get status and message */ - if ((k = ql_wai(priv))) - return (k << 16); - i = inb(qbase + 5); /* get chip irq stat */ - j = inb(qbase + 7) & 0x1f; /* and bytes rec'd */ - status = inb(qbase + 2); - message = inb(qbase + 2); - - /* - * Should get function complete int if Status and message, else - * bus serv if only status - */ - if (!((i == 8 && j == 2) || (i == 0x10 && j == 1))) { - printk(KERN_ERR "Ql:Error during status phase, int=%02X, %d bytes recd\n", i, j); - result = DID_ERROR; - } - outb(0x12, qbase + 3); /* done, disconnect */ - rtrc(1) - if ((k = ql_wai(priv))) - return (k << 16); - - /* - * Should get bus service interrupt and disconnect interrupt - */ - - i = inb(qbase + 5); /* should be bus service */ - while (!priv->qabort && ((i & 0x20) != 0x20)) { - barrier(); - cpu_relax(); - i |= inb(qbase + 5); - } - rtrc(0) - - if (priv->qabort) - return ((priv->qabort == 1 ? DID_ABORT : DID_RESET) << 16); - - return (result << 16) | (message << 8) | (status & STATUS_MASK); -} +#include "qlogicfas408.h" -/* - * Interrupt handler +/* Set the following to 2 to use normal interrupt (active high/totempole- + * tristate), otherwise use 0 (REQUIRED FOR PCMCIA) for active low, open + * drain */ +#define INT_TYPE 2 -static void ql_ihandl(int irq, void *dev_id, struct pt_regs *regs) -{ - Scsi_Cmnd *icmd; - struct Scsi_Host *host = (struct Scsi_Host *)dev_id; - qlogicfas_priv_t priv = (qlogicfas_priv_t)&(host->hostdata[0]); - int qbase = priv->qbase; - REG0; - - if (!(inb(qbase + 4) & 0x80)) /* false alarm? */ - return; - - if (priv->qlcmd == NULL) { /* no command to process? */ - int i; - i = 16; - while (i-- && inb(qbase + 5)); /* maybe also ql_zap() */ - return; - } - icmd = priv->qlcmd; - icmd->result = ql_pcmd(icmd); - priv->qlcmd = NULL; - /* - * If result is CHECK CONDITION done calls qcommand to request - * sense - */ - (icmd->scsi_done) (icmd); -} - -irqreturn_t do_ql_ihandl(int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - struct Scsi_Host *host = dev_id; - - spin_lock_irqsave(host->host_lock, flags); - ql_ihandl(irq, dev_id, regs); - spin_unlock_irqrestore(host->host_lock, flags); - return IRQ_HANDLED; -} - -/* - * Queued command - */ - -int qlogicfas_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) -{ - qlogicfas_priv_t priv = (qlogicfas_priv_t)&(cmd->device->host->hostdata[0]); - if (cmd->device->id == priv->qinitid) { - cmd->result = DID_BAD_TARGET << 16; - done(cmd); - return 0; - } - - cmd->scsi_done = done; - /* wait for the last command's interrupt to finish */ - while (priv->qlcmd != NULL) { - barrier(); - cpu_relax(); - } - ql_icmd(cmd); - return 0; -} +static char qlogicfas_name[] = "qlogicfas"; -#ifndef PCMCIA /* * Look for qlogic card and init if found */ -struct Scsi_Host *__qlogicfas_detect(Scsi_Host_Template *host, int qbase, +static struct Scsi_Host *__qlogicfas_detect(Scsi_Host_Template *host, + int qbase, int qlirq) { - int i, j; /* these are only used by IRQ detect */ int qltyp; /* type of chip */ int qinitid; struct Scsi_Host *hreg; /* registered host structure */ - qlogicfas_priv_t priv; + struct qlogicfas408_priv *priv; /* Qlogic Cards only exist at 0x230 or 0x330 (the chip itself * decodes the address - I check 230 first since MIDI cards are @@ -490,70 +65,36 @@ struct Scsi_Host *__qlogicfas_detect(Scs * the second card, but I haven't tested this. */ - if (!qbase) { - for (qbase = 0x230; qbase < 0x430; qbase += 0x100) { - if (!request_region(qbase, 0x10, qlogicfas_name)) - continue; - REG1; - if (((inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7) - && ((inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7)) - break; - release_region(qbase, 0x10); - } - if (qbase == 0x430) - return NULL; - } else - printk(KERN_INFO "Ql: Using preset base address of %03x\n", qbase); + if (!qbase || qlirq == -1) + goto err; + + if (!request_region(qbase, 0x10, qlogicfas_name)) { + printk(KERN_INFO "%s: address %#x is busy\n", qlogicfas_name, + qbase); + goto err; + } + + if (!qlogicfas408_detect(qbase, INT_TYPE)) { + printk(KERN_WARNING "%s: probe failed for %#x\n", + qlogicfas_name, + qbase); + goto err_release_mem; + } - qltyp = inb(qbase + 0xe) & 0xf8; + printk(KERN_INFO "%s: Using preset base address of %03x," + " IRQ %d\n", qlogicfas_name, qbase, qlirq); + + qltyp = qlogicfas408_get_chip_type(qbase, INT_TYPE); qinitid = host->this_id; if (qinitid < 0) qinitid = 7; /* if no ID, use 7 */ - outb(1, qbase + 8); /* set for PIO pseudo DMA */ - REG0; - outb(0x40 | qlcfg8 | qinitid, qbase + 8); /* (ini) bus id, disable scsi rst */ - outb(qlcfg5, qbase + 5); /* select timer */ - outb(qlcfg9, qbase + 9); /* prescaler */ - -#if QL_RESET_AT_START - outb(3, qbase + 3); - REG1; - /* FIXME: timeout */ - while (inb(qbase + 0xf) & 4) - cpu_relax(); - REG0; -#endif - - /* - * IRQ probe - toggle pin and check request pending - */ - if (qlirq == -1) { - i = 0xffff; - j = 3; - outb(0x90, qbase + 3); /* illegal command - cause interrupt */ - REG1; - outb(10, 0x20); /* access pending interrupt map */ - outb(10, 0xa0); - while (j--) { - outb(0xb0 | QL_INT_ACTIVE_HIGH, qbase + 0xd); /* int pin off */ - i &= ~(inb(0x20) | (inb(0xa0) << 8)); /* find IRQ off */ - outb(0xb4 | QL_INT_ACTIVE_HIGH, qbase + 0xd); /* int pin on */ - i &= inb(0x20) | (inb(0xa0) << 8); /* find IRQ on */ - } - REG0; - while (inb(qbase + 5)); /* purge int */ - j = -1; - while (i) /* find on bit */ - i >>= 1, j++; /* should check for exactly 1 on */ - qlirq = j; - } else - printk(KERN_INFO "Ql: Using preset IRQ %d\n", qlirq); + qlogicfas408_setup(qbase, qinitid, INT_TYPE); - hreg = scsi_host_alloc(host, sizeof(struct qlogicfas_priv)); + hreg = scsi_host_alloc(host, sizeof(struct qlogicfas408_priv)); if (!hreg) goto err_release_mem; - priv = (qlogicfas_priv_t)&(hreg->hostdata[0]); + priv = get_priv_by_host(hreg); hreg->io_port = qbase; hreg->n_io_port = 16; hreg->dma_channel = -1; @@ -563,13 +104,14 @@ struct Scsi_Host *__qlogicfas_detect(Scs priv->qlirq = qlirq; priv->qinitid = qinitid; priv->shost = hreg; + priv->int_type = INT_TYPE; sprintf(priv->qinfo, "Qlogicfas Driver version 0.46, chip %02X at %03X, IRQ %d, TPdma:%d", qltyp, qbase, qlirq, QL_TURBO_PDMA); host->name = qlogicfas_name; - if (request_irq(qlirq, do_ql_ihandl, 0, qlogicfas_name, hreg)) + if (request_irq(qlirq, qlogicfas408_ihandl, 0, qlogicfas_name, hreg)) goto free_scsi_host; if (scsi_add_host(hreg, NULL)) @@ -587,11 +129,12 @@ free_scsi_host: err_release_mem: release_region(qbase, 0x10); +err: return NULL; } #define MAX_QLOGICFAS 8 -static qlogicfas_priv_t cards; +static struct qlogicfas408_priv *cards; static int iobase[MAX_QLOGICFAS]; static int irq[MAX_QLOGICFAS] = { [0 ... MAX_QLOGICFAS-1] = -1 }; MODULE_PARM(iobase, "1-" __MODULE_STRING(MAX_QLOGICFAS) "i"); @@ -599,23 +142,21 @@ MODULE_PARM(irq, "1-" __MODULE_STRING(MA MODULE_PARM_DESC(iobase, "I/O address"); MODULE_PARM_DESC(irq, "IRQ"); -int __devinit qlogicfas_detect(Scsi_Host_Template *sht) +static int __devinit qlogicfas_detect(Scsi_Host_Template *sht) { - struct Scsi_Host *shost; - qlogicfas_priv_t priv; - int i, - num = 0; + struct Scsi_Host *shost; + struct qlogicfas408_priv *priv; + int num; - for (i = 0; i < MAX_QLOGICFAS; i++) { + for (num = 0; num < MAX_QLOGICFAS; num++) { shost = __qlogicfas_detect(sht, iobase[num], irq[num]); if (shost == NULL) { /* no more devices */ break; } - priv = (qlogicfas_priv_t)&(shost->hostdata[0]); + priv = get_priv_by_host(shost); priv->next = cards; cards = priv; - num++; } return num; @@ -623,13 +164,10 @@ int __devinit qlogicfas_detect(Scsi_Host static int qlogicfas_release(struct Scsi_Host *shost) { - qlogicfas_priv_t priv = (qlogicfas_priv_t)&(shost->hostdata[0]); - int qbase = priv->qbase; + struct qlogicfas408_priv *priv = get_priv_by_host(shost); if (shost->irq) { - REG1; - outb(0, qbase + 0xb); /* disable ints */ - + qlogicfas408_disable_ints(priv); free_irq(shost->irq, shost); } if (shost->dma_channel != 0xff) @@ -641,100 +179,21 @@ static int qlogicfas_release(struct Scsi return 0; } -#endif /* ifndef PCMCIA */ - -/* - * Return bios parameters - */ - -int qlogicfas_biosparam(struct scsi_device * disk, - struct block_device *dev, - sector_t capacity, int ip[]) -{ -/* This should mimic the DOS Qlogic driver's behavior exactly */ - ip[0] = 0x40; - ip[1] = 0x20; - ip[2] = (unsigned long) capacity / (ip[0] * ip[1]); - if (ip[2] > 1024) { - ip[0] = 0xff; - ip[1] = 0x3f; - ip[2] = (unsigned long) capacity / (ip[0] * ip[1]); -#if 0 - if (ip[2] > 1023) - ip[2] = 1023; -#endif - } - return 0; -} - -/* - * Abort a command in progress - */ - -static int qlogicfas_abort(Scsi_Cmnd * cmd) -{ - qlogicfas_priv_t priv = (qlogicfas_priv_t)&(cmd->device->host->hostdata[0]); - priv->qabort = 1; - ql_zap(priv); - return SUCCESS; -} - -/* - * Reset SCSI bus - * FIXME: This function is invoked with cmd = NULL directly by - * the PCMCIA qlogic_stub code. This wants fixing - */ - -int qlogicfas_bus_reset(Scsi_Cmnd * cmd) -{ - qlogicfas_priv_t priv = (qlogicfas_priv_t)&(cmd->device->host->hostdata[0]); - priv->qabort = 2; - ql_zap(priv); - return SUCCESS; -} - -/* - * Reset SCSI host controller - */ - -static int qlogicfas_host_reset(Scsi_Cmnd * cmd) -{ - return FAILED; -} - -/* - * Reset SCSI device - */ - -static int qlogicfas_device_reset(Scsi_Cmnd * cmd) -{ - return FAILED; -} - -/* - * Return info string - */ - -static const char *qlogicfas_info(struct Scsi_Host *host) -{ - qlogicfas_priv_t priv = (qlogicfas_priv_t)&(host->hostdata[0]); - return priv->qinfo; -} /* * The driver template is also needed for PCMCIA */ -Scsi_Host_Template qlogicfas_driver_template = { +static Scsi_Host_Template qlogicfas_driver_template = { .module = THIS_MODULE, .name = qlogicfas_name, .proc_name = qlogicfas_name, - .info = qlogicfas_info, - .queuecommand = qlogicfas_queuecommand, - .eh_abort_handler = qlogicfas_abort, - .eh_bus_reset_handler = qlogicfas_bus_reset, - .eh_device_reset_handler= qlogicfas_device_reset, - .eh_host_reset_handler = qlogicfas_host_reset, - .bios_param = qlogicfas_biosparam, + .info = qlogicfas408_info, + .queuecommand = qlogicfas408_queuecommand, + .eh_abort_handler = qlogicfas408_abort, + .eh_bus_reset_handler = qlogicfas408_bus_reset, + .eh_device_reset_handler= qlogicfas408_device_reset, + .eh_host_reset_handler = qlogicfas408_host_reset, + .bios_param = qlogicfas408_biosparam, .can_queue = 1, .this_id = -1, .sg_tablesize = SG_ALL, @@ -742,11 +201,13 @@ Scsi_Host_Template qlogicfas_driver_temp .use_clustering = DISABLE_CLUSTERING, }; -#ifndef PCMCIA static __init int qlogicfas_init(void) { if (!qlogicfas_detect(&qlogicfas_driver_template)) { /* no cards found */ + printk(KERN_INFO "%s: no cards were found, please specify " + "I/O address and IRQ using iobase= and irq= " + "options", qlogicfas_name); return -ENODEV; } @@ -755,16 +216,15 @@ static __init int qlogicfas_init(void) static __exit void qlogicfas_exit(void) { - qlogicfas_priv_t priv; + struct qlogicfas408_priv *priv; for (priv = cards; priv != NULL; priv = priv->next) qlogicfas_release(priv->shost); } MODULE_AUTHOR("Tom Zerucha, Michael Griffith"); -MODULE_DESCRIPTION("Driver for the Qlogic FAS SCSI controllers"); +MODULE_DESCRIPTION("Driver for the Qlogic FAS408 based ISA card"); MODULE_LICENSE("GPL"); module_init(qlogicfas_init); module_exit(qlogicfas_exit); -#endif /* ifndef PCMCIA */ --- linux-2.6.6/drivers/scsi/qlogicfas.h 2004-04-03 20:39:13.000000000 -0800 +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,124 +0,0 @@ -/* to be used by qlogicfas and qlogic_cs */ -#ifndef __QLOGICFAS_H -#define __QLOGICFAS_H - -/*----------------------------------------------------------------*/ -/* Configuration */ - -/* Set the following to 2 to use normal interrupt (active high/totempole- - tristate), otherwise use 0 (REQUIRED FOR PCMCIA) for active low, open - drain */ - -#define QL_INT_ACTIVE_HIGH 2 - -/* Set the following to max out the speed of the PIO PseudoDMA transfers, - again, 0 tends to be slower, but more stable. */ - -#define QL_TURBO_PDMA 1 - -/* This should be 1 to enable parity detection */ - -#define QL_ENABLE_PARITY 1 - -/* This will reset all devices when the driver is initialized (during bootup). - The other linux drivers don't do this, but the DOS drivers do, and after - using DOS or some kind of crash or lockup this will bring things back - without requiring a cold boot. It does take some time to recover from a - reset, so it is slower, and I have seen timeouts so that devices weren't - recognized when this was set. */ - -#define QL_RESET_AT_START 0 - -/* crystal frequency in megahertz (for offset 5 and 9) - Please set this for your card. Most Qlogic cards are 40 Mhz. The - Control Concepts ISA (not VLB) is 24 Mhz */ - -#define XTALFREQ 40 - -/**********/ -/* DANGER! modify these at your own risk */ -/* SLOWCABLE can usually be reset to zero if you have a clean setup and - proper termination. The rest are for synchronous transfers and other - advanced features if your device can transfer faster than 5Mb/sec. - If you are really curious, email me for a quick howto until I have - something official */ -/**********/ - -/*****/ -/* config register 1 (offset 8) options */ -/* This needs to be set to 1 if your cabling is long or noisy */ -#define SLOWCABLE 1 - -/*****/ -/* offset 0xc */ -/* This will set fast (10Mhz) synchronous timing when set to 1 - For this to have an effect, FASTCLK must also be 1 */ -#define FASTSCSI 0 - -/* This when set to 1 will set a faster sync transfer rate */ -#define FASTCLK 0 /*(XTALFREQ>25?1:0)*/ - -/*****/ -/* offset 6 */ -/* This is the sync transfer divisor, XTALFREQ/X will be the maximum - achievable data rate (assuming the rest of the system is capable - and set properly) */ -#define SYNCXFRPD 5 /*(XTALFREQ/5)*/ - -/*****/ -/* offset 7 */ -/* This is the count of how many synchronous transfers can take place - i.e. how many reqs can occur before an ack is given. - The maximum value for this is 15, the upper bits can modify - REQ/ACK assertion and deassertion during synchronous transfers - If this is 0, the bus will only transfer asynchronously */ -#define SYNCOFFST 0 -/* for the curious, bits 7&6 control the deassertion delay in 1/2 cycles - of the 40Mhz clock. If FASTCLK is 1, specifying 01 (1/2) will - cause the deassertion to be early by 1/2 clock. Bits 5&4 control - the assertion delay, also in 1/2 clocks (FASTCLK is ignored here). */ - -/*----------------------------------------------------------------*/ -#ifdef PCMCIA -#undef QL_INT_ACTIVE_HIGH -#define QL_INT_ACTIVE_HIGH 0 -#endif - -struct qlogicfas_priv; -typedef struct qlogicfas_priv *qlogicfas_priv_t; -struct qlogicfas_priv { - int qbase; /* Port */ - int qinitid; /* initiator ID */ - int qabort; /* Flag to cause an abort */ - int qlirq; /* IRQ being used */ - char qinfo[80]; /* description */ - Scsi_Cmnd *qlcmd; /* current command being processed */ - struct Scsi_Host *shost; /* pointer back to host */ - qlogicfas_priv_t next; /* next private struct */ -}; - -extern int qlcfg5; -extern int qlcfg6; -extern int qlcfg7; -extern int qlcfg8; -extern int qlcfg9; -extern int qlcfgc; - -/* The qlogic card uses two register maps - These macros select which one */ -#define REG0 ( outb( inb( qbase + 0xd ) & 0x7f , qbase + 0xd ), outb( 4 , qbase + 0xd )) -#define REG1 ( outb( inb( qbase + 0xd ) | 0x80 , qbase + 0xd ), outb( 0xb4 | QL_INT_ACTIVE_HIGH , qbase + 0xd )) - -/* following is watchdog timeout in microseconds */ -#define WATCHDOG 5000000 - -/*----------------------------------------------------------------*/ -/* the following will set the monitor border color (useful to find - where something crashed or gets stuck at and as a simple profiler) */ - -#if 0 -#define rtrc(i) {inb(0x3da);outb(0x31,0x3c0);outb((i),0x3c0);} -#else -#define rtrc(i) {} -#endif -#endif /* __QLOGICFAS_H */ - --- linux-2.6.6/drivers/scsi/sata_promise.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/scsi/sata_promise.c 2004-05-10 01:19:03.408220928 -0700 @@ -33,16 +33,14 @@ #include "hosts.h" #include #include +#include "sata_promise.h" #define DRV_NAME "sata_promise" -#define DRV_VERSION "0.92" +#define DRV_VERSION "1.00" enum { - PDC_PRD_TBL = 0x44, /* Direct command DMA table addr */ - PDC_PKT_SUBMIT = 0x40, /* Command packet pointer addr */ - PDC_HDMA_PKT_SUBMIT = 0x100, /* Host DMA packet pointer addr */ PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */ PDC_TBG_MODE = 0x41, /* TBG mode */ PDC_FLASH_CTL = 0x44, /* Flash control register */ @@ -51,141 +49,38 @@ enum { PDC_CTLSTAT = 0x60, /* IDE control and status (per port) */ PDC_SATA_PLUG_CSR = 0x6C, /* SATA Plug control/status reg */ PDC_SLEW_CTL = 0x470, /* slew rate control reg */ - PDC_HDMA_CTLSTAT = 0x12C, /* Host DMA control / status */ - - PDC_20621_SEQCTL = 0x400, - PDC_20621_SEQMASK = 0x480, - PDC_20621_GENERAL_CTL = 0x484, - PDC_20621_PAGE_SIZE = (32 * 1024), - - /* chosen, not constant, values; we design our own DIMM mem map */ - PDC_20621_DIMM_WINDOW = 0x0C, /* page# for 32K DIMM window */ - PDC_20621_DIMM_BASE = 0x00200000, - PDC_20621_DIMM_DATA = (64 * 1024), - PDC_DIMM_DATA_STEP = (256 * 1024), - PDC_DIMM_WINDOW_STEP = (8 * 1024), - PDC_DIMM_HOST_PRD = (6 * 1024), - PDC_DIMM_HOST_PKT = (128 * 0), - PDC_DIMM_HPKT_PRD = (128 * 1), - PDC_DIMM_ATA_PKT = (128 * 2), - PDC_DIMM_APKT_PRD = (128 * 3), - PDC_DIMM_HEADER_SZ = PDC_DIMM_APKT_PRD + 128, - PDC_PAGE_WINDOW = 0x40, - PDC_PAGE_DATA = PDC_PAGE_WINDOW + - (PDC_20621_DIMM_DATA / PDC_20621_PAGE_SIZE), - PDC_PAGE_SET = PDC_DIMM_DATA_STEP / PDC_20621_PAGE_SIZE, - - PDC_CHIP0_OFS = 0xC0000, /* offset of chip #0 */ - PDC_20621_ERR_MASK = (1<<19) | (1<<20) | (1<<21) | (1<<22) | - (1<<23), PDC_ERR_MASK = (1<<19) | (1<<20) | (1<<21) | (1<<22) | (1<<8) | (1<<9) | (1<<10), board_2037x = 0, /* FastTrak S150 TX2plus */ board_20319 = 1, /* FastTrak S150 TX4 */ - board_20621 = 2, /* FastTrak S150 SX4 */ PDC_HAS_PATA = (1 << 1), /* PDC20375 has PATA */ - PDC_FLAG_20621 = (1 << 30), /* we have a 20621 */ PDC_RESET = (1 << 11), /* HDMA reset */ - - PDC_MAX_HDMA = 32, - PDC_HDMA_Q_MASK = (PDC_MAX_HDMA - 1), - - PDC_DIMM0_SPD_DEV_ADDRESS = 0x50, - PDC_DIMM1_SPD_DEV_ADDRESS = 0x51, - PDC_MAX_DIMM_MODULE = 0x02, - PDC_I2C_CONTROL_OFFSET = 0x48, - PDC_I2C_ADDR_DATA_OFFSET = 0x4C, - PDC_DIMM0_CONTROL_OFFSET = 0x80, - PDC_DIMM1_CONTROL_OFFSET = 0x84, - PDC_SDRAM_CONTROL_OFFSET = 0x88, - PDC_I2C_WRITE = 0x00000000, - PDC_I2C_READ = 0x00000040, - PDC_I2C_START = 0x00000080, - PDC_I2C_MASK_INT = 0x00000020, - PDC_I2C_COMPLETE = 0x00010000, - PDC_I2C_NO_ACK = 0x00100000, - PDC_DIMM_SPD_SUBADDRESS_START = 0x00, - PDC_DIMM_SPD_SUBADDRESS_END = 0x7F, - PDC_DIMM_SPD_ROW_NUM = 3, - PDC_DIMM_SPD_COLUMN_NUM = 4, - PDC_DIMM_SPD_MODULE_ROW = 5, - PDC_DIMM_SPD_TYPE = 11, - PDC_DIMM_SPD_FRESH_RATE = 12, - PDC_DIMM_SPD_BANK_NUM = 17, - PDC_DIMM_SPD_CAS_LATENCY = 18, - PDC_DIMM_SPD_ATTRIBUTE = 21, - PDC_DIMM_SPD_ROW_PRE_CHARGE = 27, - PDC_DIMM_SPD_ROW_ACTIVE_DELAY = 28, - PDC_DIMM_SPD_RAS_CAS_DELAY = 29, - PDC_DIMM_SPD_ACTIVE_PRECHARGE = 30, - PDC_DIMM_SPD_SYSTEM_FREQ = 126, - PDC_CTL_STATUS = 0x08, - PDC_DIMM_WINDOW_CTLR = 0x0C, - PDC_TIME_CONTROL = 0x3C, - PDC_TIME_PERIOD = 0x40, - PDC_TIME_COUNTER = 0x44, - PDC_GENERAL_CTLR = 0x484, - PCI_PLL_INIT = 0x8A531824, - PCI_X_TCOUNT = 0xEE1E5CFF }; struct pdc_port_priv { - u8 dimm_buf[(ATA_PRD_SZ * ATA_MAX_PRD) + 512]; u8 *pkt; dma_addr_t pkt_dma; }; -struct pdc_host_priv { - void *dimm_mmio; - - unsigned int doing_hdma; - unsigned int hdma_prod; - unsigned int hdma_cons; - struct { - struct ata_queued_cmd *qc; - unsigned int seq; - unsigned long pkt_ofs; - } hdma[32]; -}; - - static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg); static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); static void pdc_dma_start(struct ata_queued_cmd *qc); -static void pdc20621_dma_start(struct ata_queued_cmd *qc); static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *regs); -static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_regs *regs); static void pdc_eng_timeout(struct ata_port *ap); -static void pdc_20621_phy_reset (struct ata_port *ap); static int pdc_port_start(struct ata_port *ap); static void pdc_port_stop(struct ata_port *ap); static void pdc_phy_reset(struct ata_port *ap); static void pdc_fill_sg(struct ata_queued_cmd *qc); -static void pdc20621_fill_sg(struct ata_queued_cmd *qc); static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf); static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf); -static void pdc20621_host_stop(struct ata_host_set *host_set); static inline void pdc_dma_complete (struct ata_port *ap, struct ata_queued_cmd *qc, int have_err); -static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe); -static int pdc20621_detect_dimm(struct ata_probe_ent *pe); -static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, - u32 device, u32 subaddr, u32 *pdata); -static int pdc20621_prog_dimm0(struct ata_probe_ent *pe); -static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe); -#ifdef ATA_VERBOSE_DEBUG -static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, - void *psource, u32 offset, u32 size); -#endif -static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, - void *psource, u32 offset, u32 size); - static Scsi_Host_Template pdc_sata_sht = { .module = THIS_MODULE, @@ -222,22 +117,6 @@ static struct ata_port_operations pdc_sa .port_stop = pdc_port_stop, }; -static struct ata_port_operations pdc_20621_ops = { - .port_disable = ata_port_disable, - .tf_load = pdc_tf_load_mmio, - .tf_read = ata_tf_read_mmio, - .check_status = ata_check_status_mmio, - .exec_command = pdc_exec_command_mmio, - .phy_reset = pdc_20621_phy_reset, - .bmdma_start = pdc20621_dma_start, - .fill_sg = pdc20621_fill_sg, - .eng_timeout = pdc_eng_timeout, - .irq_handler = pdc20621_interrupt, - .port_start = pdc_port_start, - .port_stop = pdc_port_stop, - .host_stop = pdc20621_host_stop, -}; - static struct ata_port_info pdc_port_info[] = { /* board_2037x */ { @@ -258,18 +137,6 @@ static struct ata_port_info pdc_port_inf .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &pdc_sata_ops, }, - - /* board_20621 */ - { - .sht = &pdc_sata_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_SRST | ATA_FLAG_MMIO | - PDC_FLAG_20621, - .pio_mask = 0x03, /* pio3-4 */ - .udma_mask = 0x7f, /* udma0-6 ; FIXME */ - .port_ops = &pdc_20621_ops, - }, - }; static struct pci_device_id pdc_sata_pci_tbl[] = { @@ -285,8 +152,6 @@ static struct pci_device_id pdc_sata_pci board_20319 }, { PCI_VENDOR_ID_PROMISE, 0x3319, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_20319 }, - { PCI_VENDOR_ID_PROMISE, 0x6622, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - board_20621 }, { } /* terminate list */ }; @@ -299,15 +164,6 @@ static struct pci_driver pdc_sata_pci_dr }; -static void pdc20621_host_stop(struct ata_host_set *host_set) -{ - struct pdc_host_priv *hpriv = host_set->private_data; - void *dimm_mmio = hpriv->dimm_mmio; - - iounmap(dimm_mmio); - kfree(hpriv); -} - static int pdc_port_start(struct ata_port *ap) { struct pci_dev *pdev = ap->host_set->pdev; @@ -355,14 +211,6 @@ static void pdc_port_stop(struct ata_por } -static void pdc_20621_phy_reset (struct ata_port *ap) -{ - VPRINTK("ENTER\n"); - ap->cbl = ATA_CBL_SATA; - ata_port_probe(ap); - ata_bus_reset(ap); -} - static void pdc_reset_port(struct ata_port *ap) { void *mmio = (void *) ap->ioaddr.cmd_addr + PDC_CTLSTAT; @@ -407,587 +255,6 @@ static void pdc_sata_scr_write (struct a writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4)); } -enum pdc_packet_bits { - PDC_PKT_READ = (1 << 2), - PDC_PKT_NODATA = (1 << 3), - - PDC_PKT_SIZEMASK = (1 << 7) | (1 << 6) | (1 << 5), - PDC_PKT_CLEAR_BSY = (1 << 4), - PDC_PKT_WAIT_DRDY = (1 << 3) | (1 << 4), - PDC_LAST_REG = (1 << 3), - - PDC_REG_DEVCTL = (1 << 3) | (1 << 2) | (1 << 1), -}; - -static inline unsigned int pdc_pkt_header(struct ata_taskfile *tf, - dma_addr_t sg_table, - unsigned int devno, u8 *buf) -{ - u8 dev_reg; - u32 *buf32 = (u32 *) buf; - - /* set control bits (byte 0), zero delay seq id (byte 3), - * and seq id (byte 2) - */ - switch (tf->protocol) { - case ATA_PROT_DMA: - if (!(tf->flags & ATA_TFLAG_WRITE)) - buf32[0] = cpu_to_le32(PDC_PKT_READ); - else - buf32[0] = 0; - break; - - case ATA_PROT_NODATA: - buf32[0] = cpu_to_le32(PDC_PKT_NODATA); - break; - - default: - BUG(); - break; - } - - buf32[1] = cpu_to_le32(sg_table); /* S/G table addr */ - buf32[2] = 0; /* no next-packet */ - - if (devno == 0) - dev_reg = ATA_DEVICE_OBS; - else - dev_reg = ATA_DEVICE_OBS | ATA_DEV1; - - /* select device */ - buf[12] = (1 << 5) | PDC_PKT_CLEAR_BSY | ATA_REG_DEVICE; - buf[13] = dev_reg; - - /* device control register */ - buf[14] = (1 << 5) | PDC_REG_DEVCTL; - buf[15] = tf->ctl; - - return 16; /* offset of next byte */ -} - -static inline unsigned int pdc_pkt_footer(struct ata_taskfile *tf, u8 *buf, - unsigned int i) -{ - if (tf->flags & ATA_TFLAG_DEVICE) { - buf[i++] = (1 << 5) | ATA_REG_DEVICE; - buf[i++] = tf->device; - } - - /* and finally the command itself; also includes end-of-pkt marker */ - buf[i++] = (1 << 5) | PDC_LAST_REG | ATA_REG_CMD; - buf[i++] = tf->command; - - return i; -} - -static inline unsigned int pdc_prep_lba28(struct ata_taskfile *tf, u8 *buf, unsigned int i) -{ - /* the "(1 << 5)" should be read "(count << 5)" */ - - /* ATA command block registers */ - buf[i++] = (1 << 5) | ATA_REG_FEATURE; - buf[i++] = tf->feature; - - buf[i++] = (1 << 5) | ATA_REG_NSECT; - buf[i++] = tf->nsect; - - buf[i++] = (1 << 5) | ATA_REG_LBAL; - buf[i++] = tf->lbal; - - buf[i++] = (1 << 5) | ATA_REG_LBAM; - buf[i++] = tf->lbam; - - buf[i++] = (1 << 5) | ATA_REG_LBAH; - buf[i++] = tf->lbah; - - return i; -} - -static inline unsigned int pdc_prep_lba48(struct ata_taskfile *tf, u8 *buf, unsigned int i) -{ - /* the "(2 << 5)" should be read "(count << 5)" */ - - /* ATA command block registers */ - buf[i++] = (2 << 5) | ATA_REG_FEATURE; - buf[i++] = tf->hob_feature; - buf[i++] = tf->feature; - - buf[i++] = (2 << 5) | ATA_REG_NSECT; - buf[i++] = tf->hob_nsect; - buf[i++] = tf->nsect; - - buf[i++] = (2 << 5) | ATA_REG_LBAL; - buf[i++] = tf->hob_lbal; - buf[i++] = tf->lbal; - - buf[i++] = (2 << 5) | ATA_REG_LBAM; - buf[i++] = tf->hob_lbam; - buf[i++] = tf->lbam; - - buf[i++] = (2 << 5) | ATA_REG_LBAH; - buf[i++] = tf->hob_lbah; - buf[i++] = tf->lbah; - - return i; -} - -static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf, - unsigned int portno, - unsigned int total_len) -{ - u32 addr; - unsigned int dw = PDC_DIMM_APKT_PRD >> 2; - u32 *buf32 = (u32 *) buf; - - /* output ATA packet S/G table */ - addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA + - (PDC_DIMM_DATA_STEP * portno); - VPRINTK("ATA sg addr 0x%x, %d\n", addr, addr); - buf32[dw] = cpu_to_le32(addr); - buf32[dw + 1] = cpu_to_le32(total_len | ATA_PRD_EOT); - - VPRINTK("ATA PSG @ %x == (0x%x, 0x%x)\n", - PDC_20621_DIMM_BASE + - (PDC_DIMM_WINDOW_STEP * portno) + - PDC_DIMM_APKT_PRD, - buf32[dw], buf32[dw + 1]); -} - -static inline void pdc20621_host_sg(struct ata_taskfile *tf, u8 *buf, - unsigned int portno, - unsigned int total_len) -{ - u32 addr; - unsigned int dw = PDC_DIMM_HPKT_PRD >> 2; - u32 *buf32 = (u32 *) buf; - - /* output Host DMA packet S/G table */ - addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA + - (PDC_DIMM_DATA_STEP * portno); - - buf32[dw] = cpu_to_le32(addr); - buf32[dw + 1] = cpu_to_le32(total_len | ATA_PRD_EOT); - - VPRINTK("HOST PSG @ %x == (0x%x, 0x%x)\n", - PDC_20621_DIMM_BASE + - (PDC_DIMM_WINDOW_STEP * portno) + - PDC_DIMM_HPKT_PRD, - buf32[dw], buf32[dw + 1]); -} - -static inline unsigned int pdc20621_ata_pkt(struct ata_taskfile *tf, - unsigned int devno, u8 *buf, - unsigned int portno) -{ - unsigned int i, dw; - u32 *buf32 = (u32 *) buf; - u8 dev_reg; - - unsigned int dimm_sg = PDC_20621_DIMM_BASE + - (PDC_DIMM_WINDOW_STEP * portno) + - PDC_DIMM_APKT_PRD; - VPRINTK("ENTER, dimm_sg == 0x%x, %d\n", dimm_sg, dimm_sg); - - i = PDC_DIMM_ATA_PKT; - - /* - * Set up ATA packet - */ - if ((tf->protocol == ATA_PROT_DMA) && (!(tf->flags & ATA_TFLAG_WRITE))) - buf[i++] = PDC_PKT_READ; - else if (tf->protocol == ATA_PROT_NODATA) - buf[i++] = PDC_PKT_NODATA; - else - buf[i++] = 0; - buf[i++] = 0; /* reserved */ - buf[i++] = portno + 1; /* seq. id */ - buf[i++] = 0xff; /* delay seq. id */ - - /* dimm dma S/G, and next-pkt */ - dw = i >> 2; - buf32[dw] = cpu_to_le32(dimm_sg); - buf32[dw + 1] = 0; - i += 8; - - if (devno == 0) - dev_reg = ATA_DEVICE_OBS; - else - dev_reg = ATA_DEVICE_OBS | ATA_DEV1; - - /* select device */ - buf[i++] = (1 << 5) | PDC_PKT_CLEAR_BSY | ATA_REG_DEVICE; - buf[i++] = dev_reg; - - /* device control register */ - buf[i++] = (1 << 5) | PDC_REG_DEVCTL; - buf[i++] = tf->ctl; - - return i; -} - -static inline void pdc20621_host_pkt(struct ata_taskfile *tf, u8 *buf, - unsigned int portno) -{ - unsigned int dw; - u32 tmp, *buf32 = (u32 *) buf; - - unsigned int host_sg = PDC_20621_DIMM_BASE + - (PDC_DIMM_WINDOW_STEP * portno) + - PDC_DIMM_HOST_PRD; - unsigned int dimm_sg = PDC_20621_DIMM_BASE + - (PDC_DIMM_WINDOW_STEP * portno) + - PDC_DIMM_HPKT_PRD; - VPRINTK("ENTER, dimm_sg == 0x%x, %d\n", dimm_sg, dimm_sg); - VPRINTK("host_sg == 0x%x, %d\n", host_sg, host_sg); - - dw = PDC_DIMM_HOST_PKT >> 2; - - /* - * Set up Host DMA packet - */ - if ((tf->protocol == ATA_PROT_DMA) && (!(tf->flags & ATA_TFLAG_WRITE))) - tmp = PDC_PKT_READ; - else - tmp = 0; - tmp |= ((portno + 1 + 4) << 16); /* seq. id */ - tmp |= (0xff << 24); /* delay seq. id */ - buf32[dw + 0] = cpu_to_le32(tmp); - buf32[dw + 1] = cpu_to_le32(host_sg); - buf32[dw + 2] = cpu_to_le32(dimm_sg); - buf32[dw + 3] = 0; - - VPRINTK("HOST PKT @ %x == (0x%x 0x%x 0x%x 0x%x)\n", - PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * portno) + - PDC_DIMM_HOST_PKT, - buf32[dw + 0], - buf32[dw + 1], - buf32[dw + 2], - buf32[dw + 3]); -} - -static void pdc20621_fill_sg(struct ata_queued_cmd *qc) -{ - struct scatterlist *sg = qc->sg; - struct ata_port *ap = qc->ap; - struct pdc_port_priv *pp = ap->private_data; - void *mmio = ap->host_set->mmio_base; - struct pdc_host_priv *hpriv = ap->host_set->private_data; - void *dimm_mmio = hpriv->dimm_mmio; - unsigned int portno = ap->port_no; - unsigned int i, last, idx, total_len = 0, sgt_len; - u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ]; - - VPRINTK("ata%u: ENTER\n", ap->id); - - /* hard-code chip #0 */ - mmio += PDC_CHIP0_OFS; - - /* - * Build S/G table - */ - last = qc->n_elem; - idx = 0; - for (i = 0; i < last; i++) { - buf[idx++] = cpu_to_le32(sg_dma_address(&sg[i])); - buf[idx++] = cpu_to_le32(sg_dma_len(&sg[i])); - total_len += sg[i].length; - } - buf[idx - 1] |= cpu_to_le32(ATA_PRD_EOT); - sgt_len = idx * 4; - - /* - * Build ATA, host DMA packets - */ - pdc20621_host_sg(&qc->tf, &pp->dimm_buf[0], portno, total_len); - pdc20621_host_pkt(&qc->tf, &pp->dimm_buf[0], portno); - - pdc20621_ata_sg(&qc->tf, &pp->dimm_buf[0], portno, total_len); - i = pdc20621_ata_pkt(&qc->tf, qc->dev->devno, &pp->dimm_buf[0], portno); - - if (qc->tf.flags & ATA_TFLAG_LBA48) - i = pdc_prep_lba48(&qc->tf, &pp->dimm_buf[0], i); - else - i = pdc_prep_lba28(&qc->tf, &pp->dimm_buf[0], i); - - pdc_pkt_footer(&qc->tf, &pp->dimm_buf[0], i); - - /* copy three S/G tables and two packets to DIMM MMIO window */ - memcpy_toio(dimm_mmio + (portno * PDC_DIMM_WINDOW_STEP), - &pp->dimm_buf, PDC_DIMM_HEADER_SZ); - memcpy_toio(dimm_mmio + (portno * PDC_DIMM_WINDOW_STEP) + - PDC_DIMM_HOST_PRD, - &pp->dimm_buf[PDC_DIMM_HEADER_SZ], sgt_len); - - /* force host FIFO dump */ - writel(0x00000001, mmio + PDC_20621_GENERAL_CTL); - - readl(dimm_mmio); /* MMIO PCI posting flush */ - - VPRINTK("ata pkt buf ofs %u, prd size %u, mmio copied\n", i, sgt_len); -} - -static void __pdc20621_push_hdma(struct ata_queued_cmd *qc, - unsigned int seq, - u32 pkt_ofs) -{ - struct ata_port *ap = qc->ap; - struct ata_host_set *host_set = ap->host_set; - void *mmio = host_set->mmio_base; - - /* hard-code chip #0 */ - mmio += PDC_CHIP0_OFS; - - writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4)); - readl(mmio + PDC_20621_SEQCTL + (seq * 4)); /* flush */ - - writel(pkt_ofs, mmio + PDC_HDMA_PKT_SUBMIT); - readl(mmio + PDC_HDMA_PKT_SUBMIT); /* flush */ -} - -static void pdc20621_push_hdma(struct ata_queued_cmd *qc, - unsigned int seq, - u32 pkt_ofs) -{ - struct ata_port *ap = qc->ap; - struct pdc_host_priv *pp = ap->host_set->private_data; - unsigned int idx = pp->hdma_prod & PDC_HDMA_Q_MASK; - - if (!pp->doing_hdma) { - __pdc20621_push_hdma(qc, seq, pkt_ofs); - pp->doing_hdma = 1; - return; - } - - pp->hdma[idx].qc = qc; - pp->hdma[idx].seq = seq; - pp->hdma[idx].pkt_ofs = pkt_ofs; - pp->hdma_prod++; -} - -static void pdc20621_pop_hdma(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct pdc_host_priv *pp = ap->host_set->private_data; - unsigned int idx = pp->hdma_cons & PDC_HDMA_Q_MASK; - - /* if nothing on queue, we're done */ - if (pp->hdma_prod == pp->hdma_cons) { - pp->doing_hdma = 0; - return; - } - - __pdc20621_push_hdma(pp->hdma[idx].qc, pp->hdma[idx].seq, - pp->hdma[idx].pkt_ofs); - pp->hdma_cons++; -} - -#ifdef ATA_VERBOSE_DEBUG -static void pdc20621_dump_hdma(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - unsigned int port_no = ap->port_no; - struct pdc_host_priv *hpriv = ap->host_set->private_data; - void *dimm_mmio = hpriv->dimm_mmio; - - dimm_mmio += (port_no * PDC_DIMM_WINDOW_STEP); - dimm_mmio += PDC_DIMM_HOST_PKT; - - printk(KERN_ERR "HDMA[0] == 0x%08X\n", readl(dimm_mmio)); - printk(KERN_ERR "HDMA[1] == 0x%08X\n", readl(dimm_mmio + 4)); - printk(KERN_ERR "HDMA[2] == 0x%08X\n", readl(dimm_mmio + 8)); - printk(KERN_ERR "HDMA[3] == 0x%08X\n", readl(dimm_mmio + 12)); -} -#else -static inline void pdc20621_dump_hdma(struct ata_queued_cmd *qc) { } -#endif /* ATA_VERBOSE_DEBUG */ - -static void pdc20621_dma_start(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct ata_host_set *host_set = ap->host_set; - unsigned int port_no = ap->port_no; - void *mmio = host_set->mmio_base; - unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); - u8 seq = (u8) (port_no + 1); - unsigned int doing_hdma = 0, port_ofs; - - /* hard-code chip #0 */ - mmio += PDC_CHIP0_OFS; - - VPRINTK("ata%u: ENTER\n", ap->id); - - port_ofs = PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * port_no); - - /* if writing, we (1) DMA to DIMM, then (2) do ATA command */ - if (rw) { - doing_hdma = 1; - seq += 4; - } - - wmb(); /* flush PRD, pkt writes */ - - if (doing_hdma) { - pdc20621_dump_hdma(qc); - pdc20621_push_hdma(qc, seq, port_ofs + PDC_DIMM_HOST_PKT); - VPRINTK("queued ofs 0x%x (%u), seq %u\n", - port_ofs + PDC_DIMM_HOST_PKT, - port_ofs + PDC_DIMM_HOST_PKT, - seq); - } else { - writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4)); - readl(mmio + PDC_20621_SEQCTL + (seq * 4)); /* flush */ - - writel(port_ofs + PDC_DIMM_ATA_PKT, - (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); - readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); - VPRINTK("submitted ofs 0x%x (%u), seq %u\n", - port_ofs + PDC_DIMM_ATA_PKT, - port_ofs + PDC_DIMM_ATA_PKT, - seq); - } -} - -static inline unsigned int pdc20621_host_intr( struct ata_port *ap, - struct ata_queued_cmd *qc, - unsigned int doing_hdma, - void *mmio) -{ - unsigned int port_no = ap->port_no; - unsigned int port_ofs = - PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * port_no); - u8 status; - unsigned int handled = 0; - - VPRINTK("ENTER\n"); - - if ((qc->tf.protocol == ATA_PROT_DMA) && /* read */ - (!(qc->tf.flags & ATA_TFLAG_WRITE))) { - - /* step two - DMA from DIMM to host */ - if (doing_hdma) { - VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id, - readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT)); - pdc_dma_complete(ap, qc, 0); - pdc20621_pop_hdma(qc); - } - - /* step one - exec ATA command */ - else { - u8 seq = (u8) (port_no + 1 + 4); - VPRINTK("ata%u: read ata, 0x%x 0x%x\n", ap->id, - readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT)); - - /* submit hdma pkt */ - pdc20621_dump_hdma(qc); - pdc20621_push_hdma(qc, seq, - port_ofs + PDC_DIMM_HOST_PKT); - } - handled = 1; - - } else if (qc->tf.protocol == ATA_PROT_DMA) { /* write */ - - /* step one - DMA from host to DIMM */ - if (doing_hdma) { - u8 seq = (u8) (port_no + 1); - VPRINTK("ata%u: write hdma, 0x%x 0x%x\n", ap->id, - readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT)); - - /* submit ata pkt */ - writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4)); - readl(mmio + PDC_20621_SEQCTL + (seq * 4)); - writel(port_ofs + PDC_DIMM_ATA_PKT, - (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); - readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); - } - - /* step two - execute ATA command */ - else { - VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id, - readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT)); - pdc_dma_complete(ap, qc, 0); - pdc20621_pop_hdma(qc); - } - handled = 1; - - /* command completion, but no data xfer */ - } else if (qc->tf.protocol == ATA_PROT_NODATA) { - - status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); - DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status); - ata_qc_complete(qc, status, 0); - handled = 1; - - } else { - ap->stats.idle_irq++; - } - - return handled; -} - -static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_regs *regs) -{ - struct ata_host_set *host_set = dev_instance; - struct ata_port *ap; - u32 mask = 0; - unsigned int i, tmp, port_no; - unsigned int handled = 0; - void *mmio_base; - - VPRINTK("ENTER\n"); - - if (!host_set || !host_set->mmio_base) { - VPRINTK("QUICK EXIT\n"); - return IRQ_NONE; - } - - mmio_base = host_set->mmio_base; - - /* reading should also clear interrupts */ - mmio_base += PDC_CHIP0_OFS; - mask = readl(mmio_base + PDC_20621_SEQMASK); - VPRINTK("mask == 0x%x\n", mask); - - if (mask == 0xffffffff) { - VPRINTK("QUICK EXIT 2\n"); - return IRQ_NONE; - } - mask &= 0xffff; /* only 16 tags possible */ - if (!mask) { - VPRINTK("QUICK EXIT 3\n"); - return IRQ_NONE; - } - - spin_lock(&host_set->lock); - - for (i = 1; i < 9; i++) { - port_no = i - 1; - if (port_no > 3) - port_no -= 4; - if (port_no >= host_set->n_ports) - ap = NULL; - else - ap = host_set->ports[port_no]; - tmp = mask & (1 << i); - VPRINTK("seq %u, port_no %u, ap %p, tmp %x\n", i, port_no, ap, tmp); - if (tmp && ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) { - struct ata_queued_cmd *qc; - - qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && ((qc->flags & ATA_QCFLAG_POLL) == 0)) - handled += pdc20621_host_intr(ap, qc, (i > 4), - mmio_base); - } - } - - spin_unlock(&host_set->lock); - - VPRINTK("mask == 0x%x\n", mask); - - VPRINTK("EXIT\n"); - - return IRQ_RETVAL(handled); -} - static void pdc_fill_sg(struct ata_queued_cmd *qc) { struct pdc_port_priv *pp = qc->ap->private_data; @@ -1210,456 +477,11 @@ static void pdc_sata_setup_port(struct a } -#ifdef ATA_VERBOSE_DEBUG -static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource, - u32 offset, u32 size) -{ - u32 window_size; - u16 idx; - u8 page_mask; - long dist; - void *mmio = pe->mmio_base; - struct pdc_host_priv *hpriv = pe->private_data; - void *dimm_mmio = hpriv->dimm_mmio; - - /* hard-code chip #0 */ - mmio += PDC_CHIP0_OFS; - - page_mask = 0x00; - window_size = 0x2000 * 4; /* 32K byte uchar size */ - idx = (u16) (offset / window_size); - - writel(0x01, mmio + PDC_GENERAL_CTLR); - readl(mmio + PDC_GENERAL_CTLR); - writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); - readl(mmio + PDC_DIMM_WINDOW_CTLR); - - offset -= (idx * window_size); - idx++; - dist = ((long) (window_size - (offset + size))) >= 0 ? size : - (long) (window_size - offset); - memcpy_fromio((char *) psource, (char *) (dimm_mmio + offset / 4), - dist); - - psource += dist; - size -= dist; - for (; (long) size >= (long) window_size ;) { - writel(0x01, mmio + PDC_GENERAL_CTLR); - readl(mmio + PDC_GENERAL_CTLR); - writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); - readl(mmio + PDC_DIMM_WINDOW_CTLR); - memcpy_fromio((char *) psource, (char *) (dimm_mmio), - window_size / 4); - psource += window_size; - size -= window_size; - idx ++; - } - - if (size) { - writel(0x01, mmio + PDC_GENERAL_CTLR); - readl(mmio + PDC_GENERAL_CTLR); - writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); - readl(mmio + PDC_DIMM_WINDOW_CTLR); - memcpy_fromio((char *) psource, (char *) (dimm_mmio), - size / 4); - } -} -#endif - - -static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource, - u32 offset, u32 size) -{ - u32 window_size; - u16 idx; - u8 page_mask; - long dist; - void *mmio = pe->mmio_base; - struct pdc_host_priv *hpriv = pe->private_data; - void *dimm_mmio = hpriv->dimm_mmio; - - /* hard-code chip #0 */ - mmio += PDC_CHIP0_OFS; - - page_mask = 0x00; - window_size = 0x2000 * 4; /* 32K byte uchar size */ - idx = (u16) (offset / window_size); - - writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); - readl(mmio + PDC_DIMM_WINDOW_CTLR); - offset -= (idx * window_size); - idx++; - dist = ((long) (window_size - (offset + size))) >= 0 ? size : - (long) (window_size - offset); - memcpy_toio((char *) (dimm_mmio + offset / 4), (char *) psource, dist); - writel(0x01, mmio + PDC_GENERAL_CTLR); - readl(mmio + PDC_GENERAL_CTLR); - - psource += dist; - size -= dist; - for (; (long) size >= (long) window_size ;) { - writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); - readl(mmio + PDC_DIMM_WINDOW_CTLR); - memcpy_toio((char *) (dimm_mmio), (char *) psource, - window_size / 4); - writel(0x01, mmio + PDC_GENERAL_CTLR); - readl(mmio + PDC_GENERAL_CTLR); - psource += window_size; - size -= window_size; - idx ++; - } - - if (size) { - writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); - readl(mmio + PDC_DIMM_WINDOW_CTLR); - memcpy_toio((char *) (dimm_mmio), (char *) psource, size / 4); - writel(0x01, mmio + PDC_GENERAL_CTLR); - readl(mmio + PDC_GENERAL_CTLR); - } -} - - -static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device, - u32 subaddr, u32 *pdata) -{ - void *mmio = pe->mmio_base; - u32 i2creg = 0; - u32 status; - u32 count =0; - - /* hard-code chip #0 */ - mmio += PDC_CHIP0_OFS; - - i2creg |= device << 24; - i2creg |= subaddr << 16; - - /* Set the device and subaddress */ - writel(i2creg, mmio + PDC_I2C_ADDR_DATA_OFFSET); - readl(mmio + PDC_I2C_ADDR_DATA_OFFSET); - - /* Write Control to perform read operation, mask int */ - writel(PDC_I2C_READ | PDC_I2C_START | PDC_I2C_MASK_INT, - mmio + PDC_I2C_CONTROL_OFFSET); - - for (count = 0; count <= 1000; count ++) { - status = readl(mmio + PDC_I2C_CONTROL_OFFSET); - if (status & PDC_I2C_COMPLETE) { - status = readl(mmio + PDC_I2C_ADDR_DATA_OFFSET); - break; - } else if (count == 1000) - return 0; - } - - *pdata = (status >> 8) & 0x000000ff; - return 1; -} - - -static int pdc20621_detect_dimm(struct ata_probe_ent *pe) -{ - u32 data=0 ; - if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, - PDC_DIMM_SPD_SYSTEM_FREQ, &data)) { - if (data == 100) - return 100; - } else - return 0; - - if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 9, &data)) { - if(data <= 0x75) - return 133; - } else - return 0; - - return 0; -} - - -static int pdc20621_prog_dimm0(struct ata_probe_ent *pe) -{ - u32 spd0[50]; - u32 data = 0; - int size, i; - u8 bdimmsize; - void *mmio = pe->mmio_base; - static const struct { - unsigned int reg; - unsigned int ofs; - } pdc_i2c_read_data [] = { - { PDC_DIMM_SPD_TYPE, 11 }, - { PDC_DIMM_SPD_FRESH_RATE, 12 }, - { PDC_DIMM_SPD_COLUMN_NUM, 4 }, - { PDC_DIMM_SPD_ATTRIBUTE, 21 }, - { PDC_DIMM_SPD_ROW_NUM, 3 }, - { PDC_DIMM_SPD_BANK_NUM, 17 }, - { PDC_DIMM_SPD_MODULE_ROW, 5 }, - { PDC_DIMM_SPD_ROW_PRE_CHARGE, 27 }, - { PDC_DIMM_SPD_ROW_ACTIVE_DELAY, 28 }, - { PDC_DIMM_SPD_RAS_CAS_DELAY, 29 }, - { PDC_DIMM_SPD_ACTIVE_PRECHARGE, 30 }, - { PDC_DIMM_SPD_CAS_LATENCY, 18 }, - }; - - /* hard-code chip #0 */ - mmio += PDC_CHIP0_OFS; - - for(i=0; i spd0[28]) - ? spd0[29] : spd0[28]) + 9) / 10) - 1) << 10; - data |= ((spd0[30] - spd0[29] + 9) / 10 - 2) << 12; - - if (spd0[18] & 0x08) - data |= ((0x03) << 14); - else if (spd0[18] & 0x04) - data |= ((0x02) << 14); - else if (spd0[18] & 0x01) - data |= ((0x01) << 14); - else - data |= (0 << 14); - - /* - Calculate the size of bDIMMSize (power of 2) and - merge the DIMM size by program start/end address. - */ - - bdimmsize = spd0[4] + (spd0[5] / 2) + spd0[3] + (spd0[17] / 2) + 3; - size = (1 << bdimmsize) >> 20; /* size = xxx(MB) */ - data |= (((size / 16) - 1) << 16); - data |= (0 << 23); - data |= 8; - writel(data, mmio + PDC_DIMM0_CONTROL_OFFSET); - readl(mmio + PDC_DIMM0_CONTROL_OFFSET); - return size; -} - - -static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe) -{ - u32 data, spd0; - int error, i; - void *mmio = pe->mmio_base; - - /* hard-code chip #0 */ - mmio += PDC_CHIP0_OFS; - - /* - Set To Default : DIMM Module Global Control Register (0x022259F1) - DIMM Arbitration Disable (bit 20) - DIMM Data/Control Output Driving Selection (bit12 - bit15) - Refresh Enable (bit 17) - */ - - data = 0x022259F1; - writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET); - readl(mmio + PDC_SDRAM_CONTROL_OFFSET); - - /* Turn on for ECC */ - pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, - PDC_DIMM_SPD_TYPE, &spd0); - if (spd0 == 0x02) { - data |= (0x01 << 16); - writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET); - readl(mmio + PDC_SDRAM_CONTROL_OFFSET); - printk(KERN_ERR "Local DIMM ECC Enabled\n"); - } - - /* DIMM Initialization Select/Enable (bit 18/19) */ - data &= (~(1<<18)); - data |= (1<<19); - writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET); - - error = 1; - for (i = 1; i <= 10; i++) { /* polling ~5 secs */ - data = readl(mmio + PDC_SDRAM_CONTROL_OFFSET); - if (!(data & (1<<19))) { - error = 0; - break; - } - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout((i * 100) * HZ / 1000); - } - return error; -} - - -static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe) -{ - int speed, size, length; - u32 addr,spd0,pci_status; - u32 tmp=0; - u32 time_period=0; - u32 tcount=0; - u32 ticks=0; - u32 clock=0; - u32 fparam=0; - void *mmio = pe->mmio_base; - - /* hard-code chip #0 */ - mmio += PDC_CHIP0_OFS; - - /* Initialize PLL based upon PCI Bus Frequency */ - - /* Initialize Time Period Register */ - writel(0xffffffff, mmio + PDC_TIME_PERIOD); - time_period = readl(mmio + PDC_TIME_PERIOD); - VPRINTK("Time Period Register (0x40): 0x%x\n", time_period); - - /* Enable timer */ - writel(0x00001a0, mmio + PDC_TIME_CONTROL); - readl(mmio + PDC_TIME_CONTROL); - - /* Wait 3 seconds */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(3 * HZ); - - /* - When timer is enabled, counter is decreased every internal - clock cycle. - */ - - tcount = readl(mmio + PDC_TIME_COUNTER); - VPRINTK("Time Counter Register (0x44): 0x%x\n", tcount); - - /* - If SX4 is on PCI-X bus, after 3 seconds, the timer counter - register should be >= (0xffffffff - 3x10^8). - */ - if(tcount >= PCI_X_TCOUNT) { - ticks = (time_period - tcount); - VPRINTK("Num counters 0x%x (%d)\n", ticks, ticks); - - clock = (ticks / 300000); - VPRINTK("10 * Internal clk = 0x%x (%d)\n", clock, clock); - - clock = (clock * 33); - VPRINTK("10 * Internal clk * 33 = 0x%x (%d)\n", clock, clock); - - /* PLL F Param (bit 22:16) */ - fparam = (1400000 / clock) - 2; - VPRINTK("PLL F Param: 0x%x (%d)\n", fparam, fparam); - - /* OD param = 0x2 (bit 31:30), R param = 0x5 (bit 29:25) */ - pci_status = (0x8a001824 | (fparam << 16)); - } else - pci_status = PCI_PLL_INIT; - - /* Initialize PLL. */ - VPRINTK("pci_status: 0x%x\n", pci_status); - writel(pci_status, mmio + PDC_CTL_STATUS); - readl(mmio + PDC_CTL_STATUS); - - /* - Read SPD of DIMM by I2C interface, - and program the DIMM Module Controller. - */ - if (!(speed = pdc20621_detect_dimm(pe))) { - printk(KERN_ERR "Detect Local DIMM Fail\n"); - return 1; /* DIMM error */ - } - VPRINTK("Local DIMM Speed = %d\n", speed); - - /* Programming DIMM0 Module Control Register (index_CID0:80h) */ - size = pdc20621_prog_dimm0(pe); - VPRINTK("Local DIMM Size = %dMB\n",size); - - /* Programming DIMM Module Global Control Register (index_CID0:88h) */ - if (pdc20621_prog_dimm_global(pe)) { - printk(KERN_ERR "Programming DIMM Module Global Control Register Fail\n"); - return 1; - } - -#ifdef ATA_VERBOSE_DEBUG - { - u8 test_parttern1[40] = {0x55,0xAA,'P','r','o','m','i','s','e',' ', - 'N','o','t',' ','Y','e','t',' ','D','e','f','i','n','e','d',' ', - '1','.','1','0', - '9','8','0','3','1','6','1','2',0,0}; - u8 test_parttern2[40] = {0}; - - pdc20621_put_to_dimm(pe, (void *) test_parttern2, 0x10040, 40); - pdc20621_put_to_dimm(pe, (void *) test_parttern2, 0x40, 40); - - pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x10040, 40); - pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40); - printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], - test_parttern2[1], &(test_parttern2[2])); - pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x10040, - 40); - printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], - test_parttern2[1], &(test_parttern2[2])); - - pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x40, 40); - pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40); - printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], - test_parttern2[1], &(test_parttern2[2])); - } -#endif - - /* ECC initiliazation. */ - - pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, - PDC_DIMM_SPD_TYPE, &spd0); - if (spd0 == 0x02) { - VPRINTK("Start ECC initialization\n"); - addr = 0; - length = size * 1024 * 1024; - while (addr < length) { - pdc20621_put_to_dimm(pe, (void *) &tmp, addr, - sizeof(u32)); - addr += sizeof(u32); - } - VPRINTK("Finish ECC initialization\n"); - } - return 0; -} - - -static void pdc_20621_init(struct ata_probe_ent *pe) -{ - u32 tmp; - void *mmio = pe->mmio_base; - - /* hard-code chip #0 */ - mmio += PDC_CHIP0_OFS; - - /* - * Select page 0x40 for our 32k DIMM window - */ - tmp = readl(mmio + PDC_20621_DIMM_WINDOW) & 0xffff0000; - tmp |= PDC_PAGE_WINDOW; /* page 40h; arbitrarily selected */ - writel(tmp, mmio + PDC_20621_DIMM_WINDOW); - - /* - * Reset Host DMA - */ - tmp = readl(mmio + PDC_HDMA_CTLSTAT); - tmp |= PDC_RESET; - writel(tmp, mmio + PDC_HDMA_CTLSTAT); - readl(mmio + PDC_HDMA_CTLSTAT); /* flush */ - - udelay(10); - - tmp = readl(mmio + PDC_HDMA_CTLSTAT); - tmp &= ~PDC_RESET; - writel(tmp, mmio + PDC_HDMA_CTLSTAT); - readl(mmio + PDC_HDMA_CTLSTAT); /* flush */ -} - static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe) { void *mmio = pe->mmio_base; u32 tmp; - if (chip_id == board_20621) - BUG(); - /* * Except for the hotplug stuff, this is voodoo from the * Promise driver. Label this entire section @@ -1687,7 +509,7 @@ static void pdc_host_init(unsigned int c readl(mmio + PDC_TBG_MODE); /* flush */ set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(msecs_to_jiffies(10)); + schedule_timeout(msecs_to_jiffies(10) + 1); /* adjust slew rate control register. */ tmp = readl(mmio + PDC_SLEW_CTL); @@ -1701,10 +523,8 @@ static int pdc_sata_init_one (struct pci static int printed_version; struct ata_probe_ent *probe_ent = NULL; unsigned long base; - void *mmio_base, *dimm_mmio = NULL; - struct pdc_host_priv *hpriv = NULL; + void *mmio_base; unsigned int board_idx = (unsigned int) ent->driver_data; - unsigned int have_20621 = (board_idx == board_20621); int rc; if (!printed_version++) @@ -1747,25 +567,6 @@ static int pdc_sata_init_one (struct pci } base = (unsigned long) mmio_base; - if (have_20621) { - hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL); - if (!hpriv) { - rc = -ENOMEM; - goto err_out_iounmap; - } - memset(hpriv, 0, sizeof(*hpriv)); - - dimm_mmio = ioremap(pci_resource_start(pdev, 4), - pci_resource_len(pdev, 4)); - if (!dimm_mmio) { - kfree(hpriv); - rc = -ENOMEM; - goto err_out_iounmap; - } - - hpriv->dimm_mmio = dimm_mmio; - } - probe_ent->sht = pdc_port_info[board_idx].sht; probe_ent->host_flags = pdc_port_info[board_idx].host_flags; probe_ent->pio_mask = pdc_port_info[board_idx].pio_mask; @@ -1776,32 +577,22 @@ static int pdc_sata_init_one (struct pci probe_ent->irq_flags = SA_SHIRQ; probe_ent->mmio_base = mmio_base; - if (have_20621) { - probe_ent->private_data = hpriv; - base += PDC_CHIP0_OFS; - } - pdc_sata_setup_port(&probe_ent->port[0], base + 0x200); pdc_sata_setup_port(&probe_ent->port[1], base + 0x280); - if (!have_20621) { - probe_ent->port[0].scr_addr = base + 0x400; - probe_ent->port[1].scr_addr = base + 0x500; - } + probe_ent->port[0].scr_addr = base + 0x400; + probe_ent->port[1].scr_addr = base + 0x500; /* notice 4-port boards */ switch (board_idx) { case board_20319: - case board_20621: probe_ent->n_ports = 4; pdc_sata_setup_port(&probe_ent->port[2], base + 0x300); pdc_sata_setup_port(&probe_ent->port[3], base + 0x380); - if (!have_20621) { - probe_ent->port[2].scr_addr = base + 0x600; - probe_ent->port[3].scr_addr = base + 0x700; - } + probe_ent->port[2].scr_addr = base + 0x600; + probe_ent->port[3].scr_addr = base + 0x700; break; case board_2037x: probe_ent->n_ports = 2; @@ -1814,15 +605,7 @@ static int pdc_sata_init_one (struct pci pci_set_master(pdev); /* initialize adapter */ - if (have_20621) { - /* initialize local dimm */ - if (pdc20621_dimm_init(probe_ent)) { - rc = -ENOMEM; - goto err_out_iounmap_dimm; - } - pdc_20621_init(probe_ent); - } else - pdc_host_init(board_idx, probe_ent); + pdc_host_init(board_idx, probe_ent); /* FIXME: check ata_device_add return value */ ata_device_add(probe_ent); @@ -1830,11 +613,6 @@ static int pdc_sata_init_one (struct pci return 0; -err_out_iounmap_dimm: /* only get to this label if 20621 */ - kfree(hpriv); - iounmap(dimm_mmio); -err_out_iounmap: - iounmap(mmio_base); err_out_free_ent: kfree(probe_ent); err_out_regions: @@ -1858,7 +636,7 @@ static void __exit pdc_sata_exit(void) MODULE_AUTHOR("Jeff Garzik"); -MODULE_DESCRIPTION("Promise SATA low-level driver"); +MODULE_DESCRIPTION("Promise SATA TX2/TX4 low-level driver"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, pdc_sata_pci_tbl); --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/drivers/scsi/sata_promise.h 2004-05-10 01:19:03.409220776 -0700 @@ -0,0 +1,154 @@ +/* + * sata_promise.h - Promise SATA common definitions and inline funcs + * + * Copyright 2003-2004 Red Hat, Inc. + * + * The contents of this file are subject to the Open + * Software License version 1.1 that can be found at + * http://www.opensource.org/licenses/osl-1.1.txt and is included herein + * by reference. + * + * Alternatively, the contents of this file may be used under the terms + * of the GNU General Public License version 2 (the "GPL") as distributed + * in the kernel source COPYING file, in which case the provisions of + * the GPL are applicable instead of the above. If you wish to allow + * the use of your version of this file only under the terms of the + * GPL and not to allow others to use your version of this file under + * the OSL, indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by the GPL. + * If you do not delete the provisions above, a recipient may use your + * version of this file under either the OSL or the GPL. + * + */ + +#ifndef __SATA_PROMISE_H__ +#define __SATA_PROMISE_H__ + +#include + +enum pdc_packet_bits { + PDC_PKT_READ = (1 << 2), + PDC_PKT_NODATA = (1 << 3), + + PDC_PKT_SIZEMASK = (1 << 7) | (1 << 6) | (1 << 5), + PDC_PKT_CLEAR_BSY = (1 << 4), + PDC_PKT_WAIT_DRDY = (1 << 3) | (1 << 4), + PDC_LAST_REG = (1 << 3), + + PDC_REG_DEVCTL = (1 << 3) | (1 << 2) | (1 << 1), +}; + +static inline unsigned int pdc_pkt_header(struct ata_taskfile *tf, + dma_addr_t sg_table, + unsigned int devno, u8 *buf) +{ + u8 dev_reg; + u32 *buf32 = (u32 *) buf; + + /* set control bits (byte 0), zero delay seq id (byte 3), + * and seq id (byte 2) + */ + switch (tf->protocol) { + case ATA_PROT_DMA: + if (!(tf->flags & ATA_TFLAG_WRITE)) + buf32[0] = cpu_to_le32(PDC_PKT_READ); + else + buf32[0] = 0; + break; + + case ATA_PROT_NODATA: + buf32[0] = cpu_to_le32(PDC_PKT_NODATA); + break; + + default: + BUG(); + break; + } + + buf32[1] = cpu_to_le32(sg_table); /* S/G table addr */ + buf32[2] = 0; /* no next-packet */ + + if (devno == 0) + dev_reg = ATA_DEVICE_OBS; + else + dev_reg = ATA_DEVICE_OBS | ATA_DEV1; + + /* select device */ + buf[12] = (1 << 5) | PDC_PKT_CLEAR_BSY | ATA_REG_DEVICE; + buf[13] = dev_reg; + + /* device control register */ + buf[14] = (1 << 5) | PDC_REG_DEVCTL; + buf[15] = tf->ctl; + + return 16; /* offset of next byte */ +} + +static inline unsigned int pdc_pkt_footer(struct ata_taskfile *tf, u8 *buf, + unsigned int i) +{ + if (tf->flags & ATA_TFLAG_DEVICE) { + buf[i++] = (1 << 5) | ATA_REG_DEVICE; + buf[i++] = tf->device; + } + + /* and finally the command itself; also includes end-of-pkt marker */ + buf[i++] = (1 << 5) | PDC_LAST_REG | ATA_REG_CMD; + buf[i++] = tf->command; + + return i; +} + +static inline unsigned int pdc_prep_lba28(struct ata_taskfile *tf, u8 *buf, unsigned int i) +{ + /* the "(1 << 5)" should be read "(count << 5)" */ + + /* ATA command block registers */ + buf[i++] = (1 << 5) | ATA_REG_FEATURE; + buf[i++] = tf->feature; + + buf[i++] = (1 << 5) | ATA_REG_NSECT; + buf[i++] = tf->nsect; + + buf[i++] = (1 << 5) | ATA_REG_LBAL; + buf[i++] = tf->lbal; + + buf[i++] = (1 << 5) | ATA_REG_LBAM; + buf[i++] = tf->lbam; + + buf[i++] = (1 << 5) | ATA_REG_LBAH; + buf[i++] = tf->lbah; + + return i; +} + +static inline unsigned int pdc_prep_lba48(struct ata_taskfile *tf, u8 *buf, unsigned int i) +{ + /* the "(2 << 5)" should be read "(count << 5)" */ + + /* ATA command block registers */ + buf[i++] = (2 << 5) | ATA_REG_FEATURE; + buf[i++] = tf->hob_feature; + buf[i++] = tf->feature; + + buf[i++] = (2 << 5) | ATA_REG_NSECT; + buf[i++] = tf->hob_nsect; + buf[i++] = tf->nsect; + + buf[i++] = (2 << 5) | ATA_REG_LBAL; + buf[i++] = tf->hob_lbal; + buf[i++] = tf->lbal; + + buf[i++] = (2 << 5) | ATA_REG_LBAM; + buf[i++] = tf->hob_lbam; + buf[i++] = tf->lbam; + + buf[i++] = (2 << 5) | ATA_REG_LBAH; + buf[i++] = tf->hob_lbah; + buf[i++] = tf->lbah; + + return i; +} + + +#endif /* __SATA_PROMISE_H__ */ --- linux-2.6.6/drivers/scsi/sata_sis.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/scsi/sata_sis.c 2004-05-10 01:19:03.409220776 -0700 @@ -56,7 +56,8 @@ static u32 sis_scr_read (struct ata_port static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); static struct pci_device_id sis_pci_tbl[] = { - { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_180, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 }, + { PCI_VENDOR_ID_SI, 0x180, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 }, + { PCI_VENDOR_ID_SI, 0x181, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 }, { } /* terminate list */ }; --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/drivers/scsi/sata_sx4.c 2004-05-10 01:19:03.415219864 -0700 @@ -0,0 +1,1436 @@ +/* + * sata_sx4.c - Promise SATA + * + * Copyright 2003-2004 Red Hat, Inc. + * + * The contents of this file are subject to the Open + * Software License version 1.1 that can be found at + * http://www.opensource.org/licenses/osl-1.1.txt and is included herein + * by reference. + * + * Alternatively, the contents of this file may be used under the terms + * of the GNU General Public License version 2 (the "GPL") as distributed + * in the kernel source COPYING file, in which case the provisions of + * the GPL are applicable instead of the above. If you wish to allow + * the use of your version of this file only under the terms of the + * GPL and not to allow others to use your version of this file under + * the OSL, indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by the GPL. + * If you do not delete the provisions above, a recipient may use your + * version of this file under either the OSL or the GPL. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "scsi.h" +#include "hosts.h" +#include +#include +#include "sata_promise.h" + +#define DRV_NAME "sata_sx4" +#define DRV_VERSION "0.50" + + +enum { + PDC_PRD_TBL = 0x44, /* Direct command DMA table addr */ + + PDC_PKT_SUBMIT = 0x40, /* Command packet pointer addr */ + PDC_HDMA_PKT_SUBMIT = 0x100, /* Host DMA packet pointer addr */ + PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */ + PDC_HDMA_CTLSTAT = 0x12C, /* Host DMA control / status */ + + PDC_20621_SEQCTL = 0x400, + PDC_20621_SEQMASK = 0x480, + PDC_20621_GENERAL_CTL = 0x484, + PDC_20621_PAGE_SIZE = (32 * 1024), + + /* chosen, not constant, values; we design our own DIMM mem map */ + PDC_20621_DIMM_WINDOW = 0x0C, /* page# for 32K DIMM window */ + PDC_20621_DIMM_BASE = 0x00200000, + PDC_20621_DIMM_DATA = (64 * 1024), + PDC_DIMM_DATA_STEP = (256 * 1024), + PDC_DIMM_WINDOW_STEP = (8 * 1024), + PDC_DIMM_HOST_PRD = (6 * 1024), + PDC_DIMM_HOST_PKT = (128 * 0), + PDC_DIMM_HPKT_PRD = (128 * 1), + PDC_DIMM_ATA_PKT = (128 * 2), + PDC_DIMM_APKT_PRD = (128 * 3), + PDC_DIMM_HEADER_SZ = PDC_DIMM_APKT_PRD + 128, + PDC_PAGE_WINDOW = 0x40, + PDC_PAGE_DATA = PDC_PAGE_WINDOW + + (PDC_20621_DIMM_DATA / PDC_20621_PAGE_SIZE), + PDC_PAGE_SET = PDC_DIMM_DATA_STEP / PDC_20621_PAGE_SIZE, + + PDC_CHIP0_OFS = 0xC0000, /* offset of chip #0 */ + + PDC_20621_ERR_MASK = (1<<19) | (1<<20) | (1<<21) | (1<<22) | + (1<<23), + + board_20621 = 0, /* FastTrak S150 SX4 */ + + PDC_RESET = (1 << 11), /* HDMA reset */ + + PDC_MAX_HDMA = 32, + PDC_HDMA_Q_MASK = (PDC_MAX_HDMA - 1), + + PDC_DIMM0_SPD_DEV_ADDRESS = 0x50, + PDC_DIMM1_SPD_DEV_ADDRESS = 0x51, + PDC_MAX_DIMM_MODULE = 0x02, + PDC_I2C_CONTROL_OFFSET = 0x48, + PDC_I2C_ADDR_DATA_OFFSET = 0x4C, + PDC_DIMM0_CONTROL_OFFSET = 0x80, + PDC_DIMM1_CONTROL_OFFSET = 0x84, + PDC_SDRAM_CONTROL_OFFSET = 0x88, + PDC_I2C_WRITE = 0x00000000, + PDC_I2C_READ = 0x00000040, + PDC_I2C_START = 0x00000080, + PDC_I2C_MASK_INT = 0x00000020, + PDC_I2C_COMPLETE = 0x00010000, + PDC_I2C_NO_ACK = 0x00100000, + PDC_DIMM_SPD_SUBADDRESS_START = 0x00, + PDC_DIMM_SPD_SUBADDRESS_END = 0x7F, + PDC_DIMM_SPD_ROW_NUM = 3, + PDC_DIMM_SPD_COLUMN_NUM = 4, + PDC_DIMM_SPD_MODULE_ROW = 5, + PDC_DIMM_SPD_TYPE = 11, + PDC_DIMM_SPD_FRESH_RATE = 12, + PDC_DIMM_SPD_BANK_NUM = 17, + PDC_DIMM_SPD_CAS_LATENCY = 18, + PDC_DIMM_SPD_ATTRIBUTE = 21, + PDC_DIMM_SPD_ROW_PRE_CHARGE = 27, + PDC_DIMM_SPD_ROW_ACTIVE_DELAY = 28, + PDC_DIMM_SPD_RAS_CAS_DELAY = 29, + PDC_DIMM_SPD_ACTIVE_PRECHARGE = 30, + PDC_DIMM_SPD_SYSTEM_FREQ = 126, + PDC_CTL_STATUS = 0x08, + PDC_DIMM_WINDOW_CTLR = 0x0C, + PDC_TIME_CONTROL = 0x3C, + PDC_TIME_PERIOD = 0x40, + PDC_TIME_COUNTER = 0x44, + PDC_GENERAL_CTLR = 0x484, + PCI_PLL_INIT = 0x8A531824, + PCI_X_TCOUNT = 0xEE1E5CFF +}; + + +struct pdc_port_priv { + u8 dimm_buf[(ATA_PRD_SZ * ATA_MAX_PRD) + 512]; + u8 *pkt; + dma_addr_t pkt_dma; +}; + +struct pdc_host_priv { + void *dimm_mmio; + + unsigned int doing_hdma; + unsigned int hdma_prod; + unsigned int hdma_cons; + struct { + struct ata_queued_cmd *qc; + unsigned int seq; + unsigned long pkt_ofs; + } hdma[32]; +}; + + +static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); +static void pdc20621_dma_start(struct ata_queued_cmd *qc); +static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_regs *regs); +static void pdc_eng_timeout(struct ata_port *ap); +static void pdc_20621_phy_reset (struct ata_port *ap); +static int pdc_port_start(struct ata_port *ap); +static void pdc_port_stop(struct ata_port *ap); +static void pdc20621_fill_sg(struct ata_queued_cmd *qc); +static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf); +static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf); +static void pdc20621_host_stop(struct ata_host_set *host_set); +static inline void pdc_dma_complete (struct ata_port *ap, + struct ata_queued_cmd *qc, int have_err); +static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe); +static int pdc20621_detect_dimm(struct ata_probe_ent *pe); +static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, + u32 device, u32 subaddr, u32 *pdata); +static int pdc20621_prog_dimm0(struct ata_probe_ent *pe); +static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe); +#ifdef ATA_VERBOSE_DEBUG +static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, + void *psource, u32 offset, u32 size); +#endif +static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, + void *psource, u32 offset, u32 size); + + +static Scsi_Host_Template pdc_sata_sht = { + .module = THIS_MODULE, + .name = DRV_NAME, + .queuecommand = ata_scsi_queuecmd, + .eh_strategy_handler = ata_scsi_error, + .can_queue = ATA_DEF_QUEUE, + .this_id = ATA_SHT_THIS_ID, + .sg_tablesize = LIBATA_MAX_PRD, + .max_sectors = ATA_MAX_SECTORS, + .cmd_per_lun = ATA_SHT_CMD_PER_LUN, + .emulated = ATA_SHT_EMULATED, + .use_clustering = ATA_SHT_USE_CLUSTERING, + .proc_name = DRV_NAME, + .dma_boundary = ATA_DMA_BOUNDARY, + .slave_configure = ata_scsi_slave_config, + .bios_param = ata_std_bios_param, +}; + +static struct ata_port_operations pdc_20621_ops = { + .port_disable = ata_port_disable, + .tf_load = pdc_tf_load_mmio, + .tf_read = ata_tf_read_mmio, + .check_status = ata_check_status_mmio, + .exec_command = pdc_exec_command_mmio, + .phy_reset = pdc_20621_phy_reset, + .bmdma_start = pdc20621_dma_start, + .fill_sg = pdc20621_fill_sg, + .eng_timeout = pdc_eng_timeout, + .irq_handler = pdc20621_interrupt, + .port_start = pdc_port_start, + .port_stop = pdc_port_stop, + .host_stop = pdc20621_host_stop, +}; + +static struct ata_port_info pdc_port_info[] = { + /* board_20621 */ + { + .sht = &pdc_sata_sht, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_SRST | ATA_FLAG_MMIO, + .pio_mask = 0x03, /* pio3-4 */ + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ + .port_ops = &pdc_20621_ops, + }, + +}; + +static struct pci_device_id pdc_sata_pci_tbl[] = { + { PCI_VENDOR_ID_PROMISE, 0x6622, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_20621 }, + { } /* terminate list */ +}; + + +static struct pci_driver pdc_sata_pci_driver = { + .name = DRV_NAME, + .id_table = pdc_sata_pci_tbl, + .probe = pdc_sata_init_one, + .remove = ata_pci_remove_one, +}; + + +static void pdc20621_host_stop(struct ata_host_set *host_set) +{ + struct pdc_host_priv *hpriv = host_set->private_data; + void *dimm_mmio = hpriv->dimm_mmio; + + iounmap(dimm_mmio); + kfree(hpriv); +} + +static int pdc_port_start(struct ata_port *ap) +{ + struct pci_dev *pdev = ap->host_set->pdev; + struct pdc_port_priv *pp; + int rc; + + rc = ata_port_start(ap); + if (rc) + return rc; + + pp = kmalloc(sizeof(*pp), GFP_KERNEL); + if (!pp) { + rc = -ENOMEM; + goto err_out; + } + memset(pp, 0, sizeof(*pp)); + + pp->pkt = pci_alloc_consistent(pdev, 128, &pp->pkt_dma); + if (!pp->pkt) { + rc = -ENOMEM; + goto err_out_kfree; + } + + ap->private_data = pp; + + return 0; + +err_out_kfree: + kfree(pp); +err_out: + ata_port_stop(ap); + return rc; +} + + +static void pdc_port_stop(struct ata_port *ap) +{ + struct pci_dev *pdev = ap->host_set->pdev; + struct pdc_port_priv *pp = ap->private_data; + + ap->private_data = NULL; + pci_free_consistent(pdev, 128, pp->pkt, pp->pkt_dma); + kfree(pp); + ata_port_stop(ap); +} + + +static void pdc_20621_phy_reset (struct ata_port *ap) +{ + VPRINTK("ENTER\n"); + ap->cbl = ATA_CBL_SATA; + ata_port_probe(ap); + ata_bus_reset(ap); +} + +static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf, + unsigned int portno, + unsigned int total_len) +{ + u32 addr; + unsigned int dw = PDC_DIMM_APKT_PRD >> 2; + u32 *buf32 = (u32 *) buf; + + /* output ATA packet S/G table */ + addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA + + (PDC_DIMM_DATA_STEP * portno); + VPRINTK("ATA sg addr 0x%x, %d\n", addr, addr); + buf32[dw] = cpu_to_le32(addr); + buf32[dw + 1] = cpu_to_le32(total_len | ATA_PRD_EOT); + + VPRINTK("ATA PSG @ %x == (0x%x, 0x%x)\n", + PDC_20621_DIMM_BASE + + (PDC_DIMM_WINDOW_STEP * portno) + + PDC_DIMM_APKT_PRD, + buf32[dw], buf32[dw + 1]); +} + +static inline void pdc20621_host_sg(struct ata_taskfile *tf, u8 *buf, + unsigned int portno, + unsigned int total_len) +{ + u32 addr; + unsigned int dw = PDC_DIMM_HPKT_PRD >> 2; + u32 *buf32 = (u32 *) buf; + + /* output Host DMA packet S/G table */ + addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA + + (PDC_DIMM_DATA_STEP * portno); + + buf32[dw] = cpu_to_le32(addr); + buf32[dw + 1] = cpu_to_le32(total_len | ATA_PRD_EOT); + + VPRINTK("HOST PSG @ %x == (0x%x, 0x%x)\n", + PDC_20621_DIMM_BASE + + (PDC_DIMM_WINDOW_STEP * portno) + + PDC_DIMM_HPKT_PRD, + buf32[dw], buf32[dw + 1]); +} + +static inline unsigned int pdc20621_ata_pkt(struct ata_taskfile *tf, + unsigned int devno, u8 *buf, + unsigned int portno) +{ + unsigned int i, dw; + u32 *buf32 = (u32 *) buf; + u8 dev_reg; + + unsigned int dimm_sg = PDC_20621_DIMM_BASE + + (PDC_DIMM_WINDOW_STEP * portno) + + PDC_DIMM_APKT_PRD; + VPRINTK("ENTER, dimm_sg == 0x%x, %d\n", dimm_sg, dimm_sg); + + i = PDC_DIMM_ATA_PKT; + + /* + * Set up ATA packet + */ + if ((tf->protocol == ATA_PROT_DMA) && (!(tf->flags & ATA_TFLAG_WRITE))) + buf[i++] = PDC_PKT_READ; + else if (tf->protocol == ATA_PROT_NODATA) + buf[i++] = PDC_PKT_NODATA; + else + buf[i++] = 0; + buf[i++] = 0; /* reserved */ + buf[i++] = portno + 1; /* seq. id */ + buf[i++] = 0xff; /* delay seq. id */ + + /* dimm dma S/G, and next-pkt */ + dw = i >> 2; + buf32[dw] = cpu_to_le32(dimm_sg); + buf32[dw + 1] = 0; + i += 8; + + if (devno == 0) + dev_reg = ATA_DEVICE_OBS; + else + dev_reg = ATA_DEVICE_OBS | ATA_DEV1; + + /* select device */ + buf[i++] = (1 << 5) | PDC_PKT_CLEAR_BSY | ATA_REG_DEVICE; + buf[i++] = dev_reg; + + /* device control register */ + buf[i++] = (1 << 5) | PDC_REG_DEVCTL; + buf[i++] = tf->ctl; + + return i; +} + +static inline void pdc20621_host_pkt(struct ata_taskfile *tf, u8 *buf, + unsigned int portno) +{ + unsigned int dw; + u32 tmp, *buf32 = (u32 *) buf; + + unsigned int host_sg = PDC_20621_DIMM_BASE + + (PDC_DIMM_WINDOW_STEP * portno) + + PDC_DIMM_HOST_PRD; + unsigned int dimm_sg = PDC_20621_DIMM_BASE + + (PDC_DIMM_WINDOW_STEP * portno) + + PDC_DIMM_HPKT_PRD; + VPRINTK("ENTER, dimm_sg == 0x%x, %d\n", dimm_sg, dimm_sg); + VPRINTK("host_sg == 0x%x, %d\n", host_sg, host_sg); + + dw = PDC_DIMM_HOST_PKT >> 2; + + /* + * Set up Host DMA packet + */ + if ((tf->protocol == ATA_PROT_DMA) && (!(tf->flags & ATA_TFLAG_WRITE))) + tmp = PDC_PKT_READ; + else + tmp = 0; + tmp |= ((portno + 1 + 4) << 16); /* seq. id */ + tmp |= (0xff << 24); /* delay seq. id */ + buf32[dw + 0] = cpu_to_le32(tmp); + buf32[dw + 1] = cpu_to_le32(host_sg); + buf32[dw + 2] = cpu_to_le32(dimm_sg); + buf32[dw + 3] = 0; + + VPRINTK("HOST PKT @ %x == (0x%x 0x%x 0x%x 0x%x)\n", + PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * portno) + + PDC_DIMM_HOST_PKT, + buf32[dw + 0], + buf32[dw + 1], + buf32[dw + 2], + buf32[dw + 3]); +} + +static void pdc20621_fill_sg(struct ata_queued_cmd *qc) +{ + struct scatterlist *sg = qc->sg; + struct ata_port *ap = qc->ap; + struct pdc_port_priv *pp = ap->private_data; + void *mmio = ap->host_set->mmio_base; + struct pdc_host_priv *hpriv = ap->host_set->private_data; + void *dimm_mmio = hpriv->dimm_mmio; + unsigned int portno = ap->port_no; + unsigned int i, last, idx, total_len = 0, sgt_len; + u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ]; + + VPRINTK("ata%u: ENTER\n", ap->id); + + /* hard-code chip #0 */ + mmio += PDC_CHIP0_OFS; + + /* + * Build S/G table + */ + last = qc->n_elem; + idx = 0; + for (i = 0; i < last; i++) { + buf[idx++] = cpu_to_le32(sg_dma_address(&sg[i])); + buf[idx++] = cpu_to_le32(sg_dma_len(&sg[i])); + total_len += sg[i].length; + } + buf[idx - 1] |= cpu_to_le32(ATA_PRD_EOT); + sgt_len = idx * 4; + + /* + * Build ATA, host DMA packets + */ + pdc20621_host_sg(&qc->tf, &pp->dimm_buf[0], portno, total_len); + pdc20621_host_pkt(&qc->tf, &pp->dimm_buf[0], portno); + + pdc20621_ata_sg(&qc->tf, &pp->dimm_buf[0], portno, total_len); + i = pdc20621_ata_pkt(&qc->tf, qc->dev->devno, &pp->dimm_buf[0], portno); + + if (qc->tf.flags & ATA_TFLAG_LBA48) + i = pdc_prep_lba48(&qc->tf, &pp->dimm_buf[0], i); + else + i = pdc_prep_lba28(&qc->tf, &pp->dimm_buf[0], i); + + pdc_pkt_footer(&qc->tf, &pp->dimm_buf[0], i); + + /* copy three S/G tables and two packets to DIMM MMIO window */ + memcpy_toio(dimm_mmio + (portno * PDC_DIMM_WINDOW_STEP), + &pp->dimm_buf, PDC_DIMM_HEADER_SZ); + memcpy_toio(dimm_mmio + (portno * PDC_DIMM_WINDOW_STEP) + + PDC_DIMM_HOST_PRD, + &pp->dimm_buf[PDC_DIMM_HEADER_SZ], sgt_len); + + /* force host FIFO dump */ + writel(0x00000001, mmio + PDC_20621_GENERAL_CTL); + + readl(dimm_mmio); /* MMIO PCI posting flush */ + + VPRINTK("ata pkt buf ofs %u, prd size %u, mmio copied\n", i, sgt_len); +} + +static void __pdc20621_push_hdma(struct ata_queued_cmd *qc, + unsigned int seq, + u32 pkt_ofs) +{ + struct ata_port *ap = qc->ap; + struct ata_host_set *host_set = ap->host_set; + void *mmio = host_set->mmio_base; + + /* hard-code chip #0 */ + mmio += PDC_CHIP0_OFS; + + writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4)); + readl(mmio + PDC_20621_SEQCTL + (seq * 4)); /* flush */ + + writel(pkt_ofs, mmio + PDC_HDMA_PKT_SUBMIT); + readl(mmio + PDC_HDMA_PKT_SUBMIT); /* flush */ +} + +static void pdc20621_push_hdma(struct ata_queued_cmd *qc, + unsigned int seq, + u32 pkt_ofs) +{ + struct ata_port *ap = qc->ap; + struct pdc_host_priv *pp = ap->host_set->private_data; + unsigned int idx = pp->hdma_prod & PDC_HDMA_Q_MASK; + + if (!pp->doing_hdma) { + __pdc20621_push_hdma(qc, seq, pkt_ofs); + pp->doing_hdma = 1; + return; + } + + pp->hdma[idx].qc = qc; + pp->hdma[idx].seq = seq; + pp->hdma[idx].pkt_ofs = pkt_ofs; + pp->hdma_prod++; +} + +static void pdc20621_pop_hdma(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct pdc_host_priv *pp = ap->host_set->private_data; + unsigned int idx = pp->hdma_cons & PDC_HDMA_Q_MASK; + + /* if nothing on queue, we're done */ + if (pp->hdma_prod == pp->hdma_cons) { + pp->doing_hdma = 0; + return; + } + + __pdc20621_push_hdma(pp->hdma[idx].qc, pp->hdma[idx].seq, + pp->hdma[idx].pkt_ofs); + pp->hdma_cons++; +} + +#ifdef ATA_VERBOSE_DEBUG +static void pdc20621_dump_hdma(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + unsigned int port_no = ap->port_no; + struct pdc_host_priv *hpriv = ap->host_set->private_data; + void *dimm_mmio = hpriv->dimm_mmio; + + dimm_mmio += (port_no * PDC_DIMM_WINDOW_STEP); + dimm_mmio += PDC_DIMM_HOST_PKT; + + printk(KERN_ERR "HDMA[0] == 0x%08X\n", readl(dimm_mmio)); + printk(KERN_ERR "HDMA[1] == 0x%08X\n", readl(dimm_mmio + 4)); + printk(KERN_ERR "HDMA[2] == 0x%08X\n", readl(dimm_mmio + 8)); + printk(KERN_ERR "HDMA[3] == 0x%08X\n", readl(dimm_mmio + 12)); +} +#else +static inline void pdc20621_dump_hdma(struct ata_queued_cmd *qc) { } +#endif /* ATA_VERBOSE_DEBUG */ + +static void pdc20621_dma_start(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct ata_host_set *host_set = ap->host_set; + unsigned int port_no = ap->port_no; + void *mmio = host_set->mmio_base; + unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); + u8 seq = (u8) (port_no + 1); + unsigned int doing_hdma = 0, port_ofs; + + /* hard-code chip #0 */ + mmio += PDC_CHIP0_OFS; + + VPRINTK("ata%u: ENTER\n", ap->id); + + port_ofs = PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * port_no); + + /* if writing, we (1) DMA to DIMM, then (2) do ATA command */ + if (rw) { + doing_hdma = 1; + seq += 4; + } + + wmb(); /* flush PRD, pkt writes */ + + if (doing_hdma) { + pdc20621_dump_hdma(qc); + pdc20621_push_hdma(qc, seq, port_ofs + PDC_DIMM_HOST_PKT); + VPRINTK("queued ofs 0x%x (%u), seq %u\n", + port_ofs + PDC_DIMM_HOST_PKT, + port_ofs + PDC_DIMM_HOST_PKT, + seq); + } else { + writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4)); + readl(mmio + PDC_20621_SEQCTL + (seq * 4)); /* flush */ + + writel(port_ofs + PDC_DIMM_ATA_PKT, + (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); + readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); + VPRINTK("submitted ofs 0x%x (%u), seq %u\n", + port_ofs + PDC_DIMM_ATA_PKT, + port_ofs + PDC_DIMM_ATA_PKT, + seq); + } +} + +static inline unsigned int pdc20621_host_intr( struct ata_port *ap, + struct ata_queued_cmd *qc, + unsigned int doing_hdma, + void *mmio) +{ + unsigned int port_no = ap->port_no; + unsigned int port_ofs = + PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * port_no); + u8 status; + unsigned int handled = 0; + + VPRINTK("ENTER\n"); + + if ((qc->tf.protocol == ATA_PROT_DMA) && /* read */ + (!(qc->tf.flags & ATA_TFLAG_WRITE))) { + + /* step two - DMA from DIMM to host */ + if (doing_hdma) { + VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id, + readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT)); + pdc_dma_complete(ap, qc, 0); + pdc20621_pop_hdma(qc); + } + + /* step one - exec ATA command */ + else { + u8 seq = (u8) (port_no + 1 + 4); + VPRINTK("ata%u: read ata, 0x%x 0x%x\n", ap->id, + readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT)); + + /* submit hdma pkt */ + pdc20621_dump_hdma(qc); + pdc20621_push_hdma(qc, seq, + port_ofs + PDC_DIMM_HOST_PKT); + } + handled = 1; + + } else if (qc->tf.protocol == ATA_PROT_DMA) { /* write */ + + /* step one - DMA from host to DIMM */ + if (doing_hdma) { + u8 seq = (u8) (port_no + 1); + VPRINTK("ata%u: write hdma, 0x%x 0x%x\n", ap->id, + readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT)); + + /* submit ata pkt */ + writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4)); + readl(mmio + PDC_20621_SEQCTL + (seq * 4)); + writel(port_ofs + PDC_DIMM_ATA_PKT, + (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); + readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); + } + + /* step two - execute ATA command */ + else { + VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id, + readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT)); + pdc_dma_complete(ap, qc, 0); + pdc20621_pop_hdma(qc); + } + handled = 1; + + /* command completion, but no data xfer */ + } else if (qc->tf.protocol == ATA_PROT_NODATA) { + + status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); + DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status); + ata_qc_complete(qc, status, 0); + handled = 1; + + } else { + ap->stats.idle_irq++; + } + + return handled; +} + +static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_regs *regs) +{ + struct ata_host_set *host_set = dev_instance; + struct ata_port *ap; + u32 mask = 0; + unsigned int i, tmp, port_no; + unsigned int handled = 0; + void *mmio_base; + + VPRINTK("ENTER\n"); + + if (!host_set || !host_set->mmio_base) { + VPRINTK("QUICK EXIT\n"); + return IRQ_NONE; + } + + mmio_base = host_set->mmio_base; + + /* reading should also clear interrupts */ + mmio_base += PDC_CHIP0_OFS; + mask = readl(mmio_base + PDC_20621_SEQMASK); + VPRINTK("mask == 0x%x\n", mask); + + if (mask == 0xffffffff) { + VPRINTK("QUICK EXIT 2\n"); + return IRQ_NONE; + } + mask &= 0xffff; /* only 16 tags possible */ + if (!mask) { + VPRINTK("QUICK EXIT 3\n"); + return IRQ_NONE; + } + + spin_lock(&host_set->lock); + + for (i = 1; i < 9; i++) { + port_no = i - 1; + if (port_no > 3) + port_no -= 4; + if (port_no >= host_set->n_ports) + ap = NULL; + else + ap = host_set->ports[port_no]; + tmp = mask & (1 << i); + VPRINTK("seq %u, port_no %u, ap %p, tmp %x\n", i, port_no, ap, tmp); + if (tmp && ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) { + struct ata_queued_cmd *qc; + + qc = ata_qc_from_tag(ap, ap->active_tag); + if (qc && ((qc->flags & ATA_QCFLAG_POLL) == 0)) + handled += pdc20621_host_intr(ap, qc, (i > 4), + mmio_base); + } + } + + spin_unlock(&host_set->lock); + + VPRINTK("mask == 0x%x\n", mask); + + VPRINTK("EXIT\n"); + + return IRQ_RETVAL(handled); +} + +static inline void pdc_dma_complete (struct ata_port *ap, + struct ata_queued_cmd *qc, + int have_err) +{ + u8 err_bit = have_err ? ATA_ERR : 0; + + /* get drive status; clear intr; complete txn */ + ata_qc_complete(ata_qc_from_tag(ap, ap->active_tag), + ata_wait_idle(ap) | err_bit, 0); +} + +static void pdc_eng_timeout(struct ata_port *ap) +{ + u8 drv_stat; + struct ata_queued_cmd *qc; + + DPRINTK("ENTER\n"); + + qc = ata_qc_from_tag(ap, ap->active_tag); + if (!qc) { + printk(KERN_ERR "ata%u: BUG: timeout without command\n", + ap->id); + goto out; + } + + /* hack alert! We cannot use the supplied completion + * function from inside the ->eh_strategy_handler() thread. + * libata is the only user of ->eh_strategy_handler() in + * any kernel, so the default scsi_done() assumes it is + * not being called from the SCSI EH. + */ + qc->scsidone = scsi_finish_command; + + switch (qc->tf.protocol) { + case ATA_PROT_DMA: + printk(KERN_ERR "ata%u: DMA timeout\n", ap->id); + ata_qc_complete(ata_qc_from_tag(ap, ap->active_tag), + ata_wait_idle(ap) | ATA_ERR, 0); + break; + + case ATA_PROT_NODATA: + drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); + + printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x\n", + ap->id, qc->tf.command, drv_stat); + + ata_qc_complete(qc, drv_stat, 1); + break; + + default: + drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); + + printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n", + ap->id, qc->tf.command, drv_stat); + + ata_qc_complete(qc, drv_stat, 1); + break; + } + +out: + DPRINTK("EXIT\n"); +} + +static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf) +{ + if (tf->protocol == ATA_PROT_PIO) + ata_tf_load_mmio(ap, tf); +} + + +static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf) +{ + if (tf->protocol == ATA_PROT_PIO) + ata_exec_command_mmio(ap, tf); +} + + +static void pdc_sata_setup_port(struct ata_ioports *port, unsigned long base) +{ + port->cmd_addr = base; + port->data_addr = base; + port->feature_addr = + port->error_addr = base + 0x4; + port->nsect_addr = base + 0x8; + port->lbal_addr = base + 0xc; + port->lbam_addr = base + 0x10; + port->lbah_addr = base + 0x14; + port->device_addr = base + 0x18; + port->command_addr = + port->status_addr = base + 0x1c; + port->altstatus_addr = + port->ctl_addr = base + 0x38; +} + + +#ifdef ATA_VERBOSE_DEBUG +static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource, + u32 offset, u32 size) +{ + u32 window_size; + u16 idx; + u8 page_mask; + long dist; + void *mmio = pe->mmio_base; + struct pdc_host_priv *hpriv = pe->private_data; + void *dimm_mmio = hpriv->dimm_mmio; + + /* hard-code chip #0 */ + mmio += PDC_CHIP0_OFS; + + page_mask = 0x00; + window_size = 0x2000 * 4; /* 32K byte uchar size */ + idx = (u16) (offset / window_size); + + writel(0x01, mmio + PDC_GENERAL_CTLR); + readl(mmio + PDC_GENERAL_CTLR); + writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); + readl(mmio + PDC_DIMM_WINDOW_CTLR); + + offset -= (idx * window_size); + idx++; + dist = ((long) (window_size - (offset + size))) >= 0 ? size : + (long) (window_size - offset); + memcpy_fromio((char *) psource, (char *) (dimm_mmio + offset / 4), + dist); + + psource += dist; + size -= dist; + for (; (long) size >= (long) window_size ;) { + writel(0x01, mmio + PDC_GENERAL_CTLR); + readl(mmio + PDC_GENERAL_CTLR); + writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); + readl(mmio + PDC_DIMM_WINDOW_CTLR); + memcpy_fromio((char *) psource, (char *) (dimm_mmio), + window_size / 4); + psource += window_size; + size -= window_size; + idx ++; + } + + if (size) { + writel(0x01, mmio + PDC_GENERAL_CTLR); + readl(mmio + PDC_GENERAL_CTLR); + writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); + readl(mmio + PDC_DIMM_WINDOW_CTLR); + memcpy_fromio((char *) psource, (char *) (dimm_mmio), + size / 4); + } +} +#endif + + +static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource, + u32 offset, u32 size) +{ + u32 window_size; + u16 idx; + u8 page_mask; + long dist; + void *mmio = pe->mmio_base; + struct pdc_host_priv *hpriv = pe->private_data; + void *dimm_mmio = hpriv->dimm_mmio; + + /* hard-code chip #0 */ + mmio += PDC_CHIP0_OFS; + + page_mask = 0x00; + window_size = 0x2000 * 4; /* 32K byte uchar size */ + idx = (u16) (offset / window_size); + + writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); + readl(mmio + PDC_DIMM_WINDOW_CTLR); + offset -= (idx * window_size); + idx++; + dist = ((long)(s32)(window_size - (offset + size))) >= 0 ? size : + (long) (window_size - offset); + memcpy_toio((char *) (dimm_mmio + offset / 4), (char *) psource, dist); + writel(0x01, mmio + PDC_GENERAL_CTLR); + readl(mmio + PDC_GENERAL_CTLR); + + psource += dist; + size -= dist; + for (; (long) size >= (long) window_size ;) { + writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); + readl(mmio + PDC_DIMM_WINDOW_CTLR); + memcpy_toio((char *) (dimm_mmio), (char *) psource, + window_size / 4); + writel(0x01, mmio + PDC_GENERAL_CTLR); + readl(mmio + PDC_GENERAL_CTLR); + psource += window_size; + size -= window_size; + idx ++; + } + + if (size) { + writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); + readl(mmio + PDC_DIMM_WINDOW_CTLR); + memcpy_toio((char *) (dimm_mmio), (char *) psource, size / 4); + writel(0x01, mmio + PDC_GENERAL_CTLR); + readl(mmio + PDC_GENERAL_CTLR); + } +} + + +static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device, + u32 subaddr, u32 *pdata) +{ + void *mmio = pe->mmio_base; + u32 i2creg = 0; + u32 status; + u32 count =0; + + /* hard-code chip #0 */ + mmio += PDC_CHIP0_OFS; + + i2creg |= device << 24; + i2creg |= subaddr << 16; + + /* Set the device and subaddress */ + writel(i2creg, mmio + PDC_I2C_ADDR_DATA_OFFSET); + readl(mmio + PDC_I2C_ADDR_DATA_OFFSET); + + /* Write Control to perform read operation, mask int */ + writel(PDC_I2C_READ | PDC_I2C_START | PDC_I2C_MASK_INT, + mmio + PDC_I2C_CONTROL_OFFSET); + + for (count = 0; count <= 1000; count ++) { + status = readl(mmio + PDC_I2C_CONTROL_OFFSET); + if (status & PDC_I2C_COMPLETE) { + status = readl(mmio + PDC_I2C_ADDR_DATA_OFFSET); + break; + } else if (count == 1000) + return 0; + } + + *pdata = (status >> 8) & 0x000000ff; + return 1; +} + + +static int pdc20621_detect_dimm(struct ata_probe_ent *pe) +{ + u32 data=0 ; + if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, + PDC_DIMM_SPD_SYSTEM_FREQ, &data)) { + if (data == 100) + return 100; + } else + return 0; + + if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 9, &data)) { + if(data <= 0x75) + return 133; + } else + return 0; + + return 0; +} + + +static int pdc20621_prog_dimm0(struct ata_probe_ent *pe) +{ + u32 spd0[50]; + u32 data = 0; + int size, i; + u8 bdimmsize; + void *mmio = pe->mmio_base; + static const struct { + unsigned int reg; + unsigned int ofs; + } pdc_i2c_read_data [] = { + { PDC_DIMM_SPD_TYPE, 11 }, + { PDC_DIMM_SPD_FRESH_RATE, 12 }, + { PDC_DIMM_SPD_COLUMN_NUM, 4 }, + { PDC_DIMM_SPD_ATTRIBUTE, 21 }, + { PDC_DIMM_SPD_ROW_NUM, 3 }, + { PDC_DIMM_SPD_BANK_NUM, 17 }, + { PDC_DIMM_SPD_MODULE_ROW, 5 }, + { PDC_DIMM_SPD_ROW_PRE_CHARGE, 27 }, + { PDC_DIMM_SPD_ROW_ACTIVE_DELAY, 28 }, + { PDC_DIMM_SPD_RAS_CAS_DELAY, 29 }, + { PDC_DIMM_SPD_ACTIVE_PRECHARGE, 30 }, + { PDC_DIMM_SPD_CAS_LATENCY, 18 }, + }; + + /* hard-code chip #0 */ + mmio += PDC_CHIP0_OFS; + + for(i=0; i spd0[28]) + ? spd0[29] : spd0[28]) + 9) / 10) - 1) << 10; + data |= ((spd0[30] - spd0[29] + 9) / 10 - 2) << 12; + + if (spd0[18] & 0x08) + data |= ((0x03) << 14); + else if (spd0[18] & 0x04) + data |= ((0x02) << 14); + else if (spd0[18] & 0x01) + data |= ((0x01) << 14); + else + data |= (0 << 14); + + /* + Calculate the size of bDIMMSize (power of 2) and + merge the DIMM size by program start/end address. + */ + + bdimmsize = spd0[4] + (spd0[5] / 2) + spd0[3] + (spd0[17] / 2) + 3; + size = (1 << bdimmsize) >> 20; /* size = xxx(MB) */ + data |= (((size / 16) - 1) << 16); + data |= (0 << 23); + data |= 8; + writel(data, mmio + PDC_DIMM0_CONTROL_OFFSET); + readl(mmio + PDC_DIMM0_CONTROL_OFFSET); + return size; +} + + +static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe) +{ + u32 data, spd0; + int error, i; + void *mmio = pe->mmio_base; + + /* hard-code chip #0 */ + mmio += PDC_CHIP0_OFS; + + /* + Set To Default : DIMM Module Global Control Register (0x022259F1) + DIMM Arbitration Disable (bit 20) + DIMM Data/Control Output Driving Selection (bit12 - bit15) + Refresh Enable (bit 17) + */ + + data = 0x022259F1; + writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET); + readl(mmio + PDC_SDRAM_CONTROL_OFFSET); + + /* Turn on for ECC */ + pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, + PDC_DIMM_SPD_TYPE, &spd0); + if (spd0 == 0x02) { + data |= (0x01 << 16); + writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET); + readl(mmio + PDC_SDRAM_CONTROL_OFFSET); + printk(KERN_ERR "Local DIMM ECC Enabled\n"); + } + + /* DIMM Initialization Select/Enable (bit 18/19) */ + data &= (~(1<<18)); + data |= (1<<19); + writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET); + + error = 1; + for (i = 1; i <= 10; i++) { /* polling ~5 secs */ + data = readl(mmio + PDC_SDRAM_CONTROL_OFFSET); + if (!(data & (1<<19))) { + error = 0; + break; + } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((i * 100) * HZ / 1000 + 1); + } + return error; +} + + +static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe) +{ + int speed, size, length; + u32 addr,spd0,pci_status; + u32 tmp=0; + u32 time_period=0; + u32 tcount=0; + u32 ticks=0; + u32 clock=0; + u32 fparam=0; + void *mmio = pe->mmio_base; + + /* hard-code chip #0 */ + mmio += PDC_CHIP0_OFS; + + /* Initialize PLL based upon PCI Bus Frequency */ + + /* Initialize Time Period Register */ + writel(0xffffffff, mmio + PDC_TIME_PERIOD); + time_period = readl(mmio + PDC_TIME_PERIOD); + VPRINTK("Time Period Register (0x40): 0x%x\n", time_period); + + /* Enable timer */ + writel(0x00001a0, mmio + PDC_TIME_CONTROL); + readl(mmio + PDC_TIME_CONTROL); + + /* Wait 3 seconds */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(3 * HZ); + + /* + When timer is enabled, counter is decreased every internal + clock cycle. + */ + + tcount = readl(mmio + PDC_TIME_COUNTER); + VPRINTK("Time Counter Register (0x44): 0x%x\n", tcount); + + /* + If SX4 is on PCI-X bus, after 3 seconds, the timer counter + register should be >= (0xffffffff - 3x10^8). + */ + if(tcount >= PCI_X_TCOUNT) { + ticks = (time_period - tcount); + VPRINTK("Num counters 0x%x (%d)\n", ticks, ticks); + + clock = (ticks / 300000); + VPRINTK("10 * Internal clk = 0x%x (%d)\n", clock, clock); + + clock = (clock * 33); + VPRINTK("10 * Internal clk * 33 = 0x%x (%d)\n", clock, clock); + + /* PLL F Param (bit 22:16) */ + fparam = (1400000 / clock) - 2; + VPRINTK("PLL F Param: 0x%x (%d)\n", fparam, fparam); + + /* OD param = 0x2 (bit 31:30), R param = 0x5 (bit 29:25) */ + pci_status = (0x8a001824 | (fparam << 16)); + } else + pci_status = PCI_PLL_INIT; + + /* Initialize PLL. */ + VPRINTK("pci_status: 0x%x\n", pci_status); + writel(pci_status, mmio + PDC_CTL_STATUS); + readl(mmio + PDC_CTL_STATUS); + + /* + Read SPD of DIMM by I2C interface, + and program the DIMM Module Controller. + */ + if (!(speed = pdc20621_detect_dimm(pe))) { + printk(KERN_ERR "Detect Local DIMM Fail\n"); + return 1; /* DIMM error */ + } + VPRINTK("Local DIMM Speed = %d\n", speed); + + /* Programming DIMM0 Module Control Register (index_CID0:80h) */ + size = pdc20621_prog_dimm0(pe); + VPRINTK("Local DIMM Size = %dMB\n",size); + + /* Programming DIMM Module Global Control Register (index_CID0:88h) */ + if (pdc20621_prog_dimm_global(pe)) { + printk(KERN_ERR "Programming DIMM Module Global Control Register Fail\n"); + return 1; + } + +#ifdef ATA_VERBOSE_DEBUG + { + u8 test_parttern1[40] = {0x55,0xAA,'P','r','o','m','i','s','e',' ', + 'N','o','t',' ','Y','e','t',' ','D','e','f','i','n','e','d',' ', + '1','.','1','0', + '9','8','0','3','1','6','1','2',0,0}; + u8 test_parttern2[40] = {0}; + + pdc20621_put_to_dimm(pe, (void *) test_parttern2, 0x10040, 40); + pdc20621_put_to_dimm(pe, (void *) test_parttern2, 0x40, 40); + + pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x10040, 40); + pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40); + printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], + test_parttern2[1], &(test_parttern2[2])); + pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x10040, + 40); + printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], + test_parttern2[1], &(test_parttern2[2])); + + pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x40, 40); + pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40); + printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], + test_parttern2[1], &(test_parttern2[2])); + } +#endif + + /* ECC initiliazation. */ + + pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, + PDC_DIMM_SPD_TYPE, &spd0); + if (spd0 == 0x02) { + VPRINTK("Start ECC initialization\n"); + addr = 0; + length = size * 1024 * 1024; + while (addr < length) { + pdc20621_put_to_dimm(pe, (void *) &tmp, addr, + sizeof(u32)); + addr += sizeof(u32); + } + VPRINTK("Finish ECC initialization\n"); + } + return 0; +} + + +static void pdc_20621_init(struct ata_probe_ent *pe) +{ + u32 tmp; + void *mmio = pe->mmio_base; + + /* hard-code chip #0 */ + mmio += PDC_CHIP0_OFS; + + /* + * Select page 0x40 for our 32k DIMM window + */ + tmp = readl(mmio + PDC_20621_DIMM_WINDOW) & 0xffff0000; + tmp |= PDC_PAGE_WINDOW; /* page 40h; arbitrarily selected */ + writel(tmp, mmio + PDC_20621_DIMM_WINDOW); + + /* + * Reset Host DMA + */ + tmp = readl(mmio + PDC_HDMA_CTLSTAT); + tmp |= PDC_RESET; + writel(tmp, mmio + PDC_HDMA_CTLSTAT); + readl(mmio + PDC_HDMA_CTLSTAT); /* flush */ + + udelay(10); + + tmp = readl(mmio + PDC_HDMA_CTLSTAT); + tmp &= ~PDC_RESET; + writel(tmp, mmio + PDC_HDMA_CTLSTAT); + readl(mmio + PDC_HDMA_CTLSTAT); /* flush */ +} + +static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +{ + static int printed_version; + struct ata_probe_ent *probe_ent = NULL; + unsigned long base; + void *mmio_base, *dimm_mmio = NULL; + struct pdc_host_priv *hpriv = NULL; + unsigned int board_idx = (unsigned int) ent->driver_data; + int rc; + + if (!printed_version++) + printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); + + /* + * If this driver happens to only be useful on Apple's K2, then + * we should check that here as it has a normal Serverworks ID + */ + rc = pci_enable_device(pdev); + if (rc) + return rc; + + rc = pci_request_regions(pdev, DRV_NAME); + if (rc) + goto err_out; + + rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + if (rc) + goto err_out_regions; + rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + if (rc) + goto err_out_regions; + + probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); + if (probe_ent == NULL) { + rc = -ENOMEM; + goto err_out_regions; + } + + memset(probe_ent, 0, sizeof(*probe_ent)); + probe_ent->pdev = pdev; + INIT_LIST_HEAD(&probe_ent->node); + + mmio_base = ioremap(pci_resource_start(pdev, 3), + pci_resource_len(pdev, 3)); + if (mmio_base == NULL) { + rc = -ENOMEM; + goto err_out_free_ent; + } + base = (unsigned long) mmio_base; + + hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL); + if (!hpriv) { + rc = -ENOMEM; + goto err_out_iounmap; + } + memset(hpriv, 0, sizeof(*hpriv)); + + dimm_mmio = ioremap(pci_resource_start(pdev, 4), + pci_resource_len(pdev, 4)); + if (!dimm_mmio) { + kfree(hpriv); + rc = -ENOMEM; + goto err_out_iounmap; + } + + hpriv->dimm_mmio = dimm_mmio; + + probe_ent->sht = pdc_port_info[board_idx].sht; + probe_ent->host_flags = pdc_port_info[board_idx].host_flags; + probe_ent->pio_mask = pdc_port_info[board_idx].pio_mask; + probe_ent->udma_mask = pdc_port_info[board_idx].udma_mask; + probe_ent->port_ops = pdc_port_info[board_idx].port_ops; + + probe_ent->irq = pdev->irq; + probe_ent->irq_flags = SA_SHIRQ; + probe_ent->mmio_base = mmio_base; + + probe_ent->private_data = hpriv; + base += PDC_CHIP0_OFS; + + pdc_sata_setup_port(&probe_ent->port[0], base + 0x200); + pdc_sata_setup_port(&probe_ent->port[1], base + 0x280); + + /* notice 4-port boards */ + switch (board_idx) { + case board_20621: + probe_ent->n_ports = 4; + + pdc_sata_setup_port(&probe_ent->port[2], base + 0x300); + pdc_sata_setup_port(&probe_ent->port[3], base + 0x380); + break; + default: + BUG(); + break; + } + + pci_set_master(pdev); + + /* initialize adapter */ + /* initialize local dimm */ + if (pdc20621_dimm_init(probe_ent)) { + rc = -ENOMEM; + goto err_out_iounmap_dimm; + } + pdc_20621_init(probe_ent); + + /* FIXME: check ata_device_add return value */ + ata_device_add(probe_ent); + kfree(probe_ent); + + return 0; + +err_out_iounmap_dimm: /* only get to this label if 20621 */ + kfree(hpriv); + iounmap(dimm_mmio); +err_out_iounmap: + iounmap(mmio_base); +err_out_free_ent: + kfree(probe_ent); +err_out_regions: + pci_release_regions(pdev); +err_out: + pci_disable_device(pdev); + return rc; +} + + +static int __init pdc_sata_init(void) +{ + return pci_module_init(&pdc_sata_pci_driver); +} + + +static void __exit pdc_sata_exit(void) +{ + pci_unregister_driver(&pdc_sata_pci_driver); +} + + +MODULE_AUTHOR("Jeff Garzik"); +MODULE_DESCRIPTION("Promise SATA low-level driver"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(pci, pdc_sata_pci_tbl); + +module_init(pdc_sata_init); +module_exit(pdc_sata_exit); --- linux-2.6.6/drivers/scsi/scsi.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/scsi/scsi.c 2004-05-10 01:19:04.909992624 -0700 @@ -977,8 +977,6 @@ int scsi_track_queue_full(struct scsi_de */ int scsi_device_get(struct scsi_device *sdev) { - if(!sdev) - return -ENXIO; if (sdev->sdev_state == SDEV_DEL || sdev->sdev_state == SDEV_CANCEL) return -ENXIO; if (!get_device(&sdev->sdev_gendev)) --- linux-2.6.6/drivers/scsi/scsi_scan.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/scsi/scsi_scan.c 2004-05-10 01:19:04.910992472 -0700 @@ -330,6 +330,7 @@ static void scsi_probe_lun(struct scsi_r struct scsi_device *sdev = sreq->sr_device; /* a bit ugly */ unsigned char scsi_cmd[MAX_COMMAND_SIZE]; int possible_inq_resp_len; + int count = 0; *bflags = 0; repeat_inquiry: @@ -350,19 +351,24 @@ static void scsi_probe_lun(struct scsi_r SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: 1st INQUIRY %s with" " code 0x%x\n", sreq->sr_result ? "failed" : "successful", sreq->sr_result)); + ++count; if (sreq->sr_result) { if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) != 0 && (sreq->sr_sense_buffer[2] & 0xf) == UNIT_ATTENTION && - sreq->sr_sense_buffer[12] == 0x28 && + (sreq->sr_sense_buffer[12] == 0x28 || + sreq->sr_sense_buffer[12] == 0x29) && sreq->sr_sense_buffer[13] == 0) { - /* not-ready to ready transition - good */ + /* not-ready to ready transition or power-on - good */ /* dpg: bogus? INQUIRY never returns UNIT_ATTENTION */ - } else - /* - * assume no peripheral if any other sort of error - */ - return; + /* Supposedly, but many buggy devices do so anyway */ + if (count < 3) + goto repeat_inquiry; + } + /* + * assume no peripheral if any other sort of error + */ + return; } /* @@ -543,17 +549,12 @@ static int scsi_add_lun(struct scsi_devi * 011 the same. Stay compatible with previous code, and create a * Scsi_Device for a PQ of 1 * - * XXX Save the PQ field let the upper layers figure out if they - * want to attach or not to this device, do not set online FALSE; - * otherwise, offline devices still get an sd allocated, and they - * use up an sd slot. - */ - if (((inq_result[0] >> 5) & 7) == 1) { - SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: peripheral" - " qualifier of 1, device offlined\n")); - scsi_device_set_state(sdev, SDEV_OFFLINE); - } + * Don't set the device offline here; rather let the upper + * level drivers eval the PQ to decide whether they should + * attach. So remove ((inq_result[0] >> 5) & 7) == 1 check. + */ + sdev->inq_periph_qual = (inq_result[0] >> 5) & 7; sdev->removable = (0x80 & inq_result[1]) >> 7; sdev->lockable = sdev->removable; sdev->soft_reset = (inq_result[7] & 1) && ((inq_result[3] & 7) == 2); --- linux-2.6.6/drivers/scsi/scsi_sysfs.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/scsi/scsi_sysfs.c 2004-05-10 01:19:04.911992320 -0700 @@ -181,7 +181,8 @@ struct class sdev_class = { /* all probing is done in the individual ->probe routines */ static int scsi_bus_match(struct device *dev, struct device_driver *gendrv) { - return 1; + struct scsi_device *sdp = to_scsi_device(dev); + return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0; } struct bus_type scsi_bus_type = { --- linux-2.6.6/drivers/scsi/sd.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/scsi/sd.c 2004-05-10 01:19:04.912992168 -0700 @@ -179,7 +179,16 @@ static struct scsi_disk *scsi_disk_get(s goto out; sdkp = scsi_disk(disk); if (!kref_get(&sdkp->kref)) - sdkp = NULL; + goto out_sdkp; + if (scsi_device_get(sdkp->device)) + goto out_put; + up(&sd_ref_sem); + return sdkp; + + out_put: + kref_put(&sdkp->kref); + out_sdkp: + sdkp = NULL; out: up(&sd_ref_sem); return sdkp; @@ -188,6 +197,7 @@ static struct scsi_disk *scsi_disk_get(s static void scsi_disk_put(struct scsi_disk *sdkp) { down(&sd_ref_sem); + scsi_device_put(sdkp->device); kref_put(&sdkp->kref); up(&sd_ref_sem); } @@ -1342,16 +1352,13 @@ static int sd_probe(struct device *dev) if ((sdp->type != TYPE_DISK) && (sdp->type != TYPE_MOD)) goto out; - if ((error = scsi_device_get(sdp)) != 0) - goto out; - SCSI_LOG_HLQUEUE(3, printk("sd_attach: scsi device: <%d,%d,%d,%d>\n", sdp->host->host_no, sdp->channel, sdp->id, sdp->lun)); error = -ENOMEM; sdkp = kmalloc(sizeof(*sdkp), GFP_KERNEL); if (!sdkp) - goto out_put_sdev; + goto out; memset (sdkp, 0, sizeof(*sdkp)); kref_init(&sdkp->kref, scsi_disk_release); @@ -1427,8 +1434,6 @@ out_put: put_disk(gd); out_free: kfree(sdkp); -out_put_sdev: - scsi_device_put(sdp); out: return error; } @@ -1450,7 +1455,9 @@ static int sd_remove(struct device *dev) del_gendisk(sdkp->disk); sd_shutdown(dev); - scsi_disk_put(sdkp); + down(&sd_ref_sem); + kref_put(&sdkp->kref); + up(&sd_ref_sem); return 0; } @@ -1467,7 +1474,6 @@ static int sd_remove(struct device *dev) static void scsi_disk_release(struct kref *kref) { struct scsi_disk *sdkp = to_scsi_disk(kref); - struct scsi_device *sdev = sdkp->device; struct gendisk *disk = sdkp->disk; spin_lock(&sd_index_lock); @@ -1479,8 +1485,6 @@ static void scsi_disk_release(struct kre put_disk(disk); kfree(sdkp); - - scsi_device_put(sdev); } /* --- linux-2.6.6/drivers/scsi/sgiwd93.c 2003-07-27 12:14:39.000000000 -0700 +++ 25/drivers/scsi/sgiwd93.c 2004-05-10 01:19:16.817182456 -0700 @@ -1,32 +1,32 @@ /* - * sgiwd93.c: SGI WD93 scsi driver. + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * 1999 Andrew R. Baker (andrewb@uab.edu) - * - Support for 2nd SCSI controller on Indigo2 - * 2001 Florian Lohoff (flo@rfc822.org) - * - Delete HPC scatter gather (Read corruption on - * multiple disks) - * - Cleanup wback cache handling + * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) + * Copyright (C) 2001 Florian Lohoff (flo@rfc822.org) + * Copyright (C) 2003 Ralf Baechle (ralf@linux-mips.org) * * (In all truth, Jed Schimmel wrote all this code.) - * */ #include +#include #include #include #include #include #include +#include #include #include #include #include #include -#include -#include -#include +#include +#include +#include #include #include @@ -37,95 +37,130 @@ #include +#if 0 +#define DPRINTK(args...) printk(args) +#else +#define DPRINTK(args...) +#endif + +#define HDATA(ptr) ((struct ip22_hostdata *)((ptr)->hostdata)) + +struct ip22_hostdata { + struct WD33C93_hostdata wh; + struct hpc_data { + dma_addr_t dma; + void * cpu; + } hd; +}; + struct hpc_chunk { struct hpc_dma_desc desc; u32 _padding; /* align to quadword boundary */ }; -struct Scsi_Host *sgiwd93_host = NULL; -struct Scsi_Host *sgiwd93_host1 = NULL; +struct Scsi_Host *sgiwd93_host; +struct Scsi_Host *sgiwd93_host1; /* Wuff wuff, wuff, wd33c93.c, wuff wuff, object oriented, bow wow. */ +static inline void write_wd33c93_count(const wd33c93_regs regs, + unsigned long value) +{ + *regs.SASR = WD_TRANSFER_COUNT_MSB; + mb(); + *regs.SCMD = ((value >> 16) & 0xff); + *regs.SCMD = ((value >> 8) & 0xff); + *regs.SCMD = ((value >> 0) & 0xff); + mb(); +} -/* XXX woof! */ -static void sgiwd93_intr(int irq, void *dev_id, struct pt_regs *regs) +static inline unsigned long read_wd33c93_count(const wd33c93_regs regs) { - unsigned long flags; - struct Scsi_Host *dev = dev_id; - - spin_lock_irqsave(dev->host_lock, flags); - wd33c93_intr((struct Scsi_Host *) dev_id); - spin_unlock_irqrestore(dev->host_lock, flags); + unsigned long value; + + *regs.SASR = WD_TRANSFER_COUNT_MSB; + mb(); + value = ((*regs.SCMD & 0xff) << 16); + value |= ((*regs.SCMD & 0xff) << 8); + value |= ((*regs.SCMD & 0xff) << 0); + mb(); + return value; } -#undef DEBUG_DMA +static irqreturn_t sgiwd93_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + struct Scsi_Host * host = (struct Scsi_Host *) dev_id; + unsigned long flags; + + spin_lock_irqsave(host->host_lock, flags); + wd33c93_intr(host); + spin_unlock_irqrestore(host->host_lock, flags); + + return IRQ_HANDLED; +} static inline -void fill_hpc_entries (struct hpc_chunk **hcp, char *addr, unsigned long len) +void fill_hpc_entries(struct hpc_chunk *hcp, Scsi_Cmnd *cmd, int datainp) { - unsigned long physaddr; + unsigned long len = cmd->SCp.this_residual; + void *addr = cmd->SCp.ptr; + dma_addr_t physaddr; unsigned long count; - - physaddr = PHYSADDR(addr); + + physaddr = dma_map_single(NULL, addr, len, cmd->sc_data_direction); + cmd->SCp.dma_handle = physaddr; + while (len) { /* * even cntinfo could be up to 16383, without * magic only 8192 works correctly */ count = len > 8192 ? 8192 : len; - (*hcp)->desc.pbuf = physaddr; - (*hcp)->desc.cntinfo = count; - (*hcp)++; + hcp->desc.pbuf = physaddr; + hcp->desc.cntinfo = count; + hcp++; len -= count; physaddr += count; } + + /* + * To make sure, if we trip an HPC bug, that we transfer every single + * byte, we tag on an extra zero length dma descriptor at the end of + * the chain. + */ + hcp->desc.pbuf = 0; + hcp->desc.cntinfo = HPCDMA_EOX; } static int dma_setup(Scsi_Cmnd *cmd, int datainp) { - struct WD33C93_hostdata *hdata = (struct WD33C93_hostdata *)cmd->host->hostdata; - struct hpc3_scsiregs *hregs = (struct hpc3_scsiregs *) cmd->host->base; - struct hpc_chunk *hcp = (struct hpc_chunk *) hdata->dma_bounce_buffer; - -#ifdef DEBUG_DMA - printk("dma_setup: datainp<%d> hcp<%p> ", - datainp, hcp); -#endif + struct ip22_hostdata *hdata = HDATA(cmd->device->host); + struct hpc3_scsiregs *hregs = + (struct hpc3_scsiregs *) cmd->device->host->base; + struct hpc_chunk *hcp = (struct hpc_chunk *) hdata->hd.cpu; - hdata->dma_dir = datainp; + DPRINTK("dma_setup: datainp<%d> hcp<%p> ", datainp, hcp); + + hdata->wh.dma_dir = datainp; /* - * wd33c93 shouldn't pass us bogus dma_setups, but - * it does:-( The other wd33c93 drivers deal with - * it the same way (which isn't that obvious). - * IMHO a better fix would be, not to do these - * dma setups in the first place + * wd33c93 shouldn't pass us bogus dma_setups, but it does:-( The + * other wd33c93 drivers deal with it the same way (which isn't that + * obvious). IMHO a better fix would be, not to do these dma setups + * in the first place. */ - if (cmd->SCp.ptr == NULL) + if (cmd->SCp.ptr == NULL || cmd->SCp.this_residual == 0) return 1; - fill_hpc_entries (&hcp, cmd->SCp.ptr,cmd->SCp.this_residual); + fill_hpc_entries(hcp, cmd, datainp); - /* To make sure, if we trip an HPC bug, that we transfer - * every single byte, we tag on an extra zero length dma - * descriptor at the end of the chain. - */ - hcp->desc.pbuf = 0; - hcp->desc.cntinfo = (HPCDMA_EOX); - -#ifdef DEBUG_DMA - printk(" HPCGO\n"); -#endif + DPRINTK(" HPCGO\n"); /* Start up the HPC. */ - hregs->ndptr = PHYSADDR(hdata->dma_bounce_buffer); - if(datainp) { - dma_cache_inv((unsigned long) cmd->SCp.ptr, cmd->SCp.this_residual); - hregs->ctrl = (HPC3_SCTRL_ACTIVE); - } else { - dma_cache_wback_inv((unsigned long) cmd->SCp.ptr, cmd->SCp.this_residual); - hregs->ctrl = (HPC3_SCTRL_ACTIVE | HPC3_SCTRL_DIR); - } + hregs->ndptr = hdata->hd.dma; + if (datainp) + hregs->ctrl = HPC3_SCTRL_ACTIVE; + else + hregs->ctrl = HPC3_SCTRL_ACTIVE | HPC3_SCTRL_DIR; return 0; } @@ -133,29 +168,27 @@ static int dma_setup(Scsi_Cmnd *cmd, int static void dma_stop(struct Scsi_Host *instance, Scsi_Cmnd *SCpnt, int status) { - struct WD33C93_hostdata *hdata = (struct WD33C93_hostdata *)instance->hostdata; + struct ip22_hostdata *hdata = HDATA(instance); struct hpc3_scsiregs *hregs; if (!SCpnt) return; - hregs = (struct hpc3_scsiregs *) SCpnt->host->base; + hregs = (struct hpc3_scsiregs *) SCpnt->device->host->base; -#ifdef DEBUG_DMA - printk("dma_stop: status<%d> ", status); -#endif + DPRINTK("dma_stop: status<%d> ", status); /* First stop the HPC and flush it's FIFO. */ - if(hdata->dma_dir) { + if (hdata->wh.dma_dir) { hregs->ctrl |= HPC3_SCTRL_FLUSH; - while(hregs->ctrl & HPC3_SCTRL_ACTIVE) + while (hregs->ctrl & HPC3_SCTRL_ACTIVE) barrier(); } hregs->ctrl = 0; + dma_unmap_single(NULL, SCpnt->SCp.dma_handle, SCpnt->SCp.this_residual, + SCpnt->sc_data_direction); -#ifdef DEBUG_DMA - printk("\n"); -#endif + DPRINTK("\n"); } void sgiwd93_reset(unsigned long base) @@ -163,142 +196,142 @@ void sgiwd93_reset(unsigned long base) struct hpc3_scsiregs *hregs = (struct hpc3_scsiregs *) base; hregs->ctrl = HPC3_SCTRL_CRESET; - udelay (50); + udelay(50); hregs->ctrl = 0; } -static inline void init_hpc_chain(uchar *buf) +static inline void init_hpc_chain(struct hpc_data *hd) { - struct hpc_chunk *hcp = (struct hpc_chunk *) buf; + struct hpc_chunk *hcp = (struct hpc_chunk *) hd->cpu; + struct hpc_chunk *dma = (struct hpc_chunk *) hd->dma; unsigned long start, end; - start = (unsigned long) buf; + start = (unsigned long) hcp; end = start + PAGE_SIZE; - while(start < end) { - hcp->desc.pnext = PHYSADDR((hcp + 1)); + while (start < end) { + hcp->desc.pnext = (u32) (dma + 1); hcp->desc.cntinfo = HPCDMA_EOX; - hcp++; + hcp++; dma++; start += sizeof(struct hpc_chunk); }; hcp--; - hcp->desc.pnext = PHYSADDR(buf); - - /* Force flush to memory */ - dma_cache_wback_inv((unsigned long) buf, PAGE_SIZE); + hcp->desc.pnext = hd->dma; } -int __init sgiwd93_detect(Scsi_Host_Template *SGIblows) +static struct Scsi_Host * __init sgiwd93_setup_scsi( + Scsi_Host_Template *SGIblows, int unit, int irq, + struct hpc3_scsiregs *hregs, unsigned char *wdregs) { - static unsigned char called = 0; - struct hpc3_scsiregs *hregs = &hpc3c0->scsi_chan0; - struct hpc3_scsiregs *hregs1 = &hpc3c0->scsi_chan1; - struct WD33C93_hostdata *hdata; - struct WD33C93_hostdata *hdata1; + struct ip22_hostdata *hdata; + struct Scsi_Host *host; wd33c93_regs regs; - uchar *buf; - - if(called) - return 0; /* Should bitch on the console about this... */ - SGIblows->proc_name = "SGIWD93"; - - sgiwd93_host = scsi_register(SGIblows, sizeof(struct WD33C93_hostdata)); - if(sgiwd93_host == NULL) - return 0; - sgiwd93_host->base = (unsigned long) hregs; - sgiwd93_host->irq = SGI_WD93_0_IRQ; - - buf = (uchar *) get_zeroed_page(GFP_KERNEL); - if (!buf) { - printk(KERN_WARNING "sgiwd93: Could not allocate memory for host0 buffer.\n"); - scsi_unregister(sgiwd93_host); - return 0; + host = scsi_register(SGIblows, sizeof(struct ip22_hostdata)); + if (!host) + return NULL; + + host->base = (unsigned long) hregs; + host->irq = irq; + + hdata = HDATA(host); + hdata->hd.cpu = dma_alloc_coherent(NULL, PAGE_SIZE, &hdata->hd.dma, + GFP_KERNEL); + if (!hdata->hd.cpu) { + printk(KERN_WARNING "sgiwd93: Could not allocate memory for " + "host %d buffer.\n", unit); + goto out_unregister; } - init_hpc_chain(buf); - - /* HPC_SCSI_REG0 | 0x03 | KSEG1 */ - regs.SASR = (unsigned char*) KSEG1ADDR (0x1fbc0003); - regs.SCMD = (unsigned char*) KSEG1ADDR (0x1fbc0007); - wd33c93_init(sgiwd93_host, regs, dma_setup, dma_stop, WD33C93_FS_16_20); - - hdata = (struct WD33C93_hostdata *)sgiwd93_host->hostdata; - hdata->no_sync = 0; - hdata->dma_bounce_buffer = (uchar *) (KSEG1ADDR(buf)); - - if (request_irq(SGI_WD93_0_IRQ, sgiwd93_intr, 0, "SGI WD93", (void *) sgiwd93_host)) { - printk(KERN_WARNING "sgiwd93: Could not register IRQ %d (for host 0).\n", SGI_WD93_0_IRQ); - wd33c93_release(); - free_page((unsigned long)buf); - scsi_unregister(sgiwd93_host); - return 0; + init_hpc_chain(&hdata->hd); + + regs.SASR = wdregs + 3; + regs.SCMD = wdregs + 7; + + wd33c93_init(host, regs, dma_setup, dma_stop, WD33C93_FS_16_20); + + hdata->wh.no_sync = 0; + + if (request_irq(irq, sgiwd93_intr, 0, "SGI WD93", (void *) host)) { + printk(KERN_WARNING "sgiwd93: Could not register irq %d " + "for host %d.\n", irq, unit); + goto out_free; } - /* set up second controller on the Indigo2 */ - if(!sgi_guiness) { - sgiwd93_host1 = scsi_register(SGIblows, sizeof(struct WD33C93_hostdata)); - if(sgiwd93_host1 != NULL) - { - sgiwd93_host1->base = (unsigned long) hregs1; - sgiwd93_host1->irq = SGI_WD93_1_IRQ; - - buf = (uchar *) get_zeroed_page(GFP_KERNEL); - if (!buf) { - printk(KERN_WARNING "sgiwd93: Could not allocate memory for host1 buffer.\n"); - scsi_unregister(sgiwd93_host1); - called = 1; - return 1; /* We registered host0 so return success*/ - } - init_hpc_chain(buf); - - /* HPC_SCSI_REG1 | 0x03 | KSEG1 */ - regs.SASR = (unsigned char*) KSEG1ADDR(0x1fbc8003); - regs.SCMD = (unsigned char*) KSEG1ADDR(0x1fbc8007); - wd33c93_init(sgiwd93_host1, regs, dma_setup, dma_stop, - WD33C93_FS_16_20); - - hdata1 = (struct WD33C93_hostdata *)sgiwd93_host1->hostdata; - hdata1->no_sync = 0; - hdata1->dma_bounce_buffer = (uchar *) (KSEG1ADDR(buf)); - - if (request_irq(SGI_WD93_1_IRQ, sgiwd93_intr, 0, "SGI WD93", (void *) sgiwd93_host1)) { - printk(KERN_WARNING "sgiwd93: Could not allocate irq %d (for host1).\n", SGI_WD93_1_IRQ); - wd33c93_release(); - free_page((unsigned long)buf); - scsi_unregister(sgiwd93_host1); - /* Fall through since host0 registered OK */ - } - } + return host; + +out_free: + dma_free_coherent(NULL, PAGE_SIZE, hdata->hd.cpu, hdata->hd.dma); + wd33c93_release(); + +out_unregister: + scsi_unregister(host); + + return NULL; +} + +int __init sgiwd93_detect(Scsi_Host_Template *SGIblows) +{ + int found = 0; + + SGIblows->proc_name = "SGIWD93"; + sgiwd93_host = sgiwd93_setup_scsi(SGIblows, 0, SGI_WD93_0_IRQ, + &hpc3c0->scsi_chan0, + (unsigned char *)hpc3c0->scsi0_ext); + if (sgiwd93_host) + found++; + + /* Set up second controller on the Indigo2 */ + if (ip22_is_fullhouse()) { + sgiwd93_host1 = sgiwd93_setup_scsi(SGIblows, 1, SGI_WD93_1_IRQ, + &hpc3c0->scsi_chan1, + (unsigned char *)hpc3c0->scsi1_ext); + if (sgiwd93_host1) + found++; } - - called = 1; - return 1; /* Found one. */ + return found; } int sgiwd93_release(struct Scsi_Host *instance) { - free_irq(SGI_WD93_0_IRQ, sgiwd93_intr); - free_page(KSEG0ADDR(hdata->dma_bounce_buffer)); + struct ip22_hostdata *hdata = HDATA(instance); + int irq = 0; + + if (sgiwd93_host && sgiwd93_host == instance) + irq = SGI_WD93_0_IRQ; + else if (sgiwd93_host1 && sgiwd93_host1 == instance) + irq = SGI_WD93_1_IRQ; + + free_irq(irq, sgiwd93_intr); + dma_free_coherent(NULL, PAGE_SIZE, hdata->hd.cpu, hdata->hd.dma); wd33c93_release(); - if(!sgi_guiness) { - free_irq(SGI_WD93_1_IRQ, sgiwd93_intr); - free_page(KSEG0ADDR(hdata1->dma_bounce_buffer)); - wd33c93_release(); - } + return 1; } +static int sgiwd93_bus_reset(Scsi_Cmnd *cmd) +{ + /* FIXME perform bus-specific reset */ + wd33c93_host_reset(cmd); + return SUCCESS; +} + +/* + * Kludge alert - the SCSI code calls the abort and reset method with int + * arguments not with pointers. So this is going to blow up beautyfully + * on 64-bit systems with memory outside the compat address spaces. + */ static Scsi_Host_Template driver_template = { - .proc_name = "SGIWD93", - .name = "SGI WD93", - .detect = sgiwd93_detect, - .release = sgiwd93_release, - .queuecommand = wd33c93_queuecommand, - .abort = wd33c93_abort, - .reset = wd33c93_reset, - .can_queue = CAN_QUEUE, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = CMD_PER_LUN, - .use_clustering = DISABLE_CLUSTERING, + .proc_name = "SGIWD93", + .name = "SGI WD93", + .detect = sgiwd93_detect, + .release = sgiwd93_release, + .queuecommand = wd33c93_queuecommand, + .eh_abort_handler = wd33c93_abort, + .eh_bus_reset_handler = sgiwd93_bus_reset, + .eh_host_reset_handler = wd33c93_host_reset, + .can_queue = CAN_QUEUE, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = CMD_PER_LUN, + .use_clustering = DISABLE_CLUSTERING, }; #include "scsi_module.c" --- linux-2.6.6/drivers/scsi/sgiwd93.h 2003-09-08 13:58:58.000000000 -0700 +++ 25/drivers/scsi/sgiwd93.h 2004-05-10 01:19:16.817182456 -0700 @@ -19,6 +19,6 @@ int sgiwd93_release(struct Scsi_Host *in const char *wd33c93_info(void); int wd33c93_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int wd33c93_abort(Scsi_Cmnd *); -int wd33c93_reset(Scsi_Cmnd *, unsigned int); +int wd33c93_host_reset(Scsi_Cmnd * SCpnt); #endif /* !(_SGIWD93_H) */ --- linux-2.6.6/drivers/scsi/st.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/scsi/st.c 2004-05-10 01:19:04.917991408 -0700 @@ -17,7 +17,7 @@ Last modified: 18-JAN-1998 Richard Gooch Devfs support */ -static char *verstr = "20040318"; +static char *verstr = "20040403"; #include @@ -1031,7 +1031,8 @@ static int st_open(struct inode *inode, /* See that we have at least a one page buffer available */ if (!enlarge_buffer(STp->buffer, PAGE_SIZE, STp->restr_dma)) { - printk(KERN_WARNING "%s: Can't allocate tape buffer.\n", name); + printk(KERN_WARNING "%s: Can't allocate one page tape buffer.\n", + name); retval = (-EOVERFLOW); goto err_out; } @@ -1318,6 +1319,8 @@ static int setup_buffering(Scsi_Tape *ST bufsize = count; if (bufsize > STbp->buffer_size && !enlarge_buffer(STbp, bufsize, STp->restr_dma)) { + printk(KERN_WARNING "%s: Can't allocate %d byte tape buffer.\n", + tape_name(STp), bufsize); retval = (-EOVERFLOW); goto out; } @@ -1960,26 +1963,29 @@ static ssize_t +DEB( /* Set the driver options */ static void st_log_options(Scsi_Tape * STp, ST_mode * STm, char *name) { - printk(KERN_INFO - "%s: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n", - name, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes, - STm->do_read_ahead); - printk(KERN_INFO - "%s: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n", - name, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock); - printk(KERN_INFO - "%s: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n", - name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions, - STp->scsi2_logical); - printk(KERN_INFO - "%s: sysv: %d nowait: %d\n", name, STm->sysv, STp->immediate); - DEB(printk(KERN_INFO - "%s: debugging: %d\n", - name, debugging);) + if (debugging) { + printk(KERN_INFO + "%s: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n", + name, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes, + STm->do_read_ahead); + printk(KERN_INFO + "%s: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n", + name, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock); + printk(KERN_INFO + "%s: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n", + name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions, + STp->scsi2_logical); + printk(KERN_INFO + "%s: sysv: %d nowait: %d\n", name, STm->sysv, STp->immediate); + printk(KERN_INFO "%s: debugging: %d\n", + name, debugging); + } } + ) static int st_set_options(Scsi_Tape *STp, long options) @@ -2017,8 +2023,8 @@ static int st_set_options(Scsi_Tape *STp STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0; STp->immediate = (options & MT_ST_NOWAIT) != 0; STm->sysv = (options & MT_ST_SYSV) != 0; - DEB( debugging = (options & MT_ST_DEBUGGING) != 0; ) - st_log_options(STp, STm, name); + DEB( debugging = (options & MT_ST_DEBUGGING) != 0; + st_log_options(STp, STm, name); ) } else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) { value = (code == MT_ST_SETBOOLEANS); if ((options & MT_ST_BUFFER_WRITES) != 0) @@ -2050,19 +2056,19 @@ static int st_set_options(Scsi_Tape *STp STm->sysv = value; DEB( if ((options & MT_ST_DEBUGGING) != 0) - debugging = value; ) - st_log_options(STp, STm, name); + debugging = value; + st_log_options(STp, STm, name); ) } else if (code == MT_ST_WRITE_THRESHOLD) { /* Retained for compatibility */ } else if (code == MT_ST_DEF_BLKSIZE) { value = (options & ~MT_ST_OPTIONS); if (value == ~MT_ST_OPTIONS) { STm->default_blksize = (-1); - printk(KERN_INFO "%s: Default block size disabled.\n", name); + DEBC( printk(KERN_INFO "%s: Default block size disabled.\n", name)); } else { STm->default_blksize = value; - printk(KERN_INFO "%s: Default block size set to %d bytes.\n", - name, STm->default_blksize); + DEBC( printk(KERN_INFO "%s: Default block size set to %d bytes.\n", + name, STm->default_blksize)); if (STp->ready == ST_READY) { STp->blksize_changed = FALSE; set_mode_densblk(STp, STm); @@ -2072,12 +2078,12 @@ static int st_set_options(Scsi_Tape *STp value = (options & ~MT_ST_OPTIONS); if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) { STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ; - printk(KERN_INFO "%s: Long timeout set to %d seconds.\n", name, - (value & ~MT_ST_SET_LONG_TIMEOUT)); + DEBC( printk(KERN_INFO "%s: Long timeout set to %d seconds.\n", name, + (value & ~MT_ST_SET_LONG_TIMEOUT))); } else { STp->timeout = value * HZ; - printk(KERN_INFO "%s: Normal timeout set to %d seconds.\n", - name, value); + DEBC( printk(KERN_INFO "%s: Normal timeout set to %d seconds.\n", + name, value) ); } } else if (code == MT_ST_SET_CLN) { value = (options & ~MT_ST_OPTIONS) & 0xff; @@ -2096,12 +2102,12 @@ static int st_set_options(Scsi_Tape *STp if (code == MT_ST_DEF_DENSITY) { if (value == MT_ST_CLEAR_DEFAULT) { STm->default_density = (-1); - printk(KERN_INFO "%s: Density default disabled.\n", - name); + DEBC( printk(KERN_INFO "%s: Density default disabled.\n", + name)); } else { STm->default_density = value & 0xff; - printk(KERN_INFO "%s: Density default set to %x\n", - name, STm->default_density); + DEBC( printk(KERN_INFO "%s: Density default set to %x\n", + name, STm->default_density)); if (STp->ready == ST_READY) { STp->density_changed = FALSE; set_mode_densblk(STp, STm); @@ -2110,31 +2116,31 @@ static int st_set_options(Scsi_Tape *STp } else if (code == MT_ST_DEF_DRVBUFFER) { if (value == MT_ST_CLEAR_DEFAULT) { STp->default_drvbuffer = 0xff; - printk(KERN_INFO - "%s: Drive buffer default disabled.\n", name); + DEBC( printk(KERN_INFO + "%s: Drive buffer default disabled.\n", name)); } else { STp->default_drvbuffer = value & 7; - printk(KERN_INFO + DEBC( printk(KERN_INFO "%s: Drive buffer default set to %x\n", - name, STp->default_drvbuffer); + name, STp->default_drvbuffer)); if (STp->ready == ST_READY) st_int_ioctl(STp, MTSETDRVBUFFER, STp->default_drvbuffer); } } else if (code == MT_ST_DEF_COMPRESSION) { if (value == MT_ST_CLEAR_DEFAULT) { STm->default_compression = ST_DONT_TOUCH; - printk(KERN_INFO - "%s: Compression default disabled.\n", name); + DEBC( printk(KERN_INFO + "%s: Compression default disabled.\n", name)); } else { if ((value & 0xff00) != 0) { STp->c_algo = (value & 0xff00) >> 8; - printk(KERN_INFO "%s: Compression algorithm set to 0x%x.\n", - name, STp->c_algo); + DEBC( printk(KERN_INFO "%s: Compression algorithm set to 0x%x.\n", + name, STp->c_algo)); } if ((value & 0xff) != 0xff) { STm->default_compression = (value & 1 ? ST_YES : ST_NO); - printk(KERN_INFO "%s: Compression default set to %x\n", - name, (value & 1)); + DEBC( printk(KERN_INFO "%s: Compression default set to %x\n", + name, (value & 1))); if (STp->ready == ST_READY) { STp->compression_changed = FALSE; st_compression(STp, (STm->default_compression == ST_YES)); @@ -3465,7 +3471,7 @@ static int enlarge_buffer(ST_buffer * ST if (nbr <= 0) return FALSE; - priority = GFP_KERNEL; + priority = GFP_KERNEL | __GFP_NOWARN; if (need_dma) priority |= GFP_DMA; for (b_size = PAGE_SIZE, order=0; @@ -3482,8 +3488,6 @@ static int enlarge_buffer(ST_buffer * ST order--; continue; } - printk(KERN_NOTICE "st: failed to enlarge buffer to %d bytes.\n", - new_size); DEB(STbuffer->buffer_size = got); normalize_buffer(STbuffer); return FALSE; @@ -3495,9 +3499,6 @@ static int enlarge_buffer(ST_buffer * ST segs++; } STbuffer->b_data = page_address(STbuffer->frp[0].page); - DEBC(printk(ST_DEB_MSG - "st: Succeeded to enlarge buffer at %p to %d bytes (segs %d->%d, %d).\n", - STbuffer, got, STbuffer->orig_frp_segs, STbuffer->frp_segs, b_size)); return TRUE; } @@ -3513,11 +3514,6 @@ static void normalize_buffer(ST_buffer * __free_pages(STbuffer->frp[i].page, order); STbuffer->buffer_size -= STbuffer->frp[i].length; } - DEB( - if (debugging && STbuffer->orig_frp_segs < STbuffer->frp_segs) - printk(ST_DEB_MSG "st: Buffer at %p normalized to %d bytes (segs %d->%d).\n", - STbuffer, STbuffer->buffer_size, STbuffer->frp_segs, STbuffer->orig_frp_segs); - ) /* end DEB */ STbuffer->frp_segs = STbuffer->orig_frp_segs; STbuffer->frp_sg_current = 0; } @@ -3547,11 +3543,9 @@ static int append_to_buffer(const char * ubp += cnt; offset = 0; } - if (do_count) { /* Should never happen */ - printk(KERN_WARNING "st: append_to_buffer overflow (left %d).\n", - do_count); + if (do_count) /* Should never happen */ return (-EIO); - } + return 0; } @@ -3581,11 +3575,9 @@ static int from_buffer(ST_buffer * st_bp ubp += cnt; offset = 0; } - if (do_count) { /* Should never happen */ - printk(KERN_WARNING "st: from_buffer overflow (left %d).\n", - do_count); + if (do_count) /* Should never happen */ return (-EIO); - } + return 0; } @@ -3606,10 +3598,6 @@ static void move_buffer_data(ST_buffer * break; offset -= st_bp->frp[src_seg].length; } - if (src_seg == st_bp->frp_segs) { /* Should never happen */ - printk(KERN_WARNING "st: move_buffer offset overflow.\n"); - return; - } st_bp->buffer_bytes = st_bp->read_pointer = total; for (dst_seg=dst_offset=0; total > 0; ) { --- linux-2.6.6/drivers/scsi/sym53c8xx_comm.h 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/scsi/sym53c8xx_comm.h 2004-05-10 01:19:04.918991256 -0700 @@ -59,12 +59,9 @@ ** sym53c8xx and ncr53c8xx drivers should share. ** The sharing will be achieved in a further version ** of the driver bundle. For now, only the ncr53c8xx -** driver includes this file. +** driver includes this file. */ -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) - /*========================================================== ** ** Hmmm... What complex some PCI-HOST bridges actually --- linux-2.6.6/drivers/serial/68360serial.c 2004-03-10 20:41:30.000000000 -0800 +++ 25/drivers/serial/68360serial.c 2004-05-10 01:19:50.227103376 -0700 @@ -1650,7 +1650,6 @@ static void rs_360_close(struct tty_stru if (tty_hung_up_p(filp)) { DBG_CNT("before DEC-hung"); - MOD_DEC_USE_COUNT; local_irq_restore(flags); return; } @@ -1677,7 +1676,6 @@ static void rs_360_close(struct tty_stru } if (state->count) { DBG_CNT("before DEC-2"); - MOD_DEC_USE_COUNT; local_irq_restore(flags); return; } @@ -1732,7 +1730,6 @@ static void rs_360_close(struct tty_stru } info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); wake_up_interruptible(&info->close_wait); - MOD_DEC_USE_COUNT; local_irq_restore(flags); } @@ -1993,14 +1990,12 @@ static int rs_360_open(struct tty_struct if (retval) return retval; - MOD_INC_USE_COUNT; retval = block_til_ready(tty, filp, info); if (retval) { #ifdef SERIAL_DEBUG_OPEN printk("rs_open returning after block_til_ready with %d\n", retval); #endif - MOD_DEC_USE_COUNT; return retval; } @@ -2476,6 +2471,7 @@ long console_360_init(long kmem_start, l static int baud_idx; static struct tty_operations rs_360_ops = { + .owner = THIS_MODULE, .open = rs_360_open, .close = rs_360_close, .write = rs_360_write, --- linux-2.6.6/drivers/serial/8250.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/serial/8250.c 2004-05-10 01:19:06.888691816 -0700 @@ -832,7 +832,7 @@ receive_chars(struct uart_8250_port *up, if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { tty->flip.work.func((void *)tty); if (tty->flip.count >= TTY_FLIPBUF_SIZE) - return; // if TTY_DONT_FLIP is set + return; /* if TTY_DONT_FLIP is set */ } ch = serial_inp(up, UART_RX); *tty->flip.char_buf_ptr = ch; @@ -1193,12 +1193,21 @@ static void serial8250_break_ctl(struct spin_unlock_irqrestore(&up->port.lock, flags); } +#ifdef CONFIG_KGDB +static int kgdb_irq = -1; +#endif + static int serial8250_startup(struct uart_port *port) { struct uart_8250_port *up = (struct uart_8250_port *)port; unsigned long flags; int retval; +#ifdef CONFIG_KGDB + if (up->port.irq == kgdb_irq) + return -EBUSY; +#endif + up->capabilities = uart_config[up->port.type].flags; up->mcr = 0; @@ -1888,6 +1897,10 @@ static void __init serial8250_register_p for (i = 0; i < UART_NR; i++) { struct uart_8250_port *up = &serial8250_ports[i]; +#ifdef CONFIG_KGDB + if (up->port.irq == kgdb_irq) + up->port.kgdb = 1; +#endif up->port.line = i; up->port.ops = &serial8250_pops; init_timer(&up->timer); @@ -2171,6 +2184,31 @@ void serial8250_resume_port(int line) uart_resume_port(&serial8250_reg, &serial8250_ports[line].port); } +#ifdef CONFIG_KGDB +/* + * Find all the ports using the given irq and shut them down. + * Result should be that the irq will be released. + */ +void shutdown_for_kgdb(struct async_struct * info) +{ + int irq = info->state->irq; + struct uart_8250_port *up; + int ttyS; + + kgdb_irq = irq; /* save for later init */ + for (ttyS = 0; ttyS < UART_NR; ttyS++){ + up = &serial8250_ports[ttyS]; + if (up->port.irq == irq && (irq_lists + irq)->head) { +#ifdef CONFIG_DEBUG_SPINLOCK /* ugly business... */ + if(up->port.lock.magic != SPINLOCK_MAGIC) + spin_lock_init(&up->port.lock); +#endif + serial8250_shutdown(&up->port); + } + } +} +#endif /* CONFIG_KGDB */ + static int __init serial8250_init(void) { int ret, i; --- linux-2.6.6/drivers/serial/serial_core.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/serial/serial_core.c 2004-05-10 01:19:06.890691512 -0700 @@ -1985,6 +1985,11 @@ uart_configure_port(struct uart_driver * { unsigned int flags; +#ifdef CONFIG_KGDB + if (port->kgdb) + return; +#endif + /* * If there isn't a port here, don't do anything further. */ --- linux-2.6.6/drivers/serial/sh-sci.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/serial/sh-sci.c 2004-05-10 01:19:01.798465648 -0700 @@ -758,7 +758,8 @@ static int sci_notifier(struct notifier_ struct cpufreq_freqs *freqs = p; int i; - if (phase == CPUFREQ_POSTCHANGE) { + if ((phase == CPUFREQ_POSTCHANGE) || + (phase == CPUFREQ_RESUMECHANGE)){ for (i = 0; i < SCI_NPORTS; i++) { struct uart_port *port = &sci_ports[i]; --- linux-2.6.6/drivers/telephony/ixj.h 2004-03-10 20:41:30.000000000 -0800 +++ 25/drivers/telephony/ixj.h 2004-05-10 01:20:01.764349448 -0700 @@ -1198,22 +1198,13 @@ typedef struct { int aec_level; int cid_play_aec_level; int readers, writers; -#if LINUX_VERSION_CODE < 0x020400 - struct wait_queue *poll_q; - struct wait_queue *read_q; -#else wait_queue_head_t poll_q; wait_queue_head_t read_q; -#endif char *read_buffer, *read_buffer_end; char *read_convert_buffer; size_t read_buffer_size; unsigned int read_buffer_ready; -#if LINUX_VERSION_CODE < 0x020400 - struct wait_queue *write_q; -#else wait_queue_head_t write_q; -#endif char *write_buffer, *write_buffer_end; char *write_convert_buffer; size_t write_buffer_size; --- linux-2.6.6/drivers/usb/core/config.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/core/config.c 2004-05-10 01:19:05.763862816 -0700 @@ -96,19 +96,14 @@ static int usb_parse_endpoint(struct dev return buffer - buffer0 + i; } -static void usb_free_intf(struct usb_interface *intf) +static void usb_release_interface_cache(struct kref *ref) { + struct usb_interface_cache *intfc = ref_to_usb_interface_cache(ref); int j; - if (intf->altsetting) { - for (j = 0; j < intf->num_altsetting; j++) { - struct usb_host_interface *alt = &intf->altsetting[j]; - - kfree(alt->endpoint); - } - kfree(intf->altsetting); - } - kfree(intf); + for (j = 0; j < intfc->num_altsetting; j++) + kfree(intfc->altsetting[j].endpoint); + kfree(intfc); } static int usb_parse_interface(struct device *ddev, int cfgno, @@ -117,7 +112,7 @@ static int usb_parse_interface(struct de unsigned char *buffer0 = buffer; struct usb_interface_descriptor *d; int inum, asnum; - struct usb_interface *interface; + struct usb_interface_cache *intfc; struct usb_host_interface *alt; int i, n; int len, retval; @@ -137,16 +132,16 @@ static int usb_parse_interface(struct de if (inum >= config->desc.bNumInterfaces) goto skip_to_next_interface_descriptor; - interface = config->interface[inum]; + intfc = config->intf_cache[inum]; asnum = d->bAlternateSetting; - if (asnum >= interface->num_altsetting) { + if (asnum >= intfc->num_altsetting) { dev_err(ddev, "config %d interface %d has an invalid " "alternate setting number: %d but max is %d\n", - cfgno, inum, asnum, interface->num_altsetting - 1); + cfgno, inum, asnum, intfc->num_altsetting - 1); return -EINVAL; } - alt = &interface->altsetting[asnum]; + alt = &intfc->altsetting[asnum]; if (alt->desc.bLength) { dev_err(ddev, "Duplicate descriptor for config %d " "interface %d altsetting %d\n", cfgno, inum, asnum); @@ -210,11 +205,12 @@ int usb_parse_configuration(struct devic int cfgno; int nintf, nintf_orig; int i, j, n; - struct usb_interface *interface; + struct usb_interface_cache *intfc; unsigned char *buffer2; int size2; struct usb_descriptor_header *header; int len, retval; + u8 nalts[USB_MAXINTERFACES]; memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE); if (config->desc.bDescriptorType != USB_DT_CONFIG || @@ -237,14 +233,7 @@ int usb_parse_configuration(struct devic cfgno, nintf, USB_MAXINTERFACES); config->desc.bNumInterfaces = nintf = USB_MAXINTERFACES; } - - for (i = 0; i < nintf; ++i) { - interface = config->interface[i] = - kmalloc(sizeof(struct usb_interface), GFP_KERNEL); - if (!interface) - return -ENOMEM; - memset(interface, 0, sizeof(struct usb_interface)); - } + memset(nalts, 0, nintf); /* Go through the descriptors, checking their length and counting the * number of altsettings for each interface */ @@ -277,8 +266,8 @@ int usb_parse_configuration(struct devic cfgno, i, nintf_orig - 1); return -EINVAL; } - if (i < nintf) - ++config->interface[i]->num_altsetting; + if (i < nintf && nalts[i] < 255) + ++nalts[i]; } else if (header->bDescriptorType == USB_DT_DEVICE || header->bDescriptorType == USB_DT_CONFIG) { @@ -290,29 +279,29 @@ int usb_parse_configuration(struct devic } /* for ((buffer2 = buffer, size2 = size); ...) */ - /* Allocate the altsetting arrays */ + /* Allocate the usb_interface_caches and altsetting arrays */ for (i = 0; i < nintf; ++i) { - interface = config->interface[i]; - if (interface->num_altsetting > USB_MAXALTSETTING) { + j = nalts[i]; + if (j > USB_MAXALTSETTING) { dev_err(ddev, "too many alternate settings for " "config %d interface %d: %d, " "maximum allowed: %d\n", - cfgno, i, interface->num_altsetting, - USB_MAXALTSETTING); + cfgno, i, j, USB_MAXALTSETTING); return -EINVAL; } - if (interface->num_altsetting == 0) { + if (j == 0) { dev_err(ddev, "config %d has no interface number " "%d\n", cfgno, i); return -EINVAL; } - len = sizeof(*interface->altsetting) * - interface->num_altsetting; - interface->altsetting = kmalloc(len, GFP_KERNEL); - if (!interface->altsetting) + len = sizeof(*intfc) + sizeof(struct usb_host_interface) * j; + config->intf_cache[i] = intfc = kmalloc(len, GFP_KERNEL); + if (!intfc) return -ENOMEM; - memset(interface->altsetting, 0, len); + memset(intfc, 0, len); + intfc->num_altsetting = j; + kref_init(&intfc->ref, usb_release_interface_cache); } /* Skip over any Class Specific or Vendor Specific descriptors; @@ -340,9 +329,9 @@ int usb_parse_configuration(struct devic /* Check for missing altsettings */ for (i = 0; i < nintf; ++i) { - interface = config->interface[i]; - for (j = 0; j < interface->num_altsetting; ++j) { - if (!interface->altsetting[j].desc.bLength) { + intfc = config->intf_cache[i]; + for (j = 0; j < intfc->num_altsetting; ++j) { + if (!intfc->altsetting[j].desc.bLength) { dev_err(ddev, "config %d interface %d has no " "altsetting %d\n", cfgno, i, j); return -EINVAL; @@ -374,10 +363,8 @@ void usb_destroy_configuration(struct us struct usb_host_config *cf = &dev->config[c]; for (i = 0; i < cf->desc.bNumInterfaces; i++) { - struct usb_interface *ifp = cf->interface[i]; - - if (ifp) - usb_free_intf(ifp); + if (cf->intf_cache[i]) + kref_put(&cf->intf_cache[i]->ref); } } kfree(dev->config); --- linux-2.6.6/drivers/usb/core/devices.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/core/devices.c 2004-05-10 01:19:05.765862512 -0700 @@ -232,13 +232,21 @@ static char *usb_dump_endpoint_descripto return start; } -static char *usb_dump_interface_descriptor(char *start, char *end, const struct usb_interface *iface, int setno) +static char *usb_dump_interface_descriptor(char *start, char *end, + const struct usb_interface_cache *intfc, + const struct usb_interface *iface, + int setno) { - struct usb_interface_descriptor *desc = &iface->altsetting[setno].desc; + const struct usb_interface_descriptor *desc = &intfc->altsetting[setno].desc; + char *driver_name = ""; if (start > end) return start; down_read(&usb_bus_type.subsys.rwsem); + if (iface) + driver_name = (iface->dev.driver + ? iface->dev.driver->name + : "(none)"); start += sprintf(start, format_iface, desc->bInterfaceNumber, desc->bAlternateSetting, @@ -247,9 +255,7 @@ static char *usb_dump_interface_descript class_decode(desc->bInterfaceClass), desc->bInterfaceSubClass, desc->bInterfaceProtocol, - iface->dev.driver - ? iface->dev.driver->name - : "(none)"); + driver_name); up_read(&usb_bus_type.subsys.rwsem); return start; } @@ -258,13 +264,14 @@ static char *usb_dump_interface( int speed, char *start, char *end, + const struct usb_interface_cache *intfc, const struct usb_interface *iface, int setno ) { - struct usb_host_interface *desc = &iface->altsetting[setno]; + const struct usb_host_interface *desc = &intfc->altsetting[setno]; int i; - start = usb_dump_interface_descriptor(start, end, iface, setno); + start = usb_dump_interface_descriptor(start, end, intfc, iface, setno); for (i = 0; i < desc->desc.bNumEndpoints; i++) { if (start > end) return start; @@ -303,6 +310,7 @@ static char *usb_dump_config ( ) { int i, j; + struct usb_interface_cache *intfc; struct usb_interface *interface; if (start > end) @@ -311,14 +319,13 @@ static char *usb_dump_config ( return start + sprintf(start, "(null Cfg. desc.)\n"); start = usb_dump_config_descriptor(start, end, &config->desc, active); for (i = 0; i < config->desc.bNumInterfaces; i++) { + intfc = config->intf_cache[i]; interface = config->interface[i]; - if (!interface) - break; - for (j = 0; j < interface->num_altsetting; j++) { + for (j = 0; j < intfc->num_altsetting; j++) { if (start > end) return start; start = usb_dump_interface(speed, - start, end, interface, j); + start, end, intfc, interface, j); } } return start; @@ -395,7 +402,7 @@ static char *usb_dump_desc(char *start, return start; start = usb_dump_device_strings (start, end, dev); - + for (i = 0; i < dev->descriptor.bNumConfigurations; i++) { if (start > end) return start; @@ -445,6 +452,7 @@ static char *usb_dump_string(char *start * nbytes - the maximum number of bytes to write * skip_bytes - the number of bytes to skip before writing anything * file_offset - the offset into the devices file on completion + * The caller must own the usbdev->serialize semaphore. */ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, loff_t *skip_bytes, loff_t *file_offset, struct usb_device *usbdev, struct usb_bus *bus, int level, int index, int count) @@ -545,9 +553,13 @@ static ssize_t usb_device_dump(char __us /* Now look at all of this device's children. */ for (chix = 0; chix < usbdev->maxchild; chix++) { - if (usbdev->children[chix]) { - ret = usb_device_dump(buffer, nbytes, skip_bytes, file_offset, usbdev->children[chix], + struct usb_device *childdev = usbdev->children[chix]; + + if (childdev) { + down(&childdev->serialize); + ret = usb_device_dump(buffer, nbytes, skip_bytes, file_offset, childdev, bus, level + 1, chix, ++cnt); + up(&childdev->serialize); if (ret == -EFAULT) return total_written; total_written += ret; @@ -575,8 +587,11 @@ static ssize_t usb_device_read(struct fi for (buslist = usb_bus_list.next; buslist != &usb_bus_list; buslist = buslist->next) { /* print devices for this bus */ bus = list_entry(buslist, struct usb_bus, bus_list); + /* recurse through all children of the root hub */ + down(&bus->root_hub->serialize); ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0); + up(&bus->root_hub->serialize); if (ret < 0) { up(&usb_bus_list_lock); return ret; --- linux-2.6.6/drivers/usb/core/devio.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/core/devio.c 2004-05-10 01:19:05.767862208 -0700 @@ -60,6 +60,11 @@ struct async { struct urb *urb; }; +static inline int connected (struct usb_device *dev) +{ + return dev->state != USB_STATE_NOTATTACHED; +} + static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig) { loff_t ret; @@ -87,14 +92,15 @@ static loff_t usbdev_lseek(struct file * static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) { struct dev_state *ps = (struct dev_state *)file->private_data; + struct usb_device *dev = ps->dev; ssize_t ret = 0; unsigned len; loff_t pos; int i; pos = *ppos; - down_read(&ps->devsem); - if (!ps->dev) { + down(&dev->serialize); + if (!connected(dev)) { ret = -ENODEV; goto err; } else if (pos < 0) { @@ -106,7 +112,7 @@ static ssize_t usbdev_read(struct file * len = sizeof(struct usb_device_descriptor) - pos; if (len > nbytes) len = nbytes; - if (copy_to_user(buf, ((char *)&ps->dev->descriptor) + pos, len)) { + if (copy_to_user(buf, ((char *)&dev->descriptor) + pos, len)) { ret = -EFAULT; goto err; } @@ -118,9 +124,9 @@ static ssize_t usbdev_read(struct file * } pos = sizeof(struct usb_device_descriptor); - for (i = 0; nbytes && i < ps->dev->descriptor.bNumConfigurations; i++) { + for (i = 0; nbytes && i < dev->descriptor.bNumConfigurations; i++) { struct usb_config_descriptor *config = - (struct usb_config_descriptor *)ps->dev->rawdescriptors[i]; + (struct usb_config_descriptor *)dev->rawdescriptors[i]; unsigned int length = le16_to_cpu(config->wTotalLength); if (*ppos < pos + length) { @@ -128,7 +134,7 @@ static ssize_t usbdev_read(struct file * /* The descriptor may claim to be longer than it * really is. Here is the actual allocated length. */ unsigned alloclen = - ps->dev->config[i].desc.wTotalLength; + dev->config[i].desc.wTotalLength; len = length - (*ppos - pos); if (len > nbytes) @@ -138,7 +144,7 @@ static ssize_t usbdev_read(struct file * if (alloclen > (*ppos - pos)) { alloclen -= (*ppos - pos); if (copy_to_user(buf, - ps->dev->rawdescriptors[i] + (*ppos - pos), + dev->rawdescriptors[i] + (*ppos - pos), min(len, alloclen))) { ret = -EFAULT; goto err; @@ -155,35 +161,10 @@ static ssize_t usbdev_read(struct file * } err: - up_read(&ps->devsem); + up(&dev->serialize); return ret; } -extern inline unsigned int ld2(unsigned int x) -{ - unsigned int r = 0; - - if (x >= 0x10000) { - x >>= 16; - r += 16; - } - if (x >= 0x100) { - x >>= 8; - r += 8; - } - if (x >= 0x10) { - x >>= 4; - r += 4; - } - if (x >= 4) { - x >>= 2; - r += 2; - } - if (x >= 2) - r++; - return r; -} - /* * async list handling */ @@ -213,7 +194,7 @@ static void free_async(struct async *as) kfree(as); } -extern __inline__ void async_newpending(struct async *as) +static inline void async_newpending(struct async *as) { struct dev_state *ps = as->ps; unsigned long flags; @@ -223,7 +204,7 @@ extern __inline__ void async_newpending( spin_unlock_irqrestore(&ps->lock, flags); } -extern __inline__ void async_removepending(struct async *as) +static inline void async_removepending(struct async *as) { struct dev_state *ps = as->ps; unsigned long flags; @@ -233,7 +214,7 @@ extern __inline__ void async_removependi spin_unlock_irqrestore(&ps->lock, flags); } -extern __inline__ struct async *async_getcompleted(struct dev_state *ps) +static inline struct async *async_getcompleted(struct dev_state *ps) { unsigned long flags; struct async *as = NULL; @@ -247,7 +228,7 @@ extern __inline__ struct async *async_ge return as; } -extern __inline__ struct async *async_getpending(struct dev_state *ps, void __user *userurb) +static inline struct async *async_getpending(struct dev_state *ps, void __user *userurb) { unsigned long flags; struct async *as; @@ -315,7 +296,7 @@ static void destroy_async_on_interface ( destroy_async(ps, &hitlist); } -extern __inline__ void destroy_all_async(struct dev_state *ps) +static inline void destroy_all_async(struct dev_state *ps) { destroy_async(ps, &ps->async_pending); } @@ -335,6 +316,7 @@ static int driver_probe (struct usb_inte static void driver_disconnect(struct usb_interface *intf) { struct dev_state *ps = usb_get_intfdata (intf); + unsigned int ifnum = intf->altsetting->desc.bInterfaceNumber; if (!ps) return; @@ -343,13 +325,15 @@ static void driver_disconnect(struct usb * all pending I/O requests; 2.6 does that. */ - /* prevent new I/O requests */ - ps->dev = 0; - clear_bit(intf->cur_altsetting->desc.bInterfaceNumber, &ps->ifclaimed); + if (likely(ifnum < 8*sizeof(ps->ifclaimed))) + clear_bit(ifnum, &ps->ifclaimed); + else + warn("interface number %u out of range", ifnum); + usb_set_intfdata (intf, NULL); /* force async requests to complete */ - destroy_all_async (ps); + destroy_async_on_interface(ps, ifnum); } struct usb_driver usbdevfs_driver = { @@ -365,7 +349,7 @@ static int claimintf(struct dev_state *p struct usb_interface *iface; int err; - if (intf >= 8*sizeof(ps->ifclaimed) || !dev + if (intf >= 8*sizeof(ps->ifclaimed) || intf >= dev->actconfig->desc.bNumInterfaces) return -EINVAL; /* already claimed */ @@ -395,7 +379,6 @@ static int releaseintf(struct dev_state return -EINVAL; err = -EINVAL; dev = ps->dev; - down(&dev->serialize); /* lock against other changes to driver bindings */ down_write(&usb_bus_type.subsys.rwsem); if (test_and_clear_bit(intf, &ps->ifclaimed)) { @@ -404,7 +387,6 @@ static int releaseintf(struct dev_state err = 0; } up_write(&usb_bus_type.subsys.rwsem); - up(&dev->serialize); return err; } @@ -506,7 +488,7 @@ static int usbdev_open(struct inode *ino lock_kernel(); ret = -ENOENT; - dev = inode->u.generic_ip; + dev = usb_get_dev(inode->u.generic_ip); if (!dev) { kfree(ps); goto out; @@ -518,7 +500,6 @@ static int usbdev_open(struct inode *ino INIT_LIST_HEAD(&ps->async_pending); INIT_LIST_HEAD(&ps->async_completed); init_waitqueue_head(&ps->wait); - init_rwsem(&ps->devsem); ps->discsignr = 0; ps->disctask = current; ps->disccontext = NULL; @@ -535,18 +516,21 @@ static int usbdev_open(struct inode *ino static int usbdev_release(struct inode *inode, struct file *file) { struct dev_state *ps = (struct dev_state *)file->private_data; + struct usb_device *dev = ps->dev; unsigned int i; - lock_kernel(); + down(&dev->serialize); list_del_init(&ps->list); - if (ps->dev) { + if (connected(dev)) { for (i = 0; ps->ifclaimed && i < 8*sizeof(ps->ifclaimed); i++) if (test_bit(i, &ps->ifclaimed)) releaseintf(ps, i); + destroy_all_async(ps); } - unlock_kernel(); - destroy_all_async(ps); + up(&dev->serialize); + usb_put_dev(dev); + ps->dev = NULL; kfree(ps); return 0; } @@ -702,13 +686,15 @@ static int proc_getdriver(struct dev_sta return -EFAULT; if ((ret = findintfif(ps->dev, gd.interface)) < 0) return ret; + down_read(&usb_bus_type.subsys.rwsem); interface = ps->dev->actconfig->interface[ret]; - if (!interface->dev.driver) + if (!interface || !interface->dev.driver) { + up_read(&usb_bus_type.subsys.rwsem); return -ENODATA; + } strncpy(gd.driver, interface->dev.driver->name, sizeof(gd.driver)); - if (copy_to_user(arg, &gd, sizeof(gd))) - return -EFAULT; - return 0; + up_read(&usb_bus_type.subsys.rwsem); + return copy_to_user(arg, &gd, sizeof(gd)) ? -EFAULT : 0; } static int proc_connectinfo(struct dev_state *ps, void __user *arg) @@ -724,9 +710,6 @@ static int proc_connectinfo(struct dev_s static int proc_resetdevice(struct dev_state *ps) { - /* FIXME when usb_reset_device() is fixed we'll need to grab - * ps->dev->serialize before calling it. - */ return usb_reset_device(ps->dev); } @@ -742,10 +725,8 @@ static int proc_setintf(struct dev_state if ((ret = findintfif(ps->dev, setintf.interface)) < 0) return ret; interface = ps->dev->actconfig->interface[ret]; - if (interface->dev.driver) { - if ((ret = checkintf(ps, ret))) - return ret; - } + if ((ret = checkintf(ps, ret))) + return ret; if (usb_set_interface(ps->dev, setintf.interface, setintf.altsetting)) return -EINVAL; return 0; @@ -760,7 +741,6 @@ static int proc_setconfig(struct dev_sta if (get_user(u, (unsigned int __user *)arg)) return -EFAULT; - down(&ps->dev->serialize); actconfig = ps->dev->actconfig; /* Don't touch the device if any interfaces are claimed. @@ -796,7 +776,6 @@ static int proc_setconfig(struct dev_sta else status = usb_set_configuration(ps->dev, u); } - up(&ps->dev->serialize); return status; } @@ -873,6 +852,9 @@ static int proc_submiturb(struct dev_sta /* arbitrary limit */ if (uurb.number_of_packets < 1 || uurb.number_of_packets > 128) return -EINVAL; + if (!(ep_desc = usb_epnum_to_ep_desc(ps->dev, uurb.endpoint))) + return -ENOENT; + interval = 1 << min (15, ep_desc->bInterval - 1); isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb.number_of_packets; if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL))) return -ENOMEM; @@ -898,7 +880,10 @@ static int proc_submiturb(struct dev_sta uurb.number_of_packets = 0; if (!(ep_desc = usb_epnum_to_ep_desc(ps->dev, uurb.endpoint))) return -ENOENT; - interval = ep_desc->bInterval; + if (ps->dev->speed == USB_SPEED_HIGH) + interval = 1 << min (15, ep_desc->bInterval - 1); + else + interval = ep_desc->bInterval; if (uurb.buffer_length > 16384) return -EINVAL; if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length)) @@ -1012,18 +997,19 @@ static int proc_reapurb(struct dev_state DECLARE_WAITQUEUE(wait, current); struct async *as = NULL; void __user *addr; + struct usb_device *dev = ps->dev; int ret; add_wait_queue(&ps->wait, &wait); - while (ps->dev) { + while (connected(dev)) { __set_current_state(TASK_INTERRUPTIBLE); if ((as = async_getcompleted(ps))) break; if (signal_pending(current)) break; - up_read(&ps->devsem); + up(&dev->serialize); schedule(); - down_read(&ps->devsem); + down(&dev->serialize); } remove_wait_queue(&ps->wait, &wait); set_current_state(TASK_RUNNING); @@ -1125,13 +1111,12 @@ static int proc_ioctl (struct dev_state } } - if (!ps->dev) { + if (!connected(ps->dev)) { if (buf) kfree(buf); return -ENODEV; } - down(&ps->dev->serialize); if (ps->dev->state != USB_STATE_CONFIGURED) retval = -ENODEV; else if (!(ifp = usb_ifnum_to_if (ps->dev, ctrl.ifno))) @@ -1169,7 +1154,6 @@ static int proc_ioctl (struct dev_state } up_read(&usb_bus_type.subsys.rwsem); } - up(&ps->dev->serialize); /* cleanup and return */ if (retval >= 0 @@ -1190,13 +1174,14 @@ static int proc_ioctl (struct dev_state static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct dev_state *ps = (struct dev_state *)file->private_data; + struct usb_device *dev = ps->dev; int ret = -ENOTTY; if (!(file->f_mode & FMODE_WRITE)) return -EPERM; - down_read(&ps->devsem); - if (!ps->dev) { - up_read(&ps->devsem); + down(&dev->serialize); + if (!connected(dev)) { + up(&dev->serialize); return -ENODEV; } switch (cmd) { @@ -1278,7 +1263,7 @@ static int usbdev_ioctl(struct inode *in ret = proc_ioctl(ps, (void __user *) arg); break; } - up_read(&ps->devsem); + up(&dev->serialize); if (ret >= 0) inode->i_atime = CURRENT_TIME; return ret; @@ -1293,7 +1278,7 @@ static unsigned int usbdev_poll(struct f poll_wait(file, &ps->wait, wait); if (file->f_mode & FMODE_WRITE && !list_empty(&ps->async_completed)) mask |= POLLOUT | POLLWRNORM; - if (!ps->dev) + if (!connected(ps->dev)) mask |= POLLERR | POLLHUP; return mask; } --- linux-2.6.6/drivers/usb/core/hcd.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/core/hcd.c 2004-05-10 01:19:05.770861752 -0700 @@ -171,10 +171,10 @@ static const u8 fs_rh_config_descriptor 0x01, /* __u8 bNumInterfaces; (1) */ 0x01, /* __u8 bConfigurationValue; */ 0x00, /* __u8 iConfiguration; */ - 0x40, /* __u8 bmAttributes; - Bit 7: Bus-powered, + 0xc0, /* __u8 bmAttributes; + Bit 7: must be set, 6: Self-powered, - 5 Remote-wakwup, + 5: Remote wakeup, 4..0: resvd */ 0x00, /* __u8 MaxPower; */ @@ -218,10 +218,10 @@ static const u8 hs_rh_config_descriptor 0x01, /* __u8 bNumInterfaces; (1) */ 0x01, /* __u8 bConfigurationValue; */ 0x00, /* __u8 iConfiguration; */ - 0x40, /* __u8 bmAttributes; - Bit 7: Bus-powered, + 0xc0, /* __u8 bmAttributes; + Bit 7: must be set, 6: Self-powered, - 5 Remote-wakwup, + 5: Remote wakeup, 4..0: resvd */ 0x00, /* __u8 MaxPower; */ @@ -324,13 +324,15 @@ static int rh_string ( /* Root hub control transfers execute synchronously */ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) { - struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *) urb->setup_packet; + struct usb_ctrlrequest *cmd; u16 typeReq, wValue, wIndex, wLength; const u8 *bufp = 0; u8 *ubuf = urb->transfer_buffer; int len = 0; + int patch_wakeup = 0; unsigned long flags; + cmd = (struct usb_ctrlrequest *) urb->setup_packet; typeReq = (cmd->bRequestType << 8) | cmd->bRequest; wValue = le16_to_cpu (cmd->wValue); wIndex = le16_to_cpu (cmd->wIndex); @@ -347,13 +349,21 @@ static int rh_call_control (struct usb_h /* DEVICE REQUESTS */ case DeviceRequest | USB_REQ_GET_STATUS: - // DEVICE_REMOTE_WAKEUP - ubuf [0] = 1; // selfpowered + ubuf [0] = (hcd->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP) + | (1 << USB_DEVICE_SELF_POWERED); ubuf [1] = 0; - /* FALLTHROUGH */ + break; case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: + if (wValue == USB_DEVICE_REMOTE_WAKEUP) + hcd->remote_wakeup = 0; + else + goto error; + break; case DeviceOutRequest | USB_REQ_SET_FEATURE: - dev_dbg (hcd->self.controller, "no device features yet yet\n"); + if (hcd->can_wakeup && wValue == USB_DEVICE_REMOTE_WAKEUP) + hcd->remote_wakeup = 1; + else + goto error; break; case DeviceRequest | USB_REQ_GET_CONFIGURATION: ubuf [0] = 1; @@ -379,6 +389,8 @@ static int rh_call_control (struct usb_h bufp = fs_rh_config_descriptor; len = sizeof fs_rh_config_descriptor; } + if (hcd->can_wakeup) + patch_wakeup = 1; break; case USB_DT_STRING << 8: urb->actual_length = rh_string ( @@ -444,6 +456,11 @@ error: urb->actual_length = len; // always USB_DIR_IN, toward host memcpy (ubuf, bufp, len); + + /* report whether RH hardware supports remote wakeup */ + if (patch_wakeup) + ((struct usb_config_descriptor *)ubuf)->bmAttributes + |= USB_CONFIG_ATT_WAKEUP; } /* any errors get returned through the urb completion */ @@ -762,10 +779,22 @@ int usb_register_root_hub (struct usb_de set_bit (devnum, usb_dev->bus->devmap.devicemap); usb_dev->state = USB_STATE_ADDRESS; + usb_dev->epmaxpacketin[0] = usb_dev->epmaxpacketout[0] = 64; + retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE); + if (retval != sizeof usb_dev->descriptor) { + dev_dbg (parent_dev, "can't read %s device descriptor %d\n", + usb_dev->dev.bus_id, retval); + return (retval < 0) ? retval : -EMSGSIZE; + } + + (void) usb_get_dev (usb_dev); + down (&usb_dev->serialize); retval = usb_new_device (usb_dev); if (retval) dev_err (parent_dev, "can't register root hub for %s, %d\n", usb_dev->dev.bus_id, retval); + up (&usb_dev->serialize); + usb_put_dev (usb_dev); return retval; } EXPORT_SYMBOL (usb_register_root_hub); --- linux-2.6.6/drivers/usb/core/hcd.h 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/core/hcd.h 2004-05-10 01:19:05.770861752 -0700 @@ -74,6 +74,8 @@ struct usb_hcd { /* usb_bus.hcpriv point */ struct hc_driver *driver; /* hw-specific hooks */ unsigned saw_irq : 1; + unsigned can_wakeup:1; /* hw supports wakeup? */ + unsigned remote_wakeup:1;/* sw should use wakeup? */ int irq; /* irq allocated */ void *regs; /* device memory/io */ @@ -94,7 +96,7 @@ struct usb_hcd { /* usb_bus.hcpriv point # define USB_STATE_RUNNING (__ACTIVE) # define USB_STATE_QUIESCING (__SUSPEND|__TRANSIENT|__ACTIVE) # define USB_STATE_RESUMING (__SUSPEND|__TRANSIENT) -# define USB_STATE_SUSPENDED (__SUSPEND) +# define HCD_STATE_SUSPENDED (__SUSPEND) #define HCD_IS_RUNNING(state) ((state) & __ACTIVE) #define HCD_IS_SUSPENDED(state) ((state) & __SUSPEND) @@ -344,9 +346,16 @@ extern void usb_deregister_bus (struct u extern int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev); -/* for portability to 2.4, hcds should call this */ static inline int hcd_register_root (struct usb_hcd *hcd) { + /* hcd->driver->start() reported can_wakeup, probably with + * assistance from board's boot firmware. + * NOTE: normal devices won't enable wakeup by default. + */ + if (hcd->can_wakeup) + dev_dbg (hcd->self.controller, "supports USB remote wakeup\n"); + hcd->remote_wakeup = hcd->can_wakeup; + return usb_register_root_hub ( hcd_to_bus (hcd)->root_hub, hcd->self.controller); } --- linux-2.6.6/drivers/usb/core/hcd-pci.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/core/hcd-pci.c 2004-05-10 01:19:05.768862056 -0700 @@ -293,7 +293,7 @@ int usb_hcd_pci_suspend (struct pci_dev case USB_STATE_HALT: dev_dbg (hcd->self.controller, "halted; hcd not suspended\n"); break; - case USB_STATE_SUSPENDED: + case HCD_STATE_SUSPENDED: dev_dbg (hcd->self.controller, "hcd already suspended\n"); break; default: @@ -310,7 +310,7 @@ int usb_hcd_pci_suspend (struct pci_dev "suspend fail, retval %d\n", retval); else - hcd->state = USB_STATE_SUSPENDED; + hcd->state = HCD_STATE_SUSPENDED; } pci_set_power_state (dev, state); @@ -333,7 +333,7 @@ int usb_hcd_pci_resume (struct pci_dev * dev_dbg (hcd->self.controller, "resume from state D%d\n", dev->current_state); - if (hcd->state != USB_STATE_SUSPENDED) { + if (hcd->state != HCD_STATE_SUSPENDED) { dev_dbg (hcd->self.controller, "can't resume, not suspended!\n"); return -EL3HLT; --- linux-2.6.6/drivers/usb/core/hub.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/core/hub.c 2004-05-10 01:19:05.775860992 -0700 @@ -38,7 +38,6 @@ /* Wakes up khubd */ static spinlock_t hub_event_lock = SPIN_LOCK_UNLOCKED; -static DECLARE_MUTEX(usb_address0_sem); static LIST_HEAD(hub_event_list); /* List of hubs needing servicing */ static LIST_HEAD(hub_list); /* List of all hubs (for cleanup) */ @@ -373,12 +372,13 @@ static void hub_power_on(struct usb_hub struct usb_device *dev; int i; - /* Enable power to the ports */ - dev_dbg(hubdev(interface_to_usbdev(hub->intf)), - "enabling power on all ports\n"); - dev = interface_to_usbdev(hub->intf); - for (i = 0; i < hub->descriptor->bNbrPorts; i++) - set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER); + /* if hub supports power switching, enable power on each port */ + if ((hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) < 2) { + dev_dbg(&hub->intf->dev, "enabling power on all ports\n"); + dev = interface_to_usbdev(hub->intf); + for (i = 0; i < hub->descriptor->bNbrPorts; i++) + set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER); + } /* Wait for power to be enabled */ wait_ms(hub->descriptor->bPwrOn2PwrGood * 2); @@ -545,8 +545,25 @@ static int hub_configure(struct usb_hub dev_dbg(hub_dev, "power on to power good time: %dms\n", hub->descriptor->bPwrOn2PwrGood * 2); - dev_dbg(hub_dev, "hub controller current requirement: %dmA\n", - hub->descriptor->bHubContrCurrent); + + /* power budgeting mostly matters with bus-powered hubs, + * and battery-powered root hubs (may provide just 8 mA). + */ + ret = usb_get_status(dev, USB_RECIP_DEVICE, 0, &hubstatus); + if (ret < 0) { + message = "can't get hubdev status"; + goto fail; + } + cpu_to_le16s(&hubstatus); + if ((hubstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0) { + dev_dbg(hub_dev, "hub controller current requirement: %dmA\n", + hub->descriptor->bHubContrCurrent); + hub->power_budget = (501 - hub->descriptor->bHubContrCurrent) + / 2; + dev_dbg(hub_dev, "%dmA bus power budget for children\n", + hub->power_budget * 2); + } + ret = hub_hub_status(hub, &hubstatus, &hubchange); if (ret < 0) { @@ -554,12 +571,11 @@ static int hub_configure(struct usb_hub goto fail; } - /* FIXME implement per-port power budgeting; - * enable it for bus-powered hubs. - */ - dev_dbg(hub_dev, "local power source is %s\n", - (hubstatus & HUB_STATUS_LOCAL_POWER) - ? "lost (inactive)" : "good"); + /* local power status reports aren't always correct */ + if (dev->actconfig->desc.bmAttributes & USB_CONFIG_ATT_SELFPOWER) + dev_dbg(hub_dev, "local power source is %s\n", + (hubstatus & HUB_STATUS_LOCAL_POWER) + ? "lost (inactive)" : "good"); if ((hub->descriptor->wHubCharacteristics & HUB_CHAR_OCPM) == 0) dev_dbg(hub_dev, "%sover-current condition exists\n", @@ -611,6 +627,8 @@ fail: return ret; } +static unsigned highspeed_hubs; + static void hub_disconnect(struct usb_interface *intf) { struct usb_hub *hub = usb_get_intfdata (intf); @@ -620,6 +638,9 @@ static void hub_disconnect(struct usb_in if (!hub) return; + if (interface_to_usbdev(intf)->speed == USB_SPEED_HIGH) + highspeed_hubs--; + usb_set_intfdata (intf, NULL); spin_lock_irqsave(&hub_event_lock, flags); hub->urb_complete = &urb_complete; @@ -731,6 +752,9 @@ descriptor_error: usb_set_intfdata (intf, hub); + if (dev->speed == USB_SPEED_HIGH) + highspeed_hubs++; + if (hub_configure(hub, endpoint) >= 0) return 0; @@ -841,8 +865,11 @@ static int hub_port_status(struct usb_de return ret; } -#define HUB_RESET_TRIES 5 -#define HUB_PROBE_TRIES 2 +#define PORT_RESET_TRIES 5 +#define SET_ADDRESS_TRIES 2 +#define GET_DESCRIPTOR_TRIES 2 +#define SET_CONFIG_TRIES 2 + #define HUB_ROOT_RESET_TIME 50 /* times are in msec */ #define HUB_SHORT_RESET_TIME 10 #define HUB_LONG_RESET_TIME 200 @@ -907,7 +934,7 @@ static int hub_port_reset(struct usb_dev int i, status; /* Reset the port */ - for (i = 0; i < HUB_RESET_TRIES; i++) { + for (i = 0; i < PORT_RESET_TRIES; i++) { set_port_feature(hub, port + 1, USB_PORT_FEAT_RESET); /* return on disconnect or reset */ @@ -934,7 +961,7 @@ static int hub_port_reset(struct usb_dev return -1; } -int hub_port_disable(struct usb_device *hub, int port) +static int hub_port_disable(struct usb_device *hub, int port) { int ret; @@ -1003,40 +1030,22 @@ static int hub_port_debounce(struct usb_ return ((portstatus&USB_PORT_STAT_CONNECTION)) ? 0 : 1; } -static void hub_port_connect_change(struct usb_hub *hubstate, int port, - u16 portstatus, u16 portchange) +/* reset device, (re)assign address, get device descriptor. + * device connection is stable, no more debouncing needed. + * returns device in USB_STATE_ADDRESS, except on error. + * on error return, device is no longer usable (ref dropped). + * + * caller owns dev->serialize for the device, guarding against + * config changes and disconnect processing. + */ +static int +hub_port_init (struct usb_device *hub, struct usb_device *dev, int port) { - struct usb_device *hub = interface_to_usbdev(hubstate->intf); - struct usb_device *dev; - unsigned int delay = HUB_SHORT_RESET_TIME; - int i; - - dev_dbg (&hubstate->intf->dev, - "port %d, status %x, change %x, %s\n", - port + 1, portstatus, portchange, portspeed (portstatus)); + static DECLARE_MUTEX(usb_address0_sem); - /* Clear the connection change status */ - clear_port_feature(hub, port + 1, USB_PORT_FEAT_C_CONNECTION); - - /* Disconnect any existing devices under this port */ - if (hub->children[port]) - usb_disconnect(&hub->children[port]); - - /* Return now if nothing is connected */ - if (!(portstatus & USB_PORT_STAT_CONNECTION)) { - if (portstatus & USB_PORT_STAT_ENABLE) - hub_port_disable(hub, port); - - return; - } - - if (hub_port_debounce(hub, port)) { - dev_err (&hubstate->intf->dev, - "connect-debounce failed, port %d disabled\n", - port+1); - hub_port_disable(hub, port); - return; - } + int i, j, retval = -ENODEV; + unsigned delay = HUB_SHORT_RESET_TIME; + enum usb_device_speed oldspeed = dev->speed; /* root hub ports have a slightly longer reset period * (from USB 2.0 spec, section 7.1.7.5) @@ -1046,31 +1055,53 @@ static void hub_port_connect_change(stru /* Some low speed devices have problems with the quick delay, so */ /* be a bit pessimistic with those devices. RHbug #23670 */ - if (portstatus & USB_PORT_STAT_LOW_SPEED) + if (oldspeed == USB_SPEED_LOW) delay = HUB_LONG_RESET_TIME; down(&usb_address0_sem); - for (i = 0; i < HUB_PROBE_TRIES; i++) { - - /* Allocate a new device struct */ - dev = usb_alloc_dev(hub, hub->bus, port); - if (!dev) { - dev_err (&hubstate->intf->dev, - "couldn't allocate usb_device\n"); - break; - } - - dev->state = USB_STATE_POWERED; - - /* Reset the device, and detect its speed */ - if (hub_port_reset(hub, port, dev, delay)) { - usb_put_dev(dev); - break; - } - - /* Find a new address for it */ + /* Reset the device; full speed may morph to high speed */ + switch (hub_port_reset(hub, port, dev, delay)) { + case 0: /* success, speed is known */ + break; + case 1: /* disconnect, give to companion */ + retval = -EBUSY; + /* FALL THROUGH */ + default: /* error */ + goto fail; + } + if (oldspeed != USB_SPEED_UNKNOWN && oldspeed != dev->speed) { + dev_dbg(&dev->dev, "device reset changed speed!\n"); + goto fail; + } + + /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ... + * it's fixed size except for full speed devices. + */ + switch (dev->speed) { + case USB_SPEED_HIGH: /* fixed at 64 */ + i = 64; + break; + case USB_SPEED_FULL: /* 8, 16, 32, or 64 */ + /* to determine the ep0 maxpacket size, read the first 8 + * bytes from the device descriptor to get bMaxPacketSize0; + * then correct our initial (small) guess. + */ + // FALLTHROUGH + case USB_SPEED_LOW: /* fixed at 8 */ + i = 8; + break; + default: + goto fail; + } + dev->epmaxpacketin [0] = i; + dev->epmaxpacketout[0] = i; + + /* set the address */ + if (dev->devnum <= 0) { usb_choose_address(dev); + if (dev->devnum <= 0) + goto fail; /* Set up TT records, if needed */ if (hub->tt) { @@ -1078,12 +1109,21 @@ static void hub_port_connect_change(stru dev->ttport = hub->ttport; } else if (dev->speed != USB_SPEED_HIGH && hub->speed == USB_SPEED_HIGH) { + struct usb_hub *hubstate; + + hubstate = usb_get_intfdata (hub->actconfig + ->interface[0]); dev->tt = &hubstate->tt; dev->ttport = port + 1; } - dev_info (&dev->dev, - "new %s speed USB device using address %d\n", + /* force the right log message (below) at low speed */ + oldspeed = USB_SPEED_UNKNOWN; + } + + dev_info (&dev->dev, + "%s %s speed USB device using address %d\n", + (oldspeed == USB_SPEED_UNKNOWN) ? "new" : "reset", ({ char *speed; switch (dev->speed) { case USB_SPEED_LOW: speed = "low"; break; case USB_SPEED_FULL: speed = "full"; break; @@ -1091,23 +1131,258 @@ static void hub_port_connect_change(stru default: speed = "?"; break; }; speed;}), dev->devnum); + + /* Why interleave GET_DESCRIPTOR and SET_ADDRESS this way? + * Because device hardware and firmware is sometimes buggy in + * this area, and this is how Linux has done it for ages. + * Change it cautiously. + * + * NOTE: Windows gets the descriptor first, seemingly to help + * work around device bugs like "can't use addresses with bit 3 + * set in certain configurations". Yes, really. + */ + for (i = 0; i < GET_DESCRIPTOR_TRIES; ++i) { + for (j = 0; j < SET_ADDRESS_TRIES; ++j) { + retval = usb_set_address(dev); + if (retval >= 0) + break; + wait_ms(200); + } + if (retval < 0) { + dev_err(&dev->dev, + "device not accepting address %d, error %d\n", + dev->devnum, retval); + fail: + hub_port_disable(hub, port); + clear_bit(dev->devnum, dev->bus->devmap.devicemap); + dev->devnum = -1; + usb_put_dev(dev); + up(&usb_address0_sem); + return retval; + } + + /* cope with hardware quirkiness: + * - let SET_ADDRESS settle, some device hardware wants it + * - read ep0 maxpacket even for high and low speed, + */ + wait_ms(10); + retval = usb_get_device_descriptor(dev, 8); + if (retval >= 8) + break; + wait_ms(100); + } + if (retval != 8) { + dev_err(&dev->dev, "device descriptor read/%s, error %d\n", + "8", retval); + if (retval >= 0) + retval = -EMSGSIZE; + goto fail; + } + if (dev->speed == USB_SPEED_FULL + && (dev->epmaxpacketin [0] + != dev->descriptor.bMaxPacketSize0)) { + usb_disable_endpoint(dev, 0); + usb_endpoint_running(dev, 0, 1); + usb_endpoint_running(dev, 0, 0); + dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0; + dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0; + } + + retval = usb_get_device_descriptor(dev, USB_DT_DEVICE_SIZE); + if (retval < (signed)sizeof(dev->descriptor)) { + dev_err(&dev->dev, "device descriptor read/%s, error %d\n", + "all", retval); + if (retval >= 0) + retval = -ENOMSG; + goto fail; + } - /* Run it through the hoops (find a driver, etc) */ - if (usb_new_device(dev) == 0) { - hub->children[port] = dev; - goto done; + /* now dev is visible to other tasks */ + hub->children[port] = dev; + + up(&usb_address0_sem); + return 0; +} + +static void +check_highspeed (struct usb_hub *hub, struct usb_device *dev, int port) +{ + struct usb_qualifier_descriptor *qual; + int status; + + qual = kmalloc (sizeof *qual, SLAB_KERNEL); + if (qual == 0) + return; + + status = usb_get_descriptor (dev, USB_DT_DEVICE_QUALIFIER, 0, + qual, sizeof *qual); + if (status == sizeof *qual) { + dev_info(&dev->dev, "not running at top speed; " + "connect to a high speed hub\n"); + /* hub LEDs are probably harder to miss than syslog */ + if (hub->has_indicators) { + hub->indicator[port] = INDICATOR_GREEN_BLINK; + schedule_work (&hub->leds); } + } + kfree (qual); +} + +static unsigned +hub_power_remaining (struct usb_hub *hubstate, struct usb_device *hub) +{ + int remaining; + unsigned i; - /* Free the configuration if there was an error */ - usb_put_dev(dev); + remaining = hubstate->power_budget; + if (!remaining) /* self-powered */ + return 0; - /* Switch to a long reset time */ - delay = HUB_LONG_RESET_TIME; + for (i = 0; i < hub->maxchild; i++) { + struct usb_device *dev = hub->children[i]; + int delta; + + if (!dev) + continue; + + if (dev->actconfig) + delta = dev->actconfig->desc.bMaxPower; + else + delta = 50; + // dev_dbg(&dev->dev, "budgeted %dmA\n", 2 * delta); + remaining -= delta; + } + if (remaining < 0) { + dev_warn(&hubstate->intf->dev, + "%dmA over power budget!\n", + -2 * remaining); + remaining = 0; } + return remaining; +} + +static void hub_port_connect_change(struct usb_hub *hubstate, int port, + u16 portstatus, u16 portchange) +{ + struct usb_device *hub = interface_to_usbdev(hubstate->intf); + int status, i; + + dev_dbg (&hubstate->intf->dev, + "port %d, status %04x, change %04x, %s\n", + port + 1, portstatus, portchange, portspeed (portstatus)); + + /* Clear the connection change status */ + clear_port_feature(hub, port + 1, USB_PORT_FEAT_C_CONNECTION); - hub_port_disable(hub, port); + if (hubstate->has_indicators) { + set_port_led(hub, hubstate, port + 1, HUB_LED_AUTO); + hubstate->indicator[port] = INDICATOR_AUTO; + } + + /* Disconnect any existing devices under this port */ + if (hub->children[port]) + usb_disconnect(&hub->children[port]); + + /* Return now if nothing is connected */ + if (!(portstatus & USB_PORT_STAT_CONNECTION)) { + if (portstatus & USB_PORT_STAT_ENABLE) + goto done; + return; + } + + if (hub_port_debounce(hub, port)) { + dev_err (&hubstate->intf->dev, + "connect-debounce failed, port %d disabled\n", + port+1); + goto done; + } + + for (i = 0; i < SET_CONFIG_TRIES; i++) { + struct usb_device *dev; + + /* reallocate for each attempt, since references + * to the previous one can escape in various ways + */ + dev = usb_alloc_dev(hub, hub->bus, port); + if (!dev) { + dev_err (&hubstate->intf->dev, + "couldn't allocate port %d usb_device\n", port+1); + goto done; + } + dev->state = USB_STATE_POWERED; + + /* hub can tell if it's lowspeed already: D- pullup (not D+) */ + if (portstatus & USB_PORT_STAT_LOW_SPEED) + dev->speed = USB_SPEED_LOW; + else + dev->speed = USB_SPEED_UNKNOWN; + + /* reset, set address, get descriptor, add to hub's children */ + down (&dev->serialize); + status = hub_port_init(hub, dev, port); + if (status == -EBUSY) + break; + if (status < 0) + continue; + + /* consecutive bus-powered hubs aren't reliable; they can + * violate the voltage drop budget. if the new child has + * a "powered" LED, users should notice we didn't enable it + * (without reading syslog), even without per-port LEDs + * on the parent. + */ + if (dev->descriptor.bDeviceClass == USB_CLASS_HUB + && hubstate->power_budget) { + u16 devstat; + + status = usb_get_status(dev, USB_RECIP_DEVICE, 0, + &devstat); + if (status < 0) { + dev_dbg(&dev->dev, "get status %d ?\n", status); + continue; + } + cpu_to_le16s(&devstat); + if ((devstat & (1 << USB_DEVICE_SELF_POWERED)) == 0) { + dev_err(&dev->dev, + "can't connect bus-powered hub " + "to this port\n"); + if (hubstate->has_indicators) { + hubstate->indicator[port] = + INDICATOR_AMBER_BLINK; + schedule_work (&hubstate->leds); + } + hub->children[port] = NULL; + usb_put_dev(dev); + hub_port_disable(hub, port); + return; + } + } + + /* check for devices running slower than they could */ + if (dev->descriptor.bcdUSB >= 0x0200 + && dev->speed == USB_SPEED_FULL + && highspeed_hubs != 0) + check_highspeed (hubstate, dev, port); + + /* Run it through the hoops (find a driver, etc) */ + status = usb_new_device(dev); + if (status != 0) { + hub->children[port] = NULL; + continue; + } + up (&dev->serialize); + + status = hub_power_remaining(hubstate, hub); + if (status) + dev_dbg(&hubstate->intf->dev, + "%dmA power budget left\n", + 2 * status); + + return; + } + done: - up(&usb_address0_sem); + hub_port_disable(hub, port); } static void hub_events(void) @@ -1173,7 +1448,7 @@ static void hub_events(void) hub_port_connect_change(hub, i, portstatus, portchange); } else if (portchange & USB_PORT_STAT_C_ENABLE) { dev_dbg (hubdev (dev), - "port %d enable change, status %x\n", + "port %d enable change, status %08x\n", i + 1, portstatus); clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_ENABLE); @@ -1331,25 +1606,68 @@ void usb_hub_cleanup(void) usb_deregister(&hub_driver); } /* usb_hub_cleanup() */ + +static int config_descriptors_changed(struct usb_device *dev) +{ + unsigned index; + unsigned len = 0; + struct usb_config_descriptor *buf; + + for (index = 0; index < dev->descriptor.bNumConfigurations; index++) { + if (len < dev->config[index].desc.wTotalLength) + len = dev->config[index].desc.wTotalLength; + } + buf = kmalloc (len, SLAB_KERNEL); + if (buf == 0) { + dev_err(&dev->dev, "no mem to re-read configs after reset\n"); + /* assume the worst */ + return 1; + } + for (index = 0; index < dev->descriptor.bNumConfigurations; index++) { + int length; + int old_length = dev->config[index].desc.wTotalLength; + + length = usb_get_descriptor(dev, USB_DT_CONFIG, index, buf, + old_length); + if (length < old_length) { + dev_dbg(&dev->dev, "config index %d, error %d\n", + index, length); + break; + } + if (memcmp (buf, dev->rawdescriptors[index], old_length) + != 0) { + dev_dbg(&dev->dev, "config index %d changed (#%d)\n", + index, buf->bConfigurationValue); +/* FIXME enable this when we can re-enumerate after reset; + * until then DFU-ish drivers need this and other workarounds + */ +// break; + } + } + kfree(buf); + return index != dev->descriptor.bNumConfigurations; +} + /* - * WARNING - If a driver calls usb_reset_device, you should simulate a - * disconnect() and probe() for other interfaces you doesn't claim. This - * is left up to the driver writer right now. This insures other drivers - * have a chance to re-setup their interface. + * WARNING - don't reset any device unless drivers for all of its + * interfaces are expecting that reset! Maybe some driver->reset() + * method should eventually help ensure sufficient cooperation. * - * Take a look at proc_resetdevice in devio.c for some sample code to - * do this. - * Use this only from within your probe function, otherwise use - * usb_reset_device() below, which ensure proper locking + * This is the same as usb_reset_device() except that the caller + * already holds dev->serialize. For example, it's safe to use + * this from a driver probe() routine after downloading new firmware. */ -int usb_physical_reset_device(struct usb_device *dev) +int __usb_reset_device(struct usb_device *dev) { struct usb_device *parent = dev->parent; - struct usb_device_descriptor *descriptor; + struct usb_device_descriptor descriptor = dev->descriptor; int i, ret, port = -1; - if (!parent) { - err("attempting to reset root hub!"); + if (dev->maxchild) { + /* this requires hub- or hcd-specific logic; + * see hub_reset() and OHCI hc_restart() + */ + dev_dbg(&dev->dev, "%s for hub!\n", __FUNCTION__); return -EINVAL; } @@ -1362,114 +1680,69 @@ int usb_physical_reset_device(struct usb if (port < 0) return -ENOENT; - descriptor = kmalloc(sizeof *descriptor, GFP_NOIO); - if (!descriptor) { - return -ENOMEM; - } - - down(&usb_address0_sem); - - /* Send a reset to the device */ - if (hub_port_reset(parent, port, dev, HUB_SHORT_RESET_TIME)) { - hub_port_disable(parent, port); - up(&usb_address0_sem); - kfree(descriptor); - return(-ENODEV); - } - - /* Reprogram the Address */ - ret = usb_set_address(dev); - if (ret < 0) { - err("USB device not accepting new address (error=%d)", ret); - hub_port_disable(parent, port); - up(&usb_address0_sem); - kfree(descriptor); - return ret; - } - - /* Let the SET_ADDRESS settle */ - wait_ms(10); - - up(&usb_address0_sem); - - /* - * Now we fetch the configuration descriptors for the device and - * see if anything has changed. If it has, we dump the current - * parsed descriptors and reparse from scratch. Then we leave - * the device alone for the caller to finish setting up. - * - * If nothing changed, we reprogram the configuration and then - * the alternate settings. - */ - - ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, descriptor, - sizeof(*descriptor)); - if (ret < 0) { - kfree(descriptor); - return ret; - } - - le16_to_cpus(&descriptor->bcdUSB); - le16_to_cpus(&descriptor->idVendor); - le16_to_cpus(&descriptor->idProduct); - le16_to_cpus(&descriptor->bcdDevice); - - if (memcmp(&dev->descriptor, descriptor, sizeof(*descriptor))) { - kfree(descriptor); - usb_destroy_configuration(dev); - - /* FIXME Linux doesn't yet handle these "device morphed" - * paths. DFU variants need this to work ... and they - * include the "config descriptors changed" case this - * doesn't yet detect! - */ - dev->state = USB_STATE_NOTATTACHED; - dev_err(&dev->dev, "device morphed (DFU?), nyet supported\n"); - - return -ENODEV; - } - - kfree(descriptor); + ret = hub_port_init(parent, dev, port); + if (ret < 0) + goto re_enumerate; + + /* Device might have changed firmware (DFU or similar) */ + if (memcmp(&dev->descriptor, &descriptor, sizeof descriptor) + || config_descriptors_changed (dev)) { + dev_info(&dev->dev, "device firmware changed\n"); + dev->descriptor = descriptor; /* for disconnect() calls */ + goto re_enumerate; + } + + if (!dev->actconfig) + return 0; ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_CONFIGURATION, 0, dev->actconfig->desc.bConfigurationValue, 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT); if (ret < 0) { - err("failed to set dev %s active configuration (error=%d)", - dev->devpath, ret); - return ret; - } + dev_err(&dev->dev, + "can't restore configuration #%d (error=%d)\n", + dev->actconfig->desc.bConfigurationValue, ret); + goto re_enumerate; + } dev->state = USB_STATE_CONFIGURED; for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { struct usb_interface *intf = dev->actconfig->interface[i]; struct usb_interface_descriptor *desc; + /* set_interface resets host side toggle and halt status even + * for altsetting zero. the interface may have no driver. + */ desc = &intf->cur_altsetting->desc; ret = usb_set_interface(dev, desc->bInterfaceNumber, desc->bAlternateSetting); if (ret < 0) { - err("failed to set active alternate setting " - "for dev %s interface %d (error=%d)", - dev->devpath, desc->bInterfaceNumber, ret); - return ret; + dev_err(&dev->dev, "failed to restore interface %d " + "altsetting %d (error=%d)\n", + desc->bInterfaceNumber, + desc->bAlternateSetting, + ret); + goto re_enumerate; } } return 0; + +re_enumerate: + /* FIXME make some task re-enumerate; don't just mark unusable */ + dev->state = USB_STATE_NOTATTACHED; + return -ENODEV; } +EXPORT_SYMBOL(__usb_reset_device); int usb_reset_device(struct usb_device *udev) { - struct device *gdev = &udev->dev; int r; - down_read(&gdev->bus->subsys.rwsem); - r = usb_physical_reset_device(udev); - up_read(&gdev->bus->subsys.rwsem); + down(&udev->serialize); + r = __usb_reset_device(udev); + up(&udev->serialize); return r; } - - --- linux-2.6.6/drivers/usb/core/hub.h 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/core/hub.h 2004-05-10 01:19:05.775860992 -0700 @@ -209,6 +209,8 @@ struct usb_hub { struct semaphore khubd_sem; struct usb_tt tt; /* Transaction Translator */ + u8 power_budget; /* in 2mA units; or zero */ + unsigned has_indicators:1; enum hub_led_mode indicator[USB_MAXCHILDREN]; struct work_struct leds; --- linux-2.6.6/drivers/usb/core/inode.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/core/inode.c 2004-05-10 01:19:05.776860840 -0700 @@ -717,9 +717,6 @@ void usbfs_remove_device(struct usb_devi while (!list_empty(&dev->filelist)) { ds = list_entry(dev->filelist.next, struct dev_state, list); list_del_init(&ds->list); - down_write(&ds->devsem); - ds->dev = NULL; - up_write(&ds->devsem); if (ds->discsignr) { sinfo.si_signo = SIGPIPE; sinfo.si_errno = EPIPE; --- linux-2.6.6/drivers/usb/core/message.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/core/message.c 2004-05-10 01:19:05.778860536 -0700 @@ -796,10 +796,6 @@ void usb_disable_interface(struct usb_de } } -static void release_interface(struct device *dev) -{ -} - /* * usb_disable_device - Disable all the endpoints for a USB device * @dev: the device whose endpoints are being disabled @@ -835,6 +831,7 @@ void usb_disable_device(struct usb_devic dev_dbg (&dev->dev, "unregistering interface %s\n", interface->dev.bus_id); device_unregister (&interface->dev); + dev->actconfig->interface[i] = NULL; } dev->actconfig = 0; if (dev->state == USB_STATE_CONFIGURED) @@ -1071,6 +1068,16 @@ int usb_reset_configuration(struct usb_d return 0; } +static void release_interface(struct device *dev) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct usb_interface_cache *intfc = + altsetting_to_usb_interface_cache(intf->altsetting); + + kref_put(&intfc->ref); + kfree(intf); +} + /* * usb_set_configuration - Makes a particular device setting be current * @dev: the device whose configuration is being updated @@ -1109,19 +1116,19 @@ int usb_set_configuration(struct usb_dev { int i, ret; struct usb_host_config *cp = NULL; - + struct usb_interface **new_interfaces = NULL; + int n, nintf; + /* dev->serialize guards all config changes */ - for (i=0; idescriptor.bNumConfigurations; i++) { + for (i = 0; i < dev->descriptor.bNumConfigurations; i++) { if (dev->config[i].desc.bConfigurationValue == configuration) { cp = &dev->config[i]; break; } } - if ((!cp && configuration != 0)) { - ret = -EINVAL; - goto out; - } + if ((!cp && configuration != 0)) + return -EINVAL; /* The USB spec says configuration 0 means unconfigured. * But if a device includes a configuration numbered 0, @@ -1130,6 +1137,34 @@ int usb_set_configuration(struct usb_dev if (cp && configuration == 0) dev_warn(&dev->dev, "config 0 descriptor??\n"); + /* Allocate memory for new interfaces before doing anything else, + * so that if we run out then nothing will have changed. */ + n = nintf = 0; + if (cp) { + nintf = cp->desc.bNumInterfaces; + new_interfaces = kmalloc(nintf * sizeof(*new_interfaces), + GFP_KERNEL); + if (!new_interfaces) { + dev_err(&dev->dev, "Out of memory"); + return -ENOMEM; + } + + for (; n < nintf; ++n) { + new_interfaces[n] = kmalloc( + sizeof(struct usb_interface), + GFP_KERNEL); + if (!new_interfaces[n]) { + dev_err(&dev->dev, "Out of memory"); + ret = -ENOMEM; +free_interfaces: + while (--n >= 0) + kfree(new_interfaces[n]); + kfree(new_interfaces); + return ret; + } + } + } + /* if it's already configured, clear out old state first. * getting rid of old interfaces means unbinding their drivers. */ @@ -1139,7 +1174,7 @@ int usb_set_configuration(struct usb_dev if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_CONFIGURATION, 0, configuration, 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0) - goto out; + goto free_interfaces; dev->actconfig = cp; if (!cp) @@ -1147,14 +1182,21 @@ int usb_set_configuration(struct usb_dev else { dev->state = USB_STATE_CONFIGURED; - /* re-initialize hc/hcd/usbcore interface/endpoint state. - * this triggers binding of drivers to interfaces; and - * maybe probe() calls will choose different altsettings. + /* Initialize the new interface structures and the + * hc/hcd/usbcore interface/endpoint state. */ - for (i = 0; i < cp->desc.bNumInterfaces; ++i) { - struct usb_interface *intf = cp->interface[i]; + for (i = 0; i < nintf; ++i) { + struct usb_interface_cache *intfc; + struct usb_interface *intf; struct usb_host_interface *alt; + cp->interface[i] = intf = new_interfaces[i]; + memset(intf, 0, sizeof(*intf)); + intfc = cp->intf_cache[i]; + intf->altsetting = intfc->altsetting; + intf->num_altsetting = intfc->num_altsetting; + kref_get(&intfc->ref); + alt = usb_altnum_to_altsetting(intf, 0); /* No altsetting 0? We'll assume the first altsetting. @@ -1178,12 +1220,15 @@ int usb_set_configuration(struct usb_dev configuration, alt->desc.bInterfaceNumber); } + kfree(new_interfaces); - /* Now that all interfaces are setup, probe() calls - * may claim() any interface that's not yet bound. - * Many class drivers need that: CDC, audio, video, etc. + /* Now that all the interfaces are set up, register them + * to trigger binding of drivers to interfaces. probe() + * routines may install different altsettings and may + * claim() any interfaces not yet bound. Many class drivers + * need that: CDC, audio, video, etc. */ - for (i = 0; i < cp->desc.bNumInterfaces; ++i) { + for (i = 0; i < nintf; ++i) { struct usb_interface *intf = cp->interface[i]; struct usb_interface_descriptor *desc; @@ -1204,7 +1249,6 @@ int usb_set_configuration(struct usb_dev } } -out: return ret; } --- linux-2.6.6/drivers/usb/core/urb.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/usb/core/urb.c 2004-05-10 01:19:05.779860384 -0700 @@ -13,6 +13,14 @@ #include #include "hcd.h" +#define to_urb(d) container_of(d, struct urb, kref) + +static void urb_destroy(struct kref *kref) +{ + struct urb *urb = to_urb(kref); + kfree(urb); +} + /** * usb_init_urb - initializes a urb so that it can be used by a USB driver * @urb: pointer to the urb to initialize @@ -31,7 +39,7 @@ void usb_init_urb(struct urb *urb) { if (urb) { memset(urb, 0, sizeof(*urb)); - urb->count = (atomic_t)ATOMIC_INIT(1); + kref_init(&urb->kref, urb_destroy); spin_lock_init(&urb->lock); } } @@ -80,8 +88,7 @@ struct urb *usb_alloc_urb(int iso_packet void usb_free_urb(struct urb *urb) { if (urb) - if (atomic_dec_and_test(&urb->count)) - kfree(urb); + kref_put(&urb->kref); } /** @@ -96,11 +103,9 @@ void usb_free_urb(struct urb *urb) */ struct urb * usb_get_urb(struct urb *urb) { - if (urb) { - atomic_inc(&urb->count); - return urb; - } else - return NULL; + if (urb) + kref_get(&urb->kref); + return urb; } @@ -232,6 +237,8 @@ int usb_submit_urb(struct urb *urb, int (dev->state < USB_STATE_DEFAULT) || (!dev->bus) || (dev->devnum <= 0)) return -ENODEV; + if (dev->state == USB_STATE_SUSPENDED) + return -EHOSTUNREACH; if (!(op = dev->bus->op) || !op->submit_urb) return -ENODEV; --- linux-2.6.6/drivers/usb/core/usb.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/core/usb.c 2004-05-10 01:19:05.780860232 -0700 @@ -1064,92 +1064,29 @@ static inline void usb_show_string(struc } /* - * By the time we get here, we chose a new device address - * and is in the default state. We need to identify the thing and - * get the ball rolling.. + * usb_new_device - perform initial device setup (usbcore-internal) + * @dev: newly addressed device (in ADDRESS state) * - * Returns 0 for success, != 0 for error. + * This is called with devices which have been enumerated, but not yet + * configured. The device descriptor is available, but not descriptors + * for any device configuration. The caller owns dev->serialize, and + * the device is not visible through sysfs or other filesystem code. + * + * Returns 0 for success (device is configured and listed, with its + * interfaces, in sysfs); else a negative errno value. On error, one + * reference count to the device has been dropped. * * This call is synchronous, and may not be used in an interrupt context. * * Only the hub driver should ever call this; root hub registration * uses it only indirectly. */ -#define NEW_DEVICE_RETRYS 2 -#define SET_ADDRESS_RETRYS 2 int usb_new_device(struct usb_device *dev) { - int err = -EINVAL; + int err; int i; - int j; int config; - /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ... - * it's fixed size except for full speed devices. - */ - switch (dev->speed) { - case USB_SPEED_HIGH: /* fixed at 64 */ - i = 64; - break; - case USB_SPEED_FULL: /* 8, 16, 32, or 64 */ - /* to determine the ep0 maxpacket size, read the first 8 - * bytes from the device descriptor to get bMaxPacketSize0; - * then correct our initial (small) guess. - */ - // FALLTHROUGH - case USB_SPEED_LOW: /* fixed at 8 */ - i = 8; - break; - default: - goto fail; - } - dev->epmaxpacketin [0] = i; - dev->epmaxpacketout[0] = i; - - for (i = 0; i < NEW_DEVICE_RETRYS; ++i) { - - for (j = 0; j < SET_ADDRESS_RETRYS; ++j) { - err = usb_set_address(dev); - if (err >= 0) - break; - wait_ms(200); - } - if (err < 0) { - dev_err(&dev->dev, - "device not accepting address %d, error %d\n", - dev->devnum, err); - goto fail; - } - - wait_ms(10); /* Let the SET_ADDRESS settle */ - - /* high and low speed devices don't need this... */ - err = usb_get_device_descriptor(dev, 8); - if (err >= 8) - break; - wait_ms(100); - } - - if (err < 8) { - dev_err(&dev->dev, "device descriptor read/8, error %d\n", err); - goto fail; - } - if (dev->speed == USB_SPEED_FULL) { - usb_disable_endpoint(dev, 0); - usb_endpoint_running(dev, 0, 1); - usb_endpoint_running(dev, 0, 0); - dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0; - dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0; - } - - /* USB device state == addressed ... still not usable */ - - err = usb_get_device_descriptor(dev, sizeof(dev->descriptor)); - if (err != (signed)sizeof(dev->descriptor)) { - dev_err(&dev->dev, "device descriptor read/all, error %d\n", err); - goto fail; - } - err = usb_get_configuration(dev); if (err < 0) { dev_err(&dev->dev, "can't read configurations, error %d\n", @@ -1170,13 +1107,10 @@ int usb_new_device(struct usb_device *de usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber); #endif - down(&dev->serialize); - /* put device-specific files into sysfs */ err = device_add (&dev->dev); if (err) { dev_err(&dev->dev, "can't device_add, error %d\n", err); - up(&dev->serialize); goto fail; } usb_create_driverfs_dev_files (dev); @@ -1193,7 +1127,7 @@ int usb_new_device(struct usb_device *de /* heuristic: Linux is more likely to have class * drivers, so avoid vendor-specific interfaces. */ - desc = &dev->config[i].interface[0] + desc = &dev->config[i].intf_cache[0] ->altsetting->desc; if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC) continue; @@ -1211,7 +1145,6 @@ int usb_new_device(struct usb_device *de dev->descriptor.bNumConfigurations); } err = usb_set_configuration(dev, config); - up(&dev->serialize); if (err) { dev_err(&dev->dev, "can't set config #%d, error %d\n", config, err); @@ -1226,9 +1159,10 @@ int usb_new_device(struct usb_device *de return 0; fail: - dev->state = USB_STATE_DEFAULT; + dev->state = USB_STATE_NOTATTACHED; clear_bit(dev->devnum, dev->bus->devmap.devicemap); dev->devnum = -1; + usb_put_dev(dev); return err; } @@ -1577,20 +1511,40 @@ int usb_disabled(void) */ static int __init usb_init(void) { + int retval; if (nousb) { pr_info ("%s: USB support disabled\n", usbcore_name); return 0; } - bus_register(&usb_bus_type); + retval = bus_register(&usb_bus_type); + if (retval) + goto out; usb_host_init(); - usb_major_init(); - usbfs_init(); - usb_hub_init(); + retval = usb_major_init(); + if (retval) + goto major_init_failed; + retval = usbfs_init(); + if (retval) + goto fs_init_failed; + retval = usb_hub_init(); + if (retval) + goto hub_init_failed; + + retval = driver_register(&usb_generic_driver); + if (!retval) + goto out; - driver_register(&usb_generic_driver); - - return 0; + usb_hub_cleanup(); +hub_init_failed: + usbfs_cleanup(); +fs_init_failed: + usb_major_cleanup(); +major_init_failed: + usb_host_cleanup(); + bus_unregister(&usb_bus_type); +out: + return retval; } /* --- linux-2.6.6/drivers/usb/gadget/dummy_hcd.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/gadget/dummy_hcd.c 2004-05-10 01:19:05.783859776 -0700 @@ -144,6 +144,7 @@ struct dummy { struct usb_gadget_driver *driver; struct dummy_request fifo_req; u8 fifo_buf [FIFO_SIZE]; + u16 devstatus; struct hcd_dev *hdev; @@ -156,6 +157,8 @@ struct dummy { u32 port_status; int started; struct completion released; + unsigned resuming:1; + unsigned long re_timeout; }; static struct dummy *the_controller; @@ -556,8 +559,37 @@ static int dummy_g_get_frame (struct usb return tv.tv_usec / 1000; } +static int dummy_wakeup (struct usb_gadget *_gadget) +{ + struct dummy *dum; + + dum = container_of (_gadget, struct dummy, gadget); + if ((dum->devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) == 0 + || !(dum->port_status & (1 << USB_PORT_FEAT_SUSPEND))) + return -EINVAL; + + /* hub notices our request, issues downstream resume, etc */ + dum->resuming = 1; + dum->port_status |= (1 << USB_PORT_FEAT_C_SUSPEND); + return 0; +} + +static int dummy_set_selfpowered (struct usb_gadget *_gadget, int value) +{ + struct dummy *dum; + + dum = container_of (_gadget, struct dummy, gadget); + if (value) + dum->devstatus |= (1 << USB_DEVICE_SELF_POWERED); + else + dum->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED); + return 0; +} + static const struct usb_gadget_ops dummy_ops = { .get_frame = dummy_g_get_frame, + .wakeup = dummy_wakeup, + .set_selfpowered = dummy_set_selfpowered, }; /*-------------------------------------------------------------------------*/ @@ -653,6 +685,9 @@ usb_gadget_register_driver (struct usb_g dum->gadget.ops = &dummy_ops; dum->gadget.is_dualspeed = 1; + dum->devstatus = 0; + dum->resuming = 0; + INIT_LIST_HEAD (&dum->gadget.ep_list); for (i = 0; i < DUMMY_ENDPOINTS; i++) { struct dummy_ep *ep = &dum->ep [i]; @@ -1130,8 +1165,19 @@ restart: break; case USB_REQ_SET_FEATURE: if (setup.bRequestType == Dev_Request) { - // remote wakeup, and (hs) test mode - value = -EOPNOTSUPP; + value = 0; + switch (setup.wValue) { + case USB_DEVICE_REMOTE_WAKEUP: + break; + default: + value = -EOPNOTSUPP; + } + if (value == 0) { + dum->devstatus |= + (1 << setup.wValue); + maybe_set_status (urb, 0); + } + } else if (setup.bRequestType == Ep_Request) { // endpoint halt ep2 = find_endpoint (dum, @@ -1147,9 +1193,17 @@ restart: break; case USB_REQ_CLEAR_FEATURE: if (setup.bRequestType == Dev_Request) { - // remote wakeup - value = 0; - maybe_set_status (urb, 0); + switch (setup.wValue) { + case USB_DEVICE_REMOTE_WAKEUP: + dum->devstatus &= ~(1 << + USB_DEVICE_REMOTE_WAKEUP); + value = 0; + maybe_set_status (urb, 0); + break; + default: + value = -EOPNOTSUPP; + break; + } } else if (setup.bRequestType == Ep_Request) { // endpoint halt ep2 = find_endpoint (dum, @@ -1185,6 +1239,10 @@ restart: break; } buf [0] = ep2->halted; + } else if (setup.bRequestType == + Dev_InRequest) { + buf [0] = (u8) + dum->devstatus; } else buf [0] = 0; } @@ -1338,8 +1396,21 @@ static int dummy_hub_control ( case ClearHubFeature: break; case ClearPortFeature: - // FIXME won't some of these need special handling? - dum->port_status &= ~(1 << wValue); + switch (wValue) { + case USB_PORT_FEAT_SUSPEND: + /* 20msec resume signaling */ + dum->resuming = 1; + dum->re_timeout = jiffies + ((HZ * 20)/1000); + break; + case USB_PORT_FEAT_POWER: + dum->port_status = 0; + dum->address = 0; + dum->hdev = 0; + dum->resuming = 0; + break; + default: + dum->port_status &= ~(1 << wValue); + } break; case GetHubDescriptor: hub_descriptor ((struct usb_hub_descriptor *) buf); @@ -1350,33 +1421,28 @@ static int dummy_hub_control ( case GetPortStatus: if (wIndex != 1) retval = -EPIPE; - ((u16 *) buf)[0] = cpu_to_le16 (dum->port_status); - ((u16 *) buf)[1] = cpu_to_le16 (dum->port_status >> 16); - break; - case SetHubFeature: - retval = -EPIPE; - break; - case SetPortFeature: - if (wValue == USB_PORT_FEAT_RESET) { - /* if it's already running, disconnect first */ - if (dum->port_status & USB_PORT_STAT_ENABLE) { - dum->port_status &= ~(USB_PORT_STAT_ENABLE - | USB_PORT_STAT_LOW_SPEED - | USB_PORT_STAT_HIGH_SPEED); - if (dum->driver) { - dev_dbg (hardware, "disconnect\n"); - stop_activity (dum, dum->driver); - } - /* FIXME test that code path! */ - } else - dum->port_status |= - (1 << USB_PORT_FEAT_C_ENABLE); - - dum->port_status |= USB_PORT_STAT_ENABLE | - (1 << USB_PORT_FEAT_C_RESET); + /* whoever resets or resumes must GetPortStatus to + * complete it!! + */ + if (dum->resuming && time_after (jiffies, dum->re_timeout)) { + dum->port_status |= (1 << USB_PORT_FEAT_C_SUSPEND); + dum->port_status &= ~(1 << USB_PORT_FEAT_SUSPEND); + dum->resuming = 0; + dum->re_timeout = 0; + if (dum->driver->resume) { + spin_unlock (&dum->lock); + dum->driver->resume (&dum->gadget); + spin_lock (&dum->lock); + } + } + if ((dum->port_status & (1 << USB_PORT_FEAT_RESET)) != 0 + && time_after (jiffies, dum->re_timeout)) { + dum->port_status |= (1 << USB_PORT_FEAT_C_RESET); + dum->port_status &= ~(1 << USB_PORT_FEAT_RESET); + dum->re_timeout = 0; if (dum->driver) { - + dum->port_status |= USB_PORT_STAT_ENABLE; /* give it the best speed we agree on */ dum->gadget.speed = dum->driver->speed; dum->gadget.ep0->maxpacket = 64; @@ -1395,8 +1461,42 @@ static int dummy_hub_control ( break; } } - } else + } + ((u16 *) buf)[0] = cpu_to_le16 (dum->port_status); + ((u16 *) buf)[1] = cpu_to_le16 (dum->port_status >> 16); + break; + case SetHubFeature: + retval = -EPIPE; + break; + case SetPortFeature: + switch (wValue) { + case USB_PORT_FEAT_SUSPEND: + dum->port_status |= (1 << USB_PORT_FEAT_SUSPEND); + if (dum->driver->suspend) { + spin_unlock (&dum->lock); + dum->driver->suspend (&dum->gadget); + spin_lock (&dum->lock); + } + break; + case USB_PORT_FEAT_RESET: + /* if it's already running, disconnect first */ + if (dum->port_status & USB_PORT_STAT_ENABLE) { + dum->port_status &= ~(USB_PORT_STAT_ENABLE + | USB_PORT_STAT_LOW_SPEED + | USB_PORT_STAT_HIGH_SPEED); + if (dum->driver) { + dev_dbg (hardware, "disconnect\n"); + stop_activity (dum, dum->driver); + } + + /* FIXME test that code path! */ + } + /* 50msec reset signaling */ + dum->re_timeout = jiffies + ((HZ * 50)/1000); + /* FALLTHROUGH */ + default: dum->port_status |= (1 << wValue); + } break; default: --- linux-2.6.6/drivers/usb/gadget/gadget_chips.h 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/gadget/gadget_chips.h 2004-05-10 01:19:05.783859776 -0700 @@ -20,7 +20,7 @@ #define gadget_is_dummy(g) 0 #endif -#ifdef CONFIG_USB_GADGET_PXA +#ifdef CONFIG_USB_GADGET_PXA2XX #define gadget_is_pxa(g) !strcmp("pxa2xx_udc", (g)->name) #else #define gadget_is_pxa(g) 0 --- linux-2.6.6/drivers/usb/gadget/serial.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/gadget/serial.c 2004-05-10 01:19:05.784859624 -0700 @@ -157,8 +157,12 @@ do { \ /* debug macro */ #if G_SERIAL_DEBUG - static int debug = G_SERIAL_DEBUG; +#else +static int debug = 0; +#endif + +#if G_SERIAL_DEBUG #define gs_debug(format, arg...) \ do { if (debug) printk(KERN_DEBUG format, ## arg); } while(0) --- linux-2.6.6/drivers/usb/gadget/zero.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/gadget/zero.c 2004-05-10 01:19:05.786859320 -0700 @@ -130,6 +130,9 @@ struct zero_dev { */ u8 config; struct usb_ep *in_ep, *out_ep; + + /* autoresume timer */ + struct timer_list resume; }; #define xprintk(d,level,fmt,args...) \ @@ -167,6 +170,12 @@ module_param (buflen, uint, S_IRUGO|S_IW module_param (qlen, uint, S_IRUGO|S_IWUSR); module_param (pattern, uint, S_IRUGO|S_IWUSR); +/* + * if it's nonzero, autoresume says how many seconds to wait + * before trying to wake up the host after suspend. + */ +static unsigned autoresume = 0; +module_param (autoresume, uint, 0); /* * Normally the "loopback" configuration is second (index 1) so @@ -224,7 +233,7 @@ device_desc = { .bNumConfigurations = 2, }; -static const struct usb_config_descriptor +static struct usb_config_descriptor source_sink_config = { .bLength = sizeof source_sink_config, .bDescriptorType = USB_DT_CONFIG, @@ -237,7 +246,7 @@ source_sink_config = { .bMaxPower = 1, /* self-powered */ }; -static const struct usb_config_descriptor +static struct usb_config_descriptor loopback_config = { .bLength = sizeof loopback_config, .bDescriptorType = USB_DT_CONFIG, @@ -1060,6 +1069,19 @@ zero_disconnect (struct usb_gadget *gadg */ } +static void +zero_autoresume (unsigned long _dev) +{ + struct zero_dev *dev = (struct zero_dev *) _dev; + int status; + + /* normally the host would be woken up for something + * more significant than just a timer firing... + */ + status = usb_gadget_wakeup (dev->gadget); + DBG (dev, "wakeup --> %d\n", status); +} + /*-------------------------------------------------------------------------*/ static void @@ -1072,6 +1094,7 @@ zero_unbind (struct usb_gadget *gadget) /* we've already been disconnected ... no i/o is active */ if (dev->req) free_ep_req (gadget->ep0, dev->req); + del_timer_sync (&dev->resume); kfree (dev); set_gadget_data (gadget, 0); } @@ -1176,6 +1199,14 @@ autoconf_fail: usb_gadget_set_selfpowered (gadget); + init_timer (&dev->resume); + dev->resume.function = zero_autoresume; + dev->resume.data = (unsigned long) dev; + if (autoresume) { + source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; + loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; + } + gadget->ep0->driver_data = dev; INFO (dev, "%s, version: " DRIVER_VERSION "\n", longname); @@ -1195,6 +1226,33 @@ enomem: /*-------------------------------------------------------------------------*/ +static void +zero_suspend (struct usb_gadget *gadget) +{ + struct zero_dev *dev = get_gadget_data (gadget); + + if (gadget->speed == USB_SPEED_UNKNOWN) + return; + + if (autoresume) { + mod_timer (&dev->resume, jiffies + (HZ * autoresume)); + DBG (dev, "suspend, wakeup in %d seconds\n", autoresume); + } else + DBG (dev, "suspend\n"); +} + +static void +zero_resume (struct usb_gadget *gadget) +{ + struct zero_dev *dev = get_gadget_data (gadget); + + DBG (dev, "resume\n"); + del_timer (&dev->resume); +} + + +/*-------------------------------------------------------------------------*/ + static struct usb_gadget_driver zero_driver = { #ifdef CONFIG_USB_GADGET_DUALSPEED .speed = USB_SPEED_HIGH, @@ -1208,6 +1266,9 @@ static struct usb_gadget_driver zero_dri .setup = zero_setup, .disconnect = zero_disconnect, + .suspend = zero_suspend, + .resume = zero_resume, + .driver = { .name = (char *) shortname, // .shutdown = ... --- linux-2.6.6/drivers/usb/host/ehci.h 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/host/ehci.h 2004-05-10 01:19:05.791858560 -0700 @@ -366,7 +366,8 @@ struct ehci_qh { struct ehci_qtd *dummy; struct ehci_qh *reclaim; /* next to reclaim */ - atomic_t refcount; + struct ehci_hcd *ehci; + struct kref kref; unsigned stamp; u8 qh_state; --- linux-2.6.6/drivers/usb/host/ehci-hcd.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/host/ehci-hcd.c 2004-05-10 01:19:05.787859168 -0700 @@ -965,7 +965,7 @@ idle_timeout: goto rescan; case QH_STATE_IDLE: /* fully unlinked */ if (list_empty (&qh->qtd_list)) { - qh_put (ehci, qh); + qh_put (qh); break; } /* else FALL THROUGH */ --- linux-2.6.6/drivers/usb/host/ehci-mem.c 2004-03-10 20:41:30.000000000 -0800 +++ 25/drivers/usb/host/ehci-mem.c 2004-05-10 01:19:05.788859016 -0700 @@ -87,6 +87,22 @@ static inline void ehci_qtd_free (struct } +static void qh_destroy (struct kref *kref) +{ + struct ehci_qh *qh = container_of(kref, struct ehci_qh, kref); + struct ehci_hcd *ehci = qh->ehci; + + /* clean qtds first, and know this is not linked */ + if (!list_empty (&qh->qtd_list) || qh->qh_next.ptr) { + ehci_dbg (ehci, "unused qh not empty!\n"); + BUG (); + } + if (qh->dummy) + ehci_qtd_free (ehci, qh->dummy); + usb_put_dev (qh->dev); + dma_pool_free (ehci->qh_pool, qh, qh->qh_dma); +} + static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, int flags) { struct ehci_qh *qh; @@ -98,7 +114,8 @@ static struct ehci_qh *ehci_qh_alloc (st return qh; memset (qh, 0, sizeof *qh); - atomic_set (&qh->refcount, 1); + kref_init(&qh->kref, qh_destroy); + qh->ehci = ehci; qh->qh_dma = dma; // INIT_LIST_HEAD (&qh->qh_list); INIT_LIST_HEAD (&qh->qtd_list); @@ -114,25 +131,15 @@ static struct ehci_qh *ehci_qh_alloc (st } /* to share a qh (cpu threads, or hc) */ -static inline struct ehci_qh *qh_get (/* ehci, */ struct ehci_qh *qh) +static inline struct ehci_qh *qh_get (struct ehci_qh *qh) { - atomic_inc (&qh->refcount); + kref_get(&qh->kref); return qh; } -static void qh_put (struct ehci_hcd *ehci, struct ehci_qh *qh) +static inline void qh_put (struct ehci_qh *qh) { - if (!atomic_dec_and_test (&qh->refcount)) - return; - /* clean qtds first, and know this is not linked */ - if (!list_empty (&qh->qtd_list) || qh->qh_next.ptr) { - ehci_dbg (ehci, "unused qh not empty!\n"); - BUG (); - } - if (qh->dummy) - ehci_qtd_free (ehci, qh->dummy); - usb_put_dev (qh->dev); - dma_pool_free (ehci->qh_pool, qh, qh->qh_dma); + kref_put(&qh->kref); } /*-------------------------------------------------------------------------*/ @@ -145,7 +152,7 @@ static void qh_put (struct ehci_hcd *ehc static void ehci_mem_cleanup (struct ehci_hcd *ehci) { if (ehci->async) - qh_put (ehci, ehci->async); + qh_put (ehci->async); ehci->async = 0; /* DMA consistent memory and pools */ --- linux-2.6.6/drivers/usb/host/ehci-q.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/host/ehci-q.c 2004-05-10 01:19:05.789858864 -0700 @@ -193,7 +193,7 @@ ehci_urb_done (struct ehci_hcd *ehci, st /* ... update hc-wide periodic stats (for usbfs) */ hcd_to_bus (&ehci->hcd)->bandwidth_int_reqs--; } - qh_put (ehci, qh); + qh_put (qh); } spin_lock (&urb->lock); @@ -708,7 +708,7 @@ qh_make ( default: dbg ("bogus dev %p speed %d", urb->dev, urb->dev->speed); done: - qh_put (ehci, qh); + qh_put (qh); return 0; } @@ -951,7 +951,7 @@ static void end_unlink_async (struct ehc // qh->hw_next = cpu_to_le32 (qh->qh_dma); qh->qh_state = QH_STATE_IDLE; qh->qh_next.qh = 0; - qh_put (ehci, qh); // refcount from reclaim + qh_put (qh); // refcount from reclaim /* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */ next = qh->reclaim; @@ -965,7 +965,7 @@ static void end_unlink_async (struct ehc && HCD_IS_RUNNING (ehci->hcd.state)) qh_link_async (ehci, qh); else { - qh_put (ehci, qh); // refcount from async list + qh_put (qh); // refcount from async list /* it's not free to turn the async schedule on/off; leave it * active but idle for a while once it empties. @@ -1067,7 +1067,7 @@ rescan: qh = qh_get (qh); qh->stamp = ehci->stamp; temp = qh_completions (ehci, qh, regs); - qh_put (ehci, qh); + qh_put (qh); if (temp != 0) { goto rescan; } --- linux-2.6.6/drivers/usb/host/ehci-sched.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/usb/host/ehci-sched.c 2004-05-10 01:19:05.790858712 -0700 @@ -312,7 +312,7 @@ static void intr_deschedule ( do { periodic_unlink (ehci, frame, qh); - qh_put (ehci, qh); + qh_put (qh); frame += qh->period; } while (frame < ehci->periodic_size); @@ -355,7 +355,7 @@ static void intr_deschedule ( dbg ("descheduled qh %p, period = %d frame = %d count = %d, urbs = %d", qh, qh->period, frame, - atomic_read (&qh->refcount), ehci->periodic_sched); + atomic_read (&qh->kref.refcount), ehci->periodic_sched); } static int check_period ( @@ -1846,7 +1846,7 @@ restart: modified = qh_completions (ehci, temp.qh, regs); if (unlikely (list_empty (&temp.qh->qtd_list))) intr_deschedule (ehci, temp.qh, 0); - qh_put (ehci, temp.qh); + qh_put (temp.qh); break; case Q_TYPE_FSTN: /* for "save place" FSTNs, look at QH entries --- linux-2.6.6/drivers/usb/host/uhci-hcd.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/host/uhci-hcd.c 2004-05-10 01:19:05.793858256 -0700 @@ -157,8 +157,8 @@ static struct uhci_td *uhci_alloc_td(str return td; } -static inline void uhci_fill_td(struct uhci_td *td, __u32 status, - __u32 token, __u32 buffer) +static inline void uhci_fill_td(struct uhci_td *td, u32 status, + u32 token, u32 buffer) { td->status = cpu_to_le32(status); td->token = cpu_to_le32(token); @@ -184,11 +184,11 @@ static void uhci_insert_td_frame_list(st list_add_tail(&td->fl_list, &ftd->fl_list); td->link = ltd->link; - mb(); + wmb(); ltd->link = cpu_to_le32(td->dma_handle); } else { td->link = uhci->fl->frame[framenum]; - mb(); + wmb(); uhci->fl->frame[framenum] = cpu_to_le32(td->dma_handle); uhci->fl->frame_cpu[framenum] = td; } @@ -218,7 +218,7 @@ static void uhci_remove_td(struct uhci_h ptd->link = td->link; } - mb(); + wmb(); td->link = UHCI_PTR_TERM; list_del_init(&td->fl_list); @@ -332,17 +332,7 @@ static void uhci_insert_qh(struct uhci_h /* Grab the last QH */ lqh = list_entry(skelqh->list.prev, struct uhci_qh, list); - /* - * Patch this endpoint's URB's QHs to point to the next skelqh: - * skelqh --> ... lqh --> newqh --> next skelqh - * Do this first, so the HC always sees the right QH after this one. - */ - list_for_each (tmp, &urbp->queue_list) { - struct urb_priv *turbp = - list_entry(tmp, struct urb_priv, queue_list); - - turbp->qh->link = lqh->link; - } + /* Point to the next skelqh */ urbp->qh->link = lqh->link; wmb(); /* Ordering is important */ @@ -362,15 +352,15 @@ static void uhci_insert_qh(struct uhci_h * * The HC could see (and use!) any of these as we write them. */ + lqh->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH; if (lqh->urbp) { list_for_each (tmp, &lqh->urbp->queue_list) { struct urb_priv *turbp = list_entry(tmp, struct urb_priv, queue_list); - turbp->qh->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH; + turbp->qh->link = lqh->link; } } - lqh->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH; list_add_tail(&urbp->qh->list, &skelqh->list); } @@ -382,7 +372,7 @@ static void uhci_insert_qh(struct uhci_h static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) { struct uhci_qh *pqh; - __u32 newlink; + u32 newlink; if (!qh) return; @@ -423,7 +413,7 @@ static void uhci_remove_qh(struct uhci_h turbp->qh->link = newlink; } } - mb(); + wmb(); /* Leave qh->link in case the HC is on the QH now, it will */ /* continue the rest of the schedule */ @@ -510,7 +500,7 @@ static void uhci_append_queued_urb(struc /* All qh's in the queue need to link to the next queue */ urbp->qh->link = eurbp->qh->link; - mb(); /* Make sure we flush everything */ + wmb(); /* Make sure we flush everything */ lltd->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH; @@ -1044,9 +1034,13 @@ static int uhci_submit_common(struct uhc usb_pipeout(urb->pipe)); } - /* Set the flag on the last packet */ - if (!(urb->transfer_flags & URB_NO_INTERRUPT)) - td->status |= cpu_to_le32(TD_CTRL_IOC); + /* Set the interrupt-on-completion flag on the last packet. + * A more-or-less typical 4 KB URB (= size of one memory page) + * will require about 3 ms to transfer; that's a little on the + * fast side but not enough to justify delaying an interrupt + * more than 2 or 3 URBs, so we will ignore the URB_NO_INTERRUPT + * flag setting. */ + td->status |= cpu_to_le32(TD_CTRL_IOC); qh = uhci_alloc_qh(uhci, urb->dev); if (!qh) @@ -1786,6 +1780,9 @@ static irqreturn_t uhci_irq(struct usb_h spin_unlock(&uhci->schedule_lock); + /* Wake up anyone waiting for an URB to complete */ + wake_up_all(&uhci->waitqh); + return IRQ_HANDLED; } @@ -2086,6 +2083,8 @@ static int uhci_start(struct usb_hcd *hc INIT_LIST_HEAD(&uhci->complete_list); + init_waitqueue_head(&uhci->waitqh); + uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl), &dma_handle, 0); if (!uhci->fl) { @@ -2296,6 +2295,9 @@ static void uhci_stop(struct usb_hcd *hc uhci_free_pending_qhs(uhci); uhci_free_pending_tds(uhci); spin_unlock_irq(&uhci->schedule_lock); + + /* Wake up anyone waiting for an URB to complete */ + wake_up_all(&uhci->waitqh); release_uhci(uhci); } @@ -2361,6 +2363,46 @@ static void uhci_hcd_free(struct usb_hcd kfree(hcd_to_uhci(hcd)); } +/* Are there any URBs for a particular device/endpoint on a given list? */ +static int urbs_for_ep_list(struct list_head *head, + struct hcd_dev *hdev, int ep) +{ + struct urb_priv *urbp; + + list_for_each_entry(urbp, head, urb_list) { + struct urb *urb = urbp->urb; + + if (hdev == urb->dev->hcpriv && ep == + (usb_pipeendpoint(urb->pipe) | + usb_pipein(urb->pipe))) + return 1; + } + return 0; +} + +/* Are there any URBs for a particular device/endpoint? */ +static int urbs_for_ep(struct uhci_hcd *uhci, struct hcd_dev *hdev, int ep) +{ + int rc; + + spin_lock_irq(&uhci->schedule_lock); + rc = (urbs_for_ep_list(&uhci->urb_list, hdev, ep) || + urbs_for_ep_list(&uhci->complete_list, hdev, ep) || + urbs_for_ep_list(&uhci->urb_remove_list, hdev, ep)); + spin_unlock_irq(&uhci->schedule_lock); + return rc; +} + +/* Wait until all the URBs for a particular device/endpoint are gone */ +static void uhci_hcd_endpoint_disable(struct usb_hcd *hcd, + struct hcd_dev *hdev, int endpoint) +{ + struct uhci_hcd *uhci = hcd_to_uhci(hcd); + + wait_event_interruptible(uhci->waitqh, + !urbs_for_ep(uhci, hdev, endpoint)); +} + static int uhci_hcd_get_frame_number(struct usb_hcd *hcd) { return uhci_get_current_frame_number(hcd_to_uhci(hcd)); @@ -2390,6 +2432,7 @@ static const struct hc_driver uhci_drive .urb_enqueue = uhci_urb_enqueue, .urb_dequeue = uhci_urb_dequeue, + .endpoint_disable = uhci_hcd_endpoint_disable, .get_frame_number = uhci_hcd_get_frame_number, .hub_status_data = uhci_hub_status_data, --- linux-2.6.6/drivers/usb/host/uhci-hcd.h 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/host/uhci-hcd.h 2004-05-10 01:19:05.794858104 -0700 @@ -80,7 +80,7 @@ #define CAN_SCHEDULE_FRAMES 1000 /* how far future frames can be scheduled */ struct uhci_frame_list { - __u32 frame[UHCI_NUMFRAMES]; + u32 frame[UHCI_NUMFRAMES]; void *frame_cpu[UHCI_NUMFRAMES]; @@ -105,8 +105,8 @@ struct urb_priv; */ struct uhci_qh { /* Hardware fields */ - __u32 link; /* Next queue */ - __u32 element; /* Queue element pointer */ + u32 link; /* Next queue */ + u32 element; /* Queue element pointer */ /* Software fields */ dma_addr_t dma_handle; @@ -185,10 +185,10 @@ struct uhci_qh { */ struct uhci_td { /* Hardware fields */ - __u32 link; - __u32 status; - __u32 token; - __u32 buffer; + u32 link; + u32 status; + u32 token; + u32 buffer; /* Software fields */ dma_addr_t dma_handle; @@ -370,6 +370,8 @@ struct uhci_hcd { int rh_numports; struct timer_list stall_timer; + + wait_queue_head_t waitqh; /* endpoint_disable waiters */ }; struct urb_priv { --- linux-2.6.6/drivers/usb/input/hid-core.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/usb/input/hid-core.c 2004-05-10 01:19:05.796857800 -0700 @@ -1412,6 +1412,14 @@ void hid_init_reports(struct hid_device #define USB_VENDOR_ID_CHIC 0x05fe #define USB_DEVICE_ID_CHIC_GAMEPAD 0x0014 +#define USB_VENDOR_ID_GLAB 0x06c2 +#define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 +#define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039 + +#define USB_VENDOR_ID_WISEGROUP 0x0925 +#define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101 +#define USB_DEVICE_ID_4_PHIDGETSERVO_20 0x8104 + struct hid_blacklist { __u16 idVendor; __u16 idProduct; @@ -1459,6 +1467,10 @@ struct hid_blacklist { { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 7, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PTU, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET }, --- linux-2.6.6/drivers/usb/input/Kconfig 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/input/Kconfig 2004-05-10 01:19:05.795857952 -0700 @@ -191,6 +191,19 @@ config USB_MTOUCH To compile this driver as a module, choose M here: the module will be called mtouchusb. +config USB_EGALAX + tristate "eGalax TouchKit USB Touchscreen Driver" + depends on USB && INPUT + ---help--- + Say Y here if you want to use a eGalax TouchKit USB + Touchscreen controller. + + The driver has been tested on a Xenarc 700TSV monitor + with eGalax touchscreen. + + To compile this driver as a module, choose M here: the + module will be called touchkitusb. + config USB_XPAD tristate "X-Box gamepad support" depends on USB && INPUT --- linux-2.6.6/drivers/usb/input/Makefile 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/input/Makefile 2004-05-10 01:19:05.795857952 -0700 @@ -33,6 +33,7 @@ obj-$(CONFIG_USB_KBD) += usbkbd.o obj-$(CONFIG_USB_KBTAB) += kbtab.o obj-$(CONFIG_USB_MOUSE) += usbmouse.o obj-$(CONFIG_USB_MTOUCH) += mtouchusb.o +obj-$(CONFIG_USB_EGALAX) += touchkitusb.o obj-$(CONFIG_USB_POWERMATE) += powermate.o obj-$(CONFIG_USB_WACOM) += wacom.o obj-$(CONFIG_USB_XPAD) += xpad.o --- linux-2.6.6/drivers/usb/input/mtouchusb.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/usb/input/mtouchusb.c 2004-05-10 01:19:05.798857496 -0700 @@ -28,6 +28,12 @@ * Complete rewrite using Linux Input in 2.6.3 * Unfortunately no calibration support at this time * + * 1.4 04/25/2004 (TEJ) tejohnson@yahoo.com + * Changed reset from standard USB dev reset to vendor reset + * Changed data sent to host from compensated to raw coordinates + * Eliminated vendor/product module params + * Performed multiple successfull tests with an EXII-5010UC + * *****************************************************************************/ #include @@ -45,25 +51,28 @@ #include #include -#define MTOUCHUSB_MIN_XC 0xc8 -#define MTOUCHUSB_MAX_XC 0xff78 +#define MTOUCHUSB_MIN_XC 0x0 +#define MTOUCHUSB_MAX_XC 0x4000 #define MTOUCHUSB_XC_FUZZ 0x0 #define MTOUCHUSB_XC_FLAT 0x0 #define MTOUCHUSB_MIN_YC 0x0 -#define MTOUCHUSB_MAX_YC 0xff78 +#define MTOUCHUSB_MAX_YC 0x4000 #define MTOUCHUSB_YC_FUZZ 0x0 #define MTOUCHUSB_YC_FLAT 0x0 -#define MTOUCHUSB_ASYC_REPORT 1 -#define MTOUCHUSB_REPORT_SIZE_DATA 11 + +#define MTOUCHUSB_ASYNC_REPORT 1 +#define MTOUCHUSB_RESET 7 +#define MTOUCHUSB_REPORT_DATA_SIZE 11 #define MTOUCHUSB_REQ_CTRLLR_ID 10 -#define MTOUCHUSB_GET_XC(data) (data[4]<<8 | data[3]) -#define MTOUCHUSB_GET_YC(data) (data[6]<<8 | data[5]) +#define MTOUCHUSB_GET_XC(data) (data[8]<<8 | data[7]) +#define MTOUCHUSB_GET_YC(data) (data[10]<<8 | data[9]) #define MTOUCHUSB_GET_TOUCHED(data) ((data[2] & 0x40) ? 1:0) -#define DRIVER_VERSION "v0.1" +#define DRIVER_VERSION "v1.4" #define DRIVER_AUTHOR "Todd E. Johnson, tejohnson@yahoo.com" -#define DRIVER_DESC "Microtouch USB HID Touchscreen Driver" +#define DRIVER_DESC "3M USB Touchscreen Driver" +#define DRIVER_LICENSE "GPL" struct mtouch_usb { unsigned char *data; @@ -76,11 +85,9 @@ struct mtouch_usb { char phys[64]; }; -static __s32 vendor=-1, product=-1; - static struct usb_device_id mtouchusb_devices [] = { - { USB_DEVICE(0x0596, 0x0001) }, /* 3M (Formerly MicroTouch) 14-206 */ - { } /* Terminating entry */ + { USB_DEVICE(0x0596, 0x0001) }, + { } }; static void mtouchusb_irq(struct urb *urb, struct pt_regs *regs) @@ -135,8 +142,10 @@ static int mtouchusb_open (struct input_ mtouch->irq->dev = mtouch->udev; - if (usb_submit_urb (mtouch->irq, GFP_ATOMIC)) + if (usb_submit_urb (mtouch->irq, GFP_ATOMIC)) { + mtouch->open--; return -EIO; + } return 0; } @@ -153,7 +162,7 @@ static int mtouchusb_alloc_buffers(struc { dbg("%s - called", __FUNCTION__); - mtouch->data = usb_buffer_alloc(udev, MTOUCHUSB_REPORT_SIZE_DATA, + mtouch->data = usb_buffer_alloc(udev, MTOUCHUSB_REPORT_DATA_SIZE, SLAB_ATOMIC, &mtouch->data_dma); if (!mtouch->data) @@ -167,7 +176,7 @@ static void mtouchusb_free_buffers(struc dbg("%s - called", __FUNCTION__); if (mtouch->data) - usb_buffer_free(udev, MTOUCHUSB_REPORT_SIZE_DATA, + usb_buffer_free(udev, MTOUCHUSB_REPORT_DATA_SIZE, mtouch->data, mtouch->data_dma); } @@ -180,41 +189,8 @@ static int mtouchusb_probe(struct usb_in char path[64]; char *buf; int nRet; - int ix; - char valid_device = 0; dbg("%s - called", __FUNCTION__); - if (vendor != -1 && product != -1) { - info("%s - User specified USB Touch -- Vend:Prod - %x:%x", - __FUNCTION__, vendor, product); - } - - for (ix = 0; ix < sizeof (mtouchusb_devices) / - sizeof (struct usb_device_id); ix++) { - if ((udev->descriptor.idVendor == - mtouchusb_devices [ix].idVendor) && - (udev->descriptor.idProduct == - mtouchusb_devices [ix].idProduct)) { - valid_device = 1; - break; - } - } - - if (udev->descriptor.idVendor == vendor && - udev->descriptor.idProduct == product) { /* User specified */ - valid_device = 1; - } - - if (!valid_device) { - err("%s - No valid device!", __FUNCTION__); - return -EIO; - } - - if (udev->descriptor.bNumConfigurations != 1) { - err("%s - Only one device configuration is supported.", - __FUNCTION__); - return -EIO; - } dbg("%s - setting interface", __FUNCTION__); interface = intf->cur_altsetting; @@ -222,11 +198,6 @@ static int mtouchusb_probe(struct usb_in dbg("%s - setting endpoint", __FUNCTION__); endpoint = &interface->endpoint[0].desc; - if (interface->desc.bNumEndpoints != 1) { - err("%s - Only one endpoint is supported.", __FUNCTION__); - return -EIO; - } - if (!(mtouch = kmalloc (sizeof (struct mtouch_usb), GFP_KERNEL))) { err("%s - Out of memory.", __FUNCTION__); return -ENOMEM; @@ -266,8 +237,8 @@ static int mtouchusb_probe(struct usb_in mtouch->input.absmax[ABS_X] = MTOUCHUSB_MAX_XC; mtouch->input.absfuzz[ABS_X] = MTOUCHUSB_XC_FUZZ; mtouch->input.absflat[ABS_X] = MTOUCHUSB_XC_FLAT; - mtouch->input.absmin[ABS_Y] = MTOUCHUSB_MAX_YC; - mtouch->input.absmax[ABS_Y] = MTOUCHUSB_MIN_YC; + mtouch->input.absmin[ABS_Y] = MTOUCHUSB_MIN_YC; + mtouch->input.absmax[ABS_Y] = MTOUCHUSB_MAX_YC; mtouch->input.absfuzz[ABS_Y] = MTOUCHUSB_YC_FUZZ; mtouch->input.absflat[ABS_Y] = MTOUCHUSB_YC_FLAT; @@ -290,15 +261,15 @@ static int mtouchusb_probe(struct usb_in kfree(buf); nRet = usb_control_msg(mtouch->udev, - usb_rcvctrlpipe(udev, 0x80), - USB_REQ_GET_CONFIGURATION, - USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE, + usb_rcvctrlpipe(udev, 0), + MTOUCHUSB_RESET, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 1, 0, - 0x81, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT); - dbg("%s - usb_control_msg - USB_REQ_GET_CONFIGURATION - bytes|err: %d", + dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d", __FUNCTION__, nRet); dbg("%s - usb_alloc_urb: mtouch->irq", __FUNCTION__); @@ -315,7 +286,7 @@ static int mtouchusb_probe(struct usb_in mtouch->udev, usb_rcvintpipe(mtouch->udev, 0x81), mtouch->data, - MTOUCHUSB_REPORT_SIZE_DATA, + MTOUCHUSB_REPORT_DATA_SIZE, mtouchusb_irq, mtouch, endpoint->bInterval); @@ -324,15 +295,15 @@ static int mtouchusb_probe(struct usb_in input_register_device(&mtouch->input); nRet = usb_control_msg(mtouch->udev, - usb_rcvctrlpipe(udev, 0x80), - MTOUCHUSB_ASYC_REPORT, + usb_rcvctrlpipe(udev, 0), + MTOUCHUSB_ASYNC_REPORT, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - MTOUCHUSB_ASYC_REPORT, - MTOUCHUSB_ASYC_REPORT, + 1, + 1, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT); - dbg("%s - usb_control_msg - MTOUCHUSB_ASYC_REPORT - bytes|err: %d", + dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d", __FUNCTION__, nRet); printk(KERN_INFO "input: %s on %s\n", mtouch->name, path); @@ -383,9 +354,3 @@ module_exit(mtouchusb_cleanup); MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); MODULE_LICENSE("GPL"); -MODULE_PARM(vendor, "i"); -MODULE_PARM_DESC(vendor, "User specified USB idVendor"); -MODULE_PARM(product, "i"); -MODULE_PARM_DESC(product, "User specified USB idProduct"); - - --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/drivers/usb/input/touchkitusb.c 2004-05-10 01:19:05.800857192 -0700 @@ -0,0 +1,310 @@ +/****************************************************************************** + * touchkitusb.c -- Driver for eGalax TouchKit USB Touchscreens + * + * Copyright (C) 2004 by Daniel Ritz + * Copyright (C) by Todd E. Johnson (mtouchusb.c) + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Based upon mtouchusb.c + * + *****************************************************************************/ + +//#define DEBUG + +#include +#include +#include +#include +#include +#include + +#if !defined(DEBUG) && defined(CONFIG_USB_DEBUG) +#define DEBUG +#endif +#include + + +#define TOUCHKIT_MIN_XC 0x0 +#define TOUCHKIT_MAX_XC 0x07ff +#define TOUCHKIT_XC_FUZZ 0x0 +#define TOUCHKIT_XC_FLAT 0x0 +#define TOUCHKIT_MIN_YC 0x0 +#define TOUCHKIT_MAX_YC 0x07ff +#define TOUCHKIT_YC_FUZZ 0x0 +#define TOUCHKIT_YC_FLAT 0x0 +#define TOUCHKIT_REPORT_DATA_SIZE 8 + +#define TOUCHKIT_DOWN 0x01 +#define TOUCHKIT_POINT_TOUCH 0x81 +#define TOUCHKIT_POINT_NOTOUCH 0x80 + +#define TOUCHKIT_GET_TOUCHED(dat) ((((dat)[0]) & TOUCHKIT_DOWN) ? 1 : 0) +#define TOUCHKIT_GET_X(dat) (((dat)[3] << 7) | (dat)[4]) +#define TOUCHKIT_GET_Y(dat) (((dat)[1] << 7) | (dat)[2]) + +#define DRIVER_VERSION "v0.1" +#define DRIVER_AUTHOR "Daniel Ritz " +#define DRIVER_DESC "eGalax TouchKit USB HID Touchscreen Driver" + +struct touchkit_usb { + unsigned char *data; + dma_addr_t data_dma; + struct urb *irq; + struct usb_device *udev; + struct input_dev input; + int open; + char name[128]; + char phys[64]; +}; + +static struct usb_device_id touchkit_devices[] = { + {USB_DEVICE(0x3823, 0x0001)}, + {USB_DEVICE(0x0eef, 0x0001)}, + {} +}; + +static void touchkit_irq(struct urb *urb, struct pt_regs *regs) +{ + struct touchkit_usb *touchkit = urb->context; + int retval; + + switch (urb->status) { + case 0: + /* success */ + break; + case -ETIMEDOUT: + /* this urb is timing out */ + dbg("%s - urb timed out - was the device unplugged?", + __FUNCTION__); + return; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", + __FUNCTION__, urb->status); + return; + default: + dbg("%s - nonzero urb status received: %d", + __FUNCTION__, urb->status); + goto exit; + } + + input_regs(&touchkit->input, regs); + input_report_key(&touchkit->input, BTN_TOUCH, + TOUCHKIT_GET_TOUCHED(touchkit->data)); + input_report_abs(&touchkit->input, ABS_X, + TOUCHKIT_GET_X(touchkit->data)); + input_report_abs(&touchkit->input, ABS_Y, + TOUCHKIT_GET_Y(touchkit->data)); + input_sync(&touchkit->input); + +exit: + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) + err("%s - usb_submit_urb failed with result: %d", + __FUNCTION__, retval); +} + +static int touchkit_open(struct input_dev *input) +{ + struct touchkit_usb *touchkit = input->private; + + if (touchkit->open++) + return 0; + + touchkit->irq->dev = touchkit->udev; + + if (usb_submit_urb(touchkit->irq, GFP_ATOMIC)) { + touchkit->open--; + return -EIO; + } + + return 0; +} + +static void touchkit_close(struct input_dev *input) +{ + struct touchkit_usb *touchkit = input->private; + + if (!--touchkit->open) + usb_unlink_urb(touchkit->irq); +} + +static int touchkit_alloc_buffers(struct usb_device *udev, + struct touchkit_usb *touchkit) +{ + touchkit->data = usb_buffer_alloc(udev, TOUCHKIT_REPORT_DATA_SIZE, + SLAB_ATOMIC, &touchkit->data_dma); + + if (!touchkit->data) + return -1; + + return 0; +} + +static void touchkit_free_buffers(struct usb_device *udev, + struct touchkit_usb *touchkit) +{ + if (touchkit->data) + usb_buffer_free(udev, TOUCHKIT_REPORT_DATA_SIZE, + touchkit->data, touchkit->data_dma); +} + +static int touchkit_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + int ret; + struct touchkit_usb *touchkit; + struct usb_host_interface *interface; + struct usb_endpoint_descriptor *endpoint; + struct usb_device *udev = interface_to_usbdev(intf); + char path[64]; + char *buf; + + interface = intf->cur_altsetting; + endpoint = &interface->endpoint[0].desc; + + touchkit = kmalloc(sizeof(struct touchkit_usb), GFP_KERNEL); + if (!touchkit) + return -ENOMEM; + + memset(touchkit, 0, sizeof(struct touchkit_usb)); + touchkit->udev = udev; + + if (touchkit_alloc_buffers(udev, touchkit)) { + ret = -ENOMEM; + goto out_free; + } + + touchkit->input.private = touchkit; + touchkit->input.open = touchkit_open; + touchkit->input.close = touchkit_close; + + usb_make_path(udev, path, 64); + sprintf(touchkit->phys, "%s/input0", path); + + touchkit->input.name = touchkit->name; + touchkit->input.phys = touchkit->phys; + touchkit->input.id.bustype = BUS_USB; + touchkit->input.id.vendor = udev->descriptor.idVendor; + touchkit->input.id.product = udev->descriptor.idProduct; + touchkit->input.id.version = udev->descriptor.bcdDevice; + touchkit->input.dev = &intf->dev; + + touchkit->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + touchkit->input.absbit[0] = BIT(ABS_X) | BIT(ABS_Y); + touchkit->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); + + /* Used to Scale Compensated Data */ + touchkit->input.absmin[ABS_X] = TOUCHKIT_MIN_XC; + touchkit->input.absmax[ABS_X] = TOUCHKIT_MAX_XC; + touchkit->input.absfuzz[ABS_X] = TOUCHKIT_XC_FUZZ; + touchkit->input.absflat[ABS_X] = TOUCHKIT_XC_FLAT; + touchkit->input.absmin[ABS_Y] = TOUCHKIT_MIN_YC; + touchkit->input.absmax[ABS_Y] = TOUCHKIT_MAX_YC; + touchkit->input.absfuzz[ABS_Y] = TOUCHKIT_YC_FUZZ; + touchkit->input.absflat[ABS_Y] = TOUCHKIT_YC_FLAT; + + buf = kmalloc(63, GFP_KERNEL); + if (!buf) { + ret = -ENOMEM; + goto out_free_buffers; + } + + if (udev->descriptor.iManufacturer && + usb_string(udev, udev->descriptor.iManufacturer, buf, 63) > 0) + strcat(touchkit->name, buf); + if (udev->descriptor.iProduct && + usb_string(udev, udev->descriptor.iProduct, buf, 63) > 0) + sprintf(touchkit->name, "%s %s", touchkit->name, buf); + + if (!strlen(touchkit->name)) + sprintf(touchkit->name, "USB Touchscreen %04x:%04x", + touchkit->input.id.vendor, touchkit->input.id.product); + + kfree(buf); + + touchkit->irq = usb_alloc_urb(0, GFP_KERNEL); + if (!touchkit->irq) { + dbg("%s - usb_alloc_urb failed: touchkit->irq", __FUNCTION__); + ret = -ENOMEM; + goto out_free_buffers; + } + + usb_fill_int_urb(touchkit->irq, touchkit->udev, + usb_rcvintpipe(touchkit->udev, 0x81), + touchkit->data, TOUCHKIT_REPORT_DATA_SIZE, + touchkit_irq, touchkit, endpoint->bInterval); + + input_register_device(&touchkit->input); + + printk(KERN_INFO "input: %s on %s\n", touchkit->name, path); + usb_set_intfdata(intf, touchkit); + + return 0; + +out_free_buffers: + touchkit_free_buffers(udev, touchkit); +out_free: + kfree(touchkit); + return ret; +} + +static void touchkit_disconnect(struct usb_interface *intf) +{ + struct touchkit_usb *touchkit = usb_get_intfdata(intf); + + dbg("%s - called", __FUNCTION__); + + if (!touchkit) + return; + + dbg("%s - touchkit is initialized, cleaning up", __FUNCTION__); + usb_set_intfdata(intf, NULL); + input_unregister_device(&touchkit->input); + usb_unlink_urb(touchkit->irq); + usb_free_urb(touchkit->irq); + touchkit_free_buffers(interface_to_usbdev(intf), touchkit); + kfree(touchkit); +} + +MODULE_DEVICE_TABLE(usb, touchkit_devices); + +static struct usb_driver touchkit_driver = { + .owner = THIS_MODULE, + .name = "touchkitusb", + .probe = touchkit_probe, + .disconnect = touchkit_disconnect, + .id_table = touchkit_devices, +}; + +static int __init touchkit_init(void) +{ + return usb_register(&touchkit_driver); +} + +static void __exit touchkit_cleanup(void) +{ + usb_deregister(&touchkit_driver); +} + +module_init(touchkit_init); +module_exit(touchkit_cleanup); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); --- linux-2.6.6/drivers/usb/Makefile 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/Makefile 2004-05-10 01:19:05.762862968 -0700 @@ -66,3 +66,4 @@ obj-$(CONFIG_USB_SPEEDTOUCH) += misc/ obj-$(CONFIG_USB_TEST) += misc/ obj-$(CONFIG_USB_TIGL) += misc/ obj-$(CONFIG_USB_USS720) += misc/ +obj-$(CONFIG_USB_PHIDGETSERVO) += misc/ --- linux-2.6.6/drivers/usb/media/dsbr100.c 2004-02-17 20:48:45.000000000 -0800 +++ 25/drivers/usb/media/dsbr100.c 2004-05-10 01:19:55.933235912 -0700 @@ -33,6 +33,9 @@ History: + Version 0.40: + Markus: Updates for 2.6.x kernels, code layout changes, name sanitizing + Version 0.30: Markus: Updates for 2.5.x kernel and more ISO compliant source @@ -75,13 +78,17 @@ /* * Version Information */ -#define DRIVER_VERSION "v0.30" +#define DRIVER_VERSION "v0.40" #define DRIVER_AUTHOR "Markus Demleitner " #define DRIVER_DESC "D-Link DSB-R100 USB FM radio driver" #define DSB100_VENDOR 0x04b4 #define DSB100_PRODUCT 0x1002 +/* Commands the device appears to understand */ +#define DSB100_TUNE 1 +#define DSB100_ONOFF 2 + #define TB_LEN 16 /* Frequency limits in MHz -- these are European values. For Japanese @@ -102,15 +109,19 @@ static int usb_dsbr100_close(struct inod static int radio_nr = -1; MODULE_PARM(radio_nr, "i"); -typedef struct -{ - struct usb_device *dev; +/* Data for one (physical) device */ +typedef struct { + struct usb_device *usbdev; + struct video_device *videodev; unsigned char transfer_buffer[TB_LEN]; int curfreq; int stereo; -} usb_dsbr100; + int users; + int removed; +} dsbr100_device; +/* File system interface */ static struct file_operations usb_dsbr100_fops = { .owner = THIS_MODULE, .open = usb_dsbr100_open, @@ -118,65 +129,84 @@ static struct file_operations usb_dsbr10 .ioctl = usb_dsbr100_ioctl, .llseek = no_llseek, }; -static struct video_device usb_dsbr100_radio= + +/* V4L interface */ +static struct video_device dsbr100_videodev_template= { .owner = THIS_MODULE, .name = "D-Link DSB-R 100", .type = VID_TYPE_TUNER, .hardware = VID_HARDWARE_AZTECH, .fops = &usb_dsbr100_fops, + .release = video_device_release, }; -static int users = 0; - -static struct usb_device_id usb_dsbr100_table [] = { +static struct usb_device_id usb_dsbr100_device_table [] = { { USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) }, { } /* Terminating entry */ }; -MODULE_DEVICE_TABLE (usb, usb_dsbr100_table); +MODULE_DEVICE_TABLE (usb, usb_dsbr100_device_table); +/* USB subsystem interface */ static struct usb_driver usb_dsbr100_driver = { .owner = THIS_MODULE, .name = "dsbr100", .probe = usb_dsbr100_probe, .disconnect = usb_dsbr100_disconnect, - .id_table = usb_dsbr100_table, + .id_table = usb_dsbr100_device_table, }; +/* Low-level device interface begins here */ -static int dsbr100_start(usb_dsbr100 *radio) +/* switch on radio */ +static int dsbr100_start(dsbr100_device *radio) { - if (usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0), - 0x00, 0xC0, 0x00, 0xC7, radio->transfer_buffer, 8, 300)<0 || - usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0), - 0x02, 0xC0, 0x01, 0x00, radio->transfer_buffer, 8, 300)<0) + if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), + USB_REQ_GET_STATUS, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x00, 0xC7, radio->transfer_buffer, 8, 300)<0 || + usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), + DSB100_ONOFF, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x01, 0x00, radio->transfer_buffer, 8, 300)<0) return -1; return (radio->transfer_buffer)[0]; } -static int dsbr100_stop(usb_dsbr100 *radio) +/* switch off radio */ +static int dsbr100_stop(dsbr100_device *radio) { - if (usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0), - 0x00, 0xC0, 0x16, 0x1C, radio->transfer_buffer, 8, 300)<0 || - usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0), - 0x02, 0xC0, 0x00, 0x00, radio->transfer_buffer, 8, 300)<0) + if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), + USB_REQ_GET_STATUS, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x16, 0x1C, radio->transfer_buffer, 8, 300)<0 || + usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), + DSB100_ONOFF, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x00, 0x00, radio->transfer_buffer, 8, 300)<0) return -1; return (radio->transfer_buffer)[0]; } - -static int dsbr100_setfreq(usb_dsbr100 *radio, int freq) +/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */ +static int dsbr100_setfreq(dsbr100_device *radio, int freq) { freq = (freq/16*80)/1000+856; - if (usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0), - 0x01, 0xC0, (freq>>8)&0x00ff, freq&0xff, - radio->transfer_buffer, 8, 300)<0 || - usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0), - 0x00, 0xC0, 0x96, 0xB7, radio->transfer_buffer, 8, 300)<0 || - usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0), - 0x00, 0xC0, 0x00, 0x24, radio->transfer_buffer, 8, 300)<0) { + if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), + DSB100_TUNE, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + (freq>>8)&0x00ff, freq&0xff, + radio->transfer_buffer, 8, 300)<0 || + usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), + USB_REQ_GET_STATUS, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x96, 0xB7, radio->transfer_buffer, 8, 300)<0 || + usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), + USB_REQ_GET_STATUS, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x00, 0x24, radio->transfer_buffer, 8, 300)<0) { radio->stereo = -1; return -1; } @@ -184,61 +214,91 @@ static int dsbr100_setfreq(usb_dsbr100 * return (radio->transfer_buffer)[0]; } -static void dsbr100_getstat(usb_dsbr100 *radio) -{ - if (usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0), - 0x00, 0xC0, 0x00 , 0x24, radio->transfer_buffer, 8, 300)<0) +/* return the device status. This is, in effect, just whether it +sees a stereo signal or not. Pity. */ +static void dsbr100_getstat(dsbr100_device *radio) +{ + if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), + USB_REQ_GET_STATUS, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x00 , 0x24, radio->transfer_buffer, 8, 300)<0) radio->stereo = -1; else radio->stereo = ! (radio->transfer_buffer[0]&0x01); } +/* USB subsystem interface begins here */ + +/* check if the device is present and register with v4l and +usb if it is */ static int usb_dsbr100_probe(struct usb_interface *intf, const struct usb_device_id *id) { - usb_dsbr100 *radio; + dsbr100_device *radio; - if (!(radio = kmalloc(sizeof(usb_dsbr100),GFP_KERNEL))) + if (!(radio = kmalloc(sizeof(dsbr100_device), GFP_KERNEL))) return -ENOMEM; - usb_dsbr100_radio.priv = radio; - radio->dev = interface_to_usbdev (intf); + if (!(radio->videodev = video_device_alloc())) { + kfree(radio); + return -ENOMEM; + } + memcpy(radio->videodev, &dsbr100_videodev_template, + sizeof(dsbr100_videodev_template)); + radio->removed = 0; + radio->users = 0; + radio->usbdev = interface_to_usbdev(intf); radio->curfreq = FREQ_MIN*FREQ_MUL; - usb_set_intfdata (intf, radio); + video_set_drvdata(radio->videodev, radio); + if (video_register_device(radio->videodev, VFL_TYPE_RADIO, + radio_nr)) { + warn("Could not register video device"); + video_device_release(radio->videodev); + kfree(radio); + return -EIO; + } + usb_set_intfdata(intf, radio); return 0; } +/* handle unplugging of the device, release data structures +if nothing keeps us from doing it. If something is still +keeping us busy, the release callback of v4l will take care +of releasing it. stv680.c does not relase its private +data, so I don't do this here either. Checking out the +code I'd expect I better did that, but if there's a memory +leak here it's tiny (~50 bytes per disconnect) */ static void usb_dsbr100_disconnect(struct usb_interface *intf) { - usb_dsbr100 *radio = usb_get_intfdata (intf); + dsbr100_device *radio = usb_get_intfdata(intf); usb_set_intfdata (intf, NULL); - if (radio) { - lock_kernel(); - if (users) { - unlock_kernel(); - return; + video_unregister_device(radio->videodev); + radio->videodev = NULL; + if (radio->users) { + kfree(radio); + } else { + radio->removed = 1; } - kfree(radio); - usb_dsbr100_radio.priv = NULL; - unlock_kernel(); } } + +/* Video for Linux interface */ + static int usb_dsbr100_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) { - struct video_device *dev = video_devdata(file); - usb_dsbr100 *radio=dev->priv; + dsbr100_device *radio=video_get_drvdata(video_devdata(file)); if (!radio) - return -EINVAL; + return -EIO; - switch(cmd) - { + switch(cmd) { case VIDIOCGCAP: { struct video_capability *v = arg; + memset(v, 0, sizeof(*v)); v->type = VID_TYPE_TUNER; v->channels = 1; @@ -248,6 +308,7 @@ static int usb_dsbr100_do_ioctl(struct i } case VIDIOCGTUNER: { struct video_tuner *v = arg; + dsbr100_getstat(radio); if(v->tuner) /* Only 1 tuner */ return -EINVAL; @@ -263,21 +324,21 @@ static int usb_dsbr100_do_ioctl(struct i } case VIDIOCSTUNER: { struct video_tuner *v = arg; + if(v->tuner!=0) return -EINVAL; /* Only 1 tuner so no setting needed ! */ return 0; } - case VIDIOCGFREQ: - { + case VIDIOCGFREQ: { int *freq = arg; + if (radio->curfreq==-1) return -EINVAL; *freq = radio->curfreq; return 0; } - case VIDIOCSFREQ: - { + case VIDIOCSFREQ: { int *freq = arg; radio->curfreq = *freq; @@ -287,6 +348,7 @@ static int usb_dsbr100_do_ioctl(struct i } case VIDIOCGAUDIO: { struct video_audio *v = arg; + memset(v, 0, sizeof(*v)); v->flags |= VIDEO_AUDIO_MUTABLE; v->mode = VIDEO_SOUND_STEREO; @@ -297,9 +359,9 @@ static int usb_dsbr100_do_ioctl(struct i } case VIDIOCSAUDIO: { struct video_audio *v = arg; + if (v->audio) return -EINVAL; - if (v->flags&VIDEO_AUDIO_MUTE) { if (dsbr100_stop(radio)==-1) warn("Radio did not respond properly"); @@ -322,64 +384,40 @@ static int usb_dsbr100_ioctl(struct inod static int usb_dsbr100_open(struct inode *inode, struct file *file) { - struct video_device *dev = video_devdata(file); - usb_dsbr100 *radio=dev->priv; + dsbr100_device *radio=video_get_drvdata(video_devdata(file)); - if (! radio) { - warn("Radio not initialised"); - return -EAGAIN; - } - if(users) - { - warn("Radio in use"); - return -EBUSY; - } - users++; - if (dsbr100_start(radio)<0) + radio->users = 1; + if (dsbr100_start(radio)<0) { warn("Radio did not start up properly"); + radio->users = 0; + return -EIO; + } dsbr100_setfreq(radio, radio->curfreq); return 0; } static int usb_dsbr100_close(struct inode *inode, struct file *file) { - struct video_device *dev = video_devdata(file); - usb_dsbr100 *radio=dev->priv; + dsbr100_device *radio=video_get_drvdata(video_devdata(file)); if (!radio) return -ENODEV; - users--; + radio->users = 0; + if (radio->removed) { + kfree(radio); + } return 0; } static int __init dsbr100_init(void) { - int retval; - usb_dsbr100_radio.priv = NULL; - retval = usb_register(&usb_dsbr100_driver); - if (retval) - goto failed_usb_register; - retval = video_register_device(&usb_dsbr100_radio, VFL_TYPE_RADIO, - radio_nr); - if (retval) { - warn("Couldn't register video device"); - goto failed_video_register; - } + int retval = usb_register(&usb_dsbr100_driver); info(DRIVER_VERSION ":" DRIVER_DESC); - return 0; -failed_video_register: - usb_deregister(&usb_dsbr100_driver); -failed_usb_register: return retval; } static void __exit dsbr100_exit(void) { - usb_dsbr100 *radio=usb_dsbr100_radio.priv; - - if (radio) - dsbr100_stop(radio); - video_unregister_device(&usb_dsbr100_radio); usb_deregister(&usb_dsbr100_driver); } --- linux-2.6.6/drivers/usb/media/ibmcam.c 2003-08-08 22:55:13.000000000 -0700 +++ 25/drivers/usb/media/ibmcam.c 2004-05-10 01:19:05.805856432 -0700 @@ -3647,7 +3647,7 @@ static int ibmcam_probe(struct usb_inter { struct usb_device *dev = interface_to_usbdev(intf); struct uvd *uvd = NULL; - int i, nas, model=0, canvasX=0, canvasY=0; + int ix, i, nas, model=0, canvasX=0, canvasY=0; int actInterface=-1, inactInterface=-1, maxPS=0; __u8 ifnum = intf->altsetting->desc.bInterfaceNumber; unsigned char video_ep = 0; @@ -3718,7 +3718,7 @@ static int ibmcam_probe(struct usb_inter } while (0); /* Validate found interface: must have one ISO endpoint */ - nas = dev->actconfig->interface[ifnum]->num_altsetting; + nas = intf->num_altsetting; if (debug > 0) info("Number of alternate settings=%d.", nas); if (nas < 2) { @@ -3726,11 +3726,12 @@ static int ibmcam_probe(struct usb_inter return -ENODEV; } /* Validate all alternate settings */ - for (i=0; i < nas; i++) { + for (ix=0; ix < nas; ix++) { const struct usb_host_interface *interface; const struct usb_endpoint_descriptor *endpoint; - interface = &dev->actconfig->interface[ifnum]->altsetting[i]; + interface = &intf->altsetting[ix]; + i = interface->desc.bAlternateSetting; if (interface->desc.bNumEndpoints != 1) { err("Interface %d. has %u. endpoints!", ifnum, (unsigned)(interface->desc.bNumEndpoints)); --- linux-2.6.6/drivers/usb/media/konicawc.c 2003-08-08 22:55:13.000000000 -0700 +++ 25/drivers/usb/media/konicawc.c 2004-05-10 01:19:05.806856280 -0700 @@ -381,9 +381,15 @@ static int konicawc_start_data(struct uv int i, errFlag; struct konicawc *cam = (struct konicawc *)uvd->user_data; int pktsz; - struct usb_host_interface *interface; + struct usb_interface *intf; + struct usb_host_interface *interface = NULL; - interface = &dev->actconfig->interface[uvd->iface]->altsetting[spd_to_iface[cam->speed]]; + intf = usb_ifnum_to_if(dev, uvd->iface); + if (intf) + interface = usb_altnum_to_altsetting(intf, + spd_to_iface[cam->speed]); + if (!interface) + return -ENXIO; pktsz = interface->endpoint[1].desc.wMaxPacketSize; DEBUG(1, "pktsz = %d", pktsz); if (!CAMERA_IS_OPERATIONAL(uvd)) { @@ -721,7 +727,7 @@ static int konicawc_probe(struct usb_int { struct usb_device *dev = interface_to_usbdev(intf); struct uvd *uvd = NULL; - int i, nas; + int ix, i, nas; int actInterface=-1, inactInterface=-1, maxPS=0; unsigned char video_ep = 0; @@ -741,11 +747,12 @@ static int konicawc_probe(struct usb_int return -ENODEV; } /* Validate all alternate settings */ - for (i=0; i < nas; i++) { + for (ix=0; ix < nas; ix++) { const struct usb_host_interface *interface; const struct usb_endpoint_descriptor *endpoint; - interface = &intf->altsetting[i]; + interface = &intf->altsetting[ix]; + i = interface->desc.bAlternateSetting; if (interface->desc.bNumEndpoints != 2) { err("Interface %d. has %u. endpoints!", interface->desc.bInterfaceNumber, --- linux-2.6.6/drivers/usb/media/ov511.c 2003-09-08 13:58:58.000000000 -0700 +++ 25/drivers/usb/media/ov511.c 2004-05-10 01:19:05.810855672 -0700 @@ -5603,8 +5603,16 @@ ov518_configure(struct usb_ov511 *ov) if (ov->bridge == BRG_OV518) { - struct usb_interface *ifp = ov->dev->config[0].interface[0]; - __u16 mxps = ifp->altsetting[7].endpoint[0].desc.wMaxPacketSize; + struct usb_interface *ifp; + struct usb_host_interface *alt; + __u16 mxps = 0; + + ifp = usb_ifnum_to_if(ov->dev, 0); + if (ifp) { + alt = usb_altnum_to_altsetting(ifp, 7); + if (alt) + mxps = alt->endpoint[0].desc.wMaxPacketSize; + } /* Some OV518s have packet numbering by default, some don't */ if (mxps == 897) @@ -5805,7 +5813,7 @@ ov51x_probe(struct usb_interface *intf, if (dev->descriptor.bNumConfigurations != 1) return -ENODEV; - idesc = &intf->altsetting[0].desc; + idesc = &intf->cur_altsetting->desc; if (idesc->bInterfaceClass != 0xFF) return -ENODEV; --- linux-2.6.6/drivers/usb/media/pwc-if.c 2004-01-09 00:04:32.000000000 -0800 +++ 25/drivers/usb/media/pwc-if.c 2004-05-10 01:19:05.812855368 -0700 @@ -789,7 +789,8 @@ static int pwc_isoc_init(struct pwc_devi struct urb *urb; int i, j, ret; - struct usb_host_interface *idesc; + struct usb_interface *intf; + struct usb_host_interface *idesc = NULL; if (pdev == NULL) return -EFAULT; @@ -801,7 +802,9 @@ static int pwc_isoc_init(struct pwc_devi /* Get the current alternate interface, adjust packet size */ if (!udev->actconfig) return -EFAULT; - idesc = &udev->actconfig->interface[0]->altsetting[pdev->valternate]; + intf = usb_ifnum_to_if(udev, 0); + if (intf) + idesc = usb_altnum_to_altsetting(intf, pdev->valternate); if (!idesc) return -EFAULT; --- linux-2.6.6/drivers/usb/media/se401.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/usb/media/se401.c 2004-05-10 01:19:05.813855216 -0700 @@ -1326,7 +1326,7 @@ static int se401_probe(struct usb_interf if (dev->descriptor.bNumConfigurations != 1) return -ENODEV; - interface = &intf->altsetting[0].desc; + interface = &intf->cur_altsetting->desc; /* Is it an se401? */ if (dev->descriptor.idVendor == 0x03e8 && --- linux-2.6.6/drivers/usb/media/ultracam.c 2003-06-14 12:17:59.000000000 -0700 +++ 25/drivers/usb/media/ultracam.c 2004-05-10 01:19:05.814855064 -0700 @@ -513,7 +513,7 @@ static int ultracam_probe(struct usb_int { struct usb_device *dev = interface_to_usbdev(intf); struct uvd *uvd = NULL; - int i, nas; + int ix, i, nas; int actInterface=-1, inactInterface=-1, maxPS=0; unsigned char video_ep = 0; @@ -540,11 +540,12 @@ static int ultracam_probe(struct usb_int return -ENODEV; } /* Validate all alternate settings */ - for (i=0; i < nas; i++) { + for (ix=0; ix < nas; ix++) { const struct usb_host_interface *interface; const struct usb_endpoint_descriptor *endpoint; - interface = &intf->altsetting[i]; + interface = &intf->altsetting[ix]; + i = interface->desc.bAlternateSetting; if (interface->desc.bNumEndpoints != 1) { err("Interface %d. has %u. endpoints!", interface->desc.bInterfaceNumber, --- linux-2.6.6/drivers/usb/media/vicam.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/media/vicam.c 2004-05-10 01:19:05.815854912 -0700 @@ -1303,7 +1303,7 @@ vicam_probe( struct usb_interface *intf, printk(KERN_INFO "ViCam based webcam connected\n"); - interface = &intf->altsetting[0]; + interface = intf->cur_altsetting; DBG(KERN_DEBUG "Interface %d. has %u. endpoints!\n", interface->desc.bInterfaceNumber, (unsigned) (interface->desc.bNumEndpoints)); --- linux-2.6.6/drivers/usb/media/w9968cf.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/media/w9968cf.c 2004-05-10 01:19:02.945291304 -0700 @@ -1578,7 +1578,7 @@ static int w9968cf_i2c_init(struct w9968 static struct i2c_adapter adap = { .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_W9968CF, - .class = I2C_ADAP_CLASS_CAM_DIGITAL, + .class = I2C_CLASS_CAM_DIGITAL, .owner = THIS_MODULE, .client_register = w9968cf_i2c_attach_inform, .client_unregister = w9968cf_i2c_detach_inform, --- linux-2.6.6/drivers/usb/misc/Kconfig 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/misc/Kconfig 2004-05-10 01:19:05.815854912 -0700 @@ -133,6 +133,18 @@ config USB_SPEEDTOUCH To compile this driver as a module, choose M here: the module will be called speedtch. +config USB_PHIDGETSERVO + tristate "USB PhidgetServo support" + depends on USB + help + Say Y here if you want to connect an 1 or 4 Motor PhidgetServo + servo controller version 2.0 or 3.0. + + Phidgets Inc. has a web page at . + + To compile this driver as a module, choose M here: the + module will be called phidgetservo. + config USB_TEST tristate "USB testing driver (DEVELOPMENT)" depends on USB && USB_DEVICEFS && EXPERIMENTAL --- linux-2.6.6/drivers/usb/misc/legousbtower.c 2004-01-09 00:04:32.000000000 -0800 +++ 25/drivers/usb/misc/legousbtower.c 2004-05-10 01:19:05.822853848 -0700 @@ -1,8 +1,8 @@ /* * LEGO USB Tower driver * - * Copyright (C) 2003 David Glance - * 2001 Juergen Stuber + * Copyright (C) 2003 David Glance + * 2001-2004 Juergen Stuber * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -33,14 +33,44 @@ * - changed to use lego0 rather than tower0 * - changed dbg() to use __func__ rather than deprecated __FUNCTION__ * 2003-01-12 - 0.53 david (david@csse.uwa.edu.au) - * - changed read and write to write everything or timeout (from a patch by Chris Riesen and - * Brett Thaeler driver) + * - changed read and write to write everything or + * timeout (from a patch by Chris Riesen and Brett Thaeler driver) * - added ioctl functionality to set timeouts - * 2003-07-18 - 0.54 davidgsf (david@csse.uwa.edu.au) + * 2003-07-18 - 0.54 davidgsf (david@csse.uwa.edu.au) * - initial import into LegoUSB project * - merge of existing LegoUSB.c driver - * 2003-07-18 - 0.56 davidgsf (david@csse.uwa.edu.au) + * 2003-07-18 - 0.56 davidgsf (david@csse.uwa.edu.au) * - port to 2.6 style driver + * 2004-02-29 - 0.6 Juergen Stuber + * - fix locking + * - unlink read URBs which are no longer needed + * - allow increased buffer size, eliminates need for timeout on write + * - have read URB running continuously + * - added poll + * - forbid seeking + * - added nonblocking I/O + * - changed back __func__ to __FUNCTION__ + * - read and log tower firmware version + * - reset tower on probe, avoids failure of first write + * 2004-03-09 - 0.7 Juergen Stuber + * - timeout read now only after inactivity, shorten default accordingly + * 2004-03-11 - 0.8 Juergen Stuber + * - log major, minor instead of possibly confusing device filename + * - whitespace cleanup + * 2004-03-12 - 0.9 Juergen Stuber + * - normalize whitespace in debug messages + * - take care about endianness in control message responses + * 2004-03-13 - 0.91 Juergen Stuber + * - make default intervals longer to accommodate current EHCI driver + * 2004-03-19 - 0.92 Juergen Stuber + * - replaced atomic_t by memory barriers + * 2004-04-21 - 0.93 Juergen Stuber + * - wait for completion of write urb in release (needed for remotecontrol) + * - corrected poll for write direction (missing negation) + * 2004-04-22 - 0.94 Juergen Stuber + * - make device locking interruptible + * 2004-04-30 - 0.95 Juergen Stuber + * - check for valid udev on resubmitting and unlinking urbs */ #include @@ -53,33 +83,113 @@ #include #include #include +#include #ifdef CONFIG_USB_DEBUG static int debug = 4; #else - static int debug = 1; + static int debug = 0; #endif /* Use our own dbg macro */ #undef dbg -#define dbg(lvl, format, arg...) do { if (debug >= lvl) printk(KERN_DEBUG __FILE__ " : " format " \n", ## arg); } while (0) +#define dbg(lvl, format, arg...) do { if (debug >= lvl) printk(KERN_DEBUG __FILE__ ": " format "\n", ## arg); } while (0) /* Version Information */ -#define DRIVER_VERSION "v0.56" -#define DRIVER_AUTHOR "David Glance, davidgsf@sourceforge.net" +#define DRIVER_VERSION "v0.95" +#define DRIVER_AUTHOR "Juergen Stuber " #define DRIVER_DESC "LEGO USB Tower Driver" -/* Module paramaters */ +/* Module parameters */ MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "Debug enabled or not"); +/* The defaults are chosen to work with the latest versions of leJOS and NQC. + */ + +/* Some legacy software likes to receive packets in one piece. + * In this case read_buffer_size should exceed the maximal packet length + * (417 for datalog uploads), and packet_timeout should be set. + */ +static size_t read_buffer_size = 480; +MODULE_PARM(read_buffer_size, "i"); +MODULE_PARM_DESC(read_buffer_size, "Read buffer size"); + +/* Some legacy software likes to send packets in one piece. + * In this case write_buffer_size should exceed the maximal packet length + * (417 for firmware and program downloads). + * A problem with long writes is that the following read may time out + * if the software is not prepared to wait long enough. + */ +static size_t write_buffer_size = 480; +MODULE_PARM(write_buffer_size, "i"); +MODULE_PARM_DESC(write_buffer_size, "Write buffer size"); + +/* Some legacy software expects reads to contain whole LASM packets. + * To achieve this, characters which arrive before a packet timeout + * occurs will be returned in a single read operation. + * A problem with long reads is that the software may time out + * if it is not prepared to wait long enough. + * The packet timeout should be greater than the time between the + * reception of subsequent characters, which should arrive about + * every 5ms for the standard 2400 baud. + * Set it to 0 to disable. + */ +static int packet_timeout = 50; +MODULE_PARM(packet_timeout, "i"); +MODULE_PARM_DESC(packet_timeout, "Packet timeout in ms"); + +/* Some legacy software expects blocking reads to time out. + * Timeout occurs after the specified time of read and write inactivity. + * Set it to 0 to disable. + */ +static int read_timeout = 200; +MODULE_PARM(read_timeout, "i"); +MODULE_PARM_DESC(read_timeout, "Read timeout in ms"); + +/* As of kernel version 2.6.4 ehci-hcd uses an + * "only one interrupt transfer per frame" shortcut + * to simplify the scheduling of periodic transfers. + * This conflicts with our standard 1ms intervals for in and out URBs. + * We use default intervals of 2ms for in and 8ms for out transfers, + * which is fast enough for 2400 baud and allows a small additional load. + * Increase the interval to allow more devices that do interrupt transfers, + * or set to 0 to use the standard interval from the endpoint descriptors. + */ +static int interrupt_in_interval = 2; +MODULE_PARM(interrupt_in_interval, "i"); +MODULE_PARM_DESC(interrupt_in_interval, "Interrupt in interval in ms"); + +static int interrupt_out_interval = 8; +MODULE_PARM(interrupt_out_interval, "i"); +MODULE_PARM_DESC(interrupt_out_interval, "Interrupt out interval in ms"); /* Define these values to match your device */ #define LEGO_USB_TOWER_VENDOR_ID 0x0694 #define LEGO_USB_TOWER_PRODUCT_ID 0x0001 +/* Vendor requests */ +#define LEGO_USB_TOWER_REQUEST_RESET 0x04 +#define LEGO_USB_TOWER_REQUEST_GET_VERSION 0xFD + +struct tower_reset_reply { + __u16 size; /* little-endian */ + __u8 err_code; + __u8 spare; +} __attribute__ ((packed)); + +struct tower_get_version_reply { + __u16 size; /* little-endian */ + __u8 err_code; + __u8 spare; + __u8 major; + __u8 minor; + __u16 build_no; /* little-endian */ +} __attribute__ ((packed)); + + /* table of devices that work with this driver */ static struct usb_device_id tower_table [] = { { USB_DEVICE(LEGO_USB_TOWER_VENDOR_ID, LEGO_USB_TOWER_PRODUCT_ID) }, @@ -90,22 +200,21 @@ MODULE_DEVICE_TABLE (usb, tower_table); #define LEGO_USB_TOWER_MINOR_BASE 160 -/* we can have up to this number of device plugged in at once */ -#define MAX_DEVICES 16 - -#define COMMAND_TIMEOUT (2*HZ) /* 2 second timeout for a command */ /* Structure to hold all of our device specific stuff */ struct lego_usb_tower { struct semaphore sem; /* locks this structure */ - struct usb_device* udev; /* save off the usb device pointer */ - struct usb_interface* interface; + struct usb_device* udev; /* save off the usb device pointer */ unsigned char minor; /* the starting minor number for this device */ int open_count; /* number of times this port has been opened */ char* read_buffer; - int read_buffer_length; + size_t read_buffer_length; /* this much came in */ + size_t read_packet_length; /* this much will be returned on read */ + spinlock_t read_buffer_lock; + int packet_timeout_jiffies; + unsigned long read_last_arrival; wait_queue_head_t read_wait; wait_queue_head_t write_wait; @@ -113,18 +222,18 @@ struct lego_usb_tower { char* interrupt_in_buffer; struct usb_endpoint_descriptor* interrupt_in_endpoint; struct urb* interrupt_in_urb; + int interrupt_in_interval; + int interrupt_in_running; + int interrupt_in_done; char* interrupt_out_buffer; struct usb_endpoint_descriptor* interrupt_out_endpoint; struct urb* interrupt_out_urb; + int interrupt_out_interval; + int interrupt_out_busy; }; -/* Note that no locking is needed: - * read_buffer is arbitrated by read_buffer_length == 0 - * interrupt_out_buffer is arbitrated by interrupt_out_urb->status == -EINPROGRESS - * interrupt_in_buffer belongs to urb alone and is overwritten on overflow - */ /* local function prototypes */ static ssize_t tower_read (struct file *file, char *buffer, size_t count, loff_t *ppos); @@ -132,8 +241,11 @@ static ssize_t tower_write (struct file static inline void tower_delete (struct lego_usb_tower *dev); static int tower_open (struct inode *inode, struct file *file); static int tower_release (struct inode *inode, struct file *file); -static int tower_release_internal (struct lego_usb_tower *dev); +static unsigned int tower_poll (struct file *file, poll_table *wait); +static loff_t tower_llseek (struct file *file, loff_t off, int whence); + static void tower_abort_transfers (struct lego_usb_tower *dev); +static void tower_check_for_read_packet (struct lego_usb_tower *dev); static void tower_interrupt_in_callback (struct urb *urb, struct pt_regs *regs); static void tower_interrupt_out_callback (struct urb *urb, struct pt_regs *regs); @@ -146,14 +258,16 @@ static DECLARE_MUTEX (disconnect_sem); /* file operations needed when we register this driver */ static struct file_operations tower_fops = { - .owner = THIS_MODULE, - .read = tower_read, + .owner = THIS_MODULE, + .read = tower_read, .write = tower_write, .open = tower_open, - .release = tower_release, + .release = tower_release, + .poll = tower_poll, + .llseek = tower_llseek, }; -/* +/* * usb class driver info in order to get a minor number from the usb core, * and to have the device registered with devfs and the driver core */ @@ -167,11 +281,11 @@ static struct usb_class_driver tower_cla /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver tower_driver = { - .owner = THIS_MODULE, - .name = "legousbtower", - .probe = tower_probe, - .disconnect = tower_disconnect, - .id_table = tower_table, + .owner = THIS_MODULE, + .name = "legousbtower", + .probe = tower_probe, + .disconnect = tower_disconnect, + .id_table = tower_table, }; @@ -183,8 +297,8 @@ static inline void lego_usb_tower_debug_ int i; if (debug < level) - return; - + return; + printk (KERN_DEBUG __FILE__": %s - length = %d, data = ", function, size); for (i = 0; i < size; ++i) { printk ("%.2x ", data[i]); @@ -198,7 +312,7 @@ static inline void lego_usb_tower_debug_ */ static inline void tower_delete (struct lego_usb_tower *dev) { - dbg(2, "%s enter", __func__); + dbg(2, "%s: enter", __FUNCTION__); tower_abort_transfers (dev); @@ -214,7 +328,7 @@ static inline void tower_delete (struct kfree (dev->interrupt_out_buffer); kfree (dev); - dbg(2, "%s : leave", __func__); + dbg(2, "%s: leave", __FUNCTION__); } @@ -228,7 +342,7 @@ static int tower_open (struct inode *ino int retval = 0; struct usb_interface *interface; - dbg(2,"%s : enter", __func__); + dbg(2, "%s: enter", __FUNCTION__); subminor = iminor(inode); @@ -240,37 +354,63 @@ static int tower_open (struct inode *ino err ("%s - error, can't find device for minor %d", __FUNCTION__, subminor); retval = -ENODEV; - goto exit_no_device; + goto unlock_disconnect_exit; } dev = usb_get_intfdata(interface); if (!dev) { retval = -ENODEV; - goto exit_no_device; + goto unlock_disconnect_exit; } /* lock this device */ - down (&dev->sem); - - - /* increment our usage count for the device */ - ++dev->open_count; - - /* save device in the file's private structure */ - file->private_data = dev; + if (down_interruptible (&dev->sem)) { + retval = -ERESTARTSYS; + goto unlock_disconnect_exit; + } + /* allow opening only once */ + if (dev->open_count) { + retval = -EBUSY; + goto unlock_exit; + } + dev->open_count = 1; /* initialize in direction */ dev->read_buffer_length = 0; + dev->read_packet_length = 0; + usb_fill_int_urb (dev->interrupt_in_urb, + dev->udev, + usb_rcvintpipe(dev->udev, dev->interrupt_in_endpoint->bEndpointAddress), + dev->interrupt_in_buffer, + dev->interrupt_in_endpoint->wMaxPacketSize, + tower_interrupt_in_callback, + dev, + dev->interrupt_in_interval); + + dev->interrupt_in_running = 1; + dev->interrupt_in_done = 0; + mb(); - up (&dev->sem); + retval = usb_submit_urb (dev->interrupt_in_urb, GFP_KERNEL); + if (retval) { + err("Couldn't submit interrupt_in_urb %d", retval); + dev->interrupt_in_running = 0; + dev->open_count = 0; + goto unlock_exit; + } -exit_no_device: + /* save device in the file's private structure */ + file->private_data = dev; + +unlock_exit: + up (&dev->sem); +unlock_disconnect_exit: up (&disconnect_sem); - dbg(2,"%s : leave, return value %d ", __func__, retval); + dbg(2, "%s: leave, return value %d ", __FUNCTION__, retval); return retval; } @@ -283,87 +423,137 @@ static int tower_release (struct inode * struct lego_usb_tower *dev; int retval = 0; - dbg(2," %s : enter", __func__); + dbg(2, "%s: enter", __FUNCTION__); dev = (struct lego_usb_tower *)file->private_data; if (dev == NULL) { - dbg(1," %s : object is NULL", __func__); + dbg(1, "%s: object is NULL", __FUNCTION__); retval = -ENODEV; goto exit; } + if (down_interruptible (&dev->sem)) { + retval = -ERESTARTSYS; + goto exit; + } - /* lock our device */ - down (&dev->sem); - - if (dev->open_count <= 0) { - dbg(1," %s : device not opened", __func__); + if (dev->open_count != 1) { + dbg(1, "%s: device not opened exactly once", __FUNCTION__); retval = -ENODEV; + goto unlock_exit; + } + if (dev->udev == NULL) { + /* the device was unplugged before the file was released */ + up (&dev->sem); /* unlock here as tower_delete frees dev */ + tower_delete (dev); goto exit; } - /* do the work */ - retval = tower_release_internal (dev); + /* wait until write transfer is finished */ + if (dev->interrupt_out_busy) { + wait_event_interruptible_timeout (dev->write_wait, !dev->interrupt_out_busy, 2 * HZ); + } + tower_abort_transfers (dev); + dev->open_count = 0; + +unlock_exit: + up (&dev->sem); exit: - up (&dev->sem); - dbg(2," %s : leave, return value %d", __func__, retval); + dbg(2, "%s: leave, return value %d", __FUNCTION__, retval); return retval; } /** - * tower_release_internal + * tower_abort_transfers + * aborts transfers and frees associated data structures */ -static int tower_release_internal (struct lego_usb_tower *dev) +static void tower_abort_transfers (struct lego_usb_tower *dev) { - int retval = 0; - - dbg(2," %s : enter", __func__); + dbg(2, "%s: enter", __FUNCTION__); - if (dev->udev == NULL) { - /* the device was unplugged before the file was released */ - tower_delete (dev); + if (dev == NULL) { + dbg(1, "%s: dev is null", __FUNCTION__); goto exit; } - /* decrement our usage count for the device */ - --dev->open_count; - if (dev->open_count <= 0) { - tower_abort_transfers (dev); - dev->open_count = 0; + /* shutdown transfer */ + if (dev->interrupt_in_running) { + dev->interrupt_in_running = 0; + mb(); + if (dev->interrupt_in_urb != NULL && dev->udev) { + usb_unlink_urb (dev->interrupt_in_urb); + } + } + if (dev->interrupt_out_busy) { + if (dev->interrupt_out_urb != NULL && dev->udev) { + usb_unlink_urb (dev->interrupt_out_urb); + } } exit: - dbg(2," %s : leave", __func__); - return retval; + dbg(2, "%s: leave", __FUNCTION__); } /** - * tower_abort_transfers - * aborts transfers and frees associated data structures + * tower_check_for_read_packet + * + * To get correct semantics for signals and non-blocking I/O + * with packetizing we pretend not to see any data in the read buffer + * until it has been there unchanged for at least + * dev->packet_timeout_jiffies, or until the buffer is full. */ -static void tower_abort_transfers (struct lego_usb_tower *dev) +static void tower_check_for_read_packet (struct lego_usb_tower *dev) { - dbg(2," %s : enter", __func__); - - if (dev == NULL) { - dbg(1," %s : dev is null", __func__); - goto exit; + spin_lock_irq (&dev->read_buffer_lock); + if (!packet_timeout + || time_after(jiffies, dev->read_last_arrival + dev->packet_timeout_jiffies) + || dev->read_buffer_length == read_buffer_size) { + dev->read_packet_length = dev->read_buffer_length; } + dev->interrupt_in_done = 0; + spin_unlock_irq (&dev->read_buffer_lock); +} - /* shutdown transfer */ - if (dev->interrupt_in_urb != NULL) { - usb_unlink_urb (dev->interrupt_in_urb); + +/** + * tower_poll + */ +static unsigned int tower_poll (struct file *file, poll_table *wait) +{ + struct lego_usb_tower *dev; + unsigned int mask = 0; + + dbg(2, "%s: enter", __FUNCTION__); + + dev = file->private_data; + + poll_wait(file, &dev->read_wait, wait); + poll_wait(file, &dev->write_wait, wait); + + tower_check_for_read_packet(dev); + if (dev->read_packet_length > 0) { + mask |= POLLIN | POLLRDNORM; } - if (dev->interrupt_out_urb != NULL) { - usb_unlink_urb (dev->interrupt_out_urb); + if (!dev->interrupt_out_busy) { + mask |= POLLOUT | POLLWRNORM; } -exit: - dbg(2," %s : leave", __func__); + dbg(2, "%s: leave, mask = %d", __FUNCTION__, mask); + + return mask; +} + + +/** + * tower_llseek + */ +static loff_t tower_llseek (struct file *file, loff_t off, int whence) +{ + return -ESPIPE; /* unseekable */ } @@ -373,96 +563,87 @@ exit: static ssize_t tower_read (struct file *file, char *buffer, size_t count, loff_t *ppos) { struct lego_usb_tower *dev; - size_t bytes_read = 0; size_t bytes_to_read; int i; int retval = 0; - int timeout = 0; + unsigned long timeout = 0; - dbg(2," %s : enter, count = %Zd", __func__, count); + dbg(2, "%s: enter, count = %Zd", __FUNCTION__, count); dev = (struct lego_usb_tower *)file->private_data; - + /* lock this object */ - down (&dev->sem); + if (down_interruptible (&dev->sem)) { + retval = -ERESTARTSYS; + goto exit; + } /* verify that the device wasn't unplugged */ if (dev->udev == NULL) { retval = -ENODEV; err("No device or device unplugged %d", retval); - goto exit; + goto unlock_exit; } /* verify that we actually have some data to read */ if (count == 0) { - dbg(1," %s : read request of 0 bytes", __func__); - goto exit; + dbg(1, "%s: read request of 0 bytes", __FUNCTION__); + goto unlock_exit; } + if (read_timeout) { + timeout = jiffies + read_timeout * HZ / 1000; + } + + /* wait for data */ + tower_check_for_read_packet (dev); + while (dev->read_packet_length == 0) { + if (file->f_flags & O_NONBLOCK) { + retval = -EAGAIN; + goto unlock_exit; + } + retval = wait_event_interruptible_timeout(dev->read_wait, dev->interrupt_in_done, dev->packet_timeout_jiffies); + if (retval < 0) { + goto unlock_exit; + } - timeout = COMMAND_TIMEOUT; + /* reset read timeout during read or write activity */ + if (read_timeout + && (dev->read_buffer_length || dev->interrupt_out_busy)) { + timeout = jiffies + read_timeout * HZ / 1000; + } + /* check for read timeout */ + if (read_timeout && time_after (jiffies, timeout)) { + retval = -ETIMEDOUT; + goto unlock_exit; + } + tower_check_for_read_packet (dev); + } - while (1) { - if (dev->read_buffer_length == 0) { + /* copy the data from read_buffer into userspace */ + bytes_to_read = min(count, dev->read_packet_length); - /* start reading */ - usb_fill_int_urb (dev->interrupt_in_urb,dev->udev, - usb_rcvintpipe(dev->udev, dev->interrupt_in_endpoint->bEndpointAddress), - dev->interrupt_in_buffer, - dev->interrupt_in_endpoint->wMaxPacketSize, - tower_interrupt_in_callback, - dev, - dev->interrupt_in_endpoint->bInterval); - - retval = usb_submit_urb (dev->interrupt_in_urb, GFP_KERNEL); - - if (retval < 0) { - err("Couldn't submit interrupt_in_urb"); - goto exit; - } - - if (timeout <= 0) { - retval = -ETIMEDOUT; - goto exit; - } - - if (signal_pending(current)) { - retval = -EINTR; - goto exit; - } - - up (&dev->sem); - timeout = interruptible_sleep_on_timeout (&dev->read_wait, timeout); - down (&dev->sem); + if (copy_to_user (buffer, dev->read_buffer, bytes_to_read)) { + retval = -EFAULT; + goto unlock_exit; + } - } else { - /* copy the data from read_buffer into userspace */ - bytes_to_read = count > dev->read_buffer_length ? dev->read_buffer_length : count; - if (copy_to_user (buffer, dev->read_buffer, bytes_to_read) != 0) { - retval = -EFAULT; - goto exit; - } - dev->read_buffer_length -= bytes_to_read; - for (i=0; iread_buffer_length; i++) { - dev->read_buffer[i] = dev->read_buffer[i+bytes_to_read]; - } - - buffer += bytes_to_read; - count -= bytes_to_read; - bytes_read += bytes_to_read; - if (count == 0) { - break; - } - } + spin_lock_irq (&dev->read_buffer_lock); + dev->read_buffer_length -= bytes_to_read; + dev->read_packet_length -= bytes_to_read; + for (i=0; iread_buffer_length; i++) { + dev->read_buffer[i] = dev->read_buffer[i+bytes_to_read]; } + spin_unlock_irq (&dev->read_buffer_lock); - retval = bytes_read; + retval = bytes_to_read; -exit: +unlock_exit: /* unlock the device */ up (&dev->sem); - dbg(2," %s : leave, return value %d", __func__, retval); +exit: + dbg(2, "%s: leave, return value %d", __FUNCTION__, retval); return retval; } @@ -473,107 +654,80 @@ exit: static ssize_t tower_write (struct file *file, const char *buffer, size_t count, loff_t *ppos) { struct lego_usb_tower *dev; - size_t bytes_written = 0; size_t bytes_to_write; - size_t buffer_size; int retval = 0; - int timeout = 0; - dbg(2," %s : enter, count = %Zd", __func__, count); + dbg(2, "%s: enter, count = %Zd", __FUNCTION__, count); dev = (struct lego_usb_tower *)file->private_data; /* lock this object */ - down (&dev->sem); + if (down_interruptible (&dev->sem)) { + retval = -ERESTARTSYS; + goto exit; + } /* verify that the device wasn't unplugged */ if (dev->udev == NULL) { retval = -ENODEV; err("No device or device unplugged %d", retval); - goto exit; + goto unlock_exit; } /* verify that we actually have some data to write */ if (count == 0) { - dbg(1," %s : write request of 0 bytes", __func__); - goto exit; + dbg(1, "%s: write request of 0 bytes", __FUNCTION__); + goto unlock_exit; } + /* wait until previous transfer is finished */ + while (dev->interrupt_out_busy) { + if (file->f_flags & O_NONBLOCK) { + retval = -EAGAIN; + goto unlock_exit; + } + retval = wait_event_interruptible (dev->write_wait, !dev->interrupt_out_busy); + if (retval) { + goto unlock_exit; + } + } - while (count > 0) { - if (dev->interrupt_out_urb->status == -EINPROGRESS) { - timeout = COMMAND_TIMEOUT; - - while (timeout > 0) { - if (signal_pending(current)) { - dbg(1," %s : interrupted", __func__); - retval = -EINTR; - goto exit; - } - up (&dev->sem); - timeout = interruptible_sleep_on_timeout (&dev->write_wait, timeout); - down (&dev->sem); - if (timeout > 0) { - break; - } - dbg(1," %s : interrupted timeout: %d", __func__, timeout); - } - - - dbg(1," %s : final timeout: %d", __func__, timeout); - - if (timeout == 0) { - dbg(1, "%s - command timed out.", __func__); - retval = -ETIMEDOUT; - goto exit; - } - - dbg(4," %s : in progress, count = %Zd", __func__, count); - } else { - dbg(4," %s : sending, count = %Zd", __func__, count); - - /* write the data into interrupt_out_buffer from userspace */ - buffer_size = dev->interrupt_out_endpoint->wMaxPacketSize; - bytes_to_write = count > buffer_size ? buffer_size : count; - dbg(4," %s : buffer_size = %Zd, count = %Zd, bytes_to_write = %Zd", __func__, buffer_size, count, bytes_to_write); - - if (copy_from_user (dev->interrupt_out_buffer, buffer, bytes_to_write) != 0) { - retval = -EFAULT; - goto exit; - } - - /* send off the urb */ - usb_fill_int_urb(dev->interrupt_out_urb, - dev->udev, - usb_sndintpipe(dev->udev, dev->interrupt_out_endpoint->bEndpointAddress), - dev->interrupt_out_buffer, - bytes_to_write, - tower_interrupt_out_callback, - dev, - dev->interrupt_in_endpoint->bInterval); - - dev->interrupt_out_urb->actual_length = bytes_to_write; - retval = usb_submit_urb (dev->interrupt_out_urb, GFP_KERNEL); - - if (retval < 0) { - err("Couldn't submit interrupt_out_urb %d", retval); - goto exit; - } + /* write the data into interrupt_out_buffer from userspace */ + bytes_to_write = min(count, write_buffer_size); + dbg(4, "%s: count = %Zd, bytes_to_write = %Zd", __FUNCTION__, count, bytes_to_write); + + if (copy_from_user (dev->interrupt_out_buffer, buffer, bytes_to_write)) { + retval = -EFAULT; + goto unlock_exit; + } + + /* send off the urb */ + usb_fill_int_urb(dev->interrupt_out_urb, + dev->udev, + usb_sndintpipe(dev->udev, dev->interrupt_out_endpoint->bEndpointAddress), + dev->interrupt_out_buffer, + bytes_to_write, + tower_interrupt_out_callback, + dev, + dev->interrupt_out_interval); - buffer += bytes_to_write; - count -= bytes_to_write; + dev->interrupt_out_busy = 1; + wmb(); - bytes_written += bytes_to_write; - } + retval = usb_submit_urb (dev->interrupt_out_urb, GFP_KERNEL); + if (retval) { + dev->interrupt_out_busy = 0; + err("Couldn't submit interrupt_out_urb %d", retval); + goto unlock_exit; } + retval = bytes_to_write; - retval = bytes_written; - -exit: +unlock_exit: /* unlock the device */ up (&dev->sem); - dbg(2," %s : leave, return value %d", __func__, retval); +exit: + dbg(2, "%s: leave, return value %d", __FUNCTION__, retval); return retval; } @@ -585,39 +739,53 @@ exit: static void tower_interrupt_in_callback (struct urb *urb, struct pt_regs *regs) { struct lego_usb_tower *dev = (struct lego_usb_tower *)urb->context; + int retval; - dbg(4," %s : enter, status %d", __func__, urb->status); + dbg(4, "%s: enter, status %d", __FUNCTION__, urb->status); - lego_usb_tower_debug_data(5,__func__, urb->actual_length, urb->transfer_buffer); + lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer); - if (urb->status != 0) { - if ((urb->status != -ENOENT) && (urb->status != -ECONNRESET)) { - dbg(1," %s : nonzero status received: %d", __func__, urb->status); + if (urb->status) { + if (urb->status == -ENOENT || + urb->status == -ECONNRESET || + urb->status == -ESHUTDOWN) { + goto exit; + } else { + dbg(1, "%s: nonzero status received: %d", __FUNCTION__, urb->status); + goto resubmit; /* maybe we can recover */ } - goto exit; } - down (&dev->sem); - if (urb->actual_length > 0) { - if (dev->read_buffer_length < (4 * dev->interrupt_in_endpoint->wMaxPacketSize) - (urb->actual_length)) { - - memcpy (dev->read_buffer+dev->read_buffer_length, dev->interrupt_in_buffer, urb->actual_length); - + spin_lock (&dev->read_buffer_lock); + if (dev->read_buffer_length + urb->actual_length < read_buffer_size) { + memcpy (dev->read_buffer + dev->read_buffer_length, + dev->interrupt_in_buffer, + urb->actual_length); dev->read_buffer_length += urb->actual_length; - dbg(1," %s reading %d ", __func__, urb->actual_length); - wake_up_interruptible (&dev->read_wait); - + dev->read_last_arrival = jiffies; + dbg(3, "%s: received %d bytes", __FUNCTION__, urb->actual_length); } else { - dbg(1," %s : read_buffer overflow", __func__); + printk(KERN_WARNING "%s: read_buffer overflow, %d bytes dropped", __FUNCTION__, urb->actual_length); } + spin_unlock (&dev->read_buffer_lock); } - up (&dev->sem); +resubmit: + /* resubmit if we're still running */ + if (dev->interrupt_in_running && dev->udev) { + retval = usb_submit_urb (dev->interrupt_in_urb, GFP_ATOMIC); + if (retval) { + err("%s: usb_submit_urb failed (%d)", __FUNCTION__, retval); + } + } exit: - lego_usb_tower_debug_data(5,__func__, urb->actual_length, urb->transfer_buffer); - dbg(4," %s : leave, status %d", __func__, urb->status); + dev->interrupt_in_done = 1; + wake_up_interruptible (&dev->read_wait); + + lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer); + dbg(4, "%s: leave, status %d", __FUNCTION__, urb->status); } @@ -628,22 +796,22 @@ static void tower_interrupt_out_callback { struct lego_usb_tower *dev = (struct lego_usb_tower *)urb->context; - dbg(4," %s : enter, status %d", __func__, urb->status); - lego_usb_tower_debug_data(5,__func__, urb->actual_length, urb->transfer_buffer); + dbg(4, "%s: enter, status %d", __FUNCTION__, urb->status); + lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer); - if (urb->status != 0) { - if ((urb->status != -ENOENT) && - (urb->status != -ECONNRESET)) { - dbg(1, " %s :nonzero status received: %d", __func__, urb->status); - } - goto exit; - } + /* sync/async unlink faults aren't errors */ + if (urb->status && !(urb->status == -ENOENT || + urb->status == -ECONNRESET || + urb->status == -ESHUTDOWN)) { + dbg(1, "%s - nonzero write bulk status received: %d", + __FUNCTION__, urb->status); + } + dev->interrupt_out_busy = 0; wake_up_interruptible(&dev->write_wait); -exit: - lego_usb_tower_debug_data(5,__func__, urb->actual_length, urb->transfer_buffer); - dbg(4," %s : leave, status %d", __func__, urb->status); + lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer); + dbg(4, "%s: leave, status %d", __FUNCTION__, urb->status); } @@ -659,15 +827,18 @@ static int tower_probe (struct usb_inter struct lego_usb_tower *dev = NULL; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor* endpoint; + struct tower_reset_reply reset_reply; + struct tower_get_version_reply get_version_reply; int i; int retval = -ENOMEM; + int result; - dbg(2," %s : enter", __func__); + dbg(2, "%s: enter", __FUNCTION__); if (udev == NULL) { info ("udev is NULL."); } - + /* See if the device offered us matches what we can accept */ if ((udev->descriptor.idVendor != LEGO_USB_TOWER_VENDOR_ID) || (udev->descriptor.idProduct != LEGO_USB_TOWER_PRODUCT_ID)) { @@ -691,6 +862,10 @@ static int tower_probe (struct usb_inter dev->read_buffer = NULL; dev->read_buffer_length = 0; + dev->read_packet_length = 0; + spin_lock_init (&dev->read_buffer_lock); + dev->packet_timeout_jiffies = packet_timeout * HZ / 1000; + dev->read_last_arrival = jiffies; init_waitqueue_head (&dev->read_wait); init_waitqueue_head (&dev->write_wait); @@ -698,13 +873,15 @@ static int tower_probe (struct usb_inter dev->interrupt_in_buffer = NULL; dev->interrupt_in_endpoint = NULL; dev->interrupt_in_urb = NULL; + dev->interrupt_in_running = 0; + dev->interrupt_in_done = 0; dev->interrupt_out_buffer = NULL; dev->interrupt_out_endpoint = NULL; dev->interrupt_out_urb = NULL; + dev->interrupt_out_busy = 0; - - iface_desc = &interface->altsetting[0]; + iface_desc = interface->cur_altsetting; /* set up the endpoint information */ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { @@ -714,7 +891,7 @@ static int tower_probe (struct usb_inter ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) { dev->interrupt_in_endpoint = endpoint; } - + if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) { dev->interrupt_out_endpoint = endpoint; @@ -729,7 +906,7 @@ static int tower_probe (struct usb_inter goto error; } - dev->read_buffer = kmalloc ((4*dev->interrupt_in_endpoint->wMaxPacketSize), GFP_KERNEL); + dev->read_buffer = kmalloc (read_buffer_size, GFP_KERNEL); if (!dev->read_buffer) { err("Couldn't allocate read_buffer"); goto error; @@ -744,7 +921,7 @@ static int tower_probe (struct usb_inter err("Couldn't allocate interrupt_in_urb"); goto error; } - dev->interrupt_out_buffer = kmalloc (dev->interrupt_out_endpoint->wMaxPacketSize, GFP_KERNEL); + dev->interrupt_out_buffer = kmalloc (write_buffer_size, GFP_KERNEL); if (!dev->interrupt_out_buffer) { err("Couldn't allocate interrupt_out_buffer"); goto error; @@ -753,7 +930,9 @@ static int tower_probe (struct usb_inter if (!dev->interrupt_out_urb) { err("Couldn't allocate interrupt_out_urb"); goto error; - } + } + dev->interrupt_in_interval = interrupt_in_interval ? interrupt_in_interval : dev->interrupt_in_endpoint->bInterval; + dev->interrupt_out_interval = interrupt_out_interval ? interrupt_out_interval : dev->interrupt_out_endpoint->bInterval; /* we can register the device now, as it is ready */ usb_set_intfdata (interface, dev); @@ -766,16 +945,50 @@ static int tower_probe (struct usb_inter usb_set_intfdata (interface, NULL); goto error; } - dev->minor = interface->minor; /* let the user know what node this device is now attached to */ - info ("LEGO USB Tower device now attached to /dev/usb/lego%d", (dev->minor - LEGO_USB_TOWER_MINOR_BASE)); + info ("LEGO USB Tower #%d now attached to major %d minor %d", (dev->minor - LEGO_USB_TOWER_MINOR_BASE), USB_MAJOR, dev->minor); + /* reset the tower */ + result = usb_control_msg (udev, + usb_rcvctrlpipe(udev, 0), + LEGO_USB_TOWER_REQUEST_RESET, + USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE, + 0, + 0, + &reset_reply, + sizeof(reset_reply), + HZ); + if (result < 0) { + err("LEGO USB Tower reset control request failed"); + retval = result; + goto error; + } + + /* get the firmware version and log it */ + result = usb_control_msg (udev, + usb_rcvctrlpipe(udev, 0), + LEGO_USB_TOWER_REQUEST_GET_VERSION, + USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE, + 0, + 0, + &get_version_reply, + sizeof(get_version_reply), + HZ); + if (result < 0) { + err("LEGO USB Tower get version control request failed"); + retval = result; + goto error; + } + info("LEGO USB Tower firmware version is %d.%d build %d", + get_version_reply.major, + get_version_reply.minor, + le16_to_cpu(get_version_reply.build_no)); exit: - dbg(2," %s : leave, return value 0x%.8lx (dev)", __func__, (long) dev); + dbg(2, "%s: leave, return value 0x%.8lx (dev)", __FUNCTION__, (long) dev); return retval; @@ -795,7 +1008,7 @@ static void tower_disconnect (struct usb struct lego_usb_tower *dev; int minor; - dbg(2," %s : enter", __func__); + dbg(2, "%s: enter", __FUNCTION__); down (&disconnect_sem); @@ -823,7 +1036,7 @@ static void tower_disconnect (struct usb info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE)); - dbg(2," %s : leave", __func__); + dbg(2, "%s: leave", __FUNCTION__); } @@ -836,7 +1049,7 @@ static int __init lego_usb_tower_init(vo int result; int retval = 0; - dbg(2," %s : enter", __func__); + dbg(2, "%s: enter", __FUNCTION__); /* register this driver with the USB subsystem */ result = usb_register(&tower_driver); @@ -849,7 +1062,7 @@ static int __init lego_usb_tower_init(vo info(DRIVER_DESC " " DRIVER_VERSION); exit: - dbg(2," %s : leave, return value %d", __func__, retval); + dbg(2, "%s: leave, return value %d", __FUNCTION__, retval); return retval; } @@ -860,12 +1073,12 @@ exit: */ static void __exit lego_usb_tower_exit(void) { - dbg(2," %s : enter", __func__); + dbg(2, "%s: enter", __FUNCTION__); /* deregister this driver with the USB subsystem */ usb_deregister (&tower_driver); - dbg(2," %s : leave", __func__); + dbg(2, "%s: leave", __FUNCTION__); } module_init (lego_usb_tower_init); --- linux-2.6.6/drivers/usb/misc/Makefile 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/misc/Makefile 2004-05-10 01:19:05.816854760 -0700 @@ -15,3 +15,4 @@ obj-$(CONFIG_USB_SPEEDTOUCH) += speedtch obj-$(CONFIG_USB_TEST) += usbtest.o obj-$(CONFIG_USB_TIGL) += tiglusb.o obj-$(CONFIG_USB_USS720) += uss720.o +obj-$(CONFIG_USB_PHIDGETSERVO) += phidgetservo.o --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/drivers/usb/misc/phidgetservo.c 2004-05-10 01:19:05.823853696 -0700 @@ -0,0 +1,327 @@ +/* + * USB PhidgetServo driver 1.0 + * + * Copyright (C) 2004 Sean Young + * + * 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 is a driver for the USB PhidgetServo version 2.0 and 3.0 servo + * controllers available at: http://www.phidgets.com/ + * + * Note that the driver takes input as: degrees.minutes + * -23 < degrees < 203 + * 0 < minutes < 59 + * + * CAUTION: Generally you should use 0 < degrees < 180 as anything else + * is probably beyond the range of your servo and may damage it. + */ + +#include +#ifdef CONFIG_USB_DEBUG +#define DEBUG 1 +#endif +#include +#include +#include +#include +#include +#include + +#define DRIVER_AUTHOR "Sean Young " +#define DRIVER_DESC "USB PhidgetServo Driver" + +#define VENDOR_ID_GLAB 0x06c2 +#define DEVICE_ID_4MOTOR_SERVO_30 0x0038 +#define DEVICE_ID_1MOTOR_SERVO_30 0x0039 + +#define VENDOR_ID_WISEGROUP 0x0925 +#define DEVICE_ID_1MOTOR_SERVO_20 0x8101 +#define DEVICE_ID_4MOTOR_SERVO_20 0x8104 + +static struct usb_device_id id_table[] = { + {USB_DEVICE(VENDOR_ID_GLAB, DEVICE_ID_4MOTOR_SERVO_30)}, + {USB_DEVICE(VENDOR_ID_GLAB, DEVICE_ID_1MOTOR_SERVO_30)}, + {USB_DEVICE(VENDOR_ID_WISEGROUP, DEVICE_ID_4MOTOR_SERVO_20)}, + {USB_DEVICE(VENDOR_ID_WISEGROUP, DEVICE_ID_1MOTOR_SERVO_20)}, + {} +}; + +MODULE_DEVICE_TABLE(usb, id_table); + +struct phidget_servo { + struct usb_device *udev; + int version; + int quad_servo; + int pulse[4]; + int degrees[4]; + int minutes[4]; +}; + +static void +change_position_v30(struct phidget_servo *servo, int servo_no, int degrees, + int minutes) +{ + int retval; + unsigned char *buffer; + + buffer = kmalloc(6, GFP_KERNEL); + if (!buffer) { + dev_err(&servo->udev->dev, "%s - out of memory\n", + __FUNCTION__); + return; + } + + /* + * pulse = 0 - 4095 + * angle = 0 - 180 degrees + * + * pulse = angle * 10.6 + 243.8 + */ + servo->pulse[servo_no] = ((degrees*60 + minutes)*106 + 2438*60)/600; + servo->degrees[servo_no]= degrees; + servo->minutes[servo_no]= minutes; + + /* + * The PhidgetServo v3.0 is controlled by sending 6 bytes, + * 4 * 12 bits for each servo. + * + * low = lower 8 bits pulse + * high = higher 4 bits pulse + * + * offset bits + * +---+-----------------+ + * | 0 | low 0 | + * +---+--------+--------+ + * | 1 | high 1 | high 0 | + * +---+--------+--------+ + * | 2 | low 1 | + * +---+-----------------+ + * | 3 | low 2 | + * +---+--------+--------+ + * | 4 | high 3 | high 2 | + * +---+--------+--------+ + * | 5 | low 3 | + * +---+-----------------+ + */ + + buffer[0] = servo->pulse[0] & 0xff; + buffer[1] = (servo->pulse[0] >> 8 & 0x0f) + | (servo->pulse[1] >> 4 & 0xf0); + buffer[2] = servo->pulse[1] & 0xff; + buffer[3] = servo->pulse[2] & 0xff; + buffer[4] = (servo->pulse[2] >> 8 & 0x0f) + | (servo->pulse[3] >> 4 & 0xf0); + buffer[5] = servo->pulse[3] & 0xff; + + dev_dbg(&servo->udev->dev, + "data: %02x %02x %02x %02x %02x %02x\n", + buffer[0], buffer[1], buffer[2], + buffer[3], buffer[4], buffer[5]); + + retval = usb_control_msg(servo->udev, + usb_sndctrlpipe(servo->udev, 0), + 0x09, 0x21, 0x0200, 0x0000, buffer, 6, 2 * HZ); + if (retval != 6) + dev_err(&servo->udev->dev, "retval = %d\n", retval); + kfree(buffer); +} + +static void +change_position_v20(struct phidget_servo *servo, int servo_no, int degrees, + int minutes) +{ + int retval; + unsigned char *buffer; + + buffer = kmalloc(2, GFP_KERNEL); + if (!buffer) { + dev_err(&servo->udev->dev, "%s - out of memory\n", + __FUNCTION__); + return; + } + + /* + * angle = 0 - 180 degrees + * pulse = angle + 23 + */ + servo->pulse[servo_no]= degrees + 23; + servo->degrees[servo_no]= degrees; + servo->minutes[servo_no]= 0; + + /* + * The PhidgetServo v2.0 is controlled by sending two bytes. The + * first byte is the servo number xor'ed with 2: + * + * servo 0 = 2 + * servo 1 = 3 + * servo 2 = 0 + * servo 3 = 1 + * + * The second byte is the position. + */ + + buffer[0] = servo_no ^ 2; + buffer[1] = servo->pulse[servo_no]; + + dev_dbg(&servo->udev->dev, "data: %02x %02x\n", buffer[0], buffer[1]); + + retval = usb_control_msg(servo->udev, + usb_sndctrlpipe(servo->udev, 0), + 0x09, 0x21, 0x0200, 0x0000, buffer, 2, 2 * HZ); + if (retval != 2) + dev_err(&servo->udev->dev, "retval = %d\n", retval); + kfree(buffer); +} + +#define show_set(value) \ +static ssize_t set_servo##value (struct device *dev, \ + const char *buf, size_t count) \ +{ \ + int degrees, minutes; \ + struct usb_interface *intf = to_usb_interface (dev); \ + struct phidget_servo *servo = usb_get_intfdata (intf); \ + \ + minutes = 0; \ + /* must at least convert degrees */ \ + if (sscanf (buf, "%d.%d", °rees, &minutes) < 1) { \ + return -EINVAL; \ + } \ + \ + if (degrees < -23 || degrees > (180 + 23) || \ + minutes < 0 || minutes > 59) { \ + return -EINVAL; \ + } \ + \ + if (servo->version >= 3) \ + change_position_v30 (servo, value, degrees, minutes); \ + else \ + change_position_v20 (servo, value, degrees, minutes); \ + \ + return count; \ +} \ + \ +static ssize_t show_servo##value (struct device *dev, char *buf) \ +{ \ + struct usb_interface *intf = to_usb_interface (dev); \ + struct phidget_servo *servo = usb_get_intfdata (intf); \ + \ + return sprintf (buf, "%d.%02d\n", servo->degrees[value], \ + servo->minutes[value]); \ +} \ +static DEVICE_ATTR(servo##value, S_IWUGO | S_IRUGO, \ + show_servo##value, set_servo##value); + +show_set(0); +show_set(1); +show_set(2); +show_set(3); + +static int +servo_probe(struct usb_interface *interface, const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(interface); + struct phidget_servo *dev = NULL; + + dev = kmalloc(sizeof (struct phidget_servo), GFP_KERNEL); + if (dev == NULL) { + dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__); + return -ENOMEM; + } + memset(dev, 0x00, sizeof (*dev)); + + dev->udev = usb_get_dev(udev); + switch (udev->descriptor.idVendor) { + case VENDOR_ID_WISEGROUP: + dev->version = 2; + break; + case VENDOR_ID_GLAB: + dev->version = 3; + break; + } + switch (udev->descriptor.idProduct) { + case DEVICE_ID_4MOTOR_SERVO_20: + case DEVICE_ID_4MOTOR_SERVO_30: + dev->quad_servo = 1; + break; + case DEVICE_ID_1MOTOR_SERVO_20: + case DEVICE_ID_1MOTOR_SERVO_30: + dev->quad_servo = 0; + break; + } + + usb_set_intfdata(interface, dev); + + device_create_file(&interface->dev, &dev_attr_servo0); + if (dev->quad_servo) { + device_create_file(&interface->dev, &dev_attr_servo1); + device_create_file(&interface->dev, &dev_attr_servo2); + device_create_file(&interface->dev, &dev_attr_servo3); + } + + dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 attached\n", + dev->quad_servo ? 4 : 1, dev->version); + if (dev->version == 2) + dev_info(&interface->dev, + "WARNING: v2.0 not tested! Please report if it works.\n"); + + return 0; +} + +static void +servo_disconnect(struct usb_interface *interface) +{ + struct phidget_servo *dev; + + dev = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); + + device_remove_file(&interface->dev, &dev_attr_servo0); + if (dev->quad_servo) { + device_remove_file(&interface->dev, &dev_attr_servo1); + device_remove_file(&interface->dev, &dev_attr_servo2); + device_remove_file(&interface->dev, &dev_attr_servo3); + } + + usb_put_dev(dev->udev); + + kfree(dev); + + dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 detached\n", + dev->quad_servo ? 4 : 1, dev->version); +} + +static struct usb_driver servo_driver = { + .owner = THIS_MODULE, + .name = "phidgetservo", + .probe = servo_probe, + .disconnect = servo_disconnect, + .id_table = id_table +}; + +static int __init +phidget_servo_init(void) +{ + int retval = 0; + + retval = usb_register(&servo_driver); + if (retval) + err("usb_register failed. Error number %d", retval); + + return retval; +} + +static void __exit +phidget_servo_exit(void) +{ + usb_deregister(&servo_driver); +} + +module_init(phidget_servo_init); +module_exit(phidget_servo_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); --- linux-2.6.6/drivers/usb/misc/usbtest.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/misc/usbtest.c 2004-05-10 01:19:05.825853392 -0700 @@ -802,6 +802,7 @@ error: switch (status) { case -EINPROGRESS: case -EBUSY: + case -EIDRM: continue; default: dbg ("urb unlink --> %d", status); @@ -1038,8 +1039,6 @@ static void unlink1_callback (struct urb if (!status) status = usb_submit_urb (urb, SLAB_ATOMIC); if (status) { - if (status == -ECONNRESET || status == -ENOENT) - status = 0; urb->status = status; complete ((struct completion *) urb->context); } @@ -1077,8 +1076,9 @@ static int unlink1 (struct usbtest_dev * wait_ms (jiffies % (2 * INTERRUPT_RATE)); retry: retval = usb_unlink_urb (urb); - if (retval == -EBUSY) { + if (retval == -EBUSY || retval == -EIDRM) { /* we can't unlink urbs while they're completing. + * or if they've completed, and we haven't resubmitted. * "normal" drivers would prevent resubmission, but * since we're testing unlink paths, we can't. */ --- linux-2.6.6/drivers/usb/misc/uss720.c 2004-03-10 20:41:30.000000000 -0800 +++ 25/drivers/usb/misc/uss720.c 2004-05-10 01:19:05.826853240 -0700 @@ -553,7 +553,7 @@ static int uss720_probe(struct usb_inter i = usb_set_interface(usbdev, intf->altsetting->desc.bInterfaceNumber, 2); printk(KERN_DEBUG "uss720: set inteface result %d\n", i); - interface = &intf->altsetting[2]; + interface = intf->cur_altsetting; /* * Allocate parport interface --- linux-2.6.6/drivers/usb/net/usbnet.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/net/usbnet.c 2004-05-10 01:19:05.828852936 -0700 @@ -928,8 +928,8 @@ static struct usb_driver usbnet_driver; */ static int generic_cdc_bind (struct usbnet *dev, struct usb_interface *intf) { - u8 *buf = intf->altsetting->extra; - int len = intf->altsetting->extralen; + u8 *buf = intf->cur_altsetting->extra; + int len = intf->cur_altsetting->extralen; struct usb_interface_descriptor *d; struct cdc_state *info = (void *) &dev->data; int status; @@ -955,7 +955,7 @@ static int generic_cdc_bind (struct usbn /* this assumes that if there's a non-RNDIS vendor variant * of cdc-acm, it'll fail RNDIS requests cleanly. */ - rndis = (intf->altsetting->desc.bInterfaceProtocol == 0xff); + rndis = (intf->cur_altsetting->desc.bInterfaceProtocol == 0xff); memset (info, 0, sizeof *info); info->control = intf; @@ -1025,7 +1025,7 @@ static int generic_cdc_bind (struct usbn } /* a data interface altsetting does the real i/o */ - d = &info->data->altsetting->desc; + d = &info->data->cur_altsetting->desc; if (d->bInterfaceClass != USB_CLASS_CDC_DATA) { dev_dbg (&intf->dev, "slave class %u\n", d->bInterfaceClass); @@ -3205,6 +3205,10 @@ static const struct usb_device_id produc USB_DEVICE (0x07b8, 0x420a), .driver_info = (unsigned long) &hawking_uf200_info, }, { + // Billionton Systems, USB2AR + USB_DEVICE (0x08dd, 0x90ff), + .driver_info = (unsigned long) &ax8817x_info, +}, { // ATEN UC210T USB_DEVICE (0x0557, 0x2009), .driver_info = (unsigned long) &ax8817x_info, --- linux-2.6.6/drivers/usb/serial/io_ti.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/serial/io_ti.c 2004-05-10 01:19:05.830852632 -0700 @@ -995,7 +995,7 @@ static int TIDownloadFirmware (struct ed if (status) return status; - interface = &serial->serial->dev->config->interface[0]->altsetting->desc; + interface = &serial->serial->interface->cur_altsetting->desc; if (!interface) { dev_err (&serial->serial->dev->dev, "%s - no interface set, error!", __FUNCTION__); return -ENODEV; --- linux-2.6.6/drivers/usb/serial/keyspan.c 2003-10-08 15:07:09.000000000 -0700 +++ 25/drivers/usb/serial/keyspan.c 2004-05-10 01:19:05.832852328 -0700 @@ -133,9 +133,6 @@ /* Per device and per port private data */ struct keyspan_serial_private { - /* number of active ports */ - atomic_t active_count; - const struct keyspan_device_details *device_details; struct urb *instat_urb; --- linux-2.6.6/drivers/usb/serial/kobil_sct.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/serial/kobil_sct.c 2004-05-10 01:19:05.833852176 -0700 @@ -183,7 +183,7 @@ static int kobil_startup (struct usb_ser pdev = serial->dev; actconfig = pdev->actconfig; interface = actconfig->interface[0]; - altsetting = interface->altsetting; + altsetting = interface->cur_altsetting; endpoint = altsetting->endpoint; for (i = 0; i < altsetting->desc.bNumEndpoints; i++) { --- linux-2.6.6/drivers/usb/serial/pl2303.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/serial/pl2303.c 2004-05-10 01:19:05.833852176 -0700 @@ -80,6 +80,7 @@ static struct usb_device_id id_table [] { USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) }, { USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) }, { USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID) }, + { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_ID) }, { } /* Terminating entry */ }; --- linux-2.6.6/drivers/usb/serial/pl2303.h 2004-02-03 20:42:37.000000000 -0800 +++ 25/drivers/usb/serial/pl2303.h 2004-05-10 01:19:05.834852024 -0700 @@ -41,3 +41,6 @@ #define SITECOM_VENDOR_ID 0x6189 #define SITECOM_PRODUCT_ID 0x2068 + +#define ALCATEL_VENDOR_ID 0x11f7 +#define ALCATEL_PRODUCT_ID 0x02df --- linux-2.6.6/drivers/usb/serial/safe_serial.c 2004-03-10 20:41:30.000000000 -0800 +++ 25/drivers/usb/serial/safe_serial.c 2004-05-10 01:19:05.834852024 -0700 @@ -395,7 +395,7 @@ static int safe_write_room (struct usb_s static int safe_startup (struct usb_serial *serial) { - switch (serial->interface->altsetting->desc.bInterfaceProtocol) { + switch (serial->interface->cur_altsetting->desc.bInterfaceProtocol) { case LINEO_SAFESERIAL_CRC: break; case LINEO_SAFESERIAL_CRC_PADDED: --- linux-2.6.6/drivers/usb/serial/usb-serial.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/usb/serial/usb-serial.c 2004-05-10 01:19:05.835851872 -0700 @@ -1037,7 +1037,7 @@ int usb_serial_probe(struct usb_interfac (dev->descriptor.idProduct == ATEN_PRODUCT_ID))) { if (interface != dev->actconfig->interface[0]) { /* check out the endpoints of the other interface*/ - iface_desc = &dev->actconfig->interface[0]->altsetting[0]; + iface_desc = dev->actconfig->interface[0]->cur_altsetting; for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; if ((endpoint->bEndpointAddress & 0x80) && --- linux-2.6.6/drivers/usb/serial/visor.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/serial/visor.c 2004-05-10 01:19:05.836851720 -0700 @@ -222,6 +222,8 @@ static struct usb_device_id id_table [] .driver_info = (kernel_ulong_t)&palm_os_4_probe }, { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_Z_ID), .driver_info = (kernel_ulong_t)&palm_os_4_probe }, + { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE31_ID), + .driver_info = (kernel_ulong_t)&palm_os_4_probe }, { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID), .driver_info = (kernel_ulong_t)&palm_os_4_probe }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID), @@ -273,6 +275,7 @@ static struct usb_device_id id_table_com { USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_T_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_Z_ID) }, + { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE31_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_3_5_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) }, --- linux-2.6.6/drivers/usb/serial/visor.h 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/usb/serial/visor.h 2004-05-10 01:19:05.837851568 -0700 @@ -31,6 +31,7 @@ #define PALM_M130_ID 0x0050 #define PALM_TUNGSTEN_T_ID 0x0060 #define PALM_TUNGSTEN_Z_ID 0x0031 +#define PALM_ZIRE31_ID 0x0061 #define PALM_ZIRE_ID 0x0070 #define PALM_M100_ID 0x0080 --- linux-2.6.6/drivers/usb/storage/scsiglue.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/storage/scsiglue.c 2004-05-10 01:19:05.837851568 -0700 @@ -159,14 +159,18 @@ static int command_abort( Scsi_Cmnd *srb return FAILED; } - /* Set state to ABORTING, set the ABORTING bit, and release the lock */ + /* Set state to ABORTING and set the ABORTING bit, but only if + * a device reset isn't already in progress (to avoid interfering + * with the reset). To prevent races with auto-reset, we must + * stop any ongoing USB transfers while still holding the host + * lock. */ us->sm_state = US_STATE_ABORTING; - set_bit(US_FLIDX_ABORTING, &us->flags); + if (!test_bit(US_FLIDX_RESETTING, &us->flags)) { + set_bit(US_FLIDX_ABORTING, &us->flags); + usb_stor_stop_transport(us); + } scsi_unlock(host); - /* Stop an ongoing USB transfer */ - usb_stor_stop_transport(us); - /* Wait for the aborted command to finish */ wait_for_completion(&us->notify); @@ -254,18 +258,17 @@ static int bus_reset( Scsi_Cmnd *srb ) } /* Report a driver-initiated device reset to the SCSI layer. - * Calling this for a SCSI-initiated reset is unnecessary but harmless. */ + * Calling this for a SCSI-initiated reset is unnecessary but harmless. + * The caller must own the SCSI host lock. */ void usb_stor_report_device_reset(struct us_data *us) { int i; - scsi_lock(us->host); scsi_report_device_reset(us->host, 0, 0); if (us->flags & US_FL_SCM_MULT_TARG) { for (i = 1; i < us->host->max_id; ++i) scsi_report_device_reset(us->host, 0, i); } - scsi_unlock(us->host); } /*********************************************************************** --- linux-2.6.6/drivers/usb/storage/transport.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/storage/transport.c 2004-05-10 01:19:05.839851264 -0700 @@ -137,7 +137,7 @@ static int usb_stor_msg_common(struct us int status; /* don't submit URBs during abort/disconnect processing */ - if (us->flags & DONT_SUBMIT) + if (us->flags & ABORTING_OR_DISCONNECTING) return -EIO; /* set up data structures for the wakeup system */ @@ -172,7 +172,7 @@ static int usb_stor_msg_common(struct us set_bit(US_FLIDX_URB_ACTIVE, &us->flags); /* did an abort/disconnect occur during the submission? */ - if (us->flags & DONT_SUBMIT) { + if (us->flags & ABORTING_OR_DISCONNECTING) { /* cancel the URB, if it hasn't been cancelled already */ if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->flags)) { @@ -440,7 +440,7 @@ int usb_stor_bulk_transfer_sglist(struct int result; /* don't submit s-g requests during abort/disconnect processing */ - if (us->flags & DONT_SUBMIT) + if (us->flags & ABORTING_OR_DISCONNECTING) return USB_STOR_XFER_ERROR; /* initialize the scatter-gather request block */ @@ -458,7 +458,7 @@ int usb_stor_bulk_transfer_sglist(struct set_bit(US_FLIDX_SG_ACTIVE, &us->flags); /* did an abort/disconnect occur during the submission? */ - if (us->flags & DONT_SUBMIT) { + if (us->flags & ABORTING_OR_DISCONNECTING) { /* cancel the request, if it hasn't been cancelled already */ if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->flags)) { @@ -712,14 +712,10 @@ void usb_stor_invoke_transport(Scsi_Cmnd /* abort processing: the bulk-only transport requires a reset * following an abort */ - Handle_Abort: + Handle_Abort: srb->result = DID_ABORT << 16; - if (us->protocol == US_PR_BULK) { - - /* permit the reset transfer to take place */ - clear_bit(US_FLIDX_ABORTING, &us->flags); + if (us->protocol == US_PR_BULK) us->transport_reset(us); - } } /* Stop the current URB transfer */ @@ -912,6 +908,17 @@ int usb_stor_Bulk_max_lun(struct us_data USB_RECIP_INTERFACE, 0, us->ifnum, us->iobuf, 1, HZ); + /* + * Some devices (i.e. Iomega Zip100) need this -- apparently + * the bulk pipes get STALLed when the GetMaxLUN request is + * processed. This is, in theory, harmless to all other devices + * (regardless of if they stall or not). + */ + if (result < 0) { + usb_stor_clear_halt(us, us->recv_bulk_pipe); + usb_stor_clear_halt(us, us->send_bulk_pipe); + } + US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", result, us->iobuf[0]); @@ -1079,20 +1086,28 @@ static int usb_stor_reset_common(struct { int result; int result2; + int rc = FAILED; - /* Let the SCSI layer know we are doing a reset */ + /* Let the SCSI layer know we are doing a reset, set the + * RESETTING bit, and clear the ABORTING bit so that the reset + * may proceed. + */ + scsi_lock(us->host); usb_stor_report_device_reset(us); + set_bit(US_FLIDX_RESETTING, &us->flags); + clear_bit(US_FLIDX_ABORTING, &us->flags); + scsi_unlock(us->host); /* A 20-second timeout may seem rather long, but a LaCie - * StudioDrive USB2 device takes 16+ seconds to get going - * following a powerup or USB attach event. */ - + * StudioDrive USB2 device takes 16+ seconds to get going + * following a powerup or USB attach event. + */ result = usb_stor_control_msg(us, us->send_ctrl_pipe, request, requesttype, value, index, data, size, 20*HZ); if (result < 0) { US_DEBUGP("Soft reset failed: %d\n", result); - return FAILED; + goto Done; } /* long wait for reset, so unlock to allow disconnects */ @@ -1102,12 +1117,9 @@ static int usb_stor_reset_common(struct down(&us->dev_semaphore); if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { US_DEBUGP("Reset interrupted by disconnect\n"); - return FAILED; + goto Done; } - /* permit the clear-halt transfers to take place */ - clear_bit(US_FLIDX_ABORTING, &us->flags); - US_DEBUGP("Soft reset: clearing bulk-in endpoint halt\n"); result = usb_stor_clear_halt(us, us->recv_bulk_pipe); @@ -1117,10 +1129,14 @@ static int usb_stor_reset_common(struct /* return a result code based on the result of the control message */ if (result < 0 || result2 < 0) { US_DEBUGP("Soft reset failed\n"); - return FAILED; + goto Done; } US_DEBUGP("Soft reset done\n"); - return SUCCESS; + rc = SUCCESS; + + Done: + clear_bit(US_FLIDX_RESETTING, &us->flags); + return rc; } /* This issues a CB[I] Reset to the device in question --- linux-2.6.6/drivers/usb/storage/unusual_devs.h 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/storage/unusual_devs.h 2004-05-10 01:19:05.840851112 -0700 @@ -90,6 +90,12 @@ UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ), #endif +/* Patch submitted by Alessandro Fracchetti */ +UNUSUAL_DEV( 0x0482, 0x0105, 0x0100, 0x0100, + "Kyocera", + "Finecam L3", + US_SC_SCSI, US_PR_BULK, NULL, US_FL_FIX_INQUIRY), + /* Patch submitted by Philipp Friedrich */ UNUSUAL_DEV( 0x0482, 0x0100, 0x0100, 0x0100, "Kyocera", @@ -297,6 +303,13 @@ UNUSUAL_DEV( 0x054c, 0x002e, 0x0106, 0x US_SC_SCSI, US_PR_DEVICE, NULL, US_FL_SINGLE_LUN | US_FL_MODE_XLATE), +/* Submitted by Rajesh Kumble Nayak */ +UNUSUAL_DEV( 0x054c, 0x002e, 0x0500, 0x0500, + "Sony", + "Handycam HC-85", + US_SC_UFI, US_PR_DEVICE, NULL, + US_FL_SINGLE_LUN | US_FL_MODE_XLATE), + UNUSUAL_DEV( 0x054c, 0x0032, 0x0000, 0x9999, "Sony", "Memorystick MSC-U01N", @@ -322,6 +335,13 @@ UNUSUAL_DEV( 0x054c, 0x006d, 0x0000, 0x "PEG Mass Storage", US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), + +/* Submitted by Mike Alborn */ +UNUSUAL_DEV( 0x054c, 0x016a, 0x0000, 0x9999, + "Sony", + "PEG Mass Storage", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_INQUIRY ), UNUSUAL_DEV( 0x057b, 0x0000, 0x0000, 0x0299, "Y-E Data", @@ -438,22 +458,6 @@ UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x US_FL_SINGLE_LUN ), #endif -/* Following three Minolta cameras reported by Martin Pool - * . Originally discovered by Kedar Petankar, - * Matthew Geier, Mikael Lofj"ard, Marcel de Boer. - */ -UNUSUAL_DEV( 0x0686, 0x4006, 0x0001, 0x0001, - "Minolta", - "DiMAGE 7", - US_SC_SCSI, US_PR_DEVICE, NULL, - 0 ), - -UNUSUAL_DEV( 0x0686, 0x400f, 0x0001, 0x0001, - "Minolta", - "DiMAGE 7Hi", - US_SC_SCSI, US_PR_DEVICE, NULL, - 0 ), - /* Submitted by Benny Sjostrand */ UNUSUAL_DEV( 0x0686, 0x4011, 0x0001, 0x0001, "Minolta", @@ -629,7 +633,7 @@ UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9 "Casio", "QV DigitalCamera", US_SC_DEVICE, US_PR_CB, NULL, - US_FL_FIX_INQUIRY ), + US_FL_NEED_OVERRIDE | US_FL_FIX_INQUIRY ), /* Later Casio cameras apparently tell the truth */ UNUSUAL_DEV( 0x07cf, 0x1001, 0x9010, 0x9999, @@ -688,7 +692,7 @@ UNUSUAL_DEV( 0x097a, 0x0001, 0x0000, 0x UNUSUAL_DEV( 0x0a16, 0x8888, 0x0100, 0x0100, "IBM", "IBM USB Memory Key", - US_SC_SCSI, US_PR_BULK, NULL, + US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), /* This Pentax still camera is not conformant --- linux-2.6.6/drivers/usb/storage/usb.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/usb/storage/usb.c 2004-05-10 01:19:05.841850960 -0700 @@ -84,8 +84,6 @@ #include -#include -#include #include #include @@ -490,7 +488,7 @@ static void get_device_info(struct us_da if (unusual_dev->useTransport != US_PR_DEVICE && us->protocol == idesc->bInterfaceProtocol) msg += 2; - if (msg >= 0) + if (msg >= 0 && !(unusual_dev->flags & US_FL_NEED_OVERRIDE)) printk(KERN_NOTICE USB_STORAGE "This device " "(%04x,%04x,%04x S %02x P %02x)" " has %s in unusual_devs.h\n" --- linux-2.6.6/drivers/usb/storage/usb.h 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/usb/storage/usb.h 2004-05-10 01:19:05.842850808 -0700 @@ -69,6 +69,7 @@ struct us_unusual_dev { /* Flag definitions: these entries are static */ #define US_FL_SINGLE_LUN 0x00000001 /* allow access to only LUN 0 */ #define US_FL_MODE_XLATE 0 /* [no longer used] */ +#define US_FL_NEED_OVERRIDE 0x00000004 /* unusual_devs entry is necessary */ #define US_FL_IGNORE_SER 0 /* [no longer used] */ #define US_FL_SCM_MULT_TARG 0x00000020 /* supports multiple targets */ #define US_FL_FIX_INQUIRY 0x00000040 /* INQUIRY response needs faking */ @@ -79,8 +80,9 @@ struct us_unusual_dev { #define US_FLIDX_SG_ACTIVE 19 /* 0x00080000 current_sg is in use */ #define US_FLIDX_ABORTING 20 /* 0x00100000 abort is in progress */ #define US_FLIDX_DISCONNECTING 21 /* 0x00200000 disconnect in progress */ -#define DONT_SUBMIT ((1UL << US_FLIDX_ABORTING) | \ - (1UL << US_FLIDX_DISCONNECTING)) +#define ABORTING_OR_DISCONNECTING ((1UL << US_FLIDX_ABORTING) | \ + (1UL << US_FLIDX_DISCONNECTING)) +#define US_FLIDX_RESETTING 22 /* 0x00400000 device reset in progress */ /* processing state machine states */ --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/drivers/video/asiliantfb.c 2004-05-10 01:19:43.129182424 -0700 @@ -0,0 +1,620 @@ +/* + * drivers/video/asiliantfb.c + * frame buffer driver for Asiliant 69000 chip + * Copyright (C) 2001-2003 Saito.K & Jeanne + * + * from driver/video/chipsfb.c and, + * + * drivers/video/asiliantfb.c -- frame buffer device for + * Asiliant 69030 chip (formerly Intel, formerly Chips & Technologies) + * Author: apc@agelectronics.co.uk + * Copyright (C) 2000 AG Electronics + * Note: the data sheets don't seem to be available from Asiliant. + * They are available by searching developer.intel.com, but are not otherwise + * linked to. + * + * This driver should be portable with minimal effort to the 69000 display + * chip, and to the twin-display mode of the 69030. + * Contains code from Thomas Hhenleitner (thanks) + * + * Derived from the CT65550 driver chipsfb.c: + * Copyright (C) 1998 Paul Mackerras + * ...which was derived from the Powermac "chips" driver: + * Copyright (C) 1997 Fabio Riccardi. + * And from the frame buffer device for Open Firmware-initialized devices: + * Copyright (C) 1997 Geert Uytterhoeven. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Built in clock of the 69030 */ +const unsigned Fref = 14318180; + +#define mmio_base (p->screen_base + 0x400000) + +#define mm_write_ind(num, val, ap, dp) do { \ + writeb((num), mmio_base + (ap)); writeb((val), mmio_base + (dp)); \ +} while (0) + +static void mm_write_xr(struct fb_info *p, u8 reg, u8 data) +{ + mm_write_ind(reg, data, 0x7ac, 0x7ad); +} +#define write_xr(num, val) mm_write_xr(p, num, val) + +static void mm_write_fr(struct fb_info *p, u8 reg, u8 data) +{ + mm_write_ind(reg, data, 0x7a0, 0x7a1); +} +#define write_fr(num, val) mm_write_fr(p, num, val) + +static void mm_write_cr(struct fb_info *p, u8 reg, u8 data) +{ + mm_write_ind(reg, data, 0x7a8, 0x7a9); +} +#define write_cr(num, val) mm_write_cr(p, num, val) + +static void mm_write_gr(struct fb_info *p, u8 reg, u8 data) +{ + mm_write_ind(reg, data, 0x79c, 0x79d); +} +#define write_gr(num, val) mm_write_gr(p, num, val) + +static void mm_write_sr(struct fb_info *p, u8 reg, u8 data) +{ + mm_write_ind(reg, data, 0x788, 0x789); +} +#define write_sr(num, val) mm_write_sr(p, num, val) + +static void mm_write_ar(struct fb_info *p, u8 reg, u8 data) +{ + readb(mmio_base + 0x7b4); + mm_write_ind(reg, data, 0x780, 0x780); +} +#define write_ar(num, val) mm_write_ar(p, num, val) + +/* + * Exported functions + */ +int asiliantfb_init(void); + +static int asiliantfb_pci_init(struct pci_dev *dp, const struct pci_device_id *); +static int asiliantfb_check_var(struct fb_var_screeninfo *var, + struct fb_info *info); +static int asiliantfb_set_par(struct fb_info *info); +static int asiliantfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info); + +static struct fb_ops asiliantfb_ops = { + .owner = THIS_MODULE, + .fb_check_var = asiliantfb_check_var, + .fb_set_par = asiliantfb_set_par, + .fb_setcolreg = asiliantfb_setcolreg, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, + .fb_cursor = soft_cursor, +}; + +/* Calculate the ratios for the dot clocks without using a single long long + * value */ +static void asiliant_calc_dclk2(u32 *ppixclock, u8 *dclk2_m, u8 *dclk2_n, u8 *dclk2_div) +{ + unsigned pixclock = *ppixclock; + unsigned Ftarget = 1000000 * (1000000 / pixclock); + unsigned n; + unsigned best_error = 0xffffffff; + unsigned best_m = 0xffffffff, + best_n = 0xffffffff; + unsigned ratio; + unsigned remainder; + unsigned char divisor = 0; + + /* Calculate the frequency required. This is hard enough. */ + ratio = 1000000 / pixclock; + remainder = 1000000 % pixclock; + Ftarget = 1000000 * ratio + (1000000 * remainder) / pixclock; + + while (Ftarget < 100000000) { + divisor += 0x10; + Ftarget <<= 1; + } + + ratio = Ftarget / Fref; + remainder = Ftarget % Fref; + + /* This expresses the constraint that 150kHz <= Fref/n <= 5Mhz, + * together with 3 <= n <= 257. */ + for (n = 3; n <= 257; n++) { + unsigned m = n * ratio + (n * remainder) / Fref; + + /* 3 <= m <= 257 */ + if (m >= 3 && m <= 257) { + unsigned new_error = ((Ftarget * n) - (Fref * m)) >= 0 ? + ((Ftarget * n) - (Fref * m)) : ((Fref * m) - (Ftarget * n)); + if (new_error < best_error) { + best_n = n; + best_m = m; + best_error = new_error; + } + } + /* But if VLD = 4, then 4m <= 1028 */ + else if (m <= 1028) { + /* remember there are still only 8-bits of precision in m, so + * avoid over-optimistic error calculations */ + unsigned new_error = ((Ftarget * n) - (Fref * (m & ~3))) >= 0 ? + ((Ftarget * n) - (Fref * (m & ~3))) : ((Fref * (m & ~3)) - (Ftarget * n)); + if (new_error < best_error) { + best_n = n; + best_m = m; + best_error = new_error; + } + } + } + if (best_m > 257) + best_m >>= 2; /* divide m by 4, and leave VCO loop divide at 4 */ + else + divisor |= 4; /* or set VCO loop divide to 1 */ + *dclk2_m = best_m - 2; + *dclk2_n = best_n - 2; + *dclk2_div = divisor; + *ppixclock = pixclock; + return; +} + +static void asiliant_set_timing(struct fb_info *p) +{ + unsigned hd = p->var.xres / 8; + unsigned hs = (p->var.xres + p->var.right_margin) / 8; + unsigned he = (p->var.xres + p->var.right_margin + p->var.hsync_len) / 8; + unsigned ht = (p->var.left_margin + p->var.xres + p->var.right_margin + p->var.hsync_len) / 8; + unsigned vd = p->var.yres; + unsigned vs = p->var.yres + p->var.lower_margin; + unsigned ve = p->var.yres + p->var.lower_margin + p->var.vsync_len; + unsigned vt = p->var.upper_margin + p->var.yres + p->var.lower_margin + p->var.vsync_len; + unsigned wd = (p->var.xres_virtual * ((p->var.bits_per_pixel+7)/8)) / 8; + + if ((p->var.xres == 640) && (p->var.yres == 480) && (p->var.pixclock == 39722)) { + write_fr(0x01, 0x02); /* LCD */ + } else { + write_fr(0x01, 0x01); /* CRT */ + } + + write_cr(0x11, (ve - 1) & 0x0f); + write_cr(0x00, (ht - 5) & 0xff); + write_cr(0x01, hd - 1); + write_cr(0x02, hd); + write_cr(0x03, ((ht - 1) & 0x1f) | 0x80); + write_cr(0x04, hs); + write_cr(0x05, (((ht - 1) & 0x20) <<2) | (he & 0x1f)); + write_cr(0x3c, (ht - 1) & 0xc0); + write_cr(0x06, (vt - 2) & 0xff); + write_cr(0x30, (vt - 2) >> 8); + write_cr(0x07, 0x00); + write_cr(0x08, 0x00); + write_cr(0x09, 0x00); + write_cr(0x10, (vs - 1) & 0xff); + write_cr(0x32, ((vs - 1) >> 8) & 0xf); + write_cr(0x11, ((ve - 1) & 0x0f) | 0x80); + write_cr(0x12, (vd - 1) & 0xff); + write_cr(0x31, ((vd - 1) & 0xf00) >> 8); + write_cr(0x13, wd & 0xff); + write_cr(0x41, (wd & 0xf00) >> 8); + write_cr(0x15, (vs - 1) & 0xff); + write_cr(0x33, ((vs - 1) >> 8) & 0xf); + write_cr(0x38, ((ht - 5) & 0x100) >> 8); + write_cr(0x16, (vt - 1) & 0xff); + write_cr(0x18, 0x00); + + if (p->var.xres == 640) { + writeb(0xc7, mmio_base + 0x784); /* set misc output reg */ + } else { + writeb(0x07, mmio_base + 0x784); /* set misc output reg */ + } +} + +static int asiliantfb_check_var(struct fb_var_screeninfo *var, + struct fb_info *p) +{ + unsigned long Ftarget, ratio, remainder; + + ratio = 1000000 / var->pixclock; + remainder = 1000000 % var->pixclock; + Ftarget = 1000000 * ratio + (1000000 * remainder) / var->pixclock; + + /* First check the constraint that the maximum post-VCO divisor is 32, + * and the maximum Fvco is 220MHz */ + if (Ftarget > 220000000 || Ftarget < 3125000) { + printk(KERN_ERR "asiliantfb dotclock must be between 3.125 and 220MHz\n"); + return -ENXIO; + } + var->xres_virtual = var->xres; + var->yres_virtual = var->yres; + + if (var->bits_per_pixel == 24) { + var->red.offset = 16; + var->green.offset = 8; + var->blue.offset = 0; + var->red.length = var->blue.length = var->green.length = 8; + } else if (var->bits_per_pixel == 16) { + switch (var->red.offset) { + case 11: + var->green.length = 6; + break; + case 10: + var->green.length = 5; + break; + default: + return -EINVAL; + } + var->green.offset = 5; + var->blue.offset = 0; + var->red.length = var->blue.length = 5; + } else if (var->bits_per_pixel == 8) { + var->red.offset = var->green.offset = var->blue.offset = 0; + var->red.length = var->green.length = var->blue.length = 8; + } + return 0; +} + +static int asiliantfb_set_par(struct fb_info *p) +{ + u8 dclk2_m; /* Holds m-2 value for register */ + u8 dclk2_n; /* Holds n-2 value for register */ + u8 dclk2_div; /* Holds divisor bitmask */ + + /* Set pixclock */ + asiliant_calc_dclk2(&p->var.pixclock, &dclk2_m, &dclk2_n, &dclk2_div); + + /* Set color depth */ + if (p->var.bits_per_pixel == 24) { + write_xr(0x81, 0x16); /* 24 bit packed color mode */ + write_xr(0x82, 0x00); /* Disable palettes */ + write_xr(0x20, 0x20); /* 24 bit blitter mode */ + } else if (p->var.bits_per_pixel == 16) { + if (p->var.red.offset == 11) + write_xr(0x81, 0x15); /* 16 bit color mode */ + else + write_xr(0x81, 0x14); /* 15 bit color mode */ + write_xr(0x82, 0x00); /* Disable palettes */ + write_xr(0x20, 0x10); /* 16 bit blitter mode */ + } else if (p->var.bits_per_pixel == 8) { + write_xr(0x0a, 0x02); /* Linear */ + write_xr(0x81, 0x12); /* 8 bit color mode */ + write_xr(0x82, 0x00); /* Graphics gamma enable */ + write_xr(0x20, 0x00); /* 8 bit blitter mode */ + } + p->fix.line_length = p->var.xres * (p->var.bits_per_pixel >> 3); + p->fix.visual = (p->var.bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; + write_xr(0xc4, dclk2_m); + write_xr(0xc5, dclk2_n); + write_xr(0xc7, dclk2_div); + /* Set up the CR registers */ + asiliant_set_timing(p); + return 0; +} + +static int asiliantfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *p) +{ + if (regno > 255) + return 1; + red >>= 8; + green >>= 8; + blue >>= 8; + + /* Set hardware palete */ + writeb(regno, mmio_base + 0x790); + udelay(1); + writeb(red, mmio_base + 0x791); + writeb(green, mmio_base + 0x791); + writeb(blue, mmio_base + 0x791); + + switch(p->var.bits_per_pixel) { + case 15: + if (regno < 16) { + ((u32 *)(p->pseudo_palette))[regno] = + ((red & 0xf8) << 7) | + ((green & 0xf8) << 2) | + ((blue & 0xf8) >> 3); + } + break; + case 16: + if (regno < 16) { + ((u32 *)(p->pseudo_palette))[regno] = + ((red & 0xf8) << 8) | + ((green & 0xfc) << 3) | + ((blue & 0xf8) >> 3); + } + break; + case 24: + if (regno < 24) { + ((u32 *)(p->pseudo_palette))[regno] = + (red << 16) | + (green << 8) | + (blue); + } + break; + } + return 0; +} + +struct chips_init_reg { + unsigned char addr; + unsigned char data; +}; + +#define N_ELTS(x) (sizeof(x) / sizeof(x[0])) + +static struct chips_init_reg chips_init_sr[] = +{ + {0x00, 0x03}, /* Reset register */ + {0x01, 0x01}, /* Clocking mode */ + {0x02, 0x0f}, /* Plane mask */ + {0x04, 0x0e} /* Memory mode */ +}; + +static struct chips_init_reg chips_init_gr[] = +{ + {0x03, 0x00}, /* Data rotate */ + {0x05, 0x00}, /* Graphics mode */ + {0x06, 0x01}, /* Miscellaneous */ + {0x08, 0x00} /* Bit mask */ +}; + +static struct chips_init_reg chips_init_ar[] = +{ + {0x10, 0x01}, /* Mode control */ + {0x11, 0x00}, /* Overscan */ + {0x12, 0x0f}, /* Memory plane enable */ + {0x13, 0x00} /* Horizontal pixel panning */ +}; + +static struct chips_init_reg chips_init_cr[] = +{ + {0x0c, 0x00}, /* Start address high */ + {0x0d, 0x00}, /* Start address low */ + {0x40, 0x00}, /* Extended Start Address */ + {0x41, 0x00}, /* Extended Start Address */ + {0x14, 0x00}, /* Underline location */ + {0x17, 0xe3}, /* CRT mode control */ + {0x70, 0x00} /* Interlace control */ +}; + + +static struct chips_init_reg chips_init_fr[] = +{ + {0x01, 0x02}, + {0x03, 0x08}, + {0x08, 0xcc}, + {0x0a, 0x08}, + {0x18, 0x00}, + {0x1e, 0x80}, + {0x40, 0x83}, + {0x41, 0x00}, + {0x48, 0x13}, + {0x4d, 0x60}, + {0x4e, 0x0f}, + + {0x0b, 0x01}, + + {0x21, 0x51}, + {0x22, 0x1d}, + {0x23, 0x5f}, + {0x20, 0x4f}, + {0x34, 0x00}, + {0x24, 0x51}, + {0x25, 0x00}, + {0x27, 0x0b}, + {0x26, 0x00}, + {0x37, 0x80}, + {0x33, 0x0b}, + {0x35, 0x11}, + {0x36, 0x02}, + {0x31, 0xea}, + {0x32, 0x0c}, + {0x30, 0xdf}, + {0x10, 0x0c}, + {0x11, 0xe0}, + {0x12, 0x50}, + {0x13, 0x00}, + {0x16, 0x03}, + {0x17, 0xbd}, + {0x1a, 0x00}, +}; + + +static struct chips_init_reg chips_init_xr[] = +{ + {0xce, 0x00}, /* set default memory clock */ + {0xcc, 200 }, /* MCLK ratio M */ + {0xcd, 18 }, /* MCLK ratio N */ + {0xce, 0x90}, /* MCLK divisor = 2 */ + + {0xc4, 209 }, + {0xc5, 118 }, + {0xc7, 32 }, + {0xcf, 0x06}, + {0x09, 0x01}, /* IO Control - CRT controller extensions */ + {0x0a, 0x02}, /* Frame buffer mapping */ + {0x0b, 0x01}, /* PCI burst write */ + {0x40, 0x03}, /* Memory access control */ + {0x80, 0x82}, /* Pixel pipeline configuration 0 */ + {0x81, 0x12}, /* Pixel pipeline configuration 1 */ + {0x82, 0x08}, /* Pixel pipeline configuration 2 */ + + {0xd0, 0x0f}, + {0xd1, 0x01}, +}; + +static void __init chips_hw_init(struct fb_info *p) +{ + int i; + + for (i = 0; i < N_ELTS(chips_init_xr); ++i) + write_xr(chips_init_xr[i].addr, chips_init_xr[i].data); + write_xr(0x81, 0x12); + write_xr(0x82, 0x08); + write_xr(0x20, 0x00); + for (i = 0; i < N_ELTS(chips_init_sr); ++i) + write_sr(chips_init_sr[i].addr, chips_init_sr[i].data); + for (i = 0; i < N_ELTS(chips_init_gr); ++i) + write_gr(chips_init_gr[i].addr, chips_init_gr[i].data); + for (i = 0; i < N_ELTS(chips_init_ar); ++i) + write_ar(chips_init_ar[i].addr, chips_init_ar[i].data); + /* Enable video output in attribute index register */ + writeb(0x20, mmio_base + 0x780); + for (i = 0; i < N_ELTS(chips_init_cr); ++i) + write_cr(chips_init_cr[i].addr, chips_init_cr[i].data); + for (i = 0; i < N_ELTS(chips_init_fr); ++i) + write_fr(chips_init_fr[i].addr, chips_init_fr[i].data); +} + +static struct fb_fix_screeninfo asiliantfb_fix __initdata = { + .id = "Asiliant 69000", + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_PSEUDOCOLOR, + .accel = FB_ACCEL_NONE, + .line_length = 640, + .smem_len = 0x200000, /* 2MB */ +}; + +static struct fb_var_screeninfo asiliantfb_var __initdata = { + .xres = 640, + .yres = 480, + .xres_virtual = 640, + .yres_virtual = 480, + .bits_per_pixel = 8, + .red = { .length = 8 }, + .green = { .length = 8 }, + .blue = { .length = 8 }, + .height = -1, + .width = -1, + .vmode = FB_VMODE_NONINTERLACED, + .pixclock = 39722, + .left_margin = 48, + .right_margin = 16, + .upper_margin = 33, + .lower_margin = 10, + .hsync_len = 96, + .vsync_len = 2, +}; + +static void __init init_asiliant(struct fb_info *p, unsigned long addr) +{ + p->fix = asiliantfb_fix; + p->fix.smem_start = addr; + p->var = asiliantfb_var; + p->fbops = &asiliantfb_ops; + p->flags = FBINFO_FLAG_DEFAULT; + + fb_alloc_cmap(&p->cmap, 256, 0); + + if (register_framebuffer(p) < 0) { + printk(KERN_ERR "C&T 69000 framebuffer failed to register\n"); + return; + } + + printk(KERN_INFO "fb%d: Asiliant 69000 frame buffer (%dK RAM detected)\n", + p->node, p->fix.smem_len / 1024); + + writeb(0xff, mmio_base + 0x78c); + chips_hw_init(p); +} + +static int __devinit +asiliantfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent) +{ + unsigned long addr, size; + struct fb_info *p; + + if ((dp->resource[0].flags & IORESOURCE_MEM) == 0) + return -ENODEV; + addr = pci_resource_start(dp, 0); + size = pci_resource_len(dp, 0); + if (addr == 0) + return -ENODEV; + if (!request_mem_region(addr, size, "asiliantfb")) + return -EBUSY; + + p = framebuffer_alloc(sizeof(u32) * 256, &dp->dev); + if (!p) { + release_mem_region(addr, size); + return -ENOMEM; + } + p->pseudo_palette = p->par; + p->par = NULL; + + p->screen_base = ioremap(addr, 0x800000); + if (p->screen_base == NULL) { + release_mem_region(addr, size); + framebuffer_release(p); + return -ENOMEM; + } + + pci_write_config_dword(dp, 4, 0x02800083); + writeb(3, addr + 0x400784); + + init_asiliant(p, addr); + + /* Clear the entire framebuffer */ + memset(p->screen_base, 0, 0x200000); + + pci_set_drvdata(dp, p); + return 0; +} + +static void __devexit asiliantfb_remove(struct pci_dev *dp) +{ + struct fb_info *p = pci_get_drvdata(dp); + + unregister_framebuffer(p); + iounmap(p->screen_base); + release_mem_region(pci_resource_start(dp, 0), pci_resource_len(dp, 0)); + pci_set_drvdata(dp, NULL); + framebuffer_release(p); +} + +static struct pci_device_id asiliantfb_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_69000, PCI_ANY_ID, PCI_ANY_ID }, + { 0 } +}; + +MODULE_DEVICE_TABLE(pci, asiliantfb_pci_tbl); + +static struct pci_driver asiliantfb_driver = { + .name = "asiliantfb", + .id_table = asiliantfb_pci_tbl, + .probe = asiliantfb_pci_init, + .remove = __devexit_p(asiliantfb_remove), +}; + +int __init asiliantfb_init(void) +{ + return pci_module_init(&asiliantfb_driver); +} + +static void __exit asiliantfb_exit(void) +{ + pci_unregister_driver(&asiliantfb_driver); +} + +MODULE_LICENSE("GPL"); --- linux-2.6.6/drivers/video/atafb.c 2003-06-14 12:17:58.000000000 -0700 +++ 25/drivers/video/atafb.c 2004-05-10 01:19:57.561988304 -0700 @@ -2819,8 +2819,6 @@ int __init atafb_init(void) fb_info.node, fb_info.modename, screen_len>>10); /* TODO: This driver cannot be unloaded yet */ - MOD_INC_USE_COUNT; - return 0; } @@ -3097,13 +3095,4 @@ int init_module(void) { return atafb_init(); } - -void cleanup_module(void) -{ - /* Not reached because the usecount will never - be decremented to zero */ - unregister_framebuffer(&fb_info); - /* atari_stram_free( screen_base ); */ - /* TODO: further clean up ... */ -} #endif /* MODULE */ --- linux-2.6.6/drivers/video/aty/radeon_accel.c 2004-02-17 20:48:45.000000000 -0800 +++ 25/drivers/video/aty/radeon_accel.c 2004-05-10 01:19:41.379448424 -0700 @@ -53,6 +53,18 @@ void radeonfb_fillrect(struct fb_info *i static void radeonfb_prim_copyarea(struct radeonfb_info *rinfo, const struct fb_copyarea *area) { + int xdir, ydir; + u32 sx, sy, dx, dy, w, h; + + w = area->width; h = area->height; + dx = area->dx; dy = area->dy; + sx = area->sx; sy = area->sy; + xdir = sx - dx; + ydir = sy - dy; + + if ( xdir < 0 ) { sx += w-1; dx += w-1; } + if ( ydir < 0 ) { sy += h-1; dy += h-1; } + radeon_fifo_wait(3); OUTREG(DP_GUI_MASTER_CNTL, rinfo->dp_gui_master_cntl /* i.e. GMC_DST_32BPP */ @@ -60,12 +72,13 @@ static void radeonfb_prim_copyarea(struc | ROP3_S | DP_SRC_RECT ); OUTREG(DP_WRITE_MSK, 0xffffffff); - OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM)); + OUTREG(DP_CNTL, (xdir>=0 ? DST_X_LEFT_TO_RIGHT : 0) + | (ydir>=0 ? DST_Y_TOP_TO_BOTTOM : 0)); radeon_fifo_wait(3); - OUTREG(SRC_Y_X, (area->sy << 16) | area->sx); - OUTREG(DST_Y_X, (area->dy << 16) | area->dx); - OUTREG(DST_HEIGHT_WIDTH, (area->height << 16) | area->width); + OUTREG(SRC_Y_X, (sy << 16) | sx); + OUTREG(DST_Y_X, (dy << 16) | dx); + OUTREG(DST_HEIGHT_WIDTH, (h << 16) | w); } --- linux-2.6.6/drivers/video/aty/radeon_base.c 2004-03-10 20:41:30.000000000 -0800 +++ 25/drivers/video/aty/radeon_base.c 2004-05-10 01:19:41.111489160 -0700 @@ -2204,6 +2204,7 @@ static int radeonfb_pci_register (struct rinfo->mapped_vram /= 2; continue; } + memset(rinfo->fb_base, 0, rinfo->mapped_vram); break; } --- linux-2.6.6/drivers/video/console/dummycon.c 2003-06-14 12:18:30.000000000 -0700 +++ 25/drivers/video/console/dummycon.c 2004-05-10 01:19:46.845617440 -0700 @@ -11,6 +11,7 @@ #include #include #include +#include /* * Dummy console driver @@ -58,6 +59,7 @@ static int dummycon_dummy(void) */ const struct consw dummy_con = { + .owner = THIS_MODULE, .con_startup = dummycon_startup, .con_init = dummycon_init, .con_deinit = DUMMY, --- linux-2.6.6/drivers/video/console/fbcon.c 2004-04-03 20:39:13.000000000 -0800 +++ 25/drivers/video/console/fbcon.c 2004-05-10 01:19:46.847617136 -0700 @@ -304,8 +304,7 @@ int set_con2fb_map(int unit, int newidx) return -ENODEV; con2fb_map[unit] = newidx; fbcon_is_default = (vc->vc_sw == &fb_con) ? 1 : 0; - take_over_console(&fb_con, unit, unit, fbcon_is_default); - return 0; + return take_over_console(&fb_con, unit, unit, fbcon_is_default); } /* @@ -609,6 +608,7 @@ static void fbcon_init(struct vc_data *v fb_display[unit].scrollmode = SCROLL_YNOMOVE; else fb_display[unit].scrollmode = SCROLL_YREDRAW; + con_set_default_unimap(unit); fbcon_set_display(vc, init, !init); } @@ -749,14 +749,6 @@ static void fbcon_set_display(struct vc_ vc->vc_cols = nr_cols; vc->vc_rows = nr_rows; } - p->vrows = info->var.yres_virtual / vc->vc_font.height; - if(info->var.yres > (vc->vc_font.height * (vc->vc_rows + 1))) { - p->vrows -= (info->var.yres - (vc->vc_font.height * vc->vc_rows)) / vc->vc_font.height; - } - if ((info->var.yres % vc->vc_font.height) && - (info->var.yres_virtual % vc->vc_font.height < - info->var.yres % vc->vc_font.height)) - p->vrows--; vc->vc_can_do_color = info->var.bits_per_pixel != 1; vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; if (charcnt == 256) { @@ -767,7 +759,7 @@ static void fbcon_set_display(struct vc_ vc->vc_complement_mask <<= 1; } - if (!init) { + if (logo) { if (vc->vc_cols != nr_cols || vc->vc_rows != nr_rows) vc_resize(vc->vc_num, nr_cols, nr_rows); else if (CON_IS_VISIBLE(vc) && @@ -784,9 +776,6 @@ static void fbcon_set_display(struct vc_ vc->vc_pos += logo_lines * vc->vc_size_row; kfree(save); } - } - - if (logo) { if (logo_lines > vc->vc_bottom) { logo_shown = -1; printk(KERN_INFO @@ -1570,6 +1559,8 @@ static int fbcon_resize(struct vc_data * p->vrows = var.yres_virtual/fh; if (var.yres > (fh * (height + 1))) p->vrows -= (var.yres - (fh * height)) / fh; + if ((var.yres % fh) && (var.yres_virtual % fh < var.yres % fh)) + p->vrows--; return 0; } @@ -1839,15 +1830,6 @@ static int fbcon_do_set_font(struct vc_d if (resize) { /* reset wrap/pan */ info->var.xoffset = info->var.yoffset = p->yscroll = 0; - p->vrows = info->var.yres_virtual / h; - -#if 0 /* INCOMPLETE - let the console gurus handle this */ - if(info->var.yres > (h * (vc->vc_rows + 1)) - p->vrows -= (info->var.yres - (h * vc->vc_rows)) / h; -#endif - if ((info->var.yres % h) - && (info->var.yres_virtual % h < info->var.yres % h)) - p->vrows--; updatescrollmode(p, vc); vc_resize(vc->vc_num, info->var.xres / w, info->var.yres / h); if (CON_IS_VISIBLE(vc) && softback_buf) { @@ -2257,6 +2239,7 @@ static int fbcon_event_notify(struct not */ const struct consw fb_con = { + .owner = THIS_MODULE, .con_startup = fbcon_startup, .con_init = fbcon_init, .con_deinit = fbcon_deinit, @@ -2286,10 +2269,16 @@ static int fbcon_event_notifier_register int __init fb_console_init(void) { + int err; + if (!num_registered_fb) return -ENODEV; - take_over_console(&fb_con, first_fb_vc, last_fb_vc, fbcon_is_default); + err = take_over_console(&fb_con, first_fb_vc, last_fb_vc, + fbcon_is_default); + if (err) + return err; + acquire_console_sem(); if (!fbcon_event_notifier_registered) { fb_register_client(&fbcon_event_notifer); --- linux-2.6.6/drivers/video/console/Makefile 2004-02-17 20:48:45.000000000 -0800 +++ 25/drivers/video/console/Makefile 2004-05-10 01:19:16.007305576 -0700 @@ -19,7 +19,7 @@ font-objs += $(font-objs-y) # Each configuration option enables a list of files. obj-$(CONFIG_DUMMY_CONSOLE) += dummycon.o -obj-$(CONFIG_SGI_NEWPORT_CONSOLE) += newport_con.o +obj-$(CONFIG_SGI_NEWPORT_CONSOLE) += newport_con.o font.o obj-$(CONFIG_PROM_CONSOLE) += promcon.o promcon_tbl.o obj-$(CONFIG_STI_CONSOLE) += sticon.o sticore.o obj-$(CONFIG_VGA_CONSOLE) += vgacon.o --- linux-2.6.6/drivers/video/console/mdacon.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/video/console/mdacon.c 2004-05-10 01:19:46.848616984 -0700 @@ -370,8 +370,6 @@ static void mdacon_init(struct vc_data * if (mda_display_fg == NULL) mda_display_fg = c; - - MOD_INC_USE_COUNT; } static void mdacon_deinit(struct vc_data *c) @@ -380,8 +378,6 @@ static void mdacon_deinit(struct vc_data if (mda_display_fg == c) mda_display_fg = NULL; - - MOD_DEC_USE_COUNT; } static inline u16 mda_convert_attr(u16 ch) @@ -586,6 +582,7 @@ static int mdacon_scroll(struct vc_data */ const struct consw mda_con = { + .owner = THIS_MODULE, .con_startup = mdacon_startup, .con_init = mdacon_init, .con_deinit = mdacon_deinit, @@ -609,8 +606,7 @@ int __init mda_console_init(void) if (mda_first_vc > mda_last_vc) return 1; - take_over_console(&mda_con, mda_first_vc-1, mda_last_vc-1, 0); - return 0; + return take_over_console(&mda_con, mda_first_vc-1, mda_last_vc-1, 0); } void __exit mda_console_exit(void) --- linux-2.6.6/drivers/video/console/newport_con.c 2003-06-14 12:18:30.000000000 -0700 +++ 25/drivers/video/console/newport_con.c 2004-05-10 01:19:46.848616984 -0700 @@ -32,6 +32,7 @@ extern struct font_desc font_vga_8x16; +extern unsigned long sgi_gfxaddr; #define FONT_DATA ((unsigned char *)font_vga_8x16.data) @@ -43,7 +44,7 @@ extern struct font_desc font_vga_8x16; static unsigned char *font_data[MAX_NR_CONSOLES]; -extern struct newport_regs *npregs; +static struct newport_regs *npregs; static int logo_active; static int topscan; @@ -51,6 +52,8 @@ static int xcurs_correction = 29; static int newport_xsize; static int newport_ysize; +static int newport_set_def_font(int unit, struct console_font_op *op); + #define BMASK(c) (c << 24) #define RENDER(regs, cp) do { \ @@ -95,11 +98,33 @@ static inline void newport_init_cmap(voi } } +static void newport_show_logo(void) +{ #ifdef CONFIG_LOGO_SGI_CLUT224 -static void newport_show_logo(void); -#else -#define newport_show_logo() do { } while (0) -#endif + const struct linux_logo *logo = fb_find_logo(8); + const unsigned char *clut = logo->clut; + const unsigned char *data = logo->data; + unsigned long i; + + for (i = 0; i < logo->clutsize; i++) { + newport_bfwait(); + newport_cmap_setaddr(npregs, i + 0x20); + newport_cmap_setrgb(npregs, clut[0], clut[1], clut[2]); + clut += 3; + } + + newport_wait(); + npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | + NPORT_DMODE0_CHOST); + + npregs->set.xystarti = ((newport_xsize - logo->width) << 16) | (0); + npregs->set.xyendi = ((newport_xsize - 1) << 16); + newport_wait(); + + for (i = 0; i < logo->width*logo->height; i++) + npregs->go.hostrw0 = *data++ << 24; +#endif /* CONFIG_LOGO_SGI_CLUT224 */ +} static inline void newport_clear_screen(int xstart, int ystart, int xend, int yend, int ci) @@ -258,26 +283,22 @@ static void newport_get_revisions(void) xcurs_correction = 21; } -#ifdef MODULE +/* Can't be __init, take_over_console may call it later */ static const char *newport_startup(void) -#else -static const char *__init newport_startup(void) -#endif { int i; - struct newport_regs *p; - - npregs = (struct newport_regs *) (KSEG1 + 0x1f0f0000); - p = npregs; - p->cset.config = NPORT_CFG_GD0; + if (!sgi_gfxaddr) + return NULL; + npregs = (struct newport_regs *) (KSEG1 + sgi_gfxaddr); + npregs->cset.config = NPORT_CFG_GD0; if (newport_wait()) { return NULL; } - p->set.xstarti = TESTVAL; - if (p->set._xstart.word != XSTI_TO_FXSTART(TESTVAL)) + npregs->set.xstarti = TESTVAL; + if (npregs->set._xstart.word != XSTI_TO_FXSTART(TESTVAL)) return NULL; for (i = 0; i < MAX_NR_CONSOLES; i++) @@ -287,8 +308,6 @@ static const char *__init newport_startu newport_get_revisions(); newport_get_screensize(); - /* gfx_init (display_desc); */ - return "SGI Newport"; } @@ -299,6 +318,15 @@ static void newport_init(struct vc_data vc->vc_can_do_color = 1; } +static void newport_deinit(struct vc_data *c) +{ + int i; + + /* free memory used by user font */ + for (i = 0; i < MAX_NR_CONSOLES; i++) + newport_set_def_font(i, NULL); +} + static void newport_clear(struct vc_data *vc, int sy, int sx, int height, int width) { @@ -677,9 +705,10 @@ static int newport_dummy(struct vc_data #define DUMMY (void *) newport_dummy const struct consw newport_con = { + .owner = THIS_MODULE, .con_startup = newport_startup, .con_init = newport_init, - .con_deinit = DUMMY, + .con_deinit = newport_deinit, .con_clear = newport_clear, .con_putc = newport_putc, .con_putcs = newport_putcs, @@ -696,63 +725,18 @@ const struct consw newport_con = { }; #ifdef MODULE -MODULE_LICENSE("GPL"); - -int init_module(void) +static int __init newport_console_init(void) { - if (!newport_startup()) - printk("Error loading SGI Newport Console driver\n"); - else - printk("Loading SGI Newport Console Driver\n"); - take_over_console(&newport_con, 0, MAX_NR_CONSOLES - 1, 1); - - return 0; + return take_over_console(&newport_con, 0, MAX_NR_CONSOLES - 1, 1); } -int cleanup_module(void) +static void __exit newport_console_exit(void) { - int i; - - printk("Unloading SGI Newport Console Driver\n"); - /* free memory used by user font */ - for (i = 0; i < MAX_NR_CONSOLES; i++) - newport_set_def_font(i, NULL); - - return 0; + give_up_console(&newport_con); } -#endif - -#ifdef CONFIG_LOGO_SGI_CLUT224 - -#undef __initdata -#define __initdata -#include "../logo/logo_sgi_clut224.c" - -static void newport_show_logo(void) -{ - const struct linux_logo *logo = &logo_sgi_clut224; - const unsigned char *clut = logo->clut; - const unsigned char *data = logo->data; - unsigned long i; - - for (i = 0; i < logo->clutsize; i++) { - newport_bfwait(); - newport_cmap_setaddr(npregs, i + 0x20); - newport_cmap_setrgb(npregs, clut[0], clut[1], clut[2]); - clut += 3; - } - - newport_wait(); - npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | - NPORT_DMODE0_CHOST); - - npregs->set.xystarti = ((newport_xsize - logo->width) << 16) | (0); - npregs->set.xyendi = ((newport_xsize - 1) << 16); - newport_wait(); - - for (i = 0; i < logo->width*logo->height; i++) - npregs->go.hostrw0 = *data++ << 24; -} -#endif /* CONFIG_LOGO_SGI_CLUT224 */ +module_init(newport_console_init); +module_exit(newport_console_exit); +#endif +MODULE_LICENSE("GPL"); --- linux-2.6.6/drivers/video/console/promcon.c 2004-03-10 20:41:30.000000000 -0800 +++ 25/drivers/video/console/promcon.c 2004-05-10 01:19:46.849616832 -0700 @@ -574,6 +574,7 @@ static int promcon_dummy(void) #define DUMMY (void *) promcon_dummy const struct consw prom_con = { + .owner = THIS_MODULE, .con_startup = promcon_startup, .con_init = promcon_init, .con_deinit = promcon_deinit, --- linux-2.6.6/drivers/video/console/sticon.c 2004-03-10 20:41:30.000000000 -0800 +++ 25/drivers/video/console/sticon.c 2004-05-10 01:19:46.850616680 -0700 @@ -354,6 +354,7 @@ static void sticon_save_screen(struct vc } static struct consw sti_con = { + .owner = THIS_MODULE, .con_startup = sticon_startup, .con_init = sticon_init, .con_deinit = sticon_deinit, @@ -390,7 +391,7 @@ int __init sticonsole_init(void) if (conswitchp == &dummy_con) { printk(KERN_INFO "sticon: Initializing STI text console.\n"); - take_over_console(&sti_con, 0, MAX_NR_CONSOLES - 1, 1); + return take_over_console(&sti_con, 0, MAX_NR_CONSOLES - 1, 1); } return 0; } --- linux-2.6.6/drivers/video/console/sticore.c 2004-02-17 20:48:45.000000000 -0800 +++ 25/drivers/video/console/sticore.c 2004-05-10 01:19:35.629322576 -0700 @@ -22,7 +22,6 @@ #include #include -#include #include #include #include --- linux-2.6.6/drivers/video/console/vgacon.c 2004-03-10 20:41:30.000000000 -0800 +++ 25/drivers/video/console/vgacon.c 2004-05-10 01:19:46.850616680 -0700 @@ -1065,6 +1065,7 @@ static int vgacon_dummy(struct vc_data * #define DUMMY (void *) vgacon_dummy const struct consw vga_con = { + .owner = THIS_MODULE, .con_startup = vgacon_startup, .con_init = vgacon_init, .con_deinit = vgacon_deinit, --- linux-2.6.6/drivers/video/cyberfb.c 2003-06-14 12:17:57.000000000 -0700 +++ 25/drivers/video/cyberfb.c 2004-05-10 01:19:57.563988000 -0700 @@ -1065,7 +1065,6 @@ int __init cyberfb_init(void) fb_info.node, fb_info.modename, CyberSize>>10); /* TODO: This driver cannot be unloaded yet */ - MOD_INC_USE_COUNT; DPRINTK("EXIT\n"); return 0; } @@ -1206,14 +1205,6 @@ int init_module(void) { return cyberfb_init(); } - -void cleanup_module(void) -{ - /* Not reached because the usecount will never be - decremented to zero */ - unregister_framebuffer(&fb_info); - /* TODO: clean up ... */ -} #endif /* MODULE */ /* --- linux-2.6.6/drivers/video/fbmem.c 2004-05-09 21:07:25.000000000 -0700 +++ 25/drivers/video/fbmem.c 2004-05-10 01:19:42.386295360 -0700 @@ -121,6 +121,8 @@ extern int sun3fb_init(void); extern int sun3fb_setup(char *); extern int sgivwfb_init(void); extern int sgivwfb_setup(char*); +extern int gbefb_init(void); +extern int gbefb_setup(char*); extern int rivafb_init(void); extern int rivafb_setup(char*); extern int tdfxfb_init(void); @@ -307,6 +309,9 @@ static struct { #ifdef CONFIG_FB_SGIVW { "sgivwfb", sgivwfb_init, sgivwfb_setup }, #endif +#ifdef CONFIG_FB_GBE + { "gbefb", gbefb_init, gbefb_setup }, +#endif #ifdef CONFIG_FB_ACORN { "acornfb", acornfb_init, acornfb_setup }, #endif @@ -1013,7 +1018,7 @@ fb_ioctl(struct inode *inode, struct fil struct fb_con2fbmap con2fb; #endif struct fb_cmap cmap; - int i, rc; + int i; if (!fb) return -ENODEV; @@ -1055,9 +1060,9 @@ fb_ioctl(struct inode *inode, struct fil return 0; case FBIO_CURSOR: acquire_console_sem(); - rc = fb_cursor(info, (struct fb_cursor *) arg); + i = fb_cursor(info, (struct fb_cursor *) arg); release_console_sem(); - return rc; + return i; #ifdef CONFIG_FRAMEBUFFER_CONSOLE case FBIOGET_CON2FBMAP: if (copy_from_user(&con2fb, (void *)arg, sizeof(con2fb))) @@ -1178,8 +1183,7 @@ fb_mmap(struct file *file, struct vm_are if (boot_cpu_data.x86 > 3) pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; #elif defined(__mips__) - pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK; - pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED; + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); #elif defined(__hppa__) pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE; #elif defined(__ia64__) || defined(__arm__) || defined(__sh__) @@ -1286,6 +1290,7 @@ register_framebuffer(struct fb_info *fb_ fb_info->pixmap.size = FBPIXMAPSIZE; fb_info->pixmap.buf_align = 1; fb_info->pixmap.scan_align = 1; + fb_info->pixmap.access_align = 4; fb_info->pixmap.flags = FB_PIXMAP_DEFAULT; } } @@ -1301,6 +1306,7 @@ register_framebuffer(struct fb_info *fb_ fb_info->sprite.size = FBPIXMAPSIZE; fb_info->sprite.buf_align = 1; fb_info->sprite.scan_align = 1; + fb_info->sprite.access_align = 4; fb_info->sprite.flags = FB_PIXMAP_DEFAULT; } } --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25/drivers/video/gbefb.c 2004-05-10 01:19:16.274264992 -0700 @@ -0,0 +1,1200 @@ +/* + * SGI GBE frame buffer driver + * + * Copyright (C) 1999 Silicon Graphics, Inc. - Jeffrey Newquist + * Copyright (C) 2002 Vivien Chappelier + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_X86 +#include +#endif +#ifdef CONFIG_MIPS +#include +#endif +#include +#include +#include + +#include