aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordavem <davem>2001-12-08 04:06:24 +0000
committerdavem <davem>2001-12-08 04:06:24 +0000
commit3e659fe9785aeefab6e52ddf25792edb922825b3 (patch)
tree643681a9741f7d2564e08ab3ab9b386491704b62
parente05f273d8e7f775168f501289c5139ae42fc87de (diff)
downloadnetdev-vger-cvs-3e659fe9785aeefab6e52ddf25792edb922825b3.tar.gz
Merge mainline to 2.4.17-pre6
-rw-r--r--Documentation/Changes5
-rw-r--r--Documentation/Configure.help168
-rw-r--r--Documentation/filesystems/Locking15
-rw-r--r--Documentation/pci.txt4
-rw-r--r--Documentation/sonypi.txt9
-rw-r--r--Makefile2
-rw-r--r--arch/alpha/kernel/smp.c3
-rw-r--r--arch/i386/boot/setup.S2
-rw-r--r--arch/i386/kernel/smp.c3
-rw-r--r--arch/ia64/kernel/smp.c3
-rw-r--r--arch/mips/kernel/smp.c3
-rw-r--r--arch/mips64/kernel/smp.c3
-rw-r--r--arch/ppc/kernel/smp.c3
-rw-r--r--arch/s390/kernel/smp.c3
-rw-r--r--arch/s390x/kernel/smp.c3
-rw-r--r--arch/sparc/kernel/smp.c3
-rw-r--r--arch/sparc64/kernel/smp.c3
-rw-r--r--drivers/atm/eni.c2
-rw-r--r--drivers/atm/firestream.c2
-rw-r--r--drivers/block/cciss.c2
-rw-r--r--drivers/block/paride/Config.in2
-rw-r--r--drivers/char/drm/Config.in1
-rw-r--r--drivers/char/drm/Makefile7
-rw-r--r--drivers/char/drm/drm.h4
-rw-r--r--drivers/char/drm/drm_context.h11
-rw-r--r--drivers/char/drm/sis.h56
-rw-r--r--drivers/char/drm/sis_drm.h36
-rw-r--r--drivers/char/drm/sis_drv.c74
-rw-r--r--drivers/char/drm/sis_drv.h45
-rw-r--r--drivers/char/drm/sis_ds.c406
-rw-r--r--drivers/char/drm/sis_ds.h163
-rw-r--r--drivers/char/drm/sis_mm.c307
-rw-r--r--drivers/char/joystick/cs461x.c2
-rw-r--r--drivers/char/joystick/emu10k1-gp.c2
-rw-r--r--drivers/char/joystick/pcigame.c2
-rw-r--r--drivers/char/mem.c46
-rw-r--r--drivers/char/serial.c2
-rw-r--r--drivers/char/sonypi.c8
-rw-r--r--drivers/char/sonypi.h2
-rw-r--r--drivers/ieee1394/ohci1394.c2
-rw-r--r--drivers/isdn/eicon/common.c4
-rw-r--r--drivers/isdn/eicon/eicon.h2
-rw-r--r--drivers/isdn/eicon/eicon_dsp.h2
-rw-r--r--drivers/isdn/eicon/eicon_idi.c4
-rw-r--r--drivers/isdn/eicon/eicon_idi.h2
-rw-r--r--drivers/isdn/eicon/eicon_io.c2
-rw-r--r--drivers/isdn/eicon/eicon_isa.c4
-rw-r--r--drivers/isdn/eicon/eicon_isa.h2
-rw-r--r--drivers/isdn/eicon/eicon_mod.c20
-rw-r--r--drivers/isdn/eicon/eicon_pci.c4
-rw-r--r--drivers/isdn/eicon/eicon_pci.h2
-rw-r--r--drivers/isdn/hisax/config.c2
-rw-r--r--drivers/isdn/hisax/hisax_fcpcipnp.c14
-rw-r--r--drivers/isdn/hisax/hisax_isac.c8
-rw-r--r--drivers/isdn/hisax/hisax_isac.h4
-rw-r--r--drivers/isdn/hisax/st5481_b.c4
-rw-r--r--drivers/isdn/hisax/st5481_d.c4
-rw-r--r--drivers/isdn/hisax/st5481_init.c2
-rw-r--r--drivers/isdn/hisax/st5481_usb.c6
-rw-r--r--drivers/isdn/hysdn/hysdn_procfs.c471
-rw-r--r--drivers/isdn/tpam/tpam_main.c2
-rw-r--r--drivers/media/radio/radio-gemtek-pci.c2
-rw-r--r--drivers/media/radio/radio-maxiradio.c2
-rw-r--r--drivers/media/video/bttv-driver.c2
-rw-r--r--drivers/media/video/meye.c2
-rw-r--r--drivers/net/3c59x.c2
-rw-r--r--drivers/net/8139cp.c2
-rw-r--r--drivers/net/8139too.c2
-rw-r--r--drivers/net/arcnet/com20020-pci.c2
-rw-r--r--drivers/net/defxx.c2
-rw-r--r--drivers/net/dl2k.c2
-rw-r--r--drivers/net/eepro100.c2
-rw-r--r--drivers/net/epic100.c2
-rw-r--r--drivers/net/fealnx.c2
-rw-r--r--drivers/net/ioc3-eth.c2
-rw-r--r--drivers/net/irda/vlsi_ir.c2
-rw-r--r--drivers/net/natsemi.c2
-rw-r--r--drivers/net/ne2k-pci.c2
-rw-r--r--drivers/net/ns83820.c2
-rw-r--r--drivers/net/pci-skeleton.c2
-rw-r--r--drivers/net/pcmcia/xircom_cb.c2
-rw-r--r--drivers/net/pcmcia/xircom_tulip_cb.c2
-rw-r--r--drivers/net/sis900.c2
-rw-r--r--drivers/net/starfire.c2
-rw-r--r--drivers/net/sundance.c2
-rw-r--r--drivers/net/sungem.c4
-rw-r--r--drivers/net/tlan.c2
-rw-r--r--drivers/net/tokenring/lanstreamer.c2
-rw-r--r--drivers/net/tokenring/olympic.c2
-rw-r--r--drivers/net/tulip/tulip_core.c2
-rw-r--r--drivers/net/via-rhine.c2
-rw-r--r--drivers/net/wan/farsync.c2
-rw-r--r--drivers/net/winbond-840.c2
-rw-r--r--drivers/net/wireless/airo.c2
-rw-r--r--drivers/net/wireless/orinoco_plx.c2
-rw-r--r--drivers/net/yellowfin.c2
-rw-r--r--drivers/parport/ChangeLog24
-rw-r--r--drivers/parport/daisy.c2
-rw-r--r--drivers/parport/ieee1284_ops.c41
-rw-r--r--drivers/parport/parport_pc.c17
-rw-r--r--drivers/parport/parport_serial.c2
-rw-r--r--drivers/pcmcia/pci_socket.c2
-rw-r--r--drivers/pcmcia/rsrc_mgr.c24
-rw-r--r--drivers/scsi/NCR5380.c1053
-rw-r--r--drivers/scsi/NCR5380.h110
-rw-r--r--drivers/scsi/scsi_scan.c2
-rw-r--r--drivers/sound/Config.in3
-rw-r--r--drivers/sound/Makefile1
-rw-r--r--drivers/sound/btaudio.c2
-rw-r--r--drivers/sound/emu10k1/main.c2
-rw-r--r--drivers/sound/ymfpci.c40
-rw-r--r--drivers/usb/uhci.c2
-rw-r--r--drivers/usb/usb-ohci.c2
-rw-r--r--drivers/usb/usb-uhci.c2
-rw-r--r--drivers/video/cyber2000fb.c2
-rw-r--r--drivers/video/imsttfb.c2
-rw-r--r--drivers/video/matrox/matroxfb_base.c1
-rw-r--r--drivers/video/radeonfb.c2
-rw-r--r--drivers/video/riva/fbdev.c2
-rw-r--r--drivers/video/tdfxfb.c2
-rw-r--r--fs/binfmt_elf.c72
-rw-r--r--fs/block_dev.c2
-rw-r--r--fs/buffer.c2
-rw-r--r--fs/dcache.c2
-rw-r--r--fs/exec.c2
-rw-r--r--fs/ext3/Makefile2
-rw-r--r--fs/ext3/acl.c17
-rw-r--r--fs/ext3/ialloc.c2
-rw-r--r--fs/ext3/inode.c52
-rw-r--r--fs/ext3/super.c14
-rw-r--r--fs/jbd/commit.c29
-rw-r--r--fs/jbd/journal.c120
-rw-r--r--fs/jbd/recovery.c17
-rw-r--r--fs/jbd/revoke.c2
-rw-r--r--fs/jbd/transaction.c17
-rw-r--r--fs/nfs/nfs3proc.c31
-rw-r--r--fs/nfs/pagelist.c2
-rw-r--r--fs/nfs/read.c3
-rw-r--r--fs/nfs/unlink.c2
-rw-r--r--fs/nfs/write.c52
-rw-r--r--include/linux/cache.h8
-rw-r--r--include/linux/ext3_fs.h37
-rw-r--r--include/linux/ext3_fs_i.h2
-rw-r--r--include/linux/ext3_jbd.h15
-rw-r--r--include/linux/init.h16
-rw-r--r--include/linux/jbd.h13
-rw-r--r--include/linux/list.h10
-rw-r--r--include/linux/mm.h3
-rw-r--r--include/linux/nfs_fs.h24
-rw-r--r--kernel/ptrace.c151
-rw-r--r--mm/filemap.c4
-rw-r--r--mm/highmem.c2
-rw-r--r--mm/memory.c181
-rw-r--r--mm/vmalloc.c38
154 files changed, 2601 insertions, 1743 deletions
diff --git a/Documentation/Changes b/Documentation/Changes
index 6dc50f50b..d4c8e8c31 100644
--- a/Documentation/Changes
+++ b/Documentation/Changes
@@ -53,7 +53,7 @@ o Gnu make 3.77 # make --version
o binutils 2.9.1.0.25 # ld -v
o util-linux 2.10o # fdformat --version
o modutils 2.4.2 # insmod -V
-o e2fsprogs 1.19 # tune2fs
+o e2fsprogs 1.25 # tune2fs
o reiserfsprogs 3.x.0j # reiserfsck 2>&1|grep reiserfsprogs
o pcmcia-cs 3.1.21 # cardmgr -V
o PPP 2.4.0 # pppd --version
@@ -317,8 +317,7 @@ o <ftp://rawhide.redhat.com/pub/rawhide/SRPMS/SRPMS/>
E2fsprogs
---------
-o <http://prdownloads.sourceforge.net/e2fsprogs/e2fsprogs-1.19.tar.gz>
-o <http://prdownloads.sourceforge.net/e2fsprogs/e2fsprogs-1.19-0.src.rpm>
+o <http://prdownloads.sourceforge.net/e2fsprogs/e2fsprogs-1.25.tar.gz>
Reiserfsprogs
-------------
diff --git a/Documentation/Configure.help b/Documentation/Configure.help
index 6ab6683c1..b5d4a2df7 100644
--- a/Documentation/Configure.help
+++ b/Documentation/Configure.help
@@ -2,7 +2,7 @@
# Eric S. Raymond <mailto:esr@thyrsus.com>
# Steven Cole <mailto:elenstev@mesatop.com>
#
-# Merged version 2.66: current with 2.4.17-pre2/2.5.1-pre5.
+# Merged version 2.67: current with 2.4.17-pre5/2.5.1-pre6.
#
# This version of the Linux kernel configuration help texts
# corresponds to kernel versions 2.4.x and 2.5.x.
@@ -341,7 +341,7 @@ CONFIG_NOHIGHMEM
"high memory".
If you are compiling a kernel which will never run on a machine with
- more than 1 Gigabyte total physical RAM, answer "off" here (default
+ more than 960 megabytes of total physical RAM, answer "off" here (default
choice and suitable for most users). This will result in a "3GB/1GB"
split: 3GB are mapped so that each process sees a 3GB virtual memory
space and the remaining part of the 4GB virtual memory space is used
@@ -358,10 +358,10 @@ CONFIG_NOHIGHMEM
processors (Pentium Pro and better). NOTE: If you say "64GB" here,
then the kernel will not boot on CPUs that don't support PAE!
- The actual amount of total physical memory will either be
- auto detected or can be forced by using a kernel command line option
- such as "mem=256M". (Try "man bootparam" or see the documentation of
- your boot loader (lilo or loadlin) about how to pass options to the
+ The actual amount of total physical memory will either be auto
+ detected or can be forced by using a kernel command line option such
+ as "mem=256M". (Try "man bootparam" or see the documentation of your
+ boot loader (grub, lilo or loadlin) about how to pass options to the
kernel at boot time.)
If unsure, say "off".
@@ -5206,6 +5206,14 @@ CONFIG_IPV6
It is safe to say N here for now.
+# 2.5 tree only
+IPv6: routing messages via old netlink
+CONFIG_IPV6_NETLINK
+ You can say Y here to receive routing messages from the IPv6 code
+ through the old netlink interface. However, a better option is to
+ say Y to "Kernel/User network link driver" and to "Routing
+ messages" instead.
+
Kernel httpd acceleration
CONFIG_KHTTPD
The kernel httpd acceleration daemon (kHTTPd) is a (limited) web
@@ -5959,6 +5967,34 @@ CONFIG_PACKET_MMAP
If unsure, say N.
+# 2.5 tree only
+Kernel/User network link driver
+CONFIG_NETLINK
+ This driver allows for two-way communication between the kernel and
+ user processes. It does so by creating a new socket family,
+ PF_NETLINK. Over this socket, the kernel can send and receive
+ datagrams carrying information. It is documented on many systems in
+ netlink(7).
+
+ So far, the kernel uses this feature to publish some network related
+ information if you say Y to "Routing messages", below. You also need
+ to say Y here if you want to use arpd, a daemon that helps keep the
+ internal ARP cache (a mapping between IP addresses and hardware
+ addresses on the local network) small. The ethertap device, which
+ lets user space programs read and write raw Ethernet frames, also
+ needs the network link driver.
+
+ If unsure, say Y.
+
+# 2.5 tree only
+Routing messages
+CONFIG_RTNETLINK
+ If you say Y here, user space programs can receive some network
+ related routing information over the netlink. 'rtmon', supplied
+ with the iproute2 package (<ftp://ftp.inr.ac.ru/>), can read and
+ interpret this data. Information sent to the kernel over this link
+ is ignored.
+
Netlink device emulation
CONFIG_NETLINK_DEV
This option will be removed soon. Any programs that want to use
@@ -8712,19 +8748,6 @@ CONFIG_PCMCIA_AXNET
a module, say M here and read <file:Documentation/modules.txt>. If
unsure, say N.
-Asix AX88190 PCMCIA support
-CONFIG_PCMCIA_AXNET
- Say Y here if you intend to attach an Asix AX88190-based PCMCIA
- (PC-card) Fast Ethernet card to your computer. These cards are
- nearly NE2000 compatible but need a separate driver due to a few
- misfeatures.
-
- This driver is also available as a module ( = code which can be
- inserted in and removed from the running kernel whenever you want).
- The module will be called axnet_cs.o. If you want to compile it as
- a module, say M here and read <file:Documentation/modules.txt>. If
- unsure, say N.
-
New Media PCMCIA support
CONFIG_PCMCIA_NMCLAN
Say Y here if you intend to attach a New Media Ethernet or LiveWire
@@ -13844,7 +13867,7 @@ CONFIG_EXT2_FS
Ext3 journalling file system support (EXPERIMENTAL)
CONFIG_EXT3_FS
This is the journalling version of the Second extended file system
- (often called ext3), the de facto standard Linux file system
+ (often called ext2), the de facto standard Linux file system
(method to organize files on a storage device) for hard disks.
The journalling code included in this driver means you do not have
@@ -13961,15 +13984,41 @@ CONFIG_CMS_FS
mainframe systems. Only the basic format is supported so far. If
you don't know what CMS is you probably don't want to know any more.
+# When the 2.5 version of configure.help goes away, the part of this that
+# duplicates Documentation/filesystems/tmpfs.txt can drop out.
Virtual memory file system support
CONFIG_TMPFS
Tmpfs is a file system which keeps all files in virtual memory.
-
Everything in tmpfs is temporary in the sense that no files will be
created on your hard drive. If you reboot, everything in tmpfs will
be lost.
- See <file:Documentation/filesystems/tmpfs.txt> for details
+ In contrast to RAM disks, which get allocated a fixed amount of
+ physical RAM, tmpfs grows and shrinks to accommodate the files it
+ contains and is able to swap unneeded pages out to swap space.
+
+ Everything is "virtual" in the sense that no files will be created
+ on your hard drive; if you reboot, everything in tmpfs will be
+ lost.
+
+ You should mount the file system somewhere to be able to use
+ POSIX shared memory. Adding the following line to /etc/fstab should
+ take care of things:
+
+ tmpfs /dev/shm tmpfs defaults 0 0
+
+ Remember to create the directory that you intend to mount tmpfs on
+ if necessary (/dev/shm is automagically created if you use devfs).
+
+ You can set limits for the number of blocks and inodes used by the
+ file system with the mount options "size", "nr_blocks" and
+ "nr_inodes". These parameters accept a suffix k, m or g for kilo,
+ mega and giga and can be changed on remount.
+
+ The initial permissions of the root directory can be set with the
+ mount option "mode".
+
+ See <file:Documentation/filesystems/tmpfs.txt> for details.
Simple RAM-based file system support
CONFIG_RAMFS
@@ -18846,6 +18895,26 @@ CONFIG_MIPS_UNCACHED
hardware debugging with a logic analyzer and need to see all traffic
on the bus.
+AU1000 serial console
+CONFIG_AU1000_SERIAL_CONSOLE
+ If you have an Alchemy AU1000 processor (MIPS based) and you want
+ to use a console on a serial port, say Y. Otherwise, say N.
+
+AU1000 serial support
+CONFIG_AU1000_UART
+ If you have an Alchemy AU1000 processor (MIPS based) and you want
+ to use serial ports, say Y. Otherwise, say N.
+
+AU1000 ethernet controller on SGI MIPS system
+CONFIG_MIPS_AU1000_ENET
+ If you have an Alchemy Semi AU1000 ethernet controller
+ on an SGI MIPS system, say Y. Otherwise, say N.
+
+WD93 SCSI Controller on SGI MIPS system
+CONFIG_SGIWD93_SCSI
+ If you have a Western Digital WD93 SCSI controller on
+ an SGI MIPS system, say Y. Otherwise, say N.
+
Magic System Request Key support
CONFIG_MAGIC_SYSRQ
If you say Y here, you will have some control over the system even
@@ -21467,7 +21536,7 @@ CONFIG_VIDEO_W9966
otherwise say N.
This driver is also available as a module (w9966.o).
- Check out <file:Documentation/video4linux/w9966.txt> and
+ Check out <file:drivers/media/video4linux/w9966.txt> and
<file:drivers/media/video/w9966.c> for more information.
CPiA Video For Linux
@@ -23586,6 +23655,42 @@ CONFIG_EFI_VARS
To use this option, you have to check that the "/proc file system
support" (CONFIG_PROC_FS) is enabled, too.
+Physical memory granularity (16 MB)
+CONFIG_IA64_GRANULE_16MB
+ IA64 identity-mapped regions use a large page size. We'll call such
+ large pages "granules". If you can think of a better name that's
+ unambiguous, let us know... Unless your identity-mapped regions are
+ very large, select a granule size of 16MB.
+
+Physical memory granularity (64 MB)
+CONFIG_IA64_GRANULE_64MB
+ IA64 identity-mapped regions use a large page size. We'll call such
+ large pages "granules". If you can think of a better name that's
+ unambiguous, let us know... Unless your identity-mapped regions are
+ very large, select a granule size of 16MB. (This is the "large" choice.)
+
+Enable SGI SN extra debugging code
+CONFIG_IA64_SGI_SN_DEBUG
+ Turns on extra debugging code in the SGI SN (Scalable NUMA) platform
+ for IA64. Unless you are debugging problems on an SGI SN IA64 box,
+ say N.
+
+Enable SGI Medusa Simulator Support
+CONFIG_IA64_SGI_SN_SIM
+ If you are compiling a kernel that will run under SGI's IA64
+ simulator (Medusa) then say Y, otherwise say N.
+
+PCIBA Support
+CONFIG_PCIBA
+ IRIX PCIBA-inspired user mode PCI interface for the SGI SN (Scalable
+ NUMA) platform for IA64. Unless you are compiling a kernel for an SGI SN IA64 box, say N.
+
+Enable protocol mode for the L1 console
+SERIAL_SGI_L1_PROTOCOL
+ Uses protocol mode instead of raw mode for the level 1 console on the
+ SGI SN (Scalable NUMA) platform for IA64. If you are compiling for
+ an SGI SN box then Y is the recommended value, otherwise say N.
+
Directly Connected Compact Flash support
CONFIG_CF_ENABLER
Compact Flash is a small, removable mass storage device introduced
@@ -23627,6 +23732,19 @@ CONFIG_DEBUG_SPINLOCK
best used in conjunction with the NMI watchdog so that spinlock
deadlocks are also debuggable.
+Read-write spinlock debugging
+CONFIG_DEBUG_RWLOCK
+ If you say Y here then read-write lock processing will count how many
+ times it has tried to get the lock and issue an error message after
+ too many attempts. If you suspect a rwlock problem or a kernel
+ hacker asks for this option then say Y. Otherwise say N.
+
+Semaphore debugging
+CONFIG_DEBUG_SEMAPHORE
+ If you say Y here then semaphore processing will issue lots of
+ verbose debugging messages. If you suspect a semaphore problem or a
+ kernel hacker asks for this option then say Y. Otherwise say N.
+
Verbose BUG() reporting (adds 70K)
CONFIG_DEBUG_BUGVERBOSE
Say Y here to make BUG() panics output the file name and line number
@@ -24042,10 +24160,10 @@ CONFIG_GDB_CONSOLE
# LocalWords: filesystems smbfs ATA ppp PCTech RZ www powerquest txt CMD ESDI
# LocalWords: chipset FB multicast MROUTE appletalk ifconfig IBMTR multiport
# LocalWords: Multisession STALDRV EasyIO EC EasyConnection ISTALLION ONboard
-# LocalWords: Brumby pci TNC cis ohio faq usenet dev hydra ca Tyne mem
+# LocalWords: Brumby pci TNC cis ohio faq usenet NETLINK dev hydra ca Tyne mem
# LocalWords: carleton DECstation SUNFD JENSEN Noname XXXM SLiRP LILO's amifb
# LocalWords: pppd Zilog ZS SRM bootloader ez mainmenu rarp ipfwadm paride pcd
-# LocalWords: mknod xos MTU lwared Macs netatalk macs cs Wolff
+# LocalWords: RTNETLINK mknod xos MTU lwared Macs netatalk macs cs Wolff
# LocalWords: dartmouth flowerpt MultiMaster FlashPoint tudelft etherexpress
# LocalWords: ICL EtherTeam ETH IDESCSI TXC SmartRAID SmartCache httpd sjc dlp
# LocalWords: thesphere TwoServers BOOTP DHCP ncpfs BPQETHER BPQ MG HIPPI cern
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 8e7276b35..c1d3e522b 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -123,6 +123,10 @@ prototypes:
int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
int (*bmap)(struct address_space *, long);
+ int (*flushpage) (struct page *, unsigned long);
+ int (*releasepage) (struct page *, int);
+ int (*direct_IO)(int, struct inode *, struct kiobuf *, unsigned long, int);
+
locking rules:
All may block
BKL PageLocked(page)
@@ -132,6 +136,8 @@ sync_page: no maybe
prepare_write: no yes
commit_write: no yes
bmap: yes
+flushpage: no yes
+releasepage: no yes
->prepare_write(), ->commit_write(), ->sync_page() and ->readpage()
may be called from the request handler (/dev/loop).
@@ -144,6 +150,15 @@ well-defined...
filesystems and by the swapper. The latter will eventually go away. All
instances do not actually need the BKL. Please, keep it that way and don't
breed new callers.
+ ->flushpage() is called when the filesystem must attempt to drop
+some or all of the buffers from the page when it is being truncated. It
+returns zero on success. If ->flushpage is zero, the kernel uses
+block_flushpage() instead.
+ ->releasepage() is called when the kernel is about to try to drop the
+buffers from the page in preparation for freeing it. It returns zero to
+indicate that the buffers are (or may be) freeable. If ->flushpage is zero,
+the kernel assumes that the fs has no private interest in the buffers.
+
Note: currently almost all instances of address_space methods are
using BKL for internal serialization and that's one of the worst sources
of contention. Normally they are calling library functions (in fs/buffer.c)
diff --git a/Documentation/pci.txt b/Documentation/pci.txt
index dadb9a9dc..5ac05854a 100644
--- a/Documentation/pci.txt
+++ b/Documentation/pci.txt
@@ -104,6 +104,10 @@ Tips:
If you are sure the driver is not a hotplug driver then use only
__init/exit __initdata/exitdata.
+ Pointers to functions marked as __devexit must be created using
+ __devexit_p(function_name). That will generate the function
+ name or NULL if the __devexit function will be discarded.
+
2. How to find PCI devices manually (the old style)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/Documentation/sonypi.txt b/Documentation/sonypi.txt
index 0d7314ce1..24d391c6b 100644
--- a/Documentation/sonypi.txt
+++ b/Documentation/sonypi.txt
@@ -58,6 +58,10 @@ where:
get enabled unless you set this parameter to 1.
Do not use this option unless it's actually necessary,
some Vaio models don't deal well with this option.
+ This option is available only if the kernel is
+ compiled without ACPI support (since it conflicts
+ with it and it shouldn't be required anyway if
+ ACPI is already enabled).
verbose: print unknown events from the sonypi device
@@ -93,7 +97,10 @@ Bugs:
- some users reported that the laptop speed is lower (dhrystone
tested) when using the driver with the fnkeyinit parameter. I cannot
reproduce it on my laptop and not all users have this problem.
- Still under investigation.
+ This happens because the fnkeyinit parameter enables the ACPI
+ mode (but without additionnal ACPI control, like processor
+ speed handling etc). Use ACPI instead of APM if it works on your
+ laptop.
- since all development was done by reverse engineering, there is
_absolutely no guarantee_ that this driver will not crash your
diff --git a/Makefile b/Makefile
index 3c1f52196..d0ed68b53 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 4
SUBLEVEL = 17
-EXTRAVERSION = -pre5
+EXTRAVERSION = -pre6
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index 33ca873c4..803397aaa 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -23,6 +23,7 @@
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/irq.h>
+#include <linux/cache.h>
#include <asm/hwrpb.h>
#include <asm/ptrace.h>
@@ -65,7 +66,7 @@ enum ipi_message_type {
IPI_CPU_STOP,
};
-spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
/* Set to a secondary's cpuid when it comes online. */
static unsigned long smp_secondary_alive;
diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S
index 0907ea962..dc6841590 100644
--- a/arch/i386/boot/setup.S
+++ b/arch/i386/boot/setup.S
@@ -539,7 +539,7 @@ done_apm_bios:
cmpw $0, %cs:realmode_swtch
jz rmodeswtch_normal
- lcall %cs:realmode_swtch
+ lcall *%cs:realmode_swtch
jmp rmodeswtch_end
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
index 5021c216d..d04a4306c 100644
--- a/arch/i386/kernel/smp.c
+++ b/arch/i386/kernel/smp.c
@@ -17,6 +17,7 @@
#include <linux/smp_lock.h>
#include <linux/kernel_stat.h>
#include <linux/mc146818rtc.h>
+#include <linux/cache.h>
#include <asm/mtrr.h>
#include <asm/pgalloc.h>
@@ -102,7 +103,7 @@
*/
/* The 'big kernel lock' */
-spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
struct tlb_state cpu_tlbstate[NR_CPUS] = {[0 ... NR_CPUS-1] = { &init_mm, 0 }};
diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c
index 8f6f1ffd0..9f7966c3b 100644
--- a/arch/ia64/kernel/smp.c
+++ b/arch/ia64/kernel/smp.c
@@ -30,6 +30,7 @@
#include <linux/kernel_stat.h>
#include <linux/mm.h>
#include <linux/delay.h>
+#include <linux/cache.h>
#include <asm/atomic.h>
#include <asm/bitops.h>
@@ -51,7 +52,7 @@
#include <asm/mca.h>
/* The 'big kernel lock' */
-spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
/*
* Structure and data for smp_call_function(). This is designed to minimise static memory
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index bcfdad667..48085d315 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -31,6 +31,7 @@
#include <linux/timex.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
+#include <linux/cache.h>
#include <asm/atomic.h>
#include <asm/processor.h>
@@ -52,7 +53,7 @@
/* Ze Big Kernel Lock! */
-spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
int smp_threads_ready; /* Not used */
int smp_num_cpus;
int global_irq_holder = NO_PROC_ID;
diff --git a/arch/mips64/kernel/smp.c b/arch/mips64/kernel/smp.c
index 86b338c05..e18cf01e7 100644
--- a/arch/mips64/kernel/smp.c
+++ b/arch/mips64/kernel/smp.c
@@ -5,6 +5,7 @@
#include <linux/time.h>
#include <linux/timex.h>
#include <linux/sched.h>
+#include <linux/cache.h>
#include <asm/atomic.h>
#include <asm/processor.h>
@@ -52,7 +53,7 @@ static void sendintr(int destid, unsigned char status)
#endif /* CONFIG_SGI_IP27 */
/* The 'big kernel lock' */
-spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
int smp_threads_ready; /* Not used */
atomic_t smp_commenced = ATOMIC_INIT(0);
struct cpuinfo_mips cpu_data[NR_CPUS];
diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
index b814ee640..a76cf7661 100644
--- a/arch/ppc/kernel/smp.c
+++ b/arch/ppc/kernel/smp.c
@@ -23,6 +23,7 @@
#include <linux/unistd.h>
#include <linux/init.h>
#include <linux/spinlock.h>
+#include <linux/cache.h>
#include <asm/ptrace.h>
#include <asm/atomic.h>
@@ -45,7 +46,7 @@ struct cpuinfo_PPC cpu_data[NR_CPUS];
struct klock_info_struct klock_info = { KLOCK_CLEAR, 0 };
atomic_t ipi_recv;
atomic_t ipi_sent;
-spinlock_t kernel_flag __cacheline_aligned = SPIN_LOCK_UNLOCKED;
+spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
unsigned int prof_multiplier[NR_CPUS];
unsigned int prof_counter[NR_CPUS];
cycles_t cacheflush_time;
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 0171e0d4c..6a836af79 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -29,6 +29,7 @@
#include <linux/smp_lock.h>
#include <linux/delay.h>
+#include <linux/cache.h>
#include <asm/sigp.h>
#include <asm/pgalloc.h>
@@ -55,7 +56,7 @@ cycles_t cacheflush_time=0;
int smp_threads_ready=0; /* Set when the idlers are all forked. */
static atomic_t smp_commenced = ATOMIC_INIT(0);
-spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
unsigned long cpu_online_map;
diff --git a/arch/s390x/kernel/smp.c b/arch/s390x/kernel/smp.c
index 21912c773..fe9593dbf 100644
--- a/arch/s390x/kernel/smp.c
+++ b/arch/s390x/kernel/smp.c
@@ -29,6 +29,7 @@
#include <linux/smp_lock.h>
#include <linux/delay.h>
+#include <linux/cache.h>
#include <asm/sigp.h>
#include <asm/pgalloc.h>
@@ -55,7 +56,7 @@ cycles_t cacheflush_time=0;
int smp_threads_ready=0; /* Set when the idlers are all forked. */
static atomic_t smp_commenced = ATOMIC_INIT(0);
-spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
unsigned long cpu_online_map;
diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c
index 7d272865b..bbe832d86 100644
--- a/arch/sparc/kernel/smp.c
+++ b/arch/sparc/kernel/smp.c
@@ -18,6 +18,7 @@
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/seq_file.h>
+#include <linux/cache.h>
#include <asm/ptrace.h>
#include <asm/atomic.h>
@@ -66,7 +67,7 @@ cycles_t cacheflush_time = 0; /* XXX */
*/
/* Kernel spinlock */
-spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
/* Used to make bitops atomic */
unsigned char bitops_spinlock = 0;
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 971bc1b8e..90cbdf108 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -17,6 +17,7 @@
#include <linux/spinlock.h>
#include <linux/fs.h>
#include <linux/seq_file.h>
+#include <linux/cache.h>
#include <asm/head.h>
#include <asm/ptrace.h>
@@ -49,7 +50,7 @@ static unsigned char boot_cpu_id = 0;
static int smp_activated = 0;
/* Kernel spinlock */
-spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
volatile int smp_processors_ready = 0;
unsigned long cpu_present_map = 0;
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
index 9ca723bb6..638e8d0ef 100644
--- a/drivers/atm/eni.c
+++ b/drivers/atm/eni.c
@@ -2310,7 +2310,7 @@ static struct pci_driver eni_driver = {
name: DEV_LABEL,
id_table: eni_pci_tbl,
probe: eni_init_one,
- remove: eni_remove_one,
+ remove: __devexit_p(eni_remove_one),
};
diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c
index a6a9046de..4db7ab6a3 100644
--- a/drivers/atm/firestream.c
+++ b/drivers/atm/firestream.c
@@ -2102,7 +2102,7 @@ static struct pci_driver firestream_driver = {
name: "firestream",
id_table: firestream_pci_tbl,
probe: firestream_init_one,
- remove: firestream_remove_one,
+ remove: __devexit_p(firestream_remove_one),
};
static int __init firestream_init_module (void)
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 9f9f2aee3..14fbe6ffb 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -2019,7 +2019,7 @@ static void __devexit cciss_remove_one (struct pci_dev *pdev)
static struct pci_driver cciss_pci_driver = {
name: "cciss",
probe: cciss_init_one,
- remove: cciss_remove_one,
+ remove: __devexit_p(cciss_remove_one),
id_table: cciss_pci_device_id, /* id_table */
};
diff --git a/drivers/block/paride/Config.in b/drivers/block/paride/Config.in
index e0aec10d9..eccb773ca 100644
--- a/drivers/block/paride/Config.in
+++ b/drivers/block/paride/Config.in
@@ -29,7 +29,7 @@ dep_tristate ' FIT TD-3000 protocol' CONFIG_PARIDE_FIT3 $CONFIG_PARIDE
dep_tristate ' Shuttle EPAT/EPEZ protocol' CONFIG_PARIDE_EPAT $CONFIG_PARIDE
if [ "$CONFIG_PARIDE_EPAT" != "n" ]; then
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- bool ' Support c7/c8 chips (EXPERIMENTAL)' CONFIG_PARIDE_EPATC8 $CONFIG_PARIDE
+ bool ' Support c7/c8 chips (EXPERIMENTAL)' CONFIG_PARIDE_EPATC8
fi
fi
diff --git a/drivers/char/drm/Config.in b/drivers/char/drm/Config.in
index 4936c6b3f..0cc3713d2 100644
--- a/drivers/char/drm/Config.in
+++ b/drivers/char/drm/Config.in
@@ -13,4 +13,5 @@ if [ "$CONFIG_DRM" != "n" ]; then
dep_tristate ' ATI Radeon' CONFIG_DRM_RADEON $CONFIG_AGP
dep_tristate ' Intel I810' CONFIG_DRM_I810 $CONFIG_AGP
dep_tristate ' Matrox g200/g400' CONFIG_DRM_MGA $CONFIG_AGP
+ dep_tristate ' SiS' CONFIG_DRM_SIS $CONFIG_AGP
fi
diff --git a/drivers/char/drm/Makefile b/drivers/char/drm/Makefile
index 819418eb5..f0656be88 100644
--- a/drivers/char/drm/Makefile
+++ b/drivers/char/drm/Makefile
@@ -3,7 +3,7 @@
# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
O_TARGET := drm.o
-list-multi := gamma.o tdfx.o r128.o mga.o i810.o radeon.o ffb.o
+list-multi := gamma.o tdfx.o r128.o mga.o i810.o radeon.o ffb.o sis.o
gamma-objs := gamma_drv.o gamma_dma.o
tdfx-objs := tdfx_drv.o
@@ -12,6 +12,7 @@ mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o
i810-objs := i810_drv.o i810_dma.o
radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o
ffb-objs := ffb_drv.o ffb_context.o
+sis-objs := sis_drv.o sis_ds.o sis_mm.o
obj-$(CONFIG_DRM_GAMMA) += gamma.o
obj-$(CONFIG_DRM_TDFX) += tdfx.o
@@ -20,6 +21,7 @@ obj-$(CONFIG_DRM_RADEON)+= radeon.o
obj-$(CONFIG_DRM_MGA) += mga.o
obj-$(CONFIG_DRM_I810) += i810.o
obj-$(CONFIG_DRM_FFB) += ffb.o
+obj-$(CONFIG_DRM_SIS) += sis.o
include $(TOPDIR)/Rules.make
@@ -43,3 +45,6 @@ radeon.o: $(radeon-objs) $(lib)
ffb.o: $(ffb-objs) $(lib)
$(LD) -r -o $@ $(ffb-objs) $(lib)
+
+sis.o: $(sis-objs) $(lib)
+ $(LD) -r -o $@ $(sis-objs) $(lib)
diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h
index ac9f407a7..362de2ccf 100644
--- a/drivers/char/drm/drm.h
+++ b/drivers/char/drm/drm.h
@@ -104,7 +104,7 @@ typedef struct drm_tex_region {
#include "i810_drm.h"
#include "r128_drm.h"
#include "radeon_drm.h"
-#ifdef CONFIG_DRM_SIS
+#if defined(CONFIG_DRM_SIS) || defined(CONFIG_DRM_SIS_MODULE)
#include "sis_drm.h"
#endif
@@ -483,7 +483,7 @@ typedef struct drm_scatter_gather {
#define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(0x4d, drm_radeon_indirect_t)
#define DRM_IOCTL_RADEON_TEXTURE DRM_IOWR(0x4e, drm_radeon_texture_t)
-#ifdef CONFIG_DRM_SIS
+#if defined(CONFIG_DRM_SIS) || defined(CONFIG_DRM_SIS_MODULE)
/* SiS specific ioctls */
#define SIS_IOCTL_FB_ALLOC DRM_IOWR(0x44, drm_sis_mem_t)
#define SIS_IOCTL_FB_FREE DRM_IOW( 0x45, drm_sis_mem_t)
diff --git a/drivers/char/drm/drm_context.h b/drivers/char/drm/drm_context.h
index 33d6112e3..e155946dc 100644
--- a/drivers/char/drm/drm_context.h
+++ b/drivers/char/drm/drm_context.h
@@ -27,6 +27,10 @@
* Authors:
* Rickard E. (Rik) Faith <faith@valinux.com>
* Gareth Hughes <gareth@valinux.com>
+ * ChangeLog:
+ * 2001-11-16 Torsten Duwe <duwe@caldera.de>
+ * added context constructor/destructor hooks,
+ * needed by SiS driver's memory management.
*/
#define __NO_VERSION__
@@ -316,6 +320,10 @@ int DRM(addctx)( struct inode *inode, struct file *filp,
/* Should this return -EBUSY instead? */
return -ENOMEM;
}
+#ifdef DRIVER_CTX_CTOR
+ if ( ctx.handle != DRM_KERNEL_CONTEXT )
+ DRIVER_CTX_CTOR(ctx.handle); /* XXX: also pass dev ? */
+#endif
if ( copy_to_user( (drm_ctx_t *)arg, &ctx, sizeof(ctx) ) )
return -EFAULT;
@@ -390,6 +398,9 @@ int DRM(rmctx)( struct inode *inode, struct file *filp,
priv->remove_auth_on_close = 1;
}
if ( ctx.handle != DRM_KERNEL_CONTEXT ) {
+#ifdef DRIVER_CTX_DTOR
+ DRIVER_CTX_DTOR(ctx.handle); /* XXX: also pass dev ? */
+#endif
DRM(ctxbitmap_free)( dev, ctx.handle );
}
diff --git a/drivers/char/drm/sis.h b/drivers/char/drm/sis.h
new file mode 100644
index 000000000..9903c0037
--- /dev/null
+++ b/drivers/char/drm/sis.h
@@ -0,0 +1,56 @@
+/* sis_drv.h -- Private header for sis driver -*- linux-c -*-
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/sis.h,v 1.1 2001/05/19 18:29:22 dawes Exp $ */
+
+#ifndef __SIS_H__
+#define __SIS_H__
+
+/* This remains constant for all DRM template files.
+ * Name it sisdrv_##x as there's a conflict with sis_free/malloc in the kernel
+ * that's used for fb devices
+ */
+#define DRM(x) sisdrv_##x
+
+/* General customization:
+ */
+#define __HAVE_AGP 1
+#define __MUST_HAVE_AGP 0
+#define __HAVE_MTRR 1
+#define __HAVE_CTX_BITMAP 1
+
+/* Buffer customization:
+ */
+#define DRIVER_AGP_BUFFERS_MAP( dev ) \
+ ((drm_sis_private_t *)((dev)->dev_private))->buffers
+
+extern int sis_init_context(int context);
+extern int sis_final_context(int context);
+
+#define DRIVER_CTX_CTOR sis_init_context
+#define DRIVER_CTX_DTOR sis_final_context
+
+#endif
diff --git a/drivers/char/drm/sis_drm.h b/drivers/char/drm/sis_drm.h
new file mode 100644
index 000000000..339ed5a00
--- /dev/null
+++ b/drivers/char/drm/sis_drm.h
@@ -0,0 +1,36 @@
+
+#ifndef _sis_drm_public_h_
+#define _sis_drm_public_h_
+
+typedef struct {
+ int context;
+ unsigned int offset;
+ unsigned int size;
+ unsigned int free;
+} drm_sis_mem_t;
+
+typedef struct {
+ unsigned int offset, size;
+} drm_sis_agp_t;
+
+typedef struct {
+ unsigned int left, right;
+} drm_sis_flip_t;
+
+#ifdef __KERNEL__
+
+int sis_fb_alloc(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg);
+int sis_fb_free(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg);
+
+int sisp_agp_init(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg);
+int sisp_agp_alloc(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg);
+int sisp_agp_free(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg);
+
+#endif
+
+#endif
diff --git a/drivers/char/drm/sis_drv.c b/drivers/char/drm/sis_drv.c
new file mode 100644
index 000000000..3dd83fd7e
--- /dev/null
+++ b/drivers/char/drm/sis_drv.c
@@ -0,0 +1,74 @@
+/* sis.c -- sis driver -*- linux-c -*-
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include <linux/config.h>
+#include "sis.h"
+#include "drmP.h"
+#include "sis_drm.h"
+#include "sis_drv.h"
+
+#define DRIVER_AUTHOR "SIS"
+#define DRIVER_NAME "sis"
+#define DRIVER_DESC "SIS 300/630/540"
+#define DRIVER_DATE "20010503"
+#define DRIVER_MAJOR 1
+#define DRIVER_MINOR 0
+#define DRIVER_PATCHLEVEL 0
+
+#define DRIVER_IOCTLS \
+ [DRM_IOCTL_NR(SIS_IOCTL_FB_ALLOC)] = { sis_fb_alloc, 1, 1 }, \
+ [DRM_IOCTL_NR(SIS_IOCTL_FB_FREE)] = { sis_fb_free, 1, 1 }, \
+ /* AGP Memory Management */ \
+ [DRM_IOCTL_NR(SIS_IOCTL_AGP_INIT)] = { sisp_agp_init, 1, 1 }, \
+ [DRM_IOCTL_NR(SIS_IOCTL_AGP_ALLOC)] = { sisp_agp_alloc, 1, 1 }, \
+ [DRM_IOCTL_NR(SIS_IOCTL_AGP_FREE)] = { sisp_agp_free, 1, 1 }
+#if 0 /* these don't appear to be defined */
+ /* SIS Stereo */
+ [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { sis_control, 1, 1 },
+ [DRM_IOCTL_NR(SIS_IOCTL_FLIP)] = { sis_flip, 1, 1 },
+ [DRM_IOCTL_NR(SIS_IOCTL_FLIP_INIT)] = { sis_flip_init, 1, 1 },
+ [DRM_IOCTL_NR(SIS_IOCTL_FLIP_FINAL)] = { sis_flip_final, 1, 1 }
+#endif
+
+#define __HAVE_COUNTERS 5
+
+#include "drm_auth.h"
+#include "drm_agpsupport.h"
+#include "drm_bufs.h"
+#include "drm_context.h"
+#include "drm_dma.h"
+#include "drm_drawable.h"
+#include "drm_drv.h"
+#include "drm_fops.h"
+#include "drm_init.h"
+#include "drm_ioctl.h"
+#include "drm_lists.h"
+#include "drm_lock.h"
+#include "drm_memory.h"
+#include "drm_proc.h"
+#include "drm_vm.h"
+#include "drm_stub.h"
diff --git a/drivers/char/drm/sis_drv.h b/drivers/char/drm/sis_drv.h
new file mode 100644
index 000000000..844e38b07
--- /dev/null
+++ b/drivers/char/drm/sis_drv.h
@@ -0,0 +1,45 @@
+/* sis_drv.h -- Private header for sis driver -*- linux-c -*-
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef _SIS_DRV_H_
+#define _SIS_DRV_H_
+
+typedef struct drm_sis_private {
+ drm_map_t *buffers;
+} drm_sis_private_t;
+
+/* Stereo ? - this was never committed */
+
+int sis_flip(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg);
+int sis_flip_init(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg);
+int sis_flip_final(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg);
+void flip_final(void);
+
+#endif
diff --git a/drivers/char/drm/sis_ds.c b/drivers/char/drm/sis_ds.c
new file mode 100644
index 000000000..6143ad83a
--- /dev/null
+++ b/drivers/char/drm/sis_ds.c
@@ -0,0 +1,406 @@
+/* sis_ds.c -- Private header for Direct Rendering Manager -*- linux-c -*-
+ * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw
+ *
+ * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Sung-Ching Lin <sclin@sis.com.tw>
+ *
+ */
+
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/poll.h>
+#include <asm/io.h>
+#include <linux/pci.h>
+
+#include "sis_ds.h"
+
+/* Set Data Structure, not check repeated value
+ * temporarily used
+ */
+
+set_t *setInit(void)
+{
+ int i;
+ set_t *set;
+
+ set = (set_t *)MALLOC(sizeof(set_t));
+ for(i = 0; i < SET_SIZE; i++){
+ set->list[i].free_next = i+1;
+ set->list[i].alloc_next = -1;
+ }
+ set->list[SET_SIZE-1].free_next = -1;
+ set->free = 0;
+ set->alloc = -1;
+ set->trace = -1;
+
+ return set;
+}
+
+int setAdd(set_t *set, ITEM_TYPE item)
+{
+ int free = set->free;
+
+ if(free != -1){
+ set->list[free].val = item;
+ set->free = set->list[free].free_next;
+ }
+ else{
+ return 0;
+ }
+
+ set->list[free].alloc_next = set->alloc;
+ set->alloc = free;
+ set->list[free].free_next = -1;
+
+ return 1;
+}
+
+int setDel(set_t *set, ITEM_TYPE item)
+{
+ int alloc = set->alloc;
+ int prev = -1;
+
+ while(alloc != -1){
+ if(set->list[alloc].val == item){
+ if(prev != -1)
+ set->list[prev].alloc_next = set->list[alloc].alloc_next;
+ else
+ set->alloc = set->list[alloc].alloc_next;
+ break;
+ }
+ prev = alloc;
+ alloc = set->list[alloc].alloc_next;
+ }
+
+ if(alloc == -1)
+ return 0;
+
+ set->list[alloc].free_next = set->free;
+ set->free = alloc;
+ set->list[alloc].alloc_next = -1;
+
+ return 1;
+}
+
+/* setFirst -> setAdd -> setNext is wrong */
+
+int setFirst(set_t *set, ITEM_TYPE *item)
+{
+ if(set->alloc == -1)
+ return 0;
+
+ *item = set->list[set->alloc].val;
+ set->trace = set->list[set->alloc].alloc_next;
+
+ return 1;
+}
+
+int setNext(set_t *set, ITEM_TYPE *item)
+{
+ if(set->trace == -1)
+ return 0;
+
+ *item = set->list[set->trace].val;
+ set->trace = set->list[set->trace].alloc_next;
+
+ return 1;
+}
+
+int setDestroy(set_t *set)
+{
+ FREE(set);
+
+ return 1;
+}
+
+/*
+ * GLX Hardware Device Driver common code
+ * Copyright (C) 1999 Keith Whitwell
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#define ISFREE(bptr) ((bptr)->free)
+
+#define PRINTF(fmt, arg...) do{}while(0)
+#define fprintf(fmt, arg...) do{}while(0)
+
+static void *calloc(size_t nmemb, size_t size)
+{
+ void *addr;
+ addr = kmalloc(nmemb*size, GFP_KERNEL);
+ memset(addr, 0, nmemb*size);
+ return addr;
+}
+#define free(n) kfree(n)
+
+void mmDumpMemInfo( memHeap_t *heap )
+{
+ TMemBlock *p;
+
+ PRINTF ("Memory heap %p:\n", heap);
+ if (heap == 0) {
+ PRINTF (" heap == 0\n");
+ } else {
+ p = (TMemBlock *)heap;
+ while (p) {
+ PRINTF (" Offset:%08x, Size:%08x, %c%c\n",p->ofs,p->size,
+ p->free ? '.':'U',
+ p->reserved ? 'R':'.');
+ p = p->next;
+ }
+ }
+ PRINTF ("End of memory blocks\n");
+}
+
+memHeap_t *mmInit(int ofs,
+ int size)
+{
+ PMemBlock blocks;
+
+ if (size <= 0) {
+ return 0;
+ }
+ blocks = (TMemBlock *) calloc(1,sizeof(TMemBlock));
+ if (blocks) {
+ blocks->ofs = ofs;
+ blocks->size = size;
+ blocks->free = 1;
+ return (memHeap_t *)blocks;
+ } else
+ return 0;
+}
+
+/* Kludgey workaround for existing i810 server. Remove soon.
+ */
+memHeap_t *mmAddRange( memHeap_t *heap,
+ int ofs,
+ int size )
+{
+ PMemBlock blocks;
+ blocks = (TMemBlock *) calloc(2,sizeof(TMemBlock));
+ if (blocks) {
+ blocks[0].size = size;
+ blocks[0].free = 1;
+ blocks[0].ofs = ofs;
+ blocks[0].next = &blocks[1];
+
+ /* Discontinuity - stops JoinBlock from trying to join non-adjacent
+ * ranges.
+ */
+ blocks[1].size = 0;
+ blocks[1].free = 0;
+ blocks[1].ofs = ofs+size;
+ blocks[1].next = (PMemBlock) heap;
+ return (memHeap_t *)blocks;
+ }
+ else
+ return heap;
+}
+
+static TMemBlock* SliceBlock(TMemBlock *p,
+ int startofs, int size,
+ int reserved, int alignment)
+{
+ TMemBlock *newblock;
+
+ /* break left */
+ if (startofs > p->ofs) {
+ newblock = (TMemBlock*) calloc(1,sizeof(TMemBlock));
+ newblock->ofs = startofs;
+ newblock->size = p->size - (startofs - p->ofs);
+ newblock->free = 1;
+ newblock->next = p->next;
+ p->size -= newblock->size;
+ p->next = newblock;
+ p = newblock;
+ }
+
+ /* break right */
+ if (size < p->size) {
+ newblock = (TMemBlock*) calloc(1,sizeof(TMemBlock));
+ newblock->ofs = startofs + size;
+ newblock->size = p->size - size;
+ newblock->free = 1;
+ newblock->next = p->next;
+ p->size = size;
+ p->next = newblock;
+ }
+
+ /* p = middle block */
+ p->align = alignment;
+ p->free = 0;
+ p->reserved = reserved;
+ return p;
+}
+
+PMemBlock mmAllocMem( memHeap_t *heap, int size, int align2, int startSearch)
+{
+ int mask,startofs,endofs;
+ TMemBlock *p;
+
+ if (!heap || align2 < 0 || size <= 0)
+ return NULL;
+ mask = (1 << align2)-1;
+ startofs = 0;
+ p = (TMemBlock *)heap;
+ while (p) {
+ if (ISFREE(p)) {
+ startofs = (p->ofs + mask) & ~mask;
+ if ( startofs < startSearch ) {
+ startofs = startSearch;
+ }
+ endofs = startofs+size;
+ if (endofs <= (p->ofs+p->size))
+ break;
+ }
+ p = p->next;
+ }
+ if (!p)
+ return NULL;
+ p = SliceBlock(p,startofs,size,0,mask+1);
+ p->heap = heap;
+ return p;
+}
+
+static __inline__ int Join2Blocks(TMemBlock *p)
+{
+ if (p->free && p->next && p->next->free) {
+ TMemBlock *q = p->next;
+ p->size += q->size;
+ p->next = q->next;
+ free(q);
+ return 1;
+ }
+ return 0;
+}
+
+int mmFreeMem(PMemBlock b)
+{
+ TMemBlock *p,*prev;
+
+ if (!b)
+ return 0;
+ if (!b->heap) {
+ fprintf(stderr, "no heap\n");
+ return -1;
+ }
+ p = b->heap;
+ prev = NULL;
+ while (p && p != b) {
+ prev = p;
+ p = p->next;
+ }
+ if (!p || p->free || p->reserved) {
+ if (!p)
+ fprintf(stderr, "block not found in heap\n");
+ else if (p->free)
+ fprintf(stderr, "block already free\n");
+ else
+ fprintf(stderr, "block is reserved\n");
+ return -1;
+ }
+ p->free = 1;
+ Join2Blocks(p);
+ if (prev)
+ Join2Blocks(prev);
+ return 0;
+}
+
+int mmReserveMem(memHeap_t *heap, int offset,int size)
+{
+ int endofs;
+ TMemBlock *p;
+
+ if (!heap || size <= 0)
+ return -1;
+ endofs = offset+size;
+ p = (TMemBlock *)heap;
+ while (p && p->ofs <= offset) {
+ if (ISFREE(p) && endofs <= (p->ofs+p->size)) {
+ SliceBlock(p,offset,size,1,1);
+ return 0;
+ }
+ p = p->next;
+ }
+ return -1;
+}
+
+int mmFreeReserved(memHeap_t *heap, int offset)
+{
+ TMemBlock *p,*prev;
+
+ if (!heap)
+ return -1;
+ p = (TMemBlock *)heap;
+ prev = NULL;
+ while (p && p->ofs != offset) {
+ prev = p;
+ p = p->next;
+ }
+ if (!p || !p->reserved)
+ return -1;
+ p->free = 1;
+ p->reserved = 0;
+ Join2Blocks(p);
+ if (prev)
+ Join2Blocks(prev);
+ return 0;
+}
+
+void mmDestroy(memHeap_t *heap)
+{
+ TMemBlock *p,*q;
+
+ if (!heap)
+ return;
+ p = (TMemBlock *)heap;
+ while (p) {
+ q = p->next;
+ free(p);
+ p = q;
+ }
+}
diff --git a/drivers/char/drm/sis_ds.h b/drivers/char/drm/sis_ds.h
new file mode 100644
index 000000000..c3367dba7
--- /dev/null
+++ b/drivers/char/drm/sis_ds.h
@@ -0,0 +1,163 @@
+/* sis_ds.h -- Private header for Direct Rendering Manager -*- linux-c -*-
+ * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw
+ *
+ * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Sung-Ching Lin <sclin@sis.com.tw>
+ *
+ */
+
+#ifndef _sis_ds_h_
+#define _sis_ds_h_
+
+/* Set Data Structure */
+
+#define SET_SIZE 5000
+#define MALLOC(s) kmalloc(s, GFP_KERNEL)
+#define FREE(s) kfree(s)
+
+typedef unsigned int ITEM_TYPE;
+
+typedef struct {
+ ITEM_TYPE val;
+ int alloc_next, free_next;
+} list_item_t;
+
+typedef struct {
+ int alloc;
+ int free;
+ int trace;
+ list_item_t list[SET_SIZE];
+} set_t;
+
+set_t *setInit(void);
+int setAdd(set_t *set, ITEM_TYPE item);
+int setDel(set_t *set, ITEM_TYPE item);
+int setFirst(set_t *set, ITEM_TYPE *item);
+int setNext(set_t *set, ITEM_TYPE *item);
+int setDestroy(set_t *set);
+
+#endif
+
+/*
+ * GLX Hardware Device Driver common code
+ * Copyright (C) 1999 Keith Whitwell
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef MM_INC
+#define MM_INC
+
+struct mem_block_t {
+ struct mem_block_t *next;
+ struct mem_block_t *heap;
+ int ofs,size;
+ int align;
+ int free:1;
+ int reserved:1;
+};
+typedef struct mem_block_t TMemBlock;
+typedef struct mem_block_t *PMemBlock;
+
+/* a heap is just the first block in a chain */
+typedef struct mem_block_t memHeap_t;
+
+static __inline__ int mmBlockSize(PMemBlock b)
+{ return b->size; }
+
+static __inline__ int mmOffset(PMemBlock b)
+{ return b->ofs; }
+
+static __inline__ void mmMarkReserved(PMemBlock b)
+{ b->reserved = 1; }
+
+/*
+ * input: total size in bytes
+ * return: a heap pointer if OK, NULL if error
+ */
+memHeap_t *mmInit( int ofs, int size );
+
+
+
+memHeap_t *mmAddRange( memHeap_t *heap,
+ int ofs,
+ int size );
+
+
+/*
+ * Allocate 'size' bytes with 2^align2 bytes alignment,
+ * restrict the search to free memory after 'startSearch'
+ * depth and back buffers should be in different 4mb banks
+ * to get better page hits if possible
+ * input: size = size of block
+ * align2 = 2^align2 bytes alignment
+ * startSearch = linear offset from start of heap to begin search
+ * return: pointer to the allocated block, 0 if error
+ */
+PMemBlock mmAllocMem( memHeap_t *heap, int size, int align2, int startSearch );
+
+/*
+ * Free block starts at offset
+ * input: pointer to a block
+ * return: 0 if OK, -1 if error
+ */
+int mmFreeMem( PMemBlock b );
+
+/*
+ * Reserve 'size' bytes block start at offset
+ * This is used to prevent allocation of memory already used
+ * by the X server for the front buffer, pixmaps, and cursor
+ * input: size, offset
+ * output: 0 if OK, -1 if error
+ */
+int mmReserveMem( memHeap_t *heap, int offset,int size );
+int mmFreeReserved( memHeap_t *heap, int offset );
+
+/*
+ * destroy MM
+ */
+void mmDestroy( memHeap_t *mmInit );
+
+/* For debuging purpose. */
+void mmDumpMemInfo( memHeap_t *mmInit );
+
+#endif
diff --git a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c
new file mode 100644
index 000000000..81832769d
--- /dev/null
+++ b/drivers/char/drm/sis_mm.c
@@ -0,0 +1,307 @@
+/* sis_mm.c -- Private header for Direct Rendering Manager -*- linux-c -*-
+ * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw
+ *
+ * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Sung-Ching Lin <sclin@sis.com.tw>
+ *
+ */
+
+#define __NO_VERSION__
+#include "sis.h"
+#include <linux/sisfb.h>
+#include "drmP.h"
+#include "sis_drm.h"
+#include "sis_drv.h"
+#include "sis_ds.h"
+
+#define MAX_CONTEXT 100
+#define VIDEO_TYPE 0
+#define AGP_TYPE 1
+
+typedef struct {
+ int used;
+ int context;
+ set_t *sets[2]; /* 0 for video, 1 for AGP */
+} sis_context_t;
+
+static sis_context_t global_ppriv[MAX_CONTEXT];
+
+static int add_alloc_set(int context, int type, unsigned int val)
+{
+ int i, retval = 0;
+
+ for(i = 0; i < MAX_CONTEXT; i++)
+ if(global_ppriv[i].used && global_ppriv[i].context == context){
+ retval = setAdd(global_ppriv[i].sets[type], val);
+ break;
+ }
+ return retval;
+}
+
+static int del_alloc_set(int context, int type, unsigned int val)
+{
+ int i, retval = 0;
+ for(i = 0; i < MAX_CONTEXT; i++)
+ if(global_ppriv[i].used && global_ppriv[i].context == context){
+ retval = setDel(global_ppriv[i].sets[type], val);
+ break;
+ }
+ return retval;
+}
+
+/* fb management via fb device */
+#if 1
+int sis_fb_alloc(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_sis_mem_t fb;
+ struct sis_memreq req;
+ int retval = 0;
+
+ if (copy_from_user(&fb, (drm_sis_mem_t *)arg, sizeof(fb)))
+ return -EFAULT;
+
+ req.size = fb.size;
+ sis_malloc(&req);
+ if(req.offset){
+ /* TODO */
+ fb.offset = req.offset;
+ fb.free = req.offset;
+ if(!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)){
+ DRM_DEBUG("adding to allocation set fails\n");
+ sis_free(req.offset);
+ retval = -1;
+ }
+ }
+ else{
+ fb.offset = 0;
+ fb.size = 0;
+ fb.free = 0;
+ }
+
+ if (copy_to_user((drm_sis_mem_t *)arg, &fb, sizeof(fb))) return -EFAULT;
+
+ DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb.size, req.offset);
+
+ return retval;
+}
+
+int sis_fb_free(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_sis_mem_t fb;
+ int retval = 0;
+
+ if (copy_from_user(&fb, (drm_sis_mem_t *)arg, sizeof(fb)))
+ return -EFAULT;
+
+ if(!fb.free){
+ return -1;
+ }
+
+ sis_free(fb.free);
+ if(!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
+ retval = -1;
+
+ DRM_DEBUG("free fb, offset = %d\n", fb.free);
+
+ return retval;
+}
+
+#else
+
+int sis_fb_alloc(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ return -1;
+}
+
+int sis_fb_free(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ return 0;
+}
+
+#endif
+
+/* agp memory management */
+#if 1
+
+static memHeap_t *AgpHeap = NULL;
+
+int sisp_agp_init(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_sis_agp_t agp;
+
+ if (copy_from_user(&agp, (drm_sis_agp_t *)arg, sizeof(agp)))
+ return -EFAULT;
+
+ AgpHeap = mmInit(agp.offset, agp.size);
+
+ DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size);
+
+ return 0;
+}
+
+int sisp_agp_alloc(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_sis_mem_t agp;
+ PMemBlock block;
+ int retval = 0;
+
+ if(!AgpHeap)
+ return -1;
+
+ if (copy_from_user(&agp, (drm_sis_mem_t *)arg, sizeof(agp)))
+ return -EFAULT;
+
+ block = mmAllocMem(AgpHeap, agp.size, 0, 0);
+ if(block){
+ /* TODO */
+ agp.offset = block->ofs;
+ agp.free = (unsigned int)block;
+ if(!add_alloc_set(agp.context, AGP_TYPE, agp.free)){
+ DRM_DEBUG("adding to allocation set fails\n");
+ mmFreeMem((PMemBlock)agp.free);
+ retval = -1;
+ }
+ }
+ else{
+ agp.offset = 0;
+ agp.size = 0;
+ agp.free = 0;
+ }
+
+ if (copy_to_user((drm_sis_mem_t *)arg, &agp, sizeof(agp))) return -EFAULT;
+
+ DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size, agp.offset);
+
+ return retval;
+}
+
+int sisp_agp_free(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_sis_mem_t agp;
+ int retval = 0;
+
+ if(!AgpHeap)
+ return -1;
+
+ if (copy_from_user(&agp, (drm_sis_mem_t *)arg, sizeof(agp)))
+ return -EFAULT;
+
+ if(!agp.free){
+ return -1;
+ }
+
+ mmFreeMem((PMemBlock)agp.free);
+ if(!del_alloc_set(agp.context, AGP_TYPE, agp.free))
+ retval = -1;
+
+ DRM_DEBUG("free agp, free = %d\n", agp.free);
+
+ return retval;
+}
+
+#endif
+
+int sis_init_context(int context)
+{
+ int i;
+
+ for(i = 0; i < MAX_CONTEXT ; i++)
+ if(global_ppriv[i].used && (global_ppriv[i].context == context))
+ break;
+
+ if(i >= MAX_CONTEXT){
+ for(i = 0; i < MAX_CONTEXT ; i++){
+ if(!global_ppriv[i].used){
+ global_ppriv[i].context = context;
+ global_ppriv[i].used = 1;
+ global_ppriv[i].sets[0] = setInit();
+ global_ppriv[i].sets[1] = setInit();
+ DRM_DEBUG("init allocation set, socket=%d, context = %d\n",
+ i, context);
+ break;
+ }
+ }
+ if((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) ||
+ (global_ppriv[i].sets[1] == NULL)){
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+int sis_final_context(int context)
+{
+ int i;
+
+ for(i=0; i<MAX_CONTEXT; i++)
+ if(global_ppriv[i].used && (global_ppriv[i].context == context))
+ break;
+
+ if(i < MAX_CONTEXT){
+ set_t *set;
+ unsigned int item;
+ int retval;
+
+ DRM_DEBUG("find socket %d, context = %d\n", i, context);
+
+ /* Video Memory */
+ set = global_ppriv[i].sets[0];
+ retval = setFirst(set, &item);
+ while(retval){
+ DRM_DEBUG("free video memory 0x%x\n", item);
+ sis_free(item);
+ retval = setNext(set, &item);
+ }
+ setDestroy(set);
+
+ /* AGP Memory */
+ set = global_ppriv[i].sets[1];
+ retval = setFirst(set, &item);
+ while(retval){
+ DRM_DEBUG("free agp memory 0x%x\n", item);
+ mmFreeMem((PMemBlock)item);
+ retval = setNext(set, &item);
+ }
+ setDestroy(set);
+
+ global_ppriv[i].used = 0;
+ }
+
+ /* turn-off auto-flip */
+ /* TODO */
+#if defined(SIS_STEREO)
+ flip_final();
+#endif
+
+ return 1;
+}
diff --git a/drivers/char/joystick/cs461x.c b/drivers/char/joystick/cs461x.c
index 7116b3453..6b096f0fe 100644
--- a/drivers/char/joystick/cs461x.c
+++ b/drivers/char/joystick/cs461x.c
@@ -313,7 +313,7 @@ static struct pci_driver cs461x_pci_driver = {
name: "PCI Gameport",
id_table: cs461x_pci_tbl,
probe: cs461x_pci_probe,
- remove: cs461x_pci_remove,
+ remove: __devexit_p(cs461x_pci_remove),
};
int __init js_cs461x_init(void)
diff --git a/drivers/char/joystick/emu10k1-gp.c b/drivers/char/joystick/emu10k1-gp.c
index 2489b11c6..4763a02c7 100644
--- a/drivers/char/joystick/emu10k1-gp.c
+++ b/drivers/char/joystick/emu10k1-gp.c
@@ -108,7 +108,7 @@ static struct pci_driver emu_driver = {
name: "Emu10k1 Gameport",
id_table: emu_tbl,
probe: emu_probe,
- remove: emu_remove,
+ remove: __devexit_p(emu_remove),
};
int __init emu_init(void)
diff --git a/drivers/char/joystick/pcigame.c b/drivers/char/joystick/pcigame.c
index 04e1bee04..194814ca6 100644
--- a/drivers/char/joystick/pcigame.c
+++ b/drivers/char/joystick/pcigame.c
@@ -180,7 +180,7 @@ static struct pci_driver pcigame_driver = {
name: "pcigame",
id_table: pcigame_id_table,
probe: pcigame_probe,
- remove: pcigame_remove,
+ remove: __devexit_p(pcigame_remove),
};
int __init pcigame_init(void)
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 14f29671b..4f303001c 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -272,6 +272,8 @@ static ssize_t read_kmem(struct file *file, char *buf,
return virtr + read;
}
+extern long vwrite(char *buf, char *addr, unsigned long count);
+
/*
* This function writes to the *virtual* memory as seen by the kernel.
*/
@@ -279,12 +281,46 @@ static ssize_t write_kmem(struct file * file, const char * buf,
size_t count, loff_t *ppos)
{
unsigned long p = *ppos;
+ ssize_t wrote = 0;
+ ssize_t virtr = 0;
+ char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
- if (p >= (unsigned long) high_memory)
- return 0;
- if (count > (unsigned long) high_memory - p)
- count = (unsigned long) high_memory - p;
- return do_write_mem(file, (void*)p, p, buf, count, ppos);
+ if (p < (unsigned long) high_memory) {
+ wrote = count;
+ if (count > (unsigned long) high_memory - p)
+ wrote = (unsigned long) high_memory - p;
+
+ wrote = do_write_mem(file, (void*)p, p, buf, wrote, ppos);
+
+ p += wrote;
+ buf += wrote;
+ count -= wrote;
+ }
+
+ if (count > 0) {
+ kbuf = (char *)__get_free_page(GFP_KERNEL);
+ if (!kbuf)
+ return -ENOMEM;
+ while (count > 0) {
+ int len = count;
+
+ if (len > PAGE_SIZE)
+ len = PAGE_SIZE;
+ if (len && copy_from_user(kbuf, buf, len)) {
+ free_page((unsigned long)kbuf);
+ return -EFAULT;
+ }
+ len = vwrite(kbuf, (char *)p, len);
+ count -= len;
+ buf += len;
+ virtr += len;
+ p += len;
+ }
+ free_page((unsigned long)kbuf);
+ }
+
+ *ppos = p;
+ return virtr + wrote;
}
#if !defined(__mc68000__)
diff --git a/drivers/char/serial.c b/drivers/char/serial.c
index d680bfd72..adbe3ffa8 100644
--- a/drivers/char/serial.c
+++ b/drivers/char/serial.c
@@ -4892,7 +4892,7 @@ MODULE_DEVICE_TABLE(pci, serial_pci_tbl);
static struct pci_driver serial_pci_driver = {
name: "serial",
probe: serial_init_one,
- remove: serial_remove_one,
+ remove: __devexit_p(serial_remove_one),
id_table: serial_pci_tbl,
};
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index ae4cd8890..92bc9c5c4 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -617,8 +617,11 @@ static int __devinit sonypi_probe(struct pci_dev *pcidev) {
goto out3;
}
+#if !defined(CONFIG_ACPI)
+ /* Enable ACPI mode to get Fn key events */
if (fnkeyinit)
outb(0xf0, 0xb2);
+#endif
if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
sonypi_type2_srs();
@@ -666,6 +669,11 @@ static void __devexit sonypi_remove(void) {
sonypi_type2_dis();
else
sonypi_type1_dis();
+#if !defined(CONFIG_ACPI)
+ /* disable ACPI mode */
+ if (fnkeyinit)
+ outb(0xf1, 0xb2);
+#endif
free_irq(sonypi_device.irq, sonypi_irq);
release_region(sonypi_device.ioport1, sonypi_device.region_size);
misc_deregister(&sonypi_misc_device);
diff --git a/drivers/char/sonypi.h b/drivers/char/sonypi.h
index 4385b3c5a..9d8360860 100644
--- a/drivers/char/sonypi.h
+++ b/drivers/char/sonypi.h
@@ -35,7 +35,7 @@
#ifdef __KERNEL__
#define SONYPI_DRIVER_MAJORVERSION 1
-#define SONYPI_DRIVER_MINORVERSION 7
+#define SONYPI_DRIVER_MINORVERSION 8
#include <linux/types.h>
#include <linux/pci.h>
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index 94200f895..970ec27a7 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -2374,7 +2374,7 @@ static struct pci_driver ohci1394_driver = {
name: OHCI1394_DRIVER_NAME,
id_table: ohci1394_pci_tbl,
probe: ohci1394_add_one,
- remove: ohci1394_remove_one,
+ remove: __devexit_p(ohci1394_remove_one),
};
static void __exit ohci1394_cleanup (void)
diff --git a/drivers/isdn/eicon/common.c b/drivers/isdn/eicon/common.c
index f2b4d0452..77d3a50b9 100644
--- a/drivers/isdn/eicon/common.c
+++ b/drivers/isdn/eicon/common.c
@@ -808,7 +808,9 @@ void DivasDoDpc(void *pData)
while(i--)
{
- DivaDoCardDpc(card++);
+ if (card->state == DIA_RUNNING)
+ DivaDoCardDpc(card);
+ card++;
}
}
diff --git a/drivers/isdn/eicon/eicon.h b/drivers/isdn/eicon/eicon.h
index 77f90cbb8..cd7466596 100644
--- a/drivers/isdn/eicon/eicon.h
+++ b/drivers/isdn/eicon/eicon.h
@@ -1,4 +1,4 @@
-/* $Id: eicon.h,v 1.23.6.5 2001/09/23 22:24:37 kai Exp $
+/* $Id: eicon.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
*
* ISDN low-level module for Eicon active ISDN-Cards.
*
diff --git a/drivers/isdn/eicon/eicon_dsp.h b/drivers/isdn/eicon/eicon_dsp.h
index 2ccfeb0fb..8cac8ffa8 100644
--- a/drivers/isdn/eicon/eicon_dsp.h
+++ b/drivers/isdn/eicon/eicon_dsp.h
@@ -1,4 +1,4 @@
-/* $Id: eicon_dsp.h,v 1.7.6.1 2001/09/23 22:24:37 kai Exp $
+/* $Id: eicon_dsp.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
*
* ISDN lowlevel-module for Eicon active cards.
* DSP definitions
diff --git a/drivers/isdn/eicon/eicon_idi.c b/drivers/isdn/eicon/eicon_idi.c
index b44cc2ba6..5c6f2ac38 100644
--- a/drivers/isdn/eicon/eicon_idi.c
+++ b/drivers/isdn/eicon/eicon_idi.c
@@ -1,4 +1,4 @@
-/* $Id: eicon_idi.c,v 1.41.6.4 2001/11/06 20:58:29 kai Exp $
+/* $Id: eicon_idi.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
*
* ISDN lowlevel-module for Eicon active cards.
* IDI interface
@@ -25,7 +25,7 @@
#undef EICON_FULL_SERVICE_OKTETT
-char *eicon_idi_revision = "$Revision: 1.41.6.4 $";
+char *eicon_idi_revision = "$Revision: 1.1.4.1 $";
eicon_manifbuf *manbuf;
diff --git a/drivers/isdn/eicon/eicon_idi.h b/drivers/isdn/eicon/eicon_idi.h
index c0cab657b..eefa56eb4 100644
--- a/drivers/isdn/eicon/eicon_idi.h
+++ b/drivers/isdn/eicon/eicon_idi.h
@@ -1,4 +1,4 @@
-/* $Id: eicon_idi.h,v 1.11.6.1 2001/09/23 22:24:37 kai Exp $
+/* $Id: eicon_idi.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
*
* ISDN lowlevel-module for the Eicon active cards.
* IDI-Interface
diff --git a/drivers/isdn/eicon/eicon_io.c b/drivers/isdn/eicon/eicon_io.c
index ff61c5f10..cfbded538 100644
--- a/drivers/isdn/eicon/eicon_io.c
+++ b/drivers/isdn/eicon/eicon_io.c
@@ -1,4 +1,4 @@
-/* $Id: eicon_io.c,v 1.13.6.2 2001/09/23 22:24:37 kai Exp $
+/* $Id: eicon_io.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
*
* ISDN low-level module for Eicon active ISDN-Cards.
* Code for communicating with hardware.
diff --git a/drivers/isdn/eicon/eicon_isa.c b/drivers/isdn/eicon/eicon_isa.c
index a925d1f3e..e5ae07744 100644
--- a/drivers/isdn/eicon/eicon_isa.c
+++ b/drivers/isdn/eicon/eicon_isa.c
@@ -1,4 +1,4 @@
-/* $Id: eicon_isa.c,v 1.16.6.2 2001/11/06 20:58:29 kai Exp $
+/* $Id: eicon_isa.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
*
* ISDN low-level module for Eicon active ISDN-Cards.
* Hardware-specific code for old ISA cards.
@@ -20,7 +20,7 @@
#define release_shmem release_region
#define request_shmem request_region
-char *eicon_isa_revision = "$Revision: 1.16.6.2 $";
+char *eicon_isa_revision = "$Revision: 1.1.4.1 $";
#undef EICON_MCA_DEBUG
diff --git a/drivers/isdn/eicon/eicon_isa.h b/drivers/isdn/eicon/eicon_isa.h
index 7502aabec..9379af626 100644
--- a/drivers/isdn/eicon/eicon_isa.h
+++ b/drivers/isdn/eicon/eicon_isa.h
@@ -1,4 +1,4 @@
-/* $Id: eicon_isa.h,v 1.10.6.1 2001/09/23 22:24:37 kai Exp $
+/* $Id: eicon_isa.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
*
* ISDN low-level module for Eicon active ISDN-Cards.
*
diff --git a/drivers/isdn/eicon/eicon_mod.c b/drivers/isdn/eicon/eicon_mod.c
index b7c0adb47..ea424191e 100644
--- a/drivers/isdn/eicon/eicon_mod.c
+++ b/drivers/isdn/eicon/eicon_mod.c
@@ -1,4 +1,4 @@
-/* $Id: eicon_mod.c,v 1.37.6.6 2001/09/23 22:24:37 kai Exp $
+/* $Id: eicon_mod.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
*
* ISDN lowlevel-module for Eicon active cards.
*
@@ -44,7 +44,7 @@
static eicon_card *cards = (eicon_card *) NULL; /* glob. var , contains
start of card-list */
-static char *eicon_revision = "$Revision: 1.37.6.6 $";
+static char *eicon_revision = "$Revision: 1.1.4.1 $";
extern char *eicon_pci_revision;
extern char *eicon_isa_revision;
@@ -1550,7 +1550,7 @@ int eicon_mca_find_card(int type, /* type-idx of eicon-card */
};
};
/* all adapter flavors checked without match, finito with: */
- return ENODEV;
+ return -ENODEV;
};
@@ -1597,14 +1597,14 @@ int eicon_mca_probe(int slot, /* slot-nr where the card was detected */
membase = cards_membase;
} else {
if (membase != cards_membase)
- return ENODEV;
+ return -ENODEV;
};
cards_irq=irq_array[((adf_pos0 & 0xC)>>2)];
if (irq == -1) {
irq = cards_irq;
} else {
if (irq != cards_irq)
- return ENODEV;
+ return -ENODEV;
};
cards_io= 0xC00 + ((adf_pos0>>4)*0x10);
type = EICON_CTYPE_ISAPRI;
@@ -1616,14 +1616,14 @@ int eicon_mca_probe(int slot, /* slot-nr where the card was detected */
membase = cards_membase;
} else {
if (membase != cards_membase)
- return ENODEV;
+ return -ENODEV;
};
cards_irq=irq_array[((adf_pos0 & 0xC)>>2)];
if (irq == -1) {
irq = cards_irq;
} else {
if (irq != cards_irq)
- return ENODEV;
+ return -ENODEV;
};
cards_io= 0xC00 + ((adf_pos0>>4)*0x10);
@@ -1637,12 +1637,12 @@ int eicon_mca_probe(int slot, /* slot-nr where the card was detected */
irq = cards_irq;
} else {
if (irq != cards_irq)
- return ENODEV;
+ return -ENODEV;
};
type = 0;
break;
default:
- return ENODEV;
+ return -ENODEV;
};
/* matching membase & irq */
if ( 1 == eicon_addcard(type, membase, irq, id, 0)) {
@@ -1661,7 +1661,7 @@ int eicon_mca_probe(int slot, /* slot-nr where the card was detected */
cards->mca_slot+1);
return 0 ; /* eicon_addcard added a card */
} else {
- return ENODEV;
+ return -ENODEV;
};
};
#endif /* CONFIG_MCA */
diff --git a/drivers/isdn/eicon/eicon_pci.c b/drivers/isdn/eicon/eicon_pci.c
index 69c0a0b79..d1dba2d5c 100644
--- a/drivers/isdn/eicon/eicon_pci.c
+++ b/drivers/isdn/eicon/eicon_pci.c
@@ -1,4 +1,4 @@
-/* $Id: eicon_pci.c,v 1.15.6.3 2001/09/23 22:24:37 kai Exp $
+/* $Id: eicon_pci.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
*
* ISDN low-level module for Eicon active ISDN-Cards.
* Hardware-specific code for PCI cards.
@@ -24,7 +24,7 @@
#include "adapter.h"
#include "uxio.h"
-char *eicon_pci_revision = "$Revision: 1.15.6.3 $";
+char *eicon_pci_revision = "$Revision: 1.1.4.1 $";
#if CONFIG_PCI /* intire stuff is only for PCI */
#ifdef CONFIG_ISDN_DRV_EICON_PCI
diff --git a/drivers/isdn/eicon/eicon_pci.h b/drivers/isdn/eicon/eicon_pci.h
index 7e615c6f3..d87c8cacf 100644
--- a/drivers/isdn/eicon/eicon_pci.h
+++ b/drivers/isdn/eicon/eicon_pci.h
@@ -1,4 +1,4 @@
-/* $Id: eicon_pci.h,v 1.6.6.1 2001/09/23 22:24:37 kai Exp $
+/* $Id: eicon_pci.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
*
* ISDN low-level module for Eicon active ISDN-Cards (PCI part).
*
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index c056dc334..bc098205d 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -485,7 +485,7 @@ static int __init HiSax_setup(char *line)
if (strlen(str) < HISAX_IDSIZE)
strcpy(HiSaxID, str);
else
- printk(KERN_WARNING "HiSax: ID too long!")
+ printk(KERN_WARNING "HiSax: ID too long!");
} else
strcpy(HiSaxID, "HiSax");
diff --git a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c
index 479e18fa8..a8359bb81 100644
--- a/drivers/isdn/hisax/hisax_fcpcipnp.c
+++ b/drivers/isdn/hisax/hisax_fcpcipnp.c
@@ -533,7 +533,7 @@ static inline void hdlc_xpr_irq(struct fritz_bcs *bcs)
dev_kfree_skb_irq(skb);
}
-static void hdlc_irq(struct fritz_bcs *bcs, u32 stat)
+static void hdlc_irq_one(struct fritz_bcs *bcs, u32 stat)
{
DBG(0x10, "ch%d stat %#x", bcs->channel, stat);
if (stat & HDLC_INT_RPR) {
@@ -550,7 +550,7 @@ static void hdlc_irq(struct fritz_bcs *bcs, u32 stat)
}
}
-static inline void hdlc_interrupt(struct fritz_adapter *adapter)
+static inline void hdlc_irq(struct fritz_adapter *adapter)
{
int nr;
u32 stat;
@@ -559,7 +559,7 @@ static inline void hdlc_interrupt(struct fritz_adapter *adapter)
stat = adapter->read_hdlc_status(adapter, nr);
DBG(0x10, "HDLC %c stat %#x", 'A' + nr, stat);
if (stat & HDLC_INT_MASK)
- hdlc_irq(&adapter->bcs[nr], stat);
+ hdlc_irq_one(&adapter->bcs[nr], stat);
}
}
@@ -642,10 +642,10 @@ static void fcpci2_irq(int intno, void *dev, struct pt_regs *regs)
return;
DBG(2, "STATUS0 %#x", val);
if (val & AVM_STATUS0_IRQ_ISAC)
- isacsx_interrupt(&adapter->isac);
+ isacsx_irq(&adapter->isac);
if (val & AVM_STATUS0_IRQ_HDLC)
- hdlc_interrupt(adapter);
+ hdlc_irq(adapter);
}
static void fcpci_irq(int intno, void *dev, struct pt_regs *regs)
@@ -659,10 +659,10 @@ static void fcpci_irq(int intno, void *dev, struct pt_regs *regs)
return;
DBG(2, "sval %#x", sval);
if (!(sval & AVM_STATUS0_IRQ_ISAC))
- isac_interrupt(&adapter->isac);
+ isac_irq(&adapter->isac);
if (!(sval & AVM_STATUS0_IRQ_HDLC))
- hdlc_interrupt(adapter);
+ hdlc_irq(adapter);
}
// ----------------------------------------------------------------------
diff --git a/drivers/isdn/hisax/hisax_isac.c b/drivers/isdn/hisax/hisax_isac.c
index 9a6a5065b..29a96edf3 100644
--- a/drivers/isdn/hisax/hisax_isac.c
+++ b/drivers/isdn/hisax/hisax_isac.c
@@ -601,7 +601,7 @@ static inline void isac_exi_interrupt(struct isac *isac)
}
}
-void isac_interrupt(struct isac *isac)
+void isac_irq(struct isac *isac)
{
unsigned char val;
@@ -741,7 +741,7 @@ static inline void isacsx_icd_interrupt(struct isac *isac)
}
}
-void isacsx_interrupt(struct isac *isac)
+void isacsx_irq(struct isac *isac)
{
unsigned char val;
@@ -887,10 +887,10 @@ EXPORT_SYMBOL(isac_init);
EXPORT_SYMBOL(isac_d_l2l1);
EXPORT_SYMBOL(isacsx_setup);
-EXPORT_SYMBOL(isacsx_interrupt);
+EXPORT_SYMBOL(isacsx_irq);
EXPORT_SYMBOL(isac_setup);
-EXPORT_SYMBOL(isac_interrupt);
+EXPORT_SYMBOL(isac_irq);
module_init(hisax_isac_init);
module_exit(hisax_isac_exit);
diff --git a/drivers/isdn/hisax/hisax_isac.h b/drivers/isdn/hisax/hisax_isac.h
index 6b8d2dfa0..08890cf4d 100644
--- a/drivers/isdn/hisax/hisax_isac.h
+++ b/drivers/isdn/hisax/hisax_isac.h
@@ -37,9 +37,9 @@ void isac_init(struct isac *isac);
void isac_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg);
void isac_setup(struct isac *isac);
-void isac_interrupt(struct isac *isac);
+void isac_irq(struct isac *isac);
void isacsx_setup(struct isac *isac);
-void isacsx_interrupt(struct isac *isac);
+void isacsx_irq(struct isac *isac);
#endif
diff --git a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c
index 17b2a4325..0aa033579 100644
--- a/drivers/isdn/hisax/st5481_b.c
+++ b/drivers/isdn/hisax/st5481_b.c
@@ -275,7 +275,7 @@ static int __devinit st5481_setup_b_out(struct st5481_bcs *bcs)
usb_b_out_complete, bcs);
}
-static void __devexit st5481_release_b_out(struct st5481_bcs *bcs)
+static void st5481_release_b_out(struct st5481_bcs *bcs)
{
struct st5481_b_out *b_out = &bcs->b_out;
@@ -316,7 +316,7 @@ int __devinit st5481_setup_b(struct st5481_bcs *bcs)
/*
* Release buffers and URBs for the B channels
*/
-void __devexit st5481_release_b(struct st5481_bcs *bcs)
+void st5481_release_b(struct st5481_bcs *bcs)
{
DBG(4,"");
diff --git a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c
index ce751cc46..1079bae6e 100644
--- a/drivers/isdn/hisax/st5481_d.c
+++ b/drivers/isdn/hisax/st5481_d.c
@@ -673,7 +673,7 @@ static int __devinit st5481_setup_d_out(struct st5481_adapter *adapter)
usb_d_out_complete, adapter);
}
-static void __devexit st5481_release_d_out(struct st5481_adapter *adapter)
+static void st5481_release_d_out(struct st5481_adapter *adapter)
{
struct st5481_d_out *d_out = &adapter->d_out;
@@ -723,7 +723,7 @@ int __devinit st5481_setup_d(struct st5481_adapter *adapter)
return retval;
}
-void __devexit st5481_release_d(struct st5481_adapter *adapter)
+void st5481_release_d(struct st5481_adapter *adapter)
{
DBG(2,"");
diff --git a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c
index 28ea25bf5..8aad86d9d 100644
--- a/drivers/isdn/hisax/st5481_init.c
+++ b/drivers/isdn/hisax/st5481_init.c
@@ -178,7 +178,7 @@ MODULE_DEVICE_TABLE (usb, st5481_ids);
static struct usb_driver st5481_usb_driver = {
name: "st5481_usb",
probe: probe_st5481,
- disconnect: disconnect_st5481,
+ disconnect: __devexit_p(disconnect_st5481),
id_table: st5481_ids,
};
diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c
index 859c164f5..a3098071f 100644
--- a/drivers/isdn/hisax/st5481_usb.c
+++ b/drivers/isdn/hisax/st5481_usb.c
@@ -307,7 +307,7 @@ int __devinit st5481_setup_usb(struct st5481_adapter *adapter)
* Release buffers and URBs for the interrupt and control
* endpoint.
*/
-void __devexit st5481_release_usb(struct st5481_adapter *adapter)
+void st5481_release_usb(struct st5481_adapter *adapter)
{
struct st5481_intr *intr = &adapter->intr;
struct st5481_ctrl *ctrl = &adapter->ctrl;
@@ -443,7 +443,7 @@ st5481_setup_isocpipes(struct urb* urb[2], struct usb_device *dev,
return retval;
}
-void __devexit st5481_release_isocpipes(struct urb* urb[2])
+void st5481_release_isocpipes(struct urb* urb[2])
{
int j;
@@ -547,7 +547,7 @@ int __devinit st5481_setup_in(struct st5481_in *in)
return retval;
}
-void __devexit st5481_release_in(struct st5481_in *in)
+void st5481_release_in(struct st5481_in *in)
{
DBG(2,"");
diff --git a/drivers/isdn/hysdn/hysdn_procfs.c b/drivers/isdn/hysdn/hysdn_procfs.c
deleted file mode 100644
index 39c7bd8a8..000000000
--- a/drivers/isdn/hysdn/hysdn_procfs.c
+++ /dev/null
@@ -1,471 +0,0 @@
-/* $Id: hysdn_procfs.c,v 1.1 2000/02/10 19:45:18 werner Exp $
-
- * Linux driver for HYSDN cards, /proc/net filesystem log functions.
- * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH
- *
- * Copyright 1999 by Werner Cornelius (werner@titro.de)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * 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.
- *
- * $Log: hysdn_procfs.c,v $
- * Revision 1.1 2000/02/10 19:45:18 werner
- *
- * Initial release
- *
- *
- */
-
-#define __NO_VERSION__
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/poll.h>
-#include <linux/proc_fs.h>
-#include <linux/pci.h>
-#include <linux/smp_lock.h>
-
-#include "hysdn_defs.h"
-
-static char *hysdn_procfs_revision = "$Revision: 1.1 $";
-
-#define INFO_OUT_LEN 80 /* length of info line including lf */
-
-/*************************************************/
-/* structure keeping ascii log for device output */
-/*************************************************/
-struct log_data {
- struct log_data *next;
- ulong usage_cnt; /* number of files still to work */
- void *proc_ctrl; /* pointer to own control procdata structure */
- char log_start[2]; /* log string start (final len aligned by size) */
-};
-
-/**********************************************/
-/* structure holding proc entrys for one card */
-/**********************************************/
-struct procdata {
- struct proc_dir_entry *log; /* log entry */
- char log_name[15]; /* log filename */
- struct log_data *log_head, *log_tail; /* head and tail for queue */
- int if_used; /* open count for interface */
- wait_queue_head_t rd_queue;
-};
-
-/********************************************/
-/* put an log buffer into the log queue. */
-/* This buffer will be kept until all files */
-/* opened for read got the contents. */
-/* Flushes buffers not longer in use. */
-/********************************************/
-void
-put_log_buffer(hysdn_card * card, char *cp)
-{
- struct log_data *ib;
- struct procdata *pd = card->procfs;
- int flags;
-
- if (!pd)
- return;
- if (!cp)
- return;
- if (!*cp)
- return;
- if (pd->if_used <= 0)
- return; /* no open file for read */
-
- if (!(ib = (struct log_data *) kmalloc(sizeof(struct log_data) + strlen(cp), GFP_ATOMIC)))
- return; /* no memory */
- strcpy(ib->log_start, cp); /* set output string */
- ib->next = NULL;
- ib->proc_ctrl = pd; /* point to own control structure */
- save_flags(flags);
- cli();
- ib->usage_cnt = pd->if_used;
- if (!pd->log_head)
- pd->log_head = ib; /* new head */
- else
- pd->log_tail->next = ib; /* follows existing messages */
- pd->log_tail = ib; /* new tail */
- restore_flags(flags);
-
- /* delete old entrys */
- while (pd->log_head->next) {
- if ((pd->log_head->usage_cnt <= 0) &&
- (pd->log_head->next->usage_cnt <= 0)) {
- ib = pd->log_head;
- pd->log_head = pd->log_head->next;
- kfree(ib);
- } else
- break;
- } /* pd->log_head->next */
- wake_up_interruptible(&(pd->rd_queue)); /* announce new entry */
-} /* put_log_buffer */
-
-
-/**********************************/
-/* log file operations and tables */
-/**********************************/
-
-/****************************************/
-/* write log file -> set log level bits */
-/****************************************/
-static ssize_t
-hysdn_log_write(struct file *file, const char *buf, size_t count, loff_t * off)
-{
- int retval;
- hysdn_card *card = (hysdn_card *) file->private_data;
-
- if (&file->f_pos != off) /* fs error check */
- return (-ESPIPE);
-
- if ((retval = pof_boot_write(card, buf, count)) < 0)
- retval = -EFAULT; /* an error occurred */
-
- return (retval);
-} /* hysdn_log_write */
-
-/******************/
-/* read log file */
-/******************/
-static ssize_t
-hysdn_log_read(struct file *file, char *buf, size_t count, loff_t * off)
-{
- struct log_data *inf;
- int len;
- word ino;
- struct procdata *pd;
- hysdn_card *card;
-
- if (!*((struct log_data **) file->private_data)) {
- if (file->f_flags & O_NONBLOCK)
- return (-EAGAIN);
-
- /* sorry, but we need to search the card */
- ino = file->f_dentry->d_inode->i_ino & 0xFFFF; /* low-ino */
- card = card_root;
- while (card) {
- pd = card->procfs;
- if (pd->log->low_ino == ino)
- break;
- card = card->next; /* search next entry */
- }
- if (card)
- interruptible_sleep_on(&(pd->rd_queue));
- else
- return (-EAGAIN);
-
- }
- if (!(inf = *((struct log_data **) file->private_data)))
- return (0);
-
- inf->usage_cnt--; /* new usage count */
- (struct log_data **) file->private_data = &inf->next; /* next structure */
- if ((len = strlen(inf->log_start)) <= count) {
- if (copy_to_user(buf, inf->log_start, len))
- return -EFAULT;
- file->f_pos += len;
- return (len);
- }
- return (0);
-} /* hysdn_log_read */
-
-/******************/
-/* open log file */
-/******************/
-static int
-hysdn_log_open(struct inode *ino, struct file *filep)
-{
- hysdn_card *card;
- struct procdata *pd;
- ulong flags;
-
- lock_kernel();
- card = card_root;
- while (card) {
- pd = card->procfs;
- if (pd->log->low_ino == (ino->i_ino & 0xFFFF))
- break;
- card = card->next; /* search next entry */
- }
- if (!card) {
- unlock_kernel();
- return (-ENODEV); /* device is unknown/invalid */
- }
- filep->private_data = card; /* remember our own card */
-
- if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
- /* write only access -> boot pof data */
- if (pof_boot_open(card)) {
- unlock_kernel();
- return (-EPERM); /* no permission this time */
- }
- } else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
-
- /* read access -> log/debug read */
- save_flags(flags);
- cli();
- pd->if_used++;
- if (pd->log_head)
- (struct log_data **) filep->private_data = &(pd->log_tail->next);
- else
- (struct log_data **) filep->private_data = &(pd->log_head);
- restore_flags(flags);
-
- } else { /* simultaneous read/write access forbidden ! */
- unlock_kernel();
- return (-EPERM); /* no permission this time */
- }
- unlock_kernel();
- return (0);
-} /* hysdn_log_open */
-
-/*******************************************************************************/
-/* close a cardlog file. If the file has been opened for exclusive write it is */
-/* assumed as pof data input and the pof loader is noticed about. */
-/* Otherwise file is handled as log output. In this case the interface usage */
-/* count is decremented and all buffers are noticed of closing. If this file */
-/* was the last one to be closed, all buffers are freed. */
-/*******************************************************************************/
-static int
-hysdn_log_close(struct inode *ino, struct file *filep)
-{
- struct log_data *inf;
- struct procdata *pd;
- hysdn_card *card;
- int flags, retval = 0;
-
- lock_kernel();
- if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
- /* write only access -> write debug completely written */
- retval = 0; /* success */
- } else {
- /* read access -> log/debug read, mark one further file as closed */
-
- pd = NULL;
- save_flags(flags);
- cli();
- inf = *((struct log_data **) filep->private_data); /* get first log entry */
- if (inf)
- pd = (struct procdata *) inf->proc_ctrl; /* still entries there */
- else {
- /* no info available -> search card */
- card = card_root;
- while (card) {
- pd = card->procfs;
- if (pd->log->low_ino == (ino->i_ino & 0xFFFF))
- break;
- card = card->next; /* search next entry */
- }
- if (card)
- pd = card->procfs; /* pointer to procfs ctrl */
- }
- if (pd)
- pd->if_used--; /* decrement interface usage count by one */
-
- while (inf) {
- inf->usage_cnt--; /* decrement usage count for buffers */
- inf = inf->next;
- }
- restore_flags(flags);
-
- if (pd)
- if (pd->if_used <= 0) /* delete buffers if last file closed */
- while (pd->log_head) {
- inf = pd->log_head;
- pd->log_head = pd->log_head->next;
- kfree(inf);
- }
- } /* read access */
-
- unlock_kernel();
- return (retval);
-} /* hysdn_log_close */
-
-/*************************************************/
-/* select/poll routine to be able using select() */
-/*************************************************/
-static unsigned int
-hysdn_log_poll(struct file *file, poll_table * wait)
-{
- unsigned int mask = 0;
- word ino;
- hysdn_card *card;
- struct procdata *pd;
-
- if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE)
- return (mask); /* no polling for write supported */
-
- /* we need to search the card */
- ino = file->f_dentry->d_inode->i_ino & 0xFFFF; /* low-ino */
- card = card_root;
- while (card) {
- pd = card->procfs;
- if (pd->log->low_ino == ino)
- break;
- card = card->next; /* search next entry */
- }
- if (!card)
- return (mask); /* card not found */
-
- poll_wait(file, &(pd->rd_queue), wait);
-
- if (*((struct log_data **) file->private_data))
- mask |= POLLIN | POLLRDNORM;
-
- return mask;
-} /* hysdn_log_poll */
-
-/**************************************************/
-/* table for log filesystem functions defined above. */
-/**************************************************/
-static struct file_operations log_fops =
-{
- llseek: no_llseek,
- read: hysdn_log_read,
- write: hysdn_log_write,
- poll: hysdn_log_poll,
- open: hysdn_log_open,
- release: hysdn_log_close,
-};
-
-/*****************************************/
-/* Output info data to the cardinfo file */
-/*****************************************/
-static int
-info_read(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
-{
- char tmp[INFO_OUT_LEN * 11 + 2];
- int i;
- char *cp;
- hysdn_card *card;
-
- sprintf(tmp, "id bus slot type irq iobase plx-mem dp-mem boot device");
- cp = tmp; /* start of string */
- while (*cp)
- cp++;
- while (((cp - tmp) % (INFO_OUT_LEN + 1)) != INFO_OUT_LEN)
- *cp++ = ' ';
- *cp++ = '\n';
-
- card = card_root; /* start of list */
- while (card) {
- sprintf(cp, "%d %3d %4d %4d %3d 0x%04x 0x%08x 0x%08x",
- card->myid,
- card->bus,
- PCI_SLOT(card->devfn),
- card->brdtype,
- card->irq,
- card->iobase,
- card->plxbase,
- card->membase);
- card = card->next;
- while (*cp)
- cp++;
- while (((cp - tmp) % (INFO_OUT_LEN + 1)) != INFO_OUT_LEN)
- *cp++ = ' ';
- *cp++ = '\n';
- }
-
- i = cp - tmp;
- *start = buffer;
- if (offset + length > i) {
- length = i - offset;
- *eof = 1;
- } else if (offset > i) {
- length = 0;
- *eof = 1;
- }
- cp = tmp + offset;
-
- if (length > 0) {
- /* start_bh_atomic(); */
- memcpy(buffer, cp, length);
- /* end_bh_atomic(); */
- return length;
- }
- return 0;
-} /* info_read */
-
-/*****************************/
-/* hysdn subdir in /proc/net */
-/*****************************/
-static struct proc_dir_entry *hysdn_proc_entry = NULL;
-static struct proc_dir_entry *hysdn_info_entry = NULL;
-
-/***************************************************************************************/
-/* hysdn_procfs_init is called when the module is loaded and after the cards have been */
-/* detected. The needed proc dir and card entries are created. */
-/***************************************************************************************/
-int
-hysdn_procfs_init(void)
-{
- struct procdata *pd;
- hysdn_card *card;
-
- hysdn_proc_entry = create_proc_entry(PROC_SUBDIR_NAME, S_IFDIR | S_IRUGO | S_IXUGO, proc_net);
- if (!hysdn_proc_entry) {
- printk(KERN_ERR "HYSDN: unable to create hysdn subdir\n");
- return (-1);
- }
- hysdn_info_entry = create_proc_entry("cardinfo", 0, hysdn_proc_entry);
- if (hysdn_info_entry)
- hysdn_info_entry->read_proc = info_read; /* read info function */
-
- /* create all cardlog proc entries */
-
- card = card_root; /* start with first card */
- while (card) {
- if ((pd = (struct procdata *) kmalloc(sizeof(struct procdata), GFP_KERNEL)) != NULL) {
- memset(pd, 0, sizeof(struct procdata));
-
- sprintf(pd->log_name, "%s%d", PROC_LOG_BASENAME, card->myid);
- if ((pd->log = create_proc_entry(pd->log_name, S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry)) != NULL) {
- pd->log->proc_fops = &log_fops; /* set new operations table */
- pd->log->owner = THIS_MODULE;
- }
-
- init_waitqueue_head(&(pd->rd_queue));
-
- card->procfs = (void *) pd; /* remember procfs structure */
- }
- card = card->next; /* point to next card */
- }
-
- printk(KERN_NOTICE "HYSDN: procfs Rev. %s initialised\n", hysdn_getrev(hysdn_procfs_revision));
- return (0);
-} /* hysdn_procfs_init */
-
-/***************************************************************************************/
-/* hysdn_procfs_release is called when the module is unloaded and before the cards */
-/* resources are released. The module counter is assumed to be 0 ! */
-/***************************************************************************************/
-void
-hysdn_procfs_release(void)
-{
- struct procdata *pd;
- hysdn_card *card;
-
- card = card_root; /* start with first card */
- while (card) {
- if ((pd = (struct procdata *) card->procfs) != NULL) {
- if (pd->log)
- remove_proc_entry(pd->log_name, hysdn_proc_entry);
- kfree(pd); /* release memory */
- }
- card = card->next; /* point to next card */
- }
-
- remove_proc_entry("cardinfo", hysdn_proc_entry);
- remove_proc_entry(PROC_SUBDIR_NAME, proc_net);
-} /* hysdn_procfs_release */
diff --git a/drivers/isdn/tpam/tpam_main.c b/drivers/isdn/tpam/tpam_main.c
index 9a000b3d1..4573cad5a 100644
--- a/drivers/isdn/tpam/tpam_main.c
+++ b/drivers/isdn/tpam/tpam_main.c
@@ -254,7 +254,7 @@ static struct pci_driver tpam_driver = {
name: "tpam",
id_table: tpam_pci_tbl,
probe: tpam_probe,
- remove: tpam_remove,
+ remove: __devexit_p(tpam_remove),
};
static int __init tpam_init(void) {
diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c
index 68f612caa..9da6a3619 100644
--- a/drivers/media/radio/radio-gemtek-pci.c
+++ b/drivers/media/radio/radio-gemtek-pci.c
@@ -424,7 +424,7 @@ static struct pci_driver gemtek_pci_driver =
name: "gemtek_pci",
id_table: gemtek_pci_id,
probe: gemtek_pci_probe,
- remove: gemtek_pci_remove
+ remove: __devexit_p(gemtek_pci_remove),
};
static int __init gemtek_pci_init_module( void )
diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c
index 1368ff2ed..dec250a7d 100644
--- a/drivers/media/radio/radio-maxiradio.c
+++ b/drivers/media/radio/radio-maxiradio.c
@@ -376,7 +376,7 @@ static struct pci_driver maxiradio_driver = {
name: "radio-maxiradio",
id_table: maxiradio_pci_tbl,
probe: maxiradio_init_one,
- remove: maxiradio_remove_one,
+ remove: __devexit_p(maxiradio_remove_one),
};
int __init maxiradio_radio_init(void)
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
index 86b14cd87..b04a03a87 100644
--- a/drivers/media/video/bttv-driver.c
+++ b/drivers/media/video/bttv-driver.c
@@ -3025,7 +3025,7 @@ static struct pci_driver bttv_pci_driver = {
name: "bttv",
id_table: bttv_pci_tbl,
probe: bttv_probe,
- remove: bttv_remove,
+ remove: __devexit_p(bttv_remove),
};
int bttv_init_module(void)
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c
index 79c22b488..7ad5618f0 100644
--- a/drivers/media/video/meye.c
+++ b/drivers/media/video/meye.c
@@ -1460,7 +1460,7 @@ static struct pci_driver meye_driver = {
name: "meye",
id_table: meye_pci_tbl,
probe: meye_probe,
- remove: meye_remove,
+ remove: __devexit_p(meye_remove),
};
static int __init meye_init_module(void) {
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 62b7cf473..55e03ff65 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -2919,7 +2919,7 @@ static void __devexit vortex_remove_one (struct pci_dev *pdev)
static struct pci_driver vortex_driver = {
name: "3c59x",
probe: vortex_init_one,
- remove: vortex_remove_one,
+ remove: __devexit_p(vortex_remove_one),
id_table: vortex_pci_tbl,
#ifdef CONFIG_PM
suspend: vortex_suspend,
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index ff5f5792f..f91b450e1 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -1313,7 +1313,7 @@ static struct pci_driver cp_driver = {
name: DRV_NAME,
id_table: cp_pci_tbl,
probe: cp_init_one,
- remove: cp_remove_one,
+ remove: __devexit_p(cp_remove_one),
};
static int __init cp_init (void)
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index 45d102065..352d60eaf 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -2494,7 +2494,7 @@ static struct pci_driver rtl8139_pci_driver = {
name: DRV_NAME,
id_table: rtl8139_pci_tbl,
probe: rtl8139_init_one,
- remove: rtl8139_remove_one,
+ remove: __devexit_p(rtl8139_remove_one),
#ifdef CONFIG_PM
suspend: rtl8139_suspend,
resume: rtl8139_resume,
diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c
index a6b5bc7ef..ff13552a6 100644
--- a/drivers/net/arcnet/com20020-pci.c
+++ b/drivers/net/arcnet/com20020-pci.c
@@ -160,7 +160,7 @@ static struct pci_driver com20020pci_driver = {
name: "com20020",
id_table: com20020pci_id_table,
probe: com20020pci_probe,
- remove: com20020pci_remove
+ remove: __devexit_p(com20020pci_remove),
};
static int __init com20020pci_init(void)
diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c
index 177dbed4e..d079bd417 100644
--- a/drivers/net/defxx.c
+++ b/drivers/net/defxx.c
@@ -3360,7 +3360,7 @@ MODULE_DEVICE_TABLE(pci, dfx_pci_tbl);
static struct pci_driver dfx_driver = {
name: "defxx",
probe: dfx_init_one,
- remove: dfx_remove_one,
+ remove: __devexit_p(dfx_remove_one),
id_table: dfx_pci_tbl,
};
diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c
index 161075784..657565a71 100644
--- a/drivers/net/dl2k.c
+++ b/drivers/net/dl2k.c
@@ -1671,7 +1671,7 @@ static struct pci_driver rio_driver = {
name:"dl2k",
id_table:rio_pci_tbl,
probe:rio_probe1,
- remove:rio_remove1,
+ remove:__devexit_p(rio_remove1),
};
static int __init
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index c33d5eccf..98d939356 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -2297,7 +2297,7 @@ static struct pci_driver eepro100_driver = {
name: "eepro100",
id_table: eepro100_pci_tbl,
probe: eepro100_init_one,
- remove: eepro100_remove_one,
+ remove: __devexit_p(eepro100_remove_one),
#ifdef CONFIG_PM
suspend: eepro100_suspend,
resume: eepro100_resume,
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index 468c675b4..f39c07ae4 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -1507,7 +1507,7 @@ static struct pci_driver epic_driver = {
name: DRV_NAME,
id_table: epic_pci_tbl,
probe: epic_init_one,
- remove: epic_remove_one,
+ remove: __devexit_p(epic_remove_one),
#ifdef CONFIG_PM
suspend: epic_suspend,
resume: epic_resume,
diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c
index e63a3c542..b782518e0 100644
--- a/drivers/net/fealnx.c
+++ b/drivers/net/fealnx.c
@@ -1858,7 +1858,7 @@ static struct pci_driver fealnx_driver = {
name: "fealnx",
id_table: fealnx_pci_tbl,
probe: fealnx_init_one,
- remove: fealnx_remove_one,
+ remove: __devexit_p(fealnx_remove_one),
};
static int __init fealnx_init(void)
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index dc1667b24..68a88a901 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -1515,7 +1515,7 @@ static struct pci_driver ioc3_driver = {
name: "ioc3-eth",
id_table: ioc3_pci_tbl,
probe: ioc3_probe,
- remove: ioc3_remove_one,
+ remove: __devexit_p(ioc3_remove_one),
};
static int __init ioc3_init_module(void)
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index e46fe5293..000f83892 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -1291,7 +1291,7 @@ static struct pci_driver vlsi_irda_driver = {
name: drivername,
id_table: vlsi_irda_table,
probe: vlsi_irda_probe,
- remove: vlsi_irda_remove,
+ remove: __devexit_p(vlsi_irda_remove),
suspend: vlsi_irda_suspend,
resume: vlsi_irda_resume,
};
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index 7d01a2c6e..1bd57184c 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -2518,7 +2518,7 @@ static struct pci_driver natsemi_driver = {
name: DRV_NAME,
id_table: natsemi_pci_tbl,
probe: natsemi_probe1,
- remove: natsemi_remove1,
+ remove: __devexit_p(natsemi_remove1),
#ifdef CONFIG_PM
suspend: natsemi_suspend,
resume: natsemi_resume,
diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c
index 0189756a6..d1addf61c 100644
--- a/drivers/net/ne2k-pci.c
+++ b/drivers/net/ne2k-pci.c
@@ -642,7 +642,7 @@ static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev)
static struct pci_driver ne2k_driver = {
name: DRV_NAME,
probe: ne2k_pci_init_one,
- remove: ne2k_pci_remove_one,
+ remove: __devexit_p(ne2k_pci_remove_one),
id_table: ne2k_pci_tbl,
};
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index 8a1187855..55ff98ee4 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -1455,7 +1455,7 @@ static struct pci_driver driver = {
name: "ns83820",
id_table: ns83820_pci_tbl,
probe: ns83820_init_one,
- remove: ns83820_remove_one,
+ remove: __devexit_p(ns83820_remove_one),
#if 0 /* FIXME: implement */
suspend: ,
resume: ,
diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c
index e94d6c3cb..ee1d184c4 100644
--- a/drivers/net/pci-skeleton.c
+++ b/drivers/net/pci-skeleton.c
@@ -1980,7 +1980,7 @@ static struct pci_driver netdrv_pci_driver = {
name: MODNAME,
id_table: netdrv_pci_tbl,
probe: netdrv_init_one,
- remove: netdrv_remove_one,
+ remove: __devexit_p(netdrv_remove_one),
#ifdef CONFIG_PM
suspend: netdrv_suspend,
resume: netdrv_resume,
diff --git a/drivers/net/pcmcia/xircom_cb.c b/drivers/net/pcmcia/xircom_cb.c
index 9fb35d9d0..cc15b93a4 100644
--- a/drivers/net/pcmcia/xircom_cb.c
+++ b/drivers/net/pcmcia/xircom_cb.c
@@ -170,7 +170,7 @@ static struct pci_driver xircom_ops = {
name: "xircom_cb",
id_table: xircom_pci_table,
probe: xircom_probe,
- remove: xircom_remove,
+ remove: __devexit_p(xircom_remove),
};
diff --git a/drivers/net/pcmcia/xircom_tulip_cb.c b/drivers/net/pcmcia/xircom_tulip_cb.c
index e7fe6ae79..92acf253e 100644
--- a/drivers/net/pcmcia/xircom_tulip_cb.c
+++ b/drivers/net/pcmcia/xircom_tulip_cb.c
@@ -1748,7 +1748,7 @@ static struct pci_driver xircom_driver = {
name: DRV_NAME,
id_table: xircom_pci_table,
probe: xircom_init_one,
- remove: xircom_remove_one,
+ remove: __devexit_p(xircom_remove_one),
#ifdef CONFIG_PM
suspend: xircom_suspend,
resume: xircom_resume
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index e6140c6cf..f67dd3050 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -2098,7 +2098,7 @@ static struct pci_driver sis900_pci_driver = {
name: SIS900_MODULE_NAME,
id_table: sis900_pci_tbl,
probe: sis900_probe,
- remove: sis900_remove,
+ remove: __devexit_p(sis900_remove),
};
static int __init sis900_init_module(void)
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 0fec2bcce..ff1332e88 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -1963,7 +1963,7 @@ static void __devexit starfire_remove_one (struct pci_dev *pdev)
static struct pci_driver starfire_driver = {
name: DRV_NAME,
probe: starfire_init_one,
- remove: starfire_remove_one,
+ remove: __devexit_p(starfire_remove_one),
id_table: starfire_pci_tbl,
};
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index ab376ffed..7c55c0921 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -1474,7 +1474,7 @@ static struct pci_driver sundance_driver = {
name: DRV_NAME,
id_table: sundance_pci_tbl,
probe: sundance_probe1,
- remove: sundance_remove1,
+ remove: __devexit_p(sundance_remove1),
};
static int __init sundance_init(void)
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index f7858a63c..f712f7ae1 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -1,4 +1,4 @@
-/* $Id: sungem.c,v 1.43 2001-12-05 08:40:54 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)
@@ -2859,7 +2859,7 @@ 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,
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index 57632c10e..6290b6b5e 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -430,7 +430,7 @@ static struct pci_driver tlan_driver = {
name: "tlan",
id_table: tlan_pci_tbl,
probe: tlan_init_one,
- remove: tlan_remove_one,
+ remove: __devexit_p(tlan_remove_one),
};
static int __init tlan_probe(void)
diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c
index bbae0d622..32a11e49b 100644
--- a/drivers/net/tokenring/lanstreamer.c
+++ b/drivers/net/tokenring/lanstreamer.c
@@ -1812,7 +1812,7 @@ static struct pci_driver streamer_pci_driver = {
name: "lanstreamer",
id_table: streamer_pci_tbl,
probe: streamer_init_one,
- remove: streamer_remove_one,
+ remove: __devexit_p(streamer_remove_one),
};
static int __init streamer_init_module(void) {
diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c
index ec2cc2346..e1863ed9b 100644
--- a/drivers/net/tokenring/olympic.c
+++ b/drivers/net/tokenring/olympic.c
@@ -1705,7 +1705,7 @@ static struct pci_driver olympic_driver = {
name: "olympic",
id_table: olympic_pci_tbl,
probe: olympic_probe,
- remove: olympic_remove_one
+ remove: __devexit_p(olympic_remove_one),
};
static int __init olympic_pci_init(void)
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index f67ff1373..601046c8e 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -1889,7 +1889,7 @@ static struct pci_driver tulip_driver = {
name: DRV_NAME,
id_table: tulip_pci_tbl,
probe: tulip_init_one,
- remove: tulip_remove_one,
+ remove: __devexit_p(tulip_remove_one),
#ifdef CONFIG_PM
suspend: tulip_suspend,
resume: tulip_resume,
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index 2e753ad17..e956ead13 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -1667,7 +1667,7 @@ static struct pci_driver via_rhine_driver = {
name: "via-rhine",
id_table: via_rhine_pci_tbl,
probe: via_rhine_init_one,
- remove: via_rhine_remove_one,
+ remove: __devexit_p(via_rhine_remove_one),
};
diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
index 031506a5c..64258f647 100644
--- a/drivers/net/wan/farsync.c
+++ b/drivers/net/wan/farsync.c
@@ -1810,7 +1810,7 @@ static struct pci_driver fst_driver = {
name: FST_NAME,
id_table: fst_pci_dev_id,
probe: fst_add_one,
- remove: fst_remove_one,
+ remove: __devexit_p(fst_remove_one),
suspend: NULL,
resume: NULL,
};
diff --git a/drivers/net/winbond-840.c b/drivers/net/winbond-840.c
index f81fc206f..a28cbf9c8 100644
--- a/drivers/net/winbond-840.c
+++ b/drivers/net/winbond-840.c
@@ -1697,7 +1697,7 @@ static struct pci_driver w840_driver = {
name: DRV_NAME,
id_table: w840_pci_tbl,
probe: w840_probe1,
- remove: w840_remove1,
+ remove: __devexit_p(w840_remove1),
#ifdef CONFIG_PM
suspend: w840_suspend,
resume: w840_resume,
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 458cb73a1..2c4e856e7 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -64,7 +64,7 @@ static struct pci_driver airo_driver = {
name: "airo",
id_table: card_ids,
probe: airo_pci_probe,
- remove: airo_pci_remove,
+ remove: __devexit_p(airo_pci_remove),
};
#endif /* CONFIG_PCI */
diff --git a/drivers/net/wireless/orinoco_plx.c b/drivers/net/wireless/orinoco_plx.c
index 751a1e733..9c84936c4 100644
--- a/drivers/net/wireless/orinoco_plx.c
+++ b/drivers/net/wireless/orinoco_plx.c
@@ -279,7 +279,7 @@ static struct pci_driver orinoco_plx_driver = {
name:"orinoco_plx",
id_table:orinoco_plx_pci_id_table,
probe:orinoco_plx_init_one,
- remove:orinoco_plx_remove_one,
+ remove:__devexit_p(orinoco_plx_remove_one),
suspend:0,
resume:0
};
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index e169ad56f..6cd976b85 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -1506,7 +1506,7 @@ static struct pci_driver yellowfin_driver = {
name: DRV_NAME,
id_table: yellowfin_pci_tbl,
probe: yellowfin_init_one,
- remove: yellowfin_remove_one,
+ remove: __devexit_p(yellowfin_remove_one),
};
diff --git a/drivers/parport/ChangeLog b/drivers/parport/ChangeLog
index 129450bf6..4411d2a1d 100644
--- a/drivers/parport/ChangeLog
+++ b/drivers/parport/ChangeLog
@@ -1,3 +1,27 @@
+2001-12-07 Tim Waugh <twaugh@redhat.com>
+
+ * ieee1284_ops.c (parport_ieee1284_epp_write_addr,
+ parport_ieee1284_epp_read_addr): Actually do something useful.
+
+2001-12-07 Tim Waugh <twaugh@redhat.com>
+
+ * parport_pc.c (dmaval): Don't use DMA by default. It seems to be
+ too buggy at the moment. Use 'dma=auto' to restore the previous
+ behaviour.
+
+2001-12-03 Rich Liu <Rich.Liu@ite.com.tw>
+
+ * parport_pc.c (sio_ite_8872_probe): ITE8873 is a single-port
+ serial board, not a serial+parallel.
+
+2001-11-30 Neils Kristian Bech Jensen <nkbj@image.dk>
+
+ * parport_pc.c: Fix compiler warning.
+
+2001-12-07 Tim Waugh <twaugh@redhat.com>
+
+ * daisy.c (DEBUG): Undefine.
+
2001-12-06 Tim Waugh <twaugh@redhat.com>
* ieee1284_ops.c (parport_ieee1284_ecp_read_data): Mask off
diff --git a/drivers/parport/daisy.c b/drivers/parport/daisy.c
index 573c5ef20..b9ba843b9 100644
--- a/drivers/parport/daisy.c
+++ b/drivers/parport/daisy.c
@@ -23,7 +23,7 @@
#include <linux/delay.h>
#include <asm/uaccess.h>
-#define DEBUG /* undef me for production */
+#undef DEBUG /* undef me for production */
#ifdef DEBUG
#define DPRINTK(stuff...) printk (stuff)
diff --git a/drivers/parport/ieee1284_ops.c b/drivers/parport/ieee1284_ops.c
index 8fcd6f2f1..aee6e0065 100644
--- a/drivers/parport/ieee1284_ops.c
+++ b/drivers/parport/ieee1284_ops.c
@@ -824,35 +824,40 @@ size_t parport_ieee1284_epp_write_addr (struct parport *port,
const void *buffer, size_t len,
int flags)
{
- /* This is untested */
unsigned char *bp = (unsigned char *) buffer;
size_t ret = 0;
+ /* set EPP idle state (just to make sure) with strobe low */
parport_frob_control (port,
PARPORT_CONTROL_STROBE |
+ PARPORT_CONTROL_AUTOFD |
PARPORT_CONTROL_SELECT |
- PARPORT_CONTROL_AUTOFD,
+ PARPORT_CONTROL_INIT,
PARPORT_CONTROL_STROBE |
- PARPORT_CONTROL_SELECT);
+ PARPORT_CONTROL_INIT);
port->ops->data_forward (port);
for (; len > 0; len--, bp++) {
- /* Write data and assert nAStrb. */
+ /* Event 56: Write data and set nAStrb low. */
parport_write_data (port, *bp);
parport_frob_control (port, PARPORT_CONTROL_SELECT,
PARPORT_CONTROL_SELECT);
- if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY,
- PARPORT_STATUS_BUSY, 10))
+ /* Event 58: wait for busy (nWait) to go high */
+ if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY, 0, 10))
break;
+ /* Event 59: set nAStrb high */
parport_frob_control (port, PARPORT_CONTROL_SELECT, 0);
- if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY, 0, 5))
+ /* Event 60: wait for busy (nWait) to go low */
+ if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY,
+ PARPORT_STATUS_BUSY, 5))
break;
ret++;
}
+ /* Event 61: set strobe (nWrite) high */
parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
return ret;
@@ -863,28 +868,36 @@ size_t parport_ieee1284_epp_read_addr (struct parport *port,
void *buffer, size_t len,
int flags)
{
- /* This is untested. */
unsigned char *bp = (unsigned char *) buffer;
unsigned ret = 0;
+ /* Set EPP idle state (just to make sure) with strobe high */
parport_frob_control (port,
PARPORT_CONTROL_STROBE |
- PARPORT_CONTROL_AUTOFD, 0);
+ PARPORT_CONTROL_AUTOFD |
+ PARPORT_CONTROL_SELECT |
+ PARPORT_CONTROL_INIT,
+ PARPORT_CONTROL_INIT);
port->ops->data_reverse (port);
for (; len > 0; len--, bp++) {
- parport_frob_control (port, PARPORT_CONTROL_SELECT, 0);
+ /* Event 64: set nSelectIn (nAStrb) low */
+ parport_frob_control (port, PARPORT_CONTROL_SELECT,
+ PARPORT_CONTROL_SELECT);
- /* Event 58 */
- if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY,
- PARPORT_STATUS_BUSY, 10))
+ /* Event 58: wait for Busy to go high */
+ if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY, 0)) {
break;
+ }
*bp = parport_read_data (port);
+ /* Event 59: set nSelectIn (nAStrb) high */
parport_frob_control (port, PARPORT_CONTROL_SELECT,
PARPORT_CONTROL_SELECT);
- if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY, 0, 5))
+ /* Event 60: wait for Busy to go low */
+ if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY,
+ PARPORT_STATUS_BUSY, 5))
break;
ret++;
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index 0c5c82a3b..6973a2f64 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -91,7 +91,9 @@ static struct superio_struct { /* For Super-IO chips autodetection */
} superios[NR_SUPERIOS] __devinitdata = { {0,},};
static int user_specified __devinitdata = 0;
+#if defined(CONFIG_PARPORT_PC_FIFO) || defined(CONFIG_PARPORT_PC_SUPERIO)
static int verbose_probing;
+#endif
static int registered_parport;
/* frob_control, but for ECR */
@@ -1780,6 +1782,7 @@ static int __devinit parport_PS2_supported(struct parport *pb)
return ok;
}
+#ifdef CONFIG_PARPORT_PC_FIFO
static int __devinit parport_ECP_supported(struct parport *pb)
{
int i;
@@ -1905,6 +1908,7 @@ static int __devinit parport_ECP_supported(struct parport *pb)
return 1;
}
+#endif
static int __devinit parport_ECPPS2_supported(struct parport *pb)
{
@@ -2004,7 +2008,9 @@ static int __devinit parport_ECPEPP_supported(struct parport *pb)
/* Don't bother probing for modes we know we won't use. */
static int __devinit parport_PS2_supported(struct parport *pb) { return 0; }
+#ifdef CONFIG_PARPORT_PC_FIFO
static int __devinit parport_ECP_supported(struct parport *pb) { return 0; }
+#endif
static int __devinit parport_EPP_supported(struct parport *pb) { return 0; }
static int __devinit parport_ECPEPP_supported(struct parport *pb){return 0;}
static int __devinit parport_ECPPS2_supported(struct parport *pb){return 0;}
@@ -2453,9 +2459,8 @@ static int __devinit sio_ite_8872_probe (struct pci_dev *pdev, int autoirq,
ite8872set = 0x64e00000;
break;
case 0x6:
- printk (KERN_INFO "parport_pc: ITE8873 found (1S1P)\n");
- ite8872set = 0x64a00000;
- break;
+ printk (KERN_INFO "parport_pc: ITE8873 found (1S)\n");
+ return 0;
case 0x8:
DPRINTK (KERN_DEBUG "parport_pc: ITE8874 found (2S)\n");
return 0;
@@ -3007,7 +3012,7 @@ EXPORT_SYMBOL (parport_pc_unregister_port);
static int io[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 };
static int io_hi[PARPORT_PC_MAX_PORTS+1] =
{ [0 ... PARPORT_PC_MAX_PORTS] = PARPORT_IOHI_AUTO };
-static int dmaval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_AUTO };
+static int dmaval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_NONE };
static int irqval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_IRQ_PROBEONLY };
static const char *irq[PARPORT_PC_MAX_PORTS] = { NULL, };
static const char *dma[PARPORT_PC_MAX_PORTS] = { NULL, };
@@ -3024,8 +3029,10 @@ MODULE_PARM_DESC(irq, "IRQ line");
MODULE_PARM(irq, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "s");
MODULE_PARM_DESC(dma, "DMA channel");
MODULE_PARM(dma, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "s");
-MODULE_PARM(verbose_probing, "i");
+#if defined(CONFIG_PARPORT_PC_FIFO) || defined(CONFIG_PARPORT_PC_SUPERIO)
MODULE_PARM_DESC(verbose_probing, "Log chit-chat during initialisation");
+MODULE_PARM(verbose_probing, "i");
+#endif
int init_module(void)
{
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index 6eb80f07f..52649275c 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -331,7 +331,7 @@ static struct pci_driver parport_serial_pci_driver = {
name: "parport_serial",
id_table: parport_serial_pci_tbl,
probe: parport_serial_pci_probe,
- remove: parport_serial_pci_remove,
+ remove: __devexit_p(parport_serial_pci_remove),
};
diff --git a/drivers/pcmcia/pci_socket.c b/drivers/pcmcia/pci_socket.c
index 7c6615a64..d30df9b42 100644
--- a/drivers/pcmcia/pci_socket.c
+++ b/drivers/pcmcia/pci_socket.c
@@ -249,7 +249,7 @@ static struct pci_driver pci_cardbus_driver = {
name: "cardbus",
id_table: cardbus_table,
probe: cardbus_probe,
- remove: cardbus_remove,
+ remove: __devexit_p(cardbus_remove),
suspend: cardbus_suspend,
resume: cardbus_resume,
};
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index d22ba8bae..9519d2c6d 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -107,17 +107,21 @@ static irq_info_t irq_table[NR_IRQS] = { { 0, 0, 0 }, /* etc */ };
static struct resource *resource_parent(unsigned long b, unsigned long n,
int flags, struct pci_dev *dev)
{
- struct resource res;
-
- if (dev == NULL) {
- if (flags & IORESOURCE_MEM)
- return &iomem_resource;
- return &ioport_resource;
+#ifdef CONFIG_PCI
+ struct resource res, *pr;
+
+ if (dev != NULL) {
+ res.start = b;
+ res.end = b + n - 1;
+ res.flags = flags;
+ pr = pci_find_parent_resource(dev, &res);
+ if (pr)
+ return pr;
}
- res.start = b;
- res.end = b + n - 1;
- res.flags = flags;
- return pci_find_parent_resource(dev, &res);
+#endif /* CONFIG_PCI */
+ if (flags & IORESOURCE_MEM)
+ return &iomem_resource;
+ return &ioport_resource;
}
static inline int check_io_resource(unsigned long b, unsigned long n,
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index 2f7a1d721..eab889e86 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -83,8 +83,6 @@
* basically, transfer size needs to be reduced by one
* and the last byte read as is done with PSEUDO_DMA.
*
- * 3. Test USLEEP code
- *
* 4. Test SCSI-II tagged queueing (I have no devices which support
* tagged queueing)
*
@@ -110,6 +108,12 @@
#define READ_OVERRUNS
#endif
+#ifdef BOARD_REQUIRES_NO_DELAY
+#define io_recovery_delay(x)
+#else
+#define io_recovery_delay(x) udelay(x)
+#endif
+
/*
* Design
* Issues :
@@ -192,9 +196,8 @@
* phase goes through the various phases as instructed by the target.
* if the target goes into MSG IN and sends a DISCONNECT message,
* the command structure is placed into the per instance disconnected
- * queue, and NCR5380_main tries to find more work. If USLEEP
- * was defined, and the target is idle for too long, the system
- * will try to sleep.
+ * queue, and NCR5380_main tries to find more work. If the target is
+ * idle for too long, the system will try to sleep.
*
* If a command has disconnected, eventually an interrupt will trigger,
* calling NCR5380_intr() which will in turn call NCR5380_reselect
@@ -244,21 +247,14 @@
* rely on phase mismatch and EOP interrupts to determine end
* of phase.
*
- * SCSI2 - if defined, SCSI-2 tagged queuing is used where possible
- *
* UNSAFE - leave interrupts enabled during pseudo-DMA transfers. You
* only really want to use this if you're having a problem with
* dropped characters during high speed communications, and even
* then, you're going to be better off twiddling with transfersize
* in the high level code.
*
- * USLEEP - if defined, on devices that aren't disconnecting from the
- * bus, we will go to sleep so that the CPU can get real work done
- * when we run a command that won't complete immediately.
- *
- * Defaults for these will be provided if USLEEP is defined, although
- * the user may want to adjust these to allocate CPU resources to
- * the SCSI driver or "real" code.
+ * Defaults for these will be provided although the user may want to adjust
+ * these to allocate CPU resources to the SCSI driver or "real" code.
*
* USLEEP_SLEEP - amount of time, in jiffies, to sleep
*
@@ -322,18 +318,13 @@ static int do_abort(struct Scsi_Host *host);
static void do_reset(struct Scsi_Host *host);
static struct Scsi_Host *first_instance = NULL;
static Scsi_Host_Template *the_template = NULL;
-
-#ifdef USLEEP
-struct timer_list usleep_timer;
-#endif
+static struct timer_list usleep_timer;
/*
- * Function : void initialize_SCp(Scsi_Cmnd *cmd)
- *
- * Purpose : initialize the saved data pointers for cmd to point to the
- * start of the buffer.
+ * initialize_SCp - init the scsi pointer field
+ * @cmd: command block to set up
*
- * Inputs : cmd - Scsi_Cmnd structure to have pointers reset.
+ * Set up the internal fields in the SCSI command.
*/
static __inline__ void initialize_SCp(Scsi_Cmnd * cmd)
@@ -362,46 +353,49 @@ static __inline__ void initialize_SCp(Scsi_Cmnd * cmd)
static struct {
unsigned char mask;
const char *name;
-} signals[] = { {
-
-SR_DBP, "PARITY"}, {
-SR_RST, "RST"}, {
-SR_BSY, "BSY"}, {
-SR_REQ, "REQ"}, {
-SR_MSG, "MSG"}, {
-SR_CD, "CD"}, {
-SR_IO, "IO"}, {
-SR_SEL, "SEL"}, {
-0, NULL}
-}, basrs[] = { {
-BASR_ATN, "ATN"}, {
-BASR_ACK, "ACK"}, {
-0, NULL}
-}, icrs[] = { {
-ICR_ASSERT_RST, "ASSERT RST"}, {
-ICR_ASSERT_ACK, "ASSERT ACK"}, {
-ICR_ASSERT_BSY, "ASSERT BSY"}, {
-ICR_ASSERT_SEL, "ASSERT SEL"}, {
-ICR_ASSERT_ATN, "ASSERT ATN"}, {
-ICR_ASSERT_DATA, "ASSERT DATA"}, {
-0, NULL}
-}, mrs[] = { {
-MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, {
-MR_TARGET, "MODE TARGET"}, {
-MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"}, {
-MR_ENABLE_PAR_INTR, "MODE PARITY INTR"}, {
-MR_MONITOR_BSY, "MODE MONITOR BSY"}, {
-MR_DMA_MODE, "MODE DMA"}, {
-MR_ARBITRATE, "MODE ARBITRATION"}, {
-0, NULL}
+} signals[] = {
+ {SR_DBP, "PARITY"},
+ {SR_RST, "RST"},
+ {SR_BSY, "BSY"},
+ {SR_REQ, "REQ"},
+ {SR_MSG, "MSG"},
+ {SR_CD, "CD"},
+ {SR_IO, "IO"},
+ {SR_SEL, "SEL"},
+ {0, NULL}
+},
+basrs[] = {
+ {BASR_ATN, "ATN"},
+ {BASR_ACK, "ACK"},
+ {0, NULL}
+},
+icrs[] = {
+ {ICR_ASSERT_RST, "ASSERT RST"},
+ {ICR_ASSERT_ACK, "ASSERT ACK"},
+ {ICR_ASSERT_BSY, "ASSERT BSY"},
+ {ICR_ASSERT_SEL, "ASSERT SEL"},
+ {ICR_ASSERT_ATN, "ASSERT ATN"},
+ {ICR_ASSERT_DATA, "ASSERT DATA"},
+ {0, NULL}
+},
+mrs[] = {
+ {MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"},
+ {MR_TARGET, "MODE TARGET"},
+ {MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"},
+ {MR_ENABLE_PAR_INTR, "MODE PARITY INTR"},
+ {MR_MONITOR_BSY, "MODE MONITOR BSY"},
+ {MR_DMA_MODE, "MODE DMA"},
+ {MR_ARBITRATE, "MODE ARBITRATION"},
+ {0, NULL}
};
-/*
- * Function : void NCR5380_print(struct Scsi_Host *instance)
+/**
+ * NCR5380_print - print scsi bus signals
+ * @instance: adapter state to dump
*
- * Purpose : print the SCSI bus signals for debugging purposes
+ * Print the SCSI bus signals for debugging purposes
*
- * Input : instance - which NCR5380
+ * Locks: none
*/
static void NCR5380_print(struct Scsi_Host *instance)
@@ -410,6 +404,7 @@ static void NCR5380_print(struct Scsi_Host *instance)
unsigned long flags;
unsigned char status, data, basr, mr, icr, i;
NCR5380_setup(instance);
+ /* FIXME - this needs proper locking */
save_flags(flags);
cli();
data = NCR5380_read(CURRENT_SCSI_DATA_REG);
@@ -441,23 +436,22 @@ static struct {
unsigned char value;
const char *name;
} phases[] = {
-
- {
- PHASE_DATAOUT, "DATAOUT"}, {
- PHASE_DATAIN, "DATAIN"}, {
- PHASE_CMDOUT, "CMDOUT"}, {
- PHASE_STATIN, "STATIN"}, {
- PHASE_MSGOUT, "MSGOUT"}, {
- PHASE_MSGIN, "MSGIN"}, {
- PHASE_UNKNOWN, "UNKNOWN"}
+ {PHASE_DATAOUT, "DATAOUT"},
+ {PHASE_DATAIN, "DATAIN"},
+ {PHASE_CMDOUT, "CMDOUT"},
+ {PHASE_STATIN, "STATIN"},
+ {PHASE_MSGOUT, "MSGOUT"},
+ {PHASE_MSGIN, "MSGIN"},
+ {PHASE_UNKNOWN, "UNKNOWN"}
};
/*
- * Function : void NCR5380_print_phase(struct Scsi_Host *instance)
+ * NCR5380_print_phase - show SCSI phase
+ * @instance: adapter to dump
*
- * Purpose : print the current SCSI phase for debugging purposes
+ * Print the current SCSI phase for debugging purposes
*
- * Input : instance - which NCR5380
+ * Locks: none
*/
static void NCR5380_print_phase(struct Scsi_Host *instance)
@@ -496,7 +490,7 @@ static void NCR5380_print_phase(struct Scsi_Host *instance)
* conditions are possible.
*/
-static volatile int main_running = 0;
+static unsigned long main_running = 0;
/*
* Function : run_main(void)
@@ -510,14 +504,10 @@ static volatile int main_running = 0;
static __inline__ void run_main(void)
{
- if (!main_running) {
- main_running = 1;
+ if (!test_and_set_bit(0, &main_running))
NCR5380_main();
- }
}
-#ifdef USLEEP
-
/*
* These need tweaking, and would probably work best as per-device
* flags initialized differently for disk, tape, cd, etc devices.
@@ -587,17 +577,15 @@ static int should_disconnect(unsigned char cmd)
/*
* Assumes instance->time_expires has been set in higher level code.
+ *
+ * Locks: Caller must hold io_request_lock
*/
static int NCR5380_set_timer(struct Scsi_Host *instance)
{
- unsigned long flags;
struct Scsi_Host *tmp, **prev;
- save_flags(flags);
- cli();
if (((struct NCR5380_hostdata *) (instance->hostdata))->next_timer) {
- restore_flags(flags);
return -1;
}
for (prev = &expires_first, tmp = expires_first; tmp; prev = &(((struct NCR5380_hostdata *) tmp->hostdata)->next_timer), tmp = ((struct NCR5380_hostdata *) tmp->hostdata)->next_timer)
@@ -608,17 +596,28 @@ static int NCR5380_set_timer(struct Scsi_Host *instance)
*prev = instance;
mod_timer(&usleep_timer, ((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires);
- restore_flags(flags);
return 0;
}
-/* Doing something about unwanted reentrancy here might be useful */
-void NCR5380_timer_fn(unsigned long surplus_to_requirements)
+/**
+ * NCR5380_timer_fn - handle polled timeouts
+ * @unused: unused
+ *
+ * Walk the list of controllers, find which controllers have exceeded
+ * their expiry timeout and then schedule the processing co-routine to
+ * do the real work.
+ *
+ * Doing something about unwanted reentrancy here might be useful
+ *
+ * Locks: disables irqs, takes and frees io_request_lock
+ */
+
+void NCR5380_timer_fn(unsigned long unused)
{
- unsigned long flags;
struct Scsi_Host *instance;
- save_flags(flags);
- cli();
+
+ spin_lock_irq(&io_request_lock);
+
for (; expires_first && time_before_eq(((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires, jiffies);) {
instance = ((struct NCR5380_hostdata *) expires_first->hostdata)->next_timer;
((struct NCR5380_hostdata *) expires_first->hostdata)->next_timer = NULL;
@@ -631,51 +630,56 @@ void NCR5380_timer_fn(unsigned long surplus_to_requirements)
usleep_timer.expires = ((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires;
add_timer(&usleep_timer);
}
- restore_flags(flags);
-
- spin_lock_irqsave(&io_request_lock, flags);
run_main();
- spin_unlock_irqrestore(&io_request_lock, flags);
+ spin_unlock_irq(&io_request_lock);
}
-#endif /* def USLEEP */
+/**
+ * NCR5380_all_init - global setup
+ *
+ * Set up the global values and timers needed by the NCR5380 driver
+ */
+
static inline void NCR5380_all_init(void)
{
static int done = 0;
if (!done) {
-#if (NDEBUG & NDEBUG_INIT)
- printk("scsi : NCR5380_all_init()\n");
-#endif
+ dprintk(NDEBUG_INIT, ("scsi : NCR5380_all_init()\n"));
done = 1;
-#ifdef USLEEP
init_timer(&usleep_timer);
usleep_timer.function = NCR5380_timer_fn;
-#endif
}
}
-#ifdef AUTOPROBE_IRQ
-/*
- * Function : int NCR5380_probe_irq (struct Scsi_Host *instance, int possible)
- *
- * Purpose : autoprobe for the IRQ line used by the NCR5380.
- *
- * Inputs : instance - pointer to this instance of the NCR5380 driver,
- * possible - bitmask of permissible interrupts.
- *
- * Returns : number of the IRQ selected, IRQ_NONE if no interrupt fired.
- *
- * XXX no effort is made to deal with spurious interrupts.
- */
-
static int probe_irq __initdata = 0;
+/**
+ * probe_intr - helper for IRQ autoprobe
+ * @irq: interrupt number
+ * @dev_id: unused
+ * @regs: unused
+ *
+ * Set a flag to indicate the IRQ in question was received. This is
+ * used by the IRQ probe code.
+ */
+
static void __init probe_intr(int irq, void *dev_id, struct pt_regs *regs)
{
probe_irq = irq;
}
+/**
+ * NCR5380_probe_irq - find the IRQ of an NCR5380
+ * @instance: NCR5380 controller
+ * @possible: bitmask of ISA IRQ lines
+ *
+ * Autoprobe for the IRQ line used by the NCR5380 by triggering an IRQ
+ * and then looking to see what interrupt actually turned up.
+ *
+ * Locks: none, irqs must be enabled on entry
+ */
+
static int __init NCR5380_probe_irq(struct Scsi_Host *instance, int possible)
{
NCR5380_local_declare();
@@ -685,22 +689,21 @@ static int __init NCR5380_probe_irq(struct Scsi_Host *instance, int possible)
NCR5380_setup(instance);
for (trying_irqs = i = 0, mask = 1; i < 16; ++i, mask <<= 1)
- if ((mask & possible) && (request_irq(i, &probe_intr, SA_INTERRUPT, "NCR-probe", NULL)
- == 0))
+ if ((mask & possible) && (request_irq(i, &probe_intr, SA_INTERRUPT, "NCR-probe", NULL) == 0))
trying_irqs |= mask;
timeout = jiffies + (250 * HZ / 1000);
probe_irq = IRQ_NONE;
-/*
- * A interrupt is triggered whenever BSY = false, SEL = true
- * and a bit set in the SELECT_ENABLE_REG is asserted on the
- * SCSI bus.
- *
- * Note that the bus is only driven when the phase control signals
- * (I/O, C/D, and MSG) match those in the TCR, so we must reset that
- * to zero.
- */
+ /*
+ * A interrupt is triggered whenever BSY = false, SEL = true
+ * and a bit set in the SELECT_ENABLE_REG is asserted on the
+ * SCSI bus.
+ *
+ * Note that the bus is only driven when the phase control signals
+ * (I/O, C/D, and MSG) match those in the TCR, so we must reset that
+ * to zero.
+ */
NCR5380_write(TARGET_COMMAND_REG, 0);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
@@ -719,15 +722,16 @@ static int __init NCR5380_probe_irq(struct Scsi_Host *instance, int possible)
return probe_irq;
}
-#endif /* AUTOPROBE_IRQ */
-/*
- * Function : void NCR58380_print_options (struct Scsi_Host *instance)
+/**
+ * NCR58380_print_options - show options
+ * @instance: unused for now
*
- * Purpose : called by probe code indicating the NCR5380 driver
- * options that were selected.
+ * Called by probe code indicating the NCR5380 driver options that
+ * were selected. At some point this will switch to runtime options
+ * read from the adapter in question
*
- * Inputs : instance, pointer to this instance. Unused.
+ * Locks: none
*/
static void __init NCR5380_print_options(struct Scsi_Host *instance)
@@ -754,29 +758,25 @@ static void __init NCR5380_print_options(struct Scsi_Host *instance)
#ifdef PSEUDO_DMA
" PSEUDO DMA"
#endif
-#ifdef SCSI2
- " SCSI-2"
-#endif
#ifdef UNSAFE
" UNSAFE "
#endif
);
-#ifdef USLEEP
printk(" USLEEP, USLEEP_POLL=%d USLEEP_SLEEP=%d", USLEEP_POLL, USLEEP_SLEEP);
-#endif
printk(" generic release=%d", NCR5380_PUBLIC_RELEASE);
if (((struct NCR5380_hostdata *) instance->hostdata)->flags & FLAG_NCR53C400) {
printk(" ncr53c400 release=%d", NCR53C400_PUBLIC_RELEASE);
}
}
-/*
- * Function : void NCR5380_print_status (struct Scsi_Host *instance)
+/**
+ * NCR5380_print_status - dump controller info
+ * @instance: controller to dump
*
- * Purpose : print commands in the various queues, called from
- * NCR5380_abort and NCR5380_debug to aid debugging.
+ * Print commands in the various queues, called from NCR5380_abort
+ * and NCR5380_debug to aid debugging.
*
- * Inputs : instance, pointer to this instance.
+ * Locks: called functions disable irqs, missing queue lock in proc call
*/
static void NCR5380_print_status(struct Scsi_Host *instance)
@@ -787,10 +787,8 @@ static void NCR5380_print_status(struct Scsi_Host *instance)
printk("NCR5380 : coroutine is%s running.\n", main_running ? "" : "n't");
-#ifdef NDEBUG
- NCR5380_print(instance);
- NCR5380_print_phase(instance);
-#endif
+ NCR5380_dprint(NDEBUG_ANY, instance);
+ NCR5380_dprint_phase(NDEBUG_ANY, instance);
len = NCR5380_proc_info(pr_bfr, &start, 0, sizeof(pr_bfr), instance->host_no, 0);
pr_bfr[len] = 0;
@@ -825,7 +823,6 @@ static
#endif
int NCR5380_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout)
{
- unsigned long flags;
char *pos = buffer;
struct Scsi_Host *instance;
struct NCR5380_hostdata *hostdata;
@@ -874,8 +871,7 @@ int NCR5380_proc_info(char *buffer, char **start, off_t offset, int length, int
#ifdef PAS16_PUBLIC_RELEASE
SPRINTF("Highwater I/O busy_spin_counts -- write: %d read: %d\n", pas_wmaxi, pas_maxi);
#endif
- save_flags(flags);
- cli();
+ spin_lock_irq(&io_request_lock);
SPRINTF("NCR5380 : coroutine is%s running.\n", main_running ? "" : "n't");
if (!hostdata->connected)
SPRINTF("scsi%d: no currently connected command\n", instance->host_no);
@@ -889,7 +885,8 @@ int NCR5380_proc_info(char *buffer, char **start, off_t offset, int length, int
for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
- restore_flags(flags);
+ spin_unlock_irq(&io_request_lock);
+
*start = buffer;
if (pos - buffer < offset)
return 0;
@@ -926,17 +923,18 @@ char *lprint_opcode(int opcode, char *pos, char *buffer, int length)
}
-/*
- * Function : void NCR5380_init (struct Scsi_Host *instance, flags)
+/**
+ * NCR5380_init - initialise an NCR5380
+ * @instance: adapter to configure
+ * @flags: control flags
*
- * Purpose : initializes *instance and corresponding 5380 chip,
+ * Initializes *instance and corresponding 5380 chip,
* with flags OR'd into the initial flags value.
*
- * Inputs : instance - instantiation of the 5380 driver.
- *
- * Notes : I assume that the host, hostno, and id bits have been
+ * Notes : I assume that the host, hostno, and id bits have been
* set correctly. I don't care about the irq and other fields.
- *
+ *
+ * Locks: interrupts must be enabled when we are called
*/
static void __init NCR5380_init(struct Scsi_Host *instance, int flags)
@@ -946,6 +944,8 @@ static void __init NCR5380_init(struct Scsi_Host *instance, int flags)
unsigned long timeout;
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
+ if(in_interrupt())
+ printk(KERN_ERR "NCR5380_init called with interrupts off!\n");
/*
* On NCR53C400 boards, NCR5380 registers are mapped 8 past
* the base address.
@@ -957,7 +957,6 @@ static void __init NCR5380_init(struct Scsi_Host *instance, int flags)
#endif
NCR5380_setup(instance);
-
NCR5380_all_init();
hostdata->aborted = 0;
@@ -996,15 +995,13 @@ static void __init NCR5380_init(struct Scsi_Host *instance, int flags)
the_template = instance->hostt;
first_instance = instance;
}
-#ifdef USLEEP
hostdata->time_expires = 0;
hostdata->next_timer = NULL;
-#endif
#ifndef AUTOSENSE
if ((instance->cmd_per_lun > 1) || instance->can_queue > 1)
- )
- printk("scsi%d : WARNING : support for multiple outstanding commands enabled\n" " without AUTOSENSE option, contingent allegiance conditions may\n" " be incorrectly cleared.\n", instance->host_no);
+ printk(KERN_WARNING "scsi%d : WARNING : support for multiple outstanding commands enabled\n" " without AUTOSENSE option, contingent allegiance conditions may\n"
+ " be incorrectly cleared.\n", instance->host_no);
#endif /* def AUTOSENSE */
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
@@ -1053,22 +1050,17 @@ static void __init NCR5380_init(struct Scsi_Host *instance, int flags)
}
}
-/*
- * Function : int NCR5380_queue_command (Scsi_Cmnd *cmd,
- * void (*done)(Scsi_Cmnd *))
+/**
+ * NCR5380_queue_command - queue a command
+ * @cmd: SCSI command
+ * @done: completion handler
*
- * Purpose : enqueues a SCSI command
- *
- * Inputs : cmd - SCSI command, done - function called on completion, with
- * a pointer to the command descriptor.
- *
- * Returns : 0
- *
- * Side effects :
* cmd is added to the per instance issue_queue, with minor
* twiddling done to the host specific fields of cmd. If the
* main coroutine is not running, it is restarted.
*
+ * Locks: io_request lock held by caller. Called functions drop and
+ * retake this lock. Called functions take dma lock.
*/
/* Only make static if a wrapper function is used */
@@ -1092,15 +1084,7 @@ int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) {
#endif /* (NDEBUG & NDEBUG_NO_WRITE) */
#ifdef NCR5380_STATS
-#if 0
- if (!hostdata->connected && !hostdata->issue_queue && !hostdata->disconnected_queue) {
- hostdata->timebase = jiffies;
- }
-#endif
-#ifdef NCR5380_STAT_LIMIT
- if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
-#endif
- switch (cmd->cmnd[0]) {
+ switch (cmd->cmnd[0]) {
case WRITE:
case WRITE_6:
case WRITE_10:
@@ -1115,7 +1099,7 @@ int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) {
hostdata->bytes_read[cmd->target] += cmd->request_bufflen;
hostdata->pendingr++;
break;
- }
+ }
#endif
/*
@@ -1125,10 +1109,8 @@ int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) {
cmd->host_scribble = NULL;
cmd->scsi_done = done;
-
cmd->result = 0;
-
/*
* Insert the cmd into the issue queue. Note that REQUEST SENSE
* commands are added to the head of the queue since any command will
@@ -1145,25 +1127,24 @@ int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) {
LIST(cmd, tmp);
tmp->host_scribble = (unsigned char *) cmd;
}
-#if (NDEBUG & NDEBUG_QUEUES)
- printk("scsi%d : command added to %s of queue\n", instance->host_no, (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail");
-#endif
+ dprintk(NDEBUG_QUEUES, ("scsi%d : command added to %s of queue\n", instance->host_no, (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail"));
-/* Run the coroutine if it isn't already running. */
+ /* Run the coroutine if it isn't already running. */
run_main();
return 0;
}
-/*
- * Function : NCR5380_main (void)
+/**
+ * NCR5380_main - NCR state machines
*
- * Purpose : NCR5380_main is a coroutine that runs as long as more work can
+ * NCR5380_main is a coroutine that runs as long as more work can
* be done on the NCR5380 host adapters in a system. Both
* NCR5380_queue_command() and NCR5380_intr() will try to start it
* in case it is not running.
*
- * NOTE : NCR5380_main exits with interrupts *disabled*, the caller should
- * reenable them. This prevents reentrancy and kernel stack overflow.
+ * Locks; The caller must hold the io_request_lock. The lock will still be
+ * held on return but may be dropped while running. Called functions take
+ * the DMA lock.
*/
static void NCR5380_main(void) {
@@ -1171,7 +1152,6 @@ static void NCR5380_main(void) {
struct Scsi_Host *instance;
struct NCR5380_hostdata *hostdata;
int done;
- unsigned long flags;
/*
* We run (with interrupts disabled) until we're sure that none of
@@ -1185,40 +1165,22 @@ static void NCR5380_main(void) {
* this should prevent any race conditions.
*/
- spin_unlock_irq(&io_request_lock);
-
- save_flags(flags);
-
do {
- cli(); /* Freeze request queues */
+ /* Lock held here */
done = 1;
for (instance = first_instance; instance && instance->hostt == the_template; instance = instance->next) {
hostdata = (struct NCR5380_hostdata *) instance->hostdata;
- cli();
-#ifdef USLEEP
+ /* Lock held here */
if (!hostdata->connected && !hostdata->selecting) {
-#else
- if (!hostdata->connected) {
-#endif
-#if (NDEBUG & NDEBUG_MAIN)
- printk("scsi%d : not connected\n", instance->host_no);
-#endif
+ dprintk(NDEBUG_MAIN, ("scsi%d : not connected\n", instance->host_no));
/*
* Search through the issue_queue for a command destined
* for a target that's not busy.
*/
-#if (NDEBUG & NDEBUG_LISTS)
- for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL; tmp && (tmp != prev); prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble);
- /*printk("%p ", tmp); */
- if ((tmp == prev) && tmp)
- printk(" LOOP\n"); /* else printk("\n"); */
-#endif
- for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble) {
-
-#if (NDEBUG & NDEBUG_LISTS)
+ for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble)
+ {
if (prev != tmp)
- printk("MAIN tmp=%p target=%d busy=%d lun=%d\n", tmp, tmp->target, hostdata->busy[tmp->target], tmp->lun);
-#endif
+ dprintk(NDEBUG_LISTS, ("MAIN tmp=%p target=%d busy=%d lun=%d\n", tmp, tmp->target, hostdata->busy[tmp->target], tmp->lun));
/* When we find one, remove it from the issue queue. */
if (!(hostdata->busy[tmp->target] & (1 << tmp->lun))) {
if (prev) {
@@ -1230,8 +1192,6 @@ static void NCR5380_main(void) {
}
tmp->host_scribble = NULL;
- /* reenable interrupts after finding one */
- restore_flags(flags);
/*
* Attempt to establish an I_T_L nexus here.
@@ -1239,9 +1199,7 @@ static void NCR5380_main(void) {
* On failure, we must add the command back to the
* issue queue so we can keep trying.
*/
-#if (NDEBUG & (NDEBUG_MAIN | NDEBUG_QUEUES))
- printk("scsi%d : main() : command for target %d lun %d removed from issue_queue\n", instance->host_no, tmp->target, tmp->lun);
-#endif
+ dprintk(NDEBUG_MAIN|NDEBUG_QUEUES, ("scsi%d : main() : command for target %d lun %d removed from issue_queue\n", instance->host_no, tmp->target, tmp->lun));
/*
* A successful selection is defined as one that
@@ -1253,10 +1211,8 @@ static void NCR5380_main(void) {
* and see if we can do an information transfer,
* with failures we will restart.
*/
-#ifdef USLEEP
- hostdata->selecting = 0; /* RvC: have to preset this
- to indicate a new command is being performed */
-#endif
+ hostdata->selecting = 0;
+ /* RvC: have to preset this to indicate a new command is being performed */
if (!NCR5380_select(instance, tmp,
/*
@@ -1268,23 +1224,20 @@ static void NCR5380_main(void) {
(tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : TAG_NEXT)) {
break;
} else {
- cli();
LIST(tmp, hostdata->issue_queue);
- tmp->host_scribble = (unsigned char *)
- hostdata->issue_queue;
+ tmp->host_scribble = (unsigned char *) hostdata->issue_queue;
hostdata->issue_queue = tmp;
done = 0;
- restore_flags(flags);
-#if (NDEBUG & (NDEBUG_MAIN | NDEBUG_QUEUES))
- printk("scsi%d : main(): select() failed, returned to issue_queue\n", instance->host_no);
-#endif
+ dprintk(NDEBUG_MAIN|NDEBUG_QUEUES, ("scsi%d : main(): select() failed, returned to issue_queue\n", instance->host_no));
}
+ /* lock held here still */
} /* if target/lun is not busy */
} /* for */
+ /* exited locked */
} /* if (!hostdata->connected) */
-#ifdef USLEEP
if (hostdata->selecting) {
tmp = (Scsi_Cmnd *) hostdata->selecting;
+ /* Selection will drop and retake the lock */
if (!NCR5380_select(instance, tmp, (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : TAG_NEXT)) {
/* Ok ?? */
} else {
@@ -1293,56 +1246,46 @@ static void NCR5380_main(void) {
do not respond to commands immediately
after a scan */
printk(KERN_DEBUG "scsi%d: device %d did not respond in time\n", instance->host_no, tmp->target);
- cli();
+ //spin_lock_irq(&io_request_lock);
LIST(tmp, hostdata->issue_queue);
tmp->host_scribble = (unsigned char *) hostdata->issue_queue;
hostdata->issue_queue = tmp;
- restore_flags(flags);
+ //spin_unlock_irq(&io_request_lock);
hostdata->time_expires = jiffies + USLEEP_WAITLONG;
NCR5380_set_timer(instance);
}
} /* if hostdata->selecting */
-#endif
if (hostdata->connected
#ifdef REAL_DMA
&& !hostdata->dmalen
#endif
-#ifdef USLEEP
&& (!hostdata->time_expires || time_before_eq(hostdata->time_expires, jiffies))
-#endif
) {
- restore_flags(flags);
-#if (NDEBUG & NDEBUG_MAIN)
- printk("scsi%d : main() : performing information transfer\n", instance->host_no);
-#endif
+ dprintk(NDEBUG_MAIN, ("scsi%d : main() : performing information transfer\n", instance->host_no));
NCR5380_information_transfer(instance);
-#if (NDEBUG & NDEBUG_MAIN)
- printk("scsi%d : main() : done set false\n", instance->host_no);
-#endif
+ dprintk(NDEBUG_MAIN, ("scsi%d : main() : done set false\n", instance->host_no));
done = 0;
} else
break;
} /* for instance */
} while (!done);
- spin_lock_irq(&io_request_lock);
- /* cli(); */
- main_running = 0;
+ /* Exit lock held */
+ clear_bit(0, &main_running);
}
#ifndef DONT_USE_INTR
#include <linux/blk.h>
#include <linux/spinlock.h>
-/*
- * Function : void NCR5380_intr (int irq)
- *
- * Purpose : handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses
+/**
+ * NCR5380_intr - generic NCR5380 irq handler
+ *
+ * Handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses
* from the disconnected queue, and restarting NCR5380_main()
* as required.
*
- * Inputs : int irq, irq that caused this interrupt.
- *
+ * Locks: caller must hold the io_request lock.
*/
static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {
@@ -1350,13 +1293,9 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {
struct Scsi_Host *instance;
int done;
unsigned char basr;
- unsigned long flags;
- save_flags(flags);
- cli();
-#if (NDEBUG & NDEBUG_INTR)
- printk("scsi : NCR5380 irq %d triggered\n", irq);
-#endif
+ dprintk(NDEBUG_INTR, ("scsi : NCR5380 irq %d triggered\n", irq));
+
do {
done = 1;
for (instance = first_instance; instance && (instance->hostt == the_template); instance = instance->next)
@@ -1367,33 +1306,19 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {
basr = NCR5380_read(BUS_AND_STATUS_REG);
/* XXX dispatch to appropriate routine if found and done=0 */
if (basr & BASR_IRQ) {
-#if (NDEBUG & NDEBUG_INTR)
- NCR5380_print(instance);
-#endif
+ NCR5380_dprint(NDEBUG_INTR, instance);
if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {
done = 0;
- restore_flags(flags);
-#if (NDEBUG & NDEBUG_INTR)
- printk("scsi%d : SEL interrupt\n", instance->host_no);
-#endif
+ dprintk(NDEBUG_INTR, ("scsi%d : SEL interrupt\n", instance->host_no));
NCR5380_reselect(instance);
(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
} else if (basr & BASR_PARITY_ERROR) {
-#if (NDEBUG & NDEBUG_INTR)
- printk("scsi%d : PARITY interrupt\n", instance->host_no);
-#endif
+ dprintk(NDEBUG_INTR, ("scsi%d : PARITY interrupt\n", instance->host_no));
(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
} else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) {
-#if (NDEBUG & NDEBUG_INTR)
- printk("scsi%d : RESET interrupt\n", instance->host_no);
-#endif
+ dprintk(NDEBUG_INTR, ("scsi%d : RESET interrupt\n", instance->host_no));
(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
} else {
-/*
- * XXX the rest of the interrupt conditions should *only* occur during a
- * DMA transfer, which I haven't gotten around to fixing yet.
- */
-
#if defined(REAL_DMA)
/*
* We should only get PHASE MISMATCH and EOP interrupts
@@ -1424,7 +1349,7 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {
if (time_after_eq(jiffies, timeout))
printk("scsi%d: timeout at NCR5380.c:%d\n", host->host_no, __LINE__);
}
-#else /* NCR_TIMEOUT */
+#else /* NCR_TIMEOUT */
while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK);
#endif
@@ -1432,9 +1357,7 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
}
#else
-#if (NDEBUG & NDEBUG_INTR)
- printk("scsi : unknown interrupt, BASR 0x%X, MR 0x%X, SR 0x%x\n", basr, NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG));
-#endif
+ dprintk(NDEBUG_INTR, ("scsi : unknown interrupt, BASR 0x%X, MR 0x%X, SR 0x%x\n", basr, NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG)));
(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
#endif
}
@@ -1445,6 +1368,17 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {
} while (!done);
}
+/**
+ * do_NCR5380_intr
+ * @irq: interrupt number
+ * @dev_id: device info
+ * @regs: registers (unused)
+ *
+ * Takes the io_request_lock and invokes the generic NCR5380 interrupt
+ * handler code
+ *
+ * Locks: takes and releases the io_request lock
+ */
static void do_NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {
unsigned long flags;
@@ -1454,26 +1388,37 @@ static void do_NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {
spin_unlock_irqrestore(&io_request_lock, flags);
}
#endif
+
+
+/**
+ * collect_stats - collect stats on a scsi command
+ * @hostdata: adapter
+ * @cmd: command being issued
+ *
+ * Update the statistical data by parsing the command in question
+ */
+
+static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd)
+{
#ifdef NCR5380_STATS
-static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd) {
-#ifdef NCR5380_STAT_LIMIT
- if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
+ switch (cmd->cmnd[0]) {
+ case WRITE:
+ case WRITE_6:
+ case WRITE_10:
+ hostdata->time_write[cmd->target] += (jiffies - hostdata->timebase);
+ hostdata->pendingw--;
+ break;
+ case READ:
+ case READ_6:
+ case READ_10:
+ hostdata->time_read[cmd->target] += (jiffies - hostdata->timebase);
+ hostdata->pendingr--;
+ break;
+ }
#endif
- switch (cmd->cmnd[0]) {
- case WRITE:
- case WRITE_6:
- case WRITE_10:
- hostdata->time_write[cmd->target] += (jiffies - hostdata->timebase);
- /*hostdata->bytes_write[cmd->target] += cmd->request_bufflen; */
- hostdata->pendingw--;
- break;
- case READ:case READ_6:case READ_10:hostdata->time_read[cmd->target] += (jiffies - hostdata->timebase);
- /*hostdata->bytes_read[cmd->target] += cmd->request_bufflen; */
- hostdata->pendingr--;
- break;
- }
}
-#endif
+
+
/*
* Function : int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd,
* int tag);
@@ -1503,34 +1448,30 @@ static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd) {
*
* If failed (no target) : cmd->scsi_done() will be called, and the
* cmd->result host byte set to DID_BAD_TARGET.
- */ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) {
+ *
+ * Locks: caller holds io_request_lock
+ */
+
+static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
+{
NCR5380_local_declare();
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
unsigned char tmp[3], phase;
unsigned char *data;
int len;
unsigned long timeout;
- unsigned long flags;
-#ifdef USLEEP
unsigned char value;
-#endif
-
- NCR5380_setup(instance);
-
-#ifdef USLEEP
+ NCR5380_setup(instance);
if (hostdata->selecting) {
goto part2; /* RvC: sorry prof. Dijkstra, but it keeps the
rest of the code nearly the same */
}
-#endif
+
hostdata->restart_select = 0;
-#if defined (NDEBUG) && (NDEBUG & NDEBUG_ARBITRATION)
- NCR5380_print(instance);
- printk("scsi%d : starting arbitration, id = %d\n", instance->host_no, instance->this_id);
-#endif
- save_flags(flags);
- cli();
+
+ NCR5380_dprint(NDEBUG_ARBITRATION, instance);
+ dprintk(NDEBUG_ARBITRATION, ("scsi%d : starting arbitration, id = %d\n", instance->host_no, instance->this_id));
/*
* Set the phase bits to 0, otherwise the NCR5380 won't drive the
@@ -1539,7 +1480,6 @@ static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd) {
NCR5380_write(TARGET_COMMAND_REG, 0);
-
/*
* Start arbitration.
*/
@@ -1547,8 +1487,6 @@ static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd) {
NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
NCR5380_write(MODE_REG, MR_ARBITRATE);
- restore_flags(flags);
-
/* Wait for arbitration logic to complete */
#if NCR_TIMEOUT
{
@@ -1572,11 +1510,7 @@ static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd) {
while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS));
#endif
-#if (NDEBUG & NDEBUG_ARBITRATION)
- printk("scsi%d : arbitration complete\n", instance->host_no);
-/* Avoid GCC 2.4.5 asm needs to many reloads error */
- __asm__("nop");
-#endif
+ dprintk(NDEBUG_ARBITRATION, ("scsi%d : arbitration complete\n", instance->host_no));
/*
* The arbitration delay is 2.2us, but this is a minimum and there is
@@ -1590,9 +1524,7 @@ static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd) {
/* Check for lost arbitration */
if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) || (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) || (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) {
NCR5380_write(MODE_REG, MR_BASE);
-#if (NDEBUG & NDEBUG_ARBITRATION)
- printk("scsi%d : lost arbitration, deasserting MR_ARBITRATE\n", instance->host_no);
-#endif
+ dprintk(NDEBUG_ARBITRATION, ("scsi%d : lost arbitration, deasserting MR_ARBITRATE\n", instance->host_no));
return -1;
}
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_SEL);
@@ -1605,9 +1537,7 @@ static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd) {
(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) {
NCR5380_write(MODE_REG, MR_BASE);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-#if (NDEBUG & NDEBUG_ARBITRATION)
- printk("scsi%d : lost arbitration, deasserting ICR_ASSERT_SEL\n", instance->host_no);
-#endif
+ dprintk(NDEBUG_ARBITRATION, ("scsi%d : lost arbitration, deasserting ICR_ASSERT_SEL\n", instance->host_no));
return -1;
}
/*
@@ -1617,10 +1547,7 @@ static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd) {
udelay(2);
-#if (NDEBUG & NDEBUG_ARBITRATION)
- printk("scsi%d : won arbitration\n", instance->host_no);
-#endif
-
+ dprintk(NDEBUG_ARBITRATION, ("scsi%d : won arbitration\n", instance->host_no));
/*
* Now that we have won arbitration, start Selection process, asserting
@@ -1672,9 +1599,7 @@ static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd) {
udelay(1);
-#if (NDEBUG & NDEBUG_SELECTION)
- printk("scsi%d : selecting target %d\n", instance->host_no, cmd->target);
-#endif
+ dprintk(NDEBUG_SELECTION, ("scsi%d : selecting target %d\n", instance->host_no, cmd->target));
/*
* The SCSI specification calls for a 250 ms timeout for the actual
@@ -1689,11 +1614,10 @@ static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd) {
* and it's detecting as true. Sigh.
*/
-#ifdef USLEEP
hostdata->select_time = 0; /* we count the clock ticks at which we polled */
hostdata->selecting = cmd;
- part2:
+part2:
/* RvC: here we enter after a sleeping period, or immediately after
execution of part 1
we poll only once ech clock tick */
@@ -1710,11 +1634,6 @@ static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd) {
hostdata->selecting = 0; /* clear this pointer, because we passed the
waiting period */
-#else
- spin_unlock_irq(&io_request_lock);
- while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & (SR_BSY | SR_IO)));
- spin_lock_irq(&io_request_lock);
-#endif
if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
NCR5380_reselect(instance);
@@ -1738,21 +1657,15 @@ static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd) {
printk("scsi%d : weirdness\n", instance->host_no);
if (hostdata->restart_select)
printk("\trestart select\n");
-#if (NDEBUG & NDEBUG_SELECTION)
- NCR5380_print(instance);
-#endif
+ NCR5380_dprint(NDEBUG_SELECTION, instance);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
return -1;
}
cmd->result = DID_BAD_TARGET << 16;
-#ifdef NCR5380_STATS
collect_stats(hostdata, cmd);
-#endif
cmd->scsi_done(cmd);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-#if (NDEBUG & NDEBUG_SELECTION)
- printk("scsi%d : target did not respond within 250ms\n", instance->host_no);
-#endif
+ dprintk(NDEBUG_SELECTION, ("scsi%d : target did not respond within 250ms\n", instance->host_no));
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
return 0;
}
@@ -1792,46 +1705,20 @@ static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd) {
while (!(NCR5380_read(STATUS_REG) & SR_REQ));
#endif /* def NCR_TIMEOUT */
-#if (NDEBUG & NDEBUG_SELECTION)
- printk("scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->target);
-#endif
+ dprintk(NDEBUG_SELECTION, ("scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->target));
tmp[0] = IDENTIFY(((instance->irq == IRQ_NONE) ? 0 : 1), cmd->lun);
-#ifdef SCSI2
- if (cmd->device->tagged_queue && (tag != TAG_NONE)) {
- tmp[1] = SIMPLE_QUEUE_TAG;
- if (tag == TAG_NEXT) {
- /* 0 is TAG_NONE, used to imply no tag for this command */
- if (cmd->device->current_tag == 0)
- cmd->device->current_tag = 1;
-
- cmd->tag = cmd->device->current_tag;
- cmd->device->current_tag++;
- } else
- cmd->tag = (unsigned char) tag;
-
- tmp[2] = cmd->tag;
- hostdata->last_message = SIMPLE_QUEUE_TAG;
- len = 3;
- } else
-#endif /* def SCSI2 */
- {
- len = 1;
- cmd->tag = 0;
- }
+
+ len = 1;
+ cmd->tag = 0;
/* Send message(s) */
data = tmp;
phase = PHASE_MSGOUT;
NCR5380_transfer_pio(instance, &phase, &len, &data);
-#if (NDEBUG & NDEBUG_SELECTION)
- printk("scsi%d : nexus established.\n", instance->host_no);
-#endif
+ dprintk(NDEBUG_SELECTION, ("scsi%d : nexus established.\n", instance->host_no));
/* XXX need to handle errors here */
hostdata->connected = cmd;
-#ifdef SCSI2
- if (!cmd->device->tagged_queue)
-#endif
- hostdata->busy[cmd->target] |= (1 << cmd->lun);
+ hostdata->busy[cmd->target] |= (1 << cmd->lun);
initialize_SCp(cmd);
@@ -1866,24 +1753,20 @@ static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd) {
static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data) {
NCR5380_local_declare();
- register unsigned char p = *phase, tmp;
- register int c = *count;
- register unsigned char *d = *data;
-#ifdef USLEEP
+ unsigned char p = *phase, tmp;
+ int c = *count;
+ unsigned char *d = *data;
/*
* RvC: some administrative data to process polling time
*/
int break_allowed = 0;
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
-#endif
- NCR5380_setup(instance);
+ NCR5380_setup(instance);
-#if (NDEBUG & NDEBUG_PIO)
if (!(p & SR_IO))
- printk("scsi%d : pio write %d bytes\n", instance->host_no, c);
+ dprintk(NDEBUG_PIO, ("scsi%d : pio write %d bytes\n", instance->host_no, c));
else
- printk("scsi%d : pio read %d bytes\n", instance->host_no, c);
-#endif
+ dprintk(NDEBUG_PIO, ("scsi%d : pio read %d bytes\n", instance->host_no, c));
/*
* The NCR5380 chip will only drive the SCSI bus when the
@@ -1893,21 +1776,18 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase
NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
-#ifdef USLEEP
/* RvC: don't know if this is necessary, but other SCSI I/O is short
* so breaks are not necessary there
*/
if ((p == PHASE_DATAIN) || (p == PHASE_DATAOUT)) {
break_allowed = 1;
}
-#endif
do {
/*
* Wait for assertion of REQ, after which the phase bits will be
* valid
*/
-#ifdef USLEEP
/* RvC: we simply poll once, after that we stop temporarily
* and let the device buffer fill up
* if breaking is not allowed, we keep polling as long as needed
@@ -1920,20 +1800,13 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase
NCR5380_set_timer(instance);
break;
}
-#else
- while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ));
-#endif
-#if (NDEBUG & NDEBUG_HANDSHAKE)
- printk("scsi%d : REQ detected\n", instance->host_no);
-#endif
+ dprintk(NDEBUG_HANDSHAKE, ("scsi%d : REQ detected\n", instance->host_no));
/* Check for phase mismatch */
if ((tmp & PHASE_MASK) != p) {
-#if (NDEBUG & NDEBUG_PIO)
- printk("scsi%d : phase mismatch\n", instance->host_no);
- NCR5380_print_phase(instance);
-#endif
+ dprintk(NDEBUG_HANDSHAKE, ("scsi%d : phase mismatch\n", instance->host_no));
+ NCR5380_dprint_phase(NDEBUG_HANDSHAKE, instance);
break;
}
/* Do actual transfer from SCSI bus to / from memory */
@@ -1954,29 +1827,21 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase
if (!(p & SR_IO)) {
if (!((p & SR_MSG) && c > 1)) {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
-#if (NDEBUG & NDEBUG_PIO)
- NCR5380_print(instance);
-#endif
+ NCR5380_dprint(NDEBUG_PIO, instance);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ACK);
} else {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ATN);
-#if (NDEBUG & NDEBUG_PIO)
- NCR5380_print(instance);
-#endif
+ NCR5380_dprint(NDEBUG_PIO, instance);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
}
} else {
-#if (NDEBUG & NDEBUG_PIO)
- NCR5380_print(instance);
-#endif
+ NCR5380_dprint(NDEBUG_PIO, instance);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
}
while (NCR5380_read(STATUS_REG) & SR_REQ);
-#if (NDEBUG & NDEBUG_HANDSHAKE)
- printk("scsi%d : req false, handshake complete\n", instance->host_no);
-#endif
+ dprintk(NDEBUG_HANDSHAKE, ("scsi%d : req false, handshake complete\n", instance->host_no));
/*
* We have several special cases to consider during REQ/ACK handshaking :
@@ -1997,9 +1862,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase
}
} while (--c);
-#if (NDEBUG & NDEBUG_PIO)
- printk("scsi%d : residual %d\n", instance->host_no, c);
-#endif
+ dprintk(NDEBUG_PIO, ("scsi%d : residual %d\n", instance->host_no, c));
*count = c;
*data = d;
@@ -2015,35 +1878,46 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase
return -1;
}
+/**
+ * do_reset - issue a reset command
+ * @host: adapter to reset
+ *
+ * Issue a reset sequence to the NCR5380 and try and get the bus
+ * back into sane shape.
+ *
+ * Locks: caller holds io_request lock
+ */
+
static void do_reset(struct Scsi_Host *host) {
- unsigned long flags;
- NCR5380_local_declare();
- NCR5380_setup(host);
-
- save_flags(flags);
- cli();
- NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG) & PHASE_MASK));
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST);
- udelay(25);
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
- restore_flags(flags);
-} /*
-
- * Function : do_abort (Scsi_Host *host)
- *
- * Purpose : abort the currently established nexus. Should only be
- * called from a routine which can drop into a
- *
- * Returns : 0 on success, -1 on failure.
- */ static int do_abort(struct Scsi_Host *host) {
+ NCR5380_local_declare();
+ NCR5380_setup(host);
+
+ NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG) & PHASE_MASK));
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST);
+ udelay(25);
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+}
+
+/*
+ * Function : do_abort (Scsi_Host *host)
+ *
+ * Purpose : abort the currently established nexus. Should only be
+ * called from a routine which can drop into a
+ *
+ * Returns : 0 on success, -1 on failure.
+ *
+ * Locks: io_request lock held by caller
+ */
+
+static int do_abort(struct Scsi_Host *host) {
NCR5380_local_declare();
unsigned char tmp, *msgptr, phase;
int len;
- NCR5380_setup(host);
+ NCR5380_setup(host);
/* Request message out phase */
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
/*
* Wait for the target to indicate a valid phase by asserting
@@ -2057,7 +1931,7 @@ static void do_reset(struct Scsi_Host *host) {
while (!(tmp = NCR5380_read(STATUS_REG)) & SR_REQ);
- NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
+ NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
if ((tmp & PHASE_MASK) != PHASE_MSGOUT) {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
@@ -2096,6 +1970,7 @@ static void do_reset(struct Scsi_Host *host) {
*
* Also, *phase, *count, *data are modified in place.
*
+ * Locks: io_request lock held by caller
*/
@@ -2105,19 +1980,15 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase
register unsigned char p = *phase;
register unsigned char *d = *data;
unsigned char tmp;
-#if defined(PSEUDO_DMA) && !defined(UNSAFE)
- unsigned long flags;
-#endif
int foo;
#if defined(REAL_DMA_POLL)
int cnt, toPIO;
unsigned char saved_data = 0, overrun = 0, residue;
#endif
- struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)
- instance->hostdata;
+ struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
- NCR5380_setup(instance);
+ NCR5380_setup(instance);
if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) {
*phase = tmp;
@@ -2129,9 +2000,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase
c -= 2;
}
#endif
-#if (NDEBUG & NDEBUG_DMA)
- printk("scsi%d : initializing DMA channel %d for %s, %d bytes %s %0x\n", instance->host_no, instance->dma_channel, (p & SR_IO) ? "reading" : "writing", c, (p & SR_IO) ? "to" : "from", (unsigned) d);
-#endif
+ dprintk(NDEBUG_DMA, ("scsi%d : initializing DMA channel %d for %s, %d bytes %s %0x\n", instance->host_no, instance->dma_channel, (p & SR_IO) ? "reading" : "writing", c, (p & SR_IO) ? "to" : "from", (unsigned) d));
hostdata->dma_len = (p & SR_IO) ? NCR5380_dma_read_setup(instance, d, c) : NCR5380_dma_write_setup(instance, d, c);
#endif
@@ -2148,9 +2017,8 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase
* before the setting of DMA mode to after transfer of the last byte.
*/
-#if defined(PSEUDO_DMA) && !defined(UNSAFE)
- save_flags(flags);
- cli();
+#if defined(PSEUDO_DMA) && defined(UNSAFE)
+ spin_unlock_irq(&io_request_lock);
#endif
/* KLL May need eop and parity in 53c400 */
if (hostdata->flags & FLAG_NCR53C400)
@@ -2159,36 +2027,22 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase
NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE);
#endif /* def REAL_DMA */
-#if (NDEBUG & NDEBUG_DMA) & 0
- printk("scsi%d : mode reg = 0x%X\n", instance->host_no, NCR5380_read(MODE_REG));
-#endif
+ dprintk(NDEBUG_DMA, ("scsi%d : mode reg = 0x%X\n", instance->host_no, NCR5380_read(MODE_REG)));
-/*
- * FOO stuff. For some UNAPPARENT reason, I'm getting
- * watchdog timers fired on bootup for NO APPARENT REASON, meaning it's
- * probably a timing problem.
- *
- * Since this is the only place I have back-to-back writes, perhaps this
- * is the problem?
- */
+ /*
+ * On the PAS16 at least I/O recovery delays are not needed here.
+ * Everyone else seems to want them.
+ */
if (p & SR_IO) {
-#ifndef FOO
- udelay(1);
-#endif
+ io_recovery_delay(1);
NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0);
} else {
-#ifndef FOO
- udelay(1);
-#endif
+ io_recovery_delay(1);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
-#ifndef FOO
- udelay(1);
-#endif
+ io_recovery_delay(1);
NCR5380_write(START_DMA_SEND_REG, 0);
-#ifndef FOO
- udelay(1);
-#endif
+ io_recovery_delay(1);
}
#if defined(REAL_DMA_POLL)
@@ -2250,10 +2104,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase
}
}
-
-#if (NDEBUG & NDEBUG_DMA)
- printk("scsi%d : polled DMA transfer complete, basr 0x%X, sr 0x%X\n", instance->host_no, tmp, NCR5380_read(STATUS_REG));
-#endif
+ dprintk(NDEBUG_DMA, ("scsi%d : polled DMA transfer complete, basr 0x%X, sr 0x%X\n", instance->host_no, tmp, NCR5380_read(STATUS_REG)));
NCR5380_write(MODE_REG, MR_BASE);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
@@ -2267,9 +2118,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase
#ifdef READ_OVERRUNS
if (*phase == p && (p & SR_IO) && residue == 0) {
if (overrun) {
-#if (NDEBUG & NDEBUG_DMA)
- printk("Got an input overrun, using saved byte\n");
-#endif
+ dprintk(NDEBUG_DMA, ("Got an input overrun, using saved byte\n"));
**data = saved_data;
*data += 1;
*count -= 1;
@@ -2278,17 +2127,13 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase
printk("No overrun??\n");
cnt = toPIO = 2;
}
-#if (NDEBUG & NDEBUG_DMA)
- printk("Doing %d-byte PIO to 0x%X\n", cnt, *data);
-#endif
+ dprintk(NDEBUG_DMA, ("Doing %d-byte PIO to 0x%X\n", cnt, *data));
NCR5380_transfer_pio(instance, phase, &cnt, data);
*count -= toPIO - cnt;
}
#endif
-#if (NDEBUG & NDEBUG_DMA)
- printk("Return with data ptr = 0x%X, count %d, last 0x%X, next 0x%X\n", *data, *count, *(*data + *count - 1), *(*data + *count));
-#endif
+ dprintk(NDEBUG_DMA, ("Return with data ptr = 0x%X, count %d, last 0x%X, next 0x%X\n", *data, *count, *(*data + *count - 1), *(*data + *count)));
return 0;
#elif defined(REAL_DMA)
@@ -2338,9 +2183,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase
foo = NCR5380_pwrite(instance, d, c);
#else
int timeout;
-#if (NDEBUG & NDEBUG_C400_PWRITE)
- printk("About to pwrite %d bytes\n", c);
-#endif
+ dprintk(NDEBUG_C400_PWRITE, ("About to pwrite %d bytes\n", c));
if (!(foo = NCR5380_pwrite(instance, d, c))) {
/*
* Wait for the last byte to be sent. If REQ is being asserted for
@@ -2350,30 +2193,20 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase
timeout = 20000;
while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) && (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH));
-
-#if (NDEBUG & NDEBUG_LAST_BYTE_SENT)
if (!timeout)
- printk("scsi%d : timed out on last byte\n", instance->host_no);
-#endif
-
+ dprintk(NDEBUG_LAST_BYTE_SENT, ("scsi%d : timed out on last byte\n", instance->host_no));
if (hostdata->flags & FLAG_CHECK_LAST_BYTE_SENT) {
hostdata->flags &= ~FLAG_CHECK_LAST_BYTE_SENT;
if (NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT) {
hostdata->flags |= FLAG_HAS_LAST_BYTE_SENT;
-#if (NDEBUG & NDEBUG_LAST_BYTE_SENT)
- printk("scsi%d : last bit sent works\n", instance->host_no);
-#endif
+ dprintk(NDEBUG_LAST_WRITE_SENT, ("scsi%d : last bit sent works\n", instance->host_no));
}
}
} else {
-#if (NDEBUG & NDEBUG_C400_PWRITE)
- printk("Waiting for LASTBYTE\n");
-#endif
+ dprintk(NDEBUG_C400_PWRITE, ("Waiting for LASTBYTE\n"));
while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT));
-#if (NDEBUG & NDEBUG_C400_PWRITE)
- printk("Got LASTBYTE\n");
-#endif
+ dprintk(NDEBUG_C400_PWRITE, ("Got LASTBYTE\n"));
}
}
#endif
@@ -2382,13 +2215,9 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
if ((!(p & SR_IO)) && (hostdata->flags & FLAG_NCR53C400)) {
-#if (NDEBUG & NDEBUG_C400_PWRITE)
- printk("53C400w: Checking for IRQ\n");
-#endif
+ dprintk(NDEBUG_C400_PWRITE, ("53C400w: Checking for IRQ\n"));
if (NCR5380_read(BUS_AND_STATUS_REG) & BASR_IRQ) {
-#if (NDEBUG & NDEBUG_C400_PWRITE)
- printk("53C400w: got it, reading reset interrupt reg\n");
-#endif
+ dprintk(NDEBUG_C400_PWRITE, ("53C400w: got it, reading reset interrupt reg\n"));
NCR5380_read(RESET_PARITY_INTERRUPT_REG);
} else {
printk("53C400w: IRQ NOT THERE!\n");
@@ -2397,11 +2226,8 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase
*data = d + c;
*count = 0;
*phase = NCR5380_read(STATUS_REG) & PHASE_MASK;
-#if 0
- NCR5380_print_phase(instance);
-#endif
-#if defined(PSEUDO_DMA) && !defined(UNSAFE)
- restore_flags(flags);
+#if defined(PSEUDO_DMA) && defined(UNSAFE)
+ spin_lock_irq(&io_request_lock);
#endif /* defined(REAL_DMA_POLL) */
return foo;
#endif /* def REAL_DMA */
@@ -2423,12 +2249,13 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase
*
* XXX Note : we need to watch for bus free or a reset condition here
* to recover from an unexpected bus free condition.
+ *
+ * Locks: io_request_lock held by caller
*/
static void NCR5380_information_transfer(struct Scsi_Host *instance) {
NCR5380_local_declare();
- struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)
- instance->hostdata;
+ struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)instance->hostdata;
unsigned char msgout = NOP;
int sink = 0;
int len;
@@ -2438,12 +2265,10 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
unsigned char *data;
unsigned char phase, tmp, extended_msg[10], old_phase = 0xff;
Scsi_Cmnd *cmd = (Scsi_Cmnd *) hostdata->connected;
-#ifdef USLEEP
/* RvC: we need to set the end of the polling time */
unsigned long poll_time = jiffies + USLEEP_POLL;
-#endif
- NCR5380_setup(instance);
+ NCR5380_setup(instance);
while (1) {
tmp = NCR5380_read(STATUS_REG);
@@ -2452,9 +2277,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
phase = (tmp & PHASE_MASK);
if (phase != old_phase) {
old_phase = phase;
-#if (NDEBUG & NDEBUG_INFORMATION)
- NCR5380_print_phase(instance);
-#endif
+ NCR5380_dprint_phase(NDEBUG_INFORMATION, instance);
}
if (sink && (phase != PHASE_MSGOUT)) {
NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
@@ -2486,9 +2309,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
--cmd->SCp.buffers_residual;
cmd->SCp.this_residual = cmd->SCp.buffer->length;
cmd->SCp.ptr = cmd->SCp.buffer->address;
-#if (NDEBUG & NDEBUG_INFORMATION)
- printk("scsi%d : %d bytes and %d buffers left\n", instance->host_no, cmd->SCp.this_residual, cmd->SCp.buffers_residual);
-#endif
+ dprintk(NDEBUG_INFORMATION, ("scsi%d : %d bytes and %d buffers left\n", instance->host_no, cmd->SCp.this_residual, cmd->SCp.buffers_residual));
}
/*
* The preferred transfer method is going to be
@@ -2567,16 +2388,12 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
case LINKED_FLG_CMD_COMPLETE:
/* Accept message by clearing ACK */
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-
-#if (NDEBUG & NDEBUG_LINKED)
- printk("scsi%d : target %d lun %d linked command complete.\n", instance->host_no, cmd->target, cmd->lun);
-#endif
+ dprintk(NDEBUG_LINKED, ("scsi%d : target %d lun %d linked command complete.\n", instance->host_no, cmd->target, cmd->lun));
/*
* Sanity check : A linked command should only terminate with
* one of these messages if there are more linked commands
* available.
*/
-
if (!cmd->next_link) {
printk("scsi%d : target %d lun %d linked command complete, no next_link\n" instance->host_no, cmd->target, cmd->lun);
sink = 1;
@@ -2587,12 +2404,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
/* The next command is still part of this process */
cmd->next_link->tag = cmd->tag;
cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
-#if (NDEBUG & NDEBUG_LINKED)
- printk("scsi%d : target %d lun %d linked request done, calling scsi_done().\n", instance->host_no, cmd->target, cmd->lun);
-#endif
-#ifdef NCR5380_STATS
+ dprintk(NDEBUG_LINKED, ("scsi%d : target %d lun %d linked request done, calling scsi_done().\n", instance->host_no, cmd->target, cmd->lun));
collect_stats(hostdata, cmd);
-#endif
cmd->scsi_done(cmd);
cmd = hostdata->connected;
break;
@@ -2603,9 +2416,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
sink = 1;
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
hostdata->connected = NULL;
-#if (NDEBUG & NDEBUG_QUEUES)
- printk("scsi%d : command for target %d, lun %d completed\n", instance->host_no, cmd->target, cmd->lun);
-#endif
+ dprintk(NDEBUG_QUEUES, ("scsi%d : command for target %d, lun %d completed\n", instance->host_no, cmd->target, cmd->lun));
hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
/*
@@ -2631,10 +2442,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
#ifdef AUTOSENSE
if ((cmd->cmnd[0] != REQUEST_SENSE) && (cmd->SCp.Status == CHECK_CONDITION)) {
- unsigned long flags;
-#if (NDEBUG & NDEBUG_AUTOSENSE)
- printk("scsi%d : performing request sense\n", instance->host_no);
-#endif
+ dprintk(NDEBUG_AUTOSENSE, ("scsi%d : performing request sense\n", instance->host_no));
cmd->cmnd[0] = REQUEST_SENSE;
cmd->cmnd[1] &= 0xe0;
cmd->cmnd[2] = 0;
@@ -2647,21 +2455,14 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
cmd->SCp.ptr = (char *) cmd->sense_buffer;
cmd->SCp.this_residual = sizeof(cmd->sense_buffer);
- save_flags(flags);
- cli();
LIST(cmd, hostdata->issue_queue);
cmd->host_scribble = (unsigned char *)
hostdata->issue_queue;
hostdata->issue_queue = (Scsi_Cmnd *) cmd;
- restore_flags(flags);
-#if (NDEBUG & NDEBUG_QUEUES)
- printk("scsi%d : REQUEST SENSE added to head of issue queue\n", instance->host_no);
-#endif
+ dprintk(NDEBUG_QUEUES, ("scsi%d : REQUEST SENSE added to head of issue queue\n", instance->host_no));
} else {
#endif /* def AUTOSENSE */
-#ifdef NCR5380_STATS
collect_stats(hostdata, cmd);
-#endif
cmd->scsi_done(cmd);
}
@@ -2689,21 +2490,15 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
break;
}
case DISCONNECT:{
- unsigned long flags;
/* Accept message by clearing ACK */
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
cmd->device->disconnect = 1;
- save_flags(flags);
- cli();
LIST(cmd, hostdata->disconnected_queue);
cmd->host_scribble = (unsigned char *)
hostdata->disconnected_queue;
hostdata->connected = NULL;
hostdata->disconnected_queue = cmd;
- restore_flags(flags);
-#if (NDEBUG & NDEBUG_QUEUES)
- printk("scsi%d : command for target %d lun %d was moved from connected to" " the disconnected_queue\n", instance->host_no, cmd->target, cmd->lun);
-#endif
+ dprintk(NDEBUG_QUEUES, ("scsi%d : command for target %d lun %d was moved from connected to" " the disconnected_queue\n", instance->host_no, cmd->target, cmd->lun));
/*
* Restore phase bits to 0 so an interrupted selection,
* arbitration can resume.
@@ -2715,9 +2510,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
/* Wait for bus free to avoid nasty timeouts */
while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
barrier();
-#if 0
- NCR5380_print_status(instance);
-#endif
return;
}
/*
@@ -2751,19 +2543,14 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
extended_msg[0] = EXTENDED_MESSAGE;
/* Accept first byte by clearing ACK */
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-
-#if (NDEBUG & NDEBUG_EXTENDED)
- printk("scsi%d : receiving extended message\n", instance->host_no);
-#endif
+ dprintk(NDEBUG_EXTENDED, ("scsi%d : receiving extended message\n", instance->host_no));
len = 2;
data = extended_msg + 1;
phase = PHASE_MSGIN;
NCR5380_transfer_pio(instance, &phase, &len, &data);
-#if (NDEBUG & NDEBUG_EXTENDED)
- printk("scsi%d : length=%d, code=0x%02x\n", instance->host_no, (int) extended_msg[1], (int) extended_msg[2]);
-#endif
+ dprintk(NDEBUG_EXTENDED, ("scsi%d : length=%d, code=0x%02x\n", instance->host_no, (int) extended_msg[1], (int) extended_msg[2]));
if (!len && extended_msg[1] <= (sizeof(extended_msg) - 1)) {
/* Accept third byte by clearing ACK */
@@ -2773,10 +2560,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
phase = PHASE_MSGIN;
NCR5380_transfer_pio(instance, &phase, &len, &data);
-
-#if (NDEBUG & NDEBUG_EXTENDED)
- printk("scsi%d : message received, residual %d\n", instance->host_no, len);
-#endif
+ dprintk(NDEBUG_EXTENDED, ("scsi%d : message received, residual %d\n", instance->host_no, len));
switch (extended_msg[2]) {
case EXTENDED_SDTR:
@@ -2822,9 +2606,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
hostdata->connected = NULL;
cmd->result = DID_ERROR << 16;
-#ifdef NCR5380_STATS
collect_stats(hostdata, cmd);
-#endif
cmd->scsi_done(cmd);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
return;
@@ -2840,16 +2622,12 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
* use the dma transfer function.
*/
NCR5380_transfer_pio(instance, &phase, &len, &data);
-#ifdef USLEEP
if (!cmd->device->disconnect && should_disconnect(cmd->cmnd[0])) {
hostdata->time_expires = jiffies + USLEEP_SLEEP;
-#if (NDEBUG & NDEBUG_USLEEP)
- printk("scsi%d : issued command, sleeping until %ul\n", instance->host_no, hostdata->time_expires);
-#endif
+ dprintk(NDEBUG_USLEEP, ("scsi%d : issued command, sleeping until %ul\n", instance->host_no, hostdata->time_expires));
NCR5380_set_timer(instance);
return;
}
-#endif /* def USLEEP */
break;
case PHASE_STATIN:
len = 1;
@@ -2859,25 +2637,19 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
break;
default:
printk("scsi%d : unknown phase\n", instance->host_no);
-#ifdef NDEBUG
- NCR5380_print(instance);
-#endif
+ NCR5380_dprint(NDEBUG_ALL, instance);
} /* switch(phase) */
} /* if (tmp * SR_REQ) */
-#ifdef USLEEP
else {
/* RvC: go to sleep if polling time expired
*/
if (!cmd->device->disconnect && time_after_eq(jiffies, poll_time)) {
hostdata->time_expires = jiffies + USLEEP_SLEEP;
-#if (NDEBUG & NDEBUG_USLEEP)
- printk("scsi%d : poll timed out, sleeping until %ul\n", instance->host_no, hostdata->time_expires);
-#endif
+ dprintk(NDEBUG_USLEEP, ("scsi%d : poll timed out, sleeping until %ul\n", instance->host_no, hostdata->time_expires));
NCR5380_set_timer(instance);
return;
}
}
-#endif
} /* while (1) */
}
@@ -2890,9 +2662,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
*
* Inputs : instance - this instance of the NCR5380.
*
+ * Locks: io_request_lock held by caller
*/
-
static void NCR5380_reselect(struct Scsi_Host *instance) {
NCR5380_local_declare();
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)
@@ -2900,28 +2672,22 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
unsigned char target_mask;
unsigned char lun, phase;
int len;
-#ifdef SCSI2
- unsigned char tag;
-#endif
unsigned char msg[3];
unsigned char *data;
Scsi_Cmnd *tmp = NULL, *prev;
int abort = 0;
- NCR5380_setup(instance);
+ NCR5380_setup(instance);
/*
* Disable arbitration, etc. since the host adapter obviously
* lost, and tell an interrupted NCR5380_select() to restart.
*/
- NCR5380_write(MODE_REG, MR_BASE);
- hostdata->restart_select = 1;
-
- target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask);
+ NCR5380_write(MODE_REG, MR_BASE);
+ hostdata->restart_select = 1;
-#if (NDEBUG & NDEBUG_RESELECTION)
- printk("scsi%d : reselect\n", instance->host_no);
-#endif
+ target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask);
+ dprintk(NDEBUG_SELECTION, ("scsi%d : reselect\n", instance->host_no));
/*
* At this point, we have detected that our SCSI ID is on the bus,
@@ -2932,10 +2698,10 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
* signal.
*/
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY);
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY);
while (NCR5380_read(STATUS_REG) & SR_SEL);
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
/*
* Wait for target to go into MSGIN.
@@ -2943,11 +2709,10 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
while (!(NCR5380_read(STATUS_REG) & SR_REQ));
- len = 1;
- data = msg;
- phase = PHASE_MSGIN;
- NCR5380_transfer_pio(instance, &phase, &len, &data);
-
+ len = 1;
+ data = msg;
+ phase = PHASE_MSGIN;
+ NCR5380_transfer_pio(instance, &phase, &len, &data);
if (!msg[0] & 0x80) {
printk("scsi%d : expecting IDENTIFY message, got ", instance->host_no);
@@ -2964,10 +2729,6 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
* nexuses so we can chose to do additional data transfer.
*/
-#ifdef SCSI2
-#error "SCSI-II tagged queueing is not supported yet"
-#endif
-
/*
* Find the command corresponding to the I_T_L or I_T_L_Q nexus we
* just reestablished, and remove it from the disconnected queue.
@@ -2976,9 +2737,6 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble)
if ((target_mask == (1 << tmp->target)) && (lun == tmp->lun)
-#ifdef SCSI2
- && (tag == tmp->tag)
-#endif
) {
if (prev) {
REMOVE(prev, prev->host_scribble, tmp, tmp->host_scribble);
@@ -2991,11 +2749,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
break;
}
if (!tmp) {
-#ifdef SCSI2
- printk("scsi%d : warning : target bitmask %02x lun %d tag %d not in disconnect_queue.\n", instance->host_no, target_mask, lun, tag);
-#else
printk("scsi%d : warning : target bitmask %02x lun %d not in disconnect_queue.\n", instance->host_no, target_mask, lun);
-#endif
/*
* Since we have an established nexus that we can't do anything with,
* we must abort it.
@@ -3008,9 +2762,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
do_abort(instance);
} else {
hostdata->connected = tmp;
-#if (NDEBUG & NDEBUG_RESELECTION)
- printk("scsi%d : nexus established, target = %d, lun = %d, tag = %d\n", instance->host_no, tmp->target, tmp->lun, tmp->tag);
-#endif
+ dprintk(NDEBUG_RESELECTION, ("scsi%d : nexus established, target = %d, lun = %d, tag = %d\n", instance->host_no, tmp->target, tmp->lun, tmp->tag));
}
}
@@ -3072,10 +2824,12 @@ static void NCR5380_dma_complete(NCR5380_instance * instance) {
*
* Returns : 0 - success, -1 on failure.
*
- * XXX - there is no way to abort the command that is currently
- * connected, you have to wait for it to complete. If this is
- * a problem, we could implement longjmp() / setjmp(), setjmp()
- * called where the loop started in NCR5380_main().
+ * XXX - there is no way to abort the command that is currently
+ * connected, you have to wait for it to complete. If this is
+ * a problem, we could implement longjmp() / setjmp(), setjmp()
+ * called where the loop started in NCR5380_main().
+ *
+ * Locks: io_request_lock held by caller
*/
#ifndef NCR5380_abort
@@ -3083,10 +2837,8 @@ static
#endif
int NCR5380_abort(Scsi_Cmnd * cmd) {
NCR5380_local_declare();
- unsigned long flags;
struct Scsi_Host *instance = cmd->host;
- struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)
- instance->hostdata;
+ struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
Scsi_Cmnd *tmp, **prev;
printk("scsi%d : aborting command\n", instance->host_no);
@@ -3099,14 +2851,10 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
NCR5380_print_status(instance);
- save_flags(flags);
- cli();
NCR5380_setup(instance);
-#if (NDEBUG & NDEBUG_ABORT)
- printk("scsi%d : abort called\n", instance->host_no);
- printk(" basr 0x%X, sr 0x%X\n", NCR5380_read(BUS_AND_STATUS_REG), NCR5380_read(STATUS_REG));
-#endif
+ dprintk(NDEBUG_ABORT, ("scsi%d : abort called\n", instance->host_no));
+ dprintk(NDEBUG_ABORT, (" basr 0x%X, sr 0x%X\n", NCR5380_read(BUS_AND_STATUS_REG), NCR5380_read(STATUS_REG)));
#if 0
/*
@@ -3116,9 +2864,7 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
*/
if (hostdata->connected == cmd) {
-#if (NDEBUG & NDEBUG_ABORT)
- printk("scsi%d : aborting connected command\n", instance->host_no);
-#endif
+ dprintk(NDEBUG_ABORT, ("scsi%d : aborting connected command\n", instance->host_no));
hostdata->aborted = 1;
/*
* We should perform BSY checking, and make sure we haven't slipped
@@ -3145,20 +2891,15 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
* Case 2 : If the command hasn't been issued yet, we simply remove it
* from the issue queue.
*/
-#if (NDEBUG & NDEBUG_ABORT)
/* KLL */
- printk("scsi%d : abort going into loop.\n", instance->host_no);
-#endif
+ dprintk(NDEBUG_ABORT, ("scsi%d : abort going into loop.\n", instance->host_no));
for (prev = (Scsi_Cmnd **) & (hostdata->issue_queue), tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp; prev = (Scsi_Cmnd **) & (tmp->host_scribble), tmp = (Scsi_Cmnd *) tmp->host_scribble)
if (cmd == tmp) {
REMOVE(5, *prev, tmp, tmp->host_scribble);
(*prev) = (Scsi_Cmnd *) tmp->host_scribble;
tmp->host_scribble = NULL;
tmp->result = DID_ABORT << 16;
- restore_flags(flags);
-#if (NDEBUG & NDEBUG_ABORT)
- printk("scsi%d : abort removed command from issue queue.\n", instance->host_no);
-#endif
+ dprintk(NDEBUG_ABORT, ("scsi%d : abort removed command from issue queue.\n", instance->host_no));
tmp->done(tmp);
return SCSI_ABORT_SUCCESS;
}
@@ -3180,10 +2921,7 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
*/
if (hostdata->connected) {
- restore_flags(flags);
-#if (NDEBUG & NDEBUG_ABORT)
- printk("scsi%d : abort failed, command connected.\n", instance->host_no);
-#endif
+ dprintk(NDEBUG_ABORT, ("scsi%d : abort failed, command connected.\n", instance->host_no));
return SCSI_ABORT_NOT_RUNNING;
}
/*
@@ -3213,28 +2951,20 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp; tmp = (Scsi_Cmnd *) tmp->host_scribble)
if (cmd == tmp) {
- restore_flags(flags);
-#if (NDEBUG & NDEBUG_ABORT)
- printk("scsi%d : aborting disconnected command.\n", instance->host_no);
-#endif
+ dprintk(NDEBUG_ABORT, ("scsi%d : aborting disconnected command.\n", instance->host_no));
if (NCR5380_select(instance, cmd, (int) cmd->tag))
return SCSI_ABORT_BUSY;
-
-#if (NDEBUG & NDEBUG_ABORT)
- printk("scsi%d : nexus reestablished.\n", instance->host_no);
-#endif
+ dprintk(NDEBUG_ABORT, ("scsi%d : nexus reestablished.\n", instance->host_no));
do_abort(instance);
- cli();
for (prev = (Scsi_Cmnd **) & (hostdata->disconnected_queue), tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp; prev = (Scsi_Cmnd **) & (tmp->host_scribble), tmp = (Scsi_Cmnd *) tmp->host_scribble)
if (cmd == tmp) {
REMOVE(5, *prev, tmp, tmp->host_scribble);
*prev = (Scsi_Cmnd *) tmp->host_scribble;
tmp->host_scribble = NULL;
tmp->result = DID_ABORT << 16;
- restore_flags(flags);
tmp->done(tmp);
return SCSI_ABORT_SUCCESS;
}
@@ -3248,8 +2978,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
* so we won't panic, but we will notify the user in case something really
* broke.
*/
-
- restore_flags(flags);
printk("scsi%d : warning : SCSI command probably completed successfully\n" " before abortion\n", instance->host_no);
return SCSI_ABORT_NOT_RUNNING;
}
@@ -3262,6 +2990,7 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
*
* Returns : SCSI_RESET_WAKEUP
*
+ * Locks: io_request_lock held by caller
*/
#ifndef NCR5380_reset
diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h
index a577589aa..c7882e224 100644
--- a/drivers/scsi/NCR5380.h
+++ b/drivers/scsi/NCR5380.h
@@ -55,6 +55,8 @@
#define NDEBUG_C400_PWRITE 0x200000
#define NDEBUG_LISTS 0x400000
+#define NDEBUG_ANY 0xFFFFFFFFUL
+
/*
* The contents of the OUTPUT DATA register are asserted on the bus when
* either arbitration is occurring or the phase-indicating signals (
@@ -91,10 +93,10 @@
*/
#define MR_BLOCK_DMA_MODE 0x80 /* rw block mode DMA */
#define MR_TARGET 0x40 /* rw target mode */
-#define MR_ENABLE_PAR_CHECK 0x20 /* rw enable parity checking */
+#define MR_ENABLE_PAR_CHECK 0x20 /* rw enable parity checking */
#define MR_ENABLE_PAR_INTR 0x10 /* rw enable bad parity interrupt */
#define MR_ENABLE_EOP_INTR 0x08 /* rw enable eop interrupt */
-#define MR_MONITOR_BSY 0x04 /* rw enable int on unexpected bsy fail */
+#define MR_MONITOR_BSY 0x04 /* rw enable int on unexpected bsy fail */
#define MR_DMA_MODE 0x02 /* rw DMA / pseudo DMA mode */
#define MR_ARBITRATE 0x01 /* rw start arbitration */
@@ -245,36 +247,34 @@
#ifndef ASM
struct NCR5380_hostdata {
- NCR5380_implementation_fields; /* implementation specific */
+ NCR5380_implementation_fields; /* implementation specific */
unsigned char id_mask, id_higher_mask; /* 1 << id, all bits greater */
- unsigned char targets_present; /* targets we have connected
- to, so we can call a select
- failure a retryable condition */
- volatile unsigned char busy[8]; /* index = target, bit = lun */
+ unsigned char targets_present; /* targets we have connected
+ to, so we can call a select
+ failure a retryable condition */
+ volatile unsigned char busy[8]; /* index = target, bit = lun */
#if defined(REAL_DMA) || defined(REAL_DMA_POLL)
- volatile int dma_len; /* requested length of DMA */
+ volatile int dma_len; /* requested length of DMA */
#endif
volatile unsigned char last_message; /* last message OUT */
- volatile Scsi_Cmnd *connected; /* currently connected command */
+ volatile Scsi_Cmnd *connected; /* currently connected command */
volatile Scsi_Cmnd *issue_queue; /* waiting to be issued */
volatile Scsi_Cmnd *disconnected_queue; /* waiting for reconnect */
- volatile int restart_select; /* we have disconnected,
- used to restart
- NCR5380_select() */
- volatile unsigned aborted:1; /* flag, says aborted */
+ volatile int restart_select; /* we have disconnected,
+ used to restart
+ NCR5380_select() */
+ volatile unsigned aborted:1; /* flag, says aborted */
int flags;
-#ifdef USLEEP
- unsigned long time_expires; /* in jiffies, set prior to sleeping */
+ unsigned long time_expires; /* in jiffies, set prior to sleeping */
struct Scsi_Host *next_timer;
- int select_time; /* timer in select for target response */
+ int select_time; /* timer in select for target response */
volatile Scsi_Cmnd *selecting;
-#endif
#ifdef NCR5380_STATS
- unsigned timebase; /* Base for time calcs */
- long time_read[8]; /* time to do reads */
- long time_write[8]; /* time to do writes */
- unsigned long bytes_read[8]; /* bytes read */
- unsigned long bytes_write[8]; /* bytes written */
+ unsigned timebase; /* Base for time calcs */
+ long time_read[8]; /* time to do reads */
+ long time_write[8]; /* time to do writes */
+ unsigned long bytes_read[8]; /* bytes read */
+ unsigned long bytes_write[8]; /* bytes written */
unsigned pendingr;
unsigned pendingw;
#endif
@@ -283,6 +283,10 @@ struct NCR5380_hostdata {
#ifdef __KERNEL__
static struct Scsi_Host *first_instance; /* linked list of 5380's */
+#define dprintk(a,b) do {} while(0)
+#define NCR5380_dprint(a,b) do {} while(0)
+#define NCR5380_dprint_phase(a,b) do {} while(0)
+
#if defined(AUTOPROBE_IRQ)
static int NCR5380_probe_irq(struct Scsi_Host *instance, int possible);
#endif
@@ -321,10 +325,24 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase
#if defined(i386) || defined(__alpha__)
+/**
+ * NCR5380_pc_dma_setup - setup ISA DMA
+ * @instance: adapter to set up
+ * @ptr: block to transfer (virtual address)
+ * @count: number of bytes to transfer
+ * @mode: DMA controller mode to use
+ *
+ * Program the DMA controller ready to perform an ISA DMA transfer
+ * on this chip.
+ *
+ * Locks: takes and releases the ISA DMA lock.
+ */
+
static __inline__ int NCR5380_pc_dma_setup(struct Scsi_Host *instance, unsigned char *ptr, unsigned int count, unsigned char mode)
{
unsigned limit;
unsigned long bus_addr = virt_to_bus(ptr);
+ unsigned long flags;
if (instance->dma_channel <= 3) {
if (count > 65536)
@@ -341,34 +359,72 @@ static __inline__ int NCR5380_pc_dma_setup(struct Scsi_Host *instance, unsigned
if ((count & 1) || (bus_addr & 1))
panic("scsi%d : attempted unaligned DMA transfer\n", instance->host_no);
- cli();
+
+ flags=claim_dma_lock();
disable_dma(instance->dma_channel);
clear_dma_ff(instance->dma_channel);
set_dma_addr(instance->dma_channel, bus_addr);
set_dma_count(instance->dma_channel, count);
set_dma_mode(instance->dma_channel, mode);
enable_dma(instance->dma_channel);
- sti();
+ release_dma_lock(flags);
+
return count;
}
+/**
+ * NCR5380_pc_dma_write_setup - setup ISA DMA write
+ * @instance: adapter to set up
+ * @ptr: block to transfer (virtual address)
+ * @count: number of bytes to transfer
+ *
+ * Program the DMA controller ready to perform an ISA DMA write to the
+ * SCSI controller.
+ *
+ * Locks: called routines take and release the ISA DMA lock.
+ */
+
static __inline__ int NCR5380_pc_dma_write_setup(struct Scsi_Host *instance, unsigned char *src, unsigned int count)
{
return NCR5380_pc_dma_setup(instance, src, count, DMA_MODE_WRITE);
}
+/**
+ * NCR5380_pc_dma_read_setup - setup ISA DMA read
+ * @instance: adapter to set up
+ * @ptr: block to transfer (virtual address)
+ * @count: number of bytes to transfer
+ *
+ * Program the DMA controller ready to perform an ISA DMA read from the
+ * SCSI controller.
+ *
+ * Locks: called routines take and release the ISA DMA lock.
+ */
+
static __inline__ int NCR5380_pc_dma_read_setup(struct Scsi_Host *instance, unsigned char *src, unsigned int count)
{
return NCR5380_pc_dma_setup(instance, src, count, DMA_MODE_READ);
}
+/**
+ * NCR5380_pc_dma_residual - return bytes left
+ * @instance: adapter
+ *
+ * Reports the number of bytes left over after the DMA was terminated.
+ *
+ * Locks: takes and releases the ISA DMA lock.
+ */
+
static __inline__ int NCR5380_pc_dma_residual(struct Scsi_Host *instance)
{
- register int tmp;
- cli();
+ unsigned long flags;
+ int tmp;
+
+ flags = claim_dma_lock();
clear_dma_ff(instance->dma_channel);
tmp = get_dma_residue(instance->dma_channel);
- sti();
+ release_dma_lock(flags);
+
return tmp;
}
#endif /* defined(i386) || defined(__alpha__) */
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index a8745e4b1..ad5a6ba2e 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -161,6 +161,8 @@ static struct dev_info device_list[] =
{"SONY", "TSL", "*", BLIST_FORCELUN}, // DDS3 & DDS4 autoloaders
{"DELL", "PERCRAID", "*", BLIST_FORCELUN},
{"HP", "NetRAID-4M", "*", BLIST_FORCELUN},
+ {"ADAPTEC", "AACRAID", "*", BLIST_FORCELUN},
+ {"ADAPTEC", "Adaptec 5400S", "*", BLIST_FORCELUN},
/*
* Must be at end of list...
diff --git a/drivers/sound/Config.in b/drivers/sound/Config.in
index f52174182..f6ac188c9 100644
--- a/drivers/sound/Config.in
+++ b/drivers/sound/Config.in
@@ -40,6 +40,9 @@ dep_tristate ' ESS Technology Solo1' CONFIG_SOUND_ESSSOLO1 $CONFIG_SOUND
dep_tristate ' ESS Maestro, Maestro2, Maestro2E driver' CONFIG_SOUND_MAESTRO $CONFIG_SOUND
dep_tristate ' ESS Maestro3/Allegro driver (EXPERIMENTAL)' CONFIG_SOUND_MAESTRO3 $CONFIG_SOUND $CONFIG_PCI $CONFIG_EXPERIMENTAL
dep_tristate ' Intel ICH (i8xx) audio support' CONFIG_SOUND_ICH $CONFIG_PCI
+if [ "$CONFIG_MIPS_ITE8172" = "y" -o "$CONFIG_MIPS_IVR" = "y" ]; then
+ dep_tristate ' IT8172G Sound' CONFIG_SOUND_IT8172 $CONFIG_SOUND
+fi
dep_tristate ' RME Hammerfall (RME96XX) support' CONFIG_SOUND_RME96XX $CONFIG_SOUND $CONFIG_PCI $CONFIG_EXPERIMENTAL
dep_tristate ' S3 SonicVibes' CONFIG_SOUND_SONICVIBES $CONFIG_SOUND
if [ "$CONFIG_VISWS" = "y" ]; then
diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile
index b9904f7a5..ac7150de1 100644
--- a/drivers/sound/Makefile
+++ b/drivers/sound/Makefile
@@ -73,6 +73,7 @@ obj-$(CONFIG_SOUND_EMU10K1) += ac97_codec.o
obj-$(CONFIG_SOUND_RME96XX) += rme96xx.o
obj-$(CONFIG_SOUND_BT878) += btaudio.o
obj-$(CONFIG_SOUND_EMU10K1) += ac97_codec.o
+obj-$(CONFIG_SOUND_IT8172) += ite8172.o ac97_codec.o
ifeq ($(CONFIG_MIDI_EMU10K1),y)
obj-$(CONFIG_SOUND_EMU10K1) += sound.o
diff --git a/drivers/sound/btaudio.c b/drivers/sound/btaudio.c
index 341fc0420..22daae685 100644
--- a/drivers/sound/btaudio.c
+++ b/drivers/sound/btaudio.c
@@ -1030,7 +1030,7 @@ static struct pci_driver btaudio_pci_driver = {
name: "btaudio",
id_table: btaudio_pci_tbl,
probe: btaudio_probe,
- remove: btaudio_remove,
+ remove: __devexit_p(btaudio_remove),
};
int btaudio_init_module(void)
diff --git a/drivers/sound/emu10k1/main.c b/drivers/sound/emu10k1/main.c
index bc53fcfd7..69f192c8d 100644
--- a/drivers/sound/emu10k1/main.c
+++ b/drivers/sound/emu10k1/main.c
@@ -1127,7 +1127,7 @@ static struct pci_driver emu10k1_pci_driver = {
name: "emu10k1",
id_table: emu10k1_pci_tbl,
probe: emu10k1_probe,
- remove: emu10k1_remove,
+ remove: __devexit_p(emu10k1_remove),
};
static int __init emu10k1_init_module(void)
diff --git a/drivers/sound/ymfpci.c b/drivers/sound/ymfpci.c
index 8d5de5c37..3a0ca9a70 100644
--- a/drivers/sound/ymfpci.c
+++ b/drivers/sound/ymfpci.c
@@ -1443,13 +1443,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) {
@@ -1458,12 +1459,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;
}
}
@@ -1498,6 +1508,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;
}
@@ -2430,6 +2441,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;
@@ -2438,6 +2450,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");
@@ -2452,16 +2465,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)
@@ -2491,8 +2509,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;
}
@@ -2538,6 +2555,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;
@@ -2561,6 +2580,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);
@@ -2577,7 +2597,7 @@ static struct pci_driver ymfpci_driver = {
name: "ymfpci",
id_table: ymf_id_tbl,
probe: ymf_probe_one,
- remove: ymf_remove_one,
+ remove: __devexit_p(ymf_remove_one),
suspend: ymf_suspend,
resume: ymf_resume
};
diff --git a/drivers/usb/uhci.c b/drivers/usb/uhci.c
index a3556dfe7..1f19cb11a 100644
--- a/drivers/usb/uhci.c
+++ b/drivers/usb/uhci.c
@@ -2990,7 +2990,7 @@ static struct pci_driver uhci_pci_driver = {
id_table: uhci_pci_ids,
probe: uhci_pci_probe,
- remove: uhci_pci_remove,
+ remove: __devexit_p(uhci_pci_remove),
#ifdef CONFIG_PM
suspend: uhci_pci_suspend,
diff --git a/drivers/usb/usb-ohci.c b/drivers/usb/usb-ohci.c
index 96787e4a3..a090f1c1c 100644
--- a/drivers/usb/usb-ohci.c
+++ b/drivers/usb/usb-ohci.c
@@ -2860,7 +2860,7 @@ static struct pci_driver ohci_pci_driver = {
id_table: &ohci_pci_ids [0],
probe: ohci_pci_probe,
- remove: ohci_pci_remove,
+ remove: __devexit_p(ohci_pci_remove),
#ifdef CONFIG_PM
suspend: ohci_pci_suspend,
diff --git a/drivers/usb/usb-uhci.c b/drivers/usb/usb-uhci.c
index f7df53322..d753af20f 100644
--- a/drivers/usb/usb-uhci.c
+++ b/drivers/usb/usb-uhci.c
@@ -3070,7 +3070,7 @@ static struct pci_driver uhci_pci_driver = {
id_table: &uhci_pci_ids [0],
probe: uhci_pci_probe,
- remove: uhci_pci_remove,
+ remove: __devexit_p(uhci_pci_remove),
#ifdef CONFIG_PM
suspend: uhci_pci_suspend,
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index d83338cc3..74553d139 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -1683,7 +1683,7 @@ static struct pci_device_id cyberpro_pci_table[] __devinitdata = {
static struct pci_driver cyberpro_driver = {
name: "CyberPro",
probe: cyberpro_probe,
- remove: cyberpro_remove,
+ remove: __devexit_p(cyberpro_remove),
suspend: cyberpro_suspend,
resume: cyberpro_resume,
id_table: cyberpro_pci_table
diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
index 2030ab596..3ec9b07d6 100644
--- a/drivers/video/imsttfb.c
+++ b/drivers/video/imsttfb.c
@@ -1643,7 +1643,7 @@ static struct pci_driver imsttfb_pci_driver = {
name: "imsttfb",
id_table: imsttfb_pci_tbl,
probe: imsttfb_probe,
- remove: imsttfb_remove,
+ remove: __devexit_p(imsttfb_remove),
};
static struct fb_ops imsttfb_ops = {
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 0902bee80..bd51027b0 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -108,6 +108,7 @@ static int default_cmode = CMODE_NVRAM;
#endif
static void matroxfb_unregister_device(struct matrox_fb_info* minfo);
+int matroxfb_switch(int con, struct fb_info *info);
/* --------------------------------------------------------------------- */
diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c
index 30db837cb..2b3dbe4f2 100644
--- a/drivers/video/radeonfb.c
+++ b/drivers/video/radeonfb.c
@@ -619,7 +619,7 @@ static struct pci_driver radeonfb_driver = {
name: "radeonfb",
id_table: radeonfb_pci_table,
probe: radeonfb_pci_register,
- remove: radeonfb_pci_unregister,
+ remove: __devexit_p(radeonfb_pci_unregister),
};
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index 2213a8595..72d42b197 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -2082,7 +2082,7 @@ static struct pci_driver rivafb_driver = {
name: "rivafb",
id_table: rivafb_pci_tbl,
probe: rivafb_init_one,
- remove: rivafb_remove_one,
+ remove: __devexit_p(rivafb_remove_one),
};
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index 11c93e737..b7e522187 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -495,7 +495,7 @@ static struct pci_driver tdfxfb_driver = {
name: "tdfxfb",
id_table: tdfxfb_id_table,
probe: tdfxfb_probe,
- remove: tdfxfb_remove,
+ remove: __devexit_p(tdfxfb_remove),
};
MODULE_DEVICE_TABLE(pci, tdfxfb_id_table);
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 019839acd..cbeb0fb38 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -32,7 +32,7 @@
#include <linux/highuid.h>
#include <linux/smp_lock.h>
#include <linux/compiler.h>
-#include <linux/limits.h>
+#include <linux/highmem.h>
#include <asm/uaccess.h>
#include <asm/param.h>
@@ -1032,6 +1032,25 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
elf_fpregset_t fpu; /* NT_PRFPREG */
struct elf_prpsinfo psinfo; /* NT_PRPSINFO */
+ /* first copy the parameters from user space */
+ memset(&psinfo, 0, sizeof(psinfo));
+ {
+ int i, len;
+
+ len = current->mm->arg_end - current->mm->arg_start;
+ if (len >= ELF_PRARGSZ)
+ len = ELF_PRARGSZ-1;
+ copy_from_user(&psinfo.pr_psargs,
+ (const char *)current->mm->arg_start, len);
+ for(i = 0; i < len; i++)
+ if (psinfo.pr_psargs[i] == 0)
+ psinfo.pr_psargs[i] = ' ';
+ psinfo.pr_psargs[len] = 0;
+
+ }
+
+ /* now stop all vm operations */
+ down_write(&current->mm->mmap_sem);
segs = current->mm->map_count;
#ifdef DEBUG
@@ -1073,7 +1092,6 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
* Set up the notes in similar form to SVR4 core dumps made
* with info from their /proc.
*/
- memset(&psinfo, 0, sizeof(psinfo));
memset(&prstatus, 0, sizeof(prstatus));
notes[0].name = "CORE";
@@ -1129,23 +1147,6 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
psinfo.pr_flag = current->flags;
psinfo.pr_uid = NEW_TO_OLD_UID(current->uid);
psinfo.pr_gid = NEW_TO_OLD_GID(current->gid);
- {
- int i, len;
-
- set_fs(fs);
-
- len = current->mm->arg_end - current->mm->arg_start;
- if (len >= ELF_PRARGSZ)
- len = ELF_PRARGSZ-1;
- copy_from_user(&psinfo.pr_psargs,
- (const char *)current->mm->arg_start, len);
- for(i = 0; i < len; i++)
- if (psinfo.pr_psargs[i] == 0)
- psinfo.pr_psargs[i] = ' ';
- psinfo.pr_psargs[len] = 0;
-
- set_fs(KERNEL_DS);
- }
strncpy(psinfo.pr_fname, current->comm, sizeof(psinfo.pr_fname));
notes[2].name = "CORE";
@@ -1217,8 +1218,6 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
if (!writenote(&notes[i], file))
goto end_coredump;
- set_fs(fs);
-
DUMP_SEEK(dataoff);
for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
@@ -1232,22 +1231,24 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
for (addr = vma->vm_start;
addr < vma->vm_end;
addr += PAGE_SIZE) {
- pgd_t *pgd;
- pmd_t *pmd;
- pte_t *pte;
-
- pgd = pgd_offset(vma->vm_mm, addr);
- if (pgd_none(*pgd))
- goto nextpage_coredump;
- pmd = pmd_offset(pgd, addr);
- if (pmd_none(*pmd))
- goto nextpage_coredump;
- pte = pte_offset(pmd, addr);
- if (pte_none(*pte)) {
-nextpage_coredump:
+ struct page* page;
+ struct vm_area_struct *vma;
+
+ if (get_user_pages(current, current->mm, addr, 1, 0, 1,
+ &page, &vma) <= 0) {
DUMP_SEEK (file->f_pos + PAGE_SIZE);
} else {
- DUMP_WRITE((void*)addr, PAGE_SIZE);
+ if (page == ZERO_PAGE(addr)) {
+ DUMP_SEEK (file->f_pos + PAGE_SIZE);
+ } else {
+ void *kaddr;
+ flush_cache_page(vma, addr);
+ kaddr = kmap(page);
+ DUMP_WRITE(kaddr, PAGE_SIZE);
+ flush_page_to_ram(page);
+ kunmap(page);
+ }
+ put_page(page);
}
}
}
@@ -1260,6 +1261,7 @@ nextpage_coredump:
end_coredump:
set_fs(fs);
+ up_write(&current->mm->mmap_sem);
return has_dumped;
}
#endif /* USE_ELF_CORE_DUMP */
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 485e0bffe..0563a901b 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -234,7 +234,7 @@ static struct vfsmount *bd_mnt;
#define HASH_SIZE (1UL << HASH_BITS)
#define HASH_MASK (HASH_SIZE-1)
static struct list_head bdev_hashtable[HASH_SIZE];
-static spinlock_t bdev_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t bdev_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
static kmem_cache_t * bdev_cachep;
#define alloc_bdev() \
diff --git a/fs/buffer.c b/fs/buffer.c
index d1eb1e410..e9442ec38 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -73,7 +73,7 @@ static struct buffer_head **hash_table;
static rwlock_t hash_table_lock = RW_LOCK_UNLOCKED;
static struct buffer_head *lru_list[NR_LIST];
-static spinlock_t lru_list_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t lru_list_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
static int nr_buffers_type[NR_LIST];
static unsigned long size_buffers_type[NR_LIST];
diff --git a/fs/dcache.c b/fs/dcache.c
index 313b4fe02..f04948742 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -29,7 +29,7 @@
#define DCACHE_PARANOIA 1
/* #define DCACHE_DEBUG 1 */
-spinlock_t dcache_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t dcache_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
/* Right now the dcache depends on the kernel lock */
#define check_lock() if (!kernel_locked()) BUG()
diff --git a/fs/exec.c b/fs/exec.c
index afd7577ab..3e34704f5 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -973,9 +973,7 @@ int do_coredump(long signr, struct pt_regs * regs)
if (do_truncate(file->f_dentry, 0) != 0)
goto close_fail;
- down_read(&current->mm->mmap_sem);
retval = binfmt->core_dump(signr, regs, file);
- up_read(&current->mm->mmap_sem);
close_fail:
filp_close(file, NULL);
diff --git a/fs/ext3/Makefile b/fs/ext3/Makefile
index c64318e79..68cb48618 100644
--- a/fs/ext3/Makefile
+++ b/fs/ext3/Makefile
@@ -9,7 +9,7 @@
O_TARGET := ext3.o
-obj-y := acl.o balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
+obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
ioctl.o namei.o super.o symlink.o
obj-m := $(O_TARGET)
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
deleted file mode 100644
index f77d42047..000000000
--- a/fs/ext3/acl.c
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * linux/fs/ext3/acl.c
- *
- * Copyright (C) 1993, 1994, 1995
- * Remy Card (card@masi.ibp.fr)
- * Laboratoire MASI - Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- */
-
-#include <linux/fs.h>
-#include <linux/sched.h>
-
-
-/*
- * This file will contain the Access Control Lists management for the
- * second extended file system.
- */
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
index 6059099fd..088f79673 100644
--- a/fs/ext3/ialloc.c
+++ b/fs/ext3/ialloc.c
@@ -508,7 +508,7 @@ repeat:
insert_inode_hash(inode);
inode->i_generation = event++;
- inode->u.ext3_i.i_state = (1UL << EXT3_STATE_NEW);
+ inode->u.ext3_i.i_state = EXT3_STATE_NEW;
err = ext3_mark_inode_dirty(handle, inode);
if (err) goto fail;
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 8b9008392..02ebe46d4 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -32,7 +32,6 @@
#include <linux/quotaops.h>
#include <linux/module.h>
-
/*
* SEARCH_FROM_ZERO forces each block allocation to search from the start
* of the filesystem. This is to force rapid reallocation of recently-freed
@@ -716,6 +715,8 @@ err_out:
* reachable from inode.
*
* akpm: `handle' can be NULL if create == 0.
+ *
+ * The BKL may not be held on entry here. Be sure to take it early.
*/
static int ext3_get_block_handle(handle_t *handle, struct inode *inode,
@@ -823,6 +824,9 @@ changed:
goto reread;
}
+/*
+ * The BKL is not held on entry here.
+ */
static int ext3_get_block(struct inode *inode, long iblock,
struct buffer_head *bh_result, int create)
{
@@ -1022,13 +1026,26 @@ static int ext3_prepare_write(struct file *file, struct page *page,
ret = PTR_ERR(handle);
goto out;
}
+ unlock_kernel();
ret = block_prepare_write(page, from, to, ext3_get_block);
+ lock_kernel();
if (ret != 0)
goto prepare_write_failed;
- if (ext3_should_journal_data(inode))
+ if (ext3_should_journal_data(inode)) {
ret = walk_page_buffers(handle, page->buffers,
from, to, NULL, do_journal_get_write_access);
+ if (ret) {
+ /*
+ * We're going to fail this prepare_write(),
+ * so commit_write() will not be called.
+ * We need to undo block_prepare_write()'s kmap().
+ * AKPM: Do we need to clear PageUptodate? I don't
+ * think so.
+ */
+ kunmap(page);
+ }
+ }
prepare_write_failed:
if (ret)
ext3_journal_stop(handle, inode);
@@ -1096,7 +1113,7 @@ static int ext3_commit_write(struct file *file, struct page *page,
kunmap(page);
if (pos > inode->i_size)
inode->i_size = pos;
- set_bit(EXT3_STATE_JDATA, &inode->u.ext3_i.i_state);
+ EXT3_I(inode)->i_state |= EXT3_STATE_JDATA;
} else {
if (ext3_should_order_data(inode)) {
ret = walk_page_buffers(handle, page->buffers,
@@ -1104,8 +1121,17 @@ static int ext3_commit_write(struct file *file, struct page *page,
}
/* Be careful here if generic_commit_write becomes a
* required invocation after block_prepare_write. */
- if (ret == 0)
+ if (ret == 0) {
ret = generic_commit_write(file, page, from, to);
+ } else {
+ /*
+ * block_prepare_write() was called, but we're not
+ * going to call generic_commit_write(). So we
+ * need to perform generic_commit_write()'s kunmap
+ * by hand.
+ */
+ kunmap(page);
+ }
}
if (inode->i_size > inode->u.ext3_i.i_disksize) {
inode->u.ext3_i.i_disksize = inode->i_size;
@@ -1140,7 +1166,7 @@ static int ext3_bmap(struct address_space *mapping, long block)
journal_t *journal;
int err;
- if (test_and_clear_bit(EXT3_STATE_JDATA, &inode->u.ext3_i.i_state)) {
+ if (EXT3_I(inode)->i_state & EXT3_STATE_JDATA) {
/*
* This is a REALLY heavyweight approach, but the use of
* bmap on dirty files is expected to be extremely rare:
@@ -1159,6 +1185,7 @@ static int ext3_bmap(struct address_space *mapping, long block)
* everything they get.
*/
+ EXT3_I(inode)->i_state &= ~EXT3_STATE_JDATA;
journal = EXT3_JOURNAL(inode);
journal_lock_updates(journal);
err = journal_flush(journal);
@@ -2203,7 +2230,7 @@ static int ext3_do_update_inode(handle_t *handle,
/* If we are not tracking these fields in the in-memory inode,
* then preserve them on disk, but still initialise them to zero
* for new inodes. */
- if (inode->u.ext3_i.i_state & (1UL << EXT3_STATE_NEW)) {
+ if (EXT3_I(inode)->i_state & EXT3_STATE_NEW) {
raw_inode->i_faddr = 0;
raw_inode->i_frag = 0;
raw_inode->i_fsize = 0;
@@ -2249,7 +2276,7 @@ static int ext3_do_update_inode(handle_t *handle,
rc = ext3_journal_dirty_metadata(handle, bh);
if (!err)
err = rc;
- inode->u.ext3_i.i_state &= ~(1UL << EXT3_STATE_NEW);
+ EXT3_I(inode)->i_state &= ~EXT3_STATE_NEW;
out_brelse:
brelse (bh);
@@ -2333,7 +2360,7 @@ void ext3_write_inode(struct inode *inode, int wait)
int ext3_setattr(struct dentry *dentry, struct iattr *attr)
{
struct inode *inode = dentry->d_inode;
- int error, rc;
+ int error, rc = 0;
error = inode_change_ok(inode, attr);
if (error)
@@ -2356,7 +2383,7 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr)
ext3_journal_stop(handle, inode);
}
- inode_setattr(inode, attr);
+ rc = inode_setattr(inode, attr);
/* If inode_setattr's call to ext3_truncate failed to get a
* transaction handle at all, we need to clean up the in-core
@@ -2366,7 +2393,9 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr)
err_out:
ext3_std_error(inode->i_sb, error);
- return 0;
+ if (!error)
+ error = rc;
+ return error;
}
@@ -2667,6 +2696,3 @@ int ext3_change_inode_journal_flag(struct inode *inode, int val)
* here, in ext3_aops_journal_start() to ensure that the forthcoming "see if we
* need to extend" test in ext3_prepare_write() succeeds.
*/
-
-
-MODULE_LICENSE("GPL");
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 9a5e18950..fb2303ffc 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -1257,8 +1257,11 @@ static journal_t *ext3_get_journal(struct super_block *sb, int journal_inum)
}
journal = journal_init_inode(journal_inode);
- if (!journal)
+ if (!journal) {
+ printk(KERN_ERR "EXT3-fs: Could not load journal inode\n");
iput(journal_inode);
+ }
+
return journal;
}
@@ -1350,7 +1353,7 @@ static int ext3_load_journal(struct super_block * sb,
journal_t *journal;
int journal_inum = le32_to_cpu(es->s_journal_inum);
int journal_dev = le32_to_cpu(es->s_journal_dev);
- int err;
+ int err = 0;
int really_read_only;
really_read_only = is_read_only(sb->s_dev);
@@ -1400,9 +1403,10 @@ static int ext3_load_journal(struct super_block * sb,
}
if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER))
- journal_wipe(journal, !really_read_only);
+ err = journal_wipe(journal, !really_read_only);
+ if (!err)
+ err = journal_load(journal);
- err = journal_load(journal);
if (err) {
printk(KERN_ERR "EXT3-fs: error loading journal.\n");
journal_destroy(journal);
@@ -1740,6 +1744,8 @@ static void __exit exit_ext3_fs(void)
EXPORT_NO_SYMBOLS;
+MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
+MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
MODULE_LICENSE("GPL");
module_init(init_ext3_fs)
module_exit(exit_ext3_fs)
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index 045b74ce9..29e96b885 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -47,7 +47,8 @@ void journal_commit_transaction(journal_t *journal)
struct buffer_head *wbuf[64];
int bufs;
int flags;
- int blocknr;
+ int err;
+ unsigned long blocknr;
char *tagp = NULL;
journal_header_t *header;
journal_block_tag_t *tag = NULL;
@@ -352,6 +353,11 @@ sync_datalist_empty:
jbd_debug(4, "JBD: get descriptor\n");
descriptor = journal_get_descriptor_buffer(journal);
+ if (!descriptor) {
+ __journal_abort_hard(journal);
+ continue;
+ }
+
bh = jh2bh(descriptor);
jbd_debug(4, "JBD: got buffer %ld (%p)\n",
bh->b_blocknr, bh->b_data);
@@ -375,7 +381,14 @@ sync_datalist_empty:
/* Where is the buffer to be written? */
- blocknr = journal_next_log_block(journal);
+ err = journal_next_log_block(journal, &blocknr);
+ /* If the block mapping failed, just abandon the buffer
+ and repeat this loop: we'll fall into the
+ refile-on-abort condition above. */
+ if (err) {
+ __journal_abort_hard(journal);
+ continue;
+ }
/* Bump b_count to prevent truncate from stumbling over
the shadowed buffer! @@@ This can go if we ever get
@@ -554,16 +567,20 @@ start_journal_io:
jbd_debug(3, "JBD: commit phase 6\n");
+ if (is_journal_aborted(journal))
+ goto skip_commit;
+
/* Done it all: now write the commit record. We should have
* cleaned up our previous buffers by now, so if we are in abort
* mode we can now just skip the rest of the journal write
* entirely. */
- if (is_journal_aborted(journal))
- goto skip_commit;
-
descriptor = journal_get_descriptor_buffer(journal);
-
+ if (!descriptor) {
+ __journal_abort_hard(journal);
+ goto skip_commit;
+ }
+
/* AKPM: buglet - add `i' to tmp! */
for (i = 0; i < jh2bh(descriptor)->b_size; i += 512) {
journal_header_t *tmp =
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index 2b86b94c7..cf381d4fa 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -70,7 +70,6 @@ EXPORT_SYMBOL(journal_load);
EXPORT_SYMBOL(journal_destroy);
EXPORT_SYMBOL(journal_recover);
EXPORT_SYMBOL(journal_update_superblock);
-EXPORT_SYMBOL(__journal_abort);
EXPORT_SYMBOL(journal_abort);
EXPORT_SYMBOL(journal_errno);
EXPORT_SYMBOL(journal_ack_err);
@@ -606,7 +605,7 @@ void log_wait_commit (journal_t *journal, tid_t tid)
* Log buffer allocation routines:
*/
-unsigned long journal_next_log_block(journal_t *journal)
+int journal_next_log_block(journal_t *journal, unsigned long *retp)
{
unsigned long blocknr;
@@ -617,7 +616,7 @@ unsigned long journal_next_log_block(journal_t *journal)
journal->j_free--;
if (journal->j_head == journal->j_last)
journal->j_head = journal->j_first;
- return journal_bmap(journal, blocknr);
+ return journal_bmap(journal, blocknr, retp);
}
/*
@@ -627,17 +626,28 @@ unsigned long journal_next_log_block(journal_t *journal)
* this is a no-op. If needed, we can use j_blk_offset - everything is
* ready.
*/
-unsigned long journal_bmap(journal_t *journal, unsigned long blocknr)
+int journal_bmap(journal_t *journal, unsigned long blocknr,
+ unsigned long *retp)
{
+ int err = 0;
unsigned long ret;
if (journal->j_inode) {
ret = bmap(journal->j_inode, blocknr);
- J_ASSERT(ret != 0);
+ if (ret)
+ *retp = ret;
+ else {
+ printk (KERN_ALERT __FUNCTION__
+ ": journal block not found "
+ "at offset %lu on %s\n",
+ blocknr, bdevname(journal->j_dev));
+ err = -EIO;
+ __journal_abort_soft(journal, err);
+ }
} else {
- ret = blocknr; /* +journal->j_blk_offset */
+ *retp = blocknr; /* +journal->j_blk_offset */
}
- return ret;
+ return err;
}
/*
@@ -649,7 +659,13 @@ unsigned long journal_bmap(journal_t *journal, unsigned long blocknr)
struct journal_head * journal_get_descriptor_buffer(journal_t *journal)
{
struct buffer_head *bh;
- unsigned long blocknr = journal_next_log_block(journal);
+ unsigned long blocknr;
+ int err;
+
+ err = journal_next_log_block(journal, &blocknr);
+
+ if (err)
+ return NULL;
bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
bh->b_state |= (1 << BH_Dirty);
@@ -747,7 +763,8 @@ journal_t * journal_init_inode (struct inode *inode)
{
struct buffer_head *bh;
journal_t *journal = journal_init_common();
- int blocknr;
+ int err;
+ unsigned long blocknr;
if (!journal)
return NULL;
@@ -757,13 +774,22 @@ journal_t * journal_init_inode (struct inode *inode)
journal->j_inode = inode;
jbd_debug(1,
"journal %p: inode %s/%ld, size %Ld, bits %d, blksize %ld\n",
- journal, bdevname(inode->i_dev), inode->i_ino, inode->i_size,
+ journal, bdevname(inode->i_dev), inode->i_ino,
+ (long long) inode->i_size,
inode->i_sb->s_blocksize_bits, inode->i_sb->s_blocksize);
journal->j_maxlen = inode->i_size >> inode->i_sb->s_blocksize_bits;
journal->j_blocksize = inode->i_sb->s_blocksize;
- blocknr = journal_bmap(journal, 0);
+ err = journal_bmap(journal, 0, &blocknr);
+ /* If that failed, give up */
+ if (err) {
+ printk(KERN_ERR __FUNCTION__ ": Cannnot locate journal "
+ "superblock\n");
+ kfree(journal);
+ return NULL;
+ }
+
bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
J_ASSERT(bh != NULL);
journal->j_sb_buffer = bh;
@@ -772,6 +798,18 @@ journal_t * journal_init_inode (struct inode *inode)
return journal;
}
+/*
+ * If the journal init or create aborts, we need to mark the journal
+ * superblock as being NULL to prevent the journal destroy from writing
+ * back a bogus superblock.
+ */
+static void journal_fail_superblock (journal_t *journal)
+{
+ struct buffer_head *bh = journal->j_sb_buffer;
+ brelse(bh);
+ journal->j_sb_buffer = NULL;
+}
+
/*
* Given a journal_t structure, initialise the various fields for
* startup of a new journaling session. We use this both when creating
@@ -817,14 +855,15 @@ static int journal_reset (journal_t *journal)
int journal_create (journal_t *journal)
{
- int blocknr;
+ unsigned long blocknr;
struct buffer_head *bh;
journal_superblock_t *sb;
- int i;
+ int i, err;
if (journal->j_maxlen < JFS_MIN_JOURNAL_BLOCKS) {
printk (KERN_ERR "Journal length (%d blocks) too short.\n",
journal->j_maxlen);
+ journal_fail_superblock(journal);
return -EINVAL;
}
@@ -841,7 +880,9 @@ int journal_create (journal_t *journal)
have any blocks on disk beginning with JFS_MAGIC_NUMBER. */
jbd_debug(1, "JBD: Zeroing out journal blocks...\n");
for (i = 0; i < journal->j_maxlen; i++) {
- blocknr = journal_bmap(journal, i);
+ err = journal_bmap(journal, i, &blocknr);
+ if (err)
+ return err;
bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
wait_on_buffer(bh);
memset (bh->b_data, 0, journal->j_blocksize);
@@ -851,6 +892,7 @@ int journal_create (journal_t *journal)
mark_buffer_uptodate(bh, 1);
__brelse(bh);
}
+
sync_dev(journal->j_dev);
jbd_debug(1, "JBD: journal cleared.\n");
@@ -915,7 +957,8 @@ static int journal_get_superblock(journal_t *journal)
{
struct buffer_head *bh;
journal_superblock_t *sb;
-
+ int err = -EIO;
+
bh = journal->j_sb_buffer;
J_ASSERT(bh != NULL);
@@ -925,16 +968,18 @@ static int journal_get_superblock(journal_t *journal)
if (!buffer_uptodate(bh)) {
printk (KERN_ERR
"JBD: IO error reading journal superblock\n");
- return -EIO;
+ goto out;
}
}
sb = journal->j_superblock;
+ err = -EINVAL;
+
if (sb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
sb->s_blocksize != htonl(journal->j_blocksize)) {
printk(KERN_WARNING "JBD: no valid journal superblock found\n");
- return -EINVAL;
+ goto out;
}
switch(ntohl(sb->s_header.h_blocktype)) {
@@ -946,17 +991,21 @@ static int journal_get_superblock(journal_t *journal)
break;
default:
printk(KERN_WARNING "JBD: unrecognised superblock format ID\n");
- return -EINVAL;
+ goto out;
}
if (ntohl(sb->s_maxlen) < journal->j_maxlen)
journal->j_maxlen = ntohl(sb->s_maxlen);
else if (ntohl(sb->s_maxlen) > journal->j_maxlen) {
printk (KERN_WARNING "JBD: journal file too short\n");
- return -EINVAL;
+ goto out;
}
return 0;
+
+out:
+ journal_fail_superblock(journal);
+ return err;
}
/*
@@ -1061,7 +1110,10 @@ void journal_destroy (journal_t *journal)
/* We can now mark the journal as empty. */
journal->j_tail = 0;
journal->j_tail_sequence = ++journal->j_transaction_sequence;
- journal_update_superblock(journal, 1);
+ if (journal->j_sb_buffer) {
+ journal_update_superblock(journal, 1);
+ brelse(journal->j_sb_buffer);
+ }
if (journal->j_inode)
iput(journal->j_inode);
@@ -1069,7 +1121,6 @@ void journal_destroy (journal_t *journal)
journal_destroy_revoke(journal);
unlock_journal(journal);
- brelse(journal->j_sb_buffer);
kfree(journal);
MOD_DEC_USE_COUNT;
}
@@ -1356,11 +1407,16 @@ const char * journal_dev_name(journal_t *journal)
* progress).
*/
-/* Quick version for internal journal use (doesn't lock the journal) */
-void __journal_abort (journal_t *journal)
+/* Quick version for internal journal use (doesn't lock the journal).
+ * Aborts hard --- we mark the abort as occurred, but do _nothing_ else,
+ * and don't attempt to make any other journal updates. */
+void __journal_abort_hard (journal_t *journal)
{
transaction_t *transaction;
+ if (journal->j_flags & JFS_ABORT)
+ return;
+
printk (KERN_ERR "Aborting journal on device %s.\n",
journal_dev_name(journal));
@@ -1370,23 +1426,27 @@ void __journal_abort (journal_t *journal)
log_start_commit(journal, transaction);
}
-/* Full version for external use */
-void journal_abort (journal_t *journal, int errno)
+/* Soft abort: record the abort error status in the journal superblock,
+ * but don't do any other IO. */
+void __journal_abort_soft (journal_t *journal, int errno)
{
- lock_journal(journal);
-
if (journal->j_flags & JFS_ABORT)
- goto out;
+ return;
if (!journal->j_errno)
journal->j_errno = errno;
- __journal_abort(journal);
+ __journal_abort_hard(journal);
if (errno)
journal_update_superblock(journal, 1);
+}
- out:
+/* Full version for external use */
+void journal_abort (journal_t *journal, int errno)
+{
+ lock_journal(journal);
+ __journal_abort_soft(journal, errno);
unlock_journal(journal);
}
diff --git a/fs/jbd/recovery.c b/fs/jbd/recovery.c
index 491dc6cb6..e8e416306 100644
--- a/fs/jbd/recovery.c
+++ b/fs/jbd/recovery.c
@@ -70,7 +70,8 @@ void journal_brelse_array(struct buffer_head *b[], int n)
static int do_readahead(journal_t *journal, unsigned int start)
{
int err;
- unsigned int max, nbufs, next, blocknr;
+ unsigned int max, nbufs, next;
+ unsigned long blocknr;
struct buffer_head *bh;
struct buffer_head * bufs[MAXBUF];
@@ -86,12 +87,11 @@ static int do_readahead(journal_t *journal, unsigned int start)
nbufs = 0;
for (next = start; next < max; next++) {
- blocknr = journal_bmap(journal, next);
+ err = journal_bmap(journal, next, &blocknr);
- if (!blocknr) {
+ if (err) {
printk (KERN_ERR "JBD: bad block at offset %u\n",
next);
- err = -EIO;
goto failed;
}
@@ -132,19 +132,20 @@ failed:
static int jread(struct buffer_head **bhp, journal_t *journal,
unsigned int offset)
{
- unsigned int blocknr;
+ int err;
+ unsigned long blocknr;
struct buffer_head *bh;
*bhp = NULL;
J_ASSERT (offset < journal->j_maxlen);
- blocknr = journal_bmap(journal, offset);
+ err = journal_bmap(journal, offset, &blocknr);
- if (!blocknr) {
+ if (err) {
printk (KERN_ERR "JBD: bad block at offset %u\n",
offset);
- return -EIO;
+ return err;
}
bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
diff --git a/fs/jbd/revoke.c b/fs/jbd/revoke.c
index 8feb8aae8..01b7684e9 100644
--- a/fs/jbd/revoke.c
+++ b/fs/jbd/revoke.c
@@ -495,6 +495,8 @@ static void write_one_revoke_record(journal_t *journal,
if (!descriptor) {
descriptor = journal_get_descriptor_buffer(journal);
+ if (!descriptor)
+ return;
header = (journal_header_t *) &jh2bh(descriptor)->b_data[0];
header->h_magic = htonl(JFS_MAGIC_NUMBER);
header->h_blocktype = htonl(JFS_REVOKE_BLOCK);
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index a254c2ce3..10b54892d 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -1058,21 +1058,6 @@ int journal_dirty_data (handle_t *handle, struct buffer_head *bh, int async)
JBUFFER_TRACE(jh, "not on a transaction");
__journal_file_buffer(jh, handle->h_transaction, wanted_jlist);
}
- /*
- * We need to mark the buffer dirty and refile it inside the lock to
- * protect it from release by journal_try_to_free_buffer()
- *
- * We set ->b_flushtime to something small enough to typically keep
- * kupdate away from the buffer.
- *
- * We don't need to do a balance_dirty() - __block_commit_write()
- * does that.
- */
- if (!async && !atomic_set_buffer_dirty(jh2bh(jh))) {
- jh2bh(jh)->b_flushtime =
- jiffies + journal->j_commit_interval + 1 * HZ;
- refile_buffer(jh2bh(jh));
- }
no_journal:
spin_unlock(&journal_datalist_lock);
if (need_brelse) {
@@ -1604,8 +1589,6 @@ static int __journal_try_to_free_buffer(struct buffer_head *bh,
assert_spin_locked(&journal_datalist_lock);
- if (!buffer_jbd(bh))
- return 1;
jh = bh2jh(bh);
if (buffer_locked(bh) || buffer_dirty(bh)) {
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 2c9987eba..545e1c1af 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -17,6 +17,37 @@
#define NFSDBG_FACILITY NFSDBG_PROC
+/* A wrapper to handle the EJUKEBOX error message */
+static int
+nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
+{
+ sigset_t oldset;
+ int res;
+ rpc_clnt_sigmask(clnt, &oldset);
+ do {
+ res = rpc_call_sync(clnt, msg, flags);
+ if (res != -EJUKEBOX)
+ break;
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(NFS_JUKEBOX_RETRY_TIME);
+ res = -ERESTARTSYS;
+ } while (!signalled());
+ rpc_clnt_sigunmask(clnt, &oldset);
+ return res;
+}
+
+static inline int
+nfs3_rpc_call_wrapper(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags)
+{
+ struct rpc_message msg = { proc, argp, resp, NULL };
+ return nfs3_rpc_wrapper(clnt, &msg, flags);
+}
+
+#define rpc_call(clnt, proc, argp, resp, flags) \
+ nfs3_rpc_call_wrapper(clnt, proc, argp, resp, flags)
+#define rpc_call_sync(clnt, msg, flags) \
+ nfs3_rpc_wrapper(clnt, msg, flags)
+
/*
* Bare-bones access to getattr: this is for nfs_read_super.
*/
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index 3ae20c8bd..ec88c3ccb 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -187,7 +187,7 @@ nfs_list_add_request(struct nfs_page *req, struct list_head *head)
BUG();
}
#endif
- for (pos = head->prev; pos != head; pos = pos->prev) {
+ list_for_each_prev(pos, head) {
struct nfs_page *p = nfs_list_entry(pos);
if (page_index(p->wb_page) < pg_idx)
break;
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 53d2dcdda..ff3478d67 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -402,6 +402,9 @@ nfs_readpage_result(struct rpc_task *task)
dprintk("NFS: %4d nfs_readpage_result, (status %d)\n",
task->tk_pid, task->tk_status);
+ if (nfs_async_handle_jukebox(task))
+ return;
+
nfs_refresh_inode(inode, &data->fattr);
while (!list_empty(&data->pages)) {
struct nfs_page *req = nfs_list_entry(data->pages.next);
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 800fc5767..08e67912f 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -123,6 +123,8 @@ nfs_async_unlink_done(struct rpc_task *task)
struct dentry *dir = data->dir;
struct inode *dir_i;
+ if (nfs_async_handle_jukebox(task))
+ return;
if (!dir)
return;
dir_i = dir->d_inode;
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 2d7d65392..324c6066a 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -305,18 +305,30 @@ region_locked(struct inode *inode, struct nfs_page *req)
/*
* Insert a write request into an inode
+ * Note: we sort the list in order to be able to optimize nfs_find_request()
+ * & co. for the 'write append' case. For 2.5 we may want to consider
+ * some form of hashing so as to perform well on random writes.
*/
static inline void
nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
{
+ struct list_head *pos, *head;
+ unsigned long pg_idx = page_index(req->wb_page);
+
if (!list_empty(&req->wb_hash))
return;
if (!NFS_WBACK_BUSY(req))
printk(KERN_ERR "NFS: unlocked request attempted hashed!\n");
- if (list_empty(&inode->u.nfs_i.writeback))
+ head = &inode->u.nfs_i.writeback;
+ if (list_empty(head))
igrab(inode);
+ list_for_each_prev(pos, head) {
+ struct nfs_page *entry = nfs_inode_wb_entry(pos);
+ if (page_index(entry->wb_page) < pg_idx)
+ break;
+ }
inode->u.nfs_i.npages++;
- list_add(&req->wb_hash, &inode->u.nfs_i.writeback);
+ list_add(&req->wb_hash, pos);
req->wb_count++;
}
@@ -354,15 +366,18 @@ nfs_inode_remove_request(struct nfs_page *req)
static inline struct nfs_page *
_nfs_find_request(struct inode *inode, struct page *page)
{
- struct list_head *head, *next;
+ struct list_head *head, *pos;
+ unsigned long pg_idx = page_index(page);
head = &inode->u.nfs_i.writeback;
- next = head->next;
- while (next != head) {
- struct nfs_page *req = nfs_inode_wb_entry(next);
- next = next->next;
- if (page_index(req->wb_page) != page_index(page))
+ list_for_each_prev(pos, head) {
+ struct nfs_page *req = nfs_inode_wb_entry(pos);
+ unsigned long found_idx = page_index(req->wb_page);
+
+ if (pg_idx < found_idx)
continue;
+ if (pg_idx != found_idx)
+ break;
req->wb_count++;
return req;
}
@@ -444,20 +459,20 @@ nfs_wait_on_requests(struct inode *inode, struct file *file, unsigned long idx_s
else
idx_end = idx_start + npages - 1;
- spin_lock(&nfs_wreq_lock);
head = &inode->u.nfs_i.writeback;
- p = head->next;
- while (p != head) {
+ restart:
+ spin_lock(&nfs_wreq_lock);
+ list_for_each_prev(p, head) {
unsigned long pg_idx;
struct nfs_page *req = nfs_inode_wb_entry(p);
- p = p->next;
-
if (file && req->wb_file != file)
continue;
pg_idx = page_index(req->wb_page);
- if (pg_idx < idx_start || pg_idx > idx_end)
+ if (pg_idx < idx_start)
+ break;
+ if (pg_idx > idx_end)
continue;
if (!NFS_WBACK_BUSY(req))
@@ -468,9 +483,8 @@ nfs_wait_on_requests(struct inode *inode, struct file *file, unsigned long idx_s
nfs_release_request(req);
if (error < 0)
return error;
- spin_lock(&nfs_wreq_lock);
- p = head->next;
res++;
+ goto restart;
}
spin_unlock(&nfs_wreq_lock);
return res;
@@ -991,6 +1005,9 @@ nfs_writeback_done(struct rpc_task *task)
dprintk("NFS: %4d nfs_writeback_done (status %d)\n",
task->tk_pid, task->tk_status);
+ if (nfs_async_handle_jukebox(task))
+ return;
+
/* We can't handle that yet but we check for it nevertheless */
if (resp->count < argp->count && task->tk_status >= 0) {
static unsigned long complain;
@@ -1184,6 +1201,9 @@ nfs_commit_done(struct rpc_task *task)
dprintk("NFS: %4d nfs_commit_done (status %d)\n",
task->tk_pid, task->tk_status);
+ if (nfs_async_handle_jukebox(task))
+ return;
+
nfs_write_attributes(inode, resp->fattr);
while (!list_empty(&data->pages)) {
req = nfs_list_entry(data->pages.next);
diff --git a/include/linux/cache.h b/include/linux/cache.h
index 086accecf..14e9c0b89 100644
--- a/include/linux/cache.h
+++ b/include/linux/cache.h
@@ -34,4 +34,12 @@
#endif
#endif /* __cacheline_aligned */
+#ifndef __cacheline_aligned_in_smp
+#ifdef CONFIG_SMP
+#define __cacheline_aligned_in_smp __cacheline_aligned
+#else
+#define __cacheline_aligned_in_smp
+#endif /* CONFIG_SMP */
+#endif
+
#endif /* __LINUX_CACHE_H */
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index 1768e5249..db5de1462 100644
--- a/include/linux/ext3_fs.h
+++ b/include/linux/ext3_fs.h
@@ -36,8 +36,8 @@
/*
* The second extended file system version
*/
-#define EXT3FS_DATE "06 Nov 2001"
-#define EXT3FS_VERSION "2.4-0.9.15"
+#define EXT3FS_DATE "02 Dec 2001"
+#define EXT3FS_VERSION "2.4-0.9.16"
/*
* Debug code
@@ -209,10 +209,10 @@ struct ext3_group_desc
#define EXT3_FL_USER_MODIFIABLE 0x000000FF /* User modifiable flags */
/*
- * Inode dynamic state bit positions
+ * Inode dynamic state flags
*/
-#define EXT3_STATE_JDATA 0 /* journaled data exists */
-#define EXT3_STATE_NEW 1 /* inode is newly created */
+#define EXT3_STATE_JDATA 0x00000001 /* journaled data exists */
+#define EXT3_STATE_NEW 0x00000002 /* inode is newly created */
/*
* ioctl commands
@@ -577,10 +577,6 @@ struct ext3_dir_entry_2 {
~EXT3_DIR_ROUND)
#ifdef __KERNEL__
-
-/* Filesize hard limits for 64-bit file offsets */
-extern long long ext3_max_sizes[];
-
/*
* Describe an inode's exact location on disk and in memory
*/
@@ -603,9 +599,6 @@ struct ext3_iloc
# define ATTRIB_NORET __attribute__((noreturn))
# define NORET_AND noreturn,
-/* acl.c */
-extern int ext3_permission (struct inode *, int);
-
/* balloc.c */
extern int ext3_bg_has_super(struct super_block *sb, int group);
extern unsigned long ext3_bg_num_gdb(struct super_block *sb, int group);
@@ -619,16 +612,10 @@ extern struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb,
unsigned int block_group,
struct buffer_head ** bh);
-/* bitmap.c */
-extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
-
/* dir.c */
extern int ext3_check_dir_entry(const char *, struct inode *,
struct ext3_dir_entry_2 *, struct buffer_head *,
unsigned long);
-
-/* file.c */
-
/* fsync.c */
extern int ext3_sync_file (struct file *, struct dentry *, int);
@@ -638,9 +625,9 @@ extern void ext3_free_inode (handle_t *, struct inode *);
extern struct inode * ext3_orphan_get (struct super_block *, ino_t);
extern unsigned long ext3_count_free_inodes (struct super_block *);
extern void ext3_check_inodes_bitmap (struct super_block *);
+extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
/* inode.c */
-
extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
@@ -654,13 +641,13 @@ extern int ext3_sync_inode (handle_t *, struct inode *);
extern void ext3_discard_prealloc (struct inode *);
extern void ext3_dirty_inode(struct inode *);
extern int ext3_change_inode_journal_flag(struct inode *, int);
+extern void ext3_truncate (struct inode *);
/* ioctl.c */
extern int ext3_ioctl (struct inode *, struct file *, unsigned int,
unsigned long);
/* namei.c */
-extern struct inode_operations ext3_dir_inode_operations;
extern int ext3_orphan_add(handle_t *, struct inode *);
extern int ext3_orphan_del(handle_t *, struct inode *);
@@ -684,9 +671,6 @@ extern int ext3_remount (struct super_block *, int *, char *);
extern struct super_block * ext3_read_super (struct super_block *,void *,int);
extern int ext3_statfs (struct super_block *, struct statfs *);
-/* truncate.c */
-extern void ext3_truncate (struct inode *);
-
#define ext3_std_error(sb, errno) \
do { \
if ((errno)) \
@@ -705,10 +689,15 @@ extern struct file_operations ext3_dir_operations;
extern struct inode_operations ext3_file_inode_operations;
extern struct file_operations ext3_file_operations;
+/* inode.c */
+extern struct address_space_operations ext3_aops;
+
+/* namei.c */
+extern struct inode_operations ext3_dir_inode_operations;
+
/* symlink.c */
extern struct inode_operations ext3_fast_symlink_inode_operations;
-extern struct address_space_operations ext3_aops;
#endif /* __KERNEL__ */
diff --git a/include/linux/ext3_fs_i.h b/include/linux/ext3_fs_i.h
index c3cb21235..3c8d398a8 100644
--- a/include/linux/ext3_fs_i.h
+++ b/include/linux/ext3_fs_i.h
@@ -34,7 +34,7 @@ struct ext3_inode_info {
__u32 i_dir_acl;
__u32 i_dtime;
__u32 i_block_group;
- unsigned long i_state; /* Dynamic state flags for ext3 */
+ __u32 i_state; /* Dynamic state flags for ext3 */
__u32 i_next_alloc_block;
__u32 i_next_alloc_goal;
#ifdef EXT3_PREALLOCATE
diff --git a/include/linux/ext3_jbd.h b/include/linux/ext3_jbd.h
index 9e4002b52..88bb8a516 100644
--- a/include/linux/ext3_jbd.h
+++ b/include/linux/ext3_jbd.h
@@ -196,9 +196,22 @@ __ext3_journal_dirty_metadata(const char *where,
*/
static inline handle_t *ext3_journal_start(struct inode *inode, int nblocks)
{
+ journal_t *journal;
+
if (inode->i_sb->s_flags & MS_RDONLY)
return ERR_PTR(-EROFS);
- return journal_start(EXT3_JOURNAL(inode), nblocks);
+
+ /* Special case here: if the journal has aborted behind our
+ * backs (eg. EIO in the commit thread), then we still need to
+ * take the FS itself readonly cleanly. */
+ journal = EXT3_JOURNAL(inode);
+ if (is_journal_aborted(journal)) {
+ ext3_abort(inode->i_sb, __FUNCTION__,
+ "Detected aborted journal");
+ return ERR_PTR(-EROFS);
+ }
+
+ return journal_start(journal, nblocks);
}
static inline handle_t *
diff --git a/include/linux/init.h b/include/linux/init.h
index f0644ca30..53218e330 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -111,7 +111,7 @@ extern struct kernel_param __setup_start, __setup_end;
*/
#define module_exit(x) __exitcall(x);
-#else
+#else /* MODULE */
#define __init
#define __exit
@@ -141,7 +141,7 @@ typedef void (*__cleanup_module_func_t)(void);
#define __setup(str,func) /* nothing */
-#endif
+#endif /* !MODULE */
#ifdef CONFIG_HOTPLUG
#define __devinit
@@ -155,4 +155,16 @@ typedef void (*__cleanup_module_func_t)(void);
#define __devexitdata __exitdata
#endif
+/* Functions marked as __devexit may be discarded at kernel link time, depending
+ on config options. Newer versions of binutils detect references from
+ retained sections to discarded sections and flag an error. Pointers to
+ __devexit functions must use __devexit_p(function_name), the wrapper will
+ insert either the function_name or NULL, depending on the config options.
+ */
+#if defined(MODULE) || defined(CONFIG_HOTPLUG)
+#define __devexit_p(x) x
+#else
+#define __devexit_p(x) NULL
+#endif
+
#endif /* _LINUX_INIT_H */
diff --git a/include/linux/jbd.h b/include/linux/jbd.h
index 64d90a289..2cb980fbb 100644
--- a/include/linux/jbd.h
+++ b/include/linux/jbd.h
@@ -564,7 +564,7 @@ extern void __journal_clean_data_list(transaction_t *transaction);
/* Log buffer allocation */
extern struct journal_head * journal_get_descriptor_buffer(journal_t *);
-extern unsigned long journal_next_log_block(journal_t *);
+int journal_next_log_block(journal_t *, unsigned long *);
/* Commit management */
extern void journal_commit_transaction(journal_t *);
@@ -664,15 +664,16 @@ extern int journal_load (journal_t *journal);
extern void journal_destroy (journal_t *);
extern int journal_recover (journal_t *journal);
extern int journal_wipe (journal_t *, int);
-extern int journal_skip_recovery (journal_t *);
-extern void journal_update_superblock (journal_t *, int);
-extern void __journal_abort (journal_t *);
+extern int journal_skip_recovery (journal_t *);
+extern void journal_update_superblock (journal_t *, int);
+extern void __journal_abort_hard (journal_t *);
+extern void __journal_abort_soft (journal_t *, int);
extern void journal_abort (journal_t *, int);
extern int journal_errno (journal_t *);
extern void journal_ack_err (journal_t *);
extern int journal_clear_err (journal_t *);
-extern unsigned long journal_bmap(journal_t *journal, unsigned long blocknr);
-extern int journal_force_commit(journal_t *journal);
+extern int journal_bmap(journal_t *, unsigned long, unsigned long *);
+extern int journal_force_commit(journal_t *);
/*
* journal_head management
diff --git a/include/linux/list.h b/include/linux/list.h
index 0d04422e8..61b1493f5 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -162,6 +162,16 @@ static __inline__ void list_splice(struct list_head *list, struct list_head *hea
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
+/**
+ * list_for_each_prev - iterate over a list in reverse order
+ * @pos: the &struct list_head to use as a loop counter.
+ * @head: the head for your list.
+ */
+#define list_for_each_prev(pos, head) \
+ for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \
+ pos = pos->prev, prefetch(pos->prev))
+
+
#endif /* __KERNEL__ || _LVM_H_INCLUDE */
#endif
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 186fe152a..98b763c4f 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -422,6 +422,9 @@ extern int ptrace_detach(struct task_struct *, unsigned int);
extern void ptrace_disable(struct task_struct *);
extern int ptrace_check_attach(struct task_struct *task, int kill);
+int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long start,
+ int len, int write, int force, struct page **pages, struct vm_area_struct **vmas);
+
/*
* On a two-level page table, this ends up being trivial. Thus the
* inlining and the symmetry break with pte_alloc() that does all
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index efbbdba3a..4266b3ce0 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -16,6 +16,7 @@
#include <linux/sunrpc/debug.h>
#include <linux/sunrpc/auth.h>
+#include <linux/sunrpc/clnt.h>
#include <linux/nfs.h>
#include <linux/nfs2.h>
@@ -332,6 +333,29 @@ extern void * nfs_root_data(void);
__retval; \
})
+#ifdef CONFIG_NFS_V3
+
+#define NFS_JUKEBOX_RETRY_TIME (5 * HZ)
+static inline int
+nfs_async_handle_jukebox(struct rpc_task *task)
+{
+ if (task->tk_status != -EJUKEBOX)
+ return 0;
+ task->tk_status = 0;
+ rpc_restart_call(task);
+ rpc_delay(task, NFS_JUKEBOX_RETRY_TIME);
+ return 1;
+}
+
+#else
+
+static inline int
+nfs_async_handle_jukebox(struct rpc_task *task)
+{
+ return 0;
+}
+#endif /* CONFIG_NFS_V3 */
+
#endif /* __KERNEL__ */
/*
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index da45fa2be..b729b6f30 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -121,119 +121,17 @@ int ptrace_detach(struct task_struct *child, unsigned int data)
}
/*
- * Access another process' address space, one page at a time.
+ * Access another process' address space.
+ * Source/target buffer must be kernel space,
+ * Do not walk the page table directly, use get_user_pages
*/
-static int access_one_page(struct mm_struct * mm, struct vm_area_struct * vma, unsigned long addr, void *buf, int len, int write)
-{
- pgd_t * pgdir;
- pmd_t * pgmiddle;
- pte_t * pgtable;
- char *maddr;
- struct page *page;
-
-repeat:
- spin_lock(&mm->page_table_lock);
- pgdir = pgd_offset(vma->vm_mm, addr);
- if (pgd_none(*pgdir))
- goto fault_in_page;
- if (pgd_bad(*pgdir))
- goto bad_pgd;
- pgmiddle = pmd_offset(pgdir, addr);
- if (pmd_none(*pgmiddle))
- goto fault_in_page;
- if (pmd_bad(*pgmiddle))
- goto bad_pmd;
- pgtable = pte_offset(pgmiddle, addr);
- if (!pte_present(*pgtable))
- goto fault_in_page;
- if (write && (!pte_write(*pgtable) || !pte_dirty(*pgtable)))
- goto fault_in_page;
- page = pte_page(*pgtable);
-
- /* ZERO_PAGE is special: reads from it are ok even though it's marked reserved */
- if (page != ZERO_PAGE(addr) || write) {
- if ((!VALID_PAGE(page)) || PageReserved(page)) {
- spin_unlock(&mm->page_table_lock);
- return 0;
- }
- }
- get_page(page);
- spin_unlock(&mm->page_table_lock);
- flush_cache_page(vma, addr);
-
- if (write) {
- maddr = kmap(page);
- memcpy(maddr + (addr & ~PAGE_MASK), buf, len);
- flush_page_to_ram(page);
- flush_icache_page(vma, page);
- kunmap(page);
- } else {
- maddr = kmap(page);
- memcpy(buf, maddr + (addr & ~PAGE_MASK), len);
- flush_page_to_ram(page);
- kunmap(page);
- }
- put_page(page);
- return len;
-
-fault_in_page:
- spin_unlock(&mm->page_table_lock);
- /* -1: out of memory. 0 - unmapped page */
- if (handle_mm_fault(mm, vma, addr, write) > 0)
- goto repeat;
- return 0;
-
-bad_pgd:
- spin_unlock(&mm->page_table_lock);
- pgd_ERROR(*pgdir);
- return 0;
-
-bad_pmd:
- spin_unlock(&mm->page_table_lock);
- pmd_ERROR(*pgmiddle);
- return 0;
-}
-
-static int access_mm(struct mm_struct *mm, struct vm_area_struct * vma, unsigned long addr, void *buf, int len, int write)
-{
- int copied = 0;
-
- for (;;) {
- unsigned long offset = addr & ~PAGE_MASK;
- int this_len = PAGE_SIZE - offset;
- int retval;
-
- if (this_len > len)
- this_len = len;
- retval = access_one_page(mm, vma, addr, buf, this_len, write);
- copied += retval;
- if (retval != this_len)
- break;
-
- len -= retval;
- if (!len)
- break;
-
- addr += retval;
- buf += retval;
-
- if (addr < vma->vm_end)
- continue;
- if (!vma->vm_next)
- break;
- if (vma->vm_next->vm_start != vma->vm_end)
- break;
-
- vma = vma->vm_next;
- }
- return copied;
-}
int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write)
{
- int copied;
struct mm_struct *mm;
- struct vm_area_struct * vma;
+ struct vm_area_struct *vma;
+ struct page *page;
+ void *old_buf = buf;
/* Worry about races with exit() */
task_lock(tsk);
@@ -245,14 +143,41 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in
return 0;
down_read(&mm->mmap_sem);
- vma = find_extend_vma(mm, addr);
- copied = 0;
- if (vma)
- copied = access_mm(mm, vma, addr, buf, len, write);
+ /* ignore errors, just check how much was sucessfully transfered */
+ while (len) {
+ int bytes, ret, offset;
+ void *maddr;
+
+ ret = get_user_pages(current, mm, addr, 1,
+ write, 1, &page, &vma);
+ if (ret <= 0)
+ break;
+ bytes = len;
+ offset = addr & (PAGE_SIZE-1);
+ if (bytes > PAGE_SIZE-offset)
+ bytes = PAGE_SIZE-offset;
+
+ flush_cache_page(vma, addr);
+
+ maddr = kmap(page);
+ if (write) {
+ memcpy(maddr + offset, buf, bytes);
+ flush_page_to_ram(page);
+ flush_icache_page(vma, page);
+ } else {
+ memcpy(buf, maddr + offset, bytes);
+ flush_page_to_ram(page);
+ }
+ kunmap(page);
+ put_page(page);
+ len -= bytes;
+ buf += bytes;
+ }
up_read(&mm->mmap_sem);
mmput(mm);
- return copied;
+
+ return buf - old_buf;
}
int ptrace_readdata(struct task_struct *tsk, unsigned long src, char *dst, int len)
diff --git a/mm/filemap.c b/mm/filemap.c
index 9eccb5783..129849b4b 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -53,7 +53,7 @@ EXPORT_SYMBOL(vm_max_readahead);
EXPORT_SYMBOL(vm_min_readahead);
-spinlock_t pagecache_lock ____cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
+spinlock_t pagecache_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
/*
* NOTE: to avoid deadlocking you must never acquire the pagemap_lru_lock
* with the pagecache_lock held.
@@ -63,7 +63,7 @@ spinlock_t pagecache_lock ____cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
* pagemap_lru_lock ->
* pagecache_lock
*/
-spinlock_t pagemap_lru_lock ____cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
+spinlock_t pagemap_lru_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
#define CLUSTER_PAGES (1 << page_cluster)
#define CLUSTER_OFFSET(x) (((x) >> page_cluster) << page_cluster)
diff --git a/mm/highmem.c b/mm/highmem.c
index dce6c792f..a4a3fbb71 100644
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -32,7 +32,7 @@
*/
static int pkmap_count[LAST_PKMAP];
static unsigned int last_pkmap_nr;
-static spinlock_t kmap_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t kmap_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
pte_t * pkmap_page_table;
diff --git a/mm/memory.c b/mm/memory.c
index 19924efce..f455a5d3d 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -397,17 +397,16 @@ void zap_page_range(struct mm_struct *mm, unsigned long address, unsigned long s
spin_unlock(&mm->page_table_lock);
}
-
/*
* Do a quick page-table lookup for a single page.
*/
-static struct page * follow_page(unsigned long address, int write)
+static struct page * follow_page(struct mm_struct *mm, unsigned long address, int write)
{
pgd_t *pgd;
pmd_t *pmd;
pte_t *ptep, pte;
- pgd = pgd_offset(current->mm, address);
+ pgd = pgd_offset(mm, address);
if (pgd_none(*pgd) || pgd_bad(*pgd))
goto out;
@@ -443,21 +442,74 @@ static inline struct page * get_page_map(struct page *page)
return page;
}
+int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long start,
+ int len, int write, int force, struct page **pages, struct vm_area_struct **vmas)
+{
+ int i = 0;
+
+ do {
+ struct vm_area_struct * vma;
+
+ vma = find_extend_vma(mm, start);
+
+ if ( !vma ||
+ (!force &&
+ ((write && (!(vma->vm_flags & VM_WRITE))) ||
+ (!write && (!(vma->vm_flags & VM_READ))) ) )) {
+ if (i) return i;
+ return -EFAULT;
+ }
+
+ spin_lock(&mm->page_table_lock);
+ do {
+ struct page *map;
+ while (!(map = follow_page(mm, start, write))) {
+ spin_unlock(&mm->page_table_lock);
+ switch (handle_mm_fault(mm, vma, start, write)) {
+ case 1:
+ tsk->min_flt++;
+ break;
+ case 2:
+ tsk->maj_flt++;
+ break;
+ case 0:
+ if (i) return i;
+ return -EFAULT;
+ default:
+ if (i) return i;
+ return -ENOMEM;
+ }
+ spin_lock(&mm->page_table_lock);
+ }
+ if (pages) {
+ pages[i] = get_page_map(map);
+ /* FIXME: call the correct function,
+ * depending on the type of the found page
+ */
+ if (pages[i])
+ page_cache_get(pages[i]);
+ }
+ if (vmas)
+ vmas[i] = vma;
+ i++;
+ start += PAGE_SIZE;
+ len--;
+ } while(len && start < vma->vm_end);
+ spin_unlock(&mm->page_table_lock);
+ } while(len);
+ return i;
+}
+
/*
* Force in an entire range of pages from the current process's user VA,
* and pin them in physical memory.
*/
-
#define dprintk(x...)
+
int map_user_kiobuf(int rw, struct kiobuf *iobuf, unsigned long va, size_t len)
{
- unsigned long ptr, end;
- int err;
+ int pgcount, err;
struct mm_struct * mm;
- struct vm_area_struct * vma = 0;
- struct page * map;
- int i;
- int datain = (rw == READ);
/* Make sure the iobuf is not already mapped somewhere. */
if (iobuf->nr_pages)
@@ -466,79 +518,37 @@ int map_user_kiobuf(int rw, struct kiobuf *iobuf, unsigned long va, size_t len)
mm = current->mm;
dprintk ("map_user_kiobuf: begin\n");
- ptr = va & PAGE_MASK;
- end = (va + len + PAGE_SIZE - 1) & PAGE_MASK;
- err = expand_kiobuf(iobuf, (end - ptr) >> PAGE_SHIFT);
+ pgcount = (va + len + PAGE_SIZE - 1)/PAGE_SIZE - va/PAGE_SIZE;
+ /* mapping 0 bytes is not permitted */
+ if (!pgcount) BUG();
+ err = expand_kiobuf(iobuf, pgcount);
if (err)
return err;
- down_read(&mm->mmap_sem);
-
- err = -EFAULT;
iobuf->locked = 0;
- iobuf->offset = va & ~PAGE_MASK;
+ iobuf->offset = va & (PAGE_SIZE-1);
iobuf->length = len;
- i = 0;
-
- /*
- * First of all, try to fault in all of the necessary pages
- */
- while (ptr < end) {
- if (!vma || ptr >= vma->vm_end) {
- vma = find_vma(current->mm, ptr);
- if (!vma)
- goto out_unlock;
- if (vma->vm_start > ptr) {
- if (!(vma->vm_flags & VM_GROWSDOWN))
- goto out_unlock;
- if (expand_stack(vma, ptr))
- goto out_unlock;
- }
- if (((datain) && (!(vma->vm_flags & VM_WRITE))) ||
- (!(vma->vm_flags & VM_READ))) {
- err = -EACCES;
- goto out_unlock;
- }
- }
- spin_lock(&mm->page_table_lock);
- while (!(map = follow_page(ptr, datain))) {
- int ret;
-
- spin_unlock(&mm->page_table_lock);
- ret = handle_mm_fault(current->mm, vma, ptr, datain);
- if (ret <= 0) {
- if (!ret)
- goto out_unlock;
- else {
- err = -ENOMEM;
- goto out_unlock;
- }
- }
- spin_lock(&mm->page_table_lock);
- }
- map = get_page_map(map);
- if (map) {
- flush_dcache_page(map);
- page_cache_get(map);
- } else
- printk (KERN_INFO "Mapped page missing [%d]\n", i);
- spin_unlock(&mm->page_table_lock);
- iobuf->maplist[i] = map;
- iobuf->nr_pages = ++i;
-
- ptr += PAGE_SIZE;
- }
-
+ /* Try to fault in all of the necessary pages */
+ down_read(&mm->mmap_sem);
+ /* rw==READ means read from disk, write into memory area */
+ err = get_user_pages(current, mm, va, pgcount,
+ (rw==READ), 0, iobuf->maplist, NULL);
up_read(&mm->mmap_sem);
+ if (err < 0) {
+ unmap_kiobuf(iobuf);
+ dprintk ("map_user_kiobuf: end %d\n", err);
+ return err;
+ }
+ iobuf->nr_pages = err;
+ while (pgcount--) {
+ /* FIXME: flush superflous for rw==READ,
+ * probably wrong function for rw==WRITE
+ */
+ flush_dcache_page(iobuf->maplist[pgcount]);
+ }
dprintk ("map_user_kiobuf: end OK\n");
return 0;
-
- out_unlock:
- up_read(&mm->mmap_sem);
- unmap_kiobuf(iobuf);
- dprintk ("map_user_kiobuf: end %d\n", err);
- return err;
}
/*
@@ -588,6 +598,9 @@ void unmap_kiobuf (struct kiobuf *iobuf)
if (map) {
if (iobuf->locked)
UnlockPage(map);
+ /* FIXME: cache flush missing for rw==READ
+ * FIXME: call the correct reference counting function
+ */
page_cache_release(map);
}
}
@@ -1409,23 +1422,19 @@ out:
return pte_offset(pmd, address);
}
-/*
- * Simplistic page force-in..
- */
int make_pages_present(unsigned long addr, unsigned long end)
{
- int write;
- struct mm_struct *mm = current->mm;
+ int ret, len, write;
struct vm_area_struct * vma;
- vma = find_vma(mm, addr);
+ vma = find_vma(current->mm, addr);
write = (vma->vm_flags & VM_WRITE) != 0;
if (addr >= end)
BUG();
- do {
- if (handle_mm_fault(mm, vma, addr, write) < 0)
- return -1;
- addr += PAGE_SIZE;
- } while (addr < end);
- return 0;
+ if (end > vma->vm_end)
+ BUG();
+ len = (end+PAGE_SIZE-1)/PAGE_SIZE-addr/PAGE_SIZE;
+ ret = get_user_pages(current, current->mm, addr,
+ len, write, 0, NULL, NULL);
+ return ret == len ? 0 : -1;
}
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 87fd3e0ed..b743e432e 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -6,6 +6,7 @@
* SMP-safe vmalloc/vfree/ioremap, Tigran Aivazian <tigran@veritas.com>, May 2000
*/
+#include <linux/config.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/spinlock.h>
@@ -282,3 +283,40 @@ finished:
read_unlock(&vmlist_lock);
return buf - buf_start;
}
+
+long vwrite(char *buf, char *addr, unsigned long count)
+{
+ struct vm_struct *tmp;
+ char *vaddr, *buf_start = buf;
+ unsigned long n;
+
+ /* Don't allow overflow */
+ if ((unsigned long) addr + count < count)
+ count = -(unsigned long) addr;
+
+ read_lock(&vmlist_lock);
+ for (tmp = vmlist; tmp; tmp = tmp->next) {
+ vaddr = (char *) tmp->addr;
+ if (addr >= vaddr + tmp->size - PAGE_SIZE)
+ continue;
+ while (addr < vaddr) {
+ if (count == 0)
+ goto finished;
+ buf++;
+ addr++;
+ count--;
+ }
+ n = vaddr + tmp->size - PAGE_SIZE - addr;
+ do {
+ if (count == 0)
+ goto finished;
+ *addr = *buf;
+ buf++;
+ addr++;
+ count--;
+ } while (--n > 0);
+ }
+finished:
+ read_unlock(&vmlist_lock);
+ return buf - buf_start;
+}