aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@athlon.transmeta.com>2002-02-05 00:13:33 -0800
committerLinus Torvalds <torvalds@athlon.transmeta.com>2002-02-05 00:13:33 -0800
commit5fb612aa91a08c183200312d943de6691f806ce6 (patch)
treeeeab4310853f2b2f3bed3a1931932d46b2bf39f9
parent18a933102825ea1e1b7e059234537d4d927e9216 (diff)
downloadhistory-5fb612aa91a08c183200312d943de6691f806ce6.tar.gz
v2.5.1.11 -> v2.5.2v2.5.2
- 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)
-rw-r--r--Documentation/Configure.help19
-rw-r--r--Documentation/block/request.txt86
-rw-r--r--Documentation/cciss.txt2
-rw-r--r--Documentation/filesystems/devfs/ChangeLog6
-rw-r--r--Documentation/networking/ip-sysctl.txt21
-rw-r--r--Makefile6
-rw-r--r--arch/alpha/config.in2
-rw-r--r--arch/arm/config.in2
-rw-r--r--arch/cris/config.in2
-rw-r--r--arch/i386/config.in2
-rw-r--r--arch/i386/defconfig6
-rw-r--r--arch/i386/kernel/setup.c1
-rw-r--r--arch/ia64/config.in2
-rw-r--r--arch/m68k/config.in2
-rw-r--r--arch/mips/config.in2
-rw-r--r--arch/mips64/config.in2
-rw-r--r--arch/parisc/config.in1
-rw-r--r--arch/ppc/config.in2
-rw-r--r--arch/s390/config.in1
-rw-r--r--arch/s390x/config.in1
-rw-r--r--arch/sh/config.in2
-rw-r--r--arch/sparc/config.in2
-rwxr-xr-xarch/sparc/kernel/check_asm.sh4
-rw-r--r--arch/sparc/kernel/devices.c3
-rw-r--r--arch/sparc/kernel/ebus.c2
-rw-r--r--arch/sparc/kernel/init_task.c4
-rw-r--r--arch/sparc/kernel/irq.c2
-rw-r--r--arch/sparc/kernel/process.c54
-rw-r--r--arch/sparc/kernel/signal.c3
-rw-r--r--arch/sparc/kernel/sun4d_irq.c2
-rw-r--r--arch/sparc/kernel/sun4d_smp.c10
-rw-r--r--arch/sparc/kernel/sun4m_smp.c8
-rw-r--r--arch/sparc/kernel/sys_sunos.c6
-rw-r--r--arch/sparc/kernel/trampoline.S4
-rw-r--r--arch/sparc/kernel/unaligned.c6
-rw-r--r--arch/sparc/mm/extable.c68
-rw-r--r--arch/sparc/mm/fault.c49
-rw-r--r--arch/sparc/mm/init.c5
-rw-r--r--arch/sparc/mm/io-unit.c4
-rw-r--r--arch/sparc/mm/iommu.c12
-rw-r--r--arch/sparc/prom/ranges.c17
-rw-r--r--arch/sparc64/Makefile26
-rw-r--r--arch/sparc64/config.in46
-rw-r--r--arch/sparc64/defconfig59
-rw-r--r--arch/sparc64/kernel/Makefile16
-rw-r--r--arch/sparc64/kernel/central.c3
-rwxr-xr-xarch/sparc64/kernel/check_asm.sh4
-rw-r--r--arch/sparc64/kernel/chmc.c6
-rw-r--r--arch/sparc64/kernel/entry.S28
-rw-r--r--arch/sparc64/kernel/ioctl32.c180
-rw-r--r--arch/sparc64/kernel/iommu_common.c27
-rw-r--r--arch/sparc64/kernel/irq.c45
-rw-r--r--arch/sparc64/kernel/pci_iommu.c10
-rw-r--r--arch/sparc64/kernel/pci_psycho.c17
-rw-r--r--arch/sparc64/kernel/pci_sabre.c8
-rw-r--r--arch/sparc64/kernel/pci_schizo.c8
-rw-r--r--arch/sparc64/kernel/power.c19
-rw-r--r--arch/sparc64/kernel/process.c29
-rw-r--r--arch/sparc64/kernel/rtrap.S131
-rw-r--r--arch/sparc64/kernel/sbus.c10
-rw-r--r--arch/sparc64/kernel/semaphore.c4
-rw-r--r--arch/sparc64/kernel/signal.c3
-rw-r--r--arch/sparc64/kernel/signal32.c3
-rw-r--r--arch/sparc64/kernel/smp.c96
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c15
-rw-r--r--arch/sparc64/kernel/sys_sparc.c44
-rw-r--r--arch/sparc64/kernel/sys_sunos32.c14
-rw-r--r--arch/sparc64/kernel/time.c3
-rw-r--r--arch/sparc64/kernel/trampoline.S4
-rw-r--r--arch/sparc64/kernel/traps.c37
-rw-r--r--arch/sparc64/kernel/ttable.S8
-rw-r--r--arch/sparc64/lib/atomic.S6
-rw-r--r--arch/sparc64/lib/bitops.S12
-rw-r--r--arch/sparc64/lib/blockops.S80
-rw-r--r--arch/sparc64/lib/debuglocks.c59
-rw-r--r--arch/sparc64/lib/dec_and_lock.S14
-rw-r--r--arch/sparc64/mm/extable.c68
-rw-r--r--arch/sparc64/mm/init.c12
-rw-r--r--arch/sparc64/mm/ultra.S13
-rw-r--r--arch/sparc64/solaris/fs.c6
-rw-r--r--arch/sparc64/solaris/misc.c7
-rw-r--r--arch/sparc64/solaris/socksys.c6
-rw-r--r--arch/sparc64/solaris/timod.c4
-rw-r--r--drivers/block/Config.in1
-rw-r--r--drivers/block/cciss.c82
-rw-r--r--drivers/block/cciss.h3
-rw-r--r--drivers/block/cciss_cmd.h8
-rw-r--r--drivers/block/cciss_scsi.c1634
-rw-r--r--drivers/block/cciss_scsi.h98
-rw-r--r--drivers/block/cpqarray.c13
-rw-r--r--drivers/block/elevator.c13
-rw-r--r--drivers/block/ll_rw_blk.c15
-rw-r--r--drivers/block/nbd.c6
-rw-r--r--drivers/char/rtc.c4
-rw-r--r--drivers/md/md.c22
-rw-r--r--drivers/md/multipath.c1
-rw-r--r--drivers/md/raid5.c2
-rw-r--r--drivers/message/i2o/i2o_block.c4
-rw-r--r--drivers/net/7990.c19
-rw-r--r--drivers/net/7990.h3
-rw-r--r--drivers/net/8139cp.c17
-rw-r--r--drivers/net/8139too.c19
-rw-r--r--drivers/net/8390.c27
-rw-r--r--drivers/net/Makefile.lib69
-rw-r--r--drivers/net/a2065.c20
-rw-r--r--drivers/net/a2065.h3
-rw-r--r--drivers/net/am79c961a.c25
-rw-r--r--drivers/net/at1700.c22
-rw-r--r--drivers/net/atp.c21
-rw-r--r--drivers/net/au1000_eth.c17
-rw-r--r--drivers/net/bmac.c17
-rw-r--r--drivers/net/bonding.c189
-rw-r--r--drivers/net/de2104x.c36
-rw-r--r--drivers/net/de4x5.c15
-rw-r--r--drivers/net/declance.c20
-rw-r--r--drivers/net/depca.c16
-rw-r--r--drivers/net/dl2k.c22
-rw-r--r--drivers/net/dl2k.h1
-rw-r--r--drivers/net/dmfe.c84
-rw-r--r--drivers/net/epic100.c22
-rw-r--r--drivers/net/ewrk3.c17
-rw-r--r--drivers/net/fealnx.c22
-rw-r--r--drivers/net/gmac.c18
-rw-r--r--drivers/net/ioc3-eth.c20
-rw-r--r--drivers/net/mace.c22
-rw-r--r--drivers/net/macmace.c22
-rw-r--r--drivers/net/myri_code.h2
-rw-r--r--drivers/net/myri_sbus.c3
-rw-r--r--drivers/net/natsemi.c46
-rw-r--r--drivers/net/pci-skeleton.c23
-rw-r--r--drivers/net/pcmcia/fmvj18x_cs.c22
-rw-r--r--drivers/net/pcmcia/smc91c92_cs.c26
-rw-r--r--drivers/net/pcmcia/xircom_tulip_cb.c38
-rw-r--r--drivers/net/pcnet32.c21
-rw-r--r--drivers/net/shaper.c5
-rw-r--r--drivers/net/sis900.c27
-rw-r--r--drivers/net/sk98lin/h/skdrv1st.h1
-rw-r--r--drivers/net/sk98lin/skaddr.c16
-rw-r--r--drivers/net/smc9194.c35
-rw-r--r--drivers/net/starfire.c26
-rw-r--r--drivers/net/sunbmac.c18
-rw-r--r--drivers/net/sundance.c27
-rw-r--r--drivers/net/sungem.c1232
-rw-r--r--drivers/net/sungem.h111
-rw-r--r--drivers/net/sunhme.c36
-rw-r--r--drivers/net/sunlance.c25
-rw-r--r--drivers/net/sunqe.c22
-rw-r--r--drivers/net/tulip/tulip_core.c36
-rw-r--r--drivers/net/via-rhine.c21
-rw-r--r--drivers/net/winbond-840.c17
-rw-r--r--drivers/net/yellowfin.c24
-rw-r--r--drivers/s390/block/dasd_int.h2
-rw-r--r--drivers/s390/block/xpram.c2
-rw-r--r--drivers/s390/char/tapedefs.h2
-rw-r--r--drivers/sbus/audio/audio.c16
-rw-r--r--drivers/sbus/char/aurora.c6
-rw-r--r--drivers/sbus/char/cpwatchdog.c2
-rw-r--r--drivers/sbus/char/display7seg.c8
-rw-r--r--drivers/sbus/char/sab82532.c8
-rw-r--r--drivers/sbus/char/su.c8
-rw-r--r--drivers/sbus/char/sunserial.c2
-rw-r--r--drivers/sbus/char/zs.c213
-rw-r--r--drivers/sbus/sbus.c3
-rw-r--r--drivers/scsi/advansys.c9
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_linux.c1
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.h10
-rw-r--r--drivers/scsi/constants.c1
-rw-r--r--drivers/scsi/hosts.c16
-rw-r--r--drivers/scsi/hosts.h15
-rw-r--r--drivers/scsi/ide-scsi.c8
-rw-r--r--drivers/scsi/scsi.c88
-rw-r--r--drivers/scsi/scsi_error.c49
-rw-r--r--drivers/scsi/scsi_ioctl.c1
-rw-r--r--drivers/scsi/scsi_lib.c5
-rw-r--r--drivers/scsi/scsi_merge.c1
-rw-r--r--drivers/scsi/scsi_proc.c1
-rw-r--r--drivers/scsi/scsi_queue.c5
-rw-r--r--drivers/scsi/scsi_scan.c1
-rw-r--r--drivers/scsi/scsi_syms.c1
-rw-r--r--drivers/scsi/scsicam.c1
-rw-r--r--drivers/scsi/sym53c8xx.c4
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c6
-rw-r--r--drivers/sound/trident.c16
-rw-r--r--drivers/sound/ymfpci.c367
-rw-r--r--drivers/sound/ymfpci.h22
-rw-r--r--drivers/telephony/phonedev.c2
-rw-r--r--drivers/usb/Makefile.lib1
-rw-r--r--drivers/usb/catc.c9
-rw-r--r--drivers/usb/hcd.c2
-rw-r--r--drivers/usb/hcd/ehci-hcd.c2
-rw-r--r--drivers/usb/hcd/ehci-sched.c2
-rw-r--r--drivers/video/aty/mach64_accel.c2
-rw-r--r--drivers/video/sbusfb.c2
-rw-r--r--fs/Makefile.lib2
-rw-r--r--fs/affs/file.c1
-rw-r--r--fs/block_dev.c1
-rw-r--r--fs/buffer.c43
-rw-r--r--fs/coda/inode.c4
-rw-r--r--fs/coda/pioctl.c2
-rw-r--r--fs/dcache.c2
-rw-r--r--fs/devfs/base.c150
-rw-r--r--fs/devpts/root.c8
-rw-r--r--fs/driverfs/inode.c2
-rw-r--r--fs/fat/cache.c2
-rw-r--r--fs/fat/inode.c4
-rw-r--r--fs/inode.c2
-rw-r--r--fs/intermezzo/cache.c8
-rw-r--r--fs/intermezzo/presto.c4
-rw-r--r--fs/intermezzo/psdev.c7
-rw-r--r--fs/intermezzo/sysctl.c13
-rw-r--r--fs/intermezzo/vfs.c8
-rw-r--r--fs/jbd/journal.c1
-rw-r--r--fs/jbd/revoke.c10
-rw-r--r--fs/jbd/transaction.c1
-rw-r--r--fs/jffs2/Makefile2
-rw-r--r--fs/jffs2/crc32.c97
-rw-r--r--fs/jffs2/crc32.h21
-rw-r--r--fs/jffs2/dir.c2
-rw-r--r--fs/jffs2/erase.c2
-rw-r--r--fs/jffs2/file.c2
-rw-r--r--fs/jffs2/gc.c2
-rw-r--r--fs/jffs2/read.c2
-rw-r--r--fs/jffs2/readinode.c2
-rw-r--r--fs/jffs2/scan.c2
-rw-r--r--fs/jffs2/write.c2
-rw-r--r--fs/namei.c5
-rw-r--r--fs/openpromfs/inode.c2
-rw-r--r--fs/partitions/msdos.c4
-rw-r--r--fs/reiserfs/bitmap.c2
-rw-r--r--fs/reiserfs/journal.c83
-rw-r--r--fs/reiserfs/tail_conversion.c1
-rw-r--r--include/asm-sparc/bitops.h2
-rw-r--r--include/asm-sparc/io.h5
-rw-r--r--include/asm-sparc/keyboard.h2
-rw-r--r--include/asm-sparc/mmu_context.h23
-rw-r--r--include/asm-sparc/oplib.h12
-rw-r--r--include/asm-sparc/pci.h1
-rw-r--r--include/asm-sparc/smp.h2
-rw-r--r--include/asm-sparc/smplock.h46
-rw-r--r--include/asm-sparc/string.h4
-rw-r--r--include/asm-sparc/types.h3
-rw-r--r--include/asm-sparc64/bitops.h12
-rw-r--r--include/asm-sparc64/elf.h21
-rw-r--r--include/asm-sparc64/io.h2
-rw-r--r--include/asm-sparc64/keyboard.h2
-rw-r--r--include/asm-sparc64/mmu_context.h23
-rw-r--r--include/asm-sparc64/oplib.h16
-rw-r--r--include/asm-sparc64/page.h13
-rw-r--r--include/asm-sparc64/processor.h30
-rw-r--r--include/asm-sparc64/rwsem.h14
-rw-r--r--include/asm-sparc64/semaphore.h8
-rw-r--r--include/asm-sparc64/smp.h17
-rw-r--r--include/asm-sparc64/smplock.h41
-rw-r--r--include/asm-sparc64/spinlock.h18
-rw-r--r--include/asm-sparc64/spitfire.h21
-rw-r--r--include/asm-sparc64/system.h27
-rw-r--r--include/asm-sparc64/ttable.h16
-rw-r--r--include/linux/blkdev.h4
-rw-r--r--include/linux/crc32.h17
-rw-r--r--include/linux/fs.h21
-rw-r--r--include/linux/if_arp.h1
-rw-r--r--include/linux/if_bonding.h9
-rw-r--r--include/linux/kbd_kern.h1
-rw-r--r--include/linux/limits.h2
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack.h30
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_tuple.h33
-rw-r--r--include/linux/reiserfs_fs.h5
-rw-r--r--include/linux/reiserfs_fs_sb.h2
-rw-r--r--include/linux/sched.h2
-rw-r--r--include/linux/shmem_fs.h2
-rw-r--r--include/linux/socket.h4
-rw-r--r--include/linux/sunrpc/clnt.h1
-rw-r--r--include/linux/swap.h6
-rw-r--r--include/math-emu/double.h6
-rw-r--r--include/math-emu/extended.h6
-rw-r--r--include/math-emu/op-1.h5
-rw-r--r--include/math-emu/op-2.h4
-rw-r--r--include/math-emu/op-4.h4
-rw-r--r--include/math-emu/op-8.h4
-rw-r--r--include/math-emu/op-common.h4
-rw-r--r--include/math-emu/quad.h5
-rw-r--r--include/math-emu/single.h5
-rw-r--r--include/math-emu/soft-fp.h6
-rw-r--r--kernel/ksyms.c2
-rw-r--r--kernel/sched.c31
-rw-r--r--lib/Config.in8
-rw-r--r--lib/Makefile7
-rw-r--r--lib/crc32.c571
-rw-r--r--mm/bootmem.c9
-rw-r--r--mm/highmem.c2
-rw-r--r--mm/page_io.c15
-rw-r--r--mm/swapfile.c98
-rw-r--r--net/8021q/vlan.c31
-rw-r--r--net/8021q/vlan_dev.c13
-rw-r--r--net/8021q/vlanproc.c4
-rw-r--r--net/Config.in2
-rw-r--r--net/README2
-rw-r--r--net/bridge/br.c6
-rw-r--r--net/bridge/br_device.c4
-rw-r--r--net/bridge/br_if.c7
-rw-r--r--net/bridge/br_input.c125
-rw-r--r--net/bridge/br_private.h3
-rw-r--r--net/ipv4/icmp.c6
-rw-r--r--net/ipv4/netfilter/ip_conntrack_irc.c8
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c2
-rw-r--r--net/ipv4/netfilter/ip_fw_compat.c10
-rw-r--r--net/ipv4/netfilter/ip_fw_compat_redir.c2
-rw-r--r--net/ipv4/netfilter/ip_nat_core.c12
-rw-r--r--net/ipv4/netfilter/ip_nat_helper.c17
-rw-r--r--net/ipv4/netfilter/ip_nat_irc.c6
-rw-r--r--net/ipv4/netfilter/ipt_MIRROR.c37
-rw-r--r--net/ipv4/netfilter/ipt_TCPMSS.c13
-rw-r--r--net/ipv4/netfilter/ipt_TOS.c11
-rw-r--r--net/ipv4/netfilter/ipt_unclean.c5
-rw-r--r--net/ipv6/tcp_ipv6.c3
-rw-r--r--net/sunrpc/sched.c1
-rw-r--r--net/sunrpc/xprt.c20
317 files changed, 6121 insertions, 3168 deletions
diff --git a/Documentation/Configure.help b/Documentation/Configure.help
index 9be21975f4fe9..9bc25ad78d4d6 100644
--- a/Documentation/Configure.help
+++ b/Documentation/Configure.help
@@ -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
index 0000000000000..b8de235987ebf
--- /dev/null
+++ b/Documentation/block/request.txt
@@ -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
diff --git a/Documentation/cciss.txt b/Documentation/cciss.txt
index d8c95d5791063..8548f913ee3e9 100644
--- a/Documentation/cciss.txt
+++ b/Documentation/cciss.txt
@@ -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
diff --git a/Documentation/filesystems/devfs/ChangeLog b/Documentation/filesystems/devfs/ChangeLog
index 407a684e9d16e..de386c4ea0b77 100644
--- a/Documentation/filesystems/devfs/ChangeLog
+++ b/Documentation/filesystems/devfs/ChangeLog
@@ -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>
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index 9d5454939b7c0..e0588af1fd402 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -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 $
diff --git a/Makefile b/Makefile
index fffcc6e582a74..5c2a8e1c65b8a 100644
--- 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
diff --git a/arch/alpha/config.in b/arch/alpha/config.in
index 91f072a80d708..14ca220f571a5 100644
--- a/arch/alpha/config.in
+++ b/arch/alpha/config.in
@@ -393,3 +393,5 @@ else
fi
endmenu
+
+source lib/Config.in
diff --git a/arch/arm/config.in b/arch/arm/config.in
index 02bcbfa8b0adc..f71bf71205f37 100644
--- a/arch/arm/config.in
+++ b/arch/arm/config.in
@@ -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
diff --git a/arch/cris/config.in b/arch/cris/config.in
index 5a9ee03de6fb2..66013359742ee 100644
--- a/arch/cris/config.in
+++ b/arch/cris/config.in
@@ -251,3 +251,5 @@ if [ "$CONFIG_PROFILE" = "y" ]; then
int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
fi
endmenu
+
+source lib/Config.in
diff --git a/arch/i386/config.in b/arch/i386/config.in
index 68a6cc9caa275..aa1284ad5dbdf 100644
--- a/arch/i386/config.in
+++ b/arch/i386/config.in
@@ -419,3 +419,5 @@ if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then
fi
endmenu
+
+source lib/Config.in
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index b954777752f89..11ce0b503ba9f 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -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
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index efd313e13fe9e..52b2a387bc0e7 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -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) {
diff --git a/arch/ia64/config.in b/arch/ia64/config.in
index fb0931f7b75cb..dff81a6f05b20 100644
--- a/arch/ia64/config.in
+++ b/arch/ia64/config.in
@@ -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
diff --git a/arch/m68k/config.in b/arch/m68k/config.in
index a65b213cd1341..44bc86f061827 100644
--- a/arch/m68k/config.in
+++ b/arch/m68k/config.in
@@ -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
diff --git a/arch/mips/config.in b/arch/mips/config.in
index 3136bd056906e..25b7fd9e492eb 100644
--- a/arch/mips/config.in
+++ b/arch/mips/config.in
@@ -520,3 +520,5 @@ if [ "$CONFIG_SMP" != "y" ]; then
bool 'Run uncached' CONFIG_MIPS_UNCACHED
fi
endmenu
+
+source lib/Config.in
diff --git a/arch/mips64/config.in b/arch/mips64/config.in
index 4ebb9f27a8ca5..5ddba84ff19a7 100644
--- a/arch/mips64/config.in
+++ b/arch/mips64/config.in
@@ -276,3 +276,5 @@ if [ "$CONFIG_SMP" != "y" ]; then
bool 'Run uncached' CONFIG_MIPS_UNCACHED
fi
endmenu
+
+source lib/Config.in
diff --git a/arch/parisc/config.in b/arch/parisc/config.in
index f68410f663f74..367242b77595d 100644
--- a/arch/parisc/config.in
+++ b/arch/parisc/config.in
@@ -208,3 +208,4 @@ comment 'Kernel hacking'
bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
endmenu
+source lib/Config.in
diff --git a/arch/ppc/config.in b/arch/ppc/config.in
index 3545adc66875d..7dfaf4d331e89 100644
--- a/arch/ppc/config.in
+++ b/arch/ppc/config.in
@@ -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
diff --git a/arch/s390/config.in b/arch/s390/config.in
index c545c36144202..f5932ba5c2033 100644
--- a/arch/s390/config.in
+++ b/arch/s390/config.in
@@ -73,3 +73,4 @@ fi
bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
endmenu
+source lib/Config.in
diff --git a/arch/s390x/config.in b/arch/s390x/config.in
index 5a9c5b6890807..1ab8e3c235a59 100644
--- a/arch/s390x/config.in
+++ b/arch/s390x/config.in
@@ -77,3 +77,4 @@ fi
bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
endmenu
+source lib/Config.in
diff --git a/arch/sh/config.in b/arch/sh/config.in
index 7b70ccccd7380..32fb2212b083f 100644
--- a/arch/sh/config.in
+++ b/arch/sh/config.in
@@ -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
diff --git a/arch/sparc/config.in b/arch/sparc/config.in
index 9f05197f9cf34..032e160829644 100644
--- a/arch/sparc/config.in
+++ b/arch/sparc/config.in
@@ -266,3 +266,5 @@ comment 'Kernel hacking'
bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
endmenu
+
+source lib/Config.in
diff --git a/arch/sparc/kernel/check_asm.sh b/arch/sparc/kernel/check_asm.sh
index 1c2aecb33be59..f9157e44dc9c8 100755
--- a/arch/sparc/kernel/check_asm.sh
+++ b/arch/sparc/kernel/check_asm.sh
@@ -1,12 +1,12 @@
#!/bin/sh
case $1 in
-printf)
- sed -n -e '/struct[ ]*'$2'_struct[ ]*{/,/};/p' < $3 | sed '/struct[ ]*'$2'_struct[ ]*{/d;/:[0-9]*[ ]*;/d;/^[ ]*$/d;/};/d;s/^[ ]*//;s/volatile[ ]*//;s/\(unsigned\|signed\|struct\)[ ]*//;s/\(\[\|__attribute__\).*;[ ]*$//;s/(\*//;s/)(.*)//;s/;[ ]*$//;s/^[^ ]*[ ]*//;s/,/\
+ sed -n -e '/^#/d;/struct[ ]*'$2'_struct[ ]*{/,/};/p' < $3 | sed '/struct[ ]*'$2'_struct[ ]*{/d;/:[0-9]*[ ]*;/d;/^[ ]*$/d;/};/d;s/^[ ]*//;s/volatile[ ]*//;s/\(unsigned\|signed\|struct\)[ ]*//;s/\(\[\|__attribute__\).*;[ ]*$//;s/(\*//;s/)(.*)//;s/;[ ]*$//;s/^[^ ]*[ ]*//;s/,/\
/g' | sed 's/^[ *]*//;s/[ ]*$//;s/^.*$/printf ("#define AOFF_'$2'_\0 0x%08x\\n", check_asm_data[i++]); printf("#define ASIZ_'$2'_\0 0x%08x\\n", check_asm_data[i++]);/' >> $4
echo "printf (\"#define ASIZ_$2\\t0x%08x\\n\", check_asm_data[i++]);" >> $4
;;
-data)
- sed -n -e '/struct[ ]*'$2'_struct[ ]*{/,/};/p' < $3 | sed '/struct[ ]*'$2'_struct[ ]*{/d;/:[0-9]*[ ]*;/d;/^[ ]*$/d;/};/d;s/^[ ]*//;s/volatile[ ]*//;s/\(unsigned\|signed\|struct\)[ ]*//;s/\(\[\|__attribute__\).*;[ ]*$//;s/(\*//;s/)(.*)//;s/;[ ]*$//;s/^[^ ]*[ ]*//;s/,/\
+ sed -n -e '/^#/d;/struct[ ]*'$2'_struct[ ]*{/,/};/p' < $3 | sed '/struct[ ]*'$2'_struct[ ]*{/d;/:[0-9]*[ ]*;/d;/^[ ]*$/d;/};/d;s/^[ ]*//;s/volatile[ ]*//;s/\(unsigned\|signed\|struct\)[ ]*//;s/\(\[\|__attribute__\).*;[ ]*$//;s/(\*//;s/)(.*)//;s/;[ ]*$//;s/^[^ ]*[ ]*//;s/,/\
/g' | sed 's/^[ *]*//;s/[ ]*$//;s/^.*$/ ((char *)\&((struct '$2'_struct *)0)->\0) - ((char *)((struct '$2'_struct *)0)), sizeof(((struct '$2'_struct *)0)->\0),/' >> $4
echo " sizeof(struct $2_struct)," >> $4
;;
diff --git a/arch/sparc/kernel/devices.c b/arch/sparc/kernel/devices.c
index f8a9ea63d9246..ecd4e6d150e70 100644
--- a/arch/sparc/kernel/devices.c
+++ b/arch/sparc/kernel/devices.c
@@ -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>
diff --git a/arch/sparc/kernel/ebus.c b/arch/sparc/kernel/ebus.c
index 609ab361f192c..ee31e2aaa5343 100644
--- a/arch/sparc/kernel/ebus.c
+++ b/arch/sparc/kernel/ebus.c
@@ -1,4 +1,4 @@
-/* $Id: ebus.c,v 1.18 2001/11/08 04:41:33 davem Exp $
+/* $Id: ebus.c,v 1.20 2002/01/05 01:13:43 davem Exp $
* ebus.c: PCI to EBus bridge device.
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
diff --git a/arch/sparc/kernel/init_task.c b/arch/sparc/kernel/init_task.c
index 5633c882f3278..d6d5e35e551ab 100644
--- a/arch/sparc/kernel/init_task.c
+++ b/arch/sparc/kernel/init_task.c
@@ -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) };
diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c
index 49e6f1a4c6db5..5e3a4008de43d 100644
--- a/arch/sparc/kernel/irq.c
+++ b/arch/sparc/kernel/irq.c
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.113 2001/07/17 16:17:33 anton Exp $
+/* $Id: irq.c,v 1.114 2001/12/11 04:55:51 davem Exp $
* arch/sparc/kernel/irq.c: Interrupt request handling routines. On the
* Sparc the IRQ's are basically 'cast in stone'
* and you are supposed to probe the prom's device
diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
index 0cadcd7908ef6..2e477bfbc8ecc 100644
--- a/arch/sparc/kernel/process.c
+++ b/arch/sparc/kernel/process.c
@@ -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..
diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c
index 957ddc17ca30f..51bfe75ede920 100644
--- a/arch/sparc/kernel/signal.c
+++ b/arch/sparc/kernel/signal.c
@@ -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>
diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c
index 2a47968bbfc4a..c53e219dfc9f1 100644
--- a/arch/sparc/kernel/sun4d_irq.c
+++ b/arch/sparc/kernel/sun4d_irq.c
@@ -1,4 +1,4 @@
-/* $Id: sun4d_irq.c,v 1.28 2001/07/17 16:17:33 anton Exp $
+/* $Id: sun4d_irq.c,v 1.29 2001/12/11 04:55:51 davem Exp $
* arch/sparc/kernel/sun4d_irq.c:
* SS1000/SC2000 interrupt handling.
*
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index e8f5fb37b01ef..a63ffb0670dd6 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -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++)
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index 676b9f2615912..4cd8f8bb53938 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -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... */
diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c
index 3180994194b84..8dd283c38e858 100644
--- a/arch/sparc/kernel/sys_sunos.c
+++ b/arch/sparc/kernel/sys_sunos.c
@@ -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;
diff --git a/arch/sparc/kernel/trampoline.S b/arch/sparc/kernel/trampoline.S
index b7b7025fc7197..d316096ea52e8 100644
--- a/arch/sparc/kernel/trampoline.S
+++ b/arch/sparc/kernel/trampoline.S
@@ -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
diff --git a/arch/sparc/kernel/unaligned.c b/arch/sparc/kernel/unaligned.c
index 0f718bac82a95..5f90082c1efac 100644
--- a/arch/sparc/kernel/unaligned.c
+++ b/arch/sparc/kernel/unaligned.c
@@ -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" \
diff --git a/arch/sparc/mm/extable.c b/arch/sparc/mm/extable.c
index 165c83ab5e114..5f63e466cdef8 100644
--- a/arch/sparc/mm/extable.c
+++ b/arch/sparc/mm/extable.c
@@ -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;
}
diff --git a/arch/sparc/mm/fault.c b/arch/sparc/mm/fault.c
index b422c571cfd07..8f1d7e79fa4f1 100644
--- a/arch/sparc/mm/fault.c
+++ b/arch/sparc/mm/fault.c
@@ -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;
}
diff --git a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c
index 34e289ed28438..c0baac1389411 100644
--- a/arch/sparc/mm/init.c
+++ b/arch/sparc/mm/init.c
@@ -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;
diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c
index be4522e1fadb6..16fcc375f50f8 100644
--- a/arch/sparc/mm/io-unit.c
+++ b/arch/sparc/mm/io-unit.c
@@ -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);
diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c
index 3bd631f36578b..cfd35dbdc4b59 100644
--- a/arch/sparc/mm/iommu.c
+++ b/arch/sparc/mm/iommu.c
@@ -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;
diff --git a/arch/sparc/prom/ranges.c b/arch/sparc/prom/ranges.c
index 244619eb64616..96e3a342be5da 100644
--- a/arch/sparc/prom/ranges.c
+++ b/arch/sparc/prom/ranges.c
@@ -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)
{
diff --git a/arch/sparc64/Makefile b/arch/sparc64/Makefile
index 64233d56fd5df..75ce131bbdd16 100644
--- a/arch/sparc64/Makefile
+++ b/arch/sparc64/Makefile
@@ -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
diff --git a/arch/sparc64/config.in b/arch/sparc64/config.in
index 1b91160e21aca..72294c14b4f50 100644
--- a/arch/sparc64/config.in
+++ b/arch/sparc64/config.in
@@ -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
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index 813126deeda9a..3ff8f9448112d 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -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
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
index f80dcd0c9ed71..b4b2515433bda 100644
--- a/arch/sparc64/kernel/Makefile
+++ b/arch/sparc64/kernel/Makefile
@@ -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 \
diff --git a/arch/sparc64/kernel/central.c b/arch/sparc64/kernel/central.c
index dba732a6d9e52..318efe3ccc277 100644
--- a/arch/sparc64/kernel/central.c
+++ b/arch/sparc64/kernel/central.c
@@ -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;
}
}
diff --git a/arch/sparc64/kernel/check_asm.sh b/arch/sparc64/kernel/check_asm.sh
index beaf6534807fd..65259c261dd62 100755
--- a/arch/sparc64/kernel/check_asm.sh
+++ b/arch/sparc64/kernel/check_asm.sh
@@ -1,12 +1,12 @@
#!/bin/sh
case $1 in
-printf)
- sed -n -e '/struct[ ]*'$2'_struct[ ]*{/,/};/p' < $3 | sed '/struct[ ]*'$2'_struct[ ]*{/d;/:[0-9]*[ ]*;/d;/^[ ]*$/d;/};/d;s/^[ ]*//;s/volatile[ ]*//;s/\(unsigned\|signed\|struct\)[ ]*//;s/\(\[\|__attribute__\).*;[ ]*$//;s/(\*//;s/)(.*)//;s/;[ ]*$//;s/^[^ ]*[ ]*//;s/,/\
+ sed -n -e '/^#/d;/struct[ ]*'$2'_struct[ ]*{/,/};/p' < $3 | sed '/struct[ ]*'$2'_struct[ ]*{/d;/:[0-9]*[ ]*;/d;/^[ ]*$/d;/};/d;s/^[ ]*//;s/volatile[ ]*//;s/\(unsigned\|signed\|struct\)[ ]*//;s/\(\[\|__attribute__\).*;[ ]*$//;s/(\*//;s/)(.*)//;s/;[ ]*$//;s/^[^ ]*[ ]*//;s/,/\
/g' | sed 's/^[ *]*//;s/[ ]*$//;s/^.*$/printf ("#define AOFF_'$2'_\0 0x%08x\\n", check_asm_data[i++]); printf("#define ASIZ_'$2'_\0 0x%08x\\n", check_asm_data[i++]);/' >> $4
echo "printf (\"#define ASIZ_$2\\t0x%08x\\n\", check_asm_data[i++]);" >> $4
;;
-data)
- sed -n -e '/struct[ ]*'$2'_struct[ ]*{/,/};/p' < $3 | sed '/struct[ ]*'$2'_struct[ ]*{/d;/:[0-9]*[ ]*;/d;/^[ ]*$/d;/};/d;s/^[ ]*//;s/volatile[ ]*//;s/\(unsigned\|signed\|struct\)[ ]*//;s/\(\[\|__attribute__\).*;[ ]*$//;s/(\*//;s/)(.*)//;s/;[ ]*$//;s/^[^ ]*[ ]*//;s/,/\
+ sed -n -e '/^#/d;/struct[ ]*'$2'_struct[ ]*{/,/};/p' < $3 | sed '/struct[ ]*'$2'_struct[ ]*{/d;/:[0-9]*[ ]*;/d;/^[ ]*$/d;/};/d;s/^[ ]*//;s/volatile[ ]*//;s/\(unsigned\|signed\|struct\)[ ]*//;s/\(\[\|__attribute__\).*;[ ]*$//;s/(\*//;s/)(.*)//;s/;[ ]*$//;s/^[^ ]*[ ]*//;s/,/\
/g' | sed 's/^[ *]*//;s/[ ]*$//;s/^.*$/ ((char *)\&((struct '$2'_struct *)0)->\0) - ((char *)((struct '$2'_struct *)0)), sizeof(((struct '$2'_struct *)0)->\0),/' >> $4
echo " sizeof(struct $2_struct)," >> $4
;;
diff --git a/arch/sparc64/kernel/chmc.c b/arch/sparc64/kernel/chmc.c
index 1cf4f31e50b5b..b75122e51cc94 100644
--- a/arch/sparc64/kernel/chmc.c
+++ b/arch/sparc64/kernel/chmc.c
@@ -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>
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
index acbb1b518be66..d0bbcf190f008 100644
--- a/arch/sparc64/kernel/entry.S
+++ b/arch/sparc64/kernel/entry.S
@@ -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
diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c
index 2a3ef1fb4d23a..c4bb21f4c6114 100644
--- a/arch/sparc64/kernel/ioctl32.c
+++ b/arch/sparc64/kernel/ioctl32.c
@@ -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 */
diff --git a/arch/sparc64/kernel/iommu_common.c b/arch/sparc64/kernel/iommu_common.c
index 134be5cd793cf..12c93a3eee265 100644
--- a/arch/sparc64/kernel/iommu_common.c
+++ b/arch/sparc64/kernel/iommu_common.c
@@ -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;
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index dedf08d2614c8..59b4f9c2a453a 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -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
diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c
index 38d253cbc35df..b2f341752db71 100644
--- a/arch/sparc64/kernel/pci_iommu.c
+++ b/arch/sparc64/kernel/pci_iommu.c
@@ -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;
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
index 7ea3a3036a30a..59ea29a97a415 100644
--- a/arch/sparc64/kernel/pci_psycho.c
+++ b/arch/sparc64/kernel/pci_psycho.c
@@ -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;
}
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
index b5a58611fc593..7f86b6f0189fb 100644
--- a/arch/sparc64/kernel/pci_sabre.c
+++ b/arch/sparc64/kernel/pci_sabre.c
@@ -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;
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c
index 3e35c92e30474..a660d05199aa8 100644
--- a/arch/sparc64/kernel/pci_schizo.c
+++ b/arch/sparc64/kernel/pci_schizo.c
@@ -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;
diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c
index 35f1cc2d34687..320fa2587d767 100644
--- a/arch/sparc64/kernel/power.c
+++ b/arch/sparc64/kernel/power.c
@@ -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 */
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index 797e5c78c9c6d..cedff9e3a975e 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -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));
diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S
index 20cd9a582fb3d..5625e6cc5f3a9 100644
--- a/arch/sparc64/kernel/rtrap.S
+++ b/arch/sparc64/kernel/rtrap.S
@@ -1,4 +1,4 @@
-/* $Id: rtrap.S,v 1.56 2001/10/13 00:14:34 kanoj Exp $
+/* $Id: rtrap.S,v 1.59 2002/01/11 08:45:38 davem Exp $
* rtrap.S: Preparing for return from trap on Sparc V9.
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -18,14 +18,13 @@
#define RTRAP_PSTATE_IRQOFF (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV)
#define RTRAP_PSTATE_AG_IRQOFF (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG)
-#if 0
-#define RTRAP_CHECK call rtrap_check; add %sp, (STACK_BIAS+REGWIN_SZ), %o0;
-#else
-#define RTRAP_CHECK
-#endif
+ /* Register %l6 keeps track of whether we are returning
+ * from a system call or not. It is cleared if we call
+ * do_signal, and it must not be otherwise modified until
+ * we fully commit to returning to userspace.
+ */
.text
-
.align 32
__handle_softirq:
call do_softirq
@@ -34,42 +33,100 @@ __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
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c
index 0e5a073ca69ae..4998dcfefb1ca 100644
--- a/arch/sparc64/kernel/sbus.c
+++ b/arch/sparc64/kernel/sbus.c
@@ -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;
diff --git a/arch/sparc64/kernel/semaphore.c b/arch/sparc64/kernel/semaphore.c
index 3e3b38ee4261c..e3c79264a5e18 100644
--- a/arch/sparc64/kernel/semaphore.c
+++ b/arch/sparc64/kernel/semaphore.c
@@ -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");
diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c
index 3540212785563..10785cb9c00fa 100644
--- a/arch/sparc64/kernel/signal.c
+++ b/arch/sparc64/kernel/signal.c
@@ -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>
diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c
index 956a80427b689..62db94b4f46bc 100644
--- a/arch/sparc64/kernel/signal32.c
+++ b/arch/sparc64/kernel/signal32.c
@@ -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>
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index a6f259cafad58..a4fd67dd5ad40 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -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;
}
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index 234e0af430ddd..8c9333d43fd7d 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -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
diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
index f174b54f39de8..353ddf6ad25b2 100644
--- a/arch/sparc64/kernel/sys_sparc.c
+++ b/arch/sparc64/kernel/sys_sparc.c
@@ -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 */
diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
index 39e2781f57d3b..47e5a445a2a0d 100644
--- a/arch/sparc64/kernel/sys_sunos32.c
+++ b/arch/sparc64/kernel/sys_sunos32.c
@@ -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)
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index b89235acfc2c7..3119c67b398ac 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -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));
}
diff --git a/arch/sparc64/kernel/trampoline.S b/arch/sparc64/kernel/trampoline.S
index fdf4a00f270a3..eda8ed5ab3b2a 100644
--- a/arch/sparc64/kernel/trampoline.S
+++ b/arch/sparc64/kernel/trampoline.S
@@ -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
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index 90063fb4135bf..f022447c8cdb1 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.79 2001/09/21 02:14:39 kanoj Exp $
+/* $Id: traps.c,v 1.83 2002/01/11 08:45:38 davem Exp $
* arch/sparc64/kernel/traps.c
*
* Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -38,16 +38,19 @@
void bad_trap (struct pt_regs *regs, long lvl)
{
+ char buffer[32];
siginfo_t info;
if (lvl < 0x100) {
- char buffer[24];
-
- sprintf (buffer, "Bad hw trap %lx at tl0\n", lvl);
+ sprintf(buffer, "Bad hw trap %lx at tl0\n", lvl);
+ die_if_kernel(buffer, regs);
+ }
+
+ lvl -= 0x100;
+ if (regs->tstate & TSTATE_PRIV) {
+ sprintf(buffer, "Kernel bad sw trap %lx", lvl);
die_if_kernel (buffer, regs);
}
- if (regs->tstate & TSTATE_PRIV)
- die_if_kernel ("Kernel bad trap", regs);
if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
regs->tpc &= 0xffffffff;
regs->tnpc &= 0xffffffff;
@@ -56,7 +59,7 @@ 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
}
diff --git a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S
index 182fb0f96dc69..9b2e54e269074 100644
--- a/arch/sparc64/kernel/ttable.S
+++ b/arch/sparc64/kernel/ttable.S
@@ -1,4 +1,4 @@
-/* $Id: ttable.S,v 1.35 2001/09/21 02:14:39 kanoj Exp $
+/* $Id: ttable.S,v 1.36 2001/11/28 23:32:16 davem Exp $
* ttable.S: Sparc V9 Trap Table(s) with SpitFire/Cheetah extensions.
*
* Copyright (C) 1996, 2001 David S. Miller (davem@caip.rutgers.edu)
@@ -15,11 +15,13 @@
sparc64_ttable_tl0:
tl0_resv000: BOOT_KERNEL BTRAP(0x1) BTRAP(0x2) BTRAP(0x3)
tl0_resv004: BTRAP(0x4) BTRAP(0x5) BTRAP(0x6) BTRAP(0x7)
-tl0_iax: TRAP_NOSAVE(__do_instruction_access_exception)
+tl0_iax: membar #Sync
+ TRAP_NOSAVE_7INSNS(__do_instruction_access_exception)
tl0_resv009: BTRAP(0x9)
tl0_iae: TRAP(do_iae)
tl0_resv00b: BTRAP(0xb) BTRAP(0xc) BTRAP(0xd) BTRAP(0xe) BTRAP(0xf)
-tl0_ill: TRAP(do_illegal_instruction)
+tl0_ill: membar #Sync
+ TRAP_7INSNS(do_illegal_instruction)
tl0_privop: TRAP(do_privop)
tl0_resv012: BTRAP(0x12) BTRAP(0x13) BTRAP(0x14) BTRAP(0x15) BTRAP(0x16) BTRAP(0x17)
tl0_resv018: BTRAP(0x18) BTRAP(0x19) BTRAP(0x1a) BTRAP(0x1b) BTRAP(0x1c) BTRAP(0x1d)
diff --git a/arch/sparc64/lib/atomic.S b/arch/sparc64/lib/atomic.S
index 35a34ebbf7dda..77be8b1f3e0ce 100644
--- a/arch/sparc64/lib/atomic.S
+++ b/arch/sparc64/lib/atomic.S
@@ -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:
diff --git a/arch/sparc64/lib/bitops.S b/arch/sparc64/lib/bitops.S
index fafe016c22d5d..fa8558237a7f2 100644
--- a/arch/sparc64/lib/bitops.S
+++ b/arch/sparc64/lib/bitops.S
@@ -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:
diff --git a/arch/sparc64/lib/blockops.S b/arch/sparc64/lib/blockops.S
index dedc03521902b..7042ae217cfc0 100644
--- a/arch/sparc64/lib/blockops.S
+++ b/arch/sparc64/lib/blockops.S
@@ -1,4 +1,4 @@
-/* $Id: blockops.S,v 1.36 2001/09/24 21:44:03 davem Exp $
+/* $Id: blockops.S,v 1.41 2001/12/05 06:05:35 davem Exp $
* blockops.S: UltraSparc block zero optimized routines.
*
* Copyright (C) 1996, 1998, 1999, 2000 David S. Miller (davem@redhat.com)
@@ -17,10 +17,9 @@
fmovd %reg4, %f56; fmovd %reg5, %f58; \
fmovd %reg6, %f60; fmovd %reg7, %f62;
-#define TLBTEMP_BASE (8 * 1024 * 1024)
#define DCACHE_SIZE (PAGE_SIZE * 2)
-#define TLBTEMP_ENT1 (61 << 3)
-#define TLBTEMP_ENT2 (62 << 3)
+#define TLBTEMP_ENT1 (60 << 3)
+#define TLBTEMP_ENT2 (61 << 3)
#define TLBTEMP_ENTSZ (1 << 3)
#if (PAGE_SHIFT == 13) || (PAGE_SHIFT == 19)
@@ -34,64 +33,6 @@
.text
.align 32
- .globl _copy_page
- .type _copy_page,@function
-_copy_page: /* %o0=dest, %o1=src */
- VISEntry
- membar #LoadStore | #StoreStore | #StoreLoad
- ldda [%o1] ASI_BLK_P, %f0
- add %o1, 0x40, %o1
- ldda [%o1] ASI_BLK_P, %f16
- add %o1, 0x40, %o1
- sethi %hi(PAGE_SIZE), %o2
-1: TOUCH(f0, f2, f4, f6, f8, f10, f12, f14)
- ldda [%o1] ASI_BLK_P, %f32
- stda %f48, [%o0] ASI_BLK_P
- add %o1, 0x40, %o1
- sub %o2, 0x40, %o2
- add %o0, 0x40, %o0
- TOUCH(f16, f18, f20, f22, f24, f26, f28, f30)
- ldda [%o1] ASI_BLK_P, %f0
- stda %f48, [%o0] ASI_BLK_P
- add %o1, 0x40, %o1
- sub %o2, 0x40, %o2
- add %o0, 0x40, %o0
- TOUCH(f32, f34, f36, f38, f40, f42, f44, f46)
- ldda [%o1] ASI_BLK_P, %f16
- stda %f48, [%o0] ASI_BLK_P
- sub %o2, 0x40, %o2
- add %o1, 0x40, %o1
- cmp %o2, PAGE_SIZE_REM
- bne,pt %xcc, 1b
- add %o0, 0x40, %o0
-#if (PAGE_SHIFT == 16) || (PAGE_SHIFT == 22)
- TOUCH(f0, f2, f4, f6, f8, f10, f12, f14)
- ldda [%o1] ASI_BLK_P, %f32
- stda %f48, [%o0] ASI_BLK_P
- add %o1, 0x40, %o1
- sub %o2, 0x40, %o2
- add %o0, 0x40, %o0
- TOUCH(f16, f18, f20, f22, f24, f26, f28, f30)
- ldda [%o1] ASI_BLK_P, %f0
- stda %f48, [%o0] ASI_BLK_P
- add %o1, 0x40, %o1
- sub %o2, 0x40, %o2
- add %o0, 0x40, %o0
- membar #Sync
- stda %f32, [%o0] ASI_BLK_P
- add %o0, 0x40, %o0
- stda %f0, [%o0] ASI_BLK_P
-#else
- membar #Sync
- stda %f0, [%o0] ASI_BLK_P
- add %o0, 0x40, %o0
- stda %f16, [%o0] ASI_BLK_P
-#endif
- membar #Sync
- VISExit
- retl
- nop
-
.globl copy_user_page
.type copy_user_page,@function
copy_user_page: /* %o0=dest, %o1=src, %o2=vaddr */
@@ -110,7 +51,7 @@ 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
diff --git a/arch/sparc64/lib/debuglocks.c b/arch/sparc64/lib/debuglocks.c
index b51811432239c..ea62c3ecc2f9f 100644
--- a/arch/sparc64/lib/debuglocks.c
+++ b/arch/sparc64/lib/debuglocks.c
@@ -1,4 +1,4 @@
-/* $Id: debuglocks.c,v 1.6 2001/04/24 01:09:12 davem Exp $
+/* $Id: debuglocks.c,v 1.9 2001/11/17 00:10:48 davem Exp $
* debuglocks.c: Debugging versions of SMP locking primitives.
*
* Copyright (C) 1998 David S. Miller (davem@redhat.com)
@@ -10,10 +10,7 @@
#include <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 */
diff --git a/arch/sparc64/lib/dec_and_lock.S b/arch/sparc64/lib/dec_and_lock.S
index 2a59b278821f8..b7c2631dd111c 100644
--- a/arch/sparc64/lib/dec_and_lock.S
+++ b/arch/sparc64/lib/dec_and_lock.S
@@ -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) */
diff --git a/arch/sparc64/mm/extable.c b/arch/sparc64/mm/extable.c
index dcd982b7bc462..595eff631ff01 100644
--- a/arch/sparc64/mm/extable.c
+++ b/arch/sparc64/mm/extable.c
@@ -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;
}
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index 2d363621a44be..151ff52bbd2c1 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -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 {
diff --git a/arch/sparc64/mm/ultra.S b/arch/sparc64/mm/ultra.S
index 8faa35963fb98..828749fac6ecc 100644
--- a/arch/sparc64/mm/ultra.S
+++ b/arch/sparc64/mm/ultra.S
@@ -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
diff --git a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c
index 98b1610a2327f..0ba71673d3066 100644
--- a/arch/sparc64/solaris/fs.c
+++ b/arch/sparc64/solaris/fs.c
@@ -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) ||
diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c
index 5a368d50fe8e4..339372977f5d0 100644
--- a/arch/sparc64/solaris/misc.c
+++ b/arch/sparc64/solaris/misc.c
@@ -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;
diff --git a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c
index 320f85c612d62..dd06c16183f8d 100644
--- a/arch/sparc64/solaris/socksys.c
+++ b/arch/sparc64/solaris/socksys.c
@@ -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;
diff --git a/arch/sparc64/solaris/timod.c b/arch/sparc64/solaris/timod.c
index 6728b593bb069..d2799895117b8 100644
--- a/arch/sparc64/solaris/timod.c
+++ b/arch/sparc64/solaris/timod.c
@@ -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);
diff --git a/drivers/block/Config.in b/drivers/block/Config.in
index 7902e3fc7b2d9..c78754672c412 100644
--- a/drivers/block/Config.in
+++ b/drivers/block/Config.in
@@ -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
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index e2792736f08e6..35543c2fa91ec 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -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);
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
index 1dafe1ec538ee..c6eb34da2c147 100644
--- a/drivers/block/cciss.h
+++ b/drivers/block/cciss.h
@@ -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 */
diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h
index 7faf6f05ca907..6ba126d3def5b 100644
--- a/drivers/block/cciss_cmd.h
+++ b/drivers/block/cciss_cmd.h
@@ -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
index 0000000000000..ad40c687d69ec
--- /dev/null
+++ b/drivers/block/cciss_scsi.c
@@ -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
index 0000000000000..1e580f10923d7
--- /dev/null
+++ b/drivers/block/cciss_scsi.h
@@ -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 */
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index 6a92fa4f5e28f..b67eeec19db3f 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -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
diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c
index 8fcdc77fad132..8b5536023cc5b 100644
--- a/drivers/block/elevator.c
+++ b/drivers/block/elevator.c
@@ -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)];
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index f98c41e49c017..142b4a8e83910 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -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);
@@ -964,12 +963,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);
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 49b2e7dc1d5b0..740e5c8b82bb3 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -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" );
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index f8964bf1e71f9..6f27a6120c2ce 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -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");
diff --git a/drivers/md/md.c b/drivers/md/md.c
index a02c0fccb7096..3fb9ad117ac0d 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -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);
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 94d3cbb7c79b0..792e787fc7abf 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -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;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 6773bf201e7d6..385f26395039b 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -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);
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index 9387ad20f8e7f..bd57c42e61a0c 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -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;
diff --git a/drivers/net/7990.c b/drivers/net/7990.c
index 765d9bd6b40d7..7c99d9e3a4dd4 100644
--- a/drivers/net/7990.c
+++ b/drivers/net/7990.c
@@ -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);
}
diff --git a/drivers/net/7990.h b/drivers/net/7990.h
index 0fb2a48fa8372..6875780ae87ea 100644
--- a/drivers/net/7990.h
+++ b/drivers/net/7990.h
@@ -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
*/
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index ff5f5792fb03a..e9f2252cf72c1 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -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;
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index 2d219b46649af..c96bce2accdcd 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -109,6 +109,7 @@
#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;
diff --git a/drivers/net/8390.c b/drivers/net/8390.c
index 67064058e2181..06e0746a90610 100644
--- a/drivers/net/8390.c
+++ b/drivers/net/8390.c
@@ -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>
@@ -885,27 +886,6 @@ static struct net_device_stats *get_stats(struct net_device *dev)
}
/*
- * 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
index 0000000000000..af22a0e02a3a7
--- /dev/null
+++ b/drivers/net/Makefile.lib
@@ -0,0 +1,69 @@
+# These drivers all require crc32.o
+obj-$(CONFIG_8139CP) += crc32.o
+obj-$(CONFIG_8139TOO) += crc32.o
+obj-$(CONFIG_A2065) += crc32.o
+obj-$(CONFIG_ARM_AM79C961A) += crc32.o
+obj-$(CONFIG_AT1700) += crc32.o
+obj-$(CONFIG_ATP) += crc32.o
+obj-$(CONFIG_DE2104X) += crc32.o
+obj-$(CONFIG_DE4X5) += crc32.o
+obj-$(CONFIG_DECLANCE) += crc32.o
+obj-$(CONFIG_DEPCA) += crc32.o
+obj-$(CONFIG_DL2K) += crc32.o
+obj-$(CONFIG_DM9102) += crc32.o
+obj-$(CONFIG_EPIC100) += crc32.o
+obj-$(CONFIG_EWRK3) += crc32.o
+obj-$(CONFIG_FEALNX) += crc32.o
+obj-$(CONFIG_HAPPYMEAL) += crc32.o
+obj-$(CONFIG_MACE) += crc32.o
+obj-$(CONFIG_MACMACE) += crc32.o
+obj-$(CONFIG_MIPS_AU1000_ENET) += crc32.o
+obj-$(CONFIG_NATSEMI) += crc32.o
+obj-$(CONFIG_PCMCIA_FMVJ18X) += crc32.o
+obj-$(CONFIG_PCMCIA_SMC91C92) += crc32.o
+obj-$(CONFIG_PCMCIA_XIRTULIP) += crc32.o
+obj-$(CONFIG_PCNET32) += crc32.o
+obj-$(CONFIG_SIS900) += crc32.o
+obj-$(CONFIG_SMC9194) += crc32.o
+obj-$(CONFIG_STARFIRE) += crc32.o
+obj-$(CONFIG_SUNBMAC) += crc32.o
+obj-$(CONFIG_SUNDANCE) += crc32.o
+obj-$(CONFIG_SUNGEM) += crc32.o
+obj-$(CONFIG_SUNGEM) += crc32.o
+obj-$(CONFIG_SUNLANCE) += crc32.o
+obj-$(CONFIG_SUNQE) += crc32.o
+obj-$(CONFIG_TULIP) += crc32.o
+obj-$(CONFIG_VIA_RHINE) += crc32.o
+obj-$(CONFIG_YELLOWFIN) += crc32.o
+obj-$(CONFIG_WINBOND_840) += crc32.o
+
+
+# These rely on drivers/net/7990.o which requires crc32.o
+obj-$(CONFIG_HPLANCE) += crc32.o
+obj-$(CONFIG_MVME147_NET) += crc32.o
+
+
+# These rely on drivers/net/8390.o which requires crc32.o
+obj-$(CONFIG_OAKNET) += crc32.o
+obj-$(CONFIG_NE2K_PCI) += crc32.o
+obj-$(CONFIG_STNIC) += crc32.o
+obj-$(CONFIG_MAC8390) += crc32.o
+obj-$(CONFIG_APNE) += crc32.o
+obj-$(CONFIG_PCMCIA_PCNET) += crc32.o
+obj-$(CONFIG_ARM_ETHERH) += crc32.o
+obj-$(CONFIG_WD80x3) += crc32.o
+obj-$(CONFIG_EL2) += crc32.o
+obj-$(CONFIG_NE2000) += crc32.o
+obj-$(CONFIG_NE2_MCA) += crc32.o
+obj-$(CONFIG_HPLAN) += crc32.o
+obj-$(CONFIG_HPLAN_PLUS) += crc32.o
+obj-$(CONFIG_ULTRA) += crc32.o
+obj-$(CONFIG_ULTRAMCA) += crc32.o
+obj-$(CONFIG_ULTRA32) += crc32.o
+obj-$(CONFIG_E2100) += crc32.o
+obj-$(CONFIG_ES3210) += crc32.o
+obj-$(CONFIG_LNE390) += crc32.o
+obj-$(CONFIG_NE3210) += crc32.o
+obj-$(CONFIG_AC3200) += crc32.o
+obj-$(CONFIG_ARIADNE2) += crc32.o
+obj-$(CONFIG_HYDRA) += crc32.o
diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c
index e00dee5c48cce..63ed2cbd6b1f9 100644
--- a/drivers/net/a2065.c
+++ b/drivers/net/a2065.c
@@ -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);
}
diff --git a/drivers/net/a2065.h b/drivers/net/a2065.h
index f6e4d255f4f74..184ad573dbda3 100644
--- a/drivers/net/a2065.h
+++ b/drivers/net/a2065.h
@@ -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
*/
diff --git a/drivers/net/am79c961a.c b/drivers/net/am79c961a.c
index 30840e5d530f9..b7bb8f4ca95a9 100644
--- a/drivers/net/am79c961a.c
+++ b/drivers/net/am79c961a.c
@@ -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;
diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c
index 5a9ad62ad6f22..badecbc401e16 100644
--- a/drivers/net/at1700.c
+++ b/drivers/net/at1700.c
@@ -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)
{
diff --git a/drivers/net/atp.c b/drivers/net/atp.c
index 62d7ceaeaad04..5a31cfe28fd93 100644
--- a/drivers/net/atp.c
+++ b/drivers/net/atp.c
@@ -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;
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index 168b9dd1543f8..a9a4ac16240c2 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -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;
diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c
index cf0d30df691bf..e94ccb93c3415 100644
--- a/drivers/net/bmac.c
+++ b/drivers/net/bmac.c
@@ -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);
}
diff --git a/drivers/net/bonding.c b/drivers/net/bonding.c
index 63e0c1e1fb86a..e9736dc3ce891 100644
--- a/drivers/net/bonding.c
+++ b/drivers/net/bonding.c
@@ -153,6 +153,14 @@
*
* 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>
@@ -185,7 +193,6 @@
#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;
diff --git a/drivers/net/de2104x.c b/drivers/net/de2104x.c
index 45ceb740c5677..2d8145dc3eca6 100644
--- a/drivers/net/de2104x.c
+++ b/drivers/net/de2104x.c
@@ -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)
diff --git a/drivers/net/de4x5.c b/drivers/net/de4x5.c
index 2b5cff2b930c3..3af726812573e 100644
--- a/drivers/net/de4x5.c
+++ b/drivers/net/de4x5.c
@@ -436,6 +436,7 @@
'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 */
diff --git a/drivers/net/declance.c b/drivers/net/declance.c
index 173e42b4af39b..f5c828869753d 100644
--- a/drivers/net/declance.c
+++ b/drivers/net/declance.c
@@ -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);
}
diff --git a/drivers/net/depca.c b/drivers/net/depca.c
index e6f061bedbc69..9095f2fc6bc6c 100644
--- a/drivers/net/depca.c
+++ b/drivers/net/depca.c
@@ -228,6 +228,8 @@
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
=========================================================================
*/
@@ -245,6 +247,7 @@
#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);
diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c
index 16107578479d0..1c232734fc51f 100644
--- a/drivers/net/dl2k.c
+++ b/drivers/net/dl2k.c
@@ -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);
diff --git a/drivers/net/dl2k.h b/drivers/net/dl2k.h
index fb1a8cd259167..49ed98d4d8783 100644
--- a/drivers/net/dl2k.h
+++ b/drivers/net/dl2k.h
@@ -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>
diff --git a/drivers/net/dmfe.c b/drivers/net/dmfe.c
index c94409b258b2f..4cca074aa5402 100644
--- a/drivers/net/dmfe.c
+++ b/drivers/net/dmfe.c
@@ -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;
}
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index 468c675b4ba05..7c30e77503fe2 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -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;
diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c
index 4b9319011880f..dadc8c8d331e0 100644
--- a/drivers/net/ewrk3.c
+++ b/drivers/net/ewrk3.c
@@ -132,6 +132,7 @@
<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>
=========================================================================
*/
@@ -148,6 +149,7 @@
#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 */
diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c
index e63a3c54291ae..e35d85f477be5 100644
--- a/drivers/net/fealnx.c
+++ b/drivers/net/fealnx.c
@@ -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;
diff --git a/drivers/net/gmac.c b/drivers/net/gmac.c
index 8d3e0b2d45412..1406a5edb968b 100644
--- a/drivers/net/gmac.c
+++ b/drivers/net/gmac.c
@@ -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;
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index dc1667b240cef..1a3e62efe6568 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -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; ) {
diff --git a/drivers/net/mace.c b/drivers/net/mace.c
index 04ca3c75ad16a..7704924740d25 100644
--- a/drivers/net/mace.c
+++ b/drivers/net/mace.c
@@ -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;
diff --git a/drivers/net/macmace.c b/drivers/net/macmace.c
index 099b1fc938e3f..9f792a43f0d79 100644
--- a/drivers/net/macmace.c
+++ b/drivers/net/macmace.c
@@ -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;
diff --git a/drivers/net/myri_code.h b/drivers/net/myri_code.h
index 18e2642afea86..851eba8a3e00e 100644
--- a/drivers/net/myri_code.h
+++ b/drivers/net/myri_code.h
@@ -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 */
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
index 4ea8280d6d009..09b2d0450cefe 100644
--- a/drivers/net/myri_sbus.c
+++ b/drivers/net/myri_sbus.c
@@ -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
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index 7d01a2c6e9861..a94d694536b62 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -102,6 +102,9 @@
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
@@ -110,7 +113,7 @@
#define DRV_NAME "natsemi"
#define DRV_VERSION "1.07+LK1.0.13"
-#define DRV_RELDATE "Oct 19, 2001"
+#define DRV_RELDATE "Nov 12, 2001"
/* Updated to recommendations in pci-skeleton v2.03. */
@@ -1706,36 +1709,15 @@ 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
diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c
index e94d6c3cb3a2c..6743227a34780 100644
--- a/drivers/net/pci-skeleton.c
+++ b/drivers/net/pci-skeleton.c
@@ -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;
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index 3816934946cea..6c47c37a0a0b2 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -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;
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index f1c322bb2dbd4..44c218c3fff73 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -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;
-}
/*======================================================================
diff --git a/drivers/net/pcmcia/xircom_tulip_cb.c b/drivers/net/pcmcia/xircom_tulip_cb.c
index e7fe6ae79e548..578af8d57f9c4 100644
--- a/drivers/net/pcmcia/xircom_tulip_cb.c
+++ b/drivers/net/pcmcia/xircom_tulip_cb.c
@@ -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
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index 4ad12acf7d4a0..25b86ec895387 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -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);
}
diff --git a/drivers/net/shaper.c b/drivers/net/shaper.c
index 9e1e2e30a26ce..3ff3c5fbec561 100644
--- a/drivers/net/shaper.c
+++ b/drivers/net/shaper.c
@@ -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;
}
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index e6140c6cf27cc..6724c7406fe1c 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -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
@@ -62,11 +63,12 @@
#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))
diff --git a/drivers/net/sk98lin/h/skdrv1st.h b/drivers/net/sk98lin/h/skdrv1st.h
index 7a7c953b7b162..4f8e30868e9f4 100644
--- a/drivers/net/sk98lin/h/skdrv1st.h
+++ b/drivers/net/sk98lin/h/skdrv1st.h
@@ -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>
diff --git a/drivers/net/sk98lin/skaddr.c b/drivers/net/sk98lin/skaddr.c
index b7381fe679e27..ca223be377d6b 100644
--- a/drivers/net/sk98lin/skaddr.c
+++ b/drivers/net/sk98lin/skaddr.c
@@ -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 */
diff --git a/drivers/net/smc9194.c b/drivers/net/smc9194.c
index c40f7dc8b0410..07337b7b912f6 100644
--- a/drivers/net/smc9194.c
+++ b/drivers/net/smc9194.c
@@ -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]] |=
@@ -452,33 +450,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:
. Attempt to allocate memory for a packet, if chip-memory is not
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 0fec2bcce2c3e..3d17fd6c2ff61 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -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)
{
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
index 0170283fb8540..1555eac7f1df5 100644
--- a/drivers/net/sunbmac.c
+++ b/drivers/net/sunbmac.c
@@ -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);
}
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index ab376ffedd707..c55a85e826117 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -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;
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 88ca3775ef9ec..bf06abcb22367 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -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>
@@ -23,11 +31,16 @@
#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>
@@ -45,15 +58,33 @@
#include "sungem.h"
+#define DRV_NAME "sungem"
+#define DRV_VERSION "0.96"
+#define DRV_RELDATE "11/17/01"
+#define DRV_AUTHOR "David S. Miller (davem@redhat.com)"
+
static char version[] __devinitdata =
- "sungem.c:v0.95 16/Oct/01 David S. Miller (davem@redhat.com)\n";
+ DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n";
-MODULE_AUTHOR("David S. Miller (davem@redhat.com)");
+MODULE_AUTHOR(DRV_AUTHOR);
MODULE_DESCRIPTION("Sun GEM Gbit ethernet driver");
MODULE_LICENSE("GPL");
MODULE_PARM(gem_debug, "i");
MODULE_PARM_DESC(gem_debug, "(ignored)");
+MODULE_PARM(link_mode, "i");
+
+static int link_mode;
+
+static u16 link_modes[] __devinitdata = {
+ BMCR_ANENABLE, /* 0 : autoneg */
+ 0, /* 1 : 10bt half duplex */
+ BMCR_SPEED100, /* 2 : 100bt half duplex */
+ BMCR_SPD2, /* verify this */ /* 3 : 1000bt half duplex */
+ BMCR_FULLDPLX, /* 4 : 10bt full duplex */
+ BMCR_SPEED100|BMCR_FULLDPLX, /* 5 : 100bt full duplex */
+ BMCR_SPD2|BMCR_FULLDPLX /* 6 : 1000bt full duplex */
+};
#define GEM_MODULE_NAME "gem"
#define PFX GEM_MODULE_NAME ": "
@@ -73,7 +104,7 @@ 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)
diff --git a/drivers/net/sungem.h b/drivers/net/sungem.h
index a4a63f21d4364..ec136a81885f5 100644
--- a/drivers/net/sungem.h
+++ b/drivers/net/sungem.h
@@ -1,4 +1,4 @@
-/* $Id: sungem.h,v 1.8 2001/10/17 05:55:39 davem Exp $
+/* $Id: sungem.h,v 1.10 2001/11/29 03:57:33 davem Exp $
* sungem.h: Definitions for Sun GEM ethernet driver.
*
* Copyright (C) 2000 David S. Miller (davem@redhat.com)
@@ -753,64 +753,38 @@
#define PROM_SIZE 0x0fffffUL /* Size of ROM */
#define PROM_END 0x200000UL /* End of ROM */
-/* MII phy registers */
-#define PHY_CTRL 0x00
-#define PHY_STAT 0x01
-#define PHY_ID0 0x02
-#define PHY_ID1 0x03
-#define PHY_ADV 0x04
-#define PHY_LPA 0x05
-
-#define PHY_CTRL_SPD2 0x0040 /* Gigabit enable? (bcm5411) */
-#define PHY_CTRL_FDPLX 0x0100 /* Full duplex */
-#define PHY_CTRL_ISO 0x0400 /* Isloate MII from PHY */
-#define PHY_CTRL_ANRES 0x0200 /* Auto-negotiation restart */
-#define PHY_CTRL_ANENAB 0x1000 /* Auto-negotiation enable */
-#define PHY_CTRL_SPD100 0x2000 /* Select 100Mbps */
-#define PHY_CTRL_RST 0x8000 /* Reset PHY */
-
-#define PHY_STAT_LSTAT 0x0004 /* Link status */
-#define PHY_STAT_ANEGC 0x0020 /* Auto-negotiation complete */
-
-#define PHY_ADV_10HALF 0x0020
-#define PHY_ADV_10FULL 0x0040
-#define PHY_ADV_100HALF 0x0080
-#define PHY_ADV_100FULL 0x0100
-
-#define PHY_LPA_10HALF 0x0020
-#define PHY_LPA_10FULL 0x0040
-#define PHY_LPA_100HALF 0x0080
-#define PHY_LPA_100FULL 0x0100
-#define PHY_LPA_PAUSE 0x0400
-#define PHY_LPA_FAULT 0x2000
+/* MII definitions missing from mii.h */
+
+#define BMCR_SPD2 0x0040 /* Gigabit enable? (bcm5411) */
+#define LPA_PAUSE 0x0400
/* More PHY registers (specific to Broadcom models) */
/* MII BCM5201 MULTIPHY interrupt register */
-#define PHY_BCM5201_INTERRUPT 0x1A
-#define PHY_BCM5201_INTERRUPT_INTENABLE 0x4000
+#define MII_BCM5201_INTERRUPT 0x1A
+#define MII_BCM5201_INTERRUPT_INTENABLE 0x4000
-#define PHY_BCM5201_AUXMODE2 0x1B
-#define PHY_BCM5201_AUXMODE2_LOWPOWER 0x0008
+#define MII_BCM5201_AUXMODE2 0x1B
+#define MII_BCM5201_AUXMODE2_LOWPOWER 0x0008
-#define PHY_BCM5201_MULTIPHY 0x1E
+#define MII_BCM5201_MULTIPHY 0x1E
/* MII BCM5201 MULTIPHY register bits */
-#define PHY_BCM5201_MULTIPHY_SERIALMODE 0x0002
-#define PHY_BCM5201_MULTIPHY_SUPERISOLATE 0x0008
+#define MII_BCM5201_MULTIPHY_SERIALMODE 0x0002
+#define MII_BCM5201_MULTIPHY_SUPERISOLATE 0x0008
/* MII BCM5400 1000-BASET Control register */
-#define PHY_BCM5400_GB_CONTROL 0x09
-#define PHY_BCM5400_GB_CONTROL_FULLDUPLEXCAP 0x0200
+#define MII_BCM5400_GB_CONTROL 0x09
+#define MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP 0x0200
/* MII BCM5400 AUXCONTROL register */
-#define PHY_BCM5400_AUXCONTROL 0x18
-#define PHY_BCM5400_AUXCONTROL_PWR10BASET 0x0004
+#define MII_BCM5400_AUXCONTROL 0x18
+#define MII_BCM5400_AUXCONTROL_PWR10BASET 0x0004
/* MII BCM5400 AUXSTATUS register */
-#define PHY_BCM5400_AUXSTATUS 0x19
-#define PHY_BCM5400_AUXSTATUS_LINKMODE_MASK 0x0700
-#define PHY_BCM5400_AUXSTATUS_LINKMODE_SHIFT 8
+#define MII_BCM5400_AUXSTATUS 0x19
+#define MII_BCM5400_AUXSTATUS_LINKMODE_MASK 0x0700
+#define MII_BCM5400_AUXSTATUS_LINKMODE_SHIFT 8
/* When it can, GEM internally caches 4 aligned TX descriptors
* at a time, so that it can use full cacheline DMA reads.
@@ -936,9 +910,21 @@ 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;
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index 2affbd1e28800..25778dc8676af 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -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);
}
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index 2f9cc0dac31b6..c42003b125e43 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/sunlance.c
@@ -62,12 +62,15 @@
* Anton Blanchard (anton@progsoc.uts.edu.au)
* 2.00: 11/9/99: Massive overhaul and port to new SBUS driver interfaces.
* David S. Miller (davem@redhat.com)
+ * 2.01:
+ * 11/08/01: Use library crc32 functions (Matt_Domsch@dell.com)
+ *
*/
#undef DEBUG_DRIVER
static char version[] =
- "sunlance.c:v2.00 11/Sep/99 Miguel de Icaza (miguel@nuclecu.unam.mx)\n";
+ "sunlance.c:v2.01 08/Nov/01 Miguel de Icaza (miguel@nuclecu.unam.mx)\n";
static char lancestr[] = "LANCE";
@@ -86,6 +89,7 @@ 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]);
diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c
index 30f06d1efc5c2..7ddedceacfc2d 100644
--- a/drivers/net/sunqe.c
+++ b/drivers/net/sunqe.c
@@ -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);
}
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index 917f1a9be8cf8..b396f5ba85f36 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -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)
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index 2e753ad174a46..0aed62e907c4b 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -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;
diff --git a/drivers/net/winbond-840.c b/drivers/net/winbond-840.c
index f81fc206f9857..92e18806848ec 100644
--- a/drivers/net/winbond-840.c
+++ b/drivers/net/winbond-840.c
@@ -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)
{
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index e169ad56faf88..e56ab051dda87 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -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;
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index f1deb2a35e805..bb14996daf661 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -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 )
diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c
index d6715d169e9d5..064a5cc008098 100644
--- a/drivers/s390/block/xpram.c
+++ b/drivers/s390/block/xpram.c
@@ -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 */
diff --git a/drivers/s390/char/tapedefs.h b/drivers/s390/char/tapedefs.h
index fa714c2c46eff..8506921d5a542 100644
--- a/drivers/s390/char/tapedefs.h
+++ b/drivers/s390/char/tapedefs.h
@@ -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 )
diff --git a/drivers/sbus/audio/audio.c b/drivers/sbus/audio/audio.c
index cbf93b31b2de4..1ee7f179d2e0d 100644
--- a/drivers/sbus/audio/audio.c
+++ b/drivers/sbus/audio/audio.c
@@ -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();
diff --git a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c
index 38b53ee9f16e4..86b08d5cb8272 100644
--- a/drivers/sbus/char/aurora.c
+++ b/drivers/sbus/char/aurora.c
@@ -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");
diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c
index f5ed491fb464b..fdc9936319f08 100644
--- a/drivers/sbus/char/cpwatchdog.c
+++ b/drivers/sbus/char/cpwatchdog.c
@@ -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];
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
index ea2430ec0ad24..cebf4df348d1d 100644
--- a/drivers/sbus/char/display7seg.c
+++ b/drivers/sbus/char/display7seg.c
@@ -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) {
diff --git a/drivers/sbus/char/sab82532.c b/drivers/sbus/char/sab82532.c
index fec4c3ee224cb..99fe2b473c4a8 100644
--- a/drivers/sbus/char/sab82532.c
+++ b/drivers/sbus/char/sab82532.c
@@ -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
diff --git a/drivers/sbus/char/su.c b/drivers/sbus/char/su.c
index ac0a1c40016a8..acdabc85fc9cf 100644
--- a/drivers/sbus/char/su.c
+++ b/drivers/sbus/char/su.c
@@ -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);
}
/*
diff --git a/drivers/sbus/char/sunserial.c b/drivers/sbus/char/sunserial.c
index 5ac8a930486cc..6ee3b0051b89d 100644
--- a/drivers/sbus/char/sunserial.c
+++ b/drivers/sbus/char/sunserial.c
@@ -1,4 +1,4 @@
-/* $Id: sunserial.c,v 1.79 2001/04/18 21:06:17 davem Exp $
+/* $Id: sunserial.c,v 1.81 2002/01/05 01:13:43 davem Exp $
* serial.c: Serial port driver infrastructure for the Sparc.
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
diff --git a/drivers/sbus/char/zs.c b/drivers/sbus/char/zs.c
index e9562c2ecc8cb..a31e9630ea01b 100644
--- a/drivers/sbus/char/zs.c
+++ b/drivers/sbus/char/zs.c
@@ -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)
diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c
index 96bba6454933c..c64a0901bc334 100644
--- a/drivers/sbus/sbus.c
+++ b/drivers/sbus/sbus.c
@@ -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;
}
}
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 85a91217a57de..9835bfccf1df9 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -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);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_linux.c b/drivers/scsi/aic7xxx/aic7xxx_linux.c
index 6242554a93fa1..e656d4d081a2e 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_linux.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_linux.c
@@ -130,6 +130,7 @@
#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
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
index a6036ddd92bb6..f0082058d61d9 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h
@@ -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) */
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
index 23113ae7c4a7a..ebbd33c54f0d8 100644
--- a/drivers/scsi/constants.c
+++ b/drivers/scsi/constants.c
@@ -5,7 +5,6 @@
*
*/
-#define __NO_VERSION__
#include <linux/module.h>
#include <linux/config.h>
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index aa0fd64cb32e8..e276376771aee 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -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)
diff --git a/drivers/scsi/hosts.h b/drivers/scsi/hosts.h
index 3246ba64f15d3..8604eb35140a6 100644
--- a/drivers/scsi/hosts.h
+++ b/drivers/scsi/hosts.h
@@ -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)
{
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 3bb3bef50f06b..1c47f9cc04164 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -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);
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index b3257fc4652b4..554dc6b446c4c 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -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 */
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index b6894649e12f6..57596d9eb1cca 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -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"));
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index f64d200909232..b99553c5e51be 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -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>
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 4e8745f235602..b23f616592db8 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -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.
diff --git a/drivers/scsi/scsi_merge.c b/drivers/scsi/scsi_merge.c
index 3368906c2884e..807ecbc58dca5 100644
--- a/drivers/scsi/scsi_merge.c
+++ b/drivers/scsi/scsi_merge.c
@@ -15,7 +15,6 @@
* be handled all at once by a host adapter.
*/
-#define __NO_VERSION__
#include <linux/config.h>
#include <linux/module.h>
diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c
index 01d6679250a95..2f7e4adcc3606 100644
--- a/drivers/scsi/scsi_proc.c
+++ b/drivers/scsi/scsi_proc.c
@@ -17,7 +17,6 @@
*/
#include <linux/config.h> /* for CONFIG_PROC_FS */
-#define __NO_VERSION__
#include <linux/module.h>
#include <linux/string.h>
diff --git a/drivers/scsi/scsi_queue.c b/drivers/scsi/scsi_queue.c
index 1d9a90bbdd56c..40d2ad5a28a42 100644
--- a/drivers/scsi/scsi_queue.c
+++ b/drivers/scsi/scsi_queue.c
@@ -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.
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index aede1a6a94202..8f4d70c1e6a26 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -8,7 +8,6 @@
* clearer.
*/
-#define __NO_VERSION__
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
diff --git a/drivers/scsi/scsi_syms.c b/drivers/scsi/scsi_syms.c
index 8f511d1a5105f..e363fac3d9873 100644
--- a/drivers/scsi/scsi_syms.c
+++ b/drivers/scsi/scsi_syms.c
@@ -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>
diff --git a/drivers/scsi/scsicam.c b/drivers/scsi/scsicam.c
index e8f8c90bf7937..3582d44e09d47 100644
--- a/drivers/scsi/scsicam.c
+++ b/drivers/scsi/scsicam.c
@@ -10,7 +10,6 @@
* For more information, please consult the SCSI-CAM draft.
*/
-#define __NO_VERSION__
#include <linux/module.h>
#include <linux/fs.h>
diff --git a/drivers/scsi/sym53c8xx.c b/drivers/scsi/sym53c8xx.c
index bc030dcb4fcc7..f22d1414d5634 100644
--- a/drivers/scsi/sym53c8xx.c
+++ b/drivers/scsi/sym53c8xx.c
@@ -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
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index d8c43a9d5abb7..10e68e096edc8 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -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
diff --git a/drivers/sound/trident.c b/drivers/sound/trident.c
index aabd8adc656c2..19169b4327799 100644
--- a/drivers/sound/trident.c
+++ b/drivers/sound/trident.c
@@ -187,6 +187,7 @@
#define TRIDENT_STATE_MAGIC 0x63657373 /* "cess" */
#define TRIDENT_DMA_MASK 0x3fffffff /* DMA buffer mask for pci_alloc_consist */
+#define ALI_DMA_MASK 0xffffffff /* ALI Tridents lack the 30-bit limitation */
#define NR_HW_CH 32
@@ -2555,7 +2556,7 @@ static int trident_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);
diff --git a/drivers/sound/ymfpci.c b/drivers/sound/ymfpci.c
index 25cf21c102ee3..d426b7dff7874 100644
--- a/drivers/sound/ymfpci.c
+++ b/drivers/sound/ymfpci.c
@@ -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.
*
@@ -37,8 +39,16 @@
* - Remove prog_dmabuf from read/write, leave it in open.
* - 2001/01/07 Replace the OPL3 part of CONFIG_SOUND_YMFPCI_LEGACY code with
* native synthesizer through a playback slot.
- * - Use new 2.3.x cache coherent PCI DMA routines instead of virt_to_bus.
- * - Make the thing big endian compatible. ALSA has it done.
+ * - 2001/11/29 ac97_save_state
+ * Talk to Kai to remove ac97_save_state before it's too late!
+ * - Second AC97
+ * - Restore S/PDIF - Toshibas have it.
+ *
+ * Kai used pci_alloc_consistent for DMA buffer, which sounds a little
+ * unconventional. However, given how small our fragments can be,
+ * a little uncached access is perhaps better than endless flushing.
+ * On i386 and other I/O-coherent architectures pci_alloc_consistent
+ * is entirely harmless.
*/
#include <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);
diff --git a/drivers/sound/ymfpci.h b/drivers/sound/ymfpci.h
index 1686f204dda80..9ecf6b2ca87a8 100644
--- a/drivers/sound/ymfpci.h
+++ b/drivers/sound/ymfpci.h
@@ -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;
diff --git a/drivers/telephony/phonedev.c b/drivers/telephony/phonedev.c
index 0380ee2dfdc13..c8eb8d1e48c9d 100644
--- a/drivers/telephony/phonedev.c
+++ b/drivers/telephony/phonedev.c
@@ -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
index 0000000000000..891c91821ce82
--- /dev/null
+++ b/drivers/usb/Makefile.lib
@@ -0,0 +1 @@
+obj-$(CONFIG_USB_CATC) += crc32.o
diff --git a/drivers/usb/catc.c b/drivers/usb/catc.c
index 856fb1c8f555a..cc14861706dbe 100644
--- a/drivers/usb/catc.c
+++ b/drivers/usb/catc.c
@@ -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);
}
diff --git a/drivers/usb/hcd.c b/drivers/usb/hcd.c
index f9e97651fb9f6..8d4799ae576de 100644
--- a/drivers/usb/hcd.c
+++ b/drivers/usb/hcd.c
@@ -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) {
diff --git a/drivers/usb/hcd/ehci-hcd.c b/drivers/usb/hcd/ehci-hcd.c
index 83a33212f88af..41b8f3fd2df07 100644
--- a/drivers/usb/hcd/ehci-hcd.c
+++ b/drivers/usb/hcd/ehci-hcd.c
@@ -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));
diff --git a/drivers/usb/hcd/ehci-sched.c b/drivers/usb/hcd/ehci-sched.c
index 905e506f3fa0a..5a971fee2d9f0 100644
--- a/drivers/usb/hcd/ehci-sched.c
+++ b/drivers/usb/hcd/ehci-sched.c
@@ -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 ();
diff --git a/drivers/video/aty/mach64_accel.c b/drivers/video/aty/mach64_accel.c
index 37baf66f21350..1252d7334d049 100644
--- a/drivers/video/aty/mach64_accel.c
+++ b/drivers/video/aty/mach64_accel.c
@@ -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, \
diff --git a/drivers/video/sbusfb.c b/drivers/video/sbusfb.c
index 34ee6dd29a97d..63d3b3fa48ef3 100644
--- a/drivers/video/sbusfb.c
+++ b/drivers/video/sbusfb.c
@@ -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
index 0000000000000..0ca1cff140adb
--- /dev/null
+++ b/fs/Makefile.lib
@@ -0,0 +1,2 @@
+obj-$(CONFIG_FS_JFFS2) += crc32.o
+obj-$(CONFIG_EFI_PARTITION) += crc32.o
diff --git a/fs/affs/file.c b/fs/affs/file.c
index a09a4502ea3dd..6a3602298fdbb 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -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;
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 672bd95c75678..4f34a8c0dffdd 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -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;
diff --git a/fs/buffer.c b/fs/buffer.c
index b55ac6aba6742..8a9233a44356d 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -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);
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index 8dc002027c499..3918709b08176 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -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;
diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c
index 92ce22a393dfd..861a87741e401 100644
--- a/fs/coda/pioctl.c
+++ b/fs/coda/pioctl.c
@@ -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 ) {
diff --git a/fs/dcache.c b/fs/dcache.c
index d4379a0ee9a86..7246506fff370 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -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");
diff --git a/fs/devfs/base.c b/fs/devfs/base.c
index 639ae7464c6ce..19c4066007e37 100644
--- a/fs/devfs/base.c
+++ b/fs/devfs/base.c
@@ -601,6 +601,9 @@
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>
@@ -633,7 +636,7 @@
#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)
diff --git a/fs/devpts/root.c b/fs/devpts/root.c
index dd696709f27de..e93c3354c5b7f 100644
--- a/fs/devpts/root.c
+++ b/fs/devpts/root.c
@@ -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;
}
diff --git a/fs/driverfs/inode.c b/fs/driverfs/inode.c
index 1a37b2286f80f..c8d9f41439dd3 100644
--- a/fs/driverfs/inode.c
+++ b/fs/driverfs/inode.c
@@ -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;
}
diff --git a/fs/fat/cache.c b/fs/fat/cache.c
index 540d9df2ba067..a376239068bb9 100644
--- a/fs/fat/cache.c
+++ b/fs/fat/cache.c
@@ -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("-- ");
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index e6daf9dc5f174..904a5b27721d0 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -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 =
diff --git a/fs/inode.c b/fs/inode.c
index 5b7f3e1a75a9b..22b6d538ed0f5 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -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);
diff --git a/fs/intermezzo/cache.c b/fs/intermezzo/cache.c
index db9d6948bd361..b7ef2eb4926ec 100644
--- a/fs/intermezzo/cache.c
+++ b/fs/intermezzo/cache.c
@@ -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 */
diff --git a/fs/intermezzo/presto.c b/fs/intermezzo/presto.c
index 5da2e10ae3889..1eba374ae559c 100644
--- a/fs/intermezzo/presto.c
+++ b/fs/intermezzo/presto.c
@@ -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;
}
diff --git a/fs/intermezzo/psdev.c b/fs/intermezzo/psdev.c
index 0785b7d8a1652..0384ab5c3c295 100644
--- a/fs/intermezzo/psdev.c
+++ b/fs/intermezzo/psdev.c
@@ -43,14 +43,15 @@
#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);
diff --git a/fs/intermezzo/sysctl.c b/fs/intermezzo/sysctl.c
index 9a0c34f4d34fa..212e4c19f71c6 100644
--- a/fs/intermezzo/sysctl.c
+++ b/fs/intermezzo/sysctl.c
@@ -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;
}
diff --git a/fs/intermezzo/vfs.c b/fs/intermezzo/vfs.c
index 8d37756a7f13e..f8fbdc96352dc 100644
--- a/fs/intermezzo/vfs.c
+++ b/fs/intermezzo/vfs.c
@@ -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)
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index a483de6c2ad6a..92388ce7e1269 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -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);
diff --git a/fs/jbd/revoke.c b/fs/jbd/revoke.c
index faf2b412b6746..43987b60f6e2a 100644
--- a/fs/jbd/revoke.c
+++ b/fs/jbd/revoke.c
@@ -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);
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index 16d8e3ed249f1..1b113947ccdf0 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -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;
}
diff --git a/fs/jffs2/Makefile b/fs/jffs2/Makefile
index 9c9e76fc1ca51..7cc0da6a7c0d1 100644
--- a/fs/jffs2/Makefile
+++ b/fs/jffs2/Makefile
@@ -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
index b3b6a811af776..0000000000000
--- a/fs/jffs2/crc32.c
+++ /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
index cd8979f73c7a0..0000000000000
--- a/fs/jffs2/crc32.h
+++ /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
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index c40a8fb0a45b3..c1e9143f621fa 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -38,11 +38,11 @@
#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);
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index 633875a6d2cd3..115c7a20f7651 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.c
@@ -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;
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 4771c02ee965b..f0446acb9194c 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -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));
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index 4cdb2855759b9..9294e584c4d49 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -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);
diff --git a/fs/jffs2/read.c b/fs/jffs2/read.c
index cce42560d6ab6..fd46ae954c229 100644
--- a/fs/jffs2/read.c
+++ b/fs/jffs2/read.c
@@ -37,10 +37,10 @@
#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)
{
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 2e1d93de3bc50..f72affe1a4489 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -41,10 +41,10 @@
#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)
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index c8708da6ac695..d1b870bd59dfa 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -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); \
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c
index e8af1895c565b..32c11f9546b04 100644
--- a/fs/jffs2/write.c
+++ b/fs/jffs2/write.c
@@ -37,10 +37,10 @@
#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. */
diff --git a/fs/namei.c b/fs/namei.c
index 20d3add2cf42b..3d9b2dbecde1f 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -99,16 +99,17 @@
* kernel data space before using them..
*
* POSIX.1 2.4: an empty pathname is invalid (ENOENT).
+ * PATH_MAX includes the nul terminator --RR.
*/
static inline int do_getname(const char *filename, char *page)
{
int retval;
- unsigned long len = PATH_MAX + 1;
+ unsigned long len = PATH_MAX;
if ((unsigned long) filename >= TASK_SIZE) {
if (!segment_eq(get_fs(), KERNEL_DS))
return -EFAULT;
- } else if (TASK_SIZE - (unsigned long) filename < PATH_MAX + 1)
+ } else if (TASK_SIZE - (unsigned long) filename < PATH_MAX)
len = TASK_SIZE - (unsigned long) filename;
retval = strncpy_from_user((char *)page, filename, len);
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
index b0e1fd06c3f80..61c8b2b731115 100644
--- a/fs/openpromfs/inode.c
+++ b/fs/openpromfs/inode.c
@@ -1,4 +1,4 @@
-/* $Id: inode.c,v 1.14 2001/02/13 01:17:17 davem Exp $
+/* $Id: inode.c,v 1.15 2001/11/12 09:43:39 davem Exp $
* openpromfs.c: /proc/openprom handling routines
*
* Copyright (C) 1996-1999 Jakub Jelinek (jakub@redhat.com)
diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c
index 68a58ff9de97b..870f9c1128797 100644
--- a/fs/partitions/msdos.c
+++ b/fs/partitions/msdos.c
@@ -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)) {
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
index 9caf732985868..a426e4f84584b 100644
--- a/fs/reiserfs/bitmap.c
+++ b/fs/reiserfs/bitmap.c
@@ -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;
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index 634747f31edfb..98d6b2dc31aa0 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -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) ;
diff --git a/fs/reiserfs/tail_conversion.c b/fs/reiserfs/tail_conversion.c
index 775f81cbc2ec0..5648d09857a63 100644
--- a/fs/reiserfs/tail_conversion.c
+++ b/fs/reiserfs/tail_conversion.c
@@ -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) ;
}
}
diff --git a/include/asm-sparc/bitops.h b/include/asm-sparc/bitops.h
index 7cf6d031e47b1..e4f65b8134ee5 100644
--- a/include/asm-sparc/bitops.h
+++ b/include/asm-sparc/bitops.h
@@ -1,4 +1,4 @@
-/* $Id: bitops.h,v 1.65 2001/10/30 04:08:26 davem Exp $
+/* $Id: bitops.h,v 1.67 2001/11/19 18:36:34 davem Exp $
* bitops.h: Bit string operations on the Sparc.
*
* Copyright 1995 David S. Miller (davem@caip.rutgers.edu)
diff --git a/include/asm-sparc/io.h b/include/asm-sparc/io.h
index 3d74130c7d236..d42fa22ece834 100644
--- a/include/asm-sparc/io.h
+++ b/include/asm-sparc/io.h
@@ -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)
{
diff --git a/include/asm-sparc/keyboard.h b/include/asm-sparc/keyboard.h
index 6e59c6d2557d5..6155ccbbacac4 100644
--- a/include/asm-sparc/keyboard.h
+++ b/include/asm-sparc/keyboard.h
@@ -1,4 +1,4 @@
-/* $Id: keyboard.h,v 1.7 2001/08/18 09:40:46 davem Exp $
+/* $Id: keyboard.h,v 1.8 2002/01/08 16:00:20 davem Exp $
* linux/include/asm-sparc/keyboard.h
*
* sparc64 Created Aug 29 1997 by Eddie C. Dost (ecd@skynet.be)
diff --git a/include/asm-sparc/mmu_context.h b/include/asm-sparc/mmu_context.h
index 274707e2d288a..8391aff3c9f17 100644
--- a/include/asm-sparc/mmu_context.h
+++ b/include/asm-sparc/mmu_context.h
@@ -5,6 +5,29 @@
#ifndef __ASSEMBLY__
+/*
+ * Every architecture must define this function. It's the fastest
+ * way of searching a 168-bit bitmap where the first 128 bits are
+ * unlikely to be clear. It's guaranteed that at least one of the 168
+ * bits is cleared.
+ */
+#if MAX_RT_PRIO != 128 || MAX_PRIO != 168
+# error update this function.
+#endif
+
+static inline int sched_find_first_zero_bit(unsigned long *b)
+{
+ unsigned int rt;
+
+ rt = b[0] & b[1] & b[2] & b[3];
+ if (unlikely(rt != 0xffffffff))
+ return find_first_zero_bit(b, MAX_RT_PRIO);
+
+ if (b[4] != ~0)
+ return ffz(b[4]) + MAX_RT_PRIO;
+ return ffz(b[5]) + 32 + MAX_RT_PRIO;
+}
+
static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
{
}
diff --git a/include/asm-sparc/oplib.h b/include/asm-sparc/oplib.h
index 4e2e6015735b8..27ab73c6b0568 100644
--- a/include/asm-sparc/oplib.h
+++ b/include/asm-sparc/oplib.h
@@ -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. */
diff --git a/include/asm-sparc/pci.h b/include/asm-sparc/pci.h
index 0bc0b4019c954..701ec03bc1428 100644
--- a/include/asm-sparc/pci.h
+++ b/include/asm-sparc/pci.h
@@ -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>
diff --git a/include/asm-sparc/smp.h b/include/asm-sparc/smp.h
index dbdab2c1ebb68..c283f51576175 100644
--- a/include/asm-sparc/smp.h
+++ b/include/asm-sparc/smp.h
@@ -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
diff --git a/include/asm-sparc/smplock.h b/include/asm-sparc/smplock.h
index 96565069c9887..dd2cc2b542673 100644
--- a/include/asm-sparc/smplock.h
+++ b/include/asm-sparc/smplock.h
@@ -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)
diff --git a/include/asm-sparc/string.h b/include/asm-sparc/string.h
index 7bce820e8680c..1182435f41632 100644
--- a/include/asm-sparc/string.h
+++ b/include/asm-sparc/string.h
@@ -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
diff --git a/include/asm-sparc/types.h b/include/asm-sparc/types.h
index 8a43339c1410a..8e726708e1cd4 100644
--- a/include/asm-sparc/types.h
+++ b/include/asm-sparc/types.h
@@ -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__ */
diff --git a/include/asm-sparc64/bitops.h b/include/asm-sparc64/bitops.h
index 17ef06746bfbb..69e505905cf2b 100644
--- a/include/asm-sparc64/bitops.h
+++ b/include/asm-sparc64/bitops.h
@@ -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))
diff --git a/include/asm-sparc64/elf.h b/include/asm-sparc64/elf.h
index d9a5a903a8dd2..dd584acbb34fa 100644
--- a/include/asm-sparc64/elf.h
+++ b/include/asm-sparc64/elf.h
@@ -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; \
} \
\
diff --git a/include/asm-sparc64/io.h b/include/asm-sparc64/io.h
index 8b8c056caf029..58a8ae58100a4 100644
--- a/include/asm-sparc64/io.h
+++ b/include/asm-sparc64/io.h
@@ -1,4 +1,4 @@
-/* $Id: io.h,v 1.46 2001/12/13 04:16:52 davem Exp $ */
+/* $Id: io.h,v 1.47 2001/12/13 10:36:02 davem Exp $ */
#ifndef __SPARC64_IO_H
#define __SPARC64_IO_H
diff --git a/include/asm-sparc64/keyboard.h b/include/asm-sparc64/keyboard.h
index 2202e5a942193..fc81294da408c 100644
--- a/include/asm-sparc64/keyboard.h
+++ b/include/asm-sparc64/keyboard.h
@@ -1,4 +1,4 @@
-/* $Id: keyboard.h,v 1.5 2001/08/18 09:40:46 davem Exp $
+/* $Id: keyboard.h,v 1.6 2002/01/08 16:00:20 davem Exp $
* linux/include/asm-sparc64/keyboard.h
*
* Created Aug 29 1997 by Eddie C. Dost (ecd@skynet.be)
diff --git a/include/asm-sparc64/mmu_context.h b/include/asm-sparc64/mmu_context.h
index c8296b0ce4ffa..11bb4c2461268 100644
--- a/include/asm-sparc64/mmu_context.h
+++ b/include/asm-sparc64/mmu_context.h
@@ -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
@@ -27,6 +27,27 @@
#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)
{
}
diff --git a/include/asm-sparc64/oplib.h b/include/asm-sparc64/oplib.h
index cf6cbc58967a6..77ee8a08400ff 100644
--- a/include/asm-sparc64/oplib.h
+++ b/include/asm-sparc64/oplib.h
@@ -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, ...);
diff --git a/include/asm-sparc64/page.h b/include/asm-sparc64/page.h
index 6c65d3241a8b6..c5de1e232dcfe 100644
--- a/include/asm-sparc64/page.h
+++ b/include/asm-sparc64/page.h
@@ -1,4 +1,4 @@
-/* $Id: page.h,v 1.36 2000/08/10 01:04:53 davem Exp $ */
+/* $Id: page.h,v 1.38 2001/11/30 01:04:10 davem Exp $ */
#ifndef _SPARC64_PAGE_H
#define _SPARC64_PAGE_H
@@ -18,13 +18,20 @@
#ifndef __ASSEMBLY__
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+extern void do_BUG(const char *file, int line);
+#define BUG() do { \
+ do_BUG(__FILE__, __LINE__); \
+ __builtin_trap(); \
+} while (0)
+#else
#define BUG() __builtin_trap()
+#endif
+
#define PAGE_BUG(page) BUG()
extern void _clear_page(void *page);
-extern void _copy_page(void *to, void *from);
#define clear_page(X) _clear_page((void *)(X))
-#define copy_page(X,Y) _copy_page((void *)(X), (void *)(Y))
extern void clear_user_page(void *page, unsigned long vaddr);
extern void copy_user_page(void *to, void *from, unsigned long vaddr);
diff --git a/include/asm-sparc64/processor.h b/include/asm-sparc64/processor.h
index c026b640a1038..dc0e88282f50e 100644
--- a/include/asm-sparc64/processor.h
+++ b/include/asm-sparc64/processor.h
@@ -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
diff --git a/include/asm-sparc64/rwsem.h b/include/asm-sparc64/rwsem.h
index 535ca47717cc3..1717d1a5bed6d 100644
--- a/include/asm-sparc64/rwsem.h
+++ b/include/asm-sparc64/rwsem.h
@@ -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");
diff --git a/include/asm-sparc64/semaphore.h b/include/asm-sparc64/semaphore.h
index 7a8aa9597a84e..2aaa3160115e2 100644
--- a/include/asm-sparc64/semaphore.h
+++ b/include/asm-sparc64/semaphore.h
@@ -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"
diff --git a/include/asm-sparc64/smp.h b/include/asm-sparc64/smp.h
index c2b3a411bbcce..d73d3e657cf5e 100644
--- a/include/asm-sparc64/smp.h
+++ b/include/asm-sparc64/smp.h
@@ -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
diff --git a/include/asm-sparc64/smplock.h b/include/asm-sparc64/smplock.h
index 6b3c900de906d..dd2cc2b542673 100644
--- a/include/asm-sparc64/smplock.h
+++ b/include/asm-sparc64/smplock.h
@@ -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)
diff --git a/include/asm-sparc64/spinlock.h b/include/asm-sparc64/spinlock.h
index 06956c1e8920a..ce905b46162c0 100644
--- a/include/asm-sparc64/spinlock.h
+++ b/include/asm-sparc64/spinlock.h
@@ -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__) */
diff --git a/include/asm-sparc64/spitfire.h b/include/asm-sparc64/spitfire.h
index 26a67f822452a..3839b239fe5a3 100644
--- a/include/asm-sparc64/spitfire.h
+++ b/include/asm-sparc64/spitfire.h
@@ -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));
diff --git a/include/asm-sparc64/system.h b/include/asm-sparc64/system.h
index 46dea88f62ae7..d5b497ddf5e07 100644
--- a/include/asm-sparc64/system.h
+++ b/include/asm-sparc64/system.h
@@ -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");
diff --git a/include/asm-sparc64/ttable.h b/include/asm-sparc64/ttable.h
index e9960e1c48128..8ed23fd00ad62 100644
--- a/include/asm-sparc64/ttable.h
+++ b/include/asm-sparc64/ttable.h
@@ -1,4 +1,4 @@
-/* $Id: ttable.h,v 1.16 2001/03/28 10:56:34 davem Exp $ */
+/* $Id: ttable.h,v 1.17 2001/11/28 23:32:16 davem Exp $ */
#ifndef _SPARC64_TTABLE_H
#define _SPARC64_TTABLE_H
@@ -29,6 +29,15 @@
clr %l6; \
nop;
+#define TRAP_7INSNS(routine) \
+ sethi %hi(109f), %g7; \
+ ba,pt %xcc, etrap; \
+109: or %g7, %lo(109b), %g7; \
+ call routine; \
+ add %sp, STACK_BIAS + REGWIN_SZ, %o0; \
+ ba,pt %xcc, rtrap; \
+ clr %l6;
+
#define TRAP_SAVEFPU(routine) \
sethi %hi(109f), %g7; \
ba,pt %xcc, do_fptrap; \
@@ -44,6 +53,11 @@
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; \
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 3f11ceb302dfe..0cbe78286ab51 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -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
index 0000000000000..a0033ffee91cb
--- /dev/null
+++ b/include/linux/crc32.h
@@ -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 */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index b102c2d51d544..a01f0c3b4d34d 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -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);
diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h
index ba663102f02fd..dd936fe6180ea 100644
--- a/include/linux/if_arp.h
+++ b/include/linux/if_arp.h
@@ -82,6 +82,7 @@
/* 787->799 reserved for fibrechannel media types */
#define ARPHRD_IEEE802_TR 800 /* Magic type ident for TR */
#define ARPHRD_IEEE80211 801 /* IEEE 802.11 */
+#define ARPHRD_IEEE80211_PRISM 802 /* IEEE 802.11 + Prism2 header */
#define ARPHRD_VOID 0xFFFF /* Void type, nothing is known */
diff --git a/include/linux/if_bonding.h b/include/linux/if_bonding.h
index d719560dde0b0..97d490fd8dd82 100644
--- a/include/linux/if_bonding.h
+++ b/include/linux/if_bonding.h
@@ -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;
diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h
index 465b35c3d245f..abc0c3e7bad2e 100644
--- a/include/linux/kbd_kern.h
+++ b/include/linux/kbd_kern.h
@@ -1,6 +1,7 @@
#ifndef _KBD_KERN_H
#define _KBD_KERN_H
+#include <linux/tty.h>
#include <linux/interrupt.h>
#include <linux/keyboard.h>
diff --git a/include/linux/limits.h b/include/linux/limits.h
index 51c49ec4e325b..45faa81d981d4 100644
--- a/include/linux/limits.h
+++ b/include/linux/limits.h
@@ -11,7 +11,7 @@
#define MAX_CANON 255 /* size of the canonical input queue */
#define MAX_INPUT 255 /* size of the type-ahead buffer */
#define NAME_MAX 255 /* # chars in a file name */
-#define PATH_MAX 4095 /* # chars in a path name */
+#define PATH_MAX 4096 /* # chars in a path name including nul */
#define PIPE_BUF 4096 /* # bytes in atomic write to a pipe */
#define RTSIG_MAX 32
diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h
index 8ce25aae46f09..f0e8b9927eabf 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack.h
@@ -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 */
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_tuple.h b/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
index 8b6dc4a8bf57b..9f6ec0a6bccc1 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
@@ -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 */
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index b50d60989eae3..1c4cec479ba34 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -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) ;
diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h
index 1eee601a12def..a78f789867235 100644
--- a/include/linux/reiserfs_fs_sb.h
+++ b/include/linux/reiserfs_fs_sb.h
@@ -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 */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 068d5b802a236..14b6388cc3c29 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -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;
diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
index fbcfce81e1105..070eef7b5137e 100644
--- a/include/linux/shmem_fs.h
+++ b/include/linux/shmem_fs.h
@@ -11,7 +11,7 @@
* swapper address space.
*
* We have to move it here, since not every user of fs.h is including
- * mm.h, but m.h is including fs.h via sched .h :-/
+ * mm.h, but mm.h is including fs.h via sched .h :-/
*/
typedef struct {
unsigned long val;
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 7887eee13d790..74303f129fddb 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -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
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 62f4b1bd4dd1e..be4c52c62c1c5 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -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);
/*
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 7ea6e7334bc5d..b0ac23988cf4c 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -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 *);
diff --git a/include/math-emu/double.h b/include/math-emu/double.h
index 04c4c0f4584cd..655ccf1c47398 100644
--- a/include/math-emu/double.h
+++ b/include/math-emu/double.h
@@ -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__ */
diff --git a/include/math-emu/extended.h b/include/math-emu/extended.h
index ae73cecb399bb..84770fceb53e0 100644
--- a/include/math-emu/extended.h
+++ b/include/math-emu/extended.h
@@ -19,6 +19,10 @@
not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef __MATH_EMU_EXTENDED_H__
+#define __MATH_EMU_EXTENDED_H__
+
#if _FP_W_TYPE_SIZE < 32
#error "Here's a nickel, kid. Go buy yourself a real computer."
#endif
@@ -388,3 +392,5 @@ 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__ */
diff --git a/include/math-emu/op-1.h b/include/math-emu/op-1.h
index 53e0fce1b18d4..38c0561b70a6a 100644
--- a/include/math-emu/op-1.h
+++ b/include/math-emu/op-1.h
@@ -22,6 +22,9 @@
not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+#ifndef __MATH_EMU_OP_1_H__
+#define __MATH_EMU_OP_1_H__
+
#define _FP_FRAC_DECL_1(X) _FP_W_TYPE X##_f
#define _FP_FRAC_COPY_1(D,S) (D##_f = S##_f)
#define _FP_FRAC_SET_1(X,I) (X##_f = I)
@@ -295,3 +298,5 @@
else \
D##_f <<= _FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs; \
} while (0)
+
+#endif /* __MATH_EMU_OP_1_H__ */
diff --git a/include/math-emu/op-2.h b/include/math-emu/op-2.h
index e639d534e67f7..81416782bc368 100644
--- a/include/math-emu/op-2.h
+++ b/include/math-emu/op-2.h
@@ -22,6 +22,9 @@
not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+#ifndef __MATH_EMU_OP_2_H__
+#define __MATH_EMU_OP_2_H__
+
#define _FP_FRAC_DECL_2(X) _FP_W_TYPE X##_f0, X##_f1
#define _FP_FRAC_COPY_2(D,S) (D##_f0 = S##_f0, D##_f1 = S##_f1)
#define _FP_FRAC_SET_2(X,I) __FP_FRAC_SET_2(X, I)
@@ -606,3 +609,4 @@
_FP_FRAC_SLL_2(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs)); \
} while (0)
+#endif
diff --git a/include/math-emu/op-4.h b/include/math-emu/op-4.h
index f5235f5d9726c..2aa1356325adc 100644
--- a/include/math-emu/op-4.h
+++ b/include/math-emu/op-4.h
@@ -22,6 +22,9 @@
not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+#ifndef __MATH_EMU_OP_4_H__
+#define __MATH_EMU_OP_4_H__
+
#define _FP_FRAC_DECL_4(X) _FP_W_TYPE X##_f[4]
#define _FP_FRAC_COPY_4(D,S) \
(D##_f[0] = S##_f[0], D##_f[1] = S##_f[1], \
@@ -659,3 +662,4 @@
_FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs)); \
} while (0)
+#endif
diff --git a/include/math-emu/op-8.h b/include/math-emu/op-8.h
index a9d7dbf590807..8b8c05eb8283e 100644
--- a/include/math-emu/op-8.h
+++ b/include/math-emu/op-8.h
@@ -21,6 +21,9 @@
not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+#ifndef __MATH_EMU_OP_8_H__
+#define __MATH_EMU_OP_8_H__
+
/* We need just a few things from here for op-4, if we ever need some
other macros, they can be added. */
#define _FP_FRAC_DECL_8(X) _FP_W_TYPE X##_f[8]
@@ -101,3 +104,4 @@
X##_f[0] |= (_s != 0); \
} while (0)
+#endif
diff --git a/include/math-emu/op-common.h b/include/math-emu/op-common.h
index e03e40e656bc3..dd37d44940c4e 100644
--- a/include/math-emu/op-common.h
+++ b/include/math-emu/op-common.h
@@ -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__ */
diff --git a/include/math-emu/quad.h b/include/math-emu/quad.h
index 23b20c3e672fc..616113626d096 100644
--- a/include/math-emu/quad.h
+++ b/include/math-emu/quad.h
@@ -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__ */
diff --git a/include/math-emu/single.h b/include/math-emu/single.h
index ea12cb8b0a311..87f90b0f9e5d7 100644
--- a/include/math-emu/single.h
+++ b/include/math-emu/single.h
@@ -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__ */
diff --git a/include/math-emu/soft-fp.h b/include/math-emu/soft-fp.h
index 1d13451346b5e..ca977531a1bce 100644
--- a/include/math-emu/soft-fp.h
+++ b/include/math-emu/soft-fp.h
@@ -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__ */
diff --git a/kernel/ksyms.c b/kernel/ksyms.c
index eded2d7fb3393..f3f8775d87859 100644
--- a/kernel/ksyms.c
+++ b/kernel/ksyms.c
@@ -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);
diff --git a/kernel/sched.c b/kernel/sched.c
index 8df860f0922c0..cfa9dc97603db 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -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
index 0000000000000..6072b45722e94
--- /dev/null
+++ b/lib/Config.in
@@ -0,0 +1,8 @@
+#
+# Library configuration
+#
+mainmenu_option next_comment
+comment 'Library routines'
+
+tristate 'CRC32 functions' CONFIG_CRC32
+endmenu
diff --git a/lib/Makefile b/lib/Makefile
index 38a91fa0c9e72..9e2d80f5f3505 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -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
index 0000000000000..8bf7b8d8de544
--- /dev/null
+++ b/lib/crc32.c
@@ -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);
diff --git a/mm/bootmem.c b/mm/bootmem.c
index adafe138a3da3..3b0420d653cb5 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -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;
diff --git a/mm/highmem.c b/mm/highmem.c
index 21fc70173587b..672500e52b46e 100644
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -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);
}
diff --git a/mm/page_io.c b/mm/page_io.c
index 79700f304b18b..cacb3952178fa 100644
--- a/mm/page_io.c
+++ b/mm/page_io.c
@@ -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
diff --git a/mm/swapfile.c b/mm/swapfile.c
index ff9a8e1f00ef5..2149e6eda6798 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -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;
}
/*
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index e549e336038ee..f6be310ede54b 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -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 *);
@@ -106,6 +105,23 @@ static int __init vlan_proto_init(void)
}
/*
+ * 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.
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 00a7f07bded92..7da75dbadd93d 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -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;
}
}
diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c
index 4315f2cb45d48..5c994e1a1257e 100644
--- a/net/8021q/vlanproc.c
+++ b/net/8021q/vlanproc.c
@@ -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;
}
diff --git a/net/Config.in b/net/Config.in
index 0b9568a8ab9c2..3650e020c955b 100644
--- a/net/Config.in
+++ b/net/Config.in
@@ -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
diff --git a/net/README b/net/README
index 24065ec3ffc52..e509ec526c254 100644
--- a/net/README
+++ b/net/README
@@ -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
diff --git a/net/bridge/br.c b/net/bridge/br.c
index f91d8fa6d200c..9be42e03b40a6 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -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)
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 95772a1e3dc64..94e8312a059c7 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -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;
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 08c58f19fe496..ea1a238bc7903 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -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)
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index dc1e1561a0514..907eb151316e8 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -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);
}
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index a83504d832eb9..e8ba48aae6a61 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -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,
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 62452f1080f6c..84edccae67450 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -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;
diff --git a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c
index bf1c7793a1dd5..79cec8993d405 100644
--- a/net/ipv4/netfilter/ip_conntrack_irc.c
+++ b/net/ipv4/netfilter/ip_conntrack_irc.c
@@ -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
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 3c60c0d78ea16..1846640d28377 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -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);
diff --git a/net/ipv4/netfilter/ip_fw_compat.c b/net/ipv4/netfilter/ip_fw_compat.c
index 6489ad7871104..021d125f39073 100644
--- a/net/ipv4/netfilter/ip_fw_compat.c
+++ b/net/ipv4/netfilter/ip_fw_compat.c
@@ -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)
diff --git a/net/ipv4/netfilter/ip_fw_compat_redir.c b/net/ipv4/netfilter/ip_fw_compat_redir.c
index 274bb1162265e..f55680e7e6fab 100644
--- a/net/ipv4/netfilter/ip_fw_compat_redir.c
+++ b/net/ipv4/netfilter/ip_fw_compat_redir.c
@@ -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)
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
index 79d533aae1381..07ebd39fa1159 100644
--- a/net/ipv4/netfilter/ip_nat_core.c
+++ b/net/ipv4/netfilter/ip_nat_core.c
@@ -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",
diff --git a/net/ipv4/netfilter/ip_nat_helper.c b/net/ipv4/netfilter/ip_nat_helper.c
index d62b5bf413a52..183ba3f85356d 100644
--- a/net/ipv4/netfilter/ip_nat_helper.c
+++ b/net/ipv4/netfilter/ip_nat_helper.c
@@ -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;
diff --git a/net/ipv4/netfilter/ip_nat_irc.c b/net/ipv4/netfilter/ip_nat_irc.c
index 02102b3697454..2a8b83afaf5b4 100644
--- a/net/ipv4/netfilter/ip_nat_irc.c
+++ b/net/ipv4/netfilter/ip_nat_irc.c
@@ -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));
diff --git a/net/ipv4/netfilter/ipt_MIRROR.c b/net/ipv4/netfilter/ipt_MIRROR.c
index d984d7e1fb9a0..2fd35b69924fe 100644
--- a/net/ipv4/netfilter/ipt_MIRROR.c
+++ b/net/ipv4/netfilter/ipt_MIRROR.c
@@ -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;
}
diff --git a/net/ipv4/netfilter/ipt_TCPMSS.c b/net/ipv4/netfilter/ipt_TCPMSS.c
index ced0a9dced52d..68eb02cd9f20a 100644
--- a/net/ipv4/netfilter/ipt_TCPMSS.c
+++ b/net/ipv4/netfilter/ipt_TCPMSS.c
@@ -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;
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c
index e6061d707ac5b..90d7173f3d0b7 100644
--- a/net/ipv4/netfilter/ipt_TOS.c
+++ b/net/ipv4/netfilter/ipt_TOS.c
@@ -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);
diff --git a/net/ipv4/netfilter/ipt_unclean.c b/net/ipv4/netfilter/ipt_unclean.c
index 80b6c55dbb0ef..8ca4852f9c7a1 100644
--- a/net/ipv4/netfilter/ipt_unclean.c
+++ b/net/ipv4/netfilter/ipt_unclean.c
@@ -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)
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 738a3e5d220ed..96a37a29d1ab0 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -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;
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 7313f8c18bffc..7ca2e8d46b0f7 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -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
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 5588c4c732000..18ddb790db8e0 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -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;
}