]> git.hungrycats.org Git - linux/commitdiff
v2.5.1.11 -> v2.5.2 v2.5.2
authorLinus Torvalds <torvalds@athlon.transmeta.com>
Tue, 5 Feb 2002 08:13:33 +0000 (00:13 -0800)
committerLinus Torvalds <torvalds@athlon.transmeta.com>
Tue, 5 Feb 2002 08:13:33 +0000 (00:13 -0800)
- Matt Domsch: combine common crc32 library
- Pete Zaitcev: ymfpci update
- Davide Libenzi: scheduler improvements
- Al Viro: almost there: "struct block_device *" everywhere
- Richard Gooch: devfs cpqarray update, race fix
- Rusty Russell: PATH_MAX should include the final '0' count
- David Miller: various random updates (mainly net and sparc)

317 files changed:
Documentation/Configure.help
Documentation/block/request.txt [new file with mode: 0644]
Documentation/cciss.txt
Documentation/filesystems/devfs/ChangeLog
Documentation/networking/ip-sysctl.txt
Makefile
arch/alpha/config.in
arch/arm/config.in
arch/cris/config.in
arch/i386/config.in
arch/i386/defconfig
arch/i386/kernel/setup.c
arch/ia64/config.in
arch/m68k/config.in
arch/mips/config.in
arch/mips64/config.in
arch/parisc/config.in
arch/ppc/config.in
arch/s390/config.in
arch/s390x/config.in
arch/sh/config.in
arch/sparc/config.in
arch/sparc/kernel/check_asm.sh
arch/sparc/kernel/devices.c
arch/sparc/kernel/ebus.c
arch/sparc/kernel/init_task.c
arch/sparc/kernel/irq.c
arch/sparc/kernel/process.c
arch/sparc/kernel/signal.c
arch/sparc/kernel/sun4d_irq.c
arch/sparc/kernel/sun4d_smp.c
arch/sparc/kernel/sun4m_smp.c
arch/sparc/kernel/sys_sunos.c
arch/sparc/kernel/trampoline.S
arch/sparc/kernel/unaligned.c
arch/sparc/mm/extable.c
arch/sparc/mm/fault.c
arch/sparc/mm/init.c
arch/sparc/mm/io-unit.c
arch/sparc/mm/iommu.c
arch/sparc/prom/ranges.c
arch/sparc64/Makefile
arch/sparc64/config.in
arch/sparc64/defconfig
arch/sparc64/kernel/Makefile
arch/sparc64/kernel/central.c
arch/sparc64/kernel/check_asm.sh
arch/sparc64/kernel/chmc.c
arch/sparc64/kernel/entry.S
arch/sparc64/kernel/ioctl32.c
arch/sparc64/kernel/iommu_common.c
arch/sparc64/kernel/irq.c
arch/sparc64/kernel/pci_iommu.c
arch/sparc64/kernel/pci_psycho.c
arch/sparc64/kernel/pci_sabre.c
arch/sparc64/kernel/pci_schizo.c
arch/sparc64/kernel/power.c
arch/sparc64/kernel/process.c
arch/sparc64/kernel/rtrap.S
arch/sparc64/kernel/sbus.c
arch/sparc64/kernel/semaphore.c
arch/sparc64/kernel/signal.c
arch/sparc64/kernel/signal32.c
arch/sparc64/kernel/smp.c
arch/sparc64/kernel/sparc64_ksyms.c
arch/sparc64/kernel/sys_sparc.c
arch/sparc64/kernel/sys_sunos32.c
arch/sparc64/kernel/time.c
arch/sparc64/kernel/trampoline.S
arch/sparc64/kernel/traps.c
arch/sparc64/kernel/ttable.S
arch/sparc64/lib/atomic.S
arch/sparc64/lib/bitops.S
arch/sparc64/lib/blockops.S
arch/sparc64/lib/debuglocks.c
arch/sparc64/lib/dec_and_lock.S
arch/sparc64/mm/extable.c
arch/sparc64/mm/init.c
arch/sparc64/mm/ultra.S
arch/sparc64/solaris/fs.c
arch/sparc64/solaris/misc.c
arch/sparc64/solaris/socksys.c
arch/sparc64/solaris/timod.c
drivers/block/Config.in
drivers/block/cciss.c
drivers/block/cciss.h
drivers/block/cciss_cmd.h
drivers/block/cciss_scsi.c [new file with mode: 0644]
drivers/block/cciss_scsi.h [new file with mode: 0644]
drivers/block/cpqarray.c
drivers/block/elevator.c
drivers/block/ll_rw_blk.c
drivers/block/nbd.c
drivers/char/rtc.c
drivers/md/md.c
drivers/md/multipath.c
drivers/md/raid5.c
drivers/message/i2o/i2o_block.c
drivers/net/7990.c
drivers/net/7990.h
drivers/net/8139cp.c
drivers/net/8139too.c
drivers/net/8390.c
drivers/net/Makefile.lib [new file with mode: 0644]
drivers/net/a2065.c
drivers/net/a2065.h
drivers/net/am79c961a.c
drivers/net/at1700.c
drivers/net/atp.c
drivers/net/au1000_eth.c
drivers/net/bmac.c
drivers/net/bonding.c
drivers/net/de2104x.c
drivers/net/de4x5.c
drivers/net/declance.c
drivers/net/depca.c
drivers/net/dl2k.c
drivers/net/dl2k.h
drivers/net/dmfe.c
drivers/net/epic100.c
drivers/net/ewrk3.c
drivers/net/fealnx.c
drivers/net/gmac.c
drivers/net/ioc3-eth.c
drivers/net/mace.c
drivers/net/macmace.c
drivers/net/myri_code.h
drivers/net/myri_sbus.c
drivers/net/natsemi.c
drivers/net/pci-skeleton.c
drivers/net/pcmcia/fmvj18x_cs.c
drivers/net/pcmcia/smc91c92_cs.c
drivers/net/pcmcia/xircom_tulip_cb.c
drivers/net/pcnet32.c
drivers/net/shaper.c
drivers/net/sis900.c
drivers/net/sk98lin/h/skdrv1st.h
drivers/net/sk98lin/skaddr.c
drivers/net/smc9194.c
drivers/net/starfire.c
drivers/net/sunbmac.c
drivers/net/sundance.c
drivers/net/sungem.c
drivers/net/sungem.h
drivers/net/sunhme.c
drivers/net/sunlance.c
drivers/net/sunqe.c
drivers/net/tulip/tulip_core.c
drivers/net/via-rhine.c
drivers/net/winbond-840.c
drivers/net/yellowfin.c
drivers/s390/block/dasd_int.h
drivers/s390/block/xpram.c
drivers/s390/char/tapedefs.h
drivers/sbus/audio/audio.c
drivers/sbus/char/aurora.c
drivers/sbus/char/cpwatchdog.c
drivers/sbus/char/display7seg.c
drivers/sbus/char/sab82532.c
drivers/sbus/char/su.c
drivers/sbus/char/sunserial.c
drivers/sbus/char/zs.c
drivers/sbus/sbus.c
drivers/scsi/advansys.c
drivers/scsi/aic7xxx/aic7xxx_linux.c
drivers/scsi/aic7xxx/aic7xxx_osm.h
drivers/scsi/constants.c
drivers/scsi/hosts.c
drivers/scsi/hosts.h
drivers/scsi/ide-scsi.c
drivers/scsi/scsi.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_ioctl.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_merge.c
drivers/scsi/scsi_proc.c
drivers/scsi/scsi_queue.c
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_syms.c
drivers/scsi/scsicam.c
drivers/scsi/sym53c8xx.c
drivers/scsi/sym53c8xx_2/sym_glue.c
drivers/sound/trident.c
drivers/sound/ymfpci.c
drivers/sound/ymfpci.h
drivers/telephony/phonedev.c
drivers/usb/Makefile.lib [new file with mode: 0644]
drivers/usb/catc.c
drivers/usb/hcd.c
drivers/usb/hcd/ehci-hcd.c
drivers/usb/hcd/ehci-sched.c
drivers/video/aty/mach64_accel.c
drivers/video/sbusfb.c
fs/Makefile.lib [new file with mode: 0644]
fs/affs/file.c
fs/block_dev.c
fs/buffer.c
fs/coda/inode.c
fs/coda/pioctl.c
fs/dcache.c
fs/devfs/base.c
fs/devpts/root.c
fs/driverfs/inode.c
fs/fat/cache.c
fs/fat/inode.c
fs/inode.c
fs/intermezzo/cache.c
fs/intermezzo/presto.c
fs/intermezzo/psdev.c
fs/intermezzo/sysctl.c
fs/intermezzo/vfs.c
fs/jbd/journal.c
fs/jbd/revoke.c
fs/jbd/transaction.c
fs/jffs2/Makefile
fs/jffs2/crc32.c [deleted file]
fs/jffs2/crc32.h [deleted file]
fs/jffs2/dir.c
fs/jffs2/erase.c
fs/jffs2/file.c
fs/jffs2/gc.c
fs/jffs2/read.c
fs/jffs2/readinode.c
fs/jffs2/scan.c
fs/jffs2/write.c
fs/namei.c
fs/openpromfs/inode.c
fs/partitions/msdos.c
fs/reiserfs/bitmap.c
fs/reiserfs/journal.c
fs/reiserfs/tail_conversion.c
include/asm-sparc/bitops.h
include/asm-sparc/io.h
include/asm-sparc/keyboard.h
include/asm-sparc/mmu_context.h
include/asm-sparc/oplib.h
include/asm-sparc/pci.h
include/asm-sparc/smp.h
include/asm-sparc/smplock.h
include/asm-sparc/string.h
include/asm-sparc/types.h
include/asm-sparc64/bitops.h
include/asm-sparc64/elf.h
include/asm-sparc64/io.h
include/asm-sparc64/keyboard.h
include/asm-sparc64/mmu_context.h
include/asm-sparc64/oplib.h
include/asm-sparc64/page.h
include/asm-sparc64/processor.h
include/asm-sparc64/rwsem.h
include/asm-sparc64/semaphore.h
include/asm-sparc64/smp.h
include/asm-sparc64/smplock.h
include/asm-sparc64/spinlock.h
include/asm-sparc64/spitfire.h
include/asm-sparc64/system.h
include/asm-sparc64/ttable.h
include/linux/blkdev.h
include/linux/crc32.h [new file with mode: 0644]
include/linux/fs.h
include/linux/if_arp.h
include/linux/if_bonding.h
include/linux/kbd_kern.h
include/linux/limits.h
include/linux/netfilter_ipv4/ip_conntrack.h
include/linux/netfilter_ipv4/ip_conntrack_tuple.h
include/linux/reiserfs_fs.h
include/linux/reiserfs_fs_sb.h
include/linux/sched.h
include/linux/shmem_fs.h
include/linux/socket.h
include/linux/sunrpc/clnt.h
include/linux/swap.h
include/math-emu/double.h
include/math-emu/extended.h
include/math-emu/op-1.h
include/math-emu/op-2.h
include/math-emu/op-4.h
include/math-emu/op-8.h
include/math-emu/op-common.h
include/math-emu/quad.h
include/math-emu/single.h
include/math-emu/soft-fp.h
kernel/ksyms.c
kernel/sched.c
lib/Config.in [new file with mode: 0644]
lib/Makefile
lib/crc32.c [new file with mode: 0644]
mm/bootmem.c
mm/highmem.c
mm/page_io.c
mm/swapfile.c
net/8021q/vlan.c
net/8021q/vlan_dev.c
net/8021q/vlanproc.c
net/Config.in
net/README
net/bridge/br.c
net/bridge/br_device.c
net/bridge/br_if.c
net/bridge/br_input.c
net/bridge/br_private.h
net/ipv4/icmp.c
net/ipv4/netfilter/ip_conntrack_irc.c
net/ipv4/netfilter/ip_conntrack_standalone.c
net/ipv4/netfilter/ip_fw_compat.c
net/ipv4/netfilter/ip_fw_compat_redir.c
net/ipv4/netfilter/ip_nat_core.c
net/ipv4/netfilter/ip_nat_helper.c
net/ipv4/netfilter/ip_nat_irc.c
net/ipv4/netfilter/ipt_MIRROR.c
net/ipv4/netfilter/ipt_TCPMSS.c
net/ipv4/netfilter/ipt_TOS.c
net/ipv4/netfilter/ipt_unclean.c
net/ipv6/tcp_ipv6.c
net/sunrpc/sched.c
net/sunrpc/xprt.c

index 9be21975f4fe9acc6154bad8bb7c145b09dafd88..9bc25ad78d4d6b42716a30517f778220fb4a8da5 100644 (file)
@@ -6301,6 +6301,18 @@ CONFIG_BLK_CPQ_CISS_DA
   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
@@ -24029,6 +24041,13 @@ CONFIG_GDB_CONSOLE
   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:
 #   capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet,
diff --git a/Documentation/block/request.txt b/Documentation/block/request.txt
new file mode 100644 (file)
index 0000000..b8de235
--- /dev/null
@@ -0,0 +1,86 @@
+
+struct request documentation
+
+Jens Axboe <axboe@suse.de> 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).
+
+<linux/blkdev.h>
+
+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
index d8c95d57910636c77c74f731c2fd58d1dd0ef043..8548f913ee3e9405f37d37afd34f3eeed73dfa59 100644 (file)
@@ -100,7 +100,7 @@ lun used to address the device.  Once this is done, the SCSI mid layer
 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
index 407a684e9d16eb3b5eadaaabd0d44d840d98c20f..de386c4ea0b7740d8cbf040a76d54e5b7c34a64e 100644 (file)
@@ -1863,3 +1863,9 @@ Changes for patch v205
 - 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 <devfs_lookup>
index 9d5454939b7c06fd863a3fb76f4a9b075e99d14a..e0588af1fd402a59e002e89a53b1d01eae91e4ae 100644 (file)
@@ -309,13 +309,20 @@ icmp_echo_ignore_broadcasts - BOOLEAN
        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<<ICMP_DEST_UNREACH + 1<<ICMP_SOURCE_QUENCH +
+             1<<ICMP_TIME_EXCEEDED + 1<<ICMP_PARAMETERPROB, which means
+             dest unreachable (3), source quench (4), time exceeded (11)
+             and parameter problem (12) ICMP packets are rate limited
+             (check values in icmp.h)
 
 icmp_ignore_bogus_error_responses - BOOLEAN
        Some routers violate RFC 1122 by sending bogus responses to broadcast
@@ -511,4 +518,4 @@ IPv6 Update by:
 Pekka Savola
 pekkas@netcore.fi
 
-$Id: ip-sysctl.txt,v 1.19 2001/05/16 17:11:04 davem Exp $
+$Id: ip-sysctl.txt,v 1.20 2001/12/13 09:00:18 davem Exp $
index fffcc6e582a745fd8f5fa4efcc48d7568da3cd19..5c2a8e1c65b8a44b611f9fe725ef20ab0fac90cf 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 2
-EXTRAVERSION =-pre11
+EXTRAVERSION =
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
@@ -122,7 +122,7 @@ CORE_FILES  =kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o
 NETWORKS       =net/network.o
 
 LIBS           =$(TOPDIR)/lib/lib.a
-SUBDIRS                =kernel drivers mm fs net ipc lib
+SUBDIRS                =kernel lib drivers mm fs net ipc
 
 DRIVERS-n :=
 DRIVERS-y :=
@@ -261,9 +261,9 @@ vmlinux: include/linux/version.h $(CONFIGURATION) init/main.o init/version.o ini
        $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o init/do_mounts.o \
                --start-group \
                $(CORE_FILES) \
+               $(LIBS) \
                $(DRIVERS) \
                $(NETWORKS) \
-               $(LIBS) \
                --end-group \
                -o vmlinux
        $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map
index 91f072a80d708d92b578c6515c3ac3ec2caaa718..14ca220f571a5ee7b89cd042ebe8f58c4956bfb2 100644 (file)
@@ -393,3 +393,5 @@ else
 fi
 
 endmenu
+
+source lib/Config.in
index 02bcbfa8b0adc872fa32b694095534d24d906dc2..f71bf71205f373281d4f42fc2a94d51352e4df6e 100644 (file)
@@ -709,3 +709,5 @@ dep_bool '    Kernel low-level debugging messages via footbridge serial port' CO
 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
index 5a9ee03de6fb25af39954f86f0758fafc93f5158..66013359742eefc05444013b34b800f5e6562be7 100644 (file)
@@ -251,3 +251,5 @@ if [ "$CONFIG_PROFILE" = "y" ]; then
   int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
 fi
 endmenu
+
+source lib/Config.in
index 68a6cc9caa2750dcc3cd0edfacb6ded544f7a361..aa1284ad5dbdfc2a85ef06252cad02b99b92fdf6 100644 (file)
@@ -419,3 +419,5 @@ if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then
 fi
 
 endmenu
+
+source lib/Config.in
index b954777752f892d38a0a9ac4eeb09653e433997b..11ce0b503ba9fae66591dfc7412ce25c90a45535 100644 (file)
@@ -130,6 +130,7 @@ CONFIG_BLK_DEV_FD=y
 # 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 @@ CONFIG_USB_STORAGE=y
 # Kernel hacking
 #
 # CONFIG_DEBUG_KERNEL is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
index efd313e13fe9e6ad4bff56683063ad3f5fa7ccc3..52b2a387bc0e714a3c04994927c44ba2b460a7cd 100644 (file)
@@ -748,6 +748,7 @@ void __init setup_arch(char **cmdline_p)
                        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) {
index fb0931f7b75cbbc800e46a75c1beaa05b81afe22..dff81a6f05b20c60b2105efb798366721e5b35a4 100644 (file)
@@ -234,6 +234,8 @@ endmenu
 
 source drivers/usb/Config.in
 
+source lib/Config.in
+
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
    source net/bluetooth/Config.in
 fi
index a65b213cd1341e4888afaf15fb80d984cd77f598..44bc86f0618270b1d08f0003325cb1ced795e7be 100644 (file)
@@ -546,3 +546,5 @@ comment 'Kernel hacking'
 #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
 endmenu
+
+source lib/Config.in
index 3136bd056906ecfd9f8188afb3e57d772580dd63..25b7fd9e492ebd406f6b411109190f4c32e861b8 100644 (file)
@@ -520,3 +520,5 @@ if [ "$CONFIG_SMP" != "y" ]; then
    bool 'Run uncached' CONFIG_MIPS_UNCACHED
 fi
 endmenu
+
+source lib/Config.in
index 4ebb9f27a8ca5750c23330dac8c0abf5d8e8daca..5ddba84ff19a7d5b800abd304dc5069c50406ec4 100644 (file)
@@ -276,3 +276,5 @@ if [ "$CONFIG_SMP" != "y" ]; then
    bool 'Run uncached' CONFIG_MIPS_UNCACHED
 fi
 endmenu
+
+source lib/Config.in
index f68410f663f749b03048c42c87b4426964428817..367242b77595de0e36435c74ce1a3c342edc2330 100644 (file)
@@ -208,3 +208,4 @@ comment 'Kernel hacking'
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
 endmenu
 
+source lib/Config.in
index 3545adc66875d33342882d67685410c7d22d7a03..7dfaf4d331e89ad7ab4f0e015977bc3b9e2c37de 100644 (file)
@@ -393,3 +393,5 @@ bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
 bool 'Include kgdb kernel debugger' CONFIG_KGDB
 bool 'Include xmon kernel debugger' CONFIG_XMON
 endmenu
+
+source lib/Config.in
index c545c36144202ab0b0ca7abae8aa9e0fdd489581..f5932ba5c2033500592528b4021064ae8969b429 100644 (file)
@@ -73,3 +73,4 @@ fi
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
 endmenu
 
+source lib/Config.in
index 5a9c5b68908075f1469db2ff3857b31cc8036a05..1ab8e3c235a5997b7aad0c9f9bc6382308bdb3fd 100644 (file)
@@ -77,3 +77,4 @@ fi
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
 endmenu
 
+source lib/Config.in
index 7b70ccccd73804ae97d44687e0c90800d85eb592..32fb2212b083fa3c48b702a4cbfcb225332a0f55 100644 (file)
@@ -386,3 +386,5 @@ if [ "$CONFIG_SH_STANDARD_BIOS" = "y" ]; then
    bool 'Early printk support' CONFIG_SH_EARLY_PRINTK
 fi
 endmenu
+
+source lib/Config.in
index 9f05197f9cf34ee5e89a8d94616cea6c83a2ac63..032e16082964410771e59f8a9eee99402a81d2fe 100644 (file)
@@ -266,3 +266,5 @@ comment 'Kernel hacking'
 
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
 endmenu
+
+source lib/Config.in
index 1c2aecb33be59592b9ba84217e8232b20e02a813..f9157e44dc9c8f03f8c528e1d91d9036dd8ae162 100755 (executable)
@@ -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
   ;;
index f8a9ea63d9246cd6ea5f27f73a86a7b0924bcbab..ecd4e6d150e70656960fc2769c50c3065bae656f 100644 (file)
@@ -4,9 +4,10 @@
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/threads.h>
-#include <linux/config.h>
+#include <linux/string.h>
 #include <linux/init.h>
 
 #include <asm/page.h>
index 609ab361f192c616d6e6a04e7c6a5699d0e54f39..ee31e2aaa53439013c6b60d36634bc8ad2a2049e 100644 (file)
@@ -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)
index 5633c882f3278becf895dfa3aa0b42c66ba953e8..d6d5e35e551ab0db0bb18a3ce125034b33d0afd3 100644 (file)
@@ -14,6 +14,6 @@ struct mm_struct init_mm = INIT_MM(init_mm);
  * 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) };
index 49e6f1a4c6db5f94569a33ac327e61a4bc89704b..5e3a4008de43d49fac13e989018ae4378732f77d 100644 (file)
@@ -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
index 0cadcd7908ef658cb84731165e63bd204174ce56..2e477bfbc8ecc5b69ce5e89919cda270f5902368 100644 (file)
@@ -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 @@ int cpu_idle(void)
                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 @@ out:
 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 @@ void show_regs(struct pt_regs * regs)
        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..
index 957ddc17ca30fb2c880e08e9078516b6906f9881..51bfe75ede920c099d0c33e845ed278e14c72243 100644 (file)
@@ -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 <linux/ptrace.h>
 #include <linux/unistd.h>
 #include <linux/mm.h>
+#include <linux/tty.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 
index 2a47968bbfc4a76a25a1f1fb3e1cd8e988fb72f0..c53e219dfc9f1c72558b86a412bcc097430c21d3 100644 (file)
@@ -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.
  *
index e8f5fb37b01ef661494be036c1eb1ffc149cf74e..a63ffb0670dd6590c5e696a01dcd96fcc1c4bd54 100644 (file)
@@ -127,7 +127,7 @@ void __init smp4d_callin(void)
        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 @@ void __init smp4d_boot_cpus(void)
                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 @@ void __init smp4d_boot_cpus(void)
                        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++)
index 676b9f2615912d500c4882b00bf48b7cb3399fdf..4cd8f8bb53938b7cc0d60adadcbc7701d2621b6e 100644 (file)
@@ -170,12 +170,11 @@ void __init smp4m_boot_cpus(void)
        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 @@ void __init smp4m_boot_cpus(void)
                        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... */
index 3180994194b84946615644f61bc746c32e25cf4d..8dd283c38e858f6147f9a2aa4e0589a962d92bcb 100644 (file)
@@ -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 @@ asmlinkage unsigned long sunos_mmap(unsigned long addr, unsigned long len,
         * 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;
index b7b7025fc7197ce58dcc5099a0f3f0ba09379769..d316096ea52e84275abfad0463f401b581492ef0 100644 (file)
@@ -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 @@ cpu3_startup:
        .align  4
 
 smp_do_cpu_idle:
+       call    C_LABEL(init_idle)
+        nop
        call    C_LABEL(cpu_idle)
         mov    0, %o0
 
index 0f718bac82a959b163185afdf6ba8deabd349f48..5f90082c1efac4fbf7264223ecdd235a911a60b9 100644 (file)
@@ -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 @@ __asm__ __volatile__ (                                                              \
        "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 @@ __asm__ __volatile__ (                                                              \
 "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"                                              \
index 165c83ab5e11485584957de9e08589c7e34d756d..5f63e466cdef8b97e6014ededfc4829fdcad7af8 100644 (file)
@@ -11,35 +11,49 @@ extern const struct exception_table_entry __stop___ex_table[];
 
 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;
 }
 
index b422c571cfd074097e035e0ce1d59dc87a06f085..8f1d7e79fa4f14310fcb288a8695a297b5480d9d 100644 (file)
@@ -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 @@ static void unhandled_fault(unsigned long address, struct task_struct *tsk,
 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 (&regs, 0, sizeof (regs));
+
+       default:
+               break;
+       };
+
+       memset(&regs, 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, &regs);
+       unhandled_fault(address, current, &regs);
+
        /* Not reached */
        return 0;
 }
index 34e289ed2843802940fb7e89022cd9125530de99..c0baac1389411d313f29ed44a9b7b4734d29ba60 100644 (file)
@@ -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 @@ void __init mem_init(void)
        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;
 
index be4522e1fadb6bb9bb4f964f5218bd27130c77ff..16fcc375f50f8c5a6b19218c2f5b8d08344a33f4 100644 (file)
@@ -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 @@ static void iounit_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus
        /* 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);
index 3bd631f36578bab09208f360930bd16f7a3a1f8c..cfd35dbdc4b5903f0f5530a3d9c55d075b7b6afa 100644 (file)
@@ -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 __u32 iommu_get_scsi_one_pflush(char *vaddr, unsigned long len, struct sb
 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 @@ static void iommu_get_scsi_sgl_gflush(struct scatterlist *sg, int sz, struct sbu
 {
        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 @@ static void iommu_get_scsi_sgl_pflush(struct scatterlist *sg, int sz, struct sbu
        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;
index 244619eb646161eccbb738f889a9ff2a8d3f03a4..96e3a342be5daf7753490db3d553b958eea7d347 100644 (file)
@@ -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 @@ struct linux_prom_ranges promlib_obio_ranges[PROMREG_MAX];
 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)
 {
index 64233d56fd5df48a04821e359f91b97a3a96ab2c..75ce131bbdd1638712d26d3c2bb1b09ab4ff05cd 100644 (file)
@@ -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 @@ CC_UNDECL    = -Wa,--undeclared-regs
 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
@@ -53,25 +48,6 @@ else
   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
 
 HEAD := arch/sparc64/kernel/head.o arch/sparc64/kernel/init_task.o
index 1b91160e21aca4c7d1e097d0f6483444fbf12d4f..72294c14b4f50e540bd24c6e434071e2e7861b9a 100644 (file)
@@ -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 @@ bool 'Symmetric multi-processing support' CONFIG_SMP
 # 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 @@ endmenu
 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" != "n" ]; then
       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 @@ endmenu
 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
index 813126deeda9a146cb92dde4c6367580ea5ee544..3ff8f9448112d9e139348df92428e9b8115c1048 100644 (file)
@@ -22,6 +22,7 @@ CONFIG_VT=y
 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 @@ CONFIG_WATCHDOG_RIO=m
 # Console drivers
 #
 CONFIG_PROM_CONSOLE=y
-CONFIG_FB=y
 
 #
 # Frame-buffer support
@@ -158,11 +158,11 @@ CONFIG_BLK_DEV_NBD=m
 #
 # 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_BLK_DEV_NBD=m
 #
 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_IDEDISK=y
 # 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_AUTO=y
 # 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_SCSI_AIC7XXX_OLD=m
 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_PCNET32=m
 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_EPIC100=m
 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_SLIP_SMART=y
 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_EFS_FS=m
 # 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_DEVICEFS=y
 # 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_IBMCAM=m
 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_DIGI_ACCELEPORT=m
 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=m
 # 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 @@ CONFIG_USB_SERIAL_OMNINET=m
 # USB Miscellaneous drivers
 #
 CONFIG_USB_RIO500=m
+CONFIG_USB_AUERSWALD=m
 
 #
 # Bluetooth support
@@ -861,4 +863,9 @@ CONFIG_BLUEZ_HCIVHCI=m
 #
 # 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
index f80dcd0c9ed71cd911899703e20207e45da75d36..b4b2515433bda6a487671fc77faf57ca0ae2a50b 100644 (file)
@@ -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 @@ check_asm: dummy
        @echo "#include <linux/config.h>" > tmp.c
        @echo "#undef CONFIG_SMP" >> tmp.c
        @echo "#include <linux/sched.h>" >> 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 <linux/config.h>" >> check_asm_data.c
        @echo "#undef CONFIG_SMP" >> check_asm_data.c
@@ -95,12 +95,12 @@ check_asm: dummy
        ./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 <linux/config.h>" > tmp.c
        @echo "#undef CONFIG_SMP" >> tmp.c
        @echo "#define CONFIG_SMP 1" >> tmp.c
        @echo "#include <linux/sched.h>" >> 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 <linux/config.h>" >> check_asm_data.c
        @echo "#undef CONFIG_SMP" >> check_asm_data.c
@@ -127,9 +127,9 @@ check_asm: dummy
        $(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 <linux/sched.h>" > 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 <linux/config.h>" >> check_asm_data.c
        @echo "#undef CONFIG_SMP" >> check_asm_data.c
@@ -140,7 +140,7 @@ check_asm: dummy
        $(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 @@ check_asm: dummy
        $(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 \
index dba732a6d9e52ef75e4da7d3c7640adf876e75ad..318efe3ccc277c878662a440bf48ad1585fbc50e 100644 (file)
@@ -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 @@ static void adjust_regs(struct linux_prom_registers *regp, int nregs,
                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;
        }
 }
index beaf6534807fd84f6d8e45b9b11744161673836d..65259c261dd62a77daceb7d6b8437f25b432f806 100755 (executable)
@@ -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
   ;;
index 1cf4f31e50b5bca4e6a53281fe9a80b1aff6009d..b75122e51cc9400d225602540a635d5103404c8d 100644 (file)
@@ -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 <linux/types.h>
 #include <linux/slab.h>
 #include <linux/list.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/errno.h>
 #include <linux/init.h>
 #include <asm/spitfire.h>
 #include <asm/chmctrl.h>
index acbb1b518be66039c2e1293fa90f85d019bed9ea..d0bbcf190f00879ae9cdf187686a338789a54b6c 100644 (file)
@@ -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 @@ do_ivec_xcall:
        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 @@ floppy_tdone:
        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 @@ floppy_fifo_emptied:
        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 @@ do_gettimeofday: /* %o0 = timevalp */
         *
         * 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 @@ do_gettimeofday:  /* %o0 = timevalp */
        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 @@ do_gettimeofday:  /* %o0 = timevalp */
         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
index 2a3ef1fb4d23a605d8bac4de1643be5aad9a3c9a..c4bb21f4c6114ea2058b2134e8e24474af78d73a 100644 (file)
@@ -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 @@ static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg)
                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 @@ typedef struct {
        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 @@ typedef struct {
 } 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 @@ static lv_t *get_lv_t(u32 p, int *errp)
        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 @@ static lv_t *get_lv_t(u32 p, int *errp)
                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 copy_lv_t(u32 ptr, lv_t *l)
 
 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 @@ static int do_lvm_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
        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 @@ static int do_lvm_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
                        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 @@ static int do_lvm_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
        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 @@ static int do_lvm_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
                }
                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 @@ static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg)
 }
 
 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 @@ static int do_usbdevfs_control(unsigned int fd, unsigned int cmd, unsigned long
        /* 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 @@ static int do_usbdevfs_control(unsigned int fd, unsigned int cmd, unsigned long
        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_GETFRAMING, do_atm_ioctl)
 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_REDUCE, do_lvm_ioctl)
 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 */
index 134be5cd793cfad601ff02ce9e559837aa55e073..12c93a3eee2653e289ef117c4e8b334af1da03d1 100644 (file)
@@ -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 @@ static int verify_one_map(struct scatterlist *dma_sg, struct scatterlist **__sg,
 
        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 @@ static int verify_one_map(struct scatterlist *dma_sg, struct scatterlist **__sg,
                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 @@ void verify_sglist(struct scatterlist *sg, int nents, iopte_t *iopte, int npages
                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 prepare_sg(struct scatterlist *sg, int nents)
        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;
index dedf08d2614c8f2e757493a0ab5565cf5bfbd451..59b4f9c2a453a15b5a854b3e68cb163eadddfa12 100644 (file)
@@ -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 <linux/delay.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#include <linux/kbd_ll.h>
 
 #include <asm/ptrace.h>
 #include <asm/processor.h>
@@ -35,6 +36,7 @@
 #include <asm/softirq.h>
 #include <asm/starfire.h>
 #include <asm/uaccess.h>
+#include <asm/cache.h>
 
 #ifdef CONFIG_SMP
 static void distribute_irqs(void);
@@ -53,10 +55,10 @@ static void distribute_irqs(void);
  * 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 @@ int show_interrupts(struct seq_file *p, void *v)
        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 @@ void enable_irq(unsigned int irq)
                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 @@ void handler_irq(int irq, struct pt_regs *regs)
        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 @@ void enable_prom_timer(void)
        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
index 38d253cbc35dfaf1ef2f625f8fea98561af03937..b2f341752db714008cbbba010ed7325f4b1af889 100644 (file)
@@ -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 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int
 }
 
 #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 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int
        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;
index 7ea3a3036a30a0e54f40ffd146caa5bf88269a9e..59ea29a97a415019d23aad405cb4a2233e35d023 100644 (file)
@@ -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 <linux/slab.h>
 
 #include <asm/pbm.h>
+#include <asm/fhc.h>
 #include <asm/iommu.h>
 #include <asm/irq.h>
 #include <asm/starfire.h>
@@ -371,6 +372,7 @@ static int __init psycho_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
                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 @@ static void psycho_pbm_init(struct pci_controller_info *p,
 {
        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 @@ static void psycho_pbm_init(struct pci_controller_info *p,
                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;
        }
index b5a58611fc593c60206859614937799afc1adbcb..7f86b6f0189fb368f6af46427d5e94c11a7d6ff4 100644 (file)
@@ -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 @@ static int __init sabre_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
 {
        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 @@ static int __init sabre_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
                case PCI_BASE_CLASS_MULTIMEDIA:
                case PCI_BASE_CLASS_MEMORY:
                case PCI_BASE_CLASS_BRIDGE:
+               case PCI_BASE_CLASS_SERIAL:
                        ret = 10;
                        break;
 
index 3e35c92e304743e28b35089fd83f57c76fa6efa6..a660d05199aa8731432df943ec2be77e2ed09b67 100644 (file)
@@ -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 @@ static int __init schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
 {
        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 @@ static int __init schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
                case PCI_BASE_CLASS_MULTIMEDIA:
                case PCI_BASE_CLASS_MEMORY:
                case PCI_BASE_CLASS_BRIDGE:
+               case PCI_BASE_CLASS_SERIAL:
                        ret = 10;
                        break;
 
index 35f1cc2d34687817f5de53ecf36e53233a401bca..320fa2587d7679f1db07cd40ebd3e045c41c6023 100644 (file)
@@ -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 @@ static int powerd(void *__unused)
        sprintf(current->comm, "powerd");
 
 again:
-       while(button_pressed == 0) {
+       while (button_pressed == 0) {
                spin_lock_irq(&current->sigmask_lock);
                flush_signals(current);
                spin_unlock_irq(&current->sigmask_lock);
@@ -98,16 +98,19 @@ void __init power_init(void)
 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 */
index 797e5c78c9c6d20e64a039c567c0102d95b92a44..cedff9e3a975efbc626dc47ece9597d3ba43c52c 100644 (file)
@@ -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 @@ int cpu_idle(void)
                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 @@ int cpu_idle(void)
 /*
  * 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 @@ void __show_regs(struct pt_regs * regs)
 #ifdef CONFIG_SMP
        unsigned long flags;
 
-       spin_lock_irqsave(&regdump_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(&regdump_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 @@ void __show_regs(struct pt_regs * regs)
               regs->u_regs[15]);
        show_regwindow(regs);
 #ifdef CONFIG_SMP
-       spin_unlock_irqrestore(&regdump_lock, flags);
+       spin_unlock(&regdump_lock);
+       __asm__ __volatile__("wrpr      %0, 0, %%pstate"
+                            : : "r" (flags));
 #endif
 }
 
@@ -462,6 +463,7 @@ static unsigned long clone_stackframe(unsigned long csp, unsigned long psp)
                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]));
 
@@ -582,6 +584,11 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
        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));
        memcpy(child_trap_frame, (((struct reg_window *)regs)-1), (TRACEREG_SZ+REGWIN_SZ));
index 20cd9a582fb3d3382afd3828a95b4566e4620bcf..5625e6cc5f3a93eeda598ffaa9a2bf25aeda87bc 100644 (file)
@@ -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)
 #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 @@ __handle_softirq:
                 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 @@ __handle_signal:
                .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 @@ __handle_softirq_continue:
                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
index 0e5a073ca69ae0ff29c15a9345c6bf81c8b03eae..4998dcfefb1ca2a68e8f25613187cb17673506a2 100644 (file)
@@ -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 @@ void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t dma_addr, size_t size,
 }
 
 #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 @@ int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int di
        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;
index 3e3b38ee4261cdded2848a049c46cf17cf983740..e3c79264a5e18425eae34ee096faac8eb79e6bd4 100644 (file)
@@ -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 @@ static __inline__ int __sem_update_count(struct semaphore *sem, int incr)
 "      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");
index 35402127855631ea2d849f01b0fc82103fe4ed24..10785cb9c00faecd12d57ec28f6805e450b02715 100644 (file)
@@ -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 <linux/ptrace.h>
 #include <linux/unistd.h>
 #include <linux/mm.h>
+#include <linux/tty.h>
 #include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
index 956a80427b68916ef70c77901a2a81d8ad3317b9..62db94b4f46bc9f77190d620e63ca4b084e06d3f 100644 (file)
@@ -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 <linux/ptrace.h>
 #include <linux/unistd.h>
 #include <linux/mm.h>
+#include <linux/tty.h>
 #include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
index a6f259cafad58dbc4c0fe87d5117911d1b003abd..a4fd67dd5ad40d57860ef087e920896d80b53ac6 100644 (file)
@@ -209,23 +209,10 @@ void __init smp_callin(void)
        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 @@ void __init smp_boot_cpus(void)
        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 @@ void __init smp_boot_cpus(void)
                        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 @@ retry:
                __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 @@ struct call_data_struct {
        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 @@ int smp_call_function(void (*func)(void *info), void *info,
 {
        struct call_data_struct data;
        int cpus = smp_num_cpus - 1;
+       long timeout;
 
        if (!cpus)
                return 0;
@@ -559,19 +546,36 @@ int smp_call_function(void (*func)(void *info), void *info,
        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_receive_signal;
 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 @@ void smp_flush_dcache_page_impl(struct page *page, int cpu)
        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 @@ void smp_flush_dcache_page_impl(struct page *page, int cpu)
                                                      __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 @@ void __init smp_tick_init(void)
        __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;
 }
 
index 234e0af430ddd41b7638ce651fbebf39fc087c59..8c9333d43fd7dfeed57ca7f6afc0eb146971b1c1 100644 (file)
@@ -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 @@ extern int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs);
 #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 @@ extern unsigned long phys_base;
 
 /* 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_number_map);
 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(sparc32_open);
 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 @@ EXPORT_SYMBOL_NOVERS(memmove);
 
 void VISenter(void);
 /* RAID code needs this */
-EXPORT_SYMBOL(VISenter);
+EXPORT_SYMBOL_NOVERS(VISenter);
+
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+EXPORT_SYMBOL(do_BUG);
+#endif
index f174b54f39de84416fcf67e3c4a9b94c8961ab5f..353ddf6ad25b2f0b14c918cf770c2830a7627813 100644 (file)
@@ -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 @@ asmlinkage unsigned long sys_getpagesize(void)
        return PAGE_SIZE;
 }
 
-#define COLOUR_ALIGN(addr)     (((addr)+SHMLBA-1)&~(SHMLBA-1))
+#define COLOUR_ALIGN(addr,pgoff)               \
+       ((((addr)+SHMLBA-1)&~(SHMLBA-1)) +      \
+        (((pgoff)<<PAGE_SHIFT) & (SHMLBA-1)))
 
 unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags)
 {
        struct vm_area_struct * vmm;
        unsigned long task_size = TASK_SIZE;
+       int do_color_align;
 
        if (flags & MAP_FIXED) {
                /* We do not accept a shared mapping if it would violate
@@ -63,11 +66,14 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
        if (!addr)
                addr = TASK_UNMAPPED_BASE;
 
-       if (flags & MAP_SHARED)
-               addr = COLOUR_ALIGN(addr);
+       do_color_align = 0;
+       if (filp || (flags & MAP_SHARED))
+               do_color_align = 1;
+
+       if (do_color_align)
+               addr = COLOUR_ALIGN(addr, pgoff);
        else
                addr = PAGE_ALIGN(addr);
-
        task_size -= len;
 
        for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
@@ -81,8 +87,8 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
                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 @@ extern asmlinkage long sys_personality(unsigned long);
 
 asmlinkage int sparc64_personality(unsigned long personality)
 {
-       unsigned long ret, trying, orig_ret;
-
-       trying = ret = personality;
-
-       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)
-               ret = PER_LINUX;
-
-       orig_ret = ret;
-       ret = sys_personality(ret);
+       int ret;
 
-       if (orig_ret == PER_LINUX && trying == PER_LINUX32) {
-               current->personality = PER_LINUX32;
+       if (current->personality == PER_LINUX32 && personality == PER_LINUX)
+               personality = PER_LINUX32;
+       ret = sys_personality(personality);
+       if (ret == PER_LINUX32)
                ret = PER_LINUX;
-       }
 
-       return (int) ret;
+       return ret;
 }
 
 /* Linux version of mmap */
index 39e2781f57d3ba2836363ad9eeb7390ce97ea2ec..47e5a445a2a0d2a390e95875c81b14c3f18dce1b 100644 (file)
@@ -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 @@ asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 of
        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 @@ asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 of
                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 @@ asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 of
        }
 
        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 @@ asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 of
                         (unsigned long) prot, (unsigned long) flags,
                         (unsigned long) off);
        up_write(&current->mm->mmap_sem);
-       if(!ret_type)
+       if (!ret_type)
                retval = ((retval < 0xf0000000) ? 0 : retval);
 out_putf:
        if (file)
index b89235acfc2c7640da3f984b9a210f006df4cdef..3119c67b398ac990bca52baba11f0d59607793b4 100644 (file)
@@ -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 @@ void __init time_init(void)
        unsigned long clock;
 
        init_timers(timer_interrupt, &clock);
-       timer_tick_offset = clock / HZ;
        timer_ticks_per_usec_quotient = ((1UL<<32) / (clock / 1000020));
 }
 
index fdf4a00f270a36094b1c284534df4f70ecae5caa..eda8ed5ab3b2a13db15e086748e4c93dce1125a3 100644 (file)
@@ -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 @@ startup_continue:
        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
 
index 90063fb4135bf1e31c2dedd4ccbb16c1ddb0a0ae..f022447c8cdb19c2452e7adbdae698c689dfce51 100644 (file)
@@ -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)
 
 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 @@ void bad_trap (struct pt_regs *regs, long lvl)
        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 @@ void bad_trap_tl1 (struct pt_regs *regs, long lvl)
        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 @@ static int cheetah_fix_ce(unsigned long physaddr)
        __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 @@ void do_getpsr(struct pt_regs *regs)
        }
 }
 
+/* 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
 }
index 182fb0f96dc692dd67688824207a1841627c5e36..9b2e54e269074f2d9de16fc55036379edc17a26f 100644 (file)
@@ -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)
 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)
index 35a34ebbf7dda359f48b381da1d227b938acffa2..77be8b1f3e0cef1aceed6878ed053f7976165a49 100644 (file)
@@ -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 @@ __atomic_add: /* %o0 = increment, %o1 = atomic_ptr */
        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 @@ __atomic_sub: /* %o0 = increment, %o1 = atomic_ptr */
        cas     [%o1], %g5, %g7
        cmp     %g5, %g7
        bne,pn  %icc, __atomic_sub
-        nop
+        membar #StoreLoad | #StoreStore
        retl
         sub    %g7, %o0, %o0
 atomic_impl_end:
index fafe016c22d5d8e356964c9cfdce99b88617f0e3..fa8558237a7f2724e9c94604a0f210b9c6358e97 100644 (file)
@@ -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 @@ ___test_and_set_bit:  /* %o0=nr, %o1=addr */
        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 @@ ___test_and_clear_bit:        /* %o0=nr, %o1=addr */
        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 @@ ___test_and_change_bit:       /* %o0=nr, %o1=addr */
        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 @@ ___test_and_set_le_bit:       /* %o0=nr, %o1=addr */
        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 @@ ___test_and_clear_le_bit:   /* %o0=nr, %o1=addr */
        bne,a,pn %icc, 1b
         lduwa  [%o1] ASI_PL, %g7
 2:     retl
-        nop
+        membar #StoreLoad | #StoreStore
 
        .globl  __bitops_end
 __bitops_end:
index dedc03521902b94f796132dd700708ec2c67268f..7042ae217cfc01c70a9676c01ff81f0d021ab290 100644 (file)
@@ -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)
        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)
        .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 @@ copy_user_page: /* %o0=dest, %o1=src, %o2=vaddr */
        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 @@ cheetah_patch_1:
        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 @@ cheetah_patch_1:
        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 @@ cheetah_patch_1:
         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 @@ clear_user_page:    /* %o0=dest, %o1=vaddr */
        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 @@ cheetah_patch_2:
        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 @@ cheetah_patch_2:
 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
index b51811432239cc4d7dfbc5cfe328e7fc501f15bb..ea62c3ecc2f9fa2fb873c0697499d11662ba886a 100644 (file)
@@ -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)
 #include <linux/spinlock.h>
 #include <asm/system.h>
 
-#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 @@ void _do_spin_lock(spinlock_t *lock, char *str)
        unsigned long caller, val;
        int stuck = INIT_STUCK;
        int cpu = smp_processor_id();
+       int shown = 0;
 
        GET_CALLER(caller);
 again:
@@ -67,7 +65,8 @@ again:
        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 @@ again:
        }
        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 @@ int _spin_trylock(spinlock_t *lock)
        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 @@ void _do_spin_unlock(spinlock_t *lock)
        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 @@ void _do_read_lock (rwlock_t *rw, char *str)
        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 @@ wlock_again:
        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 @@ void _do_read_unlock (rwlock_t *rw, char *str)
        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 @@ runlock_again:
        : "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 @@ void _do_write_lock (rwlock_t *rw, char *str)
        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 @@ wlock_again:
        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 @@ wlock_again:
                 * 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 @@ wlock_again:
                : "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 @@ wlock_again:
        /* 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 @@ wlock_again:
        : "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 */
index 2a59b278821f890df327eb2c062a5f4b82971508..b7c2631dd111c000f7b1a833cf96fa28a8668c70 100644 (file)
@@ -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 <linux/config.h>
 
+#ifndef CONFIG_DEBUG_SPINLOCK
        .text
        .align  64
 
@@ -34,13 +36,15 @@ nzero:      cas     [%o0], %g5, %g7
        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 @@ spin_on_lock:
        ba,pt   %xcc, to_zero
         nop
        nop
+
+#endif /* !(CONFIG_DEBUG_SPINLOCK) */
index dcd982b7bc462aaf8f2109695a0b28c13836595f..595eff631ff0103f6d3a7edfd1ebdc92f8949d8b 100644 (file)
@@ -11,35 +11,49 @@ extern const struct exception_table_entry __stop___ex_table[];
 
 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;
 }
 
index 2d363621a44be15df51361d625dbec510ed880da..151ff52bbd2c1028bb5dadb040f26069db8c52c0 100644 (file)
@@ -111,7 +111,7 @@ int do_check_pgt_cache(int low, int high)
 
 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 @@ atomic_t dcpage_flushes_xcall = ATOMIC_INIT(0);
 
 __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 @@ static __inline__ void set_dcache_dirty(struct page *page)
                             "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 @@ static __inline__ void clear_dcache_dirty_cpu(struct page *page, unsigned long c
                             "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 @@ void mmu_info(struct seq_file *m)
        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 {
index 8faa35963fb9843443cb9e7b3d1f72d2e1219f78..828749fac6ecc8a57e288c3f86191867557915d7 100644 (file)
@@ -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 @@ __spitfire_flush_tlb_range_constant_time: /* %o0=ctx, %o1=start, %o3=end */
        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 @@ __spitfire_xcall_flush_tlb_all:
        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 @@ __cheetah_xcall_flush_cache_all:
 
        .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
 
index 98b1610a2327fca799a2e0957855da0a2439c320..0ba71673d30664d225b888533adbbd7796049b30 100644 (file)
@@ -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 @@ static int report_statvfs(struct vfsmount *mnt, struct inode *inode, u32 buf)
                    __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 @@ static int report_statvfs64(struct vfsmount *mnt, struct inode *inode, u32 buf)
                    __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)    ||
index 5a368d50fe8e45c5bc044d24af5385d566f36c4b..339372977f5d05970d30c8e6e498f0c10f7cc250 100644 (file)
@@ -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 <linux/mman.h>
 #include <linux/file.h>
 #include <linux/timex.h>
+#include <linux/major.h>
 
 #include <asm/uaccess.h>
 #include <asm/string.h>
@@ -74,8 +75,8 @@ static u32 do_solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u64 o
                        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;
index 320f85c612d6284b1813b53418a87ea72a9913fb..dd06c16183f8d6bf9eec27a8680b90a0d2451fe1 100644 (file)
@@ -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 @@ static int socksys_open(struct inode * inode, struct file * filp)
                (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;
index 6728b593bb069f5374e0fbd814b38072cce85101..d2799895117b8cec70214e0f6a17ff98ab3da66e 100644 (file)
@@ -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 @@ asmlinkage int solaris_putmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
        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);
index 7902e3fc7b2d9862431927805aea91fd9a5888a6..c78754672c4124a0c38f91b1b0fe7a3ffb473b7d 100644 (file)
@@ -35,6 +35,7 @@ if [ "$CONFIG_PARIDE" = "y" -o "$CONFIG_PARIDE" = "m" ]; then
 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
index e2792736f08e6d84cbc3395096c289ea1e17aece..35543c2fa91ec284e415e8e61c43e31721438f96 100644 (file)
@@ -126,6 +126,8 @@ static struct block_device_operations cciss_fops  = {
        revalidate:             frevalidate_logvol,
 };
 
+#include "cciss_scsi.c"                /* For SCSI tape support */
+
 /*
  * Report information about this controller.
  */
@@ -160,6 +162,7 @@ static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
                 h->Qdepth, h->maxQsinceinit, h->max_outstanding, h->maxSG);
 
         pos += size; len += size;
+       cciss_proc_tape_report(ctlr, buffer, &pos, &len);
        for(i=0; i<h->num_luns; i++) {
                 drv = &h->drv[i];
                 size = sprintf(buffer+len, "cciss/c%dd%d: blksz=%d nr_blocks=%d\n",
@@ -179,20 +182,53 @@ static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
         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 @@ static int sendcmd(
        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 @@ static int sendcmd(
                                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 @@ static int sendcmd(
                        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 @@ static int sendcmd(
                         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 @@ static int sendcmd(
                                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 @@ static void do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
                                } 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 @@ static void cciss_getgeometry(int cntl_num)
         }
        /* 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 @@ static void cciss_getgeometry(int cntl_num)
        }
        /* 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 @@ static void cciss_getgeometry(int cntl_num)
 
                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 @@ static void cciss_getgeometry(int cntl_num)
                /* 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 @@ static int __init cciss_init_one(struct pci_dev *pdev,
 
        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 @@ static int __init cciss_init_one(struct pci_dev *pdev,
                        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 @@ static void __devexit cciss_remove_one (struct pci_dev *pdev)
        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); 
        
index 1dafe1ec538eebbbeeefb3a3c6dabe8407f1b60f..c6eb34da2c147c6ced68e0b1c6d9e6367280db25 100644 (file)
@@ -83,6 +83,9 @@ struct ctlr_info
        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 */
index 7faf6f05ca90787749029b7d2c540d8063300820..6ba126d3def5b41dfdff66d9c05091c9f81aff21 100644 (file)
@@ -89,6 +89,7 @@ typedef union _u64bit
 //STRUCTURES
 //###########################################################################
 #define CISS_MAX_LUN   16      
+#define CISS_MAX_PHYS_LUN      1024
 // SCSI-3 Cmmands 
 
 #pragma pack(1)        
@@ -101,6 +102,7 @@ typedef struct _InquiryData_struct
 } 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 @@ typedef struct _ErrorInfo_struct {
 #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 @@ typedef struct _CommandList_struct {
   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 --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
new file mode 100644 (file)
index 0000000..ad40c68
--- /dev/null
@@ -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 <asm/atomic.h>
+#include <linux/timer.h>
+
+#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; i<CMD_STACK_SIZE; i++) {
+               stk->elem[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;i<len;i++)
+               {
+                       if ((i % xmargin) == 0 && i>0) printk("\n");
+                       if ((i % xmargin) == 0) printk("0x%04x:", i);
+                       printk(" %02x", *x);
+                       x++;
+               }
+               printk("\n");
+       }
+       if (ascii)
+       {
+               x = c;
+               for (i=0;i<len;i++)
+               {
+                       if ((i % amargin) == 0 && i>0) 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;i<ccissscsi[ctlr].ndevices;i++)
+               target_taken[ccissscsi[ctlr].dev[i].target] = 1;
+       
+       for (i=0;i<CCISS_MAX_SCSI_DEVS_PER_HBA;i++) {
+               if (!target_taken[i]) {
+                       *bus = 0; *target=i; *lun = 0; found=1;
+                       break;
+               }
+       }
+       return (!found);        
+}
+
+static int 
+cciss_scsi_add_entry(int ctlr, int hostno, 
+               unsigned char *scsi3addr, int devtype)
+{
+       /* assumes hba[ctlr]->scsi_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;i<ccissscsi[ctlr].ndevices-1;i++)
+               ccissscsi[ctlr].dev[i] = ccissscsi[ctlr].dev[i+1];
+       ccissscsi[ctlr].ndevices--;
+       printk("cciss%d: %s device c%db%dt%dl%d removed.\n",
+               ctlr, DEVICETYPE(sd.devtype), hostno, 
+                       sd.bus, sd.target, sd.lun);
+}
+
+
+#define SCSI3ADDR_EQ(a,b) ( \
+       (a)[7] == (b)[7] && \
+       (a)[6] == (b)[6] && \
+       (a)[5] == (b)[5] && \
+       (a)[4] == (b)[4] && \
+       (a)[3] == (b)[3] && \
+       (a)[2] == (b)[2] && \
+       (a)[1] == (b)[1] && \
+       (a)[0] == (b)[0])
+
+static int
+adjust_cciss_scsi_table(int ctlr, int hostno,
+       struct cciss_scsi_dev_t sd[], int nsds)
+{
+       /* sd contains scsi3 addresses and devtypes, but
+          bus target and lun are not filled in.  This funciton
+          takes what's in sd to be the current and adjusts
+          ccissscsi[] to be in line with what's in sd. */ 
+
+       int i,j, found, changes=0;
+       struct cciss_scsi_dev_t *csd;
+       unsigned long flags;
+
+       CPQ_TAPE_LOCK(ctlr, flags);
+
+       /* find any devices in ccissscsi[] that are not in 
+          sd[] and remove them from ccissscsi[] */
+
+       i = 0;
+       while(i<ccissscsi[ctlr].ndevices) {
+               csd = &ccissscsi[ctlr].dev[i];
+               found=0;
+               for (j=0;j<nsds;j++) {
+                       if (SCSI3ADDR_EQ(sd[j].scsi3addr,
+                               csd->scsi3addr)) {
+                               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;i<nsds;i++) {
+               found=0;
+               for (j=0;j<ccissscsi[ctlr].ndevices;j++) {
+                       csd = &ccissscsi[ctlr].dev[j];
+                       if (SCSI3ADDR_EQ(sd[i].scsi3addr,
+                               csd->scsi3addr)) {
+                               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;i<ccissscsi[ctlr].ndevices;i++) {
+               sd = &ccissscsi[ctlr].dev[i];
+               if (sd->bus == 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; i<num_luns; i++) {
+               /* Execute an inquiry to figure the device type */
+               memset(inq_buff, 0, sizeof(InquiryData_struct));
+               memcpy(scsi3addr, ld_buff->LUN[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;i<ccissscsi[cntl_num].ndevices;i++)
+               printk("Tape device presented at c%db%dt%dl%d\n", 
+                       cntl_num, // <-- this is wrong
+                       ccissscsi[cntl_num].dev[i].bus,
+                       ccissscsi[cntl_num].dev[i].target,
+                       ccissscsi[cntl_num].dev[i].lun);
+#endif                 
+       CPQ_TAPE_UNLOCK(cntl_num, flags);
+       kfree(ld_buff);
+       kfree(inq_buff);
+       return;
+}
+
+static void
+complete_scsi_command( CommandList_struct *cp, int timeout, __u32 tag)
+{
+       Scsi_Cmnd *cmd;
+       ctlr_info_t *ctlr;
+       u64bit addr64;
+       ErrorInfo_struct *ei;
+
+       ei = cp->err_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; i<num_luns; i++)
+       {
+               int devtype;
+
+               /* for each physical lun, do an inquiry */
+               memset(inq_buff, 0, sizeof(InquiryData_struct));
+               memcpy(&scsi3addr[0], &ld_buff->LUN[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(&currentsd[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 --git a/drivers/block/cciss_scsi.h b/drivers/block/cciss_scsi.h
new file mode 100644 (file)
index 0000000..1e580f1
--- /dev/null
@@ -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 <scsi/scsicam.h> /* 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 */
index 6a92fa4f5e28f20c2c369590ac6a88b0ac389fac..b67eeec19db3f2af941d7125abce1acaf1ab48de 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/blkpg.h>
 #include <linux/timer.h>
 #include <linux/proc_fs.h>
+#include <linux/devfs_fs_kernel.h>
 #include <linux/init.h>
 #include <linux/hdreg.h>
 #include <linux/spinlock.h>
@@ -70,6 +71,7 @@ MODULE_LICENSE("GPL");
 
 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 @@ void cleanup_module(void)
 
                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 @@ int __init cpqarray_init(void)
                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]);
@@ -1795,6 +1800,14 @@ static void getgeometry(int ctlr)
                                        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;
                                info_p->drv_assign_map
index 8fcdc77fad1320795a6f73e5069493cd6976da61..8b5536023cc5b5a26114fa183a403ef7d5646be0 100644 (file)
@@ -58,8 +58,6 @@ inline int bio_rq_in_between(struct bio *bio, struct request *rq,
 
        next_rq = list_entry(next, struct request, queuelist);
 
-       BUG_ON(next_rq->flags & REQ_STARTED);
-
        /*
         * not a sector based request
         */
@@ -147,9 +145,10 @@ inline int elv_try_last_merge(request_queue_t *q, struct request **req,
         */
        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;
        }
 
@@ -231,6 +230,12 @@ void elevator_linus_add_request(request_queue_t *q, struct request *rq,
        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)];
 
index f98c41e49c017181d5c1bddc55201e221e9737e9..142b4a8e8391099fd73f68f6be1f1bc69d261234 100644 (file)
@@ -818,7 +818,6 @@ int blk_init_queue(request_queue_t *q, request_fn_proc *rfn, spinlock_t *lock)
        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);
 
@@ -963,12 +962,6 @@ static inline void add_request(request_queue_t * q, struct request * req,
 {
        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 @@ again:
        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 @@ again:
 
                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);
 
index 49b2e7dc1d5b02e24eb63628c19499bab1c8ef57..740e5c8b82bb38dd59e977a731f6b44319eef401 100644 (file)
@@ -206,7 +206,7 @@ struct request *nbd_read_stat(struct nbd_device *lo)
        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 @@ void nbd_do_it(struct nbd_device *lo)
                        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 @@ void nbd_clear_que(struct nbd_device *lo)
 #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" );
index f8964bf1e71f990d1dd72d6129f303f683da198b..6f27a6120c2cead114fda50f90977ad30606acf8 100644 (file)
@@ -785,6 +785,9 @@ no_irq:
                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 @@ no_irq:
        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");
index a02c0fccb70963e4d71a1080a31b20fe814239b3..3fb9ad117ac0dad178a3df9258f69b98246085d2 100644 (file)
@@ -641,7 +641,7 @@ static int lock_rdev(mdk_rdev_t *rdev)
        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 @@ struct {
  * 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 @@ static void autostart_arrays(void)
        }
        dev_cnt = 0;
 
-       autorun_devices(-1);
+       autorun_devices(to_kdev_t(-1));
 }
 
 static struct {
@@ -3855,14 +3855,14 @@ void __init md_setup_drive(void)
                                *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 @@ void __init md_setup_drive(void)
 
                        devname = p;
                }
-               devices[i] = 0;
+               devices[i] = to_kdev_t(0);
 
                if (!md_setup_args.device_set[minor])
                        continue;
@@ -3908,7 +3908,10 @@ void __init md_setup_drive(void)
                        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<<MD_DISK_ACTIVE)|(1<<MD_DISK_SYNC);
@@ -3922,7 +3925,10 @@ void __init md_setup_drive(void)
                        }
                } else {
                        /* persistent */
-                       for (i = 0; (dev = devices[i]); i++) {
+                       for (i = 0; i <= MD_SB_DISKS; i++) {
+                               dev = devices[i];
+                               if (kdev_none(dev))
+                                       break;
                                dinfo.major = major(dev);
                                dinfo.minor = minor(dev);
                                add_new_disk (mddev, &dinfo);
index 94d3cbb7c79b0d95cffd2d9dda7c0d50a76ea9f4..792e787fc7abf1fda0f27657c55b49cf10f51f59 100644 (file)
@@ -274,6 +274,7 @@ static int multipath_make_request (mddev_t *mddev, int rw,
        memcpy(bh_req, bh, sizeof(*bh));
        bh_req->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;
index 6773bf201e7d6f4ae96d388357f2e86447776544..385f26395039b7490d291b3b207682737d862ee3 100644 (file)
@@ -469,6 +469,7 @@ static struct buffer_head *raid5_build_block (struct stripe_head *sh, int i)
 
        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 @@ static void handle_stripe(struct stripe_head *sh)
                        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);
index 9387ad20f8e7fc4c61891670d200eb7ec6c95e41..bd57c42e61a0c1b8bf6cbbc3206e81dd6fbb421e 100644 (file)
@@ -892,13 +892,13 @@ static void i2ob_request(request_queue_t *q)
        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;
index 765d9bd6b40d701dd0a361173a419bdc1af7a3bf..7c99d9e3a4dd43e41a9d6d77e003bb98e4406355 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/crc32.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -569,7 +570,7 @@ static void lance_load_multicast (struct net_device *dev)
         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 @@ static void lance_load_multicast (struct net_device *dev)
                 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);
         }
index 0fb2a48fa8372f2ea210a4be6c6aec79a25780ad..6875780ae87eacb7457a32bf0a089bb46d5b8011 100644 (file)
@@ -132,9 +132,6 @@ struct lance_private
        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
  */
index ff5f5792fb03a6ba5c74c5a7368d4e286e76f43d..e9f2252cf72c115b8d6c05b8a3afa8eabc7023da 100644 (file)
@@ -55,6 +55,7 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/ethtool.h>
+#include <linux/crc32.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
@@ -723,22 +724,6 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
 /* 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)
 {
        struct cp_private *cp = dev->priv;
index 2d219b46649af4ff5a4fdf7c651b8f296019ee81..c96bce2accdcd0355c736e2a88ad6128e6070673 100644 (file)
 #include <linux/ethtool.h>
 #include <linux/mii.h>
 #include <linux/completion.h>
+#include <linux/crc32.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
@@ -587,7 +588,6 @@ static void rtl8139_interrupt (int irq, void *dev_instance,
 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);
@@ -2371,23 +2371,6 @@ static struct net_device_stats *rtl8139_get_stats (struct net_device *dev)
 /* 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)
 {
        struct rtl8139_private *tp = dev->priv;
index 67064058e2181917c2149b4dba799d23cf1e9f9f..06e0746a90610aa061f4c04f4bfb173cd599e5fb 100644 (file)
@@ -68,6 +68,7 @@ static const char version[] =
 #include <linux/in.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
+#include <linux/crc32.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -884,27 +885,6 @@ static struct net_device_stats *get_stats(struct net_device *dev)
        return &ei_local->stat;
 }
 
-/*
- * 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 @@ static inline void make_mc_bits(u8 *bits, struct net_device *dev)
 
        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; i<ETH_ALEN; i++)
-                       crc = update_crc(dmi->dmi_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 --git a/drivers/net/Makefile.lib b/drivers/net/Makefile.lib
new file mode 100644 (file)
index 0000000..af22a0e
--- /dev/null
@@ -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
index e00dee5c48cce095f39815f7d8c6508c46329e9e..63ed2cbd6b1f9a503ff5f7ba06c4d5d07d971284 100644 (file)
@@ -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 <linux/string.h>
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/crc32.h>
 
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -639,7 +641,7 @@ static void lance_load_multicast (struct net_device *dev)
        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 @@ static void lance_load_multicast (struct net_device *dev)
                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);
        }
index f6e4d255f4f74633c5b9c8a89622965a9e81d8c6..184ad573dbda3b75ab88f30970c59300a913dc46 100644 (file)
@@ -43,9 +43,6 @@ struct lance_regs {
 };
 
 
-#define CRC_POLYNOMIAL_BE 0x04c11db7UL  /* Ethernet CRC, big endian */
-#define CRC_POLYNOMIAL_LE 0xedb88320UL  /* Ethernet CRC, little endian */
-
 /*
  *             Am7990 Control and Status Registers
  */
index 30840e5d530f9771dfdbd8d337631f53a07beb1c..b7bb8f4ca95a99779d50d555ebd1ce281f41ee03 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/skbuff.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/crc32.h>
 
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -308,33 +309,13 @@ static struct net_device_stats *am79c961_getstats (struct net_device *dev)
        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;
index 5a9ad62ad6f2295420e374b72529c3853b8c0301..badecbc401e160dd9453b1932334173aab72bf88 100644 (file)
@@ -49,6 +49,7 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/init.h>
+#include <linux/crc32.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -804,27 +805,6 @@ net_get_stats(struct net_device *dev)
   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)
 {
index 62d7ceaeaad04e819167f7c922eebc964df63580..5a31cfe28fd93bd33856128dccca7a6e04065413 100644 (file)
@@ -140,6 +140,7 @@ static int xcvr[NUM_UNITS];                         /* The data transfer mode. */
 #include <asm/dma.h>
 #include <linux/errno.h>
 #include <linux/init.h>
+#include <linux/crc32.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -857,26 +858,6 @@ net_get_stats(struct net_device *dev)
  *     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)
 {
        struct net_local *lp = (struct net_local *)dev->priv;
index 168b9dd1543f8869dbb2deeca6f9b4fd34b01eb9..a9a4ac16240c2190776f8519996eea0df1309a42 100644 (file)
@@ -47,6 +47,7 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/delay.h>
+#include <linux/crc32.h>
 #include <asm/irq.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -1094,22 +1095,6 @@ static void au1000_tx_timeout(struct net_device *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)
 {
        struct au1000_private *aup = (struct au1000_private *) dev->priv;
index cf0d30df691bf33c0b85c2529a2488a237605eb4..e94ccb93c34151c8871acebed91343394c2e31f2 100644 (file)
@@ -1053,16 +1053,13 @@ static void bmac_set_multicast(struct net_device *dev)
 
 /* 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 @@ static void bmac_set_multicast(struct net_device *dev)
                        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);
                }
index 63e0c1e1fb86a8819cdf8eade0f7cf4c2dfaab91..e9736dc3ce891a25df220a78eca3b2bbbd1e309e 100644 (file)
  *
  * 2001/10/23 - Takao Indoh <indou dot takao at jp dot fujitsu dot com>
  *     - Various memory leak fixes
+ *
+ * 2001/11/5 - Mark Huth <mark dot huth at mvista dot com>
+ *     - 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 <linux/config.h>
 
 #include <linux/if_bonding.h>
 #include <linux/smp.h>
-#include <limits.h>
 #include <linux/if_ether.h>
 #include <linux/if_arp.h>
 
@@ -257,6 +264,7 @@ static void bond_set_slave_inactive_flags(slave_t *slave);
 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_dev_link(struct net_device *dev)
 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_open(struct net_device *dev)
 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 @@ static int bond_close(struct net_device *master)
        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 @@ static int bond_release(struct net_device *master, struct net_device *slave)
        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 @@ static void bond_mii_monitor(struct net_device *master)
 
        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 @@ static void bond_mii_monitor(struct net_device *master)
                } /* 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 @@ static void bond_mii_monitor(struct net_device *master)
                }
        }
 
-       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 @@ static void bond_arp_monitor(struct net_device *master)
 
        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 @@ static void bond_arp_monitor(struct net_device *master)
         * 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 @@ static void bond_arp_monitor(struct net_device *master)
                                 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 @@ static int bond_info_query(struct net_device *master, struct ifbond *info)
 {
        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 @@ static int bond_slave_info_query(struct net_device *master,
        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 @@ static int bond_ioctl(struct net_device *master_dev, struct ifreq *ifr, int cmd)
        }
 
        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 @@ static int bond_xmit_xor(struct sk_buff *skb, struct net_device *dev)
        }
 
        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 @@ static int bond_xmit_xor(struct sk_buff *skb, struct net_device *dev)
 
        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 @@ static int bond_get_info(char *buf, char **start, off_t offset, int length)
        off_t begin = 0;
        u16 link;
        slave_t *slave = NULL;
+       unsigned long flags;
 
        while (bond != NULL) {
                /*
@@ -1757,17 +1802,19 @@ static int bond_get_info(char *buf, char **start, off_t offset, int length)
                 */
                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 @@ static int bond_get_info(char *buf, char **start, off_t offset, int length)
                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 @@ static int bond_get_info(char *buf, char **start, off_t offset, int length)
                        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 @@ static int bond_get_info(char *buf, char **start, off_t offset, int length)
                        len = 0;
                }
 
-               read_unlock(&bond->ptrlock);
 
                bond = bond->next_bond;
        }
@@ -1844,7 +1892,14 @@ static int bond_event(struct notifier_block *this, unsigned long event,
                        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;
index 45ceb740c567704295f9efae580d0c3a1dc63d3b..2d8145dc3eca66b9e40ead1c2828642085f0a044 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/compiler.h>
 #include <linux/sched.h>
 #include <linux/rtnetlink.h>
+#include <linux/crc32.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
@@ -656,41 +657,6 @@ static int de_start_xmit (struct sk_buff *skb, struct net_device *dev)
    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)
 
index 2b5cff2b930c398c24910fe43b2cbfc2cf3775f8..3af726812573e9f86ca7d5795bc3594d0f53ddc9 100644 (file)
                            'pb' is now only initialized if a de4x5 chip is
                            present. 
                            <france@handhelds.org>  
+      0.547  08-Nov-01    Use library crc32 functions by <Matt_Domsch@dell.com>
     =========================================================================
 */
 
@@ -457,6 +458,7 @@ static const char *version = "de4x5.c:V0.546 2001/02/22 davies@maniac.ultranet.c
 #include <linux/init.h>
 #include <linux/version.h>
 #include <linux/spinlock.h>
+#include <linux/crc32.h>
 
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -622,9 +624,6 @@ struct parameters {
 #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 @@ SetMulticastFilter(struct net_device *dev)
     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 @@ SetMulticastFilter(struct net_device *dev)
            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 & HASH_BITS;  /* hashcode is 9 LSb of CRC */
                
                byte = hashcode >> 3;        /* bit[3-8] -> byte in filter */
index 173e42b4af39b0dbbc3559bd24725545ef7b0c93..f5c828869753da1067916e66b2a1d40e2a5fdb09 100644 (file)
@@ -79,6 +79,7 @@ static char *lancestr = "LANCE";
 #include <linux/a.out.h>
 #include <linux/tty.h>
 #include <linux/delay.h>
+#include <linux/crc32.h>
 #include <asm/io.h>
 #include <linux/etherdevice.h>
 
@@ -88,9 +89,6 @@ unsigned long dmaptr;
 #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 @@ static void lance_load_multicast(struct net_device *dev)
        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 @@ static void lance_load_multicast(struct net_device *dev)
                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);
        }
index e6f061bedbc691369130666a687e7b537f875006..9095f2fc6bc6c6e929f2376cb74f9dc1c7d270e1 100644 (file)
                           by <peterd@pnd-pc.demon.co.uk>
       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
 
     =========================================================================
 */
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/crc32.h>
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -296,9 +299,6 @@ static int depca_debug = 1;
 #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 @@ static void SetMulticastFilter(struct net_device *dev)
   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 @@ static void SetMulticastFilter(struct net_device *dev)
       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<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);
index 16107578479d004f6fb48fc7fa70321674cb584c..1c232734fc51fa8eb68d485b5d13085848584a4c 100644 (file)
@@ -75,7 +75,6 @@ static int rio_close (struct net_device *dev);
 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 @@ parse_eeprom (struct net_device *dev)
        }
 
        /* 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 @@ change_mtu (struct net_device *dev, int new_mtu)
        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 @@ set_multicast (struct net_device *dev)
 
        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);
index fb1a8cd2591679cee8ac596136c713862f3732a3..49ed98d4d87830c8388ca5a653fef1f48269ebb1 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/init.h>
+#include <linux/crc32.h>
 #include <asm/processor.h>     /* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
index c94409b258b2f8cc165eb653dec93761b86160bc..4cca074aa5402c58367e87de378fb13071e75c71 100644 (file)
@@ -84,6 +84,7 @@
 #include <linux/skbuff.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
+#include <linux/crc32.h>
 
 #include <asm/processor.h>
 #include <asm/bitops.h>
@@ -288,72 +289,6 @@ static u8 HPNA_NoiseFloor; /* Default: HPNA NoiseFloor */
 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_reuse_skb(struct dmfe_board_info *, struct sk_buff *);
 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 @@ static u16 phy_read_1bit(unsigned long ioaddr)
  *             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;
 }
 
 
index 468c675b4ba053c6169ea215176c0b07132c0706..7c30e77503fe2c75c3a5bb350421c5491b68bd19 100644 (file)
@@ -124,6 +124,7 @@ static int rx_copybreak;
 #include <linux/spinlock.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
+#include <linux/crc32.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -1302,27 +1303,6 @@ static struct net_device_stats *epic_get_stats(struct net_device *dev)
    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)
 {
        long ioaddr = dev->base_addr;
index 4b9319011880f0d03a2d1c58538bfa16cc18f06d..dadc8c8d331e005c9ad6899324a518633d662e63 100644 (file)
    <kenneth@bbs.sas.ntu.ac.sg>.
    0.42    22-Apr-96      Fix alloc_device() bug <jari@markkus2.fimr.fi>
    0.43    16-Aug-96      Update alloc_device() to conform to de4x5.c
+   0.44    08-Nov-01      use library crc32 functions <Matt_Domsch@dell.com>
 
    =========================================================================
  */
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/crc32.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -207,9 +209,6 @@ static int ewrk3_debug = 1;
 #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 @@ static void SetMulticastFilter(struct net_device *dev)
        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 @@ static void SetMulticastFilter(struct net_device *dev)
                        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 */
index e63a3c54291ae62834b145033e2b6182c7fc94b0..e35d85f477be5f1a2fa9c2b40638ba0c0e13939f 100644 (file)
@@ -72,6 +72,7 @@ static int full_duplex[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
 #include <linux/skbuff.h>
 #include <linux/init.h>
 #include <linux/mii.h>
+#include <linux/crc32.h>
 #include <asm/processor.h>     /* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -426,7 +427,6 @@ static void init_ring(struct net_device *dev);
 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);
@@ -1711,26 +1711,6 @@ static struct net_device_stats *get_stats(struct net_device *dev)
        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)
 {
        struct netdev_private *np = dev->priv;
index 8d3e0b2d45412740f6f839809f64de9fcfb12d67..1406a5edb968bdf4de0b248d4b06cef819aeb366 100644 (file)
@@ -16,6 +16,8 @@
  *  - PHY updates
  * BenH <benh@kernel.crashing.org> - 08/08/2001
  * - Add more PHYs, fixes to sleep code
+ * Matt Domsch <Matt_Domsch@dell.com> - 11/12/2001
+ * - use library crc32 functions
  */
 
 #include <linux/module.h>
@@ -33,6 +35,7 @@
 #include <linux/timer.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/crc32.h>
 #include <asm/prom.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
@@ -997,14 +1000,13 @@ gmac_stop_dma(struct gmac *gm)
  * 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 @@ gmac_set_multicast(struct net_device *dev)
                        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;
index dc1667b240cef790aae53fb15d6ff5a3fd6e9d7c..1a3e62efe6568f5414988a90416a4d39b85c37b7 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/crc32.h>
 
 #ifdef CONFIG_SERIAL
 #include <linux/serial.h>
@@ -1611,27 +1612,16 @@ static void ioc3_timeout(struct net_device *dev)
  * 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;
-
-       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;
-               }
-       }
+       u32 crc;
+       int bits;
+
+       crc = ether_crc_le(ETH_ALEN, addr);
 
        crc &= 0x3f;    /* bit reverse lowest 6 bits for hash index */
        for (bits = 6; --bits >= 0; ) {
index 04ca3c75ad16af864193c77b985524723238504a..7704924740d254a77e0410e35c8deb59b6610f4f 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/init.h>
+#include <linux/crc32.h>
 #include <asm/prom.h>
 #include <asm/dbdma.h>
 #include <asm/io.h>
@@ -508,17 +509,12 @@ static struct net_device_stats *mace_stats(struct net_device *dev)
     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 @@ static void mace_set_multicast(struct net_device *dev)
            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;
index 099b1fc938e3fd1203e055bc9e6f3abb75dbc639..9f792a43f0d7932ebbd0078775eca13ccd06952c 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/delay.h>
 #include <linux/string.h>
 #include <linux/timer.h>
+#include <linux/crc32.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/irq.h>
@@ -539,17 +540,12 @@ static struct net_device_stats *mace68k_stats(struct net_device *dev)
        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 @@ static void mace68k_set_multicast(struct net_device *dev)
                                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;
index 18e2642afea86d7cd80871b430b52c4fee07daf2..851eba8a3e00e2d1f02f5ca3092d50318c28e9fe 100644 (file)
@@ -6284,4 +6284,4 @@ static unsigned char lanai4_data[20472] __initdata = {
 #define MYRI_NetReceiveBadCrcs       0xB8D4
 #define MYRI_NetReceiveBytes         0xB8DC
 
-#endif SYMBOL_DEFINES_COMPILED
+#endif /* SYMBOL_DEFINES_COMPILED */
index 4ea8280d6d009ef8404261849dcb7c0d4e28ca8e..09b2d0450cefef835bcda91e2635d294f3c2e71a 100644 (file)
@@ -800,9 +800,6 @@ static int myri_change_mtu(struct net_device *dev, int new_mtu)
 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
index 7d01a2c6e9861ad289c9df725a3651b36fd92400..a94d694536b62a536b8ba9710a2fdf9ca4e16100 100644 (file)
        version 1.0.13:
                * ETHTOOL_[GS]EEPROM support (Tim Hockin)
 
+       version 1.0.13:
+               * crc cleanup (Matt Domsch <Matt_Domsch@dell.com>)
+
        TODO:
        * big endian support with CFG:BEM instead of cpu_to_le32
        * support for an external PHY
 
 #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 @@ static struct net_device_stats *get_stats(struct net_device *dev)
        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 @@ static unsigned ether_crc_le(int length, unsigned char *data)
 
     return (crc);
 }
-#endif
+
 
 void set_bit_le(int offset, unsigned char * data)
 {
@@ -1788,7 +1770,7 @@ static void __set_rx_mode(struct net_device *dev)
                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 
index e94d6c3cb3a2ceae03445e8861b3bf0e9043f88d..6743227a3478085d2a0f221bbd39239737b26c8e 100644 (file)
@@ -96,6 +96,7 @@ IVc. Errata
 #include <linux/delay.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
+#include <linux/crc32.h>
 #include <asm/io.h>
 
 #define NETDRV_VERSION         "1.0.0"
@@ -509,7 +510,6 @@ static void netdrv_interrupt (int irq, void *dev_instance,
 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);
 
@@ -1853,27 +1853,6 @@ static struct net_device_stats *netdrv_get_stats (struct net_device *dev)
 /* 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)
 {
        struct netdrv_private *tp = dev->priv;
index 3816934946ceae21fb85e4c92487dcffabcec556..6c47c37a0a0b22b50b8f311163abad19292f5cd1 100644 (file)
@@ -47,6 +47,7 @@
 #include <linux/skbuff.h>
 #include <linux/if_arp.h>
 #include <linux/ioport.h>
+#include <linux/crc32.h>
 
 #include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
@@ -1181,27 +1182,6 @@ static struct net_device_stats *fjn_get_stats(struct net_device *dev)
   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)
 {
     ioaddr_t ioaddr = dev->base_addr;
index f1c322bb2dbd4676a5ff9fa39af2b64bd529037e..44c218c3fff7305763e9677df89e9e915394b8fd 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/crc32.h>
 #include <asm/io.h>
 #include <asm/system.h>
 
@@ -1740,31 +1741,6 @@ static struct net_device_stats *smc91c92_get_stats(struct net_device *dev)
     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;
-}
 
 /*======================================================================
   
index e7fe6ae79e548cda1d7f2036dcbde24b8609df41..578af8d57f9c42921b08c6b285621131e75bd1a0 100644 (file)
@@ -101,6 +101,7 @@ static int csr0 = 0x00A00000 | 0x4800;
 #include <linux/init.h>
 #include <linux/mii.h>
 #include <linux/ethtool.h>
+#include <linux/crc32.h>
 
 #include <asm/io.h>
 #include <asm/processor.h>     /* Processor type for cache alignment. */
@@ -1518,43 +1519,6 @@ static int xircom_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        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
    new frame, not around filling tp->setup_frame.  This is non-deterministic
index 4ad12acf7d4a006458837bb133b4d27ac4f08af6..25b86ec8953870d90a40c5ef45584fdbd3e6729f 100644 (file)
@@ -36,6 +36,7 @@ static const char *version = "pcnet32.c:v1.25kf 26.9.1999 tsbogend@alpha.franken
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/crc32.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -215,8 +216,6 @@ static int full_duplex[MAX_UNITS];
 
 #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 @@ static void pcnet32_load_multicast (struct net_device *dev)
     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 @@ static void pcnet32_load_multicast (struct net_device *dev)
        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);
     }
index 9e1e2e30a26cebeb63302c73d70908c664590f80..3ff3c5fbec5619719ce8be4692b1b9d24c46975a 100644 (file)
@@ -737,6 +737,11 @@ static int __init shaper_init(void)
 
 static void __exit shaper_exit (void)
 {
+       int i;
+
+       for (i = 0; i < shapers; i++)
+               unregister_netdev(&devs[i]);
+
        kfree(devs);
        devs = NULL;
 }
index e6140c6cf27ccae3b5148f84caf65e37a4909e62..6724c7406fe1c957b9d91e26f2e8590913ea7db0 100644 (file)
@@ -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 <Matt_Domsch@dell.com> 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
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <linux/delay.h>
+#include <linux/crc32.h>
 
 #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 int sis900_set_config(struct net_device *dev, struct ifmap *map)
 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))
index 7a7c953b7b1625fc88ee3e378cc51cbd0283f213..4f8e30868e9f4f1ce032703db89d71c864e68c76 100644 (file)
@@ -116,6 +116,7 @@ typedef struct s_AC SK_AC;
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
+#include <linux/crc32.h>
 #include <asm/byteorder.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
index b7381fe679e277d8b59218079ce4ebe43e3b3034..ca223be377d6b23054c8b728070c0af15ee3feca 100644 (file)
@@ -199,7 +199,6 @@ extern "C" {
 /* 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 @@ int                Flags)          /* permanent/non-perm, sw-only */
 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 */
index c40f7dc8b041015f0351f13e58d87c9d4d797c9e..07337b7b912f6c28f1102f897cf0272e80229e8a 100644 (file)
@@ -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 @@ static const char version[] =
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/init.h>
+#include <linux/crc32.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <linux/errno.h>
@@ -223,10 +225,6 @@ static struct net_device_stats * smc_query_statistics( struct net_device *dev);
 */
 static void smc_set_multicast_list(struct net_device *dev);
 
-/*
- . CRC compute
- */
-static int crc32( char * s, int length );
 
 /*---------------------------------------------------------------
  .
@@ -436,7 +434,7 @@ static void smc_setmulticast( int ioaddr, int count, struct dev_mc_list * addrs
                        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]] |=
@@ -451,33 +449,6 @@ static void smc_setmulticast( int ioaddr, int count, struct dev_mc_list * addrs
        }
 }
 
-/*
-  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 * )
  . Purpose:
index 0fec2bcce2c3ec11ec8499eb34ca6eb526ac09a4..3d17fd6c2ff619b6b1b49a276aae8cdcb94dabf1 100644 (file)
@@ -109,6 +109,7 @@ TODO:
 #include <linux/etherdevice.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/crc32.h>
 #include <asm/processor.h>             /* Processor type for cache alignment. */
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -1612,32 +1613,9 @@ static struct net_device_stats *get_stats(struct net_device *dev)
 }
 
 
-/* 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)
 {
index 0170283fb85406f31e5a39a1c8394f581465d3eb..1555eac7f1df57b2b1759fa545b8c8063accbb06 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/crc32.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -979,9 +980,6 @@ static struct net_device_stats *bigmac_get_stats(struct net_device *dev)
        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 @@ static void bigmac_set_multicast(struct net_device *dev)
        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 @@ static void bigmac_set_multicast(struct net_device *dev)
                        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);
                }
index ab376ffedd7076c7a9ee62971cdd32e3ab05370e..c55a85e826117fa212e336459475ce55a7baaa19 100644 (file)
@@ -98,6 +98,7 @@ static char *media[MAX_UNITS];
 #include <linux/init.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
+#include <linux/crc32.h>
 #include <asm/uaccess.h>
 #include <asm/processor.h>             /* Processor type for cache alignment. */
 #include <asm/bitops.h>
@@ -1262,32 +1263,6 @@ static struct net_device_stats *get_stats(struct net_device *dev)
        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)
 {
        long ioaddr = dev->base_addr;
index 88ca3775ef9ece7f411efc2db4c3048da0039f0a..bf06abcb22367f1047790273be13195aea5949ba 100644 (file)
@@ -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 <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
+#include <linux/crc32.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
 
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
+#include <asm/uaccess.h>
+#include <asm/irq.h>
 
 #ifdef __sparc__
 #include <asm/idprom.h>
 
 #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 @@ static struct pci_device_id gem_pci_tbl[] __devinitdata = {
         * 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 @@ static int gem_pci_interrupt(struct net_device *dev, struct gem *gp, u32 gem_sta
        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 @@ static int gem_abnormal_irq(struct net_device *dev, struct gem *gp, u32 gem_stat
        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 @@ static void gem_tx_timeout(struct net_device *dev)
        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 @@ static void gem_tx_timeout(struct net_device *dev)
 
        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 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev)
                                        ~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 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        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 @@ static int gem_change_mtu(struct net_device *dev, int new_mtu)
                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 @@ static void gem_stop(struct gem *gp, unsigned long regs)
        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 @@ static void gem_start_dma(struct gem *gp)
        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 @@ static int phy_BCM5400_link_table[8][3] = {
        { 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 @@ static void gem_set_link_modes(struct gem *gp)
 
        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 void gem_set_link_modes(struct gem *gp)
 
 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 @@ static void gem_link_timer(unsigned long data)
                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 void gem_init_rings(struct gem *gp, int from_irq)
        }
 }
 
-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, MII_BCM5400_AUXCONTROL);
+       data |= MII_BCM5400_AUXCONTROL_PWR10BASET;
+       phy_write(gp, MII_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_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 @@ gem_init_bcm5401_phy(struct gem *gp)
        }
        
        /* 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 @@ gem_init_bcm5411_phy(struct gem *gp)
        /* 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));
+       phy_write(gp, MII_BMCR,
+                 (BMCR_ANENABLE | BMCR_FULLDPLX |
+                  BMCR_ANRESTART | BMCR_SPD2));
 
-       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);
 }
 
 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 @@ static void gem_init_phy(struct gem *gp)
                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 @@ static void gem_init_phy(struct gem *gp)
                /* 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 @@ static void gem_init_phy(struct gem *gp)
                else
                        val |= PCS_SCTRL_LOOP;
                writel(val, gp->regs + PCS_SCTRL);
+               gp->gigabit_capable = 1;
        }
 }
 
@@ -1392,7 +1623,7 @@ static void gem_init_dma(struct gem *gp)
 
        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 @@ static void gem_init_dma(struct gem *gp)
        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 @@ static void gem_init_mac(struct gem *gp)
                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 @@ static void gem_init_mac(struct gem *gp)
                        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 @@ static void gem_init_mac(struct gem *gp)
        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 @@ gem_init_pause_thresholds(struct gem* gp)
        }
 
        {
-               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 @@ static int gem_check_invariants(struct gem *gp)
        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 @@ static int gem_check_invariants(struct gem *gp)
 
                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 @@ static int gem_check_invariants(struct gem *gp)
                }
        }
 
-       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 @@ static void gem_init_hw(struct gem *gp)
         * 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 @@ static void gem_init_hw(struct gem *gp)
  * 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 @@ gem_apple_powerup(struct gem* gp)
        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 @@ static int gem_open(struct net_device *dev)
        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 @@ static int gem_open(struct net_device *dev)
        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 @@ static int gem_close(struct net_device *dev)
 {
        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 @@ static void gem_set_multicast(struct net_device *dev)
                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 @@ static void gem_set_multicast(struct net_device *dev)
                        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 @@ static void gem_set_multicast(struct net_device *dev)
                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(&regs, useraddr, sizeof(regs)))
+                       return -EFAULT;
+               
+               if (regs.len > SUNGEM_NREGS) {
+                       regs.len = SUNGEM_NREGS;
+               }
+               regs.version = 0;
+               if (copy_to_user(useraddr, &regs, 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 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
        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 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
                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 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
                       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 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
        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 @@ static void __devexit gem_remove_one(struct pci_dev *pdev)
 
                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 @@ static void __devexit gem_remove_one(struct pci_dev *pdev)
                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 @@ static struct pci_driver gem_driver = {
        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)
index a4a63f21d4364023406cf57ac8b14ee455451d9e..ec136a81885f55a10bf81755f0162b7b90fff749 100644 (file)
@@ -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)
 #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 @@ struct gem_rxd {
 
 #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 gem_phy_model {
 };
 
 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 @@ struct gem {
         * (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,15 +981,23 @@ struct gem {
        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;
        struct net_device *dev;
index 2affbd1e28800899f5190113e065ea7cd7b5b839..25778dc8676af100cdd15e0b4cfd54475a51eb68 100644 (file)
@@ -33,6 +33,7 @@ static char version[] =
 #include <linux/init.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
+#include <linux/crc32.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -1469,9 +1470,6 @@ force_link:
        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 @@ static int happy_meal_init(struct happy_meal *hp, int from_irq)
                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 @@ static int happy_meal_init(struct happy_meal *hp, int from_irq)
                        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 @@ static void happy_meal_set_multicast(struct net_device *dev)
        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 @@ static void happy_meal_set_multicast(struct net_device *dev)
                        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);
                }
index 2f9cc0dac31b6578877861d1d309d9e718e083f9..c42003b125e432496f264db414c3b56b30687331 100644 (file)
  *               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 @@ static char lancestr[] = "LANCE";
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/crc32.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -115,9 +119,6 @@ static char lancestr[] = "LANCE";
 #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 @@ static void lance_load_multicast(struct net_device *dev)
        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 @@ static void lance_load_multicast(struct net_device *dev)
                /* 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]);
index 30f06d1efc5c2981324f8aced2846602cf27ea56..7ddedceacfc2d09f7a4b7320031a34dcc3ce2dc4 100644 (file)
@@ -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 @@ static char version[] =
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/crc32.h>
 
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -494,6 +495,7 @@ static void qec_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                                spin_unlock(&qep->lock);
                        }
        next:
+                       ;
                }
                qec_status >>= 4;
                channel++;
@@ -621,9 +623,6 @@ static struct net_device_stats *qe_get_stats(struct net_device *dev)
        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 @@ static void qe_set_multicast(struct net_device *dev)
        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 @@ static void qe_set_multicast(struct net_device *dev)
 
                        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);
                }
index 917f1a9be8cf8aa37c0657858221d75512d48120..b396f5ba85f362a91a365f02827ab1dc0d354e55 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/delay.h>
 #include <linux/mii.h>
 #include <linux/ethtool.h>
+#include <linux/crc32.h>
 #include <asm/unaligned.h>
 #include <asm/uaccess.h>
 
@@ -968,41 +969,6 @@ static int private_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
    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)
 
index 2e753ad174a46e1b65572d0a129ce2c7d7133f5b..0aed62e907c4bd00b00874272c9970bdb3940a3a 100644 (file)
@@ -151,6 +151,7 @@ static const int multicast_filter_limit = 32;
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/mii.h>
+#include <linux/crc32.h>
 #include <asm/processor.h>             /* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -1519,26 +1520,6 @@ static inline void clear_tally_counters(const long ioaddr)
        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)
 {
        struct netdev_private *np = dev->priv;
index f81fc206f985725766d4ec0f153673d94f4259a9..92e18806848ec26c4c2edd49f10450cd28f12a15 100644 (file)
@@ -136,6 +136,7 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 #include <linux/ethtool.h>
 #include <linux/mii.h>
 #include <linux/rtnetlink.h>
+#include <linux/crc32.h>
 #include <asm/uaccess.h>
 #include <asm/processor.h>             /* Processor type for cache alignment. */
 #include <asm/bitops.h>
@@ -389,7 +390,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 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 @@ static struct net_device_stats *get_stats(struct net_device *dev)
        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)
 {
index e169ad56faf8890ff0b58c3c9d1c1f07436f547a..e56ab051dda87233af888322eb4930830484465b 100644 (file)
@@ -125,6 +125,7 @@ static int gx_fix;
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/ethtool.h>
+#include <linux/crc32.h>
 #include <asm/uaccess.h>
 #include <asm/processor.h>             /* Processor type for cache alignment. */
 #include <asm/unaligned.h>
@@ -1339,29 +1340,6 @@ static struct net_device_stats *yellowfin_get_stats(struct net_device *dev)
 
 /* 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)
 {
        struct yellowfin_private *yp = dev->priv;
index f1deb2a35e805b313e11621b8e268df73186b3b5..bb14996daf66170781094f3dda6ea9791b2fb0d1 100644 (file)
@@ -115,7 +115,7 @@ do { \
 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 )
index d6715d169e9d53a97b69545fae4d020c6c3df0fa..064a5cc008098f84eee1949a7dec66dce54afef7 100644 (file)
@@ -771,7 +771,7 @@ void xpram_request(request_queue_t * queue)
 
                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 */
index fa714c2c46effc272014b349d2320c43b4761b3d..8506921d5a542e28a98b025478f8816f665f03a8 100644 (file)
@@ -41,7 +41,7 @@ do { \
 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 )
index cbf93b31b2de45bbd6129b76fec0a9ee40cf38c1..1ee7f179d2e0d38a765336a86f1b364aa4a9af7b 100644 (file)
@@ -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 @@ static unsigned int sparcaudio_poll(struct file *file, poll_table * wait)
 {
         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 @@ static ssize_t sparcaudio_read(struct file * file, char *buf,
                                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 @@ static ssize_t sparcaudio_write(struct file * file, const char *buf,
                                 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 ssize_t sparcaudio_write(struct file * file, const char *buf,
 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 @@ static int sparcaudio_ioctl(struct inode * inode, struct file * file,
                            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 struct file_operations sparcaudioctl_fops = {
 
 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_open(struct inode * inode, struct file * file)
 
 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();
index 38b53ee9f16e4f1afbddb9cedd9684c6e964f715..86b08d5cb8272a9e100a415a5e2c8a2a57042886 100644 (file)
@@ -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 @@ static int aurora_open(struct tty_struct * tty, struct file * filp)
        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 @@ static int aurora_open(struct tty_struct * tty, struct file * filp)
        }
        
        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");
index f5ed491fb464beff85ee1b0c9080226a94e647a6..fdc9936319f08edd3e7d15dad47155400c4ca4d9 100644 (file)
@@ -297,7 +297,7 @@ static inline int wd_opt_timeout(void)
 
 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];
index ea2430ec0ad24c7079c564bfc8d9b0ca777d65af..cebf4df348d1dd70955243bde6fb4acfbc2c6fb2 100644 (file)
@@ -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 inline int d7s_obpflipped(void)
 
 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_open(struct inode *inode, struct file *f)
 
 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 @@ static int d7s_ioctl(struct inode *inode, struct file *f,
        __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) {
index fec4c3ee224cb9cf1e09c6a89a1095d376293eb2..99fe2b473c4a8315d5a3d93ad87500b0696c4e33 100644 (file)
@@ -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 @@ static int sab82532_open(struct tty_struct *tty, struct file * filp)
        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 void __init sab82532_kgdb_hook(int line)
 
 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 @@ sab82532_console_write(struct console *con, const char *s, unsigned n)
 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
index ac0a1c40016a81c8425fd298905ffb38e5ec2570..acdabc85fc9cf4beeae6bfee6c245b6461fffc03 100644 (file)
@@ -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 @@ su_open(struct tty_struct *tty, struct file * filp)
        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 @@ done:
  */
 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 @@ serial_console_write(struct console *co, const char *s,
 static kdev_t
 serial_console_device(struct console *c)
 {
-       return MKDEV(TTY_MAJOR, 64 + c->index);
+       return mk_kdev(TTY_MAJOR, 64 + c->index);
 }
 
 /*
index 5ac8a930486ccf352f8cc5363cdf03363374fdfa..6ee3b0051b89d983c5816a317c37a04dfe97d7a3 100644 (file)
@@ -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)
index e9562c2ecc8cbc943302a9d05fa9bd5ef302e9d9..a31e9630ea01b75e1440b9b3b2f261174fc37d4e 100644 (file)
@@ -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 unsigned char *tmp_buf = 0;
 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 @@ static inline int serial_paranoia_check(struct sun_serial *info,
                "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 @@ extern void breakpoint(void);  /* For the KGDB frame character */
 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 @@ static void receive_chars(struct sun_serial *info, struct pt_regs *regs)
                /* 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 @@ static void receive_chars(struct sun_serial *info, struct pt_regs *regs)
                                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 @@ static void receive_chars(struct sun_serial *info, struct pt_regs *regs)
                 * 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;
-
-               /* ... and see if it is clean. */
-               stat = read_zsreg(info->zs_channel, R1);
-       } while (!(stat & (PAR_ERR | Rx_OVR | CRC_ERR)));
+               {
+                       unsigned char stat;
+
+                       /* 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 @@ static void transmit_chars(struct sun_serial *info)
                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 @@ static void transmit_chars(struct sun_serial *info)
        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 @@ static void status_handle(struct sun_serial *info)
        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 @@ static void status_handle(struct sun_serial *info)
         * '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 @@ static void status_handle(struct sun_serial *info)
        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;
+               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_Tx_EMPTY) {
-                       transmit_chars(info->zs_next);
-                       return;
-               }
-               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 @@ int zs_open(struct tty_struct *tty, struct file * filp)
        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 @@ int zs_open(struct tty_struct *tty, struct file * filp)
 
 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 @@ int __init zs_init(void)
        /* 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 @@ zs_console_write(struct console *con, const char *s, unsigned count)
 
 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)
index 96bba6454933cefbfd9052499f4c4e3bfec2ebd0..c64a0901bc33437e83a19241b2284934a7f41ba4 100644 (file)
@@ -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 @@ static void __init __apply_ranges_to_regs(struct linux_prom_ranges *ranges,
                                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;
                }
        }
index 85a91217a57de5147c57d1932da796b8a53483a3..9835bfccf1df95398d1521d41bb2de590b2c6c36 100644 (file)
@@ -8392,8 +8392,8 @@ asc_prt_driver_conf(struct Scsi_Host *shp, char *cp, int cplen)
     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 @@ asc_prt_scsi_host(struct Scsi_Host *s)
         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);
index 6242554a93fa159a8dfd31dcc90c741608df4898..e656d4d081a2e96e04ea6f7bece84c7d4cca3487 100644 (file)
 
 #include <linux/mm.h>          /* For fetching system memory size */
 #include <linux/blk.h>
+#include <scsi/scsicam.h>
 
 /*
  * To generate the correct addresses for the controller to issue
index a6036ddd92bb6e6363a71e735b295b0cbdd65b2a..f0082058d61d98350ab7e1ac0928cc109d54c317 100644 (file)
@@ -713,20 +713,20 @@ static __inline void ahc_done_unlock(struct ahc_softc *, unsigned long *flags);
 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 @@ ahc_done_lock(struct ahc_softc *ahc, unsigned long *flags)
        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 @@ ahc_done_unlock(struct ahc_softc *ahc, unsigned long *flags)
 {
        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) */
index 23113ae7c4a7a4397831381ce7e5e1b3e6404704..ebbd33c54f0d861b77101f72d8f9164d40429b09 100644 (file)
@@ -5,7 +5,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/module.h>
 
 #include <linux/config.h>
index aa0fd64cb32e84bfe12c872d04b483e8afb2339b..e276376771aee32d98286389ee4f3aab63a62658 100644 (file)
@@ -24,7 +24,6 @@
  *  hosts currently present in the system.
  */
 
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/blk.h>
 #include <linux/kernel.h>
@@ -55,13 +54,6 @@ static const char RCSid[] = "$Header: /vger/u4/cvs/linux/drivers/scsi/hosts.c,v
  *  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 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j)
            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 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j)
        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)
index 3246ba64f15d38554ff58e01b081e21a1d092baf..8604eb35140a6225986efc1d5cd988c39d958dc1 100644 (file)
@@ -312,7 +312,8 @@ struct Scsi_Host
     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 @@ struct Scsi_Host
     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 @@ struct Scsi_Host
     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 @@ typedef struct SHN
     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,10 +466,14 @@ extern int next_scsi_host;
 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)
 {
index 3bb3bef50f06b572b00927afa75870e2f9e79cd5..1c47f9cc04164d720f7aabc419522234d668f9f1 100644 (file)
@@ -292,9 +292,9 @@ static void idescsi_end_request (byte uptodate, ide_hwgroup_t *hwgroup)
                }
        }
        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 @@ int idescsi_queue (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
        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);
index b3257fc4652b43f13dbc968250cd53e18504a805..554dc6b446c4cf33d5ebe38501d8a9cf4ef0bf75 100644 (file)
@@ -75,8 +75,6 @@
 #include <linux/kmod.h>
 #endif
 
-#undef USE_STATIC_SCSI_MEMORY
-
 struct proc_dir_entry *proc_scsi;
 
 #ifdef CONFIG_PROC_FS
@@ -195,16 +193,23 @@ void  scsi_initialize_queue(Scsi_Device * SDpnt, struct Scsi_Host * SHpnt)
 {
        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 @@ int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt)
 
        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 @@ int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt)
                 * 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 @@ int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt)
                        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 @@ int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt)
                }
                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 @@ void scsi_do_req(Scsi_Request * SRpnt, const void *cmnd,
        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 @@ void scsi_init_cmd_from_req(Scsi_Cmnd * SCpnt, Scsi_Request * SRpnt)
 {
        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 @@ void scsi_do_cmd(Scsi_Cmnd * SCpnt, const void *cmnd,
 {
        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 @@ void scsi_finish_command(Scsi_Cmnd * SCpnt)
        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 @@ void scsi_finish_command(Scsi_Cmnd * SCpnt)
          * 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 @@ void __init scsi_host_no_insert(char *str, int n)
            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 @@ int scsi_register_host(Scsi_Host_Template * tpnt)
                        }
                }
        }
-#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 @@ int scsi_unregister_host(Scsi_Host_Template * tpnt)
                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)
@@ -2406,35 +2397,6 @@ static void scsi_dump_status(int level)
                        }
                }
        }
-
-       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");
-                               }
-                       }
-               }
-       }
 #endif /* CONFIG_SCSI_LOGGING */ /* } */
 }
 #endif                         /* CONFIG_PROC_FS */
index b6894649e12f668b13ed64af68de7c26b11d9304..57596d9eb1cca1d7026cc508d936586db765e0aa 100644 (file)
@@ -8,7 +8,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/module.h>
 
 #include <linux/sched.h>
@@ -583,7 +582,7 @@ STATIC void scsi_send_eh_cmnd(Scsi_Cmnd * SCpnt, int timeout)
        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 @@ retry:
                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 @@ retry:
                         * 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 @@ retry:
                 * 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 @@ STATIC int scsi_try_to_abort_command(Scsi_Cmnd * SCpnt, int timeout)
 
        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 @@ STATIC int scsi_try_bus_device_reset(Scsi_Cmnd * SCpnt, int timeout)
        }
        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 @@ STATIC int scsi_try_bus_reset(Scsi_Cmnd * SCpnt)
                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 @@ STATIC int scsi_try_host_reset(Scsi_Cmnd * SCpnt)
        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 @@ STATIC void scsi_restart_operations(struct Scsi_Host *host)
        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 @@ STATIC void scsi_restart_operations(struct Scsi_Host *host)
         * 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 @@ STATIC void scsi_restart_operations(struct Scsi_Host *host)
 
                q->request_fn(q);
        }
-       spin_unlock_irqrestore(&host->host_lock, flags);
+       spin_unlock_irqrestore(host->host_lock, flags);
 }
 
 /*
@@ -1303,7 +1302,7 @@ STATIC int scsi_unjam_host(struct Scsi_Host *host)
        Scsi_Cmnd *SCdone;
        int timed_out;
 
-       ASSERT_LOCK(&host->host_lock, 0);
+       ASSERT_LOCK(host->host_lock, 0);
 
        SCdone = NULL;
 
@@ -1844,11 +1843,7 @@ void scsi_error_handler(void *data)
          * If the HA was compiled into the kernel, then we don't listen
          * to any signals.
          */
-        if( host->loaded_as_module ) {
        siginitsetinv(&current->blocked, SHUTDOWN_SIGS);
-       } else {
-       siginitsetinv(&current->blocked, 0);
-        }
 
        lock_kernel();
 
@@ -1894,10 +1889,8 @@ void scsi_error_handler(void *data)
                 * 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"));
 
index f64d20090923203d35a12d763405e89670cf642c..b99553c5e51be82118c1bc915d5b59330d8df2a6 100644 (file)
@@ -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 <linux/module.h>
 
 #include <asm/io.h>
index 4e8745f235602e02d3c2f8795ba8d3a8382a3a27..b23f616592db8cb863deef8242b42216023b042c 100644 (file)
@@ -17,7 +17,6 @@
  * go through and retrofit queueing functions into all 30 some-odd drivers.
  */
 
-#define __NO_VERSION__
 #include <linux/module.h>
 
 #include <linux/sched.h>
@@ -365,7 +364,7 @@ static Scsi_Cmnd *__scsi_end_request(Scsi_Cmnd * SCpnt,
         * 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 @@ static void scsi_release_buffers(Scsi_Cmnd * SCpnt)
 {
        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. 
index 3368906c2884ebaea958612ea49c02bd77264054..807ecbc58dca52d681f9f1a53ba6f303b159b518 100644 (file)
@@ -15,7 +15,6 @@
  * be handled all at once by a host adapter.
  */
 
-#define __NO_VERSION__
 #include <linux/config.h>
 #include <linux/module.h>
 
index 01d6679250a954ce98ee59bd837294587eba9726..2f7e4adcc3606a7b586eb0996476cac4624439c4 100644 (file)
@@ -17,7 +17,6 @@
  */
 
 #include <linux/config.h>      /* for CONFIG_PROC_FS */
-#define __NO_VERSION__
 #include <linux/module.h>
 
 #include <linux/string.h>
index 1d9a90bbdd56c5c33d323f5542d727df6d1feb93..40d2ad5a28a4200d68d5dd58fc45db2691448dfd 100644 (file)
@@ -10,7 +10,6 @@
  *  we attempt to remove commands from the queue and retry them.
  */
 
-#define __NO_VERSION__
 #include <linux/module.h>
 
 #include <linux/sched.h>
@@ -137,10 +136,10 @@ int scsi_mlqueue_insert(Scsi_Cmnd * cmd, int reason)
         * 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.
index aede1a6a94202f4409940a1b59e1fc8b4374ff89..8f4d70c1e6a26cb53b58c3fa403fca37925a6539 100644 (file)
@@ -8,7 +8,6 @@
  *  clearer.
  */
 
-#define __NO_VERSION__
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
index 8f511d1a5105f11394883d9eafdaa4873a2f664b..e363fac3d987328ddd5eede28e5af1d31619fee4 100644 (file)
@@ -2,7 +2,6 @@
  * We should not even be trying to compile this if we are not doing
  * a module.
  */
-#define __NO_VERSION__
 #include <linux/config.h>
 #include <linux/module.h>
 
index e8f8c90bf7937fc3b8ca820280ad56ebface741d..3582d44e09d47cb672388dec0eb83d883fc0d2d5 100644 (file)
@@ -10,7 +10,6 @@
  * For more information, please consult the SCSI-CAM draft.
  */
 
-#define __NO_VERSION__
 #include <linux/module.h>
 
 #include <linux/fs.h>
index bc030dcb4fcc7cbedcd46a4b92f580ac906743be..f22d1414d56341a110f20733cb7799fe300a049d 100644 (file)
@@ -643,9 +643,9 @@ spinlock_t sym53c8xx_lock = SPIN_LOCK_UNLOCKED;
 #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
 
index d8c43a9d5abb74c2a56d206506354d2850724ac5..10e68e096edc851ca2a994a1e3ce91620b97b840 100644 (file)
@@ -138,11 +138,11 @@ spinlock_t sym53c8xx_lock = SPIN_LOCK_UNLOCKED;
 #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 
index aabd8adc656c24e78e09debbc94f16c8ee05b61c..19169b4327799d047215dce2c30a3d7cc6a30361 100644 (file)
 #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_ioctl(struct inode *inode, struct file *file, unsigned int cm
 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 ali_write_proc(struct file *file, const char *buffer, unsigned long c
 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 @@ static int __init trident_probe(struct pci_dev *pci_dev, const struct pci_device
        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);
index 25cf21c102ee34871f54a159f8062a428f847bc0..d426b7dff787492dccf109a550fc68503e8ef7bb 100644 (file)
@@ -1,6 +1,8 @@
 /*
  *  Copyright 1999 Jaroslav Kysela <perex@suse.cz>
  *  Copyright 2000 Alan Cox <alan@redhat.com>
+ *  Copyright 2001 Kai Germaschewski <kai@tp1.ruhr-uni-bochum.de>
+ *  Copyright 2002 Pete Zaitcev <zaitcev@yahoo.com>
  *
  *  Yamaha YMF7xx driver.
  *
  *  - 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 <linux/config.h>
@@ -155,7 +165,7 @@ static int ymfpci_codec_ready(ymfpci_t *codec, int secondary, int sched)
                        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 void ymfpci_codec_write(struct ac97_codec *dev, u8 reg, u16 val)
 
 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 @@ static void ymf_pcm_update_shift(struct ymf_pcm_format *f)
 #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 @@ static int alloc_dmabuf(struct ymf_dmabuf *dmabuf)
 
        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 @@ static int alloc_dmabuf(struct ymf_dmabuf *dmabuf)
        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 @@ static void dealloc_dmabuf(struct ymf_dmabuf *dmabuf)
                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 @@ static int prog_dmabuf(struct ymf_state *state, int rec)
 
        /* 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 @@ static int prog_dmabuf(struct ymf_state *state, int rec)
        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 @@ static void ymf_pcm_interrupt(ymfpci_t *codec, ymfpci_voice_t *voice)
        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 @@ static void ymf_pcm_interrupt(ymfpci_t *codec, ymfpci_voice_t *voice)
                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 @@ static void ymf_pcm_interrupt(ymfpci_t *codec, ymfpci_voice_t *voice)
                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 @@ static void ymf_pcm_interrupt(ymfpci_t *codec, ymfpci_voice_t *voice)
                                /*
                                 * 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 @@ static void ymf_pcm_interrupt(ymfpci_t *codec, ymfpci_voice_t *voice)
                                /*
                                 * 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 @@ static void ymf_cap_interrupt(ymfpci_t *unit, struct ymf_capture *cap)
                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 @@ static int ymf_playback_trigger(ymfpci_t *codec, struct ymf_pcm *ypcm, int cmd)
                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 @@ static void ymf_pcm_init_voice(ymfpci_voice_t *voice, int stereo,
        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 @@ static void ymf_pcm_init_voice(ymfpci_voice_t *voice, int stereo,
                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 @@ static void ymf_pcm_init_voice(ymfpci_voice_t *voice, int stereo,
                                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 @@ static int ymf_playback_prepare(struct ymf_state *state)
                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 @@ static int ymf_capture_prepare(struct ymf_state *state)
        }
        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 @@ static unsigned int ymf_poll(struct file *file, struct poll_table_struct *wait)
 {
        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 @@ static unsigned int ymf_poll(struct file *file, struct poll_table_struct *wait)
                        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 @@ static int ymf_mmap(struct file *file, struct vm_area_struct *vma)
                return -EAGAIN;
        dmabuf->mapped = 1;
 
+/* P3 */ printk(KERN_INFO "ymfpci: using memory mapped sound, untested!\n");
        return 0;
 }
 
@@ -1508,13 +1542,16 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
        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 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
                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 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
        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 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
        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 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
                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 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
        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 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
                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 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
        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 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
                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 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
                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 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
                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 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
                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 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
                 * 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 @@ static int ymf_open(struct inode *inode, struct file *file)
        }
 
 #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 @@ out_nodma:
         * 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 @@ out_nodma:
 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 @@ static int ymf_release(struct inode *inode, struct file *file)
         */
        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 @@ static int ymf_release(struct inode *inode, struct file *file)
        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_release(struct inode *inode, struct file *file)
  */
 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 /*const*/ struct file_operations ymf_mixer_fops = {
 
 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_suspend(struct pci_dev *pcidev, u32 unused)
 
 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 @@ static int ymf_resume(struct pci_dev *pcidev)
        }
 
        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 @@ static void ymfpci_aclink_reset(struct pci_dev * pci)
 {
        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 void ymfpci_download_image(ymfpci_t *codec)
 
 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->dma_area_va = ptr;
+       codec->dma_area_ba = pba;
+       codec->dma_area_size = size + 0xff;
 
-       codec->work_ptr = ptr;
-       ptr += 0x00ff;
-       (long)ptr &= ~0x00ff;
+       if ((off = ((uint) ptr) & 0xff) != 0) {
+               ptr += 0x100 - off;
+               pba += 0x100 - off;
+       }
 
        /*
         * Hardware requires only ptr[playback_ctrl_size] zeroed,
@@ -2271,34 +2345,49 @@ static int ymfpci_memalloc(ymfpci_t *codec)
         */
        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];
+               codec->voices[voice].bank =
+                   (ymfpci_playback_bank_t *) (ptr + off);
+               codec->voices[voice].bank_ba = pba + off;
+               off += 2 * bank_size_playback;          /* 2 banks */
        }
-       ptr += (codec->bank_size_playback + 0x00ff) & ~0x00ff;
-       codec->bank_base_capture = ptr;
+       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;
+                       codec->bank_capture[voice][bank] =
+                           (ymfpci_capture_bank_t *) (ptr + off);
+                       off += bank_size_capture;
                }
-       ptr += (codec->bank_size_capture + 0x00ff) & ~0x00ff;
-       codec->bank_base_effect = ptr;
+       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;
+                       codec->bank_effect[voice][bank] =
+                           (ymfpci_effect_bank_t *) (ptr + off);
+                       off += bank_size_effect;
                }
-       ptr += (codec->bank_size_effect + 0x00ff) & ~0x00ff;
-       codec->work_base = ptr;
+       off = (off + 0xff) & ~0xff;
+       ptr += off;
+       pba += off;
+
+       codec->work_base = pba;
 
        return 0;
 }
@@ -2310,16 +2399,17 @@ static void ymfpci_memfree(ymfpci_t *codec)
        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 @@ static int ymf_ac97_init(ymfpci_t *unit, int num_ac97)
        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 assigned;
 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 @@ static int __devinit ymf_probe_one(struct pci_dev *pcidev, const struct pci_devi
                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 @@ static int __devinit ymf_probe_one(struct pci_dev *pcidev, const struct pci_devi
        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 @@ static int __devinit ymf_probe_one(struct pci_dev *pcidev, const struct pci_devi
 
        /* 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 @@ static int __devinit ymf_probe_one(struct pci_dev *pcidev, const struct pci_devi
        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 @@ static int __devinit ymf_probe_one(struct pci_dev *pcidev, const struct pci_devi
        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 @@ static void __devexit ymf_remove_one(struct pci_dev *pcidev)
        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);
index 1686f204dda80056bd39277d9ada3d238d3b3443..9ecf6b2ca87a815b90c7770ee62532a66cc5d34c 100644 (file)
@@ -227,6 +227,7 @@ struct ymf_voice {
        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_capture {
 struct ymf_unit {
        u8 rev;                         /* PCI revision */
        void *reg_area_virt;
-       void *work_ptr;
+       void *dma_area_va;
+       dma_addr_t dma_area_ba;
+       unsigned int dma_area_size;
 
-       unsigned int bank_size_playback;
-       unsigned int bank_size_capture;
-       unsigned int bank_size_effect;
+       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_unit {
 };
 
 struct ymf_dmabuf {
-
-       /* OSS buffer management stuff */
+       dma_addr_t dma_addr;
        void *rawbuf;
        unsigned buforder;
+
+       /* OSS buffer management stuff */
        unsigned numfrag;
        unsigned fragshift;
 
index 0380ee2dfdc13e9c97fb6b7edfddbf23407b3853..c8eb8d1e48c9d698abc003f38c036288854ceaf1 100644 (file)
@@ -46,7 +46,7 @@ static DECLARE_MUTEX(phone_lock);
 
 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 --git a/drivers/usb/Makefile.lib b/drivers/usb/Makefile.lib
new file mode 100644 (file)
index 0000000..891c918
--- /dev/null
@@ -0,0 +1 @@
+obj-$(CONFIG_USB_CATC)         += crc32.o
index 856fb1c8f555a888ea7c466f49dac1e63328af20..cc14861706dbe704f797100d08d713c25b2ed1c0 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
 #include <linux/ethtool.h>
+#include <linux/crc32.h>
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
 
@@ -531,13 +532,9 @@ static struct net_device_stats *catc_get_stats(struct net_device *netdev)
 
 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);
 }
 
index f9e97651fb9f6146e5339f20017ed8e95948b1fc..8d4799ae576def705a1cd8d13ea9283d2fcd87af 100644 (file)
@@ -624,7 +624,7 @@ clean_2:
 #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) {
index 83a33212f88af5ce91b33704d0e39fb05f5d144c..41b8f3fd2df07413579194b90e2bf90097c2f3af 100644 (file)
@@ -743,7 +743,7 @@ MODULE_LICENSE ("GPL");
 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));
 
index 905e506f3fa0ae3f5e5794b5436aa029c17ca577..5a971fee2d9f058b638f49b57afafe999090c18a 100644 (file)
@@ -381,7 +381,7 @@ static int intr_submit (
                        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 ();
index 37baf66f2135022e202511d3fdd66ba681eecc3e..1252d7334d0498f0699166e8c0dc26c741b845a4 100644 (file)
@@ -326,7 +326,7 @@ static void name(struct vc_data *conp, struct display *p, args) \
                     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, \
index 34ee6dd29a97d1e015afebfd8f709c5bd4a388be..63d3b3fa48ef3d0cf547f875f32ab2c59bc4141a 100644 (file)
@@ -1019,7 +1019,7 @@ sizechange:
        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 --git a/fs/Makefile.lib b/fs/Makefile.lib
new file mode 100644 (file)
index 0000000..0ca1cff
--- /dev/null
@@ -0,0 +1,2 @@
+obj-$(CONFIG_FS_JFFS2)         += crc32.o
+obj-$(CONFIG_EFI_PARTITION)    += crc32.o
index a09a4502ea3ddc4be10fe838036ce6cbb7ab4329..6a3602298fdbb943adbc75727f7507dc03c94fca 100644 (file)
@@ -401,6 +401,7 @@ err_ext:
 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;
index 672bd95c75678e9a8661c04265eb20fcebd38e00..4f34a8c0dffdd30bd2af8fa1a3aae80189e4e2c4 100644 (file)
@@ -128,6 +128,7 @@ static int blkdev_get_block(struct inode * inode, sector_t iblock, struct buffer
                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;
index b55ac6aba6742cef0babb543026570397d9197dc..8a9233a44356de7a3d9e2505931b0ca3ee9c4d4f 100644 (file)
@@ -83,7 +83,7 @@ static int nr_unused_buffer_heads;
 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 @@ static void remove_from_queues(struct buffer_head *bh)
        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 @@ struct buffer_head * get_hash_table(kdev_t dev, sector_t block, int size)
                        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 @@ void invalidate_inode_buffers(struct inode *inode)
  */
 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 @@ static void __put_unused_buffer_head(struct buffer_head * bh)
                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 @@ try_again:
                        goto no_grow;
 
                bh->b_dev = NODEV;
+               bh->b_bdev = NULL;
                bh->b_this_page = head;
                head = bh;
 
@@ -1366,6 +1367,7 @@ static void discard_buffer(struct buffer_head * bh)
        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 @@ static void unmap_underlying_metadata(struct buffer_head * bh)
 {
        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 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[], kdev_t dev, sector_t b[],
  * 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 @@ int brw_page(int rw, struct page *page, kdev_t dev, sector_t b[], int size)
        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 @@ failed:
        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 @@ static void hash_page_buffers(struct page *page, kdev_t dev, int block, int size
        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 @@ static void hash_page_buffers(struct page *page, kdev_t dev, int block, int size
  * 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 @@ static int grow_buffers(kdev_t dev, unsigned long block, int size)
        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);
 
index 8dc002027c49987ffd4b7dafc08ee8786d09dc8b..3918709b08176da950eb1be14df39a76f0c6ed89 100644 (file)
@@ -151,8 +151,8 @@ static struct super_block * coda_read_super(struct super_block *sb,
            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;
 
index 92ce22a393dfd0dc0f49f866f73577009fda39af..861a87741e40179bdc36d5e0280696df39efa93d 100644 (file)
@@ -81,7 +81,7 @@ static int coda_pioctl(struct inode * inode, struct file * filp,
        }
        
        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 ) {
index d4379a0ee9a86c19ab63e37e3a8fab00fda058b1..7246506fff3705375ff4eed0cea0db988f9dc6d5 100644 (file)
@@ -1262,7 +1262,7 @@ void __init vfs_caches_init(unsigned long mempages)
                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");
index 639ae7464c6ce960115a51baa05d8f67e05cf9fa..19c4066007e377e2b9f17444a46b1c2149d35d9c 100644 (file)
               Only return old entry in <devfs_mk_dir> if a directory.
               Defined macros for error and debug messages.
   v1.8
+    20020113   Richard Gooch <rgooch@atnf.csiro.au>
+              Fixed (rare, old) race in <devfs_lookup>.
+  v1.9
 */
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/bitops.h>
 #include <asm/atomic.h>
 
-#define DEVFS_VERSION            "1.8 (20011226)"
+#define DEVFS_VERSION            "1.9 (20020113)"
 
 #define DEVFS_NAME "devfs"
 
@@ -894,8 +897,8 @@ void devfs_put (devfs_handle_t de)
     {
        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 @@ devfs_handle_t devfs_register (devfs_handle_t dir, const char *name,
     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 @@ devfs_handle_t devfs_register (devfs_handle_t dir, const char *name,
     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 @@ devfs_handle_t devfs_register (devfs_handle_t dir, const char *name,
     {
        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 @@ EXPORT_SYMBOL(devfs_unregister_blkdev);
  *     @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 @@ static int try_modload (struct devfs_entry *parent, struct fs_info *fs_info,
     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 @@ static int check_disc_changed (struct devfs_entry *de)
 {
     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 @@ static struct inode *_devfs_get_vfs_inode (struct super_block *sb,
     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 @@ static int devfs_d_delete (struct dentry *dentry)
     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 int devfs_d_revalidate_wait (struct dentry *dentry, int flags)
 
 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 @@ static struct dentry *devfs_lookup (struct inode *dir, struct dentry *dentry)
                                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)
index dd696709f27de7f42b6663a097b2ba81d379359a..e93c3354c5b7f20152f3bf8d19c2bdda0368d1da 100644 (file)
@@ -101,7 +101,6 @@ static struct dentry *devpts_root_lookup(struct inode * dir, struct dentry * den
        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 @@ static struct dentry *devpts_root_lookup(struct inode * dir, struct dentry * den
        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;
 }
index 1a37b2286f80fa2665d50ead1ed231d883b9f2ea..c8d9f41439dd32db5eec27a8bd9bd931a6d55cc6 100644 (file)
@@ -374,7 +374,7 @@ static int driverfs_d_delete_file (struct dentry * dentry)
 
        entry = (struct driver_file_entry *)dentry->d_fsdata;
        if (entry)
-               kfree(dentry);
+               kfree(entry);
        return 0;
 }
 
index 540d9df2ba0675d9ef716faaacdc65ec78e71753..a376239068bb92978dbd62f50fd6f35384934ddd 100644 (file)
@@ -189,7 +189,7 @@ static void list_cache(void)
 
        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("-- ");
index e6daf9dc5f17489b5572cec387add764f43ccbdc..904a5b27721d0170c949581d2958d65ad7568abd 100644 (file)
@@ -407,7 +407,7 @@ static void fat_read_root(struct inode *inode)
        }
        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 @@ static void fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
        /* 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 =
index 5b7f3e1a75a9b6d0edf8bf85948e4c9d20168189..22b6d538ed0f579fbab15b9b0dd8cfc25b8ee20a 100644 (file)
@@ -1082,7 +1082,7 @@ void iput(struct inode *inode)
                                }
                                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);
index db9d6948bd361914dcbd07848a483b7f99ae0c45..b7ef2eb4926ecb2df4c1e311c55d373f4726b77f 100644 (file)
@@ -46,7 +46,7 @@ static struct list_head presto_caches[CACHES_SIZE];
 
 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 @@ struct presto_cache *presto_find_cache(kdev_t dev)
         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 @@ struct presto_cache *presto_get_cache(struct inode *inode)
         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 @@ int presto_ispresto(struct inode *inode)
         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 */
index 5da2e10ae3889fd5ffbe9eb41a9fecc27f829b17..1eba374ae559c550012153a2001ed2a49f6f0838 100644 (file)
@@ -71,8 +71,8 @@ int presto_i2m(struct inode *inode)
         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;
         }
index 0785b7d8a1652dd274c1165e63c747e57a70ff0f..0384ab5c3c295c094bb6cac501bb7ad04ce94fbf 100644 (file)
 #include <linux/proc_fs.h>
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
+#include <linux/tty.h>
 #include <linux/poll.h>
 #include <linux/init.h>
 #include <linux/list.h>
-#include <linux/termios.h>
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/poll.h>
 #include <asm/uaccess.h>
+#include <asm/ioctls.h>
 
 #include <linux/intermezzo_fs.h>
 #include <linux/intermezzo_upcall.h>
@@ -290,7 +291,7 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
                 }
 
                 len = readmount.io_len;
-                minor = MINOR(dev);
+                minor = minor(dev);
                 PRESTO_ALLOC(tmp, char *, len);
                 if (!tmp) {
                         EXIT;
@@ -627,7 +628,7 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
                         EXIT;
                         return error;
                 }
-                minor = MINOR(dev);
+                minor = minor(dev);
                 if (cmd == PRESTO_SETOPT)
                         error = dosetopt(minor, &kopt);
 
index 9a0c34f4d34fa931a51847cfbb2384e457722ed5..212e4c19f71c6902be8671ed37462ca1466c891a 100644 (file)
@@ -161,15 +161,17 @@ int dosetopt(int minor, struct psdev_opt *opt)
                 * 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 @@ int dogetopt(int minor, struct psdev_opt *opt)
 #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;
        }
index 8d37756a7f13eff3377a87aa5f8e4ee137b08ad1..f8fbdc96352dc5c1b5adc1772f65230b716dd632 100644 (file)
@@ -136,7 +136,7 @@ inline void presto_debug_fail_blkdev(struct presto_file_set *fset,
         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 @@ int presto_do_link(struct presto_file_set *fset, struct dentry *old_dentry,
                 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 @@ int presto_rename_dir(struct presto_file_set *fset, struct dentry *old_parent,
         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 @@ int presto_rename_other(struct presto_file_set *fset, struct dentry *old_parent,
         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)
index a483de6c2ad6a2fc750ae561099e4dbf862a0898..92388ce7e1269071d6264e41bde9c893eff2a07d 100644 (file)
@@ -475,6 +475,7 @@ int journal_write_metadata_buffer(transaction_t *transaction,
 
        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);
index faf2b412b6746b741a53e752ba0b40958328c879..43987b60f6e2a69622158d762118dccf7571a56a 100644 (file)
@@ -278,7 +278,7 @@ int journal_revoke(handle_t *handle, unsigned long blocknr,
 {
        struct buffer_head *bh = NULL;
        journal_t *journal;
-       kdev_t dev;
+       struct block_device *bdev;
        int err;
 
        if (bh_in)
@@ -290,11 +290,11 @@ int journal_revoke(handle_t *handle, unsigned long blocknr,
                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 @@ int journal_revoke(handle_t *handle, unsigned long blocknr,
 
                /* 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 @@ int journal_cancel_revoke(handle_t *handle, struct journal_head *jh)
         * 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);
index 16d8e3ed249f19c00947757f97a44a794635491b..1b113947ccdf0185bf5e2ca93a975d5d274b96a8 100644 (file)
@@ -1864,6 +1864,7 @@ zap_buffer:
        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;
 }
 
index 9c9e76fc1ca512da976dd4087d0250fc3edb320f..7cc0da6a7c0d1d86c32884f31d1c0c6bc6ce7646 100644 (file)
@@ -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 --git a/fs/jffs2/crc32.c b/fs/jffs2/crc32.c
deleted file mode 100644 (file)
index b3b6a81..0000000
+++ /dev/null
@@ -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 --git a/fs/jffs2/crc32.h b/fs/jffs2/crc32.h
deleted file mode 100644 (file)
index cd8979f..0000000
+++ /dev/null
@@ -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 <linux/types.h>
-
-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
index c40a8fb0a45b3f4762231bd6c32c7447ea135859..c1e9143f621fa65505f50a1f407b7bc1a6f82f5d 100644 (file)
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
+#include <linux/crc32.h>
 #include <linux/jffs2.h>
 #include <linux/jffs2_fs_i.h>
 #include <linux/jffs2_fs_sb.h>
 #include "nodelist.h"
-#include "crc32.h"
 
 static int jffs2_readdir (struct file *, void *, filldir_t);
 
index 633875a6d2cd3e051c8f1eaf3c65d8f6ff820d0b..115c7a20f7651255d5c5955693746a0b7386d509 100644 (file)
@@ -39,8 +39,8 @@
 #include <linux/mtd/mtd.h>
 #include <linux/jffs2.h>
 #include <linux/interrupt.h>
+#include <linux/crc32.h>
 #include "nodelist.h"
-#include "crc32.h"
 
 struct erase_priv_struct {
        struct jffs2_eraseblock *jeb;
index 4771c02ee965bfe758438ae65620dcbfb5d9ca07..f0446acb9194cd73d150f1762313ed194af4397b 100644 (file)
@@ -40,9 +40,9 @@
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
+#include <linux/crc32.h>
 #include <linux/jffs2.h>
 #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));
index 4cdb2855759b97ec13899ae212c12a0440fce28e..9294e584c4d492fb65fcf0b500f833b3792f4752 100644 (file)
@@ -42,8 +42,8 @@
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/pagemap.h>
+#include <linux/crc32.h>
 #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);
index cce42560d6ab6355771f25e31dcb3f15a7a408fb..fd46ae954c22921a1ee094ce22518cfdbdbaa763 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/crc32.h>
 #include <linux/jffs2.h>
 #include <linux/mtd/mtd.h>
 #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)
 {
index 2e1d93de3bc501231ce956d5cd6839db8eef31ed..f72affe1a4489afb2ac86fa2c665f7d3b028f633 100644 (file)
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
+#include <linux/crc32.h>
 #include <linux/mtd/mtd.h>
 #include <linux/jffs2.h>
 #include "nodelist.h"
-#include "crc32.h"
 
 
 D1(void jffs2_print_frag_list(struct jffs2_inode_info *f)
index c8708da6ac6954b2c0d3556e71bcf91ff4f9fe38..d1b870bd59dfaf51803d740043e34a2e53a089cf 100644 (file)
@@ -39,8 +39,8 @@
 #include <linux/jffs2.h>
 #include <linux/mtd/mtd.h>
 #include <linux/pagemap.h>
+#include <linux/crc32.h>
 #include "nodelist.h"
-#include "crc32.h"
 
 
 #define DIRTY_SPACE(x) do { typeof(x) _x = (x); \
index e8af1895c565b10d0d90c12a813b9b7f0178d4a6..32c11f9546b044fe675d54d63abffd8206b354c2 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/fs.h>
+#include <linux/crc32.h>
 #include <linux/jffs2.h>
 #include <linux/mtd/mtd.h>
 #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. */
index 20d3add2cf42b1878984d10c07c572dcb948686c..3d9b2dbecde1fc13ce0044fabe41b2fa2952925c 100644 (file)
  * 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);
index b0e1fd06c3f805e00bffdb0cebdbde8e74a28b46..61c8b2b73111576962af2d9a35f278fad1f0d719 100644 (file)
@@ -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)
index 68a58ff9de97b8a2c1dde5425bb2000357647467..870f9c1128797f3a99ea02c277027fba88fcb78a 100644 (file)
@@ -166,7 +166,7 @@ static void extended_partition(struct gendisk *hd, struct block_device *bdev,
                        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 @@ int msdos_partition(struct gendisk *hd, struct block_device *bdev,
                                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)) {
index 9caf7329858686d01be18b0ce2d32087e0ce91cf..a426e4f84584bfb1b35b534e02a7866469f24567 100644 (file)
@@ -168,7 +168,7 @@ retry:
       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;
index 634747f31edfbe602f7559fc5bb4c6bb1ce85b8c..98d6b2dc31aa05d414dfc5bfe91de78a665a9f2b 100644 (file)
@@ -414,12 +414,15 @@ void reiserfs_check_lock_depth(char *caller) {
 }
 
 /* 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_dev(struct reiserf
 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 @@ int dump_journal_writers(void) {
 ** 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 @@ int reiserfs_in_journal(struct super_block *p_s_sb, kdev_t dev,
   }
 
   /* 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 @@ int reiserfs_in_journal(struct super_block *p_s_sb, kdev_t dev,
 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 @@ reiserfs_panic(s, "journal-539: flush_commit_list: BAD count(%d) > orig_commit_l
 ** 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 @@ static struct reiserfs_journal_list *find_newer_jl_for_cn(struct reiserfs_journa
   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 @@ static struct reiserfs_journal_list *find_newer_jl_for_cn(struct reiserfs_journa
 ** 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 @@ static void remove_all_from_journal_list(struct super_block *p_s_sb, struct reis
         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 @@ loop_start:
                 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 @@ static unsigned long reiserfs_journal_kupdate(struct super_block *s) {
 ** 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 @@ void remove_journal_hash(struct reiserfs_journal_cnode **table, struct reiserfs_
        *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 @@ int journal_mark_dirty(struct reiserfs_transaction_handle *th, struct super_bloc
 
     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 @@ int journal_mark_dirty_nolog(struct reiserfs_transaction_handle *th, struct supe
       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 @@ int remove_from_transaction(struct super_block *p_s_sb, unsigned long blocknr, i
   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 @@ int remove_from_transaction(struct super_block *p_s_sb, unsigned long blocknr, i
   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 @@ int remove_from_transaction(struct super_block *p_s_sb, unsigned long blocknr, i
   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 @@ int remove_from_journal_list(struct super_block *s, struct reiserfs_journal_list
 **
 */
 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 @@ static int can_dirty(struct reiserfs_journal_cnode *cn) {
   ** 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 @@ static int can_dirty(struct reiserfs_journal_cnode *cn) {
   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 @@ int journal_mark_freed(struct reiserfs_transaction_handle *th, struct super_bloc
     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 @@ static int do_journal_end(struct reiserfs_transaction_handle *th, struct super_b
       }
       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) ; 
index 775f81cbc2ec04da16ccdae7e535e0c2a952ff19..5648d09857a63360bff1d5ed7237e16371b98895 100644 (file)
@@ -142,6 +142,7 @@ void reiserfs_unmap_buffer(struct buffer_head *bh) {
     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) ;
   }
 }
index 7cf6d031e47b157eef28f5f31631a08bf1d2d2ac..e4f65b8134ee5ab22cfd17577fe68c930edd071b 100644 (file)
@@ -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)
index 3d74130c7d236a7c5cf065cd438c236951f2905d..d42fa22ece834664795737124c8b61f91954ba57 100644 (file)
@@ -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 <asm/page.h>      /* IO address mapping routines need this */
 #include <asm/system.h>
 
-#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)
 {
index 6e59c6d2557d50f0450e24c4a2093ee194d47c2e..6155ccbbacac4d09a59137ebd209b53ece791de5 100644 (file)
@@ -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)
index 274707e2d288a4962ed85ead4e9a7cd06546384c..8391aff3c9f17d01419ea6f9066e8f07ca4cc697 100644 (file)
@@ -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)
 {
 }
index 4e2e6015735b8dc2f7909827f82158e0417b14e9..27ab73c6b0568b30bd61eda6d9247c79bf10d786 100644 (file)
@@ -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 @@ extern int prom_inst2pkg(int);
 
 /* 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. */
index 0bc0b4019c9544f59f7786c90302673c94adf9bc..701ec03bc1428917ab5d2ac294345a1b655af44b 100644 (file)
@@ -26,6 +26,7 @@ extern inline void pcibios_penalize_isa_irq(int irq)
 
 /* Dynamic DMA mapping stuff.
  */
+#define PCI_DMA_BUS_IS_PHYS    (0)
 
 #include <asm/scatterlist.h>
 
index dbdab2c1ebb6898c8749659ea53ee184e78a9f9d..c283f515761753f4a09e3cc38fcedf094506a9be 100644 (file)
@@ -190,8 +190,6 @@ extern __inline__ void smp_send_stop(void) { }
 #define MBOX_IDLECPU2         0xFD
 #define MBOX_STOPCPU2         0xFE
 
-#define PROC_CHANGE_PENALTY     15
-
 #endif /* !(CONFIG_SMP) */
 
 #define NO_PROC_ID            0xFF
index 96565069c98872052d4aba20e15ff0e60d720866..dd2cc2b5426736c4e77cd37c52d9064e189d31fc 100644 (file)
@@ -3,31 +3,35 @@
  *
  * Default SMP lock implementation
  */
+#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
 
 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 @@ do { \
  * so we only need to worry about other
  * CPU's.
  */
-extern __inline__ void lock_kernel(void)
-{
-       if (!++current->lock_depth)
-               spin_lock(&kernel_flag);
-}
+#define lock_kernel()                          \
+do {                                           \
+       if (!++current->lock_depth)             \
+               spin_lock(&kernel_flag);        \
+} while(0)
 
-extern __inline__ void unlock_kernel(void)
-{
-       if (--current->lock_depth < 0)
-               spin_unlock(&kernel_flag);
-}
+#define unlock_kernel()                                \
+do {                                           \
+       if (--current->lock_depth < 0)          \
+               spin_unlock(&kernel_flag);      \
+} while(0)
index 7bce820e8680cf0693ea0737978ce6624efbe806..1182435f416323856a4097d5c860fc8a26b06601 100644 (file)
@@ -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 @@ static inline void *__nonconstant_memset(void *s, char c, __kernel_size_t count)
 })
 
 #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
 
index 8a43339c1410afc8ba53219c0a179db134ec1c68..8e726708e1cd411ac0f61b7116dab6a8ed0f0af9 100644 (file)
@@ -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 @@ typedef unsigned long long u64;
 #define BITS_PER_LONG 32
 
 typedef u32 dma_addr_t;
+typedef u32 dma64_addr_t;
 
 #endif /* __KERNEL__ */
 
index 17ef06746bfbb982c25786570da94511e9d900b2..69e505905cf2bc1095d20e4e157d25343075b3e2 100644 (file)
@@ -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_set_bit(unsigned long nr, volatile void *addr);
 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 @@ found_middle:
 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))
 
index d9a5a903a8dd2546af0b0cfec4cb9553a7a3e3de..dd584acbb34fa8ba8e48d9f1b8d8f6ca26134a38 100644 (file)
@@ -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 @@ do { unsigned char flags = current->thread.flags;    \
        else                                            \
                flags &= ~SPARC_FLAG_32BIT;             \
        if (flags != current->thread.flags) {           \
-               unsigned long pgd_cache = 0UL;          \
-               if (flags & SPARC_FLAG_32BIT) {         \
-                 pgd_t *pgd0 = &current->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;          \
        }                                               \
                                                        \
index 8b8c056caf029783761ee79191a79b353708c28f..58a8ae58100a4e798702521f3bca7202c753462f 100644 (file)
@@ -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
 
index 2202e5a942193607f4d464dd8fa26ca1bb463461..fc81294da408ce47caeed3a6f17767483bd31e84 100644 (file)
@@ -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)
index c8296b0ce4ffa7b995b5e986bc620b3217ef5ce7..11bb4c246126812d2e2ec51cd0987885b6aa2c6d 100644 (file)
@@ -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
 
 #include <asm/system.h>
 #include <asm/spitfire.h>
 
+/*
+ * 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)
 {
 }
index cf6cbc58967a6b5356b1c9a53b29cc71228a39d2..77ee8a08400fffe531c822d4816be9d556b3de03 100644 (file)
@@ -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 @@ extern int prom_inst2pkg(int);
 /* 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, ...);
                                   
 
index 6c65d3241a8b62818226ae562440b6828fc3c7e7..c5de1e232dcfe379bf4bda154a549c9ddfe859c2 100644 (file)
@@ -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
 
 #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);
 
index c026b640a10389fa4c61b732492451c8ee79ac83..dc0e88282f50ed1646d6983e6b6cba040bf511bd 100644 (file)
@@ -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 @@ struct thread_struct {
        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 @@ struct thread_struct {
 #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 @@ struct thread_struct {
 /* 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
index 535ca47717cc30f9be658457865b59b5d2bb5cfb..1717d1a5bed6dd480a4f339c59d111ace2bed2d9 100644 (file)
@@ -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 @@ static inline void __down_read(struct rw_semaphore *sem)
                " 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 @@ static inline void __down_write(struct rw_semaphore *sem)
                "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 @@ static inline void __up_read(struct rw_semaphore *sem)
                "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 @@ static inline void __up_write(struct rw_semaphore *sem)
                " 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 @@ static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
                "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 @@ static inline __u16 rwsem_cmpxchgw(struct rw_semaphore *sem, __u16 __old, __u16
 
 again:
        __asm__ __volatile__("cas       [%2], %3, %0\n\t"
-                            "membar    #StoreStore | #StoreLoad"
+                            "membar    #StoreLoad | #StoreStore"
                             : "=&r" (prev)
                             : "0" (new), "r" (sem), "r" (old)
                             : "memory");
index 7a8aa9597a84e19f9e8cdf37cb5e803b16026ef4..2aaa3160115e266c393fa9b446f0aa6d698f9fe0 100644 (file)
@@ -75,7 +75,7 @@ static __inline__ void down(struct semaphore * sem)
 "      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 @@ static __inline__ int down_interruptible(struct semaphore *sem)
 "      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 @@ static __inline__ int down_trylock(struct semaphore *sem)
 "      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 @@ static __inline__ void up(struct semaphore * sem)
 "      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"
index c2b3a411bbccefb269c99020f582f73a7b45f441..d73d3e657cf5e7bc9e68bbbecc46e7f302510761 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/config.h>
 #include <linux/threads.h>
+#include <linux/cache.h>
 #include <asm/asi.h>
 #include <asm/starfire.h>
 #include <asm/spitfire.h>
@@ -34,7 +35,7 @@ extern struct prom_cpuinfo linux_cpus[64];
 /* 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 @@ struct cpuinfo_sparc {
 
        /* 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 @@ extern __inline__ int hard_smp_processor_id(void)
        }
 }
 
-#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);
 }
 
@@ -126,8 +129,6 @@ extern __inline__ void smp_send_stop(void) { }
 
 #endif /* !(__ASSEMBLY__) */
 
-#define PROC_CHANGE_PENALTY    20
-
 #endif /* !(CONFIG_SMP) */
 
 #define NO_PROC_ID             0xFF
index 6b3c900de906da6a429fe7b010a2f5083c25cc20..dd2cc2b5426736c4e77cd37c52d9064e189d31fc 100644 (file)
@@ -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 @@ do { \
  * 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)
index 06956c1e8920a016c3effa639a2190c48efcaf7f..ce905b46162c0c5913d613ee49818288ba33178b 100644 (file)
@@ -6,11 +6,13 @@
 #ifndef __SPARC64_SPINLOCK_H
 #define __SPARC64_SPINLOCK_H
 
+#include <linux/config.h>
+
 #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 @@ extern __inline__ void spin_unlock(spinlock_t *lock)
                             : "memory");
 }
 
-#else /* !(SPIN_LOCK_DEBUG) */
+#else /* !(CONFIG_DEBUG_SPINLOCK) */
 
 typedef struct {
        unsigned char lock;
@@ -101,11 +103,11 @@ extern int _spin_trylock (spinlock_t *lock);
 #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 @@ extern void __write_unlock(rwlock_t *);
 #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 @@ do {        unsigned long flags; \
        __restore_flags(flags); \
 } while(0)
 
-#endif /* SPIN_LOCK_DEBUG */
+#endif /* CONFIG_DEBUG_SPINLOCK */
 
 #endif /* !(__ASSEMBLY__) */
 
index 26a67f822452a1d62d04ec45d3649539fac679d3..3839b239fe5a3ad36b299a6a8492b4912eeb4ebb 100644 (file)
@@ -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 @@ extern enum ultra_tlb_layout tlb_type;
 
 #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 @@ extern __inline__ void cheetah_flush_itlb_all(void)
  * 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 @@ extern __inline__ unsigned long cheetah_get_litlb_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_ITLB_DATA_ACCESS));
@@ -430,7 +437,8 @@ extern __inline__ unsigned long cheetah_get_dtlb_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" ((2 << 16) | (entry << 3)), "i" (ASI_DTLB_DATA_ACCESS));
 
@@ -461,7 +469,8 @@ extern __inline__ unsigned long cheetah_get_itlb_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" ((2 << 16) | (entry << 3)),
                                "i" (ASI_ITLB_DATA_ACCESS));
index 46dea88f62ae7e751b5203e097a0ae755be1b008..d5b497ddf5e07993aa858ec4acc9d9a5ea43073b 100644 (file)
@@ -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 @@ extern void __flushw_user(void);
 #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 @@ extern void __flushw_user(void);
         * 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 @@ extern __inline__ unsigned long
 __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 @@ extern __inline__ unsigned long
 __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");
index e9960e1c4812826f096c9efad45c69419ceae7bc..8ed23fd00ad6230dbcca7c631b991a634ce31397 100644 (file)
@@ -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
 
         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;                        \
         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;                         \
        ba,pt   %xcc, etraptl1;                         \
index 3f11ceb302dfe338cbb1206c703a649825390184..0cbe78286ab512ab2d15cbd5fe3250a9bd3c4ef0 100644 (file)
@@ -326,10 +326,6 @@ extern int * max_readahead[MAX_BLKDEV];
 #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 --git a/include/linux/crc32.h b/include/linux/crc32.h
new file mode 100644 (file)
index 0000000..a0033ff
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * crc32.h
+ * See linux/lib/crc32.c for license and changes
+ */
+#ifndef _LINUX_CRC32_H
+#define _LINUX_CRC32_H
+
+#include <linux/types.h>
+
+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 */
index b102c2d51d544bed6b7edc908d6eb3688c959d14..a01f0c3b4d34df475a84532417c42d46eb0974ed 100644 (file)
@@ -245,6 +245,7 @@ struct buffer_head {
        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 insert_inode_hash(struct inode *);
 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_getblk(struct super_block *sb, int block)
 }
 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 wakeup_bdflush(void);
 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);
 
index ba663102f02fd7bd017e3f4fc6625f66c3f16b31..dd936fe6180ea6c541800345f45eeb9891bd3df6 100644 (file)
@@ -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 */
 
index d719560dde0b0dd21907532ce66eaf3f1969d350..97d490fd8dd823eefaa267340d15ef8232751ad5 100644 (file)
@@ -79,6 +79,15 @@ typedef struct slave {
        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;
index 465b35c3d245ff0a992ca36a7e7afbc14552194f..abc0c3e7bad2e1d3ff1d9906abaeca189572ea13 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _KBD_KERN_H
 #define _KBD_KERN_H
 
+#include <linux/tty.h>
 #include <linux/interrupt.h>
 #include <linux/keyboard.h>
 
index 51c49ec4e325bf9547b36627b2f5bca5d82a8ea4..45faa81d981d404a1a6d92142bd8ff991d5be75e 100644 (file)
@@ -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
index 8ce25aae46f0934a37237280d5a667a1b73b89a4..f0e8b9927eabf2d4c3c758e2ce08d75f2d56cd23 100644 (file)
@@ -27,6 +27,21 @@ enum ip_conntrack_info
        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 <linux/types.h>
@@ -47,21 +62,6 @@ do {                                                                 \
 #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
 {
        /* Internal linked list */
index 8b6dc4a8bf57b8e387691e976f337c0c6dabd8e4..9f6ec0a6bccc11a3cd1e051aa63f65bfe38aab2f 100644 (file)
@@ -62,6 +62,13 @@ struct ip_conntrack_tuple
        } 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 @@ DEBUGP("tuple %p: %u %u.%u.%u.%u:%hu -> %u.%u.%u.%u:%hu\n", \
 /* 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 @@ static inline int ip_ct_tuple_mask_cmp(const struct ip_conntrack_tuple *t,
                     & 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 */
index b50d60989eae33771bdb31c9a0770e578407cf42..1c4cec479ba34381c5d90cfe64cbeb5b37545f08 100644 (file)
@@ -1651,7 +1651,7 @@ extern wait_queue_head_t reiserfs_commit_thread_wait ;
 #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 pop_journal_writer(int windex) ;
 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) ;
index 1eee601a12defe70c349651c96a88d9c7109c971..a78f789867235de9498afa60ad52a87768b0072b 100644 (file)
@@ -199,7 +199,7 @@ struct reiserfs_super_block_v1
 */
 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 */
index 068d5b802a236eded5814298446fe662accf5970..14b6388cc3c29cdc39fee42deeaaac167c7c1624 100644 (file)
@@ -305,7 +305,7 @@ struct task_struct {
        prio_array_t *array;
 
        unsigned int time_slice;
-       unsigned long swap_cnt_last;
+       unsigned long sleep_jtime;
 
        unsigned long policy;
        unsigned long cpus_allowed;
index fbcfce81e1105ba6bfc472b62954edfa46a7e480..070eef7b5137e8f08e05df8d645588a3cc814e86 100644 (file)
@@ -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;
index 7887eee13d790bf6867fbc2edf8bb9309f65fe97..74303f129fddb093fdf329864c1a38bd457b0ca2 100644 (file)
@@ -156,6 +156,7 @@ struct ucred {
 #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 @@ struct ucred {
 #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 @@ struct ucred {
 #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
index 62f4b1bd4dd1ee2f507038a95afd73bd2082c69b..be4c52c62c1c53a08a58af8e0cf935394fde9564 100644 (file)
@@ -137,7 +137,6 @@ rpc_set_timeout(struct rpc_clnt *clnt, unsigned int retr, unsigned long incr)
        xprt_set_timeout(&clnt->cl_timeout, retr, incr);
 }
 
-extern void rpciod_tcp_dispatcher(void);
 extern void rpciod_wake_up(void);
 
 /*
index 7ea6e7334bc5d69fe6c61d1b365707713fcff7ad..b0ac23988cf4c7177472a9b118c98bab915125a1 100644 (file)
@@ -65,8 +65,7 @@ struct swap_info_struct {
        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 struct swap_info_struct swap_info[];
 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 *);
index 04c4c0f4584cd931301b95b8dc2c9d9bae7cb2a0..655ccf1c47398b57f4448967d310df3104a4c038 100644 (file)
@@ -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 @@ union _FP_UNION_D
 #define _FP_FRAC_HIGH_RAW_D(X) _FP_FRAC_HIGH_1(X)
 
 #endif /* W_TYPE_SIZE < 64 */
+
+
+#endif /* __MATH_EMU_DOUBLE_H__ */
index ae73cecb399bb12936c580abfb0f480996c0d2e1..84770fceb53e053cc8e2647c21710729c11bf051 100644 (file)
    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 @@ union _FP_UNION_E
 #define _FP_FRAC_HIGH_RAW_E(X) (X##_f0)
 
 #endif /* not _FP_W_TYPE_SIZE < 64 */
+
+#endif /* __MATH_EMU_EXTENDED_H__ */
index 53e0fce1b18d435657fd25d2a022d7ff9eda57cb..38c0561b70a6a6dee0206615deee88e7c11ad0d4 100644 (file)
@@ -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)
     else                                                               \
       D##_f <<= _FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs;             \
   } while (0)
+
+#endif /* __MATH_EMU_OP_1_H__ */
index e639d534e67f7a5246b01b760a459ad0b825f7c1..81416782bc36878c204111667e089257950b8e8c 100644 (file)
@@ -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)
     _FP_FRAC_SLL_2(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs));    \
   } while (0)
 
+#endif
index f5235f5d9726cc3099e87c2d8a970c98d7e6f060..2aa1356325adcb680c5b23a6b9f3d9e3251e403d 100644 (file)
@@ -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],   \
      _FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs));   \
    } while (0)
 
+#endif
index a9d7dbf5908077a47141cc7bb2ca5aba1a3279c3..8b8c05eb8283e0c0f1d635b5933e7efbbb5b9886 100644 (file)
@@ -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]
     X##_f[0] |= (_s != 0);                                             \
   } while (0)
 
+#endif
index e03e40e656bc3943994031587477384cd628e3b3..dd37d44940c4e49dade625c31753a542c8d97cdd 100644 (file)
@@ -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 @@ do {                                                                        \
     q = n / d, r = n % d;                      \
   } while (0)
 
+#endif /* __MATH_EMU_OP_COMMON_H__ */
index 23b20c3e672fc016415b6859de6c9c1eb88e85b4..616113626d096077d0f2a1519d8daf552f018516 100644 (file)
@@ -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 @@ union _FP_UNION_Q
 #define _FP_FRAC_HIGH_RAW_Q(X) _FP_FRAC_HIGH_2(X)
 
 #endif /* not _FP_W_TYPE_SIZE < 64 */
+
+#endif /* __MATH_EMU_QUAD_H__ */
index ea12cb8b0a31179d99f7ecbc00af0c590ed3e523..87f90b0f9e5d75133586ce1593d1c6d9648485b9 100644 (file)
@@ -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 @@ union _FP_UNION_S
 
 #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__ */
index 1d13451346b5ea177bc70be6ec96b892b08b6286..ca977531a1bce08d43ba8fbc0f6af22be5ca45ad 100644 (file)
@@ -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 <asm/sfp-machine.h>
 
@@ -178,4 +178,4 @@ typedef USItype UHWtype;
 #include <stdlib/longlong.h>
 #endif
 
-#endif
+#endif /* __MATH_EMU_SOFT_FP_H__ */
index eded2d7fb3393f679ac0c4eb5e4875a2e5823220..f3f8775d878598caef21cba6a2d84ec3bad27eab 100644 (file)
@@ -511,7 +511,7 @@ EXPORT_SYMBOL(clear_inode);
 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);
index 8df860f0922c085b95f4095ffdba8f23b004d5f6..cfa9dc97603db0dca3e5944b9806584d67ad19b0 100644 (file)
@@ -21,6 +21,9 @@
 #include <asm/mmu_context.h>
 
 #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 @@ static struct runqueue {
        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 @@ static inline void activate_task(task_t *p, runqueue_t *rq)
        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 @@ static inline void deactivate_task(struct task_struct *p, runqueue_t *rq)
        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 @@ void expire_task(task_t *p)
                                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 @@ need_resched_back:
        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 @@ pick_next_task:
                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 @@ void __init sched_init(void)
                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 --git a/lib/Config.in b/lib/Config.in
new file mode 100644 (file)
index 0000000..6072b45
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Library configuration
+#
+mainmenu_option next_comment
+comment 'Library routines'
+
+tristate 'CRC32 functions' CONFIG_CRC32
+endmenu
index 38a91fa0c9e7294b1bdf952476152d7caa25b12c..9e2d80f5f3505bc5a386f1c80942be2e06ad80e8 100644 (file)
@@ -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
 
@@ -19,4 +19,9 @@ 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 --git a/lib/crc32.c b/lib/crc32.c
new file mode 100644 (file)
index 0000000..8bf7b8d
--- /dev/null
@@ -0,0 +1,571 @@
+/* 
+ * Oct 15, 2000 Matt Domsch <Matt_Domsch@dell.com>
+ * Nicer crc32 functions/docs submitted by linux@horizon.com.  Thanks!
+ *
+ * Oct 12, 2000 Matt Domsch <Matt_Domsch@dell.com>
+ * 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 <linux/crc32.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <asm/atomic.h>
+
+#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 <Matt_Domsch@dell.com>");
+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<<CRC_xx_BITS bytes. */
+/* For less performance-sensitive, use 4 */
+#define CRC_LE_BITS 8
+#define CRC_BE_BITS 8
+
+/*
+ * Little-endian CRC computation.  Used with serial bit streams sent
+ * lsbit-first.  Be sure to use cpu_to_le32() to append the computed CRC.
+ */
+#if CRC_LE_BITS > 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 <stdlib.h>
+#include <stdio.h>
+
+#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);
index adafe138a3da39dac30b2ec607597a22f6117f11..3b0420d653cb5d75427435647d56e46c6d586b16 100644 (file)
@@ -155,6 +155,12 @@ static void * __init __alloc_bootmem_core (bootmem_data_t *bdata,
        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 @@ static void * __init __alloc_bootmem_core (bootmem_data_t *bdata,
                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 @@ restart_scan:
        fail_block:;
        }
        if (preferred) {
-               preferred = 0;
+               preferred = offset;
                goto restart_scan;
        }
        return NULL;
index 21fc70173587bc03064aa1a97ab4d24e988cb803..672500e52b46e0be0781047c0262565bafe86726 100644 (file)
@@ -25,7 +25,7 @@ static mempool_t *page_pool, *isa_page_pool;
 
 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);
 }
index 79700f304b18bf5ae802cf8e55b5ab50564b9738..cacb3952178fa4889d1fc0c57df3035b5f1fd353 100644 (file)
@@ -38,9 +38,9 @@ static int rw_swap_page_base(int rw, swp_entry_t entry, struct page *page)
        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 @@ static int rw_swap_page_base(int rw, swp_entry_t entry, struct page *page)
        } 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 @@ static int rw_swap_page_base(int rw, swp_entry_t entry, struct page *page)
                                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
index ff9a8e1f00ef5ce31d46af4c3cee5cd7cfa7d77b..2149e6eda67982e6367bff4200746deb3e9f83d6 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/kernel_stat.h>
 #include <linux/swap.h>
 #include <linux/swapctl.h>
-#include <linux/blkdev.h> /* for blk_size */
 #include <linux/vmalloc.h>
 #include <linux/pagemap.h>
 #include <linux/shm.h>
@@ -713,6 +712,7 @@ asmlinkage long sys_swapoff(const char * specialfile)
 {
        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 @@ asmlinkage long sys_swapoff(const char * specialfile)
        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 @@ asmlinkage long sys_swapoff(const char * specialfile)
                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 @@ asmlinkage long sys_swapoff(const char * specialfile)
        swap_device_unlock(p);
        swap_list_unlock();
        vfree(swap_map);
+       filp_close(swap_file, NULL);
        err = 0;
 
 out_dput:
@@ -813,7 +808,8 @@ int get_swaparea_info(char *buf)
        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 @@ int get_swaparea_info(char *buf)
                                }
                        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 @@ int is_swap_partition(kdev_t dev) {
 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 @@ asmlinkage long sys_swapon(const char * specialfile, int swap_flags)
        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 @@ asmlinkage long sys_swapon(const char * specialfile, int swap_flags)
                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 @@ asmlinkage long sys_swapon(const char * specialfile, int swap_flags)
                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 @@ asmlinkage long sys_swapon(const char * specialfile, int swap_flags)
        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 @@ bad_swap_2:
        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 @@ bad_unused:
  * 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 @@ void get_swaphandle_info(swp_entry_t entry, unsigned long *offset,
                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;
 }
 
 /*
index e549e336038ee85c07911ffb60ea2a4a3e6a7571..f6be310ede54b1a292af054e857053263f378716 100644 (file)
@@ -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 <greearb@candelatech.com>, <greearb@agcs.com>
+ * Authors:    Ben Greear <greearb@candelatech.com>
+ *              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 <nick@dccinc.com>;
@@ -42,7 +41,7 @@ struct vlan_group *p802_1Q_vlan_list;
 
 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 <greearb@candelatech.com>";
 
 static int vlan_device_event(struct notifier_block *, unsigned long, void *);
@@ -105,6 +104,23 @@ static int __init vlan_proto_init(void)
        return 0;
 }
 
+/*
+ * 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 @@ static void __exit vlan_cleanup_module(void)
 
        dev_remove_pack(&vlan_packet_type);
        vlan_proc_cleanup();
-
+       vlan_group_cleanup();
        vlan_ioctl_hook = NULL;
 }
 
@@ -328,6 +344,7 @@ struct net_device *register_802_1Q_vlan_device(const char* eth_IF_name,
        /* 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.
index 00a7f07bded92db37be32a06e1ce34442536458e..7da75dbadd93d241cbea237b62f667e9ab1bead7 100644 (file)
@@ -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 <greearb@candelatech.com>, <greearb@agcs.com>
+ * Authors:    Ben Greear <greearb@candelatech.com>
+ *              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 <mbokaemper@unispherenetworks.com>
  *                - reset skb->pkt_type on incoming packets when MAC was changed
@@ -512,10 +511,6 @@ void vlan_dev_destruct(struct net_device *dev)
                        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;
        }
 }
 
index 4315f2cb45d4847e16e9fd29bb81b5cd41539f66..5c994e1a1257e9545ae41038870e7caf816d7a4e 100644 (file)
@@ -115,7 +115,7 @@ static char conf_hdr[] = "VLAN Dev name      | VLAN ID\n";
  *     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 @@ int __init vlan_proc_init (void)
        return 0;
 }
 
-void __exit vlan_proc_cleanup(void)
+void vlan_proc_cleanup(void)
 {
        return;
 }
index 0b9568a8ab9c257e153a753e2dc1bf482e7100e6..3650e020c955bb6b08c9ae0553f5e77b05565e4e 100644 (file)
@@ -61,7 +61,7 @@ tristate 'DECnet Support' CONFIG_DECNET
 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
index 24065ec3ffc52273f2e48cb25cf18e6e739e2ae3..e509ec526c2542d0a2f9d162909471027573b90c 100644 (file)
@@ -23,4 +23,4 @@ wanrouter             gene@compuserve.com, jaspreet@sangoma and dm@sangoma.com
 unix                   alan@lxorguk.ukuu.org.uk
 x25                    g4klx@g4klx.demon.co.uk
 bluetooth              maxk@qualcomm.com
-
+8021q                   greearb@candelatech.com, vlan@scry.wanfear.com
index f91d8fa6d200c1f8e2f13962620e5b14ef5aa8f4..9be42e03b40a65fcf326776a4d070089d2947b98 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Lennert Buytenhek               <buytenh@gnu.org>
  *
- *     $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 @@ static int __init br_init(void)
        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_frame_hook(void)
 
 static void __br_clear_ioctl_hook(void)
 {
-#ifdef CONFIG_INET
        br_ioctl_hook = NULL;
-#endif 
 }
 
 static void __exit br_deinit(void)
index 95772a1e3dc648086f2ea13d35256f1589a9e23a..94e8312a059c788e6851a248f82eb5f7c17f511b 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Lennert Buytenhek               <buytenh@gnu.org>
  *
- *     $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 @@ static int __br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
        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;
index 08c58f19fe496ea7ed1db4085bd9e6c9e50bc66b..ea1a238bc7903ce829c1139890ea7ed735b815ac 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Lennert Buytenhek               <buytenh@gnu.org>
  *
- *     $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 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
        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) {
@@ -262,8 +265,6 @@ int br_get_bridge_ifindices(int *indices, int num)
        struct net_bridge *br;
        int i;
 
-       i = 0;
-
        br = bridge_list;
        for (i=0;i<num;i++) {
                if (br == NULL)
index dc1e1561a05140fc99b93339102eb495ea25f66f..907eb151316e89590ea574095c61217642cfa8f8 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Lennert Buytenhek               <buytenh@gnu.org>
  *
- *     $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 @@ static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb)
                        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 @@ static void __br_handle_frame(struct sk_buff *skb)
        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);
 }
index a83504d832eb94bfcdb426df533dabb49fdedb8c..e8ba48aae6a6169ecbfdee478c6025e3df603ca3 100644 (file)
@@ -4,7 +4,7 @@
  *     Authors:
  *     Lennert Buytenhek               <buytenh@gnu.org>
  *
- *     $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 @@ extern void br_inc_use_count(void);
 
 /* 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,
index 62452f1080f6c061d8a244e2da7e9563b0c2a6c9..84edccae67450cb255065e6e0eabf54e0a680443 100644 (file)
@@ -3,7 +3,7 @@
  *     
  *             Alan Cox, <alan@redhat.com>
  *
- *     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 @@ int sysctl_icmp_ignore_bogus_error_responses;
  *     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;
index bf1c7793a1dd5c03184a279a92bc20f061161ace..79cec8993d40522a31fdbb51fa49d145dd372d49 100644 (file)
@@ -1,8 +1,8 @@
-/* IRC extension for IP connection tracking, Version 1.19
- * (C) 2000 by Harald Welte <laforge@gnumonks.org>
+/* IRC extension for IP connection tracking, Version 1.20
+ * (C) 2000-2001 by Harald Welte <laforge@gnumonks.org>
  * 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<MAX_PORTS>
+ *     insmod ip_conntrack_irc.o ports=port1,port2,...port<MAX_PORTS>
  *     
  *     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
index 3c60c0d78ea163798a7b068ed1a8f0f5fc795724..1846640d2837776543d53d4a2022601476bfbbec 100644 (file)
@@ -243,7 +243,7 @@ static int init_or_cleanup(int init)
 
        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);
index 6489ad7871104f8c927799f7c8ad6fa44521c6b5..021d125f39073b3066272571515520609ff9cc1b 100644 (file)
@@ -84,6 +84,16 @@ fw_in(unsigned int hooknum,
        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)
index 274bb1162265e09aef2a9ab6d90fcc4e8e9e166b..f55680e7e6fab1ce1cc5258cb1dbc6b5c2041c8d 100644 (file)
@@ -206,6 +206,8 @@ do_redirect(struct sk_buff *skb,
                        }
                        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)
index 79d533aae1381ee97bd3d5ea3542a0420d70dfcb..07ebd39fa11596b078687a5a70f33cd91f624390 100644 (file)
@@ -734,6 +734,18 @@ do_bindings(struct ip_conntrack *ct,
           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",
index d62b5bf413a523a7a6a6052c4a3f04dbeb34be9b..183ba3f85356dcbba3bf02a8b36827b8b0d1d9b8 100644 (file)
@@ -143,6 +143,23 @@ ip_nat_mangle_tcp_packet(struct sk_buff **skb,
                }
        }
 
+       /* 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;
index 02102b369745424325cb5d38213f5bfcbd56d2d2..2a8b83afaf5b4b50015e1fb52f8385762fe1ae71 100644 (file)
@@ -1,8 +1,8 @@
 /* IRC extension for TCP NAT alteration.
- * (C) 2000 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2000-2001 by Harald Welte <laforge@gnumonks.org>
  * 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 @@ irc_nat_expected(struct sk_buff **pskb,
        }
 
        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));
 
index d984d7e1fb9a09fb5daa78d629b1af5517647e39..2fd35b69924feb2b17f6a64b928e274f3b78a004 100644 (file)
@@ -6,6 +6,10 @@
 
   Copyright (C) 2000 Emmanuel Roger <winfield@freegates.be>
 
+  Changes:
+       25 Aug 2001 Harald Welte <laforge@gnumonks.org>
+               - 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 <linux/skbuff.h>
 #include <linux/ip.h>
 #include <net/ip.h>
+#include <net/icmp.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netdevice.h>
 #include <linux/route.h>
@@ -100,15 +105,31 @@ static unsigned int ipt_mirror_target(struct sk_buff **pskb,
                                      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;
 }
index ced0a9dced52dc29a37c74426d423a6167b51c66..68eb02cd9f20a09e21b8bd0d3e451ad71077cced 100644 (file)
@@ -44,11 +44,22 @@ ipt_tcpmss_target(struct sk_buff **pskb,
 {
        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;
index e6061d707ac5b1775bebdf2c2edec3a6087b1fe5..90d7173f3d0b713a71c31601e68c528f64ba0e31 100644 (file)
@@ -21,6 +21,17 @@ target(struct sk_buff **pskb,
        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);
index 80b6c55dbb0ef913fd1231876e550b1230fe5401..8ca4852f9c7a1ab0d9e1743fade14c7f1a93947b 100644 (file)
@@ -257,6 +257,8 @@ check_udp(const struct iphdr *iph,
 #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(const struct iphdr *iph,
        }
 
        /* 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)
index 738a3e5d220ed59612105b54a0ce04a49e51eb18..96a37a29d1ab09db0ac08924e8c1132e7612d013 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>     
  *
- *     $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 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
 
        tcp_parse_options(skb, &tp, 0);
 
+       tp.tstamp_ok = tp.saw_tstamp;
        tcp_openreq_init(req, &tp, skb);
 
        req->class = &or_ipv6;
index 7313f8c18bffcc6fb1a1a4046bb98d9126ce9d39..7ca2e8d46b0f7ac332bc1183bc32b8d2581d5d65 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/spinlock.h>
 
 #include <linux/sunrpc/clnt.h>
+#include <linux/sunrpc/xprt.h>
 
 #ifdef RPC_DEBUG
 #define RPCDBG_FACILITY                RPCDBG_SCHED
index 5588c4c732000426e5d53e28b71ca8fd639b308d..18ddb790db8e039434fa2c1f64bb4c2c71d298ff 100644 (file)
@@ -630,10 +630,14 @@ static int csum_partial_copy_to_page_cache(struct iovec *iov,
                        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 @@ static int csum_partial_copy_to_page_cache(struct iovec *iov,
                }
        }
        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;
        }