Home Home > GIT Browse
summaryrefslogtreecommitdiff
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)
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 9be21975f4fe..9bc25ad78d4d 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 000000000000..b8de235987eb
--- /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 d8c95d579106..8548f913ee3e 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 407a684e9d16..de386c4ea0b7 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 9d5454939b7c..e0588af1fd40 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 fffcc6e582a7..5c2a8e1c65b8 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 91f072a80d70..14ca220f571a 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 02bcbfa8b0ad..f71bf71205f3 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 5a9ee03de6fb..66013359742e 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 68a6cc9caa27..aa1284ad5dbd 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 b954777752f8..11ce0b503ba9 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 efd313e13fe9..52b2a387bc0e 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 fb0931f7b75c..dff81a6f05b2 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 a65b213cd134..44bc86f06182 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 3136bd056906..25b7fd9e492e 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 4ebb9f27a8ca..5ddba84ff19a 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 f68410f663f7..367242b77595 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 3545adc66875..7dfaf4d331e8 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 c545c3614420..f5932ba5c203 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 5a9c5b689080..1ab8e3c235a5 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 7b70ccccd738..32fb2212b083 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 9f05197f9cf3..032e16082964 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 1c2aecb33be5..f9157e44dc9c 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 f8a9ea63d924..ecd4e6d150e7 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 609ab361f192..ee31e2aaa534 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 5633c882f327..d6d5e35e551a 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 49e6f1a4c6db..5e3a4008de43 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 0cadcd7908ef..2e477bfbc8ec 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 957ddc17ca30..51bfe75ede92 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 2a47968bbfc4..c53e219dfc9f 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 e8f5fb37b01e..a63ffb0670dd 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 676b9f261591..4cd8f8bb5393 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 3180994194b8..8dd283c38e85 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 b7b7025fc719..d316096ea52e 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 0f718bac82a9..5f90082c1efa 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 165c83ab5e11..5f63e466cdef 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 b422c571cfd0..8f1d7e79fa4f 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 34e289ed2843..c0baac138941 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 be4522e1fadb..16fcc375f50f 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 3bd631f36578..cfd35dbdc4b5 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 244619eb6461..96e3a342be5d 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 64233d56fd5d..75ce131bbdd1 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 1b91160e21ac..72294c14b4f5 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 813126deeda9..3ff8f9448112 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 f80dcd0c9ed7..b4b2515433bd 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 dba732a6d9e5..318efe3ccc27 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 beaf6534807f..65259c261dd6 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 1cf4f31e50b5..b75122e51cc9 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 acbb1b518be6..d0bbcf190f00 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 2a3ef1fb4d23..c4bb21f4c611 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 134be5cd793c..12c93a3eee26 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 dedf08d2614c..59b4f9c2a453 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 38d253cbc35d..b2f341752db7 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 7ea3a3036a30..59ea29a97a41 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 b5a58611fc59..7f86b6f0189f 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 3e35c92e3047..a660d05199aa 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 35f1cc2d3468..320fa2587d76 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 797e5c78c9c6..cedff9e3a975 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 20cd9a582fb3..5625e6cc5f3a 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 0e5a073ca69a..4998dcfefb1c 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 3e3b38ee4261..e3c79264a5e1 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 354021278556..10785cb9c00f 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 956a80427b68..62db94b4f46b 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 a6f259cafad5..a4fd67dd5ad4 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 234e0af430dd..8c9333d43fd7 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 f174b54f39de..353ddf6ad25b 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 39e2781f57d3..47e5a445a2a0 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 b89235acfc2c..3119c67b398a 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 fdf4a00f270a..eda8ed5ab3b2 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 90063fb4135b..f022447c8cdb 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 182fb0f96dc6..9b2e54e26907 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 35a34ebbf7dd..77be8b1f3e0c 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 fafe016c22d5..fa8558237a7f 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 dedc03521902..7042ae217cfc 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 b51811432239..ea62c3ecc2f9 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 2a59b278821f..b7c2631dd111 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 dcd982b7bc46..595eff631ff0 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 2d363621a44b..151ff52bbd2c 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 8faa35963fb9..828749fac6ec 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 98b1610a2327..0ba71673d306 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 5a368d50fe8e..339372977f5d 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 320f85c612d6..dd06c16183f8 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 6728b593bb06..d2799895117b 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 7902e3fc7b2d..c78754672c41 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 e2792736f08e..35543c2fa91e 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 1dafe1ec538e..c6eb34da2c14 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 7faf6f05ca90..6ba126d3def5 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 000000000000..ad40c687d69e
--- /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 000000000000..1e580f10923d
--- /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 6a92fa4f5e28..b67eeec19db3 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 8fcdc77fad13..8b5536023cc5 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 f98c41e49c01..142b4a8e8391 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 49b2e7dc1d5b..740e5c8b82bb 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 f8964bf1e71f..6f27a6120c2c 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 a02c0fccb709..3fb9ad117ac0 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 94d3cbb7c79b..792e787fc7ab 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 6773bf201e7d..385f26395039 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 9387ad20f8e7..bd57c42e61a0 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 765d9bd6b40d..7c99d9e3a4dd 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 0fb2a48fa837..6875780ae87e 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 ff5f5792fb03..e9f2252cf72c 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 2d219b46649a..c96bce2accdc 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 67064058e218..06e0746a9061 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 000000000000..af22a0e02a3a
--- /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 e00dee5c48cc..63ed2cbd6b1f 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 f6e4d255f4f7..184ad573dbda 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 30840e5d530f..b7bb8f4ca95a 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 5a9ad62ad6f2..badecbc401e1 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 62d7ceaeaad0..5a31cfe28fd9 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 168b9dd1543f..a9a4ac16240c 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 cf0d30df691b..e94ccb93c341 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 63e0c1e1fb86..e9736dc3ce89 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 45ceb740c567..2d8145dc3eca 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 2b5cff2b930c..3af726812573 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 173e42b4af39..f5c828869753 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 e6f061bedbc6..9095f2fc6bc6 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 16107578479d..1c232734fc51 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 fb1a8cd25916..49ed98d4d878 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 c94409b258b2..4cca074aa540 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 468c675b4ba0..7c30e77503fe 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 4b9319011880..dadc8c8d331e 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 e63a3c54291a..e35d85f477be 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 8d3e0b2d4541..1406a5edb968 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 dc1667b240ce..1a3e62efe656 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 04ca3c75ad16..7704924740d2 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 099b1fc938e3..9f792a43f0d7 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 18e2642afea8..851eba8a3e00 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 4ea8280d6d00..09b2d0450cef 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 7d01a2c6e986..a94d694536b6 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 e94d6c3cb3a2..6743227a3478 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 3816934946ce..6c47c37a0a0b 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 f1c322bb2dbd..44c218c3fff7 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 e7fe6ae79e54..578af8d57f9c 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 4ad12acf7d4a..25b86ec89538 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 9e1e2e30a26c..3ff3c5fbec56 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 e6140c6cf27c..6724c7406fe1 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 7a7c953b7b16..4f8e30868e9f 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 b7381fe679e2..ca223be377d6 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 c40f7dc8b041..07337b7b912f 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 0fec2bcce2c3..3d17fd6c2ff6 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 0170283fb854..1555eac7f1df 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 ab376ffedd70..c55a85e82611 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 88ca3775ef9e..bf06abcb2236 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 a4a63f21d436..ec136a81885f 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 2affbd1e2880..25778dc8676a 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 2f9cc0dac31b..c42003b125e4 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 30f06d1efc5c..7ddedceacfc2 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 917f1a9be8cf..b396f5ba85f3 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 2e753ad174a4..0aed62e907c4 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 f81fc206f985..92e18806848e 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 e169ad56faf8..e56ab051dda8 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 f1deb2a35e80..bb14996daf66 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 d6715d169e9d..064a5cc00809 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 fa714c2c46ef..8506921d5a54 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 cbf93b31b2de..1ee7f179d2e0 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 38b53ee9f16e..86b08d5cb827 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 f5ed491fb464..fdc9936319f0 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 ea2430ec0ad2..cebf4df348d1 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 fec4c3ee224c..99fe2b473c4a 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 ac0a1c40016a..acdabc85fc9c 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 5ac8a930486c..6ee3b0051b89 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 e9562c2ecc8c..a31e9630ea01 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 96bba6454933..c64a0901bc33 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 85a91217a57d..9835bfccf1df 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 6242554a93fa..e656d4d081a2 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 a6036ddd92bb..f0082058d61d 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 23113ae7c4a7..ebbd33c54f0d 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 aa0fd64cb32e..e276376771ae 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 3246ba64f15d..8604eb35140a 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 3bb3bef50f06..1c47f9cc0416 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 b3257fc4652b..554dc6b446c4 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 b6894649e12f..57596d9eb1cc 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 f64d20090923..b99553c5e51b 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 4e8745f23560..b23f616592db 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 3368906c2884..807ecbc58dca 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 01d6679250a9..2f7e4adcc360 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 1d9a90bbdd56..40d2ad5a28a4 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 aede1a6a9420..8f4d70c1e6a2 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 8f511d1a5105..e363fac3d987 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 e8f8c90bf793..3582d44e09d4 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 bc030dcb4fcc..f22d1414d563 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 d8c43a9d5abb..10e68e096edc 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 aabd8adc656c..19169b432779 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 25cf21c102ee..d426b7dff787 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 1686f204dda8..9ecf6b2ca87a 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 0380ee2dfdc1..c8eb8d1e48c9 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 000000000000..891c91821ce8
--- /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 856fb1c8f555..cc14861706db 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 f9e97651fb9f..8d4799ae576d 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 83a33212f88a..41b8f3fd2df0 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 905e506f3fa0..5a971fee2d9f 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 37baf66f2135..1252d7334d04 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 34ee6dd29a97..63d3b3fa48ef 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 000000000000..0ca1cff140ad
--- /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 a09a4502ea3d..6a3602298fdb 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 672bd95c7567..4f34a8c0dffd 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 b55ac6aba674..8a9233a44356 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 8dc002027c49..3918709b0817 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 92ce22a393df..861a87741e40 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 d4379a0ee9a8..7246506fff37 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 639ae7464c6c..19c4066007e3 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 dd696709f27d..e93c3354c5b7 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 1a37b2286f80..c8d9f41439dd 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 540d9df2ba06..a376239068bb 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 e6daf9dc5f17..904a5b27721d 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 5b7f3e1a75a9..22b6d538ed0f 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 db9d6948bd36..b7ef2eb4926e 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 5da2e10ae388..1eba374ae559 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 0785b7d8a165..0384ab5c3c29 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 9a0c34f4d34f..212e4c19f71c 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 8d37756a7f13..f8fbdc96352d 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 a483de6c2ad6..92388ce7e126 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 faf2b412b674..43987b60f6e2 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 16d8e3ed249f..1b113947ccdf 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 9c9e76fc1ca5..7cc0da6a7c0d 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 b3b6a811af77..000000000000
--- 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 cd8979f73c7a..000000000000
--- 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 c40a8fb0a45b..c1e9143f621f 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 633875a6d2cd..115c7a20f765 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 4771c02ee965..f0446acb9194 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 4cdb2855759b..9294e584c4d4 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 cce42560d6ab..fd46ae954c22 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 2e1d93de3bc5..f72affe1a448 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 c8708da6ac69..d1b870bd59df 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 e8af1895c565..32c11f9546b0 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 20d3add2cf42..3d9b2dbecde1 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 b0e1fd06c3f8..61c8b2b73111 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 68a58ff9de97..870f9c112879 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 9caf73298586..a426e4f84584 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 634747f31edf..98d6b2dc31aa 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 775f81cbc2ec..5648d09857a6 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 7cf6d031e47b..e4f65b8134ee 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 3d74130c7d23..d42fa22ece83 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 6e59c6d2557d..6155ccbbacac 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 274707e2d288..8391aff3c9f1 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 4e2e6015735b..27ab73c6b056 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 0bc0b4019c95..701ec03bc142 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 dbdab2c1ebb6..c283f5157617 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 96565069c988..dd2cc2b54267 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 7bce820e8680..1182435f4163 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 8a43339c1410..8e726708e1cd 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 17ef06746bfb..69e505905cf2 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 d9a5a903a8dd..dd584acbb34f 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_v