## Automatically generated incremental diff ## From: linux-2.5.2-pre11 ## To: linux-2.5.2 ## Robot: $Id: make-incremental-diff,v 1.9 2001/12/10 00:06:56 hpa Exp $ diff -urN linux-2.5.2-pre11/Documentation/Configure.help linux/Documentation/Configure.help --- linux-2.5.2-pre11/Documentation/Configure.help Mon Jan 14 18:28:21 2002 +++ linux/Documentation/Configure.help Mon Jan 14 18:28:26 2002 @@ -6301,6 +6301,18 @@ boards supported by this driver, and for further information on the use of this driver. +SCSI tape drive support for Smart Array 5xxx +CONFIG_CISS_SCSI_TAPE + When enabled (Y), this option allows SCSI tape drives and SCSI medium + changers (tape robots) to be accessed via a Compaq 5xxx array + controller. (See Documentation/cciss.txt for more details.) + + "SCSI support" and "SCSI tape support" must also be enabled for this + option to work. + + When this option is disabled (N), the SCSI portion of the driver + is not compiled. + QuickNet Internet LineJack/PhoneJack support CONFIG_PHONE_IXJ Say M if you have a telephony card manufactured by Quicknet @@ -24028,6 +24040,13 @@ If you are using GDB for remote debugging over a serial port and would like kernel messages to be formatted into GDB $O packets so that GDB prints them as program output, say 'Y'. + +CRC32 functions +CONFIG_CRC32 + This option is provided for the case where no in-kernel-tree + modules require CRC32 functions, but a module built outside the + kernel tree does. Such modules that use library CRC32 functions + require M here. # # A couple of things I keep forgetting: diff -urN linux-2.5.2-pre11/Documentation/block/request.txt linux/Documentation/block/request.txt --- linux-2.5.2-pre11/Documentation/block/request.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/block/request.txt Mon Jan 14 18:28:26 2002 @@ -0,0 +1,86 @@ + +struct request documentation + +Jens Axboe 070102 + +1.0 +Index + +2.0 Struct request members classification + + 2.1 struct request members explanation + +3.0 + + +2.0 +Short explanation of request members + +Classification flags: + + D driver member + B block layer member + I I/O scheduler member + +Unless an entry contains a D classification, a device driver must not access +this member. Some members may contain D classifications, but should only be +access through certain macros or functions (eg ->flags). + + + +2.1 +Member Flag Comment +------ ---- ------- + +struct list_head queuelist BI Organization on various internal + queues + +void *elevator_private I I/O scheduler private data + +unsigned char cmd[16] D Driver can use this for setting up + a cdb before execution, see + blk_queue_prep_rq + +unsigned long flags DBI Contains info about data direction, + request type, etc. + +int rq_status D Request status bits + +kdev_t rq_dev DBI Target device + +int errors DB Error counts + +sector_t sector DBI Target location + +unsigned long hard_nr_sectors B Used to keep sector sane + +unsigned long nr_sectors DBI Total number of sectors in request + +unsigned long hard_nr_sectors B Used to keep nr_sectors sane + +unsigned short nr_phys_segments DB Number of physical scatter gather + segments in a request + +unsigned short nr_hw_segments DB Number of hardware scatter gather + segments in a request + +unsigned int current_nr_sectors DB Number of sectors in first segment + of request + +unsigned int hard_cur_sectors B Used to keep current_nr_sectors sane + +void *special D Free to be used by driver + +char *buffer D Map of first segment, also see + section on bouncing SECTION + +struct completion *waiting D Can be used by driver to get signalled + on request completion + +struct bio *bio DBI First bio in request + +struct bio *biotail DBI Last bio in request + +request_queue_t *q DB Request queue this request belongs to + +struct request_list *rl B Request list this request came from diff -urN linux-2.5.2-pre11/Documentation/cciss.txt linux/Documentation/cciss.txt --- linux-2.5.2-pre11/Documentation/cciss.txt Thu Oct 11 09:04:57 2001 +++ linux/Documentation/cciss.txt Mon Jan 14 18:28:26 2002 @@ -100,7 +100,7 @@ can be informed of changes to the virtual SCSI bus which the driver presents to it in the usual way. For example: - echo add-single-device 3 2 1 0 > /proc/scsi/scsi + echo scsi add-single-device 3 2 1 0 > /proc/scsi/scsi to add a device on controller 3, bus 2, target 1, lun 0. Note that the driver makes an effort to preserve the devices positions diff -urN linux-2.5.2-pre11/Documentation/filesystems/devfs/ChangeLog linux/Documentation/filesystems/devfs/ChangeLog --- linux-2.5.2-pre11/Documentation/filesystems/devfs/ChangeLog Mon Jan 14 18:28:21 2002 +++ linux/Documentation/filesystems/devfs/ChangeLog Mon Jan 14 18:28:26 2002 @@ -1863,3 +1863,9 @@ - Defined macros for error and debug messages - Updated README from master HTML file +=============================================================================== +Changes for patch v206 + +- Added support for multiple Compaq cpqarray controllers + +- Fixed (rare, old) race in diff -urN linux-2.5.2-pre11/Documentation/networking/ip-sysctl.txt linux/Documentation/networking/ip-sysctl.txt --- linux-2.5.2-pre11/Documentation/networking/ip-sysctl.txt Wed May 16 10:21:45 2001 +++ linux/Documentation/networking/ip-sysctl.txt Mon Jan 14 18:28:27 2002 @@ -309,13 +309,20 @@ ICMP ECHO requests sent to it or just those to broadcast/multicast addresses, respectively. -icmp_destunreach_rate - INTEGER -icmp_paramprob_rate - INTEGER -icmp_timeexceed_rate - INTEGER -icmp_echoreply_rate - INTEGER (not enabled per default) - Limit the maximal rates for sending ICMP packets to specific targets. +icmp_ratelimit - INTEGER + Limit the maximal rates for sending ICMP packets whose type matches + icmp_ratemask (see below) to specific targets. 0 to disable any limiting, otherwise the maximal rate in jiffies(1) - See the source for more information. + Default: 1 + +icmp_ratemask - INTEGER + Mask made of ICMP types for which rates are being limited. + Default: 6168 + Note: 6168 = 0x1818 = 1< System.map diff -urN linux-2.5.2-pre11/arch/alpha/config.in linux/arch/alpha/config.in --- linux-2.5.2-pre11/arch/alpha/config.in Tue Nov 20 15:49:31 2001 +++ linux/arch/alpha/config.in Mon Jan 14 18:28:27 2002 @@ -393,3 +393,5 @@ fi endmenu + +source lib/Config.in diff -urN linux-2.5.2-pre11/arch/arm/config.in linux/arch/arm/config.in --- linux-2.5.2-pre11/arch/arm/config.in Mon Jan 14 18:28:21 2002 +++ linux/arch/arm/config.in Mon Jan 14 18:28:27 2002 @@ -709,3 +709,5 @@ dep_bool ' Kernel low-level debugging messages via UART2' CONFIG_DEBUG_CLPS711X_UART2 $CONFIG_DEBUG_LL $CONFIG_ARCH_CLPS711X dep_bool ' Kernel low-level debugging messages via SA1100 Ser3 (otherwise Ser1)' CONFIG_DEBUG_LL_SER3 $CONFIG_DEBUG_LL $CONFIG_ARCH_SA1100 endmenu + +source lib/Config.in diff -urN linux-2.5.2-pre11/arch/cris/config.in linux/arch/cris/config.in --- linux-2.5.2-pre11/arch/cris/config.in Mon Oct 15 13:42:14 2001 +++ linux/arch/cris/config.in Mon Jan 14 18:28:27 2002 @@ -251,3 +251,5 @@ int ' Profile shift count' CONFIG_PROFILE_SHIFT 2 fi endmenu + +source lib/Config.in diff -urN linux-2.5.2-pre11/arch/i386/config.in linux/arch/i386/config.in --- linux-2.5.2-pre11/arch/i386/config.in Mon Jan 14 18:28:22 2002 +++ linux/arch/i386/config.in Mon Jan 14 18:28:27 2002 @@ -419,3 +419,5 @@ fi endmenu + +source lib/Config.in diff -urN linux-2.5.2-pre11/arch/i386/defconfig linux/arch/i386/defconfig --- linux-2.5.2-pre11/arch/i386/defconfig Mon Jan 14 18:28:22 2002 +++ linux/arch/i386/defconfig Mon Jan 14 18:28:27 2002 @@ -130,6 +130,7 @@ # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_CISS_SCSI_TAPE is not set # CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set @@ -831,3 +832,8 @@ # Kernel hacking # # CONFIG_DEBUG_KERNEL is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -urN linux-2.5.2-pre11/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c --- linux-2.5.2-pre11/arch/i386/kernel/setup.c Mon Jan 14 18:28:22 2002 +++ linux/arch/i386/kernel/setup.c Mon Jan 14 18:28:27 2002 @@ -748,6 +748,7 @@ printk(KERN_WARNING "Use a PAE enabled kernel.\n"); else printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n"); + max_pfn = MAXMEM_PFN; #else /* !CONFIG_HIGHMEM */ #ifndef CONFIG_X86_PAE if (max_pfn > MAX_NONPAE_PFN) { diff -urN linux-2.5.2-pre11/arch/ia64/config.in linux/arch/ia64/config.in --- linux-2.5.2-pre11/arch/ia64/config.in Fri Nov 9 14:26:17 2001 +++ linux/arch/ia64/config.in Mon Jan 14 18:28:27 2002 @@ -234,6 +234,8 @@ source drivers/usb/Config.in +source lib/Config.in + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then source net/bluetooth/Config.in fi diff -urN linux-2.5.2-pre11/arch/m68k/config.in linux/arch/m68k/config.in --- linux-2.5.2-pre11/arch/m68k/config.in Mon Jun 11 19:15:27 2001 +++ linux/arch/m68k/config.in Mon Jan 14 18:28:27 2002 @@ -546,3 +546,5 @@ #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ endmenu + +source lib/Config.in diff -urN linux-2.5.2-pre11/arch/mips/config.in linux/arch/mips/config.in --- linux-2.5.2-pre11/arch/mips/config.in Mon Oct 15 13:41:34 2001 +++ linux/arch/mips/config.in Mon Jan 14 18:28:27 2002 @@ -520,3 +520,5 @@ bool 'Run uncached' CONFIG_MIPS_UNCACHED fi endmenu + +source lib/Config.in diff -urN linux-2.5.2-pre11/arch/mips64/config.in linux/arch/mips64/config.in --- linux-2.5.2-pre11/arch/mips64/config.in Sun Sep 9 10:43:02 2001 +++ linux/arch/mips64/config.in Mon Jan 14 18:28:28 2002 @@ -276,3 +276,5 @@ bool 'Run uncached' CONFIG_MIPS_UNCACHED fi endmenu + +source lib/Config.in diff -urN linux-2.5.2-pre11/arch/parisc/config.in linux/arch/parisc/config.in --- linux-2.5.2-pre11/arch/parisc/config.in Tue Apr 17 17:19:25 2001 +++ linux/arch/parisc/config.in Mon Jan 14 18:28:28 2002 @@ -208,3 +208,4 @@ bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ endmenu +source lib/Config.in diff -urN linux-2.5.2-pre11/arch/ppc/config.in linux/arch/ppc/config.in --- linux-2.5.2-pre11/arch/ppc/config.in Fri Nov 16 10:10:08 2001 +++ linux/arch/ppc/config.in Mon Jan 14 18:28:28 2002 @@ -393,3 +393,5 @@ bool 'Include kgdb kernel debugger' CONFIG_KGDB bool 'Include xmon kernel debugger' CONFIG_XMON endmenu + +source lib/Config.in diff -urN linux-2.5.2-pre11/arch/s390/config.in linux/arch/s390/config.in --- linux-2.5.2-pre11/arch/s390/config.in Fri Nov 9 13:58:02 2001 +++ linux/arch/s390/config.in Mon Jan 14 18:28:28 2002 @@ -73,3 +73,4 @@ bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ endmenu +source lib/Config.in diff -urN linux-2.5.2-pre11/arch/s390x/config.in linux/arch/s390x/config.in --- linux-2.5.2-pre11/arch/s390x/config.in Thu Oct 11 09:04:57 2001 +++ linux/arch/s390x/config.in Mon Jan 14 18:28:28 2002 @@ -77,3 +77,4 @@ bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ endmenu +source lib/Config.in diff -urN linux-2.5.2-pre11/arch/sh/config.in linux/arch/sh/config.in --- linux-2.5.2-pre11/arch/sh/config.in Tue Dec 11 10:10:18 2001 +++ linux/arch/sh/config.in Mon Jan 14 18:28:28 2002 @@ -386,3 +386,5 @@ bool 'Early printk support' CONFIG_SH_EARLY_PRINTK fi endmenu + +source lib/Config.in diff -urN linux-2.5.2-pre11/arch/sparc/config.in linux/arch/sparc/config.in --- linux-2.5.2-pre11/arch/sparc/config.in Mon Jun 11 19:15:27 2001 +++ linux/arch/sparc/config.in Mon Jan 14 18:28:28 2002 @@ -266,3 +266,5 @@ bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ endmenu + +source lib/Config.in diff -urN linux-2.5.2-pre11/arch/sparc/kernel/check_asm.sh linux/arch/sparc/kernel/check_asm.sh --- linux-2.5.2-pre11/arch/sparc/kernel/check_asm.sh Tue Oct 30 15:08:11 2001 +++ linux/arch/sparc/kernel/check_asm.sh Mon Jan 14 18:28:28 2002 @@ -1,12 +1,12 @@ #!/bin/sh case $1 in -printf) - sed -n -e '/struct[ ]*'$2'_struct[ ]*{/,/};/p' < $3 | sed '/struct[ ]*'$2'_struct[ ]*{/d;/:[0-9]*[ ]*;/d;/^[ ]*$/d;/};/d;s/^[ ]*//;s/volatile[ ]*//;s/\(unsigned\|signed\|struct\)[ ]*//;s/\(\[\|__attribute__\).*;[ ]*$//;s/(\*//;s/)(.*)//;s/;[ ]*$//;s/^[^ ]*[ ]*//;s/,/\ + sed -n -e '/^#/d;/struct[ ]*'$2'_struct[ ]*{/,/};/p' < $3 | sed '/struct[ ]*'$2'_struct[ ]*{/d;/:[0-9]*[ ]*;/d;/^[ ]*$/d;/};/d;s/^[ ]*//;s/volatile[ ]*//;s/\(unsigned\|signed\|struct\)[ ]*//;s/\(\[\|__attribute__\).*;[ ]*$//;s/(\*//;s/)(.*)//;s/;[ ]*$//;s/^[^ ]*[ ]*//;s/,/\ /g' | sed 's/^[ *]*//;s/[ ]*$//;s/^.*$/printf ("#define AOFF_'$2'_\0 0x%08x\\n", check_asm_data[i++]); printf("#define ASIZ_'$2'_\0 0x%08x\\n", check_asm_data[i++]);/' >> $4 echo "printf (\"#define ASIZ_$2\\t0x%08x\\n\", check_asm_data[i++]);" >> $4 ;; -data) - sed -n -e '/struct[ ]*'$2'_struct[ ]*{/,/};/p' < $3 | sed '/struct[ ]*'$2'_struct[ ]*{/d;/:[0-9]*[ ]*;/d;/^[ ]*$/d;/};/d;s/^[ ]*//;s/volatile[ ]*//;s/\(unsigned\|signed\|struct\)[ ]*//;s/\(\[\|__attribute__\).*;[ ]*$//;s/(\*//;s/)(.*)//;s/;[ ]*$//;s/^[^ ]*[ ]*//;s/,/\ + sed -n -e '/^#/d;/struct[ ]*'$2'_struct[ ]*{/,/};/p' < $3 | sed '/struct[ ]*'$2'_struct[ ]*{/d;/:[0-9]*[ ]*;/d;/^[ ]*$/d;/};/d;s/^[ ]*//;s/volatile[ ]*//;s/\(unsigned\|signed\|struct\)[ ]*//;s/\(\[\|__attribute__\).*;[ ]*$//;s/(\*//;s/)(.*)//;s/;[ ]*$//;s/^[^ ]*[ ]*//;s/,/\ /g' | sed 's/^[ *]*//;s/[ ]*$//;s/^.*$/ ((char *)\&((struct '$2'_struct *)0)->\0) - ((char *)((struct '$2'_struct *)0)), sizeof(((struct '$2'_struct *)0)->\0),/' >> $4 echo " sizeof(struct $2_struct)," >> $4 ;; diff -urN linux-2.5.2-pre11/arch/sparc/kernel/devices.c linux/arch/sparc/kernel/devices.c --- linux-2.5.2-pre11/arch/sparc/kernel/devices.c Tue Aug 31 11:23:29 1999 +++ linux/arch/sparc/kernel/devices.c Mon Jan 14 18:28:28 2002 @@ -4,9 +4,10 @@ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) */ +#include #include #include -#include +#include #include #include diff -urN linux-2.5.2-pre11/arch/sparc/kernel/ebus.c linux/arch/sparc/kernel/ebus.c --- linux-2.5.2-pre11/arch/sparc/kernel/ebus.c Tue Nov 13 09:16:05 2001 +++ linux/arch/sparc/kernel/ebus.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: ebus.c,v 1.18 2001/11/08 04:41:33 davem Exp $ +/* $Id: ebus.c,v 1.20 2002/01/05 01:13:43 davem Exp $ * ebus.c: PCI to EBus bridge device. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) diff -urN linux-2.5.2-pre11/arch/sparc/kernel/init_task.c linux/arch/sparc/kernel/init_task.c --- linux-2.5.2-pre11/arch/sparc/kernel/init_task.c Mon Sep 17 15:29:09 2001 +++ linux/arch/sparc/kernel/init_task.c Mon Jan 14 18:28:28 2002 @@ -14,6 +14,6 @@ * If this is not aligned on a 8k boundry, then you should change code * in etrap.S which assumes it. */ -union task_union init_task_union - __attribute__((__section__(".text"))) = +__asm__(".section \".text\",#alloc\n"); +union task_union init_task_union = { INIT_TASK(init_task_union.task) }; diff -urN linux-2.5.2-pre11/arch/sparc/kernel/irq.c linux/arch/sparc/kernel/irq.c --- linux-2.5.2-pre11/arch/sparc/kernel/irq.c Wed Nov 28 13:22:26 2001 +++ linux/arch/sparc/kernel/irq.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.113 2001/07/17 16:17:33 anton Exp $ +/* $Id: irq.c,v 1.114 2001/12/11 04:55:51 davem Exp $ * arch/sparc/kernel/irq.c: Interrupt request handling routines. On the * Sparc the IRQ's are basically 'cast in stone' * and you are supposed to probe the prom's device diff -urN linux-2.5.2-pre11/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c --- linux-2.5.2-pre11/arch/sparc/kernel/process.c Mon Jan 14 18:28:22 2002 +++ linux/arch/sparc/kernel/process.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.157 2001/11/13 00:57:05 davem Exp $ +/* $Id: process.c,v 1.160 2002/01/11 08:45:38 davem Exp $ * linux/arch/sparc/kernel/process.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -60,9 +60,6 @@ goto out; /* endless idle loop with no priority at all */ - current->nice = 20; - init_idle(); - for (;;) { if (ARCH_SUN4C_SUN4) { static int count = HZ; @@ -108,9 +105,6 @@ int cpu_idle(void) { /* endless idle loop with no priority at all */ - current->nice = 20; - init_idle(); - while(1) { if(current->need_resched) { schedule(); @@ -283,37 +277,29 @@ show_regwindow((struct reg_window *)regs->u_regs[14]); } -#if NOTUSED -void show_thread(struct thread_struct *thread) +void show_trace_task(struct task_struct *tsk) { - int i; - - printk("uwinmask: 0x%08lx kregs: 0x%08lx\n", thread->uwinmask, (unsigned long)thread->kregs); - show_regs(thread->kregs); - printk("ksp: 0x%08lx kpc: 0x%08lx\n", thread->ksp, thread->kpc); - printk("kpsr: 0x%08lx kwim: 0x%08lx\n", thread->kpsr, thread->kwim); - printk("fork_kpsr: 0x%08lx fork_kwim: 0x%08lx\n", thread->fork_kpsr, thread->fork_kwim); - - for (i = 0; i < NSWINS; i++) { - if (!thread->rwbuf_stkptrs[i]) - continue; - printk("reg_window[%d]:\n", i); - printk("stack ptr: 0x%08lx\n", thread->rwbuf_stkptrs[i]); - show_regwindow(&thread->reg_window[i]); - } - printk("w_saved: 0x%08lx\n", thread->w_saved); - - /* XXX missing: float_regs */ - printk("fsr: 0x%08lx fpqdepth: 0x%08lx\n", thread->fsr, thread->fpqdepth); - /* XXX missing: fpqueue */ + unsigned long pc, fp; + unsigned long task_base = (unsigned long) tsk; + struct reg_window *rw; + int count = 0; - printk("flags: 0x%08lx current_ds: 0x%08lx\n", thread->flags, thread->current_ds.seg); - - show_regwindow((struct reg_window *)thread->ksp); + if (!tsk) + return; - /* XXX missing: core_exec */ + fp = tsk->thread.ksp; + do { + /* Bogus frame pointer? */ + if (fp < (task_base + sizeof(struct task_struct)) || + fp >= (task_base + (PAGE_SIZE << 1))) + break; + rw = (struct reg_window *) fp; + pc = rw->ins[7]; + printk("[%08lx] ", pc); + fp = rw->ins[6]; + } while (++count < 16); + printk("\n"); } -#endif /* * Free current thread data structures etc.. diff -urN linux-2.5.2-pre11/arch/sparc/kernel/signal.c linux/arch/sparc/kernel/signal.c --- linux-2.5.2-pre11/arch/sparc/kernel/signal.c Wed Jan 24 15:18:06 2001 +++ linux/arch/sparc/kernel/signal.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.108 2001/01/24 21:05:12 davem Exp $ +/* $Id: signal.c,v 1.109 2001/12/21 01:22:31 davem Exp $ * linux/arch/sparc/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -16,6 +16,7 @@ #include #include #include +#include #include #include diff -urN linux-2.5.2-pre11/arch/sparc/kernel/sun4d_irq.c linux/arch/sparc/kernel/sun4d_irq.c --- linux-2.5.2-pre11/arch/sparc/kernel/sun4d_irq.c Wed Nov 28 13:22:26 2001 +++ linux/arch/sparc/kernel/sun4d_irq.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: sun4d_irq.c,v 1.28 2001/07/17 16:17:33 anton Exp $ +/* $Id: sun4d_irq.c,v 1.29 2001/12/11 04:55:51 davem Exp $ * arch/sparc/kernel/sun4d_irq.c: * SS1000/SC2000 interrupt handling. * diff -urN linux-2.5.2-pre11/arch/sparc/kernel/sun4d_smp.c linux/arch/sparc/kernel/sun4d_smp.c --- linux-2.5.2-pre11/arch/sparc/kernel/sun4d_smp.c Wed Nov 21 10:31:09 2001 +++ linux/arch/sparc/kernel/sun4d_smp.c Mon Jan 14 18:28:28 2002 @@ -127,7 +127,7 @@ while((unsigned long)current_set[cpuid] < PAGE_OFFSET) barrier(); - while(current_set[cpuid]->processor != cpuid) + while(current_set[cpuid]->cpu != cpuid) barrier(); /* Fix idle thread fields. */ @@ -197,10 +197,9 @@ mid_xlate[i] = i; __cpu_number_map[boot_cpu_id] = 0; __cpu_logical_map[0] = boot_cpu_id; - current->processor = boot_cpu_id; + current->cpu = boot_cpu_id; smp_store_cpu_info(boot_cpu_id); smp_setup_percpu_timer(); - init_idle(); local_flush_cache_all(); if(linux_num_cpus == 1) return; /* Not an MP box. */ @@ -222,14 +221,11 @@ cpucount++; p = init_task.prev_task; - init_tasks[i] = p; - p->processor = i; - p->cpus_runnable = 1 << i; /* we schedule the first task manually */ + p->cpu = i; current_set[i] = p; - del_from_runqueue(p); unhash_process(p); for (no = 0; no < linux_num_cpus; no++) diff -urN linux-2.5.2-pre11/arch/sparc/kernel/sun4m_smp.c linux/arch/sparc/kernel/sun4m_smp.c --- linux-2.5.2-pre11/arch/sparc/kernel/sun4m_smp.c Wed Nov 21 10:31:09 2001 +++ linux/arch/sparc/kernel/sun4m_smp.c Mon Jan 14 18:28:28 2002 @@ -170,12 +170,11 @@ mid_xlate[boot_cpu_id] = (linux_cpus[boot_cpu_id].mid & ~8); __cpu_number_map[boot_cpu_id] = 0; __cpu_logical_map[0] = boot_cpu_id; - current->processor = boot_cpu_id; + current->cpu = boot_cpu_id; smp_store_cpu_info(boot_cpu_id); set_irq_udt(mid_xlate[boot_cpu_id]); smp_setup_percpu_timer(); - init_idle(); local_flush_cache_all(); if(linux_num_cpus == 1) return; /* Not an MP box. */ @@ -195,14 +194,11 @@ cpucount++; p = init_task.prev_task; - init_tasks[i] = p; - p->processor = i; - p->cpus_runnable = 1 << i; /* we schedule the first task manually */ + p->cpu = i; current_set[i] = p; - del_from_runqueue(p); unhash_process(p); /* See trampoline.S for details... */ diff -urN linux-2.5.2-pre11/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c --- linux-2.5.2-pre11/arch/sparc/kernel/sys_sunos.c Tue Aug 14 19:57:28 2001 +++ linux/arch/sparc/kernel/sys_sunos.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: sys_sunos.c,v 1.135 2001/08/13 14:40:10 davem Exp $ +/* $Id: sys_sunos.c,v 1.136 2002/01/08 16:00:14 davem Exp $ * sys_sunos.c: SunOS specific syscall compatibility support. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -90,8 +90,8 @@ * SunOS is so stupid some times... hmph! */ if (file) { - if(MAJOR(file->f_dentry->d_inode->i_rdev) == MEM_MAJOR && - MINOR(file->f_dentry->d_inode->i_rdev) == 5) { + if(major(file->f_dentry->d_inode->i_rdev) == MEM_MAJOR && + minor(file->f_dentry->d_inode->i_rdev) == 5) { flags |= MAP_ANONYMOUS; fput(file); file = 0; diff -urN linux-2.5.2-pre11/arch/sparc/kernel/trampoline.S linux/arch/sparc/kernel/trampoline.S --- linux-2.5.2-pre11/arch/sparc/kernel/trampoline.S Wed Aug 4 16:36:41 1999 +++ linux/arch/sparc/kernel/trampoline.S Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: trampoline.S,v 1.13 1999/08/04 03:19:15 davem Exp $ +/* $Id: trampoline.S,v 1.14 2002/01/11 08:45:38 davem Exp $ * trampoline.S: SMP cpu boot-up trampoline code. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -88,6 +88,8 @@ .align 4 smp_do_cpu_idle: + call C_LABEL(init_idle) + nop call C_LABEL(cpu_idle) mov 0, %o0 diff -urN linux-2.5.2-pre11/arch/sparc/kernel/unaligned.c linux/arch/sparc/kernel/unaligned.c --- linux-2.5.2-pre11/arch/sparc/kernel/unaligned.c Wed May 3 01:47:57 2000 +++ linux/arch/sparc/kernel/unaligned.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: unaligned.c,v 1.22 2000/04/29 08:05:21 anton Exp $ +/* $Id: unaligned.c,v 1.23 2001/12/21 00:54:31 davem Exp $ * unaligned.c: Unaligned load/store trap handling with special * cases for the kernel to do them more quickly. * @@ -224,7 +224,7 @@ "or %%l1, %%g7, %%g7\n\t" \ "st %%g7, [%0 + 4]\n" \ "0:\n\n\t" \ - ".section __ex_table\n\t" \ + ".section __ex_table,#alloc\n\t" \ ".word 4b, " #errh "\n\t" \ ".word 5b, " #errh "\n\t" \ ".word 6b, " #errh "\n\t" \ @@ -277,7 +277,7 @@ "16:\t" "stb %%l2, [%0]\n" \ "17:\t" "stb %%l1, [%0 + 1]\n" \ "0:\n\n\t" \ - ".section __ex_table\n\t" \ + ".section __ex_table,#alloc\n\t" \ ".word 4b, " #errh "\n\t" \ ".word 5b, " #errh "\n\t" \ ".word 6b, " #errh "\n\t" \ diff -urN linux-2.5.2-pre11/arch/sparc/mm/extable.c linux/arch/sparc/mm/extable.c --- linux-2.5.2-pre11/arch/sparc/mm/extable.c Sun Aug 12 11:23:32 2001 +++ linux/arch/sparc/mm/extable.c Mon Jan 14 18:28:28 2002 @@ -11,35 +11,49 @@ static unsigned long search_one_table(const struct exception_table_entry *start, - const struct exception_table_entry *last, + const struct exception_table_entry *end, unsigned long value, unsigned long *g2) { - const struct exception_table_entry *first = start; - const struct exception_table_entry *mid; - long diff = 0; - while (first <= last) { - mid = (last - first) / 2 + first; - diff = mid->insn - value; - if (diff == 0) { - if (!mid->fixup) { - *g2 = 0; - return (mid + 1)->fixup; - } else - return mid->fixup; - } else if (diff < 0) - first = mid+1; - else - last = mid-1; - } - if (last->insn < value && !last->fixup && last[1].insn > value) { - *g2 = (value - last->insn)/4; - return last[1].fixup; - } - if (first > start && first[-1].insn < value - && !first[-1].fixup && first->insn < value) { - *g2 = (value - first[-1].insn)/4; - return first->fixup; - } + const struct exception_table_entry *walk; + + /* Single insn entries are encoded as: + * word 1: insn address + * word 2: fixup code address + * + * Range entries are encoded as: + * word 1: first insn address + * word 2: 0 + * word 3: last insn address + 4 bytes + * word 4: fixup code address + * + * See asm/uaccess.h for more details. + */ + + /* 1. Try to find an exact match. */ + for (walk = start; walk <= end; walk++) { + if (walk->fixup == 0) { + /* A range entry, skip both parts. */ + walk++; + continue; + } + + if (walk->insn == value) + return walk->fixup; + } + + /* 2. Try to find a range match. */ + for (walk = start; walk <= (end - 1); walk++) { + if (walk->fixup) + continue; + + if (walk[0].insn <= value && + walk[1].insn > value) { + *g2 = (value - walk[0].insn) / 4; + return walk[1].fixup; + } + walk++; + } + return 0; } diff -urN linux-2.5.2-pre11/arch/sparc/mm/fault.c linux/arch/sparc/mm/fault.c --- linux-2.5.2-pre11/arch/sparc/mm/fault.c Tue Oct 30 15:08:11 2001 +++ linux/arch/sparc/mm/fault.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: fault.c,v 1.121 2001/10/30 04:54:22 davem Exp $ +/* $Id: fault.c,v 1.122 2001/11/17 07:19:26 davem Exp $ * fault.c: Page fault handlers for the Sparc. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -155,34 +155,47 @@ asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc, unsigned long address) { + struct pt_regs regs; unsigned long g2; + unsigned int insn; int i; - unsigned insn; - struct pt_regs regs; - i = search_exception_table (ret_pc, &g2); + i = search_exception_table(ret_pc, &g2); switch (i) { - /* load & store will be handled by fixup */ - case 3: return 3; - /* store will be handled by fixup, load will bump out */ - /* for _to_ macros */ - case 1: insn = (unsigned)pc; if ((insn >> 21) & 1) return 1; break; - /* load will be handled by fixup, store will bump out */ - /* for _from_ macros */ - case 2: insn = (unsigned)pc; - if (!((insn >> 21) & 1) || ((insn>>19)&0x3f) == 15) return 2; + case 3: + /* load & store will be handled by fixup */ + return 3; + + case 1: + /* store will be handled by fixup, load will bump out */ + /* for _to_ macros */ + insn = *((unsigned int *) pc); + if ((insn >> 21) & 1) + return 1; + break; + + case 2: + /* load will be handled by fixup, store will bump out */ + /* for _from_ macros */ + insn = *((unsigned int *) pc); + if (!((insn >> 21) & 1) || ((insn>>19)&0x3f) == 15) + return 2; break; - default: break; - } - memset (®s, 0, sizeof (regs)); + + default: + break; + }; + + memset(®s, 0, sizeof (regs)); regs.pc = pc; regs.npc = pc + 4; - __asm__ __volatile__ ( + __asm__ __volatile__( "rd %%psr, %0\n\t" "nop\n\t" "nop\n\t" "nop\n" : "=r" (regs.psr)); - unhandled_fault (address, current, ®s); + unhandled_fault(address, current, ®s); + /* Not reached */ return 0; } diff -urN linux-2.5.2-pre11/arch/sparc/mm/init.c linux/arch/sparc/mm/init.c --- linux-2.5.2-pre11/arch/sparc/mm/init.c Mon Oct 1 09:19:56 2001 +++ linux/arch/sparc/mm/init.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.100 2001/09/21 22:51:47 davem Exp $ +/* $Id: init.c,v 1.103 2001/11/19 19:03:08 davem Exp $ * linux/arch/sparc/mm/init.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -410,9 +410,6 @@ int datapages = 0; int initpages = 0; int i; -#ifdef CONFIG_BLK_DEV_INITRD - unsigned long addr, last; -#endif highmem_start_page = mem_map + highstart_pfn; diff -urN linux-2.5.2-pre11/arch/sparc/mm/io-unit.c linux/arch/sparc/mm/io-unit.c --- linux-2.5.2-pre11/arch/sparc/mm/io-unit.c Sun Feb 18 19:49:54 2001 +++ linux/arch/sparc/mm/io-unit.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: io-unit.c,v 1.23 2001/02/13 01:16:43 davem Exp $ +/* $Id: io-unit.c,v 1.24 2001/12/17 07:05:09 davem Exp $ * io-unit.c: IO-UNIT specific routines for memory management. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -131,7 +131,7 @@ /* FIXME: Cache some resolved pages - often several sg entries are to the same page */ spin_lock_irqsave(&iounit->lock, flags); for (; sz >= 0; sz--) { - sg[sz].dvma_address = iounit_get_area(iounit, (unsigned long)sg[sz].address, sg[sz].length); + sg[sz].dvma_address = iounit_get_area(iounit, (unsigned long)page_address(sg[sz].page) + sg[sz].offset, sg[sz].length); sg[sz].dvma_length = sg[sz].length; } spin_unlock_irqrestore(&iounit->lock, flags); diff -urN linux-2.5.2-pre11/arch/sparc/mm/iommu.c linux/arch/sparc/mm/iommu.c --- linux-2.5.2-pre11/arch/sparc/mm/iommu.c Sun Feb 18 19:49:54 2001 +++ linux/arch/sparc/mm/iommu.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: iommu.c,v 1.21 2001/02/13 01:16:43 davem Exp $ +/* $Id: iommu.c,v 1.22 2001/12/17 07:05:09 davem Exp $ * iommu.c: IOMMU specific routines for memory management. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -168,7 +168,7 @@ static void iommu_get_scsi_sgl_noflush(struct scatterlist *sg, int sz, struct sbus_bus *sbus) { for (; sz >= 0; sz--) { - sg[sz].dvma_address = (__u32) (sg[sz].address); + sg[sz].dvma_address = (__u32) (page_address(sg[sz].page) + sg[sz].offset); sg[sz].dvma_length = (__u32) (sg[sz].length); } } @@ -177,7 +177,7 @@ { flush_page_for_dma(0); for (; sz >= 0; sz--) { - sg[sz].dvma_address = (__u32) (sg[sz].address); + sg[sz].dvma_address = (__u32) (page_address(sg[sz].page) + sg[sz].offset); sg[sz].dvma_length = (__u32) (sg[sz].length); } } @@ -187,14 +187,14 @@ unsigned long page, oldpage = 0; while(sz >= 0) { - page = ((unsigned long) sg[sz].address) & PAGE_MASK; + page = ((unsigned long) sg[sz].offset) & PAGE_MASK; if (oldpage == page) page += PAGE_SIZE; /* We flushed that page already */ - while(page < (unsigned long)(sg[sz].address + sg[sz].length)) { + while(page < (unsigned long)(page_address(sg[sz].page) + sg[sz].offset + sg[sz].length)) { flush_page_for_dma(page); page += PAGE_SIZE; } - sg[sz].dvma_address = (__u32) (sg[sz].address); + sg[sz].dvma_address = (__u32) (page_address(sg[sz].page) + sg[sz].offset); sg[sz].dvma_length = (__u32) (sg[sz].length); sz--; oldpage = page - PAGE_SIZE; diff -urN linux-2.5.2-pre11/arch/sparc/prom/ranges.c linux/arch/sparc/prom/ranges.c --- linux-2.5.2-pre11/arch/sparc/prom/ranges.c Mon Dec 20 22:05:52 1999 +++ linux/arch/sparc/prom/ranges.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: ranges.c,v 1.14 1999/10/06 19:28:54 zaitcev Exp $ +/* $Id: ranges.c,v 1.15 2001/12/19 00:29:51 davem Exp $ * ranges.c: Handle ranges in newer proms for obio/sbus. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -16,26 +16,25 @@ int num_obio_ranges; /* Adjust register values based upon the ranges parameters. */ -void +static void prom_adjust_regs(struct linux_prom_registers *regp, int nregs, struct linux_prom_ranges *rangep, int nranges) { int regc, rngc; - for(regc=0; regc < nregs; regc++) { - for(rngc=0; rngc < nranges; rngc++) - if(regp[regc].which_io == rangep[rngc].ot_child_space && - regp[regc].phys_addr >= rangep[rngc].ot_child_base && - regp[regc].phys_addr + regp[regc].reg_size <= rangep[rngc].ot_child_base + rangep[rngc].or_size) + for (regc = 0; regc < nregs; regc++) { + for (rngc = 0; rngc < nranges; rngc++) + if (regp[regc].which_io == rangep[rngc].ot_child_space) break; /* Fount it */ - if(rngc==nranges) /* oops */ + if (rngc == nranges) /* oops */ prom_printf("adjust_regs: Could not find range with matching bus type...\n"); regp[regc].which_io = rangep[rngc].ot_parent_space; + regp[regc].phys_addr -= rangep[rngc].ot_child_base; regp[regc].phys_addr += rangep[rngc].ot_parent_base; } } -void +static void prom_adjust_ranges(struct linux_prom_ranges *ranges1, int nranges1, struct linux_prom_ranges *ranges2, int nranges2) { diff -urN linux-2.5.2-pre11/arch/sparc64/Makefile linux/arch/sparc64/Makefile --- linux-2.5.2-pre11/arch/sparc64/Makefile Sun Oct 21 10:36:54 2001 +++ linux/arch/sparc64/Makefile Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.49 2001/10/17 18:26:58 davem Exp $ +# $Id: Makefile,v 1.51 2001/11/17 00:15:27 davem Exp $ # sparc64/Makefile # # Makefile for the architecture dependent flags and dependencies on the @@ -38,11 +38,6 @@ AS := $(AS) --undeclared-regs endif -# -# Uncomment the first CFLAGS if you are doing kgdb source level -# debugging of the kernel to get the proper debugging information. - -#CFLAGS := $(CFLAGS) -g -pipe -fcall-used-g5 -fcall-used-g7 ifneq ($(NEW_GCC),y) CFLAGS := $(CFLAGS) -pipe -mno-fpu -mtune=ultrasparc -mmedlow \ -ffixed-g4 -fcall-used-g5 -fcall-used-g7 -Wno-sign-compare @@ -51,25 +46,6 @@ -ffixed-g4 -fcall-used-g5 -fcall-used-g7 -Wno-sign-compare \ $(CC_UNDECL) AFLAGS += -m64 -mcpu=ultrasparc $(CC_UNDECL) -endif - -# Uncomment this to get spinlock/rwlock debugging on SMP. -# DEBUG_SPINLOCK = 1 - -ifdef CONFIG_SMP - ifdef DEBUG_SPINLOCK - CFLAGS += -DSPIN_LOCK_DEBUG - AFLAGS += -DSPIN_LOCK_DEBUG - endif -endif - -# Uncomment this to keep track of how often flush_dcache_page -# actually flushes the caches, output via /proc/cpuinfo -# -# DEBUG_DCACHE_FLUSH = 1 -ifdef DEBUG_DCACHE_FLUSH - CFLAGS += -DDCFLUSH_DEBUG - AFLAGS += -DDCFLUSH_DEBUG endif LINKFLAGS = -T arch/sparc64/vmlinux.lds diff -urN linux-2.5.2-pre11/arch/sparc64/config.in linux/arch/sparc64/config.in --- linux-2.5.2-pre11/arch/sparc64/config.in Tue Nov 13 09:16:05 2001 +++ linux/arch/sparc64/config.in Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.152 2001/11/12 10:20:47 davem Exp $ +# $Id: config.in,v 1.156 2001/11/30 00:17:32 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -31,6 +31,8 @@ # Identify this as a Sparc64 build define_bool CONFIG_SPARC64 y +bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG + # Global things across all Sun machines. define_bool CONFIG_HAVE_DEC_LOCK y define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n @@ -89,7 +91,6 @@ mainmenu_option next_comment comment 'Console drivers' bool 'PROM console' CONFIG_PROM_CONSOLE -bool 'Support Frame buffer devices' CONFIG_FB source drivers/video/Config.in endmenu @@ -191,21 +192,21 @@ if [ "$CONFIG_SCSI_SYM53C8XX_2" != "y" ]; then dep_tristate 'NCR53C8XX SCSI support' CONFIG_SCSI_NCR53C8XX $CONFIG_SCSI dep_tristate 'SYM53C8XX SCSI support' CONFIG_SCSI_SYM53C8XX $CONFIG_SCSI - fi - if [ "$CONFIG_SCSI_NCR53C8XX" != "n" -o "$CONFIG_SCSI_SYM53C8XX" != "n" ]; then - int 'default tagged command queue depth' CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS 8 - int 'maximum number of queued commands' CONFIG_SCSI_NCR53C8XX_MAX_TAGS 32 - int 'synchronous transfers frequency in MHz' CONFIG_SCSI_NCR53C8XX_SYNC 10 - bool ' enable profiling' CONFIG_SCSI_NCR53C8XX_PROFILE - if [ "$CONFIG_SCSI_SYM53C8XX" != "n" ]; then - bool ' include support for the NCR PQS/PDS SCSI card' CONFIG_SCSI_NCR53C8XX_PQS_PDS + if [ "$CONFIG_SCSI_NCR53C8XX" != "n" -o "$CONFIG_SCSI_SYM53C8XX" != "n" ]; then + int 'default tagged command queue depth' CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS 8 + int 'maximum number of queued commands' CONFIG_SCSI_NCR53C8XX_MAX_TAGS 32 + int 'synchronous transfers frequency in MHz' CONFIG_SCSI_NCR53C8XX_SYNC 10 + bool ' enable profiling' CONFIG_SCSI_NCR53C8XX_PROFILE + if [ "$CONFIG_SCSI_SYM53C8XX" != "n" ]; then + bool ' include support for the NCR PQS/PDS SCSI card' CONFIG_SCSI_NCR53C8XX_PQS_PDS + fi + if [ "$CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS" = "0" ]; then + bool ' not allow targets to disconnect' CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT + fi + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + bool ' assume boards are SYMBIOS compatible (EXPERIMENTAL)' CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT + fi fi - if [ "$CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS" = "0" ]; then - bool ' not allow targets to disconnect' CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT - fi - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - bool ' assume boards are SYMBIOS compatible (EXPERIMENTAL)' CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT - fi fi dep_tristate 'Qlogic ISP SCSI support' CONFIG_SCSI_QLOGIC_ISP $CONFIG_SCSI dep_tristate 'Qlogic ISP FC SCSI support' CONFIG_SCSI_QLOGIC_FC $CONFIG_SCSI @@ -295,6 +296,15 @@ mainmenu_option next_comment comment 'Kernel hacking' -bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ -#bool 'ECache flush trap support at ta 0x72' CONFIG_EC_FLUSH_TRAP +bool 'Kernel debugging' CONFIG_DEBUG_KERNEL +if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then + bool ' Debug memory allocations' CONFIG_DEBUG_SLAB + bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ + bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK + bool ' Verbose BUG() reporting (adds 70K)' CONFIG_DEBUG_BUGVERBOSE + bool ' D-cache flush debugging' CONFIG_DEBUG_DCFLUSH +fi + endmenu + +source lib/Config.in diff -urN linux-2.5.2-pre11/arch/sparc64/defconfig linux/arch/sparc64/defconfig --- linux-2.5.2-pre11/arch/sparc64/defconfig Tue Nov 13 09:16:05 2001 +++ linux/arch/sparc64/defconfig Mon Jan 14 18:28:28 2002 @@ -22,6 +22,7 @@ CONFIG_VT_CONSOLE=y CONFIG_SMP=y CONFIG_SPARC64=y +CONFIG_HOTPLUG=y CONFIG_HAVE_DEC_LOCK=y # CONFIG_RWSEM_GENERIC_SPINLOCK is not set CONFIG_RWSEM_XCHGADD_ALGORITHM=y @@ -84,7 +85,6 @@ # Console drivers # CONFIG_PROM_CONSOLE=y -CONFIG_FB=y # # Frame-buffer support @@ -158,11 +158,11 @@ # # Multi-device support (RAID and LVM) # -# CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set +CONFIG_MD=y +CONFIG_BLK_DEV_MD=m +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m # CONFIG_MD_RAID5 is not set # CONFIG_MD_MULTIPATH is not set # CONFIG_BLK_DEV_LVM is not set @@ -174,8 +174,6 @@ # CONFIG_PACKET=y CONFIG_PACKET_MMAP=y -CONFIG_NETLINK=y -CONFIG_RTNETLINK=y CONFIG_NETLINK_DEV=y # CONFIG_NETFILTER is not set # CONFIG_FILTER is not set @@ -266,8 +264,8 @@ # CONFIG_BLK_DEV_TIVO is not set # CONFIG_BLK_DEV_IDECS is not set CONFIG_BLK_DEV_IDECD=y -CONFIG_BLK_DEV_IDETAPE=m -CONFIG_BLK_DEV_IDEFLOPPY=m +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDESCSI is not set # @@ -313,9 +311,9 @@ # CONFIG_IDEDMA_IVB is not set # CONFIG_DMA_NONPCI is not set CONFIG_BLK_DEV_IDE_MODES=y -CONFIG_BLK_DEV_ATARAID=m -CONFIG_BLK_DEV_ATARAID_PDC=m -CONFIG_BLK_DEV_ATARAID_HPT=m +# CONFIG_BLK_DEV_ATARAID is not set +# CONFIG_BLK_DEV_ATARAID_PDC is not set +# CONFIG_BLK_DEV_ATARAID_HPT is not set # # SCSI support @@ -354,15 +352,11 @@ CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT=y CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE=8 CONFIG_AIC7XXX_OLD_PROC_STATS=y -# CONFIG_SCSI_SYM53C8XX_2 is not set -CONFIG_SCSI_NCR53C8XX=m -CONFIG_SCSI_SYM53C8XX=y -CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=4 -CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 -CONFIG_SCSI_NCR53C8XX_SYNC=40 -# CONFIG_SCSI_NCR53C8XX_PROFILE is not set -# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set -# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set +CONFIG_SCSI_SYM53C8XX_2=y +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set CONFIG_SCSI_QLOGIC_ISP=m CONFIG_SCSI_QLOGIC_FC=y CONFIG_SCSI_QLOGIC_FC_FIRMWARE=y @@ -470,6 +464,7 @@ CONFIG_ADAPTEC_STARFIRE=m # CONFIG_APRICOT is not set # CONFIG_CS89x0 is not set +CONFIG_DE2104X=m CONFIG_TULIP=m # CONFIG_TULIP_MWI is not set # CONFIG_TULIP_MMIO is not set @@ -493,6 +488,7 @@ CONFIG_SUNDANCE=m # CONFIG_TLAN is not set CONFIG_VIA_RHINE=m +# CONFIG_VIA_RHINE_MMIO is not set CONFIG_WINBOND_840=m # CONFIG_NET_POCKET is not set @@ -539,7 +535,7 @@ CONFIG_NET_FC=y # CONFIG_IPHASE5526 is not set # CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set +CONFIG_SHAPER=m # # Wan interfaces @@ -603,7 +599,7 @@ # CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set # CONFIG_TMPFS is not set -CONFIG_RAMFS=m +CONFIG_RAMFS=y CONFIG_ISO9660_FS=m CONFIG_JOLIET=y # CONFIG_ZISOFS is not set @@ -743,8 +739,9 @@ # CONFIG_USB_LONG_TIMEOUT is not set # -# USB Controllers +# USB Host Controller Drivers # +CONFIG_USB_EHCI_HCD=m CONFIG_USB_UHCI=y # CONFIG_USB_UHCI_ALT is not set CONFIG_USB_OHCI=y @@ -789,6 +786,8 @@ CONFIG_USB_OV511=m CONFIG_USB_PWC=m CONFIG_USB_SE401=m +CONFIG_USB_STV680=m +CONFIG_USB_VICAM=m CONFIG_USB_DSBR=m CONFIG_USB_DABUSB=m @@ -817,6 +816,7 @@ CONFIG_USB_SERIAL_EMPEG=m CONFIG_USB_SERIAL_FTDI_SIO=m CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m # CONFIG_USB_SERIAL_IR is not set CONFIG_USB_SERIAL_EDGEPORT=m CONFIG_USB_SERIAL_KEYSPAN_PDA=m @@ -830,6 +830,7 @@ # CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set # CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_KLSI=m CONFIG_USB_SERIAL_PL2303=m CONFIG_USB_SERIAL_CYBERJACK=m CONFIG_USB_SERIAL_XIRCOM=m @@ -839,6 +840,7 @@ # USB Miscellaneous drivers # CONFIG_USB_RIO500=m +CONFIG_USB_AUERSWALD=m # # Bluetooth support @@ -861,4 +863,9 @@ # # Kernel hacking # -# CONFIG_MAGIC_SYSRQ is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SLAB is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_DCFLUSH is not set diff -urN linux-2.5.2-pre11/arch/sparc64/kernel/Makefile linux/arch/sparc64/kernel/Makefile --- linux-2.5.2-pre11/arch/sparc64/kernel/Makefile Wed May 16 10:31:27 2001 +++ linux/arch/sparc64/kernel/Makefile Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.67 2001/05/11 04:31:55 davem Exp $ +# $Id: Makefile,v 1.69 2001/11/19 04:09:53 davem Exp $ # Makefile for the linux kernel. # # Note! Dependencies are done automagically by 'make dep', which also @@ -68,7 +68,7 @@ @echo "#include " > tmp.c @echo "#undef CONFIG_SMP" >> tmp.c @echo "#include " >> tmp.c - $(CPP) $(CPPFLAGS) tmp.c -o tmp.i + $(CPP) $(CPPFLAGS) -P tmp.c -o tmp.i @echo "/* Automatically generated. Do not edit. */" > check_asm_data.c @echo "#include " >> check_asm_data.c @echo "#undef CONFIG_SMP" >> check_asm_data.c @@ -95,12 +95,12 @@ ./check_asm >> asm_offsets.h @rm -f check_asm check_asm.c @echo -e "\n#else /* CONFIG_SMP */\n" >> asm_offsets.h - @echo -e "#ifndef SPIN_LOCK_DEBUG\n" >>asm_offsets.h + @echo -e "#ifndef CONFIG_DEBUG_SPINLOCK\n" >>asm_offsets.h @echo "#include " > tmp.c @echo "#undef CONFIG_SMP" >> tmp.c @echo "#define CONFIG_SMP 1" >> tmp.c @echo "#include " >> tmp.c - $(CPP) $(CPPFLAGS) tmp.c -o tmp.i + $(CPP) $(CPPFLAGS) -P tmp.c -o tmp.i @echo "/* Automatically generated. Do not edit. */" > check_asm_data.c @echo "#include " >> check_asm_data.c @echo "#undef CONFIG_SMP" >> check_asm_data.c @@ -127,9 +127,9 @@ $(HOSTCC) -o check_asm check_asm.c ./check_asm >> asm_offsets.h @rm -f check_asm check_asm.c - @echo -e "\n#else /* SPIN_LOCK_DEBUG */\n" >> asm_offsets.h + @echo -e "\n#else /* CONFIG_DEBUG_SPINLOCK */\n" >> asm_offsets.h @echo "#include " > tmp.c - $(CPP) $(CPPFLAGS) -DSPIN_LOCK_DEBUG tmp.c -o tmp.i + $(CPP) $(CPPFLAGS) -P -DCONFIG_DEBUG_SPINLOCK tmp.c -o tmp.i @echo "/* Automatically generated. Do not edit. */" > check_asm_data.c @echo "#include " >> check_asm_data.c @echo "#undef CONFIG_SMP" >> check_asm_data.c @@ -140,7 +140,7 @@ $(SH) ./check_asm.sh -data mm tmp.i check_asm_data.c $(SH) ./check_asm.sh -data thread tmp.i check_asm_data.c @echo '};' >> check_asm_data.c - $(CC) $(CPPFLAGS) -DSPIN_LOCK_DEBUG $(CMODEL_CFLAG) -ffixed-g4 -S -o check_asm_data.s check_asm_data.c + $(CC) $(CPPFLAGS) -DCONFIG_DEBUG_SPINLOCK $(CMODEL_CFLAG) -ffixed-g4 -S -o check_asm_data.s check_asm_data.c @echo "/* Automatically generated. Do not edit. */" > check_asm.c @echo 'extern int printf(const char *fmt, ...);' >>check_asm.c @echo 'unsigned int check_asm_data[] = {' >> check_asm.c @@ -156,7 +156,7 @@ $(HOSTCC) -o check_asm check_asm.c ./check_asm >> asm_offsets.h @rm -f check_asm check_asm.c - @echo -e "#endif /* SPIN_LOCK_DEBUG */\n" >> asm_offsets.h + @echo -e "#endif /* CONFIG_DEBUG_SPINLOCK */\n" >> asm_offsets.h @echo -e "#endif /* CONFIG_SMP */\n" >> asm_offsets.h @echo "#endif /* __ASM_OFFSETS_H__ */" >> asm_offsets.h @if test -r $(HPATH)/asm/asm_offsets.h; then \ diff -urN linux-2.5.2-pre11/arch/sparc64/kernel/central.c linux/arch/sparc64/kernel/central.c --- linux-2.5.2-pre11/arch/sparc64/kernel/central.c Tue Oct 3 09:24:41 2000 +++ linux/arch/sparc64/kernel/central.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: central.c,v 1.14 2000/09/21 06:25:14 anton Exp $ +/* $Id: central.c,v 1.15 2001/12/19 00:29:51 davem Exp $ * central.c: Central FHC driver for Sunfire/Starfire/Wildfire. * * Copyright (C) 1997, 1999 David S. Miller (davem@redhat.com) @@ -67,6 +67,7 @@ if (rngc == nranges) /* oops */ prom_printf("adjust_regs: Could not find range with matching bus type...\n"); regp[regc].which_io = rangep[rngc].ot_parent_space; + regp[regc].phys_addr -= rangep[rngc].ot_child_base; regp[regc].phys_addr += rangep[rngc].ot_parent_base; } } diff -urN linux-2.5.2-pre11/arch/sparc64/kernel/check_asm.sh linux/arch/sparc64/kernel/check_asm.sh --- linux-2.5.2-pre11/arch/sparc64/kernel/check_asm.sh Thu Apr 26 22:17:25 2001 +++ linux/arch/sparc64/kernel/check_asm.sh Mon Jan 14 18:28:28 2002 @@ -1,12 +1,12 @@ #!/bin/sh case $1 in -printf) - sed -n -e '/struct[ ]*'$2'_struct[ ]*{/,/};/p' < $3 | sed '/struct[ ]*'$2'_struct[ ]*{/d;/:[0-9]*[ ]*;/d;/^[ ]*$/d;/};/d;s/^[ ]*//;s/volatile[ ]*//;s/\(unsigned\|signed\|struct\)[ ]*//;s/\(\[\|__attribute__\).*;[ ]*$//;s/(\*//;s/)(.*)//;s/;[ ]*$//;s/^[^ ]*[ ]*//;s/,/\ + sed -n -e '/^#/d;/struct[ ]*'$2'_struct[ ]*{/,/};/p' < $3 | sed '/struct[ ]*'$2'_struct[ ]*{/d;/:[0-9]*[ ]*;/d;/^[ ]*$/d;/};/d;s/^[ ]*//;s/volatile[ ]*//;s/\(unsigned\|signed\|struct\)[ ]*//;s/\(\[\|__attribute__\).*;[ ]*$//;s/(\*//;s/)(.*)//;s/;[ ]*$//;s/^[^ ]*[ ]*//;s/,/\ /g' | sed 's/^[ *]*//;s/[ ]*$//;s/^.*$/printf ("#define AOFF_'$2'_\0 0x%08x\\n", check_asm_data[i++]); printf("#define ASIZ_'$2'_\0 0x%08x\\n", check_asm_data[i++]);/' >> $4 echo "printf (\"#define ASIZ_$2\\t0x%08x\\n\", check_asm_data[i++]);" >> $4 ;; -data) - sed -n -e '/struct[ ]*'$2'_struct[ ]*{/,/};/p' < $3 | sed '/struct[ ]*'$2'_struct[ ]*{/d;/:[0-9]*[ ]*;/d;/^[ ]*$/d;/};/d;s/^[ ]*//;s/volatile[ ]*//;s/\(unsigned\|signed\|struct\)[ ]*//;s/\(\[\|__attribute__\).*;[ ]*$//;s/(\*//;s/)(.*)//;s/;[ ]*$//;s/^[^ ]*[ ]*//;s/,/\ + sed -n -e '/^#/d;/struct[ ]*'$2'_struct[ ]*{/,/};/p' < $3 | sed '/struct[ ]*'$2'_struct[ ]*{/d;/:[0-9]*[ ]*;/d;/^[ ]*$/d;/};/d;s/^[ ]*//;s/volatile[ ]*//;s/\(unsigned\|signed\|struct\)[ ]*//;s/\(\[\|__attribute__\).*;[ ]*$//;s/(\*//;s/)(.*)//;s/;[ ]*$//;s/^[^ ]*[ ]*//;s/,/\ /g' | sed 's/^[ *]*//;s/[ ]*$//;s/^.*$/ ((char *)\&((struct '$2'_struct *)0)->\0) - ((char *)((struct '$2'_struct *)0)), sizeof(((struct '$2'_struct *)0)->\0),/' >> $4 echo " sizeof(struct $2_struct)," >> $4 ;; diff -urN linux-2.5.2-pre11/arch/sparc64/kernel/chmc.c linux/arch/sparc64/kernel/chmc.c --- linux-2.5.2-pre11/arch/sparc64/kernel/chmc.c Thu Apr 12 12:10:25 2001 +++ linux/arch/sparc64/kernel/chmc.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: chmc.c,v 1.3 2001/04/03 12:49:47 davem Exp $ +/* $Id: chmc.c,v 1.4 2002/01/08 16:00:14 davem Exp $ * memctrlr.c: Driver for UltraSPARC-III memory controller. * * Copyright (C) 2001 David S. Miller (davem@redhat.com) @@ -9,6 +9,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include diff -urN linux-2.5.2-pre11/arch/sparc64/kernel/entry.S linux/arch/sparc64/kernel/entry.S --- linux-2.5.2-pre11/arch/sparc64/kernel/entry.S Sun Oct 21 10:36:54 2001 +++ linux/arch/sparc64/kernel/entry.S Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.137 2001/10/18 09:06:36 davem Exp $ +/* $Id: entry.S,v 1.141 2001/12/05 23:56:32 davem Exp $ * arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points. * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) @@ -483,7 +483,11 @@ ldxa [%g7 + %g0] ASI_INTR_R, %g7 stxa %g0, [%g0] ASI_INTR_RECEIVE membar #Sync - jmpl %g3, %g0 + ba,pt %xcc, 1f + nop + + .align 32 +1: jmpl %g3, %g0 nop do_ivec_spurious: @@ -657,15 +661,15 @@ stx %g5, [%g1 + %lo(pdma_size)] sethi %hi(auxio_register), %g1 ldx [%g1 + %lo(auxio_register)], %g7 - ldub [%g7], %g5 + lduba [%g7] ASI_PHYS_BYPASS_EC_E, %g5 or %g5, 0xc2, %g5 - stb %g5, [%g7] + stba %g5, [%g7] ASI_PHYS_BYPASS_EC_E andn %g5, 0x02, %g5 nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; - stb %g5, [%g7] + stba %g5, [%g7] ASI_PHYS_BYPASS_EC_E sethi %hi(doing_pdma), %g1 b,pt %xcc, floppy_dosoftint st %g0, [%g1 + %lo(doing_pdma)] @@ -678,7 +682,12 @@ sethi %hi(irq_action), %g1 or %g1, %lo(irq_action), %g1 ldx [%g1 + (11 << 3)], %g3 ! irqaction[floppy_irq] - ldx [%g3 + 0x10], %g4 ! action->mask == ino_bucket ptr + ldx [%g3 + 0x08], %g4 ! action->flags>>48==ino + sethi %hi(ivector_table), %g3 + srlx %g4, 48, %g4 + or %g3, %lo(ivector_table), %g3 + sllx %g4, 5, %g4 + ldx [%g3 + %g4], %g4 ! &ivector_table[ino] ldx [%g4 + 0x10], %g4 ! bucket->iclr stwa %g0, [%g4] ASI_PHYS_BYPASS_EC_E ! ICLR_IDLE membar #Sync ! probably not needed... @@ -1615,6 +1624,11 @@ * * Note with time_t changes to the timeval type, I must now use * nucleus atomic quad 128-bit loads. + * + * If xtime was stored recently, I've seen crap from the + * quad load on Cheetah. Putting a membar SYNC before + * the quad load seems to make the problem go away. -DaveM + * (we should nop out workarounds like this on spitfire) */ sethi %hi(timer_tick_offset), %g3 sethi %hi(xtime), %g2 @@ -1626,6 +1640,7 @@ sethi %hi(0x003e0014), %o1 srlx %o2, 32, %o2 or %o1, %lo(0x003e0014), %o1 + membar #Sync ldda [%g2] ASI_NUCLEUS_QUAD_LDD, %o4 cmp %o2, %o1 bne,pt %xcc, 2f @@ -1634,6 +1649,7 @@ rd %asr24, %o1 2: rd %tick, %o1 3: ldx [%g1], %g7 + membar #Sync ldda [%g2] ASI_NUCLEUS_QUAD_LDD, %o2 xor %o4, %o2, %o2 xor %o5, %o3, %o3 diff -urN linux-2.5.2-pre11/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c --- linux-2.5.2-pre11/arch/sparc64/kernel/ioctl32.c Tue Nov 13 09:16:05 2001 +++ linux/arch/sparc64/kernel/ioctl32.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: ioctl32.c,v 1.132 2001/11/07 05:56:19 davem Exp $ +/* $Id: ioctl32.c,v 1.135 2002/01/11 08:45:38 davem Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) @@ -472,6 +472,7 @@ return -ENODEV; strcpy(ifr32.ifr_name, dev->name); + dev_put(dev); err = copy_to_user((struct ifreq32 *)arg, &ifr32, sizeof(struct ifreq32)); return (err ? -EFAULT : 0); @@ -2421,6 +2422,7 @@ u32 pv[ABS_MAX_PV + 1]; u32 lv[ABS_MAX_LV + 1]; uint8_t vg_uuid[UUID_LEN+1]; /* volume group UUID */ + uint8_t dummy1[200]; } vg32_t; typedef struct { @@ -2462,7 +2464,7 @@ } lv_status_byindex_req32_t; typedef struct { - dev_t dev; + __kernel_dev_t32 dev; u32 lv; } lv_status_bydev_req32_t; @@ -2535,7 +2537,8 @@ lv_block_exception32_t *lbe32; lv_block_exception_t *lbe; lv32_t *ul = (lv32_t *)A(p); - lv_t *l = (lv_t *)kmalloc(sizeof(lv_t), GFP_KERNEL); + lv_t *l = (lv_t *) kmalloc(sizeof(lv_t), GFP_KERNEL); + if (!l) { *errp = -ENOMEM; return NULL; @@ -2565,12 +2568,11 @@ if (l->lv_block_exception) { lbe32 = (lv_block_exception32_t *)A(ptr2); memset(lbe, 0, size); - for (i = 0; i < l->lv_remap_end; i++, lbe++, lbe32++) { - err |= get_user(lbe->rsector_org, &lbe32->rsector_org); - err |= __get_user(lbe->rdev_org, &lbe32->rdev_org); - err |= __get_user(lbe->rsector_new, &lbe32->rsector_new); - err |= __get_user(lbe->rdev_new, &lbe32->rdev_new); - + for (i = 0; i < l->lv_remap_end; i++, lbe++, lbe32++) { + err |= get_user(lbe->rsector_org, &lbe32->rsector_org); + err |= __get_user(lbe->rdev_org, &lbe32->rdev_org); + err |= __get_user(lbe->rsector_new, &lbe32->rsector_new); + err |= __get_user(lbe->rdev_new, &lbe32->rdev_new); } } } @@ -2608,7 +2610,7 @@ static int do_lvm_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) { - vg_t *v; + vg_t *v = NULL; union { lv_req_t lv_req; le_remap_req_t le_remap; @@ -2626,17 +2628,22 @@ switch (cmd) { case VG_STATUS: v = kmalloc(sizeof(vg_t), GFP_KERNEL); - if (!v) return -ENOMEM; + if (!v) + return -ENOMEM; karg = v; break; + + case VG_CREATE_OLD: case VG_CREATE: v = kmalloc(sizeof(vg_t), GFP_KERNEL); - if (!v) return -ENOMEM; - if (copy_from_user(v, (void *)arg, (long)&((vg32_t *)0)->proc) || - __get_user(v->proc, &((vg32_t *)arg)->proc)) { + if (!v) + return -ENOMEM; + if (copy_from_user(v, (void *)arg, (long)&((vg32_t *)0)->proc)) { kfree(v); return -EFAULT; } + /* 'proc' field is unused, just NULL it out. */ + v->proc = NULL; if (copy_from_user(v->vg_uuid, ((vg32_t *)arg)->vg_uuid, UUID_LEN+1)) { kfree(v); return -EFAULT; @@ -2648,39 +2655,46 @@ return -EPERM; for (i = 0; i < v->pv_max; i++) { err = __get_user(ptr, &((vg32_t *)arg)->pv[i]); - if (err) break; + if (err) + break; if (ptr) { v->pv[i] = kmalloc(sizeof(pv_t), GFP_KERNEL); if (!v->pv[i]) { err = -ENOMEM; break; } - err = copy_from_user(v->pv[i], (void *)A(ptr), sizeof(pv32_t) - 8 - UUID_LEN+1); + err = copy_from_user(v->pv[i], (void *)A(ptr), + sizeof(pv32_t) - 8 - UUID_LEN+1); if (err) { err = -EFAULT; break; } - err = copy_from_user(v->pv[i]->pv_uuid, ((pv32_t *)A(ptr))->pv_uuid, UUID_LEN+1); + err = copy_from_user(v->pv[i]->pv_uuid, + ((pv32_t *)A(ptr))->pv_uuid, + UUID_LEN+1); if (err) { err = -EFAULT; break; } - - v->pv[i]->pe = NULL; v->pv[i]->inode = NULL; + v->pv[i]->pe = NULL; + v->pv[i]->bd = NULL; } } if (!err) { for (i = 0; i < v->lv_max; i++) { err = __get_user(ptr, &((vg32_t *)arg)->lv[i]); - if (err) break; + if (err) + break; if (ptr) { v->lv[i] = get_lv_t(ptr, &err); - if (err) break; + if (err) + break; } } } break; + case LV_CREATE: case LV_EXTEND: case LV_REDUCE: @@ -2688,54 +2702,70 @@ case LV_RENAME: case LV_STATUS_BYNAME: err = copy_from_user(&u.pv_status, arg, sizeof(u.pv_status.pv_name)); - if (err) return -EFAULT; + if (err) + return -EFAULT; if (cmd != LV_REMOVE) { err = __get_user(ptr, &((lv_req32_t *)arg)->lv); - if (err) return err; + if (err) + return err; u.lv_req.lv = get_lv_t(ptr, &err); } else u.lv_req.lv = NULL; break; - case LV_STATUS_BYINDEX: - err = get_user(u.lv_byindex.lv_index, &((lv_status_byindex_req32_t *)arg)->lv_index); + err = get_user(u.lv_byindex.lv_index, + &((lv_status_byindex_req32_t *)arg)->lv_index); err |= __get_user(ptr, &((lv_status_byindex_req32_t *)arg)->lv); - if (err) return err; + if (err) + return err; u.lv_byindex.lv = get_lv_t(ptr, &err); break; + case LV_STATUS_BYDEV: err = get_user(u.lv_bydev.dev, &((lv_status_bydev_req32_t *)arg)->dev); + err |= __get_user(ptr, &((lv_status_bydev_req32_t *)arg)->lv); + if (err) + return err; u.lv_bydev.lv = get_lv_t(ptr, &err); - if (err) return err; - u.lv_bydev.lv = &p; - p.pe = NULL; p.inode = NULL; - break; + break; + case VG_EXTEND: err = copy_from_user(&p, (void *)arg, sizeof(pv32_t) - 8 - UUID_LEN+1); - if (err) return -EFAULT; + if (err) + return -EFAULT; err = copy_from_user(p.pv_uuid, ((pv32_t *)arg)->pv_uuid, UUID_LEN+1); - if (err) return -EFAULT; - p.pe = NULL; p.inode = NULL; + if (err) + return -EFAULT; + p.pe = NULL; + p.bd = NULL; karg = &p; break; + case PV_CHANGE: case PV_STATUS: err = copy_from_user(&u.pv_status, arg, sizeof(u.lv_req.lv_name)); - if (err) return -EFAULT; + if (err) + return -EFAULT; err = __get_user(ptr, &((pv_status_req32_t *)arg)->pv); - if (err) return err; + if (err) + return err; u.pv_status.pv = &p; if (cmd == PV_CHANGE) { - err = copy_from_user(&p, (void *)A(ptr), sizeof(pv32_t) - 8 - UUID_LEN+1); - if (err) return -EFAULT; - p.pe = NULL; p.inode = NULL; + err = copy_from_user(&p, (void *)A(ptr), + sizeof(pv32_t) - 8 - UUID_LEN+1); + if (err) + return -EFAULT; + p.pe = NULL; + p.bd = NULL; } break; - } + }; + old_fs = get_fs(); set_fs (KERNEL_DS); err = sys_ioctl (fd, cmd, (unsigned long)karg); set_fs (old_fs); + switch (cmd) { case VG_STATUS: if (!err) { @@ -2748,42 +2778,60 @@ } kfree(v); break; + + case VG_CREATE_OLD: case VG_CREATE: - for (i = 0; i < v->pv_max; i++) - if (v->pv[i]) kfree(v->pv[i]); - for (i = 0; i < v->lv_max; i++) - if (v->lv[i]) put_lv_t(v->lv[i]); + for (i = 0; i < v->pv_max; i++) { + if (v->pv[i]) + kfree(v->pv[i]); + } + for (i = 0; i < v->lv_max; i++) { + if (v->lv[i]) + put_lv_t(v->lv[i]); + } kfree(v); break; + case LV_STATUS_BYNAME: - if (!err && u.lv_req.lv) err = copy_lv_t(ptr, u.lv_req.lv); + if (!err && u.lv_req.lv) + err = copy_lv_t(ptr, u.lv_req.lv); /* Fall through */ + case LV_CREATE: case LV_EXTEND: case LV_REDUCE: - if (u.lv_req.lv) put_lv_t(u.lv_req.lv); + if (u.lv_req.lv) + put_lv_t(u.lv_req.lv); break; + case LV_STATUS_BYINDEX: if (u.lv_byindex.lv) { - if (!err) err = copy_lv_t(ptr, u.lv_byindex.lv); + if (!err) + err = copy_lv_t(ptr, u.lv_byindex.lv); put_lv_t(u.lv_byindex.lv); } break; + + case LV_STATUS_BYDEV: + if (u.lv_bydev.lv) { + if (!err) + err = copy_lv_t(ptr, u.lv_bydev.lv); + put_lv_t(u.lv_byindex.lv); + } + break; + case PV_STATUS: if (!err) { err = copy_to_user((void *)A(ptr), &p, sizeof(pv32_t) - 8 - UUID_LEN+1); - if (err) return -EFAULT; + if (err) + return -EFAULT; err = copy_to_user(((pv_t *)A(ptr))->pv_uuid, p.pv_uuid, UUID_LEN + 1); - if (err) return -EFAULT; + if (err) + return -EFAULT; } break; - case LV_STATUS_BYDEV: - if (!err) { - if (!err) err = copy_lv_t(ptr, u.lv_bydev.lv); - put_lv_t(u.lv_byindex.lv); - } - break; - } + }; + return err; } #endif @@ -3379,11 +3427,11 @@ } struct usbdevfs_ctrltransfer32 { - __u8 requesttype; - __u8 request; - __u16 value; - __u16 index; - __u16 length; + __u8 bRequestType; + __u8 bRequest; + __u16 wValue; + __u16 wIndex; + __u16 wLength; __u32 timeout; /* in milliseconds */ __u32 data; }; @@ -3413,14 +3461,14 @@ /* In usbdevice_fs, it limits the control buffer to a page, * for simplicity so do we. */ - if (!uptr || kctrl.length > PAGE_SIZE) + if (!uptr || kctrl.wLength > PAGE_SIZE) return -EINVAL; kptr = (void *)__get_free_page(GFP_KERNEL); - if ((kctrl.requesttype & 0x80) == 0) { + if ((kctrl.bRequestType & 0x80) == 0) { err = -EFAULT; - if (copy_from_user(kptr, uptr, kctrl.length)) + if (copy_from_user(kptr, uptr, kctrl.wLength)) goto out; } @@ -3432,8 +3480,8 @@ set_fs(old_fs); if (err >= 0 && - ((kctrl.requesttype & 0x80) != 0)) { - if (copy_to_user(uptr, kptr, kctrl.length)) + ((kctrl.bRequestType & 0x80) != 0)) { + if (copy_to_user(uptr, kptr, kctrl.wLength)) err = -EFAULT; } @@ -4666,6 +4714,7 @@ HANDLE_IOCTL(SONET_GETFRSENSE, do_atm_ioctl) #if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE) HANDLE_IOCTL(VG_STATUS, do_lvm_ioctl) +HANDLE_IOCTL(VG_CREATE_OLD, do_lvm_ioctl) HANDLE_IOCTL(VG_CREATE, do_lvm_ioctl) HANDLE_IOCTL(VG_EXTEND, do_lvm_ioctl) HANDLE_IOCTL(LV_CREATE, do_lvm_ioctl) @@ -4675,6 +4724,7 @@ HANDLE_IOCTL(LV_RENAME, do_lvm_ioctl) HANDLE_IOCTL(LV_STATUS_BYNAME, do_lvm_ioctl) HANDLE_IOCTL(LV_STATUS_BYINDEX, do_lvm_ioctl) +HANDLE_IOCTL(LV_STATUS_BYDEV, do_lvm_ioctl) HANDLE_IOCTL(PV_CHANGE, do_lvm_ioctl) HANDLE_IOCTL(PV_STATUS, do_lvm_ioctl) #endif /* LVM */ diff -urN linux-2.5.2-pre11/arch/sparc64/kernel/iommu_common.c linux/arch/sparc64/kernel/iommu_common.c --- linux-2.5.2-pre11/arch/sparc64/kernel/iommu_common.c Sun Dec 16 12:20:20 2001 +++ linux/arch/sparc64/kernel/iommu_common.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: iommu_common.c,v 1.8 2001/12/11 11:13:06 davem Exp $ +/* $Id: iommu_common.c,v 1.9 2001/12/17 07:05:09 davem Exp $ * iommu_common.c: UltraSparc SBUS/PCI common iommu code. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -66,9 +66,7 @@ daddr = dma_sg->dma_address; sglen = sg->length; - sgaddr = (unsigned long) (sg->address ? - sg->address : - page_address(sg->page) + sg->offset); + sgaddr = (unsigned long) (page_address(sg->page) + sg->offset); while (dlen > 0) { unsigned long paddr; @@ -118,9 +116,7 @@ sg++; if (--nents <= 0) break; - sgaddr = (unsigned long) (sg->address ? - sg->address : - page_address(sg->page) + sg->offset); + sgaddr = (unsigned long) (page_address(sg->page) + sg->offset); sglen = sg->length; } if (dlen < 0) { @@ -183,10 +179,11 @@ printk("%016lx.\n", sg->dma_address & IO_PAGE_MASK); for (i = 0; i < nents; i++) { - printk("sg(%d): address(%p) length(%x) " + printk("sg(%d): page_addr(%p) off(%x) length(%x) " "dma_address[%016lx] dma_length[%016lx]\n", i, - sg[i].address, sg[i].length, + page_address(sg[i].page), sg[i].offset, + sg[i].length, sg[i].dma_address, sg[i].dma_length); } } @@ -201,21 +198,15 @@ unsigned long prev; u32 dent_addr, dent_len; - prev = (unsigned long) (sg->address ? - sg->address : - page_address(sg->page) + sg->offset); + prev = (unsigned long) (page_address(sg->page) + sg->offset); prev += (unsigned long) (dent_len = sg->length); - dent_addr = (u32) ((unsigned long)(sg->address ? - sg->address : - page_address(sg->page) + sg->offset) + dent_addr = (u32) ((unsigned long)(page_address(sg->page) + sg->offset) & (IO_PAGE_SIZE - 1UL)); while (--nents) { unsigned long addr; sg++; - addr = (unsigned long) (sg->address ? - sg->address : - page_address(sg->page) + sg->offset); + addr = (unsigned long) (page_address(sg->page) + sg->offset); if (! VCONTIG(prev, addr)) { dma_sg->dma_address = dent_addr; dma_sg->dma_length = dent_len; diff -urN linux-2.5.2-pre11/arch/sparc64/kernel/irq.c linux/arch/sparc64/kernel/irq.c --- linux-2.5.2-pre11/arch/sparc64/kernel/irq.c Wed Nov 28 13:22:26 2001 +++ linux/arch/sparc64/kernel/irq.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.109 2001/11/12 22:22:37 davem Exp $ +/* $Id: irq.c,v 1.114 2002/01/11 08:45:38 davem Exp $ * irq.c: UltraSparc IRQ handling/init/registry. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -35,6 +36,7 @@ #include #include #include +#include #ifdef CONFIG_SMP static void distribute_irqs(void); @@ -53,10 +55,10 @@ * at the same time. */ -struct ino_bucket ivector_table[NUM_IVECS] __attribute__ ((aligned (64))); +struct ino_bucket ivector_table[NUM_IVECS] __attribute__ ((aligned (SMP_CACHE_BYTES))); #ifndef CONFIG_SMP -unsigned int __up_workvec[16] __attribute__ ((aligned (64))); +unsigned int __up_workvec[16] __attribute__ ((aligned (SMP_CACHE_BYTES))); #define irq_work(__cpu, __pil) &(__up_workvec[(void)(__cpu), (__pil)]) #else #define irq_work(__cpu, __pil) &(cpu_data[(__cpu)].irq_worklists[(__pil)]) @@ -116,19 +118,19 @@ for(i = 0; i < (NR_IRQS + 1); i++) { if(!(action = *(i + irq_action))) continue; - seq_print(p, "%3d: ", i); + seq_printf(p, "%3d: ", i); #ifndef CONFIG_SMP - seq_print(p, "%10u ", kstat_irqs(i)); + seq_printf(p, "%10u ", kstat_irqs(i)); #else for (j = 0; j < smp_num_cpus; j++) - seq_print(p, "%10u ", - kstat.irqs[cpu_logical_map(j)][i]); + seq_printf(p, "%10u ", + kstat.irqs[cpu_logical_map(j)][i]); #endif - seq_print(p, " %s:%lx", action->name, - get_ino_in_irqaction(action)); + seq_printf(p, " %s:%lx", action->name, + get_ino_in_irqaction(action)); for(action = action->next; action; action = action->next) { - seq_print(p, ", %s:%lx", action->name, - get_ino_in_irqaction(action)); + seq_printf(p, ", %s:%lx", action->name, + get_ino_in_irqaction(action)); } seq_putc(p, '\n'); } @@ -161,7 +163,7 @@ tid = ((tid & UPA_CONFIG_MID) << 9); tid &= IMAP_TID_UPA; } else { - tid = (starfire_translate(imap, current->processor) << 26); + tid = (starfire_translate(imap, smp_processor_id()) << 26); tid &= IMAP_TID_UPA; } @@ -823,6 +825,11 @@ irq_enter(cpu, irq); kstat.irqs[cpu][irq]++; +#ifdef CONFIG_PCI + if (irq == 9) + kbd_pt_regs = regs; +#endif + /* Sliiiick... */ #ifndef CONFIG_SMP bp = ((irq != 0) ? @@ -1246,19 +1253,15 @@ prom_timers->count0 = 0; } +/* Only invoked on boot processor. */ void __init init_IRQ(void) { - static int called = 0; - - if (called == 0) { - called = 1; - map_prom_timers(); - kill_prom_timer(); - memset(&ivector_table[0], 0, sizeof(ivector_table)); + map_prom_timers(); + kill_prom_timer(); + memset(&ivector_table[0], 0, sizeof(ivector_table)); #ifndef CONFIG_SMP - memset(&__up_workvec[0], 0, sizeof(__up_workvec)); + memset(&__up_workvec[0], 0, sizeof(__up_workvec)); #endif - } /* We need to clear any IRQ's pending in the soft interrupt * registers, a spurious one could be left around from the diff -urN linux-2.5.2-pre11/arch/sparc64/kernel/pci_iommu.c linux/arch/sparc64/kernel/pci_iommu.c --- linux-2.5.2-pre11/arch/sparc64/kernel/pci_iommu.c Fri Oct 12 15:35:53 2001 +++ linux/arch/sparc64/kernel/pci_iommu.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: pci_iommu.c,v 1.16 2001/10/09 02:24:33 davem Exp $ +/* $Id: pci_iommu.c,v 1.17 2001/12/17 07:05:09 davem Exp $ * pci_iommu.c: UltraSparc PCI controller IOM/STC support. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -425,9 +425,7 @@ } #define SG_ENT_PHYS_ADDRESS(SG) \ - ((SG)->address ? \ - __pa((SG)->address) : \ - (__pa(page_address((SG)->page)) + (SG)->offset)) + (__pa(page_address((SG)->page)) + (SG)->offset) static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, int nused, int nelems, unsigned long iopte_protection) @@ -522,9 +520,7 @@ if (nelems == 1) { sglist->dma_address = pci_map_single(pdev, - (sglist->address ? - sglist->address : - (page_address(sglist->page) + sglist->offset)), + (page_address(sglist->page) + sglist->offset), sglist->length, direction); sglist->dma_length = sglist->length; return 1; diff -urN linux-2.5.2-pre11/arch/sparc64/kernel/pci_psycho.c linux/arch/sparc64/kernel/pci_psycho.c --- linux-2.5.2-pre11/arch/sparc64/kernel/pci_psycho.c Fri Oct 12 15:35:53 2001 +++ linux/arch/sparc64/kernel/pci_psycho.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: pci_psycho.c,v 1.29 2001/10/11 00:44:38 davem Exp $ +/* $Id: pci_psycho.c,v 1.31 2002/01/05 07:33:16 davem Exp $ * pci_psycho.c: PSYCHO/U2P specific PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -371,6 +372,7 @@ case PCI_BASE_CLASS_MULTIMEDIA: case PCI_BASE_CLASS_MEMORY: case PCI_BASE_CLASS_BRIDGE: + case PCI_BASE_CLASS_SERIAL: ret = 10; break; @@ -1479,8 +1481,7 @@ { unsigned int busrange[2]; struct pci_pbm_info *pbm; - char namebuf[64]; - int err, len; + int err; if (is_pbm_a) { pbm = &p->pbm_A; @@ -1489,13 +1490,9 @@ pbm->mem_space.start = p->controller_regs + PSYCHO_MEMSPACE_A; } else { pbm = &p->pbm_B; - pbm->pci_first_slot = 1; - len = prom_getproperty(prom_root_node, "name", - namebuf, sizeof(namebuf)); - if (len > 0) { - if (!strcmp(namebuf, "SUNW,Ultra-1-Engine")) - pbm->pci_first_slot = 2; - } + pbm->pci_first_slot = 2; + if (central_bus != NULL) + pbm->pci_first_slot = 1; pbm->io_space.start = p->controller_regs + PSYCHO_IOSPACE_B; pbm->mem_space.start = p->controller_regs + PSYCHO_MEMSPACE_B; } diff -urN linux-2.5.2-pre11/arch/sparc64/kernel/pci_sabre.c linux/arch/sparc64/kernel/pci_sabre.c --- linux-2.5.2-pre11/arch/sparc64/kernel/pci_sabre.c Fri Oct 12 15:35:53 2001 +++ linux/arch/sparc64/kernel/pci_sabre.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: pci_sabre.c,v 1.40 2001/10/11 00:44:38 davem Exp $ +/* $Id: pci_sabre.c,v 1.41 2001/11/14 13:17:56 davem Exp $ * pci_sabre.c: Sabre specific PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) @@ -589,6 +589,11 @@ { int ret; + if (pdev && + pdev->vendor == PCI_VENDOR_ID_SUN && + pdev->device == PCI_DEVICE_ID_SUN_RIO_USB) + return 9; + ret = sabre_pil_table[ino]; if (ret == 0 && pdev == NULL) { ret = 1; @@ -609,6 +614,7 @@ case PCI_BASE_CLASS_MULTIMEDIA: case PCI_BASE_CLASS_MEMORY: case PCI_BASE_CLASS_BRIDGE: + case PCI_BASE_CLASS_SERIAL: ret = 10; break; diff -urN linux-2.5.2-pre11/arch/sparc64/kernel/pci_schizo.c linux/arch/sparc64/kernel/pci_schizo.c --- linux-2.5.2-pre11/arch/sparc64/kernel/pci_schizo.c Fri Oct 12 15:35:53 2001 +++ linux/arch/sparc64/kernel/pci_schizo.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: pci_schizo.c,v 1.22 2001/10/11 00:44:38 davem Exp $ +/* $Id: pci_schizo.c,v 1.23 2001/11/14 13:17:56 davem Exp $ * pci_schizo.c: SCHIZO specific PCI controller support. * * Copyright (C) 2001 David S. Miller (davem@redhat.com) @@ -337,6 +337,11 @@ { int ret; + if (pdev && + pdev->vendor == PCI_VENDOR_ID_SUN && + pdev->device == PCI_DEVICE_ID_SUN_RIO_USB) + return 9; + ret = schizo_pil_table[ino]; if (ret == 0 && pdev == NULL) { ret = 1; @@ -357,6 +362,7 @@ case PCI_BASE_CLASS_MULTIMEDIA: case PCI_BASE_CLASS_MEMORY: case PCI_BASE_CLASS_BRIDGE: + case PCI_BASE_CLASS_SERIAL: ret = 10; break; diff -urN linux-2.5.2-pre11/arch/sparc64/kernel/power.c linux/arch/sparc64/kernel/power.c --- linux-2.5.2-pre11/arch/sparc64/kernel/power.c Tue Jun 12 11:08:46 2001 +++ linux/arch/sparc64/kernel/power.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: power.c,v 1.9 2001/06/08 02:28:22 davem Exp $ +/* $Id: power.c,v 1.10 2001/12/11 01:57:16 davem Exp $ * power.c: Power management driver. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -61,7 +61,7 @@ sprintf(current->comm, "powerd"); again: - while(button_pressed == 0) { + while (button_pressed == 0) { spin_lock_irq(¤t->sigmask_lock); flush_signals(current); spin_unlock_irq(¤t->sigmask_lock); @@ -98,16 +98,19 @@ found: power_reg = (unsigned long)ioremap(edev->resource[0].start, 0x4); printk("power: Control reg at %016lx ... ", power_reg); - if (kernel_thread(powerd, 0, CLONE_FS) < 0) { - printk("Failed to start power daemon.\n"); - return; - } - printk("powerd running.\n"); - if (edev->irqs[0] != 0) { + if (edev->irqs[0] != PCI_IRQ_NONE) { + if (kernel_thread(powerd, 0, CLONE_FS) < 0) { + printk("Failed to start power daemon.\n"); + return; + } + printk("powerd running.\n"); + if (request_irq(edev->irqs[0], power_handler, SA_SHIRQ, "power", (void *) power_reg) < 0) printk("power: Error, cannot register IRQ handler.\n"); + } else { + printk("not using powerd.\n"); } } #endif /* CONFIG_PCI */ diff -urN linux-2.5.2-pre11/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c --- linux-2.5.2-pre11/arch/sparc64/kernel/process.c Mon Jan 14 18:28:22 2002 +++ linux/arch/sparc64/kernel/process.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.122 2001/10/18 09:06:36 davem Exp $ +/* $Id: process.c,v 1.128 2002/01/11 08:45:38 davem Exp $ * arch/sparc64/kernel/process.c * * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) @@ -53,9 +53,6 @@ return -EPERM; /* endless idle loop with no priority at all */ - current->nice = 20; - init_idle(); - for (;;) { /* If current->need_resched is zero we should really * setup for a system wakup event and execute a shutdown @@ -78,13 +75,10 @@ /* * the idle loop on a UltraMultiPenguin... */ -#define idle_me_harder() (cpu_data[current->processor].idle_volume += 1) -#define unidle_me() (cpu_data[current->processor].idle_volume = 0) +#define idle_me_harder() (cpu_data[smp_processor_id()].idle_volume += 1) +#define unidle_me() (cpu_data[smp_processor_id()].idle_volume = 0) int cpu_idle(void) { - current->nice = 20; - init_idle(); - while(1) { if (current->need_resched != 0) { unidle_me(); @@ -274,7 +268,12 @@ #ifdef CONFIG_SMP unsigned long flags; - spin_lock_irqsave(®dump_lock, flags); + /* Protect against xcall ipis which might lead to livelock on the lock */ + __asm__ __volatile__("rdpr %%pstate, %0\n\t" + "wrpr %0, %1, %%pstate" + : "=r" (flags) + : "i" (PSTATE_IE)); + spin_lock(®dump_lock); printk("CPU[%d]: local_irq_count[%u] irqs_running[%d]\n", smp_processor_id(), local_irq_count(smp_processor_id()), @@ -296,7 +295,9 @@ regs->u_regs[15]); show_regwindow(regs); #ifdef CONFIG_SMP - spin_unlock_irqrestore(®dump_lock, flags); + spin_unlock(®dump_lock); + __asm__ __volatile__("wrpr %0, 0, %%pstate" + : : "r" (flags)); #endif } @@ -462,6 +463,7 @@ csp += STACK_BIAS; psp += STACK_BIAS; __get_user(fp, &(((struct reg_window *)psp)->ins[6])); + fp += STACK_BIAS; } else __get_user(fp, &(((struct reg_window32 *)psp)->ins[6])); @@ -581,6 +583,11 @@ { struct thread_struct *t = &p->thread; char *child_trap_frame; + +#ifdef CONFIG_DEBUG_SPINLOCK + t->smp_lock_count = 0; + t->smp_lock_pc = 0; +#endif /* Calculate offset to stack_frame & pt_regs */ child_trap_frame = ((char *)p) + (THREAD_SIZE - (TRACEREG_SZ+REGWIN_SZ)); diff -urN linux-2.5.2-pre11/arch/sparc64/kernel/rtrap.S linux/arch/sparc64/kernel/rtrap.S --- linux-2.5.2-pre11/arch/sparc64/kernel/rtrap.S Wed Oct 17 14:16:39 2001 +++ linux/arch/sparc64/kernel/rtrap.S Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: rtrap.S,v 1.56 2001/10/13 00:14:34 kanoj Exp $ +/* $Id: rtrap.S,v 1.59 2002/01/11 08:45:38 davem Exp $ * rtrap.S: Preparing for return from trap on Sparc V9. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -18,14 +18,13 @@ #define RTRAP_PSTATE_IRQOFF (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV) #define RTRAP_PSTATE_AG_IRQOFF (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG) -#if 0 -#define RTRAP_CHECK call rtrap_check; add %sp, (STACK_BIAS+REGWIN_SZ), %o0; -#else -#define RTRAP_CHECK -#endif + /* Register %l6 keeps track of whether we are returning + * from a system call or not. It is cleared if we call + * do_signal, and it must not be otherwise modified until + * we fully commit to returning to userspace. + */ .text - .align 32 __handle_softirq: call do_softirq @@ -34,42 +33,100 @@ nop __handle_preemption: call schedule - nop + wrpr %g0, RTRAP_PSTATE, %pstate ba,pt %xcc, __handle_preemption_continue - nop + wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate + __handle_user_windows: - wrpr %g0, RTRAP_PSTATE, %pstate call fault_in_user_windows + wrpr %g0, RTRAP_PSTATE, %pstate + wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate + /* Redo sched+sig checks */ + ldx [%g6 + AOFF_task_need_resched], %l0 + brz,pt %l0, 1f nop - ba,pt %xcc, __handle_user_windows_continue + call schedule + + wrpr %g0, RTRAP_PSTATE, %pstate + wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate +1: lduw [%g6 + AOFF_task_sigpending], %l0 + brz,pt %l0, __handle_user_windows_continue nop + clr %o0 + mov %l5, %o2 + mov %l6, %o3 + + add %sp, STACK_BIAS + REGWIN_SZ, %o1 + call do_signal + wrpr %g0, RTRAP_PSTATE, %pstate + wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate + clr %l6 + /* Signal delivery can modify pt_regs tstate, so we must + * reload it. + */ + ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 + sethi %hi(0xf << 20), %l4 + and %l1, %l4, %l4 + + ba,pt %xcc, __handle_user_windows_continue + andn %l1, %l4, %l1 __handle_perfctrs: - /* Don't forget to preserve user window invariants. */ - wrpr %g0, RTRAP_PSTATE, %pstate call update_perfctrs - nop + wrpr %g0, RTRAP_PSTATE, %pstate wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate ldub [%g6 + AOFF_task_thread + AOFF_thread_w_saved], %o2 - brz,pt %o2, __handle_perfctrs_continue - sethi %hi(TSTATE_PEF), %l6 - wrpr %g0, RTRAP_PSTATE, %pstate + brz,pt %o2, 1f + nop + /* Redo userwin+sched+sig checks */ call fault_in_user_windows + wrpr %g0, RTRAP_PSTATE, %pstate + wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate +1: ldx [%g6 + AOFF_task_need_resched], %l0 + brz,pt %l0, 1f nop + call schedule + wrpr %g0, RTRAP_PSTATE, %pstate + + wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate +1: lduw [%g6 + AOFF_task_sigpending], %l0 + brz,pt %l0, __handle_perfctrs_continue + sethi %hi(TSTATE_PEF), %o0 + clr %o0 + mov %l5, %o2 + mov %l6, %o3 + add %sp, STACK_BIAS + REGWIN_SZ, %o1 + + call do_signal + wrpr %g0, RTRAP_PSTATE, %pstate + wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate + clr %l6 + /* Signal delivery can modify pt_regs tstate, so we must + * reload it. + */ + ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 + sethi %hi(0xf << 20), %l4 + and %l1, %l4, %l4 + andn %l1, %l4, %l1 + ba,pt %xcc, __handle_perfctrs_continue - nop + sethi %hi(TSTATE_PEF), %o0 __handle_userfpu: rd %fprs, %l5 andcc %l5, FPRS_FEF, %g0 + sethi %hi(TSTATE_PEF), %o0 be,a,pn %icc, __handle_userfpu_continue - andn %l1, %l6, %l1 + andn %l1, %o0, %l1 ba,a,pt %xcc, __handle_userfpu_continue + __handle_signal: clr %o0 mov %l5, %o2 mov %l6, %o3 + add %sp, STACK_BIAS + REGWIN_SZ, %o1 call do_signal - add %sp, STACK_BIAS + REGWIN_SZ, %o1 + wrpr %g0, RTRAP_PSTATE, %pstate + wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate clr %l6 /* Signal delivery can modify pt_regs tstate, so we must @@ -84,7 +141,7 @@ .align 64 .globl rtrap_clr_l6, rtrap, irqsz_patchme rtrap_clr_l6: clr %l6 -rtrap: lduw [%g6 + AOFF_task_processor], %l0 +rtrap: lduw [%g6 + AOFF_task_cpu], %l0 sethi %hi(irq_stat), %l2 ! &softirq_active or %l2, %lo(irq_stat), %l2 ! &softirq_active irqsz_patchme: sllx %l0, 0, %l0 @@ -99,29 +156,43 @@ and %l1, %l4, %l4 bne,pn %icc, to_kernel andn %l1, %l4, %l1 -to_user: ldx [%g6 + AOFF_task_need_resched], %l0 - brnz,pn %l0, __handle_preemption + /* We must hold IRQs off and atomically test schedule+signal + * state, then hold them off all the way back to userspace. + * If we are returning to kernel, none of this matters. + * + * If we do not do this, there is a window where we would do + * the tests, later the signal/resched event arrives but we do + * not process it since we are still in kernel mode. It would + * take until the next local IRQ before the signal/resched + * event would be handled. + * + * This also means that if we have to deal with performance + * counters or user windows, we have to redo all of these + * sched+signal checks with IRQs disabled. + */ +to_user: wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate __handle_preemption_continue: + ldx [%g6 + AOFF_task_need_resched], %l0 + brnz,pn %l0, __handle_preemption lduw [%g6 + AOFF_task_sigpending], %l0 brnz,pn %l0, __handle_signal nop __handle_signal_continue: -check_user_wins: - wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate ldub [%g6 + AOFF_task_thread + AOFF_thread_w_saved], %o2 brnz,pn %o2, __handle_user_windows - sethi %hi(TSTATE_PEF), %l6 - + nop __handle_user_windows_continue: - RTRAP_CHECK ldub [%g6 + AOFF_task_thread + AOFF_thread_flags], %l5 andcc %l5, SPARC_FLAG_PERFCTR, %g0 + sethi %hi(TSTATE_PEF), %o0 bne,pn %xcc, __handle_perfctrs __handle_perfctrs_continue: - andcc %l1, %l6, %g0 + andcc %l1, %o0, %g0 + + /* This fpdepth clear is neccessary for non-syscall rtraps only */ bne,pn %xcc, __handle_userfpu - stb %g0, [%g6 + AOFF_task_thread + AOFF_thread_fpdepth] ! This is neccessary for non-syscall rtraps only + stb %g0, [%g6 + AOFF_task_thread + AOFF_thread_fpdepth] __handle_userfpu_continue: rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1 diff -urN linux-2.5.2-pre11/arch/sparc64/kernel/sbus.c linux/arch/sparc64/kernel/sbus.c --- linux-2.5.2-pre11/arch/sparc64/kernel/sbus.c Fri Oct 12 15:35:53 2001 +++ linux/arch/sparc64/kernel/sbus.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: sbus.c,v 1.17 2001/10/09 02:24:33 davem Exp $ +/* $Id: sbus.c,v 1.18 2001/12/17 07:05:09 davem Exp $ * sbus.c: UltraSparc SBUS controller support. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -377,9 +377,7 @@ } #define SG_ENT_PHYS_ADDRESS(SG) \ - ((SG)->address ? \ - __pa((SG)->address) : \ - (__pa(page_address((SG)->page)) + (SG)->offset)) + (__pa(page_address((SG)->page)) + (SG)->offset) static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, int nused, int nelems, unsigned long iopte_bits) { @@ -470,9 +468,7 @@ if (nents == 1) { sg->dma_address = sbus_map_single(sdev, - (sg->address ? - sg->address : - (page_address(sg->page) + sg->offset)), + (page_address(sg->page) + sg->offset), sg->length, dir); sg->dma_length = sg->length; return 1; diff -urN linux-2.5.2-pre11/arch/sparc64/kernel/semaphore.c linux/arch/sparc64/kernel/semaphore.c --- linux-2.5.2-pre11/arch/sparc64/kernel/semaphore.c Sun May 20 11:32:07 2001 +++ linux/arch/sparc64/kernel/semaphore.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: semaphore.c,v 1.8 2001/05/18 08:01:35 davem Exp $ +/* $Id: semaphore.c,v 1.9 2001/11/18 00:12:56 davem Exp $ * semaphore.c: Sparc64 semaphore implementation. * * This is basically the PPC semaphore scheme ported to use @@ -31,7 +31,7 @@ " cas [%3], %0, %1\n" " cmp %0, %1\n" " bne,pn %%icc, 1b\n" -" nop\n" +" membar #StoreLoad | #StoreStore\n" : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count) : "r" (&sem->count), "r" (incr), "m" (sem->count) : "cc"); diff -urN linux-2.5.2-pre11/arch/sparc64/kernel/signal.c linux/arch/sparc64/kernel/signal.c --- linux-2.5.2-pre11/arch/sparc64/kernel/signal.c Sun Mar 25 18:14:21 2001 +++ linux/arch/sparc64/kernel/signal.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.56 2001/03/21 11:46:20 davem Exp $ +/* $Id: signal.c,v 1.57 2001/12/11 04:55:51 davem Exp $ * arch/sparc64/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -17,6 +17,7 @@ #include #include #include +#include #include #include diff -urN linux-2.5.2-pre11/arch/sparc64/kernel/signal32.c linux/arch/sparc64/kernel/signal32.c --- linux-2.5.2-pre11/arch/sparc64/kernel/signal32.c Thu Apr 26 22:17:25 2001 +++ linux/arch/sparc64/kernel/signal32.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: signal32.c,v 1.70 2001/04/24 01:09:12 davem Exp $ +/* $Id: signal32.c,v 1.71 2001/12/11 04:55:51 davem Exp $ * arch/sparc64/kernel/signal32.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -16,6 +16,7 @@ #include #include #include +#include #include #include diff -urN linux-2.5.2-pre11/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c --- linux-2.5.2-pre11/arch/sparc64/kernel/smp.c Mon Jan 14 18:28:22 2002 +++ linux/arch/sparc64/kernel/smp.c Mon Jan 14 18:28:28 2002 @@ -209,23 +209,10 @@ atomic_inc(&init_mm.mm_count); current->active_mm = &init_mm; - while (!smp_processors_ready) + while (!smp_threads_ready) membar("#LoadLoad"); -} - -extern int cpu_idle(void); -extern void init_IRQ(void); -void initialize_secondary(void) -{ -} - -int start_secondary(void *unused) -{ - trap_init(); - init_IRQ(); - smp_callin(); - return cpu_idle(); + init_idle(); } void cpu_panic(void) @@ -251,7 +238,6 @@ printk("Entering UltraSMPenguin Mode...\n"); __sti(); smp_store_cpu_info(boot_cpu_id); - init_idle(); if (linux_num_cpus == 1) return; @@ -270,16 +256,13 @@ int no; prom_printf("Starting CPU %d... ", i); - kernel_thread(start_secondary, NULL, CLONE_PID); + kernel_thread(NULL, NULL, CLONE_PID); cpucount++; p = init_task.prev_task; - init_tasks[cpucount] = p; - p->processor = i; - p->cpus_runnable = 1 << i; /* we schedule the first task manually */ + p->cpu = i; - del_from_runqueue(p); unhash_process(p); callin_flag = 0; @@ -483,7 +466,7 @@ __asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate)); - if ((stuck & ~(0x5555555555555555UL)) == 0) { + if ((dispatch_stat & ~(0x5555555555555555UL)) == 0) { /* Busy bits will not clear, continue instead * of freezing up on this cpu. */ @@ -543,6 +526,9 @@ int wait; }; +static spinlock_t call_lock = SPIN_LOCK_UNLOCKED; +static struct call_data_struct *call_data; + extern unsigned long xcall_call_function; int smp_call_function(void (*func)(void *info), void *info, @@ -550,6 +536,7 @@ { struct call_data_struct data; int cpus = smp_num_cpus - 1; + long timeout; if (!cpus) return 0; @@ -559,19 +546,36 @@ atomic_set(&data.finished, 0); data.wait = wait; - smp_cross_call(&xcall_call_function, - 0, (u64) &data, 0); + spin_lock_bh(&call_lock); + + call_data = &data; + + smp_cross_call(&xcall_call_function, 0, 0, 0); + /* * Wait for other cpus to complete function or at * least snap the call data. */ - while (atomic_read(&data.finished) != cpus) + timeout = 1000000; + while (atomic_read(&data.finished) != cpus) { + if (--timeout <= 0) + goto out_timeout; barrier(); + udelay(1); + } + + spin_unlock_bh(&call_lock); return 0; + +out_timeout: + spin_unlock_bh(&call_lock); + printk("XCALL: Remote cpus not responding, ncpus=%d finished=%d\n", + smp_num_cpus - 1, atomic_read(&data.finished)); + return 0; } -void smp_call_function_client(struct call_data_struct *call_data) +void smp_call_function_client(void) { void (*func) (void *info) = call_data->func; void *info = call_data->info; @@ -598,7 +602,7 @@ extern unsigned long xcall_flush_dcache_page_cheetah; extern unsigned long xcall_flush_dcache_page_spitfire; -#ifdef DCFLUSH_DEBUG +#ifdef CONFIG_DEBUG_DCFLUSH extern atomic_t dcpage_flushes; extern atomic_t dcpage_flushes_xcall; #endif @@ -621,7 +625,7 @@ if (smp_processors_ready) { unsigned long mask = 1UL << cpu; -#ifdef DCFLUSH_DEBUG +#ifdef CONFIG_DEBUG_DCFLUSH atomic_inc(&dcpage_flushes); #endif if (cpu == smp_processor_id()) { @@ -643,13 +647,46 @@ __pa(page->virtual), 0, mask); } -#ifdef DCFLUSH_DEBUG +#ifdef CONFIG_DEBUG_DCFLUSH atomic_inc(&dcpage_flushes_xcall); #endif } } } +void flush_dcache_page_all(struct mm_struct *mm, struct page *page) +{ + if (smp_processors_ready) { + unsigned long mask = cpu_present_map & ~(1UL << smp_processor_id()); + u64 data0; + +#ifdef CONFIG_DEBUG_DCFLUSH + atomic_inc(&dcpage_flushes); +#endif + if (mask == 0UL) + goto flush_self; + if (tlb_type == spitfire) { + data0 = ((u64)&xcall_flush_dcache_page_spitfire); + if (page->mapping != NULL) + data0 |= ((u64)1 << 32); + spitfire_xcall_deliver(data0, + __pa(page->virtual), + (u64) page->virtual, + mask); + } else { + data0 = ((u64)&xcall_flush_dcache_page_cheetah); + cheetah_xcall_deliver(data0, + __pa(page->virtual), + 0, mask); + } +#ifdef CONFIG_DEBUG_DCFLUSH + atomic_inc(&dcpage_flushes_xcall); +#endif + flush_self: + __local_flush_dcache_page(page); + } +} + void smp_receive_signal(int cpu) { if (smp_processors_ready) { @@ -1075,7 +1112,6 @@ __cpu_number_map[boot_cpu_id] = 0; prom_cpu_nodes[boot_cpu_id] = linux_cpus[0].prom_node; __cpu_logical_map[0] = boot_cpu_id; - current->processor = boot_cpu_id; prof_counter(boot_cpu_id) = prof_multiplier(boot_cpu_id) = 1; } diff -urN linux-2.5.2-pre11/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c --- linux-2.5.2-pre11/arch/sparc64/kernel/sparc64_ksyms.c Tue Oct 30 15:08:11 2001 +++ linux/arch/sparc64/kernel/sparc64_ksyms.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: sparc64_ksyms.c,v 1.116 2001/10/26 15:49:21 davem Exp $ +/* $Id: sparc64_ksyms.c,v 1.120 2001/12/21 04:56:15 davem Exp $ * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -98,7 +98,7 @@ #ifdef CONFIG_SMP extern spinlock_t kernel_flag; extern int smp_num_cpus; -#ifdef SPIN_LOCK_DEBUG +#ifdef CONFIG_DEBUG_SPINLOCK extern void _do_spin_lock (spinlock_t *lock, char *str); extern void _do_spin_unlock (spinlock_t *lock); extern int _spin_trylock (spinlock_t *lock); @@ -113,7 +113,7 @@ /* used by various drivers */ #ifdef CONFIG_SMP -#ifndef SPIN_LOCK_DEBUG +#ifndef CONFIG_DEBUG_SPINLOCK /* Out of line rw-locking implementation. */ EXPORT_SYMBOL(__read_lock); EXPORT_SYMBOL(__read_unlock); @@ -145,7 +145,7 @@ EXPORT_SYMBOL(__cpu_logical_map); /* Spinlock debugging library, optional. */ -#ifdef SPIN_LOCK_DEBUG +#ifdef CONFIG_DEBUG_SPINLOCK EXPORT_SYMBOL(_do_spin_lock); EXPORT_SYMBOL(_do_spin_unlock); EXPORT_SYMBOL(_spin_trylock); @@ -319,7 +319,6 @@ EXPORT_SYMBOL(__memcpy); EXPORT_SYMBOL(__memset); EXPORT_SYMBOL(_clear_page); -EXPORT_SYMBOL(_copy_page); EXPORT_SYMBOL(clear_user_page); EXPORT_SYMBOL(copy_user_page); EXPORT_SYMBOL(__bzero); @@ -354,4 +353,8 @@ void VISenter(void); /* RAID code needs this */ -EXPORT_SYMBOL(VISenter); +EXPORT_SYMBOL_NOVERS(VISenter); + +#ifdef CONFIG_DEBUG_BUGVERBOSE +EXPORT_SYMBOL(do_BUG); +#endif diff -urN linux-2.5.2-pre11/arch/sparc64/kernel/sys_sparc.c linux/arch/sparc64/kernel/sys_sparc.c --- linux-2.5.2-pre11/arch/sparc64/kernel/sys_sparc.c Tue Oct 30 15:08:11 2001 +++ linux/arch/sparc64/kernel/sys_sparc.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc.c,v 1.54 2001/10/28 20:49:13 davem Exp $ +/* $Id: sys_sparc.c,v 1.56 2001/12/21 04:56:15 davem Exp $ * linux/arch/sparc64/kernel/sys_sparc.c * * This file contains various random system calls that @@ -40,12 +40,15 @@ return PAGE_SIZE; } -#define COLOUR_ALIGN(addr) (((addr)+SHMLBA-1)&~(SHMLBA-1)) +#define COLOUR_ALIGN(addr,pgoff) \ + ((((addr)+SHMLBA-1)&~(SHMLBA-1)) + \ + (((pgoff)<mm, addr); ; vmm = vmm->vm_next) { @@ -81,8 +87,8 @@ if (!vmm || addr + len <= vmm->vm_start) return addr; addr = vmm->vm_end; - if (flags & MAP_SHARED) - addr = COLOUR_ALIGN(addr); + if (do_color_align) + addr = COLOUR_ALIGN(addr, pgoff); } } @@ -255,27 +261,15 @@ asmlinkage int sparc64_personality(unsigned long personality) { - unsigned long ret, trying, orig_ret; - - trying = ret = personality; + int ret; - if (current->personality == PER_LINUX32 && - trying == PER_LINUX) - trying = ret = PER_LINUX32; - - /* For PER_LINUX32 we want to retain &default_exec_domain. */ - if (trying == PER_LINUX32) + if (current->personality == PER_LINUX32 && personality == PER_LINUX) + personality = PER_LINUX32; + ret = sys_personality(personality); + if (ret == PER_LINUX32) ret = PER_LINUX; - orig_ret = ret; - ret = sys_personality(ret); - - if (orig_ret == PER_LINUX && trying == PER_LINUX32) { - current->personality = PER_LINUX32; - ret = PER_LINUX; - } - - return (int) ret; + return ret; } /* Linux version of mmap */ diff -urN linux-2.5.2-pre11/arch/sparc64/kernel/sys_sunos32.c linux/arch/sparc64/kernel/sys_sunos32.c --- linux-2.5.2-pre11/arch/sparc64/kernel/sys_sunos32.c Tue Aug 14 19:57:28 2001 +++ linux/arch/sparc64/kernel/sys_sunos32.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: sys_sunos32.c,v 1.61 2001/08/13 14:40:07 davem Exp $ +/* $Id: sys_sunos32.c,v 1.62 2002/01/08 16:00:14 davem Exp $ * sys_sunos32.c: SunOS binary compatability layer on sparc64. * * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu) @@ -68,7 +68,7 @@ struct file *file = NULL; unsigned long retval, ret_type; - if(flags & MAP_NORESERVE) { + if (flags & MAP_NORESERVE) { static int cnt; if (cnt++ < 10) printk("%s: unimplemented SunOS MAP_NORESERVE mmap() flag\n", @@ -76,15 +76,15 @@ flags &= ~MAP_NORESERVE; } retval = -EBADF; - if(!(flags & MAP_ANONYMOUS)) { + if (!(flags & MAP_ANONYMOUS)) { struct inode * inode; - if(fd >= SUNOS_NR_OPEN) + if (fd >= SUNOS_NR_OPEN) goto out; file = fget(fd); if (!file) goto out; inode = file->f_dentry->d_inode; - if(MAJOR(inode->i_rdev)==MEM_MAJOR && MINOR(inode->i_rdev)==5) { + if (minor(inode->i_rdev) == MEM_MAJOR && minor(inode->i_rdev) == 5) { flags |= MAP_ANONYMOUS; fput(file); file = NULL; @@ -92,7 +92,7 @@ } retval = -EINVAL; - if(!(flags & MAP_FIXED)) + if (!(flags & MAP_FIXED)) addr = 0; else if (len > 0xf0000000 || addr > 0xf0000000 - len) goto out_putf; @@ -106,7 +106,7 @@ (unsigned long) prot, (unsigned long) flags, (unsigned long) off); up_write(¤t->mm->mmap_sem); - if(!ret_type) + if (!ret_type) retval = ((retval < 0xf0000000) ? 0 : retval); out_putf: if (file) diff -urN linux-2.5.2-pre11/arch/sparc64/kernel/time.c linux/arch/sparc64/kernel/time.c --- linux-2.5.2-pre11/arch/sparc64/kernel/time.c Thu Sep 20 14:11:57 2001 +++ linux/arch/sparc64/kernel/time.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.40 2001/09/06 02:44:28 davem Exp $ +/* $Id: time.c,v 1.41 2001/11/20 18:24:55 kanoj Exp $ * time.c: UltraSparc timer and TOD clock support. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -609,7 +609,6 @@ unsigned long clock; init_timers(timer_interrupt, &clock); - timer_tick_offset = clock / HZ; timer_ticks_per_usec_quotient = ((1UL<<32) / (clock / 1000020)); } diff -urN linux-2.5.2-pre11/arch/sparc64/kernel/trampoline.S linux/arch/sparc64/kernel/trampoline.S --- linux-2.5.2-pre11/arch/sparc64/kernel/trampoline.S Thu Sep 20 14:11:57 2001 +++ linux/arch/sparc64/kernel/trampoline.S Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: trampoline.S,v 1.22 2001/09/07 21:04:40 kanoj Exp $ +/* $Id: trampoline.S,v 1.25 2002/01/11 08:45:38 davem Exp $ * trampoline.S: Jump start slave processors on sparc64. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -262,7 +262,7 @@ wrpr %o1, PSTATE_IG, %pstate /* Get our UPA MID. */ - lduw [%o2 + AOFF_task_processor], %g1 + lduw [%o2 + AOFF_task_cpu], %g1 sethi %hi(cpu_data), %g5 or %g5, %lo(cpu_data), %g5 diff -urN linux-2.5.2-pre11/arch/sparc64/kernel/traps.c linux/arch/sparc64/kernel/traps.c --- linux-2.5.2-pre11/arch/sparc64/kernel/traps.c Mon Oct 1 09:19:56 2001 +++ linux/arch/sparc64/kernel/traps.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: traps.c,v 1.79 2001/09/21 02:14:39 kanoj Exp $ +/* $Id: traps.c,v 1.83 2002/01/11 08:45:38 davem Exp $ * arch/sparc64/kernel/traps.c * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) @@ -38,16 +38,19 @@ void bad_trap (struct pt_regs *regs, long lvl) { + char buffer[32]; siginfo_t info; if (lvl < 0x100) { - char buffer[24]; - - sprintf (buffer, "Bad hw trap %lx at tl0\n", lvl); + sprintf(buffer, "Bad hw trap %lx at tl0\n", lvl); + die_if_kernel(buffer, regs); + } + + lvl -= 0x100; + if (regs->tstate & TSTATE_PRIV) { + sprintf(buffer, "Kernel bad sw trap %lx", lvl); die_if_kernel (buffer, regs); } - if (regs->tstate & TSTATE_PRIV) - die_if_kernel ("Kernel bad trap", regs); if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) { regs->tpc &= 0xffffffff; regs->tnpc &= 0xffffffff; @@ -56,7 +59,7 @@ info.si_errno = 0; info.si_code = ILL_ILLTRP; info.si_addr = (void *)regs->tpc; - info.si_trapno = lvl - 0x100; + info.si_trapno = lvl; force_sig_info(SIGILL, &info, current); } @@ -68,6 +71,14 @@ die_if_kernel (buffer, regs); } +#ifdef CONFIG_DEBUG_BUGVERBOSE +void do_BUG(const char *file, int line) +{ + bust_spinlocks(1); + printk("kernel BUG at %s:%d!\n", file, line); +} +#endif + void instruction_access_exception (struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) { @@ -947,6 +958,7 @@ __asm__ __volatile__("ldxa [%0] %3, %%g0\n\t" "ldxa [%1] %3, %%g0\n\t" "casxa [%2] %3, %%g0, %%g0\n\t" + "membar #StoreLoad | #StoreStore\n\t" "ldxa [%0] %3, %%g0\n\t" "ldxa [%1] %3, %%g0\n\t" "membar #Sync" @@ -1648,13 +1660,16 @@ } } +/* Only invoked on boot processor. */ void trap_init(void) { - /* Attach to the address space of init_task. */ + /* Attach to the address space of init_task. On SMP we + * do this in smp.c:smp_callin for other cpus. + */ atomic_inc(&init_mm.mm_count); current->active_mm = &init_mm; - /* NOTE: Other cpus have this done as they are started - * up on SMP. - */ +#ifdef CONFIG_SMP + current->cpu = hard_smp_processor_id(); +#endif } diff -urN linux-2.5.2-pre11/arch/sparc64/kernel/ttable.S linux/arch/sparc64/kernel/ttable.S --- linux-2.5.2-pre11/arch/sparc64/kernel/ttable.S Mon Oct 1 09:19:56 2001 +++ linux/arch/sparc64/kernel/ttable.S Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: ttable.S,v 1.35 2001/09/21 02:14:39 kanoj Exp $ +/* $Id: ttable.S,v 1.36 2001/11/28 23:32:16 davem Exp $ * ttable.S: Sparc V9 Trap Table(s) with SpitFire/Cheetah extensions. * * Copyright (C) 1996, 2001 David S. Miller (davem@caip.rutgers.edu) @@ -15,11 +15,13 @@ sparc64_ttable_tl0: tl0_resv000: BOOT_KERNEL BTRAP(0x1) BTRAP(0x2) BTRAP(0x3) tl0_resv004: BTRAP(0x4) BTRAP(0x5) BTRAP(0x6) BTRAP(0x7) -tl0_iax: TRAP_NOSAVE(__do_instruction_access_exception) +tl0_iax: membar #Sync + TRAP_NOSAVE_7INSNS(__do_instruction_access_exception) tl0_resv009: BTRAP(0x9) tl0_iae: TRAP(do_iae) tl0_resv00b: BTRAP(0xb) BTRAP(0xc) BTRAP(0xd) BTRAP(0xe) BTRAP(0xf) -tl0_ill: TRAP(do_illegal_instruction) +tl0_ill: membar #Sync + TRAP_7INSNS(do_illegal_instruction) tl0_privop: TRAP(do_privop) tl0_resv012: BTRAP(0x12) BTRAP(0x13) BTRAP(0x14) BTRAP(0x15) BTRAP(0x16) BTRAP(0x17) tl0_resv018: BTRAP(0x18) BTRAP(0x19) BTRAP(0x1a) BTRAP(0x1b) BTRAP(0x1c) BTRAP(0x1d) diff -urN linux-2.5.2-pre11/arch/sparc64/lib/atomic.S linux/arch/sparc64/lib/atomic.S --- linux-2.5.2-pre11/arch/sparc64/lib/atomic.S Thu Mar 16 11:40:17 2000 +++ linux/arch/sparc64/lib/atomic.S Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: atomic.S,v 1.3 2000/03/16 16:44:37 davem Exp $ +/* $Id: atomic.S,v 1.4 2001/11/18 00:12:56 davem Exp $ * atomic.S: These things are too big to do inline. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -19,7 +19,7 @@ cas [%o1], %g5, %g7 cmp %g5, %g7 bne,pn %icc, __atomic_add - nop + membar #StoreLoad | #StoreStore retl add %g7, %o0, %o0 @@ -30,7 +30,7 @@ cas [%o1], %g5, %g7 cmp %g5, %g7 bne,pn %icc, __atomic_sub - nop + membar #StoreLoad | #StoreStore retl sub %g7, %o0, %o0 atomic_impl_end: diff -urN linux-2.5.2-pre11/arch/sparc64/lib/bitops.S linux/arch/sparc64/lib/bitops.S --- linux-2.5.2-pre11/arch/sparc64/lib/bitops.S Fri Apr 13 20:15:55 2001 +++ linux/arch/sparc64/lib/bitops.S Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: bitops.S,v 1.2 2001/04/14 01:12:02 davem Exp $ +/* $Id: bitops.S,v 1.3 2001/11/18 00:12:56 davem Exp $ * bitops.S: Sparc64 atomic bit operations. * * Copyright (C) 2000 David S. Miller (davem@redhat.com) @@ -28,7 +28,7 @@ bne,a,pn %xcc, 1b ldx [%o1], %g7 2: retl - nop + membar #StoreLoad | #StoreStore .globl ___test_and_clear_bit ___test_and_clear_bit: /* %o0=nr, %o1=addr */ @@ -47,7 +47,7 @@ bne,a,pn %xcc, 1b ldx [%o1], %g7 2: retl - nop + membar #StoreLoad | #StoreStore .globl ___test_and_change_bit ___test_and_change_bit: /* %o0=nr, %o1=addr */ @@ -65,7 +65,7 @@ bne,a,pn %xcc, 1b ldx [%o1], %g7 2: retl - nop + membar #StoreLoad | #StoreStore nop .globl ___test_and_set_le_bit @@ -85,7 +85,7 @@ bne,a,pn %icc, 1b lduwa [%o1] ASI_PL, %g7 2: retl - nop + membar #StoreLoad | #StoreStore .globl ___test_and_clear_le_bit ___test_and_clear_le_bit: /* %o0=nr, %o1=addr */ @@ -104,7 +104,7 @@ bne,a,pn %icc, 1b lduwa [%o1] ASI_PL, %g7 2: retl - nop + membar #StoreLoad | #StoreStore .globl __bitops_end __bitops_end: diff -urN linux-2.5.2-pre11/arch/sparc64/lib/blockops.S linux/arch/sparc64/lib/blockops.S --- linux-2.5.2-pre11/arch/sparc64/lib/blockops.S Mon Oct 1 09:19:56 2001 +++ linux/arch/sparc64/lib/blockops.S Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: blockops.S,v 1.36 2001/09/24 21:44:03 davem Exp $ +/* $Id: blockops.S,v 1.41 2001/12/05 06:05:35 davem Exp $ * blockops.S: UltraSparc block zero optimized routines. * * Copyright (C) 1996, 1998, 1999, 2000 David S. Miller (davem@redhat.com) @@ -17,10 +17,9 @@ fmovd %reg4, %f56; fmovd %reg5, %f58; \ fmovd %reg6, %f60; fmovd %reg7, %f62; -#define TLBTEMP_BASE (8 * 1024 * 1024) #define DCACHE_SIZE (PAGE_SIZE * 2) -#define TLBTEMP_ENT1 (61 << 3) -#define TLBTEMP_ENT2 (62 << 3) +#define TLBTEMP_ENT1 (60 << 3) +#define TLBTEMP_ENT2 (61 << 3) #define TLBTEMP_ENTSZ (1 << 3) #if (PAGE_SHIFT == 13) || (PAGE_SHIFT == 19) @@ -34,64 +33,6 @@ .text .align 32 - .globl _copy_page - .type _copy_page,@function -_copy_page: /* %o0=dest, %o1=src */ - VISEntry - membar #LoadStore | #StoreStore | #StoreLoad - ldda [%o1] ASI_BLK_P, %f0 - add %o1, 0x40, %o1 - ldda [%o1] ASI_BLK_P, %f16 - add %o1, 0x40, %o1 - sethi %hi(PAGE_SIZE), %o2 -1: TOUCH(f0, f2, f4, f6, f8, f10, f12, f14) - ldda [%o1] ASI_BLK_P, %f32 - stda %f48, [%o0] ASI_BLK_P - add %o1, 0x40, %o1 - sub %o2, 0x40, %o2 - add %o0, 0x40, %o0 - TOUCH(f16, f18, f20, f22, f24, f26, f28, f30) - ldda [%o1] ASI_BLK_P, %f0 - stda %f48, [%o0] ASI_BLK_P - add %o1, 0x40, %o1 - sub %o2, 0x40, %o2 - add %o0, 0x40, %o0 - TOUCH(f32, f34, f36, f38, f40, f42, f44, f46) - ldda [%o1] ASI_BLK_P, %f16 - stda %f48, [%o0] ASI_BLK_P - sub %o2, 0x40, %o2 - add %o1, 0x40, %o1 - cmp %o2, PAGE_SIZE_REM - bne,pt %xcc, 1b - add %o0, 0x40, %o0 -#if (PAGE_SHIFT == 16) || (PAGE_SHIFT == 22) - TOUCH(f0, f2, f4, f6, f8, f10, f12, f14) - ldda [%o1] ASI_BLK_P, %f32 - stda %f48, [%o0] ASI_BLK_P - add %o1, 0x40, %o1 - sub %o2, 0x40, %o2 - add %o0, 0x40, %o0 - TOUCH(f16, f18, f20, f22, f24, f26, f28, f30) - ldda [%o1] ASI_BLK_P, %f0 - stda %f48, [%o0] ASI_BLK_P - add %o1, 0x40, %o1 - sub %o2, 0x40, %o2 - add %o0, 0x40, %o0 - membar #Sync - stda %f32, [%o0] ASI_BLK_P - add %o0, 0x40, %o0 - stda %f0, [%o0] ASI_BLK_P -#else - membar #Sync - stda %f0, [%o0] ASI_BLK_P - add %o0, 0x40, %o0 - stda %f16, [%o0] ASI_BLK_P -#endif - membar #Sync - VISExit - retl - nop - .globl copy_user_page .type copy_user_page,@function copy_user_page: /* %o0=dest, %o1=src, %o2=vaddr */ @@ -110,7 +51,7 @@ or %g2, %g3, %g2 add %o0, %o3, %o0 add %o0, %o1, %o1 -#define FIX_INSN_1 0x96102068 /* mov (13 << 3), %o3 */ +#define FIX_INSN_1 0x96102060 /* mov (12 << 3), %o3 */ cheetah_patch_1: mov TLBTEMP_ENT1, %o3 rdpr %pstate, %g3 @@ -134,6 +75,7 @@ stxa %g0, [%o5] ASI_DMMU membar #Sync + ldxa [%o3] ASI_DTLB_DATA_ACCESS, %g0 ldxa [%o3] ASI_DTLB_DATA_ACCESS, %o5 stxa %o0, [%o2] ASI_DMMU stxa %g1, [%o3] ASI_DTLB_DATA_ACCESS @@ -152,6 +94,7 @@ stxa %g0, [%g7] ASI_DMMU membar #Sync + ldxa [%o3] ASI_DTLB_DATA_ACCESS, %g0 ldxa [%o3] ASI_DTLB_DATA_ACCESS, %g7 stxa %o1, [%o2] ASI_DMMU stxa %g2, [%o3] ASI_DTLB_DATA_ACCESS @@ -169,9 +112,10 @@ nop cheetah_copy_user_page: - mov 121, %o2 ! A0 Group + sethi %hi((PAGE_SIZE/64)-7), %o2 ! A0 Group prefetch [%o1 + 0x000], #one_read ! MS - prefetch [%o1 + 0x040], #one_read ! MS Group + or %o2, %lo((PAGE_SIZE/64)-7), %o2 ! A1 Group + prefetch [%o1 + 0x040], #one_read ! MS prefetch [%o1 + 0x080], #one_read ! MS Group prefetch [%o1 + 0x0c0], #one_read ! MS Group ldd [%o1 + 0x000], %f0 ! MS Group @@ -402,7 +346,7 @@ or %g3, (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W), %g3 or %g1, %g3, %g1 add %o0, %o3, %o0 -#define FIX_INSN_2 0x96102070 /* mov (14 << 3), %o3 */ +#define FIX_INSN_2 0x96102068 /* mov (13 << 3), %o3 */ cheetah_patch_2: mov TLBTEMP_ENT2, %o3 rdpr %pstate, %g3 @@ -420,6 +364,7 @@ stxa %g0, [%g7] ASI_DMMU membar #Sync + ldxa [%o3] ASI_DTLB_DATA_ACCESS, %g0 ldxa [%o3] ASI_DTLB_DATA_ACCESS, %g7 stxa %o0, [%o2] ASI_DMMU stxa %g1, [%o3] ASI_DTLB_DATA_ACCESS @@ -430,8 +375,9 @@ clear_page_common: membar #StoreLoad | #StoreStore | #LoadStore ! LSU Group fzero %f0 ! FPA Group - mov PAGE_SIZE/256, %o1 ! IEU0 + sethi %hi(PAGE_SIZE/256), %o1 ! IEU0 fzero %f2 ! FPA Group + or %o1, %lo(PAGE_SIZE/256), %o1 ! IEU0 faddd %f0, %f2, %f4 ! FPA Group fmuld %f0, %f2, %f6 ! FPM faddd %f0, %f2, %f8 ! FPA Group diff -urN linux-2.5.2-pre11/arch/sparc64/lib/debuglocks.c linux/arch/sparc64/lib/debuglocks.c --- linux-2.5.2-pre11/arch/sparc64/lib/debuglocks.c Thu Apr 26 22:17:25 2001 +++ linux/arch/sparc64/lib/debuglocks.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: debuglocks.c,v 1.6 2001/04/24 01:09:12 davem Exp $ +/* $Id: debuglocks.c,v 1.9 2001/11/17 00:10:48 davem Exp $ * debuglocks.c: Debugging versions of SMP locking primitives. * * Copyright (C) 1998 David S. Miller (davem@redhat.com) @@ -10,10 +10,7 @@ #include #include -#ifdef CONFIG_SMP - -/* To enable this code, just define SPIN_LOCK_DEBUG in asm/spinlock.h */ -#ifdef SPIN_LOCK_DEBUG +#if defined(CONFIG_SMP) && defined(CONFIG_DEBUG_SPINLOCK) #define GET_CALLER(PC) __asm__ __volatile__("mov %%i7, %0" : "=r" (PC)) @@ -56,6 +53,7 @@ unsigned long caller, val; int stuck = INIT_STUCK; int cpu = smp_processor_id(); + int shown = 0; GET_CALLER(caller); again: @@ -67,7 +65,8 @@ if (val) { while (lock->lock) { if (!--stuck) { - show(str, lock, caller); + if (shown++ <= 2) + show(str, lock, caller); stuck = INIT_STUCK; } membar("#LoadLoad"); @@ -76,6 +75,8 @@ } lock->owner_pc = ((unsigned int)caller); lock->owner_cpu = cpu; + current->thread.smp_lock_count++; + current->thread.smp_lock_pc = ((unsigned int)caller); } int _spin_trylock(spinlock_t *lock) @@ -92,6 +93,8 @@ if (!val) { lock->owner_pc = ((unsigned int)caller); lock->owner_cpu = cpu; + current->thread.smp_lock_count++; + current->thread.smp_lock_pc = ((unsigned int)caller); } return val == 0; } @@ -102,6 +105,7 @@ lock->owner_cpu = NO_PROC_ID; membar("#StoreStore | #LoadStore"); lock->lock = 0; + current->thread.smp_lock_count--; } /* Keep INIT_STUCK the same... */ @@ -111,13 +115,15 @@ unsigned long caller, val; int stuck = INIT_STUCK; int cpu = smp_processor_id(); + int shown = 0; GET_CALLER(caller); wlock_again: /* Wait for any writer to go away. */ while (((long)(rw->lock)) < 0) { if (!--stuck) { - show_read(str, rw, caller); + if (shown++ <= 2) + show_read(str, rw, caller); stuck = INIT_STUCK; } membar("#LoadLoad"); @@ -137,6 +143,8 @@ if (val) goto wlock_again; rw->reader_pc[cpu] = ((unsigned int)caller); + current->thread.smp_lock_count++; + current->thread.smp_lock_pc = ((unsigned int)caller); } void _do_read_unlock (rwlock_t *rw, char *str) @@ -144,11 +152,13 @@ unsigned long caller, val; int stuck = INIT_STUCK; int cpu = smp_processor_id(); + int shown = 0; GET_CALLER(caller); /* Drop our identity _first_. */ rw->reader_pc[cpu] = 0; + current->thread.smp_lock_count--; runlock_again: /* Spin trying to decrement the counter using casx. */ __asm__ __volatile__( @@ -162,7 +172,8 @@ : "g5", "g7", "memory"); if (val) { if (!--stuck) { - show_read(str, rw, caller); + if (shown++ <= 2) + show_read(str, rw, caller); stuck = INIT_STUCK; } goto runlock_again; @@ -174,13 +185,15 @@ unsigned long caller, val; int stuck = INIT_STUCK; int cpu = smp_processor_id(); + int shown = 0; GET_CALLER(caller); wlock_again: /* Spin while there is another writer. */ while (((long)rw->lock) < 0) { if (!--stuck) { - show_write(str, rw, caller); + if (shown++ <= 2) + show_write(str, rw, caller); stuck = INIT_STUCK; } membar("#LoadLoad"); @@ -204,7 +217,8 @@ if (val) { /* We couldn't get the write bit. */ if (!--stuck) { - show_write(str, rw, caller); + if (shown++ <= 2) + show_write(str, rw, caller); stuck = INIT_STUCK; } goto wlock_again; @@ -214,7 +228,8 @@ * lock, spin, and try again. */ if (!--stuck) { - show_write(str, rw, caller); + if (shown++ <= 2) + show_write(str, rw, caller); stuck = INIT_STUCK; } __asm__ __volatile__( @@ -231,7 +246,8 @@ : "g3", "g5", "g7", "cc", "memory"); while(rw->lock != 0) { if (!--stuck) { - show_write(str, rw, caller); + if (shown++ <= 2) + show_write(str, rw, caller); stuck = INIT_STUCK; } membar("#LoadLoad"); @@ -242,18 +258,22 @@ /* We have it, say who we are. */ rw->writer_pc = ((unsigned int)caller); rw->writer_cpu = cpu; + current->thread.smp_lock_count++; + current->thread.smp_lock_pc = ((unsigned int)caller); } void _do_write_unlock(rwlock_t *rw) { unsigned long caller, val; int stuck = INIT_STUCK; + int shown = 0; GET_CALLER(caller); /* Drop our identity _first_ */ rw->writer_pc = 0; rw->writer_cpu = NO_PROC_ID; + current->thread.smp_lock_count--; wlock_again: __asm__ __volatile__( " mov 1, %%g3\n" @@ -268,12 +288,21 @@ : "g3", "g5", "g7", "memory"); if (val) { if (!--stuck) { - show_write("write_unlock", rw, caller); + if (shown++ <= 2) + show_write("write_unlock", rw, caller); stuck = INIT_STUCK; } goto wlock_again; } } -#endif /* SPIN_LOCK_DEBUG */ -#endif /* CONFIG_SMP */ +int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) +{ + spin_lock(lock); + if (atomic_dec_and_test(atomic)) + return 1; + spin_unlock(lock); + return 0; +} + +#endif /* CONFIG_SMP && CONFIG_DEBUG_SPINLOCK */ diff -urN linux-2.5.2-pre11/arch/sparc64/lib/dec_and_lock.S linux/arch/sparc64/lib/dec_and_lock.S --- linux-2.5.2-pre11/arch/sparc64/lib/dec_and_lock.S Sun Aug 13 12:01:54 2000 +++ linux/arch/sparc64/lib/dec_and_lock.S Mon Jan 14 18:28:28 2002 @@ -1,10 +1,12 @@ -/* $Id: dec_and_lock.S,v 1.2 2000/08/13 18:24:12 davem Exp $ +/* $Id: dec_and_lock.S,v 1.5 2001/11/18 00:12:56 davem Exp $ * dec_and_lock.S: Sparc64 version of "atomic_dec_and_lock()" * using cas and ldstub instructions. * * Copyright (C) 2000 David S. Miller (davem@redhat.com) */ +#include +#ifndef CONFIG_DEBUG_SPINLOCK .text .align 64 @@ -34,13 +36,15 @@ bne,pn %icc, loop1 mov 0, %g1 -out: retl +out: + membar #StoreLoad | #StoreStore + retl mov %g1, %o0 -to_zero:ldstub [%o1], %g3 +to_zero: + ldstub [%o1], %g3 brnz,pn %g3, spin_on_lock membar #StoreLoad | #StoreStore loop2: cas [%o0], %g5, %g7 /* ASSERT(g7 == 0) */ - nop cmp %g5, %g7 be,pt %icc, out @@ -61,3 +65,5 @@ ba,pt %xcc, to_zero nop nop + +#endif /* !(CONFIG_DEBUG_SPINLOCK) */ diff -urN linux-2.5.2-pre11/arch/sparc64/mm/extable.c linux/arch/sparc64/mm/extable.c --- linux-2.5.2-pre11/arch/sparc64/mm/extable.c Tue Aug 7 08:30:50 2001 +++ linux/arch/sparc64/mm/extable.c Mon Jan 14 18:28:28 2002 @@ -11,35 +11,49 @@ static unsigned long search_one_table(const struct exception_table_entry *start, - const struct exception_table_entry *last, + const struct exception_table_entry *end, unsigned long value, unsigned long *g2) { - const struct exception_table_entry *first = start; - const struct exception_table_entry *mid; - long diff = 0; - while (first <= last) { - mid = (last - first) / 2 + first; - diff = mid->insn - value; - if (diff == 0) { - if (!mid->fixup) { - *g2 = 0; - return (mid + 1)->fixup; - } else - return mid->fixup; - } else if (diff < 0) - first = mid+1; - else - last = mid-1; - } - if (last->insn < value && !last->fixup && last[1].insn > value) { - *g2 = (value - last->insn)/4; - return last[1].fixup; - } - if (first > start && first[-1].insn < value - && !first[-1].fixup && first->insn < value) { - *g2 = (value - first[-1].insn)/4; - return first->fixup; - } + const struct exception_table_entry *walk; + + /* Single insn entries are encoded as: + * word 1: insn address + * word 2: fixup code address + * + * Range entries are encoded as: + * word 1: first insn address + * word 2: 0 + * word 3: last insn address + 4 bytes + * word 4: fixup code address + * + * See asm/uaccess.h for more details. + */ + + /* 1. Try to find an exact match. */ + for (walk = start; walk <= end; walk++) { + if (walk->fixup == 0) { + /* A range entry, skip both parts. */ + walk++; + continue; + } + + if (walk->insn == value) + return walk->fixup; + } + + /* 2. Try to find a range match. */ + for (walk = start; walk <= (end - 1); walk++) { + if (walk->fixup) + continue; + + if (walk[0].insn <= value && + walk[1].insn > value) { + *g2 = (value - walk[0].insn) / 4; + return walk[1].fixup; + } + walk++; + } + return 0; } diff -urN linux-2.5.2-pre11/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c --- linux-2.5.2-pre11/arch/sparc64/mm/init.c Tue Nov 13 09:16:05 2001 +++ linux/arch/sparc64/mm/init.c Mon Jan 14 18:28:28 2002 @@ -111,7 +111,7 @@ extern void __update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); -#ifdef DCFLUSH_DEBUG +#ifdef CONFIG_DEBUG_DCFLUSH atomic_t dcpage_flushes = ATOMIC_INIT(0); #ifdef CONFIG_SMP atomic_t dcpage_flushes_xcall = ATOMIC_INIT(0); @@ -120,7 +120,7 @@ __inline__ void flush_dcache_page_impl(struct page *page) { -#ifdef DCFLUSH_DEBUG +#ifdef CONFIG_DEBUG_DCFLUSH atomic_inc(&dcpage_flushes); #endif @@ -152,7 +152,7 @@ "casx [%2], %%g7, %%g5\n\t" "cmp %%g7, %%g5\n\t" "bne,pn %%xcc, 1b\n\t" - " nop" + " membar #StoreLoad | #StoreStore" : /* no outputs */ : "r" (mask), "r" (non_cpu_bits), "r" (&page->flags) : "g5", "g7"); @@ -172,7 +172,7 @@ "casx [%2], %%g7, %%g5\n\t" "cmp %%g7, %%g5\n\t" "bne,pn %%xcc, 1b\n\t" - " nop\n" + " membar #StoreLoad | #StoreStore\n" "2:" : /* no outputs */ : "r" (cpu), "r" (mask), "r" (&page->flags) @@ -261,14 +261,14 @@ else seq_printf(m, "MMU Type\t: ???\n"); -#ifdef DCFLUSH_DEBUG +#ifdef CONFIG_DEBUG_DCFLUSH seq_printf(m, "DCPageFlushes\t: %d\n", atomic_read(&dcpage_flushes)); #ifdef CONFIG_SMP seq_printf(m, "DCPageFlushesXC\t: %d\n", atomic_read(&dcpage_flushes_xcall)); #endif /* CONFIG_SMP */ -#endif /* DCFLUSH_DEBUG */ +#endif /* CONFIG_DEBUG_DCFLUSH */ } struct linux_prom_translation { diff -urN linux-2.5.2-pre11/arch/sparc64/mm/ultra.S linux/arch/sparc64/mm/ultra.S --- linux-2.5.2-pre11/arch/sparc64/mm/ultra.S Tue Nov 13 09:16:05 2001 +++ linux/arch/sparc64/mm/ultra.S Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: ultra.S,v 1.68 2001/11/09 14:59:19 davem Exp $ +/* $Id: ultra.S,v 1.70 2001/11/29 16:42:10 kanoj Exp $ * ultra.S: Don't expand these all over the place... * * Copyright (C) 1997, 2000 David S. Miller (davem@redhat.com) @@ -117,7 +117,7 @@ wrpr %g1, PSTATE_IE, %pstate mov TLB_TAG_ACCESS, %g3 /* XXX Spitfire dependency... */ - mov (62 << 3), %g2 + mov ((SPITFIRE_HIGHEST_LOCKED_TLBENT-1) << 3), %g2 /* Spitfire Errata #32 workaround. */ mov 0x8, %o4 @@ -642,7 +642,7 @@ stx %g0, [%g4 + %lo(errata32_hwbug)] 2: add %g2, 1, %g2 - cmp %g2, 63 + cmp %g2, SPITFIRE_HIGHEST_LOCKED_TLBENT ble,pt %icc, 1b sll %g2, 3, %g3 flush %g6 @@ -679,20 +679,15 @@ .globl xcall_call_function xcall_call_function: - mov TLB_TAG_ACCESS, %g5 ! wheee... - stxa %g1, [%g5] ASI_IMMU ! save call_data here for a bit - membar #Sync rdpr %pstate, %g2 wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate - mov TLB_TAG_ACCESS, %g2 - ldxa [%g2] ASI_IMMU, %g5 rdpr %pil, %g2 wrpr %g0, 15, %pil sethi %hi(109f), %g7 b,pt %xcc, etrap_irq 109: or %g7, %lo(109b), %g7 call smp_call_function_client - mov %l5, %o0 + nop b,pt %xcc, rtrap clr %l6 diff -urN linux-2.5.2-pre11/arch/sparc64/solaris/fs.c linux/arch/sparc64/solaris/fs.c --- linux-2.5.2-pre11/arch/sparc64/solaris/fs.c Thu Sep 20 14:11:57 2001 +++ linux/arch/sparc64/solaris/fs.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: fs.c,v 1.25 2001/09/19 00:04:30 davem Exp $ +/* $Id: fs.c,v 1.26 2002/01/08 16:00:21 davem Exp $ * fs.c: fs related syscall emulation for Solaris * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -429,7 +429,7 @@ __put_user (s.f_files, &ss->f_files) || __put_user (s.f_ffree, &ss->f_ffree) || __put_user (s.f_ffree, &ss->f_favail) || - __put_user (R4_DEV(inode->i_sb->s_dev), &ss->f_fsid) || + __put_user (R4_DEV(kdev_t_to_nr(inode->i_sb->s_dev)), &ss->f_fsid) || __copy_to_user (ss->f_basetype,p,j) || __put_user (0, (char *)&ss->f_basetype[j]) || __put_user (s.f_namelen, &ss->f_namemax) || @@ -463,7 +463,7 @@ __put_user (s.f_files, &ss->f_files) || __put_user (s.f_ffree, &ss->f_ffree) || __put_user (s.f_ffree, &ss->f_favail) || - __put_user (R4_DEV(inode->i_sb->s_dev), &ss->f_fsid) || + __put_user (R4_DEV(kdev_t_to_nr(inode->i_sb->s_dev)), &ss->f_fsid) || __copy_to_user (ss->f_basetype,p,j) || __put_user (0, (char *)&ss->f_basetype[j]) || __put_user (s.f_namelen, &ss->f_namemax) || diff -urN linux-2.5.2-pre11/arch/sparc64/solaris/misc.c linux/arch/sparc64/solaris/misc.c --- linux-2.5.2-pre11/arch/sparc64/solaris/misc.c Thu Sep 20 14:11:57 2001 +++ linux/arch/sparc64/solaris/misc.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: misc.c,v 1.33 2001/09/18 22:29:06 davem Exp $ +/* $Id: misc.c,v 1.35 2002/01/08 16:00:21 davem Exp $ * misc.c: Miscelaneous syscall emulation for Solaris * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -74,8 +75,8 @@ goto out; else { struct inode * inode = file->f_dentry->d_inode; - if(MAJOR(inode->i_rdev) == MEM_MAJOR && - MINOR(inode->i_rdev) == 5) { + if(major(inode->i_rdev) == MEM_MAJOR && + minor(inode->i_rdev) == 5) { flags |= MAP_ANONYMOUS; fput(file); file = NULL; diff -urN linux-2.5.2-pre11/arch/sparc64/solaris/socksys.c linux/arch/sparc64/solaris/socksys.c --- linux-2.5.2-pre11/arch/sparc64/solaris/socksys.c Fri Nov 30 08:26:04 2001 +++ linux/arch/sparc64/solaris/socksys.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: socksys.c,v 1.18 2001/02/13 01:16:44 davem Exp $ +/* $Id: socksys.c,v 1.20 2002/01/08 16:00:21 davem Exp $ * socksys.c: /dev/inet/ stuff for Solaris emulation. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -61,14 +61,14 @@ (int (*)(int,int,int))SUNOS(97); struct sol_socket_struct * sock; - family = ((MINOR(inode->i_rdev) >> 4) & 0xf); + family = ((minor(inode->i_rdev) >> 4) & 0xf); switch (family) { case AF_UNIX: type = SOCK_STREAM; protocol = 0; break; case AF_INET: - protocol = af_inet_protocols[MINOR(inode->i_rdev) & 0xf]; + protocol = af_inet_protocols[minor(inode->i_rdev) & 0xf]; switch (protocol) { case IPPROTO_TCP: type = SOCK_STREAM; break; case IPPROTO_UDP: type = SOCK_DGRAM; break; diff -urN linux-2.5.2-pre11/arch/sparc64/solaris/timod.c linux/arch/sparc64/solaris/timod.c --- linux-2.5.2-pre11/arch/sparc64/solaris/timod.c Mon Dec 10 13:52:53 2001 +++ linux/arch/sparc64/solaris/timod.c Mon Jan 14 18:28:28 2002 @@ -1,4 +1,4 @@ -/* $Id: timod.c,v 1.16 2001/09/18 22:29:06 davem Exp $ +/* $Id: timod.c,v 1.18 2002/01/08 16:00:21 davem Exp $ * timod.c: timod emulation. * * Copyright (C) 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz) @@ -921,7 +921,7 @@ if (!ino) goto out; if (!ino->i_sock && - (MAJOR(ino->i_rdev) != 30 || MINOR(ino->i_rdev) != 1)) + (major(ino->i_rdev) != 30 || minor(ino->i_rdev) != 1)) goto out; ctlptr = (struct strbuf *)A(arg1); diff -urN linux-2.5.2-pre11/drivers/block/Config.in linux/drivers/block/Config.in --- linux-2.5.2-pre11/drivers/block/Config.in Fri Sep 14 14:04:06 2001 +++ linux/drivers/block/Config.in Mon Jan 14 18:28:28 2002 @@ -35,6 +35,7 @@ fi dep_tristate 'Compaq SMART2 support' CONFIG_BLK_CPQ_DA $CONFIG_PCI dep_tristate 'Compaq Smart Array 5xxx support' CONFIG_BLK_CPQ_CISS_DA $CONFIG_PCI +dep_mbool ' SCSI tape drive support for Smart Array 5xxx' CONFIG_CISS_SCSI_TAPE $CONFIG_BLK_CPQ_CISS_DA $CONFIG_SCSI dep_tristate 'Mylex DAC960/DAC1100 PCI RAID Controller support' CONFIG_BLK_DEV_DAC960 $CONFIG_PCI tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP diff -urN linux-2.5.2-pre11/drivers/block/cciss.c linux/drivers/block/cciss.c --- linux-2.5.2-pre11/drivers/block/cciss.c Mon Jan 14 18:28:22 2002 +++ linux/drivers/block/cciss.c Mon Jan 14 18:28:28 2002 @@ -126,6 +126,8 @@ revalidate: frevalidate_logvol, }; +#include "cciss_scsi.c" /* For SCSI tape support */ + /* * Report information about this controller. */ @@ -160,6 +162,7 @@ h->Qdepth, h->maxQsinceinit, h->max_outstanding, h->maxSG); pos += size; len += size; + cciss_proc_tape_report(ctlr, buffer, &pos, &len); for(i=0; inum_luns; i++) { drv = &h->drv[i]; size = sprintf(buffer+len, "cciss/c%dd%d: blksz=%d nr_blocks=%d\n", @@ -179,20 +182,53 @@ return len; } +static int +cciss_proc_write(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + unsigned char cmd[80]; + int len; +#ifdef CONFIG_CISS_SCSI_TAPE + ctlr_info_t *h = (ctlr_info_t *) data; + int rc; +#endif + + if (count > sizeof(cmd)-1) return -EINVAL; + if (copy_from_user(cmd, buffer, count)) return -EFAULT; + cmd[count] = '\0'; + len = strlen(cmd); // above 3 lines ensure safety + if (cmd[len-1] == '\n') + cmd[--len] = '\0'; +# ifdef CONFIG_CISS_SCSI_TAPE + if (strcmp("engage scsi", cmd)==0) { + rc = cciss_engage_scsi(h->ctlr); + if (rc != 0) return -rc; + return count; + } + /* might be nice to have "disengage" too, but it's not + safely possible. (only 1 module use count, lock issues.) */ +# endif + return -EINVAL; +} + /* * Get us a file in /proc/cciss that says something about each controller. * Create /proc/cciss if it doesn't exist yet. */ static void __init cciss_procinit(int i) { + struct proc_dir_entry *pde; + if (proc_cciss == NULL) { proc_cciss = proc_mkdir("cciss", proc_root_driver); if (!proc_cciss) return; } - create_proc_read_entry(hba[i]->devname, 0, proc_cciss, - cciss_proc_get_info, hba[i]); + pde = create_proc_read_entry(hba[i]->devname, + S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH, + proc_cciss, cciss_proc_get_info, hba[i]); + pde->write_proc = cciss_proc_write; } #endif /* CONFIG_PROC_FS */ @@ -824,9 +860,12 @@ int ctlr, void *buff, size_t size, - unsigned int use_unit_num, + unsigned int use_unit_num, /* 0: address the controller, + 1: address logical volume log_unit, + 2: periph device address is scsi3addr */ unsigned int log_unit, - __u8 page_code ) + __u8 page_code, + unsigned char *scsi3addr) { CommandList_struct *c; int i; @@ -860,15 +899,23 @@ to controller so It's a physical command mode = 0 target = 0. So we have nothing to write. - Otherwise - mode = 1 target = LUNID + otherwise, if use_unit_num == 1, + mode = 1(volume set addressing) target = LUNID + otherwise, if use_unit_num == 2, + mode = 0(periph dev addr) target = scsi3addr */ - if(use_unit_num != 0) + if(use_unit_num == 1) { c->Header.LUN.LogDev.VolId= hba[ctlr]->drv[log_unit].LunID; c->Header.LUN.LogDev.Mode = 1; } + else if (use_unit_num == 2) + { + memcpy(c->Header.LUN.LunAddrBytes,scsi3addr,8); + c->Header.LUN.LogDev.Mode = 0; // phys dev addr + } + /* are we trying to read a vital product page */ if(page_code != 0) { @@ -884,6 +931,7 @@ c->Request.CDB[4] = size & 0xFF; break; case CISS_REPORT_LOG: + case CISS_REPORT_PHYS: /* Talking to controller so It's a physical command mode = 00 target = 0. So we have nothing to write. @@ -893,7 +941,7 @@ c->Request.Type.Attribute = ATTR_SIMPLE; c->Request.Type.Direction = XFER_READ; // Read c->Request.Timeout = 0; // Don't time out - c->Request.CDB[0] = CISS_REPORT_LOG; + c->Request.CDB[0] = cmd; c->Request.CDB[6] = (size >> 24) & 0xFF; //MSB c->Request.CDB[7] = (size >> 16) & 0xFF; c->Request.CDB[8] = (size >> 8) & 0xFF; @@ -971,6 +1019,7 @@ ignore it */ if (((c->Request.CDB[0] == CISS_REPORT_LOG) || + (c->Request.CDB[0] == CISS_REPORT_PHYS) || (c->Request.CDB[0] == CISS_INQUIRY)) && ((c->err_info->CommandStatus == CMD_DATA_OVERRUN) || @@ -1356,6 +1405,10 @@ } else if (c->cmd_type == CMD_IOCTL_PEND) { c->cmd_type = CMD_IOCTL_DONE; } +# ifdef CONFIG_CISS_SCSI_TAPE + else if (c->cmd_type == CMD_SCSI) + complete_scsi_command(c, 0, a1); +# endif continue; } } @@ -1592,7 +1645,7 @@ } /* Get the firmware version */ return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff, - sizeof(InquiryData_struct), 0, 0 ,0 ); + sizeof(InquiryData_struct), 0, 0 ,0, NULL ); if (return_code == IO_OK) { hba[cntl_num]->firm_ver[0] = inq_buff->data_byte[32]; @@ -1606,7 +1659,7 @@ } /* Get the number of logical volumes */ return_code = sendcmd(CISS_REPORT_LOG, cntl_num, ld_buff, - sizeof(ReportLunData_struct), 0, 0, 0 ); + sizeof(ReportLunData_struct), 0, 0, 0, NULL ); if( return_code == IO_OK) { @@ -1652,7 +1705,7 @@ memset(size_buff, 0, sizeof(ReadCapdata_struct)); return_code = sendcmd(CCISS_READ_CAPACITY, cntl_num, size_buff, - sizeof( ReadCapdata_struct), 1, i, 0 ); + sizeof( ReadCapdata_struct), 1, i, 0, NULL ); if (return_code == IO_OK) { total_size = (0xff & @@ -1684,7 +1737,7 @@ /* Execute the command to read the disk geometry */ memset(inq_buff, 0, sizeof(InquiryData_struct)); return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff, - sizeof(InquiryData_struct), 1, i ,0xC1 ); + sizeof(InquiryData_struct), 1, i ,0xC1, NULL ); if (return_code == IO_OK) { if(inq_buff->data_byte[8] == 0xFF) @@ -1860,6 +1913,8 @@ cciss_getgeometry(i); + cciss_find_non_disk_devices(i); /* find our tape drives, if any */ + /* Turn the interrupts on so we can service requests */ hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON); @@ -1901,6 +1956,8 @@ MAX_PART, &cciss_fops, hba[i]->drv[j].nr_blocks); + cciss_register_scsi(i, 1); /* hook ourself into SCSI subsystem */ + return(1); } @@ -1927,6 +1984,7 @@ free_irq(hba[i]->intr, hba[i]); pci_set_drvdata(pdev, NULL); iounmap((void*)hba[i]->vaddr); + cciss_unregister_scsi(i); /* unhook from SCSI subsystem */ unregister_blkdev(MAJOR_NR+i, hba[i]->devname); remove_proc_entry(hba[i]->devname, proc_cciss); diff -urN linux-2.5.2-pre11/drivers/block/cciss.h linux/drivers/block/cciss.h --- linux-2.5.2-pre11/drivers/block/cciss.h Mon Jan 14 18:28:22 2002 +++ linux/drivers/block/cciss.h Mon Jan 14 18:28:28 2002 @@ -83,6 +83,9 @@ struct hd_struct hd[256]; int sizes[256]; int blocksizes[256]; +#ifdef CONFIG_CISS_SCSI_TAPE + void *scsi_ctlr; /* ptr to structure containing scsi related stuff */ +#endif }; /* Defining the diffent access_menthods */ diff -urN linux-2.5.2-pre11/drivers/block/cciss_cmd.h linux/drivers/block/cciss_cmd.h --- linux-2.5.2-pre11/drivers/block/cciss_cmd.h Mon Jan 14 18:28:22 2002 +++ linux/drivers/block/cciss_cmd.h Mon Jan 14 18:28:28 2002 @@ -89,6 +89,7 @@ //STRUCTURES //########################################################################### #define CISS_MAX_LUN 16 +#define CISS_MAX_PHYS_LUN 1024 // SCSI-3 Cmmands #pragma pack(1) @@ -101,6 +102,7 @@ } InquiryData_struct; #define CISS_REPORT_LOG 0xc2 /* Report Logical LUNs */ +#define CISS_REPORT_PHYS 0xc3 /* Report Physical LUNs */ // Data returned typedef struct _ReportLUNdata_struct { @@ -215,6 +217,9 @@ #define CMD_RWREQ 0x00 #define CMD_IOCTL_PEND 0x01 #define CMD_IOCTL_DONE 0x02 +#define CMD_SCSI 0x03 +#define CMD_MSG_DONE 0x04 +#define CMD_MSG_TIMEOUT 0x05 typedef struct _CommandList_struct { CommandListHeader_struct Header; @@ -229,6 +234,9 @@ struct _CommandList_struct *prev; struct _CommandList_struct *next; struct request * rq; +#ifdef CONFIG_CISS_SCSI_TAPE + void * scsi_cmd; +#endif } CommandList_struct; //Configuration Table Structure diff -urN linux-2.5.2-pre11/drivers/block/cciss_scsi.c linux/drivers/block/cciss_scsi.c --- linux-2.5.2-pre11/drivers/block/cciss_scsi.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/block/cciss_scsi.c Mon Jan 14 18:28:28 2002 @@ -0,0 +1,1634 @@ +/* + * Disk Array driver for Compaq SA53xx Controllers, SCSI Tape module + * Copyright 2001 Compaq Computer Corporation + * + * 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. + * + * Questions/Comments/Bugfixes to arrays@compaq.com + * + * Author: Stephen M. Cameron + */ +#ifdef CONFIG_CISS_SCSI_TAPE + +/* Here we have code to present the driver as a scsi driver + as it is simultaneously presented as a block driver. The + reason for doing this is to allow access to SCSI tape drives + through the array controller. Note in particular, neither + physical nor logical disks are presented through the scsi layer. */ + +#include "../scsi/scsi.h" +#include "../scsi/hosts.h" +#include +#include + +#include "cciss_scsi.h" + +/* some prototypes... */ +static int sendcmd( + __u8 cmd, + int ctlr, + void *buff, + size_t size, + unsigned int use_unit_num, /* 0: address the controller, + 1: address logical volume log_unit, + 2: address is in scsi3addr */ + unsigned int log_unit, + __u8 page_code, + unsigned char *scsi3addr ); + + +int __init cciss_scsi_detect(Scsi_Host_Template *tpnt); +int cciss_scsi_release(struct Scsi_Host *sh); +const char *cciss_scsi_info(struct Scsi_Host *sa); + +int cciss_scsi_proc_info( + char *buffer, /* data buffer */ + char **start, /* where data in buffer starts */ + off_t offset, /* offset from start of imaginary file */ + int length, /* length of data in buffer */ + int hostnum, /* which host adapter (always zero for me) */ + int func); /* 0 == read, 1 == write */ + +int cciss_scsi_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)); +#if 0 +int cciss_scsi_abort(Scsi_Cmnd *cmd); +#if defined SCSI_RESET_SYNCHRONOUS && defined SCSI_RESET_ASYNCHRONOUS +int cciss_scsi_reset(Scsi_Cmnd *cmd, unsigned int reset_flags); +#else +int cciss_scsi_reset(Scsi_Cmnd *cmd); +#endif +#endif + +static struct cciss_scsi_hba_t ccissscsi[MAX_CTLR] = { + { name: "cciss0", ndevices: 0 }, + { name: "cciss1", ndevices: 0 }, + { name: "cciss2", ndevices: 0 }, + { name: "cciss3", ndevices: 0 }, + { name: "cciss4", ndevices: 0 }, + { name: "cciss5", ndevices: 0 }, + { name: "cciss6", ndevices: 0 }, + { name: "cciss7", ndevices: 0 }, +}; + +/* We need one Scsi_Host_Template *per controller* instead of + the usual one Scsi_Host_Template per controller *type*. This + is so PCI hot plug could have a remote possibility of still + working even with the SCSI system. It's so + scsi_unregister_host will differentiate the controllers. + When register_scsi_module is called, each host template is + customized (name change) in cciss_register_scsi() + (that's called from cciss.c:cciss_init_one()) */ + +static +Scsi_Host_Template driver_template[MAX_CTLR] = +{ + CCISS_SCSI, CCISS_SCSI, CCISS_SCSI, CCISS_SCSI, + CCISS_SCSI, CCISS_SCSI, CCISS_SCSI, CCISS_SCSI, +}; + +#pragma pack(1) +struct cciss_scsi_cmd_stack_elem_t { + CommandList_struct cmd; + ErrorInfo_struct Err; + __u32 busaddr; +}; + +#pragma pack() + +#define CMD_STACK_SIZE (SCSI_CCISS_CAN_QUEUE * \ + CCISS_MAX_SCSI_DEVS_PER_HBA + 2) + // plus two for init time usage + +#pragma pack(1) +struct cciss_scsi_cmd_stack_t { + struct cciss_scsi_cmd_stack_elem_t *pool; + struct cciss_scsi_cmd_stack_elem_t *elem[CMD_STACK_SIZE]; + dma_addr_t cmd_pool_handle; + int top; +}; +#pragma pack() + +struct cciss_scsi_adapter_data_t { + struct Scsi_Host *scsi_host; + struct cciss_scsi_cmd_stack_t cmd_stack; + int registered; + spinlock_t lock; // to protect ccissscsi[ctlr]; +}; + +#define CPQ_TAPE_LOCK(ctlr, flags) spin_lock_irqsave( \ + &(((struct cciss_scsi_adapter_data_t *) \ + hba[ctlr]->scsi_ctlr)->lock), flags); +#define CPQ_TAPE_UNLOCK(ctlr, flags) spin_unlock_irqrestore( \ + &(((struct cciss_scsi_adapter_data_t *) \ + hba[ctlr]->scsi_ctlr)->lock), flags); + +static CommandList_struct * +scsi_cmd_alloc(ctlr_info_t *h) +{ + /* assume only one process in here at a time, locking done by caller. */ + /* use CCISS_LOCK(ctlr) */ + /* might be better to rewrite how we allocate scsi commands in a way that */ + /* needs no locking at all. */ + + /* take the top memory chunk off the stack and return it, if any. */ + struct cciss_scsi_cmd_stack_elem_t *c; + struct cciss_scsi_adapter_data_t *sa; + struct cciss_scsi_cmd_stack_t *stk; + u64bit temp64; + + sa = (struct cciss_scsi_adapter_data_t *) h->scsi_ctlr; + stk = &sa->cmd_stack; + + if (stk->top < 0) + return NULL; + c = stk->elem[stk->top]; + /* memset(c, 0, sizeof(*c)); */ + memset(&c->cmd, 0, sizeof(c->cmd)); + memset(&c->Err, 0, sizeof(c->Err)); + /* set physical addr of cmd and addr of scsi parameters */ + c->cmd.busaddr = c->busaddr; + /* (__u32) (stk->cmd_pool_handle + + (sizeof(struct cciss_scsi_cmd_stack_elem_t)*stk->top)); */ + + temp64.val = (__u64) (c->busaddr + sizeof(CommandList_struct)); + /* (__u64) (stk->cmd_pool_handle + + (sizeof(struct cciss_scsi_cmd_stack_elem_t)*stk->top) + + sizeof(CommandList_struct)); */ + stk->top--; + c->cmd.ErrDesc.Addr.lower = temp64.val32.lower; + c->cmd.ErrDesc.Addr.upper = temp64.val32.upper; + c->cmd.ErrDesc.Len = sizeof(ErrorInfo_struct); + + c->cmd.ctlr = h->ctlr; + c->cmd.err_info = &c->Err; + + return (CommandList_struct *) c; +} + +static void +scsi_cmd_free(ctlr_info_t *h, CommandList_struct *cmd) +{ + /* assume only one process in here at a time, locking done by caller. */ + /* use CCISS_LOCK(ctlr) */ + /* drop the free memory chunk on top of the stack. */ + + struct cciss_scsi_adapter_data_t *sa; + struct cciss_scsi_cmd_stack_t *stk; + + sa = (struct cciss_scsi_adapter_data_t *) h->scsi_ctlr; + stk = &sa->cmd_stack; + if (stk->top >= CMD_STACK_SIZE) { + printk("cciss: scsi_cmd_free called too many times.\n"); + BUG(); + } + stk->top++; + stk->elem[stk->top] = (struct cciss_scsi_cmd_stack_elem_t *) cmd; +} + +static int +scsi_cmd_stack_setup(int ctlr) +{ + int i; + struct cciss_scsi_adapter_data_t *sa; + struct cciss_scsi_cmd_stack_t *stk; + size_t size; + + sa = (struct cciss_scsi_adapter_data_t *) hba[ctlr]->scsi_ctlr; + stk = &sa->cmd_stack; + size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * CMD_STACK_SIZE; + + // We use NULL as first arg to pci_alloc_consistent so we can be + // sure that we get addresses that will fit through the 32 bit + // command register, (our DMA mask says we can do 64 bit DMA, which + // we, can, just not for commands.) + + stk->pool = (struct cciss_scsi_cmd_stack_elem_t *) + pci_alloc_consistent(NULL, size, &stk->cmd_pool_handle); + + if (stk->pool == NULL) { + printk("stk->pool is null\n"); + return -1; + } + + for (i=0; ielem[i] = &stk->pool[i]; + stk->elem[i]->busaddr = (__u32) (stk->cmd_pool_handle + + (sizeof(struct cciss_scsi_cmd_stack_elem_t) * i)); + } + stk->top = CMD_STACK_SIZE-1; + return 0; +} + +static void +scsi_cmd_stack_free(int ctlr) +{ + struct cciss_scsi_adapter_data_t *sa; + struct cciss_scsi_cmd_stack_t *stk; + size_t size; + + sa = (struct cciss_scsi_adapter_data_t *) hba[ctlr]->scsi_ctlr; + stk = &sa->cmd_stack; + if (stk->top != CMD_STACK_SIZE-1) { + printk( "cciss: %d scsi commands are still outstanding.\n", + CMD_STACK_SIZE - stk->top); + // BUG(); + printk("WE HAVE A BUG HERE!!! stk=0x%08x\n", + (unsigned int) stk); + } + size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * CMD_STACK_SIZE; + + // About NULL, see note above near pci_alloc_consistent + pci_free_consistent(NULL, size, stk->pool, stk->cmd_pool_handle); + stk->pool = NULL; +} + +/* scsi_device_types comes from scsi.h */ +#define DEVICETYPE(n) (n<0 || n>MAX_SCSI_DEVICE_CODE) ? \ + "Unknown" : scsi_device_types[n] + +#if 0 +static int xmargin=8; +static int amargin=60; + +static void +print_bytes (unsigned char *c, int len, int hex, int ascii) +{ + + int i; + unsigned char *x; + + if (hex) + { + x = c; + for (i=0;i0) printk("\n"); + if ((i % xmargin) == 0) printk("0x%04x:", i); + printk(" %02x", *x); + x++; + } + printk("\n"); + } + if (ascii) + { + x = c; + for (i=0;i0) printk("\n"); + if ((i % amargin) == 0) printk("0x%04x:", i); + if (*x > 26 && *x < 128) printk("%c", *x); + else printk("."); + x++; + } + printk("\n"); + } +} + +static void +print_cmd(CommandList_struct *cp) +{ + printk("queue:%d\n", cp->Header.ReplyQueue); + printk("sglist:%d\n", cp->Header.SGList); + printk("sgtot:%d\n", cp->Header.SGTotal); + printk("Tag:0x%08x/0x%08x\n", cp->Header.Tag.upper, + cp->Header.Tag.lower); + printk("LUN:0x%02x%02x%02x%02x%02x%02x%02x%02x\n", + cp->Header.LUN.LunAddrBytes[0], + cp->Header.LUN.LunAddrBytes[1], + cp->Header.LUN.LunAddrBytes[2], + cp->Header.LUN.LunAddrBytes[3], + cp->Header.LUN.LunAddrBytes[4], + cp->Header.LUN.LunAddrBytes[5], + cp->Header.LUN.LunAddrBytes[6], + cp->Header.LUN.LunAddrBytes[7]); + printk("CDBLen:%d\n", cp->Request.CDBLen); + printk("Type:%d\n",cp->Request.Type.Type); + printk("Attr:%d\n",cp->Request.Type.Attribute); + printk(" Dir:%d\n",cp->Request.Type.Direction); + printk("Timeout:%d\n",cp->Request.Timeout); + printk( "CDB: %02x %02x %02x %02x %02x %02x %02x %02x" + " %02x %02x %02x %02x %02x %02x %02x %02x\n", + cp->Request.CDB[0], cp->Request.CDB[1], + cp->Request.CDB[2], cp->Request.CDB[3], + cp->Request.CDB[4], cp->Request.CDB[5], + cp->Request.CDB[6], cp->Request.CDB[7], + cp->Request.CDB[8], cp->Request.CDB[9], + cp->Request.CDB[10], cp->Request.CDB[11], + cp->Request.CDB[12], cp->Request.CDB[13], + cp->Request.CDB[14], cp->Request.CDB[15]), + printk("edesc.Addr: 0x%08x/0%08x, Len = %d\n", + cp->ErrDesc.Addr.upper, cp->ErrDesc.Addr.lower, + cp->ErrDesc.Len); + printk("sgs..........Errorinfo:\n"); + printk("scsistatus:%d\n", cp->err_info->ScsiStatus); + printk("senselen:%d\n", cp->err_info->SenseLen); + printk("cmd status:%d\n", cp->err_info->CommandStatus); + printk("resid cnt:%d\n", cp->err_info->ResidualCnt); + printk("offense size:%d\n", cp->err_info->MoreErrInfo.Invalid_Cmd.offense_size); + printk("offense byte:%d\n", cp->err_info->MoreErrInfo.Invalid_Cmd.offense_num); + printk("offense value:%d\n", cp->err_info->MoreErrInfo.Invalid_Cmd.offense_value); + +} + +#endif + +static int +find_bus_target_lun(int ctlr, int *bus, int *target, int *lun) +{ + /* finds an unused bus, target, lun for a new device */ + /* assumes hba[ctlr]->scsi_ctlr->lock is held */ + int i, found=0; + unsigned char target_taken[CCISS_MAX_SCSI_DEVS_PER_HBA]; + + memset(&target_taken[0], 0, CCISS_MAX_SCSI_DEVS_PER_HBA); + + target_taken[SELF_SCSI_ID] = 1; + for (i=0;iscsi_ctlr->lock is held */ + int n = ccissscsi[ctlr].ndevices; + struct cciss_scsi_dev_t *sd; + + if (n >= CCISS_MAX_SCSI_DEVS_PER_HBA) { + printk("cciss%d: Too many devices, " + "some will be inaccessible.\n", ctlr); + return -1; + } + sd = &ccissscsi[ctlr].dev[n]; + if (find_bus_target_lun(ctlr, &sd->bus, &sd->target, &sd->lun) != 0) + return -1; + memcpy(&sd->scsi3addr[0], scsi3addr, 8); + sd->devtype = devtype; + ccissscsi[ctlr].ndevices++; + + /* initially, (before registering with scsi layer) we don't + know our hostno and we don't want to print anything first + time anyway (the scsi layer's inquiries will show that info) */ + if (hostno != -1) + printk("cciss%d: %s device c%db%dt%dl%d added.\n", + ctlr, DEVICETYPE(sd->devtype), hostno, + sd->bus, sd->target, sd->lun); + return 0; +} + +static void +cciss_scsi_remove_entry(int ctlr, int hostno, int entry) +{ + /* assumes hba[ctlr]->scsi_ctlr->lock is held */ + int i; + struct cciss_scsi_dev_t sd; + + if (entry < 0 || entry >= CCISS_MAX_SCSI_DEVS_PER_HBA) return; + sd = ccissscsi[ctlr].dev[entry]; + for (i=entry;iscsi3addr)) { + if (sd[j].devtype == csd->devtype) + found=2; + else + found=1; + break; + } + } + + if (found == 0) { /* device no longer present. */ + changes++; + /* printk("cciss%d: %s device c%db%dt%dl%d removed.\n", + ctlr, DEVICETYPE(csd->devtype), hostno, + csd->bus, csd->target, csd->lun); */ + cciss_scsi_remove_entry(ctlr, hostno, i); + /* note, i not incremented */ + } + else if (found == 1) { /* device is different kind */ + changes++; + printk("cciss%d: device c%db%dt%dl%d type changed " + "(device type now %s).\n", + ctlr, hostno, csd->bus, csd->target, csd->lun, + DEVICETYPE(csd->devtype)); + csd->devtype = sd[j].devtype; + i++; /* so just move along. */ + } else /* device is same as it ever was, */ + i++; /* so just move along. */ + } + + /* Now, make sure every device listed in sd[] is also + listed in ccissscsi[], adding them if they aren't found */ + + for (i=0;iscsi3addr)) { + if (sd[i].devtype == csd->devtype) + found=2; /* found device */ + else + found=1; /* found a bug. */ + break; + } + } + if (!found) { + changes++; + if (cciss_scsi_add_entry(ctlr, hostno, + &sd[i].scsi3addr[0], sd[i].devtype) != 0) + break; + } else if (found == 1) { + /* should never happen... */ + changes++; + printk("cciss%d: device unexpectedly changed type\n", + ctlr); + /* but if it does happen, we just ignore that device */ + } + } + CPQ_TAPE_UNLOCK(ctlr, flags); + + if (!changes) + printk("cciss%d: No device changes detected.\n", ctlr); + + return 0; +} + +static int +lookup_scsi3addr(int ctlr, int bus, int target, int lun, char *scsi3addr) +{ + int i; + struct cciss_scsi_dev_t *sd; + unsigned long flags; + + CPQ_TAPE_LOCK(ctlr, flags); + for (i=0;ibus == bus && + sd->target == target && + sd->lun == lun) { + memcpy(scsi3addr, &sd->scsi3addr[0], 8); + CPQ_TAPE_UNLOCK(ctlr, flags); + return 0; + } + } + CPQ_TAPE_UNLOCK(ctlr, flags); + return -1; +} + + +static void +cciss_find_non_disk_devices(int cntl_num) +{ + ReportLunData_struct *ld_buff; + InquiryData_struct *inq_buff; + int return_code; + int i; + int listlength = 0; + int num_luns; + unsigned char scsi3addr[8]; + unsigned long flags; + int reportlunsize = sizeof(*ld_buff) + CISS_MAX_PHYS_LUN * 8; + + hba[cntl_num]->scsi_ctlr = (void *) + kmalloc(sizeof(struct cciss_scsi_adapter_data_t), + GFP_KERNEL); + if (hba[cntl_num]->scsi_ctlr == NULL) + return; + + ((struct cciss_scsi_adapter_data_t *) + hba[cntl_num]->scsi_ctlr)->scsi_host = NULL; + ((struct cciss_scsi_adapter_data_t *) + hba[cntl_num]->scsi_ctlr)->lock = SPIN_LOCK_UNLOCKED; + ((struct cciss_scsi_adapter_data_t *) + hba[cntl_num]->scsi_ctlr)->registered = 0; + + if (scsi_cmd_stack_setup(cntl_num) != 0) { + printk("Trouble, returned non-zero!\n"); + return; + } + + ld_buff = kmalloc(reportlunsize, GFP_KERNEL); + if (ld_buff == NULL) { + printk(KERN_ERR "cciss: out of memory\n"); + return; + } + memset(ld_buff, 0, sizeof(ReportLunData_struct)); + inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL); + if (inq_buff == NULL) { + printk(KERN_ERR "cciss: out of memory\n"); + kfree(ld_buff); + return; + } + + /* Get the physical luns */ + return_code = sendcmd(CISS_REPORT_PHYS, cntl_num, ld_buff, + reportlunsize, 0, 0, 0, NULL ); + + if( return_code == IO_OK) { + unsigned char *c = &ld_buff->LUNListLength[0]; + listlength = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3]; + } + else { /* getting report of physical luns failed */ + printk(KERN_WARNING "cciss: report physical luns" + " command failed\n"); + listlength = 0; + } + + CPQ_TAPE_LOCK(cntl_num, flags); + ccissscsi[cntl_num].ndevices = 0; + num_luns = listlength / 8; // 8 bytes pre entry + /* printk("Found %d LUNs\n", num_luns); */ + + if (num_luns > CISS_MAX_PHYS_LUN) + { + printk(KERN_WARNING + "cciss: Maximum physical LUNs (%d) exceeded. " + "%d LUNs ignored.\n", CISS_MAX_PHYS_LUN, + num_luns - CISS_MAX_PHYS_LUN); + num_luns = CISS_MAX_PHYS_LUN; + } + + for(i=0; iLUN[i], 8); /* ugly... */ + return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff, + sizeof(InquiryData_struct), 2, 0 ,0, scsi3addr ); + if (return_code == IO_OK) { + if(inq_buff->data_byte[8] == 0xFF) + { + printk(KERN_WARNING "cciss: inquiry failed\n"); + } else { + int devtype; + + /* printk("Inquiry...\n"); + print_bytes((unsigned char *) inq_buff, 36, 1, 1); */ + devtype = (inq_buff->data_byte[0] & 0x1f); + + switch (devtype) + { + case 0x01: /* sequential access, (tape) */ + case 0x08: /* medium changer */ + /* this is the only kind of dev */ + /* we want to expose here. */ + if (cciss_scsi_add_entry(cntl_num, -1, + (unsigned char *) ld_buff->LUN[i], + devtype) != 0) + i=num_luns; // leave loop + break; + default: + break; + } + + } + } + else printk("cciss: inquiry failed.\n"); + } +#if 0 + for (i=0;ierr_info; + + /* First, see if it was a message rather than a command */ + if (cp->Request.Type.Type == TYPE_MSG) { + cp->cmd_type = CMD_MSG_DONE; + return; + } + + cmd = (Scsi_Cmnd *) cp->scsi_cmd; + ctlr = hba[cp->ctlr]; + + /* undo the DMA mappings */ + + if (cmd->use_sg) { + pci_unmap_sg(ctlr->pdev, + cmd->buffer, cmd->use_sg, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); + } + else if (cmd->request_bufflen) { + addr64.val32.lower = cp->SG[0].Addr.lower; + addr64.val32.upper = cp->SG[0].Addr.upper; + pci_unmap_single(ctlr->pdev, (dma_addr_t) addr64.val, + cmd->request_bufflen, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); + } + + cmd->result = (DID_OK << 16); /* host byte */ + cmd->result |= (COMMAND_COMPLETE << 8); /* msg byte */ + /* cmd->result |= (GOOD < 1); */ /* status byte */ + + cmd->result |= (ei->ScsiStatus); + /* printk("Scsistatus is 0x%02x\n", ei->ScsiStatus); */ + + /* copy the sense data whether we need to or not. */ + + memcpy(cmd->sense_buffer, ei->SenseInfo, + ei->SenseLen > SCSI_SENSE_BUFFERSIZE ? + SCSI_SENSE_BUFFERSIZE : + ei->SenseLen); + cmd->resid = ei->ResidualCnt; + + if(ei->CommandStatus != 0) + { /* an error has occurred */ + switch(ei->CommandStatus) + { + case CMD_TARGET_STATUS: + /* Pass it up to the upper layers... */ + if( ei->ScsiStatus) + { +#if 0 + printk(KERN_WARNING "cciss: cmd %p " + "has SCSI Status = %x\n", + cp, + ei->ScsiStatus); +#endif + cmd->result |= (ei->ScsiStatus < 1); + } + else { /* scsi status is zero??? How??? */ + + /* Ordinarily, this case should never happen, but there is a bug + in some released firmware revisions that allows it to happen + if, for example, a 4100 backplane loses power and the tape + drive is in it. We assume that it's a fatal error of some + kind because we can't show that it wasn't. We will make it + look like selection timeout since that is the most common + reason for this to occur, and it's severe enough. */ + + cmd->result = DID_NO_CONNECT << 16; + } + break; + case CMD_DATA_UNDERRUN: /* let mid layer handle it. */ + break; + case CMD_DATA_OVERRUN: + printk(KERN_WARNING "cciss: cp %p has" + " completed with data overrun " + "reported\n", cp); + break; + case CMD_INVALID: { + /* print_bytes(cp, sizeof(*cp), 1, 0); + print_cmd(cp); */ + /* We get CMD_INVALID if you address a non-existent tape drive instead + of a selection timeout (no response). You will see this if you yank + out a tape drive, then try to access it. This is kind of a shame + because it means that any other CMD_INVALID (e.g. driver bug) will + get interpreted as a missing target. */ + cmd->result = DID_NO_CONNECT << 16; + } + break; + case CMD_PROTOCOL_ERR: + printk(KERN_WARNING "cciss: cp %p has " + "protocol error \n", cp); + break; + case CMD_HARDWARE_ERR: + cmd->result = DID_ERROR << 16; + printk(KERN_WARNING "cciss: cp %p had " + " hardware error\n", cp); + break; + case CMD_CONNECTION_LOST: + cmd->result = DID_ERROR << 16; + printk(KERN_WARNING "cciss: cp %p had " + "connection lost\n", cp); + break; + case CMD_ABORTED: + cmd->result = DID_ABORT << 16; + printk(KERN_WARNING "cciss: cp %p was " + "aborted\n", cp); + break; + case CMD_ABORT_FAILED: + cmd->result = DID_ERROR << 16; + printk(KERN_WARNING "cciss: cp %p reports " + "abort failed\n", cp); + break; + case CMD_UNSOLICITED_ABORT: + cmd->result = DID_ABORT << 16; + printk(KERN_WARNING "cciss: cp %p aborted " + "do to an unsolicited abort\n", cp); + break; + case CMD_TIMEOUT: + cmd->result = DID_TIME_OUT << 16; + printk(KERN_WARNING "cciss: cp %p timedout\n", + cp); + break; + default: + cmd->result = DID_ERROR << 16; + printk(KERN_WARNING "cciss: cp %p returned " + "unknown status %x\n", cp, + ei->CommandStatus); + } + } + // printk("c:%p:c%db%dt%dl%d ", cmd, ctlr->ctlr, cmd->channel, + // cmd->target, cmd->lun); + cmd->scsi_done(cmd); + scsi_cmd_free(ctlr, cp); +} + +/* cciss_scsi_detect is called from the scsi mid layer. + The scsi mid layer (scsi_register_host) is + called from cciss.c:cciss_init_one(). */ + +int __init +cciss_scsi_detect(Scsi_Host_Template *tpnt) +{ + int i; + struct Scsi_Host *sh; + + /* Tell the kernel we want to be a SCSI driver... */ + sh = scsi_register(tpnt, sizeof(struct ctlr_info *)); + if (sh == NULL) return 0; + + sh->io_port = 0; // good enough? FIXME, + sh->n_io_port = 0; // I don't think we use these two... + + sh->this_id = SELF_SCSI_ID; + + /* This is a bit kludgey, using the adapter name to figure out */ + /* which scsi host template we've got, won't scale beyond 9 ctlrs. */ + i = tpnt->name[5] - '0'; + +# if MAX_CTLR > 9 +# error "cciss_scsi.c: MAX_CTLR > 9, code maintenance needed." +# endif + + if (i<0 || i>=MAX_CTLR || hba[i] == NULL) { + /* we didn't find ourself... we shouldn't get here. */ + printk("cciss_scsi_detect: could not find ourself in hba[]\n"); + return 0; + } + + ((struct cciss_scsi_adapter_data_t *) + hba[i]->scsi_ctlr)->scsi_host = (void *) sh; + sh->hostdata[0] = (unsigned long) hba[i]; + sh->irq = hba[i]->intr; + sh->unique_id = sh->irq; + scsi_set_pci_device(sh, hba[i]->pdev); + + return 1; /* Say we have 1 scsi adapter, this will be */ + /* called multiple times, once for each adapter */ + /* from cciss.c:cciss_init_one(). We do it this */ + /* way for PCI-hot plug reasons. (we don't know how */ + /* many adapters we have total, so we say we have */ + /* 1, each of a unique type.) */ +} + +static void __exit cleanup_cciss_module(void); +int +cciss_scsi_release(struct Scsi_Host *sh) +{ + return 0; +} + +static void +cciss_unmap_one(struct pci_dev *pdev, + CommandList_struct *cp, + size_t buflen, + int data_direction) +{ + u64bit addr64; + + addr64.val32.lower = cp->SG[0].Addr.lower; + addr64.val32.upper = cp->SG[0].Addr.upper; + pci_unmap_single(pdev, (dma_addr_t) addr64.val, buflen, data_direction); +} + +static void +cciss_map_one(struct pci_dev *pdev, + CommandList_struct *cp, + unsigned char *buf, + size_t buflen, + int data_direction) +{ + __u64 addr64; + + addr64 = (__u64) pci_map_single(pdev, buf, buflen, data_direction); + cp->SG[0].Addr.lower = + (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF); + cp->SG[0].Addr.upper = + (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF); + cp->SG[0].Len = buflen; + cp->Header.SGList = (__u8) 1; /* no. SGs contig in this cmd */ + cp->Header.SGTotal = (__u16) 1; /* total sgs in this cmd list */ +} + +static int +cciss_scsi_do_simple_cmd(ctlr_info_t *c, + CommandList_struct *cp, + unsigned char *scsi3addr, + unsigned char *cdb, + unsigned char cdblen, + unsigned char *buf, int bufsize, + int direction) +{ + unsigned long flags; + + cp->cmd_type = CMD_IOCTL_PEND; // treat this like an ioctl + cp->scsi_cmd = NULL; + cp->Header.ReplyQueue = 0; // unused in simple mode + memcpy(&cp->Header.LUN, scsi3addr, sizeof(cp->Header.LUN)); + cp->Header.Tag.lower = cp->busaddr; // Use k. address of cmd as tag + // Fill in the request block... + + /* printk("Using scsi3addr 0x%02x%0x2%0x2%0x2%0x2%0x2%0x2%0x2\n", + scsi3addr[0], scsi3addr[1], scsi3addr[2], scsi3addr[3], + scsi3addr[4], scsi3addr[5], scsi3addr[6], scsi3addr[7]); */ + + memset(cp->Request.CDB, 0, sizeof(cp->Request.CDB)); + memcpy(cp->Request.CDB, cdb, cdblen); + cp->Request.Timeout = 1000; // guarantee completion. + cp->Request.CDBLen = cdblen; + cp->Request.Type.Type = TYPE_CMD; + cp->Request.Type.Attribute = ATTR_SIMPLE; + cp->Request.Type.Direction = direction; + + /* Fill in the SG list and do dma mapping */ + cciss_map_one(c->pdev, cp, + (unsigned char *) buf, bufsize, + scsi_to_pci_dma_dir(SCSI_DATA_READ)); + + /* Put the request on the tail of the request queue */ + spin_lock_irqsave(CCISS_LOCK(c->ctlr), flags); + addQ(&c->reqQ, cp); + c->Qdepth++; + start_io(c); + spin_unlock_irqrestore(CCISS_LOCK(c->ctlr), flags); + + /* Wait for the request to complete */ + while(cp->cmd_type != CMD_IOCTL_DONE) + schedule_timeout(1); + + /* undo the dma mapping */ + cciss_unmap_one(c->pdev, cp, bufsize, + scsi_to_pci_dma_dir(SCSI_DATA_READ)); + + return(0); +} + +static void +cciss_scsi_interpret_error(CommandList_struct *cp) +{ + ErrorInfo_struct *ei; + + ei = cp->err_info; + switch(ei->CommandStatus) + { + case CMD_TARGET_STATUS: + printk(KERN_WARNING "cciss: cmd %p has " + "completed with errors\n", cp); + printk(KERN_WARNING "cciss: cmd %p " + "has SCSI Status = %x\n", + cp, + ei->ScsiStatus); + if (ei->ScsiStatus == 0) + printk(KERN_WARNING + "cciss:SCSI status is abnormally zero. " + "(probably indicates selection timeout " + "reported incorrectly due to a known " + "firmware bug, circa July, 2001.)\n"); + break; + case CMD_DATA_UNDERRUN: /* let mid layer handle it. */ + printk("UNDERRUN\n"); + break; + case CMD_DATA_OVERRUN: + printk(KERN_WARNING "cciss: cp %p has" + " completed with data overrun " + "reported\n", cp); + break; + case CMD_INVALID: { + /* controller unfortunately reports SCSI passthru's */ + /* to non-existent targets as invalid commands. */ + printk(KERN_WARNING "cciss: cp %p is " + "reported invalid (probably means " + "target device no longer present)\n", + cp); + /* print_bytes((unsigned char *) cp, sizeof(*cp), 1, 0); + print_cmd(cp); */ + } + break; + case CMD_PROTOCOL_ERR: + printk(KERN_WARNING "cciss: cp %p has " + "protocol error \n", cp); + break; + case CMD_HARDWARE_ERR: + /* cmd->result = DID_ERROR << 16; */ + printk(KERN_WARNING "cciss: cp %p had " + " hardware error\n", cp); + break; + case CMD_CONNECTION_LOST: + printk(KERN_WARNING "cciss: cp %p had " + "connection lost\n", cp); + break; + case CMD_ABORTED: + printk(KERN_WARNING "cciss: cp %p was " + "aborted\n", cp); + break; + case CMD_ABORT_FAILED: + printk(KERN_WARNING "cciss: cp %p reports " + "abort failed\n", cp); + break; + case CMD_UNSOLICITED_ABORT: + printk(KERN_WARNING "cciss: cp %p aborted " + "do to an unsolicited abort\n", cp); + break; + case CMD_TIMEOUT: + printk(KERN_WARNING "cciss: cp %p timedout\n", + cp); + break; + default: + printk(KERN_WARNING "cciss: cp %p returned " + "unknown status %x\n", cp, + ei->CommandStatus); + } +} + +static int +cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr, + InquiryData_struct *buf) +{ + int rc; + CommandList_struct *cp; + char cdb[6]; + ErrorInfo_struct *ei; + unsigned long flags; + + spin_lock_irqsave(CCISS_LOCK(c->ctlr), flags); + cp = scsi_cmd_alloc(c); + spin_unlock_irqrestore(CCISS_LOCK(c->ctlr), flags); + ei = cp->err_info; + + if (cp == NULL) { /* trouble... */ + printk("cmd_alloc returned NULL!\n"); + return -1; + } + + cdb[0] = CISS_INQUIRY; + cdb[1] = 0; + cdb[2] = 0; + cdb[3] = 0; + cdb[4] = sizeof(*buf) & 0xff; + cdb[5] = 0; + rc = cciss_scsi_do_simple_cmd(c, cp, scsi3addr, cdb, + 6, (unsigned char *) buf, + sizeof(*buf), XFER_READ); + + if (rc != 0) return rc; /* something went wrong */ + + if (ei->CommandStatus != 0 && + ei->CommandStatus != CMD_DATA_UNDERRUN) { + cciss_scsi_interpret_error(cp); + rc = -1; + } + spin_lock_irqsave(CCISS_LOCK(c->ctlr), flags); + scsi_cmd_free(c, cp); + spin_unlock_irqrestore(CCISS_LOCK(c->ctlr), flags); + return rc; +} + +static int +cciss_scsi_do_report_phys_luns(ctlr_info_t *c, + ReportLunData_struct *buf, int bufsize) +{ + int rc; + CommandList_struct *cp; + unsigned char cdb[12]; + unsigned char scsi3addr[8]; + ErrorInfo_struct *ei; + unsigned long flags; + + spin_lock_irqsave(CCISS_LOCK(c->ctlr), flags); + cp = scsi_cmd_alloc(c); + spin_unlock_irqrestore(CCISS_LOCK(c->ctlr), flags); + if (cp == NULL) { /* trouble... */ + printk("cmd_alloc returned NULL!\n"); + return -1; + } + + memset(&scsi3addr[0], 0, 8); /* address the controller */ + cdb[0] = CISS_REPORT_PHYS; + cdb[1] = 0; + cdb[2] = 0; + cdb[3] = 0; + cdb[4] = 0; + cdb[5] = 0; + cdb[6] = (sizeof(*buf) >> 24) & 0xFF; //MSB + cdb[7] = (sizeof(*buf) >> 16) & 0xFF; + cdb[8] = (sizeof(*buf) >> 8) & 0xFF; + cdb[9] = sizeof(*buf) & 0xFF; + cdb[10] = 0; + cdb[11] = 0; + + rc = cciss_scsi_do_simple_cmd(c, cp, scsi3addr, + cdb, 12, + (unsigned char *) buf, + bufsize, XFER_READ); + + if (rc != 0) return rc; /* something went wrong */ + + ei = cp->err_info; + if (ei->CommandStatus != 0 && + ei->CommandStatus != CMD_DATA_UNDERRUN) { + cciss_scsi_interpret_error(cp); + rc = -1; + } + spin_lock_irqsave(CCISS_LOCK(c->ctlr), flags); + scsi_cmd_free(c, cp); + spin_unlock_irqrestore(CCISS_LOCK(c->ctlr), flags); + return rc; +} + +static void +cciss_update_non_disk_devices(int cntl_num, int hostno) +{ + /* the idea here is we could get notified from /proc + that some devices have changed, so we do a report + physical luns cmd, and adjust our list of devices + accordingly. (We can't rely on the scsi-mid layer just + doing inquiries, because the "busses" that the scsi + mid-layer probes are totally fabricated by this driver, + so new devices wouldn't show up. + + the scsi3addr's of devices won't change so long as the + adapter is not reset. That means we can rescan and + tell which devices we already know about, vs. new + devices, vs. disappearing devices. + + Also, if you yank out a tape drive, then put in a disk + in it's place, (say, a configured volume from another + array controller for instance) _don't_ poke this driver + (so it thinks it's still a tape, but _do_ poke the scsi + mid layer, so it does an inquiry... the scsi mid layer + will see the physical disk. This would be bad. Need to + think about how to prevent that. One idea would be to + snoop all scsi responses and if an inquiry repsonse comes + back that reports a disk, chuck it an return selection + timeout instead and adjust our table... Not sure i like + that though. + + */ + + ReportLunData_struct *ld_buff; + InquiryData_struct *inq_buff; + unsigned char scsi3addr[8]; + ctlr_info_t *c; + __u32 num_luns=0; + unsigned char *ch; + /* unsigned char found[CCISS_MAX_SCSI_DEVS_PER_HBA]; */ + struct cciss_scsi_dev_t currentsd[CCISS_MAX_SCSI_DEVS_PER_HBA]; + int ncurrent=0; + int reportlunsize = sizeof(*ld_buff) + CISS_MAX_PHYS_LUN * 8; + int i; + + c = (ctlr_info_t *) hba[cntl_num]; + ld_buff = kmalloc(reportlunsize, GFP_KERNEL); + if (ld_buff == NULL) { + printk(KERN_ERR "cciss: out of memory\n"); + return; + } + memset(ld_buff, 0, reportlunsize); + inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL); + if (inq_buff == NULL) { + printk(KERN_ERR "cciss: out of memory\n"); + kfree(ld_buff); + return; + } + + if (cciss_scsi_do_report_phys_luns(c, ld_buff, reportlunsize) == 0) { + ch = &ld_buff->LUNListLength[0]; + num_luns = ((ch[0]<<24) | (ch[1]<<16) | (ch[2]<<8) | ch[3]) / 8; + if (num_luns > CISS_MAX_PHYS_LUN) { + printk(KERN_WARNING + "cciss: Maximum physical LUNs (%d) exceeded. " + "%d LUNs ignored.\n", CISS_MAX_PHYS_LUN, + num_luns - CISS_MAX_PHYS_LUN); + num_luns = CISS_MAX_PHYS_LUN; + } + } + else { + printk(KERN_ERR "cciss: Report physical LUNs failed.\n"); + return; + } + + + /* adjust our table of devices */ + for(i=0; iLUN[i][0], 8); + + if (cciss_scsi_do_inquiry(hba[cntl_num], + scsi3addr, inq_buff) != 0) + { + /* Inquiry failed (msg printed already) */ + devtype = 0; /* so we will skip this device. */ + } else /* what kind of device is this? */ + devtype = (inq_buff->data_byte[0] & 0x1f); + + switch (devtype) + { + case 0x01: /* sequential access, (tape) */ + case 0x08: /* medium changer */ + memcpy(¤tsd[ncurrent].scsi3addr[0], + &scsi3addr[0], 8); + currentsd[ncurrent].devtype = devtype; + currentsd[ncurrent].bus = -1; + currentsd[ncurrent].target = -1; + currentsd[ncurrent].lun = -1; + ncurrent++; + break; + default: + break; + } + } + + adjust_cciss_scsi_table(cntl_num, hostno, currentsd, ncurrent); + + kfree(inq_buff); + kfree(ld_buff); + return; +} + +static int +is_keyword(char *ptr, int len, char *verb) // Thanks to ncr53c8xx.c +{ + int verb_len = strlen(verb); + if (len >= verb_len && !memcmp(verb,ptr,verb_len)) + return verb_len; + else + return 0; +} + +static int +cciss_scsi_user_command(int ctlr, int hostno, char *buffer, int length) +{ + int arg_len; + + if ((arg_len = is_keyword(buffer, length, "rescan")) != 0) + cciss_update_non_disk_devices(ctlr, hostno); + else + return -EINVAL; + return length; +} + +/* It's a pity that we need this, but, we do... */ +extern struct Scsi_Host *scsi_hostlist; /* from ../scsi/hosts.c */ + +int +cciss_scsi_proc_info(char *buffer, /* data buffer */ + char **start, /* where data in buffer starts */ + off_t offset, /* offset from start of imaginary file */ + int length, /* length of data in buffer */ + int hostnum, /* which host adapter (always zero for me) */ + int func) /* 0 == read, 1 == write */ +{ + + int buflen, datalen; + struct Scsi_Host *sh; + int found; + ctlr_info_t *ci; + int cntl_num; + + /* Lets see if we can find our Scsi_Host... + this might be kind of "bad", searching scis_hostlist this way + but how else can we find the scsi host? I think I've seen + this coded both ways, (circular list and null terminated list) + I coded it to work either way, since I wasn't sure. */ + + sh = scsi_hostlist; + found=0; + do { + if (sh == NULL) break; + if (sh->host_no == hostnum) { + found++; + break; + } + sh = sh->next; + } while (sh != scsi_hostlist && sh != NULL); + + if (sh == NULL || found == 0) /* This really shouldn't ever happen. */ + return -EINVAL; + + ci = (ctlr_info_t *) sh->hostdata[0]; + if (ci == NULL) /* This really shouldn't ever happen. */ + return -EINVAL; + + cntl_num = ci->ctlr; /* Get our index into the hba[] array */ + + if (func == 0) { /* User is reading from /proc/scsi/ciss*?/?* */ + buflen = sprintf(buffer, "hostnum=%d\n", hostnum); + + datalen = buflen - offset; + if (datalen < 0) { /* they're reading past EOF. */ + datalen = 0; + *start = buffer+buflen; + } else + *start = buffer + offset; + return(datalen); + } else /* User is writing to /proc/scsi/cciss*?/?* ... */ + return cciss_scsi_user_command(cntl_num, hostnum, + buffer, length); +} + +/* this is via the generic proc support */ +const char * +cciss_scsi_info(struct Scsi_Host *sa) +{ + static char buf[300]; + ctlr_info_t *ci; + + /* probably need to work on putting a bit more info in here... */ + /* this is output via the /proc filesystem. */ + + ci = (ctlr_info_t *) sa->hostdata[0]; + + sprintf(buf, "%s %c%c%c%c\n", + ci->product_name, + ci->firm_ver[0], + ci->firm_ver[1], + ci->firm_ver[2], + ci->firm_ver[3]); + + return buf; +} + + +/* cciss_scatter_gather takes a Scsi_Cmnd, (cmd), and does the pci + dma mapping and fills in the scatter gather entries of the + cciss command, cp. */ + +static void +cciss_scatter_gather(struct pci_dev *pdev, + CommandList_struct *cp, + Scsi_Cmnd *cmd) +{ + unsigned int use_sg, nsegs=0, len; + struct scatterlist *scatter = (struct scatterlist *) cmd->buffer; + __u64 addr64; + + /* is it just one virtual address? */ + if (!cmd->use_sg) { + if (cmd->request_bufflen) { /* anything to xfer? */ + + addr64 = (__u64) pci_map_single(pdev, + cmd->request_buffer, + cmd->request_bufflen, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); + + cp->SG[0].Addr.lower = + (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF); + cp->SG[0].Addr.upper = + (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF); + cp->SG[0].Len = cmd->request_bufflen; + nsegs=1; + } + } /* else, must be a list of virtual addresses.... */ + else if (cmd->use_sg <= MAXSGENTRIES) { /* not too many addrs? */ + + use_sg = pci_map_sg(pdev, cmd->buffer, cmd->use_sg, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); + + for (nsegs=0; nsegs < use_sg; nsegs++) { + addr64 = (__u64) sg_dma_address(&scatter[nsegs]); + len = sg_dma_len(&scatter[nsegs]); + cp->SG[nsegs].Addr.lower = + (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF); + cp->SG[nsegs].Addr.upper = + (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF); + cp->SG[nsegs].Len = len; + cp->SG[nsegs].Ext = 0; // we are not chaining + } + } else BUG(); + + cp->Header.SGList = (__u8) nsegs; /* no. SGs contig in this cmd */ + cp->Header.SGTotal = (__u16) nsegs; /* total sgs in this cmd list */ + return; +} + + +int +cciss_scsi_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) +{ + ctlr_info_t **c; + int ctlr, rc; + unsigned char scsi3addr[8]; + CommandList_struct *cp; + unsigned long flags; + + // Get the ptr to our adapter structure (hba[i]) out of cmd->host. + // We violate cmd->host privacy here. (Is there another way?) + c = (ctlr_info_t **) &cmd->host->hostdata[0]; + ctlr = (*c)->ctlr; + + rc = lookup_scsi3addr(ctlr, cmd->channel, cmd->target, cmd->lun, + scsi3addr); + if (rc != 0) { + /* the scsi nexus does not match any that we presented... */ + /* pretend to mid layer that we got selection timeout */ + cmd->result = DID_NO_CONNECT << 16; + done(cmd); + /* we might want to think about registering controller itself + as a processor device on the bus so sg binds to it. */ + return 0; + } + + /* printk("cciss_queue_command, p=%p, cmd=0x%02x, c%db%dt%dl%d\n", + cmd, cmd->cmnd[0], ctlr, cmd->channel, cmd->target, cmd->lun);*/ + // printk("q:%p:c%db%dt%dl%d ", cmd, ctlr, cmd->channel, + // cmd->target, cmd->lun); + + /* Ok, we have a reasonable scsi nexus, so send the cmd down, and + see what the device thinks of it. */ + + spin_lock_irqsave(CCISS_LOCK(ctlr), flags); + cp = scsi_cmd_alloc(*c); + spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); + if (cp == NULL) { /* trouble... */ + printk("scsi_cmd_alloc returned NULL!\n"); + /* FIXME: next 3 lines are -> BAD! <- */ + cmd->result = DID_NO_CONNECT << 16; + done(cmd); + return 0; + } + + // Fill in the command list header + + cmd->scsi_done = done; // save this for use by completion code + + // save cp in case we have to abort it + cmd->host_scribble = (unsigned char *) cp; + + cp->cmd_type = CMD_SCSI; + cp->scsi_cmd = cmd; + cp->Header.ReplyQueue = 0; // unused in simple mode + memcpy(&cp->Header.LUN.LunAddrBytes[0], &scsi3addr[0], 8); + cp->Header.Tag.lower = cp->busaddr; // Use k. address of cmd as tag + + // Fill in the request block... + + cp->Request.Timeout = 1000; // guarantee completion + memset(cp->Request.CDB, 0, sizeof(cp->Request.CDB)); + if (cmd->cmd_len > sizeof(cp->Request.CDB)) BUG(); + cp->Request.CDBLen = cmd->cmd_len; + memcpy(cp->Request.CDB, cmd->cmnd, cmd->cmd_len); + cp->Request.Type.Type = TYPE_CMD; + cp->Request.Type.Attribute = ATTR_SIMPLE; + switch(cmd->sc_data_direction) + { + case SCSI_DATA_WRITE: cp->Request.Type.Direction = XFER_WRITE; break; + case SCSI_DATA_READ: cp->Request.Type.Direction = XFER_READ; break; + case SCSI_DATA_NONE: cp->Request.Type.Direction = XFER_NONE; break; + + case SCSI_DATA_UNKNOWN: + // This can happen if a buggy application does a scsi passthru + // and sets both inlen and outlen to non-zero. ( see + // ../scsi/scsi_ioctl.c:scsi_ioctl_send_command() ) + + cp->Request.Type.Direction = XFER_RSVD; + // This is technically wrong, and cciss controllers should + // reject it with CMD_INVALID, which is the most correct + // response, but non-fibre backends appear to let it + // slide by, and give the same results as if this field + // were set correctly. Either way is acceptable for + // our purposes here. + + break; + + default: + printk("cciss: unknown data direction: %d\n", + cmd->sc_data_direction); + BUG(); + break; + } + + cciss_scatter_gather((*c)->pdev, cp, cmd); // Fill the SG list + + /* Put the request on the tail of the request queue */ + + spin_lock_irqsave(CCISS_LOCK(ctlr), flags); + addQ(&(*c)->reqQ, cp); + (*c)->Qdepth++; + start_io(*c); + spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); + + /* the cmd'll come back via intr handler in complete_scsi_command() */ + return 0; +} + +static void +init_driver_template(int ctlr) +{ + memset(&driver_template[ctlr], 0, sizeof(driver_template[ctlr])); + driver_template[ctlr].name = ccissscsi[ctlr].name; + driver_template[ctlr].proc_name = ccissscsi[ctlr].name; + driver_template[ctlr].detect = cciss_scsi_detect; + driver_template[ctlr].release = cciss_scsi_release; + driver_template[ctlr].proc_info = cciss_scsi_proc_info; + driver_template[ctlr].queuecommand = cciss_scsi_queue_command; + driver_template[ctlr].eh_abort_handler = NULL; + driver_template[ctlr].eh_device_reset_handler = NULL; + driver_template[ctlr].bios_param = scsicam_bios_param; + driver_template[ctlr].can_queue = SCSI_CCISS_CAN_QUEUE; + driver_template[ctlr].this_id = 7; + driver_template[ctlr].sg_tablesize = MAXSGENTRIES; + driver_template[ctlr].cmd_per_lun = 1; + driver_template[ctlr].use_clustering = DISABLE_CLUSTERING; + driver_template[ctlr].module = THIS_MODULE; + + /* set scsi_host to NULL so our detect routine will + find us on register */ + + ((struct cciss_scsi_adapter_data_t *) + hba[ctlr]->scsi_ctlr)->scsi_host = NULL; + +} + +static void +cciss_unregister_scsi(int ctlr) +{ + struct cciss_scsi_adapter_data_t *sa; + struct cciss_scsi_cmd_stack_t *stk; + unsigned long flags; + + /* we are being forcibly unloaded, and may not refuse. */ + + spin_lock_irqsave(CCISS_LOCK(ctlr), flags); + sa = (struct cciss_scsi_adapter_data_t *) hba[ctlr]->scsi_ctlr; + stk = &sa->cmd_stack; + + /* if we weren't ever actually registered, don't unregister */ + if (((struct cciss_scsi_adapter_data_t *) + hba[ctlr]->scsi_ctlr)->registered) { + spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); + scsi_unregister_host(&driver_template[ctlr]); + spin_lock_irqsave(CCISS_LOCK(ctlr), flags); + } + init_driver_template(ctlr); + scsi_cmd_stack_free(ctlr); + kfree(hba[ctlr]->scsi_ctlr); + spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); +} + +static int +cciss_register_scsi(int ctlr, int this_is_init_time) +{ + unsigned long flags; + + CPQ_TAPE_LOCK(ctlr, flags); + driver_template[ctlr].name = ccissscsi[ctlr].name; + driver_template[ctlr].proc_name = ccissscsi[ctlr].name; + driver_template[ctlr].module = THIS_MODULE;; + + /* Since this is really a block driver, the SCSI core may not be + initialized yet, in which case, calling scsi_register_host + would hang. instead, we will do it later, via /proc filesystem + and rc scripts, when we know SCSI core is good to go. */ + + if (this_is_init_time) { + CPQ_TAPE_UNLOCK(ctlr, flags); + return 0; + } + + /* Only register if SCSI devices are detected. */ + if (ccissscsi[ctlr].ndevices != 0) { + ((struct cciss_scsi_adapter_data_t *) + hba[ctlr]->scsi_ctlr)->registered = 1; + CPQ_TAPE_UNLOCK(ctlr, flags); + return scsi_register_host(&driver_template[ctlr]); + } + CPQ_TAPE_UNLOCK(ctlr, flags); + printk(KERN_INFO + "cciss%d: No appropriate SCSI device detected, " + "SCSI subsystem not engaged.\n", ctlr); + return 0; +} + +static int +cciss_engage_scsi(int ctlr) +{ + struct cciss_scsi_adapter_data_t *sa; + struct cciss_scsi_cmd_stack_t *stk; + unsigned long flags; + + spin_lock_irqsave(CCISS_LOCK(ctlr), flags); + sa = (struct cciss_scsi_adapter_data_t *) hba[ctlr]->scsi_ctlr; + stk = &sa->cmd_stack; + + if (((struct cciss_scsi_adapter_data_t *) + hba[ctlr]->scsi_ctlr)->registered) { + printk("cciss%d: SCSI subsystem already engaged.\n", ctlr); + spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); + return ENXIO; + } + spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); + cciss_update_non_disk_devices(ctlr, -1); + cciss_register_scsi(ctlr, 0); + return 0; +} + +static void +cciss_proc_tape_report(int ctlr, unsigned char *buffer, off_t *pos, off_t *len) +{ + int size; + unsigned int flags; + + *pos = *pos -1; *len = *len - 1; // cut off the last trailing newline + + CPQ_TAPE_LOCK(ctlr, flags); + size = sprintf(buffer + *len, + " Sequential access devices: %d\n\n", + ccissscsi[ctlr].ndevices); + CPQ_TAPE_UNLOCK(ctlr, flags); + *pos += size; *len += size; +} + +#else /* no CONFIG_CISS_SCSI_TAPE */ + +/* If no tape support, then these become defined out of existence */ + +#define cciss_find_non_disk_devices(cntl_num) +#define cciss_unregister_scsi(ctlr) +#define cciss_register_scsi(ctlr, this_is_init_time) +#define cciss_proc_tape_report(ctlr, buffer, pos, len) + +#endif /* CONFIG_CISS_SCSI_TAPE */ diff -urN linux-2.5.2-pre11/drivers/block/cciss_scsi.h linux/drivers/block/cciss_scsi.h --- linux-2.5.2-pre11/drivers/block/cciss_scsi.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/block/cciss_scsi.h Mon Jan 14 18:28:28 2002 @@ -0,0 +1,98 @@ +/* + * Disk Array driver for Compaq SA53xx Controllers, SCSI Tape module + * Copyright 2001 Compaq Computer Corporation + * + * 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. + * + * Questions/Comments/Bugfixes to arrays@compaq.com + * + */ +#ifdef CONFIG_CISS_SCSI_TAPE +#ifndef _CCISS_SCSI_H_ +#define _CCISS_SCSI_H_ + +#include /* possibly irrelevant, since we don't show disks */ + + // the scsi id of the adapter... +#define SELF_SCSI_ID 15 + // 15 is somewhat arbitrary, since the scsi-2 bus + // that's presented by the driver to the OS is + // fabricated. The "real" scsi-3 bus the + // hardware presents is fabricated too. + // The actual, honest-to-goodness physical + // bus that the devices are attached to is not + // addressible natively, and may in fact turn + // out to be not scsi at all. + +#define SCSI_CCISS_CAN_QUEUE 2 + +/* this notation works fine for static initializations (as is the usual + case for linux scsi drivers), but not so well for dynamic settings, + so, if you change this, you also have to change cciss_unregister_scsi() + in cciss_scsi.c */ +#define CCISS_SCSI { \ + name: "", \ + detect: cciss_scsi_detect, \ + release: cciss_scsi_release, \ + proc_info: cciss_scsi_proc_info, \ + queuecommand: cciss_scsi_queue_command, \ + bios_param: scsicam_bios_param, \ + can_queue: SCSI_CCISS_CAN_QUEUE, \ + this_id: 7, \ + sg_tablesize: MAXSGENTRIES, \ + cmd_per_lun: 1, \ + use_clustering: DISABLE_CLUSTERING,\ +} + +/* + info: cciss_scsi_info, \ + +Note, cmd_per_lun could give us some trouble, so I'm setting it very low. +Likewise, SCSI_CCISS_CAN_QUEUE is set very conservatively. + +If the upper scsi layer tries to track how many commands we have +outstanding, it will be operating under the misapprehension that it is +the only one sending us requests. We also have the block interface, +which is where most requests must surely come from, so the upper layer's +notion of how many requests we have outstanding will be wrong most or +all of the time. + +Note, the normal SCSI mid-layer error handling doesn't work well +for this driver because 1) it takes the io_request_lock before +calling error handlers and uses a local variable to store flags, +so the io_request_lock cannot be released and interrupts enabled +inside the error handlers, and, the error handlers cannot poll +for command completion because they might get commands from the +block half of the driver completing, and not know what to do +with them. That's what we get for making a hybrid scsi/block +driver, I suppose. + +*/ + +struct cciss_scsi_dev_t { + int devtype; + int bus, target, lun; /* as presented to the OS */ + unsigned char scsi3addr[8]; /* as presented to the HW */ +}; + +struct cciss_scsi_hba_t { + char *name; + int ndevices; +#define CCISS_MAX_SCSI_DEVS_PER_HBA 16 + struct cciss_scsi_dev_t dev[CCISS_MAX_SCSI_DEVS_PER_HBA]; +}; + +#endif /* _CCISS_SCSI_H_ */ +#endif /* CONFIG_CISS_SCSI_TAPE */ diff -urN linux-2.5.2-pre11/drivers/block/cpqarray.c linux/drivers/block/cpqarray.c --- linux-2.5.2-pre11/drivers/block/cpqarray.c Mon Jan 14 18:28:22 2002 +++ linux/drivers/block/cpqarray.c Mon Jan 14 18:28:28 2002 @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -70,6 +71,7 @@ static int nr_ctlr; static ctlr_info_t *hba[MAX_CTLR]; +static devfs_handle_t de_arr[MAX_CTLR][NWD]; static int eisa[8]; @@ -336,6 +338,7 @@ del_gendisk(&ida_gendisk[i]); } + devfs_unregister(devfs_find_handle(NULL, "ida", 0, 0, 0, 0)); remove_proc_entry("cpqarray", proc_root_driver); kfree(ida); kfree(ida_sizes); @@ -486,6 +489,8 @@ ida_gendisk[i].part = ida + (i*256); ida_gendisk[i].sizes = ida_sizes + (i*256); ida_gendisk[i].nr_real = 0; + ida_gendisk[i].de_arr = de_arr[i]; + ida_gendisk[i].fops = &ida_fops; /* Get on the disk list */ add_gendisk(&ida_gendisk[i]); @@ -1794,6 +1799,14 @@ kfree(id_ldrive); return; + } + if (!de_arr[ctlr][log_unit]) { + char txt[16]; + + sprintf(txt, "ida/c%dd%d", ctlr, + log_unit); + de_arr[ctlr][log_unit] = + devfs_mk_dir(NULL, txt, NULL); } info_p->phys_drives = sense_config_buf->ctlr_phys_drv; diff -urN linux-2.5.2-pre11/drivers/block/elevator.c linux/drivers/block/elevator.c --- linux-2.5.2-pre11/drivers/block/elevator.c Mon Jan 14 18:28:22 2002 +++ linux/drivers/block/elevator.c Mon Jan 14 18:28:28 2002 @@ -58,8 +58,6 @@ next_rq = list_entry(next, struct request, queuelist); - BUG_ON(next_rq->flags & REQ_STARTED); - /* * not a sector based request */ @@ -147,9 +145,10 @@ */ if (q->last_merge) { struct request *__rq = list_entry_rq(q->last_merge); - BUG_ON(__rq->flags & REQ_STARTED); - if ((ret = elv_try_merge(__rq, bio))) + if (!rq_mergeable(__rq)) + q->last_merge = NULL; + else if ((ret = elv_try_merge(__rq, bio))) *req = __rq; } @@ -230,6 +229,12 @@ { elevator_t *e = &q->elevator; int lat = 0, *latency = e->elevator_data; + + /* + * it's a bug to let this rq preempt an already started request + */ + if (insert_here->next != &q->queue_head) + BUG_ON(list_entry_rq(insert_here->next)->flags & REQ_STARTED); if (!(rq->flags & REQ_BARRIER)) lat = latency[rq_data_dir(rq)]; diff -urN linux-2.5.2-pre11/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c --- linux-2.5.2-pre11/drivers/block/ll_rw_blk.c Mon Jan 14 18:28:22 2002 +++ linux/drivers/block/ll_rw_blk.c Mon Jan 14 18:28:28 2002 @@ -818,7 +818,6 @@ q->plug_tq.data = q; q->queue_flags = (1 << QUEUE_FLAG_CLUSTER); q->queue_lock = lock; - q->last_merge = NULL; blk_queue_segment_boundary(q, 0xffffffff); @@ -964,12 +963,6 @@ drive_stat_acct(req, req->nr_sectors, 1); /* - * it's a bug to let this rq preempt an already started request - */ - if (insert_here->next != &q->queue_head) - BUG_ON(list_entry_rq(insert_here->next)->flags & REQ_STARTED); - - /* * elevator indicated where it wants this request to be * inserted at elevator_merge time */ @@ -1121,8 +1114,10 @@ switch (el_ret) { case ELEVATOR_BACK_MERGE: BUG_ON(!rq_mergeable(req)); - if (!q->back_merge_fn(q, req, bio)) + if (!q->back_merge_fn(q, req, bio)) { + insert_here = &req->queuelist; break; + } elv_merge_cleanup(q, req, nr_sectors); @@ -1135,8 +1130,10 @@ case ELEVATOR_FRONT_MERGE: BUG_ON(!rq_mergeable(req)); - if (!q->front_merge_fn(q, req, bio)) + if (!q->front_merge_fn(q, req, bio)) { + insert_here = req->queuelist.prev; break; + } elv_merge_cleanup(q, req, nr_sectors); diff -urN linux-2.5.2-pre11/drivers/block/nbd.c linux/drivers/block/nbd.c --- linux-2.5.2-pre11/drivers/block/nbd.c Mon Jan 14 18:28:22 2002 +++ linux/drivers/block/nbd.c Mon Jan 14 18:28:28 2002 @@ -206,7 +206,7 @@ if (result <= 0) HARDFAIL("Recv control failed."); memcpy(&xreq, reply.handle, sizeof(xreq)); - req = blkdev_entry_prev_request(&lo->queue_head); + req = blkdev_entry_to_request(lo->queue_head.prev); if (xreq != req) FAIL("Unexpected handle received.\n"); @@ -250,7 +250,7 @@ goto out; } #ifdef PARANOIA - if (req != blkdev_entry_prev_request(&lo->queue_head)) { + if (req != blkdev_entry_to_request(lo->queue_head.prev)) { printk(KERN_ALERT "NBD: I have problem...\n"); } if (lo != &nbd_dev[minor(req->rq_dev)]) { @@ -285,7 +285,7 @@ #endif while (!list_empty(&lo->queue_head)) { - req = blkdev_entry_prev_request(&lo->queue_head); + req = blkdev_entry_to_request(lo->queue_head.prev); #ifdef PARANOIA if (!req) { printk( KERN_ALERT "NBD: panic, panic, panic\n" ); diff -urN linux-2.5.2-pre11/drivers/char/rtc.c linux/drivers/char/rtc.c --- linux-2.5.2-pre11/drivers/char/rtc.c Tue Nov 13 09:16:05 2001 +++ linux/drivers/char/rtc.c Mon Jan 14 18:28:28 2002 @@ -785,6 +785,9 @@ printk(KERN_INFO "rtc: %s epoch (%lu) detected\n", guess, epoch); #endif #if RTC_IRQ + if (rtc_has_irq == 0) + goto no_irq2; + init_timer(&rtc_irq_timer); rtc_irq_timer.function = rtc_dropped_irq; spin_lock_irq(&rtc_lock); @@ -792,6 +795,7 @@ CMOS_WRITE(((CMOS_READ(RTC_FREQ_SELECT) & 0xF0) | 0x06), RTC_FREQ_SELECT); spin_unlock_irq(&rtc_lock); rtc_freq = 1024; +no_irq2: #endif printk(KERN_INFO "Real Time Clock Driver v" RTC_VERSION "\n"); diff -urN linux-2.5.2-pre11/drivers/md/md.c linux/drivers/md/md.c --- linux-2.5.2-pre11/drivers/md/md.c Mon Jan 14 18:28:22 2002 +++ linux/drivers/md/md.c Mon Jan 14 18:28:29 2002 @@ -641,7 +641,7 @@ int err = 0; struct block_device *bdev; - bdev = bdget(rdev->dev); + bdev = bdget(kdev_t_to_nr(rdev->dev)); if (!bdev) return -ENOMEM; err = blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_RAW); @@ -3697,7 +3697,7 @@ * Searches all registered partitions for autorun RAID arrays * at boot time. */ -static int detected_devices[128]; +static kdev_t detected_devices[128]; static int dev_cnt; void md_autodetect_dev(kdev_t dev) @@ -3738,7 +3738,7 @@ } dev_cnt = 0; - autorun_devices(-1); + autorun_devices(to_kdev_t(-1)); } static struct { @@ -3855,14 +3855,14 @@ *p++ = 0; dev = name_to_kdev_t(devname); - handle = devfs_find_handle(NULL, devname, MAJOR (dev), MINOR (dev), + handle = devfs_find_handle(NULL, devname, major(dev), minor(dev), DEVFS_SPECIAL_BLK, 1); if (handle != 0) { unsigned major, minor; devfs_get_maj_min(handle, &major, &minor); dev = mk_kdev(major, minor); } - if (!dev) { + if (kdev_none(dev)) { printk(KERN_WARNING "md: Unknown device name: %s\n", devname); break; } @@ -3872,7 +3872,7 @@ devname = p; } - devices[i] = 0; + devices[i] = to_kdev_t(0); if (!md_setup_args.device_set[minor]) continue; @@ -3908,7 +3908,10 @@ ainfo.layout = 0; ainfo.chunk_size = md_setup_args.chunk[minor]; err = set_array_info(mddev, &ainfo); - for (i = 0; !err && (dev = devices[i]); i++) { + for (i = 0; !err && i <= MD_SB_DISKS; i++) { + dev = devices[i]; + if (kdev_none(dev)) + break; dinfo.number = i; dinfo.raid_disk = i; dinfo.state = (1<b_blocknr = bh->b_rsector; bh_req->b_dev = multipath->dev; + /* FIXME - later we will need bdev here */ bh_req->b_rdev = multipath->dev; /* bh_req->b_rsector = bh->n_rsector; */ bh_req->b_end_io = multipath_end_request; diff -urN linux-2.5.2-pre11/drivers/md/raid5.c linux/drivers/md/raid5.c --- linux-2.5.2-pre11/drivers/md/raid5.c Mon Jan 14 18:28:22 2002 +++ linux/drivers/md/raid5.c Mon Jan 14 18:28:29 2002 @@ -469,6 +469,7 @@ init_buffer(bh, raid5_end_read_request, sh); bh->b_dev = conf->disks[i].dev; + /* FIXME - later we will need bdev here */ bh->b_blocknr = block; bh->b_state = (1 << BH_Req) | (1 << BH_Mapped); @@ -1137,6 +1138,7 @@ else if (spare && action[i] == WRITE+1) bh->b_dev = spare->dev; else skip=1; + /* FIXME - later we will need bdev here */ if (!skip) { PRINTK("for %ld schedule op %d on disc %d\n", sh->sector, action[i]-1, i); atomic_inc(&sh->count); diff -urN linux-2.5.2-pre11/drivers/message/i2o/i2o_block.c linux/drivers/message/i2o/i2o_block.c --- linux-2.5.2-pre11/drivers/message/i2o/i2o_block.c Mon Jan 14 18:28:22 2002 +++ linux/drivers/message/i2o/i2o_block.c Mon Jan 14 18:28:29 2002 @@ -892,13 +892,13 @@ u32 m; - while (!list_empty(&q->queue_head)) { + while (!blk_queue_empty(q)) { /* * On an IRQ completion if there is an inactive * request on the queue head it means it isnt yet * ready to dispatch. */ - req = blkdev_entry_next_request(&q->queue_head); + req = elv_next_request(q); if(req->rq_status == RQ_INACTIVE) return; diff -urN linux-2.5.2-pre11/drivers/net/7990.c linux/drivers/net/7990.c --- linux-2.5.2-pre11/drivers/net/7990.c Tue Feb 13 13:15:05 2001 +++ linux/drivers/net/7990.c Mon Jan 14 18:28:29 2002 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -569,7 +570,7 @@ struct dev_mc_list *dmi=dev->mc_list; char *addrs; int i, j, bit, byte; - u32 crc, poly = CRC_POLYNOMIAL_LE; + u32 crc; /* set all multicast bits */ if (dev->flags & IFF_ALLMULTI){ @@ -590,21 +591,7 @@ if (!(*addrs & 1)) continue; - crc = 0xffffffff; - for (byte = 0; byte < 6; byte++) - for (bit = *addrs++, j = 0; j < 8; j++, bit>>=1) - { - int test; - - test = ((bit ^ crc) & 0x01); - crc >>= 1; - - if (test) - { - crc = crc ^ poly; - } - } - + crc = ether_crc_le(6, addrs); crc = crc >> 26; mcast_table [crc >> 4] |= 1 << (crc & 0xf); } diff -urN linux-2.5.2-pre11/drivers/net/7990.h linux/drivers/net/7990.h --- linux-2.5.2-pre11/drivers/net/7990.h Thu Jan 4 13:00:55 2001 +++ linux/drivers/net/7990.h Mon Jan 14 18:28:29 2002 @@ -132,9 +132,6 @@ char tx_full; }; -#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ -#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ - /* * Am7990 Control and Status Registers */ diff -urN linux-2.5.2-pre11/drivers/net/8139cp.c linux/drivers/net/8139cp.c --- linux-2.5.2-pre11/drivers/net/8139cp.c Mon Nov 19 15:19:42 2001 +++ linux/drivers/net/8139cp.c Mon Jan 14 18:28:29 2002 @@ -55,6 +55,7 @@ #include #include #include +#include #include #include @@ -722,22 +723,6 @@ /* Set or clear the multicast filter for this adaptor. This routine is not state sensitive and need not be SMP locked. */ - -static unsigned const ethernet_polynomial = 0x04c11db7U; -static inline u32 ether_crc (int length, unsigned char *data) -{ - int crc = -1; - - while (--length >= 0) { - unsigned char current_octet = *data++; - int bit; - for (bit = 0; bit < 8; bit++, current_octet >>= 1) - crc = (crc << 1) ^ ((crc < 0) ^ (current_octet & 1) ? - ethernet_polynomial : 0); - } - - return crc; -} static void __cp_set_rx_mode (struct net_device *dev) { diff -urN linux-2.5.2-pre11/drivers/net/8139too.c linux/drivers/net/8139too.c --- linux-2.5.2-pre11/drivers/net/8139too.c Sat Nov 24 11:26:37 2001 +++ linux/drivers/net/8139too.c Mon Jan 14 18:28:29 2002 @@ -109,6 +109,7 @@ #include #include #include +#include #include #include @@ -587,7 +588,6 @@ static int rtl8139_close (struct net_device *dev); static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static inline u32 ether_crc (int length, unsigned char *data); static void rtl8139_set_rx_mode (struct net_device *dev); static void __set_rx_mode (struct net_device *dev); static void rtl8139_hw_start (struct net_device *dev); @@ -2370,23 +2370,6 @@ /* Set or clear the multicast filter for this adaptor. This routine is not state sensitive and need not be SMP locked. */ - -static unsigned const ethernet_polynomial = 0x04c11db7U; -static inline u32 ether_crc (int length, unsigned char *data) -{ - int crc = -1; - - while (--length >= 0) { - unsigned char current_octet = *data++; - int bit; - for (bit = 0; bit < 8; bit++, current_octet >>= 1) - crc = (crc << 1) ^ ((crc < 0) ^ (current_octet & 1) ? - ethernet_polynomial : 0); - } - - return crc; -} - static void __set_rx_mode (struct net_device *dev) { diff -urN linux-2.5.2-pre11/drivers/net/8390.c linux/drivers/net/8390.c --- linux-2.5.2-pre11/drivers/net/8390.c Sun Sep 30 12:26:06 2001 +++ linux/drivers/net/8390.c Mon Jan 14 18:28:29 2002 @@ -68,6 +68,7 @@ #include #include #include +#include #include #include @@ -885,27 +886,6 @@ } /* - * Update the given Autodin II CRC value with another data byte. - */ - -static inline u32 update_crc(u8 byte, u32 current_crc) -{ - int bit; - u8 ah = 0; - for (bit=0; bit<8; bit++) - { - u8 carry = (current_crc>>31); - current_crc <<= 1; - ah = ((ah<<1) | carry) ^ byte; - if (ah&1) - current_crc ^= 0x04C11DB7; /* CRC polynomial */ - ah >>= 1; - byte >>= 1; - } - return current_crc; -} - -/* * Form the 64 bit 8390 multicast table from the linked list of addresses * associated with this dev structure. */ @@ -916,16 +896,13 @@ for (dmi=dev->mc_list; dmi; dmi=dmi->next) { - int i; u32 crc; if (dmi->dmi_addrlen != ETH_ALEN) { printk(KERN_INFO "%s: invalid multicast address length given.\n", dev->name); continue; } - crc = 0xffffffff; /* initial CRC value */ - for (i=0; idmi_addr[i], crc); + crc = ether_crc(ETH_ALEN, dmi->dmi_addr); /* * The 8390 uses the 6 most significant bits of the * CRC to index the multicast table. diff -urN linux-2.5.2-pre11/drivers/net/Makefile.lib linux/drivers/net/Makefile.lib --- linux-2.5.2-pre11/drivers/net/Makefile.lib Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/Makefile.lib Mon Jan 14 18:28:29 2002 @@ -0,0 +1,69 @@ +# These drivers all require crc32.o +obj-$(CONFIG_8139CP) += crc32.o +obj-$(CONFIG_8139TOO) += crc32.o +obj-$(CONFIG_A2065) += crc32.o +obj-$(CONFIG_ARM_AM79C961A) += crc32.o +obj-$(CONFIG_AT1700) += crc32.o +obj-$(CONFIG_ATP) += crc32.o +obj-$(CONFIG_DE2104X) += crc32.o +obj-$(CONFIG_DE4X5) += crc32.o +obj-$(CONFIG_DECLANCE) += crc32.o +obj-$(CONFIG_DEPCA) += crc32.o +obj-$(CONFIG_DL2K) += crc32.o +obj-$(CONFIG_DM9102) += crc32.o +obj-$(CONFIG_EPIC100) += crc32.o +obj-$(CONFIG_EWRK3) += crc32.o +obj-$(CONFIG_FEALNX) += crc32.o +obj-$(CONFIG_HAPPYMEAL) += crc32.o +obj-$(CONFIG_MACE) += crc32.o +obj-$(CONFIG_MACMACE) += crc32.o +obj-$(CONFIG_MIPS_AU1000_ENET) += crc32.o +obj-$(CONFIG_NATSEMI) += crc32.o +obj-$(CONFIG_PCMCIA_FMVJ18X) += crc32.o +obj-$(CONFIG_PCMCIA_SMC91C92) += crc32.o +obj-$(CONFIG_PCMCIA_XIRTULIP) += crc32.o +obj-$(CONFIG_PCNET32) += crc32.o +obj-$(CONFIG_SIS900) += crc32.o +obj-$(CONFIG_SMC9194) += crc32.o +obj-$(CONFIG_STARFIRE) += crc32.o +obj-$(CONFIG_SUNBMAC) += crc32.o +obj-$(CONFIG_SUNDANCE) += crc32.o +obj-$(CONFIG_SUNGEM) += crc32.o +obj-$(CONFIG_SUNGEM) += crc32.o +obj-$(CONFIG_SUNLANCE) += crc32.o +obj-$(CONFIG_SUNQE) += crc32.o +obj-$(CONFIG_TULIP) += crc32.o +obj-$(CONFIG_VIA_RHINE) += crc32.o +obj-$(CONFIG_YELLOWFIN) += crc32.o +obj-$(CONFIG_WINBOND_840) += crc32.o + + +# These rely on drivers/net/7990.o which requires crc32.o +obj-$(CONFIG_HPLANCE) += crc32.o +obj-$(CONFIG_MVME147_NET) += crc32.o + + +# These rely on drivers/net/8390.o which requires crc32.o +obj-$(CONFIG_OAKNET) += crc32.o +obj-$(CONFIG_NE2K_PCI) += crc32.o +obj-$(CONFIG_STNIC) += crc32.o +obj-$(CONFIG_MAC8390) += crc32.o +obj-$(CONFIG_APNE) += crc32.o +obj-$(CONFIG_PCMCIA_PCNET) += crc32.o +obj-$(CONFIG_ARM_ETHERH) += crc32.o +obj-$(CONFIG_WD80x3) += crc32.o +obj-$(CONFIG_EL2) += crc32.o +obj-$(CONFIG_NE2000) += crc32.o +obj-$(CONFIG_NE2_MCA) += crc32.o +obj-$(CONFIG_HPLAN) += crc32.o +obj-$(CONFIG_HPLAN_PLUS) += crc32.o +obj-$(CONFIG_ULTRA) += crc32.o +obj-$(CONFIG_ULTRAMCA) += crc32.o +obj-$(CONFIG_ULTRA32) += crc32.o +obj-$(CONFIG_E2100) += crc32.o +obj-$(CONFIG_ES3210) += crc32.o +obj-$(CONFIG_LNE390) += crc32.o +obj-$(CONFIG_NE3210) += crc32.o +obj-$(CONFIG_AC3200) += crc32.o +obj-$(CONFIG_ARIADNE2) += crc32.o +obj-$(CONFIG_HYDRA) += crc32.o diff -urN linux-2.5.2-pre11/drivers/net/a2065.c linux/drivers/net/a2065.c --- linux-2.5.2-pre11/drivers/net/a2065.c Tue Oct 16 21:56:29 2001 +++ linux/drivers/net/a2065.c Mon Jan 14 18:28:29 2002 @@ -6,6 +6,7 @@ * Fixes and tips by: * - Janos Farkas (CHEXUM@sparta.banki.hu) * - Jes Degn Soerensen (jds@kom.auc.dk) + * - Matt Domsch (Matt_Domsch@dell.com) * * ---------------------------------------------------------------------------- * @@ -47,6 +48,7 @@ #include #include #include +#include #include #include @@ -639,7 +641,7 @@ struct dev_mc_list *dmi=dev->mc_list; char *addrs; int i, j, bit, byte; - u32 crc, poly = CRC_POLYNOMIAL_LE; + u32 crc; /* set all multicast bits */ if (dev->flags & IFF_ALLMULTI){ @@ -660,21 +662,7 @@ if (!(*addrs & 1)) continue; - crc = 0xffffffff; - for (byte = 0; byte < 6; byte++) - for (bit = *addrs++, j = 0; j < 8; j++, bit>>=1) - { - int test; - - test = ((bit ^ crc) & 0x01); - crc >>= 1; - - if (test) - { - crc = crc ^ poly; - } - } - + crc = ether_crc_le(6, addrs); crc = crc >> 26; mcast_table [crc >> 4] |= 1 << (crc & 0xf); } diff -urN linux-2.5.2-pre11/drivers/net/a2065.h linux/drivers/net/a2065.h --- linux-2.5.2-pre11/drivers/net/a2065.h Wed Jan 26 12:45:20 2000 +++ linux/drivers/net/a2065.h Mon Jan 14 18:28:29 2002 @@ -43,9 +43,6 @@ }; -#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ -#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ - /* * Am7990 Control and Status Registers */ diff -urN linux-2.5.2-pre11/drivers/net/am79c961a.c linux/drivers/net/am79c961a.c --- linux-2.5.2-pre11/drivers/net/am79c961a.c Wed Jun 27 14:12:04 2001 +++ linux/drivers/net/am79c961a.c Mon Jan 14 18:28:29 2002 @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -308,33 +309,13 @@ return &priv->stats; } -static inline u32 update_crc(u32 crc, u8 byte) -{ - int i; - - for (i = 8; i != 0; i--) { - byte ^= crc & 1; - crc >>= 1; - - if (byte & 1) - crc ^= 0xedb88320; - - byte >>= 1; - } - - return crc; -} - static void am79c961_mc_hash(struct dev_mc_list *dmi, unsigned short *hash) { if (dmi->dmi_addrlen == ETH_ALEN && dmi->dmi_addr[0] & 0x01) { - int i, idx, bit; + int idx, bit; u32 crc; - crc = 0xffffffff; - - for (i = 0; i < ETH_ALEN; i++) - crc = update_crc(crc, dmi->dmi_addr[i]); + crc = ether_crc_le(ETH_ALEN, dmi->dmi_addr); idx = crc >> 30; bit = (crc >> 26) & 15; diff -urN linux-2.5.2-pre11/drivers/net/at1700.c linux/drivers/net/at1700.c --- linux-2.5.2-pre11/drivers/net/at1700.c Wed Oct 10 23:24:09 2001 +++ linux/drivers/net/at1700.c Mon Jan 14 18:28:29 2002 @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -803,27 +804,6 @@ /* Set the multicast/promiscuous mode for this adaptor. */ - -/* The little-endian AUTODIN II ethernet CRC calculation. - N.B. Do not use for bulk data, use a table-based routine instead. - This is common code and should be moved to net/core/crc.c */ -static unsigned const ethernet_polynomial_le = 0xedb88320U; -static inline unsigned ether_crc_le(int length, unsigned char *data) -{ - unsigned int crc = 0xffffffff; /* Initial value. */ - while(--length >= 0) { - unsigned char current_octet = *data++; - int bit; - for (bit = 8; --bit >= 0; current_octet >>= 1) { - if ((crc ^ current_octet) & 1) { - crc >>= 1; - crc ^= ethernet_polynomial_le; - } else - crc >>= 1; - } - } - return crc; -} static void set_rx_mode(struct net_device *dev) diff -urN linux-2.5.2-pre11/drivers/net/atp.c linux/drivers/net/atp.c --- linux-2.5.2-pre11/drivers/net/atp.c Sun Sep 30 12:26:06 2001 +++ linux/drivers/net/atp.c Mon Jan 14 18:28:29 2002 @@ -140,6 +140,7 @@ #include #include #include +#include #include #include @@ -856,26 +857,6 @@ /* * Set or clear the multicast filter for this adapter. */ - -/* The little-endian AUTODIN32 ethernet CRC calculation. - This is common code and should be moved to net/core/crc.c */ -static unsigned const ethernet_polynomial_le = 0xedb88320U; -static inline unsigned ether_crc_le(int length, unsigned char *data) -{ - unsigned int crc = 0xffffffff; /* Initial value. */ - while(--length >= 0) { - unsigned char current_octet = *data++; - int bit; - for (bit = 8; --bit >= 0; current_octet >>= 1) { - if ((crc ^ current_octet) & 1) { - crc >>= 1; - crc ^= ethernet_polynomial_le; - } else - crc >>= 1; - } - } - return crc; -} static void set_rx_mode_8002(struct net_device *dev) { diff -urN linux-2.5.2-pre11/drivers/net/au1000_eth.c linux/drivers/net/au1000_eth.c --- linux-2.5.2-pre11/drivers/net/au1000_eth.c Sun Sep 9 10:43:01 2001 +++ linux/drivers/net/au1000_eth.c Mon Jan 14 18:28:29 2002 @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -1092,22 +1093,6 @@ printk(KERN_ERR "%s: au1000_tx_timeout: dev=%p\n", dev->name, dev); reset_mac(dev); au1000_init(dev); -} - - -static unsigned const ethernet_polynomial = 0x04c11db7U; -static inline u32 ether_crc(int length, unsigned char *data) -{ - int crc = -1; - - while(--length >= 0) { - unsigned char current_octet = *data++; - int bit; - for (bit = 0; bit < 8; bit++, current_octet >>= 1) - crc = (crc << 1) ^ - ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0); - } - return crc; } static void set_rx_mode(struct net_device *dev) diff -urN linux-2.5.2-pre11/drivers/net/bmac.c linux/drivers/net/bmac.c --- linux-2.5.2-pre11/drivers/net/bmac.c Wed Nov 14 15:16:31 2001 +++ linux/drivers/net/bmac.c Mon Jan 14 18:28:29 2002 @@ -1053,16 +1053,13 @@ /* The version of set_multicast below was lifted from sunhme.c */ -#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ -#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ - static void bmac_set_multicast(struct net_device *dev) { struct dev_mc_list *dmi = dev->mc_list; char *addrs; int i, j, bit, byte; unsigned short rx_cfg; - u32 crc, poly = CRC_POLYNOMIAL_LE; + u32 crc; if((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) { bmwrite(dev, BHASH0, 0xffff); @@ -1089,17 +1086,7 @@ if(!(*addrs & 1)) continue; - crc = 0xffffffffU; - for(byte = 0; byte < 6; byte++) { - for(bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) { - int test; - - test = ((bit ^ crc) & 0x01); - crc >>= 1; - if(test) - crc = crc ^ poly; - } - } + crc = ether_crc_le(6, addrs); crc >>= 26; hash_table[crc >> 4] |= 1 << (crc & 0xf); } diff -urN linux-2.5.2-pre11/drivers/net/bonding.c linux/drivers/net/bonding.c --- linux-2.5.2-pre11/drivers/net/bonding.c Tue Nov 13 09:19:41 2001 +++ linux/drivers/net/bonding.c Mon Jan 14 18:28:29 2002 @@ -153,6 +153,14 @@ * * 2001/10/23 - Takao Indoh * - Various memory leak fixes + * + * 2001/11/5 - Mark Huth + * - Don't take rtnl lock in bond_mii_monitor as it deadlocks under + * certain hotswap conditions. + * Note: this same change may be required in bond_arp_monitor ??? + * - Remove possibility of calling bond_sethwaddr with NULL slave_dev ptr + * - Handle hot swap ethernet interface deregistration events to remove + * kernel oops following hot swap of enslaved interface */ #include @@ -185,7 +193,6 @@ #include #include -#include #include #include @@ -257,6 +264,7 @@ static void bond_set_slave_active_flags(slave_t *slave); static int bond_enslave(struct net_device *master, struct net_device *slave); static int bond_release(struct net_device *master, struct net_device *slave); +static int bond_release_all(struct net_device *master); static int bond_sethwaddr(struct net_device *master, struct net_device *slave); /* @@ -372,10 +380,13 @@ static u16 bond_check_mii_link(bonding_t *bond) { int has_active_interface = 0; + unsigned long flags; + read_lock_irqsave(&bond->lock, flags); read_lock(&bond->ptrlock); has_active_interface = (bond->current_slave != NULL); read_unlock(&bond->ptrlock); + read_unlock_irqrestore(&bond->lock, flags); return (has_active_interface ? MII_LINK_READY : 0); } @@ -407,7 +418,6 @@ static int bond_close(struct net_device *master) { bonding_t *bond = (struct bonding *) master->priv; - slave_t *slave; unsigned long flags; write_lock_irqsave(&bond->lock, flags); @@ -418,13 +428,11 @@ if (arp_interval> 0) { /* arp interval, in milliseconds. */ del_timer(&bond->arp_timer); } - /* We need to unlock this because bond_release will re-lock it */ - write_unlock_irqrestore(&bond->lock, flags); /* Release the bonded slaves */ - while ((slave = bond->prev) != (slave_t *)bond) { - bond_release(master, slave->dev); - } + bond_release_all(master); + + write_unlock_irqrestore(&bond->lock, flags); MOD_DEC_USE_COUNT; return 0; @@ -866,6 +874,49 @@ return -EINVAL; } +/* + * This function releases all slaves. + * Warning: must put write-locks around the call to this function. + */ +static int bond_release_all(struct net_device *master) +{ + bonding_t *bond; + slave_t *our_slave; + struct net_device *slave_dev; + + if (master == NULL) { + return -ENODEV; + } + + if (master->flags & IFF_SLAVE) { + return -EINVAL; + } + + bond = (struct bonding *) master->priv; + bond->current_slave = NULL; + + while ((our_slave = bond->prev) != (slave_t *)bond) { + slave_dev = our_slave->dev; + bond->prev = our_slave->prev; + + kfree(our_slave); + + netdev_set_master(slave_dev, NULL); + + /* only restore its RUNNING flag if monitoring set it down */ + if (slave_dev->flags & IFF_UP) + slave_dev->flags |= IFF_RUNNING; + + if (slave_dev->flags & IFF_NOARP) + dev_close(slave_dev); + } + bond->next = (slave_t *)bond; + bond->slave_cnt = 0; + printk (KERN_INFO "%s: releases all slaves\n", master->name); + + return 0; +} + /* this function is called regularly to monitor each slave's link. */ static void bond_mii_monitor(struct net_device *master) { @@ -876,14 +927,6 @@ read_lock_irqsave(&bond->lock, flags); - if (rtnl_shlock_nowait()) { - goto monitor_out; - } - - if (rtnl_exlock_nowait()) { - rtnl_shunlock(); - goto monitor_out; - } /* we will try to read the link status of each of our slaves, and * set their IFF_RUNNING flag appropriately. For each slave not * supporting MII status, we won't do anything so that a user-space @@ -1057,9 +1100,10 @@ } /* end of switch */ } /* end of while */ - /* if there's no active interface and we discovered that one - of the slaves could be activated earlier, so we do it. - */ + /* + * if there's no active interface and we discovered that one + * of the slaves could be activated earlier, so we do it. + */ read_lock(&bond->ptrlock); oldcurrent = bond->current_slave; read_unlock(&bond->ptrlock); @@ -1097,9 +1141,6 @@ } } - rtnl_exunlock(); - rtnl_shunlock(); -monitor_out: read_unlock_irqrestore(&bond->lock, flags); /* re-arm the timer */ mod_timer(&bond->mii_timer, jiffies + (miimon * HZ / 1000)); @@ -1128,17 +1169,17 @@ if (!IS_UP(master)) { mod_timer(&bond->arp_timer, next_timer); - goto monitor_out; + goto arp_monitor_out; } if (rtnl_shlock_nowait()) { - goto monitor_out; + goto arp_monitor_out; } if (rtnl_exlock_nowait()) { rtnl_shunlock(); - goto monitor_out; + goto arp_monitor_out; } /* see if any of the previous devices are up now (i.e. they have seen a @@ -1243,7 +1284,9 @@ * an arp on all of the interfaces */ + read_lock(&bond->ptrlock); if (bond->current_slave == NULL) { + read_unlock(&bond->ptrlock); slave = (slave_t *)bond; while ((slave = slave->prev) != (slave_t *)bond) { arp_send(ARPOP_REQUEST, ETH_P_ARP, arp_target, @@ -1251,11 +1294,14 @@ slave->dev->dev_addr, arp_target_hw_addr); } } + else { + read_unlock(&bond->ptrlock); + } rtnl_exunlock(); rtnl_shunlock(); -monitor_out: +arp_monitor_out: read_unlock_irqrestore(&bond->lock, flags); /* re-arm the timer */ @@ -1367,16 +1413,17 @@ { bonding_t *bond = (struct bonding *) master->priv; slave_t *slave; + unsigned long flags; info->bond_mode = mode; info->num_slaves = 0; info->miimon = miimon; - read_lock(&bond->ptrlock); + read_lock_irqsave(&bond->lock, flags); for (slave = bond->prev; slave!=(slave_t *)bond; slave = slave->prev) { info->num_slaves++; } - read_unlock(&bond->ptrlock); + read_unlock_irqrestore(&bond->lock, flags); return 0; } @@ -1387,27 +1434,28 @@ bonding_t *bond = (struct bonding *) master->priv; slave_t *slave; int cur_ndx = 0; + unsigned long flags; if (info->slave_id < 0) { return -ENODEV; } - read_lock(&bond->ptrlock); + read_lock_irqsave(&bond->lock, flags); for (slave = bond->prev; slave != (slave_t *)bond && cur_ndx < info->slave_id; slave = slave->prev) { cur_ndx++; } + read_unlock_irqrestore(&bond->lock, flags); + if (cur_ndx == info->slave_id) { strcpy(info->slave_name, slave->dev->name); info->link = slave->link; info->state = slave->state; info->link_failure_count = slave->link_failure_count; } else { - read_unlock(&bond->ptrlock); return -ENODEV; } - read_unlock(&bond->ptrlock); return 0; } @@ -1480,40 +1528,40 @@ } slave_dev = dev_get_by_name(ifr->ifr_slave); + #ifdef BONDING_DEBUG printk(KERN_INFO "slave_dev=%x: \n", (unsigned int)slave_dev); printk(KERN_INFO "slave_dev->name=%s: \n", slave_dev->name); #endif - switch (cmd) { - case BOND_ENSLAVE_OLD: - case SIOCBONDENSLAVE: - ret = bond_enslave(master_dev, slave_dev); - break; - case BOND_RELEASE_OLD: - case SIOCBONDRELEASE: - ret = bond_release(master_dev, slave_dev); - break; - case BOND_SETHWADDR_OLD: - case SIOCBONDSETHWADDR: - ret = bond_sethwaddr(master_dev, slave_dev); - break; - case BOND_CHANGE_ACTIVE_OLD: - case SIOCBONDCHANGEACTIVE: - if (mode == BOND_MODE_ACTIVEBACKUP) { - ret = bond_change_active(master_dev, slave_dev); - } - else { - ret = -EINVAL; - } - break; - default: - ret = -EOPNOTSUPP; - } - if (slave_dev) { - /* - * Clear the module reference that was added by dev_get_by_name - */ + if (slave_dev == NULL) { + ret = -ENODEV; + } else { + switch (cmd) { + case BOND_ENSLAVE_OLD: + case SIOCBONDENSLAVE: + ret = bond_enslave(master_dev, slave_dev); + break; + case BOND_RELEASE_OLD: + case SIOCBONDRELEASE: + ret = bond_release(master_dev, slave_dev); + break; + case BOND_SETHWADDR_OLD: + case SIOCBONDSETHWADDR: + ret = bond_sethwaddr(master_dev, slave_dev); + break; + case BOND_CHANGE_ACTIVE_OLD: + case SIOCBONDCHANGEACTIVE: + if (mode == BOND_MODE_ACTIVEBACKUP) { + ret = bond_change_active(master_dev, slave_dev); + } + else { + ret = -EINVAL; + } + break; + default: + ret = -EOPNOTSUPP; + } dev_put(slave_dev); } return ret; @@ -1593,13 +1641,11 @@ } read_lock_irqsave(&bond->lock, flags); - read_lock(&bond->ptrlock); slave = bond->prev; /* we're at the root, get the first slave */ if ((slave == NULL) || (slave->dev == NULL)) { /* no suitable interface, frame not sent */ - read_unlock(&bond->ptrlock); dev_kfree_skb(skb); read_unlock_irqrestore(&bond->lock, flags); return 0; @@ -1607,8 +1653,6 @@ slave_no = (data->h_dest[5]^slave->dev->dev_addr[5]) % bond->slave_cnt; - read_unlock(&bond->ptrlock); - while ( (slave_no > 0) && (slave != (slave_t *)bond) ) { slave = slave->prev; slave_no--; @@ -1749,6 +1793,7 @@ off_t begin = 0; u16 link; slave_t *slave = NULL; + unsigned long flags; while (bond != NULL) { /* @@ -1757,17 +1802,19 @@ */ link = bond_check_mii_link(bond); - read_lock(&bond->ptrlock); - len += sprintf(buf + len, "Bonding Mode: "); len += sprintf(buf + len, "%s\n", mode ? "active-backup" : "load balancing"); if (mode == BOND_MODE_ACTIVEBACKUP) { + read_lock_irqsave(&bond->lock, flags); + read_lock(&bond->ptrlock); if (bond->current_slave != NULL) { len += sprintf(buf + len, "Currently Active Slave: %s\n", bond->current_slave->dev->name); } + read_unlock(&bond->ptrlock); + read_unlock_irqrestore(&bond->lock, flags); } len += sprintf(buf + len, "MII Status: "); @@ -1778,6 +1825,7 @@ len += sprintf(buf + len, "Up Delay (ms): %d\n", updelay); len += sprintf(buf + len, "Down Delay (ms): %d\n", downdelay); + read_lock_irqsave(&bond->lock, flags); for (slave = bond->prev; slave != (slave_t *)bond; slave = slave->prev) { len += sprintf(buf + len, "\nSlave Interface: %s\n", slave->dev->name); @@ -1790,6 +1838,7 @@ len += sprintf(buf + len, "Link Failure Count: %d\n", slave->link_failure_count); } + read_unlock_irqrestore(&bond->lock, flags); /* * Figure out the calcs for the /proc/net interface @@ -1803,7 +1852,6 @@ len = 0; } - read_unlock(&bond->ptrlock); bond = bond->next_bond; } @@ -1844,7 +1892,14 @@ default: return NOTIFY_DONE; } - } + } else if (this_bond->device == event_dev->master) { + switch (event) { + case NETDEV_UNREGISTER: + bond_release(this_bond->device, event_dev); + break; + } + return NOTIFY_DONE; + } this_bond = this_bond->next_bond; } return NOTIFY_DONE; diff -urN linux-2.5.2-pre11/drivers/net/de2104x.c linux/drivers/net/de2104x.c --- linux-2.5.2-pre11/drivers/net/de2104x.c Mon Jan 14 18:28:22 2002 +++ linux/drivers/net/de2104x.c Mon Jan 14 18:28:29 2002 @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -655,41 +656,6 @@ Note that we only use exclusion around actually queueing the new frame, not around filling de->setup_frame. This is non-deterministic when re-entered but still correct. */ - -/* The little-endian AUTODIN32 ethernet CRC calculation. - N.B. Do not use for bulk data, use a table-based routine instead. - This is common code and should be moved to net/core/crc.c */ -static unsigned const ethernet_polynomial_le = 0xedb88320U; -static inline u32 ether_crc_le(int length, unsigned char *data) -{ - u32 crc = 0xffffffff; /* Initial value. */ - while(--length >= 0) { - unsigned char current_octet = *data++; - int bit; - for (bit = 8; --bit >= 0; current_octet >>= 1) { - if ((crc ^ current_octet) & 1) { - crc >>= 1; - crc ^= ethernet_polynomial_le; - } else - crc >>= 1; - } - } - return crc; -} -static unsigned const ethernet_polynomial = 0x04c11db7U; -static inline u32 ether_crc(int length, unsigned char *data) -{ - int crc = -1; - - while(--length >= 0) { - unsigned char current_octet = *data++; - int bit; - for (bit = 0; bit < 8; bit++, current_octet >>= 1) - crc = (crc << 1) ^ - ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0); - } - return crc; -} #undef set_bit_le #define set_bit_le(i,p) do { ((char *)(p))[(i)/8] |= (1<<((i)%8)); } while(0) diff -urN linux-2.5.2-pre11/drivers/net/de4x5.c linux/drivers/net/de4x5.c --- linux-2.5.2-pre11/drivers/net/de4x5.c Sun Sep 30 12:26:06 2001 +++ linux/drivers/net/de4x5.c Mon Jan 14 18:28:29 2002 @@ -436,6 +436,7 @@ 'pb' is now only initialized if a de4x5 chip is present. + 0.547 08-Nov-01 Use library crc32 functions by ========================================================================= */ @@ -457,6 +458,7 @@ #include #include #include +#include #include #include @@ -622,9 +624,6 @@ #define QUEUE_PKT_TIMEOUT (3*HZ) /* 3 second timeout */ -#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ -#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ - /* ** EISA bus defines */ @@ -2050,7 +2049,7 @@ u_long iobase = dev->base_addr; int i, j, bit, byte; u16 hashcode; - u32 omr, crc, poly = CRC_POLYNOMIAL_LE; + u32 omr, crc; char *pa; unsigned char *addrs; @@ -2065,13 +2064,7 @@ addrs=dmi->dmi_addr; dmi=dmi->next; if ((*addrs & 0x01) == 1) { /* multicast address? */ - crc = 0xffffffff; /* init CRC for each address */ - for (byte=0;byte>=1) { - crc = (crc >> 1) ^ (((crc ^ bit) & 0x01) ? poly : 0); - } - } + crc = ether_crc_le(ETH_ALEN, addrs); hashcode = crc & HASH_BITS; /* hashcode is 9 LSb of CRC */ byte = hashcode >> 3; /* bit[3-8] -> byte in filter */ diff -urN linux-2.5.2-pre11/drivers/net/declance.c linux/drivers/net/declance.c --- linux-2.5.2-pre11/drivers/net/declance.c Sun Sep 9 10:45:43 2001 +++ linux/drivers/net/declance.c Mon Jan 14 18:28:29 2002 @@ -79,6 +79,7 @@ #include #include #include +#include #include #include @@ -88,9 +89,6 @@ #endif static int type; -#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ -#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ - #define LE_CSR0 0 #define LE_CSR1 1 #define LE_CSR2 2 @@ -920,7 +918,7 @@ struct dev_mc_list *dmi = dev->mc_list; char *addrs; int i, j, bit, byte; - u32 crc, poly = CRC_POLYNOMIAL_BE; + u32 crc; /* set all multicast bits */ if (dev->flags & IFF_ALLMULTI) { @@ -945,19 +943,7 @@ if (!(*addrs & 1)) continue; - crc = 0xffffffff; - for (byte = 0; byte < 6; byte++) - for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) { - int test; - - test = ((bit ^ crc) & 0x01); - crc >>= 1; - - if (test) { - crc = crc ^ poly; - } - } - + crc = ether_crc(6, addrs); crc = crc >> 26; mcast_table[crc >> 3] |= 1 << (crc & 0xf); } diff -urN linux-2.5.2-pre11/drivers/net/depca.c linux/drivers/net/depca.c --- linux-2.5.2-pre11/drivers/net/depca.c Sun Sep 30 12:26:06 2001 +++ linux/drivers/net/depca.c Mon Jan 14 18:28:29 2002 @@ -228,6 +228,8 @@ by 0.53 12-Jan-01 Release resources on failure, bss tidbits by acme@conectiva.com.br + 0.54 08-Nov-01 use library crc32 functions + by Matt_Domsch@dell.com ========================================================================= */ @@ -245,6 +247,7 @@ #include #include #include +#include #include #include #include @@ -296,9 +299,6 @@ #define RX_BUFF_SZ 1536 /* Buffer size for each Rx buffer */ #define TX_BUFF_SZ 1536 /* Buffer size for each Tx buffer */ -#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ -#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ - /* ** EISA bus defines */ @@ -1225,7 +1225,7 @@ char *addrs; int i, j, bit, byte; u16 hashcode; - s32 crc, poly = CRC_POLYNOMIAL_BE; + u32 crc; if (dev->flags & IFF_ALLMULTI) { /* Set all multicast bits */ for (i=0; i<(HASH_TABLE_LEN>>3); i++) { @@ -1240,13 +1240,7 @@ addrs=dmi->dmi_addr; dmi=dmi->next; if ((*addrs & 0x01) == 1) { /* multicast address? */ - crc = 0xffffffff; /* init CRC for each address */ - for (byte=0;byte>=1) { - crc = (crc << 1) ^ ((((crc<0?1:0) ^ bit) & 0x01) ? poly : 0); - } - } + crc = ether_crc(ETH_ALEN, addrs); hashcode = (crc & 1); /* hashcode is 6 LSb of CRC ... */ for (j=0;j<5;j++) { /* ... in reverse order. */ hashcode = (hashcode << 1) | ((crc>>=1) & 1); diff -urN linux-2.5.2-pre11/drivers/net/dl2k.c linux/drivers/net/dl2k.c --- linux-2.5.2-pre11/drivers/net/dl2k.c Mon Nov 19 15:19:42 2001 +++ linux/drivers/net/dl2k.c Mon Jan 14 18:28:29 2002 @@ -75,7 +75,6 @@ static int find_miiphy (struct net_device *dev); static int parse_eeprom (struct net_device *dev); static int read_eeprom (long ioaddr, int eep_addr); -static unsigned get_crc (unsigned char *p, int len); static int mii_wait_link (struct net_device *dev, int wait); static int mii_set_media (struct net_device *dev); static int mii_get_media (struct net_device *dev); @@ -327,7 +326,7 @@ } /* Check CRC */ - crc = ~get_crc (sromdata, 256 - 4); + crc = ~ether_crc_le(256-4, sromdata); if (psrom->crc != crc) { printk (KERN_ERR "%s: EEPROM data CRC error.\n", dev->name); return -1; @@ -972,23 +971,6 @@ return 0; } -#define CRC_POLY 0xedb88320 -static unsigned -get_crc (unsigned char *p, int len) -{ - int bit; - unsigned char byte; - unsigned crc = 0xffffffff; - - while (--len >= 0) { - byte = *p++; - for (bit = 0; bit < 8; bit++, byte >>= 1) { - crc = (crc >> 1) ^ (((crc ^ byte) & 1) ? CRC_POLY : 0); - } - } - return crc; -} - static void set_multicast (struct net_device *dev) { @@ -1023,7 +1005,7 @@ for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; i++, mclist = mclist->next) { - set_bit (get_crc (mclist->dmi_addr, ETH_ALEN) & 0x3f, + set_bit (ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f, hash_table); } writel (hash_table[0], ioaddr + HashTable0); diff -urN linux-2.5.2-pre11/drivers/net/dl2k.h linux/drivers/net/dl2k.h --- linux-2.5.2-pre11/drivers/net/dl2k.h Mon Nov 19 15:19:42 2001 +++ linux/drivers/net/dl2k.h Mon Jan 14 18:28:29 2002 @@ -26,6 +26,7 @@ #include #include #include +#include #include /* Processor type for cache alignment. */ #include #include diff -urN linux-2.5.2-pre11/drivers/net/dmfe.c linux/drivers/net/dmfe.c --- linux-2.5.2-pre11/drivers/net/dmfe.c Fri Nov 9 13:50:01 2001 +++ linux/drivers/net/dmfe.c Mon Jan 14 18:28:29 2002 @@ -84,6 +84,7 @@ #include #include #include +#include #include #include @@ -288,72 +289,6 @@ static u8 SF_mode; /* Special Function: 1:VLAN, 2:RX Flow Control 4: TX pause packet */ -unsigned long CrcTable[256] = { - 0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL, - 0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L, - 0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L, - 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L, - 0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL, - 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L, - 0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL, - 0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L, - 0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L, - 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL, - 0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L, - 0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L, - 0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L, - 0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL, - 0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L, - 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL, - 0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL, - 0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L, - 0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L, - 0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L, - 0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL, - 0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L, - 0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL, - 0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L, - 0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L, - 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL, - 0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L, - 0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L, - 0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L, - 0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL, - 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L, - 0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL, - 0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL, - 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L, - 0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L, - 0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L, - 0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL, - 0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L, - 0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL, - 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L, - 0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L, - 0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL, - 0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L, - 0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L, - 0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L, - 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL, - 0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L, - 0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL, - 0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL, - 0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L, - 0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L, - 0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L, - 0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL, - 0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L, - 0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL, - 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L, - 0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L, - 0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL, - 0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L, - 0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L, - 0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L, - 0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL, - 0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L, - 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL -}; /* function declaration ------------------------------------- */ static int dmfe_open(struct DEVICE *); @@ -382,7 +317,7 @@ static void dmfe_dynamic_reset(struct DEVICE *); static void dmfe_free_rxbuffer(struct dmfe_board_info *); static void dmfe_init_dm910x(struct DEVICE *); -static unsigned long cal_CRC(unsigned char *, unsigned int, u8); +static inline u32 cal_CRC(unsigned char *, unsigned int, u8); static void dmfe_parse_srom(struct dmfe_board_info *); static void dmfe_program_DM9801(struct dmfe_board_info *, int); static void dmfe_program_DM9802(struct dmfe_board_info *); @@ -1851,18 +1786,11 @@ * 0 : return the normal CRC (for Hash Table index) */ -unsigned long cal_CRC(unsigned char * Data, unsigned int Len, u8 flag) +static inline u32 cal_CRC(unsigned char * Data, unsigned int Len, u8 flag) { - unsigned long Crc = 0xffffffff; - - while (Len--) { - Crc = CrcTable[(Crc ^ *Data++) & 0xFF] ^ (Crc >> 8); - } - - if (flag) - return ~Crc; - else - return Crc; + u32 crc = crc32(~0, Data, Len); + if (flag) crc = ~crc; + return crc; } diff -urN linux-2.5.2-pre11/drivers/net/epic100.c linux/drivers/net/epic100.c --- linux-2.5.2-pre11/drivers/net/epic100.c Sun Sep 30 12:26:06 2001 +++ linux/drivers/net/epic100.c Mon Jan 14 18:28:29 2002 @@ -124,6 +124,7 @@ #include #include #include +#include #include #include #include @@ -1301,27 +1302,6 @@ Note that we only use exclusion around actually queueing the new frame, not around filling ep->setup_frame. This is non-deterministic when re-entered but still correct. */ - -/* The little-endian AUTODIN II ethernet CRC calculation. - N.B. Do not use for bulk data, use a table-based routine instead. - This is common code and should be moved to net/core/crc.c */ -static unsigned const ethernet_polynomial_le = 0xedb88320U; -static inline unsigned ether_crc_le(int length, unsigned char *data) -{ - unsigned int crc = 0xffffffff; /* Initial value. */ - while(--length >= 0) { - unsigned char current_octet = *data++; - int bit; - for (bit = 8; --bit >= 0; current_octet >>= 1) { - if ((crc ^ current_octet) & 1) { - crc >>= 1; - crc ^= ethernet_polynomial_le; - } else - crc >>= 1; - } - } - return crc; -} static void set_rx_mode(struct net_device *dev) { diff -urN linux-2.5.2-pre11/drivers/net/ewrk3.c linux/drivers/net/ewrk3.c --- linux-2.5.2-pre11/drivers/net/ewrk3.c Sun Sep 30 12:26:06 2001 +++ linux/drivers/net/ewrk3.c Mon Jan 14 18:28:29 2002 @@ -132,6 +132,7 @@ . 0.42 22-Apr-96 Fix alloc_device() bug 0.43 16-Aug-96 Update alloc_device() to conform to de4x5.c + 0.44 08-Nov-01 use library crc32 functions ========================================================================= */ @@ -148,6 +149,7 @@ #include #include #include +#include #include #include #include @@ -207,9 +209,6 @@ #define EISA_SLOT_INC 0x1000 #endif -#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ -#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ - #define QUEUE_PKT_TIMEOUT (1*HZ) /* Jiffies */ /* @@ -1174,10 +1173,10 @@ struct dev_mc_list *dmi = dev->mc_list; u_long iobase = dev->base_addr; int i; - char *addrs, j, bit, byte; + char *addrs, bit, byte; short *p = (short *) lp->mctbl; u16 hashcode; - s32 crc, poly = CRC_POLYNOMIAL_LE; + u32 crc; spin_lock_irq(&lp->hw_lock); @@ -1219,13 +1218,7 @@ addrs = dmi->dmi_addr; dmi = dmi->next; if ((*addrs & 0x01) == 1) { /* multicast address? */ - crc = 0xffffffff; /* init CRC for each address */ - for (byte = 0; byte < ETH_ALEN; byte++) { /* for each address byte */ - /* process each address bit */ - for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) { - crc = (crc >> 1) ^ (((crc ^ bit) & 0x01) ? poly : 0); - } - } + crc = ether_crc_le(ETH_ALEN, addrs); hashcode = crc & ((1 << 9) - 1); /* hashcode is 9 LSb of CRC */ byte = hashcode >> 3; /* bit[3-8] -> byte in filter */ diff -urN linux-2.5.2-pre11/drivers/net/fealnx.c linux/drivers/net/fealnx.c --- linux-2.5.2-pre11/drivers/net/fealnx.c Mon Nov 19 15:19:42 2001 +++ linux/drivers/net/fealnx.c Mon Jan 14 18:28:29 2002 @@ -72,6 +72,7 @@ #include #include #include +#include #include /* Processor type for cache alignment. */ #include #include @@ -426,7 +427,6 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev); static void intr_handler(int irq, void *dev_instance, struct pt_regs *regs); static int netdev_rx(struct net_device *dev); -static inline unsigned ether_crc(int length, unsigned char *data); 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); @@ -1710,26 +1710,6 @@ return &np->stats; } - - -static unsigned const ethernet_polynomial = 0x04c11db7U; -static inline u32 ether_crc(int length, unsigned char *data) -{ - int crc = -1; - - while (--length >= 0) { - unsigned char current_octet = *data++; - int bit; - - for (bit = 0; bit < 8; bit++, current_octet >>= 1) { - crc = (crc << 1) ^ - ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0); - } - } - - return crc; -} - static void set_rx_mode(struct net_device *dev) { diff -urN linux-2.5.2-pre11/drivers/net/gmac.c linux/drivers/net/gmac.c --- linux-2.5.2-pre11/drivers/net/gmac.c Tue Oct 16 21:56:29 2001 +++ linux/drivers/net/gmac.c Mon Jan 14 18:28:29 2002 @@ -16,6 +16,8 @@ * - PHY updates * BenH - 08/08/2001 * - Add more PHYs, fixes to sleep code + * Matt Domsch - 11/12/2001 + * - use library crc32 functions */ #include @@ -33,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -997,14 +1000,13 @@ * Configure promisc mode and setup multicast hash table * filter */ -#define CRC_POLY 0xedb88320 static void gmac_set_multicast(struct net_device *dev) { struct gmac *gm = (struct gmac *) dev->priv; struct dev_mc_list *dmi = dev->mc_list; int i,j,k,b; - unsigned long crc; + u32 crc; int multicast_hash = 0; int multicast_all = 0; int promisc = 0; @@ -1027,17 +1029,7 @@ hash_table[i] = 0; for (i = 0; i < dev->mc_count; i++) { - crc = ~0; - for (j = 0; j < 6; ++j) { - b = dmi->dmi_addr[j]; - for (k = 0; k < 8; ++k) { - if ((crc ^ b) & 1) - crc = (crc >> 1) ^ CRC_POLY; - else - crc >>= 1; - b >>= 1; - } - } + crc = ether_crc_le(6, dmi->dmi_addr); j = crc >> 24; /* bit number in multicast_filter */ hash_table[j >> 4] |= 1 << (15 - (j & 0xf)); dmi = dmi->next; diff -urN linux-2.5.2-pre11/drivers/net/ioc3-eth.c linux/drivers/net/ioc3-eth.c --- linux-2.5.2-pre11/drivers/net/ioc3-eth.c Tue Oct 16 21:56:29 2001 +++ linux/drivers/net/ioc3-eth.c Mon Jan 14 18:28:29 2002 @@ -33,6 +33,7 @@ #include #include #include +#include #ifdef CONFIG_SERIAL #include @@ -1611,27 +1612,16 @@ * Given a multicast ethernet address, this routine calculates the * address's bit index in the logical address filter mask */ -#define CRC_MASK 0xedb88320 static inline unsigned int ioc3_hash(const unsigned char *addr) { unsigned int temp = 0; unsigned char byte; - unsigned int crc; - int bits, len; + u32 crc; + int bits; - len = ETH_ALEN; - for (crc = ~0; --len >= 0; addr++) { - byte = *addr; - for (bits = 8; --bits >= 0; ) { - if ((byte ^ crc) & 1) - crc = (crc >> 1) ^ CRC_MASK; - else - crc >>= 1; - byte >>= 1; - } - } + crc = ether_crc_le(ETH_ALEN, addr); crc &= 0x3f; /* bit reverse lowest 6 bits for hash index */ for (bits = 6; --bits >= 0; ) { diff -urN linux-2.5.2-pre11/drivers/net/mace.c linux/drivers/net/mace.c --- linux-2.5.2-pre11/drivers/net/mace.c Tue Oct 16 21:56:29 2001 +++ linux/drivers/net/mace.c Mon Jan 14 18:28:29 2002 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -508,17 +509,12 @@ return &p->stats; } -/* - * CRC polynomial - used in working out multicast filter bits. - */ -#define CRC_POLY 0xedb88320 - static void mace_set_multicast(struct net_device *dev) { struct mace_data *mp = (struct mace_data *) dev->priv; volatile struct mace *mb = mp->mace; - int i, j, k, b; - unsigned long crc; + int i, j; + u32 crc; mp->maccc &= ~PROM; if (dev->flags & IFF_PROMISC) { @@ -534,17 +530,7 @@ for (i = 0; i < 8; i++) multicast_filter[i] = 0; for (i = 0; i < dev->mc_count; i++) { - crc = ~0; - for (j = 0; j < 6; ++j) { - b = dmi->dmi_addr[j]; - for (k = 0; k < 8; ++k) { - if ((crc ^ b) & 1) - crc = (crc >> 1) ^ CRC_POLY; - else - crc >>= 1; - b >>= 1; - } - } + crc = ether_crc_le(6, dmi->dmi_addr); j = crc >> 26; /* bit number in multicast_filter */ multicast_filter[j >> 3] |= 1 << (j & 7); dmi = dmi->next; diff -urN linux-2.5.2-pre11/drivers/net/macmace.c linux/drivers/net/macmace.c --- linux-2.5.2-pre11/drivers/net/macmace.c Thu Apr 12 12:15:25 2001 +++ linux/drivers/net/macmace.c Mon Jan 14 18:28:29 2002 @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -539,17 +540,12 @@ return &p->stats; } -/* - * CRC polynomial - used in working out multicast filter bits. - */ -#define CRC_POLY 0xedb88320 - static void mace68k_set_multicast(struct net_device *dev) { struct mace68k_data *mp = (struct mace68k_data *) dev->priv; volatile struct mace *mb = mp->mace; int i, j, k, b; - unsigned long crc; + u32 crc; mp->maccc &= ~PROM; if (dev->flags & IFF_PROMISC) @@ -570,19 +566,7 @@ multicast_filter[i] = 0; for (i = 0; i < dev->mc_count; i++) { - crc = ~0; - for (j = 0; j < 6; ++j) - { - b = dmi->dmi_addr[j]; - for (k = 0; k < 8; ++k) - { - if ((crc ^ b) & 1) - crc = (crc >> 1) ^ CRC_POLY; - else - crc >>= 1; - b >>= 1; - } - } + crc = ether_crc_le(6, dmi->dmi_addr); j = crc >> 26; /* bit number in multicast_filter */ multicast_filter[j >> 3] |= 1 << (j & 7); dmi = dmi->next; diff -urN linux-2.5.2-pre11/drivers/net/myri_code.h linux/drivers/net/myri_code.h --- linux-2.5.2-pre11/drivers/net/myri_code.h Wed Apr 23 19:01:20 1997 +++ linux/drivers/net/myri_code.h Mon Jan 14 18:28:29 2002 @@ -6284,4 +6284,4 @@ #define MYRI_NetReceiveBadCrcs 0xB8D4 #define MYRI_NetReceiveBytes 0xB8DC -#endif SYMBOL_DEFINES_COMPILED +#endif /* SYMBOL_DEFINES_COMPILED */ diff -urN linux-2.5.2-pre11/drivers/net/myri_sbus.c linux/drivers/net/myri_sbus.c --- linux-2.5.2-pre11/drivers/net/myri_sbus.c Fri Oct 19 08:32:28 2001 +++ linux/drivers/net/myri_sbus.c Mon Jan 14 18:28:29 2002 @@ -800,9 +800,6 @@ static struct net_device_stats *myri_get_stats(struct net_device *dev) { return &(((struct myri_eth *)dev->priv)->enet_stats); } -#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ -#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ - static void myri_set_multicast(struct net_device *dev) { /* Do nothing, all MyriCOM nodes transmit multicast frames diff -urN linux-2.5.2-pre11/drivers/net/natsemi.c linux/drivers/net/natsemi.c --- linux-2.5.2-pre11/drivers/net/natsemi.c Mon Nov 19 15:19:42 2001 +++ linux/drivers/net/natsemi.c Mon Jan 14 18:28:29 2002 @@ -102,6 +102,9 @@ version 1.0.13: * ETHTOOL_[GS]EEPROM support (Tim Hockin) + version 1.0.13: + * crc cleanup (Matt Domsch ) + TODO: * big endian support with CFG:BEM instead of cpu_to_le32 * support for an external PHY @@ -110,7 +113,7 @@ #define DRV_NAME "natsemi" #define DRV_VERSION "1.07+LK1.0.13" -#define DRV_RELDATE "Oct 19, 2001" +#define DRV_RELDATE "Nov 12, 2001" /* Updated to recommendations in pci-skeleton v2.03. */ @@ -1706,36 +1709,15 @@ return &np->stats; } -/* The little-endian AUTODIN II ethernet CRC calculations. - A big-endian version is also available. - This is slow but compact code. Do not use this routine for bulk data, - use a table-based routine instead. - This is common code and should be moved to net/core/crc.c. - Chips may use the upper or lower CRC bits, and may reverse and/or invert - them. Select the endian-ness that results in minimal calculations. -*/ -#if 0 -static unsigned const ethernet_polynomial_le = 0xedb88320U; -static inline unsigned ether_crc_le(int length, unsigned char *data) -{ - unsigned int crc = 0xffffffff; /* Initial value. */ - while(--length >= 0) { - unsigned char current_octet = *data++; - int bit; - for (bit = 8; --bit >= 0; current_octet >>= 1) { - if ((crc ^ current_octet) & 1) { - crc >>= 1; - crc ^= ethernet_polynomial_le; - } else - crc >>= 1; - } - } - return crc; -} -#else +/** + * dp83815_crc - computer CRC for hash table entries + * + * Note - this is, for some reason, *not* the same function + * as ether_crc_le() or ether_crc(), though it uses the + * same big-endian polynomial. + */ #define DP_POLYNOMIAL 0x04C11DB7 -/* dp83815_crc - computer CRC for hash table entries */ -static unsigned ether_crc_le(int length, unsigned char *data) +static unsigned dp83815_crc(int length, unsigned char *data) { u32 crc; u8 cur_byte; @@ -1759,7 +1741,7 @@ return (crc); } -#endif + void set_bit_le(int offset, unsigned char * data) { @@ -1788,7 +1770,7 @@ memset(mc_filter, 0, sizeof(mc_filter)); for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; i++, mclist = mclist->next) { - set_bit_le(ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x1ff, + set_bit_le(dp83815_crc(ETH_ALEN, mclist->dmi_addr) & 0x1ff, mc_filter); } rx_mode = RxFilterEnable | AcceptBroadcast diff -urN linux-2.5.2-pre11/drivers/net/pci-skeleton.c linux/drivers/net/pci-skeleton.c --- linux-2.5.2-pre11/drivers/net/pci-skeleton.c Tue Oct 16 21:56:29 2001 +++ linux/drivers/net/pci-skeleton.c Mon Jan 14 18:28:29 2002 @@ -96,6 +96,7 @@ #include #include #include +#include #include #define NETDRV_VERSION "1.0.0" @@ -509,7 +510,6 @@ static int netdrv_close (struct net_device *dev); static int netdrv_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); static struct net_device_stats *netdrv_get_stats (struct net_device *dev); -static inline u32 ether_crc (int length, unsigned char *data); static void netdrv_set_rx_mode (struct net_device *dev); static void netdrv_hw_start (struct net_device *dev); @@ -1852,27 +1852,6 @@ /* Set or clear the multicast filter for this adaptor. This routine is not state sensitive and need not be SMP locked. */ - -static unsigned const ethernet_polynomial = 0x04c11db7U; -static inline u32 ether_crc (int length, unsigned char *data) -{ - int crc = -1; - - DPRINTK ("ENTER\n"); - - while (--length >= 0) { - unsigned char current_octet = *data++; - int bit; - for (bit = 0; bit < 8; bit++, current_octet >>= 1) - crc = (crc << 1) ^ - ((crc < 0) ^ (current_octet & 1) ? - ethernet_polynomial : 0); - } - - DPRINTK ("EXIT\n"); - return crc; -} - static void netdrv_set_rx_mode (struct net_device *dev) { diff -urN linux-2.5.2-pre11/drivers/net/pcmcia/fmvj18x_cs.c linux/drivers/net/pcmcia/fmvj18x_cs.c --- linux-2.5.2-pre11/drivers/net/pcmcia/fmvj18x_cs.c Mon Jan 14 18:28:23 2002 +++ linux/drivers/net/pcmcia/fmvj18x_cs.c Mon Jan 14 18:28:29 2002 @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -1180,27 +1181,6 @@ /* Set the multicast/promiscuous mode for this adaptor. */ - -/* The little-endian AUTODIN II ethernet CRC calculation. - N.B. Do not use for bulk data, use a table-based routine instead. - This is common code and should be moved to net/core/crc.c */ -static unsigned const ethernet_polynomial_le = 0xedb88320U; -static inline unsigned ether_crc_le(int length, unsigned char *data) -{ - unsigned int crc = 0xffffffff; /* Initial value. */ - while(--length >= 0) { - unsigned char current_octet = *data++; - int bit; - for (bit = 8; --bit >= 0; current_octet >>= 1) { - if ((crc ^ current_octet) & 1) { - crc >>= 1; - crc ^= ethernet_polynomial_le; - } else - crc >>= 1; - } - } - return crc; -} static void set_rx_mode(struct net_device *dev) { diff -urN linux-2.5.2-pre11/drivers/net/pcmcia/smc91c92_cs.c linux/drivers/net/pcmcia/smc91c92_cs.c --- linux-2.5.2-pre11/drivers/net/pcmcia/smc91c92_cs.c Tue Nov 13 09:02:30 2001 +++ linux/drivers/net/pcmcia/smc91c92_cs.c Mon Jan 14 18:28:29 2002 @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -1740,31 +1741,6 @@ return &smc->stats; } -/*====================================================================== - - Compute the AUTODIN polynomial "CRC32" for ethernet packets. - -======================================================================*/ - -static const u_int ethernet_polynomial = 0x04c11db7U; - -static u_int ether_crc(int length, u_char *data) -{ - int crc = 0xffffffff; /* Initial value. */ - - while (--length >= 0) { - u_char current_octet = *data++; - int bit; - for (bit = 0; bit < 8; bit++, current_octet >>= 1) { - crc = (crc << 1) ^ - ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0); - } - } - /* The hash index is the either the upper or lower bits of the CRC, so - * we return the entire CRC. - */ - return crc; -} /*====================================================================== diff -urN linux-2.5.2-pre11/drivers/net/pcmcia/xircom_tulip_cb.c linux/drivers/net/pcmcia/xircom_tulip_cb.c --- linux-2.5.2-pre11/drivers/net/pcmcia/xircom_tulip_cb.c Fri Nov 9 13:41:42 2001 +++ linux/drivers/net/pcmcia/xircom_tulip_cb.c Mon Jan 14 18:28:29 2002 @@ -101,6 +101,7 @@ #include #include #include +#include #include #include /* Processor type for cache alignment. */ @@ -1517,43 +1518,6 @@ return -EOPNOTSUPP; } - - -/* The little-endian AUTODIN32 ethernet CRC calculation. - N.B. Do not use for bulk data, use a table-based routine instead. - This is common code and should be moved to net/core/crc.c */ -static unsigned const ethernet_polynomial_le = 0xedb88320U; -static inline u32 ether_crc_le(int length, unsigned char *data) -{ - u32 crc = 0xffffffff; /* Initial value. */ - while(--length >= 0) { - unsigned char current_octet = *data++; - int bit; - for (bit = 8; --bit >= 0; current_octet >>= 1) { - if ((crc ^ current_octet) & 1) { - crc >>= 1; - crc ^= ethernet_polynomial_le; - } else - crc >>= 1; - } - } - return crc; -} -static unsigned const ethernet_polynomial = 0x04c11db7U; -static inline u32 ether_crc(int length, unsigned char *data) -{ - int crc = -1; - - while(--length >= 0) { - unsigned char current_octet = *data++; - int bit; - for (bit = 0; bit < 8; bit++, current_octet >>= 1) - crc = (crc << 1) ^ - ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0); - } - return crc; -} - /* Set or clear the multicast filter for this adaptor. Note that we only use exclusion around actually queueing the diff -urN linux-2.5.2-pre11/drivers/net/pcnet32.c linux/drivers/net/pcnet32.c --- linux-2.5.2-pre11/drivers/net/pcnet32.c Sun Nov 11 10:09:33 2001 +++ linux/drivers/net/pcnet32.c Mon Jan 14 18:28:29 2002 @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -215,8 +216,6 @@ #define PCNET32_TOTAL_SIZE 0x20 -#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ - /* The PCNET32 Rx and Tx ring descriptors. */ struct pcnet32_rx_head { u32 base; @@ -1425,8 +1424,8 @@ volatile u16 *mcast_table = (u16 *)&ib->filter; struct dev_mc_list *dmi=dev->mc_list; char *addrs; - int i, j, bit, byte; - u32 crc, poly = CRC_POLYNOMIAL_LE; + int i; + u32 crc; /* set all multicast bits */ if (dev->flags & IFF_ALLMULTI){ @@ -1447,19 +1446,7 @@ if (!(*addrs & 1)) continue; - crc = 0xffffffff; - for (byte = 0; byte < 6; byte++) - for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) { - int test; - - test = ((bit ^ crc) & 0x01); - crc >>= 1; - - if (test) { - crc = crc ^ poly; - } - } - + crc = ether_crc_le(6, addrs); crc = crc >> 26; mcast_table [crc >> 4] |= 1 << (crc & 0xf); } diff -urN linux-2.5.2-pre11/drivers/net/shaper.c linux/drivers/net/shaper.c --- linux-2.5.2-pre11/drivers/net/shaper.c Sun Sep 30 12:26:07 2001 +++ linux/drivers/net/shaper.c Mon Jan 14 18:28:29 2002 @@ -737,6 +737,11 @@ static void __exit shaper_exit (void) { + int i; + + for (i = 0; i < shapers; i++) + unregister_netdev(&devs[i]); + kfree(devs); devs = NULL; } diff -urN linux-2.5.2-pre11/drivers/net/sis900.c linux/drivers/net/sis900.c --- linux-2.5.2-pre11/drivers/net/sis900.c Tue Oct 9 15:13:03 2001 +++ linux/drivers/net/sis900.c Mon Jan 14 18:28:29 2002 @@ -1,6 +1,6 @@ /* sis900.c: A SiS 900/7016 PCI Fast Ethernet driver for Linux. Copyright 1999 Silicon Integrated System Corporation - Revision: 1.08.01 Aug. 25 2001 + Revision: 1.08.02 Jan. 4 2002 Modified from the driver which is originally written by Donald Becker. @@ -18,6 +18,7 @@ preliminary Rev. 1.0 Jan. 18, 1998 http://www.sis.com.tw/support/databook.htm + Rev 1.08.02 Jan. 4 2002 Matt Domsch update to use library crc32 function Rev 1.08.01 Aug. 25 2001 Hui-Fen Hsu update for 630ET & workaround for ICS1893 PHY Rev 1.08.00 Jun. 11 2001 Hui-Fen Hsu workaround for RTL8201 PHY and some bug fix Rev 1.07.11 Apr. 2 2001 Hui-Fen Hsu updates PCI drivers to use the new pci_set_dma_mask for kernel 2.4.3 @@ -62,11 +63,12 @@ #include #include #include +#include #include "sis900.h" static char version[] __devinitdata = -KERN_INFO "sis900.c: v1.08.01 9/25/2001\n"; +KERN_INFO "sis900.c: v1.08.02 1/4/2002\n"; static int max_interrupt_work = 40; static int multicast_filter_limit = 128; @@ -1928,26 +1930,7 @@ static u16 sis900_compute_hashtable_index(u8 *addr, u8 revision) { -/* what is the correct value of the POLYNOMIAL ?? - Donald Becker use 0x04C11DB7U - Joseph Zbiciak im14u2c@primenet.com gives me the - correct answer, thank you Joe !! */ -#define POLYNOMIAL 0x04C11DB7L - u32 crc = 0xffffffff, msb; - int i, j; - u32 byte; - - for (i = 0; i < 6; i++) { - byte = *addr++; - for (j = 0; j < 8; j++) { - msb = crc >> 31; - crc <<= 1; - if (msb ^ (byte & 1)) { - crc ^= POLYNOMIAL; - } - byte >>= 1; - } - } + u32 crc = ether_crc(6, addr); /* leave 8 or 7 most siginifant bits */ if ((revision == SIS635A_900_REV) || (revision == SIS900B_900_REV)) diff -urN linux-2.5.2-pre11/drivers/net/sk98lin/h/skdrv1st.h linux/drivers/net/sk98lin/h/skdrv1st.h --- linux-2.5.2-pre11/drivers/net/sk98lin/h/skdrv1st.h Sun Sep 9 10:45:43 2001 +++ linux/drivers/net/sk98lin/h/skdrv1st.h Mon Jan 14 18:28:29 2002 @@ -116,6 +116,7 @@ #include #include #include +#include #include #include #include diff -urN linux-2.5.2-pre11/drivers/net/sk98lin/skaddr.c linux/drivers/net/sk98lin/skaddr.c --- linux-2.5.2-pre11/drivers/net/sk98lin/skaddr.c Wed Jul 4 11:50:39 2001 +++ linux/drivers/net/sk98lin/skaddr.c Mon Jan 14 18:28:29 2002 @@ -199,7 +199,6 @@ /* defines ********************************************************************/ -#define CRC32_POLY 0xEDB88320UL /* CRC32-Poly - XMAC: Little Endian */ #define HASH_BITS 6 /* #bits in hash */ #define SK_MC_BIT 0x01 @@ -534,18 +533,9 @@ unsigned SkCrc32McHash( unsigned char *pMc) /* Multicast address */ { - unsigned Idx; - unsigned Bit; - unsigned Data; - unsigned Crc; - - Crc = 0xFFFFFFFFUL; - for (Idx = 0; Idx < SK_MAC_ADDR_LEN; Idx++) { - Data = *pMc++; - for (Bit = 0; Bit < 8; Bit++, Data >>= 1) { - Crc = (Crc >> 1) ^ (((Crc ^ Data) & 1) ? CRC32_POLY : 0); - } - } + u32 Crc; + + Crc = ether_crc_le(SK_MAC_ADDR_LEN, pMc); return (Crc & ((1 << HASH_BITS) - 1)); } /* SkCrc32McHash */ diff -urN linux-2.5.2-pre11/drivers/net/smc9194.c linux/drivers/net/smc9194.c --- linux-2.5.2-pre11/drivers/net/smc9194.c Tue Oct 16 21:56:29 2001 +++ linux/drivers/net/smc9194.c Mon Jan 14 18:28:29 2002 @@ -51,6 +51,7 @@ . allocation . 08/20/00 Arnaldo Melo fix kfree(skb) in smc_hardware_send_packet . 12/15/00 Christian Jullien fix "Warning: kfree_skb on hard IRQ" + . 11/08/01 Matt Domsch Use common crc32 function ----------------------------------------------------------------------------*/ static const char version[] = @@ -69,6 +70,7 @@ #include #include #include +#include #include #include #include @@ -223,10 +225,6 @@ */ static void smc_set_multicast_list(struct net_device *dev); -/* - . CRC compute - */ -static int crc32( char * s, int length ); /*--------------------------------------------------------------- . @@ -436,7 +434,7 @@ continue; /* only use the low order bits */ - position = crc32( cur_addr->dmi_addr, 6 ) & 0x3f; + position = ether_crc_le(6, cur_addr->dmi_addr) & 0x3f; /* do some messy swapping to put the bit in the right spot */ multicast_table[invert3[position&7]] |= @@ -450,33 +448,6 @@ outb( multicast_table[i], ioaddr + MULTICAST1 + i ); } } - -/* - Finds the CRC32 of a set of bytes. - Again, from Peter Cammaert's code. -*/ -static int crc32( char * s, int length ) { - /* indices */ - int perByte; - int perBit; - /* crc polynomial for Ethernet */ - const unsigned long poly = 0xedb88320; - /* crc value - preinitialized to all 1's */ - unsigned long crc_value = 0xffffffff; - - for ( perByte = 0; perByte < length; perByte ++ ) { - unsigned char c; - - c = *(s++); - for ( perBit = 0; perBit < 8; perBit++ ) { - crc_value = (crc_value>>1)^ - (((crc_value^c)&0x01)?poly:0); - c >>= 1; - } - } - return crc_value; -} - /* . Function: smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * ) diff -urN linux-2.5.2-pre11/drivers/net/starfire.c linux/drivers/net/starfire.c --- linux-2.5.2-pre11/drivers/net/starfire.c Sun Sep 30 12:26:07 2001 +++ linux/drivers/net/starfire.c Mon Jan 14 18:28:29 2002 @@ -109,6 +109,7 @@ #include #include #include +#include #include /* Processor type for cache alignment. */ #include #include @@ -1612,32 +1613,9 @@ } -/* The little-endian AUTODIN II ethernet CRC calculations. - A big-endian version is also available. - This is slow but compact code. Do not use this routine for bulk data, - use a table-based routine instead. - This is common code and should be moved to net/core/crc.c. - Chips may use the upper or lower CRC bits, and may reverse and/or invert +/* Chips may use the upper or lower CRC bits, and may reverse and/or invert them. Select the endian-ness that results in minimal calculations. */ -static unsigned const ethernet_polynomial_le = 0xedb88320U; -static inline unsigned ether_crc_le(int length, unsigned char *data) -{ - unsigned int crc = 0xffffffff; /* Initial value. */ - while(--length >= 0) { - unsigned char current_octet = *data++; - int bit; - for (bit = 8; --bit >= 0; current_octet >>= 1) { - if ((crc ^ current_octet) & 1) { - crc >>= 1; - crc ^= ethernet_polynomial_le; - } else - crc >>= 1; - } - } - return crc; -} - static void set_rx_mode(struct net_device *dev) { diff -urN linux-2.5.2-pre11/drivers/net/sunbmac.c linux/drivers/net/sunbmac.c --- linux-2.5.2-pre11/drivers/net/sunbmac.c Tue Oct 30 15:08:11 2001 +++ linux/drivers/net/sunbmac.c Mon Jan 14 18:28:29 2002 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -979,9 +980,6 @@ return &bp->enet_stats; } -#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ -#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ - static void bigmac_set_multicast(struct net_device *dev) { struct bigmac *bp = (struct bigmac *) dev->priv; @@ -989,7 +987,7 @@ struct dev_mc_list *dmi = dev->mc_list; char *addrs; int i, j, bit, byte; - u32 tmp, crc, poly = CRC_POLYNOMIAL_LE; + u32 tmp, crc; /* Disable the receiver. The bit self-clears when * the operation is complete. @@ -1022,17 +1020,7 @@ if (!(*addrs & 1)) continue; - crc = 0xffffffffU; - for (byte = 0; byte < 6; byte++) { - for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) { - int test; - - test = ((bit ^ crc) & 0x01); - crc >>= 1; - if (test) - crc = crc ^ poly; - } - } + crc = ether_crc_le(6, addrs); crc >>= 26; hash_table[crc >> 4] |= 1 << (crc & 0xf); } diff -urN linux-2.5.2-pre11/drivers/net/sundance.c linux/drivers/net/sundance.c --- linux-2.5.2-pre11/drivers/net/sundance.c Fri Oct 19 08:32:28 2001 +++ linux/drivers/net/sundance.c Mon Jan 14 18:28:29 2002 @@ -98,6 +98,7 @@ #include #include #include +#include #include #include /* Processor type for cache alignment. */ #include @@ -1260,32 +1261,6 @@ np->stats.rx_bytes += readw(ioaddr + RxOctetsHigh) << 16; return &np->stats; -} - -/* The little-endian AUTODIN II ethernet CRC calculations. - A big-endian version is also available. - This is slow but compact code. Do not use this routine for bulk data, - use a table-based routine instead. - This is common code and should be moved to net/core/crc.c. - Chips may use the upper or lower CRC bits, and may reverse and/or invert - them. Select the endian-ness that results in minimal calculations. -*/ -static unsigned const ethernet_polynomial_le = 0xedb88320U; -static inline unsigned ether_crc_le(int length, unsigned char *data) -{ - unsigned int crc = 0xffffffff; /* Initial value. */ - while(--length >= 0) { - unsigned char current_octet = *data++; - int bit; - for (bit = 8; --bit >= 0; current_octet >>= 1) { - if ((crc ^ current_octet) & 1) { - crc >>= 1; - crc ^= ethernet_polynomial_le; - } else - crc >>= 1; - } - } - return crc; } static void set_rx_mode(struct net_device *dev) diff -urN linux-2.5.2-pre11/drivers/net/sungem.c linux/drivers/net/sungem.c --- linux-2.5.2-pre11/drivers/net/sungem.c Sun Oct 21 10:36:54 2001 +++ linux/drivers/net/sungem.c Mon Jan 14 18:28:29 2002 @@ -1,7 +1,15 @@ -/* $Id: sungem.c,v 1.30 2001/10/17 06:55:10 davem Exp $ +/* $Id: sungem.c,v 1.44 2001/12/08 04:06:27 davem Exp $ * sungem.c: Sun GEM ethernet driver. * * Copyright (C) 2000, 2001 David S. Miller (davem@redhat.com) + * + * Support for Apple GMAC and assorted PHYs by + * Benjamin Herrenscmidt (benh@kernel.crashing.org) + * + * TODO: + * - Get rid of all those nasty mdelay's and replace them + * with schedule_timeout. + * - Implement WOL */ #include @@ -23,11 +31,16 @@ #include #include #include +#include +#include +#include #include #include #include #include +#include +#include #ifdef __sparc__ #include @@ -45,15 +58,33 @@ #include "sungem.h" +#define DRV_NAME "sungem" +#define DRV_VERSION "0.96" +#define DRV_RELDATE "11/17/01" +#define DRV_AUTHOR "David S. Miller (davem@redhat.com)" + static char version[] __devinitdata = - "sungem.c:v0.95 16/Oct/01 David S. Miller (davem@redhat.com)\n"; + DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n"; -MODULE_AUTHOR("David S. Miller (davem@redhat.com)"); +MODULE_AUTHOR(DRV_AUTHOR); MODULE_DESCRIPTION("Sun GEM Gbit ethernet driver"); MODULE_LICENSE("GPL"); MODULE_PARM(gem_debug, "i"); MODULE_PARM_DESC(gem_debug, "(ignored)"); +MODULE_PARM(link_mode, "i"); + +static int link_mode; + +static u16 link_modes[] __devinitdata = { + BMCR_ANENABLE, /* 0 : autoneg */ + 0, /* 1 : 10bt half duplex */ + BMCR_SPEED100, /* 2 : 100bt half duplex */ + BMCR_SPD2, /* verify this */ /* 3 : 1000bt half duplex */ + BMCR_FULLDPLX, /* 4 : 10bt full duplex */ + BMCR_SPEED100|BMCR_FULLDPLX, /* 5 : 100bt full duplex */ + BMCR_SPD2|BMCR_FULLDPLX /* 6 : 1000bt full duplex */ +}; #define GEM_MODULE_NAME "gem" #define PFX GEM_MODULE_NAME ": " @@ -73,7 +104,7 @@ * they only support 10/100 speeds. -DaveM * * Apple's GMAC does support gigabit on machines with - * the BCM5400 or 5401 PHYs. -BenH + * the BCM54xx PHYs. -BenH */ { PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_RIO_GEM, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, @@ -362,10 +393,6 @@ return 1; } -static void gem_stop(struct gem *, unsigned long); -static void gem_init_rings(struct gem *, int); -static void gem_init_hw(struct gem *); - /* All non-normal interrupt conditions get serviced here. * Returns non-zero if we should just exit the interrupt * handler right now (ie. if we reset the card which invalidates @@ -418,9 +445,9 @@ return 0; do_reset: - gem_stop(gp, gp->regs); - gem_init_rings(gp, 1); - gem_init_hw(gp); + gp->reset_task_pending = 1; + schedule_task(&gp->reset_task); + return 1; } @@ -627,6 +654,10 @@ struct gem *gp = dev->priv; printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name); + if (!gp->hw_running) { + printk("%s: hrm.. hw not running !\n", dev->name); + return; + } printk(KERN_ERR "%s: TX_STATE[%08x:%08x:%08x]\n", dev->name, readl(gp->regs + TXDMA_CFG), @@ -640,13 +671,19 @@ spin_lock_irq(&gp->lock); - gem_stop(gp, gp->regs); - gem_init_rings(gp, 1); - gem_init_hw(gp); + gp->reset_task_pending = 1; + schedule_task(&gp->reset_task); spin_unlock_irq(&gp->lock); +} - netif_wake_queue(dev); +static __inline__ int gem_intme(int entry) +{ + /* Algorithm: IRQ every 1/2 of descriptors. */ + if (!(entry & ((TX_RING_SIZE>>1)-1))) + return 1; + + return 0; } static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev) @@ -690,15 +727,22 @@ ~PAGE_MASK), len, PCI_DMA_TODEVICE); ctrl |= TXDCTRL_SOF | TXDCTRL_EOF | len; + if (gem_intme(entry)) + ctrl |= TXDCTRL_INTME; txd->buffer = cpu_to_le64(mapping); txd->control_word = cpu_to_le64(ctrl); entry = NEXT_TX(entry); } else { struct gem_txd *txd; u32 first_len; + u64 intme; dma_addr_t first_mapping; int frag, first_entry = entry; + intme = 0; + if (gem_intme(entry)) + intme |= TXDCTRL_INTME; + /* We must give this initial chunk to the device last. * Otherwise we could race with the device. */ @@ -727,11 +771,15 @@ txd->buffer = cpu_to_le64(mapping); txd->control_word = cpu_to_le64(this_ctrl | len); + if (gem_intme(entry)) + intme |= TXDCTRL_INTME; + entry = NEXT_TX(entry); } txd = &gp->init_block->txd[first_entry]; txd->buffer = cpu_to_le64(first_mapping); - txd->control_word = cpu_to_le64(ctrl | TXDCTRL_SOF | first_len); + txd->control_word = + cpu_to_le64(ctrl | TXDCTRL_SOF | intme | first_len); } gp->tx_new = entry; @@ -761,18 +809,19 @@ return -EINVAL; spin_lock_irq(&gp->lock); - gem_stop(gp, gp->regs); dev->mtu = new_mtu; - gem_init_rings(gp, 1); - gem_init_hw(gp); + gp->reset_task_pending = 1; + schedule_task(&gp->reset_task); spin_unlock_irq(&gp->lock); + flush_scheduled_tasks(); + return 0; } #define STOP_TRIES 32 -static void gem_stop(struct gem *gp, unsigned long regs) +static void gem_stop(struct gem *gp) { int limit; u32 val; @@ -781,13 +830,13 @@ writel(0xffffffff, gp->regs + GREG_IMASK); /* Reset the chip */ - writel(GREG_SWRST_TXRST | GREG_SWRST_RXRST, regs + GREG_SWRST); + writel(GREG_SWRST_TXRST | GREG_SWRST_RXRST, gp->regs + GREG_SWRST); limit = STOP_TRIES; do { udelay(20); - val = readl(regs + GREG_SWRST); + val = readl(gp->regs + GREG_SWRST); if (limit-- <= 0) break; } while (val & (GREG_SWRST_TXRST | GREG_SWRST_RXRST)); @@ -810,6 +859,9 @@ val = readl(gp->regs + MAC_RXCFG); writel(val | MAC_RXCFG_ENAB, gp->regs + MAC_RXCFG); + (void) readl(gp->regs + MAC_RXCFG); + udelay(100); + writel(GREG_STAT_TXDONE, gp->regs + GREG_IMASK); writel(RX_RING_SIZE - 4, gp->regs + RXDMA_KICK); @@ -828,6 +880,88 @@ { 1, 0, 1 }, /* 1000BT */ }; +static void gem_begin_auto_negotiation(struct gem *gp, struct ethtool_cmd *ep) +{ + u16 ctl; + + /* Setup link parameters */ + if (!ep) + goto start_aneg; + if (ep->autoneg == AUTONEG_ENABLE) { + /* TODO: parse ep->advertising */ + gp->link_advertise |= (ADVERTISE_10HALF | ADVERTISE_10FULL); + gp->link_advertise |= (ADVERTISE_100HALF | ADVERTISE_100FULL); + /* Can I advertise gigabit here ? I'd need BCM PHY docs... */ + gp->link_cntl = BMCR_ANENABLE; + } else { + gp->link_cntl = 0; + if (ep->speed == SPEED_100) + gp->link_cntl |= BMCR_SPEED100; + else if (ep->speed == SPEED_1000 && gp->gigabit_capable) + /* Hrm... check if this is right... */ + gp->link_cntl |= BMCR_SPD2; + if (ep->duplex == DUPLEX_FULL) + gp->link_cntl |= BMCR_FULLDPLX; + } + +start_aneg: + spin_lock_irq(&gp->lock); + if (!gp->hw_running) { + spin_unlock_irq(&gp->lock); + return; + } + + /* Configure PHY & start aneg */ + ctl = phy_read(gp, MII_BMCR); + ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_ANENABLE); + ctl |= gp->link_cntl; + if (ctl & BMCR_ANENABLE) { + ctl |= BMCR_ANRESTART; + gp->lstate = link_aneg; + } else { + gp->lstate = link_force_ok; + } + phy_write(gp, MII_BMCR, ctl); + + gp->timer_ticks = 0; + gp->link_timer.expires = jiffies + ((12 * HZ) / 10); + add_timer(&gp->link_timer); + spin_unlock_irq(&gp->lock); +} + +static void gem_read_mii_link_mode(struct gem *gp, int *fd, int *spd, int *pause) +{ + u32 val; + + *fd = 0; + *spd = 10; + *pause = 0; + + if (gp->phy_mod == phymod_bcm5400 || + gp->phy_mod == phymod_bcm5401 || + gp->phy_mod == phymod_bcm5411) { + int link_mode; + + val = phy_read(gp, MII_BCM5400_AUXSTATUS); + link_mode = ((val & MII_BCM5400_AUXSTATUS_LINKMODE_MASK) >> + MII_BCM5400_AUXSTATUS_LINKMODE_SHIFT); + *fd = phy_BCM5400_link_table[link_mode][0]; + *spd = phy_BCM5400_link_table[link_mode][2] ? + 1000 : + (phy_BCM5400_link_table[link_mode][1] ? 100 : 10); + val = phy_read(gp, MII_LPA); + if (val & LPA_PAUSE) + *pause = 1; + } else { + val = phy_read(gp, MII_LPA); + + if (val & (LPA_10FULL | LPA_100FULL)) + *fd = 1; + if (val & (LPA_100FULL | LPA_100HALF)) + *spd = 100; + } +} + /* A link-up condition has occurred, initialize and enable the * rest of the chip. */ @@ -842,32 +976,13 @@ if (gp->phy_type == phy_mii_mdio0 || gp->phy_type == phy_mii_mdio1) { - if (gp->lstate == aneg_wait) { - if (gp->phy_mod == phymod_bcm5400 || - gp->phy_mod == phymod_bcm5401 || - gp->phy_mod == phymod_bcm5411) { - int link_mode; - val = phy_read(gp, PHY_BCM5400_AUXSTATUS); - link_mode = (val & PHY_BCM5400_AUXSTATUS_LINKMODE_MASK) >> - PHY_BCM5400_AUXSTATUS_LINKMODE_SHIFT; - full_duplex = phy_BCM5400_link_table[link_mode][0]; - speed = phy_BCM5400_link_table[link_mode][2] ? 1000 - : (phy_BCM5400_link_table[link_mode][1] ? 100 : 10); - val = phy_read(gp, PHY_LPA); - if (val & PHY_LPA_PAUSE) - pause = 1; - } else { - val = phy_read(gp, PHY_LPA); - if (val & (PHY_LPA_10FULL | PHY_LPA_100FULL)) - full_duplex = 1; - if (val & (PHY_LPA_100FULL | PHY_LPA_100HALF)) - speed = 100; - } - } else { - val = phy_read(gp, PHY_CTRL); - if (val & PHY_CTRL_FDPLX) + val = phy_read(gp, MII_BMCR); + if (val & BMCR_ANENABLE) + gem_read_mii_link_mode(gp, &full_duplex, &speed, &pause); + else { + if (val & BMCR_FULLDPLX) full_duplex = 1; - if (val & PHY_CTRL_SPD100) + if (val & BMCR_SPEED100) speed = 100; } } else { @@ -944,56 +1059,142 @@ static int gem_mdio_link_not_up(struct gem *gp) { - if (gp->lstate == aneg_wait) { - u16 val = phy_read(gp, PHY_CTRL); + if (gp->lstate == link_force_ret) { + printk(KERN_INFO "%s: Autoneg failed again, keeping" + " forced mode\n", gp->dev->name); + phy_write(gp, MII_BMCR, gp->link_fcntl); + gp->timer_ticks = 5; + gp->lstate = link_force_ok; + } else if (gp->lstate == link_aneg) { + u16 val = phy_read(gp, MII_BMCR); /* Try forced modes. */ - val &= ~(PHY_CTRL_ANRES | PHY_CTRL_ANENAB); - val &= ~(PHY_CTRL_FDPLX); - val |= PHY_CTRL_SPD100; - phy_write(gp, PHY_CTRL, val); - gp->timer_ticks = 0; - gp->lstate = force_wait; - return 1; + val &= ~(BMCR_ANRESTART | BMCR_ANENABLE); + val &= ~(BMCR_FULLDPLX); + val |= BMCR_SPEED100; + phy_write(gp, MII_BMCR, val); + gp->timer_ticks = 5; + gp->lstate = link_force_try; } else { /* Downgrade from 100 to 10 Mbps if necessary. * If already at 10Mbps, warn user about the * situation every 10 ticks. */ - u16 val = phy_read(gp, PHY_CTRL); - if (val & PHY_CTRL_SPD100) { - val &= ~PHY_CTRL_SPD100; - phy_write(gp, PHY_CTRL, val); - gp->timer_ticks = 0; - return 1; + u16 val = phy_read(gp, MII_BMCR); + if (val & BMCR_SPEED100) { + val &= ~BMCR_SPEED100; + phy_write(gp, MII_BMCR, val); + gp->timer_ticks = 5; } else { - printk(KERN_ERR "%s: Link down, cable problem?\n", - gp->dev->name); - val |= (PHY_CTRL_ANRES | PHY_CTRL_ANENAB); - phy_write(gp, PHY_CTRL, val); - gp->timer_ticks = 1; - gp->lstate = aneg_wait; return 1; } } + return 0; +} + +static void gem_init_rings(struct gem *, int); +static void gem_init_hw(struct gem *, int); + +static void gem_reset_task(void *data) +{ + struct gem *gp = (struct gem *) data; + + /* The link went down, we reset the ring, but keep + * DMA stopped. Todo: Use this function for reset + * on error as well. + */ + if (gp->hw_running && gp->opened) { + /* Make sure we don't get interrupts or tx packets */ + spin_lock_irq(&gp->lock); + + netif_stop_queue(gp->dev); + + writel(0xffffffff, gp->regs + GREG_IMASK); + + spin_unlock_irq(&gp->lock); + + /* Reset the chip & rings */ + gem_stop(gp); + gem_init_rings(gp, 0); + gem_init_hw(gp, 0); + + netif_wake_queue(gp->dev); + } + gp->reset_task_pending = 0; } static void gem_link_timer(unsigned long data) { struct gem *gp = (struct gem *) data; - int restart_timer = 0; - gp->timer_ticks++; + if (!gp->hw_running) + return; + + /* If the link of task is still pending, we just + * reschedule the link timer + */ + if (gp->reset_task_pending) + goto restart; + + spin_lock_irq(&gp->lock); if (gp->phy_type == phy_mii_mdio0 || gp->phy_type == phy_mii_mdio1) { - u16 val = phy_read(gp, PHY_STAT); + u16 val = phy_read(gp, MII_BMSR); + int up; - if (val & PHY_STAT_LSTAT) { - gem_set_link_modes(gp); - } else if (gp->timer_ticks < 10) { - restart_timer = 1; + /* When using autoneg, we really wait for ANEGCOMPLETE or we may + * get a "transcient" incorrect link state + */ +#if 0 + { + u16 cntl = phy_read(gp, MII_BMCR); + if (cntl & BMCR_ANENABLE) + up = (val & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) == (BMSR_ANEGCOMPLETE | BMSR_LSTATUS); + else + up = (val & BMSR_LSTATUS) != 0; + } +#else + up = (val & BMSR_LSTATUS) != 0; +#endif + if (up) { + /* Ok, here we got a link. If we had it due to a forced + * fallback, and we were configured for autoneg, we do + * retry a short autoneg pass. If you know your hub is + * broken, use ethtool ;) + */ + if (gp->lstate == link_force_try && (gp->link_cntl & BMCR_ANENABLE)) { + gp->lstate = link_force_ret; + gp->link_fcntl = phy_read(gp, MII_BMCR); + gp->timer_ticks = 5; + printk(KERN_INFO "%s: Got link after fallback, retrying autoneg" + " once...\n", gp->dev->name); + phy_write(gp, MII_BMCR, + gp->link_fcntl | BMCR_ANENABLE | BMCR_ANRESTART); + } else if (gp->lstate != link_up) { + gp->lstate = link_up; + if (gp->opened) + gem_set_link_modes(gp); + } } else { - restart_timer = gem_mdio_link_not_up(gp); + int restart = 0; + + /* If the link was previously up, we restart the + * whole process + */ + if (gp->lstate == link_up) { + gp->lstate = link_down; + printk(KERN_INFO "%s: Link down\n", gp->dev->name); + gp->reset_task_pending = 1; + schedule_task(&gp->reset_task); + restart = 1; + } else if (++gp->timer_ticks > 10) + restart = gem_mdio_link_not_up(gp); + + if (restart) { + spin_unlock_irq(&gp->lock); + gem_begin_auto_negotiation(gp, NULL); + return; + } } } else { u32 val = readl(gp->regs + PCS_MIISTAT); @@ -1001,17 +1202,17 @@ if (!(val & PCS_MIISTAT_LS)) val = readl(gp->regs + PCS_MIISTAT); - if ((val & PCS_MIISTAT_LS) == 0) { - restart_timer = 1; - } else { - gem_set_link_modes(gp); + if ((val & PCS_MIISTAT_LS) != 0) { + gp->lstate = link_up; + if (gp->opened) + gem_set_link_modes(gp); } } - if (restart_timer) { - gp->link_timer.expires = jiffies + ((12 * HZ) / 10); - add_timer(&gp->link_timer); - } +restart: + gp->link_timer.expires = jiffies + ((12 * HZ) / 10); + add_timer(&gp->link_timer); + spin_unlock_irq(&gp->lock); } static void gem_clean_rings(struct gem *gp) @@ -1108,66 +1309,72 @@ } } -static int -gem_reset_one_mii_phy(struct gem *gp, int phy_addr) +static int gem_reset_one_mii_phy(struct gem *gp, int phy_addr) { u16 val; int limit = 10000; - val = __phy_read(gp, PHY_CTRL, phy_addr); - val &= ~PHY_CTRL_ISO; - val |= PHY_CTRL_RST; - __phy_write(gp, PHY_CTRL, val, phy_addr); + val = __phy_read(gp, MII_BMCR, phy_addr); + val &= ~BMCR_ISOLATE; + val |= BMCR_RESET; + __phy_write(gp, MII_BMCR, val, phy_addr); udelay(100); while (limit--) { - val = __phy_read(gp, PHY_CTRL, phy_addr); - if ((val & PHY_CTRL_RST) == 0) + val = __phy_read(gp, MII_BMCR, phy_addr); + if ((val & BMCR_RESET) == 0) break; udelay(10); } - if ((val & PHY_CTRL_ISO) && limit > 0) - __phy_write(gp, PHY_CTRL, val & ~PHY_CTRL_ISO, phy_addr); + if ((val & BMCR_ISOLATE) && limit > 0) + __phy_write(gp, MII_BMCR, val & ~BMCR_ISOLATE, phy_addr); return (limit <= 0); } -static void -gem_init_bcm5400_phy(struct gem *gp) +static void gem_init_bcm5201_phy(struct gem *gp) +{ + u16 data; + + data = phy_read(gp, MII_BCM5201_MULTIPHY); + data &= ~MII_BCM5201_MULTIPHY_SUPERISOLATE; + phy_write(gp, MII_BCM5201_MULTIPHY, data); +} + +static void gem_init_bcm5400_phy(struct gem *gp) { u16 data; /* Configure for gigabit full duplex */ - data = phy_read(gp, PHY_BCM5400_AUXCONTROL); - data |= PHY_BCM5400_AUXCONTROL_PWR10BASET; - phy_write(gp, PHY_BCM5400_AUXCONTROL, data); - - data = phy_read(gp, PHY_BCM5400_GB_CONTROL); - data |= PHY_BCM5400_GB_CONTROL_FULLDUPLEXCAP; - phy_write(gp, PHY_BCM5400_GB_CONTROL, data); + data = phy_read(gp, MII_BCM5400_AUXCONTROL); + data |= MII_BCM5400_AUXCONTROL_PWR10BASET; + phy_write(gp, MII_BCM5400_AUXCONTROL, data); + + data = phy_read(gp, MII_BCM5400_GB_CONTROL); + data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP; + phy_write(gp, MII_BCM5400_GB_CONTROL, data); mdelay(10); /* Reset and configure cascaded 10/100 PHY */ gem_reset_one_mii_phy(gp, 0x1f); - data = __phy_read(gp, PHY_BCM5201_MULTIPHY, 0x1f); - data |= PHY_BCM5201_MULTIPHY_SERIALMODE; - __phy_write(gp, PHY_BCM5201_MULTIPHY, data, 0x1f); + data = __phy_read(gp, MII_BCM5201_MULTIPHY, 0x1f); + data |= MII_BCM5201_MULTIPHY_SERIALMODE; + __phy_write(gp, MII_BCM5201_MULTIPHY, data, 0x1f); - data = phy_read(gp, PHY_BCM5400_AUXCONTROL); - data &= ~PHY_BCM5400_AUXCONTROL_PWR10BASET; - phy_write(gp, PHY_BCM5400_AUXCONTROL, data); + data = phy_read(gp, MII_BCM5400_AUXCONTROL); + data &= ~MII_BCM5400_AUXCONTROL_PWR10BASET; + phy_write(gp, MII_BCM5400_AUXCONTROL, data); } -static void -gem_init_bcm5401_phy(struct gem *gp) +static void gem_init_bcm5401_phy(struct gem *gp) { u16 data; int rev; - rev = phy_read(gp, PHY_ID1) & 0x000f; + rev = phy_read(gp, MII_PHYSID2) & 0x000f; if (rev == 0 || rev == 3) { /* Some revisions of 5401 appear to need this * initialisation sequence to disable, according @@ -1191,22 +1398,21 @@ } /* Configure for gigabit full duplex */ - data = phy_read(gp, PHY_BCM5400_GB_CONTROL); - data |= PHY_BCM5400_GB_CONTROL_FULLDUPLEXCAP; - phy_write(gp, PHY_BCM5400_GB_CONTROL, data); + data = phy_read(gp, MII_BCM5400_GB_CONTROL); + data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP; + phy_write(gp, MII_BCM5400_GB_CONTROL, data); mdelay(1); /* Reset and configure cascaded 10/100 PHY */ gem_reset_one_mii_phy(gp, 0x1f); - data = __phy_read(gp, PHY_BCM5201_MULTIPHY, 0x1f); - data |= PHY_BCM5201_MULTIPHY_SERIALMODE; - __phy_write(gp, PHY_BCM5201_MULTIPHY, data, 0x1f); + data = __phy_read(gp, MII_BCM5201_MULTIPHY, 0x1f); + data |= MII_BCM5201_MULTIPHY_SERIALMODE; + __phy_write(gp, MII_BCM5201_MULTIPHY, data, 0x1f); } -static void -gem_init_bcm5411_phy(struct gem *gp) +static void gem_init_bcm5411_phy(struct gem *gp) { u16 data; @@ -1220,20 +1426,30 @@ /* Here, Apple seems to want to reset it, do * it as well */ - phy_write(gp, PHY_CTRL, PHY_CTRL_RST); + phy_write(gp, MII_BMCR, BMCR_RESET); /* Start autoneg */ - phy_write(gp, PHY_CTRL, - (PHY_CTRL_ANENAB | PHY_CTRL_FDPLX | - PHY_CTRL_ANRES | PHY_CTRL_SPD2)); - - data = phy_read(gp, PHY_BCM5400_GB_CONTROL); - data |= PHY_BCM5400_GB_CONTROL_FULLDUPLEXCAP; - phy_write(gp, PHY_BCM5400_GB_CONTROL, data); + phy_write(gp, MII_BMCR, + (BMCR_ANENABLE | BMCR_FULLDPLX | + BMCR_ANRESTART | BMCR_SPD2)); + + data = phy_read(gp, MII_BCM5400_GB_CONTROL); + data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP; + phy_write(gp, MII_BCM5400_GB_CONTROL, data); } static void gem_init_phy(struct gem *gp) { + u32 mifcfg; + + if (!gp->wake_on_lan && gp->phy_mod == phymod_bcm5201) + phy_write(gp, MII_BCM5201_INTERRUPT, 0); + + /* Revert MIF CFG setting done on stop_phy */ + mifcfg = readl(gp->regs + MIF_CFG); + mifcfg &= ~MIF_CFG_BBMODE; + writel(mifcfg, gp->regs + MIF_CFG); + #ifdef CONFIG_ALL_PPC if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) { int i; @@ -1241,7 +1457,7 @@ pmac_call_feature(PMAC_FTR_GMAC_PHY_RESET, gp->of_node, 0, 0); for (i = 0; i < 32; i++) { gp->mii_phy_addr = i; - if (phy_read(gp, PHY_CTRL) != 0xffff) + if (phy_read(gp, MII_BMCR) != 0xffff) break; } if (i == 32) { @@ -1277,54 +1493,68 @@ /* Take PHY out of isloate mode and reset it. */ gem_reset_one_mii_phy(gp, gp->mii_phy_addr); - phy_id = (phy_read(gp, PHY_ID0) << 16 | phy_read(gp, PHY_ID1)) + phy_id = (phy_read(gp, MII_PHYSID1) << 16 | phy_read(gp, MII_PHYSID2)) & 0xfffffff0; printk(KERN_INFO "%s: MII PHY ID: %x ", gp->dev->name, phy_id); switch(phy_id) { - case 0x406210: - gp->phy_mod = phymod_bcm5201; - printk("BCM 5201\n"); - break; - case 0x4061e0: - printk("BCM 5221\n"); - gp->phy_mod = phymod_bcm5221; - break; - case 0x206040: - printk("BCM 5400\n"); - gp->phy_mod = phymod_bcm5400; - gem_init_bcm5400_phy(gp); - break; - case 0x206050: - printk("BCM 5401\n"); - gp->phy_mod = phymod_bcm5401; - gem_init_bcm5401_phy(gp); - break; - case 0x206070: - printk("BCM 5411\n"); - gp->phy_mod = phymod_bcm5411; - gem_init_bcm5411_phy(gp); - break; - default: - printk("Generic\n"); - gp->phy_mod = phymod_generic; + case 0x406210: + gp->phy_mod = phymod_bcm5201; + gem_init_bcm5201_phy(gp); + printk("BCM 5201\n"); + break; + + case 0x4061e0: + printk("BCM 5221\n"); + gp->phy_mod = phymod_bcm5221; + break; + + case 0x206040: + printk("BCM 5400\n"); + gp->phy_mod = phymod_bcm5400; + gem_init_bcm5400_phy(gp); + gp->gigabit_capable = 1; + break; + + case 0x206050: + printk("BCM 5401\n"); + gp->phy_mod = phymod_bcm5401; + gem_init_bcm5401_phy(gp); + gp->gigabit_capable = 1; + break; + + case 0x206070: + printk("BCM 5411\n"); + gp->phy_mod = phymod_bcm5411; + gem_init_bcm5411_phy(gp); + gp->gigabit_capable = 1; + break; + + case 0x18074c0: + printk("Lucent\n"); + gp->phy_mod = phymod_generic; + break; + + case 0x437420: + printk("Enable Semiconductor\n"); + gp->phy_mod = phymod_generic; + break; + + default: + printk("Unknown\n"); + gp->phy_mod = phymod_generic; + break; }; /* Init advertisement and enable autonegotiation. */ - val = phy_read(gp, PHY_CTRL); - val &= ~PHY_CTRL_ANENAB; - phy_write(gp, PHY_CTRL, val); + val = phy_read(gp, MII_BMCR); + val &= ~BMCR_ANENABLE; + phy_write(gp, MII_BMCR, val); udelay(10); - phy_write(gp, PHY_ADV, - phy_read(gp, PHY_ADV) | - (PHY_ADV_10HALF | PHY_ADV_10FULL | - PHY_ADV_100HALF | PHY_ADV_100FULL)); - - val = phy_read(gp, PHY_CTRL); - val |= PHY_CTRL_ANENAB; - phy_write(gp, PHY_CTRL, val); - val |= PHY_CTRL_ANRES; - phy_write(gp, PHY_CTRL, val); + phy_write(gp, MII_ADVERTISE, + phy_read(gp, MII_ADVERTISE) | + (ADVERTISE_10HALF | ADVERTISE_10FULL | + ADVERTISE_100HALF | ADVERTISE_100FULL)); } else { u32 val; int limit; @@ -1379,6 +1609,7 @@ else val |= PCS_SCTRL_LOOP; writel(val, gp->regs + PCS_SCTRL); + gp->gigabit_capable = 1; } } @@ -1392,7 +1623,7 @@ writel(desc_dma >> 32, gp->regs + TXDMA_DBHI); writel(desc_dma & 0xffffffff, gp->regs + TXDMA_DBLOW); - desc_dma += (TX_RING_SIZE * sizeof(struct gem_txd)); + desc_dma += (INIT_BLOCK_TX_RING_SIZE * sizeof(struct gem_txd)); writel(0, gp->regs + TXDMA_KICK); @@ -1410,17 +1641,15 @@ writel(val, gp->regs + RXDMA_PTHRESH); if (readl(gp->regs + GREG_BIFCFG) & GREG_BIFCFG_M66EN) - writel(((6 & RXDMA_BLANK_IPKTS) | - ((4 << 12) & RXDMA_BLANK_ITIME)), + writel(((5 & RXDMA_BLANK_IPKTS) | + ((8 << 12) & RXDMA_BLANK_ITIME)), gp->regs + RXDMA_BLANK); else - writel(((6 & RXDMA_BLANK_IPKTS) | - ((2 << 12) & RXDMA_BLANK_ITIME)), + writel(((5 & RXDMA_BLANK_IPKTS) | + ((4 << 12) & RXDMA_BLANK_ITIME)), gp->regs + RXDMA_BLANK); } -#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ - static void gem_init_mac(struct gem *gp) { unsigned char *e = &gp->dev->dev_addr[0]; @@ -1484,9 +1713,9 @@ rxcfg |= MAC_RXCFG_PROM; } else { u16 hash_table[16]; - u32 crc, poly = CRC_POLYNOMIAL_LE; + u32 crc; struct dev_mc_list *dmi = gp->dev->mc_list; - int i, j, bit, byte; + int i; for (i = 0; i < 16; i++) hash_table[i] = 0; @@ -1499,17 +1728,7 @@ if (!(*addrs & 1)) continue; - crc = 0xffffffffU; - for (byte = 0; byte < 6; byte++) { - for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) { - int test; - - test = ((bit ^ crc) & 0x01); - crc >>= 1; - if (test) - crc = crc ^ poly; - } - } + crc = ether_crc_le(6, addrs); crc >>= 24; hash_table[crc >> 4] |= 1 << (crc & 0xf); } @@ -1551,18 +1770,20 @@ writel(0, gp->regs + MAC_MCCFG); writel(0, gp->regs + MAC_XIFCFG); - writel((MAC_TXSTAT_URUN | MAC_TXSTAT_MPE | - MAC_TXSTAT_NCE | MAC_TXSTAT_ECE | - MAC_TXSTAT_LCE | MAC_TXSTAT_FCE | - MAC_TXSTAT_DTE | MAC_TXSTAT_PCE), gp->regs + MAC_TXMASK); - writel((MAC_RXSTAT_OFLW | MAC_RXSTAT_FCE | - MAC_RXSTAT_ACE | MAC_RXSTAT_CCE | - MAC_RXSTAT_LCE | MAC_RXSTAT_VCE), gp->regs + MAC_RXMASK); - writel(0, gp->regs + MAC_MCMASK); + /* Setup MAC interrupts. We want to get all of the interesting + * counter expiration events, but we do not want to hear about + * normal rx/tx as the DMA engine tells us that. + */ + writel(MAC_TXSTAT_XMIT, gp->regs + MAC_TXMASK); + writel(MAC_RXSTAT_RCV, gp->regs + MAC_RXMASK); + + /* Don't enable even the PAUSE interrupts for now, we + * make no use of those events other than to record them. + */ + writel(0xffffffff, gp->regs + MAC_MCMASK); } -static void -gem_init_pause_thresholds(struct gem* gp) +static void gem_init_pause_thresholds(struct gem *gp) { /* Calculate pause thresholds. Setting the OFF threshold to the * full RX fifo size effectively disables PAUSE generation which @@ -1580,11 +1801,7 @@ } { - u32 cfg = readl(gp->regs + GREG_BIFCFG); - - /* XXX Why do I do this? -DaveM XXX */ - cfg |= GREG_BIFCFG_B64DIS; - writel(cfg, gp->regs + GREG_BIFCFG); + u32 cfg; cfg = GREG_CFG_IBURST; cfg |= ((31 << 1) & GREG_CFG_TXDMALIM); @@ -1598,21 +1815,15 @@ struct pci_dev *pdev = gp->pdev; u32 mif_cfg; - /* On Apple's sungem, we can't realy on registers as the chip + /* On Apple's sungem, we can't rely on registers as the chip * was been powered down by the firmware. We do the PHY lookup * when the interface is opened and we configure the driver * with known values. */ if (pdev->vendor == PCI_VENDOR_ID_APPLE) { gp->phy_type = phy_mii_mdio0; - mif_cfg = readl(gp->regs + MIF_CFG); - mif_cfg &= ~MIF_CFG_PSELECT; - writel(mif_cfg, gp->regs + MIF_CFG); - writel(PCS_DMODE_MGM, gp->regs + PCS_DMODE); - writel(MAC_XIFCFG_OE, gp->regs + MAC_XIFCFG); gp->tx_fifo_sz = readl(gp->regs + TXDMA_FSZ) * 64; gp->rx_fifo_sz = readl(gp->regs + RXDMA_FSZ) * 64; - gem_init_pause_thresholds(gp); return 0; } @@ -1651,7 +1862,7 @@ for (i = 0; i < 32; i++) { gp->mii_phy_addr = i; - if (phy_read(gp, PHY_CTRL) != 0xffff) + if (phy_read(gp, MII_BMCR) != 0xffff) break; } if (i == 32) { @@ -1685,12 +1896,10 @@ } } - gem_init_pause_thresholds(gp); - return 0; } -static void gem_init_hw(struct gem *gp) +static void gem_init_hw(struct gem *gp, int restart_link) { /* On Apple's gmac, I initialize the PHY only after * setting up the chip. It appears the gigabit PHYs @@ -1698,18 +1907,28 @@ * the chip is not running, I suspect it might not * be clocked at that point. --BenH */ - if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) { - gem_check_invariants(gp); - gp->hw_running = 1; - } - gem_init_phy(gp); + if (restart_link) + gem_init_phy(gp); gem_init_dma(gp); gem_init_mac(gp); + gem_init_pause_thresholds(gp); - gp->timer_ticks = 0; - gp->lstate = aneg_wait; - gp->link_timer.expires = jiffies + ((12 * HZ) / 10); - add_timer(&gp->link_timer); + spin_lock_irq(&gp->lock); + if (restart_link) { + /* Default aneg parameters */ + gp->timer_ticks = 0; + gp->lstate = link_down; + + spin_unlock_irq(&gp->lock); + + /* Can I advertise gigabit here ? I'd need BCM PHY docs... */ + gem_begin_auto_negotiation(gp, NULL); + } else { + if (gp->lstate == link_up) + gem_set_link_modes(gp); + + spin_unlock_irq(&gp->lock); + } } #ifdef CONFIG_ALL_PPC @@ -1717,10 +1936,10 @@ * setup properly. There appear to be no need to restore the * base addresses. */ -static void -gem_apple_powerup(struct gem* gp) +static void gem_apple_powerup(struct gem *gp) { u16 cmd; + u32 mif_cfg; pmac_call_feature(PMAC_FTR_GMAC_ENABLE, gp->of_node, 0, 1); @@ -1731,31 +1950,162 @@ pci_write_config_word(gp->pdev, PCI_COMMAND, cmd); pci_write_config_byte(gp->pdev, PCI_LATENCY_TIMER, 6); pci_write_config_byte(gp->pdev, PCI_CACHE_LINE_SIZE, 8); + + mdelay(1); + + mif_cfg = readl(gp->regs + MIF_CFG); + mif_cfg &= ~(MIF_CFG_PSELECT|MIF_CFG_POLL|MIF_CFG_BBMODE|MIF_CFG_MDI1); + mif_cfg |= MIF_CFG_MDI0; + writel(mif_cfg, gp->regs + MIF_CFG); + writel(PCS_DMODE_MGM, gp->regs + PCS_DMODE); + writel(MAC_XIFCFG_OE, gp->regs + MAC_XIFCFG); + + mdelay(1); } /* Turn off the chip's clock */ -static void -gem_apple_powerdown(struct gem* gp) +static void gem_apple_powerdown(struct gem *gp) { pmac_call_feature(PMAC_FTR_GMAC_ENABLE, gp->of_node, 0, 0); } + #endif /* CONFIG_ALL_PPC */ +static void gem_stop_phy(struct gem *gp) +{ + u32 mifcfg; + + if (!gp->wake_on_lan && gp->phy_mod == phymod_bcm5201) + phy_write(gp, MII_BCM5201_INTERRUPT, 0); + + /* Make sure we aren't polling PHY status change. We + * don't currently use that feature though + */ + mifcfg = readl(gp->regs + MIF_CFG); + mifcfg &= ~MIF_CFG_POLL; + writel(mifcfg, gp->regs + MIF_CFG); + + /* Here's a strange hack used by both MacOS 9 and X */ + phy_write(gp, MII_LPA, phy_read(gp, MII_LPA)); + + if (gp->wake_on_lan) { + /* Setup wake-on-lan */ + } else + writel(0, gp->regs + MAC_RXCFG); + writel(0, gp->regs + MAC_TXCFG); + writel(0, gp->regs + MAC_XIFCFG); + writel(0, gp->regs + TXDMA_CFG); + writel(0, gp->regs + RXDMA_CFG); + + if (!gp->wake_on_lan) { + gem_stop(gp); + writel(MAC_TXRST_CMD, gp->regs + MAC_TXRST); + writel(MAC_RXRST_CMD, gp->regs + MAC_RXRST); + if (gp->phy_mod == phymod_bcm5400 || gp->phy_mod == phymod_bcm5401 || + gp->phy_mod == phymod_bcm5411) { +#if 0 /* Commented out in Darwin... someone has those dawn docs ? */ + phy_write(gp, MII_BMCR, BMCR_PDOWN); +#endif + } else if (gp->phy_mod == phymod_bcm5201 || gp->phy_mod == phymod_bcm5221) { +#if 0 /* Commented out in Darwin... someone has those dawn docs ? */ + u16 val = phy_read(gp, MII_BCM5201_AUXMODE2) + phy_write(gp, MII_BCM5201_AUXMODE2, + val & ~MII_BCM5201_AUXMODE2_LOWPOWER); +#endif + phy_write(gp, MII_BCM5201_MULTIPHY, MII_BCM5201_MULTIPHY_SUPERISOLATE); + } + + /* According to Apple, we must set the MDIO pins to this begnign + * state or we may 1) eat more current, 2) damage some PHYs + */ + writel(mifcfg | MIF_CFG_BBMODE, gp->regs + MIF_CFG); + writel(0, gp->regs + MIF_BBCLK); + writel(0, gp->regs + MIF_BBDATA); + writel(0, gp->regs + MIF_BBOENAB); + writel(MAC_XIFCFG_GMII | MAC_XIFCFG_LBCK, gp->regs + MAC_XIFCFG); + (void) readl(gp->regs + MAC_XIFCFG); + } +} + +/* Shut down the chip, must be called with pm_sem held. */ +static void gem_shutdown(struct gem *gp) +{ + /* Make us not-running to avoid timers respawning */ + gp->hw_running = 0; + + /* Stop the link timer */ + del_timer_sync(&gp->link_timer); + + /* Stop the reset task */ + while (gp->reset_task_pending) + schedule(); + + /* Actually stop the chip */ + if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) + gem_stop_phy(gp); + else + gem_stop(gp); + +#ifdef CONFIG_ALL_PPC + /* Power down the chip */ + if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) + gem_apple_powerdown(gp); +#endif /* CONFIG_ALL_PPC */ +} + +static void gem_pm_task(void *data) +{ + struct gem *gp = (struct gem *) data; + + /* We assume if we can't lock the pm_sem, then open() was + * called again (or suspend()), and we can safely ignore + * the PM request + */ + if (down_trylock(&gp->pm_sem)) + return; + + /* Driver was re-opened or already shut down */ + if (gp->opened || !gp->hw_running) { + up(&gp->pm_sem); + return; + } + + gem_shutdown(gp); + + up(&gp->pm_sem); +} + +static void gem_pm_timer(unsigned long data) +{ + struct gem *gp = (struct gem *) data; + + schedule_task(&gp->pm_task); +} + static int gem_open(struct net_device *dev) { struct gem *gp = dev->priv; - unsigned long regs = gp->regs; + int hw_was_up = gp->hw_running; - del_timer(&gp->link_timer); + down(&gp->pm_sem); + /* Stop the PM timer/task */ + del_timer(&gp->pm_timer); + flush_scheduled_tasks(); + + if (!gp->hw_running) { #ifdef CONFIG_ALL_PPC - /* First, we need to bring up the chip */ - if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) - gem_apple_powerup(gp); + /* First, we need to bring up the chip */ + if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) { + gem_apple_powerup(gp); + gem_check_invariants(gp); + } #endif /* CONFIG_ALL_PPC */ + /* Reset the chip */ + gem_stop(gp); - /* Reset the chip */ - gem_stop(gp, regs); + gp->hw_running = 1; + } /* We can now request the interrupt as we know it's masked * on the controller @@ -1763,9 +2113,14 @@ if (request_irq(gp->pdev->irq, gem_interrupt, SA_SHIRQ, dev->name, (void *)dev)) { #ifdef CONFIG_ALL_PPC - if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) + if (!hw_was_up && gp->pdev->vendor == PCI_VENDOR_ID_APPLE) gem_apple_powerdown(gp); #endif /* CONFIG_ALL_PPC */ + /* Fire the PM timer that will shut us down in about 10 seconds */ + gp->pm_timer.expires = jiffies + 10*HZ; + add_timer(&gp->pm_timer); + up(&gp->pm_sem); + return -EAGAIN; } @@ -1773,7 +2128,11 @@ gem_init_rings(gp, 0); /* Init & setup chip hardware */ - gem_init_hw(gp); + gem_init_hw(gp, !hw_was_up); + + gp->opened = 1; + + up(&gp->pm_sem); return 0; } @@ -1782,17 +2141,110 @@ { struct gem *gp = dev->priv; - del_timer(&gp->link_timer); - gem_stop(gp, gp->regs); + /* Make sure we don't get distracted by suspend/resume */ + down(&gp->pm_sem); + + /* Stop traffic, mark us closed */ + spin_lock_irq(&gp->lock); + + gp->opened = 0; + writel(0xffffffff, gp->regs + GREG_IMASK); + netif_stop_queue(dev); + + spin_unlock_irq(&gp->lock); + + /* Stop chip */ + gem_stop(gp); + + /* Get rid of rings */ gem_clean_rings(gp); - gp->hw_running = 0; + + /* Bye, the pm timer will finish the job */ + free_irq(gp->pdev->irq, (void *) dev); + + /* Fire the PM timer that will shut us down in about 10 seconds */ + gp->pm_timer.expires = jiffies + 10*HZ; + add_timer(&gp->pm_timer); + + up(&gp->pm_sem); + + return 0; +} + +#ifdef CONFIG_PM +static int gem_suspend(struct pci_dev *pdev, u32 state) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct gem *gp = dev->priv; + + /* We hold the PM semaphore during entire driver + * sleep time + */ + down(&gp->pm_sem); + + printk(KERN_INFO "%s: suspending, WakeOnLan %s\n", + dev->name, gp->wake_on_lan ? "enabled" : "disabled"); + + /* If the driver is opened, we stop the DMA */ + if (gp->opened) { + /* Stop traffic, mark us closed */ + netif_device_detach(dev); + + spin_lock_irq(&gp->lock); + + writel(0xffffffff, gp->regs + GREG_IMASK); + + spin_unlock_irq(&gp->lock); + + /* Stop chip */ + gem_stop(gp); + + /* Get rid of ring buffers */ + gem_clean_rings(gp); + + if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) + disable_irq(gp->pdev->irq); + } + + if (gp->hw_running) { + /* Kill PM timer if any */ + del_timer_sync(&gp->pm_timer); + flush_scheduled_tasks(); + + gem_shutdown(gp); + } + + return 0; +} + +static int gem_resume(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct gem *gp = dev->priv; + + printk(KERN_INFO "%s: resuming\n", dev->name); + + if (gp->opened) { #ifdef CONFIG_ALL_PPC - if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) - gem_apple_powerdown(gp); + /* First, we need to bring up the chip */ + if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) { + gem_apple_powerup(gp); + gem_check_invariants(gp); + } #endif /* CONFIG_ALL_PPC */ - free_irq(gp->pdev->irq, (void *)dev); + gem_stop(gp); + gp->hw_running = 1; + gem_init_rings(gp, 0); + gem_init_hw(gp, 1); + netif_device_attach(dev); + if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) + enable_irq(gp->pdev->irq); + } + up(&gp->pm_sem); + return 0; } +#endif /* CONFIG_PM */ static struct net_device_stats *gem_get_stats(struct net_device *dev) { @@ -1861,9 +2313,9 @@ writel(rxcfg, gp->regs + MAC_RXCFG); } else { u16 hash_table[16]; - u32 crc, poly = CRC_POLYNOMIAL_LE; + u32 crc; struct dev_mc_list *dmi = gp->dev->mc_list; - int i, j, bit, byte; + int i; for (i = 0; i < 16; i++) hash_table[i] = 0; @@ -1876,17 +2328,7 @@ if (!(*addrs & 1)) continue; - crc = 0xffffffffU; - for (byte = 0; byte < 6; byte++) { - for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) { - int test; - - test = ((bit ^ crc) & 0x01); - crc >>= 1; - if (test) - crc = crc ^ poly; - } - } + crc = ether_crc_le(6, addrs); crc >>= 24; hash_table[crc >> 4] |= 1 << (crc & 0xf); } @@ -1908,12 +2350,219 @@ writel(hash_table[15], gp->regs + MAC_HASH15); } + /* Hrm... we may walk on the reset task here... */ netif_wake_queue(dev); } +/* Eventually add support for changing the advertisement + * on autoneg. + */ +static int gem_ethtool_ioctl(struct net_device *dev, void *ep_user) +{ + struct gem *gp = dev->priv; + u16 bmcr; + int full_duplex, speed, pause; + struct ethtool_cmd ecmd; + + if (copy_from_user(&ecmd, ep_user, sizeof(ecmd))) + return -EFAULT; + + switch(ecmd.cmd) { + case ETHTOOL_GDRVINFO: { + struct ethtool_drvinfo info = { cmd: ETHTOOL_GDRVINFO }; + + strncpy(info.driver, DRV_NAME, ETHTOOL_BUSINFO_LEN); + strncpy(info.version, DRV_VERSION, ETHTOOL_BUSINFO_LEN); + info.fw_version[0] = '\0'; + strncpy(info.bus_info, gp->pdev->slot_name, ETHTOOL_BUSINFO_LEN); + info.regdump_len = 0; /*SUNGEM_NREGS;*/ + + if (copy_to_user(ep_user, &info, sizeof(info))) + return -EFAULT; + + return 0; + } + + case ETHTOOL_GSET: + ecmd.supported = + (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | + SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII); + + if (gp->gigabit_capable) + ecmd.supported |= + (SUPPORTED_1000baseT_Half | + SUPPORTED_1000baseT_Full); + + /* XXX hardcoded stuff for now */ + ecmd.port = PORT_MII; + ecmd.transceiver = XCVR_EXTERNAL; + ecmd.phy_address = 0; /* XXX fixed PHYAD */ + + /* Record PHY settings if HW is on. */ + if (gp->hw_running) { + bmcr = phy_read(gp, MII_BMCR); + gem_read_mii_link_mode(gp, &full_duplex, &speed, &pause); + } else + bmcr = 0; + if (bmcr & BMCR_ANENABLE) { + ecmd.autoneg = AUTONEG_ENABLE; + ecmd.speed = speed == 10 ? SPEED_10 : (speed == 1000 ? SPEED_1000 : SPEED_100); + ecmd.duplex = full_duplex ? DUPLEX_FULL : DUPLEX_HALF; + } else { + ecmd.autoneg = AUTONEG_DISABLE; + ecmd.speed = + (bmcr & BMCR_SPEED100) ? + SPEED_100 : SPEED_10; + ecmd.duplex = + (bmcr & BMCR_FULLDPLX) ? + DUPLEX_FULL : DUPLEX_HALF; + } + if (copy_to_user(ep_user, &ecmd, sizeof(ecmd))) + return -EFAULT; + return 0; + + case ETHTOOL_SSET: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + /* Verify the settings we care about. */ + if (ecmd.autoneg != AUTONEG_ENABLE && + ecmd.autoneg != AUTONEG_DISABLE) + return -EINVAL; + + if (ecmd.autoneg == AUTONEG_DISABLE && + ((ecmd.speed != SPEED_100 && + ecmd.speed != SPEED_10) || + (ecmd.duplex != DUPLEX_HALF && + ecmd.duplex != DUPLEX_FULL))) + return -EINVAL; + + /* Apply settings and restart link process */ + if (gp->hw_running) + del_timer(&gp->link_timer); + gem_begin_auto_negotiation(gp, &ecmd); + return 0; + + case ETHTOOL_NWAY_RST: + if ((gp->link_cntl & BMCR_ANENABLE) == 0) + return -EINVAL; + if (gp->hw_running) + del_timer(&gp->link_timer); + gem_begin_auto_negotiation(gp, NULL); + return 0; + + case ETHTOOL_GWOL: + case ETHTOOL_SWOL: + break; /* todo */ + + /* get link status */ + case ETHTOOL_GLINK: { + struct ethtool_value edata = { cmd: ETHTOOL_GLINK }; + + edata.data = (gp->lstate == link_up); + if (copy_to_user(ep_user, &edata, sizeof(edata))) + return -EFAULT; + return 0; + } + + /* get message-level */ + case ETHTOOL_GMSGLVL: { + struct ethtool_value edata = { cmd: ETHTOOL_GMSGLVL }; + + edata.data = gem_debug; + if (copy_to_user(ep_user, &edata, sizeof(edata))) + return -EFAULT; + return 0; + } + + /* set message-level */ + case ETHTOOL_SMSGLVL: { + struct ethtool_value edata; + + if (copy_from_user(&edata, ep_user, sizeof(edata))) + return -EFAULT; + gem_debug = edata.data; + return 0; + } + +#if 0 + case ETHTOOL_GREGS: { + struct ethtool_regs regs; + u32 *regbuf; + int r = 0; + + if (copy_from_user(®s, useraddr, sizeof(regs))) + return -EFAULT; + + if (regs.len > SUNGEM_NREGS) { + regs.len = SUNGEM_NREGS; + } + regs.version = 0; + if (copy_to_user(useraddr, ®s, sizeof(regs))) + return -EFAULT; + + if (!gp->hw_running) + return -ENODEV; + useraddr += offsetof(struct ethtool_regs, data); + + /* Use kmalloc to avoid bloating the stack */ + regbuf = kmalloc(4 * SUNGEM_NREGS, GFP_KERNEL); + if (!regbuf) + return -ENOMEM; + spin_lock_irq(&np->lock); + gem_get_regs(gp, regbuf); + spin_unlock_irq(&np->lock); + + if (copy_to_user(useraddr, regbuf, regs.len*sizeof(u32))) + r = -EFAULT; + kfree(regbuf); + return r; + } +#endif + }; + + return -EOPNOTSUPP; +} + static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { - return -EINVAL; + struct gem *gp = dev->priv; + struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data; + int rc = -EOPNOTSUPP; + + /* Hold the PM semaphore while doing ioctl's or we may collide + * with open/close and power management and oops. + */ + down(&gp->pm_sem); + + switch (cmd) { + case SIOCETHTOOL: + rc = gem_ethtool_ioctl(dev, ifr->ifr_data); + break; + + case SIOCGMIIPHY: /* Get address of MII PHY in use. */ + data->phy_id = gp->mii_phy_addr; + /* Fallthrough... */ + + case SIOCGMIIREG: /* Read MII PHY register. */ + data->val_out = __phy_read(gp, data->reg_num & 0x1f, data->phy_id & 0x1f); + rc = 0; + break; + + case SIOCSMIIREG: /* Write MII PHY register. */ + if (!capable(CAP_NET_ADMIN)) { + rc = -EPERM; + } else { + __phy_write(gp, data->reg_num & 0x1f, data->val_in, data->phy_id & 0x1f); + rc = 0; + } + break; + }; + + up(&gp->pm_sem); + + return rc; } static int __devinit gem_get_device_address(struct gem *gp) @@ -2030,6 +2679,26 @@ gp->dev = dev; spin_lock_init(&gp->lock); + init_MUTEX(&gp->pm_sem); + + init_timer(&gp->link_timer); + gp->link_timer.function = gem_link_timer; + gp->link_timer.data = (unsigned long) gp; + + init_timer(&gp->pm_timer); + gp->pm_timer.function = gem_pm_timer; + gp->pm_timer.data = (unsigned long) gp; + + INIT_TQUEUE(&gp->pm_task, gem_pm_task, gp); + INIT_TQUEUE(&gp->reset_task, gem_reset_task, gp); + + /* Default link parameters */ + if (link_mode >= 0 && link_mode <= 6) + gp->link_cntl = link_modes[link_mode]; + else + gp->link_cntl = BMCR_ANENABLE; + gp->lstate = link_down; + gp->timer_ticks = 0; gp->regs = (unsigned long) ioremap(gemreg_base, gemreg_len); if (gp->regs == 0UL) { @@ -2038,9 +2707,26 @@ goto err_out_free_mmio_res; } - /* On Apple's, we might not access the hardware at that point */ + /* On Apple, we power the chip up now in order for check + * invariants to work, but also because the firmware might + * not have properly shut down the PHY. + */ +#ifdef CONFIG_ALL_PPC + if (pdev->vendor == PCI_VENDOR_ID_APPLE) { + gem_apple_powerup(gp); + if (gem_check_invariants(gp)) + goto err_out_iounmap; + gem_stop(gp); + gp->hw_running = 1; + gem_init_phy(gp); + gem_begin_auto_negotiation(gp, NULL); + } +#endif + /* Non Apple hardware, we just reset the chip and check + * for invariants + */ if (pdev->vendor != PCI_VENDOR_ID_APPLE) { - gem_stop(gp, gp->regs); + gem_stop(gp); if (gem_check_invariants(gp)) goto err_out_iounmap; gp->hw_running = 1; @@ -2074,10 +2760,6 @@ i == 5 ? ' ' : ':'); printk("\n"); - init_timer(&gp->link_timer); - gp->link_timer.function = gem_link_timer; - gp->link_timer.data = (unsigned long) gp; - dev->open = gem_open; dev->stop = gem_close; dev->hard_start_xmit = gem_start_xmit; @@ -2095,9 +2777,20 @@ if (pci_using_dac) dev->features |= NETIF_F_HIGHDMA; + /* Fire the PM timer that will shut us down in about 10 seconds */ + gp->pm_timer.expires = jiffies + 10*HZ; + add_timer(&gp->pm_timer); + return 0; err_out_iounmap: + down(&gp->pm_sem); + /* Stop the PM timer & task */ + del_timer_sync(&gp->pm_timer); + flush_scheduled_tasks(); + if (gp->hw_running) + gem_shutdown(gp); + up(&gp->pm_sem); iounmap((void *) gp->regs); err_out_free_mmio_res: @@ -2120,6 +2813,14 @@ unregister_netdev(dev); + down(&gp->pm_sem); + /* Stop the PM timer & task */ + del_timer_sync(&gp->pm_timer); + flush_scheduled_tasks(); + if (gp->hw_running) + gem_shutdown(gp); + up(&gp->pm_sem); + pci_free_consistent(pdev, sizeof(struct gem_init_block), gp->init_block, @@ -2127,9 +2828,6 @@ iounmap((void *) gp->regs); release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); -#ifdef CONFIG_ALL_PPC - pmac_call_feature(PMAC_FTR_GMAC_ENABLE, gp->of_node, 0, 0); -#endif kfree(dev); pci_set_drvdata(pdev, NULL); @@ -2140,7 +2838,11 @@ name: GEM_MODULE_NAME, id_table: gem_pci_tbl, probe: gem_init_one, - remove: gem_remove_one, + remove: __devexit_p(gem_remove_one), +#ifdef CONFIG_PM + suspend: gem_suspend, + resume: gem_resume, +#endif /* CONFIG_PM */ }; static int __init gem_init(void) diff -urN linux-2.5.2-pre11/drivers/net/sungem.h linux/drivers/net/sungem.h --- linux-2.5.2-pre11/drivers/net/sungem.h Sun Oct 21 10:36:54 2001 +++ linux/drivers/net/sungem.h Mon Jan 14 18:28:29 2002 @@ -1,4 +1,4 @@ -/* $Id: sungem.h,v 1.8 2001/10/17 05:55:39 davem Exp $ +/* $Id: sungem.h,v 1.10 2001/11/29 03:57:33 davem Exp $ * sungem.h: Definitions for Sun GEM ethernet driver. * * Copyright (C) 2000 David S. Miller (davem@redhat.com) @@ -753,64 +753,38 @@ #define PROM_SIZE 0x0fffffUL /* Size of ROM */ #define PROM_END 0x200000UL /* End of ROM */ -/* MII phy registers */ -#define PHY_CTRL 0x00 -#define PHY_STAT 0x01 -#define PHY_ID0 0x02 -#define PHY_ID1 0x03 -#define PHY_ADV 0x04 -#define PHY_LPA 0x05 - -#define PHY_CTRL_SPD2 0x0040 /* Gigabit enable? (bcm5411) */ -#define PHY_CTRL_FDPLX 0x0100 /* Full duplex */ -#define PHY_CTRL_ISO 0x0400 /* Isloate MII from PHY */ -#define PHY_CTRL_ANRES 0x0200 /* Auto-negotiation restart */ -#define PHY_CTRL_ANENAB 0x1000 /* Auto-negotiation enable */ -#define PHY_CTRL_SPD100 0x2000 /* Select 100Mbps */ -#define PHY_CTRL_RST 0x8000 /* Reset PHY */ - -#define PHY_STAT_LSTAT 0x0004 /* Link status */ -#define PHY_STAT_ANEGC 0x0020 /* Auto-negotiation complete */ - -#define PHY_ADV_10HALF 0x0020 -#define PHY_ADV_10FULL 0x0040 -#define PHY_ADV_100HALF 0x0080 -#define PHY_ADV_100FULL 0x0100 - -#define PHY_LPA_10HALF 0x0020 -#define PHY_LPA_10FULL 0x0040 -#define PHY_LPA_100HALF 0x0080 -#define PHY_LPA_100FULL 0x0100 -#define PHY_LPA_PAUSE 0x0400 -#define PHY_LPA_FAULT 0x2000 +/* MII definitions missing from mii.h */ + +#define BMCR_SPD2 0x0040 /* Gigabit enable? (bcm5411) */ +#define LPA_PAUSE 0x0400 /* More PHY registers (specific to Broadcom models) */ /* MII BCM5201 MULTIPHY interrupt register */ -#define PHY_BCM5201_INTERRUPT 0x1A -#define PHY_BCM5201_INTERRUPT_INTENABLE 0x4000 +#define MII_BCM5201_INTERRUPT 0x1A +#define MII_BCM5201_INTERRUPT_INTENABLE 0x4000 -#define PHY_BCM5201_AUXMODE2 0x1B -#define PHY_BCM5201_AUXMODE2_LOWPOWER 0x0008 +#define MII_BCM5201_AUXMODE2 0x1B +#define MII_BCM5201_AUXMODE2_LOWPOWER 0x0008 -#define PHY_BCM5201_MULTIPHY 0x1E +#define MII_BCM5201_MULTIPHY 0x1E /* MII BCM5201 MULTIPHY register bits */ -#define PHY_BCM5201_MULTIPHY_SERIALMODE 0x0002 -#define PHY_BCM5201_MULTIPHY_SUPERISOLATE 0x0008 +#define MII_BCM5201_MULTIPHY_SERIALMODE 0x0002 +#define MII_BCM5201_MULTIPHY_SUPERISOLATE 0x0008 /* MII BCM5400 1000-BASET Control register */ -#define PHY_BCM5400_GB_CONTROL 0x09 -#define PHY_BCM5400_GB_CONTROL_FULLDUPLEXCAP 0x0200 +#define MII_BCM5400_GB_CONTROL 0x09 +#define MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP 0x0200 /* MII BCM5400 AUXCONTROL register */ -#define PHY_BCM5400_AUXCONTROL 0x18 -#define PHY_BCM5400_AUXCONTROL_PWR10BASET 0x0004 +#define MII_BCM5400_AUXCONTROL 0x18 +#define MII_BCM5400_AUXCONTROL_PWR10BASET 0x0004 /* MII BCM5400 AUXSTATUS register */ -#define PHY_BCM5400_AUXSTATUS 0x19 -#define PHY_BCM5400_AUXSTATUS_LINKMODE_MASK 0x0700 -#define PHY_BCM5400_AUXSTATUS_LINKMODE_SHIFT 8 +#define MII_BCM5400_AUXSTATUS 0x19 +#define MII_BCM5400_AUXSTATUS_LINKMODE_MASK 0x0700 +#define MII_BCM5400_AUXSTATUS_LINKMODE_SHIFT 8 /* When it can, GEM internally caches 4 aligned TX descriptors * at a time, so that it can use full cacheline DMA reads. @@ -936,9 +910,21 @@ #define RX_COPY_THRESHOLD 256 +#if TX_RING_SIZE < 128 +#define INIT_BLOCK_TX_RING_SIZE 128 +#else +#define INIT_BLOCK_TX_RING_SIZE TX_RING_SIZE +#endif + +#if RX_RING_SIZE < 128 +#define INIT_BLOCK_RX_RING_SIZE 128 +#else +#define INIT_BLOCK_RX_RING_SIZE RX_RING_SIZE +#endif + struct gem_init_block { - struct gem_txd txd[TX_RING_SIZE]; - struct gem_rxd rxd[RX_RING_SIZE]; + struct gem_txd txd[INIT_BLOCK_TX_RING_SIZE]; + struct gem_rxd rxd[INIT_BLOCK_RX_RING_SIZE]; }; enum gem_phy_type { @@ -958,9 +944,12 @@ }; enum link_state { - aneg_wait, - force_wait, - aneg_up, + link_down = 0, /* No link, will retry */ + link_aneg, /* Autoneg in progress */ + link_force_try, /* Try Forced link speed */ + link_force_ret, /* Forced mode worked, retrying autoneg */ + link_force_ok, /* Stay in forced mode */ + link_up /* Link is up */ }; struct gem { @@ -973,6 +962,10 @@ * (ie. not power managed) */ int hw_running; + int opened; + struct semaphore pm_sem; + struct tq_struct pm_task; + struct timer_list pm_timer; struct gem_init_block *init_block; @@ -988,14 +981,22 @@ int rx_pause_off; int rx_pause_on; int mii_phy_addr; + int gigabit_capable; + /* Autoneg & PHY control */ + int link_cntl; + int link_advertise; + int link_fcntl; + enum link_state lstate; + struct timer_list link_timer; + int timer_ticks; + int wake_on_lan; + struct tq_struct reset_task; + volatile int reset_task_pending; + /* Diagnostic counters and state. */ u64 pause_entered; u16 pause_last_time_recvd; - - struct timer_list link_timer; - int timer_ticks; - enum link_state lstate; dma_addr_t gblock_dvma; struct pci_dev *pdev; diff -urN linux-2.5.2-pre11/drivers/net/sunhme.c linux/drivers/net/sunhme.c --- linux-2.5.2-pre11/drivers/net/sunhme.c Fri Oct 12 15:35:53 2001 +++ linux/drivers/net/sunhme.c Mon Jan 14 18:28:29 2002 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -1469,9 +1470,6 @@ add_timer(&hp->happy_timer); } -#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ -#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ - static int happy_meal_init(struct happy_meal *hp, int from_irq) { unsigned long gregs = hp->gregs; @@ -1583,8 +1581,8 @@ u16 hash_table[4]; struct dev_mc_list *dmi = hp->dev->mc_list; char *addrs; - int i, j, bit, byte; - u32 crc, poly = CRC_POLYNOMIAL_LE; + int i; + u32 crc; for (i = 0; i < 4; i++) hash_table[i] = 0; @@ -1596,17 +1594,7 @@ if (!(*addrs & 1)) continue; - crc = 0xffffffffU; - for (byte = 0; byte < 6; byte++) { - for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) { - int test; - - test = ((bit ^ crc) & 0x01); - crc >>= 1; - if (test) - crc = crc ^ poly; - } - } + crc = ether_crc_le(6, addrs); crc >>= 26; hash_table[crc >> 4] |= 1 << (crc & 0xf); } @@ -2385,8 +2373,8 @@ unsigned long bregs = hp->bigmacregs; struct dev_mc_list *dmi = dev->mc_list; char *addrs; - int i, j, bit, byte; - u32 crc, poly = CRC_POLYNOMIAL_LE; + int i; + u32 crc; /* Lock out others. */ netif_stop_queue(dev); @@ -2412,17 +2400,7 @@ if (!(*addrs & 1)) continue; - crc = 0xffffffffU; - for (byte = 0; byte < 6; byte++) { - for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) { - int test; - - test = ((bit ^ crc) & 0x01); - crc >>= 1; - if (test) - crc = crc ^ poly; - } - } + crc = ether_crc_le(6, addrs); crc >>= 26; hash_table[crc >> 4] |= 1 << (crc & 0xf); } diff -urN linux-2.5.2-pre11/drivers/net/sunlance.c linux/drivers/net/sunlance.c --- linux-2.5.2-pre11/drivers/net/sunlance.c Tue Oct 30 15:08:11 2001 +++ linux/drivers/net/sunlance.c Mon Jan 14 18:28:29 2002 @@ -62,12 +62,15 @@ * Anton Blanchard (anton@progsoc.uts.edu.au) * 2.00: 11/9/99: Massive overhaul and port to new SBUS driver interfaces. * David S. Miller (davem@redhat.com) + * 2.01: + * 11/08/01: Use library crc32 functions (Matt_Domsch@dell.com) + * */ #undef DEBUG_DRIVER static char version[] = - "sunlance.c:v2.00 11/Sep/99 Miguel de Icaza (miguel@nuclecu.unam.mx)\n"; + "sunlance.c:v2.01 08/Nov/01 Miguel de Icaza (miguel@nuclecu.unam.mx)\n"; static char lancestr[] = "LANCE"; @@ -86,6 +89,7 @@ #include #include #include +#include #include #include #include @@ -115,9 +119,6 @@ #define LANCE_LOG_RX_BUFFERS 4 #endif -#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ -#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ - #define LE_CSR0 0 #define LE_CSR1 1 #define LE_CSR2 2 @@ -1181,7 +1182,7 @@ struct dev_mc_list *dmi = dev->mc_list; char *addrs; int i, j, bit, byte; - u32 crc, poly = CRC_POLYNOMIAL_LE; + u32 crc; /* set all multicast bits */ if (dev->flags & IFF_ALLMULTI) { @@ -1211,19 +1212,7 @@ /* multicast address? */ if (!(*addrs & 1)) continue; - - crc = 0xffffffff; - for (byte = 0; byte < 6; byte++) { - for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) { - int test; - - test = ((bit ^ crc) & 0x01); - crc >>= 1; - - if (test) - crc = crc ^ poly; - } - } + crc = ether_crc_le(6, addrs); crc = crc >> 26; if (lp->pio_buffer) { u16 tmp = sbus_readw(&mcast_table[crc>>4]); diff -urN linux-2.5.2-pre11/drivers/net/sunqe.c linux/drivers/net/sunqe.c --- linux-2.5.2-pre11/drivers/net/sunqe.c Sun Oct 21 10:36:54 2001 +++ linux/drivers/net/sunqe.c Mon Jan 14 18:28:29 2002 @@ -1,4 +1,4 @@ -/* $Id: sunqe.c,v 1.52 2001/10/18 08:18:08 davem Exp $ +/* $Id: sunqe.c,v 1.53 2001/12/21 00:54:31 davem Exp $ * sunqe.c: Sparc QuadEthernet 10baseT SBUS card driver. * Once again I am out to prove that every ethernet * controller out there can be most efficiently programmed @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -494,6 +495,7 @@ spin_unlock(&qep->lock); } next: + ; } qec_status >>= 4; channel++; @@ -621,9 +623,6 @@ return &qep->net_stats; } -#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ -#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ - static void qe_set_multicast(struct net_device *dev) { struct sunqe *qep = (struct sunqe *) dev->priv; @@ -631,7 +630,7 @@ u8 new_mconfig = qep->mconfig; char *addrs; int i, j, bit, byte; - u32 crc, poly = CRC_POLYNOMIAL_LE; + u32 crc; /* Lock out others. */ netif_stop_queue(dev); @@ -659,18 +658,7 @@ if (!(*addrs & 1)) continue; - - crc = 0xffffffffU; - for (byte = 0; byte < 6; byte++) { - for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) { - int test; - - test = ((bit ^ crc) & 0x01); - crc >>= 1; - if (test) - crc = crc ^ poly; - } - } + crc = ether_crc_le(6, addrs); crc >>= 26; hash_table[crc >> 4] |= 1 << (crc & 0xf); } diff -urN linux-2.5.2-pre11/drivers/net/tulip/tulip_core.c linux/drivers/net/tulip/tulip_core.c --- linux-2.5.2-pre11/drivers/net/tulip/tulip_core.c Tue Dec 11 10:47:49 2001 +++ linux/drivers/net/tulip/tulip_core.c Mon Jan 14 18:28:29 2002 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -967,41 +968,6 @@ Note that we only use exclusion around actually queueing the new frame, not around filling tp->setup_frame. This is non-deterministic when re-entered but still correct. */ - -/* The little-endian AUTODIN32 ethernet CRC calculation. - N.B. Do not use for bulk data, use a table-based routine instead. - This is common code and should be moved to net/core/crc.c */ -static unsigned const ethernet_polynomial_le = 0xedb88320U; -static inline u32 ether_crc_le(int length, unsigned char *data) -{ - u32 crc = 0xffffffff; /* Initial value. */ - while(--length >= 0) { - unsigned char current_octet = *data++; - int bit; - for (bit = 8; --bit >= 0; current_octet >>= 1) { - if ((crc ^ current_octet) & 1) { - crc >>= 1; - crc ^= ethernet_polynomial_le; - } else - crc >>= 1; - } - } - return crc; -} -static unsigned const ethernet_polynomial = 0x04c11db7U; -static inline u32 ether_crc(int length, unsigned char *data) -{ - int crc = -1; - - while(--length >= 0) { - unsigned char current_octet = *data++; - int bit; - for (bit = 0; bit < 8; bit++, current_octet >>= 1) - crc = (crc << 1) ^ - ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0); - } - return crc; -} #undef set_bit_le #define set_bit_le(i,p) do { ((char *)(p))[(i)/8] |= (1<<((i)%8)); } while(0) diff -urN linux-2.5.2-pre11/drivers/net/via-rhine.c linux/drivers/net/via-rhine.c --- linux-2.5.2-pre11/drivers/net/via-rhine.c Fri Nov 9 13:45:36 2001 +++ linux/drivers/net/via-rhine.c Mon Jan 14 18:28:29 2002 @@ -151,6 +151,7 @@ #include #include #include +#include #include /* Processor type for cache alignment. */ #include #include @@ -1517,26 +1518,6 @@ writel(0, ioaddr + RxMissed); readw(ioaddr + RxCRCErrs); readw(ioaddr + RxMissed); -} - - -/* The big-endian AUTODIN II ethernet CRC calculation. - N.B. Do not use for bulk data, use a table-based routine instead. - This is common code and should be moved to net/core/crc.c */ -static unsigned const ethernet_polynomial = 0x04c11db7U; -static inline u32 ether_crc(int length, unsigned char *data) -{ - int crc = -1; - - while(--length >= 0) { - unsigned char current_octet = *data++; - int bit; - for (bit = 0; bit < 8; bit++, current_octet >>= 1) { - crc = (crc << 1) ^ - ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0); - } - } - return crc; } static void via_rhine_set_rx_mode(struct net_device *dev) diff -urN linux-2.5.2-pre11/drivers/net/winbond-840.c linux/drivers/net/winbond-840.c --- linux-2.5.2-pre11/drivers/net/winbond-840.c Tue Oct 9 15:13:02 2001 +++ linux/drivers/net/winbond-840.c Mon Jan 14 18:28:29 2002 @@ -136,6 +136,7 @@ #include #include #include +#include #include #include /* Processor type for cache alignment. */ #include @@ -389,7 +390,6 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *regs); static void netdev_error(struct net_device *dev, int intr_status); static int netdev_rx(struct net_device *dev); -static inline unsigned ether_crc(int length, unsigned char *data); static u32 __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); @@ -1407,21 +1407,6 @@ return &np->stats; } -static unsigned const ethernet_polynomial = 0x04c11db7U; -static inline u32 ether_crc(int length, unsigned char *data) -{ - int crc = -1; - - while(--length >= 0) { - unsigned char current_octet = *data++; - int bit; - for (bit = 0; bit < 8; bit++, current_octet >>= 1) { - crc = (crc << 1) ^ - ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0); - } - } - return crc; -} static u32 __set_rx_mode(struct net_device *dev) { diff -urN linux-2.5.2-pre11/drivers/net/yellowfin.c linux/drivers/net/yellowfin.c --- linux-2.5.2-pre11/drivers/net/yellowfin.c Fri Oct 19 08:32:28 2001 +++ linux/drivers/net/yellowfin.c Mon Jan 14 18:28:30 2002 @@ -125,6 +125,7 @@ #include #include #include +#include #include #include /* Processor type for cache alignment. */ #include @@ -1338,29 +1339,6 @@ } /* Set or clear the multicast filter for this adaptor. */ - -/* The little-endian AUTODIN32 ethernet CRC calculation. - N.B. Do not use for bulk data, use a table-based routine instead. - This is common code and should be moved to net/core/crc.c */ -static unsigned const ethernet_polynomial_le = 0xedb88320U; - -static inline unsigned ether_crc_le(int length, unsigned char *data) -{ - unsigned int crc = 0xffffffff; /* Initial value. */ - while(--length >= 0) { - unsigned char current_octet = *data++; - int bit; - for (bit = 8; --bit >= 0; current_octet >>= 1) { - if ((crc ^ current_octet) & 1) { - crc >>= 1; - crc ^= ethernet_polynomial_le; - } else - crc >>= 1; - } - } - return crc; -} - static void set_rx_mode(struct net_device *dev) { diff -urN linux-2.5.2-pre11/drivers/s390/block/dasd_int.h linux/drivers/s390/block/dasd_int.h --- linux-2.5.2-pre11/drivers/s390/block/dasd_int.h Mon Jan 14 18:28:23 2002 +++ linux/drivers/s390/block/dasd_int.h Mon Jan 14 18:28:30 2002 @@ -115,7 +115,7 @@ static inline struct request * dasd_next_request( request_queue_t *queue ) { - return blkdev_entry_next_request(&queue->queue_head); + return elv_next_request(queue); } static inline void dasd_dequeue_request( request_queue_t * q, struct request *req ) diff -urN linux-2.5.2-pre11/drivers/s390/block/xpram.c linux/drivers/s390/block/xpram.c --- linux-2.5.2-pre11/drivers/s390/block/xpram.c Sat Dec 8 20:02:47 2001 +++ linux/drivers/s390/block/xpram.c Mon Jan 14 18:28:30 2002 @@ -771,7 +771,7 @@ fault=0; #if ( XPRAM_VERSION == 24 ) - current_req = blkdev_entry_next_request (&queue->queue_head); + current_req = CURRENT; #endif /* V24 */ dev_no = DEVICE_NR(current_req->rq_dev); /* Check if the minor number is in range */ diff -urN linux-2.5.2-pre11/drivers/s390/char/tapedefs.h linux/drivers/s390/char/tapedefs.h --- linux-2.5.2-pre11/drivers/s390/char/tapedefs.h Wed Jul 25 14:12:02 2001 +++ linux/drivers/s390/char/tapedefs.h Mon Jan 14 18:28:30 2002 @@ -41,7 +41,7 @@ static inline struct request * tape_next_request( request_queue_t *queue ) { - return blkdev_entry_next_request(&queue->queue_head); + return elv_next_request(queue); } static inline void tape_dequeue_request( request_queue_t * q, struct request *req ) diff -urN linux-2.5.2-pre11/drivers/sbus/audio/audio.c linux/drivers/sbus/audio/audio.c --- linux-2.5.2-pre11/drivers/sbus/audio/audio.c Wed Oct 10 23:42:46 2001 +++ linux/drivers/sbus/audio/audio.c Mon Jan 14 18:28:30 2002 @@ -1,4 +1,4 @@ -/* $Id: audio.c,v 1.62 2001/10/08 22:19:50 davem Exp $ +/* $Id: audio.c,v 1.63 2002/01/08 16:00:21 davem Exp $ * drivers/sbus/audio/audio.c * * Copyright 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu) @@ -202,7 +202,7 @@ { unsigned int mask = 0; struct inode *inode = file->f_dentry->d_inode; - struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >> + struct sparcaudio_driver *drv = drivers[(minor(inode->i_rdev) >> SPARCAUDIO_DEVICE_SHIFT)]; poll_wait(file, &drv->input_read_wait, wait); @@ -221,7 +221,7 @@ size_t count, loff_t *ppos) { struct inode *inode = file->f_dentry->d_inode; - struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >> + struct sparcaudio_driver *drv = drivers[(minor(inode->i_rdev) >> SPARCAUDIO_DEVICE_SHIFT)]; int bytes_to_copy, bytes_read = 0, err; @@ -296,7 +296,7 @@ size_t count, loff_t *ppos) { struct inode *inode = file->f_dentry->d_inode; - struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >> + struct sparcaudio_driver *drv = drivers[(minor(inode->i_rdev) >> SPARCAUDIO_DEVICE_SHIFT)]; int bytes_written = 0, bytes_to_copy, err; @@ -396,7 +396,7 @@ static int sparcaudio_mixer_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned int *arg) { - struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >> + struct sparcaudio_driver *drv = drivers[(minor(inode->i_rdev) >> SPARCAUDIO_DEVICE_SHIFT)]; unsigned long i = 0, j = 0, l = 0, m = 0; unsigned int k = 0; @@ -647,7 +647,7 @@ unsigned int cmd, unsigned long arg) { int retval = 0, i, j, k; - int minor = MINOR(inode->i_rdev); + int minor = minor(inode->i_rdev); struct audio_info ainfo; audio_buf_info binfo; count_info cinfo; @@ -1701,7 +1701,7 @@ static int sparcaudio_open(struct inode * inode, struct file * file) { - int minor = MINOR(inode->i_rdev); + int minor = minor(inode->i_rdev); struct sparcaudio_driver *drv = drivers[(minor >> SPARCAUDIO_DEVICE_SHIFT)]; int err; @@ -1835,7 +1835,7 @@ static int sparcaudio_release(struct inode * inode, struct file * file) { - struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >> + struct sparcaudio_driver *drv = drivers[(minor(inode->i_rdev) >> SPARCAUDIO_DEVICE_SHIFT)]; lock_kernel(); diff -urN linux-2.5.2-pre11/drivers/sbus/char/aurora.c linux/drivers/sbus/char/aurora.c --- linux-2.5.2-pre11/drivers/sbus/char/aurora.c Mon Jan 14 18:28:23 2002 +++ linux/drivers/sbus/char/aurora.c Mon Jan 14 18:28:30 2002 @@ -1,4 +1,4 @@ -/* $Id: aurora.c,v 1.18 2001/10/26 17:59:31 davem Exp $ +/* $Id: aurora.c,v 1.19 2002/01/08 16:00:16 davem Exp $ * linux/drivers/sbus/char/aurora.c -- Aurora multiport driver * * Copyright (c) 1999 by Oliver Aldulea (oli at bv dot ro) @@ -1427,7 +1427,7 @@ printk("aurora_open: start\n"); #endif - board = AURORA_BOARD(MINOR(tty->device)); + board = AURORA_BOARD(minor(tty->device)); if (board > AURORA_NBOARD || !(aurora_board[board].flags & AURORA_BOARD_PRESENT)) { #ifdef AURORA_DEBUG @@ -1438,7 +1438,7 @@ } bp = &aurora_board[board]; - port = aurora_port + board * AURORA_NPORT * AURORA_NCD180 + AURORA_PORT(MINOR(tty->device)); + port = aurora_port + board * AURORA_NPORT * AURORA_NCD180 + AURORA_PORT(minor(tty->device)); if (aurora_paranoia_check(port, tty->device, "aurora_open")) { #ifdef AURORA_DEBUG printk("aurora_open: error paranoia check\n"); diff -urN linux-2.5.2-pre11/drivers/sbus/char/cpwatchdog.c linux/drivers/sbus/char/cpwatchdog.c --- linux-2.5.2-pre11/drivers/sbus/char/cpwatchdog.c Wed Oct 10 23:42:47 2001 +++ linux/drivers/sbus/char/cpwatchdog.c Mon Jan 14 18:28:30 2002 @@ -297,7 +297,7 @@ static int wd_open(struct inode *inode, struct file *f) { - switch(MINOR(inode->i_rdev)) + switch(minor(inode->i_rdev)) { case WD0_MINOR: f->private_data = &wd_dev.watchdog[WD0_ID]; diff -urN linux-2.5.2-pre11/drivers/sbus/char/display7seg.c linux/drivers/sbus/char/display7seg.c --- linux-2.5.2-pre11/drivers/sbus/char/display7seg.c Wed Oct 10 23:42:47 2001 +++ linux/drivers/sbus/char/display7seg.c Mon Jan 14 18:28:30 2002 @@ -1,4 +1,4 @@ -/* $Id: display7seg.c,v 1.5 2001/10/08 22:19:51 davem Exp $ +/* $Id: display7seg.c,v 1.6 2002/01/08 16:00:16 davem Exp $ * * display7seg - Driver implementation for the 7-segment display * present on Sun Microsystems CP1400 and CP1500 @@ -89,7 +89,7 @@ static int d7s_open(struct inode *inode, struct file *f) { - if (D7S_MINOR != MINOR(inode->i_rdev)) + if (D7S_MINOR != minor(inode->i_rdev)) return -ENODEV; MOD_INC_USE_COUNT; @@ -98,7 +98,7 @@ static int d7s_release(struct inode *inode, struct file *f) { - if (D7S_MINOR != MINOR(inode->i_rdev)) + if (D7S_MINOR != minor(inode->i_rdev)) return -ENODEV; MOD_DEC_USE_COUNT; @@ -125,7 +125,7 @@ __u8 regs = readb(d7s_regs); __u8 ireg = 0; - if (D7S_MINOR != MINOR(inode->i_rdev)) + if (D7S_MINOR != minor(inode->i_rdev)) return -ENODEV; switch (cmd) { diff -urN linux-2.5.2-pre11/drivers/sbus/char/sab82532.c linux/drivers/sbus/char/sab82532.c --- linux-2.5.2-pre11/drivers/sbus/char/sab82532.c Mon Jan 14 18:28:23 2002 +++ linux/drivers/sbus/char/sab82532.c Mon Jan 14 18:28:30 2002 @@ -1,4 +1,4 @@ -/* $Id: sab82532.c,v 1.65 2001/10/13 08:27:50 davem Exp $ +/* $Id: sab82532.c,v 1.66 2002/01/08 16:00:16 davem Exp $ * sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -1913,7 +1913,7 @@ printk("sab82532_open: count = %d\n", info->count); #endif - line = MINOR(tty->device) - tty->driver.minor_start; + line = minor(tty->device) - tty->driver.minor_start; if ((line < 0) || (line >= NR_PORTS)) return -ENODEV; @@ -2200,7 +2200,7 @@ static inline void __init show_serial_version(void) { - char *revision = "$Revision: 1.65 $"; + char *revision = "$Revision: 1.66 $"; char *version, *p; version = strchr(revision, ' '); @@ -2540,7 +2540,7 @@ static kdev_t sab82532_console_device(struct console *con) { - return MKDEV(TTY_MAJOR, 64 + con->index); + return mk_kdev(TTY_MAJOR, 64 + con->index); } static int diff -urN linux-2.5.2-pre11/drivers/sbus/char/su.c linux/drivers/sbus/char/su.c --- linux-2.5.2-pre11/drivers/sbus/char/su.c Mon Jan 14 18:28:23 2002 +++ linux/drivers/sbus/char/su.c Mon Jan 14 18:28:30 2002 @@ -1,4 +1,4 @@ -/* $Id: su.c,v 1.54 2001/11/07 14:52:30 davem Exp $ +/* $Id: su.c,v 1.55 2002/01/08 16:00:16 davem Exp $ * su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -2061,7 +2061,7 @@ int retval, line; unsigned long page; - line = MINOR(tty->device) - tty->driver.minor_start; + line = minor(tty->device) - tty->driver.minor_start; if ((line < 0) || (line >= NR_PORTS)) return -ENODEV; info = su_table + line; @@ -2252,7 +2252,7 @@ */ static __inline__ void __init show_su_version(void) { - char *revision = "$Revision: 1.54 $"; + char *revision = "$Revision: 1.55 $"; char *version, *p; version = strchr(revision, ' '); @@ -2857,7 +2857,7 @@ static kdev_t serial_console_device(struct console *c) { - return MKDEV(TTY_MAJOR, 64 + c->index); + return mk_kdev(TTY_MAJOR, 64 + c->index); } /* diff -urN linux-2.5.2-pre11/drivers/sbus/char/sunserial.c linux/drivers/sbus/char/sunserial.c --- linux-2.5.2-pre11/drivers/sbus/char/sunserial.c Thu Apr 19 08:38:49 2001 +++ linux/drivers/sbus/char/sunserial.c Mon Jan 14 18:28:30 2002 @@ -1,4 +1,4 @@ -/* $Id: sunserial.c,v 1.79 2001/04/18 21:06:17 davem Exp $ +/* $Id: sunserial.c,v 1.81 2002/01/05 01:13:43 davem Exp $ * serial.c: Serial port driver infrastructure for the Sparc. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) diff -urN linux-2.5.2-pre11/drivers/sbus/char/zs.c linux/drivers/sbus/char/zs.c --- linux-2.5.2-pre11/drivers/sbus/char/zs.c Mon Jan 14 18:28:23 2002 +++ linux/drivers/sbus/char/zs.c Mon Jan 14 18:28:30 2002 @@ -1,4 +1,4 @@ -/* $Id: zs.c,v 1.68 2001/10/25 18:48:03 davem Exp $ +/* $Id: zs.c,v 1.70 2002/01/08 16:00:16 davem Exp $ * zs.c: Zilog serial port driver for the Sparc. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -224,7 +224,7 @@ static DECLARE_MUTEX(tmp_buf_sem); static inline int serial_paranoia_check(struct sun_serial *info, - dev_t device, const char *routine) + kdev_t device, const char *routine) { #ifdef SERIAL_PARANOIA_CHECK static const char *badmagic = @@ -233,11 +233,11 @@ "Warning: null sun_serial for (%d, %d) in %s\n"; if (!info) { - printk(badinfo, MAJOR(device), MINOR(device), routine); + printk(badinfo, major(device), minor(device), routine); return 1; } if (info->magic != SERIAL_MAGIC) { - printk(badmagic, MAJOR(device), MINOR(device), routine); + printk(badmagic, major(device), minor(device), routine); return 1; } #endif @@ -486,10 +486,19 @@ static void receive_chars(struct sun_serial *info, struct pt_regs *regs) { struct tty_struct *tty = info->tty; - unsigned char ch, stat; - int do_queue_task = 1; + int do_queue_task = 0; + + while (1) { + unsigned char ch, r1; + + r1 = read_zsreg(info->zs_channel, R1); + if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) { + sbus_writeb(ERR_RES, &info->zs_channel->control); + ZSDELAY(); + ZS_WSYNC(info->zs_channel); + ZSLOG(REGCTRL, ERR_RES, 1); + } - do { ch = sbus_readb(&info->zs_channel->data); ZSLOG(REGDATA, ch, 0); ch &= info->parity_mask; @@ -498,17 +507,17 @@ /* If this is the console keyboard, we need to handle * L1-A's here. */ - if(info->cons_keyb) { - if(ch == SUNKBD_RESET) { + if (info->cons_keyb) { + if (ch == SUNKBD_RESET) { l1a_state.kbd_id = 1; l1a_state.l1_down = 0; - } else if(l1a_state.kbd_id) { + } else if (l1a_state.kbd_id) { l1a_state.kbd_id = 0; - } else if(ch == SUNKBD_L1) { + } else if (ch == SUNKBD_L1) { l1a_state.l1_down = 1; - } else if(ch == (SUNKBD_L1|SUNKBD_UP)) { + } else if (ch == (SUNKBD_L1|SUNKBD_UP)) { l1a_state.l1_down = 0; - } else if(ch == SUNKBD_A && l1a_state.l1_down) { + } else if (ch == SUNKBD_A && l1a_state.l1_down) { /* whee... */ batten_down_hatches(); /* Continue execution... */ @@ -517,16 +526,14 @@ return; } sunkbd_inchar(ch, regs); - do_queue_task = 0; goto next_char; } - if(info->cons_mouse) { + if (info->cons_mouse) { sun_mouse_inbyte(ch, 0); - do_queue_task = 0; goto next_char; } - if(info->is_cons) { - if(ch == 0) { + if (info->is_cons) { + if (ch == 0) { /* whee, break received */ batten_down_hatches(); /* Continue execution... */ @@ -538,32 +545,42 @@ * documentation for remote target debugging and * arch/sparc/kernel/sparc-stub.c to see how all this works. */ - if((info->kgdb_channel) && (ch =='\003')) { + if (info->kgdb_channel && (ch =='\003')) { breakpoint(); return; } #endif - if(!tty) + if (!tty) return; + do_queue_task++; + if (tty->flip.count >= TTY_FLIPBUF_SIZE) break; tty->flip.count++; - *tty->flip.flag_buf_ptr++ = 0; + if (r1 & PAR_ERR) + *tty->flip.flag_buf_ptr++ = TTY_PARITY; + else if (r1 & Rx_OVR) + *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; + else if (r1 & CRC_ERR) + *tty->flip.flag_buf_ptr++ = TTY_FRAME; + else + *tty->flip.flag_buf_ptr++ = 0; *tty->flip.char_buf_ptr++ = ch; next_char: - /* Check if we have another character... */ - stat = sbus_readb(&info->zs_channel->control); - ZSDELAY(); - ZSLOG(REGCTRL, stat, 0); - if (!(stat & Rx_CH_AV)) - break; + { + unsigned char stat; - /* ... and see if it is clean. */ - stat = read_zsreg(info->zs_channel, R1); - } while (!(stat & (PAR_ERR | Rx_OVR | CRC_ERR))); + /* Check if we have another character... */ + stat = sbus_readb(&info->zs_channel->control); + ZSDELAY(); + ZSLOG(REGCTRL, stat, 0); + if (!(stat & Rx_CH_AV)) + break; + } + } if (do_queue_task != 0) queue_task(&tty->flip.tqueue, &tq_timer); @@ -580,7 +597,7 @@ return; } - if((info->xmit_cnt <= 0) || (tty != 0 && tty->stopped)) { + if ((info->xmit_cnt <= 0) || (tty != 0 && tty->stopped)) { /* That's peculiar... */ sbus_writeb(RES_Tx_P, &info->zs_channel->control); ZSDELAY(); @@ -597,7 +614,7 @@ if (info->xmit_cnt < WAKEUP_CHARS) zs_sched_event(info, RS_EVENT_WRITE_WAKEUP); - if(info->xmit_cnt <= 0) { + if (info->xmit_cnt <= 0) { sbus_writeb(RES_Tx_P, &info->zs_channel->control); ZSDELAY(); ZS_WSYNC(info->zs_channel); @@ -619,14 +636,14 @@ ZS_WSYNC(info->zs_channel); ZSLOG(REGCTRL, RES_EXT_INT, 1); #if 0 - if(status & DCD) { - if((info->tty->termios->c_cflag & CRTSCTS) && - ((info->curregs[3] & AUTO_ENAB)==0)) { + if (status & DCD) { + if ((info->tty->termios->c_cflag & CRTSCTS) && + ((info->curregs[3] & AUTO_ENAB)==0)) { info->curregs[3] |= AUTO_ENAB; write_zsreg(info->zs_channel, 3, info->curregs[3]); } } else { - if((info->curregs[3] & AUTO_ENAB)) { + if ((info->curregs[3] & AUTO_ENAB)) { info->curregs[3] &= ~AUTO_ENAB; write_zsreg(info->zs_channel, 3, info->curregs[3]); } @@ -636,7 +653,7 @@ * 'break asserted' status change interrupt, call * the boot prom. */ - if(status & BRK_ABRT) { + if (status & BRK_ABRT) { if (info->break_abort) batten_down_hatches(); if (info->cons_mouse) @@ -649,110 +666,49 @@ return; } -static void special_receive(struct sun_serial *info) -{ - struct tty_struct *tty = info->tty; - unsigned char ch, stat; - - stat = read_zsreg(info->zs_channel, R1); - if (stat & (PAR_ERR | Rx_OVR | CRC_ERR)) { - ch = sbus_readb(&info->zs_channel->data); - ZSDELAY(); - ZSLOG(REGDATA, ch, 0); - } - - if (!tty) - goto clear; - - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - goto done; - - tty->flip.count++; - if(stat & PAR_ERR) - *tty->flip.flag_buf_ptr++ = TTY_PARITY; - else if(stat & Rx_OVR) - *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; - else if(stat & CRC_ERR) - *tty->flip.flag_buf_ptr++ = TTY_FRAME; - -done: - queue_task(&tty->flip.tqueue, &tq_timer); -clear: - sbus_writeb(ERR_RES, &info->zs_channel->control); - ZSDELAY(); - ZS_WSYNC(info->zs_channel); - ZSLOG(REGCTRL, ERR_RES, 1); -} - - /* * This is the serial driver's generic interrupt routine */ void zs_interrupt(int irq, void *dev_id, struct pt_regs * regs) { struct sun_serial *info; - unsigned char zs_intreg; int i; info = (struct sun_serial *)dev_id; ZSLOG(REGIRQ, 0, 0); for (i = 0; i < NUM_SERIAL; i++) { - zs_intreg = read_zsreg(info->zs_next->zs_channel, 2); - zs_intreg &= STATUS_MASK; - - /* NOTE: The read register 2, which holds the irq status, - * does so for both channels on each chip. Although - * the status value itself must be read from the B - * channel and is only valid when read from channel B. - * When read from channel A, read register 2 contains - * the value written to write register 2. - */ + unsigned char r3 = read_zsreg(info->zs_channel, 3); /* Channel A -- /dev/ttya or /dev/kbd, could be the console */ - if (zs_intreg == CHA_Rx_AVAIL) { - receive_chars(info, regs); - return; - } - if(zs_intreg == CHA_Tx_EMPTY) { - transmit_chars(info); - return; - } - if (zs_intreg == CHA_EXT_STAT) { - status_handle(info); - return; - } - if (zs_intreg == CHA_SPECIAL) { - special_receive(info); - return; + if (r3 & (CHAEXT | CHATxIP | CHARxIP)) { + sbus_writeb(RES_H_IUS, &info->zs_channel->control); + ZSDELAY(); + ZS_WSYNC(info->zs_channel); + ZSLOG(REGCTRL, RES_H_IUS, 1); + if (r3 & CHARxIP) + receive_chars(info, regs); + if (r3 & CHAEXT) + status_handle(info); + if (r3 & CHATxIP) + transmit_chars(info); } /* Channel B -- /dev/ttyb or /dev/mouse, could be the console */ - if(zs_intreg == CHB_Rx_AVAIL) { - receive_chars(info->zs_next, regs); - return; - } - if(zs_intreg == CHB_Tx_EMPTY) { - transmit_chars(info->zs_next); - return; + info = info->zs_next; + if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) { + sbus_writeb(RES_H_IUS, &info->zs_channel->control); + ZSDELAY(); + ZS_WSYNC(info->zs_channel); + ZSLOG(REGCTRL, RES_H_IUS, 1); + if (r3 & CHBRxIP) + receive_chars(info, regs); + if (r3 & CHBEXT) + status_handle(info); + if (r3 & CHBTxIP) + transmit_chars(info); } - if (zs_intreg == CHB_EXT_STAT) { - status_handle(info->zs_next); - return; - } - - /* NOTE: The default value for the IRQ status in read register - * 2 in channel B is CHB_SPECIAL, so we need to look at - * read register 3 in channel A to check if this is a - * real interrupt, or just the default value. - * Yes... broken hardware... - */ - zs_intreg = read_zsreg(info->zs_channel, 3); - if (zs_intreg & CHBRxIP) { - special_receive(info->zs_next); - return; - } - info = info->zs_next->zs_next; + info = info->zs_next; } } @@ -1847,7 +1803,7 @@ struct sun_serial *info; int retval, line; - line = MINOR(tty->device) - tty->driver.minor_start; + line = minor(tty->device) - tty->driver.minor_start; /* The zilog lines for the mouse/keyboard must be * opened using their respective drivers. @@ -1931,7 +1887,7 @@ static void show_serial_version(void) { - char *revision = "$Revision: 1.68 $"; + char *revision = "$Revision: 1.70 $"; char *version, *p; version = strchr(revision, ' '); @@ -2467,8 +2423,7 @@ /* Grab IRQ line before poking the chips so we do * not lose any interrupts. */ - if (request_irq(zilog_irq, zs_interrupt, - (SA_INTERRUPT | SA_STATIC_ALLOC), + if (request_irq(zilog_irq, zs_interrupt, SA_SHIRQ, "Zilog8530", zs_chain)) { prom_printf("Unable to attach zs intr\n"); prom_halt(); @@ -2761,7 +2716,7 @@ static kdev_t zs_console_device(struct console *con) { - return MKDEV(TTY_MAJOR, 64 + con->index); + return mk_kdev(TTY_MAJOR, 64 + con->index); } static int __init zs_console_setup(struct console *con, char *options) diff -urN linux-2.5.2-pre11/drivers/sbus/sbus.c linux/drivers/sbus/sbus.c --- linux-2.5.2-pre11/drivers/sbus/sbus.c Sun Mar 25 18:14:21 2001 +++ linux/drivers/sbus/sbus.c Mon Jan 14 18:28:30 2002 @@ -1,4 +1,4 @@ -/* $Id: sbus.c,v 1.95 2001/03/15 02:11:10 davem Exp $ +/* $Id: sbus.c,v 1.98 2002/01/05 01:13:43 davem Exp $ * sbus.c: SBus support routines. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -231,6 +231,7 @@ return; } regs[regnum].which_io = ranges[rngnum].ot_parent_space; + regs[regnum].phys_addr -= ranges[rngnum].ot_child_base; regs[regnum].phys_addr += ranges[rngnum].ot_parent_base; } } diff -urN linux-2.5.2-pre11/drivers/scsi/advansys.c linux/drivers/scsi/advansys.c --- linux-2.5.2-pre11/drivers/scsi/advansys.c Mon Jan 14 18:28:23 2002 +++ linux/drivers/scsi/advansys.c Mon Jan 14 18:28:30 2002 @@ -8392,8 +8392,8 @@ ASC_PRT_NEXT(); len = asc_prt_line(cp, leftlen, -" unchecked_isa_dma %d, use_clustering %d, loaded_as_module %d\n", - shp->unchecked_isa_dma, shp->use_clustering, shp->loaded_as_module); +" unchecked_isa_dma %d, use_clustering %d\n", + shp->unchecked_isa_dma, shp->use_clustering); ASC_PRT_NEXT(); len = asc_prt_line(cp, leftlen, @@ -9411,9 +9411,8 @@ s->dma_channel, s->this_id, s->can_queue); printk( -" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d, loaded_as_module %d\n", - s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma, - s->loaded_as_module); +" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d\n", + s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma); if (ASC_NARROW_BOARD(boardp)) { asc_prt_asc_dvc_var(&ASC_BOARDP(s)->dvc_var.asc_dvc_var); diff -urN linux-2.5.2-pre11/drivers/scsi/aic7xxx/aic7xxx_linux.c linux/drivers/scsi/aic7xxx/aic7xxx_linux.c --- linux-2.5.2-pre11/drivers/scsi/aic7xxx/aic7xxx_linux.c Mon Jan 14 18:28:23 2002 +++ linux/drivers/scsi/aic7xxx/aic7xxx_linux.c Mon Jan 14 18:28:30 2002 @@ -130,6 +130,7 @@ #include /* For fetching system memory size */ #include +#include /* * To generate the correct addresses for the controller to issue diff -urN linux-2.5.2-pre11/drivers/scsi/aic7xxx/aic7xxx_osm.h linux/drivers/scsi/aic7xxx/aic7xxx_osm.h --- linux-2.5.2-pre11/drivers/scsi/aic7xxx/aic7xxx_osm.h Tue Nov 27 09:23:27 2001 +++ linux/drivers/scsi/aic7xxx/aic7xxx_osm.h Mon Jan 14 18:28:30 2002 @@ -713,20 +713,20 @@ static __inline void ahc_lockinit(struct ahc_softc *ahc) { - spin_lock_init(&ahc->platform_data->host->host_lock); + spin_lock_init(ahc->platform_data->host->host_lock); } static __inline void ahc_lock(struct ahc_softc *ahc, unsigned long *flags) { *flags = 0; - spin_lock_irqsave(&ahc->platform_data->host->host_lock, *flags); + spin_lock_irqsave(ahc->platform_data->host->host_lock, *flags); } static __inline void ahc_unlock(struct ahc_softc *ahc, unsigned long *flags) { - spin_unlock_irqrestore(&ahc->platform_data->host->host_lock, *flags); + spin_unlock_irqrestore(ahc->platform_data->host->host_lock, *flags); } static __inline void @@ -741,7 +741,7 @@ struct Scsi_Host *host = ahc->platform_data->host; *flags = 0; - spin_lock_irqsave(&host->host_lock, *flags); + spin_lock_irqsave(host->host_lock, *flags); } static __inline void @@ -749,7 +749,7 @@ { struct Scsi_Host *host = ahc->platform_data->host; - spin_unlock_irqrestore(&host->host_lock, *flags); + spin_unlock_irqrestore(host->host_lock, *flags); } #else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) */ diff -urN linux-2.5.2-pre11/drivers/scsi/constants.c linux/drivers/scsi/constants.c --- linux-2.5.2-pre11/drivers/scsi/constants.c Thu Oct 25 13:53:50 2001 +++ linux/drivers/scsi/constants.c Mon Jan 14 18:28:30 2002 @@ -5,7 +5,6 @@ * */ -#define __NO_VERSION__ #include #include diff -urN linux-2.5.2-pre11/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c --- linux-2.5.2-pre11/drivers/scsi/hosts.c Mon Jan 14 18:28:23 2002 +++ linux/drivers/scsi/hosts.c Mon Jan 14 18:28:30 2002 @@ -24,7 +24,6 @@ * hosts currently present in the system. */ -#define __NO_VERSION__ #include #include #include @@ -55,13 +54,6 @@ * number it is during detection. */ -/* This is a placeholder for controllers that are not configured into - * the system - we do this to ensure that the controller numbering is - * always consistent, no matter how the kernel is configured. */ - -#define NO_CONTROLLER {NULL, NULL, NULL, NULL, NULL, NULL, NULL, \ - NULL, NULL, 0, 0, 0, 0, 0, 0} - /* * When figure is run, we don't want to link to any object code. Since * the macro for each host will contain function pointers, we cannot @@ -157,17 +149,14 @@ flag_new = 0; retval->host_no = shn->host_no; shn->host_registered = 1; - shn->loaded_as_module = 1; break; } } - spin_lock_init(&retval->host_lock); + spin_lock_init(&retval->default_lock); + scsi_assign_lock(retval, &retval->default_lock); atomic_set(&retval->host_active,0); retval->host_busy = 0; retval->host_failed = 0; - if(j > 0xffff) panic("Too many extra bytes requested\n"); - retval->extra_bytes = j; - retval->loaded_as_module = 1; if (flag_new) { shn = (Scsi_Host_Name *) kmalloc(sizeof(Scsi_Host_Name), GFP_ATOMIC); if (!shn) { @@ -181,7 +170,6 @@ shn->name[hname_len] = 0; shn->host_no = max_scsi_hosts++; shn->host_registered = 1; - shn->loaded_as_module = 1; shn->next = NULL; if (scsi_host_no_list) { for (shn2 = scsi_host_no_list;shn2->next;shn2 = shn2->next) diff -urN linux-2.5.2-pre11/drivers/scsi/hosts.h linux/drivers/scsi/hosts.h --- linux-2.5.2-pre11/drivers/scsi/hosts.h Mon Jan 14 18:28:23 2002 +++ linux/drivers/scsi/hosts.h Mon Jan 14 18:28:30 2002 @@ -312,7 +312,8 @@ struct Scsi_Host * next; Scsi_Device * host_queue; - spinlock_t host_lock; + spinlock_t default_lock; + spinlock_t *host_lock; struct task_struct * ehandler; /* Error recovery thread. */ struct semaphore * eh_wait; /* The error recovery thread waits on @@ -329,7 +330,6 @@ volatile unsigned short host_failed; /* commands that failed. */ /* public: */ - unsigned short extra_bytes; unsigned short host_no; /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */ int resetting; /* if set, it means that last_reset is a valid value */ unsigned long last_reset; @@ -386,10 +386,6 @@ unsigned unchecked_isa_dma:1; unsigned use_clustering:1; unsigned highmem_io:1; - /* - * True if this host was loaded as a loadable module - */ - unsigned loaded_as_module:1; /* * Host has rejected a command because it was busy. @@ -451,7 +447,6 @@ char * name; unsigned short host_no; unsigned short host_registered; - unsigned loaded_as_module; } Scsi_Host_Name; extern Scsi_Host_Name * scsi_host_no_list; @@ -471,9 +466,13 @@ unsigned int scsi_init(void); extern struct Scsi_Host * scsi_register(Scsi_Host_Template *, int j); extern void scsi_unregister(struct Scsi_Host * i); - extern void scsi_register_blocked_host(struct Scsi_Host * SHpnt); extern void scsi_deregister_blocked_host(struct Scsi_Host * SHpnt); + +static inline void scsi_assign_lock(struct Scsi_Host *host, spinlock_t *lock) +{ + host->host_lock = lock; +} static inline void scsi_set_pci_device(struct Scsi_Host *SHpnt, struct pci_dev *pdev) diff -urN linux-2.5.2-pre11/drivers/scsi/ide-scsi.c linux/drivers/scsi/ide-scsi.c --- linux-2.5.2-pre11/drivers/scsi/ide-scsi.c Mon Jan 14 18:28:23 2002 +++ linux/drivers/scsi/ide-scsi.c Mon Jan 14 18:28:30 2002 @@ -292,9 +292,9 @@ } } host = pc->scsi_cmd->host; - spin_lock_irqsave(&host->host_lock, flags); + spin_lock_irqsave(host->host_lock, flags); pc->done(pc->scsi_cmd); - spin_unlock_irqrestore(&host->host_lock, flags); + spin_unlock_irqrestore(host->host_lock, flags); idescsi_free_bio (rq->bio); kfree(pc); kfree(rq); scsi->pc = NULL; @@ -805,9 +805,9 @@ rq->special = (char *) pc; rq->bio = idescsi_dma_bio (drive, pc); rq->flags = REQ_SPECIAL; - spin_unlock(&cmd->host->host_lock); + spin_unlock_irq(cmd->host->host_lock); (void) ide_do_drive_cmd (drive, rq, ide_end); - spin_lock_irq(&cmd->host->host_lock); + spin_lock_irq(cmd->host->host_lock); return 0; abort: if (pc) kfree (pc); diff -urN linux-2.5.2-pre11/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c --- linux-2.5.2-pre11/drivers/scsi/scsi.c Mon Jan 14 18:28:23 2002 +++ linux/drivers/scsi/scsi.c Mon Jan 14 18:28:30 2002 @@ -75,8 +75,6 @@ #include #endif -#undef USE_STATIC_SCSI_MEMORY - struct proc_dir_entry *proc_scsi; #ifdef CONFIG_PROC_FS @@ -195,16 +193,23 @@ { request_queue_t *q = &SDpnt->request_queue; - blk_init_queue(q, scsi_request_fn, &SHpnt->host_lock); + /* + * tell block layer about assigned host_lock for this host + */ + blk_init_queue(q, scsi_request_fn, SHpnt->host_lock); + q->queuedata = (void *) SDpnt; /* Hardware imposed limit. */ blk_queue_max_hw_segments(q, SHpnt->sg_tablesize); - blk_queue_max_sectors(q, SHpnt->max_sectors); - /* scsi_alloc_sgtable max */ + /* + * scsi_alloc_sgtable max + */ blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS); + blk_queue_max_sectors(q, SHpnt->max_sectors); + if (!SHpnt->use_clustering) clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); } @@ -647,7 +652,7 @@ host = SCpnt->host; - ASSERT_LOCK(&host->host_lock, 0); + ASSERT_LOCK(host->host_lock, 0); /* Assign a unique nonzero serial_number. */ if (++serial_number == 0) @@ -698,9 +703,9 @@ * length exceeds what the host adapter can handle. */ if (CDB_SIZE(SCpnt) <= SCpnt->host->max_cmd_len) { - spin_lock_irqsave(&host->host_lock, flags); + spin_lock_irqsave(host->host_lock, flags); rtn = host->hostt->queuecommand(SCpnt, scsi_done); - spin_unlock_irqrestore(&host->host_lock, flags); + spin_unlock_irqrestore(host->host_lock, flags); if (rtn != 0) { scsi_delete_timer(SCpnt); scsi_mlqueue_insert(SCpnt, SCSI_MLQUEUE_HOST_BUSY); @@ -711,20 +716,20 @@ SCSI_LOG_MLQUEUE(3, printk("queuecommand : command too long.\n")); SCpnt->result = (DID_ABORT << 16); - spin_lock_irqsave(&host->host_lock, flags); + spin_lock_irqsave(host->host_lock, flags); scsi_done(SCpnt); - spin_unlock_irqrestore(&host->host_lock, flags); + spin_unlock_irqrestore(host->host_lock, flags); rtn = 1; } } else { int temp; SCSI_LOG_MLQUEUE(3, printk("command() : routine at %p\n", host->hostt->command)); - spin_lock_irqsave(&host->host_lock, flags); + spin_lock_irqsave(host->host_lock, flags); temp = host->hostt->command(SCpnt); SCpnt->result = temp; #ifdef DEBUG_DELAY - spin_unlock_irqrestore(&host->host_lock, flags); + spin_unlock_irqrestore(host->host_lock, flags); clock = jiffies + 4 * HZ; while (time_before(jiffies, clock)) { barrier(); @@ -732,10 +737,10 @@ } printk("done(host = %d, result = %04x) : routine at %p\n", host->host_no, temp, host->hostt->command); - spin_lock_irqsave(&host->host_lock, flags); + spin_lock_irqsave(host->host_lock, flags); #endif scsi_done(SCpnt); - spin_unlock_irqrestore(&host->host_lock, flags); + spin_unlock_irqrestore(host->host_lock, flags); } SCSI_LOG_MLQUEUE(3, printk("leaving scsi_dispatch_cmnd()\n")); return rtn; @@ -805,7 +810,7 @@ Scsi_Device * SDpnt = SRpnt->sr_device; struct Scsi_Host *host = SDpnt->host; - ASSERT_LOCK(&host->host_lock, 0); + ASSERT_LOCK(host->host_lock, 0); SCSI_LOG_MLQUEUE(4, { @@ -902,7 +907,7 @@ { struct Scsi_Host *host = SCpnt->host; - ASSERT_LOCK(&host->host_lock, 0); + ASSERT_LOCK(host->host_lock, 0); SCpnt->owner = SCSI_OWNER_MIDLEVEL; SRpnt->sr_command = SCpnt; @@ -992,7 +997,7 @@ { struct Scsi_Host *host = SCpnt->host; - ASSERT_LOCK(&host->host_lock, 0); + ASSERT_LOCK(host->host_lock, 0); SCpnt->pid = scsi_pid++; SCpnt->owner = SCSI_OWNER_MIDLEVEL; @@ -1346,7 +1351,7 @@ host = SCpnt->host; device = SCpnt->device; - ASSERT_LOCK(&host->host_lock, 0); + ASSERT_LOCK(host->host_lock, 0); /* * We need to protect the decrement, as otherwise a race condition @@ -1355,10 +1360,10 @@ * one execution context, but the device and host structures are * shared. */ - spin_lock_irqsave(&host->host_lock, flags); + spin_lock_irqsave(host->host_lock, flags); host->host_busy--; /* Indicate that we are free */ device->device_busy--; /* Decrement device usage counter. */ - spin_unlock_irqrestore(&host->host_lock, flags); + spin_unlock_irqrestore(host->host_lock, flags); /* * Clear the flags which say that the device/host is no longer @@ -1512,7 +1517,6 @@ shn->name[len] = 0; shn->host_no = n; shn->host_registered = 0; - shn->loaded_as_module = 1; /* numbers shouldn't be freed in any case */ shn->next = NULL; if (scsi_host_no_list) { for (shn2 = scsi_host_no_list;shn2->next;shn2 = shn2->next) @@ -1968,12 +1972,6 @@ } } } -#if defined(USE_STATIC_SCSI_MEMORY) - printk("SCSI memory: total %ldKb, used %ldKb, free %ldKb.\n", - (scsi_memory_upper_value - scsi_memory_lower_value) / 1024, - (scsi_init_memory_start - scsi_memory_lower_value) / 1024, - (scsi_memory_upper_value - scsi_init_memory_start) / 1024); -#endif if (out_of_space) { scsi_unregister_host(tpnt); /* easiest way to clean up?? */ @@ -2163,13 +2161,6 @@ printk(KERN_INFO "scsi : %d host%s left.\n", next_scsi_host, (next_scsi_host == 1) ? "" : "s"); -#if defined(USE_STATIC_SCSI_MEMORY) - printk("SCSI memory: total %ldKb, used %ldKb, free %ldKb.\n", - (scsi_memory_upper_value - scsi_memory_lower_value) / 1024, - (scsi_init_memory_start - scsi_memory_lower_value) / 1024, - (scsi_memory_upper_value - scsi_init_memory_start) / 1024); -#endif - /* * Remove it from the linked list and /proc if all * hosts were successfully removed (ie preset == 0) @@ -2403,35 +2394,6 @@ SCpnt->cmnd[0], SCpnt->sense_buffer[2], SCpnt->result); - } - } - } - - for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) { - for (SDpnt = shpnt->host_queue; SDpnt; SDpnt = SDpnt->next) { - /* Now dump the request lists for each block device */ - printk(KERN_INFO "Dump of pending block device requests\n"); - for (i = 0; i < MAX_BLKDEV; i++) { - struct list_head * queue_head; - - queue_head = &blk_dev[i].request_queue.queue_head; - if (!list_empty(queue_head)) { - struct request *req; - struct list_head * entry; - - printk(KERN_INFO "%d: ", i); - entry = queue_head->next; - do { - req = blkdev_entry_to_request(entry); - printk("(%s %d %ld %ld %ld) ", - kdevname(req->rq_dev), - req->cmd, - req->sector, - req->nr_sectors, - req->current_nr_sectors); - } while ((entry = entry->next) != queue_head); - printk("\n"); - } } } } diff -urN linux-2.5.2-pre11/drivers/scsi/scsi_error.c linux/drivers/scsi/scsi_error.c --- linux-2.5.2-pre11/drivers/scsi/scsi_error.c Wed Dec 12 13:41:03 2001 +++ linux/drivers/scsi/scsi_error.c Mon Jan 14 18:28:30 2002 @@ -8,7 +8,6 @@ * */ -#define __NO_VERSION__ #include #include @@ -583,7 +582,7 @@ unsigned long flags; struct Scsi_Host *host = SCpnt->host; - ASSERT_LOCK(&host->host_lock, 0); + ASSERT_LOCK(host->host_lock, 0); retry: /* @@ -605,9 +604,9 @@ SCpnt->host->eh_action = &sem; SCpnt->request.rq_status = RQ_SCSI_BUSY; - spin_lock_irqsave(&SCpnt->host->host_lock, flags); + spin_lock_irqsave(SCpnt->host->host_lock, flags); host->hostt->queuecommand(SCpnt, scsi_eh_done); - spin_unlock_irqrestore(&SCpnt->host->host_lock, flags); + spin_unlock_irqrestore(SCpnt->host->host_lock, flags); down(&sem); @@ -630,10 +629,10 @@ * abort a timed out command or not. Not sure how * we should treat them differently anyways. */ - spin_lock_irqsave(&SCpnt->host->host_lock, flags); + spin_lock_irqsave(SCpnt->host->host_lock, flags); if (SCpnt->host->hostt->eh_abort_handler) SCpnt->host->hostt->eh_abort_handler(SCpnt); - spin_unlock_irqrestore(&SCpnt->host->host_lock, flags); + spin_unlock_irqrestore(SCpnt->host->host_lock, flags); SCpnt->request.rq_status = RQ_SCSI_DONE; SCpnt->owner = SCSI_OWNER_ERROR_HANDLER; @@ -650,9 +649,9 @@ * timeout protection here, since we would end up waiting in * the actual low level driver, we don't know how to wake it up. */ - spin_lock_irqsave(&host->host_lock, flags); + spin_lock_irqsave(host->host_lock, flags); temp = host->hostt->command(SCpnt); - spin_unlock_irqrestore(&host->host_lock, flags); + spin_unlock_irqrestore(host->host_lock, flags); SCpnt->result = temp; /* Fall through to code below to examine status. */ @@ -772,9 +771,9 @@ SCpnt->owner = SCSI_OWNER_LOWLEVEL; - spin_lock_irqsave(&SCpnt->host->host_lock, flags); + spin_lock_irqsave(SCpnt->host->host_lock, flags); rtn = SCpnt->host->hostt->eh_abort_handler(SCpnt); - spin_unlock_irqrestore(&SCpnt->host->host_lock, flags); + spin_unlock_irqrestore(SCpnt->host->host_lock, flags); return rtn; } @@ -804,9 +803,9 @@ } SCpnt->owner = SCSI_OWNER_LOWLEVEL; - spin_lock_irqsave(&SCpnt->host->host_lock, flags); + spin_lock_irqsave(SCpnt->host->host_lock, flags); rtn = SCpnt->host->hostt->eh_device_reset_handler(SCpnt); - spin_unlock_irqrestore(&SCpnt->host->host_lock, flags); + spin_unlock_irqrestore(SCpnt->host->host_lock, flags); if (rtn == SUCCESS) SCpnt->eh_state = SUCCESS; @@ -837,9 +836,9 @@ return FAILED; } - spin_lock_irqsave(&SCpnt->host->host_lock, flags); + spin_lock_irqsave(SCpnt->host->host_lock, flags); rtn = SCpnt->host->hostt->eh_bus_reset_handler(SCpnt); - spin_unlock_irqrestore(&SCpnt->host->host_lock, flags); + spin_unlock_irqrestore(SCpnt->host->host_lock, flags); if (rtn == SUCCESS) SCpnt->eh_state = SUCCESS; @@ -883,9 +882,9 @@ if (SCpnt->host->hostt->eh_host_reset_handler == NULL) { return FAILED; } - spin_lock_irqsave(&SCpnt->host->host_lock, flags); + spin_lock_irqsave(SCpnt->host->host_lock, flags); rtn = SCpnt->host->hostt->eh_host_reset_handler(SCpnt); - spin_unlock_irqrestore(&SCpnt->host->host_lock, flags); + spin_unlock_irqrestore(SCpnt->host->host_lock, flags); if (rtn == SUCCESS) SCpnt->eh_state = SUCCESS; @@ -1226,7 +1225,7 @@ Scsi_Device *SDpnt; unsigned long flags; - ASSERT_LOCK(&host->host_lock, 0); + ASSERT_LOCK(host->host_lock, 0); /* * Next free up anything directly waiting upon the host. This will be @@ -1243,7 +1242,7 @@ * now that error recovery is done, we will need to ensure that these * requests are started. */ - spin_lock_irqsave(&host->host_lock, flags); + spin_lock_irqsave(host->host_lock, flags); for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) { request_queue_t *q = &SDpnt->request_queue; @@ -1256,7 +1255,7 @@ q->request_fn(q); } - spin_unlock_irqrestore(&host->host_lock, flags); + spin_unlock_irqrestore(host->host_lock, flags); } /* @@ -1303,7 +1302,7 @@ Scsi_Cmnd *SCdone; int timed_out; - ASSERT_LOCK(&host->host_lock, 0); + ASSERT_LOCK(host->host_lock, 0); SCdone = NULL; @@ -1844,11 +1843,7 @@ * If the HA was compiled into the kernel, then we don't listen * to any signals. */ - if( host->loaded_as_module ) { siginitsetinv(¤t->blocked, SHUTDOWN_SIGS); - } else { - siginitsetinv(¤t->blocked, 0); - } lock_kernel(); @@ -1894,10 +1889,8 @@ * semaphores isn't unreasonable. */ down_interruptible(&sem); - if( host->loaded_as_module ) { - if (signal_pending(current)) - break; - } + if (signal_pending(current)) + break; SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler waking up\n")); diff -urN linux-2.5.2-pre11/drivers/scsi/scsi_ioctl.c linux/drivers/scsi/scsi_ioctl.c --- linux-2.5.2-pre11/drivers/scsi/scsi_ioctl.c Sun Dec 16 12:20:21 2001 +++ linux/drivers/scsi/scsi_ioctl.c Mon Jan 14 18:28:30 2002 @@ -4,7 +4,6 @@ * - get rid of some verify_areas and use __copy*user and __get/put_user * for the ones that remain */ -#define __NO_VERSION__ #include #include diff -urN linux-2.5.2-pre11/drivers/scsi/scsi_lib.c linux/drivers/scsi/scsi_lib.c --- linux-2.5.2-pre11/drivers/scsi/scsi_lib.c Mon Jan 14 18:28:23 2002 +++ linux/drivers/scsi/scsi_lib.c Mon Jan 14 18:28:30 2002 @@ -17,7 +17,6 @@ * go through and retrofit queueing functions into all 30 some-odd drivers. */ -#define __NO_VERSION__ #include #include @@ -365,7 +364,7 @@ * If there are blocks left over at the end, set up the command * to queue the remainder of them. */ - if (end_that_request_first(req, 1, sectors)) { + if (end_that_request_first(req, uptodate, sectors)) { if (!requeue) return SCpnt; @@ -444,7 +443,7 @@ { struct request *req = &SCpnt->request; - ASSERT_LOCK(&SCpnt->host->host_lock, 0); + ASSERT_LOCK(SCpnt->host->host_lock, 0); /* * Free up any indirection buffers we allocated for DMA purposes. diff -urN linux-2.5.2-pre11/drivers/scsi/scsi_merge.c linux/drivers/scsi/scsi_merge.c --- linux-2.5.2-pre11/drivers/scsi/scsi_merge.c Mon Jan 14 18:28:23 2002 +++ linux/drivers/scsi/scsi_merge.c Mon Jan 14 18:28:30 2002 @@ -15,7 +15,6 @@ * be handled all at once by a host adapter. */ -#define __NO_VERSION__ #include #include diff -urN linux-2.5.2-pre11/drivers/scsi/scsi_proc.c linux/drivers/scsi/scsi_proc.c --- linux-2.5.2-pre11/drivers/scsi/scsi_proc.c Wed Jun 27 17:10:55 2001 +++ linux/drivers/scsi/scsi_proc.c Mon Jan 14 18:28:30 2002 @@ -17,7 +17,6 @@ */ #include /* for CONFIG_PROC_FS */ -#define __NO_VERSION__ #include #include diff -urN linux-2.5.2-pre11/drivers/scsi/scsi_queue.c linux/drivers/scsi/scsi_queue.c --- linux-2.5.2-pre11/drivers/scsi/scsi_queue.c Wed Dec 12 13:41:09 2001 +++ linux/drivers/scsi/scsi_queue.c Mon Jan 14 18:28:30 2002 @@ -10,7 +10,6 @@ * we attempt to remove commands from the queue and retry them. */ -#define __NO_VERSION__ #include #include @@ -137,10 +136,10 @@ * Decrement the counters, since these commands are no longer * active on the host/device. */ - spin_lock_irqsave(&cmd->host->host_lock, flags); + spin_lock_irqsave(cmd->host->host_lock, flags); cmd->host->host_busy--; cmd->device->device_busy--; - spin_unlock_irqrestore(&cmd->host->host_lock, flags); + spin_unlock_irqrestore(cmd->host->host_lock, flags); /* * Insert this command at the head of the queue for it's device. diff -urN linux-2.5.2-pre11/drivers/scsi/scsi_scan.c linux/drivers/scsi/scsi_scan.c --- linux-2.5.2-pre11/drivers/scsi/scsi_scan.c Mon Jan 14 18:28:23 2002 +++ linux/drivers/scsi/scsi_scan.c Mon Jan 14 18:28:30 2002 @@ -8,7 +8,6 @@ * clearer. */ -#define __NO_VERSION__ #include #include #include diff -urN linux-2.5.2-pre11/drivers/scsi/scsi_syms.c linux/drivers/scsi/scsi_syms.c --- linux-2.5.2-pre11/drivers/scsi/scsi_syms.c Mon Jan 14 18:28:23 2002 +++ linux/drivers/scsi/scsi_syms.c Mon Jan 14 18:28:30 2002 @@ -2,7 +2,6 @@ * We should not even be trying to compile this if we are not doing * a module. */ -#define __NO_VERSION__ #include #include diff -urN linux-2.5.2-pre11/drivers/scsi/scsicam.c linux/drivers/scsi/scsicam.c --- linux-2.5.2-pre11/drivers/scsi/scsicam.c Mon Jan 14 18:28:23 2002 +++ linux/drivers/scsi/scsicam.c Mon Jan 14 18:28:30 2002 @@ -10,7 +10,6 @@ * For more information, please consult the SCSI-CAM draft. */ -#define __NO_VERSION__ #include #include diff -urN linux-2.5.2-pre11/drivers/scsi/sym53c8xx.c linux/drivers/scsi/sym53c8xx.c --- linux-2.5.2-pre11/drivers/scsi/sym53c8xx.c Sun Dec 16 12:20:21 2001 +++ linux/drivers/scsi/sym53c8xx.c Mon Jan 14 18:28:30 2002 @@ -643,9 +643,9 @@ #define NCR_UNLOCK_NCB(np, flags) spin_unlock_irqrestore(&np->smp_lock, flags) #define NCR_LOCK_SCSI_DONE(host, flags) \ - spin_lock_irqsave(&((host)->host_lock), flags) + spin_lock_irqsave(((host)->host_lock), flags) #define NCR_UNLOCK_SCSI_DONE(host, flags) \ - spin_unlock_irqrestore(&((host)->host_lock), flags) + spin_unlock_irqrestore(((host)->host_lock), flags) #else diff -urN linux-2.5.2-pre11/drivers/scsi/sym53c8xx_2/sym_glue.c linux/drivers/scsi/sym53c8xx_2/sym_glue.c --- linux-2.5.2-pre11/drivers/scsi/sym53c8xx_2/sym_glue.c Sun Dec 16 12:20:21 2001 +++ linux/drivers/scsi/sym53c8xx_2/sym_glue.c Mon Jan 14 18:28:30 2002 @@ -138,11 +138,11 @@ #define SYM_LOCK_DRIVER(flags) spin_lock_irqsave(&sym53c8xx_lock, flags) #define SYM_UNLOCK_DRIVER(flags) spin_unlock_irqrestore(&sym53c8xx_lock,flags) -#define SYM_INIT_LOCK_HCB(np) spin_lock_init(&np->s.host->host_lock); +#define SYM_INIT_LOCK_HCB(np) spin_lock_init((np)->s.host->host_lock); #define SYM_LOCK_HCB(np, flags) \ - spin_lock_irqsave(&np->s.host->host_lock, flags) + spin_lock_irqsave((np)->s.host->host_lock, flags) #define SYM_UNLOCK_HCB(np, flags) \ - spin_unlock_irqrestore(&np->s.host->host_lock, flags) + spin_unlock_irqrestore((np)->s.host->host_lock, flags) /* * These simple macros limit expression involving diff -urN linux-2.5.2-pre11/drivers/sound/trident.c linux/drivers/sound/trident.c --- linux-2.5.2-pre11/drivers/sound/trident.c Tue Nov 13 09:19:41 2001 +++ linux/drivers/sound/trident.c Mon Jan 14 18:28:30 2002 @@ -187,6 +187,7 @@ #define TRIDENT_STATE_MAGIC 0x63657373 /* "cess" */ #define TRIDENT_DMA_MASK 0x3fffffff /* DMA buffer mask for pci_alloc_consist */ +#define ALI_DMA_MASK 0xffffffff /* ALI Tridents lack the 30-bit limitation */ #define NR_HW_CH 32 @@ -2555,7 +2556,7 @@ static int trident_open(struct inode *inode, struct file *file) { int i = 0; - int minor = MINOR(inode->i_rdev); + int minor = minor(inode->i_rdev); struct trident_card *card = devs; struct trident_state *state = NULL; struct dmabuf *dmabuf = NULL; @@ -3750,7 +3751,7 @@ static int trident_open_mixdev(struct inode *inode, struct file *file) { int i = 0; - int minor = MINOR(inode->i_rdev); + int minor = minor(inode->i_rdev); struct trident_card *card = devs; for (card = devs; card != NULL; card = card->next) @@ -3948,13 +3949,20 @@ u16 temp; struct pci_dev *pci_dev_m1533 = NULL; int rc = -ENODEV; + u64 dma_mask; if (pci_enable_device(pci_dev)) goto out; - if (pci_set_dma_mask(pci_dev, TRIDENT_DMA_MASK)) { + if (pci_dev->device == PCI_DEVICE_ID_ALI_5451) + dma_mask = ALI_DMA_MASK; + else + dma_mask = TRIDENT_DMA_MASK; + if (pci_set_dma_mask(pci_dev, dma_mask)) { printk(KERN_ERR "trident: architecture does not support" - " 30bit PCI busmaster DMA\n"); + " %s PCI busmaster DMA\n", + pci_dev->device == PCI_DEVICE_ID_ALI_5451 ? + "32-bit" : "30-bit"); goto out; } pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision); diff -urN linux-2.5.2-pre11/drivers/sound/ymfpci.c linux/drivers/sound/ymfpci.c --- linux-2.5.2-pre11/drivers/sound/ymfpci.c Mon Jan 14 18:28:23 2002 +++ linux/drivers/sound/ymfpci.c Mon Jan 14 18:28:30 2002 @@ -1,6 +1,8 @@ /* * Copyright 1999 Jaroslav Kysela * Copyright 2000 Alan Cox + * Copyright 2001 Kai Germaschewski + * Copyright 2002 Pete Zaitcev * * Yamaha YMF7xx driver. * @@ -37,8 +39,16 @@ * - Remove prog_dmabuf from read/write, leave it in open. * - 2001/01/07 Replace the OPL3 part of CONFIG_SOUND_YMFPCI_LEGACY code with * native synthesizer through a playback slot. - * - Use new 2.3.x cache coherent PCI DMA routines instead of virt_to_bus. - * - Make the thing big endian compatible. ALSA has it done. + * - 2001/11/29 ac97_save_state + * Talk to Kai to remove ac97_save_state before it's too late! + * - Second AC97 + * - Restore S/PDIF - Toshibas have it. + * + * Kai used pci_alloc_consistent for DMA buffer, which sounds a little + * unconventional. However, given how small our fragments can be, + * a little uncached access is perhaps better than endless flushing. + * On i386 and other I/O-coherent architectures pci_alloc_consistent + * is entirely harmless. */ #include @@ -155,7 +165,7 @@ schedule_timeout(1); } } while (end_time - (signed long)jiffies >= 0); - printk("ymfpci_codec_ready: codec %i is not ready [0x%x]\n", + printk(KERN_ERR "ymfpci_codec_ready: codec %i is not ready [0x%x]\n", secondary, ymfpci_readw(codec, reg)); return -EBUSY; } @@ -173,19 +183,19 @@ static u16 ymfpci_codec_read(struct ac97_codec *dev, u8 reg) { - ymfpci_t *codec = dev->private_data; + ymfpci_t *unit = dev->private_data; + int i; - if (ymfpci_codec_ready(codec, 0, 0)) + if (ymfpci_codec_ready(unit, 0, 0)) return ~0; - ymfpci_writew(codec, YDSXGR_AC97CMDADR, YDSXG_AC97READCMD | reg); - if (ymfpci_codec_ready(codec, 0, 0)) + ymfpci_writew(unit, YDSXGR_AC97CMDADR, YDSXG_AC97READCMD | reg); + if (ymfpci_codec_ready(unit, 0, 0)) return ~0; - if (codec->pci->device == PCI_DEVICE_ID_YAMAHA_744 && codec->rev < 2) { - int i; + if (unit->pci->device == PCI_DEVICE_ID_YAMAHA_744 && unit->rev < 2) { for (i = 0; i < 600; i++) - ymfpci_readw(codec, YDSXGR_PRISTATUSDATA); + ymfpci_readw(unit, YDSXGR_PRISTATUSDATA); } - return ymfpci_readw(codec, YDSXGR_PRISTATUSDATA); + return ymfpci_readw(unit, YDSXGR_PRISTATUSDATA); } /* @@ -279,18 +289,22 @@ #define DMABUF_DEFAULTORDER (15-PAGE_SHIFT) #define DMABUF_MINORDER 1 -/* allocate DMA buffer, playback and recording buffer should be allocated seperately */ -static int alloc_dmabuf(struct ymf_dmabuf *dmabuf) +/* + * Allocate DMA buffer + */ +static int alloc_dmabuf(ymfpci_t *unit, struct ymf_dmabuf *dmabuf) { void *rawbuf = NULL; + dma_addr_t dma_addr; int order; - struct page * map, * mapend; + struct page *map, *mapend; /* alloc as big a chunk as we can */ - for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) - if((rawbuf = (void *)__get_free_pages(GFP_KERNEL|GFP_DMA, order))) + for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) { + rawbuf = pci_alloc_consistent(unit->pci, PAGE_SIZE << order, &dma_addr); + if (rawbuf) break; - + } if (!rawbuf) return -ENOMEM; @@ -301,6 +315,7 @@ dmabuf->ready = dmabuf->mapped = 0; dmabuf->rawbuf = rawbuf; + dmabuf->dma_addr = dma_addr; dmabuf->buforder = order; /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */ @@ -311,8 +326,10 @@ return 0; } -/* free DMA buffer */ -static void dealloc_dmabuf(struct ymf_dmabuf *dmabuf) +/* + * Free DMA buffer + */ +static void dealloc_dmabuf(ymfpci_t *unit, struct ymf_dmabuf *dmabuf) { struct page *map, *mapend; @@ -321,7 +338,9 @@ mapend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1); for (map = virt_to_page(dmabuf->rawbuf); map <= mapend; map++) clear_bit(PG_reserved, &map->flags); - free_pages((unsigned long)dmabuf->rawbuf,dmabuf->buforder); + + pci_free_consistent(unit->pci, PAGE_SIZE << dmabuf->buforder, + dmabuf->rawbuf, dmabuf->dma_addr); } dmabuf->rawbuf = NULL; dmabuf->mapped = dmabuf->ready = 0; @@ -347,7 +366,7 @@ /* allocate DMA buffer if not allocated yet */ if (!dmabuf->rawbuf) - if ((ret = alloc_dmabuf(dmabuf))) + if ((ret = alloc_dmabuf(state->unit, dmabuf))) return ret; /* @@ -404,7 +423,7 @@ dmabuf->ready = 1; #if 0 - printk("prog_dmabuf: rate %d format 0x%x," + printk(KERN_DEBUG "prog_dmabuf: rate %d format 0x%x," " numfrag %d fragsize %d dmasize %d\n", state->format.rate, state->format.format, dmabuf->numfrag, dmabuf->fragsize, dmabuf->dmasize); @@ -587,7 +606,8 @@ if (ypcm->running) { YMFDBGI("ymfpci: %d, intr bank %d count %d start 0x%x:%x\n", voice->number, codec->active_bank, dmabuf->count, - voice->bank[0].start, voice->bank[1].start); + le32_to_cpu(voice->bank[0].start), + le32_to_cpu(voice->bank[1].start)); silence = (ymf_pcm_format_width(state->format.format) == 16) ? 0 : 0x80; /* We need actual left-hand-side redzone size here. */ @@ -595,7 +615,7 @@ redzone <<= (state->format.shift + 1); swptr = dmabuf->swptr; - pos = voice->bank[codec->active_bank].start; + pos = le32_to_cpu(voice->bank[codec->active_bank].start); pos <<= state->format.shift; if (pos < 0 || pos >= dmabuf->dmasize) { /* ucode bug */ printk(KERN_ERR "ymfpci%d: runaway voice %d: hwptr %d=>%d dmasize %d\n", @@ -615,7 +635,7 @@ dmabuf->hwptr = pos; if (dmabuf->count == 0) { - printk("ymfpci%d: %d: strain: hwptr %d\n", + printk(KERN_ERR "ymfpci%d: %d: strain: hwptr %d\n", codec->dev_audio, voice->number, dmabuf->hwptr); ymf_playback_trigger(codec, ypcm, 0); } @@ -633,7 +653,7 @@ /* * Lost interrupt or other screwage. */ - printk("ymfpci%d: %d: lost: delta %d" + printk(KERN_ERR "ymfpci%d: %d: lost: delta %d" " hwptr %d swptr %d distance %d count %d\n", codec->dev_audio, voice->number, delta, dmabuf->hwptr, swptr, distance, dmabuf->count); @@ -641,10 +661,10 @@ /* * Normal end of DMA. */ -// printk("ymfpci%d: %d: done: delta %d" -// " hwptr %d swptr %d distance %d count %d\n", -// codec->dev_audio, voice->number, delta, -// dmabuf->hwptr, swptr, distance, dmabuf->count); + YMFDBGI("ymfpci%d: %d: done: delta %d" + " hwptr %d swptr %d distance %d count %d\n", + codec->dev_audio, voice->number, delta, + dmabuf->hwptr, swptr, distance, dmabuf->count); } played = dmabuf->count; if (ypcm->running) { @@ -698,7 +718,7 @@ redzone = ymf_calc_lend(state->format.rate); redzone <<= (state->format.shift + 1); - pos = cap->bank[unit->active_bank].start; + pos = le32_to_cpu(cap->bank[unit->active_bank].start); // pos <<= state->format.shift; if (pos < 0 || pos >= dmabuf->dmasize) { /* ucode bug */ printk(KERN_ERR "ymfpci%d: runaway capture %d: hwptr %d=>%d dmasize %d\n", @@ -742,9 +762,11 @@ return -EINVAL; } if (cmd != 0) { - codec->ctrl_playback[ypcm->voices[0]->number + 1] = virt_to_bus(ypcm->voices[0]->bank); + codec->ctrl_playback[ypcm->voices[0]->number + 1] = + cpu_to_le32(ypcm->voices[0]->bank_ba); if (ypcm->voices[1] != NULL) - codec->ctrl_playback[ypcm->voices[1]->number + 1] = virt_to_bus(ypcm->voices[1]->bank); + codec->ctrl_playback[ypcm->voices[1]->number + 1] = + cpu_to_le32(ypcm->voices[1]->bank_ba); ypcm->running = 1; } else { codec->ctrl_playback[ypcm->voices[0]->number + 1] = 0; @@ -810,6 +832,7 @@ u32 lpfK = ymfpci_calc_lpfK(rate); ymfpci_playback_bank_t *bank; int nbank; + unsigned le_0x40000000 = cpu_to_le32(0x40000000); format = (stereo ? 0x00010000 : 0) | (w_16 ? 0 : 0x80000000); if (stereo) @@ -818,24 +841,24 @@ end >>= 1; for (nbank = 0; nbank < 2; nbank++) { bank = &voice->bank[nbank]; - bank->format = format; + bank->format = cpu_to_le32(format); bank->loop_default = 0; /* 0-loops forever, otherwise count */ - bank->base = addr; + bank->base = cpu_to_le32(addr); bank->loop_start = 0; - bank->loop_end = end; + bank->loop_end = cpu_to_le32(end); bank->loop_frac = 0; - bank->eg_gain_end = 0x40000000; - bank->lpfQ = lpfQ; + bank->eg_gain_end = le_0x40000000; + bank->lpfQ = cpu_to_le32(lpfQ); bank->status = 0; bank->num_of_frames = 0; bank->loop_count = 0; bank->start = 0; bank->start_frac = 0; bank->delta = - bank->delta_end = delta; + bank->delta_end = cpu_to_le32(delta); bank->lpfK = - bank->lpfK_end = lpfK; - bank->eg_gain = 0x40000000; + bank->lpfK_end = cpu_to_le32(lpfK); + bank->eg_gain = le_0x40000000; bank->lpfD1 = bank->lpfD2 = 0; @@ -855,31 +878,31 @@ bank->left_gain = bank->right_gain = bank->left_gain_end = - bank->right_gain_end = 0x40000000; + bank->right_gain_end = le_0x40000000; } else { bank->eff2_gain = bank->eff2_gain_end = bank->eff3_gain = - bank->eff3_gain_end = 0x40000000; + bank->eff3_gain_end = le_0x40000000; } } else { if (!spdif) { if ((voice->number & 1) == 0) { bank->left_gain = - bank->left_gain_end = 0x40000000; + bank->left_gain_end = le_0x40000000; } else { - bank->format |= 1; + bank->format |= cpu_to_le32(1); bank->right_gain = - bank->right_gain_end = 0x40000000; + bank->right_gain_end = le_0x40000000; } } else { if ((voice->number & 1) == 0) { bank->eff2_gain = - bank->eff2_gain_end = 0x40000000; + bank->eff2_gain_end = le_0x40000000; } else { - bank->format |= 1; + bank->format |= cpu_to_le32(1); bank->eff3_gain = - bank->eff3_gain_end = 0x40000000; + bank->eff3_gain_end = le_0x40000000; } } } @@ -920,7 +943,7 @@ ymf_pcm_init_voice(ypcm->voices[nvoice], state->format.voices == 2, state->format.rate, ymf_pcm_format_width(state->format.format) == 16, - virt_to_bus(ypcm->dmabuf.rawbuf), ypcm->dmabuf.dmasize, + ypcm->dmabuf.dma_addr, ypcm->dmabuf.dmasize, ypcm->spdif); } return 0; @@ -969,9 +992,9 @@ } for (nbank = 0; nbank < 2; nbank++) { bank = unit->bank_capture[ypcm->capture_bank_number][nbank]; - bank->base = virt_to_bus(ypcm->dmabuf.rawbuf); + bank->base = cpu_to_le32(ypcm->dmabuf.dma_addr); // bank->loop_end = ypcm->dmabuf.dmasize >> state->format.shift; - bank->loop_end = ypcm->dmabuf.dmasize; + bank->loop_end = cpu_to_le32(ypcm->dmabuf.dmasize); bank->start = 0; bank->num_of_loops = 0; } @@ -1442,13 +1465,14 @@ { struct ymf_state *state = (struct ymf_state *)file->private_data; struct ymf_dmabuf *dmabuf; + int redzone; unsigned long flags; unsigned int mask = 0; if (file->f_mode & FMODE_WRITE) poll_wait(file, &state->wpcm.dmabuf.wait, wait); - // if (file->f_mode & FMODE_READ) - // poll_wait(file, &dmabuf->wait, wait); + if (file->f_mode & FMODE_READ) + poll_wait(file, &state->rpcm.dmabuf.wait, wait); spin_lock_irqsave(&state->unit->reg_lock, flags); if (file->f_mode & FMODE_READ) { @@ -1457,12 +1481,21 @@ mask |= POLLIN | POLLRDNORM; } if (file->f_mode & FMODE_WRITE) { + redzone = ymf_calc_lend(state->format.rate); + redzone <<= state->format.shift; + redzone *= 3; + dmabuf = &state->wpcm.dmabuf; if (dmabuf->mapped) { if (dmabuf->count >= (signed)dmabuf->fragsize) mask |= POLLOUT | POLLWRNORM; } else { - if ((signed)dmabuf->dmasize >= dmabuf->count + (signed)dmabuf->fragsize) + /* + * Don't select unless a full fragment is available. + * Otherwise artsd does GETOSPACE, sees 0, and loops. + */ + if (dmabuf->count + redzone + dmabuf->fragsize + <= dmabuf->dmasize) mask |= POLLOUT | POLLWRNORM; } } @@ -1497,6 +1530,7 @@ return -EAGAIN; dmabuf->mapped = 1; +/* P3 */ printk(KERN_INFO "ymfpci: using memory mapped sound, untested!\n"); return 0; } @@ -1508,13 +1542,16 @@ unsigned long flags; audio_buf_info abinfo; count_info cinfo; + int redzone; int val; switch (cmd) { case OSS_GETVERSION: + YMFDBGX("ymf_ioctl: cmd 0x%x(GETVER) arg 0x%lx\n", cmd, arg); return put_user(SOUND_VERSION, (int *)arg); case SNDCTL_DSP_RESET: + YMFDBGX("ymf_ioctl: cmd 0x%x(RESET)\n", cmd); if (file->f_mode & FMODE_WRITE) { ymf_wait_dac(state); dmabuf = &state->wpcm.dmabuf; @@ -1536,6 +1573,7 @@ return 0; case SNDCTL_DSP_SYNC: + YMFDBGX("ymf_ioctl: cmd 0x%x(SYNC)\n", cmd); if (file->f_mode & FMODE_WRITE) { dmabuf = &state->wpcm.dmabuf; if (file->f_flags & O_NONBLOCK) { @@ -1554,6 +1592,7 @@ case SNDCTL_DSP_SPEED: /* set smaple rate */ if (get_user(val, (int *)arg)) return -EFAULT; + YMFDBGX("ymf_ioctl: cmd 0x%x(SPEED) sp %d\n", cmd, val); if (val >= 8000 && val <= 48000) { if (file->f_mode & FMODE_WRITE) { ymf_wait_dac(state); @@ -1585,6 +1624,7 @@ case SNDCTL_DSP_STEREO: /* set stereo or mono channel */ if (get_user(val, (int *)arg)) return -EFAULT; + YMFDBGX("ymf_ioctl: cmd 0x%x(STEREO) st %d\n", cmd, val); if (file->f_mode & FMODE_WRITE) { ymf_wait_dac(state); dmabuf = &state->wpcm.dmabuf; @@ -1606,24 +1646,31 @@ return 0; case SNDCTL_DSP_GETBLKSIZE: + YMFDBGX("ymf_ioctl: cmd 0x%x(GETBLK)\n", cmd); if (file->f_mode & FMODE_WRITE) { if ((val = prog_dmabuf(state, 0))) return val; - return put_user(state->wpcm.dmabuf.fragsize, (int *)arg); + val = state->wpcm.dmabuf.fragsize; + YMFDBGX("ymf_ioctl: GETBLK w %d\n", val); + return put_user(val, (int *)arg); } if (file->f_mode & FMODE_READ) { if ((val = prog_dmabuf(state, 1))) return val; - return put_user(state->rpcm.dmabuf.fragsize, (int *)arg); + val = state->rpcm.dmabuf.fragsize; + YMFDBGX("ymf_ioctl: GETBLK r %d\n", val); + return put_user(val, (int *)arg); } return -EINVAL; case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format*/ + YMFDBGX("ymf_ioctl: cmd 0x%x(GETFMTS)\n", cmd); return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg); case SNDCTL_DSP_SETFMT: /* Select sample format */ if (get_user(val, (int *)arg)) return -EFAULT; + YMFDBGX("ymf_ioctl: cmd 0x%x(SETFMT) fmt %d\n", cmd, val); if (val == AFMT_S16_LE || val == AFMT_U8) { if (file->f_mode & FMODE_WRITE) { ymf_wait_dac(state); @@ -1649,6 +1696,7 @@ case SNDCTL_DSP_CHANNELS: if (get_user(val, (int *)arg)) return -EFAULT; + YMFDBGX("ymf_ioctl: cmd 0x%x(CHAN) ch %d\n", cmd, val); if (val != 0) { if (file->f_mode & FMODE_WRITE) { ymf_wait_dac(state); @@ -1676,6 +1724,7 @@ return put_user(state->format.voices, (int *)arg); case SNDCTL_DSP_POST: + YMFDBGX("ymf_ioctl: cmd 0x%x(POST)\n", cmd); /* * Quoting OSS PG: * The ioctl SNDCTL_DSP_POST is a lightweight version of @@ -1697,6 +1746,10 @@ case SNDCTL_DSP_SETFRAGMENT: if (get_user(val, (int *)arg)) return -EFAULT; + YMFDBGX("ymf_ioctl: cmd 0x%x(SETFRAG) fr 0x%04x:%04x(%d:%d)\n", + cmd, + (val >> 16) & 0xFFFF, val & 0xFFFF, + (val >> 16) & 0xFFFF, val & 0xFFFF); dmabuf = &state->wpcm.dmabuf; dmabuf->ossfragshift = val & 0xffff; dmabuf->ossmaxfrags = (val >> 16) & 0xffff; @@ -1707,20 +1760,25 @@ return 0; case SNDCTL_DSP_GETOSPACE: + YMFDBGX("ymf_ioctl: cmd 0x%x(GETOSPACE)\n", cmd); if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; dmabuf = &state->wpcm.dmabuf; if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0) return val; + redzone = ymf_calc_lend(state->format.rate); + redzone <<= state->format.shift; + redzone *= 3; spin_lock_irqsave(&state->unit->reg_lock, flags); abinfo.fragsize = dmabuf->fragsize; - abinfo.bytes = dmabuf->dmasize - dmabuf->count; + abinfo.bytes = dmabuf->dmasize - dmabuf->count - redzone; abinfo.fragstotal = dmabuf->numfrag; abinfo.fragments = abinfo.bytes >> dmabuf->fragshift; spin_unlock_irqrestore(&state->unit->reg_lock, flags); return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; case SNDCTL_DSP_GETISPACE: + YMFDBGX("ymf_ioctl: cmd 0x%x(GETISPACE)\n", cmd); if (!(file->f_mode & FMODE_READ)) return -EINVAL; dmabuf = &state->rpcm.dmabuf; @@ -1735,15 +1793,18 @@ return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; case SNDCTL_DSP_NONBLOCK: + YMFDBGX("ymf_ioctl: cmd 0x%x(NONBLOCK)\n", cmd); file->f_flags |= O_NONBLOCK; return 0; case SNDCTL_DSP_GETCAPS: + YMFDBGX("ymf_ioctl: cmd 0x%x(GETCAPS)\n", cmd); /* return put_user(DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP, (int *)arg); */ return put_user(0, (int *)arg); case SNDCTL_DSP_GETIPTR: + YMFDBGX("ymf_ioctl: cmd 0x%x(GETIPTR)\n", cmd); if (!(file->f_mode & FMODE_READ)) return -EINVAL; dmabuf = &state->rpcm.dmabuf; @@ -1751,13 +1812,13 @@ cinfo.bytes = dmabuf->total_bytes; cinfo.blocks = dmabuf->count >> dmabuf->fragshift; cinfo.ptr = dmabuf->hwptr; - /* XXX fishy - breaks invariant count=hwptr-swptr */ - if (dmabuf->mapped) - dmabuf->count &= dmabuf->fragsize-1; spin_unlock_irqrestore(&state->unit->reg_lock, flags); + YMFDBGX("ymf_ioctl: GETIPTR ptr %d bytes %d\n", + cinfo.ptr, cinfo.bytes); return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0; case SNDCTL_DSP_GETOPTR: + YMFDBGX("ymf_ioctl: cmd 0x%x(GETOPTR)\n", cmd); if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; dmabuf = &state->wpcm.dmabuf; @@ -1765,22 +1826,25 @@ cinfo.bytes = dmabuf->total_bytes; cinfo.blocks = dmabuf->count >> dmabuf->fragshift; cinfo.ptr = dmabuf->hwptr; - /* XXX fishy - breaks invariant count=swptr-hwptr */ - if (dmabuf->mapped) - dmabuf->count &= dmabuf->fragsize-1; spin_unlock_irqrestore(&state->unit->reg_lock, flags); + YMFDBGX("ymf_ioctl: GETOPTR ptr %d bytes %d\n", + cinfo.ptr, cinfo.bytes); return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0; - case SNDCTL_DSP_SETDUPLEX: /* XXX TODO */ - return -EINVAL; + case SNDCTL_DSP_SETDUPLEX: + YMFDBGX("ymf_ioctl: cmd 0x%x(SETDUPLEX)\n", cmd); + return 0; /* Always duplex */ case SOUND_PCM_READ_RATE: + YMFDBGX("ymf_ioctl: cmd 0x%x(READ_RATE)\n", cmd); return put_user(state->format.rate, (int *)arg); case SOUND_PCM_READ_CHANNELS: + YMFDBGX("ymf_ioctl: cmd 0x%x(READ_CH)\n", cmd); return put_user(state->format.voices, (int *)arg); case SOUND_PCM_READ_BITS: + YMFDBGX("ymf_ioctl: cmd 0x%x(READ_BITS)\n", cmd); return put_user(AFMT_S16_LE, (int *)arg); case SNDCTL_DSP_MAPINBUF: @@ -1796,6 +1860,7 @@ * Some programs mix up audio devices and ioctls * or perhaps they expect "universal" ioctls, * for instance we get SNDCTL_TMR_CONTINUE here. + * (mpg123 -g 100 ends here too - to be fixed.) */ YMFDBGX("ymf_ioctl: cmd 0x%x unknown\n", cmd); break; @@ -1866,8 +1931,8 @@ } #if 0 /* test if interrupts work */ - ymfpci_writew(codec, YDSXGR_TIMERCOUNT, 0xfffe); /* ~ 680ms */ - ymfpci_writeb(codec, YDSXGR_TIMERCTRL, + ymfpci_writew(unit, YDSXGR_TIMERCOUNT, 0xfffe); /* ~ 680ms */ + ymfpci_writeb(unit, YDSXGR_TIMERCTRL, (YDSXGR_TIMERCTRL_TEN|YDSXGR_TIMERCTRL_TIEN)); #endif up(&unit->open_sem); @@ -1880,8 +1945,8 @@ * a nestable exception, but here it is not nestable due to semaphore. * XXX Doubtful technique of self-describing objects.... */ - dealloc_dmabuf(&state->wpcm.dmabuf); - dealloc_dmabuf(&state->rpcm.dmabuf); + dealloc_dmabuf(unit, &state->wpcm.dmabuf); + dealloc_dmabuf(unit, &state->rpcm.dmabuf); ymf_pcm_free_substream(&state->wpcm); ymf_pcm_free_substream(&state->rpcm); @@ -1895,13 +1960,13 @@ static int ymf_release(struct inode *inode, struct file *file) { struct ymf_state *state = (struct ymf_state *)file->private_data; - ymfpci_t *codec = state->unit; + ymfpci_t *unit = state->unit; #if 0 /* test if interrupts work */ - ymfpci_writeb(codec, YDSXGR_TIMERCTRL, 0); + ymfpci_writeb(unit, YDSXGR_TIMERCTRL, 0); #endif - down(&codec->open_sem); + down(&unit->open_sem); /* * XXX Solve the case of O_NONBLOCK close - don't deallocate here. @@ -1909,8 +1974,8 @@ */ ymf_wait_dac(state); ymf_stop_adc(state); /* fortunately, it's immediate */ - dealloc_dmabuf(&state->wpcm.dmabuf); - dealloc_dmabuf(&state->rpcm.dmabuf); + dealloc_dmabuf(unit, &state->wpcm.dmabuf); + dealloc_dmabuf(unit, &state->rpcm.dmabuf); ymf_pcm_free_substream(&state->wpcm); ymf_pcm_free_substream(&state->rpcm); @@ -1918,7 +1983,7 @@ file->private_data = NULL; /* Can you tell I programmed Solaris */ kfree(state); - up(&codec->open_sem); + up(&unit->open_sem); return 0; } @@ -1928,10 +1993,10 @@ */ static int ymf_open_mixdev(struct inode *inode, struct file *file) { - int i; int minor = minor(inode->i_rdev); struct list_head *list; ymfpci_t *unit; + int i; list_for_each(list, &ymf_devs) { unit = list_entry(list, ymfpci_t, ymf_devs); @@ -1988,23 +2053,21 @@ static int ymf_suspend(struct pci_dev *pcidev, u32 unused) { - int i; struct ymf_unit *unit = pci_get_drvdata(pcidev); unsigned long flags; struct ymf_dmabuf *dmabuf; struct list_head *p; struct ymf_state *state; struct ac97_codec *codec; + int i; spin_lock_irqsave(&unit->reg_lock, flags); unit->suspended = 1; for (i = 0; i < NR_AC97; i++) { - codec = unit->ac97_codec[i]; - if (!codec) - continue; - ac97_save_state(codec); + if ((codec = unit->ac97_codec[i]) != NULL) + ac97_save_state(codec); } list_for_each(p, &unit->states) { @@ -2031,12 +2094,12 @@ static int ymf_resume(struct pci_dev *pcidev) { - int i; struct ymf_unit *unit = pci_get_drvdata(pcidev); unsigned long flags; struct list_head *p; struct ymf_state *state; struct ac97_codec *codec; + int i; ymfpci_aclink_reset(unit->pci); ymfpci_codec_ready(unit, 0, 1); /* prints diag if not ready. */ @@ -2057,10 +2120,8 @@ } for (i = 0; i < NR_AC97; i++) { - codec = unit->ac97_codec[i]; - if (!codec) - continue; - ac97_restore_state(codec); + if ((codec = unit->ac97_codec[i]) != NULL) + ac97_restore_state(codec); } unit->suspended = 0; @@ -2160,12 +2221,15 @@ { u8 cmd; + /* + * In the 744, 754 only 0x01 exists, 0x02 is undefined. + * It does not seem to hurt to trip both regardless of revision. + */ pci_read_config_byte(pci, PCIR_DSXGCTRL, &cmd); - if (cmd & 0x03) { - pci_write_config_byte(pci, PCIR_DSXGCTRL, cmd & 0xfc); - pci_write_config_byte(pci, PCIR_DSXGCTRL, cmd | 0x03); - pci_write_config_byte(pci, PCIR_DSXGCTRL, cmd & 0xfc); - } + pci_write_config_byte(pci, PCIR_DSXGCTRL, cmd & 0xfc); + pci_write_config_byte(pci, PCIR_DSXGCTRL, cmd | 0x03); + pci_write_config_byte(pci, PCIR_DSXGCTRL, cmd & 0xfc); + pci_write_config_word(pci, PCIR_DSXPWRCTRL1, 0); pci_write_config_word(pci, PCIR_DSXPWRCTRL2, 0); } @@ -2241,29 +2305,39 @@ static int ymfpci_memalloc(ymfpci_t *codec) { - long size, playback_ctrl_size; + unsigned int playback_ctrl_size; + unsigned int bank_size_playback; + unsigned int bank_size_capture; + unsigned int bank_size_effect; + unsigned int size; + unsigned int off; + char *ptr; + dma_addr_t pba; int voice, bank; - u8 *ptr; playback_ctrl_size = 4 + 4 * YDSXG_PLAYBACK_VOICES; - codec->bank_size_playback = ymfpci_readl(codec, YDSXGR_PLAYCTRLSIZE) << 2; - codec->bank_size_capture = ymfpci_readl(codec, YDSXGR_RECCTRLSIZE) << 2; - codec->bank_size_effect = ymfpci_readl(codec, YDSXGR_EFFCTRLSIZE) << 2; + bank_size_playback = ymfpci_readl(codec, YDSXGR_PLAYCTRLSIZE) << 2; + bank_size_capture = ymfpci_readl(codec, YDSXGR_RECCTRLSIZE) << 2; + bank_size_effect = ymfpci_readl(codec, YDSXGR_EFFCTRLSIZE) << 2; codec->work_size = YDSXG_DEFAULT_WORK_SIZE; size = ((playback_ctrl_size + 0x00ff) & ~0x00ff) + - ((codec->bank_size_playback * 2 * YDSXG_PLAYBACK_VOICES + 0xff) & ~0xff) + - ((codec->bank_size_capture * 2 * YDSXG_CAPTURE_VOICES + 0xff) & ~0xff) + - ((codec->bank_size_effect * 2 * YDSXG_EFFECT_VOICES + 0xff) & ~0xff) + + ((bank_size_playback * 2 * YDSXG_PLAYBACK_VOICES + 0xff) & ~0xff) + + ((bank_size_capture * 2 * YDSXG_CAPTURE_VOICES + 0xff) & ~0xff) + + ((bank_size_effect * 2 * YDSXG_EFFECT_VOICES + 0xff) & ~0xff) + codec->work_size; - ptr = (u8 *)kmalloc(size + 0x00ff, GFP_KERNEL); + ptr = pci_alloc_consistent(codec->pci, size + 0xff, &pba); if (ptr == NULL) return -ENOMEM; - - codec->work_ptr = ptr; - ptr += 0x00ff; - (long)ptr &= ~0x00ff; + codec->dma_area_va = ptr; + codec->dma_area_ba = pba; + codec->dma_area_size = size + 0xff; + + if ((off = ((uint) ptr) & 0xff) != 0) { + ptr += 0x100 - off; + pba += 0x100 - off; + } /* * Hardware requires only ptr[playback_ctrl_size] zeroed, @@ -2271,34 +2345,49 @@ */ memset(ptr, 0, size); - codec->bank_base_playback = ptr; codec->ctrl_playback = (u32 *)ptr; - codec->ctrl_playback[0] = YDSXG_PLAYBACK_VOICES; + codec->ctrl_playback_ba = pba; + codec->ctrl_playback[0] = cpu_to_le32(YDSXG_PLAYBACK_VOICES); ptr += (playback_ctrl_size + 0x00ff) & ~0x00ff; + pba += (playback_ctrl_size + 0x00ff) & ~0x00ff; + + off = 0; for (voice = 0; voice < YDSXG_PLAYBACK_VOICES; voice++) { - for (bank = 0; bank < 2; bank++) { - codec->bank_playback[voice][bank] = (ymfpci_playback_bank_t *)ptr; - ptr += codec->bank_size_playback; - } codec->voices[voice].number = voice; - codec->voices[voice].bank = codec->bank_playback[voice][0]; - } - ptr += (codec->bank_size_playback + 0x00ff) & ~0x00ff; - codec->bank_base_capture = ptr; + codec->voices[voice].bank = + (ymfpci_playback_bank_t *) (ptr + off); + codec->voices[voice].bank_ba = pba + off; + off += 2 * bank_size_playback; /* 2 banks */ + } + off = (off + 0xff) & ~0xff; + ptr += off; + pba += off; + + off = 0; + codec->bank_base_capture = pba; for (voice = 0; voice < YDSXG_CAPTURE_VOICES; voice++) for (bank = 0; bank < 2; bank++) { - codec->bank_capture[voice][bank] = (ymfpci_capture_bank_t *)ptr; - ptr += codec->bank_size_capture; - } - ptr += (codec->bank_size_capture + 0x00ff) & ~0x00ff; - codec->bank_base_effect = ptr; + codec->bank_capture[voice][bank] = + (ymfpci_capture_bank_t *) (ptr + off); + off += bank_size_capture; + } + off = (off + 0xff) & ~0xff; + ptr += off; + pba += off; + + off = 0; + codec->bank_base_effect = pba; for (voice = 0; voice < YDSXG_EFFECT_VOICES; voice++) for (bank = 0; bank < 2; bank++) { - codec->bank_effect[voice][bank] = (ymfpci_effect_bank_t *)ptr; - ptr += codec->bank_size_effect; - } - ptr += (codec->bank_size_effect + 0x00ff) & ~0x00ff; - codec->work_base = ptr; + codec->bank_effect[voice][bank] = + (ymfpci_effect_bank_t *) (ptr + off); + off += bank_size_effect; + } + off = (off + 0xff) & ~0xff; + ptr += off; + pba += off; + + codec->work_base = pba; return 0; } @@ -2310,16 +2399,17 @@ ymfpci_writel(codec, YDSXGR_EFFCTRLBASE, 0); ymfpci_writel(codec, YDSXGR_WORKBASE, 0); ymfpci_writel(codec, YDSXGR_WORKSIZE, 0); - kfree(codec->work_ptr); + pci_free_consistent(codec->pci, + codec->dma_area_size, codec->dma_area_va, codec->dma_area_ba); } static void ymf_memload(ymfpci_t *unit) { - ymfpci_writel(unit, YDSXGR_PLAYCTRLBASE, virt_to_bus(unit->bank_base_playback)); - ymfpci_writel(unit, YDSXGR_RECCTRLBASE, virt_to_bus(unit->bank_base_capture)); - ymfpci_writel(unit, YDSXGR_EFFCTRLBASE, virt_to_bus(unit->bank_base_effect)); - ymfpci_writel(unit, YDSXGR_WORKBASE, virt_to_bus(unit->work_base)); + ymfpci_writel(unit, YDSXGR_PLAYCTRLBASE, unit->ctrl_playback_ba); + ymfpci_writel(unit, YDSXGR_RECCTRLBASE, unit->bank_base_capture); + ymfpci_writel(unit, YDSXGR_EFFCTRLBASE, unit->bank_base_effect); + ymfpci_writel(unit, YDSXGR_WORKBASE, unit->work_base); ymfpci_writel(unit, YDSXGR_WORKSIZE, unit->work_size >> 2); /* S/PDIF output initialization */ @@ -2357,7 +2447,7 @@ codec->codec_write = ymfpci_codec_write; if (ac97_probe_codec(codec) == 0) { - printk("ymfpci: ac97_probe_codec failed\n"); + printk(KERN_ERR "ymfpci: ac97_probe_codec failed\n"); goto out_kfree; } @@ -2398,6 +2488,7 @@ static int __devinit ymf_probe_one(struct pci_dev *pcidev, const struct pci_device_id *ent) { u16 ctrl; + unsigned long base; ymfpci_t *codec; int err; @@ -2406,6 +2497,7 @@ printk(KERN_ERR "ymfpci: pci_enable_device failed\n"); return err; } + base = pci_resource_start(pcidev, 0); if ((codec = kmalloc(sizeof(ymfpci_t), GFP_KERNEL)) == NULL) { printk(KERN_ERR "ymfpci: no core\n"); @@ -2420,16 +2512,21 @@ codec->pci = pcidev; pci_read_config_byte(pcidev, PCI_REVISION_ID, &codec->rev); - codec->reg_area_virt = ioremap(pci_resource_start(pcidev, 0), 0x8000); - if (codec->reg_area_virt == NULL) { - printk(KERN_ERR "ymfpci: unable to map registers\n"); + + if (request_mem_region(base, 0x8000, "ymfpci") == NULL) { + printk(KERN_ERR "ymfpci: unable to request mem region\n"); goto out_free; } + if ((codec->reg_area_virt = ioremap(base, 0x8000)) == NULL) { + printk(KERN_ERR "ymfpci: unable to map registers\n"); + goto out_release_region; + } + pci_set_master(pcidev); printk(KERN_INFO "ymfpci: %s at 0x%lx IRQ %d\n", - (char *)ent->driver_data, pci_resource_start(pcidev, 0), pcidev->irq); + (char *)ent->driver_data, base, pcidev->irq); ymfpci_aclink_reset(pcidev); if (ymfpci_codec_ready(codec, 0, 1) < 0) @@ -2459,8 +2556,7 @@ /* register /dev/dsp */ if ((codec->dev_audio = register_sound_dsp(&ymf_fops, -1)) < 0) { - printk(KERN_ERR "ymfpci%d: unable to register dsp\n", - codec->dev_audio); + printk(KERN_ERR "ymfpci: unable to register dsp\n"); goto out_free_irq; } @@ -2478,7 +2574,7 @@ codec->opl3_data.irq = -1; codec->mpu_data.io_base = codec->iomidi; - codec->mpu_data.irq = -1; /* XXX Make it ours. */ + codec->mpu_data.irq = -1; /* May be different from our PCI IRQ. */ if (codec->iomidi) { if (!probe_uart401(&codec->mpu_data, THIS_MODULE)) { @@ -2506,6 +2602,8 @@ ymfpci_writel(codec, YDSXGR_STATUS, ~0); out_unmap: iounmap(codec->reg_area_virt); + out_release_region: + release_mem_region(pci_resource_start(pcidev, 0), 0x8000); out_free: kfree(codec); return -ENODEV; @@ -2529,6 +2627,7 @@ ctrl = ymfpci_readw(codec, YDSXGR_GLOBALCTRL); ymfpci_writew(codec, YDSXGR_GLOBALCTRL, ctrl & ~0x0007); iounmap(codec->reg_area_virt); + release_mem_region(pci_resource_start(pcidev, 0), 0x8000); #ifdef CONFIG_SOUND_YMFPCI_LEGACY if (codec->iomidi) { unload_uart401(&codec->mpu_data); diff -urN linux-2.5.2-pre11/drivers/sound/ymfpci.h linux/drivers/sound/ymfpci.h --- linux-2.5.2-pre11/drivers/sound/ymfpci.h Sun Aug 12 10:51:42 2001 +++ linux/drivers/sound/ymfpci.h Mon Jan 14 18:28:30 2002 @@ -227,6 +227,7 @@ char use, pcm, synth, midi; // bool ymfpci_playback_bank_t *bank; struct ymf_pcm *ypcm; + dma_addr_t bank_ba; }; struct ymf_capture { @@ -239,19 +240,17 @@ struct ymf_unit { u8 rev; /* PCI revision */ void *reg_area_virt; - void *work_ptr; - - unsigned int bank_size_playback; - unsigned int bank_size_capture; - unsigned int bank_size_effect; + void *dma_area_va; + dma_addr_t dma_area_ba; + unsigned int dma_area_size; + + dma_addr_t bank_base_capture; + dma_addr_t bank_base_effect; + dma_addr_t work_base; unsigned int work_size; - void *bank_base_playback; - void *bank_base_capture; - void *bank_base_effect; - void *work_base; - u32 *ctrl_playback; + dma_addr_t ctrl_playback_ba; ymfpci_playback_bank_t *bank_playback[YDSXG_PLAYBACK_VOICES][2]; ymfpci_capture_bank_t *bank_capture[YDSXG_CAPTURE_VOICES][2]; ymfpci_effect_bank_t *bank_effect[YDSXG_EFFECT_VOICES][2]; @@ -286,10 +285,11 @@ }; struct ymf_dmabuf { - - /* OSS buffer management stuff */ + dma_addr_t dma_addr; void *rawbuf; unsigned buforder; + + /* OSS buffer management stuff */ unsigned numfrag; unsigned fragshift; diff -urN linux-2.5.2-pre11/drivers/telephony/phonedev.c linux/drivers/telephony/phonedev.c --- linux-2.5.2-pre11/drivers/telephony/phonedev.c Fri Sep 7 09:28:37 2001 +++ linux/drivers/telephony/phonedev.c Mon Jan 14 18:28:30 2002 @@ -46,7 +46,7 @@ static int phone_open(struct inode *inode, struct file *file) { - unsigned int minor = MINOR(inode->i_rdev); + unsigned int minor = minor(inode->i_rdev); int err = 0; struct phone_device *p; struct file_operations *old_fops, *new_fops = NULL; diff -urN linux-2.5.2-pre11/drivers/usb/Makefile.lib linux/drivers/usb/Makefile.lib --- linux-2.5.2-pre11/drivers/usb/Makefile.lib Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/Makefile.lib Mon Jan 14 18:28:30 2002 @@ -0,0 +1 @@ +obj-$(CONFIG_USB_CATC) += crc32.o diff -urN linux-2.5.2-pre11/drivers/usb/catc.c linux/drivers/usb/catc.c --- linux-2.5.2-pre11/drivers/usb/catc.c Mon Jan 14 18:28:23 2002 +++ linux/drivers/usb/catc.c Mon Jan 14 18:28:31 2002 @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -531,13 +532,9 @@ static void catc_multicast(unsigned char *addr, u8 *multicast) { - unsigned int crc = 0xffffffff; - u8 byte, idx, bit; - - for (idx = 0; idx < 6; idx++) - for (byte = *addr++, bit = 0; bit < 8; bit++, byte >>= 1) - crc = (crc >> 1) ^ (((crc ^ byte) & 1) ? 0xedb88320U : 0); + u32 crc; + crc = ether_crc_le(6, addr); multicast[(crc >> 3) & 0x3f] |= 1 << (crc & 7); } diff -urN linux-2.5.2-pre11/drivers/usb/hcd/ehci-hcd.c linux/drivers/usb/hcd/ehci-hcd.c --- linux-2.5.2-pre11/drivers/usb/hcd/ehci-hcd.c Mon Jan 14 18:28:23 2002 +++ linux/drivers/usb/hcd/ehci-hcd.c Mon Jan 14 18:28:31 2002 @@ -743,7 +743,7 @@ static int __init init (void) { dbg (DRIVER_INFO); - dbg ("block sizes: qh %d qtd %d itd %d sitd %d", + dbg ("block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd", sizeof (struct ehci_qh), sizeof (struct ehci_qtd), sizeof (struct ehci_itd), sizeof (struct ehci_sitd)); diff -urN linux-2.5.2-pre11/drivers/usb/hcd/ehci-sched.c linux/drivers/usb/hcd/ehci-sched.c --- linux-2.5.2-pre11/drivers/usb/hcd/ehci-sched.c Mon Jan 14 18:28:23 2002 +++ linux/drivers/usb/hcd/ehci-sched.c Mon Jan 14 18:28:31 2002 @@ -381,7 +381,7 @@ vdbg ("qh %p usecs %d period %d starting frame %d.%d", qh, qh->usecs, period, frame, uframe); do { - if (unlikely ((int)ehci->pshadow [frame].ptr)) { + if (unlikely ((long)ehci->pshadow [frame].ptr)) { // FIXME -- just link to the end, before any qh with a shorter period, // AND handle it already being (implicitly) linked into this frame BUG (); diff -urN linux-2.5.2-pre11/drivers/usb/hcd.c linux/drivers/usb/hcd.c --- linux-2.5.2-pre11/drivers/usb/hcd.c Mon Jan 14 18:28:23 2002 +++ linux/drivers/usb/hcd.c Mon Jan 14 18:28:31 2002 @@ -624,7 +624,7 @@ #ifndef __sparc__ sprintf (buf, "%d", dev->irq); #else - bufp = __irq_itoa(irq); + bufp = __irq_itoa(dev->irq); #endif if (request_irq (dev->irq, hcd_irq, SA_SHIRQ, hcd->description, hcd) != 0) { diff -urN linux-2.5.2-pre11/drivers/video/aty/mach64_accel.c linux/drivers/video/aty/mach64_accel.c --- linux-2.5.2-pre11/drivers/video/aty/mach64_accel.c Tue Jul 31 14:43:29 2001 +++ linux/drivers/video/aty/mach64_accel.c Mon Jan 14 18:28:31 2002 @@ -326,7 +326,7 @@ fbcon_cfb##width##_clear_margins(conp, p, bottom_only), \ int bottom_only) \ \ -const struct display_switch fbcon_aty##width## = { \ +const struct display_switch fbcon_aty##width = { \ setup: fbcon_cfb##width##_setup, \ bmove: fbcon_aty_bmove, \ clear: fbcon_aty_clear, \ diff -urN linux-2.5.2-pre11/drivers/video/sbusfb.c linux/drivers/video/sbusfb.c --- linux-2.5.2-pre11/drivers/video/sbusfb.c Thu Sep 13 16:04:43 2001 +++ linux/drivers/video/sbusfb.c Mon Jan 14 18:28:31 2002 @@ -1019,7 +1019,7 @@ fix->type = FB_TYPE_PACKED_PIXELS; fix->visual = FB_VISUAL_PSEUDOCOLOR; - fb->info.node = -1; + fb->info.node = NODEV; fb->info.fbops = &sbusfb_ops; fb->info.disp = disp; strcpy(fb->info.fontname, fontname); diff -urN linux-2.5.2-pre11/fs/Makefile.lib linux/fs/Makefile.lib --- linux-2.5.2-pre11/fs/Makefile.lib Wed Dec 31 16:00:00 1969 +++ linux/fs/Makefile.lib Mon Jan 14 18:28:31 2002 @@ -0,0 +1,2 @@ +obj-$(CONFIG_FS_JFFS2) += crc32.o +obj-$(CONFIG_EFI_PARTITION) += crc32.o diff -urN linux-2.5.2-pre11/fs/affs/file.c linux/fs/affs/file.c --- linux-2.5.2-pre11/fs/affs/file.c Mon Jan 14 18:28:24 2002 +++ linux/fs/affs/file.c Mon Jan 14 18:28:31 2002 @@ -401,6 +401,7 @@ err_alloc: brelse(ext_bh); bh_result->b_state &= ~(1UL << BH_Mapped); + bh_result->b_bdev = NULL; // unlock cache affs_unlock_ext(inode); return -ENOSPC; diff -urN linux-2.5.2-pre11/fs/block_dev.c linux/fs/block_dev.c --- linux-2.5.2-pre11/fs/block_dev.c Mon Jan 14 18:28:24 2002 +++ linux/fs/block_dev.c Mon Jan 14 18:28:31 2002 @@ -128,6 +128,7 @@ return -EIO; bh->b_dev = inode->i_rdev; + bh->b_bdev = inode->i_bdev; bh->b_blocknr = iblock; bh->b_state |= 1UL << BH_Mapped; return 0; diff -urN linux-2.5.2-pre11/fs/buffer.c linux/fs/buffer.c --- linux-2.5.2-pre11/fs/buffer.c Mon Jan 14 18:28:24 2002 +++ linux/fs/buffer.c Mon Jan 14 18:28:31 2002 @@ -83,7 +83,7 @@ static spinlock_t unused_list_lock = SPIN_LOCK_UNLOCKED; static DECLARE_WAIT_QUEUE_HEAD(buffer_wait); -static int grow_buffers(kdev_t dev, unsigned long block, int size); +static int grow_buffers(struct block_device *bdev, unsigned long block, int size); static void __refile_buffer(struct buffer_head *); /* This is used by some architectures to estimate available memory. */ @@ -557,9 +557,9 @@ spin_unlock(&lru_list_lock); } -struct buffer_head * get_hash_table(kdev_t dev, sector_t block, int size) +struct buffer_head * __get_hash_table(struct block_device *bdev, sector_t block, int size) { - struct buffer_head *bh, **p = &hash(dev, block); + struct buffer_head *bh, **p = &hash(to_kdev_t(bdev->bd_dev), block); read_lock(&hash_table_lock); @@ -572,7 +572,7 @@ continue; if (bh->b_size != size) continue; - if (!kdev_same(bh->b_dev, dev)) + if (bh->b_bdev != bdev) continue; get_bh(bh); break; @@ -1024,15 +1024,14 @@ */ struct buffer_head * __getblk(struct block_device *bdev, sector_t block, int size) { - kdev_t dev = to_kdev_t(bdev->bd_dev); for (;;) { struct buffer_head * bh; - bh = get_hash_table(dev, block, size); + bh = __get_hash_table(bdev, block, size); if (bh) return bh; - if (!grow_buffers(dev, block, size)) + if (!grow_buffers(bdev, block, size)) free_more_memory(); } } @@ -1202,6 +1201,7 @@ kmem_cache_free(bh_cachep, bh); } else { bh->b_dev = B_FREE; + bh->b_bdev = NULL; bh->b_blocknr = -1; bh->b_this_page = NULL; @@ -1305,6 +1305,7 @@ goto no_grow; bh->b_dev = NODEV; + bh->b_bdev = NULL; bh->b_this_page = head; head = bh; @@ -1366,6 +1367,7 @@ if (buffer_mapped(bh)) { mark_buffer_clean(bh); lock_buffer(bh); + bh->b_bdev = NULL; clear_bit(BH_Uptodate, &bh->b_state); clear_bit(BH_Mapped, &bh->b_state); clear_bit(BH_Req, &bh->b_state); @@ -1487,7 +1489,7 @@ { struct buffer_head *old_bh; - old_bh = get_hash_table(bh->b_dev, bh->b_blocknr, bh->b_size); + old_bh = __get_hash_table(bh->b_bdev, bh->b_blocknr, bh->b_size); if (old_bh) { mark_buffer_clean(old_bh); wait_on_buffer(old_bh); @@ -2119,7 +2121,7 @@ * FIXME: we need a swapper_inode->get_block function to remove * some of the bmap kludges and interface ugliness here. */ -int brw_page(int rw, struct page *page, kdev_t dev, sector_t b[], int size) +int brw_page(int rw, struct page *page, struct block_device *bdev, sector_t b[], int size) { struct buffer_head *head, *bh; @@ -2134,7 +2136,8 @@ do { lock_buffer(bh); bh->b_blocknr = *(b++); - bh->b_dev = dev; + bh->b_bdev = bdev; + bh->b_dev = to_kdev_t(bdev->bd_dev); set_bit(BH_Mapped, &bh->b_state); set_buffer_async_io(bh); bh = bh->b_this_page; @@ -2234,7 +2237,7 @@ return NULL; } -static void hash_page_buffers(struct page *page, kdev_t dev, int block, int size) +static void hash_page_buffers(struct page *page, struct block_device *bdev, int block, int size) { struct buffer_head *head = page->buffers; struct buffer_head *bh = head; @@ -2248,7 +2251,8 @@ do { if (!(bh->b_state & (1 << BH_Mapped))) { init_buffer(bh, NULL, NULL); - bh->b_dev = dev; + bh->b_bdev = bdev; + bh->b_dev = to_kdev_t(bdev->bd_dev); bh->b_blocknr = block; bh->b_state = uptodate; } @@ -2267,15 +2271,14 @@ * Try to increase the number of buffers available: the size argument * is used to determine what kind of buffers we want. */ -static int grow_buffers(kdev_t dev, unsigned long block, int size) +static int grow_buffers(struct block_device *bdev, unsigned long block, int size) { struct page * page; - struct block_device *bdev; unsigned long index; int sizebits; /* Size must be multiple of hard sectorsize */ - if (size & (get_hardsect_size(dev)-1)) + if (size & (get_hardsect_size(to_kdev_t(bdev->bd_dev))-1)) BUG(); /* Size must be within 512 bytes and PAGE_SIZE */ if (size < 512 || size > PAGE_SIZE) @@ -2289,22 +2292,14 @@ index = block >> sizebits; block = index << sizebits; - bdev = bdget(kdev_t_to_nr(dev)); - if (!bdev) { - printk("No block device for %s\n", kdevname(dev)); - BUG(); - } - /* Create a page with the proper size buffers.. */ page = grow_dev_page(bdev, index, size); - /* This is "wrong" - talk to Al Viro */ - atomic_dec(&bdev->bd_count); if (!page) return 0; /* Hash in the buffers on the hash list */ - hash_page_buffers(page, dev, block, size); + hash_page_buffers(page, bdev, block, size); UnlockPage(page); page_cache_release(page); diff -urN linux-2.5.2-pre11/fs/coda/inode.c linux/fs/coda/inode.c --- linux-2.5.2-pre11/fs/coda/inode.c Mon Jan 14 18:28:24 2002 +++ linux/fs/coda/inode.c Mon Jan 14 18:28:31 2002 @@ -151,8 +151,8 @@ goto error; } - printk("coda_read_super: rootinode is %ld dev %d\n", - root->i_ino, root->i_dev); + printk("coda_read_super: rootinode is %ld dev %x\n", + root->i_ino, kdev_val(root->i_dev)); sb->s_root = d_alloc_root(root); return sb; diff -urN linux-2.5.2-pre11/fs/coda/pioctl.c linux/fs/coda/pioctl.c --- linux-2.5.2-pre11/fs/coda/pioctl.c Mon Jan 14 18:28:24 2002 +++ linux/fs/coda/pioctl.c Mon Jan 14 18:28:31 2002 @@ -81,7 +81,7 @@ } CDEBUG(D_PIOCTL, "target ino: 0x%ld, dev: 0x%x\n", - target_inode->i_ino, target_inode->i_dev); + target_inode->i_ino, kdev_val(target_inode->i_dev)); /* return if it is not a Coda inode */ if ( target_inode->i_sb != inode->i_sb ) { diff -urN linux-2.5.2-pre11/fs/dcache.c linux/fs/dcache.c --- linux-2.5.2-pre11/fs/dcache.c Mon Dec 10 14:13:25 2001 +++ linux/fs/dcache.c Mon Jan 14 18:28:31 2002 @@ -1262,7 +1262,7 @@ panic("Cannot create buffer head SLAB cache"); names_cachep = kmem_cache_create("names_cache", - PATH_MAX + 1, 0, + PATH_MAX, 0, SLAB_HWCACHE_ALIGN, NULL, NULL); if (!names_cachep) panic("Cannot create names SLAB cache"); diff -urN linux-2.5.2-pre11/fs/devfs/base.c linux/fs/devfs/base.c --- linux-2.5.2-pre11/fs/devfs/base.c Mon Jan 14 18:28:24 2002 +++ linux/fs/devfs/base.c Mon Jan 14 18:28:31 2002 @@ -601,6 +601,9 @@ Only return old entry in if a directory. Defined macros for error and debug messages. v1.8 + 20020113 Richard Gooch + Fixed (rare, old) race in . + v1.9 */ #include #include @@ -633,7 +636,7 @@ #include #include -#define DEVFS_VERSION "1.8 (20011226)" +#define DEVFS_VERSION "1.9 (20020113)" #define DEVFS_NAME "devfs" @@ -894,8 +897,8 @@ { devfs_dealloc_devnum ( S_ISCHR (de->mode) ? DEVFS_SPECIAL_CHR : DEVFS_SPECIAL_BLK, - mk_kdev(de->u.fcb.u.device.major, - de->u.fcb.u.device.minor) ); + mk_kdev (de->u.fcb.u.device.major, + de->u.fcb.u.device.minor) ); } WRITE_ENTRY_MAGIC (de, 0); #ifdef CONFIG_DEVFS_DEBUG @@ -1552,7 +1555,7 @@ if ( ( S_ISCHR (mode) || S_ISBLK (mode) ) && (flags & DEVFS_FL_AUTO_DEVNUM) ) { - if ( kdev_none( devnum = devfs_alloc_devnum (devtype) ) ) + if ( kdev_none ( devnum = devfs_alloc_devnum (devtype) ) ) { PRINTK ("(%s): exhausted %s device numbers\n", name, S_ISCHR (mode) ? "char" : "block"); @@ -1564,14 +1567,14 @@ if ( ( de = _devfs_prepare_leaf (&dir, name, mode) ) == NULL ) { PRINTK ("(%s): could not prepare leaf\n", name); - if (!kdev_none(devnum)) devfs_dealloc_devnum (devtype, devnum); + if ( !kdev_none (devnum) ) devfs_dealloc_devnum (devtype, devnum); return NULL; } if ( S_ISCHR (mode) || S_ISBLK (mode) ) { de->u.fcb.u.device.major = major; de->u.fcb.u.device.minor = minor; - de->u.fcb.autogen = kdev_none(devnum) ? FALSE : TRUE; + de->u.fcb.autogen = kdev_none (devnum) ? FALSE : TRUE; } else if ( !S_ISREG (mode) ) { @@ -1601,7 +1604,7 @@ { PRINTK ("(%s): could not append to parent, err: %d\n", name, err); devfs_put (dir); - if (!kdev_none(devnum)) devfs_dealloc_devnum (devtype, devnum); + if ( !kdev_none (devnum) ) devfs_dealloc_devnum (devtype, devnum); return NULL; } DPRINTK (DEBUG_REGISTER, "(%s): de: %p dir: %p \"%s\" pp: %p\n", @@ -2378,7 +2381,7 @@ * @buf: A working area that will be used. This must not go out of scope * until devfsd is idle again. * - * Returns 0 on success, else a negative error code. + * Returns 0 on success (event was queued), else a negative error code. */ static int try_modload (struct devfs_entry *parent, struct fs_info *fs_info, @@ -2397,7 +2400,7 @@ if ( !devfsd_notify_de (buf, DEVFSD_NOTIFY_LOOKUP, 0, current->euid, current->egid, fs_info, 0) ) return -ENOENT; - /* Possible success */ + /* Possible success: event has been queued */ return 0; } /* End Function try_modload */ @@ -2413,7 +2416,7 @@ { int tmp; int retval = 0; - kdev_t dev = mk_kdev(de->u.fcb.u.device.major, de->u.fcb.u.device.minor); + kdev_t dev = mk_kdev (de->u.fcb.u.device.major, de->u.fcb.u.device.minor); struct block_device_operations *bdops; extern int warn_no_part; @@ -2599,15 +2602,15 @@ inode->i_rdev = NODEV; if ( S_ISCHR (de->mode) ) { - inode->i_rdev = mk_kdev(de->u.fcb.u.device.major, - de->u.fcb.u.device.minor); + inode->i_rdev = mk_kdev (de->u.fcb.u.device.major, + de->u.fcb.u.device.minor); inode->i_cdev = cdget ( kdev_t_to_nr (inode->i_rdev) ); is_fcb = TRUE; } else if ( S_ISBLK (de->mode) ) { - inode->i_rdev = mk_kdev(de->u.fcb.u.device.major, - de->u.fcb.u.device.minor); + inode->i_rdev = mk_kdev (de->u.fcb.u.device.major, + de->u.fcb.u.device.minor); if (bd_acquire (inode) == 0) { if (!inode->i_bdev->bd_op && de->u.fcb.ops) @@ -2861,34 +2864,55 @@ return 0; } /* End Function devfs_d_delete */ +struct devfs_lookup_struct +{ + devfs_handle_t de; + wait_queue_head_t wait_queue; +}; + static int devfs_d_revalidate_wait (struct dentry *dentry, int flags) { struct inode *dir = dentry->d_parent->d_inode; struct fs_info *fs_info = dir->i_sb->u.generic_sbp; + devfs_handle_t parent = get_devfs_entry_from_vfs_inode (dir); + struct devfs_lookup_struct *lookup_info = dentry->d_fsdata; + DECLARE_WAITQUEUE (wait, current); if ( !dentry->d_inode && is_devfsd_or_child (fs_info) ) { - devfs_handle_t de; - devfs_handle_t parent = get_devfs_entry_from_vfs_inode (dir); + devfs_handle_t de = lookup_info->de; struct inode *inode; - DPRINTK (DEBUG_I_LOOKUP, "(%s): dentry: %p by: \"%s\"\n", - dentry->d_name.name, dentry, current->comm); - read_lock (&parent->u.dir.lock); - de = _devfs_search_dir (parent, dentry->d_name.name, - dentry->d_name.len); - read_unlock (&parent->u.dir.lock); - if (de == NULL) return 1; + DPRINTK (DEBUG_I_LOOKUP, "(%s): dentry: %p de: %p by: \"%s\"\n", + dentry->d_name.name, dentry, de, current->comm); + if (de == NULL) + { + read_lock (&parent->u.dir.lock); + de = _devfs_search_dir (parent, dentry->d_name.name, + dentry->d_name.len); + read_unlock (&parent->u.dir.lock); + if (de == NULL) return 1; + lookup_info->de = de; + } /* Create an inode, now that the driver information is available */ inode = _devfs_get_vfs_inode (dir->i_sb, de, dentry); - devfs_put (de); if (!inode) return 1; - DPRINTK (DEBUG_I_LOOKUP, "(%s): new VFS inode(%u): %p de: %p\n", - de->name, de->inode.ino, inode, de); + DPRINTK (DEBUG_I_LOOKUP, + "(%s): new VFS inode(%u): %p de: %p by: \"%s\"\n", + de->name, de->inode.ino, inode, de, current->comm); d_instantiate (dentry, inode); return 1; } - if ( wait_for_devfsd_finished (fs_info) ) dentry->d_op = &devfs_dops; + if (lookup_info == NULL) return 1; /* Early termination */ + read_lock (&parent->u.dir.lock); + if (dentry->d_fsdata) + { + add_wait_queue (&lookup_info->wait_queue, &wait); + current->state = TASK_UNINTERRUPTIBLE; + read_unlock (&parent->u.dir.lock); + schedule (); + } + else read_unlock (&parent->u.dir.lock); return 1; } /* End Function devfs_d_revalidate_wait */ @@ -2897,9 +2921,12 @@ static struct dentry *devfs_lookup (struct inode *dir, struct dentry *dentry) { + struct devfs_entry tmp; /* Must stay in scope until devfsd idle again */ + struct devfs_lookup_struct lookup_info; struct fs_info *fs_info = dir->i_sb->u.generic_sbp; struct devfs_entry *parent, *de; struct inode *inode; + struct dentry *retval = NULL; /* Set up the dentry operations before anything else, to ensure cleaning up on any error */ @@ -2921,60 +2948,61 @@ dentry->d_name.len); read_unlock (&parent->u.dir.lock); } + lookup_info.de = de; + init_waitqueue_head (&lookup_info.wait_queue); + dentry->d_fsdata = &lookup_info; if (de == NULL) { /* Try with devfsd. For any kind of failure, leave a negative dentry so someone else can deal with it (in the case where the sysadmin does a mknod()). It's important to do this before hashing the dentry, so that the devfsd queue is filled before revalidates can start */ - struct devfs_entry tmp; - if (try_modload (parent, fs_info, dentry->d_name.name, dentry->d_name.len, &tmp) < 0) - { + { /* Lookup event was not queued to devfsd */ d_add (dentry, NULL); return NULL; } - /* devfsd claimed success */ - dentry->d_op = &devfs_wait_dops; - d_add (dentry, NULL); /* Open the floodgates */ - /* Unlock directory semaphore, which will release any waiters. They - will get the hashed dentry, and may be forced to wait for - revalidation */ - up (&dir->i_sem); - devfs_d_revalidate_wait (dentry, 0); /* I might have to wait too */ - down (&dir->i_sem); /* Grab it again because them's the rules */ - /* If someone else has been so kind as to make the inode, we go home - early */ - if (dentry->d_inode) return NULL; + } + dentry->d_op = &devfs_wait_dops; + d_add (dentry, NULL); /* Open the floodgates */ + /* Unlock directory semaphore, which will release any waiters. They + will get the hashed dentry, and may be forced to wait for + revalidation */ + up (&dir->i_sem); + wait_for_devfsd_finished (fs_info); /* If I'm not devfsd, must wait */ + down (&dir->i_sem); /* Grab it again because them's the rules */ + de = lookup_info.de; + /* If someone else has been so kind as to make the inode, we go home + early */ + if (dentry->d_inode) goto out; + if (de == NULL) + { read_lock (&parent->u.dir.lock); de = _devfs_search_dir (parent, dentry->d_name.name, dentry->d_name.len); read_unlock (&parent->u.dir.lock); - if (de == NULL) return NULL; + if (de == NULL) goto out; /* OK, there's an entry now, but no VFS inode yet */ } - else - { - dentry->d_op = &devfs_wait_dops; - d_add (dentry, NULL); /* Open the floodgates */ - } /* Create an inode, now that the driver information is available */ inode = _devfs_get_vfs_inode (dir->i_sb, de, dentry); - devfs_put (de); - if (!inode) return ERR_PTR (-ENOMEM); - DPRINTK (DEBUG_I_LOOKUP, "(%s): new VFS inode(%u): %p de: %p\n", - de->name, de->inode.ino, inode, de); - d_instantiate (dentry, inode); - if (dentry->d_op == &devfs_wait_dops) - { /* Unlock directory semaphore, which will release any waiters. They - will get the hashed dentry, and may be forced to wait for - revalidation */ - up (&dir->i_sem); - devfs_d_revalidate_wait (dentry, 0); /* I might have to wait too */ - down (&dir->i_sem); /* Grab it again because them's the rules */ + if (!inode) + { + retval = ERR_PTR (-ENOMEM); + goto out; } - return NULL; + DPRINTK (DEBUG_I_LOOKUP, "(%s): new VFS inode(%u): %p de: %p by: \"%s\"\n", + de->name, de->inode.ino, inode, de, current->comm); + d_instantiate (dentry, inode); +out: + dentry->d_op = &devfs_dops; + dentry->d_fsdata = NULL; + write_lock (&parent->u.dir.lock); + wake_up (&lookup_info.wait_queue); + write_unlock (&parent->u.dir.lock); + devfs_put (de); + return retval; } /* End Function devfs_lookup */ static int devfs_unlink (struct inode *dir, struct dentry *dentry) diff -urN linux-2.5.2-pre11/fs/devpts/root.c linux/fs/devpts/root.c --- linux-2.5.2-pre11/fs/devpts/root.c Fri Aug 11 14:29:02 2000 +++ linux/fs/devpts/root.c Mon Jan 14 18:28:31 2002 @@ -101,7 +101,6 @@ int i; const char *p; - dentry->d_inode = NULL; /* Assume failure */ dentry->d_op = &devpts_dentry_operations; if ( dentry->d_name.len == 1 && dentry->d_name.name[0] == '0' ) { @@ -127,11 +126,10 @@ if ( entry >= sbi->max_ptys ) return NULL; - dentry->d_inode = sbi->inodes[entry]; - if ( dentry->d_inode ) - atomic_inc(&dentry->d_inode->i_count); + if ( sbi->inodes[entry] ) + atomic_inc(&sbi->inodes[entry]->i_count); - d_add(dentry, dentry->d_inode); + d_add(dentry, sbi->inodes[entry]); return NULL; } diff -urN linux-2.5.2-pre11/fs/driverfs/inode.c linux/fs/driverfs/inode.c --- linux-2.5.2-pre11/fs/driverfs/inode.c Thu Nov 29 16:55:11 2001 +++ linux/fs/driverfs/inode.c Mon Jan 14 18:28:31 2002 @@ -374,7 +374,7 @@ entry = (struct driver_file_entry *)dentry->d_fsdata; if (entry) - kfree(dentry); + kfree(entry); return 0; } diff -urN linux-2.5.2-pre11/fs/fat/cache.c linux/fs/fat/cache.c --- linux-2.5.2-pre11/fs/fat/cache.c Mon Jan 14 18:28:24 2002 +++ linux/fs/fat/cache.c Mon Jan 14 18:28:31 2002 @@ -189,7 +189,7 @@ for (walk = fat_cache; walk; walk = walk->next) { if (walk->sb) - printk("<%s,%d>(%d,%d) ", walk->sb->s_dev->s_id, + printk("<%s,%d>(%d,%d) ", walk->sb->s_id, walk->start_cluster, walk->file_cluster, walk->disk_cluster); else printk("-- "); diff -urN linux-2.5.2-pre11/fs/fat/inode.c linux/fs/fat/inode.c --- linux-2.5.2-pre11/fs/fat/inode.c Mon Jan 14 18:28:24 2002 +++ linux/fs/fat/inode.c Mon Jan 14 18:28:31 2002 @@ -407,7 +407,7 @@ } inode->i_blksize = 1 << sbi->cluster_bits; inode->i_blocks = ((inode->i_size + inode->i_blksize - 1) - & ~(inode->i_blksize - 1)) / 512; + & ~(inode->i_blksize - 1)) >> 9; MSDOS_I(inode)->i_logstart = 0; MSDOS_I(inode)->mmu_private = inode->i_size; @@ -949,7 +949,7 @@ /* this is as close to the truth as we can get ... */ inode->i_blksize = 1 << sbi->cluster_bits; inode->i_blocks = ((inode->i_size + inode->i_blksize - 1) - & ~(inode->i_blksize - 1)) / 512; + & ~(inode->i_blksize - 1)) >> 9; inode->i_mtime = inode->i_atime = date_dos2unix(CF_LE_W(de->time),CF_LE_W(de->date)); inode->i_ctime = diff -urN linux-2.5.2-pre11/fs/inode.c linux/fs/inode.c --- linux-2.5.2-pre11/fs/inode.c Mon Jan 14 18:28:24 2002 +++ linux/fs/inode.c Mon Jan 14 18:28:31 2002 @@ -1082,7 +1082,7 @@ } inodes_stat.nr_unused++; spin_unlock(&inode_lock); - if (!sb || sb->s_flags & MS_ACTIVE) + if (!sb || (sb->s_flags & MS_ACTIVE)) return; write_inode_now(inode, 1); spin_lock(&inode_lock); diff -urN linux-2.5.2-pre11/fs/intermezzo/cache.c linux/fs/intermezzo/cache.c --- linux-2.5.2-pre11/fs/intermezzo/cache.c Sun Nov 11 10:20:21 2001 +++ linux/fs/intermezzo/cache.c Mon Jan 14 18:28:31 2002 @@ -46,7 +46,7 @@ static inline int presto_cache_hash(kdev_t dev) { - return (CACHES_MASK) & ((0x000F & (dev)) + ((0x0F00 & (dev)) >>8)); + return (CACHES_MASK) & ((0x000F & (kdev_val(dev))) + ((0x0F00 & (kdev_val(dev))) >>8)); } inline void presto_cache_add(struct presto_cache *cache, kdev_t dev) @@ -73,7 +73,7 @@ lh = tmp = &(presto_caches[presto_cache_hash(dev)]); while ( (tmp = lh->next) != lh ) { cache = list_entry(tmp, struct presto_cache, cache_chain); - if ( cache->cache_dev == dev ) { + if ( kdev_same(cache->cache_dev, dev) ) { return cache; } } @@ -90,7 +90,7 @@ cache = presto_find_cache(inode->i_dev); if ( !cache ) { printk("WARNING: no presto cache for dev %x, ino %ld\n", - inode->i_dev, inode->i_ino); + kdev_val(inode->i_dev), inode->i_ino); EXIT; return NULL; } @@ -174,7 +174,7 @@ cache = presto_get_cache(inode); if ( !cache ) return 0; - return (inode->i_dev == cache->cache_dev); + return (kdev_same(inode->i_dev, cache->cache_dev)); } /* setup a cache structure when we need one */ diff -urN linux-2.5.2-pre11/fs/intermezzo/presto.c linux/fs/intermezzo/presto.c --- linux-2.5.2-pre11/fs/intermezzo/presto.c Mon Jan 14 18:28:24 2002 +++ linux/fs/intermezzo/presto.c Mon Jan 14 18:28:31 2002 @@ -71,8 +71,8 @@ cache = presto_get_cache(inode); CDEBUG(D_PSDEV, "\n"); if ( !cache ) { - printk("PRESTO: BAD: cannot find cache for dev %d, ino %ld\n", - inode->i_dev, inode->i_ino); + printk("PRESTO: BAD: cannot find cache for dev %x, ino %ld\n", + kdev_val(inode->i_dev), inode->i_ino); EXIT; return -1; } diff -urN linux-2.5.2-pre11/fs/intermezzo/psdev.c linux/fs/intermezzo/psdev.c --- linux-2.5.2-pre11/fs/intermezzo/psdev.c Mon Jan 14 18:28:24 2002 +++ linux/fs/intermezzo/psdev.c Mon Jan 14 18:28:31 2002 @@ -43,14 +43,15 @@ #include #include #include +#include #include #include #include -#include #include #include #include #include +#include #include #include @@ -290,7 +291,7 @@ } len = readmount.io_len; - minor = MINOR(dev); + minor = minor(dev); PRESTO_ALLOC(tmp, char *, len); if (!tmp) { EXIT; @@ -627,7 +628,7 @@ EXIT; return error; } - minor = MINOR(dev); + minor = minor(dev); if (cmd == PRESTO_SETOPT) error = dosetopt(minor, &kopt); diff -urN linux-2.5.2-pre11/fs/intermezzo/sysctl.c linux/fs/intermezzo/sysctl.c --- linux-2.5.2-pre11/fs/intermezzo/sysctl.c Mon Jan 14 18:28:24 2002 +++ linux/fs/intermezzo/sysctl.c Mon Jan 14 18:28:31 2002 @@ -161,15 +161,17 @@ * current presto cache. */ int errorval = upc_comms[minor].uc_errorval; + kdev_t kdev = mk_kdev(MAJOR(-errorval), MINOR(-errorval)); if (errorval < 0) { if (newval == 0) - set_device_ro(-errorval, 0); + set_device_ro(kdev, 0); else printk("device %s already read only\n", - kdevname(-errorval)); + kdevname(kdev)); } else { + kdev = mk_kdev(MAJOR(-newval), MINOR(-newval)); if (newval < 0) - set_device_ro(-newval, 1); + set_device_ro(kdev, 1); upc_comms[minor].uc_errorval = newval; CDEBUG(D_PSDEV, "setting errorval to %d\n", newval); } @@ -224,9 +226,10 @@ #ifdef PSDEV_DEBUG case PSDEV_ERRORVAL: { int errorval = upc_comms[minor].uc_errorval; - if (errorval < 0 && is_read_only(-errorval)) + kdev_t kdev = mk_kdev(MAJOR(-errorval), MINOR(-errorval)); + if (errorval < 0 && is_read_only(kdev)) printk(KERN_INFO "device %s has been set read-only\n", - kdevname(-errorval)); + kdevname(kdev)); opt->optval = upc_comms[minor].uc_errorval; break; } diff -urN linux-2.5.2-pre11/fs/intermezzo/vfs.c linux/fs/intermezzo/vfs.c --- linux-2.5.2-pre11/fs/intermezzo/vfs.c Tue Nov 13 09:20:56 2001 +++ linux/fs/intermezzo/vfs.c Mon Jan 14 18:28:31 2002 @@ -136,7 +136,7 @@ if (errorval && errorval == (long)value && !is_read_only(dev)) { CDEBUG(D_SUPER, "setting device %s read only\n", kdevname(dev)); BLKDEV_FAIL(dev, 1); - upc_comms[minor].uc_errorval = -dev; + upc_comms[minor].uc_errorval = -kdev_val(dev); } } #else @@ -602,7 +602,7 @@ goto exit_lock; error = -EXDEV; - if (dir->d_inode->i_dev != inode->i_dev) + if (!kdev_same(dir->d_inode->i_dev, inode->i_dev)) goto exit_lock; /* @@ -1609,7 +1609,7 @@ if (error) return error; - if (new_dir->i_dev != old_dir->i_dev) + if (!kdev_same(new_dir->i_dev, old_dir->i_dev)) return -EXDEV; if (!new_dentry->d_inode) @@ -1690,7 +1690,7 @@ if (error) return error; - if (new_dir->i_dev != old_dir->i_dev) + if (!kdev_same(new_dir->i_dev, old_dir->i_dev)) return -EXDEV; if (!new_dentry->d_inode) diff -urN linux-2.5.2-pre11/fs/jbd/journal.c linux/fs/jbd/journal.c --- linux-2.5.2-pre11/fs/jbd/journal.c Mon Jan 14 18:28:24 2002 +++ linux/fs/jbd/journal.c Mon Jan 14 18:28:31 2002 @@ -475,6 +475,7 @@ new_jh->b_transaction = NULL; new_bh->b_size = jh2bh(jh_in)->b_size; + new_bh->b_bdev = transaction->t_journal->j_dev; new_bh->b_dev = to_kdev_t(transaction->t_journal->j_dev->bd_dev); new_bh->b_blocknr = blocknr; new_bh->b_state |= (1 << BH_Mapped) | (1 << BH_Dirty); diff -urN linux-2.5.2-pre11/fs/jbd/revoke.c linux/fs/jbd/revoke.c --- linux-2.5.2-pre11/fs/jbd/revoke.c Mon Jan 14 18:28:24 2002 +++ linux/fs/jbd/revoke.c Mon Jan 14 18:28:31 2002 @@ -278,7 +278,7 @@ { struct buffer_head *bh = NULL; journal_t *journal; - kdev_t dev; + struct block_device *bdev; int err; if (bh_in) @@ -290,11 +290,11 @@ return -EINVAL; } - dev = to_kdev_t(journal->j_fs_dev->bd_dev); + bdev = journal->j_fs_dev; bh = bh_in; if (!bh) { - bh = get_hash_table(dev, blocknr, journal->j_blocksize); + bh = __get_hash_table(bdev, blocknr, journal->j_blocksize); if (bh) BUFFER_TRACE(bh, "found on hash"); } @@ -304,7 +304,7 @@ /* If there is a different buffer_head lying around in * memory anywhere... */ - bh2 = get_hash_table(dev, blocknr, journal->j_blocksize); + bh2 = __get_hash_table(bdev, blocknr, journal->j_blocksize); if (bh2) { /* ... and it has RevokeValid status... */ if ((bh2 != bh) && @@ -408,7 +408,7 @@ * state machine will get very upset later on. */ if (need_cancel && !bh->b_pprev) { struct buffer_head *bh2; - bh2 = get_hash_table(bh->b_dev, bh->b_blocknr, bh->b_size); + bh2 = __get_hash_table(bh->b_bdev, bh->b_blocknr, bh->b_size); if (bh2) { clear_bit(BH_Revoked, &bh2->b_state); __brelse(bh2); diff -urN linux-2.5.2-pre11/fs/jbd/transaction.c linux/fs/jbd/transaction.c --- linux-2.5.2-pre11/fs/jbd/transaction.c Mon Jan 14 18:28:24 2002 +++ linux/fs/jbd/transaction.c Mon Jan 14 18:28:31 2002 @@ -1864,6 +1864,7 @@ clear_bit(BH_Mapped, &bh->b_state); clear_bit(BH_Req, &bh->b_state); clear_bit(BH_New, &bh->b_state); + bh->b_bdev = NULL; return may_free; } diff -urN linux-2.5.2-pre11/fs/jffs2/Makefile linux/fs/jffs2/Makefile --- linux-2.5.2-pre11/fs/jffs2/Makefile Thu Oct 4 15:13:18 2001 +++ linux/fs/jffs2/Makefile Mon Jan 14 18:28:31 2002 @@ -12,7 +12,7 @@ COMPR_OBJS := compr.o compr_rubin.o compr_rtime.o pushpull.o \ compr_zlib.o zlib.o -JFFS2_OBJS := crc32.o dir.o file.o ioctl.o nodelist.o malloc.o \ +JFFS2_OBJS := dir.o file.o ioctl.o nodelist.o malloc.o \ read.o nodemgmt.o readinode.o super.o write.o scan.o gc.o \ symlink.o build.o erase.o background.o diff -urN linux-2.5.2-pre11/fs/jffs2/crc32.c linux/fs/jffs2/crc32.c --- linux-2.5.2-pre11/fs/jffs2/crc32.c Fri Sep 14 14:04:07 2001 +++ linux/fs/jffs2/crc32.c Wed Dec 31 16:00:00 1969 @@ -1,97 +0,0 @@ -/* - * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or - * code or tables extracted from it, as desired without restriction. - * - * First, the polynomial itself and its table of feedback terms. The - * polynomial is - * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 - * - * Note that we take it "backwards" and put the highest-order term in - * the lowest-order bit. The X^32 term is "implied"; the LSB is the - * X^31 term, etc. The X^0 term (usually shown as "+1") results in - * the MSB being 1 - * - * Note that the usual hardware shift register implementation, which - * is what we're using (we're merely optimizing it by doing eight-bit - * chunks at a time) shifts bits into the lowest-order term. In our - * implementation, that means shifting towards the right. Why do we - * do it this way? Because the calculated CRC must be transmitted in - * order from highest-order term to lowest-order term. UARTs transmit - * characters in order from LSB to MSB. By storing the CRC this way - * we hand it to the UART in the order low-byte to high-byte; the UART - * sends each low-bit to hight-bit; and the result is transmission bit - * by bit from highest- to lowest-order term without requiring any bit - * shuffling on our part. Reception works similarly - * - * The feedback terms table consists of 256, 32-bit entries. Notes - * - * The table can be generated at runtime if desired; code to do so - * is shown later. It might not be obvious, but the feedback - * terms simply represent the results of eight shift/xor opera - * tions for all combinations of data and CRC register values - * - * The values must be right-shifted by eight bits by the "updcrc - * logic; the shift must be unsigned (bring in zeroes). On some - * hardware you could probably optimize the shift in assembler by - * using byte-swap instructions - * polynomial $edb88320 - */ - -/* $Id: crc32.c,v 1.3 2001/02/07 16:45:32 dwmw2 Exp $ */ - -#include "crc32.h" - -const __u32 crc32_table[256] = { - 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, - 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, - 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, - 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, - 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, - 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, - 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, - 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, - 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, - 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, - 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, - 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, - 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, - 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, - 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, - 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, - 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, - 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, - 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, - 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, - 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, - 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, - 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, - 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, - 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, - 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, - 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, - 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, - 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, - 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, - 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, - 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, - 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, - 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, - 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, - 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, - 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, - 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, - 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, - 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, - 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, - 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, - 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, - 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, - 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, - 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, - 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, - 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, - 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, - 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, - 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, - 0x2d02ef8dL -}; diff -urN linux-2.5.2-pre11/fs/jffs2/crc32.h linux/fs/jffs2/crc32.h --- linux-2.5.2-pre11/fs/jffs2/crc32.h Fri Sep 14 14:04:07 2001 +++ linux/fs/jffs2/crc32.h Wed Dec 31 16:00:00 1969 @@ -1,21 +0,0 @@ -#ifndef CRC32_H -#define CRC32_H - -/* $Id: crc32.h,v 1.3 2001/02/26 14:44:37 dwmw2 Exp $ */ - -#include - -extern const __u32 crc32_table[256]; - -/* Return a 32-bit CRC of the contents of the buffer. */ - -static inline __u32 -crc32(__u32 val, const void *ss, int len) -{ - const unsigned char *s = ss; - while (--len >= 0) - val = crc32_table[(val ^ *s++) & 0xff] ^ (val >> 8); - return val; -} - -#endif diff -urN linux-2.5.2-pre11/fs/jffs2/dir.c linux/fs/jffs2/dir.c --- linux-2.5.2-pre11/fs/jffs2/dir.c Mon Jan 14 18:28:24 2002 +++ linux/fs/jffs2/dir.c Mon Jan 14 18:28:31 2002 @@ -38,11 +38,11 @@ #include #include #include +#include #include #include #include #include "nodelist.h" -#include "crc32.h" static int jffs2_readdir (struct file *, void *, filldir_t); diff -urN linux-2.5.2-pre11/fs/jffs2/erase.c linux/fs/jffs2/erase.c --- linux-2.5.2-pre11/fs/jffs2/erase.c Thu Oct 4 15:13:18 2001 +++ linux/fs/jffs2/erase.c Mon Jan 14 18:28:31 2002 @@ -39,8 +39,8 @@ #include #include #include +#include #include "nodelist.h" -#include "crc32.h" struct erase_priv_struct { struct jffs2_eraseblock *jeb; diff -urN linux-2.5.2-pre11/fs/jffs2/file.c linux/fs/jffs2/file.c --- linux-2.5.2-pre11/fs/jffs2/file.c Mon Jan 14 18:28:24 2002 +++ linux/fs/jffs2/file.c Mon Jan 14 18:28:31 2002 @@ -40,9 +40,9 @@ #include #include #include +#include #include #include "nodelist.h" -#include "crc32.h" extern int generic_file_open(struct inode *, struct file *) __attribute__((weak)); extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin) __attribute__((weak)); diff -urN linux-2.5.2-pre11/fs/jffs2/gc.c linux/fs/jffs2/gc.c --- linux-2.5.2-pre11/fs/jffs2/gc.c Mon Jan 14 18:28:24 2002 +++ linux/fs/jffs2/gc.c Mon Jan 14 18:28:31 2002 @@ -42,8 +42,8 @@ #include #include #include +#include #include "nodelist.h" -#include "crc32.h" static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct inode *inode, struct jffs2_full_dnode *fd); diff -urN linux-2.5.2-pre11/fs/jffs2/read.c linux/fs/jffs2/read.c --- linux-2.5.2-pre11/fs/jffs2/read.c Fri Sep 14 14:04:07 2001 +++ linux/fs/jffs2/read.c Mon Jan 14 18:28:31 2002 @@ -37,10 +37,10 @@ #include #include +#include #include #include #include "nodelist.h" -#include "crc32.h" int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_full_dnode *fd, unsigned char *buf, int ofs, int len) { diff -urN linux-2.5.2-pre11/fs/jffs2/readinode.c linux/fs/jffs2/readinode.c --- linux-2.5.2-pre11/fs/jffs2/readinode.c Fri Sep 14 14:04:07 2001 +++ linux/fs/jffs2/readinode.c Mon Jan 14 18:28:31 2002 @@ -41,10 +41,10 @@ #include #include #include +#include #include #include #include "nodelist.h" -#include "crc32.h" D1(void jffs2_print_frag_list(struct jffs2_inode_info *f) diff -urN linux-2.5.2-pre11/fs/jffs2/scan.c linux/fs/jffs2/scan.c --- linux-2.5.2-pre11/fs/jffs2/scan.c Thu Oct 4 15:13:18 2001 +++ linux/fs/jffs2/scan.c Mon Jan 14 18:28:31 2002 @@ -39,8 +39,8 @@ #include #include #include +#include #include "nodelist.h" -#include "crc32.h" #define DIRTY_SPACE(x) do { typeof(x) _x = (x); \ diff -urN linux-2.5.2-pre11/fs/jffs2/write.c linux/fs/jffs2/write.c --- linux-2.5.2-pre11/fs/jffs2/write.c Mon Jan 14 18:28:24 2002 +++ linux/fs/jffs2/write.c Mon Jan 14 18:28:31 2002 @@ -37,10 +37,10 @@ #include #include +#include #include #include #include "nodelist.h" -#include "crc32.h" /* jffs2_new_inode: allocate a new inode and inocache, add it to the hash, fill in the raw_inode while you're at it. */ diff -urN linux-2.5.2-pre11/fs/namei.c linux/fs/namei.c --- linux-2.5.2-pre11/fs/namei.c Mon Jan 14 18:28:24 2002 +++ linux/fs/namei.c Mon Jan 14 18:28:31 2002 @@ -99,16 +99,17 @@ * kernel data space before using them.. * * POSIX.1 2.4: an empty pathname is invalid (ENOENT). + * PATH_MAX includes the nul terminator --RR. */ static inline int do_getname(const char *filename, char *page) { int retval; - unsigned long len = PATH_MAX + 1; + unsigned long len = PATH_MAX; if ((unsigned long) filename >= TASK_SIZE) { if (!segment_eq(get_fs(), KERNEL_DS)) return -EFAULT; - } else if (TASK_SIZE - (unsigned long) filename < PATH_MAX + 1) + } else if (TASK_SIZE - (unsigned long) filename < PATH_MAX) len = TASK_SIZE - (unsigned long) filename; retval = strncpy_from_user((char *)page, filename, len); diff -urN linux-2.5.2-pre11/fs/openpromfs/inode.c linux/fs/openpromfs/inode.c --- linux-2.5.2-pre11/fs/openpromfs/inode.c Sun Nov 11 10:13:25 2001 +++ linux/fs/openpromfs/inode.c Mon Jan 14 18:28:31 2002 @@ -1,4 +1,4 @@ -/* $Id: inode.c,v 1.14 2001/02/13 01:17:17 davem Exp $ +/* $Id: inode.c,v 1.15 2001/11/12 09:43:39 davem Exp $ * openpromfs.c: /proc/openprom handling routines * * Copyright (C) 1996-1999 Jakub Jelinek (jakub@redhat.com) diff -urN linux-2.5.2-pre11/fs/partitions/msdos.c linux/fs/partitions/msdos.c --- linux-2.5.2-pre11/fs/partitions/msdos.c Thu Oct 11 08:07:07 2001 +++ linux/fs/partitions/msdos.c Mon Jan 14 18:28:31 2002 @@ -166,7 +166,7 @@ add_gd_partition(hd, *current_minor, next, size); #if CONFIG_BLK_DEV_MD if (SYS_IND(p) == LINUX_RAID_PARTITION) { - md_autodetect_dev(MKDEV(hd->major,*current_minor)); + md_autodetect_dev(mk_kdev(hd->major,*current_minor)); } #endif @@ -580,7 +580,7 @@ NR_SECTS(p)*sector_size); #if CONFIG_BLK_DEV_MD if (SYS_IND(p) == LINUX_RAID_PARTITION) { - md_autodetect_dev(MKDEV(hd->major,minor)); + md_autodetect_dev(mk_kdev(hd->major,minor)); } #endif if (is_extended_partition(p)) { diff -urN linux-2.5.2-pre11/fs/reiserfs/bitmap.c linux/fs/reiserfs/bitmap.c --- linux-2.5.2-pre11/fs/reiserfs/bitmap.c Mon Jan 14 18:28:24 2002 +++ linux/fs/reiserfs/bitmap.c Mon Jan 14 18:28:31 2002 @@ -168,7 +168,7 @@ block_to_try = (i * (s->s_blocksize << 3)) + j; /* the block is not in the journal, we can proceed */ - if (!(reiserfs_in_journal(s, s->s_dev, block_to_try, s->s_blocksize, for_unformatted, &next_block_to_try))) { + if (!(reiserfs_in_journal(s, block_to_try, for_unformatted, &next_block_to_try))) { *bmap_nr = i; *offset = j; return 1; diff -urN linux-2.5.2-pre11/fs/reiserfs/journal.c linux/fs/reiserfs/journal.c --- linux-2.5.2-pre11/fs/reiserfs/journal.c Mon Jan 14 18:28:24 2002 +++ linux/fs/reiserfs/journal.c Mon Jan 14 18:28:31 2002 @@ -414,12 +414,15 @@ } /* return a cnode with same dev, block number and size in table, or null if not found */ -static inline struct reiserfs_journal_cnode *get_journal_hash_dev(struct reiserfs_journal_cnode **table, - kdev_t dev,long bl,int size) { +static inline struct reiserfs_journal_cnode * +get_journal_hash_dev(struct super_block *sb, + struct reiserfs_journal_cnode **table, + long bl) +{ struct reiserfs_journal_cnode *cn ; - cn = journal_hash(table, dev, bl) ; + cn = journal_hash(table, sb, bl) ; while(cn) { - if ((cn->blocknr == bl) && (kdev_same(cn->dev, dev))) + if (cn->blocknr == bl && cn->sb == sb) return cn ; cn = cn->hnext ; } @@ -430,7 +433,7 @@ static inline struct reiserfs_journal_cnode *get_journal_hash(struct super_block *p_s_sb, struct buffer_head *bh) { struct reiserfs_journal_cnode *cn ; if (bh) { - cn = get_journal_hash_dev(SB_JOURNAL(p_s_sb)->j_hash_table, bh->b_dev, bh->b_blocknr, bh->b_size) ; + cn = get_journal_hash_dev(p_s_sb, SB_JOURNAL(p_s_sb)->j_hash_table, bh->b_blocknr); } else { return (struct reiserfs_journal_cnode *)0 ; @@ -502,8 +505,8 @@ ** reject it on the next call to reiserfs_in_journal ** */ -int reiserfs_in_journal(struct super_block *p_s_sb, kdev_t dev, - unsigned long bl, int size, int search_all, +int reiserfs_in_journal(struct super_block *p_s_sb, + unsigned long bl, int search_all, unsigned long *next_zero_bit) { struct reiserfs_journal_cnode *cn ; struct reiserfs_list_bitmap *jb ; @@ -540,12 +543,12 @@ } /* is it in any old transactions? */ - if (search_all && (cn = get_journal_hash_dev(SB_JOURNAL(p_s_sb)->j_list_hash_table, dev,bl,size))) { + if (search_all && (cn = get_journal_hash_dev(p_s_sb, SB_JOURNAL(p_s_sb)->j_list_hash_table, bl))) { return 1; } /* is it in the current transaction. This should never happen */ - if ((cn = get_journal_hash_dev(SB_JOURNAL(p_s_sb)->j_hash_table, dev,bl,size))) { + if ((cn = get_journal_hash_dev(p_s_sb, SB_JOURNAL(p_s_sb)->j_hash_table, bl))) { return 1; } @@ -559,13 +562,13 @@ inline void insert_journal_hash(struct reiserfs_journal_cnode **table, struct reiserfs_journal_cnode *cn) { struct reiserfs_journal_cnode *cn_orig ; - cn_orig = journal_hash(table, cn->dev, cn->blocknr) ; + cn_orig = journal_hash(table, cn->sb, cn->blocknr) ; cn->hnext = cn_orig ; cn->hprev = NULL ; if (cn_orig) { cn_orig->hprev = cn ; } - journal_hash(table, cn->dev, cn->blocknr) = cn ; + journal_hash(table, cn->sb, cn->blocknr) = cn ; } /* lock the current transaction */ @@ -760,12 +763,12 @@ ** returns NULL if it can't find anything */ static struct reiserfs_journal_list *find_newer_jl_for_cn(struct reiserfs_journal_cnode *cn) { - kdev_t dev = cn->dev; + struct super_block *sb = cn->sb; unsigned long blocknr = cn->blocknr ; cn = cn->hprev ; while(cn) { - if (kdev_same(cn->dev, dev) && cn->blocknr == blocknr && cn->jlist) { + if (cn->sb == sb && cn->blocknr == blocknr && cn->jlist) { return cn->jlist ; } cn = cn->hprev ; @@ -773,6 +776,8 @@ return NULL ; } +void remove_journal_hash(struct super_block *, struct reiserfs_journal_cnode **, +struct reiserfs_journal_list *, unsigned long, int); /* ** once all the real blocks have been flushed, it is safe to remove them from the @@ -780,12 +785,11 @@ ** block to be reallocated for data blocks if it had been deleted. */ static void remove_all_from_journal_list(struct super_block *p_s_sb, struct reiserfs_journal_list *jl, int debug) { - struct buffer_head fake_bh ; struct reiserfs_journal_cnode *cn, *last ; cn = jl->j_realblock ; /* which is better, to lock once around the whole loop, or - ** to lock for each call to remove_from_journal_list? + ** to lock for each call to remove_journal_hash? */ while(cn) { if (cn->blocknr != 0) { @@ -793,10 +797,8 @@ printk("block %lu, bh is %d, state %d\n", cn->blocknr, cn->bh ? 1: 0, cn->state) ; } - fake_bh.b_blocknr = cn->blocknr ; - fake_bh.b_dev = cn->dev ; cn->state = 0 ; - remove_from_journal_list(p_s_sb, jl, &fake_bh, 1) ; + remove_journal_hash(p_s_sb, SB_JOURNAL(p_s_sb)->j_list_hash_table, jl, cn->blocknr, 1) ; } last = cn ; cn = cn->next ; @@ -1178,7 +1180,7 @@ mark_buffer_notjournal_dirty(cn->bh) ; while(walk_cn) { if (walk_cn->bh && walk_cn->blocknr == blocknr && - kdev_same(walk_cn->dev, cn->dev)) { + walk_cn->sb == cn->sb) { if (walk_cn->jlist) { atomic_dec(&(walk_cn->jlist->j_nonzerolen)) ; } @@ -1267,21 +1269,21 @@ ** removes any nodes in table with name block and dev as bh. ** only touchs the hnext and hprev pointers. */ -void remove_journal_hash(struct reiserfs_journal_cnode **table, struct reiserfs_journal_list *jl,struct buffer_head *bh, - int remove_freed){ +void remove_journal_hash(struct super_block *sb, + struct reiserfs_journal_cnode **table, + struct reiserfs_journal_list *jl, + unsigned long block, int remove_freed) +{ struct reiserfs_journal_cnode *cur ; struct reiserfs_journal_cnode **head ; - if (!bh) - return ; - - head= &(journal_hash(table, bh->b_dev, bh->b_blocknr)) ; + head= &(journal_hash(table, sb, block)) ; if (!head) { return ; } cur = *head ; while(cur) { - if (cur->blocknr == bh->b_blocknr && kdev_same(cur->dev, bh->b_dev) && (jl == NULL || jl == cur->jlist) && + if (cur->blocknr == block && cur->sb == sb && (jl == NULL || jl == cur->jlist) && (!test_bit(BLOCK_FREED, &cur->state) || remove_freed)) { if (cur->hnext) { cur->hnext->hprev = cur->hprev ; @@ -1292,7 +1294,7 @@ *head = cur->hnext ; } cur->blocknr = 0 ; - cur->dev = NODEV ; + cur->sb = NULL ; cur->state = 0 ; if (cur->bh && cur->jlist) /* anybody who clears the cur->bh will also dec the nonzerolen */ atomic_dec(&(cur->jlist->j_nonzerolen)) ; @@ -2184,7 +2186,7 @@ cn->bh = bh ; cn->blocknr = bh->b_blocknr ; - cn->dev = bh->b_dev ; + cn->sb = p_s_sb; cn->jlist = NULL ; insert_journal_hash(SB_JOURNAL(p_s_sb)->j_hash_table, cn) ; if (!count_already_incd) { @@ -2215,7 +2217,7 @@ buffer_journal_dirty(bh)) { return journal_mark_dirty(th, p_s_sb, bh) ; } - if (get_journal_hash_dev(SB_JOURNAL(p_s_sb)->j_list_hash_table, bh->b_dev,bh->b_blocknr,bh->b_size)) { + if (get_journal_hash_dev(p_s_sb, SB_JOURNAL(p_s_sb)->j_list_hash_table, bh->b_blocknr)) { return journal_mark_dirty(th, p_s_sb, bh) ; } mark_buffer_dirty(bh) ; @@ -2238,7 +2240,7 @@ struct reiserfs_journal_cnode *cn ; int ret = 0; - cn = get_journal_hash_dev(SB_JOURNAL(p_s_sb)->j_hash_table, p_s_sb->s_dev, blocknr, p_s_sb->s_blocksize) ; + cn = get_journal_hash_dev(p_s_sb, SB_JOURNAL(p_s_sb)->j_hash_table, blocknr) ; if (!cn || !cn->bh) { return ret ; } @@ -2255,7 +2257,8 @@ if (cn == SB_JOURNAL(p_s_sb)->j_last) { SB_JOURNAL(p_s_sb)->j_last = cn->prev ; } - remove_journal_hash(SB_JOURNAL(p_s_sb)->j_hash_table, NULL, bh, 0) ; + if (bh) + remove_journal_hash(p_s_sb, SB_JOURNAL(p_s_sb)->j_hash_table, NULL, bh->b_blocknr, 0) ; mark_buffer_not_journaled(bh) ; /* don't log this one */ if (!already_cleaned) { @@ -2273,12 +2276,6 @@ return ret ; } -/* removes from a specific journal list hash */ -int remove_from_journal_list(struct super_block *s, struct reiserfs_journal_list *jl, struct buffer_head *bh, int remove_freed) { - remove_journal_hash(SB_JOURNAL(s)->j_list_hash_table, jl, bh, remove_freed) ; - return 0 ; -} - /* ** for any cnode in a journal list, it can only be dirtied of all the ** transactions that include it are commited to disk. @@ -2290,7 +2287,7 @@ ** */ static int can_dirty(struct reiserfs_journal_cnode *cn) { - kdev_t dev = cn->dev ; + struct super_block *sb = cn->sb; unsigned long blocknr = cn->blocknr ; struct reiserfs_journal_cnode *cur = cn->hprev ; int can_dirty = 1 ; @@ -2300,7 +2297,7 @@ ** to disk right now. */ while(cur && can_dirty) { - if (cur->jlist && cur->bh && cur->blocknr && kdev_same(cur->dev, dev) && + if (cur->jlist && cur->bh && cur->blocknr && cur->sb == sb && cur->blocknr == blocknr) { can_dirty = 0 ; } @@ -2313,7 +2310,7 @@ while(cur && can_dirty) { if (cur->jlist && cur->jlist->j_len > 0 && atomic_read(&(cur->jlist->j_commit_left)) > 0 && cur->bh && - cur->blocknr && kdev_same(cur->dev, dev) && cur->blocknr == blocknr) { + cur->blocknr && cur->sb == sb && cur->blocknr == blocknr) { can_dirty = 0 ; } cur = cur->hnext ; @@ -2578,9 +2575,9 @@ cleaned = remove_from_transaction(p_s_sb, blocknr, cleaned) ; /* find all older transactions with this block, make sure they don't try to write it out */ - cn = get_journal_hash_dev(SB_JOURNAL(p_s_sb)->j_list_hash_table, p_s_sb->s_dev, blocknr, p_s_sb->s_blocksize) ; + cn = get_journal_hash_dev(p_s_sb,SB_JOURNAL(p_s_sb)->j_list_hash_table, blocknr) ; while (cn) { - if (kdev_same(p_s_sb->s_dev, cn->dev) && blocknr == cn->blocknr) { + if (p_s_sb == cn->sb && blocknr == cn->blocknr) { set_bit(BLOCK_FREED, &cn->state) ; if (cn->bh) { if (!cleaned) { @@ -2821,7 +2818,7 @@ } jl_cn->blocknr = cn->bh->b_blocknr ; jl_cn->state = 0 ; - jl_cn->dev = cn->bh->b_dev ; + jl_cn->sb = p_s_sb ; jl_cn->bh = cn->bh ; jl_cn->jlist = SB_JOURNAL_LIST(p_s_sb) + SB_JOURNAL_LIST_INDEX(p_s_sb) ; insert_journal_hash(SB_JOURNAL(p_s_sb)->j_list_hash_table, jl_cn) ; diff -urN linux-2.5.2-pre11/fs/reiserfs/tail_conversion.c linux/fs/reiserfs/tail_conversion.c --- linux-2.5.2-pre11/fs/reiserfs/tail_conversion.c Tue Oct 30 15:11:34 2001 +++ linux/fs/reiserfs/tail_conversion.c Mon Jan 14 18:28:31 2002 @@ -142,6 +142,7 @@ clear_bit(BH_Mapped, &bh->b_state) ; clear_bit(BH_Req, &bh->b_state) ; clear_bit(BH_New, &bh->b_state) ; + bh->b_bdev = NULL; unlock_buffer(bh) ; } } diff -urN linux-2.5.2-pre11/include/asm-sparc/bitops.h linux/include/asm-sparc/bitops.h --- linux-2.5.2-pre11/include/asm-sparc/bitops.h Tue Oct 30 15:08:11 2001 +++ linux/include/asm-sparc/bitops.h Mon Jan 14 18:28:32 2002 @@ -1,4 +1,4 @@ -/* $Id: bitops.h,v 1.65 2001/10/30 04:08:26 davem Exp $ +/* $Id: bitops.h,v 1.67 2001/11/19 18:36:34 davem Exp $ * bitops.h: Bit string operations on the Sparc. * * Copyright 1995 David S. Miller (davem@caip.rutgers.edu) diff -urN linux-2.5.2-pre11/include/asm-sparc/io.h linux/include/asm-sparc/io.h --- linux-2.5.2-pre11/include/asm-sparc/io.h Tue Nov 13 09:16:05 2001 +++ linux/include/asm-sparc/io.h Mon Jan 14 18:28:32 2002 @@ -1,5 +1,5 @@ /* - * $Id: io.h,v 1.29 2001/11/10 09:28:34 davem Exp $ + * $Id: io.h,v 1.30 2001/12/21 01:23:21 davem Exp $ */ #ifndef __SPARC_IO_H #define __SPARC_IO_H @@ -11,8 +11,7 @@ #include /* IO address mapping routines need this */ #include -#define virt_to_bus virt_to_phys -#define bus_to_virt phys_to_virt +#define page_to_phys(page) ((page - mem_map) << PAGE_SHIFT) static __inline__ u32 flip_dword (u32 d) { diff -urN linux-2.5.2-pre11/include/asm-sparc/keyboard.h linux/include/asm-sparc/keyboard.h --- linux-2.5.2-pre11/include/asm-sparc/keyboard.h Mon Jan 14 18:28:25 2002 +++ linux/include/asm-sparc/keyboard.h Mon Jan 14 18:28:32 2002 @@ -1,4 +1,4 @@ -/* $Id: keyboard.h,v 1.7 2001/08/18 09:40:46 davem Exp $ +/* $Id: keyboard.h,v 1.8 2002/01/08 16:00:20 davem Exp $ * linux/include/asm-sparc/keyboard.h * * sparc64 Created Aug 29 1997 by Eddie C. Dost (ecd@skynet.be) diff -urN linux-2.5.2-pre11/include/asm-sparc/mmu_context.h linux/include/asm-sparc/mmu_context.h --- linux-2.5.2-pre11/include/asm-sparc/mmu_context.h Thu Aug 10 13:30:05 2000 +++ linux/include/asm-sparc/mmu_context.h Mon Jan 14 18:28:32 2002 @@ -5,6 +5,29 @@ #ifndef __ASSEMBLY__ +/* + * Every architecture must define this function. It's the fastest + * way of searching a 168-bit bitmap where the first 128 bits are + * unlikely to be clear. It's guaranteed that at least one of the 168 + * bits is cleared. + */ +#if MAX_RT_PRIO != 128 || MAX_PRIO != 168 +# error update this function. +#endif + +static inline int sched_find_first_zero_bit(unsigned long *b) +{ + unsigned int rt; + + rt = b[0] & b[1] & b[2] & b[3]; + if (unlikely(rt != 0xffffffff)) + return find_first_zero_bit(b, MAX_RT_PRIO); + + if (b[4] != ~0) + return ffz(b[4]) + MAX_RT_PRIO; + return ffz(b[5]) + 32 + MAX_RT_PRIO; +} + static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu) { } diff -urN linux-2.5.2-pre11/include/asm-sparc/oplib.h linux/include/asm-sparc/oplib.h --- linux-2.5.2-pre11/include/asm-sparc/oplib.h Mon Aug 28 21:20:03 2000 +++ linux/include/asm-sparc/oplib.h Mon Jan 14 18:28:32 2002 @@ -1,4 +1,4 @@ -/* $Id: oplib.h,v 1.21 2000/08/26 02:38:04 anton Exp $ +/* $Id: oplib.h,v 1.23 2001/12/21 00:54:31 davem Exp $ * oplib.h: Describes the interface and available routines in the * Linux Prom library. * @@ -298,15 +298,7 @@ /* Dorking with Bus ranges... */ -/* Adjust reg values with the passed ranges. */ -extern void prom_adjust_regs(struct linux_prom_registers *regp, int nregs, - struct linux_prom_ranges *rangep, int nranges); - -/* Adjust child ranges with the passed parent ranges. */ -extern void prom_adjust_ranges(struct linux_prom_ranges *cranges, int ncranges, - struct linux_prom_ranges *pranges, int npranges); - -/* Apply promlib probed OBIO ranges to registers. */ +/* Apply promlib probes OBIO ranges to registers. */ extern void prom_apply_obio_ranges(struct linux_prom_registers *obioregs, int nregs); /* Apply ranges of any prom node (and optionally parent node as well) to registers. */ diff -urN linux-2.5.2-pre11/include/asm-sparc/pci.h linux/include/asm-sparc/pci.h --- linux-2.5.2-pre11/include/asm-sparc/pci.h Tue Nov 13 09:16:05 2001 +++ linux/include/asm-sparc/pci.h Mon Jan 14 18:28:32 2002 @@ -26,6 +26,7 @@ /* Dynamic DMA mapping stuff. */ +#define PCI_DMA_BUS_IS_PHYS (0) #include diff -urN linux-2.5.2-pre11/include/asm-sparc/smp.h linux/include/asm-sparc/smp.h --- linux-2.5.2-pre11/include/asm-sparc/smp.h Tue Nov 13 09:16:05 2001 +++ linux/include/asm-sparc/smp.h Mon Jan 14 18:28:32 2002 @@ -190,8 +190,6 @@ #define MBOX_IDLECPU2 0xFD #define MBOX_STOPCPU2 0xFE -#define PROC_CHANGE_PENALTY 15 - #endif /* !(CONFIG_SMP) */ #define NO_PROC_ID 0xFF diff -urN linux-2.5.2-pre11/include/asm-sparc/smplock.h linux/include/asm-sparc/smplock.h --- linux-2.5.2-pre11/include/asm-sparc/smplock.h Thu Mar 23 12:50:09 2000 +++ linux/include/asm-sparc/smplock.h Mon Jan 14 18:28:32 2002 @@ -3,31 +3,35 @@ * * Default SMP lock implementation */ +#include #include #include extern spinlock_t kernel_flag; -#define kernel_locked() spin_is_locked(&kernel_flag) +#define kernel_locked() \ + (spin_is_locked(&kernel_flag) &&\ + (current->lock_depth >= 0)) /* * Release global kernel lock and global interrupt lock */ -#define release_kernel_lock(task, cpu) \ -do { \ - if (task->lock_depth >= 0) \ - spin_unlock(&kernel_flag); \ - release_irqlock(cpu); \ - __sti(); \ +#define release_kernel_lock(task, cpu) \ +do { \ + if (unlikely(task->lock_depth >= 0)) { \ + spin_unlock(&kernel_flag); \ + release_irqlock(cpu); \ + __sti(); \ + } \ } while (0) /* * Re-acquire the kernel lock */ -#define reacquire_kernel_lock(task) \ -do { \ - if (task->lock_depth >= 0) \ - spin_lock(&kernel_flag); \ +#define reacquire_kernel_lock(task) \ +do { \ + if (unlikely(task->lock_depth >= 0)) \ + spin_lock(&kernel_flag); \ } while (0) @@ -38,14 +42,14 @@ * so we only need to worry about other * CPU's. */ -extern __inline__ void lock_kernel(void) -{ - if (!++current->lock_depth) - spin_lock(&kernel_flag); -} - -extern __inline__ void unlock_kernel(void) -{ - if (--current->lock_depth < 0) - spin_unlock(&kernel_flag); -} +#define lock_kernel() \ +do { \ + if (!++current->lock_depth) \ + spin_lock(&kernel_flag); \ +} while(0) + +#define unlock_kernel() \ +do { \ + if (--current->lock_depth < 0) \ + spin_unlock(&kernel_flag); \ +} while(0) diff -urN linux-2.5.2-pre11/include/asm-sparc/string.h linux/include/asm-sparc/string.h --- linux-2.5.2-pre11/include/asm-sparc/string.h Wed May 3 01:47:57 2000 +++ linux/include/asm-sparc/string.h Mon Jan 14 18:28:32 2002 @@ -1,4 +1,4 @@ -/* $Id: string.h,v 1.35 2000/05/02 01:47:01 davem Exp $ +/* $Id: string.h,v 1.36 2001/12/21 00:54:31 davem Exp $ * string.h: External definitions for optimized assembly string * routines for the Linux Kernel. * @@ -126,9 +126,11 @@ }) #define __HAVE_ARCH_MEMCMP +extern int memcmp(const void *,const void *,__kernel_size_t); /* Now the str*() stuff... */ #define __HAVE_ARCH_STRLEN +extern __kernel_size_t strlen(const char *); #define __HAVE_ARCH_STRNCMP diff -urN linux-2.5.2-pre11/include/asm-sparc/types.h linux/include/asm-sparc/types.h --- linux-2.5.2-pre11/include/asm-sparc/types.h Mon Jan 31 23:37:19 2000 +++ linux/include/asm-sparc/types.h Mon Jan 14 18:28:32 2002 @@ -1,4 +1,4 @@ -/* $Id: types.h,v 1.12 2000/01/29 02:23:25 anton Exp $ */ +/* $Id: types.h,v 1.13 2001/12/21 01:22:59 davem Exp $ */ #ifndef _SPARC_TYPES_H #define _SPARC_TYPES_H @@ -46,6 +46,7 @@ #define BITS_PER_LONG 32 typedef u32 dma_addr_t; +typedef u32 dma64_addr_t; #endif /* __KERNEL__ */ diff -urN linux-2.5.2-pre11/include/asm-sparc64/bitops.h linux/include/asm-sparc64/bitops.h --- linux-2.5.2-pre11/include/asm-sparc64/bitops.h Wed Jun 20 21:00:55 2001 +++ linux/include/asm-sparc64/bitops.h Mon Jan 14 18:28:32 2002 @@ -1,4 +1,4 @@ -/* $Id: bitops.h,v 1.36 2001/06/14 12:34:49 davem Exp $ +/* $Id: bitops.h,v 1.38 2001/11/19 18:36:34 davem Exp $ * bitops.h: Bit string operations on the V9. * * Copyright 1996, 1997 David S. Miller (davem@caip.rutgers.edu) @@ -13,9 +13,9 @@ extern long ___test_and_clear_bit(unsigned long nr, volatile void *addr); extern long ___test_and_change_bit(unsigned long nr, volatile void *addr); -#define test_and_set_bit(nr,addr) (___test_and_set_bit(nr,addr)!=0) -#define test_and_clear_bit(nr,addr) (___test_and_clear_bit(nr,addr)!=0) -#define test_and_change_bit(nr,addr) (___test_and_change_bit(nr,addr)!=0) +#define test_and_set_bit(nr,addr) ({___test_and_set_bit(nr,addr)!=0;}) +#define test_and_clear_bit(nr,addr) ({___test_and_clear_bit(nr,addr)!=0;}) +#define test_and_change_bit(nr,addr) ({___test_and_change_bit(nr,addr)!=0;}) #define set_bit(nr,addr) ((void)___test_and_set_bit(nr,addr)) #define clear_bit(nr,addr) ((void)___test_and_clear_bit(nr,addr)) #define change_bit(nr,addr) ((void)___test_and_change_bit(nr,addr)) @@ -214,8 +214,8 @@ extern long ___test_and_set_le_bit(int nr, volatile void *addr); extern long ___test_and_clear_le_bit(int nr, volatile void *addr); -#define test_and_set_le_bit(nr,addr) (___test_and_set_le_bit(nr,addr)!=0) -#define test_and_clear_le_bit(nr,addr) (___test_and_clear_le_bit(nr,addr)!=0) +#define test_and_set_le_bit(nr,addr) ({___test_and_set_le_bit(nr,addr)!=0;}) +#define test_and_clear_le_bit(nr,addr) ({___test_and_clear_le_bit(nr,addr)!=0;}) #define set_le_bit(nr,addr) ((void)___test_and_set_le_bit(nr,addr)) #define clear_le_bit(nr,addr) ((void)___test_and_clear_le_bit(nr,addr)) diff -urN linux-2.5.2-pre11/include/asm-sparc64/elf.h linux/include/asm-sparc64/elf.h --- linux-2.5.2-pre11/include/asm-sparc64/elf.h Fri Sep 7 11:01:20 2001 +++ linux/include/asm-sparc64/elf.h Mon Jan 14 18:28:32 2002 @@ -1,4 +1,4 @@ -/* $Id: elf.h,v 1.30 2001/08/30 23:35:38 kanoj Exp $ */ +/* $Id: elf.h,v 1.31 2002/01/08 16:00:20 davem Exp $ */ #ifndef __ASM_SPARC64_ELF_H #define __ASM_SPARC64_ELF_H @@ -75,24 +75,7 @@ else \ flags &= ~SPARC_FLAG_32BIT; \ if (flags != current->thread.flags) { \ - unsigned long pgd_cache = 0UL; \ - if (flags & SPARC_FLAG_32BIT) { \ - pgd_t *pgd0 = ¤t->mm->pgd[0]; \ - if (pgd_none (*pgd0)) { \ - pmd_t *page = pmd_alloc_one_fast(NULL, 0); \ - if (!page) \ - page = pmd_alloc_one(NULL, 0); \ - pgd_set(pgd0, page); \ - } \ - pgd_cache = pgd_val(*pgd0) << 11UL; \ - } \ - __asm__ __volatile__( \ - "stxa\t%0, [%1] %2\n\t" \ - "membar #Sync" \ - : /* no outputs */ \ - : "r" (pgd_cache), \ - "r" (TSB_REG), \ - "i" (ASI_DMMU)); \ + /* flush_thread will update pgd cache */\ current->thread.flags = flags; \ } \ \ diff -urN linux-2.5.2-pre11/include/asm-sparc64/io.h linux/include/asm-sparc64/io.h --- linux-2.5.2-pre11/include/asm-sparc64/io.h Sun Dec 16 12:20:21 2001 +++ linux/include/asm-sparc64/io.h Mon Jan 14 18:28:32 2002 @@ -1,4 +1,4 @@ -/* $Id: io.h,v 1.46 2001/12/13 04:16:52 davem Exp $ */ +/* $Id: io.h,v 1.47 2001/12/13 10:36:02 davem Exp $ */ #ifndef __SPARC64_IO_H #define __SPARC64_IO_H diff -urN linux-2.5.2-pre11/include/asm-sparc64/keyboard.h linux/include/asm-sparc64/keyboard.h --- linux-2.5.2-pre11/include/asm-sparc64/keyboard.h Mon Jan 14 18:28:25 2002 +++ linux/include/asm-sparc64/keyboard.h Mon Jan 14 18:28:32 2002 @@ -1,4 +1,4 @@ -/* $Id: keyboard.h,v 1.5 2001/08/18 09:40:46 davem Exp $ +/* $Id: keyboard.h,v 1.6 2002/01/08 16:00:20 davem Exp $ * linux/include/asm-sparc64/keyboard.h * * Created Aug 29 1997 by Eddie C. Dost (ecd@skynet.be) diff -urN linux-2.5.2-pre11/include/asm-sparc64/mmu_context.h linux/include/asm-sparc64/mmu_context.h --- linux-2.5.2-pre11/include/asm-sparc64/mmu_context.h Tue Aug 28 07:09:44 2001 +++ linux/include/asm-sparc64/mmu_context.h Mon Jan 14 18:28:32 2002 @@ -1,4 +1,4 @@ -/* $Id: mmu_context.h,v 1.51 2001/08/17 04:55:09 kanoj Exp $ */ +/* $Id: mmu_context.h,v 1.52 2002/01/11 08:45:38 davem Exp $ */ #ifndef __SPARC64_MMU_CONTEXT_H #define __SPARC64_MMU_CONTEXT_H @@ -26,6 +26,27 @@ #include #include #include + +/* + * Every architecture must define this function. It's the fastest + * way of searching a 168-bit bitmap where the first 128 bits are + * unlikely to be clear. It's guaranteed that at least one of the 168 + * bits is cleared. + */ +#if MAX_RT_PRIO != 128 || MAX_PRIO != 168 +# error update this function. +#endif + +static inline int sched_find_first_zero_bit(unsigned long *b) +{ + unsigned long rt; + + rt = b[0] & b[1]; + if (unlikely(rt != 0xffffffffffffffff)) + return find_first_zero_bit(b, MAX_RT_PRIO); + + return ffz(b[2]) + MAX_RT_PRIO; +} static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu) { diff -urN linux-2.5.2-pre11/include/asm-sparc64/oplib.h linux/include/asm-sparc64/oplib.h --- linux-2.5.2-pre11/include/asm-sparc64/oplib.h Mon May 22 09:50:54 2000 +++ linux/include/asm-sparc64/oplib.h Mon Jan 14 18:28:32 2002 @@ -1,4 +1,4 @@ -/* $Id: oplib.h,v 1.13 2000/05/09 17:40:15 davem Exp $ +/* $Id: oplib.h,v 1.14 2001/12/19 00:29:51 davem Exp $ * oplib.h: Describes the interface and available routines in the * Linux Prom library. * @@ -326,20 +326,6 @@ /* Client interface level routines. */ extern void prom_set_trap_table(unsigned long tba); -/* Dorking with Bus ranges... */ - -/* Adjust reg values with the passed ranges. */ -extern void prom_adjust_regs(struct linux_prom_registers *regp, int nregs, - struct linux_prom_ranges *rangep, int nranges); - -/* Adjust child ranges with the passed parent ranges. */ -extern void prom_adjust_ranges(struct linux_prom_ranges *cranges, int ncranges, - struct linux_prom_ranges *pranges, int npranges); - -/* Apply ranges of any prom node (and optionally parent node as well) to registers. */ -extern void prom_apply_generic_ranges(int node, int parent, - struct linux_prom_registers *sbusregs, int nregs); - extern long p1275_cmd (char *, long, ...); diff -urN linux-2.5.2-pre11/include/asm-sparc64/page.h linux/include/asm-sparc64/page.h --- linux-2.5.2-pre11/include/asm-sparc64/page.h Thu Aug 10 12:43:12 2000 +++ linux/include/asm-sparc64/page.h Mon Jan 14 18:28:32 2002 @@ -1,4 +1,4 @@ -/* $Id: page.h,v 1.36 2000/08/10 01:04:53 davem Exp $ */ +/* $Id: page.h,v 1.38 2001/11/30 01:04:10 davem Exp $ */ #ifndef _SPARC64_PAGE_H #define _SPARC64_PAGE_H @@ -18,13 +18,20 @@ #ifndef __ASSEMBLY__ +#ifdef CONFIG_DEBUG_BUGVERBOSE +extern void do_BUG(const char *file, int line); +#define BUG() do { \ + do_BUG(__FILE__, __LINE__); \ + __builtin_trap(); \ +} while (0) +#else #define BUG() __builtin_trap() +#endif + #define PAGE_BUG(page) BUG() extern void _clear_page(void *page); -extern void _copy_page(void *to, void *from); #define clear_page(X) _clear_page((void *)(X)) -#define copy_page(X,Y) _copy_page((void *)(X), (void *)(Y)) extern void clear_user_page(void *page, unsigned long vaddr); extern void copy_user_page(void *to, void *from, unsigned long vaddr); diff -urN linux-2.5.2-pre11/include/asm-sparc64/processor.h linux/include/asm-sparc64/processor.h --- linux-2.5.2-pre11/include/asm-sparc64/processor.h Wed Oct 10 23:42:47 2001 +++ linux/include/asm-sparc64/processor.h Mon Jan 14 18:28:32 2002 @@ -1,4 +1,4 @@ -/* $Id: processor.h,v 1.76 2001/10/08 09:32:13 davem Exp $ +/* $Id: processor.h,v 1.80 2001/11/17 00:10:48 davem Exp $ * include/asm-sparc64/processor.h * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -66,6 +66,15 @@ unsigned long gsr[7]; unsigned long xfsr[7]; +#ifdef CONFIG_DEBUG_SPINLOCK + /* How many spinlocks held by this thread. + * Used with spin lock debugging to catch tasks + * sleeping illegally with locks held. + */ + int smp_lock_count; + unsigned int smp_lock_pc; +#endif + struct reg_window reg_window[NSWINS]; unsigned long rwbuf_stkptrs[NSWINS]; @@ -88,6 +97,7 @@ #define FAULT_CODE_ITLB 0x04 /* Miss happened in I-TLB */ #define FAULT_CODE_WINFIXUP 0x08 /* Miss happened during spill/fill */ +#ifndef CONFIG_DEBUG_SPINLOCK #define INIT_THREAD { \ /* ksp, wstate, cwp, flags, current_ds, */ \ 0, 0, 0, 0, KERNEL_DS, \ @@ -104,6 +114,24 @@ /* user_cntd0, user_cndd1, kernel_cntd0, kernel_cntd0, pcr_reg */ \ 0, 0, 0, 0, 0, \ } +#else /* CONFIG_DEBUG_SPINLOCK */ +#define INIT_THREAD { \ +/* ksp, wstate, cwp, flags, current_ds, */ \ + 0, 0, 0, 0, KERNEL_DS, \ +/* w_saved, fpdepth, fault_code, use_blkcommit, */ \ + 0, 0, 0, 0, \ +/* fault_address, fpsaved, __pad2, kregs, */ \ + 0, { 0 }, 0, 0, \ +/* utraps, gsr, xfsr, smp_lock_count, smp_lock_pc, */\ + 0, { 0 }, { 0 }, 0, 0, \ +/* reg_window */ \ + { { { 0, }, { 0, } }, }, \ +/* rwbuf_stkptrs */ \ + { 0, 0, 0, 0, 0, 0, 0, }, \ +/* user_cntd0, user_cndd1, kernel_cntd0, kernel_cntd0, pcr_reg */ \ + 0, 0, 0, 0, 0, \ +} +#endif /* !(CONFIG_DEBUG_SPINLOCK) */ #ifdef __KERNEL__ #if PAGE_SHIFT == 13 diff -urN linux-2.5.2-pre11/include/asm-sparc64/rwsem.h linux/include/asm-sparc64/rwsem.h --- linux-2.5.2-pre11/include/asm-sparc64/rwsem.h Thu Apr 26 22:17:26 2001 +++ linux/include/asm-sparc64/rwsem.h Mon Jan 14 18:28:32 2002 @@ -1,4 +1,4 @@ -/* $Id: rwsem.h,v 1.4 2001/04/26 02:36:36 davem Exp $ +/* $Id: rwsem.h,v 1.5 2001/11/18 00:12:56 davem Exp $ * rwsem.h: R/W semaphores implemented using CAS * * Written by David S. Miller (davem@redhat.com), 2001. @@ -59,7 +59,7 @@ " add %%g7, 1, %%g7\n\t" "cmp %%g7, 0\n\t" "bl,pn %%icc, 3f\n\t" - " membar #StoreStore\n" + " membar #StoreLoad | #StoreStore\n" "2:\n\t" ".subsection 2\n" "3:\tmov %0, %%g5\n\t" @@ -92,7 +92,7 @@ "bne,pn %%icc, 1b\n\t" " cmp %%g7, 0\n\t" "bne,pn %%icc, 3f\n\t" - " membar #StoreStore\n" + " membar #StoreLoad | #StoreStore\n" "2:\n\t" ".subsection 2\n" "3:\tmov %0, %%g5\n\t" @@ -122,7 +122,7 @@ "bne,pn %%icc, 1b\n\t" " cmp %%g7, 0\n\t" "bl,pn %%icc, 3f\n\t" - " membar #StoreStore\n" + " membar #StoreLoad | #StoreStore\n" "2:\n\t" ".subsection 2\n" "3:\tsethi %%hi(%2), %%g1\n\t" @@ -160,7 +160,7 @@ " sub %%g7, %%g1, %%g7\n\t" "cmp %%g7, 0\n\t" "bl,pn %%icc, 3f\n\t" - " membar #StoreStore\n" + " membar #StoreLoad | #StoreStore\n" "2:\n\t" ".subsection 2\n" "3:\tmov %0, %%g5\n\t" @@ -189,7 +189,7 @@ "cas [%2], %%g5, %%g7\n\t" "cmp %%g5, %%g7\n\t" "bne,pn %%icc, 1b\n\t" - " nop\n\t" + " membar #StoreLoad | #StoreStore\n\t" "mov %%g7, %0\n\t" : "=&r" (tmp) : "0" (tmp), "r" (sem) @@ -208,7 +208,7 @@ again: __asm__ __volatile__("cas [%2], %3, %0\n\t" - "membar #StoreStore | #StoreLoad" + "membar #StoreLoad | #StoreStore" : "=&r" (prev) : "0" (new), "r" (sem), "r" (old) : "memory"); diff -urN linux-2.5.2-pre11/include/asm-sparc64/semaphore.h linux/include/asm-sparc64/semaphore.h --- linux-2.5.2-pre11/include/asm-sparc64/semaphore.h Sun May 20 11:32:08 2001 +++ linux/include/asm-sparc64/semaphore.h Mon Jan 14 18:28:32 2002 @@ -75,7 +75,7 @@ " bne,pn %%icc, 1b\n" " cmp %%g7, 1\n" " bl,pn %%icc, 3f\n" -" membar #StoreStore\n" +" membar #StoreLoad | #StoreStore\n" "2:\n" " .subsection 2\n" "3: mov %0, %%g5\n" @@ -120,7 +120,7 @@ " bne,pn %%icc, 1b\n" " cmp %%g7, 1\n" " bl,pn %%icc, 3f\n" -" membar #StoreStore\n" +" membar #StoreLoad | #StoreStore\n" "2:\n" " .subsection 2\n" "3: mov %2, %%g5\n" @@ -173,7 +173,7 @@ " cmp %%g5, %%g7\n" " bne,pn %%icc, 1b\n" " mov 0, %0\n" -" membar #StoreStore\n" +" membar #StoreLoad | #StoreStore\n" "2:\n" : "=&r" (ret) : "r" (sem) @@ -207,7 +207,7 @@ " bne,pn %%icc, 1b\n" " addcc %%g7, 1, %%g0\n" " ble,pn %%icc, 3f\n" -" nop\n" +" membar #StoreLoad | #StoreStore\n" "2:\n" " .subsection 2\n" "3: mov %0, %%g5\n" diff -urN linux-2.5.2-pre11/include/asm-sparc64/smp.h linux/include/asm-sparc64/smp.h --- linux-2.5.2-pre11/include/asm-sparc64/smp.h Thu Apr 26 22:17:26 2001 +++ linux/include/asm-sparc64/smp.h Mon Jan 14 18:28:32 2002 @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -34,7 +35,7 @@ /* Per processor Sparc parameters we need. */ /* Keep this a multiple of 64-bytes for cache reasons. */ -struct cpuinfo_sparc { +typedef struct { /* Dcache line 1 */ unsigned int __pad0; /* bh_count moved to irq_stat for consistency. KAO */ unsigned int multiplier; @@ -51,9 +52,9 @@ /* Dcache lines 3 and 4 */ unsigned int irq_worklists[16]; -}; +} ____cacheline_aligned cpuinfo_sparc; -extern struct cpuinfo_sparc cpu_data[NR_CPUS]; +extern cpuinfo_sparc cpu_data[NR_CPUS]; /* * Private routines/data @@ -102,20 +103,22 @@ } } -#define smp_processor_id() (current->processor) +#define smp_processor_id() (current->cpu) /* This needn't do anything as we do not sleep the cpu * inside of the idler task, so an interrupt is not needed * to get a clean fast response. * + * XXX Reverify this assumption... -DaveM + * * Addendum: We do want it to do something for the signal * delivery case, we detect that by just seeing * if we are trying to send this to an idler or not. */ -extern __inline__ void smp_send_reschedule(int cpu) +static __inline__ void smp_send_reschedule(int cpu) { extern void smp_receive_signal(int); - if(cpu_data[cpu].idle_volume == 0) + if (cpu_data[cpu].idle_volume == 0) smp_receive_signal(cpu); } @@ -125,8 +128,6 @@ extern __inline__ void smp_send_stop(void) { } #endif /* !(__ASSEMBLY__) */ - -#define PROC_CHANGE_PENALTY 20 #endif /* !(CONFIG_SMP) */ diff -urN linux-2.5.2-pre11/include/asm-sparc64/smplock.h linux/include/asm-sparc64/smplock.h --- linux-2.5.2-pre11/include/asm-sparc64/smplock.h Thu Mar 23 12:50:09 2000 +++ linux/include/asm-sparc64/smplock.h Mon Jan 14 18:28:32 2002 @@ -9,26 +9,29 @@ extern spinlock_t kernel_flag; -#define kernel_locked() spin_is_locked(&kernel_flag) +#define kernel_locked() \ + (spin_is_locked(&kernel_flag) &&\ + (current->lock_depth >= 0)) /* * Release global kernel lock and global interrupt lock */ -#define release_kernel_lock(task, cpu) \ -do { \ - if (task->lock_depth >= 0) \ - spin_unlock(&kernel_flag); \ - release_irqlock(cpu); \ - __sti(); \ +#define release_kernel_lock(task, cpu) \ +do { \ + if (unlikely(task->lock_depth >= 0)) { \ + spin_unlock(&kernel_flag); \ + release_irqlock(cpu); \ + __sti(); \ + } \ } while (0) /* * Re-acquire the kernel lock */ -#define reacquire_kernel_lock(task) \ -do { \ - if (task->lock_depth >= 0) \ - spin_lock(&kernel_flag); \ +#define reacquire_kernel_lock(task) \ +do { \ + if (unlikely(task->lock_depth >= 0)) \ + spin_lock(&kernel_flag); \ } while (0) @@ -39,14 +42,14 @@ * so we only need to worry about other * CPU's. */ -#define lock_kernel() \ -do { \ - if (!++current->lock_depth) \ - spin_lock(&kernel_flag); \ +#define lock_kernel() \ +do { \ + if (!++current->lock_depth) \ + spin_lock(&kernel_flag); \ } while(0) -#define unlock_kernel() \ -do { \ - if (--current->lock_depth < 0) \ - spin_unlock(&kernel_flag); \ +#define unlock_kernel() \ +do { \ + if (--current->lock_depth < 0) \ + spin_unlock(&kernel_flag); \ } while(0) diff -urN linux-2.5.2-pre11/include/asm-sparc64/spinlock.h linux/include/asm-sparc64/spinlock.h --- linux-2.5.2-pre11/include/asm-sparc64/spinlock.h Thu Apr 26 22:17:26 2001 +++ linux/include/asm-sparc64/spinlock.h Mon Jan 14 18:28:32 2002 @@ -6,11 +6,13 @@ #ifndef __SPARC64_SPINLOCK_H #define __SPARC64_SPINLOCK_H +#include + #ifndef __ASSEMBLY__ /* To get debugging spinlocks which detect and catch - * deadlock situations, set DEBUG_SPINLOCKS in the sparc64 - * specific makefile and rebuild your kernel. + * deadlock situations, set CONFIG_DEBUG_SPINLOCK + * and rebuild your kernel. */ /* All of these locking primitives are expected to work properly @@ -26,7 +28,7 @@ * must be pre-V9 branches. */ -#ifndef SPIN_LOCK_DEBUG +#ifndef CONFIG_DEBUG_SPINLOCK typedef unsigned char spinlock_t; #define SPIN_LOCK_UNLOCKED 0 @@ -75,7 +77,7 @@ : "memory"); } -#else /* !(SPIN_LOCK_DEBUG) */ +#else /* !(CONFIG_DEBUG_SPINLOCK) */ typedef struct { unsigned char lock; @@ -101,11 +103,11 @@ #define spin_lock(lock) _do_spin_lock(lock, "spin_lock") #define spin_unlock(lock) _do_spin_unlock(lock) -#endif /* SPIN_LOCK_DEBUG */ +#endif /* CONFIG_DEBUG_SPINLOCK */ /* Multi-reader locks, these are much saner than the 32-bit Sparc ones... */ -#ifndef SPIN_LOCK_DEBUG +#ifndef CONFIG_DEBUG_SPINLOCK typedef unsigned int rwlock_t; #define RW_LOCK_UNLOCKED 0 @@ -121,7 +123,7 @@ #define write_lock(p) __write_lock(p) #define write_unlock(p) __write_unlock(p) -#else /* !(SPIN_LOCK_DEBUG) */ +#else /* !(CONFIG_DEBUG_SPINLOCK) */ typedef struct { unsigned long lock; @@ -164,7 +166,7 @@ __restore_flags(flags); \ } while(0) -#endif /* SPIN_LOCK_DEBUG */ +#endif /* CONFIG_DEBUG_SPINLOCK */ #endif /* !(__ASSEMBLY__) */ diff -urN linux-2.5.2-pre11/include/asm-sparc64/spitfire.h linux/include/asm-sparc64/spitfire.h --- linux-2.5.2-pre11/include/asm-sparc64/spitfire.h Mon Oct 1 09:19:56 2001 +++ linux/include/asm-sparc64/spitfire.h Mon Jan 14 18:28:32 2002 @@ -1,4 +1,4 @@ -/* $Id: spitfire.h,v 1.16 2001/09/24 21:17:57 kanoj Exp $ +/* $Id: spitfire.h,v 1.18 2001/11/29 16:42:10 kanoj Exp $ * spitfire.h: SpitFire/BlackBird/Cheetah inline MMU operations. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -32,6 +32,8 @@ #define VIRT_WATCHPOINT 0x0000000000000038 #define PHYS_WATCHPOINT 0x0000000000000040 +#define SPITFIRE_HIGHEST_LOCKED_TLBENT (64 - 1) + #ifndef __ASSEMBLY__ enum ultra_tlb_layout { @@ -43,7 +45,6 @@ #define SPARC64_USE_STICK (tlb_type == cheetah) -#define SPITFIRE_HIGHEST_LOCKED_TLBENT (64 - 1) #define CHEETAH_HIGHEST_LOCKED_TLBENT (16 - 1) #define L1DCACHE_SIZE 0x4000 @@ -357,12 +358,17 @@ * 2 way assosciative, and holds 512 entries. The fourth TLB is for * instruction accesses to 8K non-locked translations, is 2 way * assosciative, and holds 128 entries. + * + * Cheetah has some bug where bogus data can be returned from + * ASI_{D,I}TLB_DATA_ACCESS loads, doing the load twice fixes + * the problem for me. -DaveM */ extern __inline__ unsigned long cheetah_get_ldtlb_data(int entry) { unsigned long data; - __asm__ __volatile__("ldxa [%1] %2, %0" + __asm__ __volatile__("ldxa [%1] %2, %%g0\n\t" + "ldxa [%1] %2, %0" : "=r" (data) : "r" ((0 << 16) | (entry << 3)), "i" (ASI_DTLB_DATA_ACCESS)); @@ -374,7 +380,8 @@ { unsigned long data; - __asm__ __volatile__("ldxa [%1] %2, %0" + __asm__ __volatile__("ldxa [%1] %2, %%g0\n\t" + "ldxa [%1] %2, %0" : "=r" (data) : "r" ((0 << 16) | (entry << 3)), "i" (ASI_ITLB_DATA_ACCESS)); @@ -430,7 +437,8 @@ { unsigned long data; - __asm__ __volatile__("ldxa [%1] %2, %0" + __asm__ __volatile__("ldxa [%1] %2, %%g0\n\t" + "ldxa [%1] %2, %0" : "=r" (data) : "r" ((2 << 16) | (entry << 3)), "i" (ASI_DTLB_DATA_ACCESS)); @@ -461,7 +469,8 @@ { unsigned long data; - __asm__ __volatile__("ldxa [%1] %2, %0" + __asm__ __volatile__("ldxa [%1] %2, %%g0\n\t" + "ldxa [%1] %2, %0" : "=r" (data) : "r" ((2 << 16) | (entry << 3)), "i" (ASI_ITLB_DATA_ACCESS)); diff -urN linux-2.5.2-pre11/include/asm-sparc64/system.h linux/include/asm-sparc64/system.h --- linux-2.5.2-pre11/include/asm-sparc64/system.h Fri Sep 7 11:01:20 2001 +++ linux/include/asm-sparc64/system.h Mon Jan 14 18:28:32 2002 @@ -1,4 +1,4 @@ -/* $Id: system.h,v 1.64 2001/08/30 03:22:00 kanoj Exp $ */ +/* $Id: system.h,v 1.68 2001/11/18 00:12:56 davem Exp $ */ #ifndef __SPARC64_SYSTEM_H #define __SPARC64_SYSTEM_H @@ -145,6 +145,24 @@ #define flush_register_windows flushw_all #define prepare_to_switch flushw_all +#ifndef CONFIG_DEBUG_SPINLOCk +#define CHECK_LOCKS(PREV) do { } while(0) +#else /* CONFIG_DEBUG_SPINLOCk */ +#define CHECK_LOCKS(PREV) \ +if ((PREV)->thread.smp_lock_count) { \ + unsigned long rpc; \ + __asm__ __volatile__("mov %%i7, %0" : "=r" (rpc)); \ + printk(KERN_CRIT "(%s)[%d]: Sleeping with %d locks held!\n", \ + (PREV)->comm, (PREV)->pid, \ + (PREV)->thread.smp_lock_count); \ + printk(KERN_CRIT "(%s)[%d]: Last lock at %08x\n", \ + (PREV)->comm, (PREV)->pid, \ + (PREV)->thread.smp_lock_pc); \ + printk(KERN_CRIT "(%s)[%d]: Sched caller %016lx\n", \ + (PREV)->comm, (PREV)->pid, rpc); \ +} +#endif /* !(CONFIG_DEBUG_SPINLOCk) */ + /* See what happens when you design the chip correctly? * * We tell gcc we clobber all non-fixed-usage registers except @@ -155,7 +173,8 @@ * and 2 stores in this critical code path. -DaveM */ #define switch_to(prev, next, last) \ -do { if (current->thread.flags & SPARC_FLAG_PERFCTR) { \ +do { CHECK_LOCKS(prev); \ + if (current->thread.flags & SPARC_FLAG_PERFCTR) { \ unsigned long __tmp; \ read_pcr(__tmp); \ current->thread.pcr_reg = __tmp; \ @@ -276,7 +295,7 @@ __cmpxchg_u32(volatile int *m, int old, int new) { __asm__ __volatile__("cas [%2], %3, %0\n\t" - "membar #StoreStore | #StoreLoad" + "membar #StoreLoad | #StoreStore" : "=&r" (new) : "0" (new), "r" (m), "r" (old) : "memory"); @@ -288,7 +307,7 @@ __cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new) { __asm__ __volatile__("casx [%2], %3, %0\n\t" - "membar #StoreStore | #StoreLoad" + "membar #StoreLoad | #StoreStore" : "=&r" (new) : "0" (new), "r" (m), "r" (old) : "memory"); diff -urN linux-2.5.2-pre11/include/asm-sparc64/ttable.h linux/include/asm-sparc64/ttable.h --- linux-2.5.2-pre11/include/asm-sparc64/ttable.h Thu Apr 12 12:10:25 2001 +++ linux/include/asm-sparc64/ttable.h Mon Jan 14 18:28:32 2002 @@ -1,4 +1,4 @@ -/* $Id: ttable.h,v 1.16 2001/03/28 10:56:34 davem Exp $ */ +/* $Id: ttable.h,v 1.17 2001/11/28 23:32:16 davem Exp $ */ #ifndef _SPARC64_TTABLE_H #define _SPARC64_TTABLE_H @@ -29,6 +29,15 @@ clr %l6; \ nop; +#define TRAP_7INSNS(routine) \ + sethi %hi(109f), %g7; \ + ba,pt %xcc, etrap; \ +109: or %g7, %lo(109b), %g7; \ + call routine; \ + add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ + ba,pt %xcc, rtrap; \ + clr %l6; + #define TRAP_SAVEFPU(routine) \ sethi %hi(109f), %g7; \ ba,pt %xcc, do_fptrap; \ @@ -43,6 +52,11 @@ ba,pt %xcc, routine; \ nop; \ nop; nop; nop; nop; nop; nop; + +#define TRAP_NOSAVE_7INSNS(routine) \ + ba,pt %xcc, routine; \ + nop; \ + nop; nop; nop; nop; nop; #define TRAPTL1(routine) \ sethi %hi(109f), %g7; \ diff -urN linux-2.5.2-pre11/include/linux/blkdev.h linux/include/linux/blkdev.h --- linux-2.5.2-pre11/include/linux/blkdev.h Mon Jan 14 18:28:25 2002 +++ linux/include/linux/blkdev.h Mon Jan 14 18:28:32 2002 @@ -326,10 +326,6 @@ #define MIN_READAHEAD 3 #define blkdev_entry_to_request(entry) list_entry((entry), struct request, queuelist) -#define blkdev_entry_next_request(entry) blkdev_entry_to_request((entry)->next) -#define blkdev_entry_prev_request(entry) blkdev_entry_to_request((entry)->prev) -#define blkdev_next_request(req) blkdev_entry_to_request((req)->queuelist.next) -#define blkdev_prev_request(req) blkdev_entry_to_request((req)->queuelist.prev) extern void drive_stat_acct(struct request *, int, int); diff -urN linux-2.5.2-pre11/include/linux/crc32.h linux/include/linux/crc32.h --- linux-2.5.2-pre11/include/linux/crc32.h Wed Dec 31 16:00:00 1969 +++ linux/include/linux/crc32.h Mon Jan 14 18:28:32 2002 @@ -0,0 +1,17 @@ +/* + * crc32.h + * See linux/lib/crc32.c for license and changes + */ +#ifndef _LINUX_CRC32_H +#define _LINUX_CRC32_H + +#include + +extern u32 crc32_le(u32 crc, unsigned char const *p, size_t len); +extern u32 crc32_be(u32 crc, unsigned char const *p, size_t len); + +#define crc32(seed, data, length) crc32_le(seed, (unsigned char const *)data, length) +#define ether_crc_le(length, data) crc32_le(~0, data, length) +#define ether_crc(length, data) crc32_be(~0, data, length) + +#endif /* _LINUX_CRC32_H */ diff -urN linux-2.5.2-pre11/include/linux/fs.h linux/include/linux/fs.h --- linux-2.5.2-pre11/include/linux/fs.h Mon Jan 14 18:28:25 2002 +++ linux/include/linux/fs.h Mon Jan 14 18:28:32 2002 @@ -245,6 +245,7 @@ unsigned short b_size; /* block size */ unsigned short b_list; /* List that this buffer appears */ kdev_t b_dev; /* device (B_FREE = free) */ + struct block_device *b_bdev; atomic_t b_count; /* users using this block */ unsigned long b_state; /* buffer state bitmap (see above) */ @@ -1357,7 +1358,20 @@ extern void remove_inode_hash(struct inode *); extern struct file * get_empty_filp(void); extern void file_move(struct file *f, struct list_head *list); -extern struct buffer_head * get_hash_table(kdev_t, sector_t, int); +extern struct buffer_head * __get_hash_table(struct block_device *, sector_t, int); +static inline struct buffer_head * get_hash_table(kdev_t dev, sector_t block, int size) +{ + struct block_device *bdev; + struct buffer_head *bh; + bdev = bdget(kdev_t_to_nr(dev)); + if (!bdev) { + printk("No block device for %s\n", bdevname(dev)); + BUG(); + } + bh = __get_hash_table(bdev, block, size); + atomic_dec(&bdev->bd_count); + return bh; +} extern struct buffer_head * __getblk(struct block_device *, sector_t, int); static inline struct buffer_head * getblk(kdev_t dev, sector_t block, int size) { @@ -1416,11 +1430,12 @@ } static inline struct buffer_head * sb_get_hash_table(struct super_block *sb, int block) { - return get_hash_table(sb->s_dev, block, sb->s_blocksize); + return __get_hash_table(sb->s_bdev, block, sb->s_blocksize); } static inline void map_bh(struct buffer_head *bh, struct super_block *sb, int block) { bh->b_state |= 1 << BH_Mapped; + bh->b_bdev = sb->s_bdev; bh->b_dev = sb->s_dev; bh->b_blocknr = block; } @@ -1428,7 +1443,7 @@ extern void put_unused_buffer_head(struct buffer_head * bh); extern struct buffer_head * get_unused_buffer_head(int async); -extern int brw_page(int, struct page *, kdev_t, sector_t [], int); +extern int brw_page(int, struct page *, struct block_device *, sector_t [], int); typedef int (get_block_t)(struct inode*,sector_t,struct buffer_head*,int); diff -urN linux-2.5.2-pre11/include/linux/if_arp.h linux/include/linux/if_arp.h --- linux-2.5.2-pre11/include/linux/if_arp.h Sun Dec 16 15:44:15 2001 +++ linux/include/linux/if_arp.h Mon Jan 14 18:28:32 2002 @@ -82,6 +82,7 @@ /* 787->799 reserved for fibrechannel media types */ #define ARPHRD_IEEE802_TR 800 /* Magic type ident for TR */ #define ARPHRD_IEEE80211 801 /* IEEE 802.11 */ +#define ARPHRD_IEEE80211_PRISM 802 /* IEEE 802.11 + Prism2 header */ #define ARPHRD_VOID 0xFFFF /* Void type, nothing is known */ diff -urN linux-2.5.2-pre11/include/linux/if_bonding.h linux/include/linux/if_bonding.h --- linux-2.5.2-pre11/include/linux/if_bonding.h Wed Nov 7 14:39:36 2001 +++ linux/include/linux/if_bonding.h Mon Jan 14 18:28:32 2002 @@ -79,6 +79,15 @@ u32 link_failure_count; } slave_t; +/* + * Here are the locking policies for the two bonding locks: + * + * 1) Get bond->lock when reading/writing slave list. + * 2) Get bond->ptrlock when reading/writing bond->current_slave. + * (It is unnecessary when the write-lock is put with bond->lock.) + * 3) When we lock with bond->ptrlock, we must lock with bond->lock + * beforehand. + */ typedef struct bonding { slave_t *next; slave_t *prev; diff -urN linux-2.5.2-pre11/include/linux/kbd_kern.h linux/include/linux/kbd_kern.h --- linux-2.5.2-pre11/include/linux/kbd_kern.h Mon Jan 14 18:28:25 2002 +++ linux/include/linux/kbd_kern.h Mon Jan 14 18:28:32 2002 @@ -1,6 +1,7 @@ #ifndef _KBD_KERN_H #define _KBD_KERN_H +#include #include #include diff -urN linux-2.5.2-pre11/include/linux/limits.h linux/include/linux/limits.h --- linux-2.5.2-pre11/include/linux/limits.h Wed Jul 28 10:30:10 1999 +++ linux/include/linux/limits.h Mon Jan 14 18:28:32 2002 @@ -11,7 +11,7 @@ #define MAX_CANON 255 /* size of the canonical input queue */ #define MAX_INPUT 255 /* size of the type-ahead buffer */ #define NAME_MAX 255 /* # chars in a file name */ -#define PATH_MAX 4095 /* # chars in a path name */ +#define PATH_MAX 4096 /* # chars in a path name including nul */ #define PIPE_BUF 4096 /* # bytes in atomic write to a pipe */ #define RTSIG_MAX 32 diff -urN linux-2.5.2-pre11/include/linux/netfilter_ipv4/ip_conntrack.h linux/include/linux/netfilter_ipv4/ip_conntrack.h --- linux-2.5.2-pre11/include/linux/netfilter_ipv4/ip_conntrack.h Tue Oct 30 15:08:12 2001 +++ linux/include/linux/netfilter_ipv4/ip_conntrack.h Mon Jan 14 18:28:32 2002 @@ -27,6 +27,21 @@ IP_CT_NUMBER = IP_CT_IS_REPLY * 2 - 1 }; +/* Bitset representing status of connection. */ +enum ip_conntrack_status { + /* It's an expected connection: bit 0 set. This bit never changed */ + IPS_EXPECTED_BIT = 0, + IPS_EXPECTED = (1 << IPS_EXPECTED_BIT), + + /* We've seen packets both ways: bit 1 set. Can be set, not unset. */ + IPS_SEEN_REPLY_BIT = 1, + IPS_SEEN_REPLY = (1 << IPS_SEEN_REPLY_BIT), + + /* Conntrack should never be early-expired. */ + IPS_ASSURED_BIT = 2, + IPS_ASSURED = (1 << IPS_ASSURED_BIT), +}; + #ifdef __KERNEL__ #include @@ -46,21 +61,6 @@ #else #define IP_NF_ASSERT(x) #endif - -/* Bitset representing status of connection. */ -enum ip_conntrack_status { - /* It's an expected connection: bit 0 set. This bit never changed */ - IPS_EXPECTED_BIT = 0, - IPS_EXPECTED = (1 << IPS_EXPECTED_BIT), - - /* We've seen packets both ways: bit 1 set. Can be set, not unset. */ - IPS_SEEN_REPLY_BIT = 1, - IPS_SEEN_REPLY = (1 << IPS_SEEN_REPLY_BIT), - - /* Conntrack should never be early-expired. */ - IPS_ASSURED_BIT = 2, - IPS_ASSURED = (1 << IPS_ASSURED_BIT), -}; struct ip_conntrack_expect { diff -urN linux-2.5.2-pre11/include/linux/netfilter_ipv4/ip_conntrack_tuple.h linux/include/linux/netfilter_ipv4/ip_conntrack_tuple.h --- linux-2.5.2-pre11/include/linux/netfilter_ipv4/ip_conntrack_tuple.h Thu Jul 26 13:58:26 2001 +++ linux/include/linux/netfilter_ipv4/ip_conntrack_tuple.h Mon Jan 14 18:28:32 2002 @@ -62,6 +62,13 @@ } dst; }; +enum ip_conntrack_dir +{ + IP_CT_DIR_ORIGINAL, + IP_CT_DIR_REPLY, + IP_CT_DIR_MAX +}; + #ifdef __KERNEL__ #define DUMP_TUPLE(tp) \ @@ -75,13 +82,19 @@ /* If we're the first tuple, it's the original dir. */ #define DIRECTION(h) ((enum ip_conntrack_dir)(&(h)->ctrack->tuplehash[1] == (h))) -enum ip_conntrack_dir +/* Connections have two entries in the hash table: one for each way */ +struct ip_conntrack_tuple_hash { - IP_CT_DIR_ORIGINAL, - IP_CT_DIR_REPLY, - IP_CT_DIR_MAX + struct list_head list; + + struct ip_conntrack_tuple tuple; + + /* this == &ctrack->tuplehash[DIRECTION(this)]. */ + struct ip_conntrack *ctrack; }; +#endif /* __KERNEL__ */ + static inline int ip_ct_tuple_src_equal(const struct ip_conntrack_tuple *t1, const struct ip_conntrack_tuple *t2) { @@ -115,16 +128,4 @@ & mask->dst.protonum)); } -/* Connections have two entries in the hash table: one for each way */ -struct ip_conntrack_tuple_hash -{ - struct list_head list; - - struct ip_conntrack_tuple tuple; - - /* this == &ctrack->tuplehash[DIRECTION(this)]. */ - struct ip_conntrack *ctrack; -}; - -#endif /* __KERNEL__ */ #endif /* _IP_CONNTRACK_TUPLE_H */ diff -urN linux-2.5.2-pre11/include/linux/reiserfs_fs.h linux/include/linux/reiserfs_fs.h --- linux-2.5.2-pre11/include/linux/reiserfs_fs.h Mon Jan 14 18:28:25 2002 +++ linux/include/linux/reiserfs_fs.h Mon Jan 14 18:28:32 2002 @@ -1651,7 +1651,7 @@ #define _jhashfn(dev,block) \ ((((dev)<<(JBH_HASH_SHIFT - 6)) ^ ((dev)<<(JBH_HASH_SHIFT - 9))) ^ \ (((block)<<(JBH_HASH_SHIFT - 6)) ^ ((block) >> 13) ^ ((block) << (JBH_HASH_SHIFT - 12)))) -#define journal_hash(t,dev,block) ((t)[_jhashfn((kdev_t_to_nr(dev)),(block)) & JBH_HASH_MASK]) +#define journal_hash(t,sb,block) ((t)[_jhashfn((kdev_t_to_nr(sb->s_dev)),(block)) & JBH_HASH_MASK]) /* finds n'th buffer with 0 being the start of this commit. Needs to go away, j_ap_blocks has changed ** since I created this. One chunk of code in journal.c needs changing before deleting it @@ -1678,14 +1678,13 @@ int journal_lock_dobalance(struct super_block *p_s_sb) ; int journal_unlock_dobalance(struct super_block *p_s_sb) ; int journal_transaction_should_end(struct reiserfs_transaction_handle *, int) ; -int reiserfs_in_journal(struct super_block *p_s_sb, kdev_t dev, unsigned long bl, int size, int searchall, unsigned long *next) ; +int reiserfs_in_journal(struct super_block *p_s_sb, unsigned long bl, int searchall, unsigned long *next) ; int journal_begin(struct reiserfs_transaction_handle *, struct super_block *p_s_sb, unsigned long) ; int journal_join(struct reiserfs_transaction_handle *, struct super_block *p_s_sb, unsigned long) ; struct super_block *reiserfs_get_super(kdev_t dev) ; void flush_async_commits(struct super_block *p_s_sb) ; int remove_from_transaction(struct super_block *p_s_sb, unsigned long blocknr, int already_cleaned) ; -int remove_from_journal_list(struct super_block *s, struct reiserfs_journal_list *jl, struct buffer_head *bh, int remove_freed) ; int buffer_journaled(const struct buffer_head *bh) ; int mark_buffer_journal_new(struct buffer_head *bh) ; diff -urN linux-2.5.2-pre11/include/linux/reiserfs_fs_sb.h linux/include/linux/reiserfs_fs_sb.h --- linux-2.5.2-pre11/include/linux/reiserfs_fs_sb.h Sun Dec 16 15:43:25 2001 +++ linux/include/linux/reiserfs_fs_sb.h Mon Jan 14 18:28:32 2002 @@ -199,7 +199,7 @@ */ struct reiserfs_journal_cnode { struct buffer_head *bh ; /* real buffer head */ - kdev_t dev ; /* dev of real buffer head */ + struct super_block *sb ; /* dev of real buffer head */ unsigned long blocknr ; /* block number of real buffer head, == 0 when buffer on disk */ int state ; struct reiserfs_journal_list *jlist ; /* journal list this cnode lives in */ diff -urN linux-2.5.2-pre11/include/linux/sched.h linux/include/linux/sched.h --- linux-2.5.2-pre11/include/linux/sched.h Mon Jan 14 18:28:25 2002 +++ linux/include/linux/sched.h Mon Jan 14 18:28:32 2002 @@ -305,7 +305,7 @@ prio_array_t *array; unsigned int time_slice; - unsigned long swap_cnt_last; + unsigned long sleep_jtime; unsigned long policy; unsigned long cpus_allowed; diff -urN linux-2.5.2-pre11/include/linux/shmem_fs.h linux/include/linux/shmem_fs.h --- linux-2.5.2-pre11/include/linux/shmem_fs.h Wed Oct 10 07:53:57 2001 +++ linux/include/linux/shmem_fs.h Mon Jan 14 18:28:32 2002 @@ -11,7 +11,7 @@ * swapper address space. * * We have to move it here, since not every user of fs.h is including - * mm.h, but m.h is including fs.h via sched .h :-/ + * mm.h, but mm.h is including fs.h via sched .h :-/ */ typedef struct { unsigned long val; diff -urN linux-2.5.2-pre11/include/linux/socket.h linux/include/linux/socket.h --- linux-2.5.2-pre11/include/linux/socket.h Sun Dec 16 15:43:25 2001 +++ linux/include/linux/socket.h Mon Jan 14 18:28:32 2002 @@ -156,6 +156,7 @@ #define AF_IRDA 23 /* IRDA sockets */ #define AF_PPPOX 24 /* PPPoX sockets */ #define AF_WANPIPE 25 /* Wanpipe API Sockets */ +#define AF_LLC 26 /* Linux LLC */ #define AF_BLUETOOTH 31 /* Bluetooth sockets */ #define AF_MAX 32 /* For now.. */ @@ -187,6 +188,7 @@ #define PF_IRDA AF_IRDA #define PF_PPPOX AF_PPPOX #define PF_WANPIPE AF_WANPIPE +#define PF_LLC AF_LLC #define PF_BLUETOOTH AF_BLUETOOTH #define PF_MAX AF_MAX @@ -237,6 +239,8 @@ #define SOL_ATM 264 /* ATM layer (cell level) */ #define SOL_AAL 265 /* ATM Adaption Layer (packet level) */ #define SOL_IRDA 266 +#define SOL_NETBEUI 267 +#define SOL_LLC 268 /* IPX options */ #define IPX_TYPE 1 diff -urN linux-2.5.2-pre11/include/linux/sunrpc/clnt.h linux/include/linux/sunrpc/clnt.h --- linux-2.5.2-pre11/include/linux/sunrpc/clnt.h Mon Jan 14 18:28:25 2002 +++ linux/include/linux/sunrpc/clnt.h Mon Jan 14 18:28:32 2002 @@ -137,7 +137,6 @@ xprt_set_timeout(&clnt->cl_timeout, retr, incr); } -extern void rpciod_tcp_dispatcher(void); extern void rpciod_wake_up(void); /* diff -urN linux-2.5.2-pre11/include/linux/swap.h linux/include/linux/swap.h --- linux-2.5.2-pre11/include/linux/swap.h Sun Dec 16 15:43:25 2001 +++ linux/include/linux/swap.h Mon Jan 14 18:28:32 2002 @@ -65,8 +65,7 @@ unsigned int flags; kdev_t swap_device; spinlock_t sdev_lock; - struct dentry * swap_file; - struct vfsmount *swap_vfsmnt; + struct file *swap_file; unsigned short * swap_map; unsigned int lowest_bit; unsigned int highest_bit; @@ -141,8 +140,7 @@ extern int is_swap_partition(kdev_t); extern void si_swapinfo(struct sysinfo *); extern swp_entry_t get_swap_page(void); -extern void get_swaphandle_info(swp_entry_t, unsigned long *, kdev_t *, - struct inode **); +extern void get_swaphandle_info(swp_entry_t, unsigned long *, struct inode **); extern int swap_duplicate(swp_entry_t); extern int swap_count(struct page *); extern int valid_swaphandles(swp_entry_t, unsigned long *); diff -urN linux-2.5.2-pre11/include/math-emu/double.h linux/include/math-emu/double.h --- linux-2.5.2-pre11/include/math-emu/double.h Thu Dec 2 15:28:54 1999 +++ linux/include/math-emu/double.h Mon Jan 14 18:28:32 2002 @@ -22,6 +22,9 @@ not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#ifndef __MATH_EMU_DOUBLE_H__ +#define __MATH_EMU_DOUBLE_H__ + #if _FP_W_TYPE_SIZE < 32 #error "Here's a nickel kid. Go buy yourself a real computer." #endif @@ -197,3 +200,6 @@ #define _FP_FRAC_HIGH_RAW_D(X) _FP_FRAC_HIGH_1(X) #endif /* W_TYPE_SIZE < 64 */ + + +#endif /* __MATH_EMU_DOUBLE_H__ */ diff -urN linux-2.5.2-pre11/include/math-emu/extended.h linux/include/math-emu/extended.h --- linux-2.5.2-pre11/include/math-emu/extended.h Thu Dec 2 15:28:54 1999 +++ linux/include/math-emu/extended.h Mon Jan 14 18:28:32 2002 @@ -19,6 +19,10 @@ not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef __MATH_EMU_EXTENDED_H__ +#define __MATH_EMU_EXTENDED_H__ + #if _FP_W_TYPE_SIZE < 32 #error "Here's a nickel, kid. Go buy yourself a real computer." #endif @@ -388,3 +392,5 @@ #define _FP_FRAC_HIGH_RAW_E(X) (X##_f0) #endif /* not _FP_W_TYPE_SIZE < 64 */ + +#endif /* __MATH_EMU_EXTENDED_H__ */ diff -urN linux-2.5.2-pre11/include/math-emu/op-1.h linux/include/math-emu/op-1.h --- linux-2.5.2-pre11/include/math-emu/op-1.h Mon Dec 20 22:05:52 1999 +++ linux/include/math-emu/op-1.h Mon Jan 14 18:28:32 2002 @@ -22,6 +22,9 @@ not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#ifndef __MATH_EMU_OP_1_H__ +#define __MATH_EMU_OP_1_H__ + #define _FP_FRAC_DECL_1(X) _FP_W_TYPE X##_f #define _FP_FRAC_COPY_1(D,S) (D##_f = S##_f) #define _FP_FRAC_SET_1(X,I) (X##_f = I) @@ -295,3 +298,5 @@ else \ D##_f <<= _FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs; \ } while (0) + +#endif /* __MATH_EMU_OP_1_H__ */ diff -urN linux-2.5.2-pre11/include/math-emu/op-2.h linux/include/math-emu/op-2.h --- linux-2.5.2-pre11/include/math-emu/op-2.h Mon Feb 19 11:36:34 2001 +++ linux/include/math-emu/op-2.h Mon Jan 14 18:28:32 2002 @@ -22,6 +22,9 @@ not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#ifndef __MATH_EMU_OP_2_H__ +#define __MATH_EMU_OP_2_H__ + #define _FP_FRAC_DECL_2(X) _FP_W_TYPE X##_f0, X##_f1 #define _FP_FRAC_COPY_2(D,S) (D##_f0 = S##_f0, D##_f1 = S##_f1) #define _FP_FRAC_SET_2(X,I) __FP_FRAC_SET_2(X, I) @@ -606,3 +609,4 @@ _FP_FRAC_SLL_2(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs)); \ } while (0) +#endif diff -urN linux-2.5.2-pre11/include/math-emu/op-4.h linux/include/math-emu/op-4.h --- linux-2.5.2-pre11/include/math-emu/op-4.h Tue Aug 31 11:24:24 1999 +++ linux/include/math-emu/op-4.h Mon Jan 14 18:28:32 2002 @@ -22,6 +22,9 @@ not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#ifndef __MATH_EMU_OP_4_H__ +#define __MATH_EMU_OP_4_H__ + #define _FP_FRAC_DECL_4(X) _FP_W_TYPE X##_f[4] #define _FP_FRAC_COPY_4(D,S) \ (D##_f[0] = S##_f[0], D##_f[1] = S##_f[1], \ @@ -659,3 +662,4 @@ _FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs)); \ } while (0) +#endif diff -urN linux-2.5.2-pre11/include/math-emu/op-8.h linux/include/math-emu/op-8.h --- linux-2.5.2-pre11/include/math-emu/op-8.h Tue Aug 31 11:24:24 1999 +++ linux/include/math-emu/op-8.h Mon Jan 14 18:28:32 2002 @@ -21,6 +21,9 @@ not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#ifndef __MATH_EMU_OP_8_H__ +#define __MATH_EMU_OP_8_H__ + /* We need just a few things from here for op-4, if we ever need some other macros, they can be added. */ #define _FP_FRAC_DECL_8(X) _FP_W_TYPE X##_f[8] @@ -101,3 +104,4 @@ X##_f[0] |= (_s != 0); \ } while (0) +#endif diff -urN linux-2.5.2-pre11/include/math-emu/op-common.h linux/include/math-emu/op-common.h --- linux-2.5.2-pre11/include/math-emu/op-common.h Thu Dec 2 15:28:54 1999 +++ linux/include/math-emu/op-common.h Mon Jan 14 18:28:32 2002 @@ -21,6 +21,9 @@ not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#ifndef __MATH_EMU_OP_COMMON_H__ +#define __MATH_EMU_OP_COMMON_H__ + #define _FP_DECL(wc, X) \ _FP_I_TYPE X##_c, X##_s, X##_e; \ _FP_FRAC_DECL_##wc(X) @@ -846,3 +849,4 @@ q = n / d, r = n % d; \ } while (0) +#endif /* __MATH_EMU_OP_COMMON_H__ */ diff -urN linux-2.5.2-pre11/include/math-emu/quad.h linux/include/math-emu/quad.h --- linux-2.5.2-pre11/include/math-emu/quad.h Thu Dec 2 15:28:54 1999 +++ linux/include/math-emu/quad.h Mon Jan 14 18:28:32 2002 @@ -22,6 +22,9 @@ not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#ifndef __MATH_EMU_QUAD_H__ +#define __MATH_EMU_QUAD_H__ + #if _FP_W_TYPE_SIZE < 32 #error "Here's a nickel, kid. Go buy yourself a real computer." #endif @@ -201,3 +204,5 @@ #define _FP_FRAC_HIGH_RAW_Q(X) _FP_FRAC_HIGH_2(X) #endif /* not _FP_W_TYPE_SIZE < 64 */ + +#endif /* __MATH_EMU_QUAD_H__ */ diff -urN linux-2.5.2-pre11/include/math-emu/single.h linux/include/math-emu/single.h --- linux-2.5.2-pre11/include/math-emu/single.h Thu Dec 2 15:28:54 1999 +++ linux/include/math-emu/single.h Mon Jan 14 18:28:32 2002 @@ -22,6 +22,9 @@ not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#ifndef __MATH_EMU_SINGLE_H__ +#define __MATH_EMU_SINGLE_H__ + #if _FP_W_TYPE_SIZE < 32 #error "Here's a nickel kid. Go buy yourself a real computer." #endif @@ -109,3 +112,5 @@ #define _FP_FRAC_HIGH_S(X) _FP_FRAC_HIGH_1(X) #define _FP_FRAC_HIGH_RAW_S(X) _FP_FRAC_HIGH_1(X) + +#endif /* __MATH_EMU_SINGLE_H__ */ diff -urN linux-2.5.2-pre11/include/math-emu/soft-fp.h linux/include/math-emu/soft-fp.h --- linux-2.5.2-pre11/include/math-emu/soft-fp.h Thu Dec 2 15:28:54 1999 +++ linux/include/math-emu/soft-fp.h Mon Jan 14 18:28:32 2002 @@ -21,8 +21,8 @@ not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#ifndef SOFT_FP_H -#define SOFT_FP_H +#ifndef __MATH_EMU_SOFT_FP_H__ +#define __MATH_EMU_SOFT_FP_H__ #include @@ -178,4 +178,4 @@ #include #endif -#endif +#endif /* __MATH_EMU_SOFT_FP_H__ */ diff -urN linux-2.5.2-pre11/kernel/ksyms.c linux/kernel/ksyms.c --- linux-2.5.2-pre11/kernel/ksyms.c Mon Jan 14 18:28:25 2002 +++ linux/kernel/ksyms.c Mon Jan 14 18:28:32 2002 @@ -511,7 +511,7 @@ EXPORT_SYMBOL(___strtok); EXPORT_SYMBOL(init_special_inode); EXPORT_SYMBOL(read_ahead); -EXPORT_SYMBOL(get_hash_table); +EXPORT_SYMBOL(__get_hash_table); EXPORT_SYMBOL(get_empty_inode); EXPORT_SYMBOL(insert_inode_hash); EXPORT_SYMBOL(remove_inode_hash); diff -urN linux-2.5.2-pre11/kernel/sched.c linux/kernel/sched.c --- linux-2.5.2-pre11/kernel/sched.c Mon Jan 14 18:28:25 2002 +++ linux/kernel/sched.c Mon Jan 14 18:28:32 2002 @@ -21,6 +21,9 @@ #include #define BITMAP_SIZE ((MAX_PRIO+7)/8) +#define PRIO_INTERACTIVE (MAX_RT_PRIO + (MAX_PRIO - MAX_RT_PRIO) / 4) +#define TASK_INTERACTIVE(p) ((p)->prio >= MAX_RT_PRIO && (p)->prio <= PRIO_INTERACTIVE) +#define JSLEEP_TO_PRIO(t) (((t) * 20) / HZ) typedef struct runqueue runqueue_t; @@ -48,7 +51,6 @@ spinlock_t lock; unsigned long nr_running, nr_switches; task_t *curr, *idle; - unsigned long swap_cnt; prio_array_t *active, *expired, arrays[2]; char __pad [SMP_CACHE_BYTES]; } runqueues [NR_CPUS] __cacheline_aligned; @@ -97,7 +99,7 @@ prio_array_t *array = rq->active; if (!rt_task(p)) { - unsigned long prio_bonus = rq->swap_cnt - p->swap_cnt_last; + unsigned long prio_bonus = JSLEEP_TO_PRIO(jiffies - p->sleep_jtime); if (prio_bonus > MAX_PRIO) prio_bonus = MAX_PRIO; @@ -114,7 +116,7 @@ rq->nr_running--; dequeue_task(p, p->array); p->array = NULL; - p->swap_cnt_last = rq->swap_cnt; + p->sleep_jtime = jiffies; } static inline void resched_task(task_t *p) @@ -448,7 +450,10 @@ p->prio = MAX_PRIO - 1; } p->time_slice = time_slice; - enqueue_task(p, rq->expired); + if (TASK_INTERACTIVE(p)) + enqueue_task(p, rq->active); + else + enqueue_task(p, rq->expired); } spin_unlock_irqrestore(&rq->lock, flags); } @@ -475,14 +480,14 @@ spin_lock_irq(&rq->lock); switch (prev->state) { - case TASK_INTERRUPTIBLE: - if (unlikely(signal_pending(prev))) { - prev->state = TASK_RUNNING; - break; - } - default: - deactivate_task(prev, rq); - case TASK_RUNNING: + case TASK_INTERRUPTIBLE: + if (unlikely(signal_pending(prev))) { + prev->state = TASK_RUNNING; + break; + } + default: + deactivate_task(prev, rq); + case TASK_RUNNING: } pick_next_task: if (unlikely(!rq->nr_running)) { @@ -501,7 +506,6 @@ rq->active = rq->expired; rq->expired = array; array = rq->active; - rq->swap_cnt++; } idx = sched_find_first_zero_bit(array->bitmap); @@ -1187,7 +1191,6 @@ rq->expired = rq->arrays + 1; spin_lock_init(&rq->lock); rq->cpu = i; - rq->swap_cnt = 0; for (j = 0; j < 2; j++) { array = rq->arrays + j; diff -urN linux-2.5.2-pre11/lib/Config.in linux/lib/Config.in --- linux-2.5.2-pre11/lib/Config.in Wed Dec 31 16:00:00 1969 +++ linux/lib/Config.in Mon Jan 14 18:28:32 2002 @@ -0,0 +1,8 @@ +# +# Library configuration +# +mainmenu_option next_comment +comment 'Library routines' + +tristate 'CRC32 functions' CONFIG_CRC32 +endmenu diff -urN linux-2.5.2-pre11/lib/Makefile linux/lib/Makefile --- linux-2.5.2-pre11/lib/Makefile Mon Sep 17 15:31:15 2001 +++ linux/lib/Makefile Mon Jan 14 18:28:32 2002 @@ -8,7 +8,7 @@ L_TARGET := lib.a -export-objs := cmdline.o dec_and_lock.o rwsem-spinlock.o rwsem.o +export-objs := cmdline.o dec_and_lock.o rwsem-spinlock.o rwsem.o crc32.o obj-y := errno.o ctype.o string.o vsprintf.o brlock.o cmdline.o bust_spinlocks.o rbtree.o @@ -18,5 +18,10 @@ ifneq ($(CONFIG_HAVE_DEC_LOCK),y) obj-y += dec_and_lock.o endif + +obj-$(CONFIG_CRC32) += crc32.o +include $(TOPDIR)/drivers/net/Makefile.lib +include $(TOPDIR)/drivers/usb/Makefile.lib +include $(TOPDIR)/fs/Makefile.lib include $(TOPDIR)/Rules.make diff -urN linux-2.5.2-pre11/lib/crc32.c linux/lib/crc32.c --- linux-2.5.2-pre11/lib/crc32.c Wed Dec 31 16:00:00 1969 +++ linux/lib/crc32.c Mon Jan 14 18:28:32 2002 @@ -0,0 +1,571 @@ +/* + * Oct 15, 2000 Matt Domsch + * Nicer crc32 functions/docs submitted by linux@horizon.com. Thanks! + * + * Oct 12, 2000 Matt Domsch + * Same crc32 function was used in 5 other places in the kernel. + * I made one version, and deleted the others. + * There are various incantations of crc32(). Some use a seed of 0 or ~0. + * Some xor at the end with ~0. The generic crc32() function takes + * seed as an argument, and doesn't xor at the end. Then individual + * users can do whatever they need. + * drivers/net/smc9194.c uses seed ~0, doesn't xor with ~0. + * fs/jffs2 uses seed 0, doesn't xor with ~0. + * fs/partitions/efi.c uses seed ~0, xor's with ~0. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#if __GNUC__ >= 3 /* 2.x has "attribute", but only 3.0 has "pure */ +#define attribute(x) __attribute__(x) +#else +#define attribute(x) +#endif + +/* + * This code is in the public domain; copyright abandoned. + * Liability for non-performance of this code is limited to the amount + * you paid for it. Since it is distributed for free, your refund will + * be very very small. If it breaks, you get to keep both pieces. + */ + +MODULE_AUTHOR("Matt Domsch "); +MODULE_DESCRIPTION("Ethernet CRC32 calculations"); +MODULE_LICENSE("GPL and additional rights"); + + +/* + * There are multiple 16-bit CRC polynomials in common use, but this is + * *the* standard CRC-32 polynomial, first popularized by Ethernet. + * x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1+x^0 + */ +#define CRCPOLY_LE 0xedb88320 +#define CRCPOLY_BE 0x04c11db7 + +/* How many bits at a time to use. Requires a table of 4< 8 || CRC_LE_BITS < 1 || CRC_LE_BITS & CRC_LE_BITS-1 +# error CRC_LE_BITS must be a power of 2 between 1 and 8 +#endif + +#if CRC_LE_BITS == 1 +/* + * In fact, the table-based code will work in this case, but it can be + * simplified by inlining the table in ?: form. + */ +#define crc32init_le() +#define crc32cleanup_le() +/** + * crc32_le() - Calculate bitwise little-endian Ethernet AUTODIN II CRC32 + * @crc - seed value for computation. ~0 for Ethernet, sometimes 0 for + * other uses, or the previous crc32 value if computing incrementally. + * @p - pointer to buffer over which CRC is run + * @len - length of buffer @p + * + */ +u32 attribute((pure)) crc32_le(u32 crc, unsigned char const *p, size_t len) +{ + int i; + while (len--) { + crc ^= *p++; + for (i = 0; i < 8; i++) + crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0); + } + return crc; +} +#else /* Table-based approach */ + +static u32 *crc32table_le; +/** + * crc32init_le() - allocate and initialize LE table data + * + * crc is the crc of the byte i; other entries are filled in based on the + * fact that crctable[i^j] = crctable[i] ^ crctable[j]. + * + */ +static int __init crc32init_le(void) +{ + unsigned i, j; + u32 crc = 1; + + crc32table_le = + kmalloc((1 << CRC_LE_BITS) * sizeof(u32), GFP_KERNEL); + if (!crc32table_le) + return 1; + crc32table_le[0] = 0; + + for (i = 1 << (CRC_LE_BITS - 1); i; i >>= 1) { + crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0); + for (j = 0; j < 1 << CRC_LE_BITS; j += 2 * i) + crc32table_le[i + j] = crc ^ crc32table_le[j]; + } + return 0; +} + +/** + * crc32cleanup_le(): free LE table data + */ +static void __exit crc32cleanup_le(void) +{ + if (crc32table_le) kfree(crc32table_le); + crc32table_le = NULL; +} + +/** + * crc32_le() - Calculate bitwise little-endian Ethernet AUTODIN II CRC32 + * @crc - seed value for computation. ~0 for Ethernet, sometimes 0 for + * other uses, or the previous crc32 value if computing incrementally. + * @p - pointer to buffer over which CRC is run + * @len - length of buffer @p + * + */ +u32 attribute((pure)) crc32_le(u32 crc, unsigned char const *p, size_t len) +{ + while (len--) { +# if CRC_LE_BITS == 8 + crc = (crc >> 8) ^ crc32table_le[(crc ^ *p++) & 255]; +# elif CRC_LE_BITS == 4 + crc ^= *p++; + crc = (crc >> 4) ^ crc32table_le[crc & 15]; + crc = (crc >> 4) ^ crc32table_le[crc & 15]; +# elif CRC_LE_BITS == 2 + crc ^= *p++; + crc = (crc >> 2) ^ crc32table_le[crc & 3]; + crc = (crc >> 2) ^ crc32table_le[crc & 3]; + crc = (crc >> 2) ^ crc32table_le[crc & 3]; + crc = (crc >> 2) ^ crc32table_le[crc & 3]; +# endif + } + return crc; +} +#endif + +/* + * Big-endian CRC computation. Used with serial bit streams sent + * msbit-first. Be sure to use cpu_to_be32() to append the computed CRC. + */ +#if CRC_BE_BITS > 8 || CRC_BE_BITS < 1 || CRC_BE_BITS & CRC_BE_BITS-1 +# error CRC_BE_BITS must be a power of 2 between 1 and 8 +#endif + +#if CRC_BE_BITS == 1 +/* + * In fact, the table-based code will work in this case, but it can be + * simplified by inlining the table in ?: form. + */ +#define crc32init_be() +#define crc32cleanup_be() + +/** + * crc32_be() - Calculate bitwise big-endian Ethernet AUTODIN II CRC32 + * @crc - seed value for computation. ~0 for Ethernet, sometimes 0 for + * other uses, or the previous crc32 value if computing incrementally. + * @p - pointer to buffer over which CRC is run + * @len - length of buffer @p + * + */ +u32 attribute((pure)) crc32_be(u32 crc, unsigned char const *p, size_t len) +{ + int i; + while (len--) { + crc ^= *p++ << 24; + for (i = 0; i < 8; i++) + crc = + (crc << 1) ^ ((crc & 0x80000000) ? CRCPOLY_BE : + 0); + } + return crc; +} + +#else /* Table-based approach */ +static u32 *crc32table_be; + +/** + * crc32init_be() - allocate and initialize BE table data + */ +static int __init crc32init_be(void) +{ + unsigned i, j; + u32 crc = 0x80000000; + + crc32table_be = + kmalloc((1 << CRC_BE_BITS) * sizeof(u32), GFP_KERNEL); + if (!crc32table_be) + return 1; + crc32table_be[0] = 0; + + for (i = 1; i < 1 << CRC_BE_BITS; i <<= 1) { + crc = (crc << 1) ^ ((crc & 0x80000000) ? CRCPOLY_BE : 0); + for (j = 0; j < i; j++) + crc32table_be[i + j] = crc ^ crc32table_be[j]; + } + return 0; +} + +/** + * crc32cleanup_be(): free BE table data + */ +static void __exit crc32cleanup_be(void) +{ + if (crc32table_be) kfree(crc32table_be); + crc32table_be = NULL; +} + + +/** + * crc32_be() - Calculate bitwise big-endian Ethernet AUTODIN II CRC32 + * @crc - seed value for computation. ~0 for Ethernet, sometimes 0 for + * other uses, or the previous crc32 value if computing incrementally. + * @p - pointer to buffer over which CRC is run + * @len - length of buffer @p + * + */ +u32 attribute((pure)) crc32_be(u32 crc, unsigned char const *p, size_t len) +{ + while (len--) { +# if CRC_BE_BITS == 8 + crc = (crc << 8) ^ crc32table_be[(crc >> 24) ^ *p++]; +# elif CRC_BE_BITS == 4 + crc ^= *p++ << 24; + crc = (crc << 4) ^ crc32table_be[crc >> 28]; + crc = (crc << 4) ^ crc32table_be[crc >> 28]; +# elif CRC_BE_BITS == 2 + crc ^= *p++ << 24; + crc = (crc << 2) ^ crc32table_be[crc >> 30]; + crc = (crc << 2) ^ crc32table_be[crc >> 30]; + crc = (crc << 2) ^ crc32table_be[crc >> 30]; + crc = (crc << 2) ^ crc32table_be[crc >> 30]; +# endif + } + return crc; +} +#endif + +/* + * A brief CRC tutorial. + * + * A CRC is a long-division remainder. You add the CRC to the message, + * and the whole thing (message+CRC) is a multiple of the given + * CRC polynomial. To check the CRC, you can either check that the + * CRC matches the recomputed value, *or* you can check that the + * remainder computed on the message+CRC is 0. This latter approach + * is used by a lot of hardware implementations, and is why so many + * protocols put the end-of-frame flag after the CRC. + * + * It's actually the same long division you learned in school, except that + * - We're working in binary, so the digits are only 0 and 1, and + * - When dividing polynomials, there are no carries. Rather than add and + * subtract, we just xor. Thus, we tend to get a bit sloppy about + * the difference between adding and subtracting. + * + * A 32-bit CRC polynomial is actually 33 bits long. But since it's + * 33 bits long, bit 32 is always going to be set, so usually the CRC + * is written in hex with the most significant bit omitted. (If you're + * familiar with the IEEE 754 floating-point format, it's the same idea.) + * + * Note that a CRC is computed over a string of *bits*, so you have + * to decide on the endianness of the bits within each byte. To get + * the best error-detecting properties, this should correspond to the + * order they're actually sent. For example, standard RS-232 serial is + * little-endian; the most significant bit (sometimes used for parity) + * is sent last. And when appending a CRC word to a message, you should + * do it in the right order, matching the endianness. + * + * Just like with ordinary division, the remainder is always smaller than + * the divisor (the CRC polynomial) you're dividing by. Each step of the + * division, you take one more digit (bit) of the dividend and append it + * to the current remainder. Then you figure out the appropriate multiple + * of the divisor to subtract to being the remainder back into range. + * In binary, it's easy - it has to be either 0 or 1, and to make the + * XOR cancel, it's just a copy of bit 32 of the remainder. + * + * When computing a CRC, we don't care about the quotient, so we can + * throw the quotient bit away, but subtract the appropriate multiple of + * the polynomial from the remainder and we're back to where we started, + * ready to process the next bit. + * + * A big-endian CRC written this way would be coded like: + * for (i = 0; i < input_bits; i++) { + * multiple = remainder & 0x80000000 ? CRCPOLY : 0; + * remainder = (remainder << 1 | next_input_bit()) ^ multiple; + * } + * Notice how, to get at bit 32 of the shifted remainder, we look + * at bit 31 of the remainder *before* shifting it. + * + * But also notice how the next_input_bit() bits we're shifting into + * the remainder don't actually affect any decision-making until + * 32 bits later. Thus, the first 32 cycles of this are pretty boring. + * Also, to add the CRC to a message, we need a 32-bit-long hole for it at + * the end, so we have to add 32 extra cycles shifting in zeros at the + * end of every message, + * + * So the standard trick is to rearrage merging in the next_input_bit() + * until the moment it's needed. Then the first 32 cycles can be precomputed, + * and merging in the final 32 zero bits to make room for the CRC can be + * skipped entirely. + * This changes the code to: + * for (i = 0; i < input_bits; i++) { + * remainder ^= next_input_bit() << 31; + * multiple = (remainder & 0x80000000) ? CRCPOLY : 0; + * remainder = (remainder << 1) ^ multiple; + * } + * With this optimization, the little-endian code is simpler: + * for (i = 0; i < input_bits; i++) { + * remainder ^= next_input_bit(); + * multiple = (remainder & 1) ? CRCPOLY : 0; + * remainder = (remainder >> 1) ^ multiple; + * } + * + * Note that the other details of endianness have been hidden in CRCPOLY + * (which must be bit-reversed) and next_input_bit(). + * + * However, as long as next_input_bit is returning the bits in a sensible + * order, we can actually do the merging 8 or more bits at a time rather + * than one bit at a time: + * for (i = 0; i < input_bytes; i++) { + * remainder ^= next_input_byte() << 24; + * for (j = 0; j < 8; j++) { + * multiple = (remainder & 0x80000000) ? CRCPOLY : 0; + * remainder = (remainder << 1) ^ multiple; + * } + * } + * Or in little-endian: + * for (i = 0; i < input_bytes; i++) { + * remainder ^= next_input_byte(); + * for (j = 0; j < 8; j++) { + * multiple = (remainder & 1) ? CRCPOLY : 0; + * remainder = (remainder << 1) ^ multiple; + * } + * } + * If the input is a multiple of 32 bits, you can even XOR in a 32-bit + * word at a time and increase the inner loop count to 32. + * + * You can also mix and match the two loop styles, for example doing the + * bulk of a message byte-at-a-time and adding bit-at-a-time processing + * for any fractional bytes at the end. + * + * The only remaining optimization is to the byte-at-a-time table method. + * Here, rather than just shifting one bit of the remainder to decide + * in the correct multiple to subtract, we can shift a byte at a time. + * This produces a 40-bit (rather than a 33-bit) intermediate remainder, + * but again the multiple of the polynomial to subtract depends only on + * the high bits, the high 8 bits in this case. + * + * The multile we need in that case is the low 32 bits of a 40-bit + * value whose high 8 bits are given, and which is a multiple of the + * generator polynomial. This is simply the CRC-32 of the given + * one-byte message. + * + * Two more details: normally, appending zero bits to a message which + * is already a multiple of a polynomial produces a larger multiple of that + * polynomial. To enable a CRC to detect this condition, it's common to + * invert the CRC before appending it. This makes the remainder of the + * message+crc come out not as zero, but some fixed non-zero value. + * + * The same problem applies to zero bits prepended to the message, and + * a similar solution is used. Instead of starting with a remainder of + * 0, an initial remainder of all ones is used. As long as you start + * the same way on decoding, it doesn't make a difference. + */ + +#if UNITTEST + +#include +#include + +#if 0 /*Not used at present */ +static void +buf_dump(char const *prefix, unsigned char const *buf, size_t len) +{ + fputs(prefix, stdout); + while (len--) + printf(" %02x", *buf++); + putchar('\n'); + +} +#endif + +static u32 attribute((const)) bitreverse(u32 x) +{ + x = (x >> 16) | (x << 16); + x = (x >> 8 & 0x00ff00ff) | (x << 8 & 0xff00ff00); + x = (x >> 4 & 0x0f0f0f0f) | (x << 4 & 0xf0f0f0f0); + x = (x >> 2 & 0x33333333) | (x << 2 & 0xcccccccc); + x = (x >> 1 & 0x55555555) | (x << 1 & 0xaaaaaaaa); + return x; +} + +static void bytereverse(unsigned char *buf, size_t len) +{ + while (len--) { + unsigned char x = *buf; + x = (x >> 4) | (x << 4); + x = (x >> 2 & 0x33) | (x << 2 & 0xcc); + x = (x >> 1 & 0x55) | (x << 1 & 0xaa); + *buf++ = x; + } +} + +static void random_garbage(unsigned char *buf, size_t len) +{ + while (len--) + *buf++ = (unsigned char) random(); +} + +#if 0 /* Not used at present */ +static void store_le(u32 x, unsigned char *buf) +{ + buf[0] = (unsigned char) x; + buf[1] = (unsigned char) (x >> 8); + buf[2] = (unsigned char) (x >> 16); + buf[3] = (unsigned char) (x >> 24); +} +#endif + +static void store_be(u32 x, unsigned char *buf) +{ + buf[0] = (unsigned char) (x >> 24); + buf[1] = (unsigned char) (x >> 16); + buf[2] = (unsigned char) (x >> 8); + buf[3] = (unsigned char) x; +} + +/* + * This checks that CRC(buf + CRC(buf)) = 0, and that + * CRC commutes with bit-reversal. This has the side effect + * of bytewise bit-reversing the input buffer, and returns + * the CRC of the reversed buffer. + */ +static u32 test_step(u32 init, unsigned char *buf, size_t len) +{ + u32 crc1, crc2; + size_t i; + + crc1 = crc32_be(init, buf, len); + store_be(crc1, buf + len); + crc2 = crc32_be(init, buf, len + 4); + if (crc2) + printf("\nCRC cancellation fail: 0x%08x should be 0\n", + crc2); + + for (i = 0; i <= len + 4; i++) { + crc2 = crc32_be(init, buf, i); + crc2 = crc32_be(crc2, buf + i, len + 4 - i); + if (crc2) + printf("\nCRC split fail: 0x%08x\n", crc2); + } + + /* Now swap it around for the other test */ + + bytereverse(buf, len + 4); + init = bitreverse(init); + crc2 = bitreverse(crc1); + if (crc1 != bitreverse(crc2)) + printf("\nBit reversal fail: 0x%08x -> %0x08x -> 0x%08x\n", + crc1, crc2, bitreverse(crc2)); + crc1 = crc32_le(init, buf, len); + if (crc1 != crc2) + printf("\nCRC endianness fail: 0x%08x != 0x%08x\n", crc1, + crc2); + crc2 = crc32_le(init, buf, len + 4); + if (crc2) + printf("\nCRC cancellation fail: 0x%08x should be 0\n", + crc2); + + for (i = 0; i <= len + 4; i++) { + crc2 = crc32_le(init, buf, i); + crc2 = crc32_le(crc2, buf + i, len + 4 - i); + if (crc2) + printf("\nCRC split fail: 0x%08x\n", crc2); + } + + return crc1; +} + +#define SIZE 64 +#define INIT1 0 +#define INIT2 0 + +int main(void) +{ + unsigned char buf1[SIZE + 4]; + unsigned char buf2[SIZE + 4]; + unsigned char buf3[SIZE + 4]; + int i, j; + u32 crc1, crc2, crc3; + + crc32init_le(); + crc32init_be(); + + for (i = 0; i <= SIZE; i++) { + printf("\rTesting length %d...", i); + fflush(stdout); + random_garbage(buf1, i); + random_garbage(buf2, i); + for (j = 0; j < i; j++) + buf3[j] = buf1[j] ^ buf2[j]; + + crc1 = test_step(INIT1, buf1, i); + crc2 = test_step(INIT2, buf2, i); + /* Now check that CRC(buf1 ^ buf2) = CRC(buf1) ^ CRC(buf2) */ + crc3 = test_step(INIT1 ^ INIT2, buf3, i); + if (crc3 != (crc1 ^ crc2)) + printf("CRC XOR fail: 0x%08x != 0x%08x ^ 0x%08x\n", + crc3, crc1, crc2); + } + printf("\nAll test complete. No failures expected.\n"); + return 0; +} + +#endif /* UNITTEST */ + +/** + * init_crc32(): generates CRC32 tables + * + * On successful initialization, use count is increased. + * This guarantees that the library functions will stay resident + * in memory, and prevents someone from 'rmmod crc32' while + * a driver that needs it is still loaded. + * This also greatly simplifies drivers, as there's no need + * to call an initialization/cleanup function from each driver. + * Since crc32.o is a library module, there's no requirement + * that the user can unload it. + */ +static int __init init_crc32(void) +{ + int rc1, rc2, rc; + rc1 = crc32init_le(); + rc2 = crc32init_be(); + rc = rc1 || rc2; + if (!rc) MOD_INC_USE_COUNT; + return rc; +} + +/** + * cleanup_crc32(): frees crc32 data when no longer needed + */ +static void cleanup_crc32(void) +{ + crc32cleanup_le(); + crc32cleanup_be(); +} + +module_init(init_crc32); +module_exit(cleanup_crc32); + +EXPORT_SYMBOL(crc32_le); +EXPORT_SYMBOL(crc32_be); diff -urN linux-2.5.2-pre11/mm/bootmem.c linux/mm/bootmem.c --- linux-2.5.2-pre11/mm/bootmem.c Tue Nov 27 09:23:27 2001 +++ linux/mm/bootmem.c Mon Jan 14 18:28:32 2002 @@ -155,6 +155,12 @@ if (align & (align-1)) BUG(); + offset = 0; + if (align && + (bdata->node_boot_start & (align - 1UL)) != 0) + offset = (align - (bdata->node_boot_start & (align - 1UL))); + offset >>= PAGE_SHIFT; + /* * We try to allocate bootmem pages above 'goal' * first, then we try to allocate lower pages. @@ -166,6 +172,7 @@ preferred = 0; preferred = ((preferred + align - 1) & ~(align - 1)) >> PAGE_SHIFT; + preferred += offset; areasize = (size+PAGE_SIZE-1)/PAGE_SIZE; incr = align >> PAGE_SHIFT ? : 1; @@ -185,7 +192,7 @@ fail_block:; } if (preferred) { - preferred = 0; + preferred = offset; goto restart_scan; } return NULL; diff -urN linux-2.5.2-pre11/mm/highmem.c linux/mm/highmem.c --- linux-2.5.2-pre11/mm/highmem.c Mon Jan 14 18:28:25 2002 +++ linux/mm/highmem.c Mon Jan 14 18:28:32 2002 @@ -25,7 +25,7 @@ static void *page_pool_alloc(int gfp_mask, void *data) { - int gfp = gfp_mask | (int) data; + int gfp = gfp_mask | (int) (long) data; return alloc_page(gfp); } diff -urN linux-2.5.2-pre11/mm/page_io.c linux/mm/page_io.c --- linux-2.5.2-pre11/mm/page_io.c Mon Jan 14 18:28:25 2002 +++ linux/mm/page_io.c Mon Jan 14 18:28:32 2002 @@ -38,9 +38,9 @@ unsigned long offset; sector_t zones[PAGE_SIZE/512]; int zones_used; - kdev_t dev = NODEV; int block_size; struct inode *swapf = 0; + struct block_device *bdev; if (rw == READ) { ClearPageUptodate(page); @@ -48,12 +48,13 @@ } else kstat.pswpout++; - get_swaphandle_info(entry, &offset, &dev, &swapf); - if (!kdev_none(dev)) { + get_swaphandle_info(entry, &offset, &swapf); + bdev = swapf->i_bdev; + if (bdev) { zones[0] = offset; zones_used = 1; block_size = PAGE_SIZE; - } else if (swapf) { + } else { int i, j; unsigned int block = offset << (PAGE_SHIFT - swapf->i_sb->s_blocksize_bits); @@ -65,13 +66,11 @@ return 0; } zones_used = i; - dev = swapf->i_dev; - } else { - return 0; + bdev = swapf->i_sb->s_bdev; } /* block_size == PAGE_SIZE/zones_used */ - brw_page(rw, page, dev, zones, block_size); + brw_page(rw, page, bdev, zones, block_size); /* Note! For consistency we do all of the logic, * decrementing the page count, and unlocking the page in the diff -urN linux-2.5.2-pre11/mm/swapfile.c linux/mm/swapfile.c --- linux-2.5.2-pre11/mm/swapfile.c Mon Jan 14 18:28:25 2002 +++ linux/mm/swapfile.c Mon Jan 14 18:28:32 2002 @@ -11,7 +11,6 @@ #include #include #include -#include /* for blk_size */ #include #include #include @@ -713,6 +712,7 @@ { struct swap_info_struct * p = NULL; unsigned short *swap_map; + struct file *swap_file; struct nameidata nd; int i, type, prev; int err; @@ -730,8 +730,8 @@ for (type = swap_list.head; type >= 0; type = swap_info[type].next) { p = swap_info + type; if ((p->flags & SWP_WRITEOK) == SWP_WRITEOK) { - if (p->swap_file == nd.dentry) - break; + if (p->swap_file->f_dentry == nd.dentry) + break; } prev = type; } @@ -774,15 +774,9 @@ swap_list_unlock(); goto out_dput; } - if (!kdev_none(p->swap_device)) - blkdev_put(p->swap_file->d_inode->i_bdev, BDEV_SWAP); - path_release(&nd); - swap_list_lock(); swap_device_lock(p); - nd.mnt = p->swap_vfsmnt; - nd.dentry = p->swap_file; - p->swap_vfsmnt = NULL; + swap_file = p->swap_file; p->swap_file = NULL; p->swap_device = NODEV; p->max = 0; @@ -792,6 +786,7 @@ swap_device_unlock(p); swap_list_unlock(); vfree(swap_map); + filp_close(swap_file, NULL); err = 0; out_dput: @@ -813,7 +808,8 @@ len = sprintf(buf, "Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n"); for (i = 0 ; i < nr_swapfiles ; i++, ptr++) { if ((ptr->flags & SWP_USED) && ptr->swap_map) { - char * path = d_path(ptr->swap_file, ptr->swap_vfsmnt, + char * path = d_path(ptr->swap_file->f_dentry, + ptr->swap_file->f_vfsmnt, page, PAGE_SIZE); int j, usedswap = 0; for (j = 0; j < ptr->max; ++j) @@ -826,7 +822,7 @@ } len += sprintf(buf + len, "%-39s %s\t%d\t%d\t%d\n", path, - kdev_none(ptr->swap_device) ? "file\t" : "partition", + !kdev_none(ptr->swap_device) ? "partition" : "file\t", ptr->pages << (PAGE_SHIFT - 10), usedswap << (PAGE_SHIFT - 10), ptr->prio); @@ -856,8 +852,9 @@ asmlinkage long sys_swapon(const char * specialfile, int swap_flags) { struct swap_info_struct * p; - struct nameidata nd; - struct inode * swap_inode; + char *name; + struct file *swap_file = NULL; + struct address_space *mapping; unsigned int type; int i, j, prev; int error; @@ -867,7 +864,6 @@ int nr_good_pages = 0; unsigned long maxpages = 1; int swapfilesize; - struct block_device *bdev = NULL; unsigned short *swap_map; if (!capable(CAP_SYS_ADMIN)) @@ -887,7 +883,6 @@ nr_swapfiles = type+1; p->flags = SWP_USED; p->swap_file = NULL; - p->swap_vfsmnt = NULL; p->swap_device = NODEV; p->swap_map = NULL; p->lowest_bit = 0; @@ -902,53 +897,33 @@ p->prio = --least_priority; } swap_list_unlock(); - error = user_path_walk(specialfile, &nd); + name = getname(specialfile); + error = PTR_ERR(name); + if (IS_ERR(name)) + goto bad_swap_2; + swap_file = filp_open(name, O_RDWR, 0); + putname(name); + error = PTR_ERR(swap_file); if (error) goto bad_swap_2; - p->swap_file = nd.dentry; - p->swap_vfsmnt = nd.mnt; - swap_inode = nd.dentry->d_inode; - error = -EINVAL; - - if (S_ISBLK(swap_inode->i_mode)) { - kdev_t dev = swap_inode->i_rdev; - struct block_device_operations *bdops; - devfs_handle_t de; + p->swap_file = swap_file; - p->swap_device = dev; - set_blocksize(dev, PAGE_SIZE); - - bd_acquire(swap_inode); - bdev = swap_inode->i_bdev; - de = devfs_get_handle_from_inode(swap_inode); - bdops = devfs_get_ops(de); /* Increments module use count */ - if (bdops) bdev->bd_op = bdops; - - error = blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_SWAP); - devfs_put_ops(de);/*Decrement module use count now we're safe*/ - if (error) - goto bad_swap_2; - set_blocksize(dev, PAGE_SIZE); - error = -ENODEV; - if (kdev_none(dev) || (blk_size[major(dev)] && - !blk_size[major(dev)][minor(dev)])) - goto bad_swap; - swapfilesize = 0; - if (blk_size[major(dev)]) - swapfilesize = blk_size[major(dev)][minor(dev)] - >> (PAGE_SHIFT - 10); - } else if (S_ISREG(swap_inode->i_mode)) - swapfilesize = swap_inode->i_size >> PAGE_SHIFT; - else + if (S_ISBLK(swap_file->f_dentry->d_inode->i_mode)) { + p->swap_device = swap_file->f_dentry->d_inode->i_rdev; + set_blocksize(p->swap_device, PAGE_SIZE); + } else if (!S_ISREG(swap_file->f_dentry->d_inode->i_mode)) goto bad_swap; + mapping = swap_file->f_dentry->d_inode->i_mapping; + swapfilesize = mapping->host->i_size >> PAGE_SHIFT; + error = -EBUSY; for (i = 0 ; i < nr_swapfiles ; i++) { struct swap_info_struct *q = &swap_info[i]; if (i == type || !q->swap_file) continue; - if (swap_inode->i_mapping == q->swap_file->d_inode->i_mapping) + if (mapping == q->swap_file->f_dentry->d_inode->i_mapping) goto bad_swap; } @@ -1085,16 +1060,11 @@ error = 0; goto out; bad_swap: - if (bdev) - blkdev_put(bdev, BDEV_SWAP); bad_swap_2: swap_list_lock(); swap_map = p->swap_map; - nd.mnt = p->swap_vfsmnt; - nd.dentry = p->swap_file; p->swap_device = NODEV; p->swap_file = NULL; - p->swap_vfsmnt = NULL; p->swap_map = NULL; p->flags = 0; if (!(swap_flags & SWAP_FLAG_PREFER)) @@ -1102,7 +1072,8 @@ swap_list_unlock(); if (swap_map) vfree(swap_map); - path_release(&nd); + if (swap_file) + filp_close(swap_file, NULL); out: if (swap_header) free_page((long) swap_header); @@ -1219,7 +1190,7 @@ * Prior swap_duplicate protects against swap device deletion. */ void get_swaphandle_info(swp_entry_t entry, unsigned long *offset, - kdev_t *dev, struct inode **swapf) + struct inode **swapf) { unsigned long type; struct swap_info_struct *p; @@ -1245,14 +1216,7 @@ return; } - if (!kdev_none(p->swap_device)) { - *dev = p->swap_device; - } else if (p->swap_file) { - *swapf = p->swap_file->d_inode; - } else { - printk(KERN_ERR "rw_swap_page: no swap file or device\n"); - } - return; + *swapf = p->swap_file->f_dentry->d_inode; } /* diff -urN linux-2.5.2-pre11/net/8021q/vlan.c linux/net/8021q/vlan.c --- linux-2.5.2-pre11/net/8021q/vlan.c Tue Oct 30 15:08:12 2001 +++ linux/net/8021q/vlan.c Mon Jan 14 18:28:32 2002 @@ -1,11 +1,10 @@ /* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * + * INET 802.1Q VLAN * Ethernet-type device handling. * - * Authors: Ben Greear , + * Authors: Ben Greear + * Please send support related email to: vlan@scry.wanfear.com + * VLAN Home Page: http://www.candelatech.com/~greear/vlan.html * * Fixes: * Fix for packet capture - Nick Eggleston ; @@ -42,7 +41,7 @@ static char vlan_fullname[] = "802.1Q VLAN Support"; static unsigned int vlan_version = 1; -static unsigned int vlan_release = 5; +static unsigned int vlan_release = 6; static char vlan_copyright[] = " Ben Greear "; static int vlan_device_event(struct notifier_block *, unsigned long, void *); @@ -106,6 +105,23 @@ } /* + * Cleanup of groups before exit + */ + +static void vlan_group_cleanup(void) +{ + struct vlan_group *grp = NULL; + struct vlan_group *nextgroup; + + for (grp = p802_1Q_vlan_list; (grp != NULL);) { + nextgroup = grp->next; + kfree(grp); + grp = nextgroup; + } + p802_1Q_vlan_list = NULL; +} + +/* * Module 'remove' entry point. * o delete /proc/net/router directory and static entries. */ @@ -116,7 +132,7 @@ dev_remove_pack(&vlan_packet_type); vlan_proc_cleanup(); - + vlan_group_cleanup(); vlan_ioctl_hook = NULL; } @@ -328,6 +344,7 @@ /* set up method calls */ new_dev->init = vlan_dev_init; new_dev->destructor = vlan_dev_destruct; + new_dev->features |= NETIF_F_DYNALLOC ; /* new_dev->ifindex = 0; it will be set when added to * the global list. diff -urN linux-2.5.2-pre11/net/8021q/vlan_dev.c linux/net/8021q/vlan_dev.c --- linux-2.5.2-pre11/net/8021q/vlan_dev.c Tue Oct 30 15:08:12 2001 +++ linux/net/8021q/vlan_dev.c Mon Jan 14 18:28:32 2002 @@ -1,11 +1,10 @@ /* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * + * INET 802.1Q VLAN * Ethernet-type device handling. * - * Authors: Ben Greear , + * Authors: Ben Greear + * Please send support related email to: vlan@scry.wanfear.com + * VLAN Home Page: http://www.candelatech.com/~greear/vlan.html * * Fixes: Mar 22 2001: Martin Bokaemper * - reset skb->pkt_type on incoming packets when MAC was changed @@ -512,10 +511,6 @@ VLAN_FMEM_DBG("dev->priv free, addr: %p\n", dev->priv); dev->priv = NULL; } - - kfree(dev); - VLAN_FMEM_DBG("net_device free, addr: %p\n", dev); - dev = NULL; } } diff -urN linux-2.5.2-pre11/net/8021q/vlanproc.c linux/net/8021q/vlanproc.c --- linux-2.5.2-pre11/net/8021q/vlanproc.c Mon Jan 14 18:28:25 2002 +++ linux/net/8021q/vlanproc.c Mon Jan 14 18:28:32 2002 @@ -115,7 +115,7 @@ * Clean up /proc/net/vlan entries */ -void __exit vlan_proc_cleanup(void) +void vlan_proc_cleanup(void) { if (proc_vlan_conf) remove_proc_entry(name_conf, proc_vlan_dir); @@ -461,7 +461,7 @@ return 0; } -void __exit vlan_proc_cleanup(void) +void vlan_proc_cleanup(void) { return; } diff -urN linux-2.5.2-pre11/net/Config.in linux/net/Config.in --- linux-2.5.2-pre11/net/Config.in Tue Oct 30 15:08:12 2001 +++ linux/net/Config.in Mon Jan 14 18:28:32 2002 @@ -61,7 +61,7 @@ if [ "$CONFIG_DECNET" != "n" ]; then source net/decnet/Config.in fi -tristate '802.1d Ethernet Bridging' CONFIG_BRIDGE +dep_tristate '802.1d Ethernet Bridging' CONFIG_BRIDGE $CONFIG_INET if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then tristate 'CCITT X.25 Packet Layer (EXPERIMENTAL)' CONFIG_X25 tristate 'LAPB Data Link Driver (EXPERIMENTAL)' CONFIG_LAPB diff -urN linux-2.5.2-pre11/net/README linux/net/README --- linux-2.5.2-pre11/net/README Mon Jun 11 19:15:27 2001 +++ linux/net/README Mon Jan 14 18:28:32 2002 @@ -23,4 +23,4 @@ unix alan@lxorguk.ukuu.org.uk x25 g4klx@g4klx.demon.co.uk bluetooth maxk@qualcomm.com - +8021q greearb@candelatech.com, vlan@scry.wanfear.com diff -urN linux-2.5.2-pre11/net/bridge/br.c linux/net/bridge/br.c --- linux-2.5.2-pre11/net/bridge/br.c Wed Oct 17 14:16:39 2001 +++ linux/net/bridge/br.c Mon Jan 14 18:28:32 2002 @@ -5,7 +5,7 @@ * Authors: * Lennert Buytenhek * - * $Id: br.c,v 1.46 2001/10/02 02:22:36 davem Exp $ + * $Id: br.c,v 1.47 2001/12/24 00:56:41 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -43,9 +43,7 @@ printk(KERN_INFO "NET4: Ethernet Bridge 008 for NET4.0\n"); br_handle_frame_hook = br_handle_frame; -#ifdef CONFIG_INET br_ioctl_hook = br_ioctl_deviceless_stub; -#endif #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) br_fdb_get_hook = br_fdb_get; br_fdb_put_hook = br_fdb_put; @@ -62,9 +60,7 @@ static void __br_clear_ioctl_hook(void) { -#ifdef CONFIG_INET br_ioctl_hook = NULL; -#endif } static void __exit br_deinit(void) diff -urN linux-2.5.2-pre11/net/bridge/br_device.c linux/net/bridge/br_device.c --- linux-2.5.2-pre11/net/bridge/br_device.c Wed Aug 15 01:54:30 2001 +++ linux/net/bridge/br_device.c Mon Jan 14 18:28:32 2002 @@ -5,7 +5,7 @@ * Authors: * Lennert Buytenhek * - * $Id: br_device.c,v 1.5 2001/08/14 22:05:57 davem Exp $ + * $Id: br_device.c,v 1.6 2001/12/24 00:59:55 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -71,7 +71,7 @@ return 0; } -static int br_dev_xmit(struct sk_buff *skb, struct net_device *dev) +int br_dev_xmit(struct sk_buff *skb, struct net_device *dev) { struct net_bridge *br; int ret; diff -urN linux-2.5.2-pre11/net/bridge/br_if.c linux/net/bridge/br_if.c --- linux-2.5.2-pre11/net/bridge/br_if.c Thu Nov 9 15:57:53 2000 +++ linux/net/bridge/br_if.c Mon Jan 14 18:28:32 2002 @@ -5,7 +5,7 @@ * Authors: * Lennert Buytenhek * - * $Id: br_if.c,v 1.5 2000/11/08 05:16:40 davem Exp $ + * $Id: br_if.c,v 1.7 2001/12/24 00:59:55 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -226,6 +226,9 @@ if (dev->flags & IFF_LOOPBACK || dev->type != ARPHRD_ETHER) return -EINVAL; + if (dev->hard_start_xmit == br_dev_xmit) + return -ELOOP; + dev_hold(dev); write_lock_bh(&br->lock); if ((p = new_nbp(br, dev)) == NULL) { @@ -261,8 +264,6 @@ { struct net_bridge *br; int i; - - i = 0; br = bridge_list; for (i=0;i * - * $Id: br_input.c,v 1.9 2001/08/14 22:05:57 davem Exp $ + * $Id: br_input.c,v 1.10 2001/12/24 04:50:20 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -46,7 +46,7 @@ br_pass_frame_up_finish); } -static void __br_handle_frame(struct sk_buff *skb) +static int br_handle_frame_finish(struct sk_buff *skb) { struct net_bridge *br; unsigned char *dest; @@ -57,103 +57,112 @@ dest = skb->mac.ethernet->h_dest; p = skb->dev->br_port; - br = p->br; - passedup = 0; + if (p == NULL) + goto err_nolock; - if (!(br->dev.flags & IFF_UP) || - p->state == BR_STATE_DISABLED) - goto freeandout; + br = p->br; + read_lock(&br->lock); + if (skb->dev->br_port == NULL) + goto err; + passedup = 0; if (br->dev.flags & IFF_PROMISC) { struct sk_buff *skb2; skb2 = skb_clone(skb, GFP_ATOMIC); - if (skb2) { + if (skb2 != NULL) { passedup = 1; br_pass_frame_up(br, skb2); } } - if (skb->mac.ethernet->h_source[0] & 1) - goto freeandout; - - if (!passedup && - (dest[0] & 1) && - (br->dev.flags & IFF_ALLMULTI || br->dev.mc_list != NULL)) { - struct sk_buff *skb2; - - skb2 = skb_clone(skb, GFP_ATOMIC); - if (skb2) { - passedup = 1; - br_pass_frame_up(br, skb2); - } - } - - if (br->stp_enabled && - !memcmp(dest, bridge_ula, 5) && - !(dest[5] & 0xF0)) - goto handle_special_frame; - - if (p->state == BR_STATE_LEARNING || - p->state == BR_STATE_FORWARDING) - br_fdb_insert(br, p, skb->mac.ethernet->h_source, 0); - - if (p->state != BR_STATE_FORWARDING) - goto freeandout; - if (dest[0] & 1) { - br_flood_forward(br, skb, 1); + br_flood_forward(br, skb, !passedup); if (!passedup) br_pass_frame_up(br, skb); - else - kfree_skb(skb); - return; + goto out; } dst = br_fdb_get(br, dest); - if (dst != NULL && dst->is_local) { if (!passedup) br_pass_frame_up(br, skb); else kfree_skb(skb); br_fdb_put(dst); - return; + goto out; } if (dst != NULL) { br_forward(dst->dst, skb); br_fdb_put(dst); - return; + goto out; } br_flood_forward(br, skb, 0); - return; - handle_special_frame: - if (!dest[5]) { - br_stp_handle_bpdu(skb); - return; - } +out: + read_unlock(&br->lock); + return 0; - freeandout: +err: + read_unlock(&br->lock); +err_nolock: kfree_skb(skb); + return 0; } -static int br_handle_frame_finish(struct sk_buff *skb) +void br_handle_frame(struct sk_buff *skb) { struct net_bridge *br; + unsigned char *dest; + struct net_bridge_port *p; - br = skb->dev->br_port->br; + dest = skb->mac.ethernet->h_dest; + + p = skb->dev->br_port; + if (p == NULL) + goto err_nolock; + + br = p->br; read_lock(&br->lock); - __br_handle_frame(skb); - read_unlock(&br->lock); + if (skb->dev->br_port == NULL) + goto err; - return 0; -} + if (!(br->dev.flags & IFF_UP) || + p->state == BR_STATE_DISABLED) + goto err; -void br_handle_frame(struct sk_buff *skb) -{ - NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, + if (skb->mac.ethernet->h_source[0] & 1) + goto err; + + if (p->state == BR_STATE_LEARNING || + p->state == BR_STATE_FORWARDING) + br_fdb_insert(br, p, skb->mac.ethernet->h_source, 0); + + if (br->stp_enabled && + !memcmp(dest, bridge_ula, 5) && + !(dest[5] & 0xF0)) + goto handle_special_frame; + + if (p->state == BR_STATE_FORWARDING) { + NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, br_handle_frame_finish); + read_unlock(&br->lock); + return; + } + +err: + read_unlock(&br->lock); +err_nolock: + kfree_skb(skb); + return; + +handle_special_frame: + if (!dest[5]) { + br_stp_handle_bpdu(skb); + return; + } + + kfree_skb(skb); } diff -urN linux-2.5.2-pre11/net/bridge/br_private.h linux/net/bridge/br_private.h --- linux-2.5.2-pre11/net/bridge/br_private.h Mon Jun 11 19:15:27 2001 +++ linux/net/bridge/br_private.h Mon Jan 14 18:28:32 2002 @@ -4,7 +4,7 @@ * Authors: * Lennert Buytenhek * - * $Id: br_private.h,v 1.6 2001/06/01 09:28:28 davem Exp $ + * $Id: br_private.h,v 1.7 2001/12/24 00:59:55 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -121,6 +121,7 @@ /* br_device.c */ extern void br_dev_setup(struct net_device *dev); +extern int br_dev_xmit(struct sk_buff *skb, struct net_device *dev); /* br_fdb.c */ extern void br_fdb_changeaddr(struct net_bridge_port *p, diff -urN linux-2.5.2-pre11/net/ipv4/icmp.c linux/net/ipv4/icmp.c --- linux-2.5.2-pre11/net/ipv4/icmp.c Wed Nov 7 14:39:36 2001 +++ linux/net/ipv4/icmp.c Mon Jan 14 18:28:32 2002 @@ -3,7 +3,7 @@ * * Alan Cox, * - * Version: $Id: icmp.c,v 1.82 2001/11/01 23:44:31 davem Exp $ + * Version: $Id: icmp.c,v 1.83 2001/12/13 09:00:19 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -154,8 +154,8 @@ * it's bit position. * * default: - * dest unreachable (0x03), source quench (0x04), - * time exceeded (0x11), parameter problem (0x12) + * dest unreachable (3), source quench (4), + * time exceeded (11), parameter problem (12) */ int sysctl_icmp_ratelimit = 1*HZ; diff -urN linux-2.5.2-pre11/net/ipv4/netfilter/ip_conntrack_irc.c linux/net/ipv4/netfilter/ip_conntrack_irc.c --- linux-2.5.2-pre11/net/ipv4/netfilter/ip_conntrack_irc.c Tue Oct 30 15:08:12 2001 +++ linux/net/ipv4/netfilter/ip_conntrack_irc.c Mon Jan 14 18:28:32 2002 @@ -1,8 +1,8 @@ -/* IRC extension for IP connection tracking, Version 1.19 - * (C) 2000 by Harald Welte +/* IRC extension for IP connection tracking, Version 1.20 + * (C) 2000-2001 by Harald Welte * based on RR's ip_conntrack_ftp.c * - * ip_conntrack_irc.c,v 1.19 2001/10/25 14:34:21 laforge Exp + * ip_conntrack_irc.c,v 1.20 2001/12/06 07:42:10 laforge Exp * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -10,7 +10,7 @@ * 2 of the License, or (at your option) any later version. ** * Module load syntax: - * insmod ip_nat_irc.o ports=port1,port2,...port + * insmod ip_conntrack_irc.o ports=port1,port2,...port * * please give the ports of all IRC servers You wish to connect to. * If You don't specify ports, the default will be port 6667 diff -urN linux-2.5.2-pre11/net/ipv4/netfilter/ip_conntrack_standalone.c linux/net/ipv4/netfilter/ip_conntrack_standalone.c --- linux-2.5.2-pre11/net/ipv4/netfilter/ip_conntrack_standalone.c Sun Sep 30 12:26:08 2001 +++ linux/net/ipv4/netfilter/ip_conntrack_standalone.c Mon Jan 14 18:28:32 2002 @@ -243,7 +243,7 @@ ret = nf_register_hook(&ip_conntrack_in_ops); if (ret < 0) { - printk("ip_conntrack: can't register in hook.\n"); + printk("ip_conntrack: can't register pre-routing hook.\n"); goto cleanup_proc; } ret = nf_register_hook(&ip_conntrack_local_out_ops); diff -urN linux-2.5.2-pre11/net/ipv4/netfilter/ip_fw_compat.c linux/net/ipv4/netfilter/ip_fw_compat.c --- linux-2.5.2-pre11/net/ipv4/netfilter/ip_fw_compat.c Sat Nov 10 15:36:38 2001 +++ linux/net/ipv4/netfilter/ip_fw_compat.c Mon Jan 14 18:28:32 2002 @@ -84,6 +84,16 @@ if ((*pskb)->ip_summed == CHECKSUM_HW) (*pskb)->ip_summed = CHECKSUM_NONE; + /* Firewall rules can alter TOS: raw socket (tcpdump) may have + clone of incoming skb: don't disturb it --RR */ + if (skb_cloned(*pskb) && !(*pskb)->sk) { + struct sk_buff *nskb = skb_copy(*pskb, GFP_ATOMIC); + if (!nskb) + return NF_DROP; + kfree_skb(*pskb); + *pskb = nskb; + } + switch (hooknum) { case NF_IP_PRE_ROUTING: if (fwops->fw_acct_in) diff -urN linux-2.5.2-pre11/net/ipv4/netfilter/ip_fw_compat_redir.c linux/net/ipv4/netfilter/ip_fw_compat_redir.c --- linux-2.5.2-pre11/net/ipv4/netfilter/ip_fw_compat_redir.c Fri Aug 4 13:07:24 2000 +++ linux/net/ipv4/netfilter/ip_fw_compat_redir.c Mon Jan 14 18:28:32 2002 @@ -206,6 +206,8 @@ } list_prepend(&redirs, redir); init_timer(&redir->destroyme); + redir->destroyme.expires = jiffies + 75*HZ; + add_timer(&redir->destroyme); } /* In case mangling has changed, rewrite this part. */ redir->core = ((struct redir_core) diff -urN linux-2.5.2-pre11/net/ipv4/netfilter/ip_nat_core.c linux/net/ipv4/netfilter/ip_nat_core.c --- linux-2.5.2-pre11/net/ipv4/netfilter/ip_nat_core.c Sat Nov 10 15:36:38 2001 +++ linux/net/ipv4/netfilter/ip_nat_core.c Mon Jan 14 18:28:32 2002 @@ -734,6 +734,18 @@ synchronize_bh()) can vanish. */ READ_LOCK(&ip_nat_lock); for (i = 0; i < info->num_manips; i++) { + /* raw socket (tcpdump) may have clone of incoming + skb: don't disturb it --RR */ + if (skb_cloned(*pskb) && !(*pskb)->sk) { + struct sk_buff *nskb = skb_copy(*pskb, GFP_ATOMIC); + if (!nskb) { + READ_UNLOCK(&ip_nat_lock); + return NF_DROP; + } + kfree_skb(*pskb); + *pskb = nskb; + } + if (info->manips[i].direction == dir && info->manips[i].hooknum == hooknum) { DEBUGP("Mangling %p: %s to %u.%u.%u.%u %u\n", diff -urN linux-2.5.2-pre11/net/ipv4/netfilter/ip_nat_helper.c linux/net/ipv4/netfilter/ip_nat_helper.c --- linux-2.5.2-pre11/net/ipv4/netfilter/ip_nat_helper.c Tue Aug 28 07:09:44 2001 +++ linux/net/ipv4/netfilter/ip_nat_helper.c Mon Jan 14 18:28:32 2002 @@ -143,6 +143,23 @@ } } + /* Alexey says: if a hook changes _data_ ... it can break + original packet sitting in tcp queue and this is fatal */ + if (skb_cloned(*skb)) { + struct sk_buff *nskb = skb_copy(*skb, GFP_ATOMIC); + if (!nskb) { + if (net_ratelimit()) + printk("Out of memory cloning TCP packet\n"); + return 0; + } + /* Rest of kernel will get very unhappy if we pass it + a suddenly-orphaned skbuff */ + if ((*skb)->sk) + skb_set_owner_w(nskb, (*skb)->sk); + kfree_skb(*skb); + *skb = nskb; + } + /* skb may be copied !! */ iph = (*skb)->nh.iph; tcph = (void *)iph + iph->ihl*4; diff -urN linux-2.5.2-pre11/net/ipv4/netfilter/ip_nat_irc.c linux/net/ipv4/netfilter/ip_nat_irc.c --- linux-2.5.2-pre11/net/ipv4/netfilter/ip_nat_irc.c Tue Oct 30 15:08:12 2001 +++ linux/net/ipv4/netfilter/ip_nat_irc.c Mon Jan 14 18:28:32 2002 @@ -1,8 +1,8 @@ /* IRC extension for TCP NAT alteration. - * (C) 2000 by Harald Welte + * (C) 2000-2001 by Harald Welte * based on a copy of RR's ip_nat_ftp.c * - * ip_nat_irc.c,v 1.15 2001/10/22 10:43:53 laforge Exp + * ip_nat_irc.c,v 1.16 2001/12/06 07:42:10 laforge Exp * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -81,7 +81,7 @@ } newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; - newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip; + newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; DEBUGP("nat_expected: DCC cmd. %u.%u.%u.%u->%u.%u.%u.%u\n", NIPQUAD(newsrcip), NIPQUAD(newdstip)); diff -urN linux-2.5.2-pre11/net/ipv4/netfilter/ipt_MIRROR.c linux/net/ipv4/netfilter/ipt_MIRROR.c --- linux-2.5.2-pre11/net/ipv4/netfilter/ipt_MIRROR.c Sun Sep 30 12:26:08 2001 +++ linux/net/ipv4/netfilter/ipt_MIRROR.c Mon Jan 14 18:28:32 2002 @@ -6,6 +6,10 @@ Copyright (C) 2000 Emmanuel Roger + Changes: + 25 Aug 2001 Harald Welte + - decrement and check TTL if not called from FORWARD hook + 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 @@ -24,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -100,15 +105,31 @@ const void *targinfo, void *userinfo) { - if ((*pskb)->dst != NULL) { - if (route_mirror(*pskb)) { - ip_rewrite(*pskb); - /* Don't let conntrack code see this packet: - it will think we are starting a new - connection! --RR */ - ip_direct_send(*pskb); - return NF_STOLEN; + if (((*pskb)->dst != NULL) && + route_mirror(*pskb)) { + + ip_rewrite(*pskb); + + /* If we are not at FORWARD hook (INPUT/PREROUTING), + * the TTL isn't decreased by the IP stack */ + if (hooknum != NF_IP_FORWARD) { + struct iphdr *iph = (*pskb)->nh.iph; + if (iph->ttl <= 1) { + /* this will traverse normal stack, and + * thus call conntrack on the icmp packet */ + icmp_send(*pskb, ICMP_TIME_EXCEEDED, + ICMP_EXC_TTL, 0); + return NF_DROP; + } + ip_decrease_ttl(iph); } + + /* Don't let conntrack code see this packet: + it will think we are starting a new + connection! --RR */ + ip_direct_send(*pskb); + + return NF_STOLEN; } return NF_DROP; } diff -urN linux-2.5.2-pre11/net/ipv4/netfilter/ipt_TCPMSS.c linux/net/ipv4/netfilter/ipt_TCPMSS.c --- linux-2.5.2-pre11/net/ipv4/netfilter/ipt_TCPMSS.c Sat Nov 10 15:36:38 2001 +++ linux/net/ipv4/netfilter/ipt_TCPMSS.c Mon Jan 14 18:28:32 2002 @@ -44,11 +44,22 @@ { const struct ipt_tcpmss_info *tcpmssinfo = targinfo; struct tcphdr *tcph; - struct iphdr *iph = (*pskb)->nh.iph; + struct iphdr *iph; u_int16_t tcplen, newtotlen, oldval, newmss; unsigned int i; u_int8_t *opt; + /* raw socket (tcpdump) may have clone of incoming skb: don't + disturb it --RR */ + if (skb_cloned(*pskb) && !(*pskb)->sk) { + struct sk_buff *nskb = skb_copy(*pskb, GFP_ATOMIC); + if (!nskb) + return NF_DROP; + kfree_skb(*pskb); + *pskb = nskb; + } + + iph = (*pskb)->nh.iph; tcplen = (*pskb)->len - iph->ihl*4; tcph = (void *)iph + iph->ihl*4; diff -urN linux-2.5.2-pre11/net/ipv4/netfilter/ipt_TOS.c linux/net/ipv4/netfilter/ipt_TOS.c --- linux-2.5.2-pre11/net/ipv4/netfilter/ipt_TOS.c Sat Nov 10 15:36:38 2001 +++ linux/net/ipv4/netfilter/ipt_TOS.c Mon Jan 14 18:28:32 2002 @@ -21,6 +21,17 @@ if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) { u_int16_t diffs[2]; + /* raw socket (tcpdump) may have clone of incoming + skb: don't disturb it --RR */ + if (skb_cloned(*pskb) && !(*pskb)->sk) { + struct sk_buff *nskb = skb_copy(*pskb, GFP_ATOMIC); + if (!nskb) + return NF_DROP; + kfree_skb(*pskb); + *pskb = nskb; + iph = (*pskb)->nh.iph; + } + diffs[0] = htons(iph->tos) ^ 0xFFFF; iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos; diffs[1] = htons(iph->tos); diff -urN linux-2.5.2-pre11/net/ipv4/netfilter/ipt_unclean.c linux/net/ipv4/netfilter/ipt_unclean.c --- linux-2.5.2-pre11/net/ipv4/netfilter/ipt_unclean.c Sun Sep 30 12:26:08 2001 +++ linux/net/ipv4/netfilter/ipt_unclean.c Mon Jan 14 18:28:32 2002 @@ -257,6 +257,8 @@ #define TH_PUSH 0x08 #define TH_ACK 0x10 #define TH_URG 0x20 +#define TH_ECE 0x40 +#define TH_CWR 0x80 /* TCP-specific checks. */ static int @@ -328,9 +330,10 @@ } /* CHECK: TCP flags. */ - tcpflags = ((u_int8_t *)tcph)[13]; + tcpflags = (((u_int8_t *)tcph)[13] & ~(TH_ECE|TH_CWR)); if (tcpflags != TH_SYN && tcpflags != (TH_SYN|TH_ACK) + && tcpflags != TH_RST && tcpflags != (TH_RST|TH_ACK) && tcpflags != (TH_RST|TH_ACK|TH_PUSH) && tcpflags != (TH_FIN|TH_ACK) diff -urN linux-2.5.2-pre11/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c --- linux-2.5.2-pre11/net/ipv6/tcp_ipv6.c Mon Nov 5 09:46:12 2001 +++ linux/net/ipv6/tcp_ipv6.c Mon Jan 14 18:28:32 2002 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: tcp_ipv6.c,v 1.140 2001/10/15 12:34:50 davem Exp $ + * $Id: tcp_ipv6.c,v 1.143 2001/12/21 05:05:41 davem Exp $ * * Based on: * linux/net/ipv4/tcp.c @@ -1172,6 +1172,7 @@ tcp_parse_options(skb, &tp, 0); + tp.tstamp_ok = tp.saw_tstamp; tcp_openreq_init(req, &tp, skb); req->class = &or_ipv6; diff -urN linux-2.5.2-pre11/net/sunrpc/sched.c linux/net/sunrpc/sched.c --- linux-2.5.2-pre11/net/sunrpc/sched.c Mon Jan 14 18:28:25 2002 +++ linux/net/sunrpc/sched.c Mon Jan 14 18:28:32 2002 @@ -21,6 +21,7 @@ #include #include +#include #ifdef RPC_DEBUG #define RPCDBG_FACILITY RPCDBG_SCHED diff -urN linux-2.5.2-pre11/net/sunrpc/xprt.c linux/net/sunrpc/xprt.c --- linux-2.5.2-pre11/net/sunrpc/xprt.c Mon Oct 8 12:36:07 2001 +++ linux/net/sunrpc/xprt.c Mon Jan 14 18:28:32 2002 @@ -630,10 +630,14 @@ int to_move = cur_len; if (to_move > copied) to_move = copied; - if (need_csum) - csum = skb_copy_and_csum_bits(skb, offset, cur_ptr, - to_move, csum); - else + if (need_csum) { + unsigned int csum2; + + csum2 = skb_copy_and_csum_bits(skb, offset, + cur_ptr, + to_move, 0); + csum = csum_block_add(csum, csum2, offset); + } else skb_copy_bits(skb, offset, cur_ptr, to_move); offset += to_move; copied -= to_move; @@ -647,8 +651,12 @@ } } if (need_csum) { - if (slack > 0) - csum = skb_checksum(skb, offset, slack, csum); + if (slack > 0) { + unsigned int csum2; + + csum2 = skb_checksum(skb, offset, slack, 0); + csum = csum_block_add(csum, csum2, offset); + } if ((unsigned short)csum_fold(csum)) return -1; }