diff -Nru a/Documentation/cpufreq b/Documentation/cpufreq --- a/Documentation/cpufreq Fri Nov 22 13:41:22 2002 +++ b/Documentation/cpufreq Fri Nov 22 13:41:22 2002 @@ -87,7 +87,8 @@ Transmeta Crusoe Longrun: Transmeta Crusoe processors: -------------------------------- - Does not work with the 2.4. /proc/sys/cpu/ interface. + It is recommended to use the 2.6. /proc/cpufreq interface when + using this driver @@ -283,15 +284,17 @@ cpufreq_verify_t verify: This is a pointer to a function with the following definition: - void verify_function (struct cpufreq_policy *policy). + int verify_function (struct cpufreq_policy *policy). This function must verify the new policy is within the limits supported by the CPU, and at least one supported CPU is within this range. It may be useful to use cpufreq.h / - cpufreq_verify_within_limits for this. + cpufreq_verify_within_limits for this. If this is called with + CPUFREQ_ALL_CPUS, and there is no common subset of frequencies + for all CPUs, exit with an error. cpufreq_setpolicy_t setpolicy: This is a pointer to a function with the following definition: - void setpolicy_function (struct cpufreq_policy *policy). + int setpolicy_function (struct cpufreq_policy *policy). This function must set the CPU to the new policy. If it is a "dumb" CPU which only allows fixed frequencies to be set, it shall set it to the lowest within the limit for @@ -302,30 +305,30 @@ struct cpufreq_policy *policy: This is an array of NR_CPUS struct cpufreq_policies, containing the current policies set for these - CPUs. Note that policy[0].max_cpu_freq must contain the - absolute maximum CPU frequency supported by _all_ CPUs. + CPUs. Note that policy[cpu].max_cpu_freq must contain the + absolute maximum CPU frequency supported by the specified cpu. In case the driver is expected to run with the 2.4.-style API (/proc/sys/cpu/.../), two more values must be passed #ifdef CONFIG_CPU_FREQ_24_API - unsigned int cpu_min_freq; + unsigned int cpu_min_freq[NR_CPUS]; unsigned int cpu_cur_freq[NR_CPUS]; #endif - with cpu_min_freq being the minimum CPU frequency supported by - the CPUs; and the entries in cpu_cur_freq reflecting the - current speed of the appropriate CPU. + with cpu_min_freq[cpu] being the minimum CPU frequency + supported by the CPU; and the entries in cpu_cur_freq + reflecting the current speed of the appropriate CPU. Some Requirements to CPUFreq architecture drivers ------------------------------------------------- * Only call cpufreq_register() when the ability to switch CPU - frequencies is _verified_ or can't be missing + frequencies is _verified_ or can't be missing. Also, all + other initialization must be done beofre this call, as + cpfureq_register calls the driver's verify and setpolicy code for + each CPU. * cpufreq_unregister() may only be called if cpufreq_register() has been successfully(!) called before. * kfree() the struct cpufreq_driver only after the call to cpufreq_unregister(), unless cpufreq_register() failed. -* Be aware that there is currently no error management in the - setpolicy() code in the CPUFreq core. So only call yourself a - cpufreq_driver if you are really a working cpufreq_driver! diff -Nru a/Documentation/crypto/api-intro.txt b/Documentation/crypto/api-intro.txt --- a/Documentation/crypto/api-intro.txt Fri Nov 22 13:41:22 2002 +++ b/Documentation/crypto/api-intro.txt Fri Nov 22 13:41:22 2002 @@ -73,6 +73,13 @@ alias des3_ede des +The Null algorithms reside in the crypto_null module, so these lines +should also be added: + + alias cipher_null crypto_null + alias digest_null crypto_null + alias compress_null crypto_null + DEVELOPER NOTES @@ -108,6 +115,9 @@ It's a good idea to avoid using lots of macros and use inlined functions instead, as gcc does a good job with inlining, while excessive use of macros can cause compilation problems on some platforms. + +Also check the TODO list at the web site listed below to see what people +might already be working on. BUGS diff -Nru a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking --- a/Documentation/filesystems/Locking Fri Nov 22 13:41:23 2002 +++ b/Documentation/filesystems/Locking Fri Nov 22 13:41:23 2002 @@ -35,7 +35,7 @@ int (*symlink) (struct inode *,struct dentry *,const char *); int (*mkdir) (struct inode *,struct dentry *,int); int (*rmdir) (struct inode *,struct dentry *); - int (*mknod) (struct inode *,struct dentry *,int,int); + int (*mknod) (struct inode *,struct dentry *,int,dev_t); int (*rename) (struct inode *, struct dentry *, struct inode *, struct dentry *); int (*readlink) (struct dentry *, char *,int); @@ -135,7 +135,6 @@ int (*readpage)(struct file *, struct page *); int (*sync_page)(struct page *); int (*writepages)(struct address_space *, int *nr_to_write); - int (*vm_writeback)(struct page *, int *nr_to_write); int (*set_page_dirty)(struct page *page); int (*prepare_write)(struct file *, struct page *, unsigned, unsigned); int (*commit_write)(struct file *, struct page *, unsigned, unsigned); @@ -153,7 +152,6 @@ readpages: no sync_page: no maybe writepages: no -vm_writeback: no yes set_page_dirty no no prepare_write: no yes commit_write: no yes @@ -189,14 +187,6 @@ written. The address_space implementation may write more (or less) pages than *nr_to_write asks for, but it should try to be reasonably close. If nr_to_write is NULL, all dirty pages must be written. - - ->vm_writeback() is called from the VM. The address_space should -start I/O against at least *nr_to_write pages, including the passed page. As -each page is written its PG_launder flag must be set (inside the page lock). - - The vm_writeback() function is provided so that filesytems can perform -clustered writeback around the page which the VM is trying to clean. -If a_ops.vm_writeback is NULL the VM will fall back to single-page writepage(). ->set_page_dirty() is called from various places in the kernel when the target page is marked as needing writeback. It may be called diff -Nru a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt --- a/Documentation/filesystems/vfs.txt Fri Nov 22 13:41:21 2002 +++ b/Documentation/filesystems/vfs.txt Fri Nov 22 13:41:21 2002 @@ -258,7 +258,7 @@ int (*symlink) (struct inode *,struct dentry *,const char *); int (*mkdir) (struct inode *,struct dentry *,int); int (*rmdir) (struct inode *,struct dentry *); - int (*mknod) (struct inode *,struct dentry *,int,int); + int (*mknod) (struct inode *,struct dentry *,int,dev_t); int (*rename) (struct inode *, struct dentry *, struct inode *, struct dentry *); int (*readlink) (struct dentry *, char *,int); diff -Nru a/Documentation/kobject.txt b/Documentation/kobject.txt --- a/Documentation/kobject.txt Fri Nov 22 13:41:18 2002 +++ b/Documentation/kobject.txt Fri Nov 22 13:41:18 2002 @@ -5,7 +5,9 @@ 30 October 2002 -kobjects +1. kobjects + +1.1 Description struct kobject introduces a simple, intregral datatype and a simple set of semantics for operating on the device. kobjects are intended to @@ -13,8 +15,8 @@ duplicates. A set of library functions has been developed to assist in the manipulation of kobjects. -struct kobject looks like this: +1.2 Defintion struct kobject { char name[16]; @@ -26,21 +28,29 @@ }; void kobject_init(struct kobject *); +int kobject_add(struct kobject *); int kobject_register(struct kobject *); + +void kobject_del(struct kobject *); +void kobject_cleanup(struct kobject *); void kobject_unregister(struct kobject *); + struct kobject * kobject_get(struct kobject *); void kobject_put(struct kobject *); -subsystems +2. subsystems + +2.1 Description struct subsystem is introduced to describe a collection of objects of a certain type. subsystems are kobjects themselves, though they contain lists of kobjects that belong to that subsystem. Objects of a subsystem (the embedder objects in which kobjects live) are all of the -same type. The interface looks like: +same type. +2.2 Definition struct subsystem { struct kobject kobj; @@ -60,6 +70,95 @@ void subsys_put(struct subsystem * s); +3. The Interface + +The kobject API provides a symmeticral interface that may be used in +one of two ways: by using the default front-end registration +interface, or by directly using the backend helpers the registration +interface uses. + +3.1 Default Usage + +The default usage is to use kobjet_register() to add a device to the +object hierarchy, and kobject_unregister() to remove it. + +kobject_register() will call kobject_init() and kobject_add() +consecutively. kobject_init() will initialize the object and increment +the reference count of the subsystem the object belongs to. It will +leave the reference count of the object at 1. + +kobject_add() will insert it into the object hierarchy and create +a sysfs directory for the object. This will increment the reference +count of the object, leaving it at 2. + +kobject_unregister() will call kobject_del() and kobject_put() +consecutively. kobject_del() will remove the object from the hierarchy +and the sysfs directory for the object. It will decrement the +reference count for the object. Assuming there are no other users of +the object, it will be left at 1. + +kobject_put() will decrement the reference count of the object, and +when it reaches 0, call kobject_cleanup(). This will happen +immediately if there are no other users of the object. +kobject_cleanup() will call the subsystem's release() method +for the object, and decrement the subsystem's reference count. + +Because kobject_unregister() calls kobject_put(), instead of +kobject_cleanup() directly, when an object is unregistered, the +pointer to the object is guaranteed to remain valid until the last +reference to the object has gone away. + +Users of objects should call kobject_get() to obtain a reference to +the object that they are using. If the object passed to it is a valid +object (i.e. still present in the system), it will return a pointer to +the object. Otherwise, it will return NULL. + +When users are done using an object, they should call kobject_put() to +decrement the reference count on the object. As explained above, when +the reference count for the object reaches 0, kobject_cleanup() will +be called for the object. + + +3.2 Backend Usage + +Users of the kobject infrastructure may use the backend functions +directly. In order to maintain consistency and reduce confusion, users +of the interface should use only the front end registration-oriented +interface, or the backend helpers. + +Using the backend helpers allows code to use the kobjects solely for +the reference counting and garbage collection mechanisms, and +optionally adding them to the object hierarchy or exporting them via +sysfs. + +To take advantage of this side of the interface, users should call +kobject_init() to initialize the object. As stated above, this will +leave the reference count of the object at 1, and will enable the +subsystem to use the reference count of the object. + +When the life of the object is ending, the kobject_put() should be +called to decrement the reference count of the object. Just like +above, this will call kobject_cleanup() when the reference count +reaches 0, and release() method of the object's subsystem will be +called. + +During the lifetime of the object, kobject_add() and kobject_del() may +be called to add the object to the hierarchy and export it via +sysfs. kobject_del() must always be called if kobject_add() has +previously been called. Care should be taken to ensure kobject_del() +is called before the final kobject_put() is called, though not doing +so will not cause catastrophe, only confusion when reading the source +code. Fatal results are avoided by having kobject_add() increment the +reference count of the object, for kobject_del() to decrement. + + +3.3 Summary + +Using either interface, users should obtain the same results. The +registration interface does the same actions as the backend interface, +though it guarantees that initialization and addition, and deletion +and cleanup, happen consecutively. + Familial Relations @@ -133,22 +232,4 @@ object that registers with them. A subsystem definition may contain a NULL-terminated array of attributes that will be exported when an object is registered with the subsystem. - - -Reference Counting - -All objects contain reference counts. All functions accessing objects -should increment the reference count until they are finished, and -decrement the reference count. When an object is initialized, it -receives a reference count of 1. When a device is unregistered, the -reference is decremented. When the reference counts reaches 0, the -subsystem's ->release() callback for that object type (remember -subsystems control only one type of device each) is called; and the -reference counts of the kobject's subsystem and parent are -decremented. - -The ->release() callback is the opportunity for the subsystem to free -memory allocated for the object. It is the notification that -absolutely no one is using the structure any more (and can't acquire a -reference to it), so it is safe to free it. diff -Nru a/Documentation/sonypi.txt b/Documentation/sonypi.txt --- a/Documentation/sonypi.txt Fri Nov 22 13:41:17 2002 +++ b/Documentation/sonypi.txt Fri Nov 22 13:41:17 2002 @@ -1,6 +1,7 @@ Sony Programmable I/O Control Device Driver Readme -------------------------------------------------- - Copyright (C) 2001 Stelian Pop , Alcôve + Copyright (C) 2001-2002 Stelian Pop + Copyright (C) 2001-2002 Alcôve Copyright (C) 2001 Michael Ashley Copyright (C) 2001 Junichi Morita Copyright (C) 2000 Takaya Kinjo @@ -15,14 +16,14 @@ - capture button events (only on Vaio Picturebook series) - Fn keys - bluetooth button (only on C1VR model) - - back button (PCG-GR7/K model) - - lid open/close events (Z600NE model) + - programmable keys, back, help, zoom, thumbphrase buttons, etc. + (when available) Those events (see linux/sonypi.h) can be polled using the character device node /dev/sonypi (major 10, minor auto allocated or specified as a option). A simple daemon which translates the jogdial movements into mouse wheel events -can be downloaded at: +can be downloaded at: This driver supports also some ioctl commands for setting the LCD screen brightness and querying the batteries charge information (some more @@ -43,7 +44,7 @@ to /etc/modules.conf file, when the driver is compiled as a module or by adding the following to the kernel command line (in your bootloader): - sonypi=minor[,verbose[,fnkeyinit[,camera[,compat[,nojogdial]]]]] + sonypi=minor[,verbose[,fnkeyinit[,camera[,compat[,mask]]]]] where: @@ -64,15 +65,36 @@ with it and it shouldn't be required anyway if ACPI is already enabled). - verbose: print unknown events from the sonypi device + verbose: set to 1 to print unknown events received from the + sonypi device. + set to 2 to print all events received from the + sonypi device. compat: uses some compatibility code for enabling the sonypi events. If the driver worked for you in the past (prior to version 1.5) and does not work anymore, add this option and report to the author. - nojogdial: gives more accurate PKEY events on those Vaio models - which don't have a jogdial (like the FX series). + mask: event mask telling the driver what events will be + reported to the user. This parameter is required for some + Vaio models where the hardware reuses values used in + other Vaio models (like the FX series who does not + have a jogdial but reuses the jogdial events for + programmable keys events). The default event mask is + set to 0xffffffff, meaning that all possible events will be + tried. You can use the following bits to construct + your own event mask (from drivers/char/sonypi.h): + SONYPI_JOGGER_MASK 0x0001 + SONYPI_CAPTURE_MASK 0x0002 + SONYPI_FNKEY_MASK 0x0004 + SONYPI_BLUETOOTH_MASK 0x0008 + SONYPI_PKEY_MASK 0x0010 + SONYPI_BACK_MASK 0x0020 + SONYPI_HELP_MASK 0x0040 + SONYPI_LID_MASK 0x0080 + SONYPI_ZOOM_MASK 0x0100 + SONYPI_THUMBPHRASE_MASK 0x0200 + SONYPI_MEYE_MASK 0x0400 Module use: ----------- diff -Nru a/Documentation/video4linux/meye.txt b/Documentation/video4linux/meye.txt --- a/Documentation/video4linux/meye.txt Fri Nov 22 13:41:22 2002 +++ b/Documentation/video4linux/meye.txt Fri Nov 22 13:41:22 2002 @@ -1,6 +1,7 @@ Vaio Picturebook Motion Eye Camera Driver Readme ------------------------------------------------ - Copyright (C) 2001 Stelian Pop , Alcôve + Copyright (C) 2001-2002 Stelian Pop + Copyright (C) 2001-2002 Alcôve Copyright (C) 2000 Andrew Tridgell This driver enable the use of video4linux compatible applications with the @@ -52,7 +53,7 @@ or xawtv -c /dev/video0 -geometry 320x240 - motioneye () + motioneye () for getting ppm or jpg snapshots, mjpeg video Private API: diff -Nru a/MAINTAINERS b/MAINTAINERS --- a/MAINTAINERS Fri Nov 22 13:41:21 2002 +++ b/MAINTAINERS Fri Nov 22 13:41:21 2002 @@ -204,6 +204,14 @@ L: linux-scsi@vger.kernel.org S: Maintained +ALPHA PORT +P: Richard Henderson +M: rth@twiddle.net +S: Odd Fixes for 2.4; Maintained for 2.5. +P: Ivan Kokshaysky +M: ink@jurassic.park.msu.ru +S: Maintained for 2.4; PCI support for 2.5. + APM DRIVER P: Stephen Rothwell M: sfr@canb.auug.org.au @@ -411,6 +419,15 @@ M: bjornw@axis.com L: dev-etrax@axis.com W: http://developer.axis.com +S: Maintained + +CRYPTO API +P: James Morris +M: jmorris@intercode.com.au +P: David S. Miller +M: davem@redhat.com +W http://samba.org/~jamesm/crypto/ +L: linux-kernel@vger.kernel.org S: Maintained CYBERPRO FB DRIVER diff -Nru a/Makefile b/Makefile --- a/Makefile Fri Nov 22 13:41:18 2002 +++ b/Makefile Fri Nov 22 13:41:18 2002 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 5 -SUBLEVEL = 48 +SUBLEVEL = 49 EXTRAVERSION = # *DOCUMENTATION* @@ -157,7 +157,7 @@ OBJDUMP = $(CROSS_COMPILE)objdump AWK = awk GENKSYMS = /sbin/genksyms -KALLSYMS = /sbin/kallsyms +KALLSYMS = scripts/kallsyms PERL = perl MODFLAGS = -DMODULE CFLAGS_MODULE = $(MODFLAGS) @@ -299,6 +299,8 @@ endef # set -e makes the rule exit immediately on error +# Final awk script makes sure per-cpu vars are in per-cpu section, as +# old gcc (eg egcs 2.92.11) ignores section attribute if uninitialized. define rule_vmlinux__ set -e @@ -312,11 +314,22 @@ echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd endef -define rule_vmlinux +define rule_vmlinux_no_percpu $(rule_vmlinux__) $(NM) $@ | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map endef +ifdef CONFIG_SMP +define rule_vmlinux + $(rule_vmlinux_no_percpu) + $(AWK) -f scripts/per-cpu-check.awk < System.map +endef +else +define rule_vmlinux + $(rule_vmlinux_no_percpu) +endef +endif + LDFLAGS_vmlinux += -T arch/$(ARCH)/vmlinux.lds.s # Generate section listing all symbols and add it into vmlinux @@ -335,7 +348,7 @@ kallsyms.o := .tmp_kallsyms2.o quiet_cmd_kallsyms = KSYM $@ -cmd_kallsyms = $(KALLSYMS) $< > $@ +cmd_kallsyms = sh $(KALLSYMS) $< $@ .tmp_kallsyms1.o: .tmp_vmlinux1 $(call cmd,kallsyms) diff -Nru a/arch/alpha/Kconfig b/arch/alpha/Kconfig --- a/arch/alpha/Kconfig Fri Nov 22 13:41:22 2002 +++ b/arch/alpha/Kconfig Fri Nov 22 13:41:22 2002 @@ -806,6 +806,8 @@ source "drivers/message/fusion/Kconfig" endif +source "drivers/ieee1394/Kconfig" + source "net/Kconfig" diff -Nru a/arch/alpha/defconfig b/arch/alpha/defconfig --- a/arch/alpha/defconfig Fri Nov 22 13:41:20 2002 +++ b/arch/alpha/defconfig Fri Nov 22 13:41:20 2002 @@ -2,9 +2,10 @@ # Automatically generated make config: don't edit # CONFIG_ALPHA=y -# CONFIG_UID16 is not set -# CONFIG_RWSEM_GENERIC_SPINLOCK is not set +CONFIG_MMU=y +CONFIG_SWAP=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_ISA_DMA=y # # Code maturity level options @@ -23,21 +24,22 @@ # Loadable module support # CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_KMOD=y # -# General setup +# System setup # CONFIG_ALPHA_GENERIC=y # CONFIG_ALPHA_ALCOR is not set # CONFIG_ALPHA_XL is not set # CONFIG_ALPHA_BOOK1 is not set -# CONFIG_ALPHA_AVANTI is not set +# CONFIG_ALPHA_AVANTI_CH is not set # CONFIG_ALPHA_CABRIOLET is not set # CONFIG_ALPHA_DP264 is not set # CONFIG_ALPHA_EB164 is not set -# CONFIG_ALPHA_EB64P is not set +# CONFIG_ALPHA_EB64P_CH is not set # CONFIG_ALPHA_EB66 is not set # CONFIG_ALPHA_EB66P is not set # CONFIG_ALPHA_EIGER is not set @@ -46,7 +48,7 @@ # CONFIG_ALPHA_MIATA is not set # CONFIG_ALPHA_MIKASA is not set # CONFIG_ALPHA_NAUTILUS is not set -# CONFIG_ALPHA_NONAME is not set +# CONFIG_ALPHA_NONAME_CH is not set # CONFIG_ALPHA_NORITAKE is not set # CONFIG_ALPHA_PC164 is not set # CONFIG_ALPHA_P2K is not set @@ -59,21 +61,18 @@ # CONFIG_ALPHA_TAKARA is not set # CONFIG_ALPHA_TITAN is not set # CONFIG_ALPHA_WILDFIRE is not set -CONFIG_VERBOSE_MCHECK=y CONFIG_ISA=y CONFIG_EISA=y -# CONFIG_SBUS is not set -# CONFIG_MCA is not set CONFIG_PCI=y CONFIG_ALPHA_BROKEN_IRQ_MASK=y # CONFIG_SMP is not set # CONFIG_DISCONTIGMEM is not set -# CONFIG_ALPHA_LARGE_VMALLOC is not set +CONFIG_VERBOSE_MCHECK=y CONFIG_PCI_NAMES=y # CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set CONFIG_KCORE_ELF=y # CONFIG_KCORE_AOUT is not set +CONFIG_SRM_ENV=m # CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set @@ -93,6 +92,12 @@ # Plug and Play configuration # CONFIG_PNP=y +# CONFIG_PNP_NAMES is not set +# CONFIG_PNP_DEBUG is not set + +# +# Protocols +# CONFIG_ISAPNP=y # CONFIG_PNPBIOS is not set @@ -101,113 +106,21 @@ # CONFIG_BLK_DEV_FD=y # CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_CISS_SCSI_TAPE is not set # CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set CONFIG_BLK_DEV_LOOP=m # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set # # Multi-device support (RAID and LVM) # # CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_MD_MULTIPATH is not set -# CONFIG_BLK_DEV_LVM is not set - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_NETLINK_DEV=y -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -# CONFIG_FILTER is not set -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -CONFIG_INET_ECN=y -# CONFIG_SYN_COOKIES is not set # -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_IRC=m -CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=m -# CONFIG_IP_NF_MATCH_LIMIT is not set -# CONFIG_IP_NF_MATCH_MAC is not set -# CONFIG_IP_NF_MATCH_MARK is not set -# CONFIG_IP_NF_MATCH_MULTIPORT is not set -# CONFIG_IP_NF_MATCH_TOS is not set -# CONFIG_IP_NF_MATCH_AH_ESP is not set -# CONFIG_IP_NF_MATCH_LENGTH is not set -# CONFIG_IP_NF_MATCH_TTL is not set -# CONFIG_IP_NF_MATCH_TCPMSS is not set -# CONFIG_IP_NF_MATCH_STATE is not set -# CONFIG_IP_NF_MATCH_UNCLEAN is not set -# CONFIG_IP_NF_MATCH_OWNER is not set -CONFIG_IP_NF_FILTER=m -# CONFIG_IP_NF_TARGET_REJECT is not set -# CONFIG_IP_NF_TARGET_MIRROR is not set -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -# CONFIG_IP_NF_TARGET_REDIRECT is not set -# CONFIG_IP_NF_NAT_SNMP_BASIC is not set -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -# CONFIG_IP_NF_MANGLE is not set -# CONFIG_IP_NF_TARGET_LOG is not set -# CONFIG_IP_NF_TARGET_ULOG is not set -# CONFIG_IP_NF_TARGET_TCPMSS is not set -CONFIG_IP_NF_COMPAT_IPCHAINS=y -CONFIG_IP_NF_NAT_NEEDED=y -# CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set -CONFIG_VLAN_8021Q=m - -# -# -# -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# ATA/IDE/MFM/RLL support +# ATA/ATAPI/MFM/RLL support # CONFIG_IDE=y @@ -219,59 +132,55 @@ # # Please see Documentation/ide.txt for help/info on IDE drives # -# CONFIG_BLK_DEV_HD_IDE is not set # CONFIG_BLK_DEV_HD is not set CONFIG_BLK_DEV_IDEDISK=y CONFIG_IDEDISK_MULTI_MODE=y # CONFIG_IDEDISK_STROKE is not set -# CONFIG_BLK_DEV_IDECS is not set CONFIG_BLK_DEV_IDECD=y -# CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set # # IDE chipset support/bugfixes # -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set # CONFIG_BLK_DEV_ISAPNP is not set -# CONFIG_BLK_DEV_RZ1000 is not set +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_BLK_DEV_GENERIC=y # CONFIG_IDEPCI_SHARE_IRQ is not set CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDE_TCQ is not set # CONFIG_BLK_DEV_OFFBOARD is not set +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_IDEDMA_ONLYDISK is not set CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set +# CONFIG_IDEDMA_PCI_WIP is not set +CONFIG_BLK_DEV_ADMA=y # CONFIG_BLK_DEV_AEC62XX is not set -# CONFIG_AEC62XX_TUNING is not set CONFIG_BLK_DEV_ALI15X3=y # CONFIG_WDC_ALI15X3 is not set # CONFIG_BLK_DEV_AMD74XX is not set -# CONFIG_AMD74XX_OVERRIDE is not set CONFIG_BLK_DEV_CMD64X=y CONFIG_BLK_DEV_CY82C693=y # CONFIG_BLK_DEV_CS5530 is not set # CONFIG_BLK_DEV_HPT34X is not set -# CONFIG_HPT34X_AUTODMA is not set # CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_NFORCE is not set # CONFIG_BLK_DEV_NS87415 is not set # CONFIG_BLK_DEV_OPTI621 is not set -# CONFIG_BLK_DEV_PDC202XX is not set -# CONFIG_PDC202XX_BURST is not set -# CONFIG_PDC202XX_FORCE is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set # CONFIG_BLK_DEV_SVWKS is not set -# CONFIG_BLK_DEV_SIS5513 is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set # CONFIG_IDE_CHIPSETS is not set CONFIG_IDEDMA_AUTO=y # CONFIG_IDEDMA_IVB is not set CONFIG_BLK_DEV_IDE_MODES=y -# CONFIG_BLK_DEV_ATARAID is not set -# CONFIG_BLK_DEV_ATARAID_PDC is not set -# CONFIG_BLK_DEV_ATARAID_HPT is not set # # SCSI support @@ -282,18 +191,17 @@ # SCSI support type (disk, tape, CD-ROM) # CONFIG_BLK_DEV_SD=y -CONFIG_SD_EXTRA_DEVS=40 # CONFIG_CHR_DEV_ST is not set # CONFIG_CHR_DEV_OSST is not set CONFIG_BLK_DEV_SR=y CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_SR_EXTRA_DEVS=2 # CONFIG_CHR_DEV_SG is not set # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # # CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_REPORT_LUNS is not set # CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set @@ -306,10 +214,12 @@ # CONFIG_SCSI_AHA152X is not set # CONFIG_SCSI_AHA1542 is not set # CONFIG_SCSI_AHA1740 is not set -CONFIG_SCSI_AIC7XXX=y +# CONFIG_SCSI_AACRAID is not set +CONFIG_SCSI_AIC7XXX=m CONFIG_AIC7XXX_CMDS_PER_DEVICE=253 CONFIG_AIC7XXX_RESET_DELAY_MS=5000 # CONFIG_AIC7XXX_BUILD_FIRMWARE is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set @@ -325,6 +235,7 @@ # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_NCR53C406A is not set @@ -352,16 +263,115 @@ # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_T128 is not set # CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_NSP32 is not set # CONFIG_SCSI_DEBUG is not set # # Fusion MPT device support # # CONFIG_FUSION is not set -# CONFIG_FUSION_BOOT is not set -# CONFIG_FUSION_ISENSE is not set -# CONFIG_FUSION_CTL is not set -# CONFIG_FUSION_LAN is not set + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_INET_ECN=y +# CONFIG_SYN_COOKIES is not set +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_XFRM_USER=m + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +# CONFIG_IP_NF_MATCH_LIMIT is not set +# CONFIG_IP_NF_MATCH_MAC is not set +# CONFIG_IP_NF_MATCH_PKTTYPE is not set +# CONFIG_IP_NF_MATCH_MARK is not set +# CONFIG_IP_NF_MATCH_MULTIPORT is not set +# CONFIG_IP_NF_MATCH_TOS is not set +# CONFIG_IP_NF_MATCH_ECN is not set +# CONFIG_IP_NF_MATCH_DSCP is not set +# CONFIG_IP_NF_MATCH_AH_ESP is not set +# CONFIG_IP_NF_MATCH_LENGTH is not set +# CONFIG_IP_NF_MATCH_TTL is not set +# CONFIG_IP_NF_MATCH_TCPMSS is not set +# CONFIG_IP_NF_MATCH_HELPER is not set +# CONFIG_IP_NF_MATCH_STATE is not set +# CONFIG_IP_NF_MATCH_CONNTRACK is not set +# CONFIG_IP_NF_MATCH_UNCLEAN is not set +# CONFIG_IP_NF_MATCH_OWNER is not set +CONFIG_IP_NF_FILTER=m +# CONFIG_IP_NF_TARGET_REJECT is not set +# CONFIG_IP_NF_TARGET_MIRROR is not set +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +# CONFIG_IP_NF_TARGET_REDIRECT is not set +# CONFIG_IP_NF_NAT_LOCAL is not set +# CONFIG_IP_NF_NAT_SNMP_BASIC is not set +CONFIG_IP_NF_NAT_IRC=m +CONFIG_IP_NF_NAT_FTP=m +# CONFIG_IP_NF_MANGLE is not set +# CONFIG_IP_NF_TARGET_LOG is not set +# CONFIG_IP_NF_TARGET_ULOG is not set +# CONFIG_IP_NF_TARGET_TCPMSS is not set +# CONFIG_IP_NF_ARPTABLES is not set +CONFIG_IP_NF_COMPAT_IPCHAINS=y +# CONFIG_IPV6 is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +CONFIG_VLAN_8021Q=m +# CONFIG_LLC is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set # # Network device support @@ -383,10 +393,7 @@ # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -# CONFIG_SUNLANCE is not set # CONFIG_HAPPYMEAL is not set -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set # CONFIG_SUNGEM is not set CONFIG_NET_VENDOR_3COM=y # CONFIG_EL1 is not set @@ -395,12 +402,22 @@ # CONFIG_EL16 is not set # CONFIG_EL3 is not set # CONFIG_3C515 is not set -# CONFIG_ELMC is not set -# CONFIG_ELMC_II is not set CONFIG_VORTEX=y # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set + +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +CONFIG_DE2104X=m +CONFIG_TULIP=y +# CONFIG_TULIP_MWI is not set +CONFIG_TULIP_MMIO=y +# CONFIG_DE4X5 is not set +# CONFIG_WINBOND_840 is not set +# CONFIG_DM9102 is not set # CONFIG_AT1700 is not set # CONFIG_DEPCA is not set # CONFIG_HP100 is not set @@ -410,15 +427,11 @@ # CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_AC3200 is not set # CONFIG_APRICOT is not set +# CONFIG_B44 is not set # CONFIG_CS89x0 is not set -CONFIG_DE2104X=m -CONFIG_TULIP=y -# CONFIG_TULIP_MWI is not set -CONFIG_TULIP_MMIO=y -# CONFIG_DE4X5 is not set # CONFIG_DGRS is not set -# CONFIG_DM9102 is not set # CONFIG_EEPRO100 is not set +# CONFIG_E100 is not set # CONFIG_LNE390 is not set # CONFIG_FEALNX is not set # CONFIG_NATSEMI is not set @@ -427,17 +440,11 @@ # CONFIG_ES3210 is not set # CONFIG_8139CP is not set # CONFIG_8139TOO is not set -# CONFIG_8139TOO_PIO is not set -# CONFIG_8139TOO_TUNE_TWISTER is not set -# CONFIG_8139TOO_8129 is not set -# CONFIG_8139_NEW_RX_RESET is not set # CONFIG_SIS900 is not set # CONFIG_EPIC100 is not set # CONFIG_SUNDANCE is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set -# CONFIG_VIA_RHINE_MMIO is not set -# CONFIG_WINBOND_840 is not set # CONFIG_NET_POCKET is not set # @@ -445,14 +452,14 @@ # # CONFIG_ACENIC is not set CONFIG_DL2K=m -# CONFIG_MYRI_SBUS is not set +# CONFIG_E1000 is not set CONFIG_NS83820=m # CONFIG_HAMACHI is not set CONFIG_YELLOWFIN=y # CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set -# CONFIG_PLIP is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -482,7 +489,7 @@ # # ISDN subsystem # -# CONFIG_ISDN is not set +# CONFIG_ISDN_BOOL is not set # # Old CD-ROM drivers (not SCSI, not IDE) @@ -490,14 +497,43 @@ # CONFIG_CD_NO_IDESCSI is not set # +# Input device support +# +# CONFIG_INPUT is not set + +# +# Userland interfaces +# + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +# CONFIG_SERIO is not set + +# +# Input Device Drivers +# + +# # Character devices # CONFIG_VT=y CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -# CONFIG_SERIAL_CONSOLE is not set -# CONFIG_SERIAL_EXTENDED is not set +CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=m +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=m CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 @@ -510,17 +546,12 @@ # Mice # # CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=y -CONFIG_PSMOUSE=y -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set # CONFIG_QIC02_TAPE is not set # # Watchdog Cards # # CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set # CONFIG_NVRAM is not set CONFIG_RTC=y # CONFIG_DTLK is not set @@ -533,6 +564,7 @@ # CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set # # Multimedia devices @@ -549,46 +581,38 @@ # CONFIG_REISERFS_CHECK is not set # CONFIG_REISERFS_PROC_INFO is not set # CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EXT3_FS is not set # CONFIG_JBD is not set -# CONFIG_JBD_DEBUG is not set CONFIG_FAT_FS=y CONFIG_MSDOS_FS=y -# CONFIG_UMSDOS_FS is not set CONFIG_VFAT_FS=y # CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set CONFIG_TMPFS=y CONFIG_RAMFS=y CONFIG_ISO9660_FS=y # CONFIG_JOLIET is not set # CONFIG_ZISOFS is not set +# CONFIG_JFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_VXFS_FS is not set # CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y # CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set # CONFIG_SYSV_FS is not set # CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set +# CONFIG_XFS_FS is not set # # Network File Systems @@ -597,23 +621,19 @@ # CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=m CONFIG_NFS_V3=y -# CONFIG_ROOT_NFS is not set +# CONFIG_NFS_V4 is not set CONFIG_NFSD=m CONFIG_NFSD_V3=y +# CONFIG_NFSD_V4 is not set +# CONFIG_NFSD_TCP is not set CONFIG_SUNRPC=m CONFIG_LOCKD=m CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +# CONFIG_CIFS is not set # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set -# CONFIG_ZISOFS_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types @@ -621,7 +641,6 @@ # CONFIG_PARTITION_ADVANCED is not set CONFIG_OSF_PARTITION=y CONFIG_MSDOS_PARTITION=y -# CONFIG_SMB_NLS is not set CONFIG_NLS=y # @@ -649,6 +668,7 @@ # CONFIG_NLS_CODEPAGE_949 is not set # CONFIG_NLS_CODEPAGE_874 is not set # CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set # CONFIG_NLS_CODEPAGE_1251 is not set # CONFIG_NLS_ISO8859_1 is not set # CONFIG_NLS_ISO8859_2 is not set @@ -686,127 +706,6 @@ # CONFIG_USB is not set # -# USB Host Controller Drivers -# -# CONFIG_USB_EHCI_HCD is not set -# CONFIG_USB_OHCI_HCD is not set -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -# CONFIG_USB_OHCI is not set - -# -# USB Device Class drivers -# -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_BLUETOOTH is not set -# CONFIG_USB_STORAGE is not set -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_HP8200e is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set - -# -# USB Human Interface Devices (HID) -# - -# -# Input core support is needed for USB HID -# - -# -# USB Imaging devices -# -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set - -# -# USB Multimedia devices -# - -# -# Video4Linux support is needed for USB Multimedia device support -# - -# -# USB Network adaptors -# -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_CATC is not set -# CONFIG_USB_CDCETHER is not set -# CONFIG_USB_USBNET is not set - -# -# USB port drivers -# -# CONFIG_USB_USS720 is not set - -# -# USB Serial Converter support -# -# CONFIG_USB_SERIAL is not set -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_IPAQ is not set -# CONFIG_USB_SERIAL_IR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_KLSI is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_XIRCOM is not set -# CONFIG_USB_SERIAL_OMNINET is not set - -# -# USB Miscellaneous drivers -# -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_AUERSWALD is not set - -# -# Input device support -# -# CONFIG_INPUT is not set -# CONFIG_INPUT_KEYBDEV is not set -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -# CONFIG_GAMEPORT_NS558 is not set -# CONFIG_GAMEPORT_L4 is not set -# CONFIG_INPUT_EMU10K1 is not set -# CONFIG_GAMEPORT_PCIGAME is not set -# CONFIG_GAMEPORT_FM801 is not set -# CONFIG_GAMEPORT_CS461x is not set -# CONFIG_SERIO is not set -# CONFIG_SERIO_SERPORT is not set - -# # Bluetooth support # # CONFIG_BT is not set @@ -824,8 +723,16 @@ # CONFIG_DEBUG_SEMAPHORE is not set # +# Security options +# +CONFIG_SECURITY_CAPABILITIES=y + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# # Library routines # CONFIG_CRC32=y -# CONFIG_ZLIB_INFLATE is not set -# CONFIG_ZLIB_DEFLATE is not set diff -Nru a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile --- a/arch/alpha/kernel/Makefile Fri Nov 22 13:41:19 2002 +++ b/arch/alpha/kernel/Makefile Fri Nov 22 13:41:19 2002 @@ -34,7 +34,7 @@ sys_alcor.o sys_cabriolet.o sys_dp264.o sys_eb64p.o sys_eiger.o \ sys_jensen.o sys_miata.o sys_mikasa.o sys_nautilus.o sys_titan.o \ sys_noritake.o sys_rawhide.o sys_ruffian.o sys_rx164.o \ - sys_sable.o sys_sio.o sys_sx164.o sys_takara.o sys_rx164.o \ + sys_sable.o sys_sio.o sys_sx164.o sys_takara.o \ sys_wildfire.o core_wildfire.o irq_pyxis.o else diff -Nru a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S --- a/arch/alpha/kernel/entry.S Fri Nov 22 13:41:17 2002 +++ b/arch/alpha/kernel/entry.S Fri Nov 22 13:41:17 2002 @@ -688,12 +688,13 @@ .ent sys_fork sys_fork: .prologue 0 - mov $sp, $19 + mov $sp, $21 bsr $1, do_switch_stack - /* A fork is the same as clone(SIGCHLD, 0); */ bis $31, SIGCHLD, $16 mov $31, $17 mov $31, $18 + mov $31, $19 + mov $31, $20 jsr $26, alpha_clone bsr $1, undo_switch_stack ret @@ -704,10 +705,9 @@ .ent sys_clone sys_clone: .prologue 0 - mov $sp, $19 + mov $sp, $21 bsr $1, do_switch_stack - /* $16, $17, $18, $19 come from the user; $19 is used later - via pt_regs->r19. */ + /* $16, $17, $18, $19, $20 come from the user. */ jsr $26, alpha_clone bsr $1, undo_switch_stack ret @@ -718,8 +718,8 @@ .ent sys_vfork sys_vfork: .prologue 0 - bsr $1, do_switch_stack mov $sp, $16 + bsr $1, do_switch_stack jsr $26, alpha_vfork bsr $1, undo_switch_stack ret @@ -886,15 +886,6 @@ 1: lda $sp, 16($sp) ret .end sys_pipe - - .align 4 - .globl alpha_create_module - .ent alpha_create_module -alpha_create_module: - .prologue 0 - mov $sp, $18 - jmp $31, do_alpha_create_module -.end alpha_create_module .align 4 .globl sys_ptrace diff -Nru a/arch/alpha/kernel/err_common.c b/arch/alpha/kernel/err_common.c --- a/arch/alpha/kernel/err_common.c Fri Nov 22 13:41:18 2002 +++ b/arch/alpha/kernel/err_common.c Fri Nov 22 13:41:18 2002 @@ -34,12 +34,12 @@ * Generic */ void -mchk_dump_mem(void *data, int length, char **annotation) +mchk_dump_mem(void *data, size_t length, char **annotation) { unsigned long *ldata = data; - int i; + size_t i; - for(i = 0; (i * sizeof(*ldata)) < length; i++) { + for (i = 0; (i * sizeof(*ldata)) < length; i++) { if (annotation && !annotation[i]) annotation = NULL; printk("%s %08x: %016lx %s\n", @@ -624,7 +624,7 @@ subpacket = (struct el_subpacket *) ((unsigned long)header + header->length); - for(i = 0; subpacket && i < packet_count; i++) { + for (i = 0; subpacket && i < packet_count; i++) { printk("%sPROCESSING SUBPACKET %d\n", err_print_prefix, i); subpacket = el_process_subpacket(subpacket); } @@ -636,7 +636,7 @@ struct el_subpacket *next = NULL; struct el_subpacket_handler *h = subpacket_handler_list; - for(; h && h->class != header->class; h = h->next); + for (; h && h->class != header->class; h = h->next); if (h) next = h->handler(header); return next; @@ -673,7 +673,7 @@ struct el_subpacket_annotation *a; char **annotation = NULL; - for(a = subpacket_annotation_list; a; a = a->next) { + for (a = subpacket_annotation_list; a; a = a->next) { if (a->class == header->class && a->type == header->type && a->revision == header->revision) { @@ -700,7 +700,7 @@ "*** Error(s) were logged on a previous boot\n", err_print_prefix, cpu); - for(err = 0; header && (header->class != EL_CLASS__TERMINATION); err++) + for (err = 0; header && (header->class != EL_CLASS__TERMINATION); err++) header = el_process_subpacket(header); /* let the console know it's ok to clear the error(s) at restart */ @@ -715,9 +715,9 @@ cdl_check_console_data_log(void) { struct percpu_struct *pcpu; - int cpu; + unsigned long cpu; - for(cpu = 0; cpu < hwrpb->nr_processors; cpu++) { + for (cpu = 0; cpu < hwrpb->nr_processors; cpu++) { pcpu = (struct percpu_struct *) ((unsigned long)hwrpb + hwrpb->processor_offset + cpu * hwrpb->processor_size); @@ -734,7 +734,7 @@ if (a == NULL) subpacket_annotation_list = new; else { - for(; a->next != NULL; a = a->next) { + for (; a->next != NULL; a = a->next) { if ((a->class == new->class && a->type == new->type) || a == new) { printk("Attempted to re-register " @@ -756,7 +756,7 @@ if (h == NULL) subpacket_handler_list = new; else { - for(; h->next != NULL; h = h->next) { + for (; h->next != NULL; h = h->next) { if (h->class == new->class || h == new) { printk("Attempted to re-register " "subpacket handler\n"); diff -Nru a/arch/alpha/kernel/err_impl.h b/arch/alpha/kernel/err_impl.h --- a/arch/alpha/kernel/err_impl.h Fri Nov 22 13:41:19 2002 +++ b/arch/alpha/kernel/err_impl.h Fri Nov 22 13:41:19 2002 @@ -133,7 +133,7 @@ */ extern char *err_print_prefix; -extern void mchk_dump_mem(void *, int, char **); +extern void mchk_dump_mem(void *, size_t, char **); extern void mchk_dump_logout_frame(struct el_common *); extern void ev7_register_error_handlers(void); extern void ev7_machine_check(u64, u64, struct pt_regs *); diff -Nru a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c --- a/arch/alpha/kernel/irq.c Fri Nov 22 13:41:22 2002 +++ b/arch/alpha/kernel/irq.c Fri Nov 22 13:41:22 2002 @@ -252,7 +252,7 @@ { unsigned char hexnum [HEX_DIGITS]; unsigned long value; - int i; + unsigned long i; if (!count) return -EINVAL; diff -Nru a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c --- a/arch/alpha/kernel/osf_sys.c Fri Nov 22 13:41:17 2002 +++ b/arch/alpha/kernel/osf_sys.c Fri Nov 22 13:41:17 2002 @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -45,7 +46,6 @@ extern int do_pipe(int *); extern asmlinkage unsigned long sys_brk(unsigned long); -extern asmlinkage unsigned long sys_create_module(char *, unsigned long); /* * Brk needs to return an error. Still support Linux's brk(0) query idiom, @@ -103,7 +103,7 @@ struct osf_dirent_callback { struct osf_dirent *dirent; long *basep; - int count; + unsigned int count; int error; }; @@ -113,7 +113,7 @@ { struct osf_dirent *dirent; struct osf_dirent_callback *buf = (struct osf_dirent_callback *) __buf; - int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1); + unsigned int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1); buf->error = -EINVAL; /* only used if we fail */ if (reclen > buf->count) @@ -418,18 +418,6 @@ return error; } -asmlinkage int -osf_swapon(const char *path, int flags, int lowat, int hiwat) -{ - int ret; - - /* for now, simply ignore lowat and hiwat... */ - lock_kernel(); - ret = sys_swapon(path, flags); - unlock_kernel(); - return ret; -} - asmlinkage unsigned long sys_getpagesize(void) { @@ -641,33 +629,6 @@ return error; } -/* - * The Linux kernel isn't good at returning values that look - * like negative longs (they are mistaken as error values). - * Until that is fixed, we need this little workaround for - * create_module() because it's one of the few system calls - * that return kernel addresses (which are negative). - */ - -asmlinkage unsigned long -do_alpha_create_module(char *module_name, unsigned long size, - struct pt_regs *regs) -{ - long retval; - - lock_kernel(); - retval = sys_create_module(module_name, size); - - /* We get either a module address or an error number, and we know - the error number is a small negative number, while the address - is always negative but much larger. */ - if (retval + 1000 < 0) - regs->r0 = 0; - - unlock_kernel(); - return retval; -} - asmlinkage long osf_sysinfo(int command, char *buf, long count) { @@ -1343,14 +1304,14 @@ if (addr) { addr = arch_get_unmapped_area_1 (PAGE_ALIGN(addr), len, limit); - if (addr != -ENOMEM) + if (addr != (unsigned long) -ENOMEM) return addr; } /* Next, try allocating at TASK_UNMAPPED_BASE. */ addr = arch_get_unmapped_area_1 (PAGE_ALIGN(TASK_UNMAPPED_BASE), len, limit); - if (addr != -ENOMEM) + if (addr != (unsigned long) -ENOMEM) return addr; /* Finally, try allocating in low memory. */ diff -Nru a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c --- a/arch/alpha/kernel/pci.c Fri Nov 22 13:41:18 2002 +++ b/arch/alpha/kernel/pci.c Fri Nov 22 13:41:18 2002 @@ -304,7 +304,7 @@ == (PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64)) { pci_write_config_dword(dev, where+4, 0); - printk(KERN_WARNING "PCI: dev %s type 64-bit\n", dev->name); + printk(KERN_WARNING "PCI: dev %s type 64-bit\n", dev->dev.name); } /* ??? FIXME -- record old value for shutdown. */ @@ -474,5 +474,5 @@ pci_controller_num(struct pci_dev *pdev) { struct pci_controller *hose = pdev->sysdata; - return (hose ? hose->index : -ENXIO); + return (hose ? (int) hose->index : -ENXIO); } diff -Nru a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c --- a/arch/alpha/kernel/process.c Fri Nov 22 13:41:23 2002 +++ b/arch/alpha/kernel/process.c Fri Nov 22 13:41:23 2002 @@ -235,24 +235,25 @@ * with parameters (SIGCHLD, 0). */ int -alpha_clone(unsigned long clone_flags, unsigned long usp, int *user_tid, - struct pt_regs *regs) +alpha_clone(unsigned long clone_flags, unsigned long usp, int *parent_tid, + int *child_tid, unsigned long tls_value, struct pt_regs *regs) { struct task_struct *p; if (!usp) usp = rdusp(); - p = do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0, user_tid); + p = do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0, + parent_tid, child_tid); return IS_ERR(p) ? PTR_ERR(p) : p->pid; } int -alpha_vfork(struct switch_stack * swstack) +alpha_vfork(struct pt_regs *regs) { struct task_struct *p; p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), - (struct pt_regs *) (swstack+1), 0, NULL); + regs, 0, NULL, NULL); return IS_ERR(p) ? PTR_ERR(p) : p->pid; } @@ -306,7 +307,7 @@ required for proper operation in the case of a threaded application calling fork. */ if (clone_flags & CLONE_SETTLS) - childti->pcb.unique = regs->r19; + childti->pcb.unique = regs->r20; return 0; } diff -Nru a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c --- a/arch/alpha/kernel/setup.c Fri Nov 22 13:41:18 2002 +++ b/arch/alpha/kernel/setup.c Fri Nov 22 13:41:18 2002 @@ -98,9 +98,11 @@ #define N(a) (sizeof(a)/sizeof(a[0])) -static struct alpha_machine_vector *get_sysvec(long, long, long); +static struct alpha_machine_vector *get_sysvec(unsigned long, unsigned long, + unsigned long); static struct alpha_machine_vector *get_sysvec_byname(const char *); -static void get_sysnames(long, long, long, char **, char **); +static void get_sysnames(unsigned long, unsigned long, unsigned long, + char **, char **); static char command_line[COMMAND_LINE_SIZE]; char saved_command_line[COMMAND_LINE_SIZE]; @@ -202,7 +204,7 @@ }; struct resource *io = &ioport_resource; - long i; + size_t i; if (hose_head) { struct pci_controller *hose; @@ -249,6 +251,27 @@ return end >> PAGE_SHIFT; /* Return the PFN of the limit. */ } +#ifdef CONFIG_BLK_DEV_INITRD +void * __init +move_initrd(unsigned long mem_limit) +{ + void *start; + unsigned long size; + + size = initrd_end - initrd_start; + start = __alloc_bootmem(size, PAGE_SIZE, 0); + if (!start || __pa(start) + size > mem_limit) { + initrd_start = initrd_end = 0; + return NULL; + } + memmove(start, (void *)initrd_start, size); + initrd_start = (unsigned long)start; + initrd_end = initrd_start + size; + printk("initrd moved to %p\n", start); + return start; +} +#endif + #ifndef CONFIG_DISCONTIGMEM static void __init setup_memory(void *kernel_end) @@ -258,7 +281,7 @@ unsigned long start_kernel_pfn, end_kernel_pfn; unsigned long bootmap_size, bootmap_pages, bootmap_start; unsigned long start, end; - int i; + unsigned long i; /* Find free clusters, and init and free the bootmem accordingly. */ memdesc = (struct memdesc_struct *) @@ -327,7 +350,7 @@ } } - if (bootmap_start == -1) { + if (bootmap_start == ~0UL) { max_low_pfn >>= 1; goto try_again; } @@ -377,11 +400,11 @@ (void *) initrd_start, INITRD_SIZE); if ((void *)initrd_end > phys_to_virt(PFN_PHYS(max_low_pfn))) { - printk("initrd extends beyond end of memory " - "(0x%08lx > 0x%p)\ndisabling initrd\n", - initrd_end, - phys_to_virt(PFN_PHYS(max_low_pfn))); - initrd_start = initrd_end = 0; + if (!move_initrd(PFN_PHYS(max_low_pfn))) + printk("initrd extends beyond end of memory " + "(0x%08lx > 0x%p)\ndisabling initrd\n", + initrd_end, + phys_to_virt(PFN_PHYS(max_low_pfn))); } else { reserve_bootmem(virt_to_phys((void *)initrd_start), INITRD_SIZE); @@ -398,7 +421,7 @@ { struct memclust_struct * cluster; struct memdesc_struct * memdesc; - int i; + unsigned long i; memdesc = (struct memdesc_struct *) (hwrpb->mddt_offset + (unsigned long) hwrpb); @@ -691,7 +714,7 @@ static int tsunami_indices[] = {0,1,2,3,4,5,6,7,8,9,10,11,12}; static struct alpha_machine_vector * __init -get_sysvec(long type, long variation, long cpu) +get_sysvec(unsigned long type, unsigned long variation, unsigned long cpu) { static struct alpha_machine_vector *systype_vecs[] __initdata = { @@ -798,10 +821,6 @@ struct alpha_machine_vector *vec; - /* Restore real CABRIO and EB66+ family names, ie EB64+ and EB66 */ - if (type < 0) - type = -type; - /* Search the system tables first... */ vec = NULL; if (type < N(systype_vecs)) { @@ -818,7 +837,7 @@ if (!vec) { /* Member ID is a bit-field. */ - long member = (variation >> 10) & 0x3f; + unsigned long member = (variation >> 10) & 0x3f; cpu &= 0xffffffff; /* make it usable */ @@ -917,8 +936,9 @@ &xlt_mv }; - int i, n = sizeof(all_vecs)/sizeof(*all_vecs); - for (i = 0; i < n; ++i) { + size_t i; + + for (i = 0; i < N(all_vecs); ++i) { struct alpha_machine_vector *mv = all_vecs[i]; if (strcasecmp(mv->vector_name, name) == 0) return mv; @@ -927,14 +947,10 @@ } static void -get_sysnames(long type, long variation, long cpu, +get_sysnames(unsigned long type, unsigned long variation, unsigned long cpu, char **type_name, char **variation_name) { - long member; - - /* Restore real CABRIO and EB66+ family names, ie EB64+ and EB66 */ - if (type < 0) - type = -type; + unsigned long member; /* If not in the tables, make it UNKNOWN, else set type name to family */ @@ -952,7 +968,7 @@ return; } - /* Set variation to "0"; if variation is zero, done */ + /* Set variation to "0"; if variation is zero, done. */ *variation_name = systype_names[0]; if (variation == 0) { return; @@ -1042,7 +1058,8 @@ get_nr_processors(struct percpu_struct *cpubase, unsigned long num) { struct percpu_struct *cpu; - int i, count = 0; + unsigned long i; + int count = 0; for (i = 0; i < num; i++) { cpu = (struct percpu_struct *) diff -Nru a/arch/alpha/kernel/smc37c669.c b/arch/alpha/kernel/smc37c669.c --- a/arch/alpha/kernel/smc37c669.c Fri Nov 22 13:41:21 2002 +++ b/arch/alpha/kernel/smc37c669.c Fri Nov 22 13:41:21 2002 @@ -970,8 +970,8 @@ static struct DEVICE_CONFIG { unsigned int port1; unsigned int port2; - unsigned int irq; - unsigned int drq; + int irq; + int drq; } local_config [NUM_FUNCS]; /* @@ -1097,11 +1097,11 @@ ); static int SMC37c669_xlate_irq( - unsigned int irq + int irq ); static int SMC37c669_xlate_drq( - unsigned int drq + int drq ); static spinlock_t smc_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED; @@ -2260,7 +2260,7 @@ ** **-- */ -static int __init SMC37c669_xlate_irq ( unsigned int irq ) +static int __init SMC37c669_xlate_irq ( int irq ) { int i, translated_irq = -1; @@ -2312,7 +2312,7 @@ ** **-- */ -static int __init SMC37c669_xlate_drq ( unsigned int drq ) +static int __init SMC37c669_xlate_drq ( int drq ) { int i, translated_drq = -1; diff -Nru a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c --- a/arch/alpha/kernel/smp.c Fri Nov 22 13:41:18 2002 +++ b/arch/alpha/kernel/smp.c Fri Nov 22 13:41:18 2002 @@ -499,7 +499,7 @@ setup_smp(void) { struct percpu_struct *cpubase, *cpu; - int i; + unsigned long i; if (boot_cpuid != 0) { printk(KERN_WARNING "SMP: Booting off cpu %d instead of 0?\n", @@ -516,7 +516,7 @@ ((char*)hwrpb + hwrpb->processor_offset); boot_cpu_palrev = cpubase->pal_revision; - for (i = 0; i < hwrpb->nr_processors; i++ ) { + for (i = 0; i < hwrpb->nr_processors; i++) { cpu = (struct percpu_struct *) ((char *)cpubase + i*hwrpb->processor_size); if ((cpu->flags & 0x1cc) == 0x1cc) { diff -Nru a/arch/alpha/kernel/srm_env.c b/arch/alpha/kernel/srm_env.c --- a/arch/alpha/kernel/srm_env.c Fri Nov 22 13:41:18 2002 +++ b/arch/alpha/kernel/srm_env.c Fri Nov 22 13:41:18 2002 @@ -162,8 +162,8 @@ res = (int) ret1; } + out: free_page((unsigned long)buf); - return res; } diff -Nru a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c --- a/arch/alpha/kernel/sys_nautilus.c Fri Nov 22 13:41:19 2002 +++ b/arch/alpha/kernel/sys_nautilus.c Fri Nov 22 13:41:19 2002 @@ -76,12 +76,14 @@ void nautilus_kill_arch(int mode) { + struct pci_bus *bus = pci_isa_hose->bus; + switch (mode) { case LINUX_REBOOT_CMD_RESTART: if (! alpha_using_srm) { u8 t8; - pcibios_read_config_byte(0, 0x38, 0x43, &t8); - pcibios_write_config_byte(0, 0x38, 0x43, t8 | 0x80); + pci_bus_read_config_byte(bus, 0x38, 0x43, &t8); + pci_bus_write_config_byte(bus, 0x38, 0x43, t8 | 0x80); outb(1, 0x92); outb(0, 0x92); /* NOTREACHED */ @@ -91,7 +93,7 @@ case LINUX_REBOOT_CMD_POWER_OFF: { u32 pmuport; - pcibios_read_config_dword(0, 0x88, 0x10, &pmuport); + pci_bus_read_config_dword(bus, 0x88, 0x10, &pmuport); pmuport &= 0xfffe; outl(0xffff, pmuport); /* clear pending events */ outw(0x2000, pmuport+4); /* power off */ diff -Nru a/arch/alpha/kernel/sys_sio.c b/arch/alpha/kernel/sys_sio.c --- a/arch/alpha/kernel/sys_sio.c Fri Nov 22 13:41:17 2002 +++ b/arch/alpha/kernel/sys_sio.c Fri Nov 22 13:41:17 2002 @@ -77,7 +77,7 @@ static void __init sio_pci_route(void) { - pcibios_write_config_dword(0, PCI_DEVFN(7, 0), 0x60, + pci_bus_write_config_dword(pci_isa_hose->bus, PCI_DEVFN(7, 0), 0x60, alpha_mv.sys.sio.route_tab); } diff -Nru a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S --- a/arch/alpha/kernel/systbls.S Fri Nov 22 13:41:21 2002 +++ b/arch/alpha/kernel/systbls.S Fri Nov 22 13:41:21 2002 @@ -216,7 +216,8 @@ .quad alpha_ni_syscall .quad alpha_ni_syscall .quad alpha_ni_syscall - .quad osf_swapon + /* The OSF swapon has two extra arguments, but we ignore them. */ + .quad sys_swapon .quad sys_msgctl /* 200 */ .quad sys_msgget .quad sys_msgrcv @@ -324,10 +325,10 @@ .quad sys_old_adjtimex .quad sys_swapoff .quad sys_getdents /* 305 */ - .quad alpha_create_module + .quad sys_ni_syscall /* 306: old create_module */ .quad sys_init_module .quad sys_delete_module - .quad sys_get_kernel_syms + .quad sys_ni_syscall /* 309: old get_kernel_syms */ .quad sys_syslog /* 310 */ .quad sys_reboot .quad sys_clone @@ -365,7 +366,7 @@ .quad sys_getresuid .quad sys_pciconfig_read /* 345 */ .quad sys_pciconfig_write - .quad sys_query_module + .quad sys_ni_syscall /* 347: old query_module */ .quad sys_prctl .quad sys_pread64 .quad sys_pwrite64 /* 350 */ @@ -423,7 +424,13 @@ .quad sys_io_cancel .quad sys_ni_syscall /* 403, sys_alloc_hugepages */ .quad sys_ni_syscall /* 404, sys_free_hugepages */ - .quad sys_exit_group + .quad sys_exit_group /* 405 */ + .quad sys_lookup_dcookie + .quad sys_epoll_create + .quad sys_epoll_ctl + .quad sys_epoll_wait + .quad sys_remap_file_pages /* 410 */ + .quad sys_set_tid_address .size sys_call_table, . - sys_call_table .type sys_call_table, @object diff -Nru a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c --- a/arch/alpha/kernel/time.c Fri Nov 22 13:41:20 2002 +++ b/arch/alpha/kernel/time.c Fri Nov 22 13:41:20 2002 @@ -316,7 +316,7 @@ diff = cycle_freq - est_cycle_freq; if (diff < 0) diff = -diff; - if (diff > one_percent) { + if ((unsigned long)diff > one_percent) { cycle_freq = est_cycle_freq; printk("HWRPB cycle frequency bogus. " "Estimated %lu Hz\n", cycle_freq); diff -Nru a/arch/alpha/lib/fpreg.c b/arch/alpha/lib/fpreg.c --- a/arch/alpha/lib/fpreg.c Fri Nov 22 13:41:21 2002 +++ b/arch/alpha/lib/fpreg.c Fri Nov 22 13:41:21 2002 @@ -48,6 +48,7 @@ case 29: STT(29, val); break; case 30: STT(30, val); break; case 31: STT(31, val); break; + default: return 0; } return val; } @@ -141,6 +142,7 @@ case 29: STS(29, val); break; case 30: STS(30, val); break; case 31: STS(31, val); break; + default: return 0; } return val; } diff -Nru a/arch/alpha/lib/io.c b/arch/alpha/lib/io.c --- a/arch/alpha/lib/io.c Fri Nov 22 13:41:22 2002 +++ b/arch/alpha/lib/io.c Fri Nov 22 13:41:22 2002 @@ -414,7 +414,7 @@ /* Optimize co-aligned transfers. Everything else gets handled a byte at a time. */ - if (count >= 8 && ((long)to & 7) == (from & 7)) { + if (count >= 8 && ((unsigned long)to & 7) == (from & 7)) { count -= 8; do { *(u64 *)to = __raw_readq(from); @@ -425,7 +425,7 @@ count += 8; } - if (count >= 4 && ((long)to & 3) == (from & 3)) { + if (count >= 4 && ((unsigned long)to & 3) == (from & 3)) { count -= 4; do { *(u32 *)to = __raw_readl(from); @@ -436,7 +436,7 @@ count += 4; } - if (count >= 2 && ((long)to & 1) == (from & 1)) { + if (count >= 2 && ((unsigned long)to & 1) == (from & 1)) { count -= 2; do { *(u16 *)to = __raw_readw(from); @@ -465,7 +465,7 @@ a byte at a time. */ /* FIXME -- align FROM. */ - if (count >= 8 && (to & 7) == ((long)from & 7)) { + if (count >= 8 && (to & 7) == ((unsigned long)from & 7)) { count -= 8; do { __raw_writeq(*(const u64 *)from, to); @@ -476,7 +476,7 @@ count += 8; } - if (count >= 4 && (to & 3) == ((long)from & 3)) { + if (count >= 4 && (to & 3) == ((unsigned long)from & 3)) { count -= 4; do { __raw_writel(*(const u32 *)from, to); @@ -487,7 +487,7 @@ count += 4; } - if (count >= 2 && (to & 1) == ((long)from & 1)) { + if (count >= 2 && (to & 1) == ((unsigned long)from & 1)) { count -= 2; do { __raw_writew(*(const u16 *)from, to); diff -Nru a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c --- a/arch/alpha/mm/init.c Fri Nov 22 13:41:23 2002 +++ b/arch/alpha/mm/init.c Fri Nov 22 13:41:23 2002 @@ -242,7 +242,7 @@ if (alpha_using_srm) { static struct vm_struct console_remap_vm; unsigned long vaddr = VMALLOC_START; - long i, j; + unsigned long i, j; /* Set up the third level PTEs and update the virtual addresses of the CRB entries. */ @@ -357,18 +357,23 @@ #endif /* CONFIG_DISCONTIGMEM */ void -free_initmem (void) +free_reserved_mem(void *start, void *end) { - extern char __init_begin, __init_end; - unsigned long addr; - - addr = (unsigned long)(&__init_begin); - for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { - ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); - free_page(addr); + void *__start = start; + for (; __start < end; __start += PAGE_SIZE) { + ClearPageReserved(virt_to_page(__start)); + set_page_count(virt_to_page(__start), 1); + free_page((long)__start); totalram_pages++; } +} + +void +free_initmem(void) +{ + extern char __init_begin, __init_end; + + free_reserved_mem(&__init_begin, &__init_end); printk ("Freeing unused kernel memory: %ldk freed\n", (&__init_end - &__init_begin) >> 10); } @@ -377,13 +382,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) { - unsigned long __start = start; - for (; start < end; start += PAGE_SIZE) { - ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); - free_page(start); - totalram_pages++; - } - printk ("Freeing initrd memory: %ldk freed\n", (end - __start) >> 10); + free_reserved_mem((void *)start, (void *)end); + printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); } #endif diff -Nru a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c --- a/arch/alpha/mm/numa.c Fri Nov 22 13:41:17 2002 +++ b/arch/alpha/mm/numa.c Fri Nov 22 13:41:17 2002 @@ -249,16 +249,18 @@ #ifdef CONFIG_BLK_DEV_INITRD initrd_start = INITRD_START; if (initrd_start) { + extern void *move_initrd(unsigned long); + initrd_end = initrd_start+INITRD_SIZE; printk("Initial ramdisk at: 0x%p (%lu bytes)\n", (void *) initrd_start, INITRD_SIZE); if ((void *)initrd_end > phys_to_virt(PFN_PHYS(max_low_pfn))) { - printk("initrd extends beyond end of memory " - "(0x%08lx > 0x%p)\ndisabling initrd\n", - initrd_end, - phys_to_virt(PFN_PHYS(max_low_pfn))); - initrd_start = initrd_end = 0; + if (!move_initrd(PFN_PHYS(max_low_pfn))) + printk("initrd extends beyond end of memory " + "(0x%08lx > 0x%p)\ndisabling initrd\n", + initrd_end, + phys_to_virt(PFN_PHYS(max_low_pfn))); } else { reserve_bootmem_node(NODE_DATA(KVADDR_TO_NID(initrd_start)), virt_to_phys((void *)initrd_start), diff -Nru a/arch/arm/Makefile b/arch/arm/Makefile --- a/arch/arm/Makefile Fri Nov 22 13:41:18 2002 +++ b/arch/arm/Makefile Fri Nov 22 13:41:18 2002 @@ -52,8 +52,8 @@ # Force -mno-fpu to be passed to the assembler. Some versions of gcc don't # do this with -msoft-float -CFLAGS_BOOT :=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa,-mno-fpu -CFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa,-mno-fpu +CFLAGS_BOOT :=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa,-mno-fpu -Uarm +CFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa,-mno-fpu -Uarm AFLAGS +=$(apcs-y) $(arch-y) -mno-fpu -msoft-float -Wa,-mno-fpu #Default value diff -Nru a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile --- a/arch/arm/kernel/Makefile Fri Nov 22 13:41:23 2002 +++ b/arch/arm/kernel/Makefile Fri Nov 22 13:41:23 2002 @@ -22,7 +22,7 @@ obj-$(CONFIG_ARCH_CLPS7500) += time-acorn.o obj-$(CONFIG_FOOTBRIDGE) += isa.o obj-$(CONFIG_FIQ) += fiq.o -obj-$(CONFIG_MODULES) += armksyms.o +obj-$(CONFIG_MODULES) += armksyms.o module.o obj-$(CONFIG_ARTHUR) += arthur.o obj-$(CONFIG_ISA_DMA) += dma-isa.o obj-$(CONFIG_PCI) += bios32.o diff -Nru a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c --- a/arch/arm/kernel/armksyms.c Fri Nov 22 13:41:18 2002 +++ b/arch/arm/kernel/armksyms.c Fri Nov 22 13:41:18 2002 @@ -82,12 +82,9 @@ extern void __do_softirq(void); #define EXPORT_SYMBOL_ALIAS(sym,orig) \ - const char __kstrtab_##sym[] \ - __attribute__((section(".kstrtab"))) = \ - __MODULE_STRING(sym); \ - const struct module_symbol __ksymtab_##sym \ + const struct kernel_symbol __ksymtab_##sym \ __attribute__((section("__ksymtab"))) = \ - { (unsigned long)&orig, __kstrtab_##sym }; + { (unsigned long)&orig, #sym }; /* * floating point math emulator support. @@ -107,6 +104,7 @@ #endif EXPORT_SYMBOL_NOVERS(__do_softirq); +EXPORT_SYMBOL_NOVERS(__backtrace); /* platform dependent support */ EXPORT_SYMBOL(dump_thread); @@ -129,6 +127,7 @@ EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(probe_irq_mask); EXPORT_SYMBOL(set_irq_type); +EXPORT_SYMBOL(set_irq_wake); EXPORT_SYMBOL(pm_idle); EXPORT_SYMBOL(pm_power_off); EXPORT_SYMBOL(fp_init); diff -Nru a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c --- a/arch/arm/kernel/bios32.c Fri Nov 22 13:41:19 2002 +++ b/arch/arm/kernel/bios32.c Fri Nov 22 13:41:19 2002 @@ -270,7 +270,7 @@ if (debug_pci) printk("PCI: Assigning %3s %08lx to %s\n", res->flags & IORESOURCE_IO ? "IO" : "MEM", - res->start, dev->name); + res->start, dev->dev.name); if (resource < 6) { reg = PCI_BASE_ADDRESS_0 + 4*resource; @@ -303,7 +303,7 @@ void __devinit pcibios_update_irq(struct pci_dev *dev, int irq) { if (debug_pci) - printk("PCI: Assigning IRQ %02d to %s\n", irq, dev->name); + printk("PCI: Assigning IRQ %02d to %s\n", irq, dev->dev.name); pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); } @@ -642,7 +642,7 @@ enum pci_mmap_state mmap_state, int write_combine) { struct pci_sys_data *root = dev->sysdata; - unsigned long prot, phys; + unsigned long phys; if (mmap_state == pci_mmap_io) { return -EINVAL; diff -Nru a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S --- a/arch/arm/kernel/calls.S Fri Nov 22 13:41:23 2002 +++ b/arch/arm/kernel/calls.S Fri Nov 22 13:41:23 2002 @@ -141,10 +141,10 @@ .long sys_adjtimex /* 125 */ .long sys_mprotect .long sys_sigprocmask - .long sys_create_module + .long sys_ni_syscall /* was sys_create_module */ .long sys_init_module .long sys_delete_module -/* 130 */ .long sys_get_kernel_syms +/* 130 */ .long sys_ni_syscall /* was sys_get_kernel_syms */ .long sys_quotactl .long sys_getpgid .long sys_fchdir @@ -181,7 +181,7 @@ .long sys_setresuid16 /* 165 */ .long sys_getresuid16 .long sys_ni_syscall - .long sys_query_module + .long sys_ni_syscall /* was sys_query_module */ .long sys_poll .long sys_nfsservctl /* 170 */ .long sys_setresgid16 diff -Nru a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S --- a/arch/arm/kernel/entry-armv.S Fri Nov 22 13:41:18 2002 +++ b/arch/arm/kernel/entry-armv.S Fri Nov 22 13:41:18 2002 @@ -193,7 +193,7 @@ mov \irqstat, #0x0C strb \irqstat, [r4, #0x20] @outb(0x0C, 0x20) /* Poll command */ - ldrb \irqnr, [r4, #0x10] @irq = inb(0x20) & 7 + ldrb \irqnr, [r4, #0x20] @irq = inb(0x20) & 7 and \irqstat, \irqnr, #0x80 teq \irqstat, #0 beq 43f diff -Nru a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/arm/kernel/module.c Fri Nov 22 13:41:23 2002 @@ -0,0 +1,172 @@ +/* + * linux/arch/arm/kernel/module.c + * + * Copyright (C) 2002 Russell King. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Module allocation method suggested by Andi Kleen. + */ +#include +#include +#include +#include +#include +#include +#include + +#include + +void *module_alloc(unsigned long size) +{ + struct vm_struct *area; + struct page **pages; + unsigned int array_size, i; + + size = PAGE_ALIGN(size); + if (!size) + goto out_null; + + area = __get_vm_area(size, VM_ALLOC, MODULE_START, MODULE_END); + if (!area) + goto out_null; + + area->nr_pages = size >> PAGE_SHIFT; + array_size = area->nr_pages * sizeof(struct page *); + area->pages = pages = kmalloc(array_size, GFP_KERNEL); + if (!area->pages) { + remove_vm_area(area->addr); + kfree(area); + goto out_null; + } + + memset(pages, 0, array_size); + + for (i = 0; i < area->nr_pages; i++) { + pages[i] = alloc_page(GFP_KERNEL); + if (unlikely(!pages[i])) { + area->nr_pages = i; + goto out_no_pages; + } + } + + if (map_vm_area(area, PAGE_KERNEL, &pages)) + goto out_no_pages; + return area->addr; + + out_no_pages: + vfree(area->addr); + out_null: + return NULL; +} + +void module_free(struct module *module, void *region) +{ + vfree(region); +} + +long +module_core_size(const Elf32_Ehdr *hdr, const Elf32_Shdr *sechdrs, + const char *secstrings, struct module *module) +{ + return module->core_size; +} + +long +module_init_size(const Elf32_Ehdr *hdr, const Elf32_Shdr *sechdrs, + const char *secstrings, struct module *module) +{ + return module->init_size; +} + +int +apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, + unsigned int relindex, struct module *module) +{ + Elf32_Shdr *symsec = sechdrs + symindex; + Elf32_Shdr *relsec = sechdrs + relindex; + Elf32_Shdr *dstsec = sechdrs + relsec->sh_info; + Elf32_Rel *rel = (void *)relsec->sh_offset; + unsigned int i; + + for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rel); i++, rel++) { + unsigned long loc; + Elf32_Sym *sym; + s32 offset; + + offset = ELF32_R_SYM(rel->r_info); + if (offset < 0 || offset > (symsec->sh_size / sizeof(Elf32_Sym))) { + printk(KERN_ERR "%s: bad relocation, section %d reloc %d\n", + module->name, relindex, i); + return -ENOEXEC; + } + + sym = ((Elf32_Sym *)symsec->sh_offset) + offset; + if (!sym->st_value) { + printk(KERN_WARNING "%s: unknown symbol %s\n", + module->name, strtab + sym->st_name); + return -ENOENT; + } + + if (rel->r_offset < 0 || rel->r_offset > dstsec->sh_size - sizeof(u32)) { + printk(KERN_ERR "%s: out of bounds relocation, " + "section %d reloc %d offset %d size %d\n", + module->name, relindex, i, rel->r_offset, + dstsec->sh_size); + return -ENOEXEC; + } + + loc = dstsec->sh_offset + rel->r_offset; + + switch (ELF32_R_TYPE(rel->r_info)) { + case R_ARM_ABS32: + *(u32 *)loc += sym->st_value; + break; + + case R_ARM_PC24: + offset = (*(u32 *)loc & 0x00ffffff) << 2; + if (offset & 0x02000000) + offset -= 0x04000000; + + offset += sym->st_value - loc; + if (offset & 3 || + offset <= (s32)0xfc000000 || + offset >= (s32)0x04000000) { + printk(KERN_ERR "%s: unable to fixup " + "relocation: out of range\n", + module->name); + return -ENOEXEC; + } + + offset >>= 2; + + *(u32 *)loc &= 0xff000000; + *(u32 *)loc |= offset & 0x00ffffff; + break; + + default: + printk(KERN_ERR "%s: unknown relocation: %u\n", + module->name, ELF32_R_TYPE(rel->r_info)); + return -ENOEXEC; + } + } + return 0; +} + +int +apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab, + unsigned int symindex, unsigned int relsec, struct module *module) +{ + printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", + module->name); + return -ENOEXEC; +} + +int +module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, + struct module *module) +{ + return 0; +} diff -Nru a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c --- a/arch/arm/kernel/process.c Fri Nov 22 13:41:23 2002 +++ b/arch/arm/kernel/process.c Fri Nov 22 13:41:23 2002 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c --- a/arch/arm/kernel/sys_arm.c Fri Nov 22 13:41:18 2002 +++ b/arch/arm/kernel/sys_arm.c Fri Nov 22 13:41:18 2002 @@ -239,7 +239,7 @@ asmlinkage int sys_fork(struct pt_regs *regs) { struct task_struct *p; - p = do_fork(SIGCHLD, regs->ARM_sp, regs, 0, NULL); + p = do_fork(SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL); return IS_ERR(p) ? PTR_ERR(p) : p->pid; } @@ -253,13 +253,13 @@ /* * We don't support SETTID / CLEARTID */ - if (clone_flags & (CLONE_SETTID | CLONE_CLEARTID)) + if (clone_flags & (CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID)) return -EINVAL; if (!newsp) newsp = regs->ARM_sp; - p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL); + p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL); return IS_ERR(p) ? PTR_ERR(p) : p->pid; } @@ -267,7 +267,7 @@ asmlinkage int sys_vfork(struct pt_regs *regs) { struct task_struct *p; - p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs, 0, NULL); + p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL); return IS_ERR(p) ? PTR_ERR(p) : p->pid; } diff -Nru a/arch/arm/kernel/time-acorn.c b/arch/arm/kernel/time-acorn.c --- a/arch/arm/kernel/time-acorn.c Fri Nov 22 13:41:23 2002 +++ b/arch/arm/kernel/time-acorn.c Fri Nov 22 13:41:23 2002 @@ -12,12 +12,11 @@ * 10-Oct-1996 RMK Brought up to date with arch-sa110eval * 04-Dec-1997 RMK Updated for new arch/arm/time.c */ -#include +#include #include #include #include -#include #include extern unsigned long (*gettimeoffset)(void); diff -Nru a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c --- a/arch/arm/kernel/traps.c Fri Nov 22 13:41:19 2002 +++ b/arch/arm/kernel/traps.c Fri Nov 22 13:41:19 2002 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/arm/mach-footbridge/netwinder-pci.c b/arch/arm/mach-footbridge/netwinder-pci.c --- a/arch/arm/mach-footbridge/netwinder-pci.c Fri Nov 22 13:41:17 2002 +++ b/arch/arm/mach-footbridge/netwinder-pci.c Fri Nov 22 13:41:17 2002 @@ -37,7 +37,7 @@ default: printk(KERN_ERR "PCI: unknown device in slot %s: %s\n", - dev->slot_name, dev->name); + dev->slot_name, dev->dev.name); return 0; } } diff -Nru a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c --- a/arch/arm/mach-integrator/cpu.c Fri Nov 22 13:41:20 2002 +++ b/arch/arm/mach-integrator/cpu.c Fri Nov 22 13:41:20 2002 @@ -73,7 +73,7 @@ * Validate the speed in khz. If it is outside our * range, then return the lowest. */ -static void integrator_verify_speed(struct cpufreq_policy *policy) +static int integrator_verify_speed(struct cpufreq_policy *policy) { struct vco vco; @@ -93,6 +93,8 @@ vco.vdw = 152; policy->min = policy->max = vco_to_freq(vco, 1); + + return 0; } static void do_set_policy(int cpu, struct cpufreq_policy *policy) @@ -116,7 +118,7 @@ __raw_writel(0, CM_LOCK); } -static void integrator_set_policy(struct cpufreq_policy *policy) +static int integrator_set_policy(struct cpufreq_policy *policy) { unsigned long cpus_allowed; int cpu; @@ -139,6 +141,8 @@ * Restore the CPUs allowed mask. */ set_cpus_allowed(current, cpus_allowed); + + return 0; } static struct cpufreq_policy integrator_policy = { @@ -151,7 +155,6 @@ .verify = integrator_verify_speed, .setpolicy = integrator_set_policy, .policy = &integrator_policy, - .cpu_min_freq = 12000, }; #endif @@ -202,6 +205,8 @@ set_cpus_allowed(current, cpus_allowed); #ifdef CONFIG_CPU_FREQ + for (cpu=0; cpu #include #include +#include #include #include diff -Nru a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c --- a/arch/arm/mach-sa1100/cpu-sa1100.c Fri Nov 22 13:41:18 2002 +++ b/arch/arm/mach-sa1100/cpu-sa1100.c Fri Nov 22 13:41:18 2002 @@ -176,7 +176,7 @@ } } -static void sa1100_setspeed(struct cpufreq_policy *policy) +static int sa1100_setspeed(struct cpufreq_policy *policy) { unsigned int cur = sa11x0_getspeed(); struct cpufreq_freqs freqs; @@ -196,6 +196,8 @@ sa1100_update_dram_timings(cur, policy->max); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + + return 0; } static struct cpufreq_policy sa1100_policy = { @@ -208,7 +210,7 @@ .verify = sa11x0_verify_speed, .setpolicy = sa1100_setspeed, .policy = &sa1100_policy, - .cpu_min_freq = 59000, + .cpu_min_freq[0]= 59000, }; static int __init sa1100_dram_init(void) @@ -216,7 +218,7 @@ int ret = -ENODEV; if ((processor_id & CPU_SA1100_MASK) == CPU_SA1100_ID) { - sa1100_driver.cpu_curr_freq[0] = + sa1100_driver.cpu_cur_freq[0] = sa1100_policy.min = sa1100_policy.max = sa11x0_getspeed(); diff -Nru a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c --- a/arch/arm/mach-sa1100/cpu-sa1110.c Fri Nov 22 13:41:17 2002 +++ b/arch/arm/mach-sa1100/cpu-sa1110.c Fri Nov 22 13:41:17 2002 @@ -212,7 +212,7 @@ * above, we can match for an exact frequency. If we don't find * an exact match, we will to set the lowest frequency to be safe. */ -static void sa1110_setspeed(struct cpufreq_policy *policy) +static int sa1110_setspeed(struct cpufreq_policy *policy) { struct sdram_params *sdram = &sdram_params; struct cpufreq_freqs freqs; @@ -291,6 +291,8 @@ sdram_update_refresh(policy->max, sdram); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + + return 0; } static struct cpufreq_policy sa1110_policy = { @@ -300,10 +302,10 @@ }; static struct cpufreq_driver sa1110_driver = { - .verify = sa11x0_verify_speed, - .setpolicy = sa1110_setspeed, - .policy = &sa1110_policy, - .cpu_min_freq = 59000, + .verify = sa11x0_verify_speed, + .setpolicy = sa1110_setspeed, + .policy = &sa1110_policy, + .cpu_min_freq[0] = 59000, }; static int __init sa1110_clk_init(void) diff -Nru a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c --- a/arch/arm/mach-sa1100/generic.c Fri Nov 22 13:41:18 2002 +++ b/arch/arm/mach-sa1100/generic.c Fri Nov 22 13:41:18 2002 @@ -67,7 +67,7 @@ * scaling, so we force min=max, and set the policy to "performance". * If we can't generate the precise frequency requested, round it up. */ -void sa11x0_verify_speed(struct cpufreq_policy *policy) +int sa11x0_verify_speed(struct cpufreq_policy *policy) { if (policy->max > policy->max_cpu_freq) policy->max = policy->max_cpu_freq; @@ -75,6 +75,7 @@ policy->max = cclk_frequency_100khz[sa11x0_freq_to_ppcr(policy->max)] * 100; policy->min = policy->max; policy->policy = CPUFREQ_POLICY_POWERSAVE; + return 0; } unsigned int sa11x0_getspeed(void) diff -Nru a/arch/arm/mm/extable.c b/arch/arm/mm/extable.c --- a/arch/arm/mm/extable.c Fri Nov 22 13:41:20 2002 +++ b/arch/arm/mm/extable.c Fri Nov 22 13:41:20 2002 @@ -4,6 +4,7 @@ #include #include +#include #include extern const struct exception_table_entry __start___ex_table[]; @@ -41,18 +42,19 @@ /* There is only the kernel to search. */ ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr); #else - /* The kernel is the last "module" -- no need to treat it special. */ unsigned long flags; - struct module *mp; + struct list_head *l; ret = 0; + /* The kernel is the last "module" -- no need to treat it special. */ spin_lock_irqsave(&modlist_lock, flags); - for (mp = module_list; mp != NULL; mp = mp->next) { - if (mp->ex_table_start == NULL || - !(mp->flags & (MOD_RUNNING | MOD_INITIALIZING))) + list_for_each(l, &extables) { + struct exception_table *ex + = list_entry(l, struct exception_table, list); + if (ex->num_entries == 0) continue; - ret = search_one_table(mp->ex_table_start, - mp->ex_table_end - 1, addr); + ret = search_one_table(ex->entry, + ex->entry + ex->num_entries - 1, addr); if (ret) break; } diff -Nru a/arch/arm/nwfpe/fpa11.c b/arch/arm/nwfpe/fpa11.c --- a/arch/arm/nwfpe/fpa11.c Fri Nov 22 13:41:19 2002 +++ b/arch/arm/nwfpe/fpa11.c Fri Nov 22 13:41:19 2002 @@ -26,6 +26,7 @@ #include "fpmodule.inl" #include +#include #include /* forward declarations */ diff -Nru a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types --- a/arch/arm/tools/mach-types Fri Nov 22 13:41:19 2002 +++ b/arch/arm/tools/mach-types Fri Nov 22 13:41:20 2002 @@ -6,7 +6,7 @@ # To add an entry into this database, please see Documentation/arm/README, # or contact rmk@arm.linux.org.uk # -# Last update: Sat Sep 21 13:39:13 2002 +# Last update: Sat Nov 16 15:57:50 2002 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -71,7 +71,7 @@ jupiter SA1100_JUPITER JUPITER 59 psionw ARCH_PSIONW PSIONW 60 aln SA1100_ALN ALN 61 -epxa10db ARCH_CAMELOT CAMELOT 62 +epxa ARCH_CAMELOT CAMELOT 62 gds2200 SA1100_GDS2200 GDS2200 63 psion_series7 SA1100_PSION_SERIES7 PSION_SERIES7 64 xfile SA1100_XFILE XFILE 65 @@ -242,3 +242,19 @@ yoho ARCH_YOHO YOHO 231 jasper ARCH_JASPER JASPER 232 dsc25 ARCH_DSC25 DSC25 233 +innovator ARCH_INNOVATOR INNOVATOR 234 +ramses ARCH_RAMSES RAMSES 235 +s28x ARCH_S28X S28X 236 +mport3 ARCH_MPORT3 MPORT3 237 +pxa_eagle250 ARCH_PXA_EAGLE250 PXA_EAGLE250 238 +pdb ARCH_PDB PDB 239 +blue_2g SA1100_BLUE_2G BLUE_2G 240 +bluearch SA1100_BLUEARCH BLUEARCH 241 +ixdp2400 ARCH_IXMB2400 IXMB2400 242 +ixdp2800 ARCH_IXMB2800 IXMB2800 243 +explorer SA1100_EXPLORER EXPLORER 244 +ixdp425 ARCH_IXDP425 IXDP425 245 +chimp ARCH_CHIMP CHIMP 246 +stork_nest ARCH_STORK_NEST STORK_NEST 247 +stork_egg ARCH_STORK_EGG STORK_EGG 248 +wismo SA1100_WISMO WISMO 249 diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig --- a/arch/i386/Kconfig Fri Nov 22 13:41:18 2002 +++ b/arch/i386/Kconfig Fri Nov 22 13:41:18 2002 @@ -1604,14 +1604,13 @@ This options enables addition error checking for high memory systems. Disable for production systems. -# Reimplemented RSN. -#config KALLSYMS -# bool "Load all symbols for debugging/kksymoops" -# depends on DEBUG_KERNEL -# help -# Say Y here to let the kernel print out symbolic crash information and -# symbolic stack backtraces. This increases the size of the kernel -# somewhat, as all symbols have to be loaded into the kernel image. +config KALLSYMS + bool "Load all symbols for debugging/kksymoops" + depends on DEBUG_KERNEL + help + Say Y here to let the kernel print out symbolic crash information and + symbolic stack backtraces. This increases the size of the kernel + somewhat, as all symbols have to be loaded into the kernel image. config X86_EXTRA_IRQS bool diff -Nru a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c --- a/arch/i386/kernel/cpu/amd.c Fri Nov 22 13:41:23 2002 +++ b/arch/i386/kernel/cpu/amd.c Fri Nov 22 13:41:23 2002 @@ -164,12 +164,23 @@ set_bit(X86_FEATURE_XMM, c->x86_capability); } } - break; + /* It's been determined by AMD that Athlons since model 8 stepping 1 + * are more robust with CLK_CTL set to 200xxxxx instead of 600xxxxx + * As per AMD technical note 27212 0.2 + */ + if ((c->x86_model == 8 && c->x86_mask>=1) || (c->x86_model > 8)) { + rdmsr(MSR_K7_CLK_CTL, l, h); + if ((l & 0xfff00000) != 0x20000000) { + printk ("CPU: CLK_CTL MSR was %x. Reprogramming to %x\n", l, + ((l & 0x000fffff)|0x20000000)); + wrmsr(MSR_K7_CLK_CTL, (l & 0x000fffff)|0x20000000, h); + } + } + break; } display_cacheinfo(c); -// return r; } static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size) diff -Nru a/arch/i386/kernel/cpu/cpufreq/elanfreq.c b/arch/i386/kernel/cpu/cpufreq/elanfreq.c --- a/arch/i386/kernel/cpu/cpufreq/elanfreq.c Fri Nov 22 13:41:19 2002 +++ b/arch/i386/kernel/cpu/cpufreq/elanfreq.c Fri Nov 22 13:41:19 2002 @@ -172,13 +172,13 @@ * for the hardware supported by the driver. */ -static void elanfreq_verify (struct cpufreq_policy *policy) +static int elanfreq_verify (struct cpufreq_policy *policy) { unsigned int number_states = 0; unsigned int i; if (!policy || !max_freq) - return; + return -EINVAL; policy->cpu = 0; @@ -190,7 +190,7 @@ number_states++; if (number_states) - return; + return 0; for (i=(sizeof(elan_multiplier)/sizeof(struct s_elan_multiplier) - 1); i>=0; i--) if (elan_multiplier[i].clock < policy->max) @@ -198,16 +198,16 @@ policy->max = elan_multiplier[i+1].clock; - return; + return 0; } -static void elanfreq_setpolicy (struct cpufreq_policy *policy) +static int elanfreq_setpolicy (struct cpufreq_policy *policy) { unsigned int number_states = 0; unsigned int i, j=4; if (!elanfreq_driver) - return; + return -EINVAL; for (i=(sizeof(elan_multiplier)/sizeof(struct s_elan_multiplier) - 1); i>=0; i--) if ((elan_multiplier[i].clock >= policy->min) && @@ -219,7 +219,7 @@ if (number_states == 1) { elanfreq_set_cpu_state(j); - return; + return 0; } switch (policy->policy) { @@ -236,14 +236,14 @@ j = i; break; default: - return; + return -EINVAL; } if (elan_multiplier[j].clock > max_freq) - BUG(); + return -EINVAL; elanfreq_set_cpu_state(j); - return; + return 0; } @@ -296,7 +296,7 @@ max_freq = elanfreq_get_cpu_frequency(); #ifdef CONFIG_CPU_FREQ_24_API - driver->cpu_min_freq = 1000; + driver->cpu_min_freq[0] = 1000; driver->cpu_cur_freq[0] = elanfreq_get_cpu_frequency(); #endif @@ -309,15 +309,15 @@ driver->policy[0].policy = CPUFREQ_POLICY_PERFORMANCE; driver->policy[0].max_cpu_freq = max_freq; + elanfreq_driver = driver; + ret = cpufreq_register(driver); if (ret) { + elanfreq_driver = NULL; kfree(driver); - return ret; } - elanfreq_driver = driver; - - return 0; + return ret; } diff -Nru a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c Fri Nov 22 13:41:17 2002 +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c Fri Nov 22 13:41:17 2002 @@ -1,5 +1,5 @@ /* - * $Id: longhaul.c,v 1.72 2002/09/29 23:43:10 db Exp $ + * $Id: longhaul.c,v 1.77 2002/10/31 21:17:40 db Exp $ * * (C) 2001 Dave Jones. * (C) 2002 Padraig Brady. @@ -436,8 +436,10 @@ switch (longhaul) { case 1: /* Ugh, Longhaul v1 didn't have the min/max MSRs. - Assume max = whatever we booted at. */ + Assume min=3.0x & max = whatever we booted at. */ + minmult = 30; maxmult = longhaul_get_cpu_mult(); + minfsb = maxfsb = current_fsb; break; case 2 ... 3: @@ -531,7 +533,7 @@ } -static void longhaul_verify(struct cpufreq_policy *policy) +static int longhaul_verify(struct cpufreq_policy *policy) { unsigned int number_states = 0; unsigned int i; @@ -540,7 +542,7 @@ unsigned int newmax = -1; if (!policy || !longhaul_driver) - return; + return -EINVAL; policy->cpu = 0; cpufreq_verify_within_limits(policy, lowest_speed, highest_speed); @@ -552,7 +554,7 @@ number_states = longhaul_statecount_fsb(policy, current_fsb); if (number_states) - return; + return 0; /* get frequency closest above current policy->max */ if (can_scale_fsb==1) { @@ -579,10 +581,12 @@ } policy->max = newmax; + + return 0; } -static void longhaul_setpolicy (struct cpufreq_policy *policy) +static int longhaul_setpolicy (struct cpufreq_policy *policy) { unsigned int number_states = 0; unsigned int i; @@ -592,7 +596,7 @@ unsigned int best_freq = -1; if (!longhaul_driver) - return; + return -EINVAL; if (policy->policy==CPUFREQ_POLICY_PERFORMANCE) fsb_search_table = perf_fsb_table; @@ -613,7 +617,7 @@ } if (!number_states) - return; + return -EINVAL; else if (number_states == 1) { for(i=0; ipolicy = (struct cpufreq_policy *) (driver + 1); #ifdef CONFIG_CPU_FREQ_24_API - driver->cpu_min_freq = (unsigned int) lowest_speed; + driver->cpu_min_freq[0] = (unsigned int) lowest_speed; driver->cpu_cur_freq[0] = currentspeed; #endif @@ -788,15 +792,15 @@ driver->policy[0].policy = CPUFREQ_POLICY_PERFORMANCE; driver->policy[0].max_cpu_freq = (unsigned int) highest_speed; - ret = cpufreq_register(driver); + longhaul_driver = driver; + ret = cpufreq_register(driver); if (ret) { + longhaul_driver = NULL; kfree(driver); - return ret; } - longhaul_driver = driver; - return 0; + return ret; } diff -Nru a/arch/i386/kernel/cpu/cpufreq/longrun.c b/arch/i386/kernel/cpu/cpufreq/longrun.c --- a/arch/i386/kernel/cpu/cpufreq/longrun.c Fri Nov 22 13:41:22 2002 +++ b/arch/i386/kernel/cpu/cpufreq/longrun.c Fri Nov 22 13:41:22 2002 @@ -1,5 +1,5 @@ /* - * $Id: longrun.c,v 1.12 2002/09/29 23:43:10 db Exp $ + * $Id: longrun.c,v 1.14 2002/10/31 21:17:40 db Exp $ * * (C) 2002 Dominik Brodowski * @@ -67,13 +67,13 @@ * Sets a new CPUFreq policy on LongRun-capable processors. This function * has to be called with cpufreq_driver locked. */ -static void longrun_set_policy(struct cpufreq_policy *policy) +static int longrun_set_policy(struct cpufreq_policy *policy) { u32 msr_lo, msr_hi; u32 pctg_lo, pctg_hi; if (!longrun_driver || !policy) - return; + return -EINVAL; pctg_lo = (policy->min - longrun_low_freq) / ((longrun_high_freq - longrun_low_freq) / 100); @@ -105,7 +105,7 @@ msr_hi |= pctg_hi; wrmsr(MSR_TMTA_LONGRUN_CTRL, msr_lo, msr_hi); - return; + return 0; } @@ -115,16 +115,16 @@ * Validates a new CPUFreq policy. This function has to be called with * cpufreq_driver locked. */ -static void longrun_verify_policy(struct cpufreq_policy *policy) +static int longrun_verify_policy(struct cpufreq_policy *policy) { if (!policy || !longrun_driver) - return; + return -EINVAL; policy->cpu = 0; cpufreq_verify_within_limits(policy, 0, longrun_driver->policy[0].max_cpu_freq); - return; + return 0; } @@ -252,20 +252,22 @@ longrun_get_policy(&driver->policy[0]); #ifdef CONFIG_CPU_FREQ_24_API - driver->cpu_min_freq = longrun_low_freq; + driver->cpu_min_freq[0] = longrun_low_freq; driver->cpu_cur_freq[0] = longrun_high_freq; /* dummy value */ #endif driver->verify = &longrun_verify_policy; driver->setpolicy = &longrun_set_policy; + + longrun_driver = driver; + result = cpufreq_register(driver); if (result) { + longrun_driver = NULL; kfree(driver); - return result; } - longrun_driver = driver; - return 0; + return result; } diff -Nru a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c --- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c Fri Nov 22 13:41:23 2002 +++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c Fri Nov 22 13:41:23 2002 @@ -78,7 +78,7 @@ } #endif set_cpus_allowed(current, affected_cpu_map); - BUG_ON(!(smp_processor_id() & affected_cpu_map)); + BUG_ON(!(affected_cpu_map & (1 << smp_processor_id()))); /* get current state */ rdmsr(MSR_IA32_THERM_CONTROL, l, h); @@ -136,14 +136,14 @@ } -static void cpufreq_p4_setpolicy(struct cpufreq_policy *policy) +static int cpufreq_p4_setpolicy(struct cpufreq_policy *policy) { unsigned int i; unsigned int newstate = 0; unsigned int number_states = 0; if (!cpufreq_p4_driver || !stock_freq || !policy) - return; + return -EINVAL; if (policy->policy == CPUFREQ_POLICY_POWERSAVE) { @@ -183,16 +183,17 @@ min_state = newstate - (number_states - 1); } } */ + return 0; } -static void cpufreq_p4_verify(struct cpufreq_policy *policy) +static int cpufreq_p4_verify(struct cpufreq_policy *policy) { unsigned int number_states = 0; unsigned int i; if (!cpufreq_p4_driver || !stock_freq || !policy) - return; + return -EINVAL; if (!cpu_online(policy->cpu)) policy->cpu = CPUFREQ_ALL_CPUS; @@ -205,10 +206,10 @@ number_states++; if (number_states) - return; + return 0; policy->max = (stock_freq / 8) * (((unsigned int) ((policy->max * 8) / stock_freq)) + 1); - return; + return 0; } @@ -255,9 +256,10 @@ stock_freq = cpu_khz; #ifdef CONFIG_CPU_FREQ_24_API - driver->cpu_min_freq = stock_freq / 8; - for (i=0;icpu_min_freq[i] = stock_freq / 8; driver->cpu_cur_freq[i] = stock_freq; + } #endif driver->verify = &cpufreq_p4_verify; @@ -274,15 +276,15 @@ driver->policy[i].cpu = i; } + cpufreq_p4_driver = driver; + ret = cpufreq_register(driver); if (ret) { + cpufreq_p4_driver = NULL; kfree(driver); - return ret; } - cpufreq_p4_driver = driver; - - return 0; + return ret; } diff -Nru a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c --- a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c Fri Nov 22 13:41:18 2002 +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c Fri Nov 22 13:41:18 2002 @@ -1,5 +1,5 @@ /* - * $Id: powernow-k6.c,v 1.33 2002/09/29 23:43:11 db Exp $ + * $Id: powernow-k6.c,v 1.36 2002/10/31 21:17:40 db Exp $ * This file was part of Powertweak Linux (http://powertweak.sf.net) * and is shared with the Linux Kernel module. * @@ -113,13 +113,13 @@ * Policy must be within lowest and highest possible CPU Frequency, * and at least one possible state must be within min and max. */ -static void powernow_k6_verify(struct cpufreq_policy *policy) +static int powernow_k6_verify(struct cpufreq_policy *policy) { unsigned int number_states = 0; unsigned int i, j; if (!policy || !busfreq) - return; + return -EINVAL; policy->cpu = 0; cpufreq_verify_within_limits(policy, (20 * busfreq), @@ -131,7 +131,7 @@ number_states++; if (number_states) - return; + return 0; /* no state is available within range -- find next larger state */ @@ -144,7 +144,7 @@ policy->max = clock_ratio[j] * busfreq; - return; + return 0; } @@ -154,13 +154,13 @@ * * sets a new CPUFreq policy */ -static void powernow_k6_setpolicy (struct cpufreq_policy *policy) +static int powernow_k6_setpolicy (struct cpufreq_policy *policy) { unsigned int number_states = 0; unsigned int i, j=4; if (!powernow_driver) - return; + return -EINVAL; for (i=0; i<8; i++) if ((policy->min <= (busfreq * clock_ratio[i])) && @@ -174,7 +174,7 @@ /* if only one state is within the limit borders, it is easily detected and set */ powernow_k6_set_state(j); - return; + return 0; } /* more than one state within limit */ @@ -196,14 +196,14 @@ j = i; break; default: - return; + return -EINVAL; } if (clock_ratio[i] > max_multiplier) - BUG(); + return -EINVAL; powernow_k6_set_state(j); - return; + return 0; } @@ -242,7 +242,7 @@ driver->policy = (struct cpufreq_policy *) (driver + 1); #ifdef CONFIG_CPU_FREQ_24_API - driver->cpu_min_freq = busfreq * 20; + driver->cpu_min_freq[0] = busfreq * 20; driver->cpu_cur_freq[0] = busfreq * max_multiplier; #endif @@ -255,16 +255,16 @@ driver->policy[0].policy = CPUFREQ_POLICY_PERFORMANCE; driver->policy[0].max_cpu_freq = busfreq * max_multiplier; + powernow_driver = driver; result = cpufreq_register(driver); if (result) { release_region (POWERNOW_IOPORT, 16); + powernow_driver = NULL; kfree(driver); - return result; } - powernow_driver = driver; - return 0; + return result; } diff -Nru a/arch/i386/kernel/cpu/cpufreq/speedstep.c b/arch/i386/kernel/cpu/cpufreq/speedstep.c --- a/arch/i386/kernel/cpu/cpufreq/speedstep.c Fri Nov 22 13:41:17 2002 +++ b/arch/i386/kernel/cpu/cpufreq/speedstep.c Fri Nov 22 13:41:17 2002 @@ -1,5 +1,5 @@ /* - * $Id: speedstep.c,v 1.57 2002/11/05 12:01:12 db Exp $ + * $Id: speedstep.c,v 1.58 2002/11/11 15:35:46 db Exp $ * * (C) 2001 Dave Jones, Arjan van de ven. * (C) 2002 Dominik Brodowski @@ -567,10 +567,10 @@ * * Sets a new CPUFreq policy. */ -static void speedstep_setpolicy (struct cpufreq_policy *policy) +static int speedstep_setpolicy (struct cpufreq_policy *policy) { if (!speedstep_driver || !policy) - return; + return -EINVAL; if (policy->min > speedstep_low_freq) speedstep_set_state(SPEEDSTEP_HIGH, 1); @@ -585,6 +585,7 @@ speedstep_set_state(SPEEDSTEP_HIGH, 1); } } + return 0; } @@ -595,11 +596,11 @@ * Limit must be within speedstep_low_freq and speedstep_high_freq, with * at least one border included. */ -static void speedstep_verify (struct cpufreq_policy *policy) +static int speedstep_verify (struct cpufreq_policy *policy) { if (!policy || !speedstep_driver || !speedstep_low_freq || !speedstep_high_freq) - return; + return -EINVAL; policy->cpu = 0; /* UP only */ @@ -609,7 +610,7 @@ (policy->max < speedstep_high_freq)) policy->max = speedstep_high_freq; - return; + return 0; } @@ -654,12 +655,11 @@ speedstep_processor = speedstep_detect_processor(); if ((!speedstep_chipset) || (!speedstep_processor)) { - printk(KERN_INFO "a 0x%x b 0x%x\n", speedstep_processor, speedstep_chipset); printk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) for this %s not (yet) available.\n", speedstep_chipset ? "processor" : "chipset"); return -ENODEV; } - dprintk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) support $Revision: 1.57 $\n"); + dprintk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) support $Revision: 1.58 $\n"); dprintk(KERN_DEBUG "cpufreq: chipset 0x%x - processor 0x%x\n", speedstep_chipset, speedstep_processor); @@ -693,7 +693,7 @@ driver->policy = (struct cpufreq_policy *) (driver + 1); #ifdef CONFIG_CPU_FREQ_24_API - driver->cpu_min_freq = speedstep_low_freq; + driver->cpu_min_freq[0] = speedstep_low_freq; driver->cpu_cur_freq[0] = speed; #endif @@ -707,14 +707,15 @@ driver->policy[0].policy = (speed == speedstep_low_freq) ? CPUFREQ_POLICY_POWERSAVE : CPUFREQ_POLICY_PERFORMANCE; + speedstep_driver = driver; + result = cpufreq_register(driver); if (result) { + speedstep_driver = NULL; kfree(driver); - return result; } - speedstep_driver = driver; - return 0; + return result; } diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S --- a/arch/i386/kernel/entry.S Fri Nov 22 13:41:18 2002 +++ b/arch/i386/kernel/entry.S Fri Nov 22 13:41:18 2002 @@ -130,12 +130,16 @@ # gates, which has to be cleaned up later.. pushl %eax SAVE_ALL - movl EIP(%esp), %eax # due to call gates, this is eflags, not eip.. - movl CS(%esp), %edx # this is eip.. - movl EFLAGS(%esp), %ecx # and this is cs.. - movl %eax,EFLAGS(%esp) # - movl %edx,EIP(%esp) # Now we move them to their "normal" places - movl %ecx,CS(%esp) # + movl %esp, %ebx + pushl %ebx + pushl $0x7 +do_lcall: + movl EIP(%ebx), %eax # due to call gates, this is eflags, not eip.. + movl CS(%ebx), %edx # this is eip.. + movl EFLAGS(%ebx), %ecx # and this is cs.. + movl %eax,EFLAGS(%ebx) # + movl %edx,EIP(%ebx) # Now we move them to their "normal" places + movl %ecx,CS(%ebx) # # # Call gates don't clear TF and NT in eflags like @@ -147,13 +151,9 @@ pushl %eax popfl - movl %esp, %ebx - pushl %ebx andl $-8192, %ebx # GET_THREAD_INFO movl TI_EXEC_DOMAIN(%ebx), %edx # Get the execution domain - movl 4(%edx), %edx # Get the lcall7 handler for the domain - pushl $0x7 - call *%edx + call *4(%edx) # Call the lcall7 handler for the domain addl $4, %esp popl %eax jmp resume_userspace @@ -163,40 +163,15 @@ # gates, which has to be cleaned up later.. pushl %eax SAVE_ALL - movl EIP(%esp), %eax # due to call gates, this is eflags, not eip.. - movl CS(%esp), %edx # this is eip.. - movl EFLAGS(%esp), %ecx # and this is cs.. - movl %eax,EFLAGS(%esp) # - movl %edx,EIP(%esp) # Now we move them to their "normal" places - movl %ecx,CS(%esp) # - - # - # Call gates don't clear TF and NT in eflags like - # traps do, so we need to do it ourselves. - # %eax already contains eflags (but it may have - # DF set, clear that also) - # - andl $~(DF_MASK | TF_MASK | NT_MASK),%eax - pushl %eax - popfl - movl %esp, %ebx pushl %ebx - andl $-8192, %ebx # GET_THREAD_INFO - movl TI_EXEC_DOMAIN(%ebx), %edx # Get the execution domain - movl 4(%edx), %edx # Get the lcall7 handler for the domain pushl $0x27 - call *%edx - addl $4, %esp - popl %eax - jmp resume_userspace + jmp do_lcall ENTRY(ret_from_fork) -#if CONFIG_SMP || CONFIG_PREEMPT # NOTE: this function takes a parameter but it's unused on x86. call schedule_tail -#endif GET_THREAD_INFO(%ebx) jmp syscall_exit diff -Nru a/arch/i386/kernel/module.c b/arch/i386/kernel/module.c --- a/arch/i386/kernel/module.c Fri Nov 22 13:41:20 2002 +++ b/arch/i386/kernel/module.c Fri Nov 22 13:41:20 2002 @@ -25,7 +25,7 @@ #if 0 #define DEBUGP printk #else -#define DEBUGP(fmt , ...) +#define DEBUGP(fmt...) #endif void *module_alloc(unsigned long size) diff -Nru a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c --- a/arch/i386/kernel/process.c Fri Nov 22 13:41:17 2002 +++ b/arch/i386/kernel/process.c Fri Nov 22 13:41:17 2002 @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -225,7 +226,7 @@ regs.eflags = 0x286; /* Ok, create the new process.. */ - p = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL); + p = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); return IS_ERR(p) ? PTR_ERR(p) : p->pid; } @@ -287,7 +288,7 @@ struct_cpy(childregs, regs); childregs->eax = 0; childregs->esp = esp; - p->user_tid = NULL; + p->set_child_tid = p->clear_child_tid = NULL; p->thread.esp = (unsigned long) childregs; p->thread.esp0 = (unsigned long) (childregs+1); @@ -502,7 +503,7 @@ { struct task_struct *p; - p = do_fork(SIGCHLD, regs.esp, ®s, 0, NULL); + p = do_fork(SIGCHLD, regs.esp, ®s, 0, NULL, NULL); return IS_ERR(p) ? PTR_ERR(p) : p->pid; } @@ -511,14 +512,15 @@ struct task_struct *p; unsigned long clone_flags; unsigned long newsp; - int *user_tid; + int *parent_tidptr, *child_tidptr; clone_flags = regs.ebx; newsp = regs.ecx; - user_tid = (int *)regs.edx; + parent_tidptr = (int *)regs.edx; + child_tidptr = (int *)regs.edi; if (!newsp) newsp = regs.esp; - p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, user_tid); + p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, parent_tidptr, child_tidptr); return IS_ERR(p) ? PTR_ERR(p) : p->pid; } @@ -536,7 +538,7 @@ { struct task_struct *p; - p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, ®s, 0, NULL); + p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, ®s, 0, NULL, NULL); return IS_ERR(p) ? PTR_ERR(p) : p->pid; } diff -Nru a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c --- a/arch/i386/kernel/smpboot.c Fri Nov 22 13:41:20 2002 +++ b/arch/i386/kernel/smpboot.c Fri Nov 22 13:41:20 2002 @@ -419,6 +419,7 @@ smp_store_cpu_info(cpuid); disable_APIC_timer(); + local_irq_disable(); /* * Allow the master to continue. */ @@ -498,7 +499,7 @@ * don't care about the eip and regs settings since * we'll never reschedule the forked task. */ - return do_fork(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL); + return do_fork(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); } /* which physical APIC ID maps to which logical CPU number */ @@ -1179,13 +1180,18 @@ int __devinit __cpu_up(unsigned int cpu) { /* This only works at boot for x86. See "rewrite" above. */ - if (test_bit(cpu, &smp_commenced_mask)) + if (test_bit(cpu, &smp_commenced_mask)) { + local_irq_enable(); return -ENOSYS; + } /* In case one didn't come up */ - if (!test_bit(cpu, &cpu_callin_map)) + if (!test_bit(cpu, &cpu_callin_map)) { + local_irq_enable(); return -EIO; + } + local_irq_enable(); /* Unleash the CPU! */ set_bit(cpu, &smp_commenced_mask); while (!test_bit(cpu, &cpu_online_map)) diff -Nru a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c --- a/arch/i386/kernel/traps.c Fri Nov 22 13:41:18 2002 +++ b/arch/i386/kernel/traps.c Fri Nov 22 13:41:18 2002 @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef CONFIG_EISA #include diff -Nru a/arch/i386/mach-generic/topology.c b/arch/i386/mach-generic/topology.c --- a/arch/i386/mach-generic/topology.c Fri Nov 22 13:41:22 2002 +++ b/arch/i386/mach-generic/topology.c Fri Nov 22 13:41:22 2002 @@ -26,6 +26,7 @@ * Send feedback to */ #include +#include #include struct i386_cpu cpu_devices[NR_CPUS]; diff -Nru a/arch/i386/oprofile/Makefile b/arch/i386/oprofile/Makefile --- a/arch/i386/oprofile/Makefile Fri Nov 22 13:41:23 2002 +++ b/arch/i386/oprofile/Makefile Fri Nov 22 13:41:23 2002 @@ -1,12 +1,10 @@ obj-$(CONFIG_OPROFILE) += oprofile.o - + DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ - oprof.o cpu_buffer.o buffer_sync.o \ - event_buffer.o oprofile_files.o \ - oprofilefs.o oprofile_stats.o ) - -oprofile-objs := $(DRIVER_OBJS) init.o timer_int.o + oprof.o cpu_buffer.o buffer_sync.o \ + event_buffer.o oprofile_files.o \ + oprofilefs.o oprofile_stats.o ) -oprofile-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_athlon.o op_model_ppro.o - -include $(TOPDIR)/Rules.make +oprofile-y := $(DRIVER_OBJS) init.o timer_int.o +oprofile-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_athlon.o \ + op_model_ppro.o diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig --- a/arch/ia64/Kconfig Fri Nov 22 13:41:23 2002 +++ b/arch/ia64/Kconfig Fri Nov 22 13:41:23 2002 @@ -813,13 +813,13 @@ Say Y here if you are developing drivers or trying to debug and identify kernel problems. -# config KALLSYMS -# bool "Load all symbols for debugging/kksymoops" -# depends on DEBUG_KERNEL -# help -# Say Y here to let the kernel print out symbolic crash information and -# symbolic stack backtraces. This increases the size of the kernel -# somewhat, as all symbols have to be loaded into the kernel image. +config KALLSYMS + bool "Load all symbols for debugging/kksymoops" + depends on DEBUG_KERNEL + help + Say Y here to let the kernel print out symbolic crash information and + symbolic stack backtraces. This increases the size of the kernel + somewhat, as all symbols have to be loaded into the kernel image. config IA64_PRINT_HAZARDS bool "Print possible IA-64 dependency violations to console" diff -Nru a/arch/ppc/Kconfig b/arch/ppc/Kconfig --- a/arch/ppc/Kconfig Fri Nov 22 13:41:23 2002 +++ b/arch/ppc/Kconfig Fri Nov 22 13:41:23 2002 @@ -1314,6 +1314,17 @@ depends on BOOT_LOAD_BOOL default "0x00400000" +# If we don't have a custom load, we define one here depending. +config BOOT_LOAD + hex + depends on !BOOT_LOAD_BOOL && (40x || 8xx || 8260) + default "0x00400000" + +config BOOT_LOAD + hex + depends on !BOOT_LOAD_BOOL + default "0x00800000" + endmenu source "drivers/mtd/Kconfig" @@ -1807,9 +1818,9 @@ bool "Highmem debugging" depends on DEBUG_KERNEL && HIGHMEM -# config KALLSYMS -# bool "Load all symbols for debugging/kksymoops" -# depends on DEBUG_KERNEL +config KALLSYMS + bool "Load all symbols for debugging/kksymoops" + depends on DEBUG_KERNEL config KGDB bool "Include kgdb kernel debugger" diff -Nru a/arch/ppc/Makefile b/arch/ppc/Makefile --- a/arch/ppc/Makefile Fri Nov 22 13:41:17 2002 +++ b/arch/ppc/Makefile Fri Nov 22 13:41:17 2002 @@ -36,19 +36,13 @@ CFLAGS += $(shell echo $(CONFIG_COMPILE_OPTIONS) | sed -e 's/"//g') endif -ifdef CONFIG_4xx - HEAD := arch/ppc/kernel/head_4xx.o -else - ifdef CONFIG_8xx - HEAD := arch/ppc/kernel/head_8xx.o - else - ifdef CONFIG_PPC_ISERIES - HEAD := arch/ppc/kernel/iSeries_head.o - else - HEAD := arch/ppc/kernel/head.o - endif - endif -endif +head-y := head.o +head-$(CONFIG_PPC_ISERIES) := iSeries_head.o +head-$(CONFIG_8xx) := head_8xx.o +head-$(CONFIG_4xx) := head_4xx.o +head-$(CONFIG_440) := head_44x.o + +HEAD := arch/ppc/kernel/$(head-y) core-y += arch/ppc/kernel/ arch/ppc/platforms/ \ arch/ppc/mm/ arch/ppc/lib/ arch/ppc/syslib/ @@ -80,7 +74,7 @@ cp -f arch/ppc/configs/$(@:config=defconfig) .config archclean: - $(MAKE) -f scripts/Makefile.clean obj=arch/ppc/boot + +$(MAKE) -f scripts/Makefile.clean obj=arch/ppc/boot archmrproper: diff -Nru a/arch/ppc/boot/Makefile b/arch/ppc/boot/Makefile --- a/arch/ppc/boot/Makefile Fri Nov 22 13:41:21 2002 +++ b/arch/ppc/boot/Makefile Fri Nov 22 13:41:21 2002 @@ -10,19 +10,17 @@ # modified by Cort (cort@cs.nmt.edu) # -CFLAGS += -fno-builtin -D__BOOTER__ -I$(TOPDIR)/arch/$(ARCH)/boot/include +CFLAGS += -fno-builtin -D__BOOTER__ -Iarch/$(ARCH)/boot/include -AFLAGS += -D__BOOTER__ -OBJCOPY_ARGS = -O elf32-powerpc +BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd bootdir-y := simple bootdir-$(CONFIG_ALL_PPC) := openfirmware prep +subdir-y := lib common images +subdir-$(CONFIG_ALL_PPC) += of1275 -# for cleaning... -subdir- := images simple openfirmware prep \ - lib common of1275 - -HOSTCFLAGS += -Iarch/$(ARCH)/boot/include +# for cleaning +subdir- += simple openfirmware prep tools-$(CONFIG_ALL_PPC) := addnote mknote hack-coff mkprep tools-$(CONFIG_PPLUS) := mkbugboot mkprep @@ -39,15 +37,9 @@ host-progs := $(addprefix utils/,$(tools-y)) -zImage zImage.initrd znetboot znetboot.initrd: $(addprefix $(obj)/,$(bootdir-y)) - -.PHONY: FORCE - -$(obj)/simple $(obj)/openfirmware $(obj)/prep: $(obj)/lib $(obj)/common $(obj)/images -$(obj)/openfirmware $(obj)/prep: $(obj)/of1275 +.PHONY: $(BOOT_TARGETS) $(bootdir-y) -$(obj)/lib $(obj)/common $(obj)/of1275 $(obj)/images: FORCE - +@$(call descend,$@,) +$(BOOT_TARGETS): $(bootdir-y) -$(obj)/openfirmware $(obj)/prep $(obj)/simple: FORCE - +@$(call descend,$@,$(MAKECMDGOALS)) +$(bootdir-y): $(addprefix $(obj)/,$(subdir-y)) + +$(call descend,$(obj)/$@,$(MAKECMDGOALS)) diff -Nru a/arch/ppc/boot/common/Makefile b/arch/ppc/boot/common/Makefile --- a/arch/ppc/boot/common/Makefile Fri Nov 22 13:41:20 2002 +++ b/arch/ppc/boot/common/Makefile Fri Nov 22 13:41:20 2002 @@ -15,5 +15,3 @@ obj-$(CONFIG_LOPEC) += mpc10x_memory.o obj-$(CONFIG_PAL4) += cpc700_memory.o obj-$(CONFIG_SERIAL_8250_CONSOLE) += ns16550.o - -include $(TOPDIR)/Rules.make diff -Nru a/arch/ppc/boot/images/Makefile b/arch/ppc/boot/images/Makefile --- a/arch/ppc/boot/images/Makefile Fri Nov 22 13:41:18 2002 +++ b/arch/ppc/boot/images/Makefile Fri Nov 22 13:41:18 2002 @@ -10,6 +10,5 @@ $(OBJCOPY) -O binary $< $(@:.gz=) gzip $(GZIP_FLAGS) $(@:.gz=) -clean: - rm -f $(obj)/sImage $(obj)/vmapus $(obj)/vmlinux* $(obj)/miboot* - rm -f $(obj)/zImage* z$(obj)/vmlinux* +# Files generated that shall be removed upon make clean +clean-files := sImage vmapus vmlinux* miboot* zImage* diff -Nru a/arch/ppc/boot/lib/Makefile b/arch/ppc/boot/lib/Makefile --- a/arch/ppc/boot/lib/Makefile Fri Nov 22 13:41:22 2002 +++ b/arch/ppc/boot/lib/Makefile Fri Nov 22 13:41:22 2002 @@ -5,5 +5,3 @@ L_TARGET := lib.a obj-y := zlib.o div64.o - -include $(TOPDIR)/Rules.make diff -Nru a/arch/ppc/boot/of1275/Makefile b/arch/ppc/boot/of1275/Makefile --- a/arch/ppc/boot/of1275/Makefile Fri Nov 22 13:41:20 2002 +++ b/arch/ppc/boot/of1275/Makefile Fri Nov 22 13:41:20 2002 @@ -6,5 +6,3 @@ obj-y := claim.o enter.o exit.o finddevice.o getprop.o ofinit.o \ ofstdio.o read.o release.o write.o - -include $(TOPDIR)/Rules.make diff -Nru a/arch/ppc/boot/openfirmware/Makefile b/arch/ppc/boot/openfirmware/Makefile --- a/arch/ppc/boot/openfirmware/Makefile Fri Nov 22 13:41:18 2002 +++ b/arch/ppc/boot/openfirmware/Makefile Fri Nov 22 13:41:18 2002 @@ -10,13 +10,10 @@ # Merged 'chrp' and 'pmac' into 'openfirmware', and cleaned up the # rules. -EXTRA_TARGETS := start.o misc.o crt0.o coffcrt0.o coffmain.o chrpmain.o \ - newworldmain.o common.o +clean-files := note coffboot coffboot.initrd boot: zImage -include $(TOPDIR)/Rules.make - boot := arch/ppc/boot common := $(boot)/common utils := $(boot)/utils @@ -38,8 +35,6 @@ ADDNOTE := $(utils)/addnote MKNOTE := $(utils)/mknote -SIZE := $(utils)/size -OFFSET := $(utils)/offset HACKCOFF := $(utils)/hack-coff ifdef CONFIG_SMP @@ -109,12 +104,12 @@ $(LD) -o $@ $(COFF_LD_ARGS) $^ $(OBJCOPY) $@ $@ -R .comment -$(images)/vmlinux.coff: $(obj)/coffboot +$(images)/vmlinux.coff: $(obj)/coffboot $(HACKCOFF) $(OBJCOPY) $(OBJCOPY_ARGS) $(obj)/coffboot $@ $(HACKCOFF) $@ ln -sf vmlinux.coff $(images)/zImage.pmac -$(images)/vmlinux.initrd.coff: $(obj)/coffboot.initrd +$(images)/vmlinux.initrd.coff: $(obj)/coffboot.initrd $(HACKCOFF) $(OBJCOPY) $(OBJCOPY_ARGS) $(obj)/coffboot.initrd $@ $(HACKCOFF) $@ ln -sf vmlinux.initrd.coff $(images)/zImage.initrd.pmac @@ -139,11 +134,11 @@ $(LD) $(CHRP_LD_ARGS) -o $@ $^ $(OBJCOPY) $@ $@ -R .comment -$(images)/zImage.chrp-rs6k: $(images)/zImage.chrp +$(images)/zImage.chrp-rs6k: $(images)/zImage.chrp $(ADDNOTE) cp $(images)/zImage.chrp $@ $(ADDNOTE) $@ -$(images)/zImage.initrd.chrp-rs6k: $(images)/zImage.initrd.chrp +$(images)/zImage.initrd.chrp-rs6k: $(images)/zImage.initrd.chrp $(ADDNOTE) cp $(images)/zImage.initrd.chrp $@ $(ADDNOTE) $@ @@ -152,6 +147,3 @@ zImage.initrd: $(images)/vmlinux.initrd.coff $(images)/vmlinux.initrd.elf-pmac\ $(images)/zImage.initrd.chrp $(images)/miboot.initrd.image - -clean: - rm -f $(obj)/note $(obj)/image.o $(obj)/coffboot $(obj)/coffboot.initrd diff -Nru a/arch/ppc/boot/prep/Makefile b/arch/ppc/boot/prep/Makefile --- a/arch/ppc/boot/prep/Makefile Fri Nov 22 13:41:23 2002 +++ b/arch/ppc/boot/prep/Makefile Fri Nov 22 13:41:23 2002 @@ -27,10 +27,6 @@ boot-y := head.o misc.o boot-$(CONFIG_VGA_CONSOLE) += vreset.o kbd.o -EXTRA_TARGETS := $(boot-y) ../simple/legacy.o - -include $(TOPDIR)/Rules.make - boot := arch/ppc/boot common := $(boot)/common utils := $(boot)/utils @@ -43,8 +39,6 @@ # Tools MKPREP := $(utils)/mkprep -SIZE := $(utils)/size -OFFSET := $(utils)/offset # Extra include search dirs CFLAGS_kbd.o += -Idrivers/char @@ -55,8 +49,8 @@ $(obj)/dummy.o: $(common)/dummy.c $(CC) -c -o $@ $(common)/dummy.c -$(images)/zImage.prep: $(OBJS) $(LIBS) $(boot)/ld.script \ - $(images)/vmlinux.gz $(obj)/dummy.o +$(images)/zImage.prep: $(OBJS) $(LIBS) $(boot)/ld.script $(images)/vmlinux.gz \ + $(obj)/dummy.o $(MKPREP) $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ --add-section=.image=$(images)/vmlinux.gz \ --set-section-flags=.image=contents,alloc,load,readonly,data \ @@ -68,7 +62,7 @@ rm -f $(obj)/zImage $(images)/zImage.initrd.prep: $(OBJS) $(LIBS) $(boot)/ld.script \ - $(images)/vmlinux.gz $(obj)/dummy.o + $(images)/vmlinux.gz $(obj)/dummy.o $(MKPREP) $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ --add-section=.ramdisk=$(images)/ramdisk.image.gz \ --set-section-flags=.ramdisk=contents,alloc,load,readonly,data \ diff -Nru a/arch/ppc/boot/prep/misc.c b/arch/ppc/boot/prep/misc.c --- a/arch/ppc/boot/prep/misc.c Fri Nov 22 13:41:21 2002 +++ b/arch/ppc/boot/prep/misc.c Fri Nov 22 13:41:21 2002 @@ -8,6 +8,7 @@ */ #include +#include #include #include #include diff -Nru a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile --- a/arch/ppc/boot/simple/Makefile Fri Nov 22 13:41:17 2002 +++ b/arch/ppc/boot/simple/Makefile Fri Nov 22 13:41:17 2002 @@ -132,23 +132,9 @@ EXTRA := rw4/rw4_init.o rw4/rw4_init_brd.o endif -# Default linker args. Link at 0x00800000 or 0x00400000 by default, but -# allow it to be overridden. -ifeq ($(CONFIG_BOOT_LOAD_BOOL),y) -LD_ARGS := -T $(boot)/ld.script \ - -Ttext $(CONFIG_BOOT_LOAD) -Bstatic -else +# Linker args. This specifies where the image will be run at. LD_ARGS = -T $(boot)/ld.script \ - -Ttext 0x00800000 -Bstatic -ifeq ($(CONFIG_8260)$(CONFIG_40x)$(CONFIG_8xx),y) -LD_ARGS := -T $(boot)/ld.script -Ttext 0x00400000 \ - -Bstatic -endif -ifeq ($(CONFIG_440),y) -LD_ARGS := -T $(boot)/ld.script -Ttext 0x01000000 \ - -Bstatic -endif -endif + -Ttext $(CONFIG_BOOT_LOAD) -Bstatic OBJCOPY_ARGS := -O elf32-powerpc # head.o and relocate.o must be at the start. @@ -167,8 +153,7 @@ boot-$(CONFIG_GT64260_CONSOLE) += gt64260_tty.o endif -EXTRA_TARGETS := $(boot-y) -LIBS := $(common)/lib.a $(bootlib)/lib.a +LIBS := $(common)/lib.a $(bootlib)/lib.a OBJS := $(addprefix $(obj)/,$(boot-y)) @@ -181,7 +166,7 @@ $(CC) -c -o $@ $(common)/dummy.c $(obj)/zvmlinux: $(OBJS) $(LIBS) $(boot)/ld.script $(images)/vmlinux.gz \ - $(obj)/dummy.o + $(obj)/dummy.o $(OBJCOPY) $(OBJCOPY_ARGS) \ --add-section=.image=$(images)/vmlinux.gz \ --set-section-flags=.image=contents,alloc,load,readonly,data \ diff -Nru a/arch/ppc/boot/simple/misc.c b/arch/ppc/boot/simple/misc.c --- a/arch/ppc/boot/simple/misc.c Fri Nov 22 13:41:22 2002 +++ b/arch/ppc/boot/simple/misc.c Fri Nov 22 13:41:22 2002 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile --- a/arch/ppc/kernel/Makefile Fri Nov 22 13:41:23 2002 +++ b/arch/ppc/kernel/Makefile Fri Nov 22 13:41:23 2002 @@ -25,7 +25,7 @@ cputable.o ppc_htab.o obj-$(CONFIG_6xx) += l2cr.o ppc6xx_idle.o obj-$(CONFIG_ALL_PPC) += ppc6xx_idle.o -obj-$(CONFIG_MODULES) += ppc_ksyms.o +obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o obj-$(CONFIG_PCI) += pci.o ifneq ($(CONFIG_PPC_ISERIES),y) obj-$(CONFIG_PCI) += pci-dma.o diff -Nru a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S --- a/arch/ppc/kernel/misc.S Fri Nov 22 13:41:23 2002 +++ b/arch/ppc/kernel/misc.S Fri Nov 22 13:41:23 2002 @@ -1182,10 +1182,10 @@ .long sys_adjtimex .long sys_mprotect /* 125 */ .long sys_sigprocmask - .long sys_create_module + .long sys_ni_syscall /* old sys_create_module */ .long sys_init_module .long sys_delete_module - .long sys_get_kernel_syms /* 130 */ + .long sys_ni_syscall /* old sys_get_kernel_syms */ /* 130 */ .long sys_quotactl .long sys_getpgid .long sys_fchdir @@ -1221,7 +1221,7 @@ .long sys_mremap .long sys_setresuid .long sys_getresuid /* 165 */ - .long sys_query_module + .long sys_ni_syscall /* old sys_query_module */ .long sys_poll .long sys_nfsservctl .long sys_setresgid diff -Nru a/arch/ppc/kernel/module.c b/arch/ppc/kernel/module.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc/kernel/module.c Fri Nov 22 13:41:23 2002 @@ -0,0 +1,260 @@ +/* Kernel module help for PPC. + Copyright (C) 2001 Rusty Russell. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include +#include +#include +#include +#include +#include + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(fmt , ...) +#endif + +void *module_alloc(unsigned long size) +{ + if (size == 0) + return NULL; + return vmalloc(size); +} + +/* Free memory returned from module_alloc */ +void module_free(struct module *mod, void *module_region) +{ + vfree(module_region); + /* FIXME: If module_region == mod->init_region, trim exception + table entries. */ +} + +/* Count how many different relocations (different symbol, different + addend) */ +static unsigned int count_relocs(const Elf32_Rela *rela, unsigned int num) +{ + unsigned int i, j, ret = 0; + + /* Sure, this is order(n^2), but it's usually short, and not + time critical */ + for (i = 0; i < num; i++) { + for (j = 0; j < i; j++) { + /* If this addend appeared before, it's + already been counted */ + if (ELF32_R_SYM(rela[i].r_info) + == ELF32_R_SYM(rela[j].r_info) + && rela[i].r_addend == rela[j].r_addend) + break; + } + if (j == i) ret++; + } + return ret; +} + +/* Get the potential trampolines size required of the init and + non-init sections */ +static unsigned long get_plt_size(const Elf32_Ehdr *hdr, + const Elf32_Shdr *sechdrs, + const char *secstrings, + int is_init) +{ + unsigned long ret = 0; + unsigned i; + + /* Everything marked ALLOC (this includes the exported + symbols) */ + for (i = 1; i < hdr->e_shnum; i++) { + /* If it's called *.init*, and we're not init, we're + not interested */ + if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0) + != is_init) + continue; + + if (sechdrs[i].sh_type == SHT_RELA) { + DEBUGP("Found relocations in section %u\n", i); + DEBUGP("Ptr: %p. Number: %u\n", + (void *)hdr + sechdrs[i].sh_offset, + sechdrs[i].sh_size / sizeof(Elf32_Rela)); + ret += count_relocs((void *)hdr + + sechdrs[i].sh_offset, + sechdrs[i].sh_size + / sizeof(Elf32_Rela)) + * sizeof(struct ppc_plt_entry); + } + } + + return ret; +} + +long module_core_size(const Elf32_Ehdr *hdr, + const Elf32_Shdr *sechdrs, + const char *secstrings, + struct module *module) +{ + module->arch.core_plt_offset = module->core_size; + return module->core_size + get_plt_size(hdr, sechdrs, secstrings, 0); +} + +long module_init_size(const Elf32_Ehdr *hdr, + const Elf32_Shdr *sechdrs, + const char *secstrings, + struct module *module) +{ + module->arch.init_plt_offset = module->init_size; + return module->init_size + get_plt_size(hdr, sechdrs, secstrings, 1); +} + +int apply_relocate(Elf32_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *module) +{ + printk(KERN_ERR "%s: Non-ADD RELOCATION unsupported\n", + module->name); + return -ENOEXEC; +} + +static inline int entry_matches(struct ppc_plt_entry *entry, Elf32_Addr val) +{ + if (entry->jump[0] == 0x3d600000 + ((val + 0x8000) >> 16) + && entry->jump[1] == 0x396b0000 + (val & 0xffff)) + return 1; + return 0; +} + +/* Set up a trampoline in the PLT to bounce us to the distant function */ +static uint32_t do_plt_call(void *location, Elf32_Addr val, struct module *mod) +{ + struct ppc_plt_entry *entry; + + DEBUGP("Doing plt for %u\n", (unsigned int)location); + /* Init, or core PLT? */ + if (location >= mod->module_core + && location < mod->module_core + mod->arch.core_plt_offset) + entry = mod->module_core + mod->arch.core_plt_offset; + else + entry = mod->module_init + mod->arch.init_plt_offset; + + /* Find this entry, or if that fails, the next avail. entry */ + while (entry->jump[0]) { + if (entry_matches(entry, val)) return (uint32_t)entry; + entry++; + } + + /* Stolen from Paul Mackerras as well... */ + entry->jump[0] = 0x3d600000+((val+0x8000)>>16); /* lis r11,sym@ha */ + entry->jump[1] = 0x396b0000 + (val&0xffff); /* addi r11,r11,sym@l*/ + entry->jump[2] = 0x7d6903a6; /* mtctr r11 */ + entry->jump[3] = 0x4e800420; /* bctr */ + + return (uint32_t)entry; +} + +int apply_relocate_add(Elf32_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *module) +{ + unsigned int i; + Elf32_Rela *rela = (void *)sechdrs[relsec].sh_offset; + Elf32_Sym *sym; + uint32_t *location; + uint32_t value; + + DEBUGP("Applying ADD relocate section %u to %u\n", relsec, + sechdrs[relsec].sh_info); + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) { + /* This is where to make the change */ + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_offset + + rela[i].r_offset; + /* This is the symbol it is referring to */ + sym = (Elf32_Sym *)sechdrs[symindex].sh_offset + + ELF32_R_SYM(rela[i].r_info); + if (!sym->st_value) { + printk(KERN_WARNING "%s: Unknown symbol %s\n", + module->name, strtab + sym->st_name); + return -ENOENT; + } + /* `Everything is relative'. */ + value = sym->st_value + rela[i].r_addend; + + switch (ELF32_R_TYPE(rela[i].r_info)) { + case R_PPC_ADDR32: + /* Simply set it */ + *(uint32_t *)location = value; + break; + + case R_PPC_ADDR16_LO: + /* Low half of the symbol */ + *(uint16_t *)location = value; + break; + + case R_PPC_ADDR16_HA: + /* Sign-adjusted lower 16 bits: PPC ELF ABI says: + (((x >> 16) + ((x & 0x8000) ? 1 : 0))) & 0xFFFF. + This is the same, only sane. + */ + *(uint16_t *)location = (value + 0x8000) >> 16; + break; + + case R_PPC_REL24: + if ((int)(value - (uint32_t)location) < -0x02000000 + || (int)(value - (uint32_t)location) >= 0x02000000) + value = do_plt_call(location, value, module); + + /* Only replace bits 2 through 26 */ + DEBUGP("REL24 value = %08X. location = %08X\n", + value, (uint32_t)location); + DEBUGP("Location before: %08X.\n", + *(uint32_t *)location); + *(uint32_t *)location + = (*(uint32_t *)location & ~0x03fffffc) + | ((value - (uint32_t)location) + & 0x03fffffc); + DEBUGP("Location after: %08X.\n", + *(uint32_t *)location); + DEBUGP("ie. jump to %08X+%08X = %08X\n", + *(uint32_t *)location & 0x03fffffc, + (uint32_t)location, + (*(uint32_t *)location & 0x03fffffc) + + (uint32_t)location); + break; + + case R_PPC_REL32: + /* 32-bit relative jump. */ + *(uint32_t *)location = value - (uint32_t)location; + break; + + default: + printk("%s: unknown ADD relocation: %u\n", + module->name, + ELF32_R_TYPE(rela[i].r_info)); + return -ENOEXEC; + } + } + return 0; +} + +/* FIXME: Sort exception table --RR */ +int module_finalize(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, + struct module *me) +{ + return 0; +} diff -Nru a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c --- a/arch/ppc/kernel/process.c Fri Nov 22 13:41:20 2002 +++ b/arch/ppc/kernel/process.c Fri Nov 22 13:41:20 2002 @@ -34,6 +34,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/ppc/mm/extable.c b/arch/ppc/mm/extable.c --- a/arch/ppc/mm/extable.c Fri Nov 22 13:41:23 2002 +++ b/arch/ppc/mm/extable.c Fri Nov 22 13:41:23 2002 @@ -70,24 +70,29 @@ unsigned long search_exception_table(unsigned long addr) { - unsigned long ret; + unsigned long ret = 0; #ifndef CONFIG_MODULES /* There is only the kernel to search. */ ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr); - if (ret) return ret; #else - /* The kernel is the last "module" -- no need to treat it special. */ - struct module *mp; - for (mp = module_list; mp != NULL; mp = mp->next) { - if (mp->ex_table_start == NULL) + unsigned long flags; + struct list_head *i; + + /* The kernel is the last "module" -- no need to treat it special. */ + spin_lock_irqsave(&modlist_lock, flags); + list_for_each(i, &extables) { + struct exception_table *ex + = list_entry(i, struct exception_table, list); + if (ex->num_entries == 0) continue; - ret = search_one_table(mp->ex_table_start, - mp->ex_table_end - 1, addr); + ret = search_one_table(ex->entry, + ex->entry + ex->num_entries - 1, addr); if (ret) - return ret; + break; } + spin_unlock_irqrestore(&modlist_lock, flags); #endif - return 0; + return ret; } diff -Nru a/arch/ppc/platforms/pmac_pic.c b/arch/ppc/platforms/pmac_pic.c --- a/arch/ppc/platforms/pmac_pic.c Fri Nov 22 13:41:23 2002 +++ b/arch/ppc/platforms/pmac_pic.c Fri Nov 22 13:41:23 2002 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/ppc/syslib/i8259.c b/arch/ppc/syslib/i8259.c --- a/arch/ppc/syslib/i8259.c Fri Nov 22 13:41:19 2002 +++ b/arch/ppc/syslib/i8259.c Fri Nov 22 13:41:19 2002 @@ -1,9 +1,6 @@ -#include #include -#include #include -#include -#include +#include #include #include diff -Nru a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c --- a/arch/ppc/syslib/open_pic.c Fri Nov 22 13:41:21 2002 +++ b/arch/ppc/syslib/open_pic.c Fri Nov 22 13:41:21 2002 @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include diff -Nru a/arch/s390/Kconfig b/arch/s390/Kconfig --- a/arch/s390/Kconfig Fri Nov 22 13:41:19 2002 +++ b/arch/s390/Kconfig Fri Nov 22 13:41:19 2002 @@ -11,38 +11,6 @@ bool default y -config ISA - bool - help - Find out whether you have ISA slots on your motherboard. ISA is the - name of a bus system, i.e. the way the CPU talks to the other stuff - inside your box. Other bus systems are PCI, EISA, MicroChannel - (MCA) or VESA. ISA is an older system, now being displaced by PCI; - newer boards don't support it. If you have ISA, say Y, otherwise N. - -config EISA - bool - ---help--- - The Extended Industry Standard Architecture (EISA) bus was - developed as an open alternative to the IBM MicroChannel bus. - - The EISA bus provided some of the features of the IBM MicroChannel - bus while maintaining backward compatibility with cards made for - the older ISA bus. The EISA bus saw limited use between 1988 and - 1995 when it was made obsolete by the PCI bus. - - Say Y here if you are building a kernel for an EISA-based machine. - - Otherwise, say N. - -config MCA - bool - help - MicroChannel Architecture is found in some IBM PS/2 machines and - laptops. It is a bus system similar to PCI or ISA. See - (and especially the web page given - there) before attempting to build an MCA bus kernel. - config UID16 bool default y @@ -57,7 +25,6 @@ config GENERIC_BUST_SPINLOCK bool - mainmenu "Linux Kernel Configuration" config ARCH_S390 @@ -115,6 +82,13 @@ int "Maximum number of CPUs (2-32)" depends on SMP default "32" + help + This allows you to specify the maximum number of CPUs which this + kernel will support. The maximum supported value is 32 and the + minimum value which makes sense is 2. + + This is purely to save memory - each supported CPU adds + approximately eight kilobytes to the kernel image. comment "I/O subsystem configuration" @@ -153,6 +127,14 @@ config PREEMPT bool "Preemptible Kernel" + help + This option reduces the latency of the kernel when reacting to + real-time or interactive events by allowing a low priority process to + be preempted even if it is in kernel mode executing a system call. + This allows applications to run more reliably even when the system is + under load. + + Say N if you are unsure. config IPL bool "Builtin IPL record support" diff -Nru a/arch/s390/Makefile b/arch/s390/Makefile --- a/arch/s390/Makefile Fri Nov 22 13:41:18 2002 +++ b/arch/s390/Makefile Fri Nov 22 13:41:18 2002 @@ -16,6 +16,7 @@ LDFLAGS := -m elf_s390 OBJCOPYFLAGS := -O binary LDFLAGS_vmlinux := -e start +LDFLAGS_BLOB := --format binary --oformat elf32-s390 CFLAGS += -pipe -fno-strength-reduce @@ -28,18 +29,14 @@ all: image listing -listing: vmlinux - @$(MAKEBOOT) listing +makeboot = $(call descend,arch/$(ARCH)/boot,$(1)) +BOOTIMAGE= arch/$(ARCH)/boot/image -MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot - -image: vmlinux - @$(MAKEBOOT) image - -install: vmlinux - @$(MAKEBOOT) BOOTIMAGE=image install +listing install image: vmlinux + +@$(call makeboot,BOOTIMAGE=$(BOOTIMAGE) $@) archclean: + +@$(call makeboot,clean) archmrproper: diff -Nru a/arch/s390/boot/Makefile b/arch/s390/boot/Makefile --- a/arch/s390/boot/Makefile Fri Nov 22 13:41:23 2002 +++ b/arch/s390/boot/Makefile Fri Nov 22 13:41:23 2002 @@ -1,28 +1,27 @@ # -# arch/s390/boot/Makefile +# Makefile for the linux s390-specific parts of the memory manager. # EXTRA_AFLAGS := -traditional include $(TOPDIR)/Rules.make -%.lnk: %.o - $(LD) $(LDFLAGS) -Ttext 0x0 -o $@ $< +quiet_cmd_listing = OBJDUMP $(echo_target) +cmd_listing = $(OBJDUMP) --disassemble --disassemble-all \ + --disassemble-zeroes --reloc vmlinux > $@ -%.boot: %.lnk - $(OBJCOPY) $(OBJCOPYFLAGS) $< $@ +$(obj)/image: vmlinux + $(call if_changed,objcopy) -image: $(TOPDIR)/vmlinux \ - iplfba.boot ipleckd.boot ipldump.boot - $(OBJCOPY) $(OBJCOPYFLAGS) $(TOPDIR)/vmlinux image - $(NM) $(TOPDIR)/vmlinux | grep -v '\(compiled\)\|\( [aUw] \)\|\(\.\)\|\(LASH[RL]DI\)' | sort > $(TOPDIR)/System.map +$(obj)/listing: vmlinux + $(call if_changed,listing) -listing: ../../../vmlinux - $(OBJDUMP) --disassemble --disassemble-all --disassemble-zeroes --reloc $(TOPDIR)/vmlinux > listing +image: $(obj)/image + +listing: $(obj)/listing clean: - rm -f image listing iplfba.boot ipleckd.boot ipldump.boot + rm -f $(obj)/image $(obj)/listing install: $(CONFIGURE) $(BOOTIMAGE) - sh -x ./install.sh $(KERNELRELEASE) $(BOOTIMAGE) $(TOPDIR)/System.map $(TOPDIR)/Kerntypes "$(INSTALL_PATH)" - + sh -x $(obj)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map Kerntypes "$(INSTALL_PATH)" diff -Nru a/arch/s390/defconfig b/arch/s390/defconfig --- a/arch/s390/defconfig Fri Nov 22 13:41:22 2002 +++ b/arch/s390/defconfig Fri Nov 22 13:41:22 2002 @@ -1,19 +1,17 @@ # # Automatically generated make config: don't edit # -# CONFIG_ISA is not set -# CONFIG_EISA is not set -# CONFIG_MCA is not set +CONFIG_MMU=y +CONFIG_SWAP=y CONFIG_UID16=y -# CONFIG_RWSEM_GENERIC_SPINLOCK is not set CONFIG_RWSEM_XCHGADD_ALGORITHM=y -# CONFIG_GENERIC_BUST_SPINLOCK is not set CONFIG_ARCH_S390=y # # Code maturity level options # CONFIG_EXPERIMENTAL=y +CONFIG_CONFIDENTIAL=y # # General setup @@ -27,7 +25,8 @@ # Loadable module support # CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_UNLOAD is not set +# CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_KMOD=y # @@ -39,13 +38,13 @@ # CONFIG_SMP=y CONFIG_MATHEMU=y -CONFIG_NR_CPUS=64 +CONFIG_NR_CPUS=32 # # I/O subsystem configuration # CONFIG_MACHCHK_WARNING=y -CONFIG_QDIO=m +CONFIG_QDIO=y # CONFIG_QDIO_PERF_STATS is not set # @@ -57,7 +56,7 @@ CONFIG_IPL_VM=y CONFIG_KCORE_ELF=y CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set +CONFIG_BINFMT_MISC=m # CONFIG_PROCESS_DEBUG is not set CONFIG_PFAULT=y # CONFIG_SHARED_KERNEL is not set @@ -65,79 +64,15 @@ # # SCSI support # -CONFIG_SCSI=m - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=m -CONFIG_SD_EXTRA_DEVS=40 -CONFIG_CHR_DEV_ST=m -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=m -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_SR_EXTRA_DEVS=10 -CONFIG_CHR_DEV_SG=m - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -CONFIG_SCSI_MULTI_LUN=y -# CONFIG_SCSI_REPORT_LUNS is not set -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y - -# -# SCSI low-level drivers -# -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AACRAID is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_PPA is not set -# CONFIG_SCSI_IMM is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR53C7xx is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_NSP32 is not set -# CONFIG_SCSI_DEBUG is not set - -# -# PCMCIA SCSI adapter support -# -# CONFIG_SCSI_PCMCIA is not set +# CONFIG_SCSI is not set # # Block device drivers # -CONFIG_BLK_DEV_LOOP=y -# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=24576 +CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y CONFIG_BLK_DEV_XPRAM=m @@ -147,66 +82,63 @@ CONFIG_DASD=y CONFIG_DASD_ECKD=y CONFIG_DASD_FBA=y -# CONFIG_DASD_DIAG is not set +CONFIG_DASD_DIAG=y # # Multi-device support (RAID and LVM) # CONFIG_MD=y -CONFIG_BLK_DEV_MD=m -# CONFIG_MD_LINEAR is not set +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m CONFIG_MD_RAID0=m CONFIG_MD_RAID1=m CONFIG_MD_RAID5=m -# CONFIG_MD_MULTIPATH is not set -# CONFIG_BLK_DEV_LVM is not set +CONFIG_MD_MULTIPATH=m +# CONFIG_BLK_DEV_DM is not set # # Character device drivers # CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 +CONFIG_UNIX98_PTY_COUNT=2048 # # S/390 character device drivers # -CONFIG_TN3270=y -CONFIG_TN3270_CONSOLE=y +# CONFIG_TN3270 is not set CONFIG_TN3215=y CONFIG_TN3215_CONSOLE=y -CONFIG_HWC=y -CONFIG_HWC_CONSOLE=y -CONFIG_HWC_CPI=m +CONFIG_SCLP=y +CONFIG_SCLP_TTY=y +CONFIG_SCLP_CONSOLE=y +CONFIG_SCLP_CPI=m CONFIG_S390_TAPE=m # # S/390 tape interface support # -CONFIG_S390_TAPE_CHAR=y CONFIG_S390_TAPE_BLOCK=y # # S/390 tape hardware support # -CONFIG_S390_TAPE_3490=m -CONFIG_S390_TAPE_3480=m +CONFIG_S390_TAPE_34XX=m # # Network device drivers # CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m CONFIG_NET_ETHERNET=y -CONFIG_TR=y +# CONFIG_TR is not set # CONFIG_FDDI is not set # # S/390 network device drivers # -CONFIG_CHANDEV=y CONFIG_HOTPLUG=y CONFIG_LCS=m CONFIG_CTC=m @@ -221,6 +153,7 @@ # CONFIG_NETFILTER is not set # CONFIG_FILTER is not set CONFIG_UNIX=y +# CONFIG_NET_KEY is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set @@ -231,19 +164,19 @@ # CONFIG_ARPD is not set # CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_XFRM_USER is not set CONFIG_IPV6=m # -# SCTP Configuration (EXPERIMENTAL) +# SCTP Configuration (EXPERIMENTAL) # -CONFIG_IPV6_SCTP__=m +CONFIG_IPV6_SCTP__=y # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set # CONFIG_VLAN_8021Q is not set # CONFIG_LLC is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_DEV_APPLETALK is not set # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set @@ -257,66 +190,70 @@ # # QoS and/or fair queueing # -# CONFIG_NET_SCHED is not set +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CBQ=m +# CONFIG_NET_SCH_HTB is not set +CONFIG_NET_SCH_CSZ=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_QOS=y +CONFIG_NET_ESTIMATOR=y +CONFIG_NET_CLS=y +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_POLICE=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set # # File systems # # CONFIG_QUOTA is not set -# CONFIG_QFMT_V1 is not set -# CONFIG_QFMT_V2 is not set # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set # CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set # CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set -CONFIG_EXT3_FS=y -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set # CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set # CONFIG_TMPFS is not set CONFIG_RAMFS=y # CONFIG_ISO9660_FS is not set -# CONFIG_JOLIET is not set -# CONFIG_ZISOFS is not set # CONFIG_JFS_FS is not set -# CONFIG_JFS_DEBUG is not set -# CONFIG_JFS_STATISTICS is not set # CONFIG_MINIX_FS is not set # CONFIG_VXFS_FS is not set # CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y -CONFIG_DEVFS_FS=y -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -# CONFIG_DEVPTS_FS is not set +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set # CONFIG_SYSV_FS is not set # CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set # CONFIG_XFS_FS is not set -# CONFIG_XFS_RT is not set -# CONFIG_XFS_QUOTA is not set # # Network File Systems @@ -324,25 +261,20 @@ # CONFIG_CODA_FS is not set # CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_ROOT_NFS is not set +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set CONFIG_NFSD=y -# CONFIG_NFSD_V3 is not set +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V4 is not set # CONFIG_NFSD_TCP is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y +# CONFIG_CIFS is not set # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set -# CONFIG_ZISOFS_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types @@ -360,8 +292,6 @@ # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set # CONFIG_EFI_PARTITION is not set -# CONFIG_SMB_NLS is not set -# CONFIG_NLS is not set # # Kernel hacking @@ -374,8 +304,19 @@ CONFIG_SECURITY_CAPABILITIES=y # +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TEST is not set + +# # Library routines # # CONFIG_CRC32 is not set -# CONFIG_ZLIB_INFLATE is not set -# CONFIG_ZLIB_DEFLATE is not set diff -Nru a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile --- a/arch/s390/kernel/Makefile Fri Nov 22 13:41:23 2002 +++ b/arch/s390/kernel/Makefile Fri Nov 22 13:41:23 2002 @@ -10,7 +10,7 @@ setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ semaphore.o reipl.o s390_ext.o debug.o -obj-$(CONFIG_MODULES) += s390_ksyms.o +obj-$(CONFIG_MODULES) += s390_ksyms.o module.o obj-$(CONFIG_SMP) += smp.o # diff -Nru a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S --- a/arch/s390/kernel/entry.S Fri Nov 22 13:41:18 2002 +++ b/arch/s390/kernel/entry.S Fri Nov 22 13:41:18 2002 @@ -474,10 +474,10 @@ .long sys_adjtimex .long sys_mprotect /* 125 */ .long sys_sigprocmask - .long sys_create_module + .long sys_ni_syscall /* old "create module" */ .long sys_init_module .long sys_delete_module - .long sys_get_kernel_syms /* 130 */ + .long sys_ni_syscall /* 130: old get_kernel_syms */ .long sys_quotactl .long sys_getpgid .long sys_fchdir @@ -514,7 +514,7 @@ .long sys_setresuid16 .long sys_getresuid16 /* 165 */ .long sys_ni_syscall /* for vm86 */ - .long sys_query_module + .long sys_ni_syscall /* old sys_query_module */ .long sys_poll .long sys_nfsservctl .long sys_setresgid16 /* 170 */ @@ -596,7 +596,11 @@ .long sys_io_submit .long sys_io_cancel .long sys_exit_group - .rept 255-248 + .long sys_epoll_create + .long sys_epoll_ctl /* 250 */ + .long sys_epoll_wait + .long sys_set_tid_address + .rept 255-252 .long sys_ni_syscall .endr diff -Nru a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/s390/kernel/module.c Fri Nov 22 13:41:23 2002 @@ -0,0 +1,174 @@ +/* + * arch/s390x/kernel/module.c - Kernel module help for s390x. + * + * S390 version + * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Arnd Bergmann (arndb@de.ibm.com) + * Martin Schwidefsky (schwidefsky@de.ibm.com) + * + * based on i386 version + * Copyright (C) 2001 Rusty Russell. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(fmt , ...) +#endif + +void *module_alloc(unsigned long size) +{ + if (size == 0) + return NULL; + return vmalloc(size); +} + +/* Free memory returned from module_alloc */ +void module_free(struct module *mod, void *module_region) +{ + vfree(module_region); + /* FIXME: If module_region == mod->init_region, trim exception + table entries. */ +} + +/* s390/s390x needs additional memory for GOT/PLT sections. */ +long module_core_size(const Elf32_Ehdr *hdr, + const Elf32_Shdr *sechdrs, + const char *secstrings, + struct module *module) +{ + // FIXME: add space needed for GOT/PLT + return module->core_size; +} + +long module_init_size(const Elf32_Ehdr *hdr, + const Elf32_Shdr *sechdrs, + const char *secstrings, + struct module *module) +{ + return module->init_size; +} + + + +int apply_relocate(Elf_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *me) +{ + unsigned int i; + ElfW(Rel) *rel = (void *)sechdrs[relsec].sh_offset; + ElfW(Sym) *sym; + ElfW(Addr) *location; + + DEBUGP("Applying relocate section %u to %u\n", relsec, + sechdrs[relsec].sh_info); + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { + /* This is where to make the change */ + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_offset + + rel[i].r_offset; + /* This is the symbol it is referring to */ + sym = (ElfW(Sym) *)sechdrs[symindex].sh_offset + + ELFW(R_SYM)(rel[i].r_info); + if (!sym->st_value) { + printk(KERN_WARNING "%s: Unknown symbol %s\n", + me->name, strtab + sym->st_name); + return -ENOENT; + } + + switch (ELF_R_TYPE(rel[i].r_info)) { + case R_390_8: /* Direct 8 bit. */ + *(u8*) location += sym->st_value; + break; + case R_390_12: /* Direct 12 bit. */ + *(u16*) location = (*(u16*) location & 0xf000) | + (sym->st_value & 0xfff); + break; + case R_390_16: /* Direct 16 bit. */ + *(u16*) location += sym->st_value; + break; + case R_390_32: /* Direct 32 bit. */ + *(u32*) location += sym->st_value; + break; + case R_390_PC16: /* PC relative 16 bit. */ + *(u16*) location += sym->st_value + - (unsigned long )location; + + case R_390_PC16DBL: /* PC relative 16 bit shifted by 1. */ + *(u16*) location += (sym->st_value + - (unsigned long )location) >> 1; + case R_390_PC32: /* PC relative 32 bit. */ + *(u32*) location += sym->st_value + - (unsigned long )location; + break; + case R_390_GOT12: /* 12 bit GOT offset. */ + case R_390_GOT16: /* 16 bit GOT offset. */ + case R_390_GOT32: /* 32 bit GOT offset. */ + // FIXME: TODO + break; + + case R_390_PLT16DBL: /* 16 bit PC rel. PLT shifted by 1. */ + case R_390_PLT32: /* 32 bit PC relative PLT address. */ + // FIXME: TODO + break; + case R_390_GLOB_DAT: /* Create GOT entry. */ + case R_390_JMP_SLOT: /* Create PLT entry. */ + *location = sym->st_value; + break; + case R_390_RELATIVE: /* Adjust by program base. */ + // FIXME: TODO + break; + case R_390_GOTOFF: /* 32 bit offset to GOT. */ + // FIXME: TODO + break; + case R_390_GOTPC: /* 32 bit PC relative offset to GOT. */ + // FIXME: TODO + break; + default: + printk(KERN_ERR "module %s: Unknown relocation: %lu\n", + me->name, + (unsigned long)ELF_R_TYPE(rel[i].r_info)); + return -ENOEXEC; + } + } + return 0; +} + +int apply_relocate_add(Elf32_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *me) +{ + printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", + me->name); + return -ENOEXEC; +} + +int module_finalize(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, + struct module *me) +{ + return 0; +} diff -Nru a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c --- a/arch/s390/kernel/setup.c Fri Nov 22 13:41:18 2002 +++ b/arch/s390/kernel/setup.c Fri Nov 22 13:41:18 2002 @@ -164,9 +164,9 @@ static int __init conmode_setup(char *str) { -#if defined(CONFIG_HWC_CONSOLE) - if (strncmp(str, "hwc", 4) == 0) - SET_CONSOLE_HWC; +#if defined(CONFIG_SCLP_CONSOLE) + if (strncmp(str, "hwc", 4) == 0 || strncmp(str, "sclp", 5) == 0) + SET_CONSOLE_SCLP; #endif #if defined(CONFIG_TN3215_CONSOLE) if (strncmp(str, "3215", 5) == 0) @@ -198,8 +198,8 @@ */ cpcmd("TERM CONMODE 3215", NULL, 0); if (ptr == NULL) { -#if defined(CONFIG_HWC_CONSOLE) - SET_CONSOLE_HWC; +#if defined(CONFIG_SCLP_CONSOLE) + SET_CONSOLE_SCLP; #endif return; } @@ -208,16 +208,16 @@ SET_CONSOLE_3270; #elif defined(CONFIG_TN3215_CONSOLE) SET_CONSOLE_3215; -#elif defined(CONFIG_HWC_CONSOLE) - SET_CONSOLE_HWC; +#elif defined(CONFIG_SCLP_CONSOLE) + SET_CONSOLE_SCLP; #endif } else if (strncmp(ptr + 8, "3215", 4) == 0) { #if defined(CONFIG_TN3215_CONSOLE) SET_CONSOLE_3215; #elif defined(CONFIG_TN3270_CONSOLE) SET_CONSOLE_3270; -#elif defined(CONFIG_HWC_CONSOLE) - SET_CONSOLE_HWC; +#elif defined(CONFIG_SCLP_CONSOLE) + SET_CONSOLE_SCLP; #endif } } else if (MACHINE_IS_P390) { @@ -227,8 +227,8 @@ SET_CONSOLE_3270; #endif } else { -#if defined(CONFIG_HWC_CONSOLE) - SET_CONSOLE_HWC; +#if defined(CONFIG_SCLP_CONSOLE) + SET_CONSOLE_SCLP; #endif } } diff -Nru a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c --- a/arch/s390/kernel/smp.c Fri Nov 22 13:41:17 2002 +++ b/arch/s390/kernel/smp.c Fri Nov 22 13:41:17 2002 @@ -274,7 +274,7 @@ void do_ext_call_interrupt(struct pt_regs *regs, __u16 code) { - int bits; + unsigned long bits; /* * handle bit signal external calls @@ -282,9 +282,7 @@ * For the ec_schedule signal we have to do nothing. All the work * is done automatically when we return from the interrupt. */ - do { - bits = atomic_read(&S390_lowcore.ext_call_fast); - } while (atomic_compare_and_swap(bits,0,&S390_lowcore.ext_call_fast)); + bits = xchg(&S390_lowcore.ext_call_fast, 0); if (test_bit(ec_call_function, &bits)) do_call_function(); @@ -296,13 +294,12 @@ */ static sigp_ccode smp_ext_bitcall(int cpu, ec_bit_sig sig) { - struct _lowcore *lowcore = lowcore_ptr[cpu]; sigp_ccode ccode; /* * Set signaling bit in lowcore of target cpu and kick it */ - atomic_set_mask(1<ext_call_fast); + set_bit(sig, (unsigned long *) &lowcore_ptr[cpu]->ext_call_fast); ccode = signal_processor(cpu, sigp_external_call); return ccode; } @@ -323,7 +320,7 @@ /* * Set signaling bit in lowcore of target cpu and kick it */ - atomic_set_mask(1<ext_call_fast); + set_bit(sig, (unsigned long *) &lowcore_ptr[i]->ext_call_fast); while (signal_processor(i, sigp_external_call) == sigp_busy) udelay(10); } diff -Nru a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c --- a/arch/s390/kernel/time.c Fri Nov 22 13:41:17 2002 +++ b/arch/s390/kernel/time.c Fri Nov 22 13:41:17 2002 @@ -140,7 +140,6 @@ */ static void do_comparator_interrupt(struct pt_regs *regs, __u16 error_code) { - int cpu = smp_processor_id(); __u64 tmp; __u32 ticks; diff -Nru a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c --- a/arch/s390/kernel/traps.c Fri Nov 22 13:41:18 2002 +++ b/arch/s390/kernel/traps.c Fri Nov 22 13:41:18 2002 @@ -72,8 +72,8 @@ #ifdef CONFIG_MODULES -extern struct module *module_list; -extern struct module kernel_module; +/* FIXME: Accessed without a lock --RR */ +extern struct list_head modules; static inline int kernel_text_address(unsigned long addr) { @@ -84,11 +84,11 @@ addr <= (unsigned long) &_etext) return 1; - for (mod = module_list; mod != &kernel_module; mod = mod->next) { + list_for_each_entry(mod, &modules, list) { /* mod_bound tests for addr being inside the vmalloc'ed * module area. Of course it'd be better to test only * for the .text subset... */ - if (mod_bound(addr, 0, mod)) { + if (mod_bound((void*)addr, 0, mod)) { retval = 1; break; } diff -Nru a/arch/s390/lib/uaccess.S b/arch/s390/lib/uaccess.S --- a/arch/s390/lib/uaccess.S Fri Nov 22 13:41:21 2002 +++ b/arch/s390/lib/uaccess.S Fri Nov 22 13:41:21 2002 @@ -1,9 +1,9 @@ /* * arch/s390/lib/uaccess.S - * fixup routines for copy_{from|to}_user functions. + * __copy_{from|to}_user functions. * * s390 - * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Copyright (C) 2000,2002 IBM Deutschland Entwicklung GmbH, IBM Corporation * Authors(s): Martin Schwidefsky (schwidefsky@de.ibm.com) * * These functions have standard call interface @@ -22,17 +22,23 @@ 1: sacf 0 lr %r2,%r5 br %r14 -2: sll %r4,1 - srl %r4,1 - lhi %r3,-4096 - sll %r3,1 - srl %r3,1 - n %r3,__LC_TRANS_EXC_ADDR - sr %r3,%r4 - jm 1b - j 0b +2: lhi %r1,-4096 + lr %r3,%r4 + slr %r3,%r1 # %r3 = %r4 + 4096 + nr %r3,%r1 # %r3 = (%r4 + 4096) & -4096 + slr %r3,%r4 # %r3 = #bytes to next user page boundary + clr %r5,%r3 # copy crosses next page boundary ? + jnh 1b # no, this page fauled + # The page after the current user page might have faulted. + # We cant't find out which page because the program check handler + # might have callled schedule, destroying all lowcore information. + # We retry with the shortened length. +3: mvcle %r2,%r4,0 + jo 3b + j 1b .section __ex_table,"a" .long 0b,2b + .long 3b,1b .previous .align 4 @@ -46,17 +52,23 @@ 1: sacf 0 lr %r2,%r3 br %r14 -2: sll %r4,1 - srl %r4,1 - lhi %r5,-4096 - sll %r5,1 - srl %r5,1 - n %r5,__LC_TRANS_EXC_ADDR - sr %r5,%r4 - jm 1b - j 0b +2: lhi %r1,-4096 + lr %r5,%r4 + slr %r5,%r1 # %r5 = %r4 + 4096 + nr %r5,%r1 # %r5 = (%r4 + 4096) & -4096 + slr %r5,%r4 # %r5 = #bytes to next user page boundary + clr %r3,%r5 # copy crosses next page boundary ? + jnh 1b # no, the current page fauled + # The page after the current user page might have faulted. + # We cant't find out which page because the program check handler + # might have callled schedule, destroying all lowcore information. + # We retry with the shortened length. +3: mvcle %r4,%r2,0 + jo 3b + j 1b .section __ex_table,"a" - .long 0b,2b + .long 0b,2b + .long 3b,1b .previous .align 4 @@ -71,18 +83,26 @@ 0: mvcle %r4,%r2,0 jo 0b 1: sacf 0 - lr %r2,%r3 br %r14 -2: sll %r4,1 - srl %r4,1 - lhi %r5,-4096 - sll %r5,1 - srl %r5,1 - n %r5,__LC_TRANS_EXC_ADDR - sr %r5,%r4 - jm 1b - j 0b +2: lr %r2,%r5 + lhi %r1,-4096 + slr %r5,%r1 # %r5 = %r4 + 4096 + nr %r5,%r1 # %r5 = (%r4 + 4096) & -4096 + slr %r5,%r4 # %r5 = #bytes to next user page boundary + clr %r2,%r5 # copy crosses next page boundary ? + jnh 1b # no, the current page fauled + # The page after the current user page might have faulted. + # We cant't find out which page because the program check handler + # might have callled schedule, destroying all lowcore information. + # We retry with the shortened length. + slr %r2,%r5 +3: mvcle %r4,%r2,0 + jo 3b + j 1b +4: alr %r2,%r5 + j 1b .section __ex_table,"a" - .long 0b,2b + .long 0b,2b + .long 3b,4b .previous diff -Nru a/arch/s390/mm/extable.c b/arch/s390/mm/extable.c --- a/arch/s390/mm/extable.c Fri Nov 22 13:41:22 2002 +++ b/arch/s390/mm/extable.c Fri Nov 22 13:41:22 2002 @@ -42,6 +42,7 @@ unsigned long search_exception_table(unsigned long addr) { + struct list_head *i; unsigned long ret = 0; #ifndef CONFIG_MODULES @@ -52,16 +53,17 @@ return ret; #else unsigned long flags; - /* The kernel is the last "module" -- no need to treat it special. */ - struct module *mp; addr &= 0x7fffffff; /* remove amode bit from address */ + /* The kernel is the last "module" -- no need to treat it special. */ spin_lock_irqsave(&modlist_lock, flags); - for (mp = module_list; mp != NULL; mp = mp->next) { - if (mp->ex_table_start == NULL || !(mp->flags&(MOD_RUNNING|MOD_INITIALIZING))) + list_for_each(i, &extables) { + struct exception_table *ex + = list_entry(i, struct exception_table, list); + if (ex->num_entries == 0) continue; - ret = search_one_table(mp->ex_table_start, - mp->ex_table_end - 1, addr); + ret = search_one_table(ex->entry, + ex->entry + ex->num_entries - 1, addr); if (ret) { ret = ret | PSW_ADDR_AMODE31; break; diff -Nru a/arch/s390/mm/init.c b/arch/s390/mm/init.c --- a/arch/s390/mm/init.c Fri Nov 22 13:41:22 2002 +++ b/arch/s390/mm/init.c Fri Nov 22 13:41:22 2002 @@ -188,7 +188,7 @@ free_page(addr); totalram_pages++; } - printk ("Freeing unused kernel memory: %dk freed\n", + printk ("Freeing unused kernel memory: %ldk freed\n", ((unsigned long)&__init_end - (unsigned long)&__init_begin) >> 10); } diff -Nru a/arch/s390/vmlinux.lds.S b/arch/s390/vmlinux.lds.S --- a/arch/s390/vmlinux.lds.S Fri Nov 22 13:41:18 2002 +++ b/arch/s390/vmlinux.lds.S Fri Nov 22 13:41:18 2002 @@ -25,6 +25,7 @@ __ex_table : { *(__ex_table) } __stop___ex_table = .; + . = ALIGN(64); __start___ksymtab = .; /* Kernel symbol table */ __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; @@ -40,18 +41,31 @@ CONSTRUCTORS } + . = ALIGN(4096); + __nosave_begin = .; + .data_nosave : { *(.data.nosave) } + . = ALIGN(4096); + __nosave_end = .; + + . = ALIGN(4096); + .data.page_aligned : { *(.data.idt) } + + . = ALIGN(32); + .data.cacheline_aligned : { *(.data.cacheline_aligned) } + _edata = .; /* End of data section */ . = ALIGN(8192); /* init_task */ .data.init_task : { *(.data.init_task) } + /* will be freed after init */ . = ALIGN(4096); /* Init code and data */ __init_begin = .; - .text.init : { *(.text.init) } - .data.init : { *(.data.init) } + .init.text : { *(.init.text) } + .init.data : { *(.init.data) } . = ALIGN(256); __setup_start = .; - .setup.init : { *(.setup.init) } + .init.setup : { *(.init.setup) } __setup_end = .; __initcall_start = .; .initcall.init : { @@ -65,23 +79,29 @@ } __initcall_end = .; . = ALIGN(256); + __initramfs_start = .; + .init.ramfs : { *(.init.initramfs) } + __initramfs_end = .; + . = ALIGN(256); __per_cpu_start = .; .data.percpu : { *(.data.percpu) } __per_cpu_end = .; . = ALIGN(4096); __init_end = .; + /* freed after init ends here */ - . = ALIGN(32); - .data.cacheline_aligned : { *(.data.cacheline_aligned) } + __bss_start = .; /* BSS */ + .bss : { *(.bss) } + __bss_stop = .; - . = ALIGN(4096); - .data.page_aligned : { *(.data.idt) } + _end = . ; - __bss_start = .; /* BSS */ - .bss : { - *(.bss) + /* Sections to be discarded */ + /DISCARD/ : { + *(.exit.text) + *(.exit.data) + *(.exitcall.exit) } - _end = . ; /* Stabs debugging sections. */ .stab 0 : { *(.stab) } diff -Nru a/arch/s390x/Kconfig b/arch/s390x/Kconfig --- a/arch/s390x/Kconfig Fri Nov 22 13:41:20 2002 +++ b/arch/s390x/Kconfig Fri Nov 22 13:41:20 2002 @@ -11,38 +11,6 @@ bool default y -config ISA - bool - help - Find out whether you have ISA slots on your motherboard. ISA is the - name of a bus system, i.e. the way the CPU talks to the other stuff - inside your box. Other bus systems are PCI, EISA, MicroChannel - (MCA) or VESA. ISA is an older system, now being displaced by PCI; - newer boards don't support it. If you have ISA, say Y, otherwise N. - -config EISA - bool - ---help--- - The Extended Industry Standard Architecture (EISA) bus was - developed as an open alternative to the IBM MicroChannel bus. - - The EISA bus provided some of the features of the IBM MicroChannel - bus while maintaining backward compatibility with cards made for - the older ISA bus. The EISA bus saw limited use between 1988 and - 1995 when it was made obsolete by the PCI bus. - - Say Y here if you are building a kernel for an EISA-based machine. - - Otherwise, say N. - -config MCA - bool - help - MicroChannel Architecture is found in some IBM PS/2 machines and - laptops. It is a bus system similar to PCI or ISA. See - (and especially the web page given - there) before attempting to build an MCA bus kernel. - config RWSEM_GENERIC_SPINLOCK bool @@ -108,6 +76,13 @@ int "Maximum number of CPUs (2-64)" depends on SMP default "64" + help + This allows you to specify the maximum number of CPUs which this + kernel will support. The maximum supported value is 64 and the + minimum value which makes sense is 2. + + This is purely to save memory - each supported CPU adds + approximately sixteen kilobytes to the kernel image. config S390_SUPPORT bool "Kernel support for 31 bit emulation" @@ -161,6 +136,14 @@ config PREEMPT bool "Preemptible Kernel" + help + This option reduces the latency of the kernel when reacting to + real-time or interactive events by allowing a low priority process to + be preempted even if it is in kernel mode executing a system call. + This allows applications to run more reliably even when the system is + under load. + + Say N if you are unsure. config IPL bool "Builtin IPL record support" diff -Nru a/arch/s390x/Makefile b/arch/s390x/Makefile --- a/arch/s390x/Makefile Fri Nov 22 13:41:20 2002 +++ b/arch/s390x/Makefile Fri Nov 22 13:41:20 2002 @@ -16,7 +16,8 @@ LDFLAGS := -m elf64_s390 OBJCOPYFLAGS := -O binary LDFLAGS_vmlinux := -e start -MODFLAGS += -fpic +MODFLAGS += -fpic -D__PIC__ +LDFLAGS_BLOB := --format binary --oformat elf64-s390 CFLAGS += -pipe -fno-strength-reduce @@ -28,18 +29,14 @@ all: image listing -listing: vmlinux - @$(MAKEBOOT) listing +makeboot = $(call descend,arch/$(ARCH)/boot,$(1)) +BOOTIMAGE= arch/$(ARCH)/boot/image -MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot - -image: vmlinux - @$(MAKEBOOT) image - -install: vmlinux - @$(MAKEBOOT) BOOTIMAGE=image install +listing install image: vmlinux + +@$(call makeboot,BOOTIMAGE=$(BOOTIMAGE) $@) archclean: + +@$(call makeboot,clean) archmrproper: diff -Nru a/arch/s390x/boot/Makefile b/arch/s390x/boot/Makefile --- a/arch/s390x/boot/Makefile Fri Nov 22 13:41:20 2002 +++ b/arch/s390x/boot/Makefile Fri Nov 22 13:41:20 2002 @@ -6,22 +6,22 @@ include $(TOPDIR)/Rules.make -%.lnk: %.o - $(LD) -Ttext 0x0 -o $@ $< +quiet_cmd_listing = OBJDUMP $(echo_target) +cmd_listing = $(OBJDUMP) --disassemble --disassemble-all \ + --disassemble-zeroes --reloc vmlinux > $@ -%.boot: %.lnk - $(OBJCOPY) $(OBJCOPYFLAGS) $< $@ +$(obj)/image: vmlinux + $(call if_changed,objcopy) -image: $(TOPDIR)/vmlinux \ - iplfba.boot ipleckd.boot ipldump.boot - $(OBJCOPY) $(OBJCOPYFLAGS) $< $@ - $(NM) $(TOPDIR)/vmlinux | grep -v '\(compiled\)\|\( [aUw] \)\|\(\.\)\|\(LASH[RL]DI\)' | sort > $(TOPDIR)/System.map +$(obj)/listing: vmlinux + $(call if_changed,listing) -listing: ../../../vmlinux - $(OBJDUMP) --disassemble --disassemble-all --disassemble-zeroes --reloc $(TOPDIR)/vmlinux > listing +image: $(obj)/image + +listing: $(obj)/listing clean: - rm -f image listing iplfba.boot ipleckd.boot ipldump.boot + rm -f $(obj)/image $(obj)/listing install: $(CONFIGURE) $(BOOTIMAGE) - sh -x ./install.sh $(KERNELRELEASE) $(BOOTIMAGE) $(TOPDIR)/System.map $(TOPDIR)/Kerntypes "$(INSTALL_PATH)" + sh -x $(obj)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map Kerntypes "$(INSTALL_PATH)" diff -Nru a/arch/s390x/defconfig b/arch/s390x/defconfig --- a/arch/s390x/defconfig Fri Nov 22 13:41:17 2002 +++ b/arch/s390x/defconfig Fri Nov 22 13:41:17 2002 @@ -1,12 +1,9 @@ # # Automatically generated make config: don't edit # -# CONFIG_ISA is not set -# CONFIG_EISA is not set -# CONFIG_MCA is not set -# CONFIG_RWSEM_GENERIC_SPINLOCK is not set +CONFIG_MMU=y +CONFIG_SWAP=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y -# CONFIG_GENERIC_BUST_SPINLOCK is not set CONFIG_ARCH_S390=y CONFIG_ARCH_S390X=y @@ -14,6 +11,7 @@ # Code maturity level options # CONFIG_EXPERIMENTAL=y +CONFIG_CONFIDENTIAL=y # # General setup @@ -27,7 +25,8 @@ # Loadable module support # CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_UNLOAD is not set +# CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_KMOD=y # @@ -38,9 +37,9 @@ # Processor type and features # CONFIG_SMP=y +CONFIG_NR_CPUS=64 CONFIG_S390_SUPPORT=y CONFIG_BINFMT_ELF32=y -CONFIG_NR_CPUS=64 # # I/O subsystem configuration @@ -58,7 +57,7 @@ CONFIG_IPL_VM=y CONFIG_KCORE_ELF=y CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set +CONFIG_BINFMT_MISC=m # CONFIG_PROCESS_DEBUG is not set CONFIG_PFAULT=y # CONFIG_SHARED_KERNEL is not set @@ -72,18 +71,16 @@ # SCSI support type (disk, tape, CD-ROM) # CONFIG_BLK_DEV_SD=m -CONFIG_SD_EXTRA_DEVS=40 CONFIG_CHR_DEV_ST=m -# CONFIG_CHR_DEV_OSST is not set +CONFIG_CHR_DEV_OSST=m CONFIG_BLK_DEV_SR=m -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_SR_EXTRA_DEVS=10 +CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # -CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_MULTI_LUN is not set # CONFIG_SCSI_REPORT_LUNS is not set CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y @@ -91,41 +88,36 @@ # # SCSI low-level drivers # -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AACRAID is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_PPA is not set -# CONFIG_SCSI_IMM is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR53C7xx is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=253 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set +CONFIG_SCSI_AIC7XXX_OLD=m +CONFIG_SCSI_DPT_I2O=m +CONFIG_SCSI_ADVANSYS=m +CONFIG_SCSI_IN2000=m +CONFIG_SCSI_MEGARAID=m +CONFIG_SCSI_BUSLOGIC=m +# CONFIG_SCSI_OMIT_FLASHPOINT is not set +CONFIG_SCSI_EATA=m +CONFIG_SCSI_EATA_TAGGED_QUEUE=y +# CONFIG_SCSI_EATA_LINKED_COMMANDS is not set +CONFIG_SCSI_EATA_MAX_TAGS=16 +CONFIG_SCSI_EATA_DMA=m +CONFIG_SCSI_EATA_PIO=m +CONFIG_SCSI_FUTURE_DOMAIN=m +CONFIG_SCSI_GDTH=m +CONFIG_SCSI_GENERIC_NCR5380=m +# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set +# CONFIG_SCSI_GENERIC_NCR53C400 is not set +CONFIG_SCSI_PCI2000=m +CONFIG_SCSI_PCI2220I=m +CONFIG_SCSI_U14_34F=m +# CONFIG_SCSI_U14_34F_LINKED_COMMANDS is not set +CONFIG_SCSI_U14_34F_MAX_TAGS=8 # CONFIG_SCSI_NSP32 is not set -# CONFIG_SCSI_DEBUG is not set +CONFIG_SCSI_DEBUG=m # # PCMCIA SCSI adapter support @@ -135,10 +127,10 @@ # # Block device drivers # -CONFIG_BLK_DEV_LOOP=y -# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=24576 +CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y CONFIG_BLK_DEV_XPRAM=m @@ -148,65 +140,63 @@ CONFIG_DASD=y CONFIG_DASD_ECKD=y CONFIG_DASD_FBA=y +# CONFIG_DASD_DIAG is not set # # Multi-device support (RAID and LVM) # CONFIG_MD=y -CONFIG_BLK_DEV_MD=m -# CONFIG_MD_LINEAR is not set +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m CONFIG_MD_RAID0=m CONFIG_MD_RAID1=m CONFIG_MD_RAID5=m -# CONFIG_MD_MULTIPATH is not set -# CONFIG_BLK_DEV_LVM is not set +CONFIG_MD_MULTIPATH=m +# CONFIG_BLK_DEV_DM is not set # # Character device drivers # CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 +CONFIG_UNIX98_PTY_COUNT=2048 # # S/390 character device drivers # -CONFIG_TN3270=y -CONFIG_TN3270_CONSOLE=y +# CONFIG_TN3270 is not set CONFIG_TN3215=y CONFIG_TN3215_CONSOLE=y -CONFIG_HWC=y -CONFIG_HWC_CONSOLE=y -CONFIG_HWC_CPI=m +CONFIG_SCLP=y +CONFIG_SCLP_TTY=y +CONFIG_SCLP_CONSOLE=y +CONFIG_SCLP_CPI=m CONFIG_S390_TAPE=m # # S/390 tape interface support # -CONFIG_S390_TAPE_CHAR=y CONFIG_S390_TAPE_BLOCK=y # # S/390 tape hardware support # -CONFIG_S390_TAPE_3490=m -CONFIG_S390_TAPE_3480=m +CONFIG_S390_TAPE_34XX=m # # Network device drivers # CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m CONFIG_NET_ETHERNET=y -CONFIG_TR=y +# CONFIG_TR is not set # CONFIG_FDDI is not set # # S/390 network device drivers # -CONFIG_CHANDEV=y CONFIG_HOTPLUG=y CONFIG_LCS=m CONFIG_CTC=m @@ -221,6 +211,7 @@ # CONFIG_NETFILTER is not set # CONFIG_FILTER is not set CONFIG_UNIX=y +# CONFIG_NET_KEY is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set @@ -231,19 +222,19 @@ # CONFIG_ARPD is not set # CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set -# CONFIG_IPV6 is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_XFRM_USER is not set +CONFIG_IPV6=m # -# SCTP Configuration (EXPERIMENTAL) +# SCTP Configuration (EXPERIMENTAL) # CONFIG_IPV6_SCTP__=y # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set # CONFIG_VLAN_8021Q is not set # CONFIG_LLC is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_DEV_APPLETALK is not set # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set @@ -257,66 +248,73 @@ # # QoS and/or fair queueing # -# CONFIG_NET_SCHED is not set +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CBQ=m +# CONFIG_NET_SCH_HTB is not set +CONFIG_NET_SCH_CSZ=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_QOS=y +CONFIG_NET_ESTIMATOR=y +CONFIG_NET_CLS=y +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_POLICE=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set # # File systems # -# CONFIG_QUOTA is not set +CONFIG_QUOTA=y # CONFIG_QFMT_V1 is not set # CONFIG_QFMT_V2 is not set +CONFIG_QUOTACTL=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set # CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set # CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set -CONFIG_EXT3_FS=y -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set # CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set # CONFIG_TMPFS is not set CONFIG_RAMFS=y # CONFIG_ISO9660_FS is not set -# CONFIG_JOLIET is not set -# CONFIG_ZISOFS is not set # CONFIG_JFS_FS is not set -# CONFIG_JFS_DEBUG is not set -# CONFIG_JFS_STATISTICS is not set # CONFIG_MINIX_FS is not set # CONFIG_VXFS_FS is not set # CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y -CONFIG_DEVFS_FS=y -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -# CONFIG_DEVPTS_FS is not set +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set # CONFIG_SYSV_FS is not set # CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set # CONFIG_XFS_FS is not set -# CONFIG_XFS_RT is not set -# CONFIG_XFS_QUOTA is not set # # Network File Systems @@ -324,25 +322,20 @@ # CONFIG_CODA_FS is not set # CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_ROOT_NFS is not set +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set CONFIG_NFSD=y -# CONFIG_NFSD_V3 is not set +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V4 is not set # CONFIG_NFSD_TCP is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y +# CONFIG_CIFS is not set # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set -# CONFIG_ZISOFS_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types @@ -360,8 +353,6 @@ # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set # CONFIG_EFI_PARTITION is not set -# CONFIG_SMB_NLS is not set -# CONFIG_NLS is not set # # Kernel hacking @@ -374,8 +365,19 @@ CONFIG_SECURITY_CAPABILITIES=y # +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TEST is not set + +# # Library routines # # CONFIG_CRC32 is not set -# CONFIG_ZLIB_INFLATE is not set -# CONFIG_ZLIB_DEFLATE is not set diff -Nru a/arch/s390x/kernel/Makefile b/arch/s390x/kernel/Makefile --- a/arch/s390x/kernel/Makefile Fri Nov 22 13:41:19 2002 +++ b/arch/s390x/kernel/Makefile Fri Nov 22 13:41:19 2002 @@ -12,7 +12,7 @@ setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ semaphore.o reipl.o s390_ext.o debug.o -obj-$(CONFIG_MODULES) += s390_ksyms.o +obj-$(CONFIG_MODULES) += s390_ksyms.o module.o obj-$(CONFIG_SMP) += smp.o # diff -Nru a/arch/s390x/kernel/entry.S b/arch/s390x/kernel/entry.S --- a/arch/s390x/kernel/entry.S Fri Nov 22 13:41:18 2002 +++ b/arch/s390x/kernel/entry.S Fri Nov 22 13:41:18 2002 @@ -503,10 +503,10 @@ .long SYSCALL(sys_adjtimex,sys32_adjtimex_wrapper) .long SYSCALL(sys_mprotect,sys32_mprotect_wrapper) /* 125 */ .long SYSCALL(sys_sigprocmask,sys32_sigprocmask_wrapper) - .long SYSCALL(sys_create_module,sys32_create_module_wrapper) + .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old "create module" */ .long SYSCALL(sys_init_module,sys32_init_module_wrapper) .long SYSCALL(sys_delete_module,sys32_delete_module_wrapper) - .long SYSCALL(sys_get_kernel_syms,sys32_get_kernel_syms_wrapper) /* 130 */ + .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 130: old get_kernel_syms */ .long SYSCALL(sys_quotactl,sys32_quotactl_wrapper) .long SYSCALL(sys_getpgid,sys32_getpgid_wrapper) .long SYSCALL(sys_fchdir,sys32_fchdir_wrapper) @@ -543,7 +543,7 @@ .long SYSCALL(sys_ni_syscall,sys32_setresuid16_wrapper) /* old setresuid16 syscall */ .long SYSCALL(sys_ni_syscall,sys32_getresuid16_wrapper) /* old getresuid16 syscall */ .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* for vm86 */ - .long SYSCALL(sys_query_module,sys32_query_module_wrapper) + .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old sys_query_module */ .long SYSCALL(sys_poll,sys32_poll_wrapper) .long SYSCALL(sys_nfsservctl,sys32_nfsservctl_wrapper) .long SYSCALL(sys_ni_syscall,sys32_setresgid16_wrapper) /* old setresgid16 syscall */ @@ -625,7 +625,11 @@ .long SYSCALL(sys_io_submit,sys_ni_syscall) .long SYSCALL(sys_io_cancel,sys_ni_syscall) .long SYSCALL(sys_exit_group,sys32_exit_group_wrapper) - .rept 255-248 + .long SYSCALL(sys_epoll_create,sys_ni_syscall) + .long SYSCALL(sys_epoll_ctl,sys_ni_syscall) + .long SYSCALL(sys_epoll_wait,sys_ni_syscall) + .long SYSCALL(sys_set_tid_address,sys_ni_syscall) + .rept 255-252 .long SYSCALL(sys_ni_syscall,sys_ni_syscall) .endr diff -Nru a/arch/s390x/kernel/ioctl32.c b/arch/s390x/kernel/ioctl32.c --- a/arch/s390x/kernel/ioctl32.c Fri Nov 22 13:41:23 2002 +++ b/arch/s390x/kernel/ioctl32.c Fri Nov 22 13:41:23 2002 @@ -1024,6 +1024,8 @@ static void ioctl32_insert(struct ioctl32_list *entry) { int hash = ioctl32_hash(entry->handler.cmd); + + entry->next = 0; if (!ioctl32_hash_table[hash]) ioctl32_hash_table[hash] = entry; else { @@ -1032,8 +1034,49 @@ while (l->next) l = l->next; l->next = entry; - entry->next = 0; } +} + +int register_ioctl32_conversion(unsigned int cmd, + int (*handler)(unsigned int, unsigned int, + unsigned long, struct file *)) +{ + struct ioctl32_list *l, *new; + int hash; + + hash = ioctl32_hash(cmd); + for (l = ioctl32_hash_table[hash]; l != NULL; l = l->next) + if (l->handler.cmd == cmd) + return -EBUSY; + new = kmalloc(sizeof(struct ioctl32_list), GFP_KERNEL); + if (new == NULL) + return -ENOMEM; + new->handler.cmd = cmd; + new->handler.function = (void *) handler; + ioctl32_insert(new); + return 0; +} + +int unregister_ioctl32_conversion(unsigned int cmd) +{ + struct ioctl32_list *p, *l; + int hash; + + hash = ioctl32_hash(cmd); + p = NULL; + for (l = ioctl32_hash_table[hash]; l != NULL; l = l->next) { + if (l->handler.cmd == cmd) + break; + p = l; + } + if (l == NULL) + return -ENOENT; + if (p == NULL) + ioctl32_hash_table[hash] = l->next; + else + p->next = l->next; + kfree(l); + return 0; } static int __init init_ioctl32(void) diff -Nru a/arch/s390x/kernel/linux32.c b/arch/s390x/kernel/linux32.c --- a/arch/s390x/kernel/linux32.c Fri Nov 22 13:41:22 2002 +++ b/arch/s390x/kernel/linux32.c Fri Nov 22 13:41:22 2002 @@ -2492,8 +2492,23 @@ CMSG32_ALIGN(sizeof(struct cmsghdr32))); kcmsg32->cmsg_len = clen32; + switch (kcmsg32->cmsg_type) { + /* + * The timestamp type's data needs to be converted + * from 64-bit time values to 32-bit time values + */ + case SO_TIMESTAMP: { + __kernel_time_t32* ptr_time32 = CMSG32_DATA(kcmsg32); + __kernel_time_t* ptr_time = CMSG_DATA(ucmsg); + get_user(*ptr_time32, ptr_time); + get_user(*(ptr_time32+1), ptr_time+1); + kcmsg32->cmsg_len -= 2*(sizeof(__kernel_time_t) - + sizeof(__kernel_time_t32)); + } + default:; + } ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64)); - wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32)); + wp = (((char *)kcmsg32) + CMSG32_ALIGN(kcmsg32->cmsg_len)); } /* Copy back fixed up data, and adjust pointers. */ @@ -2516,148 +2531,6 @@ kmsg->msg_control = (void *) orig_cmsg_uptr; } -#if 0 -asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags) -{ - struct socket *sock; - char address[MAX_SOCK_ADDR]; - struct iovec iov[UIO_FASTIOV]; - unsigned char ctl[sizeof(struct cmsghdr) + 20]; - unsigned char *ctl_buf = ctl; - struct msghdr kern_msg; - int err, total_len; - - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ); - if (err < 0) - goto out; - total_len = err; - - if(kern_msg.msg_controllen) { - err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl)); - if(err) - goto out_freeiov; - ctl_buf = kern_msg.msg_control; - } - kern_msg.msg_flags = user_flags; - - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - if (sock->file->f_flags & O_NONBLOCK) - kern_msg.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &kern_msg, total_len); - sockfd_put(sock); - } - - /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */ - if(ctl_buf != ctl) - kfree(ctl_buf); -out_freeiov: - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: - return err; -} - -asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags) -{ - struct iovec iovstack[UIO_FASTIOV]; - struct msghdr kern_msg; - char addr[MAX_SOCK_ADDR]; - struct socket *sock; - struct iovec *iov = iovstack; - struct sockaddr *uaddr; - int *uaddr_len; - unsigned long cmsg_ptr; - int err, total_len, len = 0; - - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - - uaddr = kern_msg.msg_name; - uaddr_len = &user_msg->msg_namelen; - err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE); - if (err < 0) - goto out; - total_len = err; - - cmsg_ptr = (unsigned long) kern_msg.msg_control; - kern_msg.msg_flags = 0; - - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - struct sock_iocb *si; - struct kiocb iocb; - - if (sock->file->f_flags & O_NONBLOCK) - user_flags |= MSG_DONTWAIT; - - init_sync_kiocb(&iocb, NULL); - si = kiocb_to_siocb(&iocb); - si->sock = sock; - si->scm = &si->async_scm; - si->msg = &kern_msg; - si->size = total_len; - si->flags = user_flags; - memset(si->scm, 0, sizeof(*si->scm)); - - err = sock->ops->recvmsg(&iocb, sock, &kern_msg, total_len, - user_flags, si->scm); - if (-EIOCBQUEUED == err) - err = wait_on_sync_kiocb(&iocb); - - if(err >= 0) { - len = err; - if(!kern_msg.msg_control) { - if(sock->passcred || si->scm->fp) - kern_msg.msg_flags |= MSG_CTRUNC; - if(si->scm->fp) - __scm_destroy(si->scm); - } else { - /* If recvmsg processing itself placed some - * control messages into user space, it's is - * using 64-bit CMSG processing, so we need - * to fix it up before we tack on more stuff. - */ - if((unsigned long) kern_msg.msg_control != cmsg_ptr) - cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr); - - /* Wheee... */ - if(sock->passcred) - put_cmsg32(&kern_msg, - SOL_SOCKET, SCM_CREDENTIALS, - sizeof(si->scm->creds), - &si->scm->creds); - if(si->scm->fp != NULL) - scm_detach_fds32(&kern_msg, si->scm); - } - } - sockfd_put(sock); - } - - if(uaddr != NULL && err >= 0) - err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len); - if(cmsg_ptr != 0 && err >= 0) { - unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control); - __kernel_size_t32 uclen = (__kernel_size_t32) (ucmsg_ptr - cmsg_ptr); - err |= __put_user(uclen, &user_msg->msg_controllen); - } - if(err >= 0) - err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags); - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: - if(err < 0) - return err; - return len; -} -#endif - /* * BSD sendmsg interface */ @@ -2742,6 +2615,63 @@ return err; } +static __inline__ void +scm_recv32(struct socket *sock, struct msghdr *msg, + struct scm_cookie *scm, int flags, unsigned long cmsg_ptr) +{ + if(!msg->msg_control) + { + if(sock->passcred || scm->fp) + msg->msg_flags |= MSG_CTRUNC; + scm_destroy(scm); + return; + } + /* If recvmsg processing itself placed some + * control messages into user space, it's is + * using 64-bit CMSG processing, so we need + * to fix it up before we tack on more stuff. + */ + if((unsigned long) msg->msg_control != cmsg_ptr) + cmsg32_recvmsg_fixup(msg, cmsg_ptr); + /* Wheee... */ + if(sock->passcred) + put_cmsg32(msg, + SOL_SOCKET, SCM_CREDENTIALS, + sizeof(scm->creds), &scm->creds); + if(!scm->fp) + return; + + scm_detach_fds32(msg, scm); +} + +static int +sock_recvmsg32(struct socket *sock, struct msghdr *msg, int size, int flags, + unsigned long cmsg_ptr) +{ + struct sock_iocb *si; + struct kiocb iocb; + + init_sync_kiocb(&iocb, NULL); + + si = kiocb_to_siocb(&iocb); + si->sock = sock; + si->scm = &si->async_scm; + si->msg = msg; + si->size = size; + si->flags = flags; + + memset(si->scm, 0, sizeof(*si->scm)); + + size = sock->ops->recvmsg(&iocb, sock, msg, size, flags, si->scm); + if (size >= 0) + scm_recv32(sock, msg, si->scm, flags, cmsg_ptr); + + if (-EIOCBQUEUED == size) + size = wait_on_sync_kiocb(&iocb); + + return size; +} + /* * BSD recvmsg interface */ @@ -2755,8 +2685,6 @@ struct msghdr msg_sys; unsigned long cmsg_ptr; int err, iov_size, total_len, len; - struct sock_iocb *si; - struct kiocb iocb; /* kernel mode address */ char addr[MAX_SOCK_ADDR]; @@ -2803,20 +2731,7 @@ if (sock->file->f_flags & O_NONBLOCK) flags |= MSG_DONTWAIT; - - init_sync_kiocb(&iocb, NULL); - si = kiocb_to_siocb(&iocb); - si->sock = sock; - si->scm = &si->async_scm; - si->msg = &msg_sys; - si->size = total_len; - si->flags = flags; - memset(si->scm, 0, sizeof(*si->scm)); - - err = sock->ops->recvmsg(&iocb, sock, &msg_sys, total_len, - flags, si->scm); - if (-EIOCBQUEUED == err) - err = wait_on_sync_kiocb(&iocb); + err = sock_recvmsg32(sock, &msg_sys, total_len, flags, cmsg_ptr); if (err < 0) goto out_freeiov; len = err; @@ -2828,27 +2743,13 @@ if (err < 0) goto out_freeiov; } - if(!msg_sys.msg_control) { - if(sock->passcred || si->scm->fp) - msg_sys.msg_flags |= MSG_CTRUNC; - if(si->scm->fp) - __scm_destroy(si->scm); - } else { - /* If recvmsg processing itself placed some - * control messages into user space, it's is - * using 64-bit CMSG processing, so we need - * to fix it up before we tack on more stuff. - */ - if((unsigned long) msg_sys.msg_control != cmsg_ptr) - cmsg32_recvmsg_fixup(&msg_sys, cmsg_ptr); - /* Wheee... */ - if(sock->passcred) - put_cmsg32(&msg_sys, - SOL_SOCKET, SCM_CREDENTIALS, - sizeof(si->scm->creds), &si->scm->creds); - if(si->scm->fp != NULL) - scm_detach_fds32(&msg_sys, si->scm); - } + err = __put_user(msg_sys.msg_flags, &msg->msg_flags); + if (err) + goto out_freeiov; + err = __put_user((__kernel_size_t32) ((unsigned long)msg_sys.msg_control - cmsg_ptr), &msg->msg_controllen); + if (err) + goto out_freeiov; + err = len; out_freeiov: if (iov != iovstack) @@ -2941,6 +2842,20 @@ if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER) return do_set_icmpv6_filter(fd, level, optname, optval, optlen); + if (level == SOL_SOCKET && + (optname == SO_SNDTIMEO || optname == SO_RCVTIMEO)) { + long ret; + struct timeval tmp; + mm_segment_t old_fs; + + if (get_tv32(&tmp, (struct timeval32 *)optval )) + return -EFAULT; + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_setsockopt(fd, level, optname, (char *) &tmp, sizeof(struct timeval)); + set_fs(old_fs); + return ret; + } return sys_setsockopt(fd, level, optname, optval, optlen); } @@ -3136,13 +3051,6 @@ #ifdef CONFIG_MODULES -extern asmlinkage unsigned long sys_create_module(const char *name_user, size_t size); - -asmlinkage unsigned long sys32_create_module(const char *name_user, __kernel_size_t32 size) -{ - return sys_create_module(name_user, (size_t)size); -} - extern asmlinkage int sys_init_module(const char *name_user, struct module *mod_user); /* Hey, when you're trying to init module, take time and prepare us a nice 64bit @@ -3421,103 +3329,13 @@ return error; } -asmlinkage int sys32_query_module(char *name_user, int which, char *buf, __kernel_size_t32 bufsize, u32 ret) -{ - struct module *mod; - int err; - - lock_kernel(); - if (name_user == 0) { - /* This finds "kernel_module" which is not exported. */ - for(mod = module_list; mod->next != NULL; mod = mod->next) - ; - } else { - long namelen; - char *name; - - if ((namelen = get_mod_name(name_user, &name)) < 0) { - err = namelen; - goto out; - } - err = -ENOENT; - if (namelen == 0) { - /* This finds "kernel_module" which is not exported. */ - for(mod = module_list; mod->next != NULL; mod = mod->next) - ; - } else if ((mod = find_module(name)) == NULL) { - put_mod_name(name); - goto out; - } - put_mod_name(name); - } - - switch (which) - { - case 0: - err = 0; - break; - case QM_MODULES: - err = qm_modules(buf, bufsize, (__kernel_size_t32 *)AA(ret)); - break; - case QM_DEPS: - err = qm_deps(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret)); - break; - case QM_REFS: - err = qm_refs(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret)); - break; - case QM_SYMBOLS: - err = qm_symbols(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret)); - break; - case QM_INFO: - err = qm_info(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret)); - break; - default: - err = -EINVAL; - break; - } -out: - unlock_kernel(); - return err; -} - struct kernel_sym32 { u32 value; char name[60]; }; - -extern asmlinkage int sys_get_kernel_syms(struct kernel_sym *table); - -asmlinkage int sys32_get_kernel_syms(struct kernel_sym32 *table) -{ - int len, i; - struct kernel_sym *tbl; - mm_segment_t old_fs; - - len = sys_get_kernel_syms(NULL); - if (!table) return len; - tbl = kmalloc (len * sizeof (struct kernel_sym), GFP_KERNEL); - if (!tbl) return -ENOMEM; - old_fs = get_fs(); - set_fs (KERNEL_DS); - sys_get_kernel_syms(tbl); - set_fs (old_fs); - for (i = 0; i < len; i++, table += sizeof (struct kernel_sym32)) { - if (put_user (tbl[i].value, &table->value) || - copy_to_user (table->name, tbl[i].name, 60)) - break; - } - kfree (tbl); - return i; -} #else /* CONFIG_MODULES */ -asmlinkage unsigned long -sys32_create_module(const char *name_user, size_t size) -{ - return -ENOSYS; -} - asmlinkage int sys32_init_module(const char *name_user, struct module *mod_user) { @@ -3530,24 +3348,6 @@ return -ENOSYS; } -asmlinkage int -sys32_query_module(const char *name_user, int which, char *buf, size_t bufsize, - size_t *ret) -{ - /* Let the program know about the new interface. Not that - it'll do them much good. */ - if (which == 0) - return 0; - - return -ENOSYS; -} - -asmlinkage int -sys32_get_kernel_syms(struct kernel_sym *table) -{ - return -ENOSYS; -} - #endif /* CONFIG_MODULES */ /* Stuff for NFS server syscalls... */ @@ -4012,12 +3812,16 @@ asmlinkage ssize_t32 sys32_pread64(unsigned int fd, char *ubuf, __kernel_size_t32 count, u32 poshi, u32 poslo) { + if ((ssize_t32) count < 0) + return -EINVAL; return sys_pread64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); } asmlinkage ssize_t32 sys32_pwrite64(unsigned int fd, char *ubuf, __kernel_size_t32 count, u32 poshi, u32 poslo) { + if ((ssize_t32) count < 0) + return -EINVAL; return sys_pwrite64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); } @@ -4551,26 +4355,38 @@ sys32_futex(void *uaddr, int op, int val, struct timespec32 *timeout32) { - long ret; - struct timespec tmp, *timeout; - - ret = -ENOMEM; - timeout = kmalloc(sizeof(*timeout), GFP_USER); - if (!timeout) - goto out; + struct timespec tmp; + mm_segment_t old_fs; + int ret; - ret = -EINVAL; if (get_user (tmp.tv_sec, &timeout32->tv_sec) || - get_user (tmp.tv_nsec, &timeout32->tv_nsec) || - put_user (tmp.tv_sec, &timeout->tv_sec) || - put_user (tmp.tv_nsec, &timeout->tv_nsec)) - goto out_free; + get_user (tmp.tv_nsec, &timeout32->tv_nsec)) + return -EINVAL; - ret = sys_futex(uaddr, op, val, timeout); + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_futex(uaddr, op, val, &tmp); + set_fs(old_fs); -out_free: - kfree(timeout); -out: return ret; } +asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count); + +asmlinkage ssize_t32 sys32_read(unsigned int fd, char * buf, size_t count) +{ + if ((ssize_t32) count < 0) + return -EINVAL; + + return sys_read(fd, buf, count); +} + +asmlinkage ssize_t sys_write(unsigned int fd, const char * buf, size_t count); + +asmlinkage ssize_t32 sys32_write(unsigned int fd, char * buf, size_t count) +{ + if ((ssize_t32) count < 0) + return -EINVAL; + + return sys_write(fd, buf, count); +} diff -Nru a/arch/s390x/kernel/module.c b/arch/s390x/kernel/module.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/s390x/kernel/module.c Fri Nov 22 13:41:23 2002 @@ -0,0 +1,190 @@ +/* + * arch/s390x/kernel/module.c - Kernel module help for s390x. + * + * S390 version + * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Arnd Bergmann (arndb@de.ibm.com) + * Martin Schwidefsky (schwidefsky@de.ibm.com) + * + * based on i386 version + * Copyright (C) 2001 Rusty Russell. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(fmt , ...) +#endif + +void *module_alloc(unsigned long size) +{ + if (size == 0) + return NULL; + return vmalloc(size); +} + +/* Free memory returned from module_alloc */ +void module_free(struct module *mod, void *module_region) +{ + vfree(module_region); + /* FIXME: If module_region == mod->init_region, trim exception + table entries. */ +} + +/* s390/s390x needs additional memory for GOT/PLT sections. */ +long module_core_size(const Elf32_Ehdr *hdr, + const Elf32_Shdr *sechdrs, + const char *secstrings, + struct module *module) +{ + // FIXME: add space needed for GOT/PLT + return module->core_size; +} + +long module_init_size(const Elf32_Ehdr *hdr, + const Elf32_Shdr *sechdrs, + const char *secstrings, + struct module *module) +{ + return module->init_size; +} + + + +int apply_relocate(Elf_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *me) +{ + unsigned int i; + ElfW(Rel) *rel = (void *)sechdrs[relsec].sh_offset; + ElfW(Sym) *sym; + ElfW(Addr) *location; + + DEBUGP("Applying relocate section %u to %u\n", relsec, + sechdrs[relsec].sh_info); + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { + /* This is where to make the change */ + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_offset + + rel[i].r_offset; + /* This is the symbol it is referring to */ + sym = (ElfW(Sym) *)sechdrs[symindex].sh_offset + + ELFW(R_SYM)(rel[i].r_info); + if (!sym->st_value) { + printk(KERN_WARNING "%s: Unknown symbol %s\n", + me->name, strtab + sym->st_name); + return -ENOENT; + } + + switch (ELF_R_TYPE(rel[i].r_info)) { + case R_390_8: /* Direct 8 bit. */ + *(u8*) location += sym->st_value; + break; + case R_390_12: /* Direct 12 bit. */ + *(u16*) location = (*(u16*) location & 0xf000) | + (sym->st_value & 0xfff); + break; + case R_390_16: /* Direct 16 bit. */ + *(u16*) location += sym->st_value; + break; + case R_390_32: /* Direct 32 bit. */ + *(u32*) location += sym->st_value; + break; + case R_390_64: /* Direct 64 bit. */ + *(u64*) location += sym->st_value; + break; + case R_390_PC16: /* PC relative 16 bit. */ + *(u16*) location += sym->st_value + - (unsigned long )location; + + case R_390_PC16DBL: /* PC relative 16 bit shifted by 1. */ + *(u16*) location += (sym->st_value + - (unsigned long )location) >> 1; + case R_390_PC32: /* PC relative 32 bit. */ + *(u32*) location += sym->st_value + - (unsigned long )location; + break; + case R_390_PC32DBL: /* PC relative 32 bit shifted by 1. */ + *(u32*) location += (sym->st_value + - (unsigned long )location) >> 1; + break; + case R_390_PC64: /* PC relative 64 bit. */ + *(u64*) location += sym->st_value + - (unsigned long )location; + break; + case R_390_GOT12: /* 12 bit GOT offset. */ + case R_390_GOT16: /* 16 bit GOT offset. */ + case R_390_GOT32: /* 32 bit GOT offset. */ + case R_390_GOT64: /* 64 bit GOT offset. */ + case R_390_GOTENT: /* 32 bit PC rel. to GOT entry >> 1. */ + // FIXME: TODO + break; + + case R_390_PLT16DBL: /* 16 bit PC rel. PLT shifted by 1. */ + case R_390_PLT32: /* 32 bit PC relative PLT address. */ + case R_390_PLT32DBL: /* 32 bit PC rel. PLT shifted by 1. */ + case R_390_PLT64: /* 64 bit PC relative PLT address. */ + // FIXME: TODO + break; + case R_390_GLOB_DAT: /* Create GOT entry. */ + case R_390_JMP_SLOT: /* Create PLT entry. */ + *location = sym->st_value; + break; + case R_390_RELATIVE: /* Adjust by program base. */ + // FIXME: TODO + break; + case R_390_GOTOFF: /* 32 bit offset to GOT. */ + // FIXME: TODO + break; + case R_390_GOTPC: /* 32 bit PC relative offset to GOT. */ + case R_390_GOTPCDBL: /* 32 bit PC rel. GOT shifted by 1. */ + // FIXME: TODO + break; + default: + printk(KERN_ERR "module %s: Unknown relocation: %lu\n", + me->name, + (unsigned long)ELF_R_TYPE(rel[i].r_info)); + return -ENOEXEC; + } + } + return 0; +} + +int apply_relocate_add(Elf32_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *me) +{ + printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", + me->name); + return -ENOEXEC; +} + +int module_finalize(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, + struct module *me) +{ + return 0; +} diff -Nru a/arch/s390x/kernel/s390_ksyms.c b/arch/s390x/kernel/s390_ksyms.c --- a/arch/s390x/kernel/s390_ksyms.c Fri Nov 22 13:41:22 2002 +++ b/arch/s390x/kernel/s390_ksyms.c Fri Nov 22 13:41:22 2002 @@ -60,6 +60,20 @@ EXPORT_SYMBOL(overflowuid); EXPORT_SYMBOL(overflowgid); +#ifdef CONFIG_S390_SUPPORT +/* + * Dynamically add/remove 31 bit ioctl conversion functions. + */ +extern int register_ioctl32_conversion(unsigned int cmd, + int (*handler)(unsigned int, + unsigned int, + unsigned long, + struct file *)); +int unregister_ioctl32_conversion(unsigned int cmd); +EXPORT_SYMBOL(register_ioctl32_conversion); +EXPORT_SYMBOL(unregister_ioctl32_conversion); +#endif + /* * misc. */ diff -Nru a/arch/s390x/kernel/setup.c b/arch/s390x/kernel/setup.c --- a/arch/s390x/kernel/setup.c Fri Nov 22 13:41:19 2002 +++ b/arch/s390x/kernel/setup.c Fri Nov 22 13:41:19 2002 @@ -164,9 +164,9 @@ static int __init conmode_setup(char *str) { -#if defined(CONFIG_HWC_CONSOLE) - if (strncmp(str, "hwc", 4) == 0) - SET_CONSOLE_HWC; +#if defined(CONFIG_SCLP_CONSOLE) + if (strncmp(str, "hwc", 4) == 0 || strncmp(str, "sclp", 5) == 0) + SET_CONSOLE_SCLP; #endif #if defined(CONFIG_TN3215_CONSOLE) if (strncmp(str, "3215", 5) == 0) @@ -198,8 +198,8 @@ */ cpcmd("TERM CONMODE 3215", NULL, 0); if (ptr == NULL) { -#if defined(CONFIG_HWC_CONSOLE) - SET_CONSOLE_HWC; +#if defined(CONFIG_SCLP_CONSOLE) + SET_CONSOLE_SCLP; #endif return; } @@ -208,16 +208,16 @@ SET_CONSOLE_3270; #elif defined(CONFIG_TN3215_CONSOLE) SET_CONSOLE_3215; -#elif defined(CONFIG_HWC_CONSOLE) - SET_CONSOLE_HWC; +#elif defined(CONFIG_SCLP_CONSOLE) + SET_CONSOLE_SCLP; #endif } else if (strncmp(ptr + 8, "3215", 4) == 0) { #if defined(CONFIG_TN3215_CONSOLE) SET_CONSOLE_3215; #elif defined(CONFIG_TN3270_CONSOLE) SET_CONSOLE_3270; -#elif defined(CONFIG_HWC_CONSOLE) - SET_CONSOLE_HWC; +#elif defined(CONFIG_SCLP_CONSOLE) + SET_CONSOLE_SCLP; #endif } } else if (MACHINE_IS_P390) { @@ -227,8 +227,8 @@ SET_CONSOLE_3270; #endif } else { -#if defined(CONFIG_HWC_CONSOLE) - SET_CONSOLE_HWC; +#if defined(CONFIG_SCLP_CONSOLE) + SET_CONSOLE_SCLP; #endif } } diff -Nru a/arch/s390x/kernel/time.c b/arch/s390x/kernel/time.c --- a/arch/s390x/kernel/time.c Fri Nov 22 13:41:22 2002 +++ b/arch/s390x/kernel/time.c Fri Nov 22 13:41:22 2002 @@ -126,7 +126,6 @@ */ static void do_comparator_interrupt(struct pt_regs *regs, __u16 error_code) { - int cpu = smp_processor_id(); __u64 tmp; __u32 ticks; diff -Nru a/arch/s390x/kernel/traps.c b/arch/s390x/kernel/traps.c --- a/arch/s390x/kernel/traps.c Fri Nov 22 13:41:22 2002 +++ b/arch/s390x/kernel/traps.c Fri Nov 22 13:41:22 2002 @@ -74,8 +74,8 @@ #ifdef CONFIG_MODULES -extern struct module *module_list; -extern struct module kernel_module; +/* FIXME: Accessed without a lock --RR */ +extern struct list_head modules; static inline int kernel_text_address(unsigned long addr) { @@ -86,11 +86,11 @@ addr <= (unsigned long) &_etext) return 1; - for (mod = module_list; mod != &kernel_module; mod = mod->next) { + list_for_each_entry(mod, &modules, list) { /* mod_bound tests for addr being inside the vmalloc'ed * module area. Of course it'd be better to test only * for the .text subset... */ - if (mod_bound(addr, 0, mod)) { + if (mod_bound((void*)addr, 0, mod)) { retval = 1; break; } diff -Nru a/arch/s390x/kernel/wrapper32.S b/arch/s390x/kernel/wrapper32.S --- a/arch/s390x/kernel/wrapper32.S Fri Nov 22 13:41:23 2002 +++ b/arch/s390x/kernel/wrapper32.S Fri Nov 22 13:41:23 2002 @@ -17,14 +17,14 @@ llgfr %r2,%r2 # unsigned int llgtr %r3,%r3 # char * llgfr %r4,%r4 # size_t - jg sys_read # branch to sys_read + jg sys32_read # branch to sys_read .globl sys32_write_wrapper sys32_write_wrapper: llgfr %r2,%r2 # unsigned int llgtr %r3,%r3 # const char * llgfr %r4,%r4 # size_t - jg sys_write # branch to system call + jg sys32_write # branch to system call .globl sys32_open_wrapper sys32_open_wrapper: @@ -564,12 +564,6 @@ llgtr %r4,%r4 # old_sigset_emu31 * jg sys32_sigprocmask # branch to system call - .globl sys32_create_module_wrapper -sys32_create_module_wrapper: - llgtr %r2,%r2 # const char * - llgfr %r3,%r3 # size_t - jg sys32_create_module # branch to system call - .globl sys32_init_module_wrapper sys32_init_module_wrapper: llgtr %r2,%r2 # const char * @@ -581,11 +575,6 @@ llgtr %r2,%r2 # const char * jg sys32_delete_module # branch to system call - .globl sys32_get_kernel_syms_wrapper -sys32_get_kernel_syms_wrapper: - llgtr %r2,%r2 # struct kernel_sym_emu31 * - jg sys32_get_kernel_syms # branch to system call - .globl sys32_quotactl_wrapper sys32_quotactl_wrapper: lgfr %r2,%r2 # int @@ -785,15 +774,6 @@ llgtr %r3,%r3 # __kernel_old_uid_emu31_t * llgtr %r4,%r4 # __kernel_old_uid_emu31_t * jg sys32_getresuid16 # branch to system call - - .globl sys32_query_module_wrapper -sys32_query_module_wrapper: - llgtr %r2,%r2 # const char * - lgfr %r3,%r3 # int - llgtr %r4,%r4 # char * - llgfr %r5,%r5 # size_t - llgtr %r6,%r6 # size_t * - jg sys32_query_module # branch to system call .globl sys32_poll_wrapper sys32_poll_wrapper: diff -Nru a/arch/s390x/lib/uaccess.S b/arch/s390x/lib/uaccess.S --- a/arch/s390x/lib/uaccess.S Fri Nov 22 13:41:22 2002 +++ b/arch/s390x/lib/uaccess.S Fri Nov 22 13:41:22 2002 @@ -1,9 +1,9 @@ /* * arch/s390x/lib/uaccess.S - * fixup routines for copy_{from|to}_user functions. + * __copy_{from|to}_user functions. * - * S390 - * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * s390 + * Copyright (C) 2000,2002 IBM Deutschland Entwicklung GmbH, IBM Corporation * Authors(s): Martin Schwidefsky (schwidefsky@de.ibm.com) * * These functions have standard call interface @@ -22,14 +22,23 @@ 1: sacf 0 lgr %r2,%r5 br %r14 -2: lghi %r3,-4096 - ng %r3,__LC_TRANS_EXC_ADDR - sgr %r3,%r4 - jm 1b - j 0b +2: lghi %r1,-4096 + lgr %r3,%r4 + slgr %r3,%r1 # %r3 = %r4 + 4096 + ngr %r3,%r1 # %r3 = (%r4 + 4096) & -4096 + slgr %r3,%r4 # %r3 = #bytes to next user page boundary + clgr %r5,%r3 # copy crosses next page boundary ? + jnh 1b # no, this page fauled + # The page after the current user page might have faulted. + # We cant't find out which page because the program check handler + # might have callled schedule, destroying all lowcore information. + # We retry with the shortened length. +3: mvcle %r2,%r4,0 + jo 3b + j 1b .section __ex_table,"a" - .align 8 .quad 0b,2b + .quad 3b,1b .previous .align 4 @@ -43,14 +52,23 @@ 1: sacf 0 lgr %r2,%r3 br %r14 -2: lghi %r5,-4096 - ng %r5,__LC_TRANS_EXC_ADDR - sgr %r5,%r4 - jm 1b - j 0b +2: lghi %r1,-4096 + lgr %r5,%r4 + slgr %r5,%r1 # %r5 = %r4 + 4096 + ngr %r5,%r1 # %r5 = (%r4 + 4096) & -4096 + slgr %r5,%r4 # %r5 = #bytes to next user page boundary + clgr %r3,%r5 # copy crosses next page boundary ? + jnh 1b # no, the current page fauled + # The page after the current user page might have faulted. + # We cant't find out which page because the program check handler + # might have callled schedule, destroying all lowcore information. + # We retry with the shortened length. +3: mvcle %r4,%r2,0 + jo 3b + j 1b .section __ex_table,"a" - .align 8 - .quad 0b,2b + .quad 0b,2b + .quad 3b,1b .previous .align 4 @@ -65,14 +83,25 @@ 0: mvcle %r4,%r2,0 jo 0b 1: sacf 0 - lgr %r2,%r5 br %r14 -2: lghi %r5,-4096 - ng %r5,__LC_TRANS_EXC_ADDR - sgr %r5,%r4 - jm 1b - j 0b +2: lgr %r2,%r5 + lghi %r1,-4096 + slgr %r5,%r1 # %r5 = %r4 + 4096 + ngr %r5,%r1 # %r5 = (%r4 + 4096) & -4096 + slgr %r5,%r4 # %r5 = #bytes to next user page boundary + clgr %r2,%r5 # copy crosses next page boundary ? + jnh 1b # no, the current page fauled + # The page after the current user page might have faulted. + # We cant't find out which page because the program check handler + # might have callled schedule, destroying all lowcore information. + # We retry with the shortened length. + slgr %r2,%r5 +3: mvcle %r4,%r2,0 + jo 3b + j 1b +4: algr %r2,%r5 + j 1b .section __ex_table,"a" - .align 8 - .quad 0b,2b + .quad 0b,2b + .quad 3b,4b .previous diff -Nru a/arch/s390x/mm/extable.c b/arch/s390x/mm/extable.c --- a/arch/s390x/mm/extable.c Fri Nov 22 13:41:18 2002 +++ b/arch/s390x/mm/extable.c Fri Nov 22 13:41:18 2002 @@ -2,10 +2,8 @@ * arch/s390/mm/extable.c * * S390 version - * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation - * Author(s): Hartmut Penner (hp@de.ibm.com) * - * Derived from "arch/i386/mm/extable.c" + * identical to arch/i386/mm/extable.c */ #include @@ -42,24 +40,27 @@ unsigned long search_exception_table(unsigned long addr) { + struct list_head *i; unsigned long ret = 0; - + #ifndef CONFIG_MODULES /* There is only the kernel to search. */ ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr); return ret; #else unsigned long flags; - /* The kernel is the last "module" -- no need to treat it special. */ - struct module *mp; + struct list_head *i; + /* The kernel is the last "module" -- no need to treat it special. */ spin_lock_irqsave(&modlist_lock, flags); - for (mp = module_list; mp != NULL; mp = mp->next) { - if (mp->ex_table_start == NULL || !(mp->flags&(MOD_RUNNING|MOD_INITIALIZING))) + list_for_each(i, &extables) { + struct exception_table *ex + = list_entry(i, struct exception_table, list); + if (ex->num_entries == 0) continue; - ret = search_one_table(mp->ex_table_start, - mp->ex_table_end - 1, addr); - if (ret) + ret = search_one_table(ex->entry, + ex->entry + ex->num_entries - 1, addr); + if (ret) break; } spin_unlock_irqrestore(&modlist_lock, flags); diff -Nru a/arch/s390x/vmlinux.lds.S b/arch/s390x/vmlinux.lds.S --- a/arch/s390x/vmlinux.lds.S Fri Nov 22 13:41:18 2002 +++ b/arch/s390x/vmlinux.lds.S Fri Nov 22 13:41:18 2002 @@ -1,4 +1,4 @@ -/* ld script to make s390 Linux kernel +/* * Written by Martin Schwidefsky (schwidefsky@de.ibm.com) */ OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390") @@ -25,6 +25,7 @@ __ex_table : { *(__ex_table) } __stop___ex_table = .; + . = ALIGN(64); __start___ksymtab = .; /* Kernel symbol table */ __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; @@ -40,18 +41,31 @@ CONSTRUCTORS } + . = ALIGN(4096); + __nosave_begin = .; + .data_nosave : { *(.data.nosave) } + . = ALIGN(4096); + __nosave_end = .; + + . = ALIGN(4096); + .data.page_aligned : { *(.data.idt) } + + . = ALIGN(32); + .data.cacheline_aligned : { *(.data.cacheline_aligned) } + _edata = .; /* End of data section */ - . = ALIGN(16384); /* init_task */ + . = ALIGN(8192); /* init_task */ .data.init_task : { *(.data.init_task) } + /* will be freed after init */ . = ALIGN(4096); /* Init code and data */ __init_begin = .; - .text.init : { *(.text.init) } - .data.init : { *(.data.init) } + .init.text : { *(.init.text) } + .init.data : { *(.init.data) } . = ALIGN(256); __setup_start = .; - .setup.init : { *(.setup.init) } + .init.setup : { *(.init.setup) } __setup_end = .; __initcall_start = .; .initcall.init : { @@ -65,24 +79,29 @@ } __initcall_end = .; . = ALIGN(256); + __initramfs_start = .; + .init.ramfs : { *(.init.initramfs) } + __initramfs_end = .; + . = ALIGN(256); __per_cpu_start = .; .data.percpu : { *(.data.percpu) } __per_cpu_end = .; . = ALIGN(4096); __init_end = .; + /* freed after init ends here */ - . = ALIGN(32); - .data.cacheline_aligned : { *(.data.cacheline_aligned) } - - . = ALIGN(4096); - .data.page_aligned : { *(.data.idt) } + __bss_start = .; /* BSS */ + .bss : { *(.bss) } + __bss_stop = .; + _end = . ; - __bss_start = .; /* BSS */ - .bss : { - *(.bss) + /* Sections to be discarded */ + /DISCARD/ : { + *(.exit.text) + *(.exit.data) + *(.exitcall.exit) } - _end = . ; /* Stabs debugging sections. */ .stab 0 : { *(.stab) } diff -Nru a/arch/sparc/kernel/apc.c b/arch/sparc/kernel/apc.c --- a/arch/sparc/kernel/apc.c Fri Nov 22 13:41:23 2002 +++ b/arch/sparc/kernel/apc.c Fri Nov 22 13:41:23 2002 @@ -22,7 +22,6 @@ /* Debugging * * #define APC_DEBUG_LED - * #define APC_NO_IDLE */ #define APC_MINOR MISC_DYNAMIC_MINOR @@ -31,10 +30,27 @@ volatile static u8 *regs; static int apc_regsize; +static int apc_no_idle __initdata = 0; #define apc_readb(offs) (sbus_readb(regs+offs)) #define apc_writeb(val, offs) (sbus_writeb(val, regs+offs)) +/* Specify "apc=noidle" on the kernel command line to + * disable APC CPU standby support. Certain prototype + * systems (SPARCstation-Fox) do not play well with APC + * CPU idle, so disable this if your system has APC and + * crashes randomly. + */ +static int __init apc_setup(char *str) +{ + if(!strncmp(str, "noidle", strlen("noidle"))) { + apc_no_idle = 1; + return 1; + } + return 0; +} +__setup("apc=", apc_setup); + /* * CPU idle callback function * See .../arch/sparc/kernel/process.c @@ -127,6 +143,7 @@ struct sbus_bus *sbus = NULL; struct sbus_dev *sdev = NULL; int iTmp = 0; + for_each_sbus(sbus) { for_each_sbusdev(sdev, sbus) { if (!strcmp(sdev->prom_name, APC_OBPNAME)) { @@ -155,12 +172,12 @@ return -ENODEV; } -#ifndef APC_NO_IDLE /* Assign power management IDLE handler */ - pm_idle = apc_swift_idle; -#endif + if(!apc_no_idle) + pm_idle = apc_swift_idle; - printk(KERN_INFO "%s: power management initialized\n", APC_DEVNAME); + printk(KERN_INFO "%s: power management initialized%s\n", + APC_DEVNAME, apc_no_idle ? " (CPU idle disabled)" : ""); return 0; } @@ -169,3 +186,4 @@ * initialized, so we install ourselves thusly: */ __initcall(apc_probe); + diff -Nru a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S --- a/arch/sparc/kernel/entry.S Fri Nov 22 13:41:19 2002 +++ b/arch/sparc/kernel/entry.S Fri Nov 22 13:41:19 2002 @@ -1475,11 +1475,8 @@ .globl C_LABEL(ret_from_fork) C_LABEL(ret_from_fork): -#if CONFIG_SMP || CONFIG_PREEMPT -/* XXX Wrong location: call schedule_tail in every ret_sys_call. */ call schedule_tail mov %g3, %o0 -#endif b C_LABEL(ret_sys_call) ld [%sp + REGWIN_SZ + PT_I0], %o0 diff -Nru a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c --- a/arch/sparc/kernel/module.c Fri Nov 22 13:41:17 2002 +++ b/arch/sparc/kernel/module.c Fri Nov 22 13:41:17 2002 @@ -11,7 +11,7 @@ #include #include -static void *alloc_and_zero(unsigned long size) +void *module_alloc(unsigned long size) { void *ret; @@ -36,20 +36,21 @@ table entries. */ } -void *module_core_alloc(const Elf32_Ehdr *hdr, - const Elf32_Shdr *sechdrs, - const char *secstrings, - struct module *module) +/* We don't need anything special. */ +long module_core_size(const Elf32_Ehdr *hdr, + const Elf32_Shdr *sechdrs, + const char *secstrings, + struct module *module) { - return alloc_and_zero(module->core_size); + return module->core_size; } -void *module_init_alloc(const Elf32_Ehdr *hdr, - const Elf32_Shdr *sechdrs, - const char *secstrings, - struct module *module) +long module_init_size(const Elf32_Ehdr *hdr, + const Elf32_Shdr *sechdrs, + const char *secstrings, + struct module *module) { - return alloc_and_zero(module->init_size); + return module->init_size; } int apply_relocate(Elf32_Shdr *sechdrs, diff -Nru a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c --- a/arch/sparc/kernel/process.c Fri Nov 22 13:41:18 2002 +++ b/arch/sparc/kernel/process.c Fri Nov 22 13:41:18 2002 @@ -457,16 +457,20 @@ struct pt_regs *regs, unsigned long stack_size) { - unsigned long tid_ptr = 0; + unsigned long parent_tid_ptr = 0; + unsigned long child_tid_ptr = 0; struct task_struct *p; clone_flags &= ~CLONE_IDLETASK; - if (clone_flags & (CLONE_SETTID | CLONE_CLEARTID)) - tid_ptr = regs->u_regs[UREG_G2]; - + if (clone_flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) { + parent_tid_ptr = regs->u_regs[UREG_G2]; + child_tid_ptr = regs->u_regs[UREG_G3]; + } p = do_fork(clone_flags, stack_start, - regs, stack_size, (int *) tid_ptr); + regs, stack_size, + (int *) parent_tid_ptr, + (int *) child_tid_ptr); return IS_ERR(p) ? PTR_ERR(p) : p->pid; } @@ -507,7 +511,7 @@ #endif } - p->user_tid = NULL; + p->set_child_tid = p->clear_child_tid = NULL; /* Calculate offset to stack_frame & pt_regs */ stack_offset = THREAD_SIZE - TRACEREG_SZ; @@ -581,16 +585,6 @@ /* Set the return value for the parent. */ regs->u_regs[UREG_I1] = 0; - - if (!(clone_flags & (CLONE_SETTID | CLONE_CLEARTID))) - return 0; - - if (clone_flags & CLONE_SETTID) - if (put_user(p->pid, (int *)childregs->u_regs[UREG_G2])) - return -EFAULT; - - if (clone_flags & CLONE_CLEARTID) - p->user_tid = (int *) childregs->u_regs[UREG_G2]; return 0; } diff -Nru a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S --- a/arch/sparc/kernel/systbls.S Fri Nov 22 13:41:20 2002 +++ b/arch/sparc/kernel/systbls.S Fri Nov 22 13:41:20 2002 @@ -51,13 +51,13 @@ /*150*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64 /*155*/ .long sys_fcntl64, sys_security, sys_statfs, sys_fstatfs, sys_oldumount /*160*/ .long sys_sched_setaffinity, sys_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_nis_syscall -/*165*/ .long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_setxattr +/*165*/ .long sys_quotactl, sys_set_tid_address, sys_mount, sys_ustat, sys_setxattr /*170*/ .long sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents /*175*/ .long sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr /*180*/ .long sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_sigpending, sys_ni_syscall /*185*/ .long sys_setpgid, sys_fremovexattr, sys_tkill, sys_exit_group, sys_newuname -/*190*/ .long sys_init_module, sys_personality, sparc_remap_file_pages, sys_nis_syscall, sys_nis_syscall -/*195*/ .long sys_nis_syscall, sys_nis_syscall, sys_getppid, sparc_sigaction, sys_sgetmask +/*190*/ .long sys_init_module, sys_personality, sparc_remap_file_pages, sys_epoll_create, sys_epoll_ctl +/*195*/ .long sys_epoll_wait, sys_nis_syscall, sys_getppid, sparc_sigaction, sys_sgetmask /*200*/ .long sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, old_readdir /*205*/ .long sys_readahead, sys_socketcall, sys_syslog, sys_lookup_dcookie, sys_nis_syscall /*210*/ .long sys_nis_syscall, sys_nis_syscall, sys_waitpid, sys_swapoff, sys_sysinfo diff -Nru a/arch/sparc64/Makefile b/arch/sparc64/Makefile --- a/arch/sparc64/Makefile Fri Nov 22 13:41:23 2002 +++ b/arch/sparc64/Makefile Fri Nov 22 13:41:23 2002 @@ -33,7 +33,7 @@ LDFLAGS := -m elf64_sparc LDFLAGS_BLOB := --format binary --oformat elf64-sparc endif -ELFTOAOUT = elftoaout + ifneq ($(UNDECLARED_REGS),y) CC_UNDECL = else @@ -63,13 +63,11 @@ core-y += arch/sparc64/math-emu/ libs-y += arch/sparc64/prom/ arch/sparc64/lib/ -vmlinux.aout: vmlinux - $(ELFTOAOUT) -o $(TOPDIR)/vmlinux.aout $(TOPDIR)/vmlinux +makeboot =$(Q)$(MAKE) -f scripts/Makefile.build obj=arch/sparc64/boot $(1) -archclean: - rm -f $(TOPDIR)/vmlinux.aout +tftpboot.img vmlinux.aout: + $(call makeboot,arch/sparc64/boot/$@) archmrproper: +archclean: -tftpboot.img: - $(MAKE) -C arch/sparc64/boot tftpboot.img diff -Nru a/arch/sparc64/boot/Makefile b/arch/sparc64/boot/Makefile --- a/arch/sparc64/boot/Makefile Fri Nov 22 13:41:17 2002 +++ b/arch/sparc64/boot/Makefile Fri Nov 22 13:41:17 2002 @@ -4,17 +4,27 @@ # Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) # Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) -ROOT_IMG =/usr/src/root.img -ELFTOAOUT =elftoaout +ROOT_IMG := /usr/src/root.img +ELFTOAOUT := elftoaout -all: boot +host-progs := piggyback +EXTRA_TARGETS := tftpboot.img vmlinux.aout -boot: - @echo "Nothing special to be done for 'boot' on Linux/UltraSPARC." +quiet_cmd_elftoaout = ELT2AOUT $@ + cmd_elftoaout = $(ELFTOAOUT) vmlinux -o $@ +quiet_cmd_piggy = PIGGY $@ + cmd_piggy = $(obj)/piggyback $@ System.map $(ROOT_IMG) -tftpboot.img: piggyback $(TOPDIR)/vmlinux $(ROOT_IMG) - $(ELFTOAOUT) $(TOPDIR)/vmlinux -o tftpboot.img - ./piggyback tftpboot.img $(TOPDIR)/System.map $(ROOT_IMG) +$(obj)/tftpboot.img: $(obj)/piggyback System.map vmlinux $(ROOT_IMG) FORCE + $(call if_changed,elftoaout) + $(call if_changed,piggy) + @echo ' kernel: $@ is ready' -piggyback: piggyback.c - $(HOSTCC) $(HOSTCFLAGS) -o piggyback piggyback.c +$(obj)/vmlinux.aout: vmlinux FORCE + $(call if_changed,elftoaout) + @echo ' kernel: $@ is ready' + +archhelp: + @echo '* vmlinux - Standard sparc64 kernel' + @echo ' vmlinux.aout - a.out kernel for sparc64' + @echo ' tftpboot.img - Image prepared for tftp' diff -Nru a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile --- a/arch/sparc64/kernel/Makefile Fri Nov 22 13:41:18 2002 +++ b/arch/sparc64/kernel/Makefile Fri Nov 22 13:41:18 2002 @@ -2,8 +2,6 @@ # Makefile for the linux kernel. # -SH = $(CONFIG_SHELL) - EXTRA_AFLAGS := -ansi EXTRA_TARGETS := head.o init_task.o diff -Nru a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c --- a/arch/sparc64/kernel/ebus.c Fri Nov 22 13:41:18 2002 +++ b/arch/sparc64/kernel/ebus.c Fri Nov 22 13:41:18 2002 @@ -12,6 +12,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S --- a/arch/sparc64/kernel/entry.S Fri Nov 22 13:41:17 2002 +++ b/arch/sparc64/kernel/entry.S Fri Nov 22 13:41:17 2002 @@ -1619,10 +1619,8 @@ */ andn %o7, _TIF_NEWCHILD, %l0 stx %l0, [%g6 + TI_FLAGS] -#if CONFIG_SMP || CONFIG_PREEMPT call schedule_tail mov %g5, %o0 -#endif andcc %l0, _TIF_PERFCTR, %g0 be,pt %icc, 1f nop diff -Nru a/arch/sparc64/kernel/isa.c b/arch/sparc64/kernel/isa.c --- a/arch/sparc64/kernel/isa.c Fri Nov 22 13:41:18 2002 +++ b/arch/sparc64/kernel/isa.c Fri Nov 22 13:41:18 2002 @@ -5,14 +5,14 @@ #include #include -struct isa_bridge *isa_chain; +struct sparc_isa_bridge *isa_chain; static void __init fatal_err(const char *reason) { prom_printf("ISA: fatal error, %s.\n", reason); } -static void __init report_dev(struct isa_device *isa_dev, int child) +static void __init report_dev(struct sparc_isa_device *isa_dev, int child) { if (child) printk(" (%s)", isa_dev->prom_name); @@ -20,7 +20,7 @@ printk(" [%s", isa_dev->prom_name); } -static void __init isa_dev_get_resource(struct isa_device *isa_dev) +static void __init isa_dev_get_resource(struct sparc_isa_device *isa_dev) { struct linux_prom_registers regs[PROMREG_MAX]; unsigned long base, len; @@ -67,7 +67,7 @@ { 0, 0x00 } /* end of table */ }; -static void __init isa_dev_get_irq(struct isa_device *isa_dev) +static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev) { int irq_prop; @@ -96,7 +96,7 @@ } } -static void __init isa_fill_children(struct isa_device *parent_isa_dev) +static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev) { int node = prom_getchild(parent_isa_dev->prom_node); @@ -105,7 +105,7 @@ printk(" ->"); while (node != 0) { - struct isa_device *isa_dev; + struct sparc_isa_device *isa_dev; int prop_len; isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL); @@ -147,12 +147,12 @@ } } -static void __init isa_fill_devices(struct isa_bridge *isa_br) +static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) { int node = prom_getchild(isa_br->prom_node); while (node != 0) { - struct isa_device *isa_dev; + struct sparc_isa_device *isa_dev; int prop_len; isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL); @@ -168,7 +168,7 @@ if (isa_br->devices == NULL) { isa_br->devices = isa_dev; } else { - struct isa_device *tmp = isa_br->devices; + struct sparc_isa_device *tmp = isa_br->devices; while (tmp->next) tmp = tmp->next; @@ -220,7 +220,7 @@ while ((pdev = pci_find_device(vendor, device, pdev)) != NULL) { struct pcidev_cookie *pdev_cookie; struct pci_pbm_info *pbm; - struct isa_bridge *isa_br; + struct sparc_isa_bridge *isa_br; int prop_len; pdev_cookie = pdev->sysdata; @@ -233,7 +233,7 @@ isa_br = kmalloc(sizeof(*isa_br), GFP_KERNEL); if (!isa_br) { - fatal_err("cannot allocate isa_bridge"); + fatal_err("cannot allocate sparc_isa_bridge"); prom_halt(); } diff -Nru a/arch/sparc64/kernel/module.c b/arch/sparc64/kernel/module.c --- a/arch/sparc64/kernel/module.c Fri Nov 22 13:41:21 2002 +++ b/arch/sparc64/kernel/module.c Fri Nov 22 13:41:21 2002 @@ -118,7 +118,7 @@ return NULL; } -static void *alloc_and_zero(unsigned long size) +void *module_alloc(unsigned long size) { void *ret; @@ -143,20 +143,21 @@ table entries. */ } -void *module_core_alloc(const Elf64_Ehdr *hdr, - const Elf64_Shdr *sechdrs, - const char *secstrings, - struct module *module) +/* We don't need anything special. */ +long module_core_size(const Elf64_Ehdr *hdr, + const Elf64_Shdr *sechdrs, + const char *secstrings, + struct module *module) { - return alloc_and_zero(module->core_size); + return module->core_size; } -void *module_init_alloc(const Elf64_Ehdr *hdr, - const Elf64_Shdr *sechdrs, - const char *secstrings, - struct module *module) +long module_init_size(const Elf64_Ehdr *hdr, + const Elf64_Shdr *sechdrs, + const char *secstrings, + struct module *module) { - return alloc_and_zero(module->init_size); + return module->init_size; } int apply_relocate(Elf64_Shdr *sechdrs, diff -Nru a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c --- a/arch/sparc64/kernel/pci.c Fri Nov 22 13:41:17 2002 +++ b/arch/sparc64/kernel/pci.c Fri Nov 22 13:41:17 2002 @@ -461,7 +461,7 @@ if (err < 0) { printk("PCI: Failed to allocate resource %d for %s\n", - resource, pdev->name); + resource, pdev->dev.name); } else { /* Update PCI config space. */ pbm->parent->base_address_update(pdev, resource); diff -Nru a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c --- a/arch/sparc64/kernel/pci_common.c Fri Nov 22 13:41:18 2002 +++ b/arch/sparc64/kernel/pci_common.c Fri Nov 22 13:41:18 2002 @@ -404,7 +404,7 @@ if ((res->start >> 32) != 0UL) { printk(KERN_ERR "PCI: OBP assigns out of range MEM address " "%016lx for region %ld on device %s\n", - res->start, (res - &pdev->resource[0]), pdev->name); + res->start, (res - &pdev->resource[0]), pdev->dev.name); continue; } } @@ -426,7 +426,7 @@ "[%016lx:%016lx] of device %s\n", (res - &pdev->resource[0]), res->start, res->end, - pdev->name); + pdev->dev.name); } } } @@ -503,7 +503,7 @@ if (allocate_resource(root, res, size + 1, min, max, align, NULL, NULL) < 0) { /* uh oh */ prom_printf("PCI: Failed to allocate resource %d for %s\n", - i, pdev->name); + i, pdev->dev.name); prom_halt(); } @@ -1005,7 +1005,7 @@ pci_write_config_word(pdev, PCI_STATUS, error_bits); printk("PCI%d(PBM%c): Device [%s] saw Target Abort [%016x]\n", p->index, ((pbm == &p->pbm_A) ? 'A' : 'B'), - pdev->name, status); + pdev->dev.name, status); } } @@ -1031,7 +1031,7 @@ pci_write_config_word(pdev, PCI_STATUS, error_bits); printk("PCI%d(PBM%c): Device [%s] received Master Abort [%016x]\n", p->index, ((pbm == &p->pbm_A) ? 'A' : 'B'), - pdev->name, status); + pdev->dev.name, status); } } @@ -1058,7 +1058,7 @@ pci_write_config_word(pdev, PCI_STATUS, error_bits); printk("PCI%d(PBM%c): Device [%s] saw Parity Error [%016x]\n", p->index, ((pbm == &p->pbm_A) ? 'A' : 'B'), - pdev->name, status); + pdev->dev.name, status); } } diff -Nru a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c --- a/arch/sparc64/kernel/pci_psycho.c Fri Nov 22 13:41:21 2002 +++ b/arch/sparc64/kernel/pci_psycho.c Fri Nov 22 13:41:21 2002 @@ -11,6 +11,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c --- a/arch/sparc64/kernel/pci_sabre.c Fri Nov 22 13:41:23 2002 +++ b/arch/sparc64/kernel/pci_sabre.c Fri Nov 22 13:41:23 2002 @@ -11,6 +11,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c --- a/arch/sparc64/kernel/pci_schizo.c Fri Nov 22 13:41:21 2002 +++ b/arch/sparc64/kernel/pci_schizo.c Fri Nov 22 13:41:21 2002 @@ -9,6 +9,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c --- a/arch/sparc64/kernel/power.c Fri Nov 22 13:41:23 2002 +++ b/arch/sparc64/kernel/power.c Fri Nov 22 13:41:23 2002 @@ -10,6 +10,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c --- a/arch/sparc64/kernel/process.c Fri Nov 22 13:41:19 2002 +++ b/arch/sparc64/kernel/process.c Fri Nov 22 13:41:19 2002 @@ -568,18 +568,24 @@ unsigned long stack_size) { struct task_struct *p; - unsigned long tid_ptr = 0; + unsigned long parent_tid_ptr = 0; + unsigned long child_tid_ptr = 0; clone_flags &= ~CLONE_IDLETASK; - if (clone_flags & (CLONE_SETTID | CLONE_CLEARTID)) { - tid_ptr = regs->u_regs[UREG_G2]; - if (test_thread_flag(TIF_32BIT)) - tid_ptr &= 0xffffffff; + if (clone_flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) { + parent_tid_ptr = regs->u_regs[UREG_G2]; + child_tid_ptr = regs->u_regs[UREG_G3]; + if (test_thread_flag(TIF_32BIT)) { + parent_tid_ptr &= 0xffffffff; + child_tid_ptr &= 0xffffffff; + } } p = do_fork(clone_flags, stack_start, - regs, stack_size, (int *) tid_ptr); + regs, stack_size, + (int *) parent_tid_ptr, + (int *) child_tid_ptr); return IS_ERR(p) ? PTR_ERR(p) : p->pid; } @@ -601,7 +607,7 @@ p->thread.smp_lock_pc = 0; #endif - p->user_tid = NULL; + p->set_child_tid = p->clear_child_tid = NULL; /* Calculate offset to stack_frame & pt_regs */ child_trap_frame = ((char *)t) + (THREAD_SIZE - (TRACEREG_SZ+REGWIN_SZ)); diff -Nru a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c --- a/arch/sparc64/kernel/sbus.c Fri Nov 22 13:41:23 2002 +++ b/arch/sparc64/kernel/sbus.c Fri Nov 22 13:41:23 2002 @@ -10,6 +10,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c --- a/arch/sparc64/kernel/sys_sparc32.c Fri Nov 22 13:41:21 2002 +++ b/arch/sparc64/kernel/sys_sparc32.c Fri Nov 22 13:41:21 2002 @@ -1433,11 +1433,11 @@ if (stat->size > MAX_NON_LFS) return -EOVERFLOW; err |= put_user(stat->size, &statbuf->st_size); - err |= put_user(stat->atime, &statbuf->st_atime); + err |= put_user(stat->atime.tv_sec, &statbuf->st_atime); err |= put_user(0, &statbuf->__unused1); - err |= put_user(stat->mtime, &statbuf->st_mtime); + err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime); err |= put_user(0, &statbuf->__unused2); - err |= put_user(stat->ctime, &statbuf->st_ctime); + err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime); err |= put_user(0, &statbuf->__unused3); err |= put_user(stat->blksize, &statbuf->st_blksize); err |= put_user(stat->blocks, &statbuf->st_blocks); diff -Nru a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c --- a/arch/sparc64/kernel/sys_sunos32.c Fri Nov 22 13:41:21 2002 +++ b/arch/sparc64/kernel/sys_sunos32.c Fri Nov 22 13:41:21 2002 @@ -52,6 +52,9 @@ #include #include +/* For SOCKET_I */ +#include + /* Use this to get at 32-bit user passed pointers. */ #define A(__x) \ ({ unsigned long __ret; \ diff -Nru a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S --- a/arch/sparc64/kernel/systbls.S Fri Nov 22 13:41:19 2002 +++ b/arch/sparc64/kernel/systbls.S Fri Nov 22 13:41:19 2002 @@ -52,13 +52,13 @@ /*150*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64 .word sys32_fcntl64, sys_security, sys32_statfs, sys32_fstatfs, sys_oldumount /*160*/ .word sys32_sched_setaffinity, sys32_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_nis_syscall - .word sys_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys_setxattr + .word sys_quotactl, sys_set_tid_address, sys32_mount, sys_ustat, sys_setxattr /*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys32_getdents .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr /*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys32_sigpending, sys_ni_syscall .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_exit_group, sparc64_newuname -/*190*/ .word sys32_init_module, sparc64_personality, sys_remap_file_pages, sys_nis_syscall, sys_nis_syscall - .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys32_sigaction, sys_sgetmask +/*190*/ .word sys32_init_module, sparc64_personality, sys_remap_file_pages, sys_epoll_create, sys_epoll_ctl + .word sys_epoll_wait, sys_nis_syscall, sys_getppid, sys32_sigaction, sys_sgetmask /*200*/ .word sys_ssetmask, sys_sigsuspend, sys32_newlstat, sys_uselib, old32_readdir .word sys32_readahead, sys32_socketcall, sys_syslog, sys_lookup_dcookie, sys_nis_syscall /*210*/ .word sys_nis_syscall, sys_nis_syscall, sys_waitpid, sys_swapoff, sys32_sysinfo @@ -111,13 +111,13 @@ /*150*/ .word sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64 .word sys_nis_syscall, sys_security, sys_statfs, sys_fstatfs, sys_oldumount /*160*/ .word sys_sched_setaffinity, sys_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_utrap_install - .word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_setxattr + .word sys_quotactl, sys_set_tid_address, sys_mount, sys_ustat, sys_setxattr /*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr /*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_nis_syscall, sys_ni_syscall .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_exit_group, sparc64_newuname -/*190*/ .word sys_init_module, sparc64_personality, sys_remap_file_pages, sys_nis_syscall, sys_nis_syscall - .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys_nis_syscall, sys_sgetmask +/*190*/ .word sys_init_module, sparc64_personality, sys_remap_file_pages, sys_epoll_create, sys_epoll_ctl + .word sys_epoll_wait, sys_nis_syscall, sys_getppid, sys_nis_syscall, sys_sgetmask /*200*/ .word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall .word sys_readahead, sys_socketcall, sys_syslog, sys_lookup_dcookie, sys_nis_syscall /*210*/ .word sys_nis_syscall, sys_nis_syscall, sys_waitpid, sys_swapoff, sys_sysinfo diff -Nru a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c --- a/arch/sparc64/kernel/time.c Fri Nov 22 13:41:20 2002 +++ b/arch/sparc64/kernel/time.c Fri Nov 22 13:41:20 2002 @@ -415,7 +415,7 @@ struct linux_central *cbus; #ifdef CONFIG_PCI struct linux_ebus *ebus = NULL; - struct isa_bridge *isa_br = NULL; + struct sparc_isa_bridge *isa_br = NULL; #endif static int invoked; @@ -547,7 +547,7 @@ break; } else if (isa_br != NULL) { - struct isa_device *isadev; + struct sparc_isa_device *isadev; try_isa_clock: for_each_isadev(isadev, isa_br) diff -Nru a/arch/sparc64/lib/Makefile b/arch/sparc64/lib/Makefile --- a/arch/sparc64/lib/Makefile Fri Nov 22 13:41:17 2002 +++ b/arch/sparc64/lib/Makefile Fri Nov 22 13:41:17 2002 @@ -11,5 +11,3 @@ VIScsumcopyusr.o VISsave.o atomic.o rwlock.o bitops.o \ dec_and_lock.o U3memcpy.o U3copy_from_user.o U3copy_to_user.o \ U3copy_in_user.o mcount.o ipcsum.o - -include $(TOPDIR)/Rules.make diff -Nru a/arch/sparc64/math-emu/Makefile b/arch/sparc64/math-emu/Makefile --- a/arch/sparc64/math-emu/Makefile Fri Nov 22 13:41:18 2002 +++ b/arch/sparc64/math-emu/Makefile Fri Nov 22 13:41:18 2002 @@ -4,6 +4,4 @@ obj-y := math.o -EXTRA_CFLAGS = -I. -I$(TOPDIR)/include/math-emu -w - -include $(TOPDIR)/Rules.make +EXTRA_CFLAGS = -I. -Iinclude/math-emu -w diff -Nru a/arch/sparc64/mm/Makefile b/arch/sparc64/mm/Makefile --- a/arch/sparc64/mm/Makefile Fri Nov 22 13:41:22 2002 +++ b/arch/sparc64/mm/Makefile Fri Nov 22 13:41:22 2002 @@ -7,5 +7,3 @@ obj-y := ultra.o fault.o init.o generic.o extable.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o - -include $(TOPDIR)/Rules.make diff -Nru a/arch/sparc64/prom/Makefile b/arch/sparc64/prom/Makefile --- a/arch/sparc64/prom/Makefile Fri Nov 22 13:41:22 2002 +++ b/arch/sparc64/prom/Makefile Fri Nov 22 13:41:22 2002 @@ -8,5 +8,3 @@ L_TARGET = lib.a obj-y := bootstr.o devops.o init.o memory.o misc.o \ tree.o console.o printf.o p1275.o map.o - -include $(TOPDIR)/Rules.make diff -Nru a/arch/sparc64/solaris/Makefile b/arch/sparc64/solaris/Makefile --- a/arch/sparc64/solaris/Makefile Fri Nov 22 13:41:17 2002 +++ b/arch/sparc64/solaris/Makefile Fri Nov 22 13:41:17 2002 @@ -8,5 +8,3 @@ ioctl.o ipc.o socksys.o timod.o obj-$(CONFIG_SOLARIS_EMUL) += solaris.o - -include $(TOPDIR)/Rules.make diff -Nru a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c --- a/arch/sparc64/solaris/fs.c Fri Nov 22 13:41:18 2002 +++ b/arch/sparc64/solaris/fs.c Fri Nov 22 13:41:18 2002 @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -92,12 +93,12 @@ __put_user (kbuf->gid, &ubuf->st_gid) || __put_user (R4_DEV(kbuf->rdev), &ubuf->st_rdev) || __put_user (kbuf->size, &ubuf->st_size) || - __put_user (kbuf->atime, &ubuf->st_atime.tv_sec) || - __put_user (0, &ubuf->st_atime.tv_nsec) || - __put_user (kbuf->mtime, &ubuf->st_mtime.tv_sec) || - __put_user (0, &ubuf->st_mtime.tv_nsec) || - __put_user (kbuf->ctime, &ubuf->st_ctime.tv_sec) || - __put_user (0, &ubuf->st_ctime.tv_nsec) || + __put_user (kbuf->atime.tv_sec, &ubuf->st_atime.tv_sec) || + __put_user (kbuf->atime.tv_nsec, &ubuf->st_atime.tv_nsec) || + __put_user (kbuf->mtime.tv_sec, &ubuf->st_mtime.tv_sec) || + __put_user (kbuf->mtime.tv_nsec, &ubuf->st_mtime.tv_nsec) || + __put_user (kbuf->ctime.tv_sec, &ubuf->st_ctime.tv_sec) || + __put_user (kbuf->ctime.tv_nsec, &ubuf->st_ctime.tv_nsec) || __put_user (kbuf->blksize, &ubuf->st_blksize) || __put_user (kbuf->blocks, &ubuf->st_blocks) || __put_user (UFSMAGIC, (unsigned *)ubuf->st_fstype)) @@ -115,12 +116,12 @@ __put_user (kbuf->gid, &ubuf->st_gid) || __put_user (R4_DEV(kbuf->rdev), &ubuf->st_rdev) || __put_user (kbuf->size, &ubuf->st_size) || - __put_user (kbuf->atime, &ubuf->st_atime.tv_sec) || - __put_user (0, &ubuf->st_atime.tv_nsec) || - __put_user (kbuf->mtime, &ubuf->st_mtime.tv_sec) || - __put_user (0, &ubuf->st_mtime.tv_nsec) || - __put_user (kbuf->ctime, &ubuf->st_ctime.tv_sec) || - __put_user (0, &ubuf->st_ctime.tv_nsec) || + __put_user (kbuf->atime.tv_sec, &ubuf->st_atime.tv_sec) || + __put_user (kbuf->atime.tv_nsec, &ubuf->st_atime.tv_nsec) || + __put_user (kbuf->mtime.tv_sec, &ubuf->st_mtime.tv_sec) || + __put_user (kbuf->mtime.tv_nsec, &ubuf->st_mtime.tv_nsec) || + __put_user (kbuf->ctime.tv_sec, &ubuf->st_ctime.tv_sec) || + __put_user (kbuf->ctime.tv_nsec, &ubuf->st_ctime.tv_nsec) || __put_user (kbuf->blksize, &ubuf->st_blksize) || __put_user (kbuf->blocks, &ubuf->st_blocks) || __put_user (UFSMAGIC, (unsigned *)ubuf->st_fstype)) diff -Nru a/arch/sparc64/solaris/ioctl.c b/arch/sparc64/solaris/ioctl.c --- a/arch/sparc64/solaris/ioctl.c Fri Nov 22 13:41:20 2002 +++ b/arch/sparc64/solaris/ioctl.c Fri Nov 22 13:41:20 2002 @@ -24,6 +24,8 @@ #include #include +#include + #include #include #include diff -Nru a/arch/sparc64/solaris/socket.c b/arch/sparc64/solaris/socket.c --- a/arch/sparc64/solaris/socket.c Fri Nov 22 13:41:21 2002 +++ b/arch/sparc64/solaris/socket.c Fri Nov 22 13:41:21 2002 @@ -13,6 +13,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c --- a/arch/sparc64/solaris/socksys.c Fri Nov 22 13:41:18 2002 +++ b/arch/sparc64/solaris/socksys.c Fri Nov 22 13:41:18 2002 @@ -27,6 +27,8 @@ #include #include +#include + #include #include diff -Nru a/arch/sparc64/vmlinux.lds.S b/arch/sparc64/vmlinux.lds.S --- a/arch/sparc64/vmlinux.lds.S Fri Nov 22 13:41:22 2002 +++ b/arch/sparc64/vmlinux.lds.S Fri Nov 22 13:41:22 2002 @@ -24,6 +24,8 @@ CONSTRUCTORS } .data1 : { *(.data1) } + . = ALIGN(64); + .data.cacheline_aligned : { *(.data.cacheline_aligned) } _edata = .; PROVIDE (edata = .); .fixup : { *(.fixup) } @@ -70,8 +72,6 @@ __per_cpu_end = .; . = ALIGN(8192); __init_end = .; - . = ALIGN(64); - .data.cacheline_aligned : { *(.data.cacheline_aligned) } __bss_start = .; .sbss : { *(.sbss) *(.scommon) } .bss : diff -Nru a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig --- a/arch/x86_64/Kconfig Fri Nov 22 13:41:22 2002 +++ b/arch/x86_64/Kconfig Fri Nov 22 13:41:22 2002 @@ -739,13 +739,13 @@ help Fill __init and __initdata at the end of boot. This is only for debugging. -# config KALLSYMS -# bool "Load all symbols for debugging/kksymoops" -# depends on DEBUG_KERNEL -# help -# Say Y here to let the kernel print out symbolic crash information and -# symbolic stack backtraces. This increases the size of the kernel -# somewhat, as all symbols have to be loaded into the kernel image. +config KALLSYMS + bool "Load all symbols for debugging/kksymoops" + depends on DEBUG_KERNEL + help + Say Y here to let the kernel print out symbolic crash information and + symbolic stack backtraces. This increases the size of the kernel + somewhat, as all symbols have to be loaded into the kernel image. endmenu diff -Nru a/crypto/Kconfig b/crypto/Kconfig --- a/crypto/Kconfig Fri Nov 22 13:41:23 2002 +++ b/crypto/Kconfig Fri Nov 22 13:41:23 2002 @@ -16,6 +16,12 @@ HMAC: Keyed-Hashing for Message Authentication (RFC2104). This is required for IPSec. +config CRYPTO_NULL + tristate "Null algorithms" + depends on CRYPTO + help + These are 'Null' algorithms, used by IPsec, which do nothing. + config CRYPTO_MD4 tristate "MD4 digest algorithm" depends on CRYPTO diff -Nru a/crypto/Makefile b/crypto/Makefile --- a/crypto/Makefile Fri Nov 22 13:41:23 2002 +++ b/crypto/Makefile Fri Nov 22 13:41:23 2002 @@ -9,6 +9,7 @@ obj-$(CONFIG_CRYPTO) += api.o cipher.o digest.o compress.o $(autoload-crypto-y) obj-$(CONFIG_CRYPTO_HMAC) += hmac.o +obj-$(CONFIG_CRYPTO_NULL) += crypto_null.o obj-$(CONFIG_CRYPTO_MD4) += md4.o obj-$(CONFIG_CRYPTO_MD5) += md5.o obj-$(CONFIG_CRYPTO_SHA1) += sha1.o diff -Nru a/crypto/api.c b/crypto/api.c --- a/crypto/api.c Fri Nov 22 13:41:23 2002 +++ b/crypto/api.c Fri Nov 22 13:41:23 2002 @@ -63,7 +63,7 @@ case CRYPTO_ALG_TYPE_DIGEST: return crypto_init_digest_flags(tfm, flags); - case CRYPTO_ALG_TYPE_COMP: + case CRYPTO_ALG_TYPE_COMPRESS: return crypto_init_compress_flags(tfm, flags); default: @@ -74,19 +74,39 @@ return -EINVAL; } -static void crypto_init_ops(struct crypto_tfm *tfm) +static int crypto_init_ops(struct crypto_tfm *tfm) { switch (crypto_tfm_alg_type(tfm)) { case CRYPTO_ALG_TYPE_CIPHER: - crypto_init_cipher_ops(tfm); + return crypto_init_cipher_ops(tfm); + + case CRYPTO_ALG_TYPE_DIGEST: + return crypto_init_digest_ops(tfm); + + case CRYPTO_ALG_TYPE_COMPRESS: + return crypto_init_compress_ops(tfm); + + default: + break; + } + + BUG(); + return -EINVAL; +} + +static void crypto_exit_ops(struct crypto_tfm *tfm) +{ + switch (crypto_tfm_alg_type(tfm)) { + case CRYPTO_ALG_TYPE_CIPHER: + crypto_exit_cipher_ops(tfm); break; case CRYPTO_ALG_TYPE_DIGEST: - crypto_init_digest_ops(tfm); + crypto_exit_digest_ops(tfm); break; - case CRYPTO_ALG_TYPE_COMP: - crypto_init_compress_ops(tfm); + case CRYPTO_ALG_TYPE_COMPRESS: + crypto_exit_compress_ops(tfm); break; default: @@ -109,7 +129,7 @@ goto out_put; memset(tfm, 0, sizeof(*tfm)); - + if (alg->cra_ctxsize) { tfm->crt_ctx = kmalloc(alg->cra_ctxsize, GFP_KERNEL); if (tfm->crt_ctx == NULL) @@ -128,8 +148,11 @@ if (crypto_init_flags(tfm, flags)) goto out_free_work_block; - crypto_init_ops(tfm); - + if (crypto_init_ops(tfm)) { + crypto_exit_ops(tfm); + goto out_free_ctx; + } + goto out; out_free_work_block: diff -Nru a/crypto/cipher.c b/crypto/cipher.c --- a/crypto/cipher.c Fri Nov 22 13:41:20 2002 +++ b/crypto/cipher.c Fri Nov 22 13:41:20 2002 @@ -234,27 +234,19 @@ int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags) { - struct crypto_alg *alg = tfm->__crt_alg; u32 mode = flags & CRYPTO_TFM_MODE_MASK; tfm->crt_cipher.cit_mode = mode ? mode : CRYPTO_TFM_MODE_ECB; - - if (alg->cra_cipher.cia_ivsize && mode != CRYPTO_TFM_MODE_ECB) { - tfm->crt_cipher.cit_iv = - kmalloc(alg->cra_cipher.cia_ivsize, GFP_KERNEL); - if (tfm->crt_cipher.cit_iv == NULL) - return -ENOMEM; - } else - tfm->crt_cipher.cit_iv = NULL; - if (flags & CRYPTO_TFM_REQ_WEAK_KEY) tfm->crt_flags = CRYPTO_TFM_REQ_WEAK_KEY; return 0; } -void crypto_init_cipher_ops(struct crypto_tfm *tfm) +int crypto_init_cipher_ops(struct crypto_tfm *tfm) { + int ret = 0; + struct crypto_alg *alg = tfm->__crt_alg; struct cipher_tfm *ops = &tfm->crt_cipher; ops->cit_setkey = setkey; @@ -283,4 +275,20 @@ default: BUG(); } + + if (alg->cra_cipher.cia_ivsize && + ops->cit_mode != CRYPTO_TFM_MODE_ECB) { + + ops->cit_iv = kmalloc(alg->cra_cipher.cia_ivsize, GFP_KERNEL); + if (ops->cit_iv == NULL) + ret = -ENOMEM; + } + + return ret; +} + +void crypto_exit_cipher_ops(struct crypto_tfm *tfm) +{ + if (tfm->crt_cipher.cit_iv) + kfree(tfm->crt_cipher.cit_iv); } diff -Nru a/crypto/compress.c b/crypto/compress.c --- a/crypto/compress.c Fri Nov 22 13:41:20 2002 +++ b/crypto/compress.c Fri Nov 22 13:41:20 2002 @@ -18,25 +18,29 @@ #include #include "internal.h" -/* - * This code currently implements blazingly fast and - * lossless Quadruple ROT13 compression. - */ static void crypto_compress(struct crypto_tfm *tfm) -{ } +{ + tfm->__crt_alg->cra_compress.coa_compress(); +} static void crypto_decompress(struct crypto_tfm *tfm) -{ } +{ + tfm->__crt_alg->cra_compress.coa_decompress(); +} int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags) { return crypto_cipher_flags(flags) ? -EINVAL : 0; } -void crypto_init_compress_ops(struct crypto_tfm *tfm) +int crypto_init_compress_ops(struct crypto_tfm *tfm) { struct compress_tfm *ops = &tfm->crt_compress; ops->cot_compress = crypto_compress; ops->cot_decompress = crypto_decompress; + return 0; } + +void crypto_exit_compress_ops(struct crypto_tfm *tfm) +{ } diff -Nru a/crypto/crypto_null.c b/crypto/crypto_null.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/crypto_null.c Fri Nov 22 13:41:23 2002 @@ -0,0 +1,132 @@ +/* + * Cryptographic API. + * + * Null algorithms, aka Much Ado About Nothing. + * + * These are needed for IPsec, and may be useful in general for + * testing & debugging. + * + * The null cipher is compliant with RFC2410. + * + * Copyright (c) 2002 James Morris + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ +#include +#include +#include +#include +#include + +#define NULL_KEY_SIZE 0 +#define NULL_BLOCK_SIZE 1 +#define NULL_DIGEST_SIZE 0 + +static void null_compress(void) +{ } + +static void null_decompress(void) +{ } + +static void null_init(void *ctx) +{ } + +static void null_update(void *ctx, const u8 *data, unsigned int len) +{ } + +static void null_final(void *ctx, u8 *out) +{ } + +static int null_setkey(void *ctx, const u8 *key, + unsigned int keylen, u32 *flags) +{ return 0; } + +static void null_encrypt(void *ctx, u8 *dst, const u8 *src) +{ } + +static void null_decrypt(void *ctx, u8 *dst, const u8 *src) +{ } + +static struct crypto_alg compress_null = { + .cra_name = "compress_null", + .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, + .cra_blocksize = NULL_BLOCK_SIZE, + .cra_ctxsize = 0, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(compress_null.cra_list), + .cra_u = { .compress = { + .coa_compress = null_compress, + .coa_decompress = null_decompress } } +}; + +static struct crypto_alg digest_null = { + .cra_name = "digest_null", + .cra_flags = CRYPTO_ALG_TYPE_DIGEST, + .cra_blocksize = NULL_BLOCK_SIZE, + .cra_ctxsize = 0, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(digest_null.cra_list), + .cra_u = { .digest = { + .dia_digestsize = NULL_DIGEST_SIZE, + .dia_init = null_init, + .dia_update = null_update, + .dia_final = null_final } } +}; + +static struct crypto_alg cipher_null = { + .cra_name = "cipher_null", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = NULL_BLOCK_SIZE, + .cra_ctxsize = 0, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(cipher_null.cra_list), + .cra_u = { .cipher = { + .cia_min_keysize = NULL_KEY_SIZE, + .cia_max_keysize = NULL_KEY_SIZE, + .cia_ivsize = 0, + .cia_setkey = null_setkey, + .cia_encrypt = null_encrypt, + .cia_decrypt = null_decrypt } } +}; + +static int __init init(void) +{ + int ret = 0; + + ret = crypto_register_alg(&cipher_null); + if (ret < 0) + goto out; + + ret = crypto_register_alg(&digest_null); + if (ret < 0) { + crypto_unregister_alg(&cipher_null); + goto out; + } + + ret = crypto_register_alg(&compress_null); + if (ret < 0) { + crypto_unregister_alg(&digest_null); + crypto_unregister_alg(&cipher_null); + goto out; + } + +out: + return ret; +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&compress_null); + crypto_unregister_alg(&digest_null); + crypto_unregister_alg(&cipher_null); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Null Cryptographic Algorithms"); diff -Nru a/crypto/digest.c b/crypto/digest.c --- a/crypto/digest.c Fri Nov 22 13:41:17 2002 +++ b/crypto/digest.c Fri Nov 22 13:41:17 2002 @@ -63,12 +63,19 @@ return crypto_cipher_flags(flags) ? -EINVAL : 0; } -void crypto_init_digest_ops(struct crypto_tfm *tfm) +int crypto_init_digest_ops(struct crypto_tfm *tfm) { struct digest_tfm *ops = &tfm->crt_digest; - ops->dit_init = init; - ops->dit_update = update; - ops->dit_final = final; - ops->dit_digest = digest; + ops->dit_init = init; + ops->dit_update = update; + ops->dit_final = final; + ops->dit_digest = digest; + + return crypto_alloc_hmac_block(tfm); +} + +void crypto_exit_digest_ops(struct crypto_tfm *tfm) +{ + crypto_free_hmac_block(tfm); } diff -Nru a/crypto/hmac.c b/crypto/hmac.c --- a/crypto/hmac.c Fri Nov 22 13:41:20 2002 +++ b/crypto/hmac.c Fri Nov 22 13:41:20 2002 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "internal.h" @@ -31,18 +32,39 @@ } +int crypto_alloc_hmac_block(struct crypto_tfm *tfm) +{ + int ret = 0; + + BUG_ON(!crypto_tfm_alg_blocksize(tfm)); + + tfm->crt_digest.dit_hmac_block = kmalloc(crypto_tfm_alg_blocksize(tfm), + GFP_KERNEL); + if (tfm->crt_digest.dit_hmac_block == NULL) + ret = -ENOMEM; + + return ret; + +} + +void crypto_free_hmac_block(struct crypto_tfm *tfm) +{ + if (tfm->crt_digest.dit_hmac_block) + kfree(tfm->crt_digest.dit_hmac_block); +} + void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen) { unsigned int i; struct scatterlist tmp; - char *ipad = tfm->crt_work_block; - + char *ipad = tfm->crt_digest.dit_hmac_block; + if (*keylen > crypto_tfm_alg_blocksize(tfm)) { hash_key(tfm, key, *keylen); *keylen = crypto_tfm_alg_digestsize(tfm); } - memset(ipad, 0, crypto_tfm_alg_blocksize(tfm) + 1); + memset(ipad, 0, crypto_tfm_alg_blocksize(tfm)); memcpy(ipad, key, *keylen); for (i = 0; i < crypto_tfm_alg_blocksize(tfm); i++) @@ -67,8 +89,8 @@ { unsigned int i; struct scatterlist tmp; - char *opad = tfm->crt_work_block; - + char *opad = tfm->crt_digest.dit_hmac_block; + if (*keylen > crypto_tfm_alg_blocksize(tfm)) { hash_key(tfm, key, *keylen); *keylen = crypto_tfm_alg_digestsize(tfm); @@ -76,7 +98,7 @@ crypto_digest_final(tfm, out); - memset(opad, 0, crypto_tfm_alg_blocksize(tfm) + 1); + memset(opad, 0, crypto_tfm_alg_blocksize(tfm)); memcpy(opad, key, *keylen); for (i = 0; i < crypto_tfm_alg_blocksize(tfm); i++) diff -Nru a/crypto/internal.h b/crypto/internal.h --- a/crypto/internal.h Fri Nov 22 13:41:17 2002 +++ b/crypto/internal.h Fri Nov 22 13:41:17 2002 @@ -52,13 +52,30 @@ } #endif +#ifdef CONFIG_CRYPTO_HMAC +int crypto_alloc_hmac_block(struct crypto_tfm *tfm); +void crypto_free_hmac_block(struct crypto_tfm *tfm); +#else +static inline int crypto_alloc_hmac_block(struct crypto_tfm *tfm) +{ + return 0; +} + +static inline void crypto_free_hmac_block(struct crypto_tfm *tfm) +{ } +#endif + int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags); int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags); int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags); -void crypto_init_digest_ops(struct crypto_tfm *tfm); -void crypto_init_cipher_ops(struct crypto_tfm *tfm); -void crypto_init_compress_ops(struct crypto_tfm *tfm); +int crypto_init_digest_ops(struct crypto_tfm *tfm); +int crypto_init_cipher_ops(struct crypto_tfm *tfm); +int crypto_init_compress_ops(struct crypto_tfm *tfm); + +void crypto_exit_digest_ops(struct crypto_tfm *tfm); +void crypto_exit_cipher_ops(struct crypto_tfm *tfm); +void crypto_exit_compress_ops(struct crypto_tfm *tfm); #endif /* _CRYPTO_INTERNAL_H */ diff -Nru a/drivers/acorn/scsi/arxescsi.c b/drivers/acorn/scsi/arxescsi.c --- a/drivers/acorn/scsi/arxescsi.c Fri Nov 22 13:41:20 2002 +++ b/drivers/acorn/scsi/arxescsi.c Fri Nov 22 13:41:20 2002 @@ -411,7 +411,7 @@ return ret; } -static void __devexit arxescsi_release(struct expansion_card *ec) +static void __devexit arxescsi_remove(struct expansion_card *ec) { struct Scsi_Host *host = ecard_get_drvdata(ec); diff -Nru a/drivers/acorn/scsi/cumana_1.c b/drivers/acorn/scsi/cumana_1.c --- a/drivers/acorn/scsi/cumana_1.c Fri Nov 22 13:41:18 2002 +++ b/drivers/acorn/scsi/cumana_1.c Fri Nov 22 13:41:18 2002 @@ -260,12 +260,12 @@ }; static int __devinit -cumanascsi1_probe(struct expansion_card *ec, struct ecard_ids *id) +cumanascsi1_probe(struct expansion_card *ec, const struct ecard_id *id) { struct Scsi_Host *host; int ret = -ENOMEM; - host = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); + host = scsi_register(&cumanascsi_template, sizeof(struct NCR5380_hostdata)); if (!host) goto out; @@ -294,7 +294,7 @@ printk("scsi%d: at port 0x%08lx irq %d", host->host_no, host->io_port, host->irq); printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", - tpnt->can_queue, tpnt->cmd_per_lun, CUMANASCSI_PUBLIC_RELEASE); + host->can_queue, host->cmd_per_lun, CUMANASCSI_PUBLIC_RELEASE); printk("\nscsi%d:", host->host_no); NCR5380_print_options(host); printk("\n"); @@ -321,10 +321,10 @@ scsi_remove_host(host); free_irq(host->irq, host); release_region(host->io_port, host->n_io_port); - scsi_remove(host); + scsi_unregister(host); } -static const struct ecard_ids cumanascsi1_cids[] = { +static const struct ecard_id cumanascsi1_cids[] = { { MANU_CUMANA, PROD_CUMANA_SCSI_1 }, { 0xffff, 0xffff } }; diff -Nru a/drivers/acorn/scsi/ecoscsi.c b/drivers/acorn/scsi/ecoscsi.c --- a/drivers/acorn/scsi/ecoscsi.c Fri Nov 22 13:41:23 2002 +++ b/drivers/acorn/scsi/ecoscsi.c Fri Nov 22 13:41:23 2002 @@ -54,6 +54,18 @@ #include "../../scsi/scsi.h" #include "../../scsi/hosts.h" + +#define NCR5380_implementation_fields int port, ctrl +#define NCR5380_local_declare() struct Scsi_Host *_instance +#define NCR5380_setup(instance) _instance = instance + +#define NCR5380_read(reg) ecoscsi_read(_instance, reg) +#define NCR5380_write(reg, value) ecoscsi_write(_instance, reg, value) + +#define NCR5380_intr ecoscsi_intr +#define NCR5380_queue_command ecoscsi_queue_command +#define NCR5380_proc_info ecoscsi_proc_info + #include "../../scsi/NCR5380.h" #define ECOSCSI_PUBLIC_RELEASE 1 @@ -99,62 +111,45 @@ int ecoscsi_detect(Scsi_Host_Template * tpnt) { - struct Scsi_Host *instance; + struct Scsi_Host *host; tpnt->proc_name = "ecoscsi"; - instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); - if (!instance) + host = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); + if (!host) return 0; - instance->io_port = 0x80ce8000; - instance->n_io_port = 144; - instance->irq = IRQ_NONE; + host->io_port = 0x80ce8000; + host->n_io_port = 144; + host->irq = IRQ_NONE; - if ( !(request_region(instance->io_port, instance->n_io_port, "ecoscsi")) ) + if ( !(request_region(host->io_port, host->n_io_port, "ecoscsi")) ) goto unregister_scsi; - ecoscsi_write (instance, MODE_REG, 0x20); /* Is it really SCSI? */ - if (ecoscsi_read (instance, MODE_REG) != 0x20) /* Write to a reg. */ + ecoscsi_write (host, MODE_REG, 0x20); /* Is it really SCSI? */ + if (ecoscsi_read (host, MODE_REG) != 0x20) /* Write to a reg. */ goto release_reg; - ecoscsi_write( instance, MODE_REG, 0x00 ); /* it back. */ - if (ecoscsi_read (instance, MODE_REG) != 0x00) + ecoscsi_write( host, MODE_REG, 0x00 ); /* it back. */ + if (ecoscsi_read (host, MODE_REG) != 0x00) goto release_reg; - NCR5380_init(instance, 0); + NCR5380_init(host, 0); - if (instance->irq != IRQ_NONE) { - if (request_irq(instance->irq, do_ecoscsi_intr, SA_INTERRUPT, "ecoscsi", NULL)) { - printk("scsi%d: IRQ%d not free, interrupts disabled\n", - instance->host_no, instance->irq); - instance->irq = IRQ_NONE; - } - } - - if (instance->irq != IRQ_NONE) { - printk("scsi%d: eek! Interrupts enabled, but I don't think\n", instance->host_no); - printk("scsi%d: that the board had an interrupt!\n", instance->host_no); - } - - printk("scsi%d: at port %X irq", instance->host_no, instance->io_port); - if (instance->irq == IRQ_NONE) - printk ("s disabled"); - else - printk (" %d", instance->irq); + printk("scsi%d: at port 0x%08lx irqs disabled", host->host_no, host->io_port); printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", - CAN_QUEUE, CMD_PER_LUN, ECOSCSI_PUBLIC_RELEASE); - printk("\nscsi%d:", instance->host_no); - NCR5380_print_options(instance); + host->can_queue, host->cmd_per_lun, ECOSCSI_PUBLIC_RELEASE); + printk("\nscsi%d:", host->host_no); + NCR5380_print_options(host); printk("\n"); return 1; release_reg: - release_region(instance->io_port, instance->n_io_port); + release_region(host->io_port, host->n_io_port); unregister_scsi: - scsi_unregister(instance); - return 0 + scsi_unregister(host); + return 0; } int ecoscsi_release (struct Scsi_Host *shpnt) @@ -166,17 +161,18 @@ return 0; } -const char * ecoscsi_info (struct Scsi_Host *spnt) { - return ""; +const char * ecoscsi_info (struct Scsi_Host *spnt) +{ + return ""; } #if 0 #define STAT(p) inw(p + 144) -static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr, +static inline int NCR5380_pwrite(struct Scsi_Host *host, unsigned char *addr, int len) { - int iobase = instance->io_port; + int iobase = host->io_port; printk("writing %p len %d\n",addr, len); if(!len) return -1; @@ -187,11 +183,11 @@ } } -static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr, +static inline int NCR5380_pread(struct Scsi_Host *host, unsigned char *addr, int len) { - int iobase = instance->io_port; - int iobase2= instance->io_port + 0x100; + int iobase = host->io_port; + int iobase2= host->io_port + 0x100; unsigned char *start = addr; int s; printk("reading %p len %d\n",addr, len); @@ -236,22 +232,6 @@ } #endif #undef STAT - -#define NCR5380_implementation_fields \ - int port, ctrl - -#define NCR5380_local_declare() \ - struct Scsi_Host *_instance - -#define NCR5380_setup(instance) \ - _instance = instance - -#define NCR5380_read(reg) ecoscsi_read(_instance, reg) -#define NCR5380_write(reg, value) ecoscsi_write(_instance, reg, value) - -#define NCR5380_intr ecoscsi_intr -#define NCR5380_queue_command ecoscsi_queue_command -#define NCR5380_proc_info ecoscsi_proc_info int NCR5380_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); diff -Nru a/drivers/acorn/scsi/oak.c b/drivers/acorn/scsi/oak.c --- a/drivers/acorn/scsi/oak.c Fri Nov 22 13:41:17 2002 +++ b/drivers/acorn/scsi/oak.c Fri Nov 22 13:41:17 2002 @@ -138,12 +138,12 @@ struct Scsi_Host *host; int ret = -ENOMEM; - host = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); + host = scsi_register(&oakscsi_template, sizeof(struct NCR5380_hostdata)); if (!host) goto out; - host->io_port = ecard_address(ec, ECARD_MEMC, 0) - host->irq = IRQ_NONE; + host->io_port = ecard_address(ec, ECARD_MEMC, 0); + host->irq = IRQ_NONE; host->n_io_port = 255; ret = -EBUSY; @@ -155,7 +155,7 @@ printk("scsi%d: at port 0x%08lx irqs disabled", host->host_no, host->io_port); printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", - tpnt->can_queue, tpnt->cmd_per_lun, OAKSCSI_PUBLIC_RELEASE); + host->can_queue, host->cmd_per_lun, OAKSCSI_PUBLIC_RELEASE); printk("\nscsi%d:", host->host_no); NCR5380_print_options(host); printk("\n"); diff -Nru a/drivers/acpi/acpi_ksyms.c b/drivers/acpi/acpi_ksyms.c --- a/drivers/acpi/acpi_ksyms.c Fri Nov 22 13:41:18 2002 +++ b/drivers/acpi/acpi_ksyms.c Fri Nov 22 13:41:18 2002 @@ -24,6 +24,7 @@ */ #include +#include #include "include/acpi.h" #include "acpi_bus.h" @@ -141,3 +142,11 @@ extern int acpi_pci_irq_lookup (int segment, int bus, int device, int pin); EXPORT_SYMBOL(acpi_pci_irq_lookup); #endif /*CONFIG_ACPI_PCI */ + +#ifdef CONFIG_ACPI_EC +/* ACPI EC driver (ec.c) */ + +EXPORT_SYMBOL(ec_read); +EXPORT_SYMBOL(ec_write); +#endif + diff -Nru a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c --- a/drivers/acpi/dispatcher/dsutils.c Fri Nov 22 13:41:19 2002 +++ b/drivers/acpi/dispatcher/dsutils.c Fri Nov 22 13:41:19 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: dsutils - Dispatcher utilities - * $Revision: 96 $ + * $Revision: 97 $ * ******************************************************************************/ @@ -273,6 +273,45 @@ } return_ACPI_STATUS (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_clear_operands + * + * PARAMETERS: Walk_state - Current walk state with operands on stack + * + * RETURN: None + * + * DESCRIPTION: Clear all operands on the current walk state operand stack. + * + ******************************************************************************/ + +void +acpi_ds_clear_operands ( + acpi_walk_state *walk_state) +{ + u32 i; + + + ACPI_FUNCTION_TRACE_PTR ("Acpi_ds_clear_operands", walk_state); + + + /* + * Remove a reference on each operand on the stack + */ + for (i = 0; i < walk_state->num_operands; i++) { + /* + * Remove a reference to all operands, including both + * "Arguments" and "Targets". + */ + acpi_ut_remove_reference (walk_state->operands[i]); + walk_state->operands[i] = NULL; + } + + walk_state->num_operands = 0; + return_VOID; } #endif diff -Nru a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c --- a/drivers/acpi/dispatcher/dswexec.c Fri Nov 22 13:41:23 2002 +++ b/drivers/acpi/dispatcher/dswexec.c Fri Nov 22 13:41:23 2002 @@ -2,7 +2,7 @@ * * Module Name: dswexec - Dispatcher method execution callbacks; * dispatch to interpreter. - * $Revision: 95 $ + * $Revision: 96 $ * *****************************************************************************/ @@ -329,7 +329,6 @@ u32 op_class; acpi_parse_object *next_op; acpi_parse_object *first_arg; - u32 i; ACPI_FUNCTION_TRACE_PTR ("Ds_exec_end_op", walk_state); @@ -406,15 +405,7 @@ /* Always delete the argument objects and clear the operand stack */ - for (i = 0; i < walk_state->num_operands; i++) { - /* - * Remove a reference to all operands, including both - * "Arguments" and "Targets". - */ - acpi_ut_remove_reference (walk_state->operands[i]); - walk_state->operands[i] = NULL; - } - walk_state->num_operands = 0; + acpi_ds_clear_operands (walk_state); /* * If a result object was returned from above, push it on the @@ -475,6 +466,9 @@ */ status = acpi_ds_resolve_operands (walk_state); if (ACPI_FAILURE (status)) { + /* On error, clear all resolved operands */ + + acpi_ds_clear_operands (walk_state); break; } diff -Nru a/drivers/acpi/ec.c b/drivers/acpi/ec.c --- a/drivers/acpi/ec.c Fri Nov 22 13:41:20 2002 +++ b/drivers/acpi/ec.c Fri Nov 22 13:41:20 2002 @@ -92,6 +92,9 @@ /* If we find an EC via the ECDT, we need to keep a ptr to its context */ static struct acpi_ec *ec_ecdt; +/* External interfaces use first EC only, so remember */ +static struct acpi_device *first_ec; + /* -------------------------------------------------------------------------- Transaction Management -------------------------------------------------------------------------- */ @@ -236,6 +239,47 @@ return_VALUE(result); } +/* + * Externally callable EC access functions. For now, assume 1 EC only + */ +int +ec_read(u8 addr, u8 *val) +{ + struct acpi_ec *ec; + int err; + u32 temp_data; + + if (!first_ec) + return -ENODEV; + + ec = acpi_driver_data(first_ec); + + err = acpi_ec_read(ec, addr, &temp_data); + + if (!err) { + *val = temp_data; + return 0; + } + else + return err; +} + +int +ec_write(u8 addr, u8 val) +{ + struct acpi_ec *ec; + int err; + + if (!first_ec) + return -ENODEV; + + ec = acpi_driver_data(first_ec); + + err = acpi_ec_write(ec, addr, val); + + return err; +} + static int acpi_ec_query ( @@ -540,11 +584,15 @@ acpi_evaluate_integer(ec->handle, "_GLK", NULL, &ec->global_lock); /* If our UID matches the UID for the ECDT-enumerated EC, - we already found this EC, so abort. */ + we now have the *real* EC info, so kill the makeshift one.*/ acpi_evaluate_integer(ec->handle, "_UID", NULL, &uid); if (ec_ecdt && ec_ecdt->uid == uid) { - result = -ENODEV; - goto end; + acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, + ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); + + acpi_remove_gpe_handler(ec_ecdt->gpe_bit, &acpi_ec_gpe_handler); + + kfree(ec_ecdt); } /* Get GPE bit assignment (EC events). */ @@ -564,6 +612,9 @@ acpi_device_name(device), acpi_device_bid(device), (u32) ec->gpe_bit); + if (!first_ec) + first_ec = device; + end: if (result) kfree(ec); @@ -584,7 +635,7 @@ if (!device) return_VALUE(-EINVAL); - ec = (struct acpi_ec *) acpi_driver_data(device); + ec = acpi_driver_data(device); acpi_ec_remove_fs(device); @@ -609,7 +660,7 @@ if (!device) return_VALUE(-EINVAL); - ec = (struct acpi_ec *) acpi_driver_data(device); + ec = acpi_driver_data(device); if (!ec) return_VALUE(-EINVAL); @@ -688,7 +739,7 @@ if (!device) return_VALUE(-EINVAL); - ec = (struct acpi_ec *) acpi_driver_data(device); + ec = acpi_driver_data(device); status = acpi_remove_address_space_handler(ec->handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); @@ -711,50 +762,50 @@ status = acpi_get_firmware_table("ECDT", 1, ACPI_LOGICAL_ADDRESSING, (acpi_table_header **) &ecdt_ptr); - if (ACPI_SUCCESS(status)) { - printk(KERN_INFO PREFIX "Found ECDT\n"); + if (ACPI_FAILURE(status)) + return 0; + + printk(KERN_INFO PREFIX "Found ECDT\n"); + + /* + * Generate a temporary ec context to use until the namespace is scanned + */ + ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); + if (!ec_ecdt) + return -ENOMEM; + memset(ec_ecdt, 0, sizeof(struct acpi_ec)); + + ec_ecdt->command_addr = ecdt_ptr->ec_control; + ec_ecdt->status_addr = ecdt_ptr->ec_control; + ec_ecdt->data_addr = ecdt_ptr->ec_data; + ec_ecdt->gpe_bit = ecdt_ptr->gpe_bit; + ec_ecdt->lock = SPIN_LOCK_UNLOCKED; + /* use the GL just to be safe */ + ec_ecdt->global_lock = TRUE; + ec_ecdt->uid = ecdt_ptr->uid; - /* - * TODO: When the new driver model allows it, simply tell the - * EC driver it has a new device via that, instead if this. - */ - ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); - if (!ec_ecdt) - return -ENOMEM; - memset(ec_ecdt, 0, sizeof(struct acpi_ec)); - - ec_ecdt->command_addr = ecdt_ptr->ec_control; - ec_ecdt->status_addr = ecdt_ptr->ec_control; - ec_ecdt->data_addr = ecdt_ptr->ec_data; - ec_ecdt->gpe_bit = ecdt_ptr->gpe_bit; - ec_ecdt->lock = SPIN_LOCK_UNLOCKED; - /* use the GL just to be safe */ - ec_ecdt->global_lock = TRUE; - ec_ecdt->uid = ecdt_ptr->uid; - - status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->handle); - if (ACPI_FAILURE(status)) { - goto error; - } - - /* - * Install GPE handler - */ - status = acpi_install_gpe_handler(ec_ecdt->gpe_bit, - ACPI_EVENT_EDGE_TRIGGERED, &acpi_ec_gpe_handler, - ec_ecdt); - if (ACPI_FAILURE(status)) { - goto error; - } - - status = acpi_install_address_space_handler (ACPI_ROOT_OBJECT, - ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, - &acpi_ec_space_setup, ec_ecdt); - if (ACPI_FAILURE(status)) { - acpi_remove_gpe_handler(ec_ecdt->gpe_bit, - &acpi_ec_gpe_handler); - goto error; - } + status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->handle); + if (ACPI_FAILURE(status)) { + goto error; + } + + /* + * Install GPE handler + */ + status = acpi_install_gpe_handler(ec_ecdt->gpe_bit, + ACPI_EVENT_EDGE_TRIGGERED, &acpi_ec_gpe_handler, + ec_ecdt); + if (ACPI_FAILURE(status)) { + goto error; + } + + status = acpi_install_address_space_handler (ACPI_ROOT_OBJECT, + ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, + &acpi_ec_space_setup, ec_ecdt); + if (ACPI_FAILURE(status)) { + acpi_remove_gpe_handler(ec_ecdt->gpe_bit, + &acpi_ec_gpe_handler); + goto error; } return 0; @@ -796,20 +847,6 @@ /* EC driver currently not unloadable */ #if 0 static void __exit -acpi_ec_ecdt_exit (void) -{ - if (!ec_ecdt) - return; - - acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, - ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); - - acpi_remove_gpe_handler(ec_ecdt->gpe_bit, &acpi_ec_gpe_handler); - - kfree(ec_ecdt); -} - -static void __exit acpi_ec_exit (void) { ACPI_FUNCTION_TRACE("acpi_ec_exit"); @@ -817,8 +854,6 @@ acpi_bus_unregister_driver(&acpi_ec_driver); remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir); - - acpi_ec_ecdt_exit(); return_VOID; } diff -Nru a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c --- a/drivers/acpi/events/evmisc.c Fri Nov 22 13:41:21 2002 +++ b/drivers/acpi/events/evmisc.c Fri Nov 22 13:41:21 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: evmisc - Miscellaneous event manager support functions - * $Revision: 58 $ + * $Revision: 59 $ * *****************************************************************************/ @@ -228,7 +228,8 @@ if (!handler_obj) { /* There is no per-device notify handler for this device */ - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "No notify handler for node %p \n", node)); + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "No notify handler for [%4.4s] node %p\n", node->name.ascii, node)); } return (status); @@ -466,7 +467,7 @@ if (acquired) { /* We got the lock */ - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Acquired the HW Global Lock\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Acquired the HW Global Lock\n")); acpi_gbl_global_lock_acquired = TRUE; return_ACPI_STATUS (AE_OK); @@ -476,7 +477,7 @@ * Did not get the lock. The pending bit was set above, and we must now * wait until we get the global lock released interrupt. */ - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Waiting for the HW Global Lock\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Waiting for the HW Global Lock\n")); /* * Acquire the global lock semaphore first. diff -Nru a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c --- a/drivers/acpi/executer/exconvrt.c Fri Nov 22 13:41:17 2002 +++ b/drivers/acpi/executer/exconvrt.c Fri Nov 22 13:41:17 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: exconvrt - Object conversion routines - * $Revision: 41 $ + * $Revision: 44 $ * *****************************************************************************/ @@ -147,10 +147,15 @@ return_ACPI_STATUS (AE_NO_MEMORY); } - /* Save the Result, delete original descriptor, store new descriptor */ + /* Save the Result */ ret_desc->integer.value = result; + /* + * If we are about to overwrite the original object on the operand stack, + * we must remove a reference on the original object because we are + * essentially removing it from the stack. + */ if (*result_desc == obj_desc) { if (walk_state->opcode != AML_STORE_OP) { acpi_ut_remove_reference (obj_desc); @@ -191,76 +196,50 @@ switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { + case ACPI_TYPE_BUFFER: + + /* No conversion necessary */ + + *result_desc = obj_desc; + return_ACPI_STATUS (AE_OK); + + case ACPI_TYPE_INTEGER: /* - * Create a new Buffer object + * Create a new Buffer object. + * Need enough space for one integer */ - ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); + ret_desc = acpi_ut_create_buffer_object (acpi_gbl_integer_byte_width); if (!ret_desc) { return_ACPI_STATUS (AE_NO_MEMORY); } - /* Need enough space for one integer */ - - new_buf = ACPI_MEM_CALLOCATE (acpi_gbl_integer_byte_width); - if (!new_buf) { - ACPI_REPORT_ERROR - (("Ex_convert_to_buffer: Buffer allocation failure\n")); - acpi_ut_remove_reference (ret_desc); - return_ACPI_STATUS (AE_NO_MEMORY); - } - /* Copy the integer to the buffer */ + new_buf = ret_desc->buffer.pointer; for (i = 0; i < acpi_gbl_integer_byte_width; i++) { new_buf[i] = (u8) (obj_desc->integer.value >> (i * 8)); } - - /* Complete buffer object initialization */ - - ret_desc->buffer.flags |= AOPOBJ_DATA_VALID; - ret_desc->buffer.pointer = new_buf; - ret_desc->buffer.length = acpi_gbl_integer_byte_width; - - /* Return the new buffer descriptor */ - - *result_desc = ret_desc; break; case ACPI_TYPE_STRING: + /* * Create a new Buffer object + * Size will be the string length */ - ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); + ret_desc = acpi_ut_create_buffer_object (obj_desc->string.length); if (!ret_desc) { return_ACPI_STATUS (AE_NO_MEMORY); } - /* Need enough space for one integer */ + /* Copy the string to the buffer */ - new_buf = ACPI_MEM_CALLOCATE (obj_desc->string.length); - if (!new_buf) { - ACPI_REPORT_ERROR - (("Ex_convert_to_buffer: Buffer allocation failure\n")); - acpi_ut_remove_reference (ret_desc); - return_ACPI_STATUS (AE_NO_MEMORY); - } - - ACPI_STRNCPY ((char *) new_buf, (char *) obj_desc->string.pointer, obj_desc->string.length); - ret_desc->buffer.flags |= AOPOBJ_DATA_VALID; - ret_desc->buffer.pointer = new_buf; - ret_desc->buffer.length = obj_desc->string.length; - - /* Return the new buffer descriptor */ - - *result_desc = ret_desc; - break; - - - case ACPI_TYPE_BUFFER: - *result_desc = obj_desc; + new_buf = ret_desc->buffer.pointer; + ACPI_STRNCPY ((char *) new_buf, (char *) obj_desc->string.pointer, + obj_desc->string.length); break; @@ -270,7 +249,20 @@ /* Mark buffer initialized */ - (*result_desc)->common.flags |= AOPOBJ_DATA_VALID; + ret_desc->common.flags |= AOPOBJ_DATA_VALID; + + /* + * If we are about to overwrite the original object on the operand stack, + * we must remove a reference on the original object because we are + * essentially removing it from the stack. + */ + if (*result_desc == obj_desc) { + if (walk_state->opcode != AML_STORE_OP) { + acpi_ut_remove_reference (obj_desc); + } + } + + *result_desc = ret_desc; return_ACPI_STATUS (AE_OK); } @@ -405,6 +397,19 @@ switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { + case ACPI_TYPE_STRING: + + if (max_length >= obj_desc->string.length) { + *result_desc = obj_desc; + return_ACPI_STATUS (AE_OK); + } + else { + /* Must copy the string first and then truncate it */ + + return_ACPI_STATUS (AE_NOT_IMPLEMENTED); + } + + case ACPI_TYPE_INTEGER: string_length = acpi_gbl_integer_byte_width * 2; @@ -446,16 +451,6 @@ } ret_desc->buffer.pointer = new_buf; - - /* Return the new buffer descriptor */ - - if (*result_desc == obj_desc) { - if (walk_state->opcode != AML_STORE_OP) { - acpi_ut_remove_reference (obj_desc); - } - } - - *result_desc = ret_desc; break; @@ -511,37 +506,26 @@ new_buf [index-1] = 0; ret_desc->buffer.pointer = new_buf; ret_desc->string.length = (u32) ACPI_STRLEN ((char *) new_buf); - - /* Return the new buffer descriptor */ - - if (*result_desc == obj_desc) { - if (walk_state->opcode != AML_STORE_OP) { - acpi_ut_remove_reference (obj_desc); - } - } - - *result_desc = ret_desc; break; - case ACPI_TYPE_STRING: - - if (max_length >= obj_desc->string.length) { - *result_desc = obj_desc; - } + default: + return_ACPI_STATUS (AE_TYPE); + } - else { - /* Must copy the string first and then truncate it */ - return_ACPI_STATUS (AE_NOT_IMPLEMENTED); + /* + * If we are about to overwrite the original object on the operand stack, + * we must remove a reference on the original object because we are + * essentially removing it from the stack. + */ + if (*result_desc == obj_desc) { + if (walk_state->opcode != AML_STORE_OP) { + acpi_ut_remove_reference (obj_desc); } - break; - - - default: - return_ACPI_STATUS (AE_TYPE); } + *result_desc = ret_desc; return_ACPI_STATUS (AE_OK); } diff -Nru a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c --- a/drivers/acpi/executer/exfield.c Fri Nov 22 13:41:17 2002 +++ b/drivers/acpi/executer/exfield.c Fri Nov 22 13:41:17 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: exfield - ACPI AML (p-code) execution - field manipulation - * $Revision: 113 $ + * $Revision: 115 $ * *****************************************************************************/ @@ -27,8 +27,6 @@ #include "acpi.h" #include "acdispat.h" #include "acinterp.h" -#include "acevents.h" -#include "amlcode.h" #define _COMPONENT ACPI_EXECUTER @@ -90,25 +88,11 @@ * This is an SMBus read. We must create a buffer to hold the data * and directly access the region handler. */ - buffer_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); + buffer_desc = acpi_ut_create_buffer_object (ACPI_SMBUS_BUFFER_SIZE); if (!buffer_desc) { return_ACPI_STATUS (AE_NO_MEMORY); } - /* Create the actual read buffer */ - - buffer_desc->buffer.pointer = ACPI_MEM_CALLOCATE (ACPI_SMBUS_BUFFER_SIZE); - if (!buffer_desc->buffer.pointer) { - acpi_ut_remove_reference (buffer_desc); - return_ACPI_STATUS (AE_NO_MEMORY); - } - - /* Complete the buffer object initialization */ - - buffer_desc->common.flags = AOPOBJ_DATA_VALID; - buffer_desc->buffer.length = ACPI_SMBUS_BUFFER_SIZE; - buffer = buffer_desc->buffer.pointer; - /* Lock entire transaction if requested */ locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags); @@ -118,7 +102,7 @@ * Note: Smbus protocol value is passed in upper 16-bits of Function */ status = acpi_ex_access_region (obj_desc, 0, - (acpi_integer *) buffer_desc->buffer.pointer, + ACPI_CAST_PTR (acpi_integer, buffer_desc->buffer.pointer), ACPI_READ | (obj_desc->field.attribute << 16)); acpi_ex_release_global_lock (locked); goto exit; @@ -138,23 +122,10 @@ if (length > acpi_gbl_integer_byte_width) { /* Field is too large for an Integer, create a Buffer instead */ - buffer_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); + buffer_desc = acpi_ut_create_buffer_object (length); if (!buffer_desc) { return_ACPI_STATUS (AE_NO_MEMORY); } - - /* Create the actual read buffer */ - - buffer_desc->buffer.pointer = ACPI_MEM_CALLOCATE (length); - if (!buffer_desc->buffer.pointer) { - acpi_ut_remove_reference (buffer_desc); - return_ACPI_STATUS (AE_NO_MEMORY); - } - - /* Complete the buffer object initialization */ - - buffer_desc->common.flags = AOPOBJ_DATA_VALID; - buffer_desc->buffer.length = length; buffer = buffer_desc->buffer.pointer; } else { @@ -270,26 +241,12 @@ return_ACPI_STATUS (AE_AML_BUFFER_LIMIT); } - buffer_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); + buffer_desc = acpi_ut_create_buffer_object (ACPI_SMBUS_BUFFER_SIZE); if (!buffer_desc) { return_ACPI_STATUS (AE_NO_MEMORY); } - /* Create the actual read buffer */ - - buffer_desc->buffer.pointer = ACPI_MEM_CALLOCATE (ACPI_SMBUS_BUFFER_SIZE); - if (!buffer_desc->buffer.pointer) { - acpi_ut_remove_reference (buffer_desc); - return_ACPI_STATUS (AE_NO_MEMORY); - } - - /* Complete the buffer object initialization */ - - buffer_desc->common.flags = AOPOBJ_DATA_VALID; - buffer_desc->buffer.length = ACPI_SMBUS_BUFFER_SIZE; buffer = buffer_desc->buffer.pointer; - - ACPI_MEMCPY (buffer, source_desc->buffer.pointer, ACPI_SMBUS_BUFFER_SIZE); /* Lock entire transaction if requested */ diff -Nru a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c --- a/drivers/acpi/executer/exmisc.c Fri Nov 22 13:41:22 2002 +++ b/drivers/acpi/executer/exmisc.c Fri Nov 22 13:41:22 2002 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes - * $Revision: 110 $ + * $Revision: 112 $ * *****************************************************************************/ @@ -148,9 +148,8 @@ acpi_operand_object **actual_return_desc, acpi_walk_state *walk_state) { - acpi_status status; acpi_operand_object *return_desc; - NATIVE_CHAR *new_buf; + u8 *new_buf; u8 *end_tag1; u8 *end_tag2; ACPI_SIZE length1; @@ -168,54 +167,35 @@ return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } - /* Create a new buffer object for the result */ - - return_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); - if (!return_desc) { - return_ACPI_STATUS (AE_NO_MEMORY); - } - - /* Allocate a new buffer for the result */ + /* Compute the length of each part */ length1 = ACPI_PTR_DIFF (end_tag1, obj_desc1->buffer.pointer); length2 = ACPI_PTR_DIFF (end_tag2, obj_desc2->buffer.pointer) + 2; /* Size of END_TAG */ - new_buf = ACPI_MEM_ALLOCATE (length1 + length2); - if (!new_buf) { - ACPI_REPORT_ERROR - (("Ex_concat_template: Buffer allocation failure\n")); - status = AE_NO_MEMORY; - goto cleanup; + /* Create a new buffer object for the result */ + + return_desc = acpi_ut_create_buffer_object (length1 + length2); + if (!return_desc) { + return_ACPI_STATUS (AE_NO_MEMORY); } /* Copy the templates to the new descriptor */ + new_buf = return_desc->buffer.pointer; ACPI_MEMCPY (new_buf, obj_desc1->buffer.pointer, length1); ACPI_MEMCPY (new_buf + length1, obj_desc2->buffer.pointer, length2); - /* Complete the buffer object initialization */ - - return_desc->common.flags = AOPOBJ_DATA_VALID; - return_desc->buffer.pointer = (u8 *) new_buf; - return_desc->buffer.length = (u32) (length1 + length2); - /* Compute the new checksum */ - new_buf[return_desc->buffer.length - 1] = (NATIVE_CHAR) + new_buf[return_desc->buffer.length - 1] = acpi_ut_generate_checksum (return_desc->buffer.pointer, - (return_desc->buffer.length - 1)); + (return_desc->buffer.length - 1)); /* Return the completed template descriptor */ *actual_return_desc = return_desc; return_ACPI_STATUS (AE_OK); - - -cleanup: - - acpi_ut_remove_reference (return_desc); - return_ACPI_STATUS (status); } @@ -262,22 +242,14 @@ case ACPI_TYPE_INTEGER: /* Result of two Integers is a Buffer */ + /* Need enough buffer space for two integers */ - return_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); + return_desc = acpi_ut_create_buffer_object (acpi_gbl_integer_byte_width * 2); if (!return_desc) { return (AE_NO_MEMORY); } - /* Need enough buffer space for two integers */ - - return_desc->buffer.length = acpi_gbl_integer_byte_width * 2; - new_buf = ACPI_MEM_CALLOCATE (return_desc->buffer.length); - if (!new_buf) { - ACPI_REPORT_ERROR - (("Ex_do_concatenate: Buffer allocation failure\n")); - status = AE_NO_MEMORY; - goto cleanup; - } + new_buf = (NATIVE_CHAR *) return_desc->buffer.pointer; /* Convert the first integer */ @@ -295,10 +267,6 @@ this_integer >>= 8; } - /* Complete the buffer object initialization */ - - return_desc->common.flags = AOPOBJ_DATA_VALID; - return_desc->buffer.pointer = (u8 *) new_buf; break; @@ -340,19 +308,14 @@ /* Result of two Buffers is a Buffer */ - return_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); + return_desc = acpi_ut_create_buffer_object ( + (ACPI_SIZE) obj_desc1->buffer.length + + (ACPI_SIZE) obj_desc2->buffer.length); if (!return_desc) { return (AE_NO_MEMORY); } - new_buf = ACPI_MEM_ALLOCATE ((ACPI_SIZE) obj_desc1->buffer.length + - (ACPI_SIZE) obj_desc2->buffer.length); - if (!new_buf) { - ACPI_REPORT_ERROR - (("Ex_do_concatenate: Buffer allocation failure\n")); - status = AE_NO_MEMORY; - goto cleanup; - } + new_buf = (NATIVE_CHAR *) return_desc->buffer.pointer; /* Concatenate the buffers */ @@ -361,12 +324,6 @@ ACPI_MEMCPY (new_buf + obj_desc1->buffer.length, obj_desc2->buffer.pointer, obj_desc2->buffer.length); - /* Complete the buffer object initialization */ - - return_desc->common.flags = AOPOBJ_DATA_VALID; - return_desc->buffer.pointer = (u8 *) new_buf; - return_desc->buffer.length = obj_desc1->buffer.length + - obj_desc2->buffer.length; break; diff -Nru a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c --- a/drivers/acpi/executer/exoparg1.c Fri Nov 22 13:41:23 2002 +++ b/drivers/acpi/executer/exoparg1.c Fri Nov 22 13:41:23 2002 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: exoparg1 - AML execution - opcodes with 1 argument - * $Revision: 145 $ + * $Revision: 146 $ * *****************************************************************************/ @@ -345,12 +345,6 @@ * return FALSE */ return_desc->integer.value = 0; - - /* - * Must delete the result descriptor since there is no reference - * being returned - */ - acpi_ut_remove_reference (operand[1]); goto cleanup; } @@ -388,6 +382,8 @@ if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } + + /* It is possible that the Store already produced a return object */ if (!walk_state->result_obj) { /* diff -Nru a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c --- a/drivers/acpi/executer/exoparg2.c Fri Nov 22 13:41:20 2002 +++ b/drivers/acpi/executer/exoparg2.c Fri Nov 22 13:41:20 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: exoparg2 - AML execution - opcodes with 2 arguments - * $Revision: 114 $ + * $Revision: 115 $ * *****************************************************************************/ @@ -414,39 +414,10 @@ goto cleanup; } - if ((ACPI_GET_OBJECT_TYPE (operand[2]) == ACPI_TYPE_INTEGER) && - (operand[2]->common.flags & AOPOBJ_AML_CONSTANT)) { - /* - * There is no actual result descriptor (the Zero_op/Constant Result - * descriptor is a placeholder), so just delete the placeholder and - * return a reference to the package element - */ - acpi_ut_remove_reference (operand[2]); - } - - else { - /* - * Each element of the package is an internal object. Get the one - * we are after. - */ - temp_desc = operand[0]->package.elements [index]; - return_desc->reference.opcode = AML_INDEX_OP; - return_desc->reference.target_type = ACPI_GET_OBJECT_TYPE (temp_desc); - return_desc->reference.object = temp_desc; - - status = acpi_ex_store (return_desc, operand[2], walk_state); - return_desc->reference.object = NULL; - } - - /* - * The local return object must always be a reference to the package element, - * not the element itself. - */ - return_desc->reference.opcode = AML_INDEX_OP; return_desc->reference.target_type = ACPI_TYPE_PACKAGE; + return_desc->reference.object = operand[0]->package.elements [index]; return_desc->reference.where = &operand[0]->package.elements [index]; } - else { /* Object to be indexed is a Buffer */ @@ -457,13 +428,20 @@ goto cleanup; } - return_desc->reference.opcode = AML_INDEX_OP; return_desc->reference.target_type = ACPI_TYPE_BUFFER_FIELD; - return_desc->reference.object = operand[0]; - return_desc->reference.offset = index; - - status = acpi_ex_store (return_desc, operand[2], walk_state); + return_desc->reference.object = operand[0]; } + + /* Complete the Index reference object */ + + return_desc->reference.opcode = AML_INDEX_OP; + return_desc->reference.offset = index; + + /* Store the reference to the Target */ + + status = acpi_ex_store (return_desc, operand[2], walk_state); + + /* Return the reference */ walk_state->result_obj = return_desc; goto cleanup; diff -Nru a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c --- a/drivers/acpi/executer/exresnte.c Fri Nov 22 13:41:18 2002 +++ b/drivers/acpi/executer/exresnte.c Fri Nov 22 13:41:18 2002 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: exresnte - AML Interpreter object resolution - * $Revision: 60 $ + * $Revision: 61 $ * *****************************************************************************/ @@ -85,8 +85,8 @@ source_desc = acpi_ns_get_attached_object (node); entry_type = acpi_ns_get_type ((acpi_handle) node); - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Entry=%p Source_desc=%p Type=%X\n", - node, source_desc, entry_type)); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Entry=%p Source_desc=%p [%s]\n", + node, source_desc, acpi_ut_get_type_name (entry_type))); if (entry_type == ACPI_TYPE_LOCAL_ALIAS) { /* There is always exactly one level of indirection */ diff -Nru a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c --- a/drivers/acpi/executer/exresop.c Fri Nov 22 13:41:23 2002 +++ b/drivers/acpi/executer/exresop.c Fri Nov 22 13:41:23 2002 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: exresop - AML Interpreter operand/object resolution - * $Revision: 59 $ + * $Revision: 60 $ * *****************************************************************************/ @@ -390,14 +390,6 @@ return_ACPI_STATUS (status); } - - if (obj_desc != *stack_ptr) { - /* - * We just created a new object, remove a reference - * on the original operand object - */ - acpi_ut_remove_reference (obj_desc); - } goto next_operand; @@ -420,14 +412,6 @@ return_ACPI_STATUS (status); } - - if (obj_desc != *stack_ptr) { - /* - * We just created a new object, remove a reference - * on the original operand object - */ - acpi_ut_remove_reference (obj_desc); - } goto next_operand; @@ -449,14 +433,6 @@ } return_ACPI_STATUS (status); - } - - if (obj_desc != *stack_ptr) { - /* - * We just created a new object, remove a reference - * on the original operand object - */ - acpi_ut_remove_reference (obj_desc); } goto next_operand; diff -Nru a/drivers/acpi/include/acconfig.h b/drivers/acpi/include/acconfig.h --- a/drivers/acpi/include/acconfig.h Fri Nov 22 13:41:22 2002 +++ b/drivers/acpi/include/acconfig.h Fri Nov 22 13:41:22 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acconfig.h - Global configuration constants - * $Revision: 117 $ + * $Revision: 118 $ * *****************************************************************************/ @@ -54,7 +54,7 @@ /* Version string */ -#define ACPI_CA_VERSION 0x20021111 +#define ACPI_CA_VERSION 0x20021115 /* Version of ACPI supported */ diff -Nru a/drivers/acpi/include/acdispat.h b/drivers/acpi/include/acdispat.h --- a/drivers/acpi/include/acdispat.h Fri Nov 22 13:41:22 2002 +++ b/drivers/acpi/include/acdispat.h Fri Nov 22 13:41:22 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acdispat.h - dispatcher (parser to interpreter interface) - * $Revision: 54 $ + * $Revision: 55 $ * *****************************************************************************/ @@ -376,6 +376,10 @@ acpi_status acpi_ds_resolve_operands ( + acpi_walk_state *walk_state); + +void +acpi_ds_clear_operands ( acpi_walk_state *walk_state); diff -Nru a/drivers/acpi/include/acutils.h b/drivers/acpi/include/acutils.h --- a/drivers/acpi/include/acutils.h Fri Nov 22 13:41:17 2002 +++ b/drivers/acpi/include/acutils.h Fri Nov 22 13:41:17 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acutils.h -- prototypes for the common (subsystem-wide) procedures - * $Revision: 147 $ + * $Revision: 148 $ * *****************************************************************************/ @@ -530,6 +530,10 @@ u8 acpi_ut_valid_internal_object ( void *object); + +acpi_operand_object * +acpi_ut_create_buffer_object ( + ACPI_SIZE buffer_size); /* diff -Nru a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c --- a/drivers/acpi/namespace/nseval.c Fri Nov 22 13:41:19 2002 +++ b/drivers/acpi/namespace/nseval.c Fri Nov 22 13:41:19 2002 @@ -2,7 +2,7 @@ * * Module Name: nseval - Object evaluation interfaces -- includes control * method lookup and execution. - * $Revision: 118 $ + * $Revision: 119 $ * ******************************************************************************/ @@ -383,7 +383,7 @@ return_ACPI_STATUS (AE_NULL_OBJECT); } - ACPI_DUMP_PATHNAME (method_node, "Ns_execute_control_method: Executing", + ACPI_DUMP_PATHNAME (method_node, "Execute Method:", ACPI_LV_INFO, _COMPONENT); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Method at AML address %p Length %X\n", diff -Nru a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c --- a/drivers/acpi/namespace/nsinit.c Fri Nov 22 13:41:18 2002 +++ b/drivers/acpi/namespace/nsinit.c Fri Nov 22 13:41:18 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: nsinit - namespace initialization - * $Revision: 49 $ + * $Revision: 50 $ * *****************************************************************************/ @@ -317,7 +317,7 @@ ACPI_FUNCTION_TRACE ("Ns_init_one_device"); - if (!(acpi_dbg_level & ACPI_LV_INIT)) { + if ((acpi_dbg_level <= ACPI_LV_ALL_EXCEPTIONS) && (!(acpi_dbg_level & ACPI_LV_INFO))) { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, ".")); } diff -Nru a/drivers/acpi/osl.c b/drivers/acpi/osl.c --- a/drivers/acpi/osl.c Fri Nov 22 13:41:22 2002 +++ b/drivers/acpi/osl.c Fri Nov 22 13:41:22 2002 @@ -525,7 +525,7 @@ if (!dpc || !dpc->function) return_ACPI_STATUS (AE_BAD_PARAMETER); - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Executing function [%p(%p)].\n", dpc->function, dpc->context)); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Executing function [%p(%p)].\n", dpc->function, dpc->context)); dpc->function(dpc->context); @@ -549,7 +549,7 @@ return_VOID; } - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Creating new thread to run function [%p(%p)].\n", dpc->function, dpc->context)); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Creating new thread to run function [%p(%p)].\n", dpc->function, dpc->context)); thread_pid = kernel_thread(acpi_os_queue_exec, dpc, (CLONE_FS | CLONE_FILES | SIGCHLD)); @@ -571,7 +571,7 @@ ACPI_FUNCTION_TRACE ("os_queue_for_execution"); - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Scheduling function [%p(%p)] for deferred execution.\n", function, context)); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Scheduling function [%p(%p)] for deferred execution.\n", function, context)); if (!function) return_ACPI_STATUS (AE_BAD_PARAMETER); @@ -657,7 +657,7 @@ *handle = (acpi_handle*)sem; - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Creating semaphore[%p|%d].\n", *handle, initial_units)); + ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Creating semaphore[%p|%d].\n", *handle, initial_units)); return_ACPI_STATUS (AE_OK); } @@ -681,7 +681,7 @@ if (!sem) return_ACPI_STATUS (AE_BAD_PARAMETER); - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Deleting semaphore[%p].\n", handle)); + ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Deleting semaphore[%p].\n", handle)); acpi_os_free(sem); sem = NULL; @@ -716,7 +716,7 @@ if (units > 1) return_ACPI_STATUS (AE_SUPPORT); - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Waiting for semaphore[%p|%d|%d]\n", handle, units, timeout)); + ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n", handle, units, timeout)); if (in_atomic()) timeout = 0; @@ -740,9 +740,7 @@ * ------------------ */ case ACPI_WAIT_FOREVER: - ret = down_interruptible(sem); - if (ret < 0) - status = AE_ERROR; + down(sem); break; /* @@ -763,16 +761,17 @@ } if (ret != 0) - status = AE_TIME; - } + status = AE_TIME; + } break; } if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Failed to acquire semaphore[%p|%d|%d]\n", handle, units, timeout)); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Failed to acquire semaphore[%p|%d|%d], %s\n", + handle, units, timeout, acpi_format_exception(status))); } else { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Acquired semaphore[%p|%d|%d]\n", handle, units, timeout)); + ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Acquired semaphore[%p|%d|%d]\n", handle, units, timeout)); } return_ACPI_STATUS (status); @@ -797,7 +796,7 @@ if (units > 1) return_ACPI_STATUS (AE_SUPPORT); - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Signaling semaphore[%p|%d]\n", handle, units)); + ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Signaling semaphore[%p|%d]\n", handle, units)); up(sem); diff -Nru a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c --- a/drivers/acpi/parser/psparse.c Fri Nov 22 13:41:18 2002 +++ b/drivers/acpi/parser/psparse.c Fri Nov 22 13:41:18 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: psparse - Parser top level AML parse routines - * $Revision: 134 $ + * $Revision: 135 $ * *****************************************************************************/ @@ -1078,7 +1078,8 @@ } ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, - "Completed one call to walk loop, State=%p\n", walk_state)); + "Completed one call to walk loop, %s State=%p\n", + acpi_format_exception (status), walk_state)); if (status == AE_CTRL_TRANSFER) { /* @@ -1094,10 +1095,15 @@ walk_state = acpi_ds_get_current_walk_state (thread); continue; } - else if (status == AE_CTRL_TERMINATE) { status = AE_OK; } + else if (status != AE_OK) { + ACPI_REPORT_ERROR (("Method execution failed, %s\n", + acpi_format_exception (status))); + ACPI_DUMP_PATHNAME (walk_state->method_node, "Method pathname: ", + ACPI_LV_ERROR, _COMPONENT); + } /* We are done with this walk, move on to the parent if any */ @@ -1150,11 +1156,6 @@ /* On error, delete any return object */ acpi_ut_remove_reference (previous_walk_state->return_desc); - - ACPI_REPORT_ERROR (("Method execution failed, %s\n", - acpi_format_exception (status))); - ACPI_DUMP_PATHNAME (walk_state->method_node, "Method pathname: ", - ACPI_LV_ERROR, _COMPONENT); } } @@ -1165,7 +1166,6 @@ else if (previous_walk_state->caller_return_desc) { *(previous_walk_state->caller_return_desc) = previous_walk_state->return_desc; /* NULL if no return value */ } - else if (previous_walk_state->return_desc) { /* Caller doesn't want it, must delete it */ diff -Nru a/drivers/acpi/processor.c b/drivers/acpi/processor.c --- a/drivers/acpi/processor.c Fri Nov 22 13:41:21 2002 +++ b/drivers/acpi/processor.c Fri Nov 22 13:41:21 2002 @@ -1613,7 +1613,7 @@ cpufreq interface -------------------------------------------------------------------------- */ #ifdef CONFIG_ACPI_PROCESSOR_PERF -static void +static int acpi_cpufreq_setpolicy ( struct cpufreq_policy *policy) { @@ -1626,7 +1626,7 @@ ACPI_FUNCTION_TRACE("acpi_cpufreq_setpolicy"); if (!policy) - return_VOID; + return_VALUE(-EINVAL); /* get a present, initialized CPU */ if (policy->cpu == CPUFREQ_ALL_CPUS) @@ -1644,7 +1644,7 @@ cpu = policy->cpu; pr = processors[cpu]; if (!pr) - return_VOID; + return_VALUE(-EINVAL); } /* select appropriate P-State */ @@ -1686,11 +1686,11 @@ result = acpi_processor_set_performance (pr, next_state); } - return_VOID; + return_VALUE(0); } -static void +static int acpi_cpufreq_verify ( struct cpufreq_policy *policy) { @@ -1703,7 +1703,7 @@ ACPI_FUNCTION_TRACE("acpi_cpufreq_verify"); if (!policy) - return_VOID; + return_VALUE(-EINVAL); /* get a present, initialized CPU */ if (policy->cpu == CPUFREQ_ALL_CPUS) @@ -1721,7 +1721,7 @@ cpu = policy->cpu; pr = processors[cpu]; if (!pr) - return_VOID; + return_VALUE(-EINVAL); } /* first check if min and max are within valid limits */ @@ -1741,13 +1741,12 @@ next_larger_state = i; } - if (number_states) - return_VOID; - - /* round up now */ - policy->max = pr->performance.states[next_larger_state].core_frequency * 1000; + if (!number_states) { + /* round up now */ + policy->max = pr->performance.states[next_larger_state].core_frequency * 1000; + } - return_VOID; + return_VALUE(0); } static int @@ -1807,9 +1806,10 @@ driver->policy = (struct cpufreq_policy *) (driver + 1); #ifdef CONFIG_CPU_FREQ_24_API - driver->cpu_min_freq = pr->performance.states[pr->performance.state_count - 1].core_frequency * 1000; - for (i=0;icpu_cur_freq[0] = pr->performance.states[current_state].core_frequency * 1000; + driver->cpu_min_freq[0] = pr->performance.states[pr->performance.state_count - 1].core_frequency * 1000; + } #endif driver->verify = &acpi_cpufreq_verify; diff -Nru a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c --- a/drivers/acpi/sleep.c Fri Nov 22 13:41:17 2002 +++ b/drivers/acpi/sleep.c Fri Nov 22 13:41:17 2002 @@ -205,8 +205,10 @@ break; case ACPI_STATE_S2: +#ifdef CONFIG_SOFTWARE_SUSPEND case ACPI_STATE_S3: do_suspend_lowlevel(0); +#endif break; } local_irq_restore(flags); diff -Nru a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c --- a/drivers/acpi/utilities/utobject.c Fri Nov 22 13:41:21 2002 +++ b/drivers/acpi/utilities/utobject.c Fri Nov 22 13:41:21 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: utobject - ACPI object create/delete/size/cache routines - * $Revision: 77 $ + * $Revision: 79 $ * *****************************************************************************/ @@ -116,6 +116,59 @@ /******************************************************************************* * + * FUNCTION: Acpi_ut_create_buffer_object + * + * PARAMETERS: Buffer_size - Size of buffer to be created + * + * RETURN: Pointer to a new Buffer object + * + * DESCRIPTION: Create a fully initialized buffer object + * + ******************************************************************************/ + +acpi_operand_object * +acpi_ut_create_buffer_object ( + ACPI_SIZE buffer_size) +{ + acpi_operand_object *buffer_desc; + u8 *buffer; + + + ACPI_FUNCTION_TRACE_U32 ("Ut_create_buffer_object", buffer_size); + + + /* + * Create a new Buffer object + */ + buffer_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); + if (!buffer_desc) { + return_PTR (NULL); + } + + /* Allocate the actual buffer */ + + buffer = ACPI_MEM_CALLOCATE (buffer_size); + if (!buffer) { + ACPI_REPORT_ERROR (("Create_buffer: could not allocate size %X\n", + (u32) buffer_size)); + acpi_ut_remove_reference (buffer_desc); + return_PTR (NULL); + } + + /* Complete buffer object initialization */ + + buffer_desc->buffer.flags |= AOPOBJ_DATA_VALID; + buffer_desc->buffer.pointer = buffer; + buffer_desc->buffer.length = (u32) buffer_size; + + /* Return the new buffer descriptor */ + + return_PTR (buffer_desc); +} + + +/******************************************************************************* + * * FUNCTION: Acpi_ut_valid_internal_object * * PARAMETERS: Object - Object to be validated @@ -135,8 +188,7 @@ /* Check for a null pointer */ if (!object) { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "**** Null Object Ptr\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** Null Object Ptr\n")); return (FALSE); } @@ -161,10 +213,17 @@ "**** Obj %p is a parser obj, not ACPI obj\n", object)); break; + case ACPI_DESC_TYPE_CACHED: + + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "**** Obj %p has already been released to internal cache\n", object)); + break; + default: - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "**** Obj %p is of unknown type\n", object)); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "**** Obj %p has unknown descriptor type %X\n", object, + ACPI_GET_DESCRIPTOR_TYPE (object))); break; } diff -Nru a/drivers/base/base.h b/drivers/base/base.h --- a/drivers/base/base.h Fri Nov 22 13:41:19 2002 +++ b/drivers/base/base.h Fri Nov 22 13:41:19 2002 @@ -19,6 +19,9 @@ extern int devclass_add_device(struct device *); extern void devclass_remove_device(struct device *); +extern int devclass_add_driver(struct device_driver *); +extern void devclass_remove_driver(struct device_driver *); + extern int interface_add(struct device_class *, struct device *); extern void interface_remove(struct device_class *, struct device *); diff -Nru a/drivers/base/bus.c b/drivers/base/bus.c --- a/drivers/base/bus.c Fri Nov 22 13:41:18 2002 +++ b/drivers/base/bus.c Fri Nov 22 13:41:18 2002 @@ -7,7 +7,7 @@ * */ -#define DEBUG 0 +#undef DEBUG #include #include @@ -16,7 +16,7 @@ #include #include "base.h" -static LIST_HEAD(bus_driver_list); +static DECLARE_MUTEX(bus_sem); #define to_dev(node) container_of(node,struct device,bus_list) #define to_drv(node) container_of(node,struct device_driver,bus_list) @@ -64,8 +64,15 @@ }; +static void driver_release(struct kobject * kobj) +{ + struct device_driver * drv = to_driver(kobj); + up(&drv->unload_sem); +} + + /* - * sysfs bindings for drivers + * sysfs bindings for buses */ @@ -124,74 +131,14 @@ .sysfs_ops = &bus_sysfs_ops, }; + /** - * bus_for_each_dev - walk list of devices and do something to each - * @bus: bus in question - * @data: data for the callback - * @callback: caller-defined action to perform on each device - * - * Why do we do this? So we can guarantee proper locking and reference - * counting on devices as we touch each one. - * - * Algorithm: - * Take device_lock and get the first node in the list. - * Try and increment the reference count on it. If we can't, it's in the - * process of being removed, but that process hasn't acquired device_lock. - * It's still in the list, so we grab the next node and try that one. - * We drop the lock to call the callback. - * We can't decrement the reference count yet, because we need the next - * node in the list. So, we set @prev to point to the current device. - * On the next go-round, we decrement the reference count on @prev, so if - * it's being removed, it won't affect us. + * attach - add device to driver. + * @dev: device. + * + * By this point, we know for sure what the driver is, so we + * do the rest (which ain't that much). */ -int bus_for_each_dev(struct bus_type * bus, void * data, - int (*callback)(struct device * dev, void * data)) -{ - struct list_head * node; - int error = 0; - - bus = get_bus(bus); - if (bus) { - down_read(&bus->rwsem); - list_for_each(node,&bus->devices) { - struct device * dev = get_device(to_dev(node)); - if (dev) { - error = callback(dev,data); - put_device(dev); - if (error) - break; - } - } - up_read(&bus->rwsem); - put_bus(bus); - } - return error; -} - -int bus_for_each_drv(struct bus_type * bus, void * data, - int (*callback)(struct device_driver * drv, void * data)) -{ - struct list_head * node; - int error = 0; - - bus = get_bus(bus); - if (bus) { - down_read(&bus->rwsem); - list_for_each(node,&bus->drivers) { - struct device_driver * drv = get_driver(to_drv(node)); - if (drv) { - error = callback(drv,data); - put_driver(drv); - if (error) - break; - } - } - up_read(&bus->rwsem); - put_bus(bus); - } - return error; -} - static void attach(struct device * dev) { pr_debug("bound device '%s' to driver '%s'\n", @@ -200,6 +147,21 @@ sysfs_create_link(&dev->driver->kobj,&dev->kobj,dev->kobj.name); } + +/** + * bus_match - check compatibility between device & driver. + * @dev: device. + * @drv: driver. + * + * First, we call the bus's match function, which should compare + * the device IDs the driver supports with the device IDs of the + * device. Note we don't do this ourselves because we don't know + * the format of the ID structures, nor what is to be considered + * a match and what is not. + * + * If we find a match, we call @drv->probe(@dev) if it exists, and + * call attach() above. + */ static int bus_match(struct device * dev, struct device_driver * drv) { int error = -ENODEV; @@ -208,14 +170,24 @@ if (drv->probe) { if (!(error = drv->probe(dev))) attach(dev); - else + else dev->driver = NULL; - } else + } else { attach(dev); + error = 0; + } } return error; } + +/** + * device_attach - try to attach device to a driver. + * @dev: device. + * + * Walk the list of drivers that the bus has and call bus_match() + * for each pair. If a compatible pair is found, break out and return. + */ static int device_attach(struct device * dev) { struct bus_type * bus = dev->bus; @@ -232,17 +204,24 @@ list_for_each(entry,&bus->drivers) { struct device_driver * drv = - get_driver(container_of(entry,struct device_driver,bus_list)); - if (!drv) - continue; - error = bus_match(dev,drv); - put_driver(drv); - if (!error) + container_of(entry,struct device_driver,bus_list); + if (!(error = bus_match(dev,drv))) break; } return error; } + +/** + * driver_attach - try to bind driver to devices. + * @drv: driver. + * + * Walk the list of devices that the bus has on it and try to match + * the driver with each one. + * If bus_match() returns 0 and the @dev->driver is set, we've found + * a compatible pair, so we call devclass_add_device() to add the + * device to the class. + */ static int driver_attach(struct device_driver * drv) { struct bus_type * bus = drv->bus; @@ -254,17 +233,24 @@ list_for_each(entry,&bus->devices) { struct device * dev = container_of(entry,struct device,bus_list); - if (get_device(dev)) { - if (!dev->driver) { - if (!bus_match(dev,drv) && dev->driver) - devclass_add_device(dev); - } - put_device(dev); + if (!dev->driver) { + if (!bus_match(dev,drv) && dev->driver) + devclass_add_device(dev); } } return error; } + +/** + * detach - do dirty work of detaching device from its driver. + * @dev: device. + * @drv: its driver. + * + * Note that calls to this function are serialized by taking the + * bus's rwsem in both bus_remove_device() and bus_remove_driver(). + */ + static void detach(struct device * dev, struct device_driver * drv) { if (drv) { @@ -277,120 +263,152 @@ } } + +/** + * device_detach - detach device from its driver. + * @dev: device. + */ + static void device_detach(struct device * dev) { detach(dev,dev->driver); } + +/** + * driver_detach - detach driver from all devices it controls. + * @drv: driver. + */ + static void driver_detach(struct device_driver * drv) { struct list_head * entry, * next; list_for_each_safe(entry,next,&drv->devices) { struct device * dev = container_of(entry,struct device,driver_list); - if (get_device(dev)) { - detach(dev,drv); - put_device(dev); - } + detach(dev,drv); } } /** - * bus_add_device - add device to bus - * @dev: device being added + * bus_add_device - add device to bus + * @dev: device being added * - * Add the device to its bus's list of devices. - * Create a symlink in the bus's 'devices' directory to the - * device's physical location. - * Try and bind the device to a driver. + * - Add the device to its bus's list of devices. + * - Try to attach to driver. + * - Create link to device's physical location. */ int bus_add_device(struct device * dev) { struct bus_type * bus = get_bus(dev->bus); if (bus) { - down_write(&dev->bus->rwsem); + down_write(&dev->bus->subsys.rwsem); pr_debug("bus %s: add device %s\n",bus->name,dev->bus_id); list_add_tail(&dev->bus_list,&dev->bus->devices); device_attach(dev); - up_write(&dev->bus->rwsem); + up_write(&dev->bus->subsys.rwsem); sysfs_create_link(&bus->devsubsys.kobj,&dev->kobj,dev->bus_id); } return 0; } /** - * bus_remove_device - remove device from bus - * @dev: device to be removed + * bus_remove_device - remove device from bus + * @dev: device to be removed * - * Remove symlink from bus's directory. - * Delete device from bus's list. + * - Remove symlink from bus's directory. + * - Delete device from bus's list. + * - Detach from its driver. + * - Drop reference taken in bus_add_device(). */ void bus_remove_device(struct device * dev) { if (dev->bus) { sysfs_remove_link(&dev->bus->devsubsys.kobj,dev->bus_id); - down_write(&dev->bus->rwsem); + down_write(&dev->bus->subsys.rwsem); pr_debug("bus %s: remove device %s\n",dev->bus->name,dev->bus_id); device_detach(dev); list_del_init(&dev->bus_list); - up_write(&dev->bus->rwsem); + up_write(&dev->bus->subsys.rwsem); put_bus(dev->bus); } } + +/** + * bus_add_driver - Add a driver to the bus. + * @drv: driver. + * + */ int bus_add_driver(struct device_driver * drv) { struct bus_type * bus = get_bus(drv->bus); if (bus) { - down_write(&bus->rwsem); + down_write(&bus->subsys.rwsem); pr_debug("bus %s: add driver %s\n",bus->name,drv->name); + + strncpy(drv->kobj.name,drv->name,KOBJ_NAME_LEN); + drv->kobj.subsys = &bus->drvsubsys; + kobject_register(&drv->kobj); + + devclass_add_driver(drv); list_add_tail(&drv->bus_list,&bus->drivers); driver_attach(drv); - up_write(&bus->rwsem); + up_write(&bus->subsys.rwsem); } return 0; } + +/** + * bus_remove_driver - delete driver from bus's knowledge. + * @drv: driver. + * + * Detach the driver from the devices it controls, and remove + * it from it's bus's list of drivers. Finally, we drop the reference + * to the bus we took in bus_add_driver(). + */ + void bus_remove_driver(struct device_driver * drv) { if (drv->bus) { - down_write(&drv->bus->rwsem); + down_write(&drv->bus->subsys.rwsem); pr_debug("bus %s: remove driver %s\n",drv->bus->name,drv->name); driver_detach(drv); list_del_init(&drv->bus_list); - up_write(&drv->bus->rwsem); + devclass_remove_driver(drv); + kobject_unregister(&drv->kobj); + up_write(&drv->bus->subsys.rwsem); + put_bus(drv->bus); } } struct bus_type * get_bus(struct bus_type * bus) { - struct bus_type * ret = bus; - spin_lock(&device_lock); - if (bus && bus->present && atomic_read(&bus->refcount)) - atomic_inc(&bus->refcount); - else - ret = NULL; - spin_unlock(&device_lock); - return ret; + return bus ? container_of(subsys_get(&bus->subsys),struct bus_type,subsys) : NULL; } void put_bus(struct bus_type * bus) { - if (!atomic_dec_and_lock(&bus->refcount,&device_lock)) - return; - list_del_init(&bus->node); - spin_unlock(&device_lock); - WARN_ON(bus->present); + subsys_put(&bus->subsys); } +/** + * bus_register - register a bus with the system. + * @bus: bus. + * + * We take bus_sem here to protect against the bus being + * unregistered during the registration process. + * Once we have that, we registered the bus with the kobject + * infrastructure, then register the children subsystems it has: + * the devices and drivers that belong to the bus. + */ int bus_register(struct bus_type * bus) { - init_rwsem(&bus->rwsem); INIT_LIST_HEAD(&bus->devices); INIT_LIST_HEAD(&bus->drivers); - atomic_set(&bus->refcount,2); - bus->present = 1; + down(&bus_sem); strncpy(bus->subsys.kobj.name,bus->name,KOBJ_NAME_LEN); bus->subsys.parent = &bus_subsys; subsystem_register(&bus->subsys); @@ -402,28 +420,32 @@ snprintf(bus->drvsubsys.kobj.name,KOBJ_NAME_LEN,"drivers"); bus->drvsubsys.parent = &bus->subsys; bus->drvsubsys.sysfs_ops = &driver_sysfs_ops; + bus->drvsubsys.release = driver_release; subsystem_register(&bus->drvsubsys); - spin_lock(&device_lock); - list_add_tail(&bus->node,&bus_driver_list); - spin_unlock(&device_lock); - pr_debug("bus type '%s' registered\n",bus->name); - put_bus(bus); + up(&bus_sem); return 0; } + +/** + * bus_unregister - remove a bus from the system + * @bus: bus. + * + * Take bus_sem, in case the bus we're registering hasn't + * finished registering. Once we have it, unregister the child + * subsystems and the bus itself. + * Finally, we call put_bus() to release the refcount + */ void bus_unregister(struct bus_type * bus) { - spin_lock(&device_lock); - bus->present = 0; - spin_unlock(&device_lock); - + down(&bus_sem); pr_debug("bus %s: unregistering\n",bus->name); subsystem_unregister(&bus->drvsubsys); subsystem_unregister(&bus->devsubsys); subsystem_unregister(&bus->subsys); - put_bus(bus); + up(&bus_sem); } static int __init bus_subsys_init(void) @@ -433,8 +455,6 @@ core_initcall(bus_subsys_init); -EXPORT_SYMBOL(bus_for_each_dev); -EXPORT_SYMBOL(bus_for_each_drv); EXPORT_SYMBOL(bus_add_device); EXPORT_SYMBOL(bus_remove_device); EXPORT_SYMBOL(bus_register); diff -Nru a/drivers/base/class.c b/drivers/base/class.c --- a/drivers/base/class.c Fri Nov 22 13:41:23 2002 +++ b/drivers/base/class.c Fri Nov 22 13:41:23 2002 @@ -2,6 +2,8 @@ * class.c - basic device class management */ +#undef DEBUG + #include #include #include @@ -101,12 +103,12 @@ { struct device_class * cls = get_devclass(drv->devclass); if (cls) { - down_write(&cls->rwsem); + down_write(&cls->subsys.rwsem); pr_debug("device class %s: adding driver %s:%s\n", cls->name,drv->bus->name,drv->name); list_add_tail(&drv->class_list,&cls->drivers); devclass_drv_link(drv); - up_write(&cls->rwsem); + up_write(&cls->subsys.rwsem); } return 0; } @@ -115,12 +117,12 @@ { struct device_class * cls = drv->devclass; if (cls) { - down_write(&cls->rwsem); + down_write(&cls->subsys.rwsem); pr_debug("device class %s: removing driver %s:%s\n", cls->name,drv->bus->name,drv->name); list_del_init(&drv->class_list); devclass_drv_unlink(drv); - up_write(&cls->rwsem); + up_write(&cls->subsys.rwsem); put_devclass(cls); } } @@ -163,7 +165,7 @@ if (dev->driver) { cls = get_devclass(dev->driver->devclass); if (cls) { - down_write(&cls->rwsem); + down_write(&cls->subsys.rwsem); pr_debug("device class %s: adding device %s\n", cls->name,dev->name); if (cls->add_device) @@ -176,7 +178,7 @@ /* notify userspace (call /sbin/hotplug) */ class_hotplug (dev, "add"); - up_write(&cls->rwsem); + up_write(&cls->subsys.rwsem); if (error) put_devclass(cls); } @@ -191,7 +193,7 @@ if (dev->driver) { cls = dev->driver->devclass; if (cls) { - down_write(&cls->rwsem); + down_write(&cls->subsys.rwsem); pr_debug("device class %s: removing device %s\n", cls->name,dev->name); interface_remove(cls,dev); @@ -202,7 +204,7 @@ if (cls->remove_device) cls->remove_device(dev); - up_write(&cls->rwsem); + up_write(&cls->subsys.rwsem); put_devclass(cls); } } @@ -210,34 +212,20 @@ struct device_class * get_devclass(struct device_class * cls) { - struct device_class * ret = cls; - spin_lock(&device_lock); - if (cls && cls->present && atomic_read(&cls->refcount) > 0) - atomic_inc(&cls->refcount); - else - ret = NULL; - spin_unlock(&device_lock); - return ret; + return cls ? container_of(subsys_get(&cls->subsys),struct device_class,subsys) : NULL; } void put_devclass(struct device_class * cls) { - if (atomic_dec_and_lock(&cls->refcount,&device_lock)) { - list_del_init(&cls->node); - spin_unlock(&device_lock); - } + subsys_put(&cls->subsys); } int devclass_register(struct device_class * cls) { INIT_LIST_HEAD(&cls->drivers); - INIT_LIST_HEAD(&cls->intf_list); - init_rwsem(&cls->rwsem); - atomic_set(&cls->refcount,2); - cls->present = 1; - pr_debug("device class '%s': registering\n",cls->name); + pr_debug("device class '%s': registering\n",cls->name); strncpy(cls->subsys.kobj.name,cls->name,KOBJ_NAME_LEN); cls->subsys.parent = &class_subsys; subsystem_register(&cls->subsys); @@ -250,23 +238,15 @@ cls->drvsubsys.parent = &cls->subsys; subsystem_register(&cls->drvsubsys); - spin_lock(&device_lock); - list_add_tail(&cls->node,&class_list); - spin_unlock(&device_lock); - put_devclass(cls); return 0; } void devclass_unregister(struct device_class * cls) { - spin_lock(&device_lock); - cls->present = 0; - spin_unlock(&device_lock); pr_debug("device class '%s': unregistering\n",cls->name); subsystem_unregister(&cls->drvsubsys); subsystem_unregister(&cls->devsubsys); subsystem_unregister(&cls->subsys); - put_devclass(cls); } static int __init class_subsys_init(void) @@ -276,6 +256,8 @@ core_initcall(class_subsys_init); +EXPORT_SYMBOL(devclass_create_file); +EXPORT_SYMBOL(devclass_remove_file); EXPORT_SYMBOL(devclass_register); EXPORT_SYMBOL(devclass_unregister); EXPORT_SYMBOL(get_devclass); diff -Nru a/drivers/base/core.c b/drivers/base/core.c --- a/drivers/base/core.c Fri Nov 22 13:41:17 2002 +++ b/drivers/base/core.c Fri Nov 22 13:41:17 2002 @@ -5,7 +5,7 @@ * 2002 Open Source Development Lab */ -#define DEBUG 0 +#undef DEBUG #include #include @@ -69,15 +69,42 @@ .store = dev_attr_store, }; + +/** + * device_release - free device structure. + * @kobj: device's kobject. + * + * This is called once the reference count for the object + * reaches 0. We forward the call to the device's release + * method, which should handle actually freeing the structure. + */ +static void device_release(struct kobject * kobj) +{ + struct device * dev = to_dev(kobj); + if (dev->release) + dev->release(dev); +} + + +/** + * device_subsys - structure to be registered with kobject core. + */ struct subsystem device_subsys = { .kobj = { .name = "devices", }, + .release = device_release, .sysfs_ops = &dev_sysfs_ops, .default_attrs = dev_default_attrs, }; +/** + * device_create_file - create sysfs attribute file for device. + * @dev: device. + * @attr: device attribute descriptor. + */ + int device_create_file(struct device * dev, struct device_attribute * attr) { int error = 0; @@ -88,6 +115,12 @@ return error; } +/** + * device_remove_file - remove sysfs attribute file. + * @dev: device. + * @attr: device attribute descriptor. + */ + void device_remove_file(struct device * dev, struct device_attribute * attr) { if (get_device(dev)) { @@ -96,32 +129,73 @@ } } + +/** + * device_initialize - init device structure. + * @dev: device. + * + * This prepares the device for use by other layers, + * including adding it to the device hierarchy. + * It is the first half of device_register(), if called by + * that, though it can also be called separately, so one + * may use @dev's fields (e.g. the refcount). + */ + +void device_initialize(struct device *dev) +{ + kobject_init(&dev->kobj); + INIT_LIST_HEAD(&dev->node); + INIT_LIST_HEAD(&dev->children); + INIT_LIST_HEAD(&dev->g_list); + INIT_LIST_HEAD(&dev->driver_list); + INIT_LIST_HEAD(&dev->bus_list); + INIT_LIST_HEAD(&dev->intf_list); +// spin_lock_init(&dev->lock); +} + +/** + * device_add - add device to device hierarchy. + * @dev: device. + * + * This is part 2 of device_register(), though may be called + * separately _iff_ device_initialize() has been called separately. + * + * This adds it to the kobject hierarchy via kobject_add(), adds it + * to the global and sibling lists for the device, then + * adds it to the other relevant subsystems of the driver model. + */ int device_add(struct device *dev) { + struct device * parent; int error; + dev = get_device(dev); if (!dev || !strlen(dev->bus_id)) return -EINVAL; - down(&device_sem); - dev->state = DEVICE_REGISTERED; - if (dev->parent) { - list_add_tail(&dev->g_list,&dev->parent->g_list); - list_add_tail(&dev->node,&dev->parent->children); - } else - list_add_tail(&dev->g_list,&global_device_list); - up(&device_sem); + parent = get_device(dev->parent); pr_debug("DEV: registering device: ID = '%s', name = %s\n", dev->bus_id, dev->name); + /* first, register with generic layer. */ strncpy(dev->kobj.name,dev->bus_id,KOBJ_NAME_LEN); - if (dev->parent) - dev->kobj.parent = &dev->parent->kobj; dev->kobj.subsys = &device_subsys; - if ((error = kobject_register(&dev->kobj))) + if (parent) + dev->kobj.parent = &parent->kobj; + + if ((error = kobject_add(&dev->kobj))) goto register_done; + /* now take care of our own registration */ + down(&device_sem); + if (parent) { + list_add_tail(&dev->g_list,&dev->parent->g_list); + list_add_tail(&dev->node,&parent->children); + } else + list_add_tail(&dev->g_list,&global_device_list); + up(&device_sem); + bus_add_device(dev); /* notify platform of device entry */ @@ -133,95 +207,80 @@ devclass_add_device(dev); register_done: - if (error) { - up(&device_sem); - list_del_init(&dev->g_list); - list_del_init(&dev->node); - up(&device_sem); - } + if (error && parent) + put_device(parent); + put_device(dev); return error; } -void device_initialize(struct device *dev) -{ - kobject_init(&dev->kobj); - INIT_LIST_HEAD(&dev->node); - INIT_LIST_HEAD(&dev->children); - INIT_LIST_HEAD(&dev->g_list); - INIT_LIST_HEAD(&dev->driver_list); - INIT_LIST_HEAD(&dev->bus_list); - INIT_LIST_HEAD(&dev->intf_list); - spin_lock_init(&dev->lock); - atomic_set(&dev->refcount,1); - dev->state = DEVICE_INITIALIZED; - if (dev->parent) - get_device(dev->parent); -} /** - * device_register - register a device - * @dev: pointer to the device structure - * - * First, make sure that the device has a parent, create - * a directory for it, then add it to the parent's list of - * children. + * device_register - register a device with the system. + * @dev: pointer to the device structure * - * Maintains a global list of all devices, in depth-first ordering. - * The head for that list is device_root.g_list. + * This happens in two clean steps - initialize the device + * and add it to the system. The two steps can be called + * separately, but this is the easiest and most common. + * I.e. you should only call the two helpers separately if + * have a clearly defined need to use and refcount the device + * before it is added to the hierarchy. */ + int device_register(struct device *dev) { - int error; - - if (!dev || !strlen(dev->bus_id)) - return -EINVAL; - device_initialize(dev); - if (dev->parent) - get_device(dev->parent); - error = device_add(dev); - if (error && dev->parent) - put_device(dev->parent); - return error; + return device_add(dev); } + +/** + * get_device - increment reference count for device. + * @dev: device. + * + * This simply forwards the call to kobject_get(), though + * we do take care to provide for the case that we get a NULL + * pointer passed in. + */ + struct device * get_device(struct device * dev) { - struct device * ret = dev; - down(&device_sem); - if (device_present(dev) && atomic_read(&dev->refcount) > 0) - atomic_inc(&dev->refcount); - else - ret = NULL; - up(&device_sem); - return ret; + return dev ? to_dev(kobject_get(&dev->kobj)) : NULL; } + /** - * put_device - decrement reference count, and clean up when it hits 0 - * @dev: device in question + * put_device - decrement reference count. + * @dev: device in question. */ void put_device(struct device * dev) { - down(&device_sem); - if (!atomic_dec_and_test(&dev->refcount)) { - up(&device_sem); - return; - } - list_del_init(&dev->node); - list_del_init(&dev->g_list); - up(&device_sem); + kobject_put(&dev->kobj); +} - WARN_ON(dev->state == DEVICE_REGISTERED); - if (dev->state == DEVICE_GONE) - device_del(dev); -} +/** + * device_del - delete device from system. + * @dev: device. + * + * This is the first part of the device unregistration + * sequence. This removes the device from the lists we control + * from here, has it removed from the other driver model + * subsystems it was added to in device_add(), and removes it + * from the kobject hierarchy. + * + * NOTE: this should be called manually _iff_ device_add() was + * also called manually. + */ void device_del(struct device * dev) { struct device * parent = dev->parent; + down(&device_sem); + list_del_init(&dev->node); + list_del_init(&dev->g_list); + up(&device_sem); + /* Notify the platform of the removal, in case they * need to do anything... */ @@ -233,31 +292,29 @@ bus_remove_device(dev); - if (dev->release) - dev->release(dev); + kobject_del(&dev->kobj); if (parent) put_device(parent); + } /** - * device_unregister - unlink device - * @dev: device going away + * device_unregister - unregister device from system. + * @dev: device going away. * - * The device has been removed from the system, so we disavow knowledge - * of it. It might not be the final reference to the device, so we mark - * it as !present, so no more references to it can be acquired. - * In the end, we decrement the final reference count for it. + * We do this in two parts, like we do device_register(). First, + * we remove it from all the subsystems with device_del(), then + * we decrement the reference count via put_device(). If that + * is the final reference count, the device will be cleaned up + * via device_release() above. Otherwise, the structure will + * stick around until the final reference to the device is dropped. */ void device_unregister(struct device * dev) { - down(&device_sem); - dev->state = DEVICE_GONE; - up(&device_sem); - pr_debug("DEV: Unregistering device. ID = '%s', name = '%s'\n", dev->bus_id,dev->name); - kobject_unregister(&dev->kobj); + device_del(dev); put_device(dev); } @@ -268,7 +325,11 @@ core_initcall(device_subsys_init); +EXPORT_SYMBOL(device_initialize); +EXPORT_SYMBOL(device_add); EXPORT_SYMBOL(device_register); + +EXPORT_SYMBOL(device_del); EXPORT_SYMBOL(device_unregister); EXPORT_SYMBOL(get_device); EXPORT_SYMBOL(put_device); diff -Nru a/drivers/base/cpu.c b/drivers/base/cpu.c --- a/drivers/base/cpu.c Fri Nov 22 13:41:18 2002 +++ b/drivers/base/cpu.c Fri Nov 22 13:41:18 2002 @@ -48,7 +48,7 @@ static int __init register_cpu_type(void) { - driver_register(&cpu_driver); - return devclass_register(&cpu_devclass); + devclass_register(&cpu_devclass); + return driver_register(&cpu_driver); } postcore_initcall(register_cpu_type); diff -Nru a/drivers/base/driver.c b/drivers/base/driver.c --- a/drivers/base/driver.c Fri Nov 22 13:41:22 2002 +++ b/drivers/base/driver.c Fri Nov 22 13:41:22 2002 @@ -3,7 +3,7 @@ * */ -#define DEBUG 0 +#define DEBUG #include #include @@ -12,9 +12,12 @@ #include "base.h" #define to_dev(node) container_of(node,struct device,driver_list) +#define to_drv(obj) container_of(obj,struct device_driver,kobj) -/* - * helpers for creating driver attributes in sysfs +/** + * driver_create_file - create sysfs file for driver. + * @drv: driver. + * @attr: driver attribute descriptor. */ int driver_create_file(struct device_driver * drv, struct driver_attribute * attr) @@ -28,6 +31,13 @@ return error; } + +/** + * driver_remove_file - remove sysfs file for driver. + * @drv: driver. + * @attr: driver attribute descriptor. + */ + void driver_remove_file(struct device_driver * drv, struct driver_attribute * attr) { if (get_driver(drv)) { @@ -36,102 +46,67 @@ } } -int driver_for_each_dev(struct device_driver * drv, void * data, - int (*callback)(struct device *, void * )) -{ - struct list_head * node; - int error = 0; - - drv = get_driver(drv); - if (drv) { - down_read(&drv->bus->rwsem); - list_for_each(node,&drv->devices) { - struct device * dev = get_device(to_dev(node)); - if (dev) { - error = callback(dev,data); - put_device(dev); - if (error) - break; - } - } - up_read(&drv->bus->rwsem); - put_driver(drv); - } - return error; -} +/** + * get_driver - increment driver reference count. + * @drv: driver. + */ struct device_driver * get_driver(struct device_driver * drv) { - struct device_driver * ret = drv; - spin_lock(&device_lock); - if (drv && drv->present && atomic_read(&drv->refcount) > 0) - atomic_inc(&drv->refcount); - else - ret = NULL; - spin_unlock(&device_lock); - return ret; + return drv ? to_drv(kobject_get(&drv->kobj)) : NULL; } -void remove_driver(struct device_driver * drv) -{ - BUG(); -} - /** - * put_driver - decrement driver's refcount and clean up if necessary - * @drv: driver in question + * put_driver - decrement driver's refcount. + * @drv: driver. */ void put_driver(struct device_driver * drv) { - struct bus_type * bus = drv->bus; - if (!atomic_dec_and_lock(&drv->refcount,&device_lock)) - return; - spin_unlock(&device_lock); - BUG_ON(drv->present); - if (drv->release) - drv->release(drv); - put_bus(bus); + kobject_put(&drv->kobj); } + /** - * driver_register - register driver with bus - * @drv: driver to register - * - * Add to bus's list of devices + * driver_register - register driver with bus + * @drv: driver to register + * + * We pass off most of the work to the bus_add_driver() call, + * since most of the things we have to do deal with the bus + * structures. + * + * The one interesting aspect is that we initialize @drv->unload_sem + * to a locked state here. It will be unlocked when the driver + * reference count reaches 0. */ int driver_register(struct device_driver * drv) { - if (!drv->bus) - return -EINVAL; - - pr_debug("driver %s:%s: registering\n",drv->bus->name,drv->name); - - kobject_init(&drv->kobj); - strncpy(drv->kobj.name,drv->name,KOBJ_NAME_LEN); - drv->kobj.subsys = &drv->bus->drvsubsys; - kobject_register(&drv->kobj); - - get_bus(drv->bus); - atomic_set(&drv->refcount,2); - rwlock_init(&drv->lock); INIT_LIST_HEAD(&drv->devices); - drv->present = 1; - bus_add_driver(drv); - put_driver(drv); - return 0; + init_MUTEX_LOCKED(&drv->unload_sem); + return bus_add_driver(drv); } + +/** + * driver_unregister - remove driver from system. + * @drv: driver. + * + * Again, we pass off most of the work to the bus-level call. + * + * Though, once that is done, we attempt to take @drv->unload_sem. + * This will block until the driver refcount reaches 0, and it is + * released. Only modular drivers will call this function, and we + * have to guarantee that it won't complete, letting the driver + * unload until all references are gone. + */ + void driver_unregister(struct device_driver * drv) { - spin_lock(&device_lock); - drv->present = 0; - spin_unlock(&device_lock); - pr_debug("driver %s:%s: unregistering\n",drv->bus->name,drv->name); - put_driver(drv); + bus_remove_driver(drv); + down(&drv->unload_sem); + up(&drv->unload_sem); } -EXPORT_SYMBOL(driver_for_each_dev); EXPORT_SYMBOL(driver_register); EXPORT_SYMBOL(driver_unregister); EXPORT_SYMBOL(get_driver); diff -Nru a/drivers/base/fs/device.c b/drivers/base/fs/device.c --- a/drivers/base/fs/device.c Fri Nov 22 13:41:20 2002 +++ b/drivers/base/fs/device.c Fri Nov 22 13:41:20 2002 @@ -5,7 +5,7 @@ * 2002 Open Source Development Lab */ -#define DEBUG 0 +#undef DEBUG #include #include diff -Nru a/drivers/base/hotplug.c b/drivers/base/hotplug.c --- a/drivers/base/hotplug.c Fri Nov 22 13:41:17 2002 +++ b/drivers/base/hotplug.c Fri Nov 22 13:41:17 2002 @@ -10,7 +10,7 @@ * */ -#define DEBUG 0 +#undef DEBUG #include #include diff -Nru a/drivers/base/intf.c b/drivers/base/intf.c --- a/drivers/base/intf.c Fri Nov 22 13:41:22 2002 +++ b/drivers/base/intf.c Fri Nov 22 13:41:22 2002 @@ -2,7 +2,7 @@ * intf.c - class-specific interface management */ -#define DEBUG 1 +#undef DEBUG #include #include @@ -10,7 +10,7 @@ #include "base.h" -#define to_intf(node) container_of(node,struct device_interface,node) +#define to_intf(node) container_of(node,struct device_interface,kobj.entry) /** * intf_dev_link - symlink from interface's directory to device's directory @@ -34,22 +34,18 @@ int interface_register(struct device_interface * intf) { - struct device_class * cls = intf->devclass; + struct device_class * cls = get_devclass(intf->devclass); + int error = 0; if (cls) { - pr_debug("register interface '%s' with class '%s\n", + pr_debug("register interface '%s' with class '%s'\n", intf->name,cls->name); - kobject_init(&intf->kobj); strncpy(intf->kobj.name,intf->name,KOBJ_NAME_LEN); intf->kobj.subsys = &cls->subsys; kobject_register(&intf->kobj); - - spin_lock(&device_lock); - list_add_tail(&intf->node,&cls->intf_list); - spin_unlock(&device_lock); - return 0; - } - return -EINVAL; + } else + error = -EINVAL; + return error; } void interface_unregister(struct device_interface * intf) @@ -57,9 +53,6 @@ pr_debug("unregistering interface '%s' from class '%s'\n", intf->name,intf->devclass->name); kobject_unregister(&intf->kobj); - spin_lock(&device_lock); - list_del_init(&intf->node); - spin_unlock(&device_lock); } int interface_add(struct device_class * cls, struct device * dev) @@ -69,7 +62,7 @@ pr_debug("adding '%s' to %s class interfaces\n",dev->name,cls->name); - list_for_each(node,&cls->intf_list) { + list_for_each(node,&cls->subsys.list) { struct device_interface * intf = to_intf(node); if (intf->add_device) { error = intf->add_device(dev); @@ -89,30 +82,25 @@ pr_debug("remove '%s' from %s class interfaces: ",dev->name,cls->name); - spin_lock(&device_lock); list_for_each_safe(node,next,&dev->intf_list) { struct intf_data * intf_data = container_of(node,struct intf_data,node); list_del_init(&intf_data->node); - spin_unlock(&device_lock); intf_dev_unlink(intf_data); pr_debug("%s ",intf_data->intf->name); if (intf_data->intf->remove_device) intf_data->intf->remove_device(intf_data); - - spin_lock(&device_lock); } - spin_unlock(&device_lock); pr_debug("\n"); } int interface_add_data(struct intf_data * data) { - spin_lock(&device_lock); + down_write(&data->intf->devclass->subsys.rwsem); list_add_tail(&data->node,&data->dev->intf_list); - data->intf_num = ++data->intf->devnum; - spin_unlock(&device_lock); + data->intf_num = data->intf->devnum++; intf_dev_link(data); + up_write(&data->intf->devclass->subsys.rwsem); return 0; } diff -Nru a/drivers/base/power.c b/drivers/base/power.c --- a/drivers/base/power.c Fri Nov 22 13:41:21 2002 +++ b/drivers/base/power.c Fri Nov 22 13:41:21 2002 @@ -8,7 +8,7 @@ * */ -#define DEBUG 0 +#undef DEBUG #include #include @@ -38,7 +38,7 @@ down(&device_sem); list_for_each(node,&global_device_list) { struct device * dev = to_dev(node); - if (device_present(dev) && dev->driver && dev->driver->suspend) { + if (dev->driver && dev->driver->suspend) { pr_debug("suspending device %s\n",dev->name); error = dev->driver->suspend(dev,state,level); if (error) @@ -64,7 +64,7 @@ down(&device_sem); list_for_each_prev(node,&global_device_list) { struct device * dev = to_dev(node); - if (device_present(dev) && dev->driver && dev->driver->resume) { + if (dev->driver && dev->driver->resume) { pr_debug("resuming device %s\n",dev->name); dev->driver->resume(dev,level); } @@ -86,7 +86,7 @@ down(&device_sem); list_for_each(entry,&global_device_list) { struct device * dev = to_dev(entry); - if (device_present(dev) && dev->driver && dev->driver->shutdown) { + if (dev->driver && dev->driver->shutdown) { pr_debug("shutting down %s\n",dev->name); dev->driver->shutdown(dev); } diff -Nru a/drivers/base/sys.c b/drivers/base/sys.c --- a/drivers/base/sys.c Fri Nov 22 13:41:17 2002 +++ b/drivers/base/sys.c Fri Nov 22 13:41:17 2002 @@ -10,7 +10,7 @@ * add themselves as children of the system bus. */ -#define DEBUG 1 +#undef DEBUG #include #include diff -Nru a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c --- a/drivers/block/cciss_scsi.c Fri Nov 22 13:41:18 2002 +++ b/drivers/block/cciss_scsi.c Fri Nov 22 13:41:18 2002 @@ -73,14 +73,14 @@ #endif static struct cciss_scsi_hba_t ccissscsi[MAX_CTLR] = { - { name: "cciss0", ndevices: 0 }, - { name: "cciss1", ndevices: 0 }, - { name: "cciss2", ndevices: 0 }, - { name: "cciss3", ndevices: 0 }, - { name: "cciss4", ndevices: 0 }, - { name: "cciss5", ndevices: 0 }, - { name: "cciss6", ndevices: 0 }, - { name: "cciss7", ndevices: 0 }, + { .name = "cciss0", .ndevices = 0 }, + { .name = "cciss1", .ndevices = 0 }, + { .name = "cciss2", .ndevices = 0 }, + { .name = "cciss3", .ndevices = 0 }, + { .name = "cciss4", .ndevices = 0 }, + { .name = "cciss5", .ndevices = 0 }, + { .name = "cciss6", .ndevices = 0 }, + { .name = "cciss7", .ndevices = 0 }, }; /* We need one Scsi_Host_Template *per controller* instead of diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c --- a/drivers/block/ll_rw_blk.c Fri Nov 22 13:41:18 2002 +++ b/drivers/block/ll_rw_blk.c Fri Nov 22 13:41:18 2002 @@ -56,6 +56,7 @@ static struct congestion_state { wait_queue_head_t wqh; atomic_t nr_congested_queues; + atomic_t nr_active_queues; } congestion_states[2]; /* @@ -86,6 +87,11 @@ return ret; } +/* + * A queue has just exitted congestion. Note this in the global counter of + * congested queues, and wake up anyone who was waiting for requests to be + * put back. + */ static void clear_queue_congested(request_queue_t *q, int rw) { enum bdi_state bit; @@ -99,6 +105,10 @@ wake_up(&cs->wqh); } +/* + * A queue has just entered congestion. Flag that in the queue's VM-visible + * state flags and increment the global gounter of congested queues. + */ static void set_queue_congested(request_queue_t *q, int rw) { enum bdi_state bit; @@ -109,6 +119,34 @@ atomic_inc(&congestion_states[rw].nr_congested_queues); } +/* + * A queue has just put back its last read or write request and has fallen + * idle. + */ +static void clear_queue_active(request_queue_t *q, int rw) +{ + enum bdi_state bit; + + bit = (rw == WRITE) ? BDI_write_active : BDI_read_active; + + if (test_and_clear_bit(bit, &q->backing_dev_info.state)) + atomic_dec(&congestion_states[rw].nr_active_queues); +} + +/* + * A queue has just taken its first read or write request and has become + * active. + */ +static void set_queue_active(request_queue_t *q, int rw) +{ + enum bdi_state bit; + + bit = (rw == WRITE) ? BDI_write_active : BDI_read_active; + + if (!test_and_set_bit(bit, &q->backing_dev_info.state)) + atomic_inc(&congestion_states[rw].nr_active_queues); +} + /** * blk_get_backing_dev_info - get the address of a queue's backing_dev_info * @dev: device @@ -1038,6 +1076,16 @@ } /** + * blk_run_queue - run a single device queue + * @q The queue to run + */ +void __blk_run_queue(request_queue_t *q) +{ + blk_remove_plug(q); + q->request_fn(q); +} + +/** * blk_run_queues - fire all plugged queues * * Description: @@ -1242,6 +1290,8 @@ rq = blkdev_free_rq(&rl->free); list_del_init(&rq->queuelist); rq->ref_count = 1; + if (rl->count == queue_nr_requests) + set_queue_active(q, rw); rl->count--; if (rl->count < queue_congestion_on_threshold()) set_queue_congested(q, rw); @@ -1474,6 +1524,8 @@ rl->count++; if (rl->count >= queue_congestion_off_threshold()) clear_queue_congested(q, rw); + if (rl->count == queue_nr_requests) + clear_queue_active(q, rw); if (rl->count >= batch_requests && waitqueue_active(&rl->wait)) wake_up(&rl->wait); } @@ -1502,19 +1554,20 @@ * @timeout: timeout in jiffies * * Waits for up to @timeout jiffies for a queue (any queue) to exit congestion. - * If no queues are congested then just return, in the hope that the caller - * will submit some more IO. + * If no queues are congested then just wait for the next request to be + * returned. */ void blk_congestion_wait(int rw, long timeout) { DEFINE_WAIT(wait); struct congestion_state *cs = &congestion_states[rw]; - if (atomic_read(&cs->nr_congested_queues) == 0) + if (!atomic_read(&cs->nr_active_queues)) return; + blk_run_queues(); prepare_to_wait(&cs->wqh, &wait, TASK_UNINTERRUPTIBLE); - if (atomic_read(&cs->nr_congested_queues) != 0) + if (atomic_read(&cs->nr_active_queues)) io_schedule_timeout(timeout); finish_wait(&cs->wqh, &wait); } @@ -2147,6 +2200,7 @@ for (i = 0; i < ARRAY_SIZE(congestion_states); i++) { init_waitqueue_head(&congestion_states[i].wqh); atomic_set(&congestion_states[i].nr_congested_queues, 0); + atomic_set(&congestion_states[i].nr_active_queues, 0); } return 0; }; @@ -2198,4 +2252,5 @@ EXPORT_SYMBOL(blk_start_queue); EXPORT_SYMBOL(blk_stop_queue); EXPORT_SYMBOL(__blk_stop_queue); +EXPORT_SYMBOL(__blk_run_queue); EXPORT_SYMBOL(blk_run_queues); diff -Nru a/drivers/block/loop.c b/drivers/block/loop.c --- a/drivers/block/loop.c Fri Nov 22 13:41:21 2002 +++ b/drivers/block/loop.c Fri Nov 22 13:41:21 2002 @@ -238,7 +238,7 @@ up(&mapping->host->i_sem); out: kunmap(bvec->bv_page); - balance_dirty_pages(mapping); + balance_dirty_pages_ratelimited(mapping); return ret; unlock: diff -Nru a/drivers/block/umem.c b/drivers/block/umem.c --- a/drivers/block/umem.c Fri Nov 22 13:41:23 2002 +++ b/drivers/block/umem.c Fri Nov 22 13:41:23 2002 @@ -544,7 +544,6 @@ while(return_bio) { struct bio *bio = return_bio; - int bytes = bio->bi_size; return_bio = bio->bi_next; bio->bi_next = NULL; diff -Nru a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c --- a/drivers/cdrom/mcdx.c Fri Nov 22 13:41:19 2002 +++ b/drivers/cdrom/mcdx.c Fri Nov 22 13:41:19 2002 @@ -322,14 +322,14 @@ MODULE_PARM(mcdx, "1-4i"); static struct cdrom_device_ops mcdx_dops = { - open:mcdx_open, - release:mcdx_close, - media_changed:mcdx_media_changed, - tray_move:mcdx_tray_move, - lock_door:mcdx_lockdoor, - audio_ioctl:mcdx_audio_ioctl, - capability:CDC_OPEN_TRAY | CDC_LOCK | CDC_MEDIA_CHANGED | - CDC_PLAY_AUDIO | CDC_DRIVE_STATUS, + .open = mcdx_open, + .release = mcdx_close, + .media_changed = mcdx_media_changed, + .tray_move = mcdx_tray_move, + .lock_door = mcdx_lockdoor, + .audio_ioctl = mcdx_audio_ioctl, + .capability = CDC_OPEN_TRAY | CDC_LOCK | CDC_MEDIA_CHANGED | + CDC_PLAY_AUDIO | CDC_DRIVE_STATUS, }; /* KERNEL INTERFACE FUNCTIONS **************************************/ diff -Nru a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c --- a/drivers/cdrom/optcd.c Fri Nov 22 13:41:18 2002 +++ b/drivers/cdrom/optcd.c Fri Nov 22 13:41:18 2002 @@ -1076,7 +1076,7 @@ static int timeout = 0; static void poll(unsigned long data); -static struct timer_list req_timer = {function: poll}; +static struct timer_list req_timer = {.function = poll}; static void poll(unsigned long data) diff -Nru a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c --- a/drivers/cdrom/sbpcd.c Fri Nov 22 13:41:18 2002 +++ b/drivers/cdrom/sbpcd.c Fri Nov 22 13:41:18 2002 @@ -5469,22 +5469,22 @@ */ static int sbpcd_media_changed( struct cdrom_device_info *cdi, int disc_nr); static struct cdrom_device_ops sbpcd_dops = { - open: sbpcd_open, - release: sbpcd_release, - drive_status: sbpcd_drive_status, - media_changed: sbpcd_media_changed, - tray_move: sbpcd_tray_move, - lock_door: sbpcd_lock_door, - select_speed: sbpcd_select_speed, - get_last_session: sbpcd_get_last_session, - get_mcn: sbpcd_get_mcn, - reset: sbpcd_reset, - audio_ioctl: sbpcd_audio_ioctl, - dev_ioctl: sbpcd_dev_ioctl, - capability: CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | + .open = sbpcd_open, + .release = sbpcd_release, + .drive_status = sbpcd_drive_status, + .media_changed = sbpcd_media_changed, + .tray_move = sbpcd_tray_move, + .lock_door = sbpcd_lock_door, + .select_speed = sbpcd_select_speed, + .get_last_session = sbpcd_get_last_session, + .get_mcn = sbpcd_get_mcn, + .reset = sbpcd_reset, + .audio_ioctl = sbpcd_audio_ioctl, + .dev_ioctl = sbpcd_dev_ioctl, + .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_MULTI_SESSION | CDC_MEDIA_CHANGED | CDC_MCN | CDC_PLAY_AUDIO | CDC_IOCTLS, - n_minors: 1, + .n_minors = 1, }; /*==========================================================================*/ diff -Nru a/drivers/char/Kconfig b/drivers/char/Kconfig --- a/drivers/char/Kconfig Fri Nov 22 13:41:17 2002 +++ b/drivers/char/Kconfig Fri Nov 22 13:41:17 2002 @@ -636,289 +636,7 @@ comment "metalab.unc.edu or ftp://titus.cfw.com/pub/Linux/util/" depends on QIC02_TAPE && QIC02_DYNCONF - -menu "Watchdog Cards" - -config WATCHDOG - bool "Watchdog Timer Support" - ---help--- - If you say Y here (and to one of the following options) and create a - character special file /dev/watchdog with major number 10 and minor - number 130 using mknod ("man mknod"), you will get a watchdog, i.e.: - subsequently opening the file and then failing to write to it for - longer than 1 minute will result in rebooting the machine. This - could be useful for a networked machine that needs to come back - online as fast as possible after a lock-up. There's both a watchdog - implementation entirely in software (which can sometimes fail to - reboot the machine) and a driver for hardware watchdog boards, which - are more robust and can also keep track of the temperature inside - your computer. For details, read - in the kernel source. - - The watchdog is usually used together with the watchdog daemon - which is available from - . This daemon can - also monitor NFS connections and can reboot the machine when the process - table is full. - - If unsure, say N. - -config WATCHDOG_NOWAYOUT - bool "Disable watchdog shutdown on close" - depends on WATCHDOG - help - The default watchdog behaviour (which you get if you say N here) is - to stop the timer if the process managing it closes the file - /dev/watchdog. It's always remotely possible that this process might - get killed. If you say Y here, the watchdog cannot be stopped once - it has been started. - -config SOFT_WATCHDOG - tristate "Software watchdog" - depends on WATCHDOG - help - A software monitoring watchdog. This will fail to reboot your system - from some situations that the hardware watchdog will recover - from. Equally it's a lot cheaper to install. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to compile it as a module, say M here and read - . The module will be called - softdog.o. - -config WDT - tristate "WDT Watchdog timer" - depends on WATCHDOG - ---help--- - If you have a WDT500P or WDT501P watchdog board, say Y here, - otherwise N. It is not possible to probe for this board, which means - that you have to inform the kernel about the IO port and IRQ using - the "wdt=" kernel option (try "man bootparam" or see the - documentation of your boot loader (lilo or loadlin) about how to - pass options to the kernel at boot time). - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called wdt.o. - -config WDTPCI - tristate "WDT PCI Watchdog timer" - depends on WATCHDOG - ---help--- - If you have a PCI WDT500/501 watchdog board, say Y here, otherwise - N. It is not possible to probe for this board, which means that you - have to inform the kernel about the IO port and IRQ using the "wdt=" - kernel option (try "man bootparam" or see the documentation of your - boot loader (lilo or loadlin) about how to pass options to the - kernel at boot time). - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called wdt_pci.o. - -config WDT_501 - bool "WDT501 features" - depends on WDT - help - Saying Y here and creating a character special file /dev/temperature - with major number 10 and minor number 131 ("man mknod") will give - you a thermometer inside your computer: reading from - /dev/temperature yields one byte, the temperature in degrees - Fahrenheit. This works only if you have a WDT501P watchdog board - installed. - -config WDT_501_FAN - bool "Fan Tachometer" - depends on WDT_501 - help - Enable the Fan Tachometer on the WDT501. Only do this if you have a - fan tachometer actually set up. - -config PCWATCHDOG - tristate "Berkshire Products PC Watchdog" - depends on WATCHDOG - ---help--- - This is the driver for the Berkshire Products PC Watchdog card. - This card simply watches your kernel to make sure it doesn't freeze, - and if it does, it reboots your computer after a certain amount of - time. This driver is like the WDT501 driver but for different - hardware. Please read . The PC - watchdog cards can be ordered from . - - 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 is called pcwd.o. If you want to compile it as a module, - say M here and read . - - Most people will say N. - -config ACQUIRE_WDT - tristate "Acquire SBC Watchdog Timer" - depends on WATCHDOG - ---help--- - This is the driver for the hardware watchdog on the PSC-6x86 Single - Board Computer produced by Acquire Inc (and others). This watchdog - simply watches your kernel to make sure it doesn't freeze, and if - it does, it reboots your computer after a certain amount of time. - - This driver is like the WDT501 driver but for different hardware. - 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 is called pscwdt.o. If you want to compile it as a - module, say M here and read . Most - people will say N. - -config ADVANTECH_WDT - tristate "Advantech SBC Watchdog Timer" - depends on WATCHDOG - help - If you are configuring a Linux kernel for the Advantech single-board - computer, say `Y' here to support its built-in watchdog timer - feature. See the help for CONFIG_WATCHDOG for discussion. - -config 21285_WATCHDOG - tristate "DC21285 watchdog" - depends on WATCHDOG && FOOTBRIDGE - help - The Intel Footbridge chip contains a builtin watchdog circuit. Say Y - here if you wish to use this. Alternatively say M to compile the - driver as a module, which will be called wdt285.o. - - This driver does not work on all machines. In particular, early CATS - boards have hardware problems that will cause the machine to simply - lock up if the watchdog fires. - - "If in doubt, leave it out" - say N. - -config 977_WATCHDOG - tristate "NetWinder WB83C977 watchdog" - depends on WATCHDOG && FOOTBRIDGE && ARCH_NETWINDER - help - Say Y here to include support for the WB977 watchdog included in - NetWinder machines. Alternatively say M to compile the driver as - a module, which will be called wdt977.o. - - Not sure? It's safe to say N. - -config EUROTECH_WDT - tristate "Eurotech CPU-1220/1410 Watchdog Timer" - depends on WATCHDOG - help - Enable support for the watchdog timer on the Eurotech CPU-1220 and - CPU-1410 cards. These are PC/104 SBCs. Spec sheets and product - information are at . - -config IB700_WDT - tristate "IB700 SBC Watchdog Timer" - depends on WATCHDOG - ---help--- - This is the driver for the hardware watchdog on the IB700 Single - Board Computer produced by TMC Technology (www.tmc-uk.com). This watchdog - simply watches your kernel to make sure it doesn't freeze, and if - it does, it reboots your computer after a certain amount of time. - - This driver is like the WDT501 driver but for slightly different hardware. - - 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 is called ib700wdt.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. Most people - will say N. - -config I810_TCO - tristate "Intel i810 TCO timer / Watchdog" - depends on WATCHDOG - ---help--- - Hardware driver for the TCO timer built into the Intel i810 and i815 - chipset family. The TCO (Total Cost of Ownership) timer is a - watchdog timer that will reboot the machine after its second - expiration. The expiration time can be configured by commandline - argument "i810_margin=" where is the counter initial value. - It is decremented every 0.6 secs, the default is 50 which gives a - timeout of 30 seconds and one minute until reset. - - On some motherboards the driver may fail to reset the chipset's - NO_REBOOT flag which prevents the watchdog from rebooting the - machine. If this is the case you will get a kernel message like - "i810tco init: failed to reset NO_REBOOT flag". - - If you want to compile this as a module, say M and read - . The module will be called - i810-tco.o. - -config MIXCOMWD - tristate "Mixcom Watchdog" - depends on WATCHDOG - ---help--- - This is a driver for the Mixcom hardware watchdog cards. This - watchdog simply watches your kernel to make sure it doesn't freeze, - and if it does, it reboots your computer after a certain amount of - time. - - 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 is called mixcomwd.o. If you want to compile it as a - module, say M here and read . Most - people will say N. - -config SCx200_WDT - tristate "NatSemi SCx200 Watchdog" - depends on WATCHDOG - help - Enable the built-in watchdog timer support on the National - Semiconductor SCx200 processors. - - If compiled as a module, it will be called scx200_watchdog.o. - -config 60XX_WDT - tristate "SBC-60XX Watchdog Timer" - depends on WATCHDOG - help - This driver can be used with the watchdog timer found on some - single board computers, namely the 6010 PII based computer. - It may well work with other cards. It reads port 0x443 to enable - and re-set the watchdog timer, and reads port 0x45 to disable - the watchdog. If you have a card that behave in similar ways, - you can probably make this driver work with your card as well. - - You can compile this driver directly into the kernel, or use - it as a module. The module will be called sbc60xxwdt.o. - -config W83877F_WDT - tristate "W83877F (EMACS) Watchdog Timer" - depends on WATCHDOG - ---help--- - This is the driver for the hardware watchdog on the W83877F chipset - as used in EMACS PC-104 motherboards (and likely others). This - watchdog simply watches your kernel to make sure it doesn't freeze, - and if it does, it reboots your computer after a certain amount of - time. - - 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 is called mixcomwd.o. If you want to compile it as a - module, say M here and read . Most - people will say N. - -config MACHZ_WDT - tristate "ZF MachZ Watchdog" - depends on WATCHDOG - ---help--- - If you are using a ZF Micro MachZ processor, say Y here, otherwise - N. This is the driver for the watchdog timer builtin on that - processor using ZF-Logic interface. This watchdog simply watches - your kernel to make sure it doesn't freeze, and if it does, it - reboots your computer after a certain amount of time. - - 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 is called machzwd.o. If you want to compile it as a - module, say M here and read . - -endmenu +source "drivers/char/watchdog/Kconfig" config DS1620 tristate "NetWinder thermometer support" diff -Nru a/drivers/char/Makefile b/drivers/char/Makefile --- a/drivers/char/Makefile Fri Nov 22 13:41:23 2002 +++ b/drivers/char/Makefile Fri Nov 22 13:41:23 2002 @@ -77,31 +77,12 @@ obj-$(CONFIG_NWFLASH) += nwflash.o obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o -# Only one watchdog can succeed. We probe the hardware watchdog -# drivers first, then the softdog driver. This means if your hardware -# watchdog dies or is 'borrowed' for some reason the software watchdog -# still gives you some cover. - -obj-$(CONFIG_PCWATCHDOG) += pcwd.o -obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o -obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o -obj-$(CONFIG_IB700_WDT) += ib700wdt.o -obj-$(CONFIG_MIXCOMWD) += mixcomwd.o -obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o -obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o -obj-$(CONFIG_WDT) += wdt.o -obj-$(CONFIG_WDTPCI) += wdt_pci.o -obj-$(CONFIG_21285_WATCHDOG) += wdt285.o -obj-$(CONFIG_977_WATCHDOG) += wdt977.o -obj-$(CONFIG_I810_TCO) += i810-tco.o -obj-$(CONFIG_MACHZ_WDT) += machzwd.o -obj-$(CONFIG_SH_WDT) += shwdt.o -obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o -obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o +obj-$(CONFIG_WATCHDOGS) += watchdog/ obj-$(CONFIG_MWAVE) += mwave/ obj-$(CONFIG_AGP) += agp/ obj-$(CONFIG_DRM) += drm/ obj-$(CONFIG_PCMCIA) += pcmcia/ + # Files generated that shall be removed upon make clean clean-files := consolemap_deftbl.c defkeymap.c qtronixmap.c diff -Nru a/drivers/char/acquirewdt.c b/drivers/char/acquirewdt.c --- a/drivers/char/acquirewdt.c Fri Nov 22 13:41:21 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,251 +0,0 @@ -/* - * Acquire Single Board Computer Watchdog Timer driver for Linux 2.1.x - * - * Based on wdt.c. Original copyright messages: - * - * (c) Copyright 1996 Alan Cox , All Rights Reserved. - * http://www.redhat.com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide - * warranty for any of this software. This material is provided - * "AS-IS" and at no charge. - * - * (c) Copyright 1995 Alan Cox - * - * 14-Dec-2001 Matt Domsch - * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT - * Can't add timeout - driver doesn't allow changing value - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int acq_is_open; -static spinlock_t acq_lock; - -/* - * You must set these - there is no sane way to probe for this board. - */ - -#define WDT_STOP 0x43 -#define WDT_START 0x443 - -#ifdef CONFIG_WATCHDOG_NOWAYOUT -static int nowayout = 1; -#else -static int nowayout = 0; -#endif - -MODULE_PARM(nowayout,"i"); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); - -/* - * Kernel methods. - */ - - -static void acq_ping(void) -{ - /* Write a watchdog value */ - inb_p(WDT_START); -} - -static ssize_t acq_write(struct file *file, const char *buf, size_t count, loff_t *ppos) -{ - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - - if(count) - { - acq_ping(); - return 1; - } - return 0; -} - -static ssize_t acq_read(struct file *file, char *buf, size_t count, loff_t *ppos) -{ - return -EINVAL; -} - - - -static int acq_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) -{ - static struct watchdog_info ident= - { - WDIOF_KEEPALIVEPING, 1, "Acquire WDT" - }; - - switch(cmd) - { - case WDIOC_GETSUPPORT: - if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))) - return -EFAULT; - break; - - case WDIOC_GETSTATUS: - if (copy_to_user((int *)arg, &acq_is_open, sizeof(int))) - return -EFAULT; - break; - - case WDIOC_KEEPALIVE: - acq_ping(); - break; - - default: - return -ENOTTY; - } - return 0; -} - -static int acq_open(struct inode *inode, struct file *file) -{ - switch(minor(inode->i_rdev)) - { - case WATCHDOG_MINOR: - spin_lock(&acq_lock); - if(acq_is_open) - { - spin_unlock(&acq_lock); - return -EBUSY; - } - if (nowayout) { - MOD_INC_USE_COUNT; - } - /* - * Activate - */ - - acq_is_open=1; - inb_p(WDT_START); - spin_unlock(&acq_lock); - return 0; - default: - return -ENODEV; - } -} - -static int acq_close(struct inode *inode, struct file *file) -{ - if(minor(inode->i_rdev)==WATCHDOG_MINOR) - { - spin_lock(&acq_lock); - if (!nowayout) { - inb_p(WDT_STOP); - } - acq_is_open=0; - spin_unlock(&acq_lock); - } - return 0; -} - -/* - * Notifier for system down - */ - -static int acq_notify_sys(struct notifier_block *this, unsigned long code, - void *unused) -{ - if(code==SYS_DOWN || code==SYS_HALT) - { - /* Turn the card off */ - inb_p(WDT_STOP); - } - return NOTIFY_DONE; -} - -/* - * Kernel Interfaces - */ - - -static struct file_operations acq_fops = { - .owner = THIS_MODULE, - .read = acq_read, - .write = acq_write, - .ioctl = acq_ioctl, - .open = acq_open, - .release = acq_close, -}; - -static struct miscdevice acq_miscdev= -{ - WATCHDOG_MINOR, - "watchdog", - &acq_fops -}; - - -/* - * The WDT card needs to learn about soft shutdowns in order to - * turn the timebomb registers off. - */ - -static struct notifier_block acq_notifier= -{ - acq_notify_sys, - NULL, - 0 -}; - -static int __init acq_init(void) -{ - printk("WDT driver for Acquire single board computer initialising.\n"); - - spin_lock_init(&acq_lock); - if (misc_register(&acq_miscdev)) - return -ENODEV; - if (!request_region(WDT_STOP, 1, "Acquire WDT")) - { - misc_deregister(&acq_miscdev); - return -EIO; - } - if (!request_region(WDT_START, 1, "Acquire WDT")) - { - release_region(WDT_STOP, 1); - misc_deregister(&acq_miscdev); - return -EIO; - } - - register_reboot_notifier(&acq_notifier); - return 0; -} - -static void __exit acq_exit(void) -{ - misc_deregister(&acq_miscdev); - unregister_reboot_notifier(&acq_notifier); - release_region(WDT_STOP,1); - release_region(WDT_START,1); -} - -module_init(acq_init); -module_exit(acq_exit); - -MODULE_LICENSE("GPL"); diff -Nru a/drivers/char/advantechwdt.c b/drivers/char/advantechwdt.c --- a/drivers/char/advantechwdt.c Fri Nov 22 13:41:19 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,280 +0,0 @@ -/* - * Advantech Single Board Computer WDT driver for Linux 2.4.x - * - * (c) Copyright 2000-2001 Marek Michalkiewicz - * - * Based on acquirewdt.c which is based on wdt.c. - * Original copyright messages: - * - * (c) Copyright 1996 Alan Cox , All Rights Reserved. - * http://www.redhat.com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide - * warranty for any of this software. This material is provided - * "AS-IS" and at no charge. - * - * (c) Copyright 1995 Alan Cox - * - * 14-Dec-2001 Matt Domsch - * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT - * Added timeout module option to override default - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int advwdt_is_open; -static spinlock_t advwdt_lock; - -/* - * You must set these - there is no sane way to probe for this board. - * - * To enable or restart, write the timeout value in seconds (1 to 63) - * to I/O port WDT_START. To disable, read I/O port WDT_STOP. - * Both are 0x443 for most boards (tested on a PCA-6276VE-00B1), but - * check your manual (at least the PCA-6159 seems to be different - - * the manual says WDT_STOP is 0x43, not 0x443). - * (0x43 is also a write-only control register for the 8254 timer!) - * - * TODO: module parameters to set the I/O port addresses - */ - -#define WDT_STOP 0x443 -#define WDT_START 0x443 - -#define WD_TIMO 60 /* 1 minute */ - -static int timeout = WD_TIMO; /* in seconds */ -MODULE_PARM(timeout,"i"); -MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=60)"); - -#ifdef CONFIG_WATCHDOG_NOWAYOUT -static int nowayout = 1; -#else -static int nowayout = 0; -#endif - -MODULE_PARM(nowayout,"i"); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); - -/* - * Kernel methods. - */ - -static void -advwdt_ping(void) -{ - /* Write a watchdog value */ - outb_p(timeout, WDT_START); -} - -static ssize_t -advwdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) -{ - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - - if (count) { - advwdt_ping(); - return 1; - } - return 0; -} - -static ssize_t -advwdt_read(struct file *file, char *buf, size_t count, loff_t *ppos) -{ - return -EINVAL; -} - -static int -advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) -{ - static struct watchdog_info ident = { - WDIOF_KEEPALIVEPING, 1, "Advantech WDT" - }; - - switch (cmd) { - case WDIOC_GETSUPPORT: - if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))) - return -EFAULT; - break; - - case WDIOC_GETSTATUS: - if (copy_to_user((int *)arg, &advwdt_is_open, sizeof(int))) - return -EFAULT; - break; - - case WDIOC_KEEPALIVE: - advwdt_ping(); - break; - - default: - return -ENOTTY; - } - return 0; -} - -static int -advwdt_open(struct inode *inode, struct file *file) -{ - switch (minor(inode->i_rdev)) { - case WATCHDOG_MINOR: - spin_lock(&advwdt_lock); - if (advwdt_is_open) { - spin_unlock(&advwdt_lock); - return -EBUSY; - } - if (nowayout) { - MOD_INC_USE_COUNT; - } - /* - * Activate - */ - - advwdt_is_open = 1; - advwdt_ping(); - spin_unlock(&advwdt_lock); - return 0; - default: - return -ENODEV; - } -} - -static int -advwdt_close(struct inode *inode, struct file *file) -{ - if (minor(inode->i_rdev) == WATCHDOG_MINOR) { - spin_lock(&advwdt_lock); - if (!nowayout) { - inb_p(WDT_STOP); - } - advwdt_is_open = 0; - spin_unlock(&advwdt_lock); - } - return 0; -} - -/* - * Notifier for system down - */ - -static int -advwdt_notify_sys(struct notifier_block *this, unsigned long code, - void *unused) -{ - if (code == SYS_DOWN || code == SYS_HALT) { - /* Turn the WDT off */ - inb_p(WDT_STOP); - } - return NOTIFY_DONE; -} - -/* - * Kernel Interfaces - */ - -static struct file_operations advwdt_fops = { - .owner = THIS_MODULE, - .read = advwdt_read, - .write = advwdt_write, - .ioctl = advwdt_ioctl, - .open = advwdt_open, - .release = advwdt_close, -}; - -static struct miscdevice advwdt_miscdev = { - WATCHDOG_MINOR, - "watchdog", - &advwdt_fops -}; - -/* - * The WDT needs to learn about soft shutdowns in order to - * turn the timebomb registers off. - */ - -static struct notifier_block advwdt_notifier = { - advwdt_notify_sys, - NULL, - 0 -}; - -static void __init -advwdt_validate_timeout(void) -{ - if (timeout < 1 || timeout > 63) { - timeout = WD_TIMO; - printk(KERN_INFO "advantechwdt: timeout value must be 1 <= x <= 63, using %d\n", timeout); - } -} - -static int __init -advwdt_init(void) -{ - printk("WDT driver for Advantech single board computer initialising.\n"); - - advwdt_validate_timeout(); - spin_lock_init(&advwdt_lock); - if (misc_register(&advwdt_miscdev)) - return -ENODEV; -#if WDT_START != WDT_STOP - if (!request_region(WDT_STOP, 1, "Advantech WDT")) { - misc_deregister(&advwdt_miscdev); - return -EIO; - } -#endif - if (!request_region(WDT_START, 1, "Advantech WDT")) { - misc_deregister(&advwdt_miscdev); -#if WDT_START != WDT_STOP - release_region(WDT_STOP, 1); -#endif - return -EIO; - } - register_reboot_notifier(&advwdt_notifier); - return 0; -} - -static void __exit -advwdt_exit(void) -{ - misc_deregister(&advwdt_miscdev); - unregister_reboot_notifier(&advwdt_notifier); -#if WDT_START != WDT_STOP - release_region(WDT_STOP,1); -#endif - release_region(WDT_START,1); -} - -module_init(advwdt_init); -module_exit(advwdt_exit); - -MODULE_LICENSE("GPL"); - -/* end of advantechwdt.c */ - diff -Nru a/drivers/char/agp/agp.c b/drivers/char/agp/agp.c --- a/drivers/char/agp/agp.c Fri Nov 22 13:41:22 2002 +++ b/drivers/char/agp/agp.c Fri Nov 22 13:41:22 2002 @@ -1150,6 +1150,14 @@ .chipset_setup = via_generic_setup }, { + .device_id = PCI_DEVICE_ID_VIA_8377_0, + .vendor_id = PCI_VENDOR_ID_VIA, + .chipset = VIA_APOLLO_KT400, + .vendor_name = "Via", + .chipset_name = "Apollo Pro KT400", + .chipset_setup = via_generic_setup + }, + { .device_id = PCI_DEVICE_ID_VIA_8653_0, .vendor_id = PCI_VENDOR_ID_VIA, .chipset = VIA_APOLLO_PRO, diff -Nru a/drivers/char/eurotechwdt.c b/drivers/char/eurotechwdt.c --- a/drivers/char/eurotechwdt.c Fri Nov 22 13:41:18 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,505 +0,0 @@ -/* - * Eurotech CPU-1220/1410 on board WDT driver for Linux 2.4.x - * - * (c) Copyright 2001 Ascensit - * (c) Copyright 2001 Rodolfo Giometti - * - * Based on wdt.c. - * Original copyright messages: - * - * (c) Copyright 1996-1997 Alan Cox , All Rights Reserved. - * http://www.redhat.com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide - * warranty for any of this software. This material is provided - * "AS-IS" and at no charge. - * - * (c) Copyright 1995 Alan Cox * - * - * 14-Dec-2001 Matt Domsch - * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT - * Added timeout module option to override default - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int eurwdt_is_open; -static spinlock_t eurwdt_lock; - -/* - * You must set these - there is no sane way to probe for this board. - * You can use wdt=x,y to set these now. - */ - -static int io = 0x3f0; -static int irq = 10; -static char *ev = "int"; - -#define WDT_TIMEOUT 60 /* 1 minute */ -static int timeout = WDT_TIMEOUT; - -MODULE_PARM(timeout,"i"); -MODULE_PARM_DESC(timeout, "Eurotech WDT timeout in seconds (default=60)"); - -#ifdef CONFIG_WATCHDOG_NOWAYOUT -static int nowayout = 1; -#else -static int nowayout = 0; -#endif -MODULE_PARM(nowayout,"i"); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); - - -/* - * Some symbolic names - */ - -#define WDT_CTRL_REG 0x30 -#define WDT_OUTPIN_CFG 0xe2 - #define WDT_EVENT_INT 0x00 - #define WDT_EVENT_REBOOT 0x08 -#define WDT_UNIT_SEL 0xf1 - #define WDT_UNIT_SECS 0x80 -#define WDT_TIMEOUT_VAL 0xf2 -#define WDT_TIMER_CFG 0xf3 - - -#ifndef MODULE - -/** - * eurwdt_setup: - * @str: command line string - * - * Setup options. The board isn't really probe-able so we have to - * get the user to tell us the configuration. Sane people build it - * modular but the others come here. - */ - -static int __init eurwdt_setup(char *str) -{ - int ints[4]; - - str = get_options (str, ARRAY_SIZE(ints), ints); - - if (ints[0] > 0) { - io = ints[1]; - if (ints[0] > 1) - irq = ints[2]; - } - - return 1; -} - -__setup("wdt=", eurwdt_setup); - -#endif /* !MODULE */ - -MODULE_PARM(io, "i"); -MODULE_PARM_DESC(io, "Eurotech WDT io port (default=0x3f0)"); -MODULE_PARM(irq, "i"); -MODULE_PARM_DESC(irq, "Eurotech WDT irq (default=10)"); -MODULE_PARM(ev, "s"); -MODULE_PARM_DESC(ev, "Eurotech WDT event type (default is `reboot')"); - - -/* - * Programming support - */ - -static void __init eurwdt_validate_timeout(void) -{ - if (timeout < 0 || timeout > 255) { - timeout = WDT_TIMEOUT; - printk(KERN_INFO "eurwdt: timeout must be 0 < x < 255, using %d\n", - timeout); - } -} - -static inline void eurwdt_write_reg(u8 index, u8 data) -{ - outb(index, io); - outb(data, io+1); -} - -static inline void eurwdt_lock_chip(void) -{ - outb(0xaa, io); -} - -static inline void eurwdt_unlock_chip(void) -{ - outb(0x55, io); - eurwdt_write_reg(0x07, 0x08); /* set the logical device */ -} - -static inline void eurwdt_set_timeout(int timeout) -{ - eurwdt_write_reg(WDT_TIMEOUT_VAL, (u8) timeout); -} - -static inline void eurwdt_disable_timer(void) -{ - eurwdt_set_timeout(0); -} - -static void eurwdt_activate_timer(void) -{ - eurwdt_disable_timer(); - eurwdt_write_reg(WDT_CTRL_REG, 0x01); /* activate the WDT */ - eurwdt_write_reg(WDT_OUTPIN_CFG, !strcmp("int", ev) ? - WDT_EVENT_INT : WDT_EVENT_REBOOT); - /* Setting interrupt line */ - if (irq == 2 || irq > 15 || irq < 0) { - printk(KERN_ERR ": invalid irq number\n"); - irq = 0; /* if invalid we disable interrupt */ - } - if (irq == 0) - printk(KERN_INFO ": interrupt disabled\n"); - eurwdt_write_reg(WDT_TIMER_CFG, irq<<4); - - eurwdt_write_reg(WDT_UNIT_SEL, WDT_UNIT_SECS); /* we use seconds */ - eurwdt_set_timeout(0); /* the default timeout */ -} - - -/* - * Kernel methods. - */ - -void eurwdt_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - printk(KERN_CRIT "timeout WDT timeout\n"); - -#ifdef ONLY_TESTING - printk(KERN_CRIT "Would Reboot.\n"); -#else - printk(KERN_CRIT "Initiating system reboot.\n"); - machine_restart(NULL); -#endif -} - - -/** - * eurwdt_ping: - * - * Reload counter one with the watchdog timeout. - */ - -static void eurwdt_ping(void) -{ - /* Write the watchdog default value */ - eurwdt_set_timeout(timeout); -} - -/** - * eurwdt_write: - * @file: file handle to the watchdog - * @buf: buffer to write (unused as data does not matter here - * @count: count of bytes - * @ppos: pointer to the position to write. No seeks allowed - * - * A write to a watchdog device is defined as a keepalive signal. Any - * write of data will do, as we we don't define content meaning. - */ - -static ssize_t eurwdt_write(struct file *file, const char *buf, size_t count, -loff_t *ppos) -{ - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - - if (count) { - eurwdt_ping(); /* the default timeout */ - return 1; - } - - return 0; -} - -/** - * eurwdt_ioctl: - * @inode: inode of the device - * @file: file handle to the device - * @cmd: watchdog command - * @arg: argument pointer - * - * The watchdog API defines a common set of functions for all watchdogs - * according to their available features. - */ - -static int eurwdt_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - static struct watchdog_info ident = { - options : WDIOF_CARDRESET, - firmware_version : 1, - identity : "WDT Eurotech CPU-1220/1410" - }; - - int time; - - switch(cmd) { - default: - return -ENOTTY; - - case WDIOC_GETSUPPORT: - return copy_to_user((struct watchdog_info *)arg, &ident, - sizeof(ident)) ? -EFAULT : 0; - - case WDIOC_GETBOOTSTATUS: - return put_user(0, (int *) arg); - - case WDIOC_KEEPALIVE: - eurwdt_ping(); - return 0; - - case WDIOC_SETTIMEOUT: - if (copy_from_user(&time, (int *) arg, sizeof(int))) - return -EFAULT; - - /* Sanity check */ - if (time < 0 || time > 255) - return -EINVAL; - - timeout = time; - eurwdt_set_timeout(time); - return 0; - } -} - -/** - * eurwdt_open: - * @inode: inode of device - * @file: file handle to device - * - * The misc device has been opened. The watchdog device is single - * open and on opening we load the counter. - */ - -static int eurwdt_open(struct inode *inode, struct file *file) -{ - switch (minor(inode->i_rdev)) { - case WATCHDOG_MINOR: - spin_lock(&eurwdt_lock); - if (eurwdt_is_open) { - spin_unlock(&eurwdt_lock); - return -EBUSY; - } - if (nowayout) { - MOD_INC_USE_COUNT; - } - - eurwdt_is_open = 1; - - /* Activate the WDT */ - eurwdt_activate_timer(); - - spin_unlock(&eurwdt_lock); - - MOD_INC_USE_COUNT; - - return 0; - - case TEMP_MINOR: - return 0; - - default: - return -ENODEV; - } -} - -/** - * eurwdt_release: - * @inode: inode to board - * @file: file handle to board - * - * The watchdog has a configurable API. There is a religious dispute - * between people who want their watchdog to be able to shut down and - * those who want to be sure if the watchdog manager dies the machine - * reboots. In the former case we disable the counters, in the latter - * case you have to open it again very soon. - */ - -static int eurwdt_release(struct inode *inode, struct file *file) -{ - if (minor(inode->i_rdev) == WATCHDOG_MINOR) { - if (!nowayout) { - eurwdt_disable_timer(); - } - eurwdt_is_open = 0; - - MOD_DEC_USE_COUNT; - } - - return 0; -} - -/** - * eurwdt_notify_sys: - * @this: our notifier block - * @code: the event being reported - * @unused: unused - * - * Our notifier is called on system shutdowns. We want to turn the card - * off at reboot otherwise the machine will reboot again during memory - * test or worse yet during the following fsck. This would suck, in fact - * trust me - if it happens it does suck. - */ - -static int eurwdt_notify_sys(struct notifier_block *this, unsigned long code, - void *unused) -{ - if (code == SYS_DOWN || code == SYS_HALT) { - /* Turn the card off */ - eurwdt_disable_timer(); - } - - return NOTIFY_DONE; -} - -/* - * Kernel Interfaces - */ - - -static struct file_operations eurwdt_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .write = eurwdt_write, - .ioctl = eurwdt_ioctl, - .open = eurwdt_open, - .release = eurwdt_release, -}; - -static struct miscdevice eurwdt_miscdev = -{ - WATCHDOG_MINOR, - "watchdog", - &eurwdt_fops -}; - -/* - * The WDT card needs to learn about soft shutdowns in order to - * turn the timebomb registers off. - */ - -static struct notifier_block eurwdt_notifier = -{ - eurwdt_notify_sys, - NULL, - 0 -}; - -/** - * cleanup_module: - * - * Unload the watchdog. You cannot do this with any file handles open. - * If your watchdog is set to continue ticking on close and you unload - * it, well it keeps ticking. We won't get the interrupt but the board - * will not touch PC memory so all is fine. You just have to load a new - * module in 60 seconds or reboot. - */ - -static void __exit eurwdt_exit(void) -{ - eurwdt_lock_chip(); - - misc_deregister(&eurwdt_miscdev); - - unregister_reboot_notifier(&eurwdt_notifier); - release_region(io, 2); - free_irq(irq, NULL); -} - -/** - * eurwdt_init: - * - * Set up the WDT watchdog board. After grabbing the resources - * we require we need also to unlock the device. - * The open() function will actually kick the board off. - */ - -static int __init eurwdt_init(void) -{ - int ret; - - eurwdt_validate_timeout(); - ret = misc_register(&eurwdt_miscdev); - if (ret) { - printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n", - WATCHDOG_MINOR); - goto out; - } - - ret = request_irq(irq, eurwdt_interrupt, SA_INTERRUPT, "eurwdt", NULL); - if(ret) { - printk(KERN_ERR "eurwdt: IRQ %d is not free.\n", irq); - goto outmisc; - } - - if (!request_region(io, 2, "eurwdt")) { - printk(KERN_ERR "eurwdt: IO %X is not free.\n", io); - ret = -EBUSY; - goto outirq; - } - - ret = register_reboot_notifier(&eurwdt_notifier); - if (ret) { - printk(KERN_ERR "eurwdt: can't register reboot notifier (err=%d)\n", ret); - goto outreg; - } - - eurwdt_unlock_chip(); - - ret = 0; - printk(KERN_INFO "Eurotech WDT driver 0.01 at %X (Interrupt %d)" - " - timeout event: %s\n", - io, irq, (!strcmp("int", ev) ? "int" : "reboot")); - - spin_lock_init(&eurwdt_lock); - - out: - return ret; - - outreg: - release_region(io, 2); - - outirq: - free_irq(irq, NULL); - - outmisc: - misc_deregister(&eurwdt_miscdev); - goto out; -} - -module_init(eurwdt_init); -module_exit(eurwdt_exit); - -MODULE_AUTHOR("Rodolfo Giometti"); -MODULE_DESCRIPTION("Driver for Eurotech CPU-1220/1410 on board watchdog"); -MODULE_LICENSE("GPL"); diff -Nru a/drivers/char/i810-tco.c b/drivers/char/i810-tco.c --- a/drivers/char/i810-tco.c Fri Nov 22 13:41:17 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,431 +0,0 @@ -/* - * i810-tco 0.05: TCO timer driver for i8xx chipsets - * - * (c) Copyright 2000 kernel concepts , All Rights Reserved. - * http://www.kernelconcepts.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 of the License, or (at your option) any later version. - * - * Neither kernel concepts nor Nils Faerber admit liability nor provide - * warranty for any of this software. This material is provided - * "AS-IS" and at no charge. - * - * (c) Copyright 2000 kernel concepts - * developed for - * Jentro AG, Haar/Munich (Germany) - * - * TCO timer driver for i8xx chipsets - * based on softdog.c by Alan Cox - * - * The TCO timer is implemented in the following I/O controller hubs: - * (See the intel documentation on http://developer.intel.com.) - * 82801AA & 82801AB chip : document number 290655-003, 290677-004, - * 82801BA & 82801BAM chip : document number 290687-002, 298242-005, - * 82801CA & 82801CAM chip : document number 290716-001, 290718-001, - * 82801DB & 82801E chip : document number 290744-001, 273599-001 - * - * 20000710 Nils Faerber - * Initial Version 0.01 - * 20000728 Nils Faerber - * 0.02 Fix for SMI_EN->TCO_EN bit, some cleanups - * 20011214 Matt Domsch - * 0.03 Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT - * Didn't add timeout option as i810_margin already exists. - * 20020224 Joel Becker, Wim Van Sebroeck - * 0.04 Support for 82801CA(M) chipset, timer margin needs to be > 3, - * add support for WDIOC_SETTIMEOUT and WDIOC_GETTIMEOUT. - * 20020412 Rob Radez , Wim Van Sebroeck - * 0.05 Fix possible timer_alive race, add expect close support, - * clean up ioctls (WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS and - * WDIOC_SETOPTIONS), made i810tco_getdevice __init, - * removed boot_status, removed tco_timer_read, - * added support for 82801DB and 82801E chipset, general cleanup. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "i810-tco.h" - - -/* Module and version information */ -#define TCO_VERSION "0.05" -#define TCO_MODULE_NAME "i810 TCO timer" -#define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION - -/* Default expire timeout */ -#define TIMER_MARGIN 50 /* steps of 0.6sec, 3 0x3f || tmrval < 0x04) - return -1; - - spin_lock(&tco_lock); - val = inb (TCO1_TMR); - val &= 0xc0; - val |= tmrval; - outb (val, TCO1_TMR); - val = inb (TCO1_TMR); - spin_unlock(&tco_lock); - - if ((val & 0x3f) != tmrval) - return -1; - - return 0; -} - -/* - * Reload (trigger) the timer. Lock is needed so we dont reload it during - * a reprogramming event - */ - -static void tco_timer_reload (void) -{ - spin_lock(&tco_lock); - outb (0x01, TCO1_RLD); - spin_unlock(&tco_lock); -} - -/* - * Allow only one person to hold it open - */ - -static int i810tco_open (struct inode *inode, struct file *file) -{ - if (test_and_set_bit(0, &timer_alive)) - return -EBUSY; - - /* - * Reload and activate timer - */ - tco_timer_reload (); - tco_timer_start (); - return 0; -} - -static int i810tco_release (struct inode *inode, struct file *file) -{ - /* - * Shut off the timer. - */ - if (tco_expect_close == 42 && !nowayout) { - tco_timer_stop (); - } else { - tco_timer_reload (); - printk(KERN_CRIT TCO_MODULE_NAME ": Unexpected close, not stopping watchdog!\n"); - } - clear_bit(0, &timer_alive); - tco_expect_close = 0; - return 0; -} - -static ssize_t i810tco_write (struct file *file, const char *data, - size_t len, loff_t * ppos) -{ - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - - /* See if we got the magic character 'V' and reload the timer */ - if (len) { - size_t i; - - tco_expect_close = 0; - - /* scan to see wether or not we got the magic character */ - for (i = 0; i != len; i++) { - u8 c; - if(get_user(c, data+i)) - return -EFAULT; - if (c == 'V') - tco_expect_close = 42; - } - - /* someone wrote to us, we should reload the timer */ - tco_timer_reload (); - return 1; - } - return 0; -} - -static int i810tco_ioctl (struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int new_margin, u_margin; - int options, retval = -EINVAL; - - static struct watchdog_info ident = { - .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, - .firmware_version = 0, - .identity = "i810 TCO timer", - }; - switch (cmd) { - default: - return -ENOTTY; - case WDIOC_GETSUPPORT: - if (copy_to_user - ((struct watchdog_info *) arg, &ident, sizeof (ident))) - return -EFAULT; - return 0; - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - return put_user (0, (int *) arg); - case WDIOC_SETOPTIONS: - if (get_user (options, (int *) arg)) - return -EFAULT; - if (options & WDIOS_DISABLECARD) { - tco_timer_stop (); - retval = 0; - } - if (options & WDIOS_ENABLECARD) { - tco_timer_reload (); - tco_timer_start (); - retval = 0; - } - return retval; - case WDIOC_KEEPALIVE: - tco_timer_reload (); - return 0; - case WDIOC_SETTIMEOUT: - if (get_user (u_margin, (int *) arg)) - return -EFAULT; - new_margin = (u_margin * 10 + 5) / 6; - if ((new_margin < 4) || (new_margin > 63)) - return -EINVAL; - if (tco_timer_settimer ((unsigned char) new_margin)) - return -EINVAL; - i810_margin = new_margin; - tco_timer_reload (); - /* Fall */ - case WDIOC_GETTIMEOUT: - return put_user ((int)(i810_margin * 6 / 10), (int *) arg); - } -} - -/* - * Data for PCI driver interface - * - * This data only exists for exporting the supported - * PCI ids via MODULE_DEVICE_TABLE. We do not actually - * register a pci_driver, because someone else might one day - * want to register another driver on the same PCI id. - */ -static struct pci_device_id i810tco_pci_tbl[] __initdata = { - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0, PCI_ANY_ID, PCI_ANY_ID, }, - { 0, }, -}; -MODULE_DEVICE_TABLE (pci, i810tco_pci_tbl); - -static struct pci_dev *i810tco_pci; - -static unsigned char __init i810tco_getdevice (void) -{ - struct pci_dev *dev; - u8 val1, val2; - u16 badr; - /* - * Find the PCI device - */ - - pci_for_each_dev(dev) { - if (pci_match_device(i810tco_pci_tbl, dev)) { - i810tco_pci = dev; - break; - } - } - - if (i810tco_pci) { - /* - * Find the ACPI base I/O address which is the base - * for the TCO registers (TCOBASE=ACPIBASE + 0x60) - * ACPIBASE is bits [15:7] from 0x40-0x43 - */ - pci_read_config_byte (i810tco_pci, 0x40, &val1); - pci_read_config_byte (i810tco_pci, 0x41, &val2); - badr = ((val2 << 1) | (val1 >> 7)) << 7; - ACPIBASE = badr; - /* Something's wrong here, ACPIBASE has to be set */ - if (badr == 0x0001 || badr == 0x0000) { - printk (KERN_ERR TCO_MODULE_NAME " init: failed to get TCOBASE address\n"); - return 0; - } - /* - * Check chipset's NO_REBOOT bit - */ - pci_read_config_byte (i810tco_pci, 0xd4, &val1); - if (val1 & 0x02) { - val1 &= 0xfd; - pci_write_config_byte (i810tco_pci, 0xd4, val1); - pci_read_config_byte (i810tco_pci, 0xd4, &val1); - if (val1 & 0x02) { - printk (KERN_ERR TCO_MODULE_NAME " init: failed to reset NO_REBOOT flag, reboot disabled by hardware\n"); - return 0; /* Cannot reset NO_REBOOT bit */ - } - } - /* Set the TCO_EN bit in SMI_EN register */ - val1 = inb (SMI_EN + 1); - val1 &= 0xdf; - outb (val1, SMI_EN + 1); - /* Clear out the (probably old) status */ - outb (0, TCO1_STS); - outb (3, TCO2_STS); - return 1; - } - return 0; -} - -static struct file_operations i810tco_fops = { - .owner = THIS_MODULE, - .write = i810tco_write, - .ioctl = i810tco_ioctl, - .open = i810tco_open, - .release = i810tco_release, -}; - -static struct miscdevice i810tco_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &i810tco_fops, -}; - -static int __init watchdog_init (void) -{ - spin_lock_init(&tco_lock); - if (!i810tco_getdevice () || i810tco_pci == NULL) - return -ENODEV; - if (!request_region (TCOBASE, 0x10, "i810 TCO")) { - printk (KERN_ERR TCO_MODULE_NAME - ": I/O address 0x%04x already in use\n", - TCOBASE); - return -EIO; - } - if (misc_register (&i810tco_miscdev) != 0) { - release_region (TCOBASE, 0x10); - printk (KERN_ERR TCO_MODULE_NAME ": cannot register miscdev\n"); - return -EIO; - } - tco_timer_settimer ((unsigned char) i810_margin); - tco_timer_reload (); - - printk (KERN_INFO TCO_DRIVER_NAME - ": timer margin: %d sec (0x%04x) (nowayout=%d)\n", - (int) (i810_margin * 6 / 10), TCOBASE, nowayout); - return 0; -} - -static void __exit watchdog_cleanup (void) -{ - u8 val; - - /* Reset the timer before we leave */ - tco_timer_reload (); - /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ - pci_read_config_byte (i810tco_pci, 0xd4, &val); - val |= 0x02; - pci_write_config_byte (i810tco_pci, 0xd4, val); - release_region (TCOBASE, 0x10); - misc_deregister (&i810tco_miscdev); -} - -module_init(watchdog_init); -module_exit(watchdog_cleanup); - -MODULE_AUTHOR("Nils Faerber"); -MODULE_DESCRIPTION("TCO timer driver for i8xx chipsets"); -MODULE_LICENSE("GPL"); diff -Nru a/drivers/char/ib700wdt.c b/drivers/char/ib700wdt.c --- a/drivers/char/ib700wdt.c Fri Nov 22 13:41:23 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,311 +0,0 @@ -/* - * IB700 Single Board Computer WDT driver for Linux 2.4.x - * - * (c) Copyright 2001 Charles Howes - * - * Based on advantechwdt.c which is based on acquirewdt.c which - * is based on wdt.c. - * - * (c) Copyright 2000-2001 Marek Michalkiewicz - * - * Based on acquirewdt.c which is based on wdt.c. - * Original copyright messages: - * - * (c) Copyright 1996 Alan Cox , All Rights Reserved. - * http://www.redhat.com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide - * warranty for any of this software. This material is provided - * "AS-IS" and at no charge. - * - * (c) Copyright 1995 Alan Cox - * - * 14-Dec-2001 Matt Domsch - * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT - * Added timeout module option to override default - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int ibwdt_is_open; -static spinlock_t ibwdt_lock; - -/* - * - * Watchdog Timer Configuration - * - * The function of the watchdog timer is to reset the system - * automatically and is defined at I/O port 0443H. To enable the - * watchdog timer and allow the system to reset, write I/O port 0443H. - * To disable the timer, write I/O port 0441H for the system to stop the - * watchdog function. The timer has a tolerance of 20% for its - * intervals. - * - * The following describes how the timer should be programmed. - * - * Enabling Watchdog: - * MOV AX,000FH (Choose the values from 0 to F) - * MOV DX,0443H - * OUT DX,AX - * - * Disabling Watchdog: - * MOV AX,000FH (Any value is fine.) - * MOV DX,0441H - * OUT DX,AX - * - * Watchdog timer control table: - * Level Value Time/sec | Level Value Time/sec - * 1 F 0 | 9 7 16 - * 2 E 2 | 10 6 18 - * 3 D 4 | 11 5 20 - * 4 C 6 | 12 4 22 - * 5 B 8 | 13 3 24 - * 6 A 10 | 14 2 26 - * 7 9 12 | 15 1 28 - * 8 8 14 | 16 0 30 - * - */ - -#define WDT_STOP 0x441 -#define WDT_START 0x443 - -#define WD_TIMO 0 /* 30 seconds +/- 20%, from table */ - -static int timeout_val = WD_TIMO; /* value in table */ -static int timeout = 30; /* in seconds */ -MODULE_PARM(timeout,"i"); -MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, 0 < n < 30, must be even (default=30)"); - -#ifdef CONFIG_WATCHDOG_NOWAYOUT -static int nowayout = 1; -#else -static int nowayout = 0; -#endif - -MODULE_PARM(nowayout,"i"); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); - -/* - * Kernel methods. - */ - -static void __init -ibwdt_validate_timeout(void) -{ - timeout_val = (30 - timeout) / 2; - if (timeout_val < 0 || timeout_val > 0xF) timeout_val = WD_TIMO; -} - -static void -ibwdt_ping(void) -{ - /* Write a watchdog value */ - outb_p(timeout_val, WDT_START); -} - -static ssize_t -ibwdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) -{ - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - - if (count) { - ibwdt_ping(); - return 1; - } - return 0; -} - -static ssize_t -ibwdt_read(struct file *file, char *buf, size_t count, loff_t *ppos) -{ - return -EINVAL; -} - -static int -ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) -{ - static struct watchdog_info ident = { - WDIOF_KEEPALIVEPING, 1, "IB700 WDT" - }; - - switch (cmd) { - case WDIOC_GETSUPPORT: - if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))) - return -EFAULT; - break; - - case WDIOC_GETSTATUS: - if (copy_to_user((int *)arg, &ibwdt_is_open, sizeof(int))) - return -EFAULT; - break; - - case WDIOC_KEEPALIVE: - ibwdt_ping(); - break; - - default: - return -ENOTTY; - } - return 0; -} - -static int -ibwdt_open(struct inode *inode, struct file *file) -{ - switch (minor(inode->i_rdev)) { - case WATCHDOG_MINOR: - spin_lock(&ibwdt_lock); - if (ibwdt_is_open) { - spin_unlock(&ibwdt_lock); - return -EBUSY; - } - if (nowayout) { - MOD_INC_USE_COUNT; - } - /* - * Activate - */ - - ibwdt_is_open = 1; - ibwdt_ping(); - spin_unlock(&ibwdt_lock); - return 0; - default: - return -ENODEV; - } -} - -static int -ibwdt_close(struct inode *inode, struct file *file) -{ - lock_kernel(); - if (minor(inode->i_rdev) == WATCHDOG_MINOR) { - spin_lock(&ibwdt_lock); - if (!nowayout) { - outb_p(timeout_val, WDT_STOP); - } - ibwdt_is_open = 0; - spin_unlock(&ibwdt_lock); - } - unlock_kernel(); - return 0; -} - -/* - * Notifier for system down - */ - -static int -ibwdt_notify_sys(struct notifier_block *this, unsigned long code, - void *unused) -{ - if (code == SYS_DOWN || code == SYS_HALT) { - /* Turn the WDT off */ - outb_p(timeout_val, WDT_STOP); - } - return NOTIFY_DONE; -} - -/* - * Kernel Interfaces - */ - -static struct file_operations ibwdt_fops = { - .owner = THIS_MODULE, - .read = ibwdt_read, - .write = ibwdt_write, - .ioctl = ibwdt_ioctl, - .open = ibwdt_open, - .release = ibwdt_close, -}; - -static struct miscdevice ibwdt_miscdev = { - WATCHDOG_MINOR, - "watchdog", - &ibwdt_fops -}; - -/* - * The WDT needs to learn about soft shutdowns in order to - * turn the timebomb registers off. - */ - -static struct notifier_block ibwdt_notifier = { - ibwdt_notify_sys, - NULL, - 0 -}; - -static int __init -ibwdt_init(void) -{ - printk("WDT driver for IB700 single board computer initialising.\n"); - - ibwdt_validate_timeout(); - spin_lock_init(&ibwdt_lock); - if (misc_register(&ibwdt_miscdev)) - return -ENODEV; -#if WDT_START != WDT_STOP - if (!request_region(WDT_STOP, 1, "IB700 WDT")) { - misc_deregister(&ibwdt_miscdev); - return -EIO; - } -#endif - if (!request_region(WDT_START, 1, "IB700 WDT")) { -#if WDT_START != WDT_STOP - release_region(WDT_STOP, 1); -#endif - misc_deregister(&ibwdt_miscdev); - return -EIO; - } - register_reboot_notifier(&ibwdt_notifier); - return 0; -} - -static void __exit -ibwdt_exit(void) -{ - misc_deregister(&ibwdt_miscdev); - unregister_reboot_notifier(&ibwdt_notifier); -#if WDT_START != WDT_STOP - release_region(WDT_STOP,1); -#endif - release_region(WDT_START,1); -} - -module_init(ibwdt_init); -module_exit(ibwdt_exit); - -MODULE_AUTHOR("Charles Howes "); -MODULE_DESCRIPTION("IB700 SBC watchdog driver"); -MODULE_LICENSE("GPL"); - -/* end of ib700wdt.c */ diff -Nru a/drivers/char/machzwd.c b/drivers/char/machzwd.c --- a/drivers/char/machzwd.c Fri Nov 22 13:41:18 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,557 +0,0 @@ -/* - * MachZ ZF-Logic Watchdog Timer driver for Linux - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * The author does NOT admit liability nor provide warranty for - * any of this software. This material is provided "AS-IS" in - * the hope that it may be useful for others. - * - * Author: Fernando Fuganti - * - * Based on sbc60xxwdt.c by Jakob Oestergaard - * - * - * We have two timers (wd#1, wd#2) driven by a 32 KHz clock with the - * following periods: - * wd#1 - 2 seconds; - * wd#2 - 7.2 ms; - * After the expiration of wd#1, it can generate a NMI, SCI, SMI, or - * a system RESET and it starts wd#2 that unconditionaly will RESET - * the system when the counter reaches zero. - * - * 14-Dec-2001 Matt Domsch - * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* ports */ -#define ZF_IOBASE 0x218 -#define INDEX 0x218 -#define DATA_B 0x219 -#define DATA_W 0x21A -#define DATA_D 0x21A - -/* indexes */ /* size */ -#define ZFL_VERSION 0x02 /* 16 */ -#define CONTROL 0x10 /* 16 */ -#define STATUS 0x12 /* 8 */ -#define COUNTER_1 0x0C /* 16 */ -#define COUNTER_2 0x0E /* 8 */ -#define PULSE_LEN 0x0F /* 8 */ - -/* controls */ -#define ENABLE_WD1 0x0001 -#define ENABLE_WD2 0x0002 -#define RESET_WD1 0x0010 -#define RESET_WD2 0x0020 -#define GEN_SCI 0x0100 -#define GEN_NMI 0x0200 -#define GEN_SMI 0x0400 -#define GEN_RESET 0x0800 - - -/* utilities */ - -#define WD1 0 -#define WD2 1 - -#define zf_writew(port, data) { outb(port, INDEX); outw(data, DATA_W); } -#define zf_writeb(port, data) { outb(port, INDEX); outb(data, DATA_B); } -#define zf_get_ZFL_version() zf_readw(ZFL_VERSION) - - -static unsigned short zf_readw(unsigned char port) -{ - outb(port, INDEX); - return inw(DATA_W); -} - -static unsigned short zf_readb(unsigned char port) -{ - outb(port, INDEX); - return inb(DATA_B); -} - - -MODULE_AUTHOR("Fernando Fuganti "); -MODULE_DESCRIPTION("MachZ ZF-Logic Watchdog driver"); -MODULE_LICENSE("GPL"); -MODULE_PARM(action, "i"); -MODULE_PARM_DESC(action, "after watchdog resets, generate: 0 = RESET(*) 1 = SMI 2 = NMI 3 = SCI"); - -#ifdef CONFIG_WATCHDOG_NOWAYOUT -static int nowayout = 1; -#else -static int nowayout = 0; -#endif - -MODULE_PARM(nowayout,"i"); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); - -#define PFX "machzwd" - -static struct watchdog_info zf_info = { - .options = WDIOF_KEEPALIVEPING, - .firmware_version = 1, - .identity = "ZF-Logic watchdog" -}; - - -/* - * action refers to action taken when watchdog resets - * 0 = GEN_RESET - * 1 = GEN_SMI - * 2 = GEN_NMI - * 3 = GEN_SCI - * defaults to GEN_RESET (0) - */ -static int action = 0; -static int zf_action = GEN_RESET; -static int zf_is_open = 0; -static int zf_expect_close = 0; -static spinlock_t zf_lock; -static spinlock_t zf_port_lock; -static struct timer_list zf_timer; -static unsigned long next_heartbeat = 0; - - -/* timeout for user land heart beat (10 seconds) */ -#define ZF_USER_TIMEO (HZ*10) - -/* timeout for hardware watchdog (~500ms) */ -#define ZF_HW_TIMEO (HZ/2) - -/* number of ticks on WD#1 (driven by a 32KHz clock, 2s) */ -#define ZF_CTIMEOUT 0xffff - -#ifndef ZF_DEBUG -# define dprintk(format, args...) -#else -# define dprintk(format, args...) printk(KERN_DEBUG PFX; ":" __FUNCTION__ ":%d: " format, __LINE__ , ## args) -#endif - - -/* STATUS register functions */ - -static inline unsigned char zf_get_status(void) -{ - return zf_readb(STATUS); -} - -static inline void zf_set_status(unsigned char new) -{ - zf_writeb(STATUS, new); -} - - -/* CONTROL register functions */ - -static inline unsigned short zf_get_control(void) -{ - return zf_readw(CONTROL); -} - -static inline void zf_set_control(unsigned short new) -{ - zf_writew(CONTROL, new); -} - - -/* WD#? counter functions */ -/* - * Just get current counter value - */ - -static inline unsigned short zf_get_timer(unsigned char n) -{ - switch(n){ - case WD1: - return zf_readw(COUNTER_1); - case WD2: - return zf_readb(COUNTER_2); - default: - return 0; - } -} - -/* - * Just set counter value - */ - -static inline void zf_set_timer(unsigned short new, unsigned char n) -{ - switch(n){ - case WD1: - zf_writew(COUNTER_1, new); - case WD2: - zf_writeb(COUNTER_2, new > 0xff ? 0xff : new); - default: - return; - } -} - -/* - * stop hardware timer - */ -static void zf_timer_off(void) -{ - unsigned int ctrl_reg = 0; - unsigned long flags; - - /* stop internal ping */ - del_timer_sync(&zf_timer); - - spin_lock_irqsave(&zf_port_lock, flags); - /* stop watchdog timer */ - ctrl_reg = zf_get_control(); - ctrl_reg |= (ENABLE_WD1|ENABLE_WD2); /* disable wd1 and wd2 */ - ctrl_reg &= ~(ENABLE_WD1|ENABLE_WD2); - zf_set_control(ctrl_reg); - spin_unlock_irqrestore(&zf_port_lock, flags); - - printk(KERN_INFO PFX ": Watchdog timer is now disabled\n"); -} - - -/* - * start hardware timer - */ -static void zf_timer_on(void) -{ - unsigned int ctrl_reg = 0; - unsigned long flags; - - spin_lock_irqsave(&zf_port_lock, flags); - - zf_writeb(PULSE_LEN, 0xff); - - zf_set_timer(ZF_CTIMEOUT, WD1); - - /* user land ping */ - next_heartbeat = jiffies + ZF_USER_TIMEO; - - /* start the timer for internal ping */ - zf_timer.expires = jiffies + ZF_HW_TIMEO; - - add_timer(&zf_timer); - - /* start watchdog timer */ - ctrl_reg = zf_get_control(); - ctrl_reg |= (ENABLE_WD1|zf_action); - zf_set_control(ctrl_reg); - spin_unlock_irqrestore(&zf_port_lock, flags); - - printk(KERN_INFO PFX ": Watchdog timer is now enabled\n"); -} - - -static void zf_ping(unsigned long data) -{ - unsigned int ctrl_reg = 0; - unsigned long flags; - - zf_writeb(COUNTER_2, 0xff); - - if(time_before(jiffies, next_heartbeat)){ - - dprintk("time_before: %ld\n", next_heartbeat - jiffies); - - /* - * reset event is activated by transition from 0 to 1 on - * RESET_WD1 bit and we assume that it is already zero... - */ - - spin_lock_irqsave(&zf_port_lock, flags); - ctrl_reg = zf_get_control(); - ctrl_reg |= RESET_WD1; - zf_set_control(ctrl_reg); - - /* ...and nothing changes until here */ - ctrl_reg &= ~(RESET_WD1); - zf_set_control(ctrl_reg); - spin_unlock_irqrestore(&zf_port_lock, flags); - - zf_timer.expires = jiffies + ZF_HW_TIMEO; - add_timer(&zf_timer); - }else{ - printk(KERN_CRIT PFX ": I will reset your machine\n"); - } -} - -static ssize_t zf_write(struct file *file, const char *buf, size_t count, - loff_t *ppos) -{ - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - - /* See if we got the magic character */ - if(count){ - -/* - * no need to check for close confirmation - * no way to disable watchdog ;) - */ - if (!nowayout) { - size_t ofs; - - /* - * note: just in case someone wrote the magic character - * five months ago... - */ - zf_expect_close = 0; - - /* now scan */ - for(ofs = 0; ofs != count; ofs++){ - char c; - if (get_user(c, buf + ofs)) - return -EFAULT; - if (c == 'V'){ - zf_expect_close = 1; - dprintk("zf_expect_close 1\n"); - } - } - } - /* - * Well, anyhow someone wrote to us, - * we should return that favour - */ - next_heartbeat = jiffies + ZF_USER_TIMEO; - dprintk("user ping at %ld\n", jiffies); - - return 1; - } - - return 0; -} - -static ssize_t zf_read(struct file *file, char *buf, size_t count, - loff_t *ppos) -{ - return -EINVAL; -} - - - -static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) -{ - switch(cmd){ - case WDIOC_GETSUPPORT: - if (copy_to_user((struct watchdog_info *)arg, - &zf_info, sizeof(zf_info))) - return -EFAULT; - break; - - case WDIOC_GETSTATUS: - if (copy_to_user((int *)arg, &zf_is_open, sizeof(int))) - return -EFAULT; - break; - - case WDIOC_KEEPALIVE: - zf_ping(0); - break; - - default: - return -ENOTTY; - } - - return 0; -} - -static int zf_open(struct inode *inode, struct file *file) -{ - switch(minor(inode->i_rdev)){ - case WATCHDOG_MINOR: - spin_lock(&zf_lock); - if(zf_is_open){ - spin_unlock(&zf_lock); - return -EBUSY; - } - - if (nowayout) { - MOD_INC_USE_COUNT; - } - zf_is_open = 1; - - spin_unlock(&zf_lock); - - zf_timer_on(); - - return 0; - default: - return -ENODEV; - } -} - -static int zf_close(struct inode *inode, struct file *file) -{ - if(minor(inode->i_rdev) == WATCHDOG_MINOR){ - - if(zf_expect_close){ - zf_timer_off(); - } else { - del_timer(&zf_timer); - printk(KERN_ERR PFX ": device file closed unexpectedly. Will not stop the WDT!\n"); - } - - spin_lock(&zf_lock); - zf_is_open = 0; - spin_unlock(&zf_lock); - - zf_expect_close = 0; - } - - return 0; -} - -/* - * Notifier for system down - */ - -static int zf_notify_sys(struct notifier_block *this, unsigned long code, - void *unused) -{ - if(code == SYS_DOWN || code == SYS_HALT){ - zf_timer_off(); - } - - return NOTIFY_DONE; -} - - - - -static struct file_operations zf_fops = { - .owner = THIS_MODULE, - .read = zf_read, - .write = zf_write, - .ioctl = zf_ioctl, - .open = zf_open, - .release = zf_close, -}; - -static struct miscdevice zf_miscdev = { - WATCHDOG_MINOR, - "watchdog", - &zf_fops -}; - - -/* - * The device needs to learn about soft shutdowns in order to - * turn the timebomb registers off. - */ -static struct notifier_block zf_notifier = { - zf_notify_sys, - NULL, - 0 -}; - -static void __init zf_show_action(int act) -{ - char *str[] = { "RESET", "SMI", "NMI", "SCI" }; - - printk(KERN_INFO PFX ": Watchdog using action = %s\n", str[act]); -} - -static int __init zf_init(void) -{ - int ret; - - printk(KERN_INFO PFX ": MachZ ZF-Logic Watchdog driver initializing.\n"); - - ret = zf_get_ZFL_version(); - printk("%#x\n", ret); - if((!ret) || (ret != 0xffff)){ - printk(KERN_WARNING PFX ": no ZF-Logic found\n"); - return -ENODEV; - } - - if((action <= 3) && (action >= 0)){ - zf_action = zf_action>>action; - } else - action = 0; - - zf_show_action(action); - - spin_lock_init(&zf_lock); - spin_lock_init(&zf_port_lock); - - ret = misc_register(&zf_miscdev); - if (ret){ - printk(KERN_ERR "can't misc_register on minor=%d\n", - WATCHDOG_MINOR); - goto out; - } - - if(!request_region(ZF_IOBASE, 3, "MachZ ZFL WDT")){ - printk(KERN_ERR "cannot reserve I/O ports at %d\n", - ZF_IOBASE); - ret = -EBUSY; - goto no_region; - } - - ret = register_reboot_notifier(&zf_notifier); - if(ret){ - printk(KERN_ERR "can't register reboot notifier (err=%d)\n", - ret); - goto no_reboot; - } - - zf_set_status(0); - zf_set_control(0); - - /* this is the timer that will do the hard work */ - init_timer(&zf_timer); - zf_timer.function = zf_ping; - zf_timer.data = 0; - - return 0; - -no_reboot: - release_region(ZF_IOBASE, 3); -no_region: - misc_deregister(&zf_miscdev); -out: - return ret; -} - - -void __exit zf_exit(void) -{ - zf_timer_off(); - - misc_deregister(&zf_miscdev); - unregister_reboot_notifier(&zf_notifier); - release_region(ZF_IOBASE, 3); -} - -module_init(zf_init); -module_exit(zf_exit); diff -Nru a/drivers/char/mem.c b/drivers/char/mem.c --- a/drivers/char/mem.c Fri Nov 22 13:41:20 2002 +++ b/drivers/char/mem.c Fri Nov 22 13:41:20 2002 @@ -377,6 +377,7 @@ return count; } +#ifdef CONFIG_MMU /* * For fun, we are using the MMU for this. */ @@ -476,6 +477,29 @@ return -EAGAIN; return 0; } +#else /* CONFIG_MMU */ +static ssize_t read_zero(struct file * file, char * buf, + size_t count, loff_t *ppos) +{ + unsigned long left; + + if (!count) + return 0; + + for (left = count; left > 0; left--, buf++) { + if (put_user(0, buf)) + return -EFAULT; + cond_resched(); + } + + return count; +} + +static int mmap_zero(struct file * file, struct vm_area_struct * vma) +{ + return -ENOSYS; +} +#endif /* CONFIG_MMU */ static ssize_t write_full(struct file * file, const char * buf, size_t count, loff_t *ppos) diff -Nru a/drivers/char/mixcomwd.c b/drivers/char/mixcomwd.c --- a/drivers/char/mixcomwd.c Fri Nov 22 13:41:18 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,282 +0,0 @@ -/* - * MixCom Watchdog: A Simple Hardware Watchdog Device - * Based on Softdog driver by Alan Cox and PC Watchdog driver by Ken Hollis - * - * Author: Gergely Madarasz - * - * Copyright (c) 1999 ITConsult-Pro Co. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Version 0.1 (99/04/15): - * - first version - * - * Version 0.2 (99/06/16): - * - added kernel timer watchdog ping after close - * since the hardware does not support watchdog shutdown - * - * Version 0.3 (99/06/21): - * - added WDIOC_GETSTATUS and WDIOC_GETSUPPORT ioctl calls - * - * Version 0.3.1 (99/06/22): - * - allow module removal while internal timer is active, - * print warning about probable reset - * - * Version 0.4 (99/11/15): - * - support for one more type board - * - * Version 0.5 (2001/12/14) Matt Domsch - * - added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT - * - */ - -#define VERSION "0.5" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int mixcomwd_ioports[] = { 0x180, 0x280, 0x380, 0x000 }; - -#define MIXCOM_WATCHDOG_OFFSET 0xc10 -#define MIXCOM_ID 0x11 -#define FLASHCOM_WATCHDOG_OFFSET 0x4 -#define FLASHCOM_ID 0x18 - -static long mixcomwd_opened; /* long req'd for setbit --RR */ - -static int watchdog_port; -static int mixcomwd_timer_alive; -static struct timer_list mixcomwd_timer = TIMER_INITIALIZER(NULL, 0, 0); - -#ifdef CONFIG_WATCHDOG_NOWAYOUT -static int nowayout = 1; -#else -static int nowayout = 0; -#endif - -MODULE_PARM(nowayout,"i"); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); - -static void mixcomwd_ping(void) -{ - outb_p(55,watchdog_port); - return; -} - -static void mixcomwd_timerfun(unsigned long d) -{ - mixcomwd_ping(); - - mod_timer(&mixcomwd_timer,jiffies+ 5*HZ); -} - -/* - * Allow only one person to hold it open - */ - -static int mixcomwd_open(struct inode *inode, struct file *file) -{ - if(test_and_set_bit(0,&mixcomwd_opened)) { - return -EBUSY; - } - mixcomwd_ping(); - - if (nowayout) { - MOD_INC_USE_COUNT; - } else { - if(mixcomwd_timer_alive) { - del_timer(&mixcomwd_timer); - mixcomwd_timer_alive=0; - } - } - return 0; -} - -static int mixcomwd_release(struct inode *inode, struct file *file) -{ - - if (!nowayout) { - if(mixcomwd_timer_alive) { - printk(KERN_ERR "mixcomwd: release called while internal timer alive"); - return -EBUSY; - } - init_timer(&mixcomwd_timer); - mixcomwd_timer.expires=jiffies + 5 * HZ; - mixcomwd_timer.function=mixcomwd_timerfun; - mixcomwd_timer.data=0; - mixcomwd_timer_alive=1; - add_timer(&mixcomwd_timer); - } - clear_bit(0,&mixcomwd_opened); - return 0; -} - - -static ssize_t mixcomwd_write(struct file *file, const char *data, size_t len, loff_t *ppos) -{ - if (ppos != &file->f_pos) { - return -ESPIPE; - } - - if(len) - { - mixcomwd_ping(); - return 1; - } - return 0; -} - -static int mixcomwd_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int status; - static struct watchdog_info ident = { - WDIOF_KEEPALIVEPING, 1, "MixCOM watchdog" - }; - - switch(cmd) - { - case WDIOC_GETSTATUS: - status=mixcomwd_opened; - if (!nowayout) { - status|=mixcomwd_timer_alive; - } - if (copy_to_user((int *)arg, &status, sizeof(int))) { - return -EFAULT; - } - break; - case WDIOC_GETSUPPORT: - if (copy_to_user((struct watchdog_info *)arg, &ident, - sizeof(ident))) { - return -EFAULT; - } - break; - case WDIOC_KEEPALIVE: - mixcomwd_ping(); - break; - default: - return -ENOTTY; - } - return 0; -} - -static struct file_operations mixcomwd_fops= -{ - .owner = THIS_MODULE, - .write = mixcomwd_write, - .ioctl = mixcomwd_ioctl, - .open = mixcomwd_open, - .release = mixcomwd_release, -}; - -static struct miscdevice mixcomwd_miscdev= -{ - WATCHDOG_MINOR, - "watchdog", - &mixcomwd_fops -}; - -static int __init mixcomwd_checkcard(int port) -{ - int id; - - if(check_region(port+MIXCOM_WATCHDOG_OFFSET,1)) { - return 0; - } - - id=inb_p(port + MIXCOM_WATCHDOG_OFFSET) & 0x3f; - if(id!=MIXCOM_ID) { - return 0; - } - return 1; -} - -static int __init flashcom_checkcard(int port) -{ - int id; - - if(check_region(port + FLASHCOM_WATCHDOG_OFFSET,1)) { - return 0; - } - - id=inb_p(port + FLASHCOM_WATCHDOG_OFFSET); - if(id!=FLASHCOM_ID) { - return 0; - } - return 1; - } - -static int __init mixcomwd_init(void) -{ - int i; - int ret; - int found=0; - - for (i = 0; !found && mixcomwd_ioports[i] != 0; i++) { - if (mixcomwd_checkcard(mixcomwd_ioports[i])) { - found = 1; - watchdog_port = mixcomwd_ioports[i] + MIXCOM_WATCHDOG_OFFSET; - } - } - - /* The FlashCOM card can be set up at 0x300 -> 0x378, in 0x8 jumps */ - for (i = 0x300; !found && i < 0x380; i+=0x8) { - if (flashcom_checkcard(i)) { - found = 1; - watchdog_port = i + FLASHCOM_WATCHDOG_OFFSET; - } - } - - if (!found) { - printk("mixcomwd: No card detected, or port not available.\n"); - return -ENODEV; - } - - if (!request_region(watchdog_port,1,"MixCOM watchdog")) - return -EIO; - - ret = misc_register(&mixcomwd_miscdev); - if (ret) - { - release_region(watchdog_port, 1); - return ret; - } - - printk(KERN_INFO "MixCOM watchdog driver v%s, watchdog port at 0x%3x\n",VERSION,watchdog_port); - - return 0; -} - -static void __exit mixcomwd_exit(void) -{ - if (!nowayout) { - if(mixcomwd_timer_alive) { - printk(KERN_WARNING "mixcomwd: I quit now, hardware will" - " probably reboot!\n"); - del_timer(&mixcomwd_timer); - mixcomwd_timer_alive=0; - } - } - release_region(watchdog_port,1); - misc_deregister(&mixcomwd_miscdev); -} - -module_init(mixcomwd_init); -module_exit(mixcomwd_exit); - -MODULE_LICENSE("GPL"); diff -Nru a/drivers/char/pcwd.c b/drivers/char/pcwd.c --- a/drivers/char/pcwd.c Fri Nov 22 13:41:17 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,672 +0,0 @@ -/* - * PC Watchdog Driver - * by Ken Hollis (khollis@bitgate.com) - * - * Permission granted from Simon Machell (73244.1270@compuserve.com) - * Written for the Linux Kernel, and GPLed by Ken Hollis - * - * 960107 Added request_region routines, modulized the whole thing. - * 960108 Fixed end-of-file pointer (Thanks to Dan Hollis), added - * WD_TIMEOUT define. - * 960216 Added eof marker on the file, and changed verbose messages. - * 960716 Made functional and cosmetic changes to the source for - * inclusion in Linux 2.0.x kernels, thanks to Alan Cox. - * 960717 Removed read/seek routines, replaced with ioctl. Also, added - * check_region command due to Alan's suggestion. - * 960821 Made changes to compile in newer 2.0.x kernels. Added - * "cold reboot sense" entry. - * 960825 Made a few changes to code, deleted some defines and made - * typedefs to replace them. Made heartbeat reset only available - * via ioctl, and removed the write routine. - * 960828 Added new items for PC Watchdog Rev.C card. - * 960829 Changed around all of the IOCTLs, added new features, - * added watchdog disable/re-enable routines. Added firmware - * version reporting. Added read routine for temperature. - * Removed some extra defines, added an autodetect Revision - * routine. - * 961006 Revised some documentation, fixed some cosmetic bugs. Made - * drivers to panic the system if it's overheating at bootup. - * 961118 Changed some verbiage on some of the output, tidied up - * code bits, and added compatibility to 2.1.x. - * 970912 Enabled board on open and disable on close. - * 971107 Took account of recent VFS changes (broke read). - * 971210 Disable board on initialisation in case board already ticking. - * 971222 Changed open/close for temperature handling - * Michael Meskes . - * 980112 Used minor numbers from include/linux/miscdevice.h - * 990403 Clear reset status after reading control status register in - * pcwd_showprevstate(). [Marc Boucher ] - * 990605 Made changes to code to support Firmware 1.22a, added - * fairly useless proc entry. - * 990610 removed said useless proc code for the merge - * 000403 Removed last traces of proc code. - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -/* - * These are the auto-probe addresses available. - * - * Revision A only uses ports 0x270 and 0x370. Revision C introduced 0x350. - * Revision A has an address range of 2 addresses, while Revision C has 3. - */ -static int pcwd_ioports[] = { 0x270, 0x350, 0x370, 0x000 }; - -#define WD_VER "1.10 (06/05/99)" - -/* - * It should be noted that PCWD_REVISION_B was removed because A and B - * are essentially the same types of card, with the exception that B - * has temperature reporting. Since I didn't receive a Rev.B card, - * the Rev.B card is not supported. (It's a good thing too, as they - * are no longer in production.) - */ -#define PCWD_REVISION_A 1 -#define PCWD_REVISION_C 2 - -#define WD_TIMEOUT 3 /* 1 1/2 seconds for a timeout */ - -/* - * These are the defines for the PC Watchdog card, revision A. - */ -#define WD_WDRST 0x01 /* Previously reset state */ -#define WD_T110 0x02 /* Temperature overheat sense */ -#define WD_HRTBT 0x04 /* Heartbeat sense */ -#define WD_RLY2 0x08 /* External relay triggered */ -#define WD_SRLY2 0x80 /* Software external relay triggered */ - -static int current_readport, revision, temp_panic; -static atomic_t open_allowed = ATOMIC_INIT(1); -static int initial_status, supports_temp, mode_debug; -static spinlock_t io_lock; - -/* - * PCWD_CHECKCARD - * - * This routine checks the "current_readport" to see if the card lies there. - * If it does, it returns accordingly. - */ -static int __init pcwd_checkcard(void) -{ - int card_dat, prev_card_dat, found = 0, count = 0, done = 0; - - card_dat = 0x00; - prev_card_dat = 0x00; - - prev_card_dat = inb(current_readport); - if (prev_card_dat == 0xFF) - return 0; - - while(count < WD_TIMEOUT) { - - /* Read the raw card data from the port, and strip off the - first 4 bits */ - - card_dat = inb_p(current_readport); - card_dat &= 0x000F; - - /* Sleep 1/2 second (or 500000 microseconds :) */ - - mdelay(500); - done = 0; - - /* If there's a heart beat in both instances, then this means we - found our card. This also means that either the card was - previously reset, or the computer was power-cycled. */ - - if ((card_dat & WD_HRTBT) && (prev_card_dat & WD_HRTBT) && - (!done)) { - found = 1; - done = 1; - break; - } - - /* If the card data is exactly the same as the previous card data, - it's safe to assume that we should check again. The manual says - that the heart beat will change every second (or the bit will - toggle), and this can be used to see if the card is there. If - the card was powered up with a cold boot, then the card will - not start blinking until 2.5 minutes after a reboot, so this - bit will stay at 1. */ - - if ((card_dat == prev_card_dat) && (!done)) { - count++; - done = 1; - } - - /* If the card data is toggling any bits, this means that the heart - beat was detected, or something else about the card is set. */ - - if ((card_dat != prev_card_dat) && (!done)) { - done = 1; - found = 1; - break; - } - - /* Otherwise something else strange happened. */ - - if (!done) - count++; - } - - return((found) ? 1 : 0); -} - -void pcwd_showprevstate(void) -{ - int card_status = 0x0000; - - if (revision == PCWD_REVISION_A) - initial_status = card_status = inb(current_readport); - else { - initial_status = card_status = inb(current_readport + 1); - outb_p(0x00, current_readport + 1); /* clear reset status */ - } - - if (revision == PCWD_REVISION_A) { - if (card_status & WD_WDRST) - printk("pcwd: Previous reboot was caused by the card.\n"); - - if (card_status & WD_T110) { - printk("pcwd: Card senses a CPU Overheat. Panicking!\n"); - panic("pcwd: CPU Overheat.\n"); - } - - if ((!(card_status & WD_WDRST)) && - (!(card_status & WD_T110))) - printk("pcwd: Cold boot sense.\n"); - } else { - if (card_status & 0x01) - printk("pcwd: Previous reboot was caused by the card.\n"); - - if (card_status & 0x04) { - printk("pcwd: Card senses a CPU Overheat. Panicking!\n"); - panic("pcwd: CPU Overheat.\n"); - } - - if ((!(card_status & 0x01)) && - (!(card_status & 0x04))) - printk("pcwd: Cold boot sense.\n"); - } -} - -static void pcwd_send_heartbeat(void) -{ - int wdrst_stat; - - wdrst_stat = inb_p(current_readport); - wdrst_stat &= 0x0F; - - wdrst_stat |= WD_WDRST; - - if (revision == PCWD_REVISION_A) - outb_p(wdrst_stat, current_readport + 1); - else - outb_p(wdrst_stat, current_readport); -} - -static int pcwd_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int cdat, rv; - static struct watchdog_info ident= - { - WDIOF_OVERHEAT|WDIOF_CARDRESET, - 1, - "PCWD" - }; - - switch(cmd) { - default: - return -ENOTTY; - - case WDIOC_GETSUPPORT: - if(copy_to_user((void*)arg, &ident, sizeof(ident))) - return -EFAULT; - return 0; - - case WDIOC_GETSTATUS: - spin_lock(&io_lock); - if (revision == PCWD_REVISION_A) - cdat = inb(current_readport); - else - cdat = inb(current_readport + 1 ); - spin_unlock(&io_lock); - rv = 0; - - if (revision == PCWD_REVISION_A) - { - if (cdat & WD_WDRST) - rv |= WDIOF_CARDRESET; - - if (cdat & WD_T110) - { - rv |= WDIOF_OVERHEAT; - - if (temp_panic) - panic("pcwd: Temperature overheat trip!\n"); - } - } - else - { - if (cdat & 0x01) - rv |= WDIOF_CARDRESET; - - if (cdat & 0x04) - { - rv |= WDIOF_OVERHEAT; - - if (temp_panic) - panic("pcwd: Temperature overheat trip!\n"); - } - } - - if(put_user(rv, (int *) arg)) - return -EFAULT; - return 0; - - case WDIOC_GETBOOTSTATUS: - rv = 0; - - if (revision == PCWD_REVISION_A) - { - if (initial_status & WD_WDRST) - rv |= WDIOF_CARDRESET; - - if (initial_status & WD_T110) - rv |= WDIOF_OVERHEAT; - } - else - { - if (initial_status & 0x01) - rv |= WDIOF_CARDRESET; - - if (initial_status & 0x04) - rv |= WDIOF_OVERHEAT; - } - - if(put_user(rv, (int *) arg)) - return -EFAULT; - return 0; - - case WDIOC_GETTEMP: - - rv = 0; - if ((supports_temp) && (mode_debug == 0)) - { - spin_lock(&io_lock); - rv = inb(current_readport); - spin_unlock(&io_lock); - if(put_user(rv, (int*) arg)) - return -EFAULT; - } else if(put_user(rv, (int*) arg)) - return -EFAULT; - return 0; - - case WDIOC_SETOPTIONS: - if (revision == PCWD_REVISION_C) - { - if(copy_from_user(&rv, (int*) arg, sizeof(int))) - return -EFAULT; - - if (rv & WDIOS_DISABLECARD) - { - spin_lock(&io_lock); - outb_p(0xA5, current_readport + 3); - outb_p(0xA5, current_readport + 3); - cdat = inb_p(current_readport + 2); - spin_unlock(&io_lock); - if ((cdat & 0x10) == 0) - { - printk("pcwd: Could not disable card.\n"); - return -EIO; - } - - return 0; - } - - if (rv & WDIOS_ENABLECARD) - { - spin_lock(&io_lock); - outb_p(0x00, current_readport + 3); - cdat = inb_p(current_readport + 2); - spin_unlock(&io_lock); - if (cdat & 0x10) - { - printk("pcwd: Could not enable card.\n"); - return -EIO; - } - return 0; - } - - if (rv & WDIOS_TEMPPANIC) - { - temp_panic = 1; - } - } - return -EINVAL; - - case WDIOC_KEEPALIVE: - pcwd_send_heartbeat(); - return 0; - } - - return 0; -} - -static ssize_t pcwd_write(struct file *file, const char *buf, size_t len, - loff_t *ppos) -{ - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - - if (len) - { - pcwd_send_heartbeat(); - return 1; - } - return 0; -} - -static int pcwd_open(struct inode *ino, struct file *filep) -{ - switch (minor(ino->i_rdev)) - { - case WATCHDOG_MINOR: - if ( !atomic_dec_and_test(&open_allowed) ) - { - atomic_inc( &open_allowed ); - return -EBUSY; - } - MOD_INC_USE_COUNT; - /* Enable the port */ - if (revision == PCWD_REVISION_C) - { - spin_lock(&io_lock); - outb_p(0x00, current_readport + 3); - spin_unlock(&io_lock); - } - return(0); - case TEMP_MINOR: - return(0); - default: - return (-ENODEV); - } -} - -static ssize_t pcwd_read(struct file *file, char *buf, size_t count, - loff_t *ppos) -{ - unsigned short c; - unsigned char cp; - - /* Can't seek (pread) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - switch(minor(file->f_dentry->d_inode->i_rdev)) - { - case TEMP_MINOR: - /* - * Convert metric to Fahrenheit, since this was - * the decided 'standard' for this return value. - */ - - c = inb(current_readport); - cp = (c * 9 / 5) + 32; - if(copy_to_user(buf, &cp, 1)) - return -EFAULT; - return 1; - default: - return -EINVAL; - } -} - -static int pcwd_close(struct inode *ino, struct file *filep) -{ - if (minor(ino->i_rdev)==WATCHDOG_MINOR) - { -#ifndef CONFIG_WATCHDOG_NOWAYOUT - /* Disable the board */ - if (revision == PCWD_REVISION_C) { - spin_lock(&io_lock); - outb_p(0xA5, current_readport + 3); - outb_p(0xA5, current_readport + 3); - spin_unlock(&io_lock); - } - atomic_inc( &open_allowed ); -#endif - } - return 0; -} - -static inline void get_support(void) -{ - if (inb(current_readport) != 0xF0) - supports_temp = 1; -} - -static inline int get_revision(void) -{ - int r = PCWD_REVISION_C; - - spin_lock(&io_lock); - if ((inb(current_readport + 2) == 0xFF) || - (inb(current_readport + 3) == 0xFF)) - r=PCWD_REVISION_A; - spin_unlock(&io_lock); - - return r; -} - -static int __init send_command(int cmd) -{ - int i; - - outb_p(cmd, current_readport + 2); - mdelay(1); - - i = inb(current_readport); - i = inb(current_readport); - - return(i); -} - -static inline char *get_firmware(void) -{ - int i, found = 0, count = 0, one, ten, hund, minor; - char *ret; - - ret = kmalloc(6, GFP_KERNEL); - if(ret == NULL) - return NULL; - - while((count < 3) && (!found)) { - outb_p(0x80, current_readport + 2); - i = inb(current_readport); - - if (i == 0x00) - found = 1; - else if (i == 0xF3) - outb_p(0x00, current_readport + 2); - - udelay(400L); - count++; - } - - if (found) { - mode_debug = 1; - - one = send_command(0x81); - ten = send_command(0x82); - hund = send_command(0x83); - minor = send_command(0x84); - sprintf(ret, "%c.%c%c%c", one, ten, hund, minor); - } - else - sprintf(ret, "ERROR"); - - return(ret); -} - -static void debug_off(void) -{ - outb_p(0x00, current_readport + 2); - mode_debug = 0; -} - -static struct file_operations pcwd_fops = { - .owner = THIS_MODULE, - .read = pcwd_read, - .write = pcwd_write, - .ioctl = pcwd_ioctl, - .open = pcwd_open, - .release = pcwd_close, -}; - -static struct miscdevice pcwd_miscdev = { - WATCHDOG_MINOR, - "watchdog", - &pcwd_fops -}; - -static struct miscdevice temp_miscdev = { - TEMP_MINOR, - "temperature", - &pcwd_fops -}; - -static int __init pcwatchdog_init(void) -{ - int i, found = 0; - spin_lock_init(&io_lock); - - revision = PCWD_REVISION_A; - - printk("pcwd: v%s Ken Hollis (kenji@bitgate.com)\n", WD_VER); - - /* Initial variables */ - supports_temp = 0; - mode_debug = 0; - temp_panic = 0; - initial_status = 0x0000; - -#ifndef PCWD_BLIND - for (i = 0; pcwd_ioports[i] != 0; i++) { - current_readport = pcwd_ioports[i]; - - if (pcwd_checkcard()) { - found = 1; - break; - } - } - - if (!found) { - printk("pcwd: No card detected, or port not available.\n"); - return(-EIO); - } -#endif - -#ifdef PCWD_BLIND - current_readport = PCWD_BLIND; -#endif - - get_support(); - revision = get_revision(); - - if (revision == PCWD_REVISION_A) - printk("pcwd: PC Watchdog (REV.A) detected at port 0x%03x\n", current_readport); - else if (revision == PCWD_REVISION_C) - printk("pcwd: PC Watchdog (REV.C) detected at port 0x%03x (Firmware version: %s)\n", - current_readport, get_firmware()); - else { - /* Should NEVER happen, unless get_revision() fails. */ - printk("pcwd: Unable to get revision.\n"); - return -1; - } - - if (supports_temp) - printk("pcwd: Temperature Option Detected.\n"); - - debug_off(); - - pcwd_showprevstate(); - - /* Disable the board */ - if (revision == PCWD_REVISION_C) { - outb_p(0xA5, current_readport + 3); - outb_p(0xA5, current_readport + 3); - } - - if (misc_register(&pcwd_miscdev)) - return -ENODEV; - - if (supports_temp) - if (misc_register(&temp_miscdev)) { - misc_deregister(&pcwd_miscdev); - return -ENODEV; - } - - - if (revision == PCWD_REVISION_A) { - if (!request_region(current_readport, 2, "PCWD Rev.A (Berkshire)")) { - misc_deregister(&pcwd_miscdev); - if (supports_temp) - misc_deregister(&pcwd_miscdev); - return -EIO; - } - } - else - if (!request_region(current_readport, 4, "PCWD Rev.C (Berkshire)")) { - misc_deregister(&pcwd_miscdev); - if (supports_temp) - misc_deregister(&pcwd_miscdev); - return -EIO; - } - - return 0; -} - -static void __exit pcwatchdog_exit(void) -{ - misc_deregister(&pcwd_miscdev); - /* Disable the board */ - if (revision == PCWD_REVISION_C) { - outb_p(0xA5, current_readport + 3); - outb_p(0xA5, current_readport + 3); - } - if (supports_temp) - misc_deregister(&temp_miscdev); - - release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4); -} - -module_init(pcwatchdog_init); -module_exit(pcwatchdog_exit); - -MODULE_LICENSE("GPL"); - diff -Nru a/drivers/char/rtc.c b/drivers/char/rtc.c --- a/drivers/char/rtc.c Fri Nov 22 13:41:19 2002 +++ b/drivers/char/rtc.c Fri Nov 22 13:41:19 2002 @@ -807,8 +807,8 @@ struct linux_ebus *ebus; struct linux_ebus_device *edev; #ifdef __sparc_v9__ - struct isa_bridge *isa_br; - struct isa_device *isa_dev; + struct sparc_isa_bridge *isa_br; + struct sparc_isa_device *isa_dev; #endif #endif diff -Nru a/drivers/char/sbc60xxwdt.c b/drivers/char/sbc60xxwdt.c --- a/drivers/char/sbc60xxwdt.c Fri Nov 22 13:41:21 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,354 +0,0 @@ -/* - * 60xx Single Board Computer Watchdog Timer driver for Linux 2.2.x - * - * Based on acquirewdt.c by Alan Cox. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * The author does NOT admit liability nor provide warranty for - * any of this software. This material is provided "AS-IS" in - * the hope that it may be useful for others. - * - * (c) Copyright 2000 Jakob Oestergaard - * - * 12/4 - 2000 [Initial revision] - * 25/4 - 2000 Added /dev/watchdog support - * 09/5 - 2001 [smj@oro.net] fixed fop_write to "return 1" on success - * - * - * Theory of operation: - * A Watchdog Timer (WDT) is a hardware circuit that can - * reset the computer system in case of a software fault. - * You probably knew that already. - * - * Usually a userspace daemon will notify the kernel WDT driver - * via the /proc/watchdog special device file that userspace is - * still alive, at regular intervals. When such a notification - * occurs, the driver will usually tell the hardware watchdog - * that everything is in order, and that the watchdog should wait - * for yet another little while to reset the system. - * If userspace fails (RAM error, kernel bug, whatever), the - * notifications cease to occur, and the hardware watchdog will - * reset the system (causing a reboot) after the timeout occurs. - * - * This WDT driver is different from the other Linux WDT - * drivers in several ways: - * *) The driver will ping the watchdog by itself, because this - * particular WDT has a very short timeout (one second) and it - * would be insane to count on any userspace daemon always - * getting scheduled within that time frame. - * *) This driver expects the userspace daemon to send a specific - * character code ('V') to /dev/watchdog before closing the - * /dev/watchdog file. If the userspace daemon closes the file - * without sending this special character, the driver will assume - * that the daemon (and userspace in general) died, and will - * stop pinging the WDT without disabling it first. This will - * cause a reboot. - * - * Why `V' ? Well, `V' is the character in ASCII for the value 86, - * and we all know that 86 is _the_ most random number in the universe. - * Therefore it is the letter that has the slightest chance of occuring - * by chance, when the system becomes corrupted. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define OUR_NAME "sbc60xxwdt" - -/* - * You must set these - The driver cannot probe for the settings - */ - -#define WDT_STOP 0x45 -#define WDT_START 0x443 - -/* - * The 60xx board can use watchdog timeout values from one second - * to several minutes. The default is one second, so if we reset - * the watchdog every ~250ms we should be safe. - */ - -#define WDT_INTERVAL (HZ/4+1) - -/* - * We must not require too good response from the userspace daemon. - * Here we require the userspace daemon to send us a heartbeat - * char to /dev/watchdog every 10 seconds. - * If the daemon pulses us every 5 seconds, we can still afford - * a 5 second scheduling delay on the (high priority) daemon. That - * should be sufficient for a box under any load. - */ - -#define WDT_HEARTBEAT (HZ * 10) - -static void wdt_timer_ping(unsigned long); -static struct timer_list timer; -static unsigned long next_heartbeat; -static int wdt_is_open; -static int wdt_expect_close; - -#ifdef CONFIG_WATCHDOG_NOWAYOUT -static int nowayout = 1; -#else -static int nowayout = 0; -#endif - -MODULE_PARM(nowayout,"i"); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); - -/* - * Whack the dog - */ - -static void wdt_timer_ping(unsigned long data) -{ - /* If we got a heartbeat pulse within the WDT_US_INTERVAL - * we agree to ping the WDT - */ - if(time_before(jiffies, next_heartbeat)) - { - /* Ping the WDT by reading from WDT_START */ - inb_p(WDT_START); - /* Re-set the timer interval */ - timer.expires = jiffies + WDT_INTERVAL; - add_timer(&timer); - } else { - printk(OUR_NAME ": Heartbeat lost! Will not ping the watchdog\n"); - } -} - -/* - * Utility routines - */ - -static void wdt_startup(void) -{ - next_heartbeat = jiffies + WDT_HEARTBEAT; - - /* Start the timer */ - timer.expires = jiffies + WDT_INTERVAL; - add_timer(&timer); - printk(OUR_NAME ": Watchdog timer is now enabled.\n"); -} - -static void wdt_turnoff(void) -{ - /* Stop the timer */ - del_timer(&timer); - inb_p(WDT_STOP); - printk(OUR_NAME ": Watchdog timer is now disabled...\n"); -} - - -/* - * /dev/watchdog handling - */ - -static ssize_t fop_write(struct file * file, const char * buf, size_t count, loff_t * ppos) -{ - /* We can't seek */ - if(ppos != &file->f_pos) - return -ESPIPE; - - /* See if we got the magic character */ - if(count) - { - size_t ofs; - - /* note: just in case someone wrote the magic character - * five months ago... */ - wdt_expect_close = 0; - - /* now scan */ - for(ofs = 0; ofs != count; ofs++) - { - char c; - if(get_user(c, buf+ofs)) - return -EFAULT; - if(c == 'V') - wdt_expect_close = 1; - } - /* Well, anyhow someone wrote to us, we should return that favour */ - next_heartbeat = jiffies + WDT_HEARTBEAT; - return 1; - } - return 0; -} - -static ssize_t fop_read(struct file * file, char * buf, size_t count, loff_t * ppos) -{ - /* No can do */ - return -EINVAL; -} - -static int fop_open(struct inode * inode, struct file * file) -{ - switch(minor(inode->i_rdev)) - { - case WATCHDOG_MINOR: - /* Just in case we're already talking to someone... */ - if(wdt_is_open) - return -EBUSY; - if (nowayout) { - MOD_INC_USE_COUNT; - } - /* Good, fire up the show */ - wdt_is_open = 1; - wdt_startup(); - return 0; - - default: - return -ENODEV; - } -} - -static int fop_close(struct inode * inode, struct file * file) -{ - if(minor(inode->i_rdev) == WATCHDOG_MINOR) - { - if(wdt_expect_close && !nowayout) - wdt_turnoff(); - else { - del_timer(&timer); - printk(OUR_NAME ": device file closed unexpectedly. Will not stop the WDT!\n"); - } - } - wdt_is_open = 0; - return 0; -} - -static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) -{ - static struct watchdog_info ident= - { - 0, - 1, - "SB60xx" - }; - - switch(cmd) - { - default: - return -ENOTTY; - case WDIOC_GETSUPPORT: - return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0; - case WDIOC_KEEPALIVE: - next_heartbeat = jiffies + WDT_HEARTBEAT; - return 0; - } -} - -static struct file_operations wdt_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = fop_read, - .write = fop_write, - .open = fop_open, - .release = fop_close, - .ioctl = fop_ioctl -}; - -static struct miscdevice wdt_miscdev = { - WATCHDOG_MINOR, - "watchdog", - &wdt_fops -}; - -/* - * Notifier for system down - */ - -static int wdt_notify_sys(struct notifier_block *this, unsigned long code, - void *unused) -{ - if(code==SYS_DOWN || code==SYS_HALT) - wdt_turnoff(); - return NOTIFY_DONE; -} - -/* - * The WDT needs to learn about soft shutdowns in order to - * turn the timebomb registers off. - */ - -static struct notifier_block wdt_notifier= -{ - wdt_notify_sys, - 0, - 0 -}; - -static void __exit sbc60xxwdt_unload(void) -{ - wdt_turnoff(); - - /* Deregister */ - misc_deregister(&wdt_miscdev); - - unregister_reboot_notifier(&wdt_notifier); - release_region(WDT_START,1); - release_region(WDT_STOP,1); -} - -static int __init sbc60xxwdt_init(void) -{ - int rc = -EBUSY; - - if (!request_region(WDT_STOP, 1, "SBC 60XX WDT")) - goto err_out; - if (!request_region(WDT_START, 1, "SBC 60XX WDT")) - goto err_out_region1; - - init_timer(&timer); - timer.function = wdt_timer_ping; - timer.data = 0; - - rc = misc_register(&wdt_miscdev); - if (rc) - goto err_out_region2; - - rc = register_reboot_notifier(&wdt_notifier); - if (rc) - goto err_out_miscdev; - - printk(KERN_INFO OUR_NAME ": WDT driver for 60XX single board computer initialised.\n"); - - return 0; - -err_out_miscdev: - misc_deregister(&wdt_miscdev); -err_out_region2: - release_region(WDT_START,1); -err_out_region1: - release_region(WDT_STOP,1); -err_out: - return rc; -} - -module_init(sbc60xxwdt_init); -module_exit(sbc60xxwdt_unload); - -MODULE_LICENSE("GPL"); diff -Nru a/drivers/char/scx200_wdt.c b/drivers/char/scx200_wdt.c --- a/drivers/char/scx200_wdt.c Fri Nov 22 13:41:21 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,277 +0,0 @@ -/* linux/drivers/char/scx200_wdt.c - - National Semiconductor SCx200 Watchdog support - - Copyright (c) 2001,2002 Christer Weinigel - - Som code taken from: - National Semiconductor PC87307/PC97307 (ala SC1200) WDT driver - (c) Copyright 2002 Zwane Mwaikambo - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The author(s) of this software shall not be held liable for damages - of any nature resulting due to the use of this software. This - software is provided AS-IS with no warranties. */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define NAME "scx200_wdt" - -MODULE_AUTHOR("Christer Weinigel "); -MODULE_DESCRIPTION("NatSemi SCx200 Watchdog Driver"); -MODULE_LICENSE("GPL"); - -#ifndef CONFIG_WATCHDOG_NOWAYOUT -#define CONFIG_WATCHDOG_NOWAYOUT 0 -#endif - -static int margin = 60; /* in seconds */ -MODULE_PARM(margin, "i"); -MODULE_PARM_DESC(margin, "Watchdog margin in seconds"); - -static int nowayout = CONFIG_WATCHDOG_NOWAYOUT; -MODULE_PARM(nowayout, "i"); -MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); - -static u16 wdto_restart; -static struct semaphore open_semaphore; -static unsigned expect_close; - -/* Bits of the WDCNFG register */ -#define W_ENABLE 0x00fa /* Enable watchdog */ -#define W_DISABLE 0x0000 /* Disable watchdog */ - -/* The scaling factor for the timer, this depends on the value of W_ENABLE */ -#define W_SCALE (32768/1024) - -static void scx200_wdt_ping(void) -{ - outw(wdto_restart, SCx200_CB_BASE + SCx200_WDT_WDTO); -} - -static void scx200_wdt_update_margin(void) -{ - printk(KERN_INFO NAME ": timer margin %d seconds\n", margin); - wdto_restart = margin * W_SCALE; -} - -static void scx200_wdt_enable(void) -{ - printk(KERN_DEBUG NAME ": enabling watchdog timer, wdto_restart = %d\n", - wdto_restart); - - outw(0, SCx200_CB_BASE + SCx200_WDT_WDTO); - outb(SCx200_WDT_WDSTS_WDOVF, SCx200_CB_BASE + SCx200_WDT_WDSTS); - outw(W_ENABLE, SCx200_CB_BASE + SCx200_WDT_WDCNFG); - - scx200_wdt_ping(); -} - -static void scx200_wdt_disable(void) -{ - printk(KERN_DEBUG NAME ": disabling watchdog timer\n"); - - outw(0, SCx200_CB_BASE + SCx200_WDT_WDTO); - outb(SCx200_WDT_WDSTS_WDOVF, SCx200_CB_BASE + SCx200_WDT_WDSTS); - outw(W_DISABLE, SCx200_CB_BASE + SCx200_WDT_WDCNFG); -} - -static int scx200_wdt_open(struct inode *inode, struct file *file) -{ - /* only allow one at a time */ - if (down_trylock(&open_semaphore)) - return -EBUSY; - scx200_wdt_enable(); - expect_close = 0; - - return 0; -} - -static int scx200_wdt_release(struct inode *inode, struct file *file) -{ - if (!expect_close) { - printk(KERN_WARNING NAME ": watchdog device closed unexpectedly, will not disable the watchdog timer\n"); - } else if (!nowayout) { - scx200_wdt_disable(); - } - up(&open_semaphore); - - return 0; -} - -static int scx200_wdt_notify_sys(struct notifier_block *this, - unsigned long code, void *unused) -{ - if (code == SYS_HALT || code == SYS_POWER_OFF) - if (!nowayout) - scx200_wdt_disable(); - - return NOTIFY_DONE; -} - -static struct notifier_block scx200_wdt_notifier = -{ - .notifier_call = scx200_wdt_notify_sys -}; - -static ssize_t scx200_wdt_write(struct file *file, const char *data, - size_t len, loff_t *ppos) -{ - if (ppos != &file->f_pos) - return -ESPIPE; - - /* check for a magic close character */ - if (len) - { - size_t i; - - scx200_wdt_ping(); - - expect_close = 0; - for (i = 0; i < len; ++i) { - char c; - if (get_user(c, data+i)) - return -EFAULT; - if (c == 'V') - expect_close = 1; - } - - return len; - } - - return 0; -} - -static int scx200_wdt_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - static struct watchdog_info ident = { - .identity = "NatSemi SCx200 Watchdog", - .firmware_version = 1, - .options = (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING), - }; - int new_margin; - - switch (cmd) { - default: - return -ENOTTY; - case WDIOC_GETSUPPORT: - if(copy_to_user((struct watchdog_info *)arg, &ident, - sizeof(ident))) - return -EFAULT; - return 0; - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - if (put_user(0, (int *)arg)) - return -EFAULT; - return 0; - case WDIOC_KEEPALIVE: - scx200_wdt_ping(); - return 0; - case WDIOC_SETTIMEOUT: - if (get_user(new_margin, (int *)arg)) - return -EFAULT; - if (new_margin < 1) - return -EINVAL; - margin = new_margin; - scx200_wdt_update_margin(); - scx200_wdt_ping(); - case WDIOC_GETTIMEOUT: - if (put_user(margin, (int *)arg)) - return -EFAULT; - return 0; - } -} - -static struct file_operations scx200_wdt_fops = { - .owner = THIS_MODULE, - .write = scx200_wdt_write, - .ioctl = scx200_wdt_ioctl, - .open = scx200_wdt_open, - .release = scx200_wdt_release, -}; - -static struct miscdevice scx200_wdt_miscdev = { - .minor = WATCHDOG_MINOR, - .name = NAME, - .fops = &scx200_wdt_fops, -}; - -static int __init scx200_wdt_init(void) -{ - int r; - - printk(KERN_DEBUG NAME ": NatSemi SCx200 Watchdog Driver\n"); - - /* First check that this really is a NatSemi SCx200 CPU */ - if ((pci_find_device(PCI_VENDOR_ID_NS, - PCI_DEVICE_ID_NS_SCx200_BRIDGE, - NULL)) == NULL) - return -ENODEV; - - /* More sanity checks, verify that the configuration block is there */ - if (!scx200_cb_probe(SCx200_CB_BASE)) { - printk(KERN_WARNING NAME ": no configuration block found\n"); - return -ENODEV; - } - - if (!request_region(SCx200_CB_BASE + SCx200_WDT_OFFSET, - SCx200_WDT_SIZE, - "NatSemi SCx200 Watchdog")) { - printk(KERN_WARNING NAME ": watchdog I/O region busy\n"); - return -EBUSY; - } - - scx200_wdt_update_margin(); - scx200_wdt_disable(); - - sema_init(&open_semaphore, 1); - - r = misc_register(&scx200_wdt_miscdev); - if (r) - return r; - - r = register_reboot_notifier(&scx200_wdt_notifier); - if (r) { - printk(KERN_ERR NAME ": unable to register reboot notifier"); - misc_deregister(&scx200_wdt_miscdev); - return r; - } - - return 0; -} - -static void __exit scx200_wdt_cleanup(void) -{ - unregister_reboot_notifier(&scx200_wdt_notifier); - misc_deregister(&scx200_wdt_miscdev); - release_region(SCx200_CB_BASE + SCx200_WDT_OFFSET, - SCx200_WDT_SIZE); -} - -module_init(scx200_wdt_init); -module_exit(scx200_wdt_cleanup); - -/* - Local variables: - compile-command: "make -k -C ../.. SUBDIRS=drivers/char modules" - c-basic-offset: 8 - End: -*/ diff -Nru a/drivers/char/shwdt.c b/drivers/char/shwdt.c --- a/drivers/char/shwdt.c Fri Nov 22 13:41:18 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,417 +0,0 @@ -/* - * drivers/char/shwdt.c - * - * Watchdog driver for integrated watchdog in the SuperH 3/4 processors. - * - * Copyright (C) 2001 Paul Mundt - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * 14-Dec-2001 Matt Domsch - * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#if defined(CONFIG_CPU_SH4) - #define WTCNT 0xffc00008 - #define WTCSR 0xffc0000c -#elif defined(CONFIG_CPU_SH3) - #define WTCNT 0xffffff84 - #define WTCSR 0xffffff86 -#else - #error "Can't use SH 3/4 watchdog on non-SH 3/4 processor." -#endif - -#define WTCNT_HIGH 0x5a00 -#define WTCSR_HIGH 0xa500 - -#define WTCSR_TME 0x80 -#define WTCSR_WT 0x40 -#define WTCSR_RSTS 0x20 -#define WTCSR_WOVF 0x10 -#define WTCSR_IOVF 0x08 -#define WTCSR_CKS2 0x04 -#define WTCSR_CKS1 0x02 -#define WTCSR_CKS0 0x01 - -/* - * CKS0-2 supports a number of clock division ratios. At the time the watchdog - * is enabled, it defaults to a 41 usec overflow period .. we overload this to - * something a little more reasonable, and really can't deal with anything - * lower than WTCSR_CKS_1024, else we drop back into the usec range. - * - * Clock Division Ratio Overflow Period - * -------------------------------------------- - * 1/32 (initial value) 41 usecs - * 1/64 82 usecs - * 1/128 164 usecs - * 1/256 328 usecs - * 1/512 656 usecs - * 1/1024 1.31 msecs - * 1/2048 2.62 msecs - * 1/4096 5.25 msecs - */ -#define WTCSR_CKS_32 0x00 -#define WTCSR_CKS_64 0x01 -#define WTCSR_CKS_128 0x02 -#define WTCSR_CKS_256 0x03 -#define WTCSR_CKS_512 0x04 -#define WTCSR_CKS_1024 0x05 -#define WTCSR_CKS_2048 0x06 -#define WTCSR_CKS_4096 0x07 - -/* - * Default clock division ratio is 5.25 msecs. Overload this at module load - * time. Any value not in the msec range will default to a timeout of one - * jiffy, which exceeds the usec overflow periods. - */ -static int clock_division_ratio = WTCSR_CKS_4096; - -#define msecs_to_jiffies(msecs) (jiffies + ((HZ * msecs + 999) / 1000)) -#define next_ping_period(cks) msecs_to_jiffies(cks - 4) -#define user_ping_period(cks) (next_ping_period(cks) * 10) - -static unsigned long sh_is_open = 0; -static struct watchdog_info sh_wdt_info; -static struct timer_list timer; -static unsigned long next_heartbeat; - -#ifdef CONFIG_WATCHDOG_NOWAYOUT -static int nowayout = 1; -#else -static int nowayout = 0; -#endif - -MODULE_PARM(nowayout,"i"); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); - -/** - * sh_wdt_write_cnt - Write to Counter - * - * @val: Value to write - * - * Writes the given value @val to the lower byte of the timer counter. - * The upper byte is set manually on each write. - */ -static void sh_wdt_write_cnt(__u8 val) -{ - ctrl_outw(WTCNT_HIGH | (__u16)val, WTCNT); -} - -/** - * sh_wdt_write_csr - Write to Control/Status Register - * - * @val: Value to write - * - * Writes the given value @val to the lower byte of the control/status - * register. The upper byte is set manually on each write. - */ -static void sh_wdt_write_csr(__u8 val) -{ - ctrl_outw(WTCSR_HIGH | (__u16)val, WTCSR); -} - -/** - * sh_wdt_start - Start the Watchdog - * - * Starts the watchdog. - */ -static void sh_wdt_start(void) -{ - timer.expires = next_ping_period(clock_division_ratio); - next_heartbeat = user_ping_period(clock_division_ratio); - add_timer(&timer); - - sh_wdt_write_csr(WTCSR_WT | WTCSR_CKS_4096); - sh_wdt_write_cnt(0); - sh_wdt_write_csr((ctrl_inb(WTCSR) | WTCSR_TME)); -} - -/** - * sh_wdt_stop - Stop the Watchdog - * - * Stops the watchdog. - */ -static void sh_wdt_stop(void) -{ - del_timer(&timer); - - sh_wdt_write_csr((ctrl_inb(WTCSR) & ~WTCSR_TME)); -} - -/** - * sh_wdt_ping - Ping the Watchdog - * - * @data: Unused - * - * Clears overflow bit, resets timer counter. - */ -static void sh_wdt_ping(unsigned long data) -{ - if (time_before(jiffies, next_heartbeat)) { - sh_wdt_write_csr((ctrl_inb(WTCSR) & ~WTCSR_IOVF)); - sh_wdt_write_cnt(0); - - timer.expires = next_ping_period(clock_division_ratio); - add_timer(&timer); - } -} - -/** - * sh_wdt_open - Open the Device - * - * @inode: inode of device - * @file: file handle of device - * - * Watchdog device is opened and started. - */ -static int sh_wdt_open(struct inode *inode, struct file *file) -{ - switch (minor(inode->i_rdev)) { - case WATCHDOG_MINOR: - if (test_and_set_bit(0, &sh_is_open)) - return -EBUSY; - - if (nowayout) { - MOD_INC_USE_COUNT; - } - - sh_wdt_start(); - - break; - default: - return -ENODEV; - } - - return 0; -} - -/** - * sh_wdt_close - Close the Device - * - * @inode: inode of device - * @file: file handle of device - * - * Watchdog device is closed and stopped. - */ -static int sh_wdt_close(struct inode *inode, struct file *file) -{ - if (minor(inode->i_rdev) == WATCHDOG_MINOR) { - if (!nowayout) { - sh_wdt_stop(); - } - clear_bit(0, &sh_is_open); - } - - return 0; -} - -/** - * sh_wdt_read - Read from Device - * - * @file: file handle of device - * @buf: buffer to write to - * @count: length of buffer - * @ppos: offset - * - * Unsupported. - */ -static ssize_t sh_wdt_read(struct file *file, char *buf, - size_t count, loff_t *ppos) -{ - return -EINVAL; -} - -/** - * sh_wdt_write - Write to Device - * - * @file: file handle of device - * @buf: buffer to write - * @count: length of buffer - * @ppos: offset - * - * Pings the watchdog on write. - */ -static ssize_t sh_wdt_write(struct file *file, const char *buf, - size_t count, loff_t *ppos) -{ - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - - if (count) { - next_heartbeat = user_ping_period(clock_division_ratio); - return 1; - } - - return 0; -} - -/** - * sh_wdt_ioctl - Query Device - * - * @inode: inode of device - * @file: file handle of device - * @cmd: watchdog command - * @arg: argument - * - * Query basic information from the device or ping it, as outlined by the - * watchdog API. - */ -static int sh_wdt_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case WDIOC_GETSUPPORT: - if (copy_to_user((struct watchdog_info *)arg, - &sh_wdt_info, - sizeof(sh_wdt_info))) { - return -EFAULT; - } - - break; - case WDIOC_GETSTATUS: - if (copy_to_user((int *)arg, - &sh_is_open, - sizeof(int))) { - return -EFAULT; - } - - break; - case WDIOC_KEEPALIVE: - next_heartbeat = user_ping_period(clock_division_ratio); - - break; - default: - return -ENOTTY; - } - - return 0; -} - -/** - * sh_wdt_notify_sys - Notifier Handler - * - * @this: notifier block - * @code: notifier event - * @unused: unused - * - * Handles specific events, such as turning off the watchdog during a - * shutdown event. - */ -static int sh_wdt_notify_sys(struct notifier_block *this, - unsigned long code, void *unused) -{ - if (code == SYS_DOWN || code == SYS_HALT) { - sh_wdt_stop(); - } - - return NOTIFY_DONE; -} - -static struct file_operations sh_wdt_fops = { - .owner = THIS_MODULE, - .read = sh_wdt_read, - .write = sh_wdt_write, - .ioctl = sh_wdt_ioctl, - .open = sh_wdt_open, - .release = sh_wdt_close, -}; - -static struct watchdog_info sh_wdt_info = { - WDIOF_KEEPALIVEPING, - 1, - "SH WDT", -}; - -static struct notifier_block sh_wdt_notifier = { - sh_wdt_notify_sys, - NULL, - 0 -}; - -static struct miscdevice sh_wdt_miscdev = { - WATCHDOG_MINOR, - "watchdog", - &sh_wdt_fops, -}; - -/** - * sh_wdt_init - Initialize module - * - * Registers the device and notifier handler. Actual device - * initialization is handled by sh_wdt_open(). - */ -static int __init sh_wdt_init(void) -{ - if (misc_register(&sh_wdt_miscdev)) { - printk(KERN_ERR "shwdt: Can't register misc device\n"); - return -EINVAL; - } - - if (!request_region(WTCNT, 1, "shwdt")) { - printk(KERN_ERR "shwdt: Can't request WTCNT region\n"); - misc_deregister(&sh_wdt_miscdev); - return -ENXIO; - } - - if (!request_region(WTCSR, 1, "shwdt")) { - printk(KERN_ERR "shwdt: Can't request WTCSR region\n"); - release_region(WTCNT, 1); - misc_deregister(&sh_wdt_miscdev); - return -ENXIO; - } - - if (register_reboot_notifier(&sh_wdt_notifier)) { - printk(KERN_ERR "shwdt: Can't register reboot notifier\n"); - release_region(WTCSR, 1); - release_region(WTCNT, 1); - misc_deregister(&sh_wdt_miscdev); - return -EINVAL; - } - - init_timer(&timer); - timer.function = sh_wdt_ping; - timer.data = 0; - - return 0; -} - -/** - * sh_wdt_exit - Deinitialize module - * - * Unregisters the device and notifier handler. Actual device - * deinitialization is handled by sh_wdt_close(). - */ -static void __exit sh_wdt_exit(void) -{ - unregister_reboot_notifier(&sh_wdt_notifier); - release_region(WTCSR, 1); - release_region(WTCNT, 1); - misc_deregister(&sh_wdt_miscdev); -} - -MODULE_AUTHOR("Paul Mundt "); -MODULE_DESCRIPTION("SH 3/4 watchdog driver"); -MODULE_LICENSE("GPL"); -MODULE_PARM(clock_division_ratio, "i"); -MODULE_PARM_DESC(clock_division_ratio, "Clock division ratio. Valid ranges are from 0x5 (1.31ms) to 0x7 (5.25ms). Defaults to 0x7."); - -module_init(sh_wdt_init); -module_exit(sh_wdt_exit); - diff -Nru a/drivers/char/softdog.c b/drivers/char/softdog.c --- a/drivers/char/softdog.c Fri Nov 22 13:41:19 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,196 +0,0 @@ -/* - * SoftDog 0.06: A Software Watchdog Device - * - * (c) Copyright 1996 Alan Cox , All Rights Reserved. - * http://www.redhat.com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide - * warranty for any of this software. This material is provided - * "AS-IS" and at no charge. - * - * (c) Copyright 1995 Alan Cox - * - * Software only watchdog driver. Unlike its big brother the WDT501P - * driver this won't always recover a failed machine. - * - * 03/96: Angelo Haritsis : - * Modularised. - * Added soft_margin; use upon insmod to change the timer delay. - * NB: uses same minor as wdt (WATCHDOG_MINOR); we could use separate - * minors. - * - * 19980911 Alan Cox - * Made SMP safe for 2.3.x - * - * 20011214 Matt Domsch - * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT - * Didn't add timeout option, as soft_margin option already exists. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define TIMER_MARGIN 60 /* (secs) Default is 1 minute */ - -static int soft_margin = TIMER_MARGIN; /* in seconds */ - -MODULE_PARM(soft_margin,"i"); - -#ifdef CONFIG_WATCHDOG_NOWAYOUT -static int nowayout = 1; -#else -static int nowayout = 0; -#endif - -MODULE_PARM(nowayout,"i"); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); -MODULE_LICENSE("GPL"); - -/* - * Our timer - */ - -static void watchdog_fire(unsigned long); - -static struct timer_list watchdog_ticktock = - TIMER_INITIALIZER(watchdog_fire, 0, 0); -static int timer_alive; - - -/* - * If the timer expires.. - */ - -static void watchdog_fire(unsigned long data) -{ -#ifdef ONLY_TESTING - printk(KERN_CRIT "SOFTDOG: Would Reboot.\n"); -#else - printk(KERN_CRIT "SOFTDOG: Initiating system reboot.\n"); - machine_restart(NULL); - printk("WATCHDOG: Reboot didn't ?????\n"); -#endif -} - -/* - * Allow only one person to hold it open - */ - -static int softdog_open(struct inode *inode, struct file *file) -{ - if(timer_alive) - return -EBUSY; - if (nowayout) { - MOD_INC_USE_COUNT; - } - /* - * Activate timer - */ - mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ)); - timer_alive=1; - return 0; -} - -static int softdog_release(struct inode *inode, struct file *file) -{ - /* - * Shut off the timer. - * Lock it in if it's a module and we set nowayout - */ - if(!nowayout) { - del_timer(&watchdog_ticktock); - } - timer_alive=0; - return 0; -} - -static ssize_t softdog_write(struct file *file, const char *data, size_t len, loff_t *ppos) -{ - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - - /* - * Refresh the timer. - */ - if(len) { - mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ)); - return 1; - } - return 0; -} - -static int softdog_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - static struct watchdog_info ident = { - identity: "Software Watchdog", - }; - switch (cmd) { - default: - return -ENOTTY; - case WDIOC_GETSUPPORT: - if(copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))) - return -EFAULT; - return 0; - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - return put_user(0,(int *)arg); - case WDIOC_KEEPALIVE: - mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ)); - return 0; - } -} - -static struct file_operations softdog_fops = { - owner: THIS_MODULE, - write: softdog_write, - ioctl: softdog_ioctl, - open: softdog_open, - release: softdog_release, -}; - -static struct miscdevice softdog_miscdev = { - minor: WATCHDOG_MINOR, - name: "watchdog", - fops: &softdog_fops, -}; - -static char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.06, soft_margin: %d sec, nowayout: %d\n"; - -static int __init watchdog_init(void) -{ - int ret; - - ret = misc_register(&softdog_miscdev); - - if (ret) - return ret; - - printk(banner, soft_margin, nowayout); - - return 0; -} - -static void __exit watchdog_exit(void) -{ - misc_deregister(&softdog_miscdev); -} - -module_init(watchdog_init); -module_exit(watchdog_exit); diff -Nru a/drivers/char/sonypi.c b/drivers/char/sonypi.c --- a/drivers/char/sonypi.c Fri Nov 22 13:41:22 2002 +++ b/drivers/char/sonypi.c Fri Nov 22 13:41:22 2002 @@ -1,7 +1,9 @@ /* * Sony Programmable I/O Control Device driver for VAIO * - * Copyright (C) 2001 Stelian Pop , Alcôve + * Copyright (C) 2001-2002 Stelian Pop + * + * Copyright (C) 2001-2002 Alcôve * * Copyright (C) 2001 Michael Ashley * @@ -39,6 +41,7 @@ #include #include #include +#include #include #include @@ -53,7 +56,7 @@ static int fnkeyinit; /* = 0 */ static int camera; /* = 0 */ static int compat; /* = 0 */ -static int nojogdial; /* = 0 */ +static unsigned long mask = 0xffffffff; /* Inits the queue */ static inline void sonypi_initq(void) { @@ -113,29 +116,14 @@ return result; } -static void sonypi_ecrset(u8 addr, u8 value) { - - wait_on_command(1, inb_p(SONYPI_CST_IOPORT) & 3); - outb_p(0x81, SONYPI_CST_IOPORT); - wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2); - outb_p(addr, SONYPI_DATA_IOPORT); - wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2); - outb_p(value, SONYPI_DATA_IOPORT); - wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2); -} - -static u8 sonypi_ecrget(u8 addr) { - - wait_on_command(1, inb_p(SONYPI_CST_IOPORT) & 3); - outb_p(0x80, SONYPI_CST_IOPORT); - wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2); - outb_p(addr, SONYPI_DATA_IOPORT); - wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2); - return inb_p(SONYPI_DATA_IOPORT); -} - -static u16 sonypi_ecrget16(u8 addr) { - return sonypi_ecrget(addr) | (sonypi_ecrget(addr + 1) << 8); +static int ec_read16(u8 addr, u16 *value) { + u8 val_lb, val_hb; + if (ec_read(addr, &val_lb)) + return -1; + if (ec_read(addr + 1, &val_hb)) + return -1; + *value = val_lb | (val_hb << 8); + return 0; } /* Initializes the device - this comes from the AML code in the ACPI bios */ @@ -162,9 +150,12 @@ } static void __devinit sonypi_type2_srs(void) { - sonypi_ecrset(SONYPI_SHIB, (sonypi_device.ioport1 & 0xFF00) >> 8); - sonypi_ecrset(SONYPI_SLOB, sonypi_device.ioport1 & 0x00FF); - sonypi_ecrset(SONYPI_SIRQ, sonypi_device.bits); + if (ec_write(SONYPI_SHIB, (sonypi_device.ioport1 & 0xFF00) >> 8)) + printk(KERN_WARNING "ec_write failed\n"); + if (ec_write(SONYPI_SLOB, sonypi_device.ioport1 & 0x00FF)) + printk(KERN_WARNING "ec_write failed\n"); + if (ec_write(SONYPI_SIRQ, sonypi_device.bits)) + printk(KERN_WARNING "ec_write failed\n"); udelay(10); } @@ -182,15 +173,18 @@ } static void __devexit sonypi_type2_dis(void) { - sonypi_ecrset(SONYPI_SHIB, 0); - sonypi_ecrset(SONYPI_SLOB, 0); - sonypi_ecrset(SONYPI_SIRQ, 0); + if (ec_write(SONYPI_SHIB, 0)) + printk(KERN_WARNING "ec_write failed\n"); + if (ec_write(SONYPI_SLOB, 0)) + printk(KERN_WARNING "ec_write failed\n"); + if (ec_write(SONYPI_SIRQ, 0)) + printk(KERN_WARNING "ec_write failed\n"); } static u8 sonypi_call1(u8 dev) { u8 v1, v2; - wait_on_command(0, inb_p(sonypi_device.ioport2) & 2); + wait_on_command(0, inb_p(sonypi_device.ioport2) & 2, ITERATIONS_LONG); outb(dev, sonypi_device.ioport2); v1 = inb_p(sonypi_device.ioport2); v2 = inb_p(sonypi_device.ioport1); @@ -200,9 +194,9 @@ static u8 sonypi_call2(u8 dev, u8 fn) { u8 v1; - wait_on_command(0, inb_p(sonypi_device.ioport2) & 2); + wait_on_command(0, inb_p(sonypi_device.ioport2) & 2, ITERATIONS_LONG); outb(dev, sonypi_device.ioport2); - wait_on_command(0, inb_p(sonypi_device.ioport2) & 2); + wait_on_command(0, inb_p(sonypi_device.ioport2) & 2, ITERATIONS_LONG); outb(fn, sonypi_device.ioport1); v1 = inb_p(sonypi_device.ioport1); return v1; @@ -211,11 +205,11 @@ static u8 sonypi_call3(u8 dev, u8 fn, u8 v) { u8 v1; - wait_on_command(0, inb_p(sonypi_device.ioport2) & 2); + wait_on_command(0, inb_p(sonypi_device.ioport2) & 2, ITERATIONS_LONG); outb(dev, sonypi_device.ioport2); - wait_on_command(0, inb_p(sonypi_device.ioport2) & 2); + wait_on_command(0, inb_p(sonypi_device.ioport2) & 2, ITERATIONS_LONG); outb(fn, sonypi_device.ioport1); - wait_on_command(0, inb_p(sonypi_device.ioport2) & 2); + wait_on_command(0, inb_p(sonypi_device.ioport2) & 2, ITERATIONS_LONG); outb(v, sonypi_device.ioport1); v1 = inb_p(sonypi_device.ioport1); return v1; @@ -237,7 +231,7 @@ /* Set brightness, hue etc */ static void sonypi_set(u8 fn, u8 v) { - wait_on_command(0, sonypi_call3(0x90, fn, v)); + wait_on_command(0, sonypi_call3(0x90, fn, v), ITERATIONS_SHORT); } /* Tests if the camera is ready */ @@ -311,79 +305,30 @@ /* Interrupt handler: some event is available */ void sonypi_irq(int irq, void *dev_id, struct pt_regs *regs) { u8 v1, v2, event = 0; - int i; - u8 sonypi_jogger_ev, sonypi_fnkey_ev; - u8 sonypi_capture_ev, sonypi_bluetooth_ev; - u8 sonypi_pkey_ev; - - if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) { - sonypi_jogger_ev = SONYPI_TYPE2_JOGGER_EV; - sonypi_fnkey_ev = SONYPI_TYPE2_FNKEY_EV; - sonypi_capture_ev = SONYPI_TYPE2_CAPTURE_EV; - sonypi_bluetooth_ev = SONYPI_TYPE2_BLUETOOTH_EV; - sonypi_pkey_ev = nojogdial ? SONYPI_TYPE2_PKEY_EV - : SONYPI_TYPE1_PKEY_EV; - } - else { - sonypi_jogger_ev = SONYPI_TYPE1_JOGGER_EV; - sonypi_fnkey_ev = SONYPI_TYPE1_FNKEY_EV; - sonypi_capture_ev = SONYPI_TYPE1_CAPTURE_EV; - sonypi_bluetooth_ev = SONYPI_TYPE1_BLUETOOTH_EV; - sonypi_pkey_ev = SONYPI_TYPE1_PKEY_EV; - } + int i, j; v1 = inb_p(sonypi_device.ioport1); v2 = inb_p(sonypi_device.ioport2); - if ((v2 & sonypi_pkey_ev) == sonypi_pkey_ev) { - for (i = 0; sonypi_pkeyev[i].event; i++) - if (sonypi_pkeyev[i].data == v1) { - event = sonypi_pkeyev[i].event; - goto found; - } - } - if ((v2 & sonypi_jogger_ev) == sonypi_jogger_ev) { - for (i = 0; sonypi_joggerev[i].event; i++) - if (sonypi_joggerev[i].data == v1) { - event = sonypi_joggerev[i].event; - goto found; - } - } - if ((v2 & sonypi_capture_ev) == sonypi_capture_ev) { - for (i = 0; sonypi_captureev[i].event; i++) - if (sonypi_captureev[i].data == v1) { - event = sonypi_captureev[i].event; - goto found; - } - } - if ((v2 & sonypi_fnkey_ev) == sonypi_fnkey_ev) { - for (i = 0; sonypi_fnkeyev[i].event; i++) - if (sonypi_fnkeyev[i].data == v1) { - event = sonypi_fnkeyev[i].event; - goto found; - } - } - if ((v2 & sonypi_bluetooth_ev) == sonypi_bluetooth_ev) { - for (i = 0; sonypi_blueev[i].event; i++) - if (sonypi_blueev[i].data == v1) { - event = sonypi_blueev[i].event; - goto found; - } - } - if ((v2 & SONYPI_BACK_EV) == SONYPI_BACK_EV) { - for (i = 0; sonypi_backev[i].event; i++) - if (sonypi_backev[i].data == v1) { - event = sonypi_backev[i].event; - goto found; - } - } - if ((v2 & SONYPI_LID_EV) == SONYPI_LID_EV) { - for (i = 0; sonypi_lidev[i].event; i++) - if (sonypi_lidev[i].data == v1) { - event = sonypi_lidev[i].event; + if (verbose > 1) + printk(KERN_INFO + "sonypi: event port1=0x%02x,port2=0x%02x\n", v1, v2); + + for (i = 0; sonypi_eventtypes[i].model; i++) { + if (sonypi_device.model != sonypi_eventtypes[i].model) + continue; + if ((v2 & sonypi_eventtypes[i].data) != sonypi_eventtypes[i].data) + continue; + if (! (mask & sonypi_eventtypes[i].mask)) + continue; + for (j = 0; sonypi_eventtypes[i].events[j].event; j++) { + if (v1 == sonypi_eventtypes[i].events[j].data) { + event = sonypi_eventtypes[i].events[j].event; goto found; } + } } + if (verbose) printk(KERN_WARNING "sonypi: unknown event port1=0x%02x,port2=0x%02x\n",v1,v2); @@ -545,72 +490,77 @@ down(&sonypi_device.lock); switch (cmd) { case SONYPI_IOCGBRT: - val8 = sonypi_ecrget(SONYPI_LCD_LIGHT); - if (copy_to_user((u8 *)arg, &val8, sizeof(val8))) { - ret = -EFAULT; - goto out; + if (ec_read(SONYPI_LCD_LIGHT, &val8)) { + ret = -EIO; + break; } + if (copy_to_user((u8 *)arg, &val8, sizeof(val8))) + ret = -EFAULT; break; case SONYPI_IOCSBRT: if (copy_from_user(&val8, (u8 *)arg, sizeof(val8))) { ret = -EFAULT; - goto out; + break; } - sonypi_ecrset(SONYPI_LCD_LIGHT, val8); + if (ec_write(SONYPI_LCD_LIGHT, val8)) + ret = -EIO; break; case SONYPI_IOCGBAT1CAP: - val16 = sonypi_ecrget16(SONYPI_BAT1_FULL); - if (copy_to_user((u16 *)arg, &val16, sizeof(val16))) { - ret = -EFAULT; - goto out; + if (ec_read16(SONYPI_BAT1_FULL, &val16)) { + ret = -EIO; + break; } + if (copy_to_user((u16 *)arg, &val16, sizeof(val16))) + ret = -EFAULT; break; case SONYPI_IOCGBAT1REM: - val16 = sonypi_ecrget16(SONYPI_BAT1_LEFT); - if (copy_to_user((u16 *)arg, &val16, sizeof(val16))) { - ret = -EFAULT; - goto out; + if (ec_read16(SONYPI_BAT1_FULL, &val16)) { + ret = -EIO; + break; } + if (copy_to_user((u16 *)arg, &val16, sizeof(val16))) + ret = -EFAULT; break; case SONYPI_IOCGBAT2CAP: - val16 = sonypi_ecrget16(SONYPI_BAT2_FULL); - if (copy_to_user((u16 *)arg, &val16, sizeof(val16))) { - ret = -EFAULT; - goto out; + if (ec_read16(SONYPI_BAT1_FULL, &val16)) { + ret = -EIO; + break; } + if (copy_to_user((u16 *)arg, &val16, sizeof(val16))) + ret = -EFAULT; break; case SONYPI_IOCGBAT2REM: - val16 = sonypi_ecrget16(SONYPI_BAT2_LEFT); - if (copy_to_user((u16 *)arg, &val16, sizeof(val16))) { - ret = -EFAULT; - goto out; + if (ec_read16(SONYPI_BAT1_FULL, &val16)) { + ret = -EIO; + break; } + if (copy_to_user((u16 *)arg, &val16, sizeof(val16))) + ret = -EFAULT; break; case SONYPI_IOCGBATFLAGS: - val8 = sonypi_ecrget(SONYPI_BAT_FLAGS) & 0x07; - if (copy_to_user((u8 *)arg, &val8, sizeof(val8))) { - ret = -EFAULT; - goto out; + if (ec_read(SONYPI_BAT_FLAGS, &val8)) { + ret = -EIO; + break; } + val8 &= 0x07; + if (copy_to_user((u8 *)arg, &val8, sizeof(val8))) + ret = -EFAULT; break; case SONYPI_IOCGBLUE: val8 = sonypi_device.bluetooth_power; - if (copy_to_user((u8 *)arg, &val8, sizeof(val8))) { + if (copy_to_user((u8 *)arg, &val8, sizeof(val8))) ret = -EFAULT; - goto out; - } break; case SONYPI_IOCSBLUE: if (copy_from_user(&val8, (u8 *)arg, sizeof(val8))) { ret = -EFAULT; - goto out; + break; } sonypi_setbluetoothpower(val8); break; default: ret = -EINVAL; } -out: up(&sonypi_device.lock); return ret; } @@ -621,7 +571,7 @@ .poll = sonypi_misc_poll, .open = sonypi_misc_open, .release = sonypi_misc_release, - .fasync = sonypi_misc_fasync, + .fasync = sonypi_misc_fasync, .ioctl = sonypi_misc_ioctl, }; @@ -629,6 +579,51 @@ -1, "sonypi", &sonypi_misc_fops }; +#if CONFIG_PM +static int sonypi_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) { + static int old_camera_power; + + switch (rqst) { + case PM_SUSPEND: + sonypi_call2(0x81, 0); /* make sure we don't get any more events */ + if (camera) { + old_camera_power = sonypi_device.camera_power; + sonypi_camera_off(); + } + if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) + sonypi_type2_dis(); + else + sonypi_type1_dis(); +#if !defined(CONFIG_ACPI) + /* disable ACPI mode */ + if (fnkeyinit) + outb(0xf1, 0xb2); +#endif + break; + case PM_RESUME: +#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(); + else + sonypi_type1_srs(); + sonypi_call1(0x82); + sonypi_call2(0x81, 0xff); + if (compat) + sonypi_call1(0x92); + else + sonypi_call1(0x82); + if (camera && old_camera_power) + sonypi_camera_on(); + break; + } + return 0; +} +#endif + static int __devinit sonypi_probe(struct pci_dev *pcidev) { int i, ret; struct sonypi_ioport_list *ioport_list; @@ -720,14 +715,14 @@ SONYPI_DRIVER_MINORVERSION); printk(KERN_INFO "sonypi: detected %s model, " "verbose = %s, fnkeyinit = %s, camera = %s, " - "compat = %s, nojogdial = %s\n", + "compat = %s, mask = 0x%08lx\n", (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) ? "type1" : "type2", verbose ? "on" : "off", fnkeyinit ? "on" : "off", camera ? "on" : "off", compat ? "on" : "off", - nojogdial ? "on" : "off"); + mask); printk(KERN_INFO "sonypi: enabled at irq=%d, port1=0x%x, port2=0x%x\n", sonypi_device.irq, sonypi_device.ioport1, sonypi_device.ioport2); @@ -735,6 +730,10 @@ printk(KERN_INFO "sonypi: device allocated minor is %d\n", sonypi_misc_device.minor); +#if CONFIG_PM + sonypi_device.pm = pm_register(PM_PCI_DEV, 0, sonypi_pm_callback); +#endif + return 0; out3: @@ -746,6 +745,11 @@ } static void __devexit sonypi_remove(void) { + +#if CONFIG_PM + pm_unregister(sonypi_device.pm); +#endif + sonypi_call2(0x81, 0); /* make sure we don't get any more events */ if (camera) sonypi_camera_off(); @@ -803,7 +807,7 @@ compat = ints[5]; if (ints[0] == 5) goto out; - nojogdial = ints[6]; + mask = ints[6]; out: return 1; } @@ -815,7 +819,7 @@ module_init(sonypi_init_module); module_exit(sonypi_cleanup_module); -MODULE_AUTHOR("Stelian Pop "); +MODULE_AUTHOR("Stelian Pop "); MODULE_DESCRIPTION("Sony Programmable I/O Control Device driver"); MODULE_LICENSE("GPL"); @@ -830,7 +834,7 @@ MODULE_PARM_DESC(camera, "set this if you have a MotionEye camera (PictureBook series)"); MODULE_PARM(compat,"i"); MODULE_PARM_DESC(compat, "set this if you want to enable backward compatibility mode"); -MODULE_PARM(nojogdial, "i"); -MODULE_PARM_DESC(nojogdial, "set this if you have a Vaio without a jogdial (like the fx series)"); +MODULE_PARM(mask, "i"); +MODULE_PARM_DESC(mask, "set this to the mask of event you want to enable (see doc)"); EXPORT_SYMBOL(sonypi_camera_command); diff -Nru a/drivers/char/sonypi.h b/drivers/char/sonypi.h --- a/drivers/char/sonypi.h Fri Nov 22 13:41:21 2002 +++ b/drivers/char/sonypi.h Fri Nov 22 13:41:21 2002 @@ -1,7 +1,9 @@ /* * Sony Programmable I/O Control Device driver for VAIO * - * Copyright (C) 2001 Stelian Pop , Alcôve + * Copyright (C) 2001-2002 Stelian Pop + * + * Copyright (C) 2001-2002 Alcôve * * Copyright (C) 2001 Michael Ashley * @@ -35,10 +37,16 @@ #ifdef __KERNEL__ #define SONYPI_DRIVER_MAJORVERSION 1 -#define SONYPI_DRIVER_MINORVERSION 14 +#define SONYPI_DRIVER_MINORVERSION 15 +#define SONYPI_DEVICE_MODEL_TYPE1 1 +#define SONYPI_DEVICE_MODEL_TYPE2 2 + +#include #include #include +#include +#include #include "linux/sonypi.h" /* type1 models use those */ @@ -145,25 +153,23 @@ #define SONYPI_CAMERA_REVISION 8 #define SONYPI_CAMERA_ROMVERSION 9 -/* key press event data (ioport2) */ -#define SONYPI_TYPE1_JOGGER_EV 0x10 -#define SONYPI_TYPE2_JOGGER_EV 0x08 -#define SONYPI_TYPE1_CAPTURE_EV 0x60 -#define SONYPI_TYPE2_CAPTURE_EV 0x08 -#define SONYPI_TYPE1_FNKEY_EV 0x20 -#define SONYPI_TYPE2_FNKEY_EV 0x08 -#define SONYPI_TYPE1_BLUETOOTH_EV 0x30 -#define SONYPI_TYPE2_BLUETOOTH_EV 0x08 -#define SONYPI_TYPE1_PKEY_EV 0x40 -#define SONYPI_TYPE2_PKEY_EV 0x08 -#define SONYPI_BACK_EV 0x08 -#define SONYPI_LID_EV 0x38 +/* Event masks */ +#define SONYPI_JOGGER_MASK 0x00000001 +#define SONYPI_CAPTURE_MASK 0x00000002 +#define SONYPI_FNKEY_MASK 0x00000004 +#define SONYPI_BLUETOOTH_MASK 0x00000008 +#define SONYPI_PKEY_MASK 0x00000010 +#define SONYPI_BACK_MASK 0x00000020 +#define SONYPI_HELP_MASK 0x00000040 +#define SONYPI_LID_MASK 0x00000080 +#define SONYPI_ZOOM_MASK 0x00000100 +#define SONYPI_THUMBPHRASE_MASK 0x00000200 +#define SONYPI_MEYE_MASK 0x00000400 struct sonypi_event { u8 data; u8 event; }; - /* The set of possible jogger events */ static struct sonypi_event sonypi_joggerev[] = { { 0x1f, SONYPI_EVENT_JOGDIAL_UP }, @@ -180,7 +186,7 @@ { 0x43, SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED }, { 0x40, SONYPI_EVENT_JOGDIAL_PRESSED }, { 0x00, SONYPI_EVENT_JOGDIAL_RELEASED }, - { 0x00, 0x00 } + { 0, 0 } }; /* The set of possible capture button events */ @@ -189,7 +195,7 @@ { 0x07, SONYPI_EVENT_CAPTURE_PRESSED }, { 0x01, SONYPI_EVENT_CAPTURE_PARTIALRELEASED }, { 0x00, SONYPI_EVENT_CAPTURE_RELEASED }, - { 0x00, 0x00 } + { 0, 0 } }; /* The set of possible fnkeys events */ @@ -215,7 +221,7 @@ { 0x34, SONYPI_EVENT_FNKEY_S }, { 0x35, SONYPI_EVENT_FNKEY_B }, { 0x36, SONYPI_EVENT_FNKEY_ONLY }, - { 0x00, 0x00 } + { 0, 0 } }; /* The set of possible program key events */ @@ -223,7 +229,7 @@ { 0x01, SONYPI_EVENT_PKEY_P1 }, { 0x02, SONYPI_EVENT_PKEY_P2 }, { 0x04, SONYPI_EVENT_PKEY_P3 }, - { 0x00, 0x00 } + { 0, 0 } }; /* The set of possible bluetooth events */ @@ -231,21 +237,74 @@ { 0x55, SONYPI_EVENT_BLUETOOTH_PRESSED }, { 0x59, SONYPI_EVENT_BLUETOOTH_ON }, { 0x5a, SONYPI_EVENT_BLUETOOTH_OFF }, - { 0x00, 0x00 } + { 0, 0 } }; /* The set of possible back button events */ static struct sonypi_event sonypi_backev[] = { { 0x20, SONYPI_EVENT_BACK_PRESSED }, + { 0, 0 } +}; + +/* The set of possible help button events */ +static struct sonypi_event sonypi_helpev[] = { { 0x3b, SONYPI_EVENT_HELP_PRESSED }, - { 0x00, 0x00 } + { 0, 0 } }; + /* The set of possible lid events */ static struct sonypi_event sonypi_lidev[] = { { 0x51, SONYPI_EVENT_LID_CLOSED }, { 0x50, SONYPI_EVENT_LID_OPENED }, - { 0x00, 0x00 } + { 0, 0 } +}; + +/* The set of possible zoom events */ +static struct sonypi_event sonypi_zoomev[] = { + { 0x3a, SONYPI_EVENT_ZOOM_PRESSED }, + { 0, 0 } +}; + +/* The set of possible thumbphrase events */ +static struct sonypi_event sonypi_thumbphraseev[] = { + { 0x3a, SONYPI_EVENT_THUMBPHRASE_PRESSED }, + { 0, 0 } +}; + +/* The set of possible motioneye camera events */ +static struct sonypi_event sonypi_meyeev[] = { + { 0x00, SONYPI_EVENT_MEYE_FACE }, + { 0x01, SONYPI_EVENT_MEYE_OPPOSITE }, + { 0, 0 } +}; + +struct sonypi_eventtypes { + int model; + u8 data; + unsigned long mask; + struct sonypi_event * events; +} sonypi_eventtypes[] = { + { SONYPI_DEVICE_MODEL_TYPE1, 0x70, SONYPI_MEYE_MASK, sonypi_meyeev }, + { SONYPI_DEVICE_MODEL_TYPE1, 0x30, SONYPI_LID_MASK, sonypi_lidev }, + { SONYPI_DEVICE_MODEL_TYPE1, 0x60, SONYPI_CAPTURE_MASK, sonypi_captureev }, + { SONYPI_DEVICE_MODEL_TYPE1, 0x10, SONYPI_JOGGER_MASK, sonypi_joggerev }, + { SONYPI_DEVICE_MODEL_TYPE1, 0x20, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, + { SONYPI_DEVICE_MODEL_TYPE1, 0x30, SONYPI_BLUETOOTH_MASK, sonypi_blueev }, + { SONYPI_DEVICE_MODEL_TYPE1, 0x40, SONYPI_PKEY_MASK, sonypi_pkeyev }, + + { SONYPI_DEVICE_MODEL_TYPE2, 0x38, SONYPI_LID_MASK, sonypi_lidev }, + { SONYPI_DEVICE_MODEL_TYPE2, 0x08, SONYPI_JOGGER_MASK, sonypi_joggerev }, + { SONYPI_DEVICE_MODEL_TYPE2, 0x08, SONYPI_CAPTURE_MASK, sonypi_captureev }, + { SONYPI_DEVICE_MODEL_TYPE2, 0x08, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, + { SONYPI_DEVICE_MODEL_TYPE2, 0x08, SONYPI_BLUETOOTH_MASK, sonypi_blueev }, + { SONYPI_DEVICE_MODEL_TYPE2, 0x08, SONYPI_PKEY_MASK, sonypi_pkeyev }, + { SONYPI_DEVICE_MODEL_TYPE2, 0x08, SONYPI_BACK_MASK, sonypi_backev }, + { SONYPI_DEVICE_MODEL_TYPE2, 0x08, SONYPI_HELP_MASK, sonypi_helpev }, + { SONYPI_DEVICE_MODEL_TYPE2, 0x08, SONYPI_ZOOM_MASK, sonypi_zoomev }, + { SONYPI_DEVICE_MODEL_TYPE2, 0x08, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev }, + + { 0, 0, 0, 0 } }; #define SONYPI_BUF_SIZE 128 @@ -259,9 +318,6 @@ unsigned char buf[SONYPI_BUF_SIZE]; }; -#define SONYPI_DEVICE_MODEL_TYPE1 1 -#define SONYPI_DEVICE_MODEL_TYPE2 2 - struct sonypi_device { struct pci_dev *dev; u16 irq; @@ -275,15 +331,46 @@ struct sonypi_queue queue; int open_count; int model; +#if CONFIG_PM + struct pm_dev *pm; +#endif }; -#define wait_on_command(quiet, command) { \ - unsigned int n = 10000; \ +#define ITERATIONS_LONG 10000 +#define ITERATIONS_SHORT 10 + +#define wait_on_command(quiet, command, iterations) { \ + unsigned int n = iterations; \ while (--n && (command)) \ udelay(1); \ if (!n && (verbose || !quiet)) \ printk(KERN_WARNING "sonypi command failed at %s : %s (line %d)\n", __FILE__, __FUNCTION__, __LINE__); \ } + +#if !defined(CONFIG_ACPI) +extern int verbose; + +static inline int ec_write(u8 addr, u8 value) { + wait_on_command(1, inb_p(SONYPI_CST_IOPORT) & 3, ITERATIONS_LONG); + outb_p(0x81, SONYPI_CST_IOPORT); + wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG); + outb_p(addr, SONYPI_DATA_IOPORT); + wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG); + outb_p(value, SONYPI_DATA_IOPORT); + wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG); + return 0; +} + +static inline int ec_read(u8 addr, u8 *value) { + wait_on_command(1, inb_p(SONYPI_CST_IOPORT) & 3, ITERATIONS_LONG); + outb_p(0x80, SONYPI_CST_IOPORT); + wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG); + outb_p(addr, SONYPI_DATA_IOPORT); + wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG); + *value = inb_p(SONYPI_DATA_IOPORT); + return 0; +} +#endif /* !CONFIG_ACPI */ #endif /* __KERNEL__ */ diff -Nru a/drivers/char/tty_io.c b/drivers/char/tty_io.c --- a/drivers/char/tty_io.c Fri Nov 22 13:41:21 2002 +++ b/drivers/char/tty_io.c Fri Nov 22 13:41:21 2002 @@ -146,10 +146,9 @@ extern void console_8xx_init(void); extern int rs_8xx_init(void); extern void mac_scc_console_init(void); -extern void hwc_console_init(void); -extern void hwc_tty_init(void); +extern void sclp_console_init(void); +extern void sclp_tty_init(void); extern void con3215_init(void); -extern void tty3215_init(void); extern void tub3270_con_init(void); extern void tub3270_init(void); extern void uart_console_init(void); @@ -2208,8 +2207,8 @@ #ifdef CONFIG_TN3215 con3215_init(); #endif -#ifdef CONFIG_HWC - hwc_console_init(); +#ifdef CONFIG_SCLP_CONSOLE + sclp_console_init(); #endif #ifdef CONFIG_STDIO_CONSOLE stdio_console_init(); @@ -2349,8 +2348,8 @@ #ifdef CONFIG_TN3215 tty3215_init(); #endif -#ifdef CONFIG_HWC - hwc_tty_init(); +#ifdef CONFIG_SCLP + sclp_tty_init(); #endif #ifdef CONFIG_A2232 a2232board_init(); diff -Nru a/drivers/char/w83877f_wdt.c b/drivers/char/w83877f_wdt.c --- a/drivers/char/w83877f_wdt.c Fri Nov 22 13:41:21 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,366 +0,0 @@ -/* - * W83877F Computer Watchdog Timer driver for Linux 2.4.x - * - * Based on acquirewdt.c by Alan Cox, - * and sbc60xxwdt.c by Jakob Oestergaard - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * The authors do NOT admit liability nor provide warranty for - * any of this software. This material is provided "AS-IS" in - * the hope that it may be useful for others. - * - * (c) Copyright 2001 Scott Jennings - * - * 4/19 - 2001 [Initial revision] - * 9/27 - 2001 Added spinlocking - * - * - * Theory of operation: - * A Watchdog Timer (WDT) is a hardware circuit that can - * reset the computer system in case of a software fault. - * You probably knew that already. - * - * Usually a userspace daemon will notify the kernel WDT driver - * via the /proc/watchdog special device file that userspace is - * still alive, at regular intervals. When such a notification - * occurs, the driver will usually tell the hardware watchdog - * that everything is in order, and that the watchdog should wait - * for yet another little while to reset the system. - * If userspace fails (RAM error, kernel bug, whatever), the - * notifications cease to occur, and the hardware watchdog will - * reset the system (causing a reboot) after the timeout occurs. - * - * This WDT driver is different from most other Linux WDT - * drivers in that the driver will ping the watchdog by itself, - * because this particular WDT has a very short timeout (1.6 - * seconds) and it would be insane to count on any userspace - * daemon always getting scheduled within that time frame. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define OUR_NAME "w83877f_wdt" - -#define ENABLE_W83877F_PORT 0x3F0 -#define ENABLE_W83877F 0x87 -#define DISABLE_W83877F 0xAA -#define WDT_PING 0x443 -#define WDT_REGISTER 0x14 -#define WDT_ENABLE 0x9C -#define WDT_DISABLE 0x8C - -/* - * The W83877F seems to be fixed at 1.6s timeout (at least on the - * EMACS PC-104 board I'm using). If we reset the watchdog every - * ~250ms we should be safe. */ - -#define WDT_INTERVAL (HZ/4+1) - -/* - * We must not require too good response from the userspace daemon. - * Here we require the userspace daemon to send us a heartbeat - * char to /dev/watchdog every 30 seconds. - */ - -#define WDT_HEARTBEAT (HZ * 30) - -static void wdt_timer_ping(unsigned long); -static struct timer_list timer; -static unsigned long next_heartbeat; -static unsigned long wdt_is_open; -static int wdt_expect_close; -static spinlock_t wdt_spinlock; - -/* - * Whack the dog - */ - -static void wdt_timer_ping(unsigned long data) -{ - /* If we got a heartbeat pulse within the WDT_US_INTERVAL - * we agree to ping the WDT - */ - if(time_before(jiffies, next_heartbeat)) - { - /* Ping the WDT */ - spin_lock(&wdt_spinlock); - - /* Ping the WDT by reading from WDT_PING */ - inb_p(WDT_PING); - - /* Re-set the timer interval */ - timer.expires = jiffies + WDT_INTERVAL; - add_timer(&timer); - - spin_unlock(&wdt_spinlock); - - } else { - printk(OUR_NAME ": Heartbeat lost! Will not ping the watchdog\n"); - } -} - -/* - * Utility routines - */ - -static void wdt_change(int writeval) -{ - unsigned long flags; - spin_lock_irqsave(&wdt_spinlock, flags); - - /* buy some time */ - inb_p(WDT_PING); - - /* make W83877F available */ - outb_p(ENABLE_W83877F, ENABLE_W83877F_PORT); - outb_p(ENABLE_W83877F, ENABLE_W83877F_PORT); - - /* enable watchdog */ - outb_p(WDT_REGISTER, ENABLE_W83877F_PORT); - outb_p(writeval, ENABLE_W83877F_PORT+1); - - /* lock the W8387FF away */ - outb_p(DISABLE_W83877F, ENABLE_W83877F_PORT); - - spin_unlock_irqrestore(&wdt_spinlock, flags); -} - -static void wdt_startup(void) -{ - next_heartbeat = jiffies + WDT_HEARTBEAT; - - /* Start the timer */ - timer.expires = jiffies + WDT_INTERVAL; - add_timer(&timer); - - wdt_change(WDT_ENABLE); - - printk(OUR_NAME ": Watchdog timer is now enabled.\n"); -} - -static void wdt_turnoff(void) -{ - /* Stop the timer */ - del_timer(&timer); - - wdt_change(WDT_DISABLE); - - printk(OUR_NAME ": Watchdog timer is now disabled...\n"); -} - - -/* - * /dev/watchdog handling - */ - -static ssize_t fop_write(struct file * file, const char * buf, size_t count, loff_t * ppos) -{ - /* We can't seek */ - if(ppos != &file->f_pos) - return -ESPIPE; - - /* See if we got the magic character */ - if(count) - { - size_t ofs; - - /* note: just in case someone wrote the magic character - * five months ago... */ - wdt_expect_close = 0; - - /* now scan */ - for(ofs = 0; ofs != count; ofs++) - { - char c; - if (get_user(c, buf + ofs)) - return -EFAULT; - if (c == 'V') - wdt_expect_close = 1; - } - - /* someone wrote to us, we should restart timer */ - next_heartbeat = jiffies + WDT_HEARTBEAT; - return 1; - }; - return 0; -} - -static ssize_t fop_read(struct file * file, char * buf, size_t count, loff_t * ppos) -{ - /* No can do */ - return -EINVAL; -} - -static int fop_open(struct inode * inode, struct file * file) -{ - switch(minor(inode->i_rdev)) - { - case WATCHDOG_MINOR: - /* Just in case we're already talking to someone... */ - if(test_and_set_bit(0, &wdt_is_open)) { - return -EBUSY; - } - /* Good, fire up the show */ - wdt_startup(); - return 0; - - default: - return -ENODEV; - } -} - -static int fop_close(struct inode * inode, struct file * file) -{ - if(minor(inode->i_rdev) == WATCHDOG_MINOR) - { - if(wdt_expect_close) - wdt_turnoff(); - else { - del_timer(&timer); - printk(OUR_NAME ": device file closed unexpectedly. Will not stop the WDT!\n"); - } - } - wdt_is_open = 0; - return 0; -} - -static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) -{ - static struct watchdog_info ident= - { - 0, - 1, - "W83877F" - }; - - switch(cmd) - { - default: - return -ENOIOCTLCMD; - case WDIOC_GETSUPPORT: - return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0; - case WDIOC_KEEPALIVE: - next_heartbeat = jiffies + WDT_HEARTBEAT; - return 0; - } -} - -static struct file_operations wdt_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = fop_read, - .write = fop_write, - .open = fop_open, - .release = fop_close, - .ioctl = fop_ioctl -}; - -static struct miscdevice wdt_miscdev = { - WATCHDOG_MINOR, - "watchdog", - &wdt_fops -}; - -/* - * Notifier for system down - */ - -static int wdt_notify_sys(struct notifier_block *this, unsigned long code, - void *unused) -{ - if(code==SYS_DOWN || code==SYS_HALT) - wdt_turnoff(); - return NOTIFY_DONE; -} - -/* - * The WDT needs to learn about soft shutdowns in order to - * turn the timebomb registers off. - */ - -static struct notifier_block wdt_notifier= -{ - wdt_notify_sys, - 0, - 0 -}; - -static void __exit w83877f_wdt_unload(void) -{ - wdt_turnoff(); - - /* Deregister */ - misc_deregister(&wdt_miscdev); - - unregister_reboot_notifier(&wdt_notifier); - release_region(WDT_PING,1); - release_region(ENABLE_W83877F_PORT,2); -} - -static int __init w83877f_wdt_init(void) -{ - int rc = -EBUSY; - - spin_lock_init(&wdt_spinlock); - - if (!request_region(ENABLE_W83877F_PORT, 2, "W83877F WDT")) - goto err_out; - if (!request_region(WDT_PING, 1, "W8387FF WDT")) - goto err_out_region1; - - init_timer(&timer); - timer.function = wdt_timer_ping; - timer.data = 0; - - rc = misc_register(&wdt_miscdev); - if (rc) - goto err_out_region2; - - rc = register_reboot_notifier(&wdt_notifier); - if (rc) - goto err_out_miscdev; - - printk(KERN_INFO OUR_NAME ": WDT driver for W83877F initialised.\n"); - - return 0; - -err_out_miscdev: - misc_deregister(&wdt_miscdev); -err_out_region2: - release_region(WDT_PING,1); -err_out_region1: - release_region(ENABLE_W83877F_PORT,2); -err_out: - return rc; -} - -module_init(w83877f_wdt_init); -module_exit(w83877f_wdt_unload); - -MODULE_AUTHOR("Scott and Bill Jennings"); -MODULE_DESCRIPTION("Driver for watchdog timer in w83877f chip"); -MODULE_LICENSE("GPL"); -EXPORT_NO_SYMBOLS; diff -Nru a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/watchdog/Kconfig Fri Nov 22 13:41:23 2002 @@ -0,0 +1,286 @@ +# +# Character device configuration +# + +menu "Watchdog Cards" + +config WATCHDOG + bool "Watchdog Timer Support" + ---help--- + If you say Y here (and to one of the following options) and create a + character special file /dev/watchdog with major number 10 and minor + number 130 using mknod ("man mknod"), you will get a watchdog, i.e.: + subsequently opening the file and then failing to write to it for + longer than 1 minute will result in rebooting the machine. This + could be useful for a networked machine that needs to come back + online as fast as possible after a lock-up. There's both a watchdog + implementation entirely in software (which can sometimes fail to + reboot the machine) and a driver for hardware watchdog boards, which + are more robust and can also keep track of the temperature inside + your computer. For details, read + in the kernel source. + + The watchdog is usually used together with the watchdog daemon + which is available from + . This daemon can + also monitor NFS connections and can reboot the machine when the process + table is full. + + If unsure, say N. + +config WATCHDOG_NOWAYOUT + bool "Disable watchdog shutdown on close" + depends on WATCHDOG + help + The default watchdog behaviour (which you get if you say N here) is + to stop the timer if the process managing it closes the file + /dev/watchdog. It's always remotely possible that this process might + get killed. If you say Y here, the watchdog cannot be stopped once + it has been started. + +config SOFT_WATCHDOG + tristate "Software watchdog" + depends on WATCHDOG + help + A software monitoring watchdog. This will fail to reboot your system + from some situations that the hardware watchdog will recover + from. Equally it's a lot cheaper to install. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + If you want to compile it as a module, say M here and read + . The module will be called + softdog.o. + +config WDT + tristate "WDT Watchdog timer" + depends on WATCHDOG + ---help--- + If you have a WDT500P or WDT501P watchdog board, say Y here, + otherwise N. It is not possible to probe for this board, which means + that you have to inform the kernel about the IO port and IRQ using + the "wdt=" kernel option (try "man bootparam" or see the + documentation of your boot loader (lilo or loadlin) about how to + pass options to the kernel at boot time). + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read . The module + will be called wdt.o. + +config WDTPCI + tristate "WDT PCI Watchdog timer" + depends on WATCHDOG + ---help--- + If you have a PCI WDT500/501 watchdog board, say Y here, otherwise + N. It is not possible to probe for this board, which means that you + have to inform the kernel about the IO port and IRQ using the "wdt=" + kernel option (try "man bootparam" or see the documentation of your + boot loader (lilo or loadlin) about how to pass options to the + kernel at boot time). + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read . The module + will be called wdt_pci.o. + +config WDT_501 + bool "WDT501 features" + depends on WDT + help + Saying Y here and creating a character special file /dev/temperature + with major number 10 and minor number 131 ("man mknod") will give + you a thermometer inside your computer: reading from + /dev/temperature yields one byte, the temperature in degrees + Fahrenheit. This works only if you have a WDT501P watchdog board + installed. + +config WDT_501_FAN + bool "Fan Tachometer" + depends on WDT_501 + help + Enable the Fan Tachometer on the WDT501. Only do this if you have a + fan tachometer actually set up. + +config PCWATCHDOG + tristate "Berkshire Products PC Watchdog" + depends on WATCHDOG + ---help--- + This is the driver for the Berkshire Products PC Watchdog card. + This card simply watches your kernel to make sure it doesn't freeze, + and if it does, it reboots your computer after a certain amount of + time. This driver is like the WDT501 driver but for different + hardware. Please read . The PC + watchdog cards can be ordered from . + + 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 is called pcwd.o. If you want to compile it as a module, + say M here and read . + + Most people will say N. + +config ACQUIRE_WDT + tristate "Acquire SBC Watchdog Timer" + depends on WATCHDOG + ---help--- + This is the driver for the hardware watchdog on the PSC-6x86 Single + Board Computer produced by Acquire Inc (and others). This watchdog + simply watches your kernel to make sure it doesn't freeze, and if + it does, it reboots your computer after a certain amount of time. + + This driver is like the WDT501 driver but for different hardware. + 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 is called pscwdt.o. If you want to compile it as a + module, say M here and read . Most + people will say N. + +config ADVANTECH_WDT + tristate "Advantech SBC Watchdog Timer" + depends on WATCHDOG + help + If you are configuring a Linux kernel for the Advantech single-board + computer, say `Y' here to support its built-in watchdog timer + feature. See the help for CONFIG_WATCHDOG for discussion. + +config 21285_WATCHDOG + tristate "DC21285 watchdog" + depends on WATCHDOG && FOOTBRIDGE + help + The Intel Footbridge chip contains a builtin watchdog circuit. Say Y + here if you wish to use this. Alternatively say M to compile the + driver as a module, which will be called wdt285.o. + + This driver does not work on all machines. In particular, early CATS + boards have hardware problems that will cause the machine to simply + lock up if the watchdog fires. + + "If in doubt, leave it out" - say N. + +config 977_WATCHDOG + tristate "NetWinder WB83C977 watchdog" + depends on WATCHDOG && FOOTBRIDGE && ARCH_NETWINDER + help + Say Y here to include support for the WB977 watchdog included in + NetWinder machines. Alternatively say M to compile the driver as + a module, which will be called wdt977.o. + + Not sure? It's safe to say N. + +config EUROTECH_WDT + tristate "Eurotech CPU-1220/1410 Watchdog Timer" + depends on WATCHDOG + help + Enable support for the watchdog timer on the Eurotech CPU-1220 and + CPU-1410 cards. These are PC/104 SBCs. Spec sheets and product + information are at . + +config IB700_WDT + tristate "IB700 SBC Watchdog Timer" + depends on WATCHDOG + ---help--- + This is the driver for the hardware watchdog on the IB700 Single + Board Computer produced by TMC Technology (www.tmc-uk.com). This watchdog + simply watches your kernel to make sure it doesn't freeze, and if + it does, it reboots your computer after a certain amount of time. + + This driver is like the WDT501 driver but for slightly different hardware. + + 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 is called ib700wdt.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. Most people + will say N. + +config I810_TCO + tristate "Intel i810 TCO timer / Watchdog" + depends on WATCHDOG + ---help--- + Hardware driver for the TCO timer built into the Intel i810 and i815 + chipset family. The TCO (Total Cost of Ownership) timer is a + watchdog timer that will reboot the machine after its second + expiration. The expiration time can be configured by commandline + argument "i810_margin=" where is the counter initial value. + It is decremented every 0.6 secs, the default is 50 which gives a + timeout of 30 seconds and one minute until reset. + + On some motherboards the driver may fail to reset the chipset's + NO_REBOOT flag which prevents the watchdog from rebooting the + machine. If this is the case you will get a kernel message like + "i810tco init: failed to reset NO_REBOOT flag". + + If you want to compile this as a module, say M and read + . The module will be called + i810-tco.o. + +config MIXCOMWD + tristate "Mixcom Watchdog" + depends on WATCHDOG + ---help--- + This is a driver for the Mixcom hardware watchdog cards. This + watchdog simply watches your kernel to make sure it doesn't freeze, + and if it does, it reboots your computer after a certain amount of + time. + + 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 is called mixcomwd.o. If you want to compile it as a + module, say M here and read . Most + people will say N. + +config SCx200_WDT + tristate "NatSemi SCx200 Watchdog" + depends on WATCHDOG + help + Enable the built-in watchdog timer support on the National + Semiconductor SCx200 processors. + + If compiled as a module, it will be called scx200_watchdog.o. + +config 60XX_WDT + tristate "SBC-60XX Watchdog Timer" + depends on WATCHDOG + help + This driver can be used with the watchdog timer found on some + single board computers, namely the 6010 PII based computer. + It may well work with other cards. It reads port 0x443 to enable + and re-set the watchdog timer, and reads port 0x45 to disable + the watchdog. If you have a card that behave in similar ways, + you can probably make this driver work with your card as well. + + You can compile this driver directly into the kernel, or use + it as a module. The module will be called sbc60xxwdt.o. + +config W83877F_WDT + tristate "W83877F (EMACS) Watchdog Timer" + depends on WATCHDOG + ---help--- + This is the driver for the hardware watchdog on the W83877F chipset + as used in EMACS PC-104 motherboards (and likely others). This + watchdog simply watches your kernel to make sure it doesn't freeze, + and if it does, it reboots your computer after a certain amount of + time. + + 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 is called mixcomwd.o. If you want to compile it as a + module, say M here and read . Most + people will say N. + +config MACHZ_WDT + tristate "ZF MachZ Watchdog" + depends on WATCHDOG + ---help--- + If you are using a ZF Micro MachZ processor, say Y here, otherwise + N. This is the driver for the watchdog timer builtin on that + processor using ZF-Logic interface. This watchdog simply watches + your kernel to make sure it doesn't freeze, and if it does, it + reboots your computer after a certain amount of time. + + 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 is called machzwd.o. If you want to compile it as a + module, say M here and read . + +endmenu diff -Nru a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/watchdog/Makefile Fri Nov 22 13:41:23 2002 @@ -0,0 +1,27 @@ +# +# Makefile for the kernel character device drivers. +# + +# Only one watchdog can succeed. We probe the hardware watchdog +# drivers first, then the softdog driver. This means if your hardware +# watchdog dies or is 'borrowed' for some reason the software watchdog +# still gives you some cover. + +watchdog-$(CONFIG_PCWATCHDOG) += pcwd.o +watchdog-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o +watchdog-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o +watchdog-$(CONFIG_IB700_WDT) += ib700wdt.o +watchdog-$(CONFIG_MIXCOMWD) += mixcomwd.o +watchdog-$(CONFIG_SCx200_WDT) += scx200_wdt.o +watchdog-$(CONFIG_60XX_WDT) += sbc60xxwdt.o +watchdog-$(CONFIG_WDT) += wdt.o +watchdog-$(CONFIG_WDTPCI) += wdt_pci.o +watchdog-$(CONFIG_21285_WATCHDOG) += wdt285.o +watchdog-$(CONFIG_977_WATCHDOG) += wdt977.o +watchdog-$(CONFIG_I810_TCO) += i810-tco.o +watchdog-$(CONFIG_MACHZ_WDT) += machzwd.o +watchdog-$(CONFIG_SH_WDT) += shwdt.o +watchdog-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o +watchdog-$(CONFIG_SOFT_WATCHDOG) += softdog.o + +include $(TOPDIR)/Rules.make diff -Nru a/drivers/char/watchdog/acquirewdt.c b/drivers/char/watchdog/acquirewdt.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/watchdog/acquirewdt.c Fri Nov 22 13:41:21 2002 @@ -0,0 +1,251 @@ +/* + * Acquire Single Board Computer Watchdog Timer driver for Linux 2.1.x + * + * Based on wdt.c. Original copyright messages: + * + * (c) Copyright 1996 Alan Cox , All Rights Reserved. + * http://www.redhat.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 1995 Alan Cox + * + * 14-Dec-2001 Matt Domsch + * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT + * Can't add timeout - driver doesn't allow changing value + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int acq_is_open; +static spinlock_t acq_lock; + +/* + * You must set these - there is no sane way to probe for this board. + */ + +#define WDT_STOP 0x43 +#define WDT_START 0x443 + +#ifdef CONFIG_WATCHDOG_NOWAYOUT +static int nowayout = 1; +#else +static int nowayout = 0; +#endif + +MODULE_PARM(nowayout,"i"); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); + +/* + * Kernel methods. + */ + + +static void acq_ping(void) +{ + /* Write a watchdog value */ + inb_p(WDT_START); +} + +static ssize_t acq_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +{ + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + if(count) + { + acq_ping(); + return 1; + } + return 0; +} + +static ssize_t acq_read(struct file *file, char *buf, size_t count, loff_t *ppos) +{ + return -EINVAL; +} + + + +static int acq_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + static struct watchdog_info ident= + { + WDIOF_KEEPALIVEPING, 1, "Acquire WDT" + }; + + switch(cmd) + { + case WDIOC_GETSUPPORT: + if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))) + return -EFAULT; + break; + + case WDIOC_GETSTATUS: + if (copy_to_user((int *)arg, &acq_is_open, sizeof(int))) + return -EFAULT; + break; + + case WDIOC_KEEPALIVE: + acq_ping(); + break; + + default: + return -ENOTTY; + } + return 0; +} + +static int acq_open(struct inode *inode, struct file *file) +{ + switch(minor(inode->i_rdev)) + { + case WATCHDOG_MINOR: + spin_lock(&acq_lock); + if(acq_is_open) + { + spin_unlock(&acq_lock); + return -EBUSY; + } + if (nowayout) { + MOD_INC_USE_COUNT; + } + /* + * Activate + */ + + acq_is_open=1; + inb_p(WDT_START); + spin_unlock(&acq_lock); + return 0; + default: + return -ENODEV; + } +} + +static int acq_close(struct inode *inode, struct file *file) +{ + if(minor(inode->i_rdev)==WATCHDOG_MINOR) + { + spin_lock(&acq_lock); + if (!nowayout) { + inb_p(WDT_STOP); + } + acq_is_open=0; + spin_unlock(&acq_lock); + } + return 0; +} + +/* + * Notifier for system down + */ + +static int acq_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if(code==SYS_DOWN || code==SYS_HALT) + { + /* Turn the card off */ + inb_p(WDT_STOP); + } + return NOTIFY_DONE; +} + +/* + * Kernel Interfaces + */ + + +static struct file_operations acq_fops = { + .owner = THIS_MODULE, + .read = acq_read, + .write = acq_write, + .ioctl = acq_ioctl, + .open = acq_open, + .release = acq_close, +}; + +static struct miscdevice acq_miscdev= +{ + WATCHDOG_MINOR, + "watchdog", + &acq_fops +}; + + +/* + * The WDT card needs to learn about soft shutdowns in order to + * turn the timebomb registers off. + */ + +static struct notifier_block acq_notifier= +{ + acq_notify_sys, + NULL, + 0 +}; + +static int __init acq_init(void) +{ + printk("WDT driver for Acquire single board computer initialising.\n"); + + spin_lock_init(&acq_lock); + if (misc_register(&acq_miscdev)) + return -ENODEV; + if (!request_region(WDT_STOP, 1, "Acquire WDT")) + { + misc_deregister(&acq_miscdev); + return -EIO; + } + if (!request_region(WDT_START, 1, "Acquire WDT")) + { + release_region(WDT_STOP, 1); + misc_deregister(&acq_miscdev); + return -EIO; + } + + register_reboot_notifier(&acq_notifier); + return 0; +} + +static void __exit acq_exit(void) +{ + misc_deregister(&acq_miscdev); + unregister_reboot_notifier(&acq_notifier); + release_region(WDT_STOP,1); + release_region(WDT_START,1); +} + +module_init(acq_init); +module_exit(acq_exit); + +MODULE_LICENSE("GPL"); diff -Nru a/drivers/char/watchdog/advantechwdt.c b/drivers/char/watchdog/advantechwdt.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/watchdog/advantechwdt.c Fri Nov 22 13:41:19 2002 @@ -0,0 +1,280 @@ +/* + * Advantech Single Board Computer WDT driver for Linux 2.4.x + * + * (c) Copyright 2000-2001 Marek Michalkiewicz + * + * Based on acquirewdt.c which is based on wdt.c. + * Original copyright messages: + * + * (c) Copyright 1996 Alan Cox , All Rights Reserved. + * http://www.redhat.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 1995 Alan Cox + * + * 14-Dec-2001 Matt Domsch + * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT + * Added timeout module option to override default + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int advwdt_is_open; +static spinlock_t advwdt_lock; + +/* + * You must set these - there is no sane way to probe for this board. + * + * To enable or restart, write the timeout value in seconds (1 to 63) + * to I/O port WDT_START. To disable, read I/O port WDT_STOP. + * Both are 0x443 for most boards (tested on a PCA-6276VE-00B1), but + * check your manual (at least the PCA-6159 seems to be different - + * the manual says WDT_STOP is 0x43, not 0x443). + * (0x43 is also a write-only control register for the 8254 timer!) + * + * TODO: module parameters to set the I/O port addresses + */ + +#define WDT_STOP 0x443 +#define WDT_START 0x443 + +#define WD_TIMO 60 /* 1 minute */ + +static int timeout = WD_TIMO; /* in seconds */ +MODULE_PARM(timeout,"i"); +MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=60)"); + +#ifdef CONFIG_WATCHDOG_NOWAYOUT +static int nowayout = 1; +#else +static int nowayout = 0; +#endif + +MODULE_PARM(nowayout,"i"); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); + +/* + * Kernel methods. + */ + +static void +advwdt_ping(void) +{ + /* Write a watchdog value */ + outb_p(timeout, WDT_START); +} + +static ssize_t +advwdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +{ + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + if (count) { + advwdt_ping(); + return 1; + } + return 0; +} + +static ssize_t +advwdt_read(struct file *file, char *buf, size_t count, loff_t *ppos) +{ + return -EINVAL; +} + +static int +advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + static struct watchdog_info ident = { + WDIOF_KEEPALIVEPING, 1, "Advantech WDT" + }; + + switch (cmd) { + case WDIOC_GETSUPPORT: + if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))) + return -EFAULT; + break; + + case WDIOC_GETSTATUS: + if (copy_to_user((int *)arg, &advwdt_is_open, sizeof(int))) + return -EFAULT; + break; + + case WDIOC_KEEPALIVE: + advwdt_ping(); + break; + + default: + return -ENOTTY; + } + return 0; +} + +static int +advwdt_open(struct inode *inode, struct file *file) +{ + switch (minor(inode->i_rdev)) { + case WATCHDOG_MINOR: + spin_lock(&advwdt_lock); + if (advwdt_is_open) { + spin_unlock(&advwdt_lock); + return -EBUSY; + } + if (nowayout) { + MOD_INC_USE_COUNT; + } + /* + * Activate + */ + + advwdt_is_open = 1; + advwdt_ping(); + spin_unlock(&advwdt_lock); + return 0; + default: + return -ENODEV; + } +} + +static int +advwdt_close(struct inode *inode, struct file *file) +{ + if (minor(inode->i_rdev) == WATCHDOG_MINOR) { + spin_lock(&advwdt_lock); + if (!nowayout) { + inb_p(WDT_STOP); + } + advwdt_is_open = 0; + spin_unlock(&advwdt_lock); + } + return 0; +} + +/* + * Notifier for system down + */ + +static int +advwdt_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if (code == SYS_DOWN || code == SYS_HALT) { + /* Turn the WDT off */ + inb_p(WDT_STOP); + } + return NOTIFY_DONE; +} + +/* + * Kernel Interfaces + */ + +static struct file_operations advwdt_fops = { + .owner = THIS_MODULE, + .read = advwdt_read, + .write = advwdt_write, + .ioctl = advwdt_ioctl, + .open = advwdt_open, + .release = advwdt_close, +}; + +static struct miscdevice advwdt_miscdev = { + WATCHDOG_MINOR, + "watchdog", + &advwdt_fops +}; + +/* + * The WDT needs to learn about soft shutdowns in order to + * turn the timebomb registers off. + */ + +static struct notifier_block advwdt_notifier = { + advwdt_notify_sys, + NULL, + 0 +}; + +static void __init +advwdt_validate_timeout(void) +{ + if (timeout < 1 || timeout > 63) { + timeout = WD_TIMO; + printk(KERN_INFO "advantechwdt: timeout value must be 1 <= x <= 63, using %d\n", timeout); + } +} + +static int __init +advwdt_init(void) +{ + printk("WDT driver for Advantech single board computer initialising.\n"); + + advwdt_validate_timeout(); + spin_lock_init(&advwdt_lock); + if (misc_register(&advwdt_miscdev)) + return -ENODEV; +#if WDT_START != WDT_STOP + if (!request_region(WDT_STOP, 1, "Advantech WDT")) { + misc_deregister(&advwdt_miscdev); + return -EIO; + } +#endif + if (!request_region(WDT_START, 1, "Advantech WDT")) { + misc_deregister(&advwdt_miscdev); +#if WDT_START != WDT_STOP + release_region(WDT_STOP, 1); +#endif + return -EIO; + } + register_reboot_notifier(&advwdt_notifier); + return 0; +} + +static void __exit +advwdt_exit(void) +{ + misc_deregister(&advwdt_miscdev); + unregister_reboot_notifier(&advwdt_notifier); +#if WDT_START != WDT_STOP + release_region(WDT_STOP,1); +#endif + release_region(WDT_START,1); +} + +module_init(advwdt_init); +module_exit(advwdt_exit); + +MODULE_LICENSE("GPL"); + +/* end of advantechwdt.c */ + diff -Nru a/drivers/char/watchdog/eurotechwdt.c b/drivers/char/watchdog/eurotechwdt.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/watchdog/eurotechwdt.c Fri Nov 22 13:41:18 2002 @@ -0,0 +1,501 @@ +/* + * Eurotech CPU-1220/1410 on board WDT driver for Linux 2.4.x + * + * (c) Copyright 2001 Ascensit + * (c) Copyright 2001 Rodolfo Giometti + * + * Based on wdt.c. + * Original copyright messages: + * + * (c) Copyright 1996-1997 Alan Cox , All Rights Reserved. + * http://www.redhat.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 1995 Alan Cox * + * + * 14-Dec-2001 Matt Domsch + * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT + * Added timeout module option to override default + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static int eurwdt_is_open; +static spinlock_t eurwdt_lock; + +/* + * You must set these - there is no sane way to probe for this board. + * You can use wdt=x,y to set these now. + */ + +static int io = 0x3f0; +static int irq = 10; +static char *ev = "int"; + +#define WDT_TIMEOUT 60 /* 1 minute */ +static int timeout = WDT_TIMEOUT; + +MODULE_PARM(timeout,"i"); +MODULE_PARM_DESC(timeout, "Eurotech WDT timeout in seconds (default=60)"); + +#ifdef CONFIG_WATCHDOG_NOWAYOUT +static int nowayout = 1; +#else +static int nowayout = 0; +#endif +MODULE_PARM(nowayout,"i"); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); + + +/* + * Some symbolic names + */ + +#define WDT_CTRL_REG 0x30 +#define WDT_OUTPIN_CFG 0xe2 + #define WDT_EVENT_INT 0x00 + #define WDT_EVENT_REBOOT 0x08 +#define WDT_UNIT_SEL 0xf1 + #define WDT_UNIT_SECS 0x80 +#define WDT_TIMEOUT_VAL 0xf2 +#define WDT_TIMER_CFG 0xf3 + + +#ifndef MODULE + +/** + * eurwdt_setup: + * @str: command line string + * + * Setup options. The board isn't really probe-able so we have to + * get the user to tell us the configuration. Sane people build it + * modular but the others come here. + */ + +static int __init eurwdt_setup(char *str) +{ + int ints[4]; + + str = get_options (str, ARRAY_SIZE(ints), ints); + + if (ints[0] > 0) { + io = ints[1]; + if (ints[0] > 1) + irq = ints[2]; + } + + return 1; +} + +__setup("wdt=", eurwdt_setup); + +#endif /* !MODULE */ + +MODULE_PARM(io, "i"); +MODULE_PARM_DESC(io, "Eurotech WDT io port (default=0x3f0)"); +MODULE_PARM(irq, "i"); +MODULE_PARM_DESC(irq, "Eurotech WDT irq (default=10)"); +MODULE_PARM(ev, "s"); +MODULE_PARM_DESC(ev, "Eurotech WDT event type (default is `reboot')"); + + +/* + * Programming support + */ + +static void __init eurwdt_validate_timeout(void) +{ + if (timeout < 0 || timeout > 255) { + timeout = WDT_TIMEOUT; + printk(KERN_INFO "eurwdt: timeout must be 0 < x < 255, using %d\n", + timeout); + } +} + +static inline void eurwdt_write_reg(u8 index, u8 data) +{ + outb(index, io); + outb(data, io+1); +} + +static inline void eurwdt_lock_chip(void) +{ + outb(0xaa, io); +} + +static inline void eurwdt_unlock_chip(void) +{ + outb(0x55, io); + eurwdt_write_reg(0x07, 0x08); /* set the logical device */ +} + +static inline void eurwdt_set_timeout(int timeout) +{ + eurwdt_write_reg(WDT_TIMEOUT_VAL, (u8) timeout); +} + +static inline void eurwdt_disable_timer(void) +{ + eurwdt_set_timeout(0); +} + +static void eurwdt_activate_timer(void) +{ + eurwdt_disable_timer(); + eurwdt_write_reg(WDT_CTRL_REG, 0x01); /* activate the WDT */ + eurwdt_write_reg(WDT_OUTPIN_CFG, !strcmp("int", ev) ? + WDT_EVENT_INT : WDT_EVENT_REBOOT); + /* Setting interrupt line */ + if (irq == 2 || irq > 15 || irq < 0) { + printk(KERN_ERR ": invalid irq number\n"); + irq = 0; /* if invalid we disable interrupt */ + } + if (irq == 0) + printk(KERN_INFO ": interrupt disabled\n"); + eurwdt_write_reg(WDT_TIMER_CFG, irq<<4); + + eurwdt_write_reg(WDT_UNIT_SEL, WDT_UNIT_SECS); /* we use seconds */ + eurwdt_set_timeout(0); /* the default timeout */ +} + + +/* + * Kernel methods. + */ + +void eurwdt_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + printk(KERN_CRIT "timeout WDT timeout\n"); + +#ifdef ONLY_TESTING + printk(KERN_CRIT "Would Reboot.\n"); +#else + printk(KERN_CRIT "Initiating system reboot.\n"); + machine_restart(NULL); +#endif +} + + +/** + * eurwdt_ping: + * + * Reload counter one with the watchdog timeout. + */ + +static void eurwdt_ping(void) +{ + /* Write the watchdog default value */ + eurwdt_set_timeout(timeout); +} + +/** + * eurwdt_write: + * @file: file handle to the watchdog + * @buf: buffer to write (unused as data does not matter here + * @count: count of bytes + * @ppos: pointer to the position to write. No seeks allowed + * + * A write to a watchdog device is defined as a keepalive signal. Any + * write of data will do, as we we don't define content meaning. + */ + +static ssize_t eurwdt_write(struct file *file, const char *buf, size_t count, +loff_t *ppos) +{ + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + if (count) { + eurwdt_ping(); /* the default timeout */ + return 1; + } + + return 0; +} + +/** + * eurwdt_ioctl: + * @inode: inode of the device + * @file: file handle to the device + * @cmd: watchdog command + * @arg: argument pointer + * + * The watchdog API defines a common set of functions for all watchdogs + * according to their available features. + */ + +static int eurwdt_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + static struct watchdog_info ident = { + .options = WDIOF_CARDRESET, + .firmware_version = 1, + .identity = "WDT Eurotech CPU-1220/1410", + }; + + int time; + + switch(cmd) { + default: + return -ENOTTY; + + case WDIOC_GETSUPPORT: + return copy_to_user((struct watchdog_info *)arg, &ident, + sizeof(ident)) ? -EFAULT : 0; + + case WDIOC_GETBOOTSTATUS: + return put_user(0, (int *) arg); + + case WDIOC_KEEPALIVE: + eurwdt_ping(); + return 0; + + case WDIOC_SETTIMEOUT: + if (copy_from_user(&time, (int *) arg, sizeof(int))) + return -EFAULT; + + /* Sanity check */ + if (time < 0 || time > 255) + return -EINVAL; + + timeout = time; + eurwdt_set_timeout(time); + return 0; + } +} + +/** + * eurwdt_open: + * @inode: inode of device + * @file: file handle to device + * + * The misc device has been opened. The watchdog device is single + * open and on opening we load the counter. + */ + +static int eurwdt_open(struct inode *inode, struct file *file) +{ + switch (minor(inode->i_rdev)) { + case WATCHDOG_MINOR: + spin_lock(&eurwdt_lock); + if (eurwdt_is_open) { + spin_unlock(&eurwdt_lock); + return -EBUSY; + } + if (nowayout) { + MOD_INC_USE_COUNT; + } + + eurwdt_is_open = 1; + + /* Activate the WDT */ + eurwdt_activate_timer(); + + spin_unlock(&eurwdt_lock); + + MOD_INC_USE_COUNT; + + return 0; + + case TEMP_MINOR: + return 0; + + default: + return -ENODEV; + } +} + +/** + * eurwdt_release: + * @inode: inode to board + * @file: file handle to board + * + * The watchdog has a configurable API. There is a religious dispute + * between people who want their watchdog to be able to shut down and + * those who want to be sure if the watchdog manager dies the machine + * reboots. In the former case we disable the counters, in the latter + * case you have to open it again very soon. + */ + +static int eurwdt_release(struct inode *inode, struct file *file) +{ + if (minor(inode->i_rdev) == WATCHDOG_MINOR) { + if (!nowayout) { + eurwdt_disable_timer(); + } + eurwdt_is_open = 0; + + MOD_DEC_USE_COUNT; + } + + return 0; +} + +/** + * eurwdt_notify_sys: + * @this: our notifier block + * @code: the event being reported + * @unused: unused + * + * Our notifier is called on system shutdowns. We want to turn the card + * off at reboot otherwise the machine will reboot again during memory + * test or worse yet during the following fsck. This would suck, in fact + * trust me - if it happens it does suck. + */ + +static int eurwdt_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if (code == SYS_DOWN || code == SYS_HALT) { + /* Turn the card off */ + eurwdt_disable_timer(); + } + + return NOTIFY_DONE; +} + +/* + * Kernel Interfaces + */ + + +static struct file_operations eurwdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = eurwdt_write, + .ioctl = eurwdt_ioctl, + .open = eurwdt_open, + .release = eurwdt_release, +}; + +static struct miscdevice eurwdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &eurwdt_fops +}; + +/* + * The WDT card needs to learn about soft shutdowns in order to + * turn the timebomb registers off. + */ + +static struct notifier_block eurwdt_notifier = { + .notifier_call = eurwdt_notify_sys, +}; + +/** + * cleanup_module: + * + * Unload the watchdog. You cannot do this with any file handles open. + * If your watchdog is set to continue ticking on close and you unload + * it, well it keeps ticking. We won't get the interrupt but the board + * will not touch PC memory so all is fine. You just have to load a new + * module in 60 seconds or reboot. + */ + +static void __exit eurwdt_exit(void) +{ + eurwdt_lock_chip(); + + misc_deregister(&eurwdt_miscdev); + + unregister_reboot_notifier(&eurwdt_notifier); + release_region(io, 2); + free_irq(irq, NULL); +} + +/** + * eurwdt_init: + * + * Set up the WDT watchdog board. After grabbing the resources + * we require we need also to unlock the device. + * The open() function will actually kick the board off. + */ + +static int __init eurwdt_init(void) +{ + int ret; + + eurwdt_validate_timeout(); + ret = misc_register(&eurwdt_miscdev); + if (ret) { + printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n", + WATCHDOG_MINOR); + goto out; + } + + ret = request_irq(irq, eurwdt_interrupt, SA_INTERRUPT, "eurwdt", NULL); + if(ret) { + printk(KERN_ERR "eurwdt: IRQ %d is not free.\n", irq); + goto outmisc; + } + + if (!request_region(io, 2, "eurwdt")) { + printk(KERN_ERR "eurwdt: IO %X is not free.\n", io); + ret = -EBUSY; + goto outirq; + } + + ret = register_reboot_notifier(&eurwdt_notifier); + if (ret) { + printk(KERN_ERR "eurwdt: can't register reboot notifier (err=%d)\n", ret); + goto outreg; + } + + eurwdt_unlock_chip(); + + ret = 0; + printk(KERN_INFO "Eurotech WDT driver 0.01 at %X (Interrupt %d)" + " - timeout event: %s\n", + io, irq, (!strcmp("int", ev) ? "int" : "reboot")); + + spin_lock_init(&eurwdt_lock); + + out: + return ret; + + outreg: + release_region(io, 2); + + outirq: + free_irq(irq, NULL); + + outmisc: + misc_deregister(&eurwdt_miscdev); + goto out; +} + +module_init(eurwdt_init); +module_exit(eurwdt_exit); + +MODULE_AUTHOR("Rodolfo Giometti"); +MODULE_DESCRIPTION("Driver for Eurotech CPU-1220/1410 on board watchdog"); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/char/watchdog/i810-tco.c b/drivers/char/watchdog/i810-tco.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/watchdog/i810-tco.c Fri Nov 22 13:41:17 2002 @@ -0,0 +1,431 @@ +/* + * i810-tco 0.05: TCO timer driver for i8xx chipsets + * + * (c) Copyright 2000 kernel concepts , All Rights Reserved. + * http://www.kernelconcepts.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 of the License, or (at your option) any later version. + * + * Neither kernel concepts nor Nils Faerber admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 2000 kernel concepts + * developed for + * Jentro AG, Haar/Munich (Germany) + * + * TCO timer driver for i8xx chipsets + * based on softdog.c by Alan Cox + * + * The TCO timer is implemented in the following I/O controller hubs: + * (See the intel documentation on http://developer.intel.com.) + * 82801AA & 82801AB chip : document number 290655-003, 290677-004, + * 82801BA & 82801BAM chip : document number 290687-002, 298242-005, + * 82801CA & 82801CAM chip : document number 290716-001, 290718-001, + * 82801DB & 82801E chip : document number 290744-001, 273599-001 + * + * 20000710 Nils Faerber + * Initial Version 0.01 + * 20000728 Nils Faerber + * 0.02 Fix for SMI_EN->TCO_EN bit, some cleanups + * 20011214 Matt Domsch + * 0.03 Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT + * Didn't add timeout option as i810_margin already exists. + * 20020224 Joel Becker, Wim Van Sebroeck + * 0.04 Support for 82801CA(M) chipset, timer margin needs to be > 3, + * add support for WDIOC_SETTIMEOUT and WDIOC_GETTIMEOUT. + * 20020412 Rob Radez , Wim Van Sebroeck + * 0.05 Fix possible timer_alive race, add expect close support, + * clean up ioctls (WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS and + * WDIOC_SETOPTIONS), made i810tco_getdevice __init, + * removed boot_status, removed tco_timer_read, + * added support for 82801DB and 82801E chipset, general cleanup. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "i810-tco.h" + + +/* Module and version information */ +#define TCO_VERSION "0.05" +#define TCO_MODULE_NAME "i810 TCO timer" +#define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION + +/* Default expire timeout */ +#define TIMER_MARGIN 50 /* steps of 0.6sec, 3 0x3f || tmrval < 0x04) + return -1; + + spin_lock(&tco_lock); + val = inb (TCO1_TMR); + val &= 0xc0; + val |= tmrval; + outb (val, TCO1_TMR); + val = inb (TCO1_TMR); + spin_unlock(&tco_lock); + + if ((val & 0x3f) != tmrval) + return -1; + + return 0; +} + +/* + * Reload (trigger) the timer. Lock is needed so we dont reload it during + * a reprogramming event + */ + +static void tco_timer_reload (void) +{ + spin_lock(&tco_lock); + outb (0x01, TCO1_RLD); + spin_unlock(&tco_lock); +} + +/* + * Allow only one person to hold it open + */ + +static int i810tco_open (struct inode *inode, struct file *file) +{ + if (test_and_set_bit(0, &timer_alive)) + return -EBUSY; + + /* + * Reload and activate timer + */ + tco_timer_reload (); + tco_timer_start (); + return 0; +} + +static int i810tco_release (struct inode *inode, struct file *file) +{ + /* + * Shut off the timer. + */ + if (tco_expect_close == 42 && !nowayout) { + tco_timer_stop (); + } else { + tco_timer_reload (); + printk(KERN_CRIT TCO_MODULE_NAME ": Unexpected close, not stopping watchdog!\n"); + } + clear_bit(0, &timer_alive); + tco_expect_close = 0; + return 0; +} + +static ssize_t i810tco_write (struct file *file, const char *data, + size_t len, loff_t * ppos) +{ + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + /* See if we got the magic character 'V' and reload the timer */ + if (len) { + size_t i; + + tco_expect_close = 0; + + /* scan to see wether or not we got the magic character */ + for (i = 0; i != len; i++) { + u8 c; + if(get_user(c, data+i)) + return -EFAULT; + if (c == 'V') + tco_expect_close = 42; + } + + /* someone wrote to us, we should reload the timer */ + tco_timer_reload (); + return 1; + } + return 0; +} + +static int i810tco_ioctl (struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + int new_margin, u_margin; + int options, retval = -EINVAL; + + static struct watchdog_info ident = { + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, + .firmware_version = 0, + .identity = "i810 TCO timer", + }; + switch (cmd) { + default: + return -ENOTTY; + case WDIOC_GETSUPPORT: + if (copy_to_user + ((struct watchdog_info *) arg, &ident, sizeof (ident))) + return -EFAULT; + return 0; + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user (0, (int *) arg); + case WDIOC_SETOPTIONS: + if (get_user (options, (int *) arg)) + return -EFAULT; + if (options & WDIOS_DISABLECARD) { + tco_timer_stop (); + retval = 0; + } + if (options & WDIOS_ENABLECARD) { + tco_timer_reload (); + tco_timer_start (); + retval = 0; + } + return retval; + case WDIOC_KEEPALIVE: + tco_timer_reload (); + return 0; + case WDIOC_SETTIMEOUT: + if (get_user (u_margin, (int *) arg)) + return -EFAULT; + new_margin = (u_margin * 10 + 5) / 6; + if ((new_margin < 4) || (new_margin > 63)) + return -EINVAL; + if (tco_timer_settimer ((unsigned char) new_margin)) + return -EINVAL; + i810_margin = new_margin; + tco_timer_reload (); + /* Fall */ + case WDIOC_GETTIMEOUT: + return put_user ((int)(i810_margin * 6 / 10), (int *) arg); + } +} + +/* + * Data for PCI driver interface + * + * This data only exists for exporting the supported + * PCI ids via MODULE_DEVICE_TABLE. We do not actually + * register a pci_driver, because someone else might one day + * want to register another driver on the same PCI id. + */ +static struct pci_device_id i810tco_pci_tbl[] __initdata = { + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0, PCI_ANY_ID, PCI_ANY_ID, }, + { 0, }, +}; +MODULE_DEVICE_TABLE (pci, i810tco_pci_tbl); + +static struct pci_dev *i810tco_pci; + +static unsigned char __init i810tco_getdevice (void) +{ + struct pci_dev *dev; + u8 val1, val2; + u16 badr; + /* + * Find the PCI device + */ + + pci_for_each_dev(dev) { + if (pci_match_device(i810tco_pci_tbl, dev)) { + i810tco_pci = dev; + break; + } + } + + if (i810tco_pci) { + /* + * Find the ACPI base I/O address which is the base + * for the TCO registers (TCOBASE=ACPIBASE + 0x60) + * ACPIBASE is bits [15:7] from 0x40-0x43 + */ + pci_read_config_byte (i810tco_pci, 0x40, &val1); + pci_read_config_byte (i810tco_pci, 0x41, &val2); + badr = ((val2 << 1) | (val1 >> 7)) << 7; + ACPIBASE = badr; + /* Something's wrong here, ACPIBASE has to be set */ + if (badr == 0x0001 || badr == 0x0000) { + printk (KERN_ERR TCO_MODULE_NAME " init: failed to get TCOBASE address\n"); + return 0; + } + /* + * Check chipset's NO_REBOOT bit + */ + pci_read_config_byte (i810tco_pci, 0xd4, &val1); + if (val1 & 0x02) { + val1 &= 0xfd; + pci_write_config_byte (i810tco_pci, 0xd4, val1); + pci_read_config_byte (i810tco_pci, 0xd4, &val1); + if (val1 & 0x02) { + printk (KERN_ERR TCO_MODULE_NAME " init: failed to reset NO_REBOOT flag, reboot disabled by hardware\n"); + return 0; /* Cannot reset NO_REBOOT bit */ + } + } + /* Set the TCO_EN bit in SMI_EN register */ + val1 = inb (SMI_EN + 1); + val1 &= 0xdf; + outb (val1, SMI_EN + 1); + /* Clear out the (probably old) status */ + outb (0, TCO1_STS); + outb (3, TCO2_STS); + return 1; + } + return 0; +} + +static struct file_operations i810tco_fops = { + .owner = THIS_MODULE, + .write = i810tco_write, + .ioctl = i810tco_ioctl, + .open = i810tco_open, + .release = i810tco_release, +}; + +static struct miscdevice i810tco_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &i810tco_fops, +}; + +static int __init watchdog_init (void) +{ + spin_lock_init(&tco_lock); + if (!i810tco_getdevice () || i810tco_pci == NULL) + return -ENODEV; + if (!request_region (TCOBASE, 0x10, "i810 TCO")) { + printk (KERN_ERR TCO_MODULE_NAME + ": I/O address 0x%04x already in use\n", + TCOBASE); + return -EIO; + } + if (misc_register (&i810tco_miscdev) != 0) { + release_region (TCOBASE, 0x10); + printk (KERN_ERR TCO_MODULE_NAME ": cannot register miscdev\n"); + return -EIO; + } + tco_timer_settimer ((unsigned char) i810_margin); + tco_timer_reload (); + + printk (KERN_INFO TCO_DRIVER_NAME + ": timer margin: %d sec (0x%04x) (nowayout=%d)\n", + (int) (i810_margin * 6 / 10), TCOBASE, nowayout); + return 0; +} + +static void __exit watchdog_cleanup (void) +{ + u8 val; + + /* Reset the timer before we leave */ + tco_timer_reload (); + /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ + pci_read_config_byte (i810tco_pci, 0xd4, &val); + val |= 0x02; + pci_write_config_byte (i810tco_pci, 0xd4, val); + release_region (TCOBASE, 0x10); + misc_deregister (&i810tco_miscdev); +} + +module_init(watchdog_init); +module_exit(watchdog_cleanup); + +MODULE_AUTHOR("Nils Faerber"); +MODULE_DESCRIPTION("TCO timer driver for i8xx chipsets"); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/char/watchdog/ib700wdt.c b/drivers/char/watchdog/ib700wdt.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/watchdog/ib700wdt.c Fri Nov 22 13:41:23 2002 @@ -0,0 +1,311 @@ +/* + * IB700 Single Board Computer WDT driver for Linux 2.4.x + * + * (c) Copyright 2001 Charles Howes + * + * Based on advantechwdt.c which is based on acquirewdt.c which + * is based on wdt.c. + * + * (c) Copyright 2000-2001 Marek Michalkiewicz + * + * Based on acquirewdt.c which is based on wdt.c. + * Original copyright messages: + * + * (c) Copyright 1996 Alan Cox , All Rights Reserved. + * http://www.redhat.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 1995 Alan Cox + * + * 14-Dec-2001 Matt Domsch + * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT + * Added timeout module option to override default + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int ibwdt_is_open; +static spinlock_t ibwdt_lock; + +/* + * + * Watchdog Timer Configuration + * + * The function of the watchdog timer is to reset the system + * automatically and is defined at I/O port 0443H. To enable the + * watchdog timer and allow the system to reset, write I/O port 0443H. + * To disable the timer, write I/O port 0441H for the system to stop the + * watchdog function. The timer has a tolerance of 20% for its + * intervals. + * + * The following describes how the timer should be programmed. + * + * Enabling Watchdog: + * MOV AX,000FH (Choose the values from 0 to F) + * MOV DX,0443H + * OUT DX,AX + * + * Disabling Watchdog: + * MOV AX,000FH (Any value is fine.) + * MOV DX,0441H + * OUT DX,AX + * + * Watchdog timer control table: + * Level Value Time/sec | Level Value Time/sec + * 1 F 0 | 9 7 16 + * 2 E 2 | 10 6 18 + * 3 D 4 | 11 5 20 + * 4 C 6 | 12 4 22 + * 5 B 8 | 13 3 24 + * 6 A 10 | 14 2 26 + * 7 9 12 | 15 1 28 + * 8 8 14 | 16 0 30 + * + */ + +#define WDT_STOP 0x441 +#define WDT_START 0x443 + +#define WD_TIMO 0 /* 30 seconds +/- 20%, from table */ + +static int timeout_val = WD_TIMO; /* value in table */ +static int timeout = 30; /* in seconds */ +MODULE_PARM(timeout,"i"); +MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, 0 < n < 30, must be even (default=30)"); + +#ifdef CONFIG_WATCHDOG_NOWAYOUT +static int nowayout = 1; +#else +static int nowayout = 0; +#endif + +MODULE_PARM(nowayout,"i"); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); + +/* + * Kernel methods. + */ + +static void __init +ibwdt_validate_timeout(void) +{ + timeout_val = (30 - timeout) / 2; + if (timeout_val < 0 || timeout_val > 0xF) timeout_val = WD_TIMO; +} + +static void +ibwdt_ping(void) +{ + /* Write a watchdog value */ + outb_p(timeout_val, WDT_START); +} + +static ssize_t +ibwdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +{ + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + if (count) { + ibwdt_ping(); + return 1; + } + return 0; +} + +static ssize_t +ibwdt_read(struct file *file, char *buf, size_t count, loff_t *ppos) +{ + return -EINVAL; +} + +static int +ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + static struct watchdog_info ident = { + WDIOF_KEEPALIVEPING, 1, "IB700 WDT" + }; + + switch (cmd) { + case WDIOC_GETSUPPORT: + if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))) + return -EFAULT; + break; + + case WDIOC_GETSTATUS: + if (copy_to_user((int *)arg, &ibwdt_is_open, sizeof(int))) + return -EFAULT; + break; + + case WDIOC_KEEPALIVE: + ibwdt_ping(); + break; + + default: + return -ENOTTY; + } + return 0; +} + +static int +ibwdt_open(struct inode *inode, struct file *file) +{ + switch (minor(inode->i_rdev)) { + case WATCHDOG_MINOR: + spin_lock(&ibwdt_lock); + if (ibwdt_is_open) { + spin_unlock(&ibwdt_lock); + return -EBUSY; + } + if (nowayout) { + MOD_INC_USE_COUNT; + } + /* + * Activate + */ + + ibwdt_is_open = 1; + ibwdt_ping(); + spin_unlock(&ibwdt_lock); + return 0; + default: + return -ENODEV; + } +} + +static int +ibwdt_close(struct inode *inode, struct file *file) +{ + lock_kernel(); + if (minor(inode->i_rdev) == WATCHDOG_MINOR) { + spin_lock(&ibwdt_lock); + if (!nowayout) { + outb_p(timeout_val, WDT_STOP); + } + ibwdt_is_open = 0; + spin_unlock(&ibwdt_lock); + } + unlock_kernel(); + return 0; +} + +/* + * Notifier for system down + */ + +static int +ibwdt_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if (code == SYS_DOWN || code == SYS_HALT) { + /* Turn the WDT off */ + outb_p(timeout_val, WDT_STOP); + } + return NOTIFY_DONE; +} + +/* + * Kernel Interfaces + */ + +static struct file_operations ibwdt_fops = { + .owner = THIS_MODULE, + .read = ibwdt_read, + .write = ibwdt_write, + .ioctl = ibwdt_ioctl, + .open = ibwdt_open, + .release = ibwdt_close, +}; + +static struct miscdevice ibwdt_miscdev = { + WATCHDOG_MINOR, + "watchdog", + &ibwdt_fops +}; + +/* + * The WDT needs to learn about soft shutdowns in order to + * turn the timebomb registers off. + */ + +static struct notifier_block ibwdt_notifier = { + ibwdt_notify_sys, + NULL, + 0 +}; + +static int __init +ibwdt_init(void) +{ + printk("WDT driver for IB700 single board computer initialising.\n"); + + ibwdt_validate_timeout(); + spin_lock_init(&ibwdt_lock); + if (misc_register(&ibwdt_miscdev)) + return -ENODEV; +#if WDT_START != WDT_STOP + if (!request_region(WDT_STOP, 1, "IB700 WDT")) { + misc_deregister(&ibwdt_miscdev); + return -EIO; + } +#endif + if (!request_region(WDT_START, 1, "IB700 WDT")) { +#if WDT_START != WDT_STOP + release_region(WDT_STOP, 1); +#endif + misc_deregister(&ibwdt_miscdev); + return -EIO; + } + register_reboot_notifier(&ibwdt_notifier); + return 0; +} + +static void __exit +ibwdt_exit(void) +{ + misc_deregister(&ibwdt_miscdev); + unregister_reboot_notifier(&ibwdt_notifier); +#if WDT_START != WDT_STOP + release_region(WDT_STOP,1); +#endif + release_region(WDT_START,1); +} + +module_init(ibwdt_init); +module_exit(ibwdt_exit); + +MODULE_AUTHOR("Charles Howes "); +MODULE_DESCRIPTION("IB700 SBC watchdog driver"); +MODULE_LICENSE("GPL"); + +/* end of ib700wdt.c */ diff -Nru a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/watchdog/machzwd.c Fri Nov 22 13:41:18 2002 @@ -0,0 +1,557 @@ +/* + * MachZ ZF-Logic Watchdog Timer driver for Linux + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * The author does NOT admit liability nor provide warranty for + * any of this software. This material is provided "AS-IS" in + * the hope that it may be useful for others. + * + * Author: Fernando Fuganti + * + * Based on sbc60xxwdt.c by Jakob Oestergaard + * + * + * We have two timers (wd#1, wd#2) driven by a 32 KHz clock with the + * following periods: + * wd#1 - 2 seconds; + * wd#2 - 7.2 ms; + * After the expiration of wd#1, it can generate a NMI, SCI, SMI, or + * a system RESET and it starts wd#2 that unconditionaly will RESET + * the system when the counter reaches zero. + * + * 14-Dec-2001 Matt Domsch + * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* ports */ +#define ZF_IOBASE 0x218 +#define INDEX 0x218 +#define DATA_B 0x219 +#define DATA_W 0x21A +#define DATA_D 0x21A + +/* indexes */ /* size */ +#define ZFL_VERSION 0x02 /* 16 */ +#define CONTROL 0x10 /* 16 */ +#define STATUS 0x12 /* 8 */ +#define COUNTER_1 0x0C /* 16 */ +#define COUNTER_2 0x0E /* 8 */ +#define PULSE_LEN 0x0F /* 8 */ + +/* controls */ +#define ENABLE_WD1 0x0001 +#define ENABLE_WD2 0x0002 +#define RESET_WD1 0x0010 +#define RESET_WD2 0x0020 +#define GEN_SCI 0x0100 +#define GEN_NMI 0x0200 +#define GEN_SMI 0x0400 +#define GEN_RESET 0x0800 + + +/* utilities */ + +#define WD1 0 +#define WD2 1 + +#define zf_writew(port, data) { outb(port, INDEX); outw(data, DATA_W); } +#define zf_writeb(port, data) { outb(port, INDEX); outb(data, DATA_B); } +#define zf_get_ZFL_version() zf_readw(ZFL_VERSION) + + +static unsigned short zf_readw(unsigned char port) +{ + outb(port, INDEX); + return inw(DATA_W); +} + +static unsigned short zf_readb(unsigned char port) +{ + outb(port, INDEX); + return inb(DATA_B); +} + + +MODULE_AUTHOR("Fernando Fuganti "); +MODULE_DESCRIPTION("MachZ ZF-Logic Watchdog driver"); +MODULE_LICENSE("GPL"); +MODULE_PARM(action, "i"); +MODULE_PARM_DESC(action, "after watchdog resets, generate: 0 = RESET(*) 1 = SMI 2 = NMI 3 = SCI"); + +#ifdef CONFIG_WATCHDOG_NOWAYOUT +static int nowayout = 1; +#else +static int nowayout = 0; +#endif + +MODULE_PARM(nowayout,"i"); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); + +#define PFX "machzwd" + +static struct watchdog_info zf_info = { + .options = WDIOF_KEEPALIVEPING, + .firmware_version = 1, + .identity = "ZF-Logic watchdog" +}; + + +/* + * action refers to action taken when watchdog resets + * 0 = GEN_RESET + * 1 = GEN_SMI + * 2 = GEN_NMI + * 3 = GEN_SCI + * defaults to GEN_RESET (0) + */ +static int action = 0; +static int zf_action = GEN_RESET; +static int zf_is_open = 0; +static int zf_expect_close = 0; +static spinlock_t zf_lock; +static spinlock_t zf_port_lock; +static struct timer_list zf_timer; +static unsigned long next_heartbeat = 0; + + +/* timeout for user land heart beat (10 seconds) */ +#define ZF_USER_TIMEO (HZ*10) + +/* timeout for hardware watchdog (~500ms) */ +#define ZF_HW_TIMEO (HZ/2) + +/* number of ticks on WD#1 (driven by a 32KHz clock, 2s) */ +#define ZF_CTIMEOUT 0xffff + +#ifndef ZF_DEBUG +# define dprintk(format, args...) +#else +# define dprintk(format, args...) printk(KERN_DEBUG PFX; ":" __FUNCTION__ ":%d: " format, __LINE__ , ## args) +#endif + + +/* STATUS register functions */ + +static inline unsigned char zf_get_status(void) +{ + return zf_readb(STATUS); +} + +static inline void zf_set_status(unsigned char new) +{ + zf_writeb(STATUS, new); +} + + +/* CONTROL register functions */ + +static inline unsigned short zf_get_control(void) +{ + return zf_readw(CONTROL); +} + +static inline void zf_set_control(unsigned short new) +{ + zf_writew(CONTROL, new); +} + + +/* WD#? counter functions */ +/* + * Just get current counter value + */ + +static inline unsigned short zf_get_timer(unsigned char n) +{ + switch(n){ + case WD1: + return zf_readw(COUNTER_1); + case WD2: + return zf_readb(COUNTER_2); + default: + return 0; + } +} + +/* + * Just set counter value + */ + +static inline void zf_set_timer(unsigned short new, unsigned char n) +{ + switch(n){ + case WD1: + zf_writew(COUNTER_1, new); + case WD2: + zf_writeb(COUNTER_2, new > 0xff ? 0xff : new); + default: + return; + } +} + +/* + * stop hardware timer + */ +static void zf_timer_off(void) +{ + unsigned int ctrl_reg = 0; + unsigned long flags; + + /* stop internal ping */ + del_timer_sync(&zf_timer); + + spin_lock_irqsave(&zf_port_lock, flags); + /* stop watchdog timer */ + ctrl_reg = zf_get_control(); + ctrl_reg |= (ENABLE_WD1|ENABLE_WD2); /* disable wd1 and wd2 */ + ctrl_reg &= ~(ENABLE_WD1|ENABLE_WD2); + zf_set_control(ctrl_reg); + spin_unlock_irqrestore(&zf_port_lock, flags); + + printk(KERN_INFO PFX ": Watchdog timer is now disabled\n"); +} + + +/* + * start hardware timer + */ +static void zf_timer_on(void) +{ + unsigned int ctrl_reg = 0; + unsigned long flags; + + spin_lock_irqsave(&zf_port_lock, flags); + + zf_writeb(PULSE_LEN, 0xff); + + zf_set_timer(ZF_CTIMEOUT, WD1); + + /* user land ping */ + next_heartbeat = jiffies + ZF_USER_TIMEO; + + /* start the timer for internal ping */ + zf_timer.expires = jiffies + ZF_HW_TIMEO; + + add_timer(&zf_timer); + + /* start watchdog timer */ + ctrl_reg = zf_get_control(); + ctrl_reg |= (ENABLE_WD1|zf_action); + zf_set_control(ctrl_reg); + spin_unlock_irqrestore(&zf_port_lock, flags); + + printk(KERN_INFO PFX ": Watchdog timer is now enabled\n"); +} + + +static void zf_ping(unsigned long data) +{ + unsigned int ctrl_reg = 0; + unsigned long flags; + + zf_writeb(COUNTER_2, 0xff); + + if(time_before(jiffies, next_heartbeat)){ + + dprintk("time_before: %ld\n", next_heartbeat - jiffies); + + /* + * reset event is activated by transition from 0 to 1 on + * RESET_WD1 bit and we assume that it is already zero... + */ + + spin_lock_irqsave(&zf_port_lock, flags); + ctrl_reg = zf_get_control(); + ctrl_reg |= RESET_WD1; + zf_set_control(ctrl_reg); + + /* ...and nothing changes until here */ + ctrl_reg &= ~(RESET_WD1); + zf_set_control(ctrl_reg); + spin_unlock_irqrestore(&zf_port_lock, flags); + + zf_timer.expires = jiffies + ZF_HW_TIMEO; + add_timer(&zf_timer); + }else{ + printk(KERN_CRIT PFX ": I will reset your machine\n"); + } +} + +static ssize_t zf_write(struct file *file, const char *buf, size_t count, + loff_t *ppos) +{ + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + /* See if we got the magic character */ + if(count){ + +/* + * no need to check for close confirmation + * no way to disable watchdog ;) + */ + if (!nowayout) { + size_t ofs; + + /* + * note: just in case someone wrote the magic character + * five months ago... + */ + zf_expect_close = 0; + + /* now scan */ + for(ofs = 0; ofs != count; ofs++){ + char c; + if (get_user(c, buf + ofs)) + return -EFAULT; + if (c == 'V'){ + zf_expect_close = 1; + dprintk("zf_expect_close 1\n"); + } + } + } + /* + * Well, anyhow someone wrote to us, + * we should return that favour + */ + next_heartbeat = jiffies + ZF_USER_TIMEO; + dprintk("user ping at %ld\n", jiffies); + + return 1; + } + + return 0; +} + +static ssize_t zf_read(struct file *file, char *buf, size_t count, + loff_t *ppos) +{ + return -EINVAL; +} + + + +static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + switch(cmd){ + case WDIOC_GETSUPPORT: + if (copy_to_user((struct watchdog_info *)arg, + &zf_info, sizeof(zf_info))) + return -EFAULT; + break; + + case WDIOC_GETSTATUS: + if (copy_to_user((int *)arg, &zf_is_open, sizeof(int))) + return -EFAULT; + break; + + case WDIOC_KEEPALIVE: + zf_ping(0); + break; + + default: + return -ENOTTY; + } + + return 0; +} + +static int zf_open(struct inode *inode, struct file *file) +{ + switch(minor(inode->i_rdev)){ + case WATCHDOG_MINOR: + spin_lock(&zf_lock); + if(zf_is_open){ + spin_unlock(&zf_lock); + return -EBUSY; + } + + if (nowayout) { + MOD_INC_USE_COUNT; + } + zf_is_open = 1; + + spin_unlock(&zf_lock); + + zf_timer_on(); + + return 0; + default: + return -ENODEV; + } +} + +static int zf_close(struct inode *inode, struct file *file) +{ + if(minor(inode->i_rdev) == WATCHDOG_MINOR){ + + if(zf_expect_close){ + zf_timer_off(); + } else { + del_timer(&zf_timer); + printk(KERN_ERR PFX ": device file closed unexpectedly. Will not stop the WDT!\n"); + } + + spin_lock(&zf_lock); + zf_is_open = 0; + spin_unlock(&zf_lock); + + zf_expect_close = 0; + } + + return 0; +} + +/* + * Notifier for system down + */ + +static int zf_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if(code == SYS_DOWN || code == SYS_HALT){ + zf_timer_off(); + } + + return NOTIFY_DONE; +} + + + + +static struct file_operations zf_fops = { + .owner = THIS_MODULE, + .read = zf_read, + .write = zf_write, + .ioctl = zf_ioctl, + .open = zf_open, + .release = zf_close, +}; + +static struct miscdevice zf_miscdev = { + WATCHDOG_MINOR, + "watchdog", + &zf_fops +}; + + +/* + * The device needs to learn about soft shutdowns in order to + * turn the timebomb registers off. + */ +static struct notifier_block zf_notifier = { + zf_notify_sys, + NULL, + 0 +}; + +static void __init zf_show_action(int act) +{ + char *str[] = { "RESET", "SMI", "NMI", "SCI" }; + + printk(KERN_INFO PFX ": Watchdog using action = %s\n", str[act]); +} + +static int __init zf_init(void) +{ + int ret; + + printk(KERN_INFO PFX ": MachZ ZF-Logic Watchdog driver initializing.\n"); + + ret = zf_get_ZFL_version(); + printk("%#x\n", ret); + if((!ret) || (ret != 0xffff)){ + printk(KERN_WARNING PFX ": no ZF-Logic found\n"); + return -ENODEV; + } + + if((action <= 3) && (action >= 0)){ + zf_action = zf_action>>action; + } else + action = 0; + + zf_show_action(action); + + spin_lock_init(&zf_lock); + spin_lock_init(&zf_port_lock); + + ret = misc_register(&zf_miscdev); + if (ret){ + printk(KERN_ERR "can't misc_register on minor=%d\n", + WATCHDOG_MINOR); + goto out; + } + + if(!request_region(ZF_IOBASE, 3, "MachZ ZFL WDT")){ + printk(KERN_ERR "cannot reserve I/O ports at %d\n", + ZF_IOBASE); + ret = -EBUSY; + goto no_region; + } + + ret = register_reboot_notifier(&zf_notifier); + if(ret){ + printk(KERN_ERR "can't register reboot notifier (err=%d)\n", + ret); + goto no_reboot; + } + + zf_set_status(0); + zf_set_control(0); + + /* this is the timer that will do the hard work */ + init_timer(&zf_timer); + zf_timer.function = zf_ping; + zf_timer.data = 0; + + return 0; + +no_reboot: + release_region(ZF_IOBASE, 3); +no_region: + misc_deregister(&zf_miscdev); +out: + return ret; +} + + +void __exit zf_exit(void) +{ + zf_timer_off(); + + misc_deregister(&zf_miscdev); + unregister_reboot_notifier(&zf_notifier); + release_region(ZF_IOBASE, 3); +} + +module_init(zf_init); +module_exit(zf_exit); diff -Nru a/drivers/char/watchdog/mixcomwd.c b/drivers/char/watchdog/mixcomwd.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/watchdog/mixcomwd.c Fri Nov 22 13:41:18 2002 @@ -0,0 +1,282 @@ +/* + * MixCom Watchdog: A Simple Hardware Watchdog Device + * Based on Softdog driver by Alan Cox and PC Watchdog driver by Ken Hollis + * + * Author: Gergely Madarasz + * + * Copyright (c) 1999 ITConsult-Pro Co. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Version 0.1 (99/04/15): + * - first version + * + * Version 0.2 (99/06/16): + * - added kernel timer watchdog ping after close + * since the hardware does not support watchdog shutdown + * + * Version 0.3 (99/06/21): + * - added WDIOC_GETSTATUS and WDIOC_GETSUPPORT ioctl calls + * + * Version 0.3.1 (99/06/22): + * - allow module removal while internal timer is active, + * print warning about probable reset + * + * Version 0.4 (99/11/15): + * - support for one more type board + * + * Version 0.5 (2001/12/14) Matt Domsch + * - added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT + * + */ + +#define VERSION "0.5" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int mixcomwd_ioports[] = { 0x180, 0x280, 0x380, 0x000 }; + +#define MIXCOM_WATCHDOG_OFFSET 0xc10 +#define MIXCOM_ID 0x11 +#define FLASHCOM_WATCHDOG_OFFSET 0x4 +#define FLASHCOM_ID 0x18 + +static long mixcomwd_opened; /* long req'd for setbit --RR */ + +static int watchdog_port; +static int mixcomwd_timer_alive; +static struct timer_list mixcomwd_timer = TIMER_INITIALIZER(NULL, 0, 0); + +#ifdef CONFIG_WATCHDOG_NOWAYOUT +static int nowayout = 1; +#else +static int nowayout = 0; +#endif + +MODULE_PARM(nowayout,"i"); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); + +static void mixcomwd_ping(void) +{ + outb_p(55,watchdog_port); + return; +} + +static void mixcomwd_timerfun(unsigned long d) +{ + mixcomwd_ping(); + + mod_timer(&mixcomwd_timer,jiffies+ 5*HZ); +} + +/* + * Allow only one person to hold it open + */ + +static int mixcomwd_open(struct inode *inode, struct file *file) +{ + if(test_and_set_bit(0,&mixcomwd_opened)) { + return -EBUSY; + } + mixcomwd_ping(); + + if (nowayout) { + MOD_INC_USE_COUNT; + } else { + if(mixcomwd_timer_alive) { + del_timer(&mixcomwd_timer); + mixcomwd_timer_alive=0; + } + } + return 0; +} + +static int mixcomwd_release(struct inode *inode, struct file *file) +{ + + if (!nowayout) { + if(mixcomwd_timer_alive) { + printk(KERN_ERR "mixcomwd: release called while internal timer alive"); + return -EBUSY; + } + init_timer(&mixcomwd_timer); + mixcomwd_timer.expires=jiffies + 5 * HZ; + mixcomwd_timer.function=mixcomwd_timerfun; + mixcomwd_timer.data=0; + mixcomwd_timer_alive=1; + add_timer(&mixcomwd_timer); + } + clear_bit(0,&mixcomwd_opened); + return 0; +} + + +static ssize_t mixcomwd_write(struct file *file, const char *data, size_t len, loff_t *ppos) +{ + if (ppos != &file->f_pos) { + return -ESPIPE; + } + + if(len) + { + mixcomwd_ping(); + return 1; + } + return 0; +} + +static int mixcomwd_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + int status; + static struct watchdog_info ident = { + WDIOF_KEEPALIVEPING, 1, "MixCOM watchdog" + }; + + switch(cmd) + { + case WDIOC_GETSTATUS: + status=mixcomwd_opened; + if (!nowayout) { + status|=mixcomwd_timer_alive; + } + if (copy_to_user((int *)arg, &status, sizeof(int))) { + return -EFAULT; + } + break; + case WDIOC_GETSUPPORT: + if (copy_to_user((struct watchdog_info *)arg, &ident, + sizeof(ident))) { + return -EFAULT; + } + break; + case WDIOC_KEEPALIVE: + mixcomwd_ping(); + break; + default: + return -ENOTTY; + } + return 0; +} + +static struct file_operations mixcomwd_fops= +{ + .owner = THIS_MODULE, + .write = mixcomwd_write, + .ioctl = mixcomwd_ioctl, + .open = mixcomwd_open, + .release = mixcomwd_release, +}; + +static struct miscdevice mixcomwd_miscdev= +{ + WATCHDOG_MINOR, + "watchdog", + &mixcomwd_fops +}; + +static int __init mixcomwd_checkcard(int port) +{ + int id; + + if(check_region(port+MIXCOM_WATCHDOG_OFFSET,1)) { + return 0; + } + + id=inb_p(port + MIXCOM_WATCHDOG_OFFSET) & 0x3f; + if(id!=MIXCOM_ID) { + return 0; + } + return 1; +} + +static int __init flashcom_checkcard(int port) +{ + int id; + + if(check_region(port + FLASHCOM_WATCHDOG_OFFSET,1)) { + return 0; + } + + id=inb_p(port + FLASHCOM_WATCHDOG_OFFSET); + if(id!=FLASHCOM_ID) { + return 0; + } + return 1; + } + +static int __init mixcomwd_init(void) +{ + int i; + int ret; + int found=0; + + for (i = 0; !found && mixcomwd_ioports[i] != 0; i++) { + if (mixcomwd_checkcard(mixcomwd_ioports[i])) { + found = 1; + watchdog_port = mixcomwd_ioports[i] + MIXCOM_WATCHDOG_OFFSET; + } + } + + /* The FlashCOM card can be set up at 0x300 -> 0x378, in 0x8 jumps */ + for (i = 0x300; !found && i < 0x380; i+=0x8) { + if (flashcom_checkcard(i)) { + found = 1; + watchdog_port = i + FLASHCOM_WATCHDOG_OFFSET; + } + } + + if (!found) { + printk("mixcomwd: No card detected, or port not available.\n"); + return -ENODEV; + } + + if (!request_region(watchdog_port,1,"MixCOM watchdog")) + return -EIO; + + ret = misc_register(&mixcomwd_miscdev); + if (ret) + { + release_region(watchdog_port, 1); + return ret; + } + + printk(KERN_INFO "MixCOM watchdog driver v%s, watchdog port at 0x%3x\n",VERSION,watchdog_port); + + return 0; +} + +static void __exit mixcomwd_exit(void) +{ + if (!nowayout) { + if(mixcomwd_timer_alive) { + printk(KERN_WARNING "mixcomwd: I quit now, hardware will" + " probably reboot!\n"); + del_timer(&mixcomwd_timer); + mixcomwd_timer_alive=0; + } + } + release_region(watchdog_port,1); + misc_deregister(&mixcomwd_miscdev); +} + +module_init(mixcomwd_init); +module_exit(mixcomwd_exit); + +MODULE_LICENSE("GPL"); diff -Nru a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/watchdog/pcwd.c Fri Nov 22 13:41:17 2002 @@ -0,0 +1,672 @@ +/* + * PC Watchdog Driver + * by Ken Hollis (khollis@bitgate.com) + * + * Permission granted from Simon Machell (73244.1270@compuserve.com) + * Written for the Linux Kernel, and GPLed by Ken Hollis + * + * 960107 Added request_region routines, modulized the whole thing. + * 960108 Fixed end-of-file pointer (Thanks to Dan Hollis), added + * WD_TIMEOUT define. + * 960216 Added eof marker on the file, and changed verbose messages. + * 960716 Made functional and cosmetic changes to the source for + * inclusion in Linux 2.0.x kernels, thanks to Alan Cox. + * 960717 Removed read/seek routines, replaced with ioctl. Also, added + * check_region command due to Alan's suggestion. + * 960821 Made changes to compile in newer 2.0.x kernels. Added + * "cold reboot sense" entry. + * 960825 Made a few changes to code, deleted some defines and made + * typedefs to replace them. Made heartbeat reset only available + * via ioctl, and removed the write routine. + * 960828 Added new items for PC Watchdog Rev.C card. + * 960829 Changed around all of the IOCTLs, added new features, + * added watchdog disable/re-enable routines. Added firmware + * version reporting. Added read routine for temperature. + * Removed some extra defines, added an autodetect Revision + * routine. + * 961006 Revised some documentation, fixed some cosmetic bugs. Made + * drivers to panic the system if it's overheating at bootup. + * 961118 Changed some verbiage on some of the output, tidied up + * code bits, and added compatibility to 2.1.x. + * 970912 Enabled board on open and disable on close. + * 971107 Took account of recent VFS changes (broke read). + * 971210 Disable board on initialisation in case board already ticking. + * 971222 Changed open/close for temperature handling + * Michael Meskes . + * 980112 Used minor numbers from include/linux/miscdevice.h + * 990403 Clear reset status after reading control status register in + * pcwd_showprevstate(). [Marc Boucher ] + * 990605 Made changes to code to support Firmware 1.22a, added + * fairly useless proc entry. + * 990610 removed said useless proc code for the merge + * 000403 Removed last traces of proc code. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* + * These are the auto-probe addresses available. + * + * Revision A only uses ports 0x270 and 0x370. Revision C introduced 0x350. + * Revision A has an address range of 2 addresses, while Revision C has 3. + */ +static int pcwd_ioports[] = { 0x270, 0x350, 0x370, 0x000 }; + +#define WD_VER "1.10 (06/05/99)" + +/* + * It should be noted that PCWD_REVISION_B was removed because A and B + * are essentially the same types of card, with the exception that B + * has temperature reporting. Since I didn't receive a Rev.B card, + * the Rev.B card is not supported. (It's a good thing too, as they + * are no longer in production.) + */ +#define PCWD_REVISION_A 1 +#define PCWD_REVISION_C 2 + +#define WD_TIMEOUT 3 /* 1 1/2 seconds for a timeout */ + +/* + * These are the defines for the PC Watchdog card, revision A. + */ +#define WD_WDRST 0x01 /* Previously reset state */ +#define WD_T110 0x02 /* Temperature overheat sense */ +#define WD_HRTBT 0x04 /* Heartbeat sense */ +#define WD_RLY2 0x08 /* External relay triggered */ +#define WD_SRLY2 0x80 /* Software external relay triggered */ + +static int current_readport, revision, temp_panic; +static atomic_t open_allowed = ATOMIC_INIT(1); +static int initial_status, supports_temp, mode_debug; +static spinlock_t io_lock; + +/* + * PCWD_CHECKCARD + * + * This routine checks the "current_readport" to see if the card lies there. + * If it does, it returns accordingly. + */ +static int __init pcwd_checkcard(void) +{ + int card_dat, prev_card_dat, found = 0, count = 0, done = 0; + + card_dat = 0x00; + prev_card_dat = 0x00; + + prev_card_dat = inb(current_readport); + if (prev_card_dat == 0xFF) + return 0; + + while(count < WD_TIMEOUT) { + + /* Read the raw card data from the port, and strip off the + first 4 bits */ + + card_dat = inb_p(current_readport); + card_dat &= 0x000F; + + /* Sleep 1/2 second (or 500000 microseconds :) */ + + mdelay(500); + done = 0; + + /* If there's a heart beat in both instances, then this means we + found our card. This also means that either the card was + previously reset, or the computer was power-cycled. */ + + if ((card_dat & WD_HRTBT) && (prev_card_dat & WD_HRTBT) && + (!done)) { + found = 1; + done = 1; + break; + } + + /* If the card data is exactly the same as the previous card data, + it's safe to assume that we should check again. The manual says + that the heart beat will change every second (or the bit will + toggle), and this can be used to see if the card is there. If + the card was powered up with a cold boot, then the card will + not start blinking until 2.5 minutes after a reboot, so this + bit will stay at 1. */ + + if ((card_dat == prev_card_dat) && (!done)) { + count++; + done = 1; + } + + /* If the card data is toggling any bits, this means that the heart + beat was detected, or something else about the card is set. */ + + if ((card_dat != prev_card_dat) && (!done)) { + done = 1; + found = 1; + break; + } + + /* Otherwise something else strange happened. */ + + if (!done) + count++; + } + + return((found) ? 1 : 0); +} + +void pcwd_showprevstate(void) +{ + int card_status = 0x0000; + + if (revision == PCWD_REVISION_A) + initial_status = card_status = inb(current_readport); + else { + initial_status = card_status = inb(current_readport + 1); + outb_p(0x00, current_readport + 1); /* clear reset status */ + } + + if (revision == PCWD_REVISION_A) { + if (card_status & WD_WDRST) + printk("pcwd: Previous reboot was caused by the card.\n"); + + if (card_status & WD_T110) { + printk("pcwd: Card senses a CPU Overheat. Panicking!\n"); + panic("pcwd: CPU Overheat.\n"); + } + + if ((!(card_status & WD_WDRST)) && + (!(card_status & WD_T110))) + printk("pcwd: Cold boot sense.\n"); + } else { + if (card_status & 0x01) + printk("pcwd: Previous reboot was caused by the card.\n"); + + if (card_status & 0x04) { + printk("pcwd: Card senses a CPU Overheat. Panicking!\n"); + panic("pcwd: CPU Overheat.\n"); + } + + if ((!(card_status & 0x01)) && + (!(card_status & 0x04))) + printk("pcwd: Cold boot sense.\n"); + } +} + +static void pcwd_send_heartbeat(void) +{ + int wdrst_stat; + + wdrst_stat = inb_p(current_readport); + wdrst_stat &= 0x0F; + + wdrst_stat |= WD_WDRST; + + if (revision == PCWD_REVISION_A) + outb_p(wdrst_stat, current_readport + 1); + else + outb_p(wdrst_stat, current_readport); +} + +static int pcwd_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + int cdat, rv; + static struct watchdog_info ident= + { + WDIOF_OVERHEAT|WDIOF_CARDRESET, + 1, + "PCWD" + }; + + switch(cmd) { + default: + return -ENOTTY; + + case WDIOC_GETSUPPORT: + if(copy_to_user((void*)arg, &ident, sizeof(ident))) + return -EFAULT; + return 0; + + case WDIOC_GETSTATUS: + spin_lock(&io_lock); + if (revision == PCWD_REVISION_A) + cdat = inb(current_readport); + else + cdat = inb(current_readport + 1 ); + spin_unlock(&io_lock); + rv = 0; + + if (revision == PCWD_REVISION_A) + { + if (cdat & WD_WDRST) + rv |= WDIOF_CARDRESET; + + if (cdat & WD_T110) + { + rv |= WDIOF_OVERHEAT; + + if (temp_panic) + panic("pcwd: Temperature overheat trip!\n"); + } + } + else + { + if (cdat & 0x01) + rv |= WDIOF_CARDRESET; + + if (cdat & 0x04) + { + rv |= WDIOF_OVERHEAT; + + if (temp_panic) + panic("pcwd: Temperature overheat trip!\n"); + } + } + + if(put_user(rv, (int *) arg)) + return -EFAULT; + return 0; + + case WDIOC_GETBOOTSTATUS: + rv = 0; + + if (revision == PCWD_REVISION_A) + { + if (initial_status & WD_WDRST) + rv |= WDIOF_CARDRESET; + + if (initial_status & WD_T110) + rv |= WDIOF_OVERHEAT; + } + else + { + if (initial_status & 0x01) + rv |= WDIOF_CARDRESET; + + if (initial_status & 0x04) + rv |= WDIOF_OVERHEAT; + } + + if(put_user(rv, (int *) arg)) + return -EFAULT; + return 0; + + case WDIOC_GETTEMP: + + rv = 0; + if ((supports_temp) && (mode_debug == 0)) + { + spin_lock(&io_lock); + rv = inb(current_readport); + spin_unlock(&io_lock); + if(put_user(rv, (int*) arg)) + return -EFAULT; + } else if(put_user(rv, (int*) arg)) + return -EFAULT; + return 0; + + case WDIOC_SETOPTIONS: + if (revision == PCWD_REVISION_C) + { + if(copy_from_user(&rv, (int*) arg, sizeof(int))) + return -EFAULT; + + if (rv & WDIOS_DISABLECARD) + { + spin_lock(&io_lock); + outb_p(0xA5, current_readport + 3); + outb_p(0xA5, current_readport + 3); + cdat = inb_p(current_readport + 2); + spin_unlock(&io_lock); + if ((cdat & 0x10) == 0) + { + printk("pcwd: Could not disable card.\n"); + return -EIO; + } + + return 0; + } + + if (rv & WDIOS_ENABLECARD) + { + spin_lock(&io_lock); + outb_p(0x00, current_readport + 3); + cdat = inb_p(current_readport + 2); + spin_unlock(&io_lock); + if (cdat & 0x10) + { + printk("pcwd: Could not enable card.\n"); + return -EIO; + } + return 0; + } + + if (rv & WDIOS_TEMPPANIC) + { + temp_panic = 1; + } + } + return -EINVAL; + + case WDIOC_KEEPALIVE: + pcwd_send_heartbeat(); + return 0; + } + + return 0; +} + +static ssize_t pcwd_write(struct file *file, const char *buf, size_t len, + loff_t *ppos) +{ + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + if (len) + { + pcwd_send_heartbeat(); + return 1; + } + return 0; +} + +static int pcwd_open(struct inode *ino, struct file *filep) +{ + switch (minor(ino->i_rdev)) + { + case WATCHDOG_MINOR: + if ( !atomic_dec_and_test(&open_allowed) ) + { + atomic_inc( &open_allowed ); + return -EBUSY; + } + MOD_INC_USE_COUNT; + /* Enable the port */ + if (revision == PCWD_REVISION_C) + { + spin_lock(&io_lock); + outb_p(0x00, current_readport + 3); + spin_unlock(&io_lock); + } + return(0); + case TEMP_MINOR: + return(0); + default: + return (-ENODEV); + } +} + +static ssize_t pcwd_read(struct file *file, char *buf, size_t count, + loff_t *ppos) +{ + unsigned short c; + unsigned char cp; + + /* Can't seek (pread) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + switch(minor(file->f_dentry->d_inode->i_rdev)) + { + case TEMP_MINOR: + /* + * Convert metric to Fahrenheit, since this was + * the decided 'standard' for this return value. + */ + + c = inb(current_readport); + cp = (c * 9 / 5) + 32; + if(copy_to_user(buf, &cp, 1)) + return -EFAULT; + return 1; + default: + return -EINVAL; + } +} + +static int pcwd_close(struct inode *ino, struct file *filep) +{ + if (minor(ino->i_rdev)==WATCHDOG_MINOR) + { +#ifndef CONFIG_WATCHDOG_NOWAYOUT + /* Disable the board */ + if (revision == PCWD_REVISION_C) { + spin_lock(&io_lock); + outb_p(0xA5, current_readport + 3); + outb_p(0xA5, current_readport + 3); + spin_unlock(&io_lock); + } + atomic_inc( &open_allowed ); +#endif + } + return 0; +} + +static inline void get_support(void) +{ + if (inb(current_readport) != 0xF0) + supports_temp = 1; +} + +static inline int get_revision(void) +{ + int r = PCWD_REVISION_C; + + spin_lock(&io_lock); + if ((inb(current_readport + 2) == 0xFF) || + (inb(current_readport + 3) == 0xFF)) + r=PCWD_REVISION_A; + spin_unlock(&io_lock); + + return r; +} + +static int __init send_command(int cmd) +{ + int i; + + outb_p(cmd, current_readport + 2); + mdelay(1); + + i = inb(current_readport); + i = inb(current_readport); + + return(i); +} + +static inline char *get_firmware(void) +{ + int i, found = 0, count = 0, one, ten, hund, minor; + char *ret; + + ret = kmalloc(6, GFP_KERNEL); + if(ret == NULL) + return NULL; + + while((count < 3) && (!found)) { + outb_p(0x80, current_readport + 2); + i = inb(current_readport); + + if (i == 0x00) + found = 1; + else if (i == 0xF3) + outb_p(0x00, current_readport + 2); + + udelay(400L); + count++; + } + + if (found) { + mode_debug = 1; + + one = send_command(0x81); + ten = send_command(0x82); + hund = send_command(0x83); + minor = send_command(0x84); + sprintf(ret, "%c.%c%c%c", one, ten, hund, minor); + } + else + sprintf(ret, "ERROR"); + + return(ret); +} + +static void debug_off(void) +{ + outb_p(0x00, current_readport + 2); + mode_debug = 0; +} + +static struct file_operations pcwd_fops = { + .owner = THIS_MODULE, + .read = pcwd_read, + .write = pcwd_write, + .ioctl = pcwd_ioctl, + .open = pcwd_open, + .release = pcwd_close, +}; + +static struct miscdevice pcwd_miscdev = { + WATCHDOG_MINOR, + "watchdog", + &pcwd_fops +}; + +static struct miscdevice temp_miscdev = { + TEMP_MINOR, + "temperature", + &pcwd_fops +}; + +static int __init pcwatchdog_init(void) +{ + int i, found = 0; + spin_lock_init(&io_lock); + + revision = PCWD_REVISION_A; + + printk("pcwd: v%s Ken Hollis (kenji@bitgate.com)\n", WD_VER); + + /* Initial variables */ + supports_temp = 0; + mode_debug = 0; + temp_panic = 0; + initial_status = 0x0000; + +#ifndef PCWD_BLIND + for (i = 0; pcwd_ioports[i] != 0; i++) { + current_readport = pcwd_ioports[i]; + + if (pcwd_checkcard()) { + found = 1; + break; + } + } + + if (!found) { + printk("pcwd: No card detected, or port not available.\n"); + return(-EIO); + } +#endif + +#ifdef PCWD_BLIND + current_readport = PCWD_BLIND; +#endif + + get_support(); + revision = get_revision(); + + if (revision == PCWD_REVISION_A) + printk("pcwd: PC Watchdog (REV.A) detected at port 0x%03x\n", current_readport); + else if (revision == PCWD_REVISION_C) + printk("pcwd: PC Watchdog (REV.C) detected at port 0x%03x (Firmware version: %s)\n", + current_readport, get_firmware()); + else { + /* Should NEVER happen, unless get_revision() fails. */ + printk("pcwd: Unable to get revision.\n"); + return -1; + } + + if (supports_temp) + printk("pcwd: Temperature Option Detected.\n"); + + debug_off(); + + pcwd_showprevstate(); + + /* Disable the board */ + if (revision == PCWD_REVISION_C) { + outb_p(0xA5, current_readport + 3); + outb_p(0xA5, current_readport + 3); + } + + if (misc_register(&pcwd_miscdev)) + return -ENODEV; + + if (supports_temp) + if (misc_register(&temp_miscdev)) { + misc_deregister(&pcwd_miscdev); + return -ENODEV; + } + + + if (revision == PCWD_REVISION_A) { + if (!request_region(current_readport, 2, "PCWD Rev.A (Berkshire)")) { + misc_deregister(&pcwd_miscdev); + if (supports_temp) + misc_deregister(&pcwd_miscdev); + return -EIO; + } + } + else + if (!request_region(current_readport, 4, "PCWD Rev.C (Berkshire)")) { + misc_deregister(&pcwd_miscdev); + if (supports_temp) + misc_deregister(&pcwd_miscdev); + return -EIO; + } + + return 0; +} + +static void __exit pcwatchdog_exit(void) +{ + misc_deregister(&pcwd_miscdev); + /* Disable the board */ + if (revision == PCWD_REVISION_C) { + outb_p(0xA5, current_readport + 3); + outb_p(0xA5, current_readport + 3); + } + if (supports_temp) + misc_deregister(&temp_miscdev); + + release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4); +} + +module_init(pcwatchdog_init); +module_exit(pcwatchdog_exit); + +MODULE_LICENSE("GPL"); + diff -Nru a/drivers/char/watchdog/sbc60xxwdt.c b/drivers/char/watchdog/sbc60xxwdt.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/watchdog/sbc60xxwdt.c Fri Nov 22 13:41:21 2002 @@ -0,0 +1,354 @@ +/* + * 60xx Single Board Computer Watchdog Timer driver for Linux 2.2.x + * + * Based on acquirewdt.c by Alan Cox. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * The author does NOT admit liability nor provide warranty for + * any of this software. This material is provided "AS-IS" in + * the hope that it may be useful for others. + * + * (c) Copyright 2000 Jakob Oestergaard + * + * 12/4 - 2000 [Initial revision] + * 25/4 - 2000 Added /dev/watchdog support + * 09/5 - 2001 [smj@oro.net] fixed fop_write to "return 1" on success + * + * + * Theory of operation: + * A Watchdog Timer (WDT) is a hardware circuit that can + * reset the computer system in case of a software fault. + * You probably knew that already. + * + * Usually a userspace daemon will notify the kernel WDT driver + * via the /proc/watchdog special device file that userspace is + * still alive, at regular intervals. When such a notification + * occurs, the driver will usually tell the hardware watchdog + * that everything is in order, and that the watchdog should wait + * for yet another little while to reset the system. + * If userspace fails (RAM error, kernel bug, whatever), the + * notifications cease to occur, and the hardware watchdog will + * reset the system (causing a reboot) after the timeout occurs. + * + * This WDT driver is different from the other Linux WDT + * drivers in several ways: + * *) The driver will ping the watchdog by itself, because this + * particular WDT has a very short timeout (one second) and it + * would be insane to count on any userspace daemon always + * getting scheduled within that time frame. + * *) This driver expects the userspace daemon to send a specific + * character code ('V') to /dev/watchdog before closing the + * /dev/watchdog file. If the userspace daemon closes the file + * without sending this special character, the driver will assume + * that the daemon (and userspace in general) died, and will + * stop pinging the WDT without disabling it first. This will + * cause a reboot. + * + * Why `V' ? Well, `V' is the character in ASCII for the value 86, + * and we all know that 86 is _the_ most random number in the universe. + * Therefore it is the letter that has the slightest chance of occuring + * by chance, when the system becomes corrupted. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OUR_NAME "sbc60xxwdt" + +/* + * You must set these - The driver cannot probe for the settings + */ + +#define WDT_STOP 0x45 +#define WDT_START 0x443 + +/* + * The 60xx board can use watchdog timeout values from one second + * to several minutes. The default is one second, so if we reset + * the watchdog every ~250ms we should be safe. + */ + +#define WDT_INTERVAL (HZ/4+1) + +/* + * We must not require too good response from the userspace daemon. + * Here we require the userspace daemon to send us a heartbeat + * char to /dev/watchdog every 10 seconds. + * If the daemon pulses us every 5 seconds, we can still afford + * a 5 second scheduling delay on the (high priority) daemon. That + * should be sufficient for a box under any load. + */ + +#define WDT_HEARTBEAT (HZ * 10) + +static void wdt_timer_ping(unsigned long); +static struct timer_list timer; +static unsigned long next_heartbeat; +static int wdt_is_open; +static int wdt_expect_close; + +#ifdef CONFIG_WATCHDOG_NOWAYOUT +static int nowayout = 1; +#else +static int nowayout = 0; +#endif + +MODULE_PARM(nowayout,"i"); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); + +/* + * Whack the dog + */ + +static void wdt_timer_ping(unsigned long data) +{ + /* If we got a heartbeat pulse within the WDT_US_INTERVAL + * we agree to ping the WDT + */ + if(time_before(jiffies, next_heartbeat)) + { + /* Ping the WDT by reading from WDT_START */ + inb_p(WDT_START); + /* Re-set the timer interval */ + timer.expires = jiffies + WDT_INTERVAL; + add_timer(&timer); + } else { + printk(OUR_NAME ": Heartbeat lost! Will not ping the watchdog\n"); + } +} + +/* + * Utility routines + */ + +static void wdt_startup(void) +{ + next_heartbeat = jiffies + WDT_HEARTBEAT; + + /* Start the timer */ + timer.expires = jiffies + WDT_INTERVAL; + add_timer(&timer); + printk(OUR_NAME ": Watchdog timer is now enabled.\n"); +} + +static void wdt_turnoff(void) +{ + /* Stop the timer */ + del_timer(&timer); + inb_p(WDT_STOP); + printk(OUR_NAME ": Watchdog timer is now disabled...\n"); +} + + +/* + * /dev/watchdog handling + */ + +static ssize_t fop_write(struct file * file, const char * buf, size_t count, loff_t * ppos) +{ + /* We can't seek */ + if(ppos != &file->f_pos) + return -ESPIPE; + + /* See if we got the magic character */ + if(count) + { + size_t ofs; + + /* note: just in case someone wrote the magic character + * five months ago... */ + wdt_expect_close = 0; + + /* now scan */ + for(ofs = 0; ofs != count; ofs++) + { + char c; + if(get_user(c, buf+ofs)) + return -EFAULT; + if(c == 'V') + wdt_expect_close = 1; + } + /* Well, anyhow someone wrote to us, we should return that favour */ + next_heartbeat = jiffies + WDT_HEARTBEAT; + return 1; + } + return 0; +} + +static ssize_t fop_read(struct file * file, char * buf, size_t count, loff_t * ppos) +{ + /* No can do */ + return -EINVAL; +} + +static int fop_open(struct inode * inode, struct file * file) +{ + switch(minor(inode->i_rdev)) + { + case WATCHDOG_MINOR: + /* Just in case we're already talking to someone... */ + if(wdt_is_open) + return -EBUSY; + if (nowayout) { + MOD_INC_USE_COUNT; + } + /* Good, fire up the show */ + wdt_is_open = 1; + wdt_startup(); + return 0; + + default: + return -ENODEV; + } +} + +static int fop_close(struct inode * inode, struct file * file) +{ + if(minor(inode->i_rdev) == WATCHDOG_MINOR) + { + if(wdt_expect_close && !nowayout) + wdt_turnoff(); + else { + del_timer(&timer); + printk(OUR_NAME ": device file closed unexpectedly. Will not stop the WDT!\n"); + } + } + wdt_is_open = 0; + return 0; +} + +static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + static struct watchdog_info ident= + { + 0, + 1, + "SB60xx" + }; + + switch(cmd) + { + default: + return -ENOTTY; + case WDIOC_GETSUPPORT: + return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0; + case WDIOC_KEEPALIVE: + next_heartbeat = jiffies + WDT_HEARTBEAT; + return 0; + } +} + +static struct file_operations wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = fop_read, + .write = fop_write, + .open = fop_open, + .release = fop_close, + .ioctl = fop_ioctl +}; + +static struct miscdevice wdt_miscdev = { + WATCHDOG_MINOR, + "watchdog", + &wdt_fops +}; + +/* + * Notifier for system down + */ + +static int wdt_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if(code==SYS_DOWN || code==SYS_HALT) + wdt_turnoff(); + return NOTIFY_DONE; +} + +/* + * The WDT needs to learn about soft shutdowns in order to + * turn the timebomb registers off. + */ + +static struct notifier_block wdt_notifier= +{ + wdt_notify_sys, + 0, + 0 +}; + +static void __exit sbc60xxwdt_unload(void) +{ + wdt_turnoff(); + + /* Deregister */ + misc_deregister(&wdt_miscdev); + + unregister_reboot_notifier(&wdt_notifier); + release_region(WDT_START,1); + release_region(WDT_STOP,1); +} + +static int __init sbc60xxwdt_init(void) +{ + int rc = -EBUSY; + + if (!request_region(WDT_STOP, 1, "SBC 60XX WDT")) + goto err_out; + if (!request_region(WDT_START, 1, "SBC 60XX WDT")) + goto err_out_region1; + + init_timer(&timer); + timer.function = wdt_timer_ping; + timer.data = 0; + + rc = misc_register(&wdt_miscdev); + if (rc) + goto err_out_region2; + + rc = register_reboot_notifier(&wdt_notifier); + if (rc) + goto err_out_miscdev; + + printk(KERN_INFO OUR_NAME ": WDT driver for 60XX single board computer initialised.\n"); + + return 0; + +err_out_miscdev: + misc_deregister(&wdt_miscdev); +err_out_region2: + release_region(WDT_START,1); +err_out_region1: + release_region(WDT_STOP,1); +err_out: + return rc; +} + +module_init(sbc60xxwdt_init); +module_exit(sbc60xxwdt_unload); + +MODULE_LICENSE("GPL"); diff -Nru a/drivers/char/watchdog/scx200_wdt.c b/drivers/char/watchdog/scx200_wdt.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/watchdog/scx200_wdt.c Fri Nov 22 13:41:21 2002 @@ -0,0 +1,277 @@ +/* linux/drivers/char/scx200_wdt.c + + National Semiconductor SCx200 Watchdog support + + Copyright (c) 2001,2002 Christer Weinigel + + Som code taken from: + National Semiconductor PC87307/PC97307 (ala SC1200) WDT driver + (c) Copyright 2002 Zwane Mwaikambo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The author(s) of this software shall not be held liable for damages + of any nature resulting due to the use of this software. This + software is provided AS-IS with no warranties. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define NAME "scx200_wdt" + +MODULE_AUTHOR("Christer Weinigel "); +MODULE_DESCRIPTION("NatSemi SCx200 Watchdog Driver"); +MODULE_LICENSE("GPL"); + +#ifndef CONFIG_WATCHDOG_NOWAYOUT +#define CONFIG_WATCHDOG_NOWAYOUT 0 +#endif + +static int margin = 60; /* in seconds */ +MODULE_PARM(margin, "i"); +MODULE_PARM_DESC(margin, "Watchdog margin in seconds"); + +static int nowayout = CONFIG_WATCHDOG_NOWAYOUT; +MODULE_PARM(nowayout, "i"); +MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); + +static u16 wdto_restart; +static struct semaphore open_semaphore; +static unsigned expect_close; + +/* Bits of the WDCNFG register */ +#define W_ENABLE 0x00fa /* Enable watchdog */ +#define W_DISABLE 0x0000 /* Disable watchdog */ + +/* The scaling factor for the timer, this depends on the value of W_ENABLE */ +#define W_SCALE (32768/1024) + +static void scx200_wdt_ping(void) +{ + outw(wdto_restart, SCx200_CB_BASE + SCx200_WDT_WDTO); +} + +static void scx200_wdt_update_margin(void) +{ + printk(KERN_INFO NAME ": timer margin %d seconds\n", margin); + wdto_restart = margin * W_SCALE; +} + +static void scx200_wdt_enable(void) +{ + printk(KERN_DEBUG NAME ": enabling watchdog timer, wdto_restart = %d\n", + wdto_restart); + + outw(0, SCx200_CB_BASE + SCx200_WDT_WDTO); + outb(SCx200_WDT_WDSTS_WDOVF, SCx200_CB_BASE + SCx200_WDT_WDSTS); + outw(W_ENABLE, SCx200_CB_BASE + SCx200_WDT_WDCNFG); + + scx200_wdt_ping(); +} + +static void scx200_wdt_disable(void) +{ + printk(KERN_DEBUG NAME ": disabling watchdog timer\n"); + + outw(0, SCx200_CB_BASE + SCx200_WDT_WDTO); + outb(SCx200_WDT_WDSTS_WDOVF, SCx200_CB_BASE + SCx200_WDT_WDSTS); + outw(W_DISABLE, SCx200_CB_BASE + SCx200_WDT_WDCNFG); +} + +static int scx200_wdt_open(struct inode *inode, struct file *file) +{ + /* only allow one at a time */ + if (down_trylock(&open_semaphore)) + return -EBUSY; + scx200_wdt_enable(); + expect_close = 0; + + return 0; +} + +static int scx200_wdt_release(struct inode *inode, struct file *file) +{ + if (!expect_close) { + printk(KERN_WARNING NAME ": watchdog device closed unexpectedly, will not disable the watchdog timer\n"); + } else if (!nowayout) { + scx200_wdt_disable(); + } + up(&open_semaphore); + + return 0; +} + +static int scx200_wdt_notify_sys(struct notifier_block *this, + unsigned long code, void *unused) +{ + if (code == SYS_HALT || code == SYS_POWER_OFF) + if (!nowayout) + scx200_wdt_disable(); + + return NOTIFY_DONE; +} + +static struct notifier_block scx200_wdt_notifier = +{ + .notifier_call = scx200_wdt_notify_sys +}; + +static ssize_t scx200_wdt_write(struct file *file, const char *data, + size_t len, loff_t *ppos) +{ + if (ppos != &file->f_pos) + return -ESPIPE; + + /* check for a magic close character */ + if (len) + { + size_t i; + + scx200_wdt_ping(); + + expect_close = 0; + for (i = 0; i < len; ++i) { + char c; + if (get_user(c, data+i)) + return -EFAULT; + if (c == 'V') + expect_close = 1; + } + + return len; + } + + return 0; +} + +static int scx200_wdt_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + static struct watchdog_info ident = { + .identity = "NatSemi SCx200 Watchdog", + .firmware_version = 1, + .options = (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING), + }; + int new_margin; + + switch (cmd) { + default: + return -ENOTTY; + case WDIOC_GETSUPPORT: + if(copy_to_user((struct watchdog_info *)arg, &ident, + sizeof(ident))) + return -EFAULT; + return 0; + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + if (put_user(0, (int *)arg)) + return -EFAULT; + return 0; + case WDIOC_KEEPALIVE: + scx200_wdt_ping(); + return 0; + case WDIOC_SETTIMEOUT: + if (get_user(new_margin, (int *)arg)) + return -EFAULT; + if (new_margin < 1) + return -EINVAL; + margin = new_margin; + scx200_wdt_update_margin(); + scx200_wdt_ping(); + case WDIOC_GETTIMEOUT: + if (put_user(margin, (int *)arg)) + return -EFAULT; + return 0; + } +} + +static struct file_operations scx200_wdt_fops = { + .owner = THIS_MODULE, + .write = scx200_wdt_write, + .ioctl = scx200_wdt_ioctl, + .open = scx200_wdt_open, + .release = scx200_wdt_release, +}; + +static struct miscdevice scx200_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = NAME, + .fops = &scx200_wdt_fops, +}; + +static int __init scx200_wdt_init(void) +{ + int r; + + printk(KERN_DEBUG NAME ": NatSemi SCx200 Watchdog Driver\n"); + + /* First check that this really is a NatSemi SCx200 CPU */ + if ((pci_find_device(PCI_VENDOR_ID_NS, + PCI_DEVICE_ID_NS_SCx200_BRIDGE, + NULL)) == NULL) + return -ENODEV; + + /* More sanity checks, verify that the configuration block is there */ + if (!scx200_cb_probe(SCx200_CB_BASE)) { + printk(KERN_WARNING NAME ": no configuration block found\n"); + return -ENODEV; + } + + if (!request_region(SCx200_CB_BASE + SCx200_WDT_OFFSET, + SCx200_WDT_SIZE, + "NatSemi SCx200 Watchdog")) { + printk(KERN_WARNING NAME ": watchdog I/O region busy\n"); + return -EBUSY; + } + + scx200_wdt_update_margin(); + scx200_wdt_disable(); + + sema_init(&open_semaphore, 1); + + r = misc_register(&scx200_wdt_miscdev); + if (r) + return r; + + r = register_reboot_notifier(&scx200_wdt_notifier); + if (r) { + printk(KERN_ERR NAME ": unable to register reboot notifier"); + misc_deregister(&scx200_wdt_miscdev); + return r; + } + + return 0; +} + +static void __exit scx200_wdt_cleanup(void) +{ + unregister_reboot_notifier(&scx200_wdt_notifier); + misc_deregister(&scx200_wdt_miscdev); + release_region(SCx200_CB_BASE + SCx200_WDT_OFFSET, + SCx200_WDT_SIZE); +} + +module_init(scx200_wdt_init); +module_exit(scx200_wdt_cleanup); + +/* + Local variables: + compile-command: "make -k -C ../.. SUBDIRS=drivers/char modules" + c-basic-offset: 8 + End: +*/ diff -Nru a/drivers/char/watchdog/shwdt.c b/drivers/char/watchdog/shwdt.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/watchdog/shwdt.c Fri Nov 22 13:41:18 2002 @@ -0,0 +1,417 @@ +/* + * drivers/char/shwdt.c + * + * Watchdog driver for integrated watchdog in the SuperH 3/4 processors. + * + * Copyright (C) 2001 Paul Mundt + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * 14-Dec-2001 Matt Domsch + * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#if defined(CONFIG_CPU_SH4) + #define WTCNT 0xffc00008 + #define WTCSR 0xffc0000c +#elif defined(CONFIG_CPU_SH3) + #define WTCNT 0xffffff84 + #define WTCSR 0xffffff86 +#else + #error "Can't use SH 3/4 watchdog on non-SH 3/4 processor." +#endif + +#define WTCNT_HIGH 0x5a00 +#define WTCSR_HIGH 0xa500 + +#define WTCSR_TME 0x80 +#define WTCSR_WT 0x40 +#define WTCSR_RSTS 0x20 +#define WTCSR_WOVF 0x10 +#define WTCSR_IOVF 0x08 +#define WTCSR_CKS2 0x04 +#define WTCSR_CKS1 0x02 +#define WTCSR_CKS0 0x01 + +/* + * CKS0-2 supports a number of clock division ratios. At the time the watchdog + * is enabled, it defaults to a 41 usec overflow period .. we overload this to + * something a little more reasonable, and really can't deal with anything + * lower than WTCSR_CKS_1024, else we drop back into the usec range. + * + * Clock Division Ratio Overflow Period + * -------------------------------------------- + * 1/32 (initial value) 41 usecs + * 1/64 82 usecs + * 1/128 164 usecs + * 1/256 328 usecs + * 1/512 656 usecs + * 1/1024 1.31 msecs + * 1/2048 2.62 msecs + * 1/4096 5.25 msecs + */ +#define WTCSR_CKS_32 0x00 +#define WTCSR_CKS_64 0x01 +#define WTCSR_CKS_128 0x02 +#define WTCSR_CKS_256 0x03 +#define WTCSR_CKS_512 0x04 +#define WTCSR_CKS_1024 0x05 +#define WTCSR_CKS_2048 0x06 +#define WTCSR_CKS_4096 0x07 + +/* + * Default clock division ratio is 5.25 msecs. Overload this at module load + * time. Any value not in the msec range will default to a timeout of one + * jiffy, which exceeds the usec overflow periods. + */ +static int clock_division_ratio = WTCSR_CKS_4096; + +#define msecs_to_jiffies(msecs) (jiffies + ((HZ * msecs + 999) / 1000)) +#define next_ping_period(cks) msecs_to_jiffies(cks - 4) +#define user_ping_period(cks) (next_ping_period(cks) * 10) + +static unsigned long sh_is_open = 0; +static struct watchdog_info sh_wdt_info; +static struct timer_list timer; +static unsigned long next_heartbeat; + +#ifdef CONFIG_WATCHDOG_NOWAYOUT +static int nowayout = 1; +#else +static int nowayout = 0; +#endif + +MODULE_PARM(nowayout,"i"); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); + +/** + * sh_wdt_write_cnt - Write to Counter + * + * @val: Value to write + * + * Writes the given value @val to the lower byte of the timer counter. + * The upper byte is set manually on each write. + */ +static void sh_wdt_write_cnt(__u8 val) +{ + ctrl_outw(WTCNT_HIGH | (__u16)val, WTCNT); +} + +/** + * sh_wdt_write_csr - Write to Control/Status Register + * + * @val: Value to write + * + * Writes the given value @val to the lower byte of the control/status + * register. The upper byte is set manually on each write. + */ +static void sh_wdt_write_csr(__u8 val) +{ + ctrl_outw(WTCSR_HIGH | (__u16)val, WTCSR); +} + +/** + * sh_wdt_start - Start the Watchdog + * + * Starts the watchdog. + */ +static void sh_wdt_start(void) +{ + timer.expires = next_ping_period(clock_division_ratio); + next_heartbeat = user_ping_period(clock_division_ratio); + add_timer(&timer); + + sh_wdt_write_csr(WTCSR_WT | WTCSR_CKS_4096); + sh_wdt_write_cnt(0); + sh_wdt_write_csr((ctrl_inb(WTCSR) | WTCSR_TME)); +} + +/** + * sh_wdt_stop - Stop the Watchdog + * + * Stops the watchdog. + */ +static void sh_wdt_stop(void) +{ + del_timer(&timer); + + sh_wdt_write_csr((ctrl_inb(WTCSR) & ~WTCSR_TME)); +} + +/** + * sh_wdt_ping - Ping the Watchdog + * + * @data: Unused + * + * Clears overflow bit, resets timer counter. + */ +static void sh_wdt_ping(unsigned long data) +{ + if (time_before(jiffies, next_heartbeat)) { + sh_wdt_write_csr((ctrl_inb(WTCSR) & ~WTCSR_IOVF)); + sh_wdt_write_cnt(0); + + timer.expires = next_ping_period(clock_division_ratio); + add_timer(&timer); + } +} + +/** + * sh_wdt_open - Open the Device + * + * @inode: inode of device + * @file: file handle of device + * + * Watchdog device is opened and started. + */ +static int sh_wdt_open(struct inode *inode, struct file *file) +{ + switch (minor(inode->i_rdev)) { + case WATCHDOG_MINOR: + if (test_and_set_bit(0, &sh_is_open)) + return -EBUSY; + + if (nowayout) { + MOD_INC_USE_COUNT; + } + + sh_wdt_start(); + + break; + default: + return -ENODEV; + } + + return 0; +} + +/** + * sh_wdt_close - Close the Device + * + * @inode: inode of device + * @file: file handle of device + * + * Watchdog device is closed and stopped. + */ +static int sh_wdt_close(struct inode *inode, struct file *file) +{ + if (minor(inode->i_rdev) == WATCHDOG_MINOR) { + if (!nowayout) { + sh_wdt_stop(); + } + clear_bit(0, &sh_is_open); + } + + return 0; +} + +/** + * sh_wdt_read - Read from Device + * + * @file: file handle of device + * @buf: buffer to write to + * @count: length of buffer + * @ppos: offset + * + * Unsupported. + */ +static ssize_t sh_wdt_read(struct file *file, char *buf, + size_t count, loff_t *ppos) +{ + return -EINVAL; +} + +/** + * sh_wdt_write - Write to Device + * + * @file: file handle of device + * @buf: buffer to write + * @count: length of buffer + * @ppos: offset + * + * Pings the watchdog on write. + */ +static ssize_t sh_wdt_write(struct file *file, const char *buf, + size_t count, loff_t *ppos) +{ + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + if (count) { + next_heartbeat = user_ping_period(clock_division_ratio); + return 1; + } + + return 0; +} + +/** + * sh_wdt_ioctl - Query Device + * + * @inode: inode of device + * @file: file handle of device + * @cmd: watchdog command + * @arg: argument + * + * Query basic information from the device or ping it, as outlined by the + * watchdog API. + */ +static int sh_wdt_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case WDIOC_GETSUPPORT: + if (copy_to_user((struct watchdog_info *)arg, + &sh_wdt_info, + sizeof(sh_wdt_info))) { + return -EFAULT; + } + + break; + case WDIOC_GETSTATUS: + if (copy_to_user((int *)arg, + &sh_is_open, + sizeof(int))) { + return -EFAULT; + } + + break; + case WDIOC_KEEPALIVE: + next_heartbeat = user_ping_period(clock_division_ratio); + + break; + default: + return -ENOTTY; + } + + return 0; +} + +/** + * sh_wdt_notify_sys - Notifier Handler + * + * @this: notifier block + * @code: notifier event + * @unused: unused + * + * Handles specific events, such as turning off the watchdog during a + * shutdown event. + */ +static int sh_wdt_notify_sys(struct notifier_block *this, + unsigned long code, void *unused) +{ + if (code == SYS_DOWN || code == SYS_HALT) { + sh_wdt_stop(); + } + + return NOTIFY_DONE; +} + +static struct file_operations sh_wdt_fops = { + .owner = THIS_MODULE, + .read = sh_wdt_read, + .write = sh_wdt_write, + .ioctl = sh_wdt_ioctl, + .open = sh_wdt_open, + .release = sh_wdt_close, +}; + +static struct watchdog_info sh_wdt_info = { + WDIOF_KEEPALIVEPING, + 1, + "SH WDT", +}; + +static struct notifier_block sh_wdt_notifier = { + sh_wdt_notify_sys, + NULL, + 0 +}; + +static struct miscdevice sh_wdt_miscdev = { + WATCHDOG_MINOR, + "watchdog", + &sh_wdt_fops, +}; + +/** + * sh_wdt_init - Initialize module + * + * Registers the device and notifier handler. Actual device + * initialization is handled by sh_wdt_open(). + */ +static int __init sh_wdt_init(void) +{ + if (misc_register(&sh_wdt_miscdev)) { + printk(KERN_ERR "shwdt: Can't register misc device\n"); + return -EINVAL; + } + + if (!request_region(WTCNT, 1, "shwdt")) { + printk(KERN_ERR "shwdt: Can't request WTCNT region\n"); + misc_deregister(&sh_wdt_miscdev); + return -ENXIO; + } + + if (!request_region(WTCSR, 1, "shwdt")) { + printk(KERN_ERR "shwdt: Can't request WTCSR region\n"); + release_region(WTCNT, 1); + misc_deregister(&sh_wdt_miscdev); + return -ENXIO; + } + + if (register_reboot_notifier(&sh_wdt_notifier)) { + printk(KERN_ERR "shwdt: Can't register reboot notifier\n"); + release_region(WTCSR, 1); + release_region(WTCNT, 1); + misc_deregister(&sh_wdt_miscdev); + return -EINVAL; + } + + init_timer(&timer); + timer.function = sh_wdt_ping; + timer.data = 0; + + return 0; +} + +/** + * sh_wdt_exit - Deinitialize module + * + * Unregisters the device and notifier handler. Actual device + * deinitialization is handled by sh_wdt_close(). + */ +static void __exit sh_wdt_exit(void) +{ + unregister_reboot_notifier(&sh_wdt_notifier); + release_region(WTCSR, 1); + release_region(WTCNT, 1); + misc_deregister(&sh_wdt_miscdev); +} + +MODULE_AUTHOR("Paul Mundt "); +MODULE_DESCRIPTION("SH 3/4 watchdog driver"); +MODULE_LICENSE("GPL"); +MODULE_PARM(clock_division_ratio, "i"); +MODULE_PARM_DESC(clock_division_ratio, "Clock division ratio. Valid ranges are from 0x5 (1.31ms) to 0x7 (5.25ms). Defaults to 0x7."); + +module_init(sh_wdt_init); +module_exit(sh_wdt_exit); + diff -Nru a/drivers/char/watchdog/softdog.c b/drivers/char/watchdog/softdog.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/watchdog/softdog.c Fri Nov 22 13:41:19 2002 @@ -0,0 +1,196 @@ +/* + * SoftDog 0.06: A Software Watchdog Device + * + * (c) Copyright 1996 Alan Cox , All Rights Reserved. + * http://www.redhat.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 1995 Alan Cox + * + * Software only watchdog driver. Unlike its big brother the WDT501P + * driver this won't always recover a failed machine. + * + * 03/96: Angelo Haritsis : + * Modularised. + * Added soft_margin; use upon insmod to change the timer delay. + * NB: uses same minor as wdt (WATCHDOG_MINOR); we could use separate + * minors. + * + * 19980911 Alan Cox + * Made SMP safe for 2.3.x + * + * 20011214 Matt Domsch + * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT + * Didn't add timeout option, as soft_margin option already exists. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TIMER_MARGIN 60 /* (secs) Default is 1 minute */ + +static int soft_margin = TIMER_MARGIN; /* in seconds */ + +MODULE_PARM(soft_margin,"i"); + +#ifdef CONFIG_WATCHDOG_NOWAYOUT +static int nowayout = 1; +#else +static int nowayout = 0; +#endif + +MODULE_PARM(nowayout,"i"); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); +MODULE_LICENSE("GPL"); + +/* + * Our timer + */ + +static void watchdog_fire(unsigned long); + +static struct timer_list watchdog_ticktock = + TIMER_INITIALIZER(watchdog_fire, 0, 0); +static int timer_alive; + + +/* + * If the timer expires.. + */ + +static void watchdog_fire(unsigned long data) +{ +#ifdef ONLY_TESTING + printk(KERN_CRIT "SOFTDOG: Would Reboot.\n"); +#else + printk(KERN_CRIT "SOFTDOG: Initiating system reboot.\n"); + machine_restart(NULL); + printk("WATCHDOG: Reboot didn't ?????\n"); +#endif +} + +/* + * Allow only one person to hold it open + */ + +static int softdog_open(struct inode *inode, struct file *file) +{ + if(timer_alive) + return -EBUSY; + if (nowayout) { + MOD_INC_USE_COUNT; + } + /* + * Activate timer + */ + mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ)); + timer_alive=1; + return 0; +} + +static int softdog_release(struct inode *inode, struct file *file) +{ + /* + * Shut off the timer. + * Lock it in if it's a module and we set nowayout + */ + if(!nowayout) { + del_timer(&watchdog_ticktock); + } + timer_alive=0; + return 0; +} + +static ssize_t softdog_write(struct file *file, const char *data, size_t len, loff_t *ppos) +{ + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + /* + * Refresh the timer. + */ + if(len) { + mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ)); + return 1; + } + return 0; +} + +static int softdog_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + static struct watchdog_info ident = { + identity: "Software Watchdog", + }; + switch (cmd) { + default: + return -ENOTTY; + case WDIOC_GETSUPPORT: + if(copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))) + return -EFAULT; + return 0; + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0,(int *)arg); + case WDIOC_KEEPALIVE: + mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ)); + return 0; + } +} + +static struct file_operations softdog_fops = { + owner: THIS_MODULE, + write: softdog_write, + ioctl: softdog_ioctl, + open: softdog_open, + release: softdog_release, +}; + +static struct miscdevice softdog_miscdev = { + minor: WATCHDOG_MINOR, + name: "watchdog", + fops: &softdog_fops, +}; + +static char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.06, soft_margin: %d sec, nowayout: %d\n"; + +static int __init watchdog_init(void) +{ + int ret; + + ret = misc_register(&softdog_miscdev); + + if (ret) + return ret; + + printk(banner, soft_margin, nowayout); + + return 0; +} + +static void __exit watchdog_exit(void) +{ + misc_deregister(&softdog_miscdev); +} + +module_init(watchdog_init); +module_exit(watchdog_exit); diff -Nru a/drivers/char/watchdog/w83877f_wdt.c b/drivers/char/watchdog/w83877f_wdt.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/watchdog/w83877f_wdt.c Fri Nov 22 13:41:21 2002 @@ -0,0 +1,366 @@ +/* + * W83877F Computer Watchdog Timer driver for Linux 2.4.x + * + * Based on acquirewdt.c by Alan Cox, + * and sbc60xxwdt.c by Jakob Oestergaard + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * The authors do NOT admit liability nor provide warranty for + * any of this software. This material is provided "AS-IS" in + * the hope that it may be useful for others. + * + * (c) Copyright 2001 Scott Jennings + * + * 4/19 - 2001 [Initial revision] + * 9/27 - 2001 Added spinlocking + * + * + * Theory of operation: + * A Watchdog Timer (WDT) is a hardware circuit that can + * reset the computer system in case of a software fault. + * You probably knew that already. + * + * Usually a userspace daemon will notify the kernel WDT driver + * via the /proc/watchdog special device file that userspace is + * still alive, at regular intervals. When such a notification + * occurs, the driver will usually tell the hardware watchdog + * that everything is in order, and that the watchdog should wait + * for yet another little while to reset the system. + * If userspace fails (RAM error, kernel bug, whatever), the + * notifications cease to occur, and the hardware watchdog will + * reset the system (causing a reboot) after the timeout occurs. + * + * This WDT driver is different from most other Linux WDT + * drivers in that the driver will ping the watchdog by itself, + * because this particular WDT has a very short timeout (1.6 + * seconds) and it would be insane to count on any userspace + * daemon always getting scheduled within that time frame. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OUR_NAME "w83877f_wdt" + +#define ENABLE_W83877F_PORT 0x3F0 +#define ENABLE_W83877F 0x87 +#define DISABLE_W83877F 0xAA +#define WDT_PING 0x443 +#define WDT_REGISTER 0x14 +#define WDT_ENABLE 0x9C +#define WDT_DISABLE 0x8C + +/* + * The W83877F seems to be fixed at 1.6s timeout (at least on the + * EMACS PC-104 board I'm using). If we reset the watchdog every + * ~250ms we should be safe. */ + +#define WDT_INTERVAL (HZ/4+1) + +/* + * We must not require too good response from the userspace daemon. + * Here we require the userspace daemon to send us a heartbeat + * char to /dev/watchdog every 30 seconds. + */ + +#define WDT_HEARTBEAT (HZ * 30) + +static void wdt_timer_ping(unsigned long); +static struct timer_list timer; +static unsigned long next_heartbeat; +static unsigned long wdt_is_open; +static int wdt_expect_close; +static spinlock_t wdt_spinlock; + +/* + * Whack the dog + */ + +static void wdt_timer_ping(unsigned long data) +{ + /* If we got a heartbeat pulse within the WDT_US_INTERVAL + * we agree to ping the WDT + */ + if(time_before(jiffies, next_heartbeat)) + { + /* Ping the WDT */ + spin_lock(&wdt_spinlock); + + /* Ping the WDT by reading from WDT_PING */ + inb_p(WDT_PING); + + /* Re-set the timer interval */ + timer.expires = jiffies + WDT_INTERVAL; + add_timer(&timer); + + spin_unlock(&wdt_spinlock); + + } else { + printk(OUR_NAME ": Heartbeat lost! Will not ping the watchdog\n"); + } +} + +/* + * Utility routines + */ + +static void wdt_change(int writeval) +{ + unsigned long flags; + spin_lock_irqsave(&wdt_spinlock, flags); + + /* buy some time */ + inb_p(WDT_PING); + + /* make W83877F available */ + outb_p(ENABLE_W83877F, ENABLE_W83877F_PORT); + outb_p(ENABLE_W83877F, ENABLE_W83877F_PORT); + + /* enable watchdog */ + outb_p(WDT_REGISTER, ENABLE_W83877F_PORT); + outb_p(writeval, ENABLE_W83877F_PORT+1); + + /* lock the W8387FF away */ + outb_p(DISABLE_W83877F, ENABLE_W83877F_PORT); + + spin_unlock_irqrestore(&wdt_spinlock, flags); +} + +static void wdt_startup(void) +{ + next_heartbeat = jiffies + WDT_HEARTBEAT; + + /* Start the timer */ + timer.expires = jiffies + WDT_INTERVAL; + add_timer(&timer); + + wdt_change(WDT_ENABLE); + + printk(OUR_NAME ": Watchdog timer is now enabled.\n"); +} + +static void wdt_turnoff(void) +{ + /* Stop the timer */ + del_timer(&timer); + + wdt_change(WDT_DISABLE); + + printk(OUR_NAME ": Watchdog timer is now disabled...\n"); +} + + +/* + * /dev/watchdog handling + */ + +static ssize_t fop_write(struct file * file, const char * buf, size_t count, loff_t * ppos) +{ + /* We can't seek */ + if(ppos != &file->f_pos) + return -ESPIPE; + + /* See if we got the magic character */ + if(count) + { + size_t ofs; + + /* note: just in case someone wrote the magic character + * five months ago... */ + wdt_expect_close = 0; + + /* now scan */ + for(ofs = 0; ofs != count; ofs++) + { + char c; + if (get_user(c, buf + ofs)) + return -EFAULT; + if (c == 'V') + wdt_expect_close = 1; + } + + /* someone wrote to us, we should restart timer */ + next_heartbeat = jiffies + WDT_HEARTBEAT; + return 1; + }; + return 0; +} + +static ssize_t fop_read(struct file * file, char * buf, size_t count, loff_t * ppos) +{ + /* No can do */ + return -EINVAL; +} + +static int fop_open(struct inode * inode, struct file * file) +{ + switch(minor(inode->i_rdev)) + { + case WATCHDOG_MINOR: + /* Just in case we're already talking to someone... */ + if(test_and_set_bit(0, &wdt_is_open)) { + return -EBUSY; + } + /* Good, fire up the show */ + wdt_startup(); + return 0; + + default: + return -ENODEV; + } +} + +static int fop_close(struct inode * inode, struct file * file) +{ + if(minor(inode->i_rdev) == WATCHDOG_MINOR) + { + if(wdt_expect_close) + wdt_turnoff(); + else { + del_timer(&timer); + printk(OUR_NAME ": device file closed unexpectedly. Will not stop the WDT!\n"); + } + } + wdt_is_open = 0; + return 0; +} + +static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + static struct watchdog_info ident= + { + 0, + 1, + "W83877F" + }; + + switch(cmd) + { + default: + return -ENOIOCTLCMD; + case WDIOC_GETSUPPORT: + return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0; + case WDIOC_KEEPALIVE: + next_heartbeat = jiffies + WDT_HEARTBEAT; + return 0; + } +} + +static struct file_operations wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = fop_read, + .write = fop_write, + .open = fop_open, + .release = fop_close, + .ioctl = fop_ioctl +}; + +static struct miscdevice wdt_miscdev = { + WATCHDOG_MINOR, + "watchdog", + &wdt_fops +}; + +/* + * Notifier for system down + */ + +static int wdt_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if(code==SYS_DOWN || code==SYS_HALT) + wdt_turnoff(); + return NOTIFY_DONE; +} + +/* + * The WDT needs to learn about soft shutdowns in order to + * turn the timebomb registers off. + */ + +static struct notifier_block wdt_notifier= +{ + wdt_notify_sys, + 0, + 0 +}; + +static void __exit w83877f_wdt_unload(void) +{ + wdt_turnoff(); + + /* Deregister */ + misc_deregister(&wdt_miscdev); + + unregister_reboot_notifier(&wdt_notifier); + release_region(WDT_PING,1); + release_region(ENABLE_W83877F_PORT,2); +} + +static int __init w83877f_wdt_init(void) +{ + int rc = -EBUSY; + + spin_lock_init(&wdt_spinlock); + + if (!request_region(ENABLE_W83877F_PORT, 2, "W83877F WDT")) + goto err_out; + if (!request_region(WDT_PING, 1, "W8387FF WDT")) + goto err_out_region1; + + init_timer(&timer); + timer.function = wdt_timer_ping; + timer.data = 0; + + rc = misc_register(&wdt_miscdev); + if (rc) + goto err_out_region2; + + rc = register_reboot_notifier(&wdt_notifier); + if (rc) + goto err_out_miscdev; + + printk(KERN_INFO OUR_NAME ": WDT driver for W83877F initialised.\n"); + + return 0; + +err_out_miscdev: + misc_deregister(&wdt_miscdev); +err_out_region2: + release_region(WDT_PING,1); +err_out_region1: + release_region(ENABLE_W83877F_PORT,2); +err_out: + return rc; +} + +module_init(w83877f_wdt_init); +module_exit(w83877f_wdt_unload); + +MODULE_AUTHOR("Scott and Bill Jennings"); +MODULE_DESCRIPTION("Driver for watchdog timer in w83877f chip"); +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; diff -Nru a/drivers/char/watchdog/wdt.c b/drivers/char/watchdog/wdt.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/watchdog/wdt.c Fri Nov 22 13:41:20 2002 @@ -0,0 +1,565 @@ +/* + * Industrial Computer Source WDT500/501 driver for Linux 2.1.x + * + * (c) Copyright 1996-1997 Alan Cox , All Rights Reserved. + * http://www.redhat.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 1995 Alan Cox + * + * Release 0.09. + * + * Fixes + * Dave Gregorich : Modularisation and minor bugs + * Alan Cox : Added the watchdog ioctl() stuff + * Alan Cox : Fixed the reboot problem (as noted by + * Matt Crocker). + * Alan Cox : Added wdt= boot option + * Alan Cox : Cleaned up copy/user stuff + * Tim Hockin : Added insmod parameters, comment cleanup + * Parameterized timeout + * Tigran Aivazian : Restructured wdt_init() to handle failures + * Matt Domsch : added nowayout and timeout module options + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "wd501p.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static unsigned long wdt_is_open; + +/* + * You must set these - there is no sane way to probe for this board. + * You can use wdt=x,y to set these now. + */ + +static int io=0x240; +static int irq=11; + +#define WD_TIMO (100*60) /* 1 minute */ + +static int timeout_val = WD_TIMO; /* value passed to card */ +static int timeout = 60; /* in seconds */ +MODULE_PARM(timeout,"i"); +MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=60)"); + +#ifdef CONFIG_WATCHDOG_NOWAYOUT +static int nowayout = 1; +#else +static int nowayout = 0; +#endif + +MODULE_PARM(nowayout,"i"); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); + +static void __init +wdt_validate_timeout(void) +{ + timeout_val = timeout * 100; +} + +#ifndef MODULE + +/** + * wdt_setup: + * @str: command line string + * + * Setup options. The board isn't really probe-able so we have to + * get the user to tell us the configuration. Sane people build it + * modular but the others come here. + */ + +static int __init wdt_setup(char *str) +{ + int ints[4]; + + str = get_options (str, ARRAY_SIZE(ints), ints); + + if (ints[0] > 0) + { + io = ints[1]; + if(ints[0] > 1) + irq = ints[2]; + } + + return 1; +} + +__setup("wdt=", wdt_setup); + +#endif /* !MODULE */ + +MODULE_PARM(io, "i"); +MODULE_PARM_DESC(io, "WDT io port (default=0x240)"); +MODULE_PARM(irq, "i"); +MODULE_PARM_DESC(irq, "WDT irq (default=11)"); + +/* + * Programming support + */ + +static void wdt_ctr_mode(int ctr, int mode) +{ + ctr<<=6; + ctr|=0x30; + ctr|=(mode<<1); + outb_p(ctr, WDT_CR); +} + +static void wdt_ctr_load(int ctr, int val) +{ + outb_p(val&0xFF, WDT_COUNT0+ctr); + outb_p(val>>8, WDT_COUNT0+ctr); +} + +/* + * Kernel methods. + */ + + +/** + * wdt_status: + * + * Extract the status information from a WDT watchdog device. There are + * several board variants so we have to know which bits are valid. Some + * bits default to one and some to zero in order to be maximally painful. + * + * we then map the bits onto the status ioctl flags. + */ + +static int wdt_status(void) +{ + /* + * Status register to bit flags + */ + + int flag=0; + unsigned char status=inb_p(WDT_SR); + status|=FEATUREMAP1; + status&=~FEATUREMAP2; + + if(!(status&WDC_SR_TGOOD)) + flag|=WDIOF_OVERHEAT; + if(!(status&WDC_SR_PSUOVER)) + flag|=WDIOF_POWEROVER; + if(!(status&WDC_SR_PSUUNDR)) + flag|=WDIOF_POWERUNDER; + if(!(status&WDC_SR_FANGOOD)) + flag|=WDIOF_FANFAULT; + if(status&WDC_SR_ISOI0) + flag|=WDIOF_EXTERN1; + if(status&WDC_SR_ISII1) + flag|=WDIOF_EXTERN2; + return flag; +} + +/** + * wdt_interrupt: + * @irq: Interrupt number + * @dev_id: Unused as we don't allow multiple devices. + * @regs: Unused. + * + * Handle an interrupt from the board. These are raised when the status + * map changes in what the board considers an interesting way. That means + * a failure condition occuring. + */ + +void wdt_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + /* + * Read the status register see what is up and + * then printk it. + */ + + unsigned char status=inb_p(WDT_SR); + + status|=FEATUREMAP1; + status&=~FEATUREMAP2; + + printk(KERN_CRIT "WDT status %d\n", status); + + if(!(status&WDC_SR_TGOOD)) + printk(KERN_CRIT "Overheat alarm.(%d)\n",inb_p(WDT_RT)); + if(!(status&WDC_SR_PSUOVER)) + printk(KERN_CRIT "PSU over voltage.\n"); + if(!(status&WDC_SR_PSUUNDR)) + printk(KERN_CRIT "PSU under voltage.\n"); + if(!(status&WDC_SR_FANGOOD)) + printk(KERN_CRIT "Possible fan fault.\n"); + if(!(status&WDC_SR_WCCR)) +#ifdef SOFTWARE_REBOOT +#ifdef ONLY_TESTING + printk(KERN_CRIT "Would Reboot.\n"); +#else + printk(KERN_CRIT "Initiating system reboot.\n"); + machine_restart(NULL); +#endif +#else + printk(KERN_CRIT "Reset in 5ms.\n"); +#endif +} + + +/** + * wdt_ping: + * + * Reload counter one with the watchdog timeout. We don't bother reloading + * the cascade counter. + */ + +static void wdt_ping(void) +{ + /* Write a watchdog value */ + inb_p(WDT_DC); + wdt_ctr_mode(1,2); + wdt_ctr_load(1,timeout_val); /* Timeout */ + outb_p(0, WDT_DC); +} + +/** + * wdt_write: + * @file: file handle to the watchdog + * @buf: buffer to write (unused as data does not matter here + * @count: count of bytes + * @ppos: pointer to the position to write. No seeks allowed + * + * A write to a watchdog device is defined as a keepalive signal. Any + * write of data will do, as we we don't define content meaning. + */ + +static ssize_t wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +{ + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + if(count) + { + wdt_ping(); + return 1; + } + return 0; +} + +/** + * wdt_read: + * @file: file handle to the watchdog board + * @buf: buffer to write 1 byte into + * @count: length of buffer + * @ptr: offset (no seek allowed) + * + * Read reports the temperature in degrees Fahrenheit. The API is in + * farenheit. It was designed by an imperial measurement luddite. + */ + +static ssize_t wdt_read(struct file *file, char *buf, size_t count, loff_t *ptr) +{ + unsigned short c=inb_p(WDT_RT); + unsigned char cp; + + /* Can't seek (pread) on this device */ + if (ptr != &file->f_pos) + return -ESPIPE; + + switch(minor(file->f_dentry->d_inode->i_rdev)) + { + case TEMP_MINOR: + c*=11; + c/=15; + cp=c+7; + if(copy_to_user(buf,&cp,1)) + return -EFAULT; + return 1; + default: + return -EINVAL; + } +} + +/** + * wdt_ioctl: + * @inode: inode of the device + * @file: file handle to the device + * @cmd: watchdog command + * @arg: argument pointer + * + * The watchdog API defines a common set of functions for all watchdogs + * according to their available features. We only actually usefully support + * querying capabilities and current status. + */ + +static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + static struct watchdog_info ident= + { + WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER + |WDIOF_EXTERN1|WDIOF_EXTERN2|WDIOF_FANFAULT, + 1, + "WDT500/501" + }; + + ident.options&=WDT_OPTION_MASK; /* Mask down to the card we have */ + switch(cmd) + { + default: + return -ENOTTY; + case WDIOC_GETSUPPORT: + return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0; + + case WDIOC_GETSTATUS: + return put_user(wdt_status(),(int *)arg); + case WDIOC_GETBOOTSTATUS: + return put_user(0, (int *)arg); + case WDIOC_KEEPALIVE: + wdt_ping(); + return 0; + } +} + +/** + * wdt_open: + * @inode: inode of device + * @file: file handle to device + * + * One of our two misc devices has been opened. The watchdog device is + * single open and on opening we load the counters. Counter zero is a + * 100Hz cascade, into counter 1 which downcounts to reboot. When the + * counter triggers counter 2 downcounts the length of the reset pulse + * which set set to be as long as possible. + */ + +static int wdt_open(struct inode *inode, struct file *file) +{ + switch(minor(inode->i_rdev)) + { + case WATCHDOG_MINOR: + if(test_and_set_bit(0, &wdt_is_open)) + return -EBUSY; + if (nowayout) { + MOD_INC_USE_COUNT; + } + /* + * Activate + */ + + inb_p(WDT_DC); /* Disable */ + wdt_ctr_mode(0,3); + wdt_ctr_mode(1,2); + wdt_ctr_mode(2,0); + wdt_ctr_load(0, 8948); /* count at 100Hz */ + wdt_ctr_load(1,timeout_val); /* Timeout */ + wdt_ctr_load(2,65535); + outb_p(0, WDT_DC); /* Enable */ + return 0; + case TEMP_MINOR: + return 0; + default: + return -ENODEV; + } +} + +/** + * wdt_close: + * @inode: inode to board + * @file: file handle to board + * + * The watchdog has a configurable API. There is a religious dispute + * between people who want their watchdog to be able to shut down and + * those who want to be sure if the watchdog manager dies the machine + * reboots. In the former case we disable the counters, in the latter + * case you have to open it again very soon. + */ + +static int wdt_release(struct inode *inode, struct file *file) +{ + if(minor(inode->i_rdev)==WATCHDOG_MINOR) + { + if (!nowayout) { + inb_p(WDT_DC); /* Disable counters */ + wdt_ctr_load(2,0); /* 0 length reset pulses now */ + } + clear_bit(0, &wdt_is_open); + } + return 0; +} + +/** + * notify_sys: + * @this: our notifier block + * @code: the event being reported + * @unused: unused + * + * Our notifier is called on system shutdowns. We want to turn the card + * off at reboot otherwise the machine will reboot again during memory + * test or worse yet during the following fsck. This would suck, in fact + * trust me - if it happens it does suck. + */ + +static int wdt_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if(code==SYS_DOWN || code==SYS_HALT) + { + /* Turn the card off */ + inb_p(WDT_DC); + wdt_ctr_load(2,0); + } + return NOTIFY_DONE; +} + +/* + * Kernel Interfaces + */ + + +static struct file_operations wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = wdt_read, + .write = wdt_write, + .ioctl = wdt_ioctl, + .open = wdt_open, + .release = wdt_release, +}; + +static struct miscdevice wdt_miscdev= +{ + WATCHDOG_MINOR, + "watchdog", + &wdt_fops +}; + +#ifdef CONFIG_WDT_501 +static struct miscdevice temp_miscdev= +{ + TEMP_MINOR, + "temperature", + &wdt_fops +}; +#endif + +/* + * The WDT card needs to learn about soft shutdowns in order to + * turn the timebomb registers off. + */ + +static struct notifier_block wdt_notifier= +{ + wdt_notify_sys, + NULL, + 0 +}; + +/** + * cleanup_module: + * + * Unload the watchdog. You cannot do this with any file handles open. + * If your watchdog is set to continue ticking on close and you unload + * it, well it keeps ticking. We won't get the interrupt but the board + * will not touch PC memory so all is fine. You just have to load a new + * module in 60 seconds or reboot. + */ + +static void __exit wdt_exit(void) +{ + misc_deregister(&wdt_miscdev); +#ifdef CONFIG_WDT_501 + misc_deregister(&temp_miscdev); +#endif + unregister_reboot_notifier(&wdt_notifier); + release_region(io,8); + free_irq(irq, NULL); +} + +/** + * wdt_init: + * + * Set up the WDT watchdog board. All we have to do is grab the + * resources we require and bitch if anyone beat us to them. + * The open() function will actually kick the board off. + */ + +static int __init wdt_init(void) +{ + int ret; + + wdt_validate_timeout(); + ret = misc_register(&wdt_miscdev); + if (ret) { + printk(KERN_ERR "wdt: can't misc_register on minor=%d\n", WATCHDOG_MINOR); + goto out; + } + ret = request_irq(irq, wdt_interrupt, SA_INTERRUPT, "wdt501p", NULL); + if(ret) { + printk(KERN_ERR "wdt: IRQ %d is not free.\n", irq); + goto outmisc; + } + if (!request_region(io, 8, "wdt501p")) { + printk(KERN_ERR "wdt: IO %X is not free.\n", io); + ret = -EBUSY; + goto outirq; + } + ret = register_reboot_notifier(&wdt_notifier); + if(ret) { + printk(KERN_ERR "wdt: can't register reboot notifier (err=%d)\n", ret); + goto outreg; + } + +#ifdef CONFIG_WDT_501 + ret = misc_register(&temp_miscdev); + if (ret) { + printk(KERN_ERR "wdt: can't misc_register (temp) on minor=%d\n", TEMP_MINOR); + goto outrbt; + } +#endif + + ret = 0; + printk(KERN_INFO "WDT500/501-P driver 0.07 at %X (Interrupt %d)\n", io, irq); +out: + return ret; + +#ifdef CONFIG_WDT_501 +outrbt: + unregister_reboot_notifier(&wdt_notifier); +#endif + +outreg: + release_region(io,8); +outirq: + free_irq(irq, NULL); +outmisc: + misc_deregister(&wdt_miscdev); + goto out; +} + +module_init(wdt_init); +module_exit(wdt_exit); + +MODULE_AUTHOR("Alan Cox"); +MODULE_DESCRIPTION("Driver for ISA ICS watchdog cards (WDT500/501)"); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/char/watchdog/wdt285.c b/drivers/char/watchdog/wdt285.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/watchdog/wdt285.c Fri Nov 22 13:41:18 2002 @@ -0,0 +1,193 @@ +/* + * Intel 21285 watchdog driver + * Copyright (c) Phil Blundell , 1998 + * + * based on + * + * SoftDog 0.05: A Software Watchdog Device + * + * (c) Copyright 1996 Alan Cox , All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* + * Define this to stop the watchdog actually rebooting the machine. + */ +#undef ONLY_TESTING + +#define TIMER_MARGIN 60 /* (secs) Default is 1 minute */ + +#define FCLK (50*1000*1000) /* 50MHz */ + +static int soft_margin = TIMER_MARGIN; /* in seconds */ +static int timer_alive; + +#ifdef ONLY_TESTING +/* + * If the timer expires.. + */ + +static void watchdog_fire(int irq, void *dev_id, struct pt_regs *regs) +{ + printk(KERN_CRIT "Watchdog: Would Reboot.\n"); + *CSR_TIMER4_CNTL = 0; + *CSR_TIMER4_CLR = 0; +} +#endif + +static void watchdog_ping(void) +{ + /* + * Refresh the timer. + */ + *CSR_TIMER4_LOAD = soft_margin * (FCLK / 256); +} + +/* + * Allow only one person to hold it open + */ + +static int watchdog_open(struct inode *inode, struct file *file) +{ + if(timer_alive) + return -EBUSY; + /* + * Ahead watchdog factor ten, Mr Sulu + */ + *CSR_TIMER4_CLR = 0; + watchdog_ping(); + *CSR_TIMER4_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD + | TIMER_CNTL_DIV256; +#ifdef ONLY_TESTING + request_irq(IRQ_TIMER4, watchdog_fire, 0, "watchdog", NULL); +#else + *CSR_SA110_CNTL |= 1 << 13; + MOD_INC_USE_COUNT; +#endif + timer_alive = 1; + return 0; +} + +static int watchdog_release(struct inode *inode, struct file *file) +{ +#ifdef ONLY_TESTING + free_irq(IRQ_TIMER4, NULL); + timer_alive = 0; +#else + /* + * It's irreversible! + */ +#endif + return 0; +} + +static ssize_t watchdog_write(struct file *file, const char *data, size_t len, loff_t *ppos) +{ + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + /* + * Refresh the timer. + */ + if(len) + { + watchdog_ping(); + return 1; + } + return 0; +} + +static int watchdog_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + int i; + static struct watchdog_info ident= + { + 0, + 0, + "Footbridge Watchdog" + }; + switch(cmd) + { + default: + return -ENOTTY; + case WDIOC_GETSUPPORT: + if(copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))) + return -EFAULT; + return 0; + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0,(int *)arg); + case WDIOC_KEEPALIVE: + watchdog_ping(); + return 0; + } +} + +static struct file_operations watchdog_fops= +{ + .owner = THIS_MODULE, + .write = watchdog_write, + .ioctl = watchdog_ioctl, + .open = watchdog_open, + .release = watchdog_release, +}; + +static struct miscdevice watchdog_miscdev= +{ + WATCHDOG_MINOR, + "watchdog", + &watchdog_fops +}; + +static int __init footbridge_watchdog_init(void) +{ + if (machine_is_netwinder()) + return -ENODEV; + + misc_register(&watchdog_miscdev); + printk("Footbridge Watchdog Timer: 0.01, timer margin: %d sec\n", + soft_margin); + if (machine_is_cats()) + printk("Warning: Watchdog reset may not work on this machine.\n"); + return 0; +} + +static void __exit footbridge_watchdog_exit(void) +{ + misc_deregister(&watchdog_miscdev); +} + +MODULE_AUTHOR("Phil Blundell "); +MODULE_DESCRIPTION("21285 watchdog driver"); +MODULE_LICENSE("GPL"); + +MODULE_PARM(soft_margin,"i"); +MODULE_PARM_DESC(soft_margin,"Watchdog timeout in seconds"); + +module_init(footbridge_watchdog_init); +module_exit(footbridge_watchdog_exit); diff -Nru a/drivers/char/watchdog/wdt977.c b/drivers/char/watchdog/wdt977.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/watchdog/wdt977.c Fri Nov 22 13:41:22 2002 @@ -0,0 +1,346 @@ +/* + * Wdt977 0.02: A Watchdog Device for Netwinder W83977AF chip + * + * (c) Copyright 1998 Rebel.com (Woody Suwalski ) + * + * ----------------------- + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * ----------------------- + * 14-Dec-2001 Matt Domsch + * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT + * 19-Dec-2001 Woody Suwalski: Netwinder fixes, ioctl interface + * 06-Jan-2002 Woody Suwalski: For compatibility, convert all timeouts + * from minutes to seconds. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define WATCHDOG_MINOR 130 + +#define DEFAULT_TIMEOUT 1 /* default timeout = 1 minute */ + +static int timeout = DEFAULT_TIMEOUT*60; /* TO in seconds from user */ +static int timeoutM = DEFAULT_TIMEOUT; /* timeout in minutes */ +static unsigned long timer_alive; +static int testmode; + +MODULE_PARM(timeout, "i"); +MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (60..15300), default=60"); +MODULE_PARM(testmode, "i"); +MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0"); + +#ifdef CONFIG_WATCHDOG_NOWAYOUT +static int nowayout = 1; +#else +static int nowayout = 0; +#endif + +MODULE_PARM(nowayout,"i"); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); + + +/* This is kicking the watchdog by simply re-writing the timeout to reg. 0xF2 */ +int kick_wdog(void) +{ + /* + * Refresh the timer. + */ + + /* unlock the SuperIO chip */ + outb(0x87,0x370); + outb(0x87,0x370); + + /* select device Aux2 (device=8) and kicks watchdog reg F2 */ + /* F2 has the timeout in minutes */ + + outb(0x07,0x370); + outb(0x08,0x371); + outb(0xF2,0x370); + outb(timeoutM,0x371); + + /* lock the SuperIO chip */ + outb(0xAA,0x370); + + return 0; +} + + +/* + * Allow only one person to hold it open + */ + +static int wdt977_open(struct inode *inode, struct file *file) +{ + + if( test_and_set_bit(0,&timer_alive) ) + return -EBUSY; + + /* convert seconds to minutes, rounding up */ + timeoutM = timeout + 59; + timeoutM /= 60; + + if (nowayout) + { + MOD_INC_USE_COUNT; + + /* do not permit disabling the watchdog by writing 0 to reg. 0xF2 */ + if (!timeoutM) timeoutM = DEFAULT_TIMEOUT; + } + + if (machine_is_netwinder()) + { + /* we have a hw bug somewhere, so each 977 minute is actually only 30sec + * this limits the max timeout to half of device max of 255 minutes... + */ + timeoutM += timeoutM; + } + + /* max timeout value = 255 minutes (0xFF). Write 0 to disable WatchDog. */ + if (timeoutM > 255) timeoutM = 255; + + /* convert seconds to minutes */ + printk(KERN_INFO "Wdt977 Watchdog activated: timeout = %d sec, nowayout = %i, testmode = %i.\n", + machine_is_netwinder() ? (timeoutM>>1)*60 : timeoutM*60, + nowayout, testmode); + + /* unlock the SuperIO chip */ + outb(0x87,0x370); + outb(0x87,0x370); + + /* select device Aux2 (device=8) and set watchdog regs F2, F3 and F4 + * F2 has the timeout in minutes + * F3 could be set to the POWER LED blink (with GP17 set to PowerLed) + * at timeout, and to reset timer on kbd/mouse activity (not impl.) + * F4 is used to just clear the TIMEOUT'ed state (bit 0) + */ + outb(0x07,0x370); + outb(0x08,0x371); + outb(0xF2,0x370); + outb(timeoutM,0x371); + outb(0xF3,0x370); + outb(0x00,0x371); /* another setting is 0E for kbd/mouse/LED */ + outb(0xF4,0x370); + outb(0x00,0x371); + + /* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */ + /* in test mode watch the bit 1 on F4 to indicate "triggered" */ + if (!testmode) + { + outb(0x07,0x370); + outb(0x07,0x371); + outb(0xE6,0x370); + outb(0x08,0x371); + } + + /* lock the SuperIO chip */ + outb(0xAA,0x370); + + return 0; +} + +static int wdt977_release(struct inode *inode, struct file *file) +{ + /* + * Shut off the timer. + * Lock it in if it's a module and we set nowayout + */ + if (!nowayout) + { + /* unlock the SuperIO chip */ + outb(0x87,0x370); + outb(0x87,0x370); + + /* select device Aux2 (device=8) and set watchdog regs F2,F3 and F4 + * F3 is reset to its default state + * F4 can clear the TIMEOUT'ed state (bit 0) - back to default + * We can not use GP17 as a PowerLed, as we use its usage as a RedLed + */ + outb(0x07,0x370); + outb(0x08,0x371); + outb(0xF2,0x370); + outb(0xFF,0x371); + outb(0xF3,0x370); + outb(0x00,0x371); + outb(0xF4,0x370); + outb(0x00,0x371); + outb(0xF2,0x370); + outb(0x00,0x371); + + /* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */ + outb(0x07,0x370); + outb(0x07,0x371); + outb(0xE6,0x370); + outb(0x08,0x371); + + /* lock the SuperIO chip */ + outb(0xAA,0x370); + + clear_bit(0,&timer_alive); + + printk(KERN_INFO "Wdt977 Watchdog: shutdown\n"); + } + return 0; +} + + +/* + * wdt977_write: + * @file: file handle to the watchdog + * @buf: buffer to write (unused as data does not matter here + * @count: count of bytes + * @ppos: pointer to the position to write. No seeks allowed + * + * A write to a watchdog device is defined as a keepalive signal. Any + * write of data will do, as we we don't define content meaning. + */ + +static ssize_t wdt977_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +{ + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + if(count) + { + kick_wdog(); + return 1; + } + return 0; +} + +/* + * wdt977_ioctl: + * @inode: inode of the device + * @file: file handle to the device + * @cmd: watchdog command + * @arg: argument pointer + * + * The watchdog API defines a common set of functions for all watchdogs + * according to their available features. + */ + +static int wdt977_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ +static struct watchdog_info ident = { + identity : "Winbond 83977" +}; + +int temp; + + switch(cmd) + { + default: + return -ENOTTY; + + case WDIOC_GETSUPPORT: + return copy_to_user((struct watchdog_info *)arg, &ident, + sizeof(ident)) ? -EFAULT : 0; + + case WDIOC_GETBOOTSTATUS: + return put_user(0, (int *) arg); + + case WDIOC_GETSTATUS: + /* unlock the SuperIO chip */ + outb(0x87,0x370); + outb(0x87,0x370); + + /* select device Aux2 (device=8) and read watchdog reg F4 */ + outb(0x07,0x370); + outb(0x08,0x371); + outb(0xF4,0x370); + temp = inb(0x371); + + /* lock the SuperIO chip */ + outb(0xAA,0x370); + + /* return info if "expired" in test mode */ + return put_user(temp & 1, (int *) arg); + + case WDIOC_KEEPALIVE: + kick_wdog(); + return 0; + + case WDIOC_SETTIMEOUT: + if (copy_from_user(&temp, (int *) arg, sizeof(int))) + return -EFAULT; + + /* convert seconds to minutes, rounding up */ + temp += 59; + temp /= 60; + + /* we have a hw bug somewhere, so each 977 minute is actually only 30sec + * this limits the max timeout to half of device max of 255 minutes... + */ + if (machine_is_netwinder()) + { + temp += temp; + } + + /* Sanity check */ + if (temp < 0 || temp > 255) + return -EINVAL; + + if (!temp && nowayout) + return -EINVAL; + + timeoutM = temp; + kick_wdog(); + return 0; + } +} + + +static struct file_operations wdt977_fops= +{ + .owner = THIS_MODULE, + .write = wdt977_write, + .ioctl = wdt977_ioctl, + .open = wdt977_open, + .release = wdt977_release, +}; + +static struct miscdevice wdt977_miscdev= +{ + WATCHDOG_MINOR, + "watchdog", + &wdt977_fops +}; + +static int __init nwwatchdog_init(void) +{ + if (!machine_is_netwinder()) + return -ENODEV; + + misc_register(&wdt977_miscdev); + printk(KERN_INFO "Wdt977 Watchdog sleeping.\n"); + return 0; +} + +static void __exit nwwatchdog_exit(void) +{ + misc_deregister(&wdt977_miscdev); +} + +module_init(nwwatchdog_init); +module_exit(nwwatchdog_exit); + +MODULE_LICENSE("GPL"); diff -Nru a/drivers/char/watchdog/wdt_pci.c b/drivers/char/watchdog/wdt_pci.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/watchdog/wdt_pci.c Fri Nov 22 13:41:21 2002 @@ -0,0 +1,653 @@ +/* + * Industrial Computer Source WDT500/501 driver for Linux 2.1.x + * + * (c) Copyright 1996-1997 Alan Cox , All Rights Reserved. + * http://www.redhat.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 1995 Alan Cox + * + * Release 0.09. + * + * Fixes + * Dave Gregorich : Modularisation and minor bugs + * Alan Cox : Added the watchdog ioctl() stuff + * Alan Cox : Fixed the reboot problem (as noted by + * Matt Crocker). + * Alan Cox : Added wdt= boot option + * Alan Cox : Cleaned up copy/user stuff + * Tim Hockin : Added insmod parameters, comment cleanup + * Parameterized timeout + * JP Nollmann : Added support for PCI wdt501p + * Alan Cox : Split ISA and PCI cards into two drivers + * Jeff Garzik : PCI cleanups + * Tigran Aivazian : Restructured wdtpci_init_one() to handle failures + * Matt Domsch : added nowayout and timeout module options + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define WDT_IS_PCI +#include "wd501p.h" + +#define PFX "wdt_pci: " + +/* + * Until Access I/O gets their application for a PCI vendor ID approved, + * I don't think that it's appropriate to move these constants into the + * regular pci_ids.h file. -- JPN 2000/01/18 + */ + +#ifndef PCI_VENDOR_ID_ACCESSIO +#define PCI_VENDOR_ID_ACCESSIO 0x494f +#endif +#ifndef PCI_DEVICE_ID_WDG_CSM +#define PCI_DEVICE_ID_WDG_CSM 0x22c0 +#endif + +static unsigned long wdt_is_open; + +/* + * You must set these - there is no sane way to probe for this board. + * You can use wdt=x,y to set these now. + */ + +static int io=0x240; +static int irq=11; + +#define WD_TIMO (100*60) /* 1 minute */ + +static int timeout_val = WD_TIMO; /* value passed to card */ +static int timeout = 60; /* in seconds */ +MODULE_PARM(timeout,"i"); +MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=60)"); + +#ifdef CONFIG_WATCHDOG_NOWAYOUT +static int nowayout = 1; +#else +static int nowayout = 0; +#endif + +MODULE_PARM(nowayout,"i"); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); + +static void __init +wdtpci_validate_timeout(void) +{ + timeout_val = timeout * 100; +} + +#ifndef MODULE + +/** + * wdtpci_setup: + * @str: command line string + * + * Setup options. The board isn't really probe-able so we have to + * get the user to tell us the configuration. Sane people build it + * modular but the others come here. + */ + +static int __init wdtpci_setup(char *str) +{ + int ints[4]; + + str = get_options (str, ARRAY_SIZE(ints), ints); + + if (ints[0] > 0) + { + io = ints[1]; + if(ints[0] > 1) + irq = ints[2]; + } + + return 1; +} + +__setup("wdt=", wdtpci_setup); + +#endif /* !MODULE */ + +/* + * Programming support + */ + +static void wdtpci_ctr_mode(int ctr, int mode) +{ + ctr<<=6; + ctr|=0x30; + ctr|=(mode<<1); + outb_p(ctr, WDT_CR); +} + +static void wdtpci_ctr_load(int ctr, int val) +{ + outb_p(val&0xFF, WDT_COUNT0+ctr); + outb_p(val>>8, WDT_COUNT0+ctr); +} + +/* + * Kernel methods. + */ + + +/** + * wdtpci_status: + * + * Extract the status information from a WDT watchdog device. There are + * several board variants so we have to know which bits are valid. Some + * bits default to one and some to zero in order to be maximally painful. + * + * we then map the bits onto the status ioctl flags. + */ + +static int wdtpci_status(void) +{ + /* + * Status register to bit flags + */ + + int flag=0; + unsigned char status=inb_p(WDT_SR); + status|=FEATUREMAP1; + status&=~FEATUREMAP2; + + if(!(status&WDC_SR_TGOOD)) + flag|=WDIOF_OVERHEAT; + if(!(status&WDC_SR_PSUOVER)) + flag|=WDIOF_POWEROVER; + if(!(status&WDC_SR_PSUUNDR)) + flag|=WDIOF_POWERUNDER; + if(!(status&WDC_SR_FANGOOD)) + flag|=WDIOF_FANFAULT; + if(status&WDC_SR_ISOI0) + flag|=WDIOF_EXTERN1; + if(status&WDC_SR_ISII1) + flag|=WDIOF_EXTERN2; + return flag; +} + +/** + * wdtpci_interrupt: + * @irq: Interrupt number + * @dev_id: Unused as we don't allow multiple devices. + * @regs: Unused. + * + * Handle an interrupt from the board. These are raised when the status + * map changes in what the board considers an interesting way. That means + * a failure condition occuring. + */ + +static void wdtpci_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + /* + * Read the status register see what is up and + * then printk it. + */ + + unsigned char status=inb_p(WDT_SR); + + status|=FEATUREMAP1; + status&=~FEATUREMAP2; + + printk(KERN_CRIT "WDT status %d\n", status); + + if(!(status&WDC_SR_TGOOD)) + printk(KERN_CRIT "Overheat alarm.(%d)\n",inb_p(WDT_RT)); + if(!(status&WDC_SR_PSUOVER)) + printk(KERN_CRIT "PSU over voltage.\n"); + if(!(status&WDC_SR_PSUUNDR)) + printk(KERN_CRIT "PSU under voltage.\n"); + if(!(status&WDC_SR_FANGOOD)) + printk(KERN_CRIT "Possible fan fault.\n"); + if(!(status&WDC_SR_WCCR)) +#ifdef SOFTWARE_REBOOT +#ifdef ONLY_TESTING + printk(KERN_CRIT "Would Reboot.\n"); +#else + printk(KERN_CRIT "Initiating system reboot.\n"); + machine_restart(NULL); +#endif +#else + printk(KERN_CRIT "Reset in 5ms.\n"); +#endif +} + + +/** + * wdtpci_ping: + * + * Reload counter one with the watchdog timeout. We don't bother reloading + * the cascade counter. + */ + +static void wdtpci_ping(void) +{ + /* Write a watchdog value */ + inb_p(WDT_DC); + wdtpci_ctr_mode(1,2); + wdtpci_ctr_load(1,timeout_val); /* Timeout */ + outb_p(0, WDT_DC); +} + +/** + * wdtpci_write: + * @file: file handle to the watchdog + * @buf: buffer to write (unused as data does not matter here + * @count: count of bytes + * @ppos: pointer to the position to write. No seeks allowed + * + * A write to a watchdog device is defined as a keepalive signal. Any + * write of data will do, as we we don't define content meaning. + */ + +static ssize_t wdtpci_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +{ + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + if(count) + { + wdtpci_ping(); + return 1; + } + return 0; +} + +/** + * wdtpci_read: + * @file: file handle to the watchdog board + * @buf: buffer to write 1 byte into + * @count: length of buffer + * @ptr: offset (no seek allowed) + * + * Read reports the temperature in degrees Fahrenheit. The API is in + * fahrenheit. It was designed by an imperial measurement luddite. + */ + +static ssize_t wdtpci_read(struct file *file, char *buf, size_t count, loff_t *ptr) +{ + unsigned short c=inb_p(WDT_RT); + unsigned char cp; + + /* Can't seek (pread) on this device */ + if (ptr != &file->f_pos) + return -ESPIPE; + + switch(minor(file->f_dentry->d_inode->i_rdev)) + { + case TEMP_MINOR: + c*=11; + c/=15; + cp=c+7; + if(copy_to_user(buf,&cp,1)) + return -EFAULT; + return 1; + default: + return -EINVAL; + } +} + +/** + * wdtpci_ioctl: + * @inode: inode of the device + * @file: file handle to the device + * @cmd: watchdog command + * @arg: argument pointer + * + * The watchdog API defines a common set of functions for all watchdogs + * according to their available features. We only actually usefully support + * querying capabilities and current status. + */ + +static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + static struct watchdog_info ident = { + .options = WDIOF_OVERHEAT | WDIOF_POWERUNDER | + WDIOF_POWEROVER | WDIOF_EXTERN1 | + WDIOF_EXTERN2 | WDIOF_FANFAULT, + .firmware_version = 1, + .identity = "WDT500/501PCI", + }; + + ident.options&=WDT_OPTION_MASK; /* Mask down to the card we have */ + switch(cmd) + { + default: + return -ENOTTY; + case WDIOC_GETSUPPORT: + return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0; + + case WDIOC_GETSTATUS: + return put_user(wdtpci_status(),(int *)arg); + case WDIOC_GETBOOTSTATUS: + return put_user(0, (int *)arg); + case WDIOC_KEEPALIVE: + wdtpci_ping(); + return 0; + } +} + +/** + * wdtpci_open: + * @inode: inode of device + * @file: file handle to device + * + * One of our two misc devices has been opened. The watchdog device is + * single open and on opening we load the counters. Counter zero is a + * 100Hz cascade, into counter 1 which downcounts to reboot. When the + * counter triggers counter 2 downcounts the length of the reset pulse + * which set set to be as long as possible. + */ + +static int wdtpci_open(struct inode *inode, struct file *file) +{ + switch(minor(inode->i_rdev)) + { + case WATCHDOG_MINOR: + if( test_and_set_bit(0,&wdt_is_open) ) + { + return -EBUSY; + } + if (nowayout) { + MOD_INC_USE_COUNT; + } + /* + * Activate + */ + + inb_p(WDT_DC); /* Disable */ + + /* + * "pet" the watchdog, as Access says. + * This resets the clock outputs. + */ + + wdtpci_ctr_mode(2,0); + outb_p(0, WDT_DC); + + inb_p(WDT_DC); + + outb_p(0, WDT_CLOCK); /* 2.0833MHz clock */ + inb_p(WDT_BUZZER); /* disable */ + inb_p(WDT_OPTONOTRST); /* disable */ + inb_p(WDT_OPTORST); /* disable */ + inb_p(WDT_PROGOUT); /* disable */ + wdtpci_ctr_mode(0,3); + wdtpci_ctr_mode(1,2); + wdtpci_ctr_mode(2,1); + wdtpci_ctr_load(0,20833); /* count at 100Hz */ + wdtpci_ctr_load(1,timeout_val); /* Timeout */ + /* DO NOT LOAD CTR2 on PCI card! -- JPN */ + outb_p(0, WDT_DC); /* Enable */ + return 0; + case TEMP_MINOR: + return 0; + default: + return -ENODEV; + } +} + +/** + * wdtpci_close: + * @inode: inode to board + * @file: file handle to board + * + * The watchdog has a configurable API. There is a religious dispute + * between people who want their watchdog to be able to shut down and + * those who want to be sure if the watchdog manager dies the machine + * reboots. In the former case we disable the counters, in the latter + * case you have to open it again very soon. + */ + +static int wdtpci_release(struct inode *inode, struct file *file) +{ + if(minor(inode->i_rdev)==WATCHDOG_MINOR) + { + if (!nowayout) { + inb_p(WDT_DC); /* Disable counters */ + wdtpci_ctr_load(2,0); /* 0 length reset pulses now */ + } + clear_bit(0, &wdt_is_open ); + } + return 0; +} + +/** + * notify_sys: + * @this: our notifier block + * @code: the event being reported + * @unused: unused + * + * Our notifier is called on system shutdowns. We want to turn the card + * off at reboot otherwise the machine will reboot again during memory + * test or worse yet during the following fsck. This would suck, in fact + * trust me - if it happens it does suck. + */ + +static int wdtpci_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if(code==SYS_DOWN || code==SYS_HALT) + { + /* Turn the card off */ + inb_p(WDT_DC); + wdtpci_ctr_load(2,0); + } + return NOTIFY_DONE; +} + +/* + * Kernel Interfaces + */ + + +static struct file_operations wdtpci_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = wdtpci_read, + .write = wdtpci_write, + .ioctl = wdtpci_ioctl, + .open = wdtpci_open, + .release = wdtpci_release, +}; + +static struct miscdevice wdtpci_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &wdtpci_fops, +}; + +#ifdef CONFIG_WDT_501 +static struct miscdevice temp_miscdev = { + .minor = TEMP_MINOR, + .name = "temperature", + .fops = &wdtpci_fops, +}; +#endif + +/* + * The WDT card needs to learn about soft shutdowns in order to + * turn the timebomb registers off. + */ + +static struct notifier_block wdtpci_notifier = { + .notifier_call = wdtpci_notify_sys, +}; + + +static int __init wdtpci_init_one (struct pci_dev *dev, + const struct pci_device_id *ent) +{ + static int dev_count = 0; + int ret = -EIO; + + dev_count++; + if (dev_count > 1) { + printk (KERN_ERR PFX + "this driver only supports 1 device\n"); + return -ENODEV; + } + + if (pci_enable_device (dev)) + goto out; + + irq = dev->irq; + io = pci_resource_start (dev, 2); + printk ("WDT501-P(PCI-WDG-CSM) driver 0.07 at %X " + "(Interrupt %d)\n", io, irq); + + if (request_region (io, 16, "wdt-pci") == NULL) { + printk (KERN_ERR PFX "I/O %d is not free.\n", io); + goto out; + } + + if (request_irq (irq, wdtpci_interrupt, SA_INTERRUPT | SA_SHIRQ, + "wdt-pci", &wdtpci_miscdev)) { + printk (KERN_ERR PFX "IRQ %d is not free.\n", irq); + goto out_reg; + } + + ret = misc_register (&wdtpci_miscdev); + if (ret) { + printk (KERN_ERR PFX "can't misc_register on minor=%d\n", WATCHDOG_MINOR); + goto out_irq; + } + + ret = register_reboot_notifier (&wdtpci_notifier); + if (ret) { + printk (KERN_ERR PFX "can't misc_register on minor=%d\n", WATCHDOG_MINOR); + goto out_misc; + } +#ifdef CONFIG_WDT_501 + ret = misc_register (&temp_miscdev); + if (ret) { + printk (KERN_ERR PFX "can't misc_register (temp) on minor=%d\n", TEMP_MINOR); + goto out_rbt; + } +#endif + + ret = 0; +out: + return ret; + +#ifdef CONFIG_WDT_501 +out_rbt: + unregister_reboot_notifier(&wdtpci_notifier); +#endif +out_misc: + misc_deregister(&wdtpci_miscdev); +out_irq: + free_irq(irq, &wdtpci_miscdev); +out_reg: + release_region (io, 16); + goto out; +} + + +static void __devexit wdtpci_remove_one (struct pci_dev *pdev) +{ + /* here we assume only one device will ever have + * been picked up and registered by probe function */ + unregister_reboot_notifier(&wdtpci_notifier); +#ifdef CONFIG_WDT_501_PCI + misc_deregister(&temp_miscdev); +#endif + misc_deregister(&wdtpci_miscdev); + free_irq(irq, &wdtpci_miscdev); + release_region(io, 16); +} + + +static struct pci_device_id wdtpci_pci_tbl[] __initdata = { + { + .vendor = PCI_VENDOR_ID_ACCESSIO, + .device = PCI_DEVICE_ID_WDG_CSM, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { 0, }, /* terminate list */ +}; +MODULE_DEVICE_TABLE(pci, wdtpci_pci_tbl); + + +static struct pci_driver wdtpci_driver = { + .name = "wdt-pci", + .id_table = wdtpci_pci_tbl, + .probe = wdtpci_init_one, + .remove = __devexit_p(wdtpci_remove_one), +}; + + +/** + * wdtpci_cleanup: + * + * Unload the watchdog. You cannot do this with any file handles open. + * If your watchdog is set to continue ticking on close and you unload + * it, well it keeps ticking. We won't get the interrupt but the board + * will not touch PC memory so all is fine. You just have to load a new + * module in 60 seconds or reboot. + */ + +static void __exit wdtpci_cleanup(void) +{ + pci_unregister_driver (&wdtpci_driver); +} + + +/** + * wdtpci_init: + * + * Set up the WDT watchdog board. All we have to do is grab the + * resources we require and bitch if anyone beat us to them. + * The open() function will actually kick the board off. + */ + +static int __init wdtpci_init(void) +{ + int rc = pci_register_driver (&wdtpci_driver); + + if (rc < 1) + return -ENODEV; + + wdtpci_validate_timeout(); + + return 0; +} + + +module_init(wdtpci_init); +module_exit(wdtpci_cleanup); + +MODULE_AUTHOR("JP Nollmann, Alan Cox"); +MODULE_DESCRIPTION("Driver for the ICS PCI watchdog cards"); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/char/wdt.c b/drivers/char/wdt.c --- a/drivers/char/wdt.c Fri Nov 22 13:41:20 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,565 +0,0 @@ -/* - * Industrial Computer Source WDT500/501 driver for Linux 2.1.x - * - * (c) Copyright 1996-1997 Alan Cox , All Rights Reserved. - * http://www.redhat.com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide - * warranty for any of this software. This material is provided - * "AS-IS" and at no charge. - * - * (c) Copyright 1995 Alan Cox - * - * Release 0.09. - * - * Fixes - * Dave Gregorich : Modularisation and minor bugs - * Alan Cox : Added the watchdog ioctl() stuff - * Alan Cox : Fixed the reboot problem (as noted by - * Matt Crocker). - * Alan Cox : Added wdt= boot option - * Alan Cox : Cleaned up copy/user stuff - * Tim Hockin : Added insmod parameters, comment cleanup - * Parameterized timeout - * Tigran Aivazian : Restructured wdt_init() to handle failures - * Matt Domsch : added nowayout and timeout module options - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "wd501p.h" -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -static unsigned long wdt_is_open; - -/* - * You must set these - there is no sane way to probe for this board. - * You can use wdt=x,y to set these now. - */ - -static int io=0x240; -static int irq=11; - -#define WD_TIMO (100*60) /* 1 minute */ - -static int timeout_val = WD_TIMO; /* value passed to card */ -static int timeout = 60; /* in seconds */ -MODULE_PARM(timeout,"i"); -MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=60)"); - -#ifdef CONFIG_WATCHDOG_NOWAYOUT -static int nowayout = 1; -#else -static int nowayout = 0; -#endif - -MODULE_PARM(nowayout,"i"); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); - -static void __init -wdt_validate_timeout(void) -{ - timeout_val = timeout * 100; -} - -#ifndef MODULE - -/** - * wdt_setup: - * @str: command line string - * - * Setup options. The board isn't really probe-able so we have to - * get the user to tell us the configuration. Sane people build it - * modular but the others come here. - */ - -static int __init wdt_setup(char *str) -{ - int ints[4]; - - str = get_options (str, ARRAY_SIZE(ints), ints); - - if (ints[0] > 0) - { - io = ints[1]; - if(ints[0] > 1) - irq = ints[2]; - } - - return 1; -} - -__setup("wdt=", wdt_setup); - -#endif /* !MODULE */ - -MODULE_PARM(io, "i"); -MODULE_PARM_DESC(io, "WDT io port (default=0x240)"); -MODULE_PARM(irq, "i"); -MODULE_PARM_DESC(irq, "WDT irq (default=11)"); - -/* - * Programming support - */ - -static void wdt_ctr_mode(int ctr, int mode) -{ - ctr<<=6; - ctr|=0x30; - ctr|=(mode<<1); - outb_p(ctr, WDT_CR); -} - -static void wdt_ctr_load(int ctr, int val) -{ - outb_p(val&0xFF, WDT_COUNT0+ctr); - outb_p(val>>8, WDT_COUNT0+ctr); -} - -/* - * Kernel methods. - */ - - -/** - * wdt_status: - * - * Extract the status information from a WDT watchdog device. There are - * several board variants so we have to know which bits are valid. Some - * bits default to one and some to zero in order to be maximally painful. - * - * we then map the bits onto the status ioctl flags. - */ - -static int wdt_status(void) -{ - /* - * Status register to bit flags - */ - - int flag=0; - unsigned char status=inb_p(WDT_SR); - status|=FEATUREMAP1; - status&=~FEATUREMAP2; - - if(!(status&WDC_SR_TGOOD)) - flag|=WDIOF_OVERHEAT; - if(!(status&WDC_SR_PSUOVER)) - flag|=WDIOF_POWEROVER; - if(!(status&WDC_SR_PSUUNDR)) - flag|=WDIOF_POWERUNDER; - if(!(status&WDC_SR_FANGOOD)) - flag|=WDIOF_FANFAULT; - if(status&WDC_SR_ISOI0) - flag|=WDIOF_EXTERN1; - if(status&WDC_SR_ISII1) - flag|=WDIOF_EXTERN2; - return flag; -} - -/** - * wdt_interrupt: - * @irq: Interrupt number - * @dev_id: Unused as we don't allow multiple devices. - * @regs: Unused. - * - * Handle an interrupt from the board. These are raised when the status - * map changes in what the board considers an interesting way. That means - * a failure condition occuring. - */ - -void wdt_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - /* - * Read the status register see what is up and - * then printk it. - */ - - unsigned char status=inb_p(WDT_SR); - - status|=FEATUREMAP1; - status&=~FEATUREMAP2; - - printk(KERN_CRIT "WDT status %d\n", status); - - if(!(status&WDC_SR_TGOOD)) - printk(KERN_CRIT "Overheat alarm.(%d)\n",inb_p(WDT_RT)); - if(!(status&WDC_SR_PSUOVER)) - printk(KERN_CRIT "PSU over voltage.\n"); - if(!(status&WDC_SR_PSUUNDR)) - printk(KERN_CRIT "PSU under voltage.\n"); - if(!(status&WDC_SR_FANGOOD)) - printk(KERN_CRIT "Possible fan fault.\n"); - if(!(status&WDC_SR_WCCR)) -#ifdef SOFTWARE_REBOOT -#ifdef ONLY_TESTING - printk(KERN_CRIT "Would Reboot.\n"); -#else - printk(KERN_CRIT "Initiating system reboot.\n"); - machine_restart(NULL); -#endif -#else - printk(KERN_CRIT "Reset in 5ms.\n"); -#endif -} - - -/** - * wdt_ping: - * - * Reload counter one with the watchdog timeout. We don't bother reloading - * the cascade counter. - */ - -static void wdt_ping(void) -{ - /* Write a watchdog value */ - inb_p(WDT_DC); - wdt_ctr_mode(1,2); - wdt_ctr_load(1,timeout_val); /* Timeout */ - outb_p(0, WDT_DC); -} - -/** - * wdt_write: - * @file: file handle to the watchdog - * @buf: buffer to write (unused as data does not matter here - * @count: count of bytes - * @ppos: pointer to the position to write. No seeks allowed - * - * A write to a watchdog device is defined as a keepalive signal. Any - * write of data will do, as we we don't define content meaning. - */ - -static ssize_t wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) -{ - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - - if(count) - { - wdt_ping(); - return 1; - } - return 0; -} - -/** - * wdt_read: - * @file: file handle to the watchdog board - * @buf: buffer to write 1 byte into - * @count: length of buffer - * @ptr: offset (no seek allowed) - * - * Read reports the temperature in degrees Fahrenheit. The API is in - * farenheit. It was designed by an imperial measurement luddite. - */ - -static ssize_t wdt_read(struct file *file, char *buf, size_t count, loff_t *ptr) -{ - unsigned short c=inb_p(WDT_RT); - unsigned char cp; - - /* Can't seek (pread) on this device */ - if (ptr != &file->f_pos) - return -ESPIPE; - - switch(minor(file->f_dentry->d_inode->i_rdev)) - { - case TEMP_MINOR: - c*=11; - c/=15; - cp=c+7; - if(copy_to_user(buf,&cp,1)) - return -EFAULT; - return 1; - default: - return -EINVAL; - } -} - -/** - * wdt_ioctl: - * @inode: inode of the device - * @file: file handle to the device - * @cmd: watchdog command - * @arg: argument pointer - * - * The watchdog API defines a common set of functions for all watchdogs - * according to their available features. We only actually usefully support - * querying capabilities and current status. - */ - -static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) -{ - static struct watchdog_info ident= - { - WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER - |WDIOF_EXTERN1|WDIOF_EXTERN2|WDIOF_FANFAULT, - 1, - "WDT500/501" - }; - - ident.options&=WDT_OPTION_MASK; /* Mask down to the card we have */ - switch(cmd) - { - default: - return -ENOTTY; - case WDIOC_GETSUPPORT: - return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0; - - case WDIOC_GETSTATUS: - return put_user(wdt_status(),(int *)arg); - case WDIOC_GETBOOTSTATUS: - return put_user(0, (int *)arg); - case WDIOC_KEEPALIVE: - wdt_ping(); - return 0; - } -} - -/** - * wdt_open: - * @inode: inode of device - * @file: file handle to device - * - * One of our two misc devices has been opened. The watchdog device is - * single open and on opening we load the counters. Counter zero is a - * 100Hz cascade, into counter 1 which downcounts to reboot. When the - * counter triggers counter 2 downcounts the length of the reset pulse - * which set set to be as long as possible. - */ - -static int wdt_open(struct inode *inode, struct file *file) -{ - switch(minor(inode->i_rdev)) - { - case WATCHDOG_MINOR: - if(test_and_set_bit(0, &wdt_is_open)) - return -EBUSY; - if (nowayout) { - MOD_INC_USE_COUNT; - } - /* - * Activate - */ - - inb_p(WDT_DC); /* Disable */ - wdt_ctr_mode(0,3); - wdt_ctr_mode(1,2); - wdt_ctr_mode(2,0); - wdt_ctr_load(0, 8948); /* count at 100Hz */ - wdt_ctr_load(1,timeout_val); /* Timeout */ - wdt_ctr_load(2,65535); - outb_p(0, WDT_DC); /* Enable */ - return 0; - case TEMP_MINOR: - return 0; - default: - return -ENODEV; - } -} - -/** - * wdt_close: - * @inode: inode to board - * @file: file handle to board - * - * The watchdog has a configurable API. There is a religious dispute - * between people who want their watchdog to be able to shut down and - * those who want to be sure if the watchdog manager dies the machine - * reboots. In the former case we disable the counters, in the latter - * case you have to open it again very soon. - */ - -static int wdt_release(struct inode *inode, struct file *file) -{ - if(minor(inode->i_rdev)==WATCHDOG_MINOR) - { - if (!nowayout) { - inb_p(WDT_DC); /* Disable counters */ - wdt_ctr_load(2,0); /* 0 length reset pulses now */ - } - clear_bit(0, &wdt_is_open); - } - return 0; -} - -/** - * notify_sys: - * @this: our notifier block - * @code: the event being reported - * @unused: unused - * - * Our notifier is called on system shutdowns. We want to turn the card - * off at reboot otherwise the machine will reboot again during memory - * test or worse yet during the following fsck. This would suck, in fact - * trust me - if it happens it does suck. - */ - -static int wdt_notify_sys(struct notifier_block *this, unsigned long code, - void *unused) -{ - if(code==SYS_DOWN || code==SYS_HALT) - { - /* Turn the card off */ - inb_p(WDT_DC); - wdt_ctr_load(2,0); - } - return NOTIFY_DONE; -} - -/* - * Kernel Interfaces - */ - - -static struct file_operations wdt_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = wdt_read, - .write = wdt_write, - .ioctl = wdt_ioctl, - .open = wdt_open, - .release = wdt_release, -}; - -static struct miscdevice wdt_miscdev= -{ - WATCHDOG_MINOR, - "watchdog", - &wdt_fops -}; - -#ifdef CONFIG_WDT_501 -static struct miscdevice temp_miscdev= -{ - TEMP_MINOR, - "temperature", - &wdt_fops -}; -#endif - -/* - * The WDT card needs to learn about soft shutdowns in order to - * turn the timebomb registers off. - */ - -static struct notifier_block wdt_notifier= -{ - wdt_notify_sys, - NULL, - 0 -}; - -/** - * cleanup_module: - * - * Unload the watchdog. You cannot do this with any file handles open. - * If your watchdog is set to continue ticking on close and you unload - * it, well it keeps ticking. We won't get the interrupt but the board - * will not touch PC memory so all is fine. You just have to load a new - * module in 60 seconds or reboot. - */ - -static void __exit wdt_exit(void) -{ - misc_deregister(&wdt_miscdev); -#ifdef CONFIG_WDT_501 - misc_deregister(&temp_miscdev); -#endif - unregister_reboot_notifier(&wdt_notifier); - release_region(io,8); - free_irq(irq, NULL); -} - -/** - * wdt_init: - * - * Set up the WDT watchdog board. All we have to do is grab the - * resources we require and bitch if anyone beat us to them. - * The open() function will actually kick the board off. - */ - -static int __init wdt_init(void) -{ - int ret; - - wdt_validate_timeout(); - ret = misc_register(&wdt_miscdev); - if (ret) { - printk(KERN_ERR "wdt: can't misc_register on minor=%d\n", WATCHDOG_MINOR); - goto out; - } - ret = request_irq(irq, wdt_interrupt, SA_INTERRUPT, "wdt501p", NULL); - if(ret) { - printk(KERN_ERR "wdt: IRQ %d is not free.\n", irq); - goto outmisc; - } - if (!request_region(io, 8, "wdt501p")) { - printk(KERN_ERR "wdt: IO %X is not free.\n", io); - ret = -EBUSY; - goto outirq; - } - ret = register_reboot_notifier(&wdt_notifier); - if(ret) { - printk(KERN_ERR "wdt: can't register reboot notifier (err=%d)\n", ret); - goto outreg; - } - -#ifdef CONFIG_WDT_501 - ret = misc_register(&temp_miscdev); - if (ret) { - printk(KERN_ERR "wdt: can't misc_register (temp) on minor=%d\n", TEMP_MINOR); - goto outrbt; - } -#endif - - ret = 0; - printk(KERN_INFO "WDT500/501-P driver 0.07 at %X (Interrupt %d)\n", io, irq); -out: - return ret; - -#ifdef CONFIG_WDT_501 -outrbt: - unregister_reboot_notifier(&wdt_notifier); -#endif - -outreg: - release_region(io,8); -outirq: - free_irq(irq, NULL); -outmisc: - misc_deregister(&wdt_miscdev); - goto out; -} - -module_init(wdt_init); -module_exit(wdt_exit); - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("Driver for ISA ICS watchdog cards (WDT500/501)"); -MODULE_LICENSE("GPL"); diff -Nru a/drivers/char/wdt285.c b/drivers/char/wdt285.c --- a/drivers/char/wdt285.c Fri Nov 22 13:41:18 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,193 +0,0 @@ -/* - * Intel 21285 watchdog driver - * Copyright (c) Phil Blundell , 1998 - * - * based on - * - * SoftDog 0.05: A Software Watchdog Device - * - * (c) Copyright 1996 Alan Cox , All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* - * Define this to stop the watchdog actually rebooting the machine. - */ -#undef ONLY_TESTING - -#define TIMER_MARGIN 60 /* (secs) Default is 1 minute */ - -#define FCLK (50*1000*1000) /* 50MHz */ - -static int soft_margin = TIMER_MARGIN; /* in seconds */ -static int timer_alive; - -#ifdef ONLY_TESTING -/* - * If the timer expires.. - */ - -static void watchdog_fire(int irq, void *dev_id, struct pt_regs *regs) -{ - printk(KERN_CRIT "Watchdog: Would Reboot.\n"); - *CSR_TIMER4_CNTL = 0; - *CSR_TIMER4_CLR = 0; -} -#endif - -static void watchdog_ping(void) -{ - /* - * Refresh the timer. - */ - *CSR_TIMER4_LOAD = soft_margin * (FCLK / 256); -} - -/* - * Allow only one person to hold it open - */ - -static int watchdog_open(struct inode *inode, struct file *file) -{ - if(timer_alive) - return -EBUSY; - /* - * Ahead watchdog factor ten, Mr Sulu - */ - *CSR_TIMER4_CLR = 0; - watchdog_ping(); - *CSR_TIMER4_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD - | TIMER_CNTL_DIV256; -#ifdef ONLY_TESTING - request_irq(IRQ_TIMER4, watchdog_fire, 0, "watchdog", NULL); -#else - *CSR_SA110_CNTL |= 1 << 13; - MOD_INC_USE_COUNT; -#endif - timer_alive = 1; - return 0; -} - -static int watchdog_release(struct inode *inode, struct file *file) -{ -#ifdef ONLY_TESTING - free_irq(IRQ_TIMER4, NULL); - timer_alive = 0; -#else - /* - * It's irreversible! - */ -#endif - return 0; -} - -static ssize_t watchdog_write(struct file *file, const char *data, size_t len, loff_t *ppos) -{ - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - - /* - * Refresh the timer. - */ - if(len) - { - watchdog_ping(); - return 1; - } - return 0; -} - -static int watchdog_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int i; - static struct watchdog_info ident= - { - 0, - 0, - "Footbridge Watchdog" - }; - switch(cmd) - { - default: - return -ENOTTY; - case WDIOC_GETSUPPORT: - if(copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))) - return -EFAULT; - return 0; - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - return put_user(0,(int *)arg); - case WDIOC_KEEPALIVE: - watchdog_ping(); - return 0; - } -} - -static struct file_operations watchdog_fops= -{ - .owner = THIS_MODULE, - .write = watchdog_write, - .ioctl = watchdog_ioctl, - .open = watchdog_open, - .release = watchdog_release, -}; - -static struct miscdevice watchdog_miscdev= -{ - WATCHDOG_MINOR, - "watchdog", - &watchdog_fops -}; - -static int __init footbridge_watchdog_init(void) -{ - if (machine_is_netwinder()) - return -ENODEV; - - misc_register(&watchdog_miscdev); - printk("Footbridge Watchdog Timer: 0.01, timer margin: %d sec\n", - soft_margin); - if (machine_is_cats()) - printk("Warning: Watchdog reset may not work on this machine.\n"); - return 0; -} - -static void __exit footbridge_watchdog_exit(void) -{ - misc_deregister(&watchdog_miscdev); -} - -MODULE_AUTHOR("Phil Blundell "); -MODULE_DESCRIPTION("21285 watchdog driver"); -MODULE_LICENSE("GPL"); - -MODULE_PARM(soft_margin,"i"); -MODULE_PARM_DESC(soft_margin,"Watchdog timeout in seconds"); - -module_init(footbridge_watchdog_init); -module_exit(footbridge_watchdog_exit); diff -Nru a/drivers/char/wdt977.c b/drivers/char/wdt977.c --- a/drivers/char/wdt977.c Fri Nov 22 13:41:22 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,346 +0,0 @@ -/* - * Wdt977 0.02: A Watchdog Device for Netwinder W83977AF chip - * - * (c) Copyright 1998 Rebel.com (Woody Suwalski ) - * - * ----------------------- - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * ----------------------- - * 14-Dec-2001 Matt Domsch - * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT - * 19-Dec-2001 Woody Suwalski: Netwinder fixes, ioctl interface - * 06-Jan-2002 Woody Suwalski: For compatibility, convert all timeouts - * from minutes to seconds. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define WATCHDOG_MINOR 130 - -#define DEFAULT_TIMEOUT 1 /* default timeout = 1 minute */ - -static int timeout = DEFAULT_TIMEOUT*60; /* TO in seconds from user */ -static int timeoutM = DEFAULT_TIMEOUT; /* timeout in minutes */ -static unsigned long timer_alive; -static int testmode; - -MODULE_PARM(timeout, "i"); -MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (60..15300), default=60"); -MODULE_PARM(testmode, "i"); -MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0"); - -#ifdef CONFIG_WATCHDOG_NOWAYOUT -static int nowayout = 1; -#else -static int nowayout = 0; -#endif - -MODULE_PARM(nowayout,"i"); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); - - -/* This is kicking the watchdog by simply re-writing the timeout to reg. 0xF2 */ -int kick_wdog(void) -{ - /* - * Refresh the timer. - */ - - /* unlock the SuperIO chip */ - outb(0x87,0x370); - outb(0x87,0x370); - - /* select device Aux2 (device=8) and kicks watchdog reg F2 */ - /* F2 has the timeout in minutes */ - - outb(0x07,0x370); - outb(0x08,0x371); - outb(0xF2,0x370); - outb(timeoutM,0x371); - - /* lock the SuperIO chip */ - outb(0xAA,0x370); - - return 0; -} - - -/* - * Allow only one person to hold it open - */ - -static int wdt977_open(struct inode *inode, struct file *file) -{ - - if( test_and_set_bit(0,&timer_alive) ) - return -EBUSY; - - /* convert seconds to minutes, rounding up */ - timeoutM = timeout + 59; - timeoutM /= 60; - - if (nowayout) - { - MOD_INC_USE_COUNT; - - /* do not permit disabling the watchdog by writing 0 to reg. 0xF2 */ - if (!timeoutM) timeoutM = DEFAULT_TIMEOUT; - } - - if (machine_is_netwinder()) - { - /* we have a hw bug somewhere, so each 977 minute is actually only 30sec - * this limits the max timeout to half of device max of 255 minutes... - */ - timeoutM += timeoutM; - } - - /* max timeout value = 255 minutes (0xFF). Write 0 to disable WatchDog. */ - if (timeoutM > 255) timeoutM = 255; - - /* convert seconds to minutes */ - printk(KERN_INFO "Wdt977 Watchdog activated: timeout = %d sec, nowayout = %i, testmode = %i.\n", - machine_is_netwinder() ? (timeoutM>>1)*60 : timeoutM*60, - nowayout, testmode); - - /* unlock the SuperIO chip */ - outb(0x87,0x370); - outb(0x87,0x370); - - /* select device Aux2 (device=8) and set watchdog regs F2, F3 and F4 - * F2 has the timeout in minutes - * F3 could be set to the POWER LED blink (with GP17 set to PowerLed) - * at timeout, and to reset timer on kbd/mouse activity (not impl.) - * F4 is used to just clear the TIMEOUT'ed state (bit 0) - */ - outb(0x07,0x370); - outb(0x08,0x371); - outb(0xF2,0x370); - outb(timeoutM,0x371); - outb(0xF3,0x370); - outb(0x00,0x371); /* another setting is 0E for kbd/mouse/LED */ - outb(0xF4,0x370); - outb(0x00,0x371); - - /* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */ - /* in test mode watch the bit 1 on F4 to indicate "triggered" */ - if (!testmode) - { - outb(0x07,0x370); - outb(0x07,0x371); - outb(0xE6,0x370); - outb(0x08,0x371); - } - - /* lock the SuperIO chip */ - outb(0xAA,0x370); - - return 0; -} - -static int wdt977_release(struct inode *inode, struct file *file) -{ - /* - * Shut off the timer. - * Lock it in if it's a module and we set nowayout - */ - if (!nowayout) - { - /* unlock the SuperIO chip */ - outb(0x87,0x370); - outb(0x87,0x370); - - /* select device Aux2 (device=8) and set watchdog regs F2,F3 and F4 - * F3 is reset to its default state - * F4 can clear the TIMEOUT'ed state (bit 0) - back to default - * We can not use GP17 as a PowerLed, as we use its usage as a RedLed - */ - outb(0x07,0x370); - outb(0x08,0x371); - outb(0xF2,0x370); - outb(0xFF,0x371); - outb(0xF3,0x370); - outb(0x00,0x371); - outb(0xF4,0x370); - outb(0x00,0x371); - outb(0xF2,0x370); - outb(0x00,0x371); - - /* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */ - outb(0x07,0x370); - outb(0x07,0x371); - outb(0xE6,0x370); - outb(0x08,0x371); - - /* lock the SuperIO chip */ - outb(0xAA,0x370); - - clear_bit(0,&timer_alive); - - printk(KERN_INFO "Wdt977 Watchdog: shutdown\n"); - } - return 0; -} - - -/* - * wdt977_write: - * @file: file handle to the watchdog - * @buf: buffer to write (unused as data does not matter here - * @count: count of bytes - * @ppos: pointer to the position to write. No seeks allowed - * - * A write to a watchdog device is defined as a keepalive signal. Any - * write of data will do, as we we don't define content meaning. - */ - -static ssize_t wdt977_write(struct file *file, const char *buf, size_t count, loff_t *ppos) -{ - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - - if(count) - { - kick_wdog(); - return 1; - } - return 0; -} - -/* - * wdt977_ioctl: - * @inode: inode of the device - * @file: file handle to the device - * @cmd: watchdog command - * @arg: argument pointer - * - * The watchdog API defines a common set of functions for all watchdogs - * according to their available features. - */ - -static int wdt977_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ -static struct watchdog_info ident = { - identity : "Winbond 83977" -}; - -int temp; - - switch(cmd) - { - default: - return -ENOTTY; - - case WDIOC_GETSUPPORT: - return copy_to_user((struct watchdog_info *)arg, &ident, - sizeof(ident)) ? -EFAULT : 0; - - case WDIOC_GETBOOTSTATUS: - return put_user(0, (int *) arg); - - case WDIOC_GETSTATUS: - /* unlock the SuperIO chip */ - outb(0x87,0x370); - outb(0x87,0x370); - - /* select device Aux2 (device=8) and read watchdog reg F4 */ - outb(0x07,0x370); - outb(0x08,0x371); - outb(0xF4,0x370); - temp = inb(0x371); - - /* lock the SuperIO chip */ - outb(0xAA,0x370); - - /* return info if "expired" in test mode */ - return put_user(temp & 1, (int *) arg); - - case WDIOC_KEEPALIVE: - kick_wdog(); - return 0; - - case WDIOC_SETTIMEOUT: - if (copy_from_user(&temp, (int *) arg, sizeof(int))) - return -EFAULT; - - /* convert seconds to minutes, rounding up */ - temp += 59; - temp /= 60; - - /* we have a hw bug somewhere, so each 977 minute is actually only 30sec - * this limits the max timeout to half of device max of 255 minutes... - */ - if (machine_is_netwinder()) - { - temp += temp; - } - - /* Sanity check */ - if (temp < 0 || temp > 255) - return -EINVAL; - - if (!temp && nowayout) - return -EINVAL; - - timeoutM = temp; - kick_wdog(); - return 0; - } -} - - -static struct file_operations wdt977_fops= -{ - .owner = THIS_MODULE, - .write = wdt977_write, - .ioctl = wdt977_ioctl, - .open = wdt977_open, - .release = wdt977_release, -}; - -static struct miscdevice wdt977_miscdev= -{ - WATCHDOG_MINOR, - "watchdog", - &wdt977_fops -}; - -static int __init nwwatchdog_init(void) -{ - if (!machine_is_netwinder()) - return -ENODEV; - - misc_register(&wdt977_miscdev); - printk(KERN_INFO "Wdt977 Watchdog sleeping.\n"); - return 0; -} - -static void __exit nwwatchdog_exit(void) -{ - misc_deregister(&wdt977_miscdev); -} - -module_init(nwwatchdog_init); -module_exit(nwwatchdog_exit); - -MODULE_LICENSE("GPL"); diff -Nru a/drivers/char/wdt_pci.c b/drivers/char/wdt_pci.c --- a/drivers/char/wdt_pci.c Fri Nov 22 13:41:21 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,653 +0,0 @@ -/* - * Industrial Computer Source WDT500/501 driver for Linux 2.1.x - * - * (c) Copyright 1996-1997 Alan Cox , All Rights Reserved. - * http://www.redhat.com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide - * warranty for any of this software. This material is provided - * "AS-IS" and at no charge. - * - * (c) Copyright 1995 Alan Cox - * - * Release 0.09. - * - * Fixes - * Dave Gregorich : Modularisation and minor bugs - * Alan Cox : Added the watchdog ioctl() stuff - * Alan Cox : Fixed the reboot problem (as noted by - * Matt Crocker). - * Alan Cox : Added wdt= boot option - * Alan Cox : Cleaned up copy/user stuff - * Tim Hockin : Added insmod parameters, comment cleanup - * Parameterized timeout - * JP Nollmann : Added support for PCI wdt501p - * Alan Cox : Split ISA and PCI cards into two drivers - * Jeff Garzik : PCI cleanups - * Tigran Aivazian : Restructured wdtpci_init_one() to handle failures - * Matt Domsch : added nowayout and timeout module options - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define WDT_IS_PCI -#include "wd501p.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define PFX "wdt_pci: " - -/* - * Until Access I/O gets their application for a PCI vendor ID approved, - * I don't think that it's appropriate to move these constants into the - * regular pci_ids.h file. -- JPN 2000/01/18 - */ - -#ifndef PCI_VENDOR_ID_ACCESSIO -#define PCI_VENDOR_ID_ACCESSIO 0x494f -#endif -#ifndef PCI_DEVICE_ID_WDG_CSM -#define PCI_DEVICE_ID_WDG_CSM 0x22c0 -#endif - -static unsigned long wdt_is_open; - -/* - * You must set these - there is no sane way to probe for this board. - * You can use wdt=x,y to set these now. - */ - -static int io=0x240; -static int irq=11; - -#define WD_TIMO (100*60) /* 1 minute */ - -static int timeout_val = WD_TIMO; /* value passed to card */ -static int timeout = 60; /* in seconds */ -MODULE_PARM(timeout,"i"); -MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=60)"); - -#ifdef CONFIG_WATCHDOG_NOWAYOUT -static int nowayout = 1; -#else -static int nowayout = 0; -#endif - -MODULE_PARM(nowayout,"i"); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); - -static void __init -wdtpci_validate_timeout(void) -{ - timeout_val = timeout * 100; -} - -#ifndef MODULE - -/** - * wdtpci_setup: - * @str: command line string - * - * Setup options. The board isn't really probe-able so we have to - * get the user to tell us the configuration. Sane people build it - * modular but the others come here. - */ - -static int __init wdtpci_setup(char *str) -{ - int ints[4]; - - str = get_options (str, ARRAY_SIZE(ints), ints); - - if (ints[0] > 0) - { - io = ints[1]; - if(ints[0] > 1) - irq = ints[2]; - } - - return 1; -} - -__setup("wdt=", wdtpci_setup); - -#endif /* !MODULE */ - -/* - * Programming support - */ - -static void wdtpci_ctr_mode(int ctr, int mode) -{ - ctr<<=6; - ctr|=0x30; - ctr|=(mode<<1); - outb_p(ctr, WDT_CR); -} - -static void wdtpci_ctr_load(int ctr, int val) -{ - outb_p(val&0xFF, WDT_COUNT0+ctr); - outb_p(val>>8, WDT_COUNT0+ctr); -} - -/* - * Kernel methods. - */ - - -/** - * wdtpci_status: - * - * Extract the status information from a WDT watchdog device. There are - * several board variants so we have to know which bits are valid. Some - * bits default to one and some to zero in order to be maximally painful. - * - * we then map the bits onto the status ioctl flags. - */ - -static int wdtpci_status(void) -{ - /* - * Status register to bit flags - */ - - int flag=0; - unsigned char status=inb_p(WDT_SR); - status|=FEATUREMAP1; - status&=~FEATUREMAP2; - - if(!(status&WDC_SR_TGOOD)) - flag|=WDIOF_OVERHEAT; - if(!(status&WDC_SR_PSUOVER)) - flag|=WDIOF_POWEROVER; - if(!(status&WDC_SR_PSUUNDR)) - flag|=WDIOF_POWERUNDER; - if(!(status&WDC_SR_FANGOOD)) - flag|=WDIOF_FANFAULT; - if(status&WDC_SR_ISOI0) - flag|=WDIOF_EXTERN1; - if(status&WDC_SR_ISII1) - flag|=WDIOF_EXTERN2; - return flag; -} - -/** - * wdtpci_interrupt: - * @irq: Interrupt number - * @dev_id: Unused as we don't allow multiple devices. - * @regs: Unused. - * - * Handle an interrupt from the board. These are raised when the status - * map changes in what the board considers an interesting way. That means - * a failure condition occuring. - */ - -static void wdtpci_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - /* - * Read the status register see what is up and - * then printk it. - */ - - unsigned char status=inb_p(WDT_SR); - - status|=FEATUREMAP1; - status&=~FEATUREMAP2; - - printk(KERN_CRIT "WDT status %d\n", status); - - if(!(status&WDC_SR_TGOOD)) - printk(KERN_CRIT "Overheat alarm.(%d)\n",inb_p(WDT_RT)); - if(!(status&WDC_SR_PSUOVER)) - printk(KERN_CRIT "PSU over voltage.\n"); - if(!(status&WDC_SR_PSUUNDR)) - printk(KERN_CRIT "PSU under voltage.\n"); - if(!(status&WDC_SR_FANGOOD)) - printk(KERN_CRIT "Possible fan fault.\n"); - if(!(status&WDC_SR_WCCR)) -#ifdef SOFTWARE_REBOOT -#ifdef ONLY_TESTING - printk(KERN_CRIT "Would Reboot.\n"); -#else - printk(KERN_CRIT "Initiating system reboot.\n"); - machine_restart(NULL); -#endif -#else - printk(KERN_CRIT "Reset in 5ms.\n"); -#endif -} - - -/** - * wdtpci_ping: - * - * Reload counter one with the watchdog timeout. We don't bother reloading - * the cascade counter. - */ - -static void wdtpci_ping(void) -{ - /* Write a watchdog value */ - inb_p(WDT_DC); - wdtpci_ctr_mode(1,2); - wdtpci_ctr_load(1,timeout_val); /* Timeout */ - outb_p(0, WDT_DC); -} - -/** - * wdtpci_write: - * @file: file handle to the watchdog - * @buf: buffer to write (unused as data does not matter here - * @count: count of bytes - * @ppos: pointer to the position to write. No seeks allowed - * - * A write to a watchdog device is defined as a keepalive signal. Any - * write of data will do, as we we don't define content meaning. - */ - -static ssize_t wdtpci_write(struct file *file, const char *buf, size_t count, loff_t *ppos) -{ - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - - if(count) - { - wdtpci_ping(); - return 1; - } - return 0; -} - -/** - * wdtpci_read: - * @file: file handle to the watchdog board - * @buf: buffer to write 1 byte into - * @count: length of buffer - * @ptr: offset (no seek allowed) - * - * Read reports the temperature in degrees Fahrenheit. The API is in - * fahrenheit. It was designed by an imperial measurement luddite. - */ - -static ssize_t wdtpci_read(struct file *file, char *buf, size_t count, loff_t *ptr) -{ - unsigned short c=inb_p(WDT_RT); - unsigned char cp; - - /* Can't seek (pread) on this device */ - if (ptr != &file->f_pos) - return -ESPIPE; - - switch(minor(file->f_dentry->d_inode->i_rdev)) - { - case TEMP_MINOR: - c*=11; - c/=15; - cp=c+7; - if(copy_to_user(buf,&cp,1)) - return -EFAULT; - return 1; - default: - return -EINVAL; - } -} - -/** - * wdtpci_ioctl: - * @inode: inode of the device - * @file: file handle to the device - * @cmd: watchdog command - * @arg: argument pointer - * - * The watchdog API defines a common set of functions for all watchdogs - * according to their available features. We only actually usefully support - * querying capabilities and current status. - */ - -static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) -{ - static struct watchdog_info ident= - { - WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER - |WDIOF_EXTERN1|WDIOF_EXTERN2|WDIOF_FANFAULT, - 1, - "WDT500/501PCI" - }; - - ident.options&=WDT_OPTION_MASK; /* Mask down to the card we have */ - switch(cmd) - { - default: - return -ENOTTY; - case WDIOC_GETSUPPORT: - return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0; - - case WDIOC_GETSTATUS: - return put_user(wdtpci_status(),(int *)arg); - case WDIOC_GETBOOTSTATUS: - return put_user(0, (int *)arg); - case WDIOC_KEEPALIVE: - wdtpci_ping(); - return 0; - } -} - -/** - * wdtpci_open: - * @inode: inode of device - * @file: file handle to device - * - * One of our two misc devices has been opened. The watchdog device is - * single open and on opening we load the counters. Counter zero is a - * 100Hz cascade, into counter 1 which downcounts to reboot. When the - * counter triggers counter 2 downcounts the length of the reset pulse - * which set set to be as long as possible. - */ - -static int wdtpci_open(struct inode *inode, struct file *file) -{ - switch(minor(inode->i_rdev)) - { - case WATCHDOG_MINOR: - if( test_and_set_bit(0,&wdt_is_open) ) - { - return -EBUSY; - } - if (nowayout) { - MOD_INC_USE_COUNT; - } - /* - * Activate - */ - - inb_p(WDT_DC); /* Disable */ - - /* - * "pet" the watchdog, as Access says. - * This resets the clock outputs. - */ - - wdtpci_ctr_mode(2,0); - outb_p(0, WDT_DC); - - inb_p(WDT_DC); - - outb_p(0, WDT_CLOCK); /* 2.0833MHz clock */ - inb_p(WDT_BUZZER); /* disable */ - inb_p(WDT_OPTONOTRST); /* disable */ - inb_p(WDT_OPTORST); /* disable */ - inb_p(WDT_PROGOUT); /* disable */ - wdtpci_ctr_mode(0,3); - wdtpci_ctr_mode(1,2); - wdtpci_ctr_mode(2,1); - wdtpci_ctr_load(0,20833); /* count at 100Hz */ - wdtpci_ctr_load(1,timeout_val); /* Timeout */ - /* DO NOT LOAD CTR2 on PCI card! -- JPN */ - outb_p(0, WDT_DC); /* Enable */ - return 0; - case TEMP_MINOR: - return 0; - default: - return -ENODEV; - } -} - -/** - * wdtpci_close: - * @inode: inode to board - * @file: file handle to board - * - * The watchdog has a configurable API. There is a religious dispute - * between people who want their watchdog to be able to shut down and - * those who want to be sure if the watchdog manager dies the machine - * reboots. In the former case we disable the counters, in the latter - * case you have to open it again very soon. - */ - -static int wdtpci_release(struct inode *inode, struct file *file) -{ - if(minor(inode->i_rdev)==WATCHDOG_MINOR) - { - if (!nowayout) { - inb_p(WDT_DC); /* Disable counters */ - wdtpci_ctr_load(2,0); /* 0 length reset pulses now */ - } - clear_bit(0, &wdt_is_open ); - } - return 0; -} - -/** - * notify_sys: - * @this: our notifier block - * @code: the event being reported - * @unused: unused - * - * Our notifier is called on system shutdowns. We want to turn the card - * off at reboot otherwise the machine will reboot again during memory - * test or worse yet during the following fsck. This would suck, in fact - * trust me - if it happens it does suck. - */ - -static int wdtpci_notify_sys(struct notifier_block *this, unsigned long code, - void *unused) -{ - if(code==SYS_DOWN || code==SYS_HALT) - { - /* Turn the card off */ - inb_p(WDT_DC); - wdtpci_ctr_load(2,0); - } - return NOTIFY_DONE; -} - -/* - * Kernel Interfaces - */ - - -static struct file_operations wdtpci_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = wdtpci_read, - .write = wdtpci_write, - .ioctl = wdtpci_ioctl, - .open = wdtpci_open, - .release = wdtpci_release, -}; - -static struct miscdevice wdtpci_miscdev= -{ - WATCHDOG_MINOR, - "watchdog", - &wdtpci_fops -}; - -#ifdef CONFIG_WDT_501 -static struct miscdevice temp_miscdev= -{ - TEMP_MINOR, - "temperature", - &wdtpci_fops -}; -#endif - -/* - * The WDT card needs to learn about soft shutdowns in order to - * turn the timebomb registers off. - */ - -static struct notifier_block wdtpci_notifier= -{ - wdtpci_notify_sys, - NULL, - 0 -}; - - -static int __init wdtpci_init_one (struct pci_dev *dev, - const struct pci_device_id *ent) -{ - static int dev_count = 0; - int ret = -EIO; - - dev_count++; - if (dev_count > 1) { - printk (KERN_ERR PFX - "this driver only supports 1 device\n"); - return -ENODEV; - } - - if (pci_enable_device (dev)) - goto out; - - irq = dev->irq; - io = pci_resource_start (dev, 2); - printk ("WDT501-P(PCI-WDG-CSM) driver 0.07 at %X " - "(Interrupt %d)\n", io, irq); - - if (request_region (io, 16, "wdt-pci") == NULL) { - printk (KERN_ERR PFX "I/O %d is not free.\n", io); - goto out; - } - - if (request_irq (irq, wdtpci_interrupt, SA_INTERRUPT | SA_SHIRQ, - "wdt-pci", &wdtpci_miscdev)) { - printk (KERN_ERR PFX "IRQ %d is not free.\n", irq); - goto out_reg; - } - - ret = misc_register (&wdtpci_miscdev); - if (ret) { - printk (KERN_ERR PFX "can't misc_register on minor=%d\n", WATCHDOG_MINOR); - goto out_irq; - } - - ret = register_reboot_notifier (&wdtpci_notifier); - if (ret) { - printk (KERN_ERR PFX "can't misc_register on minor=%d\n", WATCHDOG_MINOR); - goto out_misc; - } -#ifdef CONFIG_WDT_501 - ret = misc_register (&temp_miscdev); - if (ret) { - printk (KERN_ERR PFX "can't misc_register (temp) on minor=%d\n", TEMP_MINOR); - goto out_rbt; - } -#endif - - ret = 0; -out: - return ret; - -#ifdef CONFIG_WDT_501 -out_rbt: - unregister_reboot_notifier(&wdtpci_notifier); -#endif -out_misc: - misc_deregister(&wdtpci_miscdev); -out_irq: - free_irq(irq, &wdtpci_miscdev); -out_reg: - release_region (io, 16); - goto out; -} - - -static void __devexit wdtpci_remove_one (struct pci_dev *pdev) -{ - /* here we assume only one device will ever have - * been picked up and registered by probe function */ - unregister_reboot_notifier(&wdtpci_notifier); -#ifdef CONFIG_WDT_501_PCI - misc_deregister(&temp_miscdev); -#endif - misc_deregister(&wdtpci_miscdev); - free_irq(irq, &wdtpci_miscdev); - release_region(io, 16); -} - - -static struct pci_device_id wdtpci_pci_tbl[] __initdata = { - { PCI_VENDOR_ID_ACCESSIO, PCI_DEVICE_ID_WDG_CSM, PCI_ANY_ID, PCI_ANY_ID, }, - { 0, }, /* terminate list */ -}; -MODULE_DEVICE_TABLE(pci, wdtpci_pci_tbl); - - -static struct pci_driver wdtpci_driver = { - .name = "wdt-pci", - .id_table = wdtpci_pci_tbl, - .probe = wdtpci_init_one, - .remove = __devexit_p(wdtpci_remove_one), -}; - - -/** - * wdtpci_cleanup: - * - * Unload the watchdog. You cannot do this with any file handles open. - * If your watchdog is set to continue ticking on close and you unload - * it, well it keeps ticking. We won't get the interrupt but the board - * will not touch PC memory so all is fine. You just have to load a new - * module in 60 seconds or reboot. - */ - -static void __exit wdtpci_cleanup(void) -{ - pci_unregister_driver (&wdtpci_driver); -} - - -/** - * wdtpci_init: - * - * Set up the WDT watchdog board. All we have to do is grab the - * resources we require and bitch if anyone beat us to them. - * The open() function will actually kick the board off. - */ - -static int __init wdtpci_init(void) -{ - int rc = pci_register_driver (&wdtpci_driver); - - if (rc < 1) - return -ENODEV; - - wdtpci_validate_timeout(); - - return 0; -} - - -module_init(wdtpci_init); -module_exit(wdtpci_cleanup); - -MODULE_AUTHOR("JP Nollmann, Alan Cox"); -MODULE_DESCRIPTION("Driver for the ICS PCI watchdog cards"); -MODULE_LICENSE("GPL"); diff -Nru a/drivers/hotplug/cpci_hotplug_pci.c b/drivers/hotplug/cpci_hotplug_pci.c --- a/drivers/hotplug/cpci_hotplug_pci.c Fri Nov 22 13:41:21 2002 +++ b/drivers/hotplug/cpci_hotplug_pci.c Fri Nov 22 13:41:21 2002 @@ -411,8 +411,8 @@ * Update the bridge resources of the bridge to accommodate devices * behind it. */ - pbus_size_bridges(child); - pbus_assign_resources(child); + pci_bus_size_bridges(child); + pci_bus_assign_resources(child); /* Enable resource mapping via command register */ command = PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR; diff -Nru a/drivers/hotplug/cpqphp_core.c b/drivers/hotplug/cpqphp_core.c --- a/drivers/hotplug/cpqphp_core.c Fri Nov 22 13:41:17 2002 +++ b/drivers/hotplug/cpqphp_core.c Fri Nov 22 13:41:17 2002 @@ -36,7 +36,10 @@ #include #include #include +#include + #include + #include "cpqphp.h" #include "cpqphp_nvram.h" #include "../../arch/i386/pci/pci.h" /* horrible hack showing how processor dependant we are... */ diff -Nru a/drivers/hotplug/pci_hotplug_core.c b/drivers/hotplug/pci_hotplug_core.c --- a/drivers/hotplug/pci_hotplug_core.c Fri Nov 22 13:41:22 2002 +++ b/drivers/hotplug/pci_hotplug_core.c Fri Nov 22 13:41:22 2002 @@ -121,7 +121,7 @@ static const char *slotdir_name = "slots"; #endif -static struct inode *pcihpfs_get_inode (struct super_block *sb, int mode, int dev) +static struct inode *pcihpfs_get_inode (struct super_block *sb, int mode, dev_t dev) { struct inode *inode = new_inode(sb); @@ -153,7 +153,7 @@ } /* SMP-safe */ -static int pcihpfs_mknod (struct inode *dir, struct dentry *dentry, int mode, int dev) +static int pcihpfs_mknod (struct inode *dir, struct dentry *dentry, int mode, dev_t dev) { struct inode *inode = pcihpfs_get_inode(dir->i_sb, mode, dev); int error = -ENOSPC; diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c --- a/drivers/i2c/i2c-core.c Fri Nov 22 13:41:18 2002 +++ b/drivers/i2c/i2c-core.c Fri Nov 22 13:41:18 2002 @@ -88,7 +88,7 @@ /* To implement the dynamic /proc/bus/i2c-? files, we need our own implementation of the read hook */ static struct file_operations i2cproc_operations = { - read: i2cproc_bus_read, + .read = i2cproc_bus_read, }; static int i2cproc_initialized = 0; diff -Nru a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c --- a/drivers/i2c/i2c-dev.c Fri Nov 22 13:41:22 2002 +++ b/drivers/i2c/i2c-dev.c Fri Nov 22 13:41:22 2002 @@ -69,13 +69,13 @@ void *arg); static struct file_operations i2cdev_fops = { - owner: THIS_MODULE, - llseek: no_llseek, - read: i2cdev_read, - write: i2cdev_write, - ioctl: i2cdev_ioctl, - open: i2cdev_open, - release: i2cdev_release, + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = i2cdev_read, + .write = i2cdev_write, + .ioctl = i2cdev_ioctl, + .open = i2cdev_open, + .release = i2cdev_release, }; #define I2CDEV_ADAPS_MAX I2C_ADAP_MAX @@ -86,24 +86,19 @@ #endif static struct i2c_driver i2cdev_driver = { - name: "i2c-dev dummy driver", - id: I2C_DRIVERID_I2CDEV, - flags: I2C_DF_DUMMY, - attach_adapter: i2cdev_attach_adapter, - detach_client: i2cdev_detach_client, - command: i2cdev_command, -/* inc_use: NULL, - dec_use: NULL, */ + .name = "i2c-dev dummy driver", + .id = I2C_DRIVERID_I2CDEV, + .flags = I2C_DF_DUMMY, + .attach_adapter = i2cdev_attach_adapter, + .detach_client = i2cdev_detach_client, + .command = i2cdev_command, }; static struct i2c_client i2cdev_client_template = { - name: "I2C /dev entry", - id: 1, - flags: 0, - addr: -1, -/* adapter: NULL, */ - driver: &i2cdev_driver, -/* data: NULL */ + .name = "I2C /dev entry", + .id = 1, + .addr = -1, + .driver = &i2cdev_driver, }; static int i2cdev_initialized; diff -Nru a/drivers/i2c/i2c-elektor.c b/drivers/i2c/i2c-elektor.c --- a/drivers/i2c/i2c-elektor.c Fri Nov 22 13:41:17 2002 +++ b/drivers/i2c/i2c-elektor.c Fri Nov 22 13:41:17 2002 @@ -32,23 +32,27 @@ #include #include #include +#include #include -#include -#include +#include #include #include #include + +#include +#include + #include "i2c-pcf8584.h" #define DEFAULT_BASE 0x330 -static int base = 0; -static int irq = 0; +static int base; +static int irq; static int clock = 0x1c; static int own = 0x55; -static int mmapped = 0; -static int i2c_debug = 0; +static int mmapped; +static int i2c_debug; /* vdovikin: removed static struct i2c_pcf_isa gpi; code - this module in real supports only one device, due to missing arguments @@ -199,24 +203,24 @@ * This is only done when more than one hardware adapter is supported. */ static struct i2c_algo_pcf_data pcf_isa_data = { - NULL, - pcf_isa_setbyte, - pcf_isa_getbyte, - pcf_isa_getown, - pcf_isa_getclock, - pcf_isa_waitforpin, - 10, 10, 100, /* waits, timeout */ + .setpcf = pcf_isa_setbyte, + .getpcf = pcf_isa_getbyte, + .getown = pcf_isa_getown, + .getclock = pcf_isa_getclock, + .waitforpin = pcf_isa_waitforpin, + .udelay = 10, + .mdelay = 10, + .timeout = 100, }; static struct i2c_adapter pcf_isa_ops = { - "PCF8584 ISA adapter", - I2C_HW_P_ELEK, - NULL, - &pcf_isa_data, - pcf_isa_inc_use, - pcf_isa_dec_use, - pcf_isa_reg, - pcf_isa_unreg, + .name = "PCF8584 ISA adapter", + .id = I2C_HW_P_ELEK, + .algo_data = &pcf_isa_data, + .inc_use = pcf_isa_inc_use, + .dec_use = pcf_isa_dec_use, + .client_register = pcf_isa_reg, + .client_unregister = pcf_isa_unreg, }; int __init i2c_pcfisa_init(void) diff -Nru a/drivers/i2c/i2c-frodo.c b/drivers/i2c/i2c-frodo.c --- a/drivers/i2c/i2c-frodo.c Fri Nov 22 13:41:17 2002 +++ b/drivers/i2c/i2c-frodo.c Fri Nov 22 13:41:17 2002 @@ -52,13 +52,13 @@ } static struct i2c_algo_bit_data bit_frodo_data = { - setsda: frodo_setsda, - setscl: frodo_setscl, - getsda: frodo_getsda, - getscl: frodo_getscl, - udelay: 80, - mdelay: 80, - timeout: 100 + .setsda = frodo_setsda, + .setscl = frodo_setscl, + .getsda = frodo_getsda, + .getscl = frodo_getscl, + .udelay = 80, + .mdelay = 80, + .timeout = 100 }; static int frodo_client_register (struct i2c_client *client) @@ -82,14 +82,13 @@ } static struct i2c_adapter frodo_ops = { - name: "Frodo adapter driver", - id: I2C_HW_B_FRODO, - algo: NULL, - algo_data: &bit_frodo_data, - inc_use: frodo_inc_use, - dec_use: frodo_dec_use, - client_register: frodo_client_register, - client_unregister: frodo_client_unregister + .name = "Frodo adapter driver", + .id = I2C_HW_B_FRODO, + .algo_data = &bit_frodo_data, + .inc_use = frodo_inc_use, + .dec_use = frodo_dec_use, + .client_register = frodo_client_register, + .client_unregister = frodo_client_unregister }; static int __init i2c_frodo_init (void) diff -Nru a/drivers/i2c/i2c-rpx.c b/drivers/i2c/i2c-rpx.c --- a/drivers/i2c/i2c-rpx.c Fri Nov 22 13:41:23 2002 +++ b/drivers/i2c/i2c-rpx.c Fri Nov 22 13:41:23 2002 @@ -91,7 +91,7 @@ } static struct i2c_algo_8xx_data rpx_data = { - setisr: rpx_install_isr + .setisr = rpx_install_isr }; diff -Nru a/drivers/i2c/scx200_acb.c b/drivers/i2c/scx200_acb.c --- a/drivers/i2c/scx200_acb.c Fri Nov 22 13:41:20 2002 +++ b/drivers/i2c/scx200_acb.c Fri Nov 22 13:41:20 2002 @@ -419,10 +419,10 @@ /* For now, we only handle combined mode (smbus) */ static struct i2c_algorithm scx200_acb_algorithm = { - name: "NatSemi SCx200 ACCESS.bus", - id: I2C_ALGO_SMBUS, - smbus_xfer: scx200_acb_smbus_xfer, - functionality: scx200_acb_func, + .name = "NatSemi SCx200 ACCESS.bus", + .id = I2C_ALGO_SMBUS, + .smbus_xfer = scx200_acb_smbus_xfer, + .functionality = scx200_acb_func, }; struct scx200_acb_iface *scx200_acb_list; diff -Nru a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c --- a/drivers/ide/ide-cd.c Fri Nov 22 13:41:19 2002 +++ b/drivers/ide/ide-cd.c Fri Nov 22 13:41:19 2002 @@ -908,7 +908,7 @@ ide_set_handler(drive, handler, rq->timeout, cdrom_timer_expiry); /* ATAPI commands get padded out to 12 bytes minimum */ - cmd_len = rq->cmd_len; + cmd_len = COMMAND_SIZE(rq->cmd[0]); if (cmd_len < ATAPI_MIN_CDB_BYTES) cmd_len = ATAPI_MIN_CDB_BYTES; diff -Nru a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c --- a/drivers/ide/legacy/hd.c Fri Nov 22 13:41:17 2002 +++ b/drivers/ide/legacy/hd.c Fri Nov 22 13:41:17 2002 @@ -26,9 +26,10 @@ /* Uncomment the following if you want verbose error reports. */ /* #define VERBOSE_ERRORS */ +#include #include #include -#include +#include #include #include #include @@ -45,7 +46,6 @@ #include #include #include -#include #ifdef __arm__ #undef HD_IRQ diff -Nru a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c --- a/drivers/ieee1394/dv1394.c Fri Nov 22 13:41:22 2002 +++ b/drivers/ieee1394/dv1394.c Fri Nov 22 13:41:22 2002 @@ -2579,7 +2579,7 @@ static int dv1394_devfs_add_dir(char *name) { - if (!devfs_mk_dir(NULL, name, NULL)) + if (!devfs_mk_dir(NULL, name, NULL)) { printk(KERN_ERR "dv1394: unable to create /dev/%s\n", name); return -ENOMEM; } diff -Nru a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c --- a/drivers/ieee1394/raw1394.c Fri Nov 22 13:41:17 2002 +++ b/drivers/ieee1394/raw1394.c Fri Nov 22 13:41:17 2002 @@ -90,10 +90,10 @@ static int arm_lock64 (struct hpsb_host *host, int nodeid, octlet_t *store, u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags); static struct hpsb_address_ops arm_ops = { - read: arm_read, - write: arm_write, - lock: arm_lock, - lock64: arm_lock64, + .read = arm_read, + .write = arm_write, + .lock = arm_lock, + .lock64 = arm_lock64, }; static void queue_complete_cb(struct pending_request *req); diff -Nru a/drivers/input/evbug.c b/drivers/input/evbug.c --- a/drivers/input/evbug.c Fri Nov 22 13:41:19 2002 +++ b/drivers/input/evbug.c Fri Nov 22 13:41:19 2002 @@ -74,7 +74,7 @@ } static struct input_device_id evbug_ids[] = { - { driver_info: 1 }, /* Matches all devices */ + { .driver_info = 1 }, /* Matches all devices */ { }, /* Terminating zero entry */ }; diff -Nru a/drivers/input/evdev.c b/drivers/input/evdev.c --- a/drivers/input/evdev.c Fri Nov 22 13:41:22 2002 +++ b/drivers/input/evdev.c Fri Nov 22 13:41:22 2002 @@ -419,7 +419,7 @@ } static struct input_device_id evdev_ids[] = { - { driver_info: 1 }, /* Matches all devices */ + { .driver_info = 1 }, /* Matches all devices */ { }, /* Terminating zero entry */ }; diff -Nru a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c --- a/drivers/input/misc/sparcspkr.c Fri Nov 22 13:41:23 2002 +++ b/drivers/input/misc/sparcspkr.c Fri Nov 22 13:41:23 2002 @@ -133,7 +133,7 @@ return 0; } -static int __init init_isa_beep(struct isa_device *isa_dev) +static int __init init_isa_beep(struct sparc_isa_device *isa_dev) { beep_iobase = isa_dev->resource.start; @@ -155,8 +155,8 @@ struct linux_ebus *ebus; struct linux_ebus_device *edev = NULL; #ifdef CONFIG_SPARC64 - struct isa_bridge *isa_br; - struct isa_device *isa_dev; + struct sparc_isa_bridge *isa_br; + struct sparc_isa_device *isa_dev; #endif for_each_ebus(ebus) { diff -Nru a/drivers/input/mouse/inport.c b/drivers/input/mouse/inport.c --- a/drivers/input/mouse/inport.c Fri Nov 22 13:41:20 2002 +++ b/drivers/input/mouse/inport.c Fri Nov 22 13:41:20 2002 @@ -34,14 +34,15 @@ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ -#include -#include - #include #include #include #include +#include #include + +#include +#include MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("Inport (ATI XL and Microsoft) busmouse driver"); diff -Nru a/drivers/input/mouse/logibm.c b/drivers/input/mouse/logibm.c --- a/drivers/input/mouse/logibm.c Fri Nov 22 13:41:20 2002 +++ b/drivers/input/mouse/logibm.c Fri Nov 22 13:41:20 2002 @@ -35,14 +35,15 @@ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ -#include -#include - #include #include #include #include #include +#include + +#include +#include MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("Logitech busmouse driver"); diff -Nru a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c --- a/drivers/input/mouse/pc110pad.c Fri Nov 22 13:41:18 2002 +++ b/drivers/input/mouse/pc110pad.c Fri Nov 22 13:41:18 2002 @@ -37,6 +37,7 @@ #include #include #include +#include #include #include diff -Nru a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c --- a/drivers/input/serio/ct82c710.c Fri Nov 22 13:41:17 2002 +++ b/drivers/input/serio/ct82c710.c Fri Nov 22 13:41:17 2002 @@ -28,16 +28,16 @@ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ -#include - #include #include #include #include #include +#include #include #include -#include + +#include MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("82C710 C&T mouse port chip driver"); @@ -61,8 +61,8 @@ #define CT82C710_IRQ 12 -static int ct82c710_data = 0; -static int ct82c710_status = 0; +static int ct82c710_data; +static int ct82c710_status; static void ct82c710_interrupt(int cpl, void *dev_id, struct pt_regs * regs); diff -Nru a/drivers/input/tsdev.c b/drivers/input/tsdev.c --- a/drivers/input/tsdev.c Fri Nov 22 13:41:23 2002 +++ b/drivers/input/tsdev.c Fri Nov 22 13:41:23 2002 @@ -350,17 +350,17 @@ static struct input_device_id tsdev_ids[] = { { - flags: INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT, - evbit: { BIT(EV_KEY) | BIT(EV_REL) }, - keybit: { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) }, - relbit: { BIT(REL_X) | BIT(REL_Y) }, + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT, + .evbit = { BIT(EV_KEY) | BIT(EV_REL) }, + .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) }, + .relbit = { BIT(REL_X) | BIT(REL_Y) }, },/* A mouse like device, at least one button, two relative axes */ { - flags: INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, - evbit: { BIT(EV_KEY) | BIT(EV_ABS) }, - keybit: { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) }, - absbit: { BIT(ABS_X) | BIT(ABS_Y) }, + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, + .evbit = { BIT(EV_KEY) | BIT(EV_ABS) }, + .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) }, + .absbit = { BIT(ABS_X) | BIT(ABS_Y) }, },/* A tablet like device, at least touch detection, two absolute axes */ {},/* Terminating entry */ diff -Nru a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c --- a/drivers/isdn/hisax/bkm_a8.c Fri Nov 22 13:41:22 2002 +++ b/drivers/isdn/hisax/bkm_a8.c Fri Nov 22 13:41:22 2002 @@ -278,8 +278,6 @@ static struct pci_dev *dev_a8 __initdata = NULL; static u16 sub_vendor_id __initdata = 0; static u16 sub_sys_id __initdata = 0; -static u_char pci_bus __initdata = 0; -static u_char pci_device_fn __initdata = 0; static u_char pci_irq __initdata = 0; #endif /* CONFIG_PCI */ @@ -328,8 +326,6 @@ return(0); pci_ioaddr1 = pci_resource_start(dev_a8, 1); pci_irq = dev_a8->irq; - pci_bus = dev_a8->bus->number; - pci_device_fn = dev_a8->devfn; found = 1; break; } @@ -342,20 +338,17 @@ } #ifdef ATTEMPT_PCI_REMAPPING /* HACK: PLX revision 1 bug: PLX address bit 7 must not be set */ - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_REVISION_ID, &pci_rev_id); + pci_read_config_byte(dev_a8, PCI_REVISION_ID, &pci_rev_id); if ((pci_ioaddr1 & 0x80) && (pci_rev_id == 1)) { printk(KERN_WARNING "HiSax: %s (%s): PLX rev 1, remapping required!\n", CardType[card->typ], sct_quadro_subtypes[cs->subtyp]); /* Restart PCI negotiation */ - pcibios_write_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_1, (u_int) - 1); + pci_write_config_dword(dev_a8, PCI_BASE_ADDRESS_1, (u_int) - 1); /* Move up by 0x80 byte */ pci_ioaddr1 += 0x80; pci_ioaddr1 &= PCI_BASE_ADDRESS_IO_MASK; - pcibios_write_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_1, pci_ioaddr1); + pci_write_config_dword(dev_a8, PCI_BASE_ADDRESS_1, pci_ioaddr1); dev_a8->resource[ 1].start = pci_ioaddr1; } #endif /* End HACK */ @@ -366,11 +359,11 @@ sct_quadro_subtypes[cs->subtyp]); return (0); } - pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &pci_ioaddr1); - pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_2, &pci_ioaddr2); - pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_3, &pci_ioaddr3); - pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_4, &pci_ioaddr4); - pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_5, &pci_ioaddr5); + pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_1, &pci_ioaddr1); + pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_2, &pci_ioaddr2); + pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_3, &pci_ioaddr3); + pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_4, &pci_ioaddr4); + pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_5, &pci_ioaddr5); if (!pci_ioaddr1 || !pci_ioaddr2 || !pci_ioaddr3 || !pci_ioaddr4 || !pci_ioaddr5) { printk(KERN_WARNING "HiSax: %s (%s): No IO base address(es)\n", CardType[card->typ], diff -Nru a/drivers/md/linear.c b/drivers/md/linear.c --- a/drivers/md/linear.c Fri Nov 22 13:41:19 2002 +++ b/drivers/md/linear.c Fri Nov 22 13:41:19 2002 @@ -58,15 +58,12 @@ { mddev_t *mddev = q->queuedata; dev_info_t *dev0; - int maxsectors, bio_sectors = (bio->bi_size + biovec->bv_len) >> 9; + unsigned long maxsectors, bio_sectors = bio->bi_size >> 9; dev0 = which_dev(mddev, bio->bi_sector); maxsectors = (dev0->size << 1) - (bio->bi_sector - (dev0->offset<<1)); - if (bio_sectors <= maxsectors) - return biovec->bv_len; - - return (maxsectors << 9) - bio->bi_size; + return (maxsectors - bio_sectors) << 9; } static int linear_run (mddev_t *mddev) diff -Nru a/drivers/md/md.c b/drivers/md/md.c --- a/drivers/md/md.c Fri Nov 22 13:41:18 2002 +++ b/drivers/md/md.c Fri Nov 22 13:41:18 2002 @@ -1621,10 +1621,6 @@ err = do_md_run (mddev); if (err) { printk(KERN_WARNING "md :do_md_run() returned %d\n", err); - /* - * prevent the writeback of an unrunnable array - */ - mddev->sb_dirty = 0; do_md_stop (mddev, 0); } } @@ -2354,11 +2350,11 @@ * we have to clean up the mess if * the array cannot be run for some * reason ... + * ->pers will not be set, to superblock will + * not be updated. */ - if (err) { - mddev->sb_dirty = 0; + if (err) do_md_stop (mddev, 0); - } goto done_unlock; } diff -Nru a/drivers/md/raid0.c b/drivers/md/raid0.c --- a/drivers/md/raid0.c Fri Nov 22 13:41:20 2002 +++ b/drivers/md/raid0.c Fri Nov 22 13:41:20 2002 @@ -173,15 +173,15 @@ static int raid0_mergeable_bvec(request_queue_t *q, struct bio *bio, struct bio_vec *biovec) { mddev_t *mddev = q->queuedata; - sector_t block; - unsigned int chunk_size; - unsigned int bio_sz; + sector_t sector; + unsigned int chunk_sectors; + unsigned int bio_sectors; - chunk_size = mddev->chunk_size >> 10; - block = bio->bi_sector >> 1; - bio_sz = (bio->bi_size + biovec->bv_len) >> 10; + chunk_sectors = mddev->chunk_size >> 9; + sector = bio->bi_sector; + bio_sectors = bio->bi_size >> 9; - return (chunk_size - ((block & (chunk_size - 1)) + bio_sz)) << 10; + return (chunk_sectors - ((sector & (chunk_sectors - 1)) + bio_sectors)) << 9; } static int raid0_run (mddev_t *mddev) diff -Nru a/drivers/md/raid5.c b/drivers/md/raid5.c --- a/drivers/md/raid5.c Fri Nov 22 13:41:18 2002 +++ b/drivers/md/raid5.c Fri Nov 22 13:41:18 2002 @@ -1215,7 +1215,7 @@ generic_make_request(bi); } else { PRINTK("skip op %ld on disc %d for sector %llu\n", bi->bi_rw, i, (unsigned long long)sh->sector); - clear_bit(R5_LOCKED, &dev->flags); + clear_bit(R5_LOCKED, &sh->dev[i].flags); set_bit(STRIPE_HANDLE, &sh->state); } } diff -Nru a/drivers/media/video/meye.c b/drivers/media/video/meye.c --- a/drivers/media/video/meye.c Fri Nov 22 13:41:21 2002 +++ b/drivers/media/video/meye.c Fri Nov 22 13:41:21 2002 @@ -1,7 +1,9 @@ /* * Motion Eye video4linux driver for Sony Vaio PictureBook * - * Copyright (C) 2001 Stelian Pop , Alcôve + * Copyright (C) 2001-2002 Stelian Pop + * + * Copyright (C) 2001-2002 Alcôve * * Copyright (C) 2000 Andrew Tridgell * @@ -169,16 +171,28 @@ meye.mchip_ptable[MCHIP_NB_PAGES] = pci_alloc_consistent(meye.mchip_dev, PAGE_SIZE, &meye.mchip_dmahandle); - if (!meye.mchip_ptable[MCHIP_NB_PAGES]) + if (!meye.mchip_ptable[MCHIP_NB_PAGES]) { + meye.mchip_dmahandle = 0; return -1; + } pt = (u32 *)meye.mchip_ptable[MCHIP_NB_PAGES]; for (i = 0; i < MCHIP_NB_PAGES; i++) { meye.mchip_ptable[i] = pci_alloc_consistent(meye.mchip_dev, PAGE_SIZE, pt); - if (!meye.mchip_ptable[i]) + if (!meye.mchip_ptable[i]) { + int j; + pt = (u32 *)meye.mchip_ptable[MCHIP_NB_PAGES]; + for (j = 0; j < i; ++j) { + pci_free_consistent(meye.mchip_dev, + PAGE_SIZE, + meye.mchip_ptable[j], *pt); + pt++; + } + meye.mchip_dmahandle = 0; return -1; + } pt++; } return 0; @@ -189,11 +203,13 @@ int i; pt = (u32 *)meye.mchip_ptable[MCHIP_NB_PAGES]; - for (i = 0; i < MCHIP_NB_PAGES; i++) + for (i = 0; i < MCHIP_NB_PAGES; i++) { if (meye.mchip_ptable[i]) pci_free_consistent(meye.mchip_dev, PAGE_SIZE, meye.mchip_ptable[i], *pt); + pt++; + } if (meye.mchip_ptable[MCHIP_NB_PAGES]) pci_free_consistent(meye.mchip_dev, @@ -569,6 +585,16 @@ mchip_load_tables(); } +/* sets the DMA parameters into the chip */ +static void mchip_dma_setup(u32 dma_addr) { + int i; + + mchip_set(MCHIP_MM_PT_ADDR, dma_addr); + for (i = 0; i < 4; i++) + mchip_set(MCHIP_MM_FIR(i), 0); + meye.mchip_fnum = 0; +} + /* setup for DMA transfers - also zeros the framebuffer */ static int mchip_dma_alloc(void) { if (!meye.mchip_dmahandle) @@ -579,18 +605,10 @@ /* frees the DMA buffer */ static void mchip_dma_free(void) { - if (meye.mchip_dmahandle) + if (meye.mchip_dmahandle) { + mchip_dma_setup(0); ptable_free(); -} - -/* sets the DMA parameters into the chip */ -static void mchip_dma_setup(void) { - int i; - - mchip_set(MCHIP_MM_PT_ADDR, meye.mchip_dmahandle); - for (i = 0; i < 4; i++) - mchip_set(MCHIP_MM_FIR(i), 0); - meye.mchip_fnum = 0; + } } /* stop any existing HIC action and wait for any dma to complete then @@ -698,7 +716,7 @@ mchip_hic_stop(); mchip_subsample(); - mchip_dma_setup(); + mchip_dma_setup(meye.mchip_dmahandle); mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_CAP); mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START); @@ -741,7 +759,7 @@ mchip_hic_stop(); mchip_subsample(); mchip_set_framerate(); - mchip_dma_setup(); + mchip_dma_setup(meye.mchip_dmahandle); meye.mchip_mode = MCHIP_HIC_MODE_CONT_OUT; @@ -801,7 +819,7 @@ mchip_vrj_setup(0x3f); mchip_subsample(); mchip_set_framerate(); - mchip_dma_setup(); + mchip_dma_setup(meye.mchip_dmahandle); meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP; @@ -823,7 +841,7 @@ while (1) { v = mchip_get_frame(); if (!(v & MCHIP_MM_FIR_RDY)) - goto out; + return; switch (meye.mchip_mode) { case MCHIP_HIC_MODE_CONT_OUT: @@ -856,12 +874,11 @@ default: /* do not free frame, since it can be a snap */ - goto out; + return; } /* switch */ mchip_free_frame(); } -out: } /****************************************************************************/ @@ -889,6 +906,7 @@ static int meye_release(struct inode *inode, struct file *file) { mchip_hic_stop(); + mchip_dma_free(); video_exclusive_release(inode,file); return 0; } @@ -957,7 +975,6 @@ case VIDIOCSYNC: { int *i = arg; - DECLARE_WAITQUEUE(wait, current); if (*i < 0 || *i >= gbuffers) return -EINVAL; @@ -967,18 +984,9 @@ case MEYE_BUF_UNUSED: return -EINVAL; case MEYE_BUF_USING: - add_wait_queue(&meye.grabq.proc_list, &wait); - current->state = TASK_INTERRUPTIBLE; - while (meye.grab_buffer[*i].state == MEYE_BUF_USING) { - schedule(); - if(signal_pending(current)) { - remove_wait_queue(&meye.grabq.proc_list, &wait); - current->state = TASK_RUNNING; - return -EINTR; - } - } - remove_wait_queue(&meye.grabq.proc_list, &wait); - current->state = TASK_RUNNING; + if (wait_event_interruptible(meye.grabq.proc_list, + (meye.grab_buffer[*i].state != MEYE_BUF_USING))) + return -EINTR; /* fall through */ case MEYE_BUF_DONE: meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; @@ -1095,7 +1103,6 @@ case MEYEIOC_SYNC: { int *i = arg; - DECLARE_WAITQUEUE(wait, current); if (*i < 0 || *i >= gbuffers) return -EINVAL; @@ -1105,18 +1112,9 @@ case MEYE_BUF_UNUSED: return -EINVAL; case MEYE_BUF_USING: - add_wait_queue(&meye.grabq.proc_list, &wait); - current->state = TASK_INTERRUPTIBLE; - while (meye.grab_buffer[*i].state == MEYE_BUF_USING) { - schedule(); - if(signal_pending(current)) { - remove_wait_queue(&meye.grabq.proc_list, &wait); - current->state = TASK_RUNNING; - return -EINTR; - } - } - remove_wait_queue(&meye.grabq.proc_list, &wait); - current->state = TASK_RUNNING; + if (wait_event_interruptible(meye.grabq.proc_list, + (meye.grab_buffer[*i].state != MEYE_BUF_USING))) + return -EINTR; /* fall through */ case MEYE_BUF_DONE: meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; @@ -1211,20 +1209,20 @@ } static struct file_operations meye_fops = { - owner: THIS_MODULE, - open: meye_open, - release: meye_release, - mmap: meye_mmap, - ioctl: meye_ioctl, - llseek: no_llseek, + .owner = THIS_MODULE, + .open = meye_open, + .release = meye_release, + .mmap = meye_mmap, + .ioctl = meye_ioctl, + .llseek = no_llseek, }; static struct video_device meye_template = { - owner: THIS_MODULE, - name: "meye", - type: VID_TYPE_CAPTURE, - hardware: VID_HARDWARE_MEYE, - fops: &meye_fops, + .owner = THIS_MODULE, + .name = "meye", + .type = VID_TYPE_CAPTURE, + .hardware = VID_HARDWARE_MEYE, + .fops = &meye_fops, }; static int __devinit meye_probe(struct pci_dev *pcidev, @@ -1244,15 +1242,9 @@ meye.mchip_dev = pcidev; memcpy(&meye.video_dev, &meye_template, sizeof(meye_template)); - if (mchip_dma_alloc()) { - printk(KERN_ERR "meye: mchip framebuffer allocation failed\n"); - ret = -ENOMEM; - goto out2; - } - if ((ret = pci_enable_device(meye.mchip_dev))) { printk(KERN_ERR "meye: pci_enable_device failed\n"); - goto out3; + goto out2; } meye.mchip_irq = pcidev->irq; @@ -1260,14 +1252,14 @@ if (!mchip_adr) { printk(KERN_ERR "meye: mchip has no device base address\n"); ret = -EIO; - goto out4; + goto out3; } if (!request_mem_region(pci_resource_start(meye.mchip_dev, 0), pci_resource_len(meye.mchip_dev, 0), "meye")) { ret = -EIO; printk(KERN_ERR "meye: request_mem_region failed\n"); - goto out4; + goto out3; } pci_read_config_byte(meye.mchip_dev, PCI_REVISION_ID, &revision); @@ -1280,14 +1272,14 @@ if ((ret = request_irq(meye.mchip_irq, meye_irq, SA_INTERRUPT | SA_SHIRQ, "meye", meye_irq))) { printk(KERN_ERR "meye: request_irq failed (ret=%d)\n", ret); - goto out5; + goto out4; } meye.mchip_mmregs = ioremap(mchip_adr, MCHIP_MM_REGS); if (!meye.mchip_mmregs) { printk(KERN_ERR "meye: ioremap failed\n"); ret = -EIO; - goto out6; + goto out5; } /* Ask the camera to perform a soft reset. */ @@ -1309,7 +1301,7 @@ printk(KERN_ERR "meye: video_register_device failed\n"); ret = -EIO; - goto out7; + goto out6; } printk(KERN_INFO "meye: Motion Eye Camera Driver v%d.%d.\n", @@ -1343,17 +1335,15 @@ sonypi_camera_command(SONYPI_COMMAND_SETCAMERAAGC, 48); return 0; -out7: - iounmap(meye.mchip_mmregs); out6: - free_irq(meye.mchip_irq, meye_irq); + iounmap(meye.mchip_mmregs); out5: + free_irq(meye.mchip_irq, meye_irq); +out4: release_mem_region(pci_resource_start(meye.mchip_dev, 0), pci_resource_len(meye.mchip_dev, 0)); -out4: - pci_disable_device(meye.mchip_dev); out3: - mchip_dma_free(); + pci_disable_device(meye.mchip_dev); out2: sonypi_camera_command(SONYPI_COMMAND_SETCAMERA, 0); out1: @@ -1371,7 +1361,6 @@ free_irq(meye.mchip_irq, meye_irq); - iounmap(meye.mchip_mmregs); release_mem_region(pci_resource_start(meye.mchip_dev, 0), @@ -1398,10 +1387,10 @@ MODULE_DEVICE_TABLE(pci, meye_pci_tbl); static struct pci_driver meye_driver = { - name: "meye", - id_table: meye_pci_tbl, - probe: meye_probe, - remove: __devexit_p(meye_remove), + .name = "meye", + .id_table = meye_pci_tbl, + .probe = meye_probe, + .remove = __devexit_p(meye_remove), }; static int __init meye_init_module(void) { @@ -1441,7 +1430,7 @@ __setup("meye=", meye_setup); #endif -MODULE_AUTHOR("Stelian Pop "); +MODULE_AUTHOR("Stelian Pop "); MODULE_DESCRIPTION("video4linux driver for the MotionEye camera"); MODULE_LICENSE("GPL"); diff -Nru a/drivers/media/video/meye.h b/drivers/media/video/meye.h --- a/drivers/media/video/meye.h Fri Nov 22 13:41:20 2002 +++ b/drivers/media/video/meye.h Fri Nov 22 13:41:20 2002 @@ -1,7 +1,9 @@ /* * Motion Eye video4linux driver for Sony Vaio PictureBook * - * Copyright (C) 2001 Stelian Pop , Alcôve + * Copyright (C) 2001-2002 Stelian Pop + * + * Copyright (C) 2001-2002 Alcôve * * Copyright (C) 2000 Andrew Tridgell * @@ -29,7 +31,7 @@ #define _MEYE_PRIV_H_ #define MEYE_DRIVER_MAJORVERSION 1 -#define MEYE_DRIVER_MINORVERSION 4 +#define MEYE_DRIVER_MINORVERSION 5 /****************************************************************************/ /* Motion JPEG chip registers */ diff -Nru a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c --- a/drivers/message/i2o/i2o_config.c Fri Nov 22 13:41:23 2002 +++ b/drivers/message/i2o/i2o_config.c Fri Nov 22 13:41:23 2002 @@ -904,14 +904,14 @@ static struct file_operations config_fops = { - owner: THIS_MODULE, - llseek: no_llseek, - read: cfg_read, - write: cfg_write, - ioctl: cfg_ioctl, - open: cfg_open, - release: cfg_release, - fasync: cfg_fasync, + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = cfg_read, + .write = cfg_write, + .ioctl = cfg_ioctl, + .open = cfg_open, + .release = cfg_release, + .fasync = cfg_fasync, }; static struct miscdevice i2o_miscdev = { diff -Nru a/drivers/message/i2o/i2o_pci.c b/drivers/message/i2o/i2o_pci.c --- a/drivers/message/i2o/i2o_pci.c Fri Nov 22 13:41:18 2002 +++ b/drivers/message/i2o/i2o_pci.c Fri Nov 22 13:41:18 2002 @@ -27,14 +27,16 @@ #include #include #include +#include #include + #include #ifdef CONFIG_MTRR #include #endif // CONFIG_MTRR -static int dpt = 0; +static int dpt; /** diff -Nru a/drivers/net/3c501.c b/drivers/net/3c501.c --- a/drivers/net/3c501.c Fri Nov 22 13:41:17 2002 +++ b/drivers/net/3c501.c Fri Nov 22 13:41:17 2002 @@ -110,7 +110,6 @@ #include #include -#include #include #include #include diff -Nru a/drivers/net/3c503.c b/drivers/net/3c503.c --- a/drivers/net/3c503.c Fri Nov 22 13:41:22 2002 +++ b/drivers/net/3c503.c Fri Nov 22 13:41:22 2002 @@ -42,9 +42,7 @@ DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Donald Becker (becker@scyld.com)\n"; #include - #include -#include #include #include #include diff -Nru a/drivers/net/3c505.c b/drivers/net/3c505.c --- a/drivers/net/3c505.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/3c505.c Fri Nov 22 13:41:23 2002 @@ -97,9 +97,7 @@ */ #include - #include -#include #include #include #include diff -Nru a/drivers/net/3c507.c b/drivers/net/3c507.c --- a/drivers/net/3c507.c Fri Nov 22 13:41:22 2002 +++ b/drivers/net/3c507.c Fri Nov 22 13:41:22 2002 @@ -32,9 +32,6 @@ static const char version[] = DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Donald Becker (becker@scyld.com)\n"; - -#include - /* Sources: This driver wouldn't have been written with the availability of the @@ -46,8 +43,8 @@ info that the casual reader might think that it documents the i82586 :-<. */ +#include #include -#include #include #include #include @@ -56,20 +53,18 @@ #include #include #include - -#include -#include -#include -#include -#include #include - #include #include #include #include #include +#include +#include +#include +#include +#include /* use 0 for production, 1 for verification, 2..7 for debug */ #ifndef NET_DEBUG diff -Nru a/drivers/net/3c509.c b/drivers/net/3c509.c --- a/drivers/net/3c509.c Fri Nov 22 13:41:17 2002 +++ b/drivers/net/3c509.c Fri Nov 22 13:41:17 2002 @@ -68,10 +68,8 @@ #include #include - #include #include -#include #include #include #include @@ -81,6 +79,7 @@ #include #include #include +#include #include #include /* for udelay() */ #include @@ -90,7 +89,6 @@ #include #include #include -#include static char versionA[] __initdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n"; static char versionB[] __initdata = "http://www.scyld.com/network/3c509.html\n"; diff -Nru a/drivers/net/3c515.c b/drivers/net/3c515.c --- a/drivers/net/3c515.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/3c515.c Fri Nov 22 13:41:18 2002 @@ -62,14 +62,15 @@ #include #include #include - #include -#include +#include #include #include #include #include #include +#include +#include #include #include #include @@ -78,10 +79,6 @@ #include #include #include - -#include -#include -#include #define NEW_MULTICAST #include diff -Nru a/drivers/net/3c523.c b/drivers/net/3c523.c --- a/drivers/net/3c523.c Fri Nov 22 13:41:20 2002 +++ b/drivers/net/3c523.c Fri Nov 22 13:41:20 2002 @@ -90,12 +90,15 @@ #define DRV_NAME "3c523" #define DRV_VERSION "17-Nov-2001" +#include +#include +#include #include #include -#include #include #include #include +#include #include #include #include @@ -106,11 +109,6 @@ #include #include #include - -#include -#include -#include -#include #include "3c523.h" diff -Nru a/drivers/net/3c527.c b/drivers/net/3c527.c --- a/drivers/net/3c527.c Fri Nov 22 13:41:20 2002 +++ b/drivers/net/3c527.c Fri Nov 22 13:41:20 2002 @@ -83,16 +83,22 @@ #include +#include +#include +#include +#include +#include #include -#include #include #include #include #include #include #include +#include #include #include +#include #include #include @@ -100,13 +106,6 @@ #include #include #include -#include -#include - -#include -#include -#include -#include #include "3c527.h" diff -Nru a/drivers/net/3c59x.c b/drivers/net/3c59x.c --- a/drivers/net/3c59x.c Fri Nov 22 13:41:17 2002 +++ b/drivers/net/3c59x.c Fri Nov 22 13:41:17 2002 @@ -244,7 +244,6 @@ #include #include #include -#include #include #include #include @@ -260,6 +259,7 @@ #include #include #include + #include /* For NR_IRQS only. */ #include #include diff -Nru a/drivers/net/68360enet.c b/drivers/net/68360enet.c --- a/drivers/net/68360enet.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/68360enet.c Fri Nov 22 13:41:18 2002 @@ -25,7 +25,6 @@ */ #include #include -#include #include #include #include @@ -38,6 +37,7 @@ #include #include #include + #include #include /* #include */ diff -Nru a/drivers/net/7990.c b/drivers/net/7990.c --- a/drivers/net/7990.c Fri Nov 22 13:41:22 2002 +++ b/drivers/net/7990.c Fri Nov 22 13:41:22 2002 @@ -12,35 +12,32 @@ * most of a2025 and sunlance with the aim of merging them, so the * common code was pretty obvious. */ +#include +#include +#include +#include +#include +#include +#include #include #include -#include #include #include #include #include #include +#include #include #include -#include -#include -#include +#include +/* Used for the temporal inet entries and routing */ +#include + #include #include #include #include #include -#include - -/* Used for the temporal inet entries and routing */ -#include -#include - -#include - -#include -#include -#include #include "7990.h" diff -Nru a/drivers/net/82596.c b/drivers/net/82596.c --- a/drivers/net/82596.c Fri Nov 22 13:41:22 2002 +++ b/drivers/net/82596.c Fri Nov 22 13:41:22 2002 @@ -42,9 +42,7 @@ #include #include - #include -#include #include #include #include diff -Nru a/drivers/net/a2065.c b/drivers/net/a2065.c --- a/drivers/net/a2065.c Fri Nov 22 13:41:20 2002 +++ b/drivers/net/a2065.c Fri Nov 22 13:41:20 2002 @@ -37,29 +37,27 @@ * both 10BASE-2 (thin coax) and AUI (DB-15) connectors */ +#include +#include +#include #include #include #include -#include #include #include +#include #include #include #include #include #include +#include #include #include -#include - #include #include -#include -#include -#include -#include #include "a2065.h" diff -Nru a/drivers/net/ac3200.c b/drivers/net/ac3200.c --- a/drivers/net/ac3200.c Fri Nov 22 13:41:21 2002 +++ b/drivers/net/ac3200.c Fri Nov 22 13:41:21 2002 @@ -25,9 +25,7 @@ "ac3200.c:v1.01 7/1/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; #include - #include -#include #include #include #include diff -Nru a/drivers/net/aironet4500_card.c b/drivers/net/aironet4500_card.c --- a/drivers/net/aironet4500_card.c Fri Nov 22 13:41:21 2002 +++ b/drivers/net/aironet4500_card.c Fri Nov 22 13:41:21 2002 @@ -16,28 +16,26 @@ "aironet4500_cards.c v0.2 Feb 27, 2000 Elmer Joandi, elmer@ylenurme.ee.\n"; #endif -#include +#include +#include +#include #include +#include +#include +#include #include - #include -#include +#include #include #include #include #include #include +#include + #include #include #include - -#include -#include -#include -#include -#include -#include -#include #include "aironet4500.h" diff -Nru a/drivers/net/aironet4500_core.c b/drivers/net/aironet4500_core.c --- a/drivers/net/aironet4500_core.c Fri Nov 22 13:41:17 2002 +++ b/drivers/net/aironet4500_core.c Fri Nov 22 13:41:17 2002 @@ -18,6 +18,7 @@ 10.03.00 looks like softnet take us back to normal on SMP */ +#include #include #include #include @@ -28,17 +29,16 @@ #include #include #include +#include +#include #include #include #include #include #include -#include -#include -#include + #include "aironet4500.h" -#include int bap_sleep = 10 ; diff -Nru a/drivers/net/aironet4500_proc.c b/drivers/net/aironet4500_proc.c --- a/drivers/net/aironet4500_proc.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/aironet4500_proc.c Fri Nov 22 13:41:18 2002 @@ -9,28 +9,25 @@ * * */ +#include +#include +#include #include +#include #include -#include +#include #include - #include - -#include +#include #include #include #include #include #include + #include #include #include - -#include -#include -#include -#include -#include #ifdef CONFIG_PROC_FS diff -Nru a/drivers/net/am79c961a.c b/drivers/net/am79c961a.c --- a/drivers/net/am79c961a.c Fri Nov 22 13:41:22 2002 +++ b/drivers/net/am79c961a.c Fri Nov 22 13:41:22 2002 @@ -14,7 +14,6 @@ * note that this can not be built as a module (it doesn't make sense). */ #include -#include #include #include #include diff -Nru a/drivers/net/apne.c b/drivers/net/apne.c --- a/drivers/net/apne.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/apne.c Fri Nov 22 13:41:23 2002 @@ -30,17 +30,15 @@ #include #include -#include #include #include #include #include -#include -#include - #include #include +#include +#include #include #include #include diff -Nru a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c --- a/drivers/net/appletalk/cops.c Fri Nov 22 13:41:20 2002 +++ b/drivers/net/appletalk/cops.c Fri Nov 22 13:41:20 2002 @@ -50,9 +50,7 @@ #include #include - #include -#include #include #include #include @@ -61,21 +59,20 @@ #include #include #include -#include -#include -#include -#include #include #include - #include #include #include - #include #include /* For ltalk_setup() */ #include /* For udelay() */ #include + +#include +#include +#include +#include #include "cops.h" /* Our Stuff */ #include "cops_ltdrv.h" /* Firmware code for Tangent type cards. */ diff -Nru a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c --- a/drivers/net/appletalk/ltpc.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/appletalk/ltpc.c Fri Nov 22 13:41:18 2002 @@ -208,7 +208,6 @@ #include #include -#include #include #include #include @@ -217,24 +216,21 @@ #include #include #include -#include -#include -#include -#include #include #include - #include #include #include - #include #include - #include #include - #include + +#include +#include +#include +#include /* our stuff */ #include "ltpc.h" diff -Nru a/drivers/net/ariadne.c b/drivers/net/ariadne.c --- a/drivers/net/ariadne.c Fri Nov 22 13:41:21 2002 +++ b/drivers/net/ariadne.c Fri Nov 22 13:41:21 2002 @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -48,12 +47,11 @@ #include #include #include +#include #include #include #include -#include - #include #include "ariadne.h" diff -Nru a/drivers/net/ariadne2.c b/drivers/net/ariadne2.c --- a/drivers/net/ariadne2.c Fri Nov 22 13:41:21 2002 +++ b/drivers/net/ariadne2.c Fri Nov 22 13:41:21 2002 @@ -21,7 +21,6 @@ #include #include -#include #include #include #include @@ -30,7 +29,6 @@ #include #include - #include #include #include diff -Nru a/drivers/net/at1700.c b/drivers/net/at1700.c --- a/drivers/net/at1700.c Fri Nov 22 13:41:19 2002 +++ b/drivers/net/at1700.c Fri Nov 22 13:41:19 2002 @@ -36,30 +36,27 @@ */ #include +#include +#include +#include +#include #include - #include -#include #include #include #include #include #include +#include #include #include #include #include + #include #include #include #include -#include - -#include -#include -#include - -#include static char version[] __initdata = "at1700.c:v1.15 4/7/98 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; diff -Nru a/drivers/net/atarilance.c b/drivers/net/atarilance.c --- a/drivers/net/atarilance.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/atarilance.c Fri Nov 22 13:41:18 2002 @@ -45,13 +45,14 @@ static char version[] = "atarilance.c: v1.3 04/04/96 " "Roman.Hodek@informatik.uni-erlangen.de\n"; +#include +#include #include - #include #include -#include #include #include +#include #include #include #include @@ -62,10 +63,6 @@ #include #include #include - -#include -#include -#include /* Debug level: * 0 = silent, print only serious errors diff -Nru a/drivers/net/atp.c b/drivers/net/atp.c --- a/drivers/net/atp.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/atp.c Fri Nov 22 13:41:23 2002 @@ -126,7 +126,6 @@ #include #include -#include #include #include #include @@ -134,19 +133,19 @@ #include #include #include -#include -#include -#include -#include #include #include #include - #include #include #include #include #include + +#include +#include +#include +#include #include "atp.h" diff -Nru a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c --- a/drivers/net/au1000_eth.c Fri Nov 22 13:41:20 2002 +++ b/drivers/net/au1000_eth.c Fri Nov 22 13:41:20 2002 @@ -33,7 +33,6 @@ #include #include -#include #include #include #include @@ -48,12 +47,13 @@ #include #include #include + #include #include #include #include - #include + #include "au1000_eth.h" #ifdef AU1000_ETH_DEBUG diff -Nru a/drivers/net/b44.c b/drivers/net/b44.c --- a/drivers/net/b44.c Fri Nov 22 13:41:19 2002 +++ b/drivers/net/b44.c Fri Nov 22 13:41:19 2002 @@ -12,7 +12,6 @@ #include #include #include -#include #include #include diff -Nru a/drivers/net/bagetlance.c b/drivers/net/bagetlance.c --- a/drivers/net/bagetlance.c Fri Nov 22 13:41:17 2002 +++ b/drivers/net/bagetlance.c Fri Nov 22 13:41:17 2002 @@ -15,24 +15,20 @@ static char *version = "bagetlance.c: v1.1 11/10/98\n"; #include - #include #include -#include #include #include #include #include #include - -#include -#include -#include - #include #include #include +#include +#include +#include #include #define BAGET_LANCE_IRQ BAGET_IRQ_MASK(0xdf) diff -Nru a/drivers/net/bonding.c b/drivers/net/bonding.c --- a/drivers/net/bonding.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/bonding.c Fri Nov 22 13:41:23 2002 @@ -196,7 +196,6 @@ #include #include #include -#include #include #include #include @@ -207,25 +206,24 @@ #include #include #include -#include -#include -#include -#include -#include #include - #include #include #include #include #include - #include #include #include #include #include #include + +#include +#include +#include +#include +#include /* monitor all links that often (in milliseconds). <=0 disables monitoring */ diff -Nru a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c --- a/drivers/net/cs89x0.c Fri Nov 22 13:41:22 2002 +++ b/drivers/net/cs89x0.c Fri Nov 22 13:41:22 2002 @@ -115,28 +115,27 @@ */ +#include +#include +#include #include -#include #include #include #include #include #include +#include #include +#include #include #include + #include #include #include #if ALLOW_DMA #include #endif -#include -#include - -#include -#include -#include #include "cs89x0.h" diff -Nru a/drivers/net/de600.c b/drivers/net/de600.c --- a/drivers/net/de600.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/de600.c Fri Nov 22 13:41:23 2002 @@ -54,25 +54,23 @@ #endif #include - #include -#include #include #include #include #include #include -#include #include #include #include #include #include - #include #include #include #include + +#include #include "de600.h" diff -Nru a/drivers/net/de620.c b/drivers/net/de620.c --- a/drivers/net/de620.c Fri Nov 22 13:41:20 2002 +++ b/drivers/net/de620.c Fri Nov 22 13:41:20 2002 @@ -117,24 +117,22 @@ #endif #include - #include -#include #include #include #include #include #include -#include #include -#include #include #include - #include #include #include #include + +#include +#include /* Constant definitions for the DE-620 registers, commands and bits */ #include "de620.h" diff -Nru a/drivers/net/declance.c b/drivers/net/declance.c --- a/drivers/net/declance.c Fri Nov 22 13:41:21 2002 +++ b/drivers/net/declance.c Fri Nov 22 13:41:21 2002 @@ -67,7 +67,6 @@ #include #include #include -#include #include #include #include diff -Nru a/drivers/net/defxx.c b/drivers/net/defxx.c --- a/drivers/net/defxx.c Fri Nov 22 13:41:17 2002 +++ b/drivers/net/defxx.c Fri Nov 22 13:41:17 2002 @@ -204,9 +204,7 @@ /* Include files */ #include - #include -#include #include #include #include @@ -216,12 +214,12 @@ #include #include #include +#include +#include + #include #include #include - -#include -#include #include "defxx.h" diff -Nru a/drivers/net/depca.c b/drivers/net/depca.c --- a/drivers/net/depca.c Fri Nov 22 13:41:20 2002 +++ b/drivers/net/depca.c Fri Nov 22 13:41:20 2002 @@ -236,9 +236,7 @@ #include #include - #include -#include #include #include #include @@ -247,19 +245,18 @@ #include #include #include -#include -#include -#include -#include - #include #include #include - #include #include #include #include + +#include +#include +#include +#include #ifdef CONFIG_MCA #include diff -Nru a/drivers/net/dgrs.c b/drivers/net/dgrs.c --- a/drivers/net/dgrs.c Fri Nov 22 13:41:17 2002 +++ b/drivers/net/dgrs.c Fri Nov 22 13:41:17 2002 @@ -85,7 +85,6 @@ #include #include -#include #include #include #include diff -Nru a/drivers/net/e2100.c b/drivers/net/e2100.c --- a/drivers/net/e2100.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/e2100.c Fri Nov 22 13:41:23 2002 @@ -37,9 +37,7 @@ "e2100.c:v1.01 7/21/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; #include - #include -#include #include #include #include diff -Nru a/drivers/net/eepro.c b/drivers/net/eepro.c --- a/drivers/net/eepro.c Fri Nov 22 13:41:22 2002 +++ b/drivers/net/eepro.c Fri Nov 22 13:41:22 2002 @@ -131,7 +131,6 @@ */ #include -#include #include #include #include @@ -139,18 +138,18 @@ #include #include #include -#include -#include -#include -#include #include - #include #include #include #include #include #include + +#include +#include +#include +#include #define compat_dev_kfree_skb( skb, mode ) dev_kfree_skb( (skb) ) /* I had reports of looong delays with SLOW_DOWN defined as udelay(2) */ diff -Nru a/drivers/net/eexpress.c b/drivers/net/eexpress.c --- a/drivers/net/eexpress.c Fri Nov 22 13:41:17 2002 +++ b/drivers/net/eexpress.c Fri Nov 22 13:41:17 2002 @@ -99,30 +99,27 @@ #include #include - #include -#include #include #include #include #include #include #include -#include -#include -#include -#include #include #include #include - #include #include #include #include #include - #include + +#include +#include +#include +#include #ifndef NET_DEBUG #define NET_DEBUG 4 diff -Nru a/drivers/net/es3210.c b/drivers/net/es3210.c --- a/drivers/net/es3210.c Fri Nov 22 13:41:22 2002 +++ b/drivers/net/es3210.c Fri Nov 22 13:41:22 2002 @@ -50,15 +50,15 @@ #include #include -#include #include #include #include +#include +#include + #include #include -#include -#include #include "8390.h" int es_probe(struct net_device *dev); diff -Nru a/drivers/net/eth16i.c b/drivers/net/eth16i.c --- a/drivers/net/eth16i.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/eth16i.c Fri Nov 22 13:41:18 2002 @@ -146,9 +146,7 @@ "eth16i.c: v0.35 01-Jul-1999 Mika Kuoppala (miku@iki.fi)\n"; #include - #include -#include #include #include #include @@ -159,7 +157,6 @@ #include #include #include - #include #include #include diff -Nru a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c --- a/drivers/net/ewrk3.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/ewrk3.c Fri Nov 22 13:41:23 2002 @@ -144,9 +144,7 @@ */ #include - #include -#include #include #include #include @@ -155,20 +153,19 @@ #include #include #include -#include -#include -#include -#include - #include #include #include #include - #include #include #include #include + +#include +#include +#include +#include #include "ewrk3.h" diff -Nru a/drivers/net/fc/iph5526.c b/drivers/net/fc/iph5526.c --- a/drivers/net/fc/iph5526.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/fc/iph5526.c Fri Nov 22 13:41:18 2002 @@ -37,26 +37,27 @@ #include #include -#include #include #include #include +#include #include #include #include #include #include #include -#include -#include - #include -#include /* had the declarations for init_fcdev among others + includes if_fcdevice.h */ - #include +#include /* had the declarations for init_fcdev among + others + includes if_fcdevice.h */ + #include "../../scsi/scsi.h" #include "../../scsi/hosts.h" #include "../../fc4/fcp.h" + +#include +#include /* driver specific header files */ #include "tach.h" diff -Nru a/drivers/net/fealnx.c b/drivers/net/fealnx.c --- a/drivers/net/fealnx.c Fri Nov 22 13:41:22 2002 +++ b/drivers/net/fealnx.c Fri Nov 22 13:41:22 2002 @@ -70,7 +70,6 @@ /* Include files, designed to support most kernel versions 2.0.0 and later. */ #include #include -#include #include #include #include @@ -85,6 +84,7 @@ #include #include #include + #include /* Processor type for cache alignment. */ #include #include diff -Nru a/drivers/net/fec.c b/drivers/net/fec.c --- a/drivers/net/fec.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/fec.c Fri Nov 22 13:41:18 2002 @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -40,6 +39,7 @@ #include #include #include + #include #include #include diff -Nru a/drivers/net/fmv18x.c b/drivers/net/fmv18x.c --- a/drivers/net/fmv18x.c Fri Nov 22 13:41:17 2002 +++ b/drivers/net/fmv18x.c Fri Nov 22 13:41:17 2002 @@ -36,9 +36,7 @@ "fmv18x.c:v2.2.0 09/24/98 Yutaka TAMIYA (tamy@flab.fujitsu.co.jp)\n"; #include - #include -#include #include #include #include @@ -47,17 +45,17 @@ #include #include #include -#include -#include -#include -#include #include #include - #include #include #include #include + +#include +#include +#include +#include static int fmv18x_probe_list[] __initdata = { 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0 diff -Nru a/drivers/net/gt96100eth.c b/drivers/net/gt96100eth.c --- a/drivers/net/gt96100eth.c Fri Nov 22 13:41:22 2002 +++ b/drivers/net/gt96100eth.c Fri Nov 22 13:41:22 2002 @@ -46,7 +46,6 @@ #include #include -#include #include #include #include @@ -61,6 +60,7 @@ #include #include #include + #include #include #include diff -Nru a/drivers/net/hamachi.c b/drivers/net/hamachi.c --- a/drivers/net/hamachi.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/hamachi.c Fri Nov 22 13:41:23 2002 @@ -154,7 +154,6 @@ #include #include -#include #include #include #include @@ -166,6 +165,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include /* Processor type for cache alignment. */ @@ -173,12 +177,6 @@ #include #include #include - -#include -#include -#include -#include -#include static char version[] __initdata = KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker\n" diff -Nru a/drivers/net/hamradio/baycom_par.c b/drivers/net/hamradio/baycom_par.c --- a/drivers/net/hamradio/baycom_par.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/hamradio/baycom_par.c Fri Nov 22 13:41:23 2002 @@ -71,16 +71,12 @@ #include #include #include -#include #include #include #include #include #include #include -#include -#include -#include #include #include #include @@ -88,6 +84,10 @@ #include #include #include + +#include +#include +#include /* --------------------------------------------------------------------- */ diff -Nru a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c --- a/drivers/net/hamradio/scc.c Fri Nov 22 13:41:22 2002 +++ b/drivers/net/hamradio/scc.c Fri Nov 22 13:41:22 2002 @@ -152,7 +152,6 @@ #include #include #include -#include #include #include #include @@ -162,27 +161,26 @@ #include #include #include - #include #include #include #include #include #include - #include -#include "z8530.h" +#include +#include +#include #include + #include #include #include #include #include -#include -#include -#include +#include "z8530.h" static char banner[] __initdata = KERN_INFO "AX.25: Z8530 SCC driver version "VERSION".dl1bke\n"; diff -Nru a/drivers/net/hamradio/soundmodem/sm_sbc.c b/drivers/net/hamradio/soundmodem/sm_sbc.c --- a/drivers/net/hamradio/soundmodem/sm_sbc.c Fri Nov 22 13:41:22 2002 +++ b/drivers/net/hamradio/soundmodem/sm_sbc.c Fri Nov 22 13:41:22 2002 @@ -26,13 +26,14 @@ */ #include -#include #include -#include -#include #include #include #include + +#include +#include + #include "sm.h" #include "smdma.h" diff -Nru a/drivers/net/hamradio/soundmodem/sm_wss.c b/drivers/net/hamradio/soundmodem/sm_wss.c --- a/drivers/net/hamradio/soundmodem/sm_wss.c Fri Nov 22 13:41:19 2002 +++ b/drivers/net/hamradio/soundmodem/sm_wss.c Fri Nov 22 13:41:19 2002 @@ -26,12 +26,13 @@ */ #include -#include #include -#include -#include #include #include + +#include +#include + #include "sm.h" #include "smdma.h" diff -Nru a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c --- a/drivers/net/hp-plus.c Fri Nov 22 13:41:17 2002 +++ b/drivers/net/hp-plus.c Fri Nov 22 13:41:17 2002 @@ -25,7 +25,6 @@ #include /* Important -- this inlines word moves. */ #include -#include #include #include #include @@ -35,7 +34,6 @@ #include #include - #include "8390.h" diff -Nru a/drivers/net/hp.c b/drivers/net/hp.c --- a/drivers/net/hp.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/hp.c Fri Nov 22 13:41:18 2002 @@ -24,9 +24,7 @@ #include - #include -#include #include #include #include diff -Nru a/drivers/net/hp100.c b/drivers/net/hp100.c --- a/drivers/net/hp100.c Fri Nov 22 13:41:19 2002 +++ b/drivers/net/hp100.c Fri Nov 22 13:41:19 2002 @@ -99,7 +99,6 @@ #include #include #include -#include #include #include #include @@ -107,17 +106,16 @@ #include #include #include -#include -#include - #include #include #include - #include #include /* for CONFIG_PCI */ #include #include + +#include +#include #define LINUX_2_1 typedef struct net_device_stats hp100_stats_t; diff -Nru a/drivers/net/hplance.c b/drivers/net/hplance.c --- a/drivers/net/hplance.c Fri Nov 22 13:41:19 2002 +++ b/drivers/net/hplance.c Fri Nov 22 13:41:19 2002 @@ -7,7 +7,6 @@ #include #include -#include #include #include #include @@ -16,19 +15,17 @@ #include #include #include -#include -#include -#include - /* Used for the temporal inet entries and routing */ #include #include - #include - #include #include #include + +#include +#include +#include #include "hplance.h" diff -Nru a/drivers/net/hydra.c b/drivers/net/hydra.c --- a/drivers/net/hydra.c Fri Nov 22 13:41:19 2002 +++ b/drivers/net/hydra.c Fri Nov 22 13:41:19 2002 @@ -14,7 +14,6 @@ #include #include -#include #include #include #include @@ -28,7 +27,6 @@ #include #include #include - #include #include #include diff -Nru a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c --- a/drivers/net/ibmlana.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/ibmlana.c Fri Nov 22 13:41:18 2002 @@ -76,7 +76,6 @@ #include #include -#include #include #include #include @@ -85,15 +84,14 @@ #include #include #include -#include -#include -#include - #include - #include #include #include + +#include +#include +#include #define _IBM_LANA_DRIVER_ #include "ibmlana.h" diff -Nru a/drivers/net/irda/act200l.c b/drivers/net/irda/act200l.c --- a/drivers/net/irda/act200l.c Fri Nov 22 13:41:20 2002 +++ b/drivers/net/irda/act200l.c Fri Nov 22 13:41:20 2002 @@ -21,7 +21,6 @@ #include #include #include -#include #include #include diff -Nru a/drivers/net/irda/actisys.c b/drivers/net/irda/actisys.c --- a/drivers/net/irda/actisys.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/irda/actisys.c Fri Nov 22 13:41:23 2002 @@ -38,7 +38,6 @@ #include #include #include -#include #include #include diff -Nru a/drivers/net/irda/ep7211_ir.c b/drivers/net/irda/ep7211_ir.c --- a/drivers/net/irda/ep7211_ir.c Fri Nov 22 13:41:17 2002 +++ b/drivers/net/irda/ep7211_ir.c Fri Nov 22 13:41:17 2002 @@ -7,7 +7,6 @@ #include #include #include -#include #include #include diff -Nru a/drivers/net/irda/esi.c b/drivers/net/irda/esi.c --- a/drivers/net/irda/esi.c Fri Nov 22 13:41:20 2002 +++ b/drivers/net/irda/esi.c Fri Nov 22 13:41:20 2002 @@ -31,10 +31,8 @@ ********************************************************************/ #include - #include #include -#include #include #include diff -Nru a/drivers/net/irda/girbil.c b/drivers/net/irda/girbil.c --- a/drivers/net/irda/girbil.c Fri Nov 22 13:41:17 2002 +++ b/drivers/net/irda/girbil.c Fri Nov 22 13:41:17 2002 @@ -25,7 +25,6 @@ #include #include #include -#include #include #include diff -Nru a/drivers/net/irda/litelink.c b/drivers/net/irda/litelink.c --- a/drivers/net/irda/litelink.c Fri Nov 22 13:41:20 2002 +++ b/drivers/net/irda/litelink.c Fri Nov 22 13:41:20 2002 @@ -31,7 +31,6 @@ #include #include #include -#include #include #include diff -Nru a/drivers/net/irda/ma600.c b/drivers/net/irda/ma600.c --- a/drivers/net/irda/ma600.c Fri Nov 22 13:41:19 2002 +++ b/drivers/net/irda/ma600.c Fri Nov 22 13:41:19 2002 @@ -37,7 +37,6 @@ #include #include #include -#include #include #include diff -Nru a/drivers/net/irda/mcp2120.c b/drivers/net/irda/mcp2120.c --- a/drivers/net/irda/mcp2120.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/irda/mcp2120.c Fri Nov 22 13:41:23 2002 @@ -21,7 +21,6 @@ #include #include #include -#include #include #include diff -Nru a/drivers/net/irda/old_belkin.c b/drivers/net/irda/old_belkin.c --- a/drivers/net/irda/old_belkin.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/irda/old_belkin.c Fri Nov 22 13:41:23 2002 @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include diff -Nru a/drivers/net/irda/sir_kthread.c b/drivers/net/irda/sir_kthread.c --- a/drivers/net/irda/sir_kthread.c Fri Nov 22 13:41:22 2002 +++ b/drivers/net/irda/sir_kthread.c Fri Nov 22 13:41:22 2002 @@ -19,7 +19,6 @@ #include #include #include -#include #include diff -Nru a/drivers/net/irda/tekram.c b/drivers/net/irda/tekram.c --- a/drivers/net/irda/tekram.c Fri Nov 22 13:41:20 2002 +++ b/drivers/net/irda/tekram.c Fri Nov 22 13:41:20 2002 @@ -25,7 +25,6 @@ #include #include #include -#include #include #include diff -Nru a/drivers/net/isa-skeleton.c b/drivers/net/isa-skeleton.c --- a/drivers/net/isa-skeleton.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/isa-skeleton.c Fri Nov 22 13:41:23 2002 @@ -41,9 +41,7 @@ */ #include - #include -#include #include #include #include @@ -51,17 +49,17 @@ #include #include #include -#include -#include #include -#include -#include #include #include - #include #include #include + +#include +#include +#include +#include /* * The name of the card. Is used for messages and in the requests for diff -Nru a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c --- a/drivers/net/jazzsonic.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/jazzsonic.c Fri Nov 22 13:41:18 2002 @@ -14,7 +14,6 @@ */ #include -#include #include #include #include @@ -24,6 +23,11 @@ #include #include #include +#include +#include +#include +#include + #include #include #include @@ -32,11 +36,6 @@ #include #include #include -#include - -#include -#include -#include #define SREGS_PAD(n) u16 n; diff -Nru a/drivers/net/lance.c b/drivers/net/lance.c --- a/drivers/net/lance.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/lance.c Fri Nov 22 13:41:18 2002 @@ -43,7 +43,6 @@ #include #include -#include #include #include #include @@ -51,13 +50,13 @@ #include #include #include -#include -#include -#include - #include #include #include + +#include +#include +#include static unsigned int lance_portlist[] __initdata = { 0x300, 0x320, 0x340, 0x360, 0}; int lance_probe(struct net_device *dev); diff -Nru a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c --- a/drivers/net/lasi_82596.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/lasi_82596.c Fri Nov 22 13:41:18 2002 @@ -69,9 +69,7 @@ */ #include - #include -#include #include #include #include @@ -91,7 +89,6 @@ #include #include #include - #include #include diff -Nru a/drivers/net/lne390.c b/drivers/net/lne390.c --- a/drivers/net/lne390.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/lne390.c Fri Nov 22 13:41:23 2002 @@ -36,17 +36,16 @@ #include #include -#include #include #include #include #include +#include +#include #include #include -#include -#include #include "8390.h" int lne390_probe(struct net_device *dev); diff -Nru a/drivers/net/lp486e.c b/drivers/net/lp486e.c --- a/drivers/net/lp486e.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/lp486e.c Fri Nov 22 13:41:18 2002 @@ -62,7 +62,6 @@ #include #include #include -#include #include #include #include diff -Nru a/drivers/net/mac8390.c b/drivers/net/mac8390.c --- a/drivers/net/mac8390.c Fri Nov 22 13:41:20 2002 +++ b/drivers/net/mac8390.c Fri Nov 22 13:41:20 2002 @@ -17,9 +17,7 @@ #include #include - #include -#include #include #include #include @@ -29,18 +27,19 @@ #include #include #include +#include +#include +#include +#include +#include + #include #include #include #include #include #include -#include -#include -#include -#include -#include #include "8390.h" #if (LINUX_VERSION_CODE < 0x02030e) diff -Nru a/drivers/net/mac89x0.c b/drivers/net/mac89x0.c --- a/drivers/net/mac89x0.c Fri Nov 22 13:41:20 2002 +++ b/drivers/net/mac89x0.c Fri Nov 22 13:41:20 2002 @@ -84,7 +84,6 @@ */ #include -#include #include #include #include @@ -93,17 +92,18 @@ #include #include #include +#include +#include +#include +#include +#include + #include #include #include #include #include -#include -#include -#include -#include -#include #include "cs89x0.h" static unsigned int net_debug = NET_DEBUG; diff -Nru a/drivers/net/macsonic.c b/drivers/net/macsonic.c --- a/drivers/net/macsonic.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/macsonic.c Fri Nov 22 13:41:18 2002 @@ -26,7 +26,6 @@ */ #include -#include #include #include #include @@ -38,6 +37,12 @@ #include #include #include +#include +#include +#include +#include +#include + #include #include #include @@ -49,13 +54,6 @@ #include #include #include - -#include - -#include -#include -#include -#include #define SREGS_PAD(n) u16 n; diff -Nru a/drivers/net/mvme147.c b/drivers/net/mvme147.c --- a/drivers/net/mvme147.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/mvme147.c Fri Nov 22 13:41:18 2002 @@ -7,7 +7,6 @@ #include #include -#include #include #include #include @@ -16,20 +15,17 @@ #include #include #include -#include -#include -#include - /* Used for the temporal inet entries and routing */ #include #include - #include - #include #include #include +#include +#include +#include #include /* We have 16834 bytes of RAM for the init block and buffers. This places diff -Nru a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c --- a/drivers/net/myri_sbus.c Fri Nov 22 13:41:17 2002 +++ b/drivers/net/myri_sbus.c Fri Nov 22 13:41:17 2002 @@ -7,10 +7,9 @@ "myri_sbus.c:v1.9 12/Sep/99 David S. Miller (davem@redhat.com)\n"; #include - #include +#include #include -#include #include #include #include @@ -20,14 +19,20 @@ #include #include #include +#include +#include +#include + +#include +#include +#include +#include #include #include #include #include -#include #include - #include #include #include @@ -35,20 +40,9 @@ #include #include #include - -#include -#include -#include - -#include -#include -#include -#include - #include #include "myri_sbus.h" - #include "myri_code.h" /* #define DEBUG_DETECT */ diff -Nru a/drivers/net/ne.c b/drivers/net/ne.c --- a/drivers/net/ne.c Fri Nov 22 13:41:19 2002 +++ b/drivers/net/ne.c Fri Nov 22 13:41:19 2002 @@ -42,16 +42,17 @@ #include #include -#include #include #include #include +#include #include +#include +#include + #include #include -#include -#include #include "8390.h" /* Some defines that people can play with if so inclined. */ diff -Nru a/drivers/net/ne2.c b/drivers/net/ne2.c --- a/drivers/net/ne2.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/ne2.c Fri Nov 22 13:41:23 2002 @@ -61,9 +61,7 @@ #include #include - #include -#include #include #include #include @@ -71,20 +69,19 @@ #include #include #include -#include -#include -#include -#include #include #include #include - #include #include #include -#include "8390.h" +#include +#include +#include +#include +#include "8390.h" /* Some defines that people can play with if so inclined. */ diff -Nru a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c --- a/drivers/net/ne2k-pci.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/ne2k-pci.c Fri Nov 22 13:41:18 2002 @@ -46,19 +46,19 @@ #include #include -#include #include #include #include +#include #include +#include +#include #include #include #include #include -#include -#include #include "8390.h" /* These identify the driver base version and may not be removed. */ diff -Nru a/drivers/net/ne3210.c b/drivers/net/ne3210.c --- a/drivers/net/ne3210.c Fri Nov 22 13:41:19 2002 +++ b/drivers/net/ne3210.c Fri Nov 22 13:41:19 2002 @@ -30,17 +30,17 @@ #include #include -#include #include #include #include #include +#include +#include +#include #include #include -#include -#include #include "8390.h" int ne3210_probe(struct net_device *dev); diff -Nru a/drivers/net/net_init.c b/drivers/net/net_init.c --- a/drivers/net/net_init.c Fri Nov 22 13:41:17 2002 +++ b/drivers/net/net_init.c Fri Nov 22 13:41:17 2002 @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include diff -Nru a/drivers/net/ni65.c b/drivers/net/ni65.c --- a/drivers/net/ni65.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/ni65.c Fri Nov 22 13:41:18 2002 @@ -62,7 +62,6 @@ */ #include -#include #include #include #include @@ -70,16 +69,15 @@ #include #include #include -#include -#include -#include - #include #include #include - #include #include + +#include +#include +#include #include "ni65.h" diff -Nru a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c --- a/drivers/net/pcmcia/3c574_cs.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/pcmcia/3c574_cs.c Fri Nov 22 13:41:18 2002 @@ -70,24 +70,18 @@ #include #include #include -#include #include #include #include #include #include #include -#include -#include -#include - #include #include #include #include #include #include -#include #include #include @@ -97,6 +91,11 @@ #include #include #include + +#include +#include +#include +#include /*====================================================================*/ diff -Nru a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c --- a/drivers/net/pcmcia/3c589_cs.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/pcmcia/3c589_cs.c Fri Nov 22 13:41:23 2002 @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -34,12 +33,6 @@ #include #include #include - -#include -#include -#include -#include - #include #include #include @@ -53,6 +46,11 @@ #include #include #include + +#include +#include +#include +#include /* To minimize the size of the driver source I only define operating constants if they are used several times. You'll need the manual diff -Nru a/drivers/net/pcmcia/aironet4500_cs.c b/drivers/net/pcmcia/aironet4500_cs.c --- a/drivers/net/pcmcia/aironet4500_cs.c Fri Nov 22 13:41:17 2002 +++ b/drivers/net/pcmcia/aironet4500_cs.c Fri Nov 22 13:41:17 2002 @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -28,19 +27,12 @@ #include #include #include - -#include -#include -#include -#include - #include #include #include #include #include - #include #include #include @@ -54,8 +46,12 @@ #endif #include -#include "../aironet4500.h" +#include +#include +#include +#include +#include "../aironet4500.h" static u_int irq_mask = 0x5eF8; static int awc_ports[] = {0x140,0x100,0xc0, 0x80 }; diff -Nru a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c --- a/drivers/net/pcmcia/axnet_cs.c Fri Nov 22 13:41:20 2002 +++ b/drivers/net/pcmcia/axnet_cs.c Fri Nov 22 13:41:20 2002 @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -35,11 +34,6 @@ #include #include #include -#include -#include -#include -#include - #include #include "../8390.h" @@ -50,6 +44,11 @@ #include #include #include + +#include +#include +#include +#include #define AXNET_CMD 0x00 #define AXNET_DATAPORT 0x10 /* NatSemi-defined port window offset. */ diff -Nru a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c --- a/drivers/net/pcmcia/com20020_cs.c Fri Nov 22 13:41:19 2002 +++ b/drivers/net/pcmcia/com20020_cs.c Fri Nov 22 13:41:19 2002 @@ -33,16 +33,12 @@ */ #include #include -#include #include #include #include #include #include #include -#include -#include - #include #include #include @@ -52,6 +48,9 @@ #include #include #include + +#include +#include #define VERSION "arcnet: COM20020 PCMCIA support loaded.\n" diff -Nru a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c --- a/drivers/net/pcmcia/fmvj18x_cs.c Fri Nov 22 13:41:21 2002 +++ b/drivers/net/pcmcia/fmvj18x_cs.c Fri Nov 22 13:41:21 2002 @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -43,11 +42,6 @@ #include #include #include - -#include -#include -#include - #include #include #include @@ -61,6 +55,10 @@ #include #include #include + +#include +#include +#include /*====================================================================*/ diff -Nru a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c --- a/drivers/net/pcmcia/ibmtr_cs.c Fri Nov 22 13:41:20 2002 +++ b/drivers/net/pcmcia/ibmtr_cs.c Fri Nov 22 13:41:20 2002 @@ -47,17 +47,12 @@ #include #include -#include #include #include #include #include #include #include -#include -#include -#include - #include #include #include @@ -67,6 +62,10 @@ #include #include #include + +#include +#include +#include #define PCMCIA #include "../tokenring/ibmtr.c" diff -Nru a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c --- a/drivers/net/pcmcia/nmclan_cs.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/pcmcia/nmclan_cs.c Fri Nov 22 13:41:18 2002 @@ -126,7 +126,6 @@ #include #include #include -#include #include #include #include @@ -135,12 +134,6 @@ #include #include #include - -#include -#include -#include -#include - #include #include #include @@ -153,6 +146,11 @@ #include #include #include + +#include +#include +#include +#include /* ---------------------------------------------------------------------------- Defines diff -Nru a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c --- a/drivers/net/pcmcia/pcnet_cs.c Fri Nov 22 13:41:22 2002 +++ b/drivers/net/pcmcia/pcnet_cs.c Fri Nov 22 13:41:22 2002 @@ -31,18 +31,12 @@ #include #include #include -#include #include #include #include #include #include #include -#include -#include -#include -#include - #include #include <../drivers/net/8390.h> @@ -53,6 +47,11 @@ #include #include #include + +#include +#include +#include +#include #define PCNET_CMD 0x00 #define PCNET_DATAPORT 0x10 /* NatSemi-defined port window offset. */ diff -Nru a/drivers/net/pcmcia/ray_cs.c b/drivers/net/pcmcia/ray_cs.c --- a/drivers/net/pcmcia/ray_cs.c Fri Nov 22 13:41:19 2002 +++ b/drivers/net/pcmcia/ray_cs.c Fri Nov 22 13:41:19 2002 @@ -31,25 +31,18 @@ #include #include #include -#include #include #include #include #include #include #include - -#include -#include -#include - #include #include #include #include #include #include -#include #include #include @@ -61,6 +54,11 @@ #ifdef CONFIG_NET_PCMCIA_RADIO #include + +#include +#include +#include +#include /* Warning : these stuff will slow down the driver... */ #define WIRELESS_SPY /* Enable spying addresses */ diff -Nru a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c --- a/drivers/net/pcmcia/smc91c92_cs.c Fri Nov 22 13:41:21 2002 +++ b/drivers/net/pcmcia/smc91c92_cs.c Fri Nov 22 13:41:21 2002 @@ -28,17 +28,12 @@ #include #include #include -#include #include #include #include #include #include #include -#include -#include -#include - #include #include #include @@ -54,6 +49,10 @@ #include #include #include + +#include +#include +#include /* Ositech Seven of Diamonds firmware */ #include "ositech.h" diff -Nru a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c --- a/drivers/net/pcmcia/xirc2ps_cs.c Fri Nov 22 13:41:19 2002 +++ b/drivers/net/pcmcia/xirc2ps_cs.c Fri Nov 22 13:41:19 2002 @@ -66,7 +66,6 @@ #include #include #include -#include #include #include #include @@ -75,11 +74,6 @@ #include #include #include -#include -#include -#include -#include - #include #include #include @@ -92,6 +86,11 @@ #include #include #include + +#include +#include +#include +#include #ifndef MANFID_COMPAQ #define MANFID_COMPAQ 0x0138 diff -Nru a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c --- a/drivers/net/pcnet32.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/pcnet32.c Fri Nov 22 13:41:18 2002 @@ -30,9 +30,7 @@ DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " tsbogend@alpha.franken.de\n"; #include - #include -#include #include #include #include @@ -44,15 +42,15 @@ #include #include #include -#include -#include -#include -#include - #include #include #include #include + +#include +#include +#include +#include /* * PCI device identifiers for "new style" Linux PCI Device Drivers diff -Nru a/drivers/net/plip.c b/drivers/net/plip.c --- a/drivers/net/plip.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/plip.c Fri Nov 22 13:41:23 2002 @@ -90,35 +90,33 @@ #include #include -#include #include #include #include #include #include -#include #include #include #include #include #include - #include #include #include #include #include -#include - #include #include #include +#include + +#include + +#include #include #include #include #include - -#include /* Maximum number of devices to support. */ #define PLIP_MAX 8 diff -Nru a/drivers/net/pppoe.c b/drivers/net/pppoe.c --- a/drivers/net/pppoe.c Fri Nov 22 13:41:21 2002 +++ b/drivers/net/pppoe.c Fri Nov 22 13:41:21 2002 @@ -52,14 +52,9 @@ #include #include - -#include - #include -#include #include #include - #include #include #include @@ -68,7 +63,6 @@ #include #include #include -#include #include #include #include @@ -78,7 +72,9 @@ #include #include +#include +#include static int __attribute__((unused)) pppoe_debug = 7; #define PPPOE_HASH_BITS 4 diff -Nru a/drivers/net/pppox.c b/drivers/net/pppox.c --- a/drivers/net/pppox.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/pppox.c Fri Nov 22 13:41:23 2002 @@ -21,22 +21,20 @@ #include #include - -#include - #include -#include #include #include - #include #include #include #include -#include #include #include #include + +#include + +#include static struct pppox_proto *proto[PX_MAX_PROTO+1]; diff -Nru a/drivers/net/rcpci45.c b/drivers/net/rcpci45.c --- a/drivers/net/rcpci45.c Fri Nov 22 13:41:22 2002 +++ b/drivers/net/rcpci45.c Fri Nov 22 13:41:22 2002 @@ -48,7 +48,6 @@ #include #include -#include #include #include #include @@ -58,6 +57,7 @@ #include #include #include + #include /* For NR_IRQS only. */ #include #include diff -Nru a/drivers/net/sb1000.c b/drivers/net/sb1000.c --- a/drivers/net/sb1000.c Fri Nov 22 13:41:17 2002 +++ b/drivers/net/sb1000.c Fri Nov 22 13:41:17 2002 @@ -35,13 +35,12 @@ static char version[] = "sb1000.c:v1.1.2 6/01/98 (fventuri@mediaone.net)\n"; #include - #include #include -#include #include #include #include +#include /* for SIOGCM/SIOSCM stuff */ #include #include #include @@ -49,17 +48,13 @@ #include #include #include /* for udelay() */ -#include +#include +#include #include #include +#include #include -#include -#include - -/* for SIOGCM/SIOSCM stuff */ - -#include #ifdef SB1000_DEBUG int sb1000_debug = SB1000_DEBUG; diff -Nru a/drivers/net/seeq8005.c b/drivers/net/seeq8005.c --- a/drivers/net/seeq8005.c Fri Nov 22 13:41:22 2002 +++ b/drivers/net/seeq8005.c Fri Nov 22 13:41:22 2002 @@ -32,7 +32,6 @@ #include #include -#include #include #include #include @@ -42,15 +41,16 @@ #include #include #include +#include +#include +#include +#include + #include #include #include #include -#include -#include -#include -#include #include "seeq8005.h" /* First, a few definitions that the brave might change. */ diff -Nru a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c --- a/drivers/net/sgiseeq.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/sgiseeq.c Fri Nov 22 13:41:23 2002 @@ -5,30 +5,26 @@ */ #include #include -#include #include #include #include #include +#include #include +#include #include #include +#include +#include +#include +#include +#include #include #include #include #include #include -#include -#include - -#include -#include - -#include -#include -#include - #include #include #include diff -Nru a/drivers/net/shaper.c b/drivers/net/shaper.c --- a/drivers/net/shaper.c Fri Nov 22 13:41:22 2002 +++ b/drivers/net/shaper.c Fri Nov 22 13:41:22 2002 @@ -72,7 +72,6 @@ #include #include #include -#include #include #include #include @@ -83,9 +82,10 @@ #include #include #include +#include + #include #include -#include struct shaper_cb { __u32 shapelatency; /* Latency on frame */ diff -Nru a/drivers/net/sis900.c b/drivers/net/sis900.c --- a/drivers/net/sis900.c Fri Nov 22 13:41:19 2002 +++ b/drivers/net/sis900.c Fri Nov 22 13:41:19 2002 @@ -49,7 +49,6 @@ #include #include #include -#include #include #include #include diff -Nru a/drivers/net/sk_g16.c b/drivers/net/sk_g16.c --- a/drivers/net/sk_g16.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/sk_g16.c Fri Nov 22 13:41:23 2002 @@ -60,23 +60,22 @@ #include #include -#include #include #include #include #include #include #include -#include -#include -#include #include #include #include - #include #include #include + +#include +#include +#include #include "sk_g16.h" diff -Nru a/drivers/net/sk_mca.c b/drivers/net/sk_mca.c --- a/drivers/net/sk_mca.c Fri Nov 22 13:41:21 2002 +++ b/drivers/net/sk_mca.c Fri Nov 22 13:41:21 2002 @@ -82,7 +82,6 @@ *************************************************************************/ #include -#include #include #include #include @@ -92,16 +91,15 @@ #include #include #include -#include -#include -#include - #include #include - #include #include #include + +#include +#include +#include #define _SK_MCA_DRIVER_ #include "sk_mca.h" diff -Nru a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c --- a/drivers/net/skfp/skfddi.c Fri Nov 22 13:41:17 2002 +++ b/drivers/net/skfp/skfddi.c Fri Nov 22 13:41:17 2002 @@ -77,9 +77,7 @@ /* Include files */ #include - #include -#include #include #include #include @@ -88,15 +86,15 @@ #include #include #include -#include -#include -#include -#include #include // isdigit - #include #include #include + +#include +#include +#include +#include #include "h/types.h" #undef ADDR // undo Linux definition diff -Nru a/drivers/net/slhc.c b/drivers/net/slhc.c --- a/drivers/net/slhc.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/slhc.c Fri Nov 22 13:41:18 2002 @@ -60,7 +60,6 @@ #ifdef CONFIG_INET /* Entire module is for IP only */ -#include #include #include #include diff -Nru a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c --- a/drivers/net/smc-mca.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/smc-mca.c Fri Nov 22 13:41:18 2002 @@ -36,22 +36,20 @@ - Some minor bug fixes */ - +#include #include - #include -#include #include #include #include +#include +#include + #include #include -#include -#include #include "8390.h" #include "smc-mca.h" -#include int ultramca_probe(struct net_device *dev); diff -Nru a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c --- a/drivers/net/smc-ultra.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/smc-ultra.c Fri Nov 22 13:41:18 2002 @@ -59,18 +59,17 @@ #include #include - #include -#include #include #include #include #include +#include +#include + #include #include -#include -#include #include "8390.h" /* A zero-terminated list of I/O addresses to be probed. */ diff -Nru a/drivers/net/smc-ultra32.c b/drivers/net/smc-ultra32.c --- a/drivers/net/smc-ultra32.c Fri Nov 22 13:41:22 2002 +++ b/drivers/net/smc-ultra32.c Fri Nov 22 13:41:22 2002 @@ -48,16 +48,16 @@ #include #include -#include #include #include #include +#include +#include +#include #include #include -#include -#include #include "8390.h" int ultra32_probe(struct net_device *dev); diff -Nru a/drivers/net/smc9194.c b/drivers/net/smc9194.c --- a/drivers/net/smc9194.c Fri Nov 22 13:41:22 2002 +++ b/drivers/net/smc9194.c Fri Nov 22 13:41:22 2002 @@ -60,7 +60,6 @@ #include #include #include -#include #include #include #include @@ -70,15 +69,16 @@ #include #include #include -#include -#include #include - #include #include #include +#include +#include + #include "smc9194.h" + /*------------------------------------------------------------------------ . . Configuration options, for the experienced user to change. diff -Nru a/drivers/net/stnic.c b/drivers/net/stnic.c --- a/drivers/net/stnic.c Fri Nov 22 13:41:21 2002 +++ b/drivers/net/stnic.c Fri Nov 22 13:41:21 2002 @@ -9,15 +9,15 @@ #include #include - #include -#include #include +#include #include #include #include #include #include + #include #include #include diff -Nru a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c --- a/drivers/net/sun3lance.c Fri Nov 22 13:41:22 2002 +++ b/drivers/net/sun3lance.c Fri Nov 22 13:41:22 2002 @@ -24,10 +24,8 @@ static char *version = "sun3lance.c: v1.2 1/12/2001 Sam Creasey (sammy@sammy.net)\n"; #include - #include #include -#include #include #include #include @@ -35,10 +33,12 @@ #include #include #include +#include +#include +#include #include #include - #include #include #include @@ -52,10 +52,6 @@ #else #include #endif - -#include -#include -#include /* sun3/60 addr/irq for the lance chip. If your sun is different, change this. */ diff -Nru a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c --- a/drivers/net/sunbmac.c Fri Nov 22 13:41:20 2002 +++ b/drivers/net/sunbmac.c Fri Nov 22 13:41:20 2002 @@ -7,7 +7,6 @@ #include #include -#include #include #include #include @@ -18,23 +17,22 @@ #include #include #include -#include -#include -#include -#include #include -#include +#include +#include +#include +#include +#include +#include +#include #include -#include +#include #include #include -#include #include - -#include -#include -#include +#include +#include #include "sunbmac.h" diff -Nru a/drivers/net/sungem.c b/drivers/net/sungem.c --- a/drivers/net/sungem.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/sungem.c Fri Nov 22 13:41:23 2002 @@ -17,11 +17,8 @@ */ #include - #include - #include -#include #include #include #include diff -Nru a/drivers/net/sunhme.c b/drivers/net/sunhme.c --- a/drivers/net/sunhme.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/sunhme.c Fri Nov 22 13:41:18 2002 @@ -17,10 +17,8 @@ "sunhme.c:v2.01 26/Mar/2002 David S. Miller (davem@redhat.com)\n"; #include - #include #include -#include #include #include #include @@ -34,11 +32,15 @@ #include #include #include +#include +#include +#include +#include + #include #include #include #include -#include #include #ifdef __sparc__ @@ -55,10 +57,6 @@ #include #include - -#include -#include -#include #ifdef CONFIG_PCI #include diff -Nru a/drivers/net/sunlance.c b/drivers/net/sunlance.c --- a/drivers/net/sunlance.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/sunlance.c Fri Nov 22 13:41:18 2002 @@ -76,9 +76,7 @@ #include #include - #include -#include #include #include #include @@ -89,28 +87,25 @@ #include #include #include +#include +#include /* Used for the temporal inet entries and routing */ +#include +#include +#include +#include + #include #include #include #include #include -#include #include /* Used by the checksum routines */ - -/* Used for the temporal inet entries and routing */ -#include -#include - #include #include #include #include #include /* For tpe-link-test? setting */ #include - -#include -#include -#include /* Define: 2^4 Tx buffers and 2^4 Rx buffers */ #ifndef LANCE_LOG_TX_BUFFERS diff -Nru a/drivers/net/sunqe.c b/drivers/net/sunqe.c --- a/drivers/net/sunqe.c Fri Nov 22 13:41:19 2002 +++ b/drivers/net/sunqe.c Fri Nov 22 13:41:19 2002 @@ -11,10 +11,9 @@ "sunqe.c:v2.9 9/11/99 David S. Miller (davem@redhat.com)\n"; #include - #include -#include #include +#include #include #include #include @@ -24,14 +23,15 @@ #include #include #include +#include +#include +#include #include #include #include #include -#include #include - #include #include #include @@ -39,10 +39,6 @@ #include #include #include - -#include -#include -#include #include "sunqe.h" diff -Nru a/drivers/net/tc35815.c b/drivers/net/tc35815.c --- a/drivers/net/tc35815.c Fri Nov 22 13:41:17 2002 +++ b/drivers/net/tc35815.c Fri Nov 22 13:41:17 2002 @@ -32,9 +32,7 @@ "tc35815.c:v0.00 26/07/2000 by Toshiba Corporation\n"; #include - #include -#include #include #include #include @@ -42,21 +40,20 @@ #include #include #include -#include -#include -#include -#include #include #include - #include #include #include #include #include #include -#include +#include +#include +#include +#include +#include /* * The name of the card. Is used for messages and in the requests for diff -Nru a/drivers/net/tg3.c b/drivers/net/tg3.c --- a/drivers/net/tg3.c Fri Nov 22 13:41:20 2002 +++ b/drivers/net/tg3.c Fri Nov 22 13:41:20 2002 @@ -2371,6 +2371,7 @@ unsigned int i; u32 len, entry, base_flags, mss; int would_hit_hwbug; + unsigned long flags; len = (skb->len - skb->data_len); @@ -2393,12 +2394,12 @@ * So we really do need to disable interrupts when taking * tx_lock here. */ - spin_lock_irq(&tp->tx_lock); + spin_lock_irqsave(&tp->tx_lock, flags); /* This is a hard error, log it. */ if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) { netif_stop_queue(dev); - spin_unlock_irq(&tp->tx_lock); + spin_unlock_irqrestore(&tp->tx_lock, flags); printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n", dev->name); return 1; @@ -2550,7 +2551,7 @@ netif_stop_queue(dev); out_unlock: - spin_unlock_irq(&tp->tx_lock); + spin_unlock_irqrestore(&tp->tx_lock, flags); dev->trans_start = jiffies; @@ -2562,6 +2563,7 @@ struct tg3 *tp = dev->priv; dma_addr_t mapping; u32 len, entry, base_flags, mss; + unsigned long flags; len = (skb->len - skb->data_len); @@ -2584,12 +2586,12 @@ * So we really do need to disable interrupts when taking * tx_lock here. */ - spin_lock_irq(&tp->tx_lock); + spin_lock_irqsave(&tp->tx_lock, flags); /* This is a hard error, log it. */ if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) { netif_stop_queue(dev); - spin_unlock_irq(&tp->tx_lock); + spin_unlock_irqrestore(&tp->tx_lock, flags); printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n", dev->name); return 1; @@ -2695,7 +2697,7 @@ if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1)) netif_stop_queue(dev); - spin_unlock_irq(&tp->tx_lock); + spin_unlock_irqrestore(&tp->tx_lock, flags); dev->trans_start = jiffies; diff -Nru a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c --- a/drivers/net/tokenring/3c359.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/tokenring/3c359.c Fri Nov 22 13:41:23 2002 @@ -44,9 +44,7 @@ #include #include - #include -#include #include #include #include @@ -63,6 +61,7 @@ #include #include #include + #include #include diff -Nru a/drivers/net/tokenring/Kconfig b/drivers/net/tokenring/Kconfig --- a/drivers/net/tokenring/Kconfig Fri Nov 22 13:41:18 2002 +++ b/drivers/net/tokenring/Kconfig Fri Nov 22 13:41:18 2002 @@ -2,13 +2,13 @@ # Token Ring driver configuration # -menu "Token Ring devices" +menu "Token Ring devices (depends on LLC=y)" depends on NETDEVICES # So far, we only have PCI, ISA, and MCA token ring devices config TR bool "Token Ring driver support" - depends on PCI || ISA || MCA + depends on (PCI || ISA || MCA) && LLC=y help Token Ring is IBM's way of communication on a local network; the rest of the world uses Ethernet. To participate on a Token Ring diff -Nru a/drivers/net/tokenring/abyss.c b/drivers/net/tokenring/abyss.c --- a/drivers/net/tokenring/abyss.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/tokenring/abyss.c Fri Nov 22 13:41:18 2002 @@ -27,17 +27,16 @@ #include #include -#include #include #include #include +#include +#include #include #include #include -#include -#include #include "tms380tr.h" #include "abyss.h" /* Madge-specific constants */ diff -Nru a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c --- a/drivers/net/tokenring/ibmtr.c Fri Nov 22 13:41:21 2002 +++ b/drivers/net/tokenring/ibmtr.c Fri Nov 22 13:41:21 2002 @@ -125,11 +125,11 @@ /* some 95 OS send many non UI frame; this allow removing the warning */ #define TR_FILTERNONUI 1 -#include #include #include #include #include + #include #include diff -Nru a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c --- a/drivers/net/tokenring/lanstreamer.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/tokenring/lanstreamer.c Fri Nov 22 13:41:23 2002 @@ -100,9 +100,7 @@ #include #include - #include -#include #include #include #include @@ -120,6 +118,7 @@ #include #include #include + #include #include diff -Nru a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c --- a/drivers/net/tokenring/madgemc.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/tokenring/madgemc.c Fri Nov 22 13:41:23 2002 @@ -22,17 +22,16 @@ #include #include #include -#include #include #include #include +#include +#include #include #include #include -#include -#include #include "tms380tr.h" #include "madgemc.h" /* Madge-specific constants */ diff -Nru a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c --- a/drivers/net/tokenring/olympic.c Fri Nov 22 13:41:22 2002 +++ b/drivers/net/tokenring/olympic.c Fri Nov 22 13:41:22 2002 @@ -82,9 +82,7 @@ #include #include - #include -#include #include #include #include @@ -101,6 +99,7 @@ #include #include #include + #include #include diff -Nru a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c --- a/drivers/net/tokenring/smctr.c Fri Nov 22 13:41:20 2002 +++ b/drivers/net/tokenring/smctr.c Fri Nov 22 13:41:20 2002 @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -42,21 +41,21 @@ #include #include #include -#include -#include -#include -#include -#include #include #include #include #include #include - #include #include #include #include + +#include +#include +#include +#include +#include #if BITS_PER_LONG == 64 #error FIXME: driver does not support 64-bit platforms diff -Nru a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c --- a/drivers/net/tokenring/tms380tr.c Fri Nov 22 13:41:21 2002 +++ b/drivers/net/tokenring/tms380tr.c Fri Nov 22 13:41:21 2002 @@ -73,9 +73,7 @@ #include #include - #include -#include #include #include #include @@ -85,21 +83,21 @@ #include #include #include -#include -#include -#include -#include -#include -#include #include #include #include #include - #include #include #include #include + +#include +#include +#include +#include +#include +#include #include "tms380tr.h" /* Our Stuff */ #include "tms380tr_microcode.h" /* TI microcode for COMMprocessor */ diff -Nru a/drivers/net/tokenring/tmsisa.c b/drivers/net/tokenring/tmsisa.c --- a/drivers/net/tokenring/tmsisa.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/tokenring/tmsisa.c Fri Nov 22 13:41:18 2002 @@ -23,10 +23,11 @@ #include #include -#include #include #include #include +#include +#include #include #include @@ -34,8 +35,6 @@ #include #include -#include -#include #include "tms380tr.h" #define TMS_ISA_IO_EXTENT 32 diff -Nru a/drivers/net/tokenring/tmspci.c b/drivers/net/tokenring/tmspci.c --- a/drivers/net/tokenring/tmspci.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/tokenring/tmspci.c Fri Nov 22 13:41:23 2002 @@ -28,17 +28,16 @@ #include #include -#include #include #include #include +#include +#include #include #include #include -#include -#include #include "tms380tr.h" static char version[] __initdata = diff -Nru a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c --- a/drivers/net/tulip/de2104x.c Fri Nov 22 13:41:22 2002 +++ b/drivers/net/tulip/de2104x.c Fri Nov 22 13:41:22 2002 @@ -41,9 +41,9 @@ #include #include #include -#include #include #include + #include #include #include diff -Nru a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c --- a/drivers/net/tulip/de4x5.c Fri Nov 22 13:41:17 2002 +++ b/drivers/net/tulip/de4x5.c Fri Nov 22 13:41:17 2002 @@ -444,9 +444,7 @@ #include #include - #include -#include #include #include #include @@ -459,6 +457,13 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -469,15 +474,6 @@ #ifdef CONFIG_PPC #include #endif /* CONFIG_PPC */ - -#include -#include -#include - -#include -#include -#include -#include #include "de4x5.h" diff -Nru a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c --- a/drivers/net/tulip/dmfe.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/tulip/dmfe.c Fri Nov 22 13:41:23 2002 @@ -65,9 +65,7 @@ #define DRV_RELDATE "2002-01-17" #include - #include -#include #include #include #include diff -Nru a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c --- a/drivers/net/tulip/xircom_cb.c Fri Nov 22 13:41:22 2002 +++ b/drivers/net/tulip/xircom_cb.c Fri Nov 22 13:41:22 2002 @@ -14,10 +14,8 @@ * $Id: xircom_cb.c,v 1.33 2001/03/19 14:02:07 arjanv Exp $ */ - #include #include -#include #include #include #include @@ -30,11 +28,10 @@ #include #include #include + #include #include #include - - #ifdef DEBUG #define enter(x) printk("Enter: %s, %s line %i\n",x,__FILE__,__LINE__) diff -Nru a/drivers/net/tun.c b/drivers/net/tun.c --- a/drivers/net/tun.c Fri Nov 22 13:41:19 2002 +++ b/drivers/net/tun.c Fri Nov 22 13:41:19 2002 @@ -24,17 +24,14 @@ #include #include - #include #include #include -#include #include #include #include #include #include - #include #include #include diff -Nru a/drivers/net/wan/comx-hw-comx.c b/drivers/net/wan/comx-hw-comx.c --- a/drivers/net/wan/comx-hw-comx.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/wan/comx-hw-comx.c Fri Nov 22 13:41:18 2002 @@ -49,12 +49,12 @@ #include #include #include -#include #include #include #include #include #include + #include #include diff -Nru a/drivers/net/wan/comx-hw-locomx.c b/drivers/net/wan/comx-hw-locomx.c --- a/drivers/net/wan/comx-hw-locomx.c Fri Nov 22 13:41:21 2002 +++ b/drivers/net/wan/comx-hw-locomx.c Fri Nov 22 13:41:21 2002 @@ -36,18 +36,19 @@ #define VERSION "0.14" +#include #include #include #include -#include #include #include +#include +#include + #include #include #include #include -#include -#include #include "comx.h" #include "z85230.h" diff -Nru a/drivers/net/wan/comx-hw-mixcom.c b/drivers/net/wan/comx-hw-mixcom.c --- a/drivers/net/wan/comx-hw-mixcom.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/wan/comx-hw-mixcom.c Fri Nov 22 13:41:23 2002 @@ -39,18 +39,19 @@ #define VERSION "0.65" +#include #include #include #include -#include #include #include -#include -#include -#include #include #include #include + +#include +#include +#include #include "comx.h" #include "mixcom.h" diff -Nru a/drivers/net/wan/comx-hw-munich.c b/drivers/net/wan/comx-hw-munich.c --- a/drivers/net/wan/comx-hw-munich.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/wan/comx-hw-munich.c Fri Nov 22 13:41:18 2002 @@ -32,16 +32,16 @@ #include #include #include -#include #include #include +#include +#include +#include + #include #include #include #include -#include -#include -#include #define COMX_NEW diff -Nru a/drivers/net/wan/comx-proto-fr.c b/drivers/net/wan/comx-proto-fr.c --- a/drivers/net/wan/comx-proto-fr.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/wan/comx-proto-fr.c Fri Nov 22 13:41:18 2002 @@ -46,6 +46,7 @@ #include #include #include + #include #include "comx.h" diff -Nru a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c --- a/drivers/net/wan/cosa.c Fri Nov 22 13:41:17 2002 +++ b/drivers/net/wan/cosa.c Fri Nov 22 13:41:17 2002 @@ -86,7 +86,6 @@ #include #include #include -#include #include #include #include diff -Nru a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c --- a/drivers/net/wan/dlci.c Fri Nov 22 13:41:20 2002 +++ b/drivers/net/wan/dlci.c Fri Nov 22 13:41:20 2002 @@ -30,9 +30,7 @@ #include /* for CONFIG_DLCI_COUNT */ #include - #include -#include #include #include #include @@ -42,20 +40,19 @@ #include #include #include -#include -#include -#include -#include -#include - #include - #include #include #include #include #include + +#include +#include +#include +#include +#include static const char devname[] = "dlci"; static const char version[] = "DLCI driver v0.35, 4 Jan 1997, mike.mclagan@linux.org"; diff -Nru a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c --- a/drivers/net/wan/hdlc_cisco.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/wan/hdlc_cisco.c Fri Nov 22 13:41:18 2002 @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff -Nru a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c --- a/drivers/net/wan/hdlc_fr.c Fri Nov 22 13:41:22 2002 +++ b/drivers/net/wan/hdlc_fr.c Fri Nov 22 13:41:22 2002 @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff -Nru a/drivers/net/wan/hdlc_generic.c b/drivers/net/wan/hdlc_generic.c --- a/drivers/net/wan/hdlc_generic.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/wan/hdlc_generic.c Fri Nov 22 13:41:18 2002 @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include diff -Nru a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c --- a/drivers/net/wan/hdlc_ppp.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/wan/hdlc_ppp.c Fri Nov 22 13:41:18 2002 @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff -Nru a/drivers/net/wan/hdlc_raw.c b/drivers/net/wan/hdlc_raw.c --- a/drivers/net/wan/hdlc_raw.c Fri Nov 22 13:41:21 2002 +++ b/drivers/net/wan/hdlc_raw.c Fri Nov 22 13:41:21 2002 @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff -Nru a/drivers/net/wan/hdlc_x25.c b/drivers/net/wan/hdlc_x25.c --- a/drivers/net/wan/hdlc_x25.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/wan/hdlc_x25.c Fri Nov 22 13:41:23 2002 @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff -Nru a/drivers/net/wan/lmc/lmc_debug.c b/drivers/net/wan/lmc/lmc_debug.c --- a/drivers/net/wan/lmc/lmc_debug.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/wan/lmc/lmc_debug.c Fri Nov 22 13:41:18 2002 @@ -1,9 +1,9 @@ #include -#include #include #include #include + #include "lmc_ver.h" #include "lmc_debug.h" diff -Nru a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c --- a/drivers/net/wan/lmc/lmc_main.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/wan/lmc/lmc_main.c Fri Nov 22 13:41:18 2002 @@ -40,7 +40,7 @@ #include #include -#include +#include #include #include #include @@ -51,32 +51,28 @@ #include #include #include - #if LINUX_VERSION_CODE < 0x20155 #include #endif - #include #include -#include /* Processor type for cache alignment. */ -#include -#include -#include - #include #include #include -#include #include +#include + +#include /* Processor type for cache alignment. */ +#include +#include +#include #if LINUX_VERSION_CODE >= 0x20200 #include //#include #else /* 2.0 kernel */ #define ARPHRD_HDLC 513 #endif - -#include #define DRIVER_MAJOR_VERSION 1 #define DRIVER_MINOR_VERSION 34 diff -Nru a/drivers/net/wan/lmc/lmc_media.c b/drivers/net/wan/lmc/lmc_media.c --- a/drivers/net/wan/lmc/lmc_media.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/wan/lmc/lmc_media.c Fri Nov 22 13:41:23 2002 @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -12,28 +11,25 @@ #include #include #include -//#include - #if LINUX_VERSION_CODE < 0x20155 #include #endif - #include #include -#include /* Processor type for cache alignment. */ -#include -#include -#include - #include #include #include -#include #include +#include + +#include /* Processor type for cache alignment. */ +#include +#include +#include + #if LINUX_VERSION_CODE >= 0x20200 #include -//#include #endif #include "lmc_ver.h" diff -Nru a/drivers/net/wan/lmc/lmc_proto.c b/drivers/net/wan/lmc/lmc_proto.c --- a/drivers/net/wan/lmc/lmc_proto.c Fri Nov 22 13:41:20 2002 +++ b/drivers/net/wan/lmc/lmc_proto.c Fri Nov 22 13:41:20 2002 @@ -21,7 +21,6 @@ #include #include -#include #include #include #include @@ -30,22 +29,22 @@ #include #include #include -#include - #include #include -#include /* Processor type for cache alignment. */ -#include -#include -#include - #include #include #include -#include #include #include #include + +#include + +#include /* Processor type for cache alignment. */ +#include +#include +#include +#include #include "lmc_ver.h" #include "lmc.h" diff -Nru a/drivers/net/wan/n2.c b/drivers/net/wan/n2.c --- a/drivers/net/wan/n2.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/wan/n2.c Fri Nov 22 13:41:18 2002 @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff -Nru a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c --- a/drivers/net/wan/pc300_drv.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/wan/pc300_drv.c Fri Nov 22 13:41:23 2002 @@ -219,7 +219,6 @@ #include #include #include -#include #include #include #include @@ -229,10 +228,12 @@ #include #include #include + +#include #include + #include #include -#include #include "pc300.h" diff -Nru a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c --- a/drivers/net/wan/pc300_tty.c Fri Nov 22 13:41:19 2002 +++ b/drivers/net/wan/pc300_tty.c Fri Nov 22 13:41:19 2002 @@ -42,20 +42,19 @@ #include #include #include -#include #include #include #include #include #include -#include -#include #include - /* TTY includes */ #include #include #include + +#include +#include #include "pc300.h" diff -Nru a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c --- a/drivers/net/wan/sbni.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/wan/sbni.c Fri Nov 22 13:41:18 2002 @@ -37,9 +37,9 @@ * Known problem: this driver wasn't tested on multiprocessor machine. */ +#include #include #include -#include #include #include #include @@ -47,26 +47,22 @@ #include #include #include - -#include -#include -#include -#include -#include - - #include #include +#include #include #include #include #include -#include -#include -#include "sbni.h" +#include +#include +#include +#include +#include +#include "sbni.h" /* device private data */ diff -Nru a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c --- a/drivers/net/wan/sdla.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/wan/sdla.c Fri Nov 22 13:41:23 2002 @@ -34,9 +34,7 @@ #include /* for CONFIG_DLCI_MAX */ #include - #include -#include #include #include #include @@ -48,19 +46,17 @@ #include #include #include +#include +#include +#include +#include +#include #include #include #include #include #include - -#include -#include -#include -#include - -#include static const char* version = "SDLA driver v0.30, 12 Sep 1996, mike.mclagan@linux.org"; diff -Nru a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c --- a/drivers/net/wan/syncppp.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/wan/syncppp.c Fri Nov 22 13:41:18 2002 @@ -41,7 +41,6 @@ #include #include #include -#include #include #include #include @@ -50,10 +49,12 @@ #include #include #include -#include -#include #include + #include + +#include +#include #define MAXALIVECNT 6 /* max. alive packets */ diff -Nru a/drivers/net/wd.c b/drivers/net/wd.c --- a/drivers/net/wd.c Fri Nov 22 13:41:17 2002 +++ b/drivers/net/wd.c Fri Nov 22 13:41:17 2002 @@ -29,18 +29,18 @@ "wd.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; #include - #include -#include #include #include #include +#include #include +#include +#include + #include #include -#include -#include #include "8390.h" /* A zero-terminated list of I/O addresses to be probed. */ diff -Nru a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c --- a/drivers/net/wireless/airo_cs.c Fri Nov 22 13:41:18 2002 +++ b/drivers/net/wireless/airo_cs.c Fri Nov 22 13:41:18 2002 @@ -24,19 +24,14 @@ #ifdef __IN_PCMCIA_PACKAGE__ #include #endif - #include #include #include - -#include #include #include #include #include #include -#include -#include #include #include @@ -44,6 +39,9 @@ #include #include #include + +#include +#include /* All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If diff -Nru a/drivers/net/wireless/airport.c b/drivers/net/wireless/airport.c --- a/drivers/net/wireless/airport.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/wireless/airport.c Fri Nov 22 13:41:23 2002 @@ -12,19 +12,14 @@ */ #include - #include #include #include -#include #include #include #include #include #include -#include -#include -#include #include #include #include @@ -33,10 +28,14 @@ #include #include +#include +#include +#include #include #include #include #include +#include #include "orinoco.h" diff -Nru a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c --- a/drivers/net/wireless/netwave_cs.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/wireless/netwave_cs.c Fri Nov 22 13:41:23 2002 @@ -41,7 +41,6 @@ #include #include #include -#include #include #include #include @@ -51,16 +50,10 @@ #include #include #include -#include -#include -#include -#include #include - #include #include #include - #ifdef CONFIG_NET_RADIO #include #if WIRELESS_EXT > 12 @@ -75,6 +68,11 @@ #include #include #include + +#include +#include +#include +#include #define NETWAVE_REGOFF 0x8000 /* The Netwave IO registers, offsets to iobase */ diff -Nru a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c --- a/drivers/net/wireless/orinoco.c Fri Nov 22 13:41:20 2002 +++ b/drivers/net/wireless/orinoco.c Fri Nov 22 13:41:20 2002 @@ -364,21 +364,21 @@ #include #include #include -#include #include #include #include #include #include -#include -#include -#include #include #include #include #include #include #include + +#include +#include +#include #include "hermes.h" #include "hermes_rid.h" diff -Nru a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c --- a/drivers/net/wireless/orinoco_cs.c Fri Nov 22 13:41:23 2002 +++ b/drivers/net/wireless/orinoco_cs.c Fri Nov 22 13:41:23 2002 @@ -14,7 +14,6 @@ #ifdef __IN_PCMCIA_PACKAGE__ #include #endif /* __IN_PCMCIA_PACKAGE__ */ - #include #include #include @@ -24,9 +23,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -40,6 +36,10 @@ #include #include #include + +#include +#include +#include #include "orinoco.h" diff -Nru a/drivers/net/wireless/orinoco_pci.c b/drivers/net/wireless/orinoco_pci.c --- a/drivers/net/wireless/orinoco_pci.c Fri Nov 22 13:41:21 2002 +++ b/drivers/net/wireless/orinoco_pci.c Fri Nov 22 13:41:21 2002 @@ -84,7 +84,6 @@ */ #include - #include #include #include @@ -94,9 +93,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -106,6 +102,10 @@ #include #include #include + +#include +#include +#include #include "hermes.h" #include "orinoco.h" diff -Nru a/drivers/net/znet.c b/drivers/net/znet.c --- a/drivers/net/znet.c Fri Nov 22 13:41:17 2002 +++ b/drivers/net/znet.c Fri Nov 22 13:41:17 2002 @@ -88,22 +88,21 @@ #include #include #include -#include #include #include #include #include #include #include -#include -#include -#include -#include - #include #include #include #include + +#include +#include +#include +#include /* This include could be elsewhere, since it is not wireless specific */ #include "wireless/i82593.h" diff -Nru a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c --- a/drivers/parisc/ccio-dma.c Fri Nov 22 13:41:18 2002 +++ b/drivers/parisc/ccio-dma.c Fri Nov 22 13:41:18 2002 @@ -411,10 +411,9 @@ ** when it passes in BIDIRECTIONAL flag. */ static u32 hint_lookup[] = { - [PCI_DMA_BIDIRECTIONAL] HINT_STOP_MOST | HINT_SAFE_DMA | IOPDIR_VALID, - [PCI_DMA_TODEVICE] HINT_STOP_MOST | HINT_PREFETCH | IOPDIR_VALID, - [PCI_DMA_FROMDEVICE] HINT_STOP_MOST | IOPDIR_VALID, - [PCI_DMA_NONE] 0, /* not valid */ + [PCI_DMA_BIDIRECTIONAL] = HINT_STOP_MOST | HINT_SAFE_DMA | IOPDIR_VALID, + [PCI_DMA_TODEVICE] = HINT_STOP_MOST | HINT_PREFETCH | IOPDIR_VALID, + [PCI_DMA_FROMDEVICE] = HINT_STOP_MOST | IOPDIR_VALID, }; /** diff -Nru a/drivers/parisc/dino.c b/drivers/parisc/dino.c --- a/drivers/parisc/dino.c Fri Nov 22 13:41:17 2002 +++ b/drivers/parisc/dino.c Fri Nov 22 13:41:17 2002 @@ -283,12 +283,12 @@ DINO_PORT_OUT(l, 32, 0) struct pci_port_ops dino_port_ops = { - inb: dino_in8, - inw: dino_in16, - inl: dino_in32, - outb: dino_out8, - outw: dino_out16, - outl: dino_out32 + .inb = dino_in8, + .inw = dino_in16, + .inl = dino_in32, + .outb = dino_out8, + .outw = dino_out16, + .outl = dino_out32 }; static void @@ -368,10 +368,10 @@ static struct irq_region_ops dino_irq_ops = { - disable_irq: dino_mask_irq, /* ??? */ - enable_irq: dino_enable_irq, - mask_irq: dino_mask_irq, - unmask_irq: dino_unmask_irq + .disable_irq = dino_mask_irq, /* ??? */ + .enable_irq = dino_enable_irq, + .mask_irq = dino_mask_irq, + .unmask_irq = dino_unmask_irq }; diff -Nru a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c --- a/drivers/parisc/eisa.c Fri Nov 22 13:41:17 2002 +++ b/drivers/parisc/eisa.c Fri Nov 22 13:41:17 2002 @@ -205,9 +205,9 @@ /* EISA needs to be fixed at IRQ region #0 (EISA_IRQ_REGION) */ static struct irq_region eisa_irq_region = { - ops: { eisa_disable_irq, eisa_enable_irq, eisa_mask_irq, eisa_unmask_irq }, - data: { name: "EISA", irqbase: 0 }, - action: action, + .ops = { eisa_disable_irq, eisa_enable_irq, eisa_mask_irq, eisa_unmask_irq }, + .data = { .name = "EISA", .irqbase = 0 }, + .action = action, }; static void eisa_irq(int _, void *intr_dev, struct pt_regs *regs) diff -Nru a/drivers/parisc/led.c b/drivers/parisc/led.c --- a/drivers/parisc/led.c Fri Nov 22 13:41:18 2002 +++ b/drivers/parisc/led.c Fri Nov 22 13:41:18 2002 @@ -531,7 +531,7 @@ static int led_halt(struct notifier_block *, unsigned long, void *); static struct notifier_block led_notifier = { - notifier_call: led_halt, + .notifier_call = led_halt, }; static int led_halt(struct notifier_block *nb, unsigned long event, void *buf) diff -Nru a/drivers/parisc/power.c b/drivers/parisc/power.c --- a/drivers/parisc/power.c Fri Nov 22 13:41:18 2002 +++ b/drivers/parisc/power.c Fri Nov 22 13:41:18 2002 @@ -305,8 +305,8 @@ } static struct notifier_block parisc_panic_block = { - notifier_call: parisc_panic_event, - priority: INT_MAX, + .notifier_call = parisc_panic_event, + .priority = INT_MAX, }; diff -Nru a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c --- a/drivers/parport/ieee1284.c Fri Nov 22 13:41:18 2002 +++ b/drivers/parport/ieee1284.c Fri Nov 22 13:41:18 2002 @@ -22,6 +22,8 @@ #include #include #include +#include +#include #undef DEBUG /* undef me for production */ diff -Nru a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c --- a/drivers/parport/parport_gsc.c Fri Nov 22 13:41:23 2002 +++ b/drivers/parport/parport_gsc.c Fri Nov 22 13:41:23 2002 @@ -202,40 +202,40 @@ struct parport_operations parport_gsc_ops = { - write_data: parport_gsc_write_data, - read_data: parport_gsc_read_data, + .write_data = parport_gsc_write_data, + .read_data = parport_gsc_read_data, - write_control: parport_gsc_write_control, - read_control: parport_gsc_read_control, - frob_control: parport_gsc_frob_control, + .write_control = parport_gsc_write_control, + .read_control = parport_gsc_read_control, + .frob_control = parport_gsc_frob_control, - read_status: parport_gsc_read_status, + .read_status = parport_gsc_read_status, - enable_irq: parport_gsc_enable_irq, - disable_irq: parport_gsc_disable_irq, + .enable_irq = parport_gsc_enable_irq, + .disable_irq = parport_gsc_disable_irq, - data_forward: parport_gsc_data_forward, - data_reverse: parport_gsc_data_reverse, + .data_forward = parport_gsc_data_forward, + .data_reverse = parport_gsc_data_reverse, - init_state: parport_gsc_init_state, - save_state: parport_gsc_save_state, - restore_state: parport_gsc_restore_state, + .init_state = parport_gsc_init_state, + .save_state = parport_gsc_save_state, + .restore_state = parport_gsc_restore_state, - inc_use_count: parport_gsc_inc_use_count, - dec_use_count: parport_gsc_dec_use_count, + .inc_use_count = parport_gsc_inc_use_count, + .dec_use_count = parport_gsc_dec_use_count, - epp_write_data: parport_ieee1284_epp_write_data, - epp_read_data: parport_ieee1284_epp_read_data, - epp_write_addr: parport_ieee1284_epp_write_addr, - epp_read_addr: parport_ieee1284_epp_read_addr, + .epp_write_data = parport_ieee1284_epp_write_data, + .epp_read_data = parport_ieee1284_epp_read_data, + .epp_write_addr = parport_ieee1284_epp_write_addr, + .epp_read_addr = parport_ieee1284_epp_read_addr, - ecp_write_data: parport_ieee1284_ecp_write_data, - ecp_read_data: parport_ieee1284_ecp_read_data, - ecp_write_addr: parport_ieee1284_ecp_write_addr, + .ecp_write_data = parport_ieee1284_ecp_write_data, + .ecp_read_data = parport_ieee1284_ecp_read_data, + .ecp_write_addr = parport_ieee1284_ecp_write_addr, - compat_write_data: parport_ieee1284_write_compat, - nibble_read_data: parport_ieee1284_read_nibble, - byte_read_data: parport_ieee1284_read_byte, + .compat_write_data = parport_ieee1284_write_compat, + .nibble_read_data = parport_ieee1284_read_nibble, + .byte_read_data = parport_ieee1284_read_byte, }; /* --- Mode detection ------------------------------------- */ @@ -492,9 +492,9 @@ MODULE_DEVICE_TABLE(parisc, parport_tbl); static struct parisc_driver parport_driver = { - name: "Parallel", - id_table: parport_tbl, - probe: parport_init_chip, + .name = "Parallel", + .id_table = parport_tbl, + .probe = parport_init_chip, }; int __devinit parport_gsc_init(void) diff -Nru a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c --- a/drivers/parport/parport_serial.c Fri Nov 22 13:41:23 2002 +++ b/drivers/parport/parport_serial.c Fri Nov 22 13:41:23 2002 @@ -344,10 +344,10 @@ } static struct pci_driver parport_serial_pci_driver = { - name: "parport_serial", - id_table: parport_serial_pci_tbl, - probe: parport_serial_pci_probe, - remove: __devexit_p(parport_serial_pci_remove), + .name = "parport_serial", + .id_table = parport_serial_pci_tbl, + .probe = parport_serial_pci_probe, + .remove = __devexit_p(parport_serial_pci_remove), }; diff -Nru a/drivers/pci/Makefile b/drivers/pci/Makefile --- a/drivers/pci/Makefile Fri Nov 22 13:41:23 2002 +++ b/drivers/pci/Makefile Fri Nov 22 13:41:23 2002 @@ -3,10 +3,10 @@ # export-objs := access.o hotplug.o pci-driver.o pci.o pool.o \ - probe.o proc.o search.o compat.o setup-bus.o + probe.o proc.o search.o setup-bus.o obj-y += access.o probe.o pci.o pool.o quirks.o \ - compat.o names.o pci-driver.o search.o hotplug.o + names.o pci-driver.o search.o hotplug.o obj-$(CONFIG_PM) += power.o obj-$(CONFIG_PROC_FS) += proc.o diff -Nru a/drivers/pci/compat.c b/drivers/pci/compat.c --- a/drivers/pci/compat.c Fri Nov 22 13:41:18 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,37 +0,0 @@ -/* - * $Id: compat.c,v 1.1 1998/02/16 10:35:50 mj Exp $ - * - * PCI Bus Services -- Function For Backward Compatibility - * - * Copyright 1998--2000 Martin Mares - */ - -#include -#include -#include -#include - -/* Obsolete functions, these will be going away... */ - -#define PCI_OP(rw,size,type) \ -int pcibios_##rw##_config_##size (unsigned char bus, unsigned char dev_fn, \ - unsigned char where, unsigned type val) \ -{ \ - struct pci_dev *dev = pci_find_slot(bus, dev_fn); \ - if (!dev) return PCIBIOS_DEVICE_NOT_FOUND; \ - return pci_##rw##_config_##size(dev, where, val); \ -} - -PCI_OP(read, byte, char *) -PCI_OP(read, word, short *) -PCI_OP(read, dword, int *) -PCI_OP(write, byte, char) -PCI_OP(write, word, short) -PCI_OP(write, dword, int) - -EXPORT_SYMBOL(pcibios_read_config_byte); -EXPORT_SYMBOL(pcibios_read_config_word); -EXPORT_SYMBOL(pcibios_read_config_dword); -EXPORT_SYMBOL(pcibios_write_config_byte); -EXPORT_SYMBOL(pcibios_write_config_word); -EXPORT_SYMBOL(pcibios_write_config_dword); diff -Nru a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c --- a/drivers/pci/pci-driver.c Fri Nov 22 13:41:22 2002 +++ b/drivers/pci/pci-driver.c Fri Nov 22 13:41:22 2002 @@ -145,7 +145,7 @@ } static struct pci_driver pci_compat_driver = { - name: "compat" + .name = "compat" }; /** @@ -200,9 +200,9 @@ } struct bus_type pci_bus_type = { - name: "pci", - match: pci_bus_match, - hotplug: pci_hotplug, + .name = "pci", + .match = pci_bus_match, + .hotplug = pci_hotplug, }; static int __init pci_driver_init(void) diff -Nru a/drivers/pci/pci.c b/drivers/pci/pci.c --- a/drivers/pci/pci.c Fri Nov 22 13:41:18 2002 +++ b/drivers/pci/pci.c Fri Nov 22 13:41:18 2002 @@ -182,7 +182,7 @@ int i; struct resource *best = NULL; - for(i=0; i<4; i++) { + for(i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { struct resource *r = bus->resource[i]; if (!r) continue; diff -Nru a/drivers/pci/probe.c b/drivers/pci/probe.c --- a/drivers/pci/probe.c Fri Nov 22 13:41:22 2002 +++ b/drivers/pci/probe.c Fri Nov 22 13:41:22 2002 @@ -384,7 +384,7 @@ /* The PCI-to-PCI bridge spec requires that subtractive decoding (i.e. transparent) bridge must have programming interface code of 0x01. */ - dev->transparent = ((class & 0xff) == 1); + dev->transparent = ((dev->class & 0xff) == 1); pci_read_bases(dev, 2, PCI_ROM_ADDRESS1); break; diff -Nru a/drivers/pci/proc.c b/drivers/pci/proc.c --- a/drivers/pci/proc.c Fri Nov 22 13:41:21 2002 +++ b/drivers/pci/proc.c Fri Nov 22 13:41:21 2002 @@ -285,16 +285,16 @@ #endif /* HAVE_PCI_MMAP */ static struct file_operations proc_bus_pci_operations = { - llseek: proc_bus_pci_lseek, - read: proc_bus_pci_read, - write: proc_bus_pci_write, - ioctl: proc_bus_pci_ioctl, + .llseek = proc_bus_pci_lseek, + .read = proc_bus_pci_read, + .write = proc_bus_pci_write, + .ioctl = proc_bus_pci_ioctl, #ifdef HAVE_PCI_MMAP - open: proc_bus_pci_open, - release: proc_bus_pci_release, - mmap: proc_bus_pci_mmap, + .open = proc_bus_pci_open, + .release = proc_bus_pci_release, + .mmap = proc_bus_pci_mmap, #ifdef HAVE_ARCH_PCI_GET_UNMAPPED_AREA - get_unmapped_area: get_pci_unmapped_area, + .get_unmapped_area = get_pci_unmapped_area, #endif /* HAVE_ARCH_PCI_GET_UNMAPPED_AREA */ #endif /* HAVE_PCI_MMAP */ }; @@ -365,10 +365,10 @@ } static struct seq_operations proc_bus_pci_devices_op = { - start: pci_seq_start, - next: pci_seq_next, - stop: pci_seq_stop, - show: show_device + .start = pci_seq_start, + .next = pci_seq_next, + .stop = pci_seq_stop, + .show = show_device }; struct proc_dir_entry *proc_bus_pci_dir; @@ -567,10 +567,10 @@ } static struct seq_operations proc_pci_op = { - start: pci_seq_start, - next: pci_seq_next, - stop: pci_seq_stop, - show: show_dev_config + .start = pci_seq_start, + .next = pci_seq_next, + .stop = pci_seq_stop, + .show = show_dev_config }; static int proc_bus_pci_dev_open(struct inode *inode, struct file *file) @@ -578,20 +578,20 @@ return seq_open(file, &proc_bus_pci_devices_op); } static struct file_operations proc_bus_pci_dev_operations = { - open: proc_bus_pci_dev_open, - read: seq_read, - llseek: seq_lseek, - release: seq_release, + .open = proc_bus_pci_dev_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, }; static int proc_pci_open(struct inode *inode, struct file *file) { return seq_open(file, &proc_pci_op); } static struct file_operations proc_pci_operations = { - open: proc_pci_open, - read: seq_read, - llseek: seq_lseek, - release: seq_release, + .open = proc_pci_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, }; static int __init pci_proc_init(void) diff -Nru a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c --- a/drivers/pci/setup-bus.c Fri Nov 22 13:41:23 2002 +++ b/drivers/pci/setup-bus.c Fri Nov 22 13:41:23 2002 @@ -333,13 +333,13 @@ } void __devinit -pbus_size_bridges(struct pci_bus *bus) +pci_bus_size_bridges(struct pci_bus *bus) { struct list_head *ln; unsigned long mask, type; for (ln=bus->children.next; ln != &bus->children; ln=ln->next) - pbus_size_bridges(pci_bus_b(ln)); + pci_bus_size_bridges(pci_bus_b(ln)); /* The root bus? */ if (!bus->self) @@ -358,10 +358,10 @@ } pbus_size_mem(bus, mask, type); } -EXPORT_SYMBOL(pbus_size_bridges); +EXPORT_SYMBOL(pci_bus_size_bridges); void __devinit -pbus_assign_resources(struct pci_bus *bus) +pci_bus_assign_resources(struct pci_bus *bus) { struct list_head *ln; int found_vga = pbus_assign_resources_sorted(bus); @@ -377,11 +377,11 @@ for (ln=bus->children.next; ln != &bus->children; ln=ln->next) { struct pci_bus *b = pci_bus_b(ln); - pbus_assign_resources(b); + pci_bus_assign_resources(b); pci_setup_bridge(b); } } -EXPORT_SYMBOL(pbus_assign_resources); +EXPORT_SYMBOL(pci_bus_assign_resources); void __init pci_assign_unassigned_resources(void) @@ -392,10 +392,10 @@ /* Depth first, calculate sizes and alignments of all subordinate buses. */ for(ln=pci_root_buses.next; ln != &pci_root_buses; ln=ln->next) - pbus_size_bridges(pci_bus_b(ln)); + pci_bus_size_bridges(pci_bus_b(ln)); /* Depth last, allocate resources and update the hardware. */ for(ln=pci_root_buses.next; ln != &pci_root_buses; ln=ln->next) - pbus_assign_resources(pci_bus_b(ln)); + pci_bus_assign_resources(pci_bus_b(ln)); pci_for_each_dev(dev) { pdev_enable_device(dev); diff -Nru a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c --- a/drivers/pci/setup-res.c Fri Nov 22 13:41:22 2002 +++ b/drivers/pci/setup-res.c Fri Nov 22 13:41:22 2002 @@ -36,21 +36,20 @@ int __init pci_claim_resource(struct pci_dev *dev, int resource) { - struct resource *res = &dev->resource[resource]; + struct resource *res = &dev->resource[resource]; struct resource *root = pci_find_parent_resource(dev, res); + char *dtype = resource < PCI_BRIDGE_RESOURCES ? "device" : "bridge"; int err; err = -EINVAL; - if (root != NULL) { + if (root != NULL) err = request_resource(root, res); - if (err) { - printk(KERN_ERR "PCI: Address space collision on " - "region %d of device %s [%lx:%lx]\n", - resource, dev->dev.name, res->start, res->end); - } - } else { - printk(KERN_ERR "PCI: No parent found for region %d " - "of device %s\n", resource, dev->dev.name); + + if (err) { + printk(KERN_ERR "PCI: %s region %d of %s %s [%lx:%lx]\n", + root ? "Address space collision on" : + "No parent found for", + resource, dtype, dev->slot_name, res->start, res->end); } return err; @@ -131,13 +130,13 @@ } DBGC((KERN_ERR " got res[%lx:%lx] for resource %d of %s\n", res->start, - res->end, i, dev->name)); + res->end, i, dev->dev.name)); return 0; } /* Sort resources by alignment */ -void __init +void __devinit pdev_sort_resources(struct pci_dev *dev, struct resource_list *head) { int i; diff -Nru a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c --- a/drivers/pcmcia/cistpl.c Fri Nov 22 13:41:18 2002 +++ b/drivers/pcmcia/cistpl.c Fri Nov 22 13:41:18 2002 @@ -430,7 +430,10 @@ #ifdef CONFIG_CARDBUS if (s->state & SOCKET_CARDBUS) { u_int ptr; - pcibios_read_config_dword(s->cap.cb_dev->subordinate->number, 0, 0x28, &ptr); + struct pci_dev *dev = pci_find_slot (s->cap.cb_dev->subordinate->number, 0); + if (!dev) + return CS_BAD_HANDLE; + pci_read_config_dword(dev, 0x28, &ptr); tuple->CISOffset = ptr & ~7; SPACE(tuple->Flags) = (ptr & 7); } else diff -Nru a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c --- a/drivers/pcmcia/ds.c Fri Nov 22 13:41:22 2002 +++ b/drivers/pcmcia/ds.c Fri Nov 22 13:41:22 2002 @@ -867,13 +867,13 @@ /*====================================================================*/ static struct file_operations ds_fops = { - owner: THIS_MODULE, - open: ds_open, - release: ds_release, - ioctl: ds_ioctl, - read: ds_read, - write: ds_write, - poll: ds_poll, + .owner = THIS_MODULE, + .open = ds_open, + .release = ds_release, + .ioctl = ds_ioctl, + .read = ds_read, + .write = ds_write, + .poll = ds_poll, }; EXPORT_SYMBOL(register_pccard_driver); diff -Nru a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c --- a/drivers/pcmcia/hd64465_ss.c Fri Nov 22 13:41:20 2002 +++ b/drivers/pcmcia/hd64465_ss.c Fri Nov 22 13:41:20 2002 @@ -240,13 +240,13 @@ static struct hw_interrupt_type hd64465_ss_irq_type = { - typename: "PCMCIA-IRQ", - startup: hs_startup_irq, - shutdown: hs_shutdown_irq, - enable: hs_enable_irq, - disable: hs_disable_irq, - ack: hs_mask_and_ack_irq, - end: hs_end_irq + .typename = "PCMCIA-IRQ", + .startup = hs_startup_irq, + .shutdown = hs_shutdown_irq, + .enable = hs_enable_irq, + .disable = hs_disable_irq, + .ack = hs_mask_and_ack_irq, + .end = hs_end_irq }; /* diff -Nru a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c --- a/drivers/pcmcia/i82092.c Fri Nov 22 13:41:23 2002 +++ b/drivers/pcmcia/i82092.c Fri Nov 22 13:41:23 2002 @@ -32,41 +32,37 @@ /* PCI core routines */ static struct pci_device_id i82092aa_pci_ids[] = { { - vendor:PCI_VENDOR_ID_INTEL, - device:PCI_DEVICE_ID_INTEL_82092AA_0, - subvendor:PCI_ANY_ID, - subdevice:PCI_ANY_ID, - class: 0, class_mask:0, - + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82092AA_0, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, }, {} }; MODULE_DEVICE_TABLE(pci, i82092aa_pci_ids); static struct pci_driver i82092aa_pci_drv = { - name: "i82092aa", - id_table: i82092aa_pci_ids, - probe: i82092aa_pci_probe, - remove: __devexit_p(i82092aa_pci_remove), - suspend: NULL, - resume: NULL + .name = "i82092aa", + .id_table = i82092aa_pci_ids, + .probe = i82092aa_pci_probe, + .remove = __devexit_p(i82092aa_pci_remove), }; /* the pccard structure and its functions */ static struct pccard_operations i82092aa_operations = { - init: i82092aa_init, - suspend: i82092aa_suspend, - register_callback: i82092aa_register_callback, - inquire_socket: i82092aa_inquire_socket, - get_status: i82092aa_get_status, - get_socket: i82092aa_get_socket, - set_socket: i82092aa_set_socket, - get_io_map: i82092aa_get_io_map, - set_io_map: i82092aa_set_io_map, - get_mem_map: i82092aa_get_mem_map, - set_mem_map: i82092aa_set_mem_map, - proc_setup: i82092aa_proc_setup, + .init = i82092aa_init, + .suspend = i82092aa_suspend, + .register_callback = i82092aa_register_callback, + .inquire_socket = i82092aa_inquire_socket, + .get_status = i82092aa_get_status, + .get_socket = i82092aa_get_socket, + .set_socket = i82092aa_set_socket, + .get_io_map = i82092aa_get_io_map, + .set_io_map = i82092aa_set_io_map, + .get_mem_map = i82092aa_get_mem_map, + .set_mem_map = i82092aa_set_mem_map, + .proc_setup = i82092aa_proc_setup, }; /* The card can do upto 4 sockets, allocate a structure for each of them */ diff -Nru a/drivers/pcmcia/pci_socket.c b/drivers/pcmcia/pci_socket.c --- a/drivers/pcmcia/pci_socket.c Fri Nov 22 13:41:23 2002 +++ b/drivers/pcmcia/pci_socket.c Fri Nov 22 13:41:23 2002 @@ -235,24 +235,24 @@ static struct pci_device_id cardbus_table [] __devinitdata = { { - class: PCI_CLASS_BRIDGE_CARDBUS << 8, - class_mask: ~0, + .class = PCI_CLASS_BRIDGE_CARDBUS << 8, + .class_mask = ~0, - vendor: PCI_ANY_ID, - device: PCI_ANY_ID, - subvendor: PCI_ANY_ID, - subdevice: PCI_ANY_ID, + .vendor = PCI_ANY_ID, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, }, { /* all zeroes */ } }; MODULE_DEVICE_TABLE(pci, cardbus_table); static struct pci_driver pci_cardbus_driver = { - name: "cardbus", - id_table: cardbus_table, - probe: cardbus_probe, - remove: __devexit_p(cardbus_remove), - suspend: cardbus_suspend, - resume: cardbus_resume, + .name = "cardbus", + .id_table = cardbus_table, + .probe = cardbus_probe, + .remove = __devexit_p(cardbus_remove), + .suspend = cardbus_suspend, + .resume = cardbus_resume, }; static int __init pci_socket_init(void) diff -Nru a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c --- a/drivers/pcmcia/tcic.c Fri Nov 22 13:41:20 2002 +++ b/drivers/pcmcia/tcic.c Fri Nov 22 13:41:20 2002 @@ -36,14 +36,8 @@ #include #include #include - -#include -#include -#include - -#include #include -#include +#include #include #include #include @@ -51,6 +45,10 @@ #include #include +#include +#include +#include + #include #include #include @@ -89,10 +87,10 @@ static int irq_list[16] = { -1 }; /* The card status change interrupt -- 0 means autoselect */ -static int cs_irq = 0; +static int cs_irq; /* Poll status interval -- 0 means default to interrupt */ -static int poll_interval = 0; +static int poll_interval; /* Delay for card status double-checking */ static int poll_quick = HZ/20; @@ -125,17 +123,17 @@ } socket_info_t; static struct timer_list poll_timer; -static int tcic_timer_pending = 0; +static int tcic_timer_pending; static int sockets; static socket_info_t socket_table[2]; static socket_cap_t tcic_cap = { - /* only 16-bit cards, memory windows must be size-aligned */ - SS_CAP_PCCARD | SS_CAP_MEM_ALIGN, - 0x4cf8, /* irq 14, 11, 10, 7, 6, 5, 4, 3 */ - 0x1000, /* 4K minimum window size */ - 0, 0 /* No PCI or CardBus support */ + /* only 16-bit cards, memory windows must be size-aligned */ + .features = SS_CAP_PCCARD | SS_CAP_MEM_ALIGN, + .irq_mask = 0x4cf8, /* irq 14, 11, 10, 7, 6, 5, 4, 3 */ + .map_size = 0x1000, /* 4K minimum window size */ + /* No PCI or CardBus support */ }; /*====================================================================*/ @@ -235,7 +233,7 @@ static volatile u_int irq_hits; -static void __init irq_count(int irq, void *dev, struct pt_regs *regs) +static void __init tcic_irq_count(int irq, void *dev, struct pt_regs *regs) { irq_hits++; } @@ -245,11 +243,11 @@ u_short cfg; irq_hits = 0; - if (request_irq(irq, irq_count, 0, "irq scan", irq_count) != 0) + if (request_irq(irq, tcic_irq_count, 0, "irq scan", tcic_irq_count) != 0) return -1; mdelay(10); if (irq_hits) { - free_irq(irq, irq_count); + free_irq(irq, tcic_irq_count); return -1; } @@ -260,7 +258,7 @@ tcic_setb(TCIC_ICSR, TCIC_ICSR_ERR | TCIC_ICSR_JAM); udelay(1000); - free_irq(irq, irq_count); + free_irq(irq, tcic_irq_count); /* Turn off interrupts */ tcic_setb(TCIC_IENA, TCIC_IENA_CFG_OFF); @@ -301,9 +299,9 @@ /* Fallback: just find interrupts that aren't in use */ for (i = 0; i < 16; i++) if ((mask0 & (1 << i)) && - (request_irq(i, irq_count, 0, "x", irq_count) == 0)) { + (request_irq(i, tcic_irq_count, 0, "x", tcic_irq_count) == 0)) { mask1 |= (1 << i); - free_irq(i, irq_count); + free_irq(i, tcic_irq_count); } printk("default"); } @@ -983,18 +981,18 @@ } static struct pccard_operations tcic_operations = { - tcic_init, - tcic_suspend, - tcic_register_callback, - tcic_inquire_socket, - tcic_get_status, - tcic_get_socket, - tcic_set_socket, - tcic_get_io_map, - tcic_set_io_map, - tcic_get_mem_map, - tcic_set_mem_map, - tcic_proc_setup + .init = tcic_init, + .suspend = tcic_suspend, + .register_callback = tcic_register_callback, + .inquire_socket = tcic_inquire_socket, + .get_status = tcic_get_status, + .get_socket = tcic_get_socket, + .set_socket = tcic_set_socket, + .get_io_map = tcic_get_io_map, + .set_io_map = tcic_set_io_map, + .get_mem_map = tcic_get_mem_map, + .set_mem_map = tcic_set_mem_map, + .proc_setup = tcic_proc_setup, }; /*====================================================================*/ diff -Nru a/drivers/pnp/driver.c b/drivers/pnp/driver.c --- a/drivers/pnp/driver.c Fri Nov 22 13:41:22 2002 +++ b/drivers/pnp/driver.c Fri Nov 22 13:41:22 2002 @@ -143,8 +143,8 @@ struct bus_type pnp_bus_type = { - name: "pnp", - match: pnp_bus_match, + .name = "pnp", + .match = pnp_bus_match, }; diff -Nru a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c --- a/drivers/pnp/isapnp/core.c Fri Nov 22 13:41:20 2002 +++ b/drivers/pnp/isapnp/core.c Fri Nov 22 13:41:20 2002 @@ -1055,10 +1055,10 @@ } struct pnp_protocol isapnp_protocol = { - name: "ISA Plug and Play", - get: isapnp_get_resources, - set: isapnp_set_resources, - disable:isapnp_disable_resources, + .name = "ISA Plug and Play", + .get = isapnp_get_resources, + .set = isapnp_set_resources, + .disable = isapnp_disable_resources, }; static inline int isapnp_init_device_tree(void) diff -Nru a/drivers/pnp/isapnp/proc.c b/drivers/pnp/isapnp/proc.c --- a/drivers/pnp/isapnp/proc.c Fri Nov 22 13:41:18 2002 +++ b/drivers/pnp/isapnp/proc.c Fri Nov 22 13:41:18 2002 @@ -88,8 +88,8 @@ static struct file_operations isapnp_proc_bus_file_operations = { - llseek: isapnp_proc_bus_lseek, - read: isapnp_proc_bus_read, + .llseek = isapnp_proc_bus_lseek, + .read = isapnp_proc_bus_read, }; static int isapnp_proc_attach_device(struct pnp_dev *dev) diff -Nru a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c --- a/drivers/pnp/pnpbios/core.c Fri Nov 22 13:41:17 2002 +++ b/drivers/pnp/pnpbios/core.c Fri Nov 22 13:41:17 2002 @@ -1293,29 +1293,29 @@ struct pnp_cfg * config = kmalloc(sizeof(struct pnp_cfg), GFP_KERNEL); /* first we need to set everything to a disabled value */ struct pnp_port port = { - max: 0, - min: 0, - align: 0, - size: 0, - flags: 0, - pad: 0, + .max = 0, + .min = 0, + .align = 0, + .size = 0, + .flags = 0, + .pad = 0, }; struct pnp_mem mem = { - max: 0, - min: 0, - align: 0, - size: 0, - flags: 0, - pad: 0, + .max = 0, + .min = 0, + .align = 0, + .size = 0, + .flags = 0, + .pad = 0, }; struct pnp_dma dma = { - map: 0, - flags: 0, + .map = 0, + .flags = 0, }; struct pnp_irq irq = { - map: 0, - flags: 0, - pad: 0, + .map = 0, + .flags = 0, + .pad = 0, }; int i; struct pnp_dev_node_info node_info; @@ -1358,10 +1358,10 @@ /* PnP Layer support */ static struct pnp_protocol pnpbios_protocol = { - name: "Plug and Play BIOS", - get: pnpbios_get_resources, - set: pnpbios_set_resources, - disable:pnpbios_disable_resources, + .name = "Plug and Play BIOS", + .get = pnpbios_get_resources, + .set = pnpbios_set_resources, + .disable = pnpbios_disable_resources, }; static int inline insert_device(struct pnp_dev *dev) diff -Nru a/drivers/s390/Kconfig b/drivers/s390/Kconfig --- a/drivers/s390/Kconfig Fri Nov 22 13:41:22 2002 +++ b/drivers/s390/Kconfig Fri Nov 22 13:41:22 2002 @@ -257,24 +257,30 @@ Include support for using an IBM 3215 line-mode terminal as a Linux system console. -config HWC - bool "Support for HWC line mode terminal" +config SCLP + bool "Support for SCLP" help - Include support for IBM HWC line-mode terminals. + Include support for the SCLP interface to the service element. -config HWC_CONSOLE - bool "console on HWC line mode terminal" - depends on HWC +config SCLP_TTY + bool "Support for SCLP line mode terminal" + depends on SCLP + help + Include support for IBM SCLP line-mode terminals. + +config SCLP_CONSOLE + bool "Support for console on SCLP line mode terminal" + depends on SCLP_TTY help Include support for using an IBM HWC line-mode terminal as the Linux system console. -config HWC_CPI +config SCLP_CPI tristate "Control-Program Identification" - depends on HWC + depends on SCLP help This option enables the hardware console interface for system - identification This is commonly used for workload management and + identification. This is commonly used for workload management and gives you a nice name for the system on the service element. Please select this option as a module since built-in operation is completely untested. diff -Nru a/drivers/s390/block/Makefile b/drivers/s390/block/Makefile --- a/drivers/s390/block/Makefile Fri Nov 22 13:41:23 2002 +++ b/drivers/s390/block/Makefile Fri Nov 22 13:41:23 2002 @@ -11,9 +11,9 @@ dasd_genhd.o dasd_erp.o obj-$(CONFIG_DASD) += dasd_mod.o +obj-$(CONFIG_DASD_DIAG) += dasd_diag_mod.o obj-$(CONFIG_DASD_ECKD) += dasd_eckd_mod.o obj-$(CONFIG_DASD_FBA) += dasd_fba_mod.o -obj-$(CONFIG_DASD_DIAG) += dasd_diag_mod.o obj-$(CONFIG_BLK_DEV_XPRAM) += xpram.o include $(TOPDIR)/Rules.make diff -Nru a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c --- a/drivers/s390/block/dasd_diag.c Fri Nov 22 13:41:17 2002 +++ b/drivers/s390/block/dasd_diag.c Fri Nov 22 13:41:17 2002 @@ -464,19 +464,19 @@ * for one request. Give a little safety and the result is 240. */ static dasd_discipline_t dasd_diag_discipline = { - owner:THIS_MODULE, - name:"DIAG", - ebcname:"DIAG", - max_blocks:240, - check_device:dasd_diag_check_device, - fill_geometry:dasd_diag_fill_geometry, - start_IO:dasd_start_diag, - examine_error:dasd_diag_examine_error, - erp_action:dasd_diag_erp_action, - erp_postaction:dasd_diag_erp_postaction, - build_cp:dasd_diag_build_cp, - dump_sense:dasd_diag_dump_sense, - fill_info:dasd_diag_fill_info, + .owner = THIS_MODULE, + .name = "DIAG", + .ebcname = "DIAG", + .max_blocks = 240, + .check_device = dasd_diag_check_device, + .fill_geometry = dasd_diag_fill_geometry, + .start_IO = dasd_start_diag, + .examine_error = dasd_diag_examine_error, + .erp_action = dasd_diag_erp_action, + .erp_postaction = dasd_diag_erp_postaction, + .build_cp = dasd_diag_build_cp, + .dump_sense = dasd_diag_dump_sense, + .fill_info = dasd_diag_fill_info, }; int diff -Nru a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c --- a/drivers/s390/block/dasd_eckd.c Fri Nov 22 13:41:17 2002 +++ b/drivers/s390/block/dasd_eckd.c Fri Nov 22 13:41:17 2002 @@ -73,25 +73,25 @@ static devreg_t dasd_eckd_known_devices[] = { { - ci: { hc: { ctype: 0x3880, dtype:3390 } }, - flag:(DEVREG_MATCH_CU_TYPE | DEVREG_MATCH_DEV_TYPE | + .ci = { .hc = { .ctype = 0x3880, .dtype = 3390 } }, + .flag = (DEVREG_MATCH_CU_TYPE | DEVREG_MATCH_DEV_TYPE | DEVREG_TYPE_DEVCHARS), - oper_func:dasd_oper_handler + .oper_func = dasd_oper_handler }, { - ci: { hc: { ctype:0x3990 } }, - flag:(DEVREG_MATCH_CU_TYPE | DEVREG_TYPE_DEVCHARS), - oper_func:dasd_oper_handler + .ci = { .hc = { .ctype = 0x3990 } }, + .flag = (DEVREG_MATCH_CU_TYPE | DEVREG_TYPE_DEVCHARS), + .oper_func = dasd_oper_handler }, { - ci: { hc: { ctype:0x2105 } }, - flag:(DEVREG_MATCH_CU_TYPE | DEVREG_TYPE_DEVCHARS), - oper_func:dasd_oper_handler + .ci = { .hc = { .ctype = 0x2105 } }, + .flag = (DEVREG_MATCH_CU_TYPE | DEVREG_TYPE_DEVCHARS), + .oper_func = dasd_oper_handler }, { - ci: { hc: { ctype:0x9343 } }, - flag:(DEVREG_MATCH_CU_TYPE | DEVREG_TYPE_DEVCHARS), - oper_func:dasd_oper_handler + .ci = { .hc = { .ctype = 0x9343 } }, + .flag = (DEVREG_MATCH_CU_TYPE | DEVREG_TYPE_DEVCHARS), + .oper_func = dasd_oper_handler } }; @@ -1418,22 +1418,22 @@ * for one request. Give a little safety and the result is 240. */ static dasd_discipline_t dasd_eckd_discipline = { - owner:THIS_MODULE, - name:"ECKD", - ebcname:"ECKD", - max_blocks:240, - check_device:dasd_eckd_check_device, - do_analysis:dasd_eckd_do_analysis, - fill_geometry:dasd_eckd_fill_geometry, - start_IO:dasd_start_IO, - term_IO:dasd_term_IO, - format_device:dasd_eckd_format_device, - examine_error:dasd_eckd_examine_error, - erp_action:dasd_eckd_erp_action, - erp_postaction:dasd_eckd_erp_postaction, - build_cp:dasd_eckd_build_cp, - dump_sense:dasd_eckd_dump_sense, - fill_info:dasd_eckd_fill_info, + .owner = THIS_MODULE, + .name = "ECKD", + .ebcname = "ECKD", + .max_blocks = 240, + .check_device = dasd_eckd_check_device, + .do_analysis = dasd_eckd_do_analysis, + .fill_geometry = dasd_eckd_fill_geometry, + .start_IO = dasd_start_IO, + .term_IO = dasd_term_IO, + .format_device = dasd_eckd_format_device, + .examine_error = dasd_eckd_examine_error, + .erp_action = dasd_eckd_erp_action, + .erp_postaction = dasd_eckd_erp_postaction, + .build_cp = dasd_eckd_build_cp, + .dump_sense = dasd_eckd_dump_sense, + .fill_info = dasd_eckd_fill_info, }; int diff -Nru a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c --- a/drivers/s390/block/dasd_fba.c Fri Nov 22 13:41:21 2002 +++ b/drivers/s390/block/dasd_fba.c Fri Nov 22 13:41:21 2002 @@ -47,16 +47,16 @@ static devreg_t dasd_fba_known_devices[] = { { - ci: {hc: {ctype: 0x6310, dtype:0x9336}}, - flag:(DEVREG_MATCH_CU_TYPE | + .ci = {.hc = {.ctype = 0x6310, .dtype = 0x9336}}, + .flag = (DEVREG_MATCH_CU_TYPE | DEVREG_MATCH_DEV_TYPE | DEVREG_TYPE_DEVCHARS), - oper_func:dasd_oper_handler + .oper_func = dasd_oper_handler }, { - ci: {hc: {ctype: 0x3880, dtype:0x3370}}, - flag:(DEVREG_MATCH_CU_TYPE | + .ci = {.hc = {.ctype = 0x3880, .dtype = 0x3370}}, + .flag = (DEVREG_MATCH_CU_TYPE | DEVREG_MATCH_DEV_TYPE | DEVREG_TYPE_DEVCHARS), - oper_func:dasd_oper_handler + .oper_func = dasd_oper_handler } }; @@ -392,21 +392,21 @@ * for one request. Give a little safety and the result is 96. */ static dasd_discipline_t dasd_fba_discipline = { - owner:THIS_MODULE, - name:"FBA ", - ebcname:"FBA ", - max_blocks:96, - check_device:dasd_fba_check_device, - do_analysis:dasd_fba_do_analysis, - fill_geometry:dasd_fba_fill_geometry, - start_IO:dasd_start_IO, - term_IO:dasd_term_IO, - examine_error:dasd_fba_examine_error, - erp_action:dasd_fba_erp_action, - erp_postaction:dasd_fba_erp_postaction, - build_cp:dasd_fba_build_cp, - dump_sense:dasd_fba_dump_sense, - fill_info:dasd_fba_fill_info, + .owner = THIS_MODULE, + .name = "FBA ", + .ebcname = "FBA ", + .max_blocks = 96, + .check_device = dasd_fba_check_device, + .do_analysis = dasd_fba_do_analysis, + .fill_geometry = dasd_fba_fill_geometry, + .start_IO = dasd_start_IO, + .term_IO = dasd_term_IO, + .examine_error = dasd_fba_examine_error, + .erp_action = dasd_fba_erp_action, + .erp_postaction = dasd_fba_erp_postaction, + .build_cp = dasd_fba_build_cp, + .dump_sense = dasd_fba_dump_sense, + .fill_info = dasd_fba_fill_info, }; int diff -Nru a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c --- a/drivers/s390/block/dasd_proc.c Fri Nov 22 13:41:18 2002 +++ b/drivers/s390/block/dasd_proc.c Fri Nov 22 13:41:18 2002 @@ -262,11 +262,11 @@ } static struct file_operations dasd_devices_file_ops = { - owner:THIS_MODULE, - read:dasd_generic_read, /* read */ - write:dasd_devices_write, /* write */ - open:dasd_devices_open, /* open */ - release:dasd_generic_close, /* close */ + .owner = THIS_MODULE, + .read = dasd_generic_read, /* read */ + .write = dasd_devices_write, /* write */ + .open = dasd_devices_open, /* open */ + .release = dasd_generic_close, /* close */ }; static struct inode_operations dasd_devices_inode_ops = { @@ -416,11 +416,11 @@ } static struct file_operations dasd_statistics_file_ops = { - owner: THIS_MODULE, - read: dasd_generic_read, /* read */ - write: dasd_statistics_write, /* write */ - open: dasd_statistics_open, /* open */ - release:dasd_generic_close, /* close */ + .owner = THIS_MODULE, + .read = dasd_generic_read, /* read */ + .write = dasd_statistics_write, /* write */ + .open = dasd_statistics_open, /* open */ + .release = dasd_generic_close, /* close */ }; static struct inode_operations dasd_statistics_inode_ops = { diff -Nru a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c --- a/drivers/s390/block/xpram.c Fri Nov 22 13:41:22 2002 +++ b/drivers/s390/block/xpram.c Fri Nov 22 13:41:22 2002 @@ -325,7 +325,6 @@ { struct hd_geometry *geo; unsigned long size; - int idx = minor(inode->i_rdev); if (cmd != HDIO_GETGEO) return -EINVAL; /* @@ -474,6 +473,7 @@ out: while (i--) put_disk(xpram_disks[i]); + return rc; } /* diff -Nru a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile --- a/drivers/s390/char/Makefile Fri Nov 22 13:41:19 2002 +++ b/drivers/s390/char/Makefile Fri Nov 22 13:41:19 2002 @@ -2,28 +2,23 @@ # S/390 character devices # -export-objs := hwc_rw.o tape.o tape34xx.o +export-objs := sclp_rw.o tape_core.o tape_devmap.o tape_std.o tub3270-objs := tuball.o tubfs.o tubtty.o \ tubttyaid.o tubttybld.o tubttyscl.o \ tubttyrcl.o tubttysiz.o -tape390-$(CONFIG_S390_TAPE_CHAR) += tapechar.o -tape390-$(CONFIG_S390_TAPE_BLOCK) += tapeblock.o - -tape390-objs := tape.o tape34xx.o $(sort $(tape390-y)) -tape_3480_mod-objs := tape3480.o -tape_3490_mod-objs := tape3490.o - - obj-y += ctrlchar.o obj-$(CONFIG_TN3215) += con3215.o -obj-$(CONFIG_HWC) += hwc_con.o hwc_rw.o hwc_tty.o -obj-$(CONFIG_HWC_CPI) += hwc_cpi.o +obj-$(CONFIG_SCLP) += sclp.o +obj-$(CONFIG_SCLP_TTY) += sclp_rw.o sclp_tty.o +obj-$(CONFIG_SCLP_CONSOLE) += sclp_con.o +obj-$(CONFIG_SCLP_CPI) += sclp_cpi.o obj-$(CONFIG_TN3270) += tub3270.o -obj-$(CONFIG_S390_TAPE) += tape390.o -obj-$(CONFIG_S390_TAPE_3480) += tape_3480_mod.o -obj-$(CONFIG_S390_TAPE_3490) += tape_3490_mod.o +tape-$(CONFIG_S390_TAPE_BLOCK) += tape_block.o +tape-$(CONFIG_PROC_FS) += tape_proc.o +tape-objs := tape_core.o tape_std.o tape_char.o $(tape-y) +obj-$(CONFIG_S390_TAPE) += tape.o +obj-$(CONFIG_S390_TAPE_34XX) += tape_34xx.o include $(TOPDIR)/Rules.make - diff -Nru a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c --- a/drivers/s390/char/con3215.c Fri Nov 22 13:41:21 2002 +++ b/drivers/s390/char/con3215.c Fri Nov 22 13:41:21 2002 @@ -822,12 +822,12 @@ * The console structure for the 3215 console */ static struct console con3215 = { - name: "tty3215", - write: con3215_write, - device: con3215_device, - unblank: con3215_unblank, - setup: con3215_consetup, - flags: CON_PRINTBUFFER, + .name = "tty3215", + .write = con3215_write, + .device = con3215_device, + .unblank = con3215_unblank, + .setup = con3215_consetup, + .flags = CON_PRINTBUFFER, }; #endif diff -Nru a/drivers/s390/char/hwc.h b/drivers/s390/char/hwc.h --- a/drivers/s390/char/hwc.h Fri Nov 22 13:41:21 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,280 +0,0 @@ -/* - * drivers/s390/char/hwc.h - * - * - * S390 version - * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation - * Author(s): Martin Peschke - * - * - * - */ - -#ifndef __HWC_H__ -#define __HWC_H__ - -#define HWC_EXT_INT_PARAM_ADDR 0xFFFFFFF8 -#define HWC_EXT_INT_PARAM_PEND 0x00000001 - -#define ET_OpCmd 0x01 -#define ET_Msg 0x02 -#define ET_StateChange 0x08 -#define ET_PMsgCmd 0x09 -#define ET_CntlProgOpCmd 0x20 -#define ET_CntlProgIdent 0x0B -#define ET_SigQuiesce 0x1D - -#define ET_OpCmd_Mask 0x80000000 -#define ET_Msg_Mask 0x40000000 -#define ET_StateChange_Mask 0x01000000 -#define ET_PMsgCmd_Mask 0x00800000 -#define ET_CtlProgOpCmd_Mask 0x00000001 -#define ET_CtlProgIdent_Mask 0x00200000 -#define ET_SigQuiesce_Mask 0x00000008 - -#define GMF_DOM 0x8000 -#define GMF_SndAlrm 0x4000 -#define GMF_HoldMsg 0x2000 - -#define LTF_CntlText 0x8000 -#define LTF_LabelText 0x4000 -#define LTF_DataText 0x2000 -#define LTF_EndText 0x1000 -#define LTF_PromptText 0x0800 - -#define HWC_COMMAND_INITIATED 0 -#define HWC_BUSY 2 -#define HWC_NOT_OPERATIONAL 3 - -#define hwc_cmdw_t u32; - -#define HWC_CMDW_READDATA 0x00770005 - -#define HWC_CMDW_WRITEDATA 0x00760005 - -#define HWC_CMDW_WRITEMASK 0x00780005 - -#define GDS_ID_MDSMU 0x1310 - -#define GDS_ID_MDSRouteInfo 0x1311 - -#define GDS_ID_AgUnWrkCorr 0x1549 - -#define GDS_ID_SNACondReport 0x1532 - -#define GDS_ID_CPMSU 0x1212 - -#define GDS_ID_RoutTargInstr 0x154D - -#define GDS_ID_OpReq 0x8070 - -#define GDS_ID_TextCmd 0x1320 - -#define GDS_KEY_SelfDefTextMsg 0x31 - -#define _HWCB_HEADER u16 length; \ - u8 function_code; \ - u8 control_mask[3]; \ - u16 response_code; - -#define _EBUF_HEADER u16 length; \ - u8 type; \ - u8 flags; \ - u16 _reserved; - -typedef struct { - _EBUF_HEADER -} __attribute__ ((packed)) - -evbuf_t; - -#define _MDB_HEADER u16 length; \ - u16 type; \ - u32 tag; \ - u32 revision_code; - -#define _GO_HEADER u16 length; \ - u16 type; \ - u32 domid; \ - u8 hhmmss_time[8]; \ - u8 th_time[3]; \ - u8 _reserved_0; \ - u8 dddyyyy_date[7]; \ - u8 _reserved_1; \ - u16 general_msg_flags; \ - u8 _reserved_2[10]; \ - u8 originating_system_name[8]; \ - u8 job_guest_name[8]; - -#define _MTO_HEADER u16 length; \ - u16 type; \ - u16 line_type_flags; \ - u8 alarm_control; \ - u8 _reserved[3]; - -typedef struct { - _GO_HEADER -} __attribute__ ((packed)) - -go_t; - -typedef struct { - go_t go; -} __attribute__ ((packed)) - -mdb_body_t; - -typedef struct { - _MDB_HEADER - mdb_body_t mdb_body; -} __attribute__ ((packed)) - -mdb_t; - -typedef struct { - _EBUF_HEADER - mdb_t mdb; -} __attribute__ ((packed)) - -msgbuf_t; - -typedef struct { - _HWCB_HEADER - msgbuf_t msgbuf; -} __attribute__ ((packed)) - -write_hwcb_t; - -typedef struct { - _MTO_HEADER -} __attribute__ ((packed)) - -mto_t; - -/* FIXME: don't define static variables in a header!!! */ -#warning -static write_hwcb_t write_hwcb_template = -{ - sizeof (write_hwcb_t), - 0x00, - { - 0x00, - 0x00, - 0x00 - }, - 0x0000, - { - sizeof (msgbuf_t), - ET_Msg, - 0x00, - 0x0000, - { - sizeof (mdb_t), - 0x0001, - 0xD4C4C240, - 0x00000001, - { - { - sizeof (go_t), - 0x0001 - - } - } - } - } -}; - -#warning -static mto_t mto_template = -{ - sizeof (mto_t), - 0x0004, - LTF_EndText, - 0x00 -}; - -typedef u32 _hwcb_mask_t; - -typedef struct { - _HWCB_HEADER - u16 _reserved; - u16 mask_length; - _hwcb_mask_t cp_receive_mask; - _hwcb_mask_t cp_send_mask; - _hwcb_mask_t hwc_receive_mask; - _hwcb_mask_t hwc_send_mask; -} __attribute__ ((packed)) - -init_hwcb_t; - -#warning -static init_hwcb_t init_hwcb_template = -{ - sizeof (init_hwcb_t), - 0x00, - { - 0x00, - 0x00, - 0x00 - }, - 0x0000, - 0x0000, - sizeof (_hwcb_mask_t), - ET_OpCmd_Mask | ET_PMsgCmd_Mask | - ET_StateChange_Mask | ET_SigQuiesce_Mask, - ET_Msg_Mask | ET_PMsgCmd_Mask | ET_CtlProgIdent_Mask -}; - -typedef struct { - _EBUF_HEADER - u8 validity_hwc_active_facility_mask:1; - u8 validity_hwc_receive_mask:1; - u8 validity_hwc_send_mask:1; - u8 validity_read_data_function_mask:1; - u16 _zeros:12; - u16 mask_length; - u64 hwc_active_facility_mask; - _hwcb_mask_t hwc_receive_mask; - _hwcb_mask_t hwc_send_mask; - u32 read_data_function_mask; -} __attribute__ ((packed)) - -statechangebuf_t; - -#define _GDS_VECTOR_HEADER u16 length; \ - u16 gds_id; - -#define _GDS_SUBVECTOR_HEADER u8 length; \ - u8 key; - -typedef struct { - _GDS_VECTOR_HEADER -} __attribute__ ((packed)) - -gds_vector_t; - -typedef struct { - _GDS_SUBVECTOR_HEADER -} __attribute__ ((packed)) - -gds_subvector_t; - -typedef struct { - _HWCB_HEADER -} __attribute__ ((packed)) - -read_hwcb_t; - -#warning -static read_hwcb_t read_hwcb_template = -{ - PAGE_SIZE, - 0x00, - { - 0x00, - 0x00, - 0x80 - } -}; - -#endif /* __HWC_H__ */ diff -Nru a/drivers/s390/char/hwc_con.c b/drivers/s390/char/hwc_con.c --- a/drivers/s390/char/hwc_con.c Fri Nov 22 13:41:17 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,92 +0,0 @@ -/* - * drivers/s390/char/hwc_con.c - * HWC line mode console driver - * - * S390 version - * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation - * Author(s): Martin Peschke - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hwc_rw.h" - -#ifdef CONFIG_HWC_CONSOLE - -#define hwc_console_major 4 -#define hwc_console_minor 64 -#define hwc_console_name "console" - -void hwc_console_write (struct console *, const char *, unsigned int); -kdev_t hwc_console_device (struct console *); -void hwc_console_unblank (void); - -#define HWC_CON_PRINT_HEADER "hwc console driver: " - -struct console hwc_console = -{ - - name:hwc_console_name, - write:hwc_console_write, - device:hwc_console_device, - unblank:hwc_console_unblank, - flags:CON_PRINTBUFFER, -}; - -void -hwc_console_write ( - struct console *console, - const char *message, - unsigned int count) -{ - - if (kdev_val (console->device (console)) != - kdev_val (hwc_console.device (&hwc_console))) { - - hwc_printk (KERN_WARNING HWC_CON_PRINT_HEADER - "hwc_console_write() called with wrong " - "device number"); - return; - } - hwc_write (0, message, count); -} - -kdev_t -hwc_console_device (struct console * c) -{ - return mk_kdev (hwc_console_major, hwc_console_minor); -} - -void -hwc_console_unblank (void) -{ - hwc_unblank (); -} - -#endif - -void __init -hwc_console_init (void) -{ - if (!MACHINE_HAS_HWC) - return; - - if (hwc_init () == 0) { -#ifdef CONFIG_HWC_CONSOLE - - if (CONSOLE_IS_HWC) - register_console (&hwc_console); -#endif - } else - panic (HWC_CON_PRINT_HEADER "hwc initialisation failed !"); - - return; -} diff -Nru a/drivers/s390/char/hwc_cpi.c b/drivers/s390/char/hwc_cpi.c --- a/drivers/s390/char/hwc_cpi.c Fri Nov 22 13:41:21 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,212 +0,0 @@ - -/* - * Author: Martin Peschke - * Copyright (C) 2001 IBM Entwicklung GmbH, IBM Corporation - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "hwc_rw.h" -#include "hwc.h" - -#define CPI_RETRIES 3 -#define CPI_SLEEP_TICKS 50 - -#define CPI_LENGTH_SYSTEM_TYPE 8 -#define CPI_LENGTH_SYSTEM_NAME 8 -#define CPI_LENGTH_SYSPLEX_NAME 8 - -typedef struct { - _EBUF_HEADER - u8 id_format; - u8 reserved0; - u8 system_type[CPI_LENGTH_SYSTEM_TYPE]; - u64 reserved1; - u8 system_name[CPI_LENGTH_SYSTEM_NAME]; - u64 reserved2; - u64 system_level; - u64 reserved3; - u8 sysplex_name[CPI_LENGTH_SYSPLEX_NAME]; - u8 reserved4[16]; -} __attribute__ ((packed)) - -cpi_evbuf_t; - -typedef struct _cpi_hwcb_t { - _HWCB_HEADER - cpi_evbuf_t cpi_evbuf; -} __attribute__ ((packed)) - -cpi_hwcb_t; - -cpi_hwcb_t *cpi_hwcb; - -static int __init cpi_module_init (void); -static void __exit cpi_module_exit (void); - -module_init (cpi_module_init); -module_exit (cpi_module_exit); - -MODULE_AUTHOR ( - "Martin Peschke, IBM Deutschland Entwicklung GmbH " - ""); - -MODULE_DESCRIPTION ( - "identify this operating system instance to the S/390 or zSeries hardware"); - -static char *system_name = NULL; -MODULE_PARM (system_name, "s"); -MODULE_PARM_DESC (system_name, "e.g. hostname - max. 8 characters"); - -static char *sysplex_name = NULL; -#ifdef ALLOW_SYSPLEX_NAME -MODULE_PARM (sysplex_name, "s"); -MODULE_PARM_DESC (sysplex_name, "if applicable - max. 8 characters"); -#endif - -static char *system_type = "LINUX"; - -hwc_request_t cpi_request = -{}; - -hwc_callback_t cpi_callback; - -static DECLARE_MUTEX_LOCKED (sem); - -static int __init -cpi_module_init (void) -{ - int retval; - int system_type_length; - int system_name_length; - int sysplex_name_length = 0; - int retries; - - if (!MACHINE_HAS_HWC) { - printk ("cpi: bug: hardware console not present\n"); - retval = -EINVAL; - goto out; - } - if (!system_type) { - printk ("cpi: bug: no system type specified\n"); - retval = -EINVAL; - goto out; - } - system_type_length = strlen (system_type); - if (system_type_length > CPI_LENGTH_SYSTEM_NAME) { - printk ("cpi: bug: system type has length of %i characters - " - "only %i characters supported\n", - system_type_length, - CPI_LENGTH_SYSTEM_TYPE); - retval = -EINVAL; - goto out; - } - if (!system_name) { - printk ("cpi: no system name specified\n"); - retval = -EINVAL; - goto out; - } - system_name_length = strlen (system_name); - if (system_name_length > CPI_LENGTH_SYSTEM_NAME) { - printk ("cpi: system name has length of %i characters - " - "only %i characters supported\n", - system_name_length, - CPI_LENGTH_SYSTEM_NAME); - retval = -EINVAL; - goto out; - } - if (sysplex_name) { - sysplex_name_length = strlen (sysplex_name); - if (sysplex_name_length > CPI_LENGTH_SYSPLEX_NAME) { - printk ("cpi: sysplex name has length of %i characters - " - "only %i characters supported\n", - sysplex_name_length, - CPI_LENGTH_SYSPLEX_NAME); - retval = -EINVAL; - goto out; - } - } - cpi_hwcb = kmalloc (sizeof (cpi_hwcb_t), GFP_KERNEL); - if (!cpi_hwcb) { - printk ("cpi: no storage to fulfill request\n"); - retval = -ENOMEM; - goto out; - } - memset (cpi_hwcb, 0, sizeof (cpi_hwcb_t)); - - cpi_hwcb->length = sizeof (cpi_hwcb_t); - cpi_hwcb->cpi_evbuf.length = sizeof (cpi_evbuf_t); - cpi_hwcb->cpi_evbuf.type = 0x0B; - - memset (cpi_hwcb->cpi_evbuf.system_type, ' ', CPI_LENGTH_SYSTEM_TYPE); - memcpy (cpi_hwcb->cpi_evbuf.system_type, system_type, system_type_length); - HWC_ASCEBC_STR (cpi_hwcb->cpi_evbuf.system_type, CPI_LENGTH_SYSTEM_TYPE); - EBC_TOUPPER (cpi_hwcb->cpi_evbuf.system_type, CPI_LENGTH_SYSTEM_TYPE); - - memset (cpi_hwcb->cpi_evbuf.system_name, ' ', CPI_LENGTH_SYSTEM_NAME); - memcpy (cpi_hwcb->cpi_evbuf.system_name, system_name, system_name_length); - HWC_ASCEBC_STR (cpi_hwcb->cpi_evbuf.system_name, CPI_LENGTH_SYSTEM_NAME); - EBC_TOUPPER (cpi_hwcb->cpi_evbuf.system_name, CPI_LENGTH_SYSTEM_NAME); - - cpi_hwcb->cpi_evbuf.system_level = LINUX_VERSION_CODE; - - if (sysplex_name) { - memset (cpi_hwcb->cpi_evbuf.sysplex_name, ' ', CPI_LENGTH_SYSPLEX_NAME); - memcpy (cpi_hwcb->cpi_evbuf.sysplex_name, sysplex_name, sysplex_name_length); - HWC_ASCEBC_STR (cpi_hwcb->cpi_evbuf.sysplex_name, CPI_LENGTH_SYSPLEX_NAME); - EBC_TOUPPER (cpi_hwcb->cpi_evbuf.sysplex_name, CPI_LENGTH_SYSPLEX_NAME); - } - cpi_request.block = cpi_hwcb; - cpi_request.word = HWC_CMDW_WRITEDATA; - cpi_request.callback = cpi_callback; - - for (retries = CPI_RETRIES; retries; retries--) { - retval = hwc_send (&cpi_request); - if (retval) { - - set_current_state (TASK_INTERRUPTIBLE); - schedule_timeout (CPI_SLEEP_TICKS); - } else { - - down (&sem); - - switch (cpi_hwcb->response_code) { - case 0x0020: - printk ("cpi: succeeded\n"); - break; - default: - printk ("cpi: failed with response code 0x%x\n", - cpi_hwcb->response_code); - } - goto free; - } - } - - printk ("cpi: failed (%i)\n", retval); - - free: - kfree (cpi_hwcb); - - out: - return retval; -} - -static void __exit -cpi_module_exit (void) -{ - printk ("cpi: exit\n"); -} - -void -cpi_callback (hwc_request_t * req) -{ - up (&sem); -} diff -Nru a/drivers/s390/char/hwc_rw.c b/drivers/s390/char/hwc_rw.c --- a/drivers/s390/char/hwc_rw.c Fri Nov 22 13:41:18 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,2456 +0,0 @@ -/* - * drivers/s390/char/hwc_rw.c - * driver: reading from and writing to system console on S/390 via HWC - * - * S390 version - * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation - * Author(s): Martin Peschke - * - * - * - * - * - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef MIN -#define MIN(a,b) (((amto_char_sum) - -#define _HWCB_MTO(hwcb) (_LIST(hwcb)->mto_number) - -#define _HWCB_CHAR_LOST(hwcb) (_LIST(hwcb)->mto_char_sum_lost) - -#define _HWCB_MTO_LOST(hwcb) (_LIST(hwcb)->mto_number_lost) - -#define _HWCB_TIMES_LOST(hwcb) (_LIST(hwcb)->times_lost) - -#define _HWCB_NEXT(hwcb) (_LIST(hwcb)->next) - -#define BUF_HWCB_CHAR _HWCB_CHAR(BUF_HWCB) - -#define BUF_HWCB_MTO _HWCB_MTO(BUF_HWCB) - -#define BUF_HWCB_NEXT _HWCB_NEXT(BUF_HWCB) - -#define OUT_HWCB_CHAR _HWCB_CHAR(OUT_HWCB) - -#define OUT_HWCB_MTO _HWCB_MTO(OUT_HWCB) - -#define OUT_HWCB_NEXT _HWCB_NEXT(OUT_HWCB) - -#define BUF_HWCB_CHAR_LOST _HWCB_CHAR_LOST(BUF_HWCB) - -#define BUF_HWCB_MTO_LOST _HWCB_MTO_LOST(BUF_HWCB) - -#define OUT_HWCB_CHAR_LOST _HWCB_CHAR_LOST(OUT_HWCB) - -#define OUT_HWCB_MTO_LOST _HWCB_MTO_LOST(OUT_HWCB) - -#define BUF_HWCB_TIMES_LOST _HWCB_TIMES_LOST(BUF_HWCB) - -#include "hwc.h" - -#define __HWC_RW_C__ -#include "hwc_rw.h" -#undef __HWC_RW_C__ - -static unsigned char _obuf[MAX_HWCB_ROOM]; - -static unsigned char - _page[PAGE_SIZE] __attribute__ ((aligned (PAGE_SIZE))); - -typedef unsigned long kmem_pages_t; - -#define MAX_KMEM_PAGES (sizeof(kmem_pages_t) << 3) - -#define HWC_WTIMER_RUNS 1 -#define HWC_FLUSH 2 -#define HWC_INIT 4 -#define HWC_BROKEN 8 -#define HWC_INTERRUPT 16 -#define HWC_PTIMER_RUNS 32 - -static struct { - - hwc_ioctls_t ioctls; - - hwc_ioctls_t init_ioctls; - - unsigned char *hwcb_list_head; - - unsigned char *hwcb_list_tail; - - unsigned short int mto_number; - - unsigned int mto_char_sum; - - unsigned char hwcb_count; - - unsigned long kmem_start; - - unsigned long kmem_end; - - kmem_pages_t kmem_pages; - - unsigned char *obuf; - - unsigned short int obuf_cursor; - - unsigned short int obuf_count; - - unsigned short int obuf_start; - - unsigned char *page; - - u32 current_servc; - - unsigned char *current_hwcb; - - unsigned char write_nonprio:1; - unsigned char write_prio:1; - unsigned char read_nonprio:1; - unsigned char read_prio:1; - unsigned char read_statechange:1; - unsigned char sig_quiesce:1; - - unsigned char flags; - - hwc_high_level_calls_t *calls; - - hwc_request_t *request; - - spinlock_t lock; - - struct timer_list write_timer; - - struct timer_list poll_timer; -} hwc_data = -{ - { - }, - { - 8, - 0, - 80, - 1, - MAX_KMEM_PAGES, - MAX_KMEM_PAGES, - - 0, - - 0x6c - - }, - NULL, - NULL, - 0, - 0, - 0, - 0, - 0, - 0, - _obuf, - 0, - 0, - 0, - _page, - 0, - NULL, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - NULL, - NULL - -}; - -static unsigned long cr0 __attribute__ ((aligned (8))); -static unsigned long cr0_save __attribute__ ((aligned (8))); -static unsigned char psw_mask __attribute__ ((aligned (8))); - -static ext_int_info_t ext_int_info_hwc; - -#define DELAYED_WRITE 0 -#define IMMEDIATE_WRITE 1 - -static signed int do_hwc_write (int from_user, unsigned char *, - unsigned int, - unsigned char); - -unsigned char hwc_ip_buf[512]; - -static asmlinkage int -internal_print (char write_time, char *fmt,...) -{ - va_list args; - int i; - - va_start (args, fmt); - i = vsprintf (hwc_ip_buf, fmt, args); - va_end (args); - return do_hwc_write (0, hwc_ip_buf, i, write_time); -} - -int -hwc_printk (const char *fmt,...) -{ - va_list args; - int i; - unsigned long flags; - int retval; - - spin_lock_irqsave (&hwc_data.lock, flags); - - i = vsprintf (hwc_ip_buf, fmt, args); - va_end (args); - retval = do_hwc_write (0, hwc_ip_buf, i, IMMEDIATE_WRITE); - - spin_unlock_irqrestore (&hwc_data.lock, flags); - - return retval; -} - -#ifdef DUMP_HWCB_INPUT - -static void -dump_storage_area (unsigned char *area, unsigned short int count) -{ - unsigned short int index; - ioctl_nl_t old_final_nl; - - if (!area || !count) - return; - - old_final_nl = hwc_data.ioctls.final_nl; - hwc_data.ioctls.final_nl = 1; - - internal_print (DELAYED_WRITE, "\n%8x ", area); - - for (index = 0; index < count; index++) { - - if (area[index] <= 0xF) - internal_print (DELAYED_WRITE, "0%x", area[index]); - else - internal_print (DELAYED_WRITE, "%x", area[index]); - - if ((index & 0xF) == 0xF) - internal_print (DELAYED_WRITE, "\n%8x ", - &area[index + 1]); - else if ((index & 3) == 3) - internal_print (DELAYED_WRITE, " "); - } - - internal_print (IMMEDIATE_WRITE, "\n"); - - hwc_data.ioctls.final_nl = old_final_nl; -} -#endif - -static inline u32 -service_call ( - u32 hwc_command_word, - unsigned char hwcb[]) -{ - unsigned int condition_code = 1; - - __asm__ __volatile__ ("L 1, 0(%0) \n\t" - "LRA 2, 0(%1) \n\t" - ".long 0xB2200012 \n\t" - : - :"a" (&hwc_command_word), "a" (hwcb) - :"1", "2", "memory"); - - __asm__ __volatile__ ("IPM %0 \n\t" - "SRL %0, 28 \n\t" - :"=r" (condition_code)); - - return condition_code; -} - -static inline unsigned long -hwc_ext_int_param (void) -{ - u32 param; - - __asm__ __volatile__ ("L %0,128\n\t" - :"=r" (param)); - - return (unsigned long) param; -} - -static int -prepare_write_hwcb (void) -{ - write_hwcb_t *hwcb; - - if (!BUF_HWCB) - return -ENOMEM; - - BUF_HWCB_MTO = 0; - BUF_HWCB_CHAR = 0; - - hwcb = (write_hwcb_t *) BUF_HWCB; - - memcpy (hwcb, &write_hwcb_template, sizeof (write_hwcb_t)); - - return 0; -} - -static int -sane_write_hwcb (void) -{ - unsigned short int lost_msg; - unsigned int lost_char; - unsigned char lost_hwcb; - unsigned char *bad_addr; - unsigned long page; - int page_nr; - - if (!OUT_HWCB) - return -ENOMEM; - - if ((unsigned long) OUT_HWCB & 0xFFF) { - - bad_addr = OUT_HWCB; - -#ifdef DUMP_HWC_WRITE_LIST_ERROR - __asm__ ("LHI 1,0xe30\n\t" - "LRA 2,0(%0) \n\t" - "J .+0 \n\t" - : - : "a" (bad_addr) - : "1", "2"); -#endif - - hwc_data.kmem_pages = 0; - if ((unsigned long) BUF_HWCB & 0xFFF) { - - lost_hwcb = hwc_data.hwcb_count; - lost_msg = ALL_HWCB_MTO; - lost_char = ALL_HWCB_CHAR; - - OUT_HWCB = NULL; - BUF_HWCB = NULL; - ALL_HWCB_MTO = 0; - ALL_HWCB_CHAR = 0; - hwc_data.hwcb_count = 0; - } else { - - lost_hwcb = hwc_data.hwcb_count - 1; - lost_msg = ALL_HWCB_MTO - BUF_HWCB_MTO; - lost_char = ALL_HWCB_CHAR - BUF_HWCB_CHAR; - OUT_HWCB = BUF_HWCB; - ALL_HWCB_MTO = BUF_HWCB_MTO; - ALL_HWCB_CHAR = BUF_HWCB_CHAR; - hwc_data.hwcb_count = 1; - page = (unsigned long) BUF_HWCB; - - if (page >= hwc_data.kmem_start && - page <= hwc_data.kmem_end) { - - page_nr = (int) - ((page - hwc_data.kmem_start) >> 12); - set_bit (page_nr, &hwc_data.kmem_pages); - } - } - - internal_print ( - DELAYED_WRITE, - HWC_RW_PRINT_HEADER - "found invalid HWCB at address 0x%lx. List corrupted. " - "Lost %i HWCBs with %i characters within up to %i " - "messages. Saved %i HWCB with last %i characters i" - "within up to %i messages.\n", - (unsigned long) bad_addr, - lost_hwcb, lost_char, lost_msg, - hwc_data.hwcb_count, - ALL_HWCB_CHAR, ALL_HWCB_MTO); - } - return 0; -} - -static int -reuse_write_hwcb (void) -{ - int retval; - - if (hwc_data.hwcb_count < 2) -#ifdef DUMP_HWC_WRITE_LIST_ERROR - __asm__ ("LHI 1,0xe31\n\t" - "LRA 2,0(%0)\n\t" - "LRA 3,0(%1)\n\t" - "J .+0 \n\t" - : - : "a" (BUF_HWCB), "a" (OUT_HWCB) - : "1", "2", "3"); -#else - return -EPERM; -#endif - - if (hwc_data.current_hwcb == OUT_HWCB) { - - if (hwc_data.hwcb_count > 2) { - - BUF_HWCB_NEXT = OUT_HWCB_NEXT; - - BUF_HWCB = OUT_HWCB_NEXT; - - OUT_HWCB_NEXT = BUF_HWCB_NEXT; - - BUF_HWCB_NEXT = NULL; - } - } else { - - BUF_HWCB_NEXT = OUT_HWCB; - - BUF_HWCB = OUT_HWCB; - - OUT_HWCB = OUT_HWCB_NEXT; - - BUF_HWCB_NEXT = NULL; - } - - BUF_HWCB_TIMES_LOST += 1; - BUF_HWCB_CHAR_LOST += BUF_HWCB_CHAR; - BUF_HWCB_MTO_LOST += BUF_HWCB_MTO; - ALL_HWCB_MTO -= BUF_HWCB_MTO; - ALL_HWCB_CHAR -= BUF_HWCB_CHAR; - - retval = prepare_write_hwcb (); - - if (hwc_data.hwcb_count == hwc_data.ioctls.max_hwcb) - internal_print ( - DELAYED_WRITE, - HWC_RW_PRINT_HEADER - "reached my own limit of " - "allowed buffer space for output (%i HWCBs = %li " - "bytes), skipped content of oldest HWCB %i time(s) " - "(%i lines = %i characters)\n", - hwc_data.ioctls.max_hwcb, - hwc_data.ioctls.max_hwcb * PAGE_SIZE, - BUF_HWCB_TIMES_LOST, - BUF_HWCB_MTO_LOST, - BUF_HWCB_CHAR_LOST); - else - internal_print ( - DELAYED_WRITE, - HWC_RW_PRINT_HEADER - "page allocation failed, " - "could not expand buffer for output (currently in " - "use: %i HWCBs = %li bytes), skipped content of " - "oldest HWCB %i time(s) (%i lines = %i characters)\n", - hwc_data.hwcb_count, - hwc_data.hwcb_count * PAGE_SIZE, - BUF_HWCB_TIMES_LOST, - BUF_HWCB_MTO_LOST, - BUF_HWCB_CHAR_LOST); - - return retval; -} - -static int -allocate_write_hwcb (void) -{ - unsigned char *page; - int page_nr; - - if (hwc_data.hwcb_count == hwc_data.ioctls.max_hwcb) - return -ENOMEM; - - page_nr = find_first_zero_bit (&hwc_data.kmem_pages, MAX_KMEM_PAGES); - if (page_nr < hwc_data.ioctls.kmem_hwcb) { - - page = (unsigned char *) - (hwc_data.kmem_start + (page_nr << 12)); - set_bit (page_nr, &hwc_data.kmem_pages); - } else - page = (unsigned char *) __get_free_page (GFP_ATOMIC | GFP_DMA); - - if (!page) - return -ENOMEM; - - if (!OUT_HWCB) - OUT_HWCB = page; - else - BUF_HWCB_NEXT = page; - - BUF_HWCB = page; - - BUF_HWCB_NEXT = NULL; - - hwc_data.hwcb_count++; - - prepare_write_hwcb (); - - BUF_HWCB_TIMES_LOST = 0; - BUF_HWCB_MTO_LOST = 0; - BUF_HWCB_CHAR_LOST = 0; - -#ifdef BUFFER_STRESS_TEST - - internal_print ( - DELAYED_WRITE, - "*** " HWC_RW_PRINT_HEADER - "page #%i at 0x%x for buffering allocated. ***\n", - hwc_data.hwcb_count, page); - -#endif - - return 0; -} - -static int -release_write_hwcb (void) -{ - unsigned long page; - int page_nr; - - if (!hwc_data.hwcb_count) - return -ENODATA; - - if (hwc_data.hwcb_count == 1) { - - prepare_write_hwcb (); - - ALL_HWCB_CHAR = 0; - ALL_HWCB_MTO = 0; - BUF_HWCB_TIMES_LOST = 0; - BUF_HWCB_MTO_LOST = 0; - BUF_HWCB_CHAR_LOST = 0; - } else { - page = (unsigned long) OUT_HWCB; - - ALL_HWCB_MTO -= OUT_HWCB_MTO; - ALL_HWCB_CHAR -= OUT_HWCB_CHAR; - hwc_data.hwcb_count--; - - OUT_HWCB = OUT_HWCB_NEXT; - - if (page >= hwc_data.kmem_start && - page <= hwc_data.kmem_end) { - /*memset((void *) page, 0, PAGE_SIZE); */ - - page_nr = (int) ((page - hwc_data.kmem_start) >> 12); - clear_bit (page_nr, &hwc_data.kmem_pages); - } else - free_page (page); -#ifdef BUFFER_STRESS_TEST - - internal_print ( - DELAYED_WRITE, - "*** " HWC_RW_PRINT_HEADER - "page at 0x%x released, %i pages still in use ***\n", - page, hwc_data.hwcb_count); - -#endif - } - return 0; -} - -static int -add_mto ( - unsigned char *message, - unsigned short int count) -{ - unsigned short int mto_size; - write_hwcb_t *hwcb; - mto_t *mto; - void *dest; - - if (!BUF_HWCB) - return -ENOMEM; - - if (BUF_HWCB == hwc_data.current_hwcb) - return -ENOMEM; - - mto_size = sizeof (mto_t) + count; - - hwcb = (write_hwcb_t *) BUF_HWCB; - - if ((MAX_HWCB_ROOM - hwcb->length) < mto_size) - return -ENOMEM; - - mto = (mto_t *) (((unsigned long) hwcb) + hwcb->length); - - memcpy (mto, &mto_template, sizeof (mto_t)); - - dest = (void *) (((unsigned long) mto) + sizeof (mto_t)); - - memcpy (dest, message, count); - - mto->length += count; - - hwcb->length += mto_size; - hwcb->msgbuf.length += mto_size; - hwcb->msgbuf.mdb.length += mto_size; - - BUF_HWCB_MTO++; - ALL_HWCB_MTO++; - BUF_HWCB_CHAR += count; - ALL_HWCB_CHAR += count; - - return count; -} - -static int write_event_data_1 (void); - -static void -do_poll_hwc (unsigned long data) -{ - unsigned long flags; - - spin_lock_irqsave (&hwc_data.lock, flags); - - write_event_data_1 (); - - spin_unlock_irqrestore (&hwc_data.lock, flags); -} - -void -start_poll_hwc (void) -{ - init_timer (&hwc_data.poll_timer); - hwc_data.poll_timer.function = do_poll_hwc; - hwc_data.poll_timer.data = (unsigned long) NULL; - hwc_data.poll_timer.expires = jiffies + 2 * HZ; - add_timer (&hwc_data.poll_timer); - hwc_data.flags |= HWC_PTIMER_RUNS; -} - -static int -write_event_data_1 (void) -{ - unsigned short int condition_code; - int retval; - write_hwcb_t *hwcb = (write_hwcb_t *) OUT_HWCB; - - if ((!hwc_data.write_prio) && - (!hwc_data.write_nonprio) && - hwc_data.read_statechange) - return -EOPNOTSUPP; - - if (hwc_data.current_servc) - return -EBUSY; - - retval = sane_write_hwcb (); - if (retval < 0) - return -EIO; - - if (!OUT_HWCB_MTO) - return -ENODATA; - - if (!hwc_data.write_nonprio && hwc_data.write_prio) - hwcb->msgbuf.type = ET_PMsgCmd; - else - hwcb->msgbuf.type = ET_Msg; - - condition_code = service_call (HWC_CMDW_WRITEDATA, OUT_HWCB); - -#ifdef DUMP_HWC_WRITE_ERROR - if (condition_code != HWC_COMMAND_INITIATED) - __asm__ ("LHI 1,0xe20\n\t" - "L 2,0(%0)\n\t" - "LRA 3,0(%1)\n\t" - "J .+0 \n\t" - : - : "a" (&condition_code), "a" (OUT_HWCB) - : "1", "2", "3"); -#endif - - switch (condition_code) { - case HWC_COMMAND_INITIATED: - hwc_data.current_servc = HWC_CMDW_WRITEDATA; - hwc_data.current_hwcb = OUT_HWCB; - retval = condition_code; - break; - case HWC_BUSY: - retval = -EBUSY; - break; - case HWC_NOT_OPERATIONAL: - start_poll_hwc (); - default: - retval = -EIO; - } - - return retval; -} - -static void -flush_hwcbs (void) -{ - while (hwc_data.hwcb_count > 1) - release_write_hwcb (); - - release_write_hwcb (); - - hwc_data.flags &= ~HWC_FLUSH; -} - -static int -write_event_data_2 (u32 ext_int_param) -{ - write_hwcb_t *hwcb; - int retval = 0; - -#ifdef DUMP_HWC_WRITE_ERROR - if ((ext_int_param & HWC_EXT_INT_PARAM_ADDR) - != (unsigned long) hwc_data.current_hwcb) { - internal_print ( - DELAYED_WRITE, - HWC_RW_PRINT_HEADER - "write_event_data_2 : " - "HWCB address does not fit " - "(expected: 0x%lx, got: 0x%lx).\n", - (unsigned long) hwc_data.current_hwcb, - ext_int_param); - return -EINVAL; - } -#endif - - hwcb = (write_hwcb_t *) OUT_HWCB; - -#ifdef DUMP_HWC_WRITE_LIST_ERROR - if (((unsigned char *) hwcb) != hwc_data.current_hwcb) { - __asm__ ("LHI 1,0xe22\n\t" - "LRA 2,0(%0)\n\t" - "LRA 3,0(%1)\n\t" - "LRA 4,0(%2)\n\t" - "LRA 5,0(%3)\n\t" - "J .+0 \n\t" - : - : "a" (OUT_HWCB), - "a" (hwc_data.current_hwcb), - "a" (BUF_HWCB), - "a" (hwcb) - : "1", "2", "3", "4", "5"); - } -#endif - -#ifdef DUMP_HWC_WRITE_ERROR - if (hwcb->response_code != 0x0020) { - __asm__ ("LHI 1,0xe21\n\t" - "LRA 2,0(%0)\n\t" - "LRA 3,0(%1)\n\t" - "LRA 4,0(%2)\n\t" - "LH 5,0(%3)\n\t" - "SRL 5,8\n\t" - "J .+0 \n\t" - : - : "a" (OUT_HWCB), "a" (hwc_data.current_hwcb), - "a" (BUF_HWCB), - "a" (&(hwc_data.hwcb_count)) - : "1", "2", "3", "4", "5"); - } -#endif - - switch (hwcb->response_code) { - case 0x0020: - - retval = OUT_HWCB_CHAR; - release_write_hwcb (); - break; - case 0x0040: - case 0x0340: - case 0x40F0: - if (!hwc_data.read_statechange) { - hwcb->response_code = 0; - start_poll_hwc (); - } - retval = -EIO; - break; - default: - internal_print ( - DELAYED_WRITE, - HWC_RW_PRINT_HEADER - "write_event_data_2 : " - "failed operation " - "(response code: 0x%x " - "HWCB address: 0x%x).\n", - hwcb->response_code, - hwcb); - retval = -EIO; - } - - if (retval == -EIO) { - - hwcb->control_mask[0] = 0; - hwcb->control_mask[1] = 0; - hwcb->control_mask[2] = 0; - hwcb->response_code = 0; - } - hwc_data.current_servc = 0; - hwc_data.current_hwcb = NULL; - - if (hwc_data.flags & HWC_FLUSH) - flush_hwcbs (); - - return retval; -} - -static void -do_put_line ( - unsigned char *message, - unsigned short count) -{ - - if (add_mto (message, count) != count) { - - if (allocate_write_hwcb () < 0) - reuse_write_hwcb (); - -#ifdef DUMP_HWC_WRITE_LIST_ERROR - if (add_mto (message, count) != count) - __asm__ ("LHI 1,0xe32\n\t" - "LRA 2,0(%0)\n\t" - "L 3,0(%1)\n\t" - "LRA 4,0(%2)\n\t" - "LRA 5,0(%3)\n\t" - "J .+0 \n\t" - : - : "a" (message), "a" (&hwc_data.kmem_pages), - "a" (BUF_HWCB), "a" (OUT_HWCB) - : "1", "2", "3", "4", "5"); -#else - add_mto (message, count); -#endif - } -} - -static void -put_line ( - unsigned char *message, - unsigned short count) -{ - - if ((!hwc_data.obuf_start) && (hwc_data.flags & HWC_WTIMER_RUNS)) { - del_timer (&hwc_data.write_timer); - hwc_data.flags &= ~HWC_WTIMER_RUNS; - } - hwc_data.obuf_start += count; - - do_put_line (message, count); - - hwc_data.obuf_start -= count; -} - -static void -set_alarm (void) -{ - write_hwcb_t *hwcb; - - if ((!BUF_HWCB) || (BUF_HWCB == hwc_data.current_hwcb)) - allocate_write_hwcb (); - - hwcb = (write_hwcb_t *) BUF_HWCB; - hwcb->msgbuf.mdb.mdb_body.go.general_msg_flags |= GMF_SndAlrm; -} - -static void -hwc_write_timeout (unsigned long data) -{ - unsigned long flags; - - spin_lock_irqsave (&hwc_data.lock, flags); - - hwc_data.obuf_start = hwc_data.obuf_count; - if (hwc_data.obuf_count) - put_line (hwc_data.obuf, hwc_data.obuf_count); - hwc_data.obuf_start = 0; - - hwc_data.obuf_cursor = 0; - hwc_data.obuf_count = 0; - - write_event_data_1 (); - - spin_unlock_irqrestore (&hwc_data.lock, flags); -} - -static int -do_hwc_write ( - int from_user, - unsigned char *msg, - unsigned int count, - unsigned char write_time) -{ - unsigned int i_msg = 0; - unsigned short int spaces = 0; - unsigned int processed_characters = 0; - unsigned char ch; - unsigned short int obuf_count; - unsigned short int obuf_cursor; - unsigned short int obuf_columns; - - if (hwc_data.obuf_start) { - obuf_cursor = 0; - obuf_count = 0; - obuf_columns = MIN (hwc_data.ioctls.columns, - MAX_MESSAGE_SIZE - hwc_data.obuf_start); - } else { - obuf_cursor = hwc_data.obuf_cursor; - obuf_count = hwc_data.obuf_count; - obuf_columns = hwc_data.ioctls.columns; - } - - for (i_msg = 0; i_msg < count; i_msg++) { - if (from_user) - get_user (ch, msg + i_msg); - else - ch = msg[i_msg]; - - processed_characters++; - - if ((obuf_cursor == obuf_columns) && - - (ch != '\n') && - - (ch != '\t')) { - put_line (&hwc_data.obuf[hwc_data.obuf_start], - obuf_columns); - obuf_cursor = 0; - obuf_count = 0; - } - switch (ch) { - - case '\n': - - put_line (&hwc_data.obuf[hwc_data.obuf_start], - obuf_count); - obuf_cursor = 0; - obuf_count = 0; - break; - - case '\a': - - hwc_data.obuf_start += obuf_count; - set_alarm (); - hwc_data.obuf_start -= obuf_count; - - break; - - case '\t': - - do { - if (obuf_cursor < obuf_columns) { - hwc_data.obuf[hwc_data.obuf_start + - obuf_cursor] - = HWC_ASCEBC (' '); - obuf_cursor++; - } else - break; - } while (obuf_cursor % hwc_data.ioctls.width_htab); - - break; - - case '\f': - case '\v': - - spaces = obuf_cursor; - put_line (&hwc_data.obuf[hwc_data.obuf_start], - obuf_count); - obuf_count = obuf_cursor; - while (spaces) { - hwc_data.obuf[hwc_data.obuf_start + - obuf_cursor - spaces] - = HWC_ASCEBC (' '); - spaces--; - } - - break; - - case '\b': - - if (obuf_cursor) - obuf_cursor--; - break; - - case '\r': - - obuf_cursor = 0; - break; - - case 0x00: - - put_line (&hwc_data.obuf[hwc_data.obuf_start], - obuf_count); - obuf_cursor = 0; - obuf_count = 0; - goto out; - - default: - - if (isprint (ch)) - hwc_data.obuf[hwc_data.obuf_start + - obuf_cursor++] - = HWC_ASCEBC (ch); - } - if (obuf_cursor > obuf_count) - obuf_count = obuf_cursor; - } - - if (obuf_cursor) { - - if (hwc_data.obuf_start || - (hwc_data.ioctls.final_nl == 0)) { - - put_line (&hwc_data.obuf[hwc_data.obuf_start], - obuf_count); - obuf_cursor = 0; - obuf_count = 0; - } else { - - if (hwc_data.ioctls.final_nl > 0) { - - if (hwc_data.flags & HWC_WTIMER_RUNS) { - - mod_timer (&hwc_data.write_timer, - jiffies + hwc_data.ioctls.final_nl * HZ / 10); - } else { - - init_timer (&hwc_data.write_timer); - hwc_data.write_timer.function = - hwc_write_timeout; - hwc_data.write_timer.data = - (unsigned long) NULL; - hwc_data.write_timer.expires = - jiffies + - hwc_data.ioctls.final_nl * HZ / 10; - add_timer (&hwc_data.write_timer); - hwc_data.flags |= HWC_WTIMER_RUNS; - } - } else; - - } - } else; - - out: - - if (!hwc_data.obuf_start) { - hwc_data.obuf_cursor = obuf_cursor; - hwc_data.obuf_count = obuf_count; - } - if (write_time == IMMEDIATE_WRITE) - write_event_data_1 (); - - return processed_characters; -} - -signed int -hwc_write (int from_user, const unsigned char *msg, unsigned int count) -{ - unsigned long flags; - int retval; - - spin_lock_irqsave (&hwc_data.lock, flags); - - retval = do_hwc_write (from_user, (unsigned char *) msg, - count, IMMEDIATE_WRITE); - - spin_unlock_irqrestore (&hwc_data.lock, flags); - - return retval; -} - -unsigned int -hwc_chars_in_buffer (unsigned char flag) -{ - unsigned short int number = 0; - unsigned long flags; - - spin_lock_irqsave (&hwc_data.lock, flags); - - if (flag & IN_HWCB) - number += ALL_HWCB_CHAR; - - if (flag & IN_WRITE_BUF) - number += hwc_data.obuf_cursor; - - spin_unlock_irqrestore (&hwc_data.lock, flags); - - return number; -} - -static inline int -nr_setbits (kmem_pages_t arg) -{ - int i; - int nr = 0; - - for (i = 0; i < (sizeof (arg) << 3); i++) { - if (arg & 1) - nr++; - arg >>= 1; - } - - return nr; -} - -unsigned int -hwc_write_room (unsigned char flag) -{ - unsigned int number = 0; - unsigned long flags; - write_hwcb_t *hwcb; - - spin_lock_irqsave (&hwc_data.lock, flags); - - if (flag & IN_HWCB) { - - if (BUF_HWCB) { - hwcb = (write_hwcb_t *) BUF_HWCB; - number += MAX_HWCB_ROOM - hwcb->length; - } - number += (hwc_data.ioctls.kmem_hwcb - - nr_setbits (hwc_data.kmem_pages)) * - (MAX_HWCB_ROOM - - (sizeof (write_hwcb_t) + sizeof (mto_t))); - } - if (flag & IN_WRITE_BUF) - number += MAX_HWCB_ROOM - hwc_data.obuf_cursor; - - spin_unlock_irqrestore (&hwc_data.lock, flags); - - return number; -} - -void -hwc_flush_buffer (unsigned char flag) -{ - unsigned long flags; - - spin_lock_irqsave (&hwc_data.lock, flags); - - if (flag & IN_HWCB) { - if (hwc_data.current_servc != HWC_CMDW_WRITEDATA) - flush_hwcbs (); - else - hwc_data.flags |= HWC_FLUSH; - } - if (flag & IN_WRITE_BUF) { - hwc_data.obuf_cursor = 0; - hwc_data.obuf_count = 0; - } - spin_unlock_irqrestore (&hwc_data.lock, flags); -} - -unsigned short int -seperate_cases (unsigned char *buf, unsigned short int count) -{ - - unsigned short int i_in; - - unsigned short int i_out = 0; - - unsigned char _case = 0; - - for (i_in = 0; i_in < count; i_in++) { - - if (buf[i_in] == hwc_data.ioctls.delim) { - - if ((i_in + 1 < count) && - (buf[i_in + 1] == hwc_data.ioctls.delim)) { - - buf[i_out] = hwc_data.ioctls.delim; - - i_out++; - - i_in++; - - } else - _case = ~_case; - - } else { - - if (_case) { - - if (hwc_data.ioctls.tolower) - buf[i_out] = _ebc_toupper[buf[i_in]]; - - else - buf[i_out] = _ebc_tolower[buf[i_in]]; - - } else - buf[i_out] = buf[i_in]; - - i_out++; - } - } - - return i_out; -} - -#ifdef DUMP_HWCB_INPUT - -static int -gds_vector_name (u16 id, unsigned char name[]) -{ - int retval = 0; - - switch (id) { - case GDS_ID_MDSMU: - name = "Multiple Domain Support Message Unit"; - break; - case GDS_ID_MDSRouteInfo: - name = "MDS Routing Information"; - break; - case GDS_ID_AgUnWrkCorr: - name = "Agent Unit of Work Correlator"; - break; - case GDS_ID_SNACondReport: - name = "SNA Condition Report"; - break; - case GDS_ID_CPMSU: - name = "CP Management Services Unit"; - break; - case GDS_ID_RoutTargInstr: - name = "Routing and Targeting Instructions"; - break; - case GDS_ID_OpReq: - name = "Operate Request"; - break; - case GDS_ID_TextCmd: - name = "Text Command"; - break; - - default: - name = "unknown GDS variable"; - retval = -EINVAL; - } - - return retval; -} -#endif - -inline static gds_vector_t * -find_gds_vector ( - gds_vector_t * start, void *end, u16 id) -{ - gds_vector_t *vec; - gds_vector_t *retval = NULL; - - vec = start; - - while (((void *) vec) < end) { - if (vec->gds_id == id) { - -#ifdef DUMP_HWCB_INPUT - int retval_name; - unsigned char name[64]; - - retval_name = gds_vector_name (id, name); - internal_print ( - DELAYED_WRITE, - HWC_RW_PRINT_HEADER - "%s at 0x%x up to 0x%x, length: %d", - name, - (unsigned long) vec, - ((unsigned long) vec) + vec->length - 1, - vec->length); - if (retval_name < 0) - internal_print ( - IMMEDIATE_WRITE, - ", id: 0x%x\n", - vec->gds_id); - else - internal_print ( - IMMEDIATE_WRITE, - "\n"); -#endif - - retval = vec; - break; - } - vec = (gds_vector_t *) (((unsigned long) vec) + vec->length); - } - - return retval; -} - -inline static gds_subvector_t * -find_gds_subvector ( - gds_subvector_t * start, void *end, u8 key) -{ - gds_subvector_t *subvec; - gds_subvector_t *retval = NULL; - - subvec = start; - - while (((void *) subvec) < end) { - if (subvec->key == key) { - retval = subvec; - break; - } - subvec = (gds_subvector_t *) - (((unsigned long) subvec) + subvec->length); - } - - return retval; -} - -inline static int -get_input (void *start, void *end) -{ - int count; - - count = ((unsigned long) end) - ((unsigned long) start); - - if (hwc_data.ioctls.tolower) - EBC_TOLOWER (start, count); - - if (hwc_data.ioctls.delim) - count = seperate_cases (start, count); - - HWC_EBCASC_STR (start, count); - - if (hwc_data.ioctls.echo) - do_hwc_write (0, start, count, IMMEDIATE_WRITE); - - if (hwc_data.calls != NULL) - if (hwc_data.calls->move_input != NULL) - (hwc_data.calls->move_input) (start, count); - - return count; -} - -inline static int -eval_selfdeftextmsg (gds_subvector_t * start, void *end) -{ - gds_subvector_t *subvec; - void *subvec_data; - void *subvec_end; - int retval = 0; - - subvec = start; - - while (((void *) subvec) < end) { - subvec = find_gds_subvector (subvec, end, 0x30); - if (!subvec) - break; - subvec_data = (void *) - (((unsigned long) subvec) + - sizeof (gds_subvector_t)); - subvec_end = (void *) - (((unsigned long) subvec) + subvec->length); - retval += get_input (subvec_data, subvec_end); - subvec = (gds_subvector_t *) subvec_end; - } - - return retval; -} - -inline static int -eval_textcmd (gds_subvector_t * start, void *end) -{ - gds_subvector_t *subvec; - gds_subvector_t *subvec_data; - void *subvec_end; - int retval = 0; - - subvec = start; - - while (((void *) subvec) < end) { - subvec = find_gds_subvector ( - subvec, end, GDS_KEY_SelfDefTextMsg); - if (!subvec) - break; - subvec_data = (gds_subvector_t *) - (((unsigned long) subvec) + - sizeof (gds_subvector_t)); - subvec_end = (void *) - (((unsigned long) subvec) + subvec->length); - retval += eval_selfdeftextmsg (subvec_data, subvec_end); - subvec = (gds_subvector_t *) subvec_end; - } - - return retval; -} - -inline static int -eval_cpmsu (gds_vector_t * start, void *end) -{ - gds_vector_t *vec; - gds_subvector_t *vec_data; - void *vec_end; - int retval = 0; - - vec = start; - - while (((void *) vec) < end) { - vec = find_gds_vector (vec, end, GDS_ID_TextCmd); - if (!vec) - break; - vec_data = (gds_subvector_t *) - (((unsigned long) vec) + sizeof (gds_vector_t)); - vec_end = (void *) (((unsigned long) vec) + vec->length); - retval += eval_textcmd (vec_data, vec_end); - vec = (gds_vector_t *) vec_end; - } - - return retval; -} - -inline static int -eval_mdsmu (gds_vector_t * start, void *end) -{ - gds_vector_t *vec; - gds_vector_t *vec_data; - void *vec_end; - int retval = 0; - - vec = find_gds_vector (start, end, GDS_ID_CPMSU); - if (vec) { - vec_data = (gds_vector_t *) - (((unsigned long) vec) + sizeof (gds_vector_t)); - vec_end = (void *) (((unsigned long) vec) + vec->length); - retval = eval_cpmsu (vec_data, vec_end); - } - return retval; -} - -static int -eval_evbuf (gds_vector_t * start, void *end) -{ - gds_vector_t *vec; - gds_vector_t *vec_data; - void *vec_end; - int retval = 0; - - vec = find_gds_vector (start, end, GDS_ID_MDSMU); - if (vec) { - vec_data = (gds_vector_t *) - (((unsigned long) vec) + sizeof (gds_vector_t)); - vec_end = (void *) (((unsigned long) vec) + vec->length); - retval = eval_mdsmu (vec_data, vec_end); - } - return retval; -} - -static inline int -eval_hwc_receive_mask (_hwcb_mask_t mask) -{ - - hwc_data.write_nonprio - = ((mask & ET_Msg_Mask) == ET_Msg_Mask); - - hwc_data.write_prio - = ((mask & ET_PMsgCmd_Mask) == ET_PMsgCmd_Mask); - - if (hwc_data.write_prio || hwc_data.write_nonprio) { - internal_print ( - DELAYED_WRITE, - HWC_RW_PRINT_HEADER - "can write messages\n"); - return 0; - } else { - internal_print ( - DELAYED_WRITE, - HWC_RW_PRINT_HEADER - "can not write messages\n"); - return -1; - } -} - -static inline int -eval_hwc_send_mask (_hwcb_mask_t mask) -{ - - hwc_data.read_statechange - = ((mask & ET_StateChange_Mask) == ET_StateChange_Mask); - if (hwc_data.read_statechange) - internal_print ( - DELAYED_WRITE, - HWC_RW_PRINT_HEADER - "can read state change notifications\n"); - else - internal_print ( - DELAYED_WRITE, - HWC_RW_PRINT_HEADER - "can not read state change notifications\n"); - - hwc_data.sig_quiesce - = ((mask & ET_SigQuiesce_Mask) == ET_SigQuiesce_Mask); - if (hwc_data.sig_quiesce) - internal_print ( - DELAYED_WRITE, - HWC_RW_PRINT_HEADER - "can receive signal quiesce\n"); - else - internal_print ( - DELAYED_WRITE, - HWC_RW_PRINT_HEADER - "can not receive signal quiesce\n"); - - hwc_data.read_nonprio - = ((mask & ET_OpCmd_Mask) == ET_OpCmd_Mask); - if (hwc_data.read_nonprio) - internal_print ( - DELAYED_WRITE, - HWC_RW_PRINT_HEADER - "can read commands\n"); - - hwc_data.read_prio - = ((mask & ET_PMsgCmd_Mask) == ET_PMsgCmd_Mask); - if (hwc_data.read_prio) - internal_print ( - DELAYED_WRITE, - HWC_RW_PRINT_HEADER - "can read priority commands\n"); - - if (hwc_data.read_prio || hwc_data.read_nonprio) { - return 0; - } else { - internal_print ( - DELAYED_WRITE, - HWC_RW_PRINT_HEADER - "can not read commands from operator\n"); - return -1; - } -} - -static int -eval_statechangebuf (statechangebuf_t * scbuf) -{ - int retval = 0; - - internal_print ( - DELAYED_WRITE, - HWC_RW_PRINT_HEADER - "HWC state change detected\n"); - - if (scbuf->validity_hwc_active_facility_mask) { - - } - if (scbuf->validity_hwc_receive_mask) { - - if (scbuf->mask_length != 4) { -#ifdef DUMP_HWC_INIT_ERROR - __asm__ ("LHI 1,0xe50\n\t" - "LRA 2,0(%0)\n\t" - "J .+0 \n\t" - : - : "a" (scbuf) - : "1", "2"); -#endif - } else { - - retval += eval_hwc_receive_mask - (scbuf->hwc_receive_mask); - } - } - if (scbuf->validity_hwc_send_mask) { - - if (scbuf->mask_length != 4) { -#ifdef DUMP_HWC_INIT_ERROR - __asm__ ("LHI 1,0xe51\n\t" - "LRA 2,0(%0)\n\t" - "J .+0 \n\t" - : - : "a" (scbuf) - : "1", "2"); -#endif - } else { - - retval += eval_hwc_send_mask - (scbuf->hwc_send_mask); - } - } - if (scbuf->validity_read_data_function_mask) { - - } - return retval; -} - -#ifdef CONFIG_SMP -static volatile unsigned long cpu_quiesce_map; - -static void -do_load_quiesce_psw (void) -{ - psw_t quiesce_psw; - - clear_bit (smp_processor_id (), &cpu_quiesce_map); - if (smp_processor_id () == 0) { - - while (cpu_quiesce_map != 0) ; - - quiesce_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT; - quiesce_psw.addr = 0xfff; - __load_psw (quiesce_psw); - } - signal_processor (smp_processor_id (), sigp_stop); -} - -static void -do_machine_quiesce (void) -{ - cpu_quiesce_map = cpu_online_map; - smp_call_function (do_load_quiesce_psw, NULL, 0, 0); - do_load_quiesce_psw (); -} - -#else -static void -do_machine_quiesce (void) -{ - psw_t quiesce_psw; - - quiesce_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT; - queisce_psw.addr = 0xfff; - __load_psw (quiesce_psw); -} - -#endif - -static int -process_evbufs (void *start, void *end) -{ - int retval = 0; - evbuf_t *evbuf; - void *evbuf_end; - gds_vector_t *evbuf_data; - - evbuf = (evbuf_t *) start; - while (((void *) evbuf) < end) { - evbuf_data = (gds_vector_t *) - (((unsigned long) evbuf) + sizeof (evbuf_t)); - evbuf_end = (void *) (((unsigned long) evbuf) + evbuf->length); - switch (evbuf->type) { - case ET_OpCmd: - case ET_CntlProgOpCmd: - case ET_PMsgCmd: -#ifdef DUMP_HWCB_INPUT - - internal_print ( - DELAYED_WRITE, - HWC_RW_PRINT_HEADER - "event buffer " - "at 0x%x up to 0x%x, length: %d\n", - (unsigned long) evbuf, - (unsigned long) (evbuf_end - 1), - evbuf->length); - dump_storage_area ((void *) evbuf, evbuf->length); -#endif - retval += eval_evbuf (evbuf_data, evbuf_end); - break; - case ET_StateChange: - retval += eval_statechangebuf - ((statechangebuf_t *) evbuf); - break; - case ET_SigQuiesce: - - _machine_restart = do_machine_quiesce; - _machine_halt = do_machine_quiesce; - _machine_power_off = do_machine_quiesce; - ctrl_alt_del (); - break; - default: - internal_print ( - DELAYED_WRITE, - HWC_RW_PRINT_HEADER - "unconditional read: " - "unknown event buffer found, " - "type 0x%x", - evbuf->type); - retval = -ENOSYS; - } - evbuf = (evbuf_t *) evbuf_end; - } - return retval; -} - -static int -unconditional_read_1 (void) -{ - unsigned short int condition_code; - read_hwcb_t *hwcb = (read_hwcb_t *) hwc_data.page; - int retval; - -#if 0 - - if ((!hwc_data.read_prio) && (!hwc_data.read_nonprio)) - return -EOPNOTSUPP; - - if (hwc_data.current_servc) - return -EBUSY; -#endif - - memset (hwcb, 0x00, PAGE_SIZE); - memcpy (hwcb, &read_hwcb_template, sizeof (read_hwcb_t)); - - condition_code = service_call (HWC_CMDW_READDATA, hwc_data.page); - -#ifdef DUMP_HWC_READ_ERROR - if (condition_code == HWC_NOT_OPERATIONAL) - __asm__ ("LHI 1,0xe40\n\t" - "L 2,0(%0)\n\t" - "LRA 3,0(%1)\n\t" - "J .+0 \n\t" - : - : "a" (&condition_code), "a" (hwc_data.page) - : "1", "2", "3"); -#endif - - switch (condition_code) { - case HWC_COMMAND_INITIATED: - hwc_data.current_servc = HWC_CMDW_READDATA; - hwc_data.current_hwcb = hwc_data.page; - retval = condition_code; - break; - case HWC_BUSY: - retval = -EBUSY; - break; - default: - retval = -EIO; - } - - return retval; -} - -static int -unconditional_read_2 (u32 ext_int_param) -{ - read_hwcb_t *hwcb = (read_hwcb_t *) hwc_data.page; - -#ifdef DUMP_HWC_READ_ERROR - if ((hwcb->response_code != 0x0020) && - (hwcb->response_code != 0x0220) && - (hwcb->response_code != 0x60F0) && - (hwcb->response_code != 0x62F0)) - __asm__ ("LHI 1,0xe41\n\t" - "LRA 2,0(%0)\n\t" - "L 3,0(%1)\n\t" - "J .+0\n\t" - : - : "a" (hwc_data.page), "a" (&(hwcb->response_code)) - : "1", "2", "3"); -#endif - - hwc_data.current_servc = 0; - hwc_data.current_hwcb = NULL; - - switch (hwcb->response_code) { - - case 0x0020: - case 0x0220: - return process_evbufs ( - (void *) (((unsigned long) hwcb) + sizeof (read_hwcb_t)), - (void *) (((unsigned long) hwcb) + hwcb->length)); - - case 0x60F0: - case 0x62F0: - internal_print ( - IMMEDIATE_WRITE, - HWC_RW_PRINT_HEADER - "unconditional read: " - "got interrupt and tried to read input, " - "but nothing found (response code=0x%x).\n", - hwcb->response_code); - return 0; - - case 0x0100: - internal_print ( - IMMEDIATE_WRITE, - HWC_RW_PRINT_HEADER - "unconditional read: HWCB boundary violation - this " - "must not occur in a correct driver, please contact " - "author\n"); - return -EIO; - - case 0x0300: - internal_print ( - IMMEDIATE_WRITE, - HWC_RW_PRINT_HEADER - "unconditional read: " - "insufficient HWCB length - this must not occur in a " - "correct driver, please contact author\n"); - return -EIO; - - case 0x01F0: - internal_print ( - IMMEDIATE_WRITE, - HWC_RW_PRINT_HEADER - "unconditional read: " - "invalid command - this must not occur in a correct " - "driver, please contact author\n"); - return -EIO; - - case 0x40F0: - internal_print ( - IMMEDIATE_WRITE, - HWC_RW_PRINT_HEADER - "unconditional read: invalid function code\n"); - return -EIO; - - case 0x70F0: - internal_print ( - IMMEDIATE_WRITE, - HWC_RW_PRINT_HEADER - "unconditional read: invalid selection mask\n"); - return -EIO; - - case 0x0040: - internal_print ( - IMMEDIATE_WRITE, - HWC_RW_PRINT_HEADER - "unconditional read: HWC equipment check\n"); - return -EIO; - - default: - internal_print ( - IMMEDIATE_WRITE, - HWC_RW_PRINT_HEADER - "unconditional read: invalid response code %x - this " - "must not occur in a correct driver, please contact " - "author\n", - hwcb->response_code); - return -EIO; - } -} - -static int -write_event_mask_1 (void) -{ - unsigned int condition_code; - int retval; - - condition_code = service_call (HWC_CMDW_WRITEMASK, hwc_data.page); - -#ifdef DUMP_HWC_INIT_ERROR - - if (condition_code == HWC_NOT_OPERATIONAL) - __asm__ ("LHI 1,0xe10\n\t" - "L 2,0(%0)\n\t" - "LRA 3,0(%1)\n\t" - "J .+0\n\t" - : - : "a" (&condition_code), "a" (hwc_data.page) - : "1", "2", "3"); -#endif - - switch (condition_code) { - case HWC_COMMAND_INITIATED: - hwc_data.current_servc = HWC_CMDW_WRITEMASK; - hwc_data.current_hwcb = hwc_data.page; - retval = condition_code; - break; - case HWC_BUSY: - retval = -EBUSY; - break; - default: - retval = -EIO; - } - - return retval; -} - -static int -write_event_mask_2 (u32 ext_int_param) -{ - init_hwcb_t *hwcb = (init_hwcb_t *) hwc_data.page; - int retval = 0; - - if (hwcb->response_code != 0x0020) { -#ifdef DUMP_HWC_INIT_ERROR - __asm__ ("LHI 1,0xe11\n\t" - "LRA 2,0(%0)\n\t" - "L 3,0(%1)\n\t" - "J .+0\n\t" - : - : "a" (hwcb), "a" (&(hwcb->response_code)) - : "1", "2", "3"); -#else - retval = -1; -#endif - } else { - if (hwcb->mask_length != 4) { -#ifdef DUMP_HWC_INIT_ERROR - __asm__ ("LHI 1,0xe52\n\t" - "LRA 2,0(%0)\n\t" - "J .+0 \n\t" - : - : "a" (hwcb) - : "1", "2"); -#endif - } else { - retval += eval_hwc_receive_mask - (hwcb->hwc_receive_mask); - retval += eval_hwc_send_mask (hwcb->hwc_send_mask); - } - } - - hwc_data.current_servc = 0; - hwc_data.current_hwcb = NULL; - - return retval; -} - -static int -set_hwc_ioctls (hwc_ioctls_t * ioctls, char correct) -{ - int retval = 0; - hwc_ioctls_t tmp; - - if (ioctls->width_htab > MAX_MESSAGE_SIZE) { - if (correct) - tmp.width_htab = MAX_MESSAGE_SIZE; - else - retval = -EINVAL; - } else - tmp.width_htab = ioctls->width_htab; - - tmp.echo = ioctls->echo; - - if (ioctls->columns > MAX_MESSAGE_SIZE) { - if (correct) - tmp.columns = MAX_MESSAGE_SIZE; - else - retval = -EINVAL; - } else - tmp.columns = ioctls->columns; - - tmp.final_nl = ioctls->final_nl; - - if (ioctls->max_hwcb < 2) { - if (correct) - tmp.max_hwcb = 2; - else - retval = -EINVAL; - } else - tmp.max_hwcb = ioctls->max_hwcb; - - tmp.tolower = ioctls->tolower; - - if (ioctls->kmem_hwcb > ioctls->max_hwcb) { - if (correct) - tmp.kmem_hwcb = ioctls->max_hwcb; - else - retval = -EINVAL; - } else - tmp.kmem_hwcb = ioctls->kmem_hwcb; - - if (ioctls->kmem_hwcb > MAX_KMEM_PAGES) { - if (correct) - ioctls->kmem_hwcb = MAX_KMEM_PAGES; - else - retval = -EINVAL; - } - if (ioctls->kmem_hwcb < 2) { - if (correct) - ioctls->kmem_hwcb = 2; - else - retval = -EINVAL; - } - tmp.delim = ioctls->delim; - - if (!(retval < 0)) - hwc_data.ioctls = tmp; - - return retval; -} - -int -do_hwc_init (void) -{ - int retval; - - memcpy (hwc_data.page, &init_hwcb_template, sizeof (init_hwcb_t)); - - do { - - retval = write_event_mask_1 (); - - if (retval == -EBUSY) { - - hwc_data.flags |= HWC_INIT; - - __ctl_store (cr0, 0, 0); - cr0_save = cr0; - cr0 |= 0x00000200; - cr0 &= 0xFFFFF3AC; - __ctl_load (cr0, 0, 0); - - asm volatile ("STOSM %0,0x01" - :"=m" (psw_mask)::"memory"); - - while (!(hwc_data.flags & HWC_INTERRUPT)) - barrier (); - - asm volatile ("STNSM %0,0xFE" - :"=m" (psw_mask)::"memory"); - - __ctl_load (cr0_save, 0, 0); - - hwc_data.flags &= ~HWC_INIT; - } - } while (retval == -EBUSY); - - if (retval == -EIO) { - hwc_data.flags |= HWC_BROKEN; - printk (HWC_RW_PRINT_HEADER "HWC not operational\n"); - } - return retval; -} - -void hwc_interrupt_handler (struct pt_regs *regs, __u16 code); - -int -hwc_init (void) -{ - int retval; - -#ifdef BUFFER_STRESS_TEST - - init_hwcb_t *hwcb; - int i; - -#endif - - if (register_early_external_interrupt (0x2401, hwc_interrupt_handler, - &ext_int_info_hwc) != 0) - panic ("Couldn't request external interrupts 0x2401"); - - spin_lock_init (&hwc_data.lock); - -#ifdef USE_VM_DETECTION - - if (MACHINE_IS_VM) { - - if (hwc_data.init_ioctls.columns > 76) - hwc_data.init_ioctls.columns = 76; - hwc_data.init_ioctls.tolower = 1; - if (!hwc_data.init_ioctls.delim) - hwc_data.init_ioctls.delim = DEFAULT_CASE_DELIMITER; - } else { - hwc_data.init_ioctls.tolower = 0; - hwc_data.init_ioctls.delim = 0; - } -#endif - retval = set_hwc_ioctls (&hwc_data.init_ioctls, 1); - - hwc_data.kmem_start = (unsigned long) - alloc_bootmem_low_pages (hwc_data.ioctls.kmem_hwcb * PAGE_SIZE); - hwc_data.kmem_end = hwc_data.kmem_start + - hwc_data.ioctls.kmem_hwcb * PAGE_SIZE - 1; - - retval = do_hwc_init (); - - ctl_set_bit (0, 9); - -#ifdef BUFFER_STRESS_TEST - - internal_print ( - DELAYED_WRITE, - HWC_RW_PRINT_HEADER - "use %i bytes for buffering.\n", - hwc_data.ioctls.kmem_hwcb * PAGE_SIZE); - for (i = 0; i < 500; i++) { - hwcb = (init_hwcb_t *) BUF_HWCB; - internal_print ( - DELAYED_WRITE, - HWC_RW_PRINT_HEADER - "This is stress test message #%i, free: %i bytes\n", - i, - MAX_HWCB_ROOM - (hwcb->length + sizeof (mto_t))); - } - -#endif - - return /*retval */ 0; -} - -signed int -hwc_register_calls (hwc_high_level_calls_t * calls) -{ - if (calls == NULL) - return -EINVAL; - - if (hwc_data.calls != NULL) - return -EBUSY; - - hwc_data.calls = calls; - return 0; -} - -signed int -hwc_unregister_calls (hwc_high_level_calls_t * calls) -{ - if (hwc_data.calls == NULL) - return -EINVAL; - - if (calls != hwc_data.calls) - return -EINVAL; - - hwc_data.calls = NULL; - return 0; -} - -int -hwc_send (hwc_request_t * req) -{ - unsigned long flags; - int retval; - int cc; - - spin_lock_irqsave (&hwc_data.lock, flags); - if (!req || !req->callback || !req->block) { - retval = -EINVAL; - goto unlock; - } - if (hwc_data.request) { - retval = -ENOTSUPP; - goto unlock; - } - cc = service_call (req->word, req->block); - switch (cc) { - case 0: - hwc_data.request = req; - hwc_data.current_servc = req->word; - hwc_data.current_hwcb = req->block; - retval = 0; - break; - case 2: - retval = -EBUSY; - break; - default: - retval = -ENOSYS; - - } - unlock: - spin_unlock_irqrestore (&hwc_data.lock, flags); - return retval; -} - -EXPORT_SYMBOL (hwc_send); - -void -do_hwc_callback (u32 ext_int_param) -{ - if (!hwc_data.request || !hwc_data.request->callback) - return; - if ((ext_int_param & HWC_EXT_INT_PARAM_ADDR) - != (unsigned long) hwc_data.request->block) - return; - hwc_data.request->callback (hwc_data.request); - hwc_data.request = NULL; - hwc_data.current_hwcb = NULL; - hwc_data.current_servc = 0; -} - -void -hwc_do_interrupt (u32 ext_int_param) -{ - u32 finished_hwcb = ext_int_param & HWC_EXT_INT_PARAM_ADDR; - u32 evbuf_pending = ext_int_param & HWC_EXT_INT_PARAM_PEND; - - if (hwc_data.flags & HWC_PTIMER_RUNS) { - del_timer (&hwc_data.poll_timer); - hwc_data.flags &= ~HWC_PTIMER_RUNS; - } - if (finished_hwcb) { - - if ((unsigned long) hwc_data.current_hwcb != finished_hwcb) { - internal_print ( - DELAYED_WRITE, - HWC_RW_PRINT_HEADER - "interrupt: mismatch: " - "ext. int param. (0x%x) vs. " - "current HWCB (0x%x)\n", - ext_int_param, - hwc_data.current_hwcb); - } else { - if (hwc_data.request) { - - do_hwc_callback (ext_int_param); - } else { - - switch (hwc_data.current_servc) { - - case HWC_CMDW_WRITEMASK: - - write_event_mask_2 (ext_int_param); - break; - - case HWC_CMDW_WRITEDATA: - - write_event_data_2 (ext_int_param); - break; - - case HWC_CMDW_READDATA: - - unconditional_read_2 (ext_int_param); - break; - default: - break; - } - } - } - } else { - - if (hwc_data.current_hwcb) { - internal_print ( - DELAYED_WRITE, - HWC_RW_PRINT_HEADER - "interrupt: mismatch: " - "ext. int. param. (0x%x) vs. " - "current HWCB (0x%x)\n", - ext_int_param, - hwc_data.current_hwcb); - } - } - - if (evbuf_pending) { - - unconditional_read_1 (); - } else { - - write_event_data_1 (); - } - - if (!hwc_data.calls || !hwc_data.calls->wake_up) - return; - (hwc_data.calls->wake_up) (); -} - -void -hwc_interrupt_handler (struct pt_regs *regs, __u16 code) -{ - u32 ext_int_param = hwc_ext_int_param (); - - irq_enter (); - - if (hwc_data.flags & HWC_INIT) { - - hwc_data.flags |= HWC_INTERRUPT; - } else if (hwc_data.flags & HWC_BROKEN) { - - if (!do_hwc_init ()) { - hwc_data.flags &= ~HWC_BROKEN; - internal_print (DELAYED_WRITE, - HWC_RW_PRINT_HEADER - "delayed HWC setup after" - " temporary breakdown" - " (ext. int. parameter=0x%x)\n", - ext_int_param); - } - } else { - spin_lock (&hwc_data.lock); - hwc_do_interrupt (ext_int_param); - spin_unlock (&hwc_data.lock); - } - irq_exit (); -} - -void -hwc_unblank (void) -{ - - spin_lock (&hwc_data.lock); - spin_unlock (&hwc_data.lock); - - __ctl_store (cr0, 0, 0); - cr0_save = cr0; - cr0 |= 0x00000200; - cr0 &= 0xFFFFF3AC; - __ctl_load (cr0, 0, 0); - - asm volatile ("STOSM %0,0x01":"=m" (psw_mask)::"memory"); - - while (ALL_HWCB_CHAR) - barrier (); - - asm volatile ("STNSM %0,0xFE":"=m" (psw_mask)::"memory"); - - __ctl_load (cr0_save, 0, 0); -} - -int -hwc_ioctl (unsigned int cmd, unsigned long arg) -{ - hwc_ioctls_t tmp = hwc_data.ioctls; - int retval = 0; - unsigned long flags; - unsigned int obuf; - - spin_lock_irqsave (&hwc_data.lock, flags); - - switch (cmd) { - - case TIOCHWCSHTAB: - if (get_user (tmp.width_htab, (ioctl_htab_t *) arg)) - goto fault; - break; - - case TIOCHWCSECHO: - if (get_user (tmp.echo, (ioctl_echo_t *) arg)) - goto fault; - break; - - case TIOCHWCSCOLS: - if (get_user (tmp.columns, (ioctl_cols_t *) arg)) - goto fault; - break; - - case TIOCHWCSNL: - if (get_user (tmp.final_nl, (ioctl_nl_t *) arg)) - goto fault; - break; - - case TIOCHWCSOBUF: - if (get_user (obuf, (unsigned int *) arg)) - goto fault; - if (obuf & 0xFFF) - tmp.max_hwcb = (((obuf | 0xFFF) + 1) >> 12); - else - tmp.max_hwcb = (obuf >> 12); - break; - - case TIOCHWCSCASE: - if (get_user (tmp.tolower, (ioctl_case_t *) arg)) - goto fault; - break; - - case TIOCHWCSDELIM: - if (get_user (tmp.delim, (ioctl_delim_t *) arg)) - goto fault; - break; - - case TIOCHWCSINIT: - retval = set_hwc_ioctls (&hwc_data.init_ioctls, 1); - break; - - case TIOCHWCGHTAB: - if (put_user (tmp.width_htab, (ioctl_htab_t *) arg)) - goto fault; - break; - - case TIOCHWCGECHO: - if (put_user (tmp.echo, (ioctl_echo_t *) arg)) - goto fault; - break; - - case TIOCHWCGCOLS: - if (put_user (tmp.columns, (ioctl_cols_t *) arg)) - goto fault; - break; - - case TIOCHWCGNL: - if (put_user (tmp.final_nl, (ioctl_nl_t *) arg)) - goto fault; - break; - - case TIOCHWCGOBUF: - if (put_user (tmp.max_hwcb, (ioctl_obuf_t *) arg)) - goto fault; - break; - - case TIOCHWCGKBUF: - if (put_user (tmp.kmem_hwcb, (ioctl_obuf_t *) arg)) - goto fault; - break; - - case TIOCHWCGCASE: - if (put_user (tmp.tolower, (ioctl_case_t *) arg)) - goto fault; - break; - - case TIOCHWCGDELIM: - if (put_user (tmp.delim, (ioctl_delim_t *) arg)) - goto fault; - break; -#if 0 - - case TIOCHWCGINIT: - if (put_user (&hwc_data.init_ioctls, (hwc_ioctls_t *) arg)) - goto fault; - break; - - case TIOCHWCGCURR: - if (put_user (&hwc_data.ioctls, (hwc_ioctls_t *) arg)) - goto fault; - break; -#endif - - default: - goto noioctlcmd; - } - - if (_IOC_DIR (cmd) == _IOC_WRITE) - retval = set_hwc_ioctls (&tmp, 0); - - goto out; - - fault: - retval = -EFAULT; - goto out; - noioctlcmd: - retval = -ENOIOCTLCMD; - out: - spin_unlock_irqrestore (&hwc_data.lock, flags); - return retval; -} diff -Nru a/drivers/s390/char/hwc_rw.h b/drivers/s390/char/hwc_rw.h --- a/drivers/s390/char/hwc_rw.h Fri Nov 22 13:41:18 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,132 +0,0 @@ -/* - * drivers/s390/char/hwc_rw.h - * interface to the HWC-read/write driver - * - * S390 version - * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation - * Author(s): Martin Peschke - */ - -#ifndef __HWC_RW_H__ -#define __HWC_RW_H__ - -#include - -typedef struct { - - void (*move_input) (unsigned char *, unsigned int); - - void (*wake_up) (void); -} hwc_high_level_calls_t; - -struct _hwc_request; - -typedef void hwc_callback_t (struct _hwc_request *); - -typedef struct _hwc_request { - void *block; - u32 word; - hwc_callback_t *callback; - void *data; -} __attribute__ ((packed)) - -hwc_request_t; - -#define HWC_ASCEBC(x) ((MACHINE_IS_VM ? _ascebc[x] : _ascebc_500[x])) - -#define HWC_EBCASC_STR(s,c) ((MACHINE_IS_VM ? EBCASC(s,c) : EBCASC_500(s,c))) - -#define HWC_ASCEBC_STR(s,c) ((MACHINE_IS_VM ? ASCEBC(s,c) : ASCEBC_500(s,c))) - -#define IN_HWCB 1 -#define IN_WRITE_BUF 2 -#define IN_BUFS_TOTAL (IN_HWCB | IN_WRITE_BUF) - -typedef unsigned short int ioctl_htab_t; -typedef unsigned char ioctl_echo_t; -typedef unsigned short int ioctl_cols_t; -typedef signed char ioctl_nl_t; -typedef unsigned short int ioctl_obuf_t; -typedef unsigned char ioctl_case_t; -typedef unsigned char ioctl_delim_t; - -typedef struct { - ioctl_htab_t width_htab; - ioctl_echo_t echo; - ioctl_cols_t columns; - ioctl_nl_t final_nl; - ioctl_obuf_t max_hwcb; - ioctl_obuf_t kmem_hwcb; - ioctl_case_t tolower; - ioctl_delim_t delim; -} hwc_ioctls_t; - -extern hwc_ioctls_t _hwc_ioctls; - -#define HWC_IOCTL_LETTER 'B' - -#define TIOCHWCSHTAB _IOW(HWC_IOCTL_LETTER, 0, _hwc_ioctls.width_htab) - -#define TIOCHWCSECHO _IOW(HWC_IOCTL_LETTER, 1, _hwc_ioctls.echo) - -#define TIOCHWCSCOLS _IOW(HWC_IOCTL_LETTER, 2, _hwc_ioctls.columns) - -#define TIOCHWCSNL _IOW(HWC_IOCTL_LETTER, 4, _hwc_ioctls.final_nl) - -#define TIOCHWCSOBUF _IOW(HWC_IOCTL_LETTER, 5, _hwc_ioctls.max_hwcb) - -#define TIOCHWCSINIT _IO(HWC_IOCTL_LETTER, 6) - -#define TIOCHWCSCASE _IOW(HWC_IOCTL_LETTER, 7, _hwc_ioctls.tolower) - -#define TIOCHWCSDELIM _IOW(HWC_IOCTL_LETTER, 9, _hwc_ioctls.delim) - -#define TIOCHWCGHTAB _IOR(HWC_IOCTL_LETTER, 10, _hwc_ioctls.width_htab) - -#define TIOCHWCGECHO _IOR(HWC_IOCTL_LETTER, 11, _hwc_ioctls.echo) - -#define TIOCHWCGCOLS _IOR(HWC_IOCTL_LETTER, 12, _hwc_ioctls.columns) - -#define TIOCHWCGNL _IOR(HWC_IOCTL_LETTER, 14, _hwc_ioctls.final_nl) - -#define TIOCHWCGOBUF _IOR(HWC_IOCTL_LETTER, 15, _hwc_ioctls.max_hwcb) - -#define TIOCHWCGINIT _IOR(HWC_IOCTL_LETTER, 16, _hwc_ioctls) - -#define TIOCHWCGCASE _IOR(HWC_IOCTL_LETTER, 17, _hwc_ioctls.tolower) - -#define TIOCHWCGDELIM _IOR(HWC_IOCTL_LETTER, 19, _hwc_ioctls.delim) - -#define TIOCHWCGKBUF _IOR(HWC_IOCTL_LETTER, 20, _hwc_ioctls.max_hwcb) - -#define TIOCHWCGCURR _IOR(HWC_IOCTL_LETTER, 21, _hwc_ioctls) - -#ifndef __HWC_RW_C__ - -extern int hwc_init (void); - -extern int hwc_write (int from_user, const unsigned char *, unsigned int); - -extern unsigned int hwc_chars_in_buffer (unsigned char); - -extern unsigned int hwc_write_room (unsigned char); - -extern void hwc_flush_buffer (unsigned char); - -extern void hwc_unblank (void); - -extern signed int hwc_ioctl (unsigned int, unsigned long); - -extern void do_hwc_interrupt (void); - -extern int hwc_printk (const char *,...); - -extern signed int hwc_register_calls (hwc_high_level_calls_t *); - -extern signed int hwc_unregister_calls (hwc_high_level_calls_t *); - -extern int hwc_send (hwc_request_t *); - -#endif - -#endif diff -Nru a/drivers/s390/char/hwc_tty.c b/drivers/s390/char/hwc_tty.c --- a/drivers/s390/char/hwc_tty.c Fri Nov 22 13:41:23 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,276 +0,0 @@ -/* - * drivers/s390/char/hwc_tty.c - * HWC line mode terminal driver. - * - * S390 version - * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation - * Author(s): Martin Peschke - * - * Thanks to Martin Schwidefsky. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "hwc_rw.h" -#include "ctrlchar.h" - -#define HWC_TTY_PRINT_HEADER "hwc tty driver: " - -#define HWC_TTY_BUF_SIZE 512 - -typedef struct { - - struct tty_struct *tty; - - unsigned char buf[HWC_TTY_BUF_SIZE]; - - unsigned short int buf_count; - - spinlock_t lock; - - hwc_high_level_calls_t calls; -} hwc_tty_data_struct; - -static hwc_tty_data_struct hwc_tty_data = -{ /* NULL/0 */ }; -static struct tty_driver hwc_tty_driver; -static struct tty_struct *hwc_tty_table[1]; -static struct termios *hwc_tty_termios[1]; -static struct termios *hwc_tty_termios_locked[1]; -static int hwc_tty_refcount = 0; - -extern struct termios tty_std_termios; - -void hwc_tty_wake_up (void); -void hwc_tty_input (unsigned char *, unsigned int); - -static int -hwc_tty_open (struct tty_struct *tty, - struct file *filp) -{ - - if (minor (tty->device) - tty->driver.minor_start) - return -ENODEV; - - tty->driver_data = &hwc_tty_data; - hwc_tty_data.buf_count = 0; - hwc_tty_data.tty = tty; - tty->low_latency = 0; - - hwc_tty_data.calls.wake_up = hwc_tty_wake_up; - hwc_tty_data.calls.move_input = hwc_tty_input; - hwc_register_calls (&(hwc_tty_data.calls)); - - return 0; -} - -static void -hwc_tty_close (struct tty_struct *tty, - struct file *filp) -{ - if (minor (tty->device) != tty->driver.minor_start) { - printk (KERN_WARNING HWC_TTY_PRINT_HEADER - "do not close hwc tty because of wrong device number"); - return; - } - if (tty->count > 1) - return; - - hwc_tty_data.tty = NULL; - - hwc_unregister_calls (&(hwc_tty_data.calls)); -} - -static int -hwc_tty_write_room (struct tty_struct *tty) -{ - int retval; - - retval = hwc_write_room (IN_BUFS_TOTAL); - return retval; -} - -static int -hwc_tty_write (struct tty_struct *tty, - int from_user, - const unsigned char *buf, - int count) -{ - int retval; - - if (hwc_tty_data.buf_count > 0) { - hwc_write (0, hwc_tty_data.buf, hwc_tty_data.buf_count); - hwc_tty_data.buf_count = 0; - } - retval = hwc_write (from_user, buf, count); - return retval; -} - -static void -hwc_tty_put_char (struct tty_struct *tty, - unsigned char ch) -{ - unsigned long flags; - - spin_lock_irqsave (&hwc_tty_data.lock, flags); - if (hwc_tty_data.buf_count >= HWC_TTY_BUF_SIZE) { - hwc_write (0, hwc_tty_data.buf, hwc_tty_data.buf_count); - hwc_tty_data.buf_count = 0; - } - hwc_tty_data.buf[hwc_tty_data.buf_count] = ch; - hwc_tty_data.buf_count++; - spin_unlock_irqrestore (&hwc_tty_data.lock, flags); -} - -static void -hwc_tty_flush_chars (struct tty_struct *tty) -{ - unsigned long flags; - - spin_lock_irqsave (&hwc_tty_data.lock, flags); - hwc_write (0, hwc_tty_data.buf, hwc_tty_data.buf_count); - hwc_tty_data.buf_count = 0; - spin_unlock_irqrestore (&hwc_tty_data.lock, flags); -} - -static int -hwc_tty_chars_in_buffer (struct tty_struct *tty) -{ - int retval; - - retval = hwc_chars_in_buffer (IN_BUFS_TOTAL); - return retval; -} - -static void -hwc_tty_flush_buffer (struct tty_struct *tty) -{ - hwc_tty_wake_up (); -} - -static int -hwc_tty_ioctl ( - struct tty_struct *tty, - struct file *file, - unsigned int cmd, - unsigned long arg) -{ - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - - return hwc_ioctl (cmd, arg); -} - -void -hwc_tty_wake_up (void) -{ - if (hwc_tty_data.tty == NULL) - return; - if ((hwc_tty_data.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - hwc_tty_data.tty->ldisc.write_wakeup) - (hwc_tty_data.tty->ldisc.write_wakeup) (hwc_tty_data.tty); - wake_up_interruptible (&hwc_tty_data.tty->write_wait); -} - -void -hwc_tty_input (unsigned char *buf, unsigned int count) -{ - struct tty_struct *tty = hwc_tty_data.tty; - - if (tty != NULL) { - unsigned int cchar = ctrlchar_handle(buf, count, tty); - - switch (cchar & CTRLCHAR_MASK) { - case CTRLCHAR_SYSRQ: - return; - - case CTRLCHAR_CTRL: - tty->flip.count++; - *tty->flip.flag_buf_ptr++ = TTY_NORMAL; - *tty->flip.char_buf_ptr++ = cchar; - break; - - case CTRLCHAR_NONE: - memcpy (tty->flip.char_buf_ptr, buf, count); - if (count < 2 || ( - strncmp (buf + count - 2, "^n", 2) || - strncmp (buf + count - 2, "\0252n", 2))) { - tty->flip.char_buf_ptr[count] = '\n'; - count++; - } else - count -= 2; - memset (tty->flip.flag_buf_ptr, TTY_NORMAL, count); - tty->flip.char_buf_ptr += count; - tty->flip.flag_buf_ptr += count; - tty->flip.count += count; - break; - } - tty_flip_buffer_push (tty); - hwc_tty_wake_up (); - } -} - -void -hwc_tty_init (void) -{ - if (!CONSOLE_IS_HWC) - return; - - memset (&hwc_tty_driver, 0, sizeof (struct tty_driver)); - memset (&hwc_tty_data, 0, sizeof (hwc_tty_data_struct)); - hwc_tty_driver.magic = TTY_DRIVER_MAGIC; - hwc_tty_driver.driver_name = "tty_hwc"; - hwc_tty_driver.name = "ttyS"; - hwc_tty_driver.name_base = 0; - hwc_tty_driver.major = TTY_MAJOR; - hwc_tty_driver.minor_start = 64; - hwc_tty_driver.num = 1; - hwc_tty_driver.type = TTY_DRIVER_TYPE_SYSTEM; - hwc_tty_driver.subtype = SYSTEM_TYPE_TTY; - hwc_tty_driver.init_termios = tty_std_termios; - hwc_tty_driver.init_termios.c_iflag = IGNBRK | IGNPAR; - hwc_tty_driver.init_termios.c_oflag = ONLCR; - hwc_tty_driver.init_termios.c_lflag = ISIG | ECHO; - hwc_tty_driver.flags = TTY_DRIVER_REAL_RAW; - hwc_tty_driver.refcount = &hwc_tty_refcount; - - hwc_tty_driver.table = hwc_tty_table; - hwc_tty_driver.termios = hwc_tty_termios; - hwc_tty_driver.termios_locked = hwc_tty_termios_locked; - - hwc_tty_driver.open = hwc_tty_open; - hwc_tty_driver.close = hwc_tty_close; - hwc_tty_driver.write = hwc_tty_write; - hwc_tty_driver.put_char = hwc_tty_put_char; - hwc_tty_driver.flush_chars = hwc_tty_flush_chars; - hwc_tty_driver.write_room = hwc_tty_write_room; - hwc_tty_driver.chars_in_buffer = hwc_tty_chars_in_buffer; - hwc_tty_driver.flush_buffer = hwc_tty_flush_buffer; - hwc_tty_driver.ioctl = hwc_tty_ioctl; - - hwc_tty_driver.throttle = NULL; - hwc_tty_driver.unthrottle = NULL; - hwc_tty_driver.send_xchar = NULL; - hwc_tty_driver.set_termios = NULL; - hwc_tty_driver.set_ldisc = NULL; - hwc_tty_driver.stop = NULL; - hwc_tty_driver.start = NULL; - hwc_tty_driver.hangup = NULL; - hwc_tty_driver.break_ctl = NULL; - hwc_tty_driver.wait_until_sent = NULL; - hwc_tty_driver.read_proc = NULL; - hwc_tty_driver.write_proc = NULL; - - if (tty_register_driver (&hwc_tty_driver)) - panic ("Couldn't register hwc_tty driver\n"); -} diff -Nru a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/s390/char/sclp.c Fri Nov 22 13:41:23 2002 @@ -0,0 +1,663 @@ +/* + * drivers/s390/char/sclp.c + * core function to access sclp interface + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Peschke + * Martin Schwidefsky + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sclp.h" + +#define SCLP_CORE_PRINT_HEADER "sclp low level driver: " + +/* + * decides wether we make use of the macro MACHINE_IS_VM to + * configure the driver for VM at run time (a little bit + * different behaviour); otherwise we use the default + * settings in sclp_data.init_ioctls + */ +#define USE_VM_DETECTION + +/* Structure for register_early_external_interrupt. */ +static ext_int_info_t ext_int_info_hwc; + +/* spinlock to protect global variables of sclp_core */ +static spinlock_t sclp_lock; + +/* Mask of valid sclp events */ +static sccb_mask_t sclp_receive_mask; +static sccb_mask_t sclp_send_mask; + +/* List of registered event types */ +static struct list_head sclp_reg_list; + +/* sccb queue */ +struct list_head sclp_req_queue; + +/* sccb for unconditional read */ +static struct sclp_req sclp_read_req; +static char sclp_read_sccb[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); +/* sccb for write mask sccb */ +static char sclp_init_sccb[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); + +static unsigned long sclp_status = 0; +/* some status flags */ +#define SCLP_INIT 0 +#define SCLP_RUNNING 1 +#define SCLP_READING 2 + +/* + * assembler instruction for Service Call + */ +static int +__service_call(sclp_cmdw_t command, void *sccb) +{ + int cc; + + /* + * Mnemonic: SERVC Rx, Ry [RRE] + * + * Rx: SCLP command word + * Ry: address of SCCB + */ + __asm__ __volatile__( + " .insn rre,0xb2200000,%1,%2\n" /* servc %1,%2 */ + " ipm %0\n" + " srl %0,28" + : "=&d" (cc) + : "d" (command), "a" (__pa(sccb)) + : "cc", "memory" ); + /* + * cc == 0: Service Call succesful initiated + * cc == 2: SCLP busy, new Service Call not initiated, + * new SCCB unchanged + * cc == 3: SCLP function not operational + */ + if (cc == 3) + return -EIO; + /* + * We set the SCLP_RUNNING bit for cc 2 as well because if + * service_call returns cc 2 some old request is running + * that has to complete first + */ + set_bit(SCLP_RUNNING, &sclp_status); + if (cc == 2) + return -EBUSY; + return 0; +} + +static int +__sclp_start_request(void) +{ + struct sclp_req *req; + int rc; + + /* quick exit if sclp is already in use */ + if (test_bit(SCLP_RUNNING, &sclp_status)) + return -EBUSY; + /* quick exit if queue is empty */ + if (list_empty(&sclp_req_queue)) + return -EINVAL; + /* try to start the first request on the request queue. */ + req = list_entry(sclp_req_queue.next, struct sclp_req, list); + rc = __service_call(req->command, req->sccb); + switch (rc) { + case 0: + req->status = SCLP_REQ_RUNNING; + break; + case -EIO: + req->status = SCLP_REQ_FAILED; + if (req->callback != NULL) + req->callback(req, req->callback_data); + break; + } + return rc; +} + +static int +sclp_process_evbufs(struct sccb_header *sccb) +{ + unsigned long flags; + struct evbuf_header *evbuf; + struct list_head *l; + struct sclp_register *t; + + spin_lock_irqsave(&sclp_lock, flags); + evbuf = (struct evbuf_header *) (sccb + 1); + while ((void *) evbuf < (void *) sccb + sccb->length) { + /* check registered event */ + list_for_each(l, &sclp_reg_list) { + t = list_entry(l, struct sclp_register, list); + if (t->receive_mask & (1 << (32 - evbuf->type))) { + if (t->receiver_fn != NULL) + t->receiver_fn(evbuf); + break; + } + } + } + spin_unlock_irqrestore(&sclp_lock, flags); + return -ENOSYS; +} + +/* + * postprocessing of unconditional read service call + */ +static void +sclp_unconditional_read_cb(struct sclp_req *read_req, void *data) +{ + static struct { + u16 code; char *msg; + } errors[] = { + { 0x0040, "SCLP equipment check" }, + { 0x0100, "SCCB boundary violation" }, + { 0x01f0, "invalid command" }, + { 0x0300, "insufficient SCCB length" }, + { 0x40f0, "invalid function code" }, + { 0x60f0, "got interrupt but no data found" }, + { 0x62f0, "got interrupt but no data found" }, + { 0x70f0, "invalid selection mask" } + }; + struct sccb_header *sccb; + char *errmsg; + int i; + + sccb = read_req->sccb; + if (sccb->response_code == 0x0020 || + sccb->response_code == 0x0220) { + /* normal read completion, event buffers stored in sccb */ + if (sclp_process_evbufs(sccb) == 0) { + clear_bit(SCLP_READING, &sclp_status); + return; + } + errmsg = "invalid response code"; + } else { + errmsg = NULL; + for (i = 0; i < sizeof(errors)/sizeof(errors[0]); i++) + if (sccb->response_code == errors[i].code) { + errmsg = errors[i].msg; + break; + } + if (errmsg == NULL) + errmsg = "invalid response code"; + } + printk(KERN_WARNING SCLP_CORE_PRINT_HEADER + "unconditional read: %s (response code =0x%x).\n", + errmsg, sccb->response_code); + clear_bit(SCLP_READING, &sclp_status); +} + +/* + * Function to issue Read Event Data/Unconditional Read + */ +static void +__sclp_unconditional_read(void) +{ + struct sccb_header *sccb; + struct sclp_req *read_req; + + /* + * Don´t try to initiate Unconditional Read if we are not able to + * receive anything + */ + if (sclp_receive_mask == 0) + return; + /* Don't try reading if a read is already outstanding */ + if (test_and_set_bit(SCLP_READING, &sclp_status)) + return; + /* Initialise read sccb */ + sccb = (struct sccb_header *) sclp_read_sccb; + clear_page(sccb); + sccb->length = PAGE_SIZE; + sccb->function_code = 0; /* unconditional read */ + sccb->control_mask[2] = 0x80; /* variable length response */ + /* stick the request structure to the end of the page */ + read_req = &sclp_read_req; + read_req->command = SCLP_CMDW_READDATA; + read_req->status = SCLP_REQ_QUEUED; + read_req->callback = sclp_unconditional_read_cb; + read_req->sccb = sccb; + /* Add read request to the head of queue */ + list_add(&read_req->list, &sclp_req_queue); +} + +/* + * Handler for service-signal external interruptions + */ +static void +sclp_interrupt_handler(struct pt_regs *regs, __u16 code) +{ + u32 ext_int_param, finished_sccb, evbuf_pending; + struct list_head *l; + struct sclp_req *req, *tmp; + int cpu; + + cpu = smp_processor_id(); + ext_int_param = S390_lowcore.ext_params; + finished_sccb = ext_int_param & -8U; + evbuf_pending = ext_int_param & 1; + irq_enter(); + /* + * Only do request callsbacks if sclp is initialised. + * This avoids strange effects for a pending request + * from before the last re-ipl. + */ + if (test_bit(SCLP_INIT, &sclp_status)) { + spin_lock(&sclp_lock); + req = NULL; + if (finished_sccb != 0U) { + list_for_each(l, &sclp_req_queue) { + tmp = list_entry(l, struct sclp_req, list); + if (finished_sccb == (u32)(addr_t) tmp->sccb) { + list_del(&tmp->list); + req = tmp; + break; + } + } + } + spin_unlock(&sclp_lock); + if (req != NULL) { + req->status = SCLP_REQ_DONE; + if (req->callback != NULL) + req->callback(req, req->callback_data); + } + } + spin_lock(&sclp_lock); + /* Head queue a read sccb if an event buffer is pending */ + if (evbuf_pending) + __sclp_unconditional_read(); + /* Now clear the running bit */ + clear_bit(SCLP_RUNNING, &sclp_status); + /* and start next request on the queue */ + __sclp_start_request(); + spin_unlock(&sclp_lock); + irq_exit(); +} + +/* + * Wait synchronously for external interrupt of sclp. We may not receive + * any other external interrupt, so we disable all other external interrupts + * in control register 0. + */ +void +sclp_sync_wait(void) +{ + unsigned long psw_mask; + unsigned long cr0, cr0_sync; + + /* + * save cr0 + * enable service signal external interruption (cr0.22) + * disable cr0.20-21, cr0.25, cr0.27, cr0.30-31 + * don't touch any other bit in cr0 + */ + __ctl_store(cr0, 0, 0); + cr0_sync = cr0; + cr0_sync |= 0x00000200; + cr0_sync &= 0xFFFFF3AC; + __ctl_load(cr0_sync, 0, 0); + + /* enable external interruptions (PSW-mask.7) */ + asm volatile ("STOSM 0(%1),0x01" + : "=m" (psw_mask) : "a" (&psw_mask) : "memory"); + + /* wait until ISR signals receipt of interrupt */ + while (test_bit(SCLP_RUNNING, &sclp_status)) + barrier(); + + /* disable external interruptions */ + asm volatile ("SSM 0(%0)" + : : "a" (&psw_mask) : "memory"); + + /* restore cr0 */ + __ctl_load(cr0, 0, 0); +} + +/* + * Queue a request to the tail of the ccw_queue. Start the I/O if + * possible. + */ +void +sclp_add_request(struct sclp_req *req) +{ + unsigned long flags; + + if (!test_bit(SCLP_INIT, &sclp_status)) + return; + spin_lock_irqsave(&sclp_lock, flags); + /* queue the request */ + req->status = SCLP_REQ_QUEUED; + list_add_tail(&req->list, &sclp_req_queue); + /* try to start the first request on the queue */ + __sclp_start_request(); + spin_unlock_irqrestore(&sclp_lock, flags); +} + +/* state change notification */ +struct sclp_statechangebuf { + struct evbuf_header header; + u8 validity_sclp_active_facility_mask : 1; + u8 validity_sclp_receive_mask : 1; + u8 validity_sclp_send_mask : 1; + u8 validity_read_data_function_mask : 1; + u16 _zeros : 12; + u16 mask_length; + u64 sclp_active_facility_mask; + sccb_mask_t sclp_receive_mask; + sccb_mask_t sclp_send_mask; + u32 read_data_function_mask; +} __attribute__((packed)); + +static inline void +__sclp_notify_state_change(void) +{ + struct list_head *l; + struct sclp_register *t; + sccb_mask_t receive_mask, send_mask; + + list_for_each(l, &sclp_reg_list) { + t = list_entry(l, struct sclp_register, list); + receive_mask = t->receive_mask & sclp_receive_mask; + send_mask = t->send_mask & sclp_send_mask; + if (t->sclp_receive_mask != receive_mask || + t->sclp_send_mask != send_mask) { + t->sclp_receive_mask = receive_mask; + t->sclp_send_mask = send_mask; + if (t->state_change_fn != NULL) + t->state_change_fn(t); + } + } +} + +static void +sclp_state_change(struct evbuf_header *evbuf) +{ + unsigned long flags; + struct sclp_statechangebuf *scbuf; + + spin_lock_irqsave(&sclp_lock, flags); + scbuf = (struct sclp_statechangebuf *) evbuf; + + if (scbuf->validity_sclp_receive_mask) { + if (scbuf->mask_length != 4) + printk(KERN_WARNING SCLP_CORE_PRINT_HEADER + "state change event with mask length %i\n", + scbuf->mask_length); + else + /* set new send mask */ + sclp_receive_mask = scbuf->sclp_receive_mask; + } + + if (scbuf->validity_sclp_send_mask) { + if (scbuf->mask_length != 4) + printk(KERN_WARNING SCLP_CORE_PRINT_HEADER + "state change event with mask length %i\n", + scbuf->mask_length); + else + /* set new send mask */ + sclp_send_mask = scbuf->sclp_send_mask; + } + + __sclp_notify_state_change(); + spin_unlock_irqrestore(&sclp_lock, flags); +} + +struct sclp_register sclp_state_change_event = { + .receive_mask = EvTyp_StateChange_Mask, + .receiver_fn = sclp_state_change +}; + + +/* + * SCLP quiesce event handler + */ +#ifdef CONFIG_SMP +static volatile unsigned long cpu_quiesce_map; + +static void +do_load_quiesce_psw(void * __unused) +{ + psw_t quiesce_psw; + + clear_bit(smp_processor_id(), &cpu_quiesce_map); + if (smp_processor_id() == 0) { + /* Wait for all other cpus to enter do_load_quiesce_psw */ + while (cpu_quiesce_map != 0); + /* Quiesce the last cpu with the special psw */ + quiesce_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT; + quiesce_psw.addr = 0xfff; + __load_psw(quiesce_psw); + } + signal_processor(smp_processor_id(), sigp_stop); +} + +static void +do_machine_quiesce(void) +{ + cpu_quiesce_map = cpu_online_map; + smp_call_function(do_load_quiesce_psw, NULL, 0, 0); + do_load_quiesce_psw(NULL); +} +#else +static void +do_machine_quiesce(void) +{ + psw_t quiesce_psw; + + quiesce_psw.mask = _DW_PSW_MASK; + queisce_psw.addr = 0xfff; + __load_psw(quiesce_psw); +} +#endif + +extern void ctrl_alt_del(void); + +static void +sclp_quiesce(struct evbuf_header *evbuf) +{ + /* + * We got a "shutdown" request. + * Add a call to an appropriate "shutdown" routine here. This + * routine should set all PSWs to 'disabled-wait', 'stopped' + * or 'check-stopped' - except 1 PSW which needs to carry a + * special bit pattern called 'quiesce PSW'. + */ + _machine_restart = (void *) do_machine_quiesce; + _machine_halt = do_machine_quiesce; + _machine_power_off = do_machine_quiesce; + ctrl_alt_del(); +} + +struct sclp_register sclp_quiesce_event = { + .receive_mask = EvTyp_SigQuiesce_Mask, + .receiver_fn = sclp_quiesce +}; + +/* initialisation of SCLP */ +struct init_sccb { + struct sccb_header header; + u16 _reserved; + u16 mask_length; + sccb_mask_t receive_mask; + sccb_mask_t send_mask; + sccb_mask_t sclp_send_mask; + sccb_mask_t sclp_receive_mask; +} __attribute__((packed)); + +static int +sclp_init_mask(void) +{ + unsigned long flags; + struct init_sccb *sccb; + struct sclp_req *req; + struct list_head *l; + struct sclp_register *t; + int rc; + + sccb = (struct init_sccb *) sclp_init_sccb; + /* stick the request structure to the end of the init sccb page */ + req = (struct sclp_req *) ((addr_t) sccb + PAGE_SIZE) - 1; + + /* SCLP setup concerning receiving and sending Event Buffers */ + req->command = SCLP_CMDW_WRITEMASK; + req->status = SCLP_REQ_QUEUED; + req->callback = NULL; + req->sccb = sccb; + /* setup sccb for writemask command */ + memset(sccb, 0, sizeof(struct init_sccb)); + sccb->header.length = sizeof(struct init_sccb); + sccb->mask_length = sizeof(sccb_mask_t); + /* copy in the sccb mask of the registered event types */ + spin_lock_irqsave(&sclp_lock, flags); + list_for_each(l, &sclp_reg_list) { + t = list_entry(l, struct sclp_register, list); + sccb->receive_mask |= t->receive_mask; + sccb->send_mask |= t->send_mask; + } + sccb->sclp_receive_mask = 0; + sccb->sclp_send_mask = 0; + if (test_bit(SCLP_INIT, &sclp_status)) { + /* add request to sclp queue */ + list_add_tail(&req->list, &sclp_req_queue); + /* and start if SCLP is idle */ + if (!test_bit(SCLP_RUNNING, &sclp_status)) + __sclp_start_request(); + spin_unlock_irqrestore(&sclp_lock, flags); + /* now wait for completion */ + while (req->status != SCLP_REQ_DONE && + req->status != SCLP_REQ_FAILED) + sclp_sync_wait(); + spin_lock_irqsave(&sclp_lock, flags); + } else { + /* + * Special case for the very first write mask command. + * The interrupt handler is not removing request from + * the request queue and doesn't call callbacks yet + * because there might be an pending old interrupt + * after a Re-IPL. We have to receive and ignore it. + */ + do { + rc = __service_call(req->command, req->sccb); + spin_unlock_irqrestore(&sclp_lock, flags); + if (rc == -EIO) + return -ENOSYS; + sclp_sync_wait(); + spin_lock_irqsave(&sclp_lock, flags); + } while (rc == -EBUSY); + } + sclp_receive_mask = sccb->sclp_receive_mask; + sclp_send_mask = sccb->sclp_send_mask; + __sclp_notify_state_change(); + spin_unlock_irqrestore(&sclp_lock, flags); + return 0; +} + +/* + * sclp setup function. Called early (no kmalloc!) from sclp_console_init(). + */ +static int +sclp_init(void) +{ + int rc; + + if (test_bit(SCLP_INIT, &sclp_status)) + /* Already initialised. */ + return 0; + + /* + * request the 0x2401 external interrupt + * The sclp driver is initialized early (before kmalloc works). We + * need to use register_early_external_interrupt. + */ + if (register_early_external_interrupt(0x2401, sclp_interrupt_handler, + &ext_int_info_hwc) != 0) + return -EBUSY; + + spin_lock_init(&sclp_lock); + INIT_LIST_HEAD(&sclp_req_queue); + + /* init event list */ + INIT_LIST_HEAD(&sclp_reg_list); + list_add(&sclp_state_change_event.list, &sclp_reg_list); + list_add(&sclp_quiesce_event.list, &sclp_reg_list); + + /* enable service-signal external interruptions, + * Control Register 0 bit 22 := 1 + * (besides PSW bit 7 must be set to 1 sometimes for external + * interruptions) + */ + ctl_set_bit(0, 9); + + /* do the initial write event mask */ + rc = sclp_init_mask(); + if (rc == 0) { + /* Ok, now everything is setup right. */ + set_bit(SCLP_INIT, &sclp_status); + return 0; + } + + /* The sclp_init_mask failed. SCLP is broken, unregister and exit. */ + ctl_clear_bit(0,9); + unregister_early_external_interrupt(0x2401, sclp_interrupt_handler, + &ext_int_info_hwc); + + return rc; +} + +int +sclp_register(struct sclp_register *reg) +{ + unsigned long flags; + struct list_head *l; + struct sclp_register *t; + + if (!MACHINE_HAS_SCLP) + return -ENODEV; + + if (!test_bit(SCLP_INIT, &sclp_status)) + sclp_init(); + spin_lock_irqsave(&sclp_lock, flags); + /* check already registered event masks for collisions */ + list_for_each(l, &sclp_reg_list) { + t = list_entry(l, struct sclp_register, list); + if (t->receive_mask & reg->receive_mask || + t->send_mask & reg->send_mask) { + spin_unlock_irqrestore(&sclp_lock, flags); + return -EBUSY; + } + } + /* + * set present mask to 0 to trigger state change + * callback in sclp_init_mask + */ + reg->sclp_receive_mask = 0; + reg->sclp_send_mask = 0; + list_add(®->list, &sclp_reg_list); + spin_unlock_irqrestore(&sclp_lock, flags); + sclp_init_mask(); + return 0; +} + +void +sclp_unregister(struct sclp_register *reg) +{ + unsigned long flags; + + spin_lock_irqsave(&sclp_lock, flags); + list_del(®->list); + spin_unlock_irqrestore(&sclp_lock, flags); + sclp_init_mask(); +} + diff -Nru a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/s390/char/sclp.h Fri Nov 22 13:41:23 2002 @@ -0,0 +1,157 @@ +/* + * drivers/s390/char/sclp.h + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Peschke + * Martin Schwidefsky + */ + +#ifndef __SCLP_H__ +#define __SCLP_H__ + +#include +#include + +#include + +/* maximum number of pages concerning our own memory management */ +#define MAX_KMEM_PAGES (sizeof(unsigned long) << 3) +#define MAX_CONSOLE_PAGES 4 + +#define EvTyp_OpCmd 0x01 +#define EvTyp_Msg 0x02 +#define EvTyp_StateChange 0x08 +#define EvTyp_PMsgCmd 0x09 +#define EvTyp_CntlProgOpCmd 0x20 +#define EvTyp_CntlProgIdent 0x0B +#define EvTyp_SigQuiesce 0x1D + +#define EvTyp_OpCmd_Mask 0x80000000 +#define EvTyp_Msg_Mask 0x40000000 +#define EvTyp_StateChange_Mask 0x01000000 +#define EvTyp_PMsgCmd_Mask 0x00800000 +#define EvTyp_CtlProgOpCmd_Mask 0x00000001 +#define EvTyp_CtlProgIdent_Mask 0x00200000 +#define EvTyp_SigQuiesce_Mask 0x00000008 + +#define GnrlMsgFlgs_DOM 0x8000 +#define GnrlMsgFlgs_SndAlrm 0x4000 +#define GnrlMsgFlgs_HoldMsg 0x2000 + +#define LnTpFlgs_CntlText 0x8000 +#define LnTpFlgs_LabelText 0x4000 +#define LnTpFlgs_DataText 0x2000 +#define LnTpFlgs_EndText 0x1000 +#define LnTpFlgs_PromptText 0x0800 + +#define SCLP_COMMAND_INITIATED 0 +#define SCLP_BUSY 2 +#define SCLP_NOT_OPERATIONAL 3 + +typedef unsigned int sclp_cmdw_t; + +#define SCLP_CMDW_READDATA 0x00770005 +#define SCLP_CMDW_WRITEDATA 0x00760005 +#define SCLP_CMDW_WRITEMASK 0x00780005 + +#define GDS_ID_MDSMU 0x1310 +#define GDS_ID_MDSRouteInfo 0x1311 +#define GDS_ID_AgUnWrkCorr 0x1549 +#define GDS_ID_SNACondReport 0x1532 +#define GDS_ID_CPMSU 0x1212 +#define GDS_ID_RoutTargInstr 0x154D +#define GDS_ID_OpReq 0x8070 +#define GDS_ID_TextCmd 0x1320 + +#define GDS_KEY_SelfDefTextMsg 0x31 + +typedef u32 sccb_mask_t; /* ATTENTION: assumes 32bit mask !!! */ + +struct sccb_header { + u16 length; + u8 function_code; + u8 control_mask[3]; + u16 response_code; +} __attribute__((packed)); + +struct gds_subvector { + u8 length; + u8 key; +} __attribute__((packed)); + +struct gds_vector { + u16 length; + u16 gds_id; +} __attribute__((packed)); + +struct evbuf_header { + u16 length; + u8 type; + u8 flags; + u16 _reserved; +} __attribute__((packed)); + +struct sclp_req { + struct list_head list; /* list_head for request queueing. */ + sclp_cmdw_t command; /* sclp command to execute */ + void *sccb; /* pointer to the sccb to execute */ + char status; /* status of this request */ + /* Callback that is called after reaching final status. */ + void (*callback)(struct sclp_req *, void *data); + void *callback_data; +}; + +#define SCLP_REQ_FILLED 0x00 /* request is ready to be processed */ +#define SCLP_REQ_QUEUED 0x01 /* request is queued to be processed */ +#define SCLP_REQ_RUNNING 0x02 /* request is currently running */ +#define SCLP_REQ_DONE 0x03 /* request is completed successfully */ +#define SCLP_REQ_FAILED 0x05 /* request is finally failed */ + +/* function pointers that a high level driver has to use for registration */ +/* of some routines it wants to be called from the low level driver */ +struct sclp_register { + struct list_head list; + /* event masks this user is registered for */ + sccb_mask_t receive_mask; + sccb_mask_t send_mask; + /* actually present events */ + sccb_mask_t sclp_receive_mask; + sccb_mask_t sclp_send_mask; + /* called if event type availability changes */ + void (*state_change_fn)(struct sclp_register *); + /* called for events in cp_receive_mask/sclp_receive_mask */ + void (*receiver_fn)(struct evbuf_header *); +}; + +/* externals from sclp.c */ +void sclp_add_request(struct sclp_req *req); +void sclp_sync_wait(void); +int sclp_register(struct sclp_register *reg); +void sclp_unregister(struct sclp_register *reg); + +/* useful inlines */ + +/* VM uses EBCDIC 037, LPAR+native(SE+HMC) use EBCDIC 500 */ +/* translate single character from ASCII to EBCDIC */ +static inline unsigned char +sclp_ascebc(unsigned char ch) +{ + return (MACHINE_IS_VM) ? _ascebc[ch] : _ascebc_500[ch]; +} + +/* translate string from EBCDIC to ASCII */ +static inline void +sclp_ebcasc_str(unsigned char *str, int nr) +{ + (MACHINE_IS_VM) ? EBCASC(str, nr) : EBCASC_500(str, nr); +} + +/* translate string from ASCII to EBCDIC */ +static inline void +sclp_ascebc_str(unsigned char *str, int nr) +{ + (MACHINE_IS_VM) ? ASCEBC(str, nr) : ASCEBC_500(str, nr); +} + +#endif /* __SCLP_H__ */ diff -Nru a/drivers/s390/char/sclp_con.c b/drivers/s390/char/sclp_con.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/s390/char/sclp_con.c Fri Nov 22 13:41:23 2002 @@ -0,0 +1,237 @@ +/* + * drivers/s390/char/sclp_con.c + * SCLP line mode console driver + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Peschke + * Martin Schwidefsky + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sclp.h" +#include "sclp_rw.h" + +#define SCLP_CON_PRINT_HEADER "sclp console driver: " + +#define sclp_console_major 4 /* TTYAUX_MAJOR */ +#define sclp_console_minor 64 +#define sclp_console_name "console" + +/* Lock to guard over changes to global variables */ +static spinlock_t sclp_con_lock; +/* List of free pages that can be used for console output buffering */ +static struct list_head sclp_con_pages; +/* List of full struct sclp_buffer structures ready for output */ +static struct list_head sclp_con_outqueue; +/* Counter how many buffers are emitted (max 1) and how many */ +/* are on the output queue. */ +static int sclp_con_buffer_count; +/* Pointer to current console buffer */ +static struct sclp_buffer *sclp_conbuf; +/* Timer for delayed output of console messages */ +static struct timer_list sclp_con_timer; + +/* Output format for console messages */ +static unsigned short sclp_con_columns; +static unsigned short sclp_con_width_htab; + +static void +sclp_conbuf_callback(struct sclp_buffer *buffer, int rc) +{ + unsigned long flags; + struct sclp_buffer *next; + void *page; + + /* FIXME: what if rc != 0x0020 */ + page = sclp_unmake_buffer(buffer); + spin_lock_irqsave(&sclp_con_lock, flags); + list_add_tail((struct list_head *) page, &sclp_con_pages); + sclp_con_buffer_count--; + /* Remove buffer from outqueue */ + list_del(&buffer->list); + /* Check if there is a pending buffer on the out queue. */ + next = NULL; + if (!list_empty(&sclp_con_outqueue)) + next = list_entry(sclp_con_outqueue.next, + struct sclp_buffer, list); + spin_unlock_irqrestore(&sclp_con_lock, flags); + if (next != NULL) + sclp_emit_buffer(next, sclp_conbuf_callback); +} + +static inline void +__sclp_conbuf_emit(struct sclp_buffer *buffer) +{ + list_add_tail(&buffer->list, &sclp_con_outqueue); + if (sclp_con_buffer_count++ == 0) + sclp_emit_buffer(buffer, sclp_conbuf_callback); +} + +/* + * When this routine is called from the timer then we flush the + * temporary write buffer without further waiting on a final new line. + */ +static void +sclp_console_timeout(unsigned long data) +{ + unsigned long flags; + + spin_lock_irqsave(&sclp_con_lock, flags); + if (sclp_conbuf != NULL) { + __sclp_conbuf_emit(sclp_conbuf); + sclp_conbuf = NULL; + } + spin_unlock_irqrestore(&sclp_con_lock, flags); +} + +/* + * Writes the given message to S390 system console + */ +void +sclp_console_write(struct console *console, const char *message, + unsigned int count) +{ + unsigned long flags; + void *page; + int written; + + if (count <= 0) + return; + spin_lock_irqsave(&sclp_con_lock, flags); + /* + * process escape characters, write message into buffer, + * send buffer to SCLP + */ + do { + /* make sure we have a console output buffer */ + if (sclp_conbuf == NULL) { + while (list_empty(&sclp_con_pages)) { + spin_unlock_irqrestore(&sclp_con_lock, flags); + sclp_sync_wait(); + spin_lock_irqsave(&sclp_con_lock, flags); + } + page = sclp_con_pages.next; + list_del((struct list_head *) page); + sclp_conbuf = sclp_make_buffer(page, sclp_con_columns, + sclp_con_width_htab); + } + /* try to write the string to the current output buffer */ + written = sclp_write(sclp_conbuf, message, count, 0); + if (written == -EFAULT || written == count) + break; + /* + * Not all characters could be written to the current + * output buffer. Emit the buffer, create a new buffer + * and then output the rest of the string. + */ + __sclp_conbuf_emit(sclp_conbuf); + sclp_conbuf = NULL; + message += written; + count -= written; + } while (count > 0); + /* Setup timer to output current console buffer after 1/10 second */ + if (sclp_conbuf != NULL && !timer_pending(&sclp_con_timer)) { + init_timer(&sclp_con_timer); + sclp_con_timer.function = sclp_console_timeout; + sclp_con_timer.data = 0UL; + sclp_con_timer.expires = jiffies + HZ/10; + add_timer(&sclp_con_timer); + } + spin_unlock_irqrestore(&sclp_con_lock, flags); +} + +/* returns the device number of the SCLP console */ +kdev_t +sclp_console_device(struct console *c) +{ + return mk_kdev(sclp_console_major, sclp_console_minor); +} + +/* + * This routine is called from panic when the kernel + * is going to give up. We have to make sure that all buffers + * will be flushed to the SCLP. + */ +void +sclp_console_unblank(void) +{ + unsigned long flags; + + spin_lock_irqsave(&sclp_con_lock, flags); + if (timer_pending(&sclp_con_timer)) + del_timer(&sclp_con_timer); + if (sclp_conbuf != NULL) { + __sclp_conbuf_emit(sclp_conbuf); + sclp_conbuf = NULL; + } + while (sclp_con_buffer_count > 0) { + spin_unlock_irqrestore(&sclp_con_lock, flags); + sclp_sync_wait(); + spin_lock_irqsave(&sclp_con_lock, flags); + } + spin_unlock_irqrestore(&sclp_con_lock, flags); +} + +/* + * used to register the SCLP console to the kernel and to + * give printk necessary information + */ +struct console sclp_console = +{ + .name = sclp_console_name, + .write = sclp_console_write, + .device = sclp_console_device, + .unblank = sclp_console_unblank, + .flags = CON_PRINTBUFFER +}; + +/* + * called by console_init() in drivers/char/tty_io.c at boot-time. + */ +void __init +sclp_console_init(void) +{ + void *page; + int i; + + if (!CONSOLE_IS_SCLP) + return; + if (sclp_rw_init() != 0) + return; + /* Allocate pages for output buffering */ + INIT_LIST_HEAD(&sclp_con_pages); + for (i = 0; i < MAX_CONSOLE_PAGES; i++) { + page = alloc_bootmem_low_pages(PAGE_SIZE); + if (page == NULL) + return; + list_add_tail((struct list_head *) page, &sclp_con_pages); + } + INIT_LIST_HEAD(&sclp_con_outqueue); + spin_lock_init(&sclp_con_lock); + sclp_con_buffer_count = 0; + sclp_conbuf = NULL; + init_timer(&sclp_con_timer); + + /* Set output format */ + if (MACHINE_IS_VM) + /* + * save 4 characters for the CPU number + * written at start of each line by VM/CP + */ + sclp_con_columns = 76; + else + sclp_con_columns = 80; + sclp_con_width_htab = 8; + + /* enable printk´s access to this driver */ + register_console(&sclp_console); +} diff -Nru a/drivers/s390/char/sclp_cpi.c b/drivers/s390/char/sclp_cpi.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/s390/char/sclp_cpi.c Fri Nov 22 13:41:23 2002 @@ -0,0 +1,243 @@ +/* + * Author: Martin Peschke + * Copyright (C) 2001 IBM Entwicklung GmbH, IBM Corporation + * + * SCLP Control-Program Identification. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sclp.h" +#include "sclp_rw.h" + +#define CPI_LENGTH_SYSTEM_TYPE 8 +#define CPI_LENGTH_SYSTEM_NAME 8 +#define CPI_LENGTH_SYSPLEX_NAME 8 + +struct cpi_evbuf { + struct evbuf_header header; + u8 id_format; + u8 reserved0; + u8 system_type[CPI_LENGTH_SYSTEM_TYPE]; + u64 reserved1; + u8 system_name[CPI_LENGTH_SYSTEM_NAME]; + u64 reserved2; + u64 system_level; + u64 reserved3; + u8 sysplex_name[CPI_LENGTH_SYSPLEX_NAME]; + u8 reserved4[16]; +} __attribute__((packed)); + +struct cpi_sccb { + struct sccb_header header; + struct cpi_evbuf cpi_evbuf; +} __attribute__((packed)); + +/* Event type structure for write message and write priority message */ +static struct sclp_register sclp_cpi_event = +{ + .send_mask = EvTyp_CtlProgIdent_Mask +}; + +MODULE_AUTHOR( + "Martin Peschke, IBM Deutschland Entwicklung GmbH " + ""); + +MODULE_DESCRIPTION( + "identify this operating system instance to the S/390 " + "or zSeries hardware"); + +static char *system_name = NULL; +MODULE_PARM(system_name, "s"); +MODULE_PARM_DESC(system_name, "e.g. hostname - max. 8 characters"); + +static char *sysplex_name = NULL; +#ifdef ALLOW_SYSPLEX_NAME +MODULE_PARM(sysplex_name, "s"); +MODULE_PARM_DESC(sysplex_name, "if applicable - max. 8 characters"); +#endif + +/* use default value for this field (as well as for system level) */ +static char *system_type = "LINUX"; + +static int +cpi_check_parms(void) +{ + /* reject if no system type specified */ + if (!system_type) { + printk("cpi: bug: no system type specified\n"); + return -EINVAL; + } + + /* reject if system type larger than 8 characters */ + if (strlen(system_type) > CPI_LENGTH_SYSTEM_NAME) { + printk("cpi: bug: system type has length of %li characters - " + "only %i characters supported\n", + strlen(system_type), CPI_LENGTH_SYSTEM_TYPE); + return -EINVAL; + } + + /* reject if no system name specified */ + if (!system_name) { + printk("cpi: no system name specified\n"); + return -EINVAL; + } + + /* reject if system name larger than 8 characters */ + if (strlen(system_name) > CPI_LENGTH_SYSTEM_NAME) { + printk("cpi: system name has length of %li characters - " + "only %i characters supported\n", + strlen(system_name), CPI_LENGTH_SYSTEM_NAME); + return -EINVAL; + } + + /* reject if specified sysplex name larger than 8 characters */ + if (sysplex_name && strlen(sysplex_name) > CPI_LENGTH_SYSPLEX_NAME) { + printk("cpi: sysplex name has length of %li characters" + " - only %i characters supported\n", + strlen(sysplex_name), CPI_LENGTH_SYSPLEX_NAME); + return -EINVAL; + } + return 0; +} + +static void +cpi_callback(struct sclp_req *req, void *data) +{ + struct semaphore *sem; + + sem = (struct semaphore *) data; + up(sem); +} + +static struct sclp_req * +cpi_prepare_req(void) +{ + struct sclp_req *req; + struct cpi_sccb *sccb; + struct cpi_evbuf *evb; + + req = (struct sclp_req *) kmalloc(sizeof(struct sclp_req), GFP_KERNEL); + if (req == NULL) + return ERR_PTR(-ENOMEM); + sccb = (struct cpi_sccb *) get_free_page(GFP_KERNEL); + if (sccb == NULL) { + kfree(req); + return ERR_PTR(-ENOMEM); + } + memset(sccb, 0, sizeof(struct cpi_sccb)); + + /* setup SCCB for Control-Program Identification */ + sccb->header.length = sizeof(struct cpi_sccb); + sccb->cpi_evbuf.header.length = sizeof(struct cpi_evbuf); + sccb->cpi_evbuf.header.type = 0x0B; + evb = &sccb->cpi_evbuf; + + /* set system type */ + memset(evb->system_type, ' ', CPI_LENGTH_SYSTEM_TYPE); + memcpy(evb->system_type, system_type, strlen(system_type)); + sclp_ascebc_str(evb->system_type, CPI_LENGTH_SYSTEM_TYPE); + EBC_TOUPPER(evb->system_type, CPI_LENGTH_SYSTEM_TYPE); + + /* set system name */ + memset(evb->system_name, ' ', CPI_LENGTH_SYSTEM_NAME); + memcpy(evb->system_name, system_name, strlen(system_name)); + sclp_ascebc_str(evb->system_name, CPI_LENGTH_SYSTEM_NAME); + EBC_TOUPPER(evb->system_name, CPI_LENGTH_SYSTEM_NAME); + + /* set sytem level */ + evb->system_level = LINUX_VERSION_CODE; + + /* set sysplex name */ + if (sysplex_name) { + memset(evb->sysplex_name, ' ', CPI_LENGTH_SYSPLEX_NAME); + memcpy(evb->sysplex_name, sysplex_name, strlen(sysplex_name)); + sclp_ascebc_str(evb->sysplex_name, CPI_LENGTH_SYSPLEX_NAME); + EBC_TOUPPER(evb->sysplex_name, CPI_LENGTH_SYSPLEX_NAME); + } + + /* prepare request data structure presented to SCLP driver */ + req->command = SCLP_CMDW_WRITEDATA; + req->sccb = sccb; + req->status = SCLP_REQ_FILLED; + req->callback = cpi_callback; + return req; +} + +static void +cpi_free_req(struct sclp_req *req) +{ + free_page((unsigned long) req->sccb); + kfree(req); +} + +static int __init +cpi_module_init(void) +{ + struct semaphore sem; + struct sclp_req *req; + int rc; + + rc = cpi_check_parms(); + if (rc) + return rc; + + rc = sclp_register(&sclp_cpi_event); + if (rc) { + /* could not register sclp event. Die. */ + printk("cpi: could not register to hardware console.\n"); + return -EINVAL; + } + if (!(sclp_cpi_event.sclp_send_mask & EvTyp_CtlProgIdent_Mask)) { + printk("cpi: no control program identification support\n"); + sclp_unregister(&sclp_cpi_event); + return -ENOTSUPP; + } + + req = cpi_prepare_req(); + if (IS_ERR(req)) { + printk("cpi: couldn't allocate request\n"); + sclp_unregister(&sclp_cpi_event); + return PTR_ERR(req); + } + + /* Prepare semaphore */ + sema_init(&sem, 0); + req->callback_data = &sem; + /* Add request to sclp queue */ + sclp_add_request(req); + /* make "insmod" sleep until callback arrives */ + down(&sem); + + rc = ((struct cpi_sccb *) req->sccb)->header.response_code; + if (rc != 0x0020) { + printk("cpi: failed with response code 0x%x\n", rc); + rc = -ECOMM; + } else + rc = 0; + + cpi_free_req(req); + + return rc; +} + + +static void __exit cpi_module_exit(void) +{ +} + + +/* declare driver module init/cleanup functions */ +module_init(cpi_module_init); +module_exit(cpi_module_exit); + diff -Nru a/drivers/s390/char/sclp_rw.c b/drivers/s390/char/sclp_rw.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/s390/char/sclp_rw.c Fri Nov 22 13:41:23 2002 @@ -0,0 +1,458 @@ +/* + * drivers/s390/char/sclp_rw.c + * driver: reading from and writing to system console on S/390 via SCLP + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Peschke + * Martin Schwidefsky + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sclp.h" +#include "sclp_rw.h" + +#define SCLP_RW_PRINT_HEADER "sclp low level driver: " + +/* + * The room for the SCCB (only for writing) is not equal to a pages size + * (as it is specified as the maximum size in the the SCLP ducumentation) + * because of the additional data structure described above. + */ +#define MAX_SCCB_ROOM (PAGE_SIZE - sizeof(struct sclp_buffer)) + +/* Event type structure for write message and write priority message */ +struct sclp_register sclp_rw_event = { + .send_mask = EvTyp_Msg_Mask | EvTyp_PMsgCmd_Mask +}; + +/* + * Setup a sclp write buffer. Gets a page as input (4K) and returns + * a pointer to a struct sclp_buffer structure that is located at the + * end of the input page. This reduces the buffer space by a few + * bytes but simplifies things. + */ +struct sclp_buffer * +sclp_make_buffer(void *page, unsigned short columns, unsigned short htab) +{ + struct sclp_buffer *buffer; + struct write_sccb *sccb; + + sccb = (struct write_sccb *) page; + /* + * We keep the struct sclp_buffer structure at the end + * of the sccb page. + */ + buffer = ((struct sclp_buffer *) ((addr_t) sccb + PAGE_SIZE)) - 1; + buffer->sccb = sccb; + buffer->mto_number = 0; + buffer->mto_char_sum = 0; + buffer->current_line = NULL; + buffer->current_length = 0; + buffer->columns = columns; + buffer->htab = htab; + + /* initialize sccb */ + memset(sccb, 0, sizeof(struct write_sccb)); + sccb->header.length = sizeof(struct write_sccb); + sccb->msg_buf.header.length = sizeof(struct msg_buf); + sccb->msg_buf.header.type = EvTyp_Msg; + sccb->msg_buf.mdb.header.length = sizeof(struct mdb); + sccb->msg_buf.mdb.header.type = 1; + sccb->msg_buf.mdb.header.tag = 0xD4C4C240; /* ebcdic "MDB " */ + sccb->msg_buf.mdb.header.revision_code = 1; + sccb->msg_buf.mdb.go.length = sizeof(struct go); + sccb->msg_buf.mdb.go.type = 1; + + return buffer; +} + +/* + * Return a pointer to the orignal page that has been used to create + * the buffer. + */ +void * +sclp_unmake_buffer(struct sclp_buffer *buffer) +{ + return buffer->sccb; +} + +/* + * Creates a new Message Text Object with enough room for str_len + * characters. This function will create a new sccb for buffering + * the mto if the current buffer sccb is full. A full buffer sccb + * is submitted for output. + * Returns a pointer to the start of the string in the mto. + */ +static int +sclp_create_mto(struct sclp_buffer *buffer, int max_len) +{ + struct write_sccb *sccb; + struct mto *mto; + int mto_size; + + /* max size of new Message Text Object including message text */ + mto_size = sizeof(struct mto) + max_len; + + /* check if current buffer sccb can contain the mto */ + sccb = buffer->sccb; + if ((MAX_SCCB_ROOM - sccb->header.length) < mto_size) + return -ENOMEM; + + /* find address of new message text object */ + mto = (struct mto *)(((unsigned long) sccb) + sccb->header.length); + + /* + * fill the new Message-Text Object, + * starting behind the former last byte of the SCCB + */ + memset(mto, 0, sizeof(struct mto)); + mto->length = sizeof(struct mto); + mto->type = 4; /* message text object */ + mto->line_type_flags = LnTpFlgs_EndText; /* end text */ + + /* set pointer to first byte after struct mto. */ + buffer->current_line = (char *) (mto + 1); + buffer->current_length = 0; + + return 0; +} + +/* + * Add the mto created with sclp_create_mto to the buffer sccb using + * the str_len parameter as the real length of the string. + */ +static void +sclp_add_mto(struct sclp_buffer *buffer) +{ + struct write_sccb *sccb; + struct mto *mto; + int str_len, mto_size; + + str_len = buffer->current_length; + buffer->current_line = NULL; + buffer->current_length = 0; + + /* real size of new Message Text Object including message text */ + mto_size = sizeof(struct mto) + str_len; + + /* find address of new message text object */ + sccb = buffer->sccb; + mto = (struct mto *)(((unsigned long) sccb) + sccb->header.length); + + /* set size of message text object */ + mto->length = mto_size; + + /* + * update values of sizes + * (SCCB, Event(Message) Buffer, Message Data Block) + */ + sccb->header.length += mto_size; + sccb->msg_buf.header.length += mto_size; + sccb->msg_buf.mdb.header.length += mto_size; + + /* + * count number of buffered messages (= number of Message Text + * Objects) and number of buffered characters + * for the SCCB currently used for buffering and at all + */ + buffer->mto_number++; + buffer->mto_char_sum += str_len; +} + +void +sclp_move_current_line(struct sclp_buffer *to, struct sclp_buffer *from) +{ + if (from->current_line == NULL) + return; + if (sclp_create_mto(to, from->columns) != 0) + return; + if (from->current_length > 0) { + memcpy(to->current_line, + from->current_line - from->current_length, + from->current_length); + to->current_line += from->current_length; + to->current_length = from->current_length; + } + from->current_line = NULL; +} + +/* + * processing of a message including escape characters, + * returns number of characters written to the output sccb + * ("processed" means that is not guaranteed that the character have already + * been sent to the SCLP but that it will be done at least next time the SCLP + * is not busy) + */ +int +sclp_write(struct sclp_buffer *buffer, + const char *msg, int count, int from_user) +{ + int spaces, i_msg; + char ch; + int rc; + + /* + * parse msg for escape sequences (\t,\v ...) and put formated + * msg into an mto (created by sclp_create_mto). + * + * We have to do this work ourselfs because there is no support for + * these characters on the native machine and only partial support + * under VM (Why does VM interpret \n but the native machine doesn't ?) + * + * Depending on i/o-control setting the message is always written + * immediatly or we wait for a final new line maybe coming with the + * next message. Besides we avoid a buffer overrun by writing its + * content. + * + * RESTRICTIONS: + * + * \r and \b work within one line because we are not able to modify + * previous output that have already been accepted by the SCLP. + * + * \t combined with following \r is not correctly represented because + * \t is expanded to some spaces but \r does not know about a + * previous \t and decreases the current position by one column. + * This is in order to a slim and quick implementation. + */ + for (i_msg = 0; i_msg < count; i_msg++) { + if (from_user) { + if (get_user(ch, msg + i_msg) != 0) + return -EFAULT; + } else + ch = msg[i_msg]; + + switch (ch) { + case '\n': /* new line, line feed (ASCII) */ + /* check if new mto needs to be created */ + if (buffer->current_line == NULL) { + rc = sclp_create_mto(buffer, 0); + if (rc) + return i_msg; + } + sclp_add_mto(buffer); + break; + case '\a': /* bell, one for several times */ + /* set SCLP sound alarm bit in General Object */ + buffer->sccb->msg_buf.mdb.go.general_msg_flags |= + GnrlMsgFlgs_SndAlrm; + break; + case '\t': /* horizontal tabulator */ + /* check if new mto needs to be created */ + if (buffer->current_line == NULL) { + rc = sclp_create_mto(buffer, buffer->columns); + if (rc) + return i_msg; + } + /* "go to (next htab-boundary + 1, same line)" */ + do { + if (buffer->current_length >= buffer->columns) + break; + /* ok, add a blank */ + *buffer->current_line++ = 0x40; + buffer->current_length++; + } while (buffer->current_length % buffer->htab); + break; + case '\f': /* form feed */ + case '\v': /* vertical tabulator */ + /* "go to (actual column, actual line + 1)" */ + /* = new line, leading spaces */ + if (buffer->current_line != NULL) { + spaces = buffer->current_length; + sclp_add_mto(buffer); + rc = sclp_create_mto(buffer, buffer->columns); + if (rc) + return i_msg; + memset(buffer->current_line, 0x40, spaces); + buffer->current_line += spaces; + buffer->current_length = spaces; + } else { + /* one an empty line this is the same as \n */ + rc = sclp_create_mto(buffer, buffer->columns); + if (rc) + return i_msg; + sclp_add_mto(buffer); + } + break; + case '\b': /* backspace */ + /* "go to (actual column - 1, actual line)" */ + /* decrement counter indicating position, */ + /* do not remove last character */ + if (buffer->current_line != NULL && + buffer->current_length > 0) { + buffer->current_length--; + buffer->current_line--; + } + break; + case 0x00: /* end of string */ + /* transfer current line to SCCB */ + if (buffer->current_line != NULL) + sclp_add_mto(buffer); + /* skip the rest of the message including the 0 byte */ + i_msg = count; + break; + default: /* no escape character */ + /* do not output unprintable characters */ + if (!isprint(ch)) + break; + /* check if new mto needs to be created */ + if (buffer->current_line == NULL) { + rc = sclp_create_mto(buffer, buffer->columns); + if (rc) + return i_msg; + } + *buffer->current_line++ = sclp_ascebc(ch); + buffer->current_length++; + break; + } + /* check if current mto is full */ + if (buffer->current_line != NULL && + buffer->current_length >= buffer->columns) + sclp_add_mto(buffer); + } + + /* return number of processed characters */ + return i_msg; +} + +/* + * Return the number of free bytes in the sccb + */ +int +sclp_buffer_space(struct sclp_buffer *buffer) +{ + int count; + + count = MAX_SCCB_ROOM - buffer->sccb->header.length; + if (buffer->current_line != NULL) + count -= sizeof(struct mto) + buffer->current_length; + return count; +} + +/* + * Return number of characters in buffer + */ +int +sclp_chars_in_buffer(struct sclp_buffer *buffer) +{ + int count; + + count = buffer->mto_char_sum; + if (buffer->current_line != NULL) + count += buffer->current_length; + return count; +} + +/* + * sets or provides some values that influence the drivers behaviour + */ +void +sclp_set_columns(struct sclp_buffer *buffer, unsigned short columns) +{ + buffer->columns = columns; + if (buffer->current_line != NULL && + buffer->current_length > buffer->columns) + sclp_add_mto(buffer); +} + +void +sclp_set_htab(struct sclp_buffer *buffer, unsigned short htab) +{ + buffer->htab = htab; +} + +/* + * called by sclp_console_init and/or sclp_tty_init + */ +int +sclp_rw_init(void) +{ + static int init_done = 0; + + if (init_done) + return 0; + init_done = 1; + return sclp_register(&sclp_rw_event); +} + +/* + * second half of Write Event Data-function that has to be done after + * interruption indicating completion of Service Call. + */ +static void +sclp_writedata_callback(struct sclp_req *request, void *data) +{ + struct sclp_buffer *buffer; + struct write_sccb *sccb; + + buffer = (struct sclp_buffer *) data; + sccb = buffer->sccb; + + /* FIXME: proper error handling */ + /* check SCLP response code and choose suitable action */ + switch (sccb->header.response_code) { + case 0x0020 : + /* normal completion, buffer processed, message(s) sent */ + break; + + case 0x0340: /* contained SCLP equipment check */ + case 0x40F0: /* function code disabled in SCLP receive mask */ + break; + default: + /* sclp_free_sccb(sccb); */ + printk(KERN_WARNING SCLP_RW_PRINT_HEADER + "write event data failed " + "(response code: 0x%x SCCB address %p).\n", + sccb->header.response_code, sccb); + break; + } + if (buffer->callback != NULL) + buffer->callback(buffer, sccb->header.response_code); +} + +/* + * Setup the request structure in the struct sclp_buffer to do SCLP Write + * Event Data and pass the request to the core SCLP loop. + */ +void +sclp_emit_buffer(struct sclp_buffer *buffer, + void (*callback)(struct sclp_buffer *, int)) +{ + struct write_sccb *sccb; + + /* add current line if there is one */ + if (buffer->current_line != NULL) + sclp_add_mto(buffer); + + /* Are there messages in the output buffer ? */ + if (buffer->mto_number <= 0) + return; + + sccb = buffer->sccb; + if (sclp_rw_event.sclp_send_mask & EvTyp_Msg_Mask) + /* Use normal write message */ + sccb->msg_buf.header.type = EvTyp_Msg; + else if (sclp_rw_event.sclp_send_mask & EvTyp_PMsgCmd_Mask) + /* Use write priority message */ + sccb->msg_buf.header.type = EvTyp_PMsgCmd; + else { + callback(buffer, -ENOSYS); + return; + } + buffer->request.command = SCLP_CMDW_WRITEDATA; + buffer->request.status = SCLP_REQ_FILLED; + buffer->request.callback = sclp_writedata_callback; + buffer->request.callback_data = buffer; + buffer->request.sccb = sccb; + buffer->callback = callback; + sclp_add_request(&buffer->request); +} diff -Nru a/drivers/s390/char/sclp_rw.h b/drivers/s390/char/sclp_rw.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/s390/char/sclp_rw.h Fri Nov 22 13:41:23 2002 @@ -0,0 +1,94 @@ +/* + * drivers/s390/char/sclp_rw.h + * interface to the SCLP-read/write driver + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Peschke + * Martin Schwidefsky + */ + +#ifndef __SCLP_RW_H__ +#define __SCLP_RW_H__ + +struct mto { + u16 length; + u16 type; + u16 line_type_flags; + u8 alarm_control; + u8 _reserved[3]; +} __attribute__((packed)); + +struct go { + u16 length; + u16 type; + u32 domid; + u8 hhmmss_time[8]; + u8 th_time[3]; + u8 reserved_0; + u8 dddyyyy_date[7]; + u8 _reserved_1; + u16 general_msg_flags; + u8 _reserved_2[10]; + u8 originating_system_name[8]; + u8 job_guest_name[8]; +} __attribute__((packed)); + +struct mdb_header { + u16 length; + u16 type; + u32 tag; + u32 revision_code; +} __attribute__((packed)); + +struct mdb { + struct mdb_header header; + struct go go; +} __attribute__((packed)); + +struct msg_buf { + struct evbuf_header header; + struct mdb mdb; +} __attribute__((packed)); + +struct write_sccb { + struct sccb_header header; + struct msg_buf msg_buf; +} __attribute__((packed)); + +/* The number of empty mto buffers that can be contained in a single sccb. */ +#define NR_EMPTY_MTO_PER_SCCB ((PAGE_SIZE - sizeof(struct sclp_buffer) - \ + sizeof(struct write_sccb)) / sizeof(struct mto)) + +/* + * data structure for information about list of SCCBs (only for writing), + * will be located at the end of a SCCBs page + */ +struct sclp_buffer { + struct list_head list; /* list_head for sccb_info chain */ + struct sclp_req request; + struct write_sccb *sccb; + char *current_line; + int current_length; + /* output format settings */ + unsigned short columns; + unsigned short htab; + /* statistics about this buffer */ + unsigned int mto_char_sum; /* # chars in sccb */ + unsigned int mto_number; /* # mtos in sccb */ + /* Callback that is called after reaching final status. */ + void (*callback)(struct sclp_buffer *, int); +}; + +int sclp_rw_init(void); +struct sclp_buffer *sclp_make_buffer(void *, unsigned short, unsigned short); +void *sclp_unmake_buffer(struct sclp_buffer *); +int sclp_buffer_space(struct sclp_buffer *); +int sclp_write(struct sclp_buffer *buffer, const char *, int, int); +void sclp_move_current_line(struct sclp_buffer *, struct sclp_buffer *); +void sclp_emit_buffer(struct sclp_buffer *,void (*)(struct sclp_buffer *,int)); +void sclp_set_columns(struct sclp_buffer *, unsigned short); +void sclp_set_htab(struct sclp_buffer *, unsigned short); +int sclp_chars_in_buffer(struct sclp_buffer *); + +#endif /* __SCLP_RW_H__ */ diff -Nru a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/s390/char/sclp_tty.c Fri Nov 22 13:41:23 2002 @@ -0,0 +1,798 @@ +/* + * drivers/s390/char/sclp_tty.c + * SCLP line mode terminal driver. + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Peschke + * Martin Schwidefsky + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ctrlchar.h" +#include "sclp.h" +#include "sclp_rw.h" +#include "sclp_tty.h" + +#define SCLP_TTY_PRINT_HEADER "sclp tty driver: " + +/* + * size of a buffer that collects single characters coming in + * via sclp_tty_put_char() + */ +#define SCLP_TTY_BUF_SIZE 512 + +/* + * There is excatly one SCLP terminal, so we can keep things simple + * and allocate all variables statically. + */ + +/* Lock to guard over changes to global variables. */ +static spinlock_t sclp_tty_lock; +/* List of free pages that can be used for console output buffering. */ +static struct list_head sclp_tty_pages; +/* List of full struct sclp_buffer structures ready for output. */ +static struct list_head sclp_tty_outqueue; +/* Counter how many buffers are emitted. */ +static int sclp_tty_buffer_count; +/* Pointer to current console buffer. */ +static struct sclp_buffer *sclp_ttybuf; +/* Timer for delayed output of console messages. */ +static struct timer_list sclp_tty_timer; +/* Waitqueue to wait for buffers to get empty. */ +static wait_queue_head_t sclp_tty_waitq; + +static struct tty_struct *sclp_tty; +static unsigned char sclp_tty_chars[SCLP_TTY_BUF_SIZE]; +static unsigned short int sclp_tty_chars_count; + +static struct tty_driver sclp_tty_driver; +static struct tty_struct * sclp_tty_table[1]; +static struct termios * sclp_tty_termios[1]; +static struct termios * sclp_tty_termios_locked[1]; +static int sclp_tty_refcount = 0; + +extern struct termios tty_std_termios; + +static struct sclp_ioctls sclp_ioctls; +static struct sclp_ioctls sclp_ioctls_init = +{ + 8, /* 1 hor. tab. = 8 spaces */ + 0, /* no echo of input by this driver */ + 80, /* 80 characters/line */ + 1, /* write after 1/10 s without final new line */ + MAX_KMEM_PAGES, /* quick fix: avoid __alloc_pages */ + MAX_KMEM_PAGES, /* take 32/64 pages from kernel memory, */ + 0, /* do not convert to lower case */ + 0x6c /* to seprate upper and lower case */ + /* ('%' in EBCDIC) */ +}; + +/* This routine is called whenever we try to open a SCLP terminal. */ +static int +sclp_tty_open(struct tty_struct *tty, struct file *filp) +{ + /* only 1 SCLP terminal supported */ + if (minor(tty->device) != tty->driver.minor_start) + return -ENODEV; + sclp_tty = tty; + tty->driver_data = NULL; + tty->low_latency = 0; + return 0; +} + +/* This routine is called when the SCLP terminal is closed. */ +static void +sclp_tty_close(struct tty_struct *tty, struct file *filp) +{ + /* only 1 SCLP terminal supported */ + if (minor(tty->device) != tty->driver.minor_start) + return; + if (tty->count > 1) + return; + sclp_tty = NULL; +} + +/* execute commands to control the i/o behaviour of the SCLP tty at runtime */ +static int +sclp_tty_ioctl(struct tty_struct *tty, struct file * file, + unsigned int cmd, unsigned long arg) +{ + unsigned long flags; + unsigned int obuf; + int check; + int rc; + + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + rc = 0; + check = 0; + switch (cmd) { + case TIOCSCLPSHTAB: + /* set width of horizontal tab */ + if (get_user(sclp_ioctls.htab, (unsigned short *) arg)) + rc = -EFAULT; + else + check = 1; + break; + case TIOCSCLPGHTAB: + /* get width of horizontal tab */ + if (put_user(sclp_ioctls.htab, (unsigned short *) arg)) + rc = -EFAULT; + break; + case TIOCSCLPSECHO: + /* enable/disable echo of input */ + if (get_user(sclp_ioctls.echo, (unsigned char *) arg)) + rc = -EFAULT; + break; + case TIOCSCLPGECHO: + /* Is echo of input enabled ? */ + if (put_user(sclp_ioctls.echo, (unsigned char *) arg)) + rc = -EFAULT; + break; + case TIOCSCLPSCOLS: + /* set number of columns for output */ + if (get_user(sclp_ioctls.columns, (unsigned short *) arg)) + rc = -EFAULT; + else + check = 1; + break; + case TIOCSCLPGCOLS: + /* get number of columns for output */ + if (put_user(sclp_ioctls.columns, (unsigned short *) arg)) + rc = -EFAULT; + break; + case TIOCSCLPSNL: + /* enable/disable writing without final new line character */ + if (get_user(sclp_ioctls.final_nl, (signed char *) arg)) + rc = -EFAULT; + break; + case TIOCSCLPGNL: + /* Is writing without final new line character enabled ? */ + if (put_user(sclp_ioctls.final_nl, (signed char *) arg)) + rc = -EFAULT; + break; + case TIOCSCLPSOBUF: + /* + * set the maximum buffers size for output, will be rounded + * up to next 4kB boundary and stored as number of SCCBs + * (4kB Buffers) limitation: 256 x 4kB + */ + if (get_user(obuf, (unsigned int *) arg) == 0) { + if (obuf & 0xFFF) + sclp_ioctls.max_sccb = (obuf >> 12) + 1; + else + sclp_ioctls.max_sccb = (obuf >> 12); + } else + rc = -EFAULT; + break; + case TIOCSCLPGOBUF: + /* get the maximum buffers size for output */ + obuf = sclp_ioctls.max_sccb << 12; + if (put_user(obuf, (unsigned int *) arg)) + rc = -EFAULT; + break; + case TIOCSCLPGKBUF: + /* get the number of buffers got from kernel at startup */ + if (put_user(sclp_ioctls.kmem_sccb, (unsigned short *) arg)) + rc = -EFAULT; + break; + case TIOCSCLPSCASE: + /* enable/disable conversion from upper to lower case */ + if (get_user(sclp_ioctls.tolower, (unsigned char *) arg)) + rc = -EFAULT; + break; + case TIOCSCLPGCASE: + /* Is conversion from upper to lower case of input enabled? */ + if (put_user(sclp_ioctls.tolower, (unsigned char *) arg)) + rc = -EFAULT; + break; + case TIOCSCLPSDELIM: + /* + * set special character used for seperating upper and + * lower case, 0x00 disables this feature + */ + if (get_user(sclp_ioctls.delim, (unsigned char *) arg)) + rc = -EFAULT; + break; + case TIOCSCLPGDELIM: + /* + * get special character used for seperating upper and + * lower case, 0x00 disables this feature + */ + if (put_user(sclp_ioctls.delim, (unsigned char *) arg)) + rc = -EFAULT; + break; + case TIOCSCLPSINIT: + /* set initial (default) sclp ioctls */ + sclp_ioctls = sclp_ioctls_init; + check = 1; + break; + default: + rc = -ENOIOCTLCMD; + break; + } + if (check) { + spin_lock_irqsave(&sclp_tty_lock, flags); + if (sclp_ttybuf != NULL) { + sclp_set_htab(sclp_ttybuf, sclp_ioctls.htab); + sclp_set_columns(sclp_ttybuf, sclp_ioctls.columns); + } + spin_unlock_irqrestore(&sclp_tty_lock, flags); + } + return rc; +} + +/* + * This routine returns the numbers of characters the tty driver + * will accept for queuing to be written. This number is subject + * to change as output buffers get emptied, or if the output flow + * control is acted. This is not an exact number because not every + * character needs the same space in the sccb. The worst case is + * a string of newlines. Every newlines creates a new mto which + * needs 8 bytes. + */ +static int +sclp_tty_write_room (struct tty_struct *tty) +{ + unsigned long flags; + struct list_head *l; + int count; + + spin_lock_irqsave(&sclp_tty_lock, flags); + count = 0; + if (sclp_ttybuf != NULL) + count = sclp_buffer_space(sclp_ttybuf) / sizeof(struct mto); + list_for_each(l, &sclp_tty_pages) + count += NR_EMPTY_MTO_PER_SCCB; + spin_unlock_irqrestore(&sclp_tty_lock, flags); + return count; +} + +static void +sclp_ttybuf_callback(struct sclp_buffer *buffer, int rc) +{ + unsigned long flags; + struct sclp_buffer *next; + void *page; + + /* FIXME: what if rc != 0x0020 */ + page = sclp_unmake_buffer(buffer); + spin_lock_irqsave(&sclp_tty_lock, flags); + list_add_tail((struct list_head *) page, &sclp_tty_pages); + sclp_tty_buffer_count--; + /* Remove buffer from outqueue */ + list_del(&buffer->list); + /* Check if there is a pending buffer on the out queue. */ + next = NULL; + if (!list_empty(&sclp_tty_outqueue)) + next = list_entry(sclp_tty_outqueue.next, + struct sclp_buffer, list); + spin_unlock_irqrestore(&sclp_tty_lock, flags); + if (next != NULL) + sclp_emit_buffer(next, sclp_ttybuf_callback); + wake_up(&sclp_tty_waitq); + /* check if the tty needs a wake up call */ + if (sclp_tty != NULL) { + if ((sclp_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + sclp_tty->ldisc.write_wakeup) + (sclp_tty->ldisc.write_wakeup)(sclp_tty); + wake_up_interruptible(&sclp_tty->write_wait); + } +} + +static inline void +__sclp_ttybuf_emit(struct sclp_buffer *buffer) +{ + list_add_tail(&buffer->list, &sclp_tty_outqueue); + if (sclp_tty_buffer_count++ == 0) + sclp_emit_buffer(buffer, sclp_ttybuf_callback); +} + +/* + * When this routine is called from the timer then we flush the + * temporary write buffer. + */ +static void +sclp_tty_timeout(unsigned long data) +{ + unsigned long flags; + + spin_lock_irqsave(&sclp_tty_lock, flags); + if (sclp_ttybuf != NULL) { + __sclp_ttybuf_emit(sclp_ttybuf); + sclp_ttybuf = NULL; + } + spin_unlock_irqrestore(&sclp_tty_lock, flags); +} + +/* + * Write a string to the sclp tty. + */ +static void +sclp_tty_write_string(const unsigned char *str, int count, int from_user) +{ + unsigned long flags; + void *page; + int written; + + if (count <= 0) + return; + spin_lock_irqsave(&sclp_tty_lock, flags); + do { + /* Create a sclp output buffer if none exists yet */ + if (sclp_ttybuf == NULL) { + while (list_empty(&sclp_tty_pages)) { + spin_unlock_irqrestore(&sclp_tty_lock, flags); + wait_event(sclp_tty_waitq, + !list_empty(&sclp_tty_pages)); + spin_lock_irqsave(&sclp_tty_lock, flags); + } + page = sclp_tty_pages.next; + list_del((struct list_head *) page); + sclp_ttybuf = sclp_make_buffer(page, + sclp_ioctls.columns, + sclp_ioctls.htab); + } + /* try to write the string to the current output buffer */ + written = sclp_write(sclp_ttybuf, str, count, from_user); + if (written == -EFAULT || written == count) + break; + /* + * Not all characters could be written to the current + * output buffer. Emit the buffer, create a new buffer + * and then output the rest of the string. + */ + __sclp_ttybuf_emit(sclp_ttybuf); + sclp_ttybuf = NULL; + str += written; + count -= written; + } while (count > 0); + /* Setup timer to output current console buffer after 1/10 second */ + if (sclp_ioctls.final_nl) { + if (sclp_ttybuf != NULL && !timer_pending(&sclp_tty_timer)) { + init_timer(&sclp_tty_timer); + sclp_tty_timer.function = sclp_tty_timeout; + sclp_tty_timer.data = 0UL; + sclp_tty_timer.expires = jiffies + HZ/10; + add_timer(&sclp_tty_timer); + } + } else { + __sclp_ttybuf_emit(sclp_ttybuf); + sclp_ttybuf = NULL; + } + spin_unlock_irqrestore(&sclp_tty_lock, flags); +} + +/* + * This routine is called by the kernel to write a series of characters to the + * tty device. The characters may come from user space or kernel space. This + * routine will return the number of characters actually accepted for writing. + */ +static int +sclp_tty_write(struct tty_struct *tty, int from_user, + const unsigned char *buf, int count) +{ + if (sclp_tty_chars_count > 0) { + sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0); + sclp_tty_chars_count = 0; + } + sclp_tty_write_string(buf, count, from_user); + return count; +} + +/* + * This routine is called by the kernel to write a single character to the tty + * device. If the kernel uses this routine, it must call the flush_chars() + * routine (if defined) when it is done stuffing characters into the driver. + * + * Characters provided to sclp_tty_put_char() are buffered by the SCLP driver. + * If the given character is a '\n' the contents of the SCLP write buffer + * - including previous characters from sclp_tty_put_char() and strings from + * sclp_write() without final '\n' - will be written. + */ +static void +sclp_tty_put_char(struct tty_struct *tty, unsigned char ch) +{ + sclp_tty_chars[sclp_tty_chars_count++] = ch; + if (ch == '\n' || sclp_tty_chars_count >= SCLP_TTY_BUF_SIZE) { + sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0); + sclp_tty_chars_count = 0; + } +} + +/* + * This routine is called by the kernel after it has written a series of + * characters to the tty device using put_char(). + */ +static void +sclp_tty_flush_chars(struct tty_struct *tty) +{ + if (sclp_tty_chars_count > 0) { + sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0); + sclp_tty_chars_count = 0; + } +} + +/* + * This routine returns the number of characters in the write buffer of the + * SCLP driver. The provided number includes all characters that are stored + * in the SCCB (will be written next time the SCLP is not busy) as well as + * characters in the write buffer (will not be written as long as there is a + * final line feed missing). + */ +static int +sclp_tty_chars_in_buffer(struct tty_struct *tty) +{ + unsigned long flags; + struct list_head *l; + struct sclp_buffer *t; + int count; + + spin_lock_irqsave(&sclp_tty_lock, flags); + count = 0; + if (sclp_ttybuf != NULL) + count = sclp_chars_in_buffer(sclp_ttybuf); + list_for_each(l, &sclp_tty_outqueue) { + t = list_entry(l, struct sclp_buffer, list); + count += sclp_chars_in_buffer(sclp_ttybuf); + } + spin_unlock_irqrestore(&sclp_tty_lock, flags); + return count; +} + +/* + * removes all content from buffers of low level driver + */ +static void +sclp_tty_flush_buffer(struct tty_struct *tty) +{ + if (sclp_tty_chars_count > 0) { + sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0); + sclp_tty_chars_count = 0; + } +} + +/* + * push input to tty + */ +void sclp_tty_input(unsigned char* buf, unsigned int count) +{ + unsigned int cchar; + + /* + * If this tty driver is currently closed + * then throw the received input away. + */ + if (sclp_tty == NULL) + return; + cchar = ctrlchar_handle(buf, count, sclp_tty); + switch (cchar & CTRLCHAR_MASK) { + case CTRLCHAR_SYSRQ: + break; + case CTRLCHAR_CTRL: + sclp_tty->flip.count++; + *sclp_tty->flip.flag_buf_ptr++ = TTY_NORMAL; + *sclp_tty->flip.char_buf_ptr++ = cchar; + tty_flip_buffer_push(sclp_tty); + break; + case CTRLCHAR_NONE: + /* send (normal) input to line discipline */ + memcpy(sclp_tty->flip.char_buf_ptr, buf, count); + if (count < 2 || + strncmp (buf + count - 2, "^n", 2) || + strncmp (buf + count - 2, "\0252n", 2)) { + sclp_tty->flip.char_buf_ptr[count] = '\n'; + count++; + } else + count -= 2; + memset(sclp_tty->flip.flag_buf_ptr, TTY_NORMAL, count); + sclp_tty->flip.char_buf_ptr += count; + sclp_tty->flip.flag_buf_ptr += count; + sclp_tty->flip.count += count; + tty_flip_buffer_push(sclp_tty); + break; + } +} + +/* + * get a EBCDIC string in upper/lower case, + * find out characters in lower/upper case seperated by a special character, + * modifiy original string, + * returns length of resulting string + */ +static int +sclp_switch_cases(unsigned char *buf, int count, + unsigned char delim, int tolower) +{ + unsigned char *ip, *op; + int toggle; + + /* initially changing case is off */ + toggle = 0; + ip = op = buf; + while (count-- > 0) { + /* compare with special character */ + if (*ip == delim) { + /* followed by another special character? */ + if (count && ip[1] == delim) { + /* + * ... then put a single copy of the special + * character to the output string + */ + *op++ = *ip++; + count--; + } else + /* + * ... special character follower by a normal + * character toggles the case change behaviour + */ + toggle = ~toggle; + /* skip special character */ + ip++; + } else + /* not the special character */ + if (toggle) + /* but case switching is on */ + if (tolower) + /* switch to uppercase */ + *op++ = _ebc_toupper[(int) *ip++]; + else + /* switch to lowercase */ + *op++ = _ebc_tolower[(int) *ip++]; + else + /* no case switching, copy the character */ + *op++ = *ip++; + } + /* return length of reformatted string. */ + return op - buf; +} + +static void +sclp_get_input(char *start, char *end) +{ + int count; + + count = end - start; + /* + * if set in ioctl convert EBCDIC to lower case + * (modify original input in SCCB) + */ + if (sclp_ioctls.tolower) + EBC_TOLOWER(start, count); + + /* + * if set in ioctl find out characters in lower or upper case + * (depends on current case) seperated by a special character, + * works on EBCDIC + */ + if (sclp_ioctls.delim) + count = sclp_switch_cases(start, count, + sclp_ioctls.delim, + sclp_ioctls.tolower); + + /* convert EBCDIC to ASCII (modify original input in SCCB) */ + sclp_ebcasc_str(start, count); + + /* if set in ioctl write operators input to console */ + if (sclp_ioctls.echo) + sclp_tty_write(sclp_tty, 0, start, count); + + /* transfer input to high level driver */ + sclp_tty_input(start, count); +} + +static inline struct gds_vector * +find_gds_vector(struct gds_vector *start, struct gds_vector *end, u16 id) +{ + struct gds_vector *vec; + + for (vec = start; vec < end; (void *) vec += vec->length) + if (vec->gds_id == id) + return vec; + return NULL; +} + +static inline struct gds_subvector * +find_gds_subvector(struct gds_subvector *start, + struct gds_subvector *end, u8 key) +{ + struct gds_subvector *subvec; + + for (subvec = start; subvec < end; (void *) subvec += subvec->length) + if (subvec->key == key) + return subvec; + return NULL; +} + +static inline void +sclp_eval_selfdeftextmsg(struct gds_subvector *start, + struct gds_subvector *end) +{ + struct gds_subvector *subvec; + + subvec = start; + while (subvec < end) { + subvec = find_gds_subvector(subvec, end, 0x30); + if (!subvec) + break; + sclp_get_input((void *)(subvec + 1), + (void *) subvec + subvec->length); + (void *) subvec += subvec->length; + } +} + +static inline void +sclp_eval_textcmd(struct gds_subvector *start, + struct gds_subvector *end) +{ + struct gds_subvector *subvec; + + subvec = start; + while (subvec < end) { + subvec = find_gds_subvector(subvec, end, + GDS_KEY_SelfDefTextMsg); + if (!subvec) + break; + sclp_eval_selfdeftextmsg((struct gds_subvector *)(subvec + 1), + (void *)subvec + subvec->length); + (void *) subvec += subvec->length; + } +} + +static inline void +sclp_eval_cpmsu(struct gds_vector *start, struct gds_vector *end) +{ + struct gds_vector *vec; + + vec = start; + while (vec < end) { + vec = find_gds_vector(vec, end, GDS_ID_TextCmd); + if (!vec) + break; + sclp_eval_textcmd((struct gds_subvector *)(vec + 1), + (void *) vec + vec->length); + (void *) vec += vec->length; + } +} + + +static inline void +sclp_eval_mdsmu(struct gds_vector *start, void *end) +{ + struct gds_vector *vec; + + vec = find_gds_vector(start, end, GDS_ID_CPMSU); + if (vec) + sclp_eval_cpmsu(vec + 1, (void *) vec + vec->length); +} + +static void +sclp_tty_receiver(struct evbuf_header *evbuf) +{ + struct gds_vector *start, *end, *vec; + + start = (struct gds_vector *)(evbuf + 1); + end = (void *) evbuf + evbuf->length; + vec = find_gds_vector(start, end, GDS_ID_MDSMU); + if (vec) + sclp_eval_mdsmu(vec + 1, (void *) vec + vec->length); +} + +static void +sclp_tty_state_change(struct sclp_register *reg) +{ +} + +struct sclp_register sclp_input_event = +{ + .receive_mask = EvTyp_OpCmd_Mask | EvTyp_PMsgCmd_Mask, + .state_change_fn = sclp_tty_state_change, + .receiver_fn = sclp_tty_receiver +}; + +void +sclp_tty_init(void) +{ + void *page; + int i; + + if (!CONSOLE_IS_SCLP) + return; + if (sclp_rw_init() != 0) + return; + /* Allocate pages for output buffering */ + INIT_LIST_HEAD(&sclp_tty_pages); + for (i = 0; i < MAX_KMEM_PAGES; i++) { + page = (void *) get_zeroed_page(GFP_KERNEL); + if (page == NULL) + return; + list_add_tail((struct list_head *) page, &sclp_tty_pages); + } + INIT_LIST_HEAD(&sclp_tty_outqueue); + spin_lock_init(&sclp_tty_lock); + init_waitqueue_head(&sclp_tty_waitq); + init_timer(&sclp_tty_timer); + sclp_ttybuf = NULL; + sclp_tty_buffer_count = 0; + if (MACHINE_IS_VM) { + /* + * save 4 characters for the CPU number + * written at start of each line by VM/CP + */ + sclp_ioctls_init.columns = 76; + /* case input lines to lowercase */ + sclp_ioctls_init.tolower = 1; + } + sclp_ioctls = sclp_ioctls_init; + sclp_tty_chars_count = 0; + sclp_tty = NULL; + + if (sclp_register(&sclp_input_event) != 0) + return; + + memset (&sclp_tty_driver, 0, sizeof(struct tty_driver)); + sclp_tty_driver.magic = TTY_DRIVER_MAGIC; + sclp_tty_driver.driver_name = "tty_sclp"; + sclp_tty_driver.name = "ttyS"; + sclp_tty_driver.name_base = 0; + sclp_tty_driver.major = TTY_MAJOR; + sclp_tty_driver.minor_start = 64; + sclp_tty_driver.num = 1; + sclp_tty_driver.type = TTY_DRIVER_TYPE_SYSTEM; + sclp_tty_driver.subtype = SYSTEM_TYPE_TTY; + sclp_tty_driver.init_termios = tty_std_termios; + sclp_tty_driver.init_termios.c_iflag = IGNBRK | IGNPAR; + sclp_tty_driver.init_termios.c_oflag = ONLCR | XTABS; + sclp_tty_driver.init_termios.c_lflag = ISIG | ECHO; + sclp_tty_driver.flags = TTY_DRIVER_REAL_RAW; + sclp_tty_driver.refcount = &sclp_tty_refcount; + /* sclp_tty_driver.proc_entry ? */ + sclp_tty_driver.table = sclp_tty_table; + sclp_tty_driver.termios = sclp_tty_termios; + sclp_tty_driver.termios_locked = sclp_tty_termios_locked; + sclp_tty_driver.open = sclp_tty_open; + sclp_tty_driver.close = sclp_tty_close; + sclp_tty_driver.write = sclp_tty_write; + sclp_tty_driver.put_char = sclp_tty_put_char; + sclp_tty_driver.flush_chars = sclp_tty_flush_chars; + sclp_tty_driver.write_room = sclp_tty_write_room; + sclp_tty_driver.chars_in_buffer = sclp_tty_chars_in_buffer; + sclp_tty_driver.flush_buffer = sclp_tty_flush_buffer; + sclp_tty_driver.ioctl = sclp_tty_ioctl; + /* + * No need for these function because they would be only called when + * the line discipline is close to full. That means that there must be + * collected nearly 4kB of input data. I suppose it is very difficult + * for the operator to enter lines quickly enough to let overrun the + * line discipline. Besides the n_tty line discipline does not try to + * call such functions if the pointers are set to NULL. Finally I have + * no idea what to do within these function. I can not prevent the + * operator and the SCLP to deliver input. Because of the reasons + * above it seems not worth to implement a buffer mechanism. + */ + sclp_tty_driver.throttle = NULL; + sclp_tty_driver.unthrottle = NULL; + sclp_tty_driver.send_xchar = NULL; + sclp_tty_driver.set_termios = NULL; + sclp_tty_driver.set_ldisc = NULL; + sclp_tty_driver.stop = NULL; + sclp_tty_driver.start = NULL; + sclp_tty_driver.hangup = NULL; + sclp_tty_driver.break_ctl = NULL; + sclp_tty_driver.wait_until_sent = NULL; + sclp_tty_driver.read_proc = NULL; + sclp_tty_driver.write_proc = NULL; + + if (tty_register_driver(&sclp_tty_driver)) + panic("Couldn't register sclp_tty driver\n"); +} diff -Nru a/drivers/s390/char/sclp_tty.h b/drivers/s390/char/sclp_tty.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/s390/char/sclp_tty.h Fri Nov 22 13:41:23 2002 @@ -0,0 +1,67 @@ +/* + * drivers/s390/char/sclp_tty.h + * interface to the SCLP-read/write driver + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Peschke + * Martin Schwidefsky + */ + +#ifndef __SCLP_TTY_H__ +#define __SCLP_TTY_H__ + +#include + +/* This is the type of data structures storing sclp ioctl setting. */ +struct sclp_ioctls { + unsigned short htab; + unsigned char echo; + unsigned short columns; + signed char final_nl; + unsigned short max_sccb; + unsigned short kmem_sccb; /* can´t be modified at run time */ + unsigned char tolower; + unsigned char delim; +}; + +/* must be unique, FIXME: must be added in Documentation/ioctl_number.txt */ +#define SCLP_IOCTL_LETTER 'B' + +/* set width of horizontal tabulator */ +#define TIOCSCLPSHTAB _IOW(SCLP_IOCTL_LETTER, 0, unsigned short) +/* enable/disable echo of input (independent from line discipline) */ +#define TIOCSCLPSECHO _IOW(SCLP_IOCTL_LETTER, 1, unsigned char) +/* set number of colums for output */ +#define TIOCSCLPSCOLS _IOW(SCLP_IOCTL_LETTER, 2, unsigned short) +/* enable/disable writing without final new line character */ +#define TIOCSCLPSNL _IOW(SCLP_IOCTL_LETTER, 4, signed char) +/* set the maximum buffers size for output, rounded up to next 4kB boundary */ +#define TIOCSCLPSOBUF _IOW(SCLP_IOCTL_LETTER, 5, unsigned short) +/* set initial (default) sclp ioctls */ +#define TIOCSCLPSINIT _IO(SCLP_IOCTL_LETTER, 6) +/* enable/disable conversion from upper to lower case of input */ +#define TIOCSCLPSCASE _IOW(SCLP_IOCTL_LETTER, 7, unsigned char) +/* set special character used for seperating upper and lower case, */ +/* 0x00 disables this feature */ +#define TIOCSCLPSDELIM _IOW(SCLP_IOCTL_LETTER, 9, unsigned char) + +/* get width of horizontal tabulator */ +#define TIOCSCLPGHTAB _IOR(SCLP_IOCTL_LETTER, 10, unsigned short) +/* Is echo of input enabled ? (independent from line discipline) */ +#define TIOCSCLPGECHO _IOR(SCLP_IOCTL_LETTER, 11, unsigned char) +/* get number of colums for output */ +#define TIOCSCLPGCOLS _IOR(SCLP_IOCTL_LETTER, 12, unsigned short) +/* Is writing without final new line character enabled ? */ +#define TIOCSCLPGNL _IOR(SCLP_IOCTL_LETTER, 14, signed char) +/* get the maximum buffers size for output */ +#define TIOCSCLPGOBUF _IOR(SCLP_IOCTL_LETTER, 15, unsigned short) +/* Is conversion from upper to lower case of input enabled ? */ +#define TIOCSCLPGCASE _IOR(SCLP_IOCTL_LETTER, 17, unsigned char) +/* get special character used for seperating upper and lower case, */ +/* 0x00 disables this feature */ +#define TIOCSCLPGDELIM _IOR(SCLP_IOCTL_LETTER, 19, unsigned char) +/* get the number of buffers/pages got from kernel at startup */ +#define TIOCSCLPGKBUF _IOR(SCLP_IOCTL_LETTER, 20, unsigned short) + +#endif /* __SCLP_TTY_H__ */ diff -Nru a/drivers/s390/char/tape.c b/drivers/s390/char/tape.c --- a/drivers/s390/char/tape.c Fri Nov 22 13:41:21 2002 +++ b/drivers/s390/char/tape.c Fri Nov 22 13:41:21 2002 @@ -199,10 +199,10 @@ static struct file_operations tape_proc_devices_file_ops = { - owner:THIS_MODULE, - read:tape_proc_devices_read, /* read */ - open:tape_proc_devices_open, /* open */ - release:tape_proc_devices_release, /* close */ + .owner = THIS_MODULE, + .read = tape_proc_devices_read, /* read */ + .open = tape_proc_devices_open, /* open */ + .release = tape_proc_devices_release, /* close */ }; /* diff -Nru a/drivers/s390/char/tapechar.c b/drivers/s390/char/tapechar.c --- a/drivers/s390/char/tapechar.c Fri Nov 22 13:41:19 2002 +++ b/drivers/s390/char/tapechar.c Fri Nov 22 13:41:19 2002 @@ -40,12 +40,12 @@ */ static struct file_operations tape_fops = { - owner:THIS_MODULE, - read:tapechar_read, - write:tapechar_write, - ioctl:tapechar_ioctl, - open:tapechar_open, - release:tapechar_release, + .owner = THIS_MODULE, + .read = tapechar_read, + .write = tapechar_write, + .ioctl = tapechar_ioctl, + .open = tapechar_open, + .release = tapechar_release, }; int tapechar_major = TAPECHAR_MAJOR; diff -Nru a/drivers/s390/char/tubfs.c b/drivers/s390/char/tubfs.c --- a/drivers/s390/char/tubfs.c Fri Nov 22 13:41:21 2002 +++ b/drivers/s390/char/tubfs.c Fri Nov 22 13:41:21 2002 @@ -24,13 +24,13 @@ static struct file_operations fs3270_fops = { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)) - owner: THIS_MODULE, /* owner */ + .owner = THIS_MODULE, /* owner */ #endif - read: fs3270_read, /* read */ - write: fs3270_write, /* write */ - ioctl: fs3270_ioctl, /* ioctl */ - open: fs3270_open, /* open */ - release:fs3270_close, /* release */ + .read = fs3270_read, /* read */ + .write = fs3270_write, /* write */ + .ioctl = fs3270_ioctl, /* ioctl */ + .open = fs3270_open, /* open */ + .release = fs3270_close, /* release */ }; #ifdef CONFIG_DEVFS_FS diff -Nru a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c --- a/drivers/s390/cio/chsc.c Fri Nov 22 13:41:20 2002 +++ b/drivers/s390/cio/chsc.c Fri Nov 22 13:41:20 2002 @@ -113,13 +113,13 @@ *ssd_res = &chsc_area_ssd.response_block.response_block_data.ssd_res; chsc_area_ssd = (chsc_area_t) { - request_block: { - command_code1: 0x0010, - command_code2: 0x0004, - request_block_data: { - ssd_req: { - f_sch: irq, - l_sch: irq, + .request_block = { + .command_code1 = 0x0010, + .command_code2 = 0x0004, + .request_block_data = { + .ssd_req = { + .f_sch = irq, + .l_sch = irq, } } } @@ -545,9 +545,9 @@ * allocation or prove that this function does not have to be * reentrant! */ static chsc_area_t chsc_area_sei __attribute__ ((aligned(PAGE_SIZE))) = { - request_block: { - command_code1: 0x0010, - command_code2: 0x000e + .request_block = { + .command_code1 = 0x0010, + .command_code2 = 0x000e } }; diff -Nru a/drivers/s390/cio/proc.c b/drivers/s390/cio/proc.c --- a/drivers/s390/cio/proc.c Fri Nov 22 13:41:18 2002 +++ b/drivers/s390/cio/proc.c Fri Nov 22 13:41:18 2002 @@ -154,7 +154,7 @@ } static struct file_operations chan_subch_file_ops = { - read:chan_subch_read, open:chan_subch_open, release:chan_subch_close, + .read = chan_subch_read, .open = chan_subch_open, .release = chan_subch_close, }; static int @@ -245,8 +245,8 @@ } static struct file_operations cio_irq_proc_file_ops = { - read:cio_irq_proc_read, open:cio_irq_proc_open, - release:cio_irq_proc_close, + .read = cio_irq_proc_read, .open = cio_irq_proc_open, + .release = cio_irq_proc_close, }; static int diff -Nru a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c --- a/drivers/s390/net/ctcmain.c Fri Nov 22 13:41:18 2002 +++ b/drivers/s390/net/ctcmain.c Fri Nov 22 13:41:18 2002 @@ -2865,17 +2865,17 @@ } static struct file_operations ctc_stat_fops = { - read: ctc_stat_read, - write: ctc_stat_write, - open: ctc_stat_open, - release: ctc_stat_close, + .read = ctc_stat_read, + .write = ctc_stat_write, + .open = ctc_stat_open, + .release = ctc_stat_close, }; static struct file_operations ctc_ctrl_fops = { - read: ctc_ctrl_read, - write: ctc_ctrl_write, - open: ctc_ctrl_open, - release: ctc_ctrl_close, + .read = ctc_ctrl_read, + .write = ctc_ctrl_write, + .open = ctc_ctrl_open, + .release = ctc_ctrl_close, }; static struct proc_dir_entry *ctc_dir = NULL; diff -Nru a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c --- a/drivers/s390/net/netiucv.c Fri Nov 22 13:41:20 2002 +++ b/drivers/s390/net/netiucv.c Fri Nov 22 13:41:20 2002 @@ -465,13 +465,13 @@ } static iucv_interrupt_ops_t netiucv_ops = { - ConnectionPending: netiucv_callback_connreq, - ConnectionComplete: netiucv_callback_connack, - ConnectionSevered: netiucv_callback_connrej, - ConnectionQuiesced: netiucv_callback_connsusp, - ConnectionResumed: netiucv_callback_connres, - MessagePending: netiucv_callback_rx, - MessageComplete: netiucv_callback_txdone + .ConnectionPending = netiucv_callback_connreq, + .ConnectionComplete = netiucv_callback_connack, + .ConnectionSevered = netiucv_callback_connrej, + .ConnectionQuiesced = netiucv_callback_connsusp, + .ConnectionResumed = netiucv_callback_connres, + .MessagePending = netiucv_callback_rx, + .MessageComplete = netiucv_callback_txdone }; /** @@ -1566,24 +1566,24 @@ } static struct file_operations netiucv_stat_fops = { - read: netiucv_stat_read, - write: netiucv_stat_write, - open: netiucv_stat_open, - release: netiucv_stat_close, + .read = netiucv_stat_read, + .write = netiucv_stat_write, + .open = netiucv_stat_open, + .release = netiucv_stat_close, }; static struct file_operations netiucv_buffer_fops = { - read: netiucv_buffer_read, - write: netiucv_buffer_write, - open: netiucv_buffer_open, - release: netiucv_buffer_close, + .read = netiucv_buffer_read, + .write = netiucv_buffer_write, + .open = netiucv_buffer_open, + .release = netiucv_buffer_close, }; static struct file_operations netiucv_user_fops = { - read: netiucv_user_read, - write: netiucv_user_write, - open: netiucv_user_open, - release: netiucv_user_close, + .read = netiucv_user_read, + .write = netiucv_user_write, + .open = netiucv_user_open, + .release = netiucv_user_close, }; static struct proc_dir_entry *netiucv_dir = NULL; diff -Nru a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c --- a/drivers/sbus/char/bbc_i2c.c Fri Nov 22 13:41:22 2002 +++ b/drivers/sbus/char/bbc_i2c.c Fri Nov 22 13:41:22 2002 @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include diff -Nru a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c --- a/drivers/sbus/char/display7seg.c Fri Nov 22 13:41:22 2002 +++ b/drivers/sbus/char/display7seg.c Fri Nov 22 13:41:22 2002 @@ -197,6 +197,7 @@ if (0 != iTmp) { printk("%s: unable to acquire miscdevice minor %i\n", D7S_DEVNAME, D7S_MINOR); + iounmap(d7s_regs); return iTmp; } diff -Nru a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c --- a/drivers/scsi/BusLogic.c Fri Nov 22 13:41:23 2002 +++ b/drivers/scsi/BusLogic.c Fri Nov 22 13:41:23 2002 @@ -29,24 +29,26 @@ #define BusLogic_DriverVersion "2.1.16" #define BusLogic_DriverDate "18 July 2002" +#include #include #include -#include #include +#include #include #include #include #include #include #include -#include #include #include #include +/* #include This include file is currently busted */ + #include #include #include -/* #include This include file is currently busted */ + #include "scsi.h" #include "hosts.h" #include "BusLogic.h" diff -Nru a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c --- a/drivers/scsi/NCR53c406a.c Fri Nov 22 13:41:20 2002 +++ b/drivers/scsi/NCR53c406a.c Fri Nov 22 13:41:20 2002 @@ -1070,23 +1070,23 @@ static Scsi_Host_Template driver_template = { - proc_name: "NCR53c406a" /* proc_name */, - name: "NCR53c406a" /* name */, - detect: NCR53c406a_detect /* detect */, - info: NCR53c406a_info /* info */, - command: NCR53c406a_command /* command */, - queuecommand: NCR53c406a_queue /* queuecommand */, - eh_abort_handler: NCR53c406a_abort /* abort */, - eh_bus_reset_handler: NCR53c406a_bus_reset /* reset */, - eh_device_reset_handler: NCR53c406a_device_reset /* reset */, - eh_host_reset_handler: NCR53c406a_host_reset /* reset */, - bios_param: NCR53c406a_biosparm /* biosparm */, - can_queue: 1 /* can_queue */, - this_id: 7 /* SCSI ID of the chip */, - sg_tablesize: 32 /*SG_ALL*/ /*SG_NONE*/, - cmd_per_lun: 1 /* commands per lun */, - unchecked_isa_dma: 1 /* unchecked_isa_dma */, - use_clustering: ENABLE_CLUSTERING + .proc_name = "NCR53c406a" /* proc_name */, + .name = "NCR53c406a" /* name */, + .detect = NCR53c406a_detect /* detect */, + .info = NCR53c406a_info /* info */, + .command = NCR53c406a_command /* command */, + .queuecommand = NCR53c406a_queue /* queuecommand */, + .eh_abort_handler = NCR53c406a_abort /* abort */, + .eh_bus_reset_handler = NCR53c406a_bus_reset /* reset */, + .eh_device_reset_handler = NCR53c406a_device_reset /* reset */, + .eh_host_reset_handler = NCR53c406a_host_reset /* reset */, + .bios_param = NCR53c406a_biosparm /* biosparm */, + .can_queue = 1 /* can_queue */, + .this_id = 7 /* SCSI ID of the chip */, + .sg_tablesize = 32 /*SG_ALL*/ /*SG_NONE*/, + .cmd_per_lun = 1 /* commands per lun */, + .unchecked_isa_dma = 1 /* unchecked_isa_dma */, + .use_clustering = ENABLE_CLUSTERING }; #include "scsi_module.c" diff -Nru a/drivers/scsi/NCR_D700.c b/drivers/scsi/NCR_D700.c --- a/drivers/scsi/NCR_D700.c Fri Nov 22 13:41:18 2002 +++ b/drivers/scsi/NCR_D700.c Fri Nov 22 13:41:18 2002 @@ -93,25 +93,25 @@ #define NCR_D700_VERSION "2.2" #include +#include +#include #include #include +#include #include #include #include #include #include -#include #include #include #include + #include #include #include #include #include -#include -#include - #include "scsi.h" #include "hosts.h" diff -Nru a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c --- a/drivers/scsi/advansys.c Fri Nov 22 13:41:18 2002 +++ b/drivers/scsi/advansys.c Fri Nov 22 13:41:18 2002 @@ -789,25 +789,23 @@ #endif /* CONFIG_X86 && !CONFIG_ISA */ #include -#include #include #include #include +#include #include #include #include #include #include -#include -#include -#include #include #include -#if ASC_LINUX_KERNEL24 #include -#elif ASC_LINUX_KERNEL22 -#include -#endif + +#include +#include +#include + #include "scsi.h" #include "hosts.h" #include "advansys.h" @@ -5099,7 +5097,6 @@ ep->adapter_info[3] = asc_dvc_varp->cfg->adapter_info[3]; ep->adapter_info[4] = asc_dvc_varp->cfg->adapter_info[4]; ep->adapter_info[5] = asc_dvc_varp->cfg->adapter_info[5]; - ep->adapter_info[6] = asc_dvc_varp->cfg->adapter_info[6]; /* * Modify board configuration. diff -Nru a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c --- a/drivers/scsi/aha1542.c Fri Nov 22 13:41:20 2002 +++ b/drivers/scsi/aha1542.c Fri Nov 22 13:41:20 2002 @@ -27,28 +27,26 @@ #include #include - +#include #include #include #include #include #include -#include #include #include #include #include #include +#include +#include + #include #include #include -#include -#include #include "scsi.h" #include "hosts.h" - - #include "aha1542.h" #define SCSI_BUF_PA(address) isa_virt_to_bus(address) diff -Nru a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c --- a/drivers/scsi/aha1740.c Fri Nov 22 13:41:18 2002 +++ b/drivers/scsi/aha1740.c Fri Nov 22 13:41:18 2002 @@ -30,23 +30,23 @@ * are deemed to be part of the source code. */ +#include +#include #include #include #include #include #include #include -#include -#include +#include +#include #include #include -#include + #include "scsi.h" #include "hosts.h" - #include "aha1740.h" -#include /* IF YOU ARE HAVING PROBLEMS WITH THIS DRIVER, AND WANT TO WATCH IT WORK, THEN: diff -Nru a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c --- a/drivers/scsi/aic7xxx_old.c Fri Nov 22 13:41:19 2002 +++ b/drivers/scsi/aic7xxx_old.c Fri Nov 22 13:41:19 2002 @@ -238,6 +238,7 @@ #include #include #include +#include #include "scsi.h" #include "hosts.h" #include "aic7xxx_old/aic7xxx.h" diff -Nru a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c --- a/drivers/scsi/atp870u.c Fri Nov 22 13:41:19 2002 +++ b/drivers/scsi/atp870u.c Fri Nov 22 13:41:19 2002 @@ -17,26 +17,24 @@ */ #include - +#include #include #include #include #include #include -#include #include #include -#include -#include #include #include -#include "scsi.h" -#include "hosts.h" +#include +#include +#include +#include "scsi.h" +#include "hosts.h" #include "atp870u.h" - -#include /* * static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/atp870u.c,v 1.0 1997/05/07 15:22:00 root Exp root $"; diff -Nru a/drivers/scsi/cpqfcTSinit.c b/drivers/scsi/cpqfcTSinit.c --- a/drivers/scsi/cpqfcTSinit.c Fri Nov 22 13:41:17 2002 +++ b/drivers/scsi/cpqfcTSinit.c Fri Nov 22 13:41:17 2002 @@ -31,20 +31,21 @@ #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) +#include +#include +#include +#include #include #include #include -#include #include #include #include #include #include #include // request_region() prototype -#include // ioremap() -//#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,7) #include -//#endif + #ifdef __alpha__ #define __KERNEL_SYSCALLS__ #endif @@ -61,10 +62,6 @@ #include "cpqfcTStrigger.h" #include "cpqfcTS.h" - -#include -#include -#include /* Embedded module documentation macros - see module.h */ MODULE_AUTHOR("Compaq Computer Corporation"); diff -Nru a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c --- a/drivers/scsi/dpt_i2o.c Fri Nov 22 13:41:22 2002 +++ b/drivers/scsi/dpt_i2o.c Fri Nov 22 13:41:22 2002 @@ -112,9 +112,9 @@ static int hba_count = 0; static struct file_operations adpt_fops = { - ioctl: adpt_ioctl, - open: adpt_open, - release: adpt_close + .ioctl = adpt_ioctl, + .open = adpt_open, + .release = adpt_close }; #ifdef REBOOT_NOTIFIER diff -Nru a/drivers/scsi/esp.c b/drivers/scsi/esp.c --- a/drivers/scsi/esp.c Fri Nov 22 13:41:23 2002 +++ b/drivers/scsi/esp.c Fri Nov 22 13:41:23 2002 @@ -24,6 +24,7 @@ #include #include #include +#include #include "scsi.h" #include "hosts.h" @@ -1931,15 +1932,12 @@ ESPLOG(("\n")); } -/* Abort a command. */ +/* Abort a command. The host_lock is acquired by caller. */ static int esp_abort(Scsi_Cmnd *SCptr) { struct esp *esp = (struct esp *) SCptr->host->hostdata; - unsigned long flags; int don; - spin_lock_irqsave(esp->ehost->host_lock, flags); - ESPLOG(("esp%d: Aborting command\n", esp->esp_id)); esp_dump_state(esp); @@ -1954,7 +1952,6 @@ esp->msgout_len = 1; esp->msgout_ctr = 0; esp_cmd(esp, ESP_CMD_SATN); - spin_unlock_irqrestore(esp->ehost->host_lock, flags); return SUCCESS; } @@ -1983,7 +1980,6 @@ if (don) ESP_INTSON(esp->dregs); - spin_unlock_irqrestore(esp->ehost->host_lock, flags); return SUCCESS; } } @@ -1997,7 +1993,6 @@ if (esp->current_SC) { if (don) ESP_INTSON(esp->dregs); - spin_unlock_irqrestore(esp->ehost->host_lock, flags); return FAILED; } @@ -2010,7 +2005,7 @@ if (don) ESP_INTSON(esp->dregs); - spin_unlock_irqrestore(esp->ehost->host_lock, flags); + return FAILED; } @@ -2067,17 +2062,20 @@ /* Reset ESP chip, reset hanging bus, then kill active and * disconnected commands for targets without soft reset. + * + * The host_lock is acquired by caller. */ static int esp_reset(Scsi_Cmnd *SCptr) { struct esp *esp = (struct esp *) SCptr->host->hostdata; - unsigned long flags; - spin_lock_irqsave(esp->ehost->host_lock, flags); (void) esp_do_resetbus(esp); - spin_unlock_irqrestore(esp->ehost->host_lock, flags); + + spin_unlock_irq(esp->ehost->host_lock); wait_event(esp->reset_queue, (esp->resetting_bus == 0)); + + spin_lock_irq(esp->ehost->host_lock); return SUCCESS; } diff -Nru a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c --- a/drivers/scsi/fd_mcs.c Fri Nov 22 13:41:19 2002 +++ b/drivers/scsi/fd_mcs.c Fri Nov 22 13:41:19 2002 @@ -78,8 +78,7 @@ **************************************************************************/ #include - -#include +#include #include #include #include @@ -88,6 +87,7 @@ #include #include #include + #include #include diff -Nru a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c --- a/drivers/scsi/fdomain.c Fri Nov 22 13:41:22 2002 +++ b/drivers/scsi/fdomain.c Fri Nov 22 13:41:22 2002 @@ -277,14 +277,10 @@ #undef MODULE #endif +#include /* for CONFIG_PCI */ #include -#include -#include +#include #include -#include "scsi.h" -#include "hosts.h" -#include "fdomain.h" -#include #include #include #include @@ -294,7 +290,12 @@ #include #include -#include /* for CONFIG_PCI */ +#include +#include + +#include "scsi.h" +#include "hosts.h" +#include "fdomain.h" #define VERSION "$Revision: 5.50 $" diff -Nru a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c --- a/drivers/scsi/hosts.c Fri Nov 22 13:41:17 2002 +++ b/drivers/scsi/hosts.c Fri Nov 22 13:41:17 2002 @@ -669,6 +669,67 @@ } } +/* + * Function: scsi_get_host_dev() + * + * Purpose: Create a Scsi_Device that points to the host adapter itself. + * + * Arguments: SHpnt - Host that needs a Scsi_Device + * + * Lock status: None assumed. + * + * Returns: The Scsi_Device or NULL + * + * Notes: + * Attach a single Scsi_Device to the Scsi_Host - this should + * be made to look like a "pseudo-device" that points to the + * HA itself. For the moment, we include it at the head of + * the host_queue itself - I don't think we want to show this + * to the HA in select_queue_depths(), as this would probably confuse + * matters. + * + * Note - this device is not accessible from any high-level + * drivers (including generics), which is probably not + * optimal. We can add hooks later to attach + */ +struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) +{ + struct scsi_device *sdev; + + sdev = scsi_alloc_sdev(shost, 0, shost->this_id, 0); + if (sdev) { + scsi_build_commandblocks(sdev); + if (sdev->current_queue_depth == 0) + goto fail; + sdev->borken = 0; + } + + return sdev; + +fail: + kfree(sdev); + return NULL; +} + +/* + * Function: scsi_free_host_dev() + * + * Purpose: Free a scsi_device that points to the host adapter itself. + * + * Arguments: SHpnt - Host that needs a Scsi_Device + * + * Lock status: None assumed. + * + * Returns: Nothing + * + * Notes: + */ +void scsi_free_host_dev(struct scsi_device *sdev) +{ + BUG_ON(sdev->id != sdev->host->this_id); + scsi_free_sdev(sdev); +} + void scsi_host_busy_inc(struct Scsi_Host *shost, Scsi_Device *sdev) { unsigned long flags; diff -Nru a/drivers/scsi/hosts.h b/drivers/scsi/hosts.h --- a/drivers/scsi/hosts.h Fri Nov 22 13:41:18 2002 +++ b/drivers/scsi/hosts.h Fri Nov 22 13:41:18 2002 @@ -500,15 +500,6 @@ extern void scsi_unblock_requests(struct Scsi_Host *); extern void scsi_block_requests(struct Scsi_Host *); extern void scsi_report_bus_reset(struct Scsi_Host *, int); - -typedef struct SHN -{ - struct list_head shn_list; - char *name; - unsigned short host_no; - unsigned short host_registered; -} Scsi_Host_Name; - extern void scsi_register_blocked_host(struct Scsi_Host *); extern void scsi_deregister_blocked_host(struct Scsi_Host *); diff -Nru a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c --- a/drivers/scsi/ibmmca.c Fri Nov 22 13:41:18 2002 +++ b/drivers/scsi/ibmmca.c Fri Nov 22 13:41:18 2002 @@ -17,6 +17,7 @@ */ +#include #ifndef LINUX_VERSION_CODE #include #endif @@ -28,22 +29,23 @@ #include #include #include +#include #include #include -#include #include #include #include #include #include -#include #include -#include #include + +#include +#include + #include "scsi.h" #include "hosts.h" #include "ibmmca.h" -#include /* current version of this driver-source: */ #define IBMMCA_SCSI_DRIVER_VERSION "4.0b-ac" @@ -1396,9 +1398,8 @@ io_base = 0; id_base = 0; if (str) { - token = strtok(str, ","); j = 0; - while (token) { + while ((token = strsep(&str, ",")) != NULL) { if (!strcmp(token, "activity")) display_mode |= LED_ACTIVITY; if (!strcmp(token, "display")) @@ -1422,7 +1423,6 @@ scsi_id[id_base++] = simple_strtoul(token, NULL, 0); j++; } - token = strtok(NULL, ","); } } else if (ints) { for (i = 0; i < IM_MAX_HOSTS && 2 * i + 2 < ints[0]; i++) { diff -Nru a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c --- a/drivers/scsi/ide-scsi.c Fri Nov 22 13:41:21 2002 +++ b/drivers/scsi/ide-scsi.c Fri Nov 22 13:41:21 2002 @@ -859,20 +859,20 @@ } static Scsi_Host_Template idescsi_template = { - module: THIS_MODULE, - name: "idescsi", - detect: idescsi_detect, - release: idescsi_release, - info: idescsi_info, - ioctl: idescsi_ioctl, - queuecommand: idescsi_queue, - bios_param: idescsi_bios, - can_queue: 10, - this_id: -1, - sg_tablesize: 256, - cmd_per_lun: 5, - use_clustering: DISABLE_CLUSTERING, - emulated: 1, + .module = THIS_MODULE, + .name = "idescsi", + .detect = idescsi_detect, + .release = idescsi_release, + .info = idescsi_info, + .ioctl = idescsi_ioctl, + .queuecommand = idescsi_queue, + .bios_param = idescsi_bios, + .can_queue = 10, + .this_id = -1, + .sg_tablesize = 256, + .cmd_per_lun = 5, + .use_clustering = DISABLE_CLUSTERING, + .emulated = 1, }; static int __init init_idescsi_module(void) diff -Nru a/drivers/scsi/imm.c b/drivers/scsi/imm.c --- a/drivers/scsi/imm.c Fri Nov 22 13:41:23 2002 +++ b/drivers/scsi/imm.c Fri Nov 22 13:41:23 2002 @@ -47,17 +47,9 @@ } imm_struct; #define IMM_EMPTY \ -{ dev: NULL, \ - base: -1, \ - base_hi: 0, \ - mode: IMM_AUTODETECT, \ - host: -1, \ - cur_cmd: NULL, \ - jstart: 0, \ - failed: 0, \ - dp: 0, \ - rd: 0, \ - p_busy: 0 \ +{ .base = -1, \ + .mode = IMM_AUTODETECT, \ + .host = -1, \ } #include "imm.h" diff -Nru a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c --- a/drivers/scsi/in2000.c Fri Nov 22 13:41:22 2002 +++ b/drivers/scsi/in2000.c Fri Nov 22 13:41:22 2002 @@ -114,18 +114,17 @@ */ #include - -#include -#include +#include +#include +#include #include #include #include -#include #include -#include - -#include #include + +#include +#include #include "scsi.h" #include "hosts.h" diff -Nru a/drivers/scsi/inia100.c b/drivers/scsi/inia100.c --- a/drivers/scsi/inia100.c Fri Nov 22 13:41:18 2002 +++ b/drivers/scsi/inia100.c Fri Nov 22 13:41:18 2002 @@ -75,9 +75,9 @@ #include -#include #include #include +#include #include #include #include @@ -86,12 +86,15 @@ #include #include #include -#include +//#include +#include #include + #include +#include + #include "scsi.h" #include "hosts.h" -#include #include "inia100.h" static Scsi_Host_Template driver_template = INIA100; diff -Nru a/drivers/scsi/ips.c b/drivers/scsi/ips.c --- a/drivers/scsi/ips.c Fri Nov 22 13:41:17 2002 +++ b/drivers/scsi/ips.c Fri Nov 22 13:41:17 2002 @@ -317,24 +317,24 @@ static void __devexit ips_remove_device(struct pci_dev *pci_dev); struct pci_driver ips_pci_driver = { - name: ips_hot_plug_name, - id_table: ips_pci_table, - probe: ips_insert_device, - remove: __devexit_p(ips_remove_device), + .name = ips_hot_plug_name, + .id_table = ips_pci_table, + .probe = ips_insert_device, + .remove = __devexit_p(ips_remove_device), }; struct pci_driver ips_pci_driver_5i = { - name: ips_hot_plug_name, - id_table: ips_pci_table_5i, - probe: ips_insert_device, - remove: __devexit_p(ips_remove_device), + .name = ips_hot_plug_name, + .id_table = ips_pci_table_5i, + .probe = ips_insert_device, + .remove = __devexit_p(ips_remove_device), }; struct pci_driver ips_pci_driver_i960 = { - name: ips_hot_plug_name, - id_table: ips_pci_table_i960, - probe: ips_insert_device, - remove: __devexit_p(ips_remove_device), + .name = ips_hot_plug_name, + .id_table = ips_pci_table_i960, + .probe = ips_insert_device, + .remove = __devexit_p(ips_remove_device), }; #endif diff -Nru a/drivers/scsi/mca_53c9x.c b/drivers/scsi/mca_53c9x.c --- a/drivers/scsi/mca_53c9x.c Fri Nov 22 13:41:18 2002 +++ b/drivers/scsi/mca_53c9x.c Fri Nov 22 13:41:18 2002 @@ -30,8 +30,10 @@ * look. */ -#include #include +#include +#include +#include #include #include #include @@ -45,10 +47,8 @@ #include "mca_53c9x.h" #include -#include #include #include - #include static int dma_bytes_sent(struct NCR_ESP *, int); diff -Nru a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c --- a/drivers/scsi/nsp32.c Fri Nov 22 13:41:19 2002 +++ b/drivers/scsi/nsp32.c Fri Nov 22 13:41:19 2002 @@ -2066,53 +2066,53 @@ static struct pci_device_id nsp32_pci_table[] __devinitdata = { { - vendor: PCI_VENDOR_ID_IODATA, - device: PCI_DEVICE_ID_NINJASCSI_32BI_CBSC_II, - subvendor: PCI_ANY_ID, - subdevice: PCI_ANY_ID, - driver_data: MODEL_IODATA, + .vendor = PCI_VENDOR_ID_IODATA, + .device = PCI_DEVICE_ID_NINJASCSI_32BI_CBSC_II, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = MODEL_IODATA, }, { - vendor: PCI_VENDOR_ID_WORKBIT, - device: PCI_DEVICE_ID_NINJASCSI_32BI_KME, - subvendor: PCI_ANY_ID, - subdevice: PCI_ANY_ID, - driver_data: MODEL_KME, + .vendor = PCI_VENDOR_ID_WORKBIT, + .device = PCI_DEVICE_ID_NINJASCSI_32BI_KME, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = MODEL_KME, }, { - vendor: PCI_VENDOR_ID_WORKBIT, - device: PCI_DEVICE_ID_NINJASCSI_32BI_WBT, - subvendor: PCI_ANY_ID, - subdevice: PCI_ANY_ID, - driver_data: MODEL_WORKBIT, + .vendor = PCI_VENDOR_ID_WORKBIT, + .device = PCI_DEVICE_ID_NINJASCSI_32BI_WBT, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = MODEL_WORKBIT, }, { - vendor: PCI_VENDOR_ID_WORKBIT, - device: PCI_DEVICE_ID_WORKBIT_STANDARD, - subvendor: PCI_ANY_ID, - subdevice: PCI_ANY_ID, - driver_data: MODEL_PCI_WORKBIT, + .vendor = PCI_VENDOR_ID_WORKBIT, + .device = PCI_DEVICE_ID_WORKBIT_STANDARD, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = MODEL_PCI_WORKBIT, }, { - vendor: PCI_VENDOR_ID_WORKBIT, - device: PCI_DEVICE_ID_NINJASCSI_32BI_LOGITEC, - subvendor: PCI_ANY_ID, - subdevice: PCI_ANY_ID, - driver_data: MODEL_EXT_ROM, + .vendor = PCI_VENDOR_ID_WORKBIT, + .device = PCI_DEVICE_ID_NINJASCSI_32BI_LOGITEC, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = MODEL_EXT_ROM, }, { - vendor: PCI_VENDOR_ID_WORKBIT, - device: PCI_DEVICE_ID_NINJASCSI_32BIB_LOGITEC, - subvendor: PCI_ANY_ID, - subdevice: PCI_ANY_ID, - driver_data: MODEL_PCI_LOGITEC, + .vendor = PCI_VENDOR_ID_WORKBIT, + .device = PCI_DEVICE_ID_NINJASCSI_32BIB_LOGITEC, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = MODEL_PCI_LOGITEC, }, { - vendor: PCI_VENDOR_ID_WORKBIT, - device: PCI_DEVICE_ID_NINJASCSI_32UDE_MELCO, - subvendor: PCI_ANY_ID, - subdevice: PCI_ANY_ID, - driver_data: MODEL_PCI_MELCO, + .vendor = PCI_VENDOR_ID_WORKBIT, + .device = PCI_DEVICE_ID_NINJASCSI_32UDE_MELCO, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = MODEL_PCI_MELCO, }, {0,0,}, }; diff -Nru a/drivers/scsi/osst.c b/drivers/scsi/osst.c --- a/drivers/scsi/osst.c Fri Nov 22 13:41:19 2002 +++ b/drivers/scsi/osst.c Fri Nov 22 13:41:19 2002 @@ -160,13 +160,13 @@ struct Scsi_Device_Template osst_template = { - module: THIS_MODULE, - list: LIST_HEAD_INIT(osst_template.list), - name: "OnStream tape", - tag: "osst", - scsi_type: TYPE_TAPE, - attach: osst_attach, - detach: osst_detach + .module = THIS_MODULE, + .list = LIST_HEAD_INIT(osst_template.list), + .name = "OnStream tape", + .tag = "osst", + .scsi_type = TYPE_TAPE, + .attach = osst_attach, + .detach = osst_detach }; static int osst_int_ioctl(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, unsigned int cmd_in,unsigned long arg); @@ -5354,12 +5354,12 @@ static struct file_operations osst_fops = { - read: osst_read, - write: osst_write, - ioctl: osst_ioctl, - open: os_scsi_tape_open, - flush: os_scsi_tape_flush, - release: os_scsi_tape_close, + .read = osst_read, + .write = osst_write, + .ioctl = osst_ioctl, + .open = os_scsi_tape_open, + .flush = os_scsi_tape_flush, + .release = os_scsi_tape_close, }; static int osst_supports(Scsi_Device * SDp) diff -Nru a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c --- a/drivers/scsi/ppa.c Fri Nov 22 13:41:21 2002 +++ b/drivers/scsi/ppa.c Fri Nov 22 13:41:21 2002 @@ -38,16 +38,11 @@ } ppa_struct; #define PPA_EMPTY \ -{ dev: NULL, \ - base: -1, \ - mode: PPA_AUTODETECT, \ - host: -1, \ - cur_cmd: NULL, \ - ppa_tq: { func: ppa_interrupt }, \ - jstart: 0, \ - recon_tmo: PPA_RECON_TMO, \ - failed: 0, \ - p_busy: 0 \ +{ .base = -1, \ + .mode = PPA_AUTODETECT, \ + .host = -1, \ + .ppa_tq = { .func = ppa_interrupt }, \ + .recon_tmo = PPA_RECON_TMO, \ } #include "ppa.h" diff -Nru a/drivers/scsi/psi240i.c b/drivers/scsi/psi240i.c --- a/drivers/scsi/psi240i.c Fri Nov 22 13:41:21 2002 +++ b/drivers/scsi/psi240i.c Fri Nov 22 13:41:21 2002 @@ -26,25 +26,25 @@ #include +#include #include #include #include #include #include -#include +#include #include #include +#include + #include #include #include -#include #include "scsi.h" #include "hosts.h" #include "psi240i.h" #include "psi_chip.h" - -#include //#define DEBUG 1 diff -Nru a/drivers/scsi/qlogicfas.c b/drivers/scsi/qlogicfas.c --- a/drivers/scsi/qlogicfas.c Fri Nov 22 13:41:23 2002 +++ b/drivers/scsi/qlogicfas.c Fri Nov 22 13:41:23 2002 @@ -136,17 +136,19 @@ #include #include #include +#include #include -#include #include #include #include +#include + #include #include + #include "scsi.h" #include "hosts.h" #include "qlogicfas.h" -#include /*----------------------------------------------------------------*/ /* driver state info, local to driver */ diff -Nru a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c --- a/drivers/scsi/qlogicfc.c Fri Nov 22 13:41:22 2002 +++ b/drivers/scsi/qlogicfc.c Fri Nov 22 13:41:22 2002 @@ -60,6 +60,7 @@ #include #include #include +#include #include #include #include "scsi.h" diff -Nru a/drivers/scsi/qlogicisp.c b/drivers/scsi/qlogicisp.c --- a/drivers/scsi/qlogicisp.c Fri Nov 22 13:41:23 2002 +++ b/drivers/scsi/qlogicisp.c Fri Nov 22 13:41:23 2002 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include diff -Nru a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c --- a/drivers/scsi/qlogicpti.c Fri Nov 22 13:41:21 2002 +++ b/drivers/scsi/qlogicpti.c Fri Nov 22 13:41:21 2002 @@ -22,6 +22,7 @@ #include #include #include +#include #include diff -Nru a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c --- a/drivers/scsi/scsi.c Fri Nov 22 13:41:20 2002 +++ b/drivers/scsi/scsi.c Fri Nov 22 13:41:20 2002 @@ -155,7 +155,6 @@ "Enclosure ", }; -static char * scsi_null_device_strs = "nullnullnullnull"; static const char * const spaces = " "; /* 16 of them */ static unsigned scsi_default_dev_flags; @@ -2199,8 +2198,8 @@ } struct bus_type scsi_driverfs_bus_type = { - name: "scsi", - match: scsi_bus_match, + .name = "scsi", + .match = scsi_bus_match, }; static int __init init_scsi(void) @@ -2225,6 +2224,8 @@ printk(KERN_ERR "SCSI: can't init sg mempool %s\n", sgp->name); } + scsi_init_procfs(); + scsi_devfs_handle = devfs_mk_dir(NULL, "scsi", NULL); scsi_host_init(); scsi_dev_info_list_init(scsi_dev_flags); bus_register(&scsi_driverfs_bus_type); @@ -2236,9 +2237,10 @@ { int i; + bus_unregister(&scsi_driverfs_bus_type); + scsi_dev_info_list_delete(); devfs_unregister(scsi_devfs_handle); scsi_exit_procfs(); - scsi_dev_info_list_delete(); for (i = 0; i < SG_MEMPOOL_NR; i++) { struct scsi_host_sg_pool *sgp = scsi_sg_pools + i; @@ -2251,95 +2253,3 @@ module_init(init_scsi); module_exit(exit_scsi); - -/* - * Function: scsi_get_host_dev() - * - * Purpose: Create a Scsi_Device that points to the host adapter itself. - * - * Arguments: SHpnt - Host that needs a Scsi_Device - * - * Lock status: None assumed. - * - * Returns: The Scsi_Device or NULL - * - * Notes: - */ -Scsi_Device * scsi_get_host_dev(struct Scsi_Host * SHpnt) -{ - Scsi_Device * SDpnt; - - /* - * Attach a single Scsi_Device to the Scsi_Host - this should - * be made to look like a "pseudo-device" that points to the - * HA itself. For the moment, we include it at the head of - * the host_queue itself - I don't think we want to show this - * to the HA in select_queue_depths(), as this would probably confuse - * matters. - * Note - this device is not accessible from any high-level - * drivers (including generics), which is probably not - * optimal. We can add hooks later to attach - */ - SDpnt = (Scsi_Device *) kmalloc(sizeof(Scsi_Device), - GFP_ATOMIC); - if(SDpnt == NULL) - return NULL; - - memset(SDpnt, 0, sizeof(Scsi_Device)); - SDpnt->vendor = scsi_null_device_strs; - SDpnt->model = scsi_null_device_strs; - SDpnt->rev = scsi_null_device_strs; - - SDpnt->host = SHpnt; - SDpnt->id = SHpnt->this_id; - SDpnt->type = -1; - SDpnt->new_queue_depth = 1; - - scsi_build_commandblocks(SDpnt); - if(SDpnt->current_queue_depth == 0) { - kfree(SDpnt); - return NULL; - } - - scsi_initialize_queue(SDpnt, SHpnt); - - SDpnt->online = TRUE; - - /* - * Initialize the object that we will use to wait for command blocks. - */ - init_waitqueue_head(&SDpnt->scpnt_wait); - return SDpnt; -} - -/* - * Function: scsi_free_host_dev() - * - * Purpose: Create a Scsi_Device that points to the host adapter itself. - * - * Arguments: SHpnt - Host that needs a Scsi_Device - * - * Lock status: None assumed. - * - * Returns: Nothing - * - * Notes: - */ -void scsi_free_host_dev(Scsi_Device * SDpnt) -{ - if( (unsigned char) SDpnt->id != (unsigned char) SDpnt->host->this_id ) - { - panic("Attempt to delete wrong device\n"); - } - - blk_cleanup_queue(&SDpnt->request_queue); - - /* - * We only have a single SCpnt attached to this device. Free - * it now. - */ - scsi_release_commandblocks(SDpnt); - if (SDpnt->inquiry) - kfree(SDpnt->inquiry); - kfree(SDpnt); -} diff -Nru a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h --- a/drivers/scsi/scsi.h Fri Nov 22 13:41:18 2002 +++ b/drivers/scsi/scsi.h Fri Nov 22 13:41:18 2002 @@ -18,6 +18,8 @@ #include /* for CONFIG_SCSI_LOGGING */ #include #include +#include + /* * Some of the public constants are being moved to this file. @@ -516,6 +518,13 @@ static inline void scsi_proc_host_add(struct Scsi_Host *); static inline void scsi_proc_host_rm(struct Scsi_Host *); #endif /* CONFIG_PROC_FS */ + +/* + * Prototypes for functions in scsi_scan.c + */ +extern struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *, + uint, uint, uint); +extern void scsi_free_sdev(struct scsi_device *); /* * Prototypes for functions in constants.c diff -Nru a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c --- a/drivers/scsi/scsi_debug.c Fri Nov 22 13:41:21 2002 +++ b/drivers/scsi/scsi_debug.c Fri Nov 22 13:41:21 2002 @@ -19,6 +19,7 @@ * use vmalloc() more inquiry+mode_sense [20020302] * add timers for delayed responses [20020721] * Patrick Mansfield max_luns+scsi_level [20021031] + * Mike Anderson sysfs work [20021118] */ #include @@ -40,6 +41,7 @@ #include #include "scsi.h" #include "hosts.h" +#include #include @@ -49,7 +51,7 @@ #include "scsi_debug.h" -static const char * scsi_debug_version_str = "Version: 1.64 (20021111 2)"; +static const char * scsi_debug_version_str = "Version: 1.65 (20021119)"; #ifndef SCSI_CMD_READ_16 #define SCSI_CMD_READ_16 0x88 @@ -60,24 +62,26 @@ #define SDEBUG_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */ -/* A few options that we want selected */ +/* Default values for driver parameters */ #define DEF_NR_FAKE_DEVS 1 #define DEF_DEV_SIZE_MB 8 -#define DEF_FAKE_BLK0 0 #define DEF_EVERY_NTH 100 #define DEF_DELAY 1 #define DEF_MAX_LUNS 2 #define DEF_SCSI_LEVEL 3 #define DEF_NUM_HOST 1 +#define DEF_OPTS 0 + #define MAX_NUM_HOSTS 128 -#define DEF_OPTS 0 +/* bit mask values for scsi_debug_opts */ #define SCSI_DEBUG_OPT_NOISE 1 #define SCSI_DEBUG_OPT_MEDIUM_ERR 2 #define SCSI_DEBUG_OPT_EVERY_NTH 4 #define OPT_MEDIUM_ERR_ADDR 0x1234 +static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB; static int scsi_debug_num_devs = DEF_NR_FAKE_DEVS; static int scsi_debug_opts = DEF_OPTS; static int scsi_debug_every_nth = DEF_EVERY_NTH; @@ -87,27 +91,30 @@ static int scsi_debug_scsi_level = DEF_SCSI_LEVEL; static int scsi_debug_add_host = DEF_NUM_HOST; - /* This assumes one lun used per allocated target id */ -#define N_HEAD 8 -#define N_SECTOR 32 #define DEV_READONLY(TGT) (0) #define DEV_REMOVEABLE(TGT) (0) #define PERIPH_DEVICE_TYPE(TGT) (TYPE_DISK); -static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB; -#define STORE_SIZE (scsi_debug_dev_size_mb * 1024 * 1024) +static unsigned long sdebug_store_size; /* in bytes */ +static sector_t sdebug_capacity; /* in sectors */ + +/* old BIOS stuff, kernel may get rid of them but some mode sense pages + may still need them */ +static int sdebug_heads; /* heads per disk */ +static int sdebug_cylinders_per; /* cylinders per surface */ +static int sdebug_sectors_per; /* sectors per cylinder */ /* default sector size is 512 bytes, 2**9 bytes */ #define POW2_SECT_SIZE 9 #define SECT_SIZE (1 << POW2_SECT_SIZE) - -#define N_CYLINDER (STORE_SIZE / (SECT_SIZE * N_SECTOR * N_HEAD)) - -/* Time to wait before completing a command */ -#define CAPACITY (N_HEAD * N_SECTOR * N_CYLINDER) #define SECT_SIZE_PER(TGT) SECT_SIZE -struct Scsi_Host *scsi_debug_hosts[MAX_NUM_HOSTS]; +struct sdebug_host_info { + struct Scsi_Host *shost; + struct device *dev; +}; + +struct sdebug_host_info * scsi_debug_hosts; #define SDEBUG_SENSE_LEN 32 @@ -145,7 +152,10 @@ static spinlock_t queued_arr_lock = SPIN_LOCK_UNLOCKED; static rwlock_t atomic_rw = RW_LOCK_UNLOCKED; -static struct device_driver sdebug_driverfs_driver; +static char sdebug_proc_name[] = "scsi_debug"; +static struct device_driver sdebug_driverfs_driver = { + .name = sdebug_proc_name, +}; /* function declarations */ static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff, @@ -175,8 +185,15 @@ const char * dev_id_str, int dev_id_str_len); static void do_create_driverfs_files(void); static void do_remove_driverfs_files(void); -static struct Scsi_Host * sdebug_add_shost(void); +static void sdebug_add_shost(int num); +static void sdebug_remove_shost(int num); +static int sdebug_add_adapter(int num); +static void sdebug_remove_adapter(int num); +static struct device pseudo_primary; +static struct bus_type pseudo_lld_bus; +int scsi_debug_register_driver(struct device_driver *); +int scsi_debug_unregister_driver(struct device_driver *); static unsigned char * scatg2virt(const struct scatterlist * sclp) { @@ -193,13 +210,12 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) { unsigned char *cmd = (unsigned char *) SCpnt->cmnd; - int block; - int upper_blk; + int block, upper_blk, num; unsigned char *buff; int errsts = 0; int target = SCpnt->target; int bufflen = SCpnt->request_bufflen; - int num, capac; + unsigned long capac; struct sdebug_dev_info * devip = NULL; unsigned char * sbuff; @@ -230,11 +246,6 @@ if (SCpnt->lun >= scsi_debug_max_luns) return schedule_resp(SCpnt, NULL, done, DID_NO_CONNECT << 16, 0); -#if 0 - printk(KERN_INFO "sdebug:qc: host_no=%u, id=%u, sdp=%p, cmd=0x%x\n", - (int)SCpnt->device->host->host_no, (int)SCpnt->device->id, - SCpnt->device, (int)*cmd); -#endif devip = devInfoReg(SCpnt); if (NULL == devip) return schedule_resp(SCpnt, NULL, done, @@ -302,7 +313,7 @@ errsts = check_reset(SCpnt, devip); memset(buff, 0, bufflen); if (bufflen > 7) { - capac = CAPACITY - 1; + capac = (unsigned long)sdebug_capacity - 1; buff[0] = (capac >> 24); buff[1] = (capac >> 16) & 0xff; buff[2] = (capac >> 8) & 0xff; @@ -382,10 +393,6 @@ memset(buff, 0, bufflen); break; default: -#if 0 - printk(KERN_INFO "scsi_debug: Unsupported command, " - "opcode=0x%x\n", (int)cmd[0]); -#endif if ((errsts = check_reset(SCpnt, devip))) break; mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x20, 0, 14); @@ -543,8 +550,8 @@ 0, 0, 0, 0, 0x40, 0, 0, 0}; memcpy(p, format_pg, sizeof(format_pg)); - p[10] = (N_SECTOR >> 8) & 0xff; - p[11] = N_SECTOR & 0xff; + p[10] = (sdebug_sectors_per >> 8) & 0xff; + p[11] = sdebug_sectors_per & 0xff; p[12] = (SECT_SIZE >> 8) & 0xff; p[13] = SECT_SIZE & 0xff; if (DEV_REMOVEABLE(target)) @@ -673,7 +680,7 @@ int bufflen = SCpnt->request_bufflen; unsigned long iflags; - if (upper_blk || (block + num > CAPACITY)) { + if (upper_blk || (block + num > sdebug_capacity)) { mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x21, 0, 14); return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1); } @@ -722,7 +729,7 @@ int bufflen = SCpnt->request_bufflen; unsigned long iflags; - if (upper_blk || (block + num > CAPACITY)) { + if (upper_blk || (block + num > sdebug_capacity)) { mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x21, 0, 14); return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1); } @@ -805,8 +812,6 @@ spin_unlock_irqrestore(&queued_arr_lock, iflags); } -static const char * sdebug_proc_name = "scsi_debug"; - static int scsi_debug_slave_attach(struct scsi_device * sdp) { int k; @@ -910,14 +915,22 @@ static int scsi_debug_biosparam(struct scsi_device *sdev, struct block_device * bdev, sector_t capacity, int *info) { + int res; + unsigned char *buf; + if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) printk(KERN_INFO "scsi_debug: biosparam\n"); - /* int size = capacity; */ - info[0] = N_HEAD; - info[1] = N_SECTOR; - info[2] = N_CYLINDER; - if (info[2] >= 1024) - info[2] = 1024; + buf = scsi_bios_ptable(bdev); + if (buf) { + res = scsi_partsize(buf, capacity, + &info[2], &info[0], &info[1]); + kfree(buf); + if (! res) + return res; + } + info[0] = sdebug_heads; + info[1] = sdebug_sectors_per; + info[2] = sdebug_cylinders_per; return 0; } @@ -1289,7 +1302,7 @@ scsi_debug_dev_size_mb, scsi_debug_opts, scsi_debug_every_nth, scsi_debug_cmnd_count, scsi_debug_delay, scsi_debug_max_luns, scsi_debug_scsi_level, - SECT_SIZE, N_CYLINDER, N_HEAD, N_SECTOR, + SECT_SIZE, sdebug_cylinders_per, sdebug_heads, sdebug_sectors_per, num_aborts, num_dev_resets, num_bus_resets, num_host_resets); if (pos < offset) { len = 0; @@ -1402,7 +1415,6 @@ static ssize_t sdebug_add_host_write(struct device_driver * ddp, const char * buf, size_t count, loff_t off) { - struct Scsi_Host * hpnt; int delta_hosts, k; char work[20]; @@ -1410,14 +1422,21 @@ return 0; if (1 != sscanf(buf, "%10s", work)) return -EINVAL; - if (1 != sscanf(work, "%d", &delta_hosts)) - return -EINVAL; + { /* temporary hack around sscanf() problem with -ve nums */ + int neg = 0; + + if ('-' == *work) + neg = 1; + if (1 != sscanf(work + neg, "%d", &delta_hosts)) + return -EINVAL; + if (neg) + delta_hosts = -delta_hosts; + } if (delta_hosts > 0) { do { for (k = 0; k < MAX_NUM_HOSTS; ++k) { - if (NULL == scsi_debug_hosts[k]) { - hpnt = sdebug_add_shost(); - scsi_debug_hosts[k] = hpnt; + if (NULL == scsi_debug_hosts[k].shost) { + sdebug_add_shost(k); break; } } @@ -1428,10 +1447,8 @@ } else if (delta_hosts < 0) { do { for (k = MAX_NUM_HOSTS - 1; k >= 0; --k) { - if (scsi_debug_hosts[k]) { - scsi_remove_host(scsi_debug_hosts[k]); - scsi_unregister(scsi_debug_hosts[k]); - scsi_debug_hosts[k] = NULL; + if (scsi_debug_hosts[k].shost) { + sdebug_remove_shost(k); break; } } @@ -1469,30 +1486,65 @@ driver_remove_file(&sdebug_driverfs_driver, &driver_attr_delay); } -static struct Scsi_Host * sdebug_add_shost(void) +static void sdebug_add_shost(int num) { struct Scsi_Host * hpnt; int err; + if (sdebug_add_adapter(num)){ + printk(KERN_ERR "sdebug_add_shost: sdebug_add_adapter failed\n"); + return; + } hpnt = scsi_register(&sdebug_driver_template, 0); if (NULL == hpnt) { + sdebug_remove_adapter(num); printk(KERN_ERR "sdebug_add_shost: scsi_register failed\n"); - return NULL; + return; } err = scsi_add_host(hpnt); if (err) { printk(KERN_ERR "sdebug_add_shost: scsi_add_host failed\n"); scsi_unregister(hpnt); - return NULL; + sdebug_remove_adapter(num); + return; } hpnt->max_lun = scsi_debug_max_luns; - return hpnt; + + scsi_debug_hosts[num].shost = hpnt; } +static void sdebug_remove_shost(int num) +{ + scsi_remove_host(scsi_debug_hosts[num].shost); + scsi_unregister(scsi_debug_hosts[num].shost); + sdebug_remove_adapter(num); + scsi_debug_hosts[num].shost = NULL; +} static int __init scsi_debug_init(void) { - int sz, k; + unsigned long sz; + int k; + + sdebug_store_size = (unsigned long)scsi_debug_dev_size_mb * 1048576; + sdebug_capacity = sdebug_store_size / SECT_SIZE; + + /* play around with geometry, don't waste too much on track 0 */ + sdebug_heads = 8; + sdebug_sectors_per = 32; + if (scsi_debug_dev_size_mb >= 16) + sdebug_heads = 32; + else if (scsi_debug_dev_size_mb >= 256) + sdebug_heads = 64; + sdebug_cylinders_per = (unsigned long)sdebug_capacity / + (sdebug_sectors_per * sdebug_heads); + if (sdebug_cylinders_per >= 1024) { + /* other LLDs do this; implies >= 1GB ram disk ... */ + sdebug_heads = 255; + sdebug_sectors_per = 63; + sdebug_cylinders_per = (unsigned long)sdebug_capacity / + (sdebug_sectors_per * sdebug_heads); + } if (scsi_debug_num_devs > 0) { sz = sizeof(struct sdebug_dev_info) * scsi_debug_num_devs; @@ -1504,7 +1556,15 @@ memset(devInfop, 0, sz); } - sz = STORE_SIZE; + sz = sizeof(struct sdebug_host_info) * MAX_NUM_HOSTS; + scsi_debug_hosts = vmalloc(sz); + if (NULL == scsi_debug_hosts) { + printk(KERN_ERR "scsi_debug_init: out of memory 1\n"); + return -ENOMEM; + } + memset(scsi_debug_hosts, 0, sz); + + sz = sdebug_store_size; fake_storep = vmalloc(sz); if (NULL == fake_storep) { printk(KERN_ERR "scsi_debug_init: out of memory, 1\n"); @@ -1516,23 +1576,22 @@ init_all_queued(); - sdebug_driverfs_driver.name = (char *)sdebug_proc_name; - sdebug_driverfs_driver.bus = &scsi_driverfs_bus_type; - driver_register(&sdebug_driverfs_driver); + device_register(&pseudo_primary); + bus_register(&pseudo_lld_bus); + scsi_debug_register_driver(&sdebug_driverfs_driver); do_create_driverfs_files(); sdebug_driver_template.proc_name = (char *)sdebug_proc_name; - memset(scsi_debug_hosts, 0, sizeof(struct Scsi_Host *) * MAX_NUM_HOSTS); for (k = 0; (k < scsi_debug_add_host) && (k < MAX_NUM_HOSTS); k++) { - scsi_debug_hosts[k] = sdebug_add_shost(); - if (NULL == scsi_debug_hosts[k]) { + sdebug_add_shost(k); + if (NULL == scsi_debug_hosts[k].shost) { printk(KERN_ERR "scsi_debug_init: " "sdebug_add_shost failed k=%d\n", k); break; } } - scsi_debug_add_host = k; // number of hosts actually present + scsi_debug_add_host = k; // number of hosts actually present if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) { printk(KERN_INFO "scsi_debug: ... built %d host(s)\n", @@ -1546,20 +1605,78 @@ int k; for (k = MAX_NUM_HOSTS - 1; k >= 0; --k) { - if (scsi_debug_hosts[k]) { - scsi_remove_host(scsi_debug_hosts[k]); - scsi_unregister(scsi_debug_hosts[k]); - scsi_debug_hosts[k] = NULL; + if (scsi_debug_hosts[k].shost) { + sdebug_remove_shost(k); } } stop_all_queued(); do_remove_driverfs_files(); - driver_unregister(&sdebug_driverfs_driver); + scsi_debug_unregister_driver(&sdebug_driverfs_driver); + bus_unregister(&pseudo_lld_bus); + device_unregister(&pseudo_primary); vfree(fake_storep); if (devInfop) vfree(devInfop); } -module_init(scsi_debug_init); +device_initcall(scsi_debug_init); module_exit(scsi_debug_exit); + +static struct device pseudo_primary = { + .name = "Host/Pseudo Bridge", + .bus_id = "pseudo_0", +}; + +static int pseudo_lld_bus_match(struct device *dev, + struct device_driver *dev_driver) +{ + return 1; +} + +static struct bus_type pseudo_lld_bus = { + name: "pseudo", + match: pseudo_lld_bus_match, +}; + +int scsi_debug_register_driver(struct device_driver *dev_driver) +{ + dev_driver->bus = &pseudo_lld_bus; + driver_register(dev_driver); + + return 0; +} + +int scsi_debug_unregister_driver(struct device_driver *dev_driver) +{ + driver_unregister(dev_driver); + return 0; +} + +static int sdebug_add_adapter(int num) +{ + struct device * dev; + + dev = kmalloc(sizeof(*dev),GFP_KERNEL); + if (NULL == dev) { + printk(KERN_ERR "%s: out of memory\n", __FUNCTION__); + return 1; + } + + memset(dev, 0, sizeof(*dev)); + dev->bus = &pseudo_lld_bus; + dev->parent = &pseudo_primary; + sprintf(dev->name, "scsi debug adapter"); + sprintf(dev->bus_id, "adapter%d", num); + + device_register(dev); + + scsi_debug_hosts[num].dev = dev; + + return 0; +} + +static void sdebug_remove_adapter(int num) +{ + device_unregister(scsi_debug_hosts[num].dev); +} diff -Nru a/drivers/scsi/scsi_debug.h b/drivers/scsi/scsi_debug.h --- a/drivers/scsi/scsi_debug.h Fri Nov 22 13:41:20 2002 +++ b/drivers/scsi/scsi_debug.h Fri Nov 22 13:41:20 2002 @@ -43,6 +43,7 @@ .max_sectors = 4096, .unchecked_isa_dma = 0, .use_clustering = ENABLE_CLUSTERING, + .module = THIS_MODULE, }; #endif diff -Nru a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c --- a/drivers/scsi/scsi_error.c Fri Nov 22 13:41:17 2002 +++ b/drivers/scsi/scsi_error.c Fri Nov 22 13:41:17 2002 @@ -1479,8 +1479,6 @@ */ spin_lock_irqsave(shost->host_lock, flags); for (sdev = shost->host_queue; sdev; sdev = sdev->next) { - request_queue_t *q = &sdev->request_queue; - if ((shost->can_queue > 0 && (shost->host_busy >= shost->can_queue)) || (shost->host_blocked) @@ -1488,7 +1486,7 @@ break; } - q->request_fn(q); + __blk_run_queue(&sdev->request_queue); } spin_unlock_irqrestore(shost->host_lock, flags); } diff -Nru a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c --- a/drivers/scsi/scsi_lib.c Fri Nov 22 13:41:20 2002 +++ b/drivers/scsi/scsi_lib.c Fri Nov 22 13:41:20 2002 @@ -7,50 +7,19 @@ * of people at Linux Expo. */ -/* - * The fundamental purpose of this file is to contain a library of utility - * routines that can be used by low-level drivers. Ultimately the idea - * is that there should be a sufficiently rich number of functions that it - * would be possible for a driver author to fashion a queueing function for - * a low-level driver if they wished. Note however that this file also - * contains the "default" versions of these functions, as we don't want to - * go through and retrofit queueing functions into all 30 some-odd drivers. - */ - -#include - -#include -#include #include #include #include -#include #include -#include #include -#include -#include #include #include - -#define __KERNEL_SYSCALLS__ - -#include - -#include -#include -#include - #include "scsi.h" #include "hosts.h" #include /* - * This entire source file deals with the new queueing code. - */ - -/* * Function: scsi_insert_special_cmd() * * Purpose: Insert pre-formed command into request queue. @@ -259,7 +228,7 @@ /* * Just hit the requeue function for the queue. */ - q->request_fn(q); + __blk_run_queue(q); SDpnt = (Scsi_Device *) q->queuedata; SHpnt = SDpnt->host; @@ -272,8 +241,6 @@ * use function pointers to pick the right one. */ if (SDpnt->single_lun && blk_queue_empty(q) && SDpnt->device_busy ==0) { - request_queue_t *q; - for (SDpnt = SHpnt->host_queue; SDpnt; SDpnt = SDpnt->next) { if (((SHpnt->can_queue > 0) && (SHpnt->host_busy >= SHpnt->can_queue)) @@ -283,8 +250,7 @@ break; } - q = &SDpnt->request_queue; - q->request_fn(q); + __blk_run_queue(&SDpnt->request_queue); } } @@ -299,7 +265,6 @@ all_clear = 1; if (SHpnt->some_device_starved) { for (SDpnt = SHpnt->host_queue; SDpnt; SDpnt = SDpnt->next) { - request_queue_t *q; if ((SHpnt->can_queue > 0 && (SHpnt->host_busy >= SHpnt->can_queue)) || (SHpnt->host_blocked) || (SHpnt->host_self_blocked)) { @@ -308,8 +273,7 @@ if (SDpnt->device_blocked || !SDpnt->starved) { continue; } - q = &SDpnt->request_queue; - q->request_fn(q); + __blk_run_queue(&SDpnt->request_queue); all_clear = 0; } if (SDpnt == NULL && all_clear) { @@ -1021,10 +985,11 @@ break; if(!req) { - /* can happen if the prep fails - * FIXME: elv_next_request() should be plugging the - * queue */ - blk_plug_device(q); + /* If the device is busy, a returning I/O + * will restart the queue. Otherwise, we have + * to plug the queue */ + if(SDpnt->device_busy == 0) + blk_plug_device(q); break; } diff -Nru a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c --- a/drivers/scsi/scsi_proc.c Fri Nov 22 13:41:17 2002 +++ b/drivers/scsi/scsi_proc.c Fri Nov 22 13:41:17 2002 @@ -607,25 +607,9 @@ if (sdev->attached == 0) { devfs_unregister (sdev->de); - - /* Now we can remove the device structure */ - if (sdev->next != NULL) - sdev->next->prev = sdev->prev; - - if (sdev->prev != NULL) - sdev->prev->next = sdev->next; - - if (shost->host_queue == sdev) { - shost->host_queue = sdev->next; - } - blk_cleanup_queue(&sdev->request_queue); - if (sdev->inquiry) - kfree(sdev->inquiry); - kfree((char *) sdev); - } else { - goto out; + scsi_free_sdev(sdev); + err = 0; } - err = 0; } out: diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c --- a/drivers/scsi/scsi_scan.c Fri Nov 22 13:41:22 2002 +++ b/drivers/scsi/scsi_scan.c Fri Nov 22 13:41:22 2002 @@ -465,12 +465,12 @@ * Return value: * Scsi_Device pointer, or NULL on failure. **/ -static Scsi_Device *scsi_alloc_sdev(struct Scsi_Host *shost, uint channel, +struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost, uint channel, uint id, uint lun) { - Scsi_Device *sdev; + struct scsi_device *sdev; - sdev = (Scsi_Device *) kmalloc(sizeof(Scsi_Device), GFP_ATOMIC); + sdev = kmalloc(sizeof(*sdev), GFP_ATOMIC); if (sdev == NULL) printk(ALLOC_FAILURE_MSG, __FUNCTION__); else { @@ -522,7 +522,7 @@ * Undo the actions in scsi_alloc_sdev, including removing @sdev from * the list, and freeing @sdev. **/ -static void scsi_free_sdev(Scsi_Device *sdev) +void scsi_free_sdev(struct scsi_device *sdev) { if (sdev->prev != NULL) sdev->prev->next = sdev->next; diff -Nru a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c --- a/drivers/scsi/seagate.c Fri Nov 22 13:41:19 2002 +++ b/drivers/scsi/seagate.c Fri Nov 22 13:41:19 2002 @@ -88,22 +88,24 @@ */ #include - -#include -#include +#include #include #include -#include #include #include #include #include #include +#include + +#include +#include +#include + #include "scsi.h" #include "hosts.h" #include "seagate.h" -#include -#include + #include #ifdef DEBUG diff -Nru a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h --- a/drivers/scsi/sym53c8xx_2/sym_glue.h Fri Nov 22 13:41:23 2002 +++ b/drivers/scsi/sym53c8xx_2/sym_glue.h Fri Nov 22 13:41:23 2002 @@ -82,6 +82,7 @@ #include #include #include +#include #include diff -Nru a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c --- a/drivers/scsi/tmscsim.c Fri Nov 22 13:41:23 2002 +++ b/drivers/scsi/tmscsim.c Fri Nov 22 13:41:23 2002 @@ -276,10 +276,10 @@ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,99) static struct pci_device_id tmscsim_pci_tbl[] __initdata = { { - vendor: PCI_VENDOR_ID_AMD, - device: PCI_DEVICE_ID_AMD53C974, - subvendor: PCI_ANY_ID, - subdevice: PCI_ANY_ID, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_AMD53C974, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, }, { } /* Terminating entry */ }; diff -Nru a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c --- a/drivers/scsi/u14-34f.c Fri Nov 22 13:41:18 2002 +++ b/drivers/scsi/u14-34f.c Fri Nov 22 13:41:18 2002 @@ -393,7 +393,7 @@ #endif #include -#include +#include #include #include #include @@ -402,11 +402,6 @@ #include #include #include -#include "scsi.h" -#include "hosts.h" -#include -#include -#include "u14-34f.h" #include #include #include @@ -414,6 +409,13 @@ #include #include #include + +#include +#include + +#include "scsi.h" +#include "hosts.h" +#include "u14-34f.h" #if !defined(__BIG_ENDIAN_BITFIELD) && !defined(__LITTLE_ENDIAN_BITFIELD) #error "Adjust your defines" diff -Nru a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c --- a/drivers/scsi/ultrastor.c Fri Nov 22 13:41:20 2002 +++ b/drivers/scsi/ultrastor.c Fri Nov 22 13:41:20 2002 @@ -128,25 +128,25 @@ */ #include - +#include +#include #include #include -#include #include #include #include #include +#include + #include #include #include #include #define ULTRASTOR_PRIVATE /* Get the private stuff from ultrastor.h */ -#include #include "scsi.h" #include "hosts.h" #include "ultrastor.h" -#include #define FALSE 0 #define TRUE 1 diff -Nru a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c --- a/drivers/scsi/wd7000.c Fri Nov 22 13:41:23 2002 +++ b/drivers/scsi/wd7000.c Fri Nov 22 13:41:23 2002 @@ -161,24 +161,25 @@ */ #include - -#include +#include #include #include #include -#include #include #include -#include -#include -#include #include #include #include #include #include + +#include +#include +#include + #include "scsi.h" #include "hosts.h" + #include #define ANY2SCSI_INLINE /* undef this to use old macros */ diff -Nru a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c --- a/drivers/serial/68328serial.c Fri Nov 22 13:41:23 2002 +++ b/drivers/serial/68328serial.c Fri Nov 22 13:41:23 2002 @@ -1682,12 +1682,12 @@ static struct console m68328_driver = { - name: "ttyS", - write: m68328_console_write, - device: m68328_console_device, - setup: m68328_console_setup, - flags: CON_PRINTBUFFER, - index: -1, + .name = "ttyS", + .write = m68328_console_write, + .device = m68328_console_device, + .setup = m68328_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, }; diff -Nru a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c --- a/drivers/serial/68360serial.c Fri Nov 22 13:41:23 2002 +++ b/drivers/serial/68360serial.c Fri Nov 22 13:41:23 2002 @@ -2566,13 +2566,13 @@ struct console sercons = { - name: "ttyS", - write: serial_console_write, - device: serial_console_device, - wait_key: serial_console_wait_key, - setup: serial_console_setup, - flags: CON_PRINTBUFFER, - index: CONFIG_SERIAL_CONSOLE_PORT, + .name = "ttyS", + .write = serial_console_write, + .device = serial_console_device, + .wait_key = serial_console_wait_key, + .setup = serial_console_setup, + .flags = CON_PRINTBUFFER, + .index = CONFIG_SERIAL_CONSOLE_PORT, }; diff -Nru a/drivers/serial/8250_gsc.c b/drivers/serial/8250_gsc.c --- a/drivers/serial/8250_gsc.c Fri Nov 22 13:41:22 2002 +++ b/drivers/serial/8250_gsc.c Fri Nov 22 13:41:22 2002 @@ -112,15 +112,15 @@ MODULE_DEVICE_TABLE(parisc, serial_tbl); static struct parisc_driver serial1_driver = { - name: "Serial RS232", - id_table: serial1_tbl, - probe: serial_init_chip, + .name = "Serial RS232", + .id_table = serial1_tbl, + .probe = serial_init_chip, }; static struct parisc_driver serial_driver = { - name: "Serial RS232", - id_table: serial_tbl, - probe: serial_init_chip, + .name = "Serial RS232", + .id_table = serial_tbl, + .probe = serial_init_chip, }; int __init probe_serial_gsc(void) diff -Nru a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c --- a/drivers/serial/mcfserial.c Fri Nov 22 13:41:19 2002 +++ b/drivers/serial/mcfserial.c Fri Nov 22 13:41:19 2002 @@ -1853,12 +1853,12 @@ */ struct console mcfrs_console = { - name: "ttyS", - write: mcfrs_console_write, - device: mcfrs_console_device, - setup: mcfrs_console_setup, - flags: CON_PRINTBUFFER, - index: -1, + .name = "ttyS", + .write = mcfrs_console_write, + .device = mcfrs_console_device, + .setup = mcfrs_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, }; void __init mcfrs_console_init(void) diff -Nru a/drivers/serial/nb85e_uart.c b/drivers/serial/nb85e_uart.c --- a/drivers/serial/nb85e_uart.c Fri Nov 22 13:41:22 2002 +++ b/drivers/serial/nb85e_uart.c Fri Nov 22 13:41:22 2002 @@ -255,12 +255,12 @@ static struct console nb85e_uart_cons = { - name: "ttyS", - write: nb85e_uart_cons_write, - device: nb85e_uart_cons_device, - flags: CON_PRINTBUFFER, - cflag: NB85E_UART_INIT_CFLAGS, - index: -1, + .name = "ttyS", + .write = nb85e_uart_cons_write, + .device = nb85e_uart_cons_device, + .flags = CON_PRINTBUFFER, + .cflag = NB85E_UART_INIT_CFLAGS, + .index = -1, }; void nb85e_uart_cons_init (unsigned chan) diff -Nru a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c --- a/drivers/serial/sunsu.c Fri Nov 22 13:41:18 2002 +++ b/drivers/serial/sunsu.c Fri Nov 22 13:41:18 2002 @@ -1028,8 +1028,8 @@ struct linux_ebus_device *dev = 0; struct linux_ebus *ebus; #ifdef CONFIG_SPARC64 - struct isa_bridge *isa_br; - struct isa_device *isa_dev; + struct sparc_isa_bridge *isa_br; + struct sparc_isa_device *isa_dev; #endif #ifndef CONFIG_SPARC64 struct linux_prom_registers reg0; diff -Nru a/drivers/serial/uart00.c b/drivers/serial/uart00.c --- a/drivers/serial/uart00.c Fri Nov 22 13:41:19 2002 +++ b/drivers/serial/uart00.c Fri Nov 22 13:41:19 2002 @@ -731,9 +731,9 @@ } struct pld_hotswap_ops uart00_pldhs_ops={ - name: "uart00", - add_device: uart00_add_device, - remove_devices:uart00_remove_devices, + .name = "uart00", + .add_device = uart00_add_device, + .remove_devices = uart00_remove_devices, }; #endif diff -Nru a/drivers/sgi/char/ds1286.c b/drivers/sgi/char/ds1286.c --- a/drivers/sgi/char/ds1286.c Fri Nov 22 13:41:18 2002 +++ b/drivers/sgi/char/ds1286.c Fri Nov 22 13:41:18 2002 @@ -331,12 +331,12 @@ */ static struct file_operations ds1286_fops = { - llseek: no_llseek, - read: ds1286_read, - poll: ds1286_poll, - ioctl: ds1286_ioctl, - open: ds1286_open, - release: ds1286_release, + .llseek = no_llseek, + .read = ds1286_read, + .poll = ds1286_poll, + .ioctl = ds1286_ioctl, + .open = ds1286_open, + .release = ds1286_release, }; static struct miscdevice ds1286_dev= diff -Nru a/drivers/sgi/char/graphics.c b/drivers/sgi/char/graphics.c --- a/drivers/sgi/char/graphics.c Fri Nov 22 13:41:20 2002 +++ b/drivers/sgi/char/graphics.c Fri Nov 22 13:41:20 2002 @@ -259,7 +259,7 @@ */ static struct vm_operations_struct graphics_mmap = { - nopage: sgi_graphics_nopage, /* our magic no-page fault handler */ + .nopage = sgi_graphics_nopage, /* our magic no-page fault handler */ }; int @@ -292,10 +292,10 @@ #endif struct file_operations sgi_graphics_fops = { - ioctl: sgi_graphics_ioctl, - mmap: sgi_graphics_mmap, - open: sgi_graphics_open, - release: sgi_graphics_close, + .ioctl = sgi_graphics_ioctl, + .mmap = sgi_graphics_mmap, + .open = sgi_graphics_open, + .release = sgi_graphics_close, }; /* /dev/graphics */ diff -Nru a/drivers/sgi/char/sgiserial.c b/drivers/sgi/char/sgiserial.c --- a/drivers/sgi/char/sgiserial.c Fri Nov 22 13:41:18 2002 +++ b/drivers/sgi/char/sgiserial.c Fri Nov 22 13:41:18 2002 @@ -2258,12 +2258,12 @@ } static struct console sgi_console_driver = { - name: "ttyS", - write: zs_console_write, - device: zs_console_device, - setup: zs_console_setup, - flags: CON_PRINTBUFFER, - index: -1, + .name = "ttyS", + .write = zs_console_write, + .device = zs_console_device, + .setup = zs_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, }; /* diff -Nru a/drivers/sgi/char/shmiq.c b/drivers/sgi/char/shmiq.c --- a/drivers/sgi/char/shmiq.c Fri Nov 22 13:41:22 2002 +++ b/drivers/sgi/char/shmiq.c Fri Nov 22 13:41:22 2002 @@ -311,7 +311,7 @@ } static struct vm_operations_struct qcntl_mmap = { - nopage: shmiq_nopage, /* our magic no-page fault handler */ + .nopage = shmiq_nopage, /* our magic no-page fault handler */ }; static int @@ -454,12 +454,12 @@ static struct file_operations shmiq_fops = { - poll: shmiq_qcntl_poll, - ioctl: shmiq_qcntl_ioctl, - mmap: shmiq_qcntl_mmap, - open: shmiq_qcntl_open, - release: shmiq_qcntl_close, - fasync: shmiq_qcntl_fasync, + .poll = shmiq_qcntl_poll, + .ioctl = shmiq_qcntl_ioctl, + .mmap = shmiq_qcntl_mmap, + .open = shmiq_qcntl_open, + .release = shmiq_qcntl_close, + .fasync = shmiq_qcntl_fasync, }; void diff -Nru a/drivers/sgi/char/streamable.c b/drivers/sgi/char/streamable.c --- a/drivers/sgi/char/streamable.c Fri Nov 22 13:41:18 2002 +++ b/drivers/sgi/char/streamable.c Fri Nov 22 13:41:18 2002 @@ -59,7 +59,7 @@ } struct file_operations sgi_gfx_fops = { - ioctl: sgi_gfx_ioctl, + .ioctl = sgi_gfx_ioctl, }; static struct miscdevice dev_gfx = { @@ -167,8 +167,8 @@ } struct file_operations sgi_keyb_fops = { - ioctl: sgi_keyb_ioctl, - open: sgi_keyb_open, + .ioctl = sgi_keyb_ioctl, + .open = sgi_keyb_open, }; static struct miscdevice dev_input_keyboard = { @@ -296,9 +296,9 @@ } struct file_operations sgi_mouse_fops = { - ioctl: sgi_mouse_ioctl, - open: sgi_mouse_open, - release: sgi_mouse_close, + .ioctl = sgi_mouse_ioctl, + .open = sgi_mouse_open, + .release = sgi_mouse_close, }; /* /dev/input/mouse */ diff -Nru a/drivers/sgi/char/usema.c b/drivers/sgi/char/usema.c --- a/drivers/sgi/char/usema.c Fri Nov 22 13:41:19 2002 +++ b/drivers/sgi/char/usema.c Fri Nov 22 13:41:19 2002 @@ -164,9 +164,9 @@ } struct file_operations sgi_usemaclone_fops = { - poll: sgi_usemaclone_poll, - ioctl: sgi_usemaclone_ioctl, - open: sgi_usemaclone_open, + .poll = sgi_usemaclone_poll, + .ioctl = sgi_usemaclone_ioctl, + .open = sgi_usemaclone_open, }; static struct miscdevice dev_usemaclone = { diff -Nru a/drivers/tc/lk201.c b/drivers/tc/lk201.c --- a/drivers/tc/lk201.c Fri Nov 22 13:41:23 2002 +++ b/drivers/tc/lk201.c Fri Nov 22 13:41:23 2002 @@ -36,12 +36,9 @@ static void lk201_kbd_rx_char(unsigned char, unsigned char); struct zs_hook lk201_kbdhook = { - init_channel: lk201_init, - init_info: lk201_info, - rx_char: NULL, - poll_rx_char: NULL, - poll_tx_char: NULL, - cflags: B4800 | CS8 | CSTOPB | CLOCAL + .init_channel = lk201_init, + .init_info = lk201_info, + .cflags = B4800 | CS8 | CSTOPB | CLOCAL }; /* diff -Nru a/drivers/tc/zs.c b/drivers/tc/zs.c --- a/drivers/tc/zs.c Fri Nov 22 13:41:22 2002 +++ b/drivers/tc/zs.c Fri Nov 22 13:41:22 2002 @@ -2255,12 +2255,12 @@ } static struct console sercons = { - name: "ttyS", - write: serial_console_write, - device: serial_console_device, - setup: serial_console_setup, - flags: CON_PRINTBUFFER, - index: -1, + .name = "ttyS", + .write = serial_console_write, + .device = serial_console_device, + .setup = serial_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, }; /* diff -Nru a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c --- a/drivers/telephony/ixj.c Fri Nov 22 13:41:17 2002 +++ b/drivers/telephony/ixj.c Fri Nov 22 13:41:17 2002 @@ -6765,13 +6765,13 @@ struct file_operations ixj_fops = { - owner: THIS_MODULE, - read: ixj_enhanced_read, - write: ixj_enhanced_write, - poll: ixj_poll, - ioctl: ixj_ioctl, - release: ixj_release, - fasync: ixj_fasync + .owner = THIS_MODULE, + .read = ixj_enhanced_read, + .write = ixj_enhanced_write, + .poll = ixj_poll, + .ioctl = ixj_ioctl, + .release = ixj_release, + .fasync = ixj_fasync }; static int ixj_linetest(IXJ *j) diff -Nru a/drivers/telephony/phonedev.c b/drivers/telephony/phonedev.c --- a/drivers/telephony/phonedev.c Fri Nov 22 13:41:21 2002 +++ b/drivers/telephony/phonedev.c Fri Nov 22 13:41:21 2002 @@ -135,8 +135,8 @@ static struct file_operations phone_fops = { - owner: THIS_MODULE, - open: phone_open, + .owner = THIS_MODULE, + .open = phone_open, }; /* diff -Nru a/drivers/usb/core/config.c b/drivers/usb/core/config.c --- a/drivers/usb/core/config.c Fri Nov 22 13:41:17 2002 +++ b/drivers/usb/core/config.c Fri Nov 22 13:41:17 2002 @@ -109,7 +109,8 @@ interface->num_altsetting = 0; interface->max_altsetting = USB_ALTSETTINGALLOC; - interface->altsetting = kmalloc(sizeof(struct usb_interface_descriptor) * interface->max_altsetting, GFP_KERNEL); + interface->altsetting = kmalloc(sizeof(*interface->altsetting) * interface->max_altsetting, + GFP_KERNEL); if (!interface->altsetting) { err("couldn't kmalloc interface->altsetting"); @@ -118,29 +119,27 @@ while (size > 0) { struct usb_interface_descriptor *d; - + if (interface->num_altsetting >= interface->max_altsetting) { - void *ptr; + struct usb_host_interface *ptr; int oldmas; oldmas = interface->max_altsetting; interface->max_altsetting += USB_ALTSETTINGALLOC; if (interface->max_altsetting > USB_MAXALTSETTING) { - warn("too many alternate settings (max %d)", - USB_MAXALTSETTING); + warn("too many alternate settings (incr %d max %d)\n", + USB_ALTSETTINGALLOC, USB_MAXALTSETTING); return -1; } - ptr = interface->altsetting; - interface->altsetting = kmalloc(sizeof(struct usb_interface_descriptor) * interface->max_altsetting, GFP_KERNEL); - if (!interface->altsetting) { + ptr = kmalloc(sizeof(*ptr) * interface->max_altsetting, GFP_KERNEL); + if (ptr == NULL) { err("couldn't kmalloc interface->altsetting"); - interface->altsetting = ptr; return -1; } - memcpy(interface->altsetting, ptr, sizeof(struct usb_interface_descriptor) * oldmas); - - kfree(ptr); + memcpy(ptr, interface->altsetting, sizeof(*interface->altsetting) * oldmas); + kfree(interface->altsetting); + interface->altsetting = ptr; } ifp = interface->altsetting + interface->num_altsetting; diff -Nru a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c --- a/drivers/usb/core/inode.c Fri Nov 22 13:41:17 2002 +++ b/drivers/usb/core/inode.c Fri Nov 22 13:41:17 2002 @@ -143,7 +143,7 @@ /* --------------------------------------------------------------------- */ -static struct inode *usbfs_get_inode (struct super_block *sb, int mode, int dev) +static struct inode *usbfs_get_inode (struct super_block *sb, int mode, dev_t dev) { struct inode *inode = new_inode(sb); @@ -176,7 +176,7 @@ /* SMP-safe */ static int usbfs_mknod (struct inode *dir, struct dentry *dentry, int mode, - int dev) + dev_t dev) { struct inode *inode = usbfs_get_inode(dir->i_sb, mode, dev); int error = -EPERM; @@ -255,7 +255,7 @@ if (atomic_read(&dentry->d_count) != 2) break; case 2: - list_del_init(&dentry->d_hash); + __d_drop(dentry); } spin_unlock(&dcache_lock); } diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c --- a/drivers/usb/core/usb.c Fri Nov 22 13:41:20 2002 +++ b/drivers/usb/core/usb.c Fri Nov 22 13:41:20 2002 @@ -62,16 +62,12 @@ { return 0; } -static void generic_release (struct device_driver * drv) -{ -} static struct device_driver usb_generic_driver = { .name = "usb", .bus = &usb_bus_type, .probe = generic_probe, .remove = generic_remove, - .release = generic_release, }; int usb_device_probe(struct device *dev) @@ -1427,7 +1423,7 @@ usb_major_cleanup(); usbfs_cleanup(); usb_hub_cleanup(); - put_bus(&usb_bus_type); + bus_unregister(&usb_bus_type); } subsys_initcall(usb_init); diff -Nru a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c --- a/drivers/usb/media/vicam.c Fri Nov 22 13:41:18 2002 +++ b/drivers/usb/media/vicam.c Fri Nov 22 13:41:18 2002 @@ -1,6 +1,7 @@ /* * USB ViCam WebCam driver - * Copyright (c) 2002 Joe Burks (jburks@wavicle.org) + * Copyright (c) 2002 Joe Burks (jburks@wavicle.org), + * John Tyner (fill in email address) * * Supports 3COM HomeConnect PC Digital WebCam * @@ -43,14 +44,6 @@ // #define VICAM_DEBUG -#ifndef MODULE_LICENSE -#define MODULE_LICENSE(a) -#endif - -#ifndef bool -#define bool int -#endif - #ifdef VICAM_DEBUG #define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __FUNCTION__, lineno, ##args) #define DBG(fmt,args...) ADBG((__LINE__),KERN_DEBUG __FILE__"(%ld):%s (%d):"fmt,##args) @@ -403,26 +396,27 @@ } vfree(mem); } - + struct vicam_camera { u16 shutter_speed; // capture shutter speed u16 gain; // capture gain u8 *raw_image; // raw data captured from the camera u8 *framebuf; // processed data in RGB24 format + u8 *cntrlbuf; // area used to send control msgs struct video_device vdev; // v4l video device struct usb_device *udev; // usb device struct semaphore busy_lock; // guard against SMP multithreading - bool is_initialized; + int is_initialized; u8 open_count; u8 bulkEndpoint; - bool needsDummyRead; + int needsDummyRead; -#ifdef CONFIG_PROC_FS - struct proc_dir_entry *proc_entry; +#if defined(CONFIG_VIDEO_PROC_FS) + struct proc_dir_entry *proc_dir; #endif }; @@ -437,22 +431,16 @@ { int status; - // for reasons not yet known to me, you can't send USB control messages - // with data in the module (if you are compiled as a module). Whatever - // the reason, copying it to memory allocated as kernel memory then - // doing the usb control message fixes the problem. - - unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL); - memcpy(transfer_buffer, cp, size); + /* cp must be memory that has been allocated by kmalloc */ status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), request, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, index, - transfer_buffer, size, HZ); + cp, size, HZ); - kfree(transfer_buffer); + status = min(status, 0); if (status < 0) { printk(KERN_INFO "Failed sending control message, error %d.\n", @@ -465,29 +453,30 @@ static int initialize_camera(struct vicam_camera *cam) { + const struct { + u8 *data; + u32 size; + } firmware[] = { + { .data = setup1, .size = sizeof(setup1) }, + { .data = setup2, .size = sizeof(setup2) }, + { .data = setup3, .size = sizeof(setup3) }, + { .data = setup4, .size = sizeof(setup4) }, + { .data = setup5, .size = sizeof(setup5) }, + { .data = setup3, .size = sizeof(setup3) }, + { .data = NULL, .size = 0 } + }; + struct usb_device *udev = cam->udev; - int status; + int err, i; - if ((status = - send_control_msg(udev, 0xff, 0, 0, setup1, sizeof (setup1))) < 0) - return status; - if ((status = - send_control_msg(udev, 0xff, 0, 0, setup2, sizeof (setup2))) < 0) - return status; - if ((status = - send_control_msg(udev, 0xff, 0, 0, setup3, sizeof (setup3))) < 0) - return status; - if ((status = - send_control_msg(udev, 0xff, 0, 0, setup4, sizeof (setup4))) < 0) - return status; - if ((status = - send_control_msg(udev, 0xff, 0, 0, setup5, sizeof (setup5))) < 0) - return status; - if ((status = - send_control_msg(udev, 0xff, 0, 0, setup3, sizeof (setup3))) < 0) - return status; + for (i = 0, err = 0; firmware[i].data && !err; i++) { + memcpy(cam->cntrlbuf, firmware[i].data, firmware[i].size); - return 0; + err = send_control_msg(udev, 0xff, 0, 0, + cam->cntrlbuf, firmware[i].size); + } + + return err; } static int @@ -752,7 +741,8 @@ "vicam video_device improperly initialized"); } - down_interruptible(&cam->busy_lock); + if ( down_interruptible(&cam->busy_lock) ) + return -EINTR; if (cam->open_count > 0) { printk(KERN_INFO @@ -774,6 +764,14 @@ return -ENOMEM; } + cam->cntrlbuf = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!cam->cntrlbuf) { + kfree(cam->raw_image); + rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); + up(&cam->busy_lock); + return -ENOMEM; + } + // First upload firmware, then turn the camera on if (!cam->is_initialized) { @@ -803,6 +801,7 @@ kfree(cam->raw_image); rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); + kfree(cam->cntrlbuf); cam->open_count--; @@ -831,7 +830,7 @@ // Copyright (C) 2002 Monroe Williams (monroe@pobox.com) // -------------------------------------------------------------------------------- -void vicam_decode_color( char *data, char *rgb) +static void vicam_decode_color( char *data, char *rgb) { int x,y; int Cr, Cb; @@ -915,7 +914,7 @@ static void read_frame(struct vicam_camera *cam, int framenum) { - unsigned char request[16]; + unsigned char *request = cam->cntrlbuf; int realShutter; int n; int actual_length; @@ -984,7 +983,8 @@ DBG("read %d bytes.\n", (int) count); - down_interruptible(&cam->busy_lock); + if ( down_interruptible(&cam->busy_lock) ) + return -EINTR; if (*ppos >= VICAM_MAX_FRAME_SIZE) { *ppos = 0; @@ -1057,24 +1057,17 @@ return 0; } -#ifdef CONFIG_PROC_FS +#if defined(CONFIG_VIDEO_PROC_FS) static struct proc_dir_entry *vicam_proc_root = NULL; -static int -vicam_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int vicam_read_helper(char *page, char **start, off_t off, + int count, int *eof, int value) { char *out = page; int len; - struct vicam_camera *cam = (struct vicam_camera *) data; - out += - sprintf(out, "Vicam-based WebCam Linux Driver.\n"); - out += sprintf(out, "(c) 2002 Joe Burks (jburks@wavicle.org)\n"); - out += sprintf(out, "vicam stats:\n"); - out += sprintf(out, " Shutter Speed: 1/%d\n", cam->shutter_speed); - out += sprintf(out, " Gain: %d\n", cam->gain); + out += sprintf(out, "%d",value); len = out - page; len -= off; @@ -1089,38 +1082,43 @@ return len; } -static int -vicam_write_proc(struct file *file, const char *buffer, - unsigned long count, void *data) +static int vicam_read_proc_shutter(char *page, char **start, off_t off, + int count, int *eof, void *data) { - char *in; - char *start; - struct vicam_camera *cam = (struct vicam_camera *) data; + return vicam_read_helper(page,start,off,count,eof, + ((struct vicam_camera *)data)->shutter_speed); +} - in = kmalloc(count + 1, GFP_KERNEL); - if (!in) - return -ENOMEM; +static int vicam_read_proc_gain(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + return vicam_read_helper(page,start,off,count,eof, + ((struct vicam_camera *)data)->gain); +} - in[count] = 0; // I'm not sure buffer is gauranteed to be null terminated - // so I do this to make sure I have a null in there. +static int vicam_write_proc_shutter(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + struct vicam_camera *cam = (struct vicam_camera *)data; + + cam->shutter_speed = simple_strtoul(buffer, NULL, 10); - strncpy(in, buffer, count); + return count; +} - start = strstr(in, "gain="); - if (start - && (start == in || *(start - 1) == ' ' || *(start - 1) == ',')) - cam->gain = simple_strtoul(start + 5, NULL, 10); - - start = strstr(in, "shutter="); - if (start - && (start == in || *(start - 1) == ' ' || *(start - 1) == ',')) - cam->shutter_speed = simple_strtoul(start + 8, NULL, 10); +static int vicam_write_proc_gain(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + struct vicam_camera *cam = (struct vicam_camera *)data; + + cam->gain = simple_strtoul(buffer, NULL, 10); - kfree(in); return count; } -void + + +static void vicam_create_proc_root(void) { vicam_proc_root = create_proc_entry("video/vicam", S_IFDIR, 0); @@ -1132,19 +1130,17 @@ "could not create /proc entry for vicam!"); } -void +static void vicam_destroy_proc_root(void) { if (vicam_proc_root) remove_proc_entry("video/vicam", 0); } -void -vicam_create_proc_entry(void *ptr) +static void +vicam_create_proc_entry(struct vicam_camera *cam) { - struct vicam_camera *cam = (struct vicam_camera *) ptr; - - char name[7]; + char name[64]; struct proc_dir_entry *ent; DBG(KERN_INFO "vicam: creating proc entry\n"); @@ -1158,46 +1154,54 @@ sprintf(name, "video%d", cam->vdev.minor); - ent = - create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR, - vicam_proc_root); - if (!ent) - return; + cam->proc_dir = create_proc_entry(name, S_IFDIR, vicam_proc_root); - ent->data = cam; - ent->read_proc = vicam_read_proc; - ent->write_proc = vicam_write_proc; - ent->size = 512; - cam->proc_entry = ent; + if ( !cam->proc_dir ) return; // We should probably return an error here + + ent = + create_proc_entry("shutter", S_IFREG | S_IRUGO | S_IWUSR, + cam->proc_dir); + if (ent) { + ent->data = cam; + ent->read_proc = vicam_read_proc_shutter; + ent->write_proc = vicam_write_proc_shutter; + ent->size = 64; + } + + ent = create_proc_entry("gain", S_IFREG | S_IRUGO | S_IWUSR, + cam->proc_dir); + if ( ent ) { + ent->data = cam; + ent->read_proc = vicam_read_proc_gain; + ent->write_proc = vicam_write_proc_gain; + ent->size = 64; + } } -void +static void vicam_destroy_proc_entry(void *ptr) { struct vicam_camera *cam = (struct vicam_camera *) ptr; - char name[7]; + char name[16]; - if (!cam || !cam->proc_entry) + if ( !cam->proc_dir ) return; sprintf(name, "video%d", cam->vdev.minor); - remove_proc_entry(name, vicam_proc_root); - cam->proc_entry = NULL; + remove_proc_entry("shutter", cam->proc_dir); + remove_proc_entry("gain", cam->proc_dir); + remove_proc_entry(name,vicam_proc_root); + cam->proc_dir = NULL; } +#else +static inline void vicam_create_proc_root(void) { } +static inline void vicam_destroy_proc_root(void) { } +static inline void vicam_create_proc_entry(struct vicam_camera *cam) { } +static inline void vicam_destroy_proc_entry(void *ptr) { } #endif -int -vicam_video_init(struct video_device *vdev) -{ - // This would normally create the proc entry for this camera -#ifdef CONFIG_PROC_FS - vicam_create_proc_entry(vdev->priv); -#endif - return 0; -} - static struct file_operations vicam_fops = { .owner = THIS_MODULE, .open = vicam_open, @@ -1296,6 +1300,8 @@ return -EIO; } + vicam_create_proc_entry(cam); + printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",cam->vdev.minor); dev_set_drvdata(&intf->dev, cam); @@ -1314,9 +1320,7 @@ video_unregister_device(&cam->vdev); -#ifdef CONFIG_PROC_FS vicam_destroy_proc_entry(cam); -#endif kfree(cam); @@ -1329,9 +1333,7 @@ usb_vicam_init(void) { DBG(KERN_INFO "ViCam-based WebCam driver startup\n"); -#ifdef CONFIG_PROC_FS vicam_create_proc_root(); -#endif if (usb_register(&vicam_driver) != 0) printk(KERN_WARNING "usb_register failed!\n"); return 0; @@ -1344,9 +1346,7 @@ "ViCam-based WebCam driver shutdown\n"); usb_deregister(&vicam_driver); -#ifdef CONFIG_PROC_FS vicam_destroy_proc_root(); -#endif } module_init(usb_vicam_init); diff -Nru a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c --- a/drivers/usb/net/pegasus.c Fri Nov 22 13:41:23 2002 +++ b/drivers/usb/net/pegasus.c Fri Nov 22 13:41:23 2002 @@ -28,7 +28,6 @@ * is out of the interrupt routine. */ - #include #include #include @@ -46,7 +45,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v0.5.6 (2002/06/23)" +#define DRIVER_VERSION "v0.5.7 (2002/11/18)" #define DRIVER_AUTHOR "Petko Manolov " #define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver" @@ -119,16 +118,9 @@ void *data) { int ret; - unsigned char *buffer; + unsigned char buffer[256]; DECLARE_WAITQUEUE(wait, current); - buffer = kmalloc(size, GFP_KERNEL); - if (!buffer) { - err("unable to allocate memory for configuration descriptors"); - return 0; - } - memcpy(buffer, data, size); - add_wait_queue(&pegasus->ctrl_wait, &wait); set_current_state(TASK_UNINTERRUPTIBLE); while (pegasus->flags & ETH_REGS_CHANGED) @@ -144,9 +136,9 @@ pegasus->ctrl_urb->transfer_buffer_length = size; usb_fill_control_urb(pegasus->ctrl_urb, pegasus->usb, - usb_rcvctrlpipe(pegasus->usb, 0), - (char *) &pegasus->dr, - buffer, size, ctrl_callback, pegasus); + usb_rcvctrlpipe(pegasus->usb, 0), + (char *) &pegasus->dr, + buffer, size, ctrl_callback, pegasus); add_wait_queue(&pegasus->ctrl_wait, &wait); set_current_state(TASK_UNINTERRUPTIBLE); @@ -161,7 +153,6 @@ out: remove_wait_queue(&pegasus->ctrl_wait, &wait); memcpy(data, buffer, size); - kfree(buffer); return ret; } @@ -170,14 +161,9 @@ void *data) { int ret; - unsigned char *buffer; + unsigned char buffer[256]; DECLARE_WAITQUEUE(wait, current); - buffer = kmalloc(size, GFP_KERNEL); - if (!buffer) { - err("unable to allocate memory for configuration descriptors"); - return 0; - } memcpy(buffer, data, size); add_wait_queue(&pegasus->ctrl_wait, &wait); @@ -195,9 +181,9 @@ pegasus->ctrl_urb->transfer_buffer_length = size; usb_fill_control_urb(pegasus->ctrl_urb, pegasus->usb, - usb_sndctrlpipe(pegasus->usb, 0), - (char *) &pegasus->dr, - buffer, size, ctrl_callback, pegasus); + usb_sndctrlpipe(pegasus->usb, 0), + (char *) &pegasus->dr, + buffer, size, ctrl_callback, pegasus); add_wait_queue(&pegasus->ctrl_wait, &wait); set_current_state(TASK_UNINTERRUPTIBLE); @@ -210,7 +196,6 @@ schedule(); out: remove_wait_queue(&pegasus->ctrl_wait, &wait); - kfree(buffer); return ret; } @@ -218,17 +203,9 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data) { int ret; - unsigned char *buffer; - __u16 dat = data; + __u16 tmp = data; DECLARE_WAITQUEUE(wait, current); - buffer = kmalloc(1, GFP_KERNEL); - if (!buffer) { - err("unable to allocate memory for configuration descriptors"); - return 0; - } - memcpy(buffer, &data, 1); - add_wait_queue(&pegasus->ctrl_wait, &wait); set_current_state(TASK_UNINTERRUPTIBLE); while (pegasus->flags & ETH_REGS_CHANGED) @@ -238,15 +215,15 @@ pegasus->dr.bRequestType = PEGASUS_REQT_WRITE; pegasus->dr.bRequest = PEGASUS_REQ_SET_REG; - pegasus->dr.wValue = cpu_to_le16p(&dat); + pegasus->dr.wValue = cpu_to_le16p(&tmp); pegasus->dr.wIndex = cpu_to_le16p(&indx); pegasus->dr.wLength = cpu_to_le16(1); pegasus->ctrl_urb->transfer_buffer_length = 1; usb_fill_control_urb(pegasus->ctrl_urb, pegasus->usb, - usb_sndctrlpipe(pegasus->usb, 0), - (char *) &pegasus->dr, - buffer, 1, ctrl_callback, pegasus); + usb_sndctrlpipe(pegasus->usb, 0), + (char *) &pegasus->dr, + &data, 1, ctrl_callback, pegasus); add_wait_queue(&pegasus->ctrl_wait, &wait); set_current_state(TASK_UNINTERRUPTIBLE); @@ -259,7 +236,6 @@ schedule(); out: remove_wait_queue(&pegasus->ctrl_wait, &wait); - kfree(buffer); return ret; } @@ -276,9 +252,9 @@ pegasus->ctrl_urb->transfer_buffer_length = 3; usb_fill_control_urb(pegasus->ctrl_urb, pegasus->usb, - usb_sndctrlpipe(pegasus->usb, 0), - (char *) &pegasus->dr, - pegasus->eth_regs, 3, ctrl_callback, pegasus); + usb_sndctrlpipe(pegasus->usb, 0), + (char *) &pegasus->dr, + pegasus->eth_regs, 3, ctrl_callback, pegasus); if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) err("%s: BAD CTRL %d, flgs %x", __FUNCTION__, ret, @@ -294,7 +270,7 @@ __u16 regdi; set_register(pegasus, PhyCtrl, 0); - set_registers(pegasus, PhyAddr, sizeof(data), data); + set_registers(pegasus, PhyAddr, sizeof (data), data); set_register(pegasus, PhyCtrl, (indx | PHY_READ)); for (i = 0; i < REG_TIMEOUT; i++) { get_registers(pegasus, PhyCtrl, 1, data); @@ -311,6 +287,15 @@ return 1; } +static int mdio_read(struct net_device *dev, int phy_id, int loc) +{ + pegasus_t *pegasus = (pegasus_t *) dev->priv; + int res; + + read_mii_word(pegasus, phy_id, loc, (u16 *) & res); + return res & 0xffff; +} + static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd) { int i; @@ -332,6 +317,13 @@ return 1; } +static void mdio_write(struct net_device *dev, int phy_id, int loc, int val) +{ + pegasus_t *pegasus = (pegasus_t *) dev->priv; + + write_mii_word(pegasus, phy_id, loc, val); +} + static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata) { int i; @@ -415,8 +407,8 @@ __u8 node_id[6]; get_node_id(pegasus, node_id); - set_registers(pegasus, EthID, sizeof(node_id), node_id); - memcpy(pegasus->net->dev_addr, node_id, sizeof(node_id)); + set_registers(pegasus, EthID, sizeof (node_id), node_id); + memcpy(pegasus->net->dev_addr, node_id, sizeof (node_id)); } static inline int reset_mac(pegasus_t * pegasus) @@ -473,7 +465,7 @@ data[1] = 0; data[2] = (loopback & 1) ? 0x09 : 0x01; - memcpy(pegasus->eth_regs, data, sizeof(data)); + memcpy(pegasus->eth_regs, data, sizeof (data)); set_registers(pegasus, EthCtrl0, 3, data); if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS || @@ -486,18 +478,18 @@ return 0; } -static void fill_skb_pool(pegasus_t *pegasus) +static void fill_skb_pool(pegasus_t * pegasus) { int i; - for (i=0; i < RX_SKBS; i++) { + for (i = 0; i < RX_SKBS; i++) { if (pegasus->rx_pool[i]) continue; pegasus->rx_pool[i] = dev_alloc_skb(PEGASUS_MTU + 2); /* - ** we give up if the allocation fail. the tasklet will be - ** rescheduled again anyway... - */ + ** we give up if the allocation fail. the tasklet will be + ** rescheduled again anyway... + */ if (pegasus->rx_pool[i] == NULL) return; pegasus->rx_pool[i]->dev = pegasus->net; @@ -505,11 +497,11 @@ } } -static void free_skb_pool(pegasus_t *pegasus) +static void free_skb_pool(pegasus_t * pegasus) { int i; - for (i=0; i < RX_SKBS; i++) { + for (i = 0; i < RX_SKBS; i++) { if (pegasus->rx_pool[i]) { dev_kfree_skb(pegasus->rx_pool[i]); pegasus->rx_pool[i] = NULL; @@ -517,12 +509,12 @@ } } -static inline struct sk_buff *pull_skb(pegasus_t *pegasus) +static inline struct sk_buff *pull_skb(pegasus_t * pegasus) { int i; struct sk_buff *skb; - for (i=0; i < RX_SKBS; i++) { + for (i = 0; i < RX_SKBS; i++) { if (likely(pegasus->rx_pool[i] != NULL)) { skb = pegasus->rx_pool[i]; pegasus->rx_pool[i] = NULL; @@ -563,7 +555,7 @@ if (!count) goto goon; - rx_status = le32_to_cpu(*(int *)(urb->transfer_buffer + count - 4)); + rx_status = le32_to_cpu(*(int *) (urb->transfer_buffer + count - 4)); if (rx_status & 0x000e0000) { dbg("%s: RX packet error %x", net->name, rx_status & 0xe0000); pegasus->stats.rx_errors++; @@ -575,20 +567,24 @@ pegasus->stats.rx_frame_errors++; goto goon; } - pkt_len = (rx_status & 0xfff) - 8; + if (pegasus->chip == 0x8513) { + pkt_len = le32_to_cpu(*(int *)urb->transfer_buffer); + pkt_len &= 0x0fff; + pegasus->rx_skb->data += 2; + } else { + pkt_len = (rx_status & 0xfff) - 8; + } - if (pegasus->rx_skb == NULL) - printk("%s: rx_skb == NULL\n", __FUNCTION__); /* - ** we are sure at this point pegasus->rx_skb != NULL - ** so we go ahead and pass up the packet. - */ + * at this point we are sure pegasus->rx_skb != NULL + * so we go ahead and pass up the packet. + */ skb_put(pegasus->rx_skb, pkt_len); pegasus->rx_skb->protocol = eth_type_trans(pegasus->rx_skb, net); netif_rx(pegasus->rx_skb); pegasus->stats.rx_packets++; pegasus->stats.rx_bytes += pkt_len; - + spin_lock(&pegasus->rx_pool_lock); pegasus->rx_skb = pull_skb(pegasus); spin_unlock(&pegasus->rx_pool_lock); @@ -597,19 +593,19 @@ goto tl_sched; goon: usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb, - usb_rcvbulkpipe(pegasus->usb, 1), - pegasus->rx_skb->data, PEGASUS_MTU + 8, - read_bulk_callback, pegasus); + usb_rcvbulkpipe(pegasus->usb, 1), + pegasus->rx_skb->data, PEGASUS_MTU + 8, + read_bulk_callback, pegasus); if (usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC)) { pegasus->flags |= PEGASUS_RX_URB_FAIL; goto tl_sched; } else { pegasus->flags &= ~PEGASUS_RX_URB_FAIL; } - + return; - -tl_sched: + + tl_sched: tasklet_schedule(&pegasus->rx_tl); } @@ -617,7 +613,7 @@ { pegasus_t *pegasus; - pegasus = (pegasus_t *)data; + pegasus = (pegasus_t *) data; spin_lock_irq(&pegasus->rx_pool_lock); fill_skb_pool(pegasus); @@ -636,9 +632,9 @@ return; } usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb, - usb_rcvbulkpipe(pegasus->usb, 1), - pegasus->rx_skb->data, PEGASUS_MTU + 8, - read_bulk_callback, pegasus); + usb_rcvbulkpipe(pegasus->usb, 1), + pegasus->rx_skb->data, PEGASUS_MTU + 8, + read_bulk_callback, pegasus); try_again: if (usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC)) { pegasus->flags |= PEGASUS_RX_URB_FAIL; @@ -704,10 +700,9 @@ } } - status = usb_submit_urb (urb, SLAB_ATOMIC); + status = usb_submit_urb(urb, SLAB_ATOMIC); if (status) - err ("%s: can't resubmit interrupt urb, %d", - net->name, status); + err("%s: can't resubmit interrupt urb, %d", net->name, status); } static void pegasus_tx_timeout(struct net_device *net) @@ -735,9 +730,9 @@ ((__u16 *) pegasus->tx_buff)[0] = cpu_to_le16(l16); memcpy(pegasus->tx_buff + 2, skb->data, skb->len); usb_fill_bulk_urb(pegasus->tx_urb, pegasus->usb, - usb_sndbulkpipe(pegasus->usb, 2), - pegasus->tx_buff, count, - write_bulk_callback, pegasus); + usb_sndbulkpipe(pegasus->usb, 2), + pegasus->tx_buff, count, + write_bulk_callback, pegasus); if ((res = usb_submit_urb(pegasus->tx_urb, GFP_ATOMIC))) { warn("failed tx_urb %d", res); pegasus->stats.tx_errors++; @@ -794,7 +789,7 @@ } -static void free_all_urbs(pegasus_t *pegasus) +static void free_all_urbs(pegasus_t * pegasus) { usb_free_urb(pegasus->intr_urb); usb_free_urb(pegasus->tx_urb); @@ -802,7 +797,7 @@ usb_free_urb(pegasus->ctrl_urb); } -static void unlink_all_urbs(pegasus_t *pegasus) +static void unlink_all_urbs(pegasus_t * pegasus) { usb_unlink_urb(pegasus->intr_urb); usb_unlink_urb(pegasus->tx_urb); @@ -810,7 +805,7 @@ usb_unlink_urb(pegasus->ctrl_urb); } -static int alloc_urbs(pegasus_t *pegasus) +static int alloc_urbs(pegasus_t * pegasus) { pegasus->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL); if (!pegasus->ctrl_urb) { @@ -846,22 +841,22 @@ if (pegasus->rx_skb == NULL) pegasus->rx_skb = pull_skb(pegasus); /* - ** Note: no point to free the pool. it is empty :-) - */ + ** Note: no point to free the pool. it is empty :-) + */ if (!pegasus->rx_skb) return -ENOMEM; down(&pegasus->sem); usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb, - usb_rcvbulkpipe(pegasus->usb, 1), - pegasus->rx_skb->data, PEGASUS_MTU + 8, - read_bulk_callback, pegasus); + usb_rcvbulkpipe(pegasus->usb, 1), + pegasus->rx_skb->data, PEGASUS_MTU + 8, + read_bulk_callback, pegasus); if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL))) warn("%s: failed rx_urb %d", __FUNCTION__, res); usb_fill_int_urb(pegasus->intr_urb, pegasus->usb, - usb_rcvintpipe(pegasus->usb, 3), - pegasus->intr_buff, sizeof(pegasus->intr_buff), - intr_callback, pegasus, pegasus->intr_interval); + usb_rcvintpipe(pegasus->usb, 3), + pegasus->intr_buff, sizeof (pegasus->intr_buff), + intr_callback, pegasus, pegasus->intr_interval); if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL))) warn("%s: failed intr_urb %d", __FUNCTION__, res); netif_start_queue(net); @@ -896,7 +891,82 @@ return 0; } +#ifdef CONFIG_MII +static int pegasus_ethtool_ioctl(struct net_device *dev, void *useraddr) +{ + u32 ethcmd; + pegasus_t *pegasus = dev->priv; + + if (copy_from_user(ðcmd, useraddr, sizeof (ethcmd))) + return -EFAULT; + + switch (ethcmd) { + /* get driver-specific version/etc. info */ + case ETHTOOL_GDRVINFO:{ + struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; + strncpy(info.driver, driver_name, + sizeof (info.driver) - 1); + strncpy(info.version, DRIVER_VERSION, + sizeof (info.version) - 1); + if (copy_to_user(useraddr, &info, sizeof (info))) + return -EFAULT; + return 0; + } + + /* get settings */ + case ETHTOOL_GSET:{ + struct ethtool_cmd ecmd = { ETHTOOL_GSET }; + mii_ethtool_gset(&pegasus->mii, &ecmd); + if (copy_to_user(useraddr, &ecmd, sizeof (ecmd))) + return -EFAULT; + return 0; + } + /* set settings */ + case ETHTOOL_SSET:{ + int r; + struct ethtool_cmd ecmd; + if (copy_from_user(&ecmd, useraddr, sizeof (ecmd))) + return -EFAULT; + r = mii_ethtool_sset(&pegasus->mii, &ecmd); + return r; + } + /* restart autonegotiation */ + case ETHTOOL_NWAY_RST:{ + return mii_nway_restart(&pegasus->mii); + } + + /* get link status */ + case ETHTOOL_GLINK:{ + struct ethtool_value edata = { ETHTOOL_GLINK }; + edata.data = mii_link_ok(&pegasus->mii); + if (copy_to_user(useraddr, &edata, sizeof (edata))) + return -EFAULT; + return 0; + } + /* get message-level */ + case ETHTOOL_GMSGLVL:{ + struct ethtool_value edata = { ETHTOOL_GMSGLVL }; + /* edata.data = pegasus->msg_enable; FIXME */ + if (copy_to_user(useraddr, &edata, sizeof (edata))) + return -EFAULT; + return 0; + } + /* set message-level */ + case ETHTOOL_SMSGLVL:{ + struct ethtool_value edata; + if (copy_from_user(&edata, useraddr, sizeof (edata))) + return -EFAULT; + /* sp->msg_enable = edata.data; FIXME */ + return 0; + } + + } + + return -EOPNOTSUPP; + +} +#else static int pegasus_ethtool_ioctl(struct net_device *net, void *uaddr) { pegasus_t *pegasus; @@ -912,8 +982,8 @@ strncpy(info.version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN); usb_make_path(pegasus->usb, info.bus_info, - sizeof info.bus_info); - if (copy_to_user(uaddr, &info, sizeof(info))) + sizeof info.bus_info); + if (copy_to_user(uaddr, &info, sizeof (info))) return -EFAULT; return 0; } @@ -950,7 +1020,7 @@ ecmd.duplex = bmcr & BMCR_FULLDPLX ? DUPLEX_FULL : DUPLEX_HALF; } - if (copy_to_user(uaddr, &ecmd, sizeof(ecmd))) + if (copy_to_user(uaddr, &ecmd, sizeof (ecmd))) return -EFAULT; return 0; @@ -961,7 +1031,7 @@ case ETHTOOL_GLINK:{ struct ethtool_value edata = { ETHTOOL_GLINK }; edata.data = netif_carrier_ok(net); - if (copy_to_user(uaddr, &edata, sizeof(edata))) + if (copy_to_user(uaddr, &edata, sizeof (edata))) return -EFAULT; return 0; } @@ -969,7 +1039,7 @@ return -EOPNOTSUPP; } } - +#endif static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd) { __u16 *data = (__u16 *) & rq->ifr_data; @@ -1045,8 +1115,26 @@ static inline void setup_pegasus_II(pegasus_t * pegasus) { + u16 data = 0xa5; + set_register(pegasus, Reg1d, 0); + set_register(pegasus, Reg7b, 1); + mdelay(100); set_register(pegasus, Reg7b, 2); + + set_register(pegasus, 0x83, data); + get_registers(pegasus, 0x83, 1, &data); + + if (data == 0xa5) { + pegasus->chip = 0x8513; + } else { + pegasus->chip = 0; + } + + set_register(pegasus, 0x80, 0xc0); + set_register(pegasus, 0x83, 0xff); + set_register(pegasus, 0x84, 0x01); + if (pegasus->features & HAS_HOME_PNA && mii_mode) set_register(pegasus, Reg81, 6); else @@ -1065,13 +1153,13 @@ err("usb_set_configuration() failed"); return -ENODEV; } - if (!(pegasus = kmalloc(sizeof(struct pegasus), GFP_KERNEL))) { + if (!(pegasus = kmalloc(sizeof (struct pegasus), GFP_KERNEL))) { err("out of memory allocating device structure"); return -ENOMEM; } usb_get_dev(dev); - memset(pegasus, 0, sizeof(struct pegasus)); + memset(pegasus, 0, sizeof (struct pegasus)); pegasus->dev_index = dev_index; init_waitqueue_head(&pegasus->ctrl_wait); @@ -1088,8 +1176,8 @@ } init_MUTEX(&pegasus->sem); - tasklet_init(&pegasus->rx_tl, rx_fixup, (unsigned long)pegasus); - + tasklet_init(&pegasus->rx_tl, rx_fixup, (unsigned long) pegasus); + down(&pegasus->sem); pegasus->usb = dev; pegasus->net = net; @@ -1104,6 +1192,11 @@ net->set_multicast_list = pegasus_set_multicast; net->get_stats = pegasus_netdev_stats; net->mtu = PEGASUS_MTU; + pegasus->mii.dev = net; + pegasus->mii.mdio_read = mdio_read; + pegasus->mii.mdio_write = mdio_write; + pegasus->mii.phy_id_mask = 0x1f; + pegasus->mii.reg_num_mask = 0x1f; spin_lock_init(&pegasus->rx_pool_lock); pegasus->features = usb_dev_id[dev_index].private; @@ -1132,7 +1225,7 @@ exit: up(&pegasus->sem); if (pegasus) { - dev_set_drvdata (&intf->dev, pegasus); + dev_set_drvdata(&intf->dev, pegasus); return 0; } return -EIO; @@ -1140,9 +1233,9 @@ static void pegasus_disconnect(struct usb_interface *intf) { - struct pegasus *pegasus = dev_get_drvdata (&intf->dev); + struct pegasus *pegasus = dev_get_drvdata(&intf->dev); - dev_set_drvdata (&intf->dev, NULL); + dev_set_drvdata(&intf->dev, NULL); if (!pegasus) { warn("unregistering non-existant device"); return; @@ -1162,10 +1255,10 @@ } static struct usb_driver pegasus_driver = { - .name = driver_name, - .probe = pegasus_probe, - .disconnect = pegasus_disconnect, - .id_table = pegasus_ids, + .name = driver_name, + .probe = pegasus_probe, + .disconnect = pegasus_disconnect, + .id_table = pegasus_ids, }; int __init pegasus_init(void) diff -Nru a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h --- a/drivers/usb/net/pegasus.h Fri Nov 22 13:41:23 2002 +++ b/drivers/usb/net/pegasus.h Fri Nov 22 13:41:23 2002 @@ -85,6 +85,7 @@ struct usb_device *usb; struct net_device *net; struct net_device_stats stats; + struct mii_if_info mii; unsigned flags; unsigned features; int dev_index; @@ -97,6 +98,7 @@ wait_queue_head_t ctrl_wait; struct semaphore sem; spinlock_t rx_pool_lock; + int chip; unsigned char intr_buff[8]; __u8 tx_buff[PEGASUS_MTU]; __u8 eth_regs[4]; @@ -131,11 +133,11 @@ #define VENDOR_LANEED 0x056e #define VENDOR_LINKSYS 0x066b #define VENDOR_MELCO 0x0411 +#define VENDOR_NETGEAR 0x0846 #define VENDOR_SMARTBRIDGES 0x08d1 #define VENDOR_SMC 0x0707 #define VENDOR_SOHOWARE 0x15e8 #define VENDOR_SIEMENS 0x067c -#define VENDOR_JTEC 0x11ad #else /* PEGASUS_DEV */ @@ -169,7 +171,10 @@ PEGASUS_DEV( "ADMtek ADM8511 \"Pegasus II\" USB Ethernet", VENDOR_ADMTEK, 0x8511, DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "ADMtek AN986 \"Pegasus\" USB Ethernet (eval. board)", +PEGASUS_DEV( "ADMtek ADM8513 \"Pegasus II\" USB Ethernet", + VENDOR_ADMTEK, 0x8513, + DEFAULT_GPIO_RESET | PEGASUS_II ) +PEGASUS_DEV( "ADMtek AN986 \"Pegasus\" USB Ethernet (evaluation board)", VENDOR_ADMTEK, 0x0986, DEFAULT_GPIO_RESET | HAS_HOME_PNA ) PEGASUS_DEV( "AN986A USB MAC", VENDOR_ADMTEK, 1986, @@ -192,7 +197,7 @@ DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "Corega FEter USB-TX", VENDOR_COREGA, 0x0004, DEFAULT_GPIO_RESET ) -PEGASUS_DEV( "Corega FEter", VENDOR_COREGA, 0x000d, +PEGASUS_DEV( "Corega FEter USB-TXS", VENDOR_COREGA, 0x000d, DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4001, LINKSYS_GPIO_RESET ) @@ -246,6 +251,8 @@ DEFAULT_GPIO_RESET ) PEGASUS_DEV( "MELCO/BUFFALO LUA2-TX", VENDOR_MELCO, 0x0009, DEFAULT_GPIO_RESET | PEGASUS_II ) +PEGASUS_DEV( "NETGEAR FA101", VENDOR_NETGEAR, 0x1020, + DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "smartNIC 2 PnP Adapter", VENDOR_SMARTBRIDGES, 0x0003, DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "SMC 202 USB Ethernet", VENDOR_SMC, 0x0200, @@ -257,8 +264,6 @@ PEGASUS_DEV( "SOHOware NUB110 Ethernet", VENDOR_SOHOWARE, 0x9110, DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_SIEMENS, 0x1001, - DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "FA8101 USB To ETHERNET", VENDOR_JTEC, 0x8101, DEFAULT_GPIO_RESET | PEGASUS_II ) diff -Nru a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c --- a/drivers/usb/serial/usb-serial.c Fri Nov 22 13:41:19 2002 +++ b/drivers/usb/serial/usb-serial.c Fri Nov 22 13:41:19 2002 @@ -14,6 +14,10 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (11/19/2002) gkh + * removed a few #ifdefs for the generic code and cleaned up the failure + * logic in initialization. + * * (10/02/2002) gkh * moved the console code to console.c and out of this file. * @@ -341,7 +345,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.6" +#define DRIVER_VERSION "v1.7" #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/" #define DRIVER_DESC "USB Serial Driver core" @@ -382,7 +386,29 @@ {.driver_info = 42}, {} }; -#endif + +static int generic_register (void) +{ + generic_device_ids[0].idVendor = vendor; + generic_device_ids[0].idProduct = product; + generic_device_ids[0].match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT; + + /* register our generic driver with ourselves */ + return usb_serial_register (&generic_device); +} + +static void generic_deregister (void) +{ + /* remove our generic driver */ + usb_serial_deregister (&generic_device); +} + +#else + +static inline int generic_register (void) { return 0; } +static inline void generic_deregister (void) { } + +#endif /* CONFIG_USB_SERIAL_GENERIC */ /* Driver structure we register with the USB core */ static struct usb_driver usb_serial_driver = { @@ -409,7 +435,6 @@ static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */ static LIST_HEAD(usb_serial_driver_list); - struct usb_serial *usb_serial_get_by_minor (unsigned int minor) { return serial_table[minor]; @@ -839,7 +864,7 @@ length += sprintf (page+length, "%d:", i); if (serial->type->owner) - length += sprintf (page+length, " module:%s", serial->type->owner->name); + length += sprintf (page+length, " module:%s", module_name(serial->type->owner)); length += sprintf (page+length, " name:\"%s\"", serial->type->name); length += sprintf (page+length, " vendor:%04x product:%04x", serial->vendor, serial->product); length += sprintf (page+length, " num_ports:%d", serial->num_ports); @@ -1574,40 +1599,49 @@ static int __init usb_serial_init(void) { int i; - int result; + int result = 0; /* Initalize our global data */ for (i = 0; i < SERIAL_TTY_MINORS; ++i) { serial_table[i] = NULL; } + /* register the generic driver, if we should */ + result = generic_register(); + if (result < 0) { + err("%s - registering generic driver failed", __FUNCTION__); + goto exit; + } + /* register the tty driver */ serial_tty_driver.init_termios = tty_std_termios; serial_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - if (tty_register_driver (&serial_tty_driver)) { - err("%s - failed to register tty driver", __FUNCTION__); - return -1; + result = tty_register_driver (&serial_tty_driver); + if (result) { + err("%s - tty_register_driver failed", __FUNCTION__); + goto exit_generic; } /* register the USB driver */ result = usb_register(&usb_serial_driver); if (result < 0) { - tty_unregister_driver(&serial_tty_driver); - err("usb_register failed for the usb-serial driver. Error number %d", result); - return -1; + err("%s - usb_register failed", __FUNCTION__); + goto exit_tty; } -#ifdef CONFIG_USB_SERIAL_GENERIC - generic_device_ids[0].idVendor = vendor; - generic_device_ids[0].idProduct = product; - generic_device_ids[0].match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT; - /* register our generic driver with ourselves */ - usb_serial_register (&generic_device); -#endif - info(DRIVER_DESC " " DRIVER_VERSION); - return 0; + return result; + +exit_tty: + tty_unregister_driver(&serial_tty_driver); + +exit_generic: + generic_deregister(); + +exit: + err ("%s - returning with error %d", __FUNCTION__, result); + return result; } @@ -1615,11 +1649,8 @@ { usb_serial_console_exit(); -#ifdef CONFIG_USB_SERIAL_GENERIC - /* remove our generic driver */ - usb_serial_deregister (&generic_device); -#endif - + generic_deregister(); + usb_deregister(&usb_serial_driver); tty_unregister_driver(&serial_tty_driver); } diff -Nru a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c --- a/drivers/usb/storage/freecom.c Fri Nov 22 13:41:23 2002 +++ b/drivers/usb/storage/freecom.c Fri Nov 22 13:41:23 2002 @@ -115,7 +115,7 @@ freecom_udata_t extra = (freecom_udata_t) us->extra; struct freecom_xfer_wrap *fxfr = (struct freecom_xfer_wrap *) extra->buffer; - int result, partial; + int result; fxfr->Type = FCM_PACKET_INPUT | 0x00; fxfr->Timeout = 0; /* Short timeout for debugging. */ @@ -125,14 +125,12 @@ US_DEBUGP("Read data Freecom! (c=%d)\n", count); /* Issue the transfer command. */ - result = usb_stor_bulk_msg (us, fxfr, opipe, - FCM_PACKET_LENGTH, &partial); + result = usb_stor_bulk_transfer_buf (us, opipe, fxfr, + FCM_PACKET_LENGTH, NULL); if (result != USB_STOR_XFER_GOOD) { - US_DEBUGP ("Freecom readdata xport failure: r=%d, p=%d\n", - result, partial); + US_DEBUGP ("Freecom readdata transport error\n"); return USB_STOR_TRANSPORT_ERROR; } - US_DEBUGP("Done issuing read request: %d %d\n", result, partial); /* Now transfer all of our blocks. */ US_DEBUGP("Start of read\n"); @@ -151,7 +149,7 @@ freecom_udata_t extra = (freecom_udata_t) us->extra; struct freecom_xfer_wrap *fxfr = (struct freecom_xfer_wrap *) extra->buffer; - int result, partial; + int result; fxfr->Type = FCM_PACKET_OUTPUT | 0x00; fxfr->Timeout = 0; /* Short timeout for debugging. */ @@ -161,15 +159,12 @@ US_DEBUGP("Write data Freecom! (c=%d)\n", count); /* Issue the transfer command. */ - result = usb_stor_bulk_msg (us, fxfr, opipe, - FCM_PACKET_LENGTH, &partial); + result = usb_stor_bulk_transfer_buf (us, opipe, fxfr, + FCM_PACKET_LENGTH, NULL); if (result != USB_STOR_XFER_GOOD) { - US_DEBUGP ("Freecom writedata xport failure: r=%d, p=%d\n", - result, partial); + US_DEBUGP ("Freecom writedata transport error\n"); return USB_STOR_TRANSPORT_ERROR; } - US_DEBUGP("Done issuing write request: %d %d\n", - result, partial); /* Now transfer all of our blocks. */ US_DEBUGP("Start of write\n"); @@ -191,7 +186,7 @@ struct freecom_status *fst; unsigned int ipipe, opipe; /* We need both pipes. */ int result; - int partial; + unsigned int partial; int length; freecom_udata_t extra; @@ -215,23 +210,22 @@ US_DEBUG(pdump (srb->cmnd, 12)); /* Send it out. */ - result = usb_stor_bulk_msg (us, fcb, opipe, - FCM_PACKET_LENGTH, &partial); + result = usb_stor_bulk_transfer_buf (us, opipe, fcb, + FCM_PACKET_LENGTH, NULL); /* The Freecom device will only fail if there is something wrong in * USB land. It returns the status in its own registers, which * come back in the bulk pipe. */ if (result != USB_STOR_XFER_GOOD) { - US_DEBUGP ("freecom xport failure: r=%d, p=%d\n", - result, partial); + US_DEBUGP ("freecom transport error\n"); return USB_STOR_TRANSPORT_ERROR; } /* There are times we can optimize out this status read, but it * doesn't hurt us to always do it now. */ - result = usb_stor_bulk_msg (us, fst, ipipe, + result = usb_stor_bulk_transfer_buf (us, ipipe, fst, FCM_PACKET_LENGTH, &partial); - US_DEBUGP("foo Status result %d %d\n", result, partial); + US_DEBUGP("foo Status result %d %u\n", result, partial); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -256,24 +250,23 @@ memset (fcb->Filler, 0, sizeof (fcb->Filler)); /* Send it out. */ - result = usb_stor_bulk_msg (us, fcb, opipe, - FCM_PACKET_LENGTH, &partial); + result = usb_stor_bulk_transfer_buf (us, opipe, fcb, + FCM_PACKET_LENGTH, NULL); /* The Freecom device will only fail if there is something * wrong in USB land. It returns the status in its own * registers, which come back in the bulk pipe. */ if (result != USB_STOR_XFER_GOOD) { - US_DEBUGP ("freecom xport failure: r=%d, p=%d\n", - result, partial); + US_DEBUGP ("freecom transport error\n"); return USB_STOR_TRANSPORT_ERROR; } /* get the data */ - result = usb_stor_bulk_msg (us, fst, ipipe, + result = usb_stor_bulk_transfer_buf (us, ipipe, fst, FCM_PACKET_LENGTH, &partial); - US_DEBUGP("bar Status result %d %d\n", result, partial); + US_DEBUGP("bar Status result %d %u\n", result, partial); if (result > USB_STOR_XFER_SHORT) return USB_STOR_TRANSPORT_ERROR; @@ -328,7 +321,7 @@ return result; US_DEBUGP("FCM: Waiting for status\n"); - result = usb_stor_bulk_msg (us, fst, ipipe, + result = usb_stor_bulk_transfer_buf (us, ipipe, fst, FCM_PACKET_LENGTH, &partial); US_DEBUG(pdump ((void *) fst, partial)); @@ -354,7 +347,7 @@ return result; US_DEBUGP("FCM: Waiting for status\n"); - result = usb_stor_bulk_msg (us, fst, ipipe, + result = usb_stor_bulk_transfer_buf (us, ipipe, fst, FCM_PACKET_LENGTH, &partial); if (partial != 4 || result > USB_STOR_XFER_SHORT) @@ -385,13 +378,6 @@ } return USB_STOR_TRANSPORT_GOOD; - - US_DEBUGP("Freecom: transfer_length = %d\n", - usb_stor_transfer_length (srb)); - - US_DEBUGP("Freecom: direction = %d\n", srb->sc_data_direction); - - return USB_STOR_TRANSPORT_ERROR; } int diff -Nru a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c --- a/drivers/usb/storage/isd200.c Fri Nov 22 13:41:20 2002 +++ b/drivers/usb/storage/isd200.c Fri Nov 22 13:41:20 2002 @@ -668,7 +668,7 @@ #endif /* let's send the command via the control pipe */ - result = usb_stor_control_msg( + result = usb_stor_ctrl_transfer( us, us->send_ctrl_pipe, 0x01, @@ -709,7 +709,7 @@ /* read the configuration information from ISD200. Use this to */ /* determine what the special ATA CDB bytes are. */ - result = usb_stor_control_msg( + result = usb_stor_ctrl_transfer( us, us->recv_ctrl_pipe, 0x02, diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c --- a/drivers/usb/storage/transport.c Fri Nov 22 13:41:19 2002 +++ b/drivers/usb/storage/transport.c Fri Nov 22 13:41:19 2002 @@ -479,7 +479,7 @@ usb_stor_blocking_completion, NULL); status = usb_stor_msg_common(us); - /* return the actual length of the data transferred if no error*/ + /* return the actual length of the data transferred if no error */ if (status >= 0) status = us->current_urb->actual_length; return status; @@ -543,48 +543,92 @@ return 0; } + /* - * Transfer one control message + * Interpret the results of a URB transfer * - * This function does basically the same thing as usb_stor_control_msg() - * above, except that return codes are USB_STOR_XFER_xxx rather than the - * urb status or transfer length. + * This function prints appropriate debugging messages, clears halts on + * bulk endpoints, and translates the status to the corresponding + * USB_STOR_XFER_xxx return code. */ -int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe, - u8 request, u8 requesttype, u16 value, u16 index, - void *data, u16 size) { - int result; +static int interpret_urb_result(struct us_data *us, unsigned int pipe, + unsigned int length, int result, unsigned int partial) { - US_DEBUGP("usb_stor_ctrl_transfer(): rq=%02x rqtype=%02x " - "value=%04x index=%02x len=%d\n", - request, requesttype, value, index, size); - result = usb_stor_control_msg(us, pipe, request, requesttype, - value, index, data, size); - US_DEBUGP("usb_stor_control_msg returned %d\n", result); + US_DEBUGP("Status code %d; transferred %u/%u\n", + result, partial, length); - /* a stall indicates a protocol error */ + /* stalled */ if (result == -EPIPE) { - US_DEBUGP("-- stall on control pipe\n"); + + /* for non-bulk (i.e., control) endpoints, a stall indicates + * a protocol error */ + if (!usb_pipebulk(pipe)) { + US_DEBUGP("-- stall on control pipe\n"); + return USB_STOR_XFER_ERROR; + } + + /* for a bulk endpoint, clear the stall */ + US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); + if (usb_stor_clear_halt(us, pipe) < 0) + return USB_STOR_XFER_ERROR; + return USB_STOR_XFER_STALLED; + } + + /* NAK - that means we've retried this a few times already */ + if (result == -ETIMEDOUT) { + US_DEBUGP("-- device NAKed\n"); + return USB_STOR_XFER_ERROR; + } + + /* the transfer was cancelled, presumably by an abort */ + if (result == -ENODEV) { + US_DEBUGP("-- transfer cancelled\n"); return USB_STOR_XFER_ERROR; } - /* some other serious problem here */ + /* the catch-all error case */ if (result < 0) { US_DEBUGP("-- unknown error\n"); return USB_STOR_XFER_ERROR; } - /* was the entire command transferred? */ - if (result < size) { - US_DEBUGP("-- transferred only %d bytes\n", result); + /* no error code; did we send all the data? */ + if (partial != length) { + US_DEBUGP("-- transferred only %u bytes\n", partial); return USB_STOR_XFER_SHORT; } - US_DEBUGP("-- transfer completed successfully\n"); + US_DEBUGP("-- transfer complete\n"); return USB_STOR_XFER_GOOD; } /* + * Transfer one control message + * + * This function does basically the same thing as usb_stor_control_msg() + * above, except that return codes are USB_STOR_XFER_xxx rather than the + * urb status or transfer length. + */ +int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe, + u8 request, u8 requesttype, u16 value, u16 index, + void *data, u16 size) { + int result; + unsigned int partial = 0; + + US_DEBUGP("usb_stor_ctrl_transfer(): rq=%02x rqtype=%02x " + "value=%04x index=%02x len=%u\n", + request, requesttype, value, index, size); + result = usb_stor_control_msg(us, pipe, request, requesttype, + value, index, data, size); + + if (result > 0) { /* Separate out the amount transferred */ + partial = result; + result = 0; + } + return interpret_urb_result(us, pipe, size, result, partial); +} + +/* * Transfer one buffer via bulk transfer * * This function does basically the same thing as usb_stor_bulk_msg() @@ -596,50 +640,17 @@ * urb status or transfer length. */ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe, - char *buf, unsigned int length, unsigned int *act_len) + void *buf, unsigned int length, unsigned int *act_len) { int result; - int partial; + unsigned int partial; /* transfer the data */ - US_DEBUGP("usb_stor_bulk_transfer_buf(): xfer %d bytes\n", length); + US_DEBUGP("usb_stor_bulk_transfer_buf(): xfer %u bytes\n", length); result = usb_stor_bulk_msg(us, buf, pipe, length, &partial); - US_DEBUGP("usb_stor_bulk_msg() returned %d xferred %d/%d\n", - result, partial, length); if (act_len) *act_len = partial; - - /* if we stall, we need to clear it before we go on */ - if (result == -EPIPE) { - US_DEBUGP("clearing endpoint halt for pipe 0x%x," - " stalled at %d bytes\n", pipe, partial); - if (usb_stor_clear_halt(us, pipe) < 0) - return USB_STOR_XFER_ERROR; - return USB_STOR_XFER_STALLED; - } - - /* NAK - that means we've retried a few times already */ - if (result == -ETIMEDOUT) { - US_DEBUGP("-- device NAKed\n"); - return USB_STOR_XFER_ERROR; - } - - /* the catch-all error case */ - if (result) { - US_DEBUGP("-- unknown error\n"); - return USB_STOR_XFER_ERROR; - } - - /* did we send all the data? */ - if (partial == length) { - US_DEBUGP("-- transfer complete\n"); - return USB_STOR_XFER_GOOD; - } - - /* no error code, so we must have transferred some data, - * just not all of it */ - US_DEBUGP("-- transferred only %d bytes\n", partial); - return USB_STOR_XFER_SHORT; + return interpret_urb_result(us, pipe, length, result, partial); } /* @@ -653,10 +664,10 @@ unsigned int *act_len) { int result; - int partial; + unsigned int partial; /* initialize the scatter-gather request block */ - US_DEBUGP("usb_stor_bulk_transfer_sglist(): xfer %d bytes, " + US_DEBUGP("usb_stor_bulk_transfer_sglist(): xfer %u bytes, " "%d entries\n", length, num_sg); result = usb_sg_init(us->current_sg, us->pusb_dev, pipe, 0, sg, num_sg, length, SLAB_NOIO); @@ -685,55 +696,22 @@ result = us->current_sg->status; partial = us->current_sg->bytes; - US_DEBUGP("usb_sg_wait() returned %d xferred %d/%d\n", - result, partial, length); if (act_len) *act_len = partial; - - /* if we stall, we need to clear it before we go on */ - if (result == -EPIPE) { - US_DEBUGP("clearing endpoint halt for pipe 0x%x, " - "stalled at %d bytes\n", pipe, partial); - if (usb_stor_clear_halt(us, pipe) < 0) - return USB_STOR_XFER_ERROR; - return USB_STOR_XFER_STALLED; - } - - /* NAK - that means we've retried this a few times already */ - if (result == -ETIMEDOUT) { - US_DEBUGP("-- device NAKed\n"); - return USB_STOR_XFER_ERROR; - } - - /* the catch-all error case */ - if (result) { - US_DEBUGP("-- unknown error\n"); - return USB_STOR_XFER_ERROR; - } - - /* did we send all the data? */ - if (partial == length) { - US_DEBUGP("-- transfer complete\n"); - return USB_STOR_XFER_GOOD; - } - - /* no error code, so we must have transferred some data, - * just not all of it */ - US_DEBUGP("-- transferred only %d bytes\n", partial); - return USB_STOR_XFER_SHORT; + return interpret_urb_result(us, pipe, length, result, partial); } /* * Transfer an entire SCSI command's worth of data payload over the bulk * pipe. * - * Nore that this uses usb_stor_bulk_transfer_buf() and + * Note that this uses usb_stor_bulk_transfer_buf() and * usb_stor_bulk_transfer_sglist() to achieve its goals -- * this function simply determines whether we're going to use * scatter-gather or not, and acts appropriately. */ int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe, - char *buf, unsigned int length_left, int use_sg, int *residual) + void *buf, unsigned int length_left, int use_sg, int *residual) { int result; unsigned int partial; @@ -1278,7 +1256,7 @@ (bcb.Lun >> 4), (bcb.Lun & 0x0F), le32_to_cpu(bcb.DataTransferLength), bcb.Flags, bcb.Length); result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, - (char *) &bcb, US_BULK_CB_WRAP_LEN, NULL); + &bcb, US_BULK_CB_WRAP_LEN, NULL); US_DEBUGP("Bulk command transfer result=%d\n", result); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -1302,7 +1280,7 @@ /* get CSW for device status */ US_DEBUGP("Attempting to get CSW...\n"); result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, - (char *) &bcs, US_BULK_CS_WRAP_LEN, NULL); + &bcs, US_BULK_CS_WRAP_LEN, NULL); /* did the attempt to read the CSW fail? */ if (result == USB_STOR_XFER_STALLED) { @@ -1310,7 +1288,7 @@ /* get the status again */ US_DEBUGP("Attempting to get CSW (2nd try)...\n"); result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, - (char *) &bcs, US_BULK_CS_WRAP_LEN, NULL); + &bcs, US_BULK_CS_WRAP_LEN, NULL); } /* if we still have a failure at this point, we're in trouble */ diff -Nru a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h --- a/drivers/usb/storage/transport.h Fri Nov 22 13:41:19 2002 +++ b/drivers/usb/storage/transport.h Fri Nov 22 13:41:19 2002 @@ -117,6 +117,7 @@ /* * usb_stor_bulk_transfer_xxx() return codes, in order of severity */ + #define USB_STOR_XFER_GOOD 0 /* good transfer */ #define USB_STOR_XFER_SHORT 1 /* transfered less than expected */ #define USB_STOR_XFER_STALLED 2 /* endpoint stalled */ @@ -129,7 +130,14 @@ #define USB_STOR_TRANSPORT_GOOD 0 /* Transport good, command good */ #define USB_STOR_TRANSPORT_FAILED 1 /* Transport good, command failed */ #define USB_STOR_TRANSPORT_ERROR 2 /* Transport bad (i.e. device dead) */ -#define USB_STOR_TRANSPORT_ABORTED 3 /* Transport aborted */ + +/* + * We used to have USB_STOR_XFER_ABORTED and USB_STOR_TRANSPORT_ABORTED + * return codes. But now the transport and low-level transfer routines + * treat an abort as just another error (-ENOENT for a cancelled URB). + * It is up to the invoke_transport() function to test for aborts and + * distinguish them from genuine communication errors. + */ /* * CBI accept device specific command @@ -162,12 +170,12 @@ u8 request, u8 requesttype, u16 value, u16 index, void *data, u16 size); extern int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe, - char *buf, unsigned int length, unsigned int *act_len); + void *buf, unsigned int length, unsigned int *act_len); extern int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe, struct scatterlist *sg, int num_sg, unsigned int length, unsigned int *act_len); extern int usb_stor_bulk_transfer_sg(struct us_data *us, unsigned int pipe, - char *buf, unsigned int length, int use_sg, int *residual); + void *buf, unsigned int length, int use_sg, int *residual); static __inline__ int usb_stor_bulk_transfer_srb(struct us_data *us, unsigned int pipe, Scsi_Cmnd *srb, unsigned int length) { diff -Nru a/drivers/video/matrox/matroxfb_accel.c b/drivers/video/matrox/matroxfb_accel.c --- a/drivers/video/matrox/matroxfb_accel.c Fri Nov 22 13:41:20 2002 +++ b/drivers/video/matrox/matroxfb_accel.c Fri Nov 22 13:41:21 2002 @@ -758,6 +758,7 @@ } #endif +#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB24) || defined(FBCON_HAS_CFB32) static void matrox_cfbX_revc(struct display* p, int xx, int yy) { CRITFLAGS MINFO_FROM_DISP(p); @@ -778,6 +779,7 @@ CRITEND } +#endif static void matrox_cfbX_clear_margins(struct vc_data* conp, struct display* p, int bottom_only) { unsigned int bottom_height, right_width; diff -Nru a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/matrox/matroxfb_misc.c --- a/drivers/video/matrox/matroxfb_misc.c Fri Nov 22 13:41:21 2002 +++ b/drivers/video/matrox/matroxfb_misc.c Fri Nov 22 13:41:21 2002 @@ -849,7 +849,7 @@ ( bd->pins[86] & 0x0000000F); MINFO->values.reg.opt = ((bd->pins[53] << 15) & 0x00400000) | ((bd->pins[53] << 22) & 0x10000000) | - ((bd->pins[53] << 10) & 0x00001C00); + ((bd->pins[53] << 7) & 0x00001C00); MINFO->values.reg.opt3 = get_u32(bd->pins + 67); MINFO->values.pll.system = (bd->pins[ 65] == 0xFF) ? 200000 : bd->pins[ 65] * 4000; MINFO->features.pll.ref_freq = (bd->pins[ 92] & 0x01) ? 14318 : 27000; diff -Nru a/drivers/zorro/proc.c b/drivers/zorro/proc.c --- a/drivers/zorro/proc.c Fri Nov 22 13:41:18 2002 +++ b/drivers/zorro/proc.c Fri Nov 22 13:41:18 2002 @@ -76,8 +76,8 @@ } static struct file_operations proc_bus_zorro_operations = { - llseek: proc_bus_zorro_lseek, - read: proc_bus_zorro_read, + .llseek = proc_bus_zorro_lseek, + .read = proc_bus_zorro_read, }; static int diff -Nru a/fs/Kconfig b/fs/Kconfig --- a/fs/Kconfig Fri Nov 22 13:41:20 2002 +++ b/fs/Kconfig Fri Nov 22 13:41:20 2002 @@ -531,8 +531,8 @@ levelling, compression and support for hard links. You cannot use this on normal block devices, only on 'MTD' devices. - Further information should be made available soon at - . + Further information on the design and implementation of JFFS2 is + available at . config JFFS2_FS_DEBUG int "JFFS2 debugging verbosity (0 = quiet, 2 = noisy)" @@ -554,6 +554,19 @@ config JFFS2_FS_NAND bool "JFFS2 support for NAND flash (EXPERIMENTAL)" depends on JFFS2_FS && EXPERIMENTAL + default n + ---help--- + This enables the experimental support for NAND flash in JFFS2. NAND + is a newer type of flash chip design than the traditional NOR flash, + with higher density but a handful of characteristics which make it + more interesting for the file system to use. Support for NAND flash + is not yet complete and may corrupt data. For further information, + including a link to the mailing list where details of the remaining + work to be completed for NAND flash support can be found, see the + JFFS2 web site at . + + Say 'N' unless you have NAND flash and you are willing to test and + develop JFFS2 support for it. config CRAMFS tristate "Compressed ROM file system support" diff -Nru a/fs/Makefile b/fs/Makefile --- a/fs/Makefile Fri Nov 22 13:41:21 2002 +++ b/fs/Makefile Fri Nov 22 13:41:21 2002 @@ -8,7 +8,7 @@ export-objs := open.o dcache.o buffer.o bio.o inode.o dquot.o mpage.o aio.o \ fcntl.o read_write.o dcookies.o mbcache.o posix_acl.o xattr_acl.o -obj-y := open.o read_write.o devices.o file_table.o buffer.o \ +obj-y := open.o read_write.o file_table.o buffer.o \ bio.o super.o block_dev.o char_dev.o stat.o exec.o pipe.o \ namei.o fcntl.o ioctl.o readdir.o select.o fifo.o locks.o \ dcache.o inode.o attr.o bad_inode.o file.o dnotify.o \ diff -Nru a/fs/adfs/inode.c b/fs/adfs/inode.c --- a/fs/adfs/inode.c Fri Nov 22 13:41:18 2002 +++ b/fs/adfs/inode.c Fri Nov 22 13:41:18 2002 @@ -179,13 +179,13 @@ * Convert an ADFS time to Unix time. ADFS has a 40-bit centi-second time * referenced to 1 Jan 1900 (til 2248) */ -static unsigned int -adfs_adfs2unix_time(struct inode *inode) +static void +adfs_adfs2unix_time(struct timespec *tv, struct inode *inode) { unsigned int high, low; if (ADFS_I(inode)->stamped == 0) - return CURRENT_TIME; + goto cur_time; high = ADFS_I(inode)->loadaddr << 24; low = ADFS_I(inode)->execaddr; @@ -195,17 +195,32 @@ /* Files dated pre 01 Jan 1970 00:00:00. */ if (high < 0x336e996a) - return 0; + goto too_early; /* Files dated post 18 Jan 2038 03:14:05. */ if (high >= 0x656e9969) - return 0x7ffffffd; + goto too_late; /* discard 2208988800 (0x336e996a00) seconds of time */ high -= 0x336e996a; /* convert 40-bit centi-seconds to 32-bit seconds */ - return (((high % 100) << 8) + low) / 100 + (high / 100 << 8); + tv->tv_sec = (((high % 100) << 8) + low) / 100 + (high / 100 << 8); + tv->tv_nsec = 0; + return; + + cur_time: + *tv = CURRENT_TIME; + return; + + too_early: + tv->tv_sec = tv->tv_nsec = 0; + return; + + too_late: + tv->tv_sec = 0x7ffffffd; + tv->tv_nsec = 0; + return; } /* @@ -271,10 +286,9 @@ ADFS_I(inode)->stamped = ((obj->loadaddr & 0xfff00000) == 0xfff00000); inode->i_mode = adfs_atts2mode(sb, inode); - inode->i_mtime.tv_sec = - inode->i_atime.tv_sec = - inode->i_ctime.tv_sec = adfs_adfs2unix_time(inode); - inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = inode->i_atime.tv_nsec = 0; + adfs_adfs2unix_time(&inode->i_mtime, inode); + inode->i_atime = inode->i_mtime; + inode->i_ctime = inode->i_mtime; if (S_ISDIR(inode->i_mode)) { inode->i_op = &adfs_dir_inode_operations; diff -Nru a/fs/afs/inode.c b/fs/afs/inode.c --- a/fs/afs/inode.c Fri Nov 22 13:41:18 2002 +++ b/fs/afs/inode.c Fri Nov 22 13:41:18 2002 @@ -148,7 +148,7 @@ */ inline int afs_iget(struct super_block *sb, afs_fid_t *fid, struct inode **_inode) { - struct afs_iget_data data = { fid: *fid }; + struct afs_iget_data data = { .fid = *fid }; struct afs_super_info *as; struct inode *inode; afs_vnode_t *vnode; diff -Nru a/fs/afs/vlclient.c b/fs/afs/vlclient.c --- a/fs/afs/vlclient.c Fri Nov 22 13:41:17 2002 +++ b/fs/afs/vlclient.c Fri Nov 22 13:41:17 2002 @@ -584,7 +584,7 @@ #endif /* success */ - entry->ctime = CURRENT_TIME; + entry->ctime = get_seconds(); ret = 0; goto done; } diff -Nru a/fs/autofs4/root.c b/fs/autofs4/root.c --- a/fs/autofs4/root.c Fri Nov 22 13:41:17 2002 +++ b/fs/autofs4/root.c Fri Nov 22 13:41:17 2002 @@ -418,7 +418,7 @@ unlock_kernel(); return -ENOTEMPTY; } - list_del_init(&dentry->d_hash); + __d_drop(dentry); spin_unlock(&dcache_lock); dput(ino->dentry); diff -Nru a/fs/block_dev.c b/fs/block_dev.c --- a/fs/block_dev.c Fri Nov 22 13:41:23 2002 +++ b/fs/block_dev.c Fri Nov 22 13:41:23 2002 @@ -567,6 +567,7 @@ lock_kernel(); disk = get_gendisk(bdev->bd_dev, &part); if (!disk) { + unlock_kernel(); bdput(bdev); return ret; } @@ -757,7 +758,6 @@ .prepare_write = blkdev_prepare_write, .commit_write = blkdev_commit_write, .writepages = generic_writepages, - .vm_writeback = generic_vm_writeback, .direct_IO = blkdev_direct_IO, }; diff -Nru a/fs/buffer.c b/fs/buffer.c --- a/fs/buffer.c Fri Nov 22 13:41:21 2002 +++ b/fs/buffer.c Fri Nov 22 13:41:21 2002 @@ -1640,8 +1640,6 @@ last_block = (inode->i_size - 1) >> inode->i_blkbits; if (!page_has_buffers(page)) { - if (S_ISBLK(inode->i_mode)) - buffer_error(); if (!PageUptodate(page)) buffer_error(); create_empty_buffers(page, 1 << inode->i_blkbits, @@ -1966,6 +1964,7 @@ struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE]; unsigned int blocksize, blocks; int nr, i; + int fully_mapped = 1; if (!PageLocked(page)) PAGE_BUG(page); @@ -1988,6 +1987,7 @@ continue; if (!buffer_mapped(bh)) { + fully_mapped = 0; if (iblock < lblock) { if (get_block(inode, iblock, bh, 0)) SetPageError(page); @@ -2010,6 +2010,9 @@ arr[nr++] = bh; } while (i++, iblock++, (bh = bh->b_this_page) != head); + if (fully_mapped) + SetPageMappedToDisk(page); + if (!nr) { /* * All buffers are uptodate - we can set the page uptodate @@ -2205,6 +2208,198 @@ } return 0; } + +/* + * On entry, the page is fully not uptodate. + * On exit the page is fully uptodate in the areas outside (from,to) + */ +int nobh_prepare_write(struct page *page, unsigned from, unsigned to, + get_block_t *get_block) +{ + struct inode *inode = page->mapping->host; + const unsigned blkbits = inode->i_blkbits; + const unsigned blocksize = 1 << blkbits; + struct buffer_head map_bh; + struct buffer_head *read_bh[MAX_BUF_PER_PAGE]; + unsigned block_in_page; + unsigned block_start; + sector_t block_in_file; + char *kaddr; + int nr_reads = 0; + int i; + int ret = 0; + int is_mapped_to_disk = 1; + int dirtied_it = 0; + + if (PageMappedToDisk(page)) + return 0; + + block_in_file = (sector_t)page->index << (PAGE_CACHE_SHIFT - blkbits); + map_bh.b_page = page; + + /* + * We loop across all blocks in the page, whether or not they are + * part of the affected region. This is so we can discover if the + * page is fully mapped-to-disk. + */ + for (block_start = 0, block_in_page = 0; + block_start < PAGE_CACHE_SIZE; + block_in_page++, block_start += blocksize) { + unsigned block_end = block_start + blocksize; + int create; + + map_bh.b_state = 0; + create = 1; + if (block_start >= to) + create = 0; + ret = get_block(inode, block_in_file + block_in_page, + &map_bh, create); + if (ret) + goto failed; + if (!buffer_mapped(&map_bh)) + is_mapped_to_disk = 0; + if (buffer_new(&map_bh)) + unmap_underlying_metadata(map_bh.b_bdev, + map_bh.b_blocknr); + if (PageUptodate(page)) + continue; + if (buffer_new(&map_bh) || !buffer_mapped(&map_bh)) { + kaddr = kmap_atomic(page, KM_USER0); + if (block_start < from) { + memset(kaddr+block_start, 0, from-block_start); + dirtied_it = 1; + } + if (block_end > to) { + memset(kaddr + to, 0, block_end - to); + dirtied_it = 1; + } + flush_dcache_page(page); + kunmap_atomic(kaddr, KM_USER0); + continue; + } + if (buffer_uptodate(&map_bh)) + continue; /* reiserfs does this */ + if (block_start < from || block_end > to) { + struct buffer_head *bh = alloc_buffer_head(); + + if (!bh) { + ret = -ENOMEM; + goto failed; + } + bh->b_state = map_bh.b_state; + atomic_set(&bh->b_count, 0); + bh->b_this_page = 0; + bh->b_page = page; + bh->b_blocknr = map_bh.b_blocknr; + bh->b_size = blocksize; + bh->b_data = (char *)block_start; + bh->b_bdev = map_bh.b_bdev; + bh->b_private = NULL; + read_bh[nr_reads++] = bh; + } + } + + if (nr_reads) { + ll_rw_block(READ, nr_reads, read_bh); + for (i = 0; i < nr_reads; i++) { + wait_on_buffer(read_bh[i]); + if (!buffer_uptodate(read_bh[i])) + ret = -EIO; + free_buffer_head(read_bh[i]); + read_bh[i] = NULL; + } + if (ret) + goto failed; + } + + if (is_mapped_to_disk) + SetPageMappedToDisk(page); + SetPageUptodate(page); + + /* + * Setting the page dirty here isn't necessary for the prepare_write + * function - commit_write will do that. But if/when this function is + * used within the pagefault handler to ensure that all mmapped pages + * have backing space in the filesystem, we will need to dirty the page + * if its contents were altered. + */ + if (dirtied_it) + set_page_dirty(page); + + return 0; + +failed: + for (i = 0; i < nr_reads; i++) { + if (read_bh[i]) + free_buffer_head(read_bh[i]); + } + + /* + * Error recovery is pretty slack. Clear the page and mark it dirty + * so we'll later zero out any blocks which _were_ allocated. + */ + kaddr = kmap_atomic(page, KM_USER0); + memset(kaddr, 0, PAGE_CACHE_SIZE); + kunmap_atomic(kaddr, KM_USER0); + SetPageUptodate(page); + set_page_dirty(page); + return ret; +} +EXPORT_SYMBOL(nobh_prepare_write); + +int nobh_commit_write(struct file *file, struct page *page, + unsigned from, unsigned to) +{ + struct inode *inode = page->mapping->host; + loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; + + set_page_dirty(page); + if (pos > inode->i_size) { + inode->i_size = pos; + mark_inode_dirty(inode); + } + return 0; +} +EXPORT_SYMBOL(nobh_commit_write); + +/* + * This function assumes that ->prepare_write() uses nobh_prepare_write(). + */ +int nobh_truncate_page(struct address_space *mapping, loff_t from) +{ + struct inode *inode = mapping->host; + unsigned blocksize = 1 << inode->i_blkbits; + pgoff_t index = from >> PAGE_CACHE_SHIFT; + unsigned offset = from & (PAGE_CACHE_SIZE-1); + unsigned to; + struct page *page; + struct address_space_operations *a_ops = mapping->a_ops; + char *kaddr; + int ret = 0; + + if ((offset & (blocksize - 1)) == 0) + goto out; + + ret = -ENOMEM; + page = grab_cache_page(mapping, index); + if (!page) + goto out; + + to = (offset + blocksize) & ~(blocksize - 1); + ret = a_ops->prepare_write(NULL, page, offset, to); + if (ret == 0) { + kaddr = kmap_atomic(page, KM_USER0); + memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset); + flush_dcache_page(page); + kunmap_atomic(kaddr, KM_USER0); + set_page_dirty(page); + } + unlock_page(page); + page_cache_release(page); +out: + return ret; +} +EXPORT_SYMBOL(nobh_truncate_page); int block_truncate_page(struct address_space *mapping, loff_t from, get_block_t *get_block) diff -Nru a/fs/char_dev.c b/fs/char_dev.c --- a/fs/char_dev.c Fri Nov 22 13:41:18 2002 +++ b/fs/char_dev.c Fri Nov 22 13:41:18 2002 @@ -10,6 +10,23 @@ #include #include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_KMOD +#include +#include + +/* serial module kmod load support */ +struct tty_driver *get_tty_driver(kdev_t device); +#define isa_tty_dev(ma) (ma == TTY_MAJOR || ma == TTYAUX_MAJOR) +#define need_serial(ma,mi) (get_tty_driver(mk_kdev(ma,mi)) == NULL) +#endif + #define HASH_BITS 6 #define HASH_SIZE (1UL << HASH_BITS) #define HASH_MASK (HASH_SIZE-1) @@ -113,3 +130,150 @@ } } +struct device_struct { + const char * name; + struct file_operations * fops; +}; + +static rwlock_t chrdevs_lock = RW_LOCK_UNLOCKED; +static struct device_struct chrdevs[MAX_CHRDEV]; + +int get_chrdev_list(char *page) +{ + int i; + int len; + + len = sprintf(page, "Character devices:\n"); + read_lock(&chrdevs_lock); + for (i = 0; i < MAX_CHRDEV ; i++) { + if (chrdevs[i].fops) { + len += sprintf(page+len, "%3d %s\n", i, chrdevs[i].name); + } + } + read_unlock(&chrdevs_lock); + return len; +} + +/* + Return the function table of a device. + Load the driver if needed. + Increment the reference count of module in question. +*/ +static struct file_operations * get_chrfops(unsigned int major, unsigned int minor) +{ + struct file_operations *ret = NULL; + + if (!major || major >= MAX_CHRDEV) + return NULL; + + read_lock(&chrdevs_lock); + ret = fops_get(chrdevs[major].fops); + read_unlock(&chrdevs_lock); +#ifdef CONFIG_KMOD + if (ret && isa_tty_dev(major)) { + lock_kernel(); + if (need_serial(major,minor)) { + /* Force request_module anyway, but what for? */ + fops_put(ret); + ret = NULL; + } + unlock_kernel(); + } + if (!ret) { + char name[20]; + sprintf(name, "char-major-%d", major); + request_module(name); + + read_lock(&chrdevs_lock); + ret = fops_get(chrdevs[major].fops); + read_unlock(&chrdevs_lock); + } +#endif + return ret; +} + +int register_chrdev(unsigned int major, const char * name, struct file_operations *fops) +{ + if (devfs_only()) + return 0; + if (major == 0) { + write_lock(&chrdevs_lock); + for (major = MAX_CHRDEV-1; major > 0; major--) { + if (chrdevs[major].fops == NULL) { + chrdevs[major].name = name; + chrdevs[major].fops = fops; + write_unlock(&chrdevs_lock); + return major; + } + } + write_unlock(&chrdevs_lock); + return -EBUSY; + } + if (major >= MAX_CHRDEV) + return -EINVAL; + write_lock(&chrdevs_lock); + if (chrdevs[major].fops && chrdevs[major].fops != fops) { + write_unlock(&chrdevs_lock); + return -EBUSY; + } + chrdevs[major].name = name; + chrdevs[major].fops = fops; + write_unlock(&chrdevs_lock); + return 0; +} + +int unregister_chrdev(unsigned int major, const char * name) +{ + if (devfs_only()) + return 0; + if (major >= MAX_CHRDEV) + return -EINVAL; + write_lock(&chrdevs_lock); + if (!chrdevs[major].fops || strcmp(chrdevs[major].name, name)) { + write_unlock(&chrdevs_lock); + return -EINVAL; + } + chrdevs[major].name = NULL; + chrdevs[major].fops = NULL; + write_unlock(&chrdevs_lock); + return 0; +} + +/* + * Called every time a character special file is opened + */ +int chrdev_open(struct inode * inode, struct file * filp) +{ + int ret = -ENODEV; + + filp->f_op = get_chrfops(major(inode->i_rdev), minor(inode->i_rdev)); + if (filp->f_op) { + ret = 0; + if (filp->f_op->open != NULL) { + lock_kernel(); + ret = filp->f_op->open(inode,filp); + unlock_kernel(); + } + } + return ret; +} + +/* + * Dummy default file-operations: the only thing this does + * is contain the open that then fills in the correct operations + * depending on the special file... + */ +struct file_operations def_chr_fops = { + .open = chrdev_open, +}; + +const char * cdevname(kdev_t dev) +{ + static char buffer[32]; + const char * name = chrdevs[major(dev)].name; + + if (!name) + name = "unknown-char"; + sprintf(buffer, "%s(%d,%d)", name, major(dev), minor(dev)); + return buffer; +} diff -Nru a/fs/cifs/CHANGES b/fs/cifs/CHANGES --- a/fs/cifs/CHANGES Fri Nov 22 13:41:23 2002 +++ b/fs/cifs/CHANGES Fri Nov 22 13:41:23 2002 @@ -1,3 +1,13 @@ +Version 0.60 +------------ +Fix oops in readpages caused by not setting address space operations in inode in +rare code path. + +Version 0.59 +------------ +Includes support for deleting of open files and renaming over existing files (per POSIX +requirement). Add readlink support for Windows junction points (directory symlinks). + Version 0.58 ------------ Changed read and write to go through pagecache. Added additional address space operations. diff -Nru a/fs/cifs/README b/fs/cifs/README --- a/fs/cifs/README Fri Nov 22 13:41:23 2002 +++ b/fs/cifs/README Fri Nov 22 13:41:23 2002 @@ -9,8 +9,8 @@ Build instructions: ================== -extract the kernel from http://www.cifs.bkbits.net/linux-2.5 or -http://www.cifs.bkbits.net/linux-2.4 +Get the kernel source e.g. http://linux.bkbits.net/linux-2.5 or http://www.kernel.org +http://cifs.bkbits.net/linux-2.4 make menuconfig (or make xconfig) select cifs from within the network filesystem choices save and exit @@ -57,7 +57,9 @@ from their defaults. For more information on these see the manual pages ("man smb.conf") on the Samba server system. Note that the cifs vfs, unlike the smbfs vfs, does not read the smb.conf on the client system (the few optional settings -are passed in on mount via -o parameters instead). +are passed in on mount via -o parameters instead). Note that Samba 2.2.7 or later +includes a fix that allows the CIFS VFS to delete open files (required for strict +POSIX compliance). Windows Servers already supported this feature. Use instructions: ================ @@ -77,7 +79,7 @@ and Windows NT, 2000 and XP and many other SMB/CIFS servers) and servers must support either "pure-TCP" (port 445 TCP/IP CIFS connections) or RFC 1001/1002 support for "Netbios-Over-TCP/IP." Neither of these is likely to be a problem as most servers -support this. IPv6 support is planned for the future. +support this. IPv6 support is planned for the future. Misc /proc/fs/cifs Flags and Debug Info ======================================= diff -Nru a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c --- a/fs/cifs/cifs_debug.c Fri Nov 22 13:41:19 2002 +++ b/fs/cifs/cifs_debug.c Fri Nov 22 13:41:19 2002 @@ -85,7 +85,7 @@ ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); length = sprintf(buf, - "\n%d) Name: %s Domain: %s HowManyMounts: %d ServerOS: %s ServerNOS: %s Capabilities: 0x%x\n", + "\n%d) Name: %s Domain: %s HowManyMounts: %d ServerOS: %s ServerNOS: %s\n\tCapabilities: 0x%x", i, ses->serverName, ses->serverDomain, atomic_read(&ses->inUse), ses->serverOS, ses->serverNOS, ses->capabilities); buf += length; @@ -107,7 +107,7 @@ tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); length = sprintf(buf, - "\n%d) %s UseCount: %d on FS: %s with characteristics: 0x%x Attributes: 0x%x and PathComponentLengthMax: %d", + "\n%d) %s UseCount: %d on FS: %s with characteristics: 0x%x Attributes: 0x%x\n\tPathComponentLengthMax: %d", i, tcon->treeName, atomic_read(&tcon->useCount), tcon->nativeFileSystem, diff -Nru a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h --- a/fs/cifs/cifspdu.h Fri Nov 22 13:41:22 2002 +++ b/fs/cifs/cifspdu.h Fri Nov 22 13:41:22 2002 @@ -234,6 +234,8 @@ #define ATTR_NOT_CONTENT_INDEXED 0x2000 #define ATTR_ENCRYPTED 0x4000 #define ATTR_POSIX_SEMANTICS 0x01000000 +#define ATTR_BACKUP_SEMANTICS 0x02000000 +#define ATTR_DELETE_ON_CLOSE 0x04000000 #define ATTR_SEQUENTIAL_SCAN 0x08000000 #define ATTR_RANDOM_ACCESS 0x10000000 #define ATTR_NO_BUFFERING 0x20000000 @@ -255,8 +257,12 @@ #define FILE_OVERWRITE_IF 0x00000005 /* CreateOptions */ -#define CREATE_NOT_FILE 0x00000001 /* if set, indicates must not be file */ -#define CREATE_NOT_DIR 0x00000040 /* if set, indicates must not be directory */ +#define CREATE_NOT_FILE 0x00000001 /* if set must not be file */ +#define CREATE_WRITE_THROUGH 0x00000002 +#define CREATE_NOT_DIR 0x00000040 /* if set must not be directory */ +#define CREATE_RANDOM_ACCESS 0x00000800 +#define CREATE_DELETE_ON_CLOSE 0x00001000 +#define OPEN_REPARSE_POINT 0x00200000 /* ImpersonationLevel flags */ #define SECURITY_ANONYMOUS 0 @@ -743,7 +749,10 @@ /* followed by NewFileName */ } RENAME_REQ; -#define CREATE_HARD_LINK 0x103 +#define CREATE_HARD_LINK 0x103 +#define MOVEFILE_COPY_ALLOWED 0x0002 +#define MOVEFILE_REPLACE_EXISTING 0x0001 + typedef struct smb_com_nt_rename_req { /* A5 - also used for create hardlink */ struct smb_hdr hdr; /* wct = 4 */ __u16 SearchAttributes; /* target file attributes */ @@ -798,7 +807,7 @@ __u16 ByteCount; /* bct = 0 */ } CREATE_DIRECTORY_RSP; -typedef struct smb_com_nt_transaction_ioctl_req { +typedef struct smb_com_transaction_ioctl_req { struct smb_hdr hdr; /* wct = 23 */ __u8 MaxSetupCount; __u16 Reserved; @@ -810,13 +819,13 @@ __u32 ParameterOffset; __u32 DataCount; __u32 DataOffset; - __u8 SetupCount; /* four setup words follow subcommand */ + __u8 SetupCount; /* four setup words follow subcommand */ /* SNIA spec incorrectly included spurious pad here */ - __u16 SubCommand; /* 2 = IOCTL/FSCTL */ + __u16 SubCommand;/* 2 = IOCTL/FSCTL */ __u32 FunctionCode; __u16 Fid; - __u8 IsFSCTLFlag; /* 1 = File System Control, 0 = device control (IOCTL) */ - __u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS share) */ + __u8 IsFsctl; /* 1 = File System Control, 0 = device control (IOCTL)*/ + __u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS share)*/ __u16 ByteCount; __u8 Pad[3]; __u8 Data[1]; @@ -839,6 +848,17 @@ __u8 Pad[3]; } TRANSACT_IOCTL_RSP; +struct reparse_data { + __u32 ReparseTag; + __u16 ReparseDataLength; + __u16 Reserved; + __u16 AltNameOffset; + __u16 AltNameLen; + __u16 TargetNameOffset; + __u16 TargetNameLen; + char LinkNamesBuf[1]; +}; + typedef union smb_com_transaction2 { struct { struct smb_hdr hdr; /* wct = 14+ */ @@ -894,7 +914,7 @@ #define SMB_QUERY_FILE_UNIX_BASIC 0x200 #define SMB_QUERY_FILE_UNIX_LINK 0x201 -#define SMB_SET_FILE_BASIC_INFO 0x101 +#define SMB_SET_FILE_BASIC_INFO 0x101 #define SMB_SET_FILE_DISPOSITION_INFO 0x102 #define SMB_SET_FILE_ALLOCATION_INFO 0x103 #define SMB_SET_FILE_END_OF_FILE_INFO 0x104 @@ -908,7 +928,7 @@ /* Find File infolevels */ #define SMB_FIND_FILE_DIRECTORY_INFO 0x101 #define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102 -#define SMB_FIND_FILE_NAMES_INFO 0x103 +#define SMB_FIND_FILE_NAMES_INFO 0x103 #define SMB_FIND_FILE_BOTH_DIRECTORY_INFO 0x104 #define SMB_FIND_FILE_UNIX 0x202 diff -Nru a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h --- a/fs/cifs/cifsproto.h Fri Nov 22 13:41:17 2002 +++ b/fs/cifs/cifsproto.h Fri Nov 22 13:41:17 2002 @@ -184,6 +184,11 @@ const unsigned char *searchName, char *syminfo, const int buflen, const struct nls_table *nls_codepage); +extern int CIFSSMBQueryReparseLinkInfo(const int xid, + const struct cifsTconInfo *tcon, + const unsigned char *searchName, + char *symlinkinfo, const int buflen, __u16 fid, + const struct nls_table *nls_codepage); extern int CIFSSMBOpen(const int xid, const struct cifsTconInfo *tcon, const char *fileName, const int disposition, diff -Nru a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c --- a/fs/cifs/cifssmb.c Fri Nov 22 13:41:18 2002 +++ b/fs/cifs/cifssmb.c Fri Nov 22 13:41:18 2002 @@ -390,7 +390,7 @@ int CIFSSMBOpen(const int xid, const struct cifsTconInfo *tcon, const char *fileName, const int openDisposition, - const int access_flags, const int omode, __u16 * netfid, + const int access_flags, const int create_options, __u16 * netfid, int *pOplock, const struct nls_table *nls_codepage) { int rc = -EACCES; @@ -436,7 +436,7 @@ pSMB->FileAttributes = cpu_to_le32(pSMB->FileAttributes); pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); pSMB->CreateDisposition = cpu_to_le32(openDisposition); - pSMB->CreateOptions = cpu_to_le32(CREATE_NOT_DIR); /* BB what are these? BB */ + pSMB->CreateOptions = cpu_to_le32(create_options); pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ?? BB */ pSMB->SecurityFlags = cpu_to_le32(SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY); @@ -962,7 +962,7 @@ int bytes_returned; int name_len; - cFYI(1, ("\nIn QPathSymLinkInfo (Unix) the path %s", searchName)); + cFYI(1, ("\nIn QPathSymLinkInfo (Unix) for path %s", searchName)); rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); if (rc) @@ -1014,7 +1014,8 @@ } else { /* decode response */ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset); pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount); - if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */ + if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512)) + /* BB also check enough total bytes returned */ rc = -EIO; /* bad smb */ else { if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { @@ -1041,7 +1042,89 @@ pSMBr-> DataCount)); } - symlinkinfo[buflen] = 0; /* just in case so the calling code does not go off the end of the buffer */ + symlinkinfo[buflen] = 0; + /* just in case so calling code does not go off the end of buffer */ + } + } + if (pSMB) + buf_release(pSMB); + return rc; +} + + + +int +CIFSSMBQueryReparseLinkInfo(const int xid, const struct cifsTconInfo *tcon, + const unsigned char *searchName, + char *symlinkinfo, const int buflen,__u16 fid, + const struct nls_table *nls_codepage) +{ + int rc = 0; + int bytes_returned; + int name_len; + struct smb_com_transaction_ioctl_req * pSMB; + struct smb_com_transaction_ioctl_rsp * pSMBr; + + cFYI(1, ("\nIn Windows reparse style QueryLink info for path %s", searchName)); + rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB, + (void **) &pSMBr); + if (rc) + return rc; + + pSMB->TotalParameterCount = 0 ; + pSMB->TotalDataCount = 0; + pSMB->MaxParameterCount = cpu_to_le16(2); + pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */ + pSMB->MaxSetupCount = 4; + pSMB->Reserved = 0; + pSMB->ParameterOffset = 0; + pSMB->DataCount = 0; + pSMB->DataOffset = 0; + pSMB->SetupCount = 4; + pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL); + pSMB->ParameterCount = pSMB->TotalParameterCount; + pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT); + pSMB->IsFsctl = 1; /* FSCTL */ + pSMB->IsRootFlag = 0; + pSMB->Fid = fid; /* file handle always le */ + pSMB->ByteCount = 0; + + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, + (struct smb_hdr *) pSMBr, &bytes_returned, 0); + if (rc) { + cFYI(1, ("\nSend error in QueryReparseLinkInfo = %d\n", rc)); + } else { /* decode response */ + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset); + pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount); + if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512)) + /* BB also check enough total bytes returned */ + rc = -EIO; /* bad smb */ + else { + if(pSMBr->DataCount && (pSMBr->DataCount < 2048)) { + /* could also validata reparse tag && better check name length */ + struct reparse_data * reparse_buf = (struct reparse_data *) + ((char *)&pSMBr->hdr.Protocol + pSMBr->DataOffset); + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { + name_len = UniStrnlen((wchar_t *) + (reparse_buf->LinkNamesBuf + + reparse_buf->TargetNameOffset), + min(buflen/2, reparse_buf->TargetNameLen / 2)); + cifs_strfromUCS_le(symlinkinfo, + (wchar_t *) (reparse_buf->LinkNamesBuf + + reparse_buf->TargetNameOffset), + name_len, nls_codepage); + } else { /* ASCII names */ + strncpy(symlinkinfo,reparse_buf->LinkNamesBuf + + reparse_buf->TargetNameOffset, + min(buflen, (int)reparse_buf->TargetNameLen)); + } + } else { + rc = -EIO; + cFYI(1,("\nInvalid return data count on get reparse info ioctl")); + } + symlinkinfo[buflen] = 0; /* just in case so the caller + does not go off the end of the buffer */ + cFYI(1,("\nreadlink result - %s ",symlinkinfo)); } } if (pSMB) diff -Nru a/fs/cifs/connect.c b/fs/cifs/connect.c --- a/fs/cifs/connect.c Fri Nov 22 13:41:23 2002 +++ b/fs/cifs/connect.c Fri Nov 22 13:41:23 2002 @@ -561,6 +561,7 @@ if (rc < 0) { cFYI(1, ("Error connecting to socket. %d\n", rc)); sock_release(*csocket); + *csocket = NULL; return rc; } } @@ -598,6 +599,7 @@ ("Error connecting to socket (via ipv6). %d\n", rc)); sock_release(*csocket); + *csocket = NULL; return rc; } } diff -Nru a/fs/cifs/dir.c b/fs/cifs/dir.c --- a/fs/cifs/dir.c Fri Nov 22 13:41:21 2002 +++ b/fs/cifs/dir.c Fri Nov 22 13:41:21 2002 @@ -141,7 +141,7 @@ /* BB add processing for setting the equivalent of mode - e.g. via CreateX with ACLs */ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OVERWRITE_IF, GENERIC_ALL - /* 0x20197 was used previously */ , mode, + /* 0x20197 was used previously */ , CREATE_NOT_DIR, &fileHandle, &oplock, cifs_sb->local_nls); if (rc) { cFYI(1, ("\ncifs_create returned 0x%x ", rc)); @@ -267,11 +267,6 @@ /* lock_kernel(); *//* surely we do not want to lock the kernel for a whole network round trip which could take seconds */ if (direntry->d_inode) { - cFYI(1, - ("In cifs_d_revalidate, name = %s and inode = 0x%p with count %d with time %ld and dentry 0x%p with time %ld\n", - direntry->d_name.name, direntry->d_inode, - direntry->d_inode->i_count.counter, - direntry->d_inode->i_atime, direntry, direntry->d_time)); if (cifs_revalidate(direntry)) { /* unlock_kernel(); */ return 0; diff -Nru a/fs/cifs/file.c b/fs/cifs/file.c --- a/fs/cifs/file.c Fri Nov 22 13:41:17 2002 +++ b/fs/cifs/file.c Fri Nov 22 13:41:17 2002 @@ -35,8 +35,6 @@ #include "cifs_debug.h" #include "cifs_fs_sb.h" - - int cifs_open(struct inode *inode, struct file *file) { @@ -94,9 +92,8 @@ oplock = FALSE; /* BB pass O_SYNC flag through on file attributes .. BB */ - rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, - -1 /* i.e. dummy value, ignored for time being */, - &netfid, &oplock, cifs_sb->local_nls); + rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, + CREATE_NOT_DIR, &netfid, &oplock, cifs_sb->local_nls); if (rc) { cFYI(1, ("\ncifs_open returned 0x%x ", rc)); cFYI(1, (" oplock: %d ", oplock)); @@ -112,7 +109,8 @@ pCifsFile->pfile = file; /* needed for writepage */ list_add(&pCifsFile->tlist,&pTcon->openFileList); pCifsInode = CIFS_I(file->f_dentry->d_inode); - list_add(&pCifsFile->flist,&pCifsInode->openFileList); + if(pCifsInode->openFileList.next) + list_add(&pCifsFile->flist,&pCifsInode->openFileList); if(file->f_flags & O_CREAT) { /* time to set mode which we can not set earlier due to problems creating new read-only files */ @@ -153,7 +151,8 @@ cifs_sb = CIFS_SB(inode->i_sb); pTcon = cifs_sb->tcon; if (pSMBFile) { - list_del(&pSMBFile->flist); + if(pSMBFile->flist.next) + list_del(&pSMBFile->flist); list_del(&pSMBFile->tlist); rc = CIFSSMBClose(xid, pTcon, pSMBFile->netfid); kfree(file->private_data); @@ -649,6 +648,7 @@ cFYI(1, (" File inode ")); tmp_inode->i_op = &cifs_file_inode_ops; tmp_inode->i_fop = &cifs_file_ops; + tmp_inode->i_data.a_ops = &cifs_addr_ops; } else if (S_ISDIR(tmp_inode->i_mode)) { cFYI(1, (" Directory inode")); tmp_inode->i_op = &cifs_dir_inode_ops; @@ -716,6 +716,7 @@ cFYI(1, (" File inode ")); tmp_inode->i_op = &cifs_file_inode_ops; tmp_inode->i_fop = &cifs_file_ops; + tmp_inode->i_data.a_ops = &cifs_addr_ops; } else if (S_ISDIR(tmp_inode->i_mode)) { cFYI(1, (" Directory inode")); tmp_inode->i_op = &cifs_dir_inode_ops; diff -Nru a/fs/cifs/inode.c b/fs/cifs/inode.c --- a/fs/cifs/inode.c Fri Nov 22 13:41:17 2002 +++ b/fs/cifs/inode.c Fri Nov 22 13:41:17 2002 @@ -314,14 +314,24 @@ cifs_sb = CIFS_SB(inode->i_sb); pTcon = cifs_sb->tcon; - /* BB Should we close the file if it is already open from our client? */ - full_path = build_path_from_dentry(direntry); rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls); if (!rc) { direntry->d_inode->i_nlink--; + } else if (rc == -ETXTBSY) { + int oplock = FALSE; + __u16 netfid; + + rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE, + CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE, + &netfid, &oplock, cifs_sb->local_nls); + if(rc==0) { + CIFSSMBClose(xid, pTcon, netfid); + /* BB In the future chain close with the NTCreateX to narrow window */ + direntry->d_inode->i_nlink--; + } } cifsInode = CIFS_I(direntry->d_inode); cifsInode->time = 0; /* will force revalidate to get info when needed */ @@ -454,6 +464,11 @@ rc = CIFSSMBRename(xid, pTcon, fromName, toName, cifs_sb_source->local_nls); + if(rc == -EEXIST) { + cifs_unlink(target_inode, target_direntry); + rc = CIFSSMBRename(xid, pTcon, fromName, toName, + cifs_sb_source->local_nls); + } if (fromName) kfree(fromName); if (toName) diff -Nru a/fs/cifs/link.c b/fs/cifs/link.c --- a/fs/cifs/link.c Fri Nov 22 13:41:18 2002 +++ b/fs/cifs/link.c Fri Nov 22 13:41:18 2002 @@ -176,10 +176,12 @@ struct inode *inode = direntry->d_inode; int rc = -EACCES; int xid; + int oplock = FALSE; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; char *full_path = NULL; char tmpbuffer[256]; + __u16 fid; xid = GetXid(); cifs_sb = CIFS_SB(inode->i_sb); @@ -192,12 +194,23 @@ /* BB add read reparse point symlink code and Unix extensions symlink code here BB */ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path, - tmpbuffer, - sizeof (tmpbuffer) - 1, - cifs_sb->local_nls); + tmpbuffer, + sizeof (tmpbuffer) - 1, + cifs_sb->local_nls); else { - /* rc = CIFSSMBQueryReparseLinkInfo */ - /* BB Add code to Query ReparsePoint info */ + rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ, + OPEN_REPARSE_POINT,&fid, &oplock, cifs_sb->local_nls); + if(!rc) { + rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path, + tmpbuffer, + sizeof(tmpbuffer) - 1, + fid, + cifs_sb->local_nls); + if(CIFSSMBClose(xid, pTcon, fid)) { + cFYI(1,("Error closing junction point (open for ioctl)")); + } + } + } /* BB Anything else to do to handle recursive links? */ /* BB Should we be using page ops here? */ diff -Nru a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c --- a/fs/cifs/netmisc.c Fri Nov 22 13:41:23 2002 +++ b/fs/cifs/netmisc.c Fri Nov 22 13:41:23 2002 @@ -252,7 +252,7 @@ ERRHRD, ERRgeneral, NT_STATUS_DISK_CORRUPT_ERROR}, { ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_INVALID}, { /* mapping changed since shell does lookup on * and expects file not found */ ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND}, { - ERRDOS, 183, NT_STATUS_OBJECT_NAME_COLLISION}, { + ERRDOS, ERRalreadyexists, NT_STATUS_OBJECT_NAME_COLLISION}, { ERRHRD, ERRgeneral, NT_STATUS_HANDLE_NOT_WAITABLE}, { ERRDOS, ERRbadfid, NT_STATUS_PORT_DISCONNECTED}, { ERRHRD, ERRgeneral, NT_STATUS_DEVICE_ALREADY_ATTACHED}, { @@ -285,7 +285,7 @@ ERRHRD, ERRgeneral, NT_STATUS_EA_CORRUPT_ERROR}, { ERRDOS, ERRlock, NT_STATUS_FILE_LOCK_CONFLICT}, { ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED}, { - ERRDOS, ERRnoaccess, NT_STATUS_DELETE_PENDING}, { + ERRDOS, ERRbadfile, NT_STATUS_DELETE_PENDING}, { ERRDOS, ERRunsup, NT_STATUS_CTL_FILE_NOT_SUPPORTED}, { ERRHRD, ERRgeneral, NT_STATUS_UNKNOWN_REVISION}, { ERRHRD, ERRgeneral, NT_STATUS_REVISION_MISMATCH}, { @@ -753,7 +753,7 @@ { int idx = 0; - printk("\nStatus code returned: 0x%08x", status_code); + printk("\nStatus code returned: 0x%08x ", status_code); while (nt_errs[idx].nt_errstr != NULL) { if (((nt_errs[idx].nt_errcode) & 0xFFFFFF) == diff -Nru a/fs/coda/coda_linux.c b/fs/coda/coda_linux.c --- a/fs/coda/coda_linux.c Fri Nov 22 13:41:17 2002 +++ b/fs/coda/coda_linux.c Fri Nov 22 13:41:17 2002 @@ -100,7 +100,7 @@ void coda_vattr_to_iattr(struct inode *inode, struct coda_vattr *attr) { int inode_type; - /* inode's i_dev, i_flags, i_ino are set by iget + /* inode's i_flags, i_ino are set by iget XXX: is this all we need ?? */ switch (attr->va_type) { diff -Nru a/fs/coda/dir.c b/fs/coda/dir.c --- a/fs/coda/dir.c Fri Nov 22 13:41:18 2002 +++ b/fs/coda/dir.c Fri Nov 22 13:41:18 2002 @@ -29,7 +29,7 @@ /* dir inode-ops */ static int coda_create(struct inode *dir, struct dentry *new, int mode); -static int coda_mknod(struct inode *dir, struct dentry *new, int mode, int rdev); +static int coda_mknod(struct inode *dir, struct dentry *new, int mode, dev_t rdev); static struct dentry *coda_lookup(struct inode *dir, struct dentry *target); static int coda_link(struct dentry *old_dentry, struct inode *dir_inode, struct dentry *entry); @@ -230,7 +230,7 @@ return 0; } -static int coda_mknod(struct inode *dir, struct dentry *de, int mode, int rdev) +static int coda_mknod(struct inode *dir, struct dentry *de, int mode, dev_t rdev) { int error=0; const char *name=de->d_name.name; @@ -740,4 +740,3 @@ unlock_kernel(); return -EIO; } - diff -Nru a/fs/coda/upcall.c b/fs/coda/upcall.c --- a/fs/coda/upcall.c Fri Nov 22 13:41:22 2002 +++ b/fs/coda/upcall.c Fri Nov 22 13:41:22 2002 @@ -310,8 +310,8 @@ } int venus_create(struct super_block *sb, struct ViceFid *dirfid, - const char *name, int length, int excl, int mode, int rdev, - struct ViceFid *newfid, struct coda_vattr *attrs) + const char *name, int length, int excl, int mode, dev_t rdev, + struct ViceFid *newfid, struct coda_vattr *attrs) { union inputArgs *inp; union outputArgs *outp; diff -Nru a/fs/dcache.c b/fs/dcache.c --- a/fs/dcache.c Fri Nov 22 13:41:18 2002 +++ b/fs/dcache.c Fri Nov 22 13:41:18 2002 @@ -137,7 +137,7 @@ goto unhash_it; } /* Unreachable? Get rid of it */ - if (list_empty(&dentry->d_hash)) + if (d_unhashed(dentry)) goto kill_it; list_add(&dentry->d_lru, &dentry_unused); dentry_stat.nr_unused++; @@ -146,7 +146,7 @@ return; unhash_it: - list_del_init(&dentry->d_hash); + __d_drop(dentry); kill_it: { struct dentry *parent; @@ -181,7 +181,7 @@ * If it's already been dropped, return OK. */ spin_lock(&dcache_lock); - if (list_empty(&dentry->d_hash)) { + if (d_unhashed(dentry)) { spin_unlock(&dcache_lock); return 0; } @@ -212,7 +212,7 @@ } } - list_del_init(&dentry->d_hash); + __d_drop(dentry); spin_unlock(&dcache_lock); return 0; } @@ -259,7 +259,7 @@ tmp = next; next = tmp->next; alias = list_entry(tmp, struct dentry, d_alias); - if (!list_empty(&alias->d_hash)) { + if (!d_unhashed(alias)) { if (alias->d_flags & DCACHE_DISCONNECTED) discon_alias = alias; else { @@ -308,7 +308,7 @@ { struct dentry * parent; - list_del_init(&dentry->d_hash); + __d_drop(dentry); list_del(&dentry->d_child); dentry_stat.nr_dentry--; /* For d_free, below */ dentry_iput(dentry); @@ -997,7 +997,7 @@ void d_rehash(struct dentry * entry) { struct list_head *list = d_hash(entry->d_parent, entry->d_name.hash); - if (!list_empty(&entry->d_hash)) BUG(); + if (!d_unhashed(entry)) BUG(); spin_lock(&dcache_lock); list_add(&entry->d_hash, list); spin_unlock(&dcache_lock); @@ -1065,11 +1065,10 @@ spin_lock(&dcache_lock); /* Move the dentry to the target hash queue */ - list_del(&dentry->d_hash); - list_add(&dentry->d_hash, &target->d_hash); + list_move(&dentry->d_hash, &target->d_hash); /* Unhash the target: dput() will then get rid of it */ - list_del_init(&target->d_hash); + __d_drop(target); list_del(&dentry->d_child); list_del(&target->d_child); @@ -1121,7 +1120,7 @@ *--end = '\0'; buflen--; - if (!IS_ROOT(dentry) && list_empty(&dentry->d_hash)) { + if (!IS_ROOT(dentry) && d_unhashed(dentry)) { buflen -= 10; end -= 10; memcpy(end, " (deleted)", 10); @@ -1223,7 +1222,7 @@ error = -ENOENT; /* Has the current directory has been unlinked? */ spin_lock(&dcache_lock); - if (pwd->d_parent == pwd || !list_empty(&pwd->d_hash)) { + if (pwd->d_parent == pwd || !d_unhashed(pwd)) { unsigned long len; char * cwd; diff -Nru a/fs/devfs/base.c b/fs/devfs/base.c --- a/fs/devfs/base.c Fri Nov 22 13:41:18 2002 +++ b/fs/devfs/base.c Fri Nov 22 13:41:18 2002 @@ -799,9 +799,9 @@ struct devfs_inode /* This structure is for "persistent" inode storage */ { struct dentry *dentry; - time_t atime; - time_t mtime; - time_t ctime; + struct timespec atime; + struct timespec mtime; + struct timespec ctime; unsigned int ino; /* Inode number as seen in the VFS */ uid_t uid; gid_t gid; @@ -2509,9 +2509,9 @@ de->mode = inode->i_mode; de->inode.uid = inode->i_uid; de->inode.gid = inode->i_gid; - de->inode.atime = inode->i_atime.tv_sec; - de->inode.mtime = inode->i_mtime.tv_sec; - de->inode.ctime = inode->i_ctime.tv_sec; + de->inode.atime = inode->i_atime; + de->inode.mtime = inode->i_mtime; + de->inode.ctime = inode->i_ctime; if ( ( iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID) ) && !is_devfsd_or_child (fs_info) ) devfsd_notify_de (de, DEVFSD_NOTIFY_CHANGE, inode->i_mode, @@ -2610,12 +2610,9 @@ inode->i_mode = de->mode; inode->i_uid = de->inode.uid; inode->i_gid = de->inode.gid; - inode->i_atime.tv_sec = de->inode.atime; - inode->i_mtime.tv_sec = de->inode.mtime; - inode->i_ctime.tv_sec = de->inode.ctime; - inode->i_atime.tv_nsec = 0; - inode->i_mtime.tv_nsec = 0; - inode->i_ctime.tv_nsec = 0; + inode->i_atime = de->inode.atime; + inode->i_mtime = de->inode.mtime; + inode->i_ctime = de->inode.ctime; DPRINTK (DEBUG_I_GET, "(): mode: 0%o uid: %d gid: %d\n", (int) inode->i_mode, (int) inode->i_uid, (int) inode->i_gid); return inode; @@ -3106,7 +3103,7 @@ } /* End Function devfs_rmdir */ static int devfs_mknod (struct inode *dir, struct dentry *dentry, int mode, - int rdev) + dev_t rdev) { int err; struct fs_info *fs_info = dir->i_sb->s_fs_info; diff -Nru a/fs/devices.c b/fs/devices.c --- a/fs/devices.c Fri Nov 22 13:41:20 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,221 +0,0 @@ -/* - * linux/fs/devices.c - * - * (C) 1993 Matthias Urlichs -- collected common code and tables. - * - * Copyright (C) 1991, 1992 Linus Torvalds - * - * Added kerneld support: Jacques Gelinas and Bjorn Ekwall - * (changed to kmod) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_KMOD -#include - -#include - -/* serial module kmod load support */ -struct tty_driver *get_tty_driver(kdev_t device); -#define isa_tty_dev(ma) (ma == TTY_MAJOR || ma == TTYAUX_MAJOR) -#define need_serial(ma,mi) (get_tty_driver(mk_kdev(ma,mi)) == NULL) -#endif - -struct device_struct { - const char * name; - struct file_operations * fops; -}; - -static rwlock_t chrdevs_lock = RW_LOCK_UNLOCKED; -static struct device_struct chrdevs[MAX_CHRDEV]; - -extern int get_blkdev_list(char *); - -int get_device_list(char * page) -{ - int i; - int len; - - len = sprintf(page, "Character devices:\n"); - read_lock(&chrdevs_lock); - for (i = 0; i < MAX_CHRDEV ; i++) { - if (chrdevs[i].fops) { - len += sprintf(page+len, "%3d %s\n", i, chrdevs[i].name); - } - } - read_unlock(&chrdevs_lock); - len += get_blkdev_list(page+len); - return len; -} - -/* - Return the function table of a device. - Load the driver if needed. - Increment the reference count of module in question. -*/ -static struct file_operations * get_chrfops(unsigned int major, unsigned int minor) -{ - struct file_operations *ret = NULL; - - if (!major || major >= MAX_CHRDEV) - return NULL; - - read_lock(&chrdevs_lock); - ret = fops_get(chrdevs[major].fops); - read_unlock(&chrdevs_lock); -#ifdef CONFIG_KMOD - if (ret && isa_tty_dev(major)) { - lock_kernel(); - if (need_serial(major,minor)) { - /* Force request_module anyway, but what for? */ - fops_put(ret); - ret = NULL; - } - unlock_kernel(); - } - if (!ret) { - char name[20]; - sprintf(name, "char-major-%d", major); - request_module(name); - - read_lock(&chrdevs_lock); - ret = fops_get(chrdevs[major].fops); - read_unlock(&chrdevs_lock); - } -#endif - return ret; -} - -int register_chrdev(unsigned int major, const char * name, struct file_operations *fops) -{ - if (devfs_only()) - return 0; - if (major == 0) { - write_lock(&chrdevs_lock); - for (major = MAX_CHRDEV-1; major > 0; major--) { - if (chrdevs[major].fops == NULL) { - chrdevs[major].name = name; - chrdevs[major].fops = fops; - write_unlock(&chrdevs_lock); - return major; - } - } - write_unlock(&chrdevs_lock); - return -EBUSY; - } - if (major >= MAX_CHRDEV) - return -EINVAL; - write_lock(&chrdevs_lock); - if (chrdevs[major].fops && chrdevs[major].fops != fops) { - write_unlock(&chrdevs_lock); - return -EBUSY; - } - chrdevs[major].name = name; - chrdevs[major].fops = fops; - write_unlock(&chrdevs_lock); - return 0; -} - -int unregister_chrdev(unsigned int major, const char * name) -{ - if (devfs_only()) - return 0; - if (major >= MAX_CHRDEV) - return -EINVAL; - write_lock(&chrdevs_lock); - if (!chrdevs[major].fops || strcmp(chrdevs[major].name, name)) { - write_unlock(&chrdevs_lock); - return -EINVAL; - } - chrdevs[major].name = NULL; - chrdevs[major].fops = NULL; - write_unlock(&chrdevs_lock); - return 0; -} - -/* - * Called every time a character special file is opened - */ -int chrdev_open(struct inode * inode, struct file * filp) -{ - int ret = -ENODEV; - - filp->f_op = get_chrfops(major(inode->i_rdev), minor(inode->i_rdev)); - if (filp->f_op) { - ret = 0; - if (filp->f_op->open != NULL) { - lock_kernel(); - ret = filp->f_op->open(inode,filp); - unlock_kernel(); - } - } - return ret; -} - -/* - * Dummy default file-operations: the only thing this does - * is contain the open that then fills in the correct operations - * depending on the special file... - */ -static struct file_operations def_chr_fops = { - .open = chrdev_open, -}; - -/* - * Print device name (in decimal, hexadecimal or symbolic) - * Note: returns pointer to static data! - */ -const char * kdevname(kdev_t dev) -{ - static char buffer[32]; - sprintf(buffer, "%02x:%02x", major(dev), minor(dev)); - return buffer; -} - -const char * cdevname(kdev_t dev) -{ - static char buffer[32]; - const char * name = chrdevs[major(dev)].name; - - if (!name) - name = "unknown-char"; - sprintf(buffer, "%s(%d,%d)", name, major(dev), minor(dev)); - return buffer; -} - -static int sock_no_open(struct inode *irrelevant, struct file *dontcare) -{ - return -ENXIO; -} - -static struct file_operations bad_sock_fops = { - .open = sock_no_open -}; - -void init_special_inode(struct inode *inode, umode_t mode, int rdev) -{ - inode->i_mode = mode; - if (S_ISCHR(mode)) { - inode->i_fop = &def_chr_fops; - inode->i_rdev = to_kdev_t(rdev); - inode->i_cdev = cdget(rdev); - } else if (S_ISBLK(mode)) { - inode->i_fop = &def_blk_fops; - inode->i_rdev = to_kdev_t(rdev); - } else if (S_ISFIFO(mode)) - inode->i_fop = &def_fifo_fops; - else if (S_ISSOCK(mode)) - inode->i_fop = &bad_sock_fops; - else - printk(KERN_DEBUG "init_special_inode: bogus imode (%o)\n", mode); -} diff -Nru a/fs/exec.c b/fs/exec.c --- a/fs/exec.c Fri Nov 22 13:41:19 2002 +++ b/fs/exec.c Fri Nov 22 13:41:19 2002 @@ -524,9 +524,9 @@ if (proc_dentry) { spin_lock(&dcache_lock); - if (!list_empty(&proc_dentry->d_hash)) { + if (!d_unhashed(proc_dentry)) { dget_locked(proc_dentry); - list_del_init(&proc_dentry->d_hash); + __d_drop(proc_dentry); } else proc_dentry = NULL; spin_unlock(&dcache_lock); diff -Nru a/fs/ext2/dir.c b/fs/ext2/dir.c --- a/fs/ext2/dir.c Fri Nov 22 13:41:20 2002 +++ b/fs/ext2/dir.c Fri Nov 22 13:41:20 2002 @@ -215,25 +215,25 @@ } static unsigned char ext2_filetype_table[EXT2_FT_MAX] = { - [EXT2_FT_UNKNOWN] DT_UNKNOWN, - [EXT2_FT_REG_FILE] DT_REG, - [EXT2_FT_DIR] DT_DIR, - [EXT2_FT_CHRDEV] DT_CHR, - [EXT2_FT_BLKDEV] DT_BLK, - [EXT2_FT_FIFO] DT_FIFO, - [EXT2_FT_SOCK] DT_SOCK, - [EXT2_FT_SYMLINK] DT_LNK, + [EXT2_FT_UNKNOWN] = DT_UNKNOWN, + [EXT2_FT_REG_FILE] = DT_REG, + [EXT2_FT_DIR] = DT_DIR, + [EXT2_FT_CHRDEV] = DT_CHR, + [EXT2_FT_BLKDEV] = DT_BLK, + [EXT2_FT_FIFO] = DT_FIFO, + [EXT2_FT_SOCK] = DT_SOCK, + [EXT2_FT_SYMLINK] = DT_LNK, }; #define S_SHIFT 12 static unsigned char ext2_type_by_mode[S_IFMT >> S_SHIFT] = { - [S_IFREG >> S_SHIFT] EXT2_FT_REG_FILE, - [S_IFDIR >> S_SHIFT] EXT2_FT_DIR, - [S_IFCHR >> S_SHIFT] EXT2_FT_CHRDEV, - [S_IFBLK >> S_SHIFT] EXT2_FT_BLKDEV, - [S_IFIFO >> S_SHIFT] EXT2_FT_FIFO, - [S_IFSOCK >> S_SHIFT] EXT2_FT_SOCK, - [S_IFLNK >> S_SHIFT] EXT2_FT_SYMLINK, + [S_IFREG >> S_SHIFT] = EXT2_FT_REG_FILE, + [S_IFDIR >> S_SHIFT] = EXT2_FT_DIR, + [S_IFCHR >> S_SHIFT] = EXT2_FT_CHRDEV, + [S_IFBLK >> S_SHIFT] = EXT2_FT_BLKDEV, + [S_IFIFO >> S_SHIFT] = EXT2_FT_FIFO, + [S_IFSOCK >> S_SHIFT] = EXT2_FT_SOCK, + [S_IFLNK >> S_SHIFT] = EXT2_FT_SYMLINK, }; static inline void ext2_set_de_type(ext2_dirent *de, struct inode *inode) diff -Nru a/fs/ext2/ext2.h b/fs/ext2/ext2.h --- a/fs/ext2/ext2.h Fri Nov 22 13:41:23 2002 +++ b/fs/ext2/ext2.h Fri Nov 22 13:41:23 2002 @@ -120,6 +120,7 @@ /* inode.c */ extern struct address_space_operations ext2_aops; +extern struct address_space_operations ext2_nobh_aops; /* namei.c */ extern struct inode_operations ext2_dir_inode_operations; diff -Nru a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c --- a/fs/ext2/ialloc.c Fri Nov 22 13:41:20 2002 +++ b/fs/ext2/ialloc.c Fri Nov 22 13:41:20 2002 @@ -134,9 +134,11 @@ if (desc) { desc->bg_free_inodes_count = cpu_to_le16(le16_to_cpu(desc->bg_free_inodes_count) + 1); - if (is_directory) + if (is_directory) { desc->bg_used_dirs_count = cpu_to_le16(le16_to_cpu(desc->bg_used_dirs_count) - 1); + EXT2_SB(sb)->s_dir_count--; + } } mark_buffer_dirty(bh2); es->s_free_inodes_count = diff -Nru a/fs/ext2/inode.c b/fs/ext2/inode.c --- a/fs/ext2/inode.c Fri Nov 22 13:41:17 2002 +++ b/fs/ext2/inode.c Fri Nov 22 13:41:17 2002 @@ -612,6 +612,13 @@ return block_prepare_write(page,from,to,ext2_get_block); } +static int +ext2_nobh_prepare_write(struct file *file, struct page *page, + unsigned from, unsigned to) +{ + return nobh_prepare_write(page,from,to,ext2_get_block); +} + static sector_t ext2_bmap(struct address_space *mapping, sector_t block) { return generic_block_bmap(mapping,block,ext2_get_block); @@ -655,7 +662,18 @@ .bmap = ext2_bmap, .direct_IO = ext2_direct_IO, .writepages = ext2_writepages, - .vm_writeback = generic_vm_writeback, +}; + +struct address_space_operations ext2_nobh_aops = { + .readpage = ext2_readpage, + .readpages = ext2_readpages, + .writepage = ext2_writepage, + .sync_page = block_sync_page, + .prepare_write = ext2_nobh_prepare_write, + .commit_write = nobh_commit_write, + .bmap = ext2_bmap, + .direct_IO = ext2_direct_IO, + .writepages = ext2_writepages, }; /* @@ -865,7 +883,11 @@ iblock = (inode->i_size + blocksize-1) >> EXT2_BLOCK_SIZE_BITS(inode->i_sb); - block_truncate_page(inode->i_mapping, inode->i_size, ext2_get_block); + if (test_opt(inode->i_sb, NOBH)) + nobh_truncate_page(inode->i_mapping, inode->i_size); + else + block_truncate_page(inode->i_mapping, + inode->i_size, ext2_get_block); n = ext2_block_to_path(inode, iblock, offsets, NULL); if (n == 0) @@ -1045,17 +1067,26 @@ if (S_ISREG(inode->i_mode)) { inode->i_op = &ext2_file_inode_operations; inode->i_fop = &ext2_file_operations; - inode->i_mapping->a_ops = &ext2_aops; + if (test_opt(inode->i_sb, NOBH)) + inode->i_mapping->a_ops = &ext2_nobh_aops; + else + inode->i_mapping->a_ops = &ext2_aops; } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &ext2_dir_inode_operations; inode->i_fop = &ext2_dir_operations; - inode->i_mapping->a_ops = &ext2_aops; + if (test_opt(inode->i_sb, NOBH)) + inode->i_mapping->a_ops = &ext2_nobh_aops; + else + inode->i_mapping->a_ops = &ext2_aops; } else if (S_ISLNK(inode->i_mode)) { if (ext2_inode_is_fast_symlink(inode)) inode->i_op = &ext2_fast_symlink_inode_operations; else { inode->i_op = &ext2_symlink_inode_operations; - inode->i_mapping->a_ops = &ext2_aops; + if (test_opt(inode->i_sb, NOBH)) + inode->i_mapping->a_ops = &ext2_nobh_aops; + else + inode->i_mapping->a_ops = &ext2_aops; } } else { inode->i_op = &ext2_special_inode_operations; diff -Nru a/fs/ext2/namei.c b/fs/ext2/namei.c --- a/fs/ext2/namei.c Fri Nov 22 13:41:22 2002 +++ b/fs/ext2/namei.c Fri Nov 22 13:41:22 2002 @@ -127,14 +127,17 @@ if (!IS_ERR(inode)) { inode->i_op = &ext2_file_inode_operations; inode->i_fop = &ext2_file_operations; - inode->i_mapping->a_ops = &ext2_aops; + if (test_opt(inode->i_sb, NOBH)) + inode->i_mapping->a_ops = &ext2_nobh_aops; + else + inode->i_mapping->a_ops = &ext2_aops; mark_inode_dirty(inode); err = ext2_add_nondir(dentry, inode); } return err; } -static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev) +static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_t rdev) { struct inode * inode = ext2_new_inode (dir, mode); int err = PTR_ERR(inode); @@ -168,7 +171,10 @@ if (l > sizeof (EXT2_I(inode)->i_data)) { /* slow symlink */ inode->i_op = &ext2_symlink_inode_operations; - inode->i_mapping->a_ops = &ext2_aops; + if (test_opt(inode->i_sb, NOBH)) + inode->i_mapping->a_ops = &ext2_nobh_aops; + else + inode->i_mapping->a_ops = &ext2_aops; err = page_symlink(inode, symname, l); if (err) goto out_fail; @@ -222,7 +228,10 @@ inode->i_op = &ext2_dir_inode_operations; inode->i_fop = &ext2_dir_operations; - inode->i_mapping->a_ops = &ext2_aops; + if (test_opt(inode->i_sb, NOBH)) + inode->i_mapping->a_ops = &ext2_nobh_aops; + else + inode->i_mapping->a_ops = &ext2_aops; ext2_inc_count(inode); diff -Nru a/fs/ext2/super.c b/fs/ext2/super.c --- a/fs/ext2/super.c Fri Nov 22 13:41:21 2002 +++ b/fs/ext2/super.c Fri Nov 22 13:41:21 2002 @@ -391,6 +391,8 @@ set_opt (sbi->s_mount_opt, OLDALLOC); else if (!strcmp (this_char, "orlov")) clear_opt (sbi->s_mount_opt, OLDALLOC); + else if (!strcmp (this_char, "nobh")) + set_opt(sbi->s_mount_opt, NOBH); /* Silently ignore the quota options */ else if (!strcmp (this_char, "grpquota") || !strcmp (this_char, "noquota") diff -Nru a/fs/ext2/xattr.c b/fs/ext2/xattr.c --- a/fs/ext2/xattr.c Fri Nov 22 13:41:21 2002 +++ b/fs/ext2/xattr.c Fri Nov 22 13:41:21 2002 @@ -230,7 +230,7 @@ */ int ext2_setxattr(struct dentry *dentry, const char *name, - void *value, size_t size, int flags) + const void *value, size_t size, int flags) { struct ext2_xattr_handler *handler; struct inode *inode = dentry->d_inode; diff -Nru a/fs/ext2/xattr.h b/fs/ext2/xattr.h --- a/fs/ext2/xattr.h Fri Nov 22 13:41:18 2002 +++ b/fs/ext2/xattr.h Fri Nov 22 13:41:18 2002 @@ -67,7 +67,7 @@ extern int ext2_xattr_register(int, struct ext2_xattr_handler *); extern void ext2_xattr_unregister(int, struct ext2_xattr_handler *); -extern int ext2_setxattr(struct dentry *, const char *, void *, size_t, int); +extern int ext2_setxattr(struct dentry *, const char *, const void *, size_t, int); extern ssize_t ext2_getxattr(struct dentry *, const char *, void *, size_t); extern ssize_t ext2_listxattr(struct dentry *, char *, size_t); extern int ext2_removexattr(struct dentry *, const char *); diff -Nru a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c --- a/fs/ext3/ialloc.c Fri Nov 22 13:41:20 2002 +++ b/fs/ext3/ialloc.c Fri Nov 22 13:41:20 2002 @@ -167,9 +167,11 @@ if (gdp) { gdp->bg_free_inodes_count = cpu_to_le16( le16_to_cpu(gdp->bg_free_inodes_count) + 1); - if (is_directory) + if (is_directory) { gdp->bg_used_dirs_count = cpu_to_le16( le16_to_cpu(gdp->bg_used_dirs_count) - 1); + EXT3_SB(sb)->s_dir_count--; + } } BUFFER_TRACE(bh2, "call ext3_journal_dirty_metadata"); err = ext3_journal_dirty_metadata(handle, bh2); diff -Nru a/fs/ext3/namei.c b/fs/ext3/namei.c --- a/fs/ext3/namei.c Fri Nov 22 13:41:21 2002 +++ b/fs/ext3/namei.c Fri Nov 22 13:41:21 2002 @@ -1018,7 +1018,8 @@ struct ext3_dir_entry_2 *de = (struct ext3_dir_entry_2 *) (from + map->offs); rec_len = EXT3_DIR_REC_LEN(de->name_len); memcpy (to, de, rec_len); - ((struct ext3_dir_entry_2 *) to)->rec_len = rec_len; + ((struct ext3_dir_entry_2 *) to)->rec_len = + cpu_to_le16(rec_len); de->inode = 0; map++; to += rec_len; @@ -1039,7 +1040,7 @@ rec_len = EXT3_DIR_REC_LEN(de->name_len); if (de > to) memmove(to, de, rec_len); - to->rec_len = rec_len; + to->rec_len = cpu_to_le16(rec_len); prev = to; to = (struct ext3_dir_entry_2 *) (((char *) to) + rec_len); } @@ -1616,7 +1617,7 @@ } static int ext3_mknod (struct inode * dir, struct dentry *dentry, - int mode, int rdev) + int mode, dev_t rdev) { handle_t *handle; struct inode *inode; diff -Nru a/fs/ext3/xattr.c b/fs/ext3/xattr.c --- a/fs/ext3/xattr.c Fri Nov 22 13:41:20 2002 +++ b/fs/ext3/xattr.c Fri Nov 22 13:41:20 2002 @@ -223,7 +223,7 @@ */ int ext3_setxattr(struct dentry *dentry, const char *name, - void *value, size_t size, int flags) + const void *value, size_t size, int flags) { struct ext3_xattr_handler *handler; struct inode *inode = dentry->d_inode; diff -Nru a/fs/ext3/xattr.h b/fs/ext3/xattr.h --- a/fs/ext3/xattr.h Fri Nov 22 13:41:23 2002 +++ b/fs/ext3/xattr.h Fri Nov 22 13:41:23 2002 @@ -66,7 +66,7 @@ extern int ext3_xattr_register(int, struct ext3_xattr_handler *); extern void ext3_xattr_unregister(int, struct ext3_xattr_handler *); -extern int ext3_setxattr(struct dentry *, const char *, void *, size_t, int); +extern int ext3_setxattr(struct dentry *, const char *, const void *, size_t, int); extern ssize_t ext3_getxattr(struct dentry *, const char *, void *, size_t); extern ssize_t ext3_listxattr(struct dentry *, char *, size_t); extern int ext3_removexattr(struct dentry *, const char *); diff -Nru a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h --- a/fs/hpfs/hpfs_fn.h Fri Nov 22 13:41:21 2002 +++ b/fs/hpfs/hpfs_fn.h Fri Nov 22 13:41:21 2002 @@ -282,7 +282,7 @@ int hpfs_mkdir(struct inode *, struct dentry *, int); int hpfs_create(struct inode *, struct dentry *, int); -int hpfs_mknod(struct inode *, struct dentry *, int, int); +int hpfs_mknod(struct inode *, struct dentry *, int, dev_t); int hpfs_symlink(struct inode *, struct dentry *, const char *); int hpfs_unlink(struct inode *, struct dentry *); int hpfs_rmdir(struct inode *, struct dentry *); diff -Nru a/fs/hpfs/namei.c b/fs/hpfs/namei.c --- a/fs/hpfs/namei.c Fri Nov 22 13:41:19 2002 +++ b/fs/hpfs/namei.c Fri Nov 22 13:41:19 2002 @@ -181,7 +181,7 @@ return -ENOSPC; } -int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev) +int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) { const char *name = dentry->d_name.name; unsigned len = dentry->d_name.len; diff -Nru a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c --- a/fs/hugetlbfs/inode.c Fri Nov 22 13:41:23 2002 +++ b/fs/hugetlbfs/inode.c Fri Nov 22 13:41:23 2002 @@ -359,7 +359,8 @@ return error; } -struct inode *hugetlbfs_get_inode(struct super_block *sb, int mode, int dev) +static struct inode * +hugetlbfs_get_inode(struct super_block *sb, int mode, dev_t dev) { struct inode * inode = new_inode(sb); @@ -399,7 +400,8 @@ * File creation. Allocate an inode, and we're done.. */ /* SMP-safe */ -static int hugetlbfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev) +static int +hugetlbfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) { struct inode * inode = hugetlbfs_get_inode(dir->i_sb, mode, dev); int error = -ENOSPC; diff -Nru a/fs/inode.c b/fs/inode.c --- a/fs/inode.c Fri Nov 22 13:41:23 2002 +++ b/fs/inode.c Fri Nov 22 13:41:23 2002 @@ -102,7 +102,6 @@ struct address_space * const mapping = &inode->i_data; inode->i_sb = sb; - inode->i_dev = sb->s_dev; inode->i_blkbits = sb->s_blocksize_bits; inode->i_flags = 0; atomic_set(&inode->i_count, 1); @@ -147,12 +146,10 @@ if (inode_has_buffers(inode)) BUG(); security_ops->inode_free_security(inode); - if (inode->i_sb->s_op->destroy_inode) { + if (inode->i_sb->s_op->destroy_inode) inode->i_sb->s_op->destroy_inode(inode); - } else { - BUG_ON(inode->i_data.page_tree.rnode != NULL); + else kmem_cache_free(inode_cachep, (inode)); - } } @@ -1269,4 +1266,22 @@ panic("cannot create inode slab cache"); set_shrinker(DEFAULT_SEEKS, shrink_icache_memory); +} + +void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev) +{ + inode->i_mode = mode; + if (S_ISCHR(mode)) { + inode->i_fop = &def_chr_fops; + inode->i_rdev = to_kdev_t(rdev); + inode->i_cdev = cdget(rdev); + } else if (S_ISBLK(mode)) { + inode->i_fop = &def_blk_fops; + inode->i_rdev = to_kdev_t(rdev); + } else if (S_ISFIFO(mode)) + inode->i_fop = &def_fifo_fops; + else if (S_ISSOCK(mode)) + inode->i_fop = &bad_sock_fops; + else + printk(KERN_DEBUG "init_special_inode: bogus i_mode (%o)\n", mode); } diff -Nru a/fs/intermezzo/dcache.c b/fs/intermezzo/dcache.c --- a/fs/intermezzo/dcache.c Fri Nov 22 13:41:22 2002 +++ b/fs/intermezzo/dcache.c Fri Nov 22 13:41:22 2002 @@ -48,7 +48,7 @@ #include -static kmem_cache_t * presto_dentry_slab; +kmem_cache_t * presto_dentry_slab; /* called when a cache lookup succeeds */ static int presto_d_revalidate(struct dentry *de, int flag) diff -Nru a/fs/intermezzo/dir.c b/fs/intermezzo/dir.c --- a/fs/intermezzo/dir.c Fri Nov 22 13:41:18 2002 +++ b/fs/intermezzo/dir.c Fri Nov 22 13:41:18 2002 @@ -720,7 +720,7 @@ return error; } -static int presto_mknod(struct inode * dir, struct dentry * dentry, int mode, int rdev) +static int presto_mknod(struct inode * dir, struct dentry * dentry, int mode, dev_t rdev) { int error; struct presto_cache *cache; diff -Nru a/fs/intermezzo/journal.c b/fs/intermezzo/journal.c --- a/fs/intermezzo/journal.c Fri Nov 22 13:41:17 2002 +++ b/fs/intermezzo/journal.c Fri Nov 22 13:41:17 2002 @@ -261,7 +261,7 @@ *--end = '\0'; buflen--; - if (dentry->d_parent != dentry && list_empty(&dentry->d_hash)) { + if (dentry->d_parent != dentry && d_unhashed(dentry)) { buflen -= 10; end -= 10; memcpy(end, " (deleted)", 10); @@ -1518,7 +1518,7 @@ } if (!dentry->d_inode || (dentry->d_inode->i_nlink == 0) - || ((dentry->d_parent != dentry) && list_empty(&dentry->d_hash))) { + || ((dentry->d_parent != dentry) && d_unhashed(dentry))) { EXIT; return 0; } @@ -2129,7 +2129,7 @@ } if (!dentry->d_inode || (dentry->d_inode->i_nlink == 0) - || ((dentry->d_parent != dentry) && list_empty(&dentry->d_hash))) { + || ((dentry->d_parent != dentry) && d_unhashed(dentry))) { EXIT; return 0; } @@ -2391,7 +2391,7 @@ } if (!dentry->d_inode || (dentry->d_inode->i_nlink == 0) - || ((dentry->d_parent != dentry) && list_empty(&dentry->d_hash))) { + || ((dentry->d_parent != dentry) && d_unhashed(dentry))) { EXIT; return 0; } diff -Nru a/fs/intermezzo/journal_ext2.c b/fs/intermezzo/journal_ext2.c --- a/fs/intermezzo/journal_ext2.c Fri Nov 22 13:41:18 2002 +++ b/fs/intermezzo/journal_ext2.c Fri Nov 22 13:41:18 2002 @@ -81,11 +81,11 @@ } struct journal_ops presto_ext2_journal_ops = { - tr_all_data: presto_e2_has_all_data, - tr_avail: presto_e2_freespace, - tr_start: presto_e2_trans_start, - tr_commit: presto_e2_trans_commit, - tr_journal_data: NULL + .tr_all_data = presto_e2_has_all_data, + .tr_avail = presto_e2_freespace, + .tr_start = presto_e2_trans_start, + .tr_commit = presto_e2_trans_commit, + .tr_journal_data = NULL }; #endif /* CONFIG_EXT2_FS */ diff -Nru a/fs/intermezzo/journal_tmpfs.c b/fs/intermezzo/journal_tmpfs.c --- a/fs/intermezzo/journal_tmpfs.c Fri Nov 22 13:41:23 2002 +++ b/fs/intermezzo/journal_tmpfs.c Fri Nov 22 13:41:23 2002 @@ -97,13 +97,13 @@ } struct journal_ops presto_tmpfs_journal_ops = { - tr_all_data: presto_tmpfs_has_all_data, - tr_avail: presto_tmpfs_freespace, - tr_start: presto_tmpfs_trans_start, - tr_commit: presto_tmpfs_trans_commit, - tr_journal_data: presto_tmpfs_journal_file_data, - tr_ilookup: presto_tmpfs_ilookup, - tr_add_ilookup: presto_add_ilookup_dentry + .tr_all_data = presto_tmpfs_has_all_data, + .tr_avail = presto_tmpfs_freespace, + .tr_start = presto_tmpfs_trans_start, + .tr_commit = presto_tmpfs_trans_commit, + .tr_journal_data = presto_tmpfs_journal_file_data, + .tr_ilookup = presto_tmpfs_ilookup, + .tr_add_ilookup = presto_add_ilookup_dentry }; #endif /* CONFIG_EXT3_FS */ diff -Nru a/fs/intermezzo/presto.c b/fs/intermezzo/presto.c --- a/fs/intermezzo/presto.c Fri Nov 22 13:41:21 2002 +++ b/fs/intermezzo/presto.c Fri Nov 22 13:41:21 2002 @@ -67,7 +67,7 @@ CDEBUG(D_PSDEV, "\n"); if ( !cache ) { CERROR("PRESTO: BAD: cannot find cache for dev %d, ino %ld\n", - inode->i_dev, inode->i_ino); + inode->i_sb->s_dev, inode->i_ino); EXIT; return -1; } diff -Nru a/fs/intermezzo/vfs.c b/fs/intermezzo/vfs.c --- a/fs/intermezzo/vfs.c Fri Nov 22 13:41:18 2002 +++ b/fs/intermezzo/vfs.c Fri Nov 22 13:41:18 2002 @@ -182,7 +182,7 @@ { int minor = presto_f2m(fset); int errorval = izo_channels[minor].uc_errorval; - kdev_t dev = to_kdev_t(fset->fset_dentry->d_inode->i_dev); + kdev_t dev = to_kdev_t(fset->fset_dentry->d_inode->i_sb->s_dev); if (errorval && errorval == (long)value && !is_read_only(dev)) { CDEBUG(D_SUPER, "setting device %s read only\n", kdevname(dev)); @@ -763,7 +763,7 @@ goto exit_lock; error = -EXDEV; - if (dir->d_inode->i_dev != inode->i_dev) + if (dir->d_inode->i_sb->s_dev != inode->i_sb->s_dev) goto exit_lock; /* @@ -1820,7 +1820,7 @@ if (error) return error; - if (new_dir->i_dev != old_dir->i_dev) + if (new_dir->i_sb->s_dev != old_dir->i_sb->s_dev) return -EXDEV; if (!new_dentry->d_inode) @@ -1901,7 +1901,7 @@ if (error) return error; - if (new_dir->i_dev != old_dir->i_dev) + if (new_dir->i_sb->s_dev != old_dir->i_sb->s_dev) return -EXDEV; if (!new_dentry->d_inode) diff -Nru a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c --- a/fs/jffs/inode-v23.c Fri Nov 22 13:41:21 2002 +++ b/fs/jffs/inode-v23.c Fri Nov 22 13:41:21 2002 @@ -1072,7 +1072,7 @@ static int -jffs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev) +jffs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) { struct jffs_raw_inode raw_inode; struct jffs_file *dir_f; diff -Nru a/fs/jffs2/TODO b/fs/jffs2/TODO --- a/fs/jffs2/TODO Fri Nov 22 13:41:23 2002 +++ b/fs/jffs2/TODO Fri Nov 22 13:41:23 2002 @@ -1,4 +1,4 @@ -$Id: TODO,v 1.9 2002/07/11 10:39:04 dwmw2 Exp $ +$Id: TODO,v 1.10 2002/09/09 16:31:21 dwmw2 Exp $ - disable compression in commit_write()? - fine-tune the allocation / GC thresholds @@ -23,22 +23,18 @@ - Optimisations: - Stop GC from decompressing and immediately recompressing nodes which could - just be copied intact. + just be copied intact. (We now keep track of REF_PRISTINE flag. Easy now.) - Furthermore, in the case where it could be copied intact we don't even need to call iget() for it -- if we use (raw_node_raw->flash_offset & 2) as a flag to show a node can be copied intact and it's _not_ in icache, we could just do it, fix up the next_in_ino list and move on. We would need a way to find out _whether_ it's in icache though -- if it's in icache we also need to do the fragment lists, etc. P'raps a flag or pointer in the jffs2_inode_cache could - help. + help. (We have half of this now.) - Stop keeping name in-core with struct jffs2_full_dirent. If we keep the hash in the full dirent, we only need to go to the flash in lookup() when we think we've got a match, and in readdir(). - Doubly-linked next_in_ino list to allow us to free obsoleted raw_node_refs immediately? - Remove totlen from jffs2_raw_node_ref? Need to have totlen passed into jffs2_mark_node_obsolete(). Can all callers work it out? - - Don't check data CRC on node scan during mount. We don't really need to know - yet. This means we can't build up node fragment lists, and hence can't - build accurate clean/dirty information. But we don't _need_ that for reading, - only for writing. And in fact we don't even need it for writing until we - start to need GC. + - Remove size from jffs2_raw_node_frag. diff -Nru a/fs/jffs2/background.c b/fs/jffs2/background.c --- a/fs/jffs2/background.c Fri Nov 22 13:41:17 2002 +++ b/fs/jffs2/background.c Fri Nov 22 13:41:17 2002 @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: background.c,v 1.29 2002/06/07 10:04:28 dwmw2 Exp $ + * $Id: background.c,v 1.33 2002/11/12 09:44:30 dwmw2 Exp $ * */ @@ -83,21 +83,22 @@ struct jffs2_sb_info *c = _c; daemonize(); + c->gc_task = current; up(&c->gc_thread_start); - sprintf(current->comm, "jffs2_gcd_mtd%d", c->mtd->index); + sprintf(current->comm, "jffs2_gcd_mtd%d", c->mtd->index); set_user_nice(current, 10); for (;;) { - spin_lock_irq(¤t->sig->siglock); + spin_lock_irq(¤t_sig_lock); siginitsetinv (¤t->blocked, sigmask(SIGHUP) | sigmask(SIGKILL) | sigmask(SIGSTOP) | sigmask(SIGCONT)); recalc_sigpending(); - spin_unlock_irq(¤t->sig->siglock); + spin_unlock_irq(¤t_sig_lock); if (!thread_should_wake(c)) { - set_current_state (TASK_INTERRUPTIBLE); + set_current_state (TASK_INTERRUPTIBLE); D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread sleeping...\n")); /* Yes, there's a race here; we checked thread_should_wake() before setting current->state to TASK_INTERRUPTIBLE. But it doesn't @@ -105,30 +106,30 @@ is only an optimisation anyway. */ schedule(); } - + cond_resched(); - /* Put_super will send a SIGKILL and then wait on the sem. - */ - while (signal_pending(current)) { - siginfo_t info; - unsigned long signr = 0 ; + /* Put_super will send a SIGKILL and then wait on the sem. + */ + while (signal_pending(current)) { + siginfo_t info; + unsigned long signr; - spin_lock_irq(¤t->sig->siglock); + spin_lock_irq(¤t_sig_lock); signr = dequeue_signal(¤t->blocked, &info); - spin_unlock_irq(¤t->sig->siglock); + spin_unlock_irq(¤t_sig_lock); - switch(signr) { - case SIGSTOP: - D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): SIGSTOP received.\n")); - set_current_state(TASK_STOPPED); - schedule(); - break; + switch(signr) { + case SIGSTOP: + D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): SIGSTOP received.\n")); + set_current_state(TASK_STOPPED); + schedule(); + break; - case SIGKILL: - D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): SIGKILL received.\n")); + case SIGKILL: + D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): SIGKILL received.\n")); spin_lock_bh(&c->erase_completion_lock); - c->gc_task = NULL; + c->gc_task = NULL; spin_unlock_bh(&c->erase_completion_lock); complete_and_exit(&c->gc_thread_exit, 0); @@ -137,14 +138,13 @@ break; default: D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): signal %ld received\n", signr)); - - } - } + } + } /* We don't want SIGHUP to interrupt us. STOP and KILL are OK though. */ - spin_lock_irq(¤t->sig->siglock); + spin_lock_irq(¤t_sig_lock); siginitsetinv (¤t->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP) | sigmask(SIGCONT)); recalc_sigpending(); - spin_unlock_irq(¤t->sig->siglock); + spin_unlock_irq(¤t_sig_lock); D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): pass\n")); jffs2_garbage_collect_pass(c); @@ -153,23 +153,20 @@ static int thread_should_wake(struct jffs2_sb_info *c) { - uint32_t gcnodeofs = 0; - int ret; + int ret = 0; - /* Don't count any progress we've already made through the gcblock - as dirty space, for the purposes of this calculation */ - if (c->gcblock && c->gcblock->gc_node) - gcnodeofs = c->gcblock->gc_node->flash_offset & ~3 & (c->sector_size-1); + if (c->unchecked_size) { + D1(printk(KERN_DEBUG "thread_should_wake(): unchecked_size %d, checked_ino #%d\n", + c->unchecked_size, c->checked_ino)); + return 1; + } - if (c->nr_free_blocks + c->nr_erasing_blocks < JFFS2_RESERVED_BLOCKS_GCTRIGGER && - (c->dirty_size - gcnodeofs) > c->sector_size) + if (c->nr_free_blocks + c->nr_erasing_blocks < JFFS2_RESERVED_BLOCKS_GCTRIGGER && + (c->dirty_size > c->sector_size)) ret = 1; - else - ret = 0; - D1(printk(KERN_DEBUG "thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x (mod 0x%x): %s\n", - c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size, - c->dirty_size - gcnodeofs, ret?"yes":"no")); + D1(printk(KERN_DEBUG "thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x: %s\n", + c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size, ret?"yes":"no")); return ret; } diff -Nru a/fs/jffs2/build.c b/fs/jffs2/build.c --- a/fs/jffs2/build.c Fri Nov 22 13:41:20 2002 +++ b/fs/jffs2/build.c Fri Nov 22 13:41:20 2002 @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: build.c,v 1.35 2002/05/20 14:56:37 dwmw2 Exp $ + * $Id: build.c,v 1.42 2002/09/09 16:29:08 dwmw2 Exp $ * */ @@ -43,8 +43,9 @@ return ret; D1(printk(KERN_DEBUG "Scanned flash completely\n")); - /* Now build the data map for each inode, marking obsoleted nodes - as such, and also increase nlink of any children. */ + D1(jffs2_dump_block_lists(c)); + + /* Now scan the directory tree, increasing nlink according to every dirent found. */ for_each_inode(i, c, ic) { D1(printk(KERN_DEBUG "Pass 1: ino #%u\n", ic->ino)); ret = jffs2_build_inode_pass1(c, ic); @@ -52,8 +53,10 @@ D1(printk(KERN_WARNING "Eep. jffs2_build_inode_pass1 for ino %d returned %d\n", ic->ino, ret)); return ret; } + cond_resched(); } D1(printk(KERN_DEBUG "Pass 1 complete\n")); + D1(jffs2_dump_block_lists(c)); /* Next, scan for inodes with nlink == 0 and remove them. If they were directories, then decrement the nlink of their @@ -68,6 +71,8 @@ if (ic->nlink) continue; + /* XXX: Can get high latency here. Move the cond_resched() from the end of the loop? */ + ret = jffs2_build_remove_unlinked_inode(c, ic); if (ret) break; @@ -75,115 +80,52 @@ and furthermore that it had children and their nlink has now gone to zero too. So we have to restart the scan. */ } - } while(ret == -EAGAIN); + D1(jffs2_dump_block_lists(c)); + + cond_resched(); + } while(ret == -EAGAIN); + D1(printk(KERN_DEBUG "Pass 2 complete\n")); /* Finally, we can scan again and free the dirent nodes and scan_info structs */ for_each_inode(i, c, ic) { - struct jffs2_scan_info *scan = ic->scan; struct jffs2_full_dirent *fd; D1(printk(KERN_DEBUG "Pass 3: ino #%u, ic %p, nodes %p\n", ic->ino, ic, ic->nodes)); - if (!scan) { - if (ic->nlink) { - D1(printk(KERN_WARNING "Why no scan struct for ino #%u which has nlink %d?\n", ic->ino, ic->nlink)); - } - continue; - } - ic->scan = NULL; - while(scan->dents) { - fd = scan->dents; - scan->dents = fd->next; + + while(ic->scan_dents) { + fd = ic->scan_dents; + ic->scan_dents = fd->next; jffs2_free_full_dirent(fd); } - kfree(scan); + ic->scan_dents = NULL; + cond_resched(); } D1(printk(KERN_DEBUG "Pass 3 complete\n")); + D1(jffs2_dump_block_lists(c)); /* Rotate the lists by some number to ensure wear levelling */ jffs2_rotate_lists(c); return ret; } - + int jffs2_build_inode_pass1(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) { - struct jffs2_tmp_dnode_info *tn; struct jffs2_full_dirent *fd; - struct jffs2_node_frag *fraglist = NULL; - struct jffs2_tmp_dnode_info *metadata = NULL; D1(printk(KERN_DEBUG "jffs2_build_inode building inode #%u\n", ic->ino)); + if (ic->ino > c->highest_ino) c->highest_ino = ic->ino; - if (!ic->scan->tmpnodes && ic->ino != 1) { - D1(printk(KERN_DEBUG "jffs2_build_inode: ino #%u has no data nodes!\n", ic->ino)); - } - /* Build the list to make sure any obsolete nodes are marked as such */ - while(ic->scan->tmpnodes) { - tn = ic->scan->tmpnodes; - ic->scan->tmpnodes = tn->next; - - if (metadata && tn->version > metadata->version) { - D1(printk(KERN_DEBUG "jffs2_build_inode_pass1 ignoring old metadata at 0x%08x\n", - metadata->fn->raw->flash_offset &~3)); - - jffs2_mark_node_obsolete(c, metadata->fn->raw); - jffs2_free_full_dnode(metadata->fn); - jffs2_free_tmp_dnode_info(metadata); - metadata = NULL; - } - - if (tn->fn->size) { - jffs2_add_full_dnode_to_fraglist (c, &fraglist, tn->fn); - jffs2_free_tmp_dnode_info(tn); - } else { - if (!metadata) { - metadata = tn; - } else { - /* This will only happen if it has the _same_ version - number as the existing metadata node. */ - D1(printk(KERN_DEBUG "jffs2_build_inode_pass1 ignoring new metadata at 0x%08x\n", - tn->fn->raw->flash_offset &~3)); - - jffs2_mark_node_obsolete(c, tn->fn->raw); - jffs2_free_full_dnode(tn->fn); - jffs2_free_tmp_dnode_info(tn); - } - } - } - - if (ic->scan->version) { - /* It's a regular file, so truncate it to the last known - i_size, if necessary */ - D1(printk(KERN_DEBUG "jffs2_build_inode_pass1 truncating fraglist to 0x%08x\n", ic->scan->isize)); - jffs2_truncate_fraglist(c, &fraglist, ic->scan->isize); - } - - /* OK. Now clear up */ - if (metadata) { - jffs2_free_full_dnode(metadata->fn); - jffs2_free_tmp_dnode_info(metadata); - } - metadata = NULL; - - while (fraglist) { - struct jffs2_node_frag *frag; - frag = fraglist; - fraglist = fraglist->next; - - if (frag->node && !(--frag->node->frags)) { - jffs2_free_full_dnode(frag->node); - } - jffs2_free_node_frag(frag); - } - - /* Now for each child, increase nlink */ - for(fd=ic->scan->dents; fd; fd = fd->next) { + /* For each child, increase nlink */ + for(fd=ic->scan_dents; fd; fd = fd->next) { struct jffs2_inode_cache *child_ic; if (!fd->ino) continue; + + /* XXX: Can get high latency here with huge directories */ child_ic = jffs2_get_ino_cache(c, fd->ino); if (!child_ic) { @@ -212,26 +154,33 @@ struct jffs2_full_dirent *fd; int ret = 0; - if(!ic->scan) { - D1(printk(KERN_DEBUG "ino #%u was already removed\n", ic->ino)); - return 0; - } - D1(printk(KERN_DEBUG "JFFS2: Removing ino #%u with nlink == zero.\n", ic->ino)); for (raw = ic->nodes; raw != (void *)ic; raw = raw->next_in_ino) { - D1(printk(KERN_DEBUG "obsoleting node at 0x%08x\n", raw->flash_offset&~3)); + D1(printk(KERN_DEBUG "obsoleting node at 0x%08x\n", ref_offset(raw))); jffs2_mark_node_obsolete(c, raw); } - if (ic->scan->dents) { - printk(KERN_NOTICE "Inode #%u was a directory with children - removing those too...\n", ic->ino); - - while(ic->scan->dents) { + if (ic->scan_dents) { + int whinged = 0; + D1(printk(KERN_DEBUG "Inode #%u was a directory which may have children...\n", ic->ino)); + + while(ic->scan_dents) { struct jffs2_inode_cache *child_ic; - fd = ic->scan->dents; - ic->scan->dents = fd->next; + fd = ic->scan_dents; + ic->scan_dents = fd->next; + + if (!fd->ino) { + /* It's a deletion dirent. Ignore it */ + D1(printk(KERN_DEBUG "Child \"%s\" is a deletion dirent, skipping...\n", fd->name)); + jffs2_free_full_dirent(fd); + continue; + } + if (!whinged) { + whinged = 1; + printk(KERN_NOTICE "Inode #%u was a directory with children - removing those too...\n", ic->ino); + } D1(printk(KERN_DEBUG "Removing child \"%s\", ino #%u\n", fd->name, fd->ino)); @@ -239,6 +188,7 @@ child_ic = jffs2_get_ino_cache(c, fd->ino); if (!child_ic) { printk(KERN_NOTICE "Cannot remove child \"%s\", ino #%u, because it doesn't exist\n", fd->name, fd->ino); + jffs2_free_full_dirent(fd); continue; } jffs2_free_full_dirent(fd); @@ -246,8 +196,6 @@ } ret = -EAGAIN; } - kfree(ic->scan); - ic->scan = NULL; /* We don't delete the inocache from the hash list and free it yet. @@ -271,6 +219,8 @@ c->blocks[i].offset = i * c->sector_size; c->blocks[i].free_size = c->sector_size; c->blocks[i].dirty_size = 0; + c->blocks[i].wasted_size = 0; + c->blocks[i].unchecked_size = 0; c->blocks[i].used_size = 0; c->blocks[i].first_node = NULL; c->blocks[i].last_node = NULL; diff -Nru a/fs/jffs2/dir.c b/fs/jffs2/dir.c --- a/fs/jffs2/dir.c Fri Nov 22 13:41:22 2002 +++ b/fs/jffs2/dir.c Fri Nov 22 13:41:22 2002 @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: dir.c,v 1.71 2002/07/23 17:00:45 dwmw2 Exp $ + * $Id: dir.c,v 1.73 2002/08/26 15:00:51 dwmw2 Exp $ * */ @@ -32,7 +32,7 @@ static int jffs2_symlink (struct inode *,struct dentry *,const char *); static int jffs2_mkdir (struct inode *,struct dentry *,int); static int jffs2_rmdir (struct inode *,struct dentry *); -static int jffs2_mknod (struct inode *,struct dentry *,int,int); +static int jffs2_mknod (struct inode *,struct dentry *,int,dev_t); static int jffs2_rename (struct inode *, struct dentry *, struct inode *, struct dentry *); @@ -211,7 +211,7 @@ return ret; } - dir_i->i_mtime.tv_sec = dir_i->i_ctime.tv_sec = ri->ctime; + dir_i->i_mtime.tv_sec = dir_i->i_ctime.tv_sec = je32_to_cpu(ri->ctime); dir_i->i_mtime.tv_nsec = dir_i->i_ctime.tv_nsec = 0; jffs2_free_raw_inode(ri); @@ -234,7 +234,8 @@ ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name, dentry->d_name.len, dead_f); - dentry->d_inode->i_nlink = dead_f->inocache->nlink; + if (dead_f->inocache) + dentry->d_inode->i_nlink = dead_f->inocache->nlink; return ret; } /***********************************************************************/ @@ -248,6 +249,10 @@ int ret; uint8_t type; + /* Don't let people make hard links to bad inodes. */ + if (!f->inocache) + return -EIO; + if (S_ISDIR(old_dentry->d_inode->i_mode)) return -EPERM; @@ -318,13 +323,14 @@ f = JFFS2_INODE_INFO(inode); - inode->i_size = ri->isize = ri->dsize = ri->csize = strlen(target); - ri->totlen = sizeof(*ri) + ri->dsize; - ri->hdr_crc = crc32(0, ri, sizeof(struct jffs2_unknown_node)-4); + inode->i_size = strlen(target); + ri->isize = ri->dsize = ri->csize = cpu_to_je32(inode->i_size); + ri->totlen = cpu_to_je32(sizeof(*ri) + inode->i_size); + ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); ri->compr = JFFS2_COMPR_NONE; - ri->data_crc = crc32(0, target, strlen(target)); - ri->node_crc = crc32(0, ri, sizeof(*ri)-8); + ri->data_crc = cpu_to_je32(crc32(0, target, strlen(target))); + ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); fn = jffs2_write_dnode(c, f, ri, target, strlen(target), phys_ofs, &writtenlen); @@ -370,19 +376,19 @@ dir_f = JFFS2_INODE_INFO(dir_i); down(&dir_f->sem); - rd->magic = JFFS2_MAGIC_BITMASK; - rd->nodetype = JFFS2_NODETYPE_DIRENT; - rd->totlen = sizeof(*rd) + namelen; - rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4); - - rd->pino = dir_i->i_ino; - rd->version = ++dir_f->highest_version; - rd->ino = inode->i_ino; - rd->mctime = get_seconds(); + rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); + rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); + rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); + + rd->pino = cpu_to_je32(dir_i->i_ino); + rd->version = cpu_to_je32(++dir_f->highest_version); + rd->ino = cpu_to_je32(inode->i_ino); + rd->mctime = cpu_to_je32(get_seconds()); rd->nsize = namelen; rd->type = DT_LNK; - rd->node_crc = crc32(0, rd, sizeof(*rd)-8); - rd->name_crc = crc32(0, dentry->d_name.name, namelen); + rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); + rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen); @@ -396,7 +402,7 @@ return PTR_ERR(fd); } - dir_i->i_mtime.tv_sec = dir_i->i_ctime.tv_sec = rd->mctime; + dir_i->i_mtime.tv_sec = dir_i->i_ctime.tv_sec = je32_to_cpu(rd->mctime); dir_i->i_mtime.tv_nsec = dir_i->i_ctime.tv_nsec = 0; jffs2_free_raw_dirent(rd); @@ -461,8 +467,8 @@ f = JFFS2_INODE_INFO(inode); - ri->data_crc = 0; - ri->node_crc = crc32(0, ri, sizeof(*ri)-8); + ri->data_crc = cpu_to_je32(0); + ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, &writtenlen); @@ -508,19 +514,19 @@ dir_f = JFFS2_INODE_INFO(dir_i); down(&dir_f->sem); - rd->magic = JFFS2_MAGIC_BITMASK; - rd->nodetype = JFFS2_NODETYPE_DIRENT; - rd->totlen = sizeof(*rd) + namelen; - rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4); - - rd->pino = dir_i->i_ino; - rd->version = ++dir_f->highest_version; - rd->ino = inode->i_ino; - rd->mctime = get_seconds(); + rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); + rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); + rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); + + rd->pino = cpu_to_je32(dir_i->i_ino); + rd->version = cpu_to_je32(++dir_f->highest_version); + rd->ino = cpu_to_je32(inode->i_ino); + rd->mctime = cpu_to_je32(get_seconds()); rd->nsize = namelen; rd->type = DT_DIR; - rd->node_crc = crc32(0, rd, sizeof(*rd)-8); - rd->name_crc = crc32(0, dentry->d_name.name, namelen); + rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); + rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen); @@ -534,7 +540,7 @@ return PTR_ERR(fd); } - dir_i->i_mtime.tv_sec = dir_i->i_ctime.tv_sec = rd->mctime; + dir_i->i_mtime.tv_sec = dir_i->i_ctime.tv_sec = je32_to_cpu(rd->mctime); dir_i->i_mtime.tv_nsec = dir_i->i_ctime.tv_nsec = 0; dir_i->i_nlink++; @@ -567,7 +573,7 @@ return ret; } -static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, int rdev) +static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, dev_t rdev) { struct jffs2_inode_info *f, *dir_f; struct jffs2_sb_info *c; @@ -617,13 +623,13 @@ f = JFFS2_INODE_INFO(inode); - ri->dsize = ri->csize = devlen; - ri->totlen = sizeof(*ri) + ri->csize; - ri->hdr_crc = crc32(0, ri, sizeof(struct jffs2_unknown_node)-4); + ri->dsize = ri->csize = cpu_to_je32(devlen); + ri->totlen = cpu_to_je32(sizeof(*ri) + devlen); + ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); ri->compr = JFFS2_COMPR_NONE; - ri->data_crc = crc32(0, &dev, devlen); - ri->node_crc = crc32(0, ri, sizeof(*ri)-8); + ri->data_crc = cpu_to_je32(crc32(0, &dev, devlen)); + ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); fn = jffs2_write_dnode(c, f, ri, (char *)&dev, devlen, phys_ofs, &writtenlen); @@ -669,22 +675,22 @@ dir_f = JFFS2_INODE_INFO(dir_i); down(&dir_f->sem); - rd->magic = JFFS2_MAGIC_BITMASK; - rd->nodetype = JFFS2_NODETYPE_DIRENT; - rd->totlen = sizeof(*rd) + namelen; - rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4); - - rd->pino = dir_i->i_ino; - rd->version = ++dir_f->highest_version; - rd->ino = inode->i_ino; - rd->mctime = get_seconds(); + rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); + rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); + rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); + + rd->pino = cpu_to_je32(dir_i->i_ino); + rd->version = cpu_to_je32(++dir_f->highest_version); + rd->ino = cpu_to_je32(inode->i_ino); + rd->mctime = cpu_to_je32(get_seconds()); rd->nsize = namelen; /* XXX: This is ugly. */ rd->type = (mode & S_IFMT) >> 12; - rd->node_crc = crc32(0, rd, sizeof(*rd)-8); - rd->name_crc = crc32(0, dentry->d_name.name, namelen); + rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); + rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen); @@ -698,7 +704,7 @@ return PTR_ERR(fd); } - dir_i->i_mtime.tv_sec = dir_i->i_ctime.tv_sec = rd->mctime; + dir_i->i_mtime.tv_sec = dir_i->i_ctime.tv_sec = je32_to_cpu(rd->mctime); dir_i->i_mtime.tv_nsec = dir_i->i_ctime.tv_nsec = 0; jffs2_free_raw_dirent(rd); @@ -790,7 +796,8 @@ struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode); down(&f->sem); old_dentry->d_inode->i_nlink++; - f->inocache->nlink++; + if (f->inocache) + f->inocache->nlink++; up(&f->sem); printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret); diff -Nru a/fs/jffs2/erase.c b/fs/jffs2/erase.c --- a/fs/jffs2/erase.c Fri Nov 22 13:41:18 2002 +++ b/fs/jffs2/erase.c Fri Nov 22 13:41:18 2002 @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: erase.c,v 1.39 2002/07/23 17:00:45 dwmw2 Exp $ + * $Id: erase.c,v 1.45 2002/10/09 08:27:08 dwmw2 Exp $ * */ @@ -27,6 +27,7 @@ static void jffs2_erase_callback(struct erase_info *); static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); +static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); void jffs2_erase_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) { @@ -81,12 +82,18 @@ else printk(KERN_WARNING "Erase at 0x%08x failed immediately: errno %d\n", jeb->offset, ret); + /* Note: This is almost identical to jffs2_erase_failed() except + for the fact that we used spin_lock_bh() not spin_lock(). If + we could use spin_lock_bh() from a BH, we could merge them. + Or if we abandon the idea that MTD drivers may call the erase + callback from a BH, I suppose :) + */ spin_lock_bh(&c->erase_completion_lock); + c->erasing_size -= c->sector_size; + c->bad_size += c->sector_size; list_del(&jeb->list); list_add(&jeb->list, &c->bad_list); c->nr_erasing_blocks--; - c->bad_size += c->sector_size; - c->erasing_size -= c->sector_size; spin_unlock_bh(&c->erase_completion_lock); wake_up(&c->erase_wait); } @@ -98,36 +105,46 @@ down(&c->erase_free_sem); spin_lock_bh(&c->erase_completion_lock); - while (!list_empty(&c->erase_pending_list)) { - jeb = list_entry(c->erase_pending_list.next, struct jffs2_eraseblock, list); + while (!list_empty(&c->erase_complete_list) || + !list_empty(&c->erase_pending_list)) { - D1(printk(KERN_DEBUG "Starting erase of pending block 0x%08x\n", jeb->offset)); + if (!list_empty(&c->erase_complete_list)) { + jeb = list_entry(c->erase_complete_list.next, struct jffs2_eraseblock, list); + list_del(&jeb->list); + spin_unlock_bh(&c->erase_completion_lock); + jffs2_mark_erased_block(c, jeb); + + } else if (!list_empty(&c->erase_pending_list)) { + jeb = list_entry(c->erase_pending_list.next, struct jffs2_eraseblock, list); + D1(printk(KERN_DEBUG "Starting erase of pending block 0x%08x\n", jeb->offset)); + list_del(&jeb->list); + c->erasing_size += c->sector_size; + c->free_size -= jeb->free_size; + c->used_size -= jeb->used_size; + c->dirty_size -= jeb->dirty_size; + jeb->used_size = jeb->dirty_size = jeb->free_size = 0; + jffs2_free_all_node_refs(c, jeb); + list_add(&jeb->list, &c->erasing_list); + spin_unlock_bh(&c->erase_completion_lock); - list_del(&jeb->list); - c->erasing_size += c->sector_size; - c->free_size -= jeb->free_size; - c->used_size -= jeb->used_size; - c->dirty_size -= jeb->dirty_size; - jeb->used_size = jeb->dirty_size = jeb->free_size = 0; - jffs2_free_all_node_refs(c, jeb); - list_add(&jeb->list, &c->erasing_list); - spin_unlock_bh(&c->erase_completion_lock); - - jffs2_erase_block(c, jeb); + jffs2_erase_block(c, jeb); + + } else { + BUG(); + } /* Be nice */ cond_resched(); - spin_lock_bh(&c->erase_completion_lock); } + spin_unlock_bh(&c->erase_completion_lock); D1(printk(KERN_DEBUG "jffs2_erase_pending_blocks completed\n")); up(&c->erase_free_sem); } - static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) { D1(printk(KERN_DEBUG "Erase completed successfully at 0x%08x\n", jeb->offset)); @@ -135,6 +152,8 @@ list_del(&jeb->list); list_add_tail(&jeb->list, &c->erase_complete_list); spin_unlock(&c->erase_completion_lock); + /* Ensure that kupdated calls us again to mark them clean */ + jffs2_erase_pending_trigger(c); } @@ -160,8 +179,6 @@ } else { jffs2_erase_succeeded(priv->c, priv->jeb); } - /* Make sure someone picks up the block off the erase_complete list */ - OFNI_BS_2SFFJ(priv->c)->s_dirt = 1; kfree(instr); } @@ -220,7 +237,7 @@ this = ic->nodes; while(this) { - printk( "0x%08x(%d)->", this->flash_offset & ~3, this->flash_offset &3); + printk( "0x%08x(%d)->", ref_offset(this), ref_flags(this)); if (++i == 5) { printk("\n" KERN_DEBUG); i=0; @@ -260,135 +277,133 @@ OFNI_BS_2SFFJ(c)->s_dirt = 1; } -void jffs2_mark_erased_blocks(struct jffs2_sb_info *c) +static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) { - struct jffs2_eraseblock *jeb; struct jffs2_raw_node_ref *marker_ref = NULL; unsigned char *ebuf; size_t retlen; int ret; - spin_lock_bh(&c->erase_completion_lock); - while (!list_empty(&c->erase_complete_list)) { - jeb = list_entry(c->erase_complete_list.next, struct jffs2_eraseblock, list); - list_del(&jeb->list); - spin_unlock_bh(&c->erase_completion_lock); - - if (!jffs2_cleanmarker_oob(c)) { - marker_ref = jffs2_alloc_raw_node_ref(); - if (!marker_ref) { - printk(KERN_WARNING "Failed to allocate raw node ref for clean marker\n"); - /* Come back later */ - jffs2_erase_pending_trigger(c); - return; - } + if (!jffs2_cleanmarker_oob(c)) { + marker_ref = jffs2_alloc_raw_node_ref(); + if (!marker_ref) { + printk(KERN_WARNING "Failed to allocate raw node ref for clean marker\n"); + /* Stick it back on the list from whence it came and come back later */ + jffs2_erase_pending_trigger(c); + spin_lock_bh(&c->erase_completion_lock); + list_add(&jeb->list, &c->erase_complete_list); + spin_unlock_bh(&c->erase_completion_lock); + return; } - ebuf = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!ebuf) { - printk(KERN_WARNING "Failed to allocate page buffer for verifying erase at 0x%08x. Assuming it worked\n", jeb->offset); - } else { - uint32_t ofs = jeb->offset; + } + ebuf = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!ebuf) { + printk(KERN_WARNING "Failed to allocate page buffer for verifying erase at 0x%08x. Assuming it worked\n", jeb->offset); + } else { + uint32_t ofs = jeb->offset; - D1(printk(KERN_DEBUG "Verifying erase at 0x%08x\n", jeb->offset)); - while(ofs < jeb->offset + c->sector_size) { - uint32_t readlen = min((uint32_t)PAGE_SIZE, jeb->offset + c->sector_size - ofs); - int i; - - ret = jffs2_flash_read(c, ofs, readlen, &retlen, ebuf); - if (ret) { - printk(KERN_WARNING "Read of newly-erased block at 0x%08x failed: %d. Putting on bad_list\n", ofs, ret); - goto bad; - } - if (retlen != readlen) { - printk(KERN_WARNING "Short read from newly-erased block at 0x%08x. Wanted %d, got %d\n", ofs, readlen, retlen); - goto bad; - } - for (i=0; ierase_completion_lock); - c->erasing_size -= c->sector_size; - c->bad_size += c->sector_size; - - list_add_tail(&jeb->list, &c->bad_list); - c->nr_erasing_blocks--; - spin_unlock_bh(&c->erase_completion_lock); - wake_up(&c->erase_wait); - return; - } + D1(printk(KERN_DEBUG "Verifying erase at 0x%08x\n", jeb->offset)); + while(ofs < jeb->offset + c->sector_size) { + uint32_t readlen = min((uint32_t)PAGE_SIZE, jeb->offset + c->sector_size - ofs); + int i; + + ret = jffs2_flash_read(c, ofs, readlen, &retlen, ebuf); + if (ret) { + printk(KERN_WARNING "Read of newly-erased block at 0x%08x failed: %d. Putting on bad_list\n", ofs, ret); + goto bad; + } + if (retlen != readlen) { + printk(KERN_WARNING "Short read from newly-erased block at 0x%08x. Wanted %d, got %d\n", ofs, readlen, retlen); + goto bad; + } + for (i=0; ierase_completion_lock); + c->erasing_size -= c->sector_size; + c->bad_size += c->sector_size; + + list_add_tail(&jeb->list, &c->bad_list); + c->nr_erasing_blocks--; + spin_unlock_bh(&c->erase_completion_lock); + wake_up(&c->erase_wait); + return; } - ofs += readlen; - cond_resched(); } - kfree(ebuf); + ofs += readlen; + cond_resched(); } + kfree(ebuf); + } - /* Write the erase complete marker */ - D1(printk(KERN_DEBUG "Writing erased marker to block at 0x%08x\n", jeb->offset)); - if (jffs2_cleanmarker_oob(c)) { + /* Write the erase complete marker */ + D1(printk(KERN_DEBUG "Writing erased marker to block at 0x%08x\n", jeb->offset)); + if (jffs2_cleanmarker_oob(c)) { - if (jffs2_write_nand_cleanmarker(c, jeb)) - goto bad2; - - jeb->first_node = jeb->last_node = NULL; + if (jffs2_write_nand_cleanmarker(c, jeb)) + goto bad2; - jeb->free_size = c->sector_size; - jeb->used_size = 0; - jeb->dirty_size = 0; - } else { - struct jffs2_unknown_node marker = { - .magic = JFFS2_MAGIC_BITMASK, - .nodetype = JFFS2_NODETYPE_CLEANMARKER, - .totlen = c->cleanmarker_size - }; + jeb->first_node = jeb->last_node = NULL; - marker.hdr_crc = crc32(0, &marker, marker.totlen - 4); + jeb->free_size = c->sector_size; + jeb->used_size = 0; + jeb->dirty_size = 0; + jeb->wasted_size = 0; + } else { + struct jffs2_unknown_node marker = { + .magic = cpu_to_je16(JFFS2_MAGIC_BITMASK), + .nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER), + .totlen = cpu_to_je32(c->cleanmarker_size) + }; + + marker.hdr_crc = cpu_to_je32(crc32(0, &marker, je32_to_cpu(marker.totlen) - 4)); + + ret = jffs2_flash_write(c, jeb->offset, je32_to_cpu(marker.totlen), &retlen, (char *)&marker); + if (ret) { + printk(KERN_WARNING "Write clean marker to block at 0x%08x failed: %d\n", + jeb->offset, ret); + goto bad2; + } + if (retlen != je32_to_cpu(marker.totlen)) { + printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %d, got %d\n", + jeb->offset, je32_to_cpu(marker.totlen), retlen); + goto bad2; + } - ret = jffs2_flash_write(c, jeb->offset, marker.totlen, &retlen, (char *)&marker); - if (ret) { - printk(KERN_WARNING "Write clean marker to block at 0x%08x failed: %d\n", - jeb->offset, ret); - goto bad2; - } - if (retlen != marker.totlen) { - printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %d, got %d\n", - jeb->offset, marker.totlen, retlen); - goto bad2; - } - - marker_ref->next_in_ino = NULL; - marker_ref->next_phys = NULL; - marker_ref->flash_offset = jeb->offset; - marker_ref->totlen = PAD(marker.totlen); + marker_ref->next_in_ino = NULL; + marker_ref->next_phys = NULL; + marker_ref->flash_offset = jeb->offset | REF_NORMAL; + marker_ref->totlen = PAD(je32_to_cpu(marker.totlen)); - jeb->first_node = jeb->last_node = marker_ref; + jeb->first_node = jeb->last_node = marker_ref; - jeb->free_size = c->sector_size - marker_ref->totlen; - jeb->used_size = marker_ref->totlen; - jeb->dirty_size = 0; - } + jeb->free_size = c->sector_size - marker_ref->totlen; + jeb->used_size = marker_ref->totlen; + jeb->dirty_size = 0; + jeb->wasted_size = 0; + } - spin_lock_bh(&c->erase_completion_lock); - c->erasing_size -= c->sector_size; - c->free_size += jeb->free_size; - c->used_size += jeb->used_size; + spin_lock_bh(&c->erase_completion_lock); + c->erasing_size -= c->sector_size; + c->free_size += jeb->free_size; + c->used_size += jeb->used_size; - ACCT_SANITY_CHECK(c,jeb); - ACCT_PARANOIA_CHECK(jeb); + ACCT_SANITY_CHECK(c,jeb); + D1(ACCT_PARANOIA_CHECK(jeb)); - list_add_tail(&jeb->list, &c->free_list); - c->nr_erasing_blocks--; - c->nr_free_blocks++; - wake_up(&c->erase_wait); - } + list_add_tail(&jeb->list, &c->free_list); + c->nr_erasing_blocks--; + c->nr_free_blocks++; spin_unlock_bh(&c->erase_completion_lock); + wake_up(&c->erase_wait); } + diff -Nru a/fs/jffs2/file.c b/fs/jffs2/file.c --- a/fs/jffs2/file.c Fri Nov 22 13:41:23 2002 +++ b/fs/jffs2/file.c Fri Nov 22 13:41:23 2002 @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: file.c,v 1.76 2002/07/29 08:25:35 dwmw2 Exp $ + * $Id: file.c,v 1.81 2002/11/12 09:46:22 dwmw2 Exp $ * */ @@ -139,41 +139,43 @@ down(&f->sem); ivalid = iattr->ia_valid; - ri->magic = JFFS2_MAGIC_BITMASK; - ri->nodetype = JFFS2_NODETYPE_INODE; - ri->totlen = sizeof(*ri) + mdatalen; - ri->hdr_crc = crc32(0, ri, sizeof(struct jffs2_unknown_node)-4); - - ri->ino = inode->i_ino; - ri->version = ++f->highest_version; - - ri->mode = (ivalid & ATTR_MODE)?iattr->ia_mode:inode->i_mode; - ri->uid = (ivalid & ATTR_UID)?iattr->ia_uid:inode->i_uid; - ri->gid = (ivalid & ATTR_GID)?iattr->ia_gid:inode->i_gid; - - if (ivalid & ATTR_MODE && ri->mode & S_ISGID && - !in_group_p(ri->gid) && !capable(CAP_FSETID)) - ri->mode &= ~S_ISGID; - - ri->isize = (ivalid & ATTR_SIZE)?iattr->ia_size:inode->i_size; - ri->atime = (ivalid & ATTR_ATIME)?iattr->ia_atime.tv_sec:inode->i_atime.tv_sec; - ri->mtime = (ivalid & ATTR_MTIME)?iattr->ia_mtime.tv_sec:inode->i_mtime.tv_sec; - ri->ctime = (ivalid & ATTR_CTIME)?iattr->ia_ctime.tv_sec:inode->i_ctime.tv_sec; + ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); + ri->totlen = cpu_to_je32(sizeof(*ri) + mdatalen); + ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); + + ri->ino = cpu_to_je32(inode->i_ino); + ri->version = cpu_to_je32(++f->highest_version); + + ri->uid = cpu_to_je16((ivalid & ATTR_UID)?iattr->ia_uid:inode->i_uid); + ri->gid = cpu_to_je16((ivalid & ATTR_GID)?iattr->ia_gid:inode->i_gid); + + if (ivalid & ATTR_MODE) + if (iattr->ia_mode & S_ISGID && + !in_group_p(je16_to_cpu(ri->gid)) && !capable(CAP_FSETID)) + ri->mode = cpu_to_je32(iattr->ia_mode & ~S_ISGID); + else + ri->mode = cpu_to_je32(iattr->ia_mode); + else + ri->mode = cpu_to_je32(inode->i_mode); + - ri->offset = 0; - ri->csize = ri->dsize = mdatalen; + ri->isize = cpu_to_je32((ivalid & ATTR_SIZE)?iattr->ia_size:inode->i_size); + ri->atime = cpu_to_je32((ivalid & ATTR_ATIME)?iattr->ia_atime.tv_sec:inode->i_atime.tv_sec); + ri->mtime = cpu_to_je32((ivalid & ATTR_MTIME)?iattr->ia_mtime.tv_sec:inode->i_mtime.tv_sec); + ri->ctime = cpu_to_je32((ivalid & ATTR_CTIME)?iattr->ia_ctime.tv_sec:inode->i_ctime.tv_sec); ri->compr = JFFS2_COMPR_NONE; - if (inode->i_size < ri->isize) { + if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) { /* It's an extension. Make it a hole node */ ri->compr = JFFS2_COMPR_ZERO; - ri->dsize = ri->isize - inode->i_size; - ri->offset = inode->i_size; + ri->dsize = cpu_to_je32(iattr->ia_size - inode->i_size); + ri->offset = cpu_to_je32(inode->i_size); } - ri->node_crc = crc32(0, ri, sizeof(*ri)-8); + ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); if (mdatalen) - ri->data_crc = crc32(0, mdata, mdatalen); + ri->data_crc = cpu_to_je32(crc32(0, mdata, mdatalen)); else - ri->data_crc = 0; + ri->data_crc = cpu_to_je32(0); new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, phys_ofs, NULL); if (S_ISLNK(inode->i_mode)) @@ -186,27 +188,27 @@ return PTR_ERR(new_metadata); } /* It worked. Update the inode */ - inode->i_atime.tv_sec = ri->atime; - inode->i_ctime.tv_sec = ri->ctime; - inode->i_mtime.tv_sec = ri->mtime; + inode->i_atime.tv_sec = je32_to_cpu(ri->atime); + inode->i_ctime.tv_sec = je32_to_cpu(ri->ctime); + inode->i_mtime.tv_sec = je32_to_cpu(ri->mtime); inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = inode->i_mtime.tv_nsec = 0; - inode->i_mode = ri->mode; - inode->i_uid = ri->uid; - inode->i_gid = ri->gid; + inode->i_mode = je32_to_cpu(ri->mode); + inode->i_uid = je16_to_cpu(ri->uid); + inode->i_gid = je16_to_cpu(ri->gid); old_metadata = f->metadata; - if (inode->i_size > ri->isize) { - vmtruncate(inode, ri->isize); - jffs2_truncate_fraglist (c, &f->fraglist, ri->isize); + if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) { + vmtruncate(inode, iattr->ia_size); + jffs2_truncate_fraglist (c, &f->fragtree, iattr->ia_size); } - if (inode->i_size < ri->isize) { + if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) { jffs2_add_full_dnode_to_inode(c, f, new_metadata); - inode->i_size = ri->isize; + inode->i_size = iattr->ia_size; f->metadata = NULL; } else { f->metadata = new_metadata; @@ -281,7 +283,6 @@ uint32_t pageofs = pg->index << PAGE_CACHE_SHIFT; int ret = 0; - down(&f->sem); D1(printk(KERN_DEBUG "jffs2_prepare_write()\n")); if (pageofs > inode->i_size) { @@ -295,30 +296,30 @@ (unsigned int)inode->i_size, pageofs)); ret = jffs2_reserve_space(c, sizeof(ri), &phys_ofs, &alloc_len, ALLOC_NORMAL); - if (ret) { - up(&f->sem); + if (ret) return ret; - } + + down(&f->sem); memset(&ri, 0, sizeof(ri)); - ri.magic = JFFS2_MAGIC_BITMASK; - ri.nodetype = JFFS2_NODETYPE_INODE; - ri.totlen = sizeof(ri); - ri.hdr_crc = crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4); - - ri.ino = f->inocache->ino; - ri.version = ++f->highest_version; - ri.mode = inode->i_mode; - ri.uid = inode->i_uid; - ri.gid = inode->i_gid; - ri.isize = max((uint32_t)inode->i_size, pageofs); - ri.atime = ri.ctime = ri.mtime = get_seconds(); - ri.offset = inode->i_size; - ri.dsize = pageofs - inode->i_size; - ri.csize = 0; + ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); + ri.totlen = cpu_to_je32(sizeof(ri)); + ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4)); + + ri.ino = cpu_to_je32(f->inocache->ino); + ri.version = cpu_to_je32(++f->highest_version); + ri.mode = cpu_to_je32(inode->i_mode); + ri.uid = cpu_to_je16(inode->i_uid); + ri.gid = cpu_to_je16(inode->i_gid); + ri.isize = cpu_to_je32(max((uint32_t)inode->i_size, pageofs)); + ri.atime = ri.ctime = ri.mtime = cpu_to_je32(get_seconds()); + ri.offset = cpu_to_je32(inode->i_size); + ri.dsize = cpu_to_je32(pageofs - inode->i_size); + ri.csize = cpu_to_je32(0); ri.compr = JFFS2_COMPR_ZERO; - ri.node_crc = crc32(0, &ri, sizeof(ri)-8); - ri.data_crc = 0; + ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); + ri.data_crc = cpu_to_je32(0); fn = jffs2_write_dnode(c, f, &ri, NULL, 0, phys_ofs, NULL); @@ -344,14 +345,16 @@ } jffs2_complete_reservation(c); inode->i_size = pageofs; + up(&f->sem); } - - /* Read in the page if it wasn't already present */ - if (!PageUptodate(pg) && (start || end < PAGE_SIZE)) + /* Read in the page if it wasn't already present, unless it's a whole page */ + if (!PageUptodate(pg) && (start || end < PAGE_CACHE_SIZE)) { + down(&f->sem); ret = jffs2_do_readpage_nolock(inode, pg); - D1(printk(KERN_DEBUG "end prepare_write()\n")); - up(&f->sem); + up(&f->sem); + } + D1(printk(KERN_DEBUG "end prepare_write(). pg->flags %lx\n", pg->flags)); return ret; } @@ -367,8 +370,16 @@ int ret = 0; uint32_t writtenlen = 0; - D1(printk(KERN_DEBUG "jffs2_commit_write(): ino #%lu, page at 0x%lx, range %d-%d\n", - inode->i_ino, pg->index << PAGE_CACHE_SHIFT, start, end)); + D1(printk(KERN_DEBUG "jffs2_commit_write(): ino #%lu, page at 0x%lx, range %d-%d, flags %lx\n", + inode->i_ino, pg->index << PAGE_CACHE_SHIFT, start, end, pg->flags)); + + if (!start && end == PAGE_CACHE_SIZE) { + /* We need to avoid deadlock with page_cache_read() in + jffs2_garbage_collect_pass(). So we have to mark the + page up to date, to prevent page_cache_read() from + trying to re-lock it. */ + SetPageUptodate(pg); + } ri = jffs2_alloc_raw_inode(); @@ -378,16 +389,21 @@ } /* Set the fields that the generic jffs2_write_inode_range() code can't find */ - ri->ino = inode->i_ino; - ri->mode = inode->i_mode; - ri->uid = inode->i_uid; - ri->gid = inode->i_gid; - ri->isize = (uint32_t)inode->i_size; - ri->atime = ri->ctime = ri->mtime = get_seconds(); + ri->ino = cpu_to_je32(inode->i_ino); + ri->mode = cpu_to_je32(inode->i_mode); + ri->uid = cpu_to_je16(inode->i_uid); + ri->gid = cpu_to_je16(inode->i_gid); + ri->isize = cpu_to_je32((uint32_t)inode->i_size); + ri->atime = ri->ctime = ri->mtime = cpu_to_je32(get_seconds()); + /* In 2.4, it was already kmapped by generic_file_write(). Doesn't + hurt to do it again. The alternative is ifdefs, which are ugly. */ kmap(pg); + ret = jffs2_write_inode_range(c, f, ri, page_address(pg) + start, - (pg->index << PAGE_CACHE_SHIFT) + start, end - start, &writtenlen); + (pg->index << PAGE_CACHE_SHIFT) + start, + end - start, &writtenlen); + kunmap(pg); if (ret) { @@ -400,7 +416,7 @@ inode->i_size = (pg->index << PAGE_CACHE_SHIFT) + start + writtenlen; inode->i_blocks = (inode->i_size + 511) >> 9; - inode->i_ctime.tv_sec = inode->i_mtime.tv_sec = ri->ctime; + inode->i_ctime.tv_sec = inode->i_mtime.tv_sec = je32_to_cpu(ri->ctime); inode->i_ctime.tv_nsec = inode->i_mtime.tv_nsec = 0; } } diff -Nru a/fs/jffs2/fs.c b/fs/jffs2/fs.c --- a/fs/jffs2/fs.c Fri Nov 22 13:41:19 2002 +++ b/fs/jffs2/fs.c Fri Nov 22 13:41:19 2002 @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: fs.c,v 1.13 2002/07/02 22:48:24 dwmw2 Exp $ + * $Id: fs.c,v 1.19 2002/11/12 09:53:40 dwmw2 Exp $ * */ @@ -86,15 +86,15 @@ up(&f->sem); return; } - inode->i_mode = latest_node.mode; - inode->i_uid = latest_node.uid; - inode->i_gid = latest_node.gid; - inode->i_size = latest_node.isize; - inode->i_atime.tv_sec = latest_node.atime; - inode->i_mtime.tv_sec = latest_node.mtime; - inode->i_ctime.tv_sec = latest_node.ctime; - inode->i_atime.tv_nsec = - inode->i_mtime.tv_nsec = + inode->i_mode = je32_to_cpu(latest_node.mode); + inode->i_uid = je16_to_cpu(latest_node.uid); + inode->i_gid = je16_to_cpu(latest_node.gid); + inode->i_size = je32_to_cpu(latest_node.isize); + inode->i_atime.tv_sec = je32_to_cpu(latest_node.atime); + inode->i_mtime.tv_sec = je32_to_cpu(latest_node.mtime); + inode->i_ctime.tv_sec = je32_to_cpu(latest_node.ctime); + inode->i_atime.tv_nsec = + inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = 0; inode->i_nlink = f->inocache->nlink; @@ -192,19 +192,9 @@ if (sb->s_flags & MS_RDONLY) return; - D1(printk(KERN_DEBUG "jffs2_write_super(): flush_wbuf before gc-trigger\n")); + D1(printk(KERN_DEBUG "jffs2_write_super()\n")); jffs2_garbage_collect_trigger(c); jffs2_erase_pending_blocks(c); - jffs2_mark_erased_blocks(c); - /* Eep. If we lock this here, we deadlock with jffs2_reserve_space() when - * it locks the alloc_sem and jffs2_do_reserve_space() waits for erases - * to happen. I think the erases and/or the flush_wbuf want doing from - * - */ - if (!down_trylock(&c->alloc_sem)) { - jffs2_flush_wbuf(c, 2); - up(&c->alloc_sem); - } // else it stays dirty. FIXME. } @@ -232,16 +222,16 @@ memset(ri, 0, sizeof(*ri)); /* Set OS-specific defaults for new inodes */ - ri->uid = current->fsuid; + ri->uid = cpu_to_je16(current->fsuid); if (dir_i->i_mode & S_ISGID) { - ri->gid = dir_i->i_gid; + ri->gid = cpu_to_je16(dir_i->i_gid); if (S_ISDIR(mode)) - ri->mode |= S_ISGID; + mode |= S_ISGID; } else { - ri->gid = current->fsgid; + ri->gid = cpu_to_je16(current->fsgid); } - ri->mode = mode; + ri->mode = cpu_to_je32(mode); ret = jffs2_do_new_inode (c, f, mode, ri); if (ret) { make_bad_inode(inode); @@ -249,12 +239,14 @@ return ERR_PTR(ret); } inode->i_nlink = 1; - inode->i_ino = ri->ino; - inode->i_mode = ri->mode; - inode->i_gid = ri->gid; - inode->i_uid = ri->uid; - inode->i_atime = inode->i_ctime = inode->i_mtime = - ri->atime = ri->mtime = ri->ctime = get_seconds(); + inode->i_ino = je32_to_cpu(ri->ino); + inode->i_mode = je32_to_cpu(ri->mode); + inode->i_gid = je16_to_cpu(ri->gid); + inode->i_uid = je16_to_cpu(ri->uid); + inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = inode->i_mtime.tv_nsec = 0; + inode->i_atime.tv_sec = inode->i_ctime.tv_sec = inode->i_mtime.tv_sec = get_seconds(); + ri->atime = ri->mtime = ri->ctime = cpu_to_je32(inode->i_mtime.tv_sec); + inode->i_blksize = PAGE_SIZE; inode->i_blocks = 0; inode->i_size = 0; @@ -305,9 +297,10 @@ if (!c->wbuf) return -ENOMEM; - /* Initialize process for timed wbuf flush */ + /* Initialise process for timed wbuf flush */ INIT_WORK(&c->wbuf_task,(void*) jffs2_wbuf_process, (void *)c); - /* Initialize timer for timed wbuf flush */ + + /* Initialise timer for timed wbuf flush */ init_timer(&c->wbuf_timer); c->wbuf_timer.function = jffs2_wbuf_timeout; c->wbuf_timer.data = (unsigned long) c; diff -Nru a/fs/jffs2/gc.c b/fs/jffs2/gc.c --- a/fs/jffs2/gc.c Fri Nov 22 13:41:18 2002 +++ b/fs/jffs2/gc.c Fri Nov 22 13:41:18 2002 @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: gc.c,v 1.74 2002/05/20 14:56:38 dwmw2 Exp $ + * $Id: gc.c,v 1.88 2002/10/08 16:56:08 dwmw2 Exp $ * */ @@ -17,6 +17,7 @@ #include #include #include +#include #include "nodelist.h" static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, @@ -86,6 +87,15 @@ printk(KERN_WARNING "Eep. ret->gc_node for block at 0x%08x is NULL\n", ret->offset); BUG(); } + + /* Have we accidentally picked a clean block with wasted space ? */ + if (ret->wasted_size) { + D1(printk(KERN_DEBUG "Converting wasted_size %08x to dirty_size\n", ret->wasted_size)); + ret->dirty_size += ret->wasted_size; + c->wasted_size -= ret->wasted_size; + c->dirty_size += ret->wasted_size; + ret->wasted_size = 0; + } D1(jffs2_dump_block_lists(c)); return ret; @@ -113,6 +123,49 @@ spin_lock_bh(&c->erase_completion_lock); + while (c->unchecked_size) { + /* We can't start doing GC yet. We haven't finished checking + the node CRCs etc. Do it now and wait for it. */ + struct jffs2_inode_cache *ic; + + if (c->checked_ino > c->highest_ino) { + printk(KERN_CRIT "Checked all inodes but still 0x%x bytes of unchecked space?\n", + c->unchecked_size); + D1(jffs2_dump_block_lists(c)); + BUG(); + } + ic = jffs2_get_ino_cache(c, c->checked_ino++); + if (!ic) + continue; + if (!ic->nlink) { + D1(printk(KERN_DEBUG "Skipping check of ino #%d with nlink zero\n", + ic->ino)); + continue; + } + if (ic->state != INO_STATE_UNCHECKED) { + D1(printk(KERN_DEBUG "Skipping check of ino #%d already in state %d\n", + ic->ino, ic->state)); + continue; + } + + spin_unlock_bh(&c->erase_completion_lock); + + D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() triggering inode scan of ino#%d\n", ic->ino)); + + { + /* XXX: This wants doing more sensibly -- split the core of jffs2_do_read_inode up */ + struct inode *i = iget(OFNI_BS_2SFFJ(c), ic->ino); + if (is_bad_inode(i)) { + printk(KERN_NOTICE "Eep. read_inode() failed for ino #%u\n", ic->ino); + ret = -EIO; + } + iput(i); + } + + up(&c->alloc_sem); + return ret; + } + /* First, work out which block we're garbage-collecting */ jeb = c->gcblock; @@ -128,15 +181,17 @@ D1(printk(KERN_DEBUG "GC from block %08x, used_size %08x, dirty_size %08x, free_size %08x\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size)); D1(if (c->nextblock) - printk(KERN_DEBUG "Nextblock at %08x, used_size %08x, dirty_size %08x, free_size %08x\n", c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->free_size)); + printk(KERN_DEBUG "Nextblock at %08x, used_size %08x, dirty_size %08x, wasted_size %08x, free_size %08x\n", c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->wasted_size, c->nextblock->free_size)); - if (!jeb->used_size) + if (!jeb->used_size) { + up(&c->alloc_sem); goto eraseit; + } raw = jeb->gc_node; - while(raw->flash_offset & 1) { - D1(printk(KERN_DEBUG "Node at 0x%08x is obsolete... skipping\n", raw->flash_offset &~3)); + while(ref_obsolete(raw)) { + D1(printk(KERN_DEBUG "Node at 0x%08x is obsolete... skipping\n", ref_offset(raw))); jeb->gc_node = raw = raw->next_phys; if (!raw) { printk(KERN_WARNING "eep. End of raw list while still supposedly nodes to GC\n"); @@ -147,13 +202,14 @@ BUG(); } } - D1(printk(KERN_DEBUG "Going to garbage collect node at 0x%08x\n", raw->flash_offset &~3)); + D1(printk(KERN_DEBUG "Going to garbage collect node at 0x%08x\n", ref_offset(raw))); if (!raw->next_in_ino) { /* Inode-less node. Clean marker, snapshot or something like that */ /* FIXME: If it's something that needs to be copied, including something we don't grok that has JFFS2_NODETYPE_RWCOMPAT_COPY, we should do so */ spin_unlock_bh(&c->erase_completion_lock); jffs2_mark_node_obsolete(c, raw); + up(&c->alloc_sem); goto eraseit_lock; } @@ -162,14 +218,14 @@ spin_unlock_bh(&c->erase_completion_lock); - D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass collecting from block @0x%08x. Node @0x%08x, ino #%u\n", jeb->offset, raw->flash_offset&~3, inum)); + D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass collecting from block @0x%08x. Node @0x%08x, ino #%u\n", jeb->offset, ref_offset(raw), inum)); inode = iget(OFNI_BS_2SFFJ(c), inum); if (is_bad_inode(inode)) { printk(KERN_NOTICE "Eep. read_inode() failed for ino #%u\n", inum); /* NB. This will happen again. We need to do something appropriate here. */ - iput(inode); up(&c->alloc_sem); + iput(inode); return -EIO; } @@ -179,7 +235,7 @@ /* Now we have the lock for this inode. Check that it's still the one at the head of the list. */ - if (raw->flash_offset & 1) { + if (ref_obsolete(raw)) { D1(printk(KERN_DEBUG "node to be GC'd was obsoleted in the meantime.\n")); /* They'll call again */ goto upnout; @@ -190,11 +246,26 @@ ret = jffs2_garbage_collect_metadata(c, jeb, f, fn); goto upnout; } - - for (frag = f->fraglist; frag; frag = frag->next) { + + /* FIXME. Read node and do lookup? */ + for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) { if (frag->node && frag->node->raw == raw) { fn = frag->node; end = frag->ofs + frag->size; +#if 1 /* Temporary debugging sanity checks, till we're ready to _trust_ the REF_PRISTINE flag stuff */ + if (!nrfrags && ref_flags(fn->raw) == REF_PRISTINE) { + if (fn->frags > 1) + printk(KERN_WARNING "REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2\n", ref_offset(raw), fn->frags); + + if (frag->ofs & (PAGE_CACHE_SIZE-1) && frag_prev(frag) && frag_prev(frag)->node) + printk(KERN_WARNING "REF_PRISTINE node at 0x%08x had a previous non-hole frag in the same page. Tell dwmw2\n", + ref_offset(raw)); + + if ((frag->ofs+frag->size) & (PAGE_CACHE_SIZE-1) && frag_next(frag) && frag_next(frag)->node) + printk(KERN_WARNING "REF_PRISTINE node at 0x%08x (%08x-%08x) had a following non-hole frag in the same page. Tell dwmw2\n", + ref_offset(raw), frag->ofs, frag->ofs+frag->size); + } +#endif if (!nrfrags++) start = frag->ofs; if (nrfrags == frag->node->frags) @@ -225,8 +296,8 @@ ret = jffs2_garbage_collect_deletion_dirent(c, jeb, f, fd); } else { printk(KERN_WARNING "Raw node at 0x%08x wasn't in node lists for ino #%u\n", - raw->flash_offset&~3, f->inocache->ino); - if (raw->flash_offset & 1) { + ref_offset(raw), f->inocache->ino); + if (ref_obsolete(raw)) { printk(KERN_WARNING "But it's obsolete so we don't mind too much\n"); } else { ret = -EIO; @@ -234,6 +305,7 @@ } upnout: up(&f->sem); + up(&c->alloc_sem); iput(inode); eraseit_lock: @@ -250,7 +322,6 @@ jffs2_erase_pending_trigger(c); } spin_unlock_bh(&c->erase_completion_lock); - up(&c->alloc_sem); return ret; } @@ -299,26 +370,26 @@ } memset(&ri, 0, sizeof(ri)); - ri.magic = JFFS2_MAGIC_BITMASK; - ri.nodetype = JFFS2_NODETYPE_INODE; - ri.totlen = sizeof(ri) + mdatalen; - ri.hdr_crc = crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4); - - ri.ino = f->inocache->ino; - ri.version = ++f->highest_version; - ri.mode = JFFS2_F_I_MODE(f); - ri.uid = JFFS2_F_I_UID(f); - ri.gid = JFFS2_F_I_GID(f); - ri.isize = JFFS2_F_I_SIZE(f); - ri.atime = JFFS2_F_I_ATIME(f); - ri.ctime = JFFS2_F_I_CTIME(f); - ri.mtime = JFFS2_F_I_MTIME(f); - ri.offset = 0; - ri.csize = mdatalen; - ri.dsize = mdatalen; + ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); + ri.totlen = cpu_to_je32(sizeof(ri) + mdatalen); + ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4)); + + ri.ino = cpu_to_je32(f->inocache->ino); + ri.version = cpu_to_je32(++f->highest_version); + ri.mode = cpu_to_je32(JFFS2_F_I_MODE(f)); + ri.uid = cpu_to_je16(JFFS2_F_I_UID(f)); + ri.gid = cpu_to_je16(JFFS2_F_I_GID(f)); + ri.isize = cpu_to_je32(JFFS2_F_I_SIZE(f)); + ri.atime = cpu_to_je32(JFFS2_F_I_ATIME(f)); + ri.ctime = cpu_to_je32(JFFS2_F_I_CTIME(f)); + ri.mtime = cpu_to_je32(JFFS2_F_I_MTIME(f)); + ri.offset = cpu_to_je32(0); + ri.csize = cpu_to_je32(mdatalen); + ri.dsize = cpu_to_je32(mdatalen); ri.compr = JFFS2_COMPR_NONE; - ri.node_crc = crc32(0, &ri, sizeof(ri)-8); - ri.data_crc = crc32(0, mdata, mdatalen); + ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); + ri.data_crc = cpu_to_je32(crc32(0, mdata, mdatalen)); new_fn = jffs2_write_dnode(c, f, &ri, mdata, mdatalen, phys_ofs, NULL); @@ -344,19 +415,19 @@ uint32_t alloclen, phys_ofs; int ret; - rd.magic = JFFS2_MAGIC_BITMASK; - rd.nodetype = JFFS2_NODETYPE_DIRENT; + rd.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + rd.nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); rd.nsize = strlen(fd->name); - rd.totlen = sizeof(rd) + rd.nsize; - rd.hdr_crc = crc32(0, &rd, sizeof(struct jffs2_unknown_node)-4); + rd.totlen = cpu_to_je32(sizeof(rd) + rd.nsize); + rd.hdr_crc = cpu_to_je32(crc32(0, &rd, sizeof(struct jffs2_unknown_node)-4)); - rd.pino = f->inocache->ino; - rd.version = ++f->highest_version; - rd.ino = fd->ino; - rd.mctime = max(JFFS2_F_I_MTIME(f), JFFS2_F_I_CTIME(f)); + rd.pino = cpu_to_je32(f->inocache->ino); + rd.version = cpu_to_je32(++f->highest_version); + rd.ino = cpu_to_je32(fd->ino); + rd.mctime = cpu_to_je32(max(JFFS2_F_I_MTIME(f), JFFS2_F_I_CTIME(f))); rd.type = fd->type; - rd.node_crc = crc32(0, &rd, sizeof(rd)-8); - rd.name_crc = crc32(0, fd->name, rd.nsize); + rd.node_crc = cpu_to_je32(crc32(0, &rd, sizeof(rd)-8)); + rd.name_crc = cpu_to_je32(crc32(0, fd->name, rd.nsize)); ret = jffs2_reserve_space_gc(c, sizeof(rd)+rd.nsize, &phys_ofs, &alloclen); if (ret) { @@ -401,7 +472,7 @@ for (raw = f->inocache->nodes; raw != (void *)f->inocache; raw = raw->next_in_ino) { /* We only care about obsolete ones */ - if (!(raw->flash_offset & 1)) + if (!(ref_obsolete(raw))) continue; /* Doesn't matter if there's one in the same erase block. We're going to @@ -411,40 +482,40 @@ continue; /* This is an obsolete node belonging to the same directory */ - ret = jffs2_flash_read(c, raw->flash_offset & ~3, sizeof(struct jffs2_unknown_node), &retlen, (char *)&rd); + ret = jffs2_flash_read(c, ref_offset(raw), sizeof(struct jffs2_unknown_node), &retlen, (char *)&rd); if (ret) { - printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Read error (%d) reading header from obsolete node at %08x\n", ret, raw->flash_offset & ~3); - /* If we can't read it, we don't need to continune to obsolete it. Continue */ + printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Read error (%d) reading header from obsolete node at %08x\n", ret, ref_offset(raw)); + /* If we can't read it, we don't need to continue to obsolete it. Continue */ continue; } if (retlen != sizeof(struct jffs2_unknown_node)) { printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Short read (%d not %d) reading header from obsolete node at %08x\n", - retlen, sizeof(struct jffs2_unknown_node), raw->flash_offset & ~3); + retlen, sizeof(struct jffs2_unknown_node), ref_offset(raw)); continue; } - if (rd.nodetype != JFFS2_NODETYPE_DIRENT || - PAD(rd.totlen) != PAD(sizeof(rd) + name_len)) + if (je16_to_cpu(rd.nodetype) != JFFS2_NODETYPE_DIRENT || + PAD(je32_to_cpu(rd.totlen)) != PAD(sizeof(rd) + name_len)) continue; /* OK, it's a dirent node, it's the right length. We have to take a closer look at it... */ - ret = jffs2_flash_read(c, raw->flash_offset & ~3, sizeof(rd), &retlen, (char *)&rd); + ret = jffs2_flash_read(c, ref_offset(raw), sizeof(rd), &retlen, (char *)&rd); if (ret) { - printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Read error (%d) reading from obsolete node at %08x\n", ret, raw->flash_offset & ~3); + printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Read error (%d) reading from obsolete node at %08x\n", ret, ref_offset(raw)); /* If we can't read it, we don't need to continune to obsolete it. Continue */ continue; } - if (retlen != sizeof(struct jffs2_unknown_node)) { + if (retlen != sizeof(rd)) { printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Short read (%d not %d) reading from obsolete node at %08x\n", - retlen, sizeof(struct jffs2_unknown_node), raw->flash_offset & ~3); + retlen, sizeof(rd), ref_offset(raw)); continue; } /* If the name CRC doesn't match, skip */ - if (rd.name_crc != name_crc) + if (je32_to_cpu(rd.name_crc) != name_crc) continue; /* If the name length doesn't match, or it's another deletion dirent, skip */ - if (rd.nsize != name_len || !rd.ino) + if (rd.nsize != name_len || !je32_to_cpu(rd.ino)) continue; /* OK, check the actual name now */ @@ -456,15 +527,15 @@ } } /* We read the extra byte before it so it's a word-aligned read */ - ret = jffs2_flash_read(c, (raw->flash_offset & ~3)+sizeof(rd)-1, name_len+1, &retlen, namebuf); + ret = jffs2_flash_read(c, (ref_offset(raw))+sizeof(rd)-1, name_len+1, &retlen, namebuf); if (ret) { - printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Read error (%d) reading name from obsolete node at %08x\n", ret, raw->flash_offset & ~3); + printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Read error (%d) reading name from obsolete node at %08x\n", ret, ref_offset(raw)); /* If we can't read it, we don't need to continune to obsolete it. Continue */ continue; } - if (retlen != sizeof(rd)) { + if (retlen != name_len+1) { printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Short read (%d not %d) reading name from obsolete node at %08x\n", - retlen, name_len, raw->flash_offset & ~3); + retlen, name_len+1, ref_offset(raw)); continue; } if (memcmp(namebuf+1, fd->name, name_len)) @@ -524,59 +595,62 @@ uint32_t crc; /* It's partially obsoleted by a later write. So we have to write it out again with the _same_ version as before */ - ret = jffs2_flash_read(c, fn->raw->flash_offset & ~3, sizeof(ri), &readlen, (char *)&ri); + ret = jffs2_flash_read(c, ref_offset(fn->raw), sizeof(ri), &readlen, (char *)&ri); if (readlen != sizeof(ri) || ret) { - printk(KERN_WARNING "Node read failed in jffs2_garbage_collect_hole. Ret %d, retlen %d. Data will be lost by writing new hold node\n", ret, readlen); + printk(KERN_WARNING "Node read failed in jffs2_garbage_collect_hole. Ret %d, retlen %d. Data will be lost by writing new hole node\n", ret, readlen); goto fill; } - if (ri.nodetype != JFFS2_NODETYPE_INODE) { + if (je16_to_cpu(ri.nodetype) != JFFS2_NODETYPE_INODE) { printk(KERN_WARNING "jffs2_garbage_collect_hole: Node at 0x%08x had node type 0x%04x instead of JFFS2_NODETYPE_INODE(0x%04x)\n", - fn->raw->flash_offset & ~3, ri.nodetype, JFFS2_NODETYPE_INODE); + ref_offset(fn->raw), + je16_to_cpu(ri.nodetype), JFFS2_NODETYPE_INODE); return -EIO; } - if (ri.totlen != sizeof(ri)) { + if (je32_to_cpu(ri.totlen) != sizeof(ri)) { printk(KERN_WARNING "jffs2_garbage_collect_hole: Node at 0x%08x had totlen 0x%x instead of expected 0x%x\n", - fn->raw->flash_offset & ~3, ri.totlen, sizeof(ri)); + ref_offset(fn->raw), + je32_to_cpu(ri.totlen), sizeof(ri)); return -EIO; } crc = crc32(0, &ri, sizeof(ri)-8); - if (crc != ri.node_crc) { + if (crc != je32_to_cpu(ri.node_crc)) { printk(KERN_WARNING "jffs2_garbage_collect_hole: Node at 0x%08x had CRC 0x%08x which doesn't match calculated CRC 0x%08x\n", - fn->raw->flash_offset & ~3, ri.node_crc, crc); + ref_offset(fn->raw), + je32_to_cpu(ri.node_crc), crc); /* FIXME: We could possibly deal with this by writing new holes for each frag */ printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%u will be lost\n", start, end, f->inocache->ino); goto fill; } if (ri.compr != JFFS2_COMPR_ZERO) { - printk(KERN_WARNING "jffs2_garbage_collect_hole: Node 0x%08x wasn't a hole node!\n", fn->raw->flash_offset & ~3); + printk(KERN_WARNING "jffs2_garbage_collect_hole: Node 0x%08x wasn't a hole node!\n", ref_offset(fn->raw)); printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%u will be lost\n", start, end, f->inocache->ino); goto fill; } } else { fill: - ri.magic = JFFS2_MAGIC_BITMASK; - ri.nodetype = JFFS2_NODETYPE_INODE; - ri.totlen = sizeof(ri); - ri.hdr_crc = crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4); - - ri.ino = f->inocache->ino; - ri.version = ++f->highest_version; - ri.offset = start; - ri.dsize = end - start; - ri.csize = 0; + ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); + ri.totlen = cpu_to_je32(sizeof(ri)); + ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4)); + + ri.ino = cpu_to_je32(f->inocache->ino); + ri.version = cpu_to_je32(++f->highest_version); + ri.offset = cpu_to_je32(start); + ri.dsize = cpu_to_je32(end - start); + ri.csize = cpu_to_je32(0); ri.compr = JFFS2_COMPR_ZERO; } - ri.mode = JFFS2_F_I_MODE(f); - ri.uid = JFFS2_F_I_UID(f); - ri.gid = JFFS2_F_I_GID(f); - ri.isize = JFFS2_F_I_SIZE(f); - ri.atime = JFFS2_F_I_ATIME(f); - ri.ctime = JFFS2_F_I_CTIME(f); - ri.mtime = JFFS2_F_I_MTIME(f); - ri.data_crc = 0; - ri.node_crc = crc32(0, &ri, sizeof(ri)-8); + ri.mode = cpu_to_je32(JFFS2_F_I_MODE(f)); + ri.uid = cpu_to_je16(JFFS2_F_I_UID(f)); + ri.gid = cpu_to_je16(JFFS2_F_I_GID(f)); + ri.isize = cpu_to_je32(JFFS2_F_I_SIZE(f)); + ri.atime = cpu_to_je32(JFFS2_F_I_ATIME(f)); + ri.ctime = cpu_to_je32(JFFS2_F_I_CTIME(f)); + ri.mtime = cpu_to_je32(JFFS2_F_I_MTIME(f)); + ri.data_crc = cpu_to_je32(0); + ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); ret = jffs2_reserve_space_gc(c, sizeof(ri), &phys_ofs, &alloclen); if (ret) { @@ -590,7 +664,7 @@ printk(KERN_WARNING "Error writing new hole node: %ld\n", PTR_ERR(new_fn)); return PTR_ERR(new_fn); } - if (ri.version == f->highest_version) { + if (je32_to_cpu(ri.version) == f->highest_version) { jffs2_add_full_dnode_to_inode(c, f, new_fn); if (f->metadata) { jffs2_mark_node_obsolete(c, f->metadata->raw); @@ -608,10 +682,12 @@ */ D1(if(unlikely(fn->frags <= 1)) { printk(KERN_WARNING "jffs2_garbage_collect_hole: Replacing fn with %d frag(s) but new ver %d != highest_version %d of ino #%d\n", - fn->frags, ri.version, f->highest_version, ri.ino); + fn->frags, je32_to_cpu(ri.version), f->highest_version, + je32_to_cpu(ri.ino)); }); - for (frag = f->fraglist; frag; frag = frag->next) { + for (frag = jffs2_lookup_node_frag(&f->fragtree, fn->ofs); + frag; frag = frag_next(frag)) { if (frag->ofs > fn->size + fn->ofs) break; if (frag->node == fn) { @@ -655,7 +731,6 @@ orig_end = end; - /* If we're looking at the last node in the block we're garbage-collecting, we allow ourselves to merge as if the block was already erasing. We're likely to be GC'ing a @@ -722,26 +797,26 @@ } else { datalen = cdatalen; } - ri.magic = JFFS2_MAGIC_BITMASK; - ri.nodetype = JFFS2_NODETYPE_INODE; - ri.totlen = sizeof(ri) + cdatalen; - ri.hdr_crc = crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4); - - ri.ino = f->inocache->ino; - ri.version = ++f->highest_version; - ri.mode = JFFS2_F_I_MODE(f); - ri.uid = JFFS2_F_I_UID(f); - ri.gid = JFFS2_F_I_GID(f); - ri.isize = JFFS2_F_I_SIZE(f); - ri.atime = JFFS2_F_I_ATIME(f); - ri.ctime = JFFS2_F_I_CTIME(f); - ri.mtime = JFFS2_F_I_MTIME(f); - ri.offset = offset; - ri.csize = cdatalen; - ri.dsize = datalen; + ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); + ri.totlen = cpu_to_je32(sizeof(ri) + cdatalen); + ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4)); + + ri.ino = cpu_to_je32(f->inocache->ino); + ri.version = cpu_to_je32(++f->highest_version); + ri.mode = cpu_to_je32(JFFS2_F_I_MODE(f)); + ri.uid = cpu_to_je16(JFFS2_F_I_UID(f)); + ri.gid = cpu_to_je16(JFFS2_F_I_GID(f)); + ri.isize = cpu_to_je32(JFFS2_F_I_SIZE(f)); + ri.atime = cpu_to_je32(JFFS2_F_I_ATIME(f)); + ri.ctime = cpu_to_je32(JFFS2_F_I_CTIME(f)); + ri.mtime = cpu_to_je32(JFFS2_F_I_MTIME(f)); + ri.offset = cpu_to_je32(offset); + ri.csize = cpu_to_je32(cdatalen); + ri.dsize = cpu_to_je32(datalen); ri.compr = comprtype; - ri.node_crc = crc32(0, &ri, sizeof(ri)-8); - ri.data_crc = crc32(0, writebuf, cdatalen); + ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); + ri.data_crc = cpu_to_je32(crc32(0, writebuf, cdatalen)); new_fn = jffs2_write_dnode(c, f, &ri, writebuf, cdatalen, phys_ofs, NULL); diff -Nru a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c --- a/fs/jffs2/nodelist.c Fri Nov 22 13:41:20 2002 +++ b/fs/jffs2/nodelist.c Fri Nov 22 13:41:20 2002 @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.c,v 1.47 2002/06/26 01:25:30 dwmw2 Exp $ + * $Id: nodelist.c,v 1.65 2002/11/12 09:50:13 dwmw2 Exp $ * */ @@ -15,6 +15,9 @@ #include #include #include +#include +#include +#include #include "nodelist.h" void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list) @@ -116,9 +119,9 @@ for (ref = f->inocache->nodes; ref && ref->next_in_ino; ref = ref->next_in_ino) { /* Work out whether it's a data node or a dirent node */ - if (ref->flash_offset & 1) { + if (ref_obsolete(ref)) { /* FIXME: On NAND flash we may need to read these */ - D1(printk(KERN_DEBUG "node at 0x%08x is obsoleted. Ignoring.\n", ref->flash_offset &~3)); + D1(printk(KERN_DEBUG "node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref))); continue; } /* We can hold a pointer to a non-obsolete node without the spinlock, @@ -126,9 +129,12 @@ they're in gets erased */ spin_unlock_bh(&c->erase_completion_lock); - err = jffs2_flash_read(c, (ref->flash_offset & ~3), min(ref->totlen, sizeof(node)), &retlen, (void *)&node); + cond_resched(); + + /* FIXME: point() */ + err = jffs2_flash_read(c, (ref_offset(ref)), min(ref->totlen, sizeof(node)), &retlen, (void *)&node); if (err) { - printk(KERN_WARNING "error %d reading node at 0x%08x in get_inode_nodes()\n", err, (ref->flash_offset) & ~3); + printk(KERN_WARNING "error %d reading node at 0x%08x in get_inode_nodes()\n", err, ref_offset(ref)); goto free_out; } @@ -140,20 +146,24 @@ goto free_out; } - switch (node.u.nodetype) { + switch (je16_to_cpu(node.u.nodetype)) { case JFFS2_NODETYPE_DIRENT: - D1(printk(KERN_DEBUG "Node at %08x is a dirent node\n", ref->flash_offset &~3)); + D1(printk(KERN_DEBUG "Node at %08x (%d) is a dirent node\n", ref_offset(ref), ref_flags(ref))); + if (ref_flags(ref) == REF_UNCHECKED) { + printk(KERN_WARNING "BUG: Dirent node at 0x%08x never got checked? How?\n", ref_offset(ref)); + BUG(); + } if (retlen < sizeof(node.d)) { printk(KERN_WARNING "short read in get_inode_nodes()\n"); err = -EIO; goto free_out; } - if (node.d.version > *highest_version) - *highest_version = node.d.version; - if (ref->flash_offset & 1) { + if (je32_to_cpu(node.d.version) > *highest_version) + *highest_version = je32_to_cpu(node.d.version); + if (ref_obsolete(ref)) { /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ printk(KERN_ERR "Dirent node at 0x%08x became obsolete while we weren't looking\n", - ref->flash_offset & ~3); + ref_offset(ref)); BUG(); } fd = jffs2_alloc_full_dirent(node.d.nsize+1); @@ -163,14 +173,14 @@ } memset(fd,0,sizeof(struct jffs2_full_dirent) + node.d.nsize+1); fd->raw = ref; - fd->version = node.d.version; - fd->ino = node.d.ino; + fd->version = je32_to_cpu(node.d.version); + fd->ino = je32_to_cpu(node.d.ino); fd->type = node.d.type; /* Pick out the mctime of the latest dirent */ if(fd->version > *mctime_ver) { *mctime_ver = fd->version; - *latest_mctime = node.d.mctime; + *latest_mctime = je32_to_cpu(node.d.mctime); } /* memcpy as much of the name as possible from the raw @@ -183,9 +193,10 @@ from the flash? */ if (node.d.nsize + sizeof(struct jffs2_raw_dirent) > retlen) { + /* FIXME: point() */ int already = retlen - sizeof(struct jffs2_raw_dirent); - err = jffs2_flash_read(c, (ref->flash_offset & ~3) + retlen, + err = jffs2_flash_read(c, (ref_offset(ref)) + retlen, node.d.nsize - already, &retlen, &fd->name[already]); if (!err && retlen != node.d.nsize - already) err = -EIO; @@ -206,22 +217,75 @@ break; case JFFS2_NODETYPE_INODE: - D1(printk(KERN_DEBUG "Node at %08x is a data node\n", ref->flash_offset &~3)); + D1(printk(KERN_DEBUG "Node at %08x (%d) is a data node\n", ref_offset(ref), ref_flags(ref))); if (retlen < sizeof(node.i)) { printk(KERN_WARNING "read too short for dnode\n"); err = -EIO; goto free_out; } - if (node.d.version > *highest_version) - *highest_version = node.i.version; - D1(printk(KERN_DEBUG "version %d, highest_version now %d\n", node.d.version, *highest_version)); + if (je32_to_cpu(node.i.version) > *highest_version) + *highest_version = je32_to_cpu(node.i.version); + D1(printk(KERN_DEBUG "version %d, highest_version now %d\n", je32_to_cpu(node.i.version), *highest_version)); - if (ref->flash_offset & 1) { + if (ref_obsolete(ref)) { /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ printk(KERN_ERR "Inode node at 0x%08x became obsolete while we weren't looking\n", - ref->flash_offset & ~3); + ref_offset(ref)); BUG(); } + + /* If we've never checked the CRCs on this node, check them now. */ + if (ref_flags(ref) == REF_UNCHECKED) { + uint32_t crc; + struct jffs2_eraseblock *jeb; + + crc = crc32(0, &node, sizeof(node.i)-8); + if (crc != je32_to_cpu(node.i.node_crc)) { + printk(KERN_NOTICE "jffs2_get_inode_nodes(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", + ref_offset(ref), je32_to_cpu(node.i.node_crc), crc); + jffs2_mark_node_obsolete(c, ref); + spin_lock_bh(&c->erase_completion_lock); + continue; + } + + if (node.i.compr != JFFS2_COMPR_ZERO && je32_to_cpu(node.i.csize)) { + /* FIXME: point() */ + char *buf = kmalloc(je32_to_cpu(node.i.csize), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + err = jffs2_flash_read(c, ref_offset(ref) + sizeof(node.i), je32_to_cpu(node.i.csize), + &retlen, buf); + if (!err && retlen != je32_to_cpu(node.i.csize)) + err = -EIO; + if (err) { + kfree(buf); + return err; + } + + crc = crc32(0, buf, je32_to_cpu(node.i.csize)); + kfree(buf); + + if (crc != je32_to_cpu(node.i.data_crc)) { + printk(KERN_NOTICE "jffs2_get_inode_nodes(): Data CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", + ref_offset(ref), je32_to_cpu(node.i.data_crc), crc); + jffs2_mark_node_obsolete(c, ref); + spin_lock_bh(&c->erase_completion_lock); + continue; + } + + } + + /* Mark the node as having been checked and fix the accounting accordingly */ + jeb = &c->blocks[ref->flash_offset / c->sector_size]; + jeb->used_size += ref->totlen; + jeb->unchecked_size -= ref->totlen; + c->used_size += ref->totlen; + c->unchecked_size -= ref->totlen; + + mark_ref_normal(ref); + } + tn = jffs2_alloc_tmp_dnode_info(); if (!tn) { D1(printk(KERN_DEBUG "alloc tn failed\n")); @@ -236,34 +300,66 @@ jffs2_free_tmp_dnode_info(tn); goto free_out; } - tn->version = node.i.version; - tn->fn->ofs = node.i.offset; + tn->version = je32_to_cpu(node.i.version); + tn->fn->ofs = je32_to_cpu(node.i.offset); /* There was a bug where we wrote hole nodes out with csize/dsize swapped. Deal with it */ - if (node.i.compr == JFFS2_COMPR_ZERO && !node.i.dsize && node.i.csize) - tn->fn->size = node.i.csize; + if (node.i.compr == JFFS2_COMPR_ZERO && !je32_to_cpu(node.i.dsize) && je32_to_cpu(node.i.csize)) + tn->fn->size = je32_to_cpu(node.i.csize); else // normal case... - tn->fn->size = node.i.dsize; + tn->fn->size = je32_to_cpu(node.i.dsize); tn->fn->raw = ref; - D1(printk(KERN_DEBUG "dnode @%08x: ver %u, offset %04x, dsize %04x\n", ref->flash_offset &~3, node.i.version, node.i.offset, node.i.dsize)); + D1(printk(KERN_DEBUG "dnode @%08x: ver %u, offset %04x, dsize %04x\n", + ref_offset(ref), je32_to_cpu(node.i.version), + je32_to_cpu(node.i.offset), je32_to_cpu(node.i.dsize))); jffs2_add_tn_to_list(tn, &ret_tn); break; default: - switch(node.u.nodetype & JFFS2_COMPAT_MASK) { + if (ref_flags(ref) == REF_UNCHECKED) { + struct jffs2_eraseblock *jeb; + + printk(KERN_ERR "Eep. Unknown node type %04x at %08x was marked REF_UNCHECKED\n", + je16_to_cpu(node.u.nodetype), ref_offset(ref)); + + /* Mark the node as having been checked and fix the accounting accordingly */ + jeb = &c->blocks[ref->flash_offset / c->sector_size]; + jeb->used_size += ref->totlen; + jeb->unchecked_size -= ref->totlen; + c->used_size += ref->totlen; + c->unchecked_size -= ref->totlen; + + mark_ref_normal(ref); + } + node.u.nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(node.u.nodetype)); + if (crc32(0, &node, sizeof(struct jffs2_unknown_node)-4) != je32_to_cpu(node.u.hdr_crc)) { + /* Hmmm. This should have been caught at scan time. */ + printk(KERN_ERR "Node header CRC failed at %08x. But it must have been OK earlier.\n", + ref_offset(ref)); + printk(KERN_ERR "Node was: { %04x, %04x, %08x, %08x }\n", + je16_to_cpu(node.u.magic), je16_to_cpu(node.u.nodetype), je32_to_cpu(node.u.totlen), + je32_to_cpu(node.u.hdr_crc)); + jffs2_mark_node_obsolete(c, ref); + } else switch(je16_to_cpu(node.u.nodetype) & JFFS2_COMPAT_MASK) { case JFFS2_FEATURE_INCOMPAT: - printk(KERN_NOTICE "Unknown INCOMPAT nodetype %04X at %08X\n", node.u.nodetype, ref->flash_offset & ~3); + printk(KERN_NOTICE "Unknown INCOMPAT nodetype %04X at %08x\n", je16_to_cpu(node.u.nodetype), ref_offset(ref)); + /* EEP */ + BUG(); break; case JFFS2_FEATURE_ROCOMPAT: - printk(KERN_NOTICE "Unknown ROCOMPAT nodetype %04X at %08X\n", node.u.nodetype, ref->flash_offset & ~3); + printk(KERN_NOTICE "Unknown ROCOMPAT nodetype %04X at %08x\n", je16_to_cpu(node.u.nodetype), ref_offset(ref)); + if (!(c->flags & JFFS2_SB_FLAG_RO)) + BUG(); break; case JFFS2_FEATURE_RWCOMPAT_COPY: - printk(KERN_NOTICE "Unknown RWCOMPAT_COPY nodetype %04X at %08X\n", node.u.nodetype, ref->flash_offset & ~3); + printk(KERN_NOTICE "Unknown RWCOMPAT_COPY nodetype %04X at %08x\n", je16_to_cpu(node.u.nodetype), ref_offset(ref)); break; case JFFS2_FEATURE_RWCOMPAT_DELETE: - printk(KERN_NOTICE "Unknown RWCOMPAT_DELETE nodetype %04X at %08X\n", node.u.nodetype, ref->flash_offset & ~3); + printk(KERN_NOTICE "Unknown RWCOMPAT_DELETE nodetype %04X at %08x\n", je16_to_cpu(node.u.nodetype), ref_offset(ref)); + jffs2_mark_node_obsolete(c, ref); break; } + } spin_lock_bh(&c->erase_completion_lock); @@ -369,3 +465,126 @@ } } +struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_t offset) +{ + /* The common case in lookup is that there will be a node + which precisely matches. So we go looking for that first */ + struct rb_node *next; + struct jffs2_node_frag *prev = NULL; + struct jffs2_node_frag *frag = NULL; + + D2(printk(KERN_DEBUG "jffs2_lookup_node_frag(%p, %d)\n", fragtree, offset)); + + next = fragtree->rb_node; + + while(next) { + frag = rb_entry(next, struct jffs2_node_frag, rb); + + D2(printk(KERN_DEBUG "Considering frag %d-%d (%p). left %p, right %p\n", + frag->ofs, frag->ofs+frag->size, frag, frag->rb.rb_left, frag->rb.rb_right)); + if (frag->ofs + frag->size <= offset) { + D2(printk(KERN_DEBUG "Going right from frag %d-%d, before the region we care about\n", + frag->ofs, frag->ofs+frag->size)); + /* Remember the closest smaller match on the way down */ + if (!prev || frag->ofs > prev->ofs) + prev = frag; + next = frag->rb.rb_right; + } else if (frag->ofs > offset) { + D2(printk(KERN_DEBUG "Going left from frag %d-%d, after the region we care about\n", + frag->ofs, frag->ofs+frag->size)); + next = frag->rb.rb_left; + } else { + D2(printk(KERN_DEBUG "Returning frag %d,%d, matched\n", + frag->ofs, frag->ofs+frag->size)); + return frag; + } + } + + /* Exact match not found. Go back up looking at each parent, + and return the closest smaller one */ + + if (prev) + D2(printk(KERN_DEBUG "No match. Returning frag %d,%d, closest previous\n", + prev->ofs, prev->ofs+prev->size)); + else + D2(printk(KERN_DEBUG "Returning NULL, empty fragtree\n")); + + return prev; +} + +/* Pass 'c' argument to indicate that nodes should be marked obsolete as + they're killed. */ +void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c) +{ + struct jffs2_node_frag *frag; + struct jffs2_node_frag *parent; + + if (!root->rb_node) + return; + + frag = (rb_entry(root->rb_node, struct jffs2_node_frag, rb)); + + while(frag) { + if (frag->rb.rb_left) { + D2(printk(KERN_DEBUG "Going left from frag (%p) %d-%d\n", + frag, frag->ofs, frag->ofs+frag->size)); + frag = frag_left(frag); + continue; + } + if (frag->rb.rb_right) { + D2(printk(KERN_DEBUG "Going right from frag (%p) %d-%d\n", + frag, frag->ofs, frag->ofs+frag->size)); + frag = frag_right(frag); + continue; + } + + D2(printk(KERN_DEBUG "jffs2_kill_fragtree: frag at 0x%x-0x%x: node %p, frags %d--\n", + frag->ofs, frag->ofs+frag->size, frag->node, + frag->node?frag->node->frags:0)); + + if (frag->node && !(--frag->node->frags)) { + /* Not a hole, and it's the final remaining frag + of this node. Free the node */ + if (c) + jffs2_mark_node_obsolete(c, frag->node->raw); + + jffs2_free_full_dnode(frag->node); + } + parent = frag_parent(frag); + if (parent) { + if (frag_left(parent) == frag) + parent->rb.rb_left = NULL; + else + parent->rb.rb_right = NULL; + } + + jffs2_free_node_frag(frag); + frag = parent; + } +} + +void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_node_frag *base) +{ + struct rb_node *parent = &base->rb; + struct rb_node **link = &parent; + + D2(printk(KERN_DEBUG "jffs2_fragtree_insert(%p; %d-%d, %p)\n", newfrag, + newfrag->ofs, newfrag->ofs+newfrag->size, base)); + + while (*link) { + parent = *link; + base = rb_entry(parent, struct jffs2_node_frag, rb); + + D2(printk(KERN_DEBUG "fragtree_insert considering frag at 0x%x\n", base->ofs)); + if (newfrag->ofs > base->ofs) + link = &base->rb.rb_right; + else if (newfrag->ofs < base->ofs) + link = &base->rb.rb_left; + else { + printk(KERN_CRIT "Duplicate frag at %08x (%p,%p)\n", newfrag->ofs, newfrag, base); + BUG(); + } + } + + rb_link_node(&newfrag->rb, &base->rb, link); +} diff -Nru a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h --- a/fs/jffs2/nodelist.h Fri Nov 22 13:41:23 2002 +++ b/fs/jffs2/nodelist.h Fri Nov 22 13:41:23 2002 @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.h,v 1.74 2002/06/26 01:20:43 dwmw2 Exp $ + * $Id: nodelist.h,v 1.87 2002/11/12 13:36:18 dwmw2 Exp $ * */ @@ -53,16 +53,22 @@ for this inode instead. The inode_cache will have NULL in the first word so you know when you've got there :) */ struct jffs2_raw_node_ref *next_phys; - // uint32_t ino; uint32_t flash_offset; uint32_t totlen; -// uint16_t nodetype; /* flash_offset & 3 always has to be zero, because nodes are always aligned at 4 bytes. So we have a couple of extra bits to play with. So we set the least significant bit to 1 to signify that the node is obsoleted by later nodes. */ +#define REF_UNCHECKED 0 /* We haven't yet checked the CRC or built its inode */ +#define REF_OBSOLETE 1 /* Obsolete, can be completely ignored */ +#define REF_PRISTINE 2 /* Completely clean. GC without looking */ +#define REF_NORMAL 3 /* Possibly overlapped. Read the page and write again on GC */ +#define ref_flags(ref) ((ref)->flash_offset & 3) +#define ref_offset(ref) ((ref)->flash_offset & ~3) +#define ref_obsolete(ref) (((ref)->flash_offset & 3) == REF_OBSOLETE) +#define mark_ref_normal(ref) do { (ref)->flash_offset = ref_offset(ref) | REF_NORMAL; } while(0) }; /* @@ -83,14 +89,20 @@ a pointer to the first physical node which is part of this inode, too. */ struct jffs2_inode_cache { - struct jffs2_scan_info *scan; /* Used during scan to hold - temporary lists of nodes, and later must be set to + struct jffs2_full_dirent *scan_dents; /* Used during scan to hold + temporary lists of dirents, and later must be set to NULL to mark the end of the raw_node_ref->next_in_ino chain. */ struct jffs2_inode_cache *next; struct jffs2_raw_node_ref *nodes; uint32_t ino; int nlink; + int state; +#define INO_STATE_UNCHECKED 0 +#define INO_STATE_CHECKING 1 +#define INO_STATE_CHECKEDABSENT 2 +#define INO_STATE_READINGINODE 3 +#define INO_STATE_PRESENT 5 }; #define INOCACHE_HASHSIZE 128 @@ -146,7 +158,7 @@ */ struct jffs2_node_frag { - struct jffs2_node_frag *next; + struct rb_node rb; struct jffs2_full_dnode *node; /* NULL for holes */ uint32_t size; uint32_t ofs; /* Don't really need this, but optimisation */ @@ -158,8 +170,10 @@ int bad_count; uint32_t offset; /* of this block in the MTD */ + uint32_t unchecked_size; uint32_t used_size; uint32_t dirty_size; + uint32_t wasted_size; uint32_t free_size; /* Note that sector_size - free_size is the address of the first free space */ struct jffs2_raw_node_ref *first_node; @@ -177,25 +191,28 @@ }; #define ACCT_SANITY_CHECK(c, jeb) do { \ - if (jeb->used_size + jeb->dirty_size + jeb->free_size != c->sector_size) { \ + if (jeb->used_size + jeb->dirty_size + jeb->free_size + jeb->wasted_size + jeb->unchecked_size != c->sector_size) { \ printk(KERN_NOTICE "Eeep. Space accounting for block at 0x%08x is screwed\n", jeb->offset); \ - printk(KERN_NOTICE "free 0x%08x + dirty 0x%08x + used %08x != total %08x\n", \ - jeb->free_size, jeb->dirty_size, jeb->used_size, c->sector_size); \ + printk(KERN_NOTICE "free 0x%08x + dirty 0x%08x + used %08x + wasted %08x + unchecked %08x != total %08x\n", \ + jeb->free_size, jeb->dirty_size, jeb->used_size, jeb->wasted_size, jeb->unchecked_size, c->sector_size); \ BUG(); \ } \ - if (c->used_size + c->dirty_size + c->free_size + c->erasing_size + c->bad_size != c->flash_size) { \ + if (c->used_size + c->dirty_size + c->free_size + c->erasing_size + c->bad_size + c->wasted_size + c->unchecked_size != c->flash_size) { \ printk(KERN_NOTICE "Eeep. Space accounting superblock info is screwed\n"); \ - printk(KERN_NOTICE "free 0x%08x + dirty 0x%08x + used %08x + erasing %08x + bad %08x != total %08x\n", \ - c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size, c->flash_size); \ + printk(KERN_NOTICE "free 0x%08x + dirty 0x%08x + used %08x + erasing %08x + bad %08x + wasted %08x + unchecked %08x != total %08x\n", \ + c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size, c->wasted_size, c->unchecked_size, c->flash_size); \ BUG(); \ } \ } while(0) #define ACCT_PARANOIA_CHECK(jeb) do { \ uint32_t my_used_size = 0; \ + uint32_t my_unchecked_size = 0; \ struct jffs2_raw_node_ref *ref2 = jeb->first_node; \ while (ref2) { \ - if (!(ref2->flash_offset & 1)) \ + if (ref_flags(ref2) == REF_UNCHECKED) \ + my_unchecked_size += ref2->totlen; \ + else if (!ref_obsolete(ref2)) \ my_used_size += ref2->totlen; \ ref2 = ref2->next_phys; \ } \ @@ -203,6 +220,10 @@ printk(KERN_NOTICE "Calculated used size %08x != stored used size %08x\n", my_used_size, jeb->used_size); \ BUG(); \ } \ + if (my_unchecked_size != jeb->unchecked_size) { \ + printk(KERN_NOTICE "Calculated unchecked size %08x != stored unchecked size %08x\n", my_unchecked_size, jeb->unchecked_size); \ + BUG(); \ + } \ } while(0) #define ALLOC_NORMAL 0 /* Normal allocation */ @@ -211,7 +232,7 @@ #define JFFS2_RESERVED_BLOCKS_BASE 3 /* Number of free blocks there must be before we... */ #define JFFS2_RESERVED_BLOCKS_WRITE (JFFS2_RESERVED_BLOCKS_BASE + 2) /* ... allow a normal filesystem write */ -#define JFFS2_RESERVED_BLOCKS_DELETION (JFFS2_RESERVED_BLOCKS_BASE + 1) /* ... allow a normal filesystem deletion */ +#define JFFS2_RESERVED_BLOCKS_DELETION (JFFS2_RESERVED_BLOCKS_BASE) /* ... allow a normal filesystem deletion */ #define JFFS2_RESERVED_BLOCKS_GCTRIGGER (JFFS2_RESERVED_BLOCKS_BASE + 3) /* ... wake up the GC thread */ #define JFFS2_RESERVED_BLOCKS_GCBAD (JFFS2_RESERVED_BLOCKS_BASE + 1) /* ... pick a block from the bad_list to GC */ #define JFFS2_RESERVED_BLOCKS_GCMERGE (JFFS2_RESERVED_BLOCKS_BASE) /* ... merge pages when garbage collecting */ @@ -220,6 +241,9 @@ /* How much dirty space before it goes on the very_dirty_list */ #define VERYDIRTY(c, size) ((size) >= ((c)->sector_size / 2)) +/* check if dirty space is more than 255 Byte */ +#define ISDIRTY(size) ((size) > sizeof (struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN) + #define PAD(x) (((x)+3)&~3) static inline int jffs2_raw_ref_to_inum(struct jffs2_raw_node_ref *raw) @@ -231,6 +255,24 @@ return ((struct jffs2_inode_cache *)raw)->ino; } +static inline struct jffs2_node_frag *frag_first(struct rb_root *root) +{ + struct rb_node *node = root->rb_node; + + if (!node) + return NULL; + while(node->rb_left) + node = node->rb_left; + return rb_entry(node, struct jffs2_node_frag, rb); +} +#define rb_parent(rb) ((rb)->rb_parent) +#define frag_next(frag) rb_entry(rb_next(&(frag)->rb), struct jffs2_node_frag, rb) +#define frag_prev(frag) rb_entry(rb_prev(&(frag)->rb), struct jffs2_node_frag, rb) +#define frag_parent(frag) rb_entry(rb_parent(&(frag)->rb), struct jffs2_node_frag, rb) +#define frag_left(frag) rb_entry((frag)->rb.rb_left, struct jffs2_node_frag, rb) +#define frag_right(frag) rb_entry((frag)->rb.rb_right, struct jffs2_node_frag, rb) +#define frag_erase(frag, list) rb_erase(&frag->rb, list); + /* nodelist.c */ D1(void jffs2_print_frag_list(struct jffs2_inode_info *f)); void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list); @@ -244,11 +286,17 @@ void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old); void jffs2_free_ino_caches(struct jffs2_sb_info *c); void jffs2_free_raw_node_refs(struct jffs2_sb_info *c); +struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_t offset); +void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c_delete); +void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_node_frag *base); +struct rb_node *rb_next(struct rb_node *); +struct rb_node *rb_prev(struct rb_node *); +void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root); /* nodemgmt.c */ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, int prio); int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len); -int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new, uint32_t len, int dirty); +int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new); void jffs2_complete_reservation(struct jffs2_sb_info *c); void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw); void jffs2_dump_block_lists(struct jffs2_sb_info *c); @@ -266,8 +314,8 @@ /* readinode.c */ -void jffs2_truncate_fraglist (struct jffs2_sb_info *c, struct jffs2_node_frag **list, uint32_t size); -int jffs2_add_full_dnode_to_fraglist(struct jffs2_sb_info *c, struct jffs2_node_frag **list, struct jffs2_full_dnode *fn); +void jffs2_truncate_fraglist (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); +int jffs2_add_full_dnode_to_fraglist(struct jffs2_sb_info *c, struct rb_root *list, struct jffs2_full_dnode *fn); int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t ino, struct jffs2_raw_inode *latest_node); @@ -320,7 +368,6 @@ /* erase.c */ void jffs2_erase_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); void jffs2_erase_pending_blocks(struct jffs2_sb_info *c); -void jffs2_mark_erased_blocks(struct jffs2_sb_info *c); void jffs2_erase_pending_trigger(struct jffs2_sb_info *c); #ifdef CONFIG_JFFS2_FS_NAND diff -Nru a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c --- a/fs/jffs2/nodemgmt.c Fri Nov 22 13:41:18 2002 +++ b/fs/jffs2/nodemgmt.c Fri Nov 22 13:41:18 2002 @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodemgmt.c,v 1.70 2002/07/02 22:48:24 dwmw2 Exp $ + * $Id: nodemgmt.c,v 1.84 2002/11/12 11:17:29 dwmw2 Exp $ * */ @@ -62,14 +62,17 @@ int ret; up(&c->alloc_sem); - if (c->dirty_size < c->sector_size) { - D1(printk(KERN_DEBUG "Short on space, but total dirty size 0x%08x < sector size 0x%08x, so -ENOSPC\n", c->dirty_size, c->sector_size)); + + if (c->dirty_size + c->unchecked_size < c->sector_size) { + D1(printk(KERN_DEBUG "dirty size 0x%08x + unchecked_size 0x%08x < sector size 0x%08x, returning -ENOSPC\n", + c->dirty_size, c->unchecked_size, c->sector_size)); spin_unlock_bh(&c->erase_completion_lock); return -ENOSPC; } - D1(printk(KERN_DEBUG "Triggering GC pass. nr_free_blocks %d, nr_erasing_blocks %d, free_size 0x%08x, dirty_size 0x%08x, used_size 0x%08x, erasing_size 0x%08x, bad_size 0x%08x (total 0x%08x of 0x%08x)\n", - c->nr_free_blocks, c->nr_erasing_blocks, c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size, - c->free_size + c->dirty_size + c->used_size + c->erasing_size + c->bad_size, c->flash_size)); + + D1(printk(KERN_DEBUG "Triggering GC pass. nr_free_blocks %d, nr_erasing_blocks %d, free_size 0x%08x, dirty_size 0x%08x, wasted_size 0x%08x, used_size 0x%08x, erasing_size 0x%08x, bad_size 0x%08x (total 0x%08x of 0x%08x)\n", + c->nr_free_blocks, c->nr_erasing_blocks, c->free_size, c->dirty_size, c->wasted_size, c->used_size, c->erasing_size, c->bad_size, + c->free_size + c->dirty_size + c->wasted_size + c->used_size + c->erasing_size + c->bad_size, c->flash_size)); spin_unlock_bh(&c->erase_completion_lock); ret = jffs2_garbage_collect_pass(c); @@ -130,18 +133,30 @@ spin_lock_bh(&c->erase_completion_lock); /* We know nobody's going to have changed nextblock. Just continue */ } - c->dirty_size += jeb->free_size; + c->wasted_size += jeb->free_size; c->free_size -= jeb->free_size; - jeb->dirty_size += jeb->free_size; + jeb->wasted_size += jeb->free_size; jeb->free_size = 0; - if (VERYDIRTY(c, jeb->dirty_size)) { - D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to very_dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", - jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); - list_add_tail(&jeb->list, &c->very_dirty_list); - } else { - D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", + + /* Check, if we have a dirty block now, or if it was dirty already */ + if (ISDIRTY (jeb->wasted_size + jeb->dirty_size)) { + c->dirty_size += jeb->wasted_size; + c->wasted_size -= jeb->wasted_size; + jeb->dirty_size += jeb->wasted_size; + jeb->wasted_size = 0; + if (VERYDIRTY(c, jeb->dirty_size)) { + D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to very_dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", + jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); + list_add_tail(&jeb->list, &c->very_dirty_list); + } else { + D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", + jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); + list_add_tail(&jeb->list, &c->dirty_list); + } + } else { + D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to clean_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); - list_add_tail(&jeb->list, &c->dirty_list); + list_add_tail(&jeb->list, &c->clean_list); } c->nextblock = jeb = NULL; } @@ -225,7 +240,7 @@ *ofs = jeb->offset + (c->sector_size - jeb->free_size); *len = jeb->free_size; - if (jeb->used_size == PAD(sizeof(struct jffs2_unknown_node)) && + if (c->cleanmarker_size && jeb->used_size == c->cleanmarker_size && !jeb->first_node->next_in_ino) { /* Only node in it beforehand was a CLEANMARKER node (we think). So mark it obsolete now that there's going to be another node @@ -255,15 +270,15 @@ * Must be called with the alloc_sem held. */ -int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new, uint32_t len, int dirty) +int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new) { struct jffs2_eraseblock *jeb; + uint32_t len = new->totlen; - len = PAD(len); jeb = &c->blocks[new->flash_offset / c->sector_size]; - D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x, size 0x%x\n", new->flash_offset & ~3, len)); + D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x, size 0x%x\n", ref_offset(new), len)); #if 1 - if (jeb != c->nextblock || (new->flash_offset & ~3) != jeb->offset + (c->sector_size - jeb->free_size)) { + if (jeb != c->nextblock || (ref_offset(new)) != jeb->offset + (c->sector_size - jeb->free_size)) { printk(KERN_WARNING "argh. node added in wrong place\n"); jffs2_free_raw_node_ref(new); return -EINVAL; @@ -279,8 +294,7 @@ jeb->free_size -= len; c->free_size -= len; - if (dirty) { - new->flash_offset |= 1; + if (ref_obsolete(new)) { jeb->dirty_size += len; c->dirty_size += len; } else { @@ -303,7 +317,7 @@ c->nextblock = NULL; } ACCT_SANITY_CHECK(c,jeb); - ACCT_PARANOIA_CHECK(jeb); + D1(ACCT_PARANOIA_CHECK(jeb)); spin_unlock_bh(&c->erase_completion_lock); @@ -330,8 +344,8 @@ printk(KERN_NOTICE "EEEEEK. jffs2_mark_node_obsolete called with NULL node\n"); return; } - if (ref->flash_offset & 1) { - D1(printk(KERN_DEBUG "jffs2_mark_node_obsolete called with already obsolete node at 0x%08x\n", ref->flash_offset &~3)); + if (ref_obsolete(ref)) { + D1(printk(KERN_DEBUG "jffs2_mark_node_obsolete called with already obsolete node at 0x%08x\n", ref_offset(ref))); return; } blocknr = ref->flash_offset / c->sector_size; @@ -340,22 +354,45 @@ BUG(); } jeb = &c->blocks[blocknr]; - if (jeb->used_size < ref->totlen) { - printk(KERN_NOTICE "raw node of size 0x%08x freed from erase block %d at 0x%08x, but used_size was already 0x%08x\n", - ref->totlen, blocknr, ref->flash_offset, jeb->used_size); - BUG(); - } spin_lock_bh(&c->erase_completion_lock); - jeb->used_size -= ref->totlen; - jeb->dirty_size += ref->totlen; - c->used_size -= ref->totlen; - c->dirty_size += ref->totlen; - ref->flash_offset |= 1; + + if (ref_flags(ref) == REF_UNCHECKED) { + D1(if (unlikely(jeb->unchecked_size < ref->totlen)) { + printk(KERN_NOTICE "raw unchecked node of size 0x%08x freed from erase block %d at 0x%08x, but unchecked_size was already 0x%08x\n", + ref->totlen, blocknr, ref->flash_offset, jeb->used_size); + BUG(); + }) + D1(printk(KERN_DEBUG "Obsoleting previously unchecked node at 0x%08x of len %x: ", ref_offset(ref), ref->totlen)); + jeb->unchecked_size -= ref->totlen; + c->unchecked_size -= ref->totlen; + } else { + D1(if (unlikely(jeb->used_size < ref->totlen)) { + printk(KERN_NOTICE "raw node of size 0x%08x freed from erase block %d at 0x%08x, but used_size was already 0x%08x\n", + ref->totlen, blocknr, ref->flash_offset, jeb->used_size); + BUG(); + }) + D1(printk(KERN_DEBUG "Obsoleting node at 0x%08x of len %x: ", ref_offset(ref), ref->totlen)); + jeb->used_size -= ref->totlen; + c->used_size -= ref->totlen; + } + + if ((jeb->dirty_size || ISDIRTY(jeb->wasted_size + ref->totlen)) && jeb != c->nextblock) { + D1(printk("Dirtying\n")); + jeb->dirty_size += ref->totlen + jeb->wasted_size; + c->dirty_size += ref->totlen + jeb->wasted_size; + c->wasted_size -= jeb->wasted_size; + jeb->wasted_size = 0; + } else { + D1(printk("Wasting\n")); + jeb->wasted_size += ref->totlen; + c->wasted_size += ref->totlen; + } + ref->flash_offset = ref_offset(ref) | REF_OBSOLETE; ACCT_SANITY_CHECK(c, jeb); - ACCT_PARANOIA_CHECK(jeb); + D1(ACCT_PARANOIA_CHECK(jeb)); if (c->flags & JFFS2_SB_FLAG_MOUNTING) { /* Mount in progress. Don't muck about with the block @@ -369,7 +406,7 @@ if (jeb == c->nextblock) { D2(printk(KERN_DEBUG "Not moving nextblock 0x%08x to dirty/erase_pending list\n", jeb->offset)); - } else if (!jeb->used_size) { + } else if (!jeb->used_size && !jeb->unchecked_size) { if (jeb == c->gcblock) { D1(printk(KERN_DEBUG "gcblock at 0x%08x completely dirtied. Clearing gcblock...\n", jeb->offset)); c->gcblock = NULL; @@ -417,7 +454,7 @@ D1(printk(KERN_DEBUG "Done OK\n")); } else if (jeb == c->gcblock) { D2(printk(KERN_DEBUG "Not moving gcblock 0x%08x to dirty_list\n", jeb->offset)); - } else if (jeb->dirty_size == ref->totlen) { + } else if (ISDIRTY(jeb->dirty_size) && !ISDIRTY(jeb->dirty_size - ref->totlen)) { D1(printk(KERN_DEBUG "Eraseblock at 0x%08x is freshly dirtied. Removing from clean list...\n", jeb->offset)); list_del(&jeb->list); D1(printk(KERN_DEBUG "...and adding to dirty_list\n")); @@ -428,7 +465,10 @@ list_del(&jeb->list); D1(printk(KERN_DEBUG "...and adding to very_dirty_list\n")); list_add_tail(&jeb->list, &c->very_dirty_list); - } + } else { + D1(printk(KERN_DEBUG "Eraseblock at 0x%08x not moved anywhere. (free 0x%08x, dirty 0x%08x, used 0x%08x)\n", + jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); + } spin_unlock_bh(&c->erase_completion_lock); @@ -437,32 +477,33 @@ if (jffs2_is_readonly(c)) return; - D1(printk(KERN_DEBUG "obliterating obsoleted node at 0x%08x\n", ref->flash_offset &~3)); - ret = jffs2_flash_read(c, ref->flash_offset &~3, sizeof(n), &retlen, (char *)&n); + D1(printk(KERN_DEBUG "obliterating obsoleted node at 0x%08x\n", ref_offset(ref))); + ret = jffs2_flash_read(c, ref_offset(ref), sizeof(n), &retlen, (char *)&n); if (ret) { - printk(KERN_WARNING "Read error reading from obsoleted node at 0x%08x: %d\n", ref->flash_offset &~3, ret); + printk(KERN_WARNING "Read error reading from obsoleted node at 0x%08x: %d\n", ref_offset(ref), ret); return; } if (retlen != sizeof(n)) { - printk(KERN_WARNING "Short read from obsoleted node at 0x%08x: %d\n", ref->flash_offset &~3, retlen); + printk(KERN_WARNING "Short read from obsoleted node at 0x%08x: %d\n", ref_offset(ref), retlen); return; } - if (PAD(n.totlen) != PAD(ref->totlen)) { - printk(KERN_WARNING "Node totlen on flash (0x%08x) != totlen in node ref (0x%08x)\n", n.totlen, ref->totlen); + if (PAD(je32_to_cpu(n.totlen)) != PAD(ref->totlen)) { + printk(KERN_WARNING "Node totlen on flash (0x%08x) != totlen in node ref (0x%08x)\n", je32_to_cpu(n.totlen), ref->totlen); return; } - if (!(n.nodetype & JFFS2_NODE_ACCURATE)) { - D1(printk(KERN_DEBUG "Node at 0x%08x was already marked obsolete (nodetype 0x%04x\n", ref->flash_offset &~3, n.nodetype)); + if (!(je16_to_cpu(n.nodetype) & JFFS2_NODE_ACCURATE)) { + D1(printk(KERN_DEBUG "Node at 0x%08x was already marked obsolete (nodetype 0x%04x\n", ref_offset(ref), je16_to_cpu(n.nodetype))); return; } - n.nodetype &= ~JFFS2_NODE_ACCURATE; - ret = jffs2_flash_write(c, ref->flash_offset&~3, sizeof(n), &retlen, (char *)&n); + /* XXX FIXME: This is ugly now */ + n.nodetype = cpu_to_je16(je16_to_cpu(n.nodetype) & ~JFFS2_NODE_ACCURATE); + ret = jffs2_flash_write(c, ref_offset(ref), sizeof(n), &retlen, (char *)&n); if (ret) { - printk(KERN_WARNING "Write error in obliterating obsoleted node at 0x%08x: %d\n", ref->flash_offset &~3, ret); + printk(KERN_WARNING "Write error in obliterating obsoleted node at 0x%08x: %d\n", ref_offset(ref), ret); return; } if (retlen != sizeof(n)) { - printk(KERN_WARNING "Short write in obliterating obsoleted node at 0x%08x: %d\n", ref->flash_offset &~3, retlen); + printk(KERN_WARNING "Short write in obliterating obsoleted node at 0x%08x: %d\n", ref_offset(ref), retlen); return; } } @@ -470,10 +511,14 @@ #if CONFIG_JFFS2_FS_DEBUG > 0 void jffs2_dump_block_lists(struct jffs2_sb_info *c) { + + printk(KERN_DEBUG "jffs2_dump_block_lists:\n"); printk(KERN_DEBUG "flash_size: %08x\n", c->flash_size); printk(KERN_DEBUG "used_size: %08x\n", c->used_size); printk(KERN_DEBUG "dirty_size: %08x\n", c->dirty_size); + printk(KERN_DEBUG "wasted_size: %08x\n", c->wasted_size); + printk(KERN_DEBUG "unchecked_size: %08x\n", c->unchecked_size); printk(KERN_DEBUG "free_size: %08x\n", c->free_size); printk(KERN_DEBUG "erasing_size: %08x\n", c->erasing_size); printk(KERN_DEBUG "bad_size: %08x\n", c->bad_size); @@ -481,12 +526,14 @@ printk(KERN_DEBUG "jffs2_reserved_blocks size: %08x\n",c->sector_size * JFFS2_RESERVED_BLOCKS_WRITE); if (c->nextblock) { - printk(KERN_DEBUG "nextblock: %08x (used %08x, dirty %08x, free %08x)\n", c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->free_size); + printk(KERN_DEBUG "nextblock: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", + c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->wasted_size, c->nextblock->unchecked_size, c->nextblock->free_size); } else { printk(KERN_DEBUG "nextblock: NULL\n"); } if (c->gcblock) { - printk(KERN_DEBUG "gcblock: %08x (used %08x, dirty %08x, free %08x)\n", c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size, c->gcblock->free_size); + printk(KERN_DEBUG "gcblock: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", + c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size, c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size); } else { printk(KERN_DEBUG "gcblock: NULL\n"); } @@ -494,31 +541,50 @@ printk(KERN_DEBUG "clean_list: empty\n"); } else { struct list_head *this; + int numblocks = 0; + uint32_t dirty = 0; list_for_each(this, &c->clean_list) { struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - printk(KERN_DEBUG "clean_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size); + numblocks ++; + dirty += jeb->wasted_size; + printk(KERN_DEBUG "clean_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); } + printk (KERN_DEBUG "Contains %d blocks with total wasted size %u, average wasted size: %u\n", numblocks, dirty, dirty / numblocks); } if (list_empty(&c->very_dirty_list)) { printk(KERN_DEBUG "very_dirty_list: empty\n"); } else { struct list_head *this; + int numblocks = 0; + uint32_t dirty = 0; list_for_each(this, &c->very_dirty_list) { struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - printk(KERN_DEBUG "very_dirty_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size); + numblocks ++; + dirty += jeb->dirty_size; + printk(KERN_DEBUG "very_dirty_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); } + printk (KERN_DEBUG "Contains %d blocks with total dirty size %u, average dirty size: %u\n", + numblocks, dirty, dirty / numblocks); } if (list_empty(&c->dirty_list)) { printk(KERN_DEBUG "dirty_list: empty\n"); } else { struct list_head *this; + int numblocks = 0; + uint32_t dirty = 0; list_for_each(this, &c->dirty_list) { struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - printk(KERN_DEBUG "dirty_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size); + numblocks ++; + dirty += jeb->dirty_size; + printk(KERN_DEBUG "dirty_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); } + printk (KERN_DEBUG "Contains %d blocks with total dirty size %u, average dirty size: %u\n", + numblocks, dirty, dirty / numblocks); } if (list_empty(&c->erasable_list)) { printk(KERN_DEBUG "erasable_list: empty\n"); @@ -527,7 +593,8 @@ list_for_each(this, &c->erasable_list) { struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - printk(KERN_DEBUG "erasable_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size); + printk(KERN_DEBUG "erasable_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); } } if (list_empty(&c->erasing_list)) { @@ -537,7 +604,8 @@ list_for_each(this, &c->erasing_list) { struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - printk(KERN_DEBUG "erasing_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size); + printk(KERN_DEBUG "erasing_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); } } if (list_empty(&c->erase_pending_list)) { @@ -547,7 +615,8 @@ list_for_each(this, &c->erase_pending_list) { struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - printk(KERN_DEBUG "erase_pending_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size); + printk(KERN_DEBUG "erase_pending_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); } } if (list_empty(&c->erasable_pending_wbuf_list)) { @@ -557,7 +626,8 @@ list_for_each(this, &c->erasable_pending_wbuf_list) { struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - printk(KERN_DEBUG "erase_pending_wbuf_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size); + printk(KERN_DEBUG "erase_pending_wbuf_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); } } if (list_empty(&c->free_list)) { @@ -567,7 +637,8 @@ list_for_each(this, &c->free_list) { struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - printk(KERN_DEBUG "free_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size); + printk(KERN_DEBUG "free_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); } } if (list_empty(&c->bad_list)) { @@ -577,7 +648,8 @@ list_for_each(this, &c->bad_list) { struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - printk(KERN_DEBUG "bad_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size); + printk(KERN_DEBUG "bad_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); } } if (list_empty(&c->bad_used_list)) { @@ -587,7 +659,8 @@ list_for_each(this, &c->bad_used_list) { struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - printk(KERN_DEBUG "bad_used_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size); + printk(KERN_DEBUG "bad_used_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); } } } diff -Nru a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h --- a/fs/jffs2/os-linux.h Fri Nov 22 13:41:18 2002 +++ b/fs/jffs2/os-linux.h Fri Nov 22 13:41:18 2002 @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: os-linux.h,v 1.19 2002/05/20 14:56:38 dwmw2 Exp $ + * $Id: os-linux.h,v 1.21 2002/11/12 09:44:30 dwmw2 Exp $ * */ @@ -49,11 +49,19 @@ #define JFFS2_F_I_RDEV_MAJ(f) (MAJOR(to_kdev_t(OFNI_EDONI_2SFFJ(f)->i_rdev))) #endif +/* Hmmm. P'raps generic code should only ever see versions of signal + functions which do the locking automatically? */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,40) +#define current_sig_lock current->sigmask_lock +#else +#define current_sig_lock current->sig->siglock +#endif + static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) { #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,2) f->highest_version = 0; - f->fraglist = NULL; + f->fragtree = RB_ROOT; f->metadata = NULL; f->dents = NULL; f->flags = 0; diff -Nru a/fs/jffs2/read.c b/fs/jffs2/read.c --- a/fs/jffs2/read.c Fri Nov 22 13:41:18 2002 +++ b/fs/jffs2/read.c Fri Nov 22 13:41:18 2002 @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: read.c,v 1.23 2002/05/20 14:56:38 dwmw2 Exp $ + * $Id: read.c,v 1.29 2002/11/12 09:51:22 dwmw2 Exp $ * */ @@ -31,35 +31,41 @@ if (!ri) return -ENOMEM; - ret = jffs2_flash_read(c, fd->raw->flash_offset & ~3, sizeof(*ri), &readlen, (char *)ri); + ret = jffs2_flash_read(c, ref_offset(fd->raw), sizeof(*ri), &readlen, (char *)ri); if (ret) { jffs2_free_raw_inode(ri); - printk(KERN_WARNING "Error reading node from 0x%08x: %d\n", fd->raw->flash_offset & ~3, ret); + printk(KERN_WARNING "Error reading node from 0x%08x: %d\n", ref_offset(fd->raw), ret); return ret; } if (readlen != sizeof(*ri)) { jffs2_free_raw_inode(ri); printk(KERN_WARNING "Short read from 0x%08x: wanted 0x%x bytes, got 0x%x\n", - fd->raw->flash_offset & ~3, sizeof(*ri), readlen); + ref_offset(fd->raw), sizeof(*ri), readlen); return -EIO; } crc = crc32(0, ri, sizeof(*ri)-8); - D1(printk(KERN_DEBUG "Node read from %08x: node_crc %08x, calculated CRC %08x. dsize %x, csize %x, offset %x, buf %p\n", fd->raw->flash_offset & ~3, ri->node_crc, crc, ri->dsize, ri->csize, ri->offset, buf)); - if (crc != ri->node_crc) { - printk(KERN_WARNING "Node CRC %08x != calculated CRC %08x for node at %08x\n", ri->node_crc, crc, fd->raw->flash_offset & ~3); + D1(printk(KERN_DEBUG "Node read from %08x: node_crc %08x, calculated CRC %08x. dsize %x, csize %x, offset %x, buf %p\n", + ref_offset(fd->raw), je32_to_cpu(ri->node_crc), + crc, je32_to_cpu(ri->dsize), je32_to_cpu(ri->csize), + je32_to_cpu(ri->offset), buf)); + if (crc != je32_to_cpu(ri->node_crc)) { + printk(KERN_WARNING "Node CRC %08x != calculated CRC %08x for node at %08x\n", + je32_to_cpu(ri->node_crc), crc, ref_offset(fd->raw)); ret = -EIO; goto out_ri; } /* There was a bug where we wrote hole nodes out with csize/dsize swapped. Deal with it */ - if (ri->compr == JFFS2_COMPR_ZERO && !ri->dsize && ri->csize) { + if (ri->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(ri->dsize) && + je32_to_cpu(ri->csize)) { ri->dsize = ri->csize; - ri->csize = 0; + ri->csize = cpu_to_je32(0); } - D1(if(ofs + len > ri->dsize) { - printk(KERN_WARNING "jffs2_read_dnode() asked for %d bytes at %d from %d-byte node\n", len, ofs, ri->dsize); + D1(if(ofs + len > je32_to_cpu(ri->dsize)) { + printk(KERN_WARNING "jffs2_read_dnode() asked for %d bytes at %d from %d-byte node\n", + len, ofs, je32_to_cpu(ri->dsize)); ret = -EINVAL; goto out_ri; }); @@ -76,18 +82,18 @@ Reading partial node and it's uncompressed - read into readbuf, check CRC, and copy Reading partial node and it's compressed - read into readbuf, check checksum, decompress to decomprbuf and copy */ - if (ri->compr == JFFS2_COMPR_NONE && len == ri->dsize) { + if (ri->compr == JFFS2_COMPR_NONE && len == je32_to_cpu(ri->dsize)) { readbuf = buf; } else { - readbuf = kmalloc(ri->csize, GFP_KERNEL); + readbuf = kmalloc(je32_to_cpu(ri->csize), GFP_KERNEL); if (!readbuf) { ret = -ENOMEM; goto out_ri; } } if (ri->compr != JFFS2_COMPR_NONE) { - if (len < ri->dsize) { - decomprbuf = kmalloc(ri->dsize, GFP_KERNEL); + if (len < je32_to_cpu(ri->dsize)) { + decomprbuf = kmalloc(je32_to_cpu(ri->dsize), GFP_KERNEL); if (!decomprbuf) { ret = -ENOMEM; goto out_readbuf; @@ -99,31 +105,35 @@ decomprbuf = readbuf; } - D2(printk(KERN_DEBUG "Read %d bytes to %p\n", ri->csize, readbuf)); - ret = jffs2_flash_read(c, (fd->raw->flash_offset &~3) + sizeof(*ri), ri->csize, &readlen, readbuf); + D2(printk(KERN_DEBUG "Read %d bytes to %p\n", je32_to_cpu(ri->csize), + readbuf)); + ret = jffs2_flash_read(c, (ref_offset(fd->raw)) + sizeof(*ri), + je32_to_cpu(ri->csize), &readlen, readbuf); - if (!ret && readlen != ri->csize) + if (!ret && readlen != je32_to_cpu(ri->csize)) ret = -EIO; if (ret) goto out_decomprbuf; - crc = crc32(0, readbuf, ri->csize); - if (crc != ri->data_crc) { - printk(KERN_WARNING "Data CRC %08x != calculated CRC %08x for node at %08x\n", ri->data_crc, crc, fd->raw->flash_offset & ~3); + crc = crc32(0, readbuf, je32_to_cpu(ri->csize)); + if (crc != je32_to_cpu(ri->data_crc)) { + printk(KERN_WARNING "Data CRC %08x != calculated CRC %08x for node at %08x\n", + je32_to_cpu(ri->data_crc), crc, ref_offset(fd->raw)); ret = -EIO; goto out_decomprbuf; } D2(printk(KERN_DEBUG "Data CRC matches calculated CRC %08x\n", crc)); if (ri->compr != JFFS2_COMPR_NONE) { - D2(printk(KERN_DEBUG "Decompress %d bytes from %p to %d bytes at %p\n", ri->csize, readbuf, ri->dsize, decomprbuf)); - ret = jffs2_decompress(ri->compr, readbuf, decomprbuf, ri->csize, ri->dsize); + D2(printk(KERN_DEBUG "Decompress %d bytes from %p to %d bytes at %p\n", + je32_to_cpu(ri->csize), readbuf, je32_to_cpu(ri->dsize), decomprbuf)); + ret = jffs2_decompress(ri->compr, readbuf, decomprbuf, je32_to_cpu(ri->csize), je32_to_cpu(ri->dsize)); if (ret) { printk(KERN_WARNING "Error: jffs2_decompress returned %d\n", ret); goto out_decomprbuf; } } - if (len < ri->dsize) { + if (len < je32_to_cpu(ri->dsize)) { memcpy(buf, decomprbuf+ofs, len); } out_decomprbuf: @@ -142,16 +152,14 @@ unsigned char *buf, uint32_t offset, uint32_t len) { uint32_t end = offset + len; - struct jffs2_node_frag *frag = f->fraglist; + struct jffs2_node_frag *frag; int ret; D1(printk(KERN_DEBUG "jffs2_read_inode_range: ino #%u, range 0x%08x-0x%08x\n", f->inocache->ino, offset, offset+len)); - while(frag && frag->ofs + frag->size <= offset) { - D2(printk(KERN_DEBUG "skipping frag %d-%d; before the region we care about\n", frag->ofs, frag->ofs + frag->size)); - frag = frag->next; - } + frag = jffs2_lookup_node_frag(&f->fragtree, offset); + /* XXX FIXME: Where a single physical node actually shows up in two frags, we read it twice. Don't do that. */ /* Now we're pointing at the first frag which overlaps our page */ @@ -181,24 +189,28 @@ memset(buf, 0, holeend - offset); buf += holeend - offset; offset = holeend; - frag = frag->next; + frag = frag_next(frag); continue; } else { uint32_t readlen; - readlen = min(frag->size, end - offset); - D1(printk(KERN_DEBUG "Reading %d-%d from node at 0x%x\n", frag->ofs, frag->ofs+readlen, frag->node->raw->flash_offset & ~3)); - ret = jffs2_read_dnode(c, frag->node, buf, frag->ofs - frag->node->ofs, readlen); + uint32_t fragofs; /* offset within the frag to start reading */ + + fragofs = offset - frag->ofs; + readlen = min(frag->size - fragofs, end - offset); + D1(printk(KERN_DEBUG "Reading %d-%d from node at 0x%x\n", frag->ofs+fragofs, frag->ofs+fragofs+readlen, + ref_offset(frag->node->raw))); + ret = jffs2_read_dnode(c, frag->node, buf, fragofs + frag->ofs - frag->node->ofs, readlen); D2(printk(KERN_DEBUG "node read done\n")); if (ret) { D1(printk(KERN_DEBUG"jffs2_read_inode_range error %d\n",ret)); - memset(buf, 0, frag->size); + memset(buf, 0, readlen); return ret; } + buf += readlen; + offset += readlen; + frag = frag_next(frag); + D2(printk(KERN_DEBUG "node read was OK. Looping\n")); } - buf += frag->size; - offset += frag->size; - frag = frag->next; - D2(printk(KERN_DEBUG "node read was OK. Looping\n")); } return 0; } diff -Nru a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c --- a/fs/jffs2/readinode.c Fri Nov 22 13:41:17 2002 +++ b/fs/jffs2/readinode.c Fri Nov 22 13:41:17 2002 @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.73 2002/05/20 14:56:38 dwmw2 Exp $ + * $Id: readinode.c,v 1.95 2002/11/12 11:17:29 dwmw2 Exp $ * */ @@ -15,24 +15,43 @@ #include #include #include +#include #include #include #include "nodelist.h" -D1(void jffs2_print_frag_list(struct jffs2_inode_info *f) +D1(static void jffs2_print_fragtree(struct rb_root *list, int permitbug) { - struct jffs2_node_frag *this = f->fraglist; + struct jffs2_node_frag *this = frag_first(list); + uint32_t lastofs = 0; + int buggy = 0; while(this) { if (this->node) - printk(KERN_DEBUG "frag %04x-%04x: 0x%08x on flash (*%p->%p)\n", this->ofs, this->ofs+this->size, this->node->raw->flash_offset &~3, this, this->next); + printk(KERN_DEBUG "frag %04x-%04x: 0x%08x(%d) on flash (*%p). left (%p), right (%p), parent (%p)\n", + this->ofs, this->ofs+this->size, ref_offset(this->node->raw), ref_flags(this->node->raw), + this, frag_left(this), frag_right(this), frag_parent(this)); else - printk(KERN_DEBUG "frag %04x-%04x: hole (*%p->%p)\n", this->ofs, this->ofs+this->size, this, this->next); - this = this->next; + printk(KERN_DEBUG "frag %04x-%04x: hole (*%p). left (%p} right (%p), parent (%p)\n", this->ofs, + this->ofs+this->size, this, frag_left(this), frag_right(this), frag_parent(this)); + if (this->ofs != lastofs) + buggy = 1; + lastofs = this->ofs+this->size; + this = frag_next(this); + } + if (buggy && !permitbug) { + printk(KERN_CRIT "Frag tree got a hole in it\n"); + BUG(); } +}) + +D1(void jffs2_print_frag_list(struct jffs2_inode_info *f) +{ + jffs2_print_fragtree(&f->fragtree, 0); + if (f->metadata) { - printk(KERN_DEBUG "metadata at 0x%08x\n", f->metadata->raw->flash_offset &~3); + printk(KERN_DEBUG "metadata at 0x%08x\n", ref_offset(f->metadata->raw)); } }) @@ -45,7 +64,7 @@ int ret; D1(printk(KERN_DEBUG "jffs2_add_full_dnode_to_inode(ino #%u, f %p, fn %p)\n", f->inocache->ino, f, fn)); - ret = jffs2_add_full_dnode_to_fraglist(c, &f->fraglist, fn); + ret = jffs2_add_full_dnode_to_fraglist(c, &f->fragtree, fn); D2(jffs2_print_frag_list(f)); return ret; @@ -58,13 +77,14 @@ if (!this->node->frags) { /* The node has no valid frags left. It's totally obsoleted */ D2(printk(KERN_DEBUG "Marking old node @0x%08x (0x%04x-0x%04x) obsolete\n", - this->node->raw->flash_offset &~3, this->node->ofs, this->node->ofs+this->node->size)); + ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size)); jffs2_mark_node_obsolete(c, this->node->raw); jffs2_free_full_dnode(this->node); } else { - D2(printk(KERN_DEBUG "Not marking old node @0x%08x (0x%04x-0x%04x) obsolete. frags is %d\n", - this->node->raw->flash_offset &~3, this->node->ofs, this->node->ofs+this->node->size, + D2(printk(KERN_DEBUG "Marking old node @0x%08x (0x%04x-0x%04x) REF_NORMAL. frags is %d\n", + ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size, this->node->frags)); + mark_ref_normal(this->node->raw); } } @@ -72,27 +92,24 @@ } /* Doesn't set inode->i_size */ -int jffs2_add_full_dnode_to_fraglist(struct jffs2_sb_info *c, struct jffs2_node_frag **list, struct jffs2_full_dnode *fn) +int jffs2_add_full_dnode_to_fraglist(struct jffs2_sb_info *c, struct rb_root *list, struct jffs2_full_dnode *fn) { - - struct jffs2_node_frag *this, **prev, *old; - struct jffs2_node_frag *newfrag, *newfrag2; - uint32_t lastend = 0; - + struct jffs2_node_frag *this; + struct jffs2_node_frag *newfrag; + uint32_t lastend; newfrag = jffs2_alloc_node_frag(); if (!newfrag) { return -ENOMEM; } - D2(if (fn->raw) - printk(KERN_DEBUG "adding node %04x-%04x @0x%08x on flash, newfrag *%p\n", fn->ofs, fn->ofs+fn->size, fn->raw->flash_offset &~3, newfrag); - else - printk(KERN_DEBUG "adding hole node %04x-%04x on flash, newfrag *%p\n", fn->ofs, fn->ofs+fn->size, newfrag)); - - prev = list; - this = *list; + if (!fn->raw) { + printk(KERN_WARNING "dwmw2 is stupid. j_a_f_d_t_f should never happen with ->raw == NULL\n"); + BUG(); + } + D2(printk(KERN_DEBUG "adding node %04x-%04x @0x%08x on flash, newfrag *%p\n", fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag)); + if (!fn->size) { jffs2_free_node_frag(newfrag); return 0; @@ -102,21 +119,33 @@ newfrag->size = fn->size; newfrag->node = fn; newfrag->node->frags = 1; - newfrag->next = (void *)0xdeadbeef; /* Skip all the nodes which are completed before this one starts */ - while(this && fn->ofs >= this->ofs+this->size) { - lastend = this->ofs + this->size; + this = jffs2_lookup_node_frag(list, fn->ofs); - D2(printk(KERN_DEBUG "j_a_f_d_t_f: skipping frag 0x%04x-0x%04x; phys 0x%08x (*%p->%p)\n", - this->ofs, this->ofs+this->size, this->node?(this->node->raw->flash_offset &~3):0xffffffff, this, this->next)); - prev = &this->next; - this = this->next; + if (this) { + D2(printk(KERN_DEBUG "j_a_f_d_t_f: Lookup gave frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n", + this->ofs, this->ofs+this->size, this->node?(ref_offset(this->node->raw)):0xffffffff, this)); + lastend = this->ofs + this->size; + } else { + D2(printk(KERN_DEBUG "j_a_f_d_t_f: Lookup gave no frag\n")); + lastend = 0; } - + /* See if we ran off the end of the list */ - if (!this) { + if (lastend <= newfrag->ofs) { /* We did */ + + /* Check if 'this' node was on the same page as the new node. + If so, both 'this' and the new node get marked REF_NORMAL so + the GC can take a look. + */ + if ((lastend-1) >> PAGE_CACHE_SHIFT == newfrag->ofs >> PAGE_CACHE_SHIFT) { + if (this->node) + mark_ref_normal(this->node->raw); + mark_ref_normal(fn->raw); + } + if (lastend < fn->ofs) { /* ... and we need to put a hole in before the new node */ struct jffs2_node_frag *holefrag = jffs2_alloc_node_frag(); @@ -124,96 +153,162 @@ return -ENOMEM; holefrag->ofs = lastend; holefrag->size = fn->ofs - lastend; - holefrag->next = NULL; holefrag->node = NULL; - *prev = holefrag; - prev = &holefrag->next; + if (this) { + /* By definition, the 'this' node has no right-hand child, + because there are no frags with offset greater than it. + So that's where we want to put the hole */ + D2(printk(KERN_DEBUG "Adding hole frag (%p) on right of node at (%p)\n", holefrag, this)); + rb_link_node(&holefrag->rb, &this->rb, &this->rb.rb_right); + } else { + D2(printk(KERN_DEBUG "Adding hole frag (%p) at root of tree\n", holefrag)); + rb_link_node(&holefrag->rb, NULL, &list->rb_node); + } + rb_insert_color(&holefrag->rb, list); + this = holefrag; + } + if (this) { + /* By definition, the 'this' node has no right-hand child, + because there are no frags with offset greater than it. + So that's where we want to put the hole */ + D2(printk(KERN_DEBUG "Adding new frag (%p) on right of node at (%p)\n", newfrag, this)); + rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); + } else { + D2(printk(KERN_DEBUG "Adding new frag (%p) at root of tree\n", newfrag)); + rb_link_node(&newfrag->rb, NULL, &list->rb_node); } - newfrag->next = NULL; - *prev = newfrag; + rb_insert_color(&newfrag->rb, list); return 0; } - D2(printk(KERN_DEBUG "j_a_f_d_t_f: dealing with frag 0x%04x-0x%04x; phys 0x%08x (*%p->%p)\n", - this->ofs, this->ofs+this->size, this->node?(this->node->raw->flash_offset &~3):0xffffffff, this, this->next)); + D2(printk(KERN_DEBUG "j_a_f_d_t_f: dealing with frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n", + this->ofs, this->ofs+this->size, this->node?(ref_offset(this->node->raw)):0xffffffff, this)); - /* OK. 'this' is pointing at the first frag that fn->ofs at least partially obsoletes, - * - i.e. fn->ofs < this->ofs+this->size && fn->ofs >= this->ofs + /* OK. 'this' is pointing at the first frag that newfrag->ofs at least partially obsoletes, + * - i.e. newfrag->ofs < this->ofs+this->size && newfrag->ofs >= this->ofs */ - if (fn->ofs > this->ofs) { + if (newfrag->ofs > this->ofs) { /* This node isn't completely obsoleted. The start of it remains valid */ - if (this->ofs + this->size > fn->ofs + fn->size) { + + /* Mark the new node and the partially covered node REF_NORMAL -- let + the GC take a look at them */ + mark_ref_normal(fn->raw); + if (this->node) + mark_ref_normal(this->node->raw); + + if (this->ofs + this->size > newfrag->ofs + newfrag->size) { /* The new node splits 'this' frag into two */ - newfrag2 = jffs2_alloc_node_frag(); + struct jffs2_node_frag *newfrag2 = jffs2_alloc_node_frag(); if (!newfrag2) { jffs2_free_node_frag(newfrag); return -ENOMEM; } - D1(printk(KERN_DEBUG "split old frag 0x%04x-0x%04x -->", this->ofs, this->ofs+this->size); + D2(printk(KERN_DEBUG "split old frag 0x%04x-0x%04x -->", this->ofs, this->ofs+this->size); if (this->node) - printk("phys 0x%08x\n", this->node->raw->flash_offset &~3); + printk("phys 0x%08x\n", ref_offset(this->node->raw)); else printk("hole\n"); ) - newfrag2->ofs = fn->ofs + fn->size; + + /* New second frag pointing to this's node */ + newfrag2->ofs = newfrag->ofs + newfrag->size; newfrag2->size = (this->ofs+this->size) - newfrag2->ofs; - newfrag2->next = this->next; newfrag2->node = this->node; if (this->node) this->node->frags++; - newfrag->next = newfrag2; - this->next = newfrag; + + /* Adjust size of original 'this' */ this->size = newfrag->ofs - this->ofs; + + /* Now, we know there's no node with offset + greater than this->ofs but smaller than + newfrag2->ofs or newfrag->ofs, for obvious + reasons. So we can do a tree insert from + 'this' to insert newfrag, and a tree insert + from newfrag to insert newfrag2. */ + jffs2_fragtree_insert(newfrag, this); + rb_insert_color(&newfrag->rb, list); + + jffs2_fragtree_insert(newfrag2, newfrag); + rb_insert_color(&newfrag2->rb, list); + return 0; } /* New node just reduces 'this' frag in size, doesn't split it */ - this->size = fn->ofs - this->ofs; - newfrag->next = this->next; - this->next = newfrag; - this = newfrag->next; + this->size = newfrag->ofs - this->ofs; + + /* Again, we know it lives down here in the tree */ + jffs2_fragtree_insert(newfrag, this); + rb_insert_color(&newfrag->rb, list); } else { - D2(printk(KERN_DEBUG "Inserting newfrag (*%p) in before 'this' (*%p)\n", newfrag, this)); - *prev = newfrag; - newfrag->next = this; + /* New frag starts at the same point as 'this' used to. Replace + it in the tree without doing a delete and insertion */ + D2(printk(KERN_DEBUG "Inserting newfrag (*%p),%d-%d in before 'this' (*%p),%d-%d\n", + newfrag, newfrag->ofs, newfrag->ofs+newfrag->size, + this, this->ofs, this->ofs+this->size)); + + rb_replace_node(&this->rb, &newfrag->rb, list); + + if (newfrag->ofs + newfrag->size >= this->ofs+this->size) { + D2(printk(KERN_DEBUG "Obsoleting node frag %p (%x-%x)\n", this, this->ofs, this->ofs+this->size)); + jffs2_obsolete_node_frag(c, this); + } else { + this->ofs += newfrag->size; + this->size -= newfrag->size; + + jffs2_fragtree_insert(this, newfrag); + rb_insert_color(&this->rb, list); + return 0; + } } - /* OK, now we have newfrag added in the correct place in the list, but - newfrag->next points to a fragment which may be overlapping it + /* OK, now we have newfrag added in the correct place in the tree, but + frag_next(newfrag) may be a fragment which is overlapped by it */ - while (this && newfrag->ofs + newfrag->size >= this->ofs + this->size) { - /* 'this' frag is obsoleted. */ - old = this; - this = old->next; - jffs2_obsolete_node_frag(c, old); + while ((this = frag_next(newfrag)) && newfrag->ofs + newfrag->size >= this->ofs + this->size) { + /* 'this' frag is obsoleted completely. */ + D2(printk(KERN_DEBUG "Obsoleting node frag %p (%x-%x) and removing from tree\n", this, this->ofs, this->ofs+this->size)); + rb_erase(&this->rb, list); + jffs2_obsolete_node_frag(c, this); } /* Now we're pointing at the first frag which isn't totally obsoleted by the new frag */ - newfrag->next = this; if (!this || newfrag->ofs + newfrag->size == this->ofs) { return 0; } - /* Still some overlap */ + /* Still some overlap but we don't need to move it in the tree */ this->size = (this->ofs + this->size) - (newfrag->ofs + newfrag->size); this->ofs = newfrag->ofs + newfrag->size; + + /* And mark them REF_NORMAL so the GC takes a look at them */ + if (this->node) + mark_ref_normal(this->node->raw); + mark_ref_normal(fn->raw); + return 0; } -void jffs2_truncate_fraglist (struct jffs2_sb_info *c, struct jffs2_node_frag **list, uint32_t size) +void jffs2_truncate_fraglist (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size) { + struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size); + D1(printk(KERN_DEBUG "Truncating fraglist to 0x%08x bytes\n", size)); - while (*list) { - if ((*list)->ofs >= size) { - struct jffs2_node_frag *this = *list; - *list = this->next; - D1(printk(KERN_DEBUG "Removing frag 0x%08x-0x%08x\n", this->ofs, this->ofs+this->size)); - jffs2_obsolete_node_frag(c, this); - continue; - } else if ((*list)->ofs + (*list)->size > size) { - D1(printk(KERN_DEBUG "Truncating frag 0x%08x-0x%08x\n", (*list)->ofs, (*list)->ofs + (*list)->size)); - (*list)->size = size - (*list)->ofs; - } - list = &(*list)->next; + /* We know frag->ofs <= size. That's what lookup does for us */ + if (frag && frag->ofs != size) { + if (frag->ofs+frag->size >= size) { + D1(printk(KERN_DEBUG "Truncating frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size)); + frag->size = size - frag->ofs; + } + frag = frag_next(frag); + } + while (frag && frag->ofs >= size) { + struct jffs2_node_frag *next = frag_next(frag); + + D1(printk(KERN_DEBUG "Removing frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size)); + frag_erase(frag, list); + jffs2_obsolete_node_frag(c, frag); + frag = next; } } @@ -271,7 +366,7 @@ fn = tn->fn; if (f->metadata && tn->version > mdata_ver) { - D1(printk(KERN_DEBUG "Obsoleting old metadata at 0x%08x\n", f->metadata->raw->flash_offset &~3)); + D1(printk(KERN_DEBUG "Obsoleting old metadata at 0x%08x\n", ref_offset(f->metadata->raw))); jffs2_mark_node_obsolete(c, f->metadata->raw); jffs2_free_full_dnode(f->metadata); f->metadata = NULL; @@ -283,7 +378,7 @@ jffs2_add_full_dnode_to_inode(c, f, fn); } else { /* Zero-sized node at end of version list. Just a metadata update */ - D1(printk(KERN_DEBUG "metadata @%08x: ver %d\n", fn->raw->flash_offset &~3, tn->version)); + D1(printk(KERN_DEBUG "metadata @%08x: ver %d\n", ref_offset(fn->raw), tn->version)); f->metadata = fn; mdata_ver = tn->version; } @@ -299,16 +394,16 @@ } printk(KERN_WARNING "jffs2_do_read_inode(): But it has children so we fake some modes for it\n"); } - latest_node->mode = S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO; - latest_node->version = 0; - latest_node->atime = latest_node->ctime = latest_node->mtime = 0; - latest_node->isize = 0; - latest_node->gid = 0; - latest_node->uid = 0; + latest_node->mode = cpu_to_je32(S_IFDIR|S_IRUGO|S_IWUSR|S_IXUGO); + latest_node->version = cpu_to_je32(0); + latest_node->atime = latest_node->ctime = latest_node->mtime = cpu_to_je32(0); + latest_node->isize = cpu_to_je32(0); + latest_node->gid = cpu_to_je16(0); + latest_node->uid = cpu_to_je16(0); return 0; } - ret = jffs2_flash_read(c, fn->raw->flash_offset & ~3, sizeof(*latest_node), &retlen, (void *)latest_node); + ret = jffs2_flash_read(c, ref_offset(fn->raw), sizeof(*latest_node), &retlen, (void *)latest_node); if (ret || retlen != sizeof(*latest_node)) { printk(KERN_NOTICE "MTD read in jffs2_do_read_inode() failed: Returned %d, %ld of %d bytes read\n", ret, (long)retlen, sizeof(*latest_node)); @@ -319,26 +414,26 @@ } crc = crc32(0, latest_node, sizeof(*latest_node)-8); - if (crc != latest_node->node_crc) { - printk(KERN_NOTICE "CRC failed for read_inode of inode %u at physical location 0x%x\n", ino, fn->raw->flash_offset & ~3); + if (crc != je32_to_cpu(latest_node->node_crc)) { + printk(KERN_NOTICE "CRC failed for read_inode of inode %u at physical location 0x%x\n", ino, ref_offset(fn->raw)); up(&f->sem); jffs2_do_clear_inode(c, f); return -EIO; } - switch(latest_node->mode & S_IFMT) { + switch(je32_to_cpu(latest_node->mode) & S_IFMT) { case S_IFDIR: - if (mctime_ver > latest_node->version) { + if (mctime_ver > je32_to_cpu(latest_node->version)) { /* The times in the latest_node are actually older than mctime in the latest dirent. Cheat. */ - latest_node->ctime = latest_node->mtime = latest_mctime; + latest_node->ctime = latest_node->mtime = cpu_to_je32(latest_mctime); } break; case S_IFREG: /* If it was a regular file, truncate it to the latest node's isize */ - jffs2_truncate_fraglist(c, &f->fraglist, latest_node->isize); + jffs2_truncate_fraglist(c, &f->fragtree, je32_to_cpu(latest_node->isize)); break; case S_IFLNK: @@ -346,7 +441,7 @@ Remove this when dwmw2 comes to his senses and stops symlinks from being an entirely gratuitous special case. */ - if (!latest_node->isize) + if (!je32_to_cpu(latest_node->isize)) latest_node->isize = latest_node->dsize; /* fall through... */ @@ -355,82 +450,79 @@ /* Xertain inode types should have only one data node, and it's kept as the metadata node */ if (f->metadata) { - printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o had metadata node\n", ino, latest_node->mode); + printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o had metadata node\n", ino, je32_to_cpu(latest_node->mode)); up(&f->sem); jffs2_do_clear_inode(c, f); return -EIO; } - if (!f->fraglist) { - printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o has no fragments\n", ino, latest_node->mode); + if (!frag_first(&f->fragtree)) { + printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o has no fragments\n", ino, je32_to_cpu(latest_node->mode)); up(&f->sem); jffs2_do_clear_inode(c, f); return -EIO; } /* ASSERT: f->fraglist != NULL */ - if (f->fraglist->next) { - printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o had more than one node\n", ino, latest_node->mode); + if (frag_next(frag_first(&f->fragtree))) { + printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o had more than one node\n", ino, je32_to_cpu(latest_node->mode)); /* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */ up(&f->sem); jffs2_do_clear_inode(c, f); return -EIO; } /* OK. We're happy */ - f->metadata = f->fraglist->node; - jffs2_free_node_frag(f->fraglist); - f->fraglist = NULL; + f->metadata = frag_first(&f->fragtree)->node; + jffs2_free_node_frag(frag_first(&f->fragtree)); + f->fragtree = RB_ROOT; break; } + f->inocache->state = INO_STATE_PRESENT; return 0; } - void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f) { - struct jffs2_node_frag *frag, *frags; struct jffs2_full_dirent *fd, *fds; + /* I don't think we care about the potential race due to reading this + without f->sem. It can never get undeleted. */ + int deleted = f->inocache && !f->inocache->nlink; + + /* If it's a deleted inode, grab the alloc_sem. This prevents + jffs2_garbage_collect_pass() from deciding that it wants to + garbage collect one of the nodes we're just about to mark + obsolete -- by the time we drop alloc_sem and return, all + the nodes are marked obsolete, and jffs2_g_c_pass() won't + call iget() for the inode in question. - /* If it's a deleted inode, grab the alloc_sem to keep the - (maybe temporary) BUG() in jffs2_mark_node_obsolete() - from triggering */ - if(!f->inocache->nlink) + We also do this to keep the (maybe temporary) BUG() in + jffs2_mark_node_obsolete() from triggering. + */ + if(deleted) down(&c->alloc_sem); down(&f->sem); - frags = f->fraglist; - fds = f->dents; if (f->metadata) { - if (!f->inocache->nlink) + if (deleted) jffs2_mark_node_obsolete(c, f->metadata->raw); jffs2_free_full_dnode(f->metadata); } - while (frags) { - frag = frags; - frags = frag->next; - D2(printk(KERN_DEBUG "jffs2_do_clear_inode: frag at 0x%x-0x%x: node %p, frags %d--\n", frag->ofs, frag->ofs+frag->size, frag->node, frag->node?frag->node->frags:0)); - - if (frag->node && !(--frag->node->frags)) { - /* Not a hole, and it's the final remaining frag of this node. Free the node */ - if (!f->inocache->nlink) - jffs2_mark_node_obsolete(c, frag->node->raw); + jffs2_kill_fragtree(&f->fragtree, deleted?c:NULL); + + fds = f->dents; - jffs2_free_full_dnode(frag->node); - } - jffs2_free_node_frag(frag); - } while(fds) { fd = fds; fds = fd->next; jffs2_free_full_dirent(fd); } - /* Urgh. Is there a nicer way to do this? */ - if(!f->inocache->nlink) { - up(&f->sem); + if (f->inocache) + f->inocache->state = INO_STATE_CHECKEDABSENT; + + up(&f->sem); + + if(deleted) up(&c->alloc_sem); - } else { - up(&f->sem); - } } diff -Nru a/fs/jffs2/scan.c b/fs/jffs2/scan.c --- a/fs/jffs2/scan.c Fri Nov 22 13:41:23 2002 +++ b/fs/jffs2/scan.c Fri Nov 22 13:41:23 2002 @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: scan.c,v 1.79 2002/07/25 20:48:51 dwmw2 Exp $ + * $Id: scan.c,v 1.92 2002/09/09 16:29:08 dwmw2 Exp $ * */ #include @@ -15,8 +15,10 @@ #include #include #include +#include #include "nodelist.h" +#define EMPTY_SCAN_SIZE 1024 #define DIRTY_SPACE(x) do { typeof(x) _x = (x); \ c->free_size -= _x; c->dirty_size += _x; \ @@ -26,6 +28,10 @@ c->free_size -= _x; c->used_size += _x; \ jeb->free_size -= _x ; jeb->used_size += _x; \ }while(0) +#define UNCHECKED_SPACE(x) do { typeof(x) _x = (x); \ + c->free_size -= _x; c->unchecked_size += _x; \ + jeb->free_size -= _x ; jeb->unchecked_size += _x; \ + }while(0) #define noisy_printk(noise, args...) do { \ if (*(noise)) { \ @@ -39,15 +45,17 @@ static uint32_t pseudo_random; -static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); +static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, + unsigned char *buf, uint32_t buf_size); /* These helper functions _must_ increase ofs and also do the dirty/used space accounting. * Returning an error will abort the mount - bad checksums etc. should just mark the space * as dirty. */ -static int jffs2_scan_empty(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t *ofs, int *noise); -static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t *ofs); -static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t *ofs); +static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, + struct jffs2_raw_inode *ri, uint32_t ofs); +static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, + struct jffs2_raw_dirent *rd, uint32_t ofs); #define BLK_STATE_ALLFF 0 #define BLK_STATE_CLEAN 1 @@ -60,15 +68,44 @@ { int i, ret; uint32_t empty_blocks = 0, bad_blocks = 0; + unsigned char *flashbuf = NULL; + uint32_t buf_size = 0; + size_t pointlen; if (!c->blocks) { printk(KERN_WARNING "EEEK! c->blocks is NULL!\n"); return -EINVAL; } + if (c->mtd->point) { + ret = c->mtd->point (c->mtd, 0, c->mtd->size, &pointlen, &flashbuf); + if (!ret && pointlen < c->mtd->size) { + /* Don't muck about if it won't let us point to the whole flash */ + D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%x\n", pointlen)); + c->mtd->unpoint(c->mtd, flashbuf); + flashbuf = NULL; + } + if (ret) + D1(printk(KERN_DEBUG "MTD point failed %d\n", ret)); + } + if (!flashbuf) { + /* For NAND it's quicker to read a whole eraseblock at a time, + apparently */ + if (jffs2_cleanmarker_oob(c)) + buf_size = c->sector_size; + else + buf_size = PAGE_SIZE; + + D1(printk(KERN_DEBUG "Allocating readbuf of %d bytes\n", buf_size)); + flashbuf = kmalloc(buf_size, GFP_KERNEL); + if (!flashbuf) + return -ENOMEM; + } + for (i=0; inr_blocks; i++) { struct jffs2_eraseblock *jeb = &c->blocks[i]; - ret = jffs2_scan_eraseblock(c, jeb); + ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset), buf_size); + if (ret < 0) return ret; @@ -120,6 +157,11 @@ (!c->nextblock || c->nextblock->free_size < jeb->free_size)) { /* Better candidate for the next writes to go to */ if (c->nextblock) { + c->nextblock->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size; + c->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size; + c->free_size -= c->nextblock->free_size; + c->wasted_size -= c->nextblock->wasted_size; + c->nextblock->free_size = c->nextblock->wasted_size = 0; if (VERYDIRTY(c, c->nextblock->dirty_size)) { list_add(&c->nextblock->list, &c->very_dirty_list); } else { @@ -128,6 +170,11 @@ } c->nextblock = jeb; } else { + jeb->dirty_size += jeb->free_size + jeb->wasted_size; + c->dirty_size += jeb->free_size + jeb->wasted_size; + c->free_size -= jeb->free_size; + c->wasted_size -= jeb->wasted_size; + jeb->free_size = jeb->wasted_size = 0; if (VERYDIRTY(c, jeb->dirty_size)) { list_add(&jeb->list, &c->very_dirty_list); } else { @@ -156,6 +203,14 @@ BUG(); } } + + /* Nextblock dirty is always seen as wasted, because we cannot recycle it now */ + if (c->nextblock && (c->nextblock->dirty_size)) { + c->nextblock->wasted_size += c->nextblock->dirty_size; + c->wasted_size += c->nextblock->dirty_size; + c->dirty_size -= c->nextblock->dirty_size; + c->nextblock->dirty_size = 0; + } if (!jffs2_can_mark_obsolete(c) && c->nextblock && (c->nextblock->free_size & (c->wbuf_pagesize-1))) { /* If we're going to start writing into a block which already @@ -166,8 +221,8 @@ D1(printk(KERN_DEBUG "jffs2_scan_medium(): Skipping %d bytes in nextblock to ensure page alignment\n", skip)); - c->nextblock->dirty_size += skip; - c->dirty_size += skip; + c->nextblock->wasted_size += skip; + c->wasted_size += skip; c->nextblock->free_size -= skip; c->free_size -= skip; @@ -180,17 +235,47 @@ } jffs2_erase_pending_trigger(c); } + if (buf_size) + kfree(flashbuf); + else + c->mtd->unpoint(c->mtd, flashbuf); + return 0; } -static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) { - struct jffs2_unknown_node node; +static int jffs2_fill_scan_buf (struct jffs2_sb_info *c, unsigned char *buf, + uint32_t ofs, uint32_t len) +{ + int ret; + size_t retlen; + + ret = jffs2_flash_read(c, ofs, len, &retlen, buf); + if (ret) { + D1(printk(KERN_WARNING "mtd->read(0x%x bytes from 0x%x) returned %d\n", len, ofs, ret)); + return ret; + } + if (retlen < len) { + D1(printk(KERN_WARNING "Read at 0x%x gave only 0x%x bytes\n", ofs, retlen)); + return -EIO; + } + D2(printk(KERN_DEBUG "Read 0x%x bytes from 0x%08x into buf\n", len, ofs)); + D2(printk(KERN_DEBUG "000: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15])); + return 0; +} + +static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, + unsigned char *buf, uint32_t buf_size) { + struct jffs2_unknown_node *node; + struct jffs2_unknown_node crcnode; uint32_t ofs, prevofs; - uint32_t hdr_crc, nodetype; + uint32_t hdr_crc, buf_ofs, buf_len; int err; int noise = 0; + int wasempty = 0; + uint32_t empty_start = 0; #ifdef CONFIG_JFFS2_FS_NAND - int cleanmarkerfound=0; + int cleanmarkerfound = 0; #endif ofs = jeb->offset; @@ -214,16 +299,30 @@ } } #endif - err = jffs2_scan_empty(c, jeb, &ofs, &noise); - if (err) - return err; + buf_ofs = jeb->offset; - if (ofs == jeb->offset + c->sector_size) { + if (!buf_size) { + buf_len = c->sector_size; + } else { + buf_len = EMPTY_SCAN_SIZE; + err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len); + if (err) + return err; + } + + /* We temporarily use 'ofs' as a pointer into the buffer/jeb */ + ofs = 0; + + /* Scan only 4KiB of 0xFF before declaring it's empty */ + while(ofs < EMPTY_SCAN_SIZE && *(uint32_t *)(&buf[ofs]) == 0xFFFFFFFF) + ofs += 4; + + if (ofs == EMPTY_SCAN_SIZE) { #ifdef CONFIG_JFFS2_FS_NAND if (jffs2_cleanmarker_oob(c)) { /* scan oob, take care of cleanmarker */ int ret = jffs2_check_oob_empty(c, jeb, cleanmarkerfound); - D2(printk(KERN_NOTICE "jffs_check_oob_empty returned %d\n",ret)); + D2(printk(KERN_NOTICE "jffs2_check_oob_empty returned %d\n",ret)); switch (ret) { case 0: return cleanmarkerfound ? BLK_STATE_CLEANMARKER : BLK_STATE_ALLFF; case 1: return BLK_STATE_ALLDIRTY; @@ -236,12 +335,20 @@ D1(printk(KERN_DEBUG "Block at 0x%08x is empty (erased)\n", jeb->offset)); return BLK_STATE_ALLFF; /* OK to erase if all blocks are like this */ } - + if (ofs) { + D1(printk(KERN_DEBUG "Free space at %08x ends at %08x\n", jeb->offset, + jeb->offset + ofs)); + DIRTY_SPACE(ofs); + } + + /* Now ofs is a complete physical flash offset as it always was... */ + ofs += jeb->offset; + noise = 10; while(ofs < jeb->offset + c->sector_size) { - size_t retlen; - ACCT_PARANOIA_CHECK(jeb); + + D1(ACCT_PARANOIA_CHECK(jeb)); cond_resched(); @@ -257,110 +364,174 @@ continue; } prevofs = ofs; - - if (jeb->offset + c->sector_size < ofs + sizeof(node)) { - D1(printk(KERN_DEBUG "Fewer than %d bytes left to end of block. Not reading\n", sizeof(struct jffs2_unknown_node))); + + if (jeb->offset + c->sector_size < ofs + sizeof(*node)) { + D1(printk(KERN_DEBUG "Fewer than %d bytes left to end of block. (%x+%x<%x+%x) Not reading\n", sizeof(struct jffs2_unknown_node), + jeb->offset, c->sector_size, ofs, sizeof(*node))); DIRTY_SPACE((jeb->offset + c->sector_size)-ofs); break; } - err = jffs2_flash_read(c, ofs, sizeof(node), &retlen, (char *)&node); - if (err) { - D1(printk(KERN_WARNING "mtd->read(0x%x bytes from 0x%x) returned %d\n", sizeof(node), ofs, err)); - return err; - } - if (retlen < sizeof(node)) { - D1(printk(KERN_WARNING "Read at 0x%x gave only 0x%x bytes\n", ofs, retlen)); - DIRTY_SPACE(retlen); - ofs += retlen; - continue; - } + if (buf_ofs + buf_len < ofs + sizeof(*node)) { + buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); + D1(printk(KERN_DEBUG "Fewer than %d bytes (node header) left to end of buf. Reading 0x%x at 0x%08x\n", + sizeof(struct jffs2_unknown_node), buf_len, ofs)); + err = jffs2_fill_scan_buf(c, buf, ofs, buf_len); + if (err) + return err; + buf_ofs = ofs; + } + + node = (struct jffs2_unknown_node *)&buf[ofs-buf_ofs]; + + if (*(uint32_t *)(&buf[ofs-buf_ofs]) == 0xffffffff) { + uint32_t inbuf_ofs = ofs - buf_ofs + 4; + uint32_t scanend; - if (node.magic == JFFS2_EMPTY_BITMASK && node.nodetype == JFFS2_EMPTY_BITMASK) { - D1(printk(KERN_DEBUG "Found empty flash at 0x%x\n", ofs)); - err = jffs2_scan_empty(c, jeb, &ofs, &noise); - if (err) return err; + empty_start = ofs; + ofs += 4; + + /* If scanning empty space after only a cleanmarker, don't + bother scanning the whole block */ + if (unlikely(empty_start == jeb->offset + c->cleanmarker_size && + jeb->offset + EMPTY_SCAN_SIZE < buf_ofs + buf_len)) + scanend = jeb->offset + EMPTY_SCAN_SIZE - buf_ofs; + else + scanend = buf_len; + + D1(printk(KERN_DEBUG "Found empty flash at 0x%08x\n", ofs)); + while (inbuf_ofs < scanend) { + if (*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff) + goto emptyends; + + inbuf_ofs+=4; + ofs += 4; + } + /* Ran off end. */ + D1(printk(KERN_DEBUG "Empty flash ends normally at 0x%08x\n", ofs)); + + if (buf_ofs == jeb->offset && jeb->used_size == PAD(c->cleanmarker_size) && + !jeb->first_node->next_in_ino && !jeb->dirty_size) + return BLK_STATE_CLEANMARKER; + wasempty = 1; + continue; + } else if (wasempty) { + emptyends: + printk(KERN_WARNING "Empty flash at 0x%08x ends at 0x%08x\n", empty_start, ofs); + DIRTY_SPACE(ofs-empty_start); + wasempty = 0; continue; } - if (ofs == jeb->offset && node.magic == KSAMTIB_CIGAM_2SFFJ) { + if (ofs == jeb->offset && je16_to_cpu(node->magic) == KSAMTIB_CIGAM_2SFFJ) { printk(KERN_WARNING "Magic bitmask is backwards at offset 0x%08x. Wrong endian filesystem?\n", ofs); DIRTY_SPACE(4); ofs += 4; continue; } - if (node.magic == JFFS2_DIRTY_BITMASK) { + if (je16_to_cpu(node->magic) == JFFS2_DIRTY_BITMASK) { D1(printk(KERN_DEBUG "Empty bitmask at 0x%08x\n", ofs)); DIRTY_SPACE(4); ofs += 4; continue; } - if (node.magic == JFFS2_OLD_MAGIC_BITMASK) { + if (je16_to_cpu(node->magic) == JFFS2_OLD_MAGIC_BITMASK) { printk(KERN_WARNING "Old JFFS2 bitmask found at 0x%08x\n", ofs); printk(KERN_WARNING "You cannot use older JFFS2 filesystems with newer kernels\n"); DIRTY_SPACE(4); ofs += 4; continue; } - if (node.magic != JFFS2_MAGIC_BITMASK) { + if (je16_to_cpu(node->magic) != JFFS2_MAGIC_BITMASK) { /* OK. We're out of possibilities. Whinge and move on */ - noisy_printk(&noise, "jffs2_scan_eraseblock(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead\n", JFFS2_MAGIC_BITMASK, ofs, node.magic); + noisy_printk(&noise, "jffs2_scan_eraseblock(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead\n", + JFFS2_MAGIC_BITMASK, ofs, + je16_to_cpu(node->magic)); DIRTY_SPACE(4); ofs += 4; continue; } /* We seem to have a node of sorts. Check the CRC */ - nodetype = node.nodetype; - node.nodetype |= JFFS2_NODE_ACCURATE; - hdr_crc = crc32(0, &node, sizeof(node)-4); - node.nodetype = nodetype; - if (hdr_crc != node.hdr_crc) { + crcnode.magic = node->magic; + crcnode.nodetype = cpu_to_je16( je16_to_cpu(node->nodetype) | JFFS2_NODE_ACCURATE); + crcnode.totlen = node->totlen; + hdr_crc = crc32(0, &crcnode, sizeof(crcnode)-4); + + if (hdr_crc != je32_to_cpu(node->hdr_crc)) { noisy_printk(&noise, "jffs2_scan_eraseblock(): Node at 0x%08x {0x%04x, 0x%04x, 0x%08x) has invalid CRC 0x%08x (calculated 0x%08x)\n", - ofs, node.magic, node.nodetype, node.totlen, node.hdr_crc, hdr_crc); + ofs, je16_to_cpu(node->magic), + je16_to_cpu(node->nodetype), + je32_to_cpu(node->totlen), + je32_to_cpu(node->hdr_crc), + hdr_crc); DIRTY_SPACE(4); ofs += 4; continue; } - if (ofs + node.totlen > jeb->offset + c->sector_size) { + if (ofs + je32_to_cpu(node->totlen) > + jeb->offset + c->sector_size) { /* Eep. Node goes over the end of the erase block. */ printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block\n", - ofs, node.totlen); + ofs, je32_to_cpu(node->totlen)); printk(KERN_WARNING "Perhaps the file system was created with the wrong erase size?\n"); DIRTY_SPACE(4); ofs += 4; continue; } - if (!(node.nodetype & JFFS2_NODE_ACCURATE)) { + if (!(je16_to_cpu(node->nodetype) & JFFS2_NODE_ACCURATE)) { /* Wheee. This is an obsoleted node */ D2(printk(KERN_DEBUG "Node at 0x%08x is obsolete. Skipping\n", ofs)); - DIRTY_SPACE(PAD(node.totlen)); - ofs += PAD(node.totlen); + DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); + ofs += PAD(je32_to_cpu(node->totlen)); continue; } - switch(node.nodetype) { + switch(je16_to_cpu(node->nodetype)) { case JFFS2_NODETYPE_INODE: - err = jffs2_scan_inode_node(c, jeb, &ofs); + if (buf_ofs + buf_len < ofs + sizeof(struct jffs2_raw_inode)) { + buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); + D1(printk(KERN_DEBUG "Fewer than %d bytes (inode node) left to end of buf. Reading 0x%x at 0x%08x\n", + sizeof(struct jffs2_raw_inode), buf_len, ofs)); + err = jffs2_fill_scan_buf(c, buf, ofs, buf_len); + if (err) + return err; + buf_ofs = ofs; + node = (void *)buf; + } + err = jffs2_scan_inode_node(c, jeb, (void *)node, ofs); if (err) return err; + ofs += PAD(je32_to_cpu(node->totlen)); break; case JFFS2_NODETYPE_DIRENT: - err = jffs2_scan_dirent_node(c, jeb, &ofs); + if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) { + buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); + D1(printk(KERN_DEBUG "Fewer than %d bytes (dirent node) left to end of buf. Reading 0x%x at 0x%08x\n", + je32_to_cpu(node->totlen), buf_len, ofs)); + err = jffs2_fill_scan_buf(c, buf, ofs, buf_len); + if (err) + return err; + buf_ofs = ofs; + node = (void *)buf; + } + err = jffs2_scan_dirent_node(c, jeb, (void *)node, ofs); if (err) return err; + ofs += PAD(je32_to_cpu(node->totlen)); break; case JFFS2_NODETYPE_CLEANMARKER: - if (node.totlen != c->cleanmarker_size) { + D1(printk(KERN_DEBUG "CLEANMARKER node found at 0x%08x\n", ofs)); + if (je32_to_cpu(node->totlen) != c->cleanmarker_size) { printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x\n", - ofs, node.totlen, c->cleanmarker_size); + ofs, je32_to_cpu(node->totlen), c->cleanmarker_size); DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node))); + ofs += PAD(sizeof(struct jffs2_unknown_node)); } else if (jeb->first_node) { printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x, not first node in block (0x%08x)\n", ofs, jeb->offset); DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node))); ofs += PAD(sizeof(struct jffs2_unknown_node)); - continue; } else { struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref(); if (!marker_ref) { @@ -369,45 +540,45 @@ } marker_ref->next_in_ino = NULL; marker_ref->next_phys = NULL; - marker_ref->flash_offset = ofs; - marker_ref->totlen = sizeof(struct jffs2_unknown_node); + marker_ref->flash_offset = ofs | REF_NORMAL; + marker_ref->totlen = c->cleanmarker_size; jeb->first_node = jeb->last_node = marker_ref; - USED_SPACE(PAD(sizeof(struct jffs2_unknown_node))); + USED_SPACE(PAD(c->cleanmarker_size)); + ofs += PAD(c->cleanmarker_size); } - ofs += PAD(sizeof(struct jffs2_unknown_node)); break; case JFFS2_NODETYPE_PADDING: - DIRTY_SPACE(PAD(node.totlen)); - ofs += PAD(node.totlen); + DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); + ofs += PAD(je32_to_cpu(node->totlen)); break; default: - switch (node.nodetype & JFFS2_COMPAT_MASK) { + switch (je16_to_cpu(node->nodetype) & JFFS2_COMPAT_MASK) { case JFFS2_FEATURE_ROCOMPAT: - printk(KERN_NOTICE "Read-only compatible feature node (0x%04x) found at offset 0x%08x\n", node.nodetype, ofs); + printk(KERN_NOTICE "Read-only compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs); c->flags |= JFFS2_SB_FLAG_RO; if (!(jffs2_is_readonly(c))) return -EROFS; - DIRTY_SPACE(PAD(node.totlen)); - ofs += PAD(node.totlen); + DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); + ofs += PAD(je32_to_cpu(node->totlen)); break; case JFFS2_FEATURE_INCOMPAT: - printk(KERN_NOTICE "Incompatible feature node (0x%04x) found at offset 0x%08x\n", node.nodetype, ofs); + printk(KERN_NOTICE "Incompatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs); return -EINVAL; case JFFS2_FEATURE_RWCOMPAT_DELETE: - D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", node.nodetype, ofs)); - DIRTY_SPACE(PAD(node.totlen)); - ofs += PAD(node.totlen); + D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs)); + DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); + ofs += PAD(je32_to_cpu(node->totlen)); break; case JFFS2_FEATURE_RWCOMPAT_COPY: - D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", node.nodetype, ofs)); - USED_SPACE(PAD(node.totlen)); - ofs += PAD(node.totlen); + D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs)); + USED_SPACE(PAD(je32_to_cpu(node->totlen))); + ofs += PAD(je32_to_cpu(node->totlen)); break; } } @@ -417,64 +588,30 @@ D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, used 0x%08x\n", jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); - if (jeb->used_size == PAD(sizeof(struct jffs2_unknown_node)) && + /* mark_node_obsolete can add to wasted !! */ + if (jeb->wasted_size) { + jeb->dirty_size += jeb->wasted_size; + c->dirty_size += jeb->wasted_size; + c->wasted_size -= jeb->wasted_size; + jeb->wasted_size = 0; + } + + if ((jeb->used_size + jeb->unchecked_size) == PAD(c->cleanmarker_size) && !jeb->first_node->next_in_ino && !jeb->dirty_size) return BLK_STATE_CLEANMARKER; - else if (jeb->used_size > c->sector_size - (2*sizeof(struct jffs2_raw_inode))) + /* move blocks with max 4 byte dirty space to cleanlist */ + else if (!ISDIRTY(c->sector_size - (jeb->used_size + jeb->unchecked_size))) { + c->dirty_size -= jeb->dirty_size; + c->wasted_size += jeb->dirty_size; + jeb->wasted_size += jeb->dirty_size; + jeb->dirty_size = 0; return BLK_STATE_CLEAN; - else if (jeb->used_size) + } else if (jeb->used_size || jeb->unchecked_size) return BLK_STATE_PARTDIRTY; else return BLK_STATE_ALLDIRTY; } -/* We're pointing at the first empty word on the flash. Scan and account for the whole dirty region */ -static int jffs2_scan_empty(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t *startofs, int *noise) -{ - uint32_t *buf; - uint32_t scanlen = (jeb->offset + c->sector_size) - *startofs; - uint32_t curofs = *startofs; - - buf = kmalloc(min((uint32_t)PAGE_SIZE, scanlen), GFP_KERNEL); - if (!buf) { - printk(KERN_WARNING "Scan buffer allocation failed\n"); - return -ENOMEM; - } - while(scanlen) { - size_t retlen; - int ret, i; - - ret = jffs2_flash_read(c, curofs, min((uint32_t)PAGE_SIZE, scanlen), &retlen, (char *)buf); - if (ret) { - D1(printk(KERN_WARNING "jffs2_scan_empty(): Read 0x%x bytes at 0x%08x returned %d\n", min((uint32_t)PAGE_SIZE, scanlen), curofs, ret)); - kfree(buf); - return ret; - } - if (retlen < 4) { - D1(printk(KERN_WARNING "Eep. too few bytes read in scan_empty()\n")); - kfree(buf); - return -EIO; - } - for (i=0; i<(retlen / 4); i++) { - if (buf[i] != 0xffffffff) { - curofs += i*4; - noisy_printk(noise, "jffs2_scan_empty(): Empty block at 0x%08x ends at 0x%08x (with 0x%08x)! Marking dirty\n", *startofs, curofs, buf[i]); - DIRTY_SPACE(curofs - (*startofs)); - *startofs = curofs; - kfree(buf); - return 0; - } - } - scanlen -= retlen&~3; - curofs += retlen&~3; - } - - D1(printk(KERN_DEBUG "Empty flash detected from 0x%08x to 0x%08x\n", *startofs, curofs)); - kfree(buf); - *startofs = curofs; - return 0; -} - static struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino) { struct jffs2_inode_cache *ic; @@ -489,13 +626,7 @@ return NULL; } memset(ic, 0, sizeof(*ic)); - ic->scan = kmalloc(sizeof(struct jffs2_scan_info), GFP_KERNEL); - if (!ic->scan) { - printk(KERN_NOTICE "jffs2_scan_make_inode_cache(): allocation of scan info for inode cache failed\n"); - jffs2_free_inode_cache(ic); - return NULL; - } - memset(ic->scan, 0, sizeof(*ic->scan)); + ic->ino = ino; ic->nodes = (void *)ic; jffs2_add_ino_cache(c, ic); @@ -504,116 +635,58 @@ return ic; } -static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t *ofs) +static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, + struct jffs2_raw_inode *ri, uint32_t ofs) { struct jffs2_raw_node_ref *raw; - struct jffs2_full_dnode *fn; - struct jffs2_tmp_dnode_info *tn, **tn_list; struct jffs2_inode_cache *ic; - struct jffs2_raw_inode ri; - uint32_t crc; - uint16_t oldnodetype; - int ret; - size_t retlen; + uint32_t ino = je32_to_cpu(ri->ino); - D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", *ofs)); + D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", ofs)); - ret = jffs2_flash_read(c, *ofs, sizeof(ri), &retlen, (char *)&ri); - if (ret) { - printk(KERN_NOTICE "jffs2_scan_inode_node(): Read error at 0x%08x: %d\n", *ofs, ret); - return ret; - } - if (retlen != sizeof(ri)) { - printk(KERN_NOTICE "Short read: 0x%x bytes at 0x%08x instead of requested %x\n", - retlen, *ofs, sizeof(ri)); - return -EIO; - } - - /* We sort of assume that the node was accurate when it was - first written to the medium :) */ - oldnodetype = ri.nodetype; - ri.nodetype |= JFFS2_NODE_ACCURATE; - crc = crc32(0, &ri, sizeof(ri)-8); - ri.nodetype = oldnodetype; - - if(crc != ri.node_crc) { - printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", - *ofs, ri.node_crc, crc); - /* FIXME: Why do we believe totlen? */ - DIRTY_SPACE(4); - *ofs += 4; - return 0; - } - /* There was a bug where we wrote hole nodes out with csize/dsize - swapped. Deal with it */ - if (ri.compr == JFFS2_COMPR_ZERO && !ri.dsize && ri.csize) { - ri.dsize = ri.csize; - ri.csize = 0; - } - - if (ri.csize) { - /* Check data CRC too */ - unsigned char *dbuf; - uint32_t crc; - - dbuf = kmalloc(PAGE_CACHE_SIZE, GFP_KERNEL); - if (!dbuf) { - printk(KERN_NOTICE "jffs2_scan_inode_node(): allocation of temporary data buffer for CRC check failed\n"); - return -ENOMEM; - } - ret = jffs2_flash_read(c, *ofs+sizeof(ri), ri.csize, &retlen, dbuf); - if (ret) { - printk(KERN_NOTICE "jffs2_scan_inode_node(): Read error at 0x%08x: %d\n", *ofs+sizeof(ri), ret); - kfree(dbuf); - return ret; - } - if (retlen != ri.csize) { - printk(KERN_NOTICE "Short read: 0x%x bytes at 0x%08x instead of requested %x\n", - retlen, *ofs+ sizeof(ri), ri.csize); - kfree(dbuf); - return -EIO; - } - crc = crc32(0, dbuf, ri.csize); - kfree(dbuf); - if (crc != ri.data_crc) { - printk(KERN_NOTICE "jffs2_scan_inode_node(): Data CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", - *ofs, ri.data_crc, crc); - DIRTY_SPACE(PAD(ri.totlen)); - *ofs += PAD(ri.totlen); - return 0; - } - } + /* We do very little here now. Just check the ino# to which we should attribute + this node; we can do all the CRC checking etc. later. There's a tradeoff here -- + we used to scan the flash once only, reading everything we want from it into + memory, then building all our in-core data structures and freeing the extra + information. Now we allow the first part of the mount to complete a lot quicker, + but we have to go _back_ to the flash in order to finish the CRC checking, etc. + Which means that the _full_ amount of time to get to proper write mode with GC + operational may actually be _longer_ than before. Sucks to be me. */ - /* Wheee. It worked */ raw = jffs2_alloc_raw_node_ref(); if (!raw) { printk(KERN_NOTICE "jffs2_scan_inode_node(): allocation of node reference failed\n"); return -ENOMEM; } - tn = jffs2_alloc_tmp_dnode_info(); - if (!tn) { - jffs2_free_raw_node_ref(raw); - return -ENOMEM; - } - fn = jffs2_alloc_full_dnode(); - if (!fn) { - jffs2_free_tmp_dnode_info(tn); - jffs2_free_raw_node_ref(raw); - return -ENOMEM; - } - ic = jffs2_scan_make_ino_cache(c, ri.ino); + + ic = jffs2_get_ino_cache(c, ino); if (!ic) { - jffs2_free_full_dnode(fn); - jffs2_free_tmp_dnode_info(tn); - jffs2_free_raw_node_ref(raw); - return -ENOMEM; + /* Inocache get failed. Either we read a bogus ino# or it's just genuinely the + first node we found for this inode. Do a CRC check to protect against the former + case */ + uint32_t crc = crc32(0, ri, sizeof(*ri)-8); + + if (crc != je32_to_cpu(ri->node_crc)) { + printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", + ofs, je32_to_cpu(ri->node_crc), crc); + /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */ + DIRTY_SPACE(PAD(je32_to_cpu(ri->totlen))); + return 0; + } + ic = jffs2_scan_make_ino_cache(c, ino); + if (!ic) { + jffs2_free_raw_node_ref(raw); + return -ENOMEM; + } } - /* Build the data structures and file them for later */ - raw->flash_offset = *ofs; - raw->totlen = PAD(ri.totlen); + /* Wheee. It worked */ + + raw->flash_offset = ofs | REF_UNCHECKED; + raw->totlen = PAD(je32_to_cpu(ri->totlen)); raw->next_phys = NULL; raw->next_in_ino = ic->nodes; + ic->nodes = raw; if (!jeb->first_node) jeb->first_node = raw; @@ -622,146 +695,56 @@ jeb->last_node = raw; D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n", - ri.ino, ri.version, ri.offset, ri.offset+ri.dsize)); + je32_to_cpu(ri->ino), je32_to_cpu(ri->version), + je32_to_cpu(ri->offset), + je32_to_cpu(ri->offset)+je32_to_cpu(ri->dsize))); - pseudo_random += ri.version; + pseudo_random += je32_to_cpu(ri->version); - for (tn_list = &ic->scan->tmpnodes; *tn_list; tn_list = &((*tn_list)->next)) { - if ((*tn_list)->version < ri.version) - continue; - if ((*tn_list)->version > ri.version) - break; - /* Wheee. We've found another instance of the same version number. - We should obsolete one of them. - */ - D1(printk(KERN_DEBUG "Duplicate version %d found in ino #%u. Previous one is at 0x%08x\n", ri.version, ic->ino, (*tn_list)->fn->raw->flash_offset &~3)); - if (!jeb->used_size) { - D1(printk(KERN_DEBUG "No valid nodes yet found in this eraseblock 0x%08x, so obsoleting the new instance at 0x%08x\n", - jeb->offset, raw->flash_offset & ~3)); - ri.nodetype &= ~JFFS2_NODE_ACCURATE; - /* Perhaps we could also mark it as such on the medium. Maybe later */ - } - break; - } - - if (ri.nodetype & JFFS2_NODE_ACCURATE) { - - /* Only do fraglist truncation in pass1 for S_IFREG inodes */ - if (S_ISREG(ri.mode) && ic->scan->version < ri.version) { - ic->scan->version = ri.version; - ic->scan->isize = ri.isize; - } - - memset(fn,0,sizeof(*fn)); - - fn->ofs = ri.offset; - fn->size = ri.dsize; - fn->frags = 0; - fn->raw = raw; - - tn->next = NULL; - tn->fn = fn; - tn->version = ri.version; - - USED_SPACE(PAD(ri.totlen)); - - /* No need to scan from the beginning of the list again. - We can start from tn_list instead (Thanks Jocke) */ - jffs2_add_tn_to_list(tn, tn_list); - - /* Make sure the one we just added is the _last_ in the list - with this version number, so the older ones get obsoleted */ - while (tn->next && tn->next->version == tn->version) { - - D1(printk(KERN_DEBUG "Shifting new node at 0x%08x after other node at 0x%08x for version %d in list\n", - fn->raw->flash_offset&~3, tn->next->fn->raw->flash_offset &~3, ri.version)); - - if(tn->fn != fn) - BUG(); - tn->fn = tn->next->fn; - tn->next->fn = fn; - tn = tn->next; - } - } else { - jffs2_free_full_dnode(fn); - jffs2_free_tmp_dnode_info(tn); - raw->flash_offset |= 1; - DIRTY_SPACE(PAD(ri.totlen)); - } - *ofs += PAD(ri.totlen); + UNCHECKED_SPACE(PAD(je32_to_cpu(ri->totlen))); return 0; } -static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t *ofs) +static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, + struct jffs2_raw_dirent *rd, uint32_t ofs) { struct jffs2_raw_node_ref *raw; struct jffs2_full_dirent *fd; struct jffs2_inode_cache *ic; - struct jffs2_raw_dirent rd; - uint16_t oldnodetype; - int ret; uint32_t crc; - size_t retlen; - D1(printk(KERN_DEBUG "jffs2_scan_dirent_node(): Node at 0x%08x\n", *ofs)); + D1(printk(KERN_DEBUG "jffs2_scan_dirent_node(): Node at 0x%08x\n", ofs)); - ret = jffs2_flash_read(c, *ofs, sizeof(rd), &retlen, (char *)&rd); - if (ret) { - printk(KERN_NOTICE "jffs2_scan_dirent_node(): Read error at 0x%08x: %d\n", *ofs, ret); - return ret; - } - if (retlen != sizeof(rd)) { - printk(KERN_NOTICE "Short read: 0x%x bytes at 0x%08x instead of requested %x\n", - retlen, *ofs, sizeof(rd)); - return -EIO; - } - - /* We sort of assume that the node was accurate when it was - first written to the medium :) */ - oldnodetype = rd.nodetype; - rd.nodetype |= JFFS2_NODE_ACCURATE; - crc = crc32(0, &rd, sizeof(rd)-8); - rd.nodetype = oldnodetype; + /* We don't get here unless the node is still valid, so we don't have to + mask in the ACCURATE bit any more. */ + crc = crc32(0, rd, sizeof(*rd)-8); - if (crc != rd.node_crc) { + if (crc != je32_to_cpu(rd->node_crc)) { printk(KERN_NOTICE "jffs2_scan_dirent_node(): Node CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", - *ofs, rd.node_crc, crc); - /* FIXME: Why do we believe totlen? */ - DIRTY_SPACE(4); - *ofs += 4; + ofs, je32_to_cpu(rd->node_crc), crc); + /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */ + DIRTY_SPACE(PAD(je32_to_cpu(rd->totlen))); return 0; } - pseudo_random += rd.version; + pseudo_random += je32_to_cpu(rd->version); - fd = jffs2_alloc_full_dirent(rd.nsize+1); + fd = jffs2_alloc_full_dirent(rd->nsize+1); if (!fd) { return -ENOMEM; } - ret = jffs2_flash_read(c, *ofs + sizeof(rd), rd.nsize, &retlen, &fd->name[0]); - if (ret) { - jffs2_free_full_dirent(fd); - printk(KERN_NOTICE "jffs2_scan_dirent_node(): Read error at 0x%08x: %d\n", - *ofs + sizeof(rd), ret); - return ret; - } - if (retlen != rd.nsize) { - jffs2_free_full_dirent(fd); - printk(KERN_NOTICE "Short read: 0x%x bytes at 0x%08x instead of requested %x\n", - retlen, *ofs + sizeof(rd), rd.nsize); - return -EIO; - } + memcpy(&fd->name, rd->name, rd->nsize); + fd->name[rd->nsize] = 0; - crc = crc32(0, fd->name, rd.nsize); - if (crc != rd.name_crc) { + crc = crc32(0, fd->name, rd->nsize); + if (crc != je32_to_cpu(rd->name_crc)) { printk(KERN_NOTICE "jffs2_scan_dirent_node(): Name CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", - *ofs, rd.name_crc, crc); - fd->name[rd.nsize]=0; - D1(printk(KERN_NOTICE "Name for which CRC failed is (now) '%s', ino #%d\n", fd->name, rd.ino)); + ofs, je32_to_cpu(rd->name_crc), crc); + D1(printk(KERN_NOTICE "Name for which CRC failed is (now) '%s', ino #%d\n", fd->name, je32_to_cpu(rd->ino))); jffs2_free_full_dirent(fd); /* FIXME: Why do we believe totlen? */ - DIRTY_SPACE(PAD(rd.totlen)); - *ofs += PAD(rd.totlen); + /* We believe totlen because the CRC on the node _header_ was OK, just the name failed. */ + DIRTY_SPACE(PAD(je32_to_cpu(rd->totlen))); return 0; } raw = jffs2_alloc_raw_node_ref(); @@ -770,15 +753,15 @@ printk(KERN_NOTICE "jffs2_scan_dirent_node(): allocation of node reference failed\n"); return -ENOMEM; } - ic = jffs2_scan_make_ino_cache(c, rd.pino); + ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(rd->pino)); if (!ic) { jffs2_free_full_dirent(fd); jffs2_free_raw_node_ref(raw); return -ENOMEM; } - raw->totlen = PAD(rd.totlen); - raw->flash_offset = *ofs; + raw->totlen = PAD(je32_to_cpu(rd->totlen)); + raw->flash_offset = ofs | REF_PRISTINE; raw->next_phys = NULL; raw->next_in_ino = ic->nodes; ic->nodes = raw; @@ -788,22 +771,15 @@ jeb->last_node->next_phys = raw; jeb->last_node = raw; - if (rd.nodetype & JFFS2_NODE_ACCURATE) { - fd->raw = raw; - fd->next = NULL; - fd->version = rd.version; - fd->ino = rd.ino; - fd->name[rd.nsize]=0; - fd->nhash = full_name_hash(fd->name, rd.nsize); - fd->type = rd.type; - USED_SPACE(PAD(rd.totlen)); - jffs2_add_fd_to_list(c, fd, &ic->scan->dents); - } else { - raw->flash_offset |= 1; - jffs2_free_full_dirent(fd); - DIRTY_SPACE(PAD(rd.totlen)); - } - *ofs += PAD(rd.totlen); + fd->raw = raw; + fd->next = NULL; + fd->version = je32_to_cpu(rd->version); + fd->ino = je32_to_cpu(rd->ino); + fd->nhash = full_name_hash(fd->name, rd->nsize); + fd->type = rd->type; + USED_SPACE(PAD(je32_to_cpu(rd->totlen))); + jffs2_add_fd_to_list(c, fd, &ic->scan_dents); + return 0; } diff -Nru a/fs/jffs2/super.c b/fs/jffs2/super.c --- a/fs/jffs2/super.c Fri Nov 22 13:41:18 2002 +++ b/fs/jffs2/super.c Fri Nov 22 13:41:18 2002 @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: super.c,v 1.73 2002/07/23 17:00:45 dwmw2 Exp $ + * $Id: super.c,v 1.74 2002/11/12 09:37:39 dwmw2 Exp $ * */ diff -Nru a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c --- a/fs/jffs2/wbuf.c Fri Nov 22 13:41:18 2002 +++ b/fs/jffs2/wbuf.c Fri Nov 22 13:41:18 2002 @@ -7,8 +7,9 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: wbuf.c,v 1.12 2002/05/20 14:56:39 dwmw2 Exp $ - * -- with the NAND definitions added back pending MTD update for 2.5. + * $Id: wbuf.c,v 1.20 2002/11/12 11:33:02 dwmw2 Exp $ + * + some of the dependencies on later MTD NAND code temporarily reverted. + * */ #include @@ -16,17 +17,22 @@ #include #include #include +#include #include "nodelist.h" /* FIXME duplicated defines in wbuf.c and nand.c * Constants for out of band layout */ +#ifndef NAND_BADBLOCK_POS +#define NAND_BADBLOCK_POS 5 +#endif +#ifndef NAND_JFFS2_OOB_BADBPOS #define NAND_JFFS2_OOB_BADBPOS 5 #define NAND_JFFS2_OOB8_FSDAPOS 6 #define NAND_JFFS2_OOB16_FSDAPOS 8 #define NAND_JFFS2_OOB8_FSDALEN 2 #define NAND_JFFS2_OOB16_FSDALEN 8 - +#endif /* max. erase failures before we mark a block bad */ #define MAX_ERASE_FAILURES 5 @@ -88,18 +94,40 @@ struct jffs2_sb_info *c = (struct jffs2_sb_info *) data; D1(printk(KERN_DEBUG "jffs2_wbuf_process() entered\n")); - - if (!down_trylock(&c->alloc_sem)) { - D1(printk (KERN_DEBUG "jffs2_wbuf_process() alloc_sem got\n")); - if(!c->nextblock || (c->nextblock->free_size < (c->wbuf_pagesize - c->wbuf_len))) - jffs2_flush_wbuf(c, 1); /* pad only */ - else - jffs2_flush_wbuf(c, 2); /* pad and adjust nextblock */ - up(&c->alloc_sem); - } else { + /* Check, if the timer is active again */ + if (timer_pending (&c->wbuf_timer)) { + D1(printk (KERN_DEBUG "Nothing to do, timer is active again\n")); + return; + } + + if (down_trylock(&c->alloc_sem)) { + /* If someone else has the alloc_sem, they're about to + write anyway. So no need to waste space by + padding */ D1(printk (KERN_DEBUG "jffs2_wbuf_process() alloc_sem already occupied\n")); + return; } + + D1(printk (KERN_DEBUG "jffs2_wbuf_process() alloc_sem got\n")); + + if (!c->nextblock) { + D1(printk(KERN_DEBUG "jffs2_wbuf_process(): nextblock NULL, nothing to do\n")); + if (c->wbuf_len) { + printk(KERN_WARNING "jffs2_wbuf_process(): c->wbuf_len is 0x%03x but nextblock is NULL!\n", c->wbuf_len); + up(&c->alloc_sem); + BUG(); + } + return; + } + + + /* if !c->nextblock then the tail will have got flushed from + jffs2_do_reserve_space() anyway. */ + if(c->nextblock) + jffs2_flush_wbuf(c, 2); /* pad and adjust nextblock */ + + up(&c->alloc_sem); } @@ -112,7 +140,12 @@ { int ret; size_t retlen; - + + /* Nothing to do if not NAND flash. In particular, we shouldn't + del_timer() the timer we never initialised. */ + if (jffs2_can_mark_obsolete(c)) + return 0; + if (!down_trylock(&c->alloc_sem)) { up(&c->alloc_sem); printk(KERN_CRIT "jffs2_flush_wbuf() called with alloc_sem not locked!\n"); @@ -136,10 +169,10 @@ if ( c->wbuf_len + sizeof(struct jffs2_unknown_node) < c->wbuf_pagesize) { struct jffs2_unknown_node *padnode = (void *)(c->wbuf + c->wbuf_len); - padnode->magic = JFFS2_MAGIC_BITMASK; - padnode->nodetype = JFFS2_NODETYPE_PADDING; - padnode->totlen = c->wbuf_pagesize - c->wbuf_len; - padnode->hdr_crc = crc32(0, padnode, sizeof(*padnode)-4); + padnode->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + padnode->nodetype = cpu_to_je16(JFFS2_NODETYPE_PADDING); + padnode->totlen = cpu_to_je32(c->wbuf_pagesize - c->wbuf_len); + padnode->hdr_crc = cpu_to_je32(crc32(0, padnode, sizeof(*padnode)-4)); } } /* else jffs2_flash_writev has actually filled in the rest of the @@ -175,10 +208,20 @@ spin_lock_bh(&c->erase_completion_lock); if (!c->nextblock) BUG(); - if (c->nextblock->free_size < (c->wbuf_pagesize - c->wbuf_len)) + /* wbuf_pagesize - wbuf_len is the amount of space that's to be + padded. If there is less free space in the block than that, + something screwed up */ + if (c->nextblock->free_size < (c->wbuf_pagesize - c->wbuf_len)) { + printk(KERN_CRIT "jffs2_flush_wbuf(): Accounting error. wbuf at 0x%08x has 0x%03x bytes, 0x%03x left.\n", + c->wbuf_ofs, c->wbuf_len, c->wbuf_pagesize-c->wbuf_len); + printk(KERN_CRIT "jffs2_flush_wbuf(): But free_size for block at 0x%08x is only 0x%08x\n", + c->nextblock->offset, c->nextblock->free_size); BUG(); + } c->nextblock->free_size -= (c->wbuf_pagesize - c->wbuf_len); - c->nextblock->dirty_size += (c->wbuf_pagesize - c->wbuf_len); + c->free_size -= (c->wbuf_pagesize - c->wbuf_len); + c->nextblock->wasted_size += (c->wbuf_pagesize - c->wbuf_len); + c->wasted_size += (c->wbuf_pagesize - c->wbuf_len); spin_unlock_bh(&c->erase_completion_lock); } @@ -415,28 +458,30 @@ int ret; /* Read flash */ - ret = c->mtd->read(c->mtd, ofs, len, retlen, buf); + if (!jffs2_can_mark_obsolete(c)) { + ret = c->mtd->read(c->mtd, ofs, len, retlen, buf); - if (!jffs2_can_mark_obsolete(c) && (ret == -EIO) && (*retlen == len) ) { - printk(KERN_WARNING "mtd->read(0x%x bytes from 0x%llx) returned ECC error\n", len, ofs); - /* - * We have the raw data without ECC correction in the buffer, maybe - * we are lucky and all data or parts are correct. We check the node. - * If data are corrupted node check will sort it out. - * We keep this block, it will fail on write or erase and the we - * mark it bad. Or should we do that now? But we should give him a chance. - * Maybe we had a system crash or power loss before the ecc write or - * a erase was completed. - * So we return success. :) - */ - ret = 0; - } + if ( (ret == -EIO) && (*retlen == len) ) { + printk(KERN_WARNING "mtd->read(0x%x bytes from 0x%llx) returned ECC error\n", len, ofs); + /* + * We have the raw data without ECC correction in the buffer, maybe + * we are lucky and all data or parts are correct. We check the node. + * If data are corrupted node check will sort it out. + * We keep this block, it will fail on write or erase and the we + * mark it bad. Or should we do that now? But we should give him a chance. + * Maybe we had a system crash or power loss before the ecc write or + * a erase was completed. + * So we return success. :) + */ + ret = 0; + } + } else + return c->mtd->read(c->mtd, ofs, len, retlen, buf); /* if no writebuffer available or write buffer empty, return */ if (!c->wbuf_pagesize || !c->wbuf_len) return ret; - /* if we read in a different block, return */ if ( (ofs & ~(c->sector_size-1)) != (c->wbuf_ofs & ~(c->sector_size-1)) ) return ret; @@ -478,7 +523,7 @@ switch(c->mtd->ecctype) { case MTD_ECC_SW: fsdata_pos = (c->wbuf_pagesize == 256) ? NAND_JFFS2_OOB8_FSDAPOS : NAND_JFFS2_OOB16_FSDAPOS; - badblock_pos = NAND_JFFS2_OOB_BADBPOS; + badblock_pos = NAND_BADBLOCK_POS; break; default: D1(printk(KERN_WARNING "jffs2_write_oob_empty(): Invalid ECC type\n")); @@ -486,7 +531,7 @@ } /* allocate a buffer for all oob data in this sector */ - len = oob_size * (c->sector_size/c->mtd->oobblock); + len = 4 * oob_size; buf = kmalloc(len, GFP_KERNEL); if (!buf) { printk(KERN_NOTICE "jffs2_check_oob_empty(): allocation of temporary data buffer for oob check failed\n"); @@ -510,7 +555,7 @@ } /* Special check for first two pages */ - for (page = 0; page < 2; page += oob_size) { + for (page = 0; page < 2 * oob_size; page += oob_size) { /* Check for bad block marker */ if (buf[page+badblock_pos] != 0xff) { D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Bad or failed block at %08x\n",jeb->offset)); @@ -563,7 +608,7 @@ case MTD_ECC_SW: fsdata_pos = (c->wbuf_pagesize == 256) ? NAND_JFFS2_OOB8_FSDAPOS : NAND_JFFS2_OOB16_FSDAPOS; fsdata_len = (c->wbuf_pagesize == 256) ? NAND_JFFS2_OOB8_FSDALEN : NAND_JFFS2_OOB16_FSDALEN; - badblock_pos = NAND_JFFS2_OOB_BADBPOS; + badblock_pos = NAND_BADBLOCK_POS; break; default: D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Invalid ECC type\n")); @@ -598,9 +643,9 @@ return 3; } - n.magic = JFFS2_MAGIC_BITMASK; - n.nodetype = JFFS2_NODETYPE_CLEANMARKER; - n.totlen = 8; + n.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + n.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER); + n.totlen = cpu_to_je32(8); p = (unsigned char *) &n; for (i = 0; i < fsdata_len; i++) { @@ -630,9 +675,9 @@ return -EINVAL; } - n.magic = JFFS2_MAGIC_BITMASK; - n.nodetype = JFFS2_NODETYPE_CLEANMARKER; - n.totlen = 8; + n.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + n.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER); + n.totlen = cpu_to_je32(8); ret = jffs2_flash_write_oob(c, jeb->offset + fsdata_pos, fsdata_len, &retlen, (unsigned char *)&n); @@ -661,7 +706,7 @@ switch(c->mtd->ecctype) { case MTD_ECC_SW: - badblock_pos = NAND_JFFS2_OOB_BADBPOS; + badblock_pos = NAND_BADBLOCK_POS; break; default: D1(printk(KERN_WARNING "jffs2_nand_read_failcnt(): Invalid ECC type\n")); @@ -702,7 +747,7 @@ switch(c->mtd->ecctype) { case MTD_ECC_SW: - pos = NAND_JFFS2_OOB_BADBPOS; + pos = NAND_BADBLOCK_POS; break; default: D1(printk(KERN_WARNING "jffs2_write_nand_badblock(): Invalid ECC type\n")); diff -Nru a/fs/jffs2/write.c b/fs/jffs2/write.c --- a/fs/jffs2/write.c Fri Nov 22 13:41:19 2002 +++ b/fs/jffs2/write.c Fri Nov 22 13:41:19 2002 @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: write.c,v 1.56 2002/07/10 14:05:16 dwmw2 Exp $ + * $Id: write.c,v 1.60 2002/09/09 16:29:08 dwmw2 Exp $ * */ @@ -15,6 +15,7 @@ #include #include #include +#include #include #include "nodelist.h" @@ -34,16 +35,22 @@ f->inocache = ic; f->inocache->nlink = 1; f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; - f->inocache->ino = ri->ino = ++c->highest_ino; - D1(printk(KERN_DEBUG "jffs2_do_new_inode(): Assigned ino# %d\n", ri->ino)); + f->inocache->ino = ++c->highest_ino; + f->inocache->state = INO_STATE_PRESENT; + + ri->ino = cpu_to_je32(f->inocache->ino); + + D1(printk(KERN_DEBUG "jffs2_do_new_inode(): Assigned ino# %d\n", f->inocache->ino)); jffs2_add_ino_cache(c, f->inocache); - ri->magic = JFFS2_MAGIC_BITMASK; - ri->nodetype = JFFS2_NODETYPE_INODE; - ri->totlen = PAD(sizeof(*ri)); - ri->hdr_crc = crc32(0, ri, sizeof(struct jffs2_unknown_node)-4); - ri->mode = mode; - f->highest_version = ri->version = 1; + ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); + ri->totlen = cpu_to_je32(PAD(sizeof(*ri))); + ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); + ri->mode = cpu_to_je32(mode); + + f->highest_version = 1; + ri->version = cpu_to_je32(f->highest_version); return 0; } @@ -88,7 +95,7 @@ int ret; unsigned long cnt = 2; - D1(if(ri->hdr_crc != crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)) { + D1(if(je32_to_cpu(ri->hdr_crc) != crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)) { printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dnode()\n"); BUG(); } @@ -100,8 +107,8 @@ writecheck(c, flash_ofs); - if (ri->totlen != sizeof(*ri) + datalen) { - printk(KERN_WARNING "jffs2_write_dnode: ri->totlen (0x%08x) != sizeof(*ri) (0x%08x) + datalen (0x%08x)\n", ri->totlen, sizeof(*ri), datalen); + if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) { + printk(KERN_WARNING "jffs2_write_dnode: ri->totlen (0x%08x) != sizeof(*ri) (0x%08x) + datalen (0x%08x)\n", je32_to_cpu(ri->totlen), sizeof(*ri), datalen); } raw = jffs2_alloc_raw_node_ref(); if (!raw) @@ -113,11 +120,11 @@ return ERR_PTR(-ENOMEM); } raw->flash_offset = flash_ofs; - raw->totlen = PAD(ri->totlen); + raw->totlen = PAD(sizeof(*ri)+datalen); raw->next_phys = NULL; - fn->ofs = ri->offset; - fn->size = ri->dsize; + fn->ofs = je32_to_cpu(ri->offset); + fn->size = je32_to_cpu(ri->dsize); fn->frags = 0; fn->raw = raw; @@ -140,7 +147,8 @@ seem corrupted, in which case the scan would skip over any node we write before the original intended end of this node */ - jffs2_add_physical_node_ref(c, raw, sizeof(*ri)+datalen, 1); + raw->flash_offset |= REF_OBSOLETE; + jffs2_add_physical_node_ref(c, raw); jffs2_mark_node_obsolete(c, raw); } else { printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); @@ -154,13 +162,20 @@ return ERR_PTR(ret?ret:-EIO); } /* Mark the space used */ - jffs2_add_physical_node_ref(c, raw, retlen, 0); + if (datalen == PAGE_CACHE_SIZE) + raw->flash_offset |= REF_PRISTINE; + else + raw->flash_offset |= REF_NORMAL; + jffs2_add_physical_node_ref(c, raw); /* Link into per-inode list */ raw->next_in_ino = f->inocache->nodes; f->inocache->nodes = raw; - D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n", flash_ofs, ri->dsize, ri->csize, ri->node_crc, ri->data_crc, ri->totlen)); + D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n", + flash_ofs, je32_to_cpu(ri->dsize), je32_to_cpu(ri->csize), + je32_to_cpu(ri->node_crc), je32_to_cpu(ri->data_crc), + je32_to_cpu(ri->totlen))); if (writelen) *writelen = retlen; @@ -176,10 +191,12 @@ struct iovec vecs[2]; int ret; - D1(printk(KERN_DEBUG "jffs2_write_dirent(ino #%u, name at *0x%p \"%s\"->ino #%u, name_crc 0x%08x)\n", rd->pino, name, name, rd->ino, rd->name_crc)); + D1(printk(KERN_DEBUG "jffs2_write_dirent(ino #%u, name at *0x%p \"%s\"->ino #%u, name_crc 0x%08x)\n", + je32_to_cpu(rd->pino), name, name, je32_to_cpu(rd->ino), + je32_to_cpu(rd->name_crc))); writecheck(c, flash_ofs); - D1(if(rd->hdr_crc != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) { + D1(if(je32_to_cpu(rd->hdr_crc) != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) { printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dirent()\n"); BUG(); } @@ -201,13 +218,13 @@ return ERR_PTR(-ENOMEM); } raw->flash_offset = flash_ofs; - raw->totlen = PAD(rd->totlen); + raw->totlen = PAD(sizeof(*rd)+namelen); raw->next_in_ino = f->inocache->nodes; f->inocache->nodes = raw; raw->next_phys = NULL; - fd->version = rd->version; - fd->ino = rd->ino; + fd->version = je32_to_cpu(rd->version); + fd->ino = je32_to_cpu(rd->ino); fd->nhash = full_name_hash(name, strlen(name)); fd->type = rd->type; memcpy(fd->name, name, namelen); @@ -220,7 +237,8 @@ sizeof(*rd)+namelen, flash_ofs, ret, retlen); /* Mark the space as dirtied */ if (retlen) { - jffs2_add_physical_node_ref(c, raw, sizeof(*rd)+namelen, 1); + raw->flash_offset |= REF_OBSOLETE; + jffs2_add_physical_node_ref(c, raw); jffs2_mark_node_obsolete(c, raw); } else { printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); @@ -234,7 +252,8 @@ return ERR_PTR(ret?ret:-EIO); } /* Mark the space used */ - jffs2_add_physical_node_ref(c, raw, retlen, 0); + raw->flash_offset |= REF_PRISTINE; + jffs2_add_physical_node_ref(c, raw); if (writelen) *writelen = retlen; @@ -289,20 +308,20 @@ that the comprbuf doesn't need to be kfree()d. */ - ri->magic = JFFS2_MAGIC_BITMASK; - ri->nodetype = JFFS2_NODETYPE_INODE; - ri->totlen = sizeof(*ri) + cdatalen; - ri->hdr_crc = crc32(0, ri, sizeof(struct jffs2_unknown_node)-4); - - ri->ino = f->inocache->ino; - ri->version = ++f->highest_version; - ri->isize = max(ri->isize, offset + datalen); - ri->offset = offset; - ri->csize = cdatalen; - ri->dsize = datalen; + ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); + ri->totlen = cpu_to_je32(sizeof(*ri) + cdatalen); + ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); + + ri->ino = cpu_to_je32(f->inocache->ino); + ri->version = cpu_to_je32(++f->highest_version); + ri->isize = cpu_to_je32(max(je32_to_cpu(ri->isize), offset + datalen)); + ri->offset = cpu_to_je32(offset); + ri->csize = cpu_to_je32(cdatalen); + ri->dsize = cpu_to_je32(datalen); ri->compr = comprtype; - ri->node_crc = crc32(0, ri, sizeof(*ri)-8); - ri->data_crc = crc32(0, comprbuf, cdatalen); + ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); + ri->data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen)); fn = jffs2_write_dnode(c, f, ri, comprbuf, cdatalen, phys_ofs, NULL); @@ -367,12 +386,13 @@ return ret; } - ri->data_crc = 0; - ri->node_crc = crc32(0, ri, sizeof(*ri)-8); + ri->data_crc = cpu_to_je32(0); + ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, &writtenlen); - D1(printk(KERN_DEBUG "jffs2_do_create created file with mode 0x%x\n", ri->mode)); + D1(printk(KERN_DEBUG "jffs2_do_create created file with mode 0x%x\n", + je32_to_cpu(ri->mode))); if (IS_ERR(fn)) { D1(printk(KERN_DEBUG "jffs2_write_dnode() failed\n")); @@ -413,19 +433,19 @@ down(&dir_f->sem); - rd->magic = JFFS2_MAGIC_BITMASK; - rd->nodetype = JFFS2_NODETYPE_DIRENT; - rd->totlen = sizeof(*rd) + namelen; - rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4); + rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); + rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); + rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); - rd->pino = dir_f->inocache->ino; - rd->version = ++dir_f->highest_version; + rd->pino = cpu_to_je32(dir_f->inocache->ino); + rd->version = cpu_to_je32(++dir_f->highest_version); rd->ino = ri->ino; rd->mctime = ri->ctime; rd->nsize = namelen; rd->type = DT_REG; - rd->node_crc = crc32(0, rd, sizeof(*rd)-8); - rd->name_crc = crc32(0, name, namelen); + rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); + rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, &writtenlen); @@ -471,19 +491,19 @@ down(&dir_f->sem); /* Build a deletion node */ - rd->magic = JFFS2_MAGIC_BITMASK; - rd->nodetype = JFFS2_NODETYPE_DIRENT; - rd->totlen = sizeof(*rd) + namelen; - rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4); - - rd->pino = dir_f->inocache->ino; - rd->version = ++dir_f->highest_version; - rd->ino = 0; - rd->mctime = get_seconds(); + rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); + rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); + rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); + + rd->pino = cpu_to_je32(dir_f->inocache->ino); + rd->version = cpu_to_je32(++dir_f->highest_version); + rd->ino = cpu_to_je32(0); + rd->mctime = cpu_to_je32(get_seconds()); rd->nsize = namelen; rd->type = DT_UNKNOWN; - rd->node_crc = crc32(0, rd, sizeof(*rd)-8); - rd->name_crc = crc32(0, name, namelen); + rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); + rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, NULL); @@ -498,7 +518,6 @@ /* File it. This will mark the old one obsolete. */ jffs2_add_fd_to_list(c, fd, &dir_f->dents); - jffs2_complete_reservation(c); up(&dir_f->sem); /* dead_f is NULL if this was a rename not a real unlink */ @@ -529,6 +548,8 @@ up(&dead_f->sem); } + jffs2_complete_reservation(c); + return 0; } @@ -553,21 +574,21 @@ down(&dir_f->sem); /* Build a deletion node */ - rd->magic = JFFS2_MAGIC_BITMASK; - rd->nodetype = JFFS2_NODETYPE_DIRENT; - rd->totlen = sizeof(*rd) + namelen; - rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4); - - rd->pino = dir_f->inocache->ino; - rd->version = ++dir_f->highest_version; - rd->ino = ino; - rd->mctime = get_seconds(); + rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); + rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); + rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); + + rd->pino = cpu_to_je32(dir_f->inocache->ino); + rd->version = cpu_to_je32(++dir_f->highest_version); + rd->ino = cpu_to_je32(ino); + rd->mctime = cpu_to_je32(get_seconds()); rd->nsize = namelen; rd->type = type; - rd->node_crc = crc32(0, rd, sizeof(*rd)-8); - rd->name_crc = crc32(0, name, namelen); + rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); + rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, NULL); diff -Nru a/fs/jffs2/writev.c b/fs/jffs2/writev.c --- a/fs/jffs2/writev.c Fri Nov 22 13:41:20 2002 +++ b/fs/jffs2/writev.c Fri Nov 22 13:41:20 2002 @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: writev.c,v 1.2 2002/05/20 14:56:39 dwmw2 Exp $ + * $Id: writev.c,v 1.3 2002/08/08 08:35:21 dwmw2 Exp $ * */ @@ -28,7 +28,7 @@ for (i=0; iwrite(mtd, to, vecs[i].iov_len, &thislen, vecs[i].iov_base); + ret = mtd->write(mtd, to, vecs[i].iov_len, &thislen, vecs[i].iov_base); totlen += thislen; if (ret || thislen != vecs[i].iov_len) break; diff -Nru a/fs/jfs/jfs_xattr.h b/fs/jfs/jfs_xattr.h --- a/fs/jfs/jfs_xattr.h Fri Nov 22 13:41:23 2002 +++ b/fs/jfs/jfs_xattr.h Fri Nov 22 13:41:23 2002 @@ -52,9 +52,9 @@ #define END_EALIST(ealist) \ ((struct jfs_ea *) (((char *) (ealist)) + EALIST_SIZE(ealist))) -extern int __jfs_setxattr(struct inode *, const char *, void *, size_t, - int); -extern int jfs_setxattr(struct dentry *, const char *, void *, size_t, +extern int __jfs_setxattr(struct inode *, const char *, const void *, size_t, + int); +extern int jfs_setxattr(struct dentry *, const char *, const void *, size_t, int); extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t); extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t); diff -Nru a/fs/jfs/namei.c b/fs/jfs/namei.c --- a/fs/jfs/namei.c Fri Nov 22 13:41:22 2002 +++ b/fs/jfs/namei.c Fri Nov 22 13:41:22 2002 @@ -1316,7 +1316,7 @@ * * FUNCTION: Create a special file (device) */ -int jfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev) +int jfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) { struct btstack btstack; struct component_name dname; diff -Nru a/fs/jfs/xattr.c b/fs/jfs/xattr.c --- a/fs/jfs/xattr.c Fri Nov 22 13:41:19 2002 +++ b/fs/jfs/xattr.c Fri Nov 22 13:41:19 2002 @@ -706,7 +706,7 @@ } static int can_set_xattr(struct inode *inode, const char *name, - void *value, size_t value_len) + const void *value, size_t value_len) { if (IS_RDONLY(inode)) return -EROFS; @@ -735,7 +735,7 @@ #endif } -int __jfs_setxattr(struct inode *inode, const char *name, void *value, +int __jfs_setxattr(struct inode *inode, const char *name, const void *value, size_t value_len, int flags) { struct jfs_ea_list *ealist; @@ -874,7 +874,7 @@ return rc; } -int jfs_setxattr(struct dentry *dentry, const char *name, void *value, +int jfs_setxattr(struct dentry *dentry, const char *name, const void *value, size_t value_len, int flags) { if (value == NULL) { /* empty EA, do not remove */ diff -Nru a/fs/libfs.c b/fs/libfs.c --- a/fs/libfs.c Fri Nov 22 13:41:17 2002 +++ b/fs/libfs.c Fri Nov 22 13:41:17 2002 @@ -70,7 +70,7 @@ while (n && p != &file->f_dentry->d_subdirs) { struct dentry *next; next = list_entry(p, struct dentry, d_child); - if (!list_empty(&next->d_hash) && next->d_inode) + if (!d_unhashed(next) && next->d_inode) n--; p = p->next; } @@ -127,7 +127,7 @@ for (p=q->next; p != &dentry->d_subdirs; p=p->next) { struct dentry *next; next = list_entry(p, struct dentry, d_child); - if (list_empty(&next->d_hash) || !next->d_inode) + if (d_unhashed(next) || !next->d_inode) continue; spin_unlock(&dcache_lock); @@ -322,4 +322,15 @@ inode->i_size = pos; set_page_dirty(page); return 0; +} + +/* + * Print device name (in decimal, hexadecimal or symbolic) + * Note: returns pointer to static data! + */ +const char * kdevname(kdev_t dev) +{ + static char buffer[32]; + sprintf(buffer, "%02x:%02x", major(dev), minor(dev)); + return buffer; } diff -Nru a/fs/locks.c b/fs/locks.c --- a/fs/locks.c Fri Nov 22 13:41:23 2002 +++ b/fs/locks.c Fri Nov 22 13:41:23 2002 @@ -297,11 +297,20 @@ return -EINVAL; } - if (((start += l->l_start) < 0) || (l->l_len < 0)) - return -EINVAL; + /* POSIX-1996 leaves the case l->l_len < 0 undefined; + POSIX-2001 defines it. */ + start += l->l_start; end = start + l->l_len - 1; + if (l->l_len < 0) { + end = start - 1; + start += l->l_len; + } + + if (start < 0) + return -EINVAL; if (l->l_len > 0 && end < 0) return -EOVERFLOW; + fl->fl_start = start; /* we record the absolute position */ fl->fl_end = end; if (l->l_len == 0) @@ -994,16 +1003,16 @@ } /** - * __get_lease - revoke all outstanding leases on file + * __break_lease - revoke all outstanding leases on file * @inode: the inode of the file to return * @mode: the open mode (read or write) * - * get_lease (inlined for speed) has checked there already + * break_lease (inlined for speed) has checked there already * is a lease on this file. Leases are broken on a call to open() * or truncate(). This function can sleep unless you * specified %O_NONBLOCK to your open(). */ -int __get_lease(struct inode *inode, unsigned int mode) +int __break_lease(struct inode *inode, unsigned int mode) { int error = 0, future; struct file_lock *new_fl, *flock; @@ -1766,7 +1775,7 @@ #else /* kdevname is a broken interface. but we expose it to userspace */ out += sprintf(out, "%d %s:%ld ", fl->fl_pid, - inode ? kdevname(to_kdev_t(inode->i_dev)) : "", + inode ? kdevname(to_kdev_t(inode->i_sb->s_dev)) : "", inode ? inode->i_ino : 0); #endif if (IS_POSIX(fl)) { diff -Nru a/fs/minix/namei.c b/fs/minix/namei.c --- a/fs/minix/namei.c Fri Nov 22 13:41:19 2002 +++ b/fs/minix/namei.c Fri Nov 22 13:41:19 2002 @@ -75,7 +75,7 @@ return NULL; } -static int minix_mknod(struct inode * dir, struct dentry *dentry, int mode, int rdev) +static int minix_mknod(struct inode * dir, struct dentry *dentry, int mode, dev_t rdev) { int error; struct inode * inode = minix_new_inode(dir, &error); diff -Nru a/fs/mpage.c b/fs/mpage.c --- a/fs/mpage.c Fri Nov 22 13:41:18 2002 +++ b/fs/mpage.c Fri Nov 22 13:41:18 2002 @@ -178,6 +178,7 @@ struct block_device *bdev = NULL; struct buffer_head bh; int length; + int fully_mapped = 1; if (page_has_buffers(page)) goto confused; @@ -194,6 +195,7 @@ } if (!buffer_mapped(&bh)) { + fully_mapped = 0; if (first_hole == blocks_per_page) first_hole = page_block; continue; @@ -220,6 +222,8 @@ unlock_page(page); goto out; } + } else if (fully_mapped) { + SetPageMappedToDisk(page); } /* @@ -614,12 +618,6 @@ bio = mpage_writepage(bio, page, get_block, &last_block_in_bio, &ret); } - if ((current->flags & PF_MEMALLOC) && - !PageActive(page) && PageLRU(page)) { - if (!pagevec_add(&pvec, page)) - pagevec_deactivate_inactive(&pvec); - page = NULL; - } if (ret || (--(wbc->nr_to_write) <= 0)) done = 1; if (wbc->nonblocking && bdi_write_congested(bdi)) { @@ -630,16 +628,13 @@ } else { unlock_page(page); } - - if (page) - page_cache_release(page); + page_cache_release(page); write_lock(&mapping->page_lock); } /* * Leave any remaining dirty pages on ->io_pages */ write_unlock(&mapping->page_lock); - pagevec_deactivate_inactive(&pvec); if (bio) mpage_bio_submit(WRITE, bio); return ret; diff -Nru a/fs/namei.c b/fs/namei.c --- a/fs/namei.c Fri Nov 22 13:41:18 2002 +++ b/fs/namei.c Fri Nov 22 13:41:18 2002 @@ -1183,7 +1183,7 @@ /* * Ensure there are no outstanding leases on the file. */ - error = get_lease(inode, flag); + error = break_lease(inode, flag); if (error) return error; @@ -1551,7 +1551,7 @@ if (atomic_read(&dentry->d_count) != 2) break; case 2: - list_del_init(&dentry->d_hash); + __d_drop(dentry); } spin_unlock(&dcache_lock); } diff -Nru a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c --- a/fs/ncpfs/dir.c Fri Nov 22 13:41:20 2002 +++ b/fs/ncpfs/dir.c Fri Nov 22 13:41:20 2002 @@ -42,7 +42,7 @@ static int ncp_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); static int ncp_mknod(struct inode * dir, struct dentry *dentry, - int mode, int rdev); + int mode, dev_t rdev); #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) extern int ncp_symlink(struct inode *, struct dentry *, const char *); #else @@ -883,7 +883,7 @@ } int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode, - int rdev, int attributes) + dev_t rdev, int attributes) { struct ncp_server *server = NCP_SERVER(dir); struct ncp_entry_info finfo; @@ -909,7 +909,7 @@ if (S_ISREG(mode) && (server->m.flags & NCP_MOUNT_EXTRAS) && (mode & S_IXUGO)) - attributes |= aSYSTEM; + attributes |= aSYSTEM | aSHARED; result = ncp_open_create_file_or_subdir(server, dir, __name, OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE, @@ -1169,7 +1169,7 @@ } static int ncp_mknod(struct inode * dir, struct dentry *dentry, - int mode, int rdev) + int mode, dev_t rdev) { if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) { DPRINTK(KERN_DEBUG "ncp_mknod: mode = 0%o\n", mode); diff -Nru a/fs/ncpfs/ncplib_kernel.h b/fs/ncpfs/ncplib_kernel.h --- a/fs/ncpfs/ncplib_kernel.h Fri Nov 22 13:41:18 2002 +++ b/fs/ncpfs/ncplib_kernel.h Fri Nov 22 13:41:18 2002 @@ -117,7 +117,7 @@ int ncp_dirhandle_free(struct ncp_server *, __u8 dirhandle); int ncp_create_new(struct inode *dir, struct dentry *dentry, - int mode, int rdev, int attributes); + int mode, dev_t rdev, int attributes); static inline int ncp_is_nfs_extras(struct ncp_server* server, unsigned int volnum) { #ifdef CONFIG_NCPFS_NFS_NS diff -Nru a/fs/nfs/dir.c b/fs/nfs/dir.c --- a/fs/nfs/dir.c Fri Nov 22 13:41:20 2002 +++ b/fs/nfs/dir.c Fri Nov 22 13:41:20 2002 @@ -45,7 +45,7 @@ static int nfs_unlink(struct inode *, struct dentry *); static int nfs_symlink(struct inode *, struct dentry *, const char *); static int nfs_link(struct dentry *, struct inode *, struct dentry *); -static int nfs_mknod(struct inode *, struct dentry *, int, int); +static int nfs_mknod(struct inode *, struct dentry *, int, dev_t); static int nfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); @@ -801,7 +801,8 @@ /* * See comments for nfs_proc_create regarding failed operations. */ -static int nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev) +static int +nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) { struct iattr attr; struct nfs_fattr fattr; @@ -1001,7 +1002,7 @@ return error; } if (!d_unhashed(dentry)) { - list_del_init(&dentry->d_hash); + __d_drop(dentry); need_rehash = 1; } spin_unlock(&dcache_lock); diff -Nru a/fs/nfs/inode.c b/fs/nfs/inode.c --- a/fs/nfs/inode.c Fri Nov 22 13:41:22 2002 +++ b/fs/nfs/inode.c Fri Nov 22 13:41:22 2002 @@ -656,9 +656,7 @@ goto out_no_inode; if (inode->i_state & I_NEW) { - __u64 new_size, new_mtime; - loff_t new_isize; - time_t new_atime; + struct nfs_inode *nfsi = NFS_I(inode); /* We set i_ino for the few things that still rely on it, * such as stat(2) */ @@ -686,24 +684,17 @@ else init_special_inode(inode, inode->i_mode, fattr->rdev); - new_mtime = fattr->mtime; - new_size = fattr->size; - new_isize = nfs_size_to_loff_t(fattr->size); - new_atime = nfs_time_to_secs(fattr->atime); - - NFS_READTIME(inode) = fattr->timestamp; - NFS_CACHE_CTIME(inode) = fattr->ctime; - inode->i_ctime.tv_sec = nfs_time_to_secs(fattr->ctime); - inode->i_ctime.tv_nsec = nfs_time_to_nsecs(fattr->ctime); - inode->i_atime.tv_sec = new_atime; - NFS_CACHE_MTIME(inode) = new_mtime; - inode->i_mtime.tv_sec = nfs_time_to_secs(new_mtime); - inode->i_mtime.tv_nsec = nfs_time_to_nsecs(new_mtime); - NFS_MTIME_UPDATE(inode) = fattr->timestamp; - NFS_CACHE_ISIZE(inode) = new_size; + nfsi->read_cache_jiffies = fattr->timestamp; + inode->i_atime = fattr->atime; + inode->i_mtime = fattr->mtime; + inode->i_ctime = fattr->ctime; + nfsi->read_cache_ctime = fattr->ctime; + nfsi->read_cache_mtime = fattr->mtime; + nfsi->cache_mtime_jiffies = fattr->timestamp; + nfsi->read_cache_isize = fattr->size; if (fattr->valid & NFS_ATTR_FATTR_V4) - NFS_CHANGE_ATTR(inode) = fattr->change_attr; - inode->i_size = new_isize; + nfsi->change_attr = fattr->change_attr; + inode->i_size = nfs_size_to_loff_t(fattr->size); inode->i_mode = fattr->mode; inode->i_nlink = fattr->nlink; inode->i_uid = fattr->uid; @@ -718,10 +709,10 @@ inode->i_blocks = fattr->du.nfs2.blocks; inode->i_blksize = fattr->du.nfs2.blocksize; } - NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode); - NFS_ATTRTIMEO_UPDATE(inode) = jiffies; - memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode))); - NFS_I(inode)->cache_access.cred = NULL; + nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); + nfsi->attrtimeo_timestamp = jiffies; + memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); + nfsi->cache_access.cred = NULL; unlock_new_inode(inode); } else @@ -787,9 +778,10 @@ * now to avoid invalidating the page cache. */ if (!(fattr.valid & NFS_ATTR_WCC)) { - fattr.pre_size = NFS_CACHE_ISIZE(inode); - fattr.pre_mtime = NFS_CACHE_MTIME(inode); - fattr.pre_ctime = NFS_CACHE_CTIME(inode); + struct nfs_inode *nfsi = NFS_I(inode); + fattr.pre_size = nfsi->read_cache_isize; + fattr.pre_mtime = nfsi->read_cache_mtime; + fattr.pre_ctime = nfsi->read_cache_ctime; fattr.valid |= NFS_ATTR_WCC; } /* Force an attribute cache update */ @@ -962,14 +954,18 @@ static inline int nfs_fattr_obsolete(struct inode *inode, struct nfs_fattr *fattr) { - s64 cdif; + struct nfs_inode *nfsi = NFS_I(inode); + long cdif; - if (time_after(jiffies, NFS_READTIME(inode)+NFS_ATTRTIMEO(inode))) + if (time_after(jiffies, nfsi->read_cache_jiffies + nfsi->attrtimeo)) goto out_valid; - if ((cdif = (s64)fattr->ctime - (s64)NFS_CACHE_CTIME(inode)) > 0) + cdif = fattr->ctime.tv_sec - nfsi->read_cache_ctime.tv_sec; + if (cdif == 0) + cdif = fattr->ctime.tv_nsec - nfsi->read_cache_ctime.tv_nsec; + if (cdif > 0) goto out_valid; /* Ugh... */ - if (cdif == 0 && fattr->size > NFS_CACHE_ISIZE(inode)) + if (cdif == 0 && fattr->size > nfsi->read_cache_isize) goto out_valid; return -1; out_valid: @@ -991,19 +987,20 @@ int __nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) { - __u64 new_size, new_mtime; + struct nfs_inode *nfsi = NFS_I(inode); + __u64 new_size; loff_t new_isize; - struct timespec new_atime; int invalid = 0; + int mtime_update = 0; dfprintk(VFS, "NFS: refresh_inode(%s/%ld ct=%d info=0x%x)\n", inode->i_sb->s_id, inode->i_ino, atomic_read(&inode->i_count), fattr->valid); - if (NFS_FILEID(inode) != fattr->fileid) { + if (nfsi->fileid != fattr->fileid) { printk(KERN_ERR "nfs_refresh_inode: inode number mismatch\n" "expected (%s/0x%Lx), got (%s/0x%Lx)\n", - inode->i_sb->s_id, (long long)NFS_FILEID(inode), + inode->i_sb->s_id, (long long)nfsi->fileid, inode->i_sb->s_id, (long long)fattr->fileid); goto out_err; } @@ -1017,12 +1014,9 @@ if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) goto out_changed; - new_mtime = fattr->mtime; new_size = fattr->size; new_isize = nfs_size_to_loff_t(fattr->size); - new_atime.tv_sec = nfs_time_to_secs(fattr->atime); - new_atime.tv_nsec = nfs_time_to_nsecs(fattr->atime); /* Avoid races */ if (nfs_fattr_obsolete(inode, fattr)) goto out_nochange; @@ -1030,13 +1024,13 @@ /* * Update the read time so we don't revalidate too often. */ - NFS_READTIME(inode) = fattr->timestamp; + nfsi->read_cache_jiffies = fattr->timestamp; /* * Note: NFS_CACHE_ISIZE(inode) reflects the state of the cache. * NOT inode->i_size!!! */ - if (NFS_CACHE_ISIZE(inode) != new_size) { + if (nfsi->read_cache_isize != new_size) { #ifdef NFS_DEBUG_VERBOSE printk(KERN_DEBUG "NFS: isize change on %s/%ld\n", inode->i_sb->s_id, inode->i_ino); #endif @@ -1048,15 +1042,16 @@ * can change this value in VFS without requiring a * cache revalidation. */ - if (NFS_CACHE_MTIME(inode) != new_mtime) { + if (!timespec_equal(&nfsi->read_cache_mtime, &fattr->mtime)) { #ifdef NFS_DEBUG_VERBOSE printk(KERN_DEBUG "NFS: mtime change on %s/%ld\n", inode->i_sb->s_id, inode->i_ino); #endif invalid = 1; + mtime_update = 1; } if ((fattr->valid & NFS_ATTR_FATTR_V4) - && NFS_CHANGE_ATTR(inode) != fattr->change_attr) { + && nfsi->change_attr != fattr->change_attr) { #ifdef NFS_DEBUG_VERBOSE printk(KERN_DEBUG "NFS: change_attr change on %s/%ld\n", inode->i_sb->s_id, inode->i_ino); @@ -1070,12 +1065,12 @@ * operation, so there's no need to invalidate the caches. */ if ((fattr->valid & NFS_ATTR_PRE_CHANGE) - && NFS_CHANGE_ATTR(inode) == fattr->pre_change_attr) { + && nfsi->change_attr == fattr->pre_change_attr) { invalid = 0; } else if ((fattr->valid & NFS_ATTR_WCC) - && NFS_CACHE_ISIZE(inode) == fattr->pre_size - && NFS_CACHE_MTIME(inode) == fattr->pre_mtime) { + && nfsi->read_cache_isize == fattr->pre_size + && timespec_equal(&nfsi->read_cache_mtime, &fattr->pre_mtime)) { invalid = 0; } @@ -1086,21 +1081,18 @@ if (nfs_have_writebacks(inode) && new_isize < inode->i_size) new_isize = inode->i_size; - NFS_CACHE_CTIME(inode) = fattr->ctime; - inode->i_ctime.tv_sec = nfs_time_to_secs(fattr->ctime); - inode->i_ctime.tv_nsec = nfs_time_to_nsecs(fattr->ctime); - - inode->i_atime = new_atime; + nfsi->read_cache_ctime = fattr->ctime; + inode->i_ctime = fattr->ctime; + inode->i_atime = fattr->atime; - if (NFS_CACHE_MTIME(inode) != new_mtime) { + if (mtime_update) { if (invalid) - NFS_MTIME_UPDATE(inode) = fattr->timestamp; - NFS_CACHE_MTIME(inode) = new_mtime; - inode->i_mtime.tv_sec = nfs_time_to_secs(new_mtime); - inode->i_mtime.tv_nsec = nfs_time_to_nsecs(new_mtime); + nfsi->cache_mtime_jiffies = fattr->timestamp; + nfsi->read_cache_mtime = fattr->mtime; + inode->i_mtime = fattr->mtime; } - NFS_CACHE_ISIZE(inode) = new_size; + nfsi->read_cache_isize = new_size; inode->i_size = new_isize; if (inode->i_mode != fattr->mode || @@ -1114,7 +1106,7 @@ } if (fattr->valid & NFS_ATTR_FATTR_V4) - NFS_CHANGE_ATTR(inode) = fattr->change_attr; + nfsi->change_attr = fattr->change_attr; inode->i_mode = fattr->mode; inode->i_nlink = fattr->nlink; @@ -1134,20 +1126,20 @@ /* Update attrtimeo value */ if (invalid) { - NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode); - NFS_ATTRTIMEO_UPDATE(inode) = jiffies; + nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); + nfsi->attrtimeo_timestamp = jiffies; invalidate_inode_pages(inode->i_mapping); memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode))); - } else if (time_after(jiffies, NFS_ATTRTIMEO_UPDATE(inode)+NFS_ATTRTIMEO(inode))) { - if ((NFS_ATTRTIMEO(inode) <<= 1) > NFS_MAXATTRTIMEO(inode)) - NFS_ATTRTIMEO(inode) = NFS_MAXATTRTIMEO(inode); - NFS_ATTRTIMEO_UPDATE(inode) = jiffies; + } else if (time_after(jiffies, nfsi->attrtimeo_timestamp+nfsi->attrtimeo)) { + if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode)) + nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode); + nfsi->attrtimeo_timestamp = jiffies; } return 0; out_nochange: - if (!timespec_equal(&new_atime, &inode->i_atime)) - inode->i_atime = new_atime; + if (!timespec_equal(&fattr->atime, &inode->i_atime)) + inode->i_atime = fattr->atime; return 0; out_changed: /* diff -Nru a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c --- a/fs/nfs/nfs2xdr.c Fri Nov 22 13:41:19 2002 +++ b/fs/nfs/nfs2xdr.c Fri Nov 22 13:41:19 2002 @@ -86,10 +86,20 @@ } static inline u32* -xdr_decode_time(u32 *p, u64 *timep) +xdr_encode_time(u32 *p, struct timespec *timep) { - u64 tmp = (u64)ntohl(*p++) << 32; - *timep = tmp + (u64)ntohl(*p++); + *p++ = htonl(timep->tv_sec); + /* Convert nanoseconds into microseconds */ + *p++ = htonl(timep->tv_nsec / 1000); + return p; +} + +static inline u32* +xdr_decode_time(u32 *p, struct timespec *timep) +{ + timep->tv_sec = ntohl(*p++); + /* Convert microseconds into nanoseconds */ + timep->tv_nsec = ntohl(*p++) * 1000; return p; } @@ -131,16 +141,14 @@ SATTR(p, attr, ATTR_SIZE, ia_size); if (attr->ia_valid & (ATTR_ATIME|ATTR_ATIME_SET)) { - *p++ = htonl(attr->ia_atime.tv_sec); - *p++ = 0; + p = xdr_encode_time(p, &attr->ia_atime); } else { *p++ = ~(u32) 0; *p++ = ~(u32) 0; } if (attr->ia_valid & (ATTR_MTIME|ATTR_MTIME_SET)) { - *p++ = htonl(attr->ia_mtime.tv_sec); - *p++ = 0; + p = xdr_encode_time(p, &attr->ia_mtime); } else { *p++ = ~(u32) 0; *p++ = ~(u32) 0; diff -Nru a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c --- a/fs/nfs/nfs3xdr.c Fri Nov 22 13:41:23 2002 +++ b/fs/nfs/nfs3xdr.c Fri Nov 22 13:41:23 2002 @@ -128,26 +128,18 @@ * nanosecond field. */ static inline u32 * -xdr_encode_time(u32 *p, time_t time) +xdr_encode_time3(u32 *p, struct timespec *timep) { - *p++ = htonl(time); - *p++ = 0; + *p++ = htonl(timep->tv_sec); + *p++ = htonl(timep->tv_nsec); return p; } static inline u32 * -xdr_decode_time3(u32 *p, u64 *timep) +xdr_decode_time3(u32 *p, struct timespec *timep) { - u64 tmp = (u64)ntohl(*p++) << 32; - *timep = tmp + (u64)ntohl(*p++); - return p; -} - -static inline u32 * -xdr_encode_time3(u32 *p, u64 time) -{ - *p++ = htonl(time >> 32); - *p++ = htonl(time & 0xFFFFFFFF); + timep->tv_sec = ntohl(*p++); + timep->tv_nsec = ntohl(*p++); return p; } @@ -212,7 +204,7 @@ } if (attr->ia_valid & ATTR_ATIME_SET) { *p++ = xdr_two; - p = xdr_encode_time(p, attr->ia_atime.tv_sec); + p = xdr_encode_time3(p, &attr->ia_atime); } else if (attr->ia_valid & ATTR_ATIME) { *p++ = xdr_one; } else { @@ -220,7 +212,7 @@ } if (attr->ia_valid & ATTR_MTIME_SET) { *p++ = xdr_two; - p = xdr_encode_time(p, attr->ia_mtime.tv_sec); + p = xdr_encode_time3(p, &attr->ia_mtime); } else if (attr->ia_valid & ATTR_MTIME) { *p++ = xdr_one; } else { @@ -288,7 +280,7 @@ p = xdr_encode_sattr(p, args->sattr); *p++ = htonl(args->guard); if (args->guard) - p = xdr_encode_time3(p, args->guardtime); + p = xdr_encode_time3(p, &args->guardtime); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; } diff -Nru a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c --- a/fs/nfs/nfs4proc.c Fri Nov 22 13:41:22 2002 +++ b/fs/nfs/nfs4proc.c Fri Nov 22 13:41:22 2002 @@ -65,11 +65,6 @@ memset(cp, 0, sizeof(*cp)); cp->ops = ops; cp->server = server; - -#if NFS4_DEBUG - cp->taglen = strlen(tag); - cp->tag = tag; -#endif } static void @@ -373,6 +368,7 @@ BUG_ON(cp->flags); + open->op_client_state = cp->server->nfs4_state; open->op_share_access = flags & 3; open->op_opentype = (flags & O_CREAT) ? NFS4_OPEN_CREATE : NFS4_OPEN_NOCREATE; open->op_createmode = NFS4_CREATE_UNCHECKED; @@ -527,6 +523,10 @@ static void nfs4_setup_renew(struct nfs4_compound *cp) { + struct nfs4_client **client_state = GET_OP(cp, renew); + + *client_state = cp->server->nfs4_state; + OPNUM(cp) = OP_RENEW; cp->req_nops++; cp->renew_index = cp->req_nops; @@ -563,18 +563,19 @@ { struct nfs4_setclientid *setclientid = GET_OP(cp, setclientid); struct nfs_server *server = cp->server; - struct timeval tv; + struct timespec tv; u32 *p; - do_gettimeofday(&tv); - p = (u32 *)setclientid->sc_verifier; + tv = CURRENT_TIME; + p = (u32 *)setclientid->sc_verifier; *p++ = tv.tv_sec; - *p++ = tv.tv_usec; + *p++ = tv.tv_nsec; setclientid->sc_name = server->ip_addr; sprintf(setclientid->sc_netid, "udp"); sprintf(setclientid->sc_uaddr, "%s.%d.%d", server->ip_addr, port >> 8, port & 255); setclientid->sc_prog = program; setclientid->sc_cb_ident = 0; + setclientid->sc_state = server->nfs4_state; OPNUM(cp) = OP_SETCLIENTID; cp->req_nops++; @@ -583,6 +584,10 @@ static void nfs4_setup_setclientid_confirm(struct nfs4_compound *cp) { + struct nfs4_client **client_state = GET_OP(cp, setclientid_confirm); + + *client_state = cp->server->nfs4_state; + OPNUM(cp) = OP_SETCLIENTID_CONFIRM; cp->req_nops++; cp->renew_index = cp->req_nops; diff -Nru a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c --- a/fs/nfs/nfs4xdr.c Fri Nov 22 13:41:23 2002 +++ b/fs/nfs/nfs4xdr.c Fri Nov 22 13:41:23 2002 @@ -57,8 +57,6 @@ */ #define COOKIE_MAX 0x7fffffff -#define NFS4_CLIENTID(server) ((server)->nfs4_state->cl_clientid) - #define NFSDBG_FACILITY NFSDBG_XDR /* Mapping from NFS error code to "errno" error code. */ @@ -95,25 +93,22 @@ * task to translate them into Linux-specific versions which are more * consistent with the style used in NFSv2/v3... */ -#define ENCODE_HEAD \ - u32 *p; -#define ENCODE_TAIL \ - return 0 - #define WRITE32(n) *p++ = htonl(n) #define WRITE64(n) do { \ - *p++ = htonl((u32)((n) >> 32)); \ - *p++ = htonl((u32)(n)); \ + *p++ = htonl((uint32_t)((n) >> 32)); \ + *p++ = htonl((uint32_t)(n)); \ } while (0) #define WRITEMEM(ptr,nbytes) do { \ p = xdr_writemem(p, ptr, nbytes); \ } while (0) -#define RESERVE_SPACE(nbytes) do { BUG_ON(cp->p + XDR_QUADLEN(nbytes) > cp->end); p = cp->p; } while (0) -#define ADJUST_ARGS() cp->p = p +#define RESERVE_SPACE(nbytes) do { \ + p = xdr_reserve_space(xdr, nbytes); \ + BUG_ON(!p); \ +} while (0) static inline -u32 *xdr_writemem(u32 *p, const void *ptr, int nbytes) +uint32_t *xdr_writemem(uint32_t *p, const void *ptr, int nbytes) { int tmp = XDR_QUADLEN(nbytes); if (!tmp) @@ -146,18 +141,18 @@ } static int -encode_attrs(struct nfs4_compound *cp, struct iattr *iap) +encode_attrs(struct xdr_stream *xdr, struct iattr *iap) { char owner_name[256]; char owner_group[256]; int owner_namelen = 0; int owner_grouplen = 0; - u32 *q; + uint32_t *p; + uint32_t *q; int len; - u32 bmval0 = 0; - u32 bmval1 = 0; + uint32_t bmval0 = 0; + uint32_t bmval1 = 0; int status; - ENCODE_HEAD; /* * We reserve enough space to write the entire attribute buffer at once. @@ -240,8 +235,6 @@ WRITE32(NFS4_SET_TO_SERVER_TIME); } - ADJUST_ARGS(); - /* * Now we backfill the bitmap and the attribute buffer length. */ @@ -256,69 +249,63 @@ } static int -encode_access(struct nfs4_compound *cp, struct nfs4_access *access) +encode_access(struct xdr_stream *xdr, struct nfs4_access *access) { - ENCODE_HEAD; + uint32_t *p; RESERVE_SPACE(8); WRITE32(OP_ACCESS); WRITE32(access->ac_req_access); - ADJUST_ARGS(); - ENCODE_TAIL; + return 0; } static int -encode_close(struct nfs4_compound *cp, struct nfs4_close *close) +encode_close(struct xdr_stream *xdr, struct nfs4_close *close) { - ENCODE_HEAD; + uint32_t *p; RESERVE_SPACE(20); WRITE32(OP_CLOSE); WRITE32(close->cl_seqid); WRITEMEM(close->cl_stateid, sizeof(nfs4_stateid)); - ADJUST_ARGS(); - ENCODE_TAIL; + return 0; } static int -encode_commit(struct nfs4_compound *cp, struct nfs4_commit *commit) +encode_commit(struct xdr_stream *xdr, struct nfs4_commit *commit) { - ENCODE_HEAD; + uint32_t *p; RESERVE_SPACE(16); WRITE32(OP_COMMIT); WRITE64(commit->co_start); WRITE32(commit->co_len); - ADJUST_ARGS(); - ENCODE_TAIL; + return 0; } static int -encode_create(struct nfs4_compound *cp, struct nfs4_create *create) +encode_create(struct xdr_stream *xdr, struct nfs4_create *create) { - ENCODE_HEAD; + uint32_t *p; RESERVE_SPACE(8); WRITE32(OP_CREATE); WRITE32(create->cr_ftype); - ADJUST_ARGS(); switch (create->cr_ftype) { case NF4LNK: RESERVE_SPACE(4 + create->cr_textlen); WRITE32(create->cr_textlen); WRITEMEM(create->cr_text, create->cr_textlen); - ADJUST_ARGS(); break; case NF4BLK: case NF4CHR: RESERVE_SPACE(8); WRITE32(create->cr_specdata1); WRITE32(create->cr_specdata2); - ADJUST_ARGS(); break; default: @@ -328,74 +315,69 @@ RESERVE_SPACE(4 + create->cr_namelen); WRITE32(create->cr_namelen); WRITEMEM(create->cr_name, create->cr_namelen); - ADJUST_ARGS(); - return encode_attrs(cp, create->cr_attrs); + return encode_attrs(xdr, create->cr_attrs); } static int -encode_getattr(struct nfs4_compound *cp, struct nfs4_getattr *getattr) +encode_getattr(struct xdr_stream *xdr, struct nfs4_getattr *getattr) { - ENCODE_HEAD; + uint32_t *p; RESERVE_SPACE(16); WRITE32(OP_GETATTR); WRITE32(2); WRITE32(getattr->gt_bmval[0]); WRITE32(getattr->gt_bmval[1]); - ADJUST_ARGS(); - ENCODE_TAIL; + return 0; } static int -encode_getfh(struct nfs4_compound *cp) +encode_getfh(struct xdr_stream *xdr) { - ENCODE_HEAD; + uint32_t *p; RESERVE_SPACE(4); WRITE32(OP_GETFH); - ADJUST_ARGS(); - ENCODE_TAIL; + return 0; } static int -encode_link(struct nfs4_compound *cp, struct nfs4_link *link) +encode_link(struct xdr_stream *xdr, struct nfs4_link *link) { - ENCODE_HEAD; + uint32_t *p; RESERVE_SPACE(8 + link->ln_namelen); WRITE32(OP_LINK); WRITE32(link->ln_namelen); WRITEMEM(link->ln_name, link->ln_namelen); - ADJUST_ARGS(); - ENCODE_TAIL; + return 0; } static int -encode_lookup(struct nfs4_compound *cp, struct nfs4_lookup *lookup) +encode_lookup(struct xdr_stream *xdr, struct nfs4_lookup *lookup) { int len = lookup->lo_name->len; - ENCODE_HEAD; + uint32_t *p; RESERVE_SPACE(8 + len); WRITE32(OP_LOOKUP); WRITE32(len); WRITEMEM(lookup->lo_name->name, len); - ADJUST_ARGS(); - ENCODE_TAIL; + return 0; } static int -encode_open(struct nfs4_compound *cp, struct nfs4_open *open) +encode_open(struct xdr_stream *xdr, struct nfs4_open *open) { static int global_id = 0; int id = global_id++; int status; - ENCODE_HEAD; + uint32_t *p; /* seqid, share_access, share_deny, clientid, ownerlen, owner, opentype */ RESERVE_SPACE(52); @@ -403,24 +385,21 @@ WRITE32(0); /* seqid */ WRITE32(open->op_share_access); WRITE32(0); /* for us, share_deny== 0 always */ - WRITE64(NFS4_CLIENTID(cp->server)); + WRITE64(open->op_client_state->cl_clientid); WRITE32(4); WRITE32(id); WRITE32(open->op_opentype); - ADJUST_ARGS(); if (open->op_opentype == NFS4_OPEN_CREATE) { if (open->op_createmode == NFS4_CREATE_EXCLUSIVE) { RESERVE_SPACE(12); WRITE32(open->op_createmode); WRITEMEM(open->op_verifier, sizeof(nfs4_verifier)); - ADJUST_ARGS(); } else if (open->op_attrs) { RESERVE_SPACE(4); WRITE32(open->op_createmode); - ADJUST_ARGS(); - if ((status = encode_attrs(cp, open->op_attrs))) + if ((status = encode_attrs(xdr, open->op_attrs))) return status; } else { @@ -428,7 +407,6 @@ WRITE32(open->op_createmode); WRITE32(0); WRITE32(0); - ADJUST_ARGS(); } } @@ -436,15 +414,14 @@ WRITE32(NFS4_OPEN_CLAIM_NULL); WRITE32(open->op_name->len); WRITEMEM(open->op_name->name, open->op_name->len); - ADJUST_ARGS(); - ENCODE_TAIL; + return 0; } static int -encode_open_confirm(struct nfs4_compound *cp, struct nfs4_open_confirm *open_confirm) +encode_open_confirm(struct xdr_stream *xdr, struct nfs4_open_confirm *open_confirm) { - ENCODE_HEAD; + uint32_t *p; /* * Note: In this "stateless" implementation, the OPEN_CONFIRM @@ -454,44 +431,41 @@ WRITE32(OP_OPEN_CONFIRM); WRITEMEM(open_confirm->oc_stateid, sizeof(nfs4_stateid)); WRITE32(1); - ADJUST_ARGS(); - ENCODE_TAIL; + return 0; } static int -encode_putfh(struct nfs4_compound *cp, struct nfs4_putfh *putfh) +encode_putfh(struct xdr_stream *xdr, struct nfs4_putfh *putfh) { int len = putfh->pf_fhandle->size; - ENCODE_HEAD; + uint32_t *p; RESERVE_SPACE(8 + len); WRITE32(OP_PUTFH); WRITE32(len); WRITEMEM(putfh->pf_fhandle->data, len); - ADJUST_ARGS(); - ENCODE_TAIL; + return 0; } static int -encode_putrootfh(struct nfs4_compound *cp) +encode_putrootfh(struct xdr_stream *xdr) { - ENCODE_HEAD; + uint32_t *p; RESERVE_SPACE(4); WRITE32(OP_PUTROOTFH); - ADJUST_ARGS(); - ENCODE_TAIL; + return 0; } static int -encode_read(struct nfs4_compound *cp, struct nfs4_read *read, struct rpc_rqst *req) +encode_read(struct xdr_stream *xdr, struct nfs4_read *read, struct rpc_rqst *req) { struct rpc_auth *auth = req->rq_task->tk_auth; int replen; - ENCODE_HEAD; + uint32_t *p; RESERVE_SPACE(32); WRITE32(OP_READ); @@ -501,26 +475,24 @@ WRITE32(0); WRITE64(read->rd_offset); WRITE32(read->rd_length); - ADJUST_ARGS(); /* set up reply iovec * toplevel status + taglen + rescount + OP_PUTFH + status * + OP_READ + status + eof + datalen = 9 */ - replen = (RPC_REPHDRSIZE + auth->au_rslack + 9 + XDR_QUADLEN(cp->taglen)) << 2; - req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); + replen = (RPC_REPHDRSIZE + auth->au_rslack + 9) << 2; xdr_inline_pages(&req->rq_rcv_buf, replen, read->rd_pages, read->rd_pgbase, read->rd_length); - ENCODE_TAIL; + return 0; } static int -encode_readdir(struct nfs4_compound *cp, struct nfs4_readdir *readdir, struct rpc_rqst *req) +encode_readdir(struct xdr_stream *xdr, struct nfs4_readdir *readdir, struct rpc_rqst *req) { struct rpc_auth *auth = req->rq_task->tk_auth; int replen; - ENCODE_HEAD; + uint32_t *p; RESERVE_SPACE(40); WRITE32(OP_READDIR); @@ -531,135 +503,124 @@ WRITE32(2); WRITE32(readdir->rd_bmval[0]); WRITE32(readdir->rd_bmval[1]); - ADJUST_ARGS(); /* set up reply iovec * toplevel_status + taglen + rescount + OP_PUTFH + status * + OP_READDIR + status + verifer(2) = 9 */ - replen = (RPC_REPHDRSIZE + auth->au_rslack + 9 + XDR_QUADLEN(cp->taglen)) << 2; - req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); + replen = (RPC_REPHDRSIZE + auth->au_rslack + 9) << 2; xdr_inline_pages(&req->rq_rcv_buf, replen, readdir->rd_pages, readdir->rd_pgbase, readdir->rd_count); - ENCODE_TAIL; + return 0; } static int -encode_readlink(struct nfs4_compound *cp, struct nfs4_readlink *readlink, struct rpc_rqst *req) +encode_readlink(struct xdr_stream *xdr, struct nfs4_readlink *readlink, struct rpc_rqst *req) { struct rpc_auth *auth = req->rq_task->tk_auth; int replen; - ENCODE_HEAD; + uint32_t *p; RESERVE_SPACE(4); WRITE32(OP_READLINK); - ADJUST_ARGS(); /* set up reply iovec * toplevel_status + taglen + rescount + OP_PUTFH + status * + OP_READLINK + status = 7 */ - replen = (RPC_REPHDRSIZE + auth->au_rslack + 7 + XDR_QUADLEN(cp->taglen)) << 2; - req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); + replen = (RPC_REPHDRSIZE + auth->au_rslack + 7) << 2; xdr_inline_pages(&req->rq_rcv_buf, replen, readlink->rl_pages, 0, readlink->rl_count); - ENCODE_TAIL; + return 0; } static int -encode_remove(struct nfs4_compound *cp, struct nfs4_remove *remove) +encode_remove(struct xdr_stream *xdr, struct nfs4_remove *remove) { - ENCODE_HEAD; + uint32_t *p; RESERVE_SPACE(8 + remove->rm_namelen); WRITE32(OP_REMOVE); WRITE32(remove->rm_namelen); WRITEMEM(remove->rm_name, remove->rm_namelen); - ADJUST_ARGS(); - ENCODE_TAIL; + return 0; } static int -encode_rename(struct nfs4_compound *cp, struct nfs4_rename *rename) +encode_rename(struct xdr_stream *xdr, struct nfs4_rename *rename) { - ENCODE_HEAD; + uint32_t *p; RESERVE_SPACE(8 + rename->rn_oldnamelen); WRITE32(OP_RENAME); WRITE32(rename->rn_oldnamelen); WRITEMEM(rename->rn_oldname, rename->rn_oldnamelen); - ADJUST_ARGS(); RESERVE_SPACE(8 + rename->rn_newnamelen); WRITE32(rename->rn_newnamelen); WRITEMEM(rename->rn_newname, rename->rn_newnamelen); - ADJUST_ARGS(); - ENCODE_TAIL; + return 0; } static int -encode_renew(struct nfs4_compound *cp) +encode_renew(struct xdr_stream *xdr, struct nfs4_client *client_stateid) { - ENCODE_HEAD; + uint32_t *p; RESERVE_SPACE(12); WRITE32(OP_RENEW); - WRITE64(NFS4_CLIENTID(cp->server)); - ADJUST_ARGS(); + WRITE64(client_stateid->cl_clientid); - ENCODE_TAIL; + return 0; } static int -encode_restorefh(struct nfs4_compound *cp) +encode_restorefh(struct xdr_stream *xdr) { - ENCODE_HEAD; + uint32_t *p; RESERVE_SPACE(4); WRITE32(OP_RESTOREFH); - ADJUST_ARGS(); - ENCODE_TAIL; + return 0; } static int -encode_savefh(struct nfs4_compound *cp) +encode_savefh(struct xdr_stream *xdr) { - ENCODE_HEAD; + uint32_t *p; RESERVE_SPACE(4); WRITE32(OP_SAVEFH); - ADJUST_ARGS(); - ENCODE_TAIL; + return 0; } static int -encode_setattr(struct nfs4_compound *cp, struct nfs4_setattr *setattr) +encode_setattr(struct xdr_stream *xdr, struct nfs4_setattr *setattr) { int status; - ENCODE_HEAD; + uint32_t *p; RESERVE_SPACE(20); WRITE32(OP_SETATTR); WRITEMEM(setattr->st_stateid, sizeof(nfs4_stateid)); - ADJUST_ARGS(); - if ((status = encode_attrs(cp, setattr->st_iap))) + if ((status = encode_attrs(xdr, setattr->st_iap))) return status; - ENCODE_TAIL; + return 0; } static int -encode_setclientid(struct nfs4_compound *cp, struct nfs4_setclientid *setclientid) +encode_setclientid(struct xdr_stream *xdr, struct nfs4_setclientid *setclientid) { - u32 total_len; - u32 len1, len2, len3; - ENCODE_HEAD; + uint32_t total_len; + uint32_t len1, len2, len3; + uint32_t *p; len1 = strlen(setclientid->sc_name); len2 = strlen(setclientid->sc_netid); @@ -678,30 +639,28 @@ WRITE32(len3); WRITEMEM(setclientid->sc_uaddr, len3); WRITE32(setclientid->sc_cb_ident); - ADJUST_ARGS(); - ENCODE_TAIL; + return 0; } static int -encode_setclientid_confirm(struct nfs4_compound *cp) +encode_setclientid_confirm(struct xdr_stream *xdr, struct nfs4_client *client_state) { - ENCODE_HEAD; + uint32_t *p; RESERVE_SPACE(12 + sizeof(nfs4_verifier)); WRITE32(OP_SETCLIENTID_CONFIRM); - WRITE64(cp->server->nfs4_state->cl_clientid); - WRITEMEM(cp->server->nfs4_state->cl_confirm,sizeof(nfs4_verifier)); - ADJUST_ARGS(); + WRITE64(client_state->cl_clientid); + WRITEMEM(client_state->cl_confirm,sizeof(nfs4_verifier)); - ENCODE_TAIL; + return 0; } static int -encode_write(struct nfs4_compound *cp, struct nfs4_write *write, struct rpc_rqst *req) +encode_write(struct xdr_stream *xdr, struct nfs4_write *write, struct rpc_rqst *req) { struct xdr_buf *sndbuf = &req->rq_snd_buf; - ENCODE_HEAD; + uint32_t *p; RESERVE_SPACE(36); WRITE32(OP_WRITE); @@ -712,20 +671,18 @@ WRITE64(write->wr_offset); WRITE32(write->wr_stable_how); WRITE32(write->wr_len); - ADJUST_ARGS(); - sndbuf->len = xdr_adjust_iovec(sndbuf->head, p); xdr_encode_pages(sndbuf, write->wr_pages, write->wr_pgbase, write->wr_len); - ENCODE_TAIL; + return 0; } /* FIXME: this sucks */ static int -encode_compound(struct nfs4_compound *cp, struct rpc_rqst *req) +encode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqst *req) { int i, status = 0; - ENCODE_HEAD; + uint32_t *p; dprintk("encode_compound: tag=%.*s\n", (int)cp->taglen, cp->tag); @@ -734,81 +691,80 @@ WRITEMEM(cp->tag, cp->taglen); WRITE32(NFS4_MINOR_VERSION); WRITE32(cp->req_nops); - ADJUST_ARGS(); for (i = 0; i < cp->req_nops; i++) { switch (cp->ops[i].opnum) { case OP_ACCESS: - status = encode_access(cp, &cp->ops[i].u.access); + status = encode_access(xdr, &cp->ops[i].u.access); break; case OP_CLOSE: - status = encode_close(cp, &cp->ops[i].u.close); + status = encode_close(xdr, &cp->ops[i].u.close); break; case OP_COMMIT: - status = encode_commit(cp, &cp->ops[i].u.commit); + status = encode_commit(xdr, &cp->ops[i].u.commit); break; case OP_CREATE: - status = encode_create(cp, &cp->ops[i].u.create); + status = encode_create(xdr, &cp->ops[i].u.create); break; case OP_GETATTR: - status = encode_getattr(cp, &cp->ops[i].u.getattr); + status = encode_getattr(xdr, &cp->ops[i].u.getattr); break; case OP_GETFH: - status = encode_getfh(cp); + status = encode_getfh(xdr); break; case OP_LINK: - status = encode_link(cp, &cp->ops[i].u.link); + status = encode_link(xdr, &cp->ops[i].u.link); break; case OP_LOOKUP: - status = encode_lookup(cp, &cp->ops[i].u.lookup); + status = encode_lookup(xdr, &cp->ops[i].u.lookup); break; case OP_OPEN: - status = encode_open(cp, &cp->ops[i].u.open); + status = encode_open(xdr, &cp->ops[i].u.open); break; case OP_OPEN_CONFIRM: - status = encode_open_confirm(cp, &cp->ops[i].u.open_confirm); + status = encode_open_confirm(xdr, &cp->ops[i].u.open_confirm); break; case OP_PUTFH: - status = encode_putfh(cp, &cp->ops[i].u.putfh); + status = encode_putfh(xdr, &cp->ops[i].u.putfh); break; case OP_PUTROOTFH: - status = encode_putrootfh(cp); + status = encode_putrootfh(xdr); break; case OP_READ: - status = encode_read(cp, &cp->ops[i].u.read, req); + status = encode_read(xdr, &cp->ops[i].u.read, req); break; case OP_READDIR: - status = encode_readdir(cp, &cp->ops[i].u.readdir, req); + status = encode_readdir(xdr, &cp->ops[i].u.readdir, req); break; case OP_READLINK: - status = encode_readlink(cp, &cp->ops[i].u.readlink, req); + status = encode_readlink(xdr, &cp->ops[i].u.readlink, req); break; case OP_REMOVE: - status = encode_remove(cp, &cp->ops[i].u.remove); + status = encode_remove(xdr, &cp->ops[i].u.remove); break; case OP_RENAME: - status = encode_rename(cp, &cp->ops[i].u.rename); + status = encode_rename(xdr, &cp->ops[i].u.rename); break; case OP_RENEW: - status = encode_renew(cp); + status = encode_renew(xdr, cp->ops[i].u.renew); break; case OP_RESTOREFH: - status = encode_restorefh(cp); + status = encode_restorefh(xdr); break; case OP_SAVEFH: - status = encode_savefh(cp); + status = encode_savefh(xdr); break; case OP_SETATTR: - status = encode_setattr(cp, &cp->ops[i].u.setattr); + status = encode_setattr(xdr, &cp->ops[i].u.setattr); break; case OP_SETCLIENTID: - status = encode_setclientid(cp, &cp->ops[i].u.setclientid); + status = encode_setclientid(xdr, &cp->ops[i].u.setclientid); break; case OP_SETCLIENTID_CONFIRM: - status = encode_setclientid_confirm(cp); + status = encode_setclientid_confirm(xdr, cp->ops[i].u.setclientid_confirm); break; case OP_WRITE: - status = encode_write(cp, &cp->ops[i].u.write, req); + status = encode_write(xdr, &cp->ops[i].u.write, req); break; default: BUG(); @@ -817,7 +773,7 @@ return status; } - ENCODE_TAIL; + return 0; } /* * END OF "GENERIC" ENCODE ROUTINES. @@ -828,18 +784,14 @@ * Encode COMPOUND argument */ static int -nfs4_xdr_enc_compound(struct rpc_rqst *req, u32 *p, struct nfs4_compound *cp) +nfs4_xdr_enc_compound(struct rpc_rqst *req, uint32_t *p, struct nfs4_compound *cp) { + struct xdr_stream xdr; int status; - struct xdr_buf *sndbuf = &req->rq_snd_buf; - cp->p = p; - cp->end = (u32 *) ((char *)req->rq_svec[0].iov_base + req->rq_svec[0].iov_len); - status = encode_compound(cp, req); + xdr_init_encode(&xdr, &req->rq_snd_buf, p); + status = encode_compound(&xdr, cp, req); cp->timestamp = jiffies; - - if (!status && !sndbuf->page_len) - req->rq_slen = xdr_adjust_iovec(sndbuf->head, cp->p); return status; } @@ -854,9 +806,6 @@ * task to translate them into Linux-specific versions which are more * consistent with the style used in NFSv2/v3... */ -#define DECODE_HEAD \ - u32 *p; \ - int status #define DECODE_TAIL \ status = 0; \ out: \ @@ -873,19 +822,21 @@ } while (0) #define READTIME(x) do { \ p++; \ - (x) = (u64)ntohl(*p++) << 32; \ - (x) |= ntohl(*p++); \ + (x.tv_sec) = ntohl(*p++); \ + (x.tv_nsec) = ntohl(*p++); \ } while (0) #define COPYMEM(x,nbytes) do { \ memcpy((x), p, nbytes); \ p += XDR_QUADLEN(nbytes); \ } while (0) -#define READ_BUF(nbytes) do { \ - if (nbytes > (u32)((char *)cp->end - (char *)cp->p)) \ - goto xdr_error; \ - p = cp->p; \ - cp->p += XDR_QUADLEN(nbytes); \ +#define READ_BUF(nbytes) do { \ + p = xdr_inline_decode(xdr, nbytes); \ + if (!p) { \ + printk(KERN_WARNING "%s: reply buffer overflowed in line %d.", \ + __FUNCTION__, __LINE__); \ + return -EIO; \ + } \ } while (0) /* @@ -893,7 +844,7 @@ * upcall gets in... */ static int -decode_uid(char *p, u32 len, uid_t *uid) +decode_uid(char *p, uint32_t len, uid_t *uid) { *uid = -2; return 0; @@ -904,82 +855,78 @@ * upcall gets in... */ static int -decode_gid(char *p, u32 len, gid_t *gid) +decode_gid(char *p, uint32_t len, gid_t *gid) { *gid = -2; return 0; } static int -decode_change_info(struct nfs4_compound *cp, struct nfs4_change_info *cinfo) +decode_change_info(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) { - DECODE_HEAD; + uint32_t *p; READ_BUF(20); READ32(cinfo->atomic); READ64(cinfo->before); READ64(cinfo->after); - - DECODE_TAIL; + return 0; } static int -decode_access(struct nfs4_compound *cp, int nfserr, struct nfs4_access *access) +decode_access(struct xdr_stream *xdr, int nfserr, struct nfs4_access *access) { - u32 supp, acc; - DECODE_HEAD; + uint32_t *p; + uint32_t supp, acc; if (!nfserr) { READ_BUF(8); READ32(supp); READ32(acc); - status = -EIO; if ((supp & ~access->ac_req_access) || (acc & ~supp)) { printk(KERN_NOTICE "NFS: server returned bad bits in access call!\n"); - goto out; + return -EIO; } *access->ac_resp_supported = supp; *access->ac_resp_access = acc; } - - DECODE_TAIL; + return 0; } static int -decode_close(struct nfs4_compound *cp, int nfserr, struct nfs4_close *close) +decode_close(struct xdr_stream *xdr, int nfserr, struct nfs4_close *close) { - DECODE_HEAD; + uint32_t *p; if (!nfserr) { READ_BUF(sizeof(nfs4_stateid)); COPYMEM(close->cl_stateid, sizeof(nfs4_stateid)); } - - DECODE_TAIL; + return 0; } static int -decode_commit(struct nfs4_compound *cp, int nfserr, struct nfs4_commit *commit) +decode_commit(struct xdr_stream *xdr, int nfserr, struct nfs4_commit *commit) { - DECODE_HEAD; + uint32_t *p; if (!nfserr) { READ_BUF(8); COPYMEM(commit->co_verifier->verifier, 8); } - - DECODE_TAIL; + return 0; } static int -decode_create(struct nfs4_compound *cp, int nfserr, struct nfs4_create *create) +decode_create(struct xdr_stream *xdr, int nfserr, struct nfs4_create *create) { - u32 bmlen; - DECODE_HEAD; + uint32_t *p; + uint32_t bmlen; + int status; if (!nfserr) { - if ((status = decode_change_info(cp, create->cr_cinfo))) + if ((status = decode_change_info(xdr, create->cr_cinfo))) goto out; READ_BUF(4); READ32(bmlen); @@ -991,27 +938,28 @@ DECODE_TAIL; } -extern u32 nfs4_fattr_bitmap[2]; -extern u32 nfs4_fsinfo_bitmap[2]; -extern u32 nfs4_fsstat_bitmap[2]; -extern u32 nfs4_pathconf_bitmap[2]; +extern uint32_t nfs4_fattr_bitmap[2]; +extern uint32_t nfs4_fsinfo_bitmap[2]; +extern uint32_t nfs4_fsstat_bitmap[2]; +extern uint32_t nfs4_pathconf_bitmap[2]; static int -decode_getattr(struct nfs4_compound *cp, int nfserr, struct nfs4_getattr *getattr) +decode_getattr(struct xdr_stream *xdr, int nfserr, struct nfs4_getattr *getattr) { struct nfs_fattr *nfp = getattr->gt_attrs; struct nfs_fsstat *fsstat = getattr->gt_fsstat; struct nfs_fsinfo *fsinfo = getattr->gt_fsinfo; struct nfs_pathconf *pathconf = getattr->gt_pathconf; - u32 bmlen; - u32 bmval0 = 0; - u32 bmval1 = 0; - u32 attrlen; - u32 dummy32; - u32 len = 0; + uint32_t *p; + uint32_t bmlen; + uint32_t bmval0 = 0; + uint32_t bmval1 = 0; + uint32_t attrlen; + uint32_t dummy32; + uint32_t len = 0; unsigned int type; int fmode = 0; - DECODE_HEAD; + int status; if (nfserr) goto success; @@ -1060,7 +1008,7 @@ } nfp->type = nfs_type2fmt[type].nfs2type; fmode = nfs_type2fmt[type].mode; - dprintk("read_attrs: type=%d\n", (u32)nfp->type); + dprintk("read_attrs: type=%d\n", (uint32_t)nfp->type); } if (bmval0 & FATTR4_WORD0_CHANGE) { READ_BUF(8); @@ -1228,19 +1176,19 @@ READ_BUF(12); len += 12; READTIME(nfp->atime); - dprintk("read_attrs: atime=%d\n", (int)nfp->atime); + dprintk("read_attrs: atime=%ld\n", (long)nfp->atime.tv_sec); } if (bmval1 & FATTR4_WORD1_TIME_METADATA) { READ_BUF(12); len += 12; READTIME(nfp->ctime); - dprintk("read_attrs: ctime=%d\n", (int)nfp->ctime); + dprintk("read_attrs: ctime=%ld\n", (long)nfp->ctime.tv_sec); } if (bmval1 & FATTR4_WORD1_TIME_MODIFY) { READ_BUF(12); len += 12; READTIME(nfp->mtime); - dprintk("read_attrs: mtime=%d\n", (int)nfp->mtime); + dprintk("read_attrs: mtime=%ld\n", (long)nfp->mtime.tv_sec); } if (len != attrlen) goto xdr_error; @@ -1250,11 +1198,12 @@ } static int -decode_getfh(struct nfs4_compound *cp, int nfserr, struct nfs4_getfh *getfh) +decode_getfh(struct xdr_stream *xdr, int nfserr, struct nfs4_getfh *getfh) { struct nfs_fh *fh = getfh->gf_fhandle; - int len; - DECODE_HEAD; + uint32_t *p; + uint32_t len; + int status; /* Zero handle first to allow comparisons */ memset(fh, 0, sizeof(*fh)); @@ -1273,26 +1222,27 @@ } static int -decode_link(struct nfs4_compound *cp, int nfserr, struct nfs4_link *link) +decode_link(struct xdr_stream *xdr, int nfserr, struct nfs4_link *link) { int status = 0; if (!nfserr) - status = decode_change_info(cp, link->ln_cinfo); + status = decode_change_info(xdr, link->ln_cinfo); return status; } static int -decode_open(struct nfs4_compound *cp, int nfserr, struct nfs4_open *open) +decode_open(struct xdr_stream *xdr, int nfserr, struct nfs4_open *open) { - u32 bmlen, delegation_type; - DECODE_HEAD; + uint32_t *p; + uint32_t bmlen, delegation_type; + int status; if (!nfserr) { READ_BUF(sizeof(nfs4_stateid)); COPYMEM(open->op_stateid, sizeof(nfs4_stateid)); - decode_change_info(cp, open->op_cinfo); + decode_change_info(xdr, open->op_cinfo); READ_BUF(8); READ32(*open->op_rflags); @@ -1311,23 +1261,23 @@ } static int -decode_open_confirm(struct nfs4_compound *cp, int nfserr, struct nfs4_open_confirm *open_confirm) +decode_open_confirm(struct xdr_stream *xdr, int nfserr, struct nfs4_open_confirm *open_confirm) { - DECODE_HEAD; + uint32_t *p; if (!nfserr) { READ_BUF(sizeof(nfs4_stateid)); COPYMEM(open_confirm->oc_stateid, sizeof(nfs4_stateid)); } - - DECODE_TAIL; + return 0; } static int -decode_read(struct nfs4_compound *cp, int nfserr, struct nfs4_read *read) +decode_read(struct xdr_stream *xdr, int nfserr, struct nfs4_read *read) { - u32 throwaway; - DECODE_HEAD; + uint32_t throwaway; + uint32_t *p; + int status; if (!nfserr) { READ_BUF(8); @@ -1344,23 +1294,22 @@ } static int -decode_readdir(struct nfs4_compound *cp, int nfserr, struct rpc_rqst *req, struct nfs4_readdir *readdir) +decode_readdir(struct xdr_stream *xdr, int nfserr, struct rpc_rqst *req, struct nfs4_readdir *readdir) { struct xdr_buf *rcvbuf = &req->rq_rcv_buf; struct page *page = *rcvbuf->pages; unsigned int pglen = rcvbuf->page_len; - u32 *end, *entry; - u32 len, attrlen, word; - int i; - DECODE_HEAD; + uint32_t *end, *entry, *p; + uint32_t len, attrlen, word; + int i; if (!nfserr) { READ_BUF(8); COPYMEM(readdir->rd_resp_verifier, 8); BUG_ON(pglen > PAGE_CACHE_SIZE); - p = (u32 *) kmap(page); - end = (u32 *) ((char *)p + pglen + readdir->rd_pgbase); + p = (uint32_t *) kmap(page); + end = (uint32_t *) ((char *)p + pglen + readdir->rd_pgbase); while (*p++) { entry = p - 1; @@ -1406,7 +1355,7 @@ kunmap(page); } - DECODE_TAIL; + return 0; short_pkt: printk(KERN_NOTICE "NFS: short packet in readdir reply!\n"); /* truncate listing */ @@ -1419,11 +1368,11 @@ } static int -decode_readlink(struct nfs4_compound *cp, int nfserr, struct rpc_rqst *req, struct nfs4_readlink *readlink) +decode_readlink(struct xdr_stream *xdr, int nfserr, struct rpc_rqst *req, struct nfs4_readlink *readlink) { struct xdr_buf *rcvbuf = &req->rq_rcv_buf; - u32 *strlen; - u32 len; + uint32_t *strlen; + uint32_t len; char *string; if (!nfserr) { @@ -1434,7 +1383,7 @@ * and and null-terminate the text (the VFS expects * null-termination). */ - strlen = (u32 *) kmap(rcvbuf->pages[0]); + strlen = (uint32_t *) kmap(rcvbuf->pages[0]); len = ntohl(*strlen); if (len > PAGE_CACHE_SIZE - 5) { printk(KERN_WARNING "nfs: server returned giant symlink!\n"); @@ -1451,25 +1400,25 @@ } static int -decode_remove(struct nfs4_compound *cp, int nfserr, struct nfs4_remove *remove) +decode_remove(struct xdr_stream *xdr, int nfserr, struct nfs4_remove *remove) { int status; status = 0; if (!nfserr) - status = decode_change_info(cp, remove->rm_cinfo); + status = decode_change_info(xdr, remove->rm_cinfo); return status; } static int -decode_rename(struct nfs4_compound *cp, int nfserr, struct nfs4_rename *rename) +decode_rename(struct xdr_stream *xdr, int nfserr, struct nfs4_rename *rename) { int status = 0; if (!nfserr) { - if ((status = decode_change_info(cp, rename->rn_src_cinfo))) + if ((status = decode_change_info(xdr, rename->rn_src_cinfo))) goto out; - if ((status = decode_change_info(cp, rename->rn_dst_cinfo))) + if ((status = decode_change_info(xdr, rename->rn_dst_cinfo))) goto out; } out: @@ -1477,10 +1426,11 @@ } static int -decode_setattr(struct nfs4_compound *cp) +decode_setattr(struct xdr_stream *xdr) { - u32 bmlen; - DECODE_HEAD; + uint32_t *p; + uint32_t bmlen; + int status; READ_BUF(4); READ32(bmlen); @@ -1492,17 +1442,17 @@ } static int -decode_setclientid(struct nfs4_compound *cp, int nfserr) +decode_setclientid(struct xdr_stream *xdr, int nfserr, struct nfs4_setclientid *setclientid) { - DECODE_HEAD; + uint32_t *p; if (!nfserr) { READ_BUF(8 + sizeof(nfs4_verifier)); - READ64(cp->server->nfs4_state->cl_clientid); - COPYMEM(cp->server->nfs4_state->cl_confirm, sizeof(nfs4_verifier)); + READ64(setclientid->sc_state->cl_clientid); + COPYMEM(setclientid->sc_state->cl_confirm, sizeof(nfs4_verifier)); } else if (nfserr == NFSERR_CLID_INUSE) { - u32 len; + uint32_t len; /* skip netid string */ READ_BUF(4); @@ -1515,13 +1465,14 @@ READ_BUF(len); } - DECODE_TAIL; + return 0; } static int -decode_write(struct nfs4_compound *cp, int nfserr, struct nfs4_write *write) +decode_write(struct xdr_stream *xdr, int nfserr, struct nfs4_write *write) { - DECODE_HEAD; + uint32_t *p; + int status; if (!nfserr) { READ_BUF(16); @@ -1537,11 +1488,12 @@ /* FIXME: this sucks */ static int -decode_compound(struct nfs4_compound *cp, struct rpc_rqst *req) +decode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqst *req) { - u32 taglen; - u32 opnum, nfserr; - DECODE_HEAD; + uint32_t *p; + uint32_t taglen; + uint32_t opnum, nfserr; + int status; READ_BUF(8); READ32(cp->toplevel_status); @@ -1584,34 +1536,34 @@ switch (opnum) { case OP_ACCESS: - status = decode_access(cp, nfserr, &cp->ops[cp->nops].u.access); + status = decode_access(xdr, nfserr, &cp->ops[cp->nops].u.access); break; case OP_CLOSE: - status = decode_close(cp, nfserr, &cp->ops[cp->nops].u.close); + status = decode_close(xdr, nfserr, &cp->ops[cp->nops].u.close); break; case OP_COMMIT: - status = decode_commit(cp, nfserr, &cp->ops[cp->nops].u.commit); + status = decode_commit(xdr, nfserr, &cp->ops[cp->nops].u.commit); break; case OP_CREATE: - status = decode_create(cp, nfserr, &cp->ops[cp->nops].u.create); + status = decode_create(xdr, nfserr, &cp->ops[cp->nops].u.create); break; case OP_GETATTR: - status = decode_getattr(cp, nfserr, &cp->ops[cp->nops].u.getattr); + status = decode_getattr(xdr, nfserr, &cp->ops[cp->nops].u.getattr); break; case OP_GETFH: - status = decode_getfh(cp, nfserr, &cp->ops[cp->nops].u.getfh); + status = decode_getfh(xdr, nfserr, &cp->ops[cp->nops].u.getfh); break; case OP_LINK: - status = decode_link(cp, nfserr, &cp->ops[cp->nops].u.link); + status = decode_link(xdr, nfserr, &cp->ops[cp->nops].u.link); break; case OP_LOOKUP: status = 0; break; case OP_OPEN: - status = decode_open(cp, nfserr, &cp->ops[cp->nops].u.open); + status = decode_open(xdr, nfserr, &cp->ops[cp->nops].u.open); break; case OP_OPEN_CONFIRM: - status = decode_open_confirm(cp, nfserr, &cp->ops[cp->nops].u.open_confirm); + status = decode_open_confirm(xdr, nfserr, &cp->ops[cp->nops].u.open_confirm); break; case OP_PUTFH: status = 0; @@ -1620,22 +1572,22 @@ status = 0; break; case OP_READ: - status = decode_read(cp, nfserr, &cp->ops[cp->nops].u.read); + status = decode_read(xdr, nfserr, &cp->ops[cp->nops].u.read); break; case OP_READDIR: - status = decode_readdir(cp, nfserr, req, &cp->ops[cp->nops].u.readdir); + status = decode_readdir(xdr, nfserr, req, &cp->ops[cp->nops].u.readdir); break; case OP_READLINK: - status = decode_readlink(cp, nfserr, req, &cp->ops[cp->nops].u.readlink); + status = decode_readlink(xdr, nfserr, req, &cp->ops[cp->nops].u.readlink); break; case OP_RESTOREFH: status = 0; break; case OP_REMOVE: - status = decode_remove(cp, nfserr, &cp->ops[cp->nops].u.remove); + status = decode_remove(xdr, nfserr, &cp->ops[cp->nops].u.remove); break; case OP_RENAME: - status = decode_rename(cp, nfserr, &cp->ops[cp->nops].u.rename); + status = decode_rename(xdr, nfserr, &cp->ops[cp->nops].u.rename); break; case OP_RENEW: status = 0; @@ -1644,16 +1596,16 @@ status = 0; break; case OP_SETATTR: - status = decode_setattr(cp); + status = decode_setattr(xdr); break; case OP_SETCLIENTID: - status = decode_setclientid(cp, nfserr); + status = decode_setclientid(xdr, nfserr, &cp->ops[cp->nops].u.setclientid); break; case OP_SETCLIENTID_CONFIRM: status = 0; break; case OP_WRITE: - status = decode_write(cp, nfserr, &cp->ops[cp->nops].u.write); + status = decode_write(xdr, nfserr, &cp->ops[cp->nops].u.write); break; default: BUG(); @@ -1673,14 +1625,13 @@ * Decode COMPOUND response */ static int -nfs4_xdr_dec_compound(struct rpc_rqst *rqstp, u32 *p, struct nfs4_compound *cp) +nfs4_xdr_dec_compound(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_compound *cp) { + struct xdr_stream xdr; int status; - cp->p = p; - cp->end = (u32 *) ((u8 *) rqstp->rq_rvec->iov_base + rqstp->rq_rvec->iov_len); - - if ((status = decode_compound(cp, rqstp))) + xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); + if ((status = decode_compound(&xdr, cp, rqstp))) goto out; status = 0; @@ -1691,10 +1642,10 @@ return status; } -u32 * -nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus) +uint32_t * +nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus) { - u32 len; + uint32_t len; if (!*p++) { if (!*p) diff -Nru a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c --- a/fs/nfsd/nfs3xdr.c Fri Nov 22 13:41:17 2002 +++ b/fs/nfsd/nfs3xdr.c Fri Nov 22 13:41:17 2002 @@ -226,7 +226,7 @@ && (fhp->fh_export->ex_flags & NFSEXP_FSID)) p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid); else - p = xdr_encode_hyper(p, (u64) inode->i_dev); + p = xdr_encode_hyper(p, (u64) inode->i_sb->s_dev); p = xdr_encode_hyper(p, (u64) inode->i_ino); time.tv_sec = fhp->fh_post_atime; time.tv_nsec = 0; @@ -438,13 +438,52 @@ nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, u32 *p, struct nfsd3_symlinkargs *args) { + int len; + int avail; + char *old, *new; + struct iovec *vec; + if (!(p = decode_fh(p, &args->ffh)) || !(p = decode_filename(p, &args->fname, &args->flen)) || !(p = decode_sattr3(p, &args->attrs)) - || !(p = decode_pathname(p, &args->tname, &args->tlen))) + ) + return 0; + /* now decode the pathname, which might be larger than the first page. + * As we have to check for nul's anyway, we copy it into a new page + * This page appears in the rq_res.pages list, but as pages_len is always + * 0, it won't get in the way + */ + svc_take_page(rqstp); + len = ntohl(*p++); + if (len <= 0 || len > NFS3_MAXPATHLEN) + return 0; + args->tname = new = page_address(rqstp->rq_respages[rqstp->rq_resused-1]); + args->tlen = len; + /* first copy and check from the first page */ + old = (char*)p; + vec = &rqstp->rq_arg.head[0]; + avail = vec->iov_len - (old - (char*)vec->iov_base); + while (len > 0 && *old && avail) { + *new++ = *old++; + len--; + avail--; + } + /* now copy next page if there is one */ + if (len && !avail && rqstp->rq_arg.page_len) { + avail = rqstp->rq_arg.page_len; + if (avail > PAGE_SIZE) avail = PAGE_SIZE; + old = page_address(rqstp->rq_arg.pages[0]); + } + while (len > 0 && *old && avail) { + *new++ = *old++; + len--; + avail--; + } + *new = '\0'; + if (len) return 0; - return xdr_argsize_check(rqstp, p); + return 1; } int @@ -721,7 +760,7 @@ p = resp->buffer; *p++ = 0; /* no more entries */ *p++ = htonl(resp->common.err == nfserr_eof); - rqstp->rq_res.page_len = ((unsigned long)p & ~PAGE_MASK); + rqstp->rq_res.page_len = (((unsigned long)p-1) & ~PAGE_MASK)+1; return 1; } else return xdr_ressize_check(rqstp, p); diff -Nru a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c --- a/fs/nfsd/nfs4proc.c Fri Nov 22 13:41:23 2002 +++ b/fs/nfsd/nfs4proc.c Fri Nov 22 13:41:23 2002 @@ -481,7 +481,8 @@ *p++ = nfssvc_boot.tv_usec; return nfsd_write(rqstp, current_fh, write->wr_offset, - write->wr_buf, write->wr_buflen, &write->wr_how_written); + write->wr_vec, write->wr_vlen, write->wr_buflen, + &write->wr_how_written); } /* This routine never returns NFS_OK! If there are no other errors, it @@ -565,11 +566,14 @@ fh_init(¤t_fh, NFS4_FHSIZE); fh_init(&save_fh, NFS4_FHSIZE); - resp->p = rqstp->rq_resbuf.buf + 3 + XDR_QUADLEN(args->taglen); - resp->end = rqstp->rq_resbuf.base + rqstp->rq_resbuf.buflen; + resp->xbuf = &rqstp->rq_res; + resp->p = rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len; + resp->p += 3 + XDR_QUADLEN(args->taglen); + resp->end = rqstp->rq_res.head[0].iov_base + PAGE_SIZE; resp->taglen = args->taglen; resp->tag = args->tag; resp->opcnt = 0; + resp->rqstp = rqstp; /* * According to RFC3010, this takes precedence over all other errors. @@ -595,6 +599,7 @@ * failed response to the next operation. If we don't * have enough room, fail with ERR_RESOURCE. */ +/* FIXME - is slack_space *really* words, or bytes??? - neilb */ slack_space = (char *)resp->end - (char *)resp->p; if (slack_space < COMPOUND_SLACK_SPACE + COMPOUND_ERR_SLACK_SPACE) { BUG_ON(slack_space < COMPOUND_ERR_SLACK_SPACE); @@ -699,6 +704,16 @@ if (args->ops != args->iops) { kfree(args->ops); args->ops = args->iops; + } + if (args->tmpp) { + kfree(args->tmpp); + args->tmpp = NULL; + } + while (args->to_free) { + struct tmpbuf *tb = args->to_free; + args->to_free = tb->next; + kfree(tb->buf); + kfree(tb); } fh_put(¤t_fh); fh_put(&save_fh); diff -Nru a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c --- a/fs/nfsd/nfs4xdr.c Fri Nov 22 13:41:18 2002 +++ b/fs/nfsd/nfs4xdr.c Fri Nov 22 13:41:18 2002 @@ -217,20 +217,92 @@ x = (char *)p; \ p += XDR_QUADLEN(nbytes); \ } while (0) +#define SAVEMEM(x,nbytes) do { \ + if (!(x = (p==argp->tmp || p == argp->tmpp) ? \ + savemem(argp, p, nbytes) : \ + (char *)p)) { \ + printk(KERN_NOTICE "xdr error! (%s:%d)\n", __FILE__, __LINE__); \ + goto xdr_error; \ + } \ + p += XDR_QUADLEN(nbytes); \ +} while (0) #define COPYMEM(x,nbytes) do { \ memcpy((x), p, nbytes); \ p += XDR_QUADLEN(nbytes); \ } while (0) #define READ_BUF(nbytes) do { \ - if (nbytes > (u32)((char *)argp->end - (char *)argp->p)) { \ + if (nbytes <= (u32)((char *)argp->end - (char *)argp->p)) { \ + p = argp->p; \ + argp->p += XDR_QUADLEN(nbytes); \ + } else if (!(p = read_buf(argp, nbytes))) { \ printk(KERN_NOTICE "xdr error! (%s:%d)\n", __FILE__, __LINE__); \ goto xdr_error; \ } \ - p = argp->p; \ - argp->p += XDR_QUADLEN(nbytes); \ } while (0) +u32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes) +{ + /* We want more bytes than seem to be available. + * Maybe we need a new page, may wehave just run out + */ + int avail = (char*)argp->end - (char*)argp->p; + u32 *p; + if (avail + argp->pagelen < nbytes) + return NULL; + if (avail + PAGE_SIZE > nbytes) /* need more than a page !! */ + return NULL; + /* ok, we can do it with the tail plus the next page */ + if (nbytes <= sizeof(argp->tmp)) + p = argp->tmp; + else { + if (argp->tmpp) + kfree(argp->tmpp); + p = argp->tmpp = kmalloc(nbytes, GFP_KERNEL); + if (!p) + return NULL; + + } + memcpy(p, argp->p, avail); + /* step to next page */ + argp->p = page_address(argp->pagelist[0]); + argp->pagelist++; + if (argp->pagelen < PAGE_SIZE) { + argp->end = p + (argp->pagelen>>2); + argp->pagelen = 0; + } else { + argp->end = p + (PAGE_SIZE>>2); + argp->pagelen -= PAGE_SIZE; + } + memcpy(((char*)p)+avail, argp->p, (nbytes - avail)); + argp->p += XDR_QUADLEN(nbytes - avail); + return p; +} + +char *savemem(struct nfsd4_compoundargs *argp, u32 *p, int nbytes) +{ + struct tmpbuf *tb; + if (p == argp->tmp) { + p = kmalloc(nbytes, GFP_KERNEL); + if (!p) return NULL; + memcpy(p, argp->tmp, nbytes); + } else { + if (p != argp->tmpp) + BUG(); + argp->tmpp = NULL; + } + tb = kmalloc(sizeof(*tb), GFP_KERNEL); + if (!tb) { + kfree(p); + return NULL; + } + tb->buf = p; + tb->next = argp->to_free; + argp->to_free = tb; + return (char*)p; +} + + static int nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval) { @@ -442,7 +514,7 @@ READ_BUF(4); READ32(create->cr_linklen); READ_BUF(create->cr_linklen); - READMEM(create->cr_linkname, create->cr_linklen); + SAVEMEM(create->cr_linkname, create->cr_linklen); if (check_utf8(create->cr_linkname, create->cr_linklen)) return nfserr_inval; break; @@ -463,7 +535,7 @@ READ_BUF(4); READ32(create->cr_namelen); READ_BUF(create->cr_namelen); - READMEM(create->cr_name, create->cr_namelen); + SAVEMEM(create->cr_name, create->cr_namelen); if ((status = check_filename(create->cr_name, create->cr_namelen, nfserr_inval))) return status; @@ -487,7 +559,7 @@ READ_BUF(4); READ32(link->li_namelen); READ_BUF(link->li_namelen); - READMEM(link->li_name, link->li_namelen); + SAVEMEM(link->li_name, link->li_namelen); if ((status = check_filename(link->li_name, link->li_namelen, nfserr_inval))) return status; @@ -502,7 +574,7 @@ READ_BUF(4); READ32(lookup->lo_len); READ_BUF(lookup->lo_len); - READMEM(lookup->lo_name, lookup->lo_len); + SAVEMEM(lookup->lo_name, lookup->lo_len); if ((status = check_filename(lookup->lo_name, lookup->lo_len, nfserr_noent))) return status; @@ -527,7 +599,7 @@ /* owner, open_flag */ READ_BUF(open->op_ownerlen + 4); - READMEM(open->op_owner, open->op_ownerlen); + SAVEMEM(open->op_owner, open->op_ownerlen); READ32(open->op_create); switch (open->op_create) { case NFS4_OPEN_NOCREATE: @@ -562,7 +634,7 @@ READ_BUF(4); READ32(open->op_namelen); READ_BUF(open->op_namelen); - READMEM(open->op_name, open->op_namelen); + SAVEMEM(open->op_name, open->op_namelen); if ((status = check_filename(open->op_name, open->op_namelen, nfserr_inval))) return status; break; @@ -575,7 +647,7 @@ COPYMEM(&open->op_delegate_stateid, sizeof(delegation_stateid_t)); READ32(open->op_namelen); READ_BUF(open->op_namelen); - READMEM(open->op_name, open->op_namelen); + SAVEMEM(open->op_name, open->op_namelen); if ((status = check_filename(open->op_name, open->op_namelen, nfserr_inval))) return status; break; @@ -596,7 +668,7 @@ if (putfh->pf_fhlen > NFS4_FHSIZE) goto xdr_error; READ_BUF(putfh->pf_fhlen); - READMEM(putfh->pf_fhval, putfh->pf_fhlen); + SAVEMEM(putfh->pf_fhval, putfh->pf_fhlen); DECODE_TAIL; } @@ -639,7 +711,7 @@ READ_BUF(4); READ32(remove->rm_namelen); READ_BUF(remove->rm_namelen); - READMEM(remove->rm_name, remove->rm_namelen); + SAVEMEM(remove->rm_name, remove->rm_namelen); if ((status = check_filename(remove->rm_name, remove->rm_namelen, nfserr_noent))) return status; @@ -654,10 +726,10 @@ READ_BUF(4); READ32(rename->rn_snamelen); READ_BUF(rename->rn_snamelen + 4); - READMEM(rename->rn_sname, rename->rn_snamelen); + SAVEMEM(rename->rn_sname, rename->rn_snamelen); READ32(rename->rn_tnamelen); READ_BUF(rename->rn_tnamelen); - READMEM(rename->rn_tname, rename->rn_tnamelen); + SAVEMEM(rename->rn_tname, rename->rn_tnamelen); if ((status = check_filename(rename->rn_sname, rename->rn_snamelen, nfserr_noent))) return status; if ((status = check_filename(rename->rn_tname, rename->rn_tnamelen, nfserr_inval))) @@ -701,16 +773,16 @@ READ32(setclientid->se_namelen); READ_BUF(setclientid->se_namelen + 8); - READMEM(setclientid->se_name, setclientid->se_namelen); + SAVEMEM(setclientid->se_name, setclientid->se_namelen); READ32(setclientid->se_callback_prog); READ32(setclientid->se_callback_netid_len); READ_BUF(setclientid->se_callback_netid_len + 4); - READMEM(setclientid->se_callback_netid_val, setclientid->se_callback_netid_len); + SAVEMEM(setclientid->se_callback_netid_val, setclientid->se_callback_netid_len); READ32(setclientid->se_callback_addr_len); READ_BUF(setclientid->se_callback_addr_len + 4); - READMEM(setclientid->se_callback_addr_val, setclientid->se_callback_addr_len); + SAVEMEM(setclientid->se_callback_addr_val, setclientid->se_callback_addr_len); READ32(setclientid->se_callback_ident); DECODE_TAIL; @@ -739,7 +811,7 @@ READ_BUF(4); READ32(verify->ve_attrlen); READ_BUF(verify->ve_attrlen); - READMEM(verify->ve_attrval, verify->ve_attrlen); + SAVEMEM(verify->ve_attrval, verify->ve_attrlen); DECODE_TAIL; } @@ -747,6 +819,9 @@ static int nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write) { + int avail; + int v; + int len; DECODE_HEAD; READ_BUF(sizeof(stateid_t) + 16); @@ -758,8 +833,36 @@ goto xdr_error; READ32(write->wr_buflen); - READ_BUF(write->wr_buflen); - READMEM(write->wr_buf, write->wr_buflen); + /* Sorry .. no magic macros for this.. * + * READ_BUF(write->wr_buflen); + * SAVEMEM(write->wr_buf, write->wr_buflen); + */ + avail = (char*)argp->end - (char*)argp->p; + if (avail + argp->pagelen < write->wr_buflen) { + printk(KERN_NOTICE "xdr error! (%s:%d)\n", __FILE__, __LINE__); + goto xdr_error; + } + write->wr_vec[0].iov_base = p; + write->wr_vec[0].iov_len = avail; + v = 0; + len = write->wr_buflen; + while (len > write->wr_vec[v].iov_len) { + len -= write->wr_vec[v].iov_len; + v++; + write->wr_vec[v].iov_base = page_address(argp->pagelist[0]); + argp->pagelist++; + if (argp->pagelen >= PAGE_SIZE) { + write->wr_vec[v].iov_len = PAGE_SIZE; + argp->pagelen -= PAGE_SIZE; + } else { + write->wr_vec[v].iov_len = argp->pagelen; + argp->pagelen = 0; + } + } + argp->end = (u32*) (write->wr_vec[v].iov_base + write->wr_vec[v].iov_len); + argp->p = (u32*) (write->wr_vec[v].iov_base + len); + write->wr_vec[v].iov_len = len; + write->wr_vlen = v+1; DECODE_TAIL; } @@ -780,7 +883,7 @@ READ_BUF(4); READ32(argp->taglen); READ_BUF(argp->taglen + 8); - READMEM(argp->tag, argp->taglen); + SAVEMEM(argp->tag, argp->taglen); READ32(argp->minorversion); READ32(argp->opcnt); @@ -1586,27 +1689,52 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read *read) { u32 eof; - unsigned long maxcount; + int v, pn; + unsigned long maxcount, len; ENCODE_HEAD; if (nfserr) return nfserr; + if (resp->xbuf->page_len) + return nfserr_resource; - maxcount = (char *)resp->end - (char *)resp->p - COMPOUND_ERR_SLACK_SPACE - 8; + RESERVE_SPACE(8); /* eof flag and byte count */ + + maxcount = NFSSVC_MAXBLKSIZE; if (maxcount > read->rd_length) maxcount = read->rd_length; - RESERVE_SPACE(maxcount + 8); + + len = maxcount; + v = 0; + while (len > 0) { + pn = resp->rqstp->rq_resused; + svc_take_page(resp->rqstp); + read->rd_iov[v].iov_base = page_address(resp->rqstp->rq_respages[pn]); + read->rd_iov[v].iov_len = len < PAGE_SIZE ? len : PAGE_SIZE; + v++; + len -= PAGE_SIZE; + } + read->rd_vlen = v; nfserr = nfsd_read(read->rd_rqstp, read->rd_fhp, - read->rd_offset, (char *)p + 8, &maxcount); + read->rd_offset, + read->rd_iov, read->rd_vlen, + &maxcount); if (nfserr) return nfserr; eof = (read->rd_offset + maxcount >= read->rd_fhp->fh_dentry->d_inode->i_size); WRITE32(eof); WRITE32(maxcount); - p += XDR_QUADLEN(maxcount); ADJUST_ARGS(); + resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base; + resp->p = resp->xbuf->tail[0].iov_base; + resp->xbuf->page_len = maxcount; + if (maxcount&3) { + *(resp->p)++ = 0; + resp->xbuf->tail[0].iov_base += maxcount&3; + resp->xbuf->tail[0].iov_len = 4 - (maxcount&3); + } return 0; } @@ -1614,13 +1742,24 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_readlink *readlink) { int maxcount; + char *page; ENCODE_HEAD; if (nfserr) return nfserr; + if (resp->xbuf->page_len) + return nfserr_resource; + + svc_take_page(resp->rqstp); + page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); - maxcount = (char *)resp->end - (char *)resp->p - COMPOUND_ERR_SLACK_SPACE - 4; - RESERVE_SPACE(maxcount + 4); + svc_take_page(resp->rqstp); + resp->xbuf->tail[0].iov_base = + page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); + resp->xbuf->tail[0].iov_len = 0; + + maxcount = PAGE_SIZE; + RESERVE_SPACE(4); /* * XXX: By default, the ->readlink() VFS op will truncate symlinks @@ -1628,13 +1767,20 @@ * not, one easy fix is: if ->readlink() precisely fills the buffer, * assume that truncation occured, and return NFS4ERR_RESOURCE. */ - nfserr = nfsd_readlink(readlink->rl_rqstp, readlink->rl_fhp, (char *)p + 4, &maxcount); + nfserr = nfsd_readlink(readlink->rl_rqstp, readlink->rl_fhp, page, &maxcount); if (nfserr) return nfserr; WRITE32(maxcount); - p += XDR_QUADLEN(maxcount); ADJUST_ARGS(); + resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base; + resp->p = resp->xbuf->tail[0].iov_base; + resp->xbuf->page_len = maxcount; + if (maxcount&3) { + *(resp->p)++ = 0; + resp->xbuf->tail[0].iov_base += maxcount&3; + resp->xbuf->tail[0].iov_len = 4 - (maxcount&3); + } return 0; } @@ -1643,14 +1789,22 @@ { int maxcount; loff_t offset; + u32 *page; ENCODE_HEAD; if (nfserr) return nfserr; + if (resp->xbuf->page_len) + return nfserr_resource; + + RESERVE_SPACE(8); /* verifier */ - RESERVE_SPACE(16); + /* XXX: Following NFSv3, we ignore the READDIR verifier for now. */ + WRITE32(0); + WRITE32(0); + ADJUST_ARGS(); - maxcount = (char *)resp->end - (char *)p - COMPOUND_ERR_SLACK_SPACE; + maxcount = PAGE_SIZE; if (maxcount > readdir->rd_maxcount) maxcount = readdir->rd_maxcount; @@ -1663,13 +1817,11 @@ if (maxcount < 0) return nfserr_readdir_nospc; - /* XXX: Following NFSv3, we ignore the READDIR verifier for now. */ - WRITE32(0); - WRITE32(0); - + svc_take_page(resp->rqstp); + page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); readdir->common.err = 0; readdir->buflen = maxcount; - readdir->buffer = p; + readdir->buffer = page; readdir->offset = NULL; offset = readdir->rd_cookie; @@ -1678,7 +1830,7 @@ &readdir->common, nfsd4_encode_dirent); if (nfserr == nfs_ok && readdir->common.err == nfserr_readdir_nospc && - readdir->buffer == p) + readdir->buffer == page) nfserr = nfserr_readdir_nospc; if (!nfserr) { if (readdir->offset) @@ -1687,7 +1839,7 @@ p = readdir->buffer; *p++ = 0; /* no more entries */ *p++ = htonl(readdir->common.err == nfserr_eof); - ADJUST_ARGS(); + resp->xbuf->page_len = ((char*)p) - (char*)page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); } return nfserr; } @@ -1868,17 +2020,6 @@ * END OF "GENERIC" ENCODE ROUTINES. */ -static inline int -xdr_ressize_check(struct svc_rqst *rqstp, u32 *p) -{ - struct svc_buf *buf = &rqstp->rq_resbuf; - - buf->len = p - buf->base; - dprintk("nfsd: ressize_check p %p base %p len %d\n", - p, buf->base, buf->buflen); - return (buf->len <= buf->buflen); -} - int nfs4svc_encode_voidres(struct svc_rqst *rqstp, u32 *p, void *dummy) { @@ -1891,13 +2032,29 @@ int status; args->p = p; - args->end = rqstp->rq_argbuf.base + rqstp->rq_argbuf.buflen; + args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len; + args->pagelist = rqstp->rq_arg.pages; + args->pagelen = rqstp->rq_arg.page_len; + args->tmpp = NULL; + args->to_free = NULL; args->ops = args->iops; status = nfsd4_decode_compound(args); - if (status && args->ops != args->iops) { - kfree(args->ops); - args->ops = args->iops; + if (status) { + if (args->ops != args->iops) { + kfree(args->ops); + args->ops = args->iops; + } + if (args->tmpp) { + kfree(args->tmpp); + args->tmpp = NULL; + } + while (args->to_free) { + struct tmpbuf *tb = args->to_free; + args->to_free = tb->next; + kfree(tb->buf); + kfree(tb); + } } return !status; } @@ -1908,12 +2065,18 @@ /* * All that remains is to write the tag and operation count... */ + struct iovec *iov; *p++ = htonl(resp->taglen); memcpy(p, resp->tag, resp->taglen); p += XDR_QUADLEN(resp->taglen); *p++ = htonl(resp->opcnt); - BUG_ON(!xdr_ressize_check(rqstp, resp->p)); + if (rqstp->rq_res.page_len) + iov = &rqstp->rq_res.tail[0]; + else + iov = &rqstp->rq_res.head[0]; + iov->iov_len = ((char*)resp->p) - (char*)iov->iov_base; + BUG_ON(iov->iov_len > PAGE_SIZE); return 1; } diff -Nru a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c --- a/fs/nfsd/nfsxdr.c Fri Nov 22 13:41:17 2002 +++ b/fs/nfsd/nfsxdr.c Fri Nov 22 13:41:17 2002 @@ -430,7 +430,7 @@ p = resp->buffer; *p++ = 0; /* no more entries */ *p++ = htonl((resp->common.err == nfserr_eof)); - rqstp->rq_res.page_len = ((unsigned long)p & ~PAGE_MASK); + rqstp->rq_res.page_len = (((unsigned long)p-1) & ~PAGE_MASK)+1; return 1; } diff -Nru a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c --- a/fs/nfsd/vfs.c Fri Nov 22 13:41:19 2002 +++ b/fs/nfsd/vfs.c Fri Nov 22 13:41:19 2002 @@ -259,7 +259,7 @@ * If we are changing the size of the file, then * we need to break all leases. */ - err = get_lease(inode, FMODE_WRITE); + err = break_lease(inode, FMODE_WRITE); if (err) goto out_nfserr; @@ -453,7 +453,7 @@ * Check to see if there are any leases on this file. * This may block while leases are broken. */ - err = get_lease(inode, (access & MAY_WRITE) ? FMODE_WRITE : 0); + err = break_lease(inode, (access & MAY_WRITE) ? FMODE_WRITE : 0); if (err) goto out_nfserr; @@ -632,7 +632,7 @@ #endif /* Get readahead parameters */ - ra = nfsd_get_raparms(inode->i_dev, inode->i_ino); + ra = nfsd_get_raparms(inode->i_sb->s_dev, inode->i_ino); if (ra) file.f_ra = ra->p_ra; @@ -752,7 +752,7 @@ */ if (EX_WGATHER(exp)) { if (atomic_read(&inode->i_writecount) > 1 - || (last_ino == inode->i_ino && last_dev == inode->i_dev)) { + || (last_ino == inode->i_ino && last_dev == inode->i_sb->s_dev)) { dprintk("nfsd: write defer %d\n", current->pid); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((HZ+99)/100); @@ -769,7 +769,7 @@ #endif } last_ino = inode->i_ino; - last_dev = inode->i_dev; + last_dev = inode->i_sb->s_dev; } dprintk("nfsd: write complete err=%d\n", err); diff -Nru a/fs/open.c b/fs/open.c --- a/fs/open.c Fri Nov 22 13:41:17 2002 +++ b/fs/open.c Fri Nov 22 13:41:17 2002 @@ -131,7 +131,7 @@ /* * Make sure that there are no leases. */ - error = get_lease(inode, FMODE_WRITE); + error = break_lease(inode, FMODE_WRITE); if (error) goto dput_and_out; diff -Nru a/fs/partitions/check.c b/fs/partitions/check.c --- a/fs/partitions/check.c Fri Nov 22 13:41:23 2002 +++ b/fs/partitions/check.c Fri Nov 22 13:41:23 2002 @@ -378,7 +378,7 @@ p->nr_sects = len; devfs_register_partition(disk, part); kobject_init(&p->kobj); - snprintf(p->kobj.name,KOBJ_NAME_LEN,"%s%d",disk->disk_name,part); + snprintf(p->kobj.name,KOBJ_NAME_LEN,"%s%d",disk->kobj.name,part); p->kobj.parent = &disk->kobj; p->kobj.subsys = &part_subsys; kobject_register(&p->kobj); diff -Nru a/fs/proc/array.c b/fs/proc/array.c --- a/fs/proc/array.c Fri Nov 22 13:41:21 2002 +++ b/fs/proc/array.c Fri Nov 22 13:41:21 2002 @@ -484,8 +484,9 @@ dev = 0; ino = 0; if (map->vm_file != NULL) { - dev = map->vm_file->f_dentry->d_inode->i_dev; - ino = map->vm_file->f_dentry->d_inode->i_ino; + struct inode *inode = map->vm_file->f_dentry->d_inode; + dev = inode->i_sb->s_dev; + ino = inode->i_ino; line = d_path(map->vm_file->f_dentry, map->vm_file->f_vfsmnt, buf, PAGE_SIZE); diff -Nru a/fs/proc/base.c b/fs/proc/base.c --- a/fs/proc/base.c Fri Nov 22 13:41:21 2002 +++ b/fs/proc/base.c Fri Nov 22 13:41:21 2002 @@ -258,20 +258,18 @@ */ static int proc_pid_wchan(struct task_struct *task, char *buffer) { - const char *sym_name, *ignore; - unsigned long wchan, dummy; + char *modname; + const char *sym_name; + unsigned long wchan, size, offset; wchan = get_wchan(task); - if (!kallsyms_address_to_symbol(wchan, &ignore, &dummy, &dummy, - &ignore, &dummy, &dummy, &sym_name, - &dummy, &dummy)) { - return sprintf(buffer, "%lu", wchan); - } - - return sprintf(buffer, "%s", sym_name); + sym_name = kallsyms_lookup(wchan, &size, &offset, &modname); + if (sym_name) + return sprintf(buffer, "%s", sym_name); + return sprintf(buffer, "%lu", wchan); } -#endif +#endif /* CONFIG_KALLSYMS */ /************************************************************************/ /* Here the fs part begins */ diff -Nru a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c --- a/fs/proc/proc_misc.c Fri Nov 22 13:41:18 2002 +++ b/fs/proc/proc_misc.c Fri Nov 22 13:41:18 2002 @@ -57,7 +57,8 @@ */ extern int get_hardware_list(char *); extern int get_stram_list(char *); -extern int get_device_list(char *); +extern int get_chrdev_list(char *); +extern int get_blkdev_list(char *); extern int get_filesystem_list(char *); extern int get_exec_domain_list(char *); extern int get_dma_list(char *); @@ -180,8 +181,8 @@ K(i.freeram), K(i.sharedram), K(i.bufferram), - K(ps.nr_pagecache-swapper_space.nrpages-i.bufferram), - K(swapper_space.nrpages), + K(ps.nr_pagecache-total_swapcache_pages-i.bufferram), + K(total_swapcache_pages), K(active), K(inactive), K(i.totalhigh), @@ -376,7 +377,8 @@ static int devices_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = get_device_list(page); + int len = get_chrdev_list(page); + len += get_blkdev_list(page+len); return proc_calc_metrics(page, start, off, count, eof, len); } diff -Nru a/fs/ramfs/inode.c b/fs/ramfs/inode.c --- a/fs/ramfs/inode.c Fri Nov 22 13:41:18 2002 +++ b/fs/ramfs/inode.c Fri Nov 22 13:41:18 2002 @@ -47,7 +47,7 @@ .memory_backed = 1, /* Does not contribute to dirty memory */ }; -struct inode *ramfs_get_inode(struct super_block *sb, int mode, int dev) +static struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev) { struct inode * inode = new_inode(sb); @@ -87,14 +87,15 @@ * File creation. Allocate an inode, and we're done.. */ /* SMP-safe */ -static int ramfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev) +static int +ramfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) { struct inode * inode = ramfs_get_inode(dir->i_sb, mode, dev); int error = -ENOSPC; if (inode) { d_instantiate(dentry, inode); - dget(dentry); /* Extra count - pin the dentry in core */ + dget(dentry); /* Extra count - pin the dentry in core */ error = 0; } return error; diff -Nru a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c --- a/fs/reiserfs/namei.c Fri Nov 22 13:41:21 2002 +++ b/fs/reiserfs/namei.c Fri Nov 22 13:41:21 2002 @@ -605,7 +605,7 @@ } -static int reiserfs_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev) +static int reiserfs_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_t rdev) { int retval; struct inode * inode; diff -Nru a/fs/smbfs/dir.c b/fs/smbfs/dir.c --- a/fs/smbfs/dir.c Fri Nov 22 13:41:23 2002 +++ b/fs/smbfs/dir.c Fri Nov 22 13:41:23 2002 @@ -31,7 +31,7 @@ static int smb_unlink(struct inode *, struct dentry *); static int smb_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); -static int smb_make_node(struct inode *,struct dentry *,int,int); +static int smb_make_node(struct inode *,struct dentry *,int,dev_t); static int smb_link(struct dentry *, struct inode *, struct dentry *); struct file_operations smb_dir_operations = @@ -641,7 +641,7 @@ * matches the connection credentials (and we don't know which those are ...) */ static int -smb_make_node(struct inode *dir, struct dentry *dentry, int mode, int dev) +smb_make_node(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) { int error; struct iattr attr; diff -Nru a/fs/smbfs/proto.h b/fs/smbfs/proto.h --- a/fs/smbfs/proto.h Fri Nov 22 13:41:21 2002 +++ b/fs/smbfs/proto.h Fri Nov 22 13:41:21 2002 @@ -3,6 +3,7 @@ */ struct smb_request; +struct sock; /* proc.c */ extern int smb_setcodepage(struct smb_sb_info *server, struct smb_nls_codepage *cp); diff -Nru a/fs/smbfs/request.h b/fs/smbfs/request.h --- a/fs/smbfs/request.h Fri Nov 22 13:41:18 2002 +++ b/fs/smbfs/request.h Fri Nov 22 13:41:18 2002 @@ -1,6 +1,7 @@ +#include #include +#include #include -#include struct smb_request { struct list_head rq_queue; /* recvq or xmitq for the server */ diff -Nru a/fs/stat.c b/fs/stat.c --- a/fs/stat.c Fri Nov 22 13:41:18 2002 +++ b/fs/stat.c Fri Nov 22 13:41:18 2002 @@ -18,7 +18,7 @@ void generic_fillattr(struct inode *inode, struct kstat *stat) { - stat->dev = inode->i_dev; + stat->dev = inode->i_sb->s_dev; stat->ino = inode->i_ino; stat->mode = inode->i_mode; stat->nlink = inode->i_nlink; @@ -96,7 +96,7 @@ #if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) \ && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) \ - && !defined(__arm__) && !defined(CONFIG_V850) + && !defined(__arm__) && !defined(CONFIG_V850) && !defined(__powerpc64__) /* * For backward compatibility? Maybe this should be moved diff -Nru a/fs/sysfs/inode.c b/fs/sysfs/inode.c --- a/fs/sysfs/inode.c Fri Nov 22 13:41:22 2002 +++ b/fs/sysfs/inode.c Fri Nov 22 13:41:22 2002 @@ -23,6 +23,8 @@ * Please see Documentation/filesystems/sysfs.txt for more information. */ +#undef DEBUG + #include #include #include @@ -87,7 +89,7 @@ return inode; } -static int sysfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev) +static int sysfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) { struct inode *inode; int error = 0; @@ -133,26 +135,14 @@ if (inode) { int l = strlen(symname)+1; error = page_symlink(inode, symname, l); - if (!error) { + if (!error) d_instantiate(dentry, inode); - dget(dentry); - } else + else iput(inode); } return error; } -static int sysfs_unlink(struct inode *dir, struct dentry *dentry) -{ - struct inode *inode = dentry->d_inode; - down(&inode->i_sem); - dentry->d_inode->i_nlink--; - up(&inode->i_sem); - d_invalidate(dentry); - dput(dentry); - return 0; -} - /** * sysfs_read_file - read an attribute. * @file: file pointer. @@ -173,17 +163,11 @@ sysfs_read_file(struct file *file, char *buf, size_t count, loff_t *ppos) { struct attribute * attr = file->f_dentry->d_fsdata; - struct sysfs_ops * ops = NULL; - struct kobject * kobj; + struct sysfs_ops * ops = file->private_data; + struct kobject * kobj = file->f_dentry->d_parent->d_fsdata; unsigned char *page; ssize_t retval = 0; - kobj = file->f_dentry->d_parent->d_fsdata; - if (kobj && kobj->subsys) - ops = kobj->subsys->sysfs_ops; - if (!ops || !ops->show) - return 0; - if (count > PAGE_SIZE) count = PAGE_SIZE; @@ -234,16 +218,11 @@ sysfs_write_file(struct file *file, const char *buf, size_t count, loff_t *ppos) { struct attribute * attr = file->f_dentry->d_fsdata; - struct sysfs_ops * ops = NULL; - struct kobject * kobj; + struct sysfs_ops * ops = file->private_data; + struct kobject * kobj = file->f_dentry->d_parent->d_fsdata; ssize_t retval = 0; char * page; - kobj = file->f_dentry->d_parent->d_fsdata; - if (kobj && kobj->subsys) - ops = kobj->subsys->sysfs_ops; - if (!ops || !ops->store) - return 0; page = (char *)__get_free_page(GFP_KERNEL); if (!page) @@ -275,21 +254,72 @@ return retval; } -static int sysfs_open_file(struct inode * inode, struct file * filp) +static int check_perm(struct inode * inode, struct file * file) { - struct kobject * kobj; + struct kobject * kobj = kobject_get(file->f_dentry->d_parent->d_fsdata); + struct attribute * attr = file->f_dentry->d_fsdata; + struct sysfs_ops * ops = NULL; int error = 0; - kobj = filp->f_dentry->d_parent->d_fsdata; - if ((kobj = kobject_get(kobj))) { - struct attribute * attr = filp->f_dentry->d_fsdata; - if (!attr) - error = -EINVAL; - } else - error = -EINVAL; + if (!kobj || !attr) + goto Einval; + + if (kobj->subsys) + ops = kobj->subsys->sysfs_ops; + + /* No sysfs operations, either from having no subsystem, + * or the subsystem have no operations. + */ + if (!ops) + goto Eaccess; + + /* File needs write support. + * The inode's perms must say it's ok, + * and we must have a store method. + */ + if (file->f_mode & FMODE_WRITE) { + + if (!(inode->i_mode & S_IWUGO)) + goto Eperm; + if (!ops->store) + goto Eaccess; + + } + + /* File needs read support. + * The inode's perms must say it's ok, and we there + * must be a show method for it. + */ + if (file->f_mode & FMODE_READ) { + if (!(inode->i_mode & S_IRUGO)) + goto Eperm; + if (!ops->show) + goto Eaccess; + } + + /* No error? Great, store the ops in file->private_data + * for easy access in the read/write functions. + */ + file->private_data = ops; + goto Done; + + Einval: + error = -EINVAL; + goto Done; + Eaccess: + error = -EACCES; + goto Done; + Eperm: + error = -EPERM; + Done: return error; } +static int sysfs_open_file(struct inode * inode, struct file * filp) +{ + return check_perm(inode,filp); +} + static int sysfs_release(struct inode * inode, struct file * filp) { struct kobject * kobj = filp->f_dentry->d_parent->d_fsdata; @@ -541,7 +571,8 @@ /* make sure dentry is really there */ if (victim->d_inode && (victim->d_parent->d_inode == dir->d_inode)) { - sysfs_unlink(dir->d_inode,victim); + d_invalidate(victim); + simple_unlink(dir->d_inode,victim); } } up(&dir->d_inode->i_sem); @@ -599,18 +630,15 @@ list_for_each_safe(node,next,&dentry->d_subdirs) { struct dentry * d = list_entry(node,struct dentry,d_child); /* make sure dentry is still there */ - if (d->d_inode) - sysfs_unlink(dentry->d_inode,d); + if (d->d_inode) { + d_invalidate(d); + simple_unlink(dentry->d_inode,d); + } } - d_invalidate(dentry); - if (simple_empty(dentry)) { - dentry->d_inode->i_nlink -= 2; - dentry->d_inode->i_flags |= S_DEAD; - parent->d_inode->i_nlink--; - } up(&dentry->d_inode->i_sem); - dput(dentry); + d_invalidate(dentry); + simple_rmdir(parent->d_inode,dentry); up(&parent->d_inode->i_sem); dput(parent); @@ -622,4 +650,3 @@ EXPORT_SYMBOL(sysfs_remove_link); EXPORT_SYMBOL(sysfs_create_dir); EXPORT_SYMBOL(sysfs_remove_dir); -MODULE_LICENSE("GPL"); diff -Nru a/fs/sysv/namei.c b/fs/sysv/namei.c --- a/fs/sysv/namei.c Fri Nov 22 13:41:21 2002 +++ b/fs/sysv/namei.c Fri Nov 22 13:41:21 2002 @@ -83,7 +83,7 @@ return NULL; } -static int sysv_mknod(struct inode * dir, struct dentry * dentry, int mode, int rdev) +static int sysv_mknod(struct inode * dir, struct dentry * dentry, int mode, dev_t rdev) { struct inode * inode = sysv_new_inode(dir, mode); int err = PTR_ERR(inode); diff -Nru a/fs/sysv/super.c b/fs/sysv/super.c --- a/fs/sysv/super.c Fri Nov 22 13:41:18 2002 +++ b/fs/sysv/super.c Fri Nov 22 13:41:18 2002 @@ -274,21 +274,21 @@ }; static char *flavour_names[] = { - [FSTYPE_XENIX] "Xenix", - [FSTYPE_SYSV4] "SystemV", - [FSTYPE_SYSV2] "SystemV Release 2", - [FSTYPE_COH] "Coherent", - [FSTYPE_V7] "V7", - [FSTYPE_AFS] "AFS", + [FSTYPE_XENIX] = "Xenix", + [FSTYPE_SYSV4] = "SystemV", + [FSTYPE_SYSV2] = "SystemV Release 2", + [FSTYPE_COH] = "Coherent", + [FSTYPE_V7] = "V7", + [FSTYPE_AFS] = "AFS", }; static void (*flavour_setup[])(struct sysv_sb_info *) = { - [FSTYPE_XENIX] detected_xenix, - [FSTYPE_SYSV4] detected_sysv4, - [FSTYPE_SYSV2] detected_sysv2, - [FSTYPE_COH] detected_coherent, - [FSTYPE_V7] detected_v7, - [FSTYPE_AFS] detected_sysv4, + [FSTYPE_XENIX] = detected_xenix, + [FSTYPE_SYSV4] = detected_sysv4, + [FSTYPE_SYSV2] = detected_sysv2, + [FSTYPE_COH] = detected_coherent, + [FSTYPE_V7] = detected_v7, + [FSTYPE_AFS] = detected_sysv4, }; static int complete_read_super(struct super_block *sb, int silent, int size) diff -Nru a/fs/udf/file.c b/fs/udf/file.c --- a/fs/udf/file.c Fri Nov 22 13:41:21 2002 +++ b/fs/udf/file.c Fri Nov 22 13:41:21 2002 @@ -145,10 +145,7 @@ retval = generic_file_write(file, buf, count, ppos); if (retval > 0) - { - UDF_I_UCTIME(inode) = UDF_I_UMTIME(inode) = CURRENT_UTIME; mark_inode_dirty(inode); - } return retval; } diff -Nru a/fs/udf/ialloc.c b/fs/udf/ialloc.c --- a/fs/udf/ialloc.c Fri Nov 22 13:41:19 2002 +++ b/fs/udf/ialloc.c Fri Nov 22 13:41:19 2002 @@ -156,10 +156,8 @@ UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_SHORT; else UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_LONG; - inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; - UDF_I_CRTIME(inode) = get_seconds(); - UDF_I_UMTIME(inode) = UDF_I_UCTIME(inode) = - UDF_I_UCRTIME(inode) = get_seconds(); + inode->i_mtime = inode->i_atime = inode->i_ctime = + UDF_I_CRTIME(inode) = CURRENT_TIME; insert_inode_hash(inode); mark_inode_dirty(inode); diff -Nru a/fs/udf/inode.c b/fs/udf/inode.c --- a/fs/udf/inode.c Fri Nov 22 13:41:23 2002 +++ b/fs/udf/inode.c Fri Nov 22 13:41:23 2002 @@ -573,7 +573,6 @@ UDF_I_NEXT_ALLOC_BLOCK(inode) = block; UDF_I_NEXT_ALLOC_GOAL(inode) = newblocknum; inode->i_ctime = CURRENT_TIME; - UDF_I_UCTIME(inode) = CURRENT_UTIME; if (IS_SYNC(inode)) udf_sync_inode(inode); @@ -877,7 +876,6 @@ } inode->i_mtime = inode->i_ctime = CURRENT_TIME; - UDF_I_UMTIME(inode) = UDF_I_UCTIME(inode) = CURRENT_UTIME; if (IS_SYNC(inode)) udf_sync_inode (inode); else @@ -920,7 +918,6 @@ * Set defaults, but the inode is still incomplete! * Note: get_new_inode() sets the following on a new inode: * i_sb = sb - * i_dev = sb->s_dev; * i_no = ino * i_flags = sb->s_flags * i_state = 0 @@ -1023,10 +1020,6 @@ UDF_I_STRAT4096(inode) = 1; UDF_I_ALLOCTYPE(inode) = le16_to_cpu(fe->icbTag.flags) & ICBTAG_FLAG_AD_MASK; - UDF_I_UMTIME(inode) = 0; - UDF_I_UCTIME(inode) = 0; - UDF_I_CRTIME(inode) = 0; - UDF_I_UCRTIME(inode) = 0; UDF_I_UNIQUE(inode) = 0; UDF_I_LENEATTR(inode) = 0; UDF_I_LENEXTENTS(inode) = 0; @@ -1084,40 +1077,33 @@ lets_to_cpu(fe->accessTime)) ) { inode->i_atime.tv_sec = convtime; - inode->i_atime.tv_nsec = 0; + inode->i_atime.tv_nsec = convtime_usec * 1000; } else { - inode->i_atime.tv_sec = UDF_SB_RECORDTIME(inode->i_sb); - inode->i_atime.tv_nsec = 0; + inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb); } if ( udf_stamp_to_time(&convtime, &convtime_usec, lets_to_cpu(fe->modificationTime)) ) { inode->i_mtime.tv_sec = convtime; - inode->i_mtime.tv_nsec = 0; - UDF_I_UMTIME(inode) = convtime_usec; + inode->i_mtime.tv_nsec = convtime_usec * 1000; } else { - inode->i_mtime.tv_sec = UDF_SB_RECORDTIME(inode->i_sb); - inode->i_mtime.tv_nsec = 0; - UDF_I_UMTIME(inode) = 0; + inode->i_mtime = UDF_SB_RECORDTIME(inode->i_sb); } if ( udf_stamp_to_time(&convtime, &convtime_usec, lets_to_cpu(fe->attrTime)) ) { inode->i_ctime.tv_sec = convtime; - inode->i_ctime.tv_nsec = 0; - UDF_I_UCTIME(inode) = convtime_usec; + inode->i_ctime.tv_nsec = convtime_usec * 1000; } else { - inode->i_ctime.tv_sec = UDF_SB_RECORDTIME(inode->i_sb); - inode->i_ctime.tv_nsec = 0; - UDF_I_UCTIME(inode) = 0; + inode->i_ctime = UDF_SB_RECORDTIME(inode->i_sb); } UDF_I_UNIQUE(inode) = le64_to_cpu(fe->uniqueID); @@ -1135,52 +1121,44 @@ lets_to_cpu(efe->accessTime)) ) { inode->i_atime.tv_sec = convtime; - inode->i_atime.tv_nsec = 0; + inode->i_atime.tv_nsec = convtime_usec * 1000; } else { - inode->i_atime.tv_sec = UDF_SB_RECORDTIME(inode->i_sb); - inode->i_atime.tv_nsec = 0; + inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb); } if ( udf_stamp_to_time(&convtime, &convtime_usec, lets_to_cpu(efe->modificationTime)) ) { inode->i_mtime.tv_sec = convtime; - inode->i_mtime.tv_nsec = 0; - UDF_I_UMTIME(inode) = convtime_usec; + inode->i_mtime.tv_nsec = convtime_usec * 1000; } else { - inode->i_mtime.tv_sec = UDF_SB_RECORDTIME(inode->i_sb); - inode->i_mtime.tv_nsec = 0; - UDF_I_UMTIME(inode) = 0; + inode->i_mtime = UDF_SB_RECORDTIME(inode->i_sb); } if ( udf_stamp_to_time(&convtime, &convtime_usec, lets_to_cpu(efe->createTime)) ) { - UDF_I_CRTIME(inode) = convtime; - UDF_I_UCRTIME(inode) = convtime_usec; + UDF_I_CRTIME(inode).tv_sec = convtime; + UDF_I_CRTIME(inode).tv_nsec = convtime_usec * 1000; } else { UDF_I_CRTIME(inode) = UDF_SB_RECORDTIME(inode->i_sb); - UDF_I_UCRTIME(inode) = 0; } if ( udf_stamp_to_time(&convtime, &convtime_usec, lets_to_cpu(efe->attrTime)) ) { inode->i_ctime.tv_sec = convtime; - inode->i_ctime.tv_nsec = 0; - UDF_I_UCTIME(inode) = convtime_usec; + inode->i_ctime.tv_nsec = convtime_usec * 1000; } else { - inode->i_ctime.tv_sec = UDF_SB_RECORDTIME(inode->i_sb); - inode->i_ctime.tv_nsec = 0; - UDF_I_UCTIME(inode) = 0; + inode->i_ctime = UDF_SB_RECORDTIME(inode->i_sb); } UDF_I_UNIQUE(inode) = le64_to_cpu(efe->uniqueID); @@ -1423,11 +1401,11 @@ (inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >> (inode->i_sb->s_blocksize_bits - 9)); - if (udf_time_to_stamp(&cpu_time, inode->i_atime.tv_sec, 0)) + if (udf_time_to_stamp(&cpu_time, inode->i_atime)) fe->accessTime = cpu_to_lets(cpu_time); - if (udf_time_to_stamp(&cpu_time, inode->i_mtime.tv_sec, UDF_I_UMTIME(inode))) + if (udf_time_to_stamp(&cpu_time, inode->i_mtime)) fe->modificationTime = cpu_to_lets(cpu_time); - if (udf_time_to_stamp(&cpu_time, inode->i_ctime.tv_sec, UDF_I_UCTIME(inode))) + if (udf_time_to_stamp(&cpu_time, inode->i_ctime)) fe->attrTime = cpu_to_lets(cpu_time); memset(&(fe->impIdent), 0, sizeof(regid)); strcpy(fe->impIdent.ident, UDF_ID_DEVELOPER); @@ -1447,33 +1425,32 @@ (inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >> (inode->i_sb->s_blocksize_bits - 9)); - if (UDF_I_CRTIME(inode) >= inode->i_atime.tv_sec) + if (UDF_I_CRTIME(inode).tv_sec > inode->i_atime.tv_sec || + (UDF_I_CRTIME(inode).tv_sec == inode->i_atime.tv_sec && + UDF_I_CRTIME(inode).tv_nsec > inode->i_atime.tv_nsec)) { - UDF_I_CRTIME(inode) = inode->i_atime.tv_sec; - UDF_I_UCRTIME(inode) = 0; + UDF_I_CRTIME(inode) = inode->i_atime; } - if (UDF_I_CRTIME(inode) > inode->i_mtime.tv_sec || - (UDF_I_CRTIME(inode) == inode->i_mtime.tv_sec && - UDF_I_UCRTIME(inode) > UDF_I_UMTIME(inode))) + if (UDF_I_CRTIME(inode).tv_sec > inode->i_mtime.tv_sec || + (UDF_I_CRTIME(inode).tv_sec == inode->i_mtime.tv_sec && + UDF_I_CRTIME(inode).tv_nsec > inode->i_mtime.tv_nsec)) { - UDF_I_CRTIME(inode) = inode->i_mtime.tv_sec; - UDF_I_UCRTIME(inode) = UDF_I_UMTIME(inode); + UDF_I_CRTIME(inode) = inode->i_mtime; } - if (UDF_I_CRTIME(inode) > inode->i_ctime.tv_sec || - (UDF_I_CRTIME(inode) == inode->i_ctime.tv_sec && - UDF_I_UCRTIME(inode) > UDF_I_UCTIME(inode))) + if (UDF_I_CRTIME(inode).tv_sec > inode->i_ctime.tv_sec || + (UDF_I_CRTIME(inode).tv_sec == inode->i_ctime.tv_sec && + UDF_I_CRTIME(inode).tv_nsec > inode->i_ctime.tv_nsec)) { - UDF_I_CRTIME(inode) = inode->i_ctime.tv_sec; - UDF_I_UCRTIME(inode) = UDF_I_UCTIME(inode); + UDF_I_CRTIME(inode) = inode->i_ctime; } - if (udf_time_to_stamp(&cpu_time, inode->i_atime.tv_sec, 0)) + if (udf_time_to_stamp(&cpu_time, inode->i_atime)) efe->accessTime = cpu_to_lets(cpu_time); - if (udf_time_to_stamp(&cpu_time, inode->i_mtime.tv_sec, UDF_I_UMTIME(inode))) + if (udf_time_to_stamp(&cpu_time, inode->i_mtime)) efe->modificationTime = cpu_to_lets(cpu_time); - if (udf_time_to_stamp(&cpu_time, UDF_I_CRTIME(inode), UDF_I_UCRTIME(inode))) + if (udf_time_to_stamp(&cpu_time, UDF_I_CRTIME(inode))) efe->createTime = cpu_to_lets(cpu_time); - if (udf_time_to_stamp(&cpu_time, inode->i_ctime.tv_sec, UDF_I_UCTIME(inode))) + if (udf_time_to_stamp(&cpu_time, inode->i_ctime)) efe->attrTime = cpu_to_lets(cpu_time); memset(&(efe->impIdent), 0, sizeof(regid)); diff -Nru a/fs/udf/namei.c b/fs/udf/namei.c --- a/fs/udf/namei.c Fri Nov 22 13:41:22 2002 +++ b/fs/udf/namei.c Fri Nov 22 13:41:22 2002 @@ -669,7 +669,7 @@ return 0; } -static int udf_mknod(struct inode * dir, struct dentry * dentry, int mode, int rdev) +static int udf_mknod(struct inode * dir, struct dentry * dentry, int mode, dev_t rdev) { struct inode * inode; struct udf_fileident_bh fibh; @@ -882,7 +882,6 @@ mark_inode_dirty(inode); dir->i_nlink --; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; - UDF_I_UCTIME(inode) = UDF_I_UCTIME(dir) = UDF_I_UMTIME(dir) = CURRENT_UTIME; mark_inode_dirty(dir); end_rmdir: @@ -926,7 +925,6 @@ if (retval) goto end_unlink; dir->i_ctime = dir->i_mtime = CURRENT_TIME; - UDF_I_UCTIME(dir) = UDF_I_UMTIME(dir) = CURRENT_UTIME; mark_inode_dirty(dir); inode->i_nlink--; mark_inode_dirty(inode); @@ -1157,7 +1155,6 @@ udf_release_data(fibh.sbh); inode->i_nlink ++; inode->i_ctime = CURRENT_TIME; - UDF_I_UCTIME(inode) = CURRENT_UTIME; mark_inode_dirty(inode); atomic_inc(&inode->i_count); d_instantiate(dentry, inode); @@ -1251,7 +1248,6 @@ * rename. */ old_inode->i_ctime = CURRENT_TIME; - UDF_I_UCTIME(old_inode) = CURRENT_UTIME; mark_inode_dirty(old_inode); /* @@ -1270,11 +1266,9 @@ { new_inode->i_nlink--; new_inode->i_ctime = CURRENT_TIME; - UDF_I_UCTIME(new_inode) = CURRENT_UTIME; mark_inode_dirty(new_inode); } old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; - UDF_I_UCTIME(old_dir) = UDF_I_UMTIME(old_dir) = CURRENT_UTIME; mark_inode_dirty(old_dir); if (dir_fi) diff -Nru a/fs/udf/super.c b/fs/udf/super.c --- a/fs/udf/super.c Fri Nov 22 13:41:21 2002 +++ b/fs/udf/super.c Fri Nov 22 13:41:21 2002 @@ -800,7 +800,8 @@ udf_debug("recording time %ld/%ld, %04u/%02u/%02u %02u:%02u (%x)\n", recording, recording_usec, ts.year, ts.month, ts.day, ts.hour, ts.minute, ts.typeAndTimezone); - UDF_SB_RECORDTIME(sb) = recording; + UDF_SB_RECORDTIME(sb).tv_sec = recording; + UDF_SB_RECORDTIME(sb).tv_nsec = recording_usec * 1000; } if ( !udf_build_ustr(&instr, pvoldesc->volIdent, 32) ) @@ -1339,7 +1340,7 @@ UDF_SB_LVIDIU(sb)->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; UDF_SB_LVIDIU(sb)->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; - if (udf_time_to_stamp(&cpu_time, get_seconds(), CURRENT_UTIME)) + if (udf_time_to_stamp(&cpu_time, CURRENT_TIME)) UDF_SB_LVID(sb)->recordingDateAndTime = cpu_to_lets(cpu_time); UDF_SB_LVID(sb)->integrityType = LVID_INTEGRITY_TYPE_OPEN; @@ -1367,7 +1368,7 @@ UDF_SB_LVIDIU(sb)->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; UDF_SB_LVIDIU(sb)->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; - if (udf_time_to_stamp(&cpu_time, get_seconds(), CURRENT_UTIME)) + if (udf_time_to_stamp(&cpu_time, CURRENT_TIME)) UDF_SB_LVID(sb)->recordingDateAndTime = cpu_to_lets(cpu_time); if (UDF_MAX_WRITE_VERSION > le16_to_cpu(UDF_SB_LVIDIU(sb)->maxUDFWriteRev)) UDF_SB_LVIDIU(sb)->maxUDFWriteRev = cpu_to_le16(UDF_MAX_WRITE_VERSION); @@ -1536,7 +1537,7 @@ if (!silent) { timestamp ts; - udf_time_to_stamp(&ts, UDF_SB_RECORDTIME(sb), 0); + udf_time_to_stamp(&ts, UDF_SB_RECORDTIME(sb)); udf_info("UDF %s (%s) Mounting volume '%s', timestamp %04u/%02u/%02u %02u:%02u (%x)\n", UDFFS_VERSION, UDFFS_DATE, UDF_SB_VOLIDENT(sb), ts.year, ts.month, ts.day, ts.hour, ts.minute, diff -Nru a/fs/udf/udf_i.h b/fs/udf/udf_i.h --- a/fs/udf/udf_i.h Fri Nov 22 13:41:21 2002 +++ b/fs/udf/udf_i.h Fri Nov 22 13:41:21 2002 @@ -18,10 +18,7 @@ #define UDF_I_STRAT4096(X) ( UDF_I(X)->i_strat4096 ) #define UDF_I_NEXT_ALLOC_BLOCK(X) ( UDF_I(X)->i_next_alloc_block ) #define UDF_I_NEXT_ALLOC_GOAL(X) ( UDF_I(X)->i_next_alloc_goal ) -#define UDF_I_UMTIME(X) ( UDF_I(X)->i_umtime ) -#define UDF_I_UCTIME(X) ( UDF_I(X)->i_uctime ) #define UDF_I_CRTIME(X) ( UDF_I(X)->i_crtime ) -#define UDF_I_UCRTIME(X) ( UDF_I(X)->i_ucrtime ) #define UDF_I_SAD(X) ( UDF_I(X)->i_ext.i_sad ) #define UDF_I_LAD(X) ( UDF_I(X)->i_ext.i_lad ) #define UDF_I_DATA(X) ( UDF_I(X)->i_ext.i_data ) diff -Nru a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h --- a/fs/udf/udfdecl.h Fri Nov 22 13:41:19 2002 +++ b/fs/udf/udfdecl.h Fri Nov 22 13:41:19 2002 @@ -28,8 +28,6 @@ #define UDF_NAME_LEN 255 #define UDF_PATH_LEN 1023 -#define CURRENT_UTIME (xtime.tv_nsec / 1000) - #define udf_file_entry_alloc_offset(inode)\ (UDF_I_USE(inode) ?\ sizeof(struct unallocSpaceEntry) :\ @@ -185,6 +183,6 @@ /* udftime.c */ extern time_t *udf_stamp_to_time(time_t *, long *, timestamp); -extern timestamp *udf_time_to_stamp(timestamp *, time_t, long); +extern timestamp *udf_time_to_stamp(timestamp *, struct timespec); #endif /* __UDF_DECL_H */ diff -Nru a/fs/udf/udftime.c b/fs/udf/udftime.c --- a/fs/udf/udftime.c Fri Nov 22 13:41:20 2002 +++ b/fs/udf/udftime.c Fri Nov 22 13:41:20 2002 @@ -121,7 +121,7 @@ timestamp * -udf_time_to_stamp(timestamp *dest, time_t tv_sec, long tv_usec) +udf_time_to_stamp(timestamp *dest, struct timespec ts) { long int days, rem, y; const unsigned short int *ip; @@ -134,9 +134,9 @@ dest->typeAndTimezone = 0x1000 | (offset & 0x0FFF); - tv_sec += offset * 60; - days = tv_sec / SECS_PER_DAY; - rem = tv_sec % SECS_PER_DAY; + ts.tv_sec += offset * 60; + days = ts.tv_sec / SECS_PER_DAY; + rem = ts.tv_sec % SECS_PER_DAY; dest->hour = rem / SECS_PER_HOUR; rem %= SECS_PER_HOUR; dest->minute = rem / 60; @@ -164,9 +164,9 @@ dest->month = y + 1; dest->day = days + 1; - dest->centiseconds = tv_usec / 10000; - dest->hundredsOfMicroseconds = (tv_usec - dest->centiseconds * 10000) / 100; - dest->microseconds = (tv_usec - dest->centiseconds * 10000 - + dest->centiseconds = ts.tv_nsec / 10000000; + dest->hundredsOfMicroseconds = (ts.tv_nsec / 1000 - dest->centiseconds * 10000) / 100; + dest->microseconds = (ts.tv_nsec / 1000 - dest->centiseconds * 10000 - dest->hundredsOfMicroseconds * 100); return dest; } diff -Nru a/fs/ufs/namei.c b/fs/ufs/namei.c --- a/fs/ufs/namei.c Fri Nov 22 13:41:23 2002 +++ b/fs/ufs/namei.c Fri Nov 22 13:41:23 2002 @@ -108,7 +108,7 @@ return err; } -static int ufs_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev) +static int ufs_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_t rdev) { struct inode * inode = ufs_new_inode(dir, mode); int err = PTR_ERR(inode); diff -Nru a/fs/umsdos/namei.c b/fs/umsdos/namei.c --- a/fs/umsdos/namei.c Fri Nov 22 13:41:22 2002 +++ b/fs/umsdos/namei.c Fri Nov 22 13:41:22 2002 @@ -237,7 +237,7 @@ * The same is true for directory creation. */ static int umsdos_create_any (struct inode *dir, struct dentry *dentry, - int mode, int rdev, char flags) + int mode, dev_t rdev, char flags) { struct dentry *fake; struct inode *inode; @@ -861,7 +861,7 @@ * in particular and other parts of the kernel I guess. */ int UMSDOS_mknod (struct inode *dir, struct dentry *dentry, - int mode, int rdev) + int mode, dev_t rdev) { return umsdos_create_any (dir, dentry, mode, rdev, 0); } diff -Nru a/fs/xfs/linux/xfs_iops.c b/fs/xfs/linux/xfs_iops.c --- a/fs/xfs/linux/xfs_iops.c Fri Nov 22 13:41:18 2002 +++ b/fs/xfs/linux/xfs_iops.c Fri Nov 22 13:41:18 2002 @@ -69,7 +69,7 @@ struct inode *dir, struct dentry *dentry, int mode, - int rdev) + dev_t rdev) { struct inode *ip; vattr_t va; diff -Nru a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c --- a/fs/xfs/xfs_iget.c Fri Nov 22 13:41:23 2002 +++ b/fs/xfs/xfs_iget.c Fri Nov 22 13:41:23 2002 @@ -247,8 +247,8 @@ /* * Read the disk inode attributes into a new inode structure and get * a new vnode for it. Initialize the inode lock so we can idestroy - * it soon if it's a dup. This should also initialize i_dev, i_ino, - * i_bno, i_mount, and i_index. + * it soon if it's a dup. This should also initialize i_ino, i_bno, + * i_mount, and i_index. */ error = xfs_iread(mp, tp, ino, &ip, bno); if (error) { diff -Nru a/fs/xfs/xfsidbg.c b/fs/xfs/xfsidbg.c --- a/fs/xfs/xfsidbg.c Fri Nov 22 13:41:22 2002 +++ b/fs/xfs/xfsidbg.c Fri Nov 22 13:41:22 2002 @@ -1639,7 +1639,7 @@ kdb_printf(" i_ino = %lu i_count = %u i_dev = 0x%x i_size %Ld\n", ip->i_ino, atomic_read(&ip->i_count), - ip->i_dev, ip->i_size); + ip->i_sb->s_dev, ip->i_size); kdb_printf( " i_mode = 0x%x i_nlink = %d i_rdev = 0x%x i_state = 0x%lx\n", diff -Nru a/include/asm-alpha/hardirq.h b/include/asm-alpha/hardirq.h --- a/include/asm-alpha/hardirq.h Fri Nov 22 13:41:21 2002 +++ b/include/asm-alpha/hardirq.h Fri Nov 22 13:41:21 2002 @@ -3,6 +3,8 @@ #include #include +#include + /* entry.S is sensitive to the offsets of these fields */ typedef struct { diff -Nru a/include/asm-alpha/module.h b/include/asm-alpha/module.h --- a/include/asm-alpha/module.h Fri Nov 22 13:41:18 2002 +++ b/include/asm-alpha/module.h Fri Nov 22 13:41:18 2002 @@ -1,28 +1,6 @@ #ifndef _ASM_ALPHA_MODULE_H #define _ASM_ALPHA_MODULE_H -/* - * This file contains the alpha architecture specific module code. - */ -#define module_map(x) vmalloc(x) -#define module_unmap(x) vfree(x) -#define module_arch_init(x) alpha_module_init(x) -#define arch_init_modules(x) alpha_init_modules(x) - -static inline int -alpha_module_init(struct module *mod) -{ - if (!mod_bound(mod->gp - 0x8000, 0, mod)) { - printk(KERN_ERR "module_arch_init: mod->gp out of bounds.\n"); - return 1; - } - return 0; -} - -static inline void -alpha_init_modules(struct module *mod) -{ - __asm__("stq $29,%0" : "=m" (mod->gp)); -} +/* Module rewrite still in progress. */ #endif /* _ASM_ALPHA_MODULE_H */ diff -Nru a/include/asm-alpha/suspend.h b/include/asm-alpha/suspend.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/asm-alpha/suspend.h Fri Nov 22 13:41:23 2002 @@ -0,0 +1,6 @@ +#ifndef __ALPHA_SUSPEND_H +#define __ALPHA_SUSPEND_H + +/* Dummy include. */ + +#endif /* __ALPHA_SUSPEND_H */ diff -Nru a/include/asm-alpha/unistd.h b/include/asm-alpha/unistd.h --- a/include/asm-alpha/unistd.h Fri Nov 22 13:41:19 2002 +++ b/include/asm-alpha/unistd.h Fri Nov 22 13:41:19 2002 @@ -343,7 +343,13 @@ #define __NR_alloc_hugepages 403 #define __NR_free_hugepages 404 #define __NR_exit_group 405 -#define NR_SYSCALLS 406 +#define __NR_lookup_dcookie 406 +#define __NR_sys_epoll_create 407 +#define __NR_sys_epoll_ctl 408 +#define __NR_sys_epoll_wait 409 +#define __NR_remap_file_pages 410 +#define __NR_set_tid_address 411 +#define NR_SYSCALLS 412 #if defined(__GNUC__) diff -Nru a/include/asm-alpha/xor.h b/include/asm-alpha/xor.h --- a/include/asm-alpha/xor.h Fri Nov 22 13:41:22 2002 +++ b/include/asm-alpha/xor.h Fri Nov 22 13:41:22 2002 @@ -32,793 +32,793 @@ unsigned long *, unsigned long *, unsigned long *, unsigned long *); -asm(" - .text - .align 3 - .ent xor_alpha_2 -xor_alpha_2: - .prologue 0 - srl $16, 6, $16 - .align 4 -2: - ldq $0,0($17) - ldq $1,0($18) - ldq $2,8($17) - ldq $3,8($18) - - ldq $4,16($17) - ldq $5,16($18) - ldq $6,24($17) - ldq $7,24($18) - - ldq $19,32($17) - ldq $20,32($18) - ldq $21,40($17) - ldq $22,40($18) - - ldq $23,48($17) - ldq $24,48($18) - ldq $25,56($17) - xor $0,$1,$0 # 7 cycles from $1 load - - ldq $27,56($18) - xor $2,$3,$2 - stq $0,0($17) - xor $4,$5,$4 - - stq $2,8($17) - xor $6,$7,$6 - stq $4,16($17) - xor $19,$20,$19 - - stq $6,24($17) - xor $21,$22,$21 - stq $19,32($17) - xor $23,$24,$23 - - stq $21,40($17) - xor $25,$27,$25 - stq $23,48($17) - subq $16,1,$16 - - stq $25,56($17) - addq $17,64,$17 - addq $18,64,$18 - bgt $16,2b - - ret - .end xor_alpha_2 - - .align 3 - .ent xor_alpha_3 -xor_alpha_3: - .prologue 0 - srl $16, 6, $16 - .align 4 -3: - ldq $0,0($17) - ldq $1,0($18) - ldq $2,0($19) - ldq $3,8($17) - - ldq $4,8($18) - ldq $6,16($17) - ldq $7,16($18) - ldq $21,24($17) - - ldq $22,24($18) - ldq $24,32($17) - ldq $25,32($18) - ldq $5,8($19) - - ldq $20,16($19) - ldq $23,24($19) - ldq $27,32($19) - nop - - xor $0,$1,$1 # 8 cycles from $0 load - xor $3,$4,$4 # 6 cycles from $4 load - xor $6,$7,$7 # 6 cycles from $7 load - xor $21,$22,$22 # 5 cycles from $22 load - - xor $1,$2,$2 # 9 cycles from $2 load - xor $24,$25,$25 # 5 cycles from $25 load - stq $2,0($17) - xor $4,$5,$5 # 6 cycles from $5 load - - stq $5,8($17) - xor $7,$20,$20 # 7 cycles from $20 load - stq $20,16($17) - xor $22,$23,$23 # 7 cycles from $23 load - - stq $23,24($17) - xor $25,$27,$27 # 7 cycles from $27 load - stq $27,32($17) - nop - - ldq $0,40($17) - ldq $1,40($18) - ldq $3,48($17) - ldq $4,48($18) - - ldq $6,56($17) - ldq $7,56($18) - ldq $2,40($19) - ldq $5,48($19) - - ldq $20,56($19) - xor $0,$1,$1 # 4 cycles from $1 load - xor $3,$4,$4 # 5 cycles from $4 load - xor $6,$7,$7 # 5 cycles from $7 load - - xor $1,$2,$2 # 4 cycles from $2 load - xor $4,$5,$5 # 5 cycles from $5 load - stq $2,40($17) - xor $7,$20,$20 # 4 cycles from $20 load - - stq $5,48($17) - subq $16,1,$16 - stq $20,56($17) - addq $19,64,$19 - - addq $18,64,$18 - addq $17,64,$17 - bgt $16,3b - ret - .end xor_alpha_3 - - .align 3 - .ent xor_alpha_4 -xor_alpha_4: - .prologue 0 - srl $16, 6, $16 - .align 4 -4: - ldq $0,0($17) - ldq $1,0($18) - ldq $2,0($19) - ldq $3,0($20) - - ldq $4,8($17) - ldq $5,8($18) - ldq $6,8($19) - ldq $7,8($20) - - ldq $21,16($17) - ldq $22,16($18) - ldq $23,16($19) - ldq $24,16($20) - - ldq $25,24($17) - xor $0,$1,$1 # 6 cycles from $1 load - ldq $27,24($18) - xor $2,$3,$3 # 6 cycles from $3 load - - ldq $0,24($19) - xor $1,$3,$3 - ldq $1,24($20) - xor $4,$5,$5 # 7 cycles from $5 load - - stq $3,0($17) - xor $6,$7,$7 - xor $21,$22,$22 # 7 cycles from $22 load - xor $5,$7,$7 - - stq $7,8($17) - xor $23,$24,$24 # 7 cycles from $24 load - ldq $2,32($17) - xor $22,$24,$24 - - ldq $3,32($18) - ldq $4,32($19) - ldq $5,32($20) - xor $25,$27,$27 # 8 cycles from $27 load - - ldq $6,40($17) - ldq $7,40($18) - ldq $21,40($19) - ldq $22,40($20) - - stq $24,16($17) - xor $0,$1,$1 # 9 cycles from $1 load - xor $2,$3,$3 # 5 cycles from $3 load - xor $27,$1,$1 - - stq $1,24($17) - xor $4,$5,$5 # 5 cycles from $5 load - ldq $23,48($17) - ldq $24,48($18) - - ldq $25,48($19) - xor $3,$5,$5 - ldq $27,48($20) - ldq $0,56($17) - - ldq $1,56($18) - ldq $2,56($19) - xor $6,$7,$7 # 8 cycles from $6 load - ldq $3,56($20) - - stq $5,32($17) - xor $21,$22,$22 # 8 cycles from $22 load - xor $7,$22,$22 - xor $23,$24,$24 # 5 cycles from $24 load - - stq $22,40($17) - xor $25,$27,$27 # 5 cycles from $27 load - xor $24,$27,$27 - xor $0,$1,$1 # 5 cycles from $1 load - - stq $27,48($17) - xor $2,$3,$3 # 4 cycles from $3 load - xor $1,$3,$3 - subq $16,1,$16 - - stq $3,56($17) - addq $20,64,$20 - addq $19,64,$19 - addq $18,64,$18 - - addq $17,64,$17 - bgt $16,4b - ret - .end xor_alpha_4 - - .align 3 - .ent xor_alpha_5 -xor_alpha_5: - .prologue 0 - srl $16, 6, $16 - .align 4 -5: - ldq $0,0($17) - ldq $1,0($18) - ldq $2,0($19) - ldq $3,0($20) - - ldq $4,0($21) - ldq $5,8($17) - ldq $6,8($18) - ldq $7,8($19) - - ldq $22,8($20) - ldq $23,8($21) - ldq $24,16($17) - ldq $25,16($18) - - ldq $27,16($19) - xor $0,$1,$1 # 6 cycles from $1 load - ldq $28,16($20) - xor $2,$3,$3 # 6 cycles from $3 load - - ldq $0,16($21) - xor $1,$3,$3 - ldq $1,24($17) - xor $3,$4,$4 # 7 cycles from $4 load - - stq $4,0($17) - xor $5,$6,$6 # 7 cycles from $6 load - xor $7,$22,$22 # 7 cycles from $22 load - xor $6,$23,$23 # 7 cycles from $23 load - - ldq $2,24($18) - xor $22,$23,$23 - ldq $3,24($19) - xor $24,$25,$25 # 8 cycles from $25 load - - stq $23,8($17) - xor $25,$27,$27 # 8 cycles from $27 load - ldq $4,24($20) - xor $28,$0,$0 # 7 cycles from $0 load - - ldq $5,24($21) - xor $27,$0,$0 - ldq $6,32($17) - ldq $7,32($18) - - stq $0,16($17) - xor $1,$2,$2 # 6 cycles from $2 load - ldq $22,32($19) - xor $3,$4,$4 # 4 cycles from $4 load - - ldq $23,32($20) - xor $2,$4,$4 - ldq $24,32($21) - ldq $25,40($17) - - ldq $27,40($18) - ldq $28,40($19) - ldq $0,40($20) - xor $4,$5,$5 # 7 cycles from $5 load - - stq $5,24($17) - xor $6,$7,$7 # 7 cycles from $7 load - ldq $1,40($21) - ldq $2,48($17) - - ldq $3,48($18) - xor $7,$22,$22 # 7 cycles from $22 load - ldq $4,48($19) - xor $23,$24,$24 # 6 cycles from $24 load - - ldq $5,48($20) - xor $22,$24,$24 - ldq $6,48($21) - xor $25,$27,$27 # 7 cycles from $27 load - - stq $24,32($17) - xor $27,$28,$28 # 8 cycles from $28 load - ldq $7,56($17) - xor $0,$1,$1 # 6 cycles from $1 load - - ldq $22,56($18) - ldq $23,56($19) - ldq $24,56($20) - ldq $25,56($21) - - xor $28,$1,$1 - xor $2,$3,$3 # 9 cycles from $3 load - xor $3,$4,$4 # 9 cycles from $4 load - xor $5,$6,$6 # 8 cycles from $6 load - - stq $1,40($17) - xor $4,$6,$6 - xor $7,$22,$22 # 7 cycles from $22 load - xor $23,$24,$24 # 6 cycles from $24 load - - stq $6,48($17) - xor $22,$24,$24 - subq $16,1,$16 - xor $24,$25,$25 # 8 cycles from $25 load - - stq $25,56($17) - addq $21,64,$21 - addq $20,64,$20 - addq $19,64,$19 - - addq $18,64,$18 - addq $17,64,$17 - bgt $16,5b - ret - .end xor_alpha_5 - - .align 3 - .ent xor_alpha_prefetch_2 -xor_alpha_prefetch_2: - .prologue 0 - srl $16, 6, $16 - - ldq $31, 0($17) - ldq $31, 0($18) - - ldq $31, 64($17) - ldq $31, 64($18) - - ldq $31, 128($17) - ldq $31, 128($18) - - ldq $31, 192($17) - ldq $31, 192($18) - .align 4 -2: - ldq $0,0($17) - ldq $1,0($18) - ldq $2,8($17) - ldq $3,8($18) - - ldq $4,16($17) - ldq $5,16($18) - ldq $6,24($17) - ldq $7,24($18) - - ldq $19,32($17) - ldq $20,32($18) - ldq $21,40($17) - ldq $22,40($18) - - ldq $23,48($17) - ldq $24,48($18) - ldq $25,56($17) - ldq $27,56($18) - - ldq $31,256($17) - xor $0,$1,$0 # 8 cycles from $1 load - ldq $31,256($18) - xor $2,$3,$2 - - stq $0,0($17) - xor $4,$5,$4 - stq $2,8($17) - xor $6,$7,$6 - - stq $4,16($17) - xor $19,$20,$19 - stq $6,24($17) - xor $21,$22,$21 - - stq $19,32($17) - xor $23,$24,$23 - stq $21,40($17) - xor $25,$27,$25 - - stq $23,48($17) - subq $16,1,$16 - stq $25,56($17) - addq $17,64,$17 - - addq $18,64,$18 - bgt $16,2b - ret - .end xor_alpha_prefetch_2 - - .align 3 - .ent xor_alpha_prefetch_3 -xor_alpha_prefetch_3: - .prologue 0 - srl $16, 6, $16 - - ldq $31, 0($17) - ldq $31, 0($18) - ldq $31, 0($19) - - ldq $31, 64($17) - ldq $31, 64($18) - ldq $31, 64($19) - - ldq $31, 128($17) - ldq $31, 128($18) - ldq $31, 128($19) - - ldq $31, 192($17) - ldq $31, 192($18) - ldq $31, 192($19) - .align 4 -3: - ldq $0,0($17) - ldq $1,0($18) - ldq $2,0($19) - ldq $3,8($17) - - ldq $4,8($18) - ldq $6,16($17) - ldq $7,16($18) - ldq $21,24($17) - - ldq $22,24($18) - ldq $24,32($17) - ldq $25,32($18) - ldq $5,8($19) - - ldq $20,16($19) - ldq $23,24($19) - ldq $27,32($19) - nop - - xor $0,$1,$1 # 8 cycles from $0 load - xor $3,$4,$4 # 7 cycles from $4 load - xor $6,$7,$7 # 6 cycles from $7 load - xor $21,$22,$22 # 5 cycles from $22 load - - xor $1,$2,$2 # 9 cycles from $2 load - xor $24,$25,$25 # 5 cycles from $25 load - stq $2,0($17) - xor $4,$5,$5 # 6 cycles from $5 load - - stq $5,8($17) - xor $7,$20,$20 # 7 cycles from $20 load - stq $20,16($17) - xor $22,$23,$23 # 7 cycles from $23 load - - stq $23,24($17) - xor $25,$27,$27 # 7 cycles from $27 load - stq $27,32($17) - nop - - ldq $0,40($17) - ldq $1,40($18) - ldq $3,48($17) - ldq $4,48($18) - - ldq $6,56($17) - ldq $7,56($18) - ldq $2,40($19) - ldq $5,48($19) - - ldq $20,56($19) - ldq $31,256($17) - ldq $31,256($18) - ldq $31,256($19) - - xor $0,$1,$1 # 6 cycles from $1 load - xor $3,$4,$4 # 5 cycles from $4 load - xor $6,$7,$7 # 5 cycles from $7 load - xor $1,$2,$2 # 4 cycles from $2 load - - xor $4,$5,$5 # 5 cycles from $5 load - xor $7,$20,$20 # 4 cycles from $20 load - stq $2,40($17) - subq $16,1,$16 - - stq $5,48($17) - addq $19,64,$19 - stq $20,56($17) - addq $18,64,$18 - - addq $17,64,$17 - bgt $16,3b - ret - .end xor_alpha_prefetch_3 - - .align 3 - .ent xor_alpha_prefetch_4 -xor_alpha_prefetch_4: - .prologue 0 - srl $16, 6, $16 - - ldq $31, 0($17) - ldq $31, 0($18) - ldq $31, 0($19) - ldq $31, 0($20) - - ldq $31, 64($17) - ldq $31, 64($18) - ldq $31, 64($19) - ldq $31, 64($20) - - ldq $31, 128($17) - ldq $31, 128($18) - ldq $31, 128($19) - ldq $31, 128($20) - - ldq $31, 192($17) - ldq $31, 192($18) - ldq $31, 192($19) - ldq $31, 192($20) - .align 4 -4: - ldq $0,0($17) - ldq $1,0($18) - ldq $2,0($19) - ldq $3,0($20) - - ldq $4,8($17) - ldq $5,8($18) - ldq $6,8($19) - ldq $7,8($20) - - ldq $21,16($17) - ldq $22,16($18) - ldq $23,16($19) - ldq $24,16($20) - - ldq $25,24($17) - xor $0,$1,$1 # 6 cycles from $1 load - ldq $27,24($18) - xor $2,$3,$3 # 6 cycles from $3 load - - ldq $0,24($19) - xor $1,$3,$3 - ldq $1,24($20) - xor $4,$5,$5 # 7 cycles from $5 load - - stq $3,0($17) - xor $6,$7,$7 - xor $21,$22,$22 # 7 cycles from $22 load - xor $5,$7,$7 - - stq $7,8($17) - xor $23,$24,$24 # 7 cycles from $24 load - ldq $2,32($17) - xor $22,$24,$24 - - ldq $3,32($18) - ldq $4,32($19) - ldq $5,32($20) - xor $25,$27,$27 # 8 cycles from $27 load - - ldq $6,40($17) - ldq $7,40($18) - ldq $21,40($19) - ldq $22,40($20) - - stq $24,16($17) - xor $0,$1,$1 # 9 cycles from $1 load - xor $2,$3,$3 # 5 cycles from $3 load - xor $27,$1,$1 - - stq $1,24($17) - xor $4,$5,$5 # 5 cycles from $5 load - ldq $23,48($17) - xor $3,$5,$5 - - ldq $24,48($18) - ldq $25,48($19) - ldq $27,48($20) - ldq $0,56($17) - - ldq $1,56($18) - ldq $2,56($19) - ldq $3,56($20) - xor $6,$7,$7 # 8 cycles from $6 load - - ldq $31,256($17) - xor $21,$22,$22 # 8 cycles from $22 load - ldq $31,256($18) - xor $7,$22,$22 - - ldq $31,256($19) - xor $23,$24,$24 # 6 cycles from $24 load - ldq $31,256($20) - xor $25,$27,$27 # 6 cycles from $27 load - - stq $5,32($17) - xor $24,$27,$27 - xor $0,$1,$1 # 7 cycles from $1 load - xor $2,$3,$3 # 6 cycles from $3 load - - stq $22,40($17) - xor $1,$3,$3 - stq $27,48($17) - subq $16,1,$16 - - stq $3,56($17) - addq $20,64,$20 - addq $19,64,$19 - addq $18,64,$18 - - addq $17,64,$17 - bgt $16,4b - ret - .end xor_alpha_prefetch_4 - - .align 3 - .ent xor_alpha_prefetch_5 -xor_alpha_prefetch_5: - .prologue 0 - srl $16, 6, $16 - - ldq $31, 0($17) - ldq $31, 0($18) - ldq $31, 0($19) - ldq $31, 0($20) - ldq $31, 0($21) - - ldq $31, 64($17) - ldq $31, 64($18) - ldq $31, 64($19) - ldq $31, 64($20) - ldq $31, 64($21) - - ldq $31, 128($17) - ldq $31, 128($18) - ldq $31, 128($19) - ldq $31, 128($20) - ldq $31, 128($21) - - ldq $31, 192($17) - ldq $31, 192($18) - ldq $31, 192($19) - ldq $31, 192($20) - ldq $31, 192($21) - .align 4 -5: - ldq $0,0($17) - ldq $1,0($18) - ldq $2,0($19) - ldq $3,0($20) - - ldq $4,0($21) - ldq $5,8($17) - ldq $6,8($18) - ldq $7,8($19) - - ldq $22,8($20) - ldq $23,8($21) - ldq $24,16($17) - ldq $25,16($18) - - ldq $27,16($19) - xor $0,$1,$1 # 6 cycles from $1 load - ldq $28,16($20) - xor $2,$3,$3 # 6 cycles from $3 load - - ldq $0,16($21) - xor $1,$3,$3 - ldq $1,24($17) - xor $3,$4,$4 # 7 cycles from $4 load - - stq $4,0($17) - xor $5,$6,$6 # 7 cycles from $6 load - xor $7,$22,$22 # 7 cycles from $22 load - xor $6,$23,$23 # 7 cycles from $23 load - - ldq $2,24($18) - xor $22,$23,$23 - ldq $3,24($19) - xor $24,$25,$25 # 8 cycles from $25 load - - stq $23,8($17) - xor $25,$27,$27 # 8 cycles from $27 load - ldq $4,24($20) - xor $28,$0,$0 # 7 cycles from $0 load - - ldq $5,24($21) - xor $27,$0,$0 - ldq $6,32($17) - ldq $7,32($18) - - stq $0,16($17) - xor $1,$2,$2 # 6 cycles from $2 load - ldq $22,32($19) - xor $3,$4,$4 # 4 cycles from $4 load - - ldq $23,32($20) - xor $2,$4,$4 - ldq $24,32($21) - ldq $25,40($17) - - ldq $27,40($18) - ldq $28,40($19) - ldq $0,40($20) - xor $4,$5,$5 # 7 cycles from $5 load - - stq $5,24($17) - xor $6,$7,$7 # 7 cycles from $7 load - ldq $1,40($21) - ldq $2,48($17) - - ldq $3,48($18) - xor $7,$22,$22 # 7 cycles from $22 load - ldq $4,48($19) - xor $23,$24,$24 # 6 cycles from $24 load - - ldq $5,48($20) - xor $22,$24,$24 - ldq $6,48($21) - xor $25,$27,$27 # 7 cycles from $27 load - - stq $24,32($17) - xor $27,$28,$28 # 8 cycles from $28 load - ldq $7,56($17) - xor $0,$1,$1 # 6 cycles from $1 load - - ldq $22,56($18) - ldq $23,56($19) - ldq $24,56($20) - ldq $25,56($21) - - ldq $31,256($17) - xor $28,$1,$1 - ldq $31,256($18) - xor $2,$3,$3 # 9 cycles from $3 load - - ldq $31,256($19) - xor $3,$4,$4 # 9 cycles from $4 load - ldq $31,256($20) - xor $5,$6,$6 # 8 cycles from $6 load - - stq $1,40($17) - xor $4,$6,$6 - xor $7,$22,$22 # 7 cycles from $22 load - xor $23,$24,$24 # 6 cycles from $24 load - - stq $6,48($17) - xor $22,$24,$24 - ldq $31,256($21) - xor $24,$25,$25 # 8 cycles from $25 load - - stq $25,56($17) - subq $16,1,$16 - addq $21,64,$21 - addq $20,64,$20 - - addq $19,64,$19 - addq $18,64,$18 - addq $17,64,$17 - bgt $16,5b - - ret - .end xor_alpha_prefetch_5 +asm(" \n\ + .text \n\ + .align 3 \n\ + .ent xor_alpha_2 \n\ +xor_alpha_2: \n\ + .prologue 0 \n\ + srl $16, 6, $16 \n\ + .align 4 \n\ +2: \n\ + ldq $0,0($17) \n\ + ldq $1,0($18) \n\ + ldq $2,8($17) \n\ + ldq $3,8($18) \n\ + \n\ + ldq $4,16($17) \n\ + ldq $5,16($18) \n\ + ldq $6,24($17) \n\ + ldq $7,24($18) \n\ + \n\ + ldq $19,32($17) \n\ + ldq $20,32($18) \n\ + ldq $21,40($17) \n\ + ldq $22,40($18) \n\ + \n\ + ldq $23,48($17) \n\ + ldq $24,48($18) \n\ + ldq $25,56($17) \n\ + xor $0,$1,$0 # 7 cycles from $1 load \n\ + \n\ + ldq $27,56($18) \n\ + xor $2,$3,$2 \n\ + stq $0,0($17) \n\ + xor $4,$5,$4 \n\ + \n\ + stq $2,8($17) \n\ + xor $6,$7,$6 \n\ + stq $4,16($17) \n\ + xor $19,$20,$19 \n\ + \n\ + stq $6,24($17) \n\ + xor $21,$22,$21 \n\ + stq $19,32($17) \n\ + xor $23,$24,$23 \n\ + \n\ + stq $21,40($17) \n\ + xor $25,$27,$25 \n\ + stq $23,48($17) \n\ + subq $16,1,$16 \n\ + \n\ + stq $25,56($17) \n\ + addq $17,64,$17 \n\ + addq $18,64,$18 \n\ + bgt $16,2b \n\ + \n\ + ret \n\ + .end xor_alpha_2 \n\ + \n\ + .align 3 \n\ + .ent xor_alpha_3 \n\ +xor_alpha_3: \n\ + .prologue 0 \n\ + srl $16, 6, $16 \n\ + .align 4 \n\ +3: \n\ + ldq $0,0($17) \n\ + ldq $1,0($18) \n\ + ldq $2,0($19) \n\ + ldq $3,8($17) \n\ + \n\ + ldq $4,8($18) \n\ + ldq $6,16($17) \n\ + ldq $7,16($18) \n\ + ldq $21,24($17) \n\ + \n\ + ldq $22,24($18) \n\ + ldq $24,32($17) \n\ + ldq $25,32($18) \n\ + ldq $5,8($19) \n\ + \n\ + ldq $20,16($19) \n\ + ldq $23,24($19) \n\ + ldq $27,32($19) \n\ + nop \n\ + \n\ + xor $0,$1,$1 # 8 cycles from $0 load \n\ + xor $3,$4,$4 # 6 cycles from $4 load \n\ + xor $6,$7,$7 # 6 cycles from $7 load \n\ + xor $21,$22,$22 # 5 cycles from $22 load \n\ + \n\ + xor $1,$2,$2 # 9 cycles from $2 load \n\ + xor $24,$25,$25 # 5 cycles from $25 load \n\ + stq $2,0($17) \n\ + xor $4,$5,$5 # 6 cycles from $5 load \n\ + \n\ + stq $5,8($17) \n\ + xor $7,$20,$20 # 7 cycles from $20 load \n\ + stq $20,16($17) \n\ + xor $22,$23,$23 # 7 cycles from $23 load \n\ + \n\ + stq $23,24($17) \n\ + xor $25,$27,$27 # 7 cycles from $27 load \n\ + stq $27,32($17) \n\ + nop \n\ + \n\ + ldq $0,40($17) \n\ + ldq $1,40($18) \n\ + ldq $3,48($17) \n\ + ldq $4,48($18) \n\ + \n\ + ldq $6,56($17) \n\ + ldq $7,56($18) \n\ + ldq $2,40($19) \n\ + ldq $5,48($19) \n\ + \n\ + ldq $20,56($19) \n\ + xor $0,$1,$1 # 4 cycles from $1 load \n\ + xor $3,$4,$4 # 5 cycles from $4 load \n\ + xor $6,$7,$7 # 5 cycles from $7 load \n\ + \n\ + xor $1,$2,$2 # 4 cycles from $2 load \n\ + xor $4,$5,$5 # 5 cycles from $5 load \n\ + stq $2,40($17) \n\ + xor $7,$20,$20 # 4 cycles from $20 load \n\ + \n\ + stq $5,48($17) \n\ + subq $16,1,$16 \n\ + stq $20,56($17) \n\ + addq $19,64,$19 \n\ + \n\ + addq $18,64,$18 \n\ + addq $17,64,$17 \n\ + bgt $16,3b \n\ + ret \n\ + .end xor_alpha_3 \n\ + \n\ + .align 3 \n\ + .ent xor_alpha_4 \n\ +xor_alpha_4: \n\ + .prologue 0 \n\ + srl $16, 6, $16 \n\ + .align 4 \n\ +4: \n\ + ldq $0,0($17) \n\ + ldq $1,0($18) \n\ + ldq $2,0($19) \n\ + ldq $3,0($20) \n\ + \n\ + ldq $4,8($17) \n\ + ldq $5,8($18) \n\ + ldq $6,8($19) \n\ + ldq $7,8($20) \n\ + \n\ + ldq $21,16($17) \n\ + ldq $22,16($18) \n\ + ldq $23,16($19) \n\ + ldq $24,16($20) \n\ + \n\ + ldq $25,24($17) \n\ + xor $0,$1,$1 # 6 cycles from $1 load \n\ + ldq $27,24($18) \n\ + xor $2,$3,$3 # 6 cycles from $3 load \n\ + \n\ + ldq $0,24($19) \n\ + xor $1,$3,$3 \n\ + ldq $1,24($20) \n\ + xor $4,$5,$5 # 7 cycles from $5 load \n\ + \n\ + stq $3,0($17) \n\ + xor $6,$7,$7 \n\ + xor $21,$22,$22 # 7 cycles from $22 load \n\ + xor $5,$7,$7 \n\ + \n\ + stq $7,8($17) \n\ + xor $23,$24,$24 # 7 cycles from $24 load \n\ + ldq $2,32($17) \n\ + xor $22,$24,$24 \n\ + \n\ + ldq $3,32($18) \n\ + ldq $4,32($19) \n\ + ldq $5,32($20) \n\ + xor $25,$27,$27 # 8 cycles from $27 load \n\ + \n\ + ldq $6,40($17) \n\ + ldq $7,40($18) \n\ + ldq $21,40($19) \n\ + ldq $22,40($20) \n\ + \n\ + stq $24,16($17) \n\ + xor $0,$1,$1 # 9 cycles from $1 load \n\ + xor $2,$3,$3 # 5 cycles from $3 load \n\ + xor $27,$1,$1 \n\ + \n\ + stq $1,24($17) \n\ + xor $4,$5,$5 # 5 cycles from $5 load \n\ + ldq $23,48($17) \n\ + ldq $24,48($18) \n\ + \n\ + ldq $25,48($19) \n\ + xor $3,$5,$5 \n\ + ldq $27,48($20) \n\ + ldq $0,56($17) \n\ + \n\ + ldq $1,56($18) \n\ + ldq $2,56($19) \n\ + xor $6,$7,$7 # 8 cycles from $6 load \n\ + ldq $3,56($20) \n\ + \n\ + stq $5,32($17) \n\ + xor $21,$22,$22 # 8 cycles from $22 load \n\ + xor $7,$22,$22 \n\ + xor $23,$24,$24 # 5 cycles from $24 load \n\ + \n\ + stq $22,40($17) \n\ + xor $25,$27,$27 # 5 cycles from $27 load \n\ + xor $24,$27,$27 \n\ + xor $0,$1,$1 # 5 cycles from $1 load \n\ + \n\ + stq $27,48($17) \n\ + xor $2,$3,$3 # 4 cycles from $3 load \n\ + xor $1,$3,$3 \n\ + subq $16,1,$16 \n\ + \n\ + stq $3,56($17) \n\ + addq $20,64,$20 \n\ + addq $19,64,$19 \n\ + addq $18,64,$18 \n\ + \n\ + addq $17,64,$17 \n\ + bgt $16,4b \n\ + ret \n\ + .end xor_alpha_4 \n\ + \n\ + .align 3 \n\ + .ent xor_alpha_5 \n\ +xor_alpha_5: \n\ + .prologue 0 \n\ + srl $16, 6, $16 \n\ + .align 4 \n\ +5: \n\ + ldq $0,0($17) \n\ + ldq $1,0($18) \n\ + ldq $2,0($19) \n\ + ldq $3,0($20) \n\ + \n\ + ldq $4,0($21) \n\ + ldq $5,8($17) \n\ + ldq $6,8($18) \n\ + ldq $7,8($19) \n\ + \n\ + ldq $22,8($20) \n\ + ldq $23,8($21) \n\ + ldq $24,16($17) \n\ + ldq $25,16($18) \n\ + \n\ + ldq $27,16($19) \n\ + xor $0,$1,$1 # 6 cycles from $1 load \n\ + ldq $28,16($20) \n\ + xor $2,$3,$3 # 6 cycles from $3 load \n\ + \n\ + ldq $0,16($21) \n\ + xor $1,$3,$3 \n\ + ldq $1,24($17) \n\ + xor $3,$4,$4 # 7 cycles from $4 load \n\ + \n\ + stq $4,0($17) \n\ + xor $5,$6,$6 # 7 cycles from $6 load \n\ + xor $7,$22,$22 # 7 cycles from $22 load \n\ + xor $6,$23,$23 # 7 cycles from $23 load \n\ + \n\ + ldq $2,24($18) \n\ + xor $22,$23,$23 \n\ + ldq $3,24($19) \n\ + xor $24,$25,$25 # 8 cycles from $25 load \n\ + \n\ + stq $23,8($17) \n\ + xor $25,$27,$27 # 8 cycles from $27 load \n\ + ldq $4,24($20) \n\ + xor $28,$0,$0 # 7 cycles from $0 load \n\ + \n\ + ldq $5,24($21) \n\ + xor $27,$0,$0 \n\ + ldq $6,32($17) \n\ + ldq $7,32($18) \n\ + \n\ + stq $0,16($17) \n\ + xor $1,$2,$2 # 6 cycles from $2 load \n\ + ldq $22,32($19) \n\ + xor $3,$4,$4 # 4 cycles from $4 load \n\ + \n\ + ldq $23,32($20) \n\ + xor $2,$4,$4 \n\ + ldq $24,32($21) \n\ + ldq $25,40($17) \n\ + \n\ + ldq $27,40($18) \n\ + ldq $28,40($19) \n\ + ldq $0,40($20) \n\ + xor $4,$5,$5 # 7 cycles from $5 load \n\ + \n\ + stq $5,24($17) \n\ + xor $6,$7,$7 # 7 cycles from $7 load \n\ + ldq $1,40($21) \n\ + ldq $2,48($17) \n\ + \n\ + ldq $3,48($18) \n\ + xor $7,$22,$22 # 7 cycles from $22 load \n\ + ldq $4,48($19) \n\ + xor $23,$24,$24 # 6 cycles from $24 load \n\ + \n\ + ldq $5,48($20) \n\ + xor $22,$24,$24 \n\ + ldq $6,48($21) \n\ + xor $25,$27,$27 # 7 cycles from $27 load \n\ + \n\ + stq $24,32($17) \n\ + xor $27,$28,$28 # 8 cycles from $28 load \n\ + ldq $7,56($17) \n\ + xor $0,$1,$1 # 6 cycles from $1 load \n\ + \n\ + ldq $22,56($18) \n\ + ldq $23,56($19) \n\ + ldq $24,56($20) \n\ + ldq $25,56($21) \n\ + \n\ + xor $28,$1,$1 \n\ + xor $2,$3,$3 # 9 cycles from $3 load \n\ + xor $3,$4,$4 # 9 cycles from $4 load \n\ + xor $5,$6,$6 # 8 cycles from $6 load \n\ + \n\ + stq $1,40($17) \n\ + xor $4,$6,$6 \n\ + xor $7,$22,$22 # 7 cycles from $22 load \n\ + xor $23,$24,$24 # 6 cycles from $24 load \n\ + \n\ + stq $6,48($17) \n\ + xor $22,$24,$24 \n\ + subq $16,1,$16 \n\ + xor $24,$25,$25 # 8 cycles from $25 load \n\ + \n\ + stq $25,56($17) \n\ + addq $21,64,$21 \n\ + addq $20,64,$20 \n\ + addq $19,64,$19 \n\ + \n\ + addq $18,64,$18 \n\ + addq $17,64,$17 \n\ + bgt $16,5b \n\ + ret \n\ + .end xor_alpha_5 \n\ + \n\ + .align 3 \n\ + .ent xor_alpha_prefetch_2 \n\ +xor_alpha_prefetch_2: \n\ + .prologue 0 \n\ + srl $16, 6, $16 \n\ + \n\ + ldq $31, 0($17) \n\ + ldq $31, 0($18) \n\ + \n\ + ldq $31, 64($17) \n\ + ldq $31, 64($18) \n\ + \n\ + ldq $31, 128($17) \n\ + ldq $31, 128($18) \n\ + \n\ + ldq $31, 192($17) \n\ + ldq $31, 192($18) \n\ + .align 4 \n\ +2: \n\ + ldq $0,0($17) \n\ + ldq $1,0($18) \n\ + ldq $2,8($17) \n\ + ldq $3,8($18) \n\ + \n\ + ldq $4,16($17) \n\ + ldq $5,16($18) \n\ + ldq $6,24($17) \n\ + ldq $7,24($18) \n\ + \n\ + ldq $19,32($17) \n\ + ldq $20,32($18) \n\ + ldq $21,40($17) \n\ + ldq $22,40($18) \n\ + \n\ + ldq $23,48($17) \n\ + ldq $24,48($18) \n\ + ldq $25,56($17) \n\ + ldq $27,56($18) \n\ + \n\ + ldq $31,256($17) \n\ + xor $0,$1,$0 # 8 cycles from $1 load \n\ + ldq $31,256($18) \n\ + xor $2,$3,$2 \n\ + \n\ + stq $0,0($17) \n\ + xor $4,$5,$4 \n\ + stq $2,8($17) \n\ + xor $6,$7,$6 \n\ + \n\ + stq $4,16($17) \n\ + xor $19,$20,$19 \n\ + stq $6,24($17) \n\ + xor $21,$22,$21 \n\ + \n\ + stq $19,32($17) \n\ + xor $23,$24,$23 \n\ + stq $21,40($17) \n\ + xor $25,$27,$25 \n\ + \n\ + stq $23,48($17) \n\ + subq $16,1,$16 \n\ + stq $25,56($17) \n\ + addq $17,64,$17 \n\ + \n\ + addq $18,64,$18 \n\ + bgt $16,2b \n\ + ret \n\ + .end xor_alpha_prefetch_2 \n\ + \n\ + .align 3 \n\ + .ent xor_alpha_prefetch_3 \n\ +xor_alpha_prefetch_3: \n\ + .prologue 0 \n\ + srl $16, 6, $16 \n\ + \n\ + ldq $31, 0($17) \n\ + ldq $31, 0($18) \n\ + ldq $31, 0($19) \n\ + \n\ + ldq $31, 64($17) \n\ + ldq $31, 64($18) \n\ + ldq $31, 64($19) \n\ + \n\ + ldq $31, 128($17) \n\ + ldq $31, 128($18) \n\ + ldq $31, 128($19) \n\ + \n\ + ldq $31, 192($17) \n\ + ldq $31, 192($18) \n\ + ldq $31, 192($19) \n\ + .align 4 \n\ +3: \n\ + ldq $0,0($17) \n\ + ldq $1,0($18) \n\ + ldq $2,0($19) \n\ + ldq $3,8($17) \n\ + \n\ + ldq $4,8($18) \n\ + ldq $6,16($17) \n\ + ldq $7,16($18) \n\ + ldq $21,24($17) \n\ + \n\ + ldq $22,24($18) \n\ + ldq $24,32($17) \n\ + ldq $25,32($18) \n\ + ldq $5,8($19) \n\ + \n\ + ldq $20,16($19) \n\ + ldq $23,24($19) \n\ + ldq $27,32($19) \n\ + nop \n\ + \n\ + xor $0,$1,$1 # 8 cycles from $0 load \n\ + xor $3,$4,$4 # 7 cycles from $4 load \n\ + xor $6,$7,$7 # 6 cycles from $7 load \n\ + xor $21,$22,$22 # 5 cycles from $22 load \n\ + \n\ + xor $1,$2,$2 # 9 cycles from $2 load \n\ + xor $24,$25,$25 # 5 cycles from $25 load \n\ + stq $2,0($17) \n\ + xor $4,$5,$5 # 6 cycles from $5 load \n\ + \n\ + stq $5,8($17) \n\ + xor $7,$20,$20 # 7 cycles from $20 load \n\ + stq $20,16($17) \n\ + xor $22,$23,$23 # 7 cycles from $23 load \n\ + \n\ + stq $23,24($17) \n\ + xor $25,$27,$27 # 7 cycles from $27 load \n\ + stq $27,32($17) \n\ + nop \n\ + \n\ + ldq $0,40($17) \n\ + ldq $1,40($18) \n\ + ldq $3,48($17) \n\ + ldq $4,48($18) \n\ + \n\ + ldq $6,56($17) \n\ + ldq $7,56($18) \n\ + ldq $2,40($19) \n\ + ldq $5,48($19) \n\ + \n\ + ldq $20,56($19) \n\ + ldq $31,256($17) \n\ + ldq $31,256($18) \n\ + ldq $31,256($19) \n\ + \n\ + xor $0,$1,$1 # 6 cycles from $1 load \n\ + xor $3,$4,$4 # 5 cycles from $4 load \n\ + xor $6,$7,$7 # 5 cycles from $7 load \n\ + xor $1,$2,$2 # 4 cycles from $2 load \n\ + \n\ + xor $4,$5,$5 # 5 cycles from $5 load \n\ + xor $7,$20,$20 # 4 cycles from $20 load \n\ + stq $2,40($17) \n\ + subq $16,1,$16 \n\ + \n\ + stq $5,48($17) \n\ + addq $19,64,$19 \n\ + stq $20,56($17) \n\ + addq $18,64,$18 \n\ + \n\ + addq $17,64,$17 \n\ + bgt $16,3b \n\ + ret \n\ + .end xor_alpha_prefetch_3 \n\ + \n\ + .align 3 \n\ + .ent xor_alpha_prefetch_4 \n\ +xor_alpha_prefetch_4: \n\ + .prologue 0 \n\ + srl $16, 6, $16 \n\ + \n\ + ldq $31, 0($17) \n\ + ldq $31, 0($18) \n\ + ldq $31, 0($19) \n\ + ldq $31, 0($20) \n\ + \n\ + ldq $31, 64($17) \n\ + ldq $31, 64($18) \n\ + ldq $31, 64($19) \n\ + ldq $31, 64($20) \n\ + \n\ + ldq $31, 128($17) \n\ + ldq $31, 128($18) \n\ + ldq $31, 128($19) \n\ + ldq $31, 128($20) \n\ + \n\ + ldq $31, 192($17) \n\ + ldq $31, 192($18) \n\ + ldq $31, 192($19) \n\ + ldq $31, 192($20) \n\ + .align 4 \n\ +4: \n\ + ldq $0,0($17) \n\ + ldq $1,0($18) \n\ + ldq $2,0($19) \n\ + ldq $3,0($20) \n\ + \n\ + ldq $4,8($17) \n\ + ldq $5,8($18) \n\ + ldq $6,8($19) \n\ + ldq $7,8($20) \n\ + \n\ + ldq $21,16($17) \n\ + ldq $22,16($18) \n\ + ldq $23,16($19) \n\ + ldq $24,16($20) \n\ + \n\ + ldq $25,24($17) \n\ + xor $0,$1,$1 # 6 cycles from $1 load \n\ + ldq $27,24($18) \n\ + xor $2,$3,$3 # 6 cycles from $3 load \n\ + \n\ + ldq $0,24($19) \n\ + xor $1,$3,$3 \n\ + ldq $1,24($20) \n\ + xor $4,$5,$5 # 7 cycles from $5 load \n\ + \n\ + stq $3,0($17) \n\ + xor $6,$7,$7 \n\ + xor $21,$22,$22 # 7 cycles from $22 load \n\ + xor $5,$7,$7 \n\ + \n\ + stq $7,8($17) \n\ + xor $23,$24,$24 # 7 cycles from $24 load \n\ + ldq $2,32($17) \n\ + xor $22,$24,$24 \n\ + \n\ + ldq $3,32($18) \n\ + ldq $4,32($19) \n\ + ldq $5,32($20) \n\ + xor $25,$27,$27 # 8 cycles from $27 load \n\ + \n\ + ldq $6,40($17) \n\ + ldq $7,40($18) \n\ + ldq $21,40($19) \n\ + ldq $22,40($20) \n\ + \n\ + stq $24,16($17) \n\ + xor $0,$1,$1 # 9 cycles from $1 load \n\ + xor $2,$3,$3 # 5 cycles from $3 load \n\ + xor $27,$1,$1 \n\ + \n\ + stq $1,24($17) \n\ + xor $4,$5,$5 # 5 cycles from $5 load \n\ + ldq $23,48($17) \n\ + xor $3,$5,$5 \n\ + \n\ + ldq $24,48($18) \n\ + ldq $25,48($19) \n\ + ldq $27,48($20) \n\ + ldq $0,56($17) \n\ + \n\ + ldq $1,56($18) \n\ + ldq $2,56($19) \n\ + ldq $3,56($20) \n\ + xor $6,$7,$7 # 8 cycles from $6 load \n\ + \n\ + ldq $31,256($17) \n\ + xor $21,$22,$22 # 8 cycles from $22 load \n\ + ldq $31,256($18) \n\ + xor $7,$22,$22 \n\ + \n\ + ldq $31,256($19) \n\ + xor $23,$24,$24 # 6 cycles from $24 load \n\ + ldq $31,256($20) \n\ + xor $25,$27,$27 # 6 cycles from $27 load \n\ + \n\ + stq $5,32($17) \n\ + xor $24,$27,$27 \n\ + xor $0,$1,$1 # 7 cycles from $1 load \n\ + xor $2,$3,$3 # 6 cycles from $3 load \n\ + \n\ + stq $22,40($17) \n\ + xor $1,$3,$3 \n\ + stq $27,48($17) \n\ + subq $16,1,$16 \n\ + \n\ + stq $3,56($17) \n\ + addq $20,64,$20 \n\ + addq $19,64,$19 \n\ + addq $18,64,$18 \n\ + \n\ + addq $17,64,$17 \n\ + bgt $16,4b \n\ + ret \n\ + .end xor_alpha_prefetch_4 \n\ + \n\ + .align 3 \n\ + .ent xor_alpha_prefetch_5 \n\ +xor_alpha_prefetch_5: \n\ + .prologue 0 \n\ + srl $16, 6, $16 \n\ + \n\ + ldq $31, 0($17) \n\ + ldq $31, 0($18) \n\ + ldq $31, 0($19) \n\ + ldq $31, 0($20) \n\ + ldq $31, 0($21) \n\ + \n\ + ldq $31, 64($17) \n\ + ldq $31, 64($18) \n\ + ldq $31, 64($19) \n\ + ldq $31, 64($20) \n\ + ldq $31, 64($21) \n\ + \n\ + ldq $31, 128($17) \n\ + ldq $31, 128($18) \n\ + ldq $31, 128($19) \n\ + ldq $31, 128($20) \n\ + ldq $31, 128($21) \n\ + \n\ + ldq $31, 192($17) \n\ + ldq $31, 192($18) \n\ + ldq $31, 192($19) \n\ + ldq $31, 192($20) \n\ + ldq $31, 192($21) \n\ + .align 4 \n\ +5: \n\ + ldq $0,0($17) \n\ + ldq $1,0($18) \n\ + ldq $2,0($19) \n\ + ldq $3,0($20) \n\ + \n\ + ldq $4,0($21) \n\ + ldq $5,8($17) \n\ + ldq $6,8($18) \n\ + ldq $7,8($19) \n\ + \n\ + ldq $22,8($20) \n\ + ldq $23,8($21) \n\ + ldq $24,16($17) \n\ + ldq $25,16($18) \n\ + \n\ + ldq $27,16($19) \n\ + xor $0,$1,$1 # 6 cycles from $1 load \n\ + ldq $28,16($20) \n\ + xor $2,$3,$3 # 6 cycles from $3 load \n\ + \n\ + ldq $0,16($21) \n\ + xor $1,$3,$3 \n\ + ldq $1,24($17) \n\ + xor $3,$4,$4 # 7 cycles from $4 load \n\ + \n\ + stq $4,0($17) \n\ + xor $5,$6,$6 # 7 cycles from $6 load \n\ + xor $7,$22,$22 # 7 cycles from $22 load \n\ + xor $6,$23,$23 # 7 cycles from $23 load \n\ + \n\ + ldq $2,24($18) \n\ + xor $22,$23,$23 \n\ + ldq $3,24($19) \n\ + xor $24,$25,$25 # 8 cycles from $25 load \n\ + \n\ + stq $23,8($17) \n\ + xor $25,$27,$27 # 8 cycles from $27 load \n\ + ldq $4,24($20) \n\ + xor $28,$0,$0 # 7 cycles from $0 load \n\ + \n\ + ldq $5,24($21) \n\ + xor $27,$0,$0 \n\ + ldq $6,32($17) \n\ + ldq $7,32($18) \n\ + \n\ + stq $0,16($17) \n\ + xor $1,$2,$2 # 6 cycles from $2 load \n\ + ldq $22,32($19) \n\ + xor $3,$4,$4 # 4 cycles from $4 load \n\ + \n\ + ldq $23,32($20) \n\ + xor $2,$4,$4 \n\ + ldq $24,32($21) \n\ + ldq $25,40($17) \n\ + \n\ + ldq $27,40($18) \n\ + ldq $28,40($19) \n\ + ldq $0,40($20) \n\ + xor $4,$5,$5 # 7 cycles from $5 load \n\ + \n\ + stq $5,24($17) \n\ + xor $6,$7,$7 # 7 cycles from $7 load \n\ + ldq $1,40($21) \n\ + ldq $2,48($17) \n\ + \n\ + ldq $3,48($18) \n\ + xor $7,$22,$22 # 7 cycles from $22 load \n\ + ldq $4,48($19) \n\ + xor $23,$24,$24 # 6 cycles from $24 load \n\ + \n\ + ldq $5,48($20) \n\ + xor $22,$24,$24 \n\ + ldq $6,48($21) \n\ + xor $25,$27,$27 # 7 cycles from $27 load \n\ + \n\ + stq $24,32($17) \n\ + xor $27,$28,$28 # 8 cycles from $28 load \n\ + ldq $7,56($17) \n\ + xor $0,$1,$1 # 6 cycles from $1 load \n\ + \n\ + ldq $22,56($18) \n\ + ldq $23,56($19) \n\ + ldq $24,56($20) \n\ + ldq $25,56($21) \n\ + \n\ + ldq $31,256($17) \n\ + xor $28,$1,$1 \n\ + ldq $31,256($18) \n\ + xor $2,$3,$3 # 9 cycles from $3 load \n\ + \n\ + ldq $31,256($19) \n\ + xor $3,$4,$4 # 9 cycles from $4 load \n\ + ldq $31,256($20) \n\ + xor $5,$6,$6 # 8 cycles from $6 load \n\ + \n\ + stq $1,40($17) \n\ + xor $4,$6,$6 \n\ + xor $7,$22,$22 # 7 cycles from $22 load \n\ + xor $23,$24,$24 # 6 cycles from $24 load \n\ + \n\ + stq $6,48($17) \n\ + xor $22,$24,$24 \n\ + ldq $31,256($21) \n\ + xor $24,$25,$25 # 8 cycles from $25 load \n\ + \n\ + stq $25,56($17) \n\ + subq $16,1,$16 \n\ + addq $21,64,$21 \n\ + addq $20,64,$20 \n\ + \n\ + addq $19,64,$19 \n\ + addq $18,64,$18 \n\ + addq $17,64,$17 \n\ + bgt $16,5b \n\ + \n\ + ret \n\ + .end xor_alpha_prefetch_5 \n\ "); static struct xor_block_template xor_block_alpha = { diff -Nru a/include/asm-arm/arch-adifcc/memory.h b/include/asm-arm/arch-adifcc/memory.h --- a/include/asm-arm/arch-adifcc/memory.h Fri Nov 22 13:41:21 2002 +++ b/include/asm-arm/arch-adifcc/memory.h Fri Nov 22 13:41:21 2002 @@ -11,14 +11,14 @@ /* * Task size: 3GB */ -#define TASK_SIZE (0xc0000000UL) +#define TASK_SIZE (0xbf000000UL) #define TASK_SIZE_26 (0x04000000UL) /* * This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) +#define TASK_UNMAPPED_BASE (0x40000000) /* * Page offset: 3GB diff -Nru a/include/asm-arm/arch-adifcc/vmalloc.h b/include/asm-arm/arch-adifcc/vmalloc.h --- a/include/asm-arm/arch-adifcc/vmalloc.h Fri Nov 22 13:41:18 2002 +++ b/include/asm-arm/arch-adifcc/vmalloc.h Fri Nov 22 13:41:18 2002 @@ -14,3 +14,6 @@ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) #define VMALLOC_VMADDR(x) ((unsigned long)(x)) #define VMALLOC_END (0xe8000000) + +#define MODULE_START (PAGE_OFFSET - 16*1048576) +#define MODULE_END (PAGE_OFFSET) diff -Nru a/include/asm-arm/arch-anakin/memory.h b/include/asm-arm/arch-anakin/memory.h --- a/include/asm-arm/arch-anakin/memory.h Fri Nov 22 13:41:23 2002 +++ b/include/asm-arm/arch-anakin/memory.h Fri Nov 22 13:41:23 2002 @@ -14,9 +14,9 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define TASK_SIZE (3u * 1024 * 1024 * 1024) +#define TASK_SIZE (0xbf000000) #define TASK_SIZE_26 (64u * 1024 * 1024) -#define TASK_UNMAPPED_BASE (1u * 1024 * 1024 * 1024) +#define TASK_UNMAPPED_BASE (0x40000000) #define PAGE_OFFSET 0xc0000000 #define PHYS_OFFSET 0x20000000 diff -Nru a/include/asm-arm/arch-anakin/vmalloc.h b/include/asm-arm/arch-anakin/vmalloc.h --- a/include/asm-arm/arch-anakin/vmalloc.h Fri Nov 22 13:41:18 2002 +++ b/include/asm-arm/arch-anakin/vmalloc.h Fri Nov 22 13:41:18 2002 @@ -23,4 +23,7 @@ #define VMALLOC_START ((VMALLOC_VMADDR(high_memory) + VMALLOC_ARCH_OFFSET) & ~(VMALLOC_ARCH_OFFSET - 1)) #define VMALLOC_END (PAGE_OFFSET + 0x10000000) +#define MODULE_START (PAGE_OFFSET - 16*1048576) +#define MODULE_END (PAGE_OFFSET) + #endif diff -Nru a/include/asm-arm/arch-cl7500/memory.h b/include/asm-arm/arch-cl7500/memory.h --- a/include/asm-arm/arch-cl7500/memory.h Fri Nov 22 13:41:20 2002 +++ b/include/asm-arm/arch-cl7500/memory.h Fri Nov 22 13:41:20 2002 @@ -17,14 +17,14 @@ /* * Task size: 3GB */ -#define TASK_SIZE (0xc0000000UL) +#define TASK_SIZE (0xbf000000UL) #define TASK_SIZE_26 (0x04000000UL) /* * This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) +#define TASK_UNMAPPED_BASE (0x40000000) /* * Page offset: 3GB diff -Nru a/include/asm-arm/arch-cl7500/vmalloc.h b/include/asm-arm/arch-cl7500/vmalloc.h --- a/include/asm-arm/arch-cl7500/vmalloc.h Fri Nov 22 13:41:23 2002 +++ b/include/asm-arm/arch-cl7500/vmalloc.h Fri Nov 22 13:41:23 2002 @@ -14,3 +14,7 @@ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) #define VMALLOC_VMADDR(x) ((unsigned long)(x)) #define VMALLOC_END (PAGE_OFFSET + 0x1c000000) + +#define MODULE_START (PAGE_OFFSET - 16*1048576) +#define MODULE_END (PAGE_OFFSET) + diff -Nru a/include/asm-arm/arch-clps711x/memory.h b/include/asm-arm/arch-clps711x/memory.h --- a/include/asm-arm/arch-clps711x/memory.h Fri Nov 22 13:41:17 2002 +++ b/include/asm-arm/arch-clps711x/memory.h Fri Nov 22 13:41:17 2002 @@ -25,14 +25,14 @@ /* * Task size: 3GB */ -#define TASK_SIZE (0xc0000000UL) +#define TASK_SIZE (0xbf000000UL) #define TASK_SIZE_26 (0x04000000UL) /* * This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) +#define TASK_UNMAPPED_BASE (0x40000000) /* * Page offset: 3GB diff -Nru a/include/asm-arm/arch-clps711x/vmalloc.h b/include/asm-arm/arch-clps711x/vmalloc.h --- a/include/asm-arm/arch-clps711x/vmalloc.h Fri Nov 22 13:41:17 2002 +++ b/include/asm-arm/arch-clps711x/vmalloc.h Fri Nov 22 13:41:17 2002 @@ -30,3 +30,6 @@ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) #define VMALLOC_VMADDR(x) ((unsigned long)(x)) #define VMALLOC_END (PAGE_OFFSET + 0x10000000) + +#define MODULE_START (PAGE_OFFSET - 16*1048576) +#define MODULE_END (PAGE_OFFSET) diff -Nru a/include/asm-arm/arch-ebsa110/memory.h b/include/asm-arm/arch-ebsa110/memory.h --- a/include/asm-arm/arch-ebsa110/memory.h Fri Nov 22 13:41:18 2002 +++ b/include/asm-arm/arch-ebsa110/memory.h Fri Nov 22 13:41:18 2002 @@ -19,14 +19,14 @@ /* * Task size: 3GB */ -#define TASK_SIZE (0xc0000000UL) +#define TASK_SIZE (0xbf000000UL) #define TASK_SIZE_26 (0x04000000UL) /* * This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) +#define TASK_UNMAPPED_BASE (0x40000000) /* * Page offset: 3GB diff -Nru a/include/asm-arm/arch-ebsa110/vmalloc.h b/include/asm-arm/arch-ebsa110/vmalloc.h --- a/include/asm-arm/arch-ebsa110/vmalloc.h Fri Nov 22 13:41:19 2002 +++ b/include/asm-arm/arch-ebsa110/vmalloc.h Fri Nov 22 13:41:19 2002 @@ -20,3 +20,6 @@ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) #define VMALLOC_VMADDR(x) ((unsigned long)(x)) #define VMALLOC_END (PAGE_OFFSET + 0x1f000000) + +#define MODULE_START (PAGE_OFFSET - 16*1048576) +#define MODULE_END (PAGE_OFFSET) diff -Nru a/include/asm-arm/arch-ebsa285/memory.h b/include/asm-arm/arch-ebsa285/memory.h --- a/include/asm-arm/arch-ebsa285/memory.h Fri Nov 22 13:41:22 2002 +++ b/include/asm-arm/arch-ebsa285/memory.h Fri Nov 22 13:41:22 2002 @@ -48,13 +48,13 @@ #if defined(CONFIG_ARCH_FOOTBRIDGE) /* Task size and page offset at 3GB */ -#define TASK_SIZE (0xc0000000UL) +#define TASK_SIZE (0xbf000000UL) #define PAGE_OFFSET (0xc0000000UL) #elif defined(CONFIG_ARCH_CO285) /* Task size and page offset at 1.5GB */ -#define TASK_SIZE (0x60000000UL) +#define TASK_SIZE (0x5f000000UL) #define PAGE_OFFSET (0x60000000UL) #else @@ -70,7 +70,7 @@ * This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) +#define TASK_UNMAPPED_BASE ((TASK_SIZE + 0x01000000) / 3) /* * The DRAM is always contiguous. diff -Nru a/include/asm-arm/arch-ebsa285/vmalloc.h b/include/asm-arm/arch-ebsa285/vmalloc.h --- a/include/asm-arm/arch-ebsa285/vmalloc.h Fri Nov 22 13:41:19 2002 +++ b/include/asm-arm/arch-ebsa285/vmalloc.h Fri Nov 22 13:41:19 2002 @@ -25,3 +25,6 @@ #else #define VMALLOC_END (PAGE_OFFSET + 0x20000000) #endif + +#define MODULE_START (PAGE_OFFSET - 16*1048576) +#define MODULE_END (PAGE_OFFSET) diff -Nru a/include/asm-arm/arch-epxa10db/memory.h b/include/asm-arm/arch-epxa10db/memory.h --- a/include/asm-arm/arch-epxa10db/memory.h Fri Nov 22 13:41:22 2002 +++ b/include/asm-arm/arch-epxa10db/memory.h Fri Nov 22 13:41:22 2002 @@ -23,14 +23,14 @@ /* * Task size: 3GB */ -#define TASK_SIZE (0xc0000000UL) +#define TASK_SIZE (0xbf000000UL) #define TASK_SIZE_26 (0x04000000UL) /* * This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) +#define TASK_UNMAPPED_BASE (0x40000000) /* * Page offset: 3GB diff -Nru a/include/asm-arm/arch-epxa10db/vmalloc.h b/include/asm-arm/arch-epxa10db/vmalloc.h --- a/include/asm-arm/arch-epxa10db/vmalloc.h Fri Nov 22 13:41:18 2002 +++ b/include/asm-arm/arch-epxa10db/vmalloc.h Fri Nov 22 13:41:18 2002 @@ -30,3 +30,6 @@ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) #define VMALLOC_VMADDR(x) ((unsigned long)(x)) #define VMALLOC_END (PAGE_OFFSET + 0x10000000) + +#define MODULE_START (PAGE_OFFSET - 16*1048576) +#define MODULE_END (PAGE_OFFSET) diff -Nru a/include/asm-arm/arch-integrator/memory.h b/include/asm-arm/arch-integrator/memory.h --- a/include/asm-arm/arch-integrator/memory.h Fri Nov 22 13:41:19 2002 +++ b/include/asm-arm/arch-integrator/memory.h Fri Nov 22 13:41:19 2002 @@ -23,14 +23,14 @@ /* * Task size: 3GB */ -#define TASK_SIZE (0xc0000000UL) +#define TASK_SIZE (0xbf000000UL) #define TASK_SIZE_26 (0x04000000UL) /* * This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) +#define TASK_UNMAPPED_BASE (0x40000000) /* * Page offset: 3GB diff -Nru a/include/asm-arm/arch-integrator/vmalloc.h b/include/asm-arm/arch-integrator/vmalloc.h --- a/include/asm-arm/arch-integrator/vmalloc.h Fri Nov 22 13:41:18 2002 +++ b/include/asm-arm/arch-integrator/vmalloc.h Fri Nov 22 13:41:18 2002 @@ -30,3 +30,6 @@ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) #define VMALLOC_VMADDR(x) ((unsigned long)(x)) #define VMALLOC_END (PAGE_OFFSET + 0x10000000) + +#define MODULE_START (PAGE_OFFSET - 16*1048576) +#define MODULE_END (PAGE_OFFSET) diff -Nru a/include/asm-arm/arch-iop310/memory.h b/include/asm-arm/arch-iop310/memory.h --- a/include/asm-arm/arch-iop310/memory.h Fri Nov 22 13:41:22 2002 +++ b/include/asm-arm/arch-iop310/memory.h Fri Nov 22 13:41:22 2002 @@ -10,14 +10,14 @@ /* * Task size: 3GB */ -#define TASK_SIZE (0xc0000000UL) +#define TASK_SIZE (0xbf000000UL) #define TASK_SIZE_26 (0x04000000UL) /* * This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) +#define TASK_UNMAPPED_BASE (0x40000000) /* * Page offset: 3GB diff -Nru a/include/asm-arm/arch-iop310/vmalloc.h b/include/asm-arm/arch-iop310/vmalloc.h --- a/include/asm-arm/arch-iop310/vmalloc.h Fri Nov 22 13:41:21 2002 +++ b/include/asm-arm/arch-iop310/vmalloc.h Fri Nov 22 13:41:21 2002 @@ -14,3 +14,6 @@ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) #define VMALLOC_VMADDR(x) ((unsigned long)(x)) #define VMALLOC_END (0xe8000000) + +#define MODULE_START (PAGE_OFFSET - 16*1048576) +#define MODULE_END (PAGE_OFFSET) diff -Nru a/include/asm-arm/arch-l7200/memory.h b/include/asm-arm/arch-l7200/memory.h --- a/include/asm-arm/arch-l7200/memory.h Fri Nov 22 13:41:22 2002 +++ b/include/asm-arm/arch-l7200/memory.h Fri Nov 22 13:41:22 2002 @@ -15,14 +15,14 @@ /* * Task size: 3GB */ -#define TASK_SIZE (0xc0000000UL) +#define TASK_SIZE (0xbf000000UL) #define TASK_SIZE_26 (0x04000000UL) /* * This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) +#define TASK_UNMAPPED_BASE (0x40000000) /* * Page offset: 3GB diff -Nru a/include/asm-arm/arch-l7200/vmalloc.h b/include/asm-arm/arch-l7200/vmalloc.h --- a/include/asm-arm/arch-l7200/vmalloc.h Fri Nov 22 13:41:18 2002 +++ b/include/asm-arm/arch-l7200/vmalloc.h Fri Nov 22 13:41:18 2002 @@ -14,3 +14,6 @@ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) #define VMALLOC_VMADDR(x) ((unsigned long)(x)) #define VMALLOC_END (PAGE_OFFSET + 0x10000000) + +#define MODULE_START (PAGE_OFFSET - 16*1048576) +#define MODULE_END (PAGE_OFFSET) diff -Nru a/include/asm-arm/arch-nexuspci/memory.h b/include/asm-arm/arch-nexuspci/memory.h --- a/include/asm-arm/arch-nexuspci/memory.h Fri Nov 22 13:41:23 2002 +++ b/include/asm-arm/arch-nexuspci/memory.h Fri Nov 22 13:41:23 2002 @@ -11,14 +11,14 @@ /* * Task size: 3GB */ -#define TASK_SIZE (0xc0000000UL) +#define TASK_SIZE (0xbf000000UL) #define TASK_SIZE_26 (0x04000000UL) /* * This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) +#define TASK_UNMAPPED_BASE (0x40000000) /* * Page offset: 3GB diff -Nru a/include/asm-arm/arch-nexuspci/vmalloc.h b/include/asm-arm/arch-nexuspci/vmalloc.h --- a/include/asm-arm/arch-nexuspci/vmalloc.h Fri Nov 22 13:41:20 2002 +++ b/include/asm-arm/arch-nexuspci/vmalloc.h Fri Nov 22 13:41:20 2002 @@ -14,3 +14,6 @@ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) #define VMALLOC_VMADDR(x) ((unsigned long)(x)) #define VMALLOC_END (PAGE_OFFSET + 0x20000000) + +#define MODULE_START (PAGE_OFFSET - 16*1048576) +#define MODULE_END (PAGE_OFFSET) diff -Nru a/include/asm-arm/arch-pxa/memory.h b/include/asm-arm/arch-pxa/memory.h --- a/include/asm-arm/arch-pxa/memory.h Fri Nov 22 13:41:19 2002 +++ b/include/asm-arm/arch-pxa/memory.h Fri Nov 22 13:41:19 2002 @@ -16,14 +16,14 @@ /* * Task size: 3GB */ -#define TASK_SIZE (0xc0000000UL) +#define TASK_SIZE (0xbf000000UL) #define TASK_SIZE_26 (0x04000000UL) /* * This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) +#define TASK_UNMAPPED_BASE (0x40000000) /* * Page offset: 3GB diff -Nru a/include/asm-arm/arch-pxa/vmalloc.h b/include/asm-arm/arch-pxa/vmalloc.h --- a/include/asm-arm/arch-pxa/vmalloc.h Fri Nov 22 13:41:20 2002 +++ b/include/asm-arm/arch-pxa/vmalloc.h Fri Nov 22 13:41:20 2002 @@ -21,3 +21,6 @@ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) #define VMALLOC_VMADDR(x) ((unsigned long)(x)) #define VMALLOC_END (0xe8000000) + +#define MODULE_START (PAGE_OFFSET - 16*1048576) +#define MODULE_END (PAGE_OFFSET) diff -Nru a/include/asm-arm/arch-rpc/memory.h b/include/asm-arm/arch-rpc/memory.h --- a/include/asm-arm/arch-rpc/memory.h Fri Nov 22 13:41:21 2002 +++ b/include/asm-arm/arch-rpc/memory.h Fri Nov 22 13:41:21 2002 @@ -21,14 +21,14 @@ /* * Task size: 3GB */ -#define TASK_SIZE (0xc0000000UL) +#define TASK_SIZE (0xbf000000UL) #define TASK_SIZE_26 (0x04000000UL) /* * This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) +#define TASK_UNMAPPED_BASE (0x40000000) /* * Page offset: 3GB diff -Nru a/include/asm-arm/arch-rpc/vmalloc.h b/include/asm-arm/arch-rpc/vmalloc.h --- a/include/asm-arm/arch-rpc/vmalloc.h Fri Nov 22 13:41:22 2002 +++ b/include/asm-arm/arch-rpc/vmalloc.h Fri Nov 22 13:41:22 2002 @@ -20,3 +20,6 @@ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) #define VMALLOC_VMADDR(x) ((unsigned long)(x)) #define VMALLOC_END (PAGE_OFFSET + 0x1c000000) + +#define MODULE_START (PAGE_OFFSET - 16*1048576) +#define MODULE_END (PAGE_OFFSET) diff -Nru a/include/asm-arm/arch-sa1100/memory.h b/include/asm-arm/arch-sa1100/memory.h --- a/include/asm-arm/arch-sa1100/memory.h Fri Nov 22 13:41:17 2002 +++ b/include/asm-arm/arch-sa1100/memory.h Fri Nov 22 13:41:17 2002 @@ -12,14 +12,14 @@ /* * Task size: 3GB */ -#define TASK_SIZE (0xc0000000UL) +#define TASK_SIZE (0xbf000000UL) #define TASK_SIZE_26 (0x04000000UL) /* * This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) +#define TASK_UNMAPPED_BASE (0x40000000) /* * Page offset: 3GB diff -Nru a/include/asm-arm/arch-sa1100/vmalloc.h b/include/asm-arm/arch-sa1100/vmalloc.h --- a/include/asm-arm/arch-sa1100/vmalloc.h Fri Nov 22 13:41:23 2002 +++ b/include/asm-arm/arch-sa1100/vmalloc.h Fri Nov 22 13:41:23 2002 @@ -14,3 +14,6 @@ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) #define VMALLOC_VMADDR(x) ((unsigned long)(x)) #define VMALLOC_END (0xe8000000) + +#define MODULE_START (PAGE_OFFSET - 16*1048576) +#define MODULE_END (PAGE_OFFSET) diff -Nru a/include/asm-arm/arch-shark/memory.h b/include/asm-arm/arch-shark/memory.h --- a/include/asm-arm/arch-shark/memory.h Fri Nov 22 13:41:23 2002 +++ b/include/asm-arm/arch-shark/memory.h Fri Nov 22 13:41:23 2002 @@ -13,14 +13,14 @@ /* * Task size: 3GB */ -#define TASK_SIZE (0xc0000000UL) +#define TASK_SIZE (0xbf000000UL) #define TASK_SIZE_26 (0x04000000UL) /* * This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) +#define TASK_UNMAPPED_BASE (0x40000000) /* * Page offset: = 3GB diff -Nru a/include/asm-arm/arch-shark/vmalloc.h b/include/asm-arm/arch-shark/vmalloc.h --- a/include/asm-arm/arch-shark/vmalloc.h Fri Nov 22 13:41:18 2002 +++ b/include/asm-arm/arch-shark/vmalloc.h Fri Nov 22 13:41:18 2002 @@ -15,3 +15,5 @@ #define VMALLOC_VMADDR(x) ((unsigned long)(x)) #define VMALLOC_END (PAGE_OFFSET + 0x10000000) +#define MODULE_START (PAGE_OFFSET - 16*1048576) +#define MODULE_END (PAGE_OFFSET) diff -Nru a/include/asm-arm/arch-tbox/memory.h b/include/asm-arm/arch-tbox/memory.h --- a/include/asm-arm/arch-tbox/memory.h Fri Nov 22 13:41:18 2002 +++ b/include/asm-arm/arch-tbox/memory.h Fri Nov 22 13:41:18 2002 @@ -10,14 +10,14 @@ /* * Task size: 3GB */ -#define TASK_SIZE (0xc0000000UL) +#define TASK_SIZE (0xbf000000UL) #define TASK_SIZE_26 (0x04000000UL) /* * This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) +#define TASK_UNMAPPED_BASE (0x40000000) /* * Page offset: 3GB diff -Nru a/include/asm-arm/arch-tbox/vmalloc.h b/include/asm-arm/arch-tbox/vmalloc.h --- a/include/asm-arm/arch-tbox/vmalloc.h Fri Nov 22 13:41:17 2002 +++ b/include/asm-arm/arch-tbox/vmalloc.h Fri Nov 22 13:41:17 2002 @@ -15,3 +15,5 @@ #define VMALLOC_VMADDR(x) ((unsigned long)(x)) #define VMALLOC_END (PAGE_OFFSET + 0x10000000) +#define MODULE_START (PAGE_OFFSET - 16*1048576) +#define MODULE_END (PAGE_OFFSET) diff -Nru a/include/asm-arm/bitops.h b/include/asm-arm/bitops.h --- a/include/asm-arm/bitops.h Fri Nov 22 13:41:17 2002 +++ b/include/asm-arm/bitops.h Fri Nov 22 13:41:17 2002 @@ -5,7 +5,7 @@ * Big endian support: Copyright 2001, Nicolas Pitre * reworked by rmk. * - * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). + * bit 0 is the LSB of an "unsigned long" quantity. * * Please note that the code in this file should never be included * from user space. Many of these are not implemented in assembler @@ -26,34 +26,39 @@ /* * These functions are the basis of our bit ops. - * First, the atomic bitops. * - * The endian issue for these functions is handled by the macros below. + * First, the atomic bitops. These use native endian. */ -static inline void -____atomic_set_bit_mask(unsigned int mask, volatile unsigned char *p) +static inline void ____atomic_set_bit(unsigned int bit, unsigned long *p) { unsigned long flags; + unsigned long mask = 1UL << (bit & 31); + + p += bit >> 5; local_irq_save(flags); *p |= mask; local_irq_restore(flags); } -static inline void -____atomic_clear_bit_mask(unsigned int mask, volatile unsigned char *p) +static inline void ____atomic_clear_bit(unsigned int bit, unsigned long *p) { unsigned long flags; + unsigned long mask = 1UL << (bit & 31); + + p += bit >> 5; local_irq_save(flags); *p &= ~mask; local_irq_restore(flags); } -static inline void -____atomic_change_bit_mask(unsigned int mask, volatile unsigned char *p) +static inline void ____atomic_change_bit(unsigned int bit, unsigned long *p) { unsigned long flags; + unsigned long mask = 1UL << (bit & 31); + + p += bit >> 5; local_irq_save(flags); *p ^= mask; @@ -61,10 +66,13 @@ } static inline int -____atomic_test_and_set_bit_mask(unsigned int mask, volatile unsigned char *p) +____atomic_test_and_set_bit(unsigned int bit, unsigned long *p) { unsigned long flags; unsigned int res; + unsigned long mask = 1UL << (bit & 31); + + p += bit >> 5; local_irq_save(flags); res = *p; @@ -75,10 +83,13 @@ } static inline int -____atomic_test_and_clear_bit_mask(unsigned int mask, volatile unsigned char *p) +____atomic_test_and_clear_bit(unsigned int bit, unsigned long *p) { unsigned long flags; unsigned int res; + unsigned long mask = 1UL << (bit & 31); + + p += bit >> 5; local_irq_save(flags); res = *p; @@ -89,10 +100,13 @@ } static inline int -____atomic_test_and_change_bit_mask(unsigned int mask, volatile unsigned char *p) +____atomic_test_and_change_bit(unsigned int bit, unsigned long *p) { unsigned long flags; unsigned int res; + unsigned long mask = 1UL << (bit & 31); + + p += bit >> 5; local_irq_save(flags); res = *p; @@ -103,61 +117,64 @@ } /* - * Now the non-atomic variants. We let the compiler handle all optimisations - * for these. + * Now the non-atomic variants. We let the compiler handle all + * optimisations for these. These are all _native_ endian. */ -static inline void ____nonatomic_set_bit(int nr, volatile void *p) +static inline void __set_bit(int nr, volatile unsigned long *p) { - ((unsigned char *) p)[nr >> 3] |= (1U << (nr & 7)); + p[nr >> 5] |= (1UL << (nr & 31)); } -static inline void ____nonatomic_clear_bit(int nr, volatile void *p) +static inline void __clear_bit(int nr, volatile unsigned long *p) { - ((unsigned char *) p)[nr >> 3] &= ~(1U << (nr & 7)); + p[nr >> 5] &= ~(1UL << (nr & 31)); } -static inline void ____nonatomic_change_bit(int nr, volatile void *p) +static inline void __change_bit(int nr, volatile unsigned long *p) { - ((unsigned char *) p)[nr >> 3] ^= (1U << (nr & 7)); + p[nr >> 5] ^= (1UL << (nr & 31)); } -static inline int ____nonatomic_test_and_set_bit(int nr, volatile void *p) +static inline int __test_and_set_bit(int nr, volatile unsigned long *p) { - unsigned int mask = 1 << (nr & 7); - unsigned int oldval; + unsigned long oldval, mask = 1UL << (nr & 31); - oldval = ((unsigned char *) p)[nr >> 3]; - ((unsigned char *) p)[nr >> 3] = oldval | mask; + p += nr >> 5; + + oldval = *p; + *p = oldval | mask; return oldval & mask; } -static inline int ____nonatomic_test_and_clear_bit(int nr, volatile void *p) +static inline int __test_and_clear_bit(int nr, volatile unsigned long *p) { - unsigned int mask = 1 << (nr & 7); - unsigned int oldval; + unsigned long oldval, mask = 1UL << (nr & 31); + + p += nr >> 5; - oldval = ((unsigned char *) p)[nr >> 3]; - ((unsigned char *) p)[nr >> 3] = oldval & ~mask; + oldval = *p; + *p = oldval & ~mask; return oldval & mask; } -static inline int ____nonatomic_test_and_change_bit(int nr, volatile void *p) +static inline int __test_and_change_bit(int nr, volatile unsigned long *p) { - unsigned int mask = 1 << (nr & 7); - unsigned int oldval; + unsigned long oldval, mask = 1UL << (nr & 31); - oldval = ((unsigned char *) p)[nr >> 3]; - ((unsigned char *) p)[nr >> 3] = oldval ^ mask; + p += nr >> 5; + + oldval = *p; + *p = oldval ^ mask; return oldval & mask; } /* * This routine doesn't need to be atomic. */ -static inline int ____test_bit(int nr, const void * p) +static inline int __test_bit(int nr, const unsigned long * p) { - return ((volatile unsigned char *) p)[nr >> 3] & (1U << (nr & 7)); -} + return p[nr >> 5] & (1UL << (nr & 31)); +} /* * A note about Endian-ness. @@ -187,24 +204,24 @@ /* * Little endian assembly bitops. nr = 0 -> byte 0 bit 0. */ -extern void _set_bit_le(int nr, volatile void * p); -extern void _clear_bit_le(int nr, volatile void * p); -extern void _change_bit_le(int nr, volatile void * p); -extern int _test_and_set_bit_le(int nr, volatile void * p); -extern int _test_and_clear_bit_le(int nr, volatile void * p); -extern int _test_and_change_bit_le(int nr, volatile void * p); +extern void _set_bit_le(int nr, unsigned long * p); +extern void _clear_bit_le(int nr, unsigned long * p); +extern void _change_bit_le(int nr, unsigned long * p); +extern int _test_and_set_bit_le(int nr, unsigned long * p); +extern int _test_and_clear_bit_le(int nr, unsigned long * p); +extern int _test_and_change_bit_le(int nr, unsigned long * p); extern int _find_first_zero_bit_le(void * p, unsigned size); extern int _find_next_zero_bit_le(void * p, int size, int offset); /* * Big endian assembly bitops. nr = 0 -> byte 3 bit 0. */ -extern void _set_bit_be(int nr, volatile void * p); -extern void _clear_bit_be(int nr, volatile void * p); -extern void _change_bit_be(int nr, volatile void * p); -extern int _test_and_set_bit_be(int nr, volatile void * p); -extern int _test_and_clear_bit_be(int nr, volatile void * p); -extern int _test_and_change_bit_be(int nr, volatile void * p); +extern void _set_bit_be(int nr, unsigned long * p); +extern void _clear_bit_be(int nr, unsigned long * p); +extern void _change_bit_be(int nr, unsigned long * p); +extern int _test_and_set_bit_be(int nr, unsigned long * p); +extern int _test_and_clear_bit_be(int nr, unsigned long * p); +extern int _test_and_change_bit_be(int nr, unsigned long * p); extern int _find_first_zero_bit_be(void * p, unsigned size); extern int _find_next_zero_bit_be(void * p, int size, int offset); @@ -214,22 +231,17 @@ */ #define ATOMIC_BITOP_LE(name,nr,p) \ (__builtin_constant_p(nr) ? \ - ____atomic_##name##_mask(1 << ((nr) & 7), \ - ((unsigned char *)(p)) + ((nr) >> 3)) : \ + ____atomic_##name(nr, p) : \ _##name##_le(nr,p)) #define ATOMIC_BITOP_BE(name,nr,p) \ (__builtin_constant_p(nr) ? \ - ____atomic_##name##_mask(1 << ((nr) & 7), \ - ((unsigned char *)(p)) + (((nr) >> 3) ^ 3)) : \ + ____atomic_##name(nr, p) : \ _##name##_be(nr,p)) -#define NONATOMIC_BITOP_LE(name,nr,p) \ +#define NONATOMIC_BITOP(name,nr,p) \ (____nonatomic_##name(nr, p)) -#define NONATOMIC_BITOP_BE(name,nr,p) \ - (____nonatomic_##name(nr ^ 0x18, p)) - #ifndef __ARMEB__ /* * These are the little endian, atomic definitions. @@ -240,20 +252,11 @@ #define test_and_set_bit(nr,p) ATOMIC_BITOP_LE(test_and_set_bit,nr,p) #define test_and_clear_bit(nr,p) ATOMIC_BITOP_LE(test_and_clear_bit,nr,p) #define test_and_change_bit(nr,p) ATOMIC_BITOP_LE(test_and_change_bit,nr,p) -#define test_bit(nr,p) ____test_bit(nr,p) +#define test_bit(nr,p) __test_bit(nr,p) #define find_first_zero_bit(p,sz) _find_first_zero_bit_le(p,sz) #define find_next_zero_bit(p,sz,off) _find_next_zero_bit_le(p,sz,off) -/* - * These are the little endian, non-atomic definitions. - */ -#define __set_bit(nr,p) NONATOMIC_BITOP_LE(set_bit,nr,p) -#define __clear_bit(nr,p) NONATOMIC_BITOP_LE(clear_bit,nr,p) -#define __change_bit(nr,p) NONATOMIC_BITOP_LE(change_bit,nr,p) -#define __test_and_set_bit(nr,p) NONATOMIC_BITOP_LE(test_and_set_bit,nr,p) -#define __test_and_clear_bit(nr,p) NONATOMIC_BITOP_LE(test_and_clear_bit,nr,p) -#define __test_and_change_bit(nr,p) NONATOMIC_BITOP_LE(test_and_change_bit,nr,p) -#define __test_bit(nr,p) ____test_bit(nr,p) +#define WORD_BITOFF_TO_LE(x) ((x)) #else @@ -266,20 +269,11 @@ #define test_and_set_bit(nr,p) ATOMIC_BITOP_BE(test_and_set_bit,nr,p) #define test_and_clear_bit(nr,p) ATOMIC_BITOP_BE(test_and_clear_bit,nr,p) #define test_and_change_bit(nr,p) ATOMIC_BITOP_BE(test_and_change_bit,nr,p) -#define test_bit(nr,p) ____test_bit((nr) ^ 0x18, p) +#define test_bit(nr,p) __test_bit(nr,p) #define find_first_zero_bit(p,sz) _find_first_zero_bit_be(p,sz) #define find_next_zero_bit(p,sz,off) _find_next_zero_bit_be(p,sz,off) -/* - * These are the big endian, non-atomic definitions. - */ -#define __set_bit(nr,p) NONATOMIC_BITOP_BE(set_bit,nr,p) -#define __clear_bit(nr,p) NONATOMIC_BITOP_BE(clear_bit,nr,p) -#define __change_bit(nr,p) NONATOMIC_BITOP_BE(change_bit,nr,p) -#define __test_and_set_bit(nr,p) NONATOMIC_BITOP_BE(test_and_set_bit,nr,p) -#define __test_and_clear_bit(nr,p) NONATOMIC_BITOP_BE(test_and_clear_bit,nr,p) -#define __test_and_change_bit(nr,p) NONATOMIC_BITOP_BE(test_and_change_bit,nr,p) -#define __test_bit(nr,p) ____test_bit((nr) ^ 0x18, p) +#define WORD_BITOFF_TO_LE(x) ((x) ^ 0x18) #endif @@ -361,21 +355,31 @@ * Ext2 is defined to use little-endian byte ordering. * These do not need to be atomic. */ -#define ext2_set_bit(nr,p) NONATOMIC_BITOP_LE(test_and_set_bit,nr,p) -#define ext2_clear_bit(nr,p) NONATOMIC_BITOP_LE(test_and_clear_bit,nr,p) -#define ext2_test_bit(nr,p) __test_bit(nr,p) -#define ext2_find_first_zero_bit(p,sz) _find_first_zero_bit_le(p,sz) -#define ext2_find_next_zero_bit(p,sz,off) _find_next_zero_bit_le(p,sz,off) +#define ext2_set_bit(nr,p) \ + __test_and_set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p)) +#define ext2_clear_bit(nr,p) \ + __test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p)) +#define ext2_test_bit(nr,p) \ + __test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p)) +#define ext2_find_first_zero_bit(p,sz) \ + _find_first_zero_bit_le(p,sz) +#define ext2_find_next_zero_bit(p,sz,off) \ + _find_next_zero_bit_le(p,sz,off) /* * Minix is defined to use little-endian byte ordering. * These do not need to be atomic. */ -#define minix_set_bit(nr,p) NONATOMIC_BITOP_LE(set_bit,nr,p) -#define minix_test_bit(nr,p) __test_bit(nr,p) -#define minix_test_and_set_bit(nr,p) NONATOMIC_BITOP_LE(test_and_set_bit,nr,p) -#define minix_test_and_clear_bit(nr,p) NONATOMIC_BITOP_LE(test_and_clear_bit,nr,p) -#define minix_find_first_zero_bit(p,sz) _find_first_zero_bit_le(p,sz) +#define minix_set_bit(nr,p) \ + __set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p)) +#define minix_test_bit(nr,p) \ + __test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p)) +#define minix_test_and_set_bit(nr,p) \ + __test_and_set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p)) +#define minix_test_and_clear_bit(nr,p) \ + __test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p)) +#define minix_find_first_zero_bit(p,sz) \ + _find_first_zero_bit_le(p,sz) #endif /* __KERNEL__ */ diff -Nru a/include/asm-arm/cpu-multi32.h b/include/asm-arm/cpu-multi32.h --- a/include/asm-arm/cpu-multi32.h Fri Nov 22 13:41:18 2002 +++ b/include/asm-arm/cpu-multi32.h Fri Nov 22 13:41:18 2002 @@ -96,7 +96,7 @@ /* * Set a PMD (handling IMP bit 4) */ - void (*set_pmd)(pmd_t *pmdp, pmd_t pmd); + void (*flush_pmd)(pmd_t *pmdp); /* * Set a PTE */ @@ -126,7 +126,7 @@ #define cpu_icache_invalidate_page(vp) processor.icache.invalidate_page(vp) #define cpu_set_pgd(pgd,mm) processor.pgtable.set_pgd(pgd,mm) -#define cpu_set_pmd(pmdp, pmd) processor.pgtable.set_pmd(pmdp, pmd) +#define cpu_flush_pmd(pmdp) processor.pgtable.flush_pmd(pmdp) #define cpu_set_pte(ptep, pte) processor.pgtable.set_pte(ptep, pte) #define cpu_switch_mm(pgd,mm) cpu_set_pgd(__virt_to_phys((unsigned long)(pgd)),mm) diff -Nru a/include/asm-arm/cpu-single.h b/include/asm-arm/cpu-single.h --- a/include/asm-arm/cpu-single.h Fri Nov 22 13:41:17 2002 +++ b/include/asm-arm/cpu-single.h Fri Nov 22 13:41:17 2002 @@ -36,7 +36,7 @@ #define cpu_icache_invalidate_range __cpu_fn(CPU_NAME,_icache_invalidate_range) #define cpu_icache_invalidate_page __cpu_fn(CPU_NAME,_icache_invalidate_page) #define cpu_set_pgd __cpu_fn(CPU_NAME,_set_pgd) -#define cpu_set_pmd __cpu_fn(CPU_NAME,_set_pmd) +#define cpu_flush_pmd __cpu_fn(CPU_NAME,_flush_pmd) #define cpu_set_pte __cpu_fn(CPU_NAME,_set_pte) #ifndef __ASSEMBLY__ @@ -65,7 +65,7 @@ extern void cpu_icache_invalidate_page(void *virt_page); extern void cpu_set_pgd(unsigned long pgd_phys, struct mm_struct *mm); -extern void cpu_set_pmd(pmd_t *pmdp, pmd_t pmd); +extern void cpu_flush_pmd(pmd_t *pmdp); extern void cpu_set_pte(pte_t *ptep, pte_t pte); extern volatile void cpu_reset(unsigned long addr); diff -Nru a/include/asm-arm/module.h b/include/asm-arm/module.h --- a/include/asm-arm/module.h Fri Nov 22 13:41:21 2002 +++ b/include/asm-arm/module.h Fri Nov 22 13:41:21 2002 @@ -1,12 +1,13 @@ #ifndef _ASM_ARM_MODULE_H #define _ASM_ARM_MODULE_H -/* - * This file contains the arm architecture specific module code. - */ -#define module_map(x) vmalloc(x) -#define module_unmap(x) vfree(x) -#define module_arch_init(x) (0) -#define arch_init_modules(x) do { } while (0) +struct mod_arch_specific +{ + int foo; +}; + +#define Elf_Shdr Elf32_Shdr +#define Elf_Sym Elf32_Sym +#define Elf_Ehdr Elf32_Ehdr #endif /* _ASM_ARM_MODULE_H */ diff -Nru a/include/asm-arm/proc-armv/elf.h b/include/asm-arm/proc-armv/elf.h --- a/include/asm-arm/proc-armv/elf.h Fri Nov 22 13:41:22 2002 +++ b/include/asm-arm/proc-armv/elf.h Fri Nov 22 13:41:22 2002 @@ -9,11 +9,15 @@ /* * 32-bit code is always OK. Some cpus can do 26-bit, some can't. */ -#define ELF_PROC_OK(x) \ - (( (elf_hwcap & HWCAP_THUMB) && ((x)->e_entry & 1) == 1) || \ - (!(elf_hwcap & HWCAP_THUMB) && ((x)->e_entry & 3) == 0) || \ - ( (elf_hwcap & HWCAP_26BIT) && (x)->e_flags & EF_ARM_APCS26) || \ - ((x)->e_flags & EF_ARM_APCS26) == 0) +#define ELF_PROC_OK(x) (ELF_THUMB_OK(x) && ELF_26BIT_OK(x)) + +#define ELF_THUMB_OK(x) \ + (( (elf_hwcap & HWCAP_THUMB) && ((x)->e_entry & 1) == 1) || \ + (!(elf_hwcap & HWCAP_THUMB) && ((x)->e_entry & 3) == 0)) + +#define ELF_26BIT_OK(x) \ + (( (elf_hwcap & HWCAP_26BIT) && (x)->e_flags & EF_ARM_APCS26) || \ + ((x)->e_flags & EF_ARM_APCS26) == 0) /* Old NetWinder binaries were compiled in such a way that the iBCS heuristic always trips on them. Until these binaries become uncommon diff -Nru a/include/asm-arm/proc-armv/pgtable.h b/include/asm-arm/proc-armv/pgtable.h --- a/include/asm-arm/proc-armv/pgtable.h Fri Nov 22 13:41:18 2002 +++ b/include/asm-arm/proc-armv/pgtable.h Fri Nov 22 13:41:18 2002 @@ -123,8 +123,8 @@ static inline void pmd_clear(pmd_t *pmdp) { - pmdp[0], __pmd(0)); - pmdp[1], __pmd(0)); + pmdp[0] = __pmd(0); + pmdp[1] = __pmd(0); cpu_flush_pmd(pmdp); } diff -Nru a/include/asm-i386/msr.h b/include/asm-i386/msr.h --- a/include/asm-i386/msr.h Fri Nov 22 13:41:17 2002 +++ b/include/asm-i386/msr.h Fri Nov 22 13:41:17 2002 @@ -107,6 +107,7 @@ #define MSR_K7_PERFCTR2 0xC0010006 #define MSR_K7_PERFCTR3 0xC0010007 #define MSR_K7_HWCR 0xC0010015 +#define MSR_K7_CLK_CTL 0xC001001b #define MSR_K7_FID_VID_CTL 0xC0010041 #define MSR_K7_VID_STATUS 0xC0010042 diff -Nru a/include/asm-i386/xor.h b/include/asm-i386/xor.h --- a/include/asm-i386/xor.h Fri Nov 22 13:41:18 2002 +++ b/include/asm-i386/xor.h Fri Nov 22 13:41:18 2002 @@ -868,7 +868,9 @@ #define XOR_TRY_TEMPLATES \ do { \ xor_speed(&xor_block_8regs); \ + xor_speed(&xor_block_8regs_p); \ xor_speed(&xor_block_32regs); \ + xor_speed(&xor_block_32regs_p); \ if (cpu_has_xmm) \ xor_speed(&xor_block_pIII_sse); \ if (cpu_has_mmx) { \ diff -Nru a/include/asm-ppc/atomic.h b/include/asm-ppc/atomic.h --- a/include/asm-ppc/atomic.h Fri Nov 22 13:41:18 2002 +++ b/include/asm-ppc/atomic.h Fri Nov 22 13:41:18 2002 @@ -17,8 +17,10 @@ extern void atomic_clear_mask(unsigned long mask, unsigned long *addr); #ifdef CONFIG_SMP +#define SMP_SYNC "sync" #define SMP_ISYNC "\n\tisync" #else +#define SMP_SYNC "" #define SMP_ISYNC #endif @@ -192,10 +194,11 @@ return t; } -#define smp_mb__before_atomic_dec() smp_mb() -#define smp_mb__after_atomic_dec() smp_mb() -#define smp_mb__before_atomic_inc() smp_mb() -#define smp_mb__after_atomic_inc() smp_mb() +#define __MB __asm__ __volatile__ (SMP_SYNC : : : "memory") +#define smp_mb__before_atomic_dec() __MB +#define smp_mb__after_atomic_dec() __MB +#define smp_mb__before_atomic_inc() __MB +#define smp_mb__after_atomic_inc() __MB #endif /* __KERNEL__ */ #endif /* _ASM_PPC_ATOMIC_H_ */ diff -Nru a/include/asm-ppc/hardirq.h b/include/asm-ppc/hardirq.h --- a/include/asm-ppc/hardirq.h Fri Nov 22 13:41:17 2002 +++ b/include/asm-ppc/hardirq.h Fri Nov 22 13:41:17 2002 @@ -3,7 +3,7 @@ #define __ASM_HARDIRQ_H #include -#include +#include /* The __last_jiffy_stamp field is needed to ensure that no decrementer * interrupt is lost on SMP machines. Since on most CPUs it is in the same diff -Nru a/include/asm-ppc/module.h b/include/asm-ppc/module.h --- a/include/asm-ppc/module.h Fri Nov 22 13:41:18 2002 +++ b/include/asm-ppc/module.h Fri Nov 22 13:41:18 2002 @@ -1,12 +1,33 @@ #ifndef _ASM_PPC_MODULE_H #define _ASM_PPC_MODULE_H -/* - * This file contains the PPC architecture specific module code. - */ - -#define module_map(x) vmalloc(x) -#define module_unmap(x) vfree(x) -#define module_arch_init(x) (0) -#define arch_init_modules(x) do { } while (0) +/* Module stuff for PPC. (C) 2001 Rusty Russell */ + +/* Thanks to Paul M for explaining this. + + PPC can only do rel jumps += 32MB, and often the kernel and other + modules are furthur away than this. So, we jump to a table of + trampolines attached to the module (the Procedure Linkage Table) + whenever that happens. +*/ + +struct ppc_plt_entry +{ + /* 16 byte jump instruction sequence (4 instructions) */ + unsigned int jump[4]; +}; + +struct mod_arch_specific +{ + /* How much of the core is actually taken up with core (then + we know the rest is for the PLT */ + unsigned int core_plt_offset; + + /* Same for init */ + unsigned int init_plt_offset; +}; + +#define Elf_Shdr Elf32_Shdr +#define Elf_Sym Elf32_Sym +#define Elf_Ehdr Elf32_Ehdr #endif /* _ASM_PPC_MODULE_H */ diff -Nru a/include/asm-ppc/page.h b/include/asm-ppc/page.h --- a/include/asm-ppc/page.h Fri Nov 22 13:41:18 2002 +++ b/include/asm-ppc/page.h Fri Nov 22 13:41:18 2002 @@ -14,19 +14,8 @@ #define KERNELBASE PAGE_OFFSET #ifndef __ASSEMBLY__ -#include /* for xmon definition */ +#include /* for BUG definition */ -#ifdef CONFIG_XMON -#define BUG() do { \ - printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ - xmon(0); \ -} while (0) -#else -#define BUG() do { \ - printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ - __asm__ __volatile__(".long 0x0"); \ -} while (0) -#endif #define PAGE_BUG(page) do { BUG(); } while (0) #define STRICT_MM_TYPECHECKS diff -Nru a/include/asm-ppc/processor.h b/include/asm-ppc/processor.h --- a/include/asm-ppc/processor.h Fri Nov 22 13:41:17 2002 +++ b/include/asm-ppc/processor.h Fri Nov 22 13:41:17 2002 @@ -519,47 +519,6 @@ #define PVR_MAJ(pvr) (((pvr) >> 4) & 0xF) /* Major revision field */ #define PVR_MIN(pvr) (((pvr) >> 0) & 0xF) /* Minor revision field */ -/* Processor Version Numbers */ - -#define PVR_403GA 0x00200000 -#define PVR_403GB 0x00200100 -#define PVR_403GC 0x00200200 -#define PVR_403GCX 0x00201400 -#define PVR_405GP 0x40110000 -#define PVR_STB03XXX 0x40310000 -#define PVR_NP405H 0x41410000 -#define PVR_NP405L 0x41610000 -#define PVR_601 0x00010000 -#define PVR_602 0x00050000 -#define PVR_603 0x00030000 -#define PVR_603e 0x00060000 -#define PVR_603ev 0x00070000 -#define PVR_603r 0x00071000 -#define PVR_604 0x00040000 -#define PVR_604e 0x00090000 -#define PVR_604r 0x000A0000 -#define PVR_620 0x00140000 -#define PVR_740 0x00080000 -#define PVR_750 PVR_740 -#define PVR_740P 0x10080000 -#define PVR_750P PVR_740P -#define PVR_7400 0x000C0000 -#define PVR_7410 0x800C0000 -#define PVR_7450 0x80000000 -/* - * For the 8xx processors, all of them report the same PVR family for - * the PowerPC core. The various versions of these processors must be - * differentiated by the version number in the Communication Processor - * Module (CPM). - */ -#define PVR_821 0x00500000 -#define PVR_823 PVR_821 -#define PVR_850 PVR_821 -#define PVR_860 PVR_821 -#define PVR_8240 0x00810100 -#define PVR_8245 0x80811014 -#define PVR_8260 PVR_8240 - /* We only need to define a new _MACH_xxx for machines which are part of * a configuration which supports more than one type of different machine. * This is currently limited to CONFIG_ALL_PPC and CHRP/PReP/PMac. -- Tom @@ -690,11 +649,7 @@ * as soon as I get around to remapping the io areas with the BATs * to match the mac we can raise this. -- Cort */ -#ifdef CONFIG_TASK_SIZE_BOOL -#define TASK_SIZE CONFIG_TASK_SIZE -#else -#define TASK_SIZE (0x80000000UL) -#endif +#define TASK_SIZE (CONFIG_TASK_SIZE) /* This decides where the kernel will search for a free chunk of vm * space during mmap's. @@ -787,6 +742,19 @@ } #define spin_lock_prefetch(x) prefetchw(x) + +#ifdef CONFIG_XMON +extern void xmon(struct pt_regs *); +#define BUG() do { \ + printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ + xmon(0); \ +} while (0) +#else +#define BUG() do { \ + printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ + __asm__ __volatile__(".long 0x0"); \ +} while (0) +#endif #endif /* !__ASSEMBLY__ */ diff -Nru a/include/asm-s390/debug.h b/include/asm-s390/debug.h --- a/include/asm-s390/debug.h Fri Nov 22 13:41:20 2002 +++ b/include/asm-s390/debug.h Fri Nov 22 13:41:20 2002 @@ -9,6 +9,8 @@ #ifndef DEBUG_H #define DEBUG_H +#include + /* Note: * struct __debug_entry must be defined outside of #ifdef __KERNEL__ * in order to allow a user program to analyze the 'raw'-view. diff -Nru a/include/asm-s390/ebcdic.h b/include/asm-s390/ebcdic.h --- a/include/asm-s390/ebcdic.h Fri Nov 22 13:41:19 2002 +++ b/include/asm-s390/ebcdic.h Fri Nov 22 13:41:19 2002 @@ -32,7 +32,7 @@ "0: tr 0(256,%0),0(%2)\n" " la %0,256(%0)\n" "1: ahi %1,-256\n" - " jp 0b\n" + " jnm 0b\n" " ex %1,0(1)" : "+&a" (addr), "+&a" (nr) : "a" (codepage) : "cc", "memory", "1" ); diff -Nru a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h --- a/include/asm-s390/lowcore.h Fri Nov 22 13:41:20 2002 +++ b/include/asm-s390/lowcore.h Fri Nov 22 13:41:20 2002 @@ -136,7 +136,7 @@ /* SMP info area: defined by DJB */ __u64 jiffy_timer; /* 0xc80 */ - atomic_t ext_call_fast; /* 0xc88 */ + __u32 ext_call_fast; /* 0xc88 */ __u8 pad11[0xe00-0xc8c]; /* 0xc8c */ /* 0xe00 is used as indicator for dump tools */ diff -Nru a/include/asm-s390/mman.h b/include/asm-s390/mman.h --- a/include/asm-s390/mman.h Fri Nov 22 13:41:18 2002 +++ b/include/asm-s390/mman.h Fri Nov 22 13:41:18 2002 @@ -26,6 +26,8 @@ #define MAP_EXECUTABLE 0x1000 /* mark it as an executable */ #define MAP_LOCKED 0x2000 /* pages are locked */ #define MAP_NORESERVE 0x4000 /* don't check for reservations */ +#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */ +#define MAP_NONBLOCK 0x10000 /* do not block on IO */ #define MS_ASYNC 1 /* sync memory asynchronously */ #define MS_INVALIDATE 2 /* invalidate the caches */ diff -Nru a/include/asm-s390/module.h b/include/asm-s390/module.h --- a/include/asm-s390/module.h Fri Nov 22 13:41:17 2002 +++ b/include/asm-s390/module.h Fri Nov 22 13:41:17 2002 @@ -4,9 +4,22 @@ * This file contains the s390 architecture specific module code. */ -#define module_map(x) vmalloc(x) -#define module_unmap(x) vfree(x) -#define module_arch_init(x) (0) -#define arch_init_modules(x) do { } while (0) +struct mod_arch_specific +{ + void *module_got, *module_plt; + unsigned long got_size, plt_size; +}; +#ifdef CONFIG_ARCH_S390X +#define ElfW(x) Elf64_ ## x +#define ELFW(x) ELF64_ ## x +#else +#define ElfW(x) Elf32_ ## x +#define ELFW(x) ELF32_ ## x +#endif + +#define Elf_Shdr ElfW(Shdr) +#define Elf_Sym ElfW(Sym) +#define Elf_Ehdr ElfW(Ehdr) +#define ELF_R_TYPE ELFW(R_TYPE) #endif /* _ASM_S390_MODULE_H */ diff -Nru a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h --- a/include/asm-s390/pgtable.h Fri Nov 22 13:41:22 2002 +++ b/include/asm-s390/pgtable.h Fri Nov 22 13:41:22 2002 @@ -320,7 +320,7 @@ extern inline pte_t pte_mkwrite(pte_t pte) { - pte_val(pte) &= ~_PAGE_RO; + pte_val(pte) &= ~(_PAGE_RO | _PAGE_ISCLEAN); return pte; } diff -Nru a/include/asm-s390/poll.h b/include/asm-s390/poll.h --- a/include/asm-s390/poll.h Fri Nov 22 13:41:17 2002 +++ b/include/asm-s390/poll.h Fri Nov 22 13:41:17 2002 @@ -23,6 +23,7 @@ #define POLLWRNORM 0x0100 #define POLLWRBAND 0x0200 #define POLLMSG 0x0400 +#define POLLREMOVE 0x1000 struct pollfd { int fd; diff -Nru a/include/asm-s390/setup.h b/include/asm-s390/setup.h --- a/include/asm-s390/setup.h Fri Nov 22 13:41:23 2002 +++ b/include/asm-s390/setup.h Fri Nov 22 13:41:23 2002 @@ -31,7 +31,7 @@ #define MACHINE_HAS_CSP (machine_flags & 8) #define MACHINE_HAS_MVPG (machine_flags & 16) -#define MACHINE_HAS_HWC (!MACHINE_IS_P390) +#define MACHINE_HAS_SCLP (!MACHINE_IS_P390) /* * Console mode. Override with conmode= @@ -40,10 +40,10 @@ extern unsigned int console_device; #define CONSOLE_IS_UNDEFINED (console_mode == 0) -#define CONSOLE_IS_HWC (console_mode == 1) +#define CONSOLE_IS_SCLP (console_mode == 1) #define CONSOLE_IS_3215 (console_mode == 2) #define CONSOLE_IS_3270 (console_mode == 3) -#define SET_CONSOLE_HWC do { console_mode = 1; } while (0) +#define SET_CONSOLE_SCLP do { console_mode = 1; } while (0) #define SET_CONSOLE_3215 do { console_mode = 2; } while (0) #define SET_CONSOLE_3270 do { console_mode = 3; } while (0) diff -Nru a/include/asm-s390/smp.h b/include/asm-s390/smp.h --- a/include/asm-s390/smp.h Fri Nov 22 13:41:20 2002 +++ b/include/asm-s390/smp.h Fri Nov 22 13:41:20 2002 @@ -29,7 +29,7 @@ } sigp_info; extern volatile unsigned long cpu_online_map; -extern unsigned long cpu_possible_map; +extern volatile unsigned long cpu_possible_map; #define NO_PROC_ID 0xFF /* No processor magic marker */ diff -Nru a/include/asm-s390/tlbflush.h b/include/asm-s390/tlbflush.h --- a/include/asm-s390/tlbflush.h Fri Nov 22 13:41:23 2002 +++ b/include/asm-s390/tlbflush.h Fri Nov 22 13:41:23 2002 @@ -91,13 +91,15 @@ static inline void __flush_tlb_mm(struct mm_struct * mm) { - if (((atomic_read(&mm->mm_count) != 1) || - (mm->cpu_vm_mask != (1UL << smp_processor_id())))) { - mm->cpu_vm_mask = (1UL << smp_processor_id()); + if (mm->cpu_vm_mask != (1UL << smp_processor_id())) { + /* mm was active on more than one cpu. */ + if (mm == current->active_mm && + atomic_read(&mm->mm_count) == 1) + /* this cpu is the only one using the mm. */ + mm->cpu_vm_mask = 1UL << smp_processor_id(); global_flush_tlb(); - } else { + } else local_flush_tlb(); - } } static inline void flush_tlb(void) diff -Nru a/include/asm-s390/types.h b/include/asm-s390/types.h --- a/include/asm-s390/types.h Fri Nov 22 13:41:20 2002 +++ b/include/asm-s390/types.h Fri Nov 22 13:41:20 2002 @@ -63,5 +63,10 @@ } subreg; } register_pair; +#ifdef CONFIG_LBD +typedef u64 sector_t; +#define HAVE_SECTOR_T +#endif + #endif /* __KERNEL__ */ #endif diff -Nru a/include/asm-s390/uaccess.h b/include/asm-s390/uaccess.h --- a/include/asm-s390/uaccess.h Fri Nov 22 13:41:18 2002 +++ b/include/asm-s390/uaccess.h Fri Nov 22 13:41:18 2002 @@ -199,24 +199,23 @@ */ #define __put_user(x, ptr) \ ({ \ - __typeof__(*(ptr)) *__pu_addr = (ptr); \ __typeof__(*(ptr)) __x = (x); \ int __pu_err; \ switch (sizeof (*(ptr))) { \ case 1: \ __pu_err = __put_user_asm_1((__u8)(__u32) __x, \ - __pu_addr); \ + ptr); \ break; \ case 2: \ __pu_err = __put_user_asm_2((__u16)(__u32) __x, \ - __pu_addr); \ + ptr); \ break; \ case 4: \ __pu_err = __put_user_asm_4((__u32) __x, \ - __pu_addr); \ + ptr); \ break; \ case 8: \ - __pu_err = __put_user_asm_8(&__x, __pu_addr); \ + __pu_err = __put_user_asm_8(&__x, ptr); \ break; \ default: \ __pu_err = __put_user_bad(); \ @@ -333,21 +332,20 @@ #define __get_user(x, ptr) \ ({ \ - __typeof__(ptr) __gu_addr = (ptr); \ __typeof__(*(ptr)) __x; \ int __gu_err; \ - switch (sizeof(*(__gu_addr))) { \ + switch (sizeof(*(ptr))) { \ case 1: \ - __get_user_asm_1(__x, __gu_addr, __gu_err); \ + __get_user_asm_1(__x, ptr, __gu_err); \ break; \ case 2: \ - __get_user_asm_2(__x, __gu_addr, __gu_err); \ + __get_user_asm_2(__x, ptr, __gu_err); \ break; \ case 4: \ - __get_user_asm_4(__x, __gu_addr, __gu_err); \ + __get_user_asm_4(__x, ptr, __gu_err); \ break; \ case 8: \ - __get_user_asm_8(__x, __gu_addr, __gu_err); \ + __get_user_asm_8(__x, ptr, __gu_err); \ break; \ default: \ __x = 0; \ diff -Nru a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h --- a/include/asm-s390/unistd.h Fri Nov 22 13:41:23 2002 +++ b/include/asm-s390/unistd.h Fri Nov 22 13:41:23 2002 @@ -241,6 +241,10 @@ #define __NR_io_submit 246 #define __NR_io_cancel 247 #define __NR_exit_group 248 +#define __NR_epoll_create 249 +#define __NR_epoll_ctl 250 +#define __NR_epoll_wait 251 +#define __NR_set_tid_address 252 /* user-visible error numbers are in the range -1 - -122: see */ @@ -254,11 +258,11 @@ return (type) (res); \ } while (0) -#define _svc_clobber "2", "cc", "memory" +#define _svc_clobber "cc", "memory" #define _syscall0(type,name) \ type name(void) { \ - long __res; \ + register long __res asm("2"); \ __asm__ __volatile__ ( \ " svc %b1\n" \ " lr %0,2" \ @@ -271,13 +275,13 @@ #define _syscall1(type,name,type1,arg1) \ type name(type1 arg1) { \ register type1 __arg1 asm("2") = arg1; \ - long __res; \ + register long __res asm("2"); \ __asm__ __volatile__ ( \ " svc %b1\n" \ " lr %0,2" \ : "=d" (__res) \ : "i" (__NR_##name), \ - "d" (__arg1) \ + "0" (__arg1) \ : _svc_clobber ); \ __syscall_return(type,__res); \ } @@ -286,13 +290,13 @@ type name(type1 arg1, type2 arg2) { \ register type1 __arg1 asm("2") = arg1; \ register type2 __arg2 asm("3") = arg2; \ - long __res; \ + register long __res asm("2"); \ __asm__ __volatile__ ( \ " svc %b1\n" \ " lr %0,2" \ : "=d" (__res) \ : "i" (__NR_##name), \ - "d" (__arg1), \ + "0" (__arg1), \ "d" (__arg2) \ : _svc_clobber ); \ __syscall_return(type,__res); \ @@ -303,13 +307,13 @@ register type1 __arg1 asm("2") = arg1; \ register type2 __arg2 asm("3") = arg2; \ register type3 __arg3 asm("4") = arg3; \ - long __res; \ + register long __res asm("2"); \ __asm__ __volatile__ ( \ " svc %b1\n" \ " lr %0,2" \ : "=d" (__res) \ : "i" (__NR_##name), \ - "d" (__arg1), \ + "0" (__arg1), \ "d" (__arg2), \ "d" (__arg3) \ : _svc_clobber ); \ @@ -323,13 +327,13 @@ register type2 __arg2 asm("3") = arg2; \ register type3 __arg3 asm("4") = arg3; \ register type4 __arg4 asm("5") = arg4; \ - long __res; \ + register long __res asm("2"); \ __asm__ __volatile__ ( \ " svc %b1\n" \ " lr %0,2" \ : "=d" (__res) \ : "i" (__NR_##name), \ - "d" (__arg1), \ + "0" (__arg1), \ "d" (__arg2), \ "d" (__arg3), \ "d" (__arg4) \ @@ -346,13 +350,13 @@ register type3 __arg3 asm("4") = arg3; \ register type4 __arg4 asm("5") = arg4; \ register type5 __arg5 asm("6") = arg5; \ - long __res; \ + register long __res asm("2"); \ __asm__ __volatile__ ( \ " svc %b1\n" \ " lr %0,2" \ : "=d" (__res) \ : "i" (__NR_##name), \ - "d" (__arg1), \ + "0" (__arg1), \ "d" (__arg2), \ "d" (__arg3), \ "d" (__arg4), \ diff -Nru a/include/asm-s390x/debug.h b/include/asm-s390x/debug.h --- a/include/asm-s390x/debug.h Fri Nov 22 13:41:20 2002 +++ b/include/asm-s390x/debug.h Fri Nov 22 13:41:20 2002 @@ -9,6 +9,8 @@ #ifndef DEBUG_H #define DEBUG_H +#include + /* Note: * struct __debug_entry must be defined outside of #ifdef __KERNEL__ * in order to allow a user program to analyze the 'raw'-view. diff -Nru a/include/asm-s390x/ebcdic.h b/include/asm-s390x/ebcdic.h --- a/include/asm-s390x/ebcdic.h Fri Nov 22 13:41:23 2002 +++ b/include/asm-s390x/ebcdic.h Fri Nov 22 13:41:23 2002 @@ -32,7 +32,7 @@ "0: tr 0(256,%0),0(%2)\n" " la %0,256(%0)\n" "1: ahi %1,-256\n" - " jp 0b\n" + " jnm 0b\n" " ex %1,0(1)" : "+&a" (addr), "+&a" (nr) : "a" (codepage) : "cc", "memory", "1" ); diff -Nru a/include/asm-s390x/mman.h b/include/asm-s390x/mman.h --- a/include/asm-s390x/mman.h Fri Nov 22 13:41:18 2002 +++ b/include/asm-s390x/mman.h Fri Nov 22 13:41:18 2002 @@ -26,6 +26,8 @@ #define MAP_EXECUTABLE 0x1000 /* mark it as an executable */ #define MAP_LOCKED 0x2000 /* pages are locked */ #define MAP_NORESERVE 0x4000 /* don't check for reservations */ +#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */ +#define MAP_NONBLOCK 0x10000 /* do not block on IO */ #define MS_ASYNC 1 /* sync memory asynchronously */ #define MS_INVALIDATE 2 /* invalidate the caches */ diff -Nru a/include/asm-s390x/module.h b/include/asm-s390x/module.h --- a/include/asm-s390x/module.h Fri Nov 22 13:41:17 2002 +++ b/include/asm-s390x/module.h Fri Nov 22 13:41:17 2002 @@ -4,9 +4,22 @@ * This file contains the s390 architecture specific module code. */ -#define module_map(x) vmalloc(x) -#define module_unmap(x) vfree(x) -#define module_arch_init(x) (0) -#define arch_init_modules(x) do { } while (0) +struct mod_arch_specific +{ + void *module_got, *module_plt; + unsigned long got_size, plt_size; +}; +#ifdef CONFIG_ARCH_S390X +#define ElfW(x) Elf64_ ## x +#define ELFW(x) ELF64_ ## x +#else +#define ElfW(x) Elf32_ ## x +#define ELFW(x) ELF64_ ## x +#endif + +#define Elf_Shdr ElfW(Shdr) +#define Elf_Sym ElfW(Sym) +#define Elf_Ehdr ElfW(Ehdr) +#define ELF_R_TYPE ELFW(R_TYPE) #endif /* _ASM_S390_MODULE_H */ diff -Nru a/include/asm-s390x/pgtable.h b/include/asm-s390x/pgtable.h --- a/include/asm-s390x/pgtable.h Fri Nov 22 13:41:19 2002 +++ b/include/asm-s390x/pgtable.h Fri Nov 22 13:41:19 2002 @@ -339,7 +339,7 @@ extern inline pte_t pte_mkwrite(pte_t pte) { - pte_val(pte) &= ~_PAGE_RO; + pte_val(pte) &= ~(_PAGE_RO | _PAGE_ISCLEAN); return pte; } diff -Nru a/include/asm-s390x/poll.h b/include/asm-s390x/poll.h --- a/include/asm-s390x/poll.h Fri Nov 22 13:41:22 2002 +++ b/include/asm-s390x/poll.h Fri Nov 22 13:41:22 2002 @@ -23,6 +23,7 @@ #define POLLWRNORM 0x0100 #define POLLWRBAND 0x0200 #define POLLMSG 0x0400 +#define POLLREMOVE 0x1000 struct pollfd { int fd; diff -Nru a/include/asm-s390x/setup.h b/include/asm-s390x/setup.h --- a/include/asm-s390x/setup.h Fri Nov 22 13:41:21 2002 +++ b/include/asm-s390x/setup.h Fri Nov 22 13:41:21 2002 @@ -30,7 +30,7 @@ #define MACHINE_HAS_MVPG (machine_flags & 16) #define MACHINE_HAS_DIAG44 (machine_flags & 32) -#define MACHINE_HAS_HWC (!MACHINE_IS_P390) +#define MACHINE_HAS_SCLP (!MACHINE_IS_P390) /* * Console mode. Override with conmode= @@ -39,10 +39,10 @@ extern unsigned int console_device; #define CONSOLE_IS_UNDEFINED (console_mode == 0) -#define CONSOLE_IS_HWC (console_mode == 1) +#define CONSOLE_IS_SCLP (console_mode == 1) #define CONSOLE_IS_3215 (console_mode == 2) #define CONSOLE_IS_3270 (console_mode == 3) -#define SET_CONSOLE_HWC do { console_mode = 1; } while (0) +#define SET_CONSOLE_SCLP do { console_mode = 1; } while (0) #define SET_CONSOLE_3215 do { console_mode = 2; } while (0) #define SET_CONSOLE_3270 do { console_mode = 3; } while (0) diff -Nru a/include/asm-s390x/tlbflush.h b/include/asm-s390x/tlbflush.h --- a/include/asm-s390x/tlbflush.h Fri Nov 22 13:41:22 2002 +++ b/include/asm-s390x/tlbflush.h Fri Nov 22 13:41:22 2002 @@ -88,13 +88,15 @@ static inline void __flush_tlb_mm(struct mm_struct * mm) { - if (((atomic_read(&mm->mm_count) != 1) || - (mm->cpu_vm_mask != (1UL << smp_processor_id())))) { - mm->cpu_vm_mask = (1UL << smp_processor_id()); + if (mm->cpu_vm_mask != (1UL << smp_processor_id())) { + /* mm was active on more than one cpu. */ + if (mm == current->active_mm && + atomic_read(&mm->mm_count) == 1) + /* this cpu is the only one using the mm. */ + mm->cpu_vm_mask = 1UL << smp_processor_id(); global_flush_tlb(); - } else { + } else local_flush_tlb(); - } } static inline void flush_tlb(void) diff -Nru a/include/asm-s390x/uaccess.h b/include/asm-s390x/uaccess.h --- a/include/asm-s390x/uaccess.h Fri Nov 22 13:41:17 2002 +++ b/include/asm-s390x/uaccess.h Fri Nov 22 13:41:17 2002 @@ -177,25 +177,24 @@ */ #define __put_user(x, ptr) \ ({ \ - __typeof__(*(ptr)) *__pu_addr = (ptr); \ __typeof__(*(ptr)) __x = (x); \ int __pu_err; \ - switch (sizeof (*(__pu_addr))) { \ + switch (sizeof (*(ptr))) { \ case 1: \ __pu_err = __put_user_asm_1((__u8)(__u64)(__x), \ - __pu_addr); \ + ptr); \ break; \ case 2: \ __pu_err = __put_user_asm_2((__u16)(__u64)(__x),\ - __pu_addr); \ + ptr); \ break; \ case 4: \ __pu_err = __put_user_asm_4((__u32)(__u64)(__x),\ - __pu_addr); \ + ptr); \ break; \ case 8: \ __pu_err = __put_user_asm_8((__u64)(__x), \ - __pu_addr); \ + ptr); \ break; \ default: \ __pu_err = __put_user_bad(); \ @@ -290,21 +289,20 @@ #define __get_user(x, ptr) \ ({ \ - __typeof__(ptr) __gu_addr = (ptr); \ __typeof__(*(ptr)) __x; \ int __gu_err; \ switch (sizeof(*(ptr))) { \ case 1: \ - __get_user_asm_1(__x,__gu_addr,__gu_err); \ + __get_user_asm_1(__x,ptr,__gu_err); \ break; \ case 2: \ - __get_user_asm_2(__x,__gu_addr,__gu_err); \ + __get_user_asm_2(__x,ptr,__gu_err); \ break; \ case 4: \ - __get_user_asm_4(__x,__gu_addr,__gu_err); \ + __get_user_asm_4(__x,ptr,__gu_err); \ break; \ case 8: \ - __get_user_asm_8(__x,__gu_addr,__gu_err); \ + __get_user_asm_8(__x,ptr,__gu_err); \ break; \ default: \ __x = 0; \ diff -Nru a/include/asm-s390x/unistd.h b/include/asm-s390x/unistd.h --- a/include/asm-s390x/unistd.h Fri Nov 22 13:41:22 2002 +++ b/include/asm-s390x/unistd.h Fri Nov 22 13:41:22 2002 @@ -208,6 +208,10 @@ #define __NR_io_submit 246 #define __NR_io_cancel 247 #define __NR_exit_group 248 +#define __NR_epoll_create 249 +#define __NR_epoll_ctl 250 +#define __NR_epoll_wait 251 +#define __NR_set_tid_address 252 /* user-visible error numbers are in the range -1 - -122: see */ @@ -221,11 +225,11 @@ return (type) (res); \ } while (0) -#define _svc_clobber "2", "cc", "memory" +#define _svc_clobber "cc", "memory" #define _syscall0(type,name) \ type name(void) { \ - long __res; \ + register long __res asm("2"); \ __asm__ __volatile__ ( \ " svc %b1\n" \ " lgr %0,2" \ @@ -238,13 +242,13 @@ #define _syscall1(type,name,type1,arg1) \ type name(type1 arg1) { \ register type1 __arg1 asm("2") = arg1; \ - long __res; \ + register long __res asm("2"); \ __asm__ __volatile__ ( \ " svc %b1\n" \ " lgr %0,2" \ : "=d" (__res) \ : "i" (__NR_##name), \ - "d" (__arg1) \ + "0" (__arg1) \ : _svc_clobber ); \ __syscall_return(type,__res); \ } @@ -253,13 +257,13 @@ type name(type1 arg1, type2 arg2) { \ register type1 __arg1 asm("2") = arg1; \ register type2 __arg2 asm("3") = arg2; \ - long __res; \ + register long __res asm("2"); \ __asm__ __volatile__ ( \ " svc %b1\n" \ " lgr %0,2" \ : "=d" (__res) \ : "i" (__NR_##name), \ - "d" (__arg1), \ + "0" (__arg1), \ "d" (__arg2) \ : _svc_clobber ); \ __syscall_return(type,__res); \ @@ -270,13 +274,13 @@ register type1 __arg1 asm("2") = arg1; \ register type2 __arg2 asm("3") = arg2; \ register type3 __arg3 asm("4") = arg3; \ - long __res; \ + register long __res asm("2"); \ __asm__ __volatile__ ( \ " svc %b1\n" \ " lgr %0,2" \ : "=d" (__res) \ : "i" (__NR_##name), \ - "d" (__arg1), \ + "0" (__arg1), \ "d" (__arg2), \ "d" (__arg3) \ : _svc_clobber ); \ @@ -290,13 +294,13 @@ register type2 __arg2 asm("3") = arg2; \ register type3 __arg3 asm("4") = arg3; \ register type4 __arg4 asm("5") = arg4; \ - long __res; \ + register long __res asm("2"); \ __asm__ __volatile__ ( \ " svc %b1\n" \ " lgr %0,2" \ : "=d" (__res) \ : "i" (__NR_##name), \ - "d" (__arg1), \ + "0" (__arg1), \ "d" (__arg2), \ "d" (__arg3), \ "d" (__arg4) \ @@ -313,13 +317,13 @@ register type3 __arg3 asm("4") = arg3; \ register type4 __arg4 asm("5") = arg4; \ register type5 __arg5 asm("6") = arg5; \ - long __res; \ + register long __res asm("2"); \ __asm__ __volatile__ ( \ " svc %b1\n" \ " lgr %0,2" \ : "=d" (__res) \ : "i" (__NR_##name), \ - "d" (__arg1), \ + "0" (__arg1), \ "d" (__arg2), \ "d" (__arg3), \ "d" (__arg4), \ diff -Nru a/include/asm-sparc/system.h b/include/asm-sparc/system.h --- a/include/asm-sparc/system.h Fri Nov 22 13:41:22 2002 +++ b/include/asm-sparc/system.h Fri Nov 22 13:41:22 2002 @@ -123,7 +123,7 @@ "save %sp, -0x40, %sp\n\t" \ "restore; restore; restore; restore; restore; restore; restore"); \ } while(0) -#define finish_arch_switch(rq, next) do{ }while(0) +#define finish_arch_switch(rq, next) spin_unlock_irq(&(rq)->lock) #define task_running(rq, p) ((rq)->curr == (p)) /* Much care has gone into this code, do not touch it. @@ -195,21 +195,6 @@ : "memory", "cc"); } -extern __inline__ void local_irq_disable(void) -{ - unsigned long tmp; - - __asm__ __volatile__( - "rd %%psr, %0\n\t" - "nop; nop; nop;\n\t" /* Sun4m + Cypress + SMP bug */ - "or %0, %1, %0\n\t" - "wr %0, 0x0, %%psr\n\t" - "nop; nop; nop\n" - : "=r" (tmp) - : "i" (PSR_PIL) - : "memory"); -} - extern __inline__ void local_irq_enable(void) { unsigned long tmp; @@ -233,6 +218,7 @@ return retval; } +#if 0 /* not used */ extern __inline__ unsigned long swap_pil(unsigned long __new_psr) { unsigned long retval; @@ -254,6 +240,7 @@ return retval; } +#endif extern __inline__ unsigned long read_psr_and_cli(void) { @@ -275,15 +262,9 @@ #define local_save_flags(flags) ((flags) = getipl()) #define local_irq_save(flags) ((flags) = read_psr_and_cli()) #define local_irq_restore(flags) setipl((flags)) +#define local_irq_disable() ((void) read_psr_and_cli()) -/* On sparc32 IRQ flags are the PSR register in the PSR_PIL - * field. - */ -#define irqs_disabled() \ -({ unsigned long flags; \ - local_save_flags(flags);\ - (flags & PSR_PIL) != 0; \ -}) +#define irqs_disabled() ((getipl() & PSR_PIL) != 0) #ifdef CONFIG_SMP diff -Nru a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h --- a/include/asm-sparc/unistd.h Fri Nov 22 13:41:18 2002 +++ b/include/asm-sparc/unistd.h Fri Nov 22 13:41:18 2002 @@ -181,7 +181,7 @@ #define __NR_setdomainname 163 /* Common */ /* #define __NR_ni_syscall 164 ENOSYS under SunOS */ #define __NR_quotactl 165 /* Common */ -/* #define __NR_exportfs 166 SunOS Specific */ +#define __NR_set_tid_address 166 /* Linux specific, exportfs under SunOS */ #define __NR_mount 167 /* Common */ #define __NR_ustat 168 /* Common */ #define __NR_setxattr 169 /* SunOS: semsys */ @@ -208,9 +208,9 @@ #define __NR_init_module 190 /* Linux Specific */ #define __NR_personality 191 /* Linux Specific */ #define __NR_remap_file_pages 192 /* Linux Specific */ -/* #define __NR_break 193 Linux Specific */ -/* #define __NR_lock 194 Linux Specific */ -/* #define __NR_mpx 195 Linux Specific */ +#define __NR_epoll_create 193 /* Linux Specific */ +#define __NR_epoll_ctl 194 /* Linux Specific */ +#define __NR_epoll_wait 195 /* Linux Specific */ /* #define __NR_ulimit 196 Linux Specific */ #define __NR_getppid 197 /* Linux Specific */ #define __NR_sigaction 198 /* Linux Specific */ diff -Nru a/include/asm-sparc64/floppy.h b/include/asm-sparc64/floppy.h --- a/include/asm-sparc64/floppy.h Fri Nov 22 13:41:23 2002 +++ b/include/asm-sparc64/floppy.h Fri Nov 22 13:41:23 2002 @@ -540,16 +540,18 @@ #ifdef ISA_FLOPPY_WORKS static unsigned long __init isa_floppy_init(void) { - struct isa_bridge *isa_br; - struct isa_device *isa_dev = NULL; + struct sparc_isa_bridge *isa_br; + struct sparc_isa_device *isa_dev = NULL; for_each_isa(isa_br) { for_each_isadev(isa_dev, isa_br) { if (!strcmp(isa_dev->prom_name, "dma")) { - struct isa_device *child = isa_dev->child; + struct sparc_isa_device *child = + isa_dev->child; while (child) { - if (!strcmp(child->prom_name, "floppy")) { + if (!strcmp(child->prom_name, + "floppy")) { isa_dev = child; goto isa_done; } diff -Nru a/include/asm-sparc64/isa.h b/include/asm-sparc64/isa.h --- a/include/asm-sparc64/isa.h Fri Nov 22 13:41:23 2002 +++ b/include/asm-sparc64/isa.h Fri Nov 22 13:41:23 2002 @@ -10,10 +10,12 @@ #include #include -struct isa_device { - struct isa_device *next; - struct isa_device *child; - struct isa_bridge *bus; +struct sparc_isa_bridge; + +struct sparc_isa_device { + struct sparc_isa_device *next; + struct sparc_isa_device *child; + struct sparc_isa_bridge *bus; int prom_node; char prom_name[64]; char compatible[64]; @@ -21,9 +23,9 @@ unsigned int irq; }; -struct isa_bridge { - struct isa_bridge *next; - struct isa_device *devices; +struct sparc_isa_bridge { + struct sparc_isa_bridge *next; + struct sparc_isa_device *devices; struct pci_pbm_info *parent; struct pci_dev *self; int index; @@ -34,7 +36,7 @@ int num_isa_ranges; }; -extern struct isa_bridge *isa_chain; +extern struct sparc_isa_bridge *isa_chain; extern void isa_init(void); diff -Nru a/include/asm-sparc64/parport.h b/include/asm-sparc64/parport.h --- a/include/asm-sparc64/parport.h Fri Nov 22 13:41:17 2002 +++ b/include/asm-sparc64/parport.h Fri Nov 22 13:41:17 2002 @@ -80,12 +80,12 @@ static int parport_isa_probe(int count) { - struct isa_bridge *isa_br; - struct isa_device *isa_dev; + struct sparc_isa_bridge *isa_br; + struct sparc_isa_device *isa_dev; for_each_isa(isa_br) { for_each_isadev(isa_dev, isa_br) { - struct isa_device *child; + struct sparc_isa_device *child; unsigned long base; if (strcmp(isa_dev->prom_name, "dma")) diff -Nru a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h --- a/include/asm-sparc64/unistd.h Fri Nov 22 13:41:18 2002 +++ b/include/asm-sparc64/unistd.h Fri Nov 22 13:41:18 2002 @@ -181,7 +181,7 @@ #define __NR_setdomainname 163 /* Common */ #define __NR_utrap_install 164 /* SYSV ABI/v9 required */ #define __NR_quotactl 165 /* Common */ -/* #define __NR_exportfs 166 SunOS Specific */ +#define __NR_set_tid_address 166 /* Linux specific, exportfs under SunOS */ #define __NR_mount 167 /* Common */ #define __NR_ustat 168 /* Common */ #define __NR_setxattr 169 /* SunOS: semsys */ @@ -208,9 +208,9 @@ #define __NR_init_module 190 /* Linux Specific */ #define __NR_personality 191 /* Linux Specific */ #define __NR_remap_file_pages 192 /* Linux Specific */ -/* #define __NR_break 193 Linux Specific */ -/* #define __NR_lock 194 Linux Specific */ -/* #define __NR_mpx 195 Linux Specific */ +#define __NR_epoll_create 193 /* Linux Specific */ +#define __NR_epoll_ctl 194 /* Linux Specific */ +#define __NR_epoll_wait 195 /* Linux Specific */ /* #define __NR_ulimit 196 Linux Specific */ #define __NR_getppid 197 /* Linux Specific */ #define __NR_sigaction 198 /* Linux Specific */ diff -Nru a/include/linux/acpi.h b/include/linux/acpi.h --- a/include/linux/acpi.h Fri Nov 22 13:41:17 2002 +++ b/include/linux/acpi.h Fri Nov 22 13:41:17 2002 @@ -419,6 +419,12 @@ #endif /*CONFIG_ACPI_PCI*/ +#ifdef CONFIG_ACPI_EC + +int ec_read(u8 addr, u8 *val); +int ec_write(u8 addr, u8 val); + +#endif /*CONFIG_ACPI_EC*/ #ifdef CONFIG_ACPI diff -Nru a/include/linux/agp_backend.h b/include/linux/agp_backend.h --- a/include/linux/agp_backend.h Fri Nov 22 13:41:22 2002 +++ b/include/linux/agp_backend.h Fri Nov 22 13:41:22 2002 @@ -61,6 +61,7 @@ VIA_APOLLO_PRO, VIA_APOLLO_KX133, VIA_APOLLO_KT133, + VIA_APOLLO_KT400, SIS_GENERIC, AMD_GENERIC, AMD_IRONGATE, diff -Nru a/include/linux/backing-dev.h b/include/linux/backing-dev.h --- a/include/linux/backing-dev.h Fri Nov 22 13:41:18 2002 +++ b/include/linux/backing-dev.h Fri Nov 22 13:41:18 2002 @@ -17,6 +17,8 @@ BDI_pdflush, /* A pdflush thread is working this device */ BDI_write_congested, /* The write queue is getting full */ BDI_read_congested, /* The read queue is getting full */ + BDI_write_active, /* There are one or more queued writes */ + BDI_read_active, /* There are one or more queued reads */ BDI_unused, /* Available bits start here */ }; @@ -40,6 +42,16 @@ static inline int bdi_write_congested(struct backing_dev_info *bdi) { return test_bit(BDI_write_congested, &bdi->state); +} + +static inline int bdi_read_active(struct backing_dev_info *bdi) +{ + return test_bit(BDI_read_active, &bdi->state); +} + +static inline int bdi_write_active(struct backing_dev_info *bdi) +{ + return test_bit(BDI_write_active, &bdi->state); } #endif /* _LINUX_BACKING_DEV_H */ diff -Nru a/include/linux/blkdev.h b/include/linux/blkdev.h --- a/include/linux/blkdev.h Fri Nov 22 13:41:18 2002 +++ b/include/linux/blkdev.h Fri Nov 22 13:41:18 2002 @@ -321,6 +321,7 @@ extern void blk_start_queue(request_queue_t *q); extern void blk_stop_queue(request_queue_t *q); extern void __blk_stop_queue(request_queue_t *q); +extern void __blk_run_queue(request_queue_t *q); static inline request_queue_t *bdev_get_queue(struct block_device *bdev) { diff -Nru a/include/linux/buffer_head.h b/include/linux/buffer_head.h --- a/include/linux/buffer_head.h Fri Nov 22 13:41:17 2002 +++ b/include/linux/buffer_head.h Fri Nov 22 13:41:17 2002 @@ -190,6 +190,9 @@ int generic_commit_write(struct file *, struct page *, unsigned, unsigned); int block_truncate_page(struct address_space *, loff_t, get_block_t *); int file_fsync(struct file *, struct dentry *, int); +int nobh_prepare_write(struct page*, unsigned, unsigned, get_block_t*); +int nobh_commit_write(struct file *, struct page *, unsigned, unsigned); +int nobh_truncate_page(struct address_space *, loff_t); #define OSYNC_METADATA (1<<0) #define OSYNC_DATA (1<<1) diff -Nru a/include/linux/coda_psdev.h b/include/linux/coda_psdev.h --- a/include/linux/coda_psdev.h Fri Nov 22 13:41:20 2002 +++ b/include/linux/coda_psdev.h Fri Nov 22 13:41:20 2002 @@ -47,13 +47,13 @@ int venus_open(struct super_block *sb, struct ViceFid *fid, int flags, struct file **f); int venus_mkdir(struct super_block *sb, struct ViceFid *dirfid, - const char *name, int length, - struct ViceFid *newfid, struct coda_vattr *attrs); + const char *name, int length, + struct ViceFid *newfid, struct coda_vattr *attrs); int venus_create(struct super_block *sb, struct ViceFid *dirfid, - const char *name, int length, int excl, int mode, int rdev, - struct ViceFid *newfid, struct coda_vattr *attrs) ; + const char *name, int length, int excl, int mode, dev_t rdev, + struct ViceFid *newfid, struct coda_vattr *attrs) ; int venus_rmdir(struct super_block *sb, struct ViceFid *dirfid, - const char *name, int length); + const char *name, int length); int venus_remove(struct super_block *sb, struct ViceFid *dirfid, const char *name, int length); int venus_readlink(struct super_block *sb, struct ViceFid *fid, diff -Nru a/include/linux/cpufreq.h b/include/linux/cpufreq.h --- a/include/linux/cpufreq.h Fri Nov 22 13:41:21 2002 +++ b/include/linux/cpufreq.h Fri Nov 22 13:41:21 2002 @@ -5,7 +5,7 @@ * (C) 2002 Dominik Brodowski * * - * $Id: cpufreq.h,v 1.27 2002/10/08 14:54:23 db Exp $ + * $Id: cpufreq.h,v 1.29 2002/11/11 15:35:47 db Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -104,7 +104,7 @@ * CPUFREQ DRIVER INTERFACE * *********************************************************************/ -typedef void (*cpufreq_policy_t) (struct cpufreq_policy *policy); +typedef int (*cpufreq_policy_t) (struct cpufreq_policy *policy); struct cpufreq_driver { /* needed by all drivers */ @@ -116,7 +116,7 @@ #endif /* 2.4. compatible API */ #ifdef CONFIG_CPU_FREQ_24_API - unsigned int cpu_min_freq; + unsigned int cpu_min_freq[NR_CPUS]; unsigned int cpu_cur_freq[NR_CPUS]; #endif }; @@ -205,19 +205,19 @@ CPU_NR_FREQ = 3, }; -#define CTL_CPU_VARS_SPEED_MAX { \ +#define CTL_CPU_VARS_SPEED_MAX(cpunr) { \ .ctl_name = CPU_NR_FREQ_MAX, \ - .data = &cpu_max_freq, \ + .data = &cpu_max_freq[cpunr], \ .procname = "speed-max", \ - .maxlen = sizeof(cpu_max_freq),\ + .maxlen = sizeof(cpu_max_freq[cpunr]),\ .mode = 0444, \ .proc_handler = proc_dointvec, } -#define CTL_CPU_VARS_SPEED_MIN { \ +#define CTL_CPU_VARS_SPEED_MIN(cpunr) { \ .ctl_name = CPU_NR_FREQ_MIN, \ - .data = &cpu_min_freq, \ + .data = &cpu_min_freq[cpunr], \ .procname = "speed-min", \ - .maxlen = sizeof(cpu_min_freq),\ + .maxlen = sizeof(cpu_min_freq[cpunr]),\ .mode = 0444, \ .proc_handler = proc_dointvec, } @@ -230,8 +230,8 @@ .extra1 = (void*) (cpunr), } #define CTL_TABLE_CPU_VARS(cpunr) static ctl_table ctl_cpu_vars_##cpunr[] = {\ - CTL_CPU_VARS_SPEED_MAX, \ - CTL_CPU_VARS_SPEED_MIN, \ + CTL_CPU_VARS_SPEED_MAX(cpunr), \ + CTL_CPU_VARS_SPEED_MIN(cpunr), \ CTL_CPU_VARS_SPEED(cpunr), \ { .ctl_name = 0, }, } diff -Nru a/include/linux/crypto.h b/include/linux/crypto.h --- a/include/linux/crypto.h Fri Nov 22 13:41:18 2002 +++ b/include/linux/crypto.h Fri Nov 22 13:41:18 2002 @@ -29,7 +29,7 @@ #define CRYPTO_ALG_TYPE_MASK 0x000000ff #define CRYPTO_ALG_TYPE_CIPHER 0x00000001 #define CRYPTO_ALG_TYPE_DIGEST 0x00000002 -#define CRYPTO_ALG_TYPE_COMP 0x00000004 +#define CRYPTO_ALG_TYPE_COMPRESS 0x00000004 /* @@ -144,6 +144,9 @@ void (*dit_final)(struct crypto_tfm *tfm, u8 *out); void (*dit_digest)(struct crypto_tfm *tfm, struct scatterlist *sg, unsigned int nsg, u8 *out); +#ifdef CONFIG_CRYPTO_HMAC + void *dit_hmac_block; +#endif }; struct compress_tfm { @@ -196,12 +199,7 @@ static inline const char *crypto_tfm_alg_modname(struct crypto_tfm *tfm) { - struct crypto_alg *alg = tfm->__crt_alg; - - if (alg->cra_module) - return alg->cra_module->name; - else - return NULL; + return module_name(tfm->__crt_alg->cra_module); } static inline u32 crypto_tfm_alg_type(struct crypto_tfm *tfm) @@ -211,16 +209,19 @@ static inline unsigned int crypto_tfm_alg_min_keysize(struct crypto_tfm *tfm) { + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); return tfm->__crt_alg->cra_cipher.cia_min_keysize; } static inline unsigned int crypto_tfm_alg_max_keysize(struct crypto_tfm *tfm) { + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); return tfm->__crt_alg->cra_cipher.cia_max_keysize; } static inline unsigned int crypto_tfm_alg_ivsize(struct crypto_tfm *tfm) { + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); return tfm->__crt_alg->cra_cipher.cia_ivsize; } @@ -231,6 +232,7 @@ static inline unsigned int crypto_tfm_alg_digestsize(struct crypto_tfm *tfm) { + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); return tfm->__crt_alg->cra_digest.dia_digestsize; } @@ -304,13 +306,13 @@ static inline void crypto_comp_compress(struct crypto_tfm *tfm) { - BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMP); + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS); tfm->crt_compress.cot_compress(tfm); } static inline void crypto_comp_decompress(struct crypto_tfm *tfm) { - BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMP); + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS); tfm->crt_compress.cot_decompress(tfm); } diff -Nru a/include/linux/dcache.h b/include/linux/dcache.h --- a/include/linux/dcache.h Fri Nov 22 13:41:23 2002 +++ b/include/linux/dcache.h Fri Nov 22 13:41:23 2002 @@ -160,10 +160,15 @@ * timeouts or autofs deletes). */ +static __inline__ void __d_drop(struct dentry * dentry) +{ + list_del_init(&dentry->d_hash); +} + static __inline__ void d_drop(struct dentry * dentry) { spin_lock(&dcache_lock); - list_del_init(&dentry->d_hash); + __d_drop(dentry); spin_unlock(&dcache_lock); } diff -Nru a/include/linux/device.h b/include/linux/device.h --- a/include/linux/device.h Fri Nov 22 13:41:23 2002 +++ b/include/linux/device.h Fri Nov 22 13:41:23 2002 @@ -64,14 +64,10 @@ struct bus_type { char * name; - struct rw_semaphore rwsem; - atomic_t refcount; - u32 present; struct subsystem subsys; struct subsystem drvsubsys; struct subsystem devsubsys; - struct list_head node; struct list_head devices; struct list_head drivers; @@ -88,11 +84,6 @@ extern struct bus_type * get_bus(struct bus_type * bus); extern void put_bus(struct bus_type * bus); -extern int bus_for_each_dev(struct bus_type * bus, void * data, - int (*callback)(struct device * dev, void * data)); -extern int bus_for_each_drv(struct bus_type * bus, void * data, - int (*callback)(struct device_driver * drv, void * data)); - /* driverfs interface for exporting bus attributes */ @@ -117,10 +108,7 @@ struct bus_type * bus; struct device_class * devclass; - rwlock_t lock; - atomic_t refcount; - u32 present; - + struct semaphore unload_sem; struct kobject kobj; struct list_head bus_list; struct list_head class_list; @@ -131,8 +119,6 @@ void (*shutdown) (struct device * dev); int (*suspend) (struct device * dev, u32 state, u32 level); int (*resume) (struct device * dev, u32 level); - - void (*release) (struct device_driver * drv); }; @@ -141,10 +127,6 @@ extern struct device_driver * get_driver(struct device_driver * drv); extern void put_driver(struct device_driver * drv); -extern void remove_driver(struct device_driver * drv); - -extern int driver_for_each_dev(struct device_driver * drv, void * data, - int (*callback)(struct device * dev, void * data)); /* driverfs interface for exporting driver attributes */ @@ -171,19 +153,12 @@ */ struct device_class { char * name; - struct rw_semaphore rwsem; - - atomic_t refcount; - u32 present; - u32 devnum; struct subsystem subsys; struct subsystem devsubsys; struct subsystem drvsubsys; - struct list_head node; struct list_head drivers; - struct list_head intf_list; int (*add_device)(struct device *); void (*remove_device)(struct device *); @@ -233,7 +208,6 @@ struct device_class * devclass; struct kobject kobj; - struct list_head node; struct list_head devices; u32 devnum; @@ -279,12 +253,6 @@ char name[DEVICE_NAME_SIZE]; /* descriptive ascii string */ char bus_id[BUS_ID_SIZE]; /* position on parent bus */ - spinlock_t lock; /* lock for the device to ensure two - different layers don't access it at - the same time. */ - atomic_t refcount; /* refcount to make sure the device - * persists for the right amount of time */ - struct bus_type * bus; /* type of bus device is on */ struct device_driver *driver; /* which driver has allocated this device */ @@ -296,7 +264,6 @@ void *platform_data; /* Platform specific data (e.g. ACPI, BIOS data relevant to device) */ - enum device_state state; u32 power_state; /* Current operating state. In ACPI-speak, this is D0-D3, D0 being fully functional, and D3 @@ -369,24 +336,6 @@ extern int (*platform_notify_remove)(struct device * dev); -static inline int device_present(struct device * dev) -{ - return (dev && (dev->state == DEVICE_INITIALIZED || dev->state == DEVICE_REGISTERED)); -} - -/* device and bus locking helpers. - * - * FIXME: Is there anything else we need to do? - */ -static inline void lock_device(struct device * dev) -{ - spin_lock(&dev->lock); -} - -static inline void unlock_device(struct device * dev) -{ - spin_unlock(&dev->lock); -} /** * get_device - atomically increment the reference count for the device. @@ -438,9 +387,9 @@ extern void device_shutdown(void); -/* drivrs/base/firmware.c */ +/* drivers/base/firmware.c */ extern int firmware_register(struct subsystem *); -extern void firmware_uregister(struct subsystem *); +extern void firmware_unregister(struct subsystem *); /* debugging and troubleshooting/diagnostic helpers. */ #ifdef DEBUG diff -Nru a/include/linux/elf.h b/include/linux/elf.h --- a/include/linux/elf.h Fri Nov 22 13:41:18 2002 +++ b/include/linux/elf.h Fri Nov 22 13:41:18 2002 @@ -200,6 +200,10 @@ #define ELF64_R_SYM(i) ((i) >> 32) #define ELF64_R_TYPE(i) ((i) & 0xffffffff) +#define R_ARM_NONE 0 +#define R_ARM_PC24 1 +#define R_ARM_ABS32 2 + #define R_386_NONE 0 #define R_386_32 1 #define R_386_PC32 2 @@ -412,6 +416,37 @@ #define R_PPC_SECTOFF_HA 36 /* Keep this the last entry. */ #define R_PPC_NUM 37 + +/* s390 relocations defined by the ABIs */ +#define R_390_NONE 0 /* No reloc. */ +#define R_390_8 1 /* Direct 8 bit. */ +#define R_390_12 2 /* Direct 12 bit. */ +#define R_390_16 3 /* Direct 16 bit. */ +#define R_390_32 4 /* Direct 32 bit. */ +#define R_390_PC32 5 /* PC relative 32 bit. */ +#define R_390_GOT12 6 /* 12 bit GOT offset. */ +#define R_390_GOT32 7 /* 32 bit GOT offset. */ +#define R_390_PLT32 8 /* 32 bit PC relative PLT address. */ +#define R_390_COPY 9 /* Copy symbol at runtime. */ +#define R_390_GLOB_DAT 10 /* Create GOT entry. */ +#define R_390_JMP_SLOT 11 /* Create PLT entry. */ +#define R_390_RELATIVE 12 /* Adjust by program base. */ +#define R_390_GOTOFF 13 /* 32 bit offset to GOT. */ +#define R_390_GOTPC 14 /* 32 bit PC relative offset to GOT. */ +#define R_390_GOT16 15 /* 16 bit GOT offset. */ +#define R_390_PC16 16 /* PC relative 16 bit. */ +#define R_390_PC16DBL 17 /* PC relative 16 bit shifted by 1. */ +#define R_390_PLT16DBL 18 /* 16 bit PC rel. PLT shifted by 1. */ +#define R_390_PC32DBL 19 /* PC relative 32 bit shifted by 1. */ +#define R_390_PLT32DBL 20 /* 32 bit PC rel. PLT shifted by 1. */ +#define R_390_GOTPCDBL 21 /* 32 bit PC rel. GOT shifted by 1. */ +#define R_390_64 22 /* Direct 64 bit. */ +#define R_390_PC64 23 /* PC relative 64 bit. */ +#define R_390_GOT64 24 /* 64 bit GOT offset. */ +#define R_390_PLT64 25 /* 64 bit PC relative PLT address. */ +#define R_390_GOTENT 26 /* 32 bit PC rel. to GOT entry >> 1. */ +/* Keep this the last entry. */ +#define R_390_NUM 27 /* Legal values for e_flags field of Elf64_Ehdr. */ diff -Nru a/include/linux/ext2_fs.h b/include/linux/ext2_fs.h --- a/include/linux/ext2_fs.h Fri Nov 22 13:41:18 2002 +++ b/include/linux/ext2_fs.h Fri Nov 22 13:41:18 2002 @@ -308,6 +308,7 @@ #define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */ #define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */ #define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */ +#define EXT2_MOUNT_NOBH 0x0100 /* No buffer_heads */ #define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */ #define EXT2_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */ #define EXT2_MOUNT_POSIX_ACL 0x8000 /* POSIX Access Control Lists */ diff -Nru a/include/linux/fs.h b/include/linux/fs.h --- a/include/linux/fs.h Fri Nov 22 13:41:18 2002 +++ b/include/linux/fs.h Fri Nov 22 13:41:18 2002 @@ -285,9 +285,6 @@ /* Write back some dirty pages from this mapping. */ int (*writepages)(struct address_space *, struct writeback_control *); - /* Perform a writeback as a memory-freeing operation. */ - int (*vm_writeback)(struct page *, struct writeback_control *); - /* Set a page dirty */ int (*set_page_dirty)(struct page *page); @@ -362,7 +359,6 @@ struct list_head i_dentry; unsigned long i_ino; atomic_t i_count; - dev_t i_dev; umode_t i_mode; unsigned int i_nlink; uid_t i_uid; @@ -578,7 +574,7 @@ extern void posix_block_lock(struct file_lock *, struct file_lock *); extern void posix_unblock_lock(struct file *, struct file_lock *); extern int posix_locks_deadlock(struct file_lock *, struct file_lock *); -extern int __get_lease(struct inode *inode, unsigned int flags); +extern int __break_lease(struct inode *inode, unsigned int flags); extern void lease_get_mtime(struct inode *, struct timespec *time); extern int lock_may_read(struct inode *, loff_t start, unsigned long count); extern int lock_may_write(struct inode *, loff_t start, unsigned long count); @@ -773,7 +769,7 @@ int (*symlink) (struct inode *,struct dentry *,const char *); int (*mkdir) (struct inode *,struct dentry *,int); int (*rmdir) (struct inode *,struct dentry *); - int (*mknod) (struct inode *,struct dentry *,int,int); + int (*mknod) (struct inode *,struct dentry *,int,dev_t); int (*rename) (struct inode *, struct dentry *, struct inode *, struct dentry *); int (*readlink) (struct dentry *, char *,int); @@ -782,7 +778,7 @@ int (*permission) (struct inode *, int); int (*setattr) (struct dentry *, struct iattr *); int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); - int (*setxattr) (struct dentry *, const char *, void *, size_t, int); + int (*setxattr) (struct dentry *, const char *,const void *,size_t,int); ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); ssize_t (*listxattr) (struct dentry *, char *, size_t); int (*removexattr) (struct dentry *, const char *); @@ -1052,10 +1048,10 @@ return 0; } -static inline int get_lease(struct inode *inode, unsigned int mode) +static inline int break_lease(struct inode *inode, unsigned int mode) { - if (inode->i_flock && (inode->i_flock->fl_flags & FL_LEASE)) - return __get_lease(inode, mode); + if (inode->i_flock) + return __break_lease(inode, mode); return 0; } @@ -1089,6 +1085,8 @@ extern int blkdev_close(struct inode *, struct file *); extern struct file_operations def_blk_fops; extern struct address_space_operations def_blk_aops; +extern struct file_operations def_chr_fops; +extern struct file_operations bad_sock_fops; extern struct file_operations def_fifo_fops; extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long); extern int blkdev_ioctl(struct inode *, struct file *, unsigned, unsigned long); @@ -1109,7 +1107,7 @@ } extern const char * cdevname(kdev_t); extern const char * kdevname(kdev_t); -extern void init_special_inode(struct inode *, umode_t, int); +extern void init_special_inode(struct inode *, umode_t, dev_t); /* Invalid inode operations -- fs/bad_inode.c */ extern void make_bad_inode(struct inode *); @@ -1254,9 +1252,6 @@ extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin); extern loff_t remote_llseek(struct file *file, loff_t offset, int origin); extern int generic_file_open(struct inode * inode, struct file * filp); - -extern int generic_vm_writeback(struct page *page, - struct writeback_control *wbc); static inline void do_generic_file_read(struct file * filp, loff_t *ppos, read_descriptor_t * desc, diff -Nru a/include/linux/interrupt.h b/include/linux/interrupt.h --- a/include/linux/interrupt.h Fri Nov 22 13:41:20 2002 +++ b/include/linux/interrupt.h Fri Nov 22 13:41:20 2002 @@ -3,11 +3,13 @@ #define _LINUX_INTERRUPT_H #include +#include #include #include #include #include #include +#include struct irqaction { void (*handler)(int, void *, struct pt_regs *); diff -Nru a/include/linux/jffs2.h b/include/linux/jffs2.h --- a/include/linux/jffs2.h Fri Nov 22 13:41:22 2002 +++ b/include/linux/jffs2.h Fri Nov 22 13:41:22 2002 @@ -8,7 +8,7 @@ * For licensing information, see the file 'LICENCE' in the * jffs2 directory. * - * $Id: jffs2.h,v 1.24 2002/05/20 14:56:37 dwmw2 Exp $ + * $Id: jffs2.h,v 1.25 2002/08/20 21:37:27 dwmw2 Exp $ * */ @@ -68,30 +68,65 @@ compression type */ +/* These can go once we've made sure we've caught all uses without + byteswapping */ + +typedef struct { + uint32_t v32; +} __attribute__((packed)) jint32_t; + +typedef struct { + uint16_t v16; +} __attribute__((packed)) jint16_t; + +#define JFFS2_NATIVE_ENDIAN + +#if defined(JFFS2_NATIVE_ENDIAN) +#define cpu_to_je16(x) ((jint16_t){x}) +#define cpu_to_je32(x) ((jint32_t){x}) + +#define je16_to_cpu(x) ((x).v16) +#define je32_to_cpu(x) ((x).v32) +#elif defined(JFFS2_BIG_ENDIAN) +#define cpu_to_je16(x) ((jint16_t){cpu_to_be16(x)}) +#define cpu_to_je32(x) ((jint32_t){cpu_to_be32(x)}) + +#define je16_to_cpu(x) (be16_to_cpu(x.v16)) +#define je32_to_cpu(x) (be32_to_cpu(x.v32)) +#elif defined(JFFS2_LITTLE_ENDIAN) +#define cpu_to_je16(x) ((jint16_t){cpu_to_le16(x)}) +#define cpu_to_je32(x) ((jint32_t){cpu_to_le32(x)}) + +#define je16_to_cpu(x) (le16_to_cpu(x.v16)) +#define je32_to_cpu(x) (le32_to_cpu(x.v32)) +#else +#error wibble +#endif + struct jffs2_unknown_node { /* All start like this */ - uint16_t magic; - uint16_t nodetype; - uint32_t totlen; /* So we can skip over nodes we don't grok */ - uint32_t hdr_crc; + jint16_t magic; + jint16_t nodetype; + jint32_t totlen; /* So we can skip over nodes we don't grok */ + jint32_t hdr_crc; } __attribute__((packed)); struct jffs2_raw_dirent { - uint16_t magic; - uint16_t nodetype; /* == JFFS_NODETYPE_DIRENT */ - uint32_t totlen; - uint32_t hdr_crc; - uint32_t pino; - uint32_t version; - uint32_t ino; /* == zero for unlink */ - uint32_t mctime; + jint16_t magic; + jint16_t nodetype; /* == JFFS_NODETYPE_DIRENT */ + jint32_t totlen; + jint32_t hdr_crc; + jint32_t pino; + jint32_t version; + jint32_t ino; /* == zero for unlink */ + jint32_t mctime; uint8_t nsize; uint8_t type; uint8_t unused[2]; - uint32_t node_crc; - uint32_t name_crc; + jint32_t node_crc; + jint32_t name_crc; uint8_t name[0]; } __attribute__((packed)); @@ -103,27 +138,27 @@ */ struct jffs2_raw_inode { - uint16_t magic; /* A constant magic number. */ - uint16_t nodetype; /* == JFFS_NODETYPE_INODE */ - uint32_t totlen; /* Total length of this node (inc data, etc.) */ - uint32_t hdr_crc; - uint32_t ino; /* Inode number. */ - uint32_t version; /* Version number. */ - uint32_t mode; /* The file's type or mode. */ - uint16_t uid; /* The file's owner. */ - uint16_t gid; /* The file's group. */ - uint32_t isize; /* Total resultant size of this inode (used for truncations) */ - uint32_t atime; /* Last access time. */ - uint32_t mtime; /* Last modification time. */ - uint32_t ctime; /* Change time. */ - uint32_t offset; /* Where to begin to write. */ - uint32_t csize; /* (Compressed) data size */ - uint32_t dsize; /* Size of the node's data. (after decompression) */ + jint16_t magic; /* A constant magic number. */ + jint16_t nodetype; /* == JFFS_NODETYPE_INODE */ + jint32_t totlen; /* Total length of this node (inc data, etc.) */ + jint32_t hdr_crc; + jint32_t ino; /* Inode number. */ + jint32_t version; /* Version number. */ + jint32_t mode; /* The file's type or mode. */ + jint16_t uid; /* The file's owner. */ + jint16_t gid; /* The file's group. */ + jint32_t isize; /* Total resultant size of this inode (used for truncations) */ + jint32_t atime; /* Last access time. */ + jint32_t mtime; /* Last modification time. */ + jint32_t ctime; /* Change time. */ + jint32_t offset; /* Where to begin to write. */ + jint32_t csize; /* (Compressed) data size */ + jint32_t dsize; /* Size of the node's data. (after decompression) */ uint8_t compr; /* Compression algorithm used */ uint8_t usercompr; /* Compression algorithm requested by the user */ - uint16_t flags; /* See JFFS2_INO_FLAG_* */ - uint32_t data_crc; /* CRC for the (compressed) data. */ - uint32_t node_crc; /* CRC for the raw inode (excluding data) */ + jint16_t flags; /* See JFFS2_INO_FLAG_* */ + jint32_t data_crc; /* CRC for the (compressed) data. */ + jint32_t node_crc; /* CRC for the raw inode (excluding data) */ // uint8_t data[dsize]; } __attribute__((packed)); diff -Nru a/include/linux/jffs2_fs_i.h b/include/linux/jffs2_fs_i.h --- a/include/linux/jffs2_fs_i.h Fri Nov 22 13:41:21 2002 +++ b/include/linux/jffs2_fs_i.h Fri Nov 22 13:41:21 2002 @@ -1,9 +1,10 @@ -/* $Id: jffs2_fs_i.h,v 1.12 2002/03/06 13:59:21 dwmw2 Exp $ */ +/* $Id: jffs2_fs_i.h,v 1.15 2002/11/12 09:42:49 dwmw2 Exp $ */ #ifndef _JFFS2_FS_I #define _JFFS2_FS_I #include +#include struct jffs2_inode_info { /* We need an internal semaphore similar to inode->i_sem. @@ -18,7 +19,7 @@ uint32_t highest_version; /* List of data fragments which make up the file */ - struct jffs2_node_frag *fraglist; + struct rb_root fragtree; /* There may be one datanode which isn't referenced by any of the above fragments, if it contains a metadata update but no actual diff -Nru a/include/linux/jffs2_fs_sb.h b/include/linux/jffs2_fs_sb.h --- a/include/linux/jffs2_fs_sb.h Fri Nov 22 13:41:17 2002 +++ b/include/linux/jffs2_fs_sb.h Fri Nov 22 13:41:17 2002 @@ -1,4 +1,4 @@ -/* $Id: jffs2_fs_sb.h,v 1.32 2002/07/23 14:35:34 dwmw2 Exp $ */ +/* $Id: jffs2_fs_sb.h,v 1.35 2002/11/12 09:42:18 dwmw2 Exp $ */ #ifndef _JFFS2_FS_SB #define _JFFS2_FS_SB @@ -21,6 +21,8 @@ struct mtd_info *mtd; uint32_t highest_ino; + uint32_t checked_ino; + unsigned int flags; struct task_struct *gc_task; /* GC task struct */ @@ -38,10 +40,12 @@ uint32_t flash_size; uint32_t used_size; uint32_t dirty_size; + uint32_t wasted_size; uint32_t free_size; uint32_t erasing_size; uint32_t bad_size; uint32_t sector_size; + uint32_t unchecked_size; uint32_t nr_free_blocks; uint32_t nr_erasing_blocks; diff -Nru a/include/linux/kallsyms.h b/include/linux/kallsyms.h --- a/include/linux/kallsyms.h Fri Nov 22 13:41:17 2002 +++ b/include/linux/kallsyms.h Fri Nov 22 13:41:17 2002 @@ -1,163 +1,47 @@ -/* kallsyms headers - Copyright 2000 Keith Owens - - This file is part of the Linux modutils. It is exported to kernel - space so debuggers can access the kallsyms data. - - The kallsyms data contains all the non-stack symbols from a kernel - or a module. The kernel symbols are held between __start___kallsyms - and __stop___kallsyms. The symbols for a module are accessed via - the struct module chain which is based at module_list. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ident "$Id: linux-2.4.9-kallsyms.patch,v 1.8 2002/02/11 18:34:53 arjanv Exp $" - -#ifndef MODUTILS_KALLSYMS_H -#define MODUTILS_KALLSYMS_H 1 - -/* Have to (re)define these ElfW entries here because external kallsyms - * code does not have access to modutils/include/obj.h. This code is - * included from user spaces tools (modutils) and kernel, they need - * different includes. +/* Rewritten and vastly simplified by Rusty Russell for in-kernel + * module loader: + * Copyright 2002 Rusty Russell IBM Corporation */ +#ifndef _LINUX_KALLSYMS_H +#define _LINUX_KALLSYMS_H -#ifndef ELFCLASS32 -#ifdef __KERNEL__ -#include -#else /* __KERNEL__ */ -#include -#endif /* __KERNEL__ */ -#endif /* ELFCLASS32 */ - -#ifndef ELFCLASSM -#define ELFCLASSM ELF_CLASS -#endif - -#ifndef ElfW -# if ELFCLASSM == ELFCLASS32 -# define ElfW(x) Elf32_ ## x -# define ELFW(x) ELF32_ ## x -# else -# define ElfW(x) Elf64_ ## x -# define ELFW(x) ELF64_ ## x -# endif -#endif - -/* Format of data in the kallsyms section. - * Most of the fields are small numbers but the total size and all - * offsets can be large so use the 32/64 bit types for these fields. - * - * Do not use sizeof() on these structures, modutils may be using extra - * fields. Instead use the size fields in the header to access the - * other bits of data. - */ - -struct kallsyms_header { - int size; /* Size of this header */ - ElfW(Word) total_size; /* Total size of kallsyms data */ - int sections; /* Number of section entries */ - ElfW(Off) section_off; /* Offset to first section entry */ - int section_size; /* Size of one section entry */ - int symbols; /* Number of symbol entries */ - ElfW(Off) symbol_off; /* Offset to first symbol entry */ - int symbol_size; /* Size of one symbol entry */ - ElfW(Off) string_off; /* Offset to first string */ - ElfW(Addr) start; /* Start address of first section */ - ElfW(Addr) end; /* End address of last section */ -}; - -struct kallsyms_section { - ElfW(Addr) start; /* Start address of section */ - ElfW(Word) size; /* Size of this section */ - ElfW(Off) name_off; /* Offset to section name */ - ElfW(Word) flags; /* Flags from section */ -}; - -struct kallsyms_symbol { - ElfW(Off) section_off; /* Offset to section that owns this symbol */ - ElfW(Addr) symbol_addr; /* Address of symbol */ - ElfW(Off) name_off; /* Offset to symbol name */ -}; - -#define KALLSYMS_SEC_NAME "__kallsyms" -#define KALLSYMS_IDX 2 /* obj_kallsyms creates kallsyms as section 2 */ - -#define kallsyms_next_sec(h,s) \ - ((s) = (struct kallsyms_section *)((char *)(s) + (h)->section_size)) -#define kallsyms_next_sym(h,s) \ - ((s) = (struct kallsyms_symbol *)((char *)(s) + (h)->symbol_size)) +#include #ifdef CONFIG_KALLSYMS +/* Lookup an address. modname is set to NULL if it's in the kernel. */ +const char *kallsyms_lookup(unsigned long addr, + unsigned long *symbolsize, + unsigned long *offset, + char **modname); + +/* Replace "%s" in format with address, if found */ +extern void __print_symbol(const char *fmt, unsigned long address); + +#else /* !CONFIG_KALLSYMS */ + +static inline const char *kallsyms_lookup(unsigned long addr, + unsigned long *symbolsize, + unsigned long *offset, + char **modname) +{ + return NULL; +} -int kallsyms_symbol_to_address( - const char *name, /* Name to lookup */ - unsigned long *token, /* Which module to start with */ - const char **mod_name, /* Set to module name or "kernel" */ - unsigned long *mod_start, /* Set to start address of module */ - unsigned long *mod_end, /* Set to end address of module */ - const char **sec_name, /* Set to section name */ - unsigned long *sec_start, /* Set to start address of section */ - unsigned long *sec_end, /* Set to end address of section */ - const char **sym_name, /* Set to full symbol name */ - unsigned long *sym_start, /* Set to start address of symbol */ - unsigned long *sym_end /* Set to end address of symbol */ - ); - -int kallsyms_address_to_symbol( - unsigned long address, /* Address to lookup */ - const char **mod_name, /* Set to module name */ - unsigned long *mod_start, /* Set to start address of module */ - unsigned long *mod_end, /* Set to end address of module */ - const char **sec_name, /* Set to section name */ - unsigned long *sec_start, /* Set to start address of section */ - unsigned long *sec_end, /* Set to end address of section */ - const char **sym_name, /* Set to full symbol name */ - unsigned long *sym_start, /* Set to start address of symbol */ - unsigned long *sym_end /* Set to end address of symbol */ - ); - -int kallsyms_sections(void *token, - int (*callback)(void *, /* token */ - const char *, /* module name */ - const char *, /* section name */ - ElfW(Addr), /* Section start */ - ElfW(Addr), /* Section end */ - ElfW(Word) /* Section flags */ - ) - ); - -#else - -static inline int kallsyms_address_to_symbol( - unsigned long address, /* Address to lookup */ - const char **mod_name, /* Set to module name */ - unsigned long *mod_start, /* Set to start address of module */ - unsigned long *mod_end, /* Set to end address of module */ - const char **sec_name, /* Set to section name */ - unsigned long *sec_start, /* Set to start address of section */ - unsigned long *sec_end, /* Set to end address of section */ - const char **sym_name, /* Set to full symbol name */ - unsigned long *sym_start, /* Set to start address of symbol */ - unsigned long *sym_end /* Set to end address of symbol */ - ) +/* Stupid that this does nothing, but I didn't create this mess. */ +#define __print_symbol(fmt, addr) +#endif /*CONFIG_KALLSYMS*/ + +/* This macro allows us to keep printk typechecking */ +static void __check_printsym_format(const char *fmt, ...) +__attribute__((format(printf,1,2))); +static inline void __check_printsym_format(const char *fmt, ...) { - return -ESRCH; } -#endif +#define print_symbol(fmt, addr) \ +do { \ + __check_printsym_format(fmt, ""); \ + __print_symbol(fmt, addr); \ +} while(0) -#endif /* kallsyms.h */ +#endif /*_LINUX_KALLSYMS_H*/ diff -Nru a/include/linux/kobject.h b/include/linux/kobject.h --- a/include/linux/kobject.h Fri Nov 22 13:41:17 2002 +++ b/include/linux/kobject.h Fri Nov 22 13:41:17 2002 @@ -24,6 +24,10 @@ }; extern void kobject_init(struct kobject *); +extern void kobject_cleanup(struct kobject *); + +extern int kobject_add(struct kobject *); +extern void kobject_del(struct kobject *); extern int kobject_register(struct kobject *); extern void kobject_unregister(struct kobject *); diff -Nru a/include/linux/meye.h b/include/linux/meye.h --- a/include/linux/meye.h Fri Nov 22 13:41:18 2002 +++ b/include/linux/meye.h Fri Nov 22 13:41:18 2002 @@ -1,7 +1,9 @@ /* * Motion Eye video4linux driver for Sony Vaio PictureBook * - * Copyright (C) 2001 Stelian Pop , Alcôve + * Copyright (C) 2001-2002 Stelian Pop + * + * Copyright (C) 2001-2002 Alcôve * * Copyright (C) 2000 Andrew Tridgell * diff -Nru a/include/linux/mmzone.h b/include/linux/mmzone.h --- a/include/linux/mmzone.h Fri Nov 22 13:41:17 2002 +++ b/include/linux/mmzone.h Fri Nov 22 13:41:17 2002 @@ -84,6 +84,8 @@ atomic_t refill_counter; unsigned long nr_active; unsigned long nr_inactive; + int all_unreclaimable; /* All pages pinned */ + unsigned long pages_scanned; /* since last reclaim */ ZONE_PADDING(_pad2_) @@ -203,6 +205,7 @@ void get_zone_counts(unsigned long *active, unsigned long *inactive); void build_all_zonelists(void); +void wakeup_kswapd(struct zone *zone); /** * for_each_pgdat - helper macro to iterate over all nodes diff -Nru a/include/linux/module.h b/include/linux/module.h --- a/include/linux/module.h Fri Nov 22 13:41:22 2002 +++ b/include/linux/module.h Fri Nov 22 13:41:22 2002 @@ -14,6 +14,8 @@ #include #include #include +#include + #include #include /* For struct exception_table_entry */ @@ -26,10 +28,7 @@ #define MODULE_AUTHOR(name) #define MODULE_DESCRIPTION(desc) #define MODULE_SUPPORTED_DEVICE(name) -#define MODULE_GENERIC_TABLE(gtype,name) -#define MODULE_DEVICE_TABLE(type,name) #define MODULE_PARM_DESC(var,desc) -#define print_symbol(format, addr) #define print_modules() #define MODULE_NAME_LEN (64 - sizeof(unsigned long)) @@ -40,28 +39,27 @@ }; #ifdef MODULE + +#define MODULE_GENERIC_TABLE(gtype,name) \ +static const unsigned long __module_##gtype##_size \ + __attribute__ ((unused)) = sizeof(struct gtype##_id); \ +static const struct gtype##_id * __module_##gtype##_table \ + __attribute__ ((unused)) = name + /* This is magically filled in by the linker, but THIS_MODULE must be a constant so it works in initializers. */ extern struct module __this_module; #define THIS_MODULE (&__this_module) -#else -#define THIS_MODULE ((struct module *)0) -#endif -#ifdef CONFIG_MODULES -/* Get/put a kernel symbol (calls must be symmetric) */ -void *__symbol_get(const char *symbol); -void *__symbol_get_gpl(const char *symbol); -#define symbol_get(x) ((typeof(&x))(__symbol_get(#x))) +#else /* !MODULE */ -/* For every exported symbol, place a struct in the __ksymtab section */ -#define EXPORT_SYMBOL(sym) \ - const struct kernel_symbol __ksymtab_##sym \ - __attribute__((section("__ksymtab"))) \ - = { (unsigned long)&sym, #sym } +#define MODULE_GENERIC_TABLE(gtype,name) +#define THIS_MODULE ((struct module *)0) -#define EXPORT_SYMBOL_NOVERS(sym) EXPORT_SYMBOL(sym) -#define EXPORT_SYMBOL_GPL(sym) EXPORT_SYMBOL(sym) +#endif + +#define MODULE_DEVICE_TABLE(type,name) \ + MODULE_GENERIC_TABLE(type##_device,name) struct kernel_symbol_group { @@ -83,6 +81,22 @@ const struct exception_table_entry *entry; }; + +#ifdef CONFIG_MODULES +/* Get/put a kernel symbol (calls must be symmetric) */ +void *__symbol_get(const char *symbol); +void *__symbol_get_gpl(const char *symbol); +#define symbol_get(x) ((typeof(&x))(__symbol_get(#x))) + +/* For every exported symbol, place a struct in the __ksymtab section */ +#define EXPORT_SYMBOL(sym) \ + const struct kernel_symbol __ksymtab_##sym \ + __attribute__((section("__ksymtab"))) \ + = { (unsigned long)&sym, #sym } + +#define EXPORT_SYMBOL_NOVERS(sym) EXPORT_SYMBOL(sym) +#define EXPORT_SYMBOL_GPL(sym) EXPORT_SYMBOL(sym) + struct module_ref { atomic_t count; @@ -137,6 +151,13 @@ void (*exit)(void); #endif +#ifdef CONFIG_KALLSYMS + /* We keep the symbol and string tables for kallsyms. */ + Elf_Sym *symtab; + unsigned long num_syms; + char *strtab; +#endif + /* The command line arguments (may be mangled). People like keeping pointers to this stuff */ char args[0]; @@ -211,6 +232,12 @@ } \ } while(0) +/* For kallsyms to ask for address resolution. NULL means not found. */ +const char *module_address_lookup(unsigned long addr, + unsigned long *symbolsize, + unsigned long *offset, + char **modname); + #else /* !CONFIG_MODULES... */ #define EXPORT_SYMBOL(sym) #define EXPORT_SYMBOL_GPL(sym) @@ -227,6 +254,15 @@ #define module_name(mod) "kernel" #define __unsafe(mod) + +/* For kallsyms to ask for address resolution. NULL means not found. */ +static inline const char *module_address_lookup(unsigned long addr, + unsigned long *symbolsize, + unsigned long *offset, + char **modname) +{ + return NULL; +} #endif /* CONFIG_MODULES */ /* For archs to search exception tables */ @@ -278,6 +314,14 @@ int __initfn(void) #define cleanup_module(voidarg) __exitfn(void) #endif + +/* + * The exception and symbol tables, and the lock + * to protect them. + */ +extern spinlock_t modlist_lock; +extern struct list_head extables; +extern struct list_head symbols; /* Use symbol_get and symbol_put instead. You'll thank me. */ #define HAVE_INTER_MODULE diff -Nru a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h --- a/include/linux/netfilter_bridge.h Fri Nov 22 13:41:20 2002 +++ b/include/linux/netfilter_bridge.h Fri Nov 22 13:41:20 2002 @@ -6,7 +6,9 @@ #include #include +#if defined(__KERNEL__) && defined(CONFIG_NETFILTER) #include +#endif /* Bridge Hooks */ /* After promisc drops, checksum checks. */ @@ -23,6 +25,8 @@ #define NF_BR_BROUTING 5 #define NF_BR_NUMHOOKS 6 +#ifdef __KERNEL__ + #define BRNF_PKT_TYPE 0x01 #define BRNF_BRIDGED_DNAT 0x02 #define BRNF_DONT_TAKE_PARENT 0x04 @@ -38,6 +42,7 @@ NF_BR_PRI_LAST = INT_MAX, }; +#ifdef CONFIG_NETFILTER static inline struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb) { @@ -57,5 +62,7 @@ __u32 ipv4; } daddr; }; +#endif /* CONFIG_NETFILTER */ +#endif /* __KERNEL__ */ #endif diff -Nru a/include/linux/netlink.h b/include/linux/netlink.h --- a/include/linux/netlink.h Fri Nov 22 13:41:22 2002 +++ b/include/linux/netlink.h Fri Nov 22 13:41:22 2002 @@ -110,8 +110,8 @@ extern struct sock *netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len)); extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err); extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock); -extern void netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 pid, - __u32 group, int allocation); +extern int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 pid, + __u32 group, int allocation); extern void netlink_set_err(struct sock *ssk, __u32 pid, __u32 group, int code); extern int netlink_register_notifier(struct notifier_block *nb); extern int netlink_unregister_notifier(struct notifier_block *nb); diff -Nru a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h --- a/include/linux/nfs_fs.h Fri Nov 22 13:41:18 2002 +++ b/include/linux/nfs_fs.h Fri Nov 22 13:41:18 2002 @@ -118,8 +118,8 @@ * mtime != read_cache_mtime */ unsigned long read_cache_jiffies; - __u64 read_cache_ctime; - __u64 read_cache_mtime; + struct timespec read_cache_ctime; + struct timespec read_cache_mtime; __u64 read_cache_isize; unsigned long attrtimeo; unsigned long attrtimeo_timestamp; @@ -415,20 +415,6 @@ ino ^= fileid >> (sizeof(u64)-sizeof(ino_t)) * 8; return ino; } - -static inline time_t -nfs_time_to_secs(__u64 time) -{ - return (time_t)(time >> 32); -} - - -static inline u32 -nfs_time_to_nsecs(__u64 time) -{ - return time & 0xffffffff; -} - /* NFS root */ diff -Nru a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h --- a/include/linux/nfs_xdr.h Fri Nov 22 13:41:22 2002 +++ b/include/linux/nfs_xdr.h Fri Nov 22 13:41:22 2002 @@ -6,8 +6,8 @@ struct nfs_fattr { unsigned short valid; /* which fields are valid */ __u64 pre_size; /* pre_op_attr.size */ - __u64 pre_mtime; /* pre_op_attr.mtime */ - __u64 pre_ctime; /* pre_op_attr.ctime */ + struct timespec pre_mtime; /* pre_op_attr.mtime */ + struct timespec pre_ctime; /* pre_op_attr.ctime */ enum nfs_ftype type; /* always use NFSv2 types */ __u32 mode; __u32 nlink; @@ -32,9 +32,9 @@ } nfs4; } fsid_u; __u64 fileid; - __u64 atime; - __u64 mtime; - __u64 ctime; + struct timespec atime; + struct timespec mtime; + struct timespec ctime; __u64 change_attr; /* NFSv4 change attribute */ __u64 pre_change_attr;/* pre-op NFSv4 change attribute */ unsigned long timestamp; @@ -219,7 +219,7 @@ struct nfs_fh * fh; struct iattr * sattr; unsigned int guard; - __u64 guardtime; + struct timespec guardtime; }; struct nfs3_diropargs { @@ -398,6 +398,7 @@ }; struct nfs4_open { + struct nfs4_client * op_client_state; /* request */ u32 op_share_access; /* request */ u32 op_opentype; /* request */ u32 op_createmode; /* request */ @@ -472,6 +473,7 @@ char sc_netid[4]; /* request */ char sc_uaddr[24]; /* request */ u32 sc_cb_ident; /* request */ + struct nfs4_client * sc_state; /* response */ }; struct nfs4_write { @@ -504,8 +506,10 @@ struct nfs4_readlink readlink; struct nfs4_remove remove; struct nfs4_rename rename; + struct nfs4_client * renew; struct nfs4_setattr setattr; struct nfs4_setclientid setclientid; + struct nfs4_client * setclientid_confirm; struct nfs4_write write; } u; }; diff -Nru a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h --- a/include/linux/nfsd/xdr4.h Fri Nov 22 13:41:18 2002 +++ b/include/linux/nfsd/xdr4.h Fri Nov 22 13:41:18 2002 @@ -173,6 +173,9 @@ stateid_t rd_stateid; /* request */ u64 rd_offset; /* request */ u32 rd_length; /* request */ + struct iovec rd_iov[RPCSVC_MAXPAGES]; + int rd_vlen; + struct svc_rqst *rd_rqstp; /* response */ struct svc_fh * rd_fhp; /* response */ }; @@ -249,7 +252,9 @@ u64 wr_offset; /* request */ u32 wr_stable_how; /* request */ u32 wr_buflen; /* request */ - char * wr_buf; /* request */ + struct iovec wr_vec[RPCSVC_MAXPAGES]; /* request */ + int wr_vlen; + u32 wr_bytes_written; /* response */ u32 wr_how_written; /* response */ nfs4_verifier wr_verifier; /* response */ @@ -288,6 +293,14 @@ /* scratch variables for XDR decode */ u32 * p; u32 * end; + struct page ** pagelist; + int pagelen; + u32 tmp[8]; + u32 * tmpp; + struct tmpbuf { + struct tmpbuf *next; + void *buf; + } *to_free; u32 taglen; char * tag; @@ -301,6 +314,8 @@ /* scratch variables for XDR encode */ u32 * p; u32 * end; + struct xdr_buf * xbuf; + struct svc_rqst * rqstp; u32 taglen; char * tag; diff -Nru a/include/linux/page-flags.h b/include/linux/page-flags.h --- a/include/linux/page-flags.h Fri Nov 22 13:41:22 2002 +++ b/include/linux/page-flags.h Fri Nov 22 13:41:22 2002 @@ -70,6 +70,7 @@ #define PG_chainlock 15 /* lock bit for ->pte_chain */ #define PG_direct 16 /* ->pte_chain points directly at pte */ +#define PG_mappedtodisk 17 /* Has blocks allocated on-disk */ /* * Global page accounting. One instance per CPU. Only unsigned longs are @@ -232,6 +233,10 @@ #define TestSetPageDirect(page) test_and_set_bit(PG_direct, &(page)->flags) #define ClearPageDirect(page) clear_bit(PG_direct, &(page)->flags) #define TestClearPageDirect(page) test_and_clear_bit(PG_direct, &(page)->flags) + +#define PageMappedToDisk(page) test_bit(PG_mappedtodisk, &(page)->flags) +#define SetPageMappedToDisk(page) set_bit(PG_mappedtodisk, &(page)->flags) +#define ClearPageMappedToDisk(page) clear_bit(PG_mappedtodisk, &(page)->flags) /* * The PageSwapCache predicate doesn't use a PG_flag at this time, diff -Nru a/include/linux/pagevec.h b/include/linux/pagevec.h --- a/include/linux/pagevec.h Fri Nov 22 13:41:23 2002 +++ b/include/linux/pagevec.h Fri Nov 22 13:41:23 2002 @@ -21,7 +21,6 @@ void __pagevec_free(struct pagevec *pvec); void __pagevec_lru_add(struct pagevec *pvec); void __pagevec_lru_add_active(struct pagevec *pvec); -void pagevec_deactivate_inactive(struct pagevec *pvec); void pagevec_strip(struct pagevec *pvec); unsigned int pagevec_lookup(struct pagevec *pvec, struct address_space *mapping, pgoff_t start, unsigned int nr_pages); diff -Nru a/include/linux/pci.h b/include/linux/pci.h --- a/include/linux/pci.h Fri Nov 22 13:41:19 2002 +++ b/include/linux/pci.h Fri Nov 22 13:41:19 2002 @@ -517,21 +517,6 @@ void pcibios_update_irq(struct pci_dev *, int irq); void pcibios_fixup_pbus_ranges(struct pci_bus *, struct pbus_set_ranges_data *); -/* Backward compatibility, don't use in new code! */ - -int pcibios_read_config_byte (unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned char *val); -int pcibios_read_config_word (unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned short *val); -int pcibios_read_config_dword (unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned int *val); -int pcibios_write_config_byte (unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned char val); -int pcibios_write_config_word (unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned short val); -int pcibios_write_config_dword (unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned int val); - /* Generic PCI functions used internally */ int pci_bus_exists(const struct list_head *list, int nr); @@ -616,8 +601,8 @@ /* Helper functions for low-level code (drivers/pci/setup-[bus,res].c) */ -void pbus_assign_resources(struct pci_bus *bus); -void pbus_size_bridges(struct pci_bus *bus); +void pci_bus_assign_resources(struct pci_bus *bus); +void pci_bus_size_bridges(struct pci_bus *bus); int pci_claim_resource(struct pci_dev *, int); void pci_assign_unassigned_resources(void); void pdev_enable_device(struct pci_dev *); @@ -668,8 +653,6 @@ static inline int pci_present(void) { return 0; } #define _PCI_NOP(o,s,t) \ - static inline int pcibios_##o##_config_##s (u8 bus, u8 dfn, u8 where, t val) \ - { return PCIBIOS_FUNC_NOT_SUPPORTED; } \ static inline int pci_##o##_config_##s (struct pci_dev *dev, int where, t val) \ { return PCIBIOS_FUNC_NOT_SUPPORTED; } #define _PCI_NOP_ALL(o,x) _PCI_NOP(o,byte,u8 x) \ diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h --- a/include/linux/pci_ids.h Fri Nov 22 13:41:19 2002 +++ b/include/linux/pci_ids.h Fri Nov 22 13:41:19 2002 @@ -1018,6 +1018,7 @@ #define PCI_DEVICE_ID_VIA_8361 0x3112 #define PCI_DEVICE_ID_VIA_8233A 0x3147 #define PCI_DEVICE_ID_VIA_8235 0x3177 +#define PCI_DEVICE_ID_VIA_8377_0 0x3189 #define PCI_DEVICE_ID_VIA_86C100A 0x6100 #define PCI_DEVICE_ID_VIA_8231 0x8231 #define PCI_DEVICE_ID_VIA_8231_4 0x8235 diff -Nru a/include/linux/sched.h b/include/linux/sched.h --- a/include/linux/sched.h Fri Nov 22 13:41:18 2002 +++ b/include/linux/sched.h Fri Nov 22 13:41:18 2002 @@ -46,10 +46,11 @@ #define CLONE_NEWNS 0x00020000 /* New namespace group? */ #define CLONE_SYSVSEM 0x00040000 /* share system V SEM_UNDO semantics */ #define CLONE_SETTLS 0x00080000 /* create a new TLS for the child */ -#define CLONE_SETTID 0x00100000 /* write the TID back to userspace */ -#define CLONE_CLEARTID 0x00200000 /* clear the userspace TID */ -#define CLONE_DETACHED 0x00400000 /* parent wants no child-exit signal */ -#define CLONE_UNTRACED 0x00800000 /* set if the tracing process can't force CLONE_PTRACE on this clone */ +#define CLONE_PARENT_SETTID 0x00100000 /* set the TID in the parent */ +#define CLONE_CHILD_CLEARTID 0x00200000 /* clear the TID in the child */ +#define CLONE_DETACHED 0x00400000 /* parent wants no child-exit signal */ +#define CLONE_UNTRACED 0x00800000 /* set if the tracing process can't force CLONE_PTRACE on this clone */ +#define CLONE_CHILD_SETTID 0x01000000 /* set the TID in the child */ /* * List of flags we want to share for kernel threads, @@ -149,7 +150,7 @@ extern void show_regs(struct pt_regs *); void io_schedule(void); -void io_schedule_timeout(long timeout); +long io_schedule_timeout(long timeout); extern void cpu_init (void); extern void trap_init(void); @@ -332,7 +333,8 @@ wait_queue_head_t wait_chldexit; /* for wait4() */ struct completion *vfork_done; /* for vfork() */ - int *user_tid; /* for CLONE_CLEARTID */ + int *set_child_tid; /* CLONE_CHILD_SETTID */ + int *clear_child_tid; /* CLONE_CHILD_CLEARTID */ unsigned long rt_priority; unsigned long it_real_value, it_prof_value, it_virt_value; @@ -524,36 +526,6 @@ extern int do_sigaction(int, const struct k_sigaction *, struct k_sigaction *); extern int do_sigaltstack(const stack_t *, stack_t *, unsigned long); -/* - * Re-calculate pending state from the set of locally pending - * signals, globally pending signals, and blocked signals. - */ -static inline int has_pending_signals(sigset_t *signal, sigset_t *blocked) -{ - unsigned long ready; - long i; - - switch (_NSIG_WORDS) { - default: - for (i = _NSIG_WORDS, ready = 0; --i >= 0 ;) - ready |= signal->sig[i] &~ blocked->sig[i]; - break; - - case 4: ready = signal->sig[3] &~ blocked->sig[3]; - ready |= signal->sig[2] &~ blocked->sig[2]; - ready |= signal->sig[1] &~ blocked->sig[1]; - ready |= signal->sig[0] &~ blocked->sig[0]; - break; - - case 2: ready = signal->sig[1] &~ blocked->sig[1]; - ready |= signal->sig[0] &~ blocked->sig[0]; - break; - - case 1: ready = signal->sig[0] &~ blocked->sig[0]; - } - return ready != 0; -} - /* True if we are on the alternate signal stack. */ static inline int on_sig_stack(unsigned long sp) @@ -615,7 +587,7 @@ extern task_t *child_reaper; extern int do_execve(char *, char **, char **, struct pt_regs *); -extern struct task_struct *do_fork(unsigned long, unsigned long, struct pt_regs *, unsigned long, int *); +extern struct task_struct *do_fork(unsigned long, unsigned long, struct pt_regs *, unsigned long, int *, int *); #ifdef CONFIG_SMP extern void wait_task_inactive(task_t * p); @@ -638,30 +610,6 @@ list_add_tail(&(p)->tasks,&init_task.tasks); \ add_parent(p, (p)->parent); \ } while (0) - -static inline struct task_struct *eldest_child(struct task_struct *p) -{ - if (list_empty(&p->children)) return NULL; - return list_entry(p->children.next,struct task_struct,sibling); -} - -static inline struct task_struct *youngest_child(struct task_struct *p) -{ - if (list_empty(&p->children)) return NULL; - return list_entry(p->children.prev,struct task_struct,sibling); -} - -static inline struct task_struct *older_sibling(struct task_struct *p) -{ - if (p->sibling.prev==&p->parent->children) return NULL; - return list_entry(p->sibling.prev,struct task_struct,sibling); -} - -static inline struct task_struct *younger_sibling(struct task_struct *p) -{ - if (p->sibling.next==&p->parent->children) return NULL; - return list_entry(p->sibling.next,struct task_struct,sibling); -} #define next_task(p) list_entry((p)->tasks.next, struct task_struct, tasks) #define prev_task(p) list_entry((p)->tasks.prev, struct task_struct, tasks) diff -Nru a/include/linux/sonypi.h b/include/linux/sonypi.h --- a/include/linux/sonypi.h Fri Nov 22 13:41:19 2002 +++ b/include/linux/sonypi.h Fri Nov 22 13:41:19 2002 @@ -1,7 +1,9 @@ /* * Sony Programmable I/O Control Device driver for VAIO * - * Copyright (C) 2001 Stelian Pop , Alcôve + * Copyright (C) 2001-2002 Stelian Pop + * + * Copyright (C) 2001-2002 Alcôve * * Copyright (C) 2001 Michael Ashley * @@ -85,6 +87,10 @@ #define SONYPI_EVENT_JOGDIAL_VFAST_UP 47 #define SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED 48 #define SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED 49 +#define SONYPI_EVENT_ZOOM_PRESSED 50 +#define SONYPI_EVENT_THUMBPHRASE_PRESSED 51 +#define SONYPI_EVENT_MEYE_FACE 52 +#define SONYPI_EVENT_MEYE_OPPOSITE 53 /* get/set brightness */ #define SONYPI_IOCGBRT _IOR('v', 0, __u8) diff -Nru a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h --- a/include/linux/sunrpc/xdr.h Fri Nov 22 13:41:23 2002 +++ b/include/linux/sunrpc/xdr.h Fri Nov 22 13:41:23 2002 @@ -155,6 +155,93 @@ extern void xdr_partial_copy_from_skb(struct xdr_buf *, unsigned int, skb_reader_t *, skb_read_actor_t); +/* + * Provide some simple tools for XDR buffer overflow-checking etc. + */ +struct xdr_stream { + uint32_t *p; /* start of available buffer */ + struct xdr_buf *buf; /* XDR buffer to read/write */ + + uint32_t *end; /* end of available buffer space */ + struct iovec *iov; /* pointer to the current iovec */ +}; + +/* + * Initialize an xdr_stream for encoding data. + * + * Note: at the moment the RPC client only passes the length of our + * scratch buffer in the xdr_buf's header iovec. Previously this + * meant we needed to call xdr_adjust_iovec() after encoding the + * data. With the new scheme, the xdr_stream manages the details + * of the buffer length, and takes care of adjusting the iovec + * length for us. + */ +static inline void +xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, uint32_t *p) +{ + struct iovec *iov = buf->head; + + xdr->buf = buf; + xdr->iov = iov; + xdr->end = (uint32_t *)((char *)iov->iov_base + iov->iov_len); + buf->len = iov->iov_len = (char *)p - (char *)iov->iov_base; + xdr->p = p; +} + +/* + * Check that we have enough buffer space to encode 'nbytes' more + * bytes of data. If so, update the total xdr_buf length, and + * adjust the length of the current iovec. + */ +static inline uint32_t * +xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes) +{ + uint32_t *p = xdr->p; + uint32_t *q; + + /* align nbytes on the next 32-bit boundary */ + nbytes += 3; + nbytes &= ~3; + q = p + (nbytes >> 2); + if (unlikely(q > xdr->end || q < p)) + return NULL; + xdr->p = q; + xdr->iov->iov_len += nbytes; + xdr->buf->len += nbytes; + return p; +} + +/* + * Initialize an xdr_stream for decoding data. + */ +static inline void +xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, uint32_t *p) +{ + struct iovec *iov = buf->head; + xdr->buf = buf; + xdr->iov = iov; + xdr->p = p; + xdr->end = (uint32_t *)((char *)iov->iov_base + iov->iov_len); +} + +/* + * Check if the input buffer is long enough to enable us to decode + * 'nbytes' more bytes of data starting at the current position. + * If so return the current pointer, then update the current + * position. + */ +static inline uint32_t * +xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes) +{ + uint32_t *p = xdr->p; + uint32_t *q = p + XDR_QUADLEN(nbytes); + + if (unlikely(q > xdr->end || q < p)) + return NULL; + xdr->p = q; + return p; +} + #endif /* __KERNEL__ */ #endif /* _SUNRPC_XDR_H_ */ diff -Nru a/include/linux/udf_fs_i.h b/include/linux/udf_fs_i.h --- a/include/linux/udf_fs_i.h Fri Nov 22 13:41:17 2002 +++ b/include/linux/udf_fs_i.h Fri Nov 22 13:41:17 2002 @@ -43,10 +43,7 @@ struct udf_inode_info { - long i_umtime; - long i_uctime; - long i_crtime; - long i_ucrtime; + struct timespec i_crtime; /* Physical address of inode */ lb_addr i_location; __u64 i_unique; diff -Nru a/include/linux/udf_fs_sb.h b/include/linux/udf_fs_sb.h --- a/include/linux/udf_fs_sb.h Fri Nov 22 13:41:23 2002 +++ b/include/linux/udf_fs_sb.h Fri Nov 22 13:41:23 2002 @@ -97,7 +97,7 @@ uid_t s_uid; /* Root Info */ - time_t s_recordtime; + struct timespec s_recordtime; /* Fileset Info */ __u16 s_serialnum; diff -Nru a/include/linux/umsdos_fs.p b/include/linux/umsdos_fs.p --- a/include/linux/umsdos_fs.p Fri Nov 22 13:41:18 2002 +++ b/include/linux/umsdos_fs.p Fri Nov 22 13:41:18 2002 @@ -82,7 +82,7 @@ int UMSDOS_mknod (struct inode *dir, struct dentry *dentry, int mode, - int rdev); + dev_t rdev); int UMSDOS_rmdir (struct inode *dir,struct dentry *dentry); int UMSDOS_unlink (struct inode *dir, struct dentry *dentry); int UMSDOS_rename (struct inode *old_dir, diff -Nru a/include/linux/umsdos_fs_i.h b/include/linux/umsdos_fs_i.h --- a/include/linux/umsdos_fs_i.h Fri Nov 22 13:41:22 2002 +++ b/include/linux/umsdos_fs_i.h Fri Nov 22 13:41:22 2002 @@ -50,9 +50,9 @@ struct umsdos_inode_info { struct msdos_inode_info msdos_info; struct dir_locking_info dir_info; - int i_patched; /* Inode has been patched */ - int i_is_hlink; /* Resolved hardlink inode? */ - off_t pos; /* Entry offset in the emd_owner file */ + int i_patched; /* Inode has been patched */ + int i_is_hlink; /* Resolved hardlink inode? */ + off_t pos; /* Entry offset in the emd_owner file */ }; #endif diff -Nru a/include/math-emu/op-4.h b/include/math-emu/op-4.h --- a/include/math-emu/op-4.h Fri Nov 22 13:41:23 2002 +++ b/include/math-emu/op-4.h Fri Nov 22 13:41:23 2002 @@ -513,58 +513,84 @@ (X##_f[3] = I3, X##_f[2] = I2, X##_f[1] = I1, X##_f[0] = I0) #ifndef __FP_FRAC_ADD_3 -#define __FP_FRAC_ADD_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \ - (r0 = x0 + y0, \ - r1 = x1 + y1 + (r0 < x0), \ - r2 = x2 + y2 + (r1 < x1)) +#define __FP_FRAC_ADD_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \ + do { \ + int _c1, _c2; \ + r0 = x0 + y0; \ + _c1 = r0 < x0; \ + r1 = x1 + y1; \ + _c2 = r1 < x1; \ + r1 += _c1; \ + _c2 |= r1 < _c1; \ + r2 = x2 + y2 + _c2; \ + } while (0) #endif #ifndef __FP_FRAC_ADD_4 -#define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \ - (r0 = x0 + y0, \ - r1 = x1 + y1 + (r0 < x0), \ - r2 = x2 + y2 + (r1 < x1), \ - r3 = x3 + y3 + (r2 < x2)) +#define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \ + do { \ + int _c1, _c2, _c3; \ + r0 = x0 + y0; \ + _c1 = r0 < x0; \ + r1 = x1 + y1; \ + _c2 = r1 < x1; \ + r1 += _c1; \ + _c2 |= r1 < _c1; \ + r2 = x2 + y2; \ + _c3 = r2 < x2; \ + r2 += _c2; \ + _c3 |= r2 < _c2; \ + r3 = x3 + y3 + _c3; \ + } while (0) #endif #ifndef __FP_FRAC_SUB_3 -#define __FP_FRAC_SUB_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \ - (r0 = x0 - y0, \ - r1 = x1 - y1 - (r0 > x0), \ - r2 = x2 - y2 - (r1 > x1)) +#define __FP_FRAC_SUB_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \ + do { \ + int _c1, _c2; \ + r0 = x0 - y0; \ + _c1 = r0 > x0; \ + r1 = x1 - y1; \ + _c2 = r1 > x1; \ + r1 -= _c1; \ + _c2 |= r1 > _c1; \ + r2 = x2 - y2 - _c2; \ + } while (0) #endif #ifndef __FP_FRAC_SUB_4 -#define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \ - (r0 = x0 - y0, \ - r1 = x1 - y1 - (r0 > x0), \ - r2 = x2 - y2 - (r1 > x1), \ - r3 = x3 - y3 - (r2 > x2)) +#define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \ + do { \ + int _c1, _c2, _c3; \ + r0 = x0 - y0; \ + _c1 = r0 > x0; \ + r1 = x1 - y1; \ + _c2 = r1 > x1; \ + r1 -= _c1; \ + _c2 |= r1 > _c1; \ + r2 = x2 - y2; \ + _c3 = r2 > x2; \ + r2 -= _c2; \ + _c3 |= r2 > _c2; \ + r3 = x3 - y3 - _c3; \ + } while (0) #endif #ifndef __FP_FRAC_DEC_3 #define __FP_FRAC_DEC_3(x2,x1,x0,y2,y1,y0) \ do { \ - UWtype _t0, _t1; \ - _t0 = x0; \ - x0 -= y0; \ - _t1 = x1; \ - x1 -= y1 + (x0 > _t0); \ - x2 -= y2 + (x1 > _t1); \ + UWtype _t0, _t1, _t2; \ + _t0 = x0, _t1 = x1, _t2 = x2; \ + __FP_FRAC_SUB_3 (x2, x1, x0, _t2, _t1, _t0, y2, y1, y0); \ } while (0) #endif #ifndef __FP_FRAC_DEC_4 #define __FP_FRAC_DEC_4(x3,x2,x1,x0,y3,y2,y1,y0) \ do { \ - UWtype _t0, _t1; \ - _t0 = x0; \ - x0 -= y0; \ - _t1 = x1; \ - x1 -= y1 + (x0 > _t0); \ - _t0 = x2; \ - x2 -= y2 + (x1 > _t1); \ - x3 -= y3 + (x2 > _t0); \ + UWtype _t0, _t1, _t2, _t3; \ + _t0 = x0, _t1 = x1, _t2 = x2, _t3 = x3; \ + __FP_FRAC_SUB_4 (x3,x2,x1,x0,_t3,_t2,_t1,_t0, y3,y2,y1,y0); \ } while (0) #endif diff -Nru a/include/net/sctp/command.h b/include/net/sctp/command.h --- a/include/net/sctp/command.h Fri Nov 22 13:41:23 2002 +++ b/include/net/sctp/command.h Fri Nov 22 13:41:23 2002 @@ -27,6 +27,7 @@ * * La Monte H.P. Yarroll * Karl Knutson + * Ardelle Fan * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -72,6 +73,7 @@ SCTP_CMD_STRIKE, /* Mark a strike against a transport. */ SCTP_CMD_TRANSMIT, /* Transmit the outqueue. */ SCTP_CMD_HB_TIMERS_START, /* Start the heartbeat timers. */ + SCTP_CMD_HB_TIMERS_UPDATE, /* Update the heartbeat timers. */ SCTP_CMD_TRANSPORT_RESET, /* Reset the status of a transport. */ SCTP_CMD_TRANSPORT_ON, /* Mark the transport as active. */ SCTP_CMD_REPORT_ERROR, /* Pass this error back out of the sm. */ @@ -83,6 +85,7 @@ SCTP_CMD_UPDATE_ASSOC, /* Update association information. */ SCTP_CMD_PURGE_OUTQUEUE, /* Purge all data waiting to be sent. */ SCTP_CMD_SETUP_T2, /* Hi-level, setup T2-shutdown parms. */ + SCTP_CMD_RTO_PENDING, /* Set transport's rto_pending. */ SCTP_CMD_LAST } sctp_verb_t; diff -Nru a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h --- a/include/net/sctp/sctp.h Fri Nov 22 13:41:18 2002 +++ b/include/net/sctp/sctp.h Fri Nov 22 13:41:18 2002 @@ -1,43 +1,43 @@ /* SCTP kernel reference Implementation * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001 International Business Machines, Corp. + * Copyright (c) 2001-2002 International Business Machines, Corp. * Copyright (c) 2001 Intel Corp. - * + * * This file is part of the SCTP kernel reference Implementation - * - * The base lksctp header. - * - * The SCTP reference implementation is free software; - * you can redistribute it and/or modify it under the terms of + * + * The base lksctp header. + * + * The SCTP reference implementation 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. - * - * The SCTP reference implementation is distributed in the hope that it + * + * The SCTP reference implementation 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 GNU CC; see the file COPYING. If not, write to * the Free Software Foundation, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * + * Boston, MA 02111-1307, USA. + * * Please send any bug reports or fixes you make to the * email address(es): * lksctp developers - * + * * Or submit a bug report through the following website: * http://www.sf.net/projects/lksctp * - * Written or modified by: + * Written or modified by: * La Monte H.P. Yarroll * Xingang Guo * Jon Grimm * Daisy Chang - * + * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. */ @@ -52,10 +52,10 @@ * structs * prototypes * macros, externs, and inlines - * - * Move test_frame specific items out of the kernel headers + * + * Move test_frame specific items out of the kernel headers * and into the test frame headers. This is not perfect in any sense - * and will continue to evolve. + * and will continue to evolve. */ @@ -78,7 +78,7 @@ #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) #include #include -#endif +#endif #include #include @@ -105,19 +105,19 @@ #endif -/* Certain internal static functions need to be exported when +/* Certain internal static functions need to be exported when * compiled into the test frame. */ #ifndef SCTP_STATIC #define SCTP_STATIC static #endif -/* - * Function declarations. +/* + * Function declarations. */ /* - * sctp_protocol.c + * sctp_protocol.c */ extern sctp_protocol_t sctp_proto; extern struct sock *sctp_get_ctl_sock(void); @@ -142,7 +142,7 @@ extern int sctp_primitive_SHUTDOWN(sctp_association_t *, void *arg); extern int sctp_primitive_ABORT(sctp_association_t *, void *arg); extern int sctp_primitive_SEND(sctp_association_t *, void *arg); - +extern int sctp_primitive_REQUESTHEARTBEAT(sctp_association_t *, void *arg); /* * sctp_crc32c.c @@ -418,6 +418,19 @@ return retval; } +/* Walk through a list of TLV parameters. Don't trust the + * individual parameter lengths and instead depend on + * the chunk length to indicate when to stop. Make sure + * there is room for a param header too. + */ +#define sctp_walk_params(pos, chunk, member)\ +_sctp_walk_params((pos), (chunk), ntohs((chunk)->chunk_hdr.length), member) + +#define _sctp_walk_params(pos, chunk, end, member)\ +for (pos.v = chunk->member;\ + pos.v <= (void *)chunk + end - sizeof(sctp_paramhdr_t) &&\ + pos.v <= (void *)chunk + end - WORD_ROUND(ntohs(pos.p->length)); \ + pos.v += WORD_ROUND(ntohs(pos.p->length))) /* Round an int up to the next multiple of 4. */ #define WORD_ROUND(s) (((s)+3)&~3) @@ -458,6 +471,26 @@ static inline sctp_protocol_t *sctp_get_protocol(void) { return &sctp_proto; +} + +/* Convert from an IP version number to an Address Family symbol. */ +static inline int ipver2af(__u8 ipver) +{ + int family; + + switch (ipver) { + case 4: + family = AF_INET; + break; + case 6: + family = AF_INET6; + break; + default: + family = 0; + break; + }; + + return family; } /* Warning: The following hash functions assume a power of two 'size'. */ diff -Nru a/include/net/sctp/sm.h b/include/net/sctp/sm.h --- a/include/net/sctp/sm.h Fri Nov 22 13:41:19 2002 +++ b/include/net/sctp/sm.h Fri Nov 22 13:41:19 2002 @@ -53,7 +53,6 @@ #include #include -#include #include #include #include @@ -157,6 +156,7 @@ sctp_state_fn_t sctp_sf_error_closed; sctp_state_fn_t sctp_sf_error_shutdown; sctp_state_fn_t sctp_sf_ignore_primitive; +sctp_state_fn_t sctp_sf_do_prm_requestheartbeat; /* Prototypes for other event state functions. */ sctp_state_fn_t sctp_sf_do_9_2_start_shutdown; @@ -206,9 +206,6 @@ sctp_chunk_t *, const int priority); __u32 sctp_generate_verification_tag(void); -sctpParam_t sctp_get_my_addrs_raw(const sctp_association_t *, - const int priority, int *addrs_len); - void sctp_populate_tie_tags(__u8 *cookie, __u32 curTag, __u32 hisTag); /* Prototypes for chunk-building functions. */ @@ -334,10 +331,10 @@ __u32 sctp_generate_tsn(const sctp_endpoint_t *); /* 4th level prototypes */ -void sctp_param2sockaddr(sockaddr_storage_t *addr, sctp_addr_param_t *, +void sctp_param2sockaddr(union sctp_addr *addr, sctp_addr_param_t *, __u16 port); -int sctp_addr2sockaddr(const sctpParam_t, sockaddr_storage_t *); -int sockaddr2sctp_addr(const sockaddr_storage_t *, sctp_addr_param_t *); +int sctp_addr2sockaddr(const union sctp_params, union sctp_addr *); +int sockaddr2sctp_addr(const union sctp_addr *, sctp_addr_param_t *); /* Extern declarations for major data structures. */ sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t, sctp_state_t); diff -Nru a/include/net/sctp/structs.h b/include/net/sctp/structs.h --- a/include/net/sctp/structs.h Fri Nov 22 13:41:23 2002 +++ b/include/net/sctp/structs.h Fri Nov 22 13:41:23 2002 @@ -2,35 +2,35 @@ * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 2001 Intel Corp. - * Copyright (c) 2001 International Business Machines Corp. - * + * Copyright (c) 2001-2002 International Business Machines Corp. + * * This file is part of the SCTP kernel reference Implementation - * - * The SCTP reference implementation is free software; - * you can redistribute it and/or modify it under the terms of + * + * The SCTP reference implementation 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. - * - * The SCTP reference implementation is distributed in the hope that it + * + * The SCTP reference implementation 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 GNU CC; see the file COPYING. If not, write to * the Free Software Foundation, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * + * Boston, MA 02111-1307, USA. + * * Please send any bug reports or fixes you make to the * email addresses: * lksctp developers - * + * * Or submit a bug report through the following website: * http://www.sf.net/projects/lksctp * - * Written or modified by: + * Written or modified by: * Randall Stewart * Ken Morneau * Qiaobing Xie @@ -41,8 +41,8 @@ * Hui Huang * Sridhar Samudrala * Daisy Chang - * Dajiang Zhang - * + * Dajiang Zhang + * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. */ @@ -95,11 +95,11 @@ /* A convenience structure for handling sockaddr structures. * We should wean ourselves off this. */ -typedef union { +union sctp_addr { struct sockaddr_in v4; struct sockaddr_in6 v6; struct sockaddr sa; -} sockaddr_storage_t; +}; /* Forward declarations for data structures. */ @@ -246,29 +246,47 @@ int optname, char *optval, int *optlen); - struct dst_entry *(*get_dst) (sockaddr_storage_t *daddr, - sockaddr_storage_t *saddr); - int (*cmp_saddr) (struct dst_entry *dst, - sockaddr_storage_t *saddr); - __u16 net_header_len; + struct dst_entry *(*get_dst) (union sctp_addr *daddr, + union sctp_addr *saddr); + void (*copy_addrlist) (struct list_head *, + struct net_device *); + void (*dst_saddr) (union sctp_addr *saddr, + struct dst_entry *dst); + int (*cmp_addr) (const union sctp_addr *addr1, + const union sctp_addr *addr2); + void (*addr_copy) (union sctp_addr *dst, + union sctp_addr *src); + void (*from_skb) (union sctp_addr *, + struct sk_buff *skb, + int saddr); + int (*addr_valid) (union sctp_addr *); + sctp_scope_t (*scope) (union sctp_addr *); + void (*inaddr_any) (union sctp_addr *, unsigned short); + int (*is_any) (const union sctp_addr *); + __u16 net_header_len; int sockaddr_len; sa_family_t sa_family; struct list_head list; } sctp_func_t; -sctp_func_t *sctp_get_af_specific(const sockaddr_storage_t *address); +sctp_func_t *sctp_get_af_specific(sa_family_t); /* Protocol family functions. */ typedef struct sctp_pf { void (*event_msgname)(sctp_ulpevent_t *, char *, int *); void (*skb_msgname)(struct sk_buff *, char *, int *); + int (*af_supported)(sa_family_t); + int (*cmp_addr) (const union sctp_addr *, + const union sctp_addr *, + struct sctp_opt *); + struct sctp_func *af; } sctp_pf_t; /* SCTP Socket type: UDP or TCP style. */ typedef enum { SCTP_SOCKET_UDP = 0, - SCTP_SOCKET_UDP_HIGH_BANDWIDTH, - SCTP_SOCKET_TCP + SCTP_SOCKET_UDP_HIGH_BANDWIDTH, + SCTP_SOCKET_TCP } sctp_socket_type_t; /* Per socket SCTP information. */ @@ -339,7 +357,7 @@ __u32 initial_tsn; /* This holds the originating address of the INIT packet. */ - sockaddr_storage_t peer_addr; + union sctp_addr peer_addr; /* This is a shim for my peer's INIT packet, followed by * a copy of the raw address list of the association. @@ -359,20 +377,6 @@ } sctp_signed_cookie_t; -/* This convenience type allows us to avoid casting when walking - * through a parameter list. - */ -typedef union { - __u8 *v; - sctp_paramhdr_t *p; - - sctp_cookie_preserve_param_t *bht; - sctp_hostname_param_t *dns; - sctp_cookie_param_t *cookie; - sctp_supported_addrs_param_t *sat; - sctp_ipv4addr_param_t *v4; - sctp_ipv6addr_param_t *v6; -} sctpParam_t; /* This is another convenience type to allocate memory for address * params for the maximum size and pass such structures around @@ -383,6 +387,21 @@ sctp_ipv6addr_param_t v6; } sctp_addr_param_t; +/* A convenience type to allow walking through the various + * parameters and avoid casting all over the place. + */ +union sctp_params { + void *v; + sctp_paramhdr_t *p; + sctp_cookie_preserve_param_t *life; + sctp_hostname_param_t *dns; + sctp_cookie_param_t *cookie; + sctp_supported_addrs_param_t *sat; + sctp_ipv4addr_param_t *v4; + sctp_ipv6addr_param_t *v6; + sctp_addr_param_t *addr; +}; + /* RFC 2960. Section 3.3.5 Heartbeat. * Heartbeat Information: variable length * The Sender-specific Heartbeat Info field should normally include @@ -392,7 +411,7 @@ */ typedef struct sctp_sender_hb_info { sctp_paramhdr_t param_hdr; - sockaddr_storage_t daddr; + union sctp_addr daddr; unsigned long sent_at; } sctp_sender_hb_info_t __attribute__((packed)); @@ -433,7 +452,7 @@ */ /* We point this at the FIRST TLV parameter to chunk_hdr. */ - sctpParam_t param_hdr; + union sctp_params param_hdr; union { __u8 *v; sctp_datahdr_t *data_hdr; @@ -474,13 +493,13 @@ __u8 ecn_ce_done; /* Have we processed the ECN CE bit? */ __u8 pdiscard; /* Discard the whole packet now? */ __u8 tsn_gap_acked; /* Is this chunk acked by a GAP ACK? */ - __u8 fast_retransmit; /* Is this chunk fast retransmitted? */ + __u8 fast_retransmit; /* Is this chunk fast retransmitted? */ __u8 tsn_missing_report; /* Data chunk missing counter. */ /* What is the origin IP address for this chunk? */ - sockaddr_storage_t source; + union sctp_addr source; /* Destination address for this chunk. */ - sockaddr_storage_t dest; + union sctp_addr dest; /* For an inbound chunk, this tells us where it came from. * For an outbound chunk, it tells us where we'd like it to @@ -497,8 +516,8 @@ int sctp_user_addto_chunk(sctp_chunk_t *chunk, int len, struct iovec *data); sctp_chunk_t *sctp_chunkify(struct sk_buff *, const sctp_association_t *, struct sock *); -void sctp_init_addrs(sctp_chunk_t *chunk); -const sockaddr_storage_t *sctp_source(const sctp_chunk_t *chunk); +void sctp_init_addrs(sctp_chunk_t *, union sctp_addr *, union sctp_addr *); +const union sctp_addr *sctp_source(const sctp_chunk_t *chunk); /* This is a structure for holding either an IPv6 or an IPv4 address. */ /* sin_family -- AF_INET or AF_INET6 @@ -507,7 +526,7 @@ */ struct sockaddr_storage_list { struct list_head list; - sockaddr_storage_t a; + union sctp_addr a; }; typedef sctp_chunk_t *(sctp_packet_phandler_t)(sctp_association_t *); @@ -573,7 +592,7 @@ /* This represents a remote transport address. - * For local transport addresses, we just use sockaddr_storage_t. + * For local transport addresses, we just use union sctp_addr. * * RFC2960 Section 1.4 Key Terms * @@ -601,7 +620,7 @@ int dead; /* This is the peer's IP address and port. */ - sockaddr_storage_t ipaddr; + union sctp_addr ipaddr; /* These are the functions we call to handle LLP stuff. */ sctp_func_t *af_specific; @@ -684,13 +703,15 @@ */ unsigned long last_time_ecne_reduced; - /* state : The current state of this destination, - * : i.e. DOWN, UP, ALLOW-HB, NO-HEARTBEAT, etc. + /* active : The current active state of this destination, + * : i.e. DOWN, UP, etc. */ - struct { - int active; - int hb_allowed; - } state; + int active; + + /* hb_allowed : The current heartbeat state of this destination, + * : i.e. ALLOW-HB, NO-HEARTBEAT, etc. + */ + int hb_allowed; /* These are the error stats for this destination. */ @@ -739,11 +760,12 @@ int malloced; /* Is this structure kfree()able? */ }; -extern sctp_transport_t *sctp_transport_new(const sockaddr_storage_t *, int); +extern sctp_transport_t *sctp_transport_new(const union sctp_addr *, int); extern sctp_transport_t *sctp_transport_init(sctp_transport_t *, - const sockaddr_storage_t *, int); + const union sctp_addr *, int); extern void sctp_transport_set_owner(sctp_transport_t *, sctp_association_t *); -extern void sctp_transport_route(sctp_transport_t *, sockaddr_storage_t *); +extern void sctp_transport_route(sctp_transport_t *, union sctp_addr *, + struct sctp_opt *); extern void sctp_transport_free(sctp_transport_t *); extern void sctp_transport_destroy(sctp_transport_t *); extern void sctp_transport_reset_timers(sctp_transport_t *); @@ -890,30 +912,31 @@ void sctp_bind_addr_free(sctp_bind_addr_t *); int sctp_bind_addr_copy(sctp_bind_addr_t *dest, const sctp_bind_addr_t *src, sctp_scope_t scope, int priority,int flags); -int sctp_add_bind_addr(sctp_bind_addr_t *, sockaddr_storage_t *, +int sctp_add_bind_addr(sctp_bind_addr_t *, union sctp_addr *, int priority); -int sctp_del_bind_addr(sctp_bind_addr_t *, sockaddr_storage_t *); -int sctp_bind_addr_has_addr(sctp_bind_addr_t *, const sockaddr_storage_t *); -sctpParam_t sctp_bind_addrs_to_raw(const sctp_bind_addr_t *bp, - int *addrs_len, - int priority); +int sctp_del_bind_addr(sctp_bind_addr_t *, union sctp_addr *); +int sctp_bind_addr_match(sctp_bind_addr_t *, const union sctp_addr *, + struct sctp_opt *); +union sctp_params sctp_bind_addrs_to_raw(const sctp_bind_addr_t *bp, + int *addrs_len, + int priority); int sctp_raw_to_bind_addrs(sctp_bind_addr_t *bp, __u8 *raw_addr_list, int addrs_len, unsigned short port, int priority); -sctp_scope_t sctp_scope(const sockaddr_storage_t *); -int sctp_in_scope(const sockaddr_storage_t *addr, const sctp_scope_t scope); -int sctp_is_any(const sockaddr_storage_t *addr); -int sctp_addr_is_valid(const sockaddr_storage_t *addr); +sctp_scope_t sctp_scope(const union sctp_addr *); +int sctp_in_scope(const union sctp_addr *addr, const sctp_scope_t scope); +int sctp_is_any(const union sctp_addr *addr); +int sctp_addr_is_valid(const union sctp_addr *addr); /* What type of sctp_endpoint_common? */ typedef enum { SCTP_EP_TYPE_SOCKET, SCTP_EP_TYPE_ASSOCIATION, -} sctp_endpoint_type_t; +} sctp_endpoint_type_t; /* * A common base class to bridge the implmentation view of a @@ -1048,35 +1071,25 @@ void sctp_endpoint_hold(sctp_endpoint_t *); void sctp_endpoint_add_asoc(sctp_endpoint_t *, sctp_association_t *asoc); sctp_association_t *sctp_endpoint_lookup_assoc(const sctp_endpoint_t *ep, - const sockaddr_storage_t *paddr, + const union sctp_addr *paddr, sctp_transport_t **); +int sctp_endpoint_is_peeled_off(sctp_endpoint_t *, const union sctp_addr *); sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *, - const sockaddr_storage_t *); + const union sctp_addr *); -int sctp_has_association(const sockaddr_storage_t *laddr, - const sockaddr_storage_t *paddr); +int sctp_has_association(const union sctp_addr *laddr, + const union sctp_addr *paddr); int sctp_verify_init(const sctp_association_t *asoc, sctp_cid_t cid, sctp_init_chunk_t *peer_init, sctp_chunk_t *chunk, sctp_chunk_t **err_chunk); -int sctp_verify_param(const sctp_association_t *asoc, - sctpParam_t param, - sctp_cid_t cid, - sctp_chunk_t *chunk, - sctp_chunk_t **err_chunk); -int sctp_process_unk_param(const sctp_association_t *asoc, - sctpParam_t param, - sctp_chunk_t *chunk, - sctp_chunk_t **err_chunk); -void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid, - const sockaddr_storage_t *peer_addr, - sctp_init_chunk_t *peer_init, int priority); -int sctp_process_param(sctp_association_t *asoc, - sctpParam_t param, - const sockaddr_storage_t *peer_addr, - sctp_cid_t cid, int priority); +int sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid, + const union sctp_addr *peer_addr, + sctp_init_chunk_t *peer_init, int priority); +int sctp_process_param(sctp_association_t *asoc, union sctp_params param, + const union sctp_addr *peer_addr, int priority); __u32 sctp_generate_tag(const sctp_endpoint_t *ep); __u32 sctp_generate_tsn(const sctp_endpoint_t *ep); @@ -1163,10 +1176,10 @@ sctp_transport_t *primary_path; /* Cache the primary path address here, when we - * need a an address for msg_name. + * need a an address for msg_name. */ - sockaddr_storage_t primary_addr; - + union sctp_addr primary_addr; + /* active_path * The path that we are currently using to * transmit new data and most control chunks. @@ -1267,7 +1280,7 @@ /* Overall : The threshold for this association that if * Error : the Overall Error Count reaches will cause - * Threshold : this association to be torn down. + * Threshold : this association to be torn down. */ int overall_error_threshold; @@ -1313,13 +1326,13 @@ */ __u32 next_tsn; - /* + /* * Last Rcvd : This is the last TSN received in sequence. This value * TSN : is set initially by taking the peer's Initial TSN, * : received in the INIT or INIT ACK chunk, and * : subtracting one from it. * - * Most of RFC 2960 refers to this as the Cumulative TSN Ack Point. + * Most of RFC 2960 refers to this as the Cumulative TSN Ack Point. */ __u32 ctsn_ack_point; @@ -1543,16 +1556,16 @@ sctp_transport_t *sctp_assoc_choose_shutdown_transport(sctp_association_t *); sctp_transport_t *sctp_assoc_lookup_paddr(const sctp_association_t *, - const sockaddr_storage_t *); + const union sctp_addr *); sctp_transport_t *sctp_assoc_add_peer(sctp_association_t *, - const sockaddr_storage_t *address, + const union sctp_addr *address, const int priority); void sctp_assoc_control_transport(sctp_association_t *, sctp_transport_t *, sctp_transport_cmd_t, sctp_sn_error_t); sctp_transport_t *sctp_assoc_lookup_tsn(sctp_association_t *, __u32); sctp_transport_t *sctp_assoc_is_match(sctp_association_t *, - const sockaddr_storage_t *, - const sockaddr_storage_t *); + const union sctp_addr *, + const union sctp_addr *); void sctp_assoc_migrate(sctp_association_t *, struct sock *); void sctp_assoc_update(sctp_association_t *dst, sctp_association_t *src); @@ -1560,13 +1573,10 @@ __u32 __sctp_association_get_tsn_block(sctp_association_t *, int); __u16 __sctp_association_get_next_ssn(sctp_association_t *, __u16 sid); -int sctp_cmp_addr(const sockaddr_storage_t *ss1, - const sockaddr_storage_t *ss2); -int sctp_cmp_addr_exact(const sockaddr_storage_t *ss1, - const sockaddr_storage_t *ss2); +int sctp_cmp_addr_exact(const union sctp_addr *ss1, + const union sctp_addr *ss2); sctp_chunk_t *sctp_get_ecne_prepend(sctp_association_t *asoc); sctp_chunk_t *sctp_get_no_prepend(sctp_association_t *asoc); - /* A convenience structure to parse out SCTP specific CMSGs. */ typedef struct sctp_cmsgs { diff -Nru a/include/net/xfrm.h b/include/net/xfrm.h --- a/include/net/xfrm.h Fri Nov 22 13:41:18 2002 +++ b/include/net/xfrm.h Fri Nov 22 13:41:18 2002 @@ -195,6 +195,7 @@ /* This lock only affects elements except for entry. */ rwlock_t lock; atomic_t refcnt; + struct timer_list timer; u32 priority; u32 index; diff -Nru a/include/pcmcia/mem_op.h b/include/pcmcia/mem_op.h --- a/include/pcmcia/mem_op.h Fri Nov 22 13:41:23 2002 +++ b/include/pcmcia/mem_op.h Fri Nov 22 13:41:23 2002 @@ -31,6 +31,7 @@ #define _LINUX_MEM_OP_H #include +#include /* If UNSAFE_MEMCPY is defined, we use the (optimized) system routines diff -Nru a/include/scsi/scsi_ioctl.h b/include/scsi/scsi_ioctl.h --- a/include/scsi/scsi_ioctl.h Fri Nov 22 13:41:17 2002 +++ b/include/scsi/scsi_ioctl.h Fri Nov 22 13:41:17 2002 @@ -17,6 +17,8 @@ #ifdef __KERNEL__ +struct scsi_device; + /* * Structures used for scsi_ioctl et al. */ @@ -33,19 +35,15 @@ } Scsi_Idlun; /* Fibre Channel WWN, port_id struct */ -typedef struct scsi_fctargaddress -{ +typedef struct scsi_fctargaddress { __u32 host_port_id; unsigned char host_wwn[8]; // include NULL term. } Scsi_FCTargAddress; -extern int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg); -extern int kernel_scsi_ioctl (Scsi_Device *dev, int cmd, void *arg); -extern int scsi_ioctl_send_command(Scsi_Device *dev, - Scsi_Ioctl_Command *arg); - -#endif - -#endif - +extern int scsi_ioctl(struct scsi_device *, int, void *); +extern int kernel_scsi_ioctl(struct scsi_device *, int , void *); +extern int scsi_ioctl_send_command(struct scsi_device *, + struct scsi_ioctl_command *); +#endif /* __KERNEL__ */ +#endif /* _SCSI_IOCTL_H */ diff -Nru a/include/sound/core.h b/include/sound/core.h --- a/include/sound/core.h Fri Nov 22 13:41:23 2002 +++ b/include/sound/core.h Fri Nov 22 13:41:23 2002 @@ -177,11 +177,11 @@ wake_up(&card->power_sleep); } #else -#define snd_power_lock(card) do { ; } while (0) -#define snd_power_unlock(card) do { ; } while (0) -#define snd_power_wait(card) do { ; } while (0) -#define snd_power_get_state(card) SNDRV_CTL_POWER_D0 -#define snd_power_change_state(card, state) do { ; } while (0) +#define snd_power_lock(card) do { (void)(card); } while (0) +#define snd_power_unlock(card) do { (void)(card); } while (0) +#define snd_power_wait(card) do { (void)(card); } while (0) +#define snd_power_get_state(card) SNDRV_CTL_POWER_D0 +#define snd_power_change_state(card, state) do { (void)(card); } while (0) #endif /* device.c */ diff -Nru a/init/initramfs.c b/init/initramfs.c --- a/init/initramfs.c Fri Nov 22 13:41:17 2002 +++ b/init/initramfs.c Fri Nov 22 13:41:17 2002 @@ -299,14 +299,14 @@ } static __initdata int (*actions[])(void) = { - [Start] do_start, - [Collect] do_collect, - [GotHeader] do_header, - [SkipIt] do_skip, - [GotName] do_name, - [CopyFile] do_copy, - [GotSymlink] do_symlink, - [Reset] do_reset, + [Start] = do_start, + [Collect] = do_collect, + [GotHeader] = do_header, + [SkipIt] = do_skip, + [GotName] = do_name, + [CopyFile] = do_copy, + [GotSymlink] = do_symlink, + [Reset] = do_reset, }; static int __init write_buffer(char *buf, unsigned len) diff -Nru a/ipc/shm.c b/ipc/shm.c --- a/ipc/shm.c Fri Nov 22 13:41:20 2002 +++ b/ipc/shm.c Fri Nov 22 13:41:20 2002 @@ -700,24 +700,18 @@ asmlinkage long sys_shmdt (char *shmaddr) { struct mm_struct *mm = current->mm; - struct vm_area_struct *vma; - unsigned long address = (unsigned long)shmaddr; + struct vm_area_struct *shmd, *shmdnext; int retval = -EINVAL; down_write(&mm->mmap_sem); - vma = find_vma(mm, address); - if (!vma) - goto out; - if (vma->vm_start != address) - goto out; - - /* ->vm_pgoff is always 0, see do_mmap() in sys_shmat() */ - retval = 0; - if (vma->vm_ops == &shm_vm_ops || (vma->vm_flags & VM_HUGETLB)) - do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start); - else - retval = -EINVAL; -out: + for (shmd = mm->mmap; shmd; shmd = shmdnext) { + shmdnext = shmd->vm_next; + if ((shmd->vm_ops == &shm_vm_ops || (shmd->vm_flags & VM_HUGETLB)) + && shmd->vm_start - (shmd->vm_pgoff << PAGE_SHIFT) == (ulong) shmaddr) { + do_munmap(mm, shmd->vm_start, shmd->vm_end - shmd->vm_start); + retval = 0; + } + } up_write(&mm->mmap_sem); return retval; } diff -Nru a/ipc/util.c b/ipc/util.c --- a/ipc/util.c Fri Nov 22 13:41:19 2002 +++ b/ipc/util.c Fri Nov 22 13:41:19 2002 @@ -131,7 +131,13 @@ } old = ids->entries; i = ids->size; - + + /* + * before setting the ids->entries to the new array, there must be a + * wmb() to make sure that the memcpyed contents of the new array are + * visible before the new array becomes visible. + */ + wmb(); ids->entries = new; wmb(); ids->size = newsize; diff -Nru a/kernel/Makefile b/kernel/Makefile --- a/kernel/Makefile Fri Nov 22 13:41:18 2002 +++ b/kernel/Makefile Fri Nov 22 13:41:18 2002 @@ -10,7 +10,7 @@ exit.o itimer.o time.o softirq.o resource.o \ sysctl.o capability.o ptrace.o timer.o user.o \ signal.o sys.o kmod.o workqueue.o futex.o platform.o pid.o \ - rcupdate.o intermodule.o + rcupdate.o intermodule.o extable.o obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o obj-$(CONFIG_SMP) += cpu.o diff -Nru a/kernel/capability.c b/kernel/capability.c --- a/kernel/capability.c Fri Nov 22 13:41:18 2002 +++ b/kernel/capability.c Fri Nov 22 13:41:18 2002 @@ -54,15 +54,15 @@ spin_lock(&task_capability_lock); read_lock(&tasklist_lock); - target = find_task_by_pid(pid); - if (!target) { - ret = -ESRCH; - goto out; - } + if (pid && pid != current->pid) { + target = find_task_by_pid(pid); + if (!target) { + ret = -ESRCH; + goto out; + } + } else + target = current; - data.permitted = cap_t(target->cap_permitted); - data.inheritable = cap_t(target->cap_inheritable); - data.effective = cap_t(target->cap_effective); ret = security_ops->capget(target, &data.effective, &data.inheritable, &data.permitted); out: diff -Nru a/kernel/cpufreq.c b/kernel/cpufreq.c --- a/kernel/cpufreq.c Fri Nov 22 13:41:18 2002 +++ b/kernel/cpufreq.c Fri Nov 22 13:41:18 2002 @@ -4,7 +4,7 @@ * Copyright (C) 2001 Russell King * (C) 2002 Dominik Brodowski * - * $Id: cpufreq.c,v 1.45 2002/10/08 14:54:23 db Exp $ + * $Id: cpufreq.c,v 1.50 2002/11/11 15:35:48 db Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -69,8 +69,8 @@ /** * A few values needed by the 2.4.-compatible API */ -static unsigned int cpu_max_freq; -static unsigned int cpu_min_freq; +static unsigned int cpu_max_freq[NR_CPUS]; +static unsigned int cpu_min_freq[NR_CPUS]; static unsigned int cpu_cur_freq[NR_CPUS]; #endif @@ -228,6 +228,10 @@ continue; cpufreq_get_policy(&policy, i); + + if (!policy.max_cpu_freq) + continue; + min_pctg = (policy.min * 100) / policy.max_cpu_freq; max_pctg = (policy.max * 100) / policy.max_cpu_freq; @@ -378,7 +382,7 @@ { if (!cpu_online(cpu) && (cpu != CPUFREQ_ALL_CPUS)) return -EINVAL; - return cpufreq_set(cpu_max_freq, cpu); + return cpufreq_set(cpu_max_freq[cpu], cpu); } EXPORT_SYMBOL_GPL(cpufreq_setmax); @@ -807,13 +811,14 @@ policy->min = cpufreq_driver->policy[cpu].min; policy->max = cpufreq_driver->policy[cpu].max; policy->policy = cpufreq_driver->policy[cpu].policy; - policy->max_cpu_freq = cpufreq_driver->policy[0].max_cpu_freq; + policy->max_cpu_freq = cpufreq_driver->policy[cpu].max_cpu_freq; policy->cpu = cpu; up(&cpufreq_driver_sem); return 0; } +EXPORT_SYMBOL(cpufreq_get_policy); /** @@ -825,6 +830,7 @@ int cpufreq_set_policy(struct cpufreq_policy *policy) { unsigned int i; + int ret; down(&cpufreq_driver_sem); if (!cpufreq_driver || !cpufreq_driver->verify || @@ -834,12 +840,20 @@ return -EINVAL; } - down(&cpufreq_notifier_sem); + if (policy->cpu == CPUFREQ_ALL_CPUS) + policy->max_cpu_freq = cpufreq_driver->policy[0].max_cpu_freq; + else + policy->max_cpu_freq = cpufreq_driver->policy[policy->cpu].max_cpu_freq; - policy->max_cpu_freq = cpufreq_driver->policy[0].max_cpu_freq; /* verify the cpu speed can be set within this limit */ - cpufreq_driver->verify(policy); + ret = cpufreq_driver->verify(policy); + if (ret) { + up(&cpufreq_driver_sem); + return ret; + } + + down(&cpufreq_notifier_sem); /* adjust if neccessary - all reasons */ notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_ADJUST, @@ -851,7 +865,12 @@ /* verify the cpu speed can be set within this limit, which might be different to the first one */ - cpufreq_driver->verify(policy); + ret = cpufreq_driver->verify(policy); + if (ret) { + up(&cpufreq_notifier_sem); + up(&cpufreq_driver_sem); + return ret; + } /* notification of the new policy */ notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_NOTIFY, @@ -879,11 +898,11 @@ cpu_cur_freq[policy->cpu] = policy->max; #endif - cpufreq_driver->setpolicy(policy); + ret = cpufreq_driver->setpolicy(policy); up(&cpufreq_driver_sem); - return 0; + return ret; } EXPORT_SYMBOL(cpufreq_set_policy); @@ -968,6 +987,8 @@ int cpufreq_register(struct cpufreq_driver *driver_data) { unsigned int ret; + unsigned int i; + struct cpufreq_policy policy; if (cpufreq_driver) return -EBUSY; @@ -979,41 +1000,55 @@ down(&cpufreq_driver_sem); cpufreq_driver = driver_data; - if (!default_policy.policy) - default_policy.policy = driver_data->policy[0].policy; - if (!default_policy.min) - default_policy.min = driver_data->policy[0].min; - if (!default_policy.max) - default_policy.max = driver_data->policy[0].max; - default_policy.cpu = CPUFREQ_ALL_CPUS; + /* check for a default policy - if it exists, use it on _all_ CPUs*/ + for (i=0; ipolicy[i].policy = default_policy.policy; + if (default_policy.min) + cpufreq_driver->policy[i].min = default_policy.min; + if (default_policy.max) + cpufreq_driver->policy[i].max = default_policy.max; + } - up(&cpufreq_driver_sem); + /* set default policy on all CPUs. Must be called per-CPU and not + * with CPUFREQ_ALL_CPUs as there might be no common policy for all + * CPUs (UltraSPARC etc.) + */ + for (i=0; ipolicy[i].policy; + policy.min = cpufreq_driver->policy[i].min; + policy.max = cpufreq_driver->policy[i].max; + policy.cpu = i; + up(&cpufreq_driver_sem); + ret = cpufreq_set_policy(&policy); + down(&cpufreq_driver_sem); + if (ret) { + cpufreq_driver = NULL; + up(&cpufreq_driver_sem); + return ret; + } + } - ret = cpufreq_set_policy(&default_policy); + up(&cpufreq_driver_sem); cpufreq_proc_init(); #ifdef CONFIG_CPU_FREQ_24_API - down(&cpufreq_driver_sem); - cpu_min_freq = driver_data->cpu_min_freq; - cpu_max_freq = driver_data->policy[0].max_cpu_freq; + down(&cpufreq_driver_sem); + for (i=0; icpu_cur_freq[i]; - } + cpu_min_freq[i] = driver_data->cpu_min_freq[i]; + cpu_max_freq[i] = driver_data->policy[i].max_cpu_freq; + cpu_cur_freq[i] = driver_data->cpu_cur_freq[i]; } up(&cpufreq_driver_sem); cpufreq_sysctl_init(); #endif - if (ret) { - down(&cpufreq_driver_sem); - cpufreq_driver = NULL; - up(&cpufreq_driver_sem); - } - return ret; + return 0; } EXPORT_SYMBOL_GPL(cpufreq_register); @@ -1061,6 +1096,7 @@ { struct cpufreq_policy policy; unsigned int i; + unsigned int ret = 0; if (in_interrupt()) panic("cpufreq_restore() called from interrupt context!"); @@ -1081,10 +1117,10 @@ policy.cpu = i; up(&cpufreq_driver_sem); - cpufreq_set_policy(&policy); + ret += cpufreq_set_policy(&policy); } - return 0; + return ret; } EXPORT_SYMBOL_GPL(cpufreq_restore); #else diff -Nru a/kernel/exit.c b/kernel/exit.c --- a/kernel/exit.c Fri Nov 22 13:41:23 2002 +++ b/kernel/exit.c Fri Nov 22 13:41:23 2002 @@ -47,9 +47,9 @@ proc_dentry = p->proc_dentry; if (unlikely(proc_dentry != NULL)) { spin_lock(&dcache_lock); - if (!list_empty(&proc_dentry->d_hash)) { + if (!d_unhashed(proc_dentry)) { dget_locked(proc_dentry); - list_del_init(&proc_dentry->d_hash); + __d_drop(proc_dentry); } else proc_dentry = NULL; spin_unlock(&dcache_lock); diff -Nru a/kernel/extable.c b/kernel/extable.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/kernel/extable.c Fri Nov 22 13:41:23 2002 @@ -0,0 +1,51 @@ +/* Rewritten by Rusty Russell, on the backs of many others... + Copyright (C) 2001 Rusty Russell, 2002 Rusty Russell IBM. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include +#include + +#include + +extern const struct exception_table_entry __start___ex_table[]; +extern const struct exception_table_entry __stop___ex_table[]; +extern const struct kernel_symbol __start___ksymtab[]; +extern const struct kernel_symbol __stop___ksymtab[]; + +/* Protects extables and symbol tables */ +spinlock_t modlist_lock = SPIN_LOCK_UNLOCKED; + +/* The exception and symbol tables: start with kernel only. */ +LIST_HEAD(extables); +LIST_HEAD(symbols); + +static struct exception_table kernel_extable; +static struct kernel_symbol_group kernel_symbols; + +void __init extable_init(void) +{ + /* Add kernel symbols to symbol table */ + kernel_symbols.num_syms = (__stop___ksymtab - __start___ksymtab); + kernel_symbols.syms = __start___ksymtab; + list_add(&kernel_symbols.list, &symbols); + + /* Add kernel exception table to exception tables */ + kernel_extable.num_entries = (__stop___ex_table -__start___ex_table); + kernel_extable.entry = __start___ex_table; + list_add(&kernel_extable.list, &extables); +} + + diff -Nru a/kernel/fork.c b/kernel/fork.c --- a/kernel/fork.c Fri Nov 22 13:41:18 2002 +++ b/kernel/fork.c Fri Nov 22 13:41:18 2002 @@ -238,7 +238,6 @@ for (mpnt = current->mm->mmap ; mpnt ; mpnt = mpnt->vm_next) { struct file *file; - retval = -ENOMEM; if(mpnt->vm_flags & VM_DONTCOPY) continue; if (mpnt->vm_flags & VM_ACCOUNT) { @@ -283,7 +282,7 @@ tmp->vm_ops->open(tmp); if (retval) - goto fail_nomem; + goto fail; } retval = 0; build_mmap_rb(mm); @@ -293,6 +292,8 @@ up_write(&oldmm->mmap_sem); return retval; fail_nomem: + retval = -ENOMEM; + fail: vm_unacct_memory(charge); goto out; } @@ -407,16 +408,16 @@ tsk->vfork_done = NULL; complete(vfork_done); } - if (tsk->user_tid) { - int * user_tid = tsk->user_tid; - tsk->user_tid = NULL; + if (tsk->clear_child_tid) { + int * tidptr = tsk->clear_child_tid; + tsk->clear_child_tid = NULL; /* * We dont check the error code - if userspace has * not set up a proper pointer then tough luck. */ - put_user(0, user_tid); - sys_futex((unsigned long)user_tid, FUTEX_WAKE, 1, NULL); + put_user(0, tidptr); + sys_futex((unsigned long)tidptr, FUTEX_WAKE, 1, NULL); } } @@ -679,9 +680,9 @@ p->flags = new_flags; } -asmlinkage int sys_set_tid_address(int *user_tid) +asmlinkage int sys_set_tid_address(int *tidptr) { - current->user_tid = user_tid; + current->clear_child_tid = tidptr; return current->pid; } @@ -698,7 +699,8 @@ unsigned long stack_start, struct pt_regs *regs, unsigned long stack_size, - int *user_tid) + int *parent_tidptr, + int *child_tidptr) { int retval; struct task_struct *p = NULL; @@ -765,6 +767,11 @@ if (p->pid == -1) goto bad_fork_cleanup; } + retval = -EFAULT; + if (clone_flags & CLONE_PARENT_SETTID) + if (put_user(p->pid, parent_tidptr)) + goto bad_fork_cleanup; + p->proc_dentry = NULL; INIT_LIST_HEAD(&p->run_list); @@ -822,19 +829,14 @@ retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs); if (retval) goto bad_fork_cleanup_namespace; - /* - * Notify the child of the TID? - */ - retval = -EFAULT; - if (clone_flags & CLONE_SETTID) - if (put_user(p->pid, user_tid)) - goto bad_fork_cleanup_namespace; + if (clone_flags & CLONE_CHILD_SETTID) + p->set_child_tid = child_tidptr; /* - * Does the userspace VM want the TID cleared on mm_release()? + * Clear TID on mm_release()? */ - if (clone_flags & CLONE_CLEARTID) - p->user_tid = user_tid; + if (clone_flags & CLONE_CHILD_CLEARTID) + p->clear_child_tid = child_tidptr; /* * Syscall tracing should be turned off in the child regardless @@ -1003,7 +1005,8 @@ unsigned long stack_start, struct pt_regs *regs, unsigned long stack_size, - int *user_tid) + int *parent_tidptr, + int *child_tidptr) { struct task_struct *p; int trace = 0; @@ -1014,7 +1017,7 @@ clone_flags |= CLONE_PTRACE; } - p = copy_process(clone_flags, stack_start, regs, stack_size, user_tid); + p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr); if (!IS_ERR(p)) { struct completion vfork; diff -Nru a/kernel/futex.c b/kernel/futex.c --- a/kernel/futex.c Fri Nov 22 13:41:18 2002 +++ b/kernel/futex.c Fri Nov 22 13:41:18 2002 @@ -315,6 +315,23 @@ return ret; } +static inline int futex_wait_utime(unsigned long uaddr, + int offset, + int val, + struct timespec* utime) +{ + unsigned long time = MAX_SCHEDULE_TIMEOUT; + + if (utime) { + struct timespec t; + if (copy_from_user(&t, utime, sizeof(t)) != 0) + return -EFAULT; + time = timespec_to_jiffies(&t) + 1; + } + + return futex_wait(uaddr, offset, val, time); +} + static int futex_close(struct inode *inode, struct file *filp) { struct futex_q *q = filp->private_data; @@ -422,17 +439,9 @@ asmlinkage int sys_futex(unsigned long uaddr, int op, int val, struct timespec *utime) { - unsigned long time = MAX_SCHEDULE_TIMEOUT; unsigned long pos_in_page; int ret; - if (utime) { - struct timespec t; - if (copy_from_user(&t, utime, sizeof(t)) != 0) - return -EFAULT; - time = timespec_to_jiffies(&t) + 1; - } - pos_in_page = uaddr % PAGE_SIZE; /* Must be "naturally" aligned */ @@ -441,7 +450,7 @@ switch (op) { case FUTEX_WAIT: - ret = futex_wait(uaddr, pos_in_page, val, time); + ret = futex_wait_utime(uaddr, pos_in_page, val, utime); break; case FUTEX_WAKE: ret = futex_wake(uaddr, pos_in_page, val); diff -Nru a/kernel/kallsyms.c b/kernel/kallsyms.c --- a/kernel/kallsyms.c Fri Nov 22 13:41:23 2002 +++ b/kernel/kallsyms.c Fri Nov 22 13:41:23 2002 @@ -1,233 +1,102 @@ /* - * kksymoops.c: in-kernel printing of symbolic oopses and stack traces. + * kallsyms.c: in-kernel printing of symbolic oopses and stack traces. * - * Copyright 2000 Keith Owens April 2000 - * Copyright 2002 Arjan van de Ven - * - This code uses the list of all kernel and module symbols to :- - - * Find any non-stack symbol in a kernel or module. Symbols do - not have to be exported for debugging. - - * Convert an address to the module (or kernel) that owns it, the - section it is in and the nearest symbol. This finds all non-stack - symbols, not just exported ones. - + * Rewritten and vastly simplified by Rusty Russell for in-kernel + * module loader: + * Copyright 2002 Rusty Russell IBM Corporation */ - -#include -#include #include +#include -/* A symbol can appear in more than one module. A token is used to - * restart the scan at the next module, set the token to 0 for the - * first scan of each symbol. - */ +static char kallsyms_dummy; -int kallsyms_symbol_to_address( - const char *name, /* Name to lookup */ - unsigned long *token, /* Which module to start at */ - const char **mod_name, /* Set to module name */ - unsigned long *mod_start, /* Set to start address of module */ - unsigned long *mod_end, /* Set to end address of module */ - const char **sec_name, /* Set to section name */ - unsigned long *sec_start, /* Set to start address of section */ - unsigned long *sec_end, /* Set to end address of section */ - const char **sym_name, /* Set to full symbol name */ - unsigned long *sym_start, /* Set to start address of symbol */ - unsigned long *sym_end /* Set to end address of symbol */ - ) +/* These will be re-linked against their real values during the second link stage */ +extern unsigned long kallsyms_addresses[1] __attribute__((weak, alias("kallsyms_dummy"))); +extern unsigned long kallsyms_num_syms __attribute__((weak, alias("kallsyms_dummy"))); +extern char kallsyms_names[1] __attribute__((weak, alias("kallsyms_dummy"))); + +/* Defined by the linker script. */ +extern char _stext[], _etext[]; + +/* Lookup an address. modname is set to NULL if it's in the kernel. */ +const char *kallsyms_lookup(unsigned long addr, + unsigned long *symbolsize, + unsigned long *offset, + char **modname) { - const struct kallsyms_header *ka_hdr = NULL; /* stupid gcc */ - const struct kallsyms_section *ka_sec; - const struct kallsyms_symbol *ka_sym = NULL; - const char *ka_str = NULL; - const struct module *m; - int i = 0, l; - const char *p, *pt_R; - char *p2; - - /* Restart? */ - m = module_list; - if (token && *token) { - for (; m; m = m->next) - if ((unsigned long)m == *token) - break; - if (m) - m = m->next; - } + unsigned long i, best = 0; - for (; m; m = m->next) { - if (!mod_member_present(m, kallsyms_start) || - !mod_member_present(m, kallsyms_end) || - m->kallsyms_start >= m->kallsyms_end) - continue; - ka_hdr = (struct kallsyms_header *)m->kallsyms_start; - ka_sym = (struct kallsyms_symbol *) - ((char *)(ka_hdr) + ka_hdr->symbol_off); - ka_str = - ((char *)(ka_hdr) + ka_hdr->string_off); - for (i = 0; i < ka_hdr->symbols; ++i, kallsyms_next_sym(ka_hdr, ka_sym)) { - p = ka_str + ka_sym->name_off; - if (strcmp(p, name) == 0) - break; - /* Unversioned requests match versioned names */ - if (!(pt_R = strstr(p, "_R"))) - continue; - l = strlen(pt_R); - if (l < 10) - continue; /* Not _R.*xxxxxxxx */ - (void)simple_strtoul(pt_R+l-8, &p2, 16); - if (*p2) - continue; /* Not _R.*xxxxxxxx */ - if (strncmp(p, name, pt_R-p) == 0) - break; /* Match with version */ + /* This kernel should never had been booted. */ + if ((void *)kallsyms_addresses == &kallsyms_dummy) + BUG(); + + if (addr >= (unsigned long)_stext && addr <= (unsigned long)_etext) { + unsigned long symbol_end; + char *name = kallsyms_names; + + /* They're sorted, we could be clever here, but who cares? */ + for (i = 0; i < kallsyms_num_syms; i++) { + if (kallsyms_addresses[i] > kallsyms_addresses[best] && + kallsyms_addresses[i] <= addr) + best = i; } - if (i < ka_hdr->symbols) - break; - } - if (token) - *token = (unsigned long)m; - if (!m) - return(0); /* not found */ - - ka_sec = (const struct kallsyms_section *) - ((char *)ka_hdr + ka_hdr->section_off + ka_sym->section_off); - *mod_name = m->name; - *mod_start = ka_hdr->start; - *mod_end = ka_hdr->end; - *sec_name = ka_sec->name_off + ka_str; - *sec_start = ka_sec->start; - *sec_end = ka_sec->start + ka_sec->size; - *sym_name = ka_sym->name_off + ka_str; - *sym_start = ka_sym->symbol_addr; - if (i < ka_hdr->symbols-1) { - const struct kallsyms_symbol *ka_symn = ka_sym; - kallsyms_next_sym(ka_hdr, ka_symn); - *sym_end = ka_symn->symbol_addr; - } - else - *sym_end = *sec_end; - return(1); -} - -int kallsyms_address_to_symbol( - unsigned long address, /* Address to lookup */ - const char **mod_name, /* Set to module name */ - unsigned long *mod_start, /* Set to start address of module */ - unsigned long *mod_end, /* Set to end address of module */ - const char **sec_name, /* Set to section name */ - unsigned long *sec_start, /* Set to start address of section */ - unsigned long *sec_end, /* Set to end address of section */ - const char **sym_name, /* Set to full symbol name */ - unsigned long *sym_start, /* Set to start address of symbol */ - unsigned long *sym_end /* Set to end address of symbol */ - ) -{ - const struct kallsyms_header *ka_hdr = NULL; /* stupid gcc */ - const struct kallsyms_section *ka_sec = NULL; - const struct kallsyms_symbol *ka_sym; - const char *ka_str; - const struct module *m; - int i; - unsigned long end; - - for (m = module_list; m; m = m->next) { - - if (!mod_member_present(m, kallsyms_start) || - !mod_member_present(m, kallsyms_end) || - m->kallsyms_start >= m->kallsyms_end) - continue; - ka_hdr = (struct kallsyms_header *)m->kallsyms_start; - ka_sec = (const struct kallsyms_section *) - ((char *)ka_hdr + ka_hdr->section_off); - /* Is the address in any section in this module? */ - for (i = 0; i < ka_hdr->sections; ++i, kallsyms_next_sec(ka_hdr, ka_sec)) { - if (ka_sec->start <= address && - (ka_sec->start + ka_sec->size) > address) + /* Grab name */ + for (i = 0; i < best; i++) + name += strlen(name)+1; + + /* Base symbol size on next symbol, but beware aliases. */ + symbol_end = (unsigned long)_etext; + for (i = best+1; i < kallsyms_num_syms; i++) { + if (kallsyms_addresses[i] != kallsyms_addresses[best]){ + symbol_end = kallsyms_addresses[i]; break; + } } - if (i < ka_hdr->sections) - break; /* Found a matching section */ - } - - if (!m) - return(0); /* not found */ - ka_sym = (struct kallsyms_symbol *) - ((char *)(ka_hdr) + ka_hdr->symbol_off); - ka_str = - ((char *)(ka_hdr) + ka_hdr->string_off); - *mod_name = m->name; - *mod_start = ka_hdr->start; - *mod_end = ka_hdr->end; - *sec_name = ka_sec->name_off + ka_str; - *sec_start = ka_sec->start; - *sec_end = ka_sec->start + ka_sec->size; - *sym_name = *sec_name; /* In case we find no matching symbol */ - *sym_start = *sec_start; - *sym_end = *sec_end; - - for (i = 0; i < ka_hdr->symbols; ++i, kallsyms_next_sym(ka_hdr, ka_sym)) { - if (ka_sym->symbol_addr > address) - continue; - if (i < ka_hdr->symbols-1) { - const struct kallsyms_symbol *ka_symn = ka_sym; - kallsyms_next_sym(ka_hdr, ka_symn); - end = ka_symn->symbol_addr; - } - else - end = *sec_end; - if (end <= address) - continue; - if ((char *)ka_hdr + ka_hdr->section_off + ka_sym->section_off - != (char *)ka_sec) - continue; /* wrong section */ - *sym_name = ka_str + ka_sym->name_off; - *sym_start = ka_sym->symbol_addr; - *sym_end = end; - break; + *symbolsize = symbol_end - kallsyms_addresses[best]; + *modname = NULL; + *offset = addr - kallsyms_addresses[best]; + return name; } - return(1); + + return module_address_lookup(addr, symbolsize, offset, modname); } -/* List all sections in all modules. The callback routine is invoked with - * token, module name, section name, section start, section end, section flags. - */ -int kallsyms_sections(void *token, - int (*callback)(void *, const char *, const char *, ElfW(Addr), ElfW(Addr), ElfW(Word))) +/* Replace "%s" in format with address, or returns -errno. */ +void __print_symbol(const char *fmt, unsigned long address) { - const struct kallsyms_header *ka_hdr = NULL; /* stupid gcc */ - const struct kallsyms_section *ka_sec = NULL; - const char *ka_str; - const struct module *m; - int i; - - for (m = module_list; m; m = m->next) { - if (!mod_member_present(m, kallsyms_start) || - !mod_member_present(m, kallsyms_end) || - m->kallsyms_start >= m->kallsyms_end) - continue; - ka_hdr = (struct kallsyms_header *)m->kallsyms_start; - ka_sec = (const struct kallsyms_section *) ((char *)ka_hdr + ka_hdr->section_off); - ka_str = ((char *)(ka_hdr) + ka_hdr->string_off); - for (i = 0; i < ka_hdr->sections; ++i, kallsyms_next_sec(ka_hdr, ka_sec)) { - if (callback( - token, - *(m->name) ? m->name : "kernel", - ka_sec->name_off + ka_str, - ka_sec->start, - ka_sec->start + ka_sec->size, - ka_sec->flags)) - return(0); - } + char *modname; + const char *name; + unsigned long offset, size; + + name = kallsyms_lookup(address, &size, &offset, &modname); + + if (!name) { + char addrstr[sizeof("0x%lx") + (BITS_PER_LONG*3/10)]; + + sprintf(addrstr, "0x%lx", address); + printk(fmt, addrstr); + return; + } + + if (modname) { + /* This is pretty small. */ + char buffer[sizeof("%s+%#lx/%#lx [%s]") + + strlen(name) + 2*(BITS_PER_LONG*3/10) + + strlen(modname)]; + + sprintf(buffer, "%s+%#lx/%#lx [%s]", + name, offset, size, modname); + printk(fmt, buffer); + } else { + char buffer[sizeof("%s+%#lx/%#lx") + + strlen(name) + 2*(BITS_PER_LONG*3/10)]; + + sprintf(buffer, "%s+%#lx/%#lx", name, offset, size); + printk(fmt, buffer); } - return(1); } -/* Allocate the __kallsyms section, so it's already present in - * the temporary vmlinux that kallsyms is run on, so the first - * run will pick up the section info already. */ - -__asm__(".section __kallsyms,\"a\"\n.previous"); +EXPORT_SYMBOL(kallsyms_lookup); +EXPORT_SYMBOL(__print_symbol); diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c --- a/kernel/ksyms.c Fri Nov 22 13:41:17 2002 +++ b/kernel/ksyms.c Fri Nov 22 13:41:17 2002 @@ -287,7 +287,7 @@ EXPORT_SYMBOL(page_symlink_inode_operations); EXPORT_SYMBOL(page_symlink); EXPORT_SYMBOL(vfs_readdir); -EXPORT_SYMBOL(__get_lease); +EXPORT_SYMBOL(__break_lease); EXPORT_SYMBOL(lease_get_mtime); EXPORT_SYMBOL(lock_may_read); EXPORT_SYMBOL(lock_may_write); diff -Nru a/kernel/module.c b/kernel/module.c --- a/kernel/module.c Fri Nov 22 13:41:22 2002 +++ b/kernel/module.c Fri Nov 22 13:41:22 2002 @@ -37,21 +37,6 @@ #define DEBUGP(fmt , a...) #endif -extern const struct exception_table_entry __start___ex_table[]; -extern const struct exception_table_entry __stop___ex_table[]; -extern const struct kernel_symbol __start___ksymtab[]; -extern const struct kernel_symbol __stop___ksymtab[]; - -/* Protects extables and symbol tables */ -spinlock_t modlist_lock = SPIN_LOCK_UNLOCKED; - -/* The exception and symbol tables: start with kernel only. */ -LIST_HEAD(extables); -static LIST_HEAD(symbols); - -static struct exception_table kernel_extable; -static struct kernel_symbol_group kernel_symbols; - /* List of modules, protected by module_mutex */ static DECLARE_MUTEX(module_mutex); LIST_HEAD(modules); /* FIXME: Accessed w/o lock on oops by some archs */ @@ -607,14 +592,17 @@ { void *dest; unsigned long *use; + unsigned long max; /* Only copy to init section if there is one */ if (strstr(name, ".init") && mod->module_init) { dest = mod->module_init; use = &used->init_size; + max = mod->init_size; } else { dest = mod->module_core; use = &used->core_size; + max = mod->core_size; } /* Align up */ @@ -622,6 +610,9 @@ dest += *use; *use += sechdr->sh_size; + if (*use > max) + return ERR_PTR(-ENOEXEC); + /* May not actually be in the file (eg. bss). */ if (sechdr->sh_type != SHT_NOBITS) memcpy(dest, base + sechdr->sh_offset, sechdr->sh_size); @@ -788,9 +779,10 @@ /* Get the total allocation size of the init and non-init sections */ static struct sizes get_sizes(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, - const char *secstrings) + const char *secstrings, + unsigned long common_length) { - struct sizes ret = { 0, 0 }; + struct sizes ret = { 0, common_length }; unsigned i; /* Everything marked ALLOC (this includes the exported @@ -898,6 +890,11 @@ DEBUGP("Exception table found in section %u\n", i); exindex = i; } +#ifdef CONFIG_KALLSYMS + /* symbol and string tables for decoding later. */ + if (sechdrs[i].sh_type == SHT_SYMTAB || i == hdr->e_shstrndx) + sechdrs[i].sh_flags |= SHF_ALLOC; +#endif #ifndef CONFIG_MODULE_UNLOAD /* Don't load .exit sections */ if (strstr(secstrings+sechdrs[i].sh_name, ".exit")) @@ -943,10 +940,9 @@ mod->live = 0; module_unload_init(mod); - /* How much space will we need? (Common area in core) */ - sizes = get_sizes(hdr, sechdrs, secstrings); + /* How much space will we need? (Common area in first) */ common_length = read_commons(hdr, &sechdrs[symindex]); - sizes.core_size += common_length; + sizes = get_sizes(hdr, sechdrs, secstrings, common_length); /* Set these up, and allow archs to manipulate them. */ mod->core_size = sizes.core_size; @@ -973,7 +969,7 @@ mod->module_core = ptr; ptr = module_alloc(mod->init_size); - if (!ptr) { + if (!ptr && mod->init_size) { err = -ENOMEM; goto free_core; } @@ -1026,6 +1022,11 @@ goto cleanup; } +#ifdef CONFIG_KALLSYMS + mod->symtab = (void *)sechdrs[symindex].sh_offset; + mod->num_syms = sechdrs[symindex].sh_size / sizeof(Elf_Sym); + mod->strtab = (void *)sechdrs[strindex].sh_offset; +#endif err = module_finalize(hdr, sechdrs, mod); if (err < 0) goto cleanup; @@ -1129,7 +1130,7 @@ /* Now it's a first class citizen! */ spin_lock_irq(&modlist_lock); - list_add(&mod->symbols.list, &kernel_symbols.list); + list_add_tail(&mod->symbols.list, &symbols); spin_unlock_irq(&modlist_lock); list_add(&mod->list, &modules); @@ -1141,9 +1142,82 @@ return 0; } -/* Called by the /proc file system to return a current list of - modules. Al Viro came up with this interface as an "improvement". - God save us from any more such interface improvements. */ +#ifdef CONFIG_KALLSYMS +static inline int inside_init(struct module *mod, unsigned long addr) +{ + if (mod->module_init + && (unsigned long)mod->module_init <= addr + && (unsigned long)mod->module_init + mod->init_size > addr) + return 1; + return 0; +} + +static inline int inside_core(struct module *mod, unsigned long addr) +{ + if ((unsigned long)mod->module_core <= addr + && (unsigned long)mod->module_core + mod->core_size > addr) + return 1; + return 0; +} + +static const char *get_ksymbol(struct module *mod, + unsigned long addr, + unsigned long *size, + unsigned long *offset) +{ + unsigned int i, next = 0, best = 0; + + /* Scan for closest preceeding symbol, and next symbol. (ELF + starts real symbols at 1). */ + for (i = 1; i < mod->num_syms; i++) { + if (mod->symtab[i].st_shndx == SHN_UNDEF) + continue; + + if (mod->symtab[i].st_value <= addr + && mod->symtab[i].st_value > mod->symtab[best].st_value) + best = i; + if (mod->symtab[i].st_value > addr + && mod->symtab[i].st_value < mod->symtab[next].st_value) + next = i; + } + + if (!best) + return NULL; + + if (!next) { + /* Last symbol? It ends at the end of the module then. */ + if (inside_core(mod, addr)) + *size = mod->module_core+mod->core_size - (void*)addr; + else + *size = mod->module_init+mod->init_size - (void*)addr; + } else + *size = mod->symtab[next].st_value - addr; + + *offset = addr - mod->symtab[best].st_value; + return mod->strtab + mod->symtab[best].st_name; +} + +/* For kallsyms to ask for address resolution. NULL means not found. + We don't lock, as this is used for oops resolution and races are a + lesser concern. */ +const char *module_address_lookup(unsigned long addr, + unsigned long *size, + unsigned long *offset, + char **modname) +{ + struct module *mod; + + list_for_each_entry(mod, &modules, list) { + if (inside_core(mod, addr) || inside_init(mod, addr)) { + *modname = mod->name; + return get_ksymbol(mod, addr, size, offset); + } + } + return NULL; +} +#endif /* CONFIG_KALLSYMS */ + +/* Called by the /proc file system to return a list of modules. */ static void *m_start(struct seq_file *m, loff_t *pos) { struct list_head *i; @@ -1187,19 +1261,6 @@ .stop = m_stop, .show = m_show }; - -void __init extable_init(void) -{ - /* Add kernel symbols to symbol table */ - kernel_symbols.num_syms = (__stop___ksymtab - __start___ksymtab); - kernel_symbols.syms = __start___ksymtab; - list_add(&kernel_symbols.list, &symbols); - - /* Add kernel exception table to exception tables */ - kernel_extable.num_entries = (__stop___ex_table -__start___ex_table); - kernel_extable.entry = __start___ex_table; - list_add(&kernel_extable.list, &extables); -} /* Obsolete lvalue for broken code which asks about usage */ int module_dummy_usage = 1; diff -Nru a/kernel/sched.c b/kernel/sched.c --- a/kernel/sched.c Fri Nov 22 13:41:22 2002 +++ b/kernel/sched.c Fri Nov 22 13:41:22 2002 @@ -503,12 +503,12 @@ * schedule_tail - first thing a freshly forked thread must call. * @prev: the thread we just switched away from. */ -#if CONFIG_SMP || CONFIG_PREEMPT asmlinkage void schedule_tail(task_t *prev) { finish_arch_switch(this_rq(), prev); + if (current->set_child_tid) + put_user(current->pid, current->set_child_tid); } -#endif /* * context_switch - switch to the new MM and the new @@ -856,7 +856,7 @@ #endif -DEFINE_PER_CPU(struct kernel_stat, kstat); +DEFINE_PER_CPU(struct kernel_stat, kstat) = { { 0 } }; /* * We place interactive tasks back into the active array, if possible. @@ -1745,13 +1745,15 @@ atomic_dec(&rq->nr_iowait); } -void io_schedule_timeout(long timeout) +long io_schedule_timeout(long timeout) { struct runqueue *rq = this_rq(); + long ret; atomic_inc(&rq->nr_iowait); - schedule_timeout(timeout); + ret = schedule_timeout(timeout); atomic_dec(&rq->nr_iowait); + return ret; } /** @@ -1835,6 +1837,24 @@ out_unlock: read_unlock(&tasklist_lock); return retval; +} + +static inline struct task_struct *eldest_child(struct task_struct *p) +{ + if (list_empty(&p->children)) return NULL; + return list_entry(p->children.next,struct task_struct,sibling); +} + +static inline struct task_struct *older_sibling(struct task_struct *p) +{ + if (p->sibling.prev==&p->parent->children) return NULL; + return list_entry(p->sibling.prev,struct task_struct,sibling); +} + +static inline struct task_struct *younger_sibling(struct task_struct *p) +{ + if (p->sibling.next==&p->parent->children) return NULL; + return list_entry(p->sibling.next,struct task_struct,sibling); } static void show_task(task_t * p) diff -Nru a/kernel/signal.c b/kernel/signal.c --- a/kernel/signal.c Fri Nov 22 13:41:19 2002 +++ b/kernel/signal.c Fri Nov 22 13:41:19 2002 @@ -160,6 +160,36 @@ static int __send_sig_info(int sig, struct siginfo *info, struct task_struct *p); +/* + * Re-calculate pending state from the set of locally pending + * signals, globally pending signals, and blocked signals. + */ +static inline int has_pending_signals(sigset_t *signal, sigset_t *blocked) +{ + unsigned long ready; + long i; + + switch (_NSIG_WORDS) { + default: + for (i = _NSIG_WORDS, ready = 0; --i >= 0 ;) + ready |= signal->sig[i] &~ blocked->sig[i]; + break; + + case 4: ready = signal->sig[3] &~ blocked->sig[3]; + ready |= signal->sig[2] &~ blocked->sig[2]; + ready |= signal->sig[1] &~ blocked->sig[1]; + ready |= signal->sig[0] &~ blocked->sig[0]; + break; + + case 2: ready = signal->sig[1] &~ blocked->sig[1]; + ready |= signal->sig[0] &~ blocked->sig[0]; + break; + + case 1: ready = signal->sig[0] &~ blocked->sig[0]; + } + return ready != 0; +} + #define PENDING(p,b) has_pending_signals(&(p)->signal, (b)) void recalc_sigpending_tsk(struct task_struct *t) diff -Nru a/lib/kobject.c b/lib/kobject.c --- a/lib/kobject.c Fri Nov 22 13:41:23 2002 +++ b/lib/kobject.c Fri Nov 22 13:41:23 2002 @@ -2,15 +2,17 @@ * kobject.c - library routines for handling generic kernel objects */ -#define DEBUG 0 +#undef DEBUG #include #include #include #include +static spinlock_t kobj_lock = SPIN_LOCK_UNLOCKED; + /** - * kobject_populate_dir - populate directory with attributes. + * populate_dir - populate directory with attributes. * @kobj: object we're working on. * * Most subsystems have a set of default attributes that @@ -21,7 +23,7 @@ * */ -static int kobject_populate_dir(struct kobject * kobj) +static int populate_dir(struct kobject * kobj) { struct subsystem * s = kobj->subsys; struct attribute * attr; @@ -37,6 +39,20 @@ return error; } +static int create_dir(struct kobject * kobj) +{ + int error = 0; + if (strlen(kobj->name)) { + error = sysfs_create_dir(kobj); + if (!error) { + if ((error = populate_dir(kobj))) + sysfs_remove_dir(kobj); + } + } + return error; +} + + /** * kobject_init - initialize object. * @kobj: object in question. @@ -46,70 +62,88 @@ { atomic_set(&kobj->refcount,1); INIT_LIST_HEAD(&kobj->entry); + kobj->subsys = subsys_get(kobj->subsys); } /** - * kobject_register - register an object. - * @kobj: object in question. - * - * For now, fill in the replicated fields in the object's - * directory entry, and create a dir in sysfs. - * This stuff should go away in the future, as we move - * more implicit things to sysfs. + * kobject_add - add an object to the hierarchy. + * @kobj: object. */ -int kobject_register(struct kobject * kobj) +int kobject_add(struct kobject * kobj) { int error = 0; - struct subsystem * s = subsys_get(kobj->subsys); + struct subsystem * s = kobj->subsys; struct kobject * parent = kobject_get(kobj->parent); - pr_debug("kobject %s: registering\n",kobj->name); - if (parent) - pr_debug(" parent is %s\n",parent->name); + if (!(kobj = kobject_get(kobj))) + return -ENOENT; + pr_debug("kobject %s: registering. parent: %s, subsys: %s\n", + kobj->name, parent ? parent->name : "", + kobj->subsys ? kobj->subsys->kobj.name : "" ); + if (s) { down_write(&s->rwsem); if (parent) list_add_tail(&kobj->entry,&parent->entry); else { list_add_tail(&kobj->entry,&s->list); - kobj->parent = &s->kobj; + kobj->parent = kobject_get(&s->kobj); } up_write(&s->rwsem); } - if (strlen(kobj->name)) { - error = sysfs_create_dir(kobj); - if (!error) { - error = kobject_populate_dir(kobj); - if (error) - sysfs_remove_dir(kobj); - } - } + error = create_dir(kobj); + if (error && kobj->parent) + kobject_put(kobj->parent); return error; } + /** - * kobject_unregister - unlink an object. - * @kobj: object going away. - * - * The device has been told to be removed, but may - * not necessarily be disappearing from the kernel. - * So, we remove the directory and decrement the refcount - * that we set with kobject_register(). - * - * Eventually (maybe now), the refcount will hit 0, and - * put_device() will clean the device up. + * kobject_register - initialize and add an object. + * @kobj: object in question. */ -void kobject_unregister(struct kobject * kobj) +int kobject_register(struct kobject * kobj) +{ + int error = 0; + if (kobj) { + kobject_init(kobj); + error = kobject_add(kobj); + if (error) + kobject_cleanup(kobj); + } else + error = -EINVAL; + return error; +} + +/** + * kobject_del - unlink kobject from hierarchy. + * @kobj: object. + */ + +void kobject_del(struct kobject * kobj) { - pr_debug("kobject %s: unregistering\n",kobj->name); sysfs_remove_dir(kobj); if (kobj->subsys) { down_write(&kobj->subsys->rwsem); list_del_init(&kobj->entry); up_write(&kobj->subsys->rwsem); } + if (kobj->parent) + kobject_put(kobj->parent); + kobject_put(kobj); +} + +/** + * kobject_unregister - remove object from hierarchy and decrement refcount. + * @kobj: object going away. + */ + +void kobject_unregister(struct kobject * kobj) +{ + pr_debug("kobject %s: unregistering\n",kobj->name); + kobject_del(kobj); kobject_put(kobj); } @@ -121,45 +155,48 @@ struct kobject * kobject_get(struct kobject * kobj) { struct kobject * ret = kobj; + spin_lock(&kobj_lock); if (kobj && atomic_read(&kobj->refcount) > 0) atomic_inc(&kobj->refcount); else ret = NULL; + spin_unlock(&kobj_lock); return ret; } /** - * kobject_put - decrement refcount for object. + * kobject_cleanup - free kobject resources. * @kobj: object. - * - * Decrement the refcount, and check if 0. If it is, then - * we're gonna need to clean it up, and decrement the refcount - * of its parent. - * - * @kobj->parent could point to its subsystem, which we also - * want to decrement the reference count for. We always dec - * the refcount for the parent, but only do so for the subsystem - * if it points to a different place than the parent. */ -void kobject_put(struct kobject * kobj) +void kobject_cleanup(struct kobject * kobj) { - struct kobject * parent = kobj->parent; struct subsystem * s = kobj->subsys; - if (!atomic_dec_and_test(&kobj->refcount)) - return; - pr_debug("kobject %s: cleaning up\n",kobj->name); if (s) { + down_write(&s->rwsem); + list_del_init(&kobj->entry); if (s->release) s->release(kobj); - if (&s->kobj != parent) - subsys_put(s); - } + up_write(&s->rwsem); + subsys_put(s); + } +} + +/** + * kobject_put - decrement refcount for object. + * @kobj: object. + * + * Decrement the refcount, and if 0, call kobject_cleanup(). + */ - if (parent) - kobject_put(parent); +void kobject_put(struct kobject * kobj) +{ + if (!atomic_dec_and_lock(&kobj->refcount, &kobj_lock)) + return; + spin_unlock(&kobj_lock); + kobject_cleanup(kobj); } @@ -180,9 +217,8 @@ subsystem_init(s); if (s->parent) s->kobj.parent = &s->parent->kobj; - pr_debug("subsystem %s: registering\n",s->kobj.name); - if (s->parent) - pr_debug(" parent is %s\n",s->parent->kobj.name); + pr_debug("subsystem %s: registering, parent: %s\n", + s->kobj.name,s->parent ? s->parent->kobj.name : ""); return kobject_register(&s->kobj); } diff -Nru a/lib/radix-tree.c b/lib/radix-tree.c --- a/lib/radix-tree.c Fri Nov 22 13:41:18 2002 +++ b/lib/radix-tree.c Fri Nov 22 13:41:18 2002 @@ -334,6 +334,9 @@ radix_tree_node_free(pathp[1].node); } + if (root->rnode == NULL) + root->height = 0; /* Empty tree, we can reset the height */ + return 0; } EXPORT_SYMBOL(radix_tree_delete); diff -Nru a/mm/page-writeback.c b/mm/page-writeback.c --- a/mm/page-writeback.c Fri Nov 22 13:41:21 2002 +++ b/mm/page-writeback.c Fri Nov 22 13:41:21 2002 @@ -166,7 +166,6 @@ if (!writeback_in_progress(bdi) && ps.nr_dirty > background_thresh) pdflush_operation(background_writeout, 0); } -EXPORT_SYMBOL_GPL(balance_dirty_pages); /** * balance_dirty_pages_ratelimited - balance dirty memory state @@ -200,6 +199,7 @@ } put_cpu(); } +EXPORT_SYMBOL_GPL(balance_dirty_pages_ratelimited); /* * writeback at least _min_pages, and keep writing until the amount of dirty @@ -389,71 +389,6 @@ return 0; } module_init(page_writeback_init); - -/* - * A library function, which implements the vm_writeback a_op. It's fairly - * lame at this time. The idea is: the VM wants to liberate this page, - * so we pass the page to the address_space and give the fs the opportunity - * to write out lots of pages around this one. It allows extent-based - * filesytems to do intelligent things. It lets delayed-allocate filesystems - * perform better file layout. It lets the address_space opportunistically - * write back disk-contiguous pages which are in other zones. - * - * FIXME: the VM wants to start I/O against *this* page. Because its zone - * is under pressure. But this function may start writeout against a - * totally different set of pages. Unlikely to be a huge problem, but if it - * is, we could just writepage the page if it is still (PageDirty && - * !PageWriteback) (See below). - * - * Another option is to just reposition page->mapping->dirty_pages so we - * *know* that the page will be written. That will work fine, but seems - * unpleasant. (If the page is not for-sure on ->dirty_pages we're dead). - * Plus it assumes that the address_space is performing writeback in - * ->dirty_pages order. - * - * So. The proper fix is to leave the page locked-and-dirty and to pass - * it all the way down. - */ -int generic_vm_writeback(struct page *page, struct writeback_control *wbc) -{ - struct inode *inode = page->mapping->host; - - /* - * We don't own this inode, and we don't want the address_space - * vanishing while writeback is walking its pages. - */ - inode = igrab(inode); - unlock_page(page); - - if (inode) { - do_writepages(inode->i_mapping, wbc); - - /* - * This iput() will internally call ext2_discard_prealloc(), - * which is rather bogus. But there is no other way of - * dropping our ref to the inode. However, there's no harm - * in dropping the prealloc, because there probably isn't any. - * Just a waste of cycles. - */ - iput(inode); -#if 0 - if (!PageWriteback(page) && PageDirty(page)) { - lock_page(page); - if (!PageWriteback(page)&&test_clear_page_dirty(page)) { - int ret; - - ret = page->mapping->a_ops->writepage(page); - if (ret == -EAGAIN) - __set_page_dirty_nobuffers(page); - } else { - unlock_page(page); - } - } -#endif - } - return 0; -} -EXPORT_SYMBOL(generic_vm_writeback); int do_writepages(struct address_space *mapping, struct writeback_control *wbc) { diff -Nru a/mm/page_alloc.c b/mm/page_alloc.c --- a/mm/page_alloc.c Fri Nov 22 13:41:17 2002 +++ b/mm/page_alloc.c Fri Nov 22 13:41:17 2002 @@ -72,6 +72,17 @@ printk("flags:0x%08lx mapping:%p mapped:%d count:%d\n", page->flags, page->mapping, page_mapped(page), page_count(page)); + printk("Backtrace:\n"); + dump_stack(); + printk("Trying to fix it up, but a reboot is needed\n"); + page->flags &= ~(1 << PG_private | + 1 << PG_locked | + 1 << PG_lru | + 1 << PG_active | + 1 << PG_dirty | + 1 << PG_writeback); + set_page_count(page, 0); + page->mapping = NULL; } /* @@ -156,6 +167,12 @@ * Frees a list of pages. * Assumes all pages on list are in same zone, and of same order. * count is the number of pages to free, or 0 for all on the list. + * + * If the zone was previously in an "all pages pinned" state then look to + * see if this freeing clears that state. + * + * And clear the zone's pages_scanned counter, to hold off the "all pages are + * pinned" detection logic. */ static int free_pages_bulk(struct zone *zone, int count, @@ -170,6 +187,8 @@ base = zone->zone_mem_map; area = zone->free_area + order; spin_lock_irqsave(&zone->lock, flags); + zone->all_unreclaimable = 0; + zone->pages_scanned = 0; while (!list_empty(list) && count--) { page = list_entry(list->prev, struct page, list); /* have to delete it as __free_pages_bulk list manipulates */ @@ -246,7 +265,7 @@ page->flags &= ~(1 << PG_uptodate | 1 << PG_error | 1 << PG_referenced | 1 << PG_arch_1 | - 1 << PG_checked); + 1 << PG_checked | 1 << PG_mappedtodisk); set_page_refs(page, order); } @@ -400,12 +419,25 @@ } /* - * This is the 'heart' of the zoned buddy allocator: + * This is the 'heart' of the zoned buddy allocator. + * + * Herein lies the mysterious "incremental min". That's the + * + * min += z->pages_low; + * + * thing. The intent here is to provide additional protection to low zones for + * allocation requests which _could_ use higher zones. So a GFP_HIGHMEM + * request is not allowed to dip as deeply into the normal zone as a GFP_KERNEL + * request. This preserves additional space in those lower zones for requests + * which really do need memory from those zones. It means that on a decent + * sized machine, GFP_HIGHMEM and GFP_KERNEL requests basically leave the DMA + * zone untouched. */ struct page * __alloc_pages(unsigned int gfp_mask, unsigned int order, struct zonelist *zonelist) { + const int wait = gfp_mask & __GFP_WAIT; unsigned long min; struct zone **zones, *classzone; struct page *page; @@ -413,7 +445,7 @@ int i; int cold; - if (gfp_mask & __GFP_WAIT) + if (wait) might_sleep(); cold = 0; @@ -430,9 +462,9 @@ for (i = 0; zones[i] != NULL; i++) { struct zone *z = zones[i]; - /* the incremental min is allegedly to discourage fallback */ min += z->pages_low; - if (z->free_pages > min || z->free_pages >= z->pages_high) { + if (z->free_pages > min || + (!wait && z->free_pages >= z->pages_high)) { page = buffered_rmqueue(z, order, cold); if (page) return page; @@ -440,12 +472,8 @@ } /* we're somewhat low on memory, failed to find what we needed */ - for (i = 0; zones[i] != NULL; i++) { - struct zone *z = zones[i]; - if (z->free_pages <= z->pages_low && - waitqueue_active(&z->zone_pgdat->kswapd_wait)) - wake_up_interruptible(&z->zone_pgdat->kswapd_wait); - } + for (i = 0; zones[i] != NULL; i++) + wakeup_kswapd(zones[i]); /* Go through the zonelist again, taking __GFP_HIGH into account */ min = 1UL << order; @@ -457,7 +485,8 @@ if (gfp_mask & __GFP_HIGH) local_min >>= 2; min += local_min; - if (z->free_pages > min || z->free_pages >= z->pages_high) { + if (z->free_pages > min || + (!wait && z->free_pages >= z->pages_high)) { page = buffered_rmqueue(z, order, cold); if (page) return page; @@ -479,7 +508,7 @@ } /* Atomic allocations - we can't balance anything */ - if (!(gfp_mask & __GFP_WAIT)) + if (!wait) goto nopage; inc_page_state(allocstall); @@ -494,7 +523,8 @@ struct zone *z = zones[i]; min += z->pages_min; - if (z->free_pages > min || z->free_pages >= z->pages_high) { + if (z->free_pages > min || + (!wait && z->free_pages >= z->pages_high)) { page = buffered_rmqueue(z, order, cold); if (page) return page; @@ -1181,7 +1211,8 @@ void __init free_area_init(unsigned long *zones_size) { - free_area_init_node(0, &contig_page_data, NULL, zones_size, 0, NULL); + free_area_init_node(0, &contig_page_data, NULL, zones_size, + __pa(PAGE_OFFSET) >> PAGE_SHIFT, NULL); mem_map = contig_page_data.node_mem_map; } #endif diff -Nru a/mm/page_io.c b/mm/page_io.c --- a/mm/page_io.c Fri Nov 22 13:41:18 2002 +++ b/mm/page_io.c Fri Nov 22 13:41:18 2002 @@ -115,6 +115,7 @@ struct bio *bio; int ret = 0; + BUG_ON(!PageLocked(page)); ClearPageUptodate(page); bio = get_swap_bio(GFP_KERNEL, page, end_swap_bio_read); if (bio == NULL) { @@ -127,23 +128,8 @@ out: return ret; } -/* - * swapper_space doesn't have a real inode, so it gets a special vm_writeback() - * so we don't need swap special cases in generic_vm_writeback(). - * - * Swap pages are !PageLocked and PageWriteback while under writeout so that - * memory allocators will throttle against them. - */ -static int swap_vm_writeback(struct page *page, struct writeback_control *wbc) -{ - struct address_space *mapping = page->mapping; - - unlock_page(page); - return generic_writepages(mapping, wbc); -} struct address_space_operations swap_aops = { - .vm_writeback = swap_vm_writeback, .writepage = swap_writepage, .readpage = swap_readpage, .sync_page = block_sync_page, diff -Nru a/mm/shmem.c b/mm/shmem.c --- a/mm/shmem.c Fri Nov 22 13:41:19 2002 +++ b/mm/shmem.c Fri Nov 22 13:41:19 2002 @@ -717,14 +717,6 @@ return 0; } -static int shmem_vm_writeback(struct page *page, struct writeback_control *wbc) -{ - clear_page_dirty(page); - if (shmem_writepage(page) < 0) - set_page_dirty(page); - return 0; -} - /* * shmem_getpage - either get the page from swap or allocate a new one * @@ -1015,7 +1007,8 @@ return 0; } -struct inode *shmem_get_inode(struct super_block *sb, int mode, int dev) +static struct inode * +shmem_get_inode(struct super_block *sb, int mode, dev_t dev) { struct inode *inode; struct shmem_inode_info *info; @@ -1426,7 +1419,8 @@ /* * File creation. Allocate an inode, and we're done.. */ -static int shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev) +static int +shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) { struct inode *inode = shmem_get_inode(dir->i_sb, mode, dev); int error = -ENOSPC; @@ -1809,7 +1803,6 @@ static struct address_space_operations shmem_aops = { .writepage = shmem_writepage, .writepages = shmem_writepages, - .vm_writeback = shmem_vm_writeback, .set_page_dirty = __set_page_dirty_nobuffers, #ifdef CONFIG_TMPFS .readpage = shmem_readpage, diff -Nru a/mm/swap.c b/mm/swap.c --- a/mm/swap.c Fri Nov 22 13:41:19 2002 +++ b/mm/swap.c Fri Nov 22 13:41:19 2002 @@ -200,35 +200,6 @@ } /* - * Move all the inactive pages to the head of the inactive list and release - * them. Reinitialises the caller's pagevec. - */ -void pagevec_deactivate_inactive(struct pagevec *pvec) -{ - int i; - struct zone *zone = NULL; - - if (pagevec_count(pvec) == 0) - return; - for (i = 0; i < pagevec_count(pvec); i++) { - struct page *page = pvec->pages[i]; - struct zone *pagezone = page_zone(page); - - if (pagezone != zone) { - if (zone) - spin_unlock_irq(&zone->lru_lock); - zone = pagezone; - spin_lock_irq(&zone->lru_lock); - } - if (!PageActive(page) && PageLRU(page)) - list_move(&page->lru, &pagezone->inactive_list); - } - if (zone) - spin_unlock_irq(&zone->lru_lock); - __pagevec_release(pvec); -} - -/* * Add the passed pages to the LRU, then drop the caller's refcount * on them. Reinitialises the caller's pagevec. */ diff -Nru a/mm/truncate.c b/mm/truncate.c --- a/mm/truncate.c Fri Nov 22 13:41:23 2002 +++ b/mm/truncate.c Fri Nov 22 13:41:23 2002 @@ -52,6 +52,7 @@ clear_page_dirty(page); ClearPageUptodate(page); + ClearPageMappedToDisk(page); remove_from_page_cache(page); page_cache_release(page); /* pagecache ref */ } diff -Nru a/mm/vmscan.c b/mm/vmscan.c --- a/mm/vmscan.c Fri Nov 22 13:41:18 2002 +++ b/mm/vmscan.c Fri Nov 22 13:41:18 2002 @@ -285,12 +285,6 @@ #endif /* CONFIG_SWAP */ /* - * FIXME: this is CPU-inefficient for shared mappings. - * try_to_unmap() will set the page dirty and ->vm_writeback - * will write it. So we're back to page-at-a-time writepage - * in LRU order. - */ - /* * If the page is dirty, only perform writeback if that write * will be non-blocking. To prevent this allocation from being * stalled by pagecache activity. But note that there may be @@ -308,13 +302,7 @@ * See swapfile.c:page_queue_congested(). */ if (PageDirty(page)) { - int (*writeback)(struct page *, - struct writeback_control *); struct backing_dev_info *bdi; - const int cluster_size = SWAP_CLUSTER_MAX; - struct writeback_control wbc = { - .nr_to_write = cluster_size, - }; if (!is_page_cache_freeable(page)) goto keep_locked; @@ -326,13 +314,15 @@ if (bdi != current->backing_dev_info && bdi_write_congested(bdi)) goto keep_locked; - - writeback = mapping->a_ops->vm_writeback; - if (writeback == NULL) - writeback = generic_vm_writeback; - (*writeback)(page, &wbc); - *max_scan -= (cluster_size - wbc.nr_to_write); - goto keep; + if (test_clear_page_dirty(page)) { + write_lock(&mapping->page_lock); + list_move(&page->list, &mapping->locked_pages); + write_unlock(&mapping->page_lock); + + if (mapping->a_ops->writepage(page) == -EAGAIN) + __set_page_dirty_nobuffers(page); + goto keep; + } } /* @@ -478,6 +468,7 @@ nr_taken++; } zone->nr_inactive -= nr_taken; + zone->pages_scanned += nr_taken; spin_unlock_irq(&zone->lru_lock); if (nr_taken == 0) @@ -722,28 +713,34 @@ * This is the direct reclaim path, for page-allocating processes. We only * try to reclaim pages from zones which will satisfy the caller's allocation * request. + * + * We reclaim from a zone even if that zone is over pages_high. Because: + * a) The caller may be trying to free *extra* pages to satisfy a higher-order + * allocation or + * b) The zones may be over pages_high but they must go *over* pages_high to + * satisfy the `incremental min' zone defense algorithm. + * + * Returns the number of reclaimed pages. + * + * If a zone is deemed to be full of pinned pages then just give it a light + * scan then give up on it. */ static int shrink_caches(struct zone *classzone, int priority, int *total_scanned, - int gfp_mask, const int nr_pages, int order, - struct page_state *ps) + int gfp_mask, const int nr_pages, struct page_state *ps) { struct zone *first_classzone; struct zone *zone; - int nr_mapped = 0; int ret = 0; first_classzone = classzone->zone_pgdat->node_zones; for (zone = classzone; zone >= first_classzone; zone--) { + int to_reclaim = max(nr_pages, SWAP_CLUSTER_MAX); + int nr_mapped = 0; int max_scan; - int to_reclaim; - to_reclaim = zone->pages_high - zone->free_pages; - if (order == 0 && to_reclaim < 0) - continue; /* zone has enough memory */ - - to_reclaim = min(to_reclaim, SWAP_CLUSTER_MAX); - to_reclaim = max(to_reclaim, nr_pages); + if (zone->all_unreclaimable && priority != DEF_PRIORITY) + continue; /* Let kswapd poll it */ /* * If we cannot reclaim `nr_pages' pages by scanning twice @@ -754,8 +751,7 @@ max_scan = to_reclaim * 2; ret += shrink_zone(zone, max_scan, gfp_mask, to_reclaim, &nr_mapped, ps, priority); - *total_scanned += max_scan; - *total_scanned += nr_mapped; + *total_scanned += max_scan + nr_mapped; if (ret >= nr_pages) break; } @@ -796,11 +792,11 @@ get_page_state(&ps); nr_reclaimed += shrink_caches(classzone, priority, &total_scanned, gfp_mask, - nr_pages, order, &ps); + nr_pages, &ps); if (nr_reclaimed >= nr_pages) return 1; if (total_scanned == 0) - return 1; /* All zones had enough free memory */ + printk("%s: I am buggy\n", __FUNCTION__); if (!(gfp_mask & __GFP_FS)) break; /* Let the caller handle it */ /* @@ -828,6 +824,14 @@ * special. * * Returns the number of pages which were actually freed. + * + * There is special handling here for zones which are full of pinned pages. + * This can happen if the pages are all mlocked, or if they are all used by + * device drivers (say, ZONE_DMA). Or if they are all in use by hugetlb. + * What we do is to detect the case where all pages in the zone have been + * scanned twice and there has been zero successful reclaim. Mark the zone as + * dead and from now on, only perform a short scan. Basically we're polling + * the zone for when the problem goes away. */ static int balance_pgdat(pg_data_t *pgdat, int nr_pages, struct page_state *ps) { @@ -844,6 +848,9 @@ int max_scan; int to_reclaim; + if (zone->all_unreclaimable && priority != DEF_PRIORITY) + continue; + if (nr_pages && to_free > 0) { /* Software suspend */ to_reclaim = min(to_free, SWAP_CLUSTER_MAX*8); } else { /* Zone balancing */ @@ -860,6 +867,10 @@ to_free -= shrink_zone(zone, max_scan, GFP_KSWAPD, to_reclaim, &nr_mapped, ps, priority); shrink_slab(max_scan + nr_mapped, GFP_KSWAPD); + if (zone->all_unreclaimable) + continue; + if (zone->pages_scanned > zone->present_pages * 2) + zone->all_unreclaimable = 1; } if (all_zones_ok) break; @@ -920,6 +931,18 @@ } } +/* + * A zone is low on free memory, so wake its kswapd task to service it. + */ +void wakeup_kswapd(struct zone *zone) +{ + if (zone->free_pages > zone->pages_low) + return; + if (!waitqueue_active(&zone->zone_pgdat->kswapd_wait)) + return; + wake_up_interruptible(&zone->zone_pgdat->kswapd_wait); +} + #ifdef CONFIG_SOFTWARE_SUSPEND /* * Try to free `nr_pages' of memory, system-wide. Returns the number of freed @@ -949,7 +972,6 @@ static int __init kswapd_init(void) { pg_data_t *pgdat; - printk("Starting kswapd\n"); swap_setup(); for_each_pgdat(pgdat) kernel_thread(kswapd, pgdat, CLONE_KERNEL); diff -Nru a/net/8021q/vlan.c b/net/8021q/vlan.c --- a/net/8021q/vlan.c Fri Nov 22 13:41:22 2002 +++ b/net/8021q/vlan.c Fri Nov 22 13:41:22 2002 @@ -45,7 +45,7 @@ static char vlan_fullname[] = "802.1Q VLAN Support"; static unsigned int vlan_version = 1; -static unsigned int vlan_release = 7; +static unsigned int vlan_release = 8; static char vlan_copyright[] = "Ben Greear "; static char vlan_buggyright[] = "David S. Miller "; @@ -229,12 +229,13 @@ if (real_dev->features & (NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER)) { real_dev->vlan_rx_kill_vid(real_dev, vlan_id); - } else { - br_write_lock(BR_NETPROTO_LOCK); - grp->vlan_devices[vlan_id] = NULL; - br_write_unlock(BR_NETPROTO_LOCK); } + br_write_lock(BR_NETPROTO_LOCK); + grp->vlan_devices[vlan_id] = NULL; + br_write_unlock(BR_NETPROTO_LOCK); + + /* Caller unregisters (and if necessary, puts) * VLAN device, but we get rid of the reference to * real_dev here. @@ -256,6 +257,12 @@ __grp_unhash(grp); spin_unlock_bh(&vlan_group_lock); + /* Free the group, after we have removed it + * from the hash. + */ + kfree(grp); + grp = NULL; + ret = 1; } @@ -626,6 +633,7 @@ ret = unregister_vlan_dev(dev, VLAN_DEV_INFO(vlandev)->vlan_id); + dev_put(vlandev); unregister_netdevice(vlandev); /* Group was destroyed? */ diff -Nru a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c --- a/net/8021q/vlan_dev.c Fri Nov 22 13:41:23 2002 +++ b/net/8021q/vlan_dev.c Fri Nov 22 13:41:23 2002 @@ -738,7 +738,7 @@ while (dmi) { dev_mc_delete(dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); - printk(KERN_INFO "%s: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from vlan interface\n", + printk(KERN_DEBUG "%s: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from vlan interface\n", dev->name, dmi->dmi_addr[0], dmi->dmi_addr[1], @@ -820,7 +820,7 @@ for (dmi = vlan_dev->mc_list; dmi != NULL; dmi = dmi->next) { if (vlan_should_add_mc(dmi, VLAN_DEV_INFO(vlan_dev)->old_mc_list)) { dev_mc_add(real_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); - printk(KERN_INFO "%s: add %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address to master interface\n", + printk(KERN_DEBUG "%s: add %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address to master interface\n", vlan_dev->name, dmi->dmi_addr[0], dmi->dmi_addr[1], @@ -838,7 +838,7 @@ * delete it from the real list on the underlying device. */ dev_mc_delete(real_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); - printk(KERN_INFO "%s: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from master interface\n", + printk(KERN_DEBUG "%s: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from master interface\n", vlan_dev->name, dmi->dmi_addr[0], dmi->dmi_addr[1], diff -Nru a/net/Kconfig b/net/Kconfig --- a/net/Kconfig Fri Nov 22 13:41:17 2002 +++ b/net/Kconfig Fri Nov 22 13:41:17 2002 @@ -266,14 +266,14 @@ tristate "802.1Q VLAN Support" config LLC - tristate "ANSI/IEEE 802.2 Data link layer protocol (IPX, Appletalk)" + tristate "ANSI/IEEE 802.2 - aka LLC (IPX, Appletalk, Token Ring)" help - This is a Logical Link Layer protocol used for Appletalk, IPX and in - the future by NetBEUI and by the linux-sna project. It originally - came from Procom Inc. that released the code for 2.0.36 and was - ported to 2.{4,5}. Select this if you want to have support for - those protocols or if you want to have the sockets interface for - LLC. + This is a Logical Link Layer protocol used for Appletalk, IPX, + Token Ring devices, the linux-sna.org project and in the future by + NetBEUI. It originally came from Procom Inc. that released the code + for 2.0.36 and was heavily modified to work with 2.{4,5}. + Select this if you want to have support for those protocols or if + you want to have the sockets interface for LLC. config LLC_UI diff -Nru a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c --- a/net/bridge/netfilter/ebtables.c Fri Nov 22 13:41:18 2002 +++ b/net/bridge/netfilter/ebtables.c Fri Nov 22 13:41:18 2002 @@ -183,7 +183,7 @@ point = (struct ebt_entry *)(private->hook_entry[hook]->data); counter_base = cb_base + private->hook_entry[hook]->counter_offset; // base for chain jumps - base = (char *)chaininfo; + base = private->entries; i = 0; while (i < nentries) { if (ebt_basic_match(point, (**pskb).mac.ethernet, in, out)) diff -Nru a/net/core/dev.c b/net/core/dev.c --- a/net/core/dev.c Fri Nov 22 13:41:20 2002 +++ b/net/core/dev.c Fri Nov 22 13:41:20 2002 @@ -105,6 +105,7 @@ #include #include #include +#include #if defined(CONFIG_NET_RADIO) || defined(CONFIG_NET_PCMCIA_RADIO) #include /* Note : will define WIRELESS_EXT */ #include diff -Nru a/net/ipv4/ah.c b/net/ipv4/ah.c --- a/net/ipv4/ah.c Fri Nov 22 13:41:23 2002 +++ b/net/ipv4/ah.c Fri Nov 22 13:41:23 2002 @@ -234,11 +234,12 @@ x->curlft.packets++; spin_unlock_bh(&x->lock); if ((skb->dst = dst_pop(dst)) == NULL) - goto error; + goto error_nolock; return NET_XMIT_BYPASS; error: spin_unlock_bh(&x->lock); +error_nolock: kfree_skb(skb); return err; } diff -Nru a/net/ipv4/esp.c b/net/ipv4/esp.c --- a/net/ipv4/esp.c Fri Nov 22 13:41:21 2002 +++ b/net/ipv4/esp.c Fri Nov 22 13:41:21 2002 @@ -435,11 +435,12 @@ x->curlft.packets++; spin_unlock_bh(&x->lock); if ((skb->dst = dst_pop(dst)) == NULL) - goto error; + goto error_nolock; return NET_XMIT_BYPASS; error: spin_unlock_bh(&x->lock); +error_nolock: kfree_skb(skb); return err; } diff -Nru a/net/ipv4/xfrm_policy.c b/net/ipv4/xfrm_policy.c --- a/net/ipv4/xfrm_policy.c Fri Nov 22 13:41:20 2002 +++ b/net/ipv4/xfrm_policy.c Fri Nov 22 13:41:20 2002 @@ -204,6 +204,50 @@ __MOD_DEC_USE_COUNT(type->owner); } +static inline unsigned long make_jiffies(long secs) +{ + if (secs >= (MAX_SCHEDULE_TIMEOUT-1)/HZ) + return MAX_SCHEDULE_TIMEOUT-1; + else + return secs*HZ; +} + +static void xfrm_policy_timer(unsigned long data) +{ + struct xfrm_policy *xp = (struct xfrm_policy*)data; + unsigned long now = (unsigned long)xtime.tv_sec; + long next = LONG_MAX; + + if (xp->dead) + goto out; + + if (xp->lft.hard_add_expires_seconds) { + long tmo = xp->lft.hard_add_expires_seconds + + xp->curlft.add_time - now; + if (tmo <= 0) + goto expired; + if (tmo < next) + next = tmo; + } + if (next != LONG_MAX && + !mod_timer(&xp->timer, jiffies + make_jiffies(next))) + atomic_inc(&xp->refcnt); + +out: + xfrm_pol_put(xp); + return; + +expired: + xfrm_pol_put(xp); + + /* Not 100% correct. id can be recycled in theory */ + xp = xfrm_policy_byid(0, xp->index, 1); + if (xp) { + xfrm_policy_kill(xp); + xfrm_pol_put(xp); + } +} + /* Allocate xfrm_policy. Not used here, it is supposed to be used by pfkeyv2 * SPD calls. @@ -219,6 +263,9 @@ memset(policy, 0, sizeof(struct xfrm_policy)); atomic_set(&policy->refcnt, 1); policy->lock = RW_LOCK_UNLOCKED; + init_timer(&policy->timer); + policy->timer.data = (unsigned long)policy; + policy->timer.function = xfrm_policy_timer; } return policy; } @@ -233,6 +280,9 @@ if (policy->bundles) BUG(); + if (del_timer(&policy->timer)) + BUG(); + kfree(policy); } @@ -255,6 +305,9 @@ dst_free(dst); } + if (del_timer(&policy->timer)) + atomic_dec(&policy->refcnt); + out: write_unlock_bh(&policy->lock); } @@ -302,6 +355,9 @@ policy->index = pol ? pol->index : xfrm_gen_index(dir); policy->curlft.add_time = (unsigned long)xtime.tv_sec; policy->curlft.use_time = 0; + if (policy->lft.hard_add_expires_seconds && + !mod_timer(&policy->timer, jiffies + HZ)) + atomic_inc(&policy->refcnt); write_unlock_bh(&xfrm_policy_lock); if (pol) { @@ -380,7 +436,7 @@ int count = 0; int error = 0; - read_lock(&xfrm_policy_lock); + read_lock_bh(&xfrm_policy_lock); for (dir = 0; dir < 2*XFRM_POLICY_MAX; dir++) { for (xp = xfrm_policy_list[dir]; xp; xp = xp->next) count++; @@ -400,7 +456,7 @@ } out: - read_unlock(&xfrm_policy_lock); + read_unlock_bh(&xfrm_policy_lock); return error; } @@ -411,7 +467,7 @@ { struct xfrm_policy *pol; - read_lock(&xfrm_policy_lock); + read_lock_bh(&xfrm_policy_lock); for (pol = xfrm_policy_list[dir]; pol; pol = pol->next) { struct xfrm_selector *sel = &pol->selector; @@ -420,7 +476,7 @@ break; } } - read_unlock(&xfrm_policy_lock); + read_unlock_bh(&xfrm_policy_lock); return pol; } @@ -428,14 +484,14 @@ { struct xfrm_policy *pol; - read_lock(&xfrm_policy_lock); + read_lock_bh(&xfrm_policy_lock); if ((pol = sk->policy[dir]) != NULL) { if (xfrm4_selector_match(&pol->selector, fl)) atomic_inc(&pol->refcnt); else pol = NULL; } - read_unlock(&xfrm_policy_lock); + read_unlock_bh(&xfrm_policy_lock); return pol; } @@ -727,8 +783,7 @@ return 0; } - if (!policy->curlft.use_time) - policy->curlft.use_time = (unsigned long)xtime.tv_sec; + policy->curlft.use_time = (unsigned long)xtime.tv_sec; switch (policy->action) { case XFRM_POLICY_BLOCK: @@ -936,8 +991,7 @@ if (!pol) return 1; - if (!pol->curlft.use_time) - pol->curlft.use_time = (unsigned long)xtime.tv_sec; + pol->curlft.use_time = (unsigned long)xtime.tv_sec; if (pol->action == XFRM_POLICY_ALLOW) { if (pol->xfrm_nr != 0) { diff -Nru a/net/ipv4/xfrm_state.c b/net/ipv4/xfrm_state.c --- a/net/ipv4/xfrm_state.c Fri Nov 22 13:41:22 2002 +++ b/net/ipv4/xfrm_state.c Fri Nov 22 13:41:22 2002 @@ -28,7 +28,7 @@ static void __xfrm_state_delete(struct xfrm_state *x); -unsigned long make_jiffies(long secs) +static inline unsigned long make_jiffies(long secs) { if (secs >= (MAX_SCHEDULE_TIMEOUT-1)/HZ) return MAX_SCHEDULE_TIMEOUT-1; @@ -92,7 +92,14 @@ goto out; expired: - km_expired(x); + if (x->km.state == XFRM_STATE_ACQ && x->id.spi == 0) { + x->km.state = XFRM_STATE_EXPIRED; + wake_up(&km_waitq); + next = 2; + goto resched; + } + if (x->id.spi != 0) + km_expired(x); __xfrm_state_delete(x); out: @@ -298,11 +305,13 @@ x->km.state = XFRM_STATE_DEAD; xfrm_state_put(x); x = NULL; + error = 1; } } spin_unlock_bh(&xfrm_state_lock); if (!x) - *err = acquire_in_progress ? -EAGAIN : -ENOMEM; + *err = acquire_in_progress ? -EAGAIN : + (error ? -ESRCH : -ENOMEM); return x; } @@ -612,6 +621,7 @@ list_for_each_entry(km, &xfrm_km_list, list) km->notify(x, 1); read_unlock(&xfrm_km_lock); + wake_up(&km_waitq); } int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol) diff -Nru a/net/ipv4/xfrm_user.c b/net/ipv4/xfrm_user.c --- a/net/ipv4/xfrm_user.c Fri Nov 22 13:41:20 2002 +++ b/net/ipv4/xfrm_user.c Fri Nov 22 13:41:20 2002 @@ -23,7 +23,7 @@ static int verify_one_alg(struct rtattr **xfrma, enum xfrm_attr_type_t type) { - struct rtattr *rt = xfrma[type]; + struct rtattr *rt = xfrma[type - 1]; struct xfrm_algo *algp; if (!rt) @@ -73,23 +73,23 @@ err = -EINVAL; switch (p->id.proto) { case IPPROTO_AH: - if (!xfrma[XFRMA_ALG_AUTH] || - xfrma[XFRMA_ALG_CRYPT] || - xfrma[XFRMA_ALG_COMP]) + if (!xfrma[XFRMA_ALG_AUTH-1] || + xfrma[XFRMA_ALG_CRYPT-1] || + xfrma[XFRMA_ALG_COMP-1]) goto out; break; case IPPROTO_ESP: - if ((!xfrma[XFRMA_ALG_AUTH] && - !xfrma[XFRMA_ALG_CRYPT]) || - xfrma[XFRMA_ALG_COMP]) + if ((!xfrma[XFRMA_ALG_AUTH-1] && + !xfrma[XFRMA_ALG_CRYPT-1]) || + xfrma[XFRMA_ALG_COMP-1]) goto out; break; case IPPROTO_COMP: - if (!xfrma[XFRMA_ALG_COMP] || - xfrma[XFRMA_ALG_AUTH] || - xfrma[XFRMA_ALG_CRYPT]) + if (!xfrma[XFRMA_ALG_COMP-1] || + xfrma[XFRMA_ALG_AUTH-1] || + xfrma[XFRMA_ALG_CRYPT-1]) goto out; break; @@ -162,11 +162,11 @@ copy_from_user_state(x, p); - if ((err = attach_one_algo(&x->aalg, xfrma[XFRMA_ALG_AUTH]))) + if ((err = attach_one_algo(&x->aalg, xfrma[XFRMA_ALG_AUTH-1]))) goto error; - if ((err = attach_one_algo(&x->ealg, xfrma[XFRMA_ALG_CRYPT]))) + if ((err = attach_one_algo(&x->ealg, xfrma[XFRMA_ALG_CRYPT-1]))) goto error; - if ((err = attach_one_algo(&x->calg, xfrma[XFRMA_ALG_COMP]))) + if ((err = attach_one_algo(&x->calg, xfrma[XFRMA_ALG_COMP-1]))) goto error; err = -ENOENT; @@ -485,7 +485,7 @@ static int copy_user_tmpl(struct xfrm_policy *pol, struct rtattr **xfrma) { - struct rtattr *rt = xfrma[XFRMA_TMPL]; + struct rtattr *rt = xfrma[XFRMA_TMPL-1]; struct xfrm_user_tmpl *utmpl; int nr; @@ -910,9 +910,8 @@ BUG(); NETLINK_CB(skb).dst_groups = XFRMGRP_EXPIRE; - netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC); - return 0; + return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC); } /* XXX Make this xfrm_state.c:xfrm_get_acqseq() */ @@ -971,9 +970,8 @@ BUG(); NETLINK_CB(skb).dst_groups = XFRMGRP_ACQUIRE; - netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_ACQUIRE, GFP_ATOMIC); - return 0; + return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_ACQUIRE, GFP_ATOMIC); } /* User gives us xfrm_user_policy_info followed by an array of 0 diff -Nru a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c --- a/net/ipv6/ip6_input.c Fri Nov 22 13:41:22 2002 +++ b/net/ipv6/ip6_input.c Fri Nov 22 13:41:22 2002 @@ -182,9 +182,10 @@ if (!raw_sk) { IP6_INC_STATS_BH(Ip6InUnknownProtos); icmpv6_param_prob(skb, ICMPV6_UNK_NEXTHDR, nhoff); - } else + } else { IP6_INC_STATS_BH(Ip6InDelivers); - kfree_skb(skb); + kfree_skb(skb); + } } return 0; diff -Nru a/net/ipv6/ipv6_syms.c b/net/ipv6/ipv6_syms.c --- a/net/ipv6/ipv6_syms.c Fri Nov 22 13:41:22 2002 +++ b/net/ipv6/ipv6_syms.c Fri Nov 22 13:41:22 2002 @@ -24,3 +24,4 @@ EXPORT_SYMBOL(inet6_getname); EXPORT_SYMBOL(inet6_ioctl); EXPORT_SYMBOL(ipv6_get_saddr); +EXPORT_SYMBOL(ipv6_chk_addr); diff -Nru a/net/key/af_key.c b/net/key/af_key.c --- a/net/key/af_key.c Fri Nov 22 13:41:18 2002 +++ b/net/key/af_key.c Fri Nov 22 13:41:18 2002 @@ -196,9 +196,11 @@ return 0; } -static void pfkey_broadcast_one(struct sk_buff *skb, struct sk_buff **skb2, - int allocation, struct sock *sk) +static int pfkey_broadcast_one(struct sk_buff *skb, struct sk_buff **skb2, + int allocation, struct sock *sk) { + int err = -ENOBUFS; + sock_hold(sk); if (*skb2 == NULL) { if (atomic_read(&skb->users) != 1) { @@ -215,9 +217,11 @@ skb_queue_tail(&sk->receive_queue, *skb2); sk->data_ready(sk, (*skb2)->len); *skb2 = NULL; + err = 0; } } sock_put(sk); + return err; } /* Send SKB to all pfkey sockets matching selected criteria. */ @@ -225,21 +229,23 @@ #define BROADCAST_ONE 1 #define BROADCAST_REGISTERED 2 #define BROADCAST_PROMISC_ONLY 4 -static void pfkey_broadcast(struct sk_buff *skb, int allocation, - int broadcast_flags, struct sock *one_sk) +static int pfkey_broadcast(struct sk_buff *skb, int allocation, + int broadcast_flags, struct sock *one_sk) { struct sock *sk; struct sk_buff *skb2 = NULL; + int err = -ESRCH; /* XXX Do we need something like netlink_overrun? I think * XXX PF_KEY socket apps will not mind current behavior. */ if (!skb) - return; + return -ENOMEM; pfkey_lock_table(); for (sk = pfkey_table; sk; sk = sk->next) { struct pfkey_opt *pfk = pfkey_sk(sk); + int err2; /* Yes, it means that if you are meant to receive this * pfkey message you receive it twice as promiscuous @@ -261,16 +267,22 @@ continue; } - pfkey_broadcast_one(skb, &skb2, allocation, sk); + err2 = pfkey_broadcast_one(skb, &skb2, allocation, sk); + + /* Error is cleare after succecful sending to at least one + * registered KM */ + if ((broadcast_flags & BROADCAST_REGISTERED) && err) + err = err2; } pfkey_unlock_table(); if (one_sk != NULL) - pfkey_broadcast_one(skb, &skb2, allocation, one_sk); + err = pfkey_broadcast_one(skb, &skb2, allocation, one_sk); if (skb2) kfree_skb(skb2); kfree_skb(skb); + return err; } static inline void pfkey_hdr_dup(struct sadb_msg *new, struct sadb_msg *orig) @@ -1101,8 +1113,12 @@ if (x == NULL) return 0; - if (x->km.state == XFRM_STATE_ACQ) - xfrm_state_delete(x); + spin_lock_bh(&x->lock); + if (x->km.state == XFRM_STATE_ACQ) { + x->km.state = XFRM_STATE_ERROR; + wake_up(&km_waitq); + } + spin_unlock_bh(&x->lock); xfrm_state_put(x); return 0; } @@ -1783,14 +1799,10 @@ struct sk_buff *out_skb; struct sadb_msg *out_hdr; - if (!ext_hdrs[SADB_X_EXT_POLICY-1]) + if ((pol = ext_hdrs[SADB_X_EXT_POLICY-1]) == NULL) return -EINVAL; - pol = ext_hdrs[SADB_X_EXT_POLICY-1]; - if (!pol->sadb_x_policy_dir || pol->sadb_x_policy_dir >= IPSEC_DIR_MAX) - return -EINVAL; - - xp = xfrm_policy_byid(pol->sadb_x_policy_dir-1, pol->sadb_x_policy_id, + xp = xfrm_policy_byid(0, pol->sadb_x_policy_id, hdr->sadb_msg_type == SADB_X_SPDDELETE2); if (xp == NULL) return -ENOENT; @@ -2142,9 +2154,7 @@ else if (x->id.proto == IPPROTO_ESP) dump_esp_combs(skb, t); - pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL); - - return 0; + return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL); } static struct xfrm_policy *pfkey_compile_policy(int opt, u8 *data, int len, int *dir) diff -Nru a/net/llc/llc_main.c b/net/llc/llc_main.c --- a/net/llc/llc_main.c Fri Nov 22 13:41:19 2002 +++ b/net/llc/llc_main.c Fri Nov 22 13:41:19 2002 @@ -181,22 +181,22 @@ llc->inc_cntr = llc->dec_cntr = 2; llc->dec_step = llc->connect_step = 1; - init_timer(&llc->ack_timer); + init_timer(&llc->ack_timer.timer); llc->ack_timer.expire = LLC_ACK_TIME; llc->ack_timer.timer.data = (unsigned long)sk; llc->ack_timer.timer.function = llc_conn_ack_tmr_cb; - init_timer(&llc->pf_cycle_timer); + init_timer(&llc->pf_cycle_timer.timer); llc->pf_cycle_timer.expire = LLC_P_TIME; llc->pf_cycle_timer.timer.data = (unsigned long)sk; llc->pf_cycle_timer.timer.function = llc_conn_pf_cycle_tmr_cb; - init_timer(&llc->rej_sent_timer); + init_timer(&llc->rej_sent_timer.timer); llc->rej_sent_timer.expire = LLC_REJ_TIME; llc->rej_sent_timer.timer.data = (unsigned long)sk; llc->rej_sent_timer.timer.function = llc_conn_rej_tmr_cb; - init_timer(&llc->busy_state_timer); + init_timer(&llc->busy_state_timer.timer); llc->busy_state_timer.expire = LLC_BUSY_TIME; llc->busy_state_timer.timer.data = (unsigned long)sk; llc->busy_state_timer.timer.function = llc_conn_busy_tmr_cb; diff -Nru a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c --- a/net/netlink/af_netlink.c Fri Nov 22 13:41:20 2002 +++ b/net/netlink/af_netlink.c Fri Nov 22 13:41:20 2002 @@ -503,13 +503,13 @@ return -1; } -void netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid, - u32 group, int allocation) +int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid, + u32 group, int allocation) { struct sock *sk; struct sk_buff *skb2 = NULL; int protocol = ssk->protocol; - int failure = 0; + int failure = 0, delivered = 0; /* While we sleep in clone, do not allow to change socket list */ @@ -544,8 +544,10 @@ failure = 1; } else if (netlink_broadcast_deliver(sk, skb2)) { netlink_overrun(sk); - } else + } else { + delivered = 1; skb2 = NULL; + } sock_put(sk); } @@ -554,6 +556,12 @@ if (skb2) kfree_skb(skb2); kfree_skb(skb); + + if (delivered) + return 0; + if (failure) + return -ENOBUFS; + return -ESRCH; } void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code) diff -Nru a/net/netsyms.c b/net/netsyms.c --- a/net/netsyms.c Fri Nov 22 13:41:19 2002 +++ b/net/netsyms.c Fri Nov 22 13:41:19 2002 @@ -116,6 +116,7 @@ EXPORT_SYMBOL(sock_recvmsg); EXPORT_SYMBOL(sk_alloc); EXPORT_SYMBOL(sk_free); +EXPORT_SYMBOL(sk_send_sigurg); EXPORT_SYMBOL(sock_wake_async); EXPORT_SYMBOL(sock_alloc_send_skb); EXPORT_SYMBOL(sock_alloc_send_pskb); @@ -283,6 +284,7 @@ EXPORT_SYMBOL(dlci_ioctl_hook); #endif +EXPORT_SYMBOL(km_waitq); EXPORT_SYMBOL(xfrm_cfg_sem); EXPORT_SYMBOL(xfrm_policy_alloc); EXPORT_SYMBOL(__xfrm_policy_destroy); diff -Nru a/net/sched/sch_gred.c b/net/sched/sch_gred.c --- a/net/sched/sch_gred.c Fri Nov 22 13:41:22 2002 +++ b/net/sched/sch_gred.c Fri Nov 22 13:41:22 2002 @@ -328,18 +328,20 @@ struct tc_gred_qopt *ctl; struct tc_gred_sopt *sopt; struct rtattr *tb[TCA_GRED_STAB]; - struct rtattr *tb2[TCA_GRED_STAB]; + struct rtattr *tb2[TCA_GRED_DPS]; int i; if (opt == NULL || rtattr_parse(tb, TCA_GRED_STAB, RTA_DATA(opt), RTA_PAYLOAD(opt)) ) return -EINVAL; - if (tb[TCA_GRED_PARMS-1] == 0 && tb[TCA_GRED_STAB-1] == 0 && - tb[TCA_GRED_DPS-1] != 0) { + if (tb[TCA_GRED_PARMS-1] == 0 && tb[TCA_GRED_STAB-1] == 0) { rtattr_parse(tb2, TCA_GRED_DPS, RTA_DATA(opt), RTA_PAYLOAD(opt)); + if (tb2[TCA_GRED_DPS-1] == 0) + return -EINVAL; + sopt = RTA_DATA(tb2[TCA_GRED_DPS-1]); table->DPs=sopt->DPs; table->def=sopt->def_DP; @@ -471,15 +473,17 @@ struct gred_sched *table = (struct gred_sched *)sch->data; struct tc_gred_sopt *sopt; struct rtattr *tb[TCA_GRED_STAB]; - struct rtattr *tb2[TCA_GRED_STAB]; + struct rtattr *tb2[TCA_GRED_DPS]; if (opt == NULL || rtattr_parse(tb, TCA_GRED_STAB, RTA_DATA(opt), RTA_PAYLOAD(opt)) ) return -EINVAL; - if (tb[TCA_GRED_PARMS-1] == 0 && tb[TCA_GRED_STAB-1] == 0 && - tb[TCA_GRED_DPS-1] != 0) { + if (tb[TCA_GRED_PARMS-1] == 0 && tb[TCA_GRED_STAB-1] == 0) { rtattr_parse(tb2, TCA_GRED_DPS, RTA_DATA(opt),RTA_PAYLOAD(opt)); + + if (tb2[TCA_GRED_DPS-1] == 0) + return -EINVAL; sopt = RTA_DATA(tb2[TCA_GRED_DPS-1]); table->DPs=sopt->DPs; diff -Nru a/net/sctp/associola.c b/net/sctp/associola.c --- a/net/sctp/associola.c Fri Nov 22 13:41:17 2002 +++ b/net/sctp/associola.c Fri Nov 22 13:41:17 2002 @@ -1,39 +1,39 @@ /* SCTP kernel reference Implementation * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001 International Business Machines Corp. + * Copyright (c) 2001-2002 International Business Machines Corp. * Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 La Monte H.P. Yarroll - * + * * This file is part of the SCTP kernel reference Implementation - * + * * This module provides the abstraction for an SCTP association. - * - * The SCTP reference implementation is free software; - * you can redistribute it and/or modify it under the terms of + * + * The SCTP reference implementation 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. - * - * The SCTP reference implementation is distributed in the hope that it + * + * The SCTP reference implementation 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 GNU CC; see the file COPYING. If not, write to * the Free Software Foundation, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * + * Boston, MA 02111-1307, USA. + * * Please send any bug reports or fixes you make to the * email address(es): * lksctp developers - * + * * Or submit a bug report through the following website: * http://www.sf.net/projects/lksctp * - * Written or modified by: + * Written or modified by: * La Monte H.P. Yarroll * Karl Knutson * Jon Grimm @@ -41,7 +41,7 @@ * Hui Huang * Sridhar Samudrala * Daisy Chang - * + * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. */ @@ -92,7 +92,7 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc, const sctp_endpoint_t *ep, const struct sock *sk, - sctp_scope_t scope, + sctp_scope_t scope, int priority) { sctp_opt_t *sp; @@ -363,48 +363,34 @@ /* Add a transport address to an association. */ sctp_transport_t *sctp_assoc_add_peer(sctp_association_t *asoc, - const sockaddr_storage_t *addr, + const union sctp_addr *addr, int priority) { sctp_transport_t *peer; sctp_opt_t *sp; - const __u16 *port; - - switch (addr->sa.sa_family) { - case AF_INET: - port = &addr->v4.sin_port; - break; + unsigned short port; - case AF_INET6: - SCTP_V6( - port = &addr->v6.sin6_port; - break; - ); - - default: - return NULL; - }; + /* AF_INET and AF_INET6 share common port field. */ + port = addr->v4.sin_port; /* Set the port if it has not been set yet. */ if (0 == asoc->peer.port) { - asoc->peer.port = *port; + asoc->peer.port = port; } - SCTP_ASSERT(*port == asoc->peer.port, ":Invalid port\n", return NULL); - /* Check to see if this is a duplicate. */ peer = sctp_assoc_lookup_paddr(asoc, addr); if (peer) return peer; peer = sctp_transport_new(addr, priority); - if (NULL == peer) + if (!peer) return NULL; sctp_transport_set_owner(peer, asoc); /* Cache a route for the transport. */ - sctp_transport_route(peer, NULL); + sctp_transport_route(peer, NULL, sctp_sk(asoc->base.sk)); /* If this is the first transport addr on this association, * initialize the association PMTU to the peer's PMTU. @@ -423,7 +409,7 @@ asoc->frag_point = asoc->pmtu - (SCTP_IP_OVERHEAD + sizeof(sctp_data_chunk_t)); - /* The asoc->peer.port might not be meaningful as of now, but + /* The asoc->peer.port might not be meaningful yet, but * initialize the packet structure anyway. */ (asoc->outqueue.init_output)(&peer->packet, @@ -460,6 +446,9 @@ min(asoc->overall_error_threshold + peer->error_threshold, asoc->max_retrans); + /* By default, enable heartbeat for peer address. */ + peer->hb_allowed = 1; + /* Initialize the peer's heartbeat interval based on the * sock configured value. */ @@ -474,7 +463,7 @@ asoc->peer.primary_path = peer; /* Set a default msg_name for events. */ memcpy(&asoc->peer.primary_addr, &peer->ipaddr, - sizeof(sockaddr_storage_t)); + sizeof(union sctp_addr)); asoc->peer.active_path = peer; asoc->peer.retran_path = peer; } @@ -487,7 +476,7 @@ /* Lookup a transport by address. */ sctp_transport_t *sctp_assoc_lookup_paddr(const sctp_association_t *asoc, - const sockaddr_storage_t *address) + const union sctp_addr *address) { sctp_transport_t *t; struct list_head *pos; @@ -522,12 +511,12 @@ /* Record the transition on the transport. */ switch (command) { case SCTP_TRANSPORT_UP: - transport->state.active = 1; + transport->active = 1; spc_state = ADDRESS_AVAILABLE; break; case SCTP_TRANSPORT_DOWN: - transport->state.active = 0; + transport->active = 0; spc_state = ADDRESS_UNREACHABLE; break; @@ -557,7 +546,7 @@ list_for_each(pos, &asoc->peer.transport_addr_list) { t = list_entry(pos, sctp_transport_t, transports); - if (!t->state.active) + if (!t->active) continue; if (!first || t->last_time_heard > first->last_time_heard) { second = first; @@ -577,7 +566,7 @@ * [If the primary is active but not most recent, bump the most * recently used transport.] */ - if (asoc->peer.primary_path->state.active && + if (asoc->peer.primary_path->active && first != asoc->peer.primary_path) { second = first; first = asoc->peer.primary_path; @@ -646,101 +635,20 @@ } /* Compare two addresses to see if they match. Wildcard addresses - * always match within their address family. - * - * FIXME: We do not match address scopes correctly. - */ -int sctp_cmp_addr(const sockaddr_storage_t *ss1, const sockaddr_storage_t *ss2) -{ - int len; - const void *base1; - const void *base2; - - if (ss1->sa.sa_family != ss2->sa.sa_family) - return 0; - if (ss1->v4.sin_port != ss2->v4.sin_port) - return 0; - - switch (ss1->sa.sa_family) { - case AF_INET: - if (INADDR_ANY == ss1->v4.sin_addr.s_addr || - INADDR_ANY == ss2->v4.sin_addr.s_addr) - goto match; - - len = sizeof(struct in_addr); - base1 = &ss1->v4.sin_addr; - base2 = &ss2->v4.sin_addr; - break; - - case AF_INET6: - SCTP_V6( - if (IPV6_ADDR_ANY == - sctp_ipv6_addr_type(&ss1->v6.sin6_addr)) - goto match; - - if (IPV6_ADDR_ANY == - sctp_ipv6_addr_type(&ss2->v6.sin6_addr)) - goto match; - - len = sizeof(struct in6_addr); - base1 = &ss1->v6.sin6_addr; - base2 = &ss2->v6.sin6_addr; - break; - ) - - default: - printk(KERN_WARNING - "WARNING, bogus socket address family %d\n", - ss1->sa.sa_family); - return 0; - }; - - return (0 == memcmp(base1, base2, len)); - -match: - return 1; -} - -/* Compare two addresses to see if they match. Wildcard addresses * only match themselves. * * FIXME: We do not match address scopes correctly. */ -int sctp_cmp_addr_exact(const sockaddr_storage_t *ss1, - const sockaddr_storage_t *ss2) +int sctp_cmp_addr_exact(const union sctp_addr *ss1, + const union sctp_addr *ss2) { - int len; - const void *base1; - const void *base2; + struct sctp_func *af; - if (ss1->sa.sa_family != ss2->sa.sa_family) + af = sctp_get_af_specific(ss1->sa.sa_family); + if (!af) return 0; - if (ss1->v4.sin_port != ss2->v4.sin_port) - return 0; - - switch (ss1->sa.sa_family) { - case AF_INET: - len = sizeof(struct in_addr); - base1 = &ss1->v4.sin_addr; - base2 = &ss2->v4.sin_addr; - break; - - case AF_INET6: - SCTP_V6( - len = sizeof(struct in6_addr); - base1 = &ss1->v6.sin6_addr; - base2 = &ss2->v6.sin6_addr; - break; - ) - - default: - printk(KERN_WARNING - "WARNING, bogus socket address family %d\n", - ss1->sa.sa_family); - return 0; - }; - return (0 == memcmp(base1, base2, len)); + return af->cmp_addr(ss1, ss2); } /* Return an ecne chunk to get prepended to a packet. @@ -842,8 +750,8 @@ /* Is this the association we are looking for? */ sctp_transport_t *sctp_assoc_is_match(sctp_association_t *asoc, - const sockaddr_storage_t *laddr, - const sockaddr_storage_t *paddr) + const union sctp_addr *laddr, + const union sctp_addr *paddr) { sctp_transport_t *transport; @@ -855,7 +763,8 @@ if (!transport) goto out; - if (sctp_bind_addr_has_addr(&asoc->base.bind_addr, laddr)) + if (sctp_bind_addr_match(&asoc->base.bind_addr, laddr, + sctp_sk(asoc->base.sk))) goto out; } transport = NULL; @@ -898,21 +807,17 @@ error = sctp_do_sm(SCTP_EVENT_T_CHUNK, SCTP_ST_CHUNK(subtype), state, ep, asoc, chunk, GFP_ATOMIC); - /* Check to see if the association is freed in response to + /* Check to see if the association is freed in response to * the incoming chunk. If so, get out of the while loop. */ if (!sctp_id2assoc(sk, associd)) - goto out; + break; - if (error != 0) - goto err_out; + /* If there is an error on chunk, discard this packet. */ + if (error && chunk) + chunk->pdiscard = 1; } -err_out: - /* Is this the right way to pass errors up to the ULP? */ - if (error) - sk->err = -error; -out: } /* This routine moves an association from its old sk to a new sk. */ @@ -1017,7 +922,7 @@ /* Try to find an active transport. */ - if (t->state.active) { + if (t->active) { break; } else { /* Keep track of the next transport in case diff -Nru a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c --- a/net/sctp/bind_addr.c Fri Nov 22 13:41:22 2002 +++ b/net/sctp/bind_addr.c Fri Nov 22 13:41:22 2002 @@ -1,7 +1,7 @@ /* SCTP kernel reference Implementation * Copyright (c) Cisco 1999,2000 * Copyright (c) Motorola 1999,2000,2001 - * Copyright (c) International Business Machines Corp., 2001 + * Copyright (c) International Business Machines Corp., 2001,2002 * Copyright (c) La Monte H.P. Yarroll 2001 * * This file is part of the SCTP kernel reference implementation. @@ -52,7 +52,7 @@ #include /* Forward declarations for internal helpers. */ -static int sctp_copy_one_addr(sctp_bind_addr_t *, sockaddr_storage_t *, +static int sctp_copy_one_addr(sctp_bind_addr_t *, union sctp_addr *, sctp_scope_t scope, int priority, int flags); static void sctp_bind_addr_clean(sctp_bind_addr_t *); @@ -143,7 +143,7 @@ } /* Add an address to the bind address list in the SCTP_bind_addr structure. */ -int sctp_add_bind_addr(sctp_bind_addr_t *bp, sockaddr_storage_t *new, +int sctp_add_bind_addr(sctp_bind_addr_t *bp, union sctp_addr *new, int priority) { struct sockaddr_storage_list *addr; @@ -171,7 +171,7 @@ /* Delete an address from the bind address list in the SCTP_bind_addr * structure. */ -int sctp_del_bind_addr(sctp_bind_addr_t *bp, sockaddr_storage_t *del_addr) +int sctp_del_bind_addr(sctp_bind_addr_t *bp, union sctp_addr *del_addr) { struct list_head *pos, *temp; struct sockaddr_storage_list *addr; @@ -196,18 +196,16 @@ * * The second argument is the return value for the length. */ -sctpParam_t sctp_bind_addrs_to_raw(const sctp_bind_addr_t *bp, int *addrs_len, - int priority) +union sctp_params sctp_bind_addrs_to_raw(const sctp_bind_addr_t *bp, + int *addrs_len, int priority) { - sctpParam_t addrparms; - sctpParam_t retval; + union sctp_params addrparms; + union sctp_params retval; int addrparms_len; sctp_addr_param_t rawaddr; int len; struct sockaddr_storage_list *addr; struct list_head *pos; - - retval.v = NULL; addrparms_len = 0; len = 0; @@ -216,11 +214,11 @@ len += sizeof(sctp_addr_param_t); } - addrparms.v = kmalloc(len, priority); - if (!addrparms.v) + retval.v = kmalloc(len, priority); + if (!retval.v) goto end_raw; - retval = addrparms; + addrparms = retval; list_for_each(pos, &bp->address_list) { addr = list_entry(pos, struct sockaddr_storage_list, list); @@ -244,7 +242,7 @@ { sctp_addr_param_t *rawaddr; sctp_paramhdr_t *param; - sockaddr_storage_t addr; + union sctp_addr addr; int retval = 0; int len; @@ -254,7 +252,7 @@ rawaddr = (sctp_addr_param_t *)raw_addr_list; switch (param->type) { - case SCTP_PARAM_IPV4_ADDRESS: + case SCTP_PARAM_IPV4_ADDRESS: case SCTP_PARAM_IPV6_ADDRESS: sctp_param2sockaddr(&addr, rawaddr, port); retval = sctp_add_bind_addr(bp, &addr, priority); @@ -284,15 +282,16 @@ * 2nd Level Abstractions ********************************************************************/ -/* Does this contain a specified address? */ -int sctp_bind_addr_has_addr(sctp_bind_addr_t *bp, const sockaddr_storage_t *addr) +/* Does this contain a specified address? Allow wildcarding. */ +int sctp_bind_addr_match(sctp_bind_addr_t *bp, const union sctp_addr *addr, + struct sctp_opt *opt) { struct sockaddr_storage_list *laddr; struct list_head *pos; list_for_each(pos, &bp->address_list) { laddr = list_entry(pos, struct sockaddr_storage_list, list); - if (sctp_cmp_addr(&laddr->a, addr)) + if (opt->pf->cmp_addr(&laddr->a, addr, opt)) return 1; } @@ -300,7 +299,7 @@ } /* Copy out addresses from the global local address list. */ -static int sctp_copy_one_addr(sctp_bind_addr_t *dest, sockaddr_storage_t *addr, +static int sctp_copy_one_addr(sctp_bind_addr_t *dest, union sctp_addr *addr, sctp_scope_t scope, int priority, int flags) { sctp_protocol_t *proto = sctp_get_protocol(); @@ -325,94 +324,33 @@ return error; } -/* Is addr one of the wildcards? */ -int sctp_is_any(const sockaddr_storage_t *addr) +/* Is this a wildcard address? */ +int sctp_is_any(const union sctp_addr *addr) { - int retval = 0; - - switch (addr->sa.sa_family) { - case AF_INET: - if (INADDR_ANY == addr->v4.sin_addr.s_addr) - retval = 1; - break; - - case AF_INET6: - SCTP_V6( - if (IPV6_ADDR_ANY == - sctp_ipv6_addr_type(&addr->v6.sin6_addr)) - retval = 1; - ); - break; - - default: - break; - }; - - return retval; + struct sctp_func *af = sctp_get_af_specific(addr->sa.sa_family); + if (!af) + return 0; + return af->is_any(addr); } /* Is 'addr' valid for 'scope'? */ -int sctp_in_scope(const sockaddr_storage_t *addr, sctp_scope_t scope) +int sctp_in_scope(const union sctp_addr *addr, sctp_scope_t scope) { sctp_scope_t addr_scope = sctp_scope(addr); - switch (addr->sa.sa_family) { - case AF_INET: - /* According to the SCTP IPv4 address scoping document - - * , the scope has - * a heirarchy of 5 levels: - * Level 0 - unusable SCTP addresses - * Level 1 - loopback address - * Level 2 - link-local addresses - * Level 3 - private addresses. - * Level 4 - global addresses - * For INIT and INIT-ACK address list, let L be the level of - * of requested destination address, sender and receiver - * SHOULD include all of its addresses with level greater - * than or equal to L. - */ - /* The unusable SCTP addresses will not be considered with - * any defined scopes. - */ - if (SCTP_SCOPE_UNUSABLE == addr_scope) - return 0; - - /* Note that we are assuming that the scoping are the same - * for both IPv4 addresses and IPv6 addresses, i.e., if the - * scope is link local, both IPv4 link local addresses and - * IPv6 link local addresses would be treated as in the - * scope. There is no filtering for IPv4 vs. IPv6 addresses - * based on scoping alone. - */ - if (addr_scope <= scope) - return 1; - break; - - case AF_INET6: - /* FIXME: - * This is almost certainly wrong since scopes have an - * heirarchy. I don't know what RFC to look at. - * There may be some guidance in the SCTP implementors - * guide (an Internet Draft as of October 2001). - * - * Further verification on the correctness of the IPv6 - * scoping is needed. According to the IPv6 scoping draft, - * the link local and site local address may require - * further scoping. - * - * Is the heirachy of the IPv6 scoping the same as what's - * defined for IPv4? - * If the same heirarchy indeed applies to both famiies, - * this function can be simplified with one set of code. - * (see the comments for IPv4 above) - */ - if (addr_scope <= scope) - return 1; - break; - - default: + /* The unusable SCTP addresses will not be considered with + * any defined scopes. + */ + if (SCTP_SCOPE_UNUSABLE == addr_scope) return 0; - }; + /* + * For INIT and INIT-ACK address list, let L be the level of + * of requested destination address, sender and receiver + * SHOULD include all of its addresses with level greater + * than or equal to L. + */ + if (addr_scope <= scope) + return 1; return 0; } @@ -422,112 +360,13 @@ ********************************************************************/ /* What is the scope of 'addr'? */ -sctp_scope_t sctp_scope(const sockaddr_storage_t *addr) +sctp_scope_t sctp_scope(const union sctp_addr *addr) { - sctp_scope_t retval = SCTP_SCOPE_GLOBAL; - - switch (addr->sa.sa_family) { - case AF_INET: - /* We are checking the loopback, private and other address - * scopes as defined in RFC 1918. - * The IPv4 scoping is based on the draft for SCTP IPv4 - * scoping . - * The set of SCTP address scope hopefully can cover both - * types of addresses. - */ - - /* Should IPv4 scoping be a sysctl configurable option - * so users can turn it off (default on) for certain - * unconventional networking environments? - */ + struct sctp_func *af; - /* Check for unusable SCTP addresses. */ - if (IS_IPV4_UNUSABLE_ADDRESS(&addr->v4.sin_addr.s_addr)) { - retval = SCTP_SCOPE_UNUSABLE; - } else if (LOOPBACK(addr->v4.sin_addr.s_addr)) { - retval = SCTP_SCOPE_LOOPBACK; - } else if (IS_IPV4_LINK_ADDRESS(&addr->v4.sin_addr.s_addr)) { - retval = SCTP_SCOPE_LINK; - } else if (IS_IPV4_PRIVATE_ADDRESS(&addr->v4.sin_addr.s_addr)) { - retval = SCTP_SCOPE_PRIVATE; - } else { - retval = SCTP_SCOPE_GLOBAL; - } - break; - - case AF_INET6: - { - SCTP_V6( - int v6scope; - v6scope = ipv6_addr_scope((struct in6_addr *) - &addr->v6.sin6_addr); - /* The IPv6 scope is really a set of bit - * fields. See IFA_* in . - * Mapping them to the generic SCTP scope - * set is an attempt to have code - * consistencies with the IPv4 scoping. - */ - switch (v6scope) { - case IFA_HOST: - retval = SCTP_SCOPE_LOOPBACK; - break; - - case IFA_LINK: - retval = SCTP_SCOPE_LINK; - break; - - case IFA_SITE: - retval = SCTP_SCOPE_PRIVATE; - break; - - default: - retval = SCTP_SCOPE_GLOBAL; - break; - }; - ); - break; - } - - default: - retval = SCTP_SCOPE_GLOBAL; - break; - }; - - return retval; -} - -/* This function checks if the address is a valid address to be used for - * SCTP. - * - * Output: - * Return 0 - If the address is a non-unicast or an illegal address. - * Return 1 - If the address is a unicast. - */ -int sctp_addr_is_valid(const sockaddr_storage_t *addr) -{ - unsigned short sa_family = addr->sa.sa_family; - - switch (sa_family) { - case AF_INET: - /* Is this a non-unicast address or a unusable SCTP address? */ - if (IS_IPV4_UNUSABLE_ADDRESS(&addr->v4.sin_addr.s_addr)) - return 0; - break; - - case AF_INET6: - SCTP_V6( - { - int ret = sctp_ipv6_addr_type(&addr->v6.sin6_addr); - - /* Is this a non-unicast address */ - if (!(ret & IPV6_ADDR_UNICAST)) - return 0; - break; - }); - - default: - return 0; - }; + af = sctp_get_af_specific(addr->sa.sa_family); + if (!af) + return SCTP_SCOPE_UNUSABLE; - return 1; + return af->scope((union sctp_addr *)addr); } diff -Nru a/net/sctp/endpointola.c b/net/sctp/endpointola.c --- a/net/sctp/endpointola.c Fri Nov 22 13:41:18 2002 +++ b/net/sctp/endpointola.c Fri Nov 22 13:41:18 2002 @@ -1,7 +1,7 @@ /* SCTP kernel reference Implementation * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001 International Business Machines, Corp. + * Copyright (c) 2001-2002 International Business Machines, Corp. * Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 Nokia, Inc. * Copyright (c) 2001 La Monte H.P. Yarroll @@ -237,13 +237,14 @@ /* Is this the endpoint we are looking for? */ sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *ep, - const sockaddr_storage_t *laddr) + const union sctp_addr *laddr) { sctp_endpoint_t *retval; sctp_read_lock(&ep->base.addr_lock); if (ep->base.bind_addr.port == laddr->v4.sin_port) { - if (sctp_bind_addr_has_addr(&ep->base.bind_addr, laddr)) { + if (sctp_bind_addr_match(&ep->base.bind_addr, laddr, + sctp_sk(ep->base.sk))) { retval = ep; goto out; } @@ -262,7 +263,7 @@ */ sctp_association_t *__sctp_endpoint_lookup_assoc( const sctp_endpoint_t *endpoint, - const sockaddr_storage_t *paddr, + const union sctp_addr *paddr, sctp_transport_t **transport) { int rport; @@ -289,7 +290,7 @@ /* Lookup association on an endpoint based on a peer address. BH-safe. */ sctp_association_t *sctp_endpoint_lookup_assoc(const sctp_endpoint_t *ep, - const sockaddr_storage_t *paddr, + const union sctp_addr *paddr, sctp_transport_t **transport) { sctp_association_t *asoc; @@ -301,6 +302,30 @@ return asoc; } +/* Look for any peeled off association from the endpoint that matches the + * given peer address. + */ +int sctp_endpoint_is_peeled_off(sctp_endpoint_t *ep, + const union sctp_addr *paddr) +{ + struct list_head *pos; + struct sockaddr_storage_list *addr; + sctp_bind_addr_t *bp; + + sctp_read_lock(&ep->base.addr_lock); + bp = &ep->base.bind_addr; + list_for_each(pos, &bp->address_list) { + addr = list_entry(pos, struct sockaddr_storage_list, list); + if (sctp_has_association(&addr->a, paddr)) { + sctp_read_unlock(&ep->base.addr_lock); + return 1; + } + } + sctp_read_unlock(&ep->base.addr_lock); + + return 0; +} + /* Do delayed input processing. This is scheduled by sctp_rcv(). * This may be called on BH or task time. */ @@ -316,13 +341,13 @@ int error = 0; if (ep->base.dead) - goto out; + return; asoc = NULL; inqueue = &ep->base.inqueue; sk = ep->base.sk; - while (NULL != (chunk = sctp_pop_inqueue(inqueue))) { + while (NULL != (chunk = sctp_pop_inqueue(inqueue))) { subtype.chunk = chunk->chunk_hdr->type; /* We might have grown an association since last we @@ -350,25 +375,16 @@ if (chunk->transport) chunk->transport->last_time_heard = jiffies; - /* FIX ME We really would rather NOT have to use - * GFP_ATOMIC. - */ error = sctp_do_sm(SCTP_EVENT_T_CHUNK, subtype, state, ep, asoc, chunk, GFP_ATOMIC); - if (error != 0) - goto err_out; + if (error && chunk) + chunk->pdiscard = 1; /* Check to see if the endpoint is freed in response to * the incoming chunk. If so, get out of the while loop. */ if (!sctp_sk(sk)->ep) - goto out; + break; } - -err_out: - /* Is this the right way to pass errors up to the ULP? */ - if (error) - ep->base.sk->err = -error; -out: } diff -Nru a/net/sctp/input.c b/net/sctp/input.c --- a/net/sctp/input.c Fri Nov 22 13:41:17 2002 +++ b/net/sctp/input.c Fri Nov 22 13:41:17 2002 @@ -60,64 +60,11 @@ /* Forward declarations for internal helpers. */ static int sctp_rcv_ootb(struct sk_buff *); sctp_association_t *__sctp_rcv_lookup(struct sk_buff *skb, - const sockaddr_storage_t *laddr, - const sockaddr_storage_t *paddr, + const union sctp_addr *laddr, + const union sctp_addr *paddr, sctp_transport_t **transportp); -sctp_endpoint_t *__sctp_rcv_lookup_endpoint(const sockaddr_storage_t *laddr); +sctp_endpoint_t *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr); -/* Initialize a sockaddr_storage from in incoming skb. - * FIXME: This belongs with AF specific sctp_func_t. --jgrimm - */ -static sockaddr_storage_t *sctp_sockaddr_storage_init(sockaddr_storage_t *addr, - const struct sk_buff *skb, - int is_saddr) -{ - sockaddr_storage_t *ret = NULL; - void *to, *saddr, *daddr; - __u16 *port; - size_t len; - struct sctphdr *sh; - - switch (skb->nh.iph->version) { - case 4: - to = &addr->v4.sin_addr.s_addr; - port = &addr->v4.sin_port; - saddr = &skb->nh.iph->saddr; - daddr = &skb->nh.iph->daddr; - len = sizeof(struct in_addr); - addr->v4.sin_family = AF_INET; - break; - - case 6: - SCTP_V6( - to = &addr->v6.sin6_addr; - port = &addr->v6.sin6_port; - saddr = &skb->nh.ipv6h->saddr; - daddr = &skb->nh.ipv6h->daddr; - len = sizeof(struct in6_addr); - addr->v6.sin6_family = AF_INET6; - addr->v6.sin6_flowinfo = 0; /* FIXME */ - addr->v6.sin6_scope_id = 0; /* FIXME */ - break; - ) - - default: - goto out; - }; - - sh = (struct sctphdr *) skb->h.raw; - if (is_saddr) { - *port = ntohs(sh->source); - memcpy(to, saddr, len); - } else { - *port = ntohs(sh->dest); - memcpy(to, daddr, len); - } - - ret = addr; -out: - return ret; -} /* Calculate the SCTP checksum of an SCTP packet. */ static inline int sctp_rcv_checksum(struct sk_buff *skb) @@ -147,8 +94,9 @@ sctp_transport_t *transport = NULL; sctp_chunk_t *chunk; struct sctphdr *sh; - sockaddr_storage_t src; - sockaddr_storage_t dest; + union sctp_addr src; + union sctp_addr dest; + struct sctp_func *af; int ret = 0; if (skb->pkt_type!=PACKET_HOST) @@ -163,10 +111,15 @@ if (sctp_rcv_checksum(skb) < 0) goto bad_packet; - skb_pull(skb, sizeof(struct sctphdr)); + skb_pull(skb, sizeof(struct sctphdr)); + + af = sctp_get_af_specific(ipver2af(skb->nh.iph->version)); + if (unlikely(!af)) + goto bad_packet; - sctp_sockaddr_storage_init(&src, skb, 1); - sctp_sockaddr_storage_init(&dest, skb, 0); + /* Initialize local addresses for lookups. */ + af->from_skb(&src, skb, 1); + af->from_skb(&dest, skb, 0); /* If the packet is to or from a non-unicast address, * silently discard the packet. @@ -179,7 +132,7 @@ * IP broadcast addresses cannot be used in an SCTP transport * address." */ - if (!sctp_addr_is_valid(&src) || !sctp_addr_is_valid(&dest)) + if (!af->addr_valid(&src) || !af->addr_valid(&dest)) goto discard_it; asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport); @@ -219,7 +172,7 @@ chunk->sctp_hdr = sh; /* Set the source and destination addresses of the incoming chunk. */ - sctp_init_addrs(chunk); + sctp_init_addrs(chunk, &src, &dest); /* Remember where we came from. */ chunk->transport = transport; @@ -431,7 +384,7 @@ } /* Look up an endpoint. */ -sctp_endpoint_t *__sctp_rcv_lookup_endpoint(const sockaddr_storage_t *laddr) +sctp_endpoint_t *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr) { sctp_hashbucket_t *head; sctp_endpoint_common_t *epb; @@ -523,8 +476,8 @@ } /* Look up an association. */ -sctp_association_t *__sctp_lookup_association(const sockaddr_storage_t *laddr, - const sockaddr_storage_t *paddr, +sctp_association_t *__sctp_lookup_association(const union sctp_addr *laddr, + const union sctp_addr *paddr, sctp_transport_t **transportp) { sctp_hashbucket_t *head; @@ -559,8 +512,8 @@ } /* Look up an association. BH-safe. */ -sctp_association_t *sctp_lookup_association(const sockaddr_storage_t *laddr, - const sockaddr_storage_t *paddr, +sctp_association_t *sctp_lookup_association(const union sctp_addr *laddr, + const union sctp_addr *paddr, sctp_transport_t **transportp) { sctp_association_t *asoc; @@ -568,13 +521,13 @@ sctp_local_bh_disable(); asoc = __sctp_lookup_association(laddr, paddr, transportp); sctp_local_bh_enable(); - + return asoc; } /* Is there an association matching the given local and peer addresses? */ -int sctp_has_association(const sockaddr_storage_t *laddr, - const sockaddr_storage_t *paddr) +int sctp_has_association(const union sctp_addr *laddr, + const union sctp_addr *paddr) { sctp_association_t *asoc; sctp_transport_t *transport; @@ -606,21 +559,19 @@ * in certain circumstances. * */ -static sctp_association_t *__sctp_rcv_initack_lookup(struct sk_buff *skb, - const sockaddr_storage_t *laddr, sctp_transport_t **transportp) +static sctp_association_t *__sctp_rcv_init_lookup(struct sk_buff *skb, + const union sctp_addr *laddr, sctp_transport_t **transportp) { sctp_association_t *asoc; - sockaddr_storage_t addr; - sockaddr_storage_t *paddr = &addr; + union sctp_addr addr; + union sctp_addr *paddr = &addr; struct sctphdr *sh = (struct sctphdr *) skb->h.raw; sctp_chunkhdr_t *ch; - __u8 *ch_end, *data; - sctp_paramhdr_t *parm; + union sctp_params params; + sctp_init_chunk_t *init; ch = (sctp_chunkhdr_t *) skb->data; - ch_end = ((__u8 *) ch) + WORD_ROUND(ntohs(ch->length)); - /* If this is INIT/INIT-ACK look inside the chunk too. */ switch (ch->type) { case SCTP_CID_INIT: @@ -646,24 +597,17 @@ /* Find the start of the TLVs and the end of the chunk. This is * the region we search for address parameters. */ - data = skb->data + sizeof(sctp_init_chunk_t); - - /* See sctp_process_init() for how to go thru TLVs. */ - while (data < ch_end) { - parm = (sctp_paramhdr_t *)data; - - if (!parm->length) - break; + init = (sctp_init_chunk_t *)skb->data; - data += WORD_ROUND(ntohs(parm->length)); + /* Walk the parameters looking for embedded addresses. */ + sctp_walk_params(params, init, init_hdr.params) { /* Note: Ignoring hostname addresses. */ - if ((SCTP_PARAM_IPV4_ADDRESS != parm->type) && - (SCTP_PARAM_IPV6_ADDRESS != parm->type)) + if ((SCTP_PARAM_IPV4_ADDRESS != params.p->type) && + (SCTP_PARAM_IPV6_ADDRESS != params.p->type)) continue; - sctp_param2sockaddr(paddr, (sctp_addr_param_t *)parm, - ntohs(sh->source)); + sctp_param2sockaddr(paddr, params.addr, ntohs(sh->source)); asoc = __sctp_lookup_association(laddr, paddr, transportp); if (asoc) return asoc; @@ -674,20 +618,20 @@ /* Lookup an association for an inbound skb. */ sctp_association_t *__sctp_rcv_lookup(struct sk_buff *skb, - const sockaddr_storage_t *paddr, - const sockaddr_storage_t *laddr, + const union sctp_addr *paddr, + const union sctp_addr *laddr, sctp_transport_t **transportp) { sctp_association_t *asoc; asoc = __sctp_lookup_association(laddr, paddr, transportp); - /* Further lookup for INIT-ACK packet. + /* Further lookup for INIT/INIT-ACK packets. * SCTP Implementors Guide, 2.18 Handling of address * parameters within the INIT or INIT-ACK. */ if (!asoc) - asoc = __sctp_rcv_initack_lookup(skb, laddr, transportp); + asoc = __sctp_rcv_init_lookup(skb, laddr, transportp); return asoc; } diff -Nru a/net/sctp/ipv6.c b/net/sctp/ipv6.c --- a/net/sctp/ipv6.c Fri Nov 22 13:41:21 2002 +++ b/net/sctp/ipv6.c Fri Nov 22 13:41:21 2002 @@ -172,16 +172,16 @@ /* Returns the dst cache entry for the given source and destination ip * addresses. */ -struct dst_entry *sctp_v6_get_dst(sockaddr_storage_t *daddr, - sockaddr_storage_t *saddr) +struct dst_entry *sctp_v6_get_dst(union sctp_addr *daddr, + union sctp_addr *saddr) { struct dst_entry *dst; - struct flowi fl = { .nl_u = { .ip6_u = { .daddr = &daddr->v6.sin6_addr, - } } }; + struct flowi fl = { + .nl_u = { .ip6_u = { .daddr = &daddr->v6.sin6_addr, } } }; SCTP_DEBUG_PRINTK("%s: DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", - __FUNCTION__, NIP6(fl.fl6_dst)); + __FUNCTION__, NIP6(fl.fl6_dst)); if (saddr) { fl.fl6_src = &saddr->v6.sin6_addr; @@ -206,12 +206,147 @@ return dst; } -/* Check if the dst entry's source addr matches the given source addr. */ -int sctp_v6_cmp_saddr(struct dst_entry *dst, sockaddr_storage_t *saddr) +/* Make a copy of all potential local addresses. */ +static void sctp_v6_copy_addrlist(struct list_head *addrlist, + struct net_device *dev) +{ + struct inet6_dev *in6_dev; + struct inet6_ifaddr *ifp; + struct sockaddr_storage_list *addr; + + read_lock(&addrconf_lock); + if ((in6_dev = __in6_dev_get(dev)) == NULL) { + read_unlock(&addrconf_lock); + return; + } + + read_lock(&in6_dev->lock); + for (ifp = in6_dev->addr_list; ifp; ifp = ifp->if_next) { + /* Add the address to the local list. */ + addr = t_new(struct sockaddr_storage_list, GFP_ATOMIC); + if (addr) { + addr->a.v6.sin6_family = AF_INET6; + addr->a.v6.sin6_port = 0; + addr->a.v6.sin6_addr = ifp->addr; + INIT_LIST_HEAD(&addr->list); + list_add_tail(&addr->list, addrlist); + } + } + + read_unlock(&in6_dev->lock); + read_unlock(&addrconf_lock); +} + +/* Initialize a sockaddr_storage from in incoming skb. */ +static void sctp_v6_from_skb(union sctp_addr *addr,struct sk_buff *skb, + int is_saddr) +{ + void *from; + __u16 *port; + struct sctphdr *sh; + + port = &addr->v6.sin6_port; + addr->v6.sin6_family = AF_INET6; + addr->v6.sin6_flowinfo = 0; /* FIXME */ + addr->v6.sin6_scope_id = 0; /* FIXME */ + + sh = (struct sctphdr *) skb->h.raw; + if (is_saddr) { + *port = ntohs(sh->source); + from = &skb->nh.ipv6h->saddr; + } else { + *port = ntohs(sh->dest); + from = &skb->nh.ipv6h->daddr; + } + ipv6_addr_copy(&addr->v6.sin6_addr, from); +} + +/* Initialize a sctp_addr from a dst_entry. */ +static void sctp_v6_dst_saddr(union sctp_addr *addr, struct dst_entry *dst) { struct rt6_info *rt = (struct rt6_info *)dst; + addr->sa.sa_family = AF_INET6; + ipv6_addr_copy(&addr->v6.sin6_addr, &rt->rt6i_src.addr); +} + +/* Compare addresses exactly. Well.. almost exactly; ignore scope_id + * for now. FIXME. + */ +static int sctp_v6_cmp_addr(const union sctp_addr *addr1, + const union sctp_addr *addr2) +{ + int match; + if (addr1->sa.sa_family != addr2->sa.sa_family) + return 0; + match = !ipv6_addr_cmp((struct in6_addr *)&addr1->v6.sin6_addr, + (struct in6_addr *)&addr2->v6.sin6_addr); + + return match; +} + +/* Initialize addr struct to INADDR_ANY. */ +static void sctp_v6_inaddr_any(union sctp_addr *addr, unsigned short port) +{ + memset(addr, 0x00, sizeof(union sctp_addr)); + addr->v6.sin6_family = AF_INET6; + addr->v6.sin6_port = port; +} + +/* Is this a wildcard address? */ +static int sctp_v6_is_any(const union sctp_addr *addr) +{ + int type; + type = ipv6_addr_type((struct in6_addr *)&addr->v6.sin6_addr); + return IPV6_ADDR_ANY == type; +} + +/* This function checks if the address is a valid address to be used for + * SCTP. + * + * Output: + * Return 0 - If the address is a non-unicast or an illegal address. + * Return 1 - If the address is a unicast. + */ +static int sctp_v6_addr_valid(union sctp_addr *addr) +{ + int ret = sctp_ipv6_addr_type(&addr->v6.sin6_addr); + + /* FIXME: v4-mapped-v6 address support. */ + + /* Is this a non-unicast address */ + if (!(ret & IPV6_ADDR_UNICAST)) + return 0; + + return 1; +} + +/* What is the scope of 'addr'? */ +static sctp_scope_t sctp_v6_scope(union sctp_addr *addr) +{ + int v6scope; + sctp_scope_t retval; + + /* The IPv6 scope is really a set of bit fields. + * See IFA_* in . Map to a generic SCTP scope. + */ + + v6scope = ipv6_addr_scope(&addr->v6.sin6_addr); + switch (v6scope) { + case IFA_HOST: + retval = SCTP_SCOPE_LOOPBACK; + break; + case IFA_LINK: + retval = SCTP_SCOPE_LINK; + break; + case IFA_SITE: + retval = SCTP_SCOPE_PRIVATE; + break; + default: + retval = SCTP_SCOPE_GLOBAL; + break; + }; - return ipv6_addr_cmp(&rt->rt6i_src.addr, &saddr->v6.sin6_addr); + return retval; } /* Initialize a PF_INET6 socket msg_name. */ @@ -227,12 +362,13 @@ } /* Initialize a PF_INET msgname from a ulpevent. */ -static void sctp_inet6_event_msgname(sctp_ulpevent_t *event, char *msgname, int *addrlen) +static void sctp_inet6_event_msgname(sctp_ulpevent_t *event, char *msgname, + int *addrlen) { struct sockaddr_in6 *sin6, *sin6from; if (msgname) { - sockaddr_storage_t *addr; + union sctp_addr *addr; sctp_inet6_msgname(msgname, addrlen); sin6 = (struct sockaddr_in6 *)msgname; @@ -288,6 +424,49 @@ } } +/* Do we support this AF? */ +static int sctp_inet6_af_supported(sa_family_t family) +{ + /* FIXME: v4-mapped-v6 addresses. The I-D is still waffling + * on what to do with sockaddr formats for PF_INET6 sockets. + * For now assume we'll support both. + */ + switch (family) { + case AF_INET6: + case AF_INET: + return 1; + default: + return 0; + } +} + +/* Address matching with wildcards allowed. This extra level + * of indirection lets us choose whether a PF_INET6 should + * disallow any v4 addresses if we so choose. + */ +static int sctp_inet6_cmp_addr(const union sctp_addr *addr1, + const union sctp_addr *addr2, + struct sctp_opt *opt) +{ + struct sctp_func *af1, *af2; + + af1 = sctp_get_af_specific(addr1->sa.sa_family); + af2 = sctp_get_af_specific(addr2->sa.sa_family); + + if (!af1 || !af2) + return 0; + /* Today, wildcard AF_INET/AF_INET6. */ + if (sctp_is_any(addr1) || sctp_is_any(addr2)) + return 1; + + if (addr1->sa.sa_family != addr2->sa.sa_family) + return 0; + + return af1->cmp_addr(addr1, addr2); +} + + + static struct proto_ops inet6_seqpacket_ops = { .family = PF_INET6, .release = inet6_release, @@ -327,7 +506,14 @@ .setsockopt = ipv6_setsockopt, .getsockopt = ipv6_getsockopt, .get_dst = sctp_v6_get_dst, - .cmp_saddr = sctp_v6_cmp_saddr, + .copy_addrlist = sctp_v6_copy_addrlist, + .from_skb = sctp_v6_from_skb, + .dst_saddr = sctp_v6_dst_saddr, + .cmp_addr = sctp_v6_cmp_addr, + .scope = sctp_v6_scope, + .addr_valid = sctp_v6_addr_valid, + .inaddr_any = sctp_v6_inaddr_any, + .is_any = sctp_v6_is_any, .net_header_len = sizeof(struct ipv6hdr), .sockaddr_len = sizeof(struct sockaddr_in6), .sa_family = AF_INET6, @@ -336,6 +522,9 @@ static sctp_pf_t sctp_pf_inet6_specific = { .event_msgname = sctp_inet6_event_msgname, .skb_msgname = sctp_inet6_skb_msgname, + .af_supported = sctp_inet6_af_supported, + .cmp_addr = sctp_inet6_cmp_addr, + .af = &sctp_ipv6_specific, }; /* Initialize IPv6 support and register with inet6 stack. */ diff -Nru a/net/sctp/output.c b/net/sctp/output.c --- a/net/sctp/output.c Fri Nov 22 13:41:18 2002 +++ b/net/sctp/output.c Fri Nov 22 13:41:18 2002 @@ -366,18 +366,13 @@ */ sh->checksum = htonl(crc32); + /* FIXME: Delete the rest of this switch statement once phase 2 + * of address selection (ipv6 support) drops in. + */ switch (transport->ipaddr.sa.sa_family) { - case AF_INET: - inet_sk(sk)->daddr = transport->ipaddr.v4.sin_addr.s_addr; - break; - case AF_INET6: SCTP_V6(inet6_sk(sk)->daddr = transport->ipaddr.v6.sin6_addr;) break; - - default: - /* This is bogus address type, just bail. */ - break; }; /* IP layer ECN support @@ -430,10 +425,12 @@ dst = transport->dst; if (!dst || dst->obsolete) { - sctp_transport_route(transport, NULL); + sctp_transport_route(transport, NULL, sctp_sk(sk)); } nskb->dst = dst_clone(transport->dst); + if (!nskb->dst) + goto no_route; SCTP_DEBUG_PRINTK("***sctp_transmit_packet*** skb length %d\n", nskb->len); @@ -441,6 +438,11 @@ out: packet->size = SCTP_IP_OVERHEAD; return err; +no_route: + kfree_skb(nskb); + IP_INC_STATS_BH(IpOutNoRoutes); + err = -EHOSTUNREACH; + goto out; } /******************************************************************** diff -Nru a/net/sctp/outqueue.c b/net/sctp/outqueue.c --- a/net/sctp/outqueue.c Fri Nov 22 13:41:18 2002 +++ b/net/sctp/outqueue.c Fri Nov 22 13:41:18 2002 @@ -678,7 +678,7 @@ if (!new_transport) { new_transport = asoc->peer.active_path; - } else if (!new_transport->state.active) { + } else if (!new_transport->active) { /* If the chunk is Heartbeat, send it to * chunk->transport, even it's inactive. */ @@ -835,7 +835,7 @@ */ new_transport = chunk->transport; if (new_transport == NULL || - !new_transport->state.active) + !new_transport->active) new_transport = asoc->peer.active_path; /* Change packets if necessary. */ @@ -1404,7 +1404,7 @@ /* Mark the destination transport address as * active if it is not so marked. */ - if (!transport->state.active) { + if (!transport->active) { sctp_assoc_control_transport( transport->asoc, transport, diff -Nru a/net/sctp/primitive.c b/net/sctp/primitive.c --- a/net/sctp/primitive.c Fri Nov 22 13:41:23 2002 +++ b/net/sctp/primitive.c Fri Nov 22 13:41:23 2002 @@ -38,6 +38,7 @@ * La Monte H.P. Yarroll * Narasimha Budihal * Karl Knutson + * Ardelle Fan * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -180,6 +181,28 @@ */ DECLARE_PRIMITIVE(SEND); + +/* 10.1 ULP-to-SCTP + * J) Request Heartbeat + * + * Format: REQUESTHEARTBEAT(association id, destination transport address) + * + * -> result + * + * Instructs the local endpoint to perform a HeartBeat on the specified + * destination transport address of the given association. The returned + * result should indicate whether the transmission of the HEARTBEAT + * chunk to the destination address is successful. + * + * Mandatory attributes: + * + * o association id - local handle to the SCTP association + * + * o destination transport address - the transport address of the + * asociation on which a heartbeat should be issued. + */ + +DECLARE_PRIMITIVE(REQUESTHEARTBEAT); /* COMMENT BUG. Find out where this is mentioned in the spec. */ int sctp_other_icmp_unreachfrag(sctp_association_t *asoc, void *arg) diff -Nru a/net/sctp/protocol.c b/net/sctp/protocol.c --- a/net/sctp/protocol.c Fri Nov 22 13:41:21 2002 +++ b/net/sctp/protocol.c Fri Nov 22 13:41:21 2002 @@ -1,46 +1,46 @@ /* SCTP kernel reference Implementation * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001 International Business Machines, Corp. + * Copyright (c) 2001-2002 International Business Machines, Corp. * Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 Nokia, Inc. * Copyright (c) 2001 La Monte H.P. Yarroll - * + * * This file is part of the SCTP kernel reference Implementation - * - * Initialization/cleanup for SCTP protocol support. - * - * The SCTP reference implementation is free software; - * you can redistribute it and/or modify it under the terms of + * + * Initialization/cleanup for SCTP protocol support. + * + * The SCTP reference implementation 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. - * - * The SCTP reference implementation is distributed in the hope that it + * + * The SCTP reference implementation 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 GNU CC; see the file COPYING. If not, write to * the Free Software Foundation, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * + * Boston, MA 02111-1307, USA. + * * Please send any bug reports or fixes you make to the * email address(es): * lksctp developers - * + * * Or submit a bug report through the following website: * http://www.sf.net/projects/lksctp * - * Written or modified by: + * Written or modified by: * La Monte H.P. Yarroll * Karl Knutson * Jon Grimm * Sridhar Samudrala * Daisy Chang - * + * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. */ @@ -103,8 +103,8 @@ /* Private helper to extract ipv4 address and stash them in * the protocol structure. */ -static inline void sctp_v4_get_local_addr_list(sctp_protocol_t *proto, - struct net_device *dev) +static void sctp_v4_copy_addrlist(struct list_head *addrlist, + struct net_device *dev) { struct in_device *in_dev; struct in_ifaddr *ifa; @@ -117,7 +117,6 @@ } read_lock(&in_dev->lock); - for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { /* Add the address to the local list. */ addr = t_new(struct sockaddr_storage_list, GFP_ATOMIC); @@ -126,7 +125,7 @@ addr->a.v4.sin_family = AF_INET; addr->a.v4.sin_port = 0; addr->a.v4.sin_addr.s_addr = ifa->ifa_local; - list_add_tail(&addr->list, &proto->local_addr_list); + list_add_tail(&addr->list, addrlist); } } @@ -134,56 +133,21 @@ read_unlock(&inetdev_lock); } -/* Private helper to extract ipv6 address and stash them in - * the protocol structure. - * FIXME: Make this an address family function. - */ -static inline void sctp_v6_get_local_addr_list(sctp_protocol_t *proto, - struct net_device *dev) -{ -#ifdef SCTP_V6_SUPPORT - /* FIXME: The testframe doesn't support this function. */ -#ifndef TEST_FRAME - struct inet6_dev *in6_dev; - struct inet6_ifaddr *ifp; - struct sockaddr_storage_list *addr; - - read_lock(&addrconf_lock); - if ((in6_dev = __in6_dev_get(dev)) == NULL) { - read_unlock(&addrconf_lock); - return; - } - - read_lock_bh(&in6_dev->lock); - for (ifp = in6_dev->addr_list; ifp; ifp = ifp->if_next) { - /* Add the address to the local list. */ - addr = t_new(struct sockaddr_storage_list, GFP_ATOMIC); - if (addr) { - addr->a.v6.sin6_family = AF_INET6; - addr->a.v6.sin6_port = 0; - addr->a.v6.sin6_addr = ifp->addr; - INIT_LIST_HEAD(&addr->list); - list_add_tail(&addr->list, &proto->local_addr_list); - } - } - - read_unlock_bh(&in6_dev->lock); - read_unlock(&addrconf_lock); -#endif /* TEST_FRAME */ -#endif /* SCTP_V6_SUPPORT */ -} - /* Extract our IP addresses from the system and stash them in the * protocol structure. */ static void __sctp_get_local_addr_list(sctp_protocol_t *proto) { struct net_device *dev; + struct list_head *pos; + struct sctp_func *af; read_lock(&dev_base_lock); for (dev = dev_base; dev; dev = dev->next) { - sctp_v4_get_local_addr_list(proto, dev); - sctp_v6_get_local_addr_list(proto, dev); + list_for_each(pos, &proto->address_families) { + af = list_entry(pos, sctp_func_t, list); + af->copy_addrlist(&proto->local_addr_list, dev); + } } read_unlock(&dev_base_lock); } @@ -259,13 +223,15 @@ /* Returns the dst cache entry for the given source and destination ip * addresses. */ -struct dst_entry *sctp_v4_get_dst(sockaddr_storage_t *daddr, - sockaddr_storage_t *saddr) +struct dst_entry *sctp_v4_get_dst(union sctp_addr *daddr, + union sctp_addr *saddr) { struct rtable *rt; - struct flowi fl = { .nl_u = { .ip4_u = { .daddr = - daddr->v4.sin_addr.s_addr, - } } }; + struct flowi fl; + + memset(&fl, 0x0, sizeof(struct flowi)); + fl.fl4_dst = daddr->v4.sin_addr.s_addr; + fl.proto = IPPROTO_SCTP; if (saddr) fl.fl4_src = saddr->v4.sin_addr.s_addr; @@ -285,12 +251,118 @@ return &rt->u.dst; } -/* Check if the dst entry's source addr matches the given source addr. */ -int sctp_v4_cmp_saddr(struct dst_entry *dst, sockaddr_storage_t *saddr) + +/* Initialize a sctp_addr from in incoming skb. */ +static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb, + int is_saddr) +{ + void *from; + __u16 *port; + struct sctphdr *sh; + + port = &addr->v4.sin_port; + addr->v4.sin_family = AF_INET; + + sh = (struct sctphdr *) skb->h.raw; + if (is_saddr) { + *port = ntohs(sh->source); + from = &skb->nh.iph->saddr; + } else { + *port = ntohs(sh->dest); + from = &skb->nh.iph->daddr; + } + memcpy(&addr->v4.sin_addr.s_addr, from, sizeof(struct in_addr)); +} + +/* Initialize a sctp_addr from a dst_entry. */ +static void sctp_v4_dst_saddr(union sctp_addr *saddr, struct dst_entry *dst) { struct rtable *rt = (struct rtable *)dst; + saddr->v4.sin_family = AF_INET; + saddr->v4.sin_addr.s_addr = rt->rt_src; +} + +/* Compare two addresses exactly. */ +static int sctp_v4_cmp_addr(const union sctp_addr *addr1, + const union sctp_addr *addr2) +{ + if (addr1->sa.sa_family != addr2->sa.sa_family) + return 0; + if (addr1->v4.sin_port != addr2->v4.sin_port) + return 0; + if (addr1->v4.sin_addr.s_addr != addr2->v4.sin_addr.s_addr) + return 0; - return (rt->rt_src == saddr->v4.sin_addr.s_addr); + return 1; +} + +/* Initialize addr struct to INADDR_ANY. */ +static void sctp_v4_inaddr_any(union sctp_addr *addr, unsigned short port) +{ + addr->v4.sin_family = AF_INET; + addr->v4.sin_addr.s_addr = INADDR_ANY; + addr->v4.sin_port = port; +} + +/* Is this a wildcard address? */ +static int sctp_v4_is_any(const union sctp_addr *addr) +{ + return INADDR_ANY == addr->v4.sin_addr.s_addr; +} + +/* This function checks if the address is a valid address to be used for + * SCTP. + * + * Output: + * Return 0 - If the address is a non-unicast or an illegal address. + * Return 1 - If the address is a unicast. + */ +static int sctp_v4_addr_valid(union sctp_addr *addr) +{ + /* Is this a non-unicast address or a unusable SCTP address? */ + if (IS_IPV4_UNUSABLE_ADDRESS(&addr->v4.sin_addr.s_addr)) + return 0; + + return 1; +} + +/* Checking the loopback, private and other address scopes as defined in + * RFC 1918. The IPv4 scoping is based on the draft for SCTP IPv4 + * scoping . + * + * Level 0 - unusable SCTP addresses + * Level 1 - loopback address + * Level 2 - link-local addresses + * Level 3 - private addresses. + * Level 4 - global addresses + * For INIT and INIT-ACK address list, let L be the level of + * of requested destination address, sender and receiver + * SHOULD include all of its addresses with level greater + * than or equal to L. + */ +static sctp_scope_t sctp_v4_scope(union sctp_addr *addr) +{ + sctp_scope_t retval; + + /* Should IPv4 scoping be a sysctl configurable option + * so users can turn it off (default on) for certain + * unconventional networking environments? + */ + + /* Check for unusable SCTP addresses. */ + if (IS_IPV4_UNUSABLE_ADDRESS(&addr->v4.sin_addr.s_addr)) { + retval = SCTP_SCOPE_UNUSABLE; + } else if (LOOPBACK(addr->v4.sin_addr.s_addr)) { + retval = SCTP_SCOPE_LOOPBACK; + } else if (IS_IPV4_LINK_ADDRESS(&addr->v4.sin_addr.s_addr)) { + retval = SCTP_SCOPE_LINK; + } else if (IS_IPV4_PRIVATE_ADDRESS(&addr->v4.sin_addr.s_addr)) { + retval = SCTP_SCOPE_PRIVATE; + } else { + retval = SCTP_SCOPE_GLOBAL; + } + + return retval; } /* Event handler for inet device events. @@ -336,11 +408,11 @@ /* Get the table of functions for manipulating a particular address * family. */ -sctp_func_t *sctp_get_af_specific(const sockaddr_storage_t *address) +sctp_func_t *sctp_get_af_specific(sa_family_t family) { struct list_head *pos; sctp_protocol_t *proto = sctp_get_protocol(); - sctp_func_t *retval, *af; + struct sctp_func *retval, *af; retval = NULL; @@ -349,7 +421,7 @@ */ list_for_each(pos, &proto->address_families) { af = list_entry(pos, sctp_func_t, list); - if (address->sa.sa_family == af->sa_family) { + if (family == af->sa_family) { retval = af; break; } @@ -362,15 +434,16 @@ static void sctp_inet_msgname(char *msgname, int *addr_len) { struct sockaddr_in *sin; - + sin = (struct sockaddr_in *)msgname; *addr_len = sizeof(struct sockaddr_in); sin->sin_family = AF_INET; memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); } - + /* Copy the primary address of the peer primary address as the msg_name. */ -static void sctp_inet_event_msgname(sctp_ulpevent_t *event, char *msgname, int *addr_len) +static void sctp_inet_event_msgname(sctp_ulpevent_t *event, char *msgname, + int *addr_len) { struct sockaddr_in *sin, *sinfrom; @@ -381,26 +454,56 @@ sin->sin_port = htons(event->asoc->peer.port); sin->sin_addr.s_addr = sinfrom->sin_addr.s_addr; } -} +} /* Initialize and copy out a msgname from an inbound skb. */ -static void sctp_inet_skb_msgname(struct sk_buff *skb, char *msgname, int *addr_len) +static void sctp_inet_skb_msgname(struct sk_buff *skb, char *msgname, int *len) { - struct sctphdr *sh; + struct sctphdr *sh; struct sockaddr_in *sin; if (msgname) { - sctp_inet_msgname(msgname, addr_len); + sctp_inet_msgname(msgname, len); sin = (struct sockaddr_in *)msgname; sh = (struct sctphdr *)skb->h.raw; sin->sin_port = sh->source; sin->sin_addr.s_addr = skb->nh.iph->saddr; } -} +} + +/* Do we support this AF? */ +static int sctp_inet_af_supported(sa_family_t family) +{ + /* PF_INET only supports AF_INET addresses. */ + return (AF_INET == family); +} + +/* Address matching with wildcards allowed. */ +static int sctp_inet_cmp_addr(const union sctp_addr *addr1, + const union sctp_addr *addr2, + struct sctp_opt *opt) +{ + /* PF_INET only supports AF_INET addresses. */ + if (addr1->sa.sa_family != addr2->sa.sa_family) + return 0; + if (INADDR_ANY == addr1->v4.sin_addr.s_addr || + INADDR_ANY == addr2->v4.sin_addr.s_addr) + return 1; + if (addr1->v4.sin_addr.s_addr == addr2->v4.sin_addr.s_addr) + return 1; + + return 0; +} + + +struct sctp_func sctp_ipv4_specific; static sctp_pf_t sctp_pf_inet = { .event_msgname = sctp_inet_event_msgname, - .skb_msgname = sctp_inet_skb_msgname, + .skb_msgname = sctp_inet_skb_msgname, + .af_supported = sctp_inet_af_supported, + .cmp_addr = sctp_inet_cmp_addr, + .af = &sctp_ipv4_specific, }; @@ -448,12 +551,19 @@ }; /* IPv4 address related functions. */ -sctp_func_t sctp_ipv4_specific = { +struct sctp_func sctp_ipv4_specific = { .queue_xmit = ip_queue_xmit, .setsockopt = ip_setsockopt, .getsockopt = ip_getsockopt, .get_dst = sctp_v4_get_dst, - .cmp_saddr = sctp_v4_cmp_saddr, + .copy_addrlist = sctp_v4_copy_addrlist, + .from_skb = sctp_v4_from_skb, + .dst_saddr = sctp_v4_dst_saddr, + .cmp_addr = sctp_v4_cmp_addr, + .addr_valid = sctp_v4_addr_valid, + .inaddr_any = sctp_v4_inaddr_any, + .is_any = sctp_v4_is_any, + .scope = sctp_v4_scope, .net_header_len = sizeof(struct iphdr), .sockaddr_len = sizeof(struct sockaddr_in), .sa_family = AF_INET, diff -Nru a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c --- a/net/sctp/sm_make_chunk.c Fri Nov 22 13:41:18 2002 +++ b/net/sctp/sm_make_chunk.c Fri Nov 22 13:41:18 2002 @@ -1,8 +1,8 @@ /* SCTP kernel reference Implementation * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001 Intel Corp. - * Copyright (c) 2001 International Business Machines Corp. + * Copyright (c) 2001-2002 Intel Corp. + * Copyright (c) 2001-2002 International Business Machines Corp. * * This file is part of the SCTP kernel reference Implementation * @@ -166,7 +166,7 @@ int priority) { sctp_inithdr_t init; - sctpParam_t addrs; + union sctp_params addrs; size_t chunksize; sctp_chunk_t *retval = NULL; int addrs_len = 0; @@ -228,7 +228,7 @@ { sctp_inithdr_t initack; sctp_chunk_t *retval; - sctpParam_t addrs; + union sctp_params addrs; int addrs_len; sctp_cookie_param_t *cookie; int cookie_len; @@ -1031,51 +1031,15 @@ } /* Set chunk->source and dest based on the IP header in chunk->skb. */ -void sctp_init_addrs(sctp_chunk_t *chunk) +void sctp_init_addrs(sctp_chunk_t *chunk, union sctp_addr *src, + union sctp_addr *dest) { - sockaddr_storage_t *source, *dest; - struct sk_buff *skb; - struct sctphdr *sh; - struct iphdr *ih4; - struct ipv6hdr *ih6; - - source = &chunk->source; - dest = &chunk->dest; - skb = chunk->skb; - ih4 = skb->nh.iph; - ih6 = skb->nh.ipv6h; - sh = chunk->sctp_hdr; - - switch (ih4->version) { - case 4: - source->v4.sin_family = AF_INET; - source->v4.sin_port = ntohs(sh->source); - source->v4.sin_addr.s_addr = ih4->saddr; - dest->v4.sin_family = AF_INET; - dest->v4.sin_port = ntohs(sh->dest); - dest->v4.sin_addr.s_addr = ih4->daddr; - break; - - case 6: - SCTP_V6( - source->v6.sin6_family = AF_INET6; - source->v6.sin6_port = ntohs(sh->source); - source->v6.sin6_addr = ih6->saddr; - dest->v6.sin6_family = AF_INET6; - dest->v6.sin6_port = ntohs(sh->dest); - dest->v6.sin6_addr = ih6->daddr; - /* FIXME: What do we do with scope, etc. ? */ - break; - ) - - default: - /* This is a bogus address type, just bail. */ - break; - }; + memcpy(&chunk->source, src, sizeof(union sctp_addr)); + memcpy(&chunk->dest, dest, sizeof(union sctp_addr)); } /* Extract the source address from a chunk. */ -const sockaddr_storage_t *sctp_source(const sctp_chunk_t *chunk) +const union sctp_addr *sctp_source(const sctp_chunk_t *chunk) { /* If we have a known transport, use that. */ if (chunk->transport) { @@ -1482,78 +1446,28 @@ * 3rd Level Abstractions ********************************************************************/ -/* Verify the INIT packet before we process it. */ -int sctp_verify_init(const sctp_association_t *asoc, - sctp_cid_t cid, - sctp_init_chunk_t *peer_init, - sctp_chunk_t *chunk, - sctp_chunk_t **err_chk_p) -{ - sctpParam_t param; - uint8_t *end; - - /* FIXME - Verify the fixed fields of the INIT chunk. Also, verify - * the mandatory parameters somewhere here and generate either the - * "Missing mandatory parameter" error or the "Invalid mandatory - * parameter" error. */ - - /* Find unrecognized parameters. */ - - end = ((uint8_t *)peer_init + ntohs(peer_init->chunk_hdr.length)); - - for (param.v = peer_init->init_hdr.params; - param.v < end; - param.v += WORD_ROUND(ntohs(param.p->length))) { - - if (!sctp_verify_param(asoc, param, cid, chunk, err_chk_p)) - return 0; - - } /* for (loop through all parameters) */ - - return 1; -} - - -/* Find unrecognized parameters in the chunk. - * Return values: - * 0 - discard the chunk - * 1 - continue with the chunk +/* Do not attempt to handle the HOST_NAME parm. However, do + * send back an indicator to the peer. */ -int sctp_verify_param(const sctp_association_t *asoc, - sctpParam_t param, - sctp_cid_t cid, - sctp_chunk_t *chunk, - sctp_chunk_t **err_chk_p) +static int sctp_process_hn_param(const sctp_association_t *asoc, + union sctp_params param, + sctp_chunk_t *chunk, + sctp_chunk_t **err_chk_p) { - int retval = 1; + __u16 len = ntohs(param.p->length); - /* FIXME - This routine is not looking at each parameter per the - * chunk type, i.e., unrecognized parameters should be further - * identified based on the chunk id. + /* Make an ERROR chunk, preparing enough room for + * returning multiple unknown parameters. */ + if (!*err_chk_p) + *err_chk_p = sctp_make_op_error_space(asoc, chunk, len); - switch (param.p->type) { - case SCTP_PARAM_IPV4_ADDRESS: - case SCTP_PARAM_IPV6_ADDRESS: - case SCTP_PARAM_COOKIE_PRESERVATIVE: - /* FIXME - If we don't support the host name parameter, we should - * generate an error for this - Unresolvable address. - */ - case SCTP_PARAM_HOST_NAME_ADDRESS: - case SCTP_PARAM_SUPPORTED_ADDRESS_TYPES: - case SCTP_PARAM_STATE_COOKIE: - case SCTP_PARAM_HEARTBEAT_INFO: - case SCTP_PARAM_UNRECOGNIZED_PARAMETERS: - case SCTP_PARAM_ECN_CAPABLE: - break; - default: - SCTP_DEBUG_PRINTK("Unrecognized param: %d for chunk %d.\n", - ntohs(param.p->type), cid); - return sctp_process_unk_param(asoc, param, chunk, err_chk_p); + if (*err_chk_p) + sctp_init_cause(*err_chk_p, SCTP_ERROR_DNS_FAILED, + param.v, len); - break; - } - return retval; + /* Stop processing this chunk. */ + return 0; } /* RFC 3.2.1 & the Implementers Guide 2.2. @@ -1582,10 +1496,10 @@ * 0 - discard the chunk * 1 - continue with the chunk */ -int sctp_process_unk_param(const sctp_association_t *asoc, - sctpParam_t param, - sctp_chunk_t *chunk, - sctp_chunk_t **err_chk_p) +static int sctp_process_unk_param(const sctp_association_t *asoc, + union sctp_params param, + sctp_chunk_t *chunk, + sctp_chunk_t **err_chk_p) { int retval = 1; @@ -1604,7 +1518,7 @@ if (*err_chk_p) sctp_init_cause(*err_chk_p, SCTP_ERROR_UNKNOWN_PARAM, - (const void *)param.p, + param.v, WORD_ROUND(ntohs(param.p->length))); break; @@ -1620,7 +1534,7 @@ if (*err_chk_p) { sctp_init_cause(*err_chk_p, SCTP_ERROR_UNKNOWN_PARAM, - (const void *)param.p, + param.v, WORD_ROUND(ntohs(param.p->length))); } else { /* If there is no memory for generating the ERROR @@ -1638,17 +1552,84 @@ return retval; } -/* Unpack the parameters in an INIT packet. - * FIXME: There is no return status to allow callers to do - * error handling. - */ -void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid, - const sockaddr_storage_t *peer_addr, - sctp_init_chunk_t *peer_init, - int priority) +/* Find unrecognized parameters in the chunk. + * Return values: + * 0 - discard the chunk + * 1 - continue with the chunk + */ +static int sctp_verify_param(const sctp_association_t *asoc, + union sctp_params param, + sctp_cid_t cid, + sctp_chunk_t *chunk, + sctp_chunk_t **err_chunk) { - sctpParam_t param; - __u8 *end; + int retval = 1; + + /* FIXME - This routine is not looking at each parameter per the + * chunk type, i.e., unrecognized parameters should be further + * identified based on the chunk id. + */ + + switch (param.p->type) { + case SCTP_PARAM_IPV4_ADDRESS: + case SCTP_PARAM_IPV6_ADDRESS: + case SCTP_PARAM_COOKIE_PRESERVATIVE: + case SCTP_PARAM_SUPPORTED_ADDRESS_TYPES: + case SCTP_PARAM_STATE_COOKIE: + case SCTP_PARAM_HEARTBEAT_INFO: + case SCTP_PARAM_UNRECOGNIZED_PARAMETERS: + case SCTP_PARAM_ECN_CAPABLE: + break; + + case SCTP_PARAM_HOST_NAME_ADDRESS: + /* Tell the peer, we won't support this param. */ + return sctp_process_hn_param(asoc, param, chunk, err_chunk); + default: + SCTP_DEBUG_PRINTK("Unrecognized param: %d for chunk %d.\n", + ntohs(param.p->type), cid); + return sctp_process_unk_param(asoc, param, chunk, err_chunk); + + break; + } + return retval; +} + +/* Verify the INIT packet before we process it. */ +int sctp_verify_init(const sctp_association_t *asoc, + sctp_cid_t cid, + sctp_init_chunk_t *peer_init, + sctp_chunk_t *chunk, + sctp_chunk_t **err_chk_p) +{ + union sctp_params param; + + /* FIXME - Verify the fixed fields of the INIT chunk. Also, verify + * the mandatory parameters somewhere here and generate either the + * "Missing mandatory parameter" error or the "Invalid mandatory + * parameter" error. + */ + + /* Find unrecognized parameters. */ + + sctp_walk_params(param, peer_init, init_hdr.params) { + + if (!sctp_verify_param(asoc, param, cid, chunk, err_chk_p)) + return 0; + + } /* for (loop through all parameters) */ + + return 1; +} + +/* Unpack the parameters in an INIT packet into an association. + * Returns 0 on failure, else success. + */ +int sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid, + const union sctp_addr *peer_addr, + sctp_init_chunk_t *peer_init, + int priority) +{ + union sctp_params param; sctp_transport_t *transport; struct list_head *pos, *temp; char *cookie; @@ -1664,15 +1645,14 @@ * be a a better choice than any of the embedded addresses. */ if (peer_addr) - sctp_assoc_add_peer(asoc, peer_addr, priority); + if(!sctp_assoc_add_peer(asoc, peer_addr, priority)) + goto nomem; /* Process the initialization parameters. */ - end = ((__u8 *)peer_init + ntohs(peer_init->chunk_hdr.length)); - for (param.v = peer_init->init_hdr.params; - param.v < end; - param.v += WORD_ROUND(ntohs(param.p->length))) { - if (!sctp_process_param(asoc, param, peer_addr, cid, - priority)) + + sctp_walk_params(param, peer_init, init_hdr.params) { + + if (!sctp_process_param(asoc, param, peer_addr, priority)) goto clean_up; } @@ -1738,7 +1718,7 @@ * association to the same value as the Initial TSN. */ asoc->peer.addip_serial = asoc->peer.i.initial_tsn - 1; - return; + return 1; clean_up: /* Release the transport structures. */ @@ -1747,8 +1727,11 @@ list_del(pos); sctp_transport_free(transport); } +nomem: + return 0; } + /* Update asoc with the option described in param. * * RFC2960 3.3.2.1 Optional/Variable Length Parameters in INIT @@ -1760,14 +1743,12 @@ * work we do. In particular, we should not build transport * structures for the addresses. */ -int sctp_process_param(sctp_association_t *asoc, sctpParam_t param, - const sockaddr_storage_t *peer_addr, - sctp_cid_t cid, int priority) -{ - sockaddr_storage_t addr; - sctp_addr_param_t *addrparm; - int j; +int sctp_process_param(sctp_association_t *asoc, union sctp_params param, + const union sctp_addr *peer_addr, int priority) +{ + union sctp_addr addr; int i; + __u16 sat; int retval = 1; sctp_scope_t scope; @@ -1776,30 +1757,21 @@ * came from a fresh INIT, and INIT ACK, or were stored in a cookie. */ switch (param.p->type) { + case SCTP_PARAM_IPV6_ADDRESS: + if( PF_INET6 != asoc->base.sk->family) + break; + /* Fall through. */ case SCTP_PARAM_IPV4_ADDRESS: - addrparm = (sctp_addr_param_t *)param.v; - sctp_param2sockaddr(&addr, addrparm, asoc->peer.port); + sctp_param2sockaddr(&addr, param.addr, asoc->peer.port); scope = sctp_scope(peer_addr); if (sctp_in_scope(&addr, scope)) - sctp_assoc_add_peer(asoc, &addr, priority); - break; - - case SCTP_PARAM_IPV6_ADDRESS: - /* Rethink this as we may need to keep for - * restart considerations. - */ - if (PF_INET6 == asoc->base.sk->family) { - addrparm = (sctp_addr_param_t *)param.v; - sctp_param2sockaddr(&addr, addrparm, asoc->peer.port); - scope = sctp_scope(peer_addr); - if (sctp_in_scope(&addr, scope)) - sctp_assoc_add_peer(asoc, &addr, priority); - } + if (!sctp_assoc_add_peer(asoc, &addr, priority)) + return 0; break; case SCTP_PARAM_COOKIE_PRESERVATIVE: asoc->cookie_preserve = - ntohl(param.bht->lifespan_increment); + ntohl(param.life->lifespan_increment); break; case SCTP_PARAM_HOST_NAME_ADDRESS: @@ -1813,10 +1785,12 @@ asoc->peer.ipv4_address = 0; asoc->peer.ipv6_address = 0; - j = (ntohs(param.p->length) - - sizeof(sctp_paramhdr_t)) / - sizeof(__u16); - for (i = 0; i < j; ++i) { + /* Cycle through address types; avoid divide by 0. */ + sat = ntohs(param.p->length) - sizeof(sctp_paramhdr_t); + if (sat) + sat /= sizeof(__u16); + + for (i = 0; i < sat; ++i) { switch (param.sat->types[i]) { case SCTP_PARAM_IPV4_ADDRESS: asoc->peer.ipv4_address = 1; @@ -1843,13 +1817,11 @@ break; case SCTP_PARAM_HEARTBEAT_INFO: - SCTP_DEBUG_PRINTK("unimplemented " - "SCTP_PARAM_HEARTBEAT_INFO\n"); + /* Would be odd to receive, but it causes no problems. */ break; case SCTP_PARAM_UNRECOGNIZED_PARAMETERS: - SCTP_DEBUG_PRINTK("unimplemented " - "SCTP_PARAM_UNRECOGNIZED_PARAMETERS\n"); + /* Rejected during verify stage. */ break; case SCTP_PARAM_ECN_CAPABLE: @@ -1898,8 +1870,8 @@ * 4th Level Abstractions ********************************************************************/ -/* Convert from an SCTP IP parameter to a sockaddr_storage_t. */ -void sctp_param2sockaddr(sockaddr_storage_t *addr, sctp_addr_param_t *param, +/* Convert from an SCTP IP parameter to a union sctp_addr. */ +void sctp_param2sockaddr(union sctp_addr *addr, sctp_addr_param_t *param, __u16 port) { switch(param->v4.param_hdr.type) { @@ -1926,11 +1898,8 @@ /* Convert an IP address in an SCTP param into a sockaddr_in. */ /* Returns true if a valid conversion was possible. */ -int sctp_addr2sockaddr(sctpParam_t p, sockaddr_storage_t *sa) +int sctp_addr2sockaddr(union sctp_params p, union sctp_addr *sa) { - if (!p.v) - return 0; - switch (p.p->type) { case SCTP_PARAM_IPV4_ADDRESS: sa->v4.sin_addr = *((struct in_addr *)&p.v4->addr); @@ -1950,30 +1919,10 @@ return 1; } -/* Convert from an IP version number to an Address Family symbol. */ -int ipver2af(__u8 ipver) -{ - int family; - - switch (ipver) { - case 4: - family = AF_INET; - break; - case 6: - family = AF_INET6; - break; - default: - family = 0; - break; - }; - - return family; -} - /* Convert a sockaddr_in to an IP address in an SCTP param. - * Returns len if a valid conversion was possible. + * Returns len if a valid conversion was possible. */ -int sockaddr2sctp_addr(const sockaddr_storage_t *sa, sctp_addr_param_t *p) +int sockaddr2sctp_addr(const union sctp_addr *sa, sctp_addr_param_t *p) { int len = 0; diff -Nru a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c --- a/net/sctp/sm_sideeffect.c Fri Nov 22 13:41:21 2002 +++ b/net/sctp/sm_sideeffect.c Fri Nov 22 13:41:21 2002 @@ -41,6 +41,7 @@ * Dajiang Zhang * Daisy Chang * Sridhar Samudrala + * Ardelle Fan * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -68,11 +69,13 @@ static void sctp_cmd_init_failed(sctp_cmd_seq_t *, sctp_association_t *asoc); static void sctp_cmd_assoc_failed(sctp_cmd_seq_t *, sctp_association_t *asoc, sctp_event_t event_type, sctp_chunk_t *chunk); -static void sctp_cmd_process_init(sctp_cmd_seq_t *, sctp_association_t *asoc, - sctp_chunk_t *chunk, - sctp_init_chunk_t *peer_init, - int priority); +static int sctp_cmd_process_init(sctp_cmd_seq_t *, sctp_association_t *asoc, + sctp_chunk_t *chunk, + sctp_init_chunk_t *peer_init, + int priority); static void sctp_cmd_hb_timers_start(sctp_cmd_seq_t *, sctp_association_t *); +static void sctp_cmd_hb_timers_update(sctp_cmd_seq_t *, sctp_association_t *, + sctp_transport_t *); static void sctp_cmd_set_bind_addrs(sctp_cmd_seq_t *, sctp_association_t *, sctp_bind_addr_t *); static void sctp_cmd_transport_reset(sctp_cmd_seq_t *, sctp_association_t *, @@ -83,6 +86,8 @@ sctp_sackhdr_t *); static void sctp_cmd_setup_t2(sctp_cmd_seq_t *, sctp_association_t *, sctp_chunk_t *); +static void sctp_cmd_new_state(sctp_cmd_seq_t *, sctp_association_t *, + sctp_state_t); /* These three macros allow us to pull the debugging code out of the * main flow of sctp_do_sm() to keep attention focused on the real @@ -193,6 +198,7 @@ /* BUG--we should now recover some memory, probably by * reneging... */ + error = -ENOMEM; break; case SCTP_DISPOSITION_DELETE_TCB: @@ -301,8 +307,7 @@ case SCTP_CMD_NEW_STATE: /* Enter a new state. */ - asoc->state = command->obj.state; - asoc->state_timestamp = jiffies; + sctp_cmd_new_state(commands, asoc, command->obj.state); break; case SCTP_CMD_REPORT_TSN: @@ -339,9 +344,14 @@ break; case SCTP_CMD_PEER_INIT: - /* Process a unified INIT from the peer. */ - sctp_cmd_process_init(commands, asoc, chunk, - command->obj.ptr, priority); + /* Process a unified INIT from the peer. + * Note: Only used during INIT-ACK processing. If + * there is an error just return to the outter + * layer which will bail. + */ + error = sctp_cmd_process_init(commands, asoc, chunk, + command->obj.ptr, + priority); break; case SCTP_CMD_GEN_COOKIE_ECHO: @@ -561,6 +571,11 @@ sctp_cmd_hb_timers_start(commands, asoc); break; + case SCTP_CMD_HB_TIMERS_UPDATE: + t = command->obj.transport; + sctp_cmd_hb_timers_update(commands, asoc, t); + break; + case SCTP_CMD_REPORT_ERROR: error = command->obj.error; break; @@ -581,11 +596,18 @@ chunk->pdiscard = 1; break; + case SCTP_CMD_RTO_PENDING: + t = command->obj.transport; + t->rto_pending = 1; + break; + default: printk(KERN_WARNING "Impossible command: %u, %p\n", command->verb, command->obj.ptr); break; }; + if (error) + return error; } return error; @@ -648,7 +670,7 @@ } /* Always try to quiet the other end. In case of lost CWR, - * resend last_cwr_tsn. + * resend last_cwr_tsn. */ repl = sctp_make_cwr(asoc, asoc->last_cwr_tsn, chunk); @@ -978,7 +1000,7 @@ */ asoc->overall_error_count++; - if (transport->state.active && + if (transport->active && (transport->error_count++ >= transport->error_threshold)) { SCTP_DEBUG_PRINTK("transport_strike: transport " "IP:%d.%d.%d.%d failed.\n", @@ -1058,22 +1080,32 @@ } /* Process an init chunk (may be real INIT/INIT-ACK or an embedded INIT - * inside the cookie. + * inside the cookie. In reality, this is only used for INIT-ACK processing + * since all other cases use "temporary" associations and can do all + * their work in statefuns directly. */ -static void sctp_cmd_process_init(sctp_cmd_seq_t *commands, - sctp_association_t *asoc, - sctp_chunk_t *chunk, - sctp_init_chunk_t *peer_init, - int priority) -{ - /* The command sequence holds commands assuming that the - * processing will happen successfully. If this is not the - * case, rewind the sequence and add appropriate error handling - * to the sequence. - */ - sctp_process_init(asoc, chunk->chunk_hdr->type, - sctp_source(chunk), peer_init, - priority); +static int sctp_cmd_process_init(sctp_cmd_seq_t *commands, + sctp_association_t *asoc, + sctp_chunk_t *chunk, + sctp_init_chunk_t *peer_init, + int priority) +{ + int error; + + /* We only process the init as a sideeffect in a single + * case. This is when we process the INIT-ACK. If we + * fail during INIT processing (due to malloc problems), + * just return the error and stop processing the stack. + */ + + if (!sctp_process_init(asoc, chunk->chunk_hdr->type, + sctp_source(chunk), peer_init, + priority)) + error = -ENOMEM; + else + error = 0; + + return error; } /* Helper function to break out starting up of heartbeat timers. */ @@ -1096,6 +1128,16 @@ } } +/* Helper function to update the heartbeat timer. */ +static void sctp_cmd_hb_timers_update(sctp_cmd_seq_t *cmds, + sctp_association_t *asoc, + sctp_transport_t *t) +{ + /* Update the heartbeat timer. */ + if (!mod_timer(&t->hb_timer, t->hb_interval + t->rto + jiffies)) + sctp_transport_hold(t); +} + /* Helper function to break out SCTP_CMD_SET_BIND_ADDR handling. */ void sctp_cmd_set_bind_addrs(sctp_cmd_seq_t *cmds, sctp_association_t *asoc, sctp_bind_addr_t *bp) @@ -1131,7 +1173,7 @@ /* Mark the destination transport address as active if it is not so * marked. */ - if (!t->state.active) + if (!t->active) sctp_assoc_control_transport(asoc, t, SCTP_TRANSPORT_UP, SCTP_HEARTBEAT_SUCCESS); @@ -1154,10 +1196,6 @@ /* Mark one strike against a transport. */ sctp_do_8_2_transport_strike(asoc, t); - - /* Update the heartbeat timer. */ - if (!mod_timer(&t->hb_timer, t->hb_interval + t->rto + jiffies)) - sctp_transport_hold(t); } /* Helper function to process the process SACK command. */ @@ -1195,4 +1233,19 @@ asoc->shutdown_last_sent_to = t; asoc->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] = t->rto; chunk->transport = t; +} + +/* Helper function to change the state of an association. */ +static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds, sctp_association_t *asoc, + sctp_state_t state) +{ + asoc->state = state; + asoc->state_timestamp = jiffies; + + /* Wake up any process waiting for the association to + * get established. + */ + if ((SCTP_STATE_ESTABLISHED == asoc->state) && + (waitqueue_active(&asoc->wait))) + wake_up_interruptible(&asoc->wait); } diff -Nru a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c --- a/net/sctp/sm_statefuns.c Fri Nov 22 13:41:17 2002 +++ b/net/sctp/sm_statefuns.c Fri Nov 22 13:41:17 2002 @@ -236,20 +236,18 @@ chunk->subh.init_hdr = (sctp_inithdr_t *)chunk->skb->data; /* Tag the variable length parameters. */ - chunk->param_hdr.v = - skb_pull(chunk->skb, sizeof(sctp_inithdr_t)); + chunk->param_hdr.v = skb_pull(chunk->skb, sizeof(sctp_inithdr_t)); new_asoc = sctp_make_temp_asoc(ep, chunk, GFP_ATOMIC); if (!new_asoc) goto nomem; - /* FIXME: sctp_process_init can fail, but there is no - * status nor handling. - */ - sctp_process_init(new_asoc, chunk->chunk_hdr->type, - sctp_source(chunk), - (sctp_init_chunk_t *)chunk->chunk_hdr, - GFP_ATOMIC); + /* The call, sctp_process_init(), can fail on memory allocation. */ + if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, + sctp_source(chunk), + (sctp_init_chunk_t *)chunk->chunk_hdr, + GFP_ATOMIC)) + goto nomem_init; sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc)); @@ -302,10 +300,10 @@ return SCTP_DISPOSITION_DELETE_TCB; nomem_ack: - sctp_association_free(new_asoc); if (err_chunk) sctp_free_chunk(err_chunk); - +nomem_init: + sctp_association_free(new_asoc); nomem: return SCTP_DISPOSITION_NOMEM; } @@ -563,9 +561,11 @@ * effects--it is safe to run them here. */ peer_init = &chunk->subh.cookie_hdr->c.peer_init[0]; - sctp_process_init(new_asoc, chunk->chunk_hdr->type, - &chunk->subh.cookie_hdr->c.peer_addr, peer_init, - GFP_ATOMIC); + + if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, + &chunk->subh.cookie_hdr->c.peer_addr, + peer_init, GFP_ATOMIC)) + goto nomem_init; repl = sctp_make_cookie_ack(new_asoc, chunk); if (!repl) @@ -592,10 +592,9 @@ nomem_ev: sctp_free_chunk(repl); - nomem_repl: +nomem_init: sctp_association_free(new_asoc); - nomem: return SCTP_DISPOSITION_NOMEM; } @@ -664,6 +663,39 @@ return SCTP_DISPOSITION_NOMEM; } +/* Generate and sendout a heartbeat packet. */ +sctp_disposition_t sctp_sf_heartbeat(const sctp_endpoint_t *ep, + const sctp_association_t *asoc, + const sctp_subtype_t type, + void *arg, + sctp_cmd_seq_t *commands) +{ + sctp_transport_t *transport = (sctp_transport_t *) arg; + sctp_chunk_t *reply; + sctp_sender_hb_info_t hbinfo; + size_t paylen = 0; + + hbinfo.param_hdr.type = SCTP_PARAM_HEARTBEAT_INFO; + hbinfo.param_hdr.length = htons(sizeof(sctp_sender_hb_info_t)); + hbinfo.daddr = transport->ipaddr; + hbinfo.sent_at = jiffies; + + /* Send a heartbeat to our peer. */ + paylen = sizeof(sctp_sender_hb_info_t); + reply = sctp_make_heartbeat(asoc, transport, &hbinfo, paylen); + if (!reply) + return SCTP_DISPOSITION_NOMEM; + + /* Set rto_pending indicating that an RTT measurement + * is started with this heartbeat chunk. + */ + sctp_add_cmd_sf(commands, SCTP_CMD_RTO_PENDING, + SCTP_TRANSPORT(transport)); + + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); + return SCTP_DISPOSITION_CONSUME; +} + /* Generate a HEARTBEAT packet on the given transport. */ sctp_disposition_t sctp_sf_sendbeat_8_3(const sctp_endpoint_t *ep, const sctp_association_t *asoc, @@ -672,9 +704,6 @@ sctp_cmd_seq_t *commands) { sctp_transport_t *transport = (sctp_transport_t *) arg; - sctp_chunk_t *reply; - sctp_sender_hb_info_t hbinfo; - size_t paylen = 0; if (asoc->overall_error_count >= asoc->overall_error_threshold) { /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ @@ -689,34 +718,21 @@ * HEARTBEAT is sent (see Section 8.3). */ - hbinfo.param_hdr.type = SCTP_PARAM_HEARTBEAT_INFO; - hbinfo.param_hdr.length = htons(sizeof(sctp_sender_hb_info_t)); - hbinfo.daddr = transport->ipaddr; - hbinfo.sent_at = jiffies; - - /* Set rto_pending indicating that an RTT measurement is started - * with this heartbeat chunk. - */ - transport->rto_pending = 1; - - /* Send a heartbeat to our peer. */ - paylen = sizeof(sctp_sender_hb_info_t); - reply = sctp_make_heartbeat(asoc, transport, &hbinfo, paylen); - if (!reply) - goto nomem; - - sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); - - /* Set transport error counter and association error counter - * when sending heartbeat. - */ - sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_RESET, + if (transport->hb_allowed) { + if (SCTP_DISPOSITION_NOMEM == + sctp_sf_heartbeat(ep, asoc, type, arg, + commands)) + return SCTP_DISPOSITION_NOMEM; + /* Set transport error counter and association error counter + * when sending heartbeat. + */ + sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_RESET, + SCTP_TRANSPORT(transport)); + } + sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_UPDATE, SCTP_TRANSPORT(transport)); return SCTP_DISPOSITION_CONSUME; - -nomem: - return SCTP_DISPOSITION_NOMEM; } /* @@ -817,7 +833,7 @@ sctp_cmd_seq_t *commands) { sctp_chunk_t *chunk = arg; - sockaddr_storage_t from_addr; + union sctp_addr from_addr; sctp_transport_t *link; sctp_sender_hb_info_t *hbinfo; unsigned long max_interval; @@ -866,7 +882,7 @@ /* Helper function to send out an abort for the restart * condition. */ -static int sctp_sf_send_restart_abort(sockaddr_storage_t *ssa, +static int sctp_sf_send_restart_abort(union sctp_addr *ssa, sctp_chunk_t *init, sctp_cmd_seq_t *commands) { @@ -1125,8 +1141,13 @@ * Verification Tag and Peers Verification tag into a reserved * place (local tie-tag and per tie-tag) within the state cookie. */ - sctp_process_init(new_asoc, chunk->chunk_hdr->type, sctp_source(chunk), - (sctp_init_chunk_t *)chunk->chunk_hdr, GFP_ATOMIC); + if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, + sctp_source(chunk), + (sctp_init_chunk_t *)chunk->chunk_hdr, + GFP_ATOMIC)) { + retval = SCTP_DISPOSITION_NOMEM; + goto nomem_init; + } /* Make sure no new addresses are being added during the * restart. Do not do this check for COOKIE-WAIT state, @@ -1197,6 +1218,7 @@ nomem: retval = SCTP_DISPOSITION_NOMEM; goto cleanup; +nomem_init: cleanup_asoc: sctp_association_free(new_asoc); goto cleanup; @@ -1326,15 +1348,16 @@ * side effects--it is safe to run them here. */ peer_init = &chunk->subh.cookie_hdr->c.peer_init[0]; - sctp_process_init(new_asoc, chunk->chunk_hdr->type, - sctp_source(chunk), peer_init, GFP_ATOMIC); + + if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, + sctp_source(chunk), peer_init, GFP_ATOMIC)) + goto nomem; /* Make sure no new addresses are being added during the * restart. Though this is a pretty complicated attack * since you'd have to get inside the cookie. */ if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, commands)) { - printk("cookie echo check\n"); return SCTP_DISPOSITION_CONSUME; } @@ -1391,8 +1414,9 @@ * side effects--it is safe to run them here. */ peer_init = &chunk->subh.cookie_hdr->c.peer_init[0]; - sctp_process_init(new_asoc, chunk->chunk_hdr->type, - sctp_source(chunk), peer_init, GFP_ATOMIC); + if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, + sctp_source(chunk), peer_init, GFP_ATOMIC)) + goto nomem; /* Update the content of current association. */ sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc)); @@ -3657,6 +3681,39 @@ } /* + * Process the REQUESTHEARTBEAT primitive + * + * 10.1 ULP-to-SCTP + * J) Request Heartbeat + * + * Format: REQUESTHEARTBEAT(association id, destination transport address) + * + * -> result + * + * Instructs the local endpoint to perform a HeartBeat on the specified + * destination transport address of the given association. The returned + * result should indicate whether the transmission of the HEARTBEAT + * chunk to the destination address is successful. + * + * Mandatory attributes: + * + * o association id - local handle to the SCTP association + * + * o destination transport address - the transport address of the + * asociation on which a heartbeat should be issued. + */ +sctp_disposition_t sctp_sf_do_prm_requestheartbeat( + const sctp_endpoint_t *ep, + const sctp_association_t *asoc, + const sctp_subtype_t type, + void *arg, + sctp_cmd_seq_t *commands) +{ + return sctp_sf_heartbeat(ep, asoc, type, (sctp_transport_t *)arg, + commands); +} + +/* * Ignore the primitive event * * The return value is the disposition of the primitive. @@ -4257,7 +4314,8 @@ /* Cache a route for the transport with the chunk's destination as * the source address. */ - sctp_transport_route(transport, (sockaddr_storage_t *)&chunk->dest); + sctp_transport_route(transport, (union sctp_addr *)&chunk->dest, + sctp_sk(sctp_get_ctl_sock())); packet = sctp_packet_init(packet, transport, sport, dport); packet = sctp_packet_config(packet, vtag, 0, NULL); diff -Nru a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c --- a/net/sctp/sm_statetable.c Fri Nov 22 13:41:23 2002 +++ b/net/sctp/sm_statetable.c Fri Nov 22 13:41:23 2002 @@ -39,6 +39,7 @@ * Jon Grimm * Hui Huang * Daisy Chang + * Ardelle Fan * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -706,21 +707,28 @@ /* SCTP_STATE_EMPTY */ \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \ + {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \ + {.fn = sctp_sf_do_prm_requestheartbeat, \ + .name = "sctp_sf_do_prm_requestheartbeat"}, \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \ + {.fn = sctp_sf_do_prm_requestheartbeat, \ + .name = "sctp_sf_do_prm_requestheartbeat"}, \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \ + {.fn = sctp_sf_do_prm_requestheartbeat, \ + .name = "sctp_sf_do_prm_requestheartbeat"}, \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \ + {.fn = sctp_sf_do_prm_requestheartbeat, \ + .name = "sctp_sf_do_prm_requestheartbeat"}, \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \ + {.fn = sctp_sf_do_prm_requestheartbeat, \ + .name = "sctp_sf_do_prm_requestheartbeat"}, \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \ + {.fn = sctp_sf_do_prm_requestheartbeat, \ + .name = "sctp_sf_do_prm_requestheartbeat"}, \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \ + {.fn = sctp_sf_do_prm_requestheartbeat, \ + .name = "sctp_sf_do_prm_requestheartbeat"}, \ } /* TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT */ #define TYPE_SCTP_PRIMITIVE_GETSRTTREPORT { \ diff -Nru a/net/sctp/socket.c b/net/sctp/socket.c --- a/net/sctp/socket.c Fri Nov 22 13:41:23 2002 +++ b/net/sctp/socket.c Fri Nov 22 13:41:23 2002 @@ -86,15 +86,16 @@ static int sctp_wait_for_sndbuf(sctp_association_t *asoc, long *timeo_p, int msg_len); static int sctp_wait_for_packet(struct sock * sk, int *err, long *timeo_p); +static int sctp_wait_for_connect(sctp_association_t *asoc, long *timeo_p); static inline void sctp_sk_addr_set(struct sock *, - const sockaddr_storage_t *newaddr, - sockaddr_storage_t *saveaddr); + const union sctp_addr *newaddr, + union sctp_addr *saveaddr); static inline void sctp_sk_addr_restore(struct sock *, - const sockaddr_storage_t *); -static inline int sctp_sendmsg_verify_name(struct sock *, struct msghdr *); + const union sctp_addr *); +static inline int sctp_verify_addr(struct sock *, struct sockaddr *, int); static int sctp_bindx_add(struct sock *, struct sockaddr_storage *, int); static int sctp_bindx_rem(struct sock *, struct sockaddr_storage *, int); -static int sctp_do_bind(struct sock *, sockaddr_storage_t *, int); +static int sctp_do_bind(struct sock *, union sctp_addr *, int); static int sctp_autobind(struct sock *sk); @@ -122,7 +123,7 @@ /* Disallow binding twice. */ if (!sctp_sk(sk)->ep->base.bind_addr.port) - retval = sctp_do_bind(sk, (sockaddr_storage_t *)uaddr, + retval = sctp_do_bind(sk, (union sctp_addr *)uaddr, addr_len); else retval = -EINVAL; @@ -135,14 +136,14 @@ static long sctp_get_port_local(struct sock *, unsigned short); /* Bind a local address either to an endpoint or to an association. */ -SCTP_STATIC int sctp_do_bind(struct sock *sk, sockaddr_storage_t *newaddr, +SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *newaddr, int addr_len) { sctp_opt_t *sp = sctp_sk(sk); sctp_endpoint_t *ep = sp->ep; sctp_bind_addr_t *bp = &ep->base.bind_addr; unsigned short sa_family = newaddr->sa.sa_family; - sockaddr_storage_t tmpaddr, saveaddr; + union sctp_addr tmpaddr, saveaddr; unsigned short *snum; int ret = 0; @@ -403,7 +404,7 @@ goto err_bindx_add; }; - retval = sctp_do_bind(sk, (sockaddr_storage_t *)&addrs[cnt], + retval = sctp_do_bind(sk, (union sctp_addr *)&addrs[cnt], addr_len); err_bindx_add: @@ -481,7 +482,7 @@ int cnt; sctp_bind_addr_t *bp = &ep->base.bind_addr; int retval = 0; - sockaddr_storage_t saveaddr; + union sctp_addr saveaddr; SCTP_DEBUG_PRINTK("sctp_bindx_rem (sk: %p, addrs: %p, addrcnt: %d)\n", sk, addrs, addrcnt); @@ -500,7 +501,7 @@ */ switch (((struct sockaddr *)&addrs[cnt])->sa_family) { case AF_INET: - saveaddr = *((sockaddr_storage_t *) + saveaddr = *((union sctp_addr *) &addrs[cnt]); saveaddr.v4.sin_port = ntohs(saveaddr.v4.sin_port); /* Verify the port. */ @@ -511,7 +512,7 @@ break; case AF_INET6: - saveaddr = *((sockaddr_storage_t *) + saveaddr = *((union sctp_addr *) &addrs[cnt]); saveaddr.v6.sin6_port = ntohs(saveaddr.v6.sin6_port); @@ -741,7 +742,7 @@ sctp_association_t *new_asoc=NULL, *asoc=NULL; sctp_transport_t *transport; sctp_chunk_t *chunk = NULL; - sockaddr_storage_t to; + union sctp_addr to; struct sockaddr *msg_name = NULL; struct sctp_sndrcvinfo default_sinfo = { 0 }; struct sctp_sndrcvinfo *sinfo; @@ -777,7 +778,8 @@ * For a peeled-off socket, msg_name is ignored. */ if ((SCTP_SOCKET_UDP_HIGH_BANDWIDTH != sp->type) && msg->msg_name) { - err = sctp_sendmsg_verify_name(sk, msg); + err = sctp_verify_addr(sk, (struct sockaddr *)msg->msg_name, + msg->msg_namelen); if (err) return err; @@ -826,28 +828,14 @@ /* Look for a matching association on the endpoint. */ asoc = sctp_endpoint_lookup_assoc(ep, &to, &transport); if (!asoc) { - struct list_head *pos; - struct sockaddr_storage_list *addr; - sctp_bind_addr_t *bp = &ep->base.bind_addr; - - sctp_read_lock(&ep->base.addr_lock); - - /* If we could not find a matching association on - * the endpoint, make sure that there is no peeled- - * off association. - */ - list_for_each(pos, &bp->address_list) { - addr = list_entry(pos, - struct sockaddr_storage_list, - list); - if (sctp_has_association(&addr->a, &to)) { - err = -EINVAL; - sctp_read_unlock(&ep->base.addr_lock); - goto out_unlock; - } + /* If we could not find a matching association on the + * endpoint, make sure that there is no peeled-off + * association on another socket. + */ + if (sctp_endpoint_is_peeled_off(ep, &to)) { + err = -EADDRNOTAVAIL; + goto out_unlock; } - - sctp_read_unlock(&ep->base.addr_lock); } } else { /* For a peeled-off socket, ignore any associd specified by @@ -1116,6 +1104,33 @@ #endif /* 0 */ } +/* This is an extended version of skb_pull() that removes the data from the + * start of a skb even when data is spread across the list of skb's in the + * frag_list. len specifies the total amount of data that needs to be removed. + * when 'len' bytes could be removed from the skb, it returns 0. + * If 'len' exceeds the total skb length, it returns the no. of bytes that + * could not be removed. + */ +static int sctp_skb_pull(struct sk_buff *skb, int len) +{ + struct sk_buff *list; + + if (len <= skb->len) { + __skb_pull(skb, len); + return 0; + } + len -= skb->len; + __skb_pull(skb, skb->len); + + for (list = skb_shinfo(skb)->frag_list; list; list = list->next) { + len = sctp_skb_pull(list, len); + if (!len) + return 0; + } + + return len; +} + /* API 3.1.3 recvmsg() - UDP Style Syntax * * ssize_t recvmsg(int socket, struct msghdr *message, @@ -1138,9 +1153,10 @@ { sctp_ulpevent_t *event = NULL; sctp_opt_t *sp = sctp_sk(sk); - struct sk_buff *skb; + struct sk_buff *skb, *list; int copied; int err = 0; + int skb_len; SCTP_DEBUG_PRINTK("sctp_recvmsg(" "%s: %p, %s: %p, %s: %d, %s: %d, %s: " @@ -1157,21 +1173,16 @@ if (!skb) goto out; - copied = skb->len; - - if (skb_shinfo(skb)->frag_list) { - struct sk_buff *list; + /* Get the total length of the skb including any skb's in the + * frag_list. + */ + skb_len = skb->len; + for (list = skb_shinfo(skb)->frag_list; list; list = list->next) + skb_len += list->len; - for (list = skb_shinfo(skb)->frag_list; - list; - list = list->next) - copied += list->len; - } - - if (copied > len) { + copied = skb_len; + if (copied > len) copied = len; - msg->msg_flags |= MSG_TRUNC; - } err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); @@ -1199,8 +1210,19 @@ err = copied; - /* FIXME: We need to support MSG_EOR correctly. */ - msg->msg_flags |= MSG_EOR; + /* If skb's length exceeds the user's buffer, update the skb and + * push it back to the receive_queue so that the next call to + * recvmsg() will return the remaining data. Don't set MSG_EOR. + * Otherwise, set MSG_EOR indicating the end of a message. + */ + if (skb_len > copied) { + sctp_skb_pull(skb, copied); + skb_queue_head(&sk->receive_queue, skb); + msg->msg_flags &= ~MSG_EOR; + goto out; + } else { + msg->msg_flags |= MSG_EOR; + } out_free: sctp_ulpevent_free(event); /* Free the skb. */ @@ -1252,6 +1274,67 @@ return 0; } +static inline int sctp_setsockopt_set_peer_addr_params(struct sock *sk, + char *optval, + int optlen) +{ + struct sctp_paddrparams params; + sctp_association_t *asoc; + union sctp_addr *addr; + sctp_transport_t *trans; + int error; + + if (optlen != sizeof(struct sctp_paddrparams)) + return -EINVAL; + if (copy_from_user(¶ms, optval, optlen)) + return -EFAULT; + + asoc = sctp_id2assoc(sk, params.spp_assoc_id); + if (!asoc) + return -EINVAL; + + addr = (union sctp_addr *) &(params.spp_address); + + trans = sctp_assoc_lookup_paddr(asoc, addr); + if (!trans) + return -ENOENT; + + /* Applications can enable or disable heartbeats for any peer address + * of an association, modify an address's heartbeat interval, force a + * heartbeat to be sent immediately, and adjust the address's maximum + * number of retransmissions sent before an address is considered + * unreachable. + * + * The value of the heartbeat interval, in milliseconds. A value of + * UINT32_MAX (4294967295), when modifying the parameter, specifies + * that a heartbeat should be sent immediately to the peer address, + * and the current interval should remain unchanged. + */ + if (0xffffffff == params.spp_hbinterval) { + error = sctp_primitive_REQUESTHEARTBEAT (asoc, trans); + if (error) + return error; + } + else { + /* The value of the heartbeat interval, in milliseconds. A value of 0, + * when modifying the parameter, specifies that the heartbeat on this + * address should be disabled. + */ + if (params.spp_hbinterval) { + trans->hb_allowed = 1; + trans->hb_interval = params.spp_hbinterval * HZ / 1000; + } else + trans->hb_allowed = 0; + } + + /* spp_pathmaxrxt contains the maximum number of retransmissions + * before this address shall be considered unreachable. + */ + trans->error_threshold = params.spp_pathmaxrxt; + + return 0; +} + /* API 6.2 setsockopt(), getsockopt() * * Applications use setsockopt() and getsockopt() to set or retrieve @@ -1342,6 +1425,11 @@ retval = sctp_setsockopt_autoclose(sk, optval, optlen); break; + case SCTP_SET_PEER_ADDR_PARAMS: + retval = sctp_setsockopt_set_peer_addr_params(sk, optval, + optlen); + break; + default: retval = -ENOPROTOOPT; break; @@ -1354,11 +1442,107 @@ return retval; } -/* FIXME: Write comments. */ +/* API 3.1.6 connect() - UDP Style Syntax + * + * An application may use the connect() call in the UDP model to initiate an + * association without sending data. + * + * The syntax is: + * + * ret = connect(int sd, const struct sockaddr *nam, socklen_t len); + * + * sd: the socket descriptor to have a new association added to. + * + * nam: the address structure (either struct sockaddr_in or struct + * sockaddr_in6 defined in RFC2553 [7]). + * + * len: the size of the address. + */ SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) { - return -EOPNOTSUPP; /* STUB */ + sctp_opt_t *sp; + sctp_endpoint_t *ep; + sctp_association_t *asoc; + sctp_transport_t *transport; + union sctp_addr to; + sctp_scope_t scope; + long timeo; + int err = 0; + + sctp_lock_sock(sk); + + SCTP_DEBUG_PRINTK("%s - sk: %p, sockaddr: %p, addr_len: %d)\n", + __FUNCTION__, sk, uaddr, addr_len); + + sp = sctp_sk(sk); + ep = sp->ep; + + /* connect() cannot be done on a peeled-off socket. */ + if (SCTP_SOCKET_UDP_HIGH_BANDWIDTH == sp->type) { + err = -EISCONN; + goto out_unlock; + } + + err = sctp_verify_addr(sk, uaddr, addr_len); + if (err) + goto out_unlock; + + memcpy(&to, uaddr, addr_len); + to.v4.sin_port = ntohs(to.v4.sin_port); + + asoc = sctp_endpoint_lookup_assoc(ep, &to, &transport); + if (asoc) { + if (asoc->state >= SCTP_STATE_ESTABLISHED) + err = -EISCONN; + else + err = -EALREADY; + goto out_unlock; + } + + /* If we could not find a matching association on the endpoint, + * make sure that there is no peeled-off association matching the + * peer address even on another socket. + */ + if (sctp_endpoint_is_peeled_off(ep, &to)) { + err = -EADDRNOTAVAIL; + goto out_unlock; + } + + /* If a bind() or sctp_bindx() is not called prior to a connect() + * call, the system picks an ephemeral port and will choose an address + * set equivalent to binding with a wildcard address. + */ + if (!ep->base.bind_addr.port) { + if (sctp_autobind(sk)) { + err = -EAGAIN; + goto out_unlock; + } + } + + scope = sctp_scope(&to); + asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); + if (!asoc) { + err = -ENOMEM; + goto out_unlock; + } + + /* Prime the peer's transport structures. */ + transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL); + + err = sctp_primitive_ASSOCIATE(asoc, NULL); + if (err < 0) { + sctp_association_free(asoc); + goto out_unlock; + } + + timeo = sock_sndtimeo(sk, sk->socket->file->f_flags & O_NONBLOCK); + err = sctp_wait_for_connect(asoc, &timeo); + +out_unlock: + sctp_release_sock(sk); + + return err; } /* FIXME: Write comments. */ @@ -1503,28 +1687,26 @@ if (len != sizeof(status)) { retval = -EINVAL; - goto out_nounlock; + goto out; } if (copy_from_user(&status, optval, sizeof(status))) { retval = -EFAULT; - goto out_nounlock; + goto out; } - sctp_lock_sock(sk); - associd = status.sstat_assoc_id; if ((SCTP_SOCKET_UDP_HIGH_BANDWIDTH != sctp_sk(sk)->type) && associd) { assoc = sctp_id2assoc(sk, associd); if (!assoc) { retval = -EINVAL; - goto out_unlock; + goto out; } } else { ep = sctp_sk(sk)->ep; if (list_empty(&ep->asocs)) { retval = -EINVAL; - goto out_unlock; + goto out; } assoc = list_entry(ep->asocs.next, sctp_association_t, asocs); @@ -1542,8 +1724,8 @@ status.sstat_fragmentation_point = assoc->frag_point; status.sstat_primary.spinfo_assoc_id = sctp_assoc2id(transport->asoc); memcpy(&status.sstat_primary.spinfo_address, - &(transport->ipaddr), sizeof(sockaddr_storage_t)); - status.sstat_primary.spinfo_state = transport->state.active; + &(transport->ipaddr), sizeof(union sctp_addr)); + status.sstat_primary.spinfo_state = transport->active; status.sstat_primary.spinfo_cwnd = transport->cwnd; status.sstat_primary.spinfo_srtt = transport->srtt; status.sstat_primary.spinfo_rto = transport->rto; @@ -1551,7 +1733,7 @@ if (put_user(len, optlen)) { retval = -EFAULT; - goto out_unlock; + goto out; } SCTP_DEBUG_PRINTK("sctp_getsockopt_sctp_status(%d): %d %d %p\n", @@ -1560,13 +1742,10 @@ if (copy_to_user(optval, &status, len)) { retval = -EFAULT; - goto out_unlock; + goto out; } -out_unlock: - sctp_release_sock(sk); - -out_nounlock: +out: return (retval); } @@ -1684,25 +1863,23 @@ if (copy_from_user(&peeloff, optval, len)) return -EFAULT; - sctp_lock_sock(sk); - assoc = sctp_id2assoc(sk, peeloff.associd); if (NULL == assoc) { retval = -EINVAL; - goto out_unlock; + goto out; } SCTP_DEBUG_PRINTK("%s: sk: %p assoc: %p\n", __FUNCTION__, sk, assoc); retval = sctp_do_peeloff(assoc, &newsock); if (retval < 0) - goto out_unlock; + goto out; /* Map the socket to an unused fd that can be returned to the user. */ retval = sock_map_fd(newsock); if (retval < 0) { sock_release(newsock); - goto out_unlock; + goto out; } SCTP_DEBUG_PRINTK("%s: sk: %p assoc: %p newsk: %p sd: %d\n", @@ -1713,11 +1890,54 @@ if (copy_to_user(optval, &peeloff, len)) retval = -EFAULT; -out_unlock: - sctp_release_sock(sk); +out: return retval; } +static inline int sctp_getsockopt_get_peer_addr_params(struct sock *sk, + int len, char *optval, int *optlen) +{ + struct sctp_paddrparams params; + sctp_association_t *asoc; + union sctp_addr *addr; + sctp_transport_t *trans; + + if (len != sizeof(struct sctp_paddrparams)) + return -EINVAL; + if (copy_from_user(¶ms, optval, *optlen)) + return -EFAULT; + + asoc = sctp_id2assoc(sk, params.spp_assoc_id); + if (!asoc) + return -EINVAL; + + addr = (union sctp_addr *) &(params.spp_address); + + trans = sctp_assoc_lookup_paddr(asoc, addr); + if (!trans) + return -ENOENT; + + /* The value of the heartbeat interval, in milliseconds. A value of 0, + * when modifying the parameter, specifies that the heartbeat on this + * address should be disabled. + */ + if (!trans->hb_allowed) + params.spp_hbinterval = 0; + else + params.spp_hbinterval = trans->hb_interval * 1000 / HZ; + + /* spp_pathmaxrxt contains the maximum number of retransmissions + * before this address shall be considered unreachable. + */ + params.spp_pathmaxrxt = trans->error_threshold; + + if (copy_to_user(optval, ¶ms, len)) + return -EFAULT; + *optlen = len; + + return 0; +} + SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, char *optval, int *optlen) { @@ -1748,6 +1968,8 @@ if (get_user(len, optlen)) return -EFAULT; + sctp_lock_sock(sk); + switch (optname) { case SCTP_STATUS: retval = sctp_getsockopt_sctp_status(sk, len, optval, optlen); @@ -1770,11 +1992,17 @@ retval = sctp_getsockopt_peeloff(sk, len, optval, optlen); break; + case SCTP_GET_PEER_ADDR_PARAMS: + retval = sctp_getsockopt_get_peer_addr_params(sk, len, optval, + optlen); + break; + default: retval = -ENOPROTOOPT; break; }; + sctp_release_sock(sk); return retval; } @@ -1880,7 +2108,7 @@ * socket is going to be sk2. */ int sk_reuse = sk->reuse; - sockaddr_storage_t tmpaddr; + union sctp_addr tmpaddr; struct sock *sk2 = pp->sk; SCTP_DEBUG_PRINTK("sctp_get_port() found a " @@ -1923,12 +2151,13 @@ sctp_endpoint_t *ep2; ep2 = sctp_sk(sk2)->ep; - if (!sk_reuse || !sk2->reuse) { - if (sctp_bind_addr_has_addr( - &ep2->base.bind_addr, &tmpaddr)) { - goto found; - } - } + if (sk_reuse && sk2->reuse) + continue; + + if (sctp_bind_addr_match(&ep2->base.bind_addr, + &tmpaddr, + sctp_sk(sk))) + goto found; } found: @@ -2183,34 +2412,17 @@ */ static int sctp_autobind(struct sock *sk) { - sockaddr_storage_t autoaddr; - int addr_len = 0; + union sctp_addr autoaddr; + struct sctp_func *af; + unsigned short port; - memset(&autoaddr, 0, sizeof(sockaddr_storage_t)); + /* Initialize a local sockaddr structure to INADDR_ANY. */ + af = sctp_sk(sk)->pf->af; - switch (sk->family) { - case PF_INET: - autoaddr.v4.sin_family = AF_INET; - autoaddr.v4.sin_addr.s_addr = INADDR_ANY; - autoaddr.v4.sin_port = htons(inet_sk(sk)->num); - addr_len = sizeof(struct sockaddr_in); - break; - - case PF_INET6: - SCTP_V6( - /* FIXME: Write me for v6! */ - BUG(); - autoaddr.v6.sin6_family = AF_INET6; - autoaddr.v6.sin6_port = htons(inet_sk(sk)->num); - addr_len = sizeof(struct sockaddr_in6); - ); - break; - - default: /* This should not happen. */ - break; - }; + port = htons(inet_sk(sk)->num); + af->inaddr_any(&autoaddr, port); - return sctp_do_bind(sk, &autoaddr, addr_len); + return sctp_do_bind(sk, &autoaddr, af->sockaddr_len); } /* Parse out IPPROTO_SCTP CMSG headers. Perform only minimal validation. @@ -2327,8 +2539,8 @@ /* Setup sk->rcv_saddr before calling get_port(). */ static inline void sctp_sk_addr_set(struct sock *sk, - const sockaddr_storage_t *newaddr, - sockaddr_storage_t *saveaddr) + const union sctp_addr *newaddr, + union sctp_addr *saveaddr) { struct inet_opt *inet = inet_sk(sk); @@ -2355,7 +2567,7 @@ } /* Restore sk->rcv_saddr after failing get_port(). */ -static inline void sctp_sk_addr_restore(struct sock *sk, const sockaddr_storage_t *addr) +static inline void sctp_sk_addr_restore(struct sock *sk, const union sctp_addr *addr) { struct inet_opt *inet = inet_sk(sk); @@ -2498,38 +2710,33 @@ return NULL; } -static inline int sctp_sendmsg_verify_name(struct sock *sk, struct msghdr *msg) +/* Verify that this is a valid address. */ +static int sctp_verify_addr(struct sock *sk, struct sockaddr *addr, int len) { - sockaddr_storage_t *sa; + struct sctp_func *af; - if (msg->msg_namelen < sizeof (struct sockaddr)) + /* Check minimum size. */ + if (len < sizeof (struct sockaddr)) return -EINVAL; - sa = (sockaddr_storage_t *) msg->msg_name; - switch (sa->sa.sa_family) { - case AF_INET: - if (msg->msg_namelen < sizeof(struct sockaddr_in)) - return -EINVAL; - break; - - case AF_INET6: - if (PF_INET == sk->family) - return -EINVAL; - SCTP_V6( - if (msg->msg_namelen < sizeof(struct sockaddr_in6)) - return -EINVAL; - break; - ); + /* Do we support this address family in general? */ + af = sctp_get_af_specific(addr->sa_family); + if (!af) + return -EINVAL; - default: + /* Does this PF support this AF? */ + if (!sctp_sk(sk)->pf->af_supported(addr->sa_family)) + return -EINVAL; + + /* Verify the minimum for this AF sockaddr. */ + if (len < af->sockaddr_len) return -EINVAL; - }; - /* Disallow any illegal addresses to be used as destinations. */ - if (!sctp_addr_is_valid(sa)) + /* Is this a valid SCTP address? */ + if (!af->addr_valid((union sctp_addr *)addr)) return -EINVAL; - return 0; + return 0; } /* Get the sndbuf space available at the time on the association. */ @@ -2708,6 +2915,70 @@ if (amt < 0) amt = 0; return amt; +} + +/* Wait for an association to go into ESTABLISHED state. If timeout is 0, + * returns immediately with EINPROGRESS. + */ +static int sctp_wait_for_connect(sctp_association_t *asoc, long *timeo_p) +{ + struct sock *sk = asoc->base.sk; + int err = 0; + long current_timeo = *timeo_p; + DECLARE_WAITQUEUE(wait, current); + + SCTP_DEBUG_PRINTK("%s: asoc=%p, timeo=%ld\n", __FUNCTION__, asoc, + (long)(*timeo_p)); + + add_wait_queue_exclusive(&asoc->wait, &wait); + + /* Increment the association's refcnt. */ + sctp_association_hold(asoc); + + for (;;) { + __set_current_state(TASK_INTERRUPTIBLE); + if (!*timeo_p) + goto do_nonblock; + if (sk->err || asoc->state >= SCTP_STATE_SHUTDOWN_PENDING || + asoc->base.dead) + goto do_error; + if (signal_pending(current)) + goto do_interrupted; + + if (asoc->state == SCTP_STATE_ESTABLISHED) + break; + + /* Let another process have a go. Since we are going + * to sleep anyway. + */ + sctp_release_sock(sk); + current_timeo = schedule_timeout(current_timeo); + sctp_lock_sock(sk); + + *timeo_p = current_timeo; + } + +out: + remove_wait_queue(&asoc->wait, &wait); + + /* Release the association's refcnt. */ + sctp_association_put(asoc); + + __set_current_state(TASK_RUNNING); + + return err; + +do_error: + err = -ECONNABORTED; + goto out; + +do_interrupted: + err = sock_intr_errno(*timeo_p); + goto out; + +do_nonblock: + err = -EINPROGRESS; + goto out; } /* This proto struct describes the ULP interface for SCTP. */ diff -Nru a/net/sctp/transport.c b/net/sctp/transport.c --- a/net/sctp/transport.c Fri Nov 22 13:41:18 2002 +++ b/net/sctp/transport.c Fri Nov 22 13:41:18 2002 @@ -9,7 +9,7 @@ * * This module provides the abstraction for an SCTP tranport representing * a remote transport address. For local transport addresses, we just use - * sockaddr_storage_t. + * union sctp_addr. * * The SCTP reference implementation is free software; * you can redistribute it and/or modify it under the terms of @@ -53,7 +53,7 @@ /* 1st Level Abstractions. */ /* Allocate and initialize a new transport. */ -sctp_transport_t *sctp_transport_new(const sockaddr_storage_t *addr, int priority) +sctp_transport_t *sctp_transport_new(const union sctp_addr *addr, int priority) { sctp_transport_t *transport; @@ -78,14 +78,14 @@ /* Intialize a new transport from provided memory. */ sctp_transport_t *sctp_transport_init(sctp_transport_t *peer, - const sockaddr_storage_t *addr, + const union sctp_addr *addr, int priority) { sctp_protocol_t *proto = sctp_get_protocol(); /* Copy in the address. */ peer->ipaddr = *addr; - peer->af_specific = sctp_get_af_specific(addr); + peer->af_specific = sctp_get_af_specific(addr->sa.sa_family); peer->asoc = NULL; /* From 6.3.1 RTO Calculation: @@ -104,8 +104,8 @@ peer->last_time_used = jiffies; peer->last_time_ecne_reduced = jiffies; - peer->state.active = 1; - peer->state.hb_allowed = 0; + peer->active = 1; + peer->hb_allowed = 0; /* Initialize the default path max_retrans. */ peer->max_retrans = proto->max_retrans_path; @@ -203,17 +203,18 @@ /* Caches the dst entry for a transport's destination address and an optional * souce address. */ -void sctp_transport_route(sctp_transport_t *transport, - sockaddr_storage_t *saddr) +void sctp_transport_route(sctp_transport_t *transport, union sctp_addr *saddr, + struct sctp_opt *opt) { sctp_association_t *asoc = transport->asoc; - sctp_func_t *af = transport->af_specific; - sockaddr_storage_t *daddr = &transport->ipaddr; + struct sctp_func *af = transport->af_specific; + union sctp_addr *daddr = &transport->ipaddr; sctp_bind_addr_t *bp; rwlock_t *addr_lock; struct sockaddr_storage_list *laddr; struct list_head *pos; struct dst_entry *dst; + union sctp_addr dst_saddr; dst = af->get_dst(daddr, saddr); @@ -239,7 +240,8 @@ list_for_each(pos, &bp->address_list) { laddr = list_entry(pos, struct sockaddr_storage_list, list); - if (af->cmp_saddr(dst, &laddr->a)) + af->dst_saddr(&dst_saddr, dst); + if (opt->pf->cmp_addr(&dst_saddr, &laddr->a, opt)) goto out_unlock; } sctp_read_unlock(addr_lock); diff -Nru a/net/socket.c b/net/socket.c --- a/net/socket.c Fri Nov 22 13:41:18 2002 +++ b/net/socket.c Fri Nov 22 13:41:18 2002 @@ -468,7 +468,6 @@ if (!inode) return NULL; - inode->i_dev = 0; sock = SOCKET_I(inode); inode->i_mode = S_IFSOCK|S_IRWXUGO; @@ -491,6 +490,10 @@ return -ENXIO; } +struct file_operations bad_sock_fops = { + .open = sock_no_open, +}; + /** * sock_release - close a socket * @sock: socket to close @@ -726,8 +729,8 @@ * what to do with it - that's up to the protocol still. */ -int sock_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) +static int sock_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) { struct socket *sock; int pid, err; diff -Nru a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c --- a/net/sunrpc/svcsock.c Fri Nov 22 13:41:18 2002 +++ b/net/sunrpc/svcsock.c Fri Nov 22 13:41:18 2002 @@ -324,10 +324,8 @@ static int svc_sendto(struct svc_rqst *rqstp, struct xdr_buf *xdr) { - mm_segment_t oldfs; struct svc_sock *svsk = rqstp->rq_sock; struct socket *sock = svsk->sk_sock; - struct msghdr msg; int slen; int len = 0; int result; @@ -339,23 +337,23 @@ slen = xdr->len; - msg.msg_name = &rqstp->rq_addr; - msg.msg_namelen = sizeof(rqstp->rq_addr); - msg.msg_iov = NULL; - msg.msg_iovlen = 0; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = MSG_MORE; - /* Grab svsk->sk_sem to serialize outgoing data. */ down(&svsk->sk_sem); - /* set the destination */ - oldfs = get_fs(); set_fs(KERNEL_DS); - len = sock_sendmsg(sock, &msg, 0); - set_fs(oldfs); - if (len < 0) - goto out; + if (rqstp->rq_prot == IPPROTO_UDP) { + /* set the destination */ + struct msghdr msg; + msg.msg_name = &rqstp->rq_addr; + msg.msg_namelen = sizeof(rqstp->rq_addr); + msg.msg_iov = NULL; + msg.msg_iovlen = 0; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = MSG_MORE; + + if (sock_sendmsg(sock, &msg, 0) < 0) + goto out; + } /* send head */ if (slen == xdr->head[0].iov_len) @@ -564,18 +562,8 @@ set_bit(SK_DATA, &svsk->sk_flags); /* there may be more data... */ len = skb->len - sizeof(struct udphdr); - - if (csum_partial_copy_to_xdr(&rqstp->rq_arg, skb)) { - /* checksum error */ - skb_free_datagram(svsk->sk_sk, skb); - svc_sock_received(svsk); - return 0; - } - - rqstp->rq_arg.len = len; - rqstp->rq_arg.page_len = len - rqstp->rq_arg.head[0].iov_len; - rqstp->rq_argused += (rqstp->rq_arg.page_len + PAGE_SIZE - 1)/ PAGE_SIZE; + rqstp->rq_prot = IPPROTO_UDP; /* Get sender address */ @@ -583,7 +571,38 @@ rqstp->rq_addr.sin_port = skb->h.uh->source; rqstp->rq_addr.sin_addr.s_addr = skb->nh.iph->saddr; - skb_free_datagram(svsk->sk_sk, skb); + if (skb_is_nonlinear(skb)) { + /* we have to copy */ + if (csum_partial_copy_to_xdr(&rqstp->rq_arg, skb)) { + /* checksum error */ + skb_free_datagram(svsk->sk_sk, skb); + svc_sock_received(svsk); + return 0; + } + skb_free_datagram(svsk->sk_sk, skb); + } else { + /* we can use it in-place */ + rqstp->rq_arg.head[0].iov_base = skb->data + sizeof(struct udphdr); + rqstp->rq_arg.head[0].iov_len = len; + if (skb->ip_summed != CHECKSUM_UNNECESSARY) { + if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) { + skb_free_datagram(svsk->sk_sk, skb); + svc_sock_received(svsk); + return 0; + } + skb->ip_summed = CHECKSUM_UNNECESSARY; + } + rqstp->rq_skbuff = skb; + } + + rqstp->rq_arg.page_base = 0; + if (len <= rqstp->rq_arg.head[0].iov_len) { + rqstp->rq_arg.head[0].iov_len = len; + rqstp->rq_arg.page_len = 0; + } else { + rqstp->rq_arg.page_len = len - rqstp->rq_arg.head[0].iov_len; + rqstp->rq_argused += (rqstp->rq_arg.page_len + PAGE_SIZE - 1)/ PAGE_SIZE; + } if (serv->sv_stats) serv->sv_stats->netudpcnt++; diff -Nru a/scripts/Makefile.lib b/scripts/Makefile.lib --- a/scripts/Makefile.lib Fri Nov 22 13:41:20 2002 +++ b/scripts/Makefile.lib Fri Nov 22 13:41:20 2002 @@ -130,8 +130,8 @@ $(basename_flags) $(modname_flags) $(export_flags) # Finds the multi-part object the current object will be linked into -modname-multi = $(subst $(space),_,$(strip $(foreach m,$(multi-used),\ - $(if $(filter $(*F).o,$($(m:.o=-objs))),$(m:.o=))))) +modname-multi = $(subst $(space),_,$(sort $(foreach m,$(multi-used),\ + $(if $(filter $(subst $(obj)/,,$*.o), $($(m:.o=-objs)) $($(m:.o=-y))),$(m:.o=))))) # Shipped files # =========================================================================== diff -Nru a/scripts/kallsyms b/scripts/kallsyms --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/scripts/kallsyms Fri Nov 22 13:41:23 2002 @@ -0,0 +1,40 @@ +#! /bin/sh +# Written by Rusty Russell 2002. + +if [ $# -ne 2 ]; then + echo Usage: kallsyms vmlinux objfile >&2 + + echo Adds a .kallsyms section containing symbol info. + exit 1 +fi + +set -e + +# Clean up on exit. +trap "rm -f kallsyms.map kallsyms.c $2" 0 + +# Takes nm output from $1, produces a .c file on standard output. +encode_symbols() +{ + # First take addresses. + echo "unsigned long kallsyms_addresses[] = {" + sed 's/^[ ]*\([A-Fa-f0-9]*\).*/0x\1UL,/' < $1 + echo "};" + + # Now output size. + echo "unsigned long kallsyms_num_syms = `wc -l < $1`;" + + # Now output names. + echo "char kallsyms_names[] = "; + sed 's/^[ ]*[A-Fa-f0-9]*[ ]*.[ ]\(.*\)/"\1\\0"/' < $1 + echo ";" +} + +# FIXME: Use System.map as input, and regenerate each time in Makefile. +$NM $1 | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > kallsyms.map + +encode_symbols kallsyms.map > kallsyms.c +$CC $CFLAGS -c -o $2 kallsyms.c + +trap "rm -f kallsyms.map kallsyms.c" 0 +exit 0 diff -Nru a/scripts/per-cpu-check.awk b/scripts/per-cpu-check.awk --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/scripts/per-cpu-check.awk Fri Nov 22 13:41:23 2002 @@ -0,0 +1,19 @@ +/ __per_cpu_start$$/ { + IN_PER_CPU=1 +} + +/ __per_cpu_end$$/ { + IN_PER_CPU=0 +} + +/__per_cpu$$/ && ! / __ksymtab_/ { + if (!IN_PER_CPU) { + print $$3 " not in per-cpu section" > "/dev/stderr"; + FOUND=1; + } +} + +END { + exit FOUND; +} + diff -Nru a/security/capability.c b/security/capability.c --- a/security/capability.c Fri Nov 22 13:41:18 2002 +++ b/security/capability.c Fri Nov 22 13:41:18 2002 @@ -340,13 +340,13 @@ } static int cap_inode_mknod (struct inode *inode, struct dentry *dentry, - int major, dev_t minor) + int mode, dev_t dev) { return 0; } static void cap_inode_post_mknod (struct inode *inode, struct dentry *dentry, - int major, dev_t minor) + int mode, dev_t dev) { return; } diff -Nru a/security/dummy.c b/security/dummy.c --- a/security/dummy.c Fri Nov 22 13:41:18 2002 +++ b/security/dummy.c Fri Nov 22 13:41:18 2002 @@ -27,6 +27,17 @@ static int dummy_capget (struct task_struct *target, kernel_cap_t * effective, kernel_cap_t * inheritable, kernel_cap_t * permitted) { + *effective = *inheritable = *permitted = 0; + if (!issecure(SECURE_NOROOT)) { + if (target->euid == 0) { + *permitted |= (~0 & ~CAP_FS_MASK); + *effective |= (~0 & ~CAP_TO_MASK(CAP_SETPCAP) & ~CAP_FS_MASK); + } + if (target->fsuid == 0) { + *permitted |= CAP_FS_MASK; + *effective |= CAP_FS_MASK; + } + } return 0; } @@ -35,7 +46,7 @@ kernel_cap_t * inheritable, kernel_cap_t * permitted) { - return 0; + return -EPERM; } static void dummy_capset_set (struct task_struct *target, @@ -240,13 +251,13 @@ } static int dummy_inode_mknod (struct inode *inode, struct dentry *dentry, - int major, dev_t minor) + int mode, dev_t dev) { return 0; } static void dummy_inode_post_mknod (struct inode *inode, struct dentry *dentry, - int major, dev_t minor) + int mode, dev_t dev) { return; } diff -Nru a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c --- a/sound/isa/ad1816a/ad1816a_lib.c Fri Nov 22 13:41:21 2002 +++ b/sound/isa/ad1816a/ad1816a_lib.c Fri Nov 22 13:41:21 2002 @@ -19,14 +19,16 @@ */ #include -#include -#include #include #include +#include #include #include #include #include + +#include +#include MODULE_AUTHOR("Massimo Piccioni "); MODULE_DESCRIPTION("lowlevel code for Analog Devices AD1816A chip"); diff -Nru a/sound/oss/cs4281/cs4281_wrapper-24.c b/sound/oss/cs4281/cs4281_wrapper-24.c --- a/sound/oss/cs4281/cs4281_wrapper-24.c Fri Nov 22 13:41:18 2002 +++ b/sound/oss/cs4281/cs4281_wrapper-24.c Fri Nov 22 13:41:18 2002 @@ -26,7 +26,8 @@ #include -void cs4281_null(struct pci_dev *pcidev) { return; } +int cs4281_resume_null(struct pci_dev *pcidev) { return 0; } +int cs4281_suspend_null(struct pci_dev *pcidev, u32 state) { return 0; } #define cs4x_mem_map_reserve(page) mem_map_reserve(page) #define cs4x_mem_map_unreserve(page) mem_map_unreserve(page) diff -Nru a/sound/oss/cs4281/cs4281m.c b/sound/oss/cs4281/cs4281m.c --- a/sound/oss/cs4281/cs4281m.c Fri Nov 22 13:41:23 2002 +++ b/sound/oss/cs4281/cs4281m.c Fri Nov 22 13:41:23 2002 @@ -69,15 +69,19 @@ #include #include #include -#include -#include #include +#include #include -#include #include #include +#include + +#include +#include +#include +#include #include -#include + //#include "cs_dm.h" #include "cs4281_hwdefs.h" #include "cs4281pm.h" @@ -2622,10 +2626,10 @@ // Mixer file operations struct. // ****************************************************************************************** static /*const */ struct file_operations cs4281_mixer_fops = { - llseek:no_llseek, - ioctl:cs4281_ioctl_mixdev, - open:cs4281_open_mixdev, - release:cs4281_release_mixdev, + .llseek = no_llseek, + .ioctl = cs4281_ioctl_mixdev, + .open = cs4281_open_mixdev, + .release = cs4281_release_mixdev, }; // --------------------------------------------------------------------- @@ -3743,14 +3747,14 @@ // Wave (audio) file operations struct. // ****************************************************************************************** static /*const */ struct file_operations cs4281_audio_fops = { - llseek:no_llseek, - read:cs4281_read, - write:cs4281_write, - poll:cs4281_poll, - ioctl:cs4281_ioctl, - mmap:cs4281_mmap, - open:cs4281_open, - release:cs4281_release, + .llseek = no_llseek, + .read = cs4281_read, + .write = cs4281_write, + .poll = cs4281_poll, + .ioctl = cs4281_ioctl, + .mmap = cs4281_mmap, + .open = cs4281_open, + .release = cs4281_release, }; // --------------------------------------------------------------------- @@ -4092,12 +4096,12 @@ // Midi file operations struct. // ****************************************************************************************** static /*const */ struct file_operations cs4281_midi_fops = { - llseek:no_llseek, - read:cs4281_midi_read, - write:cs4281_midi_write, - poll:cs4281_midi_poll, - open:cs4281_midi_open, - release:cs4281_midi_release, + .llseek = no_llseek, + .read = cs4281_midi_read, + .write = cs4281_midi_write, + .poll = cs4281_midi_poll, + .open = cs4281_midi_open, + .release = cs4281_midi_release, }; @@ -4467,20 +4471,24 @@ } static struct pci_device_id cs4281_pci_tbl[] __devinitdata = { - {PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CRYSTAL_CS4281, - PCI_ANY_ID, PCI_ANY_ID, 0, 0}, - {0,} + { + .vendor = PCI_VENDOR_ID_CIRRUS, + .device = PCI_DEVICE_ID_CRYSTAL_CS4281, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { 0, }, }; MODULE_DEVICE_TABLE(pci, cs4281_pci_tbl); struct pci_driver cs4281_pci_driver = { - name:"cs4281", - id_table:cs4281_pci_tbl, - probe:cs4281_probe, - remove:cs4281_remove, - suspend:CS4281_SUSPEND_TBL, - resume:CS4281_RESUME_TBL, + .name = "cs4281", + .id_table = cs4281_pci_tbl, + .probe = cs4281_probe, + .remove = cs4281_remove, + .suspend = CS4281_SUSPEND_TBL, + .resume = CS4281_RESUME_TBL, }; int __init cs4281_init_module(void) diff -Nru a/sound/oss/cs4281/cs4281pm-24.c b/sound/oss/cs4281/cs4281pm-24.c --- a/sound/oss/cs4281/cs4281pm-24.c Fri Nov 22 13:41:21 2002 +++ b/sound/oss/cs4281/cs4281pm-24.c Fri Nov 22 13:41:21 2002 @@ -38,8 +38,8 @@ #define CS4281_SUSPEND_TBL cs4281_suspend_tbl #define CS4281_RESUME_TBL cs4281_resume_tbl */ -#define CS4281_SUSPEND_TBL cs4281_null -#define CS4281_RESUME_TBL cs4281_null +#define CS4281_SUSPEND_TBL cs4281_suspend_null +#define CS4281_RESUME_TBL cs4281_resume_null int cs4281_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) { @@ -78,7 +78,7 @@ } #else /* CS4281_PM */ -#define CS4281_SUSPEND_TBL cs4281_null -#define CS4281_RESUME_TBL cs4281_null +#define CS4281_SUSPEND_TBL cs4281_suspend_null +#define CS4281_RESUME_TBL cs4281_resume_null #endif /* CS4281_PM */ diff -Nru a/sound/oss/cs46xx.c b/sound/oss/cs46xx.c --- a/sound/oss/cs46xx.c Fri Nov 22 13:41:17 2002 +++ b/sound/oss/cs46xx.c Fri Nov 22 13:41:17 2002 @@ -75,6 +75,7 @@ * turned on. */ +#include #include #include #include @@ -87,18 +88,18 @@ #include #include #include -#include -#include #include #include -#include #include +#include + +#include +#include #include #include -#include + #include "cs46xxpm-24.h" #include "cs46xx_wrapper-24.h" - #include "cs461x.h" /* MIDI buffer sizes */ @@ -5243,22 +5244,85 @@ void (*active)(struct cs_card *, int); }; -static struct cs_card_type cards[]={ - {0x1489, 0x7001, "Genius Soundmaker 128 value", amp_none, NULL, NULL}, - {0x5053, 0x3357, "Voyetra", amp_voyetra, NULL, NULL}, - {0x1071, 0x6003, "Mitac MI6020/21", amp_voyetra, NULL, NULL}, - {0x14AF, 0x0050, "Hercules Game Theatre XP", amp_hercules, NULL, NULL}, - {0x1681, 0x0050, "Hercules Game Theatre XP", amp_hercules, NULL, NULL}, - {0x1681, 0x0051, "Hercules Game Theatre XP", amp_hercules, NULL, NULL}, - {0x1681, 0x0052, "Hercules Game Theatre XP", amp_hercules, NULL, NULL}, - {0x1681, 0x0053, "Hercules Game Theatre XP", amp_hercules, NULL, NULL}, - {0x1681, 0x0054, "Hercules Game Theatre XP", amp_hercules, NULL, NULL}, +static struct cs_card_type cards[] = { + { + .vendor = 0x1489, + .id = 0x7001, + .name = "Genius Soundmaker 128 value", + .amp = amp_none, + }, + { + .vendor = 0x5053, + .id = 0x3357, + .name = "Voyetra", + .amp = amp_voyetra, + }, + { + .vendor = 0x1071, + .id = 0x6003, + .name = "Mitac MI6020/21", + .amp = amp_voyetra, + }, + { + .vendor = 0x14AF, + .id = 0x0050, + .name = "Hercules Game Theatre XP", + .amp = amp_hercules, + }, + { + .vendor = 0x1681, + .id = 0x0050, + .name = "Hercules Game Theatre XP", + .amp = amp_hercules, + }, + { + .vendor = 0x1681, + .id = 0x0051, + .name = "Hercules Game Theatre XP", + .amp = amp_hercules, + }, + { + .vendor = 0x1681, + .id = 0x0052, + .name = "Hercules Game Theatre XP", + .amp = amp_hercules, + }, + { + .vendor = 0x1681, + .id = 0x0053, + .name = "Hercules Game Theatre XP", + .amp = amp_hercules, + }, + { + .vendor = 0x1681, + .id = 0x0054, + .name = "Hercules Game Theatre XP", + .amp = amp_hercules, + }, /* Not sure if the 570 needs the clkrun hack */ - {PCI_VENDOR_ID_IBM, 0x0132, "Thinkpad 570", amp_none, NULL, clkrun_hack}, - {PCI_VENDOR_ID_IBM, 0x0153, "Thinkpad 600X/A20/T20", amp_none, NULL, clkrun_hack}, - {PCI_VENDOR_ID_IBM, 0x1010, "Thinkpad 600E (unsupported)", NULL, NULL, NULL}, - {0, 0, "Card without SSID set", NULL, NULL, NULL }, - {0, 0, NULL, NULL, NULL} + { + .vendor = PCI_VENDOR_ID_IBM, + .id = 0x0132, + .name = "Thinkpad 570", + .amp = amp_none, + .active = clkrun_hack, + }, + { + .vendor = PCI_VENDOR_ID_IBM, + .id = 0x0153, + .name = "Thinkpad 600X/A20/T20", + .amp = amp_none, + .active = clkrun_hack, + }, + { + .vendor = PCI_VENDOR_ID_IBM, + .id = 0x1010, + .name = "Thinkpad 600E (unsupported)", + }, + { + .name = "Card without SSID set", + }, + { 0, }, }; MODULE_AUTHOR("Alan Cox , Jaroslav Kysela, "); @@ -5622,22 +5686,39 @@ }; static struct pci_device_id cs46xx_pci_tbl[] __devinitdata = { - - {PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_4610, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CS46XX_4610}, - {PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_4612, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CS46XX_4612}, - {PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_4615, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CS46XX_4615}, - {0,} + { + .vendor = PCI_VENDOR_ID_CIRRUS, + .device = PCI_DEVICE_ID_CIRRUS_4610, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = CS46XX_4610, + }, + { + .vendor = PCI_VENDOR_ID_CIRRUS, + .device = PCI_DEVICE_ID_CIRRUS_4612, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = CS46XX_4612, + }, + { + .vendor = PCI_VENDOR_ID_CIRRUS, + .device = PCI_DEVICE_ID_CIRRUS_4615, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = CS46XX_4615, + }, + { 0, }, }; MODULE_DEVICE_TABLE(pci, cs46xx_pci_tbl); struct pci_driver cs46xx_pci_driver = { - .name= "cs46xx", - .id_table= cs46xx_pci_tbl, - .probe= cs46xx_probe, - .remove= cs46xx_remove, - .suspend= CS46XX_SUSPEND_TBL, - .resume= CS46XX_RESUME_TBL, + .name = "cs46xx", + .id_table = cs46xx_pci_tbl, + .probe = cs46xx_probe, + .remove = cs46xx_remove, + .suspend = CS46XX_SUSPEND_TBL, + .resume = CS46XX_RESUME_TBL, }; int __init cs46xx_init_module(void) diff -Nru a/sound/oss/maestro.c b/sound/oss/maestro.c --- a/sound/oss/maestro.c Fri Nov 22 13:41:23 2002 +++ b/sound/oss/maestro.c Fri Nov 22 13:41:23 2002 @@ -219,14 +219,18 @@ #include #include #include -#include -#include #include +#include #include #include -#include -#include #include +#include + +#include +#include +#include +#include +#include #include static int maestro_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *d); @@ -3609,10 +3613,10 @@ MODULE_DEVICE_TABLE(pci, maestro_pci_tbl); static struct pci_driver maestro_pci_driver = { - name:"maestro", - id_table:maestro_pci_tbl, - probe:maestro_probe, - remove:maestro_remove, + .name = "maestro", + .id_table = maestro_pci_tbl, + .probe = maestro_probe, + .remove = maestro_remove, }; int __init init_maestro(void) diff -Nru a/sound/oss/maestro3.c b/sound/oss/maestro3.c --- a/sound/oss/maestro3.c Fri Nov 22 13:41:23 2002 +++ b/sound/oss/maestro3.c Fri Nov 22 13:41:23 2002 @@ -137,15 +137,17 @@ #include #include #include -#include -#include #include +#include #include #include -#include -#include #include #include +#include + +#include +#include +#include /* * for crizappy mmap() @@ -320,15 +322,15 @@ #define PCI_VENDOR_ESS 0x125D #endif -#define M3_DEVICE(DEV, TYPE) \ -{ \ -vendor: PCI_VENDOR_ESS, \ -device: DEV, \ -subvendor: PCI_ANY_ID, \ -subdevice: PCI_ANY_ID, \ -class: PCI_CLASS_MULTIMEDIA_AUDIO << 8, \ -class_mask: 0xffff << 8, \ -driver_data: TYPE, \ +#define M3_DEVICE(DEV, TYPE) \ +{ \ +.vendor = PCI_VENDOR_ESS, \ +.device = DEV, \ +.subvendor = PCI_ANY_ID, \ +.subdevice = PCI_ANY_ID, \ +.class = PCI_CLASS_MULTIMEDIA_AUDIO << 8, \ +.class_mask = 0xffff << 8, \ +.driver_data = TYPE, \ } static struct pci_device_id m3_id_table[] __initdata = { @@ -381,7 +383,9 @@ static int m3_suspend(struct pci_dev *pci_dev, u32 state); static void check_suspend(struct m3_card *card); -struct notifier_block m3_reboot_nb = {m3_notifier, NULL, 0}; +struct notifier_block m3_reboot_nb = { + .notifier_call = m3_notifier, +}; static void m3_outw(struct m3_card *card, u16 value, unsigned long reg) @@ -2179,11 +2183,11 @@ } static struct file_operations m3_mixer_fops = { - owner: THIS_MODULE, - llseek: no_llseek, - ioctl: m3_ioctl_mixdev, - open: m3_open_mixdev, - release: m3_release_mixdev, + .owner = THIS_MODULE, + .llseek = no_llseek, + .ioctl = m3_ioctl_mixdev, + .open = m3_open_mixdev, + .release = m3_release_mixdev, }; void remote_codec_config(int io, int isremote) @@ -2559,15 +2563,15 @@ } static struct file_operations m3_audio_fops = { - owner: THIS_MODULE, - llseek: &no_llseek, - read: &m3_read, - write: &m3_write, - poll: &m3_poll, - ioctl: &m3_ioctl, - mmap: &m3_mmap, - open: &m3_open, - release: &m3_release, + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = m3_read, + .write = m3_write, + .poll = m3_poll, + .ioctl = m3_ioctl, + .mmap = m3_mmap, + .open = m3_open, + .release = m3_release, }; #ifdef CONFIG_PM @@ -2925,12 +2929,12 @@ MODULE_PARM(gpio_pin, "i"); static struct pci_driver m3_pci_driver = { - name: "ess_m3_audio", - id_table: m3_id_table, - probe: m3_probe, - remove: m3_remove, - suspend: m3_suspend, - resume: m3_resume, + .name = "ess_m3_audio", + .id_table = m3_id_table, + .probe = m3_probe, + .remove = m3_remove, + .suspend = m3_suspend, + .resume = m3_resume, }; static int __init m3_init_module(void) diff -Nru a/sound/oss/rme96xx.c b/sound/oss/rme96xx.c --- a/sound/oss/rme96xx.c Fri Nov 22 13:41:19 2002 +++ b/sound/oss/rme96xx.c Fri Nov 22 13:41:19 2002 @@ -41,10 +41,14 @@ #include #include #include -#include -#include #include +#include #include +#include + +#include +#include + #include "rme96xx.h" #define NR_DEVICE 2 @@ -808,17 +812,22 @@ #endif static struct pci_device_id id_table[] __devinitdata = { - { PCI_VENDOR_ID_RME, PCI_DEVICE_ID_RME9652, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, - { 0, } + { + .vendor = PCI_VENDOR_ID_RME, + .device = PCI_DEVICE_ID_RME9652, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { 0, }, }; MODULE_DEVICE_TABLE(pci, id_table); static struct pci_driver rme96xx_driver = { - name: "rme96xx", - id_table: id_table, - probe: rme96xx_probe, - remove: rme96xx_remove + .name = "rme96xx", + .id_table = id_table, + .probe = rme96xx_probe, + .remove = rme96xx_remove, }; static int __init init_rme96xx(void) @@ -1223,7 +1232,7 @@ static int rme96xx_release(struct inode *in, struct file *file) { struct dmabuf * dma = (struct dmabuf*) file->private_data; - int hwp; + /* int hwp; */ DBG(printk(__FUNCTION__"\n")); COMM ("draining") @@ -1483,15 +1492,15 @@ static struct file_operations rme96xx_audio_fops = { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - owner: THIS_MODULE, + .owner = THIS_MODULE, #endif - read: rme96xx_read, - write: rme96xx_write, - poll: rme96xx_poll, - ioctl: rme96xx_ioctl, - mmap: rm96xx_mmap, - open: rme96xx_open, - release: rme96xx_release + .read = rme96xx_read, + .write = rme96xx_write, + .poll = rme96xx_poll, + .ioctl = rme96xx_ioctl, + .mmap = rm96xx_mmap, + .open = rme96xx_open, + .release = rme96xx_release }; static int rme96xx_mixer_open(struct inode *inode, struct file *file) @@ -1565,9 +1574,9 @@ static /*const*/ struct file_operations rme96xx_mixer_fops = { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - owner: THIS_MODULE, + .owner = THIS_MODULE, #endif - ioctl: rme96xx_mixer_ioctl, - open: rme96xx_mixer_open, - release: rme96xx_mixer_release, + .ioctl = rme96xx_mixer_ioctl, + .open = rme96xx_mixer_open, + .release = rme96xx_mixer_release, }; diff -Nru a/sound/oss/vidc.c b/sound/oss/vidc.c --- a/sound/oss/vidc.c Fri Nov 22 13:41:17 2002 +++ b/sound/oss/vidc.c Fri Nov 22 13:41:17 2002 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include diff -Nru a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c --- a/sound/pci/cs46xx/cs46xx_lib.c Fri Nov 22 13:41:18 2002 +++ b/sound/pci/cs46xx/cs46xx_lib.c Fri Nov 22 13:41:18 2002 @@ -46,12 +46,13 @@ */ #include -#include #include #include #include #include +#include #include + #include #include #include @@ -59,6 +60,9 @@ #ifndef LINUX_2_2 #include #endif + +#include + #include "cs46xx_lib.h" #include "dsp_spos.h" @@ -447,7 +451,7 @@ static int cs46xx_wait_for_fifo(cs46xx_t * chip,int retry_timeout) { - u32 i, status; + u32 i, status = 0; /* * Make sure the previous FIFO write operation has completed. */ diff -Nru a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c --- a/sound/pci/emu10k1/emu10k1_main.c Fri Nov 22 13:41:23 2002 +++ b/sound/pci/emu10k1/emu10k1_main.c Fri Nov 22 13:41:23 2002 @@ -28,9 +28,11 @@ #include #include #include +#include #include #include #include + #include #include diff -Nru a/sound/pci/es1938.c b/sound/pci/es1938.c --- a/sound/pci/es1938.c Fri Nov 22 13:41:21 2002 +++ b/sound/pci/es1938.c Fri Nov 22 13:41:21 2002 @@ -48,8 +48,8 @@ #include -#include #include +#include #include #include #include @@ -62,6 +62,8 @@ #ifndef LINUX_2_2 #include #endif + +#include #define chip_t es1938_t diff -Nru a/sound/pci/fm801.c b/sound/pci/fm801.c --- a/sound/pci/fm801.c Fri Nov 22 13:41:22 2002 +++ b/sound/pci/fm801.c Fri Nov 22 13:41:22 2002 @@ -20,9 +20,9 @@ */ #include -#include #include #include +#include #include #include #include @@ -32,6 +32,8 @@ #include #define SNDRV_GET_ID #include + +#include #define chip_t fm801_t diff -Nru a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c --- a/sound/pci/korg1212/korg1212.c Fri Nov 22 13:41:17 2002 +++ b/sound/pci/korg1212/korg1212.c Fri Nov 22 13:41:17 2002 @@ -20,11 +20,13 @@ */ #include -#include #include #include +#include #include #include +#include + #include #include #include @@ -33,6 +35,8 @@ #define SNDRV_GET_ID #include +#include + // ---------------------------------------------------------------------------- // Debug Stuff // ---------------------------------------------------------------------------- @@ -403,8 +407,13 @@ MODULE_AUTHOR("Haroldo Gamal "); static struct pci_device_id snd_korg1212_ids[] __devinitdata = { - { 0x10b5, 0x906d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, - { 0, } + { + .vendor = 0x10b5, + .device = 0x906d, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { 0, }, }; static char* stateName[] = { @@ -2305,10 +2314,10 @@ } static struct pci_driver driver = { - .name = "korg1212", + .name = "korg1212", .id_table = snd_korg1212_ids, - .probe = snd_korg1212_probe, - .remove = __devexit_p(snd_korg1212_remove), + .probe = snd_korg1212_probe, + .remove = __devexit_p(snd_korg1212_remove), }; static int __init alsa_card_korg1212_init(void) diff -Nru a/sound/pci/rme32.c b/sound/pci/rme32.c --- a/sound/pci/rme32.c Fri Nov 22 13:41:23 2002 +++ b/sound/pci/rme32.c Fri Nov 22 13:41:23 2002 @@ -27,11 +27,12 @@ */ #include -#include #include #include +#include #include #include + #include #include #include @@ -40,6 +41,8 @@ #include #define SNDRV_GET_ID #include + +#include static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ diff -Nru a/sound/pci/rme96.c b/sound/pci/rme96.c --- a/sound/pci/rme96.c Fri Nov 22 13:41:18 2002 +++ b/sound/pci/rme96.c Fri Nov 22 13:41:18 2002 @@ -24,11 +24,12 @@ */ #include -#include #include #include +#include #include #include + #include #include #include @@ -37,6 +38,8 @@ #include #define SNDRV_GET_ID #include + +#include /* note, two last pcis should be equal, it is not a bug */ diff -Nru a/sound/pci/rme9652/hammerfall_mem.c b/sound/pci/rme9652/hammerfall_mem.c --- a/sound/pci/rme9652/hammerfall_mem.c Fri Nov 22 13:41:18 2002 +++ b/sound/pci/rme9652/hammerfall_mem.c Fri Nov 22 13:41:18 2002 @@ -178,7 +178,7 @@ printk ("Hammerfall memory allocator: unknown buffer address or PCI device ID"); } -static void __exit hammerfall_free_buffers (void) +static void hammerfall_free_buffers (void) { int i; diff -Nru a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c --- a/sound/pci/rme9652/hdsp.c Fri Nov 22 13:41:18 2002 +++ b/sound/pci/rme9652/hdsp.c Fri Nov 22 13:41:18 2002 @@ -20,12 +20,11 @@ */ #include -#include -#include #include -#include +#include #include #include + #include #include #include @@ -35,6 +34,10 @@ #define SNDRV_GET_ID #include +#include +#include +#include + #include "multiface_firmware.dat" #include "digiface_firmware.dat" @@ -409,10 +412,13 @@ #endif static struct pci_device_id snd_hdsp_ids[] __devinitdata = { - {PCI_VENDOR_ID_XILINX, - PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,}, /* RME Hammerfall-DSP */ - {0,} + { + .vendor = PCI_VENDOR_ID_XILINX, + .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, /* RME Hammerfall-DSP */ + { 0, }, }; MODULE_DEVICE_TABLE(pci, snd_hdsp_ids); @@ -3116,10 +3122,10 @@ } static struct pci_driver driver = { - .name = "RME Hammerfall DSP", + .name = "RME Hammerfall DSP", .id_table = snd_hdsp_ids, - .probe = snd_hdsp_probe, - .remove = __devexit_p(snd_hdsp_remove), + .probe = snd_hdsp_probe, + .remove = __devexit_p(snd_hdsp_remove), }; static int __init alsa_card_hdsp_init(void) diff -Nru a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c --- a/sound/pci/rme9652/rme9652.c Fri Nov 22 13:41:19 2002 +++ b/sound/pci/rme9652/rme9652.c Fri Nov 22 13:41:19 2002 @@ -21,11 +21,12 @@ */ #include -#include #include #include +#include #include #include + #include #include #include @@ -34,6 +35,9 @@ #define SNDRV_GET_ID #include +#include +#include + static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ @@ -311,8 +315,13 @@ #endif static struct pci_device_id snd_rme9652_ids[] __devinitdata = { - {0x10ee, 0x3fc4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,}, /* RME Digi9652 */ - {0,} + { + .vendor = 0x10ee, + .device = 0x3fc4, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, /* RME Digi9652 */ + { 0, }, }; MODULE_DEVICE_TABLE(pci, snd_rme9652_ids); @@ -2733,10 +2742,10 @@ } static struct pci_driver driver = { - .name ="RME Digi9652 (Hammerfall)", + .name = "RME Digi9652 (Hammerfall)", .id_table = snd_rme9652_ids, - .probe = snd_rme9652_probe, - .remove = __devexit_p(snd_rme9652_remove), + .probe = snd_rme9652_probe, + .remove = __devexit_p(snd_rme9652_remove), }; static int __init alsa_card_hammerfall_init(void) diff -Nru a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c --- a/sound/pci/sonicvibes.c Fri Nov 22 13:41:22 2002 +++ b/sound/pci/sonicvibes.c Fri Nov 22 13:41:22 2002 @@ -23,11 +23,12 @@ */ #include -#include #include #include +#include #include #include + #include #include #include @@ -39,6 +40,8 @@ #ifndef LINUX_2_2 #include #endif + +#include MODULE_AUTHOR("Jaroslav Kysela "); MODULE_DESCRIPTION("S3 SonicVibes PCI"); diff -Nru a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c --- a/sound/pci/trident/trident_main.c Fri Nov 22 13:41:21 2002 +++ b/sound/pci/trident/trident_main.c Fri Nov 22 13:41:21 2002 @@ -26,12 +26,13 @@ */ #include -#include #include #include +#include #include #include #include + #include #include #include @@ -40,6 +41,8 @@ #ifndef LINUX_2_2 #include #endif + +#include #define chip_t trident_t diff -Nru a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c --- a/sound/pci/ymfpci/ymfpci_main.c Fri Nov 22 13:41:22 2002 +++ b/sound/pci/ymfpci/ymfpci_main.c Fri Nov 22 13:41:23 2002 @@ -25,18 +25,22 @@ */ #include -#include #include #include +#include #include +#include #include #include + #include #include #include #include #include #include + +#include #define chip_t ymfpci_t diff -Nru a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c --- a/sound/sparc/amd7930.c Fri Nov 22 13:41:18 2002 +++ b/sound/sparc/amd7930.c Fri Nov 22 13:41:18 2002 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include diff -Nru a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c --- a/sound/sparc/cs4231.c Fri Nov 22 13:41:17 2002 +++ b/sound/sparc/cs4231.c Fri Nov 22 13:41:17 2002 @@ -14,6 +14,7 @@ #include #include #include +#include #include #include