diff options
748 files changed, 19346 insertions, 12379 deletions
@@ -1808,6 +1808,14 @@ S: Kruislaan 419 S: 1098 VA Amsterdam S: The Netherlands +N: Jiri Kosina +E: jikos@jikos.cz +E: jkosina@suse.cz +D: Generic HID layer - original code split, fixes +D: Various ACPI fixes, keeping correct battery state through suspend +D: various lockdep annotations, autofs and other random bugfixes +S: Prague, Czech Republic + N: Gene Kozin E: 74604.152@compuserve.com W: http://www.sangoma.com diff --git a/Documentation/ABI/testing/debugfs-pktcdvd b/Documentation/ABI/testing/debugfs-pktcdvd new file mode 100644 index 00000000000..03dbd883cc4 --- /dev/null +++ b/Documentation/ABI/testing/debugfs-pktcdvd @@ -0,0 +1,20 @@ +What: /debug/pktcdvd/pktcdvd[0-7] +Date: Oct. 2006 +KernelVersion: 2.6.19 +Contact: Thomas Maier <balagi@justmail.de> +Description: + +debugfs interface +----------------- + +The pktcdvd module (packet writing driver) creates +these files in debugfs: + +/debug/pktcdvd/pktcdvd[0-7]/ + info (0444) Lots of human readable driver + statistics and infos. Multiple lines! + +Example: +------- + +cat /debug/pktcdvd/pktcdvd0/info diff --git a/Documentation/ABI/testing/sysfs-class-pktcdvd b/Documentation/ABI/testing/sysfs-class-pktcdvd new file mode 100644 index 00000000000..c4c55edc9a5 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-pktcdvd @@ -0,0 +1,72 @@ +What: /sys/class/pktcdvd/ +Date: Oct. 2006 +KernelVersion: 2.6.19 +Contact: Thomas Maier <balagi@justmail.de> +Description: + +sysfs interface +--------------- + +The pktcdvd module (packet writing driver) creates +these files in the sysfs: +(<devid> is in format major:minor ) + +/sys/class/pktcdvd/ + add (0200) Write a block device id (major:minor) + to create a new pktcdvd device and map + it to the block device. + + remove (0200) Write the pktcdvd device id (major:minor) + to it to remove the pktcdvd device. + + device_map (0444) Shows the device mapping in format: + pktcdvd[0-7] <pktdevid> <blkdevid> + +/sys/class/pktcdvd/pktcdvd[0-7]/ + dev (0444) Device id + uevent (0200) To send an uevent. + +/sys/class/pktcdvd/pktcdvd[0-7]/stat/ + packets_started (0444) Number of started packets. + packets_finished (0444) Number of finished packets. + + kb_written (0444) kBytes written. + kb_read (0444) kBytes read. + kb_read_gather (0444) kBytes read to fill write packets. + + reset (0200) Write any value to it to reset + pktcdvd device statistic values, like + bytes read/written. + +/sys/class/pktcdvd/pktcdvd[0-7]/write_queue/ + size (0444) Contains the size of the bio write + queue. + + congestion_off (0644) If bio write queue size is below + this mark, accept new bio requests + from the block layer. + + congestion_on (0644) If bio write queue size is higher + as this mark, do no longer accept + bio write requests from the block + layer and wait till the pktcdvd + device has processed enough bio's + so that bio write queue size is + below congestion off mark. + A value of <= 0 disables congestion + control. + + +Example: +-------- +To use the pktcdvd sysfs interface directly, you can do: + +# create a new pktcdvd device mapped to /dev/hdc +echo "22:0" >/sys/class/pktcdvd/add +cat /sys/class/pktcdvd/device_map +# assuming device pktcdvd0 was created, look at stat's +cat /sys/class/pktcdvd/pktcdvd0/stat/kb_written +# print the device id of the mapped block device +fgrep pktcdvd0 /sys/class/pktcdvd/device_map +# remove device, using pktcdvd0 device id 253:0 +echo "253:0" >/sys/class/pktcdvd/remove diff --git a/Documentation/cdrom/packet-writing.txt b/Documentation/cdrom/packet-writing.txt index 3d44c561fe6..7715d2247c4 100644 --- a/Documentation/cdrom/packet-writing.txt +++ b/Documentation/cdrom/packet-writing.txt @@ -90,6 +90,41 @@ Notes to create an ext2 filesystem on the disc. +Using the pktcdvd sysfs interface +--------------------------------- + +Since Linux 2.6.19, the pktcdvd module has a sysfs interface +and can be controlled by it. For example the "pktcdvd" tool uses +this interface. (see http://people.freenet.de/BalaGi#pktcdvd ) + +"pktcdvd" works similar to "pktsetup", e.g.: + + # pktcdvd -a dev_name /dev/hdc + # mkudffs /dev/pktcdvd/dev_name + # mount -t udf -o rw,noatime /dev/pktcdvd/dev_name /dvdram + # cp files /dvdram + # umount /dvdram + # pktcdvd -r dev_name + + +For a description of the sysfs interface look into the file: + + Documentation/ABI/testing/sysfs-block-pktcdvd + + +Using the pktcdvd debugfs interface +----------------------------------- + +To read pktcdvd device infos in human readable form, do: + + # cat /debug/pktcdvd/pktcdvd[0-7]/info + +For a description of the debugfs interface look into the file: + + Documentation/ABI/testing/debugfs-pktcdvd + + + Links ----- diff --git a/Documentation/fault-injection/failcmd.sh b/Documentation/fault-injection/failcmd.sh new file mode 100644 index 00000000000..63177aba810 --- /dev/null +++ b/Documentation/fault-injection/failcmd.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +echo 1 > /proc/self/make-it-fail +exec $* diff --git a/Documentation/fault-injection/failmodule.sh b/Documentation/fault-injection/failmodule.sh new file mode 100644 index 00000000000..474a8b971f9 --- /dev/null +++ b/Documentation/fault-injection/failmodule.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# +# Usage: failmodule <failname> <modulename> [stacktrace-depth] +# +# <failname>: "failslab", "fail_alloc_page", or "fail_make_request" +# +# <modulename>: module name that you want to inject faults. +# +# [stacktrace-depth]: the maximum number of stacktrace walking allowed +# + +STACKTRACE_DEPTH=5 +if [ $# -gt 2 ]; then + STACKTRACE_DEPTH=$3 +fi + +if [ ! -d /debug/$1 ]; then + echo "Fault-injection $1 does not exist" >&2 + exit 1 +fi +if [ ! -d /sys/module/$2 ]; then + echo "Module $2 does not exist" >&2 + exit 1 +fi + +# Disable any fault injection +echo 0 > /debug/$1/stacktrace-depth + +echo `cat /sys/module/$2/sections/.text` > /debug/$1/require-start +echo `cat /sys/module/$2/sections/.exit.text` > /debug/$1/require-end +echo $STACKTRACE_DEPTH > /debug/$1/stacktrace-depth diff --git a/Documentation/fault-injection/fault-injection.txt b/Documentation/fault-injection/fault-injection.txt new file mode 100644 index 00000000000..b7ca560b934 --- /dev/null +++ b/Documentation/fault-injection/fault-injection.txt @@ -0,0 +1,225 @@ +Fault injection capabilities infrastructure +=========================================== + +See also drivers/md/faulty.c and "every_nth" module option for scsi_debug. + + +Available fault injection capabilities +-------------------------------------- + +o failslab + + injects slab allocation failures. (kmalloc(), kmem_cache_alloc(), ...) + +o fail_page_alloc + + injects page allocation failures. (alloc_pages(), get_free_pages(), ...) + +o fail_make_request + + injects disk IO errors on devices permitted by setting + /sys/block/<device>/make-it-fail or + /sys/block/<device>/<partition>/make-it-fail. (generic_make_request()) + +Configure fault-injection capabilities behavior +----------------------------------------------- + +o debugfs entries + +fault-inject-debugfs kernel module provides some debugfs entries for runtime +configuration of fault-injection capabilities. + +- /debug/fail*/probability: + + likelihood of failure injection, in percent. + Format: <percent> + + Note that one-failure-per-hundred is a very high error rate + for some testcases. Consider setting probability=100 and configure + /debug/fail*/interval for such testcases. + +- /debug/fail*/interval: + + specifies the interval between failures, for calls to + should_fail() that pass all the other tests. + + Note that if you enable this, by setting interval>1, you will + probably want to set probability=100. + +- /debug/fail*/times: + + specifies how many times failures may happen at most. + A value of -1 means "no limit". + +- /debug/fail*/space: + + specifies an initial resource "budget", decremented by "size" + on each call to should_fail(,size). Failure injection is + suppressed until "space" reaches zero. + +- /debug/fail*/verbose + + Format: { 0 | 1 | 2 } + specifies the verbosity of the messages when failure is + injected. '0' means no messages; '1' will print only a single + log line per failure; '2' will print a call trace too -- useful + to debug the problems revealed by fault injection. + +- /debug/fail*/task-filter: + + Format: { 'Y' | 'N' } + A value of 'N' disables filtering by process (default). + Any positive value limits failures to only processes indicated by + /proc/<pid>/make-it-fail==1. + +- /debug/fail*/require-start: +- /debug/fail*/require-end: +- /debug/fail*/reject-start: +- /debug/fail*/reject-end: + + specifies the range of virtual addresses tested during + stacktrace walking. Failure is injected only if some caller + in the walked stacktrace lies within the required range, and + none lies within the rejected range. + Default required range is [0,ULONG_MAX) (whole of virtual address space). + Default rejected range is [0,0). + +- /debug/fail*/stacktrace-depth: + + specifies the maximum stacktrace depth walked during search + for a caller within [require-start,require-end) OR + [reject-start,reject-end). + +- /debug/fail_page_alloc/ignore-gfp-highmem: + + Format: { 'Y' | 'N' } + default is 'N', setting it to 'Y' won't inject failures into + highmem/user allocations. + +- /debug/failslab/ignore-gfp-wait: +- /debug/fail_page_alloc/ignore-gfp-wait: + + Format: { 'Y' | 'N' } + default is 'N', setting it to 'Y' will inject failures + only into non-sleep allocations (GFP_ATOMIC allocations). + +o Boot option + +In order to inject faults while debugfs is not available (early boot time), +use the boot option: + + failslab= + fail_page_alloc= + fail_make_request=<interval>,<probability>,<space>,<times> + +How to add new fault injection capability +----------------------------------------- + +o #include <linux/fault-inject.h> + +o define the fault attributes + + DECLARE_FAULT_INJECTION(name); + + Please see the definition of struct fault_attr in fault-inject.h + for details. + +o provide a way to configure fault attributes + +- boot option + + If you need to enable the fault injection capability from boot time, you can + provide boot option to configure it. There is a helper function for it: + + setup_fault_attr(attr, str); + +- debugfs entries + + failslab, fail_page_alloc, and fail_make_request use this way. + Helper functions: + + init_fault_attr_entries(entries, attr, name); + void cleanup_fault_attr_entries(entries); + +- module parameters + + If the scope of the fault injection capability is limited to a + single kernel module, it is better to provide module parameters to + configure the fault attributes. + +o add a hook to insert failures + + Upon should_fail() returning true, client code should inject a failure. + + should_fail(attr, size); + +Application Examples +-------------------- + +o inject slab allocation failures into module init/cleanup code + +------------------------------------------------------------------------------ +#!/bin/bash + +FAILCMD=Documentation/fault-injection/failcmd.sh +BLACKLIST="root_plug evbug" + +FAILNAME=failslab +echo Y > /debug/$FAILNAME/task-filter +echo 10 > /debug/$FAILNAME/probability +echo 100 > /debug/$FAILNAME/interval +echo -1 > /debug/$FAILNAME/times +echo 2 > /debug/$FAILNAME/verbose +echo 1 > /debug/$FAILNAME/ignore-gfp-wait + +blacklist() +{ + echo $BLACKLIST | grep $1 > /dev/null 2>&1 +} + +oops() +{ + dmesg | grep BUG > /dev/null 2>&1 +} + +find /lib/modules/`uname -r` -name '*.ko' -exec basename {} .ko \; | + while read i + do + oops && exit 1 + + if ! blacklist $i + then + echo inserting $i... + bash $FAILCMD modprobe $i + fi + done + +lsmod | awk '{ if ($3 == 0) { print $1 } }' | + while read i + do + oops && exit 1 + + if ! blacklist $i + then + echo removing $i... + bash $FAILCMD modprobe -r $i + fi + done + +------------------------------------------------------------------------------ + +o inject slab allocation failures only for a specific module + +------------------------------------------------------------------------------ +#!/bin/bash + +FAILMOD=Documentation/fault-injection/failmodule.sh + +echo injecting errors into the module $1... + +modprobe $1 +bash $FAILMOD failslab $1 10 +echo 25 > /debug/failslab/probability + +------------------------------------------------------------------------------ + diff --git a/Documentation/ioctl-number.txt b/Documentation/ioctl-number.txt index edc04d74ae2..5a8bd5bd88e 100644 --- a/Documentation/ioctl-number.txt +++ b/Documentation/ioctl-number.txt @@ -191,3 +191,5 @@ Code Seq# Include File Comments <mailto:aherrman@de.ibm.com> 0xF3 00-3F video/sisfb.h sisfb (in development) <mailto:thomas@winischhofer.net> +0xF4 00-1F video/mbxfb.h mbxfb + <mailto:raph@8d.com> diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index b79bcdf1631..d8323b8893c 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -548,6 +548,13 @@ and is between 256 and 4096 characters. It is defined in the file eurwdt= [HW,WDT] Eurotech CPU-1220/1410 onboard watchdog. Format: <io>[,<irq>] + failslab= + fail_page_alloc= + fail_make_request=[KNL] + General fault injection mechanism. + Format: <interval>,<probability>,<space>,<times> + See also /Documentation/fault-injection/. + fd_mcs= [HW,SCSI] See header of drivers/scsi/fd_mcs.c. diff --git a/MAINTAINERS b/MAINTAINERS index 89ef018cc4b..dbf449ba240 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -684,7 +684,7 @@ S: Supported CIRRUS LOGIC GENERIC FBDEV DRIVER P: Jeff Garzik M: jgarzik@pobox.com -L: linux-fbdev-devel@lists.sourceforge.net +L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Odd Fixes CIRRUS LOGIC CS4280/CS461x SOUNDDRIVER @@ -791,7 +791,7 @@ S: Maintained CYBLAFB FRAMEBUFFER DRIVER P: Knut Petersen M: Knut_Petersen@t-online.de -L: linux-fbdev-devel@lists.sourceforge.net +L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Maintained CYCLADES 2X SYNC CARD DRIVER @@ -1128,7 +1128,7 @@ S: Supported FRAMEBUFFER LAYER P: Antonino Daplas M: adaplas@pol.net -L: linux-fbdev-devel@lists.sourceforge.net +L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) W: http://linux-fbdev.sourceforge.net/ S: Maintained @@ -1479,7 +1479,7 @@ S: Maintained IMS TWINTURBO FRAMEBUFFER DRIVER P: Paul Mundt M: lethal@chaoticdreams.org -L: linux-fbdev-devel@lists.sourceforge.net +L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Maintained INFINIBAND SUBSYSTEM @@ -1512,13 +1512,13 @@ S: Maintained INTEL FRAMEBUFFER DRIVER (excluding 810 and 815) P: Sylvain Meyer M: sylvain.meyer@worldonline.fr -L: linux-fbdev-devel@lists.sourceforge.net +L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Maintained INTEL 810/815 FRAMEBUFFER DRIVER P: Antonino Daplas M: adaplas@pol.net -L: linux-fbdev-devel@lists.sourceforge.net +L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Maintained INTEL APIC/IOAPIC, LOWLEVEL X86 SMP SUPPORT @@ -1964,7 +1964,7 @@ S: Odd Fixes for 2.4; Maintained for 2.6. MATROX FRAMEBUFFER DRIVER P: Petr Vandrovec M: vandrove@vc.cvut.cz -L: linux-fbdev-devel@lists.sourceforge.net +L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Maintained MEGARAID SCSI DRIVERS @@ -2025,6 +2025,12 @@ M: rubini@ipvvis.unipv.it L: linux-kernel@vger.kernel.org S: Maintained +MOXA SMARTIO/INDUSTIO SERIAL CARD (MXSER 2.0) +P: Jiri Slaby +M: jirislaby@gmail.com +L: linux-kernel@vger.kernel.org +S: Maintained + MSI LAPTOP SUPPORT P: Lennart Poettering M: mzxreary@0pointer.de @@ -2050,6 +2056,12 @@ P: Andrew Veliath M: andrewtv@usa.net S: Maintained +MULTITECH MULTIPORT CARD (ISICOM) +P: Jiri Slaby +M: jirislaby@gmail.com +L: linux-kernel@vger.kernel.org +S: Maintained + NATSEMI ETHERNET DRIVER (DP8381x) P: Tim Hockin M: thockin@hockin.org @@ -2210,7 +2222,7 @@ S: Maintained NVIDIA (rivafb and nvidiafb) FRAMEBUFFER DRIVER P: Antonino Daplas M: adaplas@pol.net -L: linux-fbdev-devel@lists.sourceforge.net +L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Maintained OPENCORES I2C BUS DRIVER @@ -2494,13 +2506,13 @@ S: Maintained RADEON FRAMEBUFFER DISPLAY DRIVER P: Benjamin Herrenschmidt M: benh@kernel.crashing.org -L: linux-fbdev-devel@lists.sourceforge.net +L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Maintained RAGE128 FRAMEBUFFER DISPLAY DRIVER P: Paul Mackerras M: paulus@samba.org -L: linux-fbdev-devel@lists.sourceforge.net +L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Maintained RAYLINK/WEBGEAR 802.11 WIRELESS LAN DRIVER @@ -2570,7 +2582,7 @@ S: Orphan S3 SAVAGE FRAMEBUFFER DRIVER P: Antonino Daplas M: adaplas@pol.net -L: linux-fbdev-devel@lists.sourceforge.net +L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Maintained S390 diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index 7e55ea66c6d..84caf50725b 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -25,6 +25,14 @@ config RWSEM_XCHGADD_ALGORITHM bool default y +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_FIND_NEXT_BIT bool default y diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index ad617365199..fb804043b32 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -277,7 +277,7 @@ osf_fstatfs(unsigned long fd, struct osf_statfs __user *buffer, unsigned long bu retval = -EBADF; file = fget(fd); if (file) { - retval = do_osf_statfs(file->f_dentry, buffer, bufsiz); + retval = do_osf_statfs(file->f_path.dentry, buffer, bufsiz); fput(file); } return retval; diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 8c05d4321ae..aa1d400d721 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -74,6 +74,14 @@ config RWSEM_GENERIC_SPINLOCK config RWSEM_XCHGADD_ALGORITHM bool +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_HWEIGHT bool default y diff --git a/arch/arm26/Kconfig b/arch/arm26/Kconfig index c14fe918bc4..74eba8b5a8c 100644 --- a/arch/arm26/Kconfig +++ b/arch/arm26/Kconfig @@ -41,6 +41,14 @@ config RWSEM_GENERIC_SPINLOCK config RWSEM_XCHGADD_ALGORITHM bool +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_HWEIGHT bool default y diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig index 5f1694eea84..bb059a4e1df 100644 --- a/arch/avr32/Kconfig +++ b/arch/avr32/Kconfig @@ -45,6 +45,14 @@ config GENERIC_TIME config RWSEM_XCHGADD_ALGORITHM bool +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_BUST_SPINLOCK bool diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig index 6a1238a29d6..3474309e049 100644 --- a/arch/cris/Kconfig +++ b/arch/cris/Kconfig @@ -16,6 +16,14 @@ config RWSEM_GENERIC_SPINLOCK config RWSEM_XCHGADD_ALGORITHM bool +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_FIND_NEXT_BIT bool default y diff --git a/arch/cris/arch-v32/drivers/sync_serial.c b/arch/cris/arch-v32/drivers/sync_serial.c index e067806b220..424eb0eb1cd 100644 --- a/arch/cris/arch-v32/drivers/sync_serial.c +++ b/arch/cris/arch-v32/drivers/sync_serial.c @@ -504,7 +504,7 @@ static int sync_serial_release(struct inode *inode, struct file *file) static unsigned int sync_serial_poll(struct file *file, poll_table *wait) { - int dev = iminor(file->f_dentry->d_inode); + int dev = iminor(file->f_path.dentry->d_inode); unsigned int mask = 0; sync_port* port; DEBUGPOLL( static unsigned int prev_mask = 0; ); @@ -531,7 +531,7 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int return_val = 0; - int dev = iminor(file->f_dentry->d_inode); + int dev = iminor(file->f_path.dentry->d_inode); sync_port* port; reg_sser_rw_tr_cfg tr_cfg; reg_sser_rw_rec_cfg rec_cfg; @@ -789,7 +789,7 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file, static ssize_t sync_serial_write(struct file * file, const char * buf, size_t count, loff_t *ppos) { - int dev = iminor(file->f_dentry->d_inode); + int dev = iminor(file->f_path.dentry->d_inode); DECLARE_WAITQUEUE(wait, current); sync_port *port; unsigned long c, c1; @@ -919,7 +919,7 @@ static ssize_t sync_serial_write(struct file * file, const char * buf, static ssize_t sync_serial_read(struct file * file, char * buf, size_t count, loff_t *ppos) { - int dev = iminor(file->f_dentry->d_inode); + int dev = iminor(file->f_path.dentry->d_inode); int avail; sync_port *port; unsigned char* start; diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig index cf1c446e003..7561d7b72e7 100644 --- a/arch/frv/Kconfig +++ b/arch/frv/Kconfig @@ -41,6 +41,14 @@ config TIME_LOW_RES bool default y +config ARCH_HAS_ILOG2_U32 + bool + default y + +config ARCH_HAS_ILOG2_U64 + bool + default y + mainmenu "Fujitsu FR-V Kernel Configuration" source "init/Kconfig" diff --git a/arch/frv/mm/elf-fdpic.c b/arch/frv/mm/elf-fdpic.c index f5a653033fe..9477ccce070 100644 --- a/arch/frv/mm/elf-fdpic.c +++ b/arch/frv/mm/elf-fdpic.c @@ -110,14 +110,14 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi #if 0 printk("[area] l=%lx (ENOMEM) f='%s'\n", - len, filp ? filp->f_dentry->d_name.name : ""); + len, filp ? filp->f_path.dentry->d_name.name : ""); #endif return -ENOMEM; success: #if 0 printk("[area] l=%lx ad=%lx f='%s'\n", - len, addr, filp ? filp->f_dentry->d_name.name : ""); + len, addr, filp ? filp->f_path.dentry->d_name.name : ""); #endif return addr; } /* end arch_get_unmapped_area() */ diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig index cabf0bfffc5..34a84bc4baf 100644 --- a/arch/h8300/Kconfig +++ b/arch/h8300/Kconfig @@ -29,6 +29,14 @@ config RWSEM_XCHGADD_ALGORITHM bool default n +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_FIND_NEXT_BIT bool default y diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index ea70359b02d..c2362c7ba74 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -49,6 +49,11 @@ config GENERIC_IOMAP bool default y +config GENERIC_BUG + bool + default y + depends on BUG + config GENERIC_HWEIGHT bool default y diff --git a/arch/i386/Kconfig.cpu b/arch/i386/Kconfig.cpu index 821fd269ca5..2aecfba4ac4 100644 --- a/arch/i386/Kconfig.cpu +++ b/arch/i386/Kconfig.cpu @@ -248,6 +248,14 @@ config RWSEM_XCHGADD_ALGORITHM depends on !M386 default y +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_CALIBRATE_DELAY bool default y diff --git a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c index db6dd20c358..51130b39cd2 100644 --- a/arch/i386/kernel/cpuid.c +++ b/arch/i386/kernel/cpuid.c @@ -116,7 +116,7 @@ static ssize_t cpuid_read(struct file *file, char __user *buf, char __user *tmp = buf; u32 data[4]; u32 reg = *ppos; - int cpu = iminor(file->f_dentry->d_inode); + int cpu = iminor(file->f_path.dentry->d_inode); if (count % 16) return -EINVAL; /* Invalid chunk size */ @@ -134,7 +134,7 @@ static ssize_t cpuid_read(struct file *file, char __user *buf, static int cpuid_open(struct inode *inode, struct file *file) { - unsigned int cpu = iminor(file->f_dentry->d_inode); + unsigned int cpu = iminor(file->f_path.dentry->d_inode); struct cpuinfo_x86 *c = &(cpu_data)[cpu]; if (cpu >= NR_CPUS || !cpu_online(cpu)) diff --git a/arch/i386/kernel/module.c b/arch/i386/kernel/module.c index d7d9c8b23f7..3db0a5442eb 100644 --- a/arch/i386/kernel/module.c +++ b/arch/i386/kernel/module.c @@ -21,6 +21,7 @@ #include <linux/fs.h> #include <linux/string.h> #include <linux/kernel.h> +#include <linux/bug.h> #if 0 #define DEBUGP printk @@ -141,10 +142,11 @@ int module_finalize(const Elf_Ehdr *hdr, apply_paravirt(pseg, pseg + para->sh_size); } - return 0; + return module_bug_finalize(hdr, sechdrs, me); } void module_arch_cleanup(struct module *mod) { alternatives_smp_module_del(mod); + module_bug_cleanup(mod); } diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c index 1d1a56cae34..4a472a17d1c 100644 --- a/arch/i386/kernel/msr.c +++ b/arch/i386/kernel/msr.c @@ -172,7 +172,7 @@ static ssize_t msr_read(struct file *file, char __user * buf, u32 __user *tmp = (u32 __user *) buf; u32 data[2]; u32 reg = *ppos; - int cpu = iminor(file->f_dentry->d_inode); + int cpu = iminor(file->f_path.dentry->d_inode); int err; if (count % 8) @@ -196,7 +196,7 @@ static ssize_t msr_write(struct file *file, const char __user *buf, const u32 __user *tmp = (const u32 __user *)buf; u32 data[2]; u32 reg = *ppos; - int cpu = iminor(file->f_dentry->d_inode); + int cpu = iminor(file->f_path.dentry->d_inode); int err; if (count % 8) @@ -216,7 +216,7 @@ static ssize_t msr_write(struct file *file, const char __user *buf, static int msr_open(struct inode *inode, struct file *file) { - unsigned int cpu = iminor(file->f_dentry->d_inode); + unsigned int cpu = iminor(file->f_path.dentry->d_inode); struct cpuinfo_x86 *c = &(cpu_data)[cpu]; if (cpu >= NR_CPUS || !cpu_online(cpu)) diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 4bf0e3c83b8..1e00b03163b 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -1118,7 +1118,7 @@ static int __cpuinit __smp_prepare_cpu(int cpu) /* init low mem mapping */ clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS, - KERNEL_PGD_PTRS); + min_t(unsigned long, KERNEL_PGD_PTRS, USER_PGD_PTRS)); flush_tlb_all(); schedule_work(&info.task); wait_for_completion(&done); diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 68de48e498c..2b30dbf8d11 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -30,6 +30,7 @@ #include <linux/unwind.h> #include <linux/uaccess.h> #include <linux/nmi.h> +#include <linux/bug.h> #ifdef CONFIG_EISA #include <linux/ioport.h> @@ -420,43 +421,22 @@ void show_registers(struct pt_regs *regs) printk("\n"); } -static void handle_BUG(struct pt_regs *regs) +int is_valid_bugaddr(unsigned long eip) { - unsigned long eip = regs->eip; unsigned short ud2; if (eip < PAGE_OFFSET) - return; + return 0; if (probe_kernel_address((unsigned short *)eip, ud2)) - return; - if (ud2 != 0x0b0f) - return; - - printk(KERN_EMERG "------------[ cut here ]------------\n"); - -#ifdef CONFIG_DEBUG_BUGVERBOSE - do { - unsigned short line; - char *file; - char c; - - if (probe_kernel_address((unsigned short *)(eip + 2), line)) - break; - if (probe_kernel_address((char **)(eip + 4), file) || - (unsigned long)file < PAGE_OFFSET || - probe_kernel_address(file, c)) - file = "<bad filename>"; + return 0; - printk(KERN_EMERG "kernel BUG at %s:%d!\n", file, line); - return; - } while (0); -#endif - printk(KERN_EMERG "Kernel BUG at [verbose debug info unavailable]\n"); + return ud2 == 0x0b0f; } -/* This is gone through when something in the kernel - * has done something bad and is about to be terminated. -*/ +/* + * This is gone through when something in the kernel has done something bad and + * is about to be terminated. + */ void die(const char * str, struct pt_regs * regs, long err) { static struct { @@ -488,7 +468,8 @@ void die(const char * str, struct pt_regs * regs, long err) unsigned long esp; unsigned short ss; - handle_BUG(regs); + report_bug(regs->eip); + printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); #ifdef CONFIG_PREEMPT printk(KERN_EMERG "PREEMPT "); diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S index 56e6ad5cb04..16d3c7133ad 100644 --- a/arch/i386/kernel/vmlinux.lds.S +++ b/arch/i386/kernel/vmlinux.lds.S @@ -57,6 +57,8 @@ SECTIONS RODATA + BUG_TABLE + . = ALIGN(4); .tracedata : AT(ADDR(.tracedata) - LOAD_OFFSET) { __tracedata_start = .; diff --git a/arch/i386/mach-visws/setup.c b/arch/i386/mach-visws/setup.c index 885c7cbfd47..233ee20907b 100644 --- a/arch/i386/mach-visws/setup.c +++ b/arch/i386/mach-visws/setup.c @@ -6,6 +6,7 @@ #include <linux/smp.h> #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/module.h> #include <asm/fixmap.h> #include <asm/arch_hooks.h> @@ -142,6 +143,8 @@ void __init time_init_hook(void) unsigned long sgivwfb_mem_phys; unsigned long sgivwfb_mem_size; +EXPORT_SYMBOL(sgivwfb_mem_phys); +EXPORT_SYMBOL(sgivwfb_mem_size); long long mem_size __initdata = 0; diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 75d839715b2..fcacfe291b9 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -34,6 +34,14 @@ config RWSEM_XCHGADD_ALGORITHM bool default y +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_FIND_NEXT_BIT bool default y diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c index a4a6e1463af..957681c39ad 100644 --- a/arch/ia64/ia32/sys_ia32.c +++ b/arch/ia64/ia32/sys_ia32.c @@ -235,7 +235,7 @@ mmap_subpage (struct file *file, unsigned long start, unsigned long end, int pro if (!(flags & MAP_ANONYMOUS)) { /* read the file contents */ - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; if (!inode->i_fop || !file->f_op->read || ((*file->f_op->read)(file, (char __user *) start, end - start, &off) < 0)) { @@ -837,7 +837,7 @@ emulate_mmap (struct file *file, unsigned long start, unsigned long len, int pro if (!is_congruent) { /* read the file contents */ - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; if (!inode->i_fop || !file->f_op->read || ((*file->f_op->read)(file, (char __user *) pstart, pend - pstart, &poff) < 0)) diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index dbb28164b19..aa94f60fa8e 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -2188,13 +2188,13 @@ pfm_alloc_fd(struct file **cfile) /* * allocate a new dcache entry */ - file->f_dentry = d_alloc(pfmfs_mnt->mnt_sb->s_root, &this); - if (!file->f_dentry) goto out; + file->f_path.dentry = d_alloc(pfmfs_mnt->mnt_sb->s_root, &this); + if (!file->f_path.dentry) goto out; - file->f_dentry->d_op = &pfmfs_dentry_operations; + file->f_path.dentry->d_op = &pfmfs_dentry_operations; - d_add(file->f_dentry, inode); - file->f_vfsmnt = mntget(pfmfs_mnt); + d_add(file->f_path.dentry, inode); + file->f_path.mnt = mntget(pfmfs_mnt); file->f_mapping = inode->i_mapping; file->f_op = &pfm_file_ops; diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c index fd607ca51a8..e375a2f0f2c 100644 --- a/arch/ia64/kernel/salinfo.c +++ b/arch/ia64/kernel/salinfo.c @@ -302,7 +302,7 @@ salinfo_event_open(struct inode *inode, struct file *file) static ssize_t salinfo_event_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct proc_dir_entry *entry = PDE(inode); struct salinfo_data *data = entry->data; char cmd[32]; @@ -464,7 +464,7 @@ retry: static ssize_t salinfo_log_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct proc_dir_entry *entry = PDE(inode); struct salinfo_data *data = entry->data; u8 *buf; @@ -525,7 +525,7 @@ salinfo_log_clear(struct salinfo_data *data, int cpu) static ssize_t salinfo_log_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct proc_dir_entry *entry = PDE(inode); struct salinfo_data *data = entry->data; char cmd[32]; diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig index 41fd490af3b..f383dab973f 100644 --- a/arch/m32r/Kconfig +++ b/arch/m32r/Kconfig @@ -214,6 +214,14 @@ config RWSEM_XCHGADD_ALGORITHM bool default n +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_FIND_NEXT_BIT bool default y diff --git a/arch/m32r/boot/compressed/m32r_sio.c b/arch/m32r/boot/compressed/m32r_sio.c index bce8af5e3bb..ee3c8be12fa 100644 --- a/arch/m32r/boot/compressed/m32r_sio.c +++ b/arch/m32r/boot/compressed/m32r_sio.c @@ -2,6 +2,7 @@ * arch/m32r/boot/compressed/m32r_sio.c * * 2003-02-12: Takeo Takahashi + * 2006-11-30: OPSPUT support by Kazuhiro Inaoka * */ @@ -16,7 +17,7 @@ static int puts(const char *s) return 0; } -#if defined(CONFIG_PLAT_M32700UT_Alpha) || defined(CONFIG_PLAT_M32700UT) +#if defined(CONFIG_PLAT_M32700UT_Alpha) || defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT) #include <asm/m32r.h> #include <asm/io.h> @@ -31,7 +32,11 @@ static int puts(const char *s) #define BOOT_SIO0TXB (volatile unsigned short *)(0x02c00000 + 0x2000c) #else #undef PLD_BASE +#if defined(CONFIG_PLAT_OPSPUT) +#define PLD_BASE 0x1cc00000 +#else #define PLD_BASE 0xa4c00000 +#endif #define BOOT_SIO0STS PLD_ESIO0STS #define BOOT_SIO0TXB PLD_ESIO0TXB #endif diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S index ac6d840b382..a2c472c0549 100644 --- a/arch/m32r/kernel/entry.S +++ b/arch/m32r/kernel/entry.S @@ -23,35 +23,35 @@ * updated in fork.c:copy_thread, signal.c:do_signal, * ptrace.c and ptrace.h * - * M32Rx/M32R2 M32R - * @(sp) - r4 ditto - * @(0x04,sp) - r5 ditto - * @(0x08,sp) - r6 ditto - * @(0x0c,sp) - *pt_regs ditto - * @(0x10,sp) - r0 ditto - * @(0x14,sp) - r1 ditto - * @(0x18,sp) - r2 ditto - * @(0x1c,sp) - r3 ditto - * @(0x20,sp) - r7 ditto - * @(0x24,sp) - r8 ditto - * @(0x28,sp) - r9 ditto - * @(0x2c,sp) - r10 ditto - * @(0x30,sp) - r11 ditto - * @(0x34,sp) - r12 ditto - * @(0x38,sp) - syscall_nr ditto - * @(0x3c,sp) - acc0h @(0x3c,sp) - acch - * @(0x40,sp) - acc0l @(0x40,sp) - accl - * @(0x44,sp) - acc1h @(0x44,sp) - dummy_acc1h - * @(0x48,sp) - acc1l @(0x48,sp) - dummy_acc1l - * @(0x4c,sp) - psw ditto - * @(0x50,sp) - bpc ditto - * @(0x54,sp) - bbpsw ditto - * @(0x58,sp) - bbpc ditto - * @(0x5c,sp) - spu (cr3) ditto - * @(0x60,sp) - fp (r13) ditto - * @(0x64,sp) - lr (r14) ditto - * @(0x68,sp) - spi (cr2) ditto - * @(0x6c,sp) - orig_r0 ditto + * M32R/M32Rx/M32R2 + * @(sp) - r4 + * @(0x04,sp) - r5 + * @(0x08,sp) - r6 + * @(0x0c,sp) - *pt_regs + * @(0x10,sp) - r0 + * @(0x14,sp) - r1 + * @(0x18,sp) - r2 + * @(0x1c,sp) - r3 + * @(0x20,sp) - r7 + * @(0x24,sp) - r8 + * @(0x28,sp) - r9 + * @(0x2c,sp) - r10 + * @(0x30,sp) - r11 + * @(0x34,sp) - r12 + * @(0x38,sp) - syscall_nr + * @(0x3c,sp) - acc0h + * @(0x40,sp) - acc0l + * @(0x44,sp) - acc1h ; ISA_DSP_LEVEL2 only + * @(0x48,sp) - acc1l ; ISA_DSP_LEVEL2 only + * @(0x4c,sp) - psw + * @(0x50,sp) - bpc + * @(0x54,sp) - bbpsw + * @(0x58,sp) - bbpc + * @(0x5c,sp) - spu (cr3) + * @(0x60,sp) - fp (r13) + * @(0x64,sp) - lr (r14) + * @(0x68,sp) - spi (cr2) + * @(0x6c,sp) - orig_r0 */ #include <linux/linkage.h> @@ -95,17 +95,10 @@ #define R11(reg) @(0x30,reg) #define R12(reg) @(0x34,reg) #define SYSCALL_NR(reg) @(0x38,reg) -#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2) #define ACC0H(reg) @(0x3C,reg) #define ACC0L(reg) @(0x40,reg) #define ACC1H(reg) @(0x44,reg) #define ACC1L(reg) @(0x48,reg) -#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R) -#define ACCH(reg) @(0x3C,reg) -#define ACCL(reg) @(0x40,reg) -#else -#error unknown isa configuration -#endif #define PSW(reg) @(0x4C,reg) #define BPC(reg) @(0x50,reg) #define BBPSW(reg) @(0x54,reg) @@ -603,8 +596,6 @@ ENTRY(ace_handler) beqz r1, inst oprand: ld r2, @(low(MDEVA_offset),r2) ; set address - srli r2, #12 - slli r2, #12 srli r1, #1 bra 1f inst: diff --git a/arch/m32r/kernel/io_opsput.c b/arch/m32r/kernel/io_opsput.c index da6c5f5c1f8..3cbb1f717e5 100644 --- a/arch/m32r/kernel/io_opsput.c +++ b/arch/m32r/kernel/io_opsput.c @@ -30,14 +30,34 @@ extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int); extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int); #endif /* CONFIG_PCMCIA && CONFIG_M32R_CFC */ -#define PORT2ADDR(port) _port2addr(port) -#define PORT2ADDR_USB(port) _port2addr_usb(port) +#define PORT2ADDR(port) _port2addr(port) +#define PORT2ADDR_USB(port) _port2addr_usb(port) static inline void *_port2addr(unsigned long port) { return (void *)(port | NONCACHE_OFFSET); } +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) +static inline void *__port2addr_ata(unsigned long port) +{ + static int dummy_reg; + + switch (port) { + case 0x1f0: return (void *)(0x0c002000 | NONCACHE_OFFSET); + case 0x1f1: return (void *)(0x0c012800 | NONCACHE_OFFSET); + case 0x1f2: return (void *)(0x0c012002 | NONCACHE_OFFSET); + case 0x1f3: return (void *)(0x0c012802 | NONCACHE_OFFSET); + case 0x1f4: return (void *)(0x0c012004 | NONCACHE_OFFSET); + case 0x1f5: return (void *)(0x0c012804 | NONCACHE_OFFSET); + case 0x1f6: return (void *)(0x0c012006 | NONCACHE_OFFSET); + case 0x1f7: return (void *)(0x0c012806 | NONCACHE_OFFSET); + case 0x3f6: return (void *)(0x0c01200e | NONCACHE_OFFSET); + default: return (void *)&dummy_reg; + } +} +#endif + /* * OPSPUT-LAN is located in the extended bus space * from 0x10000000 to 0x13ffffff on physical address. @@ -97,6 +117,12 @@ unsigned char _inb(unsigned long port) { if (port >= LAN_IOSTART && port < LAN_IOEND) return _ne_inb(PORT2ADDR_NE(port)); + +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + return *(volatile unsigned char *)__port2addr_ata(port); + } +#endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { unsigned char b; @@ -112,6 +138,11 @@ unsigned short _inw(unsigned long port) { if (port >= LAN_IOSTART && port < LAN_IOEND) return _ne_inw(PORT2ADDR_NE(port)); +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + return *(volatile unsigned short *)__port2addr_ata(port); + } +#endif #if defined(CONFIG_USB) else if(port >= 0x340 && port < 0x3a0) return *(volatile unsigned short *)PORT2ADDR_USB(port); @@ -164,6 +195,11 @@ void _outb(unsigned char b, unsigned long port) if (port >= LAN_IOSTART && port < LAN_IOEND) _ne_outb(b, PORT2ADDR_NE(port)); else +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + *(volatile unsigned char *)__port2addr_ata(port) = b; + } else +#endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0); @@ -177,6 +213,11 @@ void _outw(unsigned short w, unsigned long port) if (port >= LAN_IOSTART && port < LAN_IOEND) _ne_outw(w, PORT2ADDR_NE(port)); else +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + *(volatile unsigned short *)__port2addr_ata(port) = w; + } else +#endif #if defined(CONFIG_USB) if(port >= 0x340 && port < 0x3a0) *(volatile unsigned short *)PORT2ADDR_USB(port) = w; @@ -222,6 +263,14 @@ void _insb(unsigned int port, void *addr, unsigned long count) { if (port >= LAN_IOSTART && port < LAN_IOEND) _ne_insb(PORT2ADDR_NE(port), addr, count); +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + unsigned char *buf = addr; + unsigned char *portp = __port2addr_ata(port); + while (count--) + *buf++ = *(volatile unsigned char *)portp; + } +#endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { pcc_ioread_byte(0, port, (void *)addr, sizeof(unsigned char), @@ -254,6 +303,12 @@ void _insw(unsigned int port, void *addr, unsigned long count) pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short), count, 1); #endif +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + portp = __port2addr_ata(port); + while (count--) + *buf++ = *(volatile unsigned short *)portp; +#endif } else { portp = PORT2ADDR(port); while (count--) @@ -280,6 +335,12 @@ void _outsb(unsigned int port, const void *addr, unsigned long count) portp = PORT2ADDR_NE(port); while (count--) _ne_outb(*buf++, portp); +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + portp = __port2addr_ata(port); + while (count--) + *(volatile unsigned char *)portp = *buf++; +#endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char), @@ -305,6 +366,12 @@ void _outsw(unsigned int port, const void *addr, unsigned long count) portp = PORT2ADDR_NE(port); while (count--) *(volatile unsigned short *)portp = *buf++; +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + portp = __port2addr_ata(port); + while (count--) + *(volatile unsigned short *)portp = *buf++; +#endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short), diff --git a/arch/m32r/kernel/setup_opsput.c b/arch/m32r/kernel/setup_opsput.c index 61d3b01cbe0..62d6b71de45 100644 --- a/arch/m32r/kernel/setup_opsput.c +++ b/arch/m32r/kernel/setup_opsput.c @@ -218,13 +218,13 @@ static void shutdown_opsput_lanpld_irq(unsigned int irq) static struct hw_interrupt_type opsput_lanpld_irq_type = { - "OPSPUT-PLD-LAN-IRQ", - startup_opsput_lanpld_irq, - shutdown_opsput_lanpld_irq, - enable_opsput_lanpld_irq, - disable_opsput_lanpld_irq, - mask_and_ack_opsput_lanpld, - end_opsput_lanpld_irq + .typename = "OPSPUT-PLD-LAN-IRQ", + .startup = startup_opsput_lanpld_irq, + .shutdown = shutdown_opsput_lanpld_irq, + .enable = enable_opsput_lanpld_irq, + .disable = disable_opsput_lanpld_irq, + .ack = mask_and_ack_opsput_lanpld, + .end = end_opsput_lanpld_irq }; /* @@ -374,7 +374,6 @@ void __init init_IRQ(void) disable_opsput_pld_irq(PLD_IRQ_SIO0_SND); #endif /* CONFIG_SERIAL_M32R_PLDSIO */ -#if defined(CONFIG_M32R_CFC) /* INT#1: CFC IREQ on PLD */ irq_desc[PLD_IRQ_CFIREQ].status = IRQ_DISABLED; irq_desc[PLD_IRQ_CFIREQ].chip = &opsput_pld_irq_type; @@ -398,8 +397,6 @@ void __init init_IRQ(void) irq_desc[PLD_IRQ_CFC_EJECT].depth = 1; /* disable nested irq */ pld_icu_data[irq2pldirq(PLD_IRQ_CFC_EJECT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02; /* 'H' edge sense */ disable_opsput_pld_irq(PLD_IRQ_CFC_EJECT); -#endif /* CONFIG_M32R_CFC */ - /* * INT0# is used for LAN, DIO diff --git a/arch/m32r/mm/fault.c b/arch/m32r/mm/fault.c index 8d5f551b575..9b9feb0f161 100644 --- a/arch/m32r/mm/fault.c +++ b/arch/m32r/mm/fault.c @@ -173,7 +173,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code, goto good_area; if (!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; -#if 0 + if (error_code & ACE_USERMODE) { /* * accessing the stack below "spu" is always a bug. @@ -184,7 +184,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code, if (address + 4 < regs->spu) goto bad_area; } -#endif + if (expand_stack(vma, address)) goto bad_area; /* diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 7bc14461a6a..70a577c89c7 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -17,6 +17,14 @@ config RWSEM_GENERIC_SPINLOCK config RWSEM_XCHGADD_ALGORITHM bool +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_HWEIGHT bool default y diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig index aa70dde5422..25993c2a8fb 100644 --- a/arch/m68knommu/Kconfig +++ b/arch/m68knommu/Kconfig @@ -25,6 +25,14 @@ config RWSEM_XCHGADD_ALGORITHM bool default n +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_FIND_NEXT_BIT bool default y diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index d8af858fe3f..57af8d8cf46 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -819,6 +819,14 @@ config RWSEM_GENERIC_SPINLOCK config RWSEM_XCHGADD_ALGORITHM bool +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_FIND_NEXT_BIT bool default y diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c index 1bbefbf4337..37cad5de515 100644 --- a/arch/mips/kernel/irixelf.c +++ b/arch/mips/kernel/irixelf.c @@ -1145,7 +1145,7 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file) psinfo.pr_pid = prstatus.pr_pid = current->pid; psinfo.pr_ppid = prstatus.pr_ppid = current->parent->pid; psinfo.pr_pgrp = prstatus.pr_pgrp = process_group(current); - psinfo.pr_sid = prstatus.pr_sid = current->signal->session; + psinfo.pr_sid = prstatus.pr_sid = process_session(current); if (current->pid == current->tgid) { /* * This is the record for the group leader. Add in the diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c index 8c8c8324f77..5a99e3e0c96 100644 --- a/arch/mips/kernel/rtlx.c +++ b/arch/mips/kernel/rtlx.c @@ -415,7 +415,7 @@ static unsigned int file_poll(struct file *file, poll_table * wait) int minor; unsigned int mask = 0; - minor = iminor(file->f_dentry->d_inode); + minor = iminor(file->f_path.dentry->d_inode); poll_wait(file, &channel_wqs[minor].rt_queue, wait); poll_wait(file, &channel_wqs[minor].lx_queue, wait); @@ -437,7 +437,7 @@ static unsigned int file_poll(struct file *file, poll_table * wait) static ssize_t file_read(struct file *file, char __user * buffer, size_t count, loff_t * ppos) { - int minor = iminor(file->f_dentry->d_inode); + int minor = iminor(file->f_path.dentry->d_inode); /* data available? */ if (!rtlx_read_poll(minor, (file->f_flags & O_NONBLOCK) ? 0 : 1)) { @@ -454,7 +454,7 @@ static ssize_t file_write(struct file *file, const char __user * buffer, struct rtlx_channel *rt; DECLARE_WAITQUEUE(wait, current); - minor = iminor(file->f_dentry->d_inode); + minor = iminor(file->f_path.dentry->d_inode); rt = &rtlx->channel[minor]; /* any space left... */ diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c index 93c74fefff7..6c2406a93f2 100644 --- a/arch/mips/kernel/sysirix.c +++ b/arch/mips/kernel/sysirix.c @@ -732,7 +732,7 @@ asmlinkage int irix_fstatfs(unsigned int fd, struct irix_statfs __user *buf) goto out; } - error = vfs_statfs(file->f_dentry, &kbuf); + error = vfs_statfs(file->f_path.dentry, &kbuf); if (error) goto out_f; @@ -1041,7 +1041,7 @@ asmlinkage unsigned long irix_mmap32(unsigned long addr, size_t len, int prot, unsigned long old_pos; long max_size = offset + len; - if (max_size > file->f_dentry->d_inode->i_size) { + if (max_size > file->f_path.dentry->d_inode->i_size) { old_pos = sys_lseek (fd, max_size - 1, 0); sys_write (fd, (void __user *) "", 1); sys_lseek (fd, old_pos, 0); @@ -1406,7 +1406,7 @@ asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs __user *buf) error = -EBADF; goto out; } - error = vfs_statfs(file->f_dentry, &kbuf); + error = vfs_statfs(file->f_path.dentry, &kbuf); if (error) goto out_f; @@ -1526,7 +1526,7 @@ asmlinkage int irix_mmap64(struct pt_regs *regs) unsigned long old_pos; long max_size = off2 + len; - if (max_size > file->f_dentry->d_inode->i_size) { + if (max_size > file->f_path.dentry->d_inode->i_size) { old_pos = sys_lseek (fd, max_size - 1, 0); sys_write (fd, (void __user *) "", 1); sys_lseek (fd, old_pos, 0); @@ -1658,7 +1658,7 @@ asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs __user *buf) error = -EBADF; goto out; } - error = vfs_statfs(file->f_dentry, &kbuf); + error = vfs_statfs(file->f_path.dentry, &kbuf); if (error) goto out_f; diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index 51ddd216689..666bef484dc 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c @@ -1179,7 +1179,7 @@ static ssize_t vpe_write(struct file *file, const char __user * buffer, size_t ret = count; struct vpe *v; - minor = iminor(file->f_dentry->d_inode); + minor = iminor(file->f_path.dentry->d_inode); if ((v = get_vpe(minor)) == NULL) return -ENODEV; diff --git a/arch/mips/lasat/sysctl.c b/arch/mips/lasat/sysctl.c index 6dd7ae1b7c2..da35d455549 100644 --- a/arch/mips/lasat/sysctl.c +++ b/arch/mips/lasat/sysctl.c @@ -286,11 +286,11 @@ int proc_lasat_eeprom_value(ctl_table *table, int write, struct file *filp, mutex_unlock(&lasat_info_mutex); return r; } - if (filp && filp->f_dentry) + if (filp && filp->f_path.dentry) { - if (!strcmp(filp->f_dentry->d_name.name, "prid")) + if (!strcmp(filp->f_path.dentry->d_name.name, "prid")) lasat_board_info.li_eeprom_info.prid = lasat_board_info.li_prid; - if (!strcmp(filp->f_dentry->d_name.name, "debugaccess")) + if (!strcmp(filp->f_path.dentry->d_name.name, "debugaccess")) lasat_board_info.li_eeprom_info.debugaccess = lasat_board_info.li_debugaccess; } lasat_write_eeprom_info(); diff --git a/arch/mips/mm/ioremap.c b/arch/mips/mm/ioremap.c index cea7d0ea36e..fc2c96f0a1f 100644 --- a/arch/mips/mm/ioremap.c +++ b/arch/mips/mm/ioremap.c @@ -6,98 +6,13 @@ * (C) Copyright 1995 1996 Linus Torvalds * (C) Copyright 2001, 2002 Ralf Baechle */ +#include <linux/mm.h> #include <linux/module.h> #include <asm/addrspace.h> #include <asm/byteorder.h> #include <linux/vmalloc.h> -#include <asm/cacheflush.h> -#include <asm/io.h> -#include <asm/tlbflush.h> - -static inline void remap_area_pte(pte_t * pte, unsigned long address, - phys_t size, phys_t phys_addr, unsigned long flags) -{ - phys_t end; - unsigned long pfn; - pgprot_t pgprot = __pgprot(_PAGE_GLOBAL | _PAGE_PRESENT | __READABLE - | __WRITEABLE | flags); - - address &= ~PMD_MASK; - end = address + size; - if (end > PMD_SIZE) - end = PMD_SIZE; - if (address >= end) - BUG(); - pfn = phys_addr >> PAGE_SHIFT; - do { - if (!pte_none(*pte)) { - printk("remap_area_pte: page already exists\n"); - BUG(); - } - set_pte(pte, pfn_pte(pfn, pgprot)); - address += PAGE_SIZE; - pfn++; - pte++; - } while (address && (address < end)); -} - -static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, - phys_t size, phys_t phys_addr, unsigned long flags) -{ - phys_t end; - - address &= ~PGDIR_MASK; - end = address + size; - if (end > PGDIR_SIZE) - end = PGDIR_SIZE; - phys_addr -= address; - if (address >= end) - BUG(); - do { - pte_t * pte = pte_alloc_kernel(pmd, address); - if (!pte) - return -ENOMEM; - remap_area_pte(pte, address, end - address, address + phys_addr, flags); - address = (address + PMD_SIZE) & PMD_MASK; - pmd++; - } while (address && (address < end)); - return 0; -} - -static int remap_area_pages(unsigned long address, phys_t phys_addr, - phys_t size, unsigned long flags) -{ - int error; - pgd_t * dir; - unsigned long end = address + size; - - phys_addr -= address; - dir = pgd_offset(&init_mm, address); - flush_cache_all(); - if (address >= end) - BUG(); - do { - pud_t *pud; - pmd_t *pmd; - - error = -ENOMEM; - pud = pud_alloc(&init_mm, dir, address); - if (!pud) - break; - pmd = pmd_alloc(&init_mm, pud, address); - if (!pmd) - break; - if (remap_area_pmd(pmd, address, end - address, - phys_addr + address, flags)) - break; - error = 0; - address = (address + PGDIR_SIZE) & PGDIR_MASK; - dir++; - } while (address && (address < end)); - flush_tlb_all(); - return error; -} +#include <linux/io.h> /* * Generic mapping function (not visible outside): @@ -121,6 +36,7 @@ void __iomem * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags) unsigned long offset; phys_t last_addr; void * addr; + pgprot_t pgprot; phys_addr = fixup_bigphys_addr(phys_addr, size); @@ -152,6 +68,9 @@ void __iomem * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags) return NULL; } + pgprot = __pgprot(_PAGE_GLOBAL | _PAGE_PRESENT | __READABLE + | __WRITEABLE | flags); + /* * Mappings have to be page-aligned */ @@ -166,7 +85,8 @@ void __iomem * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags) if (!area) return NULL; addr = area->addr; - if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) { + if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size, + phys_addr, pgprot)) { vunmap(addr); return NULL; } diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index d2101237442..0f9ff618c6d 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -25,6 +25,14 @@ config RWSEM_GENERIC_SPINLOCK config RWSEM_XCHGADD_ALGORITHM bool +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_FIND_NEXT_BIT bool default y diff --git a/arch/parisc/hpux/sys_hpux.c b/arch/parisc/hpux/sys_hpux.c index 2e2dc4f2c85..d88309209f5 100644 --- a/arch/parisc/hpux/sys_hpux.c +++ b/arch/parisc/hpux/sys_hpux.c @@ -237,7 +237,7 @@ asmlinkage long hpux_fstatfs(unsigned int fd, struct hpux_statfs __user * buf) file = fget(fd); if (!file) goto out; - error = vfs_statfs_hpux(file->f_dentry, &tmp); + error = vfs_statfs_hpux(file->f_path.dentry, &tmp); if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) error = -EFAULT; fput(file); diff --git a/arch/parisc/mm/ioremap.c b/arch/parisc/mm/ioremap.c index 47a1d2ac941..44b42c7f639 100644 --- a/arch/parisc/mm/ioremap.c +++ b/arch/parisc/mm/ioremap.c @@ -9,110 +9,8 @@ #include <linux/vmalloc.h> #include <linux/errno.h> #include <linux/module.h> -#include <asm/io.h> +#include <linux/io.h> #include <asm/pgalloc.h> -#include <asm/tlbflush.h> -#include <asm/cacheflush.h> - -static inline void -remap_area_pte(pte_t *pte, unsigned long address, unsigned long size, - unsigned long phys_addr, unsigned long flags) -{ - unsigned long end, pfn; - pgprot_t pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | - _PAGE_ACCESSED | flags); - - address &= ~PMD_MASK; - - end = address + size; - if (end > PMD_SIZE) - end = PMD_SIZE; - - BUG_ON(address >= end); - - pfn = phys_addr >> PAGE_SHIFT; - do { - BUG_ON(!pte_none(*pte)); - - set_pte(pte, pfn_pte(pfn, pgprot)); - - address += PAGE_SIZE; - pfn++; - pte++; - } while (address && (address < end)); -} - -static inline int -remap_area_pmd(pmd_t *pmd, unsigned long address, unsigned long size, - unsigned long phys_addr, unsigned long flags) -{ - unsigned long end; - - address &= ~PGDIR_MASK; - - end = address + size; - if (end > PGDIR_SIZE) - end = PGDIR_SIZE; - - BUG_ON(address >= end); - - phys_addr -= address; - do { - pte_t *pte = pte_alloc_kernel(pmd, address); - if (!pte) - return -ENOMEM; - - remap_area_pte(pte, address, end - address, - address + phys_addr, flags); - - address = (address + PMD_SIZE) & PMD_MASK; - pmd++; - } while (address && (address < end)); - - return 0; -} - -static int -remap_area_pages(unsigned long address, unsigned long phys_addr, - unsigned long size, unsigned long flags) -{ - pgd_t *dir; - int error = 0; - unsigned long end = address + size; - - BUG_ON(address >= end); - - phys_addr -= address; - dir = pgd_offset_k(address); - - flush_cache_all(); - - do { - pud_t *pud; - pmd_t *pmd; - - error = -ENOMEM; - pud = pud_alloc(&init_mm, dir, address); - if (!pud) - break; - - pmd = pmd_alloc(&init_mm, pud, address); - if (!pmd) - break; - - if (remap_area_pmd(pmd, address, end - address, - phys_addr + address, flags)) - break; - - error = 0; - address = (address + PGDIR_SIZE) & PGDIR_MASK; - dir++; - } while (address && (address < end)); - - flush_tlb_all(); - - return error; -} /* * Generic mapping function (not visible outside): @@ -131,6 +29,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l void *addr; struct vm_struct *area; unsigned long offset, last_addr; + pgprot_t pgprot; #ifdef CONFIG_EISA unsigned long end = phys_addr + size - 1; @@ -164,6 +63,9 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l } } + pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | + _PAGE_ACCESSED | flags); + /* * Mappings have to be page-aligned */ @@ -179,7 +81,8 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l return NULL; addr = area->addr; - if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) { + if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size, + phys_addr, pgprot)) { vfree(addr); return NULL; } diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 291c95ac4b3..56c3c4065eb 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -41,6 +41,14 @@ config RWSEM_XCHGADD_ALGORITHM bool default y +config ARCH_HAS_ILOG2_U32 + bool + default y + +config ARCH_HAS_ILOG2_U64 + bool + default y if 64BIT + config GENERIC_HWEIGHT bool default y diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c index f598cb51953..dd7001cacf7 100644 --- a/arch/powerpc/kernel/proc_ppc64.c +++ b/arch/powerpc/kernel/proc_ppc64.c @@ -83,7 +83,7 @@ __initcall(proc_ppc64_init); static loff_t page_map_seek( struct file *file, loff_t off, int whence) { loff_t new; - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode); switch(whence) { case 0: @@ -106,13 +106,13 @@ static loff_t page_map_seek( struct file *file, loff_t off, int whence) static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) { - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode); return simple_read_from_buffer(buf, nbytes, ppos, dp->data, dp->size); } static int page_map_mmap( struct file *file, struct vm_area_struct *vma ) { - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode); if ((vma->vm_end - vma->vm_start) > dp->size) return -EINVAL; diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index 7d0f13fecc0..0c4fcd34bfe 100644 --- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c @@ -193,7 +193,7 @@ static void free_flash_list(struct flash_block_list *f) static int rtas_flash_release(struct inode *inode, struct file *file) { - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode); struct rtas_update_flash_t *uf; uf = (struct rtas_update_flash_t *) dp->data; @@ -255,7 +255,7 @@ static void get_flash_status_msg(int status, char *buf) static ssize_t rtas_flash_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode); struct rtas_update_flash_t *uf; char msg[RTAS_MSG_MAXLEN]; int msglen; @@ -299,7 +299,7 @@ void rtas_block_ctor(void *ptr, struct kmem_cache *cache, unsigned long flags) static ssize_t rtas_flash_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode); struct rtas_update_flash_t *uf; char *p; int next_free; @@ -391,7 +391,7 @@ static void manage_flash(struct rtas_manage_flash_t *args_buf) static ssize_t manage_flash_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode); struct rtas_manage_flash_t *args_buf; char msg[RTAS_MSG_MAXLEN]; int msglen; @@ -421,7 +421,7 @@ static ssize_t manage_flash_read(struct file *file, char __user *buf, static ssize_t manage_flash_write(struct file *file, const char __user *buf, size_t count, loff_t *off) { - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode); struct rtas_manage_flash_t *args_buf; const char reject_str[] = "0"; const char commit_str[] = "1"; @@ -492,7 +492,7 @@ static int get_validate_flash_msg(struct rtas_validate_flash_t *args_buf, static ssize_t validate_flash_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode); struct rtas_validate_flash_t *args_buf; char msg[RTAS_MSG_MAXLEN]; int msglen; @@ -520,7 +520,7 @@ static ssize_t validate_flash_read(struct file *file, char __user *buf, static ssize_t validate_flash_write(struct file *file, const char __user *buf, size_t count, loff_t *off) { - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode); struct rtas_validate_flash_t *args_buf; int rc; @@ -569,7 +569,7 @@ done: static int validate_flash_release(struct inode *inode, struct file *file) { - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode); struct rtas_validate_flash_t *args_buf; args_buf = (struct rtas_validate_flash_t *) dp->data; diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index e3af9112c02..738b9244382 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -205,7 +205,7 @@ static int spufs_dir_close(struct inode *inode, struct file *file) struct dentry *dir; int ret; - dir = file->f_dentry; + dir = file->f_path.dentry; parent = dir->d_parent->d_inode; ctx = SPUFS_I(dir->d_inode)->i_ctx; @@ -363,7 +363,7 @@ static int spufs_gang_close(struct inode *inode, struct file *file) struct dentry *dir; int ret; - dir = file->f_dentry; + dir = file->f_path.dentry; parent = dir->d_parent->d_inode; ret = spufs_rmgang(parent, dir); diff --git a/arch/powerpc/platforms/cell/spufs/syscalls.c b/arch/powerpc/platforms/cell/spufs/syscalls.c index a6d1ae4dc2a..8e37bdf4dfd 100644 --- a/arch/powerpc/platforms/cell/spufs/syscalls.c +++ b/arch/powerpc/platforms/cell/spufs/syscalls.c @@ -46,7 +46,7 @@ static long do_spu_run(struct file *filp, if (filp->f_op != &spufs_context_fops) goto out; - i = SPUFS_I(filp->f_dentry->d_inode); + i = SPUFS_I(filp->f_path.dentry->d_inode); ret = spufs_run_spu(filp, i->i_ctx, &npc, &status); if (put_user(npc, unpc)) diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index b5737d68d6c..cff15ae24f6 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c @@ -1178,7 +1178,7 @@ static ssize_t proc_mf_change_vmlinux(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode); ssize_t rc; dma_addr_t dma_addr; char *page; diff --git a/arch/powerpc/platforms/pseries/hvCall_inst.c b/arch/powerpc/platforms/pseries/hvCall_inst.c index 446e17d162a..80181c4c49e 100644 --- a/arch/powerpc/platforms/pseries/hvCall_inst.c +++ b/arch/powerpc/platforms/pseries/hvCall_inst.c @@ -85,7 +85,7 @@ static int hcall_inst_seq_open(struct inode *inode, struct file *file) rc = seq_open(file, &hcall_inst_seq_ops); seq = file->private_data; - seq->private = file->f_dentry->d_inode->i_private; + seq->private = file->f_path.dentry->d_inode->i_private; return rc; } diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c index 77a5bb1d9c3..45368a57d7d 100644 --- a/arch/powerpc/platforms/pseries/scanlog.c +++ b/arch/powerpc/platforms/pseries/scanlog.c @@ -47,7 +47,7 @@ static struct proc_dir_entry *proc_ppc64_scan_log_dump; /* The proc file */ static ssize_t scanlog_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct inode * inode = file->f_dentry->d_inode; + struct inode * inode = file->f_path.dentry->d_inode; struct proc_dir_entry *dp; unsigned int *data; int status; diff --git a/arch/ppc/8xx_io/cs4218_tdm.c b/arch/ppc/8xx_io/cs4218_tdm.c index 959d31c26cb..c71ef3c2e7b 100644 --- a/arch/ppc/8xx_io/cs4218_tdm.c +++ b/arch/ppc/8xx_io/cs4218_tdm.c @@ -2165,7 +2165,7 @@ static int sq_release(struct inode *inode, struct file *file) int rc = 0; if (sq.busy) - rc = sq_fsync(file, file->f_dentry); + rc = sq_fsync(file, file->f_path.dentry); sound.soft = sound.dsp; sound.hard = sound.dsp; sound_silence(); @@ -2218,25 +2218,25 @@ static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd, return 0; case SNDCTL_DSP_POST: case SNDCTL_DSP_SYNC: - return sq_fsync(file, file->f_dentry); + return sq_fsync(file, file->f_path.dentry); /* ++TeSche: before changing any of these it's * probably wise to wait until sound playing has * settled down. */ case SNDCTL_DSP_SPEED: - sq_fsync(file, file->f_dentry); + sq_fsync(file, file->f_path.dentry); IOCTL_IN(arg, data); return IOCTL_OUT(arg, sound_set_speed(data)); case SNDCTL_DSP_STEREO: - sq_fsync(file, file->f_dentry); + sq_fsync(file, file->f_path.dentry); IOCTL_IN(arg, data); return IOCTL_OUT(arg, sound_set_stereo(data)); case SOUND_PCM_WRITE_CHANNELS: - sq_fsync(file, file->f_dentry); + sq_fsync(file, file->f_path.dentry); IOCTL_IN(arg, data); return IOCTL_OUT(arg, sound_set_stereo(data-1)+1); case SNDCTL_DSP_SETFMT: - sq_fsync(file, file->f_dentry); + sq_fsync(file, file->f_path.dentry); IOCTL_IN(arg, data); return IOCTL_OUT(arg, sound_set_format(data)); case SNDCTL_DSP_GETFMTS: diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index edf71a4ecc9..692b5ba5320 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -19,6 +19,14 @@ config RWSEM_XCHGADD_ALGORITHM bool default y +config ARCH_HAS_ILOG2_U32 + bool + default y + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_HWEIGHT bool default y @@ -52,6 +60,11 @@ config ARCH_MAY_HAVE_PC_FDC bool default y +config GENERIC_BUG + bool + default y + depends on BUG + source "init/Kconfig" menu "Processor" diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index 2f835b9e95e..810f7aa72e9 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -28,6 +28,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/prctl.h> +#include <linux/bug.h> #include <asm/pgtable.h> #include <asm/uaccess.h> @@ -559,64 +560,9 @@ static void emulate_single_step(struct pt_regs *regs) } } -/* - * Look through the list of trap instructions that are used for BUG(), - * BUG_ON() and WARN_ON() and see if we hit one. At this point we know - * that the exception was caused by a trap instruction of some kind. - * Returns 1 if we should continue (i.e. it was a WARN_ON) or 0 - * otherwise. - */ -extern struct bug_entry __start___bug_table[], __stop___bug_table[]; - -#ifndef CONFIG_MODULES -#define module_find_bug(x) NULL -#endif - -struct bug_entry *find_bug(unsigned long bugaddr) -{ - struct bug_entry *bug; - - for (bug = __start___bug_table; bug < __stop___bug_table; ++bug) - if (bugaddr == bug->bug_addr) - return bug; - return module_find_bug(bugaddr); -} - -int check_bug_trap(struct pt_regs *regs) +int is_valid_bugaddr(unsigned long addr) { - struct bug_entry *bug; - unsigned long addr; - - if (regs->msr & MSR_PR) - return 0; /* not in kernel */ - addr = regs->nip; /* address of trap instruction */ - if (addr < PAGE_OFFSET) - return 0; - bug = find_bug(regs->nip); - if (bug == NULL) - return 0; - if (bug->line & BUG_WARNING_TRAP) { - /* this is a WARN_ON rather than BUG/BUG_ON */ -#ifdef CONFIG_XMON - xmon_printf(KERN_ERR "Badness in %s at %s:%ld\n", - bug->function, bug->file, - bug->line & ~BUG_WARNING_TRAP); -#endif /* CONFIG_XMON */ - printk(KERN_ERR "Badness in %s at %s:%ld\n", - bug->function, bug->file, - bug->line & ~BUG_WARNING_TRAP); - dump_stack(); - return 1; - } -#ifdef CONFIG_XMON - xmon_printf(KERN_CRIT "kernel BUG in %s at %s:%ld!\n", - bug->function, bug->file, bug->line); - xmon(regs); -#endif /* CONFIG_XMON */ - printk(KERN_CRIT "kernel BUG in %s at %s:%ld!\n", - bug->function, bug->file, bug->line); - - return 0; + return addr >= PAGE_OFFSET; } void program_check_exception(struct pt_regs *regs) @@ -671,7 +617,9 @@ void program_check_exception(struct pt_regs *regs) /* trap exception */ if (debugger_bpt(regs)) return; - if (check_bug_trap(regs)) { + + if (!(regs->msr & MSR_PR) && /* not user-mode */ + report_bug(regs->nip) == BUG_TRAP_TYPE_WARN) { regs->nip += 4; return; } diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 04f5a023029..ff690564edb 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -22,6 +22,14 @@ config RWSEM_XCHGADD_ALGORITHM bool default y +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_HWEIGHT bool default y diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c index cd702ae45d6..b6716c4b993 100644 --- a/arch/s390/hypfs/inode.c +++ b/arch/s390/hypfs/inode.c @@ -109,7 +109,7 @@ static void hypfs_drop_inode(struct inode *inode) static int hypfs_open(struct inode *inode, struct file *filp) { - char *data = filp->f_dentry->d_inode->i_private; + char *data = filp->f_path.dentry->d_inode->i_private; struct hypfs_sb_info *fs_info; if (filp->f_mode & FMODE_WRITE) { @@ -174,7 +174,7 @@ static ssize_t hypfs_aio_write(struct kiocb *iocb, const struct iovec *iov, struct hypfs_sb_info *fs_info; size_t count = iov_length(iov, nr_segs); - sb = iocb->ki_filp->f_dentry->d_inode->i_sb; + sb = iocb->ki_filp->f_path.dentry->d_inode->i_sb; fs_info = sb->s_fs_info; /* * Currently we only allow one update per second for two reasons: diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index 43f3d0c7e13..ef5266fbce6 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c @@ -603,13 +603,13 @@ debug_open(struct inode *inode, struct file *file) debug_info_t *debug_info, *debug_info_snapshot; down(&debug_lock); - debug_info = file->f_dentry->d_inode->i_private; + debug_info = file->f_path.dentry->d_inode->i_private; /* find debug view */ for (i = 0; i < DEBUG_MAX_VIEWS; i++) { if (!debug_info->views[i]) continue; else if (debug_info->debugfs_entries[i] == - file->f_dentry) { + file->f_path.dentry) { goto found; /* found view ! */ } } diff --git a/arch/s390/mm/ioremap.c b/arch/s390/mm/ioremap.c index 0f6e9ecbefe..3d2100a4e20 100644 --- a/arch/s390/mm/ioremap.c +++ b/arch/s390/mm/ioremap.c @@ -15,87 +15,8 @@ #include <linux/vmalloc.h> #include <linux/mm.h> -#include <asm/io.h> +#include <linux/io.h> #include <asm/pgalloc.h> -#include <asm/cacheflush.h> -#include <asm/tlbflush.h> - -static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, - unsigned long phys_addr, unsigned long flags) -{ - unsigned long end; - unsigned long pfn; - - address &= ~PMD_MASK; - end = address + size; - if (end > PMD_SIZE) - end = PMD_SIZE; - if (address >= end) - BUG(); - pfn = phys_addr >> PAGE_SHIFT; - do { - if (!pte_none(*pte)) { - printk("remap_area_pte: page already exists\n"); - BUG(); - } - set_pte(pte, pfn_pte(pfn, __pgprot(flags))); - address += PAGE_SIZE; - pfn++; - pte++; - } while (address && (address < end)); -} - -static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, - unsigned long phys_addr, unsigned long flags) -{ - unsigned long end; - - address &= ~PGDIR_MASK; - end = address + size; - if (end > PGDIR_SIZE) - end = PGDIR_SIZE; - phys_addr -= address; - if (address >= end) - BUG(); - do { - pte_t * pte = pte_alloc_kernel(pmd, address); - if (!pte) - return -ENOMEM; - remap_area_pte(pte, address, end - address, address + phys_addr, flags); - address = (address + PMD_SIZE) & PMD_MASK; - pmd++; - } while (address && (address < end)); - return 0; -} - -static int remap_area_pages(unsigned long address, unsigned long phys_addr, - unsigned long size, unsigned long flags) -{ - int error; - pgd_t * dir; - unsigned long end = address + size; - - phys_addr -= address; - dir = pgd_offset(&init_mm, address); - flush_cache_all(); - if (address >= end) - BUG(); - do { - pmd_t *pmd; - pmd = pmd_alloc(&init_mm, dir, address); - error = -ENOMEM; - if (!pmd) - break; - if (remap_area_pmd(pmd, address, end - address, - phys_addr + address, flags)) - break; - error = 0; - address = (address + PGDIR_SIZE) & PGDIR_MASK; - dir++; - } while (address && (address < end)); - flush_tlb_all(); - return 0; -} /* * Generic mapping function (not visible outside): @@ -122,7 +43,8 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag if (!area) return NULL; addr = area->addr; - if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) { + if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size, + phys_addr, __pgprot(flags))) { vfree(addr); return NULL; } diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index d83d64af31f..8e24c40662e 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -59,6 +59,14 @@ config LOCKDEP_SUPPORT bool default y +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + source "init/Kconfig" menu "System type" diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c index 11d54c14982..90b494a0cf4 100644 --- a/arch/sh/mm/ioremap.c +++ b/arch/sh/mm/ioremap.c @@ -16,97 +16,13 @@ #include <linux/module.h> #include <linux/mm.h> #include <linux/pci.h> -#include <asm/io.h> +#include <linux/io.h> #include <asm/page.h> #include <asm/pgalloc.h> #include <asm/addrspace.h> #include <asm/cacheflush.h> #include <asm/tlbflush.h> -static inline void remap_area_pte(pte_t * pte, unsigned long address, - unsigned long size, unsigned long phys_addr, unsigned long flags) -{ - unsigned long end; - unsigned long pfn; - pgprot_t pgprot = __pgprot(pgprot_val(PAGE_KERNEL_NOCACHE) | flags); - - address &= ~PMD_MASK; - end = address + size; - if (end > PMD_SIZE) - end = PMD_SIZE; - if (address >= end) - BUG(); - pfn = phys_addr >> PAGE_SHIFT; - do { - if (!pte_none(*pte)) { - printk("remap_area_pte: page already exists\n"); - BUG(); - } - set_pte(pte, pfn_pte(pfn, pgprot)); - address += PAGE_SIZE; - pfn++; - pte++; - } while (address && (address < end)); -} - -static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, - unsigned long size, unsigned long phys_addr, unsigned long flags) -{ - unsigned long end; - - address &= ~PGDIR_MASK; - end = address + size; - if (end > PGDIR_SIZE) - end = PGDIR_SIZE; - phys_addr -= address; - if (address >= end) - BUG(); - do { - pte_t * pte = pte_alloc_kernel(pmd, address); - if (!pte) - return -ENOMEM; - remap_area_pte(pte, address, end - address, address + phys_addr, flags); - address = (address + PMD_SIZE) & PMD_MASK; - pmd++; - } while (address && (address < end)); - return 0; -} - -int remap_area_pages(unsigned long address, unsigned long phys_addr, - unsigned long size, unsigned long flags) -{ - int error; - pgd_t * dir; - unsigned long end = address + size; - - phys_addr -= address; - dir = pgd_offset_k(address); - flush_cache_all(); - if (address >= end) - BUG(); - do { - pud_t *pud; - pmd_t *pmd; - - error = -ENOMEM; - - pud = pud_alloc(&init_mm, dir, address); - if (!pud) - break; - pmd = pmd_alloc(&init_mm, pud, address); - if (!pmd) - break; - if (remap_area_pmd(pmd, address, end - address, - phys_addr + address, flags)) - break; - error = 0; - address = (address + PGDIR_SIZE) & PGDIR_MASK; - dir++; - } while (address && (address < end)); - flush_tlb_all(); - return error; -} - /* * Remap an arbitrary physical address space into the kernel virtual * address space. Needed when the kernel wants to access high addresses @@ -121,6 +37,7 @@ void __iomem *__ioremap(unsigned long phys_addr, unsigned long size, { struct vm_struct * area; unsigned long offset, last_addr, addr, orig_addr; + pgprot_t pgprot; /* Don't allow wraparound or zero size */ last_addr = phys_addr + size - 1; @@ -190,8 +107,9 @@ void __iomem *__ioremap(unsigned long phys_addr, unsigned long size, } #endif + pgprot = __pgprot(pgprot_val(PAGE_KERNEL_NOCACHE) | flags); if (likely(size)) - if (remap_area_pages(addr, phys_addr, size, flags)) { + if (ioremap_page_range(addr, addr + size, phys_addr, pgprot)) { vunmap((void *)orig_addr); return NULL; } diff --git a/arch/sh/oprofile/op_model_sh7750.c b/arch/sh/oprofile/op_model_sh7750.c index c265185b22a..60402eec4b4 100644 --- a/arch/sh/oprofile/op_model_sh7750.c +++ b/arch/sh/oprofile/op_model_sh7750.c @@ -142,7 +142,7 @@ static u64 sh7750_read_counter(int counter) */ static inline int to_counter(struct file *file) { - const unsigned char *name = file->f_dentry->d_parent->d_name.name; + const unsigned char *name = file->f_path.dentry->d_parent->d_name.name; return (int)simple_strtol(name, NULL, 10); } diff --git a/arch/sh64/Kconfig b/arch/sh64/Kconfig index 58c678e0666..7bc0744b7ab 100644 --- a/arch/sh64/Kconfig +++ b/arch/sh64/Kconfig @@ -39,6 +39,14 @@ config RWSEM_XCHGADD_ALGORITHM config GENERIC_ISA_DMA bool +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + source init/Kconfig menu "System type" diff --git a/arch/sh64/mm/ioremap.c b/arch/sh64/mm/ioremap.c index 80c56754f51..ff26c02511a 100644 --- a/arch/sh64/mm/ioremap.c +++ b/arch/sh64/mm/ioremap.c @@ -18,7 +18,7 @@ #include <linux/vmalloc.h> #include <linux/sched.h> #include <linux/string.h> -#include <asm/io.h> +#include <linux/io.h> #include <asm/pgalloc.h> #include <asm/tlbflush.h> #include <linux/ioport.h> @@ -28,96 +28,6 @@ static void shmedia_mapioaddr(unsigned long, unsigned long); static unsigned long shmedia_ioremap(struct resource *, u32, int); -static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, - unsigned long phys_addr, unsigned long flags) -{ - unsigned long end; - unsigned long pfn; - pgprot_t pgprot = __pgprot(_PAGE_PRESENT | _PAGE_READ | - _PAGE_WRITE | _PAGE_DIRTY | - _PAGE_ACCESSED | _PAGE_SHARED | flags); - - address &= ~PMD_MASK; - end = address + size; - if (end > PMD_SIZE) - end = PMD_SIZE; - if (address >= end) - BUG(); - - pfn = phys_addr >> PAGE_SHIFT; - - pr_debug(" %s: pte %p address %lx size %lx phys_addr %lx\n", - __FUNCTION__,pte,address,size,phys_addr); - - do { - if (!pte_none(*pte)) { - printk("remap_area_pte: page already exists\n"); - BUG(); - } - - set_pte(pte, pfn_pte(pfn, pgprot)); - address += PAGE_SIZE; - pfn++; - pte++; - } while (address && (address < end)); -} - -static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, - unsigned long phys_addr, unsigned long flags) -{ - unsigned long end; - - address &= ~PGDIR_MASK; - end = address + size; - - if (end > PGDIR_SIZE) - end = PGDIR_SIZE; - - phys_addr -= address; - - if (address >= end) - BUG(); - - do { - pte_t * pte = pte_alloc_kernel(pmd, address); - if (!pte) - return -ENOMEM; - remap_area_pte(pte, address, end - address, address + phys_addr, flags); - address = (address + PMD_SIZE) & PMD_MASK; - pmd++; - } while (address && (address < end)); - return 0; -} - -static int remap_area_pages(unsigned long address, unsigned long phys_addr, - unsigned long size, unsigned long flags) -{ - int error; - pgd_t * dir; - unsigned long end = address + size; - - phys_addr -= address; - dir = pgd_offset_k(address); - flush_cache_all(); - if (address >= end) - BUG(); - do { - pmd_t *pmd = pmd_alloc(&init_mm, dir, address); - error = -ENOMEM; - if (!pmd) - break; - if (remap_area_pmd(pmd, address, end - address, - phys_addr + address, flags)) { - break; - } - error = 0; - address = (address + PGDIR_SIZE) & PGDIR_MASK; - dir++; - } while (address && (address < end)); - flush_tlb_all(); - return 0; -} - /* * Generic mapping function (not visible outside): */ @@ -136,12 +46,17 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag void * addr; struct vm_struct * area; unsigned long offset, last_addr; + pgprot_t pgprot; /* Don't allow wraparound or zero size */ last_addr = phys_addr + size - 1; if (!size || last_addr < phys_addr) return NULL; + pgprot = __pgprot(_PAGE_PRESENT | _PAGE_READ | + _PAGE_WRITE | _PAGE_DIRTY | + _PAGE_ACCESSED | _PAGE_SHARED | flags); + /* * Mappings have to be page-aligned */ @@ -158,7 +73,8 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag return NULL; area->phys_addr = phys_addr; addr = area->addr; - if (remap_area_pages((unsigned long)addr, phys_addr, size, flags)) { + if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size, + phys_addr, pgprot)) { vunmap(addr); return NULL; } diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 92a7c8a636d..d0dec1ea2ee 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -166,6 +166,14 @@ config ARCH_MAY_HAVE_PC_FDC bool default y +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config SUN_PM bool default y diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c index 6f3ac548ee6..0bf8c165fc9 100644 --- a/arch/sparc/kernel/sys_sunos.c +++ b/arch/sparc/kernel/sys_sunos.c @@ -94,8 +94,8 @@ asmlinkage unsigned long sunos_mmap(unsigned long addr, unsigned long len, * SunOS is so stupid some times... hmph! */ if (file) { - if (imajor(file->f_dentry->d_inode) == MEM_MAJOR && - iminor(file->f_dentry->d_inode) == 5) { + if (imajor(file->f_path.dentry->d_inode) == MEM_MAJOR && + iminor(file->f_path.dentry->d_inode) == 5) { flags |= MAP_ANONYMOUS; fput(file); file = NULL; @@ -655,7 +655,7 @@ sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr) if (!file) goto out; - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; socket = SOCKET_I(inode); local.sin_family = AF_INET; diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index b627f8dbcaa..d391d11f245 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig @@ -34,6 +34,14 @@ config ARCH_MAY_HAVE_PC_FDC bool default y +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config AUDIT_ARCH bool default y diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c index d7caa60a007..f205fc7cbcd 100644 --- a/arch/sparc64/kernel/binfmt_aout32.c +++ b/arch/sparc64/kernel/binfmt_aout32.c @@ -209,7 +209,7 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs) if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC && N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) || N_TRSIZE(ex) || N_DRSIZE(ex) || - bprm->file->f_dentry->d_inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) { + bprm->file->f_path.dentry->d_inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) { return -ENOEXEC; } @@ -349,7 +349,7 @@ static int load_aout32_library(struct file *file) int retval; struct exec ex; - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; retval = -ENOEXEC; error = kernel_read(file, 0, (char *) &ex, sizeof(ex)); diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c index 7da72d3b322..4446f66590f 100644 --- a/arch/sparc64/kernel/sys_sunos32.c +++ b/arch/sparc64/kernel/sys_sunos32.c @@ -83,7 +83,7 @@ asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 of file = fget(fd); if (!file) goto out; - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; if (imajor(inode) == MEM_MAJOR && iminor(inode) == 5) { flags |= MAP_ANONYMOUS; fput(file); @@ -615,7 +615,7 @@ sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr) if (!file) return 0; - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; socket = SOCKET_I(inode); local.sin_family = AF_INET; diff --git a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c index 12a940cc791..61be597bf43 100644 --- a/arch/sparc64/solaris/fs.c +++ b/arch/sparc64/solaris/fs.c @@ -449,7 +449,7 @@ asmlinkage int solaris_fstatvfs(unsigned int fd, u32 buf) error = -EBADF; file = fget(fd); if (file) { - error = report_statvfs(file->f_vfsmnt, file->f_dentry->d_inode, buf); + error = report_statvfs(file->f_path.mnt, file->f_path.dentry->d_inode, buf); fput(file); } @@ -481,7 +481,7 @@ asmlinkage int solaris_fstatvfs64(unsigned int fd, u32 buf) file = fget(fd); if (file) { lock_kernel(); - error = report_statvfs64(file->f_vfsmnt, file->f_dentry->d_inode, buf); + error = report_statvfs64(file->f_path.mnt, file->f_path.dentry->d_inode, buf); unlock_kernel(); fput(file); } diff --git a/arch/sparc64/solaris/ioctl.c b/arch/sparc64/solaris/ioctl.c index be0a054e3ed..330743c5b3d 100644 --- a/arch/sparc64/solaris/ioctl.c +++ b/arch/sparc64/solaris/ioctl.c @@ -299,8 +299,8 @@ static inline int solaris_sockmod(unsigned int fd, unsigned int cmd, u32 arg) rcu_read_lock(); fdt = files_fdtable(current->files); if (! fdt->fd[fd] || - ! fdt->fd[fd]->f_dentry || - ! (ino = fdt->fd[fd]->f_dentry->d_inode) || + ! fdt->fd[fd]->f_path.dentry || + ! (ino = fdt->fd[fd]->f_path.dentry->d_inode) || ! S_ISSOCK(ino->i_mode)) { rcu_read_unlock(); return TBADF; @@ -480,7 +480,7 @@ static inline int solaris_S(struct file *filp, unsigned int fd, unsigned int cmd struct sol_socket_struct *sock; struct module_info *mi; - ino = filp->f_dentry->d_inode; + ino = filp->f_path.dentry->d_inode; if (!S_ISSOCK(ino->i_mode)) return -EBADF; sock = filp->private_data; diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c index 9ed997982f8..bca16e8c95c 100644 --- a/arch/sparc64/solaris/misc.c +++ b/arch/sparc64/solaris/misc.c @@ -77,7 +77,7 @@ static u32 do_solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u64 o if (!file) goto out; else { - struct inode * inode = file->f_dentry->d_inode; + struct inode * inode = file->f_path.dentry->d_inode; if(imajor(inode) == MEM_MAJOR && iminor(inode) == 5) { flags |= MAP_ANONYMOUS; @@ -423,9 +423,7 @@ asmlinkage int solaris_procids(int cmd, s32 pid, s32 pgid) Solaris setpgrp and setsid? */ ret = sys_setpgid(0, 0); if (ret) return ret; - mutex_lock(&tty_mutex); - current->signal->tty = NULL; - mutex_unlock(&tty_mutex); + proc_clear_tty(current); return process_group(current); } case 2: /* getsid */ diff --git a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c index 7c90e41fd3b..89a4757f192 100644 --- a/arch/sparc64/solaris/socksys.c +++ b/arch/sparc64/solaris/socksys.c @@ -96,13 +96,13 @@ static int socksys_open(struct inode * inode, struct file * filp) * No shit. WTF is it supposed to do, anyway? * * Try instead: - * d_delete(filp->f_dentry), then d_instantiate with sock inode + * d_delete(filp->f_path.dentry), then d_instantiate with sock inode */ - dentry = filp->f_dentry; - filp->f_dentry = dget(fcheck(fd)->f_dentry); - filp->f_dentry->d_inode->i_rdev = inode->i_rdev; - filp->f_dentry->d_inode->i_flock = inode->i_flock; - SOCKET_I(filp->f_dentry->d_inode)->file = filp; + dentry = filp->f_path.dentry; + filp->f_path.dentry = dget(fcheck(fd)->f_path.dentry); + filp->f_path.dentry->d_inode->i_rdev = inode->i_rdev; + filp->f_path.dentry->d_inode->i_flock = inode->i_flock; + SOCKET_I(filp->f_path.dentry->d_inode)->file = filp; filp->f_op = &socksys_file_ops; sock = (struct sol_socket_struct*) mykmalloc(sizeof(struct sol_socket_struct), GFP_KERNEL); @@ -148,7 +148,7 @@ static unsigned int socksys_poll(struct file * filp, poll_table * wait) struct inode *ino; unsigned int mask = 0; - ino=filp->f_dentry->d_inode; + ino=filp->f_path.dentry->d_inode; if (ino && S_ISSOCK(ino->i_mode)) { struct sol_socket_struct *sock; sock = (struct sol_socket_struct*)filp->private_data; diff --git a/arch/sparc64/solaris/timod.c b/arch/sparc64/solaris/timod.c index b84e5456b02..a9d32ceabf2 100644 --- a/arch/sparc64/solaris/timod.c +++ b/arch/sparc64/solaris/timod.c @@ -147,7 +147,7 @@ static void timod_wake_socket(unsigned int fd) SOLD("wakeing socket"); fdt = files_fdtable(current->files); - sock = SOCKET_I(fdt->fd[fd]->f_dentry->d_inode); + sock = SOCKET_I(fdt->fd[fd]->f_path.dentry->d_inode); wake_up_interruptible(&sock->wait); read_lock(&sock->sk->sk_callback_lock); if (sock->fasync_list && !test_bit(SOCK_ASYNC_WAITDATA, &sock->flags)) @@ -361,7 +361,7 @@ int timod_putmsg(unsigned int fd, char __user *ctl_buf, int ctl_len, fdt = files_fdtable(current->files); filp = fdt->fd[fd]; - ino = filp->f_dentry->d_inode; + ino = filp->f_path.dentry->d_inode; sock = (struct sol_socket_struct *)filp->private_data; SOLD("entry"); if (get_user(ret, (int __user *)A(ctl_buf))) @@ -644,7 +644,7 @@ int timod_getmsg(unsigned int fd, char __user *ctl_buf, int ctl_maxlen, s32 __us SOLDD(("%u %p %d %p %p %d %p %d\n", fd, ctl_buf, ctl_maxlen, ctl_len, data_buf, data_maxlen, data_len, *flags_p)); fdt = files_fdtable(current->files); filp = fdt->fd[fd]; - ino = filp->f_dentry->d_inode; + ino = filp->f_path.dentry->d_inode; sock = (struct sol_socket_struct *)filp->private_data; SOLDD(("%p %p\n", sock->pfirst, sock->pfirst ? sock->pfirst->next : NULL)); if ( ctl_maxlen > 0 && !sock->pfirst && SOCKET_I(ino)->type == SOCK_STREAM @@ -865,7 +865,7 @@ asmlinkage int solaris_getmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3) filp = fdt->fd[fd]; if(!filp) goto out; - ino = filp->f_dentry->d_inode; + ino = filp->f_path.dentry->d_inode; if (!ino || !S_ISSOCK(ino->i_mode)) goto out; @@ -933,7 +933,7 @@ asmlinkage int solaris_putmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3) filp = fdt->fd[fd]; if(!filp) goto out; - ino = filp->f_dentry->d_inode; + ino = filp->f_path.dentry->d_inode; if (!ino) goto out; if (!S_ISSOCK(ino->i_mode) && diff --git a/arch/um/Kconfig b/arch/um/Kconfig index 5ac1f2963ae..d32a80e6668 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -47,6 +47,11 @@ config GENERIC_CALIBRATE_DELAY bool default y +config GENERIC_BUG + bool + default y + depends on BUG + # Used in kernel/irq/manage.c and include/linux/irq.h config IRQ_RELEASE_METHOD bool diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index aa3090d05a8..83301e1ef67 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -246,7 +246,7 @@ out_up: return ret; } -void line_set_termios(struct tty_struct *tty, struct termios * old) +void line_set_termios(struct tty_struct *tty, struct ktermios * old) { /* nothing */ } diff --git a/arch/um/include/line.h b/arch/um/include/line.h index 214ee76c40d..5f232ae89fb 100644 --- a/arch/um/include/line.h +++ b/arch/um/include/line.h @@ -76,7 +76,7 @@ extern int line_setup(struct line *lines, unsigned int sizeof_lines, extern int line_write(struct tty_struct *tty, const unsigned char *buf, int len); extern void line_put_char(struct tty_struct *tty, unsigned char ch); -extern void line_set_termios(struct tty_struct *tty, struct termios * old); +extern void line_set_termios(struct tty_struct *tty, struct ktermios * old); extern int line_chars_in_buffer(struct tty_struct *tty); extern void line_flush_buffer(struct tty_struct *tty); extern void line_flush_chars(struct tty_struct *tty); diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c index 0561c43b468..8d56ec6cca7 100644 --- a/arch/um/kernel/exec.c +++ b/arch/um/kernel/exec.c @@ -39,12 +39,13 @@ static long execve1(char *file, char __user * __user *argv, char __user *__user *env) { long error; + struct tty_struct *tty; #ifdef CONFIG_TTY_LOG mutex_lock(&tty_mutex); - task_lock(current); /* FIXME: is this needed ? */ - log_exec(argv, current->signal->tty); - task_unlock(current); + tty = get_current_tty(); + if (tty) + log_exec(argv, tty); mutex_unlock(&tty_mutex); #endif error = do_execve(file, argv, env, ¤t->thread.regs); diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile index 0e32adf03be..098720be019 100644 --- a/arch/um/sys-i386/Makefile +++ b/arch/um/sys-i386/Makefile @@ -1,4 +1,4 @@ -obj-y = bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ +obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ ptrace_user.o setjmp.o signal.o sigcontext.o syscalls.o sysrq.o \ sys_call_table.o tls.o diff --git a/arch/um/sys-i386/bug.c b/arch/um/sys-i386/bug.c new file mode 100644 index 00000000000..200c8ba2879 --- /dev/null +++ b/arch/um/sys-i386/bug.c @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com) + * Licensed under the GPL V2 + */ + +#include <linux/uaccess.h> + +/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because + * that's not relevent in skas mode. + */ + +int is_valid_bugaddr(unsigned long eip) +{ + unsigned short ud2; + + if (probe_kernel_address((unsigned short __user *)eip, ud2)) + return 0; + + return ud2 == 0x0b0f; +} diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile index f41768b8e25..4d9e5efa6fb 100644 --- a/arch/um/sys-x86_64/Makefile +++ b/arch/um/sys-x86_64/Makefile @@ -4,7 +4,7 @@ # Licensed under the GPL # -obj-y = bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \ +obj-y = bug.o bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \ setjmp.o sigcontext.o signal.o syscalls.o syscall_table.o sysrq.o \ ksyms.o tls.o diff --git a/arch/um/sys-x86_64/bug.c b/arch/um/sys-x86_64/bug.c new file mode 100644 index 00000000000..200c8ba2879 --- /dev/null +++ b/arch/um/sys-x86_64/bug.c @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com) + * Licensed under the GPL V2 + */ + +#include <linux/uaccess.h> + +/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because + * that's not relevent in skas mode. + */ + +int is_valid_bugaddr(unsigned long eip) +{ + unsigned short ud2; + + if (probe_kernel_address((unsigned short __user *)eip, ud2)) + return 0; + + return ud2 == 0x0b0f; +} diff --git a/arch/v850/Kconfig b/arch/v850/Kconfig index 37ec644603a..bcf825875d1 100644 --- a/arch/v850/Kconfig +++ b/arch/v850/Kconfig @@ -38,6 +38,14 @@ config TIME_LOW_RES bool default y +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + # Turn off some random 386 crap that can affect device config config ISA bool diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index bfbb9bcae12..3ac581d1720 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -96,6 +96,19 @@ config AUDIT_ARCH bool default y +config GENERIC_BUG + bool + default y + depends on BUG + +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + source "init/Kconfig" diff --git a/arch/x86_64/ia32/ia32_aout.c b/arch/x86_64/ia32/ia32_aout.c index 396d3c10001..be87df506f3 100644 --- a/arch/x86_64/ia32/ia32_aout.c +++ b/arch/x86_64/ia32/ia32_aout.c @@ -272,7 +272,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC && N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) || N_TRSIZE(ex) || N_DRSIZE(ex) || - i_size_read(bprm->file->f_dentry->d_inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) { + i_size_read(bprm->file->f_path.dentry->d_inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) { return -ENOEXEC; } @@ -357,7 +357,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) { printk(KERN_WARNING "fd_offset is not page aligned. Please convert program: %s\n", - bprm->file->f_dentry->d_name.name); + bprm->file->f_path.dentry->d_name.name); error_time = jiffies; } #endif @@ -440,7 +440,7 @@ static int load_aout_library(struct file *file) int retval; struct exec ex; - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; retval = -ENOEXEC; error = kernel_read(file, 0, (char *) &ex, sizeof(ex)); @@ -471,7 +471,7 @@ static int load_aout_library(struct file *file) { printk(KERN_WARNING "N_TXTOFF is not page aligned. Please convert library: %s\n", - file->f_dentry->d_name.name); + file->f_path.dentry->d_name.name); error_time = jiffies; } #endif diff --git a/arch/x86_64/kernel/module.c b/arch/x86_64/kernel/module.c index 9d0958ff547..a888e67f587 100644 --- a/arch/x86_64/kernel/module.c +++ b/arch/x86_64/kernel/module.c @@ -23,6 +23,7 @@ #include <linux/string.h> #include <linux/kernel.h> #include <linux/slab.h> +#include <linux/bug.h> #include <asm/system.h> #include <asm/page.h> @@ -173,10 +174,12 @@ int module_finalize(const Elf_Ehdr *hdr, lseg, lseg + locks->sh_size, tseg, tseg + text->sh_size); } - return 0; + + return module_bug_finalize(hdr, sechdrs, me); } void module_arch_cleanup(struct module *mod) { alternatives_smp_module_del(mod); + module_bug_cleanup(mod); } diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index a1641ffdffc..b54ccc07f37 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c @@ -31,6 +31,7 @@ #include <linux/kexec.h> #include <linux/unwind.h> #include <linux/uaccess.h> +#include <linux/bug.h> #include <asm/system.h> #include <asm/io.h> @@ -524,30 +525,15 @@ bad: printk("\n"); } -void handle_BUG(struct pt_regs *regs) -{ - struct bug_frame f; - long len; - const char *prefix = ""; +int is_valid_bugaddr(unsigned long rip) +{ + unsigned short ud2; - if (user_mode(regs)) - return; - if (__copy_from_user(&f, (const void __user *) regs->rip, - sizeof(struct bug_frame))) - return; - if (f.filename >= 0 || - f.ud2[0] != 0x0f || f.ud2[1] != 0x0b) - return; - len = __strnlen_user((char *)(long)f.filename, PATH_MAX) - 1; - if (len < 0 || len >= PATH_MAX) - f.filename = (int)(long)"unmapped filename"; - else if (len > 50) { - f.filename += len - 50; - prefix = "..."; - } - printk("----------- [cut here ] --------- [please bite here ] ---------\n"); - printk(KERN_ALERT "Kernel BUG at %s%.50s:%d\n", prefix, (char *)(long)f.filename, f.line); -} + if (__copy_from_user(&ud2, (const void __user *) rip, sizeof(ud2))) + return 0; + + return ud2 == 0x0b0f; +} #ifdef CONFIG_BUG void out_of_line_bug(void) @@ -627,7 +613,9 @@ void die(const char * str, struct pt_regs * regs, long err) { unsigned long flags = oops_begin(); - handle_BUG(regs); + if (!user_mode(regs)) + report_bug(regs->rip); + __die(str, regs, err); oops_end(flags); do_exit(SIGSEGV); diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S index 6a1f8f491e5..6c417788c54 100644 --- a/arch/x86_64/kernel/vmlinux.lds.S +++ b/arch/x86_64/kernel/vmlinux.lds.S @@ -51,6 +51,8 @@ SECTIONS RODATA + BUG_TABLE + . = ALIGN(PAGE_SIZE); /* Align data segment to page size boundary */ /* Data */ .data : AT(ADDR(.data) - LOAD_OFFSET) { diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index c1e69a1f92a..9eccfbd1b53 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -34,6 +34,14 @@ config GENERIC_HARDIRQS bool default y +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + source "init/Kconfig" menu "Processor type and features" diff --git a/block/genhd.c b/block/genhd.c index 653919d50cd..457fdac4c17 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -417,6 +417,34 @@ static struct disk_attribute disk_attr_stat = { .show = disk_stats_read }; +#ifdef CONFIG_FAIL_MAKE_REQUEST + +static ssize_t disk_fail_store(struct gendisk * disk, + const char *buf, size_t count) +{ + int i; + + if (count > 0 && sscanf(buf, "%d", &i) > 0) { + if (i == 0) + disk->flags &= ~GENHD_FL_FAIL; + else + disk->flags |= GENHD_FL_FAIL; + } + + return count; +} +static ssize_t disk_fail_read(struct gendisk * disk, char *page) +{ + return sprintf(page, "%d\n", disk->flags & GENHD_FL_FAIL ? 1 : 0); +} +static struct disk_attribute disk_attr_fail = { + .attr = {.name = "make-it-fail", .mode = S_IRUGO | S_IWUSR }, + .store = disk_fail_store, + .show = disk_fail_read +}; + +#endif + static struct attribute * default_attrs[] = { &disk_attr_uevent.attr, &disk_attr_dev.attr, @@ -424,6 +452,9 @@ static struct attribute * default_attrs[] = { &disk_attr_removable.attr, &disk_attr_size.attr, &disk_attr_stat.attr, +#ifdef CONFIG_FAIL_MAKE_REQUEST + &disk_attr_fail.attr, +#endif NULL, }; diff --git a/block/ioctl.c b/block/ioctl.c index 58aab630dfc..f6962b64660 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -72,7 +72,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user bdevp = bdget_disk(disk, part); if (!bdevp) return -ENOMEM; - mutex_lock_nested(&bdevp->bd_mutex, BD_MUTEX_PARTITION); + mutex_lock(&bdevp->bd_mutex); if (bdevp->bd_openers) { mutex_unlock(&bdevp->bd_mutex); bdput(bdevp); @@ -82,7 +82,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user fsync_bdev(bdevp); invalidate_bdev(bdevp, 0); - mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_WHOLE); + mutex_lock(&bdev->bd_mutex); delete_partition(disk, part); mutex_unlock(&bdev->bd_mutex); mutex_unlock(&bdevp->bd_mutex); @@ -290,7 +290,7 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, ENOIOCTLCMD for unknown ioctls. */ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) { - struct block_device *bdev = file->f_dentry->d_inode->i_bdev; + struct block_device *bdev = file->f_path.dentry->d_inode->i_bdev; struct gendisk *disk = bdev->bd_disk; int ret = -ENOIOCTLCMD; if (disk->fops->compat_ioctl) { diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 31512cd9f3a..4f83fd92237 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -28,6 +28,7 @@ #include <linux/interrupt.h> #include <linux/cpu.h> #include <linux/blktrace_api.h> +#include <linux/fault-inject.h> /* * for max sense size @@ -3056,6 +3057,42 @@ static void handle_bad_sector(struct bio *bio) set_bit(BIO_EOF, &bio->bi_flags); } +#ifdef CONFIG_FAIL_MAKE_REQUEST + +static DECLARE_FAULT_ATTR(fail_make_request); + +static int __init setup_fail_make_request(char *str) +{ + return setup_fault_attr(&fail_make_request, str); +} +__setup("fail_make_request=", setup_fail_make_request); + +static int should_fail_request(struct bio *bio) +{ + if ((bio->bi_bdev->bd_disk->flags & GENHD_FL_FAIL) || + (bio->bi_bdev->bd_part && bio->bi_bdev->bd_part->make_it_fail)) + return should_fail(&fail_make_request, bio->bi_size); + + return 0; +} + +static int __init fail_make_request_debugfs(void) +{ + return init_fault_attr_dentries(&fail_make_request, + "fail_make_request"); +} + +late_initcall(fail_make_request_debugfs); + +#else /* CONFIG_FAIL_MAKE_REQUEST */ + +static inline int should_fail_request(struct bio *bio) +{ + return 0; +} + +#endif /* CONFIG_FAIL_MAKE_REQUEST */ + /** * generic_make_request: hand a buffer to its device driver for I/O * @bio: The bio describing the location in memory and on the device. @@ -3141,6 +3178,9 @@ end_io: if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) goto end_io; + if (should_fail_request(bio)) + goto end_io; + /* * If this device has partitions, remap block n * of partition p to block n+start(p) of the disk. diff --git a/drivers/Kconfig b/drivers/Kconfig index f3946341890..4929e923b5c 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -64,6 +64,8 @@ source "drivers/video/Kconfig" source "sound/Kconfig" +source "drivers/hid/Kconfig" + source "drivers/usb/Kconfig" source "drivers/mmc/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 67711770b1d..50f76da598c 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -77,4 +77,5 @@ obj-$(CONFIG_CRYPTO) += crypto/ obj-$(CONFIG_SUPERH) += sh/ obj-$(CONFIG_GENERIC_TIME) += clocksource/ obj-$(CONFIG_DMA_ENGINE) += dma/ +obj-$(CONFIG_HID) += hid/ obj-$(CONFIG_PPC_PS3) += ps3/ diff --git a/drivers/atm/Kconfig b/drivers/atm/Kconfig index cfa5af883e1..2ddd76fdbc4 100644 --- a/drivers/atm/Kconfig +++ b/drivers/atm/Kconfig @@ -242,6 +242,7 @@ config ATM_IDT77252_USE_SUNI config ATM_AMBASSADOR tristate "Madge Ambassador (Collage PCI 155 Server)" depends on PCI && ATM + select BITREVERSE help This is a driver for ATMizer based ATM card produced by Madge Networks Ltd. Say Y (or M to compile as a module named ambassador) diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c index afa7d750a59..3c372e08f77 100644 --- a/drivers/atm/ambassador.c +++ b/drivers/atm/ambassador.c @@ -32,6 +32,7 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/poison.h> +#include <linux/bitrev.h> #include <asm/atomic.h> #include <asm/io.h> @@ -2068,18 +2069,6 @@ static void __devinit amb_ucode_version (amb_dev * dev) { PRINTK (KERN_INFO, "microcode version is %u.%u", major, minor); } -// swap bits within byte to get Ethernet ordering -static u8 bit_swap (u8 byte) -{ - const u8 swap[] = { - 0x0, 0x8, 0x4, 0xc, - 0x2, 0xa, 0x6, 0xe, - 0x1, 0x9, 0x5, 0xd, - 0x3, 0xb, 0x7, 0xf - }; - return ((swap[byte & 0xf]<<4) | swap[byte>>4]); -} - // get end station address static void __devinit amb_esi (amb_dev * dev, u8 * esi) { u32 lower4; @@ -2101,9 +2090,9 @@ static void __devinit amb_esi (amb_dev * dev, u8 * esi) { PRINTDB (DBG_INIT, "ESI:"); for (i = 0; i < ESI_LEN; ++i) { if (i < 4) - esi[i] = bit_swap (lower4>>(8*i)); + esi[i] = bitrev8(lower4>>(8*i)); else - esi[i] = bit_swap (upper2>>(8*(i-4))); + esi[i] = bitrev8(upper2>>(8*(i-4))); PRINTDM (DBG_INIT, " %02x", esi[i]); } diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 85072446d77..ce9cfcb6071 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -431,14 +431,18 @@ config CDROM_PKTCDVD tristate "Packet writing on CD/DVD media" depends on !UML help - If you have a CDROM drive that supports packet writing, say Y to - include preliminary support. It should work with any MMC/Mt Fuji - compliant ATAPI or SCSI drive, which is just about any newer CD - writer. + If you have a CDROM/DVD drive that supports packet writing, say + Y to include support. It should work with any MMC/Mt Fuji + compliant ATAPI or SCSI drive, which is just about any newer + DVD/CD writer. - Currently only writing to CD-RW, DVD-RW and DVD+RW discs is possible. + Currently only writing to CD-RW, DVD-RW, DVD+RW and DVDRAM discs + is possible. DVD-RW disks must be in restricted overwrite mode. + See the file <file:Documentation/cdrom/packet-writing.txt> + for further information on the use of this driver. + To compile this driver as a module, choose M here: the module will be called pktcdvd. diff --git a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c index 8e41c87b026..e04be94d195 100644 --- a/drivers/block/acsi_slm.c +++ b/drivers/block/acsi_slm.c @@ -363,7 +363,7 @@ static ssize_t slm_read( struct file *file, char *buf, size_t count, loff_t *ppos ) { - struct inode *node = file->f_dentry->d_inode; + struct inode *node = file->f_path.dentry->d_inode; unsigned long page; int length; int end; @@ -618,7 +618,7 @@ static ssize_t slm_write( struct file *file, const char *buf, size_t count, loff_t *ppos ) { - struct inode *node = file->f_dentry->d_inode; + struct inode *node = file->f_path.dentry->d_inode; int device = iminor(node); int n, filled, w, h; diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 892e092afe9..ee159edb6b8 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -535,7 +535,7 @@ static int do_ioctl(struct file *f, unsigned cmd, unsigned long arg) { int ret; lock_kernel(); - ret = cciss_ioctl(f->f_dentry->d_inode, f, cmd, arg); + ret = cciss_ioctl(f->f_path.dentry->d_inode, f, cmd, arg); unlock_kernel(); return ret; } diff --git a/drivers/block/loop.c b/drivers/block/loop.c index beab6d2643c..6b5b6420740 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1000,7 +1000,7 @@ loop_get_status(struct loop_device *lo, struct loop_info64 *info) if (lo->lo_state != Lo_bound) return -ENXIO; - error = vfs_getattr(file->f_vfsmnt, file->f_dentry, &stat); + error = vfs_getattr(file->f_path.mnt, file->f_path.dentry, &stat); if (error) return error; memset(info, 0, sizeof(*info)); @@ -1287,7 +1287,7 @@ loop_get_status_compat(struct loop_device *lo, static long lo_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct loop_device *lo = inode->i_bdev->bd_disk->private_data; int err; diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 7bf2cfbd628..090796bef78 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -537,7 +537,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file, error = -EINVAL; file = fget(arg); if (file) { - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; if (S_ISSOCK(inode->i_mode)) { lo->file = file; lo->sock = SOCKET_I(inode); diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index e45eaa26411..7c95c762950 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2000 Jens Axboe <axboe@suse.de> * Copyright (C) 2001-2004 Peter Osterlund <petero2@telia.com> + * Copyright (C) 2006 Thomas Maier <balagi@justmail.de> * * May be copied or modified under the terms of the GNU General Public * License. See linux/COPYING for more information. @@ -59,6 +60,8 @@ #include <scsi/scsi_cmnd.h> #include <scsi/scsi_ioctl.h> #include <scsi/scsi.h> +#include <linux/debugfs.h> +#include <linux/device.h> #include <asm/uaccess.h> @@ -83,9 +86,424 @@ static struct pktcdvd_device *pkt_devs[MAX_WRITERS]; static struct proc_dir_entry *pkt_proc; static int pktdev_major; +static int write_congestion_on = PKT_WRITE_CONGESTION_ON; +static int write_congestion_off = PKT_WRITE_CONGESTION_OFF; static struct mutex ctl_mutex; /* Serialize open/close/setup/teardown */ static mempool_t *psd_pool; +static struct class *class_pktcdvd = NULL; /* /sys/class/pktcdvd */ +static struct dentry *pkt_debugfs_root = NULL; /* /debug/pktcdvd */ + +/* forward declaration */ +static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev); +static int pkt_remove_dev(dev_t pkt_dev); +static int pkt_seq_show(struct seq_file *m, void *p); + + + +/* + * create and register a pktcdvd kernel object. + */ +static struct pktcdvd_kobj* pkt_kobj_create(struct pktcdvd_device *pd, + const char* name, + struct kobject* parent, + struct kobj_type* ktype) +{ + struct pktcdvd_kobj *p; + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return NULL; + kobject_set_name(&p->kobj, "%s", name); + p->kobj.parent = parent; + p->kobj.ktype = ktype; + p->pd = pd; + if (kobject_register(&p->kobj) != 0) + return NULL; + return p; +} +/* + * remove a pktcdvd kernel object. + */ +static void pkt_kobj_remove(struct pktcdvd_kobj *p) +{ + if (p) + kobject_unregister(&p->kobj); +} +/* + * default release function for pktcdvd kernel objects. + */ +static void pkt_kobj_release(struct kobject *kobj) +{ + kfree(to_pktcdvdkobj(kobj)); +} + + +/********************************************************** + * + * sysfs interface for pktcdvd + * by (C) 2006 Thomas Maier <balagi@justmail.de> + * + **********************************************************/ + +#define DEF_ATTR(_obj,_name,_mode) \ + static struct attribute _obj = { \ + .name = _name, .owner = THIS_MODULE, .mode = _mode } + +/********************************************************** + /sys/class/pktcdvd/pktcdvd[0-7]/ + stat/reset + stat/packets_started + stat/packets_finished + stat/kb_written + stat/kb_read + stat/kb_read_gather + write_queue/size + write_queue/congestion_off + write_queue/congestion_on + **********************************************************/ + +DEF_ATTR(kobj_pkt_attr_st1, "reset", 0200); +DEF_ATTR(kobj_pkt_attr_st2, "packets_started", 0444); +DEF_ATTR(kobj_pkt_attr_st3, "packets_finished", 0444); +DEF_ATTR(kobj_pkt_attr_st4, "kb_written", 0444); +DEF_ATTR(kobj_pkt_attr_st5, "kb_read", 0444); +DEF_ATTR(kobj_pkt_attr_st6, "kb_read_gather", 0444); + +static struct attribute *kobj_pkt_attrs_stat[] = { + &kobj_pkt_attr_st1, + &kobj_pkt_attr_st2, + &kobj_pkt_attr_st3, + &kobj_pkt_attr_st4, + &kobj_pkt_attr_st5, + &kobj_pkt_attr_st6, + NULL +}; + +DEF_ATTR(kobj_pkt_attr_wq1, "size", 0444); +DEF_ATTR(kobj_pkt_attr_wq2, "congestion_off", 0644); +DEF_ATTR(kobj_pkt_attr_wq3, "congestion_on", 0644); + +static struct attribute *kobj_pkt_attrs_wqueue[] = { + &kobj_pkt_attr_wq1, + &kobj_pkt_attr_wq2, + &kobj_pkt_attr_wq3, + NULL +}; + +/* declares a char buffer[64] _dbuf, copies data from + * _b with length _l into it and ensures that _dbuf ends + * with a \0 character. + */ +#define DECLARE_BUF_AS_STRING(_dbuf, _b, _l) \ + char _dbuf[64]; int dlen = (_l) < 0 ? 0 : (_l); \ + if (dlen >= sizeof(_dbuf)) dlen = sizeof(_dbuf)-1; \ + memcpy(_dbuf, _b, dlen); _dbuf[dlen] = 0 + +static ssize_t kobj_pkt_show(struct kobject *kobj, + struct attribute *attr, char *data) +{ + struct pktcdvd_device *pd = to_pktcdvdkobj(kobj)->pd; + int n = 0; + int v; + if (strcmp(attr->name, "packets_started") == 0) { + n = sprintf(data, "%lu\n", pd->stats.pkt_started); + + } else if (strcmp(attr->name, "packets_finished") == 0) { + n = sprintf(data, "%lu\n", pd->stats.pkt_ended); + + } else if (strcmp(attr->name, "kb_written") == 0) { + n = sprintf(data, "%lu\n", pd->stats.secs_w >> 1); + + } else if (strcmp(attr->name, "kb_read") == 0) { + n = sprintf(data, "%lu\n", pd->stats.secs_r >> 1); + + } else if (strcmp(attr->name, "kb_read_gather") == 0) { + n = sprintf(data, "%lu\n", pd->stats.secs_rg >> 1); + + } else if (strcmp(attr->name, "size") == 0) { + spin_lock(&pd->lock); + v = pd->bio_queue_size; + spin_unlock(&pd->lock); + n = sprintf(data, "%d\n", v); + + } else if (strcmp(attr->name, "congestion_off") == 0) { + spin_lock(&pd->lock); + v = pd->write_congestion_off; + spin_unlock(&pd->lock); + n = sprintf(data, "%d\n", v); + + } else if (strcmp(attr->name, "congestion_on") == 0) { + spin_lock(&pd->lock); + v = pd->write_congestion_on; + spin_unlock(&pd->lock); + n = sprintf(data, "%d\n", v); + } + return n; +} + +static void init_write_congestion_marks(int* lo, int* hi) +{ + if (*hi > 0) { + *hi = max(*hi, 500); + *hi = min(*hi, 1000000); + if (*lo <= 0) + *lo = *hi - 100; + else { + *lo = min(*lo, *hi - 100); + *lo = max(*lo, 100); + } + } else { + *hi = -1; + *lo = -1; + } +} + +static ssize_t kobj_pkt_store(struct kobject *kobj, + struct attribute *attr, + const char *data, size_t len) +{ + struct pktcdvd_device *pd = to_pktcdvdkobj(kobj)->pd; + int val; + DECLARE_BUF_AS_STRING(dbuf, data, len); /* ensure sscanf scans a string */ + + if (strcmp(attr->name, "reset") == 0 && dlen > 0) { + pd->stats.pkt_started = 0; + pd->stats.pkt_ended = 0; + pd->stats.secs_w = 0; + pd->stats.secs_rg = 0; + pd->stats.secs_r = 0; + + } else if (strcmp(attr->name, "congestion_off") == 0 + && sscanf(dbuf, "%d", &val) == 1) { + spin_lock(&pd->lock); + pd->write_congestion_off = val; + init_write_congestion_marks(&pd->write_congestion_off, + &pd->write_congestion_on); + spin_unlock(&pd->lock); + + } else if (strcmp(attr->name, "congestion_on") == 0 + && sscanf(dbuf, "%d", &val) == 1) { + spin_lock(&pd->lock); + pd->write_congestion_on = val; + init_write_congestion_marks(&pd->write_congestion_off, + &pd->write_congestion_on); + spin_unlock(&pd->lock); + } + return len; +} + +static struct sysfs_ops kobj_pkt_ops = { + .show = kobj_pkt_show, + .store = kobj_pkt_store +}; +static struct kobj_type kobj_pkt_type_stat = { + .release = pkt_kobj_release, + .sysfs_ops = &kobj_pkt_ops, + .default_attrs = kobj_pkt_attrs_stat +}; +static struct kobj_type kobj_pkt_type_wqueue = { + .release = pkt_kobj_release, + .sysfs_ops = &kobj_pkt_ops, + .default_attrs = kobj_pkt_attrs_wqueue +}; + +static void pkt_sysfs_dev_new(struct pktcdvd_device *pd) +{ + if (class_pktcdvd) { + pd->clsdev = class_device_create(class_pktcdvd, + NULL, pd->pkt_dev, + NULL, "%s", pd->name); + if (IS_ERR(pd->clsdev)) + pd->clsdev = NULL; + } + if (pd->clsdev) { + pd->kobj_stat = pkt_kobj_create(pd, "stat", + &pd->clsdev->kobj, + &kobj_pkt_type_stat); + pd->kobj_wqueue = pkt_kobj_create(pd, "write_queue", + &pd->clsdev->kobj, + &kobj_pkt_type_wqueue); + } +} + +static void pkt_sysfs_dev_remove(struct pktcdvd_device *pd) +{ + pkt_kobj_remove(pd->kobj_stat); + pkt_kobj_remove(pd->kobj_wqueue); + if (class_pktcdvd) + class_device_destroy(class_pktcdvd, pd->pkt_dev); +} + + +/******************************************************************** + /sys/class/pktcdvd/ + add map block device + remove unmap packet dev + device_map show mappings + *******************************************************************/ + +static void class_pktcdvd_release(struct class *cls) +{ + kfree(cls); +} +static ssize_t class_pktcdvd_show_map(struct class *c, char *data) +{ + int n = 0; + int idx; + mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); + for (idx = 0; idx < MAX_WRITERS; idx++) { + struct pktcdvd_device *pd = pkt_devs[idx]; + if (!pd) + continue; + n += sprintf(data+n, "%s %u:%u %u:%u\n", + pd->name, + MAJOR(pd->pkt_dev), MINOR(pd->pkt_dev), + MAJOR(pd->bdev->bd_dev), + MINOR(pd->bdev->bd_dev)); + } + mutex_unlock(&ctl_mutex); + return n; +} + +static ssize_t class_pktcdvd_store_add(struct class *c, const char *buf, + size_t count) +{ + unsigned int major, minor; + DECLARE_BUF_AS_STRING(dbuf, buf, count); + if (sscanf(dbuf, "%u:%u", &major, &minor) == 2) { + pkt_setup_dev(MKDEV(major, minor), NULL); + return count; + } + return -EINVAL; +} + +static ssize_t class_pktcdvd_store_remove(struct class *c, const char *buf, + size_t count) +{ + unsigned int major, minor; + DECLARE_BUF_AS_STRING(dbuf, buf, count); + if (sscanf(dbuf, "%u:%u", &major, &minor) == 2) { + pkt_remove_dev(MKDEV(major, minor)); + return count; + } + return -EINVAL; +} + +static struct class_attribute class_pktcdvd_attrs[] = { + __ATTR(add, 0200, NULL, class_pktcdvd_store_add), + __ATTR(remove, 0200, NULL, class_pktcdvd_store_remove), + __ATTR(device_map, 0444, class_pktcdvd_show_map, NULL), + __ATTR_NULL +}; + + +static int pkt_sysfs_init(void) +{ + int ret = 0; + + /* + * create control files in sysfs + * /sys/class/pktcdvd/... + */ + class_pktcdvd = kzalloc(sizeof(*class_pktcdvd), GFP_KERNEL); + if (!class_pktcdvd) + return -ENOMEM; + class_pktcdvd->name = DRIVER_NAME; + class_pktcdvd->owner = THIS_MODULE; + class_pktcdvd->class_release = class_pktcdvd_release; + class_pktcdvd->class_attrs = class_pktcdvd_attrs; + ret = class_register(class_pktcdvd); + if (ret) { + kfree(class_pktcdvd); + class_pktcdvd = NULL; + printk(DRIVER_NAME": failed to create class pktcdvd\n"); + return ret; + } + return 0; +} + +static void pkt_sysfs_cleanup(void) +{ + if (class_pktcdvd) + class_destroy(class_pktcdvd); + class_pktcdvd = NULL; +} + +/******************************************************************** + entries in debugfs + + /debugfs/pktcdvd[0-7]/ + info + + *******************************************************************/ + +static int pkt_debugfs_seq_show(struct seq_file *m, void *p) +{ + return pkt_seq_show(m, p); +} + +static int pkt_debugfs_fops_open(struct inode *inode, struct file *file) +{ + return single_open(file, pkt_debugfs_seq_show, inode->i_private); +} + +static struct file_operations debug_fops = { + .open = pkt_debugfs_fops_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static void pkt_debugfs_dev_new(struct pktcdvd_device *pd) +{ + if (!pkt_debugfs_root) + return; + pd->dfs_f_info = NULL; + pd->dfs_d_root = debugfs_create_dir(pd->name, pkt_debugfs_root); + if (IS_ERR(pd->dfs_d_root)) { + pd->dfs_d_root = NULL; + return; + } + pd->dfs_f_info = debugfs_create_file("info", S_IRUGO, + pd->dfs_d_root, pd, &debug_fops); + if (IS_ERR(pd->dfs_f_info)) { + pd->dfs_f_info = NULL; + return; + } +} + +static void pkt_debugfs_dev_remove(struct pktcdvd_device *pd) +{ + if (!pkt_debugfs_root) + return; + if (pd->dfs_f_info) + debugfs_remove(pd->dfs_f_info); + pd->dfs_f_info = NULL; + if (pd->dfs_d_root) + debugfs_remove(pd->dfs_d_root); + pd->dfs_d_root = NULL; +} + +static void pkt_debugfs_init(void) +{ + pkt_debugfs_root = debugfs_create_dir(DRIVER_NAME, NULL); + if (IS_ERR(pkt_debugfs_root)) { + pkt_debugfs_root = NULL; + return; + } +} + +static void pkt_debugfs_cleanup(void) +{ + if (!pkt_debugfs_root) + return; + debugfs_remove(pkt_debugfs_root); + pkt_debugfs_root = NULL; +} + +/* ----------------------------------------------------------*/ + static void pkt_bio_finished(struct pktcdvd_device *pd) { @@ -893,6 +1311,7 @@ static int pkt_handle_queue(struct pktcdvd_device *pd) sector_t zone = 0; /* Suppress gcc warning */ struct pkt_rb_node *node, *first_node; struct rb_node *n; + int wakeup; VPRINTK("handle_queue\n"); @@ -965,7 +1384,13 @@ try_next_bio: pkt->write_size += bio->bi_size / CD_FRAMESIZE; spin_unlock(&pkt->lock); } + /* check write congestion marks, and if bio_queue_size is + below, wake up any waiters */ + wakeup = (pd->write_congestion_on > 0 + && pd->bio_queue_size <= pd->write_congestion_off); spin_unlock(&pd->lock); + if (wakeup) + blk_clear_queue_congested(pd->disk->queue, WRITE); pkt->sleep_time = max(PACKET_WAIT_TIME, 1); pkt_set_state(pkt, PACKET_WAITING_STATE); @@ -2178,6 +2603,23 @@ static int pkt_make_request(request_queue_t *q, struct bio *bio) } spin_unlock(&pd->cdrw.active_list_lock); + /* + * Test if there is enough room left in the bio work queue + * (queue size >= congestion on mark). + * If not, wait till the work queue size is below the congestion off mark. + */ + spin_lock(&pd->lock); + if (pd->write_congestion_on > 0 + && pd->bio_queue_size >= pd->write_congestion_on) { + blk_set_queue_congested(q, WRITE); + do { + spin_unlock(&pd->lock); + congestion_wait(WRITE, HZ); + spin_lock(&pd->lock); + } while(pd->bio_queue_size > pd->write_congestion_off); + } + spin_unlock(&pd->lock); + /* * No matching packet found. Store the bio in the work queue. */ @@ -2297,6 +2739,9 @@ static int pkt_seq_show(struct seq_file *m, void *p) seq_printf(m, "\tstate:\t\t\ti:%d ow:%d rw:%d ww:%d rec:%d fin:%d\n", states[0], states[1], states[2], states[3], states[4], states[5]); + seq_printf(m, "\twrite congestion marks:\toff=%d on=%d\n", + pd->write_congestion_off, + pd->write_congestion_on); return 0; } @@ -2436,36 +2881,33 @@ static struct block_device_operations pktcdvd_ops = { /* * Set up mapping from pktcdvd device to CD-ROM device. */ -static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd) +static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev) { int idx; int ret = -ENOMEM; struct pktcdvd_device *pd; struct gendisk *disk; - dev_t dev = new_decode_dev(ctrl_cmd->dev); + + mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); for (idx = 0; idx < MAX_WRITERS; idx++) if (!pkt_devs[idx]) break; if (idx == MAX_WRITERS) { printk(DRIVER_NAME": max %d writers supported\n", MAX_WRITERS); - return -EBUSY; + ret = -EBUSY; + goto out_mutex; } pd = kzalloc(sizeof(struct pktcdvd_device), GFP_KERNEL); if (!pd) - return ret; + goto out_mutex; pd->rb_pool = mempool_create_kmalloc_pool(PKT_RB_POOL_SIZE, sizeof(struct pkt_rb_node)); if (!pd->rb_pool) goto out_mem; - disk = alloc_disk(1); - if (!disk) - goto out_mem; - pd->disk = disk; - INIT_LIST_HEAD(&pd->cdrw.pkt_free_list); INIT_LIST_HEAD(&pd->cdrw.pkt_active_list); spin_lock_init(&pd->cdrw.active_list_lock); @@ -2476,11 +2918,18 @@ static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd) init_waitqueue_head(&pd->wqueue); pd->bio_queue = RB_ROOT; + pd->write_congestion_on = write_congestion_on; + pd->write_congestion_off = write_congestion_off; + + disk = alloc_disk(1); + if (!disk) + goto out_mem; + pd->disk = disk; disk->major = pktdev_major; disk->first_minor = idx; disk->fops = &pktcdvd_ops; disk->flags = GENHD_FL_REMOVABLE; - sprintf(disk->disk_name, DRIVER_NAME"%d", idx); + strcpy(disk->disk_name, pd->name); disk->private_data = pd; disk->queue = blk_alloc_queue(GFP_KERNEL); if (!disk->queue) @@ -2492,8 +2941,15 @@ static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd) goto out_new_dev; add_disk(disk); + + pkt_sysfs_dev_new(pd); + pkt_debugfs_dev_new(pd); + pkt_devs[idx] = pd; - ctrl_cmd->pkt_dev = new_encode_dev(pd->pkt_dev); + if (pkt_dev) + *pkt_dev = pd->pkt_dev; + + mutex_unlock(&ctl_mutex); return 0; out_new_dev: @@ -2504,17 +2960,22 @@ out_mem: if (pd->rb_pool) mempool_destroy(pd->rb_pool); kfree(pd); +out_mutex: + mutex_unlock(&ctl_mutex); + printk(DRIVER_NAME": setup of pktcdvd device failed\n"); return ret; } /* * Tear down mapping from pktcdvd device to CD-ROM device. */ -static int pkt_remove_dev(struct pkt_ctrl_command *ctrl_cmd) +static int pkt_remove_dev(dev_t pkt_dev) { struct pktcdvd_device *pd; int idx; - dev_t pkt_dev = new_decode_dev(ctrl_cmd->pkt_dev); + int ret = 0; + + mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); for (idx = 0; idx < MAX_WRITERS; idx++) { pd = pkt_devs[idx]; @@ -2523,15 +2984,22 @@ static int pkt_remove_dev(struct pkt_ctrl_command *ctrl_cmd) } if (idx == MAX_WRITERS) { DPRINTK(DRIVER_NAME": dev not setup\n"); - return -ENXIO; + ret = -ENXIO; + goto out; } - if (pd->refcnt > 0) - return -EBUSY; - + if (pd->refcnt > 0) { + ret = -EBUSY; + goto out; + } if (!IS_ERR(pd->cdrw.thread)) kthread_stop(pd->cdrw.thread); + pkt_devs[idx] = NULL; + + pkt_debugfs_dev_remove(pd); + pkt_sysfs_dev_remove(pd); + blkdev_put(pd->bdev); remove_proc_entry(pd->name, pkt_proc); @@ -2541,18 +3009,24 @@ static int pkt_remove_dev(struct pkt_ctrl_command *ctrl_cmd) blk_cleanup_queue(pd->disk->queue); put_disk(pd->disk); - pkt_devs[idx] = NULL; mempool_destroy(pd->rb_pool); kfree(pd); /* This is safe: open() is still holding a reference. */ module_put(THIS_MODULE); - return 0; + +out: + mutex_unlock(&ctl_mutex); + return ret; } static void pkt_get_status(struct pkt_ctrl_command *ctrl_cmd) { - struct pktcdvd_device *pd = pkt_find_dev_from_minor(ctrl_cmd->dev_index); + struct pktcdvd_device *pd; + + mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); + + pd = pkt_find_dev_from_minor(ctrl_cmd->dev_index); if (pd) { ctrl_cmd->dev = new_encode_dev(pd->bdev->bd_dev); ctrl_cmd->pkt_dev = new_encode_dev(pd->pkt_dev); @@ -2561,6 +3035,8 @@ static void pkt_get_status(struct pkt_ctrl_command *ctrl_cmd) ctrl_cmd->pkt_dev = 0; } ctrl_cmd->num_devices = MAX_WRITERS; + + mutex_unlock(&ctl_mutex); } static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) @@ -2568,6 +3044,7 @@ static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cm void __user *argp = (void __user *)arg; struct pkt_ctrl_command ctrl_cmd; int ret = 0; + dev_t pkt_dev = 0; if (cmd != PACKET_CTRL_CMD) return -ENOTTY; @@ -2579,21 +3056,16 @@ static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cm case PKT_CTRL_CMD_SETUP: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); - ret = pkt_setup_dev(&ctrl_cmd); - mutex_unlock(&ctl_mutex); + ret = pkt_setup_dev(new_decode_dev(ctrl_cmd.dev), &pkt_dev); + ctrl_cmd.pkt_dev = new_encode_dev(pkt_dev); break; case PKT_CTRL_CMD_TEARDOWN: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); - ret = pkt_remove_dev(&ctrl_cmd); - mutex_unlock(&ctl_mutex); + ret = pkt_remove_dev(new_decode_dev(ctrl_cmd.pkt_dev)); break; case PKT_CTRL_CMD_STATUS: - mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); pkt_get_status(&ctrl_cmd); - mutex_unlock(&ctl_mutex); break; default: return -ENOTTY; @@ -2620,6 +3092,8 @@ static int __init pkt_init(void) { int ret; + mutex_init(&ctl_mutex); + psd_pool = mempool_create_kmalloc_pool(PSD_POOL_SIZE, sizeof(struct packet_stacked_data)); if (!psd_pool) @@ -2633,18 +3107,25 @@ static int __init pkt_init(void) if (!pktdev_major) pktdev_major = ret; + ret = pkt_sysfs_init(); + if (ret) + goto out; + + pkt_debugfs_init(); + ret = misc_register(&pkt_misc); if (ret) { printk(DRIVER_NAME": Unable to register misc device\n"); - goto out; + goto out_misc; } - mutex_init(&ctl_mutex); - pkt_proc = proc_mkdir(DRIVER_NAME, proc_root_driver); return 0; +out_misc: + pkt_debugfs_cleanup(); + pkt_sysfs_cleanup(); out: unregister_blkdev(pktdev_major, DRIVER_NAME); out2: @@ -2656,6 +3137,10 @@ static void __exit pkt_exit(void) { remove_proc_entry(DRIVER_NAME, proc_root_driver); misc_deregister(&pkt_misc); + + pkt_debugfs_cleanup(); + pkt_sysfs_cleanup(); + unregister_blkdev(pktdev_major, DRIVER_NAME); mempool_destroy(psd_pool); } diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 24f922f1278..b10f4d8fdc7 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -201,6 +201,21 @@ config MOXA_SMARTIO The module will be called mxser. If you want to do that, say M here. +config MOXA_SMARTIO_NEW + tristate "Moxa SmartIO support v. 2.0 (EXPERIMENTAL)" + depends on SERIAL_NONSTANDARD + help + Say Y here if you have a Moxa SmartIO multiport serial card and/or + want to help develop a new version of this driver. + + This is upgraded (1.9.1) driver from original Moxa drivers with + changes finally resulting in PCI probing. + + Use at your own risk. + + This driver can also be built as a module. The module will be called + mxser_new. If you want to do that, say M here. + config ISI tristate "Multi-Tech multiport card support (EXPERIMENTAL)" depends on SERIAL_NONSTANDARD diff --git a/drivers/char/Makefile b/drivers/char/Makefile index b1fcdab9094..fc110637ced 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_MOXA_INTELLIO) += moxa.o obj-$(CONFIG_A2232) += ser_a2232.o generic_serial.o obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o obj-$(CONFIG_MOXA_SMARTIO) += mxser.o +obj-$(CONFIG_MOXA_SMARTIO_NEW) += mxser_new.o obj-$(CONFIG_COMPUTONE) += ip2/ obj-$(CONFIG_RISCOM8) += riscom8.o obj-$(CONFIG_ISI) += isicom.o diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 66086fa2d59..feb4ac802a0 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c @@ -104,7 +104,7 @@ static struct async_struct *IRQ_ports; static unsigned char current_ctl_bits; -static void change_speed(struct async_struct *info, struct termios *old); +static void change_speed(struct async_struct *info, struct ktermios *old); static void rs_wait_until_sent(struct tty_struct *tty, int timeout); @@ -694,7 +694,7 @@ static void shutdown(struct async_struct * info) * the specified baud rate for a serial port. */ static void change_speed(struct async_struct *info, - struct termios *old_termios) + struct ktermios *old_termios) { int quot = 0, baud_base, baud; unsigned cflag, cval = 0; @@ -1365,7 +1365,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, return 0; } -static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct async_struct *info = (struct async_struct *)tty->driver_data; unsigned long flags; diff --git a/drivers/char/cs5535_gpio.c b/drivers/char/cs5535_gpio.c index 8ce3f34cfc2..c02d9e99e05 100644 --- a/drivers/char/cs5535_gpio.c +++ b/drivers/char/cs5535_gpio.c @@ -82,7 +82,7 @@ static inline u32 cs5535_lowhigh_base(int reg) static ssize_t cs5535_gpio_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { - u32 m = iminor(file->f_dentry->d_inode); + u32 m = iminor(file->f_path.dentry->d_inode); int i, j; u32 base = gpio_base + cs5535_lowhigh_base(m); u32 m0, m1; @@ -117,7 +117,7 @@ static ssize_t cs5535_gpio_write(struct file *file, const char __user *data, static ssize_t cs5535_gpio_read(struct file *file, char __user *buf, size_t len, loff_t *ppos) { - u32 m = iminor(file->f_dentry->d_inode); + u32 m = iminor(file->f_path.dentry->d_inode); u32 base = gpio_base + cs5535_lowhigh_base(m); int rd_bit = 1 << (m & 0x0f); int i; diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index acb2de5e3a9..3ffa0807754 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -1,8 +1,6 @@ #undef BLOCKMOVE #define Z_WAKE #undef Z_EXT_CHARS_IN_BUFFER -static char rcsid[] = -"$Revision: 2.3.2.20 $$Date: 2004/02/25 18:14:16 $"; /* * linux/drivers/char/cyclades.c @@ -593,18 +591,20 @@ static char rcsid[] = * */ +#define CY_VERSION "2.4" + /* If you need to install more boards than NR_CARDS, change the constant in the definition below. No other change is necessary to support up to eight boards. Beyond that you'll have to extend cy_isa_addresses. */ -#define NR_CARDS 4 +#define NR_CARDS 4 /* If the total number of ports is larger than NR_PORTS, change this constant in the definition below. No other change is necessary to support more boards/ports. */ -#define NR_PORTS 256 +#define NR_PORTS 256 #define ZE_V1_NPORTS 64 #define ZO_V1 0 @@ -625,9 +625,9 @@ static char rcsid[] = #undef CY_PCI_DEBUG #if 0 -#define PAUSE __asm__("nop"); +#define PAUSE __asm__("nop") #else -#define PAUSE ; +#define PAUSE do {} while (0) #endif /* @@ -663,7 +663,7 @@ static char rcsid[] = do { \ spin_lock_irqsave(&cy_card[info->card].card_lock, flags); \ } while (0) - + #define CY_UNLOCK(info,flags) \ do { \ spin_unlock_irqrestore(&cy_card[info->card].card_lock, flags); \ @@ -676,14 +676,14 @@ static char rcsid[] = #include <linux/stat.h> #include <linux/proc_fs.h> -static void cy_throttle (struct tty_struct *tty); -static void cy_send_xchar (struct tty_struct *tty, char ch); +static void cy_throttle(struct tty_struct *tty); +static void cy_send_xchar(struct tty_struct *tty, char ch); #define IS_CYC_Z(card) ((card).num_chips == -1) #define Z_FPGA_CHECK(card) \ - ((cy_readl(&((struct RUNTIME_9060 __iomem *) \ - ((card).ctl_addr))->init_ctrl) & (1<<17)) != 0) + ((cy_readl(&((struct RUNTIME_9060 __iomem *) \ + ((card).ctl_addr))->init_ctrl) & (1<<17)) != 0) #define ISZLOADED(card) (((ZO_V1==cy_readl(&((struct RUNTIME_9060 __iomem *) \ ((card).ctl_addr))->mail_box_0)) || \ @@ -698,8 +698,6 @@ static void cy_send_xchar (struct tty_struct *tty, char ch); #define STD_COM_FLAGS (0) -#define JIFFIES_DIFF(n, j) ((j) - (n)) - static struct tty_driver *cy_serial_driver; #ifdef CONFIG_ISA @@ -713,27 +711,28 @@ static struct tty_driver *cy_serial_driver; */ static unsigned int cy_isa_addresses[] = { - 0xD0000, - 0xD2000, - 0xD4000, - 0xD6000, - 0xD8000, - 0xDA000, - 0xDC000, - 0xDE000, - 0,0,0,0,0,0,0,0 + 0xD0000, + 0xD2000, + 0xD4000, + 0xD6000, + 0xD8000, + 0xDA000, + 0xDC000, + 0xDE000, + 0, 0, 0, 0, 0, 0, 0, 0 }; + #define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses) #ifdef MODULE static long maddr[NR_CARDS] = { 0, }; -static int irq[NR_CARDS] = { 0, }; +static int irq[NR_CARDS] = { 0, }; module_param_array(maddr, long, NULL, 0); module_param_array(irq, int, NULL, 0); #endif -#endif /* CONFIG_ISA */ +#endif /* CONFIG_ISA */ /* This is the per-card data structure containing address, irq, number of channels, etc. This driver supports a maximum of NR_CARDS cards. @@ -745,7 +744,7 @@ static struct cyclades_card cy_card[NR_CARDS]; */ static struct cyclades_port cy_port[NR_PORTS]; -static int cy_next_channel; /* next minor available */ +static int cy_next_channel; /* next minor available */ /* * This is used to look up the divisor speeds and the timeouts @@ -757,36 +756,42 @@ static int cy_next_channel; /* next minor available */ * 20 */ static int baud_table[] = { - 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, - 1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800,115200,150000, - 230400, 0}; - -static char baud_co_25[] = { /* 25 MHz clock option table */ - /* value => 00 01 02 03 04 */ - /* divide by 8 32 128 512 2048 */ - 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02, - 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - -static char baud_bpr_25[] = { /* 25 MHz baud rate period table */ - 0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3, - 0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15}; - -static char baud_co_60[] = { /* 60 MHz clock option table (CD1400 J) */ - /* value => 00 01 02 03 04 */ - /* divide by 8 32 128 512 2048 */ - 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, - 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00}; - -static char baud_bpr_60[] = { /* 60 MHz baud rate period table (CD1400 J) */ - 0x00, 0x82, 0x21, 0xff, 0xdb, 0xc3, 0x92, 0x62, 0xc3, 0x62, - 0x41, 0xc3, 0x62, 0xc3, 0x62, 0xc3, 0x82, 0x62, 0x41, 0x32, - 0x21}; - -static char baud_cor3[] = { /* receive threshold */ - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07, - 0x07}; + 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, + 1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 150000, + 230400, 0 +}; + +static char baud_co_25[] = { /* 25 MHz clock option table */ + /* value => 00 01 02 03 04 */ + /* divide by 8 32 128 512 2048 */ + 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02, + 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static char baud_bpr_25[] = { /* 25 MHz baud rate period table */ + 0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3, + 0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15 +}; + +static char baud_co_60[] = { /* 60 MHz clock option table (CD1400 J) */ + /* value => 00 01 02 03 04 */ + /* divide by 8 32 128 512 2048 */ + 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, + 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00 +}; + +static char baud_bpr_60[] = { /* 60 MHz baud rate period table (CD1400 J) */ + 0x00, 0x82, 0x21, 0xff, 0xdb, 0xc3, 0x92, 0x62, 0xc3, 0x62, + 0x41, 0xc3, 0x62, 0xc3, 0x62, 0xc3, 0x82, 0x62, 0x41, 0x32, + 0x21 +}; + +static char baud_cor3[] = { /* receive threshold */ + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07, + 0x07 +}; /* * The Cyclades driver implements HW flow control as any serial driver. @@ -799,42 +804,42 @@ static char baud_cor3[] = { /* receive threshold */ * cables. */ -static char rflow_thr[] = { /* rflow threshold */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a}; +static char rflow_thr[] = { /* rflow threshold */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a +}; /* The Cyclom-Ye has placed the sequential chips in non-sequential * address order. This look-up table overcomes that problem. */ -static int cy_chip_offset [] = - { 0x0000, - 0x0400, - 0x0800, - 0x0C00, - 0x0200, - 0x0600, - 0x0A00, - 0x0E00 - }; +static int cy_chip_offset[] = { 0x0000, + 0x0400, + 0x0800, + 0x0C00, + 0x0200, + 0x0600, + 0x0A00, + 0x0E00 +}; /* PCI related definitions */ -static unsigned short cy_pci_nboard; -static unsigned short cy_isa_nboard; -static unsigned short cy_nboard; +static unsigned short cy_pci_nboard; +static unsigned short cy_isa_nboard; +static unsigned short cy_nboard; #ifdef CONFIG_PCI -static unsigned short cy_pci_dev_id[] = { - PCI_DEVICE_ID_CYCLOM_Y_Lo, /* PCI < 1Mb */ - PCI_DEVICE_ID_CYCLOM_Y_Hi, /* PCI > 1Mb */ - PCI_DEVICE_ID_CYCLOM_4Y_Lo, /* 4Y PCI < 1Mb */ - PCI_DEVICE_ID_CYCLOM_4Y_Hi, /* 4Y PCI > 1Mb */ - PCI_DEVICE_ID_CYCLOM_8Y_Lo, /* 8Y PCI < 1Mb */ - PCI_DEVICE_ID_CYCLOM_8Y_Hi, /* 8Y PCI > 1Mb */ - PCI_DEVICE_ID_CYCLOM_Z_Lo, /* Z PCI < 1Mb */ - PCI_DEVICE_ID_CYCLOM_Z_Hi, /* Z PCI > 1Mb */ - 0 /* end of table */ - }; +static unsigned short cy_pci_dev_id[] = { + PCI_DEVICE_ID_CYCLOM_Y_Lo, /* PCI < 1Mb */ + PCI_DEVICE_ID_CYCLOM_Y_Hi, /* PCI > 1Mb */ + PCI_DEVICE_ID_CYCLOM_4Y_Lo, /* 4Y PCI < 1Mb */ + PCI_DEVICE_ID_CYCLOM_4Y_Hi, /* 4Y PCI > 1Mb */ + PCI_DEVICE_ID_CYCLOM_8Y_Lo, /* 8Y PCI < 1Mb */ + PCI_DEVICE_ID_CYCLOM_8Y_Hi, /* 8Y PCI > 1Mb */ + PCI_DEVICE_ID_CYCLOM_Z_Lo, /* Z PCI < 1Mb */ + PCI_DEVICE_ID_CYCLOM_Z_Hi, /* Z PCI > 1Mb */ + 0 /* end of table */ +}; #endif static void cy_start(struct tty_struct *); @@ -842,9 +847,9 @@ static void set_line_char(struct cyclades_port *); static int cyz_issue_cmd(struct cyclades_card *, uclong, ucchar, uclong); #ifdef CONFIG_ISA static unsigned detect_isa_irq(void __iomem *); -#endif /* CONFIG_ISA */ +#endif /* CONFIG_ISA */ -static int cyclades_get_proc_info(char *, char **, off_t , int , int *, void *); +static int cyclades_get_proc_info(char *, char **, off_t, int, int *, void *); #ifndef CONFIG_CYZ_INTR static void cyz_poll(unsigned long); @@ -855,41 +860,36 @@ static long cyz_polling_cycle = CZ_DEF_POLL; static int cyz_timeron = 0; static DEFINE_TIMER(cyz_timerlist, cyz_poll, 0, 0); -#else /* CONFIG_CYZ_INTR */ +#else /* CONFIG_CYZ_INTR */ static void cyz_rx_restart(unsigned long); static struct timer_list cyz_rx_full_timer[NR_PORTS]; -#endif /* CONFIG_CYZ_INTR */ +#endif /* CONFIG_CYZ_INTR */ -static inline int -serial_paranoia_check(struct cyclades_port *info, - char *name, const char *routine) +static inline int serial_paranoia_check(struct cyclades_port *info, + char *name, const char *routine) { #ifdef SERIAL_PARANOIA_CHECK - static const char *badmagic = - "cyc Warning: bad magic number for serial struct (%s) in %s\n"; - static const char *badinfo = - "cyc Warning: null cyclades_port for (%s) in %s\n"; - static const char *badrange = - "cyc Warning: cyclades_port out of range for (%s) in %s\n"; - - if (!info) { - printk(badinfo, name, routine); - return 1; - } - - if( (long)info < (long)(&cy_port[0]) - || (long)(&cy_port[NR_PORTS]) < (long)info ){ - printk(badrange, name, routine); - return 1; - } - - if (info->magic != CYCLADES_MAGIC) { - printk(badmagic, name, routine); - return 1; - } + if (!info) { + printk("cyc Warning: null cyclades_port for (%s) in %s\n", + name, routine); + return 1; + } + + if ((long)info < (long)(&cy_port[0]) || + (long)(&cy_port[NR_PORTS]) < (long)info) { + printk("cyc Warning: cyclades_port out of range for (%s) in " + "%s\n", name, routine); + return 1; + } + + if (info->magic != CYCLADES_MAGIC) { + printk("cyc Warning: bad magic number for serial struct (%s) " + "in %s\n", name, routine); + return 1; + } #endif - return 0; -} /* serial_paranoia_check */ + return 0; +} /* serial_paranoia_check */ /* * This routine is used by the interrupt handler to schedule @@ -897,13 +897,11 @@ serial_paranoia_check(struct cyclades_port *info, * (also known as the "bottom half"). This can be called any * number of times for any channel without harm. */ -static inline void -cy_sched_event(struct cyclades_port *info, int event) +static inline void cy_sched_event(struct cyclades_port *info, int event) { - info->event |= 1 << event; /* remember what kind of event and who */ - schedule_work(&info->tqueue); -} /* cy_sched_event */ - + info->event |= 1 << event; /* remember what kind of event and who */ + schedule_work(&info->tqueue); +} /* cy_sched_event */ /* * This routine is used to handle the "bottom half" processing for the @@ -930,41 +928,36 @@ do_softint(struct work_struct *work) { struct cyclades_port *info = container_of(work, struct cyclades_port, tqueue); - struct tty_struct *tty; - - tty = info->tty; - if (!tty) - return; - - if (test_and_clear_bit(Cy_EVENT_HANGUP, &info->event)) { - tty_hangup(info->tty); - wake_up_interruptible(&info->open_wait); - info->flags &= ~ASYNC_NORMAL_ACTIVE; - } - if (test_and_clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event)) { - wake_up_interruptible(&info->open_wait); - } + struct tty_struct *tty; + + tty = info->tty; + if (!tty) + return; + + if (test_and_clear_bit(Cy_EVENT_HANGUP, &info->event)) { + tty_hangup(info->tty); + wake_up_interruptible(&info->open_wait); + info->flags &= ~ASYNC_NORMAL_ACTIVE; + } + if (test_and_clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event)) + wake_up_interruptible(&info->open_wait); #ifdef CONFIG_CYZ_INTR - if (test_and_clear_bit(Cy_EVENT_Z_RX_FULL, &info->event)) { - if (cyz_rx_full_timer[info->line].function == NULL) { - cyz_rx_full_timer[info->line].expires = jiffies + 1; - cyz_rx_full_timer[info->line].function = cyz_rx_restart; - cyz_rx_full_timer[info->line].data = (unsigned long)info; - add_timer(&cyz_rx_full_timer[info->line]); + if (test_and_clear_bit(Cy_EVENT_Z_RX_FULL, &info->event)) { + if (cyz_rx_full_timer[info->line].function == NULL) { + cyz_rx_full_timer[info->line].expires = jiffies + 1; + cyz_rx_full_timer[info->line].function = cyz_rx_restart; + cyz_rx_full_timer[info->line].data = + (unsigned long)info; + add_timer(&cyz_rx_full_timer[info->line]); + } } - } #endif - if (test_and_clear_bit(Cy_EVENT_DELTA_WAKEUP, &info->event)) { - wake_up_interruptible(&info->delta_msr_wait); - } - if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) { - tty_wakeup(tty); - wake_up_interruptible(&tty->write_wait); - } + if (test_and_clear_bit(Cy_EVENT_DELTA_WAKEUP, &info->event)) + wake_up_interruptible(&info->delta_msr_wait); + tty_wakeup(tty); #ifdef Z_WAKE - if (test_and_clear_bit(Cy_EVENT_SHUTDOWN_WAKEUP, &info->event)) { - wake_up_interruptible(&info->shutdown_wait); - } + if (test_and_clear_bit(Cy_EVENT_SHUTDOWN_WAKEUP, &info->event)) + wake_up_interruptible(&info->shutdown_wait); #endif } /* do_softint */ @@ -979,341 +972,339 @@ do_softint(struct work_struct *work) This function is only called from inside spinlock-protected code. */ -static int -cyy_issue_cmd(void __iomem *base_addr, u_char cmd, int index) +static int cyy_issue_cmd(void __iomem * base_addr, u_char cmd, int index) { - volatile int i; + volatile int i; - /* Check to see that the previous command has completed */ - for(i = 0 ; i < 100 ; i++){ - if (cy_readb(base_addr+(CyCCR<<index)) == 0){ - break; + /* Check to see that the previous command has completed */ + for (i = 0; i < 100; i++) { + if (cy_readb(base_addr + (CyCCR << index)) == 0) { + break; + } + udelay(10L); } - udelay(10L); - } - /* if the CCR never cleared, the previous command - didn't finish within the "reasonable time" */ - if (i == 100) return (-1); + /* if the CCR never cleared, the previous command + didn't finish within the "reasonable time" */ + if (i == 100) + return -1; - /* Issue the new command */ - cy_writeb(base_addr+(CyCCR<<index), cmd); + /* Issue the new command */ + cy_writeb(base_addr + (CyCCR << index), cmd); - return(0); -} /* cyy_issue_cmd */ + return 0; +} /* cyy_issue_cmd */ #ifdef CONFIG_ISA /* ISA interrupt detection code */ -static unsigned -detect_isa_irq(void __iomem *address) +static unsigned detect_isa_irq(void __iomem * address) { - int irq; - unsigned long irqs, flags; - int save_xir, save_car; - int index = 0; /* IRQ probing is only for ISA */ - - /* forget possible initially masked and pending IRQ */ - irq = probe_irq_off(probe_irq_on()); - - /* Clear interrupts on the board first */ - cy_writeb(address + (Cy_ClrIntr<<index), 0); - /* Cy_ClrIntr is 0x1800 */ - - irqs = probe_irq_on(); - /* Wait ... */ - udelay(5000L); - - /* Enable the Tx interrupts on the CD1400 */ - local_irq_save(flags); - cy_writeb(address + (CyCAR<<index), 0); - cyy_issue_cmd(address, CyCHAN_CTL|CyENB_XMTR, index); - - cy_writeb(address + (CyCAR<<index), 0); - cy_writeb(address + (CySRER<<index), - cy_readb(address + (CySRER<<index)) | CyTxRdy); - local_irq_restore(flags); - - /* Wait ... */ - udelay(5000L); - - /* Check which interrupt is in use */ - irq = probe_irq_off(irqs); - - /* Clean up */ - save_xir = (u_char) cy_readb(address + (CyTIR<<index)); - save_car = cy_readb(address + (CyCAR<<index)); - cy_writeb(address + (CyCAR<<index), (save_xir & 0x3)); - cy_writeb(address + (CySRER<<index), - cy_readb(address + (CySRER<<index)) & ~CyTxRdy); - cy_writeb(address + (CyTIR<<index), (save_xir & 0x3f)); - cy_writeb(address + (CyCAR<<index), (save_car)); - cy_writeb(address + (Cy_ClrIntr<<index), 0); - /* Cy_ClrIntr is 0x1800 */ - - return (irq > 0)? irq : 0; + int irq; + unsigned long irqs, flags; + int save_xir, save_car; + int index = 0; /* IRQ probing is only for ISA */ + + /* forget possible initially masked and pending IRQ */ + irq = probe_irq_off(probe_irq_on()); + + /* Clear interrupts on the board first */ + cy_writeb(address + (Cy_ClrIntr << index), 0); + /* Cy_ClrIntr is 0x1800 */ + + irqs = probe_irq_on(); + /* Wait ... */ + udelay(5000L); + + /* Enable the Tx interrupts on the CD1400 */ + local_irq_save(flags); + cy_writeb(address + (CyCAR << index), 0); + cyy_issue_cmd(address, CyCHAN_CTL | CyENB_XMTR, index); + + cy_writeb(address + (CyCAR << index), 0); + cy_writeb(address + (CySRER << index), + cy_readb(address + (CySRER << index)) | CyTxRdy); + local_irq_restore(flags); + + /* Wait ... */ + udelay(5000L); + + /* Check which interrupt is in use */ + irq = probe_irq_off(irqs); + + /* Clean up */ + save_xir = (u_char) cy_readb(address + (CyTIR << index)); + save_car = cy_readb(address + (CyCAR << index)); + cy_writeb(address + (CyCAR << index), (save_xir & 0x3)); + cy_writeb(address + (CySRER << index), + cy_readb(address + (CySRER << index)) & ~CyTxRdy); + cy_writeb(address + (CyTIR << index), (save_xir & 0x3f)); + cy_writeb(address + (CyCAR << index), (save_car)); + cy_writeb(address + (Cy_ClrIntr << index), 0); + /* Cy_ClrIntr is 0x1800 */ + + return (irq > 0) ? irq : 0; } -#endif /* CONFIG_ISA */ +#endif /* CONFIG_ISA */ -/* The real interrupt service routine is called - whenever the card wants its hand held--chars - received, out buffer empty, modem change, etc. - */ -static irqreturn_t -cyy_interrupt(int irq, void *dev_id) +static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, + void __iomem * base_addr, int status, int index) { - struct tty_struct *tty; - int status; - struct cyclades_card *cinfo; - struct cyclades_port *info; - void __iomem *base_addr, *card_base_addr; - int chip; - int save_xir, channel, save_car; - char data; - volatile int char_count; - int outch; - int i,j,index; - int too_many; - int had_work; - int mdm_change; - int mdm_status; - int len; - if((cinfo = (struct cyclades_card *)dev_id) == 0){ -#ifdef CY_DEBUG_INTERRUPTS - printk("cyy_interrupt: spurious interrupt %d\n\r", irq); -#endif - return IRQ_NONE; /* spurious interrupt */ - } - - card_base_addr = cinfo->base_addr; - index = cinfo->bus_index; - - - /* This loop checks all chips in the card. Make a note whenever - _any_ chip had some work to do, as this is considered an - indication that there will be more to do. Only when no chip - has any work does this outermost loop exit. - */ - do{ - had_work = 0; - for ( chip = 0 ; chip < cinfo->num_chips ; chip ++) { - base_addr = cinfo->base_addr + (cy_chip_offset[chip]<<index); - too_many = 0; - while ( (status = cy_readb(base_addr+(CySVRR<<index))) != 0x00) { - had_work++; - /* The purpose of the following test is to ensure that - no chip can monopolize the driver. This forces the - chips to be checked in a round-robin fashion (after - draining each of a bunch (1000) of characters). - */ - if(1000<too_many++){ - break; - } - if (status & CySRReceive) { /* reception interrupt */ + struct cyclades_port *info; + struct tty_struct *tty; + volatile int char_count; + int i, j, len, mdm_change, mdm_status, outch; + int save_xir, channel, save_car; + char data; + + if (status & CySRReceive) { /* reception interrupt */ #ifdef CY_DEBUG_INTERRUPTS - printk("cyy_interrupt: rcvd intr, chip %d\n\r", chip); + printk("cyy_interrupt: rcvd intr, chip %d\n\r", chip); #endif - /* determine the channel & change to that context */ - spin_lock(&cinfo->card_lock); - save_xir = (u_char) cy_readb(base_addr+(CyRIR<<index)); - channel = (u_short ) (save_xir & CyIRChannel); - i = channel + chip * 4 + cinfo->first_line; - info = &cy_port[i]; - info->last_active = jiffies; - save_car = cy_readb(base_addr+(CyCAR<<index)); - cy_writeb(base_addr+(CyCAR<<index), save_xir); - - /* if there is nowhere to put the data, discard it */ - if(info->tty == 0){ - j = (cy_readb(base_addr+(CyRIVR<<index)) & CyIVRMask); - if ( j == CyIVRRxEx ) { /* exception */ - data = cy_readb(base_addr+(CyRDSR<<index)); - } else { /* normal character reception */ - char_count = cy_readb(base_addr+(CyRDCR<<index)); - while(char_count--){ - data = cy_readb(base_addr+(CyRDSR<<index)); - } - } - }else{ /* there is an open port for this data */ - tty = info->tty; - j = (cy_readb(base_addr+(CyRIVR<<index)) & CyIVRMask); - if ( j == CyIVRRxEx ) { /* exception */ - data = cy_readb(base_addr+(CyRDSR<<index)); - - /* For statistics only */ - if (data & CyBREAK) - info->icount.brk++; - else if(data & CyFRAME) - info->icount.frame++; - else if(data & CyPARITY) - info->icount.parity++; - else if(data & CyOVERRUN) - info->icount.overrun++; - - if(data & info->ignore_status_mask){ - info->icount.rx++; - continue; - } - if (tty_buffer_request_room(tty, 1)) { - if (data & info->read_status_mask){ - if(data & CyBREAK){ - tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<<index)), TTY_BREAK); - info->icount.rx++; - if (info->flags & ASYNC_SAK){ - do_SAK(tty); - } - }else if(data & CyFRAME){ - tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<<index)), TTY_FRAME); - info->icount.rx++; - info->idle_stats.frame_errs++; - }else if(data & CyPARITY){ - /* Pieces of seven... */ - tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<<index)), TTY_PARITY); - info->icount.rx++; - info->idle_stats.parity_errs++; - }else if(data & CyOVERRUN){ - tty_insert_flip_char(tty, 0, TTY_OVERRUN); + /* determine the channel & change to that context */ + spin_lock(&cinfo->card_lock); + save_xir = (u_char) cy_readb(base_addr + (CyRIR << index)); + channel = (u_short) (save_xir & CyIRChannel); + i = channel + chip * 4 + cinfo->first_line; + info = &cy_port[i]; + info->last_active = jiffies; + save_car = cy_readb(base_addr + (CyCAR << index)); + cy_writeb(base_addr + (CyCAR << index), save_xir); + + /* if there is nowhere to put the data, discard it */ + if (info->tty == 0) { + j = (cy_readb(base_addr + (CyRIVR << index)) & + CyIVRMask); + if (j == CyIVRRxEx) { /* exception */ + data = cy_readb(base_addr + (CyRDSR << index)); + } else { /* normal character reception */ + char_count = cy_readb(base_addr + + (CyRDCR << index)); + while (char_count--) { + data = cy_readb(base_addr + + (CyRDSR << index)); + } + } + } else { /* there is an open port for this data */ + tty = info->tty; + j = (cy_readb(base_addr + (CyRIVR << index)) & + CyIVRMask); + if (j == CyIVRRxEx) { /* exception */ + data = cy_readb(base_addr + (CyRDSR << index)); + + /* For statistics only */ + if (data & CyBREAK) + info->icount.brk++; + else if (data & CyFRAME) + info->icount.frame++; + else if (data & CyPARITY) + info->icount.parity++; + else if (data & CyOVERRUN) + info->icount.overrun++; + + if (data & info->ignore_status_mask) { info->icount.rx++; - /* If the flip buffer itself is - overflowing, we still lose - the next incoming character. - */ - tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<<index)), TTY_FRAME); - info->icount.rx++; + return; + } + if (tty_buffer_request_room(tty, 1)) { + if (data & info->read_status_mask) { + if (data & CyBREAK) { + tty_insert_flip_char( + tty, + cy_readb( + base_addr + + (CyRDSR << + index)), + TTY_BREAK); + info->icount.rx++; + if (info->flags & + ASYNC_SAK) { + do_SAK(tty); + } + } else if (data & CyFRAME) { + tty_insert_flip_char( + tty, + cy_readb( + base_addr + + (CyRDSR << + index)), + TTY_FRAME); + info->icount.rx++; + info->idle_stats. + frame_errs++; + } else if (data & CyPARITY) { + /* Pieces of seven... */ + tty_insert_flip_char( + tty, + cy_readb( + base_addr + + (CyRDSR << + index)), + TTY_PARITY); + info->icount.rx++; + info->idle_stats. + parity_errs++; + } else if (data & CyOVERRUN) { + tty_insert_flip_char( + tty, 0, + TTY_OVERRUN); + info->icount.rx++; + /* If the flip buffer itself is + overflowing, we still lose + the next incoming character. + */ + tty_insert_flip_char( + tty, + cy_readb( + base_addr + + (CyRDSR << + index)), + TTY_FRAME); + info->icount.rx++; + info->idle_stats. + overruns++; + /* These two conditions may imply */ + /* a normal read should be done. */ + /* }else if(data & CyTIMEOUT){ */ + /* }else if(data & CySPECHAR){ */ + } else { + tty_insert_flip_char( + tty, 0, + TTY_NORMAL); + info->icount.rx++; + } + } else { + tty_insert_flip_char(tty, 0, + TTY_NORMAL); + info->icount.rx++; + } + } else { + /* there was a software buffer + overrun and nothing could be + done about it!!! */ + info->icount.buf_overrun++; info->idle_stats.overruns++; - /* These two conditions may imply */ - /* a normal read should be done. */ - /* }else if(data & CyTIMEOUT){ */ - /* }else if(data & CySPECHAR){ */ - }else { - tty_insert_flip_char(tty, 0, TTY_NORMAL); - info->icount.rx++; - } - }else{ - tty_insert_flip_char(tty, 0, TTY_NORMAL); - info->icount.rx++; - } - }else{ - /* there was a software buffer - overrun and nothing could be - done about it!!! */ - info->icount.buf_overrun++; - info->idle_stats.overruns++; - } - } else { /* normal character reception */ - /* load # chars available from the chip */ - char_count = cy_readb(base_addr+(CyRDCR<<index)); + } + } else { /* normal character reception */ + /* load # chars available from the chip */ + char_count = cy_readb(base_addr + + (CyRDCR << index)); #ifdef CY_ENABLE_MONITORING - ++info->mon.int_count; - info->mon.char_count += char_count; - if (char_count > info->mon.char_max) - info->mon.char_max = char_count; - info->mon.char_last = char_count; + ++info->mon.int_count; + info->mon.char_count += char_count; + if (char_count > info->mon.char_max) + info->mon.char_max = char_count; + info->mon.char_last = char_count; #endif - len = tty_buffer_request_room(tty, char_count); - while(len--){ - data = cy_readb(base_addr+(CyRDSR<<index)); - tty_insert_flip_char(tty, data, TTY_NORMAL); - info->idle_stats.recv_bytes++; - info->icount.rx++; + len = tty_buffer_request_room(tty, char_count); + while (len--) { + data = cy_readb(base_addr + + (CyRDSR << index)); + tty_insert_flip_char(tty, data, + TTY_NORMAL); + info->idle_stats.recv_bytes++; + info->icount.rx++; #ifdef CY_16Y_HACK - udelay(10L); + udelay(10L); #endif - } - info->idle_stats.recv_idle = jiffies; - } + } + info->idle_stats.recv_idle = jiffies; + } tty_schedule_flip(tty); - } - /* end of service */ - cy_writeb(base_addr+(CyRIR<<index), (save_xir & 0x3f)); - cy_writeb(base_addr+(CyCAR<<index), (save_car)); - spin_unlock(&cinfo->card_lock); - } - - - if (status & CySRTransmit) { /* transmission interrupt */ - /* Since we only get here when the transmit buffer - is empty, we know we can always stuff a dozen - characters. */ + } + /* end of service */ + cy_writeb(base_addr + (CyRIR << index), (save_xir & 0x3f)); + cy_writeb(base_addr + (CyCAR << index), (save_car)); + spin_unlock(&cinfo->card_lock); + } + + if (status & CySRTransmit) { /* transmission interrupt */ + /* Since we only get here when the transmit buffer + is empty, we know we can always stuff a dozen + characters. */ #ifdef CY_DEBUG_INTERRUPTS - printk("cyy_interrupt: xmit intr, chip %d\n\r", chip); + printk("cyy_interrupt: xmit intr, chip %d\n\r", chip); #endif - /* determine the channel & change to that context */ - spin_lock(&cinfo->card_lock); - save_xir = (u_char) cy_readb(base_addr+(CyTIR<<index)); - channel = (u_short ) (save_xir & CyIRChannel); - i = channel + chip * 4 + cinfo->first_line; - save_car = cy_readb(base_addr+(CyCAR<<index)); - cy_writeb(base_addr+(CyCAR<<index), save_xir); - - /* validate the port# (as configured and open) */ - if( (i < 0) || (NR_PORTS <= i) ){ - cy_writeb(base_addr+(CySRER<<index), - cy_readb(base_addr+(CySRER<<index)) & ~CyTxRdy); - goto txend; - } - info = &cy_port[i]; - info->last_active = jiffies; - if(info->tty == 0){ - cy_writeb(base_addr+(CySRER<<index), - cy_readb(base_addr+(CySRER<<index)) & ~CyTxRdy); - goto txdone; - } - - /* load the on-chip space for outbound data */ - char_count = info->xmit_fifo_size; - - if(info->x_char) { /* send special char */ - outch = info->x_char; - cy_writeb(base_addr+(CyTDR<<index), outch); - char_count--; + /* determine the channel & change to that context */ + spin_lock(&cinfo->card_lock); + save_xir = (u_char) cy_readb(base_addr + (CyTIR << index)); + channel = (u_short) (save_xir & CyIRChannel); + i = channel + chip * 4 + cinfo->first_line; + save_car = cy_readb(base_addr + (CyCAR << index)); + cy_writeb(base_addr + (CyCAR << index), save_xir); + + /* validate the port# (as configured and open) */ + if ((i < 0) || (NR_PORTS <= i)) { + cy_writeb(base_addr + (CySRER << index), + cy_readb(base_addr + (CySRER << index)) & + ~CyTxRdy); + goto txend; + } + info = &cy_port[i]; + info->last_active = jiffies; + if (info->tty == 0) { + cy_writeb(base_addr + (CySRER << index), + cy_readb(base_addr + (CySRER << index)) & + ~CyTxRdy); + goto txdone; + } + + /* load the on-chip space for outbound data */ + char_count = info->xmit_fifo_size; + + if (info->x_char) { /* send special char */ + outch = info->x_char; + cy_writeb(base_addr + (CyTDR << index), outch); + char_count--; info->icount.tx++; - info->x_char = 0; - } + info->x_char = 0; + } - if (info->breakon || info->breakoff) { + if (info->breakon || info->breakoff) { if (info->breakon) { - cy_writeb(base_addr + (CyTDR<<index), 0); - cy_writeb(base_addr + (CyTDR<<index), 0x81); - info->breakon = 0; - char_count -= 2; + cy_writeb(base_addr + (CyTDR << index), 0); + cy_writeb(base_addr + (CyTDR << index), 0x81); + info->breakon = 0; + char_count -= 2; } if (info->breakoff) { - cy_writeb(base_addr + (CyTDR<<index), 0); - cy_writeb(base_addr + (CyTDR<<index), 0x83); - info->breakoff = 0; - char_count -= 2; + cy_writeb(base_addr + (CyTDR << index), 0); + cy_writeb(base_addr + (CyTDR << index), 0x83); + info->breakoff = 0; + char_count -= 2; } - } - - while (char_count-- > 0){ - if (!info->xmit_cnt){ - if (cy_readb(base_addr+(CySRER<<index))&CyTxMpty) { - cy_writeb(base_addr+(CySRER<<index), - cy_readb(base_addr+(CySRER<<index)) & - ~CyTxMpty); - } else { - cy_writeb(base_addr+(CySRER<<index), - ((cy_readb(base_addr+(CySRER<<index)) - & ~CyTxRdy) - | CyTxMpty)); - } - goto txdone; + } + + while (char_count-- > 0) { + if (!info->xmit_cnt) { + if (cy_readb(base_addr + (CySRER << index)) & + CyTxMpty) { + cy_writeb(base_addr + (CySRER << index), + cy_readb(base_addr + + (CySRER << index)) & + ~CyTxMpty); + } else { + cy_writeb(base_addr + (CySRER << index), + (cy_readb(base_addr + + (CySRER << index)) & + ~CyTxRdy) | CyTxMpty); + } + goto txdone; } - if (info->xmit_buf == 0){ - cy_writeb(base_addr+(CySRER<<index), - cy_readb(base_addr+(CySRER<<index)) & + if (info->xmit_buf == 0) { + cy_writeb(base_addr + (CySRER << index), + cy_readb(base_addr + (CySRER << index))& ~CyTxRdy); - goto txdone; + goto txdone; } - if (info->tty->stopped || info->tty->hw_stopped){ - cy_writeb(base_addr+(CySRER<<index), - cy_readb(base_addr+(CySRER<<index)) & + if (info->tty->stopped || info->tty->hw_stopped) { + cy_writeb(base_addr + (CySRER << index), + cy_readb(base_addr + (CySRER << index))& ~CyTxRdy); - goto txdone; + goto txdone; } - /* Because the Embedded Transmit Commands have - been enabled, we must check to see if the + /* Because the Embedded Transmit Commands have + been enabled, we must check to see if the escape character, NULL, is being sent. If it is, we must ensure that there is room for it to be doubled in the output stream. Therefore @@ -1322,125 +1313,182 @@ cyy_interrupt(int irq, void *dev_id) after the check for a NULL output character. This is necessary because there may not be room for the two chars needed to send a NULL.) - */ - outch = info->xmit_buf[info->xmit_tail]; - if( outch ){ - info->xmit_cnt--; - info->xmit_tail = (info->xmit_tail + 1) - & (SERIAL_XMIT_SIZE - 1); - cy_writeb(base_addr+(CyTDR<<index), outch); - info->icount.tx++; - }else{ - if(char_count > 1){ - info->xmit_cnt--; - info->xmit_tail = (info->xmit_tail + 1) - & (SERIAL_XMIT_SIZE - 1); - cy_writeb(base_addr+(CyTDR<<index), - outch); - cy_writeb(base_addr+(CyTDR<<index), 0); + */ + outch = info->xmit_buf[info->xmit_tail]; + if (outch) { + info->xmit_cnt--; + info->xmit_tail = (info->xmit_tail + 1) & + (SERIAL_XMIT_SIZE - 1); + cy_writeb(base_addr + (CyTDR << index), outch); info->icount.tx++; - char_count--; - }else{ - } - } - } - - txdone: - if (info->xmit_cnt < WAKEUP_CHARS) { - cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP); - } - txend: - /* end of service */ - cy_writeb(base_addr+(CyTIR<<index), - (save_xir & 0x3f)); - cy_writeb(base_addr+(CyCAR<<index), (save_car)); - spin_unlock(&cinfo->card_lock); - } - - if (status & CySRModem) { /* modem interrupt */ - - /* determine the channel & change to that context */ - spin_lock(&cinfo->card_lock); - save_xir = (u_char) cy_readb(base_addr+(CyMIR<<index)); - channel = (u_short ) (save_xir & CyIRChannel); - info = &cy_port[channel + chip * 4 - + cinfo->first_line]; - info->last_active = jiffies; - save_car = cy_readb(base_addr+(CyCAR<<index)); - cy_writeb(base_addr+(CyCAR<<index), save_xir); - - mdm_change = cy_readb(base_addr+(CyMISR<<index)); - mdm_status = cy_readb(base_addr+(CyMSVR1<<index)); - - if(info->tty == 0){/* no place for data, ignore it*/ - ; - }else{ + } else { + if (char_count > 1) { + info->xmit_cnt--; + info->xmit_tail = (info->xmit_tail + 1)& + (SERIAL_XMIT_SIZE - 1); + cy_writeb(base_addr + (CyTDR << index), + outch); + cy_writeb(base_addr + (CyTDR << index), + 0); + info->icount.tx++; + char_count--; + } else { + } + } + } + +txdone: + if (info->xmit_cnt < WAKEUP_CHARS) { + cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP); + } +txend: + /* end of service */ + cy_writeb(base_addr + (CyTIR << index), (save_xir & 0x3f)); + cy_writeb(base_addr + (CyCAR << index), (save_car)); + spin_unlock(&cinfo->card_lock); + } + + if (status & CySRModem) { /* modem interrupt */ + + /* determine the channel & change to that context */ + spin_lock(&cinfo->card_lock); + save_xir = (u_char) cy_readb(base_addr + (CyMIR << index)); + channel = (u_short) (save_xir & CyIRChannel); + info = &cy_port[channel + chip * 4 + cinfo->first_line]; + info->last_active = jiffies; + save_car = cy_readb(base_addr + (CyCAR << index)); + cy_writeb(base_addr + (CyCAR << index), save_xir); + + mdm_change = cy_readb(base_addr + (CyMISR << index)); + mdm_status = cy_readb(base_addr + (CyMSVR1 << index)); + + if (info->tty == 0) { /* no place for data, ignore it */ + ; + } else { if (mdm_change & CyANY_DELTA) { - /* For statistics only */ - if (mdm_change & CyDCD) info->icount.dcd++; - if (mdm_change & CyCTS) info->icount.cts++; - if (mdm_change & CyDSR) info->icount.dsr++; - if (mdm_change & CyRI) info->icount.rng++; + /* For statistics only */ + if (mdm_change & CyDCD) + info->icount.dcd++; + if (mdm_change & CyCTS) + info->icount.cts++; + if (mdm_change & CyDSR) + info->icount.dsr++; + if (mdm_change & CyRI) + info->icount.rng++; + + cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP); + } + + if ((mdm_change & CyDCD) && + (info->flags & ASYNC_CHECK_CD)) { + if (mdm_status & CyDCD) { + cy_sched_event(info, + Cy_EVENT_OPEN_WAKEUP); + } else { + cy_sched_event(info, Cy_EVENT_HANGUP); + } + } + if ((mdm_change & CyCTS) && + (info->flags & ASYNC_CTS_FLOW)) { + if (info->tty->hw_stopped) { + if (mdm_status & CyCTS) { + /* cy_start isn't used + because... !!! */ + info->tty->hw_stopped = 0; + cy_writeb(base_addr + + (CySRER << index), + cy_readb(base_addr + + (CySRER << + index))| + CyTxRdy); + cy_sched_event(info, + Cy_EVENT_WRITE_WAKEUP); + } + } else { + if (!(mdm_status & CyCTS)) { + /* cy_stop isn't used + because ... !!! */ + info->tty->hw_stopped = 1; + cy_writeb(base_addr + + (CySRER << index), + cy_readb(base_addr + + (CySRER << + index)) & + ~CyTxRdy); + } + } + } + if (mdm_change & CyDSR) { + } + if (mdm_change & CyRI) { + } + } + /* end of service */ + cy_writeb(base_addr + (CyMIR << index), (save_xir & 0x3f)); + cy_writeb(base_addr + (CyCAR << index), save_car); + spin_unlock(&cinfo->card_lock); + } +} + +/* The real interrupt service routine is called + whenever the card wants its hand held--chars + received, out buffer empty, modem change, etc. + */ +static irqreturn_t cyy_interrupt(int irq, void *dev_id) +{ + int status; + struct cyclades_card *cinfo; + void __iomem *base_addr, *card_base_addr; + int chip; + int index; + int too_many; + int had_work; + + if ((cinfo = (struct cyclades_card *)dev_id) == 0) { +#ifdef CY_DEBUG_INTERRUPTS + printk("cyy_interrupt: spurious interrupt %d\n\r", irq); +#endif + return IRQ_NONE; /* spurious interrupt */ + } + + card_base_addr = cinfo->base_addr; + index = cinfo->bus_index; - cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP); + /* This loop checks all chips in the card. Make a note whenever + _any_ chip had some work to do, as this is considered an + indication that there will be more to do. Only when no chip + has any work does this outermost loop exit. + */ + do { + had_work = 0; + for (chip = 0; chip < cinfo->num_chips; chip++) { + base_addr = cinfo->base_addr + + (cy_chip_offset[chip] << index); + too_many = 0; + while ((status = cy_readb(base_addr + + (CySVRR << index))) != 0x00) { + had_work++; + /* The purpose of the following test is to ensure that + no chip can monopolize the driver. This forces the + chips to be checked in a round-robin fashion (after + draining each of a bunch (1000) of characters). + */ + if (1000 < too_many++) { + break; + } + cyy_intr_chip(cinfo, chip, base_addr, status, + index); } + } + } while (had_work); - if((mdm_change & CyDCD) - && (info->flags & ASYNC_CHECK_CD)){ - if(mdm_status & CyDCD){ - cy_sched_event(info, - Cy_EVENT_OPEN_WAKEUP); - }else{ - cy_sched_event(info, - Cy_EVENT_HANGUP); - } - } - if((mdm_change & CyCTS) - && (info->flags & ASYNC_CTS_FLOW)){ - if(info->tty->hw_stopped){ - if(mdm_status & CyCTS){ - /* cy_start isn't used - because... !!! */ - info->tty->hw_stopped = 0; - cy_writeb(base_addr+(CySRER<<index), - cy_readb(base_addr+(CySRER<<index)) | - CyTxRdy); - cy_sched_event(info, - Cy_EVENT_WRITE_WAKEUP); - } - }else{ - if(!(mdm_status & CyCTS)){ - /* cy_stop isn't used - because ... !!! */ - info->tty->hw_stopped = 1; - cy_writeb(base_addr+(CySRER<<index), - cy_readb(base_addr+(CySRER<<index)) & - ~CyTxRdy); - } - } - } - if(mdm_change & CyDSR){ - } - if(mdm_change & CyRI){ - } - } - /* end of service */ - cy_writeb(base_addr+(CyMIR<<index), - (save_xir & 0x3f)); - cy_writeb(base_addr+(CyCAR<<index), save_car); - spin_unlock(&cinfo->card_lock); - } - } /* end while status != 0 */ - } /* end loop for chips... */ - } while(had_work); - - /* clear interrupts */ - spin_lock(&cinfo->card_lock); - cy_writeb(card_base_addr + (Cy_ClrIntr<<index), 0); - /* Cy_ClrIntr is 0x1800 */ - spin_unlock(&cinfo->card_lock); - return IRQ_HANDLED; -} /* cyy_interrupt */ + /* clear interrupts */ + spin_lock(&cinfo->card_lock); + cy_writeb(card_base_addr + (Cy_ClrIntr << index), 0); + /* Cy_ClrIntr is 0x1800 */ + spin_unlock(&cinfo->card_lock); + return IRQ_HANDLED; +} /* cyy_interrupt */ /***********************************************************/ /********* End of block of Cyclom-Y specific code **********/ @@ -1448,643 +1496,655 @@ cyy_interrupt(int irq, void *dev_id) /***********************************************************/ static int -cyz_fetch_msg( struct cyclades_card *cinfo, - uclong *channel, ucchar *cmd, uclong *param) +cyz_fetch_msg(struct cyclades_card *cinfo, + uclong * channel, ucchar * cmd, uclong * param) { - struct FIRM_ID __iomem *firm_id; - struct ZFW_CTRL __iomem *zfw_ctrl; - struct BOARD_CTRL __iomem *board_ctrl; - unsigned long loc_doorbell; - - firm_id = cinfo->base_addr + ID_ADDRESS; - if (!ISZLOADED(*cinfo)){ - return (-1); - } - zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); - board_ctrl = &zfw_ctrl->board_ctrl; - - loc_doorbell = cy_readl(&((struct RUNTIME_9060 __iomem *) - (cinfo->ctl_addr))->loc_doorbell); - if (loc_doorbell){ - *cmd = (char)(0xff & loc_doorbell); - *channel = cy_readl(&board_ctrl->fwcmd_channel); - *param = (uclong)cy_readl(&board_ctrl->fwcmd_param); - cy_writel(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->loc_doorbell, - 0xffffffff); - return 1; - } - return 0; -} /* cyz_fetch_msg */ + struct FIRM_ID __iomem *firm_id; + struct ZFW_CTRL __iomem *zfw_ctrl; + struct BOARD_CTRL __iomem *board_ctrl; + unsigned long loc_doorbell; + + firm_id = cinfo->base_addr + ID_ADDRESS; + if (!ISZLOADED(*cinfo)) { + return -1; + } + zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & + 0xfffff); + board_ctrl = &zfw_ctrl->board_ctrl; + + loc_doorbell = cy_readl(&((struct RUNTIME_9060 __iomem *) + (cinfo->ctl_addr))->loc_doorbell); + if (loc_doorbell) { + *cmd = (char)(0xff & loc_doorbell); + *channel = cy_readl(&board_ctrl->fwcmd_channel); + *param = (uclong) cy_readl(&board_ctrl->fwcmd_param); + cy_writel(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))-> + loc_doorbell, 0xffffffff); + return 1; + } + return 0; +} /* cyz_fetch_msg */ static int -cyz_issue_cmd( struct cyclades_card *cinfo, - uclong channel, ucchar cmd, uclong param) +cyz_issue_cmd(struct cyclades_card *cinfo, + uclong channel, ucchar cmd, uclong param) { - struct FIRM_ID __iomem *firm_id; - struct ZFW_CTRL __iomem *zfw_ctrl; - struct BOARD_CTRL __iomem *board_ctrl; - unsigned long __iomem *pci_doorbell; - int index; - - firm_id = cinfo->base_addr + ID_ADDRESS; - if (!ISZLOADED(*cinfo)){ - return (-1); - } - zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); - board_ctrl = &zfw_ctrl->board_ctrl; - - index = 0; - pci_doorbell = &((struct RUNTIME_9060 __iomem *) (cinfo->ctl_addr))->pci_doorbell; - while( (cy_readl(pci_doorbell) & 0xff) != 0){ - if (index++ == 1000){ - return((int)(cy_readl(pci_doorbell) & 0xff)); - } - udelay(50L); - } - cy_writel(&board_ctrl->hcmd_channel, channel); - cy_writel(&board_ctrl->hcmd_param , param); - cy_writel(pci_doorbell, (long)cmd); - - return(0); -} /* cyz_issue_cmd */ + struct FIRM_ID __iomem *firm_id; + struct ZFW_CTRL __iomem *zfw_ctrl; + struct BOARD_CTRL __iomem *board_ctrl; + unsigned long __iomem *pci_doorbell; + int index; + + firm_id = cinfo->base_addr + ID_ADDRESS; + if (!ISZLOADED(*cinfo)) { + return -1; + } + zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & + 0xfffff); + board_ctrl = &zfw_ctrl->board_ctrl; + + index = 0; + pci_doorbell = + &((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->pci_doorbell; + while ((cy_readl(pci_doorbell) & 0xff) != 0) { + if (index++ == 1000) { + return (int)(cy_readl(pci_doorbell) & 0xff); + } + udelay(50L); + } + cy_writel(&board_ctrl->hcmd_channel, channel); + cy_writel(&board_ctrl->hcmd_param, param); + cy_writel(pci_doorbell, (long)cmd); + + return 0; +} /* cyz_issue_cmd */ static void cyz_handle_rx(struct cyclades_port *info, - volatile struct CH_CTRL __iomem *ch_ctrl, - volatile struct BUF_CTRL __iomem *buf_ctrl) + volatile struct CH_CTRL __iomem * ch_ctrl, + volatile struct BUF_CTRL __iomem * buf_ctrl) { - struct cyclades_card *cinfo = &cy_card[info->card]; - struct tty_struct *tty = info->tty; - volatile int char_count; - int len; + struct cyclades_card *cinfo = &cy_card[info->card]; + struct tty_struct *tty = info->tty; + volatile int char_count; + int len; #ifdef BLOCKMOVE - int small_count; + int small_count; #else - char data; + char data; #endif - volatile uclong rx_put, rx_get, new_rx_get, rx_bufsize, rx_bufaddr; + volatile uclong rx_put, rx_get, new_rx_get, rx_bufsize, rx_bufaddr; - rx_get = new_rx_get = cy_readl(&buf_ctrl->rx_get); - rx_put = cy_readl(&buf_ctrl->rx_put); - rx_bufsize = cy_readl(&buf_ctrl->rx_bufsize); - rx_bufaddr = cy_readl(&buf_ctrl->rx_bufaddr); - if (rx_put >= rx_get) - char_count = rx_put - rx_get; - else - char_count = rx_put - rx_get + rx_bufsize; + rx_get = new_rx_get = cy_readl(&buf_ctrl->rx_get); + rx_put = cy_readl(&buf_ctrl->rx_put); + rx_bufsize = cy_readl(&buf_ctrl->rx_bufsize); + rx_bufaddr = cy_readl(&buf_ctrl->rx_bufaddr); + if (rx_put >= rx_get) + char_count = rx_put - rx_get; + else + char_count = rx_put - rx_get + rx_bufsize; - if ( char_count ) { - info->last_active = jiffies; - info->jiffies[1] = jiffies; + if (char_count) { + info->last_active = jiffies; + info->jiffies[1] = jiffies; #ifdef CY_ENABLE_MONITORING - info->mon.int_count++; - info->mon.char_count += char_count; - if (char_count > info->mon.char_max) - info->mon.char_max = char_count; - info->mon.char_last = char_count; + info->mon.int_count++; + info->mon.char_count += char_count; + if (char_count > info->mon.char_max) + info->mon.char_max = char_count; + info->mon.char_last = char_count; #endif - if(tty == 0){ - /* flush received characters */ - new_rx_get = (new_rx_get + char_count) & (rx_bufsize - 1); - info->rflush_count++; - }else{ + if (tty == 0) { + /* flush received characters */ + new_rx_get = (new_rx_get + char_count) & + (rx_bufsize - 1); + info->rflush_count++; + } else { #ifdef BLOCKMOVE - /* we'd like to use memcpy(t, f, n) and memset(s, c, count) - for performance, but because of buffer boundaries, there - may be several steps to the operation */ - while(0 < (small_count = - min_t(unsigned int, (rx_bufsize - new_rx_get), - min_t(unsigned int, (TTY_FLIPBUF_SIZE - tty->flip.count), char_count)) - )) { - memcpy_fromio(tty->flip.char_buf_ptr, - (char *)(cinfo->base_addr - + rx_bufaddr + new_rx_get), - small_count); - - tty->flip.char_buf_ptr += small_count; - memset(tty->flip.flag_buf_ptr, TTY_NORMAL, small_count); - tty->flip.flag_buf_ptr += small_count; - new_rx_get = (new_rx_get + small_count) & (rx_bufsize - 1); - char_count -= small_count; - info->icount.rx += small_count; - info->idle_stats.recv_bytes += small_count; - tty->flip.count += small_count; - } + /* we'd like to use memcpy(t, f, n) and memset(s, c, count) + for performance, but because of buffer boundaries, there + may be several steps to the operation */ + while (0 < (small_count = min_t(unsigned int, + rx_bufsize - new_rx_get, + min_t(unsigned int, TTY_FLIPBUF_SIZE - + tty->flip.count, char_count)))){ + memcpy_fromio(tty->flip.char_buf_ptr, + (char *)(cinfo->base_addr + rx_bufaddr + + new_rx_get), + small_count); + + tty->flip.char_buf_ptr += small_count; + memset(tty->flip.flag_buf_ptr, TTY_NORMAL, + small_count); + tty->flip.flag_buf_ptr += small_count; + new_rx_get = (new_rx_get + small_count) & + (rx_bufsize - 1); + char_count -= small_count; + info->icount.rx += small_count; + info->idle_stats.recv_bytes += small_count; + tty->flip.count += small_count; + } #else - len = tty_buffer_request_room(tty, char_count); - while(len--){ - data = cy_readb(cinfo->base_addr + rx_bufaddr + new_rx_get); - new_rx_get = (new_rx_get + 1) & (rx_bufsize - 1); - tty_insert_flip_char(tty, data, TTY_NORMAL); - info->idle_stats.recv_bytes++; - info->icount.rx++; - } + len = tty_buffer_request_room(tty, char_count); + while (len--) { + data = cy_readb(cinfo->base_addr + rx_bufaddr + + new_rx_get); + new_rx_get = (new_rx_get + 1)& (rx_bufsize - 1); + tty_insert_flip_char(tty, data, TTY_NORMAL); + info->idle_stats.recv_bytes++; + info->icount.rx++; + } #endif #ifdef CONFIG_CYZ_INTR - /* Recalculate the number of chars in the RX buffer and issue - a cmd in case it's higher than the RX high water mark */ - rx_put = cy_readl(&buf_ctrl->rx_put); - if (rx_put >= rx_get) - char_count = rx_put - rx_get; - else - char_count = rx_put - rx_get + rx_bufsize; - if(char_count >= cy_readl(&buf_ctrl->rx_threshold)) { - cy_sched_event(info, Cy_EVENT_Z_RX_FULL); - } + /* Recalculate the number of chars in the RX buffer and issue + a cmd in case it's higher than the RX high water mark */ + rx_put = cy_readl(&buf_ctrl->rx_put); + if (rx_put >= rx_get) + char_count = rx_put - rx_get; + else + char_count = rx_put - rx_get + rx_bufsize; + if (char_count >= (int)cy_readl(&buf_ctrl-> + rx_threshold)) { + cy_sched_event(info, Cy_EVENT_Z_RX_FULL); + } #endif - info->idle_stats.recv_idle = jiffies; - tty_schedule_flip(tty); + info->idle_stats.recv_idle = jiffies; + tty_schedule_flip(tty); + } + /* Update rx_get */ + cy_writel(&buf_ctrl->rx_get, new_rx_get); } - /* Update rx_get */ - cy_writel(&buf_ctrl->rx_get, new_rx_get); - } } static void cyz_handle_tx(struct cyclades_port *info, - volatile struct CH_CTRL __iomem *ch_ctrl, - volatile struct BUF_CTRL __iomem *buf_ctrl) + volatile struct CH_CTRL __iomem * ch_ctrl, + volatile struct BUF_CTRL __iomem * buf_ctrl) { - struct cyclades_card *cinfo = &cy_card[info->card]; - struct tty_struct *tty = info->tty; - char data; - volatile int char_count; + struct cyclades_card *cinfo = &cy_card[info->card]; + struct tty_struct *tty = info->tty; + char data; + volatile int char_count; #ifdef BLOCKMOVE - int small_count; + int small_count; #endif - volatile uclong tx_put, tx_get, tx_bufsize, tx_bufaddr; + volatile uclong tx_put, tx_get, tx_bufsize, tx_bufaddr; - if (info->xmit_cnt <= 0) /* Nothing to transmit */ - return; + if (info->xmit_cnt <= 0) /* Nothing to transmit */ + return; - tx_get = cy_readl(&buf_ctrl->tx_get); - tx_put = cy_readl(&buf_ctrl->tx_put); - tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize); - tx_bufaddr = cy_readl(&buf_ctrl->tx_bufaddr); - if (tx_put >= tx_get) - char_count = tx_get - tx_put - 1 + tx_bufsize; - else - char_count = tx_get - tx_put - 1; + tx_get = cy_readl(&buf_ctrl->tx_get); + tx_put = cy_readl(&buf_ctrl->tx_put); + tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize); + tx_bufaddr = cy_readl(&buf_ctrl->tx_bufaddr); + if (tx_put >= tx_get) + char_count = tx_get - tx_put - 1 + tx_bufsize; + else + char_count = tx_get - tx_put - 1; - if ( char_count ) { + if (char_count) { - if( tty == 0 ){ - goto ztxdone; - } + if (tty == 0) { + goto ztxdone; + } - if(info->x_char) { /* send special char */ - data = info->x_char; + if (info->x_char) { /* send special char */ + data = info->x_char; - cy_writeb((cinfo->base_addr + tx_bufaddr + tx_put), data); - tx_put = (tx_put + 1) & (tx_bufsize - 1); - info->x_char = 0; - char_count--; - info->icount.tx++; - info->last_active = jiffies; - info->jiffies[2] = jiffies; - } + cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data); + tx_put = (tx_put + 1) & (tx_bufsize - 1); + info->x_char = 0; + char_count--; + info->icount.tx++; + info->last_active = jiffies; + info->jiffies[2] = jiffies; + } #ifdef BLOCKMOVE - while(0 < (small_count = - min_t(unsigned int, (tx_bufsize - tx_put), - min_t(unsigned int, (SERIAL_XMIT_SIZE - info->xmit_tail), - min_t(unsigned int, info->xmit_cnt, char_count))))) { - - memcpy_toio((char *)(cinfo->base_addr + tx_bufaddr + tx_put), - &info->xmit_buf[info->xmit_tail], - small_count); - - tx_put = (tx_put + small_count) & (tx_bufsize - 1); - char_count -= small_count; - info->icount.tx += small_count; - info->xmit_cnt -= small_count; - info->xmit_tail = - (info->xmit_tail + small_count) & (SERIAL_XMIT_SIZE - 1); - info->last_active = jiffies; - info->jiffies[2] = jiffies; - } + while (0 < (small_count = min_t(unsigned int, + tx_bufsize - tx_put, min_t(unsigned int, + (SERIAL_XMIT_SIZE - info->xmit_tail), + min_t(unsigned int, info->xmit_cnt, + char_count))))) { + + memcpy_toio((char *)(cinfo->base_addr + tx_bufaddr + + tx_put), + &info->xmit_buf[info->xmit_tail], + small_count); + + tx_put = (tx_put + small_count) & (tx_bufsize - 1); + char_count -= small_count; + info->icount.tx += small_count; + info->xmit_cnt -= small_count; + info->xmit_tail = (info->xmit_tail + small_count) & + (SERIAL_XMIT_SIZE - 1); + info->last_active = jiffies; + info->jiffies[2] = jiffies; + } #else - while (info->xmit_cnt && char_count){ - data = info->xmit_buf[info->xmit_tail]; - info->xmit_cnt--; - info->xmit_tail = (info->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1); - - cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data); - tx_put = (tx_put + 1) & (tx_bufsize - 1); - char_count--; - info->icount.tx++; - info->last_active = jiffies; - info->jiffies[2] = jiffies; - } + while (info->xmit_cnt && char_count) { + data = info->xmit_buf[info->xmit_tail]; + info->xmit_cnt--; + info->xmit_tail = (info->xmit_tail + 1) & + (SERIAL_XMIT_SIZE - 1); + + cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data); + tx_put = (tx_put + 1) & (tx_bufsize - 1); + char_count--; + info->icount.tx++; + info->last_active = jiffies; + info->jiffies[2] = jiffies; + } #endif - ztxdone: - if (info->xmit_cnt < WAKEUP_CHARS) { - cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP); +ztxdone: + if (info->xmit_cnt < WAKEUP_CHARS) { + cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP); + } + /* Update tx_put */ + cy_writel(&buf_ctrl->tx_put, tx_put); } - /* Update tx_put */ - cy_writel(&buf_ctrl->tx_put, tx_put); - } } -static void -cyz_handle_cmd(struct cyclades_card *cinfo) +static void cyz_handle_cmd(struct cyclades_card *cinfo) { - struct tty_struct *tty; - struct cyclades_port *info; - static volatile struct FIRM_ID __iomem *firm_id; - static volatile struct ZFW_CTRL __iomem *zfw_ctrl; - static volatile struct BOARD_CTRL __iomem *board_ctrl; - static volatile struct CH_CTRL __iomem *ch_ctrl; - static volatile struct BUF_CTRL __iomem *buf_ctrl; - uclong channel; - ucchar cmd; - uclong param; - uclong hw_ver, fw_ver; - int special_count; - int delta_count; - - firm_id = cinfo->base_addr + ID_ADDRESS; - zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); - board_ctrl = &zfw_ctrl->board_ctrl; - fw_ver = cy_readl(&board_ctrl->fw_version); - hw_ver = cy_readl(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->mail_box_0); - - - while(cyz_fetch_msg(cinfo, &channel, &cmd, ¶m) == 1) { - special_count = 0; - delta_count = 0; - info = &cy_port[channel + cinfo->first_line]; - if((tty = info->tty) == 0) { - continue; - } - ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); - buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]); - - switch(cmd) { - case C_CM_PR_ERROR: - tty_insert_flip_char(tty, 0, TTY_PARITY); - info->icount.rx++; - special_count++; - break; - case C_CM_FR_ERROR: - tty_insert_flip_char(tty, 0, TTY_FRAME); - info->icount.rx++; - special_count++; - break; - case C_CM_RXBRK: - tty_insert_flip_char(tty, 0, TTY_BREAK); - info->icount.rx++; - special_count++; - break; - case C_CM_MDCD: - info->icount.dcd++; - delta_count++; - if (info->flags & ASYNC_CHECK_CD){ - if ((fw_ver > 241 ? - ((u_long)param) : - cy_readl(&ch_ctrl->rs_status)) & C_RS_DCD) { - cy_sched_event(info, Cy_EVENT_OPEN_WAKEUP); - }else{ - cy_sched_event(info, Cy_EVENT_HANGUP); - } + struct tty_struct *tty; + struct cyclades_port *info; + static volatile struct FIRM_ID __iomem *firm_id; + static volatile struct ZFW_CTRL __iomem *zfw_ctrl; + static volatile struct BOARD_CTRL __iomem *board_ctrl; + static volatile struct CH_CTRL __iomem *ch_ctrl; + static volatile struct BUF_CTRL __iomem *buf_ctrl; + uclong channel; + ucchar cmd; + uclong param; + uclong hw_ver, fw_ver; + int special_count; + int delta_count; + + firm_id = cinfo->base_addr + ID_ADDRESS; + zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & + 0xfffff); + board_ctrl = &zfw_ctrl->board_ctrl; + fw_ver = cy_readl(&board_ctrl->fw_version); + hw_ver = cy_readl(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))-> + mail_box_0); + + while (cyz_fetch_msg(cinfo, &channel, &cmd, ¶m) == 1) { + special_count = 0; + delta_count = 0; + info = &cy_port[channel + cinfo->first_line]; + if ((tty = info->tty) == 0) { + continue; } - break; - case C_CM_MCTS: - info->icount.cts++; - delta_count++; - break; - case C_CM_MRI: - info->icount.rng++; - delta_count++; - break; - case C_CM_MDSR: - info->icount.dsr++; - delta_count++; - break; + ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); + buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]); + + switch (cmd) { + case C_CM_PR_ERROR: + tty_insert_flip_char(tty, 0, TTY_PARITY); + info->icount.rx++; + special_count++; + break; + case C_CM_FR_ERROR: + tty_insert_flip_char(tty, 0, TTY_FRAME); + info->icount.rx++; + special_count++; + break; + case C_CM_RXBRK: + tty_insert_flip_char(tty, 0, TTY_BREAK); + info->icount.rx++; + special_count++; + break; + case C_CM_MDCD: + info->icount.dcd++; + delta_count++; + if (info->flags & ASYNC_CHECK_CD) { + if ((fw_ver > 241 ? ((u_long) param) : + cy_readl(&ch_ctrl->rs_status)) & + C_RS_DCD) { + cy_sched_event(info, + Cy_EVENT_OPEN_WAKEUP); + } else { + cy_sched_event(info, Cy_EVENT_HANGUP); + } + } + break; + case C_CM_MCTS: + info->icount.cts++; + delta_count++; + break; + case C_CM_MRI: + info->icount.rng++; + delta_count++; + break; + case C_CM_MDSR: + info->icount.dsr++; + delta_count++; + break; #ifdef Z_WAKE - case C_CM_IOCTLW: - cy_sched_event(info, Cy_EVENT_SHUTDOWN_WAKEUP); - break; + case C_CM_IOCTLW: + cy_sched_event(info, Cy_EVENT_SHUTDOWN_WAKEUP); + break; #endif #ifdef CONFIG_CYZ_INTR - case C_CM_RXHIWM: - case C_CM_RXNNDT: - case C_CM_INTBACK2: - /* Reception Interrupt */ + case C_CM_RXHIWM: + case C_CM_RXNNDT: + case C_CM_INTBACK2: + /* Reception Interrupt */ #ifdef CY_DEBUG_INTERRUPTS - printk("cyz_interrupt: rcvd intr, card %d, port %ld\n\r", - info->card, channel); + printk("cyz_interrupt: rcvd intr, card %d, " + "port %ld\n\r", info->card, channel); #endif - cyz_handle_rx(info, ch_ctrl, buf_ctrl); - break; - case C_CM_TXBEMPTY: - case C_CM_TXLOWWM: - case C_CM_INTBACK: - /* Transmission Interrupt */ + cyz_handle_rx(info, ch_ctrl, buf_ctrl); + break; + case C_CM_TXBEMPTY: + case C_CM_TXLOWWM: + case C_CM_INTBACK: + /* Transmission Interrupt */ #ifdef CY_DEBUG_INTERRUPTS - printk("cyz_interrupt: xmit intr, card %d, port %ld\n\r", - info->card, channel); + printk("cyz_interrupt: xmit intr, card %d, " + "port %ld\n\r", info->card, channel); #endif - cyz_handle_tx(info, ch_ctrl, buf_ctrl); - break; -#endif /* CONFIG_CYZ_INTR */ - case C_CM_FATAL: - /* should do something with this !!! */ - break; - default: - break; + cyz_handle_tx(info, ch_ctrl, buf_ctrl); + break; +#endif /* CONFIG_CYZ_INTR */ + case C_CM_FATAL: + /* should do something with this !!! */ + break; + default: + break; + } + if (delta_count) + cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP); + if (special_count) + tty_schedule_flip(tty); } - if(delta_count) - cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP); - if(special_count) - tty_schedule_flip(tty); - } } #ifdef CONFIG_CYZ_INTR -static irqreturn_t -cyz_interrupt(int irq, void *dev_id) +static irqreturn_t cyz_interrupt(int irq, void *dev_id) { - struct cyclades_card *cinfo; + struct cyclades_card *cinfo; - if((cinfo = (struct cyclades_card *)dev_id) == 0){ + if ((cinfo = (struct cyclades_card *)dev_id) == 0) { #ifdef CY_DEBUG_INTERRUPTS - printk("cyz_interrupt: spurious interrupt %d\n\r", irq); + printk("cyz_interrupt: spurious interrupt %d\n\r", irq); #endif - return IRQ_NONE; /* spurious interrupt */ - } + return IRQ_NONE; /* spurious interrupt */ + } - if (!ISZLOADED(*cinfo)) { + if (!ISZLOADED(*cinfo)) { #ifdef CY_DEBUG_INTERRUPTS - printk("cyz_interrupt: board not yet loaded (IRQ%d).\n\r", irq); + printk("cyz_interrupt: board not yet loaded (IRQ%d).\n\r", irq); #endif - return IRQ_NONE; - } + return IRQ_NONE; + } - /* Handle the interrupts */ - cyz_handle_cmd(cinfo); + /* Handle the interrupts */ + cyz_handle_cmd(cinfo); - return IRQ_HANDLED; -} /* cyz_interrupt */ + return IRQ_HANDLED; +} /* cyz_interrupt */ -static void -cyz_rx_restart(unsigned long arg) +static void cyz_rx_restart(unsigned long arg) { - struct cyclades_port *info = (struct cyclades_port *)arg; - int retval; - int card = info->card; - uclong channel = (info->line) - (cy_card[card].first_line); - unsigned long flags; - - CY_LOCK(info, flags); - retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK2, 0L); - if (retval != 0){ - printk("cyc:cyz_rx_restart retval on ttyC%d was %x\n", - info->line, retval); - } - cyz_rx_full_timer[info->line].function = NULL; - CY_UNLOCK(info, flags); + struct cyclades_port *info = (struct cyclades_port *)arg; + int retval; + int card = info->card; + uclong channel = (info->line) - (cy_card[card].first_line); + unsigned long flags; + + CY_LOCK(info, flags); + retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK2, 0L); + if (retval != 0) { + printk("cyc:cyz_rx_restart retval on ttyC%d was %x\n", + info->line, retval); + } + cyz_rx_full_timer[info->line].function = NULL; + CY_UNLOCK(info, flags); } -#else /* CONFIG_CYZ_INTR */ +#else /* CONFIG_CYZ_INTR */ -static void -cyz_poll(unsigned long arg) +static void cyz_poll(unsigned long arg) { - struct cyclades_card *cinfo; - struct cyclades_port *info; - struct tty_struct *tty; - static volatile struct FIRM_ID *firm_id; - static volatile struct ZFW_CTRL *zfw_ctrl; - static volatile struct BOARD_CTRL *board_ctrl; - static volatile struct CH_CTRL *ch_ctrl; - static volatile struct BUF_CTRL *buf_ctrl; - int card, port; - - cyz_timerlist.expires = jiffies + (HZ); - for (card = 0 ; card < NR_CARDS ; card++){ - cinfo = &cy_card[card]; - - if (!IS_CYC_Z(*cinfo)) continue; - if (!ISZLOADED(*cinfo)) continue; + struct cyclades_card *cinfo; + struct cyclades_port *info; + struct tty_struct *tty; + static volatile struct FIRM_ID *firm_id; + static volatile struct ZFW_CTRL *zfw_ctrl; + static volatile struct BOARD_CTRL *board_ctrl; + static volatile struct CH_CTRL *ch_ctrl; + static volatile struct BUF_CTRL *buf_ctrl; + int card, port; - firm_id = cinfo->base_addr + ID_ADDRESS; - zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); - board_ctrl = &(zfw_ctrl->board_ctrl); + cyz_timerlist.expires = jiffies + (HZ); + for (card = 0; card < NR_CARDS; card++) { + cinfo = &cy_card[card]; + + if (!IS_CYC_Z(*cinfo)) + continue; + if (!ISZLOADED(*cinfo)) + continue; + + firm_id = cinfo->base_addr + ID_ADDRESS; + zfw_ctrl = cinfo->base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); + board_ctrl = &(zfw_ctrl->board_ctrl); /* Skip first polling cycle to avoid racing conditions with the FW */ - if (!cinfo->intr_enabled) { - cinfo->nports = (int) cy_readl(&board_ctrl->n_channel); - cinfo->intr_enabled = 1; - continue; - } + if (!cinfo->intr_enabled) { + cinfo->nports = (int)cy_readl(&board_ctrl->n_channel); + cinfo->intr_enabled = 1; + continue; + } - cyz_handle_cmd(cinfo); + cyz_handle_cmd(cinfo); - for (port = 0 ; port < cinfo->nports ; port++) { - info = &cy_port[ port + cinfo->first_line ]; - tty = info->tty; - ch_ctrl = &(zfw_ctrl->ch_ctrl[port]); - buf_ctrl = &(zfw_ctrl->buf_ctrl[port]); + for (port = 0; port < cinfo->nports; port++) { + info = &cy_port[port + cinfo->first_line]; + tty = info->tty; + ch_ctrl = &(zfw_ctrl->ch_ctrl[port]); + buf_ctrl = &(zfw_ctrl->buf_ctrl[port]); - if (!info->throttle) - cyz_handle_rx(info, ch_ctrl, buf_ctrl); - cyz_handle_tx(info, ch_ctrl, buf_ctrl); + if (!info->throttle) + cyz_handle_rx(info, ch_ctrl, buf_ctrl); + cyz_handle_tx(info, ch_ctrl, buf_ctrl); + } + /* poll every 'cyz_polling_cycle' period */ + cyz_timerlist.expires = jiffies + cyz_polling_cycle; } - /* poll every 'cyz_polling_cycle' period */ - cyz_timerlist.expires = jiffies + cyz_polling_cycle; - } - add_timer(&cyz_timerlist); + add_timer(&cyz_timerlist); +} /* cyz_poll */ - return; -} /* cyz_poll */ - -#endif /* CONFIG_CYZ_INTR */ +#endif /* CONFIG_CYZ_INTR */ /********** End of block of Cyclades-Z specific code *********/ /***********************************************************/ - /* This is called whenever a port becomes active; interrupts are enabled and DTR & RTS are turned on. */ -static int -startup(struct cyclades_port * info) +static int startup(struct cyclades_port *info) { - unsigned long flags; - int retval = 0; - void __iomem *base_addr; - int card,chip,channel,index; - unsigned long page; + unsigned long flags; + int retval = 0; + void __iomem *base_addr; + int card, chip, channel, index; + unsigned long page; - card = info->card; - channel = (info->line) - (cy_card[card].first_line); + card = info->card; + channel = (info->line) - (cy_card[card].first_line); - page = get_zeroed_page(GFP_KERNEL); - if (!page) - return -ENOMEM; + page = get_zeroed_page(GFP_KERNEL); + if (!page) + return -ENOMEM; - CY_LOCK(info, flags); + CY_LOCK(info, flags); - if (info->flags & ASYNC_INITIALIZED){ - free_page(page); - goto errout; - } + if (info->flags & ASYNC_INITIALIZED) { + free_page(page); + goto errout; + } - if (!info->type){ - if (info->tty){ - set_bit(TTY_IO_ERROR, &info->tty->flags); - } - free_page(page); - goto errout; - } + if (!info->type) { + if (info->tty) { + set_bit(TTY_IO_ERROR, &info->tty->flags); + } + free_page(page); + goto errout; + } - if (info->xmit_buf) - free_page(page); - else - info->xmit_buf = (unsigned char *) page; + if (info->xmit_buf) + free_page(page); + else + info->xmit_buf = (unsigned char *)page; - CY_UNLOCK(info, flags); + CY_UNLOCK(info, flags); - set_line_char(info); + set_line_char(info); - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index); + if (!IS_CYC_Z(cy_card[card])) { + chip = channel >> 2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = cy_card[card].base_addr + + (cy_chip_offset[chip] << index); #ifdef CY_DEBUG_OPEN - printk("cyc startup card %d, chip %d, channel %d, base_addr %lx\n", - card, chip, channel, (long)base_addr);/**/ + printk("cyc startup card %d, chip %d, channel %d, " + "base_addr %lx\n", + card, chip, channel, (long)base_addr); + /**/ #endif + CY_LOCK(info, flags); - CY_LOCK(info, flags); - - cy_writeb(base_addr+(CyCAR<<index), (u_char)channel); + cy_writeb(base_addr + (CyCAR << index), (u_char) channel); - cy_writeb(base_addr+(CyRTPR<<index), (info->default_timeout - ? info->default_timeout : 0x02)); /* 10ms rx timeout */ + cy_writeb(base_addr + (CyRTPR << index), + (info->default_timeout ? info->default_timeout : 0x02)); + /* 10ms rx timeout */ - cyy_issue_cmd(base_addr,CyCHAN_CTL|CyENB_RCVR|CyENB_XMTR,index); + cyy_issue_cmd(base_addr, CyCHAN_CTL | CyENB_RCVR | CyENB_XMTR, + index); - cy_writeb(base_addr+(CyCAR<<index), (u_char)channel); - cy_writeb(base_addr+(CyMSVR1<<index), CyRTS); - cy_writeb(base_addr+(CyMSVR2<<index), CyDTR); + cy_writeb(base_addr + (CyCAR << index), (u_char) channel); + cy_writeb(base_addr + (CyMSVR1 << index), CyRTS); + cy_writeb(base_addr + (CyMSVR2 << index), CyDTR); #ifdef CY_DEBUG_DTR - printk("cyc:startup raising DTR\n"); - printk(" status: 0x%x, 0x%x\n", - cy_readb(base_addr+(CyMSVR1<<index)), - cy_readb(base_addr+(CyMSVR2<<index))); + printk("cyc:startup raising DTR\n"); + printk(" status: 0x%x, 0x%x\n", + cy_readb(base_addr + (CyMSVR1 << index)), + cy_readb(base_addr + (CyMSVR2 << index))); #endif - cy_writeb(base_addr+(CySRER<<index), - cy_readb(base_addr+(CySRER<<index)) | CyRxData); - info->flags |= ASYNC_INITIALIZED; + cy_writeb(base_addr + (CySRER << index), + cy_readb(base_addr + (CySRER << index)) | CyRxData); + info->flags |= ASYNC_INITIALIZED; - if (info->tty){ - clear_bit(TTY_IO_ERROR, &info->tty->flags); - } - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - info->breakon = info->breakoff = 0; - memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats)); - info->idle_stats.in_use = - info->idle_stats.recv_idle = - info->idle_stats.xmit_idle = jiffies; + if (info->tty) { + clear_bit(TTY_IO_ERROR, &info->tty->flags); + } + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + info->breakon = info->breakoff = 0; + memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats)); + info->idle_stats.in_use = + info->idle_stats.recv_idle = + info->idle_stats.xmit_idle = jiffies; - CY_UNLOCK(info, flags); + CY_UNLOCK(info, flags); - } else { - struct FIRM_ID __iomem *firm_id; - struct ZFW_CTRL __iomem *zfw_ctrl; - struct BOARD_CTRL __iomem *board_ctrl; - struct CH_CTRL __iomem *ch_ctrl; - int retval; + } else { + struct FIRM_ID __iomem *firm_id; + struct ZFW_CTRL __iomem *zfw_ctrl; + struct BOARD_CTRL __iomem *board_ctrl; + struct CH_CTRL __iomem *ch_ctrl; + int retval; - base_addr = cy_card[card].base_addr; + base_addr = cy_card[card].base_addr; - firm_id = base_addr + ID_ADDRESS; - if (!ISZLOADED(cy_card[card])){ - return -ENODEV; - } + firm_id = base_addr + ID_ADDRESS; + if (!ISZLOADED(cy_card[card])) { + return -ENODEV; + } - zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); - board_ctrl = &zfw_ctrl->board_ctrl; - ch_ctrl = zfw_ctrl->ch_ctrl; + zfw_ctrl = cy_card[card].base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); + board_ctrl = &zfw_ctrl->board_ctrl; + ch_ctrl = zfw_ctrl->ch_ctrl; #ifdef CY_DEBUG_OPEN - printk("cyc startup Z card %d, channel %d, base_addr %lx\n", - card, channel, (long)base_addr);/**/ + printk("cyc startup Z card %d, channel %d, base_addr %lx\n", + card, channel, (long)base_addr); + /**/ #endif + CY_LOCK(info, flags); - CY_LOCK(info, flags); - - cy_writel(&ch_ctrl[channel].op_mode, C_CH_ENABLE); + cy_writel(&ch_ctrl[channel].op_mode, C_CH_ENABLE); #ifdef Z_WAKE #ifdef CONFIG_CYZ_INTR - cy_writel(&ch_ctrl[channel].intr_enable, - C_IN_TXBEMPTY|C_IN_TXLOWWM|C_IN_RXHIWM|C_IN_RXNNDT| - C_IN_IOCTLW| - C_IN_MDCD); + cy_writel(&ch_ctrl[channel].intr_enable, + C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM | + C_IN_RXNNDT | C_IN_IOCTLW | C_IN_MDCD); #else - cy_writel(&ch_ctrl[channel].intr_enable, - C_IN_IOCTLW| - C_IN_MDCD); -#endif /* CONFIG_CYZ_INTR */ + cy_writel(&ch_ctrl[channel].intr_enable, + C_IN_IOCTLW | C_IN_MDCD); +#endif /* CONFIG_CYZ_INTR */ #else #ifdef CONFIG_CYZ_INTR - cy_writel(&ch_ctrl[channel].intr_enable, - C_IN_TXBEMPTY|C_IN_TXLOWWM|C_IN_RXHIWM|C_IN_RXNNDT| - C_IN_MDCD); + cy_writel(&ch_ctrl[channel].intr_enable, + C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM | + C_IN_RXNNDT | C_IN_MDCD); #else - cy_writel(&ch_ctrl[channel].intr_enable, - C_IN_MDCD); -#endif /* CONFIG_CYZ_INTR */ -#endif /* Z_WAKE */ - - retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTL, 0L); - if (retval != 0){ - printk("cyc:startup(1) retval on ttyC%d was %x\n", - info->line, retval); - } + cy_writel(&ch_ctrl[channel].intr_enable, C_IN_MDCD); +#endif /* CONFIG_CYZ_INTR */ +#endif /* Z_WAKE */ + + retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTL, 0L); + if (retval != 0) { + printk("cyc:startup(1) retval on ttyC%d was %x\n", + info->line, retval); + } - /* Flush RX buffers before raising DTR and RTS */ - retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_RX, 0L); - if (retval != 0){ - printk("cyc:startup(2) retval on ttyC%d was %x\n", - info->line, retval); - } + /* Flush RX buffers before raising DTR and RTS */ + retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_RX, + 0L); + if (retval != 0) { + printk("cyc:startup(2) retval on ttyC%d was %x\n", + info->line, retval); + } - /* set timeout !!! */ - /* set RTS and DTR !!! */ - cy_writel(&ch_ctrl[channel].rs_control, - cy_readl(&ch_ctrl[channel].rs_control) | C_RS_RTS | C_RS_DTR) ; - retval = cyz_issue_cmd(&cy_card[info->card], - channel, C_CM_IOCTLM, 0L); - if (retval != 0){ - printk("cyc:startup(3) retval on ttyC%d was %x\n", - info->line, retval); - } + /* set timeout !!! */ + /* set RTS and DTR !!! */ + cy_writel(&ch_ctrl[channel].rs_control, + cy_readl(&ch_ctrl[channel].rs_control) | C_RS_RTS | + C_RS_DTR); + retval = cyz_issue_cmd(&cy_card[info->card], channel, + C_CM_IOCTLM, 0L); + if (retval != 0) { + printk("cyc:startup(3) retval on ttyC%d was %x\n", + info->line, retval); + } #ifdef CY_DEBUG_DTR - printk("cyc:startup raising Z DTR\n"); + printk("cyc:startup raising Z DTR\n"); #endif - /* enable send, recv, modem !!! */ + /* enable send, recv, modem !!! */ - info->flags |= ASYNC_INITIALIZED; - if (info->tty){ - clear_bit(TTY_IO_ERROR, &info->tty->flags); - } - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - info->breakon = info->breakoff = 0; - memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats)); - info->idle_stats.in_use = - info->idle_stats.recv_idle = - info->idle_stats.xmit_idle = jiffies; + info->flags |= ASYNC_INITIALIZED; + if (info->tty) { + clear_bit(TTY_IO_ERROR, &info->tty->flags); + } + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + info->breakon = info->breakoff = 0; + memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats)); + info->idle_stats.in_use = + info->idle_stats.recv_idle = + info->idle_stats.xmit_idle = jiffies; - CY_UNLOCK(info, flags); - } + CY_UNLOCK(info, flags); + } #ifdef CY_DEBUG_OPEN printk(" cyc startup done\n"); @@ -2094,165 +2154,165 @@ startup(struct cyclades_port * info) errout: CY_UNLOCK(info, flags); return retval; -} /* startup */ - +} /* startup */ -static void -start_xmit( struct cyclades_port *info ) +static void start_xmit(struct cyclades_port *info) { - unsigned long flags; - void __iomem *base_addr; - int card,chip,channel,index; - - card = info->card; - channel = (info->line) - (cy_card[card].first_line); - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index); + unsigned long flags; + void __iomem *base_addr; + int card, chip, channel, index; - CY_LOCK(info, flags); - cy_writeb(base_addr+(CyCAR<<index), channel); - cy_writeb(base_addr+(CySRER<<index), - cy_readb(base_addr+(CySRER<<index)) | CyTxRdy); - CY_UNLOCK(info, flags); - } else { + card = info->card; + channel = (info->line) - (cy_card[card].first_line); + if (!IS_CYC_Z(cy_card[card])) { + chip = channel >> 2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = cy_card[card].base_addr + + (cy_chip_offset[chip] << index); + + CY_LOCK(info, flags); + cy_writeb(base_addr + (CyCAR << index), channel); + cy_writeb(base_addr + (CySRER << index), + cy_readb(base_addr + (CySRER << index)) | CyTxRdy); + CY_UNLOCK(info, flags); + } else { #ifdef CONFIG_CYZ_INTR - int retval; + int retval; - CY_LOCK(info, flags); - retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK, 0L); - if (retval != 0){ - printk("cyc:start_xmit retval on ttyC%d was %x\n", - info->line, retval); - } - CY_UNLOCK(info, flags); -#else /* CONFIG_CYZ_INTR */ - /* Don't have to do anything at this time */ -#endif /* CONFIG_CYZ_INTR */ - } -} /* start_xmit */ + CY_LOCK(info, flags); + retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK, + 0L); + if (retval != 0) { + printk("cyc:start_xmit retval on ttyC%d was %x\n", + info->line, retval); + } + CY_UNLOCK(info, flags); +#else /* CONFIG_CYZ_INTR */ + /* Don't have to do anything at this time */ +#endif /* CONFIG_CYZ_INTR */ + } +} /* start_xmit */ /* * This routine shuts down a serial port; interrupts are disabled, * and DTR is dropped if the hangup on close termio flag is on. */ -static void -shutdown(struct cyclades_port * info) +static void shutdown(struct cyclades_port *info) { - unsigned long flags; - void __iomem *base_addr; - int card,chip,channel,index; - - if (!(info->flags & ASYNC_INITIALIZED)){ - return; - } - - card = info->card; - channel = info->line - cy_card[card].first_line; - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index); + unsigned long flags; + void __iomem *base_addr; + int card, chip, channel, index; + + if (!(info->flags & ASYNC_INITIALIZED)) { + return; + } + + card = info->card; + channel = info->line - cy_card[card].first_line; + if (!IS_CYC_Z(cy_card[card])) { + chip = channel >> 2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = cy_card[card].base_addr + + (cy_chip_offset[chip] << index); #ifdef CY_DEBUG_OPEN - printk("cyc shutdown Y card %d, chip %d, channel %d, base_addr %lx\n", - card, chip, channel, (long)base_addr); + printk("cyc shutdown Y card %d, chip %d, channel %d, " + "base_addr %lx\n", + card, chip, channel, (long)base_addr); #endif - CY_LOCK(info, flags); + CY_LOCK(info, flags); - /* Clear delta_msr_wait queue to avoid mem leaks. */ - wake_up_interruptible(&info->delta_msr_wait); - - if (info->xmit_buf){ - unsigned char * temp; - temp = info->xmit_buf; - info->xmit_buf = NULL; - free_page((unsigned long) temp); - } - cy_writeb(base_addr+(CyCAR<<index), (u_char)channel); - if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { - cy_writeb(base_addr+(CyMSVR1<<index), ~CyRTS); - cy_writeb(base_addr+(CyMSVR2<<index), ~CyDTR); + /* Clear delta_msr_wait queue to avoid mem leaks. */ + wake_up_interruptible(&info->delta_msr_wait); + + if (info->xmit_buf) { + unsigned char *temp; + temp = info->xmit_buf; + info->xmit_buf = NULL; + free_page((unsigned long)temp); + } + cy_writeb(base_addr + (CyCAR << index), (u_char) channel); + if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { + cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS); + cy_writeb(base_addr + (CyMSVR2 << index), ~CyDTR); #ifdef CY_DEBUG_DTR - printk("cyc shutdown dropping DTR\n"); - printk(" status: 0x%x, 0x%x\n", - cy_readb(base_addr+(CyMSVR1<<index)), - cy_readb(base_addr+(CyMSVR2<<index))); + printk("cyc shutdown dropping DTR\n"); + printk(" status: 0x%x, 0x%x\n", + cy_readb(base_addr + (CyMSVR1 << index)), + cy_readb(base_addr + (CyMSVR2 << index))); #endif - } - cyy_issue_cmd(base_addr,CyCHAN_CTL|CyDIS_RCVR,index); - /* it may be appropriate to clear _XMIT at - some later date (after testing)!!! */ - - if (info->tty){ - set_bit(TTY_IO_ERROR, &info->tty->flags); - } - info->flags &= ~ASYNC_INITIALIZED; - CY_UNLOCK(info, flags); - } else { - struct FIRM_ID __iomem *firm_id; - struct ZFW_CTRL __iomem *zfw_ctrl; - struct BOARD_CTRL __iomem *board_ctrl; - struct CH_CTRL __iomem *ch_ctrl; - int retval; - - base_addr = cy_card[card].base_addr; + } + cyy_issue_cmd(base_addr, CyCHAN_CTL | CyDIS_RCVR, index); + /* it may be appropriate to clear _XMIT at + some later date (after testing)!!! */ + + if (info->tty) { + set_bit(TTY_IO_ERROR, &info->tty->flags); + } + info->flags &= ~ASYNC_INITIALIZED; + CY_UNLOCK(info, flags); + } else { + struct FIRM_ID __iomem *firm_id; + struct ZFW_CTRL __iomem *zfw_ctrl; + struct BOARD_CTRL __iomem *board_ctrl; + struct CH_CTRL __iomem *ch_ctrl; + int retval; + + base_addr = cy_card[card].base_addr; #ifdef CY_DEBUG_OPEN - printk("cyc shutdown Z card %d, channel %d, base_addr %lx\n", - card, channel, (long)base_addr); + printk("cyc shutdown Z card %d, channel %d, base_addr %lx\n", + card, channel, (long)base_addr); #endif - firm_id = base_addr + ID_ADDRESS; - if (!ISZLOADED(cy_card[card])) { - return; - } + firm_id = base_addr + ID_ADDRESS; + if (!ISZLOADED(cy_card[card])) { + return; + } - zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); - board_ctrl = &zfw_ctrl->board_ctrl; - ch_ctrl = zfw_ctrl->ch_ctrl; + zfw_ctrl = cy_card[card].base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); + board_ctrl = &zfw_ctrl->board_ctrl; + ch_ctrl = zfw_ctrl->ch_ctrl; - CY_LOCK(info, flags); + CY_LOCK(info, flags); - if (info->xmit_buf){ - unsigned char * temp; - temp = info->xmit_buf; - info->xmit_buf = NULL; - free_page((unsigned long) temp); - } - - if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { - cy_writel(&ch_ctrl[channel].rs_control, - (uclong)(cy_readl(&ch_ctrl[channel].rs_control) & - ~(C_RS_RTS | C_RS_DTR))); - retval = cyz_issue_cmd(&cy_card[info->card], - channel, C_CM_IOCTLM, 0L); - if (retval != 0){ - printk("cyc:shutdown retval on ttyC%d was %x\n", - info->line, retval); + if (info->xmit_buf) { + unsigned char *temp; + temp = info->xmit_buf; + info->xmit_buf = NULL; + free_page((unsigned long)temp); } + + if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { + cy_writel(&ch_ctrl[channel].rs_control, + (uclong)(cy_readl(&ch_ctrl[channel].rs_control)& + ~(C_RS_RTS | C_RS_DTR))); + retval = cyz_issue_cmd(&cy_card[info->card], channel, + C_CM_IOCTLM, 0L); + if (retval != 0) { + printk("cyc:shutdown retval on ttyC%d was %x\n", + info->line, retval); + } #ifdef CY_DEBUG_DTR - printk("cyc:shutdown dropping Z DTR\n"); + printk("cyc:shutdown dropping Z DTR\n"); #endif - } - - if (info->tty){ - set_bit(TTY_IO_ERROR, &info->tty->flags); - } - info->flags &= ~ASYNC_INITIALIZED; + } - CY_UNLOCK(info, flags); - } + if (info->tty) { + set_bit(TTY_IO_ERROR, &info->tty->flags); + } + info->flags &= ~ASYNC_INITIALIZED; + + CY_UNLOCK(info, flags); + } #ifdef CY_DEBUG_OPEN - printk(" cyc shutdown done\n"); + printk(" cyc shutdown done\n"); #endif - return; -} /* shutdown */ - +} /* shutdown */ /* * ------------------------------------------------------------ @@ -2261,527 +2321,546 @@ shutdown(struct cyclades_port * info) */ static int -block_til_ready(struct tty_struct *tty, struct file * filp, - struct cyclades_port *info) +block_til_ready(struct tty_struct *tty, struct file *filp, + struct cyclades_port *info) { - DECLARE_WAITQUEUE(wait, current); - struct cyclades_card *cinfo; - unsigned long flags; - int chip, channel,index; - int retval; - void __iomem *base_addr; - - cinfo = &cy_card[info->card]; - channel = info->line - cinfo->first_line; - - /* - * If the device is in the middle of being closed, then block - * until it's done, and then try again. - */ - if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) { - interruptible_sleep_on(&info->close_wait); + DECLARE_WAITQUEUE(wait, current); + struct cyclades_card *cinfo; + unsigned long flags; + int chip, channel, index; + int retval; + void __iomem *base_addr; + + cinfo = &cy_card[info->card]; + channel = info->line - cinfo->first_line; + + /* + * If the device is in the middle of being closed, then block + * until it's done, and then try again. + */ + if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { + if (info->flags & ASYNC_CLOSING) { + interruptible_sleep_on(&info->close_wait); + } + return (info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; + } + + /* + * If non-blocking mode is set, then make the check up front + * and then exit. + */ + if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) { + info->flags |= ASYNC_NORMAL_ACTIVE; + return 0; } - return ((info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); - } - - /* - * If non-blocking mode is set, then make the check up front - * and then exit. - */ - if ((filp->f_flags & O_NONBLOCK) || - (tty->flags & (1 << TTY_IO_ERROR))) { - info->flags |= ASYNC_NORMAL_ACTIVE; - return 0; - } - - /* - * Block waiting for the carrier detect and the line to become - * free (i.e., not in use by the callout). While we are in - * this loop, info->count is dropped by one, so that - * cy_close() knows when to free things. We restore it upon - * exit, either normal or abnormal. - */ - retval = 0; - add_wait_queue(&info->open_wait, &wait); + + /* + * Block waiting for the carrier detect and the line to become + * free (i.e., not in use by the callout). While we are in + * this loop, info->count is dropped by one, so that + * cy_close() knows when to free things. We restore it upon + * exit, either normal or abnormal. + */ + retval = 0; + add_wait_queue(&info->open_wait, &wait); #ifdef CY_DEBUG_OPEN - printk("cyc block_til_ready before block: ttyC%d, count = %d\n", - info->line, info->count);/**/ + printk("cyc block_til_ready before block: ttyC%d, count = %d\n", + info->line, info->count); + /**/ #endif - CY_LOCK(info, flags); - if (!tty_hung_up_p(filp)) - info->count--; - CY_UNLOCK(info, flags); + CY_LOCK(info, flags); + if (!tty_hung_up_p(filp)) + info->count--; + CY_UNLOCK(info, flags); #ifdef CY_DEBUG_COUNT - printk("cyc block_til_ready: (%d): decrementing count to %d\n", - current->pid, info->count); + printk("cyc block_til_ready: (%d): decrementing count to %d\n", + current->pid, info->count); #endif - info->blocked_open++; - - if (!IS_CYC_Z(*cinfo)) { - chip = channel>>2; - channel &= 0x03; - index = cinfo->bus_index; - base_addr = cinfo->base_addr + (cy_chip_offset[chip]<<index); - - while (1) { - CY_LOCK(info, flags); - if ((tty->termios->c_cflag & CBAUD)){ - cy_writeb(base_addr+(CyCAR<<index), (u_char)channel); - cy_writeb(base_addr+(CyMSVR1<<index), CyRTS); - cy_writeb(base_addr+(CyMSVR2<<index), CyDTR); + info->blocked_open++; + + if (!IS_CYC_Z(*cinfo)) { + chip = channel >> 2; + channel &= 0x03; + index = cinfo->bus_index; + base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index); + + while (1) { + CY_LOCK(info, flags); + if ((tty->termios->c_cflag & CBAUD)) { + cy_writeb(base_addr + (CyCAR << index), + (u_char) channel); + cy_writeb(base_addr + (CyMSVR1 << index), + CyRTS); + cy_writeb(base_addr + (CyMSVR2 << index), + CyDTR); #ifdef CY_DEBUG_DTR - printk("cyc:block_til_ready raising DTR\n"); - printk(" status: 0x%x, 0x%x\n", - cy_readb(base_addr+(CyMSVR1<<index)), - cy_readb(base_addr+(CyMSVR2<<index))); + printk("cyc:block_til_ready raising DTR\n"); + printk(" status: 0x%x, 0x%x\n", + cy_readb(base_addr + + (CyMSVR1 << index)), + cy_readb(base_addr + + (CyMSVR2 << index))); #endif - } - CY_UNLOCK(info, flags); + } + CY_UNLOCK(info, flags); - set_current_state(TASK_INTERRUPTIBLE); - if (tty_hung_up_p(filp) - || !(info->flags & ASYNC_INITIALIZED) ){ - retval = ((info->flags & ASYNC_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS); - break; - } + set_current_state(TASK_INTERRUPTIBLE); + if (tty_hung_up_p(filp) || + !(info->flags & ASYNC_INITIALIZED)) { + retval = ((info->flags & ASYNC_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS); + break; + } - CY_LOCK(info, flags); - cy_writeb(base_addr+(CyCAR<<index), (u_char)channel); - if (!(info->flags & ASYNC_CLOSING) - && (C_CLOCAL(tty) - || (cy_readb(base_addr+(CyMSVR1<<index)) & CyDCD))) { + CY_LOCK(info, flags); + cy_writeb(base_addr + (CyCAR << index), + (u_char) channel); + if (!(info->flags & ASYNC_CLOSING) && (C_CLOCAL(tty) || + (cy_readb(base_addr + + (CyMSVR1 << index)) & CyDCD))) { + CY_UNLOCK(info, flags); + break; + } CY_UNLOCK(info, flags); - break; - } - CY_UNLOCK(info, flags); - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } #ifdef CY_DEBUG_OPEN - printk("cyc block_til_ready blocking: ttyC%d, count = %d\n", - info->line, info->count);/**/ + printk("cyc block_til_ready blocking: ttyC%d, " + "count = %d\n", + info->line, info->count); + /**/ #endif - schedule(); - } - } else { - struct FIRM_ID __iomem *firm_id; - struct ZFW_CTRL __iomem *zfw_ctrl; - struct BOARD_CTRL __iomem *board_ctrl; - struct CH_CTRL __iomem *ch_ctrl; - int retval; - - base_addr = cinfo->base_addr; - firm_id = base_addr + ID_ADDRESS; - if (!ISZLOADED(*cinfo)){ - current->state = TASK_RUNNING; - remove_wait_queue(&info->open_wait, &wait); - return -EINVAL; - } - - zfw_ctrl = base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); - board_ctrl = &zfw_ctrl->board_ctrl; - ch_ctrl = zfw_ctrl->ch_ctrl; - - while (1) { - if ((tty->termios->c_cflag & CBAUD)){ - cy_writel(&ch_ctrl[channel].rs_control, - cy_readl(&ch_ctrl[channel].rs_control) | - (C_RS_RTS | C_RS_DTR)); - retval = cyz_issue_cmd(&cy_card[info->card], - channel, C_CM_IOCTLM, 0L); - if (retval != 0){ - printk("cyc:block_til_ready retval on ttyC%d was %x\n", - info->line, retval); + schedule(); + } + } else { + struct FIRM_ID __iomem *firm_id; + struct ZFW_CTRL __iomem *zfw_ctrl; + struct BOARD_CTRL __iomem *board_ctrl; + struct CH_CTRL __iomem *ch_ctrl; + int retval; + + base_addr = cinfo->base_addr; + firm_id = base_addr + ID_ADDRESS; + if (!ISZLOADED(*cinfo)) { + current->state = TASK_RUNNING; + remove_wait_queue(&info->open_wait, &wait); + return -EINVAL; } + + zfw_ctrl = base_addr + (cy_readl(&firm_id->zfwctrl_addr) & + 0xfffff); + board_ctrl = &zfw_ctrl->board_ctrl; + ch_ctrl = zfw_ctrl->ch_ctrl; + + while (1) { + if ((tty->termios->c_cflag & CBAUD)) { + cy_writel(&ch_ctrl[channel].rs_control, + cy_readl(&ch_ctrl[channel]. + rs_control) | (C_RS_RTS | + C_RS_DTR)); + retval = cyz_issue_cmd(&cy_card[info->card], + channel, C_CM_IOCTLM, 0L); + if (retval != 0) { + printk("cyc:block_til_ready retval on " + "ttyC%d was %x\n", + info->line, retval); + } #ifdef CY_DEBUG_DTR - printk("cyc:block_til_ready raising Z DTR\n"); + printk("cyc:block_til_ready raising Z DTR\n"); #endif - } + } - set_current_state(TASK_INTERRUPTIBLE); - if (tty_hung_up_p(filp) - || !(info->flags & ASYNC_INITIALIZED) ){ - retval = ((info->flags & ASYNC_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS); - break; - } - if (!(info->flags & ASYNC_CLOSING) - && (C_CLOCAL(tty) - || (cy_readl(&ch_ctrl[channel].rs_status) & C_RS_DCD))) { - break; - } - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } + set_current_state(TASK_INTERRUPTIBLE); + if (tty_hung_up_p(filp) || + !(info->flags & ASYNC_INITIALIZED)) { + retval = ((info->flags & ASYNC_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS); + break; + } + if (!(info->flags & ASYNC_CLOSING) && (C_CLOCAL(tty) || + (cy_readl(&ch_ctrl[channel].rs_status) & + C_RS_DCD))) { + break; + } + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } #ifdef CY_DEBUG_OPEN - printk("cyc block_til_ready blocking: ttyC%d, count = %d\n", - info->line, info->count);/**/ + printk("cyc block_til_ready blocking: ttyC%d, " + "count = %d\n", + info->line, info->count); + /**/ #endif - schedule(); + schedule(); + } } - } - current->state = TASK_RUNNING; - remove_wait_queue(&info->open_wait, &wait); - if (!tty_hung_up_p(filp)){ - info->count++; + current->state = TASK_RUNNING; + remove_wait_queue(&info->open_wait, &wait); + if (!tty_hung_up_p(filp)) { + info->count++; #ifdef CY_DEBUG_COUNT - printk("cyc:block_til_ready (%d): incrementing count to %d\n", - current->pid, info->count); + printk("cyc:block_til_ready (%d): incrementing count to %d\n", + current->pid, info->count); #endif - } - info->blocked_open--; + } + info->blocked_open--; #ifdef CY_DEBUG_OPEN - printk("cyc:block_til_ready after blocking: ttyC%d, count = %d\n", - info->line, info->count);/**/ + printk("cyc:block_til_ready after blocking: ttyC%d, count = %d\n", + info->line, info->count); + /**/ #endif - if (retval) - return retval; - info->flags |= ASYNC_NORMAL_ACTIVE; - return 0; -} /* block_til_ready */ - + if (retval) + return retval; + info->flags |= ASYNC_NORMAL_ACTIVE; + return 0; +} /* block_til_ready */ /* * This routine is called whenever a serial port is opened. It * performs the serial-specific initialization for the tty structure. */ -static int -cy_open(struct tty_struct *tty, struct file * filp) +static int cy_open(struct tty_struct *tty, struct file *filp) { - struct cyclades_port *info; - int retval, line; - - line = tty->index; - if ((line < 0) || (NR_PORTS <= line)){ - return -ENODEV; - } - info = &cy_port[line]; - if (info->line < 0){ - return -ENODEV; - } - - /* If the card's firmware hasn't been loaded, - treat it as absent from the system. This - will make the user pay attention. - */ - if (IS_CYC_Z(cy_card[info->card])) { - struct cyclades_card *cinfo = &cy_card[info->card]; - struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS; - - if (!ISZLOADED(*cinfo)) { - if (((ZE_V1 ==cy_readl(&((struct RUNTIME_9060 __iomem *) - (cinfo->ctl_addr))->mail_box_0)) && - Z_FPGA_CHECK (*cinfo)) && - (ZFIRM_HLT == cy_readl (&firm_id->signature))) - { - printk ("cyc:Cyclades-Z Error: you need an external power supply for this number of ports.\n\rFirmware halted.\r\n"); - } else { - printk("cyc:Cyclades-Z firmware not yet loaded\n"); - } - return -ENODEV; - } -#ifdef CONFIG_CYZ_INTR - else { - /* In case this Z board is operating in interrupt mode, its - interrupts should be enabled as soon as the first open happens - to one of its ports. */ - if (!cinfo->intr_enabled) { - struct ZFW_CTRL __iomem *zfw_ctrl; - struct BOARD_CTRL __iomem *board_ctrl; - - zfw_ctrl = cinfo->base_addr + (cy_readl (&firm_id->zfwctrl_addr) & 0xfffff); + struct cyclades_port *info; + int retval, line; - board_ctrl = &zfw_ctrl->board_ctrl; + line = tty->index; + if ((line < 0) || (NR_PORTS <= line)) { + return -ENODEV; + } + info = &cy_port[line]; + if (info->line < 0) { + return -ENODEV; + } - /* Enable interrupts on the PLX chip */ - cy_writew(cinfo->ctl_addr+0x68, - cy_readw(cinfo->ctl_addr+0x68)|0x0900); - /* Enable interrupts on the FW */ - retval = cyz_issue_cmd(cinfo, - 0, C_CM_IRQ_ENBL, 0L); - if (retval != 0){ - printk("cyc:IRQ enable retval was %x\n", retval); + /* If the card's firmware hasn't been loaded, + treat it as absent from the system. This + will make the user pay attention. + */ + if (IS_CYC_Z(cy_card[info->card])) { + struct cyclades_card *cinfo = &cy_card[info->card]; + struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS; + + if (!ISZLOADED(*cinfo)) { + if (((ZE_V1 == cy_readl( + &((struct RUNTIME_9060 __iomem *) + (cinfo->ctl_addr))->mail_box_0)) && + Z_FPGA_CHECK(*cinfo)) && + (ZFIRM_HLT == cy_readl( + &firm_id->signature))) { + printk("cyc:Cyclades-Z Error: you need an " + "external power supply for this number " + "of ports.\n\rFirmware halted.\r\n"); + } else { + printk("cyc:Cyclades-Z firmware not yet " + "loaded\n"); + } + return -ENODEV; } - cinfo->nports = (int) cy_readl (&board_ctrl->n_channel); - cinfo->intr_enabled = 1; - } +#ifdef CONFIG_CYZ_INTR + else { + /* In case this Z board is operating in interrupt mode, its + interrupts should be enabled as soon as the first open + happens to one of its ports. */ + if (!cinfo->intr_enabled) { + struct ZFW_CTRL __iomem *zfw_ctrl; + struct BOARD_CTRL __iomem *board_ctrl; + + zfw_ctrl = cinfo->base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & + 0xfffff); + + board_ctrl = &zfw_ctrl->board_ctrl; + + /* Enable interrupts on the PLX chip */ + cy_writew(cinfo->ctl_addr + 0x68, + cy_readw(cinfo->ctl_addr + + 0x68) | 0x0900); + /* Enable interrupts on the FW */ + retval = cyz_issue_cmd(cinfo, 0, + C_CM_IRQ_ENBL, 0L); + if (retval != 0) { + printk("cyc:IRQ enable retval was %x\n", + retval); + } + cinfo->nports = + (int)cy_readl(&board_ctrl->n_channel); + cinfo->intr_enabled = 1; + } + } +#endif /* CONFIG_CYZ_INTR */ + /* Make sure this Z port really exists in hardware */ + if (info->line > (cinfo->first_line + cinfo->nports - 1)) + return -ENODEV; } -#endif /* CONFIG_CYZ_INTR */ - /* Make sure this Z port really exists in hardware */ - if (info->line > (cinfo->first_line + cinfo->nports - 1)) - return -ENODEV; - } #ifdef CY_DEBUG_OTHER - printk("cyc:cy_open ttyC%d\n", info->line); /* */ + printk("cyc:cy_open ttyC%d\n", info->line); /* */ #endif - tty->driver_data = info; - info->tty = tty; - if (serial_paranoia_check(info, tty->name, "cy_open")){ - return -ENODEV; - } + tty->driver_data = info; + info->tty = tty; + if (serial_paranoia_check(info, tty->name, "cy_open")) { + return -ENODEV; + } #ifdef CY_DEBUG_OPEN - printk("cyc:cy_open ttyC%d, count = %d\n", - info->line, info->count);/**/ + printk("cyc:cy_open ttyC%d, count = %d\n", info->line, info->count); + /**/ #endif - info->count++; + info->count++; #ifdef CY_DEBUG_COUNT - printk("cyc:cy_open (%d): incrementing count to %d\n", - current->pid, info->count); + printk("cyc:cy_open (%d): incrementing count to %d\n", + current->pid, info->count); #endif - /* - * If the port is the middle of closing, bail out now - */ - if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); - return ((info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); - } - - /* - * Start up serial port - */ - retval = startup(info); - if (retval){ - return retval; - } - - retval = block_til_ready(tty, filp, info); - if (retval) { -#ifdef CY_DEBUG_OPEN - printk("cyc:cy_open returning after block_til_ready with %d\n", - retval); -#endif - return retval; - } + /* + * If the port is the middle of closing, bail out now + */ + if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { + if (info->flags & ASYNC_CLOSING) + interruptible_sleep_on(&info->close_wait); + return (info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; + } - info->throttle = 0; + /* + * Start up serial port + */ + retval = startup(info); + if (retval) { + return retval; + } + retval = block_til_ready(tty, filp, info); + if (retval) { #ifdef CY_DEBUG_OPEN - printk(" cyc:cy_open done\n");/**/ + printk("cyc:cy_open returning after block_til_ready with %d\n", + retval); #endif + return retval; + } - return 0; -} /* cy_open */ + info->throttle = 0; +#ifdef CY_DEBUG_OPEN + printk(" cyc:cy_open done\n"); + /**/ +#endif + return 0; +} /* cy_open */ /* * cy_wait_until_sent() --- wait until the transmitter is empty */ -static void -cy_wait_until_sent(struct tty_struct *tty, int timeout) +static void cy_wait_until_sent(struct tty_struct *tty, int timeout) { - struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; - void __iomem *base_addr; - int card,chip,channel,index; - unsigned long orig_jiffies; - int char_time; - - if (serial_paranoia_check(info, tty->name, "cy_wait_until_sent")) - return; - - if (info->xmit_fifo_size == 0) - return; /* Just in case.... */ - - - orig_jiffies = jiffies; - /* - * Set the check interval to be 1/5 of the estimated time to - * send a single character, and make it at least 1. The check - * interval should also be less than the timeout. - * - * Note: we have to use pretty tight timings here to satisfy - * the NIST-PCTS. - */ - char_time = (info->timeout - HZ/50) / info->xmit_fifo_size; - char_time = char_time / 5; - if (char_time <= 0) - char_time = 1; - if (timeout < 0) - timeout = 0; - if (timeout) - char_time = min(char_time, timeout); - /* - * If the transmitter hasn't cleared in twice the approximate - * amount of time to send the entire FIFO, it probably won't - * ever clear. This assumes the UART isn't doing flow - * control, which is currently the case. Hence, if it ever - * takes longer than info->timeout, this is probably due to a - * UART bug of some kind. So, we clamp the timeout parameter at - * 2*info->timeout. - */ - if (!timeout || timeout > 2*info->timeout) - timeout = 2*info->timeout; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + void __iomem *base_addr; + int card, chip, channel, index; + unsigned long orig_jiffies; + int char_time; + + if (serial_paranoia_check(info, tty->name, "cy_wait_until_sent")) + return; + + if (info->xmit_fifo_size == 0) + return; /* Just in case.... */ + + orig_jiffies = jiffies; + /* + * Set the check interval to be 1/5 of the estimated time to + * send a single character, and make it at least 1. The check + * interval should also be less than the timeout. + * + * Note: we have to use pretty tight timings here to satisfy + * the NIST-PCTS. + */ + char_time = (info->timeout - HZ / 50) / info->xmit_fifo_size; + char_time = char_time / 5; + if (char_time <= 0) + char_time = 1; + if (timeout < 0) + timeout = 0; + if (timeout) + char_time = min(char_time, timeout); + /* + * If the transmitter hasn't cleared in twice the approximate + * amount of time to send the entire FIFO, it probably won't + * ever clear. This assumes the UART isn't doing flow + * control, which is currently the case. Hence, if it ever + * takes longer than info->timeout, this is probably due to a + * UART bug of some kind. So, we clamp the timeout parameter at + * 2*info->timeout. + */ + if (!timeout || timeout > 2 * info->timeout) + timeout = 2 * info->timeout; #ifdef CY_DEBUG_WAIT_UNTIL_SENT - printk("In cy_wait_until_sent(%d) check=%lu...", timeout, char_time); - printk("jiff=%lu...", jiffies); + printk("In cy_wait_until_sent(%d) check=%lu...", timeout, char_time); + printk("jiff=%lu...", jiffies); #endif - card = info->card; - channel = (info->line) - (cy_card[card].first_line); - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index); - while (cy_readb(base_addr+(CySRER<<index)) & CyTxRdy) { + card = info->card; + channel = (info->line) - (cy_card[card].first_line); + if (!IS_CYC_Z(cy_card[card])) { + chip = channel >> 2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = + cy_card[card].base_addr + (cy_chip_offset[chip] << index); + while (cy_readb(base_addr + (CySRER << index)) & CyTxRdy) { #ifdef CY_DEBUG_WAIT_UNTIL_SENT - printk("Not clean (jiff=%lu)...", jiffies); + printk("Not clean (jiff=%lu)...", jiffies); #endif - if (msleep_interruptible(jiffies_to_msecs(char_time))) - break; - if (timeout && time_after(jiffies, orig_jiffies + timeout)) - break; + if (msleep_interruptible(jiffies_to_msecs(char_time))) + break; + if (timeout && time_after(jiffies, orig_jiffies + + timeout)) + break; + } + } else { + /* Nothing to do! */ } - } else { - // Nothing to do! - } - /* Run one more char cycle */ - msleep_interruptible(jiffies_to_msecs(char_time * 5)); + /* Run one more char cycle */ + msleep_interruptible(jiffies_to_msecs(char_time * 5)); #ifdef CY_DEBUG_WAIT_UNTIL_SENT - printk("Clean (jiff=%lu)...done\n", jiffies); + printk("Clean (jiff=%lu)...done\n", jiffies); #endif } /* * This routine is called when a particular tty device is closed. */ -static void -cy_close(struct tty_struct *tty, struct file *filp) +static void cy_close(struct tty_struct *tty, struct file *filp) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - unsigned long flags; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + unsigned long flags; #ifdef CY_DEBUG_OTHER - printk("cyc:cy_close ttyC%d\n", info->line); + printk("cyc:cy_close ttyC%d\n", info->line); #endif - if (!info || serial_paranoia_check(info, tty->name, "cy_close")){ - return; - } + if (!info || serial_paranoia_check(info, tty->name, "cy_close")) { + return; + } - CY_LOCK(info, flags); - /* If the TTY is being hung up, nothing to do */ - if (tty_hung_up_p(filp)) { - CY_UNLOCK(info, flags); - return; - } - + CY_LOCK(info, flags); + /* If the TTY is being hung up, nothing to do */ + if (tty_hung_up_p(filp)) { + CY_UNLOCK(info, flags); + return; + } #ifdef CY_DEBUG_OPEN - printk("cyc:cy_close ttyC%d, count = %d\n", info->line, info->count); + printk("cyc:cy_close ttyC%d, count = %d\n", info->line, info->count); #endif - if ((tty->count == 1) && (info->count != 1)) { - /* - * Uh, oh. tty->count is 1, which means that the tty - * structure will be freed. Info->count should always - * be one in these conditions. If it's greater than - * one, we've got real problems, since it means the - * serial port won't be shutdown. - */ - printk("cyc:cy_close: bad serial port count; tty->count is 1, " - "info->count is %d\n", info->count); - info->count = 1; - } + if ((tty->count == 1) && (info->count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty + * structure will be freed. Info->count should always + * be one in these conditions. If it's greater than + * one, we've got real problems, since it means the + * serial port won't be shutdown. + */ + printk("cyc:cy_close: bad serial port count; tty->count is 1, " + "info->count is %d\n", info->count); + info->count = 1; + } #ifdef CY_DEBUG_COUNT - printk("cyc:cy_close at (%d): decrementing count to %d\n", - current->pid, info->count - 1); + printk("cyc:cy_close at (%d): decrementing count to %d\n", + current->pid, info->count - 1); #endif - if (--info->count < 0) { + if (--info->count < 0) { #ifdef CY_DEBUG_COUNT - printk("cyc:cyc_close setting count to 0\n"); + printk("cyc:cyc_close setting count to 0\n"); #endif - info->count = 0; - } - if (info->count) { - CY_UNLOCK(info, flags); - return; - } - info->flags |= ASYNC_CLOSING; - - /* - * Now we wait for the transmit buffer to clear; and we notify - * the line discipline to only process XON/XOFF characters. - */ - tty->closing = 1; - CY_UNLOCK(info, flags); - if (info->closing_wait != CY_CLOSING_WAIT_NONE) { - tty_wait_until_sent(tty, info->closing_wait); - } - CY_LOCK(info, flags); - - if (!IS_CYC_Z(cy_card[info->card])) { - int channel = info->line - cy_card[info->card].first_line; - int index = cy_card[info->card].bus_index; - void __iomem *base_addr = cy_card[info->card].base_addr + (cy_chip_offset[channel>>2] << index); - /* Stop accepting input */ - channel &= 0x03; - cy_writeb(base_addr+(CyCAR<<index), (u_char)channel); - cy_writeb(base_addr+(CySRER<<index), - cy_readb(base_addr+(CySRER<<index)) & ~CyRxData); - if (info->flags & ASYNC_INITIALIZED) { - /* Waiting for on-board buffers to be empty before closing - the port */ - CY_UNLOCK(info, flags); - cy_wait_until_sent(tty, info->timeout); - CY_LOCK(info, flags); + info->count = 0; } - } else { -#ifdef Z_WAKE - /* Waiting for on-board buffers to be empty before closing the port */ - void __iomem *base_addr = cy_card[info->card].base_addr; - struct FIRM_ID __iomem *firm_id = base_addr + ID_ADDRESS; - struct ZFW_CTRL __iomem *zfw_ctrl = base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); - struct CH_CTRL __iomem *ch_ctrl = zfw_ctrl->ch_ctrl; - int channel = info->line - cy_card[info->card].first_line; - int retval; + if (info->count) { + CY_UNLOCK(info, flags); + return; + } + info->flags |= ASYNC_CLOSING; - if (cy_readl(&ch_ctrl[channel].flow_status) != C_FS_TXIDLE) { - retval = cyz_issue_cmd(&cy_card[info->card], channel, - C_CM_IOCTLW, 0L); - if (retval != 0){ - printk("cyc:cy_close retval on ttyC%d was %x\n", - info->line, retval); - } - CY_UNLOCK(info, flags); - interruptible_sleep_on(&info->shutdown_wait); - CY_LOCK(info, flags); + /* + * Now we wait for the transmit buffer to clear; and we notify + * the line discipline to only process XON/XOFF characters. + */ + tty->closing = 1; + CY_UNLOCK(info, flags); + if (info->closing_wait != CY_CLOSING_WAIT_NONE) { + tty_wait_until_sent(tty, info->closing_wait); } + CY_LOCK(info, flags); + + if (!IS_CYC_Z(cy_card[info->card])) { + int channel = info->line - cy_card[info->card].first_line; + int index = cy_card[info->card].bus_index; + void __iomem *base_addr = cy_card[info->card].base_addr + + (cy_chip_offset[channel >> 2] << index); + /* Stop accepting input */ + channel &= 0x03; + cy_writeb(base_addr + (CyCAR << index), (u_char) channel); + cy_writeb(base_addr + (CySRER << index), + cy_readb(base_addr + (CySRER << index)) & ~CyRxData); + if (info->flags & ASYNC_INITIALIZED) { + /* Waiting for on-board buffers to be empty before closing + the port */ + CY_UNLOCK(info, flags); + cy_wait_until_sent(tty, info->timeout); + CY_LOCK(info, flags); + } + } else { +#ifdef Z_WAKE + /* Waiting for on-board buffers to be empty before closing the port */ + void __iomem *base_addr = cy_card[info->card].base_addr; + struct FIRM_ID __iomem *firm_id = base_addr + ID_ADDRESS; + struct ZFW_CTRL __iomem *zfw_ctrl = + base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); + struct CH_CTRL __iomem *ch_ctrl = zfw_ctrl->ch_ctrl; + int channel = info->line - cy_card[info->card].first_line; + int retval; + + if (cy_readl(&ch_ctrl[channel].flow_status) != C_FS_TXIDLE) { + retval = cyz_issue_cmd(&cy_card[info->card], channel, + C_CM_IOCTLW, 0L); + if (retval != 0) { + printk("cyc:cy_close retval on ttyC%d was %x\n", + info->line, retval); + } + CY_UNLOCK(info, flags); + interruptible_sleep_on(&info->shutdown_wait); + CY_LOCK(info, flags); + } #endif - } - - CY_UNLOCK(info, flags); - shutdown(info); - if (tty->driver->flush_buffer) - tty->driver->flush_buffer(tty); - tty_ldisc_flush(tty); - CY_LOCK(info, flags); - - tty->closing = 0; - info->event = 0; - info->tty = NULL; - if (info->blocked_open) { + } + CY_UNLOCK(info, flags); - if (info->close_delay) { - msleep_interruptible(jiffies_to_msecs(info->close_delay)); - } - wake_up_interruptible(&info->open_wait); + shutdown(info); + if (tty->driver->flush_buffer) + tty->driver->flush_buffer(tty); + tty_ldisc_flush(tty); CY_LOCK(info, flags); - } - info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); - wake_up_interruptible(&info->close_wait); + + tty->closing = 0; + info->event = 0; + info->tty = NULL; + if (info->blocked_open) { + CY_UNLOCK(info, flags); + if (info->close_delay) { + msleep_interruptible(jiffies_to_msecs + (info->close_delay)); + } + wake_up_interruptible(&info->open_wait); + CY_LOCK(info, flags); + } + info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); + wake_up_interruptible(&info->close_wait); #ifdef CY_DEBUG_OTHER - printk(" cyc:cy_close done\n"); + printk(" cyc:cy_close done\n"); #endif - CY_UNLOCK(info, flags); - return; -} /* cy_close */ - + CY_UNLOCK(info, flags); +} /* cy_close */ /* This routine gets called when tty_write has put something into * the write_queue. The characters may come from user space or @@ -2796,50 +2875,49 @@ cy_close(struct tty_struct *tty, struct file *filp) * If the port is already active, there is no need to kick it. * */ -static int -cy_write(struct tty_struct * tty, const unsigned char *buf, int count) +static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - unsigned long flags; - int c, ret = 0; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + unsigned long flags; + int c, ret = 0; #ifdef CY_DEBUG_IO - printk("cyc:cy_write ttyC%d\n", info->line); /* */ + printk("cyc:cy_write ttyC%d\n", info->line); /* */ #endif - if (serial_paranoia_check(info, tty->name, "cy_write")){ - return 0; - } - - if (!info->xmit_buf) - return 0; + if (serial_paranoia_check(info, tty->name, "cy_write")) { + return 0; + } - CY_LOCK(info, flags); - while (1) { - c = min(count, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1), - (int)(SERIAL_XMIT_SIZE - info->xmit_head))); - - if (c <= 0) - break; - - memcpy(info->xmit_buf + info->xmit_head, buf, c); - info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt += c; - buf += c; - count -= c; - ret += c; - } - CY_UNLOCK(info, flags); - - info->idle_stats.xmit_bytes += ret; - info->idle_stats.xmit_idle = jiffies; - - if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) { - start_xmit(info); - } - return ret; -} /* cy_write */ + if (!info->xmit_buf) + return 0; + CY_LOCK(info, flags); + while (1) { + c = min(count, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1), + (int)(SERIAL_XMIT_SIZE - info->xmit_head))); + + if (c <= 0) + break; + + memcpy(info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = (info->xmit_head + c) & + (SERIAL_XMIT_SIZE - 1); + info->xmit_cnt += c; + buf += c; + count -= c; + ret += c; + } + CY_UNLOCK(info, flags); + + info->idle_stats.xmit_bytes += ret; + info->idle_stats.xmit_idle = jiffies; + + if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) { + start_xmit(info); + } + return ret; +} /* cy_write */ /* * This routine is called by the kernel to write a single @@ -2848,60 +2926,56 @@ cy_write(struct tty_struct * tty, const unsigned char *buf, int count) * done stuffing characters into the driver. If there is no room * in the queue, the character is ignored. */ -static void -cy_put_char(struct tty_struct *tty, unsigned char ch) +static void cy_put_char(struct tty_struct *tty, unsigned char ch) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - unsigned long flags; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + unsigned long flags; #ifdef CY_DEBUG_IO - printk("cyc:cy_put_char ttyC%d\n", info->line); + printk("cyc:cy_put_char ttyC%d\n", info->line); #endif - if (serial_paranoia_check(info, tty->name, "cy_put_char")) - return; + if (serial_paranoia_check(info, tty->name, "cy_put_char")) + return; - if (!info->xmit_buf) - return; + if (!info->xmit_buf) + return; - CY_LOCK(info, flags); - if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) { - CY_UNLOCK(info, flags); - return; - } + CY_LOCK(info, flags); + if (info->xmit_cnt >= (int)(SERIAL_XMIT_SIZE - 1)) { + CY_UNLOCK(info, flags); + return; + } - info->xmit_buf[info->xmit_head++] = ch; - info->xmit_head &= SERIAL_XMIT_SIZE - 1; - info->xmit_cnt++; + info->xmit_buf[info->xmit_head++] = ch; + info->xmit_head &= SERIAL_XMIT_SIZE - 1; + info->xmit_cnt++; info->idle_stats.xmit_bytes++; info->idle_stats.xmit_idle = jiffies; - CY_UNLOCK(info, flags); -} /* cy_put_char */ - + CY_UNLOCK(info, flags); +} /* cy_put_char */ /* * This routine is called by the kernel after it has written a * series of characters to the tty device using put_char(). */ -static void -cy_flush_chars(struct tty_struct *tty) +static void cy_flush_chars(struct tty_struct *tty) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + #ifdef CY_DEBUG_IO - printk("cyc:cy_flush_chars ttyC%d\n", info->line); /* */ + printk("cyc:cy_flush_chars ttyC%d\n", info->line); /* */ #endif - if (serial_paranoia_check(info, tty->name, "cy_flush_chars")) - return; - - if (info->xmit_cnt <= 0 || tty->stopped - || tty->hw_stopped || !info->xmit_buf) - return; + if (serial_paranoia_check(info, tty->name, "cy_flush_chars")) + return; - start_xmit(info); -} /* cy_flush_chars */ + if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || + !info->xmit_buf) + return; + start_xmit(info); +} /* cy_flush_chars */ /* * This routine returns the numbers of characters the tty driver @@ -2909,75 +2983,70 @@ cy_flush_chars(struct tty_struct *tty) * to change as output buffers get emptied, or if the output flow * control is activated. */ -static int -cy_write_room(struct tty_struct *tty) +static int cy_write_room(struct tty_struct *tty) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - int ret; - + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + int ret; + #ifdef CY_DEBUG_IO - printk("cyc:cy_write_room ttyC%d\n", info->line); /* */ + printk("cyc:cy_write_room ttyC%d\n", info->line); /* */ #endif - if (serial_paranoia_check(info, tty->name, "cy_write_room")) - return 0; - ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; - if (ret < 0) - ret = 0; - return ret; -} /* cy_write_room */ - + if (serial_paranoia_check(info, tty->name, "cy_write_room")) + return 0; + ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; + if (ret < 0) + ret = 0; + return ret; +} /* cy_write_room */ -static int -cy_chars_in_buffer(struct tty_struct *tty) +static int cy_chars_in_buffer(struct tty_struct *tty) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - int card, channel; - - if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer")) - return 0; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + int card, channel; + + if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer")) + return 0; - card = info->card; - channel = (info->line) - (cy_card[card].first_line); + card = info->card; + channel = (info->line) - (cy_card[card].first_line); #ifdef Z_EXT_CHARS_IN_BUFFER - if (!IS_CYC_Z(cy_card[card])) { -#endif /* Z_EXT_CHARS_IN_BUFFER */ + if (!IS_CYC_Z(cy_card[card])) { +#endif /* Z_EXT_CHARS_IN_BUFFER */ #ifdef CY_DEBUG_IO - printk("cyc:cy_chars_in_buffer ttyC%d %d\n", - info->line, info->xmit_cnt); /* */ + printk("cyc:cy_chars_in_buffer ttyC%d %d\n", info->line, info->xmit_cnt); /* */ #endif - return info->xmit_cnt; + return info->xmit_cnt; #ifdef Z_EXT_CHARS_IN_BUFFER - } else { - static volatile struct FIRM_ID *firm_id; - static volatile struct ZFW_CTRL *zfw_ctrl; - static volatile struct CH_CTRL *ch_ctrl; - static volatile struct BUF_CTRL *buf_ctrl; - int char_count; - volatile uclong tx_put, tx_get, tx_bufsize; - - firm_id = cy_card[card].base_addr + ID_ADDRESS; - zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); - ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); - buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]); - - tx_get = cy_readl(&buf_ctrl->tx_get); - tx_put = cy_readl(&buf_ctrl->tx_put); - tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize); - if (tx_put >= tx_get) - char_count = tx_put - tx_get; - else - char_count = tx_put - tx_get + tx_bufsize; + } else { + static volatile struct FIRM_ID *firm_id; + static volatile struct ZFW_CTRL *zfw_ctrl; + static volatile struct CH_CTRL *ch_ctrl; + static volatile struct BUF_CTRL *buf_ctrl; + int char_count; + volatile uclong tx_put, tx_get, tx_bufsize; + + firm_id = cy_card[card].base_addr + ID_ADDRESS; + zfw_ctrl = cy_card[card].base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); + ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); + buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]); + + tx_get = cy_readl(&buf_ctrl->tx_get); + tx_put = cy_readl(&buf_ctrl->tx_put); + tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize); + if (tx_put >= tx_get) + char_count = tx_put - tx_get; + else + char_count = tx_put - tx_get + tx_bufsize; #ifdef CY_DEBUG_IO - printk("cyc:cy_chars_in_buffer ttyC%d %d\n", - info->line, info->xmit_cnt + char_count); /* */ + printk("cyc:cy_chars_in_buffer ttyC%d %d\n", info->line, info->xmit_cnt + char_count); /* */ #endif - return (info->xmit_cnt + char_count); - } -#endif /* Z_EXT_CHARS_IN_BUFFER */ -} /* cy_chars_in_buffer */ - + return info->xmit_cnt + char_count; + } +#endif /* Z_EXT_CHARS_IN_BUFFER */ +} /* cy_chars_in_buffer */ /* * ------------------------------------------------------------ @@ -2985,178 +3054,179 @@ cy_chars_in_buffer(struct tty_struct *tty) * ------------------------------------------------------------ */ -static void -cyy_baud_calc(struct cyclades_port *info, uclong baud) +static void cyy_baud_calc(struct cyclades_port *info, uclong baud) { - int co, co_val, bpr; - uclong cy_clock = ((info->chip_rev >= CD1400_REV_J) ? 60000000 : 25000000); - - if (baud == 0) { - info->tbpr = info->tco = info->rbpr = info->rco = 0; - return; - } - - /* determine which prescaler to use */ - for (co = 4, co_val = 2048; co; co--, co_val >>= 2) { - if (cy_clock / co_val / baud > 63) - break; - } - - bpr = (cy_clock / co_val * 2 / baud + 1) / 2; - if (bpr > 255) - bpr = 255; - - info->tbpr = info->rbpr = bpr; - info->tco = info->rco = co; + int co, co_val, bpr; + uclong cy_clock = ((info->chip_rev >= CD1400_REV_J) ? 60000000 : + 25000000); + + if (baud == 0) { + info->tbpr = info->tco = info->rbpr = info->rco = 0; + return; + } + + /* determine which prescaler to use */ + for (co = 4, co_val = 2048; co; co--, co_val >>= 2) { + if (cy_clock / co_val / baud > 63) + break; + } + + bpr = (cy_clock / co_val * 2 / baud + 1) / 2; + if (bpr > 255) + bpr = 255; + + info->tbpr = info->rbpr = bpr; + info->tco = info->rco = co; } /* * This routine finds or computes the various line characteristics. * It used to be called config_setup */ -static void -set_line_char(struct cyclades_port * info) +static void set_line_char(struct cyclades_port *info) { - unsigned long flags; - void __iomem *base_addr; - int card,chip,channel,index; - unsigned cflag, iflag; - unsigned short chip_number; - int baud, baud_rate = 0; - int i; - - - if (!info->tty || !info->tty->termios){ - return; - } - if (info->line == -1){ - return; - } - cflag = info->tty->termios->c_cflag; - iflag = info->tty->termios->c_iflag; - - /* - * Set up the tty->alt_speed kludge - */ - if (info->tty) { - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - info->tty->alt_speed = 57600; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - info->tty->alt_speed = 115200; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - info->tty->alt_speed = 230400; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - info->tty->alt_speed = 460800; - } - - card = info->card; - channel = (info->line) - (cy_card[card].first_line); - chip_number = channel / 4; - - if (!IS_CYC_Z(cy_card[card])) { - - index = cy_card[card].bus_index; - - /* baud rate */ - baud = tty_get_baud_rate(info->tty); - if ((baud == 38400) && - ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) { - if (info->custom_divisor) - baud_rate = info->baud / info->custom_divisor; - else - baud_rate = info->baud; - } else if (baud > CD1400_MAX_SPEED) { - baud = CD1400_MAX_SPEED; + unsigned long flags; + void __iomem *base_addr; + int card, chip, channel, index; + unsigned cflag, iflag; + unsigned short chip_number; + int baud, baud_rate = 0; + int i; + + if (!info->tty || !info->tty->termios) { + return; } - /* find the baud index */ - for (i = 0; i < 20; i++) { - if (baud == baud_table[i]) { - break; - } + if (info->line == -1) { + return; } - if (i == 20) { - i = 19; /* CD1400_MAX_SPEED */ - } + cflag = info->tty->termios->c_cflag; + iflag = info->tty->termios->c_iflag; - if ((baud == 38400) && - ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) { - cyy_baud_calc(info, baud_rate); - } else { - if(info->chip_rev >= CD1400_REV_J) { - /* It is a CD1400 rev. J or later */ - info->tbpr = baud_bpr_60[i]; /* Tx BPR */ - info->tco = baud_co_60[i]; /* Tx CO */ - info->rbpr = baud_bpr_60[i]; /* Rx BPR */ - info->rco = baud_co_60[i]; /* Rx CO */ - } else { - info->tbpr = baud_bpr_25[i]; /* Tx BPR */ - info->tco = baud_co_25[i]; /* Tx CO */ - info->rbpr = baud_bpr_25[i]; /* Rx BPR */ - info->rco = baud_co_25[i]; /* Rx CO */ - } - } - if (baud_table[i] == 134) { - /* get it right for 134.5 baud */ - info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2; - } else if ((baud == 38400) && - ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) { - info->timeout = (info->xmit_fifo_size*HZ*15/baud_rate) + 2; - } else if (baud_table[i]) { - info->timeout = (info->xmit_fifo_size*HZ*15/baud_table[i]) + 2; - /* this needs to be propagated into the card info */ - } else { - info->timeout = 0; - } - /* By tradition (is it a standard?) a baud rate of zero - implies the line should be/has been closed. A bit - later in this routine such a test is performed. */ - - /* byte size and parity */ - info->cor5 = 0; - info->cor4 = 0; - info->cor3 = (info->default_threshold - ? info->default_threshold - : baud_cor3[i]); /* receive threshold */ - info->cor2 = CyETC; - switch(cflag & CSIZE){ - case CS5: - info->cor1 = Cy_5_BITS; - break; - case CS6: - info->cor1 = Cy_6_BITS; - break; - case CS7: - info->cor1 = Cy_7_BITS; - break; - case CS8: - info->cor1 = Cy_8_BITS; - break; - } - if(cflag & CSTOPB){ - info->cor1 |= Cy_2_STOP; - } - if (cflag & PARENB){ - if (cflag & PARODD){ - info->cor1 |= CyPARITY_O; - }else{ - info->cor1 |= CyPARITY_E; - } - }else{ - info->cor1 |= CyPARITY_NONE; - } - - /* CTS flow control flag */ - if (cflag & CRTSCTS){ - info->flags |= ASYNC_CTS_FLOW; - info->cor2 |= CyCtsAE; - }else{ - info->flags &= ~ASYNC_CTS_FLOW; - info->cor2 &= ~CyCtsAE; + /* + * Set up the tty->alt_speed kludge + */ + if (info->tty) { + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + info->tty->alt_speed = 57600; + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + info->tty->alt_speed = 115200; + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) + info->tty->alt_speed = 230400; + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) + info->tty->alt_speed = 460800; } - if (cflag & CLOCAL) - info->flags &= ~ASYNC_CHECK_CD; - else - info->flags |= ASYNC_CHECK_CD; + + card = info->card; + channel = (info->line) - (cy_card[card].first_line); + chip_number = channel / 4; + + if (!IS_CYC_Z(cy_card[card])) { + + index = cy_card[card].bus_index; + + /* baud rate */ + baud = tty_get_baud_rate(info->tty); + if (baud == 38400 && (info->flags & ASYNC_SPD_MASK) == + ASYNC_SPD_CUST) { + if (info->custom_divisor) + baud_rate = info->baud / info->custom_divisor; + else + baud_rate = info->baud; + } else if (baud > CD1400_MAX_SPEED) { + baud = CD1400_MAX_SPEED; + } + /* find the baud index */ + for (i = 0; i < 20; i++) { + if (baud == baud_table[i]) { + break; + } + } + if (i == 20) { + i = 19; /* CD1400_MAX_SPEED */ + } + + if (baud == 38400 && (info->flags & ASYNC_SPD_MASK) == + ASYNC_SPD_CUST) { + cyy_baud_calc(info, baud_rate); + } else { + if (info->chip_rev >= CD1400_REV_J) { + /* It is a CD1400 rev. J or later */ + info->tbpr = baud_bpr_60[i]; /* Tx BPR */ + info->tco = baud_co_60[i]; /* Tx CO */ + info->rbpr = baud_bpr_60[i]; /* Rx BPR */ + info->rco = baud_co_60[i]; /* Rx CO */ + } else { + info->tbpr = baud_bpr_25[i]; /* Tx BPR */ + info->tco = baud_co_25[i]; /* Tx CO */ + info->rbpr = baud_bpr_25[i]; /* Rx BPR */ + info->rco = baud_co_25[i]; /* Rx CO */ + } + } + if (baud_table[i] == 134) { + /* get it right for 134.5 baud */ + info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) + + 2; + } else if (baud == 38400 && (info->flags & ASYNC_SPD_MASK) == + ASYNC_SPD_CUST) { + info->timeout = (info->xmit_fifo_size * HZ * 15 / + baud_rate) + 2; + } else if (baud_table[i]) { + info->timeout = (info->xmit_fifo_size * HZ * 15 / + baud_table[i]) + 2; + /* this needs to be propagated into the card info */ + } else { + info->timeout = 0; + } + /* By tradition (is it a standard?) a baud rate of zero + implies the line should be/has been closed. A bit + later in this routine such a test is performed. */ + + /* byte size and parity */ + info->cor5 = 0; + info->cor4 = 0; + /* receive threshold */ + info->cor3 = (info->default_threshold ? + info->default_threshold : baud_cor3[i]); + info->cor2 = CyETC; + switch (cflag & CSIZE) { + case CS5: + info->cor1 = Cy_5_BITS; + break; + case CS6: + info->cor1 = Cy_6_BITS; + break; + case CS7: + info->cor1 = Cy_7_BITS; + break; + case CS8: + info->cor1 = Cy_8_BITS; + break; + } + if (cflag & CSTOPB) { + info->cor1 |= Cy_2_STOP; + } + if (cflag & PARENB) { + if (cflag & PARODD) { + info->cor1 |= CyPARITY_O; + } else { + info->cor1 |= CyPARITY_E; + } + } else { + info->cor1 |= CyPARITY_NONE; + } + + /* CTS flow control flag */ + if (cflag & CRTSCTS) { + info->flags |= ASYNC_CTS_FLOW; + info->cor2 |= CyCtsAE; + } else { + info->flags &= ~ASYNC_CTS_FLOW; + info->cor2 &= ~CyCtsAE; + } + if (cflag & CLOCAL) + info->flags &= ~ASYNC_CHECK_CD; + else + info->flags |= ASYNC_CHECK_CD; /*********************************************** The hardware option, CyRtsAO, presents RTS when @@ -3168,300 +3238,319 @@ set_line_char(struct cyclades_port * info) cable. Contact Marcio Saito for details. ***********************************************/ - chip = channel>>2; - channel &= 0x03; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index); + chip = channel >> 2; + channel &= 0x03; + base_addr = cy_card[card].base_addr + + (cy_chip_offset[chip] << index); - CY_LOCK(info, flags); - cy_writeb(base_addr+(CyCAR<<index), (u_char)channel); - - /* tx and rx baud rate */ - - cy_writeb(base_addr+(CyTCOR<<index), info->tco); - cy_writeb(base_addr+(CyTBPR<<index), info->tbpr); - cy_writeb(base_addr+(CyRCOR<<index), info->rco); - cy_writeb(base_addr+(CyRBPR<<index), info->rbpr); - - /* set line characteristics according configuration */ - - cy_writeb(base_addr+(CySCHR1<<index), - START_CHAR(info->tty)); - cy_writeb(base_addr+(CySCHR2<<index), - STOP_CHAR(info->tty)); - cy_writeb(base_addr+(CyCOR1<<index), info->cor1); - cy_writeb(base_addr+(CyCOR2<<index), info->cor2); - cy_writeb(base_addr+(CyCOR3<<index), info->cor3); - cy_writeb(base_addr+(CyCOR4<<index), info->cor4); - cy_writeb(base_addr+(CyCOR5<<index), info->cor5); - - cyy_issue_cmd(base_addr, - CyCOR_CHANGE|CyCOR1ch|CyCOR2ch|CyCOR3ch,index); - - cy_writeb(base_addr+(CyCAR<<index), - (u_char)channel); /* !!! Is this needed? */ - cy_writeb(base_addr+(CyRTPR<<index), (info->default_timeout - ? info->default_timeout - : 0x02)); /* 10ms rx timeout */ - - if (C_CLOCAL(info->tty)) { - /* without modem intr */ - cy_writeb(base_addr+(CySRER<<index), - cy_readb(base_addr+(CySRER<<index)) | CyMdmCh); - /* act on 1->0 modem transitions */ - if ((cflag & CRTSCTS) && info->rflow) { - cy_writeb(base_addr+(CyMCOR1<<index), - (CyCTS|rflow_thr[i])); - } else { - cy_writeb(base_addr+(CyMCOR1<<index), CyCTS); - } - /* act on 0->1 modem transitions */ - cy_writeb(base_addr+(CyMCOR2<<index), CyCTS); - } else { - /* without modem intr */ - cy_writeb(base_addr+(CySRER<<index), - cy_readb(base_addr+(CySRER<<index)) | CyMdmCh); - /* act on 1->0 modem transitions */ - if ((cflag & CRTSCTS) && info->rflow) { - cy_writeb(base_addr+(CyMCOR1<<index), - (CyDSR|CyCTS|CyRI|CyDCD|rflow_thr[i])); - } else { - cy_writeb(base_addr+(CyMCOR1<<index), - CyDSR|CyCTS|CyRI|CyDCD); - } - /* act on 0->1 modem transitions */ - cy_writeb(base_addr+(CyMCOR2<<index), - CyDSR|CyCTS|CyRI|CyDCD); - } - - if(i == 0){ /* baud rate is zero, turn off line */ - if (info->rtsdtr_inv) { - cy_writeb(base_addr+(CyMSVR1<<index), ~CyRTS); + CY_LOCK(info, flags); + cy_writeb(base_addr + (CyCAR << index), (u_char) channel); + + /* tx and rx baud rate */ + + cy_writeb(base_addr + (CyTCOR << index), info->tco); + cy_writeb(base_addr + (CyTBPR << index), info->tbpr); + cy_writeb(base_addr + (CyRCOR << index), info->rco); + cy_writeb(base_addr + (CyRBPR << index), info->rbpr); + + /* set line characteristics according configuration */ + + cy_writeb(base_addr + (CySCHR1 << index), + START_CHAR(info->tty)); + cy_writeb(base_addr + (CySCHR2 << index), STOP_CHAR(info->tty)); + cy_writeb(base_addr + (CyCOR1 << index), info->cor1); + cy_writeb(base_addr + (CyCOR2 << index), info->cor2); + cy_writeb(base_addr + (CyCOR3 << index), info->cor3); + cy_writeb(base_addr + (CyCOR4 << index), info->cor4); + cy_writeb(base_addr + (CyCOR5 << index), info->cor5); + + cyy_issue_cmd(base_addr, CyCOR_CHANGE | CyCOR1ch | CyCOR2ch | + CyCOR3ch, index); + + cy_writeb(base_addr + (CyCAR << index), (u_char) channel); /* !!! Is this needed? */ + cy_writeb(base_addr + (CyRTPR << index), + (info->default_timeout ? info->default_timeout : 0x02)); + /* 10ms rx timeout */ + + if (C_CLOCAL(info->tty)) { + /* without modem intr */ + cy_writeb(base_addr + (CySRER << index), + cy_readb(base_addr + + (CySRER << index)) | CyMdmCh); + /* act on 1->0 modem transitions */ + if ((cflag & CRTSCTS) && info->rflow) { + cy_writeb(base_addr + (CyMCOR1 << index), + (CyCTS | rflow_thr[i])); + } else { + cy_writeb(base_addr + (CyMCOR1 << index), + CyCTS); + } + /* act on 0->1 modem transitions */ + cy_writeb(base_addr + (CyMCOR2 << index), CyCTS); } else { - cy_writeb(base_addr+(CyMSVR2<<index), ~CyDTR); + /* without modem intr */ + cy_writeb(base_addr + (CySRER << index), + cy_readb(base_addr + + (CySRER << index)) | CyMdmCh); + /* act on 1->0 modem transitions */ + if ((cflag & CRTSCTS) && info->rflow) { + cy_writeb(base_addr + (CyMCOR1 << index), + (CyDSR | CyCTS | CyRI | CyDCD | + rflow_thr[i])); + } else { + cy_writeb(base_addr + (CyMCOR1 << index), + CyDSR | CyCTS | CyRI | CyDCD); + } + /* act on 0->1 modem transitions */ + cy_writeb(base_addr + (CyMCOR2 << index), + CyDSR | CyCTS | CyRI | CyDCD); } + + if (i == 0) { /* baud rate is zero, turn off line */ + if (info->rtsdtr_inv) { + cy_writeb(base_addr + (CyMSVR1 << index), + ~CyRTS); + } else { + cy_writeb(base_addr + (CyMSVR2 << index), + ~CyDTR); + } #ifdef CY_DEBUG_DTR - printk("cyc:set_line_char dropping DTR\n"); - printk(" status: 0x%x, 0x%x\n", - cy_readb(base_addr+(CyMSVR1<<index)), - cy_readb(base_addr+(CyMSVR2<<index))); + printk("cyc:set_line_char dropping DTR\n"); + printk(" status: 0x%x, 0x%x\n", + cy_readb(base_addr + (CyMSVR1 << index)), + cy_readb(base_addr + (CyMSVR2 << index))); #endif - }else{ - if (info->rtsdtr_inv) { - cy_writeb(base_addr+(CyMSVR1<<index), CyRTS); - } else { - cy_writeb(base_addr+(CyMSVR2<<index), CyDTR); - } + } else { + if (info->rtsdtr_inv) { + cy_writeb(base_addr + (CyMSVR1 << index), + CyRTS); + } else { + cy_writeb(base_addr + (CyMSVR2 << index), + CyDTR); + } #ifdef CY_DEBUG_DTR - printk("cyc:set_line_char raising DTR\n"); - printk(" status: 0x%x, 0x%x\n", - cy_readb(base_addr+(CyMSVR1<<index)), - cy_readb(base_addr+(CyMSVR2<<index))); + printk("cyc:set_line_char raising DTR\n"); + printk(" status: 0x%x, 0x%x\n", + cy_readb(base_addr + (CyMSVR1 << index)), + cy_readb(base_addr + (CyMSVR2 << index))); #endif - } - - if (info->tty){ - clear_bit(TTY_IO_ERROR, &info->tty->flags); - } - CY_UNLOCK(info, flags); + } - } else { - struct FIRM_ID __iomem *firm_id; - struct ZFW_CTRL __iomem *zfw_ctrl; - struct BOARD_CTRL __iomem *board_ctrl; - struct CH_CTRL __iomem *ch_ctrl; - struct BUF_CTRL __iomem *buf_ctrl; - uclong sw_flow; - int retval; - - firm_id = cy_card[card].base_addr + ID_ADDRESS; - if (!ISZLOADED(cy_card[card])) { - return; - } + if (info->tty) { + clear_bit(TTY_IO_ERROR, &info->tty->flags); + } + CY_UNLOCK(info, flags); - zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); - board_ctrl = &zfw_ctrl->board_ctrl; - ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); - buf_ctrl = &zfw_ctrl->buf_ctrl[channel]; - - /* baud rate */ - baud = tty_get_baud_rate(info->tty); - if ((baud == 38400) && - ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) { - if (info->custom_divisor) - baud_rate = info->baud / info->custom_divisor; - else - baud_rate = info->baud; - } else if (baud > CYZ_MAX_SPEED) { - baud = CYZ_MAX_SPEED; - } - cy_writel(&ch_ctrl->comm_baud , baud); - - if (baud == 134) { - /* get it right for 134.5 baud */ - info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2; - } else if ((baud == 38400) && - ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) { - info->timeout = (info->xmit_fifo_size*HZ*15/baud_rate) + 2; - } else if (baud) { - info->timeout = (info->xmit_fifo_size*HZ*15/baud) + 2; - /* this needs to be propagated into the card info */ } else { - info->timeout = 0; - } + struct FIRM_ID __iomem *firm_id; + struct ZFW_CTRL __iomem *zfw_ctrl; + struct BOARD_CTRL __iomem *board_ctrl; + struct CH_CTRL __iomem *ch_ctrl; + struct BUF_CTRL __iomem *buf_ctrl; + uclong sw_flow; + int retval; + + firm_id = cy_card[card].base_addr + ID_ADDRESS; + if (!ISZLOADED(cy_card[card])) { + return; + } - /* byte size and parity */ - switch(cflag & CSIZE){ - case CS5: cy_writel(&ch_ctrl->comm_data_l , C_DL_CS5); break; - case CS6: cy_writel(&ch_ctrl->comm_data_l , C_DL_CS6); break; - case CS7: cy_writel(&ch_ctrl->comm_data_l , C_DL_CS7); break; - case CS8: cy_writel(&ch_ctrl->comm_data_l , C_DL_CS8); break; - } - if(cflag & CSTOPB){ - cy_writel(&ch_ctrl->comm_data_l, - cy_readl(&ch_ctrl->comm_data_l) | C_DL_2STOP); - }else{ - cy_writel(&ch_ctrl->comm_data_l, - cy_readl(&ch_ctrl->comm_data_l) | C_DL_1STOP); - } - if (cflag & PARENB){ - if (cflag & PARODD){ - cy_writel(&ch_ctrl->comm_parity , C_PR_ODD); - }else{ - cy_writel(&ch_ctrl->comm_parity , C_PR_EVEN); - } - }else{ - cy_writel(&ch_ctrl->comm_parity , C_PR_NONE); - } + zfw_ctrl = cy_card[card].base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); + board_ctrl = &zfw_ctrl->board_ctrl; + ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); + buf_ctrl = &zfw_ctrl->buf_ctrl[channel]; + + /* baud rate */ + baud = tty_get_baud_rate(info->tty); + if (baud == 38400 && (info->flags & ASYNC_SPD_MASK) == + ASYNC_SPD_CUST) { + if (info->custom_divisor) + baud_rate = info->baud / info->custom_divisor; + else + baud_rate = info->baud; + } else if (baud > CYZ_MAX_SPEED) { + baud = CYZ_MAX_SPEED; + } + cy_writel(&ch_ctrl->comm_baud, baud); + + if (baud == 134) { + /* get it right for 134.5 baud */ + info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) + + 2; + } else if (baud == 38400 && (info->flags & ASYNC_SPD_MASK) == + ASYNC_SPD_CUST) { + info->timeout = (info->xmit_fifo_size * HZ * 15 / + baud_rate) + 2; + } else if (baud) { + info->timeout = (info->xmit_fifo_size * HZ * 15 / + baud) + 2; + /* this needs to be propagated into the card info */ + } else { + info->timeout = 0; + } - /* CTS flow control flag */ - if (cflag & CRTSCTS){ - cy_writel(&ch_ctrl->hw_flow, - cy_readl(&ch_ctrl->hw_flow) | C_RS_CTS | C_RS_RTS); - }else{ - cy_writel(&ch_ctrl->hw_flow, - cy_readl(&ch_ctrl->hw_flow) & ~(C_RS_CTS | C_RS_RTS)); - } - /* As the HW flow control is done in firmware, the driver doesn't - need to care about it */ - info->flags &= ~ASYNC_CTS_FLOW; - - /* XON/XOFF/XANY flow control flags */ - sw_flow = 0; - if (iflag & IXON){ - sw_flow |= C_FL_OXX; - if (iflag & IXANY) - sw_flow |= C_FL_OIXANY; - } - cy_writel(&ch_ctrl->sw_flow, sw_flow); + /* byte size and parity */ + switch (cflag & CSIZE) { + case CS5: + cy_writel(&ch_ctrl->comm_data_l, C_DL_CS5); + break; + case CS6: + cy_writel(&ch_ctrl->comm_data_l, C_DL_CS6); + break; + case CS7: + cy_writel(&ch_ctrl->comm_data_l, C_DL_CS7); + break; + case CS8: + cy_writel(&ch_ctrl->comm_data_l, C_DL_CS8); + break; + } + if (cflag & CSTOPB) { + cy_writel(&ch_ctrl->comm_data_l, + cy_readl(&ch_ctrl->comm_data_l) | C_DL_2STOP); + } else { + cy_writel(&ch_ctrl->comm_data_l, + cy_readl(&ch_ctrl->comm_data_l) | C_DL_1STOP); + } + if (cflag & PARENB) { + if (cflag & PARODD) { + cy_writel(&ch_ctrl->comm_parity, C_PR_ODD); + } else { + cy_writel(&ch_ctrl->comm_parity, C_PR_EVEN); + } + } else { + cy_writel(&ch_ctrl->comm_parity, C_PR_NONE); + } - retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTL, 0L); - if (retval != 0){ - printk("cyc:set_line_char retval on ttyC%d was %x\n", - info->line, retval); - } + /* CTS flow control flag */ + if (cflag & CRTSCTS) { + cy_writel(&ch_ctrl->hw_flow, + cy_readl(&ch_ctrl-> + hw_flow) | C_RS_CTS | C_RS_RTS); + } else { + cy_writel(&ch_ctrl->hw_flow, + cy_readl(&ch_ctrl-> + hw_flow) & ~(C_RS_CTS | C_RS_RTS)); + } + /* As the HW flow control is done in firmware, the driver + doesn't need to care about it */ + info->flags &= ~ASYNC_CTS_FLOW; + + /* XON/XOFF/XANY flow control flags */ + sw_flow = 0; + if (iflag & IXON) { + sw_flow |= C_FL_OXX; + if (iflag & IXANY) + sw_flow |= C_FL_OIXANY; + } + cy_writel(&ch_ctrl->sw_flow, sw_flow); - /* CD sensitivity */ - if (cflag & CLOCAL){ - info->flags &= ~ASYNC_CHECK_CD; - }else{ - info->flags |= ASYNC_CHECK_CD; - } + retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTL, 0L); + if (retval != 0) { + printk("cyc:set_line_char retval on ttyC%d was %x\n", + info->line, retval); + } + + /* CD sensitivity */ + if (cflag & CLOCAL) { + info->flags &= ~ASYNC_CHECK_CD; + } else { + info->flags |= ASYNC_CHECK_CD; + } - if(baud == 0){ /* baud rate is zero, turn off line */ - cy_writel(&ch_ctrl->rs_control, - cy_readl(&ch_ctrl->rs_control) & ~C_RS_DTR); + if (baud == 0) { /* baud rate is zero, turn off line */ + cy_writel(&ch_ctrl->rs_control, + cy_readl(&ch_ctrl->rs_control) & ~C_RS_DTR); #ifdef CY_DEBUG_DTR - printk("cyc:set_line_char dropping Z DTR\n"); + printk("cyc:set_line_char dropping Z DTR\n"); #endif - }else{ - cy_writel(&ch_ctrl->rs_control, - cy_readl(&ch_ctrl->rs_control) | C_RS_DTR); + } else { + cy_writel(&ch_ctrl->rs_control, + cy_readl(&ch_ctrl->rs_control) | C_RS_DTR); #ifdef CY_DEBUG_DTR - printk("cyc:set_line_char raising Z DTR\n"); + printk("cyc:set_line_char raising Z DTR\n"); #endif - } + } - retval = cyz_issue_cmd( &cy_card[card], channel, C_CM_IOCTLM, 0L); - if (retval != 0){ - printk("cyc:set_line_char(2) retval on ttyC%d was %x\n", - info->line, retval); - } + retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTLM,0L); + if (retval != 0) { + printk("cyc:set_line_char(2) retval on ttyC%d was %x\n", + info->line, retval); + } - if (info->tty){ - clear_bit(TTY_IO_ERROR, &info->tty->flags); + if (info->tty) { + clear_bit(TTY_IO_ERROR, &info->tty->flags); + } } - } -} /* set_line_char */ - +} /* set_line_char */ static int -get_serial_info(struct cyclades_port * info, - struct serial_struct __user * retinfo) +get_serial_info(struct cyclades_port *info, + struct serial_struct __user * retinfo) { - struct serial_struct tmp; - struct cyclades_card *cinfo = &cy_card[info->card]; - - if (!retinfo) - return -EFAULT; - memset(&tmp, 0, sizeof(tmp)); - tmp.type = info->type; - tmp.line = info->line; - tmp.port = info->card * 0x100 + info->line - cinfo->first_line; - tmp.irq = cinfo->irq; - tmp.flags = info->flags; - tmp.close_delay = info->close_delay; - tmp.baud_base = info->baud; - tmp.custom_divisor = info->custom_divisor; - tmp.hub6 = 0; /*!!!*/ - return copy_to_user(retinfo,&tmp,sizeof(*retinfo))?-EFAULT:0; -} /* get_serial_info */ + struct serial_struct tmp; + struct cyclades_card *cinfo = &cy_card[info->card]; + if (!retinfo) + return -EFAULT; + memset(&tmp, 0, sizeof(tmp)); + tmp.type = info->type; + tmp.line = info->line; + tmp.port = info->card * 0x100 + info->line - cinfo->first_line; + tmp.irq = cinfo->irq; + tmp.flags = info->flags; + tmp.close_delay = info->close_delay; + tmp.baud_base = info->baud; + tmp.custom_divisor = info->custom_divisor; + tmp.hub6 = 0; /*!!! */ + return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0; +} /* get_serial_info */ static int -set_serial_info(struct cyclades_port * info, - struct serial_struct __user * new_info) +set_serial_info(struct cyclades_port *info, + struct serial_struct __user * new_info) { - struct serial_struct new_serial; - struct cyclades_port old_info; - - if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) - return -EFAULT; - old_info = *info; - - if (!capable(CAP_SYS_ADMIN)) { - if ((new_serial.close_delay != info->close_delay) || - (new_serial.baud_base != info->baud) || - ((new_serial.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK) != - (info->flags & ASYNC_FLAGS & ~ASYNC_USR_MASK))) - return -EPERM; - info->flags = ((info->flags & ~ASYNC_USR_MASK) | - (new_serial.flags & ASYNC_USR_MASK)); - info->baud = new_serial.baud_base; - info->custom_divisor = new_serial.custom_divisor; - goto check_and_exit; - } - - - /* - * OK, past this point, all the error checking has been done. - * At this point, we start making changes..... - */ - - info->baud = new_serial.baud_base; - info->custom_divisor = new_serial.custom_divisor; - info->flags = ((info->flags & ~ASYNC_FLAGS) | - (new_serial.flags & ASYNC_FLAGS)); - info->close_delay = new_serial.close_delay * HZ/100; - info->closing_wait = new_serial.closing_wait * HZ/100; + struct serial_struct new_serial; + struct cyclades_port old_info; + + if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) + return -EFAULT; + old_info = *info; + + if (!capable(CAP_SYS_ADMIN)) { + if (new_serial.close_delay != info->close_delay || + new_serial.baud_base != info->baud || + (new_serial.flags & ASYNC_FLAGS & + ~ASYNC_USR_MASK) != + (info->flags & ASYNC_FLAGS & ~ASYNC_USR_MASK)) + return -EPERM; + info->flags = (info->flags & ~ASYNC_USR_MASK) | + (new_serial.flags & ASYNC_USR_MASK); + info->baud = new_serial.baud_base; + info->custom_divisor = new_serial.custom_divisor; + goto check_and_exit; + } + + /* + * OK, past this point, all the error checking has been done. + * At this point, we start making changes..... + */ + + info->baud = new_serial.baud_base; + info->custom_divisor = new_serial.custom_divisor; + info->flags = (info->flags & ~ASYNC_FLAGS) | + (new_serial.flags & ASYNC_FLAGS); + info->close_delay = new_serial.close_delay * HZ / 100; + info->closing_wait = new_serial.closing_wait * HZ / 100; check_and_exit: - if (info->flags & ASYNC_INITIALIZED){ - set_line_char(info); - return 0; - }else{ - return startup(info); - } -} /* set_serial_info */ + if (info->flags & ASYNC_INITIALIZED) { + set_line_char(info); + return 0; + } else { + return startup(info); + } +} /* set_serial_info */ /* * get_lsr_info - get line status register info @@ -3473,441 +3562,452 @@ check_and_exit: * transmit holding register is empty. This functionality * allows an RS485 driver to be written in user space. */ -static int get_lsr_info(struct cyclades_port *info, unsigned int __user *value) +static int get_lsr_info(struct cyclades_port *info, unsigned int __user * value) { - int card, chip, channel, index; - unsigned char status; - unsigned int result; - unsigned long flags; - void __iomem *base_addr; - - card = info->card; - channel = (info->line) - (cy_card[card].first_line); - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index); + int card, chip, channel, index; + unsigned char status; + unsigned int result; + unsigned long flags; + void __iomem *base_addr; - CY_LOCK(info, flags); - status = cy_readb(base_addr+(CySRER<<index)) & (CyTxRdy|CyTxMpty); - CY_UNLOCK(info, flags); - result = (status ? 0 : TIOCSER_TEMT); - } else { - /* Not supported yet */ - return -EINVAL; - } - return put_user(result, (unsigned long __user *) value); + card = info->card; + channel = (info->line) - (cy_card[card].first_line); + if (!IS_CYC_Z(cy_card[card])) { + chip = channel >> 2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = + cy_card[card].base_addr + (cy_chip_offset[chip] << index); + + CY_LOCK(info, flags); + status = cy_readb(base_addr + (CySRER << index)) & + (CyTxRdy | CyTxMpty); + CY_UNLOCK(info, flags); + result = (status ? 0 : TIOCSER_TEMT); + } else { + /* Not supported yet */ + return -EINVAL; + } + return put_user(result, (unsigned long __user *)value); } -static int -cy_tiocmget(struct tty_struct *tty, struct file *file) +static int cy_tiocmget(struct tty_struct *tty, struct file *file) { - struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; - int card,chip,channel,index; - void __iomem *base_addr; - unsigned long flags; - unsigned char status; - unsigned long lstatus; - unsigned int result; - struct FIRM_ID __iomem *firm_id; - struct ZFW_CTRL __iomem *zfw_ctrl; - struct BOARD_CTRL __iomem *board_ctrl; - struct CH_CTRL __iomem *ch_ctrl; - - if (serial_paranoia_check(info, tty->name, __FUNCTION__)) - return -ENODEV; - - card = info->card; - channel = (info->line) - (cy_card[card].first_line); - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index); + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + int card, chip, channel, index; + void __iomem *base_addr; + unsigned long flags; + unsigned char status; + unsigned long lstatus; + unsigned int result; + struct FIRM_ID __iomem *firm_id; + struct ZFW_CTRL __iomem *zfw_ctrl; + struct BOARD_CTRL __iomem *board_ctrl; + struct CH_CTRL __iomem *ch_ctrl; + + if (serial_paranoia_check(info, tty->name, __FUNCTION__)) + return -ENODEV; - CY_LOCK(info, flags); - cy_writeb(base_addr+(CyCAR<<index), (u_char)channel); - status = cy_readb(base_addr+(CyMSVR1<<index)); - status |= cy_readb(base_addr+(CyMSVR2<<index)); - CY_UNLOCK(info, flags); + card = info->card; + channel = (info->line) - (cy_card[card].first_line); + if (!IS_CYC_Z(cy_card[card])) { + chip = channel >> 2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = + cy_card[card].base_addr + (cy_chip_offset[chip] << index); - if (info->rtsdtr_inv) { - result = ((status & CyRTS) ? TIOCM_DTR : 0) - | ((status & CyDTR) ? TIOCM_RTS : 0); + CY_LOCK(info, flags); + cy_writeb(base_addr + (CyCAR << index), (u_char) channel); + status = cy_readb(base_addr + (CyMSVR1 << index)); + status |= cy_readb(base_addr + (CyMSVR2 << index)); + CY_UNLOCK(info, flags); + + if (info->rtsdtr_inv) { + result = ((status & CyRTS) ? TIOCM_DTR : 0) | + ((status & CyDTR) ? TIOCM_RTS : 0); + } else { + result = ((status & CyRTS) ? TIOCM_RTS : 0) | + ((status & CyDTR) ? TIOCM_DTR : 0); + } + result |= ((status & CyDCD) ? TIOCM_CAR : 0) | + ((status & CyRI) ? TIOCM_RNG : 0) | + ((status & CyDSR) ? TIOCM_DSR : 0) | + ((status & CyCTS) ? TIOCM_CTS : 0); } else { - result = ((status & CyRTS) ? TIOCM_RTS : 0) - | ((status & CyDTR) ? TIOCM_DTR : 0); - } - result |= ((status & CyDCD) ? TIOCM_CAR : 0) - | ((status & CyRI) ? TIOCM_RNG : 0) - | ((status & CyDSR) ? TIOCM_DSR : 0) - | ((status & CyCTS) ? TIOCM_CTS : 0); - } else { - base_addr = cy_card[card].base_addr; - - if (cy_card[card].num_chips != -1){ - return -EINVAL; - } + base_addr = cy_card[card].base_addr; - firm_id = cy_card[card].base_addr + ID_ADDRESS; - if (ISZLOADED(cy_card[card])) { - zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); - board_ctrl = &zfw_ctrl->board_ctrl; - ch_ctrl = zfw_ctrl->ch_ctrl; - lstatus = cy_readl(&ch_ctrl[channel].rs_status); - result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0) - | ((lstatus & C_RS_DTR) ? TIOCM_DTR : 0) - | ((lstatus & C_RS_DCD) ? TIOCM_CAR : 0) - | ((lstatus & C_RS_RI) ? TIOCM_RNG : 0) - | ((lstatus & C_RS_DSR) ? TIOCM_DSR : 0) - | ((lstatus & C_RS_CTS) ? TIOCM_CTS : 0); - }else{ - result = 0; - return -ENODEV; - } + if (cy_card[card].num_chips != -1) { + return -EINVAL; + } - } - return result; -} /* cy_tiomget */ + firm_id = cy_card[card].base_addr + ID_ADDRESS; + if (ISZLOADED(cy_card[card])) { + zfw_ctrl = cy_card[card].base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); + board_ctrl = &zfw_ctrl->board_ctrl; + ch_ctrl = zfw_ctrl->ch_ctrl; + lstatus = cy_readl(&ch_ctrl[channel].rs_status); + result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0) | + ((lstatus & C_RS_DTR) ? TIOCM_DTR : 0) | + ((lstatus & C_RS_DCD) ? TIOCM_CAR : 0) | + ((lstatus & C_RS_RI) ? TIOCM_RNG : 0) | + ((lstatus & C_RS_DSR) ? TIOCM_DSR : 0) | + ((lstatus & C_RS_CTS) ? TIOCM_CTS : 0); + } else { + result = 0; + return -ENODEV; + } + } + return result; +} /* cy_tiomget */ static int cy_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) + unsigned int set, unsigned int clear) { - struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; - int card,chip,channel,index; - void __iomem *base_addr; - unsigned long flags; - struct FIRM_ID __iomem *firm_id; - struct ZFW_CTRL __iomem *zfw_ctrl; - struct BOARD_CTRL __iomem *board_ctrl; - struct CH_CTRL __iomem *ch_ctrl; - int retval; - - if (serial_paranoia_check(info, tty->name, __FUNCTION__)) - return -ENODEV; - - card = info->card; - channel = (info->line) - (cy_card[card].first_line); - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index); - - if (set & TIOCM_RTS){ - CY_LOCK(info, flags); - cy_writeb(base_addr+(CyCAR<<index), (u_char)channel); - if (info->rtsdtr_inv) { - cy_writeb(base_addr+(CyMSVR2<<index), CyDTR); - } else { - cy_writeb(base_addr+(CyMSVR1<<index), CyRTS); - } - CY_UNLOCK(info, flags); - } - if (clear & TIOCM_RTS) { - CY_LOCK(info, flags); - cy_writeb(base_addr+(CyCAR<<index), (u_char)channel); - if (info->rtsdtr_inv) { - cy_writeb(base_addr+(CyMSVR2<<index), ~CyDTR); - } else { - cy_writeb(base_addr+(CyMSVR1<<index), ~CyRTS); - } - CY_UNLOCK(info, flags); - } - if (set & TIOCM_DTR){ - CY_LOCK(info, flags); - cy_writeb(base_addr+(CyCAR<<index), (u_char)channel); - if (info->rtsdtr_inv) { - cy_writeb(base_addr+(CyMSVR1<<index), CyRTS); - } else { - cy_writeb(base_addr+(CyMSVR2<<index), CyDTR); - } + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + int card, chip, channel, index; + void __iomem *base_addr; + unsigned long flags; + struct FIRM_ID __iomem *firm_id; + struct ZFW_CTRL __iomem *zfw_ctrl; + struct BOARD_CTRL __iomem *board_ctrl; + struct CH_CTRL __iomem *ch_ctrl; + int retval; + + if (serial_paranoia_check(info, tty->name, __FUNCTION__)) + return -ENODEV; + + card = info->card; + channel = (info->line) - (cy_card[card].first_line); + if (!IS_CYC_Z(cy_card[card])) { + chip = channel >> 2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = + cy_card[card].base_addr + (cy_chip_offset[chip] << index); + + if (set & TIOCM_RTS) { + CY_LOCK(info, flags); + cy_writeb(base_addr + (CyCAR << index), + (u_char) channel); + if (info->rtsdtr_inv) { + cy_writeb(base_addr + (CyMSVR2 << index), + CyDTR); + } else { + cy_writeb(base_addr + (CyMSVR1 << index), + CyRTS); + } + CY_UNLOCK(info, flags); + } + if (clear & TIOCM_RTS) { + CY_LOCK(info, flags); + cy_writeb(base_addr + (CyCAR << index), + (u_char) channel); + if (info->rtsdtr_inv) { + cy_writeb(base_addr + (CyMSVR2 << index), + ~CyDTR); + } else { + cy_writeb(base_addr + (CyMSVR1 << index), + ~CyRTS); + } + CY_UNLOCK(info, flags); + } + if (set & TIOCM_DTR) { + CY_LOCK(info, flags); + cy_writeb(base_addr + (CyCAR << index), + (u_char) channel); + if (info->rtsdtr_inv) { + cy_writeb(base_addr + (CyMSVR1 << index), + CyRTS); + } else { + cy_writeb(base_addr + (CyMSVR2 << index), + CyDTR); + } #ifdef CY_DEBUG_DTR - printk("cyc:set_modem_info raising DTR\n"); - printk(" status: 0x%x, 0x%x\n", - cy_readb(base_addr+(CyMSVR1<<index)), - cy_readb(base_addr+(CyMSVR2<<index))); + printk("cyc:set_modem_info raising DTR\n"); + printk(" status: 0x%x, 0x%x\n", + cy_readb(base_addr + (CyMSVR1 << index)), + cy_readb(base_addr + (CyMSVR2 << index))); #endif - CY_UNLOCK(info, flags); - } - if (clear & TIOCM_DTR) { - CY_LOCK(info, flags); - cy_writeb(base_addr+(CyCAR<<index), (u_char)channel); - if (info->rtsdtr_inv) { - cy_writeb(base_addr+(CyMSVR1<<index), ~CyRTS); - } else { - cy_writeb(base_addr+(CyMSVR2<<index), ~CyDTR); - } + CY_UNLOCK(info, flags); + } + if (clear & TIOCM_DTR) { + CY_LOCK(info, flags); + cy_writeb(base_addr + (CyCAR << index), + (u_char) channel); + if (info->rtsdtr_inv) { + cy_writeb(base_addr + (CyMSVR1 << index), + ~CyRTS); + } else { + cy_writeb(base_addr + (CyMSVR2 << index), + ~CyDTR); + } #ifdef CY_DEBUG_DTR - printk("cyc:set_modem_info dropping DTR\n"); - printk(" status: 0x%x, 0x%x\n", - cy_readb(base_addr+(CyMSVR1<<index)), - cy_readb(base_addr+(CyMSVR2<<index))); + printk("cyc:set_modem_info dropping DTR\n"); + printk(" status: 0x%x, 0x%x\n", + cy_readb(base_addr + (CyMSVR1 << index)), + cy_readb(base_addr + (CyMSVR2 << index))); #endif - CY_UNLOCK(info, flags); - } - } else { - base_addr = cy_card[card].base_addr; - - firm_id = cy_card[card].base_addr + ID_ADDRESS; - if (ISZLOADED(cy_card[card])) { - zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); - board_ctrl = &zfw_ctrl->board_ctrl; - ch_ctrl = zfw_ctrl->ch_ctrl; - - if (set & TIOCM_RTS){ - CY_LOCK(info, flags); - cy_writel(&ch_ctrl[channel].rs_control, - cy_readl(&ch_ctrl[channel].rs_control) | C_RS_RTS); - CY_UNLOCK(info, flags); - } - if (clear & TIOCM_RTS) { - CY_LOCK(info, flags); - cy_writel(&ch_ctrl[channel].rs_control, - cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_RTS); - CY_UNLOCK(info, flags); - } - if (set & TIOCM_DTR){ - CY_LOCK(info, flags); - cy_writel(&ch_ctrl[channel].rs_control, - cy_readl(&ch_ctrl[channel].rs_control) | C_RS_DTR); + CY_UNLOCK(info, flags); + } + } else { + base_addr = cy_card[card].base_addr; + + firm_id = cy_card[card].base_addr + ID_ADDRESS; + if (ISZLOADED(cy_card[card])) { + zfw_ctrl = cy_card[card].base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); + board_ctrl = &zfw_ctrl->board_ctrl; + ch_ctrl = zfw_ctrl->ch_ctrl; + + if (set & TIOCM_RTS) { + CY_LOCK(info, flags); + cy_writel(&ch_ctrl[channel].rs_control, + cy_readl(&ch_ctrl[channel]. + rs_control) | C_RS_RTS); + CY_UNLOCK(info, flags); + } + if (clear & TIOCM_RTS) { + CY_LOCK(info, flags); + cy_writel(&ch_ctrl[channel].rs_control, + cy_readl(&ch_ctrl[channel]. + rs_control) & ~C_RS_RTS); + CY_UNLOCK(info, flags); + } + if (set & TIOCM_DTR) { + CY_LOCK(info, flags); + cy_writel(&ch_ctrl[channel].rs_control, + cy_readl(&ch_ctrl[channel]. + rs_control) | C_RS_DTR); #ifdef CY_DEBUG_DTR - printk("cyc:set_modem_info raising Z DTR\n"); + printk("cyc:set_modem_info raising Z DTR\n"); #endif - CY_UNLOCK(info, flags); - } - if (clear & TIOCM_DTR) { - CY_LOCK(info, flags); - cy_writel(&ch_ctrl[channel].rs_control, - cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_DTR); + CY_UNLOCK(info, flags); + } + if (clear & TIOCM_DTR) { + CY_LOCK(info, flags); + cy_writel(&ch_ctrl[channel].rs_control, + cy_readl(&ch_ctrl[channel]. + rs_control) & ~C_RS_DTR); #ifdef CY_DEBUG_DTR - printk("cyc:set_modem_info clearing Z DTR\n"); + printk("cyc:set_modem_info clearing Z DTR\n"); #endif - CY_UNLOCK(info, flags); - } - }else{ - return -ENODEV; - } - CY_LOCK(info, flags); - retval = cyz_issue_cmd(&cy_card[info->card], - channel, C_CM_IOCTLM,0L); - if (retval != 0){ - printk("cyc:set_modem_info retval on ttyC%d was %x\n", - info->line, retval); + CY_UNLOCK(info, flags); + } + } else { + return -ENODEV; + } + CY_LOCK(info, flags); + retval = cyz_issue_cmd(&cy_card[info->card], + channel, C_CM_IOCTLM, 0L); + if (retval != 0) { + printk("cyc:set_modem_info retval on ttyC%d was %x\n", + info->line, retval); + } + CY_UNLOCK(info, flags); } - CY_UNLOCK(info, flags); - } - return 0; -} /* cy_tiocmset */ + return 0; +} /* cy_tiocmset */ /* * cy_break() --- routine which turns the break handling on or off */ -static void -cy_break(struct tty_struct *tty, int break_state) +static void cy_break(struct tty_struct *tty, int break_state) { - struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "cy_break")) - return; - - CY_LOCK(info, flags); - if (!IS_CYC_Z(cy_card[info->card])) { - /* Let the transmit ISR take care of this (since it - requires stuffing characters into the output stream). - */ - if (break_state == -1) { - if (!info->breakon) { - info->breakon = 1; - if (!info->xmit_cnt) { - CY_UNLOCK(info, flags); - start_xmit(info); - CY_LOCK(info, flags); + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->name, "cy_break")) + return; + + CY_LOCK(info, flags); + if (!IS_CYC_Z(cy_card[info->card])) { + /* Let the transmit ISR take care of this (since it + requires stuffing characters into the output stream). + */ + if (break_state == -1) { + if (!info->breakon) { + info->breakon = 1; + if (!info->xmit_cnt) { + CY_UNLOCK(info, flags); + start_xmit(info); + CY_LOCK(info, flags); + } + } + } else { + if (!info->breakoff) { + info->breakoff = 1; + if (!info->xmit_cnt) { + CY_UNLOCK(info, flags); + start_xmit(info); + CY_LOCK(info, flags); + } + } } - } } else { - if (!info->breakoff) { - info->breakoff = 1; - if (!info->xmit_cnt) { - CY_UNLOCK(info, flags); - start_xmit(info); - CY_LOCK(info, flags); + int retval; + + if (break_state == -1) { + retval = cyz_issue_cmd(&cy_card[info->card], + info->line - cy_card[info->card].first_line, + C_CM_SET_BREAK, 0L); + if (retval != 0) { + printk("cyc:cy_break (set) retval on ttyC%d " + "was %x\n", info->line, retval); + } + } else { + retval = cyz_issue_cmd(&cy_card[info->card], + info->line - cy_card[info->card].first_line, + C_CM_CLR_BREAK, 0L); + if (retval != 0) { + printk("cyc:cy_break (clr) retval on ttyC%d " + "was %x\n", info->line, retval); + } } - } - } - } else { - int retval; - - if (break_state == -1) { - retval = cyz_issue_cmd(&cy_card[info->card], - (info->line) - (cy_card[info->card].first_line), - C_CM_SET_BREAK, 0L); - if (retval != 0) { - printk("cyc:cy_break (set) retval on ttyC%d was %x\n", - info->line, retval); - } - } else { - retval = cyz_issue_cmd(&cy_card[info->card], - (info->line) - (cy_card[info->card].first_line), - C_CM_CLR_BREAK, 0L); - if (retval != 0) { - printk("cyc:cy_break (clr) retval on ttyC%d was %x\n", - info->line, retval); - } } - } - CY_UNLOCK(info, flags); -} /* cy_break */ + CY_UNLOCK(info, flags); +} /* cy_break */ static int -get_mon_info(struct cyclades_port * info, struct cyclades_monitor __user * mon) +get_mon_info(struct cyclades_port *info, struct cyclades_monitor __user * mon) { - if(copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor))) - return -EFAULT; - info->mon.int_count = 0; - info->mon.char_count = 0; - info->mon.char_max = 0; - info->mon.char_last = 0; - return 0; -}/* get_mon_info */ - + if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor))) + return -EFAULT; + info->mon.int_count = 0; + info->mon.char_count = 0; + info->mon.char_max = 0; + info->mon.char_last = 0; + return 0; +} /* get_mon_info */ -static int -set_threshold(struct cyclades_port * info, unsigned long value) +static int set_threshold(struct cyclades_port *info, unsigned long value) { - void __iomem *base_addr; - int card,channel,chip,index; - unsigned long flags; - - card = info->card; - channel = info->line - cy_card[card].first_line; - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index); - - info->cor3 &= ~CyREC_FIFO; - info->cor3 |= value & CyREC_FIFO; + void __iomem *base_addr; + int card, channel, chip, index; + unsigned long flags; - CY_LOCK(info, flags); - cy_writeb(base_addr+(CyCOR3<<index), info->cor3); - cyy_issue_cmd(base_addr,CyCOR_CHANGE|CyCOR3ch,index); - CY_UNLOCK(info, flags); - } else { - // Nothing to do! - } - return 0; -}/* set_threshold */ + card = info->card; + channel = info->line - cy_card[card].first_line; + if (!IS_CYC_Z(cy_card[card])) { + chip = channel >> 2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = + cy_card[card].base_addr + (cy_chip_offset[chip] << index); + info->cor3 &= ~CyREC_FIFO; + info->cor3 |= value & CyREC_FIFO; -static int -get_threshold(struct cyclades_port * info, unsigned long __user *value) -{ - void __iomem *base_addr; - int card,channel,chip,index; - unsigned long tmp; - - card = info->card; - channel = info->line - cy_card[card].first_line; - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index); - - tmp = cy_readb(base_addr+(CyCOR3<<index)) & CyREC_FIFO; - return put_user(tmp,value); - } else { - // Nothing to do! + CY_LOCK(info, flags); + cy_writeb(base_addr + (CyCOR3 << index), info->cor3); + cyy_issue_cmd(base_addr, CyCOR_CHANGE | CyCOR3ch, index); + CY_UNLOCK(info, flags); + } else { + /* Nothing to do! */ + } return 0; - } -}/* get_threshold */ - +} /* set_threshold */ static int -set_default_threshold(struct cyclades_port * info, unsigned long value) +get_threshold(struct cyclades_port *info, unsigned long __user * value) { - info->default_threshold = value & 0x0f; - return 0; -}/* set_default_threshold */ + void __iomem *base_addr; + int card, channel, chip, index; + unsigned long tmp; + card = info->card; + channel = info->line - cy_card[card].first_line; + if (!IS_CYC_Z(cy_card[card])) { + chip = channel >> 2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = + cy_card[card].base_addr + (cy_chip_offset[chip] << index); + + tmp = cy_readb(base_addr + (CyCOR3 << index)) & CyREC_FIFO; + return put_user(tmp, value); + } else { + /* Nothing to do! */ + return 0; + } +} /* get_threshold */ static int -get_default_threshold(struct cyclades_port * info, unsigned long __user *value) +set_default_threshold(struct cyclades_port *info, unsigned long value) { - return put_user(info->default_threshold,value); -}/* get_default_threshold */ - + info->default_threshold = value & 0x0f; + return 0; +} /* set_default_threshold */ static int -set_timeout(struct cyclades_port * info, unsigned long value) +get_default_threshold(struct cyclades_port *info, unsigned long __user * value) { - void __iomem *base_addr; - int card,channel,chip,index; - unsigned long flags; - - card = info->card; - channel = info->line - cy_card[card].first_line; - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index); + return put_user(info->default_threshold, value); +} /* get_default_threshold */ - CY_LOCK(info, flags); - cy_writeb(base_addr+(CyRTPR<<index), value & 0xff); - CY_UNLOCK(info, flags); - } else { - // Nothing to do! - } - return 0; -}/* set_timeout */ +static int set_timeout(struct cyclades_port *info, unsigned long value) +{ + void __iomem *base_addr; + int card, channel, chip, index; + unsigned long flags; + card = info->card; + channel = info->line - cy_card[card].first_line; + if (!IS_CYC_Z(cy_card[card])) { + chip = channel >> 2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = + cy_card[card].base_addr + (cy_chip_offset[chip] << index); -static int -get_timeout(struct cyclades_port * info, unsigned long __user *value) -{ - void __iomem *base_addr; - int card,channel,chip,index; - unsigned long tmp; - - card = info->card; - channel = info->line - cy_card[card].first_line; - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index); - - tmp = cy_readb(base_addr+(CyRTPR<<index)); - return put_user(tmp,value); - } else { - // Nothing to do! + CY_LOCK(info, flags); + cy_writeb(base_addr + (CyRTPR << index), value & 0xff); + CY_UNLOCK(info, flags); + } else { + /* Nothing to do! */ + } return 0; - } -}/* get_timeout */ - +} /* set_timeout */ -static int -set_default_timeout(struct cyclades_port * info, unsigned long value) +static int get_timeout(struct cyclades_port *info, unsigned long __user * value) { - info->default_timeout = value & 0xff; - return 0; -}/* set_default_timeout */ + void __iomem *base_addr; + int card, channel, chip, index; + unsigned long tmp; + card = info->card; + channel = info->line - cy_card[card].first_line; + if (!IS_CYC_Z(cy_card[card])) { + chip = channel >> 2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = + cy_card[card].base_addr + (cy_chip_offset[chip] << index); + + tmp = cy_readb(base_addr + (CyRTPR << index)); + return put_user(tmp, value); + } else { + /* Nothing to do! */ + return 0; + } +} /* get_timeout */ + +static int set_default_timeout(struct cyclades_port *info, unsigned long value) +{ + info->default_timeout = value & 0xff; + return 0; +} /* set_default_timeout */ static int -get_default_timeout(struct cyclades_port * info, unsigned long __user *value) +get_default_timeout(struct cyclades_port *info, unsigned long __user * value) { - return put_user(info->default_timeout,value); -}/* get_default_timeout */ + return put_user(info->default_timeout, value); +} /* get_default_timeout */ /* * This routine allows the tty driver to implement device- @@ -3915,184 +4015,193 @@ get_default_timeout(struct cyclades_port * info, unsigned long __user *value) * not recognized by the driver, it should return ENOIOCTLCMD. */ static int -cy_ioctl(struct tty_struct *tty, struct file * file, - unsigned int cmd, unsigned long arg) +cy_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) { - struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; - struct cyclades_icount cprev, cnow; /* kernel counter temps */ - struct serial_icounter_struct __user *p_cuser; /* user space */ - int ret_val = 0; - unsigned long flags; - void __user *argp = (void __user *)arg; - - if (serial_paranoia_check(info, tty->name, "cy_ioctl")) - return -ENODEV; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + struct cyclades_icount cprev, cnow; /* kernel counter temps */ + struct serial_icounter_struct __user *p_cuser; /* user space */ + int ret_val = 0; + unsigned long flags; + void __user *argp = (void __user *)arg; + + if (serial_paranoia_check(info, tty->name, "cy_ioctl")) + return -ENODEV; #ifdef CY_DEBUG_OTHER - printk("cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n", - info->line, cmd, arg); /* */ + printk("cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n", info->line, cmd, arg); /* */ #endif - switch (cmd) { - case CYGETMON: - ret_val = get_mon_info(info, argp); - break; - case CYGETTHRESH: - ret_val = get_threshold(info, argp); - break; - case CYSETTHRESH: - ret_val = set_threshold(info, arg); - break; - case CYGETDEFTHRESH: - ret_val = get_default_threshold(info, argp); - break; - case CYSETDEFTHRESH: - ret_val = set_default_threshold(info, arg); - break; - case CYGETTIMEOUT: - ret_val = get_timeout(info, argp); - break; - case CYSETTIMEOUT: - ret_val = set_timeout(info, arg); - break; - case CYGETDEFTIMEOUT: - ret_val = get_default_timeout(info, argp); - break; - case CYSETDEFTIMEOUT: - ret_val = set_default_timeout(info, arg); - break; + switch (cmd) { + case CYGETMON: + ret_val = get_mon_info(info, argp); + break; + case CYGETTHRESH: + ret_val = get_threshold(info, argp); + break; + case CYSETTHRESH: + ret_val = set_threshold(info, arg); + break; + case CYGETDEFTHRESH: + ret_val = get_default_threshold(info, argp); + break; + case CYSETDEFTHRESH: + ret_val = set_default_threshold(info, arg); + break; + case CYGETTIMEOUT: + ret_val = get_timeout(info, argp); + break; + case CYSETTIMEOUT: + ret_val = set_timeout(info, arg); + break; + case CYGETDEFTIMEOUT: + ret_val = get_default_timeout(info, argp); + break; + case CYSETDEFTIMEOUT: + ret_val = set_default_timeout(info, arg); + break; case CYSETRFLOW: - info->rflow = (int)arg; - ret_val = 0; - break; + info->rflow = (int)arg; + ret_val = 0; + break; case CYGETRFLOW: - ret_val = info->rflow; - break; + ret_val = info->rflow; + break; case CYSETRTSDTR_INV: - info->rtsdtr_inv = (int)arg; - ret_val = 0; - break; + info->rtsdtr_inv = (int)arg; + ret_val = 0; + break; case CYGETRTSDTR_INV: - ret_val = info->rtsdtr_inv; - break; + ret_val = info->rtsdtr_inv; + break; case CYGETCARDINFO: - if (copy_to_user(argp, &cy_card[info->card], - sizeof (struct cyclades_card))) { - ret_val = -EFAULT; + if (copy_to_user(argp, &cy_card[info->card], + sizeof(struct cyclades_card))) { + ret_val = -EFAULT; + break; + } + ret_val = 0; break; - } - ret_val = 0; - break; case CYGETCD1400VER: - ret_val = info->chip_rev; - break; + ret_val = info->chip_rev; + break; #ifndef CONFIG_CYZ_INTR case CYZSETPOLLCYCLE: - cyz_polling_cycle = (arg * HZ) / 1000; - ret_val = 0; - break; + cyz_polling_cycle = (arg * HZ) / 1000; + ret_val = 0; + break; case CYZGETPOLLCYCLE: - ret_val = (cyz_polling_cycle * 1000) / HZ; - break; -#endif /* CONFIG_CYZ_INTR */ + ret_val = (cyz_polling_cycle * 1000) / HZ; + break; +#endif /* CONFIG_CYZ_INTR */ case CYSETWAIT: - info->closing_wait = (unsigned short)arg * HZ/100; - ret_val = 0; - break; + info->closing_wait = (unsigned short)arg *HZ / 100; + ret_val = 0; + break; case CYGETWAIT: - ret_val = info->closing_wait / (HZ/100); - break; - case TIOCGSERIAL: - ret_val = get_serial_info(info, argp); - break; - case TIOCSSERIAL: - ret_val = set_serial_info(info, argp); - break; - case TIOCSERGETLSR: /* Get line status register */ - ret_val = get_lsr_info(info, argp); - break; - /* - * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - * - mask passed in arg for lines of interest - * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) - * Caller should use TIOCGICOUNT to see which one it was - */ + ret_val = info->closing_wait / (HZ / 100); + break; + case TIOCGSERIAL: + ret_val = get_serial_info(info, argp); + break; + case TIOCSSERIAL: + ret_val = set_serial_info(info, argp); + break; + case TIOCSERGETLSR: /* Get line status register */ + ret_val = get_lsr_info(info, argp); + break; + /* + * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change + * - mask passed in arg for lines of interest + * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) + * Caller should use TIOCGICOUNT to see which one it was + */ case TIOCMIWAIT: - CY_LOCK(info, flags); - /* note the counters on entry */ - cprev = info->icount; - CY_UNLOCK(info, flags); - while (1) { - interruptible_sleep_on(&info->delta_msr_wait); - /* see if a signal did it */ - if (signal_pending(current)) { - return -ERESTARTSYS; - } - CY_LOCK(info, flags); - cnow = info->icount; /* atomic copy */ + /* note the counters on entry */ + cprev = info->icount; CY_UNLOCK(info, flags); + while (1) { + interruptible_sleep_on(&info->delta_msr_wait); + /* see if a signal did it */ + if (signal_pending(current)) { + return -ERESTARTSYS; + } - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) { - return -EIO; /* no change => error */ - } - if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || - ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || - ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { - return 0; - } - cprev = cnow; - } - /* NOTREACHED */ + CY_LOCK(info, flags); + cnow = info->icount; /* atomic copy */ + CY_UNLOCK(info, flags); - /* - * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) - * Return: write counters to the user passed counter struct - * NB: both 1->0 and 0->1 transitions are counted except for - * RI where only 0->1 is counted. - */ + if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && + cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) { + return -EIO; /* no change => error */ + } + if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || + ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || + ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || + ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { + return 0; + } + cprev = cnow; + } + /* NOTREACHED */ + + /* + * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) + * Return: write counters to the user passed counter struct + * NB: both 1->0 and 0->1 transitions are counted except for + * RI where only 0->1 is counted. + */ case TIOCGICOUNT: - CY_LOCK(info, flags); - cnow = info->icount; - CY_UNLOCK(info, flags); - p_cuser = argp; - ret_val = put_user(cnow.cts, &p_cuser->cts); - if (ret_val) return ret_val; - ret_val = put_user(cnow.dsr, &p_cuser->dsr); - if (ret_val) return ret_val; - ret_val = put_user(cnow.rng, &p_cuser->rng); - if (ret_val) return ret_val; - ret_val = put_user(cnow.dcd, &p_cuser->dcd); - if (ret_val) return ret_val; - ret_val = put_user(cnow.rx, &p_cuser->rx); - if (ret_val) return ret_val; - ret_val = put_user(cnow.tx, &p_cuser->tx); - if (ret_val) return ret_val; - ret_val = put_user(cnow.frame, &p_cuser->frame); - if (ret_val) return ret_val; - ret_val = put_user(cnow.overrun, &p_cuser->overrun); - if (ret_val) return ret_val; - ret_val = put_user(cnow.parity, &p_cuser->parity); - if (ret_val) return ret_val; - ret_val = put_user(cnow.brk, &p_cuser->brk); - if (ret_val) return ret_val; - ret_val = put_user(cnow.buf_overrun, &p_cuser->buf_overrun); - if (ret_val) return ret_val; - ret_val = 0; - break; - default: - ret_val = -ENOIOCTLCMD; - } + CY_LOCK(info, flags); + cnow = info->icount; + CY_UNLOCK(info, flags); + p_cuser = argp; + ret_val = put_user(cnow.cts, &p_cuser->cts); + if (ret_val) + return ret_val; + ret_val = put_user(cnow.dsr, &p_cuser->dsr); + if (ret_val) + return ret_val; + ret_val = put_user(cnow.rng, &p_cuser->rng); + if (ret_val) + return ret_val; + ret_val = put_user(cnow.dcd, &p_cuser->dcd); + if (ret_val) + return ret_val; + ret_val = put_user(cnow.rx, &p_cuser->rx); + if (ret_val) + return ret_val; + ret_val = put_user(cnow.tx, &p_cuser->tx); + if (ret_val) + return ret_val; + ret_val = put_user(cnow.frame, &p_cuser->frame); + if (ret_val) + return ret_val; + ret_val = put_user(cnow.overrun, &p_cuser->overrun); + if (ret_val) + return ret_val; + ret_val = put_user(cnow.parity, &p_cuser->parity); + if (ret_val) + return ret_val; + ret_val = put_user(cnow.brk, &p_cuser->brk); + if (ret_val) + return ret_val; + ret_val = put_user(cnow.buf_overrun, &p_cuser->buf_overrun); + if (ret_val) + return ret_val; + ret_val = 0; + break; + default: + ret_val = -ENOIOCTLCMD; + } #ifdef CY_DEBUG_OTHER - printk(" cyc:cy_ioctl done\n"); + printk(" cyc:cy_ioctl done\n"); #endif - return ret_val; -} /* cy_ioctl */ - + return ret_val; +} /* cy_ioctl */ /* * This routine allows the tty driver to be notified when @@ -4100,66 +4209,64 @@ cy_ioctl(struct tty_struct *tty, struct file * file, * well-designed tty driver should be prepared to accept the case * where old == NULL, and try to do something rational. */ -static void -cy_set_termios(struct tty_struct *tty, struct termios * old_termios) +static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; #ifdef CY_DEBUG_OTHER - printk("cyc:cy_set_termios ttyC%d\n", info->line); + printk("cyc:cy_set_termios ttyC%d\n", info->line); #endif - if ((tty->termios->c_cflag == old_termios->c_cflag) && - ((tty->termios->c_iflag & (IXON|IXANY)) == - (old_termios->c_iflag & (IXON|IXANY)))) - return; - set_line_char(info); - - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios->c_cflag & CRTSCTS)) { - tty->hw_stopped = 0; - cy_start(tty); - } + if (tty->termios->c_cflag == old_termios->c_cflag && + (tty->termios->c_iflag & (IXON | IXANY)) == + (old_termios->c_iflag & (IXON | IXANY))) + return; + set_line_char(info); + + if ((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + cy_start(tty); + } #if 0 - /* - * No need to wake up processes in open wait, since they - * sample the CLOCAL flag once, and don't recheck it. - * XXX It's not clear whether the current behavior is correct - * or not. Hence, this may change..... - */ - if (!(old_termios->c_cflag & CLOCAL) && - (tty->termios->c_cflag & CLOCAL)) - wake_up_interruptible(&info->open_wait); + /* + * No need to wake up processes in open wait, since they + * sample the CLOCAL flag once, and don't recheck it. + * XXX It's not clear whether the current behavior is correct + * or not. Hence, this may change..... + */ + if (!(old_termios->c_cflag & CLOCAL) && + (tty->termios->c_cflag & CLOCAL)) + wake_up_interruptible(&info->open_wait); #endif - - return; -} /* cy_set_termios */ +} /* cy_set_termios */ /* This function is used to send a high-priority XON/XOFF character to the device. */ -static void -cy_send_xchar (struct tty_struct *tty, char ch) +static void cy_send_xchar(struct tty_struct *tty, char ch) { - struct cyclades_port *info = (struct cyclades_port *) tty->driver_data; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; int card, channel; - if (serial_paranoia_check (info, tty->name, "cy_send_xchar")) + if (serial_paranoia_check(info, tty->name, "cy_send_xchar")) return; - info->x_char = ch; + info->x_char = ch; if (ch) - cy_start (tty); + cy_start(tty); card = info->card; channel = info->line - cy_card[card].first_line; - if (IS_CYC_Z (cy_card[card])) { - if (ch == STOP_CHAR (tty)) - cyz_issue_cmd (&cy_card[card], channel, C_CM_SENDXOFF, 0L); - else if (ch == START_CHAR (tty)) - cyz_issue_cmd (&cy_card[card], channel, C_CM_SENDXON, 0L); + if (IS_CYC_Z(cy_card[card])) { + if (ch == STOP_CHAR(tty)) + cyz_issue_cmd(&cy_card[card], channel, C_CM_SENDXOFF, + 0L); + else if (ch == START_CHAR(tty)) + cyz_issue_cmd(&cy_card[card], channel, C_CM_SENDXON, + 0L); } } @@ -4167,260 +4274,248 @@ cy_send_xchar (struct tty_struct *tty, char ch) that incoming characters should be throttled because the input buffers are close to full. */ -static void -cy_throttle(struct tty_struct * tty) +static void cy_throttle(struct tty_struct *tty) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - unsigned long flags; - void __iomem *base_addr; - int card,chip,channel,index; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + unsigned long flags; + void __iomem *base_addr; + int card, chip, channel, index; #ifdef CY_DEBUG_THROTTLE - char buf[64]; + char buf[64]; - printk("cyc:throttle %s: %d....ttyC%d\n", - tty_name(tty, buf), - tty->ldisc.chars_in_buffer(tty), info->line); + printk("cyc:throttle %s: %d....ttyC%d\n", tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty), info->line); #endif - if (serial_paranoia_check(info, tty->name, "cy_throttle")){ - return; - } - - card = info->card; - - if (I_IXOFF(tty)) { - if (!IS_CYC_Z (cy_card[card])) - cy_send_xchar (tty, STOP_CHAR (tty)); - else - info->throttle = 1; - } - - if (tty->termios->c_cflag & CRTSCTS) { - channel = info->line - cy_card[card].first_line; - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index); - - CY_LOCK(info, flags); - cy_writeb(base_addr+(CyCAR<<index), (u_char)channel); - if (info->rtsdtr_inv) { - cy_writeb(base_addr+(CyMSVR2<<index), ~CyDTR); - } else { - cy_writeb(base_addr+(CyMSVR1<<index), ~CyRTS); - } - CY_UNLOCK(info, flags); - } else { - info->throttle = 1; - } - } + if (serial_paranoia_check(info, tty->name, "cy_throttle")) { + return; + } - return; -} /* cy_throttle */ + card = info->card; + + if (I_IXOFF(tty)) { + if (!IS_CYC_Z(cy_card[card])) + cy_send_xchar(tty, STOP_CHAR(tty)); + else + info->throttle = 1; + } + if (tty->termios->c_cflag & CRTSCTS) { + channel = info->line - cy_card[card].first_line; + if (!IS_CYC_Z(cy_card[card])) { + chip = channel >> 2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = cy_card[card].base_addr + + (cy_chip_offset[chip] << index); + + CY_LOCK(info, flags); + cy_writeb(base_addr + (CyCAR << index), + (u_char) channel); + if (info->rtsdtr_inv) { + cy_writeb(base_addr + (CyMSVR2 << index), + ~CyDTR); + } else { + cy_writeb(base_addr + (CyMSVR1 << index), + ~CyRTS); + } + CY_UNLOCK(info, flags); + } else { + info->throttle = 1; + } + } +} /* cy_throttle */ /* * This routine notifies the tty driver that it should signal * that characters can now be sent to the tty without fear of * overrunning the input buffers of the line disciplines. */ -static void -cy_unthrottle(struct tty_struct * tty) +static void cy_unthrottle(struct tty_struct *tty) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - unsigned long flags; - void __iomem *base_addr; - int card,chip,channel,index; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + unsigned long flags; + void __iomem *base_addr; + int card, chip, channel, index; #ifdef CY_DEBUG_THROTTLE - char buf[64]; - - printk("cyc:unthrottle %s: %d....ttyC%d\n", - tty_name(tty, buf), - tty->ldisc.chars_in_buffer(tty), info->line); -#endif + char buf[64]; - if (serial_paranoia_check(info, tty->name, "cy_unthrottle")){ - return; - } + printk("cyc:unthrottle %s: %d....ttyC%d\n", tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty), info->line); +#endif - if (I_IXOFF(tty)) { - if (info->x_char) - info->x_char = 0; - else - cy_send_xchar (tty, START_CHAR (tty)); - } - - if (tty->termios->c_cflag & CRTSCTS) { - card = info->card; - channel = info->line - cy_card[card].first_line; - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index); - - CY_LOCK(info, flags); - cy_writeb(base_addr+(CyCAR<<index), (u_char)channel); - if (info->rtsdtr_inv) { - cy_writeb(base_addr+(CyMSVR2<<index), CyDTR); - } else { - cy_writeb(base_addr+(CyMSVR1<<index), CyRTS); - } - CY_UNLOCK(info, flags); - } else { - info->throttle = 0; + if (serial_paranoia_check(info, tty->name, "cy_unthrottle")) { + return; } - } - return; -} /* cy_unthrottle */ + if (I_IXOFF(tty)) { + if (info->x_char) + info->x_char = 0; + else + cy_send_xchar(tty, START_CHAR(tty)); + } + if (tty->termios->c_cflag & CRTSCTS) { + card = info->card; + channel = info->line - cy_card[card].first_line; + if (!IS_CYC_Z(cy_card[card])) { + chip = channel >> 2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = cy_card[card].base_addr + + (cy_chip_offset[chip] << index); + + CY_LOCK(info, flags); + cy_writeb(base_addr + (CyCAR << index), + (u_char) channel); + if (info->rtsdtr_inv) { + cy_writeb(base_addr + (CyMSVR2 << index), + CyDTR); + } else { + cy_writeb(base_addr + (CyMSVR1 << index), + CyRTS); + } + CY_UNLOCK(info, flags); + } else { + info->throttle = 0; + } + } +} /* cy_unthrottle */ /* cy_start and cy_stop provide software output flow control as a function of XON/XOFF, software CTS, and other such stuff. */ -static void -cy_stop(struct tty_struct *tty) +static void cy_stop(struct tty_struct *tty) { - struct cyclades_card *cinfo; - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - void __iomem *base_addr; - int chip,channel,index; - unsigned long flags; + struct cyclades_card *cinfo; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + void __iomem *base_addr; + int chip, channel, index; + unsigned long flags; #ifdef CY_DEBUG_OTHER - printk("cyc:cy_stop ttyC%d\n", info->line); /* */ + printk("cyc:cy_stop ttyC%d\n", info->line); /* */ #endif - if (serial_paranoia_check(info, tty->name, "cy_stop")) - return; - - cinfo = &cy_card[info->card]; - channel = info->line - cinfo->first_line; - if (!IS_CYC_Z(*cinfo)) { - index = cinfo->bus_index; - chip = channel>>2; - channel &= 0x03; - base_addr = cy_card[info->card].base_addr + (cy_chip_offset[chip]<<index); - - CY_LOCK(info, flags); - cy_writeb(base_addr+(CyCAR<<index), - (u_char)(channel & 0x0003)); /* index channel */ - cy_writeb(base_addr+(CySRER<<index), - cy_readb(base_addr+(CySRER<<index)) & ~CyTxRdy); - CY_UNLOCK(info, flags); - } else { - // Nothing to do! - } + if (serial_paranoia_check(info, tty->name, "cy_stop")) + return; - return; -} /* cy_stop */ + cinfo = &cy_card[info->card]; + channel = info->line - cinfo->first_line; + if (!IS_CYC_Z(*cinfo)) { + index = cinfo->bus_index; + chip = channel >> 2; + channel &= 0x03; + base_addr = cy_card[info->card].base_addr + + (cy_chip_offset[chip] << index); + CY_LOCK(info, flags); + cy_writeb(base_addr + (CyCAR << index), + (u_char)(channel & 0x0003)); /* index channel */ + cy_writeb(base_addr + (CySRER << index), + cy_readb(base_addr + (CySRER << index)) & ~CyTxRdy); + CY_UNLOCK(info, flags); + } else { + /* Nothing to do! */ + } +} /* cy_stop */ -static void -cy_start(struct tty_struct *tty) +static void cy_start(struct tty_struct *tty) { - struct cyclades_card *cinfo; - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - void __iomem *base_addr; - int chip,channel,index; - unsigned long flags; + struct cyclades_card *cinfo; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + void __iomem *base_addr; + int chip, channel, index; + unsigned long flags; #ifdef CY_DEBUG_OTHER - printk("cyc:cy_start ttyC%d\n", info->line); /* */ + printk("cyc:cy_start ttyC%d\n", info->line); /* */ #endif - if (serial_paranoia_check(info, tty->name, "cy_start")) - return; - - cinfo = &cy_card[info->card]; - channel = info->line - cinfo->first_line; - index = cinfo->bus_index; - if (!IS_CYC_Z(*cinfo)) { - chip = channel>>2; - channel &= 0x03; - base_addr = cy_card[info->card].base_addr + (cy_chip_offset[chip]<<index); - - CY_LOCK(info, flags); - cy_writeb(base_addr+(CyCAR<<index), - (u_char)(channel & 0x0003)); /* index channel */ - cy_writeb(base_addr+(CySRER<<index), - cy_readb(base_addr+(CySRER<<index)) | CyTxRdy); - CY_UNLOCK(info, flags); - } else { - // Nothing to do! - } + if (serial_paranoia_check(info, tty->name, "cy_start")) + return; - return; -} /* cy_start */ + cinfo = &cy_card[info->card]; + channel = info->line - cinfo->first_line; + index = cinfo->bus_index; + if (!IS_CYC_Z(*cinfo)) { + chip = channel >> 2; + channel &= 0x03; + base_addr = cy_card[info->card].base_addr + + (cy_chip_offset[chip] << index); + CY_LOCK(info, flags); + cy_writeb(base_addr + (CyCAR << index), (u_char) (channel & 0x0003)); /* index channel */ + cy_writeb(base_addr + (CySRER << index), + cy_readb(base_addr + (CySRER << index)) | CyTxRdy); + CY_UNLOCK(info, flags); + } else { + /* Nothing to do! */ + } +} /* cy_start */ -static void -cy_flush_buffer(struct tty_struct *tty) +static void cy_flush_buffer(struct tty_struct *tty) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - int card, channel, retval; - unsigned long flags; - + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + int card, channel, retval; + unsigned long flags; + #ifdef CY_DEBUG_IO - printk("cyc:cy_flush_buffer ttyC%d\n", info->line); /* */ + printk("cyc:cy_flush_buffer ttyC%d\n", info->line); /* */ #endif - if (serial_paranoia_check(info, tty->name, "cy_flush_buffer")) - return; - - card = info->card; - channel = (info->line) - (cy_card[card].first_line); + if (serial_paranoia_check(info, tty->name, "cy_flush_buffer")) + return; - CY_LOCK(info, flags); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - CY_UNLOCK(info, flags); + card = info->card; + channel = (info->line) - (cy_card[card].first_line); - if (IS_CYC_Z(cy_card[card])) { /* If it is a Z card, flush the on-board - buffers as well */ CY_LOCK(info, flags); - retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_TX, 0L); - if (retval != 0) { - printk("cyc: flush_buffer retval on ttyC%d was %x\n", - info->line, retval); - } + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; CY_UNLOCK(info, flags); - } - tty_wakeup(tty); - wake_up_interruptible(&tty->write_wait); -} /* cy_flush_buffer */ + if (IS_CYC_Z(cy_card[card])) { /* If it is a Z card, flush the on-board + buffers as well */ + CY_LOCK(info, flags); + retval = + cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_TX, 0L); + if (retval != 0) { + printk("cyc: flush_buffer retval on ttyC%d was %x\n", + info->line, retval); + } + CY_UNLOCK(info, flags); + } + tty_wakeup(tty); + wake_up_interruptible(&tty->write_wait); +} /* cy_flush_buffer */ /* * cy_hangup() --- called by tty_hangup() when a hangup is signaled. */ -static void -cy_hangup(struct tty_struct *tty) +static void cy_hangup(struct tty_struct *tty) { - struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; - + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + #ifdef CY_DEBUG_OTHER - printk("cyc:cy_hangup ttyC%d\n", info->line); /* */ + printk("cyc:cy_hangup ttyC%d\n", info->line); /* */ #endif - if (serial_paranoia_check(info, tty->name, "cy_hangup")) - return; + if (serial_paranoia_check(info, tty->name, "cy_hangup")) + return; - cy_flush_buffer(tty); - shutdown(info); - info->event = 0; - info->count = 0; + cy_flush_buffer(tty); + shutdown(info); + info->event = 0; + info->count = 0; #ifdef CY_DEBUG_COUNT - printk("cyc:cy_hangup (%d): setting count to 0\n", current->pid); + printk("cyc:cy_hangup (%d): setting count to 0\n", current->pid); #endif - info->tty = NULL; - info->flags &= ~ASYNC_NORMAL_ACTIVE; - wake_up_interruptible(&info->open_wait); -} /* cy_hangup */ - + info->tty = NULL; + info->flags &= ~ASYNC_NORMAL_ACTIVE; + wake_up_interruptible(&info->open_wait); +} /* cy_hangup */ /* * --------------------------------------------------------------------- @@ -4433,82 +4528,84 @@ cy_hangup(struct tty_struct *tty) /* initialize chips on Cyclom-Y card -- return number of valid chips (which is number of ports/4) */ static unsigned short __init -cyy_init_card(void __iomem *true_base_addr,int index) +cyy_init_card(void __iomem * true_base_addr, int index) { - unsigned int chip_number; - void __iomem *base_addr; - - cy_writeb(true_base_addr+(Cy_HwReset<<index), 0); - /* Cy_HwReset is 0x1400 */ - cy_writeb(true_base_addr+(Cy_ClrIntr<<index), 0); - /* Cy_ClrIntr is 0x1800 */ - udelay(500L); - - for(chip_number=0; chip_number<CyMAX_CHIPS_PER_CARD; chip_number++){ - base_addr = true_base_addr + (cy_chip_offset[chip_number]<<index); - mdelay(1); - if(cy_readb(base_addr+(CyCCR<<index)) != 0x00){ - /************* - printk(" chip #%d at %#6lx is never idle (CCR != 0)\n", - chip_number, (unsigned long)base_addr); - *************/ - return chip_number; - } - - cy_writeb(base_addr+(CyGFRCR<<index), 0); - udelay(10L); - - /* The Cyclom-16Y does not decode address bit 9 and therefore - cannot distinguish between references to chip 0 and a non- - existent chip 4. If the preceding clearing of the supposed - chip 4 GFRCR register appears at chip 0, there is no chip 4 - and this must be a Cyclom-16Y, not a Cyclom-32Ye. - */ - if (chip_number == 4 - && cy_readb(true_base_addr - + (cy_chip_offset[0]<<index) - + (CyGFRCR<<index)) == 0){ - return chip_number; - } - - cy_writeb(base_addr+(CyCCR<<index), CyCHIP_RESET); - mdelay(1); - - if(cy_readb(base_addr+(CyGFRCR<<index)) == 0x00){ - /* - printk(" chip #%d at %#6lx is not responding ", - chip_number, (unsigned long)base_addr); - printk("(GFRCR stayed 0)\n", - */ - return chip_number; - } - if((0xf0 & (cy_readb(base_addr+(CyGFRCR<<index)))) != 0x40){ - /* - printk(" chip #%d at %#6lx is not valid (GFRCR == %#2x)\n", - chip_number, (unsigned long)base_addr, - base_addr[CyGFRCR<<index]); - */ - return chip_number; - } - cy_writeb(base_addr+(CyGCR<<index), CyCH0_SERIAL); - if (cy_readb(base_addr+(CyGFRCR<<index)) >= CD1400_REV_J){ - /* It is a CD1400 rev. J or later */ - /* Impossible to reach 5ms with this chip. - Changed to 2ms instead (f = 500 Hz). */ - cy_writeb(base_addr+(CyPPR<<index), CyCLOCK_60_2MS); - } else { - /* f = 200 Hz */ - cy_writeb(base_addr+(CyPPR<<index), CyCLOCK_25_5MS); - } + unsigned int chip_number; + void __iomem *base_addr; + + cy_writeb(true_base_addr + (Cy_HwReset << index), 0); + /* Cy_HwReset is 0x1400 */ + cy_writeb(true_base_addr + (Cy_ClrIntr << index), 0); + /* Cy_ClrIntr is 0x1800 */ + udelay(500L); + + for (chip_number = 0; chip_number < CyMAX_CHIPS_PER_CARD; chip_number++) { + base_addr = + true_base_addr + (cy_chip_offset[chip_number] << index); + mdelay(1); + if (cy_readb(base_addr + (CyCCR << index)) != 0x00) { + /************* + printk(" chip #%d at %#6lx is never idle (CCR != 0)\n", + chip_number, (unsigned long)base_addr); + *************/ + return chip_number; + } + + cy_writeb(base_addr + (CyGFRCR << index), 0); + udelay(10L); + + /* The Cyclom-16Y does not decode address bit 9 and therefore + cannot distinguish between references to chip 0 and a non- + existent chip 4. If the preceding clearing of the supposed + chip 4 GFRCR register appears at chip 0, there is no chip 4 + and this must be a Cyclom-16Y, not a Cyclom-32Ye. + */ + if (chip_number == 4 && cy_readb(true_base_addr + + (cy_chip_offset[0] << index) + + (CyGFRCR << index)) == 0) { + return chip_number; + } + + cy_writeb(base_addr + (CyCCR << index), CyCHIP_RESET); + mdelay(1); + + if (cy_readb(base_addr + (CyGFRCR << index)) == 0x00) { + /* + printk(" chip #%d at %#6lx is not responding ", + chip_number, (unsigned long)base_addr); + printk("(GFRCR stayed 0)\n", + */ + return chip_number; + } + if ((0xf0 & (cy_readb(base_addr + (CyGFRCR << index)))) != + 0x40) { + /* + printk(" chip #%d at %#6lx is not valid (GFRCR == " + "%#2x)\n", + chip_number, (unsigned long)base_addr, + base_addr[CyGFRCR<<index]); + */ + return chip_number; + } + cy_writeb(base_addr + (CyGCR << index), CyCH0_SERIAL); + if (cy_readb(base_addr + (CyGFRCR << index)) >= CD1400_REV_J) { + /* It is a CD1400 rev. J or later */ + /* Impossible to reach 5ms with this chip. + Changed to 2ms instead (f = 500 Hz). */ + cy_writeb(base_addr + (CyPPR << index), CyCLOCK_60_2MS); + } else { + /* f = 200 Hz */ + cy_writeb(base_addr + (CyPPR << index), CyCLOCK_25_5MS); + } - /* - printk(" chip #%d at %#6lx is rev 0x%2x\n", - chip_number, (unsigned long)base_addr, - cy_readb(base_addr+(CyGFRCR<<index))); - */ - } - return chip_number; -} /* cyy_init_card */ + /* + printk(" chip #%d at %#6lx is rev 0x%2x\n", + chip_number, (unsigned long)base_addr, + cy_readb(base_addr+(CyGFRCR<<index))); + */ + } + return chip_number; +} /* cyy_init_card */ /* * --------------------------------------------------------------------- @@ -4516,126 +4613,124 @@ cyy_init_card(void __iomem *true_base_addr,int index) * sets global variables and return the number of ISA boards found. * --------------------------------------------------------------------- */ -static int __init -cy_detect_isa(void) +static int __init cy_detect_isa(void) { #ifdef CONFIG_ISA - unsigned short cy_isa_irq,nboard; - void __iomem *cy_isa_address; - unsigned short i,j,cy_isa_nchan; + unsigned short cy_isa_irq, nboard; + void __iomem *cy_isa_address; + unsigned short i, j, cy_isa_nchan; #ifdef MODULE - int isparam = 0; + int isparam = 0; #endif - nboard = 0; + nboard = 0; #ifdef MODULE /* Check for module parameters */ - for(i = 0 ; i < NR_CARDS; i++) { - if (maddr[i] || i) { - isparam = 1; - cy_isa_addresses[i] = maddr[i]; - } - if (!maddr[i]) - break; + for (i = 0; i < NR_CARDS; i++) { + if (maddr[i] || i) { + isparam = 1; + cy_isa_addresses[i] = maddr[i]; + } + if (!maddr[i]) + break; } #endif - /* scan the address table probing for Cyclom-Y/ISA boards */ - for (i = 0 ; i < NR_ISA_ADDRS ; i++) { - unsigned int isa_address = cy_isa_addresses[i]; - if (isa_address == 0x0000) { - return(nboard); - } + /* scan the address table probing for Cyclom-Y/ISA boards */ + for (i = 0; i < NR_ISA_ADDRS; i++) { + unsigned int isa_address = cy_isa_addresses[i]; + if (isa_address == 0x0000) { + return nboard; + } - /* probe for CD1400... */ + /* probe for CD1400... */ cy_isa_address = ioremap(isa_address, CyISA_Ywin); - cy_isa_nchan = CyPORTS_PER_CHIP * - cyy_init_card(cy_isa_address,0); - if (cy_isa_nchan == 0) { - continue; - } - + cy_isa_nchan = CyPORTS_PER_CHIP * + cyy_init_card(cy_isa_address, 0); + if (cy_isa_nchan == 0) { + continue; + } #ifdef MODULE if (isparam && irq[i]) - cy_isa_irq = irq[i]; + cy_isa_irq = irq[i]; else #endif - /* find out the board's irq by probing */ - cy_isa_irq = detect_isa_irq(cy_isa_address); - if (cy_isa_irq == 0) { - printk("Cyclom-Y/ISA found at 0x%lx ", - (unsigned long) cy_isa_address); - printk("but the IRQ could not be detected.\n"); - continue; - } - - if((cy_next_channel+cy_isa_nchan) > NR_PORTS) { - printk("Cyclom-Y/ISA found at 0x%lx ", - (unsigned long) cy_isa_address); - printk("but no more channels are available.\n"); - printk("Change NR_PORTS in cyclades.c and recompile kernel.\n"); - return(nboard); - } - /* fill the next cy_card structure available */ - for (j = 0 ; j < NR_CARDS ; j++) { - if (cy_card[j].base_addr == 0) break; - } - if (j == NR_CARDS) { /* no more cy_cards available */ - printk("Cyclom-Y/ISA found at 0x%lx ", - (unsigned long) cy_isa_address); - printk("but no more cards can be used .\n"); - printk("Change NR_CARDS in cyclades.c and recompile kernel.\n"); - return(nboard); - } - - /* allocate IRQ */ - if(request_irq(cy_isa_irq, cyy_interrupt, - IRQF_DISABLED, "Cyclom-Y", &cy_card[j])) - { - printk("Cyclom-Y/ISA found at 0x%lx ", - (unsigned long) cy_isa_address); - printk("but could not allocate IRQ#%d.\n", - cy_isa_irq); - return(nboard); - } - - /* set cy_card */ - cy_card[j].base_addr = cy_isa_address; - cy_card[j].ctl_addr = NULL; - cy_card[j].irq = (int) cy_isa_irq; - cy_card[j].bus_index = 0; - cy_card[j].first_line = cy_next_channel; - cy_card[j].num_chips = cy_isa_nchan/4; - nboard++; - - /* print message */ - printk("Cyclom-Y/ISA #%d: 0x%lx-0x%lx, IRQ%d, ", - j+1, (unsigned long) cy_isa_address, - (unsigned long)(cy_isa_address + (CyISA_Ywin - 1)), - cy_isa_irq); - printk("%d channels starting from port %d.\n", - cy_isa_nchan, cy_next_channel); - cy_next_channel += cy_isa_nchan; - } - return(nboard); + /* find out the board's irq by probing */ + cy_isa_irq = detect_isa_irq(cy_isa_address); + if (cy_isa_irq == 0) { + printk("Cyclom-Y/ISA found at 0x%lx ", + (unsigned long)cy_isa_address); + printk("but the IRQ could not be detected.\n"); + continue; + } + + if ((cy_next_channel + cy_isa_nchan) > NR_PORTS) { + printk("Cyclom-Y/ISA found at 0x%lx ", + (unsigned long)cy_isa_address); + printk("but no more channels are available.\n"); + printk("Change NR_PORTS in cyclades.c and recompile " + "kernel.\n"); + return nboard; + } + /* fill the next cy_card structure available */ + for (j = 0; j < NR_CARDS; j++) { + if (cy_card[j].base_addr == 0) + break; + } + if (j == NR_CARDS) { /* no more cy_cards available */ + printk("Cyclom-Y/ISA found at 0x%lx ", + (unsigned long)cy_isa_address); + printk("but no more cards can be used .\n"); + printk("Change NR_CARDS in cyclades.c and recompile " + "kernel.\n"); + return nboard; + } + + /* allocate IRQ */ + if (request_irq(cy_isa_irq, cyy_interrupt, + IRQF_DISABLED, "Cyclom-Y", &cy_card[j])) { + printk("Cyclom-Y/ISA found at 0x%lx ", + (unsigned long)cy_isa_address); + printk("but could not allocate IRQ#%d.\n", cy_isa_irq); + return nboard; + } + + /* set cy_card */ + cy_card[j].base_addr = cy_isa_address; + cy_card[j].ctl_addr = NULL; + cy_card[j].irq = (int)cy_isa_irq; + cy_card[j].bus_index = 0; + cy_card[j].first_line = cy_next_channel; + cy_card[j].num_chips = cy_isa_nchan / 4; + nboard++; + + /* print message */ + printk("Cyclom-Y/ISA #%d: 0x%lx-0x%lx, IRQ%d, ", + j + 1, (unsigned long)cy_isa_address, + (unsigned long)(cy_isa_address + (CyISA_Ywin - 1)), + cy_isa_irq); + printk("%d channels starting from port %d.\n", + cy_isa_nchan, cy_next_channel); + cy_next_channel += cy_isa_nchan; + } + return nboard; #else - return(0); -#endif /* CONFIG_ISA */ -} /* cy_detect_isa */ + return 0; +#endif /* CONFIG_ISA */ +} /* cy_detect_isa */ -static void -plx_init(void __iomem *addr, uclong initctl) +static void plx_init(void __iomem * addr, uclong initctl) { - /* Reset PLX */ - cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x40000000); - udelay(100L); - cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x40000000); - - /* Reload Config. Registers from EEPROM */ - cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x20000000); - udelay(100L); - cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x20000000); + /* Reset PLX */ + cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x40000000); + udelay(100L); + cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x40000000); + + /* Reload Config. Registers from EEPROM */ + cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x20000000); + udelay(100L); + cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x20000000); } /* @@ -4644,43 +4739,42 @@ plx_init(void __iomem *addr, uclong initctl) * sets global variables and return the number of PCI boards found. * --------------------------------------------------------------------- */ -static int __init -cy_detect_pci(void) +static int __init cy_detect_pci(void) { #ifdef CONFIG_PCI - struct pci_dev *pdev = NULL; - unsigned char cyy_rev_id; - unsigned char cy_pci_irq = 0; - uclong cy_pci_phys0, cy_pci_phys2; - void __iomem *cy_pci_addr0, *cy_pci_addr2; - unsigned short i,j,cy_pci_nchan, plx_ver; - unsigned short device_id,dev_index = 0; - uclong mailbox; - uclong ZeIndex = 0; - void __iomem *Ze_addr0[NR_CARDS], *Ze_addr2[NR_CARDS]; - uclong Ze_phys0[NR_CARDS], Ze_phys2[NR_CARDS]; - unsigned char Ze_irq[NR_CARDS]; - struct pci_dev *Ze_pdev[NR_CARDS]; - - for (i = 0; i < NR_CARDS; i++) { - /* look for a Cyclades card by vendor and device id */ - while((device_id = cy_pci_dev_id[dev_index]) != 0) { - if((pdev = pci_get_device(PCI_VENDOR_ID_CYCLADES, - device_id, pdev)) == NULL) { - dev_index++; /* try next device id */ - } else { - break; /* found a board */ - } - } + struct pci_dev *pdev = NULL; + unsigned char cyy_rev_id; + unsigned char cy_pci_irq = 0; + uclong cy_pci_phys0, cy_pci_phys2; + void __iomem *cy_pci_addr0, *cy_pci_addr2; + unsigned short i, j, cy_pci_nchan, plx_ver; + unsigned short device_id, dev_index = 0; + uclong mailbox; + uclong ZeIndex = 0; + void __iomem *Ze_addr0[NR_CARDS], *Ze_addr2[NR_CARDS]; + uclong Ze_phys0[NR_CARDS], Ze_phys2[NR_CARDS]; + unsigned char Ze_irq[NR_CARDS]; + struct pci_dev *Ze_pdev[NR_CARDS]; + + for (i = 0; i < NR_CARDS; i++) { + /* look for a Cyclades card by vendor and device id */ + while ((device_id = cy_pci_dev_id[dev_index]) != 0) { + if ((pdev = pci_get_device(PCI_VENDOR_ID_CYCLADES, + device_id, pdev)) == NULL) { + dev_index++; /* try next device id */ + } else { + break; /* found a board */ + } + } if (device_id == 0) - break; + break; if (pci_enable_device(pdev)) - continue; + continue; - /* read PCI configuration area */ + /* read PCI configuration area */ cy_pci_irq = pdev->irq; cy_pci_phys0 = pci_resource_start(pdev, 0); cy_pci_phys2 = pci_resource_start(pdev, 2); @@ -4688,482 +4782,497 @@ cy_detect_pci(void) device_id &= ~PCI_DEVICE_ID_MASK; - if ((device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) - || (device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi)){ + if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo || + device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { #ifdef CY_PCI_DEBUG - printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ", - pdev->bus->number, pdev->devfn); - printk("rev_id=%d) IRQ%d\n", - cyy_rev_id, (int)cy_pci_irq); - printk("Cyclom-Y/PCI:found winaddr=0x%lx ctladdr=0x%lx\n", - (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); + printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ", + pdev->bus->number, pdev->devfn); + printk("rev_id=%d) IRQ%d\n", + cyy_rev_id, (int)cy_pci_irq); + printk("Cyclom-Y/PCI:found winaddr=0x%lx " + "ctladdr=0x%lx\n", + (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); #endif - if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { - printk(" Warning: PCI I/O bit incorrectly set. " - "Ignoring it...\n"); - pdev->resource[2].flags &= ~IORESOURCE_IO; - } - - /* Although we don't use this I/O region, we should - request it from the kernel anyway, to avoid problems - with other drivers accessing it. */ - if (pci_request_regions(pdev, "Cyclom-Y") != 0) { - printk(KERN_ERR "cyclades: failed to reserve PCI resources\n"); - continue; - } + if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { + printk(" Warning: PCI I/O bit incorrectly " + "set. Ignoring it...\n"); + pdev->resource[2].flags &= ~IORESOURCE_IO; + } + /* Although we don't use this I/O region, we should + request it from the kernel anyway, to avoid problems + with other drivers accessing it. */ + if (pci_request_regions(pdev, "Cyclom-Y") != 0) { + printk(KERN_ERR "cyclades: failed to reserve " + "PCI resources\n"); + continue; + } #if defined(__alpha__) - if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */ - printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ", - pdev->bus->number, pdev->devfn); - printk("rev_id=%d) IRQ%d\n", - cyy_rev_id, (int)cy_pci_irq); - printk("Cyclom-Y/PCI:found winaddr=0x%lx ctladdr=0x%lx\n", - (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); - printk("Cyclom-Y/PCI not supported for low addresses in " - "Alpha systems.\n"); - i--; - continue; - } + if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */ + printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ", + pdev->bus->number, pdev->devfn); + printk("rev_id=%d) IRQ%d\n", + cyy_rev_id, (int)cy_pci_irq); + printk("Cyclom-Y/PCI:found winaddr=0x%lx " + "ctladdr=0x%lx\n", + (ulong)cy_pci_phys2, + (ulong)cy_pci_phys0); + printk("Cyclom-Y/PCI not supported for low " + "addresses in Alpha systems.\n"); + i--; + continue; + } #endif - cy_pci_addr0 = ioremap(cy_pci_phys0, CyPCI_Yctl); - cy_pci_addr2 = ioremap(cy_pci_phys2, CyPCI_Ywin); + cy_pci_addr0 = ioremap(cy_pci_phys0, CyPCI_Yctl); + cy_pci_addr2 = ioremap(cy_pci_phys2, CyPCI_Ywin); #ifdef CY_PCI_DEBUG - printk("Cyclom-Y/PCI: relocate winaddr=0x%lx ctladdr=0x%lx\n", - (u_long)cy_pci_addr2, (u_long)cy_pci_addr0); + printk("Cyclom-Y/PCI: relocate winaddr=0x%lx " + "ctladdr=0x%lx\n", + (u_long)cy_pci_addr2, (u_long)cy_pci_addr0); #endif - cy_pci_nchan = (unsigned short)(CyPORTS_PER_CHIP * - cyy_init_card(cy_pci_addr2, 1)); - if(cy_pci_nchan == 0) { - printk("Cyclom-Y PCI host card with "); - printk("no Serial-Modules at 0x%lx.\n", - (ulong) cy_pci_phys2); - i--; - continue; - } - if((cy_next_channel+cy_pci_nchan) > NR_PORTS) { - printk("Cyclom-Y/PCI found at 0x%lx ", - (ulong) cy_pci_phys2); - printk("but no channels are available.\n"); - printk("Change NR_PORTS in cyclades.c and recompile kernel.\n"); - return(i); - } - /* fill the next cy_card structure available */ - for (j = 0 ; j < NR_CARDS ; j++) { - if (cy_card[j].base_addr == 0) break; - } - if (j == NR_CARDS) { /* no more cy_cards available */ - printk("Cyclom-Y/PCI found at 0x%lx ", - (ulong) cy_pci_phys2); - printk("but no more cards can be used.\n"); - printk("Change NR_CARDS in cyclades.c and recompile kernel.\n"); - return(i); - } - - /* allocate IRQ */ - if(request_irq(cy_pci_irq, cyy_interrupt, - IRQF_SHARED, "Cyclom-Y", &cy_card[j])) - { - printk("Cyclom-Y/PCI found at 0x%lx ", - (ulong) cy_pci_phys2); - printk("but could not allocate IRQ%d.\n", - cy_pci_irq); - return(i); - } - - /* set cy_card */ - cy_card[j].base_phys = (ulong)cy_pci_phys2; - cy_card[j].ctl_phys = (ulong)cy_pci_phys0; - cy_card[j].base_addr = cy_pci_addr2; - cy_card[j].ctl_addr = cy_pci_addr0; - cy_card[j].irq = (int) cy_pci_irq; - cy_card[j].bus_index = 1; - cy_card[j].first_line = cy_next_channel; - cy_card[j].num_chips = cy_pci_nchan/4; - cy_card[j].pdev = pdev; - - /* enable interrupts in the PCI interface */ - plx_ver = cy_readb(cy_pci_addr2 + CyPLX_VER) & 0x0f; - switch (plx_ver) { - case PLX_9050: - - cy_writeb(cy_pci_addr0+0x4c, 0x43); - break; - - case PLX_9060: - case PLX_9080: - default: /* Old boards, use PLX_9060 */ - - plx_init(cy_pci_addr0, 0x6c); - /* For some yet unknown reason, once the PLX9060 reloads - the EEPROM, the IRQ is lost and, thus, we have to - re-write it to the PCI config. registers. - This will remain here until we find a permanent fix. */ - pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, cy_pci_irq); - - cy_writew(cy_pci_addr0+0x68, - cy_readw(cy_pci_addr0+0x68)|0x0900); - break; - } + cy_pci_nchan = (unsigned short)(CyPORTS_PER_CHIP * + cyy_init_card(cy_pci_addr2, 1)); + if (cy_pci_nchan == 0) { + printk("Cyclom-Y PCI host card with "); + printk("no Serial-Modules at 0x%lx.\n", + (ulong) cy_pci_phys2); + i--; + continue; + } + if ((cy_next_channel + cy_pci_nchan) > NR_PORTS) { + printk("Cyclom-Y/PCI found at 0x%lx ", + (ulong) cy_pci_phys2); + printk("but no channels are available.\n"); + printk("Change NR_PORTS in cyclades.c and " + "recompile kernel.\n"); + return i; + } + /* fill the next cy_card structure available */ + for (j = 0; j < NR_CARDS; j++) { + if (cy_card[j].base_addr == 0) + break; + } + if (j == NR_CARDS) { /* no more cy_cards available */ + printk("Cyclom-Y/PCI found at 0x%lx ", + (ulong) cy_pci_phys2); + printk("but no more cards can be used.\n"); + printk("Change NR_CARDS in cyclades.c and " + "recompile kernel.\n"); + return i; + } + + /* allocate IRQ */ + if (request_irq(cy_pci_irq, cyy_interrupt, + IRQF_SHARED, "Cyclom-Y", &cy_card[j])) { + printk("Cyclom-Y/PCI found at 0x%lx ", + (ulong) cy_pci_phys2); + printk("but could not allocate IRQ%d.\n", + cy_pci_irq); + return i; + } - /* print message */ - printk("Cyclom-Y/PCI #%d: 0x%lx-0x%lx, IRQ%d, ", - j+1, - (ulong)cy_pci_phys2, - (ulong)(cy_pci_phys2 + CyPCI_Ywin - 1), - (int)cy_pci_irq); - printk("%d channels starting from port %d.\n", - cy_pci_nchan, cy_next_channel); - - cy_next_channel += cy_pci_nchan; - }else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo){ - /* print message */ - printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ", - pdev->bus->number, pdev->devfn); - printk("rev_id=%d) IRQ%d\n", - cyy_rev_id, (int)cy_pci_irq); - printk("Cyclades-Z/PCI: found winaddr=0x%lx ctladdr=0x%lx\n", - (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); - printk("Cyclades-Z/PCI not supported for low addresses\n"); - break; - }else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi){ + /* set cy_card */ + cy_card[j].base_phys = (ulong) cy_pci_phys2; + cy_card[j].ctl_phys = (ulong) cy_pci_phys0; + cy_card[j].base_addr = cy_pci_addr2; + cy_card[j].ctl_addr = cy_pci_addr0; + cy_card[j].irq = (int)cy_pci_irq; + cy_card[j].bus_index = 1; + cy_card[j].first_line = cy_next_channel; + cy_card[j].num_chips = cy_pci_nchan / 4; + cy_card[j].pdev = pdev; + + /* enable interrupts in the PCI interface */ + plx_ver = cy_readb(cy_pci_addr2 + CyPLX_VER) & 0x0f; + switch (plx_ver) { + case PLX_9050: + + cy_writeb(cy_pci_addr0 + 0x4c, 0x43); + break; + + case PLX_9060: + case PLX_9080: + default: /* Old boards, use PLX_9060 */ + + plx_init(cy_pci_addr0, 0x6c); + /* For some yet unknown reason, once the PLX9060 reloads + the EEPROM, the IRQ is lost and, thus, we have to + re-write it to the PCI config. registers. + This will remain here until we find a permanent + fix. */ + pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, + cy_pci_irq); + + cy_writew(cy_pci_addr0 + 0x68, + cy_readw(cy_pci_addr0 + + 0x68) | 0x0900); + break; + } + + /* print message */ + printk("Cyclom-Y/PCI #%d: 0x%lx-0x%lx, IRQ%d, ", + j + 1, (ulong)cy_pci_phys2, + (ulong) (cy_pci_phys2 + CyPCI_Ywin - 1), + (int)cy_pci_irq); + printk("%d channels starting from port %d.\n", + cy_pci_nchan, cy_next_channel); + + cy_next_channel += cy_pci_nchan; + } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo) { + /* print message */ + printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ", + pdev->bus->number, pdev->devfn); + printk("rev_id=%d) IRQ%d\n", + cyy_rev_id, (int)cy_pci_irq); + printk("Cyclades-Z/PCI: found winaddr=0x%lx " + "ctladdr=0x%lx\n", + (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); + printk("Cyclades-Z/PCI not supported for low " + "addresses\n"); + break; + } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) { #ifdef CY_PCI_DEBUG - printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ", - pdev->bus->number, pdev->devfn); - printk("rev_id=%d) IRQ%d\n", - cyy_rev_id, (int)cy_pci_irq); - printk("Cyclades-Z/PCI: found winaddr=0x%lx ctladdr=0x%lx\n", - (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); + printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ", + pdev->bus->number, pdev->devfn); + printk("rev_id=%d) IRQ%d\n", + cyy_rev_id, (int)cy_pci_irq); + printk("Cyclades-Z/PCI: found winaddr=0x%lx " + "ctladdr=0x%lx\n", + (ulong) cy_pci_phys2, (ulong) cy_pci_phys0); #endif - cy_pci_addr0 = ioremap(cy_pci_phys0, CyPCI_Zctl); - - /* Disable interrupts on the PLX before resetting it */ - cy_writew(cy_pci_addr0+0x68, - cy_readw(cy_pci_addr0+0x68) & ~0x0900); - - plx_init(cy_pci_addr0, 0x6c); - /* For some yet unknown reason, once the PLX9060 reloads - the EEPROM, the IRQ is lost and, thus, we have to - re-write it to the PCI config. registers. - This will remain here until we find a permanent fix. */ - pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, cy_pci_irq); - - mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 __iomem *) - cy_pci_addr0)->mail_box_0); - - if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { - printk(" Warning: PCI I/O bit incorrectly set. " - "Ignoring it...\n"); - pdev->resource[2].flags &= ~IORESOURCE_IO; - } + cy_pci_addr0 = ioremap(cy_pci_phys0, CyPCI_Zctl); + + /* Disable interrupts on the PLX before resetting it */ + cy_writew(cy_pci_addr0 + 0x68, + cy_readw(cy_pci_addr0 + 0x68) & ~0x0900); + + plx_init(cy_pci_addr0, 0x6c); + /* For some yet unknown reason, once the PLX9060 reloads + the EEPROM, the IRQ is lost and, thus, we have to + re-write it to the PCI config. registers. + This will remain here until we find a permanent + fix. */ + pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, + cy_pci_irq); + + mailbox = + (uclong)cy_readl(&((struct RUNTIME_9060 __iomem *) + cy_pci_addr0)->mail_box_0); + + if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { + printk(" Warning: PCI I/O bit incorrectly " + "set. Ignoring it...\n"); + pdev->resource[2].flags &= ~IORESOURCE_IO; + } - /* Although we don't use this I/O region, we should - request it from the kernel anyway, to avoid problems - with other drivers accessing it. */ - if (pci_request_regions(pdev, "Cyclades-Z") != 0) { - printk(KERN_ERR "cyclades: failed to reserve PCI resources\n"); - continue; - } - - if (mailbox == ZE_V1) { - cy_pci_addr2 = ioremap(cy_pci_phys2, CyPCI_Ze_win); - if (ZeIndex == NR_CARDS) { - printk("Cyclades-Ze/PCI found at 0x%lx ", - (ulong)cy_pci_phys2); - printk("but no more cards can be used.\n"); - printk("Change NR_CARDS in cyclades.c and recompile kernel.\n"); - } else { - Ze_phys0[ZeIndex] = cy_pci_phys0; - Ze_phys2[ZeIndex] = cy_pci_phys2; - Ze_addr0[ZeIndex] = cy_pci_addr0; - Ze_addr2[ZeIndex] = cy_pci_addr2; - Ze_irq[ZeIndex] = cy_pci_irq; - Ze_pdev[ZeIndex] = pdev; - ZeIndex++; - } - i--; - continue; - } else { - cy_pci_addr2 = ioremap(cy_pci_phys2, CyPCI_Zwin); - } + /* Although we don't use this I/O region, we should + request it from the kernel anyway, to avoid problems + with other drivers accessing it. */ + if (pci_request_regions(pdev, "Cyclades-Z") != 0) { + printk(KERN_ERR "cyclades: failed to reserve " + "PCI resources\n"); + continue; + } + + if (mailbox == ZE_V1) { + cy_pci_addr2 = ioremap(cy_pci_phys2, + CyPCI_Ze_win); + if (ZeIndex == NR_CARDS) { + printk("Cyclades-Ze/PCI found at " + "0x%lx but no more cards can " + "be used.\nChange NR_CARDS in " + "cyclades.c and recompile " + "kernel.\n", + (ulong)cy_pci_phys2); + } else { + Ze_phys0[ZeIndex] = cy_pci_phys0; + Ze_phys2[ZeIndex] = cy_pci_phys2; + Ze_addr0[ZeIndex] = cy_pci_addr0; + Ze_addr2[ZeIndex] = cy_pci_addr2; + Ze_irq[ZeIndex] = cy_pci_irq; + Ze_pdev[ZeIndex] = pdev; + ZeIndex++; + } + i--; + continue; + } else { + cy_pci_addr2 = ioremap(cy_pci_phys2,CyPCI_Zwin); + } #ifdef CY_PCI_DEBUG - printk("Cyclades-Z/PCI: relocate winaddr=0x%lx ctladdr=0x%lx\n", - (ulong)cy_pci_addr2, (ulong)cy_pci_addr0); - if (mailbox == ZO_V1) { - cy_writel(&((struct RUNTIME_9060 *) - (cy_pci_addr0))->loc_addr_base, WIN_CREG); - PAUSE - printk("Cyclades-8Zo/PCI: FPGA id %lx, ver %lx\n", - (ulong)(0xff & cy_readl(&((struct CUSTOM_REG *) - (cy_pci_addr2))->fpga_id)), - (ulong)(0xff & cy_readl(&((struct CUSTOM_REG *) - (cy_pci_addr2))->fpga_version))); - cy_writel(&((struct RUNTIME_9060 *) - (cy_pci_addr0))->loc_addr_base, WIN_RAM); - } else { - printk("Cyclades-Z/PCI: New Cyclades-Z board. FPGA not loaded\n"); - } + printk("Cyclades-Z/PCI: relocate winaddr=0x%lx " + "ctladdr=0x%lx\n", + (ulong) cy_pci_addr2, (ulong) cy_pci_addr0); + if (mailbox == ZO_V1) { + cy_writel(&((struct RUNTIME_9060 *) + (cy_pci_addr0))->loc_addr_base, + WIN_CREG); + PAUSE; + printk("Cyclades-8Zo/PCI: FPGA id %lx, ver " + "%lx\n", (ulong) (0xff & + cy_readl(&((struct CUSTOM_REG *) + (cy_pci_addr2))->fpga_id)), + (ulong)(0xff & + cy_readl(&((struct CUSTOM_REG *) + (cy_pci_addr2))-> + fpga_version))); + cy_writel(&((struct RUNTIME_9060 *) + (cy_pci_addr0))->loc_addr_base, + WIN_RAM); + } else { + printk("Cyclades-Z/PCI: New Cyclades-Z board. " + "FPGA not loaded\n"); + } #endif - /* The following clears the firmware id word. This ensures - that the driver will not attempt to talk to the board - until it has been properly initialized. - */ - PAUSE - if ((mailbox == ZO_V1) || (mailbox == ZO_V2)) - cy_writel(cy_pci_addr2 + ID_ADDRESS, 0L); - - /* This must be a Cyclades-8Zo/PCI. The extendable - version will have a different device_id and will - be allocated its maximum number of ports. */ - cy_pci_nchan = 8; - - if((cy_next_channel+cy_pci_nchan) > NR_PORTS) { - printk("Cyclades-8Zo/PCI found at 0x%lx ", - (ulong)cy_pci_phys2); - printk("but no channels are available.\n"); - printk("Change NR_PORTS in cyclades.c and recompile kernel.\n"); - return(i); - } - - /* fill the next cy_card structure available */ - for (j = 0 ; j < NR_CARDS ; j++) { - if (cy_card[j].base_addr == 0) break; - } - if (j == NR_CARDS) { /* no more cy_cards available */ - printk("Cyclades-8Zo/PCI found at 0x%lx ", - (ulong)cy_pci_phys2); - printk("but no more cards can be used.\n"); - printk("Change NR_CARDS in cyclades.c and recompile kernel.\n"); - return(i); - } + /* The following clears the firmware id word. This + ensures that the driver will not attempt to talk to + the board until it has been properly initialized. + */ + PAUSE; + if ((mailbox == ZO_V1) || (mailbox == ZO_V2)) + cy_writel(cy_pci_addr2 + ID_ADDRESS, 0L); + + /* This must be a Cyclades-8Zo/PCI. The extendable + version will have a different device_id and will + be allocated its maximum number of ports. */ + cy_pci_nchan = 8; + + if ((cy_next_channel + cy_pci_nchan) > NR_PORTS) { + printk("Cyclades-8Zo/PCI found at 0x%lx but" + "no channels are available.\nChange " + "NR_PORTS in cyclades.c and recompile " + "kernel.\n", (ulong)cy_pci_phys2); + return i; + } + /* fill the next cy_card structure available */ + for (j = 0; j < NR_CARDS; j++) { + if (cy_card[j].base_addr == 0) + break; + } + if (j == NR_CARDS) { /* no more cy_cards available */ + printk("Cyclades-8Zo/PCI found at 0x%lx but" + "no more cards can be used.\nChange " + "NR_CARDS in cyclades.c and recompile " + "kernel.\n", (ulong)cy_pci_phys2); + return i; + } +#ifdef CONFIG_CYZ_INTR + /* allocate IRQ only if board has an IRQ */ + if ((cy_pci_irq != 0) && (cy_pci_irq != 255)) { + if (request_irq(cy_pci_irq, cyz_interrupt, + IRQF_SHARED, "Cyclades-Z", + &cy_card[j])) { + printk("Cyclom-8Zo/PCI found at 0x%lx " + "but could not allocate " + "IRQ%d.\n", (ulong)cy_pci_phys2, + cy_pci_irq); + return i; + } + } +#endif /* CONFIG_CYZ_INTR */ + + /* set cy_card */ + cy_card[j].base_phys = cy_pci_phys2; + cy_card[j].ctl_phys = cy_pci_phys0; + cy_card[j].base_addr = cy_pci_addr2; + cy_card[j].ctl_addr = cy_pci_addr0; + cy_card[j].irq = (int)cy_pci_irq; + cy_card[j].bus_index = 1; + cy_card[j].first_line = cy_next_channel; + cy_card[j].num_chips = -1; + cy_card[j].pdev = pdev; + + /* print message */ #ifdef CONFIG_CYZ_INTR - /* allocate IRQ only if board has an IRQ */ - if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) { - if(request_irq(cy_pci_irq, cyz_interrupt, - IRQF_SHARED, "Cyclades-Z", &cy_card[j])) - { - printk("Cyclom-8Zo/PCI found at 0x%lx ", - (ulong) cy_pci_phys2); - printk("but could not allocate IRQ%d.\n", - cy_pci_irq); - return(i); - } + /* don't report IRQ if board is no IRQ */ + if ((cy_pci_irq != 0) && (cy_pci_irq != 255)) + printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, " + "IRQ%d, ", j + 1, (ulong)cy_pci_phys2, + (ulong) (cy_pci_phys2 + CyPCI_Zwin - 1), + (int)cy_pci_irq); + else +#endif /* CONFIG_CYZ_INTR */ + printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, ", + j + 1, (ulong)cy_pci_phys2, + (ulong)(cy_pci_phys2 + CyPCI_Zwin - 1)); + + printk("%d channels starting from port %d.\n", + cy_pci_nchan, cy_next_channel); + cy_next_channel += cy_pci_nchan; } -#endif /* CONFIG_CYZ_INTR */ - - - /* set cy_card */ - cy_card[j].base_phys = cy_pci_phys2; - cy_card[j].ctl_phys = cy_pci_phys0; - cy_card[j].base_addr = cy_pci_addr2; - cy_card[j].ctl_addr = cy_pci_addr0; - cy_card[j].irq = (int) cy_pci_irq; - cy_card[j].bus_index = 1; - cy_card[j].first_line = cy_next_channel; - cy_card[j].num_chips = -1; - cy_card[j].pdev = pdev; + } - /* print message */ -#ifdef CONFIG_CYZ_INTR - /* don't report IRQ if board is no IRQ */ - if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) - printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, IRQ%d, ", - j+1,(ulong)cy_pci_phys2, - (ulong)(cy_pci_phys2 + CyPCI_Zwin - 1), - (int)cy_pci_irq); - else -#endif /* CONFIG_CYZ_INTR */ - printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, ", - j+1,(ulong)cy_pci_phys2, - (ulong)(cy_pci_phys2 + CyPCI_Zwin - 1)); - - printk("%d channels starting from port %d.\n", - cy_pci_nchan,cy_next_channel); - cy_next_channel += cy_pci_nchan; - } - } - - for (; ZeIndex != 0 && i < NR_CARDS; i++) { - cy_pci_phys0 = Ze_phys0[0]; - cy_pci_phys2 = Ze_phys2[0]; - cy_pci_addr0 = Ze_addr0[0]; - cy_pci_addr2 = Ze_addr2[0]; - cy_pci_irq = Ze_irq[0]; - pdev = Ze_pdev[0]; - for (j = 0 ; j < ZeIndex-1 ; j++) { - Ze_phys0[j] = Ze_phys0[j+1]; - Ze_phys2[j] = Ze_phys2[j+1]; - Ze_addr0[j] = Ze_addr0[j+1]; - Ze_addr2[j] = Ze_addr2[j+1]; - Ze_irq[j] = Ze_irq[j+1]; - Ze_pdev[j] = Ze_pdev[j+1]; - } - ZeIndex--; - mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 __iomem *) - cy_pci_addr0)->mail_box_0); + for (; ZeIndex != 0 && i < NR_CARDS; i++) { + cy_pci_phys0 = Ze_phys0[0]; + cy_pci_phys2 = Ze_phys2[0]; + cy_pci_addr0 = Ze_addr0[0]; + cy_pci_addr2 = Ze_addr2[0]; + cy_pci_irq = Ze_irq[0]; + pdev = Ze_pdev[0]; + for (j = 0; j < ZeIndex - 1; j++) { + Ze_phys0[j] = Ze_phys0[j + 1]; + Ze_phys2[j] = Ze_phys2[j + 1]; + Ze_addr0[j] = Ze_addr0[j + 1]; + Ze_addr2[j] = Ze_addr2[j + 1]; + Ze_irq[j] = Ze_irq[j + 1]; + Ze_pdev[j] = Ze_pdev[j + 1]; + } + ZeIndex--; + mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 __iomem *) + cy_pci_addr0)->mail_box_0); #ifdef CY_PCI_DEBUG - printk("Cyclades-Z/PCI: relocate winaddr=0x%lx ctladdr=0x%lx\n", - (ulong)cy_pci_addr2, (ulong)cy_pci_addr0); - printk("Cyclades-Z/PCI: New Cyclades-Z board. FPGA not loaded\n"); + printk("Cyclades-Z/PCI: relocate winaddr=0x%lx ctladdr=0x%lx\n", + (ulong)cy_pci_addr2, (ulong)cy_pci_addr0); + printk("Cyclades-Z/PCI: New Cyclades-Z board. FPGA not " + "loaded\n"); #endif - PAUSE - /* This must be the new Cyclades-Ze/PCI. */ - cy_pci_nchan = ZE_V1_NPORTS; - - if((cy_next_channel+cy_pci_nchan) > NR_PORTS) { - printk("Cyclades-Ze/PCI found at 0x%lx ", - (ulong)cy_pci_phys2); - printk("but no channels are available.\n"); - printk("Change NR_PORTS in cyclades.c and recompile kernel.\n"); - return(i); - } - - /* fill the next cy_card structure available */ - for (j = 0 ; j < NR_CARDS ; j++) { - if (cy_card[j].base_addr == 0) break; - } - if (j == NR_CARDS) { /* no more cy_cards available */ - printk("Cyclades-Ze/PCI found at 0x%lx ", - (ulong)cy_pci_phys2); - printk("but no more cards can be used.\n"); - printk("Change NR_CARDS in cyclades.c and recompile kernel.\n"); - return(i); - } + PAUSE; + /* This must be the new Cyclades-Ze/PCI. */ + cy_pci_nchan = ZE_V1_NPORTS; + + if ((cy_next_channel + cy_pci_nchan) > NR_PORTS) { + printk("Cyclades-Ze/PCI found at 0x%lx but no channels " + "are available.\nChange NR_PORTS in cyclades.c " + "and recompile kernel.\n", + (ulong) cy_pci_phys2); + return i; + } + /* fill the next cy_card structure available */ + for (j = 0; j < NR_CARDS; j++) { + if (cy_card[j].base_addr == 0) + break; + } + if (j == NR_CARDS) { /* no more cy_cards available */ + printk("Cyclades-Ze/PCI found at 0x%lx but no more " + "cards can be used.\nChange NR_CARDS in " + "cyclades.c and recompile kernel.\n", + (ulong) cy_pci_phys2); + return i; + } #ifdef CONFIG_CYZ_INTR - /* allocate IRQ only if board has an IRQ */ - if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) { - if(request_irq(cy_pci_irq, cyz_interrupt, - IRQF_SHARED, "Cyclades-Z", &cy_card[j])) - { - printk("Cyclom-Ze/PCI found at 0x%lx ", - (ulong) cy_pci_phys2); - printk("but could not allocate IRQ%d.\n", - cy_pci_irq); - return(i); - } + /* allocate IRQ only if board has an IRQ */ + if ((cy_pci_irq != 0) && (cy_pci_irq != 255)) { + if (request_irq(cy_pci_irq, cyz_interrupt, + IRQF_SHARED, "Cyclades-Z", + &cy_card[j])) { + printk("Cyclom-Ze/PCI found at 0x%lx ", + (ulong) cy_pci_phys2); + printk("but could not allocate IRQ%d.\n", + cy_pci_irq); + return i; + } } -#endif /* CONFIG_CYZ_INTR */ - - /* set cy_card */ - cy_card[j].base_phys = cy_pci_phys2; - cy_card[j].ctl_phys = cy_pci_phys0; - cy_card[j].base_addr = cy_pci_addr2; - cy_card[j].ctl_addr = cy_pci_addr0; - cy_card[j].irq = (int) cy_pci_irq; - cy_card[j].bus_index = 1; - cy_card[j].first_line = cy_next_channel; - cy_card[j].num_chips = -1; +#endif /* CONFIG_CYZ_INTR */ + + /* set cy_card */ + cy_card[j].base_phys = cy_pci_phys2; + cy_card[j].ctl_phys = cy_pci_phys0; + cy_card[j].base_addr = cy_pci_addr2; + cy_card[j].ctl_addr = cy_pci_addr0; + cy_card[j].irq = (int)cy_pci_irq; + cy_card[j].bus_index = 1; + cy_card[j].first_line = cy_next_channel; + cy_card[j].num_chips = -1; cy_card[j].pdev = pdev; - /* print message */ + /* print message */ #ifdef CONFIG_CYZ_INTR /* don't report IRQ if board is no IRQ */ - if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) - printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, IRQ%d, ", - j+1,(ulong)cy_pci_phys2, - (ulong)(cy_pci_phys2 + CyPCI_Ze_win - 1), - (int)cy_pci_irq); + if ((cy_pci_irq != 0) && (cy_pci_irq != 255)) + printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, IRQ%d, ", + j + 1, (ulong) cy_pci_phys2, + (ulong) (cy_pci_phys2 + CyPCI_Ze_win - 1), + (int)cy_pci_irq); else -#endif /* CONFIG_CYZ_INTR */ - printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, ", - j+1,(ulong)cy_pci_phys2, - (ulong)(cy_pci_phys2 + CyPCI_Ze_win - 1)); - - printk("%d channels starting from port %d.\n", - cy_pci_nchan,cy_next_channel); - cy_next_channel += cy_pci_nchan; - } +#endif /* CONFIG_CYZ_INTR */ + printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, ", + j + 1, (ulong) cy_pci_phys2, + (ulong) (cy_pci_phys2 + CyPCI_Ze_win - 1)); + + printk("%d channels starting from port %d.\n", + cy_pci_nchan, cy_next_channel); + cy_next_channel += cy_pci_nchan; + } if (ZeIndex != 0) { - printk("Cyclades-Ze/PCI found at 0x%x ", - (unsigned int) Ze_phys2[0]); - printk("but no more cards can be used.\n"); - printk("Change NR_CARDS in cyclades.c and recompile kernel.\n"); + printk("Cyclades-Ze/PCI found at 0x%x but no more cards can be " + "used.\nChange NR_CARDS in cyclades.c and recompile " + "kernel.\n", (unsigned int)Ze_phys2[0]); } - return(i); + return i; #else - return(0); -#endif /* ifdef CONFIG_PCI */ -} /* cy_detect_pci */ - + return 0; +#endif /* ifdef CONFIG_PCI */ +} /* cy_detect_pci */ /* * This routine prints out the appropriate serial driver version number * and identifies which options were configured into this driver. */ -static inline void -show_version(void) +static inline void show_version(void) { - char *rcsvers, *rcsdate, *tmp; - rcsvers = strchr(rcsid, ' '); rcsvers++; - tmp = strchr(rcsvers, ' '); *tmp++ = '\0'; - rcsdate = strchr(tmp, ' '); rcsdate++; - tmp = strrchr(rcsdate, ' '); *tmp = '\0'; - printk("Cyclades driver %s %s\n", - rcsvers, rcsdate); - printk(" built %s %s\n", - __DATE__, __TIME__); -} /* show_version */ - -static int + printk("Cyclades driver " CY_VERSION "\n"); + printk(" built %s %s\n", __DATE__, __TIME__); +} /* show_version */ + +static int cyclades_get_proc_info(char *buf, char **start, off_t offset, int length, - int *eof, void *data) + int *eof, void *data) { - struct cyclades_port *info; - int i; - int len=0; - off_t begin=0; - off_t pos=0; - int size; - __u32 cur_jifs = jiffies; - - size = sprintf(buf, "Dev TimeOpen BytesOut IdleOut BytesIn IdleIn Overruns Ldisc\n"); - - pos += size; - len += size; - - /* Output one line for each known port */ - for (i = 0; i < NR_PORTS && cy_port[i].line >= 0; i++) { - info = &cy_port[i]; - - if (info->count) - size = sprintf(buf+len, - "%3d %8lu %10lu %8lu %10lu %8lu %9lu %6ld\n", - info->line, - JIFFIES_DIFF(info->idle_stats.in_use, cur_jifs) / HZ, - info->idle_stats.xmit_bytes, - JIFFIES_DIFF(info->idle_stats.xmit_idle, cur_jifs) / HZ, - info->idle_stats.recv_bytes, - JIFFIES_DIFF(info->idle_stats.recv_idle, cur_jifs) / HZ, - info->idle_stats.overruns, - (long) info->tty->ldisc.num); - else - size = sprintf(buf+len, - "%3d %8lu %10lu %8lu %10lu %8lu %9lu %6ld\n", - info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L); + struct cyclades_port *info; + int i; + int len = 0; + off_t begin = 0; + off_t pos = 0; + int size; + __u32 cur_jifs = jiffies; + + size = sprintf(buf, "Dev TimeOpen BytesOut IdleOut BytesIn " + "IdleIn Overruns Ldisc\n"); + + pos += size; len += size; - pos = begin + len; - if (pos < offset) { - len = 0; - begin = pos; + /* Output one line for each known port */ + for (i = 0; i < NR_PORTS && cy_port[i].line >= 0; i++) { + info = &cy_port[i]; + + if (info->count) + size = sprintf(buf + len, "%3d %8lu %10lu %8lu %10lu " + "%8lu %9lu %6ld\n", info->line, + (cur_jifs - info->idle_stats.in_use) / HZ, + info->idle_stats.xmit_bytes, + (cur_jifs - info->idle_stats.xmit_idle) / HZ, + info->idle_stats.recv_bytes, + (cur_jifs - info->idle_stats.recv_idle) / HZ, + info->idle_stats.overruns, + (long)info->tty->ldisc.num); + else + size = sprintf(buf + len, "%3d %8lu %10lu %8lu %10lu " + "%8lu %9lu %6ld\n", + info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L); + len += size; + pos = begin + len; + + if (pos < offset) { + len = 0; + begin = pos; + } + if (pos > offset + length) + goto done; } - if (pos > offset + length) - goto done; - } - *eof = 1; + *eof = 1; done: - *start = buf + (offset - begin); /* Start of wanted data */ - len -= (offset - begin); /* Start slop */ - if (len > length) - len = length; /* Ending slop */ - if (len < 0) - len = 0; - return len; + *start = buf + (offset - begin); /* Start of wanted data */ + len -= (offset - begin); /* Start slop */ + if (len > length) + len = length; /* Ending slop */ + if (len < 0) + len = 0; + return len; } /* The serial driver boot-time initialization code! @@ -5185,290 +5294,288 @@ done: */ static const struct tty_operations cy_ops = { - .open = cy_open, - .close = cy_close, - .write = cy_write, - .put_char = cy_put_char, - .flush_chars = cy_flush_chars, - .write_room = cy_write_room, - .chars_in_buffer = cy_chars_in_buffer, - .flush_buffer = cy_flush_buffer, - .ioctl = cy_ioctl, - .throttle = cy_throttle, - .unthrottle = cy_unthrottle, - .set_termios = cy_set_termios, - .stop = cy_stop, - .start = cy_start, - .hangup = cy_hangup, - .break_ctl = cy_break, - .wait_until_sent = cy_wait_until_sent, - .read_proc = cyclades_get_proc_info, - .tiocmget = cy_tiocmget, - .tiocmset = cy_tiocmset, + .open = cy_open, + .close = cy_close, + .write = cy_write, + .put_char = cy_put_char, + .flush_chars = cy_flush_chars, + .write_room = cy_write_room, + .chars_in_buffer = cy_chars_in_buffer, + .flush_buffer = cy_flush_buffer, + .ioctl = cy_ioctl, + .throttle = cy_throttle, + .unthrottle = cy_unthrottle, + .set_termios = cy_set_termios, + .stop = cy_stop, + .start = cy_start, + .hangup = cy_hangup, + .break_ctl = cy_break, + .wait_until_sent = cy_wait_until_sent, + .read_proc = cyclades_get_proc_info, + .tiocmget = cy_tiocmget, + .tiocmset = cy_tiocmset, }; -static int __init -cy_init(void) +static int __init cy_init(void) { - struct cyclades_port *info; - struct cyclades_card *cinfo; - int number_z_boards = 0; - int board,port,i,index; - unsigned long mailbox; - unsigned short chip_number; - int nports; - - cy_serial_driver = alloc_tty_driver(NR_PORTS); - if (!cy_serial_driver) - return -ENOMEM; - show_version(); - - /* Initialize the tty_driver structure */ - - cy_serial_driver->owner = THIS_MODULE; - cy_serial_driver->driver_name = "cyclades"; - cy_serial_driver->name = "ttyC"; - cy_serial_driver->major = CYCLADES_MAJOR; - cy_serial_driver->minor_start = 0; - cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL; - cy_serial_driver->subtype = SERIAL_TYPE_NORMAL; - cy_serial_driver->init_termios = tty_std_termios; - cy_serial_driver->init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; - cy_serial_driver->flags = TTY_DRIVER_REAL_RAW; - tty_set_operations(cy_serial_driver, &cy_ops); - - if (tty_register_driver(cy_serial_driver)) - panic("Couldn't register Cyclades serial driver\n"); - - for (i = 0; i < NR_CARDS; i++) { - /* base_addr=0 indicates board not found */ - cy_card[i].base_addr = NULL; - } - - /* the code below is responsible to find the boards. Each different - type of board has its own detection routine. If a board is found, - the next cy_card structure available is set by the detection - routine. These functions are responsible for checking the - availability of cy_card and cy_port data structures and updating - the cy_next_channel. */ - - /* look for isa boards */ - cy_isa_nboard = cy_detect_isa(); - - /* look for pci boards */ - cy_pci_nboard = cy_detect_pci(); - - cy_nboard = cy_isa_nboard + cy_pci_nboard; - - /* invalidate remaining cy_card structures */ - for (i = 0 ; i < NR_CARDS ; i++) { - if (cy_card[i].base_addr == 0) { - cy_card[i].first_line = -1; - cy_card[i].ctl_addr = NULL; - cy_card[i].irq = 0; - cy_card[i].bus_index = 0; - cy_card[i].first_line = 0; - cy_card[i].num_chips = 0; - } - } - /* invalidate remaining cy_port structures */ - for (i = cy_next_channel ; i < NR_PORTS ; i++) { - cy_port[i].line = -1; - cy_port[i].magic = -1; - } - - /* initialize per-port data structures for each valid board found */ - for (board = 0 ; board < cy_nboard ; board++) { - cinfo = &cy_card[board]; - if (cinfo->num_chips == -1) { /* Cyclades-Z */ - number_z_boards++; - mailbox = cy_readl(&((struct RUNTIME_9060 __iomem *) - cy_card[board].ctl_addr)->mail_box_0); - nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8; - cinfo->intr_enabled = 0; - cinfo->nports = 0; /* Will be correctly set later, after - Z FW is loaded */ - spin_lock_init(&cinfo->card_lock); - for (port = cinfo->first_line ; - port < cinfo->first_line + nports; - port++) - { - info = &cy_port[port]; - info->magic = CYCLADES_MAGIC; - info->type = PORT_STARTECH; - info->card = board; - info->line = port; - info->chip_rev = 0; - info->flags = STD_COM_FLAGS; - info->tty = NULL; - if (mailbox == ZO_V1) - info->xmit_fifo_size = CYZ_FIFO_SIZE; - else - info->xmit_fifo_size = 4 * CYZ_FIFO_SIZE; - info->cor1 = 0; - info->cor2 = 0; - info->cor3 = 0; - info->cor4 = 0; - info->cor5 = 0; - info->tbpr = 0; - info->tco = 0; - info->rbpr = 0; - info->rco = 0; - info->custom_divisor = 0; - info->close_delay = 5*HZ/10; - info->closing_wait = CLOSING_WAIT_DELAY; - info->icount.cts = info->icount.dsr = - info->icount.rng = info->icount.dcd = 0; - info->icount.rx = info->icount.tx = 0; - info->icount.frame = info->icount.parity = 0; - info->icount.overrun = info->icount.brk = 0; - info->x_char = 0; - info->event = 0; - info->count = 0; - info->blocked_open = 0; - info->default_threshold = 0; - info->default_timeout = 0; - INIT_WORK(&info->tqueue, do_softint); - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); - init_waitqueue_head(&info->shutdown_wait); - init_waitqueue_head(&info->delta_msr_wait); - /* info->session */ - /* info->pgrp */ - info->read_status_mask = 0; - /* info->timeout */ - /* Bentson's vars */ - info->jiffies[0] = 0; - info->jiffies[1] = 0; - info->jiffies[2] = 0; - info->rflush_count = 0; + struct cyclades_port *info; + struct cyclades_card *cinfo; + int number_z_boards = 0; + int board, port, i, index; + unsigned long mailbox; + unsigned short chip_number; + int nports; + + cy_serial_driver = alloc_tty_driver(NR_PORTS); + if (!cy_serial_driver) + return -ENOMEM; + show_version(); + + /* Initialize the tty_driver structure */ + + cy_serial_driver->owner = THIS_MODULE; + cy_serial_driver->driver_name = "cyclades"; + cy_serial_driver->name = "ttyC"; + cy_serial_driver->major = CYCLADES_MAJOR; + cy_serial_driver->minor_start = 0; + cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL; + cy_serial_driver->subtype = SERIAL_TYPE_NORMAL; + cy_serial_driver->init_termios = tty_std_termios; + cy_serial_driver->init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + cy_serial_driver->flags = TTY_DRIVER_REAL_RAW; + tty_set_operations(cy_serial_driver, &cy_ops); + + if (tty_register_driver(cy_serial_driver)) + panic("Couldn't register Cyclades serial driver\n"); + + for (i = 0; i < NR_CARDS; i++) { + /* base_addr=0 indicates board not found */ + cy_card[i].base_addr = NULL; + } + + /* the code below is responsible to find the boards. Each different + type of board has its own detection routine. If a board is found, + the next cy_card structure available is set by the detection + routine. These functions are responsible for checking the + availability of cy_card and cy_port data structures and updating + the cy_next_channel. */ + + /* look for isa boards */ + cy_isa_nboard = cy_detect_isa(); + + /* look for pci boards */ + cy_pci_nboard = cy_detect_pci(); + + cy_nboard = cy_isa_nboard + cy_pci_nboard; + + /* invalidate remaining cy_card structures */ + for (i = 0; i < NR_CARDS; i++) { + if (cy_card[i].base_addr == 0) { + cy_card[i].first_line = -1; + cy_card[i].ctl_addr = NULL; + cy_card[i].irq = 0; + cy_card[i].bus_index = 0; + cy_card[i].first_line = 0; + cy_card[i].num_chips = 0; + } + } + /* invalidate remaining cy_port structures */ + for (i = cy_next_channel; i < NR_PORTS; i++) { + cy_port[i].line = -1; + cy_port[i].magic = -1; + } + + /* initialize per-port data structures for each valid board found */ + for (board = 0; board < cy_nboard; board++) { + cinfo = &cy_card[board]; + if (cinfo->num_chips == -1) { /* Cyclades-Z */ + number_z_boards++; + mailbox = cy_readl(&((struct RUNTIME_9060 __iomem *) + cy_card[board].ctl_addr)-> + mail_box_0); + nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8; + cinfo->intr_enabled = 0; + cinfo->nports = 0; /* Will be correctly set later, after + Z FW is loaded */ + spin_lock_init(&cinfo->card_lock); + for (port = cinfo->first_line; + port < cinfo->first_line + nports; port++) { + info = &cy_port[port]; + info->magic = CYCLADES_MAGIC; + info->type = PORT_STARTECH; + info->card = board; + info->line = port; + info->chip_rev = 0; + info->flags = STD_COM_FLAGS; + info->tty = NULL; + if (mailbox == ZO_V1) + info->xmit_fifo_size = CYZ_FIFO_SIZE; + else + info->xmit_fifo_size = + 4 * CYZ_FIFO_SIZE; + info->cor1 = 0; + info->cor2 = 0; + info->cor3 = 0; + info->cor4 = 0; + info->cor5 = 0; + info->tbpr = 0; + info->tco = 0; + info->rbpr = 0; + info->rco = 0; + info->custom_divisor = 0; + info->close_delay = 5 * HZ / 10; + info->closing_wait = CLOSING_WAIT_DELAY; + info->icount.cts = info->icount.dsr = + info->icount.rng = info->icount.dcd = 0; + info->icount.rx = info->icount.tx = 0; + info->icount.frame = info->icount.parity = 0; + info->icount.overrun = info->icount.brk = 0; + info->x_char = 0; + info->event = 0; + info->count = 0; + info->blocked_open = 0; + info->default_threshold = 0; + info->default_timeout = 0; + INIT_WORK(&info->tqueue, do_softint); + init_waitqueue_head(&info->open_wait); + init_waitqueue_head(&info->close_wait); + init_waitqueue_head(&info->shutdown_wait); + init_waitqueue_head(&info->delta_msr_wait); + /* info->session */ + /* info->pgrp */ + info->read_status_mask = 0; + /* info->timeout */ + /* Bentson's vars */ + info->jiffies[0] = 0; + info->jiffies[1] = 0; + info->jiffies[2] = 0; + info->rflush_count = 0; #ifdef CONFIG_CYZ_INTR - init_timer(&cyz_rx_full_timer[port]); - cyz_rx_full_timer[port].function = NULL; + init_timer(&cyz_rx_full_timer[port]); + cyz_rx_full_timer[port].function = NULL; #endif - } - continue; - }else{ /* Cyclom-Y of some kind*/ - index = cinfo->bus_index; - spin_lock_init(&cinfo->card_lock); - cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips; - for (port = cinfo->first_line ; - port < cinfo->first_line + cinfo->nports ; - port++) - { - info = &cy_port[port]; - info->magic = CYCLADES_MAGIC; - info->type = PORT_CIRRUS; - info->card = board; - info->line = port; - info->flags = STD_COM_FLAGS; - info->tty = NULL; - info->xmit_fifo_size = CyMAX_CHAR_FIFO; - info->cor1 = CyPARITY_NONE|Cy_1_STOP|Cy_8_BITS; - info->cor2 = CyETC; - info->cor3 = 0x08; /* _very_ small rcv threshold */ - info->cor4 = 0; - info->cor5 = 0; - info->custom_divisor = 0; - info->close_delay = 5*HZ/10; - info->closing_wait = CLOSING_WAIT_DELAY; - info->icount.cts = info->icount.dsr = - info->icount.rng = info->icount.dcd = 0; - info->icount.rx = info->icount.tx = 0; - info->icount.frame = info->icount.parity = 0; - info->icount.overrun = info->icount.brk = 0; - chip_number = (port - cinfo->first_line) / 4; - if ((info->chip_rev = - cy_readb(cinfo->base_addr + - (cy_chip_offset[chip_number]<<index) + - (CyGFRCR<<index))) >= CD1400_REV_J) { - /* It is a CD1400 rev. J or later */ - info->tbpr = baud_bpr_60[13]; /* Tx BPR */ - info->tco = baud_co_60[13]; /* Tx CO */ - info->rbpr = baud_bpr_60[13]; /* Rx BPR */ - info->rco = baud_co_60[13]; /* Rx CO */ - info->rflow = 0; - info->rtsdtr_inv = 1; - } else { - info->tbpr = baud_bpr_25[13]; /* Tx BPR */ - info->tco = baud_co_25[13]; /* Tx CO */ - info->rbpr = baud_bpr_25[13]; /* Rx BPR */ - info->rco = baud_co_25[13]; /* Rx CO */ - info->rflow = 0; - info->rtsdtr_inv = 0; - } - info->x_char = 0; - info->event = 0; - info->count = 0; - info->blocked_open = 0; - info->default_threshold = 0; - info->default_timeout = 0; - INIT_WORK(&info->tqueue, do_softint); - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); - init_waitqueue_head(&info->shutdown_wait); - init_waitqueue_head(&info->delta_msr_wait); - /* info->session */ - /* info->pgrp */ - info->read_status_mask = - CyTIMEOUT| CySPECHAR| CyBREAK - | CyPARITY| CyFRAME| CyOVERRUN; - /* info->timeout */ - } - } - } + } + continue; + } else { /* Cyclom-Y of some kind */ + index = cinfo->bus_index; + spin_lock_init(&cinfo->card_lock); + cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips; + for (port = cinfo->first_line; + port < cinfo->first_line + cinfo->nports; port++) { + info = &cy_port[port]; + info->magic = CYCLADES_MAGIC; + info->type = PORT_CIRRUS; + info->card = board; + info->line = port; + info->flags = STD_COM_FLAGS; + info->tty = NULL; + info->xmit_fifo_size = CyMAX_CHAR_FIFO; + info->cor1 = + CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS; + info->cor2 = CyETC; + info->cor3 = 0x08; /* _very_ small rcv threshold */ + info->cor4 = 0; + info->cor5 = 0; + info->custom_divisor = 0; + info->close_delay = 5 * HZ / 10; + info->closing_wait = CLOSING_WAIT_DELAY; + info->icount.cts = info->icount.dsr = + info->icount.rng = info->icount.dcd = 0; + info->icount.rx = info->icount.tx = 0; + info->icount.frame = info->icount.parity = 0; + info->icount.overrun = info->icount.brk = 0; + chip_number = (port - cinfo->first_line) / 4; + if ((info->chip_rev = + cy_readb(cinfo->base_addr + + (cy_chip_offset[chip_number] << + index) + (CyGFRCR << index))) >= + CD1400_REV_J) { + /* It is a CD1400 rev. J or later */ + info->tbpr = baud_bpr_60[13]; /* Tx BPR */ + info->tco = baud_co_60[13]; /* Tx CO */ + info->rbpr = baud_bpr_60[13]; /* Rx BPR */ + info->rco = baud_co_60[13]; /* Rx CO */ + info->rflow = 0; + info->rtsdtr_inv = 1; + } else { + info->tbpr = baud_bpr_25[13]; /* Tx BPR */ + info->tco = baud_co_25[13]; /* Tx CO */ + info->rbpr = baud_bpr_25[13]; /* Rx BPR */ + info->rco = baud_co_25[13]; /* Rx CO */ + info->rflow = 0; + info->rtsdtr_inv = 0; + } + info->x_char = 0; + info->event = 0; + info->count = 0; + info->blocked_open = 0; + info->default_threshold = 0; + info->default_timeout = 0; + INIT_WORK(&info->tqueue, do_softint); + init_waitqueue_head(&info->open_wait); + init_waitqueue_head(&info->close_wait); + init_waitqueue_head(&info->shutdown_wait); + init_waitqueue_head(&info->delta_msr_wait); + /* info->session */ + /* info->pgrp */ + info->read_status_mask = + CyTIMEOUT | CySPECHAR | CyBREAK + | CyPARITY | CyFRAME | CyOVERRUN; + /* info->timeout */ + } + } + } #ifndef CONFIG_CYZ_INTR - if (number_z_boards && !cyz_timeron){ - cyz_timeron++; - cyz_timerlist.expires = jiffies + 1; - add_timer(&cyz_timerlist); + if (number_z_boards && !cyz_timeron) { + cyz_timeron++; + cyz_timerlist.expires = jiffies + 1; + add_timer(&cyz_timerlist); #ifdef CY_PCI_DEBUG - printk("Cyclades-Z polling initialized\n"); + printk("Cyclades-Z polling initialized\n"); #endif - } -#endif /* CONFIG_CYZ_INTR */ + } +#endif /* CONFIG_CYZ_INTR */ + + return 0; - return 0; - -} /* cy_init */ +} /* cy_init */ -static void __exit -cy_cleanup_module(void) +static void __exit cy_cleanup_module(void) { - int i, e1; + int i, e1; #ifndef CONFIG_CYZ_INTR - if (cyz_timeron){ - cyz_timeron = 0; - del_timer(&cyz_timerlist); - } + if (cyz_timeron){ + cyz_timeron = 0; + del_timer(&cyz_timerlist); + } #endif /* CONFIG_CYZ_INTR */ - if ((e1 = tty_unregister_driver(cy_serial_driver))) - printk("cyc: failed to unregister Cyclades serial driver(%d)\n", - e1); + if ((e1 = tty_unregister_driver(cy_serial_driver))) + printk("cyc: failed to unregister Cyclades serial driver(%d)\n", + e1); - put_tty_driver(cy_serial_driver); + put_tty_driver(cy_serial_driver); - for (i = 0; i < NR_CARDS; i++) { - if (cy_card[i].base_addr) { - iounmap(cy_card[i].base_addr); - if (cy_card[i].ctl_addr) - iounmap(cy_card[i].ctl_addr); - if (cy_card[i].irq + for (i = 0; i < NR_CARDS; i++) { + if (cy_card[i].base_addr) { + iounmap(cy_card[i].base_addr); + if (cy_card[i].ctl_addr) + iounmap(cy_card[i].ctl_addr); + if (cy_card[i].irq #ifndef CONFIG_CYZ_INTR - && cy_card[i].num_chips != -1 /* not a Z card */ + && cy_card[i].num_chips != -1 /* not a Z card */ #endif /* CONFIG_CYZ_INTR */ - ) - free_irq(cy_card[i].irq, &cy_card[i]); + ) + free_irq(cy_card[i].irq, &cy_card[i]); #ifdef CONFIG_PCI - if (cy_card[i].pdev) - pci_release_regions(cy_card[i].pdev); + if (cy_card[i].pdev) + pci_release_regions(cy_card[i].pdev); #endif - } - } + } + } } /* cy_cleanup_module */ module_init(cy_init); diff --git a/drivers/char/drm/drm_ioc32.c b/drivers/char/drm/drm_ioc32.c index d4f87452008..fafeb34f89d 100644 --- a/drivers/char/drm/drm_ioc32.c +++ b/drivers/char/drm/drm_ioc32.c @@ -102,7 +102,7 @@ static int compat_drm_version(struct file *file, unsigned int cmd, &version->desc)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_VERSION, (unsigned long)version); if (err) return err; @@ -143,7 +143,7 @@ static int compat_drm_getunique(struct file *file, unsigned int cmd, &u->unique)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_GET_UNIQUE, (unsigned long)u); if (err) return err; @@ -172,7 +172,7 @@ static int compat_drm_setunique(struct file *file, unsigned int cmd, &u->unique)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_SET_UNIQUE, (unsigned long)u); } @@ -203,7 +203,7 @@ static int compat_drm_getmap(struct file *file, unsigned int cmd, if (__put_user(idx, &map->offset)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_GET_MAP, (unsigned long)map); if (err) return err; @@ -244,7 +244,7 @@ static int compat_drm_addmap(struct file *file, unsigned int cmd, || __put_user(m32.flags, &map->flags)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_ADD_MAP, (unsigned long)map); if (err) return err; @@ -282,7 +282,7 @@ static int compat_drm_rmmap(struct file *file, unsigned int cmd, if (__put_user((void *)(unsigned long)handle, &map->handle)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_RM_MAP, (unsigned long)map); } @@ -312,7 +312,7 @@ static int compat_drm_getclient(struct file *file, unsigned int cmd, if (__put_user(idx, &client->idx)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_GET_CLIENT, (unsigned long)client); if (err) return err; @@ -349,7 +349,7 @@ static int compat_drm_getstats(struct file *file, unsigned int cmd, if (!access_ok(VERIFY_WRITE, stats, sizeof(*stats))) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_GET_STATS, (unsigned long)stats); if (err) return err; @@ -393,7 +393,7 @@ static int compat_drm_addbufs(struct file *file, unsigned int cmd, || __put_user(agp_start, &buf->agp_start)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_ADD_BUFS, (unsigned long)buf); if (err) return err; @@ -425,7 +425,7 @@ static int compat_drm_markbufs(struct file *file, unsigned int cmd, || __put_user(b32.high_mark, &buf->high_mark)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_MARK_BUFS, (unsigned long)buf); } @@ -467,7 +467,7 @@ static int compat_drm_infobufs(struct file *file, unsigned int cmd, || __put_user(list, &request->list)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_INFO_BUFS, (unsigned long)request); if (err) return err; @@ -529,7 +529,7 @@ static int compat_drm_mapbufs(struct file *file, unsigned int cmd, || __put_user(list, &request->list)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_MAP_BUFS, (unsigned long)request); if (err) return err; @@ -576,7 +576,7 @@ static int compat_drm_freebufs(struct file *file, unsigned int cmd, &request->list)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_FREE_BUFS, (unsigned long)request); } @@ -603,7 +603,7 @@ static int compat_drm_setsareactx(struct file *file, unsigned int cmd, &request->handle)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_SET_SAREA_CTX, (unsigned long)request); } @@ -626,7 +626,7 @@ static int compat_drm_getsareactx(struct file *file, unsigned int cmd, if (__put_user(ctx_id, &request->ctx_id)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_GET_SAREA_CTX, (unsigned long)request); if (err) return err; @@ -662,7 +662,7 @@ static int compat_drm_resctx(struct file *file, unsigned int cmd, &res->contexts)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_RES_CTX, (unsigned long)res); if (err) return err; @@ -716,7 +716,7 @@ static int compat_drm_dma(struct file *file, unsigned int cmd, &d->request_sizes)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_DMA, (unsigned long)d); if (err) return err; @@ -749,7 +749,7 @@ static int compat_drm_agp_enable(struct file *file, unsigned int cmd, if (put_user(m32.mode, &mode->mode)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_AGP_ENABLE, (unsigned long)mode); } @@ -779,7 +779,7 @@ static int compat_drm_agp_info(struct file *file, unsigned int cmd, if (!access_ok(VERIFY_WRITE, info, sizeof(*info))) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_AGP_INFO, (unsigned long)info); if (err) return err; @@ -825,7 +825,7 @@ static int compat_drm_agp_alloc(struct file *file, unsigned int cmd, || __put_user(req32.type, &request->type)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_AGP_ALLOC, (unsigned long)request); if (err) return err; @@ -833,7 +833,7 @@ static int compat_drm_agp_alloc(struct file *file, unsigned int cmd, if (__get_user(req32.handle, &request->handle) || __get_user(req32.physical, &request->physical) || copy_to_user(argp, &req32, sizeof(req32))) { - drm_ioctl(file->f_dentry->d_inode, file, + drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_AGP_FREE, (unsigned long)request); return -EFAULT; } @@ -854,7 +854,7 @@ static int compat_drm_agp_free(struct file *file, unsigned int cmd, || __put_user(handle, &request->handle)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_AGP_FREE, (unsigned long)request); } @@ -879,7 +879,7 @@ static int compat_drm_agp_bind(struct file *file, unsigned int cmd, || __put_user(req32.offset, &request->offset)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_AGP_BIND, (unsigned long)request); } @@ -896,7 +896,7 @@ static int compat_drm_agp_unbind(struct file *file, unsigned int cmd, || __put_user(handle, &request->handle)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_AGP_UNBIND, (unsigned long)request); } #endif /* __OS_HAS_AGP */ @@ -921,7 +921,7 @@ static int compat_drm_sg_alloc(struct file *file, unsigned int cmd, || __put_user(x, &request->size)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_SG_ALLOC, (unsigned long)request); if (err) return err; @@ -948,7 +948,7 @@ static int compat_drm_sg_free(struct file *file, unsigned int cmd, || __put_user(x << PAGE_SHIFT, &request->handle)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_SG_FREE, (unsigned long)request); } @@ -988,7 +988,7 @@ static int compat_drm_wait_vblank(struct file *file, unsigned int cmd, || __put_user(req32.request.signal, &request->request.signal)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_WAIT_VBLANK, (unsigned long)request); if (err) return err; @@ -1060,7 +1060,7 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (fn != NULL) ret = (*fn) (filp, cmd, arg); else - ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); + ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); unlock_kernel(); return ret; diff --git a/drivers/char/drm/i915_ioc32.c b/drivers/char/drm/i915_ioc32.c index 296248cdc76..1fe68a251b7 100644 --- a/drivers/char/drm/i915_ioc32.c +++ b/drivers/char/drm/i915_ioc32.c @@ -66,7 +66,7 @@ static int compat_i915_batchbuffer(struct file *file, unsigned int cmd, &batchbuffer->cliprects)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_I915_BATCHBUFFER, (unsigned long)batchbuffer); } @@ -102,7 +102,7 @@ static int compat_i915_cmdbuffer(struct file *file, unsigned int cmd, &cmdbuffer->cliprects)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_I915_CMDBUFFER, (unsigned long)cmdbuffer); } @@ -125,7 +125,7 @@ static int compat_i915_irq_emit(struct file *file, unsigned int cmd, &request->irq_seq)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_I915_IRQ_EMIT, (unsigned long)request); } typedef struct drm_i915_getparam32 { @@ -149,7 +149,7 @@ static int compat_i915_getparam(struct file *file, unsigned int cmd, &request->value)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_I915_GETPARAM, (unsigned long)request); } @@ -178,7 +178,7 @@ static int compat_i915_alloc(struct file *file, unsigned int cmd, &request->region_offset)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_I915_ALLOC, (unsigned long)request); } @@ -215,7 +215,7 @@ long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (fn != NULL) ret = (*fn) (filp, cmd, arg); else - ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); + ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); unlock_kernel(); return ret; diff --git a/drivers/char/drm/mga_ioc32.c b/drivers/char/drm/mga_ioc32.c index 54a18eb2fc0..30d00478dde 100644 --- a/drivers/char/drm/mga_ioc32.c +++ b/drivers/char/drm/mga_ioc32.c @@ -100,7 +100,7 @@ static int compat_mga_init(struct file *file, unsigned int cmd, if (err) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_MGA_INIT, (unsigned long)init); } @@ -125,7 +125,7 @@ static int compat_mga_getparam(struct file *file, unsigned int cmd, &getparam->value)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam); } @@ -166,7 +166,7 @@ static int compat_mga_dma_bootstrap(struct file *file, unsigned int cmd, || __put_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_MGA_DMA_BOOTSTRAP, (unsigned long)dma_bootstrap); if (err) @@ -224,7 +224,7 @@ long mga_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (fn != NULL) ret = (*fn) (filp, cmd, arg); else - ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); + ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); unlock_kernel(); return ret; diff --git a/drivers/char/drm/r128_ioc32.c b/drivers/char/drm/r128_ioc32.c index 9dd6d4116e4..d3cb676eee8 100644 --- a/drivers/char/drm/r128_ioc32.c +++ b/drivers/char/drm/r128_ioc32.c @@ -95,7 +95,7 @@ static int compat_r128_init(struct file *file, unsigned int cmd, &init->agp_textures_offset)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_R128_INIT, (unsigned long)init); } @@ -129,7 +129,7 @@ static int compat_r128_depth(struct file *file, unsigned int cmd, &depth->mask)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_R128_DEPTH, (unsigned long)depth); } @@ -153,7 +153,7 @@ static int compat_r128_stipple(struct file *file, unsigned int cmd, &stipple->mask)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_R128_STIPPLE, (unsigned long)stipple); } @@ -178,7 +178,7 @@ static int compat_r128_getparam(struct file *file, unsigned int cmd, &getparam->value)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_R128_GETPARAM, (unsigned long)getparam); } @@ -214,7 +214,7 @@ long r128_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (fn != NULL) ret = (*fn) (filp, cmd, arg); else - ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); + ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); unlock_kernel(); return ret; diff --git a/drivers/char/drm/radeon_ioc32.c b/drivers/char/drm/radeon_ioc32.c index 0ccfd3618ff..1f1f9cc055a 100644 --- a/drivers/char/drm/radeon_ioc32.c +++ b/drivers/char/drm/radeon_ioc32.c @@ -92,7 +92,7 @@ static int compat_radeon_cp_init(struct file *file, unsigned int cmd, &init->gart_textures_offset)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_RADEON_CP_INIT, (unsigned long)init); } @@ -125,7 +125,7 @@ static int compat_radeon_cp_clear(struct file *file, unsigned int cmd, &clr->depth_boxes)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_RADEON_CLEAR, (unsigned long)clr); } @@ -149,7 +149,7 @@ static int compat_radeon_cp_stipple(struct file *file, unsigned int cmd, &request->mask)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_RADEON_STIPPLE, (unsigned long)request); } @@ -204,7 +204,7 @@ static int compat_radeon_cp_texture(struct file *file, unsigned int cmd, &image->data)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_RADEON_TEXTURE, (unsigned long)request); } @@ -238,7 +238,7 @@ static int compat_radeon_cp_vertex2(struct file *file, unsigned int cmd, &request->prim)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_RADEON_VERTEX2, (unsigned long)request); } @@ -268,7 +268,7 @@ static int compat_radeon_cp_cmdbuf(struct file *file, unsigned int cmd, &request->boxes)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_RADEON_CMDBUF, (unsigned long)request); } @@ -293,7 +293,7 @@ static int compat_radeon_cp_getparam(struct file *file, unsigned int cmd, &request->value)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_RADEON_GETPARAM, (unsigned long)request); } @@ -322,7 +322,7 @@ static int compat_radeon_mem_alloc(struct file *file, unsigned int cmd, &request->region_offset)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_RADEON_ALLOC, (unsigned long)request); } @@ -345,7 +345,7 @@ static int compat_radeon_irq_emit(struct file *file, unsigned int cmd, &request->irq_seq)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long)request); } @@ -386,7 +386,7 @@ long radeon_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (fn != NULL) ret = (*fn) (filp, cmd, arg); else - ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); + ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); unlock_kernel(); return ret; diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c index 9b1bf60ffbe..06f2dbf1771 100644 --- a/drivers/char/dsp56k.c +++ b/drivers/char/dsp56k.c @@ -201,7 +201,7 @@ static int dsp56k_upload(u_char __user *bin, int len) static ssize_t dsp56k_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int dev = iminor(inode) & 0x0f; switch(dev) @@ -264,7 +264,7 @@ static ssize_t dsp56k_read(struct file *file, char __user *buf, size_t count, static ssize_t dsp56k_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int dev = iminor(inode) & 0x0f; switch(dev) @@ -420,7 +420,7 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file, #if 0 static unsigned int dsp56k_poll(struct file *file, poll_table *wait) { - int dev = iminor(file->f_dentry->d_inode) & 0x0f; + int dev = iminor(file->f_path.dentry->d_inode) & 0x0f; switch(dev) { diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c index 5e82c3bad2e..d4005e94fe5 100644 --- a/drivers/char/dtlk.c +++ b/drivers/char/dtlk.c @@ -122,7 +122,7 @@ static void dtlk_timer_tick(unsigned long data); static ssize_t dtlk_read(struct file *file, char __user *buf, size_t count, loff_t * ppos) { - unsigned int minor = iminor(file->f_dentry->d_inode); + unsigned int minor = iminor(file->f_path.dentry->d_inode); char ch; int i = 0, retries; @@ -174,7 +174,7 @@ static ssize_t dtlk_write(struct file *file, const char __user *buf, } #endif - if (iminor(file->f_dentry->d_inode) != DTLK_MINOR) + if (iminor(file->f_path.dentry->d_inode) != DTLK_MINOR) return -EINVAL; while (1) { diff --git a/drivers/char/epca.c b/drivers/char/epca.c index 7c71eb77980..a0f822c9d74 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c @@ -199,7 +199,7 @@ static int pc_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long); static int info_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long); -static void pc_set_termios(struct tty_struct *, struct termios *); +static void pc_set_termios(struct tty_struct *, struct ktermios *); static void do_softint(struct work_struct *work); static void pc_stop(struct tty_struct *); static void pc_start(struct tty_struct *); @@ -1236,6 +1236,8 @@ static int __init pc_init(void) pc_driver->init_termios.c_oflag = 0; pc_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; pc_driver->init_termios.c_lflag = 0; + pc_driver->init_termios.c_ispeed = 9600; + pc_driver->init_termios.c_ospeed = 9600; pc_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(pc_driver, &pc_ops); @@ -1250,6 +1252,8 @@ static int __init pc_init(void) pc_info->init_termios.c_oflag = 0; pc_info->init_termios.c_lflag = 0; pc_info->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL; + pc_info->init_termios.c_ispeed = 9600; + pc_info->init_termios.c_ospeed = 9600; pc_info->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(pc_info, &info_ops); @@ -1999,7 +2003,7 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch) { /* Begin epcaparam */ unsigned int cmdHead; - struct termios *ts; + struct ktermios *ts; struct board_chan __iomem *bc; unsigned mval, hflow, cflag, iflag; @@ -2114,7 +2118,7 @@ static void receive_data(struct channel *ch) { /* Begin receive_data */ unchar *rptr; - struct termios *ts = NULL; + struct ktermios *ts = NULL; struct tty_struct *tty; struct board_chan __iomem *bc; int dataToRead, wrapgap, bytesAvailable; @@ -2362,12 +2366,14 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, switch (cmd) { /* Begin switch cmd */ +#if 0 /* Handled by calling layer properly */ case TCGETS: - if (copy_to_user(argp, tty->termios, sizeof(struct termios))) + if (copy_to_user(argp, tty->termios, sizeof(struct ktermios))) return -EFAULT; return 0; case TCGETA: return get_termio(tty, argp); +#endif case TCSBRK: /* SVID version: non-zero arg --> no break */ retval = tty_check_change(tty); if (retval) @@ -2536,7 +2542,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, /* --------------------- Begin pc_set_termios ----------------------- */ -static void pc_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void pc_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { /* Begin pc_set_termios */ struct channel *ch; diff --git a/drivers/char/esp.c b/drivers/char/esp.c index 93b55196251..d1bfbaa2aa0 100644 --- a/drivers/char/esp.c +++ b/drivers/char/esp.c @@ -1915,7 +1915,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, return 0; } -static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct esp_struct *info = (struct esp_struct *)tty->driver_data; unsigned long flags; diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c index 87127e49c0d..e769811e741 100644 --- a/drivers/char/generic_serial.c +++ b/drivers/char/generic_serial.c @@ -718,11 +718,11 @@ static unsigned int gs_baudrates[] = { void gs_set_termios (struct tty_struct * tty, - struct termios * old_termios) + struct ktermios * old_termios) { struct gs_port *port; int baudrate, tmp, rv; - struct termios *tiosp; + struct ktermios *tiosp; func_enter(); diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c index d090622f1de..207f7343ba6 100644 --- a/drivers/char/hvcs.c +++ b/drivers/char/hvcs.c @@ -192,11 +192,13 @@ MODULE_VERSION(HVCS_DRIVER_VERSION); * that will cause echoing or we'll go into recursive loop echoing chars back * and forth with the console drivers. */ -static struct termios hvcs_tty_termios = { +static struct ktermios hvcs_tty_termios = { .c_iflag = IGNBRK | IGNPAR, .c_oflag = OPOST, .c_cflag = B38400 | CS8 | CREAD | HUPCL, - .c_cc = INIT_C_CC + .c_cc = INIT_C_CC, + .c_ispeed = 38400, + .c_ospeed = 38400 }; /* diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c index 82a41d5b4ed..d7806834fc1 100644 --- a/drivers/char/hvsi.c +++ b/drivers/char/hvsi.c @@ -1161,6 +1161,8 @@ static int __init hvsi_init(void) hvsi_driver->type = TTY_DRIVER_TYPE_SYSTEM; hvsi_driver->init_termios = tty_std_termios; hvsi_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL; + hvsi_driver->init_termios.c_ispeed = 9600; + hvsi_driver->init_termios.c_ospeed = 9600; hvsi_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(hvsi_driver, &hvsi_ops); diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index cda2459c1d6..7c70310a49b 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c @@ -177,7 +177,7 @@ static int ip2_write_room(PTTY); static int ip2_chars_in_buf(PTTY); static void ip2_flush_buffer(PTTY); static int ip2_ioctl(PTTY, struct file *, UINT, ULONG); -static void ip2_set_termios(PTTY, struct termios *); +static void ip2_set_termios(PTTY, struct ktermios *); static void ip2_set_line_discipline(PTTY); static void ip2_throttle(PTTY); static void ip2_unthrottle(PTTY); @@ -198,7 +198,7 @@ static void do_status(struct work_struct *); static void ip2_wait_until_sent(PTTY,int); -static void set_params (i2ChanStrPtr, struct termios *); +static void set_params (i2ChanStrPtr, struct ktermios *); static int get_serial_info(i2ChanStrPtr, struct serial_struct __user *); static int set_serial_info(i2ChanStrPtr, struct serial_struct __user *); @@ -2398,7 +2398,7 @@ set_serial_info( i2ChanStrPtr pCh, struct serial_struct __user *new_info ) /* */ /******************************************************************************/ static void -ip2_set_termios( PTTY tty, struct termios *old_termios ) +ip2_set_termios( PTTY tty, struct ktermios *old_termios ) { i2ChanStrPtr pCh = (i2ChanStrPtr)tty->driver_data; @@ -2440,11 +2440,11 @@ ip2_set_line_discipline ( PTTY tty ) /* change. */ /******************************************************************************/ static void -set_params( i2ChanStrPtr pCh, struct termios *o_tios ) +set_params( i2ChanStrPtr pCh, struct ktermios *o_tios ) { tcflag_t cflag, iflag, lflag; char stop_char, start_char; - struct termios dummy; + struct ktermios dummy; lflag = pCh->pTTY->termios->c_lflag; cflag = pCh->pTTY->termios->c_cflag; @@ -2700,7 +2700,7 @@ static ssize_t ip2_ipl_read(struct file *pFile, char __user *pData, size_t count, loff_t *off ) { - unsigned int minor = iminor(pFile->f_dentry->d_inode); + unsigned int minor = iminor(pFile->f_path.dentry->d_inode); int rc = 0; #ifdef IP2DEBUG_IPL diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index 375d3378eec..e257835a9a7 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c @@ -798,7 +798,7 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd, if (copy_to_user(precv64, &recv64, sizeof(recv64))) return -EFAULT; - rc = ipmi_ioctl(filep->f_dentry->d_inode, filep, + rc = ipmi_ioctl(filep->f_path.dentry->d_inode, filep, ((cmd == COMPAT_IPMICTL_RECEIVE_MSG) ? IPMICTL_RECEIVE_MSG : IPMICTL_RECEIVE_MSG_TRUNC), @@ -815,7 +815,7 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd, return rc; } default: - return ipmi_ioctl(filep->f_dentry->d_inode, filep, cmd, arg); + return ipmi_ioctl(filep->f_path.dentry->d_inode, filep, cmd, arg); } } #endif diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 1637c1d9a4b..5a747e68599 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c @@ -172,12 +172,14 @@ static struct pci_driver isicom_driver = { static int prev_card = 3; /* start servicing isi_card[0] */ static struct tty_driver *isicom_normal; -static struct timer_list tx; +static DECLARE_COMPLETION(isi_timerdone); static char re_schedule = 1; static void isicom_tx(unsigned long _data); static void isicom_start(struct tty_struct *tty); +static DEFINE_TIMER(tx, isicom_tx, 0, 0); + /* baud index mappings from linux defns to isi */ static signed char linuxb_to_isib[] = { @@ -193,9 +195,9 @@ struct isi_board { unsigned short shift_count; struct isi_port * ports; signed char count; - unsigned char isa; spinlock_t card_lock; /* Card wide lock 11/5/00 -sameer */ unsigned long flags; + unsigned int index; }; struct isi_port { @@ -514,17 +516,11 @@ static void isicom_tx(unsigned long _data) /* schedule another tx for hopefully in about 10ms */ sched_again: if (!re_schedule) { - re_schedule = 2; + complete(&isi_timerdone); return; } - init_timer(&tx); - tx.expires = jiffies + HZ/100; - tx.data = 0; - tx.function = isicom_tx; - add_timer(&tx); - - return; + mod_timer(&tx, jiffies + msecs_to_jiffies(10)); } /* Interrupt handlers */ @@ -562,14 +558,12 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) base = card->base; spin_lock(&card->card_lock); - if (card->isa == NO) { - /* - * disable any interrupts from the PCI card and lower the - * interrupt line - */ - outw(0x8000, base+0x04); - ClearInterrupt(base); - } + /* + * disable any interrupts from the PCI card and lower the + * interrupt line + */ + outw(0x8000, base+0x04); + ClearInterrupt(base); inw(base); /* get the dummy word out */ header = inw(base); @@ -579,19 +573,13 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) if (channel + 1 > card->port_count) { printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%lx): " "%d(channel) > port_count.\n", base, channel+1); - if (card->isa) - ClearInterrupt(base); - else - outw(0x0000, base+0x04); /* enable interrupts */ + outw(0x0000, base+0x04); /* enable interrupts */ spin_unlock(&card->card_lock); return IRQ_HANDLED; } port = card->ports + channel; if (!(port->flags & ASYNC_INITIALIZED)) { - if (card->isa) - ClearInterrupt(base); - else - outw(0x0000, base+0x04); /* enable interrupts */ + outw(0x0000, base+0x04); /* enable interrupts */ return IRQ_HANDLED; } @@ -604,10 +592,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) } if (byte_count & 0x01) inw(base); - if (card->isa == YES) - ClearInterrupt(base); - else - outw(0x0000, base+0x04); /* enable interrupts */ + outw(0x0000, base+0x04); /* enable interrupts */ spin_unlock(&card->card_lock); return IRQ_HANDLED; } @@ -708,10 +693,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) } tty_flip_buffer_push(tty); } - if (card->isa == YES) - ClearInterrupt(base); - else - outw(0x0000, base+0x04); /* enable interrupts */ + outw(0x0000, base+0x04); /* enable interrupts */ return IRQ_HANDLED; } @@ -964,8 +946,8 @@ static int isicom_open(struct tty_struct *tty, struct file *filp) { struct isi_port *port; struct isi_board *card; - unsigned int line, board; - int error; + unsigned int board; + int error, line; line = tty->index; if (line < 0 || line > PORT_COUNT-1) @@ -1399,7 +1381,7 @@ static int isicom_ioctl(struct tty_struct *tty, struct file *filp, /* set_termios et all */ static void isicom_set_termios(struct tty_struct *tty, - struct termios *old_termios) + struct ktermios *old_termios) { struct isi_port *port = tty->driver_data; @@ -1520,37 +1502,6 @@ static void isicom_flush_buffer(struct tty_struct *tty) * Driver init and deinit functions */ -static int __devinit isicom_register_ioregion(struct pci_dev *pdev, - const unsigned int index) -{ - struct isi_board *board = pci_get_drvdata(pdev); - - if (!board->base) - return -EINVAL; - - if (!request_region(board->base, 16, ISICOM_NAME)) { - dev_dbg(&pdev->dev, "I/O Region 0x%lx-0x%lx is busy. Card%d " - "will be disabled.\n", board->base, board->base + 15, - index + 1); - return -EBUSY; - } - - return 0; -} - -static void isicom_unregister_ioregion(struct pci_dev *pdev) -{ - struct isi_board *board = pci_get_drvdata(pdev); - - if (!board->base) - return; - - release_region(board->base, 16); - dev_dbg(&pdev->dev, "I/O Region 0x%lx-0x%lx released.\n", - board->base, board->base + 15); - board->base = 0; -} - static const struct tty_operations isicom_ops = { .open = isicom_open, .close = isicom_close, @@ -1571,70 +1522,6 @@ static const struct tty_operations isicom_ops = { .tiocmset = isicom_tiocmset, }; -static int __devinit isicom_register_tty_driver(void) -{ - int error = -ENOMEM; - - /* tty driver structure initialization */ - isicom_normal = alloc_tty_driver(PORT_COUNT); - if (!isicom_normal) - goto end; - - isicom_normal->owner = THIS_MODULE; - isicom_normal->name = "ttyM"; - isicom_normal->major = ISICOM_NMAJOR; - isicom_normal->minor_start = 0; - isicom_normal->type = TTY_DRIVER_TYPE_SERIAL; - isicom_normal->subtype = SERIAL_TYPE_NORMAL; - isicom_normal->init_termios = tty_std_termios; - isicom_normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | - CLOCAL; - isicom_normal->flags = TTY_DRIVER_REAL_RAW; - tty_set_operations(isicom_normal, &isicom_ops); - - if ((error = tty_register_driver(isicom_normal))) { - pr_dbg("Couldn't register the dialin driver, error=%d\n", - error); - put_tty_driver(isicom_normal); - } -end: - return error; -} - -static void isicom_unregister_tty_driver(void) -{ - int error; - - if ((error = tty_unregister_driver(isicom_normal))) - pr_dbg("couldn't unregister normal driver, error=%d.\n", error); - - put_tty_driver(isicom_normal); -} - -static int __devinit isicom_register_isr(struct pci_dev *pdev, - const unsigned int index) -{ - struct isi_board *board = pci_get_drvdata(pdev); - unsigned long irqflags = IRQF_DISABLED; - int retval = -EINVAL; - - if (!board->base) - goto end; - - if (board->isa == NO) - irqflags |= IRQF_SHARED; - - retval = request_irq(board->irq, isicom_interrupt, irqflags, - ISICOM_NAME, board); - if (retval < 0) - dev_warn(&pdev->dev, "Could not install handler at Irq %d. " - "Card%d will be disabled.\n", board->irq, index + 1); - else - retval = 0; -end: - return retval; -} - static int __devinit reset_card(struct pci_dev *pdev, const unsigned int card, unsigned int *signature) { @@ -1656,36 +1543,23 @@ static int __devinit reset_card(struct pci_dev *pdev, *signature = inw(base + 0x4) & 0xff; - if (board->isa == YES) { - if (!(inw(base + 0xe) & 0x1) || (inw(base + 0x2))) { - dev_dbg(&pdev->dev, "base+0x2=0x%lx, base+0xe=0x%lx\n", - inw(base + 0x2), inw(base + 0xe)); - dev_err(&pdev->dev, "ISILoad:ISA Card%d reset failure " - "(Possible bad I/O Port Address 0x%lx).\n", - card + 1, base); - retval = -EIO; - goto end; - } - } else { - portcount = inw(base + 0x2); - if (!(inw(base + 0xe) & 0x1) || ((portcount != 0) && - (portcount != 4) && (portcount != 8))) { - dev_dbg(&pdev->dev, "base+0x2=0x%lx, base+0xe=0x%lx\n", - inw(base + 0x2), inw(base + 0xe)); - dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure " - "(Possible bad I/O Port Address 0x%lx).\n", - card + 1, base); - retval = -EIO; - goto end; - } + portcount = inw(base + 0x2); + if (!(inw(base + 0xe) & 0x1) || ((portcount != 0) && + (portcount != 4) && (portcount != 8))) { + dev_dbg(&pdev->dev, "base+0x2=0x%lx, base+0xe=0x%lx\n", + inw(base + 0x2), inw(base + 0xe)); + dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure " + "(Possible bad I/O Port Address 0x%lx).\n", + card + 1, base); + retval = -EIO; + goto end; } switch (*signature) { case 0xa5: case 0xbb: case 0xdd: - board->port_count = (board->isa == NO && portcount == 4) ? 4 : - 8; + board->port_count = (portcount == 4) ? 4 : 8; board->shift_count = 12; break; case 0xcc: @@ -1831,6 +1705,11 @@ static int __devinit load_firmware(struct pci_dev *pdev, } data = kmalloc(word_count * 2, GFP_KERNEL); + if (data == NULL) { + dev_err(&pdev->dev, "Card%d, firmware upload " + "failed, not enough memory\n", index + 1); + goto errrelfw; + } inw(base); insw(base, data, word_count); InterruptTheCard(base); @@ -1879,8 +1758,6 @@ end: /* * Insmod can set static symbols so keep these static */ -static int io[4]; -static int irq[4]; static int card; static int __devinit isicom_probe(struct pci_dev *pdev, @@ -1906,20 +1783,29 @@ static int __devinit isicom_probe(struct pci_dev *pdev, break; } + board->index = index; board->base = ioaddr; board->irq = pciirq; - board->isa = NO; card++; pci_set_drvdata(pdev, board); - retval = isicom_register_ioregion(pdev, index); - if (retval < 0) + retval = pci_request_region(pdev, 3, ISICOM_NAME); + if (retval) { + dev_err(&pdev->dev, "I/O Region 0x%lx-0x%lx is busy. Card%d " + "will be disabled.\n", board->base, board->base + 15, + index + 1); + retval = -EBUSY; goto err; + } - retval = isicom_register_isr(pdev, index); - if (retval < 0) + retval = request_irq(board->irq, isicom_interrupt, + IRQF_SHARED | IRQF_DISABLED, ISICOM_NAME, board); + if (retval < 0) { + dev_err(&pdev->dev, "Could not install handler at Irq %d. " + "Card%d will be disabled.\n", board->irq, index + 1); goto errunrr; + } retval = reset_card(pdev, index, &signature); if (retval < 0) @@ -1929,12 +1815,16 @@ static int __devinit isicom_probe(struct pci_dev *pdev, if (retval < 0) goto errunri; + for (index = 0; index < board->port_count; index++) + tty_register_device(isicom_normal, board->index * 16 + index, + &pdev->dev); + return 0; errunri: free_irq(board->irq, board); errunrr: - isicom_unregister_ioregion(pdev); + pci_release_region(pdev, 3); err: board->base = 0; return retval; @@ -1943,18 +1833,21 @@ err: static void __devexit isicom_remove(struct pci_dev *pdev) { struct isi_board *board = pci_get_drvdata(pdev); + unsigned int i; + + for (i = 0; i < board->port_count; i++) + tty_unregister_device(isicom_normal, board->index * 16 + i); free_irq(board->irq, board); - isicom_unregister_ioregion(pdev); + pci_release_region(pdev, 3); } -static int __devinit isicom_setup(void) +static int __init isicom_init(void) { int retval, idx, channel; struct isi_port *port; card = 0; - memset(isi_ports, 0, sizeof(isi_ports)); for(idx = 0; idx < BOARD_COUNT; idx++) { port = &isi_ports[idx * 16]; @@ -1975,66 +1868,65 @@ static int __devinit isicom_setup(void) } isi_card[idx].base = 0; isi_card[idx].irq = 0; - - if (!io[idx]) - continue; - - if (irq[idx] == 2 || irq[idx] == 3 || irq[idx] == 4 || - irq[idx] == 5 || irq[idx] == 7 || - irq[idx] == 10 || irq[idx] == 11 || - irq[idx] == 12 || irq[idx] == 15) { - printk(KERN_ERR "ISICOM: ISA not supported yet.\n"); - retval = -EINVAL; - goto error; - } else - printk(KERN_ERR "ISICOM: Irq %d unsupported. " - "Disabling Card%d...\n", irq[idx], idx + 1); } - retval = isicom_register_tty_driver(); - if (retval < 0) + /* tty driver structure initialization */ + isicom_normal = alloc_tty_driver(PORT_COUNT); + if (!isicom_normal) { + retval = -ENOMEM; goto error; + } + + isicom_normal->owner = THIS_MODULE; + isicom_normal->name = "ttyM"; + isicom_normal->major = ISICOM_NMAJOR; + isicom_normal->minor_start = 0; + isicom_normal->type = TTY_DRIVER_TYPE_SERIAL; + isicom_normal->subtype = SERIAL_TYPE_NORMAL; + isicom_normal->init_termios = tty_std_termios; + isicom_normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | + CLOCAL; + isicom_normal->flags = TTY_DRIVER_REAL_RAW | + TTY_DRIVER_DYNAMIC_DEV; + tty_set_operations(isicom_normal, &isicom_ops); + + retval = tty_register_driver(isicom_normal); + if (retval) { + pr_dbg("Couldn't register the dialin driver\n"); + goto err_puttty; + } retval = pci_register_driver(&isicom_driver); if (retval < 0) { printk(KERN_ERR "ISICOM: Unable to register pci driver.\n"); - goto errtty; + goto err_unrtty; } - init_timer(&tx); - tx.expires = jiffies + 1; - tx.data = 0; - tx.function = isicom_tx; - re_schedule = 1; - add_timer(&tx); + mod_timer(&tx, jiffies + 1); return 0; -errtty: - isicom_unregister_tty_driver(); +err_unrtty: + tty_unregister_driver(isicom_normal); +err_puttty: + put_tty_driver(isicom_normal); error: return retval; } static void __exit isicom_exit(void) { - unsigned int index = 0; - re_schedule = 0; - while (re_schedule != 2 && index++ < 100) - msleep(10); + wait_for_completion_timeout(&isi_timerdone, HZ); pci_unregister_driver(&isicom_driver); - isicom_unregister_tty_driver(); + tty_unregister_driver(isicom_normal); + put_tty_driver(isicom_normal); } -module_init(isicom_setup); +module_init(isicom_init); module_exit(isicom_exit); MODULE_AUTHOR("MultiTech"); MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech"); MODULE_LICENSE("GPL"); -module_param_array(io, int, NULL, 0); -MODULE_PARM_DESC(io, "I/O ports for the cards"); -module_param_array(irq, int, NULL, 0); -MODULE_PARM_DESC(irq, "Interrupts for the cards"); diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 8f591945ebd..68645d35187 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c @@ -14,14 +14,6 @@ * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ /*****************************************************************************/ @@ -41,6 +33,7 @@ #include <linux/device.h> #include <linux/wait.h> #include <linux/eisa.h> +#include <linux/ctype.h> #include <asm/io.h> #include <asm/uaccess.h> @@ -61,21 +54,10 @@ #define BRD_BRUMBY4 2 #define BRD_ONBOARD2 3 #define BRD_ONBOARD 4 -#define BRD_BRUMBY8 5 -#define BRD_BRUMBY16 6 #define BRD_ONBOARDE 7 -#define BRD_ONBOARD32 9 -#define BRD_ONBOARD2_32 10 -#define BRD_ONBOARDRS 11 -#define BRD_EASYIO 20 -#define BRD_ECH 21 -#define BRD_ECHMC 22 #define BRD_ECP 23 #define BRD_ECPE 24 #define BRD_ECPMC 25 -#define BRD_ECHPCI 26 -#define BRD_ECH64PCI 27 -#define BRD_EASYIOPCI 28 #define BRD_ECPPCI 29 #define BRD_BRUMBY BRD_BRUMBY4 @@ -119,20 +101,16 @@ * interrupt is required. */ -typedef struct { +struct stlconf { int brdtype; int ioaddr1; int ioaddr2; unsigned long memaddr; int irq; int irqtype; -} stlconf_t; - -static stlconf_t stli_brdconf[] = { - /*{ BRD_ECP, 0x2a0, 0, 0xcc000, 0, 0 },*/ }; -static int stli_nrbrds = ARRAY_SIZE(stli_brdconf); +static unsigned int stli_nrbrds; /* stli_lock must NOT be taken holding brd_lock */ static spinlock_t stli_lock; /* TTY logic lock */ @@ -194,9 +172,11 @@ static struct tty_struct *stli_txcooktty; * with this termios initially. Basically all it defines is a raw port * at 9600 baud, 8 data bits, no parity, 1 stop bit. */ -static struct termios stli_deftermios = { +static struct ktermios stli_deftermios = { .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL), .c_cc = INIT_C_CC, + .c_ispeed = 9600, + .c_ospeed = 9600, }; /* @@ -205,13 +185,12 @@ static struct termios stli_deftermios = { */ static comstats_t stli_comstats; static combrd_t stli_brdstats; -static asystats_t stli_cdkstats; -static stlibrd_t stli_dummybrd; -static stliport_t stli_dummyport; +static struct asystats stli_cdkstats; /*****************************************************************************/ -static stlibrd_t *stli_brds[STL_MAXBRDS]; +static DEFINE_MUTEX(stli_brdslock); +static struct stlibrd *stli_brds[STL_MAXBRDS]; static int stli_shared; @@ -223,6 +202,7 @@ static int stli_shared; */ #define BST_FOUND 0x1 #define BST_STARTED 0x2 +#define BST_PROBED 0x4 /* * Define the set of port state flags. These are marked for internal @@ -255,18 +235,18 @@ static char *stli_brdnames[] = { "Brumby", "Brumby", "ONboard-EI", - (char *) NULL, + NULL, "ONboard", "ONboard-MC", "ONboard-MC", - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, "EasyIO", "EC8/32-AT", "EC8/32-MC", @@ -304,12 +284,10 @@ static char **stli_brdsp[] = { * parse any module arguments. */ -typedef struct stlibrdtype { +static struct stlibrdtype { char *name; int type; -} stlibrdtype_t; - -static stlibrdtype_t stli_brdstr[] = { +} stli_brdstr[] = { { "stallion", BRD_STALLION }, { "1", BRD_STALLION }, { "brumby", BRD_BRUMBY }, @@ -379,6 +357,7 @@ MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,memaddr]"); module_param_array(board3, charp, NULL, 0); MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,memaddr]"); +#if STLI_EISAPROBE != 0 /* * Set up a default memory address table for EISA board probing. * The default addresses are all bellow 1Mbyte, which has to be the @@ -396,14 +375,11 @@ static unsigned long stli_eisamemprobeaddrs[] = { }; static int stli_eisamempsize = ARRAY_SIZE(stli_eisamemprobeaddrs); +#endif /* * Define the Stallion PCI vendor and device IDs. */ -#ifdef CONFIG_PCI -#ifndef PCI_VENDOR_ID_STALLION -#define PCI_VENDOR_ID_STALLION 0x124d -#endif #ifndef PCI_DEVICE_ID_ECRA #define PCI_DEVICE_ID_ECRA 0x0004 #endif @@ -414,7 +390,7 @@ static struct pci_device_id istallion_pci_tbl[] = { }; MODULE_DEVICE_TABLE(pci, istallion_pci_tbl); -#endif /* CONFIG_PCI */ +static struct pci_driver stli_pcidriver; /*****************************************************************************/ @@ -615,22 +591,10 @@ MODULE_DEVICE_TABLE(pci, istallion_pci_tbl); /*****************************************************************************/ /* - * Define some handy local macros... - */ -#undef MIN -#define MIN(a,b) (((a) <= (b)) ? (a) : (b)) - -#undef TOLOWER -#define TOLOWER(x) ((((x) >= 'A') && ((x) <= 'Z')) ? ((x) + 0x20) : (x)) - -/*****************************************************************************/ - -/* * Prototype all functions in this driver! */ -static int stli_parsebrd(stlconf_t *confp, char **argp); -static int stli_init(void); +static int stli_parsebrd(struct stlconf *confp, char **argp); static int stli_open(struct tty_struct *tty, struct file *filp); static void stli_close(struct tty_struct *tty, struct file *filp); static int stli_write(struct tty_struct *tty, const unsigned char *buf, int count); @@ -639,7 +603,7 @@ static void stli_flushchars(struct tty_struct *tty); static int stli_writeroom(struct tty_struct *tty); static int stli_charsinbuffer(struct tty_struct *tty); static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); -static void stli_settermios(struct tty_struct *tty, struct termios *old); +static void stli_settermios(struct tty_struct *tty, struct ktermios *old); static void stli_throttle(struct tty_struct *tty); static void stli_unthrottle(struct tty_struct *tty); static void stli_stop(struct tty_struct *tty); @@ -649,86 +613,84 @@ static void stli_breakctl(struct tty_struct *tty, int state); static void stli_waituntilsent(struct tty_struct *tty, int timeout); static void stli_sendxchar(struct tty_struct *tty, char ch); static void stli_hangup(struct tty_struct *tty); -static int stli_portinfo(stlibrd_t *brdp, stliport_t *portp, int portnr, char *pos); +static int stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portnr, char *pos); -static int stli_brdinit(stlibrd_t *brdp); -static int stli_startbrd(stlibrd_t *brdp); +static int stli_brdinit(struct stlibrd *brdp); +static int stli_startbrd(struct stlibrd *brdp); static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp); static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp); static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg); -static void stli_brdpoll(stlibrd_t *brdp, cdkhdr_t __iomem *hdrp); +static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp); static void stli_poll(unsigned long arg); -static int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp); -static int stli_initopen(stlibrd_t *brdp, stliport_t *portp); -static int stli_rawopen(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait); -static int stli_rawclose(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait); -static int stli_waitcarrier(stlibrd_t *brdp, stliport_t *portp, struct file *filp); +static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp); +static int stli_initopen(struct stlibrd *brdp, struct stliport *portp); +static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); +static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); +static int stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct file *filp); static void stli_dohangup(struct work_struct *); -static int stli_setport(stliport_t *portp); -static int stli_cmdwait(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback); -static void stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback); -static void __stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback); -static void stli_dodelaycmd(stliport_t *portp, cdkctrl_t __iomem *cp); -static void stli_mkasyport(stliport_t *portp, asyport_t *pp, struct termios *tiosp); +static int stli_setport(struct stliport *portp); +static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); +static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); +static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); +static void stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp); +static void stli_mkasyport(struct stliport *portp, asyport_t *pp, struct ktermios *tiosp); static void stli_mkasysigs(asysigs_t *sp, int dtr, int rts); static long stli_mktiocm(unsigned long sigvalue); -static void stli_read(stlibrd_t *brdp, stliport_t *portp); -static int stli_getserial(stliport_t *portp, struct serial_struct __user *sp); -static int stli_setserial(stliport_t *portp, struct serial_struct __user *sp); +static void stli_read(struct stlibrd *brdp, struct stliport *portp); +static int stli_getserial(struct stliport *portp, struct serial_struct __user *sp); +static int stli_setserial(struct stliport *portp, struct serial_struct __user *sp); static int stli_getbrdstats(combrd_t __user *bp); -static int stli_getportstats(stliport_t *portp, comstats_t __user *cp); -static int stli_portcmdstats(stliport_t *portp); -static int stli_clrportstats(stliport_t *portp, comstats_t __user *cp); -static int stli_getportstruct(stliport_t __user *arg); -static int stli_getbrdstruct(stlibrd_t __user *arg); -static stlibrd_t *stli_allocbrd(void); - -static void stli_ecpinit(stlibrd_t *brdp); -static void stli_ecpenable(stlibrd_t *brdp); -static void stli_ecpdisable(stlibrd_t *brdp); -static void __iomem *stli_ecpgetmemptr(stlibrd_t *brdp, unsigned long offset, int line); -static void stli_ecpreset(stlibrd_t *brdp); -static void stli_ecpintr(stlibrd_t *brdp); -static void stli_ecpeiinit(stlibrd_t *brdp); -static void stli_ecpeienable(stlibrd_t *brdp); -static void stli_ecpeidisable(stlibrd_t *brdp); -static void __iomem *stli_ecpeigetmemptr(stlibrd_t *brdp, unsigned long offset, int line); -static void stli_ecpeireset(stlibrd_t *brdp); -static void stli_ecpmcenable(stlibrd_t *brdp); -static void stli_ecpmcdisable(stlibrd_t *brdp); -static void __iomem *stli_ecpmcgetmemptr(stlibrd_t *brdp, unsigned long offset, int line); -static void stli_ecpmcreset(stlibrd_t *brdp); -static void stli_ecppciinit(stlibrd_t *brdp); -static void __iomem *stli_ecppcigetmemptr(stlibrd_t *brdp, unsigned long offset, int line); -static void stli_ecppcireset(stlibrd_t *brdp); - -static void stli_onbinit(stlibrd_t *brdp); -static void stli_onbenable(stlibrd_t *brdp); -static void stli_onbdisable(stlibrd_t *brdp); -static void __iomem *stli_onbgetmemptr(stlibrd_t *brdp, unsigned long offset, int line); -static void stli_onbreset(stlibrd_t *brdp); -static void stli_onbeinit(stlibrd_t *brdp); -static void stli_onbeenable(stlibrd_t *brdp); -static void stli_onbedisable(stlibrd_t *brdp); -static void __iomem *stli_onbegetmemptr(stlibrd_t *brdp, unsigned long offset, int line); -static void stli_onbereset(stlibrd_t *brdp); -static void stli_bbyinit(stlibrd_t *brdp); -static void __iomem *stli_bbygetmemptr(stlibrd_t *brdp, unsigned long offset, int line); -static void stli_bbyreset(stlibrd_t *brdp); -static void stli_stalinit(stlibrd_t *brdp); -static void __iomem *stli_stalgetmemptr(stlibrd_t *brdp, unsigned long offset, int line); -static void stli_stalreset(stlibrd_t *brdp); - -static stliport_t *stli_getport(int brdnr, int panelnr, int portnr); - -static int stli_initecp(stlibrd_t *brdp); -static int stli_initonb(stlibrd_t *brdp); -static int stli_eisamemprobe(stlibrd_t *brdp); -static int stli_initports(stlibrd_t *brdp); - -#ifdef CONFIG_PCI -static int stli_initpcibrd(int brdtype, struct pci_dev *devp); +static int stli_getportstats(struct stliport *portp, comstats_t __user *cp); +static int stli_portcmdstats(struct stliport *portp); +static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp); +static int stli_getportstruct(struct stliport __user *arg); +static int stli_getbrdstruct(struct stlibrd __user *arg); +static struct stlibrd *stli_allocbrd(void); + +static void stli_ecpinit(struct stlibrd *brdp); +static void stli_ecpenable(struct stlibrd *brdp); +static void stli_ecpdisable(struct stlibrd *brdp); +static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offset, int line); +static void stli_ecpreset(struct stlibrd *brdp); +static void stli_ecpintr(struct stlibrd *brdp); +static void stli_ecpeiinit(struct stlibrd *brdp); +static void stli_ecpeienable(struct stlibrd *brdp); +static void stli_ecpeidisable(struct stlibrd *brdp); +static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long offset, int line); +static void stli_ecpeireset(struct stlibrd *brdp); +static void stli_ecpmcenable(struct stlibrd *brdp); +static void stli_ecpmcdisable(struct stlibrd *brdp); +static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long offset, int line); +static void stli_ecpmcreset(struct stlibrd *brdp); +static void stli_ecppciinit(struct stlibrd *brdp); +static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long offset, int line); +static void stli_ecppcireset(struct stlibrd *brdp); + +static void stli_onbinit(struct stlibrd *brdp); +static void stli_onbenable(struct stlibrd *brdp); +static void stli_onbdisable(struct stlibrd *brdp); +static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offset, int line); +static void stli_onbreset(struct stlibrd *brdp); +static void stli_onbeinit(struct stlibrd *brdp); +static void stli_onbeenable(struct stlibrd *brdp); +static void stli_onbedisable(struct stlibrd *brdp); +static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offset, int line); +static void stli_onbereset(struct stlibrd *brdp); +static void stli_bbyinit(struct stlibrd *brdp); +static void __iomem *stli_bbygetmemptr(struct stlibrd *brdp, unsigned long offset, int line); +static void stli_bbyreset(struct stlibrd *brdp); +static void stli_stalinit(struct stlibrd *brdp); +static void __iomem *stli_stalgetmemptr(struct stlibrd *brdp, unsigned long offset, int line); +static void stli_stalreset(struct stlibrd *brdp); + +static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr, unsigned int portnr); + +static int stli_initecp(struct stlibrd *brdp); +static int stli_initonb(struct stlibrd *brdp); +#if STLI_EISAPROBE != 0 +static int stli_eisamemprobe(struct stlibrd *brdp); #endif +static int stli_initports(struct stlibrd *brdp); /*****************************************************************************/ @@ -766,136 +728,19 @@ static int stli_timeron; static struct class *istallion_class; -/* - * Loadable module initialization stuff. - */ - -static int __init istallion_module_init(void) -{ - stli_init(); - return 0; -} - -/*****************************************************************************/ - -static void __exit istallion_module_exit(void) -{ - stlibrd_t *brdp; - stliport_t *portp; - int i, j; - - printk(KERN_INFO "Unloading %s: version %s\n", stli_drvtitle, - stli_drvversion); - - /* - * Free up all allocated resources used by the ports. This includes - * memory and interrupts. - */ - if (stli_timeron) { - stli_timeron = 0; - del_timer_sync(&stli_timerlist); - } - - i = tty_unregister_driver(stli_serial); - if (i) { - printk("STALLION: failed to un-register tty driver, " - "errno=%d\n", -i); - return; - } - put_tty_driver(stli_serial); - for (i = 0; i < 4; i++) - class_device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, i)); - class_destroy(istallion_class); - if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"))) - printk("STALLION: failed to un-register serial memory device, " - "errno=%d\n", -i); - - kfree(stli_txcookbuf); - - for (i = 0; (i < stli_nrbrds); i++) { - if ((brdp = stli_brds[i]) == NULL) - continue; - for (j = 0; (j < STL_MAXPORTS); j++) { - portp = brdp->ports[j]; - if (portp != NULL) { - if (portp->tty != NULL) - tty_hangup(portp->tty); - kfree(portp); - } - } - - iounmap(brdp->membase); - if (brdp->iosize > 0) - release_region(brdp->iobase, brdp->iosize); - kfree(brdp); - stli_brds[i] = NULL; - } -} - -module_init(istallion_module_init); -module_exit(istallion_module_exit); - -/*****************************************************************************/ - -/* - * Check for any arguments passed in on the module load command line. - */ - -static void stli_argbrds(void) +static void stli_cleanup_ports(struct stlibrd *brdp) { - stlconf_t conf; - stlibrd_t *brdp; - int i; - - for (i = stli_nrbrds; i < ARRAY_SIZE(stli_brdsp); i++) { - memset(&conf, 0, sizeof(conf)); - if (stli_parsebrd(&conf, stli_brdsp[i]) == 0) - continue; - if ((brdp = stli_allocbrd()) == NULL) - continue; - stli_nrbrds = i + 1; - brdp->brdnr = i; - brdp->brdtype = conf.brdtype; - brdp->iobase = conf.ioaddr1; - brdp->memaddr = conf.memaddr; - stli_brdinit(brdp); - } -} - -/*****************************************************************************/ - -/* - * Convert an ascii string number into an unsigned long. - */ - -static unsigned long stli_atol(char *str) -{ - unsigned long val; - int base, c; - char *sp; - - val = 0; - sp = str; - if ((*sp == '0') && (*(sp+1) == 'x')) { - base = 16; - sp += 2; - } else if (*sp == '0') { - base = 8; - sp++; - } else { - base = 10; - } - - for (; (*sp != 0); sp++) { - c = (*sp > '9') ? (TOLOWER(*sp) - 'a' + 10) : (*sp - '0'); - if ((c < 0) || (c >= base)) { - printk("STALLION: invalid argument %s\n", str); - val = 0; - break; + struct stliport *portp; + unsigned int j; + + for (j = 0; j < STL_MAXPORTS; j++) { + portp = brdp->ports[j]; + if (portp != NULL) { + if (portp->tty != NULL) + tty_hangup(portp->tty); + kfree(portp); } - val = (val * base) + c; } - return(val); } /*****************************************************************************/ @@ -904,16 +749,16 @@ static unsigned long stli_atol(char *str) * Parse the supplied argument string, into the board conf struct. */ -static int stli_parsebrd(stlconf_t *confp, char **argp) +static int stli_parsebrd(struct stlconf *confp, char **argp) { + unsigned int i; char *sp; - int i; if (argp[0] == NULL || *argp[0] == 0) return 0; for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++) - *sp = TOLOWER(*sp); + *sp = tolower(*sp); for (i = 0; i < ARRAY_SIZE(stli_brdstr); i++) { if (strcmp(stli_brdstr[i].name, argp[0]) == 0) @@ -926,9 +771,9 @@ static int stli_parsebrd(stlconf_t *confp, char **argp) confp->brdtype = stli_brdstr[i].type; if (argp[1] != NULL && *argp[1] != 0) - confp->ioaddr1 = stli_atol(argp[1]); + confp->ioaddr1 = simple_strtoul(argp[1], NULL, 0); if (argp[2] != NULL && *argp[2] != 0) - confp->memaddr = stli_atol(argp[2]); + confp->memaddr = simple_strtoul(argp[2], NULL, 0); return(1); } @@ -936,10 +781,10 @@ static int stli_parsebrd(stlconf_t *confp, char **argp) static int stli_open(struct tty_struct *tty, struct file *filp) { - stlibrd_t *brdp; - stliport_t *portp; - unsigned int minordev; - int brdnr, portnr, rc; + struct stlibrd *brdp; + struct stliport *portp; + unsigned int minordev, brdnr, portnr; + int rc; minordev = tty->index; brdnr = MINOR2BRD(minordev); @@ -951,7 +796,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp) if ((brdp->state & BST_STARTED) == 0) return -ENODEV; portnr = MINOR2PORT(minordev); - if ((portnr < 0) || (portnr > brdp->nrports)) + if (portnr > brdp->nrports) return -ENODEV; portp = brdp->ports[portnr]; @@ -1031,8 +876,8 @@ static int stli_open(struct tty_struct *tty, struct file *filp) static void stli_close(struct tty_struct *tty, struct file *filp) { - stlibrd_t *brdp; - stliport_t *portp; + struct stlibrd *brdp; + struct stliport *portp; unsigned long flags; portp = tty->driver_data; @@ -1109,7 +954,7 @@ static void stli_close(struct tty_struct *tty, struct file *filp) * this still all happens pretty quickly. */ -static int stli_initopen(stlibrd_t *brdp, stliport_t *portp) +static int stli_initopen(struct stlibrd *brdp, struct stliport *portp) { struct tty_struct *tty; asynotify_t nt; @@ -1157,7 +1002,7 @@ static int stli_initopen(stlibrd_t *brdp, stliport_t *portp) * to overlap. */ -static int stli_rawopen(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait) +static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait) { cdkhdr_t __iomem *hdrp; cdkctrl_t __iomem *cp; @@ -1228,7 +1073,7 @@ static int stli_rawopen(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, i * wait is true then must have user context (to sleep). */ -static int stli_rawclose(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait) +static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait) { cdkhdr_t __iomem *hdrp; cdkctrl_t __iomem *cp; @@ -1292,7 +1137,7 @@ static int stli_rawclose(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, * to complete (as opposed to initiating the command then returning). */ -static int stli_cmdwait(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback) +static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback) { wait_event_interruptible(portp->raw_wait, !test_bit(ST_CMDING, &portp->state)); @@ -1318,16 +1163,16 @@ static int stli_cmdwait(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, v * waiting for the command to complete - so must have user context. */ -static int stli_setport(stliport_t *portp) +static int stli_setport(struct stliport *portp) { - stlibrd_t *brdp; + struct stlibrd *brdp; asyport_t aport; if (portp == NULL) return -ENODEV; if (portp->tty == NULL) return -ENODEV; - if (portp->brdnr < 0 && portp->brdnr >= stli_nrbrds) + if (portp->brdnr >= stli_nrbrds) return -ENODEV; brdp = stli_brds[portp->brdnr]; if (brdp == NULL) @@ -1344,7 +1189,7 @@ static int stli_setport(stliport_t *portp) * maybe because if we are clocal then we don't need to wait... */ -static int stli_waitcarrier(stlibrd_t *brdp, stliport_t *portp, struct file *filp) +static int stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct file *filp) { unsigned long flags; int rc, doclocal; @@ -1409,8 +1254,8 @@ static int stli_write(struct tty_struct *tty, const unsigned char *buf, int coun unsigned char __iomem *bits; unsigned char __iomem *shbuf; unsigned char *chbuf; - stliport_t *portp; - stlibrd_t *brdp; + struct stliport *portp; + struct stlibrd *brdp; unsigned int len, stlen, head, tail, size; unsigned long flags; @@ -1419,7 +1264,7 @@ static int stli_write(struct tty_struct *tty, const unsigned char *buf, int coun portp = tty->driver_data; if (portp == NULL) return 0; - if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds)) + if (portp->brdnr >= stli_nrbrds) return 0; brdp = stli_brds[portp->brdnr]; if (brdp == NULL) @@ -1445,12 +1290,12 @@ static int stli_write(struct tty_struct *tty, const unsigned char *buf, int coun stlen = len; } - len = MIN(len, count); + len = min(len, (unsigned int)count); count = 0; shbuf = (char __iomem *) EBRDGETMEMPTR(brdp, portp->txoffset); while (len > 0) { - stlen = MIN(len, stlen); + stlen = min(len, stlen); memcpy_toio(shbuf + head, chbuf, stlen); chbuf += stlen; len -= stlen; @@ -1516,8 +1361,8 @@ static void stli_flushchars(struct tty_struct *tty) unsigned char __iomem *bits; cdkasy_t __iomem *ap; struct tty_struct *cooktty; - stliport_t *portp; - stlibrd_t *brdp; + struct stliport *portp; + struct stlibrd *brdp; unsigned int len, stlen, head, tail, size, count, cooksize; unsigned char *buf; unsigned char __iomem *shbuf; @@ -1541,7 +1386,7 @@ static void stli_flushchars(struct tty_struct *tty) portp = tty->driver_data; if (portp == NULL) return; - if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds)) + if (portp->brdnr >= stli_nrbrds) return; brdp = stli_brds[portp->brdnr]; if (brdp == NULL) @@ -1564,13 +1409,13 @@ static void stli_flushchars(struct tty_struct *tty) stlen = len; } - len = MIN(len, cooksize); + len = min(len, cooksize); count = 0; shbuf = EBRDGETMEMPTR(brdp, portp->txoffset); buf = stli_txcookbuf; while (len > 0) { - stlen = MIN(len, stlen); + stlen = min(len, stlen); memcpy_toio(shbuf + head, buf, stlen); buf += stlen; len -= stlen; @@ -1604,8 +1449,8 @@ static void stli_flushchars(struct tty_struct *tty) static int stli_writeroom(struct tty_struct *tty) { cdkasyrq_t __iomem *rp; - stliport_t *portp; - stlibrd_t *brdp; + struct stliport *portp; + struct stlibrd *brdp; unsigned int head, tail, len; unsigned long flags; @@ -1619,7 +1464,7 @@ static int stli_writeroom(struct tty_struct *tty) portp = tty->driver_data; if (portp == NULL) return 0; - if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds)) + if (portp->brdnr >= stli_nrbrds) return 0; brdp = stli_brds[portp->brdnr]; if (brdp == NULL) @@ -1657,8 +1502,8 @@ static int stli_writeroom(struct tty_struct *tty) static int stli_charsinbuffer(struct tty_struct *tty) { cdkasyrq_t __iomem *rp; - stliport_t *portp; - stlibrd_t *brdp; + struct stliport *portp; + struct stlibrd *brdp; unsigned int head, tail, len; unsigned long flags; @@ -1667,7 +1512,7 @@ static int stli_charsinbuffer(struct tty_struct *tty) portp = tty->driver_data; if (portp == NULL) return 0; - if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds)) + if (portp->brdnr >= stli_nrbrds) return 0; brdp = stli_brds[portp->brdnr]; if (brdp == NULL) @@ -1695,10 +1540,10 @@ static int stli_charsinbuffer(struct tty_struct *tty) * Generate the serial struct info. */ -static int stli_getserial(stliport_t *portp, struct serial_struct __user *sp) +static int stli_getserial(struct stliport *portp, struct serial_struct __user *sp) { struct serial_struct sio; - stlibrd_t *brdp; + struct stlibrd *brdp; memset(&sio, 0, sizeof(struct serial_struct)); sio.type = PORT_UNKNOWN; @@ -1728,7 +1573,7 @@ static int stli_getserial(stliport_t *portp, struct serial_struct __user *sp) * just quietly ignore any requests to change irq, etc. */ -static int stli_setserial(stliport_t *portp, struct serial_struct __user *sp) +static int stli_setserial(struct stliport *portp, struct serial_struct __user *sp) { struct serial_struct sio; int rc; @@ -1759,13 +1604,13 @@ static int stli_setserial(stliport_t *portp, struct serial_struct __user *sp) static int stli_tiocmget(struct tty_struct *tty, struct file *file) { - stliport_t *portp = tty->driver_data; - stlibrd_t *brdp; + struct stliport *portp = tty->driver_data; + struct stlibrd *brdp; int rc; if (portp == NULL) return -ENODEV; - if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds) + if (portp->brdnr >= stli_nrbrds) return 0; brdp = stli_brds[portp->brdnr]; if (brdp == NULL) @@ -1783,13 +1628,13 @@ static int stli_tiocmget(struct tty_struct *tty, struct file *file) static int stli_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { - stliport_t *portp = tty->driver_data; - stlibrd_t *brdp; + struct stliport *portp = tty->driver_data; + struct stlibrd *brdp; int rts = -1, dtr = -1; if (portp == NULL) return -ENODEV; - if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds) + if (portp->brdnr >= stli_nrbrds) return 0; brdp = stli_brds[portp->brdnr]; if (brdp == NULL) @@ -1814,8 +1659,8 @@ static int stli_tiocmset(struct tty_struct *tty, struct file *file, static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { - stliport_t *portp; - stlibrd_t *brdp; + struct stliport *portp; + struct stlibrd *brdp; unsigned int ival; int rc; void __user *argp = (void __user *)arg; @@ -1823,7 +1668,7 @@ static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm portp = tty->driver_data; if (portp == NULL) return -ENODEV; - if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds) + if (portp->brdnr >= stli_nrbrds) return 0; brdp = stli_brds[portp->brdnr]; if (brdp == NULL) @@ -1889,11 +1734,11 @@ static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm * Looks like it is true for the current ttys implementation..!! */ -static void stli_settermios(struct tty_struct *tty, struct termios *old) +static void stli_settermios(struct tty_struct *tty, struct ktermios *old) { - stliport_t *portp; - stlibrd_t *brdp; - struct termios *tiosp; + struct stliport *portp; + struct stlibrd *brdp; + struct ktermios *tiosp; asyport_t aport; if (tty == NULL) @@ -1901,7 +1746,7 @@ static void stli_settermios(struct tty_struct *tty, struct termios *old) portp = tty->driver_data; if (portp == NULL) return; - if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds) + if (portp->brdnr >= stli_nrbrds) return; brdp = stli_brds[portp->brdnr]; if (brdp == NULL) @@ -1937,7 +1782,7 @@ static void stli_settermios(struct tty_struct *tty, struct termios *old) static void stli_throttle(struct tty_struct *tty) { - stliport_t *portp = tty->driver_data; + struct stliport *portp = tty->driver_data; if (portp == NULL) return; set_bit(ST_RXSTOP, &portp->state); @@ -1953,7 +1798,7 @@ static void stli_throttle(struct tty_struct *tty) static void stli_unthrottle(struct tty_struct *tty) { - stliport_t *portp = tty->driver_data; + struct stliport *portp = tty->driver_data; if (portp == NULL) return; clear_bit(ST_RXSTOP, &portp->state); @@ -1992,7 +1837,7 @@ static void stli_start(struct tty_struct *tty) static void stli_dohangup(struct work_struct *ugly_api) { - stliport_t *portp = container_of(ugly_api, stliport_t, tqhangup); + struct stliport *portp = container_of(ugly_api, struct stliport, tqhangup); if (portp->tty != NULL) { tty_hangup(portp->tty); } @@ -2009,14 +1854,14 @@ static void stli_dohangup(struct work_struct *ugly_api) static void stli_hangup(struct tty_struct *tty) { - stliport_t *portp; - stlibrd_t *brdp; + struct stliport *portp; + struct stlibrd *brdp; unsigned long flags; portp = tty->driver_data; if (portp == NULL) return; - if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds) + if (portp->brdnr >= stli_nrbrds) return; brdp = stli_brds[portp->brdnr]; if (brdp == NULL) @@ -2062,14 +1907,14 @@ static void stli_hangup(struct tty_struct *tty) static void stli_flushbuffer(struct tty_struct *tty) { - stliport_t *portp; - stlibrd_t *brdp; + struct stliport *portp; + struct stlibrd *brdp; unsigned long ftype, flags; portp = tty->driver_data; if (portp == NULL) return; - if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds) + if (portp->brdnr >= stli_nrbrds) return; brdp = stli_brds[portp->brdnr]; if (brdp == NULL) @@ -2099,14 +1944,14 @@ static void stli_flushbuffer(struct tty_struct *tty) static void stli_breakctl(struct tty_struct *tty, int state) { - stlibrd_t *brdp; - stliport_t *portp; + struct stlibrd *brdp; + struct stliport *portp; long arg; portp = tty->driver_data; if (portp == NULL) return; - if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds) + if (portp->brdnr >= stli_nrbrds) return; brdp = stli_brds[portp->brdnr]; if (brdp == NULL) @@ -2120,7 +1965,7 @@ static void stli_breakctl(struct tty_struct *tty, int state) static void stli_waituntilsent(struct tty_struct *tty, int timeout) { - stliport_t *portp; + struct stliport *portp; unsigned long tend; if (tty == NULL) @@ -2146,14 +1991,14 @@ static void stli_waituntilsent(struct tty_struct *tty, int timeout) static void stli_sendxchar(struct tty_struct *tty, char ch) { - stlibrd_t *brdp; - stliport_t *portp; + struct stlibrd *brdp; + struct stliport *portp; asyctrl_t actrl; portp = tty->driver_data; if (portp == NULL) return; - if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds) + if (portp->brdnr >= stli_nrbrds) return; brdp = stli_brds[portp->brdnr]; if (brdp == NULL) @@ -2181,7 +2026,7 @@ static void stli_sendxchar(struct tty_struct *tty, char ch) * short then padded with spaces). */ -static int stli_portinfo(stlibrd_t *brdp, stliport_t *portp, int portnr, char *pos) +static int stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portnr, char *pos) { char *sp, *uart; int rc, cnt; @@ -2244,9 +2089,9 @@ static int stli_portinfo(stlibrd_t *brdp, stliport_t *portp, int portnr, char *p static int stli_readproc(char *page, char **start, off_t off, int count, int *eof, void *data) { - stlibrd_t *brdp; - stliport_t *portp; - int brdnr, portnr, totalport; + struct stlibrd *brdp; + struct stliport *portp; + unsigned int brdnr, portnr, totalport; int curoff, maxoff; char *pos; @@ -2316,7 +2161,7 @@ stli_readdone: * entry point) */ -static void __stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback) +static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback) { cdkhdr_t __iomem *hdrp; cdkctrl_t __iomem *cp; @@ -2352,7 +2197,7 @@ static void __stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd spin_unlock_irqrestore(&brd_lock, flags); } -static void stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback) +static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback) { unsigned long flags; @@ -2371,7 +2216,7 @@ static void stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, * more chars to unload. */ -static void stli_read(stlibrd_t *brdp, stliport_t *portp) +static void stli_read(struct stlibrd *brdp, struct stliport *portp) { cdkasyrq_t __iomem *rp; char __iomem *shbuf; @@ -2406,7 +2251,7 @@ static void stli_read(stlibrd_t *brdp, stliport_t *portp) while (len > 0) { unsigned char *cptr; - stlen = MIN(len, stlen); + stlen = min(len, stlen); tty_prepare_flip_string(tty, &cptr, stlen); memcpy_fromio(cptr, shbuf + tail, stlen); len -= stlen; @@ -2433,7 +2278,7 @@ static void stli_read(stlibrd_t *brdp, stliport_t *portp) * difficult to deal with them here. */ -static void stli_dodelaycmd(stliport_t *portp, cdkctrl_t __iomem *cp) +static void stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp) { int cmd; @@ -2481,7 +2326,7 @@ static void stli_dodelaycmd(stliport_t *portp, cdkctrl_t __iomem *cp) * then port is still busy, otherwise no longer busy. */ -static int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp) +static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp) { cdkasy_t __iomem *ap; cdkctrl_t __iomem *cp; @@ -2628,9 +2473,9 @@ static int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp) * at the cdk header structure. */ -static void stli_brdpoll(stlibrd_t *brdp, cdkhdr_t __iomem *hdrp) +static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp) { - stliport_t *portp; + struct stliport *portp; unsigned char hostbits[(STL_MAXCHANS / 8) + 1]; unsigned char slavebits[(STL_MAXCHANS / 8) + 1]; unsigned char __iomem *slavep; @@ -2697,11 +2542,10 @@ static void stli_brdpoll(stlibrd_t *brdp, cdkhdr_t __iomem *hdrp) static void stli_poll(unsigned long arg) { cdkhdr_t __iomem *hdrp; - stlibrd_t *brdp; - int brdnr; + struct stlibrd *brdp; + unsigned int brdnr; - stli_timerlist.expires = STLI_TIMEOUT; - add_timer(&stli_timerlist); + mod_timer(&stli_timerlist, STLI_TIMEOUT); /* * Check each board and do any servicing required. @@ -2730,7 +2574,7 @@ static void stli_poll(unsigned long arg) * the slave. */ -static void stli_mkasyport(stliport_t *portp, asyport_t *pp, struct termios *tiosp) +static void stli_mkasyport(struct stliport *portp, asyport_t *pp, struct ktermios *tiosp) { memset(pp, 0, sizeof(asyport_t)); @@ -2879,13 +2723,13 @@ static long stli_mktiocm(unsigned long sigvalue) * we need to do here is set up the appropriate per port data structures. */ -static int stli_initports(stlibrd_t *brdp) +static int stli_initports(struct stlibrd *brdp) { - stliport_t *portp; - int i, panelnr, panelport; + struct stliport *portp; + unsigned int i, panelnr, panelport; for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) { - portp = kzalloc(sizeof(stliport_t), GFP_KERNEL); + portp = kzalloc(sizeof(struct stliport), GFP_KERNEL); if (!portp) { printk("STALLION: failed to allocate port structure\n"); continue; @@ -2919,7 +2763,7 @@ static int stli_initports(stlibrd_t *brdp) * All the following routines are board specific hardware operations. */ -static void stli_ecpinit(stlibrd_t *brdp) +static void stli_ecpinit(struct stlibrd *brdp) { unsigned long memconf; @@ -2934,21 +2778,21 @@ static void stli_ecpinit(stlibrd_t *brdp) /*****************************************************************************/ -static void stli_ecpenable(stlibrd_t *brdp) +static void stli_ecpenable(struct stlibrd *brdp) { outb(ECP_ATENABLE, (brdp->iobase + ECP_ATCONFR)); } /*****************************************************************************/ -static void stli_ecpdisable(stlibrd_t *brdp) +static void stli_ecpdisable(struct stlibrd *brdp) { outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR)); } /*****************************************************************************/ -static void __iomem *stli_ecpgetmemptr(stlibrd_t *brdp, unsigned long offset, int line) +static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offset, int line) { void __iomem *ptr; unsigned char val; @@ -2969,7 +2813,7 @@ static void __iomem *stli_ecpgetmemptr(stlibrd_t *brdp, unsigned long offset, in /*****************************************************************************/ -static void stli_ecpreset(stlibrd_t *brdp) +static void stli_ecpreset(struct stlibrd *brdp) { outb(ECP_ATSTOP, (brdp->iobase + ECP_ATCONFR)); udelay(10); @@ -2979,7 +2823,7 @@ static void stli_ecpreset(stlibrd_t *brdp) /*****************************************************************************/ -static void stli_ecpintr(stlibrd_t *brdp) +static void stli_ecpintr(struct stlibrd *brdp) { outb(0x1, brdp->iobase); } @@ -2990,7 +2834,7 @@ static void stli_ecpintr(stlibrd_t *brdp) * The following set of functions act on ECP EISA boards. */ -static void stli_ecpeiinit(stlibrd_t *brdp) +static void stli_ecpeiinit(struct stlibrd *brdp) { unsigned long memconf; @@ -3008,21 +2852,21 @@ static void stli_ecpeiinit(stlibrd_t *brdp) /*****************************************************************************/ -static void stli_ecpeienable(stlibrd_t *brdp) +static void stli_ecpeienable(struct stlibrd *brdp) { outb(ECP_EIENABLE, (brdp->iobase + ECP_EICONFR)); } /*****************************************************************************/ -static void stli_ecpeidisable(stlibrd_t *brdp) +static void stli_ecpeidisable(struct stlibrd *brdp) { outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR)); } /*****************************************************************************/ -static void __iomem *stli_ecpeigetmemptr(stlibrd_t *brdp, unsigned long offset, int line) +static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long offset, int line) { void __iomem *ptr; unsigned char val; @@ -3046,7 +2890,7 @@ static void __iomem *stli_ecpeigetmemptr(stlibrd_t *brdp, unsigned long offset, /*****************************************************************************/ -static void stli_ecpeireset(stlibrd_t *brdp) +static void stli_ecpeireset(struct stlibrd *brdp) { outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR)); udelay(10); @@ -3060,21 +2904,21 @@ static void stli_ecpeireset(stlibrd_t *brdp) * The following set of functions act on ECP MCA boards. */ -static void stli_ecpmcenable(stlibrd_t *brdp) +static void stli_ecpmcenable(struct stlibrd *brdp) { outb(ECP_MCENABLE, (brdp->iobase + ECP_MCCONFR)); } /*****************************************************************************/ -static void stli_ecpmcdisable(stlibrd_t *brdp) +static void stli_ecpmcdisable(struct stlibrd *brdp) { outb(ECP_MCDISABLE, (brdp->iobase + ECP_MCCONFR)); } /*****************************************************************************/ -static void __iomem *stli_ecpmcgetmemptr(stlibrd_t *brdp, unsigned long offset, int line) +static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long offset, int line) { void __iomem *ptr; unsigned char val; @@ -3095,7 +2939,7 @@ static void __iomem *stli_ecpmcgetmemptr(stlibrd_t *brdp, unsigned long offset, /*****************************************************************************/ -static void stli_ecpmcreset(stlibrd_t *brdp) +static void stli_ecpmcreset(struct stlibrd *brdp) { outb(ECP_MCSTOP, (brdp->iobase + ECP_MCCONFR)); udelay(10); @@ -3109,7 +2953,7 @@ static void stli_ecpmcreset(stlibrd_t *brdp) * The following set of functions act on ECP PCI boards. */ -static void stli_ecppciinit(stlibrd_t *brdp) +static void stli_ecppciinit(struct stlibrd *brdp) { outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR)); udelay(10); @@ -3119,7 +2963,7 @@ static void stli_ecppciinit(stlibrd_t *brdp) /*****************************************************************************/ -static void __iomem *stli_ecppcigetmemptr(stlibrd_t *brdp, unsigned long offset, int line) +static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long offset, int line) { void __iomem *ptr; unsigned char val; @@ -3140,7 +2984,7 @@ static void __iomem *stli_ecppcigetmemptr(stlibrd_t *brdp, unsigned long offset, /*****************************************************************************/ -static void stli_ecppcireset(stlibrd_t *brdp) +static void stli_ecppcireset(struct stlibrd *brdp) { outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR)); udelay(10); @@ -3154,7 +2998,7 @@ static void stli_ecppcireset(stlibrd_t *brdp) * The following routines act on ONboards. */ -static void stli_onbinit(stlibrd_t *brdp) +static void stli_onbinit(struct stlibrd *brdp) { unsigned long memconf; @@ -3171,21 +3015,21 @@ static void stli_onbinit(stlibrd_t *brdp) /*****************************************************************************/ -static void stli_onbenable(stlibrd_t *brdp) +static void stli_onbenable(struct stlibrd *brdp) { outb((brdp->enabval | ONB_ATENABLE), (brdp->iobase + ONB_ATCONFR)); } /*****************************************************************************/ -static void stli_onbdisable(stlibrd_t *brdp) +static void stli_onbdisable(struct stlibrd *brdp) { outb((brdp->enabval | ONB_ATDISABLE), (brdp->iobase + ONB_ATCONFR)); } /*****************************************************************************/ -static void __iomem *stli_onbgetmemptr(stlibrd_t *brdp, unsigned long offset, int line) +static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offset, int line) { void __iomem *ptr; @@ -3202,7 +3046,7 @@ static void __iomem *stli_onbgetmemptr(stlibrd_t *brdp, unsigned long offset, in /*****************************************************************************/ -static void stli_onbreset(stlibrd_t *brdp) +static void stli_onbreset(struct stlibrd *brdp) { outb(ONB_ATSTOP, (brdp->iobase + ONB_ATCONFR)); udelay(10); @@ -3216,7 +3060,7 @@ static void stli_onbreset(stlibrd_t *brdp) * The following routines act on ONboard EISA. */ -static void stli_onbeinit(stlibrd_t *brdp) +static void stli_onbeinit(struct stlibrd *brdp) { unsigned long memconf; @@ -3236,21 +3080,21 @@ static void stli_onbeinit(stlibrd_t *brdp) /*****************************************************************************/ -static void stli_onbeenable(stlibrd_t *brdp) +static void stli_onbeenable(struct stlibrd *brdp) { outb(ONB_EIENABLE, (brdp->iobase + ONB_EICONFR)); } /*****************************************************************************/ -static void stli_onbedisable(stlibrd_t *brdp) +static void stli_onbedisable(struct stlibrd *brdp) { outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR)); } /*****************************************************************************/ -static void __iomem *stli_onbegetmemptr(stlibrd_t *brdp, unsigned long offset, int line) +static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offset, int line) { void __iomem *ptr; unsigned char val; @@ -3274,7 +3118,7 @@ static void __iomem *stli_onbegetmemptr(stlibrd_t *brdp, unsigned long offset, i /*****************************************************************************/ -static void stli_onbereset(stlibrd_t *brdp) +static void stli_onbereset(struct stlibrd *brdp) { outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR)); udelay(10); @@ -3288,7 +3132,7 @@ static void stli_onbereset(stlibrd_t *brdp) * The following routines act on Brumby boards. */ -static void stli_bbyinit(stlibrd_t *brdp) +static void stli_bbyinit(struct stlibrd *brdp) { outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR)); udelay(10); @@ -3300,7 +3144,7 @@ static void stli_bbyinit(stlibrd_t *brdp) /*****************************************************************************/ -static void __iomem *stli_bbygetmemptr(stlibrd_t *brdp, unsigned long offset, int line) +static void __iomem *stli_bbygetmemptr(struct stlibrd *brdp, unsigned long offset, int line) { void __iomem *ptr; unsigned char val; @@ -3315,7 +3159,7 @@ static void __iomem *stli_bbygetmemptr(stlibrd_t *brdp, unsigned long offset, in /*****************************************************************************/ -static void stli_bbyreset(stlibrd_t *brdp) +static void stli_bbyreset(struct stlibrd *brdp) { outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR)); udelay(10); @@ -3329,7 +3173,7 @@ static void stli_bbyreset(stlibrd_t *brdp) * The following routines act on original old Stallion boards. */ -static void stli_stalinit(stlibrd_t *brdp) +static void stli_stalinit(struct stlibrd *brdp) { outb(0x1, brdp->iobase); mdelay(1000); @@ -3337,7 +3181,7 @@ static void stli_stalinit(stlibrd_t *brdp) /*****************************************************************************/ -static void __iomem *stli_stalgetmemptr(stlibrd_t *brdp, unsigned long offset, int line) +static void __iomem *stli_stalgetmemptr(struct stlibrd *brdp, unsigned long offset, int line) { BUG_ON(offset > brdp->memsize); return brdp->membase + (offset % STAL_PAGESIZE); @@ -3345,7 +3189,7 @@ static void __iomem *stli_stalgetmemptr(stlibrd_t *brdp, unsigned long offset, i /*****************************************************************************/ -static void stli_stalreset(stlibrd_t *brdp) +static void stli_stalreset(struct stlibrd *brdp) { u32 __iomem *vecp; @@ -3362,21 +3206,22 @@ static void stli_stalreset(stlibrd_t *brdp) * board types. */ -static int stli_initecp(stlibrd_t *brdp) +static int stli_initecp(struct stlibrd *brdp) { cdkecpsig_t sig; cdkecpsig_t __iomem *sigsp; unsigned int status, nxtid; char *name; - int panelnr, nrports; + int retval, panelnr, nrports; - if (!request_region(brdp->iobase, brdp->iosize, "istallion")) - return -EIO; - - if ((brdp->iobase == 0) || (brdp->memaddr == 0)) - { - release_region(brdp->iobase, brdp->iosize); - return -ENODEV; + if ((brdp->iobase == 0) || (brdp->memaddr == 0)) { + retval = -ENODEV; + goto err; + } + + if (!request_region(brdp->iobase, brdp->iosize, "istallion")) { + retval = -EIO; + goto err; } brdp->iosize = ECP_IOSIZE; @@ -3388,7 +3233,6 @@ static int stli_initecp(stlibrd_t *brdp) */ switch (brdp->brdtype) { case BRD_ECP: - brdp->membase = (void *) brdp->memaddr; brdp->memsize = ECP_MEMSIZE; brdp->pagesize = ECP_ATPAGESIZE; brdp->init = stli_ecpinit; @@ -3402,7 +3246,6 @@ static int stli_initecp(stlibrd_t *brdp) break; case BRD_ECPE: - brdp->membase = (void *) brdp->memaddr; brdp->memsize = ECP_MEMSIZE; brdp->pagesize = ECP_EIPAGESIZE; brdp->init = stli_ecpeiinit; @@ -3416,7 +3259,6 @@ static int stli_initecp(stlibrd_t *brdp) break; case BRD_ECPMC: - brdp->membase = (void *) brdp->memaddr; brdp->memsize = ECP_MEMSIZE; brdp->pagesize = ECP_MCPAGESIZE; brdp->init = NULL; @@ -3430,7 +3272,6 @@ static int stli_initecp(stlibrd_t *brdp) break; case BRD_ECPPCI: - brdp->membase = (void *) brdp->memaddr; brdp->memsize = ECP_PCIMEMSIZE; brdp->pagesize = ECP_PCIPAGESIZE; brdp->init = stli_ecppciinit; @@ -3444,8 +3285,8 @@ static int stli_initecp(stlibrd_t *brdp) break; default: - release_region(brdp->iobase, brdp->iosize); - return -EINVAL; + retval = -EINVAL; + goto err_reg; } /* @@ -3457,10 +3298,9 @@ static int stli_initecp(stlibrd_t *brdp) EBRDINIT(brdp); brdp->membase = ioremap(brdp->memaddr, brdp->memsize); - if (brdp->membase == NULL) - { - release_region(brdp->iobase, brdp->iosize); - return -ENOMEM; + if (brdp->membase == NULL) { + retval = -ENOMEM; + goto err_reg; } /* @@ -3473,12 +3313,9 @@ static int stli_initecp(stlibrd_t *brdp) memcpy_fromio(&sig, sigsp, sizeof(cdkecpsig_t)); EBRDDISABLE(brdp); - if (sig.magic != cpu_to_le32(ECP_MAGIC)) - { - release_region(brdp->iobase, brdp->iosize); - iounmap(brdp->membase); - brdp->membase = NULL; - return -ENODEV; + if (sig.magic != cpu_to_le32(ECP_MAGIC)) { + retval = -ENODEV; + goto err_unmap; } /* @@ -3503,6 +3340,13 @@ static int stli_initecp(stlibrd_t *brdp) brdp->state |= BST_FOUND; return 0; +err_unmap: + iounmap(brdp->membase); + brdp->membase = NULL; +err_reg: + release_region(brdp->iobase, brdp->iosize); +err: + return retval; } /*****************************************************************************/ @@ -3512,23 +3356,27 @@ static int stli_initecp(stlibrd_t *brdp) * This handles only these board types. */ -static int stli_initonb(stlibrd_t *brdp) +static int stli_initonb(struct stlibrd *brdp) { cdkonbsig_t sig; cdkonbsig_t __iomem *sigsp; char *name; - int i; + int i, retval; /* * Do a basic sanity check on the IO and memory addresses. */ - if (brdp->iobase == 0 || brdp->memaddr == 0) - return -ENODEV; + if (brdp->iobase == 0 || brdp->memaddr == 0) { + retval = -ENODEV; + goto err; + } brdp->iosize = ONB_IOSIZE; - if (!request_region(brdp->iobase, brdp->iosize, "istallion")) - return -EIO; + if (!request_region(brdp->iobase, brdp->iosize, "istallion")) { + retval = -EIO; + goto err; + } /* * Based on the specific board type setup the common vars to access @@ -3537,10 +3385,7 @@ static int stli_initonb(stlibrd_t *brdp) */ switch (brdp->brdtype) { case BRD_ONBOARD: - case BRD_ONBOARD32: case BRD_ONBOARD2: - case BRD_ONBOARD2_32: - case BRD_ONBOARDRS: brdp->memsize = ONB_MEMSIZE; brdp->pagesize = ONB_ATPAGESIZE; brdp->init = stli_onbinit; @@ -3571,8 +3416,6 @@ static int stli_initonb(stlibrd_t *brdp) break; case BRD_BRUMBY4: - case BRD_BRUMBY8: - case BRD_BRUMBY16: brdp->memsize = BBY_MEMSIZE; brdp->pagesize = BBY_PAGESIZE; brdp->init = stli_bbyinit; @@ -3599,8 +3442,8 @@ static int stli_initonb(stlibrd_t *brdp) break; default: - release_region(brdp->iobase, brdp->iosize); - return -EINVAL; + retval = -EINVAL; + goto err_reg; } /* @@ -3612,10 +3455,9 @@ static int stli_initonb(stlibrd_t *brdp) EBRDINIT(brdp); brdp->membase = ioremap(brdp->memaddr, brdp->memsize); - if (brdp->membase == NULL) - { - release_region(brdp->iobase, brdp->iosize); - return -ENOMEM; + if (brdp->membase == NULL) { + retval = -ENOMEM; + goto err_reg; } /* @@ -3631,12 +3473,9 @@ static int stli_initonb(stlibrd_t *brdp) if (sig.magic0 != cpu_to_le16(ONB_MAGIC0) || sig.magic1 != cpu_to_le16(ONB_MAGIC1) || sig.magic2 != cpu_to_le16(ONB_MAGIC2) || - sig.magic3 != cpu_to_le16(ONB_MAGIC3)) - { - release_region(brdp->iobase, brdp->iosize); - iounmap(brdp->membase); - brdp->membase = NULL; - return -ENODEV; + sig.magic3 != cpu_to_le16(ONB_MAGIC3)) { + retval = -ENODEV; + goto err_unmap; } /* @@ -3658,6 +3497,13 @@ static int stli_initonb(stlibrd_t *brdp) brdp->state |= BST_FOUND; return 0; +err_unmap: + iounmap(brdp->membase); + brdp->membase = NULL; +err_reg: + release_region(brdp->iobase, brdp->iosize); +err: + return retval; } /*****************************************************************************/ @@ -3668,14 +3514,15 @@ static int stli_initonb(stlibrd_t *brdp) * read in the memory map, and get the show on the road... */ -static int stli_startbrd(stlibrd_t *brdp) +static int stli_startbrd(struct stlibrd *brdp) { cdkhdr_t __iomem *hdrp; cdkmem_t __iomem *memp; cdkasy_t __iomem *ap; unsigned long flags; - stliport_t *portp; - int portnr, nrdevs, i, rc = 0; + unsigned int portnr, nrdevs, i; + struct stliport *portp; + int rc = 0; u32 memoff; spin_lock_irqsave(&brd_lock, flags); @@ -3762,8 +3609,7 @@ stli_donestartup: if (! stli_timeron) { stli_timeron++; - stli_timerlist.expires = STLI_TIMEOUT; - add_timer(&stli_timerlist); + mod_timer(&stli_timerlist, STLI_TIMEOUT); } return rc; @@ -3775,49 +3621,32 @@ stli_donestartup: * Probe and initialize the specified board. */ -static int __init stli_brdinit(stlibrd_t *brdp) +static int __devinit stli_brdinit(struct stlibrd *brdp) { - stli_brds[brdp->brdnr] = brdp; + int retval; switch (brdp->brdtype) { case BRD_ECP: case BRD_ECPE: case BRD_ECPMC: case BRD_ECPPCI: - stli_initecp(brdp); + retval = stli_initecp(brdp); break; case BRD_ONBOARD: case BRD_ONBOARDE: case BRD_ONBOARD2: - case BRD_ONBOARD32: - case BRD_ONBOARD2_32: - case BRD_ONBOARDRS: case BRD_BRUMBY4: - case BRD_BRUMBY8: - case BRD_BRUMBY16: case BRD_STALLION: - stli_initonb(brdp); + retval = stli_initonb(brdp); break; - case BRD_EASYIO: - case BRD_ECH: - case BRD_ECHMC: - case BRD_ECHPCI: - printk(KERN_ERR "STALLION: %s board type not supported in " - "this driver\n", stli_brdnames[brdp->brdtype]); - return -ENODEV; default: printk(KERN_ERR "STALLION: board=%d is unknown board " "type=%d\n", brdp->brdnr, brdp->brdtype); - return -ENODEV; + retval = -ENODEV; } - if ((brdp->state & BST_FOUND) == 0) { - printk(KERN_ERR "STALLION: %s board not found, board=%d " - "io=%x mem=%x\n", - stli_brdnames[brdp->brdtype], brdp->brdnr, - brdp->iobase, (int) brdp->memaddr); - return -ENODEV; - } + if (retval) + return retval; stli_initports(brdp); printk(KERN_INFO "STALLION: %s found, board=%d io=%x mem=%x " @@ -3827,6 +3656,7 @@ static int __init stli_brdinit(stlibrd_t *brdp) return 0; } +#if STLI_EISAPROBE != 0 /*****************************************************************************/ /* @@ -3834,7 +3664,7 @@ static int __init stli_brdinit(stlibrd_t *brdp) * might be. This is a bit if hack, but it is the best we can do. */ -static int stli_eisamemprobe(stlibrd_t *brdp) +static int stli_eisamemprobe(struct stlibrd *brdp) { cdkecpsig_t ecpsig, __iomem *ecpsigp; cdkonbsig_t onbsig, __iomem *onbsigp; @@ -3920,10 +3750,11 @@ static int stli_eisamemprobe(stlibrd_t *brdp) } return 0; } +#endif static int stli_getbrdnr(void) { - int i; + unsigned int i; for (i = 0; i < STL_MAXBRDS; i++) { if (!stli_brds[i]) { @@ -3935,6 +3766,7 @@ static int stli_getbrdnr(void) return -1; } +#if STLI_EISAPROBE != 0 /*****************************************************************************/ /* @@ -3949,9 +3781,9 @@ static int stli_getbrdnr(void) static int stli_findeisabrds(void) { - stlibrd_t *brdp; - unsigned int iobase, eid; - int i; + struct stlibrd *brdp; + unsigned int iobase, eid, i; + int brdnr, found = 0; /* * Firstly check if this is an EISA system. If this is not an EISA system then @@ -3989,9 +3821,11 @@ static int stli_findeisabrds(void) * Allocate a board structure and initialize it. */ if ((brdp = stli_allocbrd()) == NULL) - return -ENOMEM; - if ((brdp->brdnr = stli_getbrdnr()) < 0) - return -ENOMEM; + return found ? : -ENOMEM; + brdnr = stli_getbrdnr(); + if (brdnr < 0) + return found ? : -ENOMEM; + brdp->brdnr = (unsigned int)brdnr; eid = inb(iobase + 0xc82); if (eid == ECP_EISAID) brdp->brdtype = BRD_ECPE; @@ -4003,11 +3837,24 @@ static int stli_findeisabrds(void) outb(0x1, (iobase + 0xc84)); if (stli_eisamemprobe(brdp)) outb(0, (iobase + 0xc84)); - stli_brdinit(brdp); + if (stli_brdinit(brdp) < 0) { + kfree(brdp); + continue; + } + + stli_brds[brdp->brdnr] = brdp; + found++; + + for (i = 0; i < brdp->nrports; i++) + tty_register_device(stli_serial, + brdp->brdnr * STL_MAXPORTS + i, NULL); } - return 0; + return found; } +#else +static inline int stli_findeisabrds(void) { return 0; } +#endif /*****************************************************************************/ @@ -4017,72 +3864,104 @@ static int stli_findeisabrds(void) /*****************************************************************************/ -#ifdef CONFIG_PCI - /* * We have a Stallion board. Allocate a board structure and * initialize it. Read its IO and MEMORY resources from PCI * configuration space. */ -static int stli_initpcibrd(int brdtype, struct pci_dev *devp) +static int __devinit stli_pciprobe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - stlibrd_t *brdp; - - if (pci_enable_device(devp)) - return -EIO; - if ((brdp = stli_allocbrd()) == NULL) - return -ENOMEM; - if ((brdp->brdnr = stli_getbrdnr()) < 0) { + struct stlibrd *brdp; + unsigned int i; + int brdnr, retval = -EIO; + + retval = pci_enable_device(pdev); + if (retval) + goto err; + brdp = stli_allocbrd(); + if (brdp == NULL) { + retval = -ENOMEM; + goto err; + } + mutex_lock(&stli_brdslock); + brdnr = stli_getbrdnr(); + if (brdnr < 0) { printk(KERN_INFO "STALLION: too many boards found, " "maximum supported %d\n", STL_MAXBRDS); - return 0; + mutex_unlock(&stli_brdslock); + retval = -EIO; + goto err_fr; } - brdp->brdtype = brdtype; + brdp->brdnr = (unsigned int)brdnr; + stli_brds[brdp->brdnr] = brdp; + mutex_unlock(&stli_brdslock); + brdp->brdtype = BRD_ECPPCI; /* * We have all resources from the board, so lets setup the actual * board structure now. */ - brdp->iobase = pci_resource_start(devp, 3); - brdp->memaddr = pci_resource_start(devp, 2); - stli_brdinit(brdp); + brdp->iobase = pci_resource_start(pdev, 3); + brdp->memaddr = pci_resource_start(pdev, 2); + retval = stli_brdinit(brdp); + if (retval) + goto err_null; + + brdp->state |= BST_PROBED; + pci_set_drvdata(pdev, brdp); + + EBRDENABLE(brdp); + brdp->enable = NULL; + brdp->disable = NULL; + + for (i = 0; i < brdp->nrports; i++) + tty_register_device(stli_serial, brdp->brdnr * STL_MAXPORTS + i, + &pdev->dev); return 0; +err_null: + stli_brds[brdp->brdnr] = NULL; +err_fr: + kfree(brdp); +err: + return retval; } -/*****************************************************************************/ +static void stli_pciremove(struct pci_dev *pdev) +{ + struct stlibrd *brdp = pci_get_drvdata(pdev); -/* - * Find all Stallion PCI boards that might be installed. Initialize each - * one as it is found. - */ + stli_cleanup_ports(brdp); -static int stli_findpcibrds(void) -{ - struct pci_dev *dev = NULL; + iounmap(brdp->membase); + if (brdp->iosize > 0) + release_region(brdp->iobase, brdp->iosize); - while ((dev = pci_get_device(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECRA, dev))) { - stli_initpcibrd(BRD_ECPPCI, dev); - } - return 0; + stli_brds[brdp->brdnr] = NULL; + kfree(brdp); } -#endif - +static struct pci_driver stli_pcidriver = { + .name = "istallion", + .id_table = istallion_pci_tbl, + .probe = stli_pciprobe, + .remove = __devexit_p(stli_pciremove) +}; /*****************************************************************************/ /* * Allocate a new board structure. Fill out the basic info in it. */ -static stlibrd_t *stli_allocbrd(void) +static struct stlibrd *stli_allocbrd(void) { - stlibrd_t *brdp; + struct stlibrd *brdp; - brdp = kzalloc(sizeof(stlibrd_t), GFP_KERNEL); + brdp = kzalloc(sizeof(struct stlibrd), GFP_KERNEL); if (!brdp) { printk(KERN_ERR "STALLION: failed to allocate memory " - "(size=%Zd)\n", sizeof(stlibrd_t)); + "(size=%Zd)\n", sizeof(struct stlibrd)); return NULL; } brdp->magic = STLI_BOARDMAGIC; @@ -4098,43 +3977,37 @@ static stlibrd_t *stli_allocbrd(void) static int stli_initbrds(void) { - stlibrd_t *brdp, *nxtbrdp; - stlconf_t *confp; - int i, j; - - if (stli_nrbrds > STL_MAXBRDS) { - printk(KERN_INFO "STALLION: too many boards in configuration " - "table, truncating to %d\n", STL_MAXBRDS); - stli_nrbrds = STL_MAXBRDS; - } + struct stlibrd *brdp, *nxtbrdp; + struct stlconf conf; + unsigned int i, j, found = 0; + int retval; -/* - * Firstly scan the list of static boards configured. Allocate - * resources and initialize the boards as found. If this is a - * module then let the module args override static configuration. - */ - for (i = 0; (i < stli_nrbrds); i++) { - confp = &stli_brdconf[i]; - stli_parsebrd(confp, stli_brdsp[i]); + for (stli_nrbrds = 0; stli_nrbrds < ARRAY_SIZE(stli_brdsp); + stli_nrbrds++) { + memset(&conf, 0, sizeof(conf)); + if (stli_parsebrd(&conf, stli_brdsp[stli_nrbrds]) == 0) + continue; if ((brdp = stli_allocbrd()) == NULL) - return -ENOMEM; - brdp->brdnr = i; - brdp->brdtype = confp->brdtype; - brdp->iobase = confp->ioaddr1; - brdp->memaddr = confp->memaddr; - stli_brdinit(brdp); + continue; + brdp->brdnr = stli_nrbrds; + brdp->brdtype = conf.brdtype; + brdp->iobase = conf.ioaddr1; + brdp->memaddr = conf.memaddr; + if (stli_brdinit(brdp) < 0) { + kfree(brdp); + continue; + } + stli_brds[brdp->brdnr] = brdp; + found++; + + for (i = 0; i < brdp->nrports; i++) + tty_register_device(stli_serial, + brdp->brdnr * STL_MAXPORTS + i, NULL); } -/* - * Static configuration table done, so now use dynamic methods to - * see if any more boards should be configured. - */ - stli_argbrds(); - if (STLI_EISAPROBE) - stli_findeisabrds(); -#ifdef CONFIG_PCI - stli_findpcibrds(); -#endif + retval = stli_findeisabrds(); + if (retval > 0) + found += retval; /* * All found boards are initialized. Now for a little optimization, if @@ -4174,7 +4047,16 @@ static int stli_initbrds(void) } } + retval = pci_register_driver(&stli_pcidriver); + if (retval && found == 0) { + printk(KERN_ERR "Neither isa nor eisa cards found nor pci " + "driver can be registered!\n"); + goto err; + } + return 0; +err: + return retval; } /*****************************************************************************/ @@ -4189,12 +4071,13 @@ static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, lof { unsigned long flags; void __iomem *memptr; - stlibrd_t *brdp; - int brdnr, size, n; + struct stlibrd *brdp; + unsigned int brdnr; + int size, n; void *p; loff_t off = *offp; - brdnr = iminor(fp->f_dentry->d_inode); + brdnr = iminor(fp->f_path.dentry->d_inode); if (brdnr >= stli_nrbrds) return -ENODEV; brdp = stli_brds[brdnr]; @@ -4205,7 +4088,7 @@ static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, lof if (off >= brdp->memsize || off + count < off) return 0; - size = MIN(count, (brdp->memsize - off)); + size = min(count, (size_t)(brdp->memsize - off)); /* * Copy the data a page at a time @@ -4219,8 +4102,8 @@ static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, lof spin_lock_irqsave(&brd_lock, flags); EBRDENABLE(brdp); memptr = EBRDGETMEMPTR(brdp, off); - n = MIN(size, (brdp->pagesize - (((unsigned long) off) % brdp->pagesize))); - n = MIN(n, PAGE_SIZE); + n = min(size, (int)(brdp->pagesize - (((unsigned long) off) % brdp->pagesize))); + n = min(n, (int)PAGE_SIZE); memcpy_fromio(p, memptr, n); EBRDDISABLE(brdp); spin_unlock_irqrestore(&brd_lock, flags); @@ -4252,13 +4135,14 @@ static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t cou { unsigned long flags; void __iomem *memptr; - stlibrd_t *brdp; + struct stlibrd *brdp; char __user *chbuf; - int brdnr, size, n; + unsigned int brdnr; + int size, n; void *p; loff_t off = *offp; - brdnr = iminor(fp->f_dentry->d_inode); + brdnr = iminor(fp->f_path.dentry->d_inode); if (brdnr >= stli_nrbrds) return -ENODEV; @@ -4271,7 +4155,7 @@ static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t cou return 0; chbuf = (char __user *) buf; - size = MIN(count, (brdp->memsize - off)); + size = min(count, (size_t)(brdp->memsize - off)); /* * Copy the data a page at a time @@ -4282,8 +4166,8 @@ static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t cou return -ENOMEM; while (size > 0) { - n = MIN(size, (brdp->pagesize - (((unsigned long) off) % brdp->pagesize))); - n = MIN(n, PAGE_SIZE); + n = min(size, (int)(brdp->pagesize - (((unsigned long) off) % brdp->pagesize))); + n = min(n, (int)PAGE_SIZE); if (copy_from_user(p, chbuf, n)) { if (count == 0) count = -EFAULT; @@ -4313,8 +4197,8 @@ out: static int stli_getbrdstats(combrd_t __user *bp) { - stlibrd_t *brdp; - int i; + struct stlibrd *brdp; + unsigned int i; if (copy_from_user(&stli_brdstats, bp, sizeof(combrd_t))) return -EFAULT; @@ -4350,19 +4234,20 @@ static int stli_getbrdstats(combrd_t __user *bp) * Resolve the referenced port number into a port struct pointer. */ -static stliport_t *stli_getport(int brdnr, int panelnr, int portnr) +static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr, + unsigned int portnr) { - stlibrd_t *brdp; - int i; + struct stlibrd *brdp; + unsigned int i; - if (brdnr < 0 || brdnr >= STL_MAXBRDS) + if (brdnr >= STL_MAXBRDS) return NULL; brdp = stli_brds[brdnr]; if (brdp == NULL) return NULL; for (i = 0; (i < panelnr); i++) portnr += brdp->panels[i]; - if ((portnr < 0) || (portnr >= brdp->nrports)) + if (portnr >= brdp->nrports) return NULL; return brdp->ports[portnr]; } @@ -4375,10 +4260,10 @@ static stliport_t *stli_getport(int brdnr, int panelnr, int portnr) * what port to get stats for (used through board control device). */ -static int stli_portcmdstats(stliport_t *portp) +static int stli_portcmdstats(struct stliport *portp) { unsigned long flags; - stlibrd_t *brdp; + struct stlibrd *brdp; int rc; memset(&stli_comstats, 0, sizeof(comstats_t)); @@ -4449,9 +4334,9 @@ static int stli_portcmdstats(stliport_t *portp) * what port to get stats for (used through board control device). */ -static int stli_getportstats(stliport_t *portp, comstats_t __user *cp) +static int stli_getportstats(struct stliport *portp, comstats_t __user *cp) { - stlibrd_t *brdp; + struct stlibrd *brdp; int rc; if (!portp) { @@ -4480,9 +4365,9 @@ static int stli_getportstats(stliport_t *portp, comstats_t __user *cp) * Clear the port stats structure. We also return it zeroed out... */ -static int stli_clrportstats(stliport_t *portp, comstats_t __user *cp) +static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp) { - stlibrd_t *brdp; + struct stlibrd *brdp; int rc; if (!portp) { @@ -4519,17 +4404,18 @@ static int stli_clrportstats(stliport_t *portp, comstats_t __user *cp) * Return the entire driver ports structure to a user app. */ -static int stli_getportstruct(stliport_t __user *arg) +static int stli_getportstruct(struct stliport __user *arg) { - stliport_t *portp; + struct stliport stli_dummyport; + struct stliport *portp; - if (copy_from_user(&stli_dummyport, arg, sizeof(stliport_t))) + if (copy_from_user(&stli_dummyport, arg, sizeof(struct stliport))) return -EFAULT; portp = stli_getport(stli_dummyport.brdnr, stli_dummyport.panelnr, stli_dummyport.portnr); if (!portp) return -ENODEV; - if (copy_to_user(arg, portp, sizeof(stliport_t))) + if (copy_to_user(arg, portp, sizeof(struct stliport))) return -EFAULT; return 0; } @@ -4540,18 +4426,19 @@ static int stli_getportstruct(stliport_t __user *arg) * Return the entire driver board structure to a user app. */ -static int stli_getbrdstruct(stlibrd_t __user *arg) +static int stli_getbrdstruct(struct stlibrd __user *arg) { - stlibrd_t *brdp; + struct stlibrd stli_dummybrd; + struct stlibrd *brdp; - if (copy_from_user(&stli_dummybrd, arg, sizeof(stlibrd_t))) + if (copy_from_user(&stli_dummybrd, arg, sizeof(struct stlibrd))) return -EFAULT; - if ((stli_dummybrd.brdnr < 0) || (stli_dummybrd.brdnr >= STL_MAXBRDS)) + if (stli_dummybrd.brdnr >= STL_MAXBRDS) return -ENODEV; brdp = stli_brds[stli_dummybrd.brdnr]; if (!brdp) return -ENODEV; - if (copy_to_user(arg, brdp, sizeof(stlibrd_t))) + if (copy_to_user(arg, brdp, sizeof(struct stlibrd))) return -EFAULT; return 0; } @@ -4566,7 +4453,7 @@ static int stli_getbrdstruct(stlibrd_t __user *arg) static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg) { - stlibrd_t *brdp; + struct stlibrd *brdp; int brdnr, rc, done; void __user *argp = (void __user *)arg; @@ -4665,46 +4552,53 @@ static const struct tty_operations stli_ops = { }; /*****************************************************************************/ +/* + * Loadable module initialization stuff. + */ + +static void istallion_cleanup_isa(void) +{ + struct stlibrd *brdp; + unsigned int j; + + for (j = 0; (j < stli_nrbrds); j++) { + if ((brdp = stli_brds[j]) == NULL || (brdp->state & BST_PROBED)) + continue; + + stli_cleanup_ports(brdp); -static int __init stli_init(void) + iounmap(brdp->membase); + if (brdp->iosize > 0) + release_region(brdp->iobase, brdp->iosize); + kfree(brdp); + stli_brds[j] = NULL; + } +} + +static int __init istallion_module_init(void) { - int i; + unsigned int i; + int retval; + printk(KERN_INFO "%s: version %s\n", stli_drvtitle, stli_drvversion); spin_lock_init(&stli_lock); spin_lock_init(&brd_lock); - stli_initbrds(); - - stli_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS); - if (!stli_serial) - return -ENOMEM; - -/* - * Allocate a temporary write buffer. - */ stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL); - if (!stli_txcookbuf) + if (!stli_txcookbuf) { printk(KERN_ERR "STALLION: failed to allocate memory " "(size=%d)\n", STLI_TXBUFSIZE); + retval = -ENOMEM; + goto err; + } -/* - * Set up a character driver for the shared memory region. We need this - * to down load the slave code image. Also it is a useful debugging tool. - */ - if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem)) - printk(KERN_ERR "STALLION: failed to register serial memory " - "device\n"); - - istallion_class = class_create(THIS_MODULE, "staliomem"); - for (i = 0; i < 4; i++) - class_device_create(istallion_class, NULL, - MKDEV(STL_SIOMEMMAJOR, i), - NULL, "staliomem%d", i); + stli_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS); + if (!stli_serial) { + retval = -ENOMEM; + goto err_free; + } -/* - * Set up the tty driver structure and register us as a driver. - */ stli_serial->owner = THIS_MODULE; stli_serial->driver_name = stli_drvname; stli_serial->name = stli_serialname; @@ -4713,15 +4607,79 @@ static int __init stli_init(void) stli_serial->type = TTY_DRIVER_TYPE_SERIAL; stli_serial->subtype = SERIAL_TYPE_NORMAL; stli_serial->init_termios = stli_deftermios; - stli_serial->flags = TTY_DRIVER_REAL_RAW; + stli_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; tty_set_operations(stli_serial, &stli_ops); - if (tty_register_driver(stli_serial)) { - put_tty_driver(stli_serial); + retval = tty_register_driver(stli_serial); + if (retval) { printk(KERN_ERR "STALLION: failed to register serial driver\n"); - return -EBUSY; + goto err_ttyput; } + + retval = stli_initbrds(); + if (retval) + goto err_ttyunr; + +/* + * Set up a character driver for the shared memory region. We need this + * to down load the slave code image. Also it is a useful debugging tool. + */ + retval = register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem); + if (retval) { + printk(KERN_ERR "STALLION: failed to register serial memory " + "device\n"); + goto err_deinit; + } + + istallion_class = class_create(THIS_MODULE, "staliomem"); + for (i = 0; i < 4; i++) + class_device_create(istallion_class, NULL, + MKDEV(STL_SIOMEMMAJOR, i), + NULL, "staliomem%d", i); + return 0; +err_deinit: + pci_unregister_driver(&stli_pcidriver); + istallion_cleanup_isa(); +err_ttyunr: + tty_unregister_driver(stli_serial); +err_ttyput: + put_tty_driver(stli_serial); +err_free: + kfree(stli_txcookbuf); +err: + return retval; } /*****************************************************************************/ + +static void __exit istallion_module_exit(void) +{ + unsigned int j; + + printk(KERN_INFO "Unloading %s: version %s\n", stli_drvtitle, + stli_drvversion); + + if (stli_timeron) { + stli_timeron = 0; + del_timer_sync(&stli_timerlist); + } + + unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"); + + for (j = 0; j < 4; j++) + class_device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, + j)); + class_destroy(istallion_class); + + pci_unregister_driver(&stli_pcidriver); + istallion_cleanup_isa(); + + tty_unregister_driver(stli_serial); + put_tty_driver(stli_serial); + + kfree(stli_txcookbuf); +} + +module_init(istallion_module_init); +module_exit(istallion_module_exit); diff --git a/drivers/char/lp.c b/drivers/char/lp.c index 1ecea7d448f..b70b5388b5a 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -296,7 +296,7 @@ static int lp_wait_ready(int minor, int nonblock) static ssize_t lp_write(struct file * file, const char __user * buf, size_t count, loff_t *ppos) { - unsigned int minor = iminor(file->f_dentry->d_inode); + unsigned int minor = iminor(file->f_path.dentry->d_inode); struct parport *port = lp_table[minor].dev->port; char *kbuf = lp_table[minor].lp_buffer; ssize_t retv = 0; @@ -415,7 +415,7 @@ static ssize_t lp_read(struct file * file, char __user * buf, size_t count, loff_t *ppos) { DEFINE_WAIT(wait); - unsigned int minor=iminor(file->f_dentry->d_inode); + unsigned int minor=iminor(file->f_path.dentry->d_inode); struct parport *port = lp_table[minor].dev->port; ssize_t retval = 0; char *kbuf = lp_table[minor].lp_buffer; diff --git a/drivers/char/mem.c b/drivers/char/mem.c index e67eef4867b..089020e0ee5 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -774,7 +774,7 @@ static loff_t memory_lseek(struct file * file, loff_t offset, int orig) { loff_t ret; - mutex_lock(&file->f_dentry->d_inode->i_mutex); + mutex_lock(&file->f_path.dentry->d_inode->i_mutex); switch (orig) { case 0: file->f_pos = offset; @@ -789,7 +789,7 @@ static loff_t memory_lseek(struct file * file, loff_t offset, int orig) default: ret = -EINVAL; } - mutex_unlock(&file->f_dentry->d_inode->i_mutex); + mutex_unlock(&file->f_path.dentry->d_inode->i_mutex); return ret; } diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index 8b316953173..f391a24a1b4 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c @@ -234,7 +234,7 @@ static void moxa_put_char(struct tty_struct *, unsigned char); static int moxa_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long); static void moxa_throttle(struct tty_struct *); static void moxa_unthrottle(struct tty_struct *); -static void moxa_set_termios(struct tty_struct *, struct termios *); +static void moxa_set_termios(struct tty_struct *, struct ktermios *); static void moxa_stop(struct tty_struct *); static void moxa_start(struct tty_struct *); static void moxa_hangup(struct tty_struct *); @@ -261,7 +261,7 @@ static void MoxaPortEnable(int); static void MoxaPortDisable(int); static long MoxaPortGetMaxBaud(int); static long MoxaPortSetBaud(int, long); -static int MoxaPortSetTermio(int, struct termios *, speed_t); +static int MoxaPortSetTermio(int, struct ktermios *, speed_t); static int MoxaPortGetLineOut(int, int *, int *); static void MoxaPortLineCtrl(int, int, int); static void MoxaPortFlowCtrl(int, int, int, int, int, int); @@ -355,6 +355,8 @@ static int __init moxa_init(void) moxaDriver->init_termios.c_oflag = 0; moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; moxaDriver->init_termios.c_lflag = 0; + moxaDriver->init_termios.c_ispeed = 9600; + moxaDriver->init_termios.c_ospeed = 9600; moxaDriver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(moxaDriver, &moxa_ops); @@ -864,7 +866,7 @@ static void moxa_unthrottle(struct tty_struct *tty) } static void moxa_set_termios(struct tty_struct *tty, - struct termios *old_termios) + struct ktermios *old_termios) { struct moxa_str *ch = (struct moxa_str *) tty->driver_data; @@ -978,7 +980,7 @@ static void moxa_poll(unsigned long ignored) static void set_tty_param(struct tty_struct *tty) { - register struct termios *ts; + register struct ktermios *ts; struct moxa_str *ch; int rts, cts, txflow, rxflow, xany; @@ -1149,7 +1151,7 @@ static void shut_down(struct moxa_str *ch) static void receive_data(struct moxa_str *ch) { struct tty_struct *tp; - struct termios *ts; + struct ktermios *ts; unsigned long flags; ts = NULL; @@ -1912,9 +1914,9 @@ int MoxaPortsOfCard(int cardno) * * Function 12: Configure the port. * Syntax: - * int MoxaPortSetTermio(int port, struct termios *termio, speed_t baud); + * int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud); * int port : port number (0 - 127) - * struct termios * termio : termio structure pointer + * struct ktermios * termio : termio structure pointer * speed_t baud : baud rate * * return: -1 : this port is invalid or termio == NULL @@ -2195,7 +2197,7 @@ long MoxaPortSetBaud(int port, long baud) return (baud); } -int MoxaPortSetTermio(int port, struct termios *termio, speed_t baud) +int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud) { void __iomem *ofsAddr; tcflag_t cflag; diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 5ed2486b758..c063359baf7 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -328,8 +328,8 @@ struct mxser_struct { int xmit_tail; int xmit_cnt; struct work_struct tqueue; - struct termios normal_termios; - struct termios callout_termios; + struct ktermios normal_termios; + struct ktermios callout_termios; wait_queue_head_t open_wait; wait_queue_head_t close_wait; wait_queue_head_t delta_msr_wait; @@ -364,8 +364,8 @@ static int mxserBoardCAP[MXSER_BOARDS] = { static struct tty_driver *mxvar_sdriver; static struct mxser_struct mxvar_table[MXSER_PORTS]; static struct tty_struct *mxvar_tty[MXSER_PORTS + 1]; -static struct termios *mxvar_termios[MXSER_PORTS + 1]; -static struct termios *mxvar_termios_locked[MXSER_PORTS + 1]; +static struct ktermios *mxvar_termios[MXSER_PORTS + 1]; +static struct ktermios *mxvar_termios_locked[MXSER_PORTS + 1]; static struct mxser_log mxvar_log; static int mxvar_diagflag; static unsigned char mxser_msr[MXSER_PORTS + 1]; @@ -402,7 +402,7 @@ static int mxser_ioctl(struct tty_struct *, struct file *, uint, ulong); static int mxser_ioctl_special(unsigned int, void __user *); static void mxser_throttle(struct tty_struct *); static void mxser_unthrottle(struct tty_struct *); -static void mxser_set_termios(struct tty_struct *, struct termios *); +static void mxser_set_termios(struct tty_struct *, struct ktermios *); static void mxser_stop(struct tty_struct *); static void mxser_start(struct tty_struct *); static void mxser_hangup(struct tty_struct *); @@ -414,7 +414,7 @@ static void mxser_check_modem_status(struct mxser_struct *, int); static int mxser_block_til_ready(struct tty_struct *, struct file *, struct mxser_struct *); static int mxser_startup(struct mxser_struct *); static void mxser_shutdown(struct mxser_struct *); -static int mxser_change_speed(struct mxser_struct *, struct termios *old_termios); +static int mxser_change_speed(struct mxser_struct *, struct ktermios *old_termios); static int mxser_get_serial_info(struct mxser_struct *, struct serial_struct __user *); static int mxser_set_serial_info(struct mxser_struct *, struct serial_struct __user *); static int mxser_get_lsr_info(struct mxser_struct *, unsigned int __user *); @@ -515,6 +515,7 @@ static void __exit mxser_module_exit(void) if (pdev != NULL) { /* PCI */ release_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2)); release_region(pci_resource_start(pdev, 3), pci_resource_len(pdev, 3)); + pci_dev_put(pdev); } else { release_region(mxsercfg[i].ioaddr[0], 8 * mxsercfg[i].ports); release_region(mxsercfg[i].vector, 1); @@ -556,7 +557,7 @@ static int mxser_initbrd(int board, struct mxser_hwconf *hwconf) n = board * MXSER_PORTS_PER_BOARD; info = &mxvar_table[n]; /*if (verbose) */ { - printk(KERN_DEBUG " ttyM%d - ttyM%d ", + printk(KERN_DEBUG " ttyMI%d - ttyMI%d ", n, n + hwconf->ports - 1); printk(" max. baud rate = %d bps.\n", hwconf->MaxCanSetBaudRate[0]); @@ -717,7 +718,7 @@ static int mxser_init(void) /* Initialize the tty_driver structure */ memset(mxvar_sdriver, 0, sizeof(struct tty_driver)); mxvar_sdriver->magic = TTY_DRIVER_MAGIC; - mxvar_sdriver->name = "ttyM"; + mxvar_sdriver->name = "ttyMI"; mxvar_sdriver->major = ttymajor; mxvar_sdriver->minor_start = 0; mxvar_sdriver->num = MXSER_PORTS + 1; @@ -725,6 +726,8 @@ static int mxser_init(void) mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL; mxvar_sdriver->init_termios = tty_std_termios; mxvar_sdriver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL; + mxvar_sdriver->init_termios.c_ispeed = 9600; + mxvar_sdriver->init_termios.c_ospeed = 9600; mxvar_sdriver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(mxvar_sdriver, &mxser_ops); mxvar_sdriver->ttys = mxvar_tty; @@ -839,9 +842,9 @@ static int mxser_init(void) index = 0; b = 0; while (b < n) { - pdev = pci_find_device(mxser_pcibrds[b].vendor, + pdev = pci_get_device(mxser_pcibrds[b].vendor, mxser_pcibrds[b].device, pdev); - if (pdev == NULL) { + if (pdev == NULL) { b++; continue; } @@ -893,6 +896,9 @@ static int mxser_init(void) if (mxser_initbrd(m, &hwconf) < 0) continue; m++; + /* Keep an extra reference if we succeeded. It will + be returned at unload time */ + pci_dev_get(pdev); } } #endif @@ -994,7 +1000,7 @@ static int mxser_open(struct tty_struct *tty, struct file *filp) mxser_change_speed(info, NULL); } - info->session = current->signal->session; + info->session = process_session(current); info->pgrp = process_group(current); /* @@ -1745,7 +1751,7 @@ static void mxser_unthrottle(struct tty_struct *tty) /* MX_UNLOCK(&info->slock); */ } -static void mxser_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct mxser_struct *info = tty->driver_data; unsigned long flags; @@ -2537,7 +2543,7 @@ static void mxser_shutdown(struct mxser_struct *info) * This routine is called to set the UART divisor registers to match * the specified baud rate for a serial port. */ -static int mxser_change_speed(struct mxser_struct *info, struct termios *old_termios) +static int mxser_change_speed(struct mxser_struct *info, struct ktermios *old_termios) { unsigned cflag, cval, fcr; int ret = 0; diff --git a/drivers/char/mxser_new.c b/drivers/char/mxser_new.c new file mode 100644 index 00000000000..efa8076c33e --- /dev/null +++ b/drivers/char/mxser_new.c @@ -0,0 +1,2804 @@ +/* + * mxser.c -- MOXA Smartio/Industio family multiport serial driver. + * + * Copyright (C) 1999-2006 Moxa Technologies (support@moxa.com.tw). + * Copyright (C) 2006 Jiri Slaby <jirislaby@gmail.com> + * + * This code is loosely based on the 1.8 moxa driver which is based on + * Linux serial driver, written by Linus Torvalds, Theodore T'so and + * others. + * + * 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. + * + * Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox + * <alan@redhat.com>. The original 1.8 code is available on www.moxa.com. + * - Fixed x86_64 cleanness + * - Fixed sleep with spinlock held in mxser_send_break + */ + +#include <linux/module.h> +#include <linux/autoconf.h> +#include <linux/errno.h> +#include <linux/signal.h> +#include <linux/sched.h> +#include <linux/timer.h> +#include <linux/interrupt.h> +#include <linux/tty.h> +#include <linux/tty_flip.h> +#include <linux/serial.h> +#include <linux/serial_reg.h> +#include <linux/major.h> +#include <linux/string.h> +#include <linux/fcntl.h> +#include <linux/ptrace.h> +#include <linux/gfp.h> +#include <linux/ioport.h> +#include <linux/mm.h> +#include <linux/smp_lock.h> +#include <linux/delay.h> +#include <linux/pci.h> + +#include <asm/system.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/bitops.h> +#include <asm/uaccess.h> + +#include "mxser_new.h" + +#define MXSER_VERSION "2.0" +#define MXSERMAJOR 174 +#define MXSERCUMAJOR 175 + +#define MXSER_EVENT_TXLOW 1 + +#define MXSER_BOARDS 4 /* Max. boards */ +#define MXSER_PORTS_PER_BOARD 8 /* Max. ports per board */ +#define MXSER_PORTS (MXSER_BOARDS * MXSER_PORTS_PER_BOARD) +#define MXSER_ISR_PASS_LIMIT 99999L + +#define MXSER_ERR_IOADDR -1 +#define MXSER_ERR_IRQ -2 +#define MXSER_ERR_IRQ_CONFLIT -3 +#define MXSER_ERR_VECTOR -4 + +#define WAKEUP_CHARS 256 + +#define UART_MCR_AFE 0x20 +#define UART_LSR_SPECIAL 0x1E + +#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|\ + IXON|IXOFF)) + +#define C168_ASIC_ID 1 +#define C104_ASIC_ID 2 +#define C102_ASIC_ID 0xB +#define CI132_ASIC_ID 4 +#define CI134_ASIC_ID 3 +#define CI104J_ASIC_ID 5 + +#define MXSER_HIGHBAUD 1 +#define MXSER_HAS2 2 + +/* This is only for PCI */ +static const struct { + int type; + int tx_fifo; + int rx_fifo; + int xmit_fifo_size; + int rx_high_water; + int rx_trigger; + int rx_low_water; + long max_baud; +} Gpci_uart_info[] = { + {MOXA_OTHER_UART, 16, 16, 16, 14, 14, 1, 921600L}, + {MOXA_MUST_MU150_HWID, 64, 64, 64, 48, 48, 16, 230400L}, + {MOXA_MUST_MU860_HWID, 128, 128, 128, 96, 96, 32, 921600L} +}; +#define UART_INFO_NUM ARRAY_SIZE(Gpci_uart_info) + +struct mxser_cardinfo { + unsigned int nports; + char *name; + unsigned int flags; +}; + +static const struct mxser_cardinfo mxser_cards[] = { + { 8, "C168 series", }, /* C168-ISA */ + { 4, "C104 series", }, /* C104-ISA */ + { 4, "CI-104J series", }, /* CI104J */ + { 8, "C168H/PCI series", }, /* C168-PCI */ + { 4, "C104H/PCI series", }, /* C104-PCI */ + { 4, "C102 series", MXSER_HAS2 }, /* C102-ISA */ + { 4, "CI-132 series", MXSER_HAS2 }, /* CI132 */ + { 4, "CI-134 series", }, /* CI134 */ + { 2, "CP-132 series", }, /* CP132 */ + { 4, "CP-114 series", }, /* CP114 */ + { 4, "CT-114 series", }, /* CT114 */ + { 2, "CP-102 series", MXSER_HIGHBAUD }, /* CP102 */ + { 4, "CP-104U series", }, /* CP104U */ + { 8, "CP-168U series", }, /* CP168U */ + { 2, "CP-132U series", }, /* CP132U */ + { 4, "CP-134U series", }, /* CP134U */ + { 4, "CP-104JU series", }, /* CP104JU */ + { 8, "Moxa UC7000 Serial", }, /* RC7000 */ + { 8, "CP-118U series", }, /* CP118U */ + { 2, "CP-102UL series", }, /* CP102UL */ + { 2, "CP-102U series", }, /* CP102U */ + { 8, "CP-118EL series", }, /* CP118EL */ + { 8, "CP-168EL series", }, /* CP168EL */ + { 4, "CP-104EL series", } /* CP104EL */ +}; + +/* driver_data correspond to the lines in the structure above + see also ISA probe function before you change something */ +static struct pci_device_id mxser_pcibrds[] = { + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C168), + .driver_data = 3 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C104), + .driver_data = 4 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP132), + .driver_data = 8 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP114), + .driver_data = 9 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CT114), + .driver_data = 10 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102), + .driver_data = 11 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104U), + .driver_data = 12 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP168U), + .driver_data = 13 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP132U), + .driver_data = 14 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP134U), + .driver_data = 15 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104JU), + .driver_data = 16 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_RC7000), + .driver_data = 17 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP118U), + .driver_data = 18 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102UL), + .driver_data = 19 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102U), + .driver_data = 20 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP118EL), + .driver_data = 21 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP168EL), + .driver_data = 22 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104EL), + .driver_data = 23 }, + { } +}; +MODULE_DEVICE_TABLE(pci, mxser_pcibrds); + +static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 }; +static int ttymajor = MXSERMAJOR; +static int calloutmajor = MXSERCUMAJOR; + +/* Variables for insmod */ + +MODULE_AUTHOR("Casper Yang"); +MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver"); +module_param_array(ioaddr, int, NULL, 0); +module_param(ttymajor, int, 0); +MODULE_LICENSE("GPL"); + +struct mxser_log { + int tick; + unsigned long rxcnt[MXSER_PORTS]; + unsigned long txcnt[MXSER_PORTS]; +}; + + +struct mxser_mon { + unsigned long rxcnt; + unsigned long txcnt; + unsigned long up_rxcnt; + unsigned long up_txcnt; + int modem_status; + unsigned char hold_reason; +}; + +struct mxser_mon_ext { + unsigned long rx_cnt[32]; + unsigned long tx_cnt[32]; + unsigned long up_rxcnt[32]; + unsigned long up_txcnt[32]; + int modem_status[32]; + + long baudrate[32]; + int databits[32]; + int stopbits[32]; + int parity[32]; + int flowctrl[32]; + int fifo[32]; + int iftype[32]; +}; + +struct mxser_board; + +struct mxser_port { + struct mxser_board *board; + struct tty_struct *tty; + + unsigned long ioaddr; + unsigned long opmode_ioaddr; + int max_baud; + + int rx_high_water; + int rx_trigger; /* Rx fifo trigger level */ + int rx_low_water; + int baud_base; /* max. speed */ + long realbaud; + int type; /* UART type */ + int flags; /* defined in tty.h */ + long session; /* Session of opening process */ + long pgrp; /* pgrp of opening process */ + + int x_char; /* xon/xoff character */ + int IER; /* Interrupt Enable Register */ + int MCR; /* Modem control register */ + + unsigned char stop_rx; + unsigned char ldisc_stop_rx; + + int custom_divisor; + int close_delay; + unsigned short closing_wait; + unsigned char err_shadow; + unsigned long event; + + int count; /* # of fd on device */ + int blocked_open; /* # of blocked opens */ + struct async_icount icount; /* kernel counters for 4 input interrupts */ + int timeout; + + int read_status_mask; + int ignore_status_mask; + int xmit_fifo_size; + unsigned char *xmit_buf; + int xmit_head; + int xmit_tail; + int xmit_cnt; + + struct ktermios normal_termios; + struct ktermios callout_termios; + + struct mxser_mon mon_data; + + spinlock_t slock; + struct work_struct tqueue; + wait_queue_head_t open_wait; + wait_queue_head_t close_wait; + wait_queue_head_t delta_msr_wait; +}; + +struct mxser_board { + unsigned int idx; + int irq; + const struct mxser_cardinfo *info; + unsigned long vector; + unsigned long vector_mask; + + int chip_flag; + int uart_type; + + struct mxser_port ports[MXSER_PORTS_PER_BOARD]; +}; + +struct mxser_mstatus { + tcflag_t cflag; + int cts; + int dsr; + int ri; + int dcd; +}; + +static struct mxser_mstatus GMStatus[MXSER_PORTS]; + +static int mxserBoardCAP[MXSER_BOARDS] = { + 0, 0, 0, 0 + /* 0x180, 0x280, 0x200, 0x320 */ +}; + +static struct mxser_board mxser_boards[MXSER_BOARDS]; +static struct tty_driver *mxvar_sdriver; +static struct mxser_log mxvar_log; +static int mxvar_diagflag; +static unsigned char mxser_msr[MXSER_PORTS + 1]; +static struct mxser_mon_ext mon_data_ext; +static int mxser_set_baud_method[MXSER_PORTS + 1]; +static spinlock_t gm_lock; + +static int CheckIsMoxaMust(int io) +{ + u8 oldmcr, hwid; + int i; + + outb(0, io + UART_LCR); + DISABLE_MOXA_MUST_ENCHANCE_MODE(io); + oldmcr = inb(io + UART_MCR); + outb(0, io + UART_MCR); + SET_MOXA_MUST_XON1_VALUE(io, 0x11); + if ((hwid = inb(io + UART_MCR)) != 0) { + outb(oldmcr, io + UART_MCR); + return MOXA_OTHER_UART; + } + + GET_MOXA_MUST_HARDWARE_ID(io, &hwid); + for (i = 1; i < UART_INFO_NUM; i++) { /* 0 = OTHER_UART */ + if (hwid == Gpci_uart_info[i].type) + return (int)hwid; + } + return MOXA_OTHER_UART; +} + +static void process_txrx_fifo(struct mxser_port *info) +{ + int i; + + if ((info->type == PORT_16450) || (info->type == PORT_8250)) { + info->rx_trigger = 1; + info->rx_high_water = 1; + info->rx_low_water = 1; + info->xmit_fifo_size = 1; + } else + for (i = 0; i < UART_INFO_NUM; i++) + if (info->board->chip_flag == Gpci_uart_info[i].type) { + info->rx_trigger = Gpci_uart_info[i].rx_trigger; + info->rx_low_water = Gpci_uart_info[i].rx_low_water; + info->rx_high_water = Gpci_uart_info[i].rx_high_water; + info->xmit_fifo_size = Gpci_uart_info[i].xmit_fifo_size; + break; + } +} + +static void mxser_do_softint(struct work_struct *work) +{ + struct mxser_port *info = container_of(work, struct mxser_port, tqueue); + struct tty_struct *tty = info->tty; + + if (test_and_clear_bit(MXSER_EVENT_TXLOW, &info->event)) + tty_wakeup(tty); +} + +static unsigned char mxser_get_msr(int baseaddr, int mode, int port) +{ + unsigned char status = 0; + + status = inb(baseaddr + UART_MSR); + + mxser_msr[port] &= 0x0F; + mxser_msr[port] |= status; + status = mxser_msr[port]; + if (mode) + mxser_msr[port] = 0; + + return status; +} + +static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, + struct mxser_port *port) +{ + DECLARE_WAITQUEUE(wait, current); + int retval; + int do_clocal = 0; + unsigned long flags; + + /* + * If non-blocking mode is set, or the port is not enabled, + * then make the check up front and then exit. + */ + if ((filp->f_flags & O_NONBLOCK) || + test_bit(TTY_IO_ERROR, &tty->flags)) { + port->flags |= ASYNC_NORMAL_ACTIVE; + return 0; + } + + if (tty->termios->c_cflag & CLOCAL) + do_clocal = 1; + + /* + * Block waiting for the carrier detect and the line to become + * free (i.e., not in use by the callout). While we are in + * this loop, port->count is dropped by one, so that + * mxser_close() knows when to free things. We restore it upon + * exit, either normal or abnormal. + */ + retval = 0; + add_wait_queue(&port->open_wait, &wait); + + spin_lock_irqsave(&port->slock, flags); + if (!tty_hung_up_p(filp)) + port->count--; + spin_unlock_irqrestore(&port->slock, flags); + port->blocked_open++; + while (1) { + spin_lock_irqsave(&port->slock, flags); + outb(inb(port->ioaddr + UART_MCR) | + UART_MCR_DTR | UART_MCR_RTS, port->ioaddr + UART_MCR); + spin_unlock_irqrestore(&port->slock, flags); + set_current_state(TASK_INTERRUPTIBLE); + if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) { + if (port->flags & ASYNC_HUP_NOTIFY) + retval = -EAGAIN; + else + retval = -ERESTARTSYS; + break; + } + if (!(port->flags & ASYNC_CLOSING) && + (do_clocal || + (inb(port->ioaddr + UART_MSR) & UART_MSR_DCD))) + break; + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } + schedule(); + } + set_current_state(TASK_RUNNING); + remove_wait_queue(&port->open_wait, &wait); + if (!tty_hung_up_p(filp)) + port->count++; + port->blocked_open--; + if (retval) + return retval; + port->flags |= ASYNC_NORMAL_ACTIVE; + return 0; +} + +static int mxser_set_baud(struct mxser_port *info, long newspd) +{ + int quot = 0; + unsigned char cval; + int ret = 0; + unsigned long flags; + + if (!info->tty || !info->tty->termios) + return ret; + + if (!(info->ioaddr)) + return ret; + + if (newspd > info->max_baud) + return 0; + + info->realbaud = newspd; + if (newspd == 134) { + quot = (2 * info->baud_base / 269); + } else if (newspd) { + quot = info->baud_base / newspd; + if (quot == 0) + quot = 1; + } else { + quot = 0; + } + + info->timeout = ((info->xmit_fifo_size * HZ * 10 * quot) / info->baud_base); + info->timeout += HZ / 50; /* Add .02 seconds of slop */ + + if (quot) { + spin_lock_irqsave(&info->slock, flags); + info->MCR |= UART_MCR_DTR; + outb(info->MCR, info->ioaddr + UART_MCR); + spin_unlock_irqrestore(&info->slock, flags); + } else { + spin_lock_irqsave(&info->slock, flags); + info->MCR &= ~UART_MCR_DTR; + outb(info->MCR, info->ioaddr + UART_MCR); + spin_unlock_irqrestore(&info->slock, flags); + return ret; + } + + cval = inb(info->ioaddr + UART_LCR); + + outb(cval | UART_LCR_DLAB, info->ioaddr + UART_LCR); /* set DLAB */ + + outb(quot & 0xff, info->ioaddr + UART_DLL); /* LS of divisor */ + outb(quot >> 8, info->ioaddr + UART_DLM); /* MS of divisor */ + outb(cval, info->ioaddr + UART_LCR); /* reset DLAB */ + + + return ret; +} + +/* + * This routine is called to set the UART divisor registers to match + * the specified baud rate for a serial port. + */ +static int mxser_change_speed(struct mxser_port *info, + struct ktermios *old_termios) +{ + unsigned cflag, cval, fcr; + int ret = 0; + unsigned char status; + long baud; + unsigned long flags; + + if (!info->tty || !info->tty->termios) + return ret; + cflag = info->tty->termios->c_cflag; + if (!(info->ioaddr)) + return ret; + + if (mxser_set_baud_method[info->tty->index] == 0) { + baud = tty_get_baud_rate(info->tty); + mxser_set_baud(info, baud); + } + + /* byte size and parity */ + switch (cflag & CSIZE) { + case CS5: + cval = 0x00; + break; + case CS6: + cval = 0x01; + break; + case CS7: + cval = 0x02; + break; + case CS8: + cval = 0x03; + break; + default: + cval = 0x00; + break; /* too keep GCC shut... */ + } + if (cflag & CSTOPB) + cval |= 0x04; + if (cflag & PARENB) + cval |= UART_LCR_PARITY; + if (!(cflag & PARODD)) + cval |= UART_LCR_EPAR; + if (cflag & CMSPAR) + cval |= UART_LCR_SPAR; + + if ((info->type == PORT_8250) || (info->type == PORT_16450)) { + if (info->board->chip_flag) { + fcr = UART_FCR_ENABLE_FIFO; + fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE; + SET_MOXA_MUST_FIFO_VALUE(info); + } else + fcr = 0; + } else { + fcr = UART_FCR_ENABLE_FIFO; + if (info->board->chip_flag) { + fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE; + SET_MOXA_MUST_FIFO_VALUE(info); + } else { + switch (info->rx_trigger) { + case 1: + fcr |= UART_FCR_TRIGGER_1; + break; + case 4: + fcr |= UART_FCR_TRIGGER_4; + break; + case 8: + fcr |= UART_FCR_TRIGGER_8; + break; + default: + fcr |= UART_FCR_TRIGGER_14; + break; + } + } + } + + /* CTS flow control flag and modem status interrupts */ + info->IER &= ~UART_IER_MSI; + info->MCR &= ~UART_MCR_AFE; + if (cflag & CRTSCTS) { + info->flags |= ASYNC_CTS_FLOW; + info->IER |= UART_IER_MSI; + if ((info->type == PORT_16550A) || (info->board->chip_flag)) { + info->MCR |= UART_MCR_AFE; + } else { + status = inb(info->ioaddr + UART_MSR); + if (info->tty->hw_stopped) { + if (status & UART_MSR_CTS) { + info->tty->hw_stopped = 0; + if (info->type != PORT_16550A && + !info->board->chip_flag) { + outb(info->IER & ~UART_IER_THRI, + info->ioaddr + + UART_IER); + info->IER |= UART_IER_THRI; + outb(info->IER, info->ioaddr + + UART_IER); + } + set_bit(MXSER_EVENT_TXLOW, &info->event); + schedule_work(&info->tqueue); } + } else { + if (!(status & UART_MSR_CTS)) { + info->tty->hw_stopped = 1; + if ((info->type != PORT_16550A) && + (!info->board->chip_flag)) { + info->IER &= ~UART_IER_THRI; + outb(info->IER, info->ioaddr + + UART_IER); + } + } + } + } + } else { + info->flags &= ~ASYNC_CTS_FLOW; + } + outb(info->MCR, info->ioaddr + UART_MCR); + if (cflag & CLOCAL) { + info->flags &= ~ASYNC_CHECK_CD; + } else { + info->flags |= ASYNC_CHECK_CD; + info->IER |= UART_IER_MSI; + } + outb(info->IER, info->ioaddr + UART_IER); + + /* + * Set up parity check flag + */ + info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; + if (I_INPCK(info->tty)) + info->read_status_mask |= UART_LSR_FE | UART_LSR_PE; + if (I_BRKINT(info->tty) || I_PARMRK(info->tty)) + info->read_status_mask |= UART_LSR_BI; + + info->ignore_status_mask = 0; + + if (I_IGNBRK(info->tty)) { + info->ignore_status_mask |= UART_LSR_BI; + info->read_status_mask |= UART_LSR_BI; + /* + * If we're ignore parity and break indicators, ignore + * overruns too. (For real raw support). + */ + if (I_IGNPAR(info->tty)) { + info->ignore_status_mask |= + UART_LSR_OE | + UART_LSR_PE | + UART_LSR_FE; + info->read_status_mask |= + UART_LSR_OE | + UART_LSR_PE | + UART_LSR_FE; + } + } + if (info->board->chip_flag) { + spin_lock_irqsave(&info->slock, flags); + SET_MOXA_MUST_XON1_VALUE(info->ioaddr, START_CHAR(info->tty)); + SET_MOXA_MUST_XOFF1_VALUE(info->ioaddr, STOP_CHAR(info->tty)); + if (I_IXON(info->tty)) { + ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->ioaddr); + } else { + DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->ioaddr); + } + if (I_IXOFF(info->tty)) { + ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->ioaddr); + } else { + DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->ioaddr); + } + spin_unlock_irqrestore(&info->slock, flags); + } + + + outb(fcr, info->ioaddr + UART_FCR); /* set fcr */ + outb(cval, info->ioaddr + UART_LCR); + + return ret; +} + +static void mxser_check_modem_status(struct mxser_port *port, int status) +{ + /* update input line counters */ + if (status & UART_MSR_TERI) + port->icount.rng++; + if (status & UART_MSR_DDSR) + port->icount.dsr++; + if (status & UART_MSR_DDCD) + port->icount.dcd++; + if (status & UART_MSR_DCTS) + port->icount.cts++; + port->mon_data.modem_status = status; + wake_up_interruptible(&port->delta_msr_wait); + + if ((port->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) { + if (status & UART_MSR_DCD) + wake_up_interruptible(&port->open_wait); + schedule_work(&port->tqueue); + } + + if (port->flags & ASYNC_CTS_FLOW) { + if (port->tty->hw_stopped) { + if (status & UART_MSR_CTS) { + port->tty->hw_stopped = 0; + + if ((port->type != PORT_16550A) && + (!port->board->chip_flag)) { + outb(port->IER & ~UART_IER_THRI, + port->ioaddr + UART_IER); + port->IER |= UART_IER_THRI; + outb(port->IER, port->ioaddr + + UART_IER); + } + set_bit(MXSER_EVENT_TXLOW, &port->event); + schedule_work(&port->tqueue); + } + } else { + if (!(status & UART_MSR_CTS)) { + port->tty->hw_stopped = 1; + if (port->type != PORT_16550A && + !port->board->chip_flag) { + port->IER &= ~UART_IER_THRI; + outb(port->IER, port->ioaddr + + UART_IER); + } + } + } + } +} + +static int mxser_startup(struct mxser_port *info) +{ + unsigned long page; + unsigned long flags; + + page = __get_free_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + + spin_lock_irqsave(&info->slock, flags); + + if (info->flags & ASYNC_INITIALIZED) { + free_page(page); + spin_unlock_irqrestore(&info->slock, flags); + return 0; + } + + if (!info->ioaddr || !info->type) { + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + free_page(page); + spin_unlock_irqrestore(&info->slock, flags); + return 0; + } + if (info->xmit_buf) + free_page(page); + else + info->xmit_buf = (unsigned char *) page; + + /* + * Clear the FIFO buffers and disable them + * (they will be reenabled in mxser_change_speed()) + */ + if (info->board->chip_flag) + outb((UART_FCR_CLEAR_RCVR | + UART_FCR_CLEAR_XMIT | + MOXA_MUST_FCR_GDA_MODE_ENABLE), info->ioaddr + UART_FCR); + else + outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), + info->ioaddr + UART_FCR); + + /* + * At this point there's no way the LSR could still be 0xFF; + * if it is, then bail out, because there's likely no UART + * here. + */ + if (inb(info->ioaddr + UART_LSR) == 0xff) { + spin_unlock_irqrestore(&info->slock, flags); + if (capable(CAP_SYS_ADMIN)) { + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + return 0; + } else + return -ENODEV; + } + + /* + * Clear the interrupt registers. + */ + (void) inb(info->ioaddr + UART_LSR); + (void) inb(info->ioaddr + UART_RX); + (void) inb(info->ioaddr + UART_IIR); + (void) inb(info->ioaddr + UART_MSR); + + /* + * Now, initialize the UART + */ + outb(UART_LCR_WLEN8, info->ioaddr + UART_LCR); /* reset DLAB */ + info->MCR = UART_MCR_DTR | UART_MCR_RTS; + outb(info->MCR, info->ioaddr + UART_MCR); + + /* + * Finally, enable interrupts + */ + info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI; + + if (info->board->chip_flag) + info->IER |= MOXA_MUST_IER_EGDAI; + outb(info->IER, info->ioaddr + UART_IER); /* enable interrupts */ + + /* + * And clear the interrupt registers again for luck. + */ + (void) inb(info->ioaddr + UART_LSR); + (void) inb(info->ioaddr + UART_RX); + (void) inb(info->ioaddr + UART_IIR); + (void) inb(info->ioaddr + UART_MSR); + + if (info->tty) + clear_bit(TTY_IO_ERROR, &info->tty->flags); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + + /* + * and set the speed of the serial port + */ + spin_unlock_irqrestore(&info->slock, flags); + mxser_change_speed(info, NULL); + + info->flags |= ASYNC_INITIALIZED; + return 0; +} + +/* + * This routine will shutdown a serial port; interrupts maybe disabled, and + * DTR is dropped if the hangup on close termio flag is on. + */ +static void mxser_shutdown(struct mxser_port *info) +{ + unsigned long flags; + + if (!(info->flags & ASYNC_INITIALIZED)) + return; + + spin_lock_irqsave(&info->slock, flags); + + /* + * clear delta_msr_wait queue to avoid mem leaks: we may free the irq + * here so the queue might never be waken up + */ + wake_up_interruptible(&info->delta_msr_wait); + + /* + * Free the IRQ, if necessary + */ + if (info->xmit_buf) { + free_page((unsigned long) info->xmit_buf); + info->xmit_buf = NULL; + } + + info->IER = 0; + outb(0x00, info->ioaddr + UART_IER); + + if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) + info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS); + outb(info->MCR, info->ioaddr + UART_MCR); + + /* clear Rx/Tx FIFO's */ + if (info->board->chip_flag) + outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | + MOXA_MUST_FCR_GDA_MODE_ENABLE, + info->ioaddr + UART_FCR); + else + outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, + info->ioaddr + UART_FCR); + + /* read data port to reset things */ + (void) inb(info->ioaddr + UART_RX); + + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + + info->flags &= ~ASYNC_INITIALIZED; + + if (info->board->chip_flag) + SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->ioaddr); + + spin_unlock_irqrestore(&info->slock, flags); +} + +/* + * This routine is called whenever a serial port is opened. It + * enables interrupts for a serial port, linking in its async structure into + * the IRQ chain. It also performs the serial-specific + * initialization for the tty structure. + */ +static int mxser_open(struct tty_struct *tty, struct file *filp) +{ + struct mxser_port *info; + int retval, line; + + /* initialize driver_data in case something fails */ + tty->driver_data = NULL; + + line = tty->index; + if (line == MXSER_PORTS) + return 0; + if (line < 0 || line > MXSER_PORTS) + return -ENODEV; + info = &mxser_boards[line / MXSER_PORTS_PER_BOARD].ports[line % MXSER_PORTS_PER_BOARD]; + if (!info->ioaddr) + return -ENODEV; + + tty->driver_data = info; + info->tty = tty; + /* + * Start up serial port + */ + info->count++; + retval = mxser_startup(info); + if (retval) + return retval; + + retval = mxser_block_til_ready(tty, filp, info); + if (retval) + return retval; + + if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) { + if (tty->driver->subtype == SERIAL_TYPE_NORMAL) + *tty->termios = info->normal_termios; + else + *tty->termios = info->callout_termios; + mxser_change_speed(info, NULL); + } + + info->session = process_session(current); + info->pgrp = process_group(current); + + /* unmark here for very high baud rate (ex. 921600 bps) used */ + tty->low_latency = 1; + return 0; +} + +/* + * This routine is called when the serial port gets closed. First, we + * wait for the last remaining data to be sent. Then, we unlink its + * async structure from the interrupt chain if necessary, and we free + * that IRQ if nothing is left in the chain. + */ +static void mxser_close(struct tty_struct *tty, struct file *filp) +{ + struct mxser_port *info = tty->driver_data; + + unsigned long timeout; + unsigned long flags; + + if (tty->index == MXSER_PORTS) + return; + if (!info) + return; + + spin_lock_irqsave(&info->slock, flags); + + if (tty_hung_up_p(filp)) { + spin_unlock_irqrestore(&info->slock, flags); + return; + } + if ((tty->count == 1) && (info->count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty + * structure will be freed. Info->count should always + * be one in these conditions. If it's greater than + * one, we've got real problems, since it means the + * serial port won't be shutdown. + */ + printk(KERN_ERR "mxser_close: bad serial port count; " + "tty->count is 1, info->count is %d\n", info->count); + info->count = 1; + } + if (--info->count < 0) { + printk(KERN_ERR "mxser_close: bad serial port count for " + "ttys%d: %d\n", tty->index, info->count); + info->count = 0; + } + if (info->count) { + spin_unlock_irqrestore(&info->slock, flags); + return; + } + info->flags |= ASYNC_CLOSING; + spin_unlock_irqrestore(&info->slock, flags); + /* + * Save the termios structure, since this port may have + * separate termios for callout and dialin. + */ + if (info->flags & ASYNC_NORMAL_ACTIVE) + info->normal_termios = *tty->termios; + /* + * Now we wait for the transmit buffer to clear; and we notify + * the line discipline to only process XON/XOFF characters. + */ + tty->closing = 1; + if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, info->closing_wait); + /* + * At this point we stop accepting input. To do this, we + * disable the receive line status interrupts, and tell the + * interrupt driver to stop checking the data ready bit in the + * line status register. + */ + info->IER &= ~UART_IER_RLSI; + if (info->board->chip_flag) + info->IER &= ~MOXA_MUST_RECV_ISR; + + if (info->flags & ASYNC_INITIALIZED) { + outb(info->IER, info->ioaddr + UART_IER); + /* + * Before we drop DTR, make sure the UART transmitter + * has completely drained; this is especially + * important if there is a transmit FIFO! + */ + timeout = jiffies + HZ; + while (!(inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT)) { + schedule_timeout_interruptible(5); + if (time_after(jiffies, timeout)) + break; + } + } + mxser_shutdown(info); + + if (tty->driver->flush_buffer) + tty->driver->flush_buffer(tty); + + tty_ldisc_flush(tty); + + tty->closing = 0; + info->event = 0; + info->tty = NULL; + if (info->blocked_open) { + if (info->close_delay) + schedule_timeout_interruptible(info->close_delay); + wake_up_interruptible(&info->open_wait); + } + + info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); + wake_up_interruptible(&info->close_wait); + +} + +static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count) +{ + int c, total = 0; + struct mxser_port *info = tty->driver_data; + unsigned long flags; + + if (!info->xmit_buf) + return 0; + + while (1) { + c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) + break; + + memcpy(info->xmit_buf + info->xmit_head, buf, c); + spin_lock_irqsave(&info->slock, flags); + info->xmit_head = (info->xmit_head + c) & + (SERIAL_XMIT_SIZE - 1); + info->xmit_cnt += c; + spin_unlock_irqrestore(&info->slock, flags); + + buf += c; + count -= c; + total += c; + } + + if (info->xmit_cnt && !tty->stopped) { + if (!tty->hw_stopped || + (info->type == PORT_16550A) || + (info->board->chip_flag)) { + spin_lock_irqsave(&info->slock, flags); + outb(info->IER & ~UART_IER_THRI, info->ioaddr + + UART_IER); + info->IER |= UART_IER_THRI; + outb(info->IER, info->ioaddr + UART_IER); + spin_unlock_irqrestore(&info->slock, flags); + } + } + return total; +} + +static void mxser_put_char(struct tty_struct *tty, unsigned char ch) +{ + struct mxser_port *info = tty->driver_data; + unsigned long flags; + + if (!info->xmit_buf) + return; + + if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) + return; + + spin_lock_irqsave(&info->slock, flags); + info->xmit_buf[info->xmit_head++] = ch; + info->xmit_head &= SERIAL_XMIT_SIZE - 1; + info->xmit_cnt++; + spin_unlock_irqrestore(&info->slock, flags); + if (!tty->stopped) { + if (!tty->hw_stopped || + (info->type == PORT_16550A) || + info->board->chip_flag) { + spin_lock_irqsave(&info->slock, flags); + outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER); + info->IER |= UART_IER_THRI; + outb(info->IER, info->ioaddr + UART_IER); + spin_unlock_irqrestore(&info->slock, flags); + } + } +} + + +static void mxser_flush_chars(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + unsigned long flags; + + if (info->xmit_cnt <= 0 || + tty->stopped || + !info->xmit_buf || + (tty->hw_stopped && + (info->type != PORT_16550A) && + (!info->board->chip_flag) + )) + return; + + spin_lock_irqsave(&info->slock, flags); + + outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER); + info->IER |= UART_IER_THRI; + outb(info->IER, info->ioaddr + UART_IER); + + spin_unlock_irqrestore(&info->slock, flags); +} + +static int mxser_write_room(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + int ret; + + ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; + if (ret < 0) + ret = 0; + return ret; +} + +static int mxser_chars_in_buffer(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + return info->xmit_cnt; +} + +static void mxser_flush_buffer(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + char fcr; + unsigned long flags; + + + spin_lock_irqsave(&info->slock, flags); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + + fcr = inb(info->ioaddr + UART_FCR); + outb((fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), + info->ioaddr + UART_FCR); + outb(fcr, info->ioaddr + UART_FCR); + + spin_unlock_irqrestore(&info->slock, flags); + + tty_wakeup(tty); +} + +/* + * ------------------------------------------------------------ + * friends of mxser_ioctl() + * ------------------------------------------------------------ + */ +static int mxser_get_serial_info(struct mxser_port *info, + struct serial_struct __user *retinfo) +{ + struct serial_struct tmp; + + if (!retinfo) + return -EFAULT; + memset(&tmp, 0, sizeof(tmp)); + tmp.type = info->type; + tmp.line = info->tty->index; + tmp.port = info->ioaddr; + tmp.irq = info->board->irq; + tmp.flags = info->flags; + tmp.baud_base = info->baud_base; + tmp.close_delay = info->close_delay; + tmp.closing_wait = info->closing_wait; + tmp.custom_divisor = info->custom_divisor; + tmp.hub6 = 0; + if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) + return -EFAULT; + return 0; +} + +static int mxser_set_serial_info(struct mxser_port *info, + struct serial_struct __user *new_info) +{ + struct serial_struct new_serial; + unsigned int flags; + int retval = 0; + + if (!new_info || !info->ioaddr) + return -EFAULT; + if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) + return -EFAULT; + + if ((new_serial.irq != info->board->irq) || + (new_serial.port != info->ioaddr) || + (new_serial.custom_divisor != info->custom_divisor) || + (new_serial.baud_base != info->baud_base)) + return -EPERM; + + flags = info->flags & ASYNC_SPD_MASK; + + if (!capable(CAP_SYS_ADMIN)) { + if ((new_serial.baud_base != info->baud_base) || + (new_serial.close_delay != info->close_delay) || + ((new_serial.flags & ~ASYNC_USR_MASK) != (info->flags & ~ASYNC_USR_MASK))) + return -EPERM; + info->flags = ((info->flags & ~ASYNC_USR_MASK) | + (new_serial.flags & ASYNC_USR_MASK)); + } else { + /* + * OK, past this point, all the error checking has been done. + * At this point, we start making changes..... + */ + info->flags = ((info->flags & ~ASYNC_FLAGS) | + (new_serial.flags & ASYNC_FLAGS)); + info->close_delay = new_serial.close_delay * HZ / 100; + info->closing_wait = new_serial.closing_wait * HZ / 100; + info->tty->low_latency = + (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + info->tty->low_latency = 0; + } + + info->type = new_serial.type; + + process_txrx_fifo(info); + + if (info->flags & ASYNC_INITIALIZED) { + if (flags != (info->flags & ASYNC_SPD_MASK)) + mxser_change_speed(info, NULL); + } else + retval = mxser_startup(info); + + return retval; +} + +/* + * mxser_get_lsr_info - get line status register info + * + * Purpose: Let user call ioctl() to get info when the UART physically + * is emptied. On bus types like RS485, the transmitter must + * release the bus after transmitting. This must be done when + * the transmit shift register is empty, not be done when the + * transmit holding register is empty. This functionality + * allows an RS485 driver to be written in user space. + */ +static int mxser_get_lsr_info(struct mxser_port *info, + unsigned int __user *value) +{ + unsigned char status; + unsigned int result; + unsigned long flags; + + spin_lock_irqsave(&info->slock, flags); + status = inb(info->ioaddr + UART_LSR); + spin_unlock_irqrestore(&info->slock, flags); + result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0); + return put_user(result, value); +} + +/* + * This routine sends a break character out the serial port. + */ +static void mxser_send_break(struct mxser_port *info, int duration) +{ + unsigned long flags; + + if (!info->ioaddr) + return; + set_current_state(TASK_INTERRUPTIBLE); + spin_lock_irqsave(&info->slock, flags); + outb(inb(info->ioaddr + UART_LCR) | UART_LCR_SBC, + info->ioaddr + UART_LCR); + spin_unlock_irqrestore(&info->slock, flags); + schedule_timeout(duration); + spin_lock_irqsave(&info->slock, flags); + outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC, + info->ioaddr + UART_LCR); + spin_unlock_irqrestore(&info->slock, flags); +} + +static int mxser_tiocmget(struct tty_struct *tty, struct file *file) +{ + struct mxser_port *info = tty->driver_data; + unsigned char control, status; + unsigned long flags; + + + if (tty->index == MXSER_PORTS) + return -ENOIOCTLCMD; + if (test_bit(TTY_IO_ERROR, &tty->flags)) + return -EIO; + + control = info->MCR; + + spin_lock_irqsave(&info->slock, flags); + status = inb(info->ioaddr + UART_MSR); + if (status & UART_MSR_ANY_DELTA) + mxser_check_modem_status(info, status); + spin_unlock_irqrestore(&info->slock, flags); + return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) | + ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) | + ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) | + ((status & UART_MSR_RI) ? TIOCM_RNG : 0) | + ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) | + ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); +} + +static int mxser_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) +{ + struct mxser_port *info = tty->driver_data; + unsigned long flags; + + + if (tty->index == MXSER_PORTS) + return -ENOIOCTLCMD; + if (test_bit(TTY_IO_ERROR, &tty->flags)) + return -EIO; + + spin_lock_irqsave(&info->slock, flags); + + if (set & TIOCM_RTS) + info->MCR |= UART_MCR_RTS; + if (set & TIOCM_DTR) + info->MCR |= UART_MCR_DTR; + + if (clear & TIOCM_RTS) + info->MCR &= ~UART_MCR_RTS; + if (clear & TIOCM_DTR) + info->MCR &= ~UART_MCR_DTR; + + outb(info->MCR, info->ioaddr + UART_MCR); + spin_unlock_irqrestore(&info->slock, flags); + return 0; +} + +static int mxser_program_mode(int port) +{ + int id, i, j, n; + + spin_lock(&gm_lock); + outb(0, port); + outb(0, port); + outb(0, port); + (void)inb(port); + (void)inb(port); + outb(0, port); + (void)inb(port); + spin_unlock(&gm_lock); + + id = inb(port + 1) & 0x1F; + if ((id != C168_ASIC_ID) && + (id != C104_ASIC_ID) && + (id != C102_ASIC_ID) && + (id != CI132_ASIC_ID) && + (id != CI134_ASIC_ID) && + (id != CI104J_ASIC_ID)) + return -1; + for (i = 0, j = 0; i < 4; i++) { + n = inb(port + 2); + if (n == 'M') { + j = 1; + } else if ((j == 1) && (n == 1)) { + j = 2; + break; + } else + j = 0; + } + if (j != 2) + id = -2; + return id; +} + +static void mxser_normal_mode(int port) +{ + int i, n; + + outb(0xA5, port + 1); + outb(0x80, port + 3); + outb(12, port + 0); /* 9600 bps */ + outb(0, port + 1); + outb(0x03, port + 3); /* 8 data bits */ + outb(0x13, port + 4); /* loop back mode */ + for (i = 0; i < 16; i++) { + n = inb(port + 5); + if ((n & 0x61) == 0x60) + break; + if ((n & 1) == 1) + (void)inb(port); + } + outb(0x00, port + 4); +} + +#define CHIP_SK 0x01 /* Serial Data Clock in Eprom */ +#define CHIP_DO 0x02 /* Serial Data Output in Eprom */ +#define CHIP_CS 0x04 /* Serial Chip Select in Eprom */ +#define CHIP_DI 0x08 /* Serial Data Input in Eprom */ +#define EN_CCMD 0x000 /* Chip's command register */ +#define EN0_RSARLO 0x008 /* Remote start address reg 0 */ +#define EN0_RSARHI 0x009 /* Remote start address reg 1 */ +#define EN0_RCNTLO 0x00A /* Remote byte count reg WR */ +#define EN0_RCNTHI 0x00B /* Remote byte count reg WR */ +#define EN0_DCFG 0x00E /* Data configuration reg WR */ +#define EN0_PORT 0x010 /* Rcv missed frame error counter RD */ +#define ENC_PAGE0 0x000 /* Select page 0 of chip registers */ +#define ENC_PAGE3 0x0C0 /* Select page 3 of chip registers */ +static int mxser_read_register(int port, unsigned short *regs) +{ + int i, k, value, id; + unsigned int j; + + id = mxser_program_mode(port); + if (id < 0) + return id; + for (i = 0; i < 14; i++) { + k = (i & 0x3F) | 0x180; + for (j = 0x100; j > 0; j >>= 1) { + outb(CHIP_CS, port); + if (k & j) { + outb(CHIP_CS | CHIP_DO, port); + outb(CHIP_CS | CHIP_DO | CHIP_SK, port); /* A? bit of read */ + } else { + outb(CHIP_CS, port); + outb(CHIP_CS | CHIP_SK, port); /* A? bit of read */ + } + } + (void)inb(port); + value = 0; + for (k = 0, j = 0x8000; k < 16; k++, j >>= 1) { + outb(CHIP_CS, port); + outb(CHIP_CS | CHIP_SK, port); + if (inb(port) & CHIP_DI) + value |= j; + } + regs[i] = value; + outb(0, port); + } + mxser_normal_mode(port); + return id; +} + +static int mxser_ioctl_special(unsigned int cmd, void __user *argp) +{ + struct mxser_port *port; + int result, status; + unsigned int i, j; + + switch (cmd) { + case MOXA_GET_CONF: +/* if (copy_to_user(argp, mxsercfg, + sizeof(struct mxser_hwconf) * 4)) + return -EFAULT; + return 0;*/ + return -ENXIO; + case MOXA_GET_MAJOR: + if (copy_to_user(argp, &ttymajor, sizeof(int))) + return -EFAULT; + return 0; + + case MOXA_GET_CUMAJOR: + if (copy_to_user(argp, &calloutmajor, sizeof(int))) + return -EFAULT; + return 0; + + case MOXA_CHKPORTENABLE: + result = 0; + + for (i = 0; i < MXSER_BOARDS; i++) + for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) + if (mxser_boards[i].ports[j].ioaddr) + result |= (1 << i); + + return put_user(result, (unsigned long __user *)argp); + case MOXA_GETDATACOUNT: + if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log))) + return -EFAULT; + return 0; + case MOXA_GETMSTATUS: + for (i = 0; i < MXSER_BOARDS; i++) + for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { + port = &mxser_boards[i].ports[j]; + + GMStatus[i].ri = 0; + if (!port->ioaddr) { + GMStatus[i].dcd = 0; + GMStatus[i].dsr = 0; + GMStatus[i].cts = 0; + continue; + } + + if (!port->tty || !port->tty->termios) + GMStatus[i].cflag = + port->normal_termios.c_cflag; + else + GMStatus[i].cflag = + port->tty->termios->c_cflag; + + status = inb(port->ioaddr + UART_MSR); + if (status & 0x80 /*UART_MSR_DCD */ ) + GMStatus[i].dcd = 1; + else + GMStatus[i].dcd = 0; + + if (status & 0x20 /*UART_MSR_DSR */ ) + GMStatus[i].dsr = 1; + else + GMStatus[i].dsr = 0; + + + if (status & 0x10 /*UART_MSR_CTS */ ) + GMStatus[i].cts = 1; + else + GMStatus[i].cts = 0; + } + if (copy_to_user(argp, GMStatus, + sizeof(struct mxser_mstatus) * MXSER_PORTS)) + return -EFAULT; + return 0; + case MOXA_ASPP_MON_EXT: { + int status, p, shiftbit; + unsigned long opmode; + unsigned cflag, iflag; + + for (i = 0; i < MXSER_BOARDS; i++) + for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { + port = &mxser_boards[i].ports[j]; + if (!port->ioaddr) + continue; + + status = mxser_get_msr(port->ioaddr, 0, i); + + if (status & UART_MSR_TERI) + port->icount.rng++; + if (status & UART_MSR_DDSR) + port->icount.dsr++; + if (status & UART_MSR_DDCD) + port->icount.dcd++; + if (status & UART_MSR_DCTS) + port->icount.cts++; + + port->mon_data.modem_status = status; + mon_data_ext.rx_cnt[i] = port->mon_data.rxcnt; + mon_data_ext.tx_cnt[i] = port->mon_data.txcnt; + mon_data_ext.up_rxcnt[i] = + port->mon_data.up_rxcnt; + mon_data_ext.up_txcnt[i] = + port->mon_data.up_txcnt; + mon_data_ext.modem_status[i] = + port->mon_data.modem_status; + mon_data_ext.baudrate[i] = port->realbaud; + + if (!port->tty || !port->tty->termios) { + cflag = port->normal_termios.c_cflag; + iflag = port->normal_termios.c_iflag; + } else { + cflag = port->tty->termios->c_cflag; + iflag = port->tty->termios->c_iflag; + } + + mon_data_ext.databits[i] = cflag & CSIZE; + + mon_data_ext.stopbits[i] = cflag & CSTOPB; + + mon_data_ext.parity[i] = + cflag & (PARENB | PARODD | CMSPAR); + + mon_data_ext.flowctrl[i] = 0x00; + + if (cflag & CRTSCTS) + mon_data_ext.flowctrl[i] |= 0x03; + + if (iflag & (IXON | IXOFF)) + mon_data_ext.flowctrl[i] |= 0x0C; + + if (port->type == PORT_16550A) + mon_data_ext.fifo[i] = 1; + else + mon_data_ext.fifo[i] = 0; + + p = i % 4; + shiftbit = p * 2; + opmode = inb(port->opmode_ioaddr) >> shiftbit; + opmode &= OP_MODE_MASK; + + mon_data_ext.iftype[i] = opmode; + + } + if (copy_to_user(argp, &mon_data_ext, + sizeof(mon_data_ext))) + return -EFAULT; + + return 0; + + } default: + return -ENOIOCTLCMD; + } + return 0; +} + +static int mxser_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct mxser_port *info = tty->driver_data; + struct async_icount cprev, cnow; /* kernel counter temps */ + struct serial_icounter_struct __user *p_cuser; + unsigned long templ; + unsigned long flags; + void __user *argp = (void __user *)arg; + int retval; + + if (tty->index == MXSER_PORTS) + return mxser_ioctl_special(cmd, argp); + + if (cmd == MOXA_SET_OP_MODE || cmd == MOXA_GET_OP_MODE) { + int p; + unsigned long opmode; + static unsigned char ModeMask[] = { 0xfc, 0xf3, 0xcf, 0x3f }; + int shiftbit; + unsigned char val, mask; + + p = tty->index % 4; + if (cmd == MOXA_SET_OP_MODE) { + if (get_user(opmode, (int __user *) argp)) + return -EFAULT; + if (opmode != RS232_MODE && + opmode != RS485_2WIRE_MODE && + opmode != RS422_MODE && + opmode != RS485_4WIRE_MODE) + return -EFAULT; + mask = ModeMask[p]; + shiftbit = p * 2; + val = inb(info->opmode_ioaddr); + val &= mask; + val |= (opmode << shiftbit); + outb(val, info->opmode_ioaddr); + } else { + shiftbit = p * 2; + opmode = inb(info->opmode_ioaddr) >> shiftbit; + opmode &= OP_MODE_MASK; + if (copy_to_user(argp, &opmode, sizeof(int))) + return -EFAULT; + } + return 0; + } + + if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT && + test_bit(TTY_IO_ERROR, &tty->flags)) + return -EIO; + + switch (cmd) { + case TCSBRK: /* SVID version: non-zero arg --> no break */ + retval = tty_check_change(tty); + if (retval) + return retval; + tty_wait_until_sent(tty, 0); + if (!arg) + mxser_send_break(info, HZ / 4); /* 1/4 second */ + return 0; + case TCSBRKP: /* support for POSIX tcsendbreak() */ + retval = tty_check_change(tty); + if (retval) + return retval; + tty_wait_until_sent(tty, 0); + mxser_send_break(info, arg ? arg * (HZ / 10) : HZ / 4); + return 0; + case TIOCGSOFTCAR: + return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp); + case TIOCSSOFTCAR: + if (get_user(templ, (unsigned long __user *) argp)) + return -EFAULT; + arg = templ; + tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); + return 0; + case TIOCGSERIAL: + return mxser_get_serial_info(info, argp); + case TIOCSSERIAL: + return mxser_set_serial_info(info, argp); + case TIOCSERGETLSR: /* Get line status register */ + return mxser_get_lsr_info(info, argp); + /* + * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change + * - mask passed in arg for lines of interest + * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) + * Caller should use TIOCGICOUNT to see which one it was + */ + case TIOCMIWAIT: { + DECLARE_WAITQUEUE(wait, current); + int ret; + spin_lock_irqsave(&info->slock, flags); + cprev = info->icount; /* note the counters on entry */ + spin_unlock_irqrestore(&info->slock, flags); + + add_wait_queue(&info->delta_msr_wait, &wait); + while (1) { + spin_lock_irqsave(&info->slock, flags); + cnow = info->icount; /* atomic copy */ + spin_unlock_irqrestore(&info->slock, flags); + + set_current_state(TASK_INTERRUPTIBLE); + if (((arg & TIOCM_RNG) && + (cnow.rng != cprev.rng)) || + ((arg & TIOCM_DSR) && + (cnow.dsr != cprev.dsr)) || + ((arg & TIOCM_CD) && + (cnow.dcd != cprev.dcd)) || + ((arg & TIOCM_CTS) && + (cnow.cts != cprev.cts))) { + ret = 0; + break; + } + /* see if a signal did it */ + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + cprev = cnow; + } + current->state = TASK_RUNNING; + remove_wait_queue(&info->delta_msr_wait, &wait); + break; + } + /* NOTREACHED */ + /* + * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) + * Return: write counters to the user passed counter struct + * NB: both 1->0 and 0->1 transitions are counted except for + * RI where only 0->1 is counted. + */ + case TIOCGICOUNT: + spin_lock_irqsave(&info->slock, flags); + cnow = info->icount; + spin_unlock_irqrestore(&info->slock, flags); + p_cuser = argp; + if (put_user(cnow.frame, &p_cuser->frame)) + return -EFAULT; + if (put_user(cnow.brk, &p_cuser->brk)) + return -EFAULT; + if (put_user(cnow.overrun, &p_cuser->overrun)) + return -EFAULT; + if (put_user(cnow.buf_overrun, &p_cuser->buf_overrun)) + return -EFAULT; + if (put_user(cnow.parity, &p_cuser->parity)) + return -EFAULT; + if (put_user(cnow.rx, &p_cuser->rx)) + return -EFAULT; + if (put_user(cnow.tx, &p_cuser->tx)) + return -EFAULT; + put_user(cnow.cts, &p_cuser->cts); + put_user(cnow.dsr, &p_cuser->dsr); + put_user(cnow.rng, &p_cuser->rng); + put_user(cnow.dcd, &p_cuser->dcd); + return 0; + case MOXA_HighSpeedOn: + return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); + case MOXA_SDS_RSTICOUNTER: + info->mon_data.rxcnt = 0; + info->mon_data.txcnt = 0; + return 0; + case MOXA_ASPP_SETBAUD:{ + long baud; + if (get_user(baud, (long __user *)argp)) + return -EFAULT; + mxser_set_baud(info, baud); + return 0; + } + case MOXA_ASPP_GETBAUD: + if (copy_to_user(argp, &info->realbaud, sizeof(long))) + return -EFAULT; + + return 0; + + case MOXA_ASPP_OQUEUE:{ + int len, lsr; + + len = mxser_chars_in_buffer(tty); + + lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT; + + len += (lsr ? 0 : 1); + + if (copy_to_user(argp, &len, sizeof(int))) + return -EFAULT; + + return 0; + } + case MOXA_ASPP_MON: { + int mcr, status; + + status = mxser_get_msr(info->ioaddr, 1, tty->index); + mxser_check_modem_status(info, status); + + mcr = inb(info->ioaddr + UART_MCR); + if (mcr & MOXA_MUST_MCR_XON_FLAG) + info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD; + else + info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFHOLD; + + if (mcr & MOXA_MUST_MCR_TX_XON) + info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFXENT; + else + info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFXENT; + + if (info->tty->hw_stopped) + info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD; + else + info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD; + + if (copy_to_user(argp, &info->mon_data, + sizeof(struct mxser_mon))) + return -EFAULT; + + return 0; + } + case MOXA_ASPP_LSTATUS: { + if (copy_to_user(argp, &info->err_shadow, + sizeof(unsigned char))) + return -EFAULT; + + info->err_shadow = 0; + return 0; + } + case MOXA_SET_BAUD_METHOD: { + int method; + + if (get_user(method, (int __user *)argp)) + return -EFAULT; + mxser_set_baud_method[tty->index] = method; + if (copy_to_user(argp, &method, sizeof(int))) + return -EFAULT; + + return 0; + } + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static void mxser_stoprx(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + + info->ldisc_stop_rx = 1; + if (I_IXOFF(tty)) { + if (info->board->chip_flag) { + info->IER &= ~MOXA_MUST_RECV_ISR; + outb(info->IER, info->ioaddr + UART_IER); + } else { + info->x_char = STOP_CHAR(tty); + outb(0, info->ioaddr + UART_IER); + info->IER |= UART_IER_THRI; + outb(info->IER, info->ioaddr + UART_IER); + } + } + + if (info->tty->termios->c_cflag & CRTSCTS) { + info->MCR &= ~UART_MCR_RTS; + outb(info->MCR, info->ioaddr + UART_MCR); + } +} + +/* + * This routine is called by the upper-layer tty layer to signal that + * incoming characters should be throttled. + */ +static void mxser_throttle(struct tty_struct *tty) +{ + mxser_stoprx(tty); +} + +static void mxser_unthrottle(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + + /* startrx */ + info->ldisc_stop_rx = 0; + if (I_IXOFF(tty)) { + if (info->x_char) + info->x_char = 0; + else { + if (info->board->chip_flag) { + info->IER |= MOXA_MUST_RECV_ISR; + outb(info->IER, info->ioaddr + UART_IER); + } else { + info->x_char = START_CHAR(tty); + outb(0, info->ioaddr + UART_IER); + info->IER |= UART_IER_THRI; + outb(info->IER, info->ioaddr + UART_IER); + } + } + } + + if (info->tty->termios->c_cflag & CRTSCTS) { + info->MCR |= UART_MCR_RTS; + outb(info->MCR, info->ioaddr + UART_MCR); + } +} + +/* + * mxser_stop() and mxser_start() + * + * This routines are called before setting or resetting tty->stopped. + * They enable or disable transmitter interrupts, as necessary. + */ +static void mxser_stop(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + unsigned long flags; + + spin_lock_irqsave(&info->slock, flags); + if (info->IER & UART_IER_THRI) { + info->IER &= ~UART_IER_THRI; + outb(info->IER, info->ioaddr + UART_IER); + } + spin_unlock_irqrestore(&info->slock, flags); +} + +static void mxser_start(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + unsigned long flags; + + spin_lock_irqsave(&info->slock, flags); + if (info->xmit_cnt && info->xmit_buf) { + outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER); + info->IER |= UART_IER_THRI; + outb(info->IER, info->ioaddr + UART_IER); + } + spin_unlock_irqrestore(&info->slock, flags); +} + +static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termios) +{ + struct mxser_port *info = tty->driver_data; + unsigned long flags; + + if ((tty->termios->c_cflag != old_termios->c_cflag) || + (RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) { + + mxser_change_speed(info, old_termios); + + if ((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + mxser_start(tty); + } + } + + /* Handle sw stopped */ + if ((old_termios->c_iflag & IXON) && + !(tty->termios->c_iflag & IXON)) { + tty->stopped = 0; + + if (info->board->chip_flag) { + spin_lock_irqsave(&info->slock, flags); + DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->ioaddr); + spin_unlock_irqrestore(&info->slock, flags); + } + + mxser_start(tty); + } +} + +/* + * mxser_wait_until_sent() --- wait until the transmitter is empty + */ +static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) +{ + struct mxser_port *info = tty->driver_data; + unsigned long orig_jiffies, char_time; + int lsr; + + if (info->type == PORT_UNKNOWN) + return; + + if (info->xmit_fifo_size == 0) + return; /* Just in case.... */ + + orig_jiffies = jiffies; + /* + * Set the check interval to be 1/5 of the estimated time to + * send a single character, and make it at least 1. The check + * interval should also be less than the timeout. + * + * Note: we have to use pretty tight timings here to satisfy + * the NIST-PCTS. + */ + char_time = (info->timeout - HZ / 50) / info->xmit_fifo_size; + char_time = char_time / 5; + if (char_time == 0) + char_time = 1; + if (timeout && timeout < char_time) + char_time = timeout; + /* + * If the transmitter hasn't cleared in twice the approximate + * amount of time to send the entire FIFO, it probably won't + * ever clear. This assumes the UART isn't doing flow + * control, which is currently the case. Hence, if it ever + * takes longer than info->timeout, this is probably due to a + * UART bug of some kind. So, we clamp the timeout parameter at + * 2*info->timeout. + */ + if (!timeout || timeout > 2 * info->timeout) + timeout = 2 * info->timeout; +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + printk(KERN_DEBUG "In rs_wait_until_sent(%d) check=%lu...", + timeout, char_time); + printk("jiff=%lu...", jiffies); +#endif + while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) { +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + printk("lsr = %d (jiff=%lu)...", lsr, jiffies); +#endif + schedule_timeout_interruptible(char_time); + if (signal_pending(current)) + break; + if (timeout && time_after(jiffies, orig_jiffies + timeout)) + break; + } + set_current_state(TASK_RUNNING); + +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); +#endif +} + +/* + * This routine is called by tty_hangup() when a hangup is signaled. + */ +void mxser_hangup(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + + mxser_flush_buffer(tty); + mxser_shutdown(info); + info->event = 0; + info->count = 0; + info->flags &= ~ASYNC_NORMAL_ACTIVE; + info->tty = NULL; + wake_up_interruptible(&info->open_wait); +} + +/* + * mxser_rs_break() --- routine which turns the break handling on or off + */ +static void mxser_rs_break(struct tty_struct *tty, int break_state) +{ + struct mxser_port *info = tty->driver_data; + unsigned long flags; + + spin_lock_irqsave(&info->slock, flags); + if (break_state == -1) + outb(inb(info->ioaddr + UART_LCR) | UART_LCR_SBC, + info->ioaddr + UART_LCR); + else + outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC, + info->ioaddr + UART_LCR); + spin_unlock_irqrestore(&info->slock, flags); +} + +static void mxser_receive_chars(struct mxser_port *port, int *status) +{ + struct tty_struct *tty = port->tty; + unsigned char ch, gdl; + int ignored = 0; + int cnt = 0; + int recv_room; + int max = 256; + unsigned long flags; + + spin_lock_irqsave(&port->slock, flags); + + recv_room = tty->receive_room; + if ((recv_room == 0) && (!port->ldisc_stop_rx)) + mxser_stoprx(tty); + + if (port->board->chip_flag != MOXA_OTHER_UART) { + + if (*status & UART_LSR_SPECIAL) + goto intr_old; + if (port->board->chip_flag == MOXA_MUST_MU860_HWID && + (*status & MOXA_MUST_LSR_RERR)) + goto intr_old; + if (*status & MOXA_MUST_LSR_RERR) + goto intr_old; + + gdl = inb(port->ioaddr + MOXA_MUST_GDL_REGISTER); + + if (port->board->chip_flag == MOXA_MUST_MU150_HWID) + gdl &= MOXA_MUST_GDL_MASK; + if (gdl >= recv_room) { + if (!port->ldisc_stop_rx) + mxser_stoprx(tty); + } + while (gdl--) { + ch = inb(port->ioaddr + UART_RX); + tty_insert_flip_char(tty, ch, 0); + cnt++; + } + goto end_intr; + } +intr_old: + + do { + if (max-- < 0) + break; + + ch = inb(port->ioaddr + UART_RX); + if (port->board->chip_flag && (*status & UART_LSR_OE)) + outb(0x23, port->ioaddr + UART_FCR); + *status &= port->read_status_mask; + if (*status & port->ignore_status_mask) { + if (++ignored > 100) + break; + } else { + char flag = 0; + if (*status & UART_LSR_SPECIAL) { + if (*status & UART_LSR_BI) { + flag = TTY_BREAK; + port->icount.brk++; + + if (port->flags & ASYNC_SAK) + do_SAK(tty); + } else if (*status & UART_LSR_PE) { + flag = TTY_PARITY; + port->icount.parity++; + } else if (*status & UART_LSR_FE) { + flag = TTY_FRAME; + port->icount.frame++; + } else if (*status & UART_LSR_OE) { + flag = TTY_OVERRUN; + port->icount.overrun++; + } + } + tty_insert_flip_char(tty, ch, flag); + cnt++; + if (cnt >= recv_room) { + if (!port->ldisc_stop_rx) + mxser_stoprx(tty); + break; + } + + } + + if (port->board->chip_flag) + break; + + *status = inb(port->ioaddr + UART_LSR); + } while (*status & UART_LSR_DR); + +end_intr: + mxvar_log.rxcnt[port->tty->index] += cnt; + port->mon_data.rxcnt += cnt; + port->mon_data.up_rxcnt += cnt; + spin_unlock_irqrestore(&port->slock, flags); + + tty_flip_buffer_push(tty); +} + +static void mxser_transmit_chars(struct mxser_port *port) +{ + int count, cnt; + unsigned long flags; + + spin_lock_irqsave(&port->slock, flags); + + if (port->x_char) { + outb(port->x_char, port->ioaddr + UART_TX); + port->x_char = 0; + mxvar_log.txcnt[port->tty->index]++; + port->mon_data.txcnt++; + port->mon_data.up_txcnt++; + port->icount.tx++; + goto unlock; + } + + if (port->xmit_buf == 0) + goto unlock; + + if ((port->xmit_cnt <= 0) || port->tty->stopped || + (port->tty->hw_stopped && + (port->type != PORT_16550A) && + (!port->board->chip_flag))) { + port->IER &= ~UART_IER_THRI; + outb(port->IER, port->ioaddr + UART_IER); + goto unlock; + } + + cnt = port->xmit_cnt; + count = port->xmit_fifo_size; + do { + outb(port->xmit_buf[port->xmit_tail++], + port->ioaddr + UART_TX); + port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE - 1); + if (--port->xmit_cnt <= 0) + break; + } while (--count > 0); + mxvar_log.txcnt[port->tty->index] += (cnt - port->xmit_cnt); + + port->mon_data.txcnt += (cnt - port->xmit_cnt); + port->mon_data.up_txcnt += (cnt - port->xmit_cnt); + port->icount.tx += (cnt - port->xmit_cnt); + + if (port->xmit_cnt < WAKEUP_CHARS) { + set_bit(MXSER_EVENT_TXLOW, &port->event); + schedule_work(&port->tqueue); + } + if (port->xmit_cnt <= 0) { + port->IER &= ~UART_IER_THRI; + outb(port->IER, port->ioaddr + UART_IER); + } +unlock: + spin_unlock_irqrestore(&port->slock, flags); +} + +/* + * This is the serial driver's generic interrupt routine + */ +static irqreturn_t mxser_interrupt(int irq, void *dev_id) +{ + int status, iir, i; + struct mxser_board *brd = NULL; + struct mxser_port *port; + int max, irqbits, bits, msr; + int pass_counter = 0; + unsigned int int_cnt; + int handled = IRQ_NONE; + + for (i = 0; i < MXSER_BOARDS; i++) + if (dev_id == &mxser_boards[i]) { + brd = dev_id; + break; + } + + if (i == MXSER_BOARDS) + goto irq_stop; + if (brd == NULL) + goto irq_stop; + max = brd->info->nports; + while (1) { + irqbits = inb(brd->vector) & brd->vector_mask; + if (irqbits == brd->vector_mask) + break; + + handled = IRQ_HANDLED; + for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) { + if (irqbits == brd->vector_mask) + break; + if (bits & irqbits) + continue; + port = &brd->ports[i]; + + int_cnt = 0; + do { + iir = inb(port->ioaddr + UART_IIR); + if (iir & UART_IIR_NO_INT) + break; + iir &= MOXA_MUST_IIR_MASK; + if (!port->tty) { + status = inb(port->ioaddr + UART_LSR); + outb(0x27, port->ioaddr + UART_FCR); + inb(port->ioaddr + UART_MSR); + break; + } + + status = inb(port->ioaddr + UART_LSR); + + if (status & UART_LSR_PE) + port->err_shadow |= NPPI_NOTIFY_PARITY; + if (status & UART_LSR_FE) + port->err_shadow |= NPPI_NOTIFY_FRAMING; + if (status & UART_LSR_OE) + port->err_shadow |= + NPPI_NOTIFY_HW_OVERRUN; + if (status & UART_LSR_BI) + port->err_shadow |= NPPI_NOTIFY_BREAK; + + if (port->board->chip_flag) { + if (iir == MOXA_MUST_IIR_GDA || + iir == MOXA_MUST_IIR_RDA || + iir == MOXA_MUST_IIR_RTO || + iir == MOXA_MUST_IIR_LSR) + mxser_receive_chars(port, + &status); + + } else { + status &= port->read_status_mask; + if (status & UART_LSR_DR) + mxser_receive_chars(port, + &status); + } + msr = inb(port->ioaddr + UART_MSR); + if (msr & UART_MSR_ANY_DELTA) + mxser_check_modem_status(port, msr); + + if (port->board->chip_flag) { + if (iir == 0x02 && (status & + UART_LSR_THRE)) + mxser_transmit_chars(port); + } else { + if (status & UART_LSR_THRE) + mxser_transmit_chars(port); + } + } while (int_cnt++ < MXSER_ISR_PASS_LIMIT); + } + if (pass_counter++ > MXSER_ISR_PASS_LIMIT) + break; /* Prevent infinite loops */ + } + +irq_stop: + return handled; +} + +static const struct tty_operations mxser_ops = { + .open = mxser_open, + .close = mxser_close, + .write = mxser_write, + .put_char = mxser_put_char, + .flush_chars = mxser_flush_chars, + .write_room = mxser_write_room, + .chars_in_buffer = mxser_chars_in_buffer, + .flush_buffer = mxser_flush_buffer, + .ioctl = mxser_ioctl, + .throttle = mxser_throttle, + .unthrottle = mxser_unthrottle, + .set_termios = mxser_set_termios, + .stop = mxser_stop, + .start = mxser_start, + .hangup = mxser_hangup, + .break_ctl = mxser_rs_break, + .wait_until_sent = mxser_wait_until_sent, + .tiocmget = mxser_tiocmget, + .tiocmset = mxser_tiocmset, +}; + +/* + * The MOXA Smartio/Industio serial driver boot-time initialization code! + */ + +static void mxser_release_res(struct mxser_board *brd, struct pci_dev *pdev, + unsigned int irq) +{ + if (irq) + free_irq(brd->irq, brd); + if (pdev != NULL) { /* PCI */ + pci_release_region(pdev, 2); + pci_release_region(pdev, 3); + pci_dev_put(pdev); + } else { + release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); + release_region(brd->vector, 1); + } +} + +static int __devinit mxser_initbrd(struct mxser_board *brd, + struct pci_dev *pdev) +{ + struct mxser_port *info; + unsigned int i; + int retval; + + printk(KERN_INFO "max. baud rate = %d bps.\n", brd->ports[0].max_baud); + + for (i = 0; i < brd->info->nports; i++) { + info = &brd->ports[i]; + info->board = brd; + info->stop_rx = 0; + info->ldisc_stop_rx = 0; + + /* Enhance mode enabled here */ + if (brd->chip_flag != MOXA_OTHER_UART) + ENABLE_MOXA_MUST_ENCHANCE_MODE(info->ioaddr); + + info->flags = ASYNC_SHARE_IRQ; + info->type = brd->uart_type; + + process_txrx_fifo(info); + + info->custom_divisor = info->baud_base * 16; + info->close_delay = 5 * HZ / 10; + info->closing_wait = 30 * HZ; + INIT_WORK(&info->tqueue, mxser_do_softint); + info->normal_termios = mxvar_sdriver->init_termios; + init_waitqueue_head(&info->open_wait); + init_waitqueue_head(&info->close_wait); + init_waitqueue_head(&info->delta_msr_wait); + memset(&info->mon_data, 0, sizeof(struct mxser_mon)); + info->err_shadow = 0; + spin_lock_init(&info->slock); + + /* before set INT ISR, disable all int */ + outb(inb(info->ioaddr + UART_IER) & 0xf0, + info->ioaddr + UART_IER); + } + /* + * Allocate the IRQ if necessary + */ + + retval = request_irq(brd->irq, mxser_interrupt, + (brd->ports[0].flags & ASYNC_SHARE_IRQ) ? IRQF_SHARED : + IRQF_DISABLED, "mxser", brd); + if (retval) { + printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may " + "conflict with another device.\n", + brd->info->name, brd->irq); + /* We hold resources, we need to release them. */ + mxser_release_res(brd, pdev, 0); + return retval; + } + return 0; +} + +static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd) +{ + int id, i, bits; + unsigned short regs[16], irq; + unsigned char scratch, scratch2; + + brd->chip_flag = MOXA_OTHER_UART; + + id = mxser_read_register(cap, regs); + switch (id) { + case C168_ASIC_ID: + brd->info = &mxser_cards[0]; + break; + case C104_ASIC_ID: + brd->info = &mxser_cards[1]; + break; + case CI104J_ASIC_ID: + brd->info = &mxser_cards[2]; + break; + case C102_ASIC_ID: + brd->info = &mxser_cards[5]; + break; + case CI132_ASIC_ID: + brd->info = &mxser_cards[6]; + break; + case CI134_ASIC_ID: + brd->info = &mxser_cards[7]; + break; + default: + return 0; + } + + irq = 0; + /* some ISA cards have 2 ports, but we want to see them as 4-port (why?) + Flag-hack checks if configuration should be read as 2-port here. */ + if (brd->info->nports == 2 || (brd->info->flags & MXSER_HAS2)) { + irq = regs[9] & 0xF000; + irq = irq | (irq >> 4); + if (irq != (regs[9] & 0xFF00)) + return MXSER_ERR_IRQ_CONFLIT; + } else if (brd->info->nports == 4) { + irq = regs[9] & 0xF000; + irq = irq | (irq >> 4); + irq = irq | (irq >> 8); + if (irq != regs[9]) + return MXSER_ERR_IRQ_CONFLIT; + } else if (brd->info->nports == 8) { + irq = regs[9] & 0xF000; + irq = irq | (irq >> 4); + irq = irq | (irq >> 8); + if ((irq != regs[9]) || (irq != regs[10])) + return MXSER_ERR_IRQ_CONFLIT; + } + + if (!irq) + return MXSER_ERR_IRQ; + brd->irq = ((int)(irq & 0xF000) >> 12); + for (i = 0; i < 8; i++) + brd->ports[i].ioaddr = (int) regs[i + 1] & 0xFFF8; + if ((regs[12] & 0x80) == 0) + return MXSER_ERR_VECTOR; + brd->vector = (int)regs[11]; /* interrupt vector */ + if (id == 1) + brd->vector_mask = 0x00FF; + else + brd->vector_mask = 0x000F; + for (i = 7, bits = 0x0100; i >= 0; i--, bits <<= 1) { + if (regs[12] & bits) { + brd->ports[i].baud_base = 921600; + brd->ports[i].max_baud = 921600; + } else { + brd->ports[i].baud_base = 115200; + brd->ports[i].max_baud = 115200; + } + } + scratch2 = inb(cap + UART_LCR) & (~UART_LCR_DLAB); + outb(scratch2 | UART_LCR_DLAB, cap + UART_LCR); + outb(0, cap + UART_EFR); /* EFR is the same as FCR */ + outb(scratch2, cap + UART_LCR); + outb(UART_FCR_ENABLE_FIFO, cap + UART_FCR); + scratch = inb(cap + UART_IIR); + + if (scratch & 0xC0) + brd->uart_type = PORT_16550A; + else + brd->uart_type = PORT_16450; + if (!request_region(brd->ports[0].ioaddr, 8 * brd->info->nports, + "mxser(IO)")) + return MXSER_ERR_IOADDR; + if (!request_region(brd->vector, 1, "mxser(vector)")) { + release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); + return MXSER_ERR_VECTOR; + } + return brd->info->nports; +} + +static int __devinit mxser_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct mxser_board *brd; + unsigned int i, j; + unsigned long ioaddress; + int retval = -EINVAL; + + for (i = 0; i < MXSER_BOARDS; i++) + if (mxser_boards[i].info == NULL) + break; + + if (i >= MXSER_BOARDS) { + printk(KERN_ERR "Too many Smartio/Industio family boards found " + "(maximum %d), board not configured\n", MXSER_BOARDS); + goto err; + } + + brd = &mxser_boards[i]; + brd->idx = i * MXSER_PORTS_PER_BOARD; + printk(KERN_INFO "Found MOXA %s board (BusNo=%d, DevNo=%d)\n", + mxser_cards[ent->driver_data].name, + pdev->bus->number, PCI_SLOT(pdev->devfn)); + + retval = pci_enable_device(pdev); + if (retval) { + printk(KERN_ERR "Moxa SmartI/O PCI enable fail !\n"); + goto err; + } + + /* io address */ + ioaddress = pci_resource_start(pdev, 2); + retval = pci_request_region(pdev, 2, "mxser(IO)"); + if (retval) + goto err; + + brd->info = &mxser_cards[ent->driver_data]; + for (i = 0; i < brd->info->nports; i++) + brd->ports[i].ioaddr = ioaddress + 8 * i; + + /* vector */ + ioaddress = pci_resource_start(pdev, 3); + retval = pci_request_region(pdev, 3, "mxser(vector)"); + if (retval) + goto err_relio; + brd->vector = ioaddress; + + /* irq */ + brd->irq = pdev->irq; + + brd->chip_flag = CheckIsMoxaMust(brd->ports[0].ioaddr); + brd->uart_type = PORT_16550A; + brd->vector_mask = 0; + + for (i = 0; i < brd->info->nports; i++) { + for (j = 0; j < UART_INFO_NUM; j++) { + if (Gpci_uart_info[j].type == brd->chip_flag) { + brd->ports[i].max_baud = + Gpci_uart_info[j].max_baud; + + /* exception....CP-102 */ + if (brd->info->flags & MXSER_HIGHBAUD) + brd->ports[i].max_baud = 921600; + break; + } + } + } + + if (brd->chip_flag == MOXA_MUST_MU860_HWID) { + for (i = 0; i < brd->info->nports; i++) { + if (i < 4) + brd->ports[i].opmode_ioaddr = ioaddress + 4; + else + brd->ports[i].opmode_ioaddr = ioaddress + 0x0c; + } + outb(0, ioaddress + 4); /* default set to RS232 mode */ + outb(0, ioaddress + 0x0c); /* default set to RS232 mode */ + } + + for (i = 0; i < brd->info->nports; i++) { + brd->vector_mask |= (1 << i); + brd->ports[i].baud_base = 921600; + } + + /* mxser_initbrd will hook ISR. */ + if (mxser_initbrd(brd, pdev) < 0) + goto err_relvec; + + for (i = 0; i < brd->info->nports; i++) + tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev); + + pci_set_drvdata(pdev, brd); + + return 0; +err_relvec: + pci_release_region(pdev, 3); +err_relio: + pci_release_region(pdev, 2); + brd->info = NULL; +err: + return retval; +} + +static void __devexit mxser_remove(struct pci_dev *pdev) +{ + struct mxser_board *brd = pci_get_drvdata(pdev); + unsigned int i; + + for (i = 0; i < brd->info->nports; i++) + tty_unregister_device(mxvar_sdriver, brd->idx + i); + + mxser_release_res(brd, pdev, 1); +} + +static struct pci_driver mxser_driver = { + .name = "mxser", + .id_table = mxser_pcibrds, + .probe = mxser_probe, + .remove = __devexit_p(mxser_remove) +}; + +static int __init mxser_module_init(void) +{ + struct mxser_board *brd; + unsigned long cap; + unsigned int i, m, isaloop; + int retval, b; + + pr_debug("Loading module mxser ...\n"); + + mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1); + if (!mxvar_sdriver) + return -ENOMEM; + spin_lock_init(&gm_lock); + + printk(KERN_INFO "MOXA Smartio/Industio family driver version %s\n", + MXSER_VERSION); + + /* Initialize the tty_driver structure */ + mxvar_sdriver->magic = TTY_DRIVER_MAGIC; + mxvar_sdriver->name = "ttyMI"; + mxvar_sdriver->major = ttymajor; + mxvar_sdriver->minor_start = 0; + mxvar_sdriver->num = MXSER_PORTS + 1; + mxvar_sdriver->type = TTY_DRIVER_TYPE_SERIAL; + mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL; + mxvar_sdriver->init_termios = tty_std_termios; + mxvar_sdriver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL; + mxvar_sdriver->flags = TTY_DRIVER_REAL_RAW|TTY_DRIVER_DYNAMIC_DEV; + tty_set_operations(mxvar_sdriver, &mxser_ops); + + retval = tty_register_driver(mxvar_sdriver); + if (retval) { + printk(KERN_ERR "Couldn't install MOXA Smartio/Industio family " + "tty driver !\n"); + goto err_put; + } + + mxvar_diagflag = 0; + + m = 0; + /* Start finding ISA boards here */ + for (isaloop = 0; isaloop < 2; isaloop++) + for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) { + if (!isaloop) + cap = mxserBoardCAP[b]; /* predefined */ + else + cap = ioaddr[b]; /* module param */ + + if (!cap) + continue; + + brd = &mxser_boards[m]; + retval = mxser_get_ISA_conf(cap, brd); + + if (retval != 0) + printk(KERN_INFO "Found MOXA %s board " + "(CAP=0x%x)\n", + brd->info->name, ioaddr[b]); + + if (retval <= 0) { + if (retval == MXSER_ERR_IRQ) + printk(KERN_ERR "Invalid interrupt " + "number, board not " + "configured\n"); + else if (retval == MXSER_ERR_IRQ_CONFLIT) + printk(KERN_ERR "Invalid interrupt " + "number, board not " + "configured\n"); + else if (retval == MXSER_ERR_VECTOR) + printk(KERN_ERR "Invalid interrupt " + "vector, board not " + "configured\n"); + else if (retval == MXSER_ERR_IOADDR) + printk(KERN_ERR "Invalid I/O address, " + "board not configured\n"); + + brd->info = NULL; + continue; + } + + /* mxser_initbrd will hook ISR. */ + if (mxser_initbrd(brd, NULL) < 0) { + brd->info = NULL; + continue; + } + + brd->idx = m * MXSER_PORTS_PER_BOARD; + for (i = 0; i < brd->info->nports; i++) + tty_register_device(mxvar_sdriver, brd->idx + i, + NULL); + + m++; + } + + retval = pci_register_driver(&mxser_driver); + if (retval) { + printk(KERN_ERR "Can't register pci driver\n"); + if (!m) { + retval = -ENODEV; + goto err_unr; + } /* else: we have some ISA cards under control */ + } + + pr_debug("Done.\n"); + + return 0; +err_unr: + tty_unregister_driver(mxvar_sdriver); +err_put: + put_tty_driver(mxvar_sdriver); + return retval; +} + +static void __exit mxser_module_exit(void) +{ + unsigned int i, j; + + pr_debug("Unloading module mxser ...\n"); + + pci_unregister_driver(&mxser_driver); + + for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */ + if (mxser_boards[i].info != NULL) + for (j = 0; j < mxser_boards[i].info->nports; j++) + tty_unregister_device(mxvar_sdriver, + mxser_boards[i].idx + j); + tty_unregister_driver(mxvar_sdriver); + put_tty_driver(mxvar_sdriver); + + for (i = 0; i < MXSER_BOARDS; i++) + if (mxser_boards[i].info != NULL) + mxser_release_res(&mxser_boards[i], NULL, 1); + + pr_debug("Done.\n"); +} + +module_init(mxser_module_init); +module_exit(mxser_module_exit); diff --git a/drivers/char/mxser_new.h b/drivers/char/mxser_new.h new file mode 100644 index 00000000000..a08f0ecb09b --- /dev/null +++ b/drivers/char/mxser_new.h @@ -0,0 +1,450 @@ +#ifndef _MXSER_H +#define _MXSER_H + +/* + * Semi-public control interfaces + */ + +/* + * MOXA ioctls + */ + +#define MOXA 0x400 +#define MOXA_GETDATACOUNT (MOXA + 23) +#define MOXA_GET_CONF (MOXA + 35) +#define MOXA_DIAGNOSE (MOXA + 50) +#define MOXA_CHKPORTENABLE (MOXA + 60) +#define MOXA_HighSpeedOn (MOXA + 61) +#define MOXA_GET_MAJOR (MOXA + 63) +#define MOXA_GET_CUMAJOR (MOXA + 64) +#define MOXA_GETMSTATUS (MOXA + 65) +#define MOXA_SET_OP_MODE (MOXA + 66) +#define MOXA_GET_OP_MODE (MOXA + 67) + +#define RS232_MODE 0 +#define RS485_2WIRE_MODE 1 +#define RS422_MODE 2 +#define RS485_4WIRE_MODE 3 +#define OP_MODE_MASK 3 +// above add by Victor Yu. 01-05-2004 + +#define TTY_THRESHOLD_THROTTLE 128 + +#define LO_WATER (TTY_FLIPBUF_SIZE) +#define HI_WATER (TTY_FLIPBUF_SIZE*2*3/4) + +// added by James. 03-11-2004. +#define MOXA_SDS_GETICOUNTER (MOXA + 68) +#define MOXA_SDS_RSTICOUNTER (MOXA + 69) +// (above) added by James. + +#define MOXA_ASPP_OQUEUE (MOXA + 70) +#define MOXA_ASPP_SETBAUD (MOXA + 71) +#define MOXA_ASPP_GETBAUD (MOXA + 72) +#define MOXA_ASPP_MON (MOXA + 73) +#define MOXA_ASPP_LSTATUS (MOXA + 74) +#define MOXA_ASPP_MON_EXT (MOXA + 75) +#define MOXA_SET_BAUD_METHOD (MOXA + 76) + + +/* --------------------------------------------------- */ + +#define NPPI_NOTIFY_PARITY 0x01 +#define NPPI_NOTIFY_FRAMING 0x02 +#define NPPI_NOTIFY_HW_OVERRUN 0x04 +#define NPPI_NOTIFY_SW_OVERRUN 0x08 +#define NPPI_NOTIFY_BREAK 0x10 + +#define NPPI_NOTIFY_CTSHOLD 0x01 // Tx hold by CTS low +#define NPPI_NOTIFY_DSRHOLD 0x02 // Tx hold by DSR low +#define NPPI_NOTIFY_XOFFHOLD 0x08 // Tx hold by Xoff received +#define NPPI_NOTIFY_XOFFXENT 0x10 // Xoff Sent + +//CheckIsMoxaMust return value +#define MOXA_OTHER_UART 0x00 +#define MOXA_MUST_MU150_HWID 0x01 +#define MOXA_MUST_MU860_HWID 0x02 + +// follow just for Moxa Must chip define. +// +// when LCR register (offset 0x03) write following value, +// the Must chip will enter enchance mode. And write value +// on EFR (offset 0x02) bit 6,7 to change bank. +#define MOXA_MUST_ENTER_ENCHANCE 0xBF + +// when enhance mode enable, access on general bank register +#define MOXA_MUST_GDL_REGISTER 0x07 +#define MOXA_MUST_GDL_MASK 0x7F +#define MOXA_MUST_GDL_HAS_BAD_DATA 0x80 + +#define MOXA_MUST_LSR_RERR 0x80 // error in receive FIFO +// enchance register bank select and enchance mode setting register +// when LCR register equal to 0xBF +#define MOXA_MUST_EFR_REGISTER 0x02 +// enchance mode enable +#define MOXA_MUST_EFR_EFRB_ENABLE 0x10 +// enchance reister bank set 0, 1, 2 +#define MOXA_MUST_EFR_BANK0 0x00 +#define MOXA_MUST_EFR_BANK1 0x40 +#define MOXA_MUST_EFR_BANK2 0x80 +#define MOXA_MUST_EFR_BANK3 0xC0 +#define MOXA_MUST_EFR_BANK_MASK 0xC0 + +// set XON1 value register, when LCR=0xBF and change to bank0 +#define MOXA_MUST_XON1_REGISTER 0x04 + +// set XON2 value register, when LCR=0xBF and change to bank0 +#define MOXA_MUST_XON2_REGISTER 0x05 + +// set XOFF1 value register, when LCR=0xBF and change to bank0 +#define MOXA_MUST_XOFF1_REGISTER 0x06 + +// set XOFF2 value register, when LCR=0xBF and change to bank0 +#define MOXA_MUST_XOFF2_REGISTER 0x07 + +#define MOXA_MUST_RBRTL_REGISTER 0x04 +#define MOXA_MUST_RBRTH_REGISTER 0x05 +#define MOXA_MUST_RBRTI_REGISTER 0x06 +#define MOXA_MUST_THRTL_REGISTER 0x07 +#define MOXA_MUST_ENUM_REGISTER 0x04 +#define MOXA_MUST_HWID_REGISTER 0x05 +#define MOXA_MUST_ECR_REGISTER 0x06 +#define MOXA_MUST_CSR_REGISTER 0x07 + +// good data mode enable +#define MOXA_MUST_FCR_GDA_MODE_ENABLE 0x20 +// only good data put into RxFIFO +#define MOXA_MUST_FCR_GDA_ONLY_ENABLE 0x10 + +// enable CTS interrupt +#define MOXA_MUST_IER_ECTSI 0x80 +// enable RTS interrupt +#define MOXA_MUST_IER_ERTSI 0x40 +// enable Xon/Xoff interrupt +#define MOXA_MUST_IER_XINT 0x20 +// enable GDA interrupt +#define MOXA_MUST_IER_EGDAI 0x10 + +#define MOXA_MUST_RECV_ISR (UART_IER_RDI | MOXA_MUST_IER_EGDAI) + +// GDA interrupt pending +#define MOXA_MUST_IIR_GDA 0x1C +#define MOXA_MUST_IIR_RDA 0x04 +#define MOXA_MUST_IIR_RTO 0x0C +#define MOXA_MUST_IIR_LSR 0x06 + +// recieved Xon/Xoff or specical interrupt pending +#define MOXA_MUST_IIR_XSC 0x10 + +// RTS/CTS change state interrupt pending +#define MOXA_MUST_IIR_RTSCTS 0x20 +#define MOXA_MUST_IIR_MASK 0x3E + +#define MOXA_MUST_MCR_XON_FLAG 0x40 +#define MOXA_MUST_MCR_XON_ANY 0x80 +#define MOXA_MUST_MCR_TX_XON 0x08 + + +// software flow control on chip mask value +#define MOXA_MUST_EFR_SF_MASK 0x0F +// send Xon1/Xoff1 +#define MOXA_MUST_EFR_SF_TX1 0x08 +// send Xon2/Xoff2 +#define MOXA_MUST_EFR_SF_TX2 0x04 +// send Xon1,Xon2/Xoff1,Xoff2 +#define MOXA_MUST_EFR_SF_TX12 0x0C +// don't send Xon/Xoff +#define MOXA_MUST_EFR_SF_TX_NO 0x00 +// Tx software flow control mask +#define MOXA_MUST_EFR_SF_TX_MASK 0x0C +// don't receive Xon/Xoff +#define MOXA_MUST_EFR_SF_RX_NO 0x00 +// receive Xon1/Xoff1 +#define MOXA_MUST_EFR_SF_RX1 0x02 +// receive Xon2/Xoff2 +#define MOXA_MUST_EFR_SF_RX2 0x01 +// receive Xon1,Xon2/Xoff1,Xoff2 +#define MOXA_MUST_EFR_SF_RX12 0x03 +// Rx software flow control mask +#define MOXA_MUST_EFR_SF_RX_MASK 0x03 + +//#define MOXA_MUST_MIN_XOFFLIMIT 66 +//#define MOXA_MUST_MIN_XONLIMIT 20 +//#define ID1_RX_TRIG 120 + + +#define CHECK_MOXA_MUST_XOFFLIMIT(info) { \ + if ( (info)->IsMoxaMustChipFlag && \ + (info)->HandFlow.XoffLimit < MOXA_MUST_MIN_XOFFLIMIT ) { \ + (info)->HandFlow.XoffLimit = MOXA_MUST_MIN_XOFFLIMIT; \ + (info)->HandFlow.XonLimit = MOXA_MUST_MIN_XONLIMIT; \ + } \ +} + +#define ENABLE_MOXA_MUST_ENCHANCE_MODE(baseio) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr |= MOXA_MUST_EFR_EFRB_ENABLE; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define DISABLE_MOXA_MUST_ENCHANCE_MODE(baseio) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_EFRB_ENABLE; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define SET_MOXA_MUST_XON1_VALUE(baseio, Value) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ + __efr |= MOXA_MUST_EFR_BANK0; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb((u8)(Value), (baseio)+MOXA_MUST_XON1_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define SET_MOXA_MUST_XON2_VALUE(baseio, Value) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ + __efr |= MOXA_MUST_EFR_BANK0; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb((u8)(Value), (baseio)+MOXA_MUST_XON2_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define SET_MOXA_MUST_XOFF1_VALUE(baseio, Value) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ + __efr |= MOXA_MUST_EFR_BANK0; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb((u8)(Value), (baseio)+MOXA_MUST_XOFF1_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define SET_MOXA_MUST_XOFF2_VALUE(baseio, Value) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ + __efr |= MOXA_MUST_EFR_BANK0; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb((u8)(Value), (baseio)+MOXA_MUST_XOFF2_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define SET_MOXA_MUST_RBRTL_VALUE(baseio, Value) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ + __efr |= MOXA_MUST_EFR_BANK1; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb((u8)(Value), (baseio)+MOXA_MUST_RBRTL_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define SET_MOXA_MUST_RBRTH_VALUE(baseio, Value) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ + __efr |= MOXA_MUST_EFR_BANK1; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb((u8)(Value), (baseio)+MOXA_MUST_RBRTH_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define SET_MOXA_MUST_RBRTI_VALUE(baseio, Value) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ + __efr |= MOXA_MUST_EFR_BANK1; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb((u8)(Value), (baseio)+MOXA_MUST_RBRTI_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define SET_MOXA_MUST_THRTL_VALUE(baseio, Value) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ + __efr |= MOXA_MUST_EFR_BANK1; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb((u8)(Value), (baseio)+MOXA_MUST_THRTL_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +//#define MOXA_MUST_RBRL_VALUE 4 +#define SET_MOXA_MUST_FIFO_VALUE(info) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((info)->ioaddr+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (info)->ioaddr+UART_LCR); \ + __efr = inb((info)->ioaddr+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ + __efr |= MOXA_MUST_EFR_BANK1; \ + outb(__efr, (info)->ioaddr+MOXA_MUST_EFR_REGISTER); \ + outb((u8)((info)->rx_high_water), (info)->ioaddr+MOXA_MUST_RBRTH_REGISTER); \ + outb((u8)((info)->rx_trigger), (info)->ioaddr+MOXA_MUST_RBRTI_REGISTER); \ + outb((u8)((info)->rx_low_water), (info)->ioaddr+MOXA_MUST_RBRTL_REGISTER); \ + outb(__oldlcr, (info)->ioaddr+UART_LCR); \ +} + + + +#define SET_MOXA_MUST_ENUM_VALUE(baseio, Value) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ + __efr |= MOXA_MUST_EFR_BANK2; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb((u8)(Value), (baseio)+MOXA_MUST_ENUM_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define GET_MOXA_MUST_HARDWARE_ID(baseio, pId) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ + __efr |= MOXA_MUST_EFR_BANK2; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + *pId = inb((baseio)+MOXA_MUST_HWID_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(baseio) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_SF_MASK; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define SET_MOXA_MUST_JUST_TX_SOFTWARE_FLOW_CONTROL(baseio) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_SF_MASK; \ + __efr |= MOXA_MUST_EFR_SF_TX1; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_SF_TX_MASK; \ + __efr |= MOXA_MUST_EFR_SF_TX1; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_SF_TX_MASK; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define SET_MOXA_MUST_JUST_RX_SOFTWARE_FLOW_CONTROL(baseio) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_SF_MASK; \ + __efr |= MOXA_MUST_EFR_SF_RX1; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_SF_RX_MASK; \ + __efr |= MOXA_MUST_EFR_SF_RX1; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_SF_RX_MASK; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define ENABLE_MOXA_MUST_TX_RX_SOFTWARE_FLOW_CONTROL(baseio) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_SF_MASK; \ + __efr |= (MOXA_MUST_EFR_SF_RX1|MOXA_MUST_EFR_SF_TX1); \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define ENABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(baseio) { \ + u8 __oldmcr; \ + __oldmcr = inb((baseio)+UART_MCR); \ + __oldmcr |= MOXA_MUST_MCR_XON_ANY; \ + outb(__oldmcr, (baseio)+UART_MCR); \ +} + +#define DISABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(baseio) { \ + u8 __oldmcr; \ + __oldmcr = inb((baseio)+UART_MCR); \ + __oldmcr &= ~MOXA_MUST_MCR_XON_ANY; \ + outb(__oldmcr, (baseio)+UART_MCR); \ +} + +#define READ_MOXA_MUST_GDL(baseio) inb((baseio)+MOXA_MUST_GDL_REGISTER) + + +#ifndef INIT_WORK +#define INIT_WORK(_work, _func, _data){ \ + _data->tqueue.routine = _func;\ + _data->tqueue.data = _data;\ + } +#endif + +#endif diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index 203dc2b661d..103d338f21e 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c @@ -142,7 +142,7 @@ static ssize_t r3964_write(struct tty_struct * tty, struct file * file, const unsigned char * buf, size_t nr); static int r3964_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg); -static void r3964_set_termios(struct tty_struct *tty, struct termios * old); +static void r3964_set_termios(struct tty_struct *tty, struct ktermios * old); static unsigned int r3964_poll(struct tty_struct * tty, struct file * file, struct poll_table_struct *wait); static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, @@ -1347,7 +1347,7 @@ static int r3964_ioctl(struct tty_struct * tty, struct file * file, } } -static void r3964_set_termios(struct tty_struct *tty, struct termios * old) +static void r3964_set_termios(struct tty_struct *tty, struct ktermios * old) { TRACE_L("set_termios"); } diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 603b9ade5eb..e96a00fe138 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -994,7 +994,7 @@ int is_ignored(int sig) * when the ldisc is closed. */ -static void n_tty_set_termios(struct tty_struct *tty, struct termios * old) +static void n_tty_set_termios(struct tty_struct *tty, struct ktermios * old) { if (!tty) return; diff --git a/drivers/char/nsc_gpio.c b/drivers/char/nsc_gpio.c index 4d47d79bcea..808d44e9a32 100644 --- a/drivers/char/nsc_gpio.c +++ b/drivers/char/nsc_gpio.c @@ -41,7 +41,7 @@ void nsc_gpio_dump(struct nsc_gpio_ops *amp, unsigned index) ssize_t nsc_gpio_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { - unsigned m = iminor(file->f_dentry->d_inode); + unsigned m = iminor(file->f_path.dentry->d_inode); struct nsc_gpio_ops *amp = file->private_data; struct device *dev = amp->dev; size_t i; @@ -104,7 +104,7 @@ ssize_t nsc_gpio_write(struct file *file, const char __user *data, ssize_t nsc_gpio_read(struct file *file, char __user * buf, size_t len, loff_t * ppos) { - unsigned m = iminor(file->f_dentry->d_inode); + unsigned m = iminor(file->f_path.dentry->d_inode); int value; struct nsc_gpio_ops *amp = file->private_data; diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 74d21c1c104..5152cedd887 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -2375,7 +2375,7 @@ static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg) * tty pointer to tty structure * termios pointer to buffer to hold returned old termios */ -static void mgslpc_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; unsigned long flags; diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index c1e3dd837fc..4abd1eff61d 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -106,7 +106,7 @@ static inline void pp_enable_irq (struct pp_struct *pp) static ssize_t pp_read (struct file * file, char __user * buf, size_t count, loff_t * ppos) { - unsigned int minor = iminor(file->f_dentry->d_inode); + unsigned int minor = iminor(file->f_path.dentry->d_inode); struct pp_struct *pp = file->private_data; char * kbuffer; ssize_t bytes_read = 0; @@ -189,7 +189,7 @@ static ssize_t pp_read (struct file * file, char __user * buf, size_t count, static ssize_t pp_write (struct file * file, const char __user * buf, size_t count, loff_t * ppos) { - unsigned int minor = iminor(file->f_dentry->d_inode); + unsigned int minor = iminor(file->f_path.dentry->d_inode); struct pp_struct *pp = file->private_data; char * kbuffer; ssize_t bytes_written = 0; diff --git a/drivers/char/pty.c b/drivers/char/pty.c index 80d3eedd7f9..c07a1b5cd05 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -218,7 +218,7 @@ out: return retval; } -static void pty_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void pty_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { tty->termios->c_cflag &= ~(CSIZE | PARENB); tty->termios->c_cflag |= (CS8 | CREAD); @@ -272,6 +272,8 @@ static void __init legacy_pty_init(void) pty_driver->init_termios.c_oflag = 0; pty_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; pty_driver->init_termios.c_lflag = 0; + pty_driver->init_termios.c_ispeed = 38400; + pty_driver->init_termios.c_ospeed = 38400; pty_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW; pty_driver->other = pty_slave_driver; tty_set_operations(pty_driver, &pty_ops); @@ -286,6 +288,8 @@ static void __init legacy_pty_init(void) pty_slave_driver->subtype = PTY_TYPE_SLAVE; pty_slave_driver->init_termios = tty_std_termios; pty_slave_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; + pty_slave_driver->init_termios.c_ispeed = 38400; + pty_slave_driver->init_termios.c_ospeed = 38400; pty_slave_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW; pty_slave_driver->other = pty_driver; @@ -366,6 +370,8 @@ static void __init unix98_pty_init(void) ptm_driver->init_termios.c_oflag = 0; ptm_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; ptm_driver->init_termios.c_lflag = 0; + ptm_driver->init_termios.c_ispeed = 38400; + ptm_driver->init_termios.c_ospeed = 38400; ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM; ptm_driver->other = pts_driver; @@ -381,6 +387,8 @@ static void __init unix98_pty_init(void) pts_driver->subtype = PTY_TYPE_SLAVE; pts_driver->init_termios = tty_std_termios; pts_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; + pts_driver->init_termios.c_ispeed = 38400; + pts_driver->init_termios.c_ospeed = 38400; pts_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM; pts_driver->other = ptm_driver; diff --git a/drivers/char/random.c b/drivers/char/random.c index 4c6782a1ecd..092a01cc02d 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1048,7 +1048,7 @@ random_write(struct file * file, const char __user * buffer, if (p == buffer) { return (ssize_t)ret; } else { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; inode->i_mtime = current_fs_time(inode->i_sb); mark_inode_dirty(inode); return (ssize_t)(p - buffer); diff --git a/drivers/char/raw.c b/drivers/char/raw.c index 3b32313f6eb..645e20a06ec 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c @@ -75,7 +75,7 @@ static int raw_open(struct inode *inode, struct file *filp) filp->f_flags |= O_DIRECT; filp->f_mapping = bdev->bd_inode->i_mapping; if (++raw_devices[minor].inuse == 1) - filp->f_dentry->d_inode->i_mapping = + filp->f_path.dentry->d_inode->i_mapping = bdev->bd_inode->i_mapping; filp->private_data = bdev; mutex_unlock(&raw_mutex); diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 0a77bfcd5b5..e2a94bfb2a4 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c @@ -1539,7 +1539,7 @@ static void rc_hangup(struct tty_struct * tty) wake_up_interruptible(&port->open_wait); } -static void rc_set_termios(struct tty_struct * tty, struct termios * old_termios) +static void rc_set_termios(struct tty_struct * tty, struct ktermios * old_termios) { struct riscom_port *port = (struct riscom_port *)tty->driver_data; unsigned long flags; @@ -1614,6 +1614,8 @@ static inline int rc_init_drivers(void) riscom_driver->init_termios = tty_std_termios; riscom_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + riscom_driver->init_termios.c_ispeed = 9600; + riscom_driver->init_termios.c_ospeed = 9600; riscom_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(riscom_driver, &riscom_ops); if ((error = tty_register_driver(riscom_driver))) { diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index bac80056f7e..e94a62e30fc 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -712,7 +712,7 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev) * user mode into the driver (exception handler). *info CD manipulation is spinlock protected. */ static void configure_r_port(struct r_port *info, - struct termios *old_termios) + struct ktermios *old_termios) { unsigned cflag; unsigned long flags; @@ -1017,7 +1017,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp) /* * Info->count is now 1; so it's safe to sleep now. */ - info->session = current->signal->session; + info->session = process_session(current); info->pgrp = process_group(current); if ((info->flags & ROCKET_INITIALIZED) == 0) { @@ -1194,7 +1194,7 @@ static void rp_close(struct tty_struct *tty, struct file *filp) } static void rp_set_termios(struct tty_struct *tty, - struct termios *old_termios) + struct ktermios *old_termios) { struct r_port *info = (struct r_port *) tty->driver_data; CHANNEL_t *cp; @@ -2214,7 +2214,7 @@ static int __init init_PCI(int boards_found) int count = 0; /* Work through the PCI device list, pulling out ours */ - while ((dev = pci_find_device(PCI_VENDOR_ID_RP, PCI_ANY_ID, dev))) { + while ((dev = pci_get_device(PCI_VENDOR_ID_RP, PCI_ANY_ID, dev))) { if (register_PCI(count + boards_found, dev)) count++; } @@ -2436,6 +2436,8 @@ static int __init rp_init(void) rocket_driver->init_termios = tty_std_termios; rocket_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + rocket_driver->init_termios.c_ispeed = 9600; + rocket_driver->init_termios.c_ospeed = 9600; #ifdef ROCKET_SOFT_FLOW rocket_driver->flags |= TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; #endif diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c index 4217d38caef..75de5f66517 100644 --- a/drivers/char/ser_a2232.c +++ b/drivers/char/ser_a2232.c @@ -695,6 +695,8 @@ static int a2232_init_drivers(void) a2232_driver->init_termios = tty_std_termios; a2232_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + a2232_driver->init_termios.c_ispeed = 9600; + a2232_driver->init_termios.c_ospeed = 9600; a2232_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(a2232_driver, &a2232_ops); if ((error = tty_register_driver(a2232_driver))) { diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index 9ba13af234b..af50d32ae2c 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c @@ -1695,7 +1695,7 @@ cy_ioctl(struct tty_struct *tty, struct file * file, static void -cy_set_termios(struct tty_struct *tty, struct termios * old_termios) +cy_set_termios(struct tty_struct *tty, struct ktermios * old_termios) { struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index fc87070f186..17d54e1331b 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -979,7 +979,7 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf, } if (ret > 0) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; inode->i_atime = current_fs_time(inode->i_sb); } diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 99137ab66b6..20946f5127e 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c @@ -2311,7 +2311,7 @@ static void sx_hangup(struct tty_struct * tty) } -static void sx_set_termios(struct tty_struct * tty, struct termios * old_termios) +static void sx_set_termios(struct tty_struct * tty, struct ktermios * old_termios) { struct specialix_port *port = (struct specialix_port *)tty->driver_data; unsigned long flags; @@ -2400,6 +2400,8 @@ static int sx_init_drivers(void) specialix_driver->init_termios = tty_std_termios; specialix_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + specialix_driver->init_termios.c_ispeed = 9600; + specialix_driver->init_termios.c_ospeed = 9600; specialix_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(specialix_driver, &sx_ops); @@ -2475,7 +2477,7 @@ static int __init specialix_init(void) i++; continue; } - pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, + pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_IO8, pdev); if (!pdev) break; @@ -2491,6 +2493,9 @@ static int __init specialix_init(void) if (!sx_probe(&sx_board[i])) found ++; } + /* May exit pci_get sequence early with lots of boards */ + if (pdev != NULL) + pci_dev_put(pdev); } #endif diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 5e2de62bce7..e45113a7a47 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c @@ -41,13 +41,12 @@ #include <linux/smp_lock.h> #include <linux/device.h> #include <linux/delay.h> +#include <linux/ctype.h> #include <asm/io.h> #include <asm/uaccess.h> -#ifdef CONFIG_PCI #include <linux/pci.h> -#endif /*****************************************************************************/ @@ -63,45 +62,16 @@ #define BRD_ECH64PCI 27 #define BRD_EASYIOPCI 28 -/* - * Define a configuration structure to hold the board configuration. - * Need to set this up in the code (for now) with the boards that are - * to be configured into the system. This is what needs to be modified - * when adding/removing/modifying boards. Each line entry in the - * stl_brdconf[] array is a board. Each line contains io/irq/memory - * ranges for that board (as well as what type of board it is). - * Some examples: - * { BRD_EASYIO, 0x2a0, 0, 0, 10, 0 }, - * This line would configure an EasyIO board (4 or 8, no difference), - * at io address 2a0 and irq 10. - * Another example: - * { BRD_ECH, 0x2a8, 0x280, 0, 12, 0 }, - * This line will configure an EasyConnection 8/32 board at primary io - * address 2a8, secondary io address 280 and irq 12. - * Enter as many lines into this array as you want (only the first 4 - * will actually be used!). Any combination of EasyIO and EasyConnection - * boards can be specified. EasyConnection 8/32 boards can share their - * secondary io addresses between each other. - * - * NOTE: there is no need to put any entries in this table for PCI - * boards. They will be found automatically by the driver - provided - * PCI BIOS32 support is compiled into the kernel. - */ - -typedef struct { - int brdtype; +struct stlconf { + unsigned int brdtype; int ioaddr1; int ioaddr2; unsigned long memaddr; int irq; int irqtype; -} stlconf_t; - -static stlconf_t stl_brdconf[] = { - /*{ BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },*/ }; -static int stl_nrbrds = ARRAY_SIZE(stl_brdconf); +static unsigned int stl_nrbrds; /*****************************************************************************/ @@ -143,34 +113,30 @@ static struct tty_driver *stl_serial; * with this termios initially. Basically all it defines is a raw port * at 9600, 8 data bits, 1 stop bit. */ -static struct termios stl_deftermios = { +static struct ktermios stl_deftermios = { .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL), .c_cc = INIT_C_CC, + .c_ispeed = 9600, + .c_ospeed = 9600, }; /* - * Define global stats structures. Not used often, and can be - * re-used for each stats call. - */ -static comstats_t stl_comstats; -static combrd_t stl_brdstats; -static stlbrd_t stl_dummybrd; -static stlport_t stl_dummyport; - -/* * Define global place to put buffer overflow characters. */ static char stl_unwanted[SC26198_RXFIFOSIZE]; /*****************************************************************************/ -static stlbrd_t *stl_brds[STL_MAXBRDS]; +static DEFINE_MUTEX(stl_brdslock); +static struct stlbrd *stl_brds[STL_MAXBRDS]; /* * Per board state flags. Used with the state field of the board struct. * Not really much here! */ #define BRD_FOUND 0x1 +#define STL_PROBED 0x2 + /* * Define the port structure istate flags. These set of flags are @@ -187,32 +153,32 @@ static stlbrd_t *stl_brds[STL_MAXBRDS]; * referencing boards when printing trace and stuff. */ static char *stl_brdnames[] = { - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, "EasyIO", "EC8/32-AT", "EC8/32-MC", - (char *) NULL, - (char *) NULL, - (char *) NULL, + NULL, + NULL, + NULL, "EC8/32-PCI", "EC8/64-PCI", "EasyIO-PCI", @@ -225,7 +191,7 @@ static char *stl_brdnames[] = { * load line. These allow for easy board definitions, and easy * modification of the io, memory and irq resoucres. */ -static int stl_nargs = 0; +static unsigned int stl_nargs; static char *board0[4]; static char *board1[4]; static char *board2[4]; @@ -243,12 +209,10 @@ static char **stl_brdsp[] = { * parse any module arguments. */ -typedef struct stlbrdtype { +static struct { char *name; int type; -} stlbrdtype_t; - -static stlbrdtype_t stl_brdstr[] = { +} stl_brdstr[] = { { "easyio", BRD_EASYIO }, { "eio", BRD_EASYIO }, { "20", BRD_EASYIO }, @@ -282,9 +246,6 @@ static stlbrdtype_t stl_brdstr[] = { /* * Define the module agruments. */ -MODULE_AUTHOR("Greg Ungerer"); -MODULE_DESCRIPTION("Stallion Multiport Serial Driver"); -MODULE_LICENSE("GPL"); module_param_array(board0, charp, &stl_nargs, 0); MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]"); @@ -386,8 +347,6 @@ static spinlock_t stallion_lock; /* Guard the tty driver */ /*****************************************************************************/ -#ifdef CONFIG_PCI - /* * Define the Stallion PCI vendor and device IDs. */ @@ -407,22 +366,19 @@ static spinlock_t stallion_lock; /* Guard the tty driver */ /* * Define structure to hold all Stallion PCI boards. */ -typedef struct stlpcibrd { - unsigned short vendid; - unsigned short devid; - int brdtype; -} stlpcibrd_t; - -static stlpcibrd_t stl_pcibrds[] = { - { PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864, BRD_ECH64PCI }, - { PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI, BRD_EASYIOPCI }, - { PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832, BRD_ECHPCI }, - { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410, BRD_ECHPCI }, -}; - -static int stl_nrpcibrds = ARRAY_SIZE(stl_pcibrds); -#endif +static struct pci_device_id stl_pcibrds[] = { + { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864), + .driver_data = BRD_ECH64PCI }, + { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI), + .driver_data = BRD_EASYIOPCI }, + { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832), + .driver_data = BRD_ECHPCI }, + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410), + .driver_data = BRD_ECHPCI }, + { } +}; +MODULE_DEVICE_TABLE(pci, stl_pcibrds); /*****************************************************************************/ @@ -442,134 +398,74 @@ static unsigned int stl_baudrates[] = { 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600 }; -/* - * Define some handy local macros... - */ -#undef MIN -#define MIN(a,b) (((a) <= (b)) ? (a) : (b)) - -#undef TOLOWER -#define TOLOWER(x) ((((x) >= 'A') && ((x) <= 'Z')) ? ((x) + 0x20) : (x)) - /*****************************************************************************/ /* * Declare all those functions in this driver! */ -static void stl_argbrds(void); -static int stl_parsebrd(stlconf_t *confp, char **argp); - -static unsigned long stl_atol(char *str); - -static int stl_init(void); -static int stl_open(struct tty_struct *tty, struct file *filp); -static void stl_close(struct tty_struct *tty, struct file *filp); -static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count); -static void stl_putchar(struct tty_struct *tty, unsigned char ch); -static void stl_flushchars(struct tty_struct *tty); -static int stl_writeroom(struct tty_struct *tty); -static int stl_charsinbuffer(struct tty_struct *tty); -static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); -static void stl_settermios(struct tty_struct *tty, struct termios *old); -static void stl_throttle(struct tty_struct *tty); -static void stl_unthrottle(struct tty_struct *tty); -static void stl_stop(struct tty_struct *tty); -static void stl_start(struct tty_struct *tty); -static void stl_flushbuffer(struct tty_struct *tty); -static void stl_breakctl(struct tty_struct *tty, int state); -static void stl_waituntilsent(struct tty_struct *tty, int timeout); -static void stl_sendxchar(struct tty_struct *tty, char ch); -static void stl_hangup(struct tty_struct *tty); static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg); -static int stl_portinfo(stlport_t *portp, int portnr, char *pos); -static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data); - -static int stl_brdinit(stlbrd_t *brdp); -static int stl_initports(stlbrd_t *brdp, stlpanel_t *panelp); -static int stl_getserial(stlport_t *portp, struct serial_struct __user *sp); -static int stl_setserial(stlport_t *portp, struct serial_struct __user *sp); -static int stl_getbrdstats(combrd_t __user *bp); -static int stl_getportstats(stlport_t *portp, comstats_t __user *cp); -static int stl_clrportstats(stlport_t *portp, comstats_t __user *cp); -static int stl_getportstruct(stlport_t __user *arg); -static int stl_getbrdstruct(stlbrd_t __user *arg); -static int stl_waitcarrier(stlport_t *portp, struct file *filp); -static int stl_eiointr(stlbrd_t *brdp); -static int stl_echatintr(stlbrd_t *brdp); -static int stl_echmcaintr(stlbrd_t *brdp); -static int stl_echpciintr(stlbrd_t *brdp); -static int stl_echpci64intr(stlbrd_t *brdp); -static void stl_offintr(struct work_struct *); -static stlbrd_t *stl_allocbrd(void); -static stlport_t *stl_getport(int brdnr, int panelnr, int portnr); - -static inline int stl_initbrds(void); -static inline int stl_initeio(stlbrd_t *brdp); -static inline int stl_initech(stlbrd_t *brdp); -static inline int stl_getbrdnr(void); - -#ifdef CONFIG_PCI -static inline int stl_findpcibrds(void); -static inline int stl_initpcibrd(int brdtype, struct pci_dev *devp); -#endif +static int stl_brdinit(struct stlbrd *brdp); +static int stl_getportstats(struct stlport *portp, comstats_t __user *cp); +static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp); +static int stl_waitcarrier(struct stlport *portp, struct file *filp); /* * CD1400 uart specific handling functions. */ -static void stl_cd1400setreg(stlport_t *portp, int regnr, int value); -static int stl_cd1400getreg(stlport_t *portp, int regnr); -static int stl_cd1400updatereg(stlport_t *portp, int regnr, int value); -static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp); -static void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp); -static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp); -static int stl_cd1400getsignals(stlport_t *portp); -static void stl_cd1400setsignals(stlport_t *portp, int dtr, int rts); -static void stl_cd1400ccrwait(stlport_t *portp); -static void stl_cd1400enablerxtx(stlport_t *portp, int rx, int tx); -static void stl_cd1400startrxtx(stlport_t *portp, int rx, int tx); -static void stl_cd1400disableintrs(stlport_t *portp); -static void stl_cd1400sendbreak(stlport_t *portp, int len); -static void stl_cd1400flowctrl(stlport_t *portp, int state); -static void stl_cd1400sendflow(stlport_t *portp, int state); -static void stl_cd1400flush(stlport_t *portp); -static int stl_cd1400datastate(stlport_t *portp); -static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase); -static void stl_cd1400echintr(stlpanel_t *panelp, unsigned int iobase); -static void stl_cd1400txisr(stlpanel_t *panelp, int ioaddr); -static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr); -static void stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr); - -static inline int stl_cd1400breakisr(stlport_t *portp, int ioaddr); +static void stl_cd1400setreg(struct stlport *portp, int regnr, int value); +static int stl_cd1400getreg(struct stlport *portp, int regnr); +static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value); +static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp); +static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp); +static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp); +static int stl_cd1400getsignals(struct stlport *portp); +static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts); +static void stl_cd1400ccrwait(struct stlport *portp); +static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx); +static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx); +static void stl_cd1400disableintrs(struct stlport *portp); +static void stl_cd1400sendbreak(struct stlport *portp, int len); +static void stl_cd1400flowctrl(struct stlport *portp, int state); +static void stl_cd1400sendflow(struct stlport *portp, int state); +static void stl_cd1400flush(struct stlport *portp); +static int stl_cd1400datastate(struct stlport *portp); +static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase); +static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase); +static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr); +static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr); +static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr); + +static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr); /* * SC26198 uart specific handling functions. */ -static void stl_sc26198setreg(stlport_t *portp, int regnr, int value); -static int stl_sc26198getreg(stlport_t *portp, int regnr); -static int stl_sc26198updatereg(stlport_t *portp, int regnr, int value); -static int stl_sc26198getglobreg(stlport_t *portp, int regnr); -static int stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp); -static void stl_sc26198portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp); -static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp); -static int stl_sc26198getsignals(stlport_t *portp); -static void stl_sc26198setsignals(stlport_t *portp, int dtr, int rts); -static void stl_sc26198enablerxtx(stlport_t *portp, int rx, int tx); -static void stl_sc26198startrxtx(stlport_t *portp, int rx, int tx); -static void stl_sc26198disableintrs(stlport_t *portp); -static void stl_sc26198sendbreak(stlport_t *portp, int len); -static void stl_sc26198flowctrl(stlport_t *portp, int state); -static void stl_sc26198sendflow(stlport_t *portp, int state); -static void stl_sc26198flush(stlport_t *portp); -static int stl_sc26198datastate(stlport_t *portp); -static void stl_sc26198wait(stlport_t *portp); -static void stl_sc26198txunflow(stlport_t *portp, struct tty_struct *tty); -static void stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase); -static void stl_sc26198txisr(stlport_t *port); -static void stl_sc26198rxisr(stlport_t *port, unsigned int iack); -static void stl_sc26198rxbadch(stlport_t *portp, unsigned char status, char ch); -static void stl_sc26198rxbadchars(stlport_t *portp); -static void stl_sc26198otherisr(stlport_t *port, unsigned int iack); +static void stl_sc26198setreg(struct stlport *portp, int regnr, int value); +static int stl_sc26198getreg(struct stlport *portp, int regnr); +static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value); +static int stl_sc26198getglobreg(struct stlport *portp, int regnr); +static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp); +static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp); +static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp); +static int stl_sc26198getsignals(struct stlport *portp); +static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts); +static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx); +static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx); +static void stl_sc26198disableintrs(struct stlport *portp); +static void stl_sc26198sendbreak(struct stlport *portp, int len); +static void stl_sc26198flowctrl(struct stlport *portp, int state); +static void stl_sc26198sendflow(struct stlport *portp, int state); +static void stl_sc26198flush(struct stlport *portp); +static int stl_sc26198datastate(struct stlport *portp); +static void stl_sc26198wait(struct stlport *portp); +static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty); +static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase); +static void stl_sc26198txisr(struct stlport *port); +static void stl_sc26198rxisr(struct stlport *port, unsigned int iack); +static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch); +static void stl_sc26198rxbadchars(struct stlport *portp); +static void stl_sc26198otherisr(struct stlport *port, unsigned int iack); /*****************************************************************************/ @@ -577,20 +473,20 @@ static void stl_sc26198otherisr(stlport_t *port, unsigned int iack); * Generic UART support structure. */ typedef struct uart { - int (*panelinit)(stlbrd_t *brdp, stlpanel_t *panelp); - void (*portinit)(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp); - void (*setport)(stlport_t *portp, struct termios *tiosp); - int (*getsignals)(stlport_t *portp); - void (*setsignals)(stlport_t *portp, int dtr, int rts); - void (*enablerxtx)(stlport_t *portp, int rx, int tx); - void (*startrxtx)(stlport_t *portp, int rx, int tx); - void (*disableintrs)(stlport_t *portp); - void (*sendbreak)(stlport_t *portp, int len); - void (*flowctrl)(stlport_t *portp, int state); - void (*sendflow)(stlport_t *portp, int state); - void (*flush)(stlport_t *portp); - int (*datastate)(stlport_t *portp); - void (*intr)(stlpanel_t *panelp, unsigned int iobase); + int (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp); + void (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp); + void (*setport)(struct stlport *portp, struct ktermios *tiosp); + int (*getsignals)(struct stlport *portp); + void (*setsignals)(struct stlport *portp, int dtr, int rts); + void (*enablerxtx)(struct stlport *portp, int rx, int tx); + void (*startrxtx)(struct stlport *portp, int rx, int tx); + void (*disableintrs)(struct stlport *portp); + void (*sendbreak)(struct stlport *portp, int len); + void (*flowctrl)(struct stlport *portp, int state); + void (*sendflow)(struct stlport *portp, int state); + void (*flush)(struct stlport *portp); + int (*datastate)(struct stlport *portp); + void (*intr)(struct stlpanel *panelp, unsigned int iobase); } uart_t; /* @@ -712,184 +608,35 @@ static const struct file_operations stl_fsiomem = { .ioctl = stl_memioctl, }; -/*****************************************************************************/ - static struct class *stallion_class; /* - * Loadable module initialization stuff. - */ - -static int __init stallion_module_init(void) -{ - stl_init(); - return 0; -} - -/*****************************************************************************/ - -static void __exit stallion_module_exit(void) -{ - stlbrd_t *brdp; - stlpanel_t *panelp; - stlport_t *portp; - int i, j, k; - -#ifdef DEBUG - printk("cleanup_module()\n"); -#endif - - printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle, - stl_drvversion); - -/* - * Free up all allocated resources used by the ports. This includes - * memory and interrupts. As part of this process we will also do - * a hangup on every open port - to try to flush out any processes - * hanging onto ports. - */ - i = tty_unregister_driver(stl_serial); - put_tty_driver(stl_serial); - if (i) { - printk("STALLION: failed to un-register tty driver, " - "errno=%d\n", -i); - return; - } - for (i = 0; i < 4; i++) - class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i)); - if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"))) - printk("STALLION: failed to un-register serial memory device, " - "errno=%d\n", -i); - class_destroy(stallion_class); - - for (i = 0; (i < stl_nrbrds); i++) { - if ((brdp = stl_brds[i]) == (stlbrd_t *) NULL) - continue; - - free_irq(brdp->irq, brdp); - - for (j = 0; (j < STL_MAXPANELS); j++) { - panelp = brdp->panels[j]; - if (panelp == (stlpanel_t *) NULL) - continue; - for (k = 0; (k < STL_PORTSPERPANEL); k++) { - portp = panelp->ports[k]; - if (portp == (stlport_t *) NULL) - continue; - if (portp->tty != (struct tty_struct *) NULL) - stl_hangup(portp->tty); - kfree(portp->tx.buf); - kfree(portp); - } - kfree(panelp); - } - - release_region(brdp->ioaddr1, brdp->iosize1); - if (brdp->iosize2 > 0) - release_region(brdp->ioaddr2, brdp->iosize2); - - kfree(brdp); - stl_brds[i] = (stlbrd_t *) NULL; - } -} - -module_init(stallion_module_init); -module_exit(stallion_module_exit); - -/*****************************************************************************/ - -/* * Check for any arguments passed in on the module load command line. */ -static void stl_argbrds(void) -{ - stlconf_t conf; - stlbrd_t *brdp; - int i; - -#ifdef DEBUG - printk("stl_argbrds()\n"); -#endif - - for (i = stl_nrbrds; (i < stl_nargs); i++) { - memset(&conf, 0, sizeof(conf)); - if (stl_parsebrd(&conf, stl_brdsp[i]) == 0) - continue; - if ((brdp = stl_allocbrd()) == (stlbrd_t *) NULL) - continue; - stl_nrbrds = i + 1; - brdp->brdnr = i; - brdp->brdtype = conf.brdtype; - brdp->ioaddr1 = conf.ioaddr1; - brdp->ioaddr2 = conf.ioaddr2; - brdp->irq = conf.irq; - brdp->irqtype = conf.irqtype; - stl_brdinit(brdp); - } -} - -/*****************************************************************************/ - -/* - * Convert an ascii string number into an unsigned long. - */ - -static unsigned long stl_atol(char *str) -{ - unsigned long val; - int base, c; - char *sp; - - val = 0; - sp = str; - if ((*sp == '0') && (*(sp+1) == 'x')) { - base = 16; - sp += 2; - } else if (*sp == '0') { - base = 8; - sp++; - } else { - base = 10; - } - - for (; (*sp != 0); sp++) { - c = (*sp > '9') ? (TOLOWER(*sp) - 'a' + 10) : (*sp - '0'); - if ((c < 0) || (c >= base)) { - printk("STALLION: invalid argument %s\n", str); - val = 0; - break; - } - val = (val * base) + c; - } - return val; -} - /*****************************************************************************/ /* * Parse the supplied argument string, into the board conf struct. */ -static int stl_parsebrd(stlconf_t *confp, char **argp) +static int __init stl_parsebrd(struct stlconf *confp, char **argp) { char *sp; - int i; + unsigned int i; -#ifdef DEBUG - printk("stl_parsebrd(confp=%x,argp=%x)\n", (int) confp, (int) argp); -#endif + pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp); - if ((argp[0] == (char *) NULL) || (*argp[0] == 0)) + if ((argp[0] == NULL) || (*argp[0] == 0)) return 0; - for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++) - *sp = TOLOWER(*sp); + for (sp = argp[0], i = 0; (*sp != 0) && (i < 25); sp++, i++) + *sp = tolower(*sp); - for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++) { + for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++) if (strcmp(stl_brdstr[i].name, argp[0]) == 0) break; - } + if (i == ARRAY_SIZE(stl_brdstr)) { printk("STALLION: unknown board name, %s?\n", argp[0]); return 0; @@ -898,16 +645,16 @@ static int stl_parsebrd(stlconf_t *confp, char **argp) confp->brdtype = stl_brdstr[i].type; i = 1; - if ((argp[i] != (char *) NULL) && (*argp[i] != 0)) - confp->ioaddr1 = stl_atol(argp[i]); + if ((argp[i] != NULL) && (*argp[i] != 0)) + confp->ioaddr1 = simple_strtoul(argp[i], NULL, 0); i++; if (confp->brdtype == BRD_ECH) { - if ((argp[i] != (char *) NULL) && (*argp[i] != 0)) - confp->ioaddr2 = stl_atol(argp[i]); + if ((argp[i] != NULL) && (*argp[i] != 0)) + confp->ioaddr2 = simple_strtoul(argp[i], NULL, 0); i++; } - if ((argp[i] != (char *) NULL) && (*argp[i] != 0)) - confp->irq = stl_atol(argp[i]); + if ((argp[i] != NULL) && (*argp[i] != 0)) + confp->irq = simple_strtoul(argp[i], NULL, 0); return 1; } @@ -917,14 +664,14 @@ static int stl_parsebrd(stlconf_t *confp, char **argp) * Allocate a new board structure. Fill out the basic info in it. */ -static stlbrd_t *stl_allocbrd(void) +static struct stlbrd *stl_allocbrd(void) { - stlbrd_t *brdp; + struct stlbrd *brdp; - brdp = kzalloc(sizeof(stlbrd_t), GFP_KERNEL); + brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL); if (!brdp) { printk("STALLION: failed to allocate memory (size=%Zd)\n", - sizeof(stlbrd_t)); + sizeof(struct stlbrd)); return NULL; } @@ -936,26 +683,23 @@ static stlbrd_t *stl_allocbrd(void) static int stl_open(struct tty_struct *tty, struct file *filp) { - stlport_t *portp; - stlbrd_t *brdp; - unsigned int minordev; - int brdnr, panelnr, portnr, rc; - -#ifdef DEBUG - printk("stl_open(tty=%x,filp=%x): device=%s\n", (int) tty, - (int) filp, tty->name); -#endif + struct stlport *portp; + struct stlbrd *brdp; + unsigned int minordev, brdnr, panelnr; + int portnr, rc; + + pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name); minordev = tty->index; brdnr = MINOR2BRD(minordev); if (brdnr >= stl_nrbrds) return -ENODEV; brdp = stl_brds[brdnr]; - if (brdp == (stlbrd_t *) NULL) + if (brdp == NULL) return -ENODEV; minordev = MINOR2PORT(minordev); - for (portnr = -1, panelnr = 0; (panelnr < STL_MAXPANELS); panelnr++) { - if (brdp->panels[panelnr] == (stlpanel_t *) NULL) + for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) { + if (brdp->panels[panelnr] == NULL) break; if (minordev < brdp->panels[panelnr]->nrports) { portnr = minordev; @@ -967,7 +711,7 @@ static int stl_open(struct tty_struct *tty, struct file *filp) return -ENODEV; portp = brdp->panels[panelnr]->ports[portnr]; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return -ENODEV; /* @@ -1013,10 +757,10 @@ static int stl_open(struct tty_struct *tty, struct file *filp) * previous opens still in effect. If we are a normal serial device * then also we might have to wait for carrier. */ - if (!(filp->f_flags & O_NONBLOCK)) { + if (!(filp->f_flags & O_NONBLOCK)) if ((rc = stl_waitcarrier(portp, filp)) != 0) return rc; - } + portp->flags |= ASYNC_NORMAL_ACTIVE; return 0; @@ -1029,14 +773,12 @@ static int stl_open(struct tty_struct *tty, struct file *filp) * maybe because if we are clocal then we don't need to wait... */ -static int stl_waitcarrier(stlport_t *portp, struct file *filp) +static int stl_waitcarrier(struct stlport *portp, struct file *filp) { unsigned long flags; int rc, doclocal; -#ifdef DEBUG - printk("stl_waitcarrier(portp=%x,filp=%x)\n", (int) portp, (int) filp); -#endif + pr_debug("stl_waitcarrier(portp=%p,filp=%p)\n", portp, filp); rc = 0; doclocal = 0; @@ -1062,9 +804,8 @@ static int stl_waitcarrier(stlport_t *portp, struct file *filp) break; } if (((portp->flags & ASYNC_CLOSING) == 0) && - (doclocal || (portp->sigs & TIOCM_CD))) { + (doclocal || (portp->sigs & TIOCM_CD))) break; - } if (signal_pending(current)) { rc = -ERESTARTSYS; break; @@ -1083,17 +824,61 @@ static int stl_waitcarrier(stlport_t *portp, struct file *filp) /*****************************************************************************/ +static void stl_flushbuffer(struct tty_struct *tty) +{ + struct stlport *portp; + + pr_debug("stl_flushbuffer(tty=%p)\n", tty); + + if (tty == NULL) + return; + portp = tty->driver_data; + if (portp == NULL) + return; + + stl_flush(portp); + tty_wakeup(tty); +} + +/*****************************************************************************/ + +static void stl_waituntilsent(struct tty_struct *tty, int timeout) +{ + struct stlport *portp; + unsigned long tend; + + pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout); + + if (tty == NULL) + return; + portp = tty->driver_data; + if (portp == NULL) + return; + + if (timeout == 0) + timeout = HZ; + tend = jiffies + timeout; + + while (stl_datastate(portp)) { + if (signal_pending(current)) + break; + msleep_interruptible(20); + if (time_after_eq(jiffies, tend)) + break; + } +} + +/*****************************************************************************/ + static void stl_close(struct tty_struct *tty, struct file *filp) { - stlport_t *portp; + struct stlport *portp; unsigned long flags; -#ifdef DEBUG - printk("stl_close(tty=%x,filp=%x)\n", (int) tty, (int) filp); -#endif + pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp); portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; spin_lock_irqsave(&stallion_lock, flags); @@ -1136,17 +921,17 @@ static void stl_close(struct tty_struct *tty, struct file *filp) stl_enablerxtx(portp, 0, 0); stl_flushbuffer(tty); portp->istate = 0; - if (portp->tx.buf != (char *) NULL) { + if (portp->tx.buf != NULL) { kfree(portp->tx.buf); - portp->tx.buf = (char *) NULL; - portp->tx.head = (char *) NULL; - portp->tx.tail = (char *) NULL; + portp->tx.buf = NULL; + portp->tx.head = NULL; + portp->tx.tail = NULL; } set_bit(TTY_IO_ERROR, &tty->flags); tty_ldisc_flush(tty); tty->closing = 0; - portp->tty = (struct tty_struct *) NULL; + portp->tty = NULL; if (portp->openwaitcnt) { if (portp->close_delay) @@ -1167,20 +952,17 @@ static void stl_close(struct tty_struct *tty, struct file *filp) static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count) { - stlport_t *portp; + struct stlport *portp; unsigned int len, stlen; unsigned char *chbuf; char *head, *tail; -#ifdef DEBUG - printk("stl_write(tty=%x,buf=%x,count=%d)\n", - (int) tty, (int) buf, count); -#endif + pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count); portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return 0; - if (portp->tx.buf == (char *) NULL) + if (portp->tx.buf == NULL) return 0; /* @@ -1201,10 +983,10 @@ static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count stlen = len; } - len = MIN(len, count); + len = min(len, (unsigned int)count); count = 0; while (len > 0) { - stlen = MIN(len, stlen); + stlen = min(len, stlen); memcpy(head, chbuf, stlen); len -= stlen; chbuf += stlen; @@ -1227,20 +1009,18 @@ static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count static void stl_putchar(struct tty_struct *tty, unsigned char ch) { - stlport_t *portp; + struct stlport *portp; unsigned int len; char *head, *tail; -#ifdef DEBUG - printk("stl_putchar(tty=%x,ch=%x)\n", (int) tty, (int) ch); -#endif + pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch); - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; - if (portp->tx.buf == (char *) NULL) + if (portp->tx.buf == NULL) return; head = portp->tx.head; @@ -1267,18 +1047,16 @@ static void stl_putchar(struct tty_struct *tty, unsigned char ch) static void stl_flushchars(struct tty_struct *tty) { - stlport_t *portp; + struct stlport *portp; -#ifdef DEBUG - printk("stl_flushchars(tty=%x)\n", (int) tty); -#endif + pr_debug("stl_flushchars(tty=%p)\n", tty); - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; - if (portp->tx.buf == (char *) NULL) + if (portp->tx.buf == NULL) return; stl_startrxtx(portp, -1, 1); @@ -1288,24 +1066,22 @@ static void stl_flushchars(struct tty_struct *tty) static int stl_writeroom(struct tty_struct *tty) { - stlport_t *portp; + struct stlport *portp; char *head, *tail; -#ifdef DEBUG - printk("stl_writeroom(tty=%x)\n", (int) tty); -#endif + pr_debug("stl_writeroom(tty=%p)\n", tty); - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return 0; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return 0; - if (portp->tx.buf == (char *) NULL) + if (portp->tx.buf == NULL) return 0; head = portp->tx.head; tail = portp->tx.tail; - return ((head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1)); + return (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1); } /*****************************************************************************/ @@ -1321,20 +1097,18 @@ static int stl_writeroom(struct tty_struct *tty) static int stl_charsinbuffer(struct tty_struct *tty) { - stlport_t *portp; + struct stlport *portp; unsigned int size; char *head, *tail; -#ifdef DEBUG - printk("stl_charsinbuffer(tty=%x)\n", (int) tty); -#endif + pr_debug("stl_charsinbuffer(tty=%p)\n", tty); - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return 0; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return 0; - if (portp->tx.buf == (char *) NULL) + if (portp->tx.buf == NULL) return 0; head = portp->tx.head; @@ -1351,14 +1125,12 @@ static int stl_charsinbuffer(struct tty_struct *tty) * Generate the serial struct info. */ -static int stl_getserial(stlport_t *portp, struct serial_struct __user *sp) +static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp) { struct serial_struct sio; - stlbrd_t *brdp; + struct stlbrd *brdp; -#ifdef DEBUG - printk("stl_getserial(portp=%x,sp=%x)\n", (int) portp, (int) sp); -#endif + pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp); memset(&sio, 0, sizeof(struct serial_struct)); sio.line = portp->portnr; @@ -1378,7 +1150,7 @@ static int stl_getserial(stlport_t *portp, struct serial_struct __user *sp) } brdp = stl_brds[portp->brdnr]; - if (brdp != (stlbrd_t *) NULL) + if (brdp != NULL) sio.irq = brdp->irq; return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0; @@ -1392,13 +1164,11 @@ static int stl_getserial(stlport_t *portp, struct serial_struct __user *sp) * just quietly ignore any requests to change irq, etc. */ -static int stl_setserial(stlport_t *portp, struct serial_struct __user *sp) +static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp) { struct serial_struct sio; -#ifdef DEBUG - printk("stl_setserial(portp=%x,sp=%x)\n", (int) portp, (int) sp); -#endif + pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp); if (copy_from_user(&sio, sp, sizeof(struct serial_struct))) return -EFAULT; @@ -1424,12 +1194,12 @@ static int stl_setserial(stlport_t *portp, struct serial_struct __user *sp) static int stl_tiocmget(struct tty_struct *tty, struct file *file) { - stlport_t *portp; + struct stlport *portp; - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return -ENODEV; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return -ENODEV; if (tty->flags & (1 << TTY_IO_ERROR)) return -EIO; @@ -1440,13 +1210,13 @@ static int stl_tiocmget(struct tty_struct *tty, struct file *file) static int stl_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { - stlport_t *portp; + struct stlport *portp; int rts = -1, dtr = -1; - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return -ENODEV; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return -ENODEV; if (tty->flags & (1 << TTY_IO_ERROR)) return -EIO; @@ -1466,27 +1236,24 @@ static int stl_tiocmset(struct tty_struct *tty, struct file *file, static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { - stlport_t *portp; + struct stlport *portp; unsigned int ival; int rc; void __user *argp = (void __user *)arg; -#ifdef DEBUG - printk("stl_ioctl(tty=%x,file=%x,cmd=%x,arg=%x)\n", - (int) tty, (int) file, cmd, (int) arg); -#endif + pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd, + arg); - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return -ENODEV; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return -ENODEV; if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) { + (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) if (tty->flags & (1 << TTY_IO_ERROR)) return -EIO; - } rc = 0; @@ -1531,19 +1298,37 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd /*****************************************************************************/ -static void stl_settermios(struct tty_struct *tty, struct termios *old) +/* + * Start the transmitter again. Just turn TX interrupts back on. + */ + +static void stl_start(struct tty_struct *tty) { - stlport_t *portp; - struct termios *tiosp; + struct stlport *portp; -#ifdef DEBUG - printk("stl_settermios(tty=%x,old=%x)\n", (int) tty, (int) old); -#endif + pr_debug("stl_start(tty=%p)\n", tty); - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) + return; + stl_startrxtx(portp, -1, 1); +} + +/*****************************************************************************/ + +static void stl_settermios(struct tty_struct *tty, struct ktermios *old) +{ + struct stlport *portp; + struct ktermios *tiosp; + + pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old); + + if (tty == NULL) + return; + portp = tty->driver_data; + if (portp == NULL) return; tiosp = tty->termios; @@ -1571,16 +1356,14 @@ static void stl_settermios(struct tty_struct *tty, struct termios *old) static void stl_throttle(struct tty_struct *tty) { - stlport_t *portp; + struct stlport *portp; -#ifdef DEBUG - printk("stl_throttle(tty=%x)\n", (int) tty); -#endif + pr_debug("stl_throttle(tty=%p)\n", tty); - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; stl_flowctrl(portp, 0); } @@ -1593,16 +1376,14 @@ static void stl_throttle(struct tty_struct *tty) static void stl_unthrottle(struct tty_struct *tty) { - stlport_t *portp; + struct stlport *portp; -#ifdef DEBUG - printk("stl_unthrottle(tty=%x)\n", (int) tty); -#endif + pr_debug("stl_unthrottle(tty=%p)\n", tty); - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; stl_flowctrl(portp, 1); } @@ -1616,16 +1397,14 @@ static void stl_unthrottle(struct tty_struct *tty) static void stl_stop(struct tty_struct *tty) { - stlport_t *portp; + struct stlport *portp; -#ifdef DEBUG - printk("stl_stop(tty=%x)\n", (int) tty); -#endif + pr_debug("stl_stop(tty=%p)\n", tty); - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; stl_startrxtx(portp, -1, 0); } @@ -1633,28 +1412,6 @@ static void stl_stop(struct tty_struct *tty) /*****************************************************************************/ /* - * Start the transmitter again. Just turn TX interrupts back on. - */ - -static void stl_start(struct tty_struct *tty) -{ - stlport_t *portp; - -#ifdef DEBUG - printk("stl_start(tty=%x)\n", (int) tty); -#endif - - if (tty == (struct tty_struct *) NULL) - return; - portp = tty->driver_data; - if (portp == (stlport_t *) NULL) - return; - stl_startrxtx(portp, -1, 1); -} - -/*****************************************************************************/ - -/* * Hangup this port. This is pretty much like closing the port, only * a little more brutal. No waiting for data to drain. Shutdown the * port and maybe drop signals. @@ -1662,16 +1419,14 @@ static void stl_start(struct tty_struct *tty) static void stl_hangup(struct tty_struct *tty) { - stlport_t *portp; + struct stlport *portp; -#ifdef DEBUG - printk("stl_hangup(tty=%x)\n", (int) tty); -#endif + pr_debug("stl_hangup(tty=%p)\n", tty); - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; portp->flags &= ~ASYNC_INITIALIZED; @@ -1682,13 +1437,13 @@ static void stl_hangup(struct tty_struct *tty) stl_flushbuffer(tty); portp->istate = 0; set_bit(TTY_IO_ERROR, &tty->flags); - if (portp->tx.buf != (char *) NULL) { + if (portp->tx.buf != NULL) { kfree(portp->tx.buf); - portp->tx.buf = (char *) NULL; - portp->tx.head = (char *) NULL; - portp->tx.tail = (char *) NULL; + portp->tx.buf = NULL; + portp->tx.head = NULL; + portp->tx.tail = NULL; } - portp->tty = (struct tty_struct *) NULL; + portp->tty = NULL; portp->flags &= ~ASYNC_NORMAL_ACTIVE; portp->refcount = 0; wake_up_interruptible(&portp->open_wait); @@ -1696,38 +1451,16 @@ static void stl_hangup(struct tty_struct *tty) /*****************************************************************************/ -static void stl_flushbuffer(struct tty_struct *tty) -{ - stlport_t *portp; - -#ifdef DEBUG - printk("stl_flushbuffer(tty=%x)\n", (int) tty); -#endif - - if (tty == (struct tty_struct *) NULL) - return; - portp = tty->driver_data; - if (portp == (stlport_t *) NULL) - return; - - stl_flush(portp); - tty_wakeup(tty); -} - -/*****************************************************************************/ - static void stl_breakctl(struct tty_struct *tty, int state) { - stlport_t *portp; + struct stlport *portp; -#ifdef DEBUG - printk("stl_breakctl(tty=%x,state=%d)\n", (int) tty, state); -#endif + pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state); - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; stl_sendbreak(portp, ((state == -1) ? 1 : 2)); @@ -1735,48 +1468,16 @@ static void stl_breakctl(struct tty_struct *tty, int state) /*****************************************************************************/ -static void stl_waituntilsent(struct tty_struct *tty, int timeout) -{ - stlport_t *portp; - unsigned long tend; - -#ifdef DEBUG - printk("stl_waituntilsent(tty=%x,timeout=%d)\n", (int) tty, timeout); -#endif - - if (tty == (struct tty_struct *) NULL) - return; - portp = tty->driver_data; - if (portp == (stlport_t *) NULL) - return; - - if (timeout == 0) - timeout = HZ; - tend = jiffies + timeout; - - while (stl_datastate(portp)) { - if (signal_pending(current)) - break; - msleep_interruptible(20); - if (time_after_eq(jiffies, tend)) - break; - } -} - -/*****************************************************************************/ - static void stl_sendxchar(struct tty_struct *tty, char ch) { - stlport_t *portp; + struct stlport *portp; -#ifdef DEBUG - printk("stl_sendxchar(tty=%x,ch=%x)\n", (int) tty, ch); -#endif + pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch); - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; if (ch == STOP_CHAR(tty)) @@ -1797,7 +1498,7 @@ static void stl_sendxchar(struct tty_struct *tty, char ch) * short then padded with spaces). */ -static int stl_portinfo(stlport_t *portp, int portnr, char *pos) +static int stl_portinfo(struct stlport *portp, int portnr, char *pos) { char *sp; int sigs, cnt; @@ -1826,7 +1527,7 @@ static int stl_portinfo(stlport_t *portp, int portnr, char *pos) *sp = ' '; sp += cnt; - for (cnt = (sp - pos); (cnt < (MAXLINE - 1)); cnt++) + for (cnt = sp - pos; cnt < (MAXLINE - 1); cnt++) *sp++ = ' '; if (cnt >= MAXLINE) pos[(MAXLINE - 2)] = '+'; @@ -1843,18 +1544,15 @@ static int stl_portinfo(stlport_t *portp, int portnr, char *pos) static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data) { - stlbrd_t *brdp; - stlpanel_t *panelp; - stlport_t *portp; - int brdnr, panelnr, portnr, totalport; - int curoff, maxoff; + struct stlbrd *brdp; + struct stlpanel *panelp; + struct stlport *portp; + unsigned int brdnr, panelnr, portnr; + int totalport, curoff, maxoff; char *pos; -#ifdef DEBUG - printk("stl_readproc(page=%x,start=%x,off=%x,count=%d,eof=%x," - "data=%x\n", (int) page, (int) start, (int) off, count, - (int) eof, (int) data); -#endif + pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p," + "data=%p\n", page, start, off, count, eof, data); pos = page; totalport = 0; @@ -1873,9 +1571,9 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof * We scan through for each board, panel and port. The offset is * calculated on the fly, and irrelevant ports are skipped. */ - for (brdnr = 0; (brdnr < stl_nrbrds); brdnr++) { + for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) { brdp = stl_brds[brdnr]; - if (brdp == (stlbrd_t *) NULL) + if (brdp == NULL) continue; if (brdp->state == 0) continue; @@ -1887,9 +1585,9 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof } totalport = brdnr * STL_MAXPORTS; - for (panelnr = 0; (panelnr < brdp->nrpanels); panelnr++) { + for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) { panelp = brdp->panels[panelnr]; - if (panelp == (stlpanel_t *) NULL) + if (panelp == NULL) continue; maxoff = curoff + (panelp->nrports * MAXLINE); @@ -1899,10 +1597,10 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof continue; } - for (portnr = 0; (portnr < panelp->nrports); portnr++, + for (portnr = 0; portnr < panelp->nrports; portnr++, totalport++) { portp = panelp->ports[portnr]; - if (portp == (stlport_t *) NULL) + if (portp == NULL) continue; if (off >= (curoff += MAXLINE)) continue; @@ -1917,7 +1615,7 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof stl_readdone: *start = page; - return (pos - page); + return pos - page; } /*****************************************************************************/ @@ -1929,11 +1627,9 @@ stl_readdone: static irqreturn_t stl_intr(int irq, void *dev_id) { - stlbrd_t *brdp = (stlbrd_t *) dev_id; + struct stlbrd *brdp = dev_id; -#ifdef DEBUG - printk("stl_intr(brdp=%x,irq=%d)\n", (int) brdp, irq); -#endif + pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, irq); return IRQ_RETVAL((* brdp->isr)(brdp)); } @@ -1944,9 +1640,9 @@ static irqreturn_t stl_intr(int irq, void *dev_id) * Interrupt service routine for EasyIO board types. */ -static int stl_eiointr(stlbrd_t *brdp) +static int stl_eiointr(struct stlbrd *brdp) { - stlpanel_t *panelp; + struct stlpanel *panelp; unsigned int iobase; int handled = 0; @@ -1967,18 +1663,17 @@ static int stl_eiointr(stlbrd_t *brdp) * Interrupt service routine for ECH-AT board types. */ -static int stl_echatintr(stlbrd_t *brdp) +static int stl_echatintr(struct stlbrd *brdp) { - stlpanel_t *panelp; - unsigned int ioaddr; - int bnknr; + struct stlpanel *panelp; + unsigned int ioaddr, bnknr; int handled = 0; outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl); while (inb(brdp->iostatus) & ECH_INTRPEND) { handled = 1; - for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) { + for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) { ioaddr = brdp->bnkstataddr[bnknr]; if (inb(ioaddr) & ECH_PNLINTRPEND) { panelp = brdp->bnk2panel[bnknr]; @@ -1998,16 +1693,15 @@ static int stl_echatintr(stlbrd_t *brdp) * Interrupt service routine for ECH-MCA board types. */ -static int stl_echmcaintr(stlbrd_t *brdp) +static int stl_echmcaintr(struct stlbrd *brdp) { - stlpanel_t *panelp; - unsigned int ioaddr; - int bnknr; + struct stlpanel *panelp; + unsigned int ioaddr, bnknr; int handled = 0; while (inb(brdp->iostatus) & ECH_INTRPEND) { handled = 1; - for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) { + for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) { ioaddr = brdp->bnkstataddr[bnknr]; if (inb(ioaddr) & ECH_PNLINTRPEND) { panelp = brdp->bnk2panel[bnknr]; @@ -2024,16 +1718,15 @@ static int stl_echmcaintr(stlbrd_t *brdp) * Interrupt service routine for ECH-PCI board types. */ -static int stl_echpciintr(stlbrd_t *brdp) +static int stl_echpciintr(struct stlbrd *brdp) { - stlpanel_t *panelp; - unsigned int ioaddr; - int bnknr, recheck; + struct stlpanel *panelp; + unsigned int ioaddr, bnknr, recheck; int handled = 0; while (1) { recheck = 0; - for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) { + for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) { outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl); ioaddr = brdp->bnkstataddr[bnknr]; if (inb(ioaddr) & ECH_PNLINTRPEND) { @@ -2055,16 +1748,15 @@ static int stl_echpciintr(stlbrd_t *brdp) * Interrupt service routine for ECH-8/64-PCI board types. */ -static int stl_echpci64intr(stlbrd_t *brdp) +static int stl_echpci64intr(struct stlbrd *brdp) { - stlpanel_t *panelp; - unsigned int ioaddr; - int bnknr; + struct stlpanel *panelp; + unsigned int ioaddr, bnknr; int handled = 0; while (inb(brdp->ioctrl) & 0x1) { handled = 1; - for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) { + for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) { ioaddr = brdp->bnkstataddr[bnknr]; if (inb(ioaddr) & ECH_PNLINTRPEND) { panelp = brdp->bnk2panel[bnknr]; @@ -2083,35 +1775,32 @@ static int stl_echpci64intr(stlbrd_t *brdp) */ static void stl_offintr(struct work_struct *work) { - stlport_t *portp = container_of(work, stlport_t, tqueue); + struct stlport *portp = container_of(work, struct stlport, tqueue); struct tty_struct *tty; unsigned int oldsigs; -#ifdef DEBUG - printk("stl_offintr(portp=%x)\n", (int) portp); -#endif + pr_debug("stl_offintr(portp=%p)\n", portp); - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; tty = portp->tty; - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; lock_kernel(); - if (test_bit(ASYI_TXLOW, &portp->istate)) { + if (test_bit(ASYI_TXLOW, &portp->istate)) tty_wakeup(tty); - } + if (test_bit(ASYI_DCDCHANGE, &portp->istate)) { clear_bit(ASYI_DCDCHANGE, &portp->istate); oldsigs = portp->sigs; portp->sigs = stl_getsignals(portp); if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0)) wake_up_interruptible(&portp->open_wait); - if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0)) { + if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0)) if (portp->flags & ASYNC_CHECK_CD) tty_hangup(tty); /* FIXME: module removal race here - AKPM */ - } } unlock_kernel(); } @@ -2122,14 +1811,13 @@ static void stl_offintr(struct work_struct *work) * Initialize all the ports on a panel. */ -static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp) +static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp) { - stlport_t *portp; - int chipmask, i; + struct stlport *portp; + unsigned int i; + int chipmask; -#ifdef DEBUG - printk("stl_initports(brdp=%x,panelp=%x)\n", (int) brdp, (int) panelp); -#endif + pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp); chipmask = stl_panelinit(brdp, panelp); @@ -2137,11 +1825,11 @@ static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp) * All UART's are initialized (if found!). Now go through and setup * each ports data structures. */ - for (i = 0; (i < panelp->nrports); i++) { - portp = kzalloc(sizeof(stlport_t), GFP_KERNEL); + for (i = 0; i < panelp->nrports; i++) { + portp = kzalloc(sizeof(struct stlport), GFP_KERNEL); if (!portp) { printk("STALLION: failed to allocate memory " - "(size=%Zd)\n", sizeof(stlport_t)); + "(size=%Zd)\n", sizeof(struct stlport)); break; } @@ -2164,7 +1852,30 @@ static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp) stl_portinit(brdp, panelp, portp); } - return(0); + return 0; +} + +static void stl_cleanup_panels(struct stlbrd *brdp) +{ + struct stlpanel *panelp; + struct stlport *portp; + unsigned int j, k; + + for (j = 0; j < STL_MAXPANELS; j++) { + panelp = brdp->panels[j]; + if (panelp == NULL) + continue; + for (k = 0; k < STL_PORTSPERPANEL; k++) { + portp = panelp->ports[k]; + if (portp == NULL) + continue; + if (portp->tty != NULL) + stl_hangup(portp->tty); + kfree(portp->tx.buf); + kfree(portp); + } + kfree(panelp); + } } /*****************************************************************************/ @@ -2173,16 +1884,14 @@ static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp) * Try to find and initialize an EasyIO board. */ -static inline int stl_initeio(stlbrd_t *brdp) +static int __devinit stl_initeio(struct stlbrd *brdp) { - stlpanel_t *panelp; + struct stlpanel *panelp; unsigned int status; char *name; - int rc; + int retval; -#ifdef DEBUG - printk("stl_initeio(brdp=%x)\n", (int) brdp); -#endif + pr_debug("stl_initeio(brdp=%p)\n", brdp); brdp->ioctrl = brdp->ioaddr1 + 1; brdp->iostatus = brdp->ioaddr1 + 2; @@ -2207,18 +1916,20 @@ static inline int stl_initeio(stlbrd_t *brdp) (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) { printk("STALLION: invalid irq=%d for brd=%d\n", brdp->irq, brdp->brdnr); - return(-EINVAL); + retval = -EINVAL; + goto err; } outb((stl_vecmap[brdp->irq] | EIO_0WS | ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)), brdp->ioctrl); } + retval = -EBUSY; if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) { printk(KERN_WARNING "STALLION: Warning, board %d I/O address " "%x conflicts with another device\n", brdp->brdnr, brdp->ioaddr1); - return(-EBUSY); + goto err; } if (brdp->iosize2 > 0) @@ -2229,8 +1940,7 @@ static inline int stl_initeio(stlbrd_t *brdp) printk(KERN_WARNING "STALLION: Warning, also " "releasing board %d I/O address %x \n", brdp->brdnr, brdp->ioaddr1); - release_region(brdp->ioaddr1, brdp->iosize1); - return(-EBUSY); + goto err_rel1; } /* @@ -2239,6 +1949,7 @@ static inline int stl_initeio(stlbrd_t *brdp) brdp->clk = CD1400_CLK; brdp->isr = stl_eiointr; + retval = -ENODEV; switch (status & EIO_IDBITMASK) { case EIO_8PORTM: brdp->clk = CD1400_CLK8M; @@ -2262,11 +1973,11 @@ static inline int stl_initeio(stlbrd_t *brdp) brdp->nrports = 16; break; default: - return(-ENODEV); + goto err_rel2; } break; default: - return(-ENODEV); + goto err_rel2; } /* @@ -2274,11 +1985,12 @@ static inline int stl_initeio(stlbrd_t *brdp) * can complete the setup. */ - panelp = kzalloc(sizeof(stlpanel_t), GFP_KERNEL); + panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL); if (!panelp) { printk(KERN_WARNING "STALLION: failed to allocate memory " - "(size=%Zd)\n", sizeof(stlpanel_t)); - return -ENOMEM; + "(size=%Zd)\n", sizeof(struct stlpanel)); + retval = -ENOMEM; + goto err_rel2; } panelp->magic = STL_PANELMAGIC; @@ -2288,10 +2000,10 @@ static inline int stl_initeio(stlbrd_t *brdp) panelp->iobase = brdp->ioaddr1; panelp->hwid = status; if ((status & EIO_IDBITMASK) == EIO_MK3) { - panelp->uartp = (void *) &stl_sc26198uart; + panelp->uartp = &stl_sc26198uart; panelp->isr = stl_sc26198intr; } else { - panelp->uartp = (void *) &stl_cd1400uart; + panelp->uartp = &stl_cd1400uart; panelp->isr = stl_cd1400eiointr; } @@ -2302,11 +2014,20 @@ static inline int stl_initeio(stlbrd_t *brdp) if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) { printk("STALLION: failed to register interrupt " "routine for %s irq=%d\n", name, brdp->irq); - rc = -ENODEV; - } else { - rc = 0; + retval = -ENODEV; + goto err_fr; } - return rc; + + return 0; +err_fr: + stl_cleanup_panels(brdp); +err_rel2: + if (brdp->iosize2 > 0) + release_region(brdp->ioaddr2, brdp->iosize2); +err_rel1: + release_region(brdp->ioaddr1, brdp->iosize1); +err: + return retval; } /*****************************************************************************/ @@ -2316,16 +2037,14 @@ static inline int stl_initeio(stlbrd_t *brdp) * dealing with all types of ECH board. */ -static inline int stl_initech(stlbrd_t *brdp) +static int __devinit stl_initech(struct stlbrd *brdp) { - stlpanel_t *panelp; - unsigned int status, nxtid, ioaddr, conflict; - int panelnr, banknr, i; + struct stlpanel *panelp; + unsigned int status, nxtid, ioaddr, conflict, panelnr, banknr, i; + int retval; char *name; -#ifdef DEBUG - printk("stl_initech(brdp=%x)\n", (int) brdp); -#endif + pr_debug("stl_initech(brdp=%p)\n", brdp); status = 0; conflict = 0; @@ -2342,20 +2061,23 @@ static inline int stl_initech(stlbrd_t *brdp) brdp->ioctrl = brdp->ioaddr1 + 1; brdp->iostatus = brdp->ioaddr1 + 1; status = inb(brdp->iostatus); - if ((status & ECH_IDBITMASK) != ECH_ID) - return(-ENODEV); + if ((status & ECH_IDBITMASK) != ECH_ID) { + retval = -ENODEV; + goto err; + } if ((brdp->irq < 0) || (brdp->irq > 15) || (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) { printk("STALLION: invalid irq=%d for brd=%d\n", brdp->irq, brdp->brdnr); - return(-EINVAL); + retval = -EINVAL; + goto err; } status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1); status |= (stl_vecmap[brdp->irq] << 1); outb((status | ECH_BRDRESET), brdp->ioaddr1); brdp->ioctrlval = ECH_INTENABLE | ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE); - for (i = 0; (i < 10); i++) + for (i = 0; i < 10; i++) outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl); brdp->iosize1 = 2; brdp->iosize2 = 32; @@ -2368,13 +2090,16 @@ static inline int stl_initech(stlbrd_t *brdp) brdp->ioctrl = brdp->ioaddr1 + 0x20; brdp->iostatus = brdp->ioctrl; status = inb(brdp->iostatus); - if ((status & ECH_IDBITMASK) != ECH_ID) - return(-ENODEV); + if ((status & ECH_IDBITMASK) != ECH_ID) { + retval = -ENODEV; + goto err; + } if ((brdp->irq < 0) || (brdp->irq > 15) || (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) { printk("STALLION: invalid irq=%d for brd=%d\n", brdp->irq, brdp->brdnr); - return(-EINVAL); + retval = -EINVAL; + goto err; } outb(ECHMC_BRDRESET, brdp->ioctrl); outb(ECHMC_INTENABLE, brdp->ioctrl); @@ -2401,19 +2126,20 @@ static inline int stl_initech(stlbrd_t *brdp) default: printk("STALLION: unknown board type=%d\n", brdp->brdtype); - return(-EINVAL); - break; + retval = -EINVAL; + goto err; } /* * Check boards for possible IO address conflicts and return fail status * if an IO conflict found. */ + retval = -EBUSY; if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) { printk(KERN_WARNING "STALLION: Warning, board %d I/O address " "%x conflicts with another device\n", brdp->brdnr, brdp->ioaddr1); - return(-EBUSY); + goto err; } if (brdp->iosize2 > 0) @@ -2424,8 +2150,7 @@ static inline int stl_initech(stlbrd_t *brdp) printk(KERN_WARNING "STALLION: Warning, also " "releasing board %d I/O address %x \n", brdp->brdnr, brdp->ioaddr1); - release_region(brdp->ioaddr1, brdp->iosize1); - return(-EBUSY); + goto err_rel1; } /* @@ -2440,19 +2165,19 @@ static inline int stl_initech(stlbrd_t *brdp) panelnr = 0; nxtid = 0; - for (i = 0; (i < STL_MAXPANELS); i++) { + for (i = 0; i < STL_MAXPANELS; i++) { if (brdp->brdtype == BRD_ECHPCI) { outb(nxtid, brdp->ioctrl); ioaddr = brdp->ioaddr2; } status = inb(ioaddr + ECH_PNLSTATUS); if ((status & ECH_PNLIDMASK) != nxtid) - break; - panelp = kzalloc(sizeof(stlpanel_t), GFP_KERNEL); + goto err_fr; + panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL); if (!panelp) { printk("STALLION: failed to allocate memory " - "(size=%Zd)\n", sizeof(stlpanel_t)); - break; + "(size=%Zd)\n", sizeof(struct stlpanel)); + goto err_fr; } panelp->magic = STL_PANELMAGIC; panelp->brdnr = brdp->brdnr; @@ -2465,7 +2190,7 @@ static inline int stl_initech(stlbrd_t *brdp) brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS; if (status & ECH_PNLXPID) { - panelp->uartp = (void *) &stl_sc26198uart; + panelp->uartp = &stl_sc26198uart; panelp->isr = stl_sc26198intr; if (status & ECH_PNL16PORT) { panelp->nrports = 16; @@ -2473,11 +2198,10 @@ static inline int stl_initech(stlbrd_t *brdp) brdp->bnkpageaddr[banknr] = nxtid; brdp->bnkstataddr[banknr++] = ioaddr + 4 + ECH_PNLSTATUS; - } else { + } else panelp->nrports = 8; - } } else { - panelp->uartp = (void *) &stl_cd1400uart; + panelp->uartp = &stl_cd1400uart; panelp->isr = stl_cd1400echintr; if (status & ECH_PNL16PORT) { panelp->nrports = 16; @@ -2500,7 +2224,7 @@ static inline int stl_initech(stlbrd_t *brdp) brdp->panels[panelnr++] = panelp; if ((brdp->brdtype != BRD_ECHPCI) && (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) - break; + goto err_fr; } brdp->nrpanels = panelnr; @@ -2512,12 +2236,19 @@ static inline int stl_initech(stlbrd_t *brdp) if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) { printk("STALLION: failed to register interrupt " "routine for %s irq=%d\n", name, brdp->irq); - i = -ENODEV; - } else { - i = 0; + retval = -ENODEV; + goto err_fr; } - return(i); + return 0; +err_fr: + stl_cleanup_panels(brdp); + if (brdp->iosize2 > 0) + release_region(brdp->ioaddr2, brdp->iosize2); +err_rel1: + release_region(brdp->ioaddr1, brdp->iosize1); +err: + return retval; } /*****************************************************************************/ @@ -2529,48 +2260,61 @@ static inline int stl_initech(stlbrd_t *brdp) * since the initial search and setup is very different. */ -static int __init stl_brdinit(stlbrd_t *brdp) +static int __devinit stl_brdinit(struct stlbrd *brdp) { - int i; + int i, retval; -#ifdef DEBUG - printk("stl_brdinit(brdp=%x)\n", (int) brdp); -#endif + pr_debug("stl_brdinit(brdp=%p)\n", brdp); switch (brdp->brdtype) { case BRD_EASYIO: case BRD_EASYIOPCI: - stl_initeio(brdp); + retval = stl_initeio(brdp); + if (retval) + goto err; break; case BRD_ECH: case BRD_ECHMC: case BRD_ECHPCI: case BRD_ECH64PCI: - stl_initech(brdp); + retval = stl_initech(brdp); + if (retval) + goto err; break; default: printk("STALLION: board=%d is unknown board type=%d\n", brdp->brdnr, brdp->brdtype); - return(ENODEV); + retval = -ENODEV; + goto err; } - stl_brds[brdp->brdnr] = brdp; if ((brdp->state & BRD_FOUND) == 0) { printk("STALLION: %s board not found, board=%d io=%x irq=%d\n", stl_brdnames[brdp->brdtype], brdp->brdnr, brdp->ioaddr1, brdp->irq); - return(ENODEV); + goto err_free; } - for (i = 0; (i < STL_MAXPANELS); i++) - if (brdp->panels[i] != (stlpanel_t *) NULL) + for (i = 0; i < STL_MAXPANELS; i++) + if (brdp->panels[i] != NULL) stl_initports(brdp, brdp->panels[i]); printk("STALLION: %s found, board=%d io=%x irq=%d " "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype], brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels, brdp->nrports); - return(0); + + return 0; +err_free: + free_irq(brdp->irq, brdp); + + stl_cleanup_panels(brdp); + + release_region(brdp->ioaddr1, brdp->iosize1); + if (brdp->iosize2 > 0) + release_region(brdp->ioaddr2, brdp->iosize2); +err: + return retval; } /*****************************************************************************/ @@ -2579,59 +2323,62 @@ static int __init stl_brdinit(stlbrd_t *brdp) * Find the next available board number that is free. */ -static inline int stl_getbrdnr(void) +static int __devinit stl_getbrdnr(void) { - int i; + unsigned int i; - for (i = 0; (i < STL_MAXBRDS); i++) { - if (stl_brds[i] == (stlbrd_t *) NULL) { + for (i = 0; i < STL_MAXBRDS; i++) + if (stl_brds[i] == NULL) { if (i >= stl_nrbrds) stl_nrbrds = i + 1; - return(i); + return i; } - } - return(-1); + + return -1; } /*****************************************************************************/ - -#ifdef CONFIG_PCI - /* * We have a Stallion board. Allocate a board structure and * initialize it. Read its IO and IRQ resources from PCI * configuration space. */ -static inline int stl_initpcibrd(int brdtype, struct pci_dev *devp) +static int __devinit stl_pciprobe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - stlbrd_t *brdp; - -#ifdef DEBUG - printk("stl_initpcibrd(brdtype=%d,busnr=%x,devnr=%x)\n", brdtype, - devp->bus->number, devp->devfn); -#endif - - if (pci_enable_device(devp)) - return(-EIO); - if ((brdp = stl_allocbrd()) == (stlbrd_t *) NULL) - return(-ENOMEM); - if ((brdp->brdnr = stl_getbrdnr()) < 0) { - printk("STALLION: too many boards found, " + struct stlbrd *brdp; + unsigned int i, brdtype = ent->driver_data; + int brdnr, retval = -ENODEV; + + if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) + goto err; + + dev_info(&pdev->dev, "please, report this to LKML: %x/%x/%x\n", + pdev->vendor, pdev->device, pdev->class); + + retval = pci_enable_device(pdev); + if (retval) + goto err; + brdp = stl_allocbrd(); + if (brdp == NULL) { + retval = -ENOMEM; + goto err; + } + mutex_lock(&stl_brdslock); + brdnr = stl_getbrdnr(); + if (brdnr < 0) { + dev_err(&pdev->dev, "too many boards found, " "maximum supported %d\n", STL_MAXBRDS); - return(0); + mutex_unlock(&stl_brdslock); + goto err_fr; } - brdp->brdtype = brdtype; + brdp->brdnr = (unsigned int)brdnr; + stl_brds[brdp->brdnr] = brdp; + mutex_unlock(&stl_brdslock); -/* - * Different Stallion boards use the BAR registers in different ways, - * so set up io addresses based on board type. - */ -#ifdef DEBUG - printk("%s(%d): BAR[]=%x,%x,%x,%x IRQ=%x\n", __FILE__, __LINE__, - pci_resource_start(devp, 0), pci_resource_start(devp, 1), - pci_resource_start(devp, 2), pci_resource_start(devp, 3), devp->irq); -#endif + brdp->brdtype = brdtype; + brdp->state |= STL_PROBED; /* * We have all resources from the board, so let's setup the actual @@ -2639,120 +2386,70 @@ static inline int stl_initpcibrd(int brdtype, struct pci_dev *devp) */ switch (brdtype) { case BRD_ECHPCI: - brdp->ioaddr2 = pci_resource_start(devp, 0); - brdp->ioaddr1 = pci_resource_start(devp, 1); + brdp->ioaddr2 = pci_resource_start(pdev, 0); + brdp->ioaddr1 = pci_resource_start(pdev, 1); break; case BRD_ECH64PCI: - brdp->ioaddr2 = pci_resource_start(devp, 2); - brdp->ioaddr1 = pci_resource_start(devp, 1); + brdp->ioaddr2 = pci_resource_start(pdev, 2); + brdp->ioaddr1 = pci_resource_start(pdev, 1); break; case BRD_EASYIOPCI: - brdp->ioaddr1 = pci_resource_start(devp, 2); - brdp->ioaddr2 = pci_resource_start(devp, 1); + brdp->ioaddr1 = pci_resource_start(pdev, 2); + brdp->ioaddr2 = pci_resource_start(pdev, 1); break; default: - printk("STALLION: unknown PCI board type=%d\n", brdtype); + dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype); break; } - brdp->irq = devp->irq; - stl_brdinit(brdp); - - return(0); -} - -/*****************************************************************************/ - -/* - * Find all Stallion PCI boards that might be installed. Initialize each - * one as it is found. - */ - + brdp->irq = pdev->irq; + retval = stl_brdinit(brdp); + if (retval) + goto err_null; -static inline int stl_findpcibrds(void) -{ - struct pci_dev *dev = NULL; - int i, rc; - -#ifdef DEBUG - printk("stl_findpcibrds()\n"); -#endif + pci_set_drvdata(pdev, brdp); - for (i = 0; (i < stl_nrpcibrds); i++) - while ((dev = pci_find_device(stl_pcibrds[i].vendid, - stl_pcibrds[i].devid, dev))) { - -/* - * Found a device on the PCI bus that has our vendor and - * device ID. Need to check now that it is really us. - */ - if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE) - continue; - - rc = stl_initpcibrd(stl_pcibrds[i].brdtype, dev); - if (rc) - return(rc); - } + for (i = 0; i < brdp->nrports; i++) + tty_register_device(stl_serial, + brdp->brdnr * STL_MAXPORTS + i, &pdev->dev); - return(0); + return 0; +err_null: + stl_brds[brdp->brdnr] = NULL; +err_fr: + kfree(brdp); +err: + return retval; } -#endif - -/*****************************************************************************/ - -/* - * Scan through all the boards in the configuration and see what we - * can find. Handle EIO and the ECH boards a little differently here - * since the initial search and setup is too different. - */ - -static inline int stl_initbrds(void) +static void __devexit stl_pciremove(struct pci_dev *pdev) { - stlbrd_t *brdp; - stlconf_t *confp; - int i; + struct stlbrd *brdp = pci_get_drvdata(pdev); + unsigned int i; -#ifdef DEBUG - printk("stl_initbrds()\n"); -#endif + free_irq(brdp->irq, brdp); - if (stl_nrbrds > STL_MAXBRDS) { - printk("STALLION: too many boards in configuration table, " - "truncating to %d\n", STL_MAXBRDS); - stl_nrbrds = STL_MAXBRDS; - } + stl_cleanup_panels(brdp); -/* - * Firstly scan the list of static boards configured. Allocate - * resources and initialize the boards as found. - */ - for (i = 0; (i < stl_nrbrds); i++) { - confp = &stl_brdconf[i]; - stl_parsebrd(confp, stl_brdsp[i]); - if ((brdp = stl_allocbrd()) == (stlbrd_t *) NULL) - return(-ENOMEM); - brdp->brdnr = i; - brdp->brdtype = confp->brdtype; - brdp->ioaddr1 = confp->ioaddr1; - brdp->ioaddr2 = confp->ioaddr2; - brdp->irq = confp->irq; - brdp->irqtype = confp->irqtype; - stl_brdinit(brdp); - } + release_region(brdp->ioaddr1, brdp->iosize1); + if (brdp->iosize2 > 0) + release_region(brdp->ioaddr2, brdp->iosize2); -/* - * Find any dynamically supported boards. That is via module load - * line options or auto-detected on the PCI bus. - */ - stl_argbrds(); -#ifdef CONFIG_PCI - stl_findpcibrds(); -#endif + for (i = 0; i < brdp->nrports; i++) + tty_unregister_device(stl_serial, + brdp->brdnr * STL_MAXPORTS + i); - return(0); + stl_brds[brdp->brdnr] = NULL; + kfree(brdp); } +static struct pci_driver stl_pcidriver = { + .name = "stallion", + .id_table = stl_pcibrds, + .probe = stl_pciprobe, + .remove = __devexit_p(stl_pciremove) +}; + /*****************************************************************************/ /* @@ -2761,17 +2458,18 @@ static inline int stl_initbrds(void) static int stl_getbrdstats(combrd_t __user *bp) { - stlbrd_t *brdp; - stlpanel_t *panelp; - int i; + combrd_t stl_brdstats; + struct stlbrd *brdp; + struct stlpanel *panelp; + unsigned int i; if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t))) return -EFAULT; if (stl_brdstats.brd >= STL_MAXBRDS) - return(-ENODEV); + return -ENODEV; brdp = stl_brds[stl_brdstats.brd]; - if (brdp == (stlbrd_t *) NULL) - return(-ENODEV); + if (brdp == NULL) + return -ENODEV; memset(&stl_brdstats, 0, sizeof(combrd_t)); stl_brdstats.brd = brdp->brdnr; @@ -2783,7 +2481,7 @@ static int stl_getbrdstats(combrd_t __user *bp) stl_brdstats.irq = brdp->irq; stl_brdstats.nrpanels = brdp->nrpanels; stl_brdstats.nrports = brdp->nrports; - for (i = 0; (i < brdp->nrpanels); i++) { + for (i = 0; i < brdp->nrpanels; i++) { panelp = brdp->panels[i]; stl_brdstats.panels[i].panel = i; stl_brdstats.panels[i].hwid = panelp->hwid; @@ -2799,24 +2497,24 @@ static int stl_getbrdstats(combrd_t __user *bp) * Resolve the referenced port number into a port struct pointer. */ -static stlport_t *stl_getport(int brdnr, int panelnr, int portnr) +static struct stlport *stl_getport(int brdnr, int panelnr, int portnr) { - stlbrd_t *brdp; - stlpanel_t *panelp; + struct stlbrd *brdp; + struct stlpanel *panelp; - if ((brdnr < 0) || (brdnr >= STL_MAXBRDS)) - return((stlport_t *) NULL); + if (brdnr < 0 || brdnr >= STL_MAXBRDS) + return NULL; brdp = stl_brds[brdnr]; - if (brdp == (stlbrd_t *) NULL) - return((stlport_t *) NULL); - if ((panelnr < 0) || (panelnr >= brdp->nrpanels)) - return((stlport_t *) NULL); + if (brdp == NULL) + return NULL; + if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels) + return NULL; panelp = brdp->panels[panelnr]; - if (panelp == (stlpanel_t *) NULL) - return((stlport_t *) NULL); - if ((portnr < 0) || (portnr >= panelp->nrports)) - return((stlport_t *) NULL); - return(panelp->ports[portnr]); + if (panelp == NULL) + return NULL; + if (portnr < 0 || (unsigned int)portnr >= panelp->nrports) + return NULL; + return panelp->ports[portnr]; } /*****************************************************************************/ @@ -2827,8 +2525,9 @@ static stlport_t *stl_getport(int brdnr, int panelnr, int portnr) * what port to get stats for (used through board control device). */ -static int stl_getportstats(stlport_t *portp, comstats_t __user *cp) +static int stl_getportstats(struct stlport *portp, comstats_t __user *cp) { + comstats_t stl_comstats; unsigned char *head, *tail; unsigned long flags; @@ -2837,8 +2536,8 @@ static int stl_getportstats(stlport_t *portp, comstats_t __user *cp) return -EFAULT; portp = stl_getport(stl_comstats.brd, stl_comstats.panel, stl_comstats.port); - if (portp == (stlport_t *) NULL) - return(-ENODEV); + if (portp == NULL) + return -ENODEV; } portp->stats.state = portp->istate; @@ -2853,25 +2552,24 @@ static int stl_getportstats(stlport_t *portp, comstats_t __user *cp) portp->stats.rxbuffered = 0; spin_lock_irqsave(&stallion_lock, flags); - if (portp->tty != (struct tty_struct *) NULL) { + if (portp->tty != NULL) if (portp->tty->driver_data == portp) { portp->stats.ttystate = portp->tty->flags; /* No longer available as a statistic */ portp->stats.rxbuffered = 1; /*portp->tty->flip.count; */ - if (portp->tty->termios != (struct termios *) NULL) { + if (portp->tty->termios != NULL) { portp->stats.cflags = portp->tty->termios->c_cflag; portp->stats.iflags = portp->tty->termios->c_iflag; portp->stats.oflags = portp->tty->termios->c_oflag; portp->stats.lflags = portp->tty->termios->c_lflag; } } - } spin_unlock_irqrestore(&stallion_lock, flags); head = portp->tx.head; tail = portp->tx.tail; - portp->stats.txbuffered = ((head >= tail) ? (head - tail) : - (STL_TXBUFSIZE - (tail - head))); + portp->stats.txbuffered = (head >= tail) ? (head - tail) : + (STL_TXBUFSIZE - (tail - head)); portp->stats.signals = (unsigned long) stl_getsignals(portp); @@ -2885,15 +2583,17 @@ static int stl_getportstats(stlport_t *portp, comstats_t __user *cp) * Clear the port stats structure. We also return it zeroed out... */ -static int stl_clrportstats(stlport_t *portp, comstats_t __user *cp) +static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp) { + comstats_t stl_comstats; + if (!portp) { if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t))) return -EFAULT; portp = stl_getport(stl_comstats.brd, stl_comstats.panel, stl_comstats.port); - if (portp == (stlport_t *) NULL) - return(-ENODEV); + if (portp == NULL) + return -ENODEV; } memset(&portp->stats, 0, sizeof(comstats_t)); @@ -2910,17 +2610,18 @@ static int stl_clrportstats(stlport_t *portp, comstats_t __user *cp) * Return the entire driver ports structure to a user app. */ -static int stl_getportstruct(stlport_t __user *arg) +static int stl_getportstruct(struct stlport __user *arg) { - stlport_t *portp; + struct stlport stl_dummyport; + struct stlport *portp; - if (copy_from_user(&stl_dummyport, arg, sizeof(stlport_t))) + if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport))) return -EFAULT; portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr, stl_dummyport.portnr); if (!portp) return -ENODEV; - return copy_to_user(arg, portp, sizeof(stlport_t)) ? -EFAULT : 0; + return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0; } /*****************************************************************************/ @@ -2929,18 +2630,19 @@ static int stl_getportstruct(stlport_t __user *arg) * Return the entire driver board structure to a user app. */ -static int stl_getbrdstruct(stlbrd_t __user *arg) +static int stl_getbrdstruct(struct stlbrd __user *arg) { - stlbrd_t *brdp; + struct stlbrd stl_dummybrd; + struct stlbrd *brdp; - if (copy_from_user(&stl_dummybrd, arg, sizeof(stlbrd_t))) + if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd))) return -EFAULT; - if ((stl_dummybrd.brdnr < 0) || (stl_dummybrd.brdnr >= STL_MAXBRDS)) + if (stl_dummybrd.brdnr >= STL_MAXBRDS) return -ENODEV; brdp = stl_brds[stl_dummybrd.brdnr]; if (!brdp) - return(-ENODEV); - return copy_to_user(arg, brdp, sizeof(stlbrd_t)) ? -EFAULT : 0; + return -ENODEV; + return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0; } /*****************************************************************************/ @@ -2956,14 +2658,11 @@ static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, uns int brdnr, rc; void __user *argp = (void __user *)arg; -#ifdef DEBUG - printk("stl_memioctl(ip=%x,fp=%x,cmd=%x,arg=%x)\n", (int) ip, - (int) fp, cmd, (int) arg); -#endif + pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg); brdnr = iminor(ip); if (brdnr >= STL_MAXBRDS) - return(-ENODEV); + return -ENODEV; rc = 0; switch (cmd) { @@ -2987,7 +2686,7 @@ static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, uns break; } - return(rc); + return rc; } static const struct tty_operations stl_ops = { @@ -3015,55 +2714,6 @@ static const struct tty_operations stl_ops = { }; /*****************************************************************************/ - -static int __init stl_init(void) -{ - int i; - printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion); - - spin_lock_init(&stallion_lock); - spin_lock_init(&brd_lock); - - stl_initbrds(); - - stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS); - if (!stl_serial) - return -1; - -/* - * Set up a character driver for per board stuff. This is mainly used - * to do stats ioctls on the ports. - */ - if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem)) - printk("STALLION: failed to register serial board device\n"); - - stallion_class = class_create(THIS_MODULE, "staliomem"); - for (i = 0; i < 4; i++) - class_device_create(stallion_class, NULL, - MKDEV(STL_SIOMEMMAJOR, i), NULL, - "staliomem%d", i); - - stl_serial->owner = THIS_MODULE; - stl_serial->driver_name = stl_drvname; - stl_serial->name = "ttyE"; - stl_serial->major = STL_SERIALMAJOR; - stl_serial->minor_start = 0; - stl_serial->type = TTY_DRIVER_TYPE_SERIAL; - stl_serial->subtype = SERIAL_TYPE_NORMAL; - stl_serial->init_termios = stl_deftermios; - stl_serial->flags = TTY_DRIVER_REAL_RAW; - tty_set_operations(stl_serial, &stl_ops); - - if (tty_register_driver(stl_serial)) { - put_tty_driver(stl_serial); - printk("STALLION: failed to register serial driver\n"); - return -1; - } - - return 0; -} - -/*****************************************************************************/ /* CD1400 HARDWARE FUNCTIONS */ /*****************************************************************************/ @@ -3073,21 +2723,21 @@ static int __init stl_init(void) * (Maybe should make this inline...) */ -static int stl_cd1400getreg(stlport_t *portp, int regnr) +static int stl_cd1400getreg(struct stlport *portp, int regnr) { outb((regnr + portp->uartaddr), portp->ioaddr); return inb(portp->ioaddr + EREG_DATA); } -static void stl_cd1400setreg(stlport_t *portp, int regnr, int value) +static void stl_cd1400setreg(struct stlport *portp, int regnr, int value) { - outb((regnr + portp->uartaddr), portp->ioaddr); + outb(regnr + portp->uartaddr, portp->ioaddr); outb(value, portp->ioaddr + EREG_DATA); } -static int stl_cd1400updatereg(stlport_t *portp, int regnr, int value) +static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value) { - outb((regnr + portp->uartaddr), portp->ioaddr); + outb(regnr + portp->uartaddr, portp->ioaddr); if (inb(portp->ioaddr + EREG_DATA) != value) { outb(value, portp->ioaddr + EREG_DATA); return 1; @@ -3103,16 +2753,14 @@ static int stl_cd1400updatereg(stlport_t *portp, int regnr, int value) * identical when dealing with ports. */ -static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp) +static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp) { unsigned int gfrcr; int chipmask, i, j; int nrchips, uartaddr, ioaddr; unsigned long flags; -#ifdef DEBUG - printk("stl_panelinit(brdp=%x,panelp=%x)\n", (int) brdp, (int) panelp); -#endif + pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp); spin_lock_irqsave(&brd_lock, flags); BRDENABLE(panelp->brdnr, panelp->pagenr); @@ -3122,13 +2770,12 @@ static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp) */ chipmask = 0; nrchips = panelp->nrports / CD1400_PORTS; - for (i = 0; (i < nrchips); i++) { + for (i = 0; i < nrchips; i++) { if (brdp->brdtype == BRD_ECHPCI) { outb((panelp->pagenr + (i >> 1)), brdp->ioctrl); ioaddr = panelp->iobase; - } else { + } else ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1)); - } uartaddr = (i & 0x01) ? 0x080 : 0; outb((GFRCR + uartaddr), ioaddr); outb(0, (ioaddr + EREG_DATA)); @@ -3136,10 +2783,10 @@ static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp) outb(CCR_RESETFULL, (ioaddr + EREG_DATA)); outb(CCR_RESETFULL, (ioaddr + EREG_DATA)); outb((GFRCR + uartaddr), ioaddr); - for (j = 0; (j < CCR_MAXWAIT); j++) { + for (j = 0; j < CCR_MAXWAIT; j++) if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0) break; - } + if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) { printk("STALLION: cd1400 not responding, " "brd=%d panel=%d chip=%d\n", @@ -3162,16 +2809,14 @@ static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp) * Initialize hardware specific port registers. */ -static void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp) +static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp) { unsigned long flags; -#ifdef DEBUG - printk("stl_cd1400portinit(brdp=%x,panelp=%x,portp=%x)\n", - (int) brdp, (int) panelp, (int) portp); -#endif + pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp, + panelp, portp); - if ((brdp == (stlbrd_t *) NULL) || (panelp == (stlpanel_t *) NULL) || - (portp == (stlport_t *) NULL)) + if ((brdp == NULL) || (panelp == NULL) || + (portp == NULL)) return; spin_lock_irqsave(&brd_lock, flags); @@ -3195,15 +2840,13 @@ static void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *po * since it won't usually take too long to be ready. */ -static void stl_cd1400ccrwait(stlport_t *portp) +static void stl_cd1400ccrwait(struct stlport *portp) { int i; - for (i = 0; (i < CCR_MAXWAIT); i++) { - if (stl_cd1400getreg(portp, CCR) == 0) { + for (i = 0; i < CCR_MAXWAIT; i++) + if (stl_cd1400getreg(portp, CCR) == 0) return; - } - } printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n", portp->portnr, portp->panelnr, portp->brdnr); @@ -3216,9 +2859,9 @@ static void stl_cd1400ccrwait(stlport_t *portp) * settings. */ -static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp) +static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp) { - stlbrd_t *brdp; + struct stlbrd *brdp; unsigned long flags; unsigned int clkdiv, baudrate; unsigned char cor1, cor2, cor3; @@ -3242,7 +2885,7 @@ static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp) sreroff = 0; brdp = stl_brds[portp->brdnr]; - if (brdp == (stlbrd_t *) NULL) + if (brdp == NULL) return; /* @@ -3339,8 +2982,8 @@ static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp) baudrate = STL_CD1400MAXBAUD; if (baudrate > 0) { - for (clk = 0; (clk < CD1400_NUMCLKS); clk++) { - clkdiv = ((portp->clk / stl_cd1400clkdivs[clk]) / baudrate); + for (clk = 0; clk < CD1400_NUMCLKS; clk++) { + clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate; if (clkdiv < 0x100) break; } @@ -3355,9 +2998,8 @@ static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp) mcor2 |= MCOR2_DCD; sreron |= SRER_MODEM; portp->flags |= ASYNC_CHECK_CD; - } else { + } else portp->flags &= ~ASYNC_CHECK_CD; - } /* * Setup cd1400 enhanced modes if we can. In particular we want to @@ -3382,18 +3024,16 @@ static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp) * them all up. */ -#ifdef DEBUG - printk("SETPORT: portnr=%d panelnr=%d brdnr=%d\n", + pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n", portp->portnr, portp->panelnr, portp->brdnr); - printk(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n", + pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n", cor1, cor2, cor3, cor4, cor5); - printk(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n", + pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n", mcor1, mcor2, rtpr, sreron, sreroff); - printk(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div); - printk(" schr1=%x schr2=%x schr3=%x schr4=%x\n", + pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div); + pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n", tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP], tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]); -#endif spin_lock_irqsave(&brd_lock, flags); BRDENABLE(portp->brdnr, portp->pagenr); @@ -3441,15 +3081,13 @@ static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp) * Set the state of the DTR and RTS signals. */ -static void stl_cd1400setsignals(stlport_t *portp, int dtr, int rts) +static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts) { unsigned char msvr1, msvr2; unsigned long flags; -#ifdef DEBUG - printk("stl_cd1400setsignals(portp=%x,dtr=%d,rts=%d)\n", - (int) portp, dtr, rts); -#endif + pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n", + portp, dtr, rts); msvr1 = 0; msvr2 = 0; @@ -3475,15 +3113,13 @@ static void stl_cd1400setsignals(stlport_t *portp, int dtr, int rts) * Return the state of the signals. */ -static int stl_cd1400getsignals(stlport_t *portp) +static int stl_cd1400getsignals(struct stlport *portp) { unsigned char msvr1, msvr2; unsigned long flags; int sigs; -#ifdef DEBUG - printk("stl_cd1400getsignals(portp=%x)\n", (int) portp); -#endif + pr_debug("stl_cd1400getsignals(portp=%p)\n", portp); spin_lock_irqsave(&brd_lock, flags); BRDENABLE(portp->brdnr, portp->pagenr); @@ -3513,15 +3149,13 @@ static int stl_cd1400getsignals(stlport_t *portp) * Enable/Disable the Transmitter and/or Receiver. */ -static void stl_cd1400enablerxtx(stlport_t *portp, int rx, int tx) +static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx) { unsigned char ccr; unsigned long flags; -#ifdef DEBUG - printk("stl_cd1400enablerxtx(portp=%x,rx=%d,tx=%d)\n", - (int) portp, rx, tx); -#endif + pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx); + ccr = 0; if (tx == 0) @@ -3549,15 +3183,12 @@ static void stl_cd1400enablerxtx(stlport_t *portp, int rx, int tx) * Start/stop the Transmitter and/or Receiver. */ -static void stl_cd1400startrxtx(stlport_t *portp, int rx, int tx) +static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx) { unsigned char sreron, sreroff; unsigned long flags; -#ifdef DEBUG - printk("stl_cd1400startrxtx(portp=%x,rx=%d,tx=%d)\n", - (int) portp, rx, tx); -#endif + pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx); sreron = 0; sreroff = 0; @@ -3589,13 +3220,12 @@ static void stl_cd1400startrxtx(stlport_t *portp, int rx, int tx) * Disable all interrupts from this port. */ -static void stl_cd1400disableintrs(stlport_t *portp) +static void stl_cd1400disableintrs(struct stlport *portp) { unsigned long flags; -#ifdef DEBUG - printk("stl_cd1400disableintrs(portp=%x)\n", (int) portp); -#endif + pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp); + spin_lock_irqsave(&brd_lock, flags); BRDENABLE(portp->brdnr, portp->pagenr); stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); @@ -3606,13 +3236,11 @@ static void stl_cd1400disableintrs(stlport_t *portp) /*****************************************************************************/ -static void stl_cd1400sendbreak(stlport_t *portp, int len) +static void stl_cd1400sendbreak(struct stlport *portp, int len) { unsigned long flags; -#ifdef DEBUG - printk("stl_cd1400sendbreak(portp=%x,len=%d)\n", (int) portp, len); -#endif + pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len); spin_lock_irqsave(&brd_lock, flags); BRDENABLE(portp->brdnr, portp->pagenr); @@ -3633,19 +3261,17 @@ static void stl_cd1400sendbreak(stlport_t *portp, int len) * Take flow control actions... */ -static void stl_cd1400flowctrl(stlport_t *portp, int state) +static void stl_cd1400flowctrl(struct stlport *portp, int state) { struct tty_struct *tty; unsigned long flags; -#ifdef DEBUG - printk("stl_cd1400flowctrl(portp=%x,state=%x)\n", (int) portp, state); -#endif + pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state); - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; tty = portp->tty; - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; spin_lock_irqsave(&brd_lock, flags); @@ -3697,19 +3323,17 @@ static void stl_cd1400flowctrl(stlport_t *portp, int state) * Send a flow control character... */ -static void stl_cd1400sendflow(stlport_t *portp, int state) +static void stl_cd1400sendflow(struct stlport *portp, int state) { struct tty_struct *tty; unsigned long flags; -#ifdef DEBUG - printk("stl_cd1400sendflow(portp=%x,state=%x)\n", (int) portp, state); -#endif + pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state); - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; tty = portp->tty; - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; spin_lock_irqsave(&brd_lock, flags); @@ -3732,15 +3356,13 @@ static void stl_cd1400sendflow(stlport_t *portp, int state) /*****************************************************************************/ -static void stl_cd1400flush(stlport_t *portp) +static void stl_cd1400flush(struct stlport *portp) { unsigned long flags; -#ifdef DEBUG - printk("stl_cd1400flush(portp=%x)\n", (int) portp); -#endif + pr_debug("stl_cd1400flush(portp=%p)\n", portp); - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; spin_lock_irqsave(&brd_lock, flags); @@ -3763,13 +3385,11 @@ static void stl_cd1400flush(stlport_t *portp) * maintains the busy port flag. */ -static int stl_cd1400datastate(stlport_t *portp) +static int stl_cd1400datastate(struct stlport *portp) { -#ifdef DEBUG - printk("stl_cd1400datastate(portp=%x)\n", (int) portp); -#endif + pr_debug("stl_cd1400datastate(portp=%p)\n", portp); - if (portp == (stlport_t *) NULL) + if (portp == NULL) return 0; return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0; @@ -3781,14 +3401,11 @@ static int stl_cd1400datastate(stlport_t *portp) * Interrupt service routine for cd1400 EasyIO boards. */ -static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase) +static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase) { unsigned char svrtype; -#ifdef DEBUG - printk("stl_cd1400eiointr(panelp=%x,iobase=%x)\n", - (int) panelp, iobase); -#endif + pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase); spin_lock(&brd_lock); outb(SVRR, iobase); @@ -3814,14 +3431,11 @@ static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase) * Interrupt service routine for cd1400 panels. */ -static void stl_cd1400echintr(stlpanel_t *panelp, unsigned int iobase) +static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase) { unsigned char svrtype; -#ifdef DEBUG - printk("stl_cd1400echintr(panelp=%x,iobase=%x)\n", (int) panelp, - iobase); -#endif + pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase); outb(SVRR, iobase); svrtype = inb(iobase + EREG_DATA); @@ -3843,7 +3457,7 @@ static void stl_cd1400echintr(stlpanel_t *panelp, unsigned int iobase) * this is the only way to generate them on the cd1400. */ -static inline int stl_cd1400breakisr(stlport_t *portp, int ioaddr) +static int stl_cd1400breakisr(struct stlport *portp, int ioaddr) { if (portp->brklen == 1) { outb((COR2 + portp->uartaddr), ioaddr); @@ -3885,16 +3499,14 @@ static inline int stl_cd1400breakisr(stlport_t *portp, int ioaddr) * be NULL if the buffer has been freed. */ -static void stl_cd1400txisr(stlpanel_t *panelp, int ioaddr) +static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr) { - stlport_t *portp; + struct stlport *portp; int len, stlen; char *head, *tail; unsigned char ioack, srer; -#ifdef DEBUG - printk("stl_cd1400txisr(panelp=%x,ioaddr=%x)\n", (int) panelp, ioaddr); -#endif + pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr); ioack = inb(ioaddr + EREG_TXACK); if (((ioack & panelp->ackmask) != 0) || @@ -3933,9 +3545,9 @@ static void stl_cd1400txisr(stlpanel_t *panelp, int ioaddr) } outb(srer, (ioaddr + EREG_DATA)); } else { - len = MIN(len, CD1400_TXFIFOSIZE); + len = min(len, CD1400_TXFIFOSIZE); portp->stats.txtotal += len; - stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail)); + stlen = min(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail)); outb((TDR + portp->uartaddr), ioaddr); outsb((ioaddr + EREG_DATA), tail, stlen); len -= stlen; @@ -3966,17 +3578,15 @@ stl_txalldone: * shutdown a port not in user context. Need to handle this case. */ -static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr) +static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr) { - stlport_t *portp; + struct stlport *portp; struct tty_struct *tty; unsigned int ioack, len, buflen; unsigned char status; char ch; -#ifdef DEBUG - printk("stl_cd1400rxisr(panelp=%x,ioaddr=%x)\n", (int) panelp, ioaddr); -#endif + pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr); ioack = inb(ioaddr + EREG_RXACK); if ((ioack & panelp->ackmask) != 0) { @@ -3990,13 +3600,13 @@ static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr) outb((RDCR + portp->uartaddr), ioaddr); len = inb(ioaddr + EREG_DATA); if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) { - len = MIN(len, sizeof(stl_unwanted)); + len = min(len, sizeof(stl_unwanted)); outb((RDSR + portp->uartaddr), ioaddr); insb((ioaddr + EREG_DATA), &stl_unwanted[0], len); portp->stats.rxlost += len; portp->stats.rxtotal += len; } else { - len = MIN(len, buflen); + len = min(len, buflen); if (len > 0) { unsigned char *ptr; outb((RDSR + portp->uartaddr), ioaddr); @@ -4033,18 +3643,16 @@ static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr) do_SAK(tty); BRDENABLE(portp->brdnr, portp->pagenr); } - } else if (status & ST_PARITY) { + } else if (status & ST_PARITY) status = TTY_PARITY; - } else if (status & ST_FRAMING) { + else if (status & ST_FRAMING) status = TTY_FRAME; - } else if(status & ST_OVERRUN) { + else if(status & ST_OVERRUN) status = TTY_OVERRUN; - } else { + else status = 0; - } - } else { + } else status = 0; - } tty_insert_flip_char(tty, ch, status); tty_schedule_flip(tty); } @@ -4066,15 +3674,13 @@ stl_rxalldone: * processing routine. */ -static void stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr) +static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr) { - stlport_t *portp; + struct stlport *portp; unsigned int ioack; unsigned char misr; -#ifdef DEBUG - printk("stl_cd1400mdmisr(panelp=%x)\n", (int) panelp); -#endif + pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp); ioack = inb(ioaddr + EREG_MDACK); if (((ioack & panelp->ackmask) != 0) || @@ -4106,19 +3712,19 @@ static void stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr) * (Maybe should make this inline...) */ -static int stl_sc26198getreg(stlport_t *portp, int regnr) +static int stl_sc26198getreg(struct stlport *portp, int regnr) { outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR)); return inb(portp->ioaddr + XP_DATA); } -static void stl_sc26198setreg(stlport_t *portp, int regnr, int value) +static void stl_sc26198setreg(struct stlport *portp, int regnr, int value) { outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR)); outb(value, (portp->ioaddr + XP_DATA)); } -static int stl_sc26198updatereg(stlport_t *portp, int regnr, int value) +static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value) { outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR)); if (inb(portp->ioaddr + XP_DATA) != value) { @@ -4134,14 +3740,14 @@ static int stl_sc26198updatereg(stlport_t *portp, int regnr, int value) * Functions to get and set the sc26198 global registers. */ -static int stl_sc26198getglobreg(stlport_t *portp, int regnr) +static int stl_sc26198getglobreg(struct stlport *portp, int regnr) { outb(regnr, (portp->ioaddr + XP_ADDR)); return inb(portp->ioaddr + XP_DATA); } #if 0 -static void stl_sc26198setglobreg(stlport_t *portp, int regnr, int value) +static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value) { outb(regnr, (portp->ioaddr + XP_ADDR)); outb(value, (portp->ioaddr + XP_DATA)); @@ -4156,15 +3762,12 @@ static void stl_sc26198setglobreg(stlport_t *portp, int regnr, int value) * identical when dealing with ports. */ -static int stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp) +static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp) { int chipmask, i; int nrchips, ioaddr; -#ifdef DEBUG - printk("stl_sc26198panelinit(brdp=%x,panelp=%x)\n", - (int) brdp, (int) panelp); -#endif + pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp); BRDENABLE(panelp->brdnr, panelp->pagenr); @@ -4176,7 +3779,7 @@ static int stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp) if (brdp->brdtype == BRD_ECHPCI) outb(panelp->pagenr, brdp->ioctrl); - for (i = 0; (i < nrchips); i++) { + for (i = 0; i < nrchips; i++) { ioaddr = panelp->iobase + (i * 4); outb(SCCR, (ioaddr + XP_ADDR)); outb(CR_RESETALL, (ioaddr + XP_DATA)); @@ -4204,15 +3807,13 @@ static int stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp) * Initialize hardware specific port registers. */ -static void stl_sc26198portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp) +static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp) { -#ifdef DEBUG - printk("stl_sc26198portinit(brdp=%x,panelp=%x,portp=%x)\n", - (int) brdp, (int) panelp, (int) portp); -#endif + pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp, + panelp, portp); - if ((brdp == (stlbrd_t *) NULL) || (panelp == (stlpanel_t *) NULL) || - (portp == (stlport_t *) NULL)) + if ((brdp == NULL) || (panelp == NULL) || + (portp == NULL)) return; portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4); @@ -4232,9 +3833,9 @@ static void stl_sc26198portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *p * settings. */ -static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp) +static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp) { - stlbrd_t *brdp; + struct stlbrd *brdp; unsigned long flags; unsigned int baudrate; unsigned char mr0, mr1, mr2, clk; @@ -4249,7 +3850,7 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp) imroff = 0; brdp = stl_brds[portp->brdnr]; - if (brdp == (stlbrd_t *) NULL) + if (brdp == NULL) return; /* @@ -4298,9 +3899,8 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp) mr1 |= (MR1_PARENB | MR1_PARODD); else mr1 |= (MR1_PARENB | MR1_PAREVEN); - } else { + } else mr1 |= MR1_PARNONE; - } mr1 |= MR1_ERRBLOCK; @@ -4340,12 +3940,10 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp) if (baudrate > STL_SC26198MAXBAUD) baudrate = STL_SC26198MAXBAUD; - if (baudrate > 0) { - for (clk = 0; (clk < SC26198_NRBAUDS); clk++) { + if (baudrate > 0) + for (clk = 0; clk < SC26198_NRBAUDS; clk++) if (baudrate <= sc26198_baudtable[clk]) break; - } - } /* * Check what form of modem signaling is required and set it up. @@ -4367,9 +3965,9 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp) if (tiosp->c_iflag & IXON) { mr0 |= MR0_SWFTX | MR0_SWFT; imron |= IR_XONXOFF; - } else { + } else imroff |= IR_XONXOFF; - } + if (tiosp->c_iflag & IXOFF) mr0 |= MR0_SWFRX; @@ -4383,15 +3981,13 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp) * them all up. */ -#ifdef DEBUG - printk("SETPORT: portnr=%d panelnr=%d brdnr=%d\n", + pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n", portp->portnr, portp->panelnr, portp->brdnr); - printk(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk); - printk(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff); - printk(" schr1=%x schr2=%x schr3=%x schr4=%x\n", + pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk); + pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff); + pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n", tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP], tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]); -#endif spin_lock_irqsave(&brd_lock, flags); BRDENABLE(portp->brdnr, portp->pagenr); @@ -4429,15 +4025,13 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp) * Set the state of the DTR and RTS signals. */ -static void stl_sc26198setsignals(stlport_t *portp, int dtr, int rts) +static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts) { unsigned char iopioron, iopioroff; unsigned long flags; -#ifdef DEBUG - printk("stl_sc26198setsignals(portp=%x,dtr=%d,rts=%d)\n", - (int) portp, dtr, rts); -#endif + pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp, + dtr, rts); iopioron = 0; iopioroff = 0; @@ -4464,15 +4058,13 @@ static void stl_sc26198setsignals(stlport_t *portp, int dtr, int rts) * Return the state of the signals. */ -static int stl_sc26198getsignals(stlport_t *portp) +static int stl_sc26198getsignals(struct stlport *portp) { unsigned char ipr; unsigned long flags; int sigs; -#ifdef DEBUG - printk("stl_sc26198getsignals(portp=%x)\n", (int) portp); -#endif + pr_debug("stl_sc26198getsignals(portp=%p)\n", portp); spin_lock_irqsave(&brd_lock, flags); BRDENABLE(portp->brdnr, portp->pagenr); @@ -4495,15 +4087,12 @@ static int stl_sc26198getsignals(stlport_t *portp) * Enable/Disable the Transmitter and/or Receiver. */ -static void stl_sc26198enablerxtx(stlport_t *portp, int rx, int tx) +static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx) { unsigned char ccr; unsigned long flags; -#ifdef DEBUG - printk("stl_sc26198enablerxtx(portp=%x,rx=%d,tx=%d)\n", - (int) portp, rx, tx); -#endif + pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx); ccr = portp->crenable; if (tx == 0) @@ -4529,15 +4118,12 @@ static void stl_sc26198enablerxtx(stlport_t *portp, int rx, int tx) * Start/stop the Transmitter and/or Receiver. */ -static void stl_sc26198startrxtx(stlport_t *portp, int rx, int tx) +static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx) { unsigned char imr; unsigned long flags; -#ifdef DEBUG - printk("stl_sc26198startrxtx(portp=%x,rx=%d,tx=%d)\n", - (int) portp, rx, tx); -#endif + pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx); imr = portp->imr; if (tx == 0) @@ -4565,13 +4151,11 @@ static void stl_sc26198startrxtx(stlport_t *portp, int rx, int tx) * Disable all interrupts from this port. */ -static void stl_sc26198disableintrs(stlport_t *portp) +static void stl_sc26198disableintrs(struct stlport *portp) { unsigned long flags; -#ifdef DEBUG - printk("stl_sc26198disableintrs(portp=%x)\n", (int) portp); -#endif + pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp); spin_lock_irqsave(&brd_lock, flags); BRDENABLE(portp->brdnr, portp->pagenr); @@ -4583,22 +4167,20 @@ static void stl_sc26198disableintrs(stlport_t *portp) /*****************************************************************************/ -static void stl_sc26198sendbreak(stlport_t *portp, int len) +static void stl_sc26198sendbreak(struct stlport *portp, int len) { unsigned long flags; -#ifdef DEBUG - printk("stl_sc26198sendbreak(portp=%x,len=%d)\n", (int) portp, len); -#endif + pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len); spin_lock_irqsave(&brd_lock, flags); BRDENABLE(portp->brdnr, portp->pagenr); if (len == 1) { stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK); portp->stats.txbreaks++; - } else { + } else stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK); - } + BRDDISABLE(portp->brdnr); spin_unlock_irqrestore(&brd_lock, flags); } @@ -4609,20 +4191,18 @@ static void stl_sc26198sendbreak(stlport_t *portp, int len) * Take flow control actions... */ -static void stl_sc26198flowctrl(stlport_t *portp, int state) +static void stl_sc26198flowctrl(struct stlport *portp, int state) { struct tty_struct *tty; unsigned long flags; unsigned char mr0; -#ifdef DEBUG - printk("stl_sc26198flowctrl(portp=%x,state=%x)\n", (int) portp, state); -#endif + pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state); - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; tty = portp->tty; - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; spin_lock_irqsave(&brd_lock, flags); @@ -4680,20 +4260,18 @@ static void stl_sc26198flowctrl(stlport_t *portp, int state) * Send a flow control character. */ -static void stl_sc26198sendflow(stlport_t *portp, int state) +static void stl_sc26198sendflow(struct stlport *portp, int state) { struct tty_struct *tty; unsigned long flags; unsigned char mr0; -#ifdef DEBUG - printk("stl_sc26198sendflow(portp=%x,state=%x)\n", (int) portp, state); -#endif + pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state); - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; tty = portp->tty; - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; spin_lock_irqsave(&brd_lock, flags); @@ -4721,15 +4299,13 @@ static void stl_sc26198sendflow(stlport_t *portp, int state) /*****************************************************************************/ -static void stl_sc26198flush(stlport_t *portp) +static void stl_sc26198flush(struct stlport *portp) { unsigned long flags; -#ifdef DEBUG - printk("stl_sc26198flush(portp=%x)\n", (int) portp); -#endif + pr_debug("stl_sc26198flush(portp=%p)\n", portp); - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; spin_lock_irqsave(&brd_lock, flags); @@ -4751,16 +4327,14 @@ static void stl_sc26198flush(stlport_t *portp) * check the port statusy register to be sure. */ -static int stl_sc26198datastate(stlport_t *portp) +static int stl_sc26198datastate(struct stlport *portp) { unsigned long flags; unsigned char sr; -#ifdef DEBUG - printk("stl_sc26198datastate(portp=%x)\n", (int) portp); -#endif + pr_debug("stl_sc26198datastate(portp=%p)\n", portp); - if (portp == (stlport_t *) NULL) + if (portp == NULL) return 0; if (test_bit(ASYI_TXBUSY, &portp->istate)) return 1; @@ -4781,18 +4355,16 @@ static int stl_sc26198datastate(stlport_t *portp) * to process a command... */ -static void stl_sc26198wait(stlport_t *portp) +static void stl_sc26198wait(struct stlport *portp) { int i; -#ifdef DEBUG - printk("stl_sc26198wait(portp=%x)\n", (int) portp); -#endif + pr_debug("stl_sc26198wait(portp=%p)\n", portp); - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; - for (i = 0; (i < 20); i++) + for (i = 0; i < 20; i++) stl_sc26198getglobreg(portp, TSTR); } @@ -4804,7 +4376,7 @@ static void stl_sc26198wait(stlport_t *portp) * automatic flow control modes of the sc26198. */ -static inline void stl_sc26198txunflow(stlport_t *portp, struct tty_struct *tty) +static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty) { unsigned char mr0; @@ -4822,9 +4394,9 @@ static inline void stl_sc26198txunflow(stlport_t *portp, struct tty_struct *tty) * Interrupt service routine for sc26198 panels. */ -static void stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase) +static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase) { - stlport_t *portp; + struct stlport *portp; unsigned int iack; spin_lock(&brd_lock); @@ -4860,16 +4432,14 @@ static void stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase) * be NULL if the buffer has been freed. */ -static void stl_sc26198txisr(stlport_t *portp) +static void stl_sc26198txisr(struct stlport *portp) { unsigned int ioaddr; unsigned char mr0; int len, stlen; char *head, *tail; -#ifdef DEBUG - printk("stl_sc26198txisr(portp=%x)\n", (int) portp); -#endif + pr_debug("stl_sc26198txisr(portp=%p)\n", portp); ioaddr = portp->ioaddr; head = portp->tx.head; @@ -4894,9 +4464,9 @@ static void stl_sc26198txisr(stlport_t *portp) outb(mr0, (ioaddr + XP_DATA)); } } else { - len = MIN(len, SC26198_TXFIFOSIZE); + len = min(len, SC26198_TXFIFOSIZE); portp->stats.txtotal += len; - stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail)); + stlen = min(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail)); outb(GTXFIFO, (ioaddr + XP_ADDR)); outsb((ioaddr + XP_DATA), tail, stlen); len -= stlen; @@ -4923,14 +4493,12 @@ static void stl_sc26198txisr(stlport_t *portp) * shutdown a port not in user context. Need to handle this case. */ -static void stl_sc26198rxisr(stlport_t *portp, unsigned int iack) +static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack) { struct tty_struct *tty; unsigned int len, buflen, ioaddr; -#ifdef DEBUG - printk("stl_sc26198rxisr(portp=%x,iack=%x)\n", (int) portp, iack); -#endif + pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack); tty = portp->tty; ioaddr = portp->ioaddr; @@ -4939,13 +4507,13 @@ static void stl_sc26198rxisr(stlport_t *portp, unsigned int iack) if ((iack & IVR_TYPEMASK) == IVR_RXDATA) { if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) { - len = MIN(len, sizeof(stl_unwanted)); + len = min(len, sizeof(stl_unwanted)); outb(GRXFIFO, (ioaddr + XP_ADDR)); insb((ioaddr + XP_DATA), &stl_unwanted[0], len); portp->stats.rxlost += len; portp->stats.rxtotal += len; } else { - len = MIN(len, buflen); + len = min(len, buflen); if (len > 0) { unsigned char *ptr; outb(GRXFIFO, (ioaddr + XP_ADDR)); @@ -4965,8 +4533,8 @@ static void stl_sc26198rxisr(stlport_t *portp, unsigned int iack) * flow control modes of the sc26198. */ if (test_bit(ASYI_TXFLOWED, &portp->istate)) { - if ((tty != (struct tty_struct *) NULL) && - (tty->termios != (struct termios *) NULL) && + if ((tty != NULL) && + (tty->termios != NULL) && (tty->termios->c_iflag & IXANY)) { stl_sc26198txunflow(portp, tty); } @@ -4979,7 +4547,7 @@ static void stl_sc26198rxisr(stlport_t *portp, unsigned int iack) * Process an RX bad character. */ -static inline void stl_sc26198rxbadch(stlport_t *portp, unsigned char status, char ch) +static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch) { struct tty_struct *tty; unsigned int ioaddr; @@ -4996,7 +4564,7 @@ static inline void stl_sc26198rxbadch(stlport_t *portp, unsigned char status, ch if (status & SR_RXBREAK) portp->stats.rxbreaks++; - if ((tty != (struct tty_struct *) NULL) && + if ((tty != NULL) && ((portp->rxignoremsk & status) == 0)) { if (portp->rxmarkmsk & status) { if (status & SR_RXBREAK) { @@ -5005,18 +4573,16 @@ static inline void stl_sc26198rxbadch(stlport_t *portp, unsigned char status, ch do_SAK(tty); BRDENABLE(portp->brdnr, portp->pagenr); } - } else if (status & SR_RXPARITY) { + } else if (status & SR_RXPARITY) status = TTY_PARITY; - } else if (status & SR_RXFRAMING) { + else if (status & SR_RXFRAMING) status = TTY_FRAME; - } else if(status & SR_RXOVERRUN) { + else if(status & SR_RXOVERRUN) status = TTY_OVERRUN; - } else { + else status = 0; - } - } else { + } else status = 0; - } tty_insert_flip_char(tty, ch, status); tty_schedule_flip(tty); @@ -5037,7 +4603,7 @@ static inline void stl_sc26198rxbadch(stlport_t *portp, unsigned char status, ch * the FIFO). */ -static void stl_sc26198rxbadchars(stlport_t *portp) +static void stl_sc26198rxbadchars(struct stlport *portp) { unsigned char status, mr1; char ch; @@ -5070,13 +4636,11 @@ static void stl_sc26198rxbadchars(stlport_t *portp) * processing time. */ -static void stl_sc26198otherisr(stlport_t *portp, unsigned int iack) +static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack) { unsigned char cir, ipr, xisr; -#ifdef DEBUG - printk("stl_sc26198otherisr(portp=%x,iack=%x)\n", (int) portp, iack); -#endif + pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack); cir = stl_sc26198getglobreg(portp, CIR); @@ -5109,4 +4673,172 @@ static void stl_sc26198otherisr(stlport_t *portp, unsigned int iack) } } -/*****************************************************************************/ +static void stl_free_isabrds(void) +{ + struct stlbrd *brdp; + unsigned int i; + + for (i = 0; i < stl_nrbrds; i++) { + if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED)) + continue; + + free_irq(brdp->irq, brdp); + + stl_cleanup_panels(brdp); + + release_region(brdp->ioaddr1, brdp->iosize1); + if (brdp->iosize2 > 0) + release_region(brdp->ioaddr2, brdp->iosize2); + + kfree(brdp); + stl_brds[i] = NULL; + } +} + +/* + * Loadable module initialization stuff. + */ +static int __init stallion_module_init(void) +{ + struct stlbrd *brdp; + struct stlconf conf; + unsigned int i, j; + int retval; + + printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion); + + spin_lock_init(&stallion_lock); + spin_lock_init(&brd_lock); + +/* + * Find any dynamically supported boards. That is via module load + * line options. + */ + for (i = stl_nrbrds; i < stl_nargs; i++) { + memset(&conf, 0, sizeof(conf)); + if (stl_parsebrd(&conf, stl_brdsp[i]) == 0) + continue; + if ((brdp = stl_allocbrd()) == NULL) + continue; + brdp->brdnr = i; + brdp->brdtype = conf.brdtype; + brdp->ioaddr1 = conf.ioaddr1; + brdp->ioaddr2 = conf.ioaddr2; + brdp->irq = conf.irq; + brdp->irqtype = conf.irqtype; + if (stl_brdinit(brdp)) + kfree(brdp); + else { + for (j = 0; j < brdp->nrports; j++) + tty_register_device(stl_serial, + brdp->brdnr * STL_MAXPORTS + j, NULL); + stl_brds[brdp->brdnr] = brdp; + stl_nrbrds = i + 1; + } + } + + /* this has to be _after_ isa finding because of locking */ + retval = pci_register_driver(&stl_pcidriver); + if (retval && stl_nrbrds == 0) + goto err; + + stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS); + if (!stl_serial) { + retval = -ENOMEM; + goto err_pcidr; + } + +/* + * Set up a character driver for per board stuff. This is mainly used + * to do stats ioctls on the ports. + */ + if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem)) + printk("STALLION: failed to register serial board device\n"); + + stallion_class = class_create(THIS_MODULE, "staliomem"); + if (IS_ERR(stallion_class)) { + retval = PTR_ERR(stallion_class); + goto err_reg; + } + for (i = 0; i < 4; i++) + class_device_create(stallion_class, NULL, + MKDEV(STL_SIOMEMMAJOR, i), NULL, + "staliomem%d", i); + + stl_serial->owner = THIS_MODULE; + stl_serial->driver_name = stl_drvname; + stl_serial->name = "ttyE"; + stl_serial->major = STL_SERIALMAJOR; + stl_serial->minor_start = 0; + stl_serial->type = TTY_DRIVER_TYPE_SERIAL; + stl_serial->subtype = SERIAL_TYPE_NORMAL; + stl_serial->init_termios = stl_deftermios; + stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; + tty_set_operations(stl_serial, &stl_ops); + + retval = tty_register_driver(stl_serial); + if (retval) { + printk("STALLION: failed to register serial driver\n"); + goto err_clsdev; + } + + return 0; +err_clsdev: + for (i = 0; i < 4; i++) + class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i)); + class_destroy(stallion_class); +err_reg: + unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"); + put_tty_driver(stl_serial); +err_pcidr: + pci_unregister_driver(&stl_pcidriver); + stl_free_isabrds(); +err: + return retval; +} + +static void __exit stallion_module_exit(void) +{ + struct stlbrd *brdp; + unsigned int i, j; + int retval; + + pr_debug("cleanup_module()\n"); + + printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle, + stl_drvversion); + +/* + * Free up all allocated resources used by the ports. This includes + * memory and interrupts. As part of this process we will also do + * a hangup on every open port - to try to flush out any processes + * hanging onto ports. + */ + for (i = 0; i < stl_nrbrds; i++) { + if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED)) + continue; + for (j = 0; j < brdp->nrports; j++) + tty_unregister_device(stl_serial, + brdp->brdnr * STL_MAXPORTS + j); + } + tty_unregister_driver(stl_serial); + put_tty_driver(stl_serial); + + for (i = 0; i < 4; i++) + class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i)); + if ((retval = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"))) + printk("STALLION: failed to un-register serial memory device, " + "errno=%d\n", -retval); + class_destroy(stallion_class); + + pci_unregister_driver(&stl_pcidriver); + + stl_free_isabrds(); +} + +module_init(stallion_module_init); +module_exit(stallion_module_exit); + +MODULE_AUTHOR("Greg Ungerer"); +MODULE_DESCRIPTION("Stallion Multiport Serial Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/sx.c b/drivers/char/sx.c index cc10af08cb0..a3008ce1301 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c @@ -32,7 +32,6 @@ * USA. * * Revision history: - * $Log: sx.c,v $ * Revision 1.33 2000/03/09 10:00:00 pvdl,wolff * - Fixed module and port counting * - Fixed signal handling @@ -199,9 +198,7 @@ * * */ - -#define RCS_ID "$Id: sx.c,v 1.33 2000/03/08 10:01:02 wolff, pvdl Exp $" -#define RCS_REV "$Revision: 1.33 $" +#define SX_VERSION 1.33 #include <linux/module.h> #include <linux/kdev_t.h> @@ -217,6 +214,7 @@ #include <linux/fcntl.h> #include <linux/major.h> #include <linux/delay.h> +#include <linux/eisa.h> #include <linux/pci.h> #include <linux/slab.h> #include <linux/init.h> @@ -240,7 +238,6 @@ #include <linux/generic_serial.h> #include "sx.h" - /* I don't think that this driver can handle more than 256 ports on one machine. You'll have to increase the number of boards in sx.h if you want more than 4 boards. */ @@ -249,21 +246,12 @@ #define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000 #endif -#ifdef CONFIG_PCI -static struct pci_device_id sx_pci_tbl[] = { - { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, PCI_ANY_ID, PCI_ANY_ID }, - { 0 } -}; -MODULE_DEVICE_TABLE(pci, sx_pci_tbl); -#endif /* CONFIG_PCI */ - /* Configurable options: (Don't be too sure that it'll work if you toggle them) */ /* Am I paranoid or not ? ;-) */ #undef SX_PARANOIA_CHECK - /* 20 -> 2000 per second. The card should rate-limit interrupts at 100 Hz, but it is user configurable. I don't recommend going above 1000 Hz. The interrupt ratelimit might trigger if the interrupt is @@ -277,7 +265,6 @@ MODULE_DEVICE_TABLE(pci, sx_pci_tbl); interrupt. Use polling. */ #undef IRQ_RATE_LIMIT - #if 0 /* Not implemented */ /* @@ -286,35 +273,33 @@ MODULE_DEVICE_TABLE(pci, sx_pci_tbl); */ #define SX_REPORT_FIFO #define SX_REPORT_OVERRUN -#endif - +#endif /* Function prototypes */ -static void sx_disable_tx_interrupts (void * ptr); -static void sx_enable_tx_interrupts (void * ptr); -static void sx_disable_rx_interrupts (void * ptr); -static void sx_enable_rx_interrupts (void * ptr); -static int sx_get_CD (void * ptr); -static void sx_shutdown_port (void * ptr); -static int sx_set_real_termios (void *ptr); -static void sx_close (void *ptr); -static int sx_chars_in_buffer (void * ptr); -static int sx_init_board (struct sx_board *board); -static int sx_init_portstructs (int nboards, int nports); -static int sx_fw_ioctl (struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +static void sx_disable_tx_interrupts(void *ptr); +static void sx_enable_tx_interrupts(void *ptr); +static void sx_disable_rx_interrupts(void *ptr); +static void sx_enable_rx_interrupts(void *ptr); +static int sx_get_CD(void *ptr); +static void sx_shutdown_port(void *ptr); +static int sx_set_real_termios(void *ptr); +static void sx_close(void *ptr); +static int sx_chars_in_buffer(void *ptr); +static int sx_init_board(struct sx_board *board); +static int sx_init_portstructs(int nboards, int nports); +static int sx_fw_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); static int sx_init_drivers(void); - static struct tty_driver *sx_driver; +static DEFINE_MUTEX(sx_boards_lock); static struct sx_board boards[SX_NBOARDS]; static struct sx_port *sx_ports; static int sx_initialized; static int sx_nports; static int sx_debug; - /* You can have the driver poll your card. - Set sx_poll to 1 to poll every timer tick (10ms on Intel). This is used when the card cannot use an interrupt for some reason. @@ -333,27 +318,36 @@ static int sx_slowpoll; static int sx_maxints = 100; +#ifdef CONFIG_ISA + /* These are the only open spaces in my computer. Yours may have more or less.... -- REW duh: Card at 0xa0000 is possible on HP Netserver?? -- pvdl */ -static int sx_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000, - 0xc8000, 0xd8000, 0xe8000}; -static int si_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000, - 0xc8000, 0xd8000, 0xe8000, 0xa0000}; -static int si1_probe_addrs[]= { 0xd0000}; +static int sx_probe_addrs[] = { + 0xc0000, 0xd0000, 0xe0000, + 0xc8000, 0xd8000, 0xe8000 +}; +static int si_probe_addrs[] = { + 0xc0000, 0xd0000, 0xe0000, + 0xc8000, 0xd8000, 0xe8000, 0xa0000 +}; +static int si1_probe_addrs[] = { + 0xd0000 +}; #define NR_SX_ADDRS ARRAY_SIZE(sx_probe_addrs) #define NR_SI_ADDRS ARRAY_SIZE(si_probe_addrs) #define NR_SI1_ADDRS ARRAY_SIZE(si1_probe_addrs) +module_param_array(sx_probe_addrs, int, NULL, 0); +module_param_array(si_probe_addrs, int, NULL, 0); +#endif /* Set the mask to all-ones. This alas, only supports 32 interrupts. Some architectures may need more. */ static int sx_irqmask = -1; -module_param_array(sx_probe_addrs, int, NULL, 0); -module_param_array(si_probe_addrs, int, NULL, 0); module_param(sx_poll, int, 0); module_param(sx_slowpoll, int, 0); module_param(sx_maxints, int, 0); @@ -368,13 +362,12 @@ static struct real_driver sx_real_driver = { sx_disable_rx_interrupts, sx_enable_rx_interrupts, sx_get_CD, - sx_shutdown_port, - sx_set_real_termios, + sx_shutdown_port, + sx_set_real_termios, sx_chars_in_buffer, sx_close, }; - /* This driver can spew a whole lot of debugging output at you. If you need maximum performance, you should disable the DEBUG define. To @@ -385,23 +378,17 @@ static struct real_driver sx_real_driver = { */ #define DEBUG - #ifdef DEBUG -#define sx_dprintk(f, str...) if (sx_debug & f) printk (str) +#define sx_dprintk(f, str...) if (sx_debug & f) printk (str) #else -#define sx_dprintk(f, str...) /* nothing */ +#define sx_dprintk(f, str...) /* nothing */ #endif +#define func_enter() sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s\n",__FUNCTION__) +#define func_exit() sx_dprintk(SX_DEBUG_FLOW, "sx: exit %s\n",__FUNCTION__) - -#define func_enter() sx_dprintk (SX_DEBUG_FLOW, "sx: enter %s\n",__FUNCTION__) -#define func_exit() sx_dprintk (SX_DEBUG_FLOW, "sx: exit %s\n", __FUNCTION__) - -#define func_enter2() sx_dprintk (SX_DEBUG_FLOW, "sx: enter %s (port %d)\n", \ - __FUNCTION__, port->line) - - - +#define func_enter2() sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s (port %d)\n", \ + __FUNCTION__, port->line) /* * Firmware loader driver specific routines @@ -409,31 +396,26 @@ static struct real_driver sx_real_driver = { */ static const struct file_operations sx_fw_fops = { - .owner = THIS_MODULE, - .ioctl = sx_fw_ioctl, + .owner = THIS_MODULE, + .ioctl = sx_fw_ioctl, }; static struct miscdevice sx_fw_device = { SXCTL_MISC_MINOR, "sxctl", &sx_fw_fops }; - - - - #ifdef SX_PARANOIA_CHECK /* This doesn't work. Who's paranoid around here? Not me! */ -static inline int sx_paranoia_check(struct sx_port const * port, +static inline int sx_paranoia_check(struct sx_port const *port, char *name, const char *routine) { + static const char *badmagic = KERN_ERR "sx: Warning: bad sx port magic " + "number for device %s in %s\n"; + static const char *badinfo = KERN_ERR "sx: Warning: null sx port for " + "device %s in %s\n"; - static const char *badmagic = - KERN_ERR "sx: Warning: bad sx port magic number for device %s in %s\n"; - static const char *badinfo = - KERN_ERR "sx: Warning: null sx port for device %s in %s\n"; - if (!port) { printk(badinfo, name, routine); return 1; @@ -456,23 +438,24 @@ static inline int sx_paranoia_check(struct sx_port const * port, #define TIMEOUT_1 30 #define TIMEOUT_2 1000000 - #ifdef DEBUG static void my_hd_io(void __iomem *p, int len) { int i, j, ch; unsigned char __iomem *addr = p; - for (i=0;i<len;i+=16) { - printk ("%p ", addr+i); - for (j=0;j<16;j++) { - printk ("%02x %s", readb(addr+j+i), (j==7)?" ":""); + for (i = 0; i < len; i += 16) { + printk("%p ", addr + i); + for (j = 0; j < 16; j++) { + printk("%02x %s", readb(addr + j + i), + (j == 7) ? " " : ""); } - for (j=0;j<16;j++) { - ch = readb(addr+j+i); - printk ("%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch)); + for (j = 0; j < 16; j++) { + ch = readb(addr + j + i); + printk("%c", (ch < 0x20) ? '.' : + ((ch > 0x7f) ? '.' : ch)); } - printk ("\n"); + printk("\n"); } } static void my_hd(void *p, int len) @@ -480,419 +463,468 @@ static void my_hd(void *p, int len) int i, j, ch; unsigned char *addr = p; - for (i=0;i<len;i+=16) { - printk ("%p ", addr+i); - for (j=0;j<16;j++) { - printk ("%02x %s", addr[j+i], (j==7)?" ":""); + for (i = 0; i < len; i += 16) { + printk("%p ", addr + i); + for (j = 0; j < 16; j++) { + printk("%02x %s", addr[j + i], (j == 7) ? " " : ""); } - for (j=0;j<16;j++) { - ch = addr[j+i]; - printk ("%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch)); + for (j = 0; j < 16; j++) { + ch = addr[j + i]; + printk("%c", (ch < 0x20) ? '.' : + ((ch > 0x7f) ? '.' : ch)); } - printk ("\n"); + printk("\n"); } } #endif - - /* This needs redoing for Alpha -- REW -- Done. */ -static inline void write_sx_byte (struct sx_board *board, int offset, u8 byte) +static inline void write_sx_byte(struct sx_board *board, int offset, u8 byte) { - writeb (byte, board->base+offset); + writeb(byte, board->base + offset); } -static inline u8 read_sx_byte (struct sx_board *board, int offset) +static inline u8 read_sx_byte(struct sx_board *board, int offset) { - return readb (board->base+offset); + return readb(board->base + offset); } - -static inline void write_sx_word (struct sx_board *board, int offset, u16 word) +static inline void write_sx_word(struct sx_board *board, int offset, u16 word) { - writew (word, board->base+offset); + writew(word, board->base + offset); } -static inline u16 read_sx_word (struct sx_board *board, int offset) +static inline u16 read_sx_word(struct sx_board *board, int offset) { - return readw (board->base + offset); + return readw(board->base + offset); } - -static int sx_busy_wait_eq (struct sx_board *board, - int offset, int mask, int correctval) +static int sx_busy_wait_eq(struct sx_board *board, + int offset, int mask, int correctval) { int i; - func_enter (); + func_enter(); - for (i=0; i < TIMEOUT_1 ;i++) - if ((read_sx_byte (board, offset) & mask) == correctval) { - func_exit (); + for (i = 0; i < TIMEOUT_1; i++) + if ((read_sx_byte(board, offset) & mask) == correctval) { + func_exit(); return 1; } - for (i=0; i < TIMEOUT_2 ;i++) { - if ((read_sx_byte (board, offset) & mask) == correctval) { - func_exit (); + for (i = 0; i < TIMEOUT_2; i++) { + if ((read_sx_byte(board, offset) & mask) == correctval) { + func_exit(); return 1; } - udelay (1); + udelay(1); } - func_exit (); + func_exit(); return 0; } - -static int sx_busy_wait_neq (struct sx_board *board, - int offset, int mask, int badval) +static int sx_busy_wait_neq(struct sx_board *board, + int offset, int mask, int badval) { int i; - func_enter (); + func_enter(); - for (i=0; i < TIMEOUT_1 ;i++) - if ((read_sx_byte (board, offset) & mask) != badval) { - func_exit (); + for (i = 0; i < TIMEOUT_1; i++) + if ((read_sx_byte(board, offset) & mask) != badval) { + func_exit(); return 1; } - for (i=0; i < TIMEOUT_2 ;i++) { - if ((read_sx_byte (board, offset) & mask) != badval) { - func_exit (); + for (i = 0; i < TIMEOUT_2; i++) { + if ((read_sx_byte(board, offset) & mask) != badval) { + func_exit(); return 1; } - udelay (1); + udelay(1); } - func_exit (); + func_exit(); return 0; } - - /* 5.6.4 of 6210028 r2.3 */ -static int sx_reset (struct sx_board *board) +static int sx_reset(struct sx_board *board) { - func_enter (); + func_enter(); - if (IS_SX_BOARD (board)) { + if (IS_SX_BOARD(board)) { - write_sx_byte (board, SX_CONFIG, 0); - write_sx_byte (board, SX_RESET, 1); /* Value doesn't matter */ + write_sx_byte(board, SX_CONFIG, 0); + write_sx_byte(board, SX_RESET, 1); /* Value doesn't matter */ - if (!sx_busy_wait_eq (board, SX_RESET_STATUS, 1, 0)) { - printk (KERN_INFO "sx: Card doesn't respond to reset....\n"); + if (!sx_busy_wait_eq(board, SX_RESET_STATUS, 1, 0)) { + printk(KERN_INFO "sx: Card doesn't respond to " + "reset...\n"); return 0; } } else if (IS_EISA_BOARD(board)) { - outb(board->irq<<4, board->eisa_base+0xc02); + outb(board->irq << 4, board->eisa_base + 0xc02); } else if (IS_SI1_BOARD(board)) { - write_sx_byte (board, SI1_ISA_RESET, 0); // value does not matter + write_sx_byte(board, SI1_ISA_RESET, 0); /*value doesn't matter*/ } else { /* Gory details of the SI/ISA board */ - write_sx_byte (board, SI2_ISA_RESET, SI2_ISA_RESET_SET); - write_sx_byte (board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_CLEAR); - write_sx_byte (board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_CLEAR); - write_sx_byte (board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_CLEAR); - write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR); - write_sx_byte (board, SI2_ISA_IRQSET, SI2_ISA_IRQSET_CLEAR); + write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_SET); + write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_CLEAR); + write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_CLEAR); + write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_CLEAR); + write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR); + write_sx_byte(board, SI2_ISA_IRQSET, SI2_ISA_IRQSET_CLEAR); } - func_exit (); + func_exit(); return 1; } - /* This doesn't work on machines where "NULL" isn't 0 */ /* If you have one of those, someone will need to write the equivalent of this, which will amount to about 3 lines. I don't want to complicate this right now. -- REW (See, I do write comments every now and then :-) */ -#define OFFSETOF(strct, elem) ((long)&(((struct strct *)NULL)->elem)) - - -#define CHAN_OFFSET(port,elem) (port->ch_base + OFFSETOF (_SXCHANNEL, elem)) -#define MODU_OFFSET(board,addr,elem) (addr + OFFSETOF (_SXMODULE, elem)) -#define BRD_OFFSET(board,elem) (OFFSETOF (_SXCARD, elem)) +#define OFFSETOF(strct, elem) ((long)&(((struct strct *)NULL)->elem)) +#define CHAN_OFFSET(port,elem) (port->ch_base + OFFSETOF (_SXCHANNEL, elem)) +#define MODU_OFFSET(board,addr,elem) (addr + OFFSETOF (_SXMODULE, elem)) +#define BRD_OFFSET(board,elem) (OFFSETOF (_SXCARD, elem)) #define sx_write_channel_byte(port, elem, val) \ - write_sx_byte (port->board, CHAN_OFFSET (port, elem), val) + write_sx_byte (port->board, CHAN_OFFSET (port, elem), val) #define sx_read_channel_byte(port, elem) \ - read_sx_byte (port->board, CHAN_OFFSET (port, elem)) + read_sx_byte (port->board, CHAN_OFFSET (port, elem)) #define sx_write_channel_word(port, elem, val) \ - write_sx_word (port->board, CHAN_OFFSET (port, elem), val) + write_sx_word (port->board, CHAN_OFFSET (port, elem), val) #define sx_read_channel_word(port, elem) \ - read_sx_word (port->board, CHAN_OFFSET (port, elem)) - + read_sx_word (port->board, CHAN_OFFSET (port, elem)) #define sx_write_module_byte(board, addr, elem, val) \ - write_sx_byte (board, MODU_OFFSET (board, addr, elem), val) + write_sx_byte (board, MODU_OFFSET (board, addr, elem), val) #define sx_read_module_byte(board, addr, elem) \ - read_sx_byte (board, MODU_OFFSET (board, addr, elem)) + read_sx_byte (board, MODU_OFFSET (board, addr, elem)) #define sx_write_module_word(board, addr, elem, val) \ - write_sx_word (board, MODU_OFFSET (board, addr, elem), val) + write_sx_word (board, MODU_OFFSET (board, addr, elem), val) #define sx_read_module_word(board, addr, elem) \ - read_sx_word (board, MODU_OFFSET (board, addr, elem)) - + read_sx_word (board, MODU_OFFSET (board, addr, elem)) #define sx_write_board_byte(board, elem, val) \ - write_sx_byte (board, BRD_OFFSET (board, elem), val) + write_sx_byte (board, BRD_OFFSET (board, elem), val) #define sx_read_board_byte(board, elem) \ - read_sx_byte (board, BRD_OFFSET (board, elem)) + read_sx_byte (board, BRD_OFFSET (board, elem)) #define sx_write_board_word(board, elem, val) \ - write_sx_word (board, BRD_OFFSET (board, elem), val) + write_sx_word (board, BRD_OFFSET (board, elem), val) #define sx_read_board_word(board, elem) \ - read_sx_word (board, BRD_OFFSET (board, elem)) - + read_sx_word (board, BRD_OFFSET (board, elem)) -static int sx_start_board (struct sx_board *board) +static int sx_start_board(struct sx_board *board) { - if (IS_SX_BOARD (board)) { - write_sx_byte (board, SX_CONFIG, SX_CONF_BUSEN); + if (IS_SX_BOARD(board)) { + write_sx_byte(board, SX_CONFIG, SX_CONF_BUSEN); } else if (IS_EISA_BOARD(board)) { write_sx_byte(board, SI2_EISA_OFF, SI2_EISA_VAL); - outb((board->irq<<4)|4, board->eisa_base+0xc02); + outb((board->irq << 4) | 4, board->eisa_base + 0xc02); } else if (IS_SI1_BOARD(board)) { - write_sx_byte (board, SI1_ISA_RESET_CLEAR, 0); - write_sx_byte (board, SI1_ISA_INTCL, 0); + write_sx_byte(board, SI1_ISA_RESET_CLEAR, 0); + write_sx_byte(board, SI1_ISA_INTCL, 0); } else { /* Don't bug me about the clear_set. I haven't the foggiest idea what it's about -- REW */ - write_sx_byte (board, SI2_ISA_RESET, SI2_ISA_RESET_CLEAR); - write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET); + write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_CLEAR); + write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET); } return 1; } #define SX_IRQ_REG_VAL(board) \ - ((board->flags & SX_ISA_BOARD)?(board->irq << 4):0) + ((board->flags & SX_ISA_BOARD) ? (board->irq << 4) : 0) /* Note. The SX register is write-only. Therefore, we have to enable the bus too. This is a no-op, if you don't mess with this driver... */ -static int sx_start_interrupts (struct sx_board *board) +static int sx_start_interrupts(struct sx_board *board) { /* Don't call this with board->irq == 0 */ if (IS_SX_BOARD(board)) { - write_sx_byte (board, SX_CONFIG, SX_IRQ_REG_VAL (board) | - SX_CONF_BUSEN | - SX_CONF_HOSTIRQ); + write_sx_byte(board, SX_CONFIG, SX_IRQ_REG_VAL(board) | + SX_CONF_BUSEN | SX_CONF_HOSTIRQ); } else if (IS_EISA_BOARD(board)) { - inb(board->eisa_base+0xc03); + inb(board->eisa_base + 0xc03); } else if (IS_SI1_BOARD(board)) { - write_sx_byte (board, SI1_ISA_INTCL,0); - write_sx_byte (board, SI1_ISA_INTCL_CLEAR,0); + write_sx_byte(board, SI1_ISA_INTCL, 0); + write_sx_byte(board, SI1_ISA_INTCL_CLEAR, 0); } else { switch (board->irq) { - case 11:write_sx_byte (board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_SET);break; - case 12:write_sx_byte (board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_SET);break; - case 15:write_sx_byte (board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_SET);break; - default:printk (KERN_INFO "sx: SI/XIO card doesn't support interrupt %d.\n", - board->irq); - return 0; + case 11: + write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_SET); + break; + case 12: + write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_SET); + break; + case 15: + write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_SET); + break; + default: + printk(KERN_INFO "sx: SI/XIO card doesn't support " + "interrupt %d.\n", board->irq); + return 0; } - write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET); + write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET); } return 1; } - -static int sx_send_command (struct sx_port *port, - int command, int mask, int newstat) +static int sx_send_command(struct sx_port *port, + int command, int mask, int newstat) { - func_enter2 (); - write_sx_byte (port->board, CHAN_OFFSET (port, hi_hstat), command); - func_exit (); - return sx_busy_wait_eq (port->board, CHAN_OFFSET (port, hi_hstat), mask, newstat); + func_enter2(); + write_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat), command); + func_exit(); + return sx_busy_wait_eq(port->board, CHAN_OFFSET(port, hi_hstat), mask, + newstat); } - -static char *mod_type_s (int module_type) +static char *mod_type_s(int module_type) { switch (module_type) { - case TA4: return "TA4"; - case TA8: return "TA8"; - case TA4_ASIC: return "TA4_ASIC"; - case TA8_ASIC: return "TA8_ASIC"; - case MTA_CD1400:return "MTA_CD1400"; - case SXDC: return "SXDC"; - default:return "Unknown/invalid"; + case TA4: + return "TA4"; + case TA8: + return "TA8"; + case TA4_ASIC: + return "TA4_ASIC"; + case TA8_ASIC: + return "TA8_ASIC"; + case MTA_CD1400: + return "MTA_CD1400"; + case SXDC: + return "SXDC"; + default: + return "Unknown/invalid"; } } - -static char *pan_type_s (int pan_type) +static char *pan_type_s(int pan_type) { switch (pan_type) { - case MOD_RS232DB25: return "MOD_RS232DB25"; - case MOD_RS232RJ45: return "MOD_RS232RJ45"; - case MOD_RS422DB25: return "MOD_RS422DB25"; - case MOD_PARALLEL: return "MOD_PARALLEL"; - case MOD_2_RS232DB25: return "MOD_2_RS232DB25"; - case MOD_2_RS232RJ45: return "MOD_2_RS232RJ45"; - case MOD_2_RS422DB25: return "MOD_2_RS422DB25"; - case MOD_RS232DB25MALE: return "MOD_RS232DB25MALE"; - case MOD_2_PARALLEL: return "MOD_2_PARALLEL"; - case MOD_BLANK: return "empty"; - default:return "invalid"; + case MOD_RS232DB25: + return "MOD_RS232DB25"; + case MOD_RS232RJ45: + return "MOD_RS232RJ45"; + case MOD_RS422DB25: + return "MOD_RS422DB25"; + case MOD_PARALLEL: + return "MOD_PARALLEL"; + case MOD_2_RS232DB25: + return "MOD_2_RS232DB25"; + case MOD_2_RS232RJ45: + return "MOD_2_RS232RJ45"; + case MOD_2_RS422DB25: + return "MOD_2_RS422DB25"; + case MOD_RS232DB25MALE: + return "MOD_RS232DB25MALE"; + case MOD_2_PARALLEL: + return "MOD_2_PARALLEL"; + case MOD_BLANK: + return "empty"; + default: + return "invalid"; } } - -static int mod_compat_type (int module_type) +static int mod_compat_type(int module_type) { return module_type >> 4; } static void sx_reconfigure_port(struct sx_port *port) { - if (sx_read_channel_byte (port, hi_hstat) == HS_IDLE_OPEN) { - if (sx_send_command (port, HS_CONFIG, -1, HS_IDLE_OPEN) != 1) { - printk (KERN_WARNING "sx: Sent reconfigure command, but card didn't react.\n"); + if (sx_read_channel_byte(port, hi_hstat) == HS_IDLE_OPEN) { + if (sx_send_command(port, HS_CONFIG, -1, HS_IDLE_OPEN) != 1) { + printk(KERN_WARNING "sx: Sent reconfigure command, but " + "card didn't react.\n"); } } else { - sx_dprintk (SX_DEBUG_TERMIOS, - "sx: Not sending reconfigure: port isn't open (%02x).\n", - sx_read_channel_byte (port, hi_hstat)); - } + sx_dprintk(SX_DEBUG_TERMIOS, "sx: Not sending reconfigure: " + "port isn't open (%02x).\n", + sx_read_channel_byte(port, hi_hstat)); + } } -static void sx_setsignals (struct sx_port *port, int dtr, int rts) +static void sx_setsignals(struct sx_port *port, int dtr, int rts) { int t; - func_enter2 (); + func_enter2(); - t = sx_read_channel_byte (port, hi_op); - if (dtr >= 0) t = dtr? (t | OP_DTR): (t & ~OP_DTR); - if (rts >= 0) t = rts? (t | OP_RTS): (t & ~OP_RTS); - sx_write_channel_byte (port, hi_op, t); - sx_dprintk (SX_DEBUG_MODEMSIGNALS, "setsignals: %d/%d\n", dtr, rts); + t = sx_read_channel_byte(port, hi_op); + if (dtr >= 0) + t = dtr ? (t | OP_DTR) : (t & ~OP_DTR); + if (rts >= 0) + t = rts ? (t | OP_RTS) : (t & ~OP_RTS); + sx_write_channel_byte(port, hi_op, t); + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "setsignals: %d/%d\n", dtr, rts); - func_exit (); + func_exit(); } - - -static int sx_getsignals (struct sx_port *port) +static int sx_getsignals(struct sx_port *port) { - int i_stat,o_stat; - - o_stat = sx_read_channel_byte (port, hi_op); - i_stat = sx_read_channel_byte (port, hi_ip); - - sx_dprintk (SX_DEBUG_MODEMSIGNALS, "getsignals: %d/%d (%d/%d) %02x/%02x\n", - (o_stat & OP_DTR) != 0, (o_stat & OP_RTS) != 0, - port->c_dcd, sx_get_CD (port), - sx_read_channel_byte (port, hi_ip), - sx_read_channel_byte (port, hi_state)); - - return (((o_stat & OP_DTR)?TIOCM_DTR:0) | - ((o_stat & OP_RTS)?TIOCM_RTS:0) | - ((i_stat & IP_CTS)?TIOCM_CTS:0) | - ((i_stat & IP_DCD)?TIOCM_CAR:0) | - ((i_stat & IP_DSR)?TIOCM_DSR:0) | - ((i_stat & IP_RI)?TIOCM_RNG:0) - ); + int i_stat, o_stat; + + o_stat = sx_read_channel_byte(port, hi_op); + i_stat = sx_read_channel_byte(port, hi_ip); + + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "getsignals: %d/%d (%d/%d) " + "%02x/%02x\n", + (o_stat & OP_DTR) != 0, (o_stat & OP_RTS) != 0, + port->c_dcd, sx_get_CD(port), + sx_read_channel_byte(port, hi_ip), + sx_read_channel_byte(port, hi_state)); + + return (((o_stat & OP_DTR) ? TIOCM_DTR : 0) | + ((o_stat & OP_RTS) ? TIOCM_RTS : 0) | + ((i_stat & IP_CTS) ? TIOCM_CTS : 0) | + ((i_stat & IP_DCD) ? TIOCM_CAR : 0) | + ((i_stat & IP_DSR) ? TIOCM_DSR : 0) | + ((i_stat & IP_RI) ? TIOCM_RNG : 0)); } - -static void sx_set_baud (struct sx_port *port) +static void sx_set_baud(struct sx_port *port) { int t; if (port->board->ta_type == MOD_SXDC) { switch (port->gs.baud) { - /* Save some typing work... */ -#define e(x) case x:t= BAUD_ ## x ; break - e(50);e(75);e(110);e(150);e(200);e(300);e(600); - e(1200);e(1800);e(2000);e(2400);e(4800);e(7200); - e(9600);e(14400);e(19200);e(28800);e(38400); - e(56000);e(57600);e(64000);e(76800);e(115200); - e(128000);e(150000);e(230400);e(256000);e(460800); - e(921600); - case 134 :t = BAUD_134_5; break; - case 0 :t = -1; - break; + /* Save some typing work... */ +#define e(x) case x: t = BAUD_ ## x; break + e(50); + e(75); + e(110); + e(150); + e(200); + e(300); + e(600); + e(1200); + e(1800); + e(2000); + e(2400); + e(4800); + e(7200); + e(9600); + e(14400); + e(19200); + e(28800); + e(38400); + e(56000); + e(57600); + e(64000); + e(76800); + e(115200); + e(128000); + e(150000); + e(230400); + e(256000); + e(460800); + e(921600); + case 134: + t = BAUD_134_5; + break; + case 0: + t = -1; + break; default: /* Can I return "invalid"? */ t = BAUD_9600; - printk (KERN_INFO "sx: unsupported baud rate: %d.\n", port->gs.baud); + printk(KERN_INFO "sx: unsupported baud rate: %d.\n", + port->gs.baud); break; } #undef e if (t > 0) { - /* The baud rate is not set to 0, so we're enabeling DTR... -- REW */ - sx_setsignals (port, 1, -1); +/* The baud rate is not set to 0, so we're enabeling DTR... -- REW */ + sx_setsignals(port, 1, -1); /* XXX This is not TA & MTA compatible */ - sx_write_channel_byte (port, hi_csr, 0xff); + sx_write_channel_byte(port, hi_csr, 0xff); - sx_write_channel_byte (port, hi_txbaud, t); - sx_write_channel_byte (port, hi_rxbaud, t); + sx_write_channel_byte(port, hi_txbaud, t); + sx_write_channel_byte(port, hi_rxbaud, t); } else { - sx_setsignals (port, 0, -1); + sx_setsignals(port, 0, -1); } } else { switch (port->gs.baud) { -#define e(x) case x:t= CSR_ ## x ; break - e(75);e(150);e(300);e(600);e(1200);e(2400);e(4800); - e(1800);e(9600); - e(19200);e(57600);e(38400); - /* TA supports 110, but not 115200, MTA supports 115200, but not 110 */ - case 110: +#define e(x) case x: t = CSR_ ## x; break + e(75); + e(150); + e(300); + e(600); + e(1200); + e(2400); + e(4800); + e(1800); + e(9600); + e(19200); + e(57600); + e(38400); +/* TA supports 110, but not 115200, MTA supports 115200, but not 110 */ + case 110: if (port->board->ta_type == MOD_TA) { t = CSR_110; break; } else { t = CSR_9600; - printk (KERN_INFO "sx: Unsupported baud rate: %d.\n", port->gs.baud); + printk(KERN_INFO "sx: Unsupported baud rate: " + "%d.\n", port->gs.baud); break; } - case 115200: + case 115200: if (port->board->ta_type == MOD_TA) { t = CSR_9600; - printk (KERN_INFO "sx: Unsupported baud rate: %d.\n", port->gs.baud); + printk(KERN_INFO "sx: Unsupported baud rate: " + "%d.\n", port->gs.baud); break; } else { t = CSR_110; break; } - case 0 :t = -1; - break; + case 0: + t = -1; + break; default: t = CSR_9600; - printk (KERN_INFO "sx: Unsupported baud rate: %d.\n", port->gs.baud); + printk(KERN_INFO "sx: Unsupported baud rate: %d.\n", + port->gs.baud); break; } #undef e if (t >= 0) { - sx_setsignals (port, 1, -1); - sx_write_channel_byte (port, hi_csr, t * 0x11); + sx_setsignals(port, 1, -1); + sx_write_channel_byte(port, hi_csr, t * 0x11); } else { - sx_setsignals (port, 0, -1); + sx_setsignals(port, 0, -1); } } } - /* Simon Allen's version of this routine was 225 lines long. 85 is a lot better. -- REW */ -static int sx_set_real_termios (void *ptr) +static int sx_set_real_termios(void *ptr) { struct sx_port *port = ptr; @@ -907,80 +939,83 @@ static int sx_set_real_termios (void *ptr) belongs (next to the drop dtr if baud == 0) -- REW */ /* sx_setsignals (port, 1, -1); */ - sx_set_baud (port); + sx_set_baud(port); #define CFLAG port->gs.tty->termios->c_cflag - sx_write_channel_byte (port, hi_mr1, - (C_PARENB (port->gs.tty)? MR1_WITH:MR1_NONE) | - (C_PARODD (port->gs.tty)? MR1_ODD:MR1_EVEN) | - (C_CRTSCTS(port->gs.tty)? MR1_RTS_RXFLOW:0) | - (((CFLAG & CSIZE)==CS8) ? MR1_8_BITS:0) | - (((CFLAG & CSIZE)==CS7) ? MR1_7_BITS:0) | - (((CFLAG & CSIZE)==CS6) ? MR1_6_BITS:0) | - (((CFLAG & CSIZE)==CS5) ? MR1_5_BITS:0) ); - - sx_write_channel_byte (port, hi_mr2, - (C_CRTSCTS(port->gs.tty)?MR2_CTS_TXFLOW:0) | - (C_CSTOPB (port->gs.tty)?MR2_2_STOP:MR2_1_STOP)); + sx_write_channel_byte(port, hi_mr1, + (C_PARENB(port->gs.tty) ? MR1_WITH : MR1_NONE) | + (C_PARODD(port->gs.tty) ? MR1_ODD : MR1_EVEN) | + (C_CRTSCTS(port->gs.tty) ? MR1_RTS_RXFLOW : 0) | + (((CFLAG & CSIZE) == CS8) ? MR1_8_BITS : 0) | + (((CFLAG & CSIZE) == CS7) ? MR1_7_BITS : 0) | + (((CFLAG & CSIZE) == CS6) ? MR1_6_BITS : 0) | + (((CFLAG & CSIZE) == CS5) ? MR1_5_BITS : 0)); + + sx_write_channel_byte(port, hi_mr2, + (C_CRTSCTS(port->gs.tty) ? MR2_CTS_TXFLOW : 0) | + (C_CSTOPB(port->gs.tty) ? MR2_2_STOP : + MR2_1_STOP)); switch (CFLAG & CSIZE) { - case CS8:sx_write_channel_byte (port, hi_mask, 0xff);break; - case CS7:sx_write_channel_byte (port, hi_mask, 0x7f);break; - case CS6:sx_write_channel_byte (port, hi_mask, 0x3f);break; - case CS5:sx_write_channel_byte (port, hi_mask, 0x1f);break; + case CS8: + sx_write_channel_byte(port, hi_mask, 0xff); + break; + case CS7: + sx_write_channel_byte(port, hi_mask, 0x7f); + break; + case CS6: + sx_write_channel_byte(port, hi_mask, 0x3f); + break; + case CS5: + sx_write_channel_byte(port, hi_mask, 0x1f); + break; default: - printk (KERN_INFO "sx: Invalid wordsize: %u\n", CFLAG & CSIZE); + printk(KERN_INFO "sx: Invalid wordsize: %u\n", CFLAG & CSIZE); break; } - sx_write_channel_byte (port, hi_prtcl, - (I_IXON (port->gs.tty)?SP_TXEN:0) | - (I_IXOFF (port->gs.tty)?SP_RXEN:0) | - (I_IXANY (port->gs.tty)?SP_TANY:0) | - SP_DCEN); + sx_write_channel_byte(port, hi_prtcl, + (I_IXON(port->gs.tty) ? SP_TXEN : 0) | + (I_IXOFF(port->gs.tty) ? SP_RXEN : 0) | + (I_IXANY(port->gs.tty) ? SP_TANY : 0) | SP_DCEN); - sx_write_channel_byte (port, hi_break, - (I_IGNBRK(port->gs.tty)?BR_IGN:0 | - I_BRKINT(port->gs.tty)?BR_INT:0)); + sx_write_channel_byte(port, hi_break, + (I_IGNBRK(port->gs.tty) ? BR_IGN : 0 | + I_BRKINT(port->gs.tty) ? BR_INT : 0)); - sx_write_channel_byte (port, hi_txon, START_CHAR (port->gs.tty)); - sx_write_channel_byte (port, hi_rxon, START_CHAR (port->gs.tty)); - sx_write_channel_byte (port, hi_txoff, STOP_CHAR (port->gs.tty)); - sx_write_channel_byte (port, hi_rxoff, STOP_CHAR (port->gs.tty)); + sx_write_channel_byte(port, hi_txon, START_CHAR(port->gs.tty)); + sx_write_channel_byte(port, hi_rxon, START_CHAR(port->gs.tty)); + sx_write_channel_byte(port, hi_txoff, STOP_CHAR(port->gs.tty)); + sx_write_channel_byte(port, hi_rxoff, STOP_CHAR(port->gs.tty)); sx_reconfigure_port(port); /* Tell line discipline whether we will do input cooking */ - if(I_OTHER(port->gs.tty)) { + if (I_OTHER(port->gs.tty)) { clear_bit(TTY_HW_COOK_IN, &port->gs.tty->flags); } else { set_bit(TTY_HW_COOK_IN, &port->gs.tty->flags); } - sx_dprintk (SX_DEBUG_TERMIOS, "iflags: %x(%d) ", - port->gs.tty->termios->c_iflag, - I_OTHER(port->gs.tty)); - + sx_dprintk(SX_DEBUG_TERMIOS, "iflags: %x(%d) ", + port->gs.tty->termios->c_iflag, I_OTHER(port->gs.tty)); /* Tell line discipline whether we will do output cooking. * If OPOST is set and no other output flags are set then we can do output * processing. Even if only *one* other flag in the O_OTHER group is set * we do cooking in software. */ - if(O_OPOST(port->gs.tty) && !O_OTHER(port->gs.tty)) { + if (O_OPOST(port->gs.tty) && !O_OTHER(port->gs.tty)) { set_bit(TTY_HW_COOK_OUT, &port->gs.tty->flags); } else { clear_bit(TTY_HW_COOK_OUT, &port->gs.tty->flags); } - sx_dprintk (SX_DEBUG_TERMIOS, "oflags: %x(%d)\n", - port->gs.tty->termios->c_oflag, - O_OTHER(port->gs.tty)); + sx_dprintk(SX_DEBUG_TERMIOS, "oflags: %x(%d)\n", + port->gs.tty->termios->c_oflag, O_OTHER(port->gs.tty)); /* port->c_dcd = sx_get_CD (port); */ - func_exit (); + func_exit(); return 0; } - - /* ********************************************************************** * * the interrupt related routines * * ********************************************************************** */ @@ -996,245 +1031,260 @@ static int sx_set_real_termios (void *ptr) know I'm dead against that, but I think it is required in this case. */ - -static void sx_transmit_chars (struct sx_port *port) +static void sx_transmit_chars(struct sx_port *port) { int c; int tx_ip; int txroom; - func_enter2 (); - sx_dprintk (SX_DEBUG_TRANSMIT, "Port %p: transmit %d chars\n", - port, port->gs.xmit_cnt); + func_enter2(); + sx_dprintk(SX_DEBUG_TRANSMIT, "Port %p: transmit %d chars\n", + port, port->gs.xmit_cnt); - if (test_and_set_bit (SX_PORT_TRANSMIT_LOCK, &port->locks)) { + if (test_and_set_bit(SX_PORT_TRANSMIT_LOCK, &port->locks)) { return; } while (1) { c = port->gs.xmit_cnt; - sx_dprintk (SX_DEBUG_TRANSMIT, "Copying %d ", c); - tx_ip = sx_read_channel_byte (port, hi_txipos); + sx_dprintk(SX_DEBUG_TRANSMIT, "Copying %d ", c); + tx_ip = sx_read_channel_byte(port, hi_txipos); /* Took me 5 minutes to deduce this formula. Luckily it is literally in the manual in section 6.5.4.3.5 */ - txroom = (sx_read_channel_byte (port, hi_txopos) - tx_ip - 1) & 0xff; + txroom = (sx_read_channel_byte(port, hi_txopos) - tx_ip - 1) & + 0xff; /* Don't copy more bytes than there is room for in the buffer */ if (c > txroom) c = txroom; - sx_dprintk (SX_DEBUG_TRANSMIT, " %d(%d) ", c, txroom ); + sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, txroom); /* Don't copy past the end of the hardware transmit buffer */ - if (c > 0x100 - tx_ip) + if (c > 0x100 - tx_ip) c = 0x100 - tx_ip; - sx_dprintk (SX_DEBUG_TRANSMIT, " %d(%d) ", c, 0x100-tx_ip ); + sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, 0x100 - tx_ip); /* Don't copy pas the end of the source buffer */ - if (c > SERIAL_XMIT_SIZE - port->gs.xmit_tail) + if (c > SERIAL_XMIT_SIZE - port->gs.xmit_tail) c = SERIAL_XMIT_SIZE - port->gs.xmit_tail; - sx_dprintk (SX_DEBUG_TRANSMIT, " %d(%ld) \n", - c, SERIAL_XMIT_SIZE- port->gs.xmit_tail); - - /* If for one reason or another, we can't copy more data, we're done! */ - if (c == 0) break; + sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%ld) \n", + c, SERIAL_XMIT_SIZE - port->gs.xmit_tail); + /* If for one reason or another, we can't copy more data, we're + done! */ + if (c == 0) + break; - memcpy_toio (port->board->base + CHAN_OFFSET(port,hi_txbuf) + tx_ip, - port->gs.xmit_buf + port->gs.xmit_tail, c); + memcpy_toio(port->board->base + CHAN_OFFSET(port, hi_txbuf) + + tx_ip, port->gs.xmit_buf + port->gs.xmit_tail, c); /* Update the pointer in the card */ - sx_write_channel_byte (port, hi_txipos, (tx_ip+c) & 0xff); + sx_write_channel_byte(port, hi_txipos, (tx_ip + c) & 0xff); /* Update the kernel buffer end */ - port->gs.xmit_tail = (port->gs.xmit_tail + c) & (SERIAL_XMIT_SIZE-1); + port->gs.xmit_tail = (port->gs.xmit_tail + c) & + (SERIAL_XMIT_SIZE - 1); /* This one last. (this is essential) - It would allow others to start putting more data into the buffer! */ + It would allow others to start putting more data into the + buffer! */ port->gs.xmit_cnt -= c; } if (port->gs.xmit_cnt == 0) { - sx_disable_tx_interrupts (port); + sx_disable_tx_interrupts(port); } if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.tty) { tty_wakeup(port->gs.tty); - sx_dprintk (SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n", - port->gs.wakeup_chars); + sx_dprintk(SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n", + port->gs.wakeup_chars); } - clear_bit (SX_PORT_TRANSMIT_LOCK, &port->locks); - func_exit (); + clear_bit(SX_PORT_TRANSMIT_LOCK, &port->locks); + func_exit(); } - /* Note the symmetry between receiving chars and transmitting them! Note: The kernel should have implemented both a receive buffer and a transmit buffer. */ /* Inlined: Called only once. Remove the inline when you add another call */ -static inline void sx_receive_chars (struct sx_port *port) +static inline void sx_receive_chars(struct sx_port *port) { int c; int rx_op; struct tty_struct *tty; - int copied=0; + int copied = 0; unsigned char *rp; - func_enter2 (); + func_enter2(); tty = port->gs.tty; while (1) { - rx_op = sx_read_channel_byte (port, hi_rxopos); - c = (sx_read_channel_byte (port, hi_rxipos) - rx_op) & 0xff; + rx_op = sx_read_channel_byte(port, hi_rxopos); + c = (sx_read_channel_byte(port, hi_rxipos) - rx_op) & 0xff; - sx_dprintk (SX_DEBUG_RECEIVE, "rxop=%d, c = %d.\n", rx_op, c); + sx_dprintk(SX_DEBUG_RECEIVE, "rxop=%d, c = %d.\n", rx_op, c); /* Don't copy past the end of the hardware receive buffer */ - if (rx_op + c > 0x100) c = 0x100 - rx_op; + if (rx_op + c > 0x100) + c = 0x100 - rx_op; - sx_dprintk (SX_DEBUG_RECEIVE, "c = %d.\n", c); + sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c); /* Don't copy more bytes than there is room for in the buffer */ c = tty_prepare_flip_string(tty, &rp, c); - sx_dprintk (SX_DEBUG_RECEIVE, "c = %d.\n", c); + sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c); /* If for one reason or another, we can't copy more data, we're done! */ - if (c == 0) break; + if (c == 0) + break; - sx_dprintk (SX_DEBUG_RECEIVE , "Copying over %d chars. First is %d at %lx\n", c, - read_sx_byte (port->board, CHAN_OFFSET(port,hi_rxbuf) + rx_op), - CHAN_OFFSET(port, hi_rxbuf)); - memcpy_fromio (rp, - port->board->base + CHAN_OFFSET(port,hi_rxbuf) + rx_op, c); + sx_dprintk(SX_DEBUG_RECEIVE, "Copying over %d chars. First is " + "%d at %lx\n", c, read_sx_byte(port->board, + CHAN_OFFSET(port, hi_rxbuf) + rx_op), + CHAN_OFFSET(port, hi_rxbuf)); + memcpy_fromio(rp, port->board->base + + CHAN_OFFSET(port, hi_rxbuf) + rx_op, c); /* This one last. ( Not essential.) - It allows the card to start putting more data into the buffer! + It allows the card to start putting more data into the + buffer! Update the pointer in the card */ - sx_write_channel_byte (port, hi_rxopos, (rx_op + c) & 0xff); + sx_write_channel_byte(port, hi_rxopos, (rx_op + c) & 0xff); copied += c; } if (copied) { struct timeval tv; - do_gettimeofday (&tv); - sx_dprintk (SX_DEBUG_RECEIVE, - "pushing flipq port %d (%3d chars): %d.%06d (%d/%d)\n", - port->line, copied, - (int) (tv.tv_sec % 60), (int)tv.tv_usec, tty->raw, tty->real_raw); + do_gettimeofday(&tv); + sx_dprintk(SX_DEBUG_RECEIVE, "pushing flipq port %d (%3d " + "chars): %d.%06d (%d/%d)\n", port->line, + copied, (int)(tv.tv_sec % 60), (int)tv.tv_usec, + tty->raw, tty->real_raw); - /* Tell the rest of the system the news. Great news. New characters! */ - tty_flip_buffer_push (tty); + /* Tell the rest of the system the news. Great news. New + characters! */ + tty_flip_buffer_push(tty); /* tty_schedule_flip (tty); */ } - func_exit (); + func_exit(); } /* Inlined: it is called only once. Remove the inline if you add another call */ -static inline void sx_check_modem_signals (struct sx_port *port) +static inline void sx_check_modem_signals(struct sx_port *port) { int hi_state; int c_dcd; - hi_state = sx_read_channel_byte (port, hi_state); - sx_dprintk (SX_DEBUG_MODEMSIGNALS, "Checking modem signals (%d/%d)\n", - port->c_dcd, sx_get_CD (port)); + hi_state = sx_read_channel_byte(port, hi_state); + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Checking modem signals (%d/%d)\n", + port->c_dcd, sx_get_CD(port)); if (hi_state & ST_BREAK) { hi_state &= ~ST_BREAK; - sx_dprintk (SX_DEBUG_MODEMSIGNALS, "got a break.\n"); - sx_write_channel_byte (port, hi_state, hi_state); - gs_got_break (&port->gs); + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a break.\n"); + sx_write_channel_byte(port, hi_state, hi_state); + gs_got_break(&port->gs); } if (hi_state & ST_DCD) { hi_state &= ~ST_DCD; - sx_dprintk (SX_DEBUG_MODEMSIGNALS, "got a DCD change.\n"); - sx_write_channel_byte (port, hi_state, hi_state); - c_dcd = sx_get_CD (port); - sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD is now %d\n", c_dcd); + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a DCD change.\n"); + sx_write_channel_byte(port, hi_state, hi_state); + c_dcd = sx_get_CD(port); + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD is now %d\n", c_dcd); if (c_dcd != port->c_dcd) { port->c_dcd = c_dcd; - if (sx_get_CD (port)) { + if (sx_get_CD(port)) { /* DCD went UP */ - if ((sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED) && - !(port->gs.tty->termios->c_cflag & CLOCAL) ) { - /* Are we blocking in open?*/ - sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD active, unblocking open\n"); - wake_up_interruptible(&port->gs.open_wait); + if ((sx_read_channel_byte(port, hi_hstat) != + HS_IDLE_CLOSED) && + !(port->gs.tty->termios-> + c_cflag & CLOCAL)) { + /* Are we blocking in open? */ + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD " + "active, unblocking open\n"); + wake_up_interruptible(&port->gs. + open_wait); } else { - sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD raised. Ignoring.\n"); + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD " + "raised. Ignoring.\n"); } } else { /* DCD went down! */ - if (!(port->gs.tty->termios->c_cflag & CLOCAL) ) { - sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD dropped. hanging up....\n"); - tty_hangup (port->gs.tty); + if (!(port->gs.tty->termios->c_cflag & CLOCAL)){ + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD " + "dropped. hanging up....\n"); + tty_hangup(port->gs.tty); } else { - sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD dropped. ignoring.\n"); + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD " + "dropped. ignoring.\n"); } } } else { - sx_dprintk (SX_DEBUG_MODEMSIGNALS, "Hmmm. card told us DCD changed, but it didn't.\n"); + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Hmmm. card told us " + "DCD changed, but it didn't.\n"); } } } - /* This is what an interrupt routine should look like. * Small, elegant, clear. */ -static irqreturn_t sx_interrupt (int irq, void *ptr) +static irqreturn_t sx_interrupt(int irq, void *ptr) { struct sx_board *board = ptr; struct sx_port *port; int i; - func_enter (); - sx_dprintk (SX_DEBUG_FLOW, "sx: enter sx_interrupt (%d/%d)\n", irq, board->irq); + func_enter(); + sx_dprintk(SX_DEBUG_FLOW, "sx: enter sx_interrupt (%d/%d)\n", irq, + board->irq); /* AAargh! The order in which to do these things is essential and not trivial. - Rate limit goes before "recursive". Otherwise a series of - recursive calls will hang the machine in the interrupt routine. + recursive calls will hang the machine in the interrupt routine. - hardware twiddling goes before "recursive". Otherwise when we - poll the card, and a recursive interrupt happens, we won't - ack the card, so it might keep on interrupting us. (especially - level sensitive interrupt systems like PCI). + poll the card, and a recursive interrupt happens, we won't + ack the card, so it might keep on interrupting us. (especially + level sensitive interrupt systems like PCI). - Rate limit goes before hardware twiddling. Otherwise we won't - catch a card that has gone bonkers. + catch a card that has gone bonkers. - The "initialized" test goes after the hardware twiddling. Otherwise - the card will stick us in the interrupt routine again. + the card will stick us in the interrupt routine again. - The initialized test goes before recursive. - */ - - + */ #ifdef IRQ_RATE_LIMIT /* Aaargh! I'm ashamed. This costs more lines-of-code than the - actual interrupt routine!. (Well, used to when I wrote that comment) */ + actual interrupt routine!. (Well, used to when I wrote that + comment) */ { static int lastjif; - static int nintr=0; + static int nintr = 0; if (lastjif == jiffies) { if (++nintr > IRQ_RATE_LIMIT) { - free_irq (board->irq, board); - printk (KERN_ERR "sx: Too many interrupts. Turning off interrupt %d.\n", - board->irq); + free_irq(board->irq, board); + printk(KERN_ERR "sx: Too many interrupts. " + "Turning off interrupt %d.\n", + board->irq); } } else { lastjif = jiffies; @@ -1243,19 +1293,20 @@ static irqreturn_t sx_interrupt (int irq, void *ptr) } #endif - if (board->irq == irq) { /* Tell the card we've noticed the interrupt. */ - sx_write_board_word (board, cc_int_pending, 0); - if (IS_SX_BOARD (board)) { - write_sx_byte (board, SX_RESET_IRQ, 1); + sx_write_board_word(board, cc_int_pending, 0); + if (IS_SX_BOARD(board)) { + write_sx_byte(board, SX_RESET_IRQ, 1); } else if (IS_EISA_BOARD(board)) { - inb(board->eisa_base+0xc03); - write_sx_word(board, 8, 0); + inb(board->eisa_base + 0xc03); + write_sx_word(board, 8, 0); } else { - write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR); - write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET); + write_sx_byte(board, SI2_ISA_INTCLEAR, + SI2_ISA_INTCLEAR_CLEAR); + write_sx_byte(board, SI2_ISA_INTCLEAR, + SI2_ISA_INTCLEAR_SET); } } @@ -1264,53 +1315,48 @@ static irqreturn_t sx_interrupt (int irq, void *ptr) if (!(board->flags & SX_BOARD_INITIALIZED)) return IRQ_HANDLED; - if (test_and_set_bit (SX_BOARD_INTR_LOCK, &board->locks)) { - printk (KERN_ERR "Recursive interrupt! (%d)\n", board->irq); + if (test_and_set_bit(SX_BOARD_INTR_LOCK, &board->locks)) { + printk(KERN_ERR "Recursive interrupt! (%d)\n", board->irq); return IRQ_HANDLED; } - for (i=0;i<board->nports;i++) { + for (i = 0; i < board->nports; i++) { port = &board->ports[i]; if (port->gs.flags & GS_ACTIVE) { - if (sx_read_channel_byte (port, hi_state)) { - sx_dprintk (SX_DEBUG_INTERRUPTS, - "Port %d: modem signal change?... \n", i); - sx_check_modem_signals (port); + if (sx_read_channel_byte(port, hi_state)) { + sx_dprintk(SX_DEBUG_INTERRUPTS, "Port %d: " + "modem signal change?... \n",i); + sx_check_modem_signals(port); } if (port->gs.xmit_cnt) { - sx_transmit_chars (port); + sx_transmit_chars(port); } if (!(port->gs.flags & SX_RX_THROTTLE)) { - sx_receive_chars (port); + sx_receive_chars(port); } } } - clear_bit (SX_BOARD_INTR_LOCK, &board->locks); + clear_bit(SX_BOARD_INTR_LOCK, &board->locks); - sx_dprintk (SX_DEBUG_FLOW, "sx: exit sx_interrupt (%d/%d)\n", irq, board->irq); - func_exit (); + sx_dprintk(SX_DEBUG_FLOW, "sx: exit sx_interrupt (%d/%d)\n", irq, + board->irq); + func_exit(); return IRQ_HANDLED; } - -static void sx_pollfunc (unsigned long data) +static void sx_pollfunc(unsigned long data) { - struct sx_board *board = (struct sx_board *) data; - - func_enter (); + struct sx_board *board = (struct sx_board *)data; - sx_interrupt (0, board); + func_enter(); - init_timer(&board->timer); + sx_interrupt(0, board); - board->timer.expires = jiffies + sx_poll; - add_timer (&board->timer); - func_exit (); + mod_timer(&board->timer, jiffies + sx_poll); + func_exit(); } - - /* ********************************************************************** * * Here are the routines that actually * * interface with the generic_serial driver * @@ -1319,9 +1365,9 @@ static void sx_pollfunc (unsigned long data) /* Ehhm. I don't know how to fiddle with interrupts on the SX card. --REW */ /* Hmm. Ok I figured it out. You don't. */ -static void sx_disable_tx_interrupts (void * ptr) +static void sx_disable_tx_interrupts(void *ptr) { - struct sx_port *port = ptr; + struct sx_port *port = ptr; func_enter2(); port->gs.flags &= ~GS_TX_INTEN; @@ -1329,30 +1375,28 @@ static void sx_disable_tx_interrupts (void * ptr) func_exit(); } - -static void sx_enable_tx_interrupts (void * ptr) +static void sx_enable_tx_interrupts(void *ptr) { - struct sx_port *port = ptr; + struct sx_port *port = ptr; int data_in_buffer; func_enter2(); /* First transmit the characters that we're supposed to */ - sx_transmit_chars (port); + sx_transmit_chars(port); /* The sx card will never interrupt us if we don't fill the buffer past 25%. So we keep considering interrupts off if that's the case. */ - data_in_buffer = (sx_read_channel_byte (port, hi_txipos) - - sx_read_channel_byte (port, hi_txopos)) & 0xff; + data_in_buffer = (sx_read_channel_byte(port, hi_txipos) - + sx_read_channel_byte(port, hi_txopos)) & 0xff; /* XXX Must be "HIGH_WATER" for SI card according to doc. */ - if (data_in_buffer < LOW_WATER) + if (data_in_buffer < LOW_WATER) port->gs.flags &= ~GS_TX_INTEN; func_exit(); } - -static void sx_disable_rx_interrupts (void * ptr) +static void sx_disable_rx_interrupts(void *ptr) { /* struct sx_port *port = ptr; */ func_enter(); @@ -1360,7 +1404,7 @@ static void sx_disable_rx_interrupts (void * ptr) func_exit(); } -static void sx_enable_rx_interrupts (void * ptr) +static void sx_enable_rx_interrupts(void *ptr) { /* struct sx_port *port = ptr; */ func_enter(); @@ -1368,55 +1412,48 @@ static void sx_enable_rx_interrupts (void * ptr) func_exit(); } - /* Jeez. Isn't this simple? */ -static int sx_get_CD (void * ptr) +static int sx_get_CD(void *ptr) { struct sx_port *port = ptr; func_enter2(); func_exit(); - return ((sx_read_channel_byte (port, hi_ip) & IP_DCD) != 0); + return ((sx_read_channel_byte(port, hi_ip) & IP_DCD) != 0); } - /* Jeez. Isn't this simple? */ -static int sx_chars_in_buffer (void * ptr) +static int sx_chars_in_buffer(void *ptr) { struct sx_port *port = ptr; func_enter2(); func_exit(); - return ((sx_read_channel_byte (port, hi_txipos) - - sx_read_channel_byte (port, hi_txopos)) & 0xff); + return ((sx_read_channel_byte(port, hi_txipos) - + sx_read_channel_byte(port, hi_txopos)) & 0xff); } - -static void sx_shutdown_port (void * ptr) +static void sx_shutdown_port(void *ptr) { - struct sx_port *port = ptr; + struct sx_port *port = ptr; func_enter(); - port->gs.flags &= ~ GS_ACTIVE; + port->gs.flags &= ~GS_ACTIVE; if (port->gs.tty && (port->gs.tty->termios->c_cflag & HUPCL)) { - sx_setsignals (port, 0, 0); + sx_setsignals(port, 0, 0); sx_reconfigure_port(port); } func_exit(); } - - - - /* ********************************************************************** * * Here are the routines that actually * * interface with the rest of the system * * ********************************************************************** */ -static int sx_open (struct tty_struct * tty, struct file * filp) +static int sx_open(struct tty_struct *tty, struct file *filp) { struct sx_port *port; int retval, line; @@ -1429,18 +1466,18 @@ static int sx_open (struct tty_struct * tty, struct file * filp) } line = tty->index; - sx_dprintk (SX_DEBUG_OPEN, "%d: opening line %d. tty=%p ctty=%p, np=%d)\n", - current->pid, line, tty, current->signal->tty, sx_nports); + sx_dprintk(SX_DEBUG_OPEN, "%d: opening line %d. tty=%p ctty=%p, " + "np=%d)\n", current->pid, line, tty, + current->signal->tty, sx_nports); if ((line < 0) || (line >= SX_NPORTS) || (line >= sx_nports)) return -ENODEV; - port = & sx_ports[line]; + port = &sx_ports[line]; port->c_dcd = 0; /* Make sure that the first interrupt doesn't detect a - 1 -> 0 transition. */ + 1 -> 0 transition. */ - - sx_dprintk (SX_DEBUG_OPEN, "port = %p c_dcd = %d\n", port, port->c_dcd); + sx_dprintk(SX_DEBUG_OPEN, "port = %p c_dcd = %d\n", port, port->c_dcd); spin_lock_irqsave(&port->gs.driver_lock, flags); @@ -1449,13 +1486,13 @@ static int sx_open (struct tty_struct * tty, struct file * filp) port->gs.count++; spin_unlock_irqrestore(&port->gs.driver_lock, flags); - sx_dprintk (SX_DEBUG_OPEN, "starting port\n"); + sx_dprintk(SX_DEBUG_OPEN, "starting port\n"); /* * Start up serial port */ retval = gs_init_port(&port->gs); - sx_dprintk (SX_DEBUG_OPEN, "done gs_init\n"); + sx_dprintk(SX_DEBUG_OPEN, "done gs_init\n"); if (retval) { port->gs.count--; return retval; @@ -1463,19 +1500,20 @@ static int sx_open (struct tty_struct * tty, struct file * filp) port->gs.flags |= GS_ACTIVE; if (port->gs.count <= 1) - sx_setsignals (port, 1,1); + sx_setsignals(port, 1, 1); #if 0 if (sx_debug & SX_DEBUG_OPEN) - my_hd (port, sizeof (*port)); + my_hd(port, sizeof(*port)); #else if (sx_debug & SX_DEBUG_OPEN) - my_hd_io (port->board->base + port->ch_base, sizeof (*port)); + my_hd_io(port->board->base + port->ch_base, sizeof(*port)); #endif if (port->gs.count <= 1) { - if (sx_send_command (port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) { - printk (KERN_ERR "sx: Card didn't respond to LOPEN command.\n"); + if (sx_send_command(port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) { + printk(KERN_ERR "sx: Card didn't respond to LOPEN " + "command.\n"); spin_lock_irqsave(&port->gs.driver_lock, flags); port->gs.count--; spin_unlock_irqrestore(&port->gs.driver_lock, flags); @@ -1484,75 +1522,76 @@ static int sx_open (struct tty_struct * tty, struct file * filp) } retval = gs_block_til_ready(port, filp); - sx_dprintk (SX_DEBUG_OPEN, "Block til ready returned %d. Count=%d\n", - retval, port->gs.count); + sx_dprintk(SX_DEBUG_OPEN, "Block til ready returned %d. Count=%d\n", + retval, port->gs.count); if (retval) { - /* - * Don't lower gs.count here because sx_close() will be called later - */ +/* + * Don't lower gs.count here because sx_close() will be called later + */ return retval; } /* tty->low_latency = 1; */ - port->c_dcd = sx_get_CD (port); - sx_dprintk (SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd); + port->c_dcd = sx_get_CD(port); + sx_dprintk(SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd); func_exit(); return 0; } - -static void sx_close (void *ptr) +static void sx_close(void *ptr) { - struct sx_port *port = ptr; + struct sx_port *port = ptr; /* Give the port 5 seconds to close down. */ - int to = 5 * HZ; + int to = 5 * HZ; - func_enter (); + func_enter(); - sx_setsignals (port, 0, 0); - sx_reconfigure_port(port); - sx_send_command (port, HS_CLOSE, 0, 0); + sx_setsignals(port, 0, 0); + sx_reconfigure_port(port); + sx_send_command(port, HS_CLOSE, 0, 0); - while (to-- && (sx_read_channel_byte (port, hi_hstat) != HS_IDLE_CLOSED)) + while (to-- && (sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED)) if (msleep_interruptible(10)) break; - if (sx_read_channel_byte (port, hi_hstat) != HS_IDLE_CLOSED) { - if (sx_send_command (port, HS_FORCE_CLOSED, -1, HS_IDLE_CLOSED) != 1) { - printk (KERN_ERR - "sx: sent the force_close command, but card didn't react\n"); + if (sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED) { + if (sx_send_command(port, HS_FORCE_CLOSED, -1, HS_IDLE_CLOSED) + != 1) { + printk(KERN_ERR "sx: sent the force_close command, but " + "card didn't react\n"); } else - sx_dprintk (SX_DEBUG_CLOSE, "sent the force_close command.\n"); + sx_dprintk(SX_DEBUG_CLOSE, "sent the force_close " + "command.\n"); } - sx_dprintk (SX_DEBUG_CLOSE, "waited %d jiffies for close. count=%d\n", - 5 * HZ - to - 1, port->gs.count); + sx_dprintk(SX_DEBUG_CLOSE, "waited %d jiffies for close. count=%d\n", + 5 * HZ - to - 1, port->gs.count); - if(port->gs.count) { - sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n", port->gs.count); - //printk ("%s SETTING port count to zero: %p count: %d\n", __FUNCTION__, port, port->gs.count); - //port->gs.count = 0; + if (port->gs.count) { + sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n", + port->gs.count); + /*printk("%s SETTING port count to zero: %p count: %d\n", + __FUNCTION__, port, port->gs.count); + port->gs.count = 0;*/ } - func_exit (); + func_exit(); } - - /* This is relatively thorough. But then again it is only 20 lines. */ -#define MARCHUP for (i=min;i<max;i++) -#define MARCHDOWN for (i=max-1;i>=min;i--) -#define W0 write_sx_byte (board, i, 0x55) -#define W1 write_sx_byte (board, i, 0xaa) -#define R0 if (read_sx_byte (board, i) != 0x55) return 1 -#define R1 if (read_sx_byte (board, i) != 0xaa) return 1 +#define MARCHUP for (i = min; i < max; i++) +#define MARCHDOWN for (i = max - 1; i >= min; i--) +#define W0 write_sx_byte(board, i, 0x55) +#define W1 write_sx_byte(board, i, 0xaa) +#define R0 if (read_sx_byte(board, i) != 0x55) return 1 +#define R1 if (read_sx_byte(board, i) != 0xaa) return 1 /* This memtest takes a human-noticable time. You normally only do it once a boot, so I guess that it is worth it. */ -static int do_memtest (struct sx_board *board, int min, int max) +static int do_memtest(struct sx_board *board, int min, int max) { int i; @@ -1561,16 +1600,37 @@ static int do_memtest (struct sx_board *board, int min, int max) intermittent errors. -- REW (For the theory behind memory testing see: Testing Semiconductor Memories by A.J. van de Goor.) */ - MARCHUP {W0;} - MARCHUP {R0;W1;R1;W0;R0;W1;} - MARCHUP {R1;W0;W1;} - MARCHDOWN {R1;W0;W1;W0;} - MARCHDOWN {R0;W1;W0;} + MARCHUP { + W0; + } + MARCHUP { + R0; + W1; + R1; + W0; + R0; + W1; + } + MARCHUP { + R1; + W0; + W1; + } + MARCHDOWN { + R1; + W0; + W1; + W0; + } + MARCHDOWN { + R0; + W1; + W0; + } return 0; } - #undef MARCHUP #undef MARCHDOWN #undef W0 @@ -1578,33 +1638,54 @@ static int do_memtest (struct sx_board *board, int min, int max) #undef R0 #undef R1 -#define MARCHUP for (i=min;i<max;i+=2) -#define MARCHDOWN for (i=max-1;i>=min;i-=2) -#define W0 write_sx_word (board, i, 0x55aa) -#define W1 write_sx_word (board, i, 0xaa55) -#define R0 if (read_sx_word (board, i) != 0x55aa) return 1 -#define R1 if (read_sx_word (board, i) != 0xaa55) return 1 +#define MARCHUP for (i = min; i < max; i += 2) +#define MARCHDOWN for (i = max - 1; i >= min; i -= 2) +#define W0 write_sx_word(board, i, 0x55aa) +#define W1 write_sx_word(board, i, 0xaa55) +#define R0 if (read_sx_word(board, i) != 0x55aa) return 1 +#define R1 if (read_sx_word(board, i) != 0xaa55) return 1 #if 0 /* This memtest takes a human-noticable time. You normally only do it once a boot, so I guess that it is worth it. */ -static int do_memtest_w (struct sx_board *board, int min, int max) +static int do_memtest_w(struct sx_board *board, int min, int max) { int i; - MARCHUP {W0;} - MARCHUP {R0;W1;R1;W0;R0;W1;} - MARCHUP {R1;W0;W1;} - MARCHDOWN {R1;W0;W1;W0;} - MARCHDOWN {R0;W1;W0;} + MARCHUP { + W0; + } + MARCHUP { + R0; + W1; + R1; + W0; + R0; + W1; + } + MARCHUP { + R1; + W0; + W1; + } + MARCHDOWN { + R1; + W0; + W1; + W0; + } + MARCHDOWN { + R0; + W1; + W0; + } return 0; } #endif - -static int sx_fw_ioctl (struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +static int sx_fw_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { int rc = 0; int __user *descr = (int __user *)arg; @@ -1616,7 +1697,7 @@ static int sx_fw_ioctl (struct inode *inode, struct file *filp, func_enter(); -#if 0 +#if 0 /* Removed superuser check: Sysops can use the permissions on the device file to restrict access. Recommendation: Root only. (root.root 600) */ if (!capable(CAP_SYS_ADMIN)) { @@ -1624,103 +1705,115 @@ static int sx_fw_ioctl (struct inode *inode, struct file *filp, } #endif - sx_dprintk (SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg); + sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg); - if (!board) board = &boards[0]; + if (!board) + board = &boards[0]; if (board->flags & SX_BOARD_PRESENT) { - sx_dprintk (SX_DEBUG_FIRMWARE, "Board present! (%x)\n", - board->flags); + sx_dprintk(SX_DEBUG_FIRMWARE, "Board present! (%x)\n", + board->flags); } else { - sx_dprintk (SX_DEBUG_FIRMWARE, "Board not present! (%x) all:", - board->flags); - for (i=0;i< SX_NBOARDS;i++) - sx_dprintk (SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags); - sx_dprintk (SX_DEBUG_FIRMWARE, "\n"); + sx_dprintk(SX_DEBUG_FIRMWARE, "Board not present! (%x) all:", + board->flags); + for (i = 0; i < SX_NBOARDS; i++) + sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags); + sx_dprintk(SX_DEBUG_FIRMWARE, "\n"); return -EIO; } switch (cmd) { case SXIO_SET_BOARD: - sx_dprintk (SX_DEBUG_FIRMWARE, "set board to %ld\n", arg); - if (arg >= SX_NBOARDS) return -EIO; - sx_dprintk (SX_DEBUG_FIRMWARE, "not out of range\n"); - if (!(boards[arg].flags & SX_BOARD_PRESENT)) return -EIO; - sx_dprintk (SX_DEBUG_FIRMWARE, ".. and present!\n"); + sx_dprintk(SX_DEBUG_FIRMWARE, "set board to %ld\n", arg); + if (arg >= SX_NBOARDS) + return -EIO; + sx_dprintk(SX_DEBUG_FIRMWARE, "not out of range\n"); + if (!(boards[arg].flags & SX_BOARD_PRESENT)) + return -EIO; + sx_dprintk(SX_DEBUG_FIRMWARE, ".. and present!\n"); board = &boards[arg]; break; case SXIO_GET_TYPE: - rc = -ENOENT; /* If we manage to miss one, return error. */ - if (IS_SX_BOARD (board)) rc = SX_TYPE_SX; - if (IS_CF_BOARD (board)) rc = SX_TYPE_CF; - if (IS_SI_BOARD (board)) rc = SX_TYPE_SI; - if (IS_SI1_BOARD (board)) rc = SX_TYPE_SI; - if (IS_EISA_BOARD (board)) rc = SX_TYPE_SI; - sx_dprintk (SX_DEBUG_FIRMWARE, "returning type= %d\n", rc); + rc = -ENOENT; /* If we manage to miss one, return error. */ + if (IS_SX_BOARD(board)) + rc = SX_TYPE_SX; + if (IS_CF_BOARD(board)) + rc = SX_TYPE_CF; + if (IS_SI_BOARD(board)) + rc = SX_TYPE_SI; + if (IS_SI1_BOARD(board)) + rc = SX_TYPE_SI; + if (IS_EISA_BOARD(board)) + rc = SX_TYPE_SI; + sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %d\n", rc); break; case SXIO_DO_RAMTEST: - if (sx_initialized) /* Already initialized: better not ramtest the board. */ + if (sx_initialized) /* Already initialized: better not ramtest the board. */ return -EPERM; - if (IS_SX_BOARD (board)) { - rc = do_memtest (board, 0, 0x7000); - if (!rc) rc = do_memtest (board, 0, 0x7000); - /*if (!rc) rc = do_memtest_w (board, 0, 0x7000);*/ + if (IS_SX_BOARD(board)) { + rc = do_memtest(board, 0, 0x7000); + if (!rc) + rc = do_memtest(board, 0, 0x7000); + /*if (!rc) rc = do_memtest_w (board, 0, 0x7000); */ } else { - rc = do_memtest (board, 0, 0x7ff8); + rc = do_memtest(board, 0, 0x7ff8); /* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */ } - sx_dprintk (SX_DEBUG_FIRMWARE, "returning memtest result= %d\n", rc); + sx_dprintk(SX_DEBUG_FIRMWARE, "returning memtest result= %d\n", + rc); break; case SXIO_DOWNLOAD: - if (sx_initialized) /* Already initialized */ + if (sx_initialized) /* Already initialized */ return -EEXIST; - if (!sx_reset (board)) + if (!sx_reset(board)) return -EIO; - sx_dprintk (SX_DEBUG_INIT, "reset the board...\n"); - - tmp = kmalloc (SX_CHUNK_SIZE, GFP_USER); - if (!tmp) return -ENOMEM; - get_user (nbytes, descr++); - get_user (offset, descr++); - get_user (data, descr++); + sx_dprintk(SX_DEBUG_INIT, "reset the board...\n"); + + tmp = kmalloc(SX_CHUNK_SIZE, GFP_USER); + if (!tmp) + return -ENOMEM; + get_user(nbytes, descr++); + get_user(offset, descr++); + get_user(data, descr++); while (nbytes && data) { - for (i=0;i<nbytes;i += SX_CHUNK_SIZE) { - if (copy_from_user(tmp, (char __user *)data+i, - (i + SX_CHUNK_SIZE > - nbytes) ? nbytes - i : - SX_CHUNK_SIZE)) { - kfree (tmp); + for (i = 0; i < nbytes; i += SX_CHUNK_SIZE) { + if (copy_from_user(tmp, (char __user *)data + i, + (i + SX_CHUNK_SIZE > nbytes) ? + nbytes - i : SX_CHUNK_SIZE)) { + kfree(tmp); return -EFAULT; } - memcpy_toio(board->base2 + offset + i, tmp, - (i+SX_CHUNK_SIZE>nbytes)?nbytes-i:SX_CHUNK_SIZE); + memcpy_toio(board->base2 + offset + i, tmp, + (i + SX_CHUNK_SIZE > nbytes) ? + nbytes - i : SX_CHUNK_SIZE); } - get_user (nbytes, descr++); - get_user (offset, descr++); - get_user (data, descr++); + get_user(nbytes, descr++); + get_user(offset, descr++); + get_user(data, descr++); } - kfree (tmp); - sx_nports += sx_init_board (board); + kfree(tmp); + sx_nports += sx_init_board(board); rc = sx_nports; break; case SXIO_INIT: - if (sx_initialized) /* Already initialized */ + if (sx_initialized) /* Already initialized */ return -EEXIST; /* This is not allowed until all boards are initialized... */ - for (i=0;i<SX_NBOARDS;i++) { - if ( (boards[i].flags & SX_BOARD_PRESENT) && - !(boards[i].flags & SX_BOARD_INITIALIZED)) + for (i = 0; i < SX_NBOARDS; i++) { + if ((boards[i].flags & SX_BOARD_PRESENT) && + !(boards[i].flags & SX_BOARD_INITIALIZED)) return -EIO; } - for (i=0;i<SX_NBOARDS;i++) - if (!(boards[i].flags & SX_BOARD_PRESENT)) break; - - sx_dprintk (SX_DEBUG_FIRMWARE, "initing portstructs, %d boards, " - "%d channels, first board: %d ports\n", - i, sx_nports, boards[0].nports); - rc = sx_init_portstructs (i, sx_nports); - sx_init_drivers (); - if (rc >= 0) + for (i = 0; i < SX_NBOARDS; i++) + if (!(boards[i].flags & SX_BOARD_PRESENT)) + break; + + sx_dprintk(SX_DEBUG_FIRMWARE, "initing portstructs, %d boards, " + "%d channels, first board: %d ports\n", + i, sx_nports, boards[0].nports); + rc = sx_init_portstructs(i, sx_nports); + sx_init_drivers(); + if (rc >= 0) sx_initialized++; break; case SXIO_SETDEBUG: @@ -1737,32 +1830,32 @@ static int sx_fw_ioctl (struct inode *inode, struct file *filp, rc = sx_nports; break; default: - printk (KERN_WARNING "Unknown ioctl on firmware device (%x).\n", cmd); + printk(KERN_WARNING "Unknown ioctl on firmware device (%x).\n", + cmd); break; } - func_exit (); + func_exit(); return rc; } - -static void sx_break (struct tty_struct * tty, int flag) +static void sx_break(struct tty_struct *tty, int flag) { struct sx_port *port = tty->driver_data; int rv; - func_enter (); + func_enter(); - if (flag) - rv = sx_send_command (port, HS_START, -1, HS_IDLE_BREAK); - else - rv = sx_send_command (port, HS_STOP, -1, HS_IDLE_OPEN); - if (rv != 1) printk (KERN_ERR "sx: couldn't send break (%x).\n", - read_sx_byte (port->board, CHAN_OFFSET (port, hi_hstat))); + if (flag) + rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK); + else + rv = sx_send_command(port, HS_STOP, -1, HS_IDLE_OPEN); + if (rv != 1) + printk(KERN_ERR "sx: couldn't send break (%x).\n", + read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat))); - func_exit (); + func_exit(); } - static int sx_tiocmget(struct tty_struct *tty, struct file *file) { struct sx_port *port = tty->driver_data; @@ -1770,7 +1863,7 @@ static int sx_tiocmget(struct tty_struct *tty, struct file *file) } static int sx_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) + unsigned int set, unsigned int clear) { struct sx_port *port = tty->driver_data; int rts = -1, dtr = -1; @@ -1789,8 +1882,8 @@ static int sx_tiocmset(struct tty_struct *tty, struct file *file, return 0; } -static int sx_ioctl (struct tty_struct * tty, struct file * filp, - unsigned int cmd, unsigned long arg) +static int sx_ioctl(struct tty_struct *tty, struct file *filp, + unsigned int cmd, unsigned long arg) { int rc; struct sx_port *port = tty->driver_data; @@ -1803,10 +1896,10 @@ static int sx_ioctl (struct tty_struct * tty, struct file * filp, switch (cmd) { case TIOCGSOFTCAR: rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0), - (unsigned __user *) argp); + (unsigned __user *)argp); break; case TIOCSSOFTCAR: - if ((rc = get_user(ival, (unsigned __user *) argp)) == 0) { + if ((rc = get_user(ival, (unsigned __user *)argp)) == 0) { tty->termios->c_cflag = (tty->termios->c_cflag & ~CLOCAL) | (ival ? CLOCAL : 0); @@ -1827,7 +1920,6 @@ static int sx_ioctl (struct tty_struct * tty, struct file * filp, return rc; } - /* The throttle/unthrottle scheme for the Specialix card is different * from other drivers and deserves some explanation. * The Specialix hardware takes care of XON/XOFF @@ -1844,7 +1936,7 @@ static int sx_ioctl (struct tty_struct * tty, struct file * filp, * flow control scheme is in use for that port. -- Simon Allen */ -static void sx_throttle (struct tty_struct * tty) +static void sx_throttle(struct tty_struct *tty) { struct sx_port *port = (struct sx_port *)tty->driver_data; @@ -1852,14 +1944,13 @@ static void sx_throttle (struct tty_struct * tty) /* If the port is using any type of input flow * control then throttle the port. */ - if((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty)) ) { + if ((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty))) { port->gs.flags |= SX_RX_THROTTLE; } func_exit(); } - -static void sx_unthrottle (struct tty_struct * tty) +static void sx_unthrottle(struct tty_struct *tty) { struct sx_port *port = (struct sx_port *)tty->driver_data; @@ -1873,15 +1964,11 @@ static void sx_unthrottle (struct tty_struct * tty) return; } - /* ********************************************************************** * * Here are the initialization routines. * * ********************************************************************** */ - - - -static int sx_init_board (struct sx_board *board) +static int sx_init_board(struct sx_board *board) { int addr; int chans; @@ -1893,36 +1980,38 @@ static int sx_init_board (struct sx_board *board) board->flags |= SX_BOARD_INITIALIZED; - if (read_sx_byte (board, 0)) + if (read_sx_byte(board, 0)) /* CF boards may need this. */ - write_sx_byte(board,0, 0); + write_sx_byte(board, 0, 0); /* This resets the processor again, to make sure it didn't do any foolish things while we were downloading the image */ - if (!sx_reset (board)) + if (!sx_reset(board)) return 0; - sx_start_board (board); - udelay (10); - if (!sx_busy_wait_neq (board, 0, 0xff, 0)) { - printk (KERN_ERR "sx: Ooops. Board won't initialize.\n"); + sx_start_board(board); + udelay(10); + if (!sx_busy_wait_neq(board, 0, 0xff, 0)) { + printk(KERN_ERR "sx: Ooops. Board won't initialize.\n"); return 0; } /* Ok. So now the processor on the card is running. It gathered some info for us... */ - sx_dprintk (SX_DEBUG_INIT, "The sxcard structure:\n"); - if (sx_debug & SX_DEBUG_INIT) my_hd_io (board->base, 0x10); - sx_dprintk (SX_DEBUG_INIT, "the first sx_module structure:\n"); - if (sx_debug & SX_DEBUG_INIT) my_hd_io (board->base + 0x80, 0x30); - - sx_dprintk (SX_DEBUG_INIT, - "init_status: %x, %dk memory, firmware V%x.%02x,\n", - read_sx_byte (board, 0), read_sx_byte(board, 1), - read_sx_byte (board, 5), read_sx_byte(board, 4)); - - if (read_sx_byte (board, 0) == 0xff) { - printk (KERN_INFO "sx: No modules found. Sorry.\n"); + sx_dprintk(SX_DEBUG_INIT, "The sxcard structure:\n"); + if (sx_debug & SX_DEBUG_INIT) + my_hd_io(board->base, 0x10); + sx_dprintk(SX_DEBUG_INIT, "the first sx_module structure:\n"); + if (sx_debug & SX_DEBUG_INIT) + my_hd_io(board->base + 0x80, 0x30); + + sx_dprintk(SX_DEBUG_INIT, "init_status: %x, %dk memory, firmware " + "V%x.%02x,\n", + read_sx_byte(board, 0), read_sx_byte(board, 1), + read_sx_byte(board, 5), read_sx_byte(board, 4)); + + if (read_sx_byte(board, 0) == 0xff) { + printk(KERN_INFO "sx: No modules found. Sorry.\n"); board->nports = 0; return 0; } @@ -1930,82 +2019,97 @@ static int sx_init_board (struct sx_board *board) chans = 0; if (IS_SX_BOARD(board)) { - sx_write_board_word (board, cc_int_count, sx_maxints); + sx_write_board_word(board, cc_int_count, sx_maxints); } else { if (sx_maxints) - sx_write_board_word (board, cc_int_count, SI_PROCESSOR_CLOCK/8/sx_maxints); + sx_write_board_word(board, cc_int_count, + SI_PROCESSOR_CLOCK / 8 / sx_maxints); } /* grab the first module type... */ - /* board->ta_type = mod_compat_type (read_sx_byte (board, 0x80 + 0x08)); */ - board->ta_type = mod_compat_type (sx_read_module_byte (board, 0x80, mc_chip)); + /* board->ta_type = mod_compat_type (read_sx_byte (board, 0x80 + 0x08)); */ + board->ta_type = mod_compat_type(sx_read_module_byte(board, 0x80, + mc_chip)); /* XXX byteorder */ - for (addr = 0x80;addr != 0;addr = read_sx_word (board, addr) & 0x7fff) { - type = sx_read_module_byte (board, addr, mc_chip); - sx_dprintk (SX_DEBUG_INIT, "Module at %x: %d channels\n", - addr, read_sx_byte (board, addr + 2)); - - chans += sx_read_module_byte (board, addr, mc_type); - - sx_dprintk (SX_DEBUG_INIT, "module is an %s, which has %s/%s panels\n", - mod_type_s (type), - pan_type_s (sx_read_module_byte (board, addr, mc_mods) & 0xf), - pan_type_s (sx_read_module_byte (board, addr, mc_mods) >> 4)); - - sx_dprintk (SX_DEBUG_INIT, "CD1400 versions: %x/%x, ASIC version: %x\n", - sx_read_module_byte (board, addr, mc_rev1), - sx_read_module_byte (board, addr, mc_rev2), - sx_read_module_byte (board, addr, mc_mtaasic_rev)); + for (addr = 0x80; addr != 0; addr = read_sx_word(board, addr) & 0x7fff){ + type = sx_read_module_byte(board, addr, mc_chip); + sx_dprintk(SX_DEBUG_INIT, "Module at %x: %d channels\n", + addr, read_sx_byte(board, addr + 2)); + + chans += sx_read_module_byte(board, addr, mc_type); + + sx_dprintk(SX_DEBUG_INIT, "module is an %s, which has %s/%s " + "panels\n", + mod_type_s(type), + pan_type_s(sx_read_module_byte(board, addr, + mc_mods) & 0xf), + pan_type_s(sx_read_module_byte(board, addr, + mc_mods) >> 4)); + + sx_dprintk(SX_DEBUG_INIT, "CD1400 versions: %x/%x, ASIC " + "version: %x\n", + sx_read_module_byte(board, addr, mc_rev1), + sx_read_module_byte(board, addr, mc_rev2), + sx_read_module_byte(board, addr, mc_mtaasic_rev)); /* The following combinations are illegal: It should theoretically work, but timing problems make the bus HANG. */ - if (mod_compat_type (type) != board->ta_type) { - printk (KERN_ERR "sx: This is an invalid configuration.\n" - "Don't mix TA/MTA/SXDC on the same hostadapter.\n"); - chans=0; + if (mod_compat_type(type) != board->ta_type) { + printk(KERN_ERR "sx: This is an invalid " + "configuration.\nDon't mix TA/MTA/SXDC on the " + "same hostadapter.\n"); + chans = 0; break; } - if ((IS_EISA_BOARD(board) || - IS_SI_BOARD(board)) && (mod_compat_type(type) == 4)) { - printk (KERN_ERR "sx: This is an invalid configuration.\n" - "Don't use SXDCs on an SI/XIO adapter.\n"); - chans=0; + if ((IS_EISA_BOARD(board) || + IS_SI_BOARD(board)) && + (mod_compat_type(type) == 4)) { + printk(KERN_ERR "sx: This is an invalid " + "configuration.\nDon't use SXDCs on an SI/XIO " + "adapter.\n"); + chans = 0; break; } -#if 0 /* Problem fixed: firmware 3.05 */ +#if 0 /* Problem fixed: firmware 3.05 */ if (IS_SX_BOARD(board) && (type == TA8)) { /* There are some issues with the firmware and the DCD/RTS lines. It might work if you tie them together or something. - It might also work if you get a newer sx_firmware. Therefore + It might also work if you get a newer sx_firmware. Therefore this is just a warning. */ - printk (KERN_WARNING "sx: The SX host doesn't work too well " - "with the TA8 adapters.\nSpecialix is working on it.\n"); + printk(KERN_WARNING + "sx: The SX host doesn't work too well " + "with the TA8 adapters.\nSpecialix is working on it.\n"); } #endif } if (chans) { - /* board->flags |= SX_BOARD_PRESENT; */ - if(board->irq > 0) { + if (board->irq > 0) { /* fixed irq, probably PCI */ - if(sx_irqmask & (1 << board->irq)) { /* may we use this irq? */ - if(request_irq(board->irq, sx_interrupt, IRQF_SHARED | IRQF_DISABLED, "sx", board)) { - printk(KERN_ERR "sx: Cannot allocate irq %d.\n", board->irq); + if (sx_irqmask & (1 << board->irq)) { /* may we use this irq? */ + if (request_irq(board->irq, sx_interrupt, + IRQF_SHARED | IRQF_DISABLED, + "sx", board)) { + printk(KERN_ERR "sx: Cannot allocate " + "irq %d.\n", board->irq); board->irq = 0; } } else board->irq = 0; - } else if(board->irq < 0 && sx_irqmask) { + } else if (board->irq < 0 && sx_irqmask) { /* auto-allocate irq */ int irqnr; - int irqmask = sx_irqmask & (IS_SX_BOARD(board) ? SX_ISA_IRQ_MASK : SI2_ISA_IRQ_MASK); - for(irqnr = 15; irqnr > 0; irqnr--) - if(irqmask & (1 << irqnr)) - if(! request_irq(irqnr, sx_interrupt, IRQF_SHARED | IRQF_DISABLED, "sx", board)) + int irqmask = sx_irqmask & (IS_SX_BOARD(board) ? + SX_ISA_IRQ_MASK : SI2_ISA_IRQ_MASK); + for (irqnr = 15; irqnr > 0; irqnr--) + if (irqmask & (1 << irqnr)) + if (!request_irq(irqnr, sx_interrupt, + IRQF_SHARED | IRQF_DISABLED, + "sx", board)) break; - if(! irqnr) + if (!irqnr) printk(KERN_ERR "sx: Cannot allocate IRQ.\n"); board->irq = irqnr; } else @@ -2013,52 +2117,48 @@ static int sx_init_board (struct sx_board *board) if (board->irq) { /* Found a valid interrupt, start up interrupts! */ - sx_dprintk (SX_DEBUG_INIT, "Using irq %d.\n", board->irq); - sx_start_interrupts (board); + sx_dprintk(SX_DEBUG_INIT, "Using irq %d.\n", + board->irq); + sx_start_interrupts(board); board->poll = sx_slowpoll; board->flags |= SX_IRQ_ALLOCATED; } else { /* no irq: setup board for polled operation */ board->poll = sx_poll; - sx_dprintk (SX_DEBUG_INIT, "Using poll-interval %d.\n", board->poll); + sx_dprintk(SX_DEBUG_INIT, "Using poll-interval %d.\n", + board->poll); } - /* The timer should be initialized anyway: That way we can safely - del_timer it when the module is unloaded. */ - init_timer (&board->timer); + /* The timer should be initialized anyway: That way we can + safely del_timer it when the module is unloaded. */ + setup_timer(&board->timer, sx_pollfunc, (unsigned long)board); - if (board->poll) { - board->timer.data = (unsigned long) board; - board->timer.function = sx_pollfunc; - board->timer.expires = jiffies + board->poll; - add_timer (&board->timer); - } + if (board->poll) + mod_timer(&board->timer, jiffies + board->poll); } else { board->irq = 0; } board->nports = chans; - sx_dprintk (SX_DEBUG_INIT, "returning %d ports.", board->nports); + sx_dprintk(SX_DEBUG_INIT, "returning %d ports.", board->nports); func_exit(); return chans; } - -static void printheader(void) +static void __devinit printheader(void) { static int header_printed; if (!header_printed) { - printk (KERN_INFO "Specialix SX driver " - "(C) 1998/1999 R.E.Wolff@BitWizard.nl \n"); - printk (KERN_INFO "sx: version %s\n", RCS_ID); + printk(KERN_INFO "Specialix SX driver " + "(C) 1998/1999 R.E.Wolff@BitWizard.nl\n"); + printk(KERN_INFO "sx: version " __stringify(SX_VERSION) "\n"); header_printed = 1; } } - -static int probe_sx (struct sx_board *board) +static int __devinit probe_sx(struct sx_board *board) { struct vpd_prom vpdp; char *p; @@ -2066,51 +2166,57 @@ static int probe_sx (struct sx_board *board) func_enter(); - if (!IS_CF_BOARD (board)) { - sx_dprintk (SX_DEBUG_PROBE, "Going to verify vpd prom at %p.\n", - board->base + SX_VPD_ROM); + if (!IS_CF_BOARD(board)) { + sx_dprintk(SX_DEBUG_PROBE, "Going to verify vpd prom at %p.\n", + board->base + SX_VPD_ROM); if (sx_debug & SX_DEBUG_PROBE) my_hd_io(board->base + SX_VPD_ROM, 0x40); - p = (char *) &vpdp; - for (i=0;i< sizeof (struct vpd_prom);i++) - *p++ = read_sx_byte (board, SX_VPD_ROM + i*2); + p = (char *)&vpdp; + for (i = 0; i < sizeof(struct vpd_prom); i++) + *p++ = read_sx_byte(board, SX_VPD_ROM + i * 2); if (sx_debug & SX_DEBUG_PROBE) - my_hd (&vpdp, 0x20); + my_hd(&vpdp, 0x20); - sx_dprintk (SX_DEBUG_PROBE, "checking identifier...\n"); + sx_dprintk(SX_DEBUG_PROBE, "checking identifier...\n"); - if (strncmp (vpdp.identifier, SX_VPD_IDENT_STRING, 16) != 0) { - sx_dprintk (SX_DEBUG_PROBE, "Got non-SX identifier: '%s'\n", - vpdp.identifier); + if (strncmp(vpdp.identifier, SX_VPD_IDENT_STRING, 16) != 0) { + sx_dprintk(SX_DEBUG_PROBE, "Got non-SX identifier: " + "'%s'\n", vpdp.identifier); return 0; } } - printheader (); - - if (!IS_CF_BOARD (board)) { - printk (KERN_DEBUG "sx: Found an SX board at %lx\n", board->hw_base); - printk (KERN_DEBUG "sx: hw_rev: %d, assembly level: %d, uniq ID:%08x, ", - vpdp.hwrev, vpdp.hwass, vpdp.uniqid); - printk ( "Manufactured: %d/%d\n", - 1970 + vpdp.myear, vpdp.mweek); + printheader(); + if (!IS_CF_BOARD(board)) { + printk(KERN_DEBUG "sx: Found an SX board at %lx\n", + board->hw_base); + printk(KERN_DEBUG "sx: hw_rev: %d, assembly level: %d, " + "uniq ID:%08x, ", + vpdp.hwrev, vpdp.hwass, vpdp.uniqid); + printk("Manufactured: %d/%d\n", 1970 + vpdp.myear, vpdp.mweek); - if ((((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) != SX_PCI_UNIQUEID1) && - (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) != SX_ISA_UNIQUEID1)) { - /* This might be a bit harsh. This was the primary reason the - SX/ISA card didn't work at first... */ - printk (KERN_ERR "sx: Hmm. Not an SX/PCI or SX/ISA card. Sorry: giving up.\n"); + if ((((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) != + SX_PCI_UNIQUEID1) && (((vpdp.uniqid >> 24) & + SX_UNIQUEID_MASK) != SX_ISA_UNIQUEID1)) { + /* This might be a bit harsh. This was the primary + reason the SX/ISA card didn't work at first... */ + printk(KERN_ERR "sx: Hmm. Not an SX/PCI or SX/ISA " + "card. Sorry: giving up.\n"); return (0); } - if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) == SX_ISA_UNIQUEID1) { + if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) == + SX_ISA_UNIQUEID1) { if (((unsigned long)board->hw_base) & 0x8000) { - printk (KERN_WARNING "sx: Warning: There may be hardware problems with the card at %lx.\n", board->hw_base); - printk (KERN_WARNING "sx: Read sx.txt for more info.\n"); + printk(KERN_WARNING "sx: Warning: There may be " + "hardware problems with the card at " + "%lx.\n", board->hw_base); + printk(KERN_WARNING "sx: Read sx.txt for more " + "info.\n"); } } } @@ -2118,17 +2224,15 @@ static int probe_sx (struct sx_board *board) board->nports = -1; /* This resets the processor, and keeps it off the bus. */ - if (!sx_reset (board)) + if (!sx_reset(board)) return 0; - sx_dprintk (SX_DEBUG_INIT, "reset the board...\n"); - - board->flags |= SX_BOARD_PRESENT; + sx_dprintk(SX_DEBUG_INIT, "reset the board...\n"); func_exit(); return 1; } - +#if defined(CONFIG_ISA) || defined(CONFIG_EISA) /* Specialix probes for this card at 32k increments from 640k to 16M. I consider machines with less than 16M unlikely nowadays, so I'm @@ -2136,28 +2240,27 @@ static int probe_sx (struct sx_board *board) card. 0xe0000 and 0xf0000 are taken by the BIOS. That only leaves 0xc0000, 0xc8000, 0xd0000 and 0xd8000 . */ -static int probe_si (struct sx_board *board) +static int __devinit probe_si(struct sx_board *board) { int i; func_enter(); - sx_dprintk (SX_DEBUG_PROBE, "Going to verify SI signature hw %lx at %p.\n", board->hw_base, - board->base + SI2_ISA_ID_BASE); + sx_dprintk(SX_DEBUG_PROBE, "Going to verify SI signature hw %lx at " + "%p.\n", board->hw_base, board->base + SI2_ISA_ID_BASE); if (sx_debug & SX_DEBUG_PROBE) my_hd_io(board->base + SI2_ISA_ID_BASE, 0x8); if (!IS_EISA_BOARD(board)) { - if( IS_SI1_BOARD(board) ) - { - for (i=0;i<8;i++) { - write_sx_byte (board, SI2_ISA_ID_BASE+7-i,i); - + if (IS_SI1_BOARD(board)) { + for (i = 0; i < 8; i++) { + write_sx_byte(board, SI2_ISA_ID_BASE + 7 - i,i); + } } - } - for (i=0;i<8;i++) { - if ((read_sx_byte (board, SI2_ISA_ID_BASE+7-i) & 7) != i) { - func_exit (); + for (i = 0; i < 8; i++) { + if ((read_sx_byte(board, SI2_ISA_ID_BASE + 7 - i) & 7) + != i) { + func_exit(); return 0; } } @@ -2167,20 +2270,20 @@ static int probe_si (struct sx_board *board) but to prevent trouble, we'd better double check that we don't have an SI1 board when we're probing for an SI2 board.... */ - write_sx_byte (board, SI2_ISA_ID_BASE,0x10); - if ( IS_SI1_BOARD(board)) { + write_sx_byte(board, SI2_ISA_ID_BASE, 0x10); + if (IS_SI1_BOARD(board)) { /* This should be an SI1 board, which has this location writable... */ - if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10) { - func_exit (); - return 0; + if (read_sx_byte(board, SI2_ISA_ID_BASE) != 0x10) { + func_exit(); + return 0; } } else { /* This should be an SI2 board, which has the bottom 3 bits non-writable... */ - if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10) { - func_exit (); - return 0; + if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) { + func_exit(); + return 0; } } @@ -2188,45 +2291,44 @@ static int probe_si (struct sx_board *board) but to prevent trouble, we'd better double check that we don't have an SI1 board when we're probing for an SI2 board.... */ - write_sx_byte (board, SI2_ISA_ID_BASE,0x10); - if ( IS_SI1_BOARD(board)) { + write_sx_byte(board, SI2_ISA_ID_BASE, 0x10); + if (IS_SI1_BOARD(board)) { /* This should be an SI1 board, which has this location writable... */ - if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10) { + if (read_sx_byte(board, SI2_ISA_ID_BASE) != 0x10) { func_exit(); - return 0; + return 0; } } else { /* This should be an SI2 board, which has the bottom 3 bits non-writable... */ - if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10) { - func_exit (); - return 0; + if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) { + func_exit(); + return 0; } } - printheader (); + printheader(); - printk (KERN_DEBUG "sx: Found an SI board at %lx\n", board->hw_base); + printk(KERN_DEBUG "sx: Found an SI board at %lx\n", board->hw_base); /* Compared to the SX boards, it is a complete guess as to what - this card is up to... */ + this card is up to... */ board->nports = -1; /* This resets the processor, and keeps it off the bus. */ - if (!sx_reset (board)) + if (!sx_reset(board)) return 0; - sx_dprintk (SX_DEBUG_INIT, "reset the board...\n"); - - board->flags |= SX_BOARD_PRESENT; + sx_dprintk(SX_DEBUG_INIT, "reset the board...\n"); func_exit(); return 1; } +#endif static const struct tty_operations sx_ops = { .break_ctl = sx_break, - .open = sx_open, + .open = sx_open, .close = gs_close, .write = gs_write, .put_char = gs_put_char, @@ -2261,34 +2363,23 @@ static int sx_init_drivers(void) sx_driver->type = TTY_DRIVER_TYPE_SERIAL; sx_driver->subtype = SERIAL_TYPE_NORMAL; sx_driver->init_termios = tty_std_termios; - sx_driver->init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; + sx_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + sx_driver->init_termios.c_ispeed = 9600; + sx_driver->init_termios.c_ospeed = 9600; sx_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(sx_driver, &sx_ops); if ((error = tty_register_driver(sx_driver))) { put_tty_driver(sx_driver); printk(KERN_ERR "sx: Couldn't register sx driver, error = %d\n", - error); + error); return 1; } func_exit(); return 0; } - -static void * ckmalloc (int size) -{ - void *p; - - p = kmalloc(size, GFP_KERNEL); - if (p) - memset(p, 0, size); - return p; -} - - -static int sx_init_portstructs (int nboards, int nports) +static int sx_init_portstructs(int nboards, int nports) { struct sx_board *board; struct sx_port *port; @@ -2299,8 +2390,9 @@ static int sx_init_portstructs (int nboards, int nports) func_enter(); /* Many drivers statically allocate the maximum number of ports - There is no reason not to allocate them dynamically. Is there? -- REW */ - sx_ports = ckmalloc(nports * sizeof (struct sx_port)); + There is no reason not to allocate them dynamically. + Is there? -- REW */ + sx_ports = kcalloc(nports, sizeof(struct sx_port), GFP_KERNEL); if (!sx_ports) return -ENOMEM; @@ -2308,10 +2400,10 @@ static int sx_init_portstructs (int nboards, int nports) for (i = 0; i < nboards; i++) { board = &boards[i]; board->ports = port; - for (j=0; j < boards[i].nports;j++) { - sx_dprintk (SX_DEBUG_INIT, "initing port %d\n", j); + for (j = 0; j < boards[i].nports; j++) { + sx_dprintk(SX_DEBUG_INIT, "initing port %d\n", j); port->gs.magic = SX_MAGIC; - port->gs.close_delay = HZ/2; + port->gs.close_delay = HZ / 2; port->gs.closing_wait = 30 * HZ; port->board = board; port->gs.rd = &sx_real_driver; @@ -2323,8 +2415,8 @@ static int sx_init_portstructs (int nboards, int nports) * Initializing wait queue */ init_waitqueue_head(&port->gs.open_wait); - init_waitqueue_head(&port->gs.close_wait); - + init_waitqueue_head(&port->gs.close_wait); + port++; } } @@ -2335,28 +2427,36 @@ static int sx_init_portstructs (int nboards, int nports) board = &boards[i]; board->port_base = portno; /* Possibly the configuration was rejected. */ - sx_dprintk (SX_DEBUG_PROBE, "Board has %d channels\n", board->nports); - if (board->nports <= 0) continue; + sx_dprintk(SX_DEBUG_PROBE, "Board has %d channels\n", + board->nports); + if (board->nports <= 0) + continue; /* XXX byteorder ?? */ - for (addr = 0x80;addr != 0;addr = read_sx_word (board, addr) & 0x7fff) { - chans = sx_read_module_byte (board, addr, mc_type); - sx_dprintk (SX_DEBUG_PROBE, "Module at %x: %d channels\n", addr, chans); - sx_dprintk (SX_DEBUG_PROBE, "Port at"); - for (j=0;j<chans;j++) { - /* The "sx-way" is the way it SHOULD be done. That way in the - future, the firmware may for example pack the structures a bit - more efficient. Neil tells me it isn't going to happen anytime - soon though. */ + for (addr = 0x80; addr != 0; + addr = read_sx_word(board, addr) & 0x7fff) { + chans = sx_read_module_byte(board, addr, mc_type); + sx_dprintk(SX_DEBUG_PROBE, "Module at %x: %d " + "channels\n", addr, chans); + sx_dprintk(SX_DEBUG_PROBE, "Port at"); + for (j = 0; j < chans; j++) { + /* The "sx-way" is the way it SHOULD be done. + That way in the future, the firmware may for + example pack the structures a bit more + efficient. Neil tells me it isn't going to + happen anytime soon though. */ if (IS_SX_BOARD(board)) - port->ch_base = sx_read_module_word (board, addr+j*2, mc_chan_pointer); + port->ch_base = sx_read_module_word( + board, addr + j * 2, + mc_chan_pointer); else - port->ch_base = addr + 0x100 + 0x300*j; + port->ch_base = addr + 0x100 + 0x300 *j; - sx_dprintk (SX_DEBUG_PROBE, " %x", port->ch_base); + sx_dprintk(SX_DEBUG_PROBE, " %x", + port->ch_base); port->line = portno++; port++; } - sx_dprintk (SX_DEBUG_PROBE, "\n"); + sx_dprintk(SX_DEBUG_PROBE, "\n"); } /* This has to be done earlier. */ /* board->flags |= SX_BOARD_INITIALIZED; */ @@ -2366,6 +2466,17 @@ static int sx_init_portstructs (int nboards, int nports) return 0; } +static unsigned int sx_find_free_board(void) +{ + unsigned int i; + + for (i = 0; i < SX_NBOARDS; i++) + if (!(boards[i].flags & SX_BOARD_PRESENT)) + break; + + return i; +} + static void __exit sx_release_drivers(void) { func_enter(); @@ -2374,7 +2485,122 @@ static void __exit sx_release_drivers(void) func_exit(); } -#ifdef CONFIG_PCI +static void __devexit sx_remove_card(struct sx_board *board, + struct pci_dev *pdev) +{ + if (board->flags & SX_BOARD_INITIALIZED) { + /* The board should stop messing with us. (actually I mean the + interrupt) */ + sx_reset(board); + if ((board->irq) && (board->flags & SX_IRQ_ALLOCATED)) + free_irq(board->irq, board); + + /* It is safe/allowed to del_timer a non-active timer */ + del_timer(&board->timer); + if (pdev) { + pci_iounmap(pdev, board->base); + pci_release_region(pdev, IS_CF_BOARD(board) ? 3 : 2); + } else { + iounmap(board->base); + release_region(board->hw_base, board->hw_len); + } + + board->flags &= ~(SX_BOARD_INITIALIZED | SX_BOARD_PRESENT); + } +} + +#ifdef CONFIG_EISA + +static int __devinit sx_eisa_probe(struct device *dev) +{ + struct eisa_device *edev = to_eisa_device(dev); + struct sx_board *board; + unsigned long eisa_slot = edev->base_addr; + unsigned int i; + int retval = -EIO; + + mutex_lock(&sx_boards_lock); + i = sx_find_free_board(); + if (i == SX_NBOARDS) { + mutex_unlock(&sx_boards_lock); + goto err; + } + board = &boards[i]; + board->flags |= SX_BOARD_PRESENT; + mutex_unlock(&sx_boards_lock); + + dev_info(dev, "XIO : Signature found in EISA slot %lu, " + "Product %d Rev %d (REPORT THIS TO LKLM)\n", + eisa_slot >> 12, + inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 2), + inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 3)); + + board->eisa_base = eisa_slot; + board->flags &= ~SX_BOARD_TYPE; + board->flags |= SI_EISA_BOARD; + + board->hw_base = ((inb(eisa_slot + 0xc01) << 8) + + inb(eisa_slot + 0xc00)) << 16; + board->hw_len = SI2_EISA_WINDOW_LEN; + if (!request_region(board->hw_base, board->hw_len, "sx")) { + dev_err(dev, "can't request region\n"); + goto err_flag; + } + board->base2 = + board->base = ioremap(board->hw_base, SI2_EISA_WINDOW_LEN); + if (!board->base) { + dev_err(dev, "can't remap memory\n"); + goto err_reg; + } + + sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %lx\n", board->hw_base); + sx_dprintk(SX_DEBUG_PROBE, "base: %p\n", board->base); + board->irq = inb(eisa_slot + 0xc02) >> 4; + sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq); + + if (!probe_si(board)) + goto err_unmap; + + dev_set_drvdata(dev, board); + + return 0; +err_unmap: + iounmap(board->base); +err_reg: + release_region(board->hw_base, board->hw_len); +err_flag: + board->flags &= ~SX_BOARD_PRESENT; +err: + return retval; +} + +static int __devexit sx_eisa_remove(struct device *dev) +{ + struct sx_board *board = dev_get_drvdata(dev); + + sx_remove_card(board, NULL); + + return 0; +} + +static struct eisa_device_id sx_eisa_tbl[] = { + { "SLX" }, + { "" } +}; + +MODULE_DEVICE_TABLE(eisa, sx_eisa_tbl); + +static struct eisa_driver sx_eisadriver = { + .id_table = sx_eisa_tbl, + .driver = { + .name = "sx", + .probe = sx_eisa_probe, + .remove = __devexit_p(sx_eisa_remove), + } +}; + +#endif + /******************************************************** * Setting bit 17 in the CNTRL register of the PLX 9050 * * chip forces a retry on writes while a read is pending.* @@ -2386,233 +2612,265 @@ static void __exit sx_release_drivers(void) EEprom. As the bit is read/write for the CPU, we can fix it here, if we detect that it isn't set correctly. -- REW */ -static void fix_sx_pci (struct pci_dev *pdev, struct sx_board *board) +static void __devinit fix_sx_pci(struct pci_dev *pdev, struct sx_board *board) { unsigned int hwbase; void __iomem *rebase; unsigned int t; -#define CNTRL_REG_OFFSET 0x50 -#define CNTRL_REG_GOODVALUE 0x18260000 +#define CNTRL_REG_OFFSET 0x50 +#define CNTRL_REG_GOODVALUE 0x18260000 pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase); hwbase &= PCI_BASE_ADDRESS_MEM_MASK; rebase = ioremap(hwbase, 0x80); - t = readl (rebase + CNTRL_REG_OFFSET); + t = readl(rebase + CNTRL_REG_OFFSET); if (t != CNTRL_REG_GOODVALUE) { - printk (KERN_DEBUG "sx: performing cntrl reg fix: %08x -> %08x\n", t, CNTRL_REG_GOODVALUE); - writel (CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET); + printk(KERN_DEBUG "sx: performing cntrl reg fix: %08x -> " + "%08x\n", t, CNTRL_REG_GOODVALUE); + writel(CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET); } iounmap(rebase); } -#endif - -static int __init sx_init(void) +static int __devinit sx_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - int i; - int found = 0; - int eisa_slot; struct sx_board *board; + unsigned int i, reg; + int retval = -EIO; -#ifdef CONFIG_PCI - struct pci_dev *pdev = NULL; - unsigned int tint; - unsigned short tshort; -#endif + mutex_lock(&sx_boards_lock); + i = sx_find_free_board(); + if (i == SX_NBOARDS) { + mutex_unlock(&sx_boards_lock); + goto err; + } + board = &boards[i]; + board->flags |= SX_BOARD_PRESENT; + mutex_unlock(&sx_boards_lock); - func_enter(); - sx_dprintk (SX_DEBUG_INIT, "Initing sx module... (sx_debug=%d)\n", sx_debug); - if (abs ((long) (&sx_debug) - sx_debug) < 0x10000) { - printk (KERN_WARNING "sx: sx_debug is an address, instead of a value. " - "Assuming -1.\n"); - printk ("(%p)\n", &sx_debug); - sx_debug=-1; + retval = pci_enable_device(pdev); + if (retval) + goto err_flag; + + board->flags &= ~SX_BOARD_TYPE; + board->flags |= (pdev->subsystem_vendor == 0x200) ? SX_PCI_BOARD : + SX_CFPCI_BOARD; + + /* CF boards use base address 3.... */ + reg = IS_CF_BOARD(board) ? 3 : 2; + retval = pci_request_region(pdev, reg, "sx"); + if (retval) { + dev_err(&pdev->dev, "can't request region\n"); + goto err_flag; + } + board->hw_base = pci_resource_start(pdev, reg); + board->base2 = + board->base = pci_iomap(pdev, reg, WINDOW_LEN(board)); + if (!board->base) { + dev_err(&pdev->dev, "ioremap failed\n"); + goto err_reg; } - if (misc_register(&sx_fw_device) < 0) { - printk(KERN_ERR "SX: Unable to register firmware loader driver.\n"); - return -EIO; + /* Most of the stuff on the CF board is offset by 0x18000 .... */ + if (IS_CF_BOARD(board)) + board->base += 0x18000; + + board->irq = pdev->irq; + + dev_info(&pdev->dev, "Got a specialix card: %p(%d) %x.\n", board->base, + board->irq, board->flags); + + if (!probe_sx(board)) { + retval = -EIO; + goto err_unmap; } -#ifdef CONFIG_PCI - while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, - PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, - pdev))) { - if (pci_enable_device(pdev)) - continue; + fix_sx_pci(pdev, board); - /* Specialix has a whole bunch of cards with - 0x2000 as the device ID. They say its because - the standard requires it. Stupid standard. */ - /* It seems that reading a word doesn't work reliably on 2.0. - Also, reading a non-aligned dword doesn't work. So we read the - whole dword at 0x2c and extract the word at 0x2e (SUBSYSTEM_ID) - ourselves */ - /* I don't know why the define doesn't work, constant 0x2c does --REW */ - pci_read_config_dword (pdev, 0x2c, &tint); - tshort = (tint >> 16) & 0xffff; - sx_dprintk (SX_DEBUG_PROBE, "Got a specialix card: %x.\n", tint); - /* sx_dprintk (SX_DEBUG_PROBE, "pdev = %d/%d (%x)\n", pdev, tint); */ - if ((tshort != 0x0200) && (tshort != 0x0300)) { - sx_dprintk (SX_DEBUG_PROBE, "But it's not an SX card (%d)...\n", - tshort); - continue; - } - board = &boards[found]; + pci_set_drvdata(pdev, board); - board->flags &= ~SX_BOARD_TYPE; - board->flags |= (tshort == 0x200)?SX_PCI_BOARD: - SX_CFPCI_BOARD; - - /* CF boards use base address 3.... */ - if (IS_CF_BOARD (board)) - board->hw_base = pci_resource_start (pdev, 3); - else - board->hw_base = pci_resource_start (pdev, 2); - board->base2 = - board->base = ioremap(board->hw_base, WINDOW_LEN (board)); - if (!board->base) { - printk(KERN_ERR "ioremap failed\n"); - /* XXX handle error */ - } + return 0; +err_unmap: + pci_iounmap(pdev, board->base); +err_reg: + pci_release_region(pdev, reg); +err_flag: + board->flags &= ~SX_BOARD_PRESENT; +err: + return retval; +} - /* Most of the stuff on the CF board is offset by - 0x18000 .... */ - if (IS_CF_BOARD (board)) board->base += 0x18000; +static void __devexit sx_pci_remove(struct pci_dev *pdev) +{ + struct sx_board *board = pci_get_drvdata(pdev); - board->irq = pdev->irq; + sx_remove_card(board, pdev); +} - sx_dprintk (SX_DEBUG_PROBE, "Got a specialix card: %x/%p(%d) %x.\n", - tint, boards[found].base, board->irq, board->flags); +/* Specialix has a whole bunch of cards with 0x2000 as the device ID. They say + its because the standard requires it. So check for SUBVENDOR_ID. */ +static struct pci_device_id sx_pci_tbl[] = { + { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, + .subvendor = 0x0200,.subdevice = PCI_ANY_ID }, + { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, + .subvendor = 0x0300,.subdevice = PCI_ANY_ID }, + { 0 } +}; - if (probe_sx (board)) { - found++; - fix_sx_pci (pdev, board); - } else - iounmap(board->base2); - } +MODULE_DEVICE_TABLE(pci, sx_pci_tbl); + +static struct pci_driver sx_pcidriver = { + .name = "sx", + .id_table = sx_pci_tbl, + .probe = sx_pci_probe, + .remove = __devexit_p(sx_pci_remove) +}; + +static int __init sx_init(void) +{ +#ifdef CONFIG_EISA + int retval1; #endif +#ifdef CONFIG_ISA + struct sx_board *board; + unsigned int i; +#endif + unsigned int found = 0; + int retval; + + func_enter(); + sx_dprintk(SX_DEBUG_INIT, "Initing sx module... (sx_debug=%d)\n", + sx_debug); + if (abs((long)(&sx_debug) - sx_debug) < 0x10000) { + printk(KERN_WARNING "sx: sx_debug is an address, instead of a " + "value. Assuming -1.\n(%p)\n", &sx_debug); + sx_debug = -1; + } - for (i=0;i<NR_SX_ADDRS;i++) { + if (misc_register(&sx_fw_device) < 0) { + printk(KERN_ERR "SX: Unable to register firmware loader " + "driver.\n"); + return -EIO; + } +#ifdef CONFIG_ISA + for (i = 0; i < NR_SX_ADDRS; i++) { board = &boards[found]; board->hw_base = sx_probe_addrs[i]; + board->hw_len = SX_WINDOW_LEN; + if (!request_region(board->hw_base, board->hw_len, "sx")) + continue; board->base2 = - board->base = ioremap(board->hw_base, SX_WINDOW_LEN); + board->base = ioremap(board->hw_base, board->hw_len); + if (!board->base) + goto err_sx_reg; board->flags &= ~SX_BOARD_TYPE; - board->flags |= SX_ISA_BOARD; - board->irq = sx_irqmask?-1:0; + board->flags |= SX_ISA_BOARD; + board->irq = sx_irqmask ? -1 : 0; - if (probe_sx (board)) { + if (probe_sx(board)) { + board->flags |= SX_BOARD_PRESENT; found++; } else { iounmap(board->base); +err_sx_reg: + release_region(board->hw_base, board->hw_len); } } - for (i=0;i<NR_SI_ADDRS;i++) { + for (i = 0; i < NR_SI_ADDRS; i++) { board = &boards[found]; board->hw_base = si_probe_addrs[i]; + board->hw_len = SI2_ISA_WINDOW_LEN; + if (!request_region(board->hw_base, board->hw_len, "sx")) + continue; board->base2 = - board->base = ioremap(board->hw_base, SI2_ISA_WINDOW_LEN); + board->base = ioremap(board->hw_base, board->hw_len); + if (!board->base) + goto err_si_reg; board->flags &= ~SX_BOARD_TYPE; - board->flags |= SI_ISA_BOARD; - board->irq = sx_irqmask ?-1:0; + board->flags |= SI_ISA_BOARD; + board->irq = sx_irqmask ? -1 : 0; - if (probe_si (board)) { + if (probe_si(board)) { + board->flags |= SX_BOARD_PRESENT; found++; } else { - iounmap (board->base); + iounmap(board->base); +err_si_reg: + release_region(board->hw_base, board->hw_len); } } - for (i=0;i<NR_SI1_ADDRS;i++) { + for (i = 0; i < NR_SI1_ADDRS; i++) { board = &boards[found]; board->hw_base = si1_probe_addrs[i]; + board->hw_len = SI1_ISA_WINDOW_LEN; + if (!request_region(board->hw_base, board->hw_len, "sx")) + continue; board->base2 = - board->base = ioremap(board->hw_base, SI1_ISA_WINDOW_LEN); + board->base = ioremap(board->hw_base, board->hw_len); + if (!board->base) + goto err_si1_reg; board->flags &= ~SX_BOARD_TYPE; - board->flags |= SI1_ISA_BOARD; - board->irq = sx_irqmask ?-1:0; + board->flags |= SI1_ISA_BOARD; + board->irq = sx_irqmask ? -1 : 0; - if (probe_si (board)) { + if (probe_si(board)) { + board->flags |= SX_BOARD_PRESENT; found++; } else { - iounmap (board->base); + iounmap(board->base); +err_si1_reg: + release_region(board->hw_base, board->hw_len); } } +#endif +#ifdef CONFIG_EISA + retval1 = eisa_driver_register(&sx_eisadriver); +#endif + retval = pci_register_driver(&sx_pcidriver); - sx_dprintk(SX_DEBUG_PROBE, "Probing for EISA cards\n"); - for(eisa_slot=0x1000; eisa_slot<0x10000; eisa_slot+=0x1000) - { - if((inb(eisa_slot+0xc80)==0x4d) && - (inb(eisa_slot+0xc81)==0x98)) - { - sx_dprintk(SX_DEBUG_PROBE, "%s : Signature found in EISA slot %d, Product %d Rev %d\n", - "XIO", (eisa_slot>>12), inb(eisa_slot+0xc82), inb(eisa_slot+0xc83)); - - board = &boards[found]; - board->eisa_base = eisa_slot; - board->flags &= ~SX_BOARD_TYPE; - board->flags |= SI_EISA_BOARD; - - board->hw_base = (((inb(0xc01+eisa_slot) << 8) + inb(0xc00+eisa_slot)) << 16); - board->base2 = - board->base = ioremap(board->hw_base, SI2_EISA_WINDOW_LEN); - - sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %lx\n", board->hw_base); - sx_dprintk(SX_DEBUG_PROBE, "base: %p\n", board->base); - board->irq = inb(board->eisa_base+0xc02)>>4; - sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq); - - probe_si(board); - - found++; - } - } if (found) { - printk (KERN_INFO "sx: total of %d boards detected.\n", found); - } else { - misc_deregister(&sx_fw_device); + printk(KERN_INFO "sx: total of %d boards detected.\n", found); + retval = 0; + } else if (retval) { +#ifdef CONFIG_EISA + retval = retval1; + if (retval1) +#endif + misc_deregister(&sx_fw_device); } func_exit(); - return found?0:-EIO; + return retval; } - -static void __exit sx_exit (void) +static void __exit sx_exit(void) { - int i; - struct sx_board *board; + int i; func_enter(); - for (i = 0; i < SX_NBOARDS; i++) { - board = &boards[i]; - if (board->flags & SX_BOARD_INITIALIZED) { - sx_dprintk (SX_DEBUG_CLEANUP, "Cleaning up board at %p\n", board->base); - /* The board should stop messing with us. - (actually I mean the interrupt) */ - sx_reset (board); - if ((board->irq) && (board->flags & SX_IRQ_ALLOCATED)) - free_irq (board->irq, board); - - /* It is safe/allowed to del_timer a non-active timer */ - del_timer (& board->timer); - iounmap(board->base); - } - } +#ifdef CONFIG_EISA + eisa_driver_unregister(&sx_eisadriver); +#endif + pci_unregister_driver(&sx_pcidriver); + + for (i = 0; i < SX_NBOARDS; i++) + sx_remove_card(&boards[i], NULL); + if (misc_deregister(&sx_fw_device) < 0) { - printk (KERN_INFO "sx: couldn't deregister firmware loader device\n"); + printk(KERN_INFO "sx: couldn't deregister firmware loader " + "device\n"); } - sx_dprintk (SX_DEBUG_CLEANUP, "Cleaning up drivers (%d)\n", sx_initialized); + sx_dprintk(SX_DEBUG_CLEANUP, "Cleaning up drivers (%d)\n", + sx_initialized); if (sx_initialized) - sx_release_drivers (); + sx_release_drivers(); - kfree (sx_ports); + kfree(sx_ports); func_exit(); } module_init(sx_init); module_exit(sx_exit); - - diff --git a/drivers/char/sx.h b/drivers/char/sx.h index e01f83cbe29..432aad0a2dd 100644 --- a/drivers/char/sx.h +++ b/drivers/char/sx.h @@ -35,6 +35,7 @@ struct sx_board { void __iomem *base; void __iomem *base2; unsigned long hw_base; + resource_size_t hw_len; int eisa_base; int port_base; /* Number of the first port */ struct sx_port *ports; diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 645187b9141..acc6fab601c 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -3060,7 +3060,7 @@ static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigne * * Return Value: None */ -static void mgsl_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data; unsigned long flags; @@ -4405,6 +4405,8 @@ static int mgsl_init_tty(void) serial_driver->init_termios = tty_std_termios; serial_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver->init_termios.c_ispeed = 9600; + serial_driver->init_termios.c_ospeed = 9600; serial_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(serial_driver, &mgsl_ops); if ((rc = tty_register_driver(serial_driver)) < 0) { diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index e4730a7312b..792c79c315e 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -151,7 +151,7 @@ static struct tty_driver *serial_driver; static int open(struct tty_struct *tty, struct file * filp); static void close(struct tty_struct *tty, struct file * filp); static void hangup(struct tty_struct *tty); -static void set_termios(struct tty_struct *tty, struct termios *old_termios); +static void set_termios(struct tty_struct *tty, struct ktermios *old_termios); static int write(struct tty_struct *tty, const unsigned char *buf, int count); static void put_char(struct tty_struct *tty, unsigned char ch); @@ -816,7 +816,7 @@ static void hangup(struct tty_struct *tty) wake_up_interruptible(&info->open_wait); } -static void set_termios(struct tty_struct *tty, struct termios *old_termios) +static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct slgt_info *info = tty->driver_data; unsigned long flags; @@ -3546,6 +3546,8 @@ static int __init slgt_init(void) serial_driver->init_termios = tty_std_termios; serial_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver->init_termios.c_ispeed = 9600; + serial_driver->init_termios.c_ospeed = 9600; serial_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(serial_driver, &ops); if ((rc = tty_register_driver(serial_driver)) < 0) { diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 20a96ef250b..53e8ccf94fe 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -519,7 +519,7 @@ static struct tty_driver *serial_driver; static int open(struct tty_struct *tty, struct file * filp); static void close(struct tty_struct *tty, struct file * filp); static void hangup(struct tty_struct *tty); -static void set_termios(struct tty_struct *tty, struct termios *old_termios); +static void set_termios(struct tty_struct *tty, struct ktermios *old_termios); static int write(struct tty_struct *tty, const unsigned char *buf, int count); static void put_char(struct tty_struct *tty, unsigned char ch); @@ -918,7 +918,7 @@ static void hangup(struct tty_struct *tty) /* Set new termios settings */ -static void set_termios(struct tty_struct *tty, struct termios *old_termios) +static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) { SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; unsigned long flags; @@ -4034,6 +4034,8 @@ static int __init synclinkmp_init(void) serial_driver->init_termios = tty_std_termios; serial_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver->init_termios.c_ispeed = 9600; + serial_driver->init_termios.c_ospeed = 9600; serial_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(serial_driver, &ops); if ((rc = tty_register_driver(serial_driver)) < 0) { diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c index bb1bad4c18f..4c431cb7cf1 100644 --- a/drivers/char/tb0219.c +++ b/drivers/char/tb0219.c @@ -164,7 +164,7 @@ static ssize_t tanbac_tb0219_read(struct file *file, char __user *buf, size_t le unsigned int minor; char value; - minor = iminor(file->f_dentry->d_inode); + minor = iminor(file->f_path.dentry->d_inode); switch (minor) { case 0: value = get_led(); @@ -200,7 +200,7 @@ static ssize_t tanbac_tb0219_write(struct file *file, const char __user *data, int retval = 0; char c; - minor = iminor(file->f_dentry->d_inode); + minor = iminor(file->f_path.dentry->d_inode); switch (minor) { case 0: type = TYPE_LED; diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c index 9df0ca1be0e..47fb20f6969 100644 --- a/drivers/char/tipar.c +++ b/drivers/char/tipar.c @@ -285,7 +285,7 @@ static ssize_t tipar_write (struct file *file, const char __user *buf, size_t count, loff_t * ppos) { - unsigned int minor = iminor(file->f_dentry->d_inode) - TIPAR_MINOR; + unsigned int minor = iminor(file->f_path.dentry->d_inode) - TIPAR_MINOR; ssize_t n; parport_claim_or_block(table[minor].dev); @@ -313,7 +313,7 @@ static ssize_t tipar_read(struct file *file, char __user *buf, size_t count, loff_t * ppos) { int b = 0; - unsigned int minor = iminor(file->f_dentry->d_inode) - TIPAR_MINOR; + unsigned int minor = iminor(file->f_path.dentry->d_inode) - TIPAR_MINOR; ssize_t retval = 0; ssize_t n = 0; diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index b3cfc8bc613..4044c864fdd 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -109,13 +109,15 @@ #define TTY_PARANOIA_CHECK 1 #define CHECK_TTY_COUNT 1 -struct termios tty_std_termios = { /* for the benefit of tty drivers */ +struct ktermios tty_std_termios = { /* for the benefit of tty drivers */ .c_iflag = ICRNL | IXON, .c_oflag = OPOST | ONLCR, .c_cflag = B38400 | CS8 | CREAD | HUPCL, .c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN, - .c_cc = INIT_C_CC + .c_cc = INIT_C_CC, + .c_ispeed = 38400, + .c_ospeed = 38400 }; EXPORT_SYMBOL(tty_std_termios); @@ -126,7 +128,7 @@ EXPORT_SYMBOL(tty_std_termios); LIST_HEAD(tty_drivers); /* linked list of tty drivers */ -/* Semaphore to protect creating and releasing a tty. This is shared with +/* Mutex to protect creating and releasing a tty. This is shared with vt.c for deeply disgusting hack reasons */ DEFINE_MUTEX(tty_mutex); EXPORT_SYMBOL(tty_mutex); @@ -250,7 +252,7 @@ static int check_tty_count(struct tty_struct *tty, const char *routine) "!= #fd's(%d) in %s\n", tty->name, tty->count, count, routine); return count; - } + } #endif return 0; } @@ -259,18 +261,6 @@ static int check_tty_count(struct tty_struct *tty, const char *routine) * Tty buffer allocation management */ - -/** - * tty_buffer_free_all - free buffers used by a tty - * @tty: tty to free from - * - * Remove all the buffers pending on a tty whether queued with data - * or in the free ring. Must be called when the tty is no longer in use - * - * Locking: none - */ - - /** * tty_buffer_free_all - free buffers used by a tty * @tty: tty to free from @@ -614,7 +604,7 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags); * they are not on hot paths so a little discipline won't do * any harm. * - * Locking: takes termios_sem + * Locking: takes termios_mutex */ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) @@ -915,7 +905,7 @@ static void tty_ldisc_enable(struct tty_struct *tty) * context. * * Locking: takes tty_ldisc_lock. - * called functions take termios_sem + * called functions take termios_mutex */ static int tty_set_ldisc(struct tty_struct *tty, int ldisc) @@ -1251,6 +1241,22 @@ void tty_ldisc_flush(struct tty_struct *tty) } EXPORT_SYMBOL_GPL(tty_ldisc_flush); + +/** + * tty_reset_termios - reset terminal state + * @tty: tty to reset + * + * Restore a terminal to the driver default state + */ + +static void tty_reset_termios(struct tty_struct *tty) +{ + mutex_lock(&tty->termios_mutex); + *tty->termios = tty->driver->init_termios; + tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios); + tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios); + mutex_unlock(&tty->termios_mutex); +} /** * do_tty_hangup - actual handler for hangup events @@ -1267,12 +1273,12 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush); * * Locking: * BKL - * redirect lock for undoing redirection - * file list lock for manipulating list of ttys - * tty_ldisc_lock from called functions - * termios_sem resetting termios data - * tasklist_lock to walk task list for hangup event - * + * redirect lock for undoing redirection + * file list lock for manipulating list of ttys + * tty_ldisc_lock from called functions + * termios_mutex resetting termios data + * tasklist_lock to walk task list for hangup event + * ->siglock to protect ->signal/->sighand */ static void do_tty_hangup(struct work_struct *work) { @@ -1339,11 +1345,7 @@ static void do_tty_hangup(struct work_struct *work) * N_TTY. */ if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) - { - mutex_lock(&tty->termios_mutex); - *tty->termios = tty->driver->init_termios; - mutex_unlock(&tty->termios_mutex); - } + tty_reset_termios(tty); /* Defer ldisc switch */ /* tty_deferred_ldisc_switch(N_TTY); @@ -1354,14 +1356,18 @@ static void do_tty_hangup(struct work_struct *work) read_lock(&tasklist_lock); if (tty->session > 0) { do_each_task_pid(tty->session, PIDTYPE_SID, p) { + spin_lock_irq(&p->sighand->siglock); if (p->signal->tty == tty) p->signal->tty = NULL; - if (!p->signal->leader) + if (!p->signal->leader) { + spin_unlock_irq(&p->sighand->siglock); continue; - group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p); - group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p); + } + __group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p); + __group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p); if (tty->pgrp > 0) p->signal->tty_old_pgrp = tty->pgrp; + spin_unlock_irq(&p->sighand->siglock); } while_each_task_pid(tty->session, PIDTYPE_SID, p); } read_unlock(&tasklist_lock); @@ -1453,6 +1459,14 @@ int tty_hung_up_p(struct file * filp) EXPORT_SYMBOL(tty_hung_up_p); +static void session_clear_tty(pid_t session) +{ + struct task_struct *p; + do_each_task_pid(session, PIDTYPE_SID, p) { + proc_clear_tty(p); + } while_each_task_pid(session, PIDTYPE_SID, p); +} + /** * disassociate_ctty - disconnect controlling tty * @on_exit: true if exiting so need to "hang up" the session @@ -1469,31 +1483,35 @@ EXPORT_SYMBOL(tty_hung_up_p); * The argument on_exit is set to 1 if called when a process is * exiting; it is 0 if called by the ioctl TIOCNOTTY. * - * Locking: tty_mutex is taken to protect current->signal->tty + * Locking: * BKL is taken for hysterical raisins - * Tasklist lock is taken (under tty_mutex) to walk process - * lists for the session. + * tty_mutex is taken to protect tty + * ->siglock is taken to protect ->signal/->sighand + * tasklist_lock is taken to walk process list for sessions + * ->siglock is taken to protect ->signal/->sighand */ void disassociate_ctty(int on_exit) { struct tty_struct *tty; - struct task_struct *p; int tty_pgrp = -1; + int session; lock_kernel(); mutex_lock(&tty_mutex); - tty = current->signal->tty; + tty = get_current_tty(); if (tty) { tty_pgrp = tty->pgrp; mutex_unlock(&tty_mutex); + /* XXX: here we race, there is nothing protecting tty */ if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) tty_vhangup(tty); } else { - if (current->signal->tty_old_pgrp) { - kill_pg(current->signal->tty_old_pgrp, SIGHUP, on_exit); - kill_pg(current->signal->tty_old_pgrp, SIGCONT, on_exit); + pid_t old_pgrp = current->signal->tty_old_pgrp; + if (old_pgrp) { + kill_pg(old_pgrp, SIGHUP, on_exit); + kill_pg(old_pgrp, SIGCONT, on_exit); } mutex_unlock(&tty_mutex); unlock_kernel(); @@ -1505,19 +1523,29 @@ void disassociate_ctty(int on_exit) kill_pg(tty_pgrp, SIGCONT, on_exit); } - /* Must lock changes to tty_old_pgrp */ - mutex_lock(&tty_mutex); + spin_lock_irq(¤t->sighand->siglock); current->signal->tty_old_pgrp = 0; - tty->session = 0; - tty->pgrp = -1; + session = process_session(current); + spin_unlock_irq(¤t->sighand->siglock); + + mutex_lock(&tty_mutex); + /* It is possible that do_tty_hangup has free'd this tty */ + tty = get_current_tty(); + if (tty) { + tty->session = 0; + tty->pgrp = 0; + } else { +#ifdef TTY_DEBUG_HANGUP + printk(KERN_DEBUG "error attempted to write to tty [0x%p]" + " = NULL", tty); +#endif + } + mutex_unlock(&tty_mutex); /* Now clear signal->tty under the lock */ read_lock(&tasklist_lock); - do_each_task_pid(current->signal->session, PIDTYPE_SID, p) { - p->signal->tty = NULL; - } while_each_task_pid(current->signal->session, PIDTYPE_SID, p); + session_clear_tty(session); read_unlock(&tasklist_lock); - mutex_unlock(&tty_mutex); unlock_kernel(); } @@ -1615,7 +1643,7 @@ static ssize_t tty_read(struct file * file, char __user * buf, size_t count, struct tty_ldisc *ld; tty = (struct tty_struct *)file->private_data; - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; if (tty_paranoia_check(tty, inode, "tty_read")) return -EIO; if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags))) @@ -1718,7 +1746,7 @@ static inline ssize_t do_tty_write( cond_resched(); } if (written) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; inode->i_mtime = current_fs_time(inode->i_sb); ret = written; } @@ -1749,7 +1777,7 @@ static ssize_t tty_write(struct file * file, const char __user * buf, size_t cou loff_t *ppos) { struct tty_struct * tty; - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; ssize_t ret; struct tty_ldisc *ld; @@ -1856,8 +1884,8 @@ static int init_dev(struct tty_driver *driver, int idx, struct tty_struct **ret_tty) { struct tty_struct *tty, *o_tty; - struct termios *tp, **tp_loc, *o_tp, **o_tp_loc; - struct termios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc; + struct ktermios *tp, **tp_loc, *o_tp, **o_tp_loc; + struct ktermios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc; int retval = 0; /* check whether we're reopening an existing tty */ @@ -1904,7 +1932,7 @@ static int init_dev(struct tty_driver *driver, int idx, } if (!*tp_loc) { - tp = (struct termios *) kmalloc(sizeof(struct termios), + tp = (struct ktermios *) kmalloc(sizeof(struct ktermios), GFP_KERNEL); if (!tp) goto free_mem_out; @@ -1912,11 +1940,11 @@ static int init_dev(struct tty_driver *driver, int idx, } if (!*ltp_loc) { - ltp = (struct termios *) kmalloc(sizeof(struct termios), + ltp = (struct ktermios *) kmalloc(sizeof(struct ktermios), GFP_KERNEL); if (!ltp) goto free_mem_out; - memset(ltp, 0, sizeof(struct termios)); + memset(ltp, 0, sizeof(struct ktermios)); } if (driver->type == TTY_DRIVER_TYPE_PTY) { @@ -1937,19 +1965,19 @@ static int init_dev(struct tty_driver *driver, int idx, } if (!*o_tp_loc) { - o_tp = (struct termios *) - kmalloc(sizeof(struct termios), GFP_KERNEL); + o_tp = (struct ktermios *) + kmalloc(sizeof(struct ktermios), GFP_KERNEL); if (!o_tp) goto free_mem_out; *o_tp = driver->other->init_termios; } if (!*o_ltp_loc) { - o_ltp = (struct termios *) - kmalloc(sizeof(struct termios), GFP_KERNEL); + o_ltp = (struct ktermios *) + kmalloc(sizeof(struct ktermios), GFP_KERNEL); if (!o_ltp) goto free_mem_out; - memset(o_ltp, 0, sizeof(struct termios)); + memset(o_ltp, 0, sizeof(struct ktermios)); } /* @@ -1988,6 +2016,9 @@ static int init_dev(struct tty_driver *driver, int idx, *ltp_loc = ltp; tty->termios = *tp_loc; tty->termios_locked = *ltp_loc; + /* Compatibility until drivers always set this */ + tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios); + tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios); driver->refcount++; tty->count++; @@ -2090,7 +2121,7 @@ release_mem_out: static void release_mem(struct tty_struct *tty, int idx) { struct tty_struct *o_tty; - struct termios *tp; + struct ktermios *tp; int devpts = tty->driver->flags & TTY_DRIVER_DEVPTS_MEM; if ((o_tty = tty->link) != NULL) { @@ -2156,7 +2187,7 @@ static void release_dev(struct file * filp) unsigned long flags; tty = (struct tty_struct *)filp->private_data; - if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "release_dev")) + if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "release_dev")) return; check_tty_count(tty, "release_dev"); @@ -2337,16 +2368,10 @@ static void release_dev(struct file * filp) * tty. */ if (tty_closing || o_tty_closing) { - struct task_struct *p; - read_lock(&tasklist_lock); - do_each_task_pid(tty->session, PIDTYPE_SID, p) { - p->signal->tty = NULL; - } while_each_task_pid(tty->session, PIDTYPE_SID, p); + session_clear_tty(tty->session); if (o_tty) - do_each_task_pid(o_tty->session, PIDTYPE_SID, p) { - p->signal->tty = NULL; - } while_each_task_pid(o_tty->session, PIDTYPE_SID, p); + session_clear_tty(o_tty->session); read_unlock(&tasklist_lock); } @@ -2443,9 +2468,9 @@ static void release_dev(struct file * filp) * The termios state of a pty is reset on first open so that * settings don't persist across reuse. * - * Locking: tty_mutex protects current->signal->tty, get_tty_driver and - * init_dev work. tty->count should protect the rest. - * task_lock is held to update task details for sessions + * Locking: tty_mutex protects tty, get_tty_driver and init_dev work. + * tty->count should protect the rest. + * ->siglock protects ->signal/->sighand */ static int tty_open(struct inode * inode, struct file * filp) @@ -2467,12 +2492,13 @@ retry_open: mutex_lock(&tty_mutex); if (device == MKDEV(TTYAUX_MAJOR,0)) { - if (!current->signal->tty) { + tty = get_current_tty(); + if (!tty) { mutex_unlock(&tty_mutex); return -ENXIO; } - driver = current->signal->tty->driver; - index = current->signal->tty->index; + driver = tty->driver; + index = tty->index; filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */ /* noctty = 1; */ goto got_driver; @@ -2547,17 +2573,16 @@ got_driver: filp->f_op = &tty_fops; goto retry_open; } + + mutex_lock(&tty_mutex); + spin_lock_irq(¤t->sighand->siglock); if (!noctty && current->signal->leader && !current->signal->tty && - tty->session == 0) { - task_lock(current); - current->signal->tty = tty; - task_unlock(current); - current->signal->tty_old_pgrp = 0; - tty->session = current->signal->session; - tty->pgrp = process_group(current); - } + tty->session == 0) + __proc_set_tty(current, tty); + spin_unlock_irq(¤t->sighand->siglock); + mutex_unlock(&tty_mutex); return 0; } @@ -2672,7 +2697,7 @@ static unsigned int tty_poll(struct file * filp, poll_table * wait) int ret = 0; tty = (struct tty_struct *)filp->private_data; - if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "tty_poll")) + if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_poll")) return 0; ld = tty_ldisc_ref_wait(tty); @@ -2688,7 +2713,7 @@ static int tty_fasync(int fd, struct file * filp, int on) int retval; tty = (struct tty_struct *)filp->private_data; - if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "tty_fasync")) + if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync")) return 0; retval = fasync_helper(fd, filp, on, &tty->fasync); @@ -2747,7 +2772,7 @@ static int tiocsti(struct tty_struct *tty, char __user *p) * * Copies the kernel idea of the window size into the user buffer. * - * Locking: tty->termios_sem is taken to ensure the winsize data + * Locking: tty->termios_mutex is taken to ensure the winsize data * is consistent. */ @@ -2774,8 +2799,8 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user * arg) * Locking: * Called function use the console_sem is used to ensure we do * not try and resize the console twice at once. - * The tty->termios_sem is used to ensure we don't double - * resize and get confused. Lock order - tty->termios.sem before + * The tty->termios_mutex is used to ensure we don't double + * resize and get confused. Lock order - tty->termios_mutex before * console sem */ @@ -2880,25 +2905,28 @@ static int fionbio(struct file *file, int __user *p) * leader to set this tty as the controlling tty for the session. * * Locking: - * Takes tasklist lock internally to walk sessions - * Takes task_lock() when updating signal->tty * Takes tty_mutex() to protect tty instance - * + * Takes tasklist_lock internally to walk sessions + * Takes ->siglock() when updating signal->tty */ static int tiocsctty(struct tty_struct *tty, int arg) { - struct task_struct *p; - + int ret = 0; if (current->signal->leader && - (current->signal->session == tty->session)) - return 0; + (process_session(current) == tty->session)) + return ret; + + mutex_lock(&tty_mutex); /* * The process must be a session leader and * not have a controlling tty already. */ - if (!current->signal->leader || current->signal->tty) - return -EPERM; + if (!current->signal->leader || current->signal->tty) { + ret = -EPERM; + goto unlock; + } + if (tty->session > 0) { /* * This tty is already the controlling @@ -2908,24 +2936,18 @@ static int tiocsctty(struct tty_struct *tty, int arg) /* * Steal it away */ - read_lock(&tasklist_lock); - do_each_task_pid(tty->session, PIDTYPE_SID, p) { - p->signal->tty = NULL; - } while_each_task_pid(tty->session, PIDTYPE_SID, p); + session_clear_tty(tty->session); read_unlock(&tasklist_lock); - } else - return -EPERM; + } else { + ret = -EPERM; + goto unlock; + } } - mutex_lock(&tty_mutex); - task_lock(current); - current->signal->tty = tty; - task_unlock(current); + proc_set_tty(current, tty); +unlock: mutex_unlock(&tty_mutex); - current->signal->tty_old_pgrp = 0; - tty->session = current->signal->session; - tty->pgrp = process_group(current); - return 0; + return ret; } /** @@ -2937,7 +2959,7 @@ static int tiocsctty(struct tty_struct *tty, int arg) * Obtain the process group of the tty. If there is no process group * return an error. * - * Locking: none. Reference to ->signal->tty is safe. + * Locking: none. Reference to current->signal->tty is safe. */ static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p) @@ -2974,13 +2996,13 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t return retval; if (!current->signal->tty || (current->signal->tty != real_tty) || - (real_tty->session != current->signal->session)) + (real_tty->session != process_session(current))) return -ENOTTY; if (get_user(pgrp, p)) return -EFAULT; if (pgrp < 0) return -EINVAL; - if (session_of_pgrp(pgrp) != current->signal->session) + if (session_of_pgrp(pgrp) != process_session(current)) return -EPERM; real_tty->pgrp = pgrp; return 0; @@ -2995,7 +3017,7 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t * Obtain the session id of the tty. If there is no session * return an error. * - * Locking: none. Reference to ->signal->tty is safe. + * Locking: none. Reference to current->signal->tty is safe. */ static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p) @@ -3214,14 +3236,11 @@ int tty_ioctl(struct inode * inode, struct file * file, clear_bit(TTY_EXCLUSIVE, &tty->flags); return 0; case TIOCNOTTY: - /* FIXME: taks lock or tty_mutex ? */ if (current->signal->tty != tty) return -ENOTTY; if (current->signal->leader) disassociate_ctty(0); - task_lock(current); - current->signal->tty = NULL; - task_unlock(current); + proc_clear_tty(current); return 0; case TIOCSCTTY: return tiocsctty(tty, arg); @@ -3321,7 +3340,7 @@ static void __do_SAK(struct work_struct *work) if (!tty) return; - session = tty->session; + session = tty->session; /* We don't want an ldisc switch during this */ disc = tty_ldisc_ref(tty); @@ -3336,7 +3355,7 @@ static void __do_SAK(struct work_struct *work) /* Kill the entire session */ do_each_task_pid(session, PIDTYPE_SID, p) { printk(KERN_NOTICE "SAK: killed process %d" - " (%s): p->signal->session==tty->session\n", + " (%s): process_session(p)==tty->session\n", p->pid, p->comm); send_sig(SIGKILL, p, 1); } while_each_task_pid(session, PIDTYPE_SID, p); @@ -3346,7 +3365,7 @@ static void __do_SAK(struct work_struct *work) do_each_thread(g, p) { if (p->signal->tty == tty) { printk(KERN_NOTICE "SAK: killed process %d" - " (%s): p->signal->session==tty->session\n", + " (%s): process_session(p)==tty->session\n", p->pid, p->comm); send_sig(SIGKILL, p, 1); continue; @@ -3456,84 +3475,6 @@ static void flush_to_ldisc(struct work_struct *work) tty_ldisc_deref(disc); } -/* - * Routine which returns the baud rate of the tty - * - * Note that the baud_table needs to be kept in sync with the - * include/asm/termbits.h file. - */ -static int baud_table[] = { - 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, - 9600, 19200, 38400, 57600, 115200, 230400, 460800, -#ifdef __sparc__ - 76800, 153600, 307200, 614400, 921600 -#else - 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000, - 2500000, 3000000, 3500000, 4000000 -#endif -}; - -static int n_baud_table = ARRAY_SIZE(baud_table); - -/** - * tty_termios_baud_rate - * @termios: termios structure - * - * Convert termios baud rate data into a speed. This should be called - * with the termios lock held if this termios is a terminal termios - * structure. May change the termios data. - * - * Locking: none - */ - -int tty_termios_baud_rate(struct termios *termios) -{ - unsigned int cbaud; - - cbaud = termios->c_cflag & CBAUD; - - if (cbaud & CBAUDEX) { - cbaud &= ~CBAUDEX; - - if (cbaud < 1 || cbaud + 15 > n_baud_table) - termios->c_cflag &= ~CBAUDEX; - else - cbaud += 15; - } - return baud_table[cbaud]; -} - -EXPORT_SYMBOL(tty_termios_baud_rate); - -/** - * tty_get_baud_rate - get tty bit rates - * @tty: tty to query - * - * Returns the baud rate as an integer for this terminal. The - * termios lock must be held by the caller and the terminal bit - * flags may be updated. - * - * Locking: none - */ - -int tty_get_baud_rate(struct tty_struct *tty) -{ - int baud = tty_termios_baud_rate(tty->termios); - - if (baud == 38400 && tty->alt_speed) { - if (!tty->warned) { - printk(KERN_WARNING "Use of setserial/setrocket to " - "set SPD_* flags is deprecated\n"); - tty->warned = 1; - } - baud = tty->alt_speed; - } - - return baud; -} - -EXPORT_SYMBOL(tty_get_baud_rate); - /** * tty_flip_buffer_push - terminal * @tty: tty to push @@ -3756,8 +3697,8 @@ int tty_register_driver(struct tty_driver *driver) if (p) { driver->ttys = (struct tty_struct **)p; - driver->termios = (struct termios **)(p + driver->num); - driver->termios_locked = (struct termios **)(p + driver->num * 2); + driver->termios = (struct ktermios **)(p + driver->num); + driver->termios_locked = (struct ktermios **)(p + driver->num * 2); } else { driver->ttys = NULL; driver->termios = NULL; @@ -3796,7 +3737,7 @@ EXPORT_SYMBOL(tty_register_driver); int tty_unregister_driver(struct tty_driver *driver) { int i; - struct termios *tp; + struct ktermios *tp; void *p; if (driver->refcount) @@ -3834,9 +3775,52 @@ int tty_unregister_driver(struct tty_driver *driver) cdev_del(&driver->cdev); return 0; } - EXPORT_SYMBOL(tty_unregister_driver); +dev_t tty_devnum(struct tty_struct *tty) +{ + return MKDEV(tty->driver->major, tty->driver->minor_start) + tty->index; +} +EXPORT_SYMBOL(tty_devnum); + +void proc_clear_tty(struct task_struct *p) +{ + spin_lock_irq(&p->sighand->siglock); + p->signal->tty = NULL; + spin_unlock_irq(&p->sighand->siglock); +} +EXPORT_SYMBOL(proc_clear_tty); + +void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty) +{ + if (tty) { + tty->session = process_session(tsk); + tty->pgrp = process_group(tsk); + } + tsk->signal->tty = tty; + tsk->signal->tty_old_pgrp = 0; +} + +void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty) +{ + spin_lock_irq(&tsk->sighand->siglock); + __proc_set_tty(tsk, tty); + spin_unlock_irq(&tsk->sighand->siglock); +} + +struct tty_struct *get_current_tty(void) +{ + struct tty_struct *tty; + WARN_ON_ONCE(!mutex_is_locked(&tty_mutex)); + tty = current->signal->tty; + /* + * session->tty can be changed/cleared from under us, make sure we + * issue the load. The obtained pointer, when not NULL, is valid as + * long as we hold tty_mutex. + */ + barrier(); + return tty; +} /* * Initialize the console device. This is called *early*, so diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index 3b6fa7b0be8..dee47f40c6a 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c @@ -36,6 +36,7 @@ #define TERMIOS_FLUSH 1 #define TERMIOS_WAIT 2 #define TERMIOS_TERMIO 4 +#define TERMIOS_OLD 8 /** @@ -84,9 +85,9 @@ stop_waiting: EXPORT_SYMBOL(tty_wait_until_sent); -static void unset_locked_termios(struct termios *termios, - struct termios *old, - struct termios *locked) +static void unset_locked_termios(struct ktermios *termios, + struct ktermios *old, + struct ktermios *locked) { int i; @@ -105,8 +106,204 @@ static void unset_locked_termios(struct termios *termios, for (i=0; i < NCCS; i++) termios->c_cc[i] = locked->c_cc[i] ? old->c_cc[i] : termios->c_cc[i]; + /* FIXME: What should we do for i/ospeed */ } +/* + * Routine which returns the baud rate of the tty + * + * Note that the baud_table needs to be kept in sync with the + * include/asm/termbits.h file. + */ +static const speed_t baud_table[] = { + 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, + 9600, 19200, 38400, 57600, 115200, 230400, 460800, +#ifdef __sparc__ + 76800, 153600, 307200, 614400, 921600 +#else + 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000, + 2500000, 3000000, 3500000, 4000000 +#endif +}; + +#ifndef __sparc__ +static const tcflag_t baud_bits[] = { + B0, B50, B75, B110, B134, B150, B200, B300, B600, + B1200, B1800, B2400, B4800, B9600, B19200, B38400, + B57600, B115200, B230400, B460800, B500000, B576000, + B921600, B1000000, B1152000, B1500000, B2000000, B2500000, + B3000000, B3500000, B4000000 +}; +#else +static const tcflag_t baud_bits[] = { + B0, B50, B75, B110, B134, B150, B200, B300, B600, + B1200, B1800, B2400, B4800, B9600, B19200, B38400, + B57600, B115200, B230400, B460800, B76800, B153600, + B307200, B614400, B921600 +}; +#endif + +static int n_baud_table = ARRAY_SIZE(baud_table); + +/** + * tty_termios_baud_rate + * @termios: termios structure + * + * Convert termios baud rate data into a speed. This should be called + * with the termios lock held if this termios is a terminal termios + * structure. May change the termios data. Device drivers can call this + * function but should use ->c_[io]speed directly as they are updated. + * + * Locking: none + */ + +speed_t tty_termios_baud_rate(struct ktermios *termios) +{ + unsigned int cbaud; + + cbaud = termios->c_cflag & CBAUD; + +#ifdef BOTHER + /* Magic token for arbitary speed via c_ispeed/c_ospeed */ + if (cbaud == BOTHER) + return termios->c_ospeed; +#endif + if (cbaud & CBAUDEX) { + cbaud &= ~CBAUDEX; + + if (cbaud < 1 || cbaud + 15 > n_baud_table) + termios->c_cflag &= ~CBAUDEX; + else + cbaud += 15; + } + return baud_table[cbaud]; +} + +EXPORT_SYMBOL(tty_termios_baud_rate); + +/** + * tty_termios_input_baud_rate + * @termios: termios structure + * + * Convert termios baud rate data into a speed. This should be called + * with the termios lock held if this termios is a terminal termios + * structure. May change the termios data. Device drivers can call this + * function but should use ->c_[io]speed directly as they are updated. + * + * Locking: none + */ + +speed_t tty_termios_input_baud_rate(struct ktermios *termios) +{ +#ifdef IBSHIFT + unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD; + + if (cbaud == B0) + return tty_termios_baud_rate(termios); + + /* Magic token for arbitary speed via c_ispeed*/ + if (cbaud == BOTHER) + return termios->c_ispeed; + + if (cbaud & CBAUDEX) { + cbaud &= ~CBAUDEX; + + if (cbaud < 1 || cbaud + 15 > n_baud_table) + termios->c_cflag &= ~(CBAUDEX << IBSHIFT); + else + cbaud += 15; + } + return baud_table[cbaud]; +#else + return tty_termios_baud_rate(termios); +#endif +} + +EXPORT_SYMBOL(tty_termios_input_baud_rate); + +#ifdef BOTHER + +/** + * tty_termios_encode_baud_rate + * @termios: termios structure + * @ispeed: input speed + * @ospeed: output speed + * + * Encode the speeds set into the passed termios structure. This is + * used as a library helper for drivers os that they can report back + * the actual speed selected when it differs from the speed requested + * + * For now input and output speed must agree. + * + * Locking: Caller should hold termios lock. This is already held + * when calling this function from the driver termios handler. + */ + +void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed_t obaud) +{ + int i = 0; + int ifound = 0, ofound = 0; + + termios->c_ispeed = ibaud; + termios->c_ospeed = obaud; + + termios->c_cflag &= ~CBAUD; + /* Identical speed means no input encoding (ie B0 << IBSHIFT)*/ + if (termios->c_ispeed == termios->c_ospeed) + ifound = 1; + + do { + if (obaud == baud_table[i]) { + termios->c_cflag |= baud_bits[i]; + ofound = 1; + /* So that if ibaud == obaud we don't set it */ + continue; + } + if (ibaud == baud_table[i]) { + termios->c_cflag |= (baud_bits[i] << IBSHIFT); + ifound = 1; + } + } + while(++i < n_baud_table); + if (!ofound) + termios->c_cflag |= BOTHER; + if (!ifound) + termios->c_cflag |= (BOTHER << IBSHIFT); +} + +EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate); + +#endif + +/** + * tty_get_baud_rate - get tty bit rates + * @tty: tty to query + * + * Returns the baud rate as an integer for this terminal. The + * termios lock must be held by the caller and the terminal bit + * flags may be updated. + * + * Locking: none + */ + +speed_t tty_get_baud_rate(struct tty_struct *tty) +{ + speed_t baud = tty_termios_baud_rate(tty->termios); + + if (baud == 38400 && tty->alt_speed) { + if (!tty->warned) { + printk(KERN_WARNING "Use of setserial/setrocket to " + "set SPD_* flags is deprecated\n"); + tty->warned = 1; + } + baud = tty->alt_speed; + } + + return baud; +} + +EXPORT_SYMBOL(tty_get_baud_rate); + /** * change_termios - update termios values * @tty: tty to update @@ -119,10 +316,10 @@ static void unset_locked_termios(struct termios *termios, * Locking: termios_sem */ -static void change_termios(struct tty_struct * tty, struct termios * new_termios) +static void change_termios(struct tty_struct * tty, struct ktermios * new_termios) { int canon_change; - struct termios old_termios = *tty->termios; + struct ktermios old_termios = *tty->termios; struct tty_ldisc *ld; /* @@ -195,23 +392,39 @@ static void change_termios(struct tty_struct * tty, struct termios * new_termios static int set_termios(struct tty_struct * tty, void __user *arg, int opt) { - struct termios tmp_termios; + struct ktermios tmp_termios; struct tty_ldisc *ld; int retval = tty_check_change(tty); if (retval) return retval; + memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios)); + if (opt & TERMIOS_TERMIO) { - memcpy(&tmp_termios, tty->termios, sizeof(struct termios)); if (user_termio_to_kernel_termios(&tmp_termios, (struct termio __user *)arg)) return -EFAULT; +#ifdef TCGETS2 + } else if (opt & TERMIOS_OLD) { + if (user_termios_to_kernel_termios_1(&tmp_termios, + (struct termios __user *)arg)) + return -EFAULT; } else { if (user_termios_to_kernel_termios(&tmp_termios, - (struct termios __user *)arg)) + (struct termios2 __user *)arg)) return -EFAULT; } +#else + } else if (user_termios_to_kernel_termios(&tmp_termios, + (struct termios __user *)arg)) + return -EFAULT; +#endif + + /* If old style Bfoo values are used then load c_ispeed/c_ospeed with the real speed + so its unconditionally usable */ + tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios); + tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios); ld = tty_ldisc_ref(tty); @@ -286,8 +499,8 @@ static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb) struct sgttyb tmp; mutex_lock(&tty->termios_mutex); - tmp.sg_ispeed = 0; - tmp.sg_ospeed = 0; + tmp.sg_ispeed = tty->termios->c_ispeed; + tmp.sg_ospeed = tty->termios->c_ospeed; tmp.sg_erase = tty->termios->c_cc[VERASE]; tmp.sg_kill = tty->termios->c_cc[VKILL]; tmp.sg_flags = get_sgflags(tty); @@ -296,7 +509,7 @@ static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb) return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0; } -static void set_sgflags(struct termios * termios, int flags) +static void set_sgflags(struct ktermios * termios, int flags) { termios->c_iflag = ICRNL | IXON; termios->c_oflag = 0; @@ -337,7 +550,7 @@ static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb) { int retval; struct sgttyb tmp; - struct termios termios; + struct ktermios termios; retval = tty_check_change(tty); if (retval) @@ -351,6 +564,10 @@ static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb) termios.c_cc[VERASE] = tmp.sg_erase; termios.c_cc[VKILL] = tmp.sg_kill; set_sgflags(&termios, tmp.sg_flags); + /* Try and encode into Bfoo format */ +#ifdef BOTHER + tty_termios_encode_baud_rate(&termios, termios.c_ispeed, termios.c_ospeed); +#endif mutex_unlock(&tty->termios_mutex); change_termios(tty, &termios); return 0; @@ -481,16 +698,33 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file, case TIOCSLTC: return set_ltchars(real_tty, p); #endif + case TCSETSF: + return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD); + case TCSETSW: + return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD); + case TCSETS: + return set_termios(real_tty, p, TERMIOS_OLD); +#ifndef TCGETS2 case TCGETS: if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios)) return -EFAULT; return 0; - case TCSETSF: +#else + case TCGETS: + if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios)) + return -EFAULT; + return 0; + case TCGETS2: + if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios)) + return -EFAULT; + return 0; + case TCSETSF2: return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT); - case TCSETSW: + case TCSETSW2: return set_termios(real_tty, p, TERMIOS_WAIT); - case TCSETS: + case TCSETS2: return set_termios(real_tty, p, 0); +#endif case TCGETA: return get_termio(real_tty, p); case TCSETAF: diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c index f442b574b44..26776517f04 100644 --- a/drivers/char/vc_screen.c +++ b/drivers/char/vc_screen.c @@ -72,7 +72,7 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig) int size; down(&con_buf_sem); - size = vcs_size(file->f_dentry->d_inode); + size = vcs_size(file->f_path.dentry->d_inode); switch (orig) { default: up(&con_buf_sem); @@ -98,7 +98,7 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig) static ssize_t vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; unsigned int currcons = iminor(inode); struct vc_data *vc; long pos; @@ -271,7 +271,7 @@ unlock_out: static ssize_t vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; unsigned int currcons = iminor(inode); struct vc_data *vc; long pos; diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index 73c78bf75d7..94d79cb8ce8 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c @@ -442,7 +442,7 @@ static ssize_t viotap_write(struct file *file, const char *buf, if (op == NULL) return -ENOMEM; - get_dev_info(file->f_dentry->d_inode, &devi); + get_dev_info(file->f_path.dentry->d_inode, &devi); /* * We need to make sure we can send a request. We use @@ -532,7 +532,7 @@ static ssize_t viotap_read(struct file *file, char *buf, size_t count, if (op == NULL) return -ENOMEM; - get_dev_info(file->f_dentry->d_inode, &devi); + get_dev_info(file->f_path.dentry->d_inode, &devi); /* * We need to make sure we can send a request. We use @@ -612,7 +612,7 @@ static int viotap_ioctl(struct inode *inode, struct file *file, if (op == NULL) return -ENOMEM; - get_dev_info(file->f_dentry->d_inode, &devi); + get_dev_info(file->f_path.dentry->d_inode, &devi); down(&reqSem); @@ -777,7 +777,7 @@ static int viotap_open(struct inode *inode, struct file *file) if (op == NULL) return -ENOMEM; - get_dev_info(file->f_dentry->d_inode, &devi); + get_dev_info(file->f_path.dentry->d_inode, &devi); /* Note: We currently only support one mode! */ if ((devi.devno >= viotape_numdev) || (devi.mode)) { @@ -822,7 +822,7 @@ static int viotap_release(struct inode *inode, struct file *file) return -ENOMEM; init_completion(&op->com); - get_dev_info(file->f_dentry->d_inode, &devi); + get_dev_info(file->f_path.dentry->d_inode, &devi); if (devi.devno >= viotape_numdev) { ret = -ENODEV; diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c index d0b94dd1af6..e01317cb1a0 100644 --- a/drivers/char/vme_scc.c +++ b/drivers/char/vme_scc.c @@ -153,6 +153,8 @@ static int scc_init_drivers(void) scc_driver->init_termios = tty_std_termios; scc_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + scc_driver->init_termios.c_ispeed = 9600; + scc_driver->init_termios.c_ospeed = 9600; scc_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(scc_driver, &scc_ops); diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c index 8e794930517..a744dad9cf4 100644 --- a/drivers/char/vr41xx_giu.c +++ b/drivers/char/vr41xx_giu.c @@ -506,7 +506,7 @@ static ssize_t gpio_read(struct file *file, char __user *buf, size_t len, unsigned int pin; char value = '0'; - pin = iminor(file->f_dentry->d_inode); + pin = iminor(file->f_path.dentry->d_inode); if (pin >= giu_nr_pins) return -EBADF; @@ -530,7 +530,7 @@ static ssize_t gpio_write(struct file *file, const char __user *data, char c; int retval = 0; - pin = iminor(file->f_dentry->d_inode); + pin = iminor(file->f_path.dentry->d_inode); if (pin >= giu_nr_pins) return -EBADF; diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c index 7fcb77a9d01..8ab61ef97b4 100644 --- a/drivers/clocksource/acpi_pm.c +++ b/drivers/clocksource/acpi_pm.c @@ -142,6 +142,39 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_LE, acpi_pm_check_graylist); #endif +#ifndef CONFIG_X86_64 +#include "mach_timer.h" +#define PMTMR_EXPECTED_RATE \ + ((CALIBRATE_LATCH * (PMTMR_TICKS_PER_SEC >> 10)) / (CLOCK_TICK_RATE>>10)) +/* + * Some boards have the PMTMR running way too fast. We check + * the PMTMR rate against PIT channel 2 to catch these cases. + */ +static int verify_pmtmr_rate(void) +{ + u32 value1, value2; + unsigned long count, delta; + + mach_prepare_counter(); + value1 = read_pmtmr(); + mach_countup(&count); + value2 = read_pmtmr(); + delta = (value2 - value1) & ACPI_PM_MASK; + + /* Check that the PMTMR delta is within 5% of what we expect */ + if (delta < (PMTMR_EXPECTED_RATE * 19) / 20 || + delta > (PMTMR_EXPECTED_RATE * 21) / 20) { + printk(KERN_INFO "PM-Timer running at invalid rate: %lu%% " + "of normal - aborting.\n", + 100UL * delta / PMTMR_EXPECTED_RATE); + return -1; + } + + return 0; +} +#else +#define verify_pmtmr_rate() (0) +#endif static int __init init_acpi_pm_clocksource(void) { @@ -173,6 +206,9 @@ static int __init init_acpi_pm_clocksource(void) return -ENODEV; pm_good: + if (verify_pmtmr_rate() != 0) + return -ENODEV; + return clocksource_register(&clocksource_acpi_pm); } diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig new file mode 100644 index 00000000000..96d4a0bb220 --- /dev/null +++ b/drivers/hid/Kconfig @@ -0,0 +1,18 @@ +# +# HID driver configuration +# +menu "HID Devices" + depends on INPUT + +config HID + tristate "Generic HID support" + default y + ---help--- + Say Y here if you want generic HID support to connect keyboards, + mice, joysticks, graphic tablets, or any other HID based devices + to your computer. You also need to select particular types of + HID devices you want to compile support for, in the particular + driver menu (USB, Bluetooth) + +endmenu + diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile new file mode 100644 index 00000000000..6432392110b --- /dev/null +++ b/drivers/hid/Makefile @@ -0,0 +1,15 @@ +# +# Makefile for the HID driver +# + +# Multipart objects. +hid-objs := hid-core.o hid-input.o + +# Optional parts of multipart objects. + +obj-$(CONFIG_HID) += hid.o + +ifeq ($(CONFIG_INPUT_DEBUG),y) +EXTRA_CFLAGS += -DDEBUG +endif + diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c new file mode 100644 index 00000000000..18c2b3cf6bc --- /dev/null +++ b/drivers/hid/hid-core.c @@ -0,0 +1,1003 @@ +/* + * HID support for Linux + * + * Copyright (c) 1999 Andreas Gal + * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> + * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc + * Copyright (c) 2006 Jiri Kosina + */ + +/* + * 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 <linux/module.h> +#include <linux/slab.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/list.h> +#include <linux/mm.h> +#include <linux/smp_lock.h> +#include <linux/spinlock.h> +#include <asm/unaligned.h> +#include <asm/byteorder.h> +#include <linux/input.h> +#include <linux/wait.h> + +#undef DEBUG +#undef DEBUG_DATA + +#include <linux/hid.h> +#include <linux/hiddev.h> + +/* + * Version Information + */ + +#define DRIVER_VERSION "v2.6" +#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik" +#define DRIVER_DESC "USB HID core driver" +#define DRIVER_LICENSE "GPL" + +/* + * Module parameters. + */ + +static unsigned int hid_mousepoll_interval; +module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644); +MODULE_PARM_DESC(mousepoll, "Polling interval of mice"); + +/* + * Register a new report for a device. + */ + +static struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id) +{ + struct hid_report_enum *report_enum = device->report_enum + type; + struct hid_report *report; + + if (report_enum->report_id_hash[id]) + return report_enum->report_id_hash[id]; + + if (!(report = kzalloc(sizeof(struct hid_report), GFP_KERNEL))) + return NULL; + + if (id != 0) + report_enum->numbered = 1; + + report->id = id; + report->type = type; + report->size = 0; + report->device = device; + report_enum->report_id_hash[id] = report; + + list_add_tail(&report->list, &report_enum->report_list); + + return report; +} + +/* + * Register a new field for this report. + */ + +static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values) +{ + struct hid_field *field; + + if (report->maxfield == HID_MAX_FIELDS) { + dbg("too many fields in report"); + return NULL; + } + + if (!(field = kzalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage) + + values * sizeof(unsigned), GFP_KERNEL))) return NULL; + + field->index = report->maxfield++; + report->field[field->index] = field; + field->usage = (struct hid_usage *)(field + 1); + field->value = (unsigned *)(field->usage + usages); + field->report = report; + + return field; +} + +/* + * Open a collection. The type/usage is pushed on the stack. + */ + +static int open_collection(struct hid_parser *parser, unsigned type) +{ + struct hid_collection *collection; + unsigned usage; + + usage = parser->local.usage[0]; + + if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) { + dbg("collection stack overflow"); + return -1; + } + + if (parser->device->maxcollection == parser->device->collection_size) { + collection = kmalloc(sizeof(struct hid_collection) * + parser->device->collection_size * 2, GFP_KERNEL); + if (collection == NULL) { + dbg("failed to reallocate collection array"); + return -1; + } + memcpy(collection, parser->device->collection, + sizeof(struct hid_collection) * + parser->device->collection_size); + memset(collection + parser->device->collection_size, 0, + sizeof(struct hid_collection) * + parser->device->collection_size); + kfree(parser->device->collection); + parser->device->collection = collection; + parser->device->collection_size *= 2; + } + + parser->collection_stack[parser->collection_stack_ptr++] = + parser->device->maxcollection; + + collection = parser->device->collection + + parser->device->maxcollection++; + collection->type = type; + collection->usage = usage; + collection->level = parser->collection_stack_ptr - 1; + + if (type == HID_COLLECTION_APPLICATION) + parser->device->maxapplication++; + + return 0; +} + +/* + * Close a collection. + */ + +static int close_collection(struct hid_parser *parser) +{ + if (!parser->collection_stack_ptr) { + dbg("collection stack underflow"); + return -1; + } + parser->collection_stack_ptr--; + return 0; +} + +/* + * Climb up the stack, search for the specified collection type + * and return the usage. + */ + +static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type) +{ + int n; + for (n = parser->collection_stack_ptr - 1; n >= 0; n--) + if (parser->device->collection[parser->collection_stack[n]].type == type) + return parser->device->collection[parser->collection_stack[n]].usage; + return 0; /* we know nothing about this usage type */ +} + +/* + * Add a usage to the temporary parser table. + */ + +static int hid_add_usage(struct hid_parser *parser, unsigned usage) +{ + if (parser->local.usage_index >= HID_MAX_USAGES) { + dbg("usage index exceeded"); + return -1; + } + parser->local.usage[parser->local.usage_index] = usage; + parser->local.collection_index[parser->local.usage_index] = + parser->collection_stack_ptr ? + parser->collection_stack[parser->collection_stack_ptr - 1] : 0; + parser->local.usage_index++; + return 0; +} + +/* + * Register a new field for this report. + */ + +static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsigned flags) +{ + struct hid_report *report; + struct hid_field *field; + int usages; + unsigned offset; + int i; + + if (!(report = hid_register_report(parser->device, report_type, parser->global.report_id))) { + dbg("hid_register_report failed"); + return -1; + } + + if (parser->global.logical_maximum < parser->global.logical_minimum) { + dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum); + return -1; + } + + offset = report->size; + report->size += parser->global.report_size * parser->global.report_count; + + if (!parser->local.usage_index) /* Ignore padding fields */ + return 0; + + usages = max_t(int, parser->local.usage_index, parser->global.report_count); + + if ((field = hid_register_field(report, usages, parser->global.report_count)) == NULL) + return 0; + + field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL); + field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL); + field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION); + + for (i = 0; i < usages; i++) { + int j = i; + /* Duplicate the last usage we parsed if we have excess values */ + if (i >= parser->local.usage_index) + j = parser->local.usage_index - 1; + field->usage[i].hid = parser->local.usage[j]; + field->usage[i].collection_index = + parser->local.collection_index[j]; + } + + field->maxusage = usages; + field->flags = flags; + field->report_offset = offset; + field->report_type = report_type; + field->report_size = parser->global.report_size; + field->report_count = parser->global.report_count; + field->logical_minimum = parser->global.logical_minimum; + field->logical_maximum = parser->global.logical_maximum; + field->physical_minimum = parser->global.physical_minimum; + field->physical_maximum = parser->global.physical_maximum; + field->unit_exponent = parser->global.unit_exponent; + field->unit = parser->global.unit; + + return 0; +} + +/* + * Read data value from item. + */ + +static u32 item_udata(struct hid_item *item) +{ + switch (item->size) { + case 1: return item->data.u8; + case 2: return item->data.u16; + case 4: return item->data.u32; + } + return 0; +} + +static s32 item_sdata(struct hid_item *item) +{ + switch (item->size) { + case 1: return item->data.s8; + case 2: return item->data.s16; + case 4: return item->data.s32; + } + return 0; +} + +/* + * Process a global item. + */ + +static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) +{ + switch (item->tag) { + + case HID_GLOBAL_ITEM_TAG_PUSH: + + if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) { + dbg("global enviroment stack overflow"); + return -1; + } + + memcpy(parser->global_stack + parser->global_stack_ptr++, + &parser->global, sizeof(struct hid_global)); + return 0; + + case HID_GLOBAL_ITEM_TAG_POP: + + if (!parser->global_stack_ptr) { + dbg("global enviroment stack underflow"); + return -1; + } + + memcpy(&parser->global, parser->global_stack + --parser->global_stack_ptr, + sizeof(struct hid_global)); + return 0; + + case HID_GLOBAL_ITEM_TAG_USAGE_PAGE: + parser->global.usage_page = item_udata(item); + return 0; + + case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM: + parser->global.logical_minimum = item_sdata(item); + return 0; + + case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM: + if (parser->global.logical_minimum < 0) + parser->global.logical_maximum = item_sdata(item); + else + parser->global.logical_maximum = item_udata(item); + return 0; + + case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM: + parser->global.physical_minimum = item_sdata(item); + return 0; + + case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM: + if (parser->global.physical_minimum < 0) + parser->global.physical_maximum = item_sdata(item); + else + parser->global.physical_maximum = item_udata(item); + return 0; + + case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT: + parser->global.unit_exponent = item_sdata(item); + return 0; + + case HID_GLOBAL_ITEM_TAG_UNIT: + parser->global.unit = item_udata(item); + return 0; + + case HID_GLOBAL_ITEM_TAG_REPORT_SIZE: + if ((parser->global.report_size = item_udata(item)) > 32) { + dbg("invalid report_size %d", parser->global.report_size); + return -1; + } + return 0; + + case HID_GLOBAL_ITEM_TAG_REPORT_COUNT: + if ((parser->global.report_count = item_udata(item)) > HID_MAX_USAGES) { + dbg("invalid report_count %d", parser->global.report_count); + return -1; + } + return 0; + + case HID_GLOBAL_ITEM_TAG_REPORT_ID: + if ((parser->global.report_id = item_udata(item)) == 0) { + dbg("report_id 0 is invalid"); + return -1; + } + return 0; + + default: + dbg("unknown global tag 0x%x", item->tag); + return -1; + } +} + +/* + * Process a local item. + */ + +static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) +{ + __u32 data; + unsigned n; + + if (item->size == 0) { + dbg("item data expected for local item"); + return -1; + } + + data = item_udata(item); + + switch (item->tag) { + + case HID_LOCAL_ITEM_TAG_DELIMITER: + + if (data) { + /* + * We treat items before the first delimiter + * as global to all usage sets (branch 0). + * In the moment we process only these global + * items and the first delimiter set. + */ + if (parser->local.delimiter_depth != 0) { + dbg("nested delimiters"); + return -1; + } + parser->local.delimiter_depth++; + parser->local.delimiter_branch++; + } else { + if (parser->local.delimiter_depth < 1) { + dbg("bogus close delimiter"); + return -1; + } + parser->local.delimiter_depth--; + } + return 1; + + case HID_LOCAL_ITEM_TAG_USAGE: + + if (parser->local.delimiter_branch > 1) { + dbg("alternative usage ignored"); + return 0; + } + + if (item->size <= 2) + data = (parser->global.usage_page << 16) + data; + + return hid_add_usage(parser, data); + + case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM: + + if (parser->local.delimiter_branch > 1) { + dbg("alternative usage ignored"); + return 0; + } + + if (item->size <= 2) + data = (parser->global.usage_page << 16) + data; + + parser->local.usage_minimum = data; + return 0; + + case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM: + + if (parser->local.delimiter_branch > 1) { + dbg("alternative usage ignored"); + return 0; + } + + if (item->size <= 2) + data = (parser->global.usage_page << 16) + data; + + for (n = parser->local.usage_minimum; n <= data; n++) + if (hid_add_usage(parser, n)) { + dbg("hid_add_usage failed\n"); + return -1; + } + return 0; + + default: + + dbg("unknown local item tag 0x%x", item->tag); + return 0; + } + return 0; +} + +/* + * Process a main item. + */ + +static int hid_parser_main(struct hid_parser *parser, struct hid_item *item) +{ + __u32 data; + int ret; + + data = item_udata(item); + + switch (item->tag) { + case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION: + ret = open_collection(parser, data & 0xff); + break; + case HID_MAIN_ITEM_TAG_END_COLLECTION: + ret = close_collection(parser); + break; + case HID_MAIN_ITEM_TAG_INPUT: + ret = hid_add_field(parser, HID_INPUT_REPORT, data); + break; + case HID_MAIN_ITEM_TAG_OUTPUT: + ret = hid_add_field(parser, HID_OUTPUT_REPORT, data); + break; + case HID_MAIN_ITEM_TAG_FEATURE: + ret = hid_add_field(parser, HID_FEATURE_REPORT, data); + break; + default: + dbg("unknown main item tag 0x%x", item->tag); + ret = 0; + } + + memset(&parser->local, 0, sizeof(parser->local)); /* Reset the local parser environment */ + + return ret; +} + +/* + * Process a reserved item. + */ + +static int hid_parser_reserved(struct hid_parser *parser, struct hid_item *item) +{ + dbg("reserved item type, tag 0x%x", item->tag); + return 0; +} + +/* + * Free a report and all registered fields. The field->usage and + * field->value table's are allocated behind the field, so we need + * only to free(field) itself. + */ + +static void hid_free_report(struct hid_report *report) +{ + unsigned n; + + for (n = 0; n < report->maxfield; n++) + kfree(report->field[n]); + kfree(report); +} + +/* + * Free a device structure, all reports, and all fields. + */ + +void hid_free_device(struct hid_device *device) +{ + unsigned i,j; + + for (i = 0; i < HID_REPORT_TYPES; i++) { + struct hid_report_enum *report_enum = device->report_enum + i; + + for (j = 0; j < 256; j++) { + struct hid_report *report = report_enum->report_id_hash[j]; + if (report) + hid_free_report(report); + } + } + + kfree(device->rdesc); + kfree(device); +} +EXPORT_SYMBOL_GPL(hid_free_device); + +/* + * Fetch a report description item from the data stream. We support long + * items, though they are not used yet. + */ + +static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item) +{ + u8 b; + + if ((end - start) <= 0) + return NULL; + + b = *start++; + + item->type = (b >> 2) & 3; + item->tag = (b >> 4) & 15; + + if (item->tag == HID_ITEM_TAG_LONG) { + + item->format = HID_ITEM_FORMAT_LONG; + + if ((end - start) < 2) + return NULL; + + item->size = *start++; + item->tag = *start++; + + if ((end - start) < item->size) + return NULL; + + item->data.longdata = start; + start += item->size; + return start; + } + + item->format = HID_ITEM_FORMAT_SHORT; + item->size = b & 3; + + switch (item->size) { + + case 0: + return start; + + case 1: + if ((end - start) < 1) + return NULL; + item->data.u8 = *start++; + return start; + + case 2: + if ((end - start) < 2) + return NULL; + item->data.u16 = le16_to_cpu(get_unaligned((__le16*)start)); + start = (__u8 *)((__le16 *)start + 1); + return start; + + case 3: + item->size++; + if ((end - start) < 4) + return NULL; + item->data.u32 = le32_to_cpu(get_unaligned((__le32*)start)); + start = (__u8 *)((__le32 *)start + 1); + return start; + } + + return NULL; +} + +/* + * Parse a report description into a hid_device structure. Reports are + * enumerated, fields are attached to these reports. + */ + +struct hid_device *hid_parse_report(__u8 *start, unsigned size) +{ + struct hid_device *device; + struct hid_parser *parser; + struct hid_item item; + __u8 *end; + unsigned i; + static int (*dispatch_type[])(struct hid_parser *parser, + struct hid_item *item) = { + hid_parser_main, + hid_parser_global, + hid_parser_local, + hid_parser_reserved + }; + + if (!(device = kzalloc(sizeof(struct hid_device), GFP_KERNEL))) + return NULL; + + if (!(device->collection = kzalloc(sizeof(struct hid_collection) * + HID_DEFAULT_NUM_COLLECTIONS, GFP_KERNEL))) { + kfree(device); + return NULL; + } + device->collection_size = HID_DEFAULT_NUM_COLLECTIONS; + + for (i = 0; i < HID_REPORT_TYPES; i++) + INIT_LIST_HEAD(&device->report_enum[i].report_list); + + if (!(device->rdesc = (__u8 *)kmalloc(size, GFP_KERNEL))) { + kfree(device->collection); + kfree(device); + return NULL; + } + memcpy(device->rdesc, start, size); + device->rsize = size; + + if (!(parser = kzalloc(sizeof(struct hid_parser), GFP_KERNEL))) { + kfree(device->rdesc); + kfree(device->collection); + kfree(device); + return NULL; + } + parser->device = device; + + end = start + size; + while ((start = fetch_item(start, end, &item)) != NULL) { + + if (item.format != HID_ITEM_FORMAT_SHORT) { + dbg("unexpected long global item"); + kfree(device->collection); + hid_free_device(device); + kfree(parser); + return NULL; + } + + if (dispatch_type[item.type](parser, &item)) { + dbg("item %u %u %u %u parsing failed\n", + item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag); + kfree(device->collection); + hid_free_device(device); + kfree(parser); + return NULL; + } + + if (start == end) { + if (parser->collection_stack_ptr) { + dbg("unbalanced collection at end of report description"); + kfree(device->collection); + hid_free_device(device); + kfree(parser); + return NULL; + } + if (parser->local.delimiter_depth) { + dbg("unbalanced delimiter at end of report description"); + kfree(device->collection); + hid_free_device(device); + kfree(parser); + return NULL; + } + kfree(parser); + return device; + } + } + + dbg("item fetching failed at offset %d\n", (int)(end - start)); + kfree(device->collection); + hid_free_device(device); + kfree(parser); + return NULL; +} +EXPORT_SYMBOL_GPL(hid_parse_report); + +/* + * Convert a signed n-bit integer to signed 32-bit integer. Common + * cases are done through the compiler, the screwed things has to be + * done by hand. + */ + +static s32 snto32(__u32 value, unsigned n) +{ + switch (n) { + case 8: return ((__s8)value); + case 16: return ((__s16)value); + case 32: return ((__s32)value); + } + return value & (1 << (n - 1)) ? value | (-1 << n) : value; +} + +/* + * Convert a signed 32-bit integer to a signed n-bit integer. + */ + +static u32 s32ton(__s32 value, unsigned n) +{ + s32 a = value >> (n - 1); + if (a && a != -1) + return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1; + return value & ((1 << n) - 1); +} + +/* + * Extract/implement a data field from/to a little endian report (bit array). + * + * Code sort-of follows HID spec: + * http://www.usb.org/developers/devclass_docs/HID1_11.pdf + * + * While the USB HID spec allows unlimited length bit fields in "report + * descriptors", most devices never use more than 16 bits. + * One model of UPS is claimed to report "LINEV" as a 32-bit field. + * Search linux-kernel and linux-usb-devel archives for "hid-core extract". + */ + +static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n) +{ + u64 x; + + WARN_ON(n > 32); + + report += offset >> 3; /* adjust byte index */ + offset &= 7; /* now only need bit offset into one byte */ + x = get_unaligned((u64 *) report); + x = le64_to_cpu(x); + x = (x >> offset) & ((1ULL << n) - 1); /* extract bit field */ + return (u32) x; +} + +/* + * "implement" : set bits in a little endian bit stream. + * Same concepts as "extract" (see comments above). + * The data mangled in the bit stream remains in little endian + * order the whole time. It make more sense to talk about + * endianness of register values by considering a register + * a "cached" copy of the little endiad bit stream. + */ +static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value) +{ + u64 x; + u64 m = (1ULL << n) - 1; + + WARN_ON(n > 32); + + WARN_ON(value > m); + value &= m; + + report += offset >> 3; + offset &= 7; + + x = get_unaligned((u64 *)report); + x &= cpu_to_le64(~(m << offset)); + x |= cpu_to_le64(((u64) value) << offset); + put_unaligned(x, (u64 *) report); +} + +/* + * Search an array for a value. + */ + +static __inline__ int search(__s32 *array, __s32 value, unsigned n) +{ + while (n--) { + if (*array++ == value) + return 0; + } + return -1; +} + +static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, int interrupt) +{ + hid_dump_input(usage, value); + if (hid->claimed & HID_CLAIMED_INPUT) + hidinput_hid_event(hid, field, usage, value); + if (hid->claimed & HID_CLAIMED_HIDDEV && interrupt && hid->hiddev_hid_event) + hid->hiddev_hid_event(hid, field, usage, value); +} + +/* + * Analyse a received field, and fetch the data from it. The field + * content is stored for next report processing (we do differential + * reporting to the layer). + */ + +void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt) +{ + unsigned n; + unsigned count = field->report_count; + unsigned offset = field->report_offset; + unsigned size = field->report_size; + __s32 min = field->logical_minimum; + __s32 max = field->logical_maximum; + __s32 *value; + + if (!(value = kmalloc(sizeof(__s32) * count, GFP_ATOMIC))) + return; + + for (n = 0; n < count; n++) { + + value[n] = min < 0 ? snto32(extract(data, offset + n * size, size), size) : + extract(data, offset + n * size, size); + + if (!(field->flags & HID_MAIN_ITEM_VARIABLE) /* Ignore report if ErrorRollOver */ + && value[n] >= min && value[n] <= max + && field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1) + goto exit; + } + + for (n = 0; n < count; n++) { + + if (HID_MAIN_ITEM_VARIABLE & field->flags) { + hid_process_event(hid, field, &field->usage[n], value[n], interrupt); + continue; + } + + if (field->value[n] >= min && field->value[n] <= max + && field->usage[field->value[n] - min].hid + && search(value, field->value[n], count)) + hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, interrupt); + + if (value[n] >= min && value[n] <= max + && field->usage[value[n] - min].hid + && search(field->value, value[n], count)) + hid_process_event(hid, field, &field->usage[value[n] - min], 1, interrupt); + } + + memcpy(field->value, value, count * sizeof(__s32)); +exit: + kfree(value); +} +EXPORT_SYMBOL_GPL(hid_input_field); + +/* + * Output the field into the report. + */ + +static void hid_output_field(struct hid_field *field, __u8 *data) +{ + unsigned count = field->report_count; + unsigned offset = field->report_offset; + unsigned size = field->report_size; + unsigned n; + + for (n = 0; n < count; n++) { + if (field->logical_minimum < 0) /* signed values */ + implement(data, offset + n * size, size, s32ton(field->value[n], size)); + else /* unsigned values */ + implement(data, offset + n * size, size, field->value[n]); + } +} + +/* + * Create a report. + */ + +void hid_output_report(struct hid_report *report, __u8 *data) +{ + unsigned n; + + if (report->id > 0) + *data++ = report->id; + + for (n = 0; n < report->maxfield; n++) + hid_output_field(report->field[n], data); +} +EXPORT_SYMBOL_GPL(hid_output_report); + +/* + * Set a field value. The report this field belongs to has to be + * created and transferred to the device, to set this value in the + * device. + */ + +int hid_set_field(struct hid_field *field, unsigned offset, __s32 value) +{ + unsigned size = field->report_size; + + hid_dump_input(field->usage + offset, value); + + if (offset >= field->report_count) { + dbg("offset (%d) exceeds report_count (%d)", offset, field->report_count); + hid_dump_field(field, 8); + return -1; + } + if (field->logical_minimum < 0) { + if (value != snto32(s32ton(value, size), size)) { + dbg("value %d is out of range", value); + return -1; + } + } + field->value[offset] = value; + return 0; +} +EXPORT_SYMBOL_GPL(hid_set_field); + +int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int interrupt) +{ + struct hid_report_enum *report_enum = hid->report_enum + type; + struct hid_report *report; + int n, rsize; + + if (!hid) + return -ENODEV; + + if (!size) { + dbg("empty report"); + return -1; + } + +#ifdef DEBUG_DATA + printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", len, report_enum->numbered ? "" : "un"); +#endif + + n = 0; /* Normally report number is 0 */ + if (report_enum->numbered) { /* Device uses numbered reports, data[0] is report number */ + n = *data++; + size--; + } + +#ifdef DEBUG_DATA + { + int i; + printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, size); + for (i = 0; i < size; i++) + printk(" %02x", data[i]); + printk("\n"); + } +#endif + + if (!(report = report_enum->report_id_hash[n])) { + dbg("undefined report_id %d received", n); + return -1; + } + + rsize = ((report->size - 1) >> 3) + 1; + + if (size < rsize) { + dbg("report %d is too short, (%d < %d)", report->id, size, rsize); + return -1; + } + + if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event) + hid->hiddev_report_event(hid, report); + + for (n = 0; n < report->maxfield; n++) + hid_input_field(hid, report->field[n], data, interrupt); + + if (hid->claimed & HID_CLAIMED_INPUT) + hidinput_report_event(hid, report); + + return 0; +} +EXPORT_SYMBOL_GPL(hid_input_report); + +MODULE_LICENSE(DRIVER_LICENSE); + diff --git a/drivers/usb/input/hid-input.c b/drivers/hid/hid-input.c index 3a7e5fbff02..14cdf09316c 100644 --- a/drivers/usb/input/hid-input.c +++ b/drivers/hid/hid-input.c @@ -2,8 +2,9 @@ * $Id: hid-input.c,v 1.2 2002/04/23 00:59:25 rdamazio Exp $ * * Copyright (c) 2000-2001 Vojtech Pavlik + * Copyright (c) 2006 Jiri Kosina * - * USB HID to Linux Input mapping + * HID to Linux Input mapping */ /* @@ -33,7 +34,7 @@ #undef DEBUG -#include "hid.h" +#include <linux/hid.h> #define unk KEY_UNKNOWN @@ -81,42 +82,42 @@ struct hidinput_key_translation { static struct hidinput_key_translation powerbook_fn_keys[] = { { KEY_BACKSPACE, KEY_DELETE }, - { KEY_F1, KEY_BRIGHTNESSDOWN, POWERBOOK_FLAG_FKEY }, - { KEY_F2, KEY_BRIGHTNESSUP, POWERBOOK_FLAG_FKEY }, - { KEY_F3, KEY_MUTE, POWERBOOK_FLAG_FKEY }, - { KEY_F4, KEY_VOLUMEDOWN, POWERBOOK_FLAG_FKEY }, - { KEY_F5, KEY_VOLUMEUP, POWERBOOK_FLAG_FKEY }, - { KEY_F6, KEY_NUMLOCK, POWERBOOK_FLAG_FKEY }, - { KEY_F7, KEY_SWITCHVIDEOMODE, POWERBOOK_FLAG_FKEY }, - { KEY_F8, KEY_KBDILLUMTOGGLE, POWERBOOK_FLAG_FKEY }, - { KEY_F9, KEY_KBDILLUMDOWN, POWERBOOK_FLAG_FKEY }, - { KEY_F10, KEY_KBDILLUMUP, POWERBOOK_FLAG_FKEY }, - { KEY_UP, KEY_PAGEUP }, - { KEY_DOWN, KEY_PAGEDOWN }, - { KEY_LEFT, KEY_HOME }, - { KEY_RIGHT, KEY_END }, + { KEY_F1, KEY_BRIGHTNESSDOWN, POWERBOOK_FLAG_FKEY }, + { KEY_F2, KEY_BRIGHTNESSUP, POWERBOOK_FLAG_FKEY }, + { KEY_F3, KEY_MUTE, POWERBOOK_FLAG_FKEY }, + { KEY_F4, KEY_VOLUMEDOWN, POWERBOOK_FLAG_FKEY }, + { KEY_F5, KEY_VOLUMEUP, POWERBOOK_FLAG_FKEY }, + { KEY_F6, KEY_NUMLOCK, POWERBOOK_FLAG_FKEY }, + { KEY_F7, KEY_SWITCHVIDEOMODE, POWERBOOK_FLAG_FKEY }, + { KEY_F8, KEY_KBDILLUMTOGGLE, POWERBOOK_FLAG_FKEY }, + { KEY_F9, KEY_KBDILLUMDOWN, POWERBOOK_FLAG_FKEY }, + { KEY_F10, KEY_KBDILLUMUP, POWERBOOK_FLAG_FKEY }, + { KEY_UP, KEY_PAGEUP }, + { KEY_DOWN, KEY_PAGEDOWN }, + { KEY_LEFT, KEY_HOME }, + { KEY_RIGHT, KEY_END }, { } }; static struct hidinput_key_translation powerbook_numlock_keys[] = { - { KEY_J, KEY_KP1 }, - { KEY_K, KEY_KP2 }, - { KEY_L, KEY_KP3 }, - { KEY_U, KEY_KP4 }, - { KEY_I, KEY_KP5 }, - { KEY_O, KEY_KP6 }, - { KEY_7, KEY_KP7 }, - { KEY_8, KEY_KP8 }, - { KEY_9, KEY_KP9 }, - { KEY_M, KEY_KP0 }, - { KEY_DOT, KEY_KPDOT }, - { KEY_SLASH, KEY_KPPLUS }, + { KEY_J, KEY_KP1 }, + { KEY_K, KEY_KP2 }, + { KEY_L, KEY_KP3 }, + { KEY_U, KEY_KP4 }, + { KEY_I, KEY_KP5 }, + { KEY_O, KEY_KP6 }, + { KEY_7, KEY_KP7 }, + { KEY_8, KEY_KP8 }, + { KEY_9, KEY_KP9 }, + { KEY_M, KEY_KP0 }, + { KEY_DOT, KEY_KPDOT }, + { KEY_SLASH, KEY_KPPLUS }, { KEY_SEMICOLON, KEY_KPMINUS }, - { KEY_P, KEY_KPASTERISK }, - { KEY_MINUS, KEY_KPEQUAL }, - { KEY_0, KEY_KPSLASH }, - { KEY_F6, KEY_NUMLOCK }, - { KEY_KPENTER, KEY_KPENTER }, + { KEY_P, KEY_KPASTERISK }, + { KEY_MINUS, KEY_KPEQUAL }, + { KEY_0, KEY_KPSLASH }, + { KEY_F6, KEY_NUMLOCK }, + { KEY_KPENTER, KEY_KPENTER }, { KEY_BACKSPACE, KEY_BACKSPACE }, { } }; @@ -127,11 +128,6 @@ static struct hidinput_key_translation powerbook_iso_keyboard[] = { { } }; -static int usbhid_pb_fnmode = 1; -module_param_named(pb_fnmode, usbhid_pb_fnmode, int, 0644); -MODULE_PARM_DESC(pb_fnmode, - "Mode of fn key on PowerBooks (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)"); - static struct hidinput_key_translation *find_translation(struct hidinput_key_translation *table, u16 from) { struct hidinput_key_translation *trans; @@ -145,7 +141,7 @@ static struct hidinput_key_translation *find_translation(struct hidinput_key_tra } static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input, - struct hid_usage *usage, __s32 value) + struct hid_usage *usage, __s32 value) { struct hidinput_key_translation *trans; @@ -158,7 +154,7 @@ static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input, return 1; } - if (usbhid_pb_fnmode) { + if (hid->pb_fnmode) { int do_translate; trans = find_translation(powerbook_fn_keys, usage->code); @@ -167,8 +163,8 @@ static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input, do_translate = 1; else if (trans->flags & POWERBOOK_FLAG_FKEY) do_translate = - (usbhid_pb_fnmode == 2 && (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)) || - (usbhid_pb_fnmode == 1 && !(hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)); + (hid->pb_fnmode == 2 && (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)) || + (hid->pb_fnmode == 1 && !(hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)); else do_translate = (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON); @@ -185,7 +181,7 @@ static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input, } if (test_bit(usage->code, hid->pb_pressed_numlock) || - test_bit(LED_NUML, input->led)) { + test_bit(LED_NUML, input->led)) { trans = find_translation(powerbook_numlock_keys, usage->code); if (trans) { @@ -227,10 +223,11 @@ static void hidinput_pb_setup(struct input_dev *input) for (trans = powerbook_iso_keyboard; trans->from; trans++) set_bit(trans->to, input->keybit); + } #else static inline int hidinput_pb_event(struct hid_device *hid, struct input_dev *input, - struct hid_usage *usage, __s32 value) + struct hid_usage *usage, __s32 value) { return 0; } @@ -582,7 +579,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel goto ignore; if ((device->quirks & HID_QUIRK_BAD_RELATIVE_KEYS) && - usage->type == EV_KEY && (field->flags & HID_MAIN_ITEM_RELATIVE)) + usage->type == EV_KEY && (field->flags & HID_MAIN_ITEM_RELATIVE)) field->flags &= ~HID_MAIN_ITEM_RELATIVE; set_bit(usage->type, input->evbit); @@ -724,8 +721,9 @@ void hidinput_report_event(struct hid_device *hid, struct hid_report *report) list_for_each_entry(hidinput, &hid->inputs, list) input_sync(hidinput->input); } +EXPORT_SYMBOL_GPL(hidinput_report_event); -static int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field) +int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field) { struct hid_report *report; int i, j; @@ -740,41 +738,7 @@ static int hidinput_find_field(struct hid_device *hid, unsigned int type, unsign } return -1; } - -static int hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) -{ - struct hid_device *hid = dev->private; - struct hid_field *field; - int offset; - - if (type == EV_FF) - return input_ff_event(dev, type, code, value); - - if (type != EV_LED) - return -1; - - if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) { - warn("event field not found"); - return -1; - } - - hid_set_field(field, offset, value); - hid_submit_report(hid, field->report, USB_DIR_OUT); - - return 0; -} - -static int hidinput_open(struct input_dev *dev) -{ - struct hid_device *hid = dev->private; - return hid_open(hid); -} - -static void hidinput_close(struct input_dev *dev) -{ - struct hid_device *hid = dev->private; - hid_close(hid); -} +EXPORT_SYMBOL_GPL(hidinput_find_field); /* * Register the input device; print a message. @@ -784,7 +748,6 @@ static void hidinput_close(struct input_dev *dev) int hidinput_connect(struct hid_device *hid) { - struct usb_device *dev = hid->dev; struct hid_report *report; struct hid_input *hidinput = NULL; struct input_dev *input_dev; @@ -818,16 +781,18 @@ int hidinput_connect(struct hid_device *hid) } input_dev->private = hid; - input_dev->event = hidinput_input_event; - input_dev->open = hidinput_open; - input_dev->close = hidinput_close; + input_dev->event = hid->hidinput_input_event; + input_dev->open = hid->hidinput_open; + input_dev->close = hid->hidinput_close; input_dev->name = hid->name; input_dev->phys = hid->phys; input_dev->uniq = hid->uniq; - usb_to_input_id(dev, &input_dev->id); - input_dev->cdev.dev = &hid->intf->dev; - + input_dev->id.bustype = hid->bus; + input_dev->id.vendor = hid->vendor; + input_dev->id.product = hid->product; + input_dev->id.version = hid->version; + input_dev->cdev.dev = hid->dev; hidinput->input = input_dev; list_add_tail(&hidinput->list, &hid->inputs); } @@ -849,16 +814,12 @@ int hidinput_connect(struct hid_device *hid) } } - /* This only gets called when we are a single-input (most of the - * time). IOW, not a HID_QUIRK_MULTI_INPUT. The hid_ff_init() is - * only useful in this case, and not for multi-input quirks. */ - if (hidinput) { - hid_ff_init(hid); + if (hidinput) input_register_device(hidinput->input); - } return 0; } +EXPORT_SYMBOL_GPL(hidinput_connect); void hidinput_disconnect(struct hid_device *hid) { @@ -870,3 +831,5 @@ void hidinput_disconnect(struct hid_device *hid) kfree(hidinput); } } +EXPORT_SYMBOL_GPL(hidinput_disconnect); + diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 94a4e9a3013..2e22a2ffa60 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -119,7 +119,7 @@ static ssize_t i2cdev_read (struct file *file, char __user *buf, size_t count, return -ENOMEM; pr_debug("i2c-dev: i2c-%d reading %zd bytes.\n", - iminor(file->f_dentry->d_inode), count); + iminor(file->f_path.dentry->d_inode), count); ret = i2c_master_recv(client,tmp,count); if (ret >= 0) @@ -147,7 +147,7 @@ static ssize_t i2cdev_write (struct file *file, const char __user *buf, size_t c } pr_debug("i2c-dev: i2c-%d writing %zd bytes.\n", - iminor(file->f_dentry->d_inode), count); + iminor(file->f_path.dentry->d_inode), count); ret = i2c_master_send(client,tmp,count); kfree(tmp); diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c index d419e4bb54f..89109be5162 100644 --- a/drivers/ide/pci/alim15x3.c +++ b/drivers/ide/pci/alim15x3.c @@ -586,11 +586,11 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c { unsigned long flags; u8 tmpbyte; - struct pci_dev *north = pci_find_slot(0, PCI_DEVFN(0,0)); + struct pci_dev *north = pci_get_slot(dev->bus, PCI_DEVFN(0,0)); pci_read_config_byte(dev, PCI_REVISION_ID, &m5229_revision); - isa_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); + isa_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); #if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) if (!ali_proc) { @@ -613,8 +613,7 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c * clear bit 7 */ pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F); - local_irq_restore(flags); - return 0; + goto out; } /* @@ -637,10 +636,8 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c * box without a device at 0:0.0. The ALi bridge will be at * 0:0.0 so if we didn't find one we know what is cooking. */ - if (north && north->vendor != PCI_VENDOR_ID_AL) { - local_irq_restore(flags); - return 0; - } + if (north && north->vendor != PCI_VENDOR_ID_AL) + goto out; if (m5229_revision < 0xC5 && isa_dev) { @@ -661,6 +658,9 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x02); } } +out: + pci_dev_put(north); + pci_dev_put(isa_dev); local_irq_restore(flags); return 0; } diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c index 6c097e80b4d..3ca581063f7 100644 --- a/drivers/ide/pci/pdc202xx_new.c +++ b/drivers/ide/pci/pdc202xx_new.c @@ -9,6 +9,7 @@ * Split from: * linux/drivers/ide/pdc202xx.c Version 0.35 Mar. 30, 2002 * Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org> + * Copyright (C) 2005-2006 MontaVista Software, Inc. * Portions Copyright (C) 1999 Promise Technology, Inc. * Author: Frank Tiernan (frankt@promise.com) * Released under terms of General Public License @@ -168,12 +169,8 @@ static int pdcnew_new_tune_chipset (ide_drive_t *drive, u8 xferspeed) */ static void pdcnew_tune_drive(ide_drive_t *drive, u8 pio) { - u8 speed; - - if (pio == 5) pio = 4; - speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, pio, NULL); - - (void)pdcnew_new_tune_chipset(drive, speed); + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + (void)pdcnew_new_tune_chipset(drive, XFER_PIO_0 + pio); } static u8 pdcnew_new_cable_detect (ide_hwif_t *hwif) @@ -207,10 +204,8 @@ static int config_chipset_for_dma (ide_drive_t *drive) speed = ide_dma_speed(drive, pdcnew_ratemask(drive)); - if (!(speed)) { - hwif->tuneproc(drive, 5); + if (!speed) return 0; - } (void) hwif->speedproc(drive, speed); return ide_dma_enable(drive); @@ -234,7 +229,7 @@ static int pdcnew_config_drive_xfer_rate (ide_drive_t *drive) } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: - hwif->tuneproc(drive, 5); + hwif->tuneproc(drive, 255); return hwif->ide_dma_off_quietly(drive); } /* IORDY not supported */ @@ -362,6 +357,7 @@ static int __devinit init_setup_pdc20270(struct pci_dev *dev, ide_pci_device_t *d) { struct pci_dev *findev = NULL; + int ret; if ((dev->bus->self && dev->bus->self->vendor == PCI_VENDOR_ID_DEC) && @@ -369,14 +365,16 @@ static int __devinit init_setup_pdc20270(struct pci_dev *dev, if (PCI_SLOT(dev->devfn) & 2) return -ENODEV; d->extra = 0; - while ((findev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) { + while ((findev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) { if ((findev->vendor == dev->vendor) && (findev->device == dev->device) && (PCI_SLOT(findev->devfn) & 2)) { if (findev->irq != dev->irq) { findev->irq = dev->irq; } - return ide_setup_pci_devices(dev, findev, d); + ret = ide_setup_pci_devices(dev, findev, d); + pci_dev_put(findev); + return ret; } } } diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c index 92edf76bd7a..6b313139b5e 100644 --- a/drivers/ide/pci/sis5513.c +++ b/drivers/ide/pci/sis5513.c @@ -800,9 +800,10 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c if (trueid == 0x5517) { /* SiS 961/961B */ - lpc_bridge = pci_find_slot(0x00, 0x10); /* Bus 0, Dev 2, Fn 0 */ + lpc_bridge = pci_get_slot(dev->bus, 0x10); /* Bus 0, Dev 2, Fn 0 */ pci_read_config_byte(lpc_bridge, PCI_REVISION_ID, &sbrev); pci_read_config_byte(dev, 0x49, &prefctl); + pci_dev_put(lpc_bridge); if (sbrev == 0x10 && (prefctl & 0x80)) { printk(KERN_INFO "SIS5513: SiS 961B MuTIOL IDE UDMA133 controller\n"); diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c index 0b4b6049851..5afefe8692f 100644 --- a/drivers/ide/pci/sl82c105.c +++ b/drivers/ide/pci/sl82c105.c @@ -299,14 +299,14 @@ static void sl82c105_selectproc(ide_drive_t *drive) //DBG(("sl82c105_selectproc(drive:%s)\n", drive->name)); mask = hwif->channel ? CTRL_P1F16 : CTRL_P0F16; - old = val = *((u32 *)&hwif->hwif_data); + old = val = (u32)pci_get_drvdata(dev); if (drive->using_dma) val &= ~mask; else val |= mask; if (old != val) { pci_write_config_dword(dev, 0x40, val); - *((u32 *)&hwif->hwif_data) = val; + pci_set_drvdata(dev, (void *)val); } } @@ -316,14 +316,13 @@ static void sl82c105_selectproc(ide_drive_t *drive) */ static void sl82c105_resetproc(ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = HWIF(drive)->pci_dev; u32 val; DBG(("sl82c105_resetproc(drive:%s)\n", drive->name)); pci_read_config_dword(dev, 0x40, &val); - *((u32 *)&hwif->hwif_data) = val; + pci_set_drvdata(dev, (void *)val); } /* @@ -394,6 +393,7 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c pci_read_config_dword(dev, 0x40, &val); val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16; pci_write_config_dword(dev, 0x40, val); + pci_set_drvdata(dev, (void *)val); return dev->irq; } @@ -404,30 +404,25 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) { - struct pci_dev *dev = hwif->pci_dev; unsigned int rev; u8 dma_state; - u32 val; - + DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index)); hwif->tuneproc = tune_sl82c105; hwif->selectproc = sl82c105_selectproc; hwif->resetproc = sl82c105_resetproc; - - /* Default to PIO 0 for fallback unless tuned otherwise, - * we always autotune PIO, this is done before DMA is - * checked, so there is no risk of accidentally disabling - * DMA - */ + + /* + * Default to PIO 0 for fallback unless tuned otherwise. + * We always autotune PIO, this is done before DMA is checked, + * so there's no risk of accidentally disabling DMA + */ hwif->drives[0].pio_speed = XFER_PIO_0; hwif->drives[0].autotune = 1; - hwif->drives[1].pio_speed = XFER_PIO_1; + hwif->drives[1].pio_speed = XFER_PIO_0; hwif->drives[1].autotune = 1; - pci_read_config_dword(dev, 0x40, &val); - *((u32 *)&hwif->hwif_data) = val; - hwif->atapi_dma = 0; hwif->mwdma_mask = 0; hwif->swdma_mask = 0; diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h index af4a78a8ef3..536ba3f580f 100644 --- a/drivers/ieee1394/ieee1394_core.h +++ b/drivers/ieee1394/ieee1394_core.h @@ -217,7 +217,7 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size, /* return the index (within a minor number block) of a file */ static inline unsigned char ieee1394_file_to_instance(struct file *file) { - return file->f_dentry->d_inode->i_cindex; + return file->f_path.dentry->d_inode->i_cindex; } extern int hpsb_disable_irm; diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 4e16314e8e6..a617ca7b692 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -534,9 +534,9 @@ struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file, * module reference. */ filp->f_op = fops_get(&uverbs_event_fops); - filp->f_vfsmnt = mntget(uverbs_event_mnt); - filp->f_dentry = dget(uverbs_event_mnt->mnt_root); - filp->f_mapping = filp->f_dentry->d_inode->i_mapping; + filp->f_path.mnt = mntget(uverbs_event_mnt); + filp->f_path.dentry = dget(uverbs_event_mnt->mnt_root); + filp->f_mapping = filp->f_path.dentry->d_inode->i_mapping; filp->f_flags = O_RDONLY; filp->f_mode = FMODE_READ; filp->private_data = ev_file; diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c index a9ddc6911f6..340f27e3ebf 100644 --- a/drivers/infiniband/hw/ipath/ipath_file_ops.c +++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c @@ -1745,9 +1745,9 @@ static int ipath_assign_port(struct file *fp, goto done; } - i_minor = iminor(fp->f_dentry->d_inode) - IPATH_USER_MINOR_BASE; + i_minor = iminor(fp->f_path.dentry->d_inode) - IPATH_USER_MINOR_BASE; ipath_cdbg(VERBOSE, "open on dev %lx (minor %d)\n", - (long)fp->f_dentry->d_inode->i_rdev, i_minor); + (long)fp->f_path.dentry->d_inode->i_rdev, i_minor); if (i_minor) ret = find_free_port(i_minor - 1, fp, uinfo); diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c index d9ff283f725..79a60f020a2 100644 --- a/drivers/infiniband/hw/ipath/ipath_fs.c +++ b/drivers/infiniband/hw/ipath/ipath_fs.c @@ -118,7 +118,7 @@ static ssize_t atomic_counters_read(struct file *file, char __user *buf, u16 i; struct ipath_devdata *dd; - dd = file->f_dentry->d_inode->i_private; + dd = file->f_path.dentry->d_inode->i_private; for (i = 0; i < NUM_COUNTERS; i++) counters[i] = ipath_snap_cntr(dd, i); @@ -138,7 +138,7 @@ static ssize_t atomic_node_info_read(struct file *file, char __user *buf, struct ipath_devdata *dd; u64 guid; - dd = file->f_dentry->d_inode->i_private; + dd = file->f_path.dentry->d_inode->i_private; guid = be64_to_cpu(dd->ipath_guid); @@ -177,7 +177,7 @@ static ssize_t atomic_port_info_read(struct file *file, char __user *buf, u32 tmp, tmp2; struct ipath_devdata *dd; - dd = file->f_dentry->d_inode->i_private; + dd = file->f_path.dentry->d_inode->i_private; /* so we only initialize non-zero fields. */ memset(portinfo, 0, sizeof portinfo); @@ -324,7 +324,7 @@ static ssize_t flash_read(struct file *file, char __user *buf, goto bail; } - dd = file->f_dentry->d_inode->i_private; + dd = file->f_path.dentry->d_inode->i_private; if (ipath_eeprom_read(dd, pos, tmp, count)) { ipath_dev_err(dd, "failed to read from flash\n"); ret = -ENXIO; @@ -377,7 +377,7 @@ static ssize_t flash_write(struct file *file, const char __user *buf, goto bail_tmp; } - dd = file->f_dentry->d_inode->i_private; + dd = file->f_path.dentry->d_inode->i_private; if (ipath_eeprom_write(dd, pos, tmp, count)) { ret = -ENXIO; ipath_dev_err(dd, "failed to write to flash\n"); diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index 21422a3336a..7ec7c4b937f 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c @@ -124,7 +124,7 @@ static int mthca_query_device(struct ib_device *ibdev, props->max_map_per_fmr = 255; else props->max_map_per_fmr = - (1 << (32 - long_log2(mdev->limits.num_mpts))) - 1; + (1 << (32 - ilog2(mdev->limits.num_mpts))) - 1; err = 0; out: @@ -816,7 +816,7 @@ static int mthca_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *uda lkey = ucmd.lkey; } - ret = mthca_RESIZE_CQ(dev, cq->cqn, lkey, long_log2(entries), &status); + ret = mthca_RESIZE_CQ(dev, cq->cqn, lkey, ilog2(entries), &status); if (status) ret = -EINVAL; diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 33e3ba7937f..d844a2569b4 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -636,11 +636,11 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, if (mthca_is_memfree(dev)) { if (qp->rq.max) - qp_context->rq_size_stride = long_log2(qp->rq.max) << 3; + qp_context->rq_size_stride = ilog2(qp->rq.max) << 3; qp_context->rq_size_stride |= qp->rq.wqe_shift - 4; if (qp->sq.max) - qp_context->sq_size_stride = long_log2(qp->sq.max) << 3; + qp_context->sq_size_stride = ilog2(qp->sq.max) << 3; qp_context->sq_size_stride |= qp->sq.wqe_shift - 4; } diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index 34d2c476896..10684da33d5 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c @@ -120,7 +120,7 @@ static void mthca_arbel_init_srq_context(struct mthca_dev *dev, memset(context, 0, sizeof *context); - logsize = long_log2(srq->max); + logsize = ilog2(srq->max); context->state_logsize_srqn = cpu_to_be32(logsize << 24 | srq->srqn); context->lkey = cpu_to_be32(srq->mr.ibmr.lkey); context->db_index = cpu_to_be32(srq->db_index); @@ -213,7 +213,7 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd, if (!mthca_is_memfree(dev) && (ds > dev->limits.max_desc_sz)) return -EINVAL; - srq->wqe_shift = long_log2(ds); + srq->wqe_shift = ilog2(ds); srq->srqn = mthca_alloc(&dev->srq_table.alloc); if (srq->srqn == -1) diff --git a/drivers/infiniband/ulp/iser/iser_memory.c b/drivers/infiniband/ulp/iser/iser_memory.c index 5e122501fd8..3aedd59b8a8 100644 --- a/drivers/infiniband/ulp/iser/iser_memory.c +++ b/drivers/infiniband/ulp/iser/iser_memory.c @@ -114,7 +114,7 @@ int iser_start_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask, if (cmd_data_len > ISER_KMALLOC_THRESHOLD) mem = (void *)__get_free_pages(GFP_NOIO, - long_log2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT); + ilog2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT); else mem = kmalloc(cmd_data_len, GFP_NOIO); @@ -211,7 +211,7 @@ void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask, if (cmd_data_len > ISER_KMALLOC_THRESHOLD) free_pages((unsigned long)mem_copy->copy_buf, - long_log2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT); + ilog2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT); else kfree(mem_copy->copy_buf); diff --git a/drivers/input/Makefile b/drivers/input/Makefile index a005b1df5f1..da575deb3c7 100644 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile @@ -21,3 +21,4 @@ obj-$(CONFIG_INPUT_MOUSE) += mouse/ obj-$(CONFIG_INPUT_JOYSTICK) += joystick/ obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/ obj-$(CONFIG_INPUT_MISC) += misc/ + diff --git a/drivers/isdn/act2000/module.c b/drivers/isdn/act2000/module.c index 90593e2ef87..e3e5c139907 100644 --- a/drivers/isdn/act2000/module.c +++ b/drivers/isdn/act2000/module.c @@ -573,12 +573,11 @@ act2000_alloccard(int bus, int port, int irq, char *id) { int i; act2000_card *card; - if (!(card = (act2000_card *) kmalloc(sizeof(act2000_card), GFP_KERNEL))) { + if (!(card = kzalloc(sizeof(act2000_card), GFP_KERNEL))) { printk(KERN_WARNING "act2000: (%s) Could not allocate card-struct.\n", id); return; } - memset((char *) card, 0, sizeof(act2000_card)); spin_lock_init(&card->lock); spin_lock_init(&card->mnlock); skb_queue_head_init(&card->sndq); diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 11844bbfe93..d22c0224fde 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -215,13 +215,12 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) unsigned int minor = 0; unsigned long flags; - mp = kmalloc(sizeof(*mp), GFP_ATOMIC); + mp = kzalloc(sizeof(*mp), GFP_ATOMIC); if (!mp) { printk(KERN_ERR "capi: can't alloc capiminor\n"); return NULL; } - memset(mp, 0, sizeof(struct capiminor)); mp->ap = ap; mp->ncci = ncci; mp->msgid = 0; @@ -304,10 +303,9 @@ static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci) struct capiminor *mp = NULL; #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ - np = kmalloc(sizeof(*np), GFP_ATOMIC); + np = kzalloc(sizeof(*np), GFP_ATOMIC); if (!np) return NULL; - memset(np, 0, sizeof(struct capincci)); np->ncci = ncci; np->cdev = cdev; #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE @@ -384,10 +382,9 @@ static struct capidev *capidev_alloc(void) struct capidev *cdev; unsigned long flags; - cdev = kmalloc(sizeof(*cdev), GFP_KERNEL); + cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); if (!cdev) return NULL; - memset(cdev, 0, sizeof(struct capidev)); init_MUTEX(&cdev->ncci_list_sem); skb_queue_head_init(&cdev->recvqueue); @@ -1010,7 +1007,7 @@ static int capinc_tty_open(struct tty_struct * tty, struct file * file) { struct capiminor *mp; - if ((mp = capiminor_find(iminor(file->f_dentry->d_inode))) == 0) + if ((mp = capiminor_find(iminor(file->f_path.dentry->d_inode))) == 0) return -ENXIO; if (mp->nccip == 0) return -ENXIO; @@ -1203,7 +1200,7 @@ static int capinc_tty_ioctl(struct tty_struct *tty, struct file * file, return error; } -static void capinc_tty_set_termios(struct tty_struct *tty, struct termios * old) +static void capinc_tty_set_termios(struct tty_struct *tty, struct ktermios * old) { #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_set_termios\n"); diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c index b6f9476c050..097bfa7bc32 100644 --- a/drivers/isdn/capi/capidrv.c +++ b/drivers/isdn/capi/capidrv.c @@ -334,12 +334,11 @@ static capidrv_plci *new_plci(capidrv_contr * card, int chan) { capidrv_plci *plcip; - plcip = (capidrv_plci *) kmalloc(sizeof(capidrv_plci), GFP_ATOMIC); + plcip = kzalloc(sizeof(capidrv_plci), GFP_ATOMIC); if (plcip == 0) return NULL; - memset(plcip, 0, sizeof(capidrv_plci)); plcip->state = ST_PLCI_NONE; plcip->plci = 0; plcip->msgid = 0; @@ -404,12 +403,11 @@ static inline capidrv_ncci *new_ncci(capidrv_contr * card, { capidrv_ncci *nccip; - nccip = (capidrv_ncci *) kmalloc(sizeof(capidrv_ncci), GFP_ATOMIC); + nccip = kzalloc(sizeof(capidrv_ncci), GFP_ATOMIC); if (nccip == 0) return NULL; - memset(nccip, 0, sizeof(capidrv_ncci)); nccip->ncci = ncci; nccip->state = ST_NCCI_NONE; nccip->plcip = plcip; @@ -2005,12 +2003,11 @@ static int capidrv_addcontr(u16 contr, struct capi_profile *profp) printk(KERN_WARNING "capidrv: (%s) Could not reserve module\n", id); return -1; } - if (!(card = (capidrv_contr *) kmalloc(sizeof(capidrv_contr), GFP_ATOMIC))) { + if (!(card = kzalloc(sizeof(capidrv_contr), GFP_ATOMIC))) { printk(KERN_WARNING "capidrv: (%s) Could not allocate contr-struct.\n", id); return -1; } - memset(card, 0, sizeof(capidrv_contr)); card->owner = THIS_MODULE; init_timer(&card->listentimer); strcpy(card->name, id); diff --git a/drivers/isdn/gigaset/Kconfig b/drivers/isdn/gigaset/Kconfig index 5b203fe21dc..708d47a6484 100644 --- a/drivers/isdn/gigaset/Kconfig +++ b/drivers/isdn/gigaset/Kconfig @@ -5,6 +5,7 @@ config ISDN_DRV_GIGASET tristate "Siemens Gigaset support (isdn)" depends on ISDN_I4L select CRC_CCITT + select BITREVERSE help Say m here if you have a Gigaset or Sinus isdn device. diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c index ce3cd77094b..88e958f176d 100644 --- a/drivers/isdn/gigaset/asyncdata.c +++ b/drivers/isdn/gigaset/asyncdata.c @@ -15,6 +15,7 @@ #include "gigaset.h" #include <linux/crc-ccitt.h> +#include <linux/bitrev.h> //#define GIG_M10x_STUFF_VOICE_DATA @@ -302,7 +303,7 @@ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes, inputstate |= INS_skip_frame; break; } - *__skb_put(skb, 1) = gigaset_invtab[c]; + *__skb_put(skb, 1) = bitrev8(c); } if (unlikely(!numbytes)) @@ -543,7 +544,7 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail) cp = skb->data; len = skb->len; while (len--) { - c = gigaset_invtab[*cp++]; + c = bitrev8(*cp++); if (c == DLE_FLAG) *(skb_put(iraw_skb, 1)) = c; *(skb_put(iraw_skb, 1)) = c; diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index defd5743dba..95eff3b2917 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -33,43 +33,6 @@ MODULE_PARM_DESC(debug, "debug level"); #define VALID_ID 0x02 #define ASSIGNED 0x04 -/* bitwise byte inversion table */ -__u8 gigaset_invtab[256] = { - 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, - 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, - 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, - 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, - 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, - 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, - 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, - 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, - 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, - 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, - 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, - 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, - 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, - 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, - 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, - 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, - 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, - 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, - 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, - 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, - 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, - 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, - 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, - 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, - 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, - 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, - 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, - 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, - 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, - 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, - 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, - 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff -}; -EXPORT_SYMBOL_GPL(gigaset_invtab); - void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, size_t len, const unsigned char *buf) { diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index 06298cc52bf..a0317abaeb1 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -876,10 +876,6 @@ static inline void gigaset_rcv_error(struct sk_buff *procskb, } } - -/* bitwise byte inversion table */ -extern __u8 gigaset_invtab[]; /* in common.c */ - /* append received bytes to inbuf */ int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, unsigned numbytes); diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index 7edea015867..458b6462f93 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c @@ -127,7 +127,7 @@ static int if_write_room(struct tty_struct *tty); static int if_chars_in_buffer(struct tty_struct *tty); static void if_throttle(struct tty_struct *tty); static void if_unthrottle(struct tty_struct *tty); -static void if_set_termios(struct tty_struct *tty, struct termios *old); +static void if_set_termios(struct tty_struct *tty, struct ktermios *old); static int if_tiocmget(struct tty_struct *tty, struct file *file); static int if_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); @@ -490,7 +490,7 @@ static void if_unthrottle(struct tty_struct *tty) mutex_unlock(&cs->mutex); } -static void if_set_termios(struct tty_struct *tty, struct termios *old) +static void if_set_termios(struct tty_struct *tty, struct ktermios *old) { struct cardstate *cs; unsigned int iflag; diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index 8667daaa1a8..df988eb0e36 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c @@ -14,6 +14,7 @@ #include "gigaset.h" #include <linux/crc-ccitt.h> +#include <linux/bitrev.h> /* access methods for isowbuf_t */ /* ============================ */ @@ -487,7 +488,7 @@ static inline int trans_buildframe(struct isowbuf_t *iwb, gig_dbg(DEBUG_STREAM, "put %d bytes", count); write = atomic_read(&iwb->write); do { - c = gigaset_invtab[*in++]; + c = bitrev8(*in++); iwb->data[write++] = c; write %= BAS_OUTBUFSIZE; } while (--count > 0); @@ -876,7 +877,7 @@ static inline void trans_receive(unsigned char *src, unsigned count, while (count > 0) { dst = skb_put(skb, count < dobytes ? count : dobytes); while (count > 0 && dobytes > 0) { - *dst++ = gigaset_invtab[*src++]; + *dst++ = bitrev8(*src++); count--; dobytes--; } diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index fd5d7364a48..eba10466ccc 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c @@ -121,10 +121,9 @@ static int avmcs_probe(struct pcmcia_device *p_dev) p_dev->conf.Present = PRESENT_OPTION; /* Allocate space for private device-specific data */ - local = kmalloc(sizeof(local_info_t), GFP_KERNEL); + local = kzalloc(sizeof(local_info_t), GFP_KERNEL); if (!local) goto err; - memset(local, 0, sizeof(local_info_t)); p_dev->priv = local; return avmcs_config(p_dev); diff --git a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c index da272924771..7a69a18d07e 100644 --- a/drivers/isdn/hardware/avm/b1.c +++ b/drivers/isdn/hardware/avm/b1.c @@ -65,18 +65,15 @@ avmcard *b1_alloc_card(int nr_controllers) avmctrl_info *cinfo; int i; - card = kmalloc(sizeof(*card), GFP_KERNEL); + card = kzalloc(sizeof(*card), GFP_KERNEL); if (!card) return NULL; - memset(card, 0, sizeof(*card)); - - cinfo = kmalloc(sizeof(*cinfo) * nr_controllers, GFP_KERNEL); + cinfo = kzalloc(sizeof(*cinfo) * nr_controllers, GFP_KERNEL); if (!cinfo) { kfree(card); return NULL; } - memset(cinfo, 0, sizeof(*cinfo) * nr_controllers); card->ctrlinfo = cinfo; for (i = 0; i < nr_controllers; i++) { @@ -718,12 +715,11 @@ avmcard_dma_alloc(char *name, struct pci_dev *pdev, long rsize, long ssize) avmcard_dmainfo *p; void *buf; - p = kmalloc(sizeof(avmcard_dmainfo), GFP_KERNEL); + p = kzalloc(sizeof(avmcard_dmainfo), GFP_KERNEL); if (!p) { printk(KERN_WARNING "%s: no memory.\n", name); goto err; } - memset(p, 0, sizeof(avmcard_dmainfo)); p->recvbuf.size = rsize; buf = pci_alloc_consistent(pdev, rsize, &p->recvbuf.dmaaddr); diff --git a/drivers/isdn/hardware/avm/t1isa.c b/drivers/isdn/hardware/avm/t1isa.c index e47c60b0a8e..c925020fe9b 100644 --- a/drivers/isdn/hardware/avm/t1isa.c +++ b/drivers/isdn/hardware/avm/t1isa.c @@ -584,6 +584,7 @@ static void __exit t1isa_exit(void) { int i; + unregister_capi_driver(&capi_driver_t1isa); for (i = 0; i < MAX_CARDS; i++) { if (!io[i]) break; diff --git a/drivers/isdn/hardware/eicon/debug.c b/drivers/isdn/hardware/eicon/debug.c index 6851c6270ce..d835e74ecf1 100644 --- a/drivers/isdn/hardware/eicon/debug.c +++ b/drivers/isdn/hardware/eicon/debug.c @@ -756,14 +756,14 @@ int diva_get_driver_info (dword id, byte* data, int data_length) { data_length -= 9; - if ((to_copy = MIN(strlen(clients[id].drvName), data_length-1))) { + if ((to_copy = min(strlen(clients[id].drvName), (size_t)(data_length-1)))) { memcpy (p, clients[id].drvName, to_copy); p += to_copy; data_length -= to_copy; if ((data_length >= 4) && clients[id].hDbg->drvTag[0]) { *p++ = '('; data_length -= 1; - if ((to_copy = MIN(strlen(clients[id].hDbg->drvTag), data_length-2))) { + if ((to_copy = min(strlen(clients[id].hDbg->drvTag), (size_t)(data_length-2)))) { memcpy (p, clients[id].hDbg->drvTag, to_copy); p += to_copy; data_length -= to_copy; diff --git a/drivers/isdn/hardware/eicon/di.c b/drivers/isdn/hardware/eicon/di.c index 0617d7cabf0..e1df8d98c31 100644 --- a/drivers/isdn/hardware/eicon/di.c +++ b/drivers/isdn/hardware/eicon/di.c @@ -133,7 +133,7 @@ void pr_out(ADAPTER * a) i = this->XCurrent; X = PTR_X(a,this); while(i<this->XNum && length<270) { - clength = MIN((word)(270-length),X[i].PLength-this->XOffset); + clength = min((word)(270-length),(word)(X[i].PLength-this->XOffset)); a->ram_out_buffer(a, &ReqOut->XBuffer.P[length], PTR_P(a,this,&X[i].P[this->XOffset]), @@ -622,7 +622,7 @@ byte isdn_ind(ADAPTER * a, sizeof(a->stream_buffer), &final, NULL, NULL); } - IoAdapter->RBuffer.length = MIN(MLength, 270); + IoAdapter->RBuffer.length = min(MLength, (word)270); if (IoAdapter->RBuffer.length != MLength) { this->complete = 0; } else { @@ -676,9 +676,9 @@ byte isdn_ind(ADAPTER * a, this->RCurrent++; } if (cma) { - clength = MIN(MLength, R[this->RCurrent].PLength-this->ROffset); + clength = min(MLength, (word)(R[this->RCurrent].PLength-this->ROffset)); } else { - clength = MIN(a->ram_inw(a, &RBuffer->length)-offset, + clength = min(a->ram_inw(a, &RBuffer->length)-offset, R[this->RCurrent].PLength-this->ROffset); } if(R[this->RCurrent].P) { diff --git a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c index dae2e83dd5e..91fc92c01af 100644 --- a/drivers/isdn/hardware/eicon/divasmain.c +++ b/drivers/isdn/hardware/eicon/divasmain.c @@ -185,7 +185,7 @@ void diva_log_info(unsigned char *format, ...) unsigned char line[160]; va_start(args, format); - vsprintf(line, format, args); + vsnprintf(line, sizeof(line), format, args); va_end(args); printk(KERN_INFO "%s: %s\n", DRIVERLNAME, line); diff --git a/drivers/isdn/hardware/eicon/io.c b/drivers/isdn/hardware/eicon/io.c index 4a27e230b0a..6fd9b007417 100644 --- a/drivers/isdn/hardware/eicon/io.c +++ b/drivers/isdn/hardware/eicon/io.c @@ -262,7 +262,7 @@ void request(PISDN_ADAPTER IoAdapter, ENTITY * e) case IDI_SYNC_REQ_XDI_GET_CAPI_PARAMS: { diva_xdi_get_capi_parameters_t prms, *pI = &syncReq->xdi_capi_prms.info; memset (&prms, 0x00, sizeof(prms)); - prms.structure_length = MIN(sizeof(prms), pI->structure_length); + prms.structure_length = min_t(size_t, sizeof(prms), pI->structure_length); memset (pI, 0x00, pI->structure_length); prms.flag_dynamic_l1_down = (IoAdapter->capi_cfg.cfg_1 & \ DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON) ? 1 : 0; diff --git a/drivers/isdn/hardware/eicon/istream.c b/drivers/isdn/hardware/eicon/istream.c index 23139668d9b..18f8798442f 100644 --- a/drivers/isdn/hardware/eicon/istream.c +++ b/drivers/isdn/hardware/eicon/istream.c @@ -92,7 +92,7 @@ int diva_istream_write (void* context, return (-1); /* was not able to write */ break; /* only part of message was written */ } - to_write = MIN(length, DIVA_DFIFO_DATA_SZ); + to_write = min(length, DIVA_DFIFO_DATA_SZ); if (to_write) { a->ram_out_buffer (a, #ifdef PLATFORM_GT_32BIT @@ -176,7 +176,7 @@ int diva_istream_read (void* context, return (-1); /* was not able to read */ break; } - to_read = MIN(max_length, tmp[1]); + to_read = min(max_length, (int)tmp[1]); if (to_read) { a->ram_in_buffer(a, #ifdef PLATFORM_GT_32BIT diff --git a/drivers/isdn/hardware/eicon/platform.h b/drivers/isdn/hardware/eicon/platform.h index a66836cf756..2444811e0b3 100644 --- a/drivers/isdn/hardware/eicon/platform.h +++ b/drivers/isdn/hardware/eicon/platform.h @@ -83,14 +83,6 @@ #define NULL ((void *) 0) #endif -#ifndef MIN -#define MIN(a,b) ((a)>(b) ? (b) : (a)) -#endif - -#ifndef MAX -#define MAX(a,b) ((a)>(b) ? (a) : (b)) -#endif - #ifndef far #define far #endif diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig index cfd2718a490..6fa12cc8e4f 100644 --- a/drivers/isdn/hisax/Kconfig +++ b/drivers/isdn/hisax/Kconfig @@ -349,13 +349,6 @@ config HISAX_ENTERNOW_PCI This enables HiSax support for the Formula-n enter:now PCI ISDN card. -config HISAX_AMD7930 - bool "Am7930 (EXPERIMENTAL)" - depends on EXPERIMENTAL && SPARC && BROKEN - help - This enables HiSax support for the AMD7930 chips on some SPARCs. - This code is not finished yet. - endif if ISDN_DRV_HISAX @@ -402,6 +395,7 @@ config HISAX_ST5481 tristate "ST5481 USB ISDN modem (EXPERIMENTAL)" depends on USB && EXPERIMENTAL select CRC_CCITT + select BITREVERSE help This enables the driver for ST5481 based USB ISDN adapters, e.g. the BeWan Gazel 128 USB diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index 876fec6c6be..9e70c206779 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c @@ -123,11 +123,10 @@ static int avma1cs_probe(struct pcmcia_device *p_dev) DEBUG(0, "avma1cs_attach()\n"); /* Allocate space for private device-specific data */ - local = kmalloc(sizeof(local_info_t), GFP_KERNEL); + local = kzalloc(sizeof(local_info_t), GFP_KERNEL); if (!local) return -ENOMEM; - memset(local, 0, sizeof(local_info_t)); p_dev->priv = local; /* The io structure describes IO port mapping */ diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c index cede72cdbb3..17ec0b70ba1 100644 --- a/drivers/isdn/hisax/config.c +++ b/drivers/isdn/hisax/config.c @@ -227,14 +227,6 @@ const char *CardType[] = { #define DEFAULT_CFG {5,0x2E0,0,0} #endif - -#ifdef CONFIG_HISAX_AMD7930 -#undef DEFAULT_CARD -#undef DEFAULT_CFG -#define DEFAULT_CARD ISDN_CTYPE_AMD7930 -#define DEFAULT_CFG {12,0x3e0,0,0} -#endif - #ifdef CONFIG_HISAX_NICCY #undef DEFAULT_CARD #undef DEFAULT_CFG @@ -545,10 +537,6 @@ extern int setup_hfcpci(struct IsdnCard *card); extern int setup_hfcsx(struct IsdnCard *card); #endif -#if CARD_AMD7930 -extern int setup_amd7930(struct IsdnCard *card); -#endif - #if CARD_NICCY extern int setup_niccy(struct IsdnCard *card); #endif @@ -869,14 +857,13 @@ static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockow struct IsdnCard *card = cards + cardnr; struct IsdnCardState *cs; - cs = kmalloc(sizeof(struct IsdnCardState), GFP_ATOMIC); + cs = kzalloc(sizeof(struct IsdnCardState), GFP_ATOMIC); if (!cs) { printk(KERN_WARNING "HiSax: No memory for IsdnCardState(card %d)\n", cardnr + 1); goto out; } - memset(cs, 0, sizeof(struct IsdnCardState)); card->cs = cs; spin_lock_init(&cs->statlock); spin_lock_init(&cs->lock); @@ -1064,11 +1051,6 @@ static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockow ret = setup_niccy(card); break; #endif -#if CARD_AMD7930 - case ISDN_CTYPE_AMD7930: - ret = setup_amd7930(card); - break; -#endif #if CARD_ISURF case ISDN_CTYPE_ISURF: ret = setup_isurf(card); @@ -1437,7 +1419,6 @@ static int __init HiSax_init(void) break; case ISDN_CTYPE_ELSA_PCI: case ISDN_CTYPE_NETJET_S: - case ISDN_CTYPE_AMD7930: case ISDN_CTYPE_TELESPCI: case ISDN_CTYPE_W6692: case ISDN_CTYPE_NETJET_U: diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c index 3dacfff93f5..6eebeb441bf 100644 --- a/drivers/isdn/hisax/diva.c +++ b/drivers/isdn/hisax/diva.c @@ -1121,7 +1121,11 @@ setup_diva(struct IsdnCard *card) bytecnt = 32; } } + +#ifdef __ISAPNP__ ready: +#endif + printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n", (cs->subtyp == DIVA_PCI) ? "PCI" : diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index 4e180d210fa..79ab9dda7d0 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c @@ -146,9 +146,8 @@ static int elsa_cs_probe(struct pcmcia_device *link) DEBUG(0, "elsa_cs_attach()\n"); /* Allocate space for private device-specific data */ - local = kmalloc(sizeof(local_info_t), GFP_KERNEL); + local = kzalloc(sizeof(local_info_t), GFP_KERNEL); if (!local) return -ENOMEM; - memset(local, 0, sizeof(local_info_t)); local->p_dev = link; link->priv = local; diff --git a/drivers/isdn/hisax/fsm.c b/drivers/isdn/hisax/fsm.c index 0d44a3f480a..34fade96a58 100644 --- a/drivers/isdn/hisax/fsm.c +++ b/drivers/isdn/hisax/fsm.c @@ -26,12 +26,10 @@ FsmNew(struct Fsm *fsm, struct FsmNode *fnlist, int fncount) int i; fsm->jumpmatrix = (FSMFNPTR *) - kmalloc(sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count, GFP_KERNEL); + kzalloc(sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count, GFP_KERNEL); if (!fsm->jumpmatrix) return -ENOMEM; - memset(fsm->jumpmatrix, 0, sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count); - for (i = 0; i < fncount; i++) if ((fnlist[i].state>=fsm->state_count) || (fnlist[i].event>=fsm->event_count)) { printk(KERN_ERR "FsmNew Error line %d st(%ld/%ld) ev(%ld/%ld)\n", diff --git a/drivers/isdn/hisax/hfc4s8s_l1.c b/drivers/isdn/hisax/hfc4s8s_l1.c index de9b1a4d6ba..a2fa4ecb8c8 100644 --- a/drivers/isdn/hisax/hfc4s8s_l1.c +++ b/drivers/isdn/hisax/hfc4s8s_l1.c @@ -1591,11 +1591,10 @@ hfc4s8s_probe(struct pci_dev *pdev, const struct pci_device_id *ent) hfc4s8s_param *driver_data = (hfc4s8s_param *) ent->driver_data; hfc4s8s_hw *hw; - if (!(hw = kmalloc(sizeof(hfc4s8s_hw), GFP_ATOMIC))) { + if (!(hw = kzalloc(sizeof(hfc4s8s_hw), GFP_ATOMIC))) { printk(KERN_ERR "No kmem for HFC-4S/8S card\n"); return (err); } - memset(hw, 0, sizeof(hfc4s8s_hw)); hw->pdev = pdev; err = pci_enable_device(pdev); diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c index 5db0a85b827..8a48a3ce0a5 100644 --- a/drivers/isdn/hisax/hfc_pci.c +++ b/drivers/isdn/hisax/hfc_pci.c @@ -1211,7 +1211,7 @@ HFCPCI_l1hw(struct PStack *st, int pr, void *arg) break; case (HW_TESTLOOP | REQUEST): spin_lock_irqsave(&cs->lock, flags); - switch ((int) arg) { + switch ((long) arg) { case (1): Write_hfc(cs, HFCPCI_B1_SSL, 0x80); /* tx slot */ Write_hfc(cs, HFCPCI_B1_RSL, 0x80); /* rx slot */ @@ -1229,7 +1229,7 @@ HFCPCI_l1hw(struct PStack *st, int pr, void *arg) default: spin_unlock_irqrestore(&cs->lock, flags); if (cs->debug & L1_DEB_WARN) - debugl1(cs, "hfcpci_l1hw loop invalid %4x", (int) arg); + debugl1(cs, "hfcpci_l1hw loop invalid %4lx", (long) arg); return; } cs->hw.hfcpci.trm |= 0x80; /* enable IOM-loop */ @@ -1711,9 +1711,9 @@ setup_hfcpci(struct IsdnCard *card) pci_write_config_dword(cs->hw.hfcpci.dev, 0x80, (u_int) virt_to_bus(cs->hw.hfcpci.fifos)); cs->hw.hfcpci.pci_io = ioremap((ulong) cs->hw.hfcpci.pci_io, 256); printk(KERN_INFO - "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n", - (u_int) cs->hw.hfcpci.pci_io, - (u_int) cs->hw.hfcpci.fifos, + "HFC-PCI: defined at mem %p fifo %p(%#x) IRQ %d HZ %d\n", + cs->hw.hfcpci.pci_io, + cs->hw.hfcpci.fifos, (u_int) virt_to_bus(cs->hw.hfcpci.fifos), cs->irq, HZ); spin_lock_irqsave(&cs->lock, flags); diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c index 7105b043add..5a6989f23fc 100644 --- a/drivers/isdn/hisax/hfc_usb.c +++ b/drivers/isdn/hisax/hfc_usb.c @@ -1481,9 +1481,8 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) iface = iface_used; if (! (context = - kmalloc(sizeof(hfcusb_data), GFP_KERNEL))) + kzalloc(sizeof(hfcusb_data), GFP_KERNEL))) return (-ENOMEM); /* got no mem */ - memset(context, 0, sizeof(hfcusb_data)); ep = iface->endpoint; vcf = validconf[small_match]; diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h index 159c5896061..3f1137e3467 100644 --- a/drivers/isdn/hisax/hisax.h +++ b/drivers/isdn/hisax/hisax.h @@ -1139,12 +1139,6 @@ struct IsdnCardState { #define CARD_HFC_SX 0 #endif -#ifdef CONFIG_HISAX_AMD7930 -#define CARD_AMD7930 1 -#else -#define CARD_AMD7930 0 -#endif - #ifdef CONFIG_HISAX_NICCY #define CARD_NICCY 1 #ifndef ISDN_CHIP_ISAC diff --git a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c index f6db55a752c..9e088fce8c3 100644 --- a/drivers/isdn/hisax/hisax_fcpcipnp.c +++ b/drivers/isdn/hisax/hisax_fcpcipnp.c @@ -841,12 +841,10 @@ new_adapter(void) struct hisax_b_if *b_if[2]; int i; - adapter = kmalloc(sizeof(struct fritz_adapter), GFP_KERNEL); + adapter = kzalloc(sizeof(struct fritz_adapter), GFP_KERNEL); if (!adapter) return NULL; - memset(adapter, 0, sizeof(struct fritz_adapter)); - adapter->isac.hisax_d_if.owner = THIS_MODULE; adapter->isac.hisax_d_if.ifc.priv = &adapter->isac; adapter->isac.hisax_d_if.ifc.l2l1 = isac_d_l2l1; diff --git a/drivers/isdn/hisax/hisax_isac.c b/drivers/isdn/hisax/hisax_isac.c index 81eac344bb0..d0fefcf999c 100644 --- a/drivers/isdn/hisax/hisax_isac.c +++ b/drivers/isdn/hisax/hisax_isac.c @@ -433,7 +433,7 @@ static void l1m_debug(struct FsmInst *fi, char *fmt, ...) char buf[256]; va_start(args, fmt); - vsprintf(buf, fmt, args); + vsnprintf(buf, sizeof(buf), fmt, args); DBG(DBG_L1M, "%s", buf); va_end(args); } diff --git a/drivers/isdn/hisax/isdnhdlc.c b/drivers/isdn/hisax/isdnhdlc.c index cbdf54c5af8..268dced6c34 100644 --- a/drivers/isdn/hisax/isdnhdlc.c +++ b/drivers/isdn/hisax/isdnhdlc.c @@ -35,30 +35,6 @@ MODULE_LICENSE("GPL"); /*-------------------------------------------------------------------*/ -/* bit swap table. - * Very handy for devices with different bit order, - * and neccessary for each transparent B-channel access for all - * devices which works with this HDLC decoder without bit reversal. - */ -const unsigned char isdnhdlc_bit_rev_tab[256] = { - 0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0, - 0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8, - 0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4, - 0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC, - 0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2, - 0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA, - 0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6, - 0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE, - 0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1, - 0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9, - 0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5, - 0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD, - 0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3, - 0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB, - 0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7, - 0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF -}; - enum { HDLC_FAST_IDLE,HDLC_GET_FLAG_B0,HDLC_GETFLAG_B1A6,HDLC_GETFLAG_B7, HDLC_GET_DATA,HDLC_FAST_FLAG @@ -621,7 +597,6 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src, return len; } -EXPORT_SYMBOL(isdnhdlc_bit_rev_tab); EXPORT_SYMBOL(isdnhdlc_rcv_init); EXPORT_SYMBOL(isdnhdlc_decode); EXPORT_SYMBOL(isdnhdlc_out_init); diff --git a/drivers/isdn/hisax/isdnhdlc.h b/drivers/isdn/hisax/isdnhdlc.h index 5655b5f9c48..45167d2f8fb 100644 --- a/drivers/isdn/hisax/isdnhdlc.h +++ b/drivers/isdn/hisax/isdnhdlc.h @@ -57,8 +57,6 @@ struct isdnhdlc_vars { #define HDLC_CRC_ERROR 2 #define HDLC_LENGTH_ERROR 3 -extern const unsigned char isdnhdlc_bit_rev_tab[256]; - extern void isdnhdlc_rcv_init (struct isdnhdlc_vars *hdlc, int do_adapt56); extern int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, int slen,int *count, diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c index 9522141f435..030d1625c5c 100644 --- a/drivers/isdn/hisax/sedlbauer.c +++ b/drivers/isdn/hisax/sedlbauer.c @@ -677,7 +677,11 @@ setup_sedlbauer(struct IsdnCard *card) return (0); #endif /* CONFIG_PCI */ } + +#ifdef __ISAPNP__ ready: +#endif + /* In case of the sedlbauer pcmcia card, this region is in use, * reserved for us by the card manager. So we do not check it * here, it would fail. diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index 46ed65334c5..45debde05fb 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c @@ -155,9 +155,8 @@ static int sedlbauer_probe(struct pcmcia_device *link) DEBUG(0, "sedlbauer_attach()\n"); /* Allocate space for private device-specific data */ - local = kmalloc(sizeof(local_info_t), GFP_KERNEL); + local = kzalloc(sizeof(local_info_t), GFP_KERNEL); if (!local) return -ENOMEM; - memset(local, 0, sizeof(local_info_t)); local->cardnr = -1; local->p_dev = link; diff --git a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c index 75d0f248e4e..fa64115cd7c 100644 --- a/drivers/isdn/hisax/st5481_b.c +++ b/drivers/isdn/hisax/st5481_b.c @@ -14,6 +14,7 @@ #include <linux/usb.h> #include <linux/slab.h> #include <linux/netdevice.h> +#include <linux/bitrev.h> #include "st5481.h" static inline void B_L1L2(struct st5481_bcs *bcs, int pr, void *arg) @@ -72,7 +73,7 @@ static void usb_b_out(struct st5481_bcs *bcs,int buf_nr) register unsigned char *dest = urb->transfer_buffer+len; register unsigned int count; for (count = 0; count < bytes_sent; count++) - *dest++ = isdnhdlc_bit_rev_tab[*src++]; + *dest++ = bitrev8(*src++); } len += bytes_sent; } else { diff --git a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c index 1d8c2618366..b8c4855cc88 100644 --- a/drivers/isdn/hisax/st5481_d.c +++ b/drivers/isdn/hisax/st5481_d.c @@ -173,7 +173,7 @@ static void l1m_debug(struct FsmInst *fi, char *fmt, ...) char buf[256]; va_start(args, fmt); - vsprintf(buf, fmt, args); + vsnprintf(buf, sizeof(buf), fmt, args); DBG(8, "%s", buf); va_end(args); } @@ -275,7 +275,7 @@ static void dout_debug(struct FsmInst *fi, char *fmt, ...) char buf[256]; va_start(args, fmt); - vsprintf(buf, fmt, args); + vsnprintf(buf, sizeof(buf), fmt, args); DBG(0x2, "%s", buf); va_end(args); } diff --git a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c index 2716aa5c60f..bb3a28a53ff 100644 --- a/drivers/isdn/hisax/st5481_init.c +++ b/drivers/isdn/hisax/st5481_init.c @@ -69,12 +69,10 @@ static int probe_st5481(struct usb_interface *intf, le16_to_cpu(dev->descriptor.idProduct), number_of_leds); - adapter = kmalloc(sizeof(struct st5481_adapter), GFP_KERNEL); + adapter = kzalloc(sizeof(struct st5481_adapter), GFP_KERNEL); if (!adapter) return -ENOMEM; - memset(adapter, 0, sizeof(struct st5481_adapter)); - adapter->number_of_leds = number_of_leds; adapter->usb_dev = dev; diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index 6b754f18379..3e3e18239ec 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c @@ -137,9 +137,8 @@ static int teles_probe(struct pcmcia_device *link) DEBUG(0, "teles_attach()\n"); /* Allocate space for private device-specific data */ - local = kmalloc(sizeof(local_info_t), GFP_KERNEL); + local = kzalloc(sizeof(local_info_t), GFP_KERNEL); if (!local) return -ENOMEM; - memset(local, 0, sizeof(local_info_t)); local->cardnr = -1; local->p_dev = link; diff --git a/drivers/isdn/hysdn/hycapi.c b/drivers/isdn/hysdn/hycapi.c index 6bac43cc91b..b2ae4ec1e49 100644 --- a/drivers/isdn/hysdn/hycapi.c +++ b/drivers/isdn/hysdn/hycapi.c @@ -745,12 +745,11 @@ hycapi_capi_create(hysdn_card *card) return 1; } if (!card->hyctrlinfo) { - cinfo = (hycapictrl_info *) kmalloc(sizeof(hycapictrl_info), GFP_ATOMIC); + cinfo = kzalloc(sizeof(hycapictrl_info), GFP_ATOMIC); if (!cinfo) { printk(KERN_WARNING "HYSDN: no memory for capi-ctrl.\n"); return -ENOMEM; } - memset(cinfo, 0, sizeof(hycapictrl_info)); card->hyctrlinfo = cinfo; cinfo->card = card; spin_lock_init(&cinfo->lock); diff --git a/drivers/isdn/hysdn/hysdn_boot.c b/drivers/isdn/hysdn/hysdn_boot.c index 6d0eb0f42fc..be787e16bb7 100644 --- a/drivers/isdn/hysdn/hysdn_boot.c +++ b/drivers/isdn/hysdn/hysdn_boot.c @@ -278,14 +278,13 @@ pof_write_open(hysdn_card * card, unsigned char **bufp) return (-ERR_ALREADY_BOOT); /* boot already active */ } /* error no mem available */ - if (!(boot = kmalloc(sizeof(struct boot_data), GFP_KERNEL))) { + if (!(boot = kzalloc(sizeof(struct boot_data), GFP_KERNEL))) { if (card->debug_flags & LOG_MEM_ERR) hysdn_addlog(card, "POF open: unable to allocate mem"); return (-EFAULT); } card->boot = boot; card->state = CARD_STATE_BOOTING; - memset(boot, 0, sizeof(struct boot_data)); card->stopcard(card); /* first stop the card */ if (card->testram(card)) { diff --git a/drivers/isdn/hysdn/hysdn_init.c b/drivers/isdn/hysdn/hysdn_init.c index b702ed27252..9e01748a176 100644 --- a/drivers/isdn/hysdn/hysdn_init.c +++ b/drivers/isdn/hysdn/hysdn_init.c @@ -81,11 +81,10 @@ search_cards(void) if (pci_enable_device(akt_pcidev)) continue; - if (!(card = kmalloc(sizeof(hysdn_card), GFP_KERNEL))) { + if (!(card = kzalloc(sizeof(hysdn_card), GFP_KERNEL))) { printk(KERN_ERR "HYSDN: unable to alloc device mem \n"); return; } - memset(card, 0, sizeof(hysdn_card)); card->myid = cardmax; /* set own id */ card->bus = akt_pcidev->bus->number; card->devfn = akt_pcidev->devfn; /* slot + function */ diff --git a/drivers/isdn/hysdn/hysdn_net.c b/drivers/isdn/hysdn/hysdn_net.c index d205249a124..557d96c78a6 100644 --- a/drivers/isdn/hysdn/hysdn_net.c +++ b/drivers/isdn/hysdn/hysdn_net.c @@ -278,11 +278,10 @@ hysdn_net_create(hysdn_card * card) return (-ENOMEM); } hysdn_net_release(card); /* release an existing net device */ - if ((dev = kmalloc(sizeof(struct net_local), GFP_KERNEL)) == NULL) { + if ((dev = kzalloc(sizeof(struct net_local), GFP_KERNEL)) == NULL) { printk(KERN_WARNING "HYSDN: unable to allocate mem\n"); return (-ENOMEM); } - memset(dev, 0, sizeof(struct net_local)); /* clean the structure */ spin_lock_init(&((struct net_local *) dev)->lock); diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c index fcd49920b22..f241f5e551c 100644 --- a/drivers/isdn/hysdn/hysdn_proclog.c +++ b/drivers/isdn/hysdn/hysdn_proclog.c @@ -204,7 +204,7 @@ hysdn_log_read(struct file *file, char __user *buf, size_t count, loff_t * off) { struct log_data *inf; int len; - struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode); struct procdata *pd = NULL; hysdn_card *card; @@ -354,7 +354,7 @@ static unsigned int hysdn_log_poll(struct file *file, poll_table * wait) { unsigned int mask = 0; - struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode); hysdn_card *card; struct procdata *pd = NULL; @@ -405,8 +405,7 @@ hysdn_proclog_init(hysdn_card * card) /* create a cardlog proc entry */ - if ((pd = (struct procdata *) kmalloc(sizeof(struct procdata), GFP_KERNEL)) != NULL) { - memset(pd, 0, sizeof(struct procdata)); + if ((pd = kzalloc(sizeof(struct procdata), GFP_KERNEL)) != NULL) { sprintf(pd->log_name, "%s%d", PROC_LOG_BASENAME, card->myid); if ((pd->log = create_proc_entry(pd->log_name, S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry)) != NULL) { pd->log->proc_fops = &log_fops; diff --git a/drivers/isdn/i4l/isdn_bsdcomp.c b/drivers/isdn/i4l/isdn_bsdcomp.c index 0afe442db3b..a20f33b4a22 100644 --- a/drivers/isdn/i4l/isdn_bsdcomp.c +++ b/drivers/isdn/i4l/isdn_bsdcomp.c @@ -331,12 +331,10 @@ static void *bsd_alloc (struct isdn_ppp_comp_data *data) * Allocate the main control structure for this instance. */ maxmaxcode = MAXCODE(bits); - db = (struct bsd_db *) kmalloc (sizeof (struct bsd_db),GFP_KERNEL); + db = kzalloc (sizeof (struct bsd_db),GFP_KERNEL); if (!db) return NULL; - memset (db, 0, sizeof(struct bsd_db)); - db->xmit = data->flags & IPPP_COMP_FLAG_XMIT; decomp = db->xmit ? 0 : 1; diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index 69aee2602aa..6a2ef0a87ed 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -1059,7 +1059,7 @@ isdn_info_update(void) static ssize_t isdn_read(struct file *file, char __user *buf, size_t count, loff_t * off) { - uint minor = iminor(file->f_dentry->d_inode); + uint minor = iminor(file->f_path.dentry->d_inode); int len = 0; int drvidx; int chidx; @@ -1166,7 +1166,7 @@ isdn_read(struct file *file, char __user *buf, size_t count, loff_t * off) static ssize_t isdn_write(struct file *file, const char __user *buf, size_t count, loff_t * off) { - uint minor = iminor(file->f_dentry->d_inode); + uint minor = iminor(file->f_path.dentry->d_inode); int drvidx; int chidx; int retval; @@ -1228,7 +1228,7 @@ static unsigned int isdn_poll(struct file *file, poll_table * wait) { unsigned int mask = 0; - unsigned int minor = iminor(file->f_dentry->d_inode); + unsigned int minor = iminor(file->f_path.dentry->d_inode); int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL); lock_kernel(); @@ -2072,21 +2072,19 @@ isdn_add_channels(isdn_driver_t *d, int drvidx, int n, int adding) if ((adding) && (d->rcverr)) kfree(d->rcverr); - if (!(d->rcverr = kmalloc(sizeof(int) * m, GFP_ATOMIC))) { + if (!(d->rcverr = kzalloc(sizeof(int) * m, GFP_ATOMIC))) { printk(KERN_WARNING "register_isdn: Could not alloc rcverr\n"); return -1; } - memset((char *) d->rcverr, 0, sizeof(int) * m); if ((adding) && (d->rcvcount)) kfree(d->rcvcount); - if (!(d->rcvcount = kmalloc(sizeof(int) * m, GFP_ATOMIC))) { + if (!(d->rcvcount = kzalloc(sizeof(int) * m, GFP_ATOMIC))) { printk(KERN_WARNING "register_isdn: Could not alloc rcvcount\n"); if (!adding) kfree(d->rcverr); return -1; } - memset((char *) d->rcvcount, 0, sizeof(int) * m); if ((adding) && (d->rpqueue)) { for (j = 0; j < d->channels; j++) @@ -2226,11 +2224,10 @@ register_isdn(isdn_if * i) printk(KERN_WARNING "register_isdn: No write routine given.\n"); return 0; } - if (!(d = kmalloc(sizeof(isdn_driver_t), GFP_KERNEL))) { + if (!(d = kzalloc(sizeof(isdn_driver_t), GFP_KERNEL))) { printk(KERN_WARNING "register_isdn: Could not alloc driver-struct\n"); return 0; } - memset((char *) d, 0, sizeof(isdn_driver_t)); d->maxbufsize = i->maxbufsize; d->pktcount = 0; diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c index 2e4daebfb7e..c36c817578c 100644 --- a/drivers/isdn/i4l/isdn_net.c +++ b/drivers/isdn/i4l/isdn_net.c @@ -2542,17 +2542,15 @@ isdn_net_new(char *name, struct net_device *master) printk(KERN_WARNING "isdn_net: interface %s already exists\n", name); return NULL; } - if (!(netdev = (isdn_net_dev *) kmalloc(sizeof(isdn_net_dev), GFP_KERNEL))) { + if (!(netdev = kzalloc(sizeof(isdn_net_dev), GFP_KERNEL))) { printk(KERN_WARNING "isdn_net: Could not allocate net-device\n"); return NULL; } - memset(netdev, 0, sizeof(isdn_net_dev)); - if (!(netdev->local = (isdn_net_local *) kmalloc(sizeof(isdn_net_local), GFP_KERNEL))) { + if (!(netdev->local = kzalloc(sizeof(isdn_net_local), GFP_KERNEL))) { printk(KERN_WARNING "isdn_net: Could not allocate device locals\n"); kfree(netdev); return NULL; } - memset(netdev->local, 0, sizeof(isdn_net_local)); if (name == NULL) strcpy(netdev->local->name, " "); else diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c index 119412d6bd1..43811795b46 100644 --- a/drivers/isdn/i4l/isdn_ppp.c +++ b/drivers/isdn/i4l/isdn_ppp.c @@ -667,7 +667,7 @@ isdn_ppp_poll(struct file *file, poll_table * wait) if (is->debug & 0x2) printk(KERN_DEBUG "isdn_ppp_poll: minor: %d\n", - iminor(file->f_dentry->d_inode)); + iminor(file->f_path.dentry->d_inode)); /* just registers wait_queue hook. This doesn't really wait. */ poll_wait(file, &is->wq, wait); @@ -876,14 +876,12 @@ isdn_ppp_init(void) #endif /* CONFIG_ISDN_MPP */ for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - if (!(ippp_table[i] = (struct ippp_struct *) - kmalloc(sizeof(struct ippp_struct), GFP_KERNEL))) { + if (!(ippp_table[i] = kzalloc(sizeof(struct ippp_struct), GFP_KERNEL))) { printk(KERN_WARNING "isdn_ppp_init: Could not alloc ippp_table\n"); for (j = 0; j < i; j++) kfree(ippp_table[j]); return -1; } - memset((char *) ippp_table[i], 0, sizeof(struct ippp_struct)); spin_lock_init(&ippp_table[i]->buflock); ippp_table[i]->state = 0; ippp_table[i]->first = ippp_table[i]->rq + NUM_RCV_BUFFS - 1; @@ -1529,10 +1527,8 @@ static int isdn_ppp_mp_bundle_array_init(void) { int i; int sz = ISDN_MAX_CHANNELS*sizeof(ippp_bundle); - if( (isdn_ppp_bundle_arr = (ippp_bundle*)kmalloc(sz, - GFP_KERNEL)) == NULL ) + if( (isdn_ppp_bundle_arr = kzalloc(sz, GFP_KERNEL)) == NULL ) return -ENOMEM; - memset(isdn_ppp_bundle_arr, 0, sz); for( i = 0; i < ISDN_MAX_CHANNELS; i++ ) spin_lock_init(&isdn_ppp_bundle_arr[i].lock); return 0; @@ -2246,13 +2242,12 @@ static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto, static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is) { struct ippp_ccp_reset *r; - r = kmalloc(sizeof(struct ippp_ccp_reset), GFP_KERNEL); + r = kzalloc(sizeof(struct ippp_ccp_reset), GFP_KERNEL); if(!r) { printk(KERN_ERR "ippp_ccp: failed to allocate reset data" " structure - no mem\n"); return NULL; } - memset(r, 0, sizeof(struct ippp_ccp_reset)); printk(KERN_DEBUG "ippp_ccp: allocated reset data structure %p\n", r); is->reset = r; return r; @@ -2338,10 +2333,9 @@ static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_s id); return NULL; } else { - rs = kmalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL); + rs = kzalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL); if(!rs) return NULL; - memset(rs, 0, sizeof(struct ippp_ccp_reset_state)); rs->state = CCPResetIdle; rs->is = is; rs->id = id; @@ -2536,6 +2530,11 @@ static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struc rsparm.maxdlen = IPPP_RESET_MAXDATABYTES; skb_out = dev_alloc_skb(is->mru + PPP_HDRLEN); + if (!skb_out) { + kfree_skb(skb); + printk(KERN_ERR "ippp: decomp memory allocation failure\n"); + return NULL; + } len = ipc->decompress(stat, skb, skb_out, &rsparm); kfree_skb(skb); if (len <= 0) { diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 2b91bb07fc7..fc80afe555b 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -1464,7 +1464,7 @@ isdn_tty_ioctl(struct tty_struct *tty, struct file *file, } static void -isdn_tty_set_termios(struct tty_struct *tty, struct termios *old_termios) +isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { modem_info *info = (modem_info *) tty->driver_data; diff --git a/drivers/isdn/i4l/isdn_v110.c b/drivers/isdn/i4l/isdn_v110.c index 38619e8cd82..5484d3c38a5 100644 --- a/drivers/isdn/i4l/isdn_v110.c +++ b/drivers/isdn/i4l/isdn_v110.c @@ -92,9 +92,8 @@ isdn_v110_open(unsigned char key, int hdrlen, int maxsize) int i; isdn_v110_stream *v; - if ((v = kmalloc(sizeof(isdn_v110_stream), GFP_ATOMIC)) == NULL) + if ((v = kzalloc(sizeof(isdn_v110_stream), GFP_ATOMIC)) == NULL) return NULL; - memset(v, 0, sizeof(isdn_v110_stream)); v->key = key; v->nbits = 0; for (i = 0; key & (1 << i); i++) diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c index 730bbd07ebc..1e699bcaba0 100644 --- a/drivers/isdn/icn/icn.c +++ b/drivers/isdn/icn/icn.c @@ -1519,12 +1519,11 @@ icn_initcard(int port, char *id) icn_card *card; int i; - if (!(card = (icn_card *) kmalloc(sizeof(icn_card), GFP_KERNEL))) { + if (!(card = kzalloc(sizeof(icn_card), GFP_KERNEL))) { printk(KERN_WARNING "icn: (%s) Could not allocate card-struct.\n", id); return (icn_card *) 0; } - memset((char *) card, 0, sizeof(icn_card)); spin_lock_init(&card->lock); card->port = port; card->interface.owner = THIS_MODULE; diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c index c3ae2edaf6f..e3add27dd0e 100644 --- a/drivers/isdn/isdnloop/isdnloop.c +++ b/drivers/isdn/isdnloop/isdnloop.c @@ -1430,12 +1430,11 @@ isdnloop_initcard(char *id) isdnloop_card *card; int i; - if (!(card = (isdnloop_card *) kmalloc(sizeof(isdnloop_card), GFP_KERNEL))) { + if (!(card = kzalloc(sizeof(isdnloop_card), GFP_KERNEL))) { printk(KERN_WARNING "isdnloop: (%s) Could not allocate card-struct.\n", id); return (isdnloop_card *) 0; } - memset((char *) card, 0, sizeof(isdnloop_card)); card->interface.owner = THIS_MODULE; card->interface.channels = ISDNLOOP_BCH; card->interface.hl_hdrlen = 1; /* scratch area for storing ack flag*/ diff --git a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c index 1966f3410a1..11c1b0b6e39 100644 --- a/drivers/isdn/pcbit/drv.c +++ b/drivers/isdn/pcbit/drv.c @@ -73,14 +73,13 @@ int pcbit_init_dev(int board, int mem_base, int irq) struct pcbit_dev *dev; isdn_if *dev_if; - if ((dev=kmalloc(sizeof(struct pcbit_dev), GFP_KERNEL)) == NULL) + if ((dev=kzalloc(sizeof(struct pcbit_dev), GFP_KERNEL)) == NULL) { printk("pcbit_init: couldn't malloc pcbit_dev struct\n"); return -ENOMEM; } dev_pcbit[board] = dev; - memset(dev, 0, sizeof(struct pcbit_dev)); init_waitqueue_head(&dev->set_running_wq); spin_lock_init(&dev->lock); @@ -104,7 +103,7 @@ int pcbit_init_dev(int board, int mem_base, int irq) return -EACCES; } - dev->b1 = kmalloc(sizeof(struct pcbit_chan), GFP_KERNEL); + dev->b1 = kzalloc(sizeof(struct pcbit_chan), GFP_KERNEL); if (!dev->b1) { printk("pcbit_init: couldn't malloc pcbit_chan struct\n"); iounmap(dev->sh_mem); @@ -113,7 +112,7 @@ int pcbit_init_dev(int board, int mem_base, int irq) return -ENOMEM; } - dev->b2 = kmalloc(sizeof(struct pcbit_chan), GFP_KERNEL); + dev->b2 = kzalloc(sizeof(struct pcbit_chan), GFP_KERNEL); if (!dev->b2) { printk("pcbit_init: couldn't malloc pcbit_chan struct\n"); kfree(dev->b1); @@ -123,8 +122,6 @@ int pcbit_init_dev(int board, int mem_base, int irq) return -ENOMEM; } - memset(dev->b1, 0, sizeof(struct pcbit_chan)); - memset(dev->b2, 0, sizeof(struct pcbit_chan)); dev->b2->id = 1; INIT_WORK(&dev->qdelivery, pcbit_deliver); diff --git a/drivers/isdn/pcbit/layer2.c b/drivers/isdn/pcbit/layer2.c index 0c9f6df873f..6ff85574e94 100644 --- a/drivers/isdn/pcbit/layer2.c +++ b/drivers/isdn/pcbit/layer2.c @@ -369,13 +369,12 @@ pcbit_receive(struct pcbit_dev *dev) kfree(dev->read_frame); dev->read_frame = NULL; } - frame = kmalloc(sizeof(struct frame_buf), GFP_ATOMIC); + frame = kzalloc(sizeof(struct frame_buf), GFP_ATOMIC); if (frame == NULL) { printk(KERN_WARNING "kmalloc failed\n"); return; } - memset(frame, 0, sizeof(struct frame_buf)); cpu = pcbit_readb(dev); proc = pcbit_readb(dev); diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c index 06c9872e8c6..150759a5cdd 100644 --- a/drivers/isdn/sc/init.c +++ b/drivers/isdn/sc/init.c @@ -271,14 +271,13 @@ static int __init sc_init(void) * Horray! We found a board, Make sure we can register * it with ISDN4Linux */ - interface = kmalloc(sizeof(isdn_if), GFP_KERNEL); + interface = kzalloc(sizeof(isdn_if), GFP_KERNEL); if (interface == NULL) { /* * Oops, can't malloc isdn_if */ continue; } - memset(interface, 0, sizeof(isdn_if)); interface->owner = THIS_MODULE; interface->hl_hdrlen = 0; @@ -294,7 +293,7 @@ static int __init sc_init(void) /* * Allocate the board structure */ - sc_adapter[cinst] = kmalloc(sizeof(board), GFP_KERNEL); + sc_adapter[cinst] = kzalloc(sizeof(board), GFP_KERNEL); if (sc_adapter[cinst] == NULL) { /* * Oops, can't alloc memory for the board @@ -302,7 +301,6 @@ static int __init sc_init(void) kfree(interface); continue; } - memset(sc_adapter[cinst], 0, sizeof(board)); spin_lock_init(&sc_adapter[cinst]->lock); if(!register_isdn(interface)) { @@ -326,7 +324,7 @@ static int __init sc_init(void) /* * Allocate channels status structures */ - sc_adapter[cinst]->channel = kmalloc(sizeof(bchan) * channels, GFP_KERNEL); + sc_adapter[cinst]->channel = kzalloc(sizeof(bchan) * channels, GFP_KERNEL); if (sc_adapter[cinst]->channel == NULL) { /* * Oops, can't alloc memory for the channels @@ -336,7 +334,6 @@ static int __init sc_init(void) kfree(sc_adapter[cinst]); continue; } - memset(sc_adapter[cinst]->channel, 0, sizeof(bchan) * channels); /* * Lock down the hardware resources diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index d6f614738bb..5432d07c074 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -212,8 +212,8 @@ char *file_path(struct file *file, char *buf, int count) if (!buf) return NULL; - d = file->f_dentry; - v = file->f_vfsmnt; + d = file->f_path.dentry; + v = file->f_path.mnt; buf = d_path(d, v, buf, count); @@ -349,7 +349,7 @@ static struct page *read_page(struct file *file, unsigned long index, unsigned long count) { struct page *page = NULL; - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct buffer_head *bh; sector_t block; @@ -662,7 +662,7 @@ static void bitmap_file_put(struct bitmap *bitmap) bitmap_file_unmap(bitmap); if (file) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; invalidate_inode_pages(inode->i_mapping); fput(file); } diff --git a/drivers/md/dm-bio-list.h b/drivers/md/dm-bio-list.h index bbf4615f0e3..da4349649f7 100644 --- a/drivers/md/dm-bio-list.h +++ b/drivers/md/dm-bio-list.h @@ -44,6 +44,20 @@ static inline void bio_list_merge(struct bio_list *bl, struct bio_list *bl2) bl->tail = bl2->tail; } +static inline void bio_list_merge_head(struct bio_list *bl, + struct bio_list *bl2) +{ + if (!bl2->head) + return; + + if (bl->head) + bl2->tail->bi_next = bl->head; + else + bl->tail = bl2->tail; + + bl->head = bl2->head; +} + static inline struct bio *bio_list_pop(struct bio_list *bl) { struct bio *bio = bl->head; diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index a1086ee8ccc..4c2471ee054 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -220,7 +220,7 @@ static int crypt_iv_benbi_ctr(struct crypt_config *cc, struct dm_target *ti, const char *opts) { unsigned int bs = crypto_blkcipher_blocksize(cc->tfm); - int log = long_log2(bs); + int log = ilog2(bs); /* we need to calculate how far we must shift the sector count * to get the cipher block count, we use this shift in _gen */ @@ -962,7 +962,7 @@ static int crypt_map(struct dm_target *ti, struct bio *bio, atomic_set(&io->pending, 0); kcryptd_queue_io(io); - return 0; + return DM_MAPIO_SUBMITTED; } static int crypt_status(struct dm_target *ti, status_type_t type, diff --git a/drivers/md/dm-emc.c b/drivers/md/dm-emc.c index 2b2d45d7baa..265c467854d 100644 --- a/drivers/md/dm-emc.c +++ b/drivers/md/dm-emc.c @@ -40,7 +40,7 @@ static inline void free_bio(struct bio *bio) static int emc_endio(struct bio *bio, unsigned int bytes_done, int error) { - struct path *path = bio->bi_private; + struct dm_path *path = bio->bi_private; if (bio->bi_size) return 1; @@ -61,7 +61,7 @@ static int emc_endio(struct bio *bio, unsigned int bytes_done, int error) return 0; } -static struct bio *get_failover_bio(struct path *path, unsigned data_size) +static struct bio *get_failover_bio(struct dm_path *path, unsigned data_size) { struct bio *bio; struct page *page; @@ -96,7 +96,7 @@ static struct bio *get_failover_bio(struct path *path, unsigned data_size) } static struct request *get_failover_req(struct emc_handler *h, - struct bio *bio, struct path *path) + struct bio *bio, struct dm_path *path) { struct request *rq; struct block_device *bdev = bio->bi_bdev; @@ -133,7 +133,7 @@ static struct request *get_failover_req(struct emc_handler *h, } static struct request *emc_trespass_get(struct emc_handler *h, - struct path *path) + struct dm_path *path) { struct bio *bio; struct request *rq; @@ -191,7 +191,7 @@ static struct request *emc_trespass_get(struct emc_handler *h, } static void emc_pg_init(struct hw_handler *hwh, unsigned bypassed, - struct path *path) + struct dm_path *path) { struct request *rq; struct request_queue *q = bdev_get_queue(path->dev->bdev); diff --git a/drivers/md/dm-hw-handler.h b/drivers/md/dm-hw-handler.h index 15f5629e231..32eff28e4ad 100644 --- a/drivers/md/dm-hw-handler.h +++ b/drivers/md/dm-hw-handler.h @@ -32,7 +32,7 @@ struct hw_handler_type { void (*destroy) (struct hw_handler *hwh); void (*pg_init) (struct hw_handler *hwh, unsigned bypassed, - struct path *path); + struct dm_path *path); unsigned (*error) (struct hw_handler *hwh, struct bio *bio); int (*status) (struct hw_handler *hwh, status_type_t type, char *result, unsigned int maxlen); diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index da663d2ff55..4eb73d39521 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c @@ -92,12 +92,12 @@ void dm_io_put(unsigned int num_pages) *---------------------------------------------------------------*/ static inline void bio_set_region(struct bio *bio, unsigned region) { - bio->bi_io_vec[bio->bi_max_vecs - 1].bv_len = region; + bio->bi_io_vec[bio->bi_max_vecs].bv_len = region; } static inline unsigned bio_get_region(struct bio *bio) { - return bio->bi_io_vec[bio->bi_max_vecs - 1].bv_len; + return bio->bi_io_vec[bio->bi_max_vecs].bv_len; } /*----------------------------------------------------------------- @@ -136,6 +136,7 @@ static int endio(struct bio *bio, unsigned int done, int error) zero_fill_bio(bio); dec_count(io, bio_get_region(bio), error); + bio->bi_max_vecs++; bio_put(bio); return 0; @@ -250,16 +251,18 @@ static void do_region(int rw, unsigned int region, struct io_region *where, while (remaining) { /* - * Allocate a suitably sized bio, we add an extra - * bvec for bio_get/set_region(). + * Allocate a suitably sized-bio: we add an extra + * bvec for bio_get/set_region() and decrement bi_max_vecs + * to hide it from bio_add_page(). */ - num_bvecs = (remaining / (PAGE_SIZE >> 9)) + 2; + num_bvecs = (remaining / (PAGE_SIZE >> SECTOR_SHIFT)) + 2; bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, _bios); bio->bi_sector = where->sector + (where->count - remaining); bio->bi_bdev = where->bdev; bio->bi_end_io = endio; bio->bi_private = io; bio->bi_destructor = dm_bio_destructor; + bio->bi_max_vecs--; bio_set_region(bio, region); /* @@ -302,7 +305,7 @@ static void dispatch_io(int rw, unsigned int num_regions, } /* - * Drop the extra refence that we were holding to avoid + * Drop the extra reference that we were holding to avoid * the io being completed too early. */ dec_count(io, 0, 0); diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 4510ad8f971..cd6a184536a 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -765,7 +765,7 @@ out: static int do_suspend(struct dm_ioctl *param) { int r = 0; - int do_lockfs = 1; + unsigned suspend_flags = DM_SUSPEND_LOCKFS_FLAG; struct mapped_device *md; md = find_device(param); @@ -773,10 +773,12 @@ static int do_suspend(struct dm_ioctl *param) return -ENXIO; if (param->flags & DM_SKIP_LOCKFS_FLAG) - do_lockfs = 0; + suspend_flags &= ~DM_SUSPEND_LOCKFS_FLAG; + if (param->flags & DM_NOFLUSH_FLAG) + suspend_flags |= DM_SUSPEND_NOFLUSH_FLAG; if (!dm_suspended(md)) - r = dm_suspend(md, do_lockfs); + r = dm_suspend(md, suspend_flags); if (!r) r = __dev_status(md, param); @@ -788,7 +790,7 @@ static int do_suspend(struct dm_ioctl *param) static int do_resume(struct dm_ioctl *param) { int r = 0; - int do_lockfs = 1; + unsigned suspend_flags = DM_SUSPEND_LOCKFS_FLAG; struct hash_cell *hc; struct mapped_device *md; struct dm_table *new_map; @@ -814,9 +816,11 @@ static int do_resume(struct dm_ioctl *param) if (new_map) { /* Suspend if it isn't already suspended */ if (param->flags & DM_SKIP_LOCKFS_FLAG) - do_lockfs = 0; + suspend_flags &= ~DM_SUSPEND_LOCKFS_FLAG; + if (param->flags & DM_NOFLUSH_FLAG) + suspend_flags |= DM_SUSPEND_NOFLUSH_FLAG; if (!dm_suspended(md)) - dm_suspend(md, do_lockfs); + dm_suspend(md, suspend_flags); r = dm_swap_table(md, new_map); if (r) { diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c index 00234909b3d..17753d80ad2 100644 --- a/drivers/md/dm-linear.c +++ b/drivers/md/dm-linear.c @@ -77,7 +77,7 @@ static int linear_map(struct dm_target *ti, struct bio *bio, bio->bi_bdev = lc->dev->bdev; bio->bi_sector = lc->start + (bio->bi_sector - ti->begin); - return 1; + return DM_MAPIO_REMAPPED; } static int linear_status(struct dm_target *ti, status_type_t type, @@ -108,7 +108,7 @@ static int linear_ioctl(struct dm_target *ti, struct inode *inode, struct dentry fake_dentry = {}; fake_file.f_mode = lc->dev->mode; - fake_file.f_dentry = &fake_dentry; + fake_file.f_path.dentry = &fake_dentry; fake_dentry.d_inode = bdev->bd_inode; return blkdev_driver_ioctl(bdev->bd_inode, &fake_file, bdev->bd_disk, cmd, arg); diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c index 64b764bd02c..6a926135184 100644 --- a/drivers/md/dm-log.c +++ b/drivers/md/dm-log.c @@ -466,6 +466,7 @@ static int disk_resume(struct dirty_log *log) /* copy clean across to sync */ memcpy(lc->sync_bits, lc->clean_bits, size); lc->sync_count = count_bits32(lc->clean_bits, lc->bitset_uint32_count); + lc->sync_search = 0; /* set the correct number of regions in the header */ lc->header.nr_regions = lc->region_count; @@ -480,6 +481,13 @@ static uint32_t core_get_region_size(struct dirty_log *log) return lc->region_size; } +static int core_resume(struct dirty_log *log) +{ + struct log_c *lc = (struct log_c *) log->context; + lc->sync_search = 0; + return 0; +} + static int core_is_clean(struct dirty_log *log, region_t region) { struct log_c *lc = (struct log_c *) log->context; @@ -549,16 +557,19 @@ static int core_get_resync_work(struct dirty_log *log, region_t *region) return 1; } -static void core_complete_resync_work(struct dirty_log *log, region_t region, - int success) +static void core_set_region_sync(struct dirty_log *log, region_t region, + int in_sync) { struct log_c *lc = (struct log_c *) log->context; log_clear_bit(lc, lc->recovering_bits, region); - if (success) { + if (in_sync) { log_set_bit(lc, lc->sync_bits, region); lc->sync_count++; - } + } else if (log_test_bit(lc->sync_bits, region)) { + lc->sync_count--; + log_clear_bit(lc, lc->sync_bits, region); + } } static region_t core_get_sync_count(struct dirty_log *log) @@ -618,6 +629,7 @@ static struct dirty_log_type _core_type = { .module = THIS_MODULE, .ctr = core_ctr, .dtr = core_dtr, + .resume = core_resume, .get_region_size = core_get_region_size, .is_clean = core_is_clean, .in_sync = core_in_sync, @@ -625,7 +637,7 @@ static struct dirty_log_type _core_type = { .mark_region = core_mark_region, .clear_region = core_clear_region, .get_resync_work = core_get_resync_work, - .complete_resync_work = core_complete_resync_work, + .set_region_sync = core_set_region_sync, .get_sync_count = core_get_sync_count, .status = core_status, }; @@ -644,7 +656,7 @@ static struct dirty_log_type _disk_type = { .mark_region = core_mark_region, .clear_region = core_clear_region, .get_resync_work = core_get_resync_work, - .complete_resync_work = core_complete_resync_work, + .set_region_sync = core_set_region_sync, .get_sync_count = core_get_sync_count, .status = disk_status, }; diff --git a/drivers/md/dm-log.h b/drivers/md/dm-log.h index 5ae5309ebf2..86a301c8daf 100644 --- a/drivers/md/dm-log.h +++ b/drivers/md/dm-log.h @@ -90,12 +90,12 @@ struct dirty_log_type { int (*get_resync_work)(struct dirty_log *log, region_t *region); /* - * This notifies the log that the resync of an area has - * been completed. The log should then mark this region - * as CLEAN. + * This notifies the log that the resync status of a region + * has changed. It also clears the region from the recovering + * list (if present). */ - void (*complete_resync_work)(struct dirty_log *log, - region_t region, int success); + void (*set_region_sync)(struct dirty_log *log, + region_t region, int in_sync); /* * Returns the number of regions that are in sync. diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index cf8bf052138..3aa01350696 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -31,7 +31,7 @@ struct pgpath { struct priority_group *pg; /* Owning PG */ unsigned fail_count; /* Cumulative failure count */ - struct path path; + struct dm_path path; }; #define path_to_pgpath(__pgp) container_of((__pgp), struct pgpath, path) @@ -229,7 +229,7 @@ static void __switch_pg(struct multipath *m, struct pgpath *pgpath) static int __choose_path_in_pg(struct multipath *m, struct priority_group *pg) { - struct path *path; + struct dm_path *path; path = pg->ps.type->select_path(&pg->ps, &m->repeat_count); if (!path) @@ -282,10 +282,27 @@ failed: m->current_pg = NULL; } +/* + * Check whether bios must be queued in the device-mapper core rather + * than here in the target. + * + * m->lock must be held on entry. + * + * If m->queue_if_no_path and m->saved_queue_if_no_path hold the + * same value then we are not between multipath_presuspend() + * and multipath_resume() calls and we have no need to check + * for the DMF_NOFLUSH_SUSPENDING flag. + */ +static int __must_push_back(struct multipath *m) +{ + return (m->queue_if_no_path != m->saved_queue_if_no_path && + dm_noflush_suspending(m->ti)); +} + static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio, unsigned was_queued) { - int r = 1; + int r = DM_MAPIO_REMAPPED; unsigned long flags; struct pgpath *pgpath; @@ -310,11 +327,13 @@ static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio, !m->queue_io) queue_work(kmultipathd, &m->process_queued_ios); pgpath = NULL; - r = 0; - } else if (!pgpath) - r = -EIO; /* Failed */ - else + r = DM_MAPIO_SUBMITTED; + } else if (pgpath) bio->bi_bdev = pgpath->path.dev->bdev; + else if (__must_push_back(m)) + r = DM_MAPIO_REQUEUE; + else + r = -EIO; /* Failed */ mpio->pgpath = pgpath; @@ -372,8 +391,10 @@ static void dispatch_queued_ios(struct multipath *m) r = map_io(m, bio, mpio, 1); if (r < 0) bio_endio(bio, bio->bi_size, r); - else if (r == 1) + else if (r == DM_MAPIO_REMAPPED) generic_make_request(bio); + else if (r == DM_MAPIO_REQUEUE) + bio_endio(bio, bio->bi_size, -EIO); bio = next; } @@ -783,7 +804,7 @@ static int multipath_map(struct dm_target *ti, struct bio *bio, map_context->ptr = mpio; bio->bi_rw |= (1 << BIO_RW_FAILFAST); r = map_io(m, bio, mpio, 0); - if (r < 0) + if (r < 0 || r == DM_MAPIO_REQUEUE) mempool_free(mpio, m->mpio_pool); return r; @@ -957,7 +978,7 @@ static int bypass_pg_num(struct multipath *m, const char *pgstr, int bypassed) /* * pg_init must call this when it has completed its initialisation */ -void dm_pg_init_complete(struct path *path, unsigned err_flags) +void dm_pg_init_complete(struct dm_path *path, unsigned err_flags) { struct pgpath *pgpath = path_to_pgpath(path); struct priority_group *pg = pgpath->pg; @@ -1007,7 +1028,10 @@ static int do_end_io(struct multipath *m, struct bio *bio, spin_lock_irqsave(&m->lock, flags); if (!m->nr_valid_paths) { - if (!m->queue_if_no_path) { + if (__must_push_back(m)) { + spin_unlock_irqrestore(&m->lock, flags); + return DM_ENDIO_REQUEUE; + } else if (!m->queue_if_no_path) { spin_unlock_irqrestore(&m->lock, flags); return -EIO; } else { @@ -1042,7 +1066,7 @@ static int do_end_io(struct multipath *m, struct bio *bio, queue_work(kmultipathd, &m->process_queued_ios); spin_unlock_irqrestore(&m->lock, flags); - return 1; /* io not complete */ + return DM_ENDIO_INCOMPLETE; /* io not complete */ } static int multipath_end_io(struct dm_target *ti, struct bio *bio, @@ -1060,7 +1084,7 @@ static int multipath_end_io(struct dm_target *ti, struct bio *bio, if (ps->type->end_io) ps->type->end_io(ps, &pgpath->path); } - if (r <= 0) + if (r != DM_ENDIO_INCOMPLETE) mempool_free(mpio, m->mpio_pool); return r; @@ -1272,7 +1296,7 @@ static int multipath_ioctl(struct dm_target *ti, struct inode *inode, struct dentry fake_dentry = {}; int r = 0; - fake_file.f_dentry = &fake_dentry; + fake_file.f_path.dentry = &fake_dentry; spin_lock_irqsave(&m->lock, flags); diff --git a/drivers/md/dm-mpath.h b/drivers/md/dm-mpath.h index 8a4bf2b6d52..b9cdcbb3ed5 100644 --- a/drivers/md/dm-mpath.h +++ b/drivers/md/dm-mpath.h @@ -11,7 +11,7 @@ struct dm_dev; -struct path { +struct dm_path { struct dm_dev *dev; /* Read-only */ unsigned is_active; /* Read-only */ @@ -20,6 +20,6 @@ struct path { }; /* Callback for hwh_pg_init_fn to use when complete */ -void dm_pg_init_complete(struct path *path, unsigned err_flags); +void dm_pg_init_complete(struct dm_path *path, unsigned err_flags); #endif diff --git a/drivers/md/dm-path-selector.h b/drivers/md/dm-path-selector.h index 732d06a84f8..27357b85d73 100644 --- a/drivers/md/dm-path-selector.h +++ b/drivers/md/dm-path-selector.h @@ -44,7 +44,7 @@ struct path_selector_type { * Add an opaque path object, along with some selector specific * path args (eg, path priority). */ - int (*add_path) (struct path_selector *ps, struct path *path, + int (*add_path) (struct path_selector *ps, struct dm_path *path, int argc, char **argv, char **error); /* @@ -55,27 +55,27 @@ struct path_selector_type { * calling the function again. 0 means don't call it again unless * the path fails. */ - struct path *(*select_path) (struct path_selector *ps, + struct dm_path *(*select_path) (struct path_selector *ps, unsigned *repeat_count); /* * Notify the selector that a path has failed. */ - void (*fail_path) (struct path_selector *ps, struct path *p); + void (*fail_path) (struct path_selector *ps, struct dm_path *p); /* * Ask selector to reinstate a path. */ - int (*reinstate_path) (struct path_selector *ps, struct path *p); + int (*reinstate_path) (struct path_selector *ps, struct dm_path *p); /* * Table content based on parameters added in ps_add_path_fn * or path selector status */ - int (*status) (struct path_selector *ps, struct path *path, + int (*status) (struct path_selector *ps, struct dm_path *path, status_type_t type, char *result, unsigned int maxlen); - int (*end_io) (struct path_selector *ps, struct path *path); + int (*end_io) (struct path_selector *ps, struct dm_path *path); }; /* Register a path selector */ diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index fc8cbb168e3..23a642619be 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -344,6 +344,17 @@ static void dispatch_bios(struct mirror_set *ms, struct bio_list *bio_list) } } +static void complete_resync_work(struct region *reg, int success) +{ + struct region_hash *rh = reg->rh; + + rh->log->type->set_region_sync(rh->log, reg->key, success); + dispatch_bios(rh->ms, ®->delayed_bios); + if (atomic_dec_and_test(&rh->recovery_in_flight)) + wake_up_all(&_kmirrord_recovery_stopped); + up(&rh->recovery_count); +} + static void rh_update_states(struct region_hash *rh) { struct region *reg, *next; @@ -383,11 +394,7 @@ static void rh_update_states(struct region_hash *rh) */ list_for_each_entry_safe (reg, next, &recovered, list) { rh->log->type->clear_region(rh->log, reg->key); - rh->log->type->complete_resync_work(rh->log, reg->key, 1); - dispatch_bios(rh->ms, ®->delayed_bios); - if (atomic_dec_and_test(&rh->recovery_in_flight)) - wake_up_all(&_kmirrord_recovery_stopped); - up(&rh->recovery_count); + complete_resync_work(reg, 1); mempool_free(reg, rh->region_pool); } @@ -1137,7 +1144,7 @@ static int mirror_map(struct dm_target *ti, struct bio *bio, if (rw == WRITE) { queue_bio(ms, bio, rw); - return 0; + return DM_MAPIO_SUBMITTED; } r = ms->rh.log->type->in_sync(ms->rh.log, @@ -1146,7 +1153,7 @@ static int mirror_map(struct dm_target *ti, struct bio *bio, return r; if (r == -EWOULDBLOCK) /* FIXME: ugly */ - r = 0; + r = DM_MAPIO_SUBMITTED; /* * We don't want to fast track a recovery just for a read @@ -1159,7 +1166,7 @@ static int mirror_map(struct dm_target *ti, struct bio *bio, if (!r) { /* Pass this io over to the daemon */ queue_bio(ms, bio, rw); - return 0; + return DM_MAPIO_SUBMITTED; } m = choose_mirror(ms, bio->bi_sector); @@ -1167,7 +1174,7 @@ static int mirror_map(struct dm_target *ti, struct bio *bio, return -EIO; map_bio(ms, m, bio); - return 1; + return DM_MAPIO_REMAPPED; } static int mirror_end_io(struct dm_target *ti, struct bio *bio, diff --git a/drivers/md/dm-round-robin.c b/drivers/md/dm-round-robin.c index 6f9fcd4db9b..a348a97b65a 100644 --- a/drivers/md/dm-round-robin.c +++ b/drivers/md/dm-round-robin.c @@ -21,7 +21,7 @@ *---------------------------------------------------------------*/ struct path_info { struct list_head list; - struct path *path; + struct dm_path *path; unsigned repeat_count; }; @@ -80,7 +80,7 @@ static void rr_destroy(struct path_selector *ps) ps->context = NULL; } -static int rr_status(struct path_selector *ps, struct path *path, +static int rr_status(struct path_selector *ps, struct dm_path *path, status_type_t type, char *result, unsigned int maxlen) { struct path_info *pi; @@ -106,7 +106,7 @@ static int rr_status(struct path_selector *ps, struct path *path, * Called during initialisation to register each path with an * optional repeat_count. */ -static int rr_add_path(struct path_selector *ps, struct path *path, +static int rr_add_path(struct path_selector *ps, struct dm_path *path, int argc, char **argv, char **error) { struct selector *s = (struct selector *) ps->context; @@ -141,7 +141,7 @@ static int rr_add_path(struct path_selector *ps, struct path *path, return 0; } -static void rr_fail_path(struct path_selector *ps, struct path *p) +static void rr_fail_path(struct path_selector *ps, struct dm_path *p) { struct selector *s = (struct selector *) ps->context; struct path_info *pi = p->pscontext; @@ -149,7 +149,7 @@ static void rr_fail_path(struct path_selector *ps, struct path *p) list_move(&pi->list, &s->invalid_paths); } -static int rr_reinstate_path(struct path_selector *ps, struct path *p) +static int rr_reinstate_path(struct path_selector *ps, struct dm_path *p) { struct selector *s = (struct selector *) ps->context; struct path_info *pi = p->pscontext; @@ -159,7 +159,7 @@ static int rr_reinstate_path(struct path_selector *ps, struct path *p) return 0; } -static struct path *rr_select_path(struct path_selector *ps, +static struct dm_path *rr_select_path(struct path_selector *ps, unsigned *repeat_count) { struct selector *s = (struct selector *) ps->context; diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index b0ce2ce8227..0821a2b68a7 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -39,7 +39,7 @@ */ #define SNAPSHOT_PAGES 256 -struct workqueue_struct *ksnapd; +static struct workqueue_struct *ksnapd; static void flush_queued_bios(struct work_struct *work); struct pending_exception { @@ -564,6 +564,17 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) return r; } +static void __free_exceptions(struct dm_snapshot *s) +{ + kcopyd_client_destroy(s->kcopyd_client); + s->kcopyd_client = NULL; + + exit_exception_table(&s->pending, pending_cache); + exit_exception_table(&s->complete, exception_cache); + + s->store.destroy(&s->store); +} + static void snapshot_dtr(struct dm_target *ti) { struct dm_snapshot *s = (struct dm_snapshot *) ti->private; @@ -574,13 +585,7 @@ static void snapshot_dtr(struct dm_target *ti) /* After this returns there can be no new kcopyd jobs. */ unregister_snapshot(s); - kcopyd_client_destroy(s->kcopyd_client); - - exit_exception_table(&s->pending, pending_cache); - exit_exception_table(&s->complete, exception_cache); - - /* Deallocate memory used */ - s->store.destroy(&s->store); + __free_exceptions(s); dm_put_device(ti, s->origin); dm_put_device(ti, s->cow); @@ -868,7 +873,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio, { struct exception *e; struct dm_snapshot *s = (struct dm_snapshot *) ti->private; - int r = 1; + int r = DM_MAPIO_REMAPPED; chunk_t chunk; struct pending_exception *pe = NULL; @@ -914,7 +919,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio, remap_exception(s, &pe->e, bio); bio_list_add(&pe->snapshot_bios, bio); - r = 0; + r = DM_MAPIO_SUBMITTED; if (!pe->started) { /* this is protected by snap->lock */ @@ -992,7 +997,7 @@ static int snapshot_status(struct dm_target *ti, status_type_t type, *---------------------------------------------------------------*/ static int __origin_write(struct list_head *snapshots, struct bio *bio) { - int r = 1, first = 0; + int r = DM_MAPIO_REMAPPED, first = 0; struct dm_snapshot *snap; struct exception *e; struct pending_exception *pe, *next_pe, *primary_pe = NULL; @@ -1050,7 +1055,7 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio) bio_list_add(&primary_pe->origin_bios, bio); - r = 0; + r = DM_MAPIO_SUBMITTED; } if (!pe->primary_pe) { @@ -1099,7 +1104,7 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio) static int do_origin(struct dm_dev *origin, struct bio *bio) { struct origin *o; - int r = 1; + int r = DM_MAPIO_REMAPPED; down_read(&_origins_lock); o = __lookup_origin(origin->bdev); @@ -1156,7 +1161,7 @@ static int origin_map(struct dm_target *ti, struct bio *bio, return -EOPNOTSUPP; /* Only tell snapshots if this is a write */ - return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : 1; + return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : DM_MAPIO_REMAPPED; } #define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r)) diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index 6c29fcecd89..51f5e076001 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c @@ -186,7 +186,7 @@ static int stripe_map(struct dm_target *ti, struct bio *bio, bio->bi_bdev = sc->stripe[stripe].dev->bdev; bio->bi_sector = sc->stripe[stripe].physical_start + (chunk << sc->chunk_shift) + (offset & sc->chunk_mask); - return 1; + return DM_MAPIO_REMAPPED; } static int stripe_status(struct dm_target *ti, diff --git a/drivers/md/dm-zero.c b/drivers/md/dm-zero.c index ea569f7348d..f314d7dc9c2 100644 --- a/drivers/md/dm-zero.c +++ b/drivers/md/dm-zero.c @@ -46,7 +46,7 @@ static int zero_map(struct dm_target *ti, struct bio *bio, bio_endio(bio, bio->bi_size, 0); /* accepted bio, don't make new request */ - return 0; + return DM_MAPIO_SUBMITTED; } static struct target_type zero_target = { diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 7ec1b112a6d..fe7c56e1043 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -68,10 +68,12 @@ union map_info *dm_get_mapinfo(struct bio *bio) #define DMF_FROZEN 2 #define DMF_FREEING 3 #define DMF_DELETING 4 +#define DMF_NOFLUSH_SUSPENDING 5 struct mapped_device { struct rw_semaphore io_lock; struct semaphore suspend_lock; + spinlock_t pushback_lock; rwlock_t map_lock; atomic_t holders; atomic_t open_count; @@ -89,7 +91,8 @@ struct mapped_device { */ atomic_t pending; wait_queue_head_t wait; - struct bio_list deferred; + struct bio_list deferred; + struct bio_list pushback; /* * The current mapping. @@ -444,23 +447,50 @@ int dm_set_geometry(struct mapped_device *md, struct hd_geometry *geo) * you this clearly demarcated crap. *---------------------------------------------------------------*/ +static int __noflush_suspending(struct mapped_device *md) +{ + return test_bit(DMF_NOFLUSH_SUSPENDING, &md->flags); +} + /* * Decrements the number of outstanding ios that a bio has been * cloned into, completing the original io if necc. */ static void dec_pending(struct dm_io *io, int error) { - if (error) + unsigned long flags; + + /* Push-back supersedes any I/O errors */ + if (error && !(io->error > 0 && __noflush_suspending(io->md))) io->error = error; if (atomic_dec_and_test(&io->io_count)) { + if (io->error == DM_ENDIO_REQUEUE) { + /* + * Target requested pushing back the I/O. + * This must be handled before the sleeper on + * suspend queue merges the pushback list. + */ + spin_lock_irqsave(&io->md->pushback_lock, flags); + if (__noflush_suspending(io->md)) + bio_list_add(&io->md->pushback, io->bio); + else + /* noflush suspend was interrupted. */ + io->error = -EIO; + spin_unlock_irqrestore(&io->md->pushback_lock, flags); + } + if (end_io_acct(io)) /* nudge anyone waiting on suspend queue */ wake_up(&io->md->wait); - blk_add_trace_bio(io->md->queue, io->bio, BLK_TA_COMPLETE); + if (io->error != DM_ENDIO_REQUEUE) { + blk_add_trace_bio(io->md->queue, io->bio, + BLK_TA_COMPLETE); + + bio_endio(io->bio, io->bio->bi_size, io->error); + } - bio_endio(io->bio, io->bio->bi_size, io->error); free_io(io->md, io); } } @@ -480,12 +510,19 @@ static int clone_endio(struct bio *bio, unsigned int done, int error) if (endio) { r = endio(tio->ti, bio, error, &tio->info); - if (r < 0) + if (r < 0 || r == DM_ENDIO_REQUEUE) + /* + * error and requeue request are handled + * in dec_pending(). + */ error = r; - - else if (r > 0) - /* the target wants another shot at the io */ + else if (r == DM_ENDIO_INCOMPLETE) + /* The target will handle the io */ return 1; + else if (r) { + DMWARN("unimplemented target endio return value: %d", r); + BUG(); + } } dec_pending(tio->io, error); @@ -543,7 +580,7 @@ static void __map_bio(struct dm_target *ti, struct bio *clone, atomic_inc(&tio->io->io_count); sector = clone->bi_sector; r = ti->type->map(ti, clone, &tio->info); - if (r > 0) { + if (r == DM_MAPIO_REMAPPED) { /* the bio has been remapped so dispatch it */ blk_add_trace_remap(bdev_get_queue(clone->bi_bdev), clone, @@ -551,10 +588,8 @@ static void __map_bio(struct dm_target *ti, struct bio *clone, clone->bi_sector); generic_make_request(clone); - } - - else if (r < 0) { - /* error the io and bail out */ + } else if (r < 0 || r == DM_MAPIO_REQUEUE) { + /* error the io and bail out, or requeue it if needed */ md = tio->io->md; dec_pending(tio->io, r); /* @@ -563,6 +598,9 @@ static void __map_bio(struct dm_target *ti, struct bio *clone, clone->bi_private = md->bs; bio_put(clone); free_tio(md, tio); + } else if (r) { + DMWARN("unimplemented target map return value: %d", r); + BUG(); } } @@ -948,6 +986,7 @@ static struct mapped_device *alloc_dev(int minor) memset(md, 0, sizeof(*md)); init_rwsem(&md->io_lock); init_MUTEX(&md->suspend_lock); + spin_lock_init(&md->pushback_lock); rwlock_init(&md->map_lock); atomic_set(&md->holders, 1); atomic_set(&md->open_count, 0); @@ -966,8 +1005,8 @@ static struct mapped_device *alloc_dev(int minor) md->queue->issue_flush_fn = dm_flush_all; md->io_pool = mempool_create_slab_pool(MIN_IOS, _io_cache); - if (!md->io_pool) - goto bad2; + if (!md->io_pool) + goto bad2; md->tio_pool = mempool_create_slab_pool(MIN_IOS, _tio_cache); if (!md->tio_pool) @@ -1275,12 +1314,15 @@ static void unlock_fs(struct mapped_device *md) * dm_bind_table, dm_suspend must be called to flush any in * flight bios and ensure that any further io gets deferred. */ -int dm_suspend(struct mapped_device *md, int do_lockfs) +int dm_suspend(struct mapped_device *md, unsigned suspend_flags) { struct dm_table *map = NULL; + unsigned long flags; DECLARE_WAITQUEUE(wait, current); struct bio *def; int r = -EINVAL; + int do_lockfs = suspend_flags & DM_SUSPEND_LOCKFS_FLAG ? 1 : 0; + int noflush = suspend_flags & DM_SUSPEND_NOFLUSH_FLAG ? 1 : 0; down(&md->suspend_lock); @@ -1289,6 +1331,13 @@ int dm_suspend(struct mapped_device *md, int do_lockfs) map = dm_get_table(md); + /* + * DMF_NOFLUSH_SUSPENDING must be set before presuspend. + * This flag is cleared before dm_suspend returns. + */ + if (noflush) + set_bit(DMF_NOFLUSH_SUSPENDING, &md->flags); + /* This does not get reverted if there's an error later. */ dm_table_presuspend_targets(map); @@ -1296,11 +1345,14 @@ int dm_suspend(struct mapped_device *md, int do_lockfs) if (!md->suspended_bdev) { DMWARN("bdget failed in dm_suspend"); r = -ENOMEM; - goto out; + goto flush_and_out; } - /* Flush I/O to the device. */ - if (do_lockfs) { + /* + * Flush I/O to the device. + * noflush supersedes do_lockfs, because lock_fs() needs to flush I/Os. + */ + if (do_lockfs && !noflush) { r = lock_fs(md); if (r) goto out; @@ -1336,6 +1388,14 @@ int dm_suspend(struct mapped_device *md, int do_lockfs) down_write(&md->io_lock); remove_wait_queue(&md->wait, &wait); + if (noflush) { + spin_lock_irqsave(&md->pushback_lock, flags); + clear_bit(DMF_NOFLUSH_SUSPENDING, &md->flags); + bio_list_merge_head(&md->deferred, &md->pushback); + bio_list_init(&md->pushback); + spin_unlock_irqrestore(&md->pushback_lock, flags); + } + /* were we interrupted ? */ r = -EINTR; if (atomic_read(&md->pending)) { @@ -1344,7 +1404,7 @@ int dm_suspend(struct mapped_device *md, int do_lockfs) __flush_deferred_io(md, def); up_write(&md->io_lock); unlock_fs(md); - goto out; + goto out; /* pushback list is already flushed, so skip flush */ } up_write(&md->io_lock); @@ -1354,6 +1414,25 @@ int dm_suspend(struct mapped_device *md, int do_lockfs) r = 0; +flush_and_out: + if (r && noflush) { + /* + * Because there may be already I/Os in the pushback list, + * flush them before return. + */ + down_write(&md->io_lock); + + spin_lock_irqsave(&md->pushback_lock, flags); + clear_bit(DMF_NOFLUSH_SUSPENDING, &md->flags); + bio_list_merge_head(&md->deferred, &md->pushback); + bio_list_init(&md->pushback); + spin_unlock_irqrestore(&md->pushback_lock, flags); + + def = bio_list_get(&md->deferred); + __flush_deferred_io(md, def); + up_write(&md->io_lock); + } + out: if (r && md->suspended_bdev) { bdput(md->suspended_bdev); @@ -1440,6 +1519,17 @@ int dm_suspended(struct mapped_device *md) return test_bit(DMF_SUSPENDED, &md->flags); } +int dm_noflush_suspending(struct dm_target *ti) +{ + struct mapped_device *md = dm_table_get_md(ti->table); + int r = __noflush_suspending(md); + + dm_put(md); + + return r; +} +EXPORT_SYMBOL_GPL(dm_noflush_suspending); + static struct block_device_operations dm_blk_dops = { .open = dm_blk_open, .release = dm_blk_close, diff --git a/drivers/md/dm.h b/drivers/md/dm.h index a48ec5e3c1f..2f796b1436b 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -33,6 +33,25 @@ #define SECTOR_SHIFT 9 /* + * Definitions of return values from target end_io function. + */ +#define DM_ENDIO_INCOMPLETE 1 +#define DM_ENDIO_REQUEUE 2 + +/* + * Definitions of return values from target map function. + */ +#define DM_MAPIO_SUBMITTED 0 +#define DM_MAPIO_REMAPPED 1 +#define DM_MAPIO_REQUEUE DM_ENDIO_REQUEUE + +/* + * Suspend feature flags + */ +#define DM_SUSPEND_LOCKFS_FLAG (1 << 0) +#define DM_SUSPEND_NOFLUSH_FLAG (1 << 1) + +/* * List of devices that a metadevice uses and should open/close. */ struct dm_dev { diff --git a/drivers/md/md.c b/drivers/md/md.c index 6c4345bde07..53bd46dba0c 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1413,7 +1413,7 @@ static int lock_rdev(mdk_rdev_t *rdev, dev_t dev) struct block_device *bdev; char b[BDEVNAME_SIZE]; - bdev = open_partition_by_devnum(dev, FMODE_READ|FMODE_WRITE); + bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE); if (IS_ERR(bdev)) { printk(KERN_ERR "md: could not open %s.\n", __bdevname(dev, b)); @@ -1423,7 +1423,7 @@ static int lock_rdev(mdk_rdev_t *rdev, dev_t dev) if (err) { printk(KERN_ERR "md: could not bd_claim %s.\n", bdevname(bdev, b)); - blkdev_put_partition(bdev); + blkdev_put(bdev); return err; } rdev->bdev = bdev; @@ -1437,7 +1437,7 @@ static void unlock_rdev(mdk_rdev_t *rdev) if (!bdev) MD_BUG(); bd_release(bdev); - blkdev_put_partition(bdev); + blkdev_put(bdev); } void md_autodetect_dev(dev_t dev); @@ -4423,7 +4423,7 @@ static int md_open(struct inode *inode, struct file *file) mddev_t *mddev = inode->i_bdev->bd_disk->private_data; int err; - if ((err = mddev_lock(mddev))) + if ((err = mutex_lock_interruptible_nested(&mddev->reconfig_mutex, 1))) goto out; err = 0; @@ -4846,8 +4846,8 @@ static int md_seq_show(struct seq_file *seq, void *v) chunk_kb ? "KB" : "B"); if (bitmap->file) { seq_printf(seq, ", file: "); - seq_path(seq, bitmap->file->f_vfsmnt, - bitmap->file->f_dentry," \t\n"); + seq_path(seq, bitmap->file->f_path.mnt, + bitmap->file->f_path.dentry," \t\n"); } seq_printf(seq, "\n"); diff --git a/drivers/media/video/compat_ioctl32.c b/drivers/media/video/compat_ioctl32.c index d82a488f12a..f065ad12cc6 100644 --- a/drivers/media/video/compat_ioctl32.c +++ b/drivers/media/video/compat_ioctl32.c @@ -118,7 +118,7 @@ static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ret = file->f_op->unlocked_ioctl(file, cmd, arg); else if (file->f_op->ioctl) { lock_kernel(); - ret = file->f_op->ioctl(file->f_dentry->d_inode, file, cmd, arg); + ret = file->f_op->ioctl(file->f_path.dentry->d_inode, file, cmd, arg); unlock_kernel(); } diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index d424a4129d6..41ec0c4b35a 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -105,7 +105,7 @@ static DEFINE_MUTEX(videodev_lock); struct video_device* video_devdata(struct file *file) { - return video_device[iminor(file->f_dentry->d_inode)]; + return video_device[iminor(file->f_path.dentry->d_inode)]; } /* diff --git a/drivers/media/video/zoran_procfs.c b/drivers/media/video/zoran_procfs.c index c7f6f648836..c374c76b375 100644 --- a/drivers/media/video/zoran_procfs.c +++ b/drivers/media/video/zoran_procfs.c @@ -144,7 +144,7 @@ static int zoran_open(struct inode *inode, struct file *file) static ssize_t zoran_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { - struct zoran *zr = PDE(file->f_dentry->d_inode)->data; + struct zoran *zr = PDE(file->f_path.dentry->d_inode)->data; char *string, *sp; char *line, *ldelim, *varname, *svar, *tdelim; @@ -165,7 +165,7 @@ static ssize_t zoran_write(struct file *file, const char __user *buffer, } string[count] = 0; dprintk(4, KERN_INFO "%s: write_proc: name=%s count=%zu zr=%p\n", - ZR_DEVNAME(zr), file->f_dentry->d_name.name, count, zr); + ZR_DEVNAME(zr), file->f_path.dentry->d_name.name, count, zr); ldelim = " \t\n"; tdelim = "="; line = strpbrk(sp, ldelim); diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c index 447fba5825f..800527cf40d 100644 --- a/drivers/mmc/au1xmmc.c +++ b/drivers/mmc/au1xmmc.c @@ -875,7 +875,7 @@ static void au1xmmc_init_dma(struct au1xmmc_host *host) host->rx_chan = rxchan; } -struct const mmc_host_ops au1xmmc_ops = { +static const struct mmc_host_ops au1xmmc_ops = { .request = au1xmmc_request, .set_ios = au1xmmc_set_ios, }; diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c index 471e9f4e053..45a9283ce49 100644 --- a/drivers/mmc/pxamci.c +++ b/drivers/mmc/pxamci.c @@ -355,7 +355,7 @@ static int pxamci_get_ro(struct mmc_host *mmc) struct pxamci_host *host = mmc_priv(mmc); if (host->pdata && host->pdata->get_ro) - return host->pdata->get_ro(mmc->dev); + return host->pdata->get_ro(mmc_dev(mmc)); /* Host doesn't support read only detection so assume writeable */ return 0; } @@ -383,7 +383,7 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) host->power_mode = ios->power_mode; if (host->pdata && host->pdata->setpower) - host->pdata->setpower(mmc->dev, ios->vdd); + host->pdata->setpower(mmc_dev(mmc), ios->vdd); if (ios->power_mode == MMC_POWER_ON) host->cmdat |= CMDAT_INIT; diff --git a/drivers/mmc/tifm_sd.c b/drivers/mmc/tifm_sd.c index e846499a004..f18ad998b3c 100644 --- a/drivers/mmc/tifm_sd.c +++ b/drivers/mmc/tifm_sd.c @@ -387,7 +387,7 @@ static void tifm_sd_prepare_data(struct tifm_sd *card, struct mmc_command *cmd) writel(TIFM_FIFO_INT_SETALL, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); - writel(long_log2(cmd->data->blksz) - 2, + writel(ilog2(cmd->data->blksz) - 2, sock->addr + SOCK_FIFO_PAGE_SIZE); writel(TIFM_FIFO_ENABLE, sock->addr + SOCK_FIFO_CONTROL); writel(TIFM_FIFO_INTMASK, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c index 6a98b7ae497..ad1857364d5 100644 --- a/drivers/net/irda/irtty-sir.c +++ b/drivers/net/irda/irtty-sir.c @@ -117,7 +117,7 @@ static int irtty_change_speed(struct sir_dev *dev, unsigned speed) { struct sirtty_cb *priv = dev->priv; struct tty_struct *tty; - struct termios old_termios; + struct ktermios old_termios; int cflag; IRDA_ASSERT(priv != NULL, return -1;); @@ -318,7 +318,7 @@ static void irtty_write_wakeup(struct tty_struct *tty) static inline void irtty_stop_receiver(struct tty_struct *tty, int stop) { - struct termios old_termios; + struct ktermios old_termios; int cflag; lock_kernel(); diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 74f894795a1..4587f23f4e4 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -3132,7 +3132,7 @@ static u16 wol_calc_crc(int size, u8 * pattern, u8 *mask_pattern) } /* Finally, invert the result once to get the correct data */ crc = ~crc; - return bitreverse(crc) >> 16; + return bitrev32(crc) >> 16; } /** diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c index e1bf8b93f95..6c7dfb50143 100644 --- a/drivers/net/wan/cosa.c +++ b/drivers/net/wan/cosa.c @@ -974,12 +974,12 @@ static int cosa_open(struct inode *inode, struct file *file) unsigned long flags; int n; - if ((n=iminor(file->f_dentry->d_inode)>>CARD_MINOR_BITS) + if ((n=iminor(file->f_path.dentry->d_inode)>>CARD_MINOR_BITS) >= nr_cards) return -ENODEV; cosa = cosa_cards+n; - if ((n=iminor(file->f_dentry->d_inode) + if ((n=iminor(file->f_path.dentry->d_inode) & ((1<<CARD_MINOR_BITS)-1)) >= cosa->nchannels) return -ENODEV; chan = cosa->chan + n; diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c index 337c692f6fd..ce3a8bac66f 100644 --- a/drivers/net/wireless/strip.c +++ b/drivers/net/wireless/strip.c @@ -798,7 +798,7 @@ static unsigned int get_baud(struct tty_struct *tty) */ static void set_baud(struct tty_struct *tty, unsigned int baudcode) { - struct termios old_termios = *(tty->termios); + struct ktermios old_termios = *(tty->termios); tty->termios->c_cflag &= ~CBAUD; /* Clear the old baud setting */ tty->termios->c_cflag |= baudcode; /* Set the new baud setting */ tty->driver->set_termios(tty, &old_termios); diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index 43e521e9912..78c2e6e4b42 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -220,8 +220,8 @@ static unsigned long get_exec_dcookie(struct mm_struct * mm) continue; if (!(vma->vm_flags & VM_EXECUTABLE)) continue; - cookie = fast_get_dcookie(vma->vm_file->f_dentry, - vma->vm_file->f_vfsmnt); + cookie = fast_get_dcookie(vma->vm_file->f_path.dentry, + vma->vm_file->f_path.mnt); break; } @@ -246,8 +246,8 @@ static unsigned long lookup_dcookie(struct mm_struct * mm, unsigned long addr, o continue; if (vma->vm_file) { - cookie = fast_get_dcookie(vma->vm_file->f_dentry, - vma->vm_file->f_vfsmnt); + cookie = fast_get_dcookie(vma->vm_file->f_path.dentry, + vma->vm_file->f_path.mnt); *offset = (vma->vm_pgoff << PAGE_SHIFT) + addr - vma->vm_start; } else { diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index 99cf3337976..4a6760a3b31 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c @@ -23,7 +23,7 @@ static loff_t proc_bus_pci_lseek(struct file *file, loff_t off, int whence) { loff_t new = -1; - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; mutex_lock(&inode->i_mutex); switch (whence) { @@ -48,7 +48,7 @@ proc_bus_pci_lseek(struct file *file, loff_t off, int whence) static ssize_t proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) { - const struct inode *ino = file->f_dentry->d_inode; + const struct inode *ino = file->f_path.dentry->d_inode; const struct proc_dir_entry *dp = PDE(ino); struct pci_dev *dev = dp->data; unsigned int pos = *ppos; @@ -130,7 +130,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp static ssize_t proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, loff_t *ppos) { - const struct inode *ino = file->f_dentry->d_inode; + const struct inode *ino = file->f_path.dentry->d_inode; const struct proc_dir_entry *dp = PDE(ino); struct pci_dev *dev = dp->data; int pos = *ppos; @@ -245,7 +245,7 @@ static int proc_bus_pci_ioctl(struct inode *inode, struct file *file, unsigned i #ifdef HAVE_PCI_MMAP static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; const struct proc_dir_entry *dp = PDE(inode); struct pci_dev *dev = dp->data; struct pci_filp_private *fpriv = file->private_data; diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c index d077870c673..327372b7a54 100644 --- a/drivers/pcmcia/pcmcia_ioctl.c +++ b/drivers/pcmcia/pcmcia_ioctl.c @@ -486,7 +486,7 @@ static ssize_t ds_read(struct file *file, char __user *buf, user_info_t *user; int ret; - ds_dbg(2, "ds_read(socket %d)\n", iminor(file->f_dentry->d_inode)); + ds_dbg(2, "ds_read(socket %d)\n", iminor(file->f_path.dentry->d_inode)); if (count < 4) return -EINVAL; @@ -511,7 +511,7 @@ static ssize_t ds_read(struct file *file, char __user *buf, static ssize_t ds_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - ds_dbg(2, "ds_write(socket %d)\n", iminor(file->f_dentry->d_inode)); + ds_dbg(2, "ds_write(socket %d)\n", iminor(file->f_path.dentry->d_inode)); if (count != 4) return -EINVAL; @@ -529,7 +529,7 @@ static u_int ds_poll(struct file *file, poll_table *wait) struct pcmcia_socket *s; user_info_t *user; - ds_dbg(2, "ds_poll(socket %d)\n", iminor(file->f_dentry->d_inode)); + ds_dbg(2, "ds_poll(socket %d)\n", iminor(file->f_path.dentry->d_inode)); user = file->private_data; if (CHECK_USER(user)) diff --git a/drivers/pnp/isapnp/proc.c b/drivers/pnp/isapnp/proc.c index 958c11bedd0..d21f3c1e72f 100644 --- a/drivers/pnp/isapnp/proc.c +++ b/drivers/pnp/isapnp/proc.c @@ -56,7 +56,7 @@ static loff_t isapnp_proc_bus_lseek(struct file *file, loff_t off, int whence) static ssize_t isapnp_proc_bus_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) { - struct inode *ino = file->f_dentry->d_inode; + struct inode *ino = file->f_path.dentry->d_inode; struct proc_dir_entry *dp = PDE(ino); struct pnp_dev *dev = dp->data; int pos = *ppos; diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index 8fed3603e9e..758cfb54286 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -430,7 +430,7 @@ dasd_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) int rval; lock_kernel(); - rval = dasd_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); + rval = dasd_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); unlock_kernel(); return (rval == -EINVAL) ? -ENOIOCTLCMD : rval; diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c index 78f8bda81da..0893d306ae8 100644 --- a/drivers/s390/char/fs3270.c +++ b/drivers/s390/char/fs3270.c @@ -419,16 +419,20 @@ fs3270_open(struct inode *inode, struct file *filp) struct idal_buffer *ib; int minor, rc; - if (imajor(filp->f_dentry->d_inode) != IBM_FS3270_MAJOR) + if (imajor(filp->f_path.dentry->d_inode) != IBM_FS3270_MAJOR) return -ENODEV; - minor = iminor(filp->f_dentry->d_inode); + minor = iminor(filp->f_path.dentry->d_inode); /* Check for minor 0 multiplexer. */ if (minor == 0) { - if (!current->signal->tty) + struct tty_struct *tty; + mutex_lock(&tty_mutex); + tty = get_current_tty(); + if (!tty || tty->driver->major != IBM_TTY3270_MAJOR) { + mutex_unlock(&tty_mutex); return -ENODEV; - if (current->signal->tty->driver->major != IBM_TTY3270_MAJOR) - return -ENODEV; - minor = current->signal->tty->index + RAW3270_FIRSTMINOR; + } + minor = tty->index + RAW3270_FIRSTMINOR; + mutex_unlock(&tty_mutex); } /* Check if some other program is already using fullscreen mode. */ fp = (struct fs3270 *) raw3270_find_view(&fs3270_fn, minor); diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c index 6f43e04dbef..2d173e5c8a0 100644 --- a/drivers/s390/char/sclp_tty.c +++ b/drivers/s390/char/sclp_tty.c @@ -60,8 +60,6 @@ static unsigned short int sclp_tty_chars_count; struct tty_driver *sclp_tty_driver; -extern struct termios tty_std_termios; - static struct sclp_ioctls sclp_ioctls; static struct sclp_ioctls sclp_ioctls_init = { diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c index 97f75237bed..31198c8f271 100644 --- a/drivers/s390/char/tape_char.c +++ b/drivers/s390/char/tape_char.c @@ -298,13 +298,13 @@ tapechar_open (struct inode *inode, struct file *filp) int minor, rc; DBF_EVENT(6, "TCHAR:open: %i:%i\n", - imajor(filp->f_dentry->d_inode), - iminor(filp->f_dentry->d_inode)); + imajor(filp->f_path.dentry->d_inode), + iminor(filp->f_path.dentry->d_inode)); - if (imajor(filp->f_dentry->d_inode) != tapechar_major) + if (imajor(filp->f_path.dentry->d_inode) != tapechar_major) return -ENODEV; - minor = iminor(filp->f_dentry->d_inode); + minor = iminor(filp->f_path.dentry->d_inode); device = tape_get_device(minor / TAPE_MINORS_PER_DEV); if (IS_ERR(device)) { DBF_EVENT(3, "TCHAR:open: tape_get_device() failed\n"); diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c index 4717c361160..09844621edc 100644 --- a/drivers/s390/char/tty3270.c +++ b/drivers/s390/char/tty3270.c @@ -1659,7 +1659,7 @@ tty3270_flush_buffer(struct tty_struct *tty) * Check for visible/invisible input switches */ static void -tty3270_set_termios(struct tty_struct *tty, struct termios *old) +tty3270_set_termios(struct tty_struct *tty, struct ktermios *old) { struct tty3270 *tp; int new; diff --git a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c index 385f4f76831..ac7d1258efe 100644 --- a/drivers/sbus/char/bpp.c +++ b/drivers/sbus/char/bpp.c @@ -621,7 +621,7 @@ static long read_ecp(unsigned minor, char __user *c, unsigned long cnt) static ssize_t bpp_read(struct file *f, char __user *c, size_t cnt, loff_t * ppos) { long rc; - unsigned minor = iminor(f->f_dentry->d_inode); + unsigned minor = iminor(f->f_path.dentry->d_inode); if (minor >= BPP_NO) return -ENODEV; if (!instances[minor].present) return -ENODEV; @@ -774,7 +774,7 @@ static long write_ecp(unsigned minor, const char __user *c, unsigned long cnt) static ssize_t bpp_write(struct file *f, const char __user *c, size_t cnt, loff_t * ppos) { long errno = 0; - unsigned minor = iminor(f->f_dentry->d_inode); + unsigned minor = iminor(f->f_path.dentry->d_inode); if (minor >= BPP_NO) return -ENODEV; if (!instances[minor].present) return -ENODEV; diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c index f5803ecb199..ad1c7db96cb 100644 --- a/drivers/sbus/char/cpwatchdog.c +++ b/drivers/sbus/char/cpwatchdog.c @@ -404,7 +404,7 @@ static long wd_compat_ioctl(struct file *file, unsigned int cmd, case WIOCSTOP: case WIOCGSTAT: lock_kernel(); - rval = wd_ioctl(file->f_dentry->d_inode, file, cmd, arg); + rval = wd_ioctl(file->f_path.dentry->d_inode, file, cmd, arg); unlock_kernel(); break; /* everything else is handled by the generic compat layer */ diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c index d92bc8827a9..a4909e0c7f8 100644 --- a/drivers/sbus/char/display7seg.c +++ b/drivers/sbus/char/display7seg.c @@ -121,7 +121,7 @@ static long d7s_ioctl(struct file *file, unsigned int cmd, unsigned long arg) __u8 ireg = 0; int error = 0; - if (D7S_MINOR != iminor(file->f_dentry->d_inode)) + if (D7S_MINOR != iminor(file->f_path.dentry->d_inode)) return -ENODEV; lock_kernel(); diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c index 81ba2d71cee..4e2a0e2dcc2 100644 --- a/drivers/sbus/char/openprom.c +++ b/drivers/sbus/char/openprom.c @@ -676,7 +676,7 @@ static long openprom_compat_ioctl(struct file *file, unsigned int cmd, case OPROMSETCUR: case OPROMPCI2NODE: case OPROMPATH2NODE: - rval = openprom_ioctl(file->f_dentry->d_inode, file, cmd, arg); + rval = openprom_ioctl(file->f_path.dentry->d_inode, file, cmd, arg); break; } diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c index 55b2b31bd7a..2722af5d340 100644 --- a/drivers/sbus/char/vfc_dev.c +++ b/drivers/sbus/char/vfc_dev.c @@ -610,7 +610,7 @@ static int vfc_mmap(struct file *file, struct vm_area_struct *vma) unsigned int map_size, ret, map_offset; struct vfc_dev *dev; - dev = vfc_get_dev_ptr(iminor(file->f_dentry->d_inode)); + dev = vfc_get_dev_ptr(iminor(file->f_path.dentry->d_inode)); if(dev == NULL) return -ENODEV; diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index f6a452846fa..978bfc1e0c6 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -863,7 +863,7 @@ static void sd_rescan(struct device *dev) */ static long sd_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct block_device *bdev = file->f_dentry->d_inode->i_bdev; + struct block_device *bdev = file->f_path.dentry->d_inode->i_bdev; struct gendisk *disk = bdev->bd_disk; struct scsi_device *sdev = scsi_disk(disk)->device; diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 587274dd705..e016e0906e1 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -922,7 +922,7 @@ static int check_tape(struct scsi_tape *STp, struct file *filp) struct st_modedef *STm; struct st_partstat *STps; char *name = tape_name(STp); - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; int mode = TAPE_MODE(inode); STp->ready = ST_READY; diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c index 6a1a568ca64..facb6785561 100644 --- a/drivers/serial/21285.c +++ b/drivers/serial/21285.c @@ -214,8 +214,8 @@ static void serial21285_shutdown(struct uart_port *port) } static void -serial21285_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +serial21285_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned long flags; unsigned int baud, quot, h_lcr; diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index 9b8b585513e..cad426c9711 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c @@ -1061,7 +1061,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, return 0; } -static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c index 634ecca36a7..68817a7d8c0 100644 --- a/drivers/serial/68360serial.c +++ b/drivers/serial/68360serial.c @@ -1523,7 +1523,7 @@ static int rs_360_ioctl(struct tty_struct *tty, struct file * file, /* FIX UP modem control here someday...... */ -static void rs_360_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void rs_360_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { ser_info_t *info = (ser_info_t *)tty->driver_data; diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index e34bd03cfce..51f3c739f7e 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -1763,8 +1763,8 @@ static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int } static void -serial8250_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +serial8250_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_8250_port *up = (struct uart_8250_port *)port; unsigned char cval, fcr = 0; diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index 4d3626ef464..61db6973755 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c @@ -345,8 +345,8 @@ static void pl010_shutdown(struct uart_port *port) } static void -pl010_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +pl010_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned int lcr_h, old_cr; unsigned long flags; diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index d503625730d..9a3b374b2a0 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c @@ -412,8 +412,8 @@ static void pl011_shutdown(struct uart_port *port) } static void -pl011_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +pl011_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned int lcr_h, old_cr; unsigned long flags; diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index 9217ee6c786..ed7f7209ea5 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c @@ -478,7 +478,7 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state, unsigned /* * Change the port parameters */ -static void atmel_set_termios(struct uart_port *port, struct termios * termios, struct termios * old) +static void atmel_set_termios(struct uart_port *port, struct ktermios * termios, struct ktermios * old) { unsigned long flags; unsigned int mode, imr, quot, baud; diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c index 59801271488..23827189ec0 100644 --- a/drivers/serial/clps711x.c +++ b/drivers/serial/clps711x.c @@ -286,8 +286,8 @@ static void clps711xuart_shutdown(struct uart_port *port) } static void -clps711xuart_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +clps711xuart_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned int ubrlcr, baud, quot; unsigned long flags; diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index 7a24e53546c..42b050c46ab 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c @@ -804,8 +804,8 @@ static struct e100_serial rs_table[] = { #define NR_PORTS (sizeof(rs_table)/sizeof(struct e100_serial)) -static struct termios *serial_termios[NR_PORTS]; -static struct termios *serial_termios_locked[NR_PORTS]; +static struct ktermios *serial_termios[NR_PORTS]; +static struct ktermios *serial_termios_locked[NR_PORTS]; #ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER static struct fast_timer fast_timers[NR_PORTS]; #endif @@ -4223,7 +4223,7 @@ rs_ioctl(struct tty_struct *tty, struct file * file, } static void -rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct e100_serial *info = (struct e100_serial *)tty->driver_data; @@ -4877,6 +4877,8 @@ rs_init(void) driver->init_termios = tty_std_termios; driver->init_termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL; /* is normally B9600 default... */ + driver->init_termios.c_ispeed = 115200; + driver->init_termios.c_ospeed = 115200; driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; driver->termios = serial_termios; driver->termios_locked = serial_termios_locked; diff --git a/drivers/serial/crisv10.h b/drivers/serial/crisv10.h index f30b93d6ef7..4a23340663a 100644 --- a/drivers/serial/crisv10.h +++ b/drivers/serial/crisv10.h @@ -93,8 +93,8 @@ struct e100_serial { struct work_struct work; struct async_icount icount; /* error-statistics etc.*/ - struct termios normal_termios; - struct termios callout_termios; + struct ktermios normal_termios; + struct ktermios callout_termios; #ifdef DECLARE_WAITQUEUE wait_queue_head_t open_wait; wait_queue_head_t close_wait; diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c index af1544f3356..587d87b9eb3 100644 --- a/drivers/serial/dz.c +++ b/drivers/serial/dz.c @@ -461,8 +461,8 @@ static void dz_break_ctl(struct uart_port *uport, int break_state) spin_unlock_irqrestore(&uport->lock, flags); } -static void dz_set_termios(struct uart_port *uport, struct termios *termios, - struct termios *old_termios) +static void dz_set_termios(struct uart_port *uport, struct ktermios *termios, + struct ktermios *old_termios) { struct dz_port *dport = (struct dz_port *)uport; unsigned long flags; diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c index 8aa0f641866..7d623003e65 100644 --- a/drivers/serial/icom.c +++ b/drivers/serial/icom.c @@ -1087,8 +1087,8 @@ static void icom_close(struct uart_port *port) } static void icom_set_termios(struct uart_port *port, - struct termios *termios, - struct termios *old_termios) + struct ktermios *termios, + struct ktermios *old_termios) { int baud; unsigned cflag, iflag; diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index ee5c782597d..e216dcf2937 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -459,8 +459,8 @@ static void imx_shutdown(struct uart_port *port) } static void -imx_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +imx_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct imx_port *sport = (struct imx_port *)port; unsigned long flags; diff --git a/drivers/serial/ioc3_serial.c b/drivers/serial/ioc3_serial.c index 2308d26c862..9cc0be93231 100644 --- a/drivers/serial/ioc3_serial.c +++ b/drivers/serial/ioc3_serial.c @@ -950,7 +950,7 @@ static void transmit_chars(struct uart_port *the_port) */ static void ioc3_change_speed(struct uart_port *the_port, - struct termios *new_termios, struct termios *old_termios) + struct ktermios *new_termios, struct ktermios *old_termios) { struct ioc3_port *port = get_ioc3_port(the_port); unsigned int cflag; @@ -1853,7 +1853,7 @@ static int ic3_startup(struct uart_port *the_port) */ static void ic3_set_termios(struct uart_port *the_port, - struct termios *termios, struct termios *old_termios) + struct ktermios *termios, struct ktermios *old_termios) { unsigned long port_flags; diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index 711bd151143..c862f67c985 100644 --- a/drivers/serial/ioc4_serial.c +++ b/drivers/serial/ioc4_serial.c @@ -1681,7 +1681,7 @@ static void transmit_chars(struct uart_port *the_port) */ static void ioc4_change_speed(struct uart_port *the_port, - struct termios *new_termios, struct termios *old_termios) + struct ktermios *new_termios, struct ktermios *old_termios) { struct ioc4_port *port = get_ioc4_port(the_port, 0); int baud, bits; @@ -1802,7 +1802,7 @@ static inline int ic4_startup_local(struct uart_port *the_port) ioc4_set_proto(port, the_port->mapbase); /* set the speed of the serial port */ - ioc4_change_speed(the_port, info->tty->termios, (struct termios *)0); + ioc4_change_speed(the_port, info->tty->termios, (struct ktermios *)0); return 0; } @@ -2570,7 +2570,7 @@ static int ic4_startup(struct uart_port *the_port) */ static void ic4_set_termios(struct uart_port *the_port, - struct termios *termios, struct termios *old_termios) + struct ktermios *termios, struct ktermios *old_termios) { unsigned long port_flags; diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c index dca6c1bde8f..0746c9446ae 100644 --- a/drivers/serial/ip22zilog.c +++ b/drivers/serial/ip22zilog.c @@ -840,8 +840,8 @@ ip22zilog_convert_to_zs(struct uart_ip22zilog_port *up, unsigned int cflag, /* The port lock is not held. */ static void -ip22zilog_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +ip22zilog_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port; unsigned long flags; diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c index f8262e6ad8d..7cf1c60027f 100644 --- a/drivers/serial/jsm/jsm_tty.c +++ b/drivers/serial/jsm/jsm_tty.c @@ -142,7 +142,7 @@ static void jsm_tty_send_xchar(struct uart_port *port, char ch) { unsigned long lock_flags; struct jsm_channel *channel = (struct jsm_channel *)port; - struct termios *termios; + struct ktermios *termios; spin_lock_irqsave(&port->lock, lock_flags); termios = port->info->tty->termios; @@ -180,7 +180,7 @@ static int jsm_tty_open(struct uart_port *port) struct jsm_board *brd; int rc = 0; struct jsm_channel *channel = (struct jsm_channel *)port; - struct termios *termios; + struct ktermios *termios; /* Get board pointer from our array of majors we have allocated */ brd = channel->ch_bd; @@ -269,7 +269,7 @@ static int jsm_tty_open(struct uart_port *port) static void jsm_tty_close(struct uart_port *port) { struct jsm_board *bd; - struct termios *ts; + struct ktermios *ts; struct jsm_channel *channel = (struct jsm_channel *)port; jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "start\n"); @@ -302,8 +302,8 @@ static void jsm_tty_close(struct uart_port *port) } static void jsm_tty_set_termios(struct uart_port *port, - struct termios *termios, - struct termios *old_termios) + struct ktermios *termios, + struct ktermios *old_termios) { unsigned long lock_flags; struct jsm_channel *channel = (struct jsm_channel *)port; diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c index 7656a35f5e2..6e09c8b395e 100644 --- a/drivers/serial/m32r_sio.c +++ b/drivers/serial/m32r_sio.c @@ -699,7 +699,7 @@ static unsigned int m32r_sio_get_divisor(struct uart_port *port, } static void m32r_sio_set_termios(struct uart_port *port, - struct termios *termios, struct termios *old) + struct ktermios *termios, struct ktermios *old) { struct uart_sio_port *up = (struct uart_sio_port *)port; unsigned char cval = 0; diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c index 3db206d29b3..08430961a89 100644 --- a/drivers/serial/mcfserial.c +++ b/drivers/serial/mcfserial.c @@ -1132,7 +1132,7 @@ static int mcfrs_ioctl(struct tty_struct *tty, struct file * file, return 0; } -static void mcfrs_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void mcfrs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 6dd579ed977..9d11a75663e 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c @@ -270,8 +270,8 @@ mpc52xx_uart_shutdown(struct uart_port *port) } static void -mpc52xx_uart_set_termios(struct uart_port *port, struct termios *new, - struct termios *old) +mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, + struct ktermios *old) { struct mpc52xx_psc __iomem *psc = PSC(port); unsigned long flags; diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c index 29823bd60fb..3d2fcc57b1c 100644 --- a/drivers/serial/mpsc.c +++ b/drivers/serial/mpsc.c @@ -1440,8 +1440,8 @@ mpsc_shutdown(struct uart_port *port) } static void -mpsc_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +mpsc_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct mpsc_port_info *pi = (struct mpsc_port_info *)port; u32 baud; diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c index 8ad1b8c5ec5..ccb8fa1800a 100644 --- a/drivers/serial/mux.c +++ b/drivers/serial/mux.c @@ -273,8 +273,8 @@ static void mux_shutdown(struct uart_port *port) * The Serial Mux does not support this function. */ static void -mux_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +mux_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { } diff --git a/drivers/serial/netx-serial.c b/drivers/serial/netx-serial.c index 062bad457b1..b56f7db4503 100644 --- a/drivers/serial/netx-serial.c +++ b/drivers/serial/netx-serial.c @@ -337,8 +337,8 @@ static void netx_shutdown(struct uart_port *port) } static void -netx_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +netx_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned int baud, quot; unsigned char old_cr; diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index bf9809ed9c0..752ef07516b 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c @@ -1262,8 +1262,8 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud) } -static void __pmz_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +static void __pmz_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_pmac_port *uap = to_pmz(port); unsigned long baud; @@ -1273,7 +1273,7 @@ static void __pmz_set_termios(struct uart_port *port, struct termios *termios, if (ZS_IS_ASLEEP(uap)) return; - memcpy(&uap->termios_cache, termios, sizeof(struct termios)); + memcpy(&uap->termios_cache, termios, sizeof(struct ktermios)); /* XXX Check which revs of machines actually allow 1 and 4Mb speeds * on the IR dongle. Note that the IRTTY driver currently doesn't know @@ -1313,8 +1313,8 @@ static void __pmz_set_termios(struct uart_port *port, struct termios *termios, } /* The port lock is not held. */ -static void pmz_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +static void pmz_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_pmac_port *uap = to_pmz(port); unsigned long flags; diff --git a/drivers/serial/pmac_zilog.h b/drivers/serial/pmac_zilog.h index c03f9bfacdd..570b0d925e8 100644 --- a/drivers/serial/pmac_zilog.h +++ b/drivers/serial/pmac_zilog.h @@ -60,7 +60,7 @@ struct uart_pmac_port { volatile struct dbdma_regs __iomem *tx_dma_regs; volatile struct dbdma_regs __iomem *rx_dma_regs; - struct termios termios_cache; + struct ktermios termios_cache; }; #define to_pmz(p) ((struct uart_pmac_port *)(p)) diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index 415fe9633a9..d403aaa5509 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c @@ -433,8 +433,8 @@ static void serial_pxa_shutdown(struct uart_port *port) } static void -serial_pxa_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_pxa_port *up = (struct uart_pxa_port *)port; unsigned char cval, fcr = 0; diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index 8dfc2dd058c..3ba9208ebd0 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c @@ -738,8 +738,8 @@ static unsigned int s3c24xx_serial_getclk(struct uart_port *port, } static void s3c24xx_serial_set_termios(struct uart_port *port, - struct termios *termios, - struct termios *old) + struct ktermios *termios, + struct ktermios *old) { struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port); struct s3c24xx_uart_port *ourport = to_ourport(port); diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c index d4065266b6f..58a83c27e14 100644 --- a/drivers/serial/sa1100.c +++ b/drivers/serial/sa1100.c @@ -408,8 +408,8 @@ static void sa1100_shutdown(struct uart_port *port) } static void -sa1100_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +sa1100_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct sa1100_port *sport = (struct sa1100_port *)port; unsigned long flags; diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index c67b05e9a45..f84982e508c 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -65,7 +65,7 @@ static struct lock_class_key port_lock_key; #define uart_console(port) (0) #endif -static void uart_change_speed(struct uart_state *state, struct termios *old_termios); +static void uart_change_speed(struct uart_state *state, struct ktermios *old_termios); static void uart_wait_until_sent(struct tty_struct *tty, int timeout); static void uart_change_pm(struct uart_state *state, int pm_state); @@ -338,8 +338,8 @@ EXPORT_SYMBOL(uart_update_timeout); * we're actually going to be using. */ unsigned int -uart_get_baud_rate(struct uart_port *port, struct termios *termios, - struct termios *old, unsigned int min, unsigned int max) +uart_get_baud_rate(struct uart_port *port, struct ktermios *termios, + struct ktermios *old, unsigned int min, unsigned int max) { unsigned int try, baud, altbaud = 38400; upf_t flags = port->flags & UPF_SPD_MASK; @@ -421,11 +421,11 @@ uart_get_divisor(struct uart_port *port, unsigned int baud) EXPORT_SYMBOL(uart_get_divisor); static void -uart_change_speed(struct uart_state *state, struct termios *old_termios) +uart_change_speed(struct uart_state *state, struct ktermios *old_termios) { struct tty_struct *tty = state->info->tty; struct uart_port *port = state->port; - struct termios *termios; + struct ktermios *termios; /* * If we have no tty, termios, or the port does not exist, @@ -1139,7 +1139,7 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, return ret; } -static void uart_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void uart_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct uart_state *state = tty->driver_data; unsigned long flags; @@ -1866,7 +1866,7 @@ int __init uart_set_options(struct uart_port *port, struct console *co, int baud, int parity, int bits, int flow) { - struct termios termios; + struct ktermios termios; int i; /* @@ -1876,7 +1876,7 @@ uart_set_options(struct uart_port *port, struct console *co, spin_lock_init(&port->lock); lockdep_set_class(&port->lock, &port_lock_key); - memset(&termios, 0, sizeof(struct termios)); + memset(&termios, 0, sizeof(struct ktermios)); termios.c_cflag = CREAD | HUPCL | CLOCAL; @@ -1991,12 +1991,12 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) * Re-enable the console device after suspending. */ if (uart_console(port)) { - struct termios termios; + struct ktermios termios; /* * First try to use the console cflag setting. */ - memset(&termios, 0, sizeof(struct termios)); + memset(&termios, 0, sizeof(struct ktermios)); termios.c_cflag = port->cons->cflag; /* @@ -2189,6 +2189,7 @@ int uart_register_driver(struct uart_driver *drv) normal->subtype = SERIAL_TYPE_NORMAL; normal->init_termios = tty_std_termios; normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + normal->init_termios.c_ispeed = normal->init_termios.c_ospeed = 9600; normal->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; normal->driver_state = drv; tty_set_operations(normal, &uart_ops); diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c index 5e1ac356bbb..eb18d429752 100644 --- a/drivers/serial/serial_lh7a40x.c +++ b/drivers/serial/serial_lh7a40x.c @@ -348,8 +348,8 @@ static void lh7a40xuart_shutdown (struct uart_port* port) } static void lh7a40xuart_set_termios (struct uart_port* port, - struct termios* termios, - struct termios* old) + struct ktermios* termios, + struct ktermios* old) { unsigned int con; unsigned int inten; diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c index 2a48289ac72..7186a82c475 100644 --- a/drivers/serial/serial_txx9.c +++ b/drivers/serial/serial_txx9.c @@ -556,8 +556,8 @@ static void serial_txx9_shutdown(struct uart_port *port) } static void -serial_txx9_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +serial_txx9_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_txx9_port *up = (struct uart_txx9_port *)port; unsigned int cval, fcr = 0; diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 3b5f19ec212..9031b57f12d 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -943,8 +943,8 @@ static void sci_shutdown(struct uart_port *port) s->disable(port); } -static void sci_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +static void sci_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct sci_port *s = &sci_ports[port->line]; unsigned int status, baud, smr_val; diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c index 956b2cf08e1..253ceb895ca 100644 --- a/drivers/serial/sn_console.c +++ b/drivers/serial/sn_console.c @@ -361,8 +361,8 @@ static int snp_startup(struct uart_port *port) * */ static void -snp_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +snp_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { } diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index 03941d27d15..40d48566215 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c @@ -281,8 +281,8 @@ static void sunhv_shutdown(struct uart_port *port) } /* port->lock is not held. */ -static void sunhv_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +static void sunhv_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned int baud = uart_get_baud_rate(port, termios, old, 0, 4000000); unsigned int quot = uart_get_divisor(port, baud); diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 08a7cd6a3a0..493d5bbb661 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -786,8 +786,8 @@ static void sunsab_convert_to_sab(struct uart_sunsab_port *up, unsigned int cfla } /* port->lock is not held. */ -static void sunsab_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +static void sunsab_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_sunsab_port *up = (struct uart_sunsab_port *) port; unsigned long flags; diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index c577faea60e..564592b2b2b 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -893,8 +893,8 @@ sunsu_change_speed(struct uart_port *port, unsigned int cflag, } static void -sunsu_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +sunsu_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned int baud, quot; diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index b2cc703b2b9..75de919a947 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -922,8 +922,8 @@ sunzilog_convert_to_zs(struct uart_sunzilog_port *up, unsigned int cflag, /* The port lock is not held. */ static void -sunzilog_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +sunzilog_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port; unsigned long flags; diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c index 83690653b78..92eba893559 100644 --- a/drivers/serial/uartlite.c +++ b/drivers/serial/uartlite.c @@ -214,8 +214,8 @@ static void ulite_shutdown(struct uart_port *port) free_irq(port->irq, port); } -static void ulite_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +static void ulite_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned long flags; unsigned int baud; diff --git a/drivers/serial/v850e_uart.c b/drivers/serial/v850e_uart.c index 28f3bbff87b..dd98aca6ed0 100644 --- a/drivers/serial/v850e_uart.c +++ b/drivers/serial/v850e_uart.c @@ -404,8 +404,8 @@ static void v850e_uart_shutdown (struct uart_port *port) } static void -v850e_uart_set_termios (struct uart_port *port, struct termios *termios, - struct termios *old) +v850e_uart_set_termios (struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned cflags = termios->c_cflag; diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c index fd51f8182de..cf0e663b42e 100644 --- a/drivers/serial/vr41xx_siu.c +++ b/drivers/serial/vr41xx_siu.c @@ -562,8 +562,8 @@ static void siu_shutdown(struct uart_port *port) free_irq(port->irq, port); } -static void siu_set_termios(struct uart_port *port, struct termios *new, - struct termios *old) +static void siu_set_termios(struct uart_port *port, struct ktermios *new, + struct ktermios *old) { tcflag_t c_cflag, c_iflag; uint8_t lcr, fcr, ier; diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c index 792becdfe6f..fc319727366 100644 --- a/drivers/tc/zs.c +++ b/drivers/tc/zs.c @@ -1238,7 +1238,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, return 0; } -static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct dec_serial *info = (struct dec_serial *)tty->driver_data; int was_stopped; diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c index 1b601b6cf2a..df4cc1fb5f6 100644 --- a/drivers/telephony/ixj.c +++ b/drivers/telephony/ixj.c @@ -2747,7 +2747,7 @@ static void alaw2ulaw(unsigned char *buff, unsigned long len) static ssize_t ixj_read(struct file * file_p, char __user *buf, size_t length, loff_t * ppos) { unsigned long i = *ppos; - IXJ * j = get_ixj(NUM(file_p->f_dentry->d_inode)); + IXJ * j = get_ixj(NUM(file_p->f_path.dentry->d_inode)); DECLARE_WAITQUEUE(wait, current); @@ -2804,7 +2804,7 @@ static ssize_t ixj_enhanced_read(struct file * file_p, char __user *buf, size_t { int pre_retval; ssize_t read_retval = 0; - IXJ *j = get_ixj(NUM(file_p->f_dentry->d_inode)); + IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode)); pre_retval = ixj_PreRead(j, 0L); switch (pre_retval) { @@ -2883,7 +2883,7 @@ static ssize_t ixj_enhanced_write(struct file * file_p, const char __user *buf, int pre_retval; ssize_t write_retval = 0; - IXJ *j = get_ixj(NUM(file_p->f_dentry->d_inode)); + IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode)); pre_retval = ixj_PreWrite(j, 0L); switch (pre_retval) { @@ -4582,7 +4582,7 @@ static unsigned int ixj_poll(struct file *file_p, poll_table * wait) { unsigned int mask = 0; - IXJ *j = get_ixj(NUM(file_p->f_dentry->d_inode)); + IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode)); poll_wait(file_p, &(j->poll_q), wait); if (j->read_buffer_ready > 0) @@ -6657,7 +6657,7 @@ static int ixj_ioctl(struct inode *inode, struct file *file_p, unsigned int cmd, static int ixj_fasync(int fd, struct file *file_p, int mode) { - IXJ *j = get_ixj(NUM(file_p->f_dentry->d_inode)); + IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode)); return fasync_helper(fd, file_p, mode, &j->async_queue); } diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 7f1fa956dcd..98199628e39 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -677,10 +677,10 @@ static const __u8 acm_tty_size[] = { 5, 6, 7, 8 }; -static void acm_tty_set_termios(struct tty_struct *tty, struct termios *termios_old) +static void acm_tty_set_termios(struct tty_struct *tty, struct ktermios *termios_old) { struct acm *acm = tty->driver_data; - struct termios *termios = tty->termios; + struct ktermios *termios = tty->termios; struct usb_cdc_line_coding newline; int newctrl = acm->ctrlout; diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index b5d6a79af0b..11dad22da41 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c @@ -379,7 +379,7 @@ static loff_t default_file_lseek (struct file *file, loff_t offset, int orig) { loff_t retval = -EINVAL; - mutex_lock(&file->f_dentry->d_inode->i_mutex); + mutex_lock(&file->f_path.dentry->d_inode->i_mutex); switch(orig) { case 0: if (offset > 0) { @@ -396,7 +396,7 @@ static loff_t default_file_lseek (struct file *file, loff_t offset, int orig) default: break; } - mutex_unlock(&file->f_dentry->d_inode->i_mutex); + mutex_unlock(&file->f_path.dentry->d_inode->i_mutex); return retval; } diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index c98316ce838..a265e262a2e 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -1909,10 +1909,10 @@ static int fsync_sub(struct lun *curlun) if (!filp->f_op->fsync) return -EINVAL; - inode = filp->f_dentry->d_inode; + inode = filp->f_path.dentry->d_inode; mutex_lock(&inode->i_mutex); rc = filemap_fdatawrite(inode->i_mapping); - err = filp->f_op->fsync(filp, filp->f_dentry, 1); + err = filp->f_op->fsync(filp, filp->f_path.dentry, 1); if (!rc) rc = err; err = filemap_fdatawait(inode->i_mapping); @@ -1950,7 +1950,7 @@ static int do_synchronize_cache(struct fsg_dev *fsg) static void invalidate_sub(struct lun *curlun) { struct file *filp = curlun->filp; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; unsigned long rc; rc = invalidate_inode_pages(inode->i_mapping); @@ -3526,8 +3526,8 @@ static int open_backing_file(struct lun *curlun, const char *filename) if (!(filp->f_mode & FMODE_WRITE)) ro = 1; - if (filp->f_dentry) - inode = filp->f_dentry->d_inode; + if (filp->f_path.dentry) + inode = filp->f_path.dentry->d_inode; if (inode && S_ISBLK(inode->i_mode)) { if (bdev_read_only(inode->i_bdev)) ro = 1; @@ -3606,7 +3606,7 @@ static ssize_t show_file(struct device *dev, struct device_attribute *attr, char down_read(&fsg->filesem); if (backing_file_is_open(curlun)) { // Get the complete pathname - p = d_path(curlun->filp->f_dentry, curlun->filp->f_vfsmnt, + p = d_path(curlun->filp->f_path.dentry, curlun->filp->f_path.mnt, buf, PAGE_SIZE - 1); if (IS_ERR(p)) rc = PTR_ERR(p); @@ -4030,8 +4030,8 @@ static int __init fsg_bind(struct usb_gadget *gadget) if (backing_file_is_open(curlun)) { p = NULL; if (pathbuf) { - p = d_path(curlun->filp->f_dentry, - curlun->filp->f_vfsmnt, + p = d_path(curlun->filp->f_path.dentry, + curlun->filp->f_path.mnt, pathbuf, PATH_MAX); if (IS_ERR(p)) p = NULL; diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 208e55a667a..5516c59ed5e 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -200,7 +200,7 @@ static void gs_unthrottle(struct tty_struct * tty); static void gs_break(struct tty_struct *tty, int break_state); static int gs_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); -static void gs_set_termios(struct tty_struct *tty, struct termios *old); +static void gs_set_termios(struct tty_struct *tty, struct ktermios *old); static int gs_send(struct gs_dev *dev); static int gs_send_packet(struct gs_dev *dev, char *packet, @@ -1077,7 +1077,7 @@ static int gs_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, /* * gs_set_termios */ -static void gs_set_termios(struct tty_struct *tty, struct termios *old) +static void gs_set_termios(struct tty_struct *tty, struct ktermios *old) { } diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig index 661af7aa623..8a62d478575 100644 --- a/drivers/usb/input/Kconfig +++ b/drivers/usb/input/Kconfig @@ -6,9 +6,10 @@ comment "USB Input Devices" config USB_HID tristate "USB Human Interface Device (full HID) support" - depends on USB + default y + depends on USB && HID ---help--- - Say Y here if you want full HID support to connect keyboards, + Say Y here if you want full HID support to connect USB keyboards, mice, joysticks, graphic tablets, or any other HID based devices to your computer via USB. You also need to select HID Input layer support (below) if you want to use keyboards, mice, joysticks and @@ -27,20 +28,10 @@ config USB_HID comment "Input core support is needed for USB HID input layer or HIDBP support" depends on USB_HID && INPUT=n -config USB_HIDINPUT - bool "HID input layer support" - default y - depends on INPUT && USB_HID - help - Say Y here if you want to use a USB keyboard, mouse or joystick, - or any other HID input device. - - If unsure, say Y. - -config USB_HIDINPUT_POWERBOOK +config USB_HID_POWERBOOK bool "Enable support for iBook/PowerBook special keys" default n - depends on USB_HIDINPUT + depends on USB_HID help Say Y here if you want support for the special keys (Fn, Numlock) on Apple iBooks and PowerBooks. @@ -49,7 +40,7 @@ config USB_HIDINPUT_POWERBOOK config HID_FF bool "Force feedback support (EXPERIMENTAL)" - depends on USB_HIDINPUT && EXPERIMENTAL + depends on USB_HID && EXPERIMENTAL help Say Y here is you want force feedback support for a few HID devices. See below for a list of supported devices. diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile index d946d5213b3..1a24b5bfa05 100644 --- a/drivers/usb/input/Makefile +++ b/drivers/usb/input/Makefile @@ -11,9 +11,6 @@ usbhid-objs := hid-core.o ifeq ($(CONFIG_USB_HIDDEV),y) usbhid-objs += hiddev.o endif -ifeq ($(CONFIG_USB_HIDINPUT),y) - usbhid-objs += hid-input.o -endif ifeq ($(CONFIG_HID_PID),y) usbhid-objs += hid-pidff.o endif diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 0811c39bd14..89fa6885709 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -4,6 +4,7 @@ * Copyright (c) 1999 Andreas Gal * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc + * Copyright (c) 2006 Jiri Kosina */ /* @@ -32,8 +33,9 @@ #include <linux/usb.h> -#include "hid.h" +#include <linux/hid.h> #include <linux/hiddev.h> +#include "usbhid.h" /* * Version Information @@ -54,886 +56,10 @@ static unsigned int hid_mousepoll_interval; module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644); MODULE_PARM_DESC(mousepoll, "Polling interval of mice"); -/* - * Register a new report for a device. - */ - -static struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id) -{ - struct hid_report_enum *report_enum = device->report_enum + type; - struct hid_report *report; - - if (report_enum->report_id_hash[id]) - return report_enum->report_id_hash[id]; - - if (!(report = kzalloc(sizeof(struct hid_report), GFP_KERNEL))) - return NULL; - - if (id != 0) - report_enum->numbered = 1; - - report->id = id; - report->type = type; - report->size = 0; - report->device = device; - report_enum->report_id_hash[id] = report; - - list_add_tail(&report->list, &report_enum->report_list); - - return report; -} - -/* - * Register a new field for this report. - */ - -static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values) -{ - struct hid_field *field; - - if (report->maxfield == HID_MAX_FIELDS) { - dbg("too many fields in report"); - return NULL; - } - - if (!(field = kzalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage) - + values * sizeof(unsigned), GFP_KERNEL))) return NULL; - - field->index = report->maxfield++; - report->field[field->index] = field; - field->usage = (struct hid_usage *)(field + 1); - field->value = (unsigned *)(field->usage + usages); - field->report = report; - - return field; -} - -/* - * Open a collection. The type/usage is pushed on the stack. - */ - -static int open_collection(struct hid_parser *parser, unsigned type) -{ - struct hid_collection *collection; - unsigned usage; - - usage = parser->local.usage[0]; - - if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) { - dbg("collection stack overflow"); - return -1; - } - - if (parser->device->maxcollection == parser->device->collection_size) { - collection = kmalloc(sizeof(struct hid_collection) * - parser->device->collection_size * 2, GFP_KERNEL); - if (collection == NULL) { - dbg("failed to reallocate collection array"); - return -1; - } - memcpy(collection, parser->device->collection, - sizeof(struct hid_collection) * - parser->device->collection_size); - memset(collection + parser->device->collection_size, 0, - sizeof(struct hid_collection) * - parser->device->collection_size); - kfree(parser->device->collection); - parser->device->collection = collection; - parser->device->collection_size *= 2; - } - - parser->collection_stack[parser->collection_stack_ptr++] = - parser->device->maxcollection; - - collection = parser->device->collection + - parser->device->maxcollection++; - collection->type = type; - collection->usage = usage; - collection->level = parser->collection_stack_ptr - 1; - - if (type == HID_COLLECTION_APPLICATION) - parser->device->maxapplication++; - - return 0; -} - -/* - * Close a collection. - */ - -static int close_collection(struct hid_parser *parser) -{ - if (!parser->collection_stack_ptr) { - dbg("collection stack underflow"); - return -1; - } - parser->collection_stack_ptr--; - return 0; -} - -/* - * Climb up the stack, search for the specified collection type - * and return the usage. - */ - -static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type) -{ - int n; - for (n = parser->collection_stack_ptr - 1; n >= 0; n--) - if (parser->device->collection[parser->collection_stack[n]].type == type) - return parser->device->collection[parser->collection_stack[n]].usage; - return 0; /* we know nothing about this usage type */ -} - -/* - * Add a usage to the temporary parser table. - */ - -static int hid_add_usage(struct hid_parser *parser, unsigned usage) -{ - if (parser->local.usage_index >= HID_MAX_USAGES) { - dbg("usage index exceeded"); - return -1; - } - parser->local.usage[parser->local.usage_index] = usage; - parser->local.collection_index[parser->local.usage_index] = - parser->collection_stack_ptr ? - parser->collection_stack[parser->collection_stack_ptr - 1] : 0; - parser->local.usage_index++; - return 0; -} - -/* - * Register a new field for this report. - */ - -static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsigned flags) -{ - struct hid_report *report; - struct hid_field *field; - int usages; - unsigned offset; - int i; - - if (!(report = hid_register_report(parser->device, report_type, parser->global.report_id))) { - dbg("hid_register_report failed"); - return -1; - } - - if (parser->global.logical_maximum < parser->global.logical_minimum) { - dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum); - return -1; - } - - offset = report->size; - report->size += parser->global.report_size * parser->global.report_count; - - if (!parser->local.usage_index) /* Ignore padding fields */ - return 0; - - usages = max_t(int, parser->local.usage_index, parser->global.report_count); - - if ((field = hid_register_field(report, usages, parser->global.report_count)) == NULL) - return 0; - - field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL); - field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL); - field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION); - - for (i = 0; i < usages; i++) { - int j = i; - /* Duplicate the last usage we parsed if we have excess values */ - if (i >= parser->local.usage_index) - j = parser->local.usage_index - 1; - field->usage[i].hid = parser->local.usage[j]; - field->usage[i].collection_index = - parser->local.collection_index[j]; - } - - field->maxusage = usages; - field->flags = flags; - field->report_offset = offset; - field->report_type = report_type; - field->report_size = parser->global.report_size; - field->report_count = parser->global.report_count; - field->logical_minimum = parser->global.logical_minimum; - field->logical_maximum = parser->global.logical_maximum; - field->physical_minimum = parser->global.physical_minimum; - field->physical_maximum = parser->global.physical_maximum; - field->unit_exponent = parser->global.unit_exponent; - field->unit = parser->global.unit; - - return 0; -} - -/* - * Read data value from item. - */ - -static u32 item_udata(struct hid_item *item) -{ - switch (item->size) { - case 1: return item->data.u8; - case 2: return item->data.u16; - case 4: return item->data.u32; - } - return 0; -} - -static s32 item_sdata(struct hid_item *item) -{ - switch (item->size) { - case 1: return item->data.s8; - case 2: return item->data.s16; - case 4: return item->data.s32; - } - return 0; -} - -/* - * Process a global item. - */ - -static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) -{ - switch (item->tag) { - - case HID_GLOBAL_ITEM_TAG_PUSH: - - if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) { - dbg("global enviroment stack overflow"); - return -1; - } - - memcpy(parser->global_stack + parser->global_stack_ptr++, - &parser->global, sizeof(struct hid_global)); - return 0; - - case HID_GLOBAL_ITEM_TAG_POP: - - if (!parser->global_stack_ptr) { - dbg("global enviroment stack underflow"); - return -1; - } - - memcpy(&parser->global, parser->global_stack + --parser->global_stack_ptr, - sizeof(struct hid_global)); - return 0; - - case HID_GLOBAL_ITEM_TAG_USAGE_PAGE: - parser->global.usage_page = item_udata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM: - parser->global.logical_minimum = item_sdata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM: - if (parser->global.logical_minimum < 0) - parser->global.logical_maximum = item_sdata(item); - else - parser->global.logical_maximum = item_udata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM: - parser->global.physical_minimum = item_sdata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM: - if (parser->global.physical_minimum < 0) - parser->global.physical_maximum = item_sdata(item); - else - parser->global.physical_maximum = item_udata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT: - parser->global.unit_exponent = item_sdata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_UNIT: - parser->global.unit = item_udata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_REPORT_SIZE: - if ((parser->global.report_size = item_udata(item)) > 32) { - dbg("invalid report_size %d", parser->global.report_size); - return -1; - } - return 0; - - case HID_GLOBAL_ITEM_TAG_REPORT_COUNT: - if ((parser->global.report_count = item_udata(item)) > HID_MAX_USAGES) { - dbg("invalid report_count %d", parser->global.report_count); - return -1; - } - return 0; - - case HID_GLOBAL_ITEM_TAG_REPORT_ID: - if ((parser->global.report_id = item_udata(item)) == 0) { - dbg("report_id 0 is invalid"); - return -1; - } - return 0; - - default: - dbg("unknown global tag 0x%x", item->tag); - return -1; - } -} - -/* - * Process a local item. - */ - -static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) -{ - __u32 data; - unsigned n; - - if (item->size == 0) { - dbg("item data expected for local item"); - return -1; - } - - data = item_udata(item); - - switch (item->tag) { - - case HID_LOCAL_ITEM_TAG_DELIMITER: - - if (data) { - /* - * We treat items before the first delimiter - * as global to all usage sets (branch 0). - * In the moment we process only these global - * items and the first delimiter set. - */ - if (parser->local.delimiter_depth != 0) { - dbg("nested delimiters"); - return -1; - } - parser->local.delimiter_depth++; - parser->local.delimiter_branch++; - } else { - if (parser->local.delimiter_depth < 1) { - dbg("bogus close delimiter"); - return -1; - } - parser->local.delimiter_depth--; - } - return 1; - - case HID_LOCAL_ITEM_TAG_USAGE: - - if (parser->local.delimiter_branch > 1) { - dbg("alternative usage ignored"); - return 0; - } - - if (item->size <= 2) - data = (parser->global.usage_page << 16) + data; - - return hid_add_usage(parser, data); - - case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM: - - if (parser->local.delimiter_branch > 1) { - dbg("alternative usage ignored"); - return 0; - } - - if (item->size <= 2) - data = (parser->global.usage_page << 16) + data; - - parser->local.usage_minimum = data; - return 0; - - case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM: - - if (parser->local.delimiter_branch > 1) { - dbg("alternative usage ignored"); - return 0; - } - - if (item->size <= 2) - data = (parser->global.usage_page << 16) + data; - - for (n = parser->local.usage_minimum; n <= data; n++) - if (hid_add_usage(parser, n)) { - dbg("hid_add_usage failed\n"); - return -1; - } - return 0; - - default: - - dbg("unknown local item tag 0x%x", item->tag); - return 0; - } - return 0; -} - -/* - * Process a main item. - */ - -static int hid_parser_main(struct hid_parser *parser, struct hid_item *item) -{ - __u32 data; - int ret; - - data = item_udata(item); - - switch (item->tag) { - case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION: - ret = open_collection(parser, data & 0xff); - break; - case HID_MAIN_ITEM_TAG_END_COLLECTION: - ret = close_collection(parser); - break; - case HID_MAIN_ITEM_TAG_INPUT: - ret = hid_add_field(parser, HID_INPUT_REPORT, data); - break; - case HID_MAIN_ITEM_TAG_OUTPUT: - ret = hid_add_field(parser, HID_OUTPUT_REPORT, data); - break; - case HID_MAIN_ITEM_TAG_FEATURE: - ret = hid_add_field(parser, HID_FEATURE_REPORT, data); - break; - default: - dbg("unknown main item tag 0x%x", item->tag); - ret = 0; - } - - memset(&parser->local, 0, sizeof(parser->local)); /* Reset the local parser environment */ - - return ret; -} - -/* - * Process a reserved item. - */ - -static int hid_parser_reserved(struct hid_parser *parser, struct hid_item *item) -{ - dbg("reserved item type, tag 0x%x", item->tag); - return 0; -} - -/* - * Free a report and all registered fields. The field->usage and - * field->value table's are allocated behind the field, so we need - * only to free(field) itself. - */ - -static void hid_free_report(struct hid_report *report) -{ - unsigned n; - - for (n = 0; n < report->maxfield; n++) - kfree(report->field[n]); - kfree(report); -} - -/* - * Free a device structure, all reports, and all fields. - */ - -static void hid_free_device(struct hid_device *device) -{ - unsigned i,j; - - for (i = 0; i < HID_REPORT_TYPES; i++) { - struct hid_report_enum *report_enum = device->report_enum + i; - - for (j = 0; j < 256; j++) { - struct hid_report *report = report_enum->report_id_hash[j]; - if (report) - hid_free_report(report); - } - } - - kfree(device->rdesc); - kfree(device); -} - -/* - * Fetch a report description item from the data stream. We support long - * items, though they are not used yet. - */ - -static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item) -{ - u8 b; - - if ((end - start) <= 0) - return NULL; - - b = *start++; - - item->type = (b >> 2) & 3; - item->tag = (b >> 4) & 15; - - if (item->tag == HID_ITEM_TAG_LONG) { - - item->format = HID_ITEM_FORMAT_LONG; - - if ((end - start) < 2) - return NULL; - - item->size = *start++; - item->tag = *start++; - - if ((end - start) < item->size) - return NULL; - - item->data.longdata = start; - start += item->size; - return start; - } - - item->format = HID_ITEM_FORMAT_SHORT; - item->size = b & 3; - - switch (item->size) { - - case 0: - return start; - - case 1: - if ((end - start) < 1) - return NULL; - item->data.u8 = *start++; - return start; - - case 2: - if ((end - start) < 2) - return NULL; - item->data.u16 = le16_to_cpu(get_unaligned((__le16*)start)); - start = (__u8 *)((__le16 *)start + 1); - return start; - - case 3: - item->size++; - if ((end - start) < 4) - return NULL; - item->data.u32 = le32_to_cpu(get_unaligned((__le32*)start)); - start = (__u8 *)((__le32 *)start + 1); - return start; - } - - return NULL; -} - -/* - * Parse a report description into a hid_device structure. Reports are - * enumerated, fields are attached to these reports. - */ - -static struct hid_device *hid_parse_report(__u8 *start, unsigned size) -{ - struct hid_device *device; - struct hid_parser *parser; - struct hid_item item; - __u8 *end; - unsigned i; - static int (*dispatch_type[])(struct hid_parser *parser, - struct hid_item *item) = { - hid_parser_main, - hid_parser_global, - hid_parser_local, - hid_parser_reserved - }; - - if (!(device = kzalloc(sizeof(struct hid_device), GFP_KERNEL))) - return NULL; - - if (!(device->collection = kzalloc(sizeof(struct hid_collection) * - HID_DEFAULT_NUM_COLLECTIONS, GFP_KERNEL))) { - kfree(device); - return NULL; - } - device->collection_size = HID_DEFAULT_NUM_COLLECTIONS; - - for (i = 0; i < HID_REPORT_TYPES; i++) - INIT_LIST_HEAD(&device->report_enum[i].report_list); - - if (!(device->rdesc = (__u8 *)kmalloc(size, GFP_KERNEL))) { - kfree(device->collection); - kfree(device); - return NULL; - } - memcpy(device->rdesc, start, size); - device->rsize = size; - - if (!(parser = kzalloc(sizeof(struct hid_parser), GFP_KERNEL))) { - kfree(device->rdesc); - kfree(device->collection); - kfree(device); - return NULL; - } - parser->device = device; - - end = start + size; - while ((start = fetch_item(start, end, &item)) != NULL) { - - if (item.format != HID_ITEM_FORMAT_SHORT) { - dbg("unexpected long global item"); - kfree(device->collection); - hid_free_device(device); - kfree(parser); - return NULL; - } - - if (dispatch_type[item.type](parser, &item)) { - dbg("item %u %u %u %u parsing failed\n", - item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag); - kfree(device->collection); - hid_free_device(device); - kfree(parser); - return NULL; - } - - if (start == end) { - if (parser->collection_stack_ptr) { - dbg("unbalanced collection at end of report description"); - kfree(device->collection); - hid_free_device(device); - kfree(parser); - return NULL; - } - if (parser->local.delimiter_depth) { - dbg("unbalanced delimiter at end of report description"); - kfree(device->collection); - hid_free_device(device); - kfree(parser); - return NULL; - } - kfree(parser); - return device; - } - } - - dbg("item fetching failed at offset %d\n", (int)(end - start)); - kfree(device->collection); - hid_free_device(device); - kfree(parser); - return NULL; -} - -/* - * Convert a signed n-bit integer to signed 32-bit integer. Common - * cases are done through the compiler, the screwed things has to be - * done by hand. - */ - -static s32 snto32(__u32 value, unsigned n) -{ - switch (n) { - case 8: return ((__s8)value); - case 16: return ((__s16)value); - case 32: return ((__s32)value); - } - return value & (1 << (n - 1)) ? value | (-1 << n) : value; -} - -/* - * Convert a signed 32-bit integer to a signed n-bit integer. - */ - -static u32 s32ton(__s32 value, unsigned n) -{ - s32 a = value >> (n - 1); - if (a && a != -1) - return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1; - return value & ((1 << n) - 1); -} - -/* - * Extract/implement a data field from/to a little endian report (bit array). - * - * Code sort-of follows HID spec: - * http://www.usb.org/developers/devclass_docs/HID1_11.pdf - * - * While the USB HID spec allows unlimited length bit fields in "report - * descriptors", most devices never use more than 16 bits. - * One model of UPS is claimed to report "LINEV" as a 32-bit field. - * Search linux-kernel and linux-usb-devel archives for "hid-core extract". - */ - -static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n) -{ - u64 x; - - WARN_ON(n > 32); - - report += offset >> 3; /* adjust byte index */ - offset &= 7; /* now only need bit offset into one byte */ - x = get_unaligned((u64 *) report); - x = le64_to_cpu(x); - x = (x >> offset) & ((1ULL << n) - 1); /* extract bit field */ - return (u32) x; -} - -/* - * "implement" : set bits in a little endian bit stream. - * Same concepts as "extract" (see comments above). - * The data mangled in the bit stream remains in little endian - * order the whole time. It make more sense to talk about - * endianness of register values by considering a register - * a "cached" copy of the little endiad bit stream. - */ -static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value) -{ - u64 x; - u64 m = (1ULL << n) - 1; - - WARN_ON(n > 32); - - WARN_ON(value > m); - value &= m; - - report += offset >> 3; - offset &= 7; - - x = get_unaligned((u64 *)report); - x &= cpu_to_le64(~(m << offset)); - x |= cpu_to_le64(((u64) value) << offset); - put_unaligned(x, (u64 *) report); -} - -/* - * Search an array for a value. - */ - -static __inline__ int search(__s32 *array, __s32 value, unsigned n) -{ - while (n--) { - if (*array++ == value) - return 0; - } - return -1; -} - -static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, int interrupt) -{ - hid_dump_input(usage, value); - if (hid->claimed & HID_CLAIMED_INPUT) - hidinput_hid_event(hid, field, usage, value); - if (hid->claimed & HID_CLAIMED_HIDDEV && interrupt) - hiddev_hid_event(hid, field, usage, value); -} - -/* - * Analyse a received field, and fetch the data from it. The field - * content is stored for next report processing (we do differential - * reporting to the layer). - */ - -static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt) -{ - unsigned n; - unsigned count = field->report_count; - unsigned offset = field->report_offset; - unsigned size = field->report_size; - __s32 min = field->logical_minimum; - __s32 max = field->logical_maximum; - __s32 *value; - - if (!(value = kmalloc(sizeof(__s32) * count, GFP_ATOMIC))) - return; - - for (n = 0; n < count; n++) { - - value[n] = min < 0 ? snto32(extract(data, offset + n * size, size), size) : - extract(data, offset + n * size, size); - - if (!(field->flags & HID_MAIN_ITEM_VARIABLE) /* Ignore report if ErrorRollOver */ - && value[n] >= min && value[n] <= max - && field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1) - goto exit; - } - - for (n = 0; n < count; n++) { - - if (HID_MAIN_ITEM_VARIABLE & field->flags) { - hid_process_event(hid, field, &field->usage[n], value[n], interrupt); - continue; - } - - if (field->value[n] >= min && field->value[n] <= max - && field->usage[field->value[n] - min].hid - && search(value, field->value[n], count)) - hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, interrupt); - - if (value[n] >= min && value[n] <= max - && field->usage[value[n] - min].hid - && search(field->value, value[n], count)) - hid_process_event(hid, field, &field->usage[value[n] - min], 1, interrupt); - } - - memcpy(field->value, value, count * sizeof(__s32)); -exit: - kfree(value); -} - -static int hid_input_report(int type, struct urb *urb, int interrupt) -{ - struct hid_device *hid = urb->context; - struct hid_report_enum *report_enum = hid->report_enum + type; - u8 *data = urb->transfer_buffer; - int len = urb->actual_length; - struct hid_report *report; - int n, size; - - if (!len) { - dbg("empty report"); - return -1; - } - -#ifdef DEBUG_DATA - printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", len, report_enum->numbered ? "" : "un"); -#endif - - n = 0; /* Normally report number is 0 */ - if (report_enum->numbered) { /* Device uses numbered reports, data[0] is report number */ - n = *data++; - len--; - } - -#ifdef DEBUG_DATA - { - int i; - printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, len); - for (i = 0; i < len; i++) - printk(" %02x", data[i]); - printk("\n"); - } -#endif - - if (!(report = report_enum->report_id_hash[n])) { - dbg("undefined report_id %d received", n); - return -1; - } - - size = ((report->size - 1) >> 3) + 1; - - if (len < size) { - dbg("report %d is too short, (%d < %d)", report->id, len, size); - memset(data + len, 0, size - len); - } - - if (hid->claimed & HID_CLAIMED_HIDDEV) - hiddev_report_event(hid, report); - - for (n = 0; n < report->maxfield; n++) - hid_input_field(hid, report->field[n], data, interrupt); - - if (hid->claimed & HID_CLAIMED_INPUT) - hidinput_report_event(hid, report); - - return 0; -} +static int usbhid_pb_fnmode = 1; +module_param_named(pb_fnmode, usbhid_pb_fnmode, int, 0644); +MODULE_PARM_DESC(pb_fnmode, + "Mode of fn key on PowerBooks (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)"); /* * Input submission and I/O error handler. @@ -946,15 +72,16 @@ static int hid_start_in(struct hid_device *hid) { unsigned long flags; int rc = 0; + struct usbhid_device *usbhid = hid->driver_data; - spin_lock_irqsave(&hid->inlock, flags); - if (hid->open > 0 && !test_bit(HID_SUSPENDED, &hid->iofl) && - !test_and_set_bit(HID_IN_RUNNING, &hid->iofl)) { - rc = usb_submit_urb(hid->urbin, GFP_ATOMIC); + spin_lock_irqsave(&usbhid->inlock, flags); + if (hid->open > 0 && !test_bit(HID_SUSPENDED, &usbhid->iofl) && + !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) { + rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC); if (rc != 0) - clear_bit(HID_IN_RUNNING, &hid->iofl); + clear_bit(HID_IN_RUNNING, &usbhid->iofl); } - spin_unlock_irqrestore(&hid->inlock, flags); + spin_unlock_irqrestore(&usbhid->inlock, flags); return rc; } @@ -962,8 +89,9 @@ static int hid_start_in(struct hid_device *hid) static void hid_retry_timeout(unsigned long _hid) { struct hid_device *hid = (struct hid_device *) _hid; + struct usbhid_device *usbhid = hid->driver_data; - dev_dbg(&hid->intf->dev, "retrying intr urb\n"); + dev_dbg(&usbhid->intf->dev, "retrying intr urb\n"); if (hid_start_in(hid)) hid_io_error(hid); } @@ -971,38 +99,39 @@ static void hid_retry_timeout(unsigned long _hid) /* Workqueue routine to reset the device or clear a halt */ static void hid_reset(struct work_struct *work) { - struct hid_device *hid = - container_of(work, struct hid_device, reset_work); + struct usbhid_device *usbhid = + container_of(work, struct usbhid_device, reset_work); + struct hid_device *hid = usbhid->hid; int rc_lock, rc = 0; - if (test_bit(HID_CLEAR_HALT, &hid->iofl)) { - dev_dbg(&hid->intf->dev, "clear halt\n"); - rc = usb_clear_halt(hid->dev, hid->urbin->pipe); - clear_bit(HID_CLEAR_HALT, &hid->iofl); + if (test_bit(HID_CLEAR_HALT, &usbhid->iofl)) { + dev_dbg(&usbhid->intf->dev, "clear halt\n"); + rc = usb_clear_halt(to_usb_device(hid->dev), usbhid->urbin->pipe); + clear_bit(HID_CLEAR_HALT, &usbhid->iofl); hid_start_in(hid); } - else if (test_bit(HID_RESET_PENDING, &hid->iofl)) { - dev_dbg(&hid->intf->dev, "resetting device\n"); - rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf); + else if (test_bit(HID_RESET_PENDING, &usbhid->iofl)) { + dev_dbg(&usbhid->intf->dev, "resetting device\n"); + rc = rc_lock = usb_lock_device_for_reset(to_usb_device(hid->dev), usbhid->intf); if (rc_lock >= 0) { - rc = usb_reset_composite_device(hid->dev, hid->intf); + rc = usb_reset_composite_device(to_usb_device(hid->dev), usbhid->intf); if (rc_lock) - usb_unlock_device(hid->dev); + usb_unlock_device(to_usb_device(hid->dev)); } - clear_bit(HID_RESET_PENDING, &hid->iofl); + clear_bit(HID_RESET_PENDING, &usbhid->iofl); } switch (rc) { case 0: - if (!test_bit(HID_IN_RUNNING, &hid->iofl)) + if (!test_bit(HID_IN_RUNNING, &usbhid->iofl)) hid_io_error(hid); break; default: err("can't reset device, %s-%s/input%d, status %d", - hid->dev->bus->bus_name, - hid->dev->devpath, - hid->ifnum, rc); + to_usb_device(hid->dev)->bus->bus_name, + to_usb_device(hid->dev)->devpath, + usbhid->ifnum, rc); /* FALLTHROUGH */ case -EHOSTUNREACH: case -ENODEV: @@ -1015,33 +144,34 @@ static void hid_reset(struct work_struct *work) static void hid_io_error(struct hid_device *hid) { unsigned long flags; + struct usbhid_device *usbhid = hid->driver_data; - spin_lock_irqsave(&hid->inlock, flags); + spin_lock_irqsave(&usbhid->inlock, flags); /* Stop when disconnected */ - if (usb_get_intfdata(hid->intf) == NULL) + if (usb_get_intfdata(usbhid->intf) == NULL) goto done; /* When an error occurs, retry at increasing intervals */ - if (hid->retry_delay == 0) { - hid->retry_delay = 13; /* Then 26, 52, 104, 104, ... */ - hid->stop_retry = jiffies + msecs_to_jiffies(1000); - } else if (hid->retry_delay < 100) - hid->retry_delay *= 2; + if (usbhid->retry_delay == 0) { + usbhid->retry_delay = 13; /* Then 26, 52, 104, 104, ... */ + usbhid->stop_retry = jiffies + msecs_to_jiffies(1000); + } else if (usbhid->retry_delay < 100) + usbhid->retry_delay *= 2; - if (time_after(jiffies, hid->stop_retry)) { + if (time_after(jiffies, usbhid->stop_retry)) { /* Retries failed, so do a port reset */ - if (!test_and_set_bit(HID_RESET_PENDING, &hid->iofl)) { - schedule_work(&hid->reset_work); + if (!test_and_set_bit(HID_RESET_PENDING, &usbhid->iofl)) { + schedule_work(&usbhid->reset_work); goto done; } } - mod_timer(&hid->io_retry, - jiffies + msecs_to_jiffies(hid->retry_delay)); + mod_timer(&usbhid->io_retry, + jiffies + msecs_to_jiffies(usbhid->retry_delay)); done: - spin_unlock_irqrestore(&hid->inlock, flags); + spin_unlock_irqrestore(&usbhid->inlock, flags); } /* @@ -1051,28 +181,31 @@ done: static void hid_irq_in(struct urb *urb) { struct hid_device *hid = urb->context; + struct usbhid_device *usbhid = hid->driver_data; int status; switch (urb->status) { case 0: /* success */ - hid->retry_delay = 0; - hid_input_report(HID_INPUT_REPORT, urb, 1); + usbhid->retry_delay = 0; + hid_input_report(urb->context, HID_INPUT_REPORT, + urb->transfer_buffer, + urb->actual_length, 1); break; case -EPIPE: /* stall */ - clear_bit(HID_IN_RUNNING, &hid->iofl); - set_bit(HID_CLEAR_HALT, &hid->iofl); - schedule_work(&hid->reset_work); + clear_bit(HID_IN_RUNNING, &usbhid->iofl); + set_bit(HID_CLEAR_HALT, &usbhid->iofl); + schedule_work(&usbhid->reset_work); return; case -ECONNRESET: /* unlink */ case -ENOENT: case -ESHUTDOWN: /* unplug */ - clear_bit(HID_IN_RUNNING, &hid->iofl); + clear_bit(HID_IN_RUNNING, &usbhid->iofl); return; case -EILSEQ: /* protocol error or unplug */ case -EPROTO: /* protocol error or unplug */ case -ETIME: /* protocol error or unplug */ case -ETIMEDOUT: /* Should never happen, but... */ - clear_bit(HID_IN_RUNNING, &hid->iofl); + clear_bit(HID_IN_RUNNING, &usbhid->iofl); hid_io_error(hid); return; default: /* error */ @@ -1081,79 +214,18 @@ static void hid_irq_in(struct urb *urb) status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { - clear_bit(HID_IN_RUNNING, &hid->iofl); + clear_bit(HID_IN_RUNNING, &usbhid->iofl); if (status != -EPERM) { err("can't resubmit intr, %s-%s/input%d, status %d", - hid->dev->bus->bus_name, - hid->dev->devpath, - hid->ifnum, status); + to_usb_device(hid->dev)->bus->bus_name, + to_usb_device(hid->dev)->devpath, + usbhid->ifnum, status); hid_io_error(hid); } } } /* - * Output the field into the report. - */ - -static void hid_output_field(struct hid_field *field, __u8 *data) -{ - unsigned count = field->report_count; - unsigned offset = field->report_offset; - unsigned size = field->report_size; - unsigned n; - - for (n = 0; n < count; n++) { - if (field->logical_minimum < 0) /* signed values */ - implement(data, offset + n * size, size, s32ton(field->value[n], size)); - else /* unsigned values */ - implement(data, offset + n * size, size, field->value[n]); - } -} - -/* - * Create a report. - */ - -static void hid_output_report(struct hid_report *report, __u8 *data) -{ - unsigned n; - - if (report->id > 0) - *data++ = report->id; - - for (n = 0; n < report->maxfield; n++) - hid_output_field(report->field[n], data); -} - -/* - * Set a field value. The report this field belongs to has to be - * created and transferred to the device, to set this value in the - * device. - */ - -int hid_set_field(struct hid_field *field, unsigned offset, __s32 value) -{ - unsigned size = field->report_size; - - hid_dump_input(field->usage + offset, value); - - if (offset >= field->report_count) { - dbg("offset (%d) exceeds report_count (%d)", offset, field->report_count); - hid_dump_field(field, 8); - return -1; - } - if (field->logical_minimum < 0) { - if (value != snto32(s32ton(value, size), size)) { - dbg("value %d is out of range", value); - return -1; - } - } - field->value[offset] = value; - return 0; -} - -/* * Find a report field with a specified HID usage. */ #if 0 @@ -1173,16 +245,17 @@ struct hid_field *hid_find_field_by_usage(struct hid_device *hid, __u32 wanted_u static int hid_submit_out(struct hid_device *hid) { struct hid_report *report; + struct usbhid_device *usbhid = hid->driver_data; - report = hid->out[hid->outtail]; + report = usbhid->out[usbhid->outtail]; - hid_output_report(report, hid->outbuf); - hid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0); - hid->urbout->dev = hid->dev; + hid_output_report(report, usbhid->outbuf); + usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0); + usbhid->urbout->dev = to_usb_device(hid->dev); dbg("submitting out urb"); - if (usb_submit_urb(hid->urbout, GFP_ATOMIC)) { + if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) { err("usb_submit_urb(out) failed"); return -1; } @@ -1195,42 +268,43 @@ static int hid_submit_ctrl(struct hid_device *hid) struct hid_report *report; unsigned char dir; int len; + struct usbhid_device *usbhid = hid->driver_data; - report = hid->ctrl[hid->ctrltail].report; - dir = hid->ctrl[hid->ctrltail].dir; + report = usbhid->ctrl[usbhid->ctrltail].report; + dir = usbhid->ctrl[usbhid->ctrltail].dir; len = ((report->size - 1) >> 3) + 1 + (report->id > 0); if (dir == USB_DIR_OUT) { - hid_output_report(report, hid->ctrlbuf); - hid->urbctrl->pipe = usb_sndctrlpipe(hid->dev, 0); - hid->urbctrl->transfer_buffer_length = len; + hid_output_report(report, usbhid->ctrlbuf); + usbhid->urbctrl->pipe = usb_sndctrlpipe(to_usb_device(hid->dev), 0); + usbhid->urbctrl->transfer_buffer_length = len; } else { int maxpacket, padlen; - hid->urbctrl->pipe = usb_rcvctrlpipe(hid->dev, 0); - maxpacket = usb_maxpacket(hid->dev, hid->urbctrl->pipe, 0); + usbhid->urbctrl->pipe = usb_rcvctrlpipe(to_usb_device(hid->dev), 0); + maxpacket = usb_maxpacket(to_usb_device(hid->dev), usbhid->urbctrl->pipe, 0); if (maxpacket > 0) { padlen = (len + maxpacket - 1) / maxpacket; padlen *= maxpacket; - if (padlen > hid->bufsize) - padlen = hid->bufsize; + if (padlen > usbhid->bufsize) + padlen = usbhid->bufsize; } else padlen = 0; - hid->urbctrl->transfer_buffer_length = padlen; + usbhid->urbctrl->transfer_buffer_length = padlen; } - hid->urbctrl->dev = hid->dev; + usbhid->urbctrl->dev = to_usb_device(hid->dev); - hid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir; - hid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : HID_REQ_GET_REPORT; - hid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) | report->id); - hid->cr->wIndex = cpu_to_le16(hid->ifnum); - hid->cr->wLength = cpu_to_le16(len); + usbhid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir; + usbhid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : HID_REQ_GET_REPORT; + usbhid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) | report->id); + usbhid->cr->wIndex = cpu_to_le16(usbhid->ifnum); + usbhid->cr->wLength = cpu_to_le16(len); dbg("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u", - hid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report", - hid->cr->wValue, hid->cr->wIndex, hid->cr->wLength); + usbhid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report", + usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength); - if (usb_submit_urb(hid->urbctrl, GFP_ATOMIC)) { + if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) { err("usb_submit_urb(ctrl) failed"); return -1; } @@ -1245,6 +319,7 @@ static int hid_submit_ctrl(struct hid_device *hid) static void hid_irq_out(struct urb *urb) { struct hid_device *hid = urb->context; + struct usbhid_device *usbhid = hid->driver_data; unsigned long flags; int unplug = 0; @@ -1262,24 +337,24 @@ static void hid_irq_out(struct urb *urb) warn("output irq status %d received", urb->status); } - spin_lock_irqsave(&hid->outlock, flags); + spin_lock_irqsave(&usbhid->outlock, flags); if (unplug) - hid->outtail = hid->outhead; + usbhid->outtail = usbhid->outhead; else - hid->outtail = (hid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1); + usbhid->outtail = (usbhid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1); - if (hid->outhead != hid->outtail) { + if (usbhid->outhead != usbhid->outtail) { if (hid_submit_out(hid)) { - clear_bit(HID_OUT_RUNNING, &hid->iofl); + clear_bit(HID_OUT_RUNNING, &usbhid->iofl); wake_up(&hid->wait); } - spin_unlock_irqrestore(&hid->outlock, flags); + spin_unlock_irqrestore(&usbhid->outlock, flags); return; } - clear_bit(HID_OUT_RUNNING, &hid->iofl); - spin_unlock_irqrestore(&hid->outlock, flags); + clear_bit(HID_OUT_RUNNING, &usbhid->iofl); + spin_unlock_irqrestore(&usbhid->outlock, flags); wake_up(&hid->wait); } @@ -1290,15 +365,17 @@ static void hid_irq_out(struct urb *urb) static void hid_ctrl(struct urb *urb) { struct hid_device *hid = urb->context; + struct usbhid_device *usbhid = hid->driver_data; unsigned long flags; int unplug = 0; - spin_lock_irqsave(&hid->ctrllock, flags); + spin_lock_irqsave(&usbhid->ctrllock, flags); switch (urb->status) { case 0: /* success */ - if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN) - hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, 0); + if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN) + hid_input_report(urb->context, usbhid->ctrl[usbhid->ctrltail].report->type, + urb->transfer_buffer, urb->actual_length, 0); break; case -ESHUTDOWN: /* unplug */ unplug = 1; @@ -1313,76 +390,102 @@ static void hid_ctrl(struct urb *urb) } if (unplug) - hid->ctrltail = hid->ctrlhead; + usbhid->ctrltail = usbhid->ctrlhead; else - hid->ctrltail = (hid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1); + usbhid->ctrltail = (usbhid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1); - if (hid->ctrlhead != hid->ctrltail) { + if (usbhid->ctrlhead != usbhid->ctrltail) { if (hid_submit_ctrl(hid)) { - clear_bit(HID_CTRL_RUNNING, &hid->iofl); + clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); wake_up(&hid->wait); } - spin_unlock_irqrestore(&hid->ctrllock, flags); + spin_unlock_irqrestore(&usbhid->ctrllock, flags); return; } - clear_bit(HID_CTRL_RUNNING, &hid->iofl); - spin_unlock_irqrestore(&hid->ctrllock, flags); + clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); + spin_unlock_irqrestore(&usbhid->ctrllock, flags); wake_up(&hid->wait); } -void hid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir) +void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir) { int head; unsigned long flags; + struct usbhid_device *usbhid = hid->driver_data; if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN) return; - if (hid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) { + if (usbhid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) { - spin_lock_irqsave(&hid->outlock, flags); + spin_lock_irqsave(&usbhid->outlock, flags); - if ((head = (hid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == hid->outtail) { - spin_unlock_irqrestore(&hid->outlock, flags); + if ((head = (usbhid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == usbhid->outtail) { + spin_unlock_irqrestore(&usbhid->outlock, flags); warn("output queue full"); return; } - hid->out[hid->outhead] = report; - hid->outhead = head; + usbhid->out[usbhid->outhead] = report; + usbhid->outhead = head; - if (!test_and_set_bit(HID_OUT_RUNNING, &hid->iofl)) + if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl)) if (hid_submit_out(hid)) - clear_bit(HID_OUT_RUNNING, &hid->iofl); + clear_bit(HID_OUT_RUNNING, &usbhid->iofl); - spin_unlock_irqrestore(&hid->outlock, flags); + spin_unlock_irqrestore(&usbhid->outlock, flags); return; } - spin_lock_irqsave(&hid->ctrllock, flags); + spin_lock_irqsave(&usbhid->ctrllock, flags); - if ((head = (hid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == hid->ctrltail) { - spin_unlock_irqrestore(&hid->ctrllock, flags); + if ((head = (usbhid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == usbhid->ctrltail) { + spin_unlock_irqrestore(&usbhid->ctrllock, flags); warn("control queue full"); return; } - hid->ctrl[hid->ctrlhead].report = report; - hid->ctrl[hid->ctrlhead].dir = dir; - hid->ctrlhead = head; + usbhid->ctrl[usbhid->ctrlhead].report = report; + usbhid->ctrl[usbhid->ctrlhead].dir = dir; + usbhid->ctrlhead = head; - if (!test_and_set_bit(HID_CTRL_RUNNING, &hid->iofl)) + if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl)) if (hid_submit_ctrl(hid)) - clear_bit(HID_CTRL_RUNNING, &hid->iofl); + clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); - spin_unlock_irqrestore(&hid->ctrllock, flags); + spin_unlock_irqrestore(&usbhid->ctrllock, flags); } -int hid_wait_io(struct hid_device *hid) +static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { - if (!wait_event_timeout(hid->wait, (!test_bit(HID_CTRL_RUNNING, &hid->iofl) && - !test_bit(HID_OUT_RUNNING, &hid->iofl)), + struct hid_device *hid = dev->private; + struct hid_field *field; + int offset; + + if (type == EV_FF) + return input_ff_event(dev, type, code, value); + + if (type != EV_LED) + return -1; + + if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) { + warn("event field not found"); + return -1; + } + + hid_set_field(field, offset, value); + usbhid_submit_report(hid, field->report, USB_DIR_OUT); + + return 0; +} + +int usbhid_wait_io(struct hid_device *hid) +{ + struct usbhid_device *usbhid = hid->driver_data; + + if (!wait_event_timeout(hid->wait, (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl) && + !test_bit(HID_OUT_RUNNING, &usbhid->iofl)), 10*HZ)) { dbg("timeout waiting for ctrl or out queue to clear"); return -1; @@ -1414,7 +517,7 @@ static int hid_get_class_descriptor(struct usb_device *dev, int ifnum, return result; } -int hid_open(struct hid_device *hid) +int usbhid_open(struct hid_device *hid) { ++hid->open; if (hid_start_in(hid)) @@ -1422,10 +525,24 @@ int hid_open(struct hid_device *hid) return 0; } -void hid_close(struct hid_device *hid) +void usbhid_close(struct hid_device *hid) { + struct usbhid_device *usbhid = hid->driver_data; + if (!--hid->open) - usb_kill_urb(hid->urbin); + usb_kill_urb(usbhid->urbin); +} + +static int hidinput_open(struct input_dev *dev) +{ + struct hid_device *hid = dev->private; + return usbhid_open(hid); +} + +static void hidinput_close(struct input_dev *dev) +{ + struct hid_device *hid = dev->private; + usbhid_close(hid); } #define USB_VENDOR_ID_PANJIT 0x134c @@ -1437,26 +554,27 @@ void hid_close(struct hid_device *hid) * Initialize all reports */ -void hid_init_reports(struct hid_device *hid) +void usbhid_init_reports(struct hid_device *hid) { struct hid_report *report; + struct usbhid_device *usbhid = hid->driver_data; int err, ret; list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list) - hid_submit_report(hid, report, USB_DIR_IN); + usbhid_submit_report(hid, report, USB_DIR_IN); list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list) - hid_submit_report(hid, report, USB_DIR_IN); + usbhid_submit_report(hid, report, USB_DIR_IN); err = 0; - ret = hid_wait_io(hid); + ret = usbhid_wait_io(hid); while (ret) { err |= ret; - if (test_bit(HID_CTRL_RUNNING, &hid->iofl)) - usb_kill_urb(hid->urbctrl); - if (test_bit(HID_OUT_RUNNING, &hid->iofl)) - usb_kill_urb(hid->urbout); - ret = hid_wait_io(hid); + if (test_bit(HID_CTRL_RUNNING, &usbhid->iofl)) + usb_kill_urb(usbhid->urbctrl); + if (test_bit(HID_OUT_RUNNING, &usbhid->iofl)) + usb_kill_urb(usbhid->urbout); + ret = usbhid_wait_io(hid); } if (err) @@ -1869,13 +987,15 @@ static void hid_find_max_report(struct hid_device *hid, unsigned int type, int * static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid) { - if (!(hid->inbuf = usb_buffer_alloc(dev, hid->bufsize, GFP_ATOMIC, &hid->inbuf_dma))) + struct usbhid_device *usbhid = hid->driver_data; + + if (!(usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->inbuf_dma))) return -1; - if (!(hid->outbuf = usb_buffer_alloc(dev, hid->bufsize, GFP_ATOMIC, &hid->outbuf_dma))) + if (!(usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->outbuf_dma))) return -1; - if (!(hid->cr = usb_buffer_alloc(dev, sizeof(*(hid->cr)), GFP_ATOMIC, &hid->cr_dma))) + if (!(usbhid->cr = usb_buffer_alloc(dev, sizeof(*(usbhid->cr)), GFP_ATOMIC, &usbhid->cr_dma))) return -1; - if (!(hid->ctrlbuf = usb_buffer_alloc(dev, hid->bufsize, GFP_ATOMIC, &hid->ctrlbuf_dma))) + if (!(usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->ctrlbuf_dma))) return -1; return 0; @@ -1883,14 +1003,16 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid) static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) { - if (hid->inbuf) - usb_buffer_free(dev, hid->bufsize, hid->inbuf, hid->inbuf_dma); - if (hid->outbuf) - usb_buffer_free(dev, hid->bufsize, hid->outbuf, hid->outbuf_dma); - if (hid->cr) - usb_buffer_free(dev, sizeof(*(hid->cr)), hid->cr, hid->cr_dma); - if (hid->ctrlbuf) - usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma); + struct usbhid_device *usbhid = hid->driver_data; + + if (usbhid->inbuf) + usb_buffer_free(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma); + if (usbhid->outbuf) + usb_buffer_free(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma); + if (usbhid->cr) + usb_buffer_free(dev, sizeof(*(usbhid->cr)), usbhid->cr, usbhid->cr_dma); + if (usbhid->ctrlbuf) + usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma); } /* @@ -1916,6 +1038,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) unsigned quirks = 0, rsize = 0; char *rdesc; int n, len, insize = 0; + struct usbhid_device *usbhid; /* Ignore all Wacom devices */ if (le16_to_cpu(dev->descriptor.idVendor) == USB_VENDOR_ID_WACOM) @@ -1985,13 +1108,19 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) kfree(rdesc); hid->quirks = quirks; - hid->bufsize = HID_MIN_BUFFER_SIZE; - hid_find_max_report(hid, HID_INPUT_REPORT, &hid->bufsize); - hid_find_max_report(hid, HID_OUTPUT_REPORT, &hid->bufsize); - hid_find_max_report(hid, HID_FEATURE_REPORT, &hid->bufsize); + if (!(usbhid = kzalloc(sizeof(struct usbhid_device), GFP_KERNEL))) + goto fail; + + hid->driver_data = usbhid; + usbhid->hid = hid; + + usbhid->bufsize = HID_MIN_BUFFER_SIZE; + hid_find_max_report(hid, HID_INPUT_REPORT, &usbhid->bufsize); + hid_find_max_report(hid, HID_OUTPUT_REPORT, &usbhid->bufsize); + hid_find_max_report(hid, HID_FEATURE_REPORT, &usbhid->bufsize); - if (hid->bufsize > HID_MAX_BUFFER_SIZE) - hid->bufsize = HID_MAX_BUFFER_SIZE; + if (usbhid->bufsize > HID_MAX_BUFFER_SIZE) + usbhid->bufsize = HID_MAX_BUFFER_SIZE; hid_find_max_report(hid, HID_INPUT_REPORT, &insize); @@ -2020,47 +1149,47 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) interval = hid_mousepoll_interval; if (usb_endpoint_dir_in(endpoint)) { - if (hid->urbin) + if (usbhid->urbin) continue; - if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL))) + if (!(usbhid->urbin = usb_alloc_urb(0, GFP_KERNEL))) goto fail; pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); - usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, insize, + usb_fill_int_urb(usbhid->urbin, dev, pipe, usbhid->inbuf, insize, hid_irq_in, hid, interval); - hid->urbin->transfer_dma = hid->inbuf_dma; - hid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + usbhid->urbin->transfer_dma = usbhid->inbuf_dma; + usbhid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; } else { - if (hid->urbout) + if (usbhid->urbout) continue; - if (!(hid->urbout = usb_alloc_urb(0, GFP_KERNEL))) + if (!(usbhid->urbout = usb_alloc_urb(0, GFP_KERNEL))) goto fail; pipe = usb_sndintpipe(dev, endpoint->bEndpointAddress); - usb_fill_int_urb(hid->urbout, dev, pipe, hid->outbuf, 0, + usb_fill_int_urb(usbhid->urbout, dev, pipe, usbhid->outbuf, 0, hid_irq_out, hid, interval); - hid->urbout->transfer_dma = hid->outbuf_dma; - hid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + usbhid->urbout->transfer_dma = usbhid->outbuf_dma; + usbhid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; } } - if (!hid->urbin) { + if (!usbhid->urbin) { err("couldn't find an input interrupt endpoint"); goto fail; } init_waitqueue_head(&hid->wait); - INIT_WORK(&hid->reset_work, hid_reset); - setup_timer(&hid->io_retry, hid_retry_timeout, (unsigned long) hid); + INIT_WORK(&usbhid->reset_work, hid_reset); + setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); - spin_lock_init(&hid->inlock); - spin_lock_init(&hid->outlock); - spin_lock_init(&hid->ctrllock); + spin_lock_init(&usbhid->inlock); + spin_lock_init(&usbhid->outlock); + spin_lock_init(&usbhid->ctrllock); hid->version = le16_to_cpu(hdesc->bcdHID); hid->country = hdesc->bCountryCode; - hid->dev = dev; - hid->intf = intf; - hid->ifnum = interface->desc.bInterfaceNumber; + hid->dev = &dev->dev; + usbhid->intf = intf; + usbhid->ifnum = interface->desc.bInterfaceNumber; hid->name[0] = 0; @@ -2078,6 +1207,10 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) le16_to_cpu(dev->descriptor.idVendor), le16_to_cpu(dev->descriptor.idProduct)); + hid->bus = BUS_USB; + hid->vendor = dev->descriptor.idVendor; + hid->product = dev->descriptor.idProduct; + usb_make_path(dev, hid->phys, sizeof(hid->phys)); strlcat(hid->phys, "/input", sizeof(hid->phys)); len = strlen(hid->phys); @@ -2088,22 +1221,32 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0) hid->uniq[0] = 0; - hid->urbctrl = usb_alloc_urb(0, GFP_KERNEL); - if (!hid->urbctrl) + usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL); + if (!usbhid->urbctrl) goto fail; - usb_fill_control_urb(hid->urbctrl, dev, 0, (void *) hid->cr, - hid->ctrlbuf, 1, hid_ctrl, hid); - hid->urbctrl->setup_dma = hid->cr_dma; - hid->urbctrl->transfer_dma = hid->ctrlbuf_dma; - hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); + usb_fill_control_urb(usbhid->urbctrl, dev, 0, (void *) usbhid->cr, + usbhid->ctrlbuf, 1, hid_ctrl, hid); + usbhid->urbctrl->setup_dma = usbhid->cr_dma; + usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma; + usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); + hid->hidinput_input_event = usb_hidinput_input_event; + hid->hidinput_open = hidinput_open; + hid->hidinput_close = hidinput_close; +#ifdef CONFIG_USB_HIDDEV + hid->hiddev_hid_event = hiddev_hid_event; + hid->hiddev_report_event = hiddev_report_event; +#endif +#ifdef CONFIG_USB_HIDINPUT_POWERBOOK + hid->pb_fnmode = usbhid_pb_fnmode; +#endif return hid; fail: - usb_free_urb(hid->urbin); - usb_free_urb(hid->urbout); - usb_free_urb(hid->urbctrl); + usb_free_urb(usbhid->urbin); + usb_free_urb(usbhid->urbout); + usb_free_urb(usbhid->urbctrl); hid_free_buffers(dev, hid); hid_free_device(hid); @@ -2113,18 +1256,21 @@ fail: static void hid_disconnect(struct usb_interface *intf) { struct hid_device *hid = usb_get_intfdata (intf); + struct usbhid_device *usbhid; if (!hid) return; - spin_lock_irq(&hid->inlock); /* Sync with error handler */ + usbhid = hid->driver_data; + + spin_lock_irq(&usbhid->inlock); /* Sync with error handler */ usb_set_intfdata(intf, NULL); - spin_unlock_irq(&hid->inlock); - usb_kill_urb(hid->urbin); - usb_kill_urb(hid->urbout); - usb_kill_urb(hid->urbctrl); + spin_unlock_irq(&usbhid->inlock); + usb_kill_urb(usbhid->urbin); + usb_kill_urb(usbhid->urbout); + usb_kill_urb(usbhid->urbctrl); - del_timer_sync(&hid->io_retry); + del_timer_sync(&usbhid->io_retry); flush_scheduled_work(); if (hid->claimed & HID_CLAIMED_INPUT) @@ -2132,11 +1278,11 @@ static void hid_disconnect(struct usb_interface *intf) if (hid->claimed & HID_CLAIMED_HIDDEV) hiddev_disconnect(hid); - usb_free_urb(hid->urbin); - usb_free_urb(hid->urbctrl); - usb_free_urb(hid->urbout); + usb_free_urb(usbhid->urbin); + usb_free_urb(usbhid->urbctrl); + usb_free_urb(usbhid->urbout); - hid_free_buffers(hid->dev, hid); + hid_free_buffers(to_usb_device(hid->dev), hid); hid_free_device(hid); } @@ -2153,7 +1299,7 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) if (!(hid = usb_hid_configure(intf))) return -ENODEV; - hid_init_reports(hid); + usbhid_init_reports(hid); hid_dump_device(hid); if (!hidinput_connect(hid)) @@ -2169,6 +1315,13 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) return -ENODEV; } + /* This only gets called when we are a single-input (most of the + * time). IOW, not a HID_QUIRK_MULTI_INPUT. The hid_ff_init() is + * only useful in this case, and not for multi-input quirks. */ + if ((hid->claimed & HID_CLAIMED_INPUT) && + !(hid->quirks & HID_QUIRK_MULTI_INPUT)) + hid_ff_init(hid); + printk(KERN_INFO); if (hid->claimed & HID_CLAIMED_INPUT) @@ -2199,12 +1352,13 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) static int hid_suspend(struct usb_interface *intf, pm_message_t message) { struct hid_device *hid = usb_get_intfdata (intf); + struct usbhid_device *usbhid = hid->driver_data; - spin_lock_irq(&hid->inlock); /* Sync with error handler */ - set_bit(HID_SUSPENDED, &hid->iofl); - spin_unlock_irq(&hid->inlock); - del_timer(&hid->io_retry); - usb_kill_urb(hid->urbin); + spin_lock_irq(&usbhid->inlock); /* Sync with error handler */ + set_bit(HID_SUSPENDED, &usbhid->iofl); + spin_unlock_irq(&usbhid->inlock); + del_timer(&usbhid->io_retry); + usb_kill_urb(usbhid->urbin); dev_dbg(&intf->dev, "suspend\n"); return 0; } @@ -2212,10 +1366,11 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) static int hid_resume(struct usb_interface *intf) { struct hid_device *hid = usb_get_intfdata (intf); + struct usbhid_device *usbhid = hid->driver_data; int status; - clear_bit(HID_SUSPENDED, &hid->iofl); - hid->retry_delay = 0; + clear_bit(HID_SUSPENDED, &usbhid->iofl); + usbhid->retry_delay = 0; status = hid_start_in(hid); dev_dbg(&intf->dev, "resume status %d\n", status); return status; diff --git a/drivers/usb/input/hid-ff.c b/drivers/usb/input/hid-ff.c index a8fc46c721c..f8f660ee3fa 100644 --- a/drivers/usb/input/hid-ff.c +++ b/drivers/usb/input/hid-ff.c @@ -32,7 +32,7 @@ #undef DEBUG #include <linux/usb.h> -#include "hid.h" +#include <linux/hid.h> /* * This table contains pointers to initializers. To add support for new @@ -70,8 +70,8 @@ static struct hid_ff_initializer inits[] = { int hid_ff_init(struct hid_device* hid) { struct hid_ff_initializer *init; - int vendor = le16_to_cpu(hid->dev->descriptor.idVendor); - int product = le16_to_cpu(hid->dev->descriptor.idProduct); + int vendor = le16_to_cpu(to_usb_device(hid->dev)->descriptor.idVendor); + int product = le16_to_cpu(to_usb_device(hid->dev)->descriptor.idProduct); for (init = inits; init->idVendor; init++) if (init->idVendor == vendor && init->idProduct == product) @@ -79,3 +79,5 @@ int hid_ff_init(struct hid_device* hid) return init->init(hid); } +EXPORT_SYMBOL_GPL(hid_ff_init); + diff --git a/drivers/usb/input/hid-lgff.c b/drivers/usb/input/hid-lgff.c index 93da222b6da..e4746626856 100644 --- a/drivers/usb/input/hid-lgff.c +++ b/drivers/usb/input/hid-lgff.c @@ -29,7 +29,8 @@ #include <linux/input.h> #include <linux/usb.h> -#include "hid.h" +#include <linux/hid.h> +#include "usbhid.h" struct device_type { u16 idVendor; @@ -75,7 +76,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef report->field[0]->value[2] = x; report->field[0]->value[3] = y; dbg("(x, y)=(%04x, %04x)", x, y); - hid_submit_report(hid, report, USB_DIR_OUT); + usbhid_submit_report(hid, report, USB_DIR_OUT); break; case FF_RUMBLE: @@ -90,7 +91,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef report->field[0]->value[2] = left; report->field[0]->value[3] = right; dbg("(left, right)=(%04x, %04x)", left, right); - hid_submit_report(hid, report, USB_DIR_OUT); + usbhid_submit_report(hid, report, USB_DIR_OUT); break; } return 0; diff --git a/drivers/usb/input/hid-pidff.c b/drivers/usb/input/hid-pidff.c index 5420c13eb8e..cbd2d53feff 100644 --- a/drivers/usb/input/hid-pidff.c +++ b/drivers/usb/input/hid-pidff.c @@ -28,7 +28,9 @@ #include <linux/input.h> #include <linux/usb.h> -#include "hid.h" +#include <linux/hid.h> + +#include "usbhid.h" #define PID_EFFECTS_MAX 64 @@ -260,7 +262,7 @@ static void pidff_set_envelope_report(struct pidff_device *pidff, debug("attack %u => %d", envelope->attack_level, pidff->set_envelope[PID_ATTACK_LEVEL].value[0]); - hid_submit_report(pidff->hid, pidff->reports[PID_SET_ENVELOPE], + usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_ENVELOPE], USB_DIR_OUT); } @@ -287,7 +289,7 @@ static void pidff_set_constant_force_report(struct pidff_device *pidff, pidff_set_signed(&pidff->set_constant[PID_MAGNITUDE], effect->u.constant.level); - hid_submit_report(pidff->hid, pidff->reports[PID_SET_CONSTANT], + usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONSTANT], USB_DIR_OUT); } @@ -322,7 +324,7 @@ static void pidff_set_effect_report(struct pidff_device *pidff, pidff->effect_direction); pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay; - hid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT], + usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT], USB_DIR_OUT); } @@ -354,7 +356,7 @@ static void pidff_set_periodic_report(struct pidff_device *pidff, pidff_set(&pidff->set_periodic[PID_PHASE], effect->u.periodic.phase); pidff->set_periodic[PID_PERIOD].value[0] = effect->u.periodic.period; - hid_submit_report(pidff->hid, pidff->reports[PID_SET_PERIODIC], + usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_PERIODIC], USB_DIR_OUT); } @@ -396,8 +398,8 @@ static void pidff_set_condition_report(struct pidff_device *pidff, effect->u.condition[i].left_saturation); pidff_set(&pidff->set_condition[PID_DEAD_BAND], effect->u.condition[i].deadband); - hid_wait_io(pidff->hid); - hid_submit_report(pidff->hid, pidff->reports[PID_SET_CONDITION], + usbhid_wait_io(pidff->hid); + usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONDITION], USB_DIR_OUT); } } @@ -438,7 +440,7 @@ static void pidff_set_ramp_force_report(struct pidff_device *pidff, effect->u.ramp.start_level); pidff_set_signed(&pidff->set_ramp[PID_RAMP_END], effect->u.ramp.end_level); - hid_submit_report(pidff->hid, pidff->reports[PID_SET_RAMP], + usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_RAMP], USB_DIR_OUT); } @@ -463,19 +465,19 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum) int j; pidff->create_new_effect_type->value[0] = efnum; - hid_submit_report(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT], + usbhid_submit_report(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT], USB_DIR_OUT); debug("create_new_effect sent, type: %d", efnum); pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0; pidff->block_load_status->value[0] = 0; - hid_wait_io(pidff->hid); + usbhid_wait_io(pidff->hid); for (j = 0; j < 60; j++) { debug("pid_block_load requested"); - hid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_LOAD], + usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_LOAD], USB_DIR_IN); - hid_wait_io(pidff->hid); + usbhid_wait_io(pidff->hid); if (pidff->block_load_status->value[0] == pidff->status_id[PID_BLOCK_LOAD_SUCCESS]) { debug("device reported free memory: %d bytes", @@ -511,8 +513,8 @@ static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n) pidff->effect_operation[PID_LOOP_COUNT].value[0] = n; } - hid_wait_io(pidff->hid); - hid_submit_report(pidff->hid, pidff->reports[PID_EFFECT_OPERATION], + usbhid_wait_io(pidff->hid); + usbhid_submit_report(pidff->hid, pidff->reports[PID_EFFECT_OPERATION], USB_DIR_OUT); } @@ -534,7 +536,7 @@ static int pidff_playback(struct input_dev *dev, int effect_id, int value) static void pidff_erase_pid(struct pidff_device *pidff, int pid_id) { pidff->block_free[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id; - hid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_FREE], + usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_FREE], USB_DIR_OUT); } @@ -714,7 +716,7 @@ static void pidff_set_gain(struct input_dev *dev, u16 gain) struct pidff_device *pidff = dev->ff->private; pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], gain); - hid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN], + usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN], USB_DIR_OUT); } @@ -739,7 +741,7 @@ static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude) pidff_set(&pidff->set_effect[PID_GAIN], magnitude); pidff->set_effect[PID_START_DELAY].value[0] = 0; - hid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT], + usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT], USB_DIR_OUT); } @@ -1163,19 +1165,19 @@ static void pidff_reset(struct pidff_device *pidff) pidff->device_control->value[0] = pidff->control_id[PID_RESET]; /* We reset twice as sometimes hid_wait_io isn't waiting long enough */ - hid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); - hid_wait_io(hid); - hid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); - hid_wait_io(hid); + usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); + usbhid_wait_io(hid); + usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); + usbhid_wait_io(hid); pidff->device_control->value[0] = pidff->control_id[PID_ENABLE_ACTUATORS]; - hid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); - hid_wait_io(hid); + usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); + usbhid_wait_io(hid); /* pool report is sometimes messed up, refetch it */ - hid_submit_report(hid, pidff->reports[PID_POOL], USB_DIR_IN); - hid_wait_io(hid); + usbhid_submit_report(hid, pidff->reports[PID_POOL], USB_DIR_IN); + usbhid_wait_io(hid); if (pidff->pool[PID_SIMULTANEOUS_MAX].value) { int sim_effects = pidff->pool[PID_SIMULTANEOUS_MAX].value[0]; @@ -1187,9 +1189,9 @@ static void pidff_reset(struct pidff_device *pidff) break; } debug("pid_pool requested again"); - hid_submit_report(hid, pidff->reports[PID_POOL], + usbhid_submit_report(hid, pidff->reports[PID_POOL], USB_DIR_IN); - hid_wait_io(hid); + usbhid_wait_io(hid); } } } @@ -1275,7 +1277,7 @@ int hid_pidff_init(struct hid_device *hid) if (test_bit(FF_GAIN, dev->ffbit)) { pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff); - hid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN], + usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN], USB_DIR_OUT); } diff --git a/drivers/usb/input/hid-tmff.c b/drivers/usb/input/hid-tmff.c index 2d5be4c318a..ab67331620d 100644 --- a/drivers/usb/input/hid-tmff.c +++ b/drivers/usb/input/hid-tmff.c @@ -32,7 +32,8 @@ #undef DEBUG #include <linux/usb.h> -#include "hid.h" +#include <linux/hid.h> +#include "usbhid.h" /* Usages for thrustmaster devices I know about */ #define THRUSTMASTER_USAGE_RUMBLE_LR (HID_UP_GENDESK | 0xbb) @@ -70,7 +71,7 @@ static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *ef tmff->rumble->value[0] = left; tmff->rumble->value[1] = right; dbg("(left,right)=(%08x, %08x)", left, right); - hid_submit_report(hid, tmff->report, USB_DIR_OUT); + usbhid_submit_report(hid, tmff->report, USB_DIR_OUT); return 0; } diff --git a/drivers/usb/input/hid-zpff.c b/drivers/usb/input/hid-zpff.c index d2ce3214572..7bd8238ca21 100644 --- a/drivers/usb/input/hid-zpff.c +++ b/drivers/usb/input/hid-zpff.c @@ -27,7 +27,8 @@ #include <linux/input.h> #include <linux/usb.h> -#include "hid.h" +#include <linux/hid.h> +#include "usbhid.h" struct zpff_device { struct hid_report *report; @@ -56,7 +57,7 @@ static int hid_zpff_play(struct input_dev *dev, void *data, zpff->report->field[2]->value[0] = left; zpff->report->field[3]->value[0] = right; debug("running with 0x%02x 0x%02x", left, right); - hid_submit_report(hid, zpff->report, USB_DIR_OUT); + usbhid_submit_report(hid, zpff->report, USB_DIR_OUT); return 0; } @@ -101,7 +102,7 @@ int hid_zpff_init(struct hid_device *hid) zpff->report->field[1]->value[0] = 0x02; zpff->report->field[2]->value[0] = 0x00; zpff->report->field[3]->value[0] = 0x00; - hid_submit_report(hid, zpff->report, USB_DIR_OUT); + usbhid_submit_report(hid, zpff->report, USB_DIR_OUT); printk(KERN_INFO "Force feedback for Zeroplus based devices by " "Anssi Hannula <anssi.hannula@gmail.com>\n"); diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c index 7dc14d0cacc..114d6c9f64b 100644 --- a/drivers/usb/input/hiddev.c +++ b/drivers/usb/input/hiddev.c @@ -32,8 +32,9 @@ #include <linux/smp_lock.h> #include <linux/input.h> #include <linux/usb.h> -#include "hid.h" +#include <linux/hid.h> #include <linux/hiddev.h> +#include "usbhid.h" #ifdef CONFIG_USB_DYNAMIC_MINORS #define HIDDEV_MINOR_BASE 0 @@ -196,7 +197,7 @@ void hiddev_hid_event(struct hid_device *hid, struct hid_field *field, hiddev_send_event(hid, &uref); } - +EXPORT_SYMBOL_GPL(hiddev_hid_event); void hiddev_report_event(struct hid_device *hid, struct hid_report *report) { @@ -213,6 +214,7 @@ void hiddev_report_event(struct hid_device *hid, struct hid_report *report) hiddev_send_event(hid, &uref); } + /* * fasync file op */ @@ -239,7 +241,7 @@ static int hiddev_release(struct inode * inode, struct file * file) if (!--list->hiddev->open) { if (list->hiddev->exist) - hid_close(list->hiddev->hid); + usbhid_close(list->hiddev->hid); else kfree(list->hiddev); } @@ -270,7 +272,7 @@ static int hiddev_open(struct inode *inode, struct file *file) if (!list->hiddev->open++) if (list->hiddev->exist) - hid_open(hiddev_table[i]->hid); + usbhid_open(hiddev_table[i]->hid); return 0; } @@ -382,7 +384,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd struct hiddev_list *list = file->private_data; struct hiddev *hiddev = list->hiddev; struct hid_device *hid = hiddev->hid; - struct usb_device *dev = hid->dev; + struct usb_device *dev = to_usb_device(hid->dev); struct hiddev_collection_info cinfo; struct hiddev_report_info rinfo; struct hiddev_field_info finfo; @@ -391,6 +393,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd struct hiddev_devinfo dinfo; struct hid_report *report; struct hid_field *field; + struct usbhid_device *usbhid = hid->driver_data; void __user *user_arg = (void __user *)arg; int i; @@ -420,7 +423,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd dinfo.bustype = BUS_USB; dinfo.busnum = dev->bus->busnum; dinfo.devnum = dev->devnum; - dinfo.ifnum = hid->ifnum; + dinfo.ifnum = usbhid->ifnum; dinfo.vendor = le16_to_cpu(dev->descriptor.idVendor); dinfo.product = le16_to_cpu(dev->descriptor.idProduct); dinfo.version = le16_to_cpu(dev->descriptor.bcdDevice); @@ -479,7 +482,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd } case HIDIOCINITREPORT: - hid_init_reports(hid); + usbhid_init_reports(hid); return 0; @@ -493,8 +496,8 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) return -EINVAL; - hid_submit_report(hid, report, USB_DIR_IN); - hid_wait_io(hid); + usbhid_submit_report(hid, report, USB_DIR_IN); + usbhid_wait_io(hid); return 0; @@ -508,8 +511,8 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) return -EINVAL; - hid_submit_report(hid, report, USB_DIR_OUT); - hid_wait_io(hid); + usbhid_submit_report(hid, report, USB_DIR_OUT); + usbhid_wait_io(hid); return 0; @@ -745,6 +748,7 @@ static struct usb_class_driver hiddev_class = { int hiddev_connect(struct hid_device *hid) { struct hiddev *hiddev; + struct usbhid_device *usbhid = hid->driver_data; int i; int retval; @@ -760,7 +764,7 @@ int hiddev_connect(struct hid_device *hid) if (!(hiddev = kzalloc(sizeof(struct hiddev), GFP_KERNEL))) return -1; - retval = usb_register_dev(hid->intf, &hiddev_class); + retval = usb_register_dev(usbhid->intf, &hiddev_class); if (retval) { err("Not able to get a minor for this device."); kfree(hiddev); @@ -772,10 +776,10 @@ int hiddev_connect(struct hid_device *hid) hiddev->hid = hid; hiddev->exist = 1; - hid->minor = hid->intf->minor; + hid->minor = usbhid->intf->minor; hid->hiddev = hiddev; - hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; + hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; return 0; } @@ -788,14 +792,15 @@ static struct usb_class_driver hiddev_class; void hiddev_disconnect(struct hid_device *hid) { struct hiddev *hiddev = hid->hiddev; + struct usbhid_device *usbhid = hid->driver_data; hiddev->exist = 0; hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL; - usb_deregister_dev(hiddev->hid->intf, &hiddev_class); + usb_deregister_dev(usbhid->intf, &hiddev_class); if (hiddev->open) { - hid_close(hiddev->hid); + usbhid_close(hiddev->hid); wake_up_interruptible(&hiddev->wait); } else { kfree(hiddev); diff --git a/drivers/usb/input/usbhid.h b/drivers/usb/input/usbhid.h new file mode 100644 index 00000000000..830107e5251 --- /dev/null +++ b/drivers/usb/input/usbhid.h @@ -0,0 +1,84 @@ +#ifndef __USBHID_H +#define __USBHID_H + +/* + * Copyright (c) 1999 Andreas Gal + * Copyright (c) 2000-2001 Vojtech Pavlik + * Copyright (c) 2006 Jiri Kosina + */ + +/* + * 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 <linux/types.h> +#include <linux/slab.h> +#include <linux/list.h> +#include <linux/timer.h> +#include <linux/workqueue.h> +#include <linux/input.h> + +/* API provided by hid-core.c for USB HID drivers */ +int usbhid_wait_io(struct hid_device* hid); +void usbhid_close(struct hid_device *hid); +int usbhid_open(struct hid_device *hid); +void usbhid_init_reports(struct hid_device *hid); +void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir); + +/* + * USB-specific HID struct, to be pointed to + * from struct hid_device->driver_data + */ + +struct usbhid_device { + struct hid_device *hid; /* pointer to corresponding HID dev */ + + struct usb_interface *intf; /* USB interface */ + int ifnum; /* USB interface number */ + + unsigned int bufsize; /* URB buffer size */ + + struct urb *urbin; /* Input URB */ + char *inbuf; /* Input buffer */ + dma_addr_t inbuf_dma; /* Input buffer dma */ + spinlock_t inlock; /* Input fifo spinlock */ + + struct urb *urbctrl; /* Control URB */ + struct usb_ctrlrequest *cr; /* Control request struct */ + dma_addr_t cr_dma; /* Control request struct dma */ + struct hid_control_fifo ctrl[HID_CONTROL_FIFO_SIZE]; /* Control fifo */ + unsigned char ctrlhead, ctrltail; /* Control fifo head & tail */ + char *ctrlbuf; /* Control buffer */ + dma_addr_t ctrlbuf_dma; /* Control buffer dma */ + spinlock_t ctrllock; /* Control fifo spinlock */ + + struct urb *urbout; /* Output URB */ + struct hid_report *out[HID_CONTROL_FIFO_SIZE]; /* Output pipe fifo */ + unsigned char outhead, outtail; /* Output pipe fifo head & tail */ + char *outbuf; /* Output buffer */ + dma_addr_t outbuf_dma; /* Output buffer dma */ + spinlock_t outlock; /* Output fifo spinlock */ + + unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ + struct timer_list io_retry; /* Retry timer */ + unsigned long stop_retry; /* Time to give up, in jiffies */ + unsigned int retry_delay; /* Delay length in ms */ + struct work_struct reset_work; /* Task context for resets */ + +}; + +#endif + diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index b99ca9c7982..0398908b15d 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -3168,7 +3168,7 @@ sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg) case SISUSB_GET_CONFIG: case SISUSB_COMMAND: lock_kernel(); - retval = sisusb_ioctl(f->f_dentry->d_inode, f, cmd, arg); + retval = sisusb_ioctl(f->f_path.dentry->d_inode, f, cmd, arg); unlock_kernel(); return retval; diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index 863966c1c5a..5261cd22ee6 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -156,7 +156,7 @@ cleanup: } static void ark3116_set_termios(struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { struct usb_serial *serial = port->serial; struct ark3116_private *priv = usb_get_serial_port_data(port); @@ -326,7 +326,7 @@ static void ark3116_set_termios(struct usb_serial_port *port, static int ark3116_open(struct usb_serial_port *port, struct file *filp) { - struct termios tmp_termios; + struct ktermios tmp_termios; struct usb_serial *serial = port->serial; char *buf; int result = 0; diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index 8835bb58ca9..38b4dae319e 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -92,7 +92,7 @@ static void belkin_sa_shutdown (struct usb_serial *serial); static int belkin_sa_open (struct usb_serial_port *port, struct file *filp); static void belkin_sa_close (struct usb_serial_port *port, struct file *filp); static void belkin_sa_read_int_callback (struct urb *urb); -static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios * old); +static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios * old); static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); static void belkin_sa_break_ctl (struct usb_serial_port *port, int break_state ); static int belkin_sa_tiocmget (struct usb_serial_port *port, struct file *file); @@ -333,7 +333,7 @@ exit: __FUNCTION__, retval); } -static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios *old_termios) +static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { struct usb_serial *serial = port->serial; struct belkin_sa_private *priv = usb_get_serial_port_data(port); diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 7167728d764..9386e216d68 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -65,7 +65,7 @@ static int usb_console_setup(struct console *co, char *options) struct usb_serial_port *port; int retval = 0; struct tty_struct *tty; - struct termios *termios; + struct ktermios *termios; dbg ("%s", __FUNCTION__); diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index f95d42c0d16..2f9b7ac3266 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -41,7 +41,7 @@ static int cp2101_open(struct usb_serial_port*, struct file*); static void cp2101_cleanup(struct usb_serial_port*); static void cp2101_close(struct usb_serial_port*, struct file*); static void cp2101_get_termios(struct usb_serial_port*); -static void cp2101_set_termios(struct usb_serial_port*, struct termios*); +static void cp2101_set_termios(struct usb_serial_port*, struct ktermios*); static int cp2101_tiocmget (struct usb_serial_port *, struct file *); static int cp2101_tiocmset (struct usb_serial_port *, struct file *, unsigned int, unsigned int); @@ -506,7 +506,7 @@ static void cp2101_get_termios (struct usb_serial_port *port) } static void cp2101_set_termios (struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { unsigned int cflag, old_cflag=0; int baud=0, bits; diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 093f303b318..a1fdb85b8c0 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -143,7 +143,7 @@ struct cypress_private { wait_queue_head_t delta_msr_wait; /* used for TIOCMIWAIT */ char prev_status, diff_status; /* used for TIOCMIWAIT */ /* we pass a pointer to this as the arguement sent to cypress_set_termios old_termios */ - struct termios tmp_termios; /* stores the old termios settings */ + struct ktermios tmp_termios; /* stores the old termios settings */ }; /* write buffer structure */ @@ -165,7 +165,7 @@ static int cypress_write (struct usb_serial_port *port, const unsigned char *b static void cypress_send (struct usb_serial_port *port); static int cypress_write_room (struct usb_serial_port *port); static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); -static void cypress_set_termios (struct usb_serial_port *port, struct termios * old); +static void cypress_set_termios (struct usb_serial_port *port, struct ktermios * old); static int cypress_tiocmget (struct usb_serial_port *port, struct file *file); static int cypress_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear); static int cypress_chars_in_buffer (struct usb_serial_port *port); @@ -949,13 +949,13 @@ static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsi switch (cmd) { case TIOCGSERIAL: - if (copy_to_user((void __user *)arg, port->tty->termios, sizeof(struct termios))) { + if (copy_to_user((void __user *)arg, port->tty->termios, sizeof(struct ktermios))) { return -EFAULT; } return (0); break; case TIOCSSERIAL: - if (copy_from_user(port->tty->termios, (void __user *)arg, sizeof(struct termios))) { + if (copy_from_user(port->tty->termios, (void __user *)arg, sizeof(struct ktermios))) { return -EFAULT; } /* here we need to call cypress_set_termios to invoke the new settings */ @@ -1019,7 +1019,7 @@ static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsi static void cypress_set_termios (struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { struct cypress_private *priv = usb_get_serial_port_data(port); struct tty_struct *tty; diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 83d0e21145b..9d9ea874639 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -449,7 +449,7 @@ static int digi_transmit_idle( struct usb_serial_port *port, static void digi_rx_throttle (struct usb_serial_port *port); static void digi_rx_unthrottle (struct usb_serial_port *port); static void digi_set_termios( struct usb_serial_port *port, - struct termios *old_termios ); + struct ktermios *old_termios ); static void digi_break_ctl( struct usb_serial_port *port, int break_state ); static int digi_ioctl( struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg ); @@ -976,7 +976,7 @@ dbg( "digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num ); static void digi_set_termios( struct usb_serial_port *port, - struct termios *old_termios ) + struct ktermios *old_termios ) { struct digi_port *priv = usb_get_serial_port_data(port); @@ -1463,7 +1463,7 @@ static int digi_open( struct usb_serial_port *port, struct file *filp ) int ret; unsigned char buf[32]; struct digi_port *priv = usb_get_serial_port_data(port); - struct termios not_termios; + struct ktermios not_termios; unsigned long flags = 0; diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c index 4ce10a83195..92beeb19795 100644 --- a/drivers/usb/serial/empeg.c +++ b/drivers/usb/serial/empeg.c @@ -92,7 +92,7 @@ static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); -static void empeg_set_termios (struct usb_serial_port *port, struct termios *old_termios); +static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *old_termios); static void empeg_write_bulk_callback (struct urb *urb); static void empeg_read_bulk_callback (struct urb *urb); @@ -442,7 +442,7 @@ static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsign } -static void empeg_set_termios (struct usb_serial_port *port, struct termios *old_termios) +static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { dbg("%s - port %d", __FUNCTION__, port->number); diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 72e4d48f51e..41b0ad2d56a 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -595,7 +595,7 @@ static int ftdi_chars_in_buffer (struct usb_serial_port *port); static void ftdi_write_bulk_callback (struct urb *urb); static void ftdi_read_bulk_callback (struct urb *urb); static void ftdi_process_read (struct work_struct *work); -static void ftdi_set_termios (struct usb_serial_port *port, struct termios * old); +static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios * old); static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file); static int ftdi_tiocmset (struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear); static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); @@ -1880,7 +1880,7 @@ static void ftdi_break_ctl( struct usb_serial_port *port, int break_state ) * WARNING: set_termios calls this with old_termios in kernel space */ -static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_termios) +static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { /* ftdi_termios */ struct usb_device *dev = port->serial->dev; unsigned int cflag = port->tty->termios->c_cflag; diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index d06547a13f2..f623d58370a 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -229,7 +229,7 @@ static int edge_write_room (struct usb_serial_port *port); static int edge_chars_in_buffer (struct usb_serial_port *port); static void edge_throttle (struct usb_serial_port *port); static void edge_unthrottle (struct usb_serial_port *port); -static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios); +static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios); static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg); static void edge_break (struct usb_serial_port *port, int break_state); static int edge_tiocmget (struct usb_serial_port *port, struct file *file); @@ -257,7 +257,7 @@ static void handle_new_lsr (struct edgeport_port *edge_port, __u8 lsrData, __u8 static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u8 param); static int calc_baud_rate_divisor (int baud_rate, int *divisor); static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRate); -static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios); +static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios); static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 regNum, __u8 regValue); static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer, int writeLength); static void send_more_port_data (struct edgeport_serial *edge_serial, struct edgeport_port *edge_port); @@ -1431,7 +1431,7 @@ static void edge_unthrottle (struct usb_serial_port *port) * SerialSetTermios * this function is called by the tty driver when it wants to change the termios structure *****************************************************************************/ -static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios) +static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { struct edgeport_port *edge_port = usb_get_serial_port_data(port); struct tty_struct *tty = port->tty; @@ -2412,7 +2412,7 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r #ifndef CMSPAR #define CMSPAR 0 #endif -static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios) +static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios) { struct tty_struct *tty; int baud; diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index ee0c921e152..2da2684e080 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -238,7 +238,7 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned c static void stop_read(struct edgeport_port *edge_port); static int restart_read(struct edgeport_port *edge_port); -static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios); +static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios); static void edge_send(struct usb_serial_port *port); /* circular buffer */ @@ -2361,7 +2361,7 @@ static int restart_read(struct edgeport_port *edge_port) return status; } -static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios) +static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios) { struct ump_uart_config *config; struct tty_struct *tty; @@ -2512,7 +2512,7 @@ static void change_port_settings (struct edgeport_port *edge_port, struct termio return; } -static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios) +static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { struct edgeport_port *edge_port = usb_get_serial_port_data(port); struct tty_struct *tty = port->tty; diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index 331bf81556f..8fdf486e346 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c @@ -107,7 +107,7 @@ static void ir_close (struct usb_serial_port *port, struct file *filep); static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int count); static void ir_write_bulk_callback (struct urb *urb); static void ir_read_bulk_callback (struct urb *urb); -static void ir_set_termios (struct usb_serial_port *port, struct termios *old_termios); +static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios); static u8 ir_baud = 0; static u8 ir_xbof = 0; @@ -497,7 +497,7 @@ static void ir_read_bulk_callback (struct urb *urb) return; } -static void ir_set_termios (struct usb_serial_port *port, struct termios *old_termios) +static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { unsigned char *transfer_buffer; unsigned int cflag; diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 7639652cec4..9d2fdfd6865 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -264,7 +264,7 @@ static void keyspan_break_ctl (struct usb_serial_port *port, int break_state) static void keyspan_set_termios (struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { int baud_rate, device_port; struct keyspan_port_private *p_priv; diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h index 7472ed6bf62..6413d73c139 100644 --- a/drivers/usb/serial/keyspan.h +++ b/drivers/usb/serial/keyspan.h @@ -59,7 +59,7 @@ static int keyspan_ioctl (struct usb_serial_port *port, unsigned int cmd, unsigned long arg); static void keyspan_set_termios (struct usb_serial_port *port, - struct termios *old); + struct ktermios *old); static void keyspan_break_ctl (struct usb_serial_port *port, int break_state); static int keyspan_tiocmget (struct usb_serial_port *port, diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index e09a0bfe623..126b9703bba 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -365,7 +365,7 @@ static void keyspan_pda_break_ctl (struct usb_serial_port *port, int break_state static void keyspan_pda_set_termios (struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { struct usb_serial *serial = port->serial; unsigned int cflag = port->tty->termios->c_cflag; diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index 17e205699c2..73d755df484 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -86,7 +86,7 @@ static int klsi_105_write_room (struct usb_serial_port *port); static void klsi_105_read_bulk_callback (struct urb *urb); static void klsi_105_set_termios (struct usb_serial_port *port, - struct termios * old); + struct ktermios *old); static int klsi_105_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, @@ -164,7 +164,7 @@ struct klsi_105_port_settings { #define URB_TRANSFER_BUFFER_SIZE 64 struct klsi_105_private { struct klsi_105_port_settings cfg; - struct termios termios; + struct ktermios termios; unsigned long line_state; /* modem line settings */ /* write pool */ struct urb * write_urb_pool[NUM_URBS]; @@ -688,7 +688,7 @@ static void klsi_105_read_bulk_callback (struct urb *urb) static void klsi_105_set_termios (struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { struct klsi_105_private *priv = usb_get_serial_port_data(port); unsigned int iflag = port->tty->termios->c_iflag; diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 237289920f0..e284d6c0fd3 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -136,7 +136,7 @@ struct kobil_private { int cur_pos; // index of the next char to send in buf __u16 device_type; int line_state; - struct termios internal_termios; + struct ktermios internal_termios; }; @@ -624,11 +624,11 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file, switch (cmd) { case TCGETS: // 0x5401 - if (!access_ok(VERIFY_WRITE, user_arg, sizeof(struct termios))) { + if (!access_ok(VERIFY_WRITE, user_arg, sizeof(struct ktermios))) { dbg("%s - port %d Error in access_ok", __FUNCTION__, port->number); return -EFAULT; } - if (kernel_termios_to_user_termios((struct termios __user *)arg, + if (kernel_termios_to_user_termios((struct ktermios __user *)arg, &priv->internal_termios)) return -EFAULT; return 0; @@ -638,12 +638,12 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file, dbg("%s - port %d Error: port->tty->termios is NULL", __FUNCTION__, port->number); return -ENOTTY; } - if (!access_ok(VERIFY_READ, user_arg, sizeof(struct termios))) { + if (!access_ok(VERIFY_READ, user_arg, sizeof(struct ktermios))) { dbg("%s - port %d Error in access_ok", __FUNCTION__, port->number); return -EFAULT; } if (user_termios_to_kernel_termios(&priv->internal_termios, - (struct termios __user *)arg)) + (struct ktermios __user *)arg)) return -EFAULT; settings = kzalloc(50, GFP_KERNEL); diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index a906e500a02..38b1d17e06e 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -98,7 +98,7 @@ static void mct_u232_close (struct usb_serial_port *port, struct file *filp); static void mct_u232_read_int_callback (struct urb *urb); static void mct_u232_set_termios (struct usb_serial_port *port, - struct termios * old); + struct ktermios * old); static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, @@ -556,7 +556,7 @@ exit: } /* mct_u232_read_int_callback */ static void mct_u232_set_termios (struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { struct usb_serial *serial = port->serial; struct mct_u232_private *priv = usb_get_serial_port_data(port); diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 70f93b18292..e55f4ed81d7 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -1014,7 +1014,7 @@ static int send_cmd_write_baud_rate(struct moschip_port *mos7720_port, * the specified new settings. */ static void change_port_settings(struct moschip_port *mos7720_port, - struct termios *old_termios) + struct ktermios *old_termios) { struct usb_serial_port *port; struct usb_serial *serial; @@ -1203,7 +1203,7 @@ static void change_port_settings(struct moschip_port *mos7720_port, * termios structure. */ static void mos7720_set_termios(struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { int status; unsigned int cflag; diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 5432c634008..8cc728a49e4 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -1931,7 +1931,7 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port, *****************************************************************************/ static void mos7840_change_port_settings(struct moschip_port *mos7840_port, - struct termios *old_termios) + struct ktermios *old_termios) { struct tty_struct *tty; int baud; @@ -2118,7 +2118,7 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port, *****************************************************************************/ static void mos7840_set_termios(struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { int status; unsigned int cflag; diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 130afbbd3fc..0ae4098718c 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -59,7 +59,7 @@ static int option_chars_in_buffer(struct usb_serial_port *port); static int option_ioctl(struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg); static void option_set_termios(struct usb_serial_port *port, - struct termios *old); + struct ktermios *old); static void option_break_ctl(struct usb_serial_port *port, int break_state); static int option_tiocmget(struct usb_serial_port *port, struct file *file); static int option_tiocmset(struct usb_serial_port *port, struct file *file, @@ -230,7 +230,7 @@ static void option_break_ctl(struct usb_serial_port *port, int break_state) } static void option_set_termios(struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { dbg("%s", __FUNCTION__); diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index bc800c8787a..d124d780e42 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -455,7 +455,7 @@ static int pl2303_chars_in_buffer(struct usb_serial_port *port) } static void pl2303_set_termios(struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { struct usb_serial *serial = port->serial; struct pl2303_private *priv = usb_get_serial_port_data(port); @@ -687,7 +687,7 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp) static int pl2303_open(struct usb_serial_port *port, struct file *filp) { - struct termios tmp_termios; + struct ktermios tmp_termios; struct usb_serial *serial = port->serial; struct pl2303_private *priv = usb_get_serial_port_data(port); unsigned char *buf; diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 4b5097fa48d..6d8e91e00ec 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -145,7 +145,7 @@ static void sierra_break_ctl(struct usb_serial_port *port, int break_state) } static void sierra_set_termios(struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { dbg("%s", __FUNCTION__); diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index ae98d8cbdbb..f42eb9ea640 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -161,7 +161,7 @@ static void ti_throttle(struct usb_serial_port *port); static void ti_unthrottle(struct usb_serial_port *port); static int ti_ioctl(struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg); static void ti_set_termios(struct usb_serial_port *port, - struct termios *old_termios); + struct ktermios *old_termios); static int ti_tiocmget(struct usb_serial_port *port, struct file *file); static int ti_tiocmset(struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear); @@ -881,7 +881,7 @@ static int ti_ioctl(struct usb_serial_port *port, struct file *file, static void ti_set_termios(struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { struct ti_port *tport = usb_get_serial_port_data(port); struct tty_struct *tty = port->tty; diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 3d5072f14b8..716f6806cc8 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -397,7 +397,7 @@ exit: return retval; } -static void serial_set_termios (struct tty_struct *tty, struct termios * old) +static void serial_set_termios (struct tty_struct *tty, struct ktermios * old) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index eef5eaa5fa0..b09f0609605 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -46,7 +46,7 @@ static int visor_probe (struct usb_serial *serial, const struct usb_device_id static int visor_calc_num_ports(struct usb_serial *serial); static void visor_shutdown (struct usb_serial *serial); static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); -static void visor_set_termios (struct usb_serial_port *port, struct termios *old_termios); +static void visor_set_termios (struct usb_serial_port *port, struct ktermios *old_termios); static void visor_write_bulk_callback (struct urb *urb); static void visor_read_bulk_callback (struct urb *urb); static void visor_read_int_callback (struct urb *urb); @@ -916,7 +916,7 @@ static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsign /* This function is all nice and good, but we don't change anything based on it :) */ -static void visor_set_termios (struct usb_serial_port *port, struct termios *old_termios) +static void visor_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { unsigned int cflag; diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 154c7d29059..dc45e58e2b8 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -145,7 +145,7 @@ static void whiteheat_close (struct usb_serial_port *port, struct file *filp); static int whiteheat_write (struct usb_serial_port *port, const unsigned char *buf, int count); static int whiteheat_write_room (struct usb_serial_port *port); static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); -static void whiteheat_set_termios (struct usb_serial_port *port, struct termios * old); +static void whiteheat_set_termios (struct usb_serial_port *port, struct ktermios * old); static int whiteheat_tiocmget (struct usb_serial_port *port, struct file *file); static int whiteheat_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear); static void whiteheat_break_ctl (struct usb_serial_port *port, int break_state); @@ -597,7 +597,7 @@ static void whiteheat_shutdown (struct usb_serial *serial) static int whiteheat_open (struct usb_serial_port *port, struct file *filp) { int retval = 0; - struct termios old_term; + struct ktermios old_term; dbg("%s - port %d", __FUNCTION__, port->number); @@ -870,7 +870,7 @@ static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, un } -static void whiteheat_set_termios (struct usb_serial_port *port, struct termios *old_termios) +static void whiteheat_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { dbg("%s -port %d", __FUNCTION__, port->number); diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 7a43020fa58..ab1daecfeac 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -541,6 +541,7 @@ config FB_TGA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select BITREVERSE help This is the frame buffer device driver for generic TGA graphic cards. Say Y if you have one of those. @@ -551,6 +552,7 @@ config FB_VESA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select VIDEO_SELECT help This is the frame buffer device driver for generic VESA 2.0 compliant graphic cards. The older VESA 1.2 cards are not supported. @@ -705,6 +707,7 @@ config FB_NVIDIA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select BITREVERSE help This driver supports graphics boards with the nVidia chips, TNT and newer. For very old chipsets, such as the RIVA128, then use @@ -744,6 +747,7 @@ config FB_RIVA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select BITREVERSE help This driver supports graphics boards with the nVidia Riva/Geforce chips. diff --git a/drivers/video/S3triofb.c b/drivers/video/S3triofb.c index 397005eb392..b3717c8f1bc 100644 --- a/drivers/video/S3triofb.c +++ b/drivers/video/S3triofb.c @@ -535,8 +535,11 @@ static void __init s3triofb_of_init(struct device_node *dp) #endif fb_info.flags = FBINFO_FLAG_DEFAULT; - if (register_framebuffer(&fb_info) < 0) - return; + if (register_framebuffer(&fb_info) < 0) { + iounmap(fb_info.screen_base); + fb_info.screen_base = NULL; + return; + } printk("fb%d: S3 Trio frame buffer device on %s\n", fb_info.node, dp->full_name); diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index a4e3fca0589..88a47845c4f 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c @@ -2407,10 +2407,10 @@ default_chipset: fb_info.fix.smem_len); if (!videomemory) { printk("amifb: WARNING! unable to map videomem cached writethrough\n"); - videomemory = ZTWO_VADDR(fb_info.fix.smem_start); - } + fb_info.screen_base = (char *)ZTWO_VADDR(fb_info.fix.smem_start); + } else + fb_info.screen_base = (char *)videomemory; - fb_info.screen_base = (char *)videomemory; memset(dummysprite, 0, DUMMYSPRITEMEMSIZE); /* @@ -2453,6 +2453,8 @@ static void amifb_deinit(void) { fb_dealloc_cmap(&fb_info.cmap); chipfree(); + if (videomemory) + iounmap((void*)videomemory); release_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120); custom.dmacon = DMAF_ALL | DMAF_MASTER; } diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c index ab34b96acc3..30a8369757e 100644 --- a/drivers/video/arcfb.c +++ b/drivers/video/arcfb.c @@ -454,7 +454,7 @@ static ssize_t arcfb_write(struct file *file, const char __user *buf, size_t cou unsigned int xres; p = *ppos; - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; fbidx = iminor(inode); info = registered_fb[fbidx]; diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c index 02c41a626fa..602db660bc7 100644 --- a/drivers/video/atafb.c +++ b/drivers/video/atafb.c @@ -2804,8 +2804,19 @@ int __init atafb_init(void) atafb_set_disp(-1, &fb_info); do_install_cmap(0, &fb_info); - if (register_framebuffer(&fb_info) < 0) + if (register_framebuffer(&fb_info) < 0) { +#ifdef ATAFB_EXT + if (external_addr) { + iounmap(external_addr); + external_addr = NULL; + } + if (external_vgaiobase) { + iounmap((void*)external_vgaiobase); + external_vgaiobase = 0; + } +#endif return -EINVAL; + } printk("Determined %dx%d, depth %d\n", disp.var.xres, disp.var.yres, disp.var.bits_per_pixel); diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 276a21530b9..3feddf89d10 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -1333,6 +1333,8 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll, if (vclk * 12 < c.ppll_min) vclk = c.ppll_min/12; + pll->post_divider = -1; + /* now, find an acceptable divider */ for (i = 0; i < sizeof(post_dividers); i++) { output_freq = post_dividers[i] * vclk; @@ -1342,6 +1344,9 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll, } } + if (pll->post_divider < 0) + return -EINVAL; + /* calculate feedback divider */ n = c.ref_divider * output_freq; d = c.ref_clk; diff --git a/drivers/video/aty/atyfb.h b/drivers/video/aty/atyfb.h index b04f49fb976..f72faff33c0 100644 --- a/drivers/video/aty/atyfb.h +++ b/drivers/video/aty/atyfb.h @@ -126,7 +126,6 @@ union aty_pll { */ struct atyfb_par { - struct aty_cmap_regs __iomem *aty_cmap_regs; struct { u8 red, green, blue; } palette[256]; const struct aty_dac_ops *dac_ops; const struct aty_pll_ops *pll_ops; @@ -186,6 +185,7 @@ struct atyfb_par { int mtrr_aper; int mtrr_reg; #endif + u32 mem_cntl; }; /* @@ -227,7 +227,7 @@ static inline u32 aty_ld_le32(int regindex, const struct atyfb_par *par) regindex -= 0x800; #ifdef CONFIG_ATARI - return in_le32((volatile u32 *)(par->ati_regbase + regindex)); + return in_le32(par->ati_regbase + regindex); #else return readl(par->ati_regbase + regindex); #endif @@ -240,7 +240,7 @@ static inline void aty_st_le32(int regindex, u32 val, const struct atyfb_par *pa regindex -= 0x800; #ifdef CONFIG_ATARI - out_le32((volatile u32 *)(par->ati_regbase + regindex), val); + out_le32(par->ati_regbase + regindex, val); #else writel(val, par->ati_regbase + regindex); #endif @@ -253,7 +253,7 @@ static inline void aty_st_le16(int regindex, u16 val, if (regindex >= 0x400) regindex -= 0x800; #ifdef CONFIG_ATARI - out_le16((volatile u16 *)(par->ati_regbase + regindex), val); + out_le16(par->ati_regbase + regindex, val); #else writel(val, par->ati_regbase + regindex); #endif @@ -315,6 +315,7 @@ struct aty_pll_ops { void (*set_pll) (const struct fb_info * info, const union aty_pll * pll); void (*get_pll) (const struct fb_info *info, union aty_pll * pll); int (*init_pll) (const struct fb_info * info, union aty_pll * pll); + void (*resume_pll)(const struct fb_info *info, union aty_pll *pll); }; extern const struct aty_pll_ops aty_pll_ati18818_1; /* ATI 18818 */ diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index e815b354c09..176f9b85cdb 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -203,14 +203,6 @@ static void ATIReduceRatio(int *Numerator, int *Denominator) * The Hardware parameters for each card */ -struct aty_cmap_regs { - u8 windex; - u8 lut; - u8 mask; - u8 rindex; - u8 cntl; -}; - struct pci_mmap_map { unsigned long voff; unsigned long poff; @@ -249,7 +241,8 @@ static int atyfb_sync(struct fb_info *info); * Internal routines */ -static int aty_init(struct fb_info *info, const char *name); +static int aty_init(struct fb_info *info); +static void aty_resume_chip(struct fb_info *info); #ifdef CONFIG_ATARI static int store_video_par(char *videopar, unsigned char m64_num); #endif @@ -1937,17 +1930,14 @@ static void atyfb_save_palette(struct atyfb_par *par, int enter) aty_st_8(DAC_CNTL, tmp, par); aty_st_8(DAC_MASK, 0xff, par); - writeb(i, &par->aty_cmap_regs->rindex); - atyfb_save.r[enter][i] = readb(&par->aty_cmap_regs->lut); - atyfb_save.g[enter][i] = readb(&par->aty_cmap_regs->lut); - atyfb_save.b[enter][i] = readb(&par->aty_cmap_regs->lut); - writeb(i, &par->aty_cmap_regs->windex); - writeb(atyfb_save.r[1 - enter][i], - &par->aty_cmap_regs->lut); - writeb(atyfb_save.g[1 - enter][i], - &par->aty_cmap_regs->lut); - writeb(atyfb_save.b[1 - enter][i], - &par->aty_cmap_regs->lut); + aty_st_8(DAC_R_INDEX, i, par); + atyfb_save.r[enter][i] = aty_ld_8(DAC_DATA, par); + atyfb_save.g[enter][i] = aty_ld_8(DAC_DATA, par); + atyfb_save.b[enter][i] = aty_ld_8(DAC_DATA, par); + aty_st_8(DAC_W_INDEX, i, par); + aty_st_8(DAC_DATA, atyfb_save.r[1 - enter][i], par); + aty_st_8(DAC_DATA, atyfb_save.g[1 - enter][i], par); + aty_st_8(DAC_DATA, atyfb_save.b[1 - enter][i], par); } } @@ -1982,6 +1972,7 @@ static void atyfb_palette(int enter) #if defined(CONFIG_PM) && defined(CONFIG_PCI) +#ifdef CONFIG_PPC_PMAC /* Power management routines. Those are used for PowerBook sleep. */ static int aty_power_mgmt(int sleep, struct atyfb_par *par) @@ -2038,21 +2029,13 @@ static int aty_power_mgmt(int sleep, struct atyfb_par *par) return timeout ? 0 : -EIO; } +#endif static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) { struct fb_info *info = pci_get_drvdata(pdev); struct atyfb_par *par = (struct atyfb_par *) info->par; -#ifndef CONFIG_PPC_PMAC - /* HACK ALERT ! Once I find a proper way to say to each driver - * individually what will happen with it's PCI slot, I'll change - * that. On laptops, the AGP slot is just unclocked, so D2 is - * expected, while on desktops, the card is powered off - */ - return 0; -#endif /* CONFIG_PPC_PMAC */ - if (state.event == pdev->dev.power.power_state.event) return 0; @@ -2070,6 +2053,7 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) par->asleep = 1; par->lock_blank = 1; +#ifdef CONFIG_PPC_PMAC /* Set chip to "suspend" mode */ if (aty_power_mgmt(1, par)) { par->asleep = 0; @@ -2079,6 +2063,9 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) release_console_sem(); return -EIO; } +#else + pci_set_power_state(pdev, pci_choose_state(pdev, state)); +#endif release_console_sem(); @@ -2097,8 +2084,15 @@ static int atyfb_pci_resume(struct pci_dev *pdev) acquire_console_sem(); +#ifdef CONFIG_PPC_PMAC if (pdev->dev.power.power_state.event == 2) aty_power_mgmt(0, par); +#else + pci_set_power_state(pdev, PCI_D0); +#endif + + aty_resume_chip(info); + par->asleep = 0; /* Restore display */ @@ -2344,24 +2338,16 @@ static int __devinit atyfb_get_timings_from_lcd(struct atyfb_par *par, } #endif /* defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD) */ -static int __devinit aty_init(struct fb_info *info, const char *name) +static int __devinit aty_init(struct fb_info *info) { struct atyfb_par *par = (struct atyfb_par *) info->par; const char *ramname = NULL, *xtal; int gtb_memsize, has_var = 0; struct fb_var_screeninfo var; - u8 pll_ref_div; - u32 i; -#if defined(CONFIG_PPC) - int sense; -#endif init_waitqueue_head(&par->vblank.wait); spin_lock_init(&par->int_lock); - par->aty_cmap_regs = - (struct aty_cmap_regs __iomem *) (par->ati_regbase + 0xc0); - #ifdef CONFIG_PPC_PMAC /* The Apple iBook1 uses non-standard memory frequencies. We detect it * and set the frequency manually. */ @@ -2464,18 +2450,21 @@ static int __devinit aty_init(struct fb_info *info, const char *name) par->pll_limits.mclk = 63; } - if (M64_HAS(GTB_DSP) - && (pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par))) { - int diff1, diff2; - diff1 = 510 * 14 / pll_ref_div - par->pll_limits.pll_max; - diff2 = 510 * 29 / pll_ref_div - par->pll_limits.pll_max; - if (diff1 < 0) - diff1 = -diff1; - if (diff2 < 0) - diff2 = -diff2; - if (diff2 < diff1) { - par->ref_clk_per = 1000000000000ULL / 29498928; - xtal = "29.498928"; + if (M64_HAS(GTB_DSP)) { + u8 pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par); + + if (pll_ref_div) { + int diff1, diff2; + diff1 = 510 * 14 / pll_ref_div - par->pll_limits.pll_max; + diff2 = 510 * 29 / pll_ref_div - par->pll_limits.pll_max; + if (diff1 < 0) + diff1 = -diff1; + if (diff2 < 0) + diff2 = -diff2; + if (diff2 < diff1) { + par->ref_clk_per = 1000000000000ULL / 29498928; + xtal = "29.498928"; + } } } #endif /* CONFIG_FB_ATY_CT */ @@ -2485,10 +2474,10 @@ static int __devinit aty_init(struct fb_info *info, const char *name) if(par->pll_ops->get_pll) par->pll_ops->get_pll(info, &saved_pll); - i = aty_ld_le32(MEM_CNTL, par); + par->mem_cntl = aty_ld_le32(MEM_CNTL, par); gtb_memsize = M64_HAS(GTB_DSP); if (gtb_memsize) - switch (i & 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */ + switch (par->mem_cntl & 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */ case MEM_SIZE_512K: info->fix.smem_len = 0x80000; break; @@ -2510,7 +2499,7 @@ static int __devinit aty_init(struct fb_info *info, const char *name) default: info->fix.smem_len = 0x80000; } else - switch (i & MEM_SIZE_ALIAS) { + switch (par->mem_cntl & MEM_SIZE_ALIAS) { case MEM_SIZE_512K: info->fix.smem_len = 0x80000; break; @@ -2540,20 +2529,20 @@ static int __devinit aty_init(struct fb_info *info, const char *name) if (vram) { info->fix.smem_len = vram * 1024; - i = i & ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS); + par->mem_cntl &= ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS); if (info->fix.smem_len <= 0x80000) - i |= MEM_SIZE_512K; + par->mem_cntl |= MEM_SIZE_512K; else if (info->fix.smem_len <= 0x100000) - i |= MEM_SIZE_1M; + par->mem_cntl |= MEM_SIZE_1M; else if (info->fix.smem_len <= 0x200000) - i |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M; + par->mem_cntl |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M; else if (info->fix.smem_len <= 0x400000) - i |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M; + par->mem_cntl |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M; else if (info->fix.smem_len <= 0x600000) - i |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M; + par->mem_cntl |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M; else - i |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M; - aty_st_le32(MEM_CNTL, i, par); + par->mem_cntl |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M; + aty_st_le32(MEM_CNTL, par->mem_cntl, par); } /* @@ -2599,11 +2588,12 @@ static int __devinit aty_init(struct fb_info *info, const char *name) #endif if(par->pll_ops->init_pll) par->pll_ops->init_pll(info, &par->pll); + if (par->pll_ops->resume_pll) + par->pll_ops->resume_pll(info, &par->pll); /* - * Last page of 8 MB (4 MB on ISA) aperture is MMIO - * FIXME: we should use the auxiliary aperture instead so we can access - * the full 8 MB of video RAM on 8 MB boards + * Last page of 8 MB (4 MB on ISA) aperture is MMIO, + * unless the auxiliary register aperture is used. */ if (!par->aux_start && @@ -2669,6 +2659,7 @@ static int __devinit aty_init(struct fb_info *info, const char *name) has_var = 1; } else { if (default_vmode == VMODE_CHOOSE) { + int sense; if (M64_HAS(G3_PB_1024x768)) /* G3 PowerBook with 1024x768 LCD */ default_vmode = VMODE_1024_768_60; @@ -2749,7 +2740,7 @@ static int __devinit aty_init(struct fb_info *info, const char *name) fb_list = info; PRINTKI("fb%d: %s frame buffer device on %s\n", - info->node, info->fix.id, name); + info->node, info->fix.id, par->bus_type == ISA ? "ISA" : "PCI"); return 0; aty_init_exit: @@ -2770,6 +2761,19 @@ aty_init_exit: return -1; } +static void aty_resume_chip(struct fb_info *info) +{ + struct atyfb_par *par = info->par; + + aty_st_le32(MEM_CNTL, par->mem_cntl, par); + + if (par->pll_ops->resume_pll) + par->pll_ops->resume_pll(info, &par->pll); + + if (par->aux_start) + aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, par) | BUS_APER_REG_DIS, par); +} + #ifdef CONFIG_ATARI static int __devinit store_video_par(char *video_str, unsigned char m64_num) { @@ -2826,9 +2830,9 @@ static int atyfb_blank(int blank, struct fb_info *info) #endif gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par); + gen_cntl &= ~0x400004c; switch (blank) { - case FB_BLANK_UNBLANK: - gen_cntl &= ~0x400004c; + case FB_BLANK_UNBLANK: break; case FB_BLANK_NORMAL: gen_cntl |= 0x4000040; @@ -2863,17 +2867,10 @@ static int atyfb_blank(int blank, struct fb_info *info) static void aty_st_pal(u_int regno, u_int red, u_int green, u_int blue, const struct atyfb_par *par) { -#ifdef CONFIG_ATARI - out_8(&par->aty_cmap_regs->windex, regno); - out_8(&par->aty_cmap_regs->lut, red); - out_8(&par->aty_cmap_regs->lut, green); - out_8(&par->aty_cmap_regs->lut, blue); -#else - writeb(regno, &par->aty_cmap_regs->windex); - writeb(red, &par->aty_cmap_regs->lut); - writeb(green, &par->aty_cmap_regs->lut); - writeb(blue, &par->aty_cmap_regs->lut); -#endif + aty_st_8(DAC_W_INDEX, regno, par); + aty_st_8(DAC_DATA, red, par); + aty_st_8(DAC_DATA, green, par); + aty_st_8(DAC_DATA, blue, par); } /* @@ -3182,7 +3179,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev, #ifdef __i386__ #ifdef CONFIG_FB_ATY_GENERIC_LCD -static void aty_init_lcd(struct atyfb_par *par, u32 bios_base) +static void __devinit aty_init_lcd(struct atyfb_par *par, u32 bios_base) { u32 driv_inf_tab, sig; u16 lcd_ofs; @@ -3527,6 +3524,10 @@ static int __devinit atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *i atyfb_setup_generic_fail: iounmap(par->ati_regbase); par->ati_regbase = NULL; + if (info->screen_base) { + iounmap(info->screen_base); + info->screen_base = NULL; + } return ret; } @@ -3594,7 +3595,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi pci_set_drvdata(pdev, info); /* Init chip & register framebuffer */ - if (aty_init(info, "PCI")) + if (aty_init(info)) goto err_release_io; #ifdef __sparc__ @@ -3641,12 +3642,13 @@ err_release_mem: #ifdef CONFIG_ATARI -static int __devinit atyfb_atari_probe(void) +static int __init atyfb_atari_probe(void) { struct atyfb_par *par; struct fb_info *info; int m64_num; u32 clock_r; + int num_found = 0; for (m64_num = 0; m64_num < mach64_count; m64_num++) { if (!phys_vmembase[m64_num] || !phys_size[m64_num] || @@ -3694,16 +3696,34 @@ static int __devinit atyfb_atari_probe(void) break; } - if (aty_init(info, "ISA bus")) { + /* Fake pci_id for correct_chipset() */ + switch (aty_ld_le32(CONFIG_CHIP_ID, par) & CFG_CHIP_TYPE) { + case 0x00d7: + par->pci_id = PCI_CHIP_MACH64GX; + break; + case 0x0057: + par->pci_id = PCI_CHIP_MACH64CX; + break; + default: + break; + } + + if (correct_chipset(par) || aty_init(info)) { + iounmap(info->screen_base); + iounmap(par->ati_regbase); framebuffer_release(info); - /* This is insufficient! kernel_map has added two large chunks!! */ - return -ENXIO; + } else { + num_found++; } } + + return num_found ? 0 : -ENXIO; } #endif /* CONFIG_ATARI */ +#ifdef CONFIG_PCI + static void __devexit atyfb_remove(struct fb_info *info) { struct atyfb_par *par = (struct atyfb_par *) info->par; @@ -3751,7 +3771,6 @@ static void __devexit atyfb_remove(struct fb_info *info) framebuffer_release(info); } -#ifdef CONFIG_PCI static void __devexit atyfb_pci_remove(struct pci_dev *pdev) { @@ -3786,7 +3805,7 @@ static struct pci_driver atyfb_driver = { #endif /* CONFIG_PCI */ #ifndef MODULE -static int __devinit atyfb_setup(char *options) +static int __init atyfb_setup(char *options) { char *this_opt; @@ -3858,7 +3877,7 @@ static int __devinit atyfb_setup(char *options) } #endif /* MODULE */ -static int __devinit atyfb_init(void) +static int __init atyfb_init(void) { int err1 = 1, err2 = 1; #ifndef MODULE diff --git a/drivers/video/aty/mach64_ct.c b/drivers/video/aty/mach64_ct.c index 5080816be65..f3b487b8710 100644 --- a/drivers/video/aty/mach64_ct.c +++ b/drivers/video/aty/mach64_ct.c @@ -370,8 +370,8 @@ void aty_set_pll_ct(const struct fb_info *info, const union aty_pll *pll) #endif } -static void __init aty_get_pll_ct(const struct fb_info *info, - union aty_pll *pll) +static void __devinit aty_get_pll_ct(const struct fb_info *info, + union aty_pll *pll) { struct atyfb_par *par = (struct atyfb_par *) info->par; u8 tmp, clock; @@ -394,12 +394,12 @@ static void __init aty_get_pll_ct(const struct fb_info *info, } } -static int __init aty_init_pll_ct(const struct fb_info *info, - union aty_pll *pll) +static int __devinit aty_init_pll_ct(const struct fb_info *info, + union aty_pll *pll) { struct atyfb_par *par = (struct atyfb_par *) info->par; - u8 mpost_div, xpost_div, sclk_post_div_real, sclk_fb_div, spll_cntl2; - u32 q, i, memcntl, trp; + u8 mpost_div, xpost_div, sclk_post_div_real; + u32 q, memcntl, trp; u32 dsp_config, dsp_on_off, vga_dsp_config, vga_dsp_on_off; #ifdef DEBUG int pllmclk, pllsclk; @@ -575,14 +575,30 @@ static int __init aty_init_pll_ct(const struct fb_info *info, mpost_div += (q < 32*8); } sclk_post_div_real = postdividers[mpost_div]; - sclk_fb_div = q * sclk_post_div_real / 8; - spll_cntl2 = mpost_div << 4; + pll->ct.sclk_fb_div = q * sclk_post_div_real / 8; + pll->ct.spll_cntl2 = mpost_div << 4; #ifdef DEBUG - pllsclk = (1000000 * 2 * sclk_fb_div) / + pllsclk = (1000000 * 2 * pll->ct.sclk_fb_div) / (par->ref_clk_per * pll->ct.pll_ref_div); printk("atyfb(%s): use sclk, pllsclk=%d MHz, sclk=mclk=%d MHz\n", __FUNCTION__, pllsclk, pllsclk / sclk_post_div_real); #endif + } + + /* Disable the extra precision pixel clock controls since we do not use them. */ + pll->ct.ext_vpll_cntl = aty_ld_pll_ct(EXT_VPLL_CNTL, par); + pll->ct.ext_vpll_cntl &= ~(EXT_VPLL_EN | EXT_VPLL_VGA_EN | EXT_VPLL_INSYNC); + + return 0; +} + +static void aty_resume_pll_ct(const struct fb_info *info, + union aty_pll *pll) +{ + struct atyfb_par *par = info->par; + + if (par->mclk_per != par->xclk_per) { + int i; /* * This disables the sclk, crashes the computer as reported: * aty_st_pll_ct(SPLL_CNTL2, 3, info); @@ -590,8 +606,8 @@ static int __init aty_init_pll_ct(const struct fb_info *info, * So it seems the sclk must be enabled before it is used; * so PLL_GEN_CNTL must be programmed *after* the sclk. */ - aty_st_pll_ct(SCLK_FB_DIV, sclk_fb_div, par); - aty_st_pll_ct(SPLL_CNTL2, spll_cntl2, par); + aty_st_pll_ct(SCLK_FB_DIV, pll->ct.sclk_fb_div, par); + aty_st_pll_ct(SPLL_CNTL2, pll->ct.spll_cntl2, par); /* * The sclk has been started. However, I believe the first clock * ticks it generates are not very stable. Hope this primitive loop @@ -605,11 +621,7 @@ static int __init aty_init_pll_ct(const struct fb_info *info, aty_st_pll_ct(PLL_GEN_CNTL, pll->ct.pll_gen_cntl, par); aty_st_pll_ct(MCLK_FB_DIV, pll->ct.mclk_fb_div, par); aty_st_pll_ct(PLL_EXT_CNTL, pll->ct.pll_ext_cntl, par); - /* Disable the extra precision pixel clock controls since we do not use them. */ - aty_st_pll_ct(EXT_VPLL_CNTL, aty_ld_pll_ct(EXT_VPLL_CNTL, par) & - ~(EXT_VPLL_EN | EXT_VPLL_VGA_EN | EXT_VPLL_INSYNC), par); - - return 0; + aty_st_pll_ct(EXT_VPLL_CNTL, pll->ct.ext_vpll_cntl, par); } static int dummy(void) @@ -626,5 +638,6 @@ const struct aty_pll_ops aty_pll_ct = { .pll_to_var = aty_pll_to_var_ct, .set_pll = aty_set_pll_ct, .get_pll = aty_get_pll_ct, - .init_pll = aty_init_pll_ct + .init_pll = aty_init_pll_ct, + .resume_pll = aty_resume_pll_ct, }; diff --git a/drivers/video/aty/radeon_monitor.c b/drivers/video/aty/radeon_monitor.c index ea531a6f45d..38c7dbf8c15 100644 --- a/drivers/video/aty/radeon_monitor.c +++ b/drivers/video/aty/radeon_monitor.c @@ -104,10 +104,9 @@ static int __devinit radeon_parse_montype_prop(struct device_node *dp, u8 **out_ if (pedid == NULL) return mt; - tmp = (u8 *)kmalloc(EDID_LENGTH, GFP_KERNEL); + tmp = kmemdup(pedid, EDID_LENGTH, GFP_KERNEL); if (!tmp) return mt; - memcpy(tmp, pedid, EDID_LENGTH); *out_EDID = tmp; return mt; } diff --git a/drivers/video/au1100fb.h b/drivers/video/au1100fb.h index 2855534dc23..164fe2f231e 100644 --- a/drivers/video/au1100fb.h +++ b/drivers/video/au1100fb.h @@ -274,7 +274,7 @@ static struct au1100fb_panel known_lcd_panels[] = .bpp = 16, .control_base = 0x0004886A | LCD_CONTROL_DEFAULT_PO | LCD_CONTROL_DEFAULT_SBPPF | - LCD_CONTROL_BPP_16, + LCD_CONTROL_BPP_16 | LCD_CONTROL_SBB_4, .clkcontrol_base = 0x00020000, .horztiming = 0x005aff1f, .verttiming = 0x16000e57, diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 27597c576ef..db8c191b120 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -14,6 +14,59 @@ #include <linux/err.h> #include <linux/fb.h> + +#if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \ + defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)) +/* This callback gets called when something important happens inside a + * framebuffer driver. We're looking if that important event is blanking, + * and if it is, we're switching backlight power as well ... + */ +static int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + struct backlight_device *bd; + struct fb_event *evdata = data; + + /* If we aren't interested in this event, skip it immediately ... */ + if (event != FB_EVENT_BLANK) + return 0; + + bd = container_of(self, struct backlight_device, fb_notif); + down(&bd->sem); + if (bd->props) + if (!bd->props->check_fb || + bd->props->check_fb(evdata->info)) { + bd->props->fb_blank = *(int *)evdata->data; + if (likely(bd->props && bd->props->update_status)) + bd->props->update_status(bd); + } + up(&bd->sem); + return 0; +} + +static int backlight_register_fb(struct backlight_device *bd) +{ + memset(&bd->fb_notif, 0, sizeof(bd->fb_notif)); + bd->fb_notif.notifier_call = fb_notifier_callback; + + return fb_register_client(&bd->fb_notif); +} + +static void backlight_unregister_fb(struct backlight_device *bd) +{ + fb_unregister_client(&bd->fb_notif); +} +#else +static inline int backlight_register_fb(struct backlight_device *bd) +{ + return 0; +} + +static inline void backlight_unregister_fb(struct backlight_device *bd) +{ +} +#endif /* CONFIG_FB */ + static ssize_t backlight_show_power(struct class_device *cdev, char *buf) { int rc = -ENXIO; @@ -142,7 +195,7 @@ static struct class backlight_class = { .store = _store, \ } -static struct class_device_attribute bl_class_device_attributes[] = { +static const struct class_device_attribute bl_class_device_attributes[] = { DECLARE_ATTR(power, 0644, backlight_show_power, backlight_store_power), DECLARE_ATTR(brightness, 0644, backlight_show_brightness, backlight_store_brightness), @@ -151,33 +204,6 @@ static struct class_device_attribute bl_class_device_attributes[] = { DECLARE_ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL), }; -/* This callback gets called when something important happens inside a - * framebuffer driver. We're looking if that important event is blanking, - * and if it is, we're switching backlight power as well ... - */ -static int fb_notifier_callback(struct notifier_block *self, - unsigned long event, void *data) -{ - struct backlight_device *bd; - struct fb_event *evdata =(struct fb_event *)data; - - /* If we aren't interested in this event, skip it immediately ... */ - if (event != FB_EVENT_BLANK) - return 0; - - bd = container_of(self, struct backlight_device, fb_notif); - down(&bd->sem); - if (bd->props) - if (!bd->props->check_fb || - bd->props->check_fb(evdata->info)) { - bd->props->fb_blank = *(int *)evdata->data; - if (likely(bd->props && bd->props->update_status)) - bd->props->update_status(bd); - } - up(&bd->sem); - return 0; -} - /** * backlight_device_register - create and register a new object of * backlight_device class. @@ -215,10 +241,7 @@ error: kfree(new_bd); return ERR_PTR(rc); } - memset(&new_bd->fb_notif, 0, sizeof(new_bd->fb_notif)); - new_bd->fb_notif.notifier_call = fb_notifier_callback; - - rc = fb_register_client(&new_bd->fb_notif); + rc = backlight_register_fb(new_bd); if (unlikely(rc)) goto error; @@ -259,16 +282,10 @@ void backlight_device_unregister(struct backlight_device *bd) &bl_class_device_attributes[i]); down(&bd->sem); - if (likely(bd->props && bd->props->update_status)) { - bd->props->brightness = 0; - bd->props->power = 0; - bd->props->update_status(bd); - } - bd->props = NULL; up(&bd->sem); - fb_unregister_client(&bd->fb_notif); + backlight_unregister_fb(bd); class_device_unregister(&bd->class_dev); } diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c index d07ecb53c68..61587ca2cdb 100644 --- a/drivers/video/backlight/corgi_bl.c +++ b/drivers/video/backlight/corgi_bl.c @@ -135,6 +135,10 @@ static int corgibl_probe(struct platform_device *pdev) static int corgibl_remove(struct platform_device *dev) { + corgibl_data.power = 0; + corgibl_data.brightness = 0; + corgibl_send_intensity(corgi_backlight_device); + backlight_device_unregister(corgi_backlight_device); printk("Corgi Backlight Driver Unloaded\n"); diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c index e3993213d10..1c569fb543a 100644 --- a/drivers/video/backlight/hp680_bl.c +++ b/drivers/video/backlight/hp680_bl.c @@ -117,6 +117,10 @@ static int __init hp680bl_probe(struct platform_device *dev) static int hp680bl_remove(struct platform_device *dev) { + hp680bl_data.brightness = 0; + hp680bl_data.power = 0; + hp680bl_send_intensity(hp680_backlight_device); + backlight_device_unregister(hp680_backlight_device); return 0; diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index bc8ab005a3f..f6e041627ed 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c @@ -14,6 +14,53 @@ #include <linux/err.h> #include <linux/fb.h> +#if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \ + defined(CONFIG_LCD_CLASS_DEVICE_MODULE)) +/* This callback gets called when something important happens inside a + * framebuffer driver. We're looking if that important event is blanking, + * and if it is, we're switching lcd power as well ... + */ +static int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + struct lcd_device *ld; + struct fb_event *evdata = data; + + /* If we aren't interested in this event, skip it immediately ... */ + if (event != FB_EVENT_BLANK) + return 0; + + ld = container_of(self, struct lcd_device, fb_notif); + down(&ld->sem); + if (ld->props) + if (!ld->props->check_fb || ld->props->check_fb(evdata->info)) + ld->props->set_power(ld, *(int *)evdata->data); + up(&ld->sem); + return 0; +} + +static int lcd_register_fb(struct lcd_device *ld) +{ + memset(&ld->fb_notif, 0, sizeof(&ld->fb_notif)); + ld->fb_notif.notifier_call = fb_notifier_callback; + return fb_register_client(&ld->fb_notif); +} + +static void lcd_unregister_fb(struct lcd_device *ld) +{ + fb_unregister_client(&ld->fb_notif); +} +#else +static int lcd_register_fb(struct lcd_device *ld) +{ + return 0; +} + +static inline void lcd_unregister_fb(struct lcd_device *ld) +{ +} +#endif /* CONFIG_FB */ + static ssize_t lcd_show_power(struct class_device *cdev, char *buf) { int rc; @@ -121,35 +168,12 @@ static struct class lcd_class = { .store = _store, \ } -static struct class_device_attribute lcd_class_device_attributes[] = { +static const struct class_device_attribute lcd_class_device_attributes[] = { DECLARE_ATTR(power, 0644, lcd_show_power, lcd_store_power), DECLARE_ATTR(contrast, 0644, lcd_show_contrast, lcd_store_contrast), DECLARE_ATTR(max_contrast, 0444, lcd_show_max_contrast, NULL), }; -/* This callback gets called when something important happens inside a - * framebuffer driver. We're looking if that important event is blanking, - * and if it is, we're switching lcd power as well ... - */ -static int fb_notifier_callback(struct notifier_block *self, - unsigned long event, void *data) -{ - struct lcd_device *ld; - struct fb_event *evdata =(struct fb_event *)data; - - /* If we aren't interested in this event, skip it immediately ... */ - if (event != FB_EVENT_BLANK) - return 0; - - ld = container_of(self, struct lcd_device, fb_notif); - down(&ld->sem); - if (ld->props) - if (!ld->props->check_fb || ld->props->check_fb(evdata->info)) - ld->props->set_power(ld, *(int *)evdata->data); - up(&ld->sem); - return 0; -} - /** * lcd_device_register - register a new object of lcd_device class. * @name: the name of the new object(must be the same as the name of the @@ -186,10 +210,8 @@ error: kfree(new_ld); return ERR_PTR(rc); } - memset(&new_ld->fb_notif, 0, sizeof(new_ld->fb_notif)); - new_ld->fb_notif.notifier_call = fb_notifier_callback; + rc = lcd_register_fb(new_ld); - rc = fb_register_client(&new_ld->fb_notif); if (unlikely(rc)) goto error; @@ -232,9 +254,7 @@ void lcd_device_unregister(struct lcd_device *ld) down(&ld->sem); ld->props = NULL; up(&ld->sem); - - fb_unregister_client(&ld->fb_notif); - + lcd_unregister_fb(ld); class_device_unregister(&ld->class_dev); } EXPORT_SYMBOL(lcd_device_unregister); diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c index 628571c63ba..2d7905410b2 100644 --- a/drivers/video/backlight/locomolcd.c +++ b/drivers/video/backlight/locomolcd.c @@ -200,6 +200,10 @@ static int locomolcd_remove(struct locomo_dev *dev) { unsigned long flags; + locomobl_data.brightness = 0; + locomobl_data.power = 0; + locomolcd_set_intensity(locomolcd_bl_device); + backlight_device_unregister(locomolcd_bl_device); local_irq_save(flags); locomolcd_dev = NULL; diff --git a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c index 51d35386a94..261004473c8 100644 --- a/drivers/video/cfbimgblt.c +++ b/drivers/video/cfbimgblt.c @@ -42,7 +42,7 @@ #define DPRINTK(fmt, args...) #endif -static u32 cfb_tab8[] = { +static const u32 cfb_tab8[] = { #if defined(__BIG_ENDIAN) 0x00000000,0x000000ff,0x0000ff00,0x0000ffff, 0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff, @@ -58,7 +58,7 @@ static u32 cfb_tab8[] = { #endif }; -static u32 cfb_tab16[] = { +static const u32 cfb_tab16[] = { #if defined(__BIG_ENDIAN) 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff #elif defined(__LITTLE_ENDIAN) @@ -68,7 +68,7 @@ static u32 cfb_tab16[] = { #endif }; -static u32 cfb_tab32[] = { +static const u32 cfb_tab32[] = { 0x00000000, 0xffffffff }; @@ -218,7 +218,7 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info * u32 bit_mask, end_mask, eorx, shift; const char *s = image->data, *src; u32 __iomem *dst; - u32 *tab = NULL; + const u32 *tab = NULL; int i, j, k; switch (bpp) { diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index daf43f535a0..2c4bc620573 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -2442,7 +2442,10 @@ static int cirrusfb_pci_register (struct pci_dev *pdev, printk ("Cirrus Logic chipset on PCI bus\n"); pci_set_drvdata(pdev, info); - return cirrusfb_register(cinfo); + ret = cirrusfb_register(cinfo); + if (ret) + iounmap(cinfo->fbmem); + return ret; err_release_legacy: if (release_io_ports) @@ -2574,7 +2577,15 @@ static int cirrusfb_zorro_register(struct zorro_dev *z, printk (KERN_INFO "Cirrus Logic chipset on Zorro bus\n"); zorro_set_drvdata(z, info); - return cirrusfb_register(cinfo); + ret = cirrusfb_register(cinfo); + if (ret) { + if (btype == BT_PICASSO4) { + iounmap(cinfo->fbmem); + iounmap(cinfo->regbase - 0x600000); + } else if (board_addr > 0x01000000) + iounmap(cinfo->fbmem); + } + return ret; err_unmap_regbase: /* Parental advisory: explicit hack */ diff --git a/drivers/video/console/softcursor.c b/drivers/video/console/softcursor.c index 7d07d838356..f577bd80e02 100644 --- a/drivers/video/console/softcursor.c +++ b/drivers/video/console/softcursor.c @@ -1,11 +1,13 @@ /* - * linux/drivers/video/softcursor.c -- Generic software cursor for frame buffer devices + * linux/drivers/video/softcursor.c + * + * Generic software cursor for frame buffer devices * * Created 14 Nov 2002 by James Simmons * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file COPYING in the main directory of this + * archive for more details. */ #include <linux/module.h> @@ -25,7 +27,7 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) unsigned int buf_align = info->pixmap.buf_align - 1; unsigned int i, size, dsize, s_pitch, d_pitch; struct fb_image *image; - u8 *dst; + u8 *src, *dst; if (info->state != FBINFO_STATE_RUNNING) return 0; @@ -45,7 +47,8 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) } } - image = (struct fb_image *) (ops->cursor_src + dsize); + src = ops->cursor_src + sizeof(struct fb_image); + image = (struct fb_image *)ops->cursor_src; *image = cursor->image; d_pitch = (s_pitch + scan_align) & ~scan_align; @@ -57,21 +60,18 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) switch (cursor->rop) { case ROP_XOR: for (i = 0; i < dsize; i++) - ops->cursor_src[i] = image->data[i] ^ - cursor->mask[i]; + src[i] = image->data[i] ^ cursor->mask[i]; break; case ROP_COPY: default: for (i = 0; i < dsize; i++) - ops->cursor_src[i] = image->data[i] & - cursor->mask[i]; + src[i] = image->data[i] & cursor->mask[i]; break; } } else - memcpy(ops->cursor_src, image->data, dsize); + memcpy(src, image->data, dsize); - fb_pad_aligned_buffer(dst, d_pitch, ops->cursor_src, s_pitch, - image->height); + fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, image->height); image->data = dst; info->fbops->fb_imageblit(info, image); return 0; diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index 45586aaabd1..57b21e53303 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c @@ -345,7 +345,7 @@ static void sticon_save_screen(struct vc_data *conp) { } -static struct consw sti_con = { +static const struct consw sti_con = { .owner = THIS_MODULE, .con_startup = sticon_startup, .con_init = sticon_init, diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 0a2c10a1abf..4a9bde2c839 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -93,27 +93,27 @@ static void vgacon_invert_region(struct vc_data *c, u16 * p, int count); static unsigned long vgacon_uni_pagedir[2]; /* Description of the hardware situation */ -static unsigned long vga_vram_base; /* Base of video memory */ -static unsigned long vga_vram_end; /* End of video memory */ -static int vga_vram_size; /* Size of video memory */ -static u16 vga_video_port_reg; /* Video register select port */ -static u16 vga_video_port_val; /* Video register value port */ -static unsigned int vga_video_num_columns; /* Number of text columns */ -static unsigned int vga_video_num_lines; /* Number of text lines */ -static int vga_can_do_color = 0; /* Do we support colors? */ -static unsigned int vga_default_font_height;/* Height of default screen font */ -static unsigned char vga_video_type; /* Card type */ -static unsigned char vga_hardscroll_enabled; -static unsigned char vga_hardscroll_user_enable = 1; +static int vga_init_done __read_mostly; +static unsigned long vga_vram_base __read_mostly; /* Base of video memory */ +static unsigned long vga_vram_end __read_mostly; /* End of video memory */ +static unsigned int vga_vram_size __read_mostly; /* Size of video memory */ +static u16 vga_video_port_reg __read_mostly; /* Video register select port */ +static u16 vga_video_port_val __read_mostly; /* Video register value port */ +static unsigned int vga_video_num_columns; /* Number of text columns */ +static unsigned int vga_video_num_lines; /* Number of text lines */ +static int vga_can_do_color __read_mostly; /* Do we support colors? */ +static unsigned int vga_default_font_height __read_mostly; /* Height of default screen font */ +static unsigned char vga_video_type __read_mostly; /* Card type */ +static unsigned char vga_hardscroll_enabled __read_mostly; +static unsigned char vga_hardscroll_user_enable __read_mostly = 1; static unsigned char vga_font_is_default = 1; static int vga_vesa_blanked; static int vga_palette_blanked; static int vga_is_gfx; static int vga_512_chars; static int vga_video_font_height; -static int vga_scan_lines; -static unsigned int vga_rolled_over = 0; -static int vga_init_done; +static int vga_scan_lines __read_mostly; +static unsigned int vga_rolled_over; static int __init no_scroll(char *str) { diff --git a/drivers/video/cyberfb.c b/drivers/video/cyberfb.c index c40e72dafb0..0b8d5b12115 100644 --- a/drivers/video/cyberfb.c +++ b/drivers/video/cyberfb.c @@ -109,8 +109,6 @@ static void cv64_dump(void); #define wb_64(regs,reg,dat) (*(((volatile unsigned char *)regs) + reg) = dat) #define rb_64(regs, reg) (*(((volatile unsigned char *)regs) + reg)) -#define ww_64(regs,reg,dat) (*((volatile unsigned short *)(regs + reg) = dat) - struct cyberfb_par { struct fb_var_screeninfo var; __u32 type; @@ -1055,6 +1053,8 @@ int __init cyberfb_init(void) if (register_framebuffer(&fb_info) < 0) { DPRINTK("EXIT - register_framebuffer failed\n"); + if (CyberBase) + iounmap(CyberBase); release_mem_region(CyberMem_phys, 0x400000); release_mem_region(CyberRegs_phys, 0x10000); return -EINVAL; diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c index 737257d278f..29e07c10988 100644 --- a/drivers/video/epson1355fb.c +++ b/drivers/video/epson1355fb.c @@ -405,7 +405,7 @@ static inline unsigned long copy_to_user16(void *to, const void *from, static ssize_t epson1355fb_read(struct file *file, char *buf, size_t count, loff_t * ppos) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int fbidx = iminor(inode); struct fb_info *info = registered_fb[fbidx]; unsigned long p = *ppos; @@ -437,7 +437,7 @@ static ssize_t epson1355fb_write(struct file *file, const char *buf, size_t count, loff_t * ppos) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int fbidx = iminor(inode); struct fb_info *info = registered_fb[fbidx]; unsigned long p = *ppos; diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c index e8b135f3d80..148108afdd5 100644 --- a/drivers/video/fbcmap.c +++ b/drivers/video/fbcmap.c @@ -18,63 +18,64 @@ #include <asm/uaccess.h> -static u16 red2[] = { +static u16 red2[] __read_mostly = { 0x0000, 0xaaaa }; -static u16 green2[] = { +static u16 green2[] __read_mostly = { 0x0000, 0xaaaa }; -static u16 blue2[] = { +static u16 blue2[] __read_mostly = { 0x0000, 0xaaaa }; -static u16 red4[] = { +static u16 red4[] __read_mostly = { 0x0000, 0xaaaa, 0x5555, 0xffff }; -static u16 green4[] = { +static u16 green4[] __read_mostly = { 0x0000, 0xaaaa, 0x5555, 0xffff }; -static u16 blue4[] = { +static u16 blue4[] __read_mostly = { 0x0000, 0xaaaa, 0x5555, 0xffff }; -static u16 red8[] = { +static u16 red8[] __read_mostly = { 0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa }; -static u16 green8[] = { +static u16 green8[] __read_mostly = { 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa }; -static u16 blue8[] = { +static u16 blue8[] __read_mostly = { 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa }; -static u16 red16[] = { +static u16 red16[] __read_mostly = { 0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa, 0x5555, 0x5555, 0x5555, 0x5555, 0xffff, 0xffff, 0xffff, 0xffff }; -static u16 green16[] = { +static u16 green16[] __read_mostly = { 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa, 0x5555, 0x5555, 0xffff, 0xffff, 0x5555, 0x5555, 0xffff, 0xffff }; -static u16 blue16[] = { +static u16 blue16[] __read_mostly = { 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff }; -static struct fb_cmap default_2_colors = { - 0, 2, red2, green2, blue2, NULL +static const struct fb_cmap default_2_colors = { + .len=2, .red=red2, .green=green2, .blue=blue2 }; -static struct fb_cmap default_8_colors = { - 0, 8, red8, green8, blue8, NULL +static const struct fb_cmap default_8_colors = { + .len=8, .red=red8, .green=green8, .blue=blue8 }; -static struct fb_cmap default_4_colors = { - 0, 4, red4, green4, blue4, NULL +static const struct fb_cmap default_4_colors = { + .len=4, .red=red4, .green=green4, .blue=blue4 }; -static struct fb_cmap default_16_colors = { - 0, 16, red16, green16, blue16, NULL +static const struct fb_cmap default_16_colors = { + .len=16, .red=red16, .green=green16, .blue=blue16 }; + /** * fb_alloc_cmap - allocate a colormap * @cmap: frame buffer colormap structure @@ -146,7 +147,7 @@ void fb_dealloc_cmap(struct fb_cmap *cmap) * Copy contents of colormap from @from to @to. */ -int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to) +int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to) { int tooff = 0, fromoff = 0; int size; @@ -170,7 +171,7 @@ int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to) return 0; } -int fb_cmap_to_user(struct fb_cmap *from, struct fb_cmap_user *to) +int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to) { int tooff = 0, fromoff = 0; int size; @@ -282,7 +283,7 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info) * */ -struct fb_cmap *fb_default_cmap(int len) +const struct fb_cmap *fb_default_cmap(int len) { if (len <= 2) return &default_2_colors; @@ -305,22 +306,22 @@ void fb_invert_cmaps(void) { u_int i; - for (i = 0; i < 2; i++) { + for (i = 0; i < ARRAY_SIZE(red2); i++) { red2[i] = ~red2[i]; green2[i] = ~green2[i]; blue2[i] = ~blue2[i]; } - for (i = 0; i < 4; i++) { + for (i = 0; i < ARRAY_SIZE(red4); i++) { red4[i] = ~red4[i]; green4[i] = ~green4[i]; blue4[i] = ~blue4[i]; } - for (i = 0; i < 8; i++) { + for (i = 0; i < ARRAY_SIZE(red8); i++) { red8[i] = ~red8[i]; green8[i] = ~green8[i]; blue8[i] = ~blue8[i]; } - for (i = 0; i < 16; i++) { + for (i = 0; i < ARRAY_SIZE(red16); i++) { red16[i] = ~red16[i]; green16[i] = ~green16[i]; blue16[i] = ~blue16[i]; diff --git a/drivers/video/fbcvt.c b/drivers/video/fbcvt.c index b5498999c4e..0847c5e72cb 100644 --- a/drivers/video/fbcvt.c +++ b/drivers/video/fbcvt.c @@ -57,7 +57,7 @@ struct fb_cvt_data { u32 status; }; -static int fb_cvt_vbi_tab[] = { +static const unsigned char fb_cvt_vbi_tab[] = { 4, /* 4:3 */ 5, /* 16:9 */ 6, /* 16:10 */ diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index e973a87fbb0..3cfea315a48 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -52,8 +52,8 @@ #define FBPIXMAPSIZE (1024 * 8) -struct fb_info *registered_fb[FB_MAX]; -int num_registered_fb; +struct fb_info *registered_fb[FB_MAX] __read_mostly; +int num_registered_fb __read_mostly; /* * Helpers @@ -202,7 +202,7 @@ static void fb_set_logo_truepalette(struct fb_info *info, const struct linux_logo *logo, u32 *palette) { - unsigned char mask[9] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff }; + static const unsigned char mask[] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff }; unsigned char redmask, greenmask, bluemask; int redshift, greenshift, blueshift; int i; @@ -317,7 +317,7 @@ static struct logo_data { int needs_truepalette; int needs_cmapreset; const struct linux_logo *logo; -} fb_logo; +} fb_logo __read_mostly; static void fb_rotate_logo_ud(const u8 *in, u8 *out, u32 width, u32 height) { @@ -572,7 +572,7 @@ static ssize_t fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { unsigned long p = *ppos; - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int fbidx = iminor(inode); struct fb_info *info = registered_fb[fbidx]; u32 *buffer, *dst; @@ -647,7 +647,7 @@ static ssize_t fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { unsigned long p = *ppos; - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int fbidx = iminor(inode); struct fb_info *info = registered_fb[fbidx]; u32 *buffer, *src; @@ -1081,7 +1081,7 @@ static int fb_get_fscreeninfo(struct inode *inode, struct file *file, static long fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int fbidx = iminor(inode); struct fb_info *info = registered_fb[fbidx]; struct fb_ops *fb = info->fbops; @@ -1121,7 +1121,7 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) static int fb_mmap(struct file *file, struct vm_area_struct * vma) { - int fbidx = iminor(file->f_dentry->d_inode); + int fbidx = iminor(file->f_path.dentry->d_inode); struct fb_info *info = registered_fb[fbidx]; struct fb_ops *fb = info->fbops; unsigned long off; @@ -1253,7 +1253,7 @@ fb_release(struct inode *inode, struct file *file) return 0; } -static struct file_operations fb_fops = { +static const struct file_operations fb_fops = { .owner = THIS_MODULE, .read = fb_read, .write = fb_write, @@ -1459,8 +1459,8 @@ int fb_new_modelist(struct fb_info *info) return err; } -static char *video_options[FB_MAX]; -static int ofonly; +static char *video_options[FB_MAX] __read_mostly; +static int ofonly __read_mostly; extern const char *global_mode_option; diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c index de93139ccbb..6b385c39b8b 100644 --- a/drivers/video/fbmon.c +++ b/drivers/video/fbmon.c @@ -58,7 +58,7 @@ struct broken_edid { u32 fix; }; -static struct broken_edid brokendb[] = { +static const struct broken_edid brokendb[] = { /* DEC FR-PCXAV-YZ */ { .manufacturer = "DEC", diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c index 2a0e8210d39..949141bd44d 100644 --- a/drivers/video/ffb.c +++ b/drivers/video/ffb.c @@ -968,6 +968,8 @@ static int ffb_init_one(struct of_device *op) if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { printk(KERN_ERR "ffb: Could not allocate color map.\n"); + of_iounmap(all->par.fbc, sizeof(struct ffb_fbc)); + of_iounmap(all->par.dac, sizeof(struct ffb_dac)); kfree(all); return -ENOMEM; } @@ -978,6 +980,8 @@ static int ffb_init_one(struct of_device *op) if (err < 0) { printk(KERN_ERR "ffb: Could not register framebuffer.\n"); fb_dealloc_cmap(&all->info.cmap); + of_iounmap(all->par.fbc, sizeof(struct ffb_fbc)); + of_iounmap(all->par.dac, sizeof(struct ffb_dac)); kfree(all); return err; } diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c index 998374cfae6..70ff55b1459 100644 --- a/drivers/video/fm2fb.c +++ b/drivers/video/fm2fb.c @@ -283,6 +283,7 @@ static int __devinit fm2fb_probe(struct zorro_dev *z, if (register_framebuffer(info) < 0) { fb_dealloc_cmap(&info->cmap); + iounmap(info->screen_base); framebuffer_release(info); zorro_release_device(z); return -EINVAL; diff --git a/drivers/video/geode/Kconfig b/drivers/video/geode/Kconfig index 4e173ef20a7..a814b6c2605 100644 --- a/drivers/video/geode/Kconfig +++ b/drivers/video/geode/Kconfig @@ -23,6 +23,26 @@ config FB_GEODE_GX If unsure, say N. +config FB_GEODE_GX_SET_FBSIZE + bool "Manually specify the Geode GX framebuffer size" + depends on FB_GEODE_GX + default n + ---help--- + If you want to manually specify the size of your GX framebuffer, + say Y here, otherwise say N to dynamically probe it. + + Say N unless you know what you are doing. + +config FB_GEODE_GX_FBSIZE + hex "Size of the GX framebuffer, in bytes" + depends on FB_GEODE_GX_SET_FBSIZE + default "0x1600000" + ---help--- + Specify the size of the GX framebuffer. Normally, you will + want this to be MB aligned. Common values are 0x80000 (8MB) + and 0x1600000 (16MB). Don't change this unless you know what + you are doing + config FB_GEODE_GX1 tristate "AMD Geode GX1 framebuffer support (EXPERIMENTAL)" depends on FB && FB_GEODE && EXPERIMENTAL diff --git a/drivers/video/geode/display_gx.c b/drivers/video/geode/display_gx.c index 825c3405f5c..0f16e4bffc6 100644 --- a/drivers/video/geode/display_gx.c +++ b/drivers/video/geode/display_gx.c @@ -21,11 +21,27 @@ #include "geodefb.h" #include "display_gx.h" -int gx_frame_buffer_size(void) +#ifdef CONFIG_FB_GEODE_GX_SET_FBSIZE +unsigned int gx_frame_buffer_size(void) { - /* Assuming 16 MiB. */ - return 16*1024*1024; + return CONFIG_FB_GEODE_GX_FBSIZE; } +#else +unsigned int gx_frame_buffer_size(void) +{ + unsigned int val; + + /* FB size is reported by a virtual register */ + /* Virtual register class = 0x02 */ + /* VG_MEM_SIZE(512Kb units) = 0x00 */ + + outw(0xFC53, 0xAC1C); + outw(0x0200, 0xAC1C); + + val = (unsigned int)(inw(0xAC1E)) & 0xFFl; + return (val << 19); +} +#endif int gx_line_delta(int xres, int bpp) { @@ -81,6 +97,7 @@ static void gx_set_mode(struct fb_info *info) writel(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2, par->dc_regs + DC_LINE_SIZE); + /* Enable graphics and video data and unmask address lines. */ dcfg |= DC_DCFG_GDEN | DC_DCFG_VDEN | DC_DCFG_A20M | DC_DCFG_A18M; diff --git a/drivers/video/geode/display_gx.h b/drivers/video/geode/display_gx.h index 86c62336130..0af33f329e8 100644 --- a/drivers/video/geode/display_gx.h +++ b/drivers/video/geode/display_gx.h @@ -11,11 +11,15 @@ #ifndef __DISPLAY_GX_H__ #define __DISPLAY_GX_H__ -int gx_frame_buffer_size(void); +unsigned int gx_frame_buffer_size(void); int gx_line_delta(int xres, int bpp); extern struct geode_dc_ops gx_dc_ops; +/* MSR that tells us if a TFT or CRT is attached */ +#define GLD_MSR_CONFIG 0xC0002001 +#define GLD_MSR_CONFIG_DM_FP 0x40 + /* Display controller registers */ #define DC_UNLOCK 0x00 @@ -93,4 +97,5 @@ extern struct geode_dc_ops gx_dc_ops; #define DC_PAL_ADDRESS 0x70 #define DC_PAL_DATA 0x74 +#define DC_GLIU0_MEM_OFFSET 0x84 #endif /* !__DISPLAY_GX1_H__ */ diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/geode/gxfb_core.c index a454dcb8e21..cf841efa229 100644 --- a/drivers/video/geode/gxfb_core.c +++ b/drivers/video/geode/gxfb_core.c @@ -35,10 +35,10 @@ #include "display_gx.h" #include "video_gx.h" -static char mode_option[32] = "640x480-16@60"; +static char *mode_option; /* Modes relevant to the GX (taken from modedb.c) */ -static const struct fb_videomode __initdata gx_modedb[] = { +static const struct fb_videomode gx_modedb[] __initdata = { /* 640x480-60 VESA */ { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2, 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, @@ -240,6 +240,12 @@ static int __init gxfb_map_video_memory(struct fb_info *info, struct pci_dev *de if (!info->screen_base) return -ENOMEM; + /* Set the 16MB aligned base address of the graphics memory region + * in the display controller */ + + writel(info->fix.smem_start & 0xFF000000, + par->dc_regs + DC_GLIU0_MEM_OFFSET); + dev_info(&dev->dev, "%d Kibyte of video memory at 0x%lx\n", info->fix.smem_len / 1024, info->fix.smem_start); @@ -302,6 +308,7 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i struct geodefb_par *par; struct fb_info *info; int ret; + unsigned long val; info = gxfb_init_fbinfo(&pdev->dev); if (!info) @@ -317,6 +324,15 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i goto err; } + /* Figure out if this is a TFT or CRT part */ + + rdmsrl(GLD_MSR_CONFIG, val); + + if ((val & GLD_MSR_CONFIG_DM_FP) == GLD_MSR_CONFIG_DM_FP) + par->enable_crt = 0; + else + par->enable_crt = 1; + ret = fb_find_mode(&info->var, info, mode_option, gx_modedb, ARRAY_SIZE(gx_modedb), NULL, 16); if (ret == 0 || ret == 4) { @@ -325,7 +341,8 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i goto err; } - /* Clear the frame buffer of garbage. */ + + /* Clear the frame buffer of garbage. */ memset_io(info->screen_base, 0, info->fix.smem_len); gxfb_check_var(&info->var, info); @@ -395,11 +412,35 @@ static struct pci_driver gxfb_driver = { .remove = gxfb_remove, }; +#ifndef MODULE +static int __init gxfb_setup(char *options) +{ + + char *opt; + + if (!options || !*options) + return 0; + + while ((opt = strsep(&options, ",")) != NULL) { + if (!*opt) + continue; + + mode_option = opt; + } + + return 0; +} +#endif + static int __init gxfb_init(void) { #ifndef MODULE - if (fb_get_options("gxfb", NULL)) + char *option = NULL; + + if (fb_get_options("gxfb", &option)) return -ENODEV; + + gxfb_setup(option); #endif return pci_register_driver(&gxfb_driver); } @@ -412,8 +453,8 @@ static void __exit gxfb_cleanup(void) module_init(gxfb_init); module_exit(gxfb_cleanup); -module_param_string(mode, mode_option, sizeof(mode_option), 0444); -MODULE_PARM_DESC(mode, "video mode (<x>x<y>[-<bpp>][@<refr>])"); +module_param(mode_option, charp, 0); +MODULE_PARM_DESC(mode_option, "video mode (<x>x<y>[-<bpp>][@<refr>])"); MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode GX"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/geode/video_gx.c b/drivers/video/geode/video_gx.c index 2b2a7880ea7..7f3f18d0671 100644 --- a/drivers/video/geode/video_gx.c +++ b/drivers/video/geode/video_gx.c @@ -175,13 +175,88 @@ static void gx_set_dclk_frequency(struct fb_info *info) } while (timeout-- && !(dotpll & MSR_GLCP_DOTPLL_LOCK)); } +static void +gx_configure_tft(struct fb_info *info) +{ + struct geodefb_par *par = info->par; + unsigned long val; + unsigned long fp; + + /* Set up the DF pad select MSR */ + + rdmsrl(GX_VP_MSR_PAD_SELECT, val); + val &= ~GX_VP_PAD_SELECT_MASK; + val |= GX_VP_PAD_SELECT_TFT; + wrmsrl(GX_VP_MSR_PAD_SELECT, val); + + /* Turn off the panel */ + + fp = readl(par->vid_regs + GX_FP_PM); + fp &= ~GX_FP_PM_P; + writel(fp, par->vid_regs + GX_FP_PM); + + /* Set timing 1 */ + + fp = readl(par->vid_regs + GX_FP_PT1); + fp &= GX_FP_PT1_VSIZE_MASK; + fp |= info->var.yres << GX_FP_PT1_VSIZE_SHIFT; + writel(fp, par->vid_regs + GX_FP_PT1); + + /* Timing 2 */ + /* Set bits that are always on for TFT */ + + fp = 0x0F100000; + + /* Add sync polarity */ + + if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT)) + fp |= GX_FP_PT2_VSP; + + if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT)) + fp |= GX_FP_PT2_HSP; + + writel(fp, par->vid_regs + GX_FP_PT2); + + /* Set the dither control */ + writel(0x70, par->vid_regs + GX_FP_DFC); + + /* Enable the FP data and power (in case the BIOS didn't) */ + + fp = readl(par->vid_regs + GX_DCFG); + fp |= GX_DCFG_FP_PWR_EN | GX_DCFG_FP_DATA_EN; + writel(fp, par->vid_regs + GX_DCFG); + + /* Unblank the panel */ + + fp = readl(par->vid_regs + GX_FP_PM); + fp |= GX_FP_PM_P; + writel(fp, par->vid_regs + GX_FP_PM); +} + static void gx_configure_display(struct fb_info *info) { struct geodefb_par *par = info->par; - u32 dcfg, fp_pm; + u32 dcfg, misc; + + /* Set up the MISC register */ + + misc = readl(par->vid_regs + GX_MISC); + + /* Power up the DAC */ + misc &= ~(GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN); + + /* Disable gamma correction */ + misc |= GX_MISC_GAM_EN; + + writel(misc, par->vid_regs + GX_MISC); + /* Write the display configuration */ dcfg = readl(par->vid_regs + GX_DCFG); + /* Disable hsync and vsync */ + dcfg &= ~(GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN); + writel(dcfg, par->vid_regs + GX_DCFG); + /* Clear bits from existing mode. */ dcfg &= ~(GX_DCFG_CRT_SYNC_SKW_MASK | GX_DCFG_CRT_HSYNC_POL | GX_DCFG_CRT_VSYNC_POL @@ -199,12 +274,19 @@ static void gx_configure_display(struct fb_info *info) if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) dcfg |= GX_DCFG_CRT_VSYNC_POL; + /* Enable the display logic */ + /* Set up the DACS to blank normally */ + + dcfg |= GX_DCFG_CRT_EN | GX_DCFG_DAC_BL_EN; + + /* Enable the external DAC VREF? */ + writel(dcfg, par->vid_regs + GX_DCFG); - /* Power on flat panel. */ - fp_pm = readl(par->vid_regs + GX_FP_PM); - fp_pm |= GX_FP_PM_P; - writel(fp_pm, par->vid_regs + GX_FP_PM); + /* Set up the flat panel (if it is enabled) */ + + if (par->enable_crt == 0) + gx_configure_tft(info); } static int gx_blank_display(struct fb_info *info, int blank_mode) @@ -245,12 +327,15 @@ static int gx_blank_display(struct fb_info *info, int blank_mode) writel(dcfg, par->vid_regs + GX_DCFG); /* Power on/off flat panel. */ - fp_pm = readl(par->vid_regs + GX_FP_PM); - if (blank_mode == FB_BLANK_POWERDOWN) - fp_pm &= ~GX_FP_PM_P; - else - fp_pm |= GX_FP_PM_P; - writel(fp_pm, par->vid_regs + GX_FP_PM); + + if (par->enable_crt == 0) { + fp_pm = readl(par->vid_regs + GX_FP_PM); + if (blank_mode == FB_BLANK_POWERDOWN) + fp_pm &= ~GX_FP_PM_P; + else + fp_pm |= GX_FP_PM_P; + writel(fp_pm, par->vid_regs + GX_FP_PM); + } return 0; } diff --git a/drivers/video/geode/video_gx.h b/drivers/video/geode/video_gx.h index 2d9211f3ed8..ce28d8f382d 100644 --- a/drivers/video/geode/video_gx.h +++ b/drivers/video/geode/video_gx.h @@ -13,6 +13,11 @@ extern struct geode_vid_ops gx_vid_ops; +/* GX Flatpanel control MSR */ +#define GX_VP_MSR_PAD_SELECT 0xC0002011 +#define GX_VP_PAD_SELECT_MASK 0x3FFFFFFF +#define GX_VP_PAD_SELECT_TFT 0x1FFFFFFF + /* Geode GX video processor registers */ #define GX_DCFG 0x0008 @@ -20,6 +25,8 @@ extern struct geode_vid_ops gx_vid_ops; # define GX_DCFG_HSYNC_EN 0x00000002 # define GX_DCFG_VSYNC_EN 0x00000004 # define GX_DCFG_DAC_BL_EN 0x00000008 +# define GX_DCFG_FP_PWR_EN 0x00000040 +# define GX_DCFG_FP_DATA_EN 0x00000080 # define GX_DCFG_CRT_HSYNC_POL 0x00000100 # define GX_DCFG_CRT_VSYNC_POL 0x00000200 # define GX_DCFG_CRT_SYNC_SKW_MASK 0x0001C000 @@ -28,10 +35,28 @@ extern struct geode_vid_ops gx_vid_ops; # define GX_DCFG_GV_GAM 0x00200000 # define GX_DCFG_DAC_VREF 0x04000000 +/* Geode GX MISC video configuration */ + +#define GX_MISC 0x50 +#define GX_MISC_GAM_EN 0x00000001 +#define GX_MISC_DAC_PWRDN 0x00000400 +#define GX_MISC_A_PWRDN 0x00000800 + /* Geode GX flat panel display control registers */ + +#define GX_FP_PT1 0x0400 +#define GX_FP_PT1_VSIZE_MASK 0x7FF0000 +#define GX_FP_PT1_VSIZE_SHIFT 16 + +#define GX_FP_PT2 0x408 +#define GX_FP_PT2_VSP (1 << 23) +#define GX_FP_PT2_HSP (1 << 22) + #define GX_FP_PM 0x410 # define GX_FP_PM_P 0x01000000 +#define GX_FP_DFC 0x418 + /* Geode GX clock control MSRs */ #define MSR_GLCP_SYS_RSTPLL 0x4c000014 diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c index 91cf3b577d1..9ab9b839a0f 100644 --- a/drivers/video/hpfb.c +++ b/drivers/video/hpfb.c @@ -295,6 +295,8 @@ static int __init hpfb_init_one(unsigned long phys_base, unsigned long virt_base if (register_framebuffer(&fb_info) < 0) { fb_dealloc_cmap(&fb_info.cmap); + iounmap(fb_info.screen_base); + fb_info.screen_base = NULL; return 1; } diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c index b38d805db31..b952e4504ab 100644 --- a/drivers/video/i810/i810-i2c.c +++ b/drivers/video/i810/i810-i2c.c @@ -162,9 +162,7 @@ int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn) if (e != NULL) { DPRINTK("i810-i2c: Getting EDID from BIOS\n"); - edid = kmalloc(EDID_LENGTH, GFP_KERNEL); - if (edid) - memcpy(edid, e, EDID_LENGTH); + edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL); } } diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c index e6df492c22a..655ae0fa99c 100644 --- a/drivers/video/igafb.c +++ b/drivers/video/igafb.c @@ -384,19 +384,21 @@ int __init igafb_init(void) if (!con_is_present()) return -ENXIO; - pdev = pci_find_device(PCI_VENDOR_ID_INTERG, + pdev = pci_get_device(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682, 0); if (pdev == NULL) { /* * XXX We tried to use cyber2000fb.c for IGS 2000. * But it does not initialize the chip in JavaStation-E, alas. */ - pdev = pci_find_device(PCI_VENDOR_ID_INTERG, 0x2000, 0); + pdev = pci_get_device(PCI_VENDOR_ID_INTERG, 0x2000, 0); if(pdev == NULL) { return -ENXIO; } iga2000 = 1; } + /* We leak a reference here but as it cannot be unloaded this is + fine. If you write unload code remember to free it in unload */ size = sizeof(struct fb_info) + sizeof(struct iga_par) + sizeof(u32)*16; diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c index 6f9de04193d..664fc5cf962 100644 --- a/drivers/video/intelfb/intelfbdrv.c +++ b/drivers/video/intelfb/intelfbdrv.c @@ -1058,10 +1058,9 @@ intelfb_init_var(struct intelfb_info *dinfo) u8 *edid_d = NULL; if (edid_s) { - edid_d = kmalloc(EDID_LENGTH, GFP_KERNEL); + edid_d = kmemdup(edid_s, EDID_LENGTH, GFP_KERNEL); if (edid_d) { - memcpy(edid_d, edid_s, EDID_LENGTH); fb_edid_to_monspecs(edid_d, &dinfo->info->monspecs); kfree(edid_d); diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c index 80a04380716..180d94c2b4d 100644 --- a/drivers/video/macfb.c +++ b/drivers/video/macfb.c @@ -608,6 +608,22 @@ void __init macfb_setup(char *options) } } +static void __init iounmap_macfb(void) +{ + if (valkyrie_cmap_regs) + iounmap(valkyrie_cmap_regs); + if (dafb_cmap_regs) + iounmap(dafb_cmap_regs); + if (v8_brazil_cmap_regs) + iounmap(v8_brazil_cmap_regs); + if (rbv_cmap_regs) + iounmap(rbv_cmap_regs); + if (civic_cmap_regs) + iounmap(civic_cmap_regs); + if (csc_cmap_regs) + iounmap(csc_cmap_regs); +} + static int __init macfb_init(void) { int video_cmap_len, video_is_nubus = 0; @@ -962,6 +978,10 @@ static int __init macfb_init(void) if (!err) printk("fb%d: %s frame buffer device\n", fb_info.node, fb_info.fix.id); + else { + iounmap(fb_info.screen_base); + iounmap_macfb(); + } return err; } diff --git a/drivers/video/mbx/mbxdebugfs.c b/drivers/video/mbx/mbxdebugfs.c index 84aab3ad024..472a3ca3d92 100644 --- a/drivers/video/mbx/mbxdebugfs.c +++ b/drivers/video/mbx/mbxdebugfs.c @@ -10,6 +10,8 @@ struct mbxfb_debugfs_data { struct dentry *clock; struct dentry *display; struct dentry *gsctl; + struct dentry *sdram; + struct dentry *misc; }; static int open_file_generic(struct inode *inode, struct file *file) @@ -29,11 +31,11 @@ static ssize_t sysconf_read_file(struct file *file, char __user *userbuf, { char * s = big_buffer; - s += sprintf(s, "SYSCFG = %08lx\n", SYSCFG); - s += sprintf(s, "PFBASE = %08lx\n", PFBASE); - s += sprintf(s, "PFCEIL = %08lx\n", PFCEIL); - s += sprintf(s, "POLLFLAG = %08lx\n", POLLFLAG); - s += sprintf(s, "SYSRST = %08lx\n", SYSRST); + s += sprintf(s, "SYSCFG = %08x\n", readl(SYSCFG)); + s += sprintf(s, "PFBASE = %08x\n", readl(PFBASE)); + s += sprintf(s, "PFCEIL = %08x\n", readl(PFCEIL)); + s += sprintf(s, "POLLFLAG = %08x\n", readl(POLLFLAG)); + s += sprintf(s, "SYSRST = %08x\n", readl(SYSRST)); return simple_read_from_buffer(userbuf, count, ppos, big_buffer, s-big_buffer); @@ -45,24 +47,24 @@ static ssize_t gsctl_read_file(struct file *file, char __user *userbuf, { char * s = big_buffer; - s += sprintf(s, "GSCTRL = %08lx\n", GSCTRL); - s += sprintf(s, "VSCTRL = %08lx\n", VSCTRL); - s += sprintf(s, "GBBASE = %08lx\n", GBBASE); - s += sprintf(s, "VBBASE = %08lx\n", VBBASE); - s += sprintf(s, "GDRCTRL = %08lx\n", GDRCTRL); - s += sprintf(s, "VCMSK = %08lx\n", VCMSK); - s += sprintf(s, "GSCADR = %08lx\n", GSCADR); - s += sprintf(s, "VSCADR = %08lx\n", VSCADR); - s += sprintf(s, "VUBASE = %08lx\n", VUBASE); - s += sprintf(s, "VVBASE = %08lx\n", VVBASE); - s += sprintf(s, "GSADR = %08lx\n", GSADR); - s += sprintf(s, "VSADR = %08lx\n", VSADR); - s += sprintf(s, "HCCTRL = %08lx\n", HCCTRL); - s += sprintf(s, "HCSIZE = %08lx\n", HCSIZE); - s += sprintf(s, "HCPOS = %08lx\n", HCPOS); - s += sprintf(s, "HCBADR = %08lx\n", HCBADR); - s += sprintf(s, "HCCKMSK = %08lx\n", HCCKMSK); - s += sprintf(s, "GPLUT = %08lx\n", GPLUT); + s += sprintf(s, "GSCTRL = %08x\n", readl(GSCTRL)); + s += sprintf(s, "VSCTRL = %08x\n", readl(VSCTRL)); + s += sprintf(s, "GBBASE = %08x\n", readl(GBBASE)); + s += sprintf(s, "VBBASE = %08x\n", readl(VBBASE)); + s += sprintf(s, "GDRCTRL = %08x\n", readl(GDRCTRL)); + s += sprintf(s, "VCMSK = %08x\n", readl(VCMSK)); + s += sprintf(s, "GSCADR = %08x\n", readl(GSCADR)); + s += sprintf(s, "VSCADR = %08x\n", readl(VSCADR)); + s += sprintf(s, "VUBASE = %08x\n", readl(VUBASE)); + s += sprintf(s, "VVBASE = %08x\n", readl(VVBASE)); + s += sprintf(s, "GSADR = %08x\n", readl(GSADR)); + s += sprintf(s, "VSADR = %08x\n", readl(VSADR)); + s += sprintf(s, "HCCTRL = %08x\n", readl(HCCTRL)); + s += sprintf(s, "HCSIZE = %08x\n", readl(HCSIZE)); + s += sprintf(s, "HCPOS = %08x\n", readl(HCPOS)); + s += sprintf(s, "HCBADR = %08x\n", readl(HCBADR)); + s += sprintf(s, "HCCKMSK = %08x\n", readl(HCCKMSK)); + s += sprintf(s, "GPLUT = %08x\n", readl(GPLUT)); return simple_read_from_buffer(userbuf, count, ppos, big_buffer, s-big_buffer); @@ -73,36 +75,36 @@ static ssize_t display_read_file(struct file *file, char __user *userbuf, { char * s = big_buffer; - s += sprintf(s, "DSCTRL = %08lx\n", DSCTRL); - s += sprintf(s, "DHT01 = %08lx\n", DHT01); - s += sprintf(s, "DHT02 = %08lx\n", DHT02); - s += sprintf(s, "DHT03 = %08lx\n", DHT03); - s += sprintf(s, "DVT01 = %08lx\n", DVT01); - s += sprintf(s, "DVT02 = %08lx\n", DVT02); - s += sprintf(s, "DVT03 = %08lx\n", DVT03); - s += sprintf(s, "DBCOL = %08lx\n", DBCOL); - s += sprintf(s, "BGCOLOR = %08lx\n", BGCOLOR); - s += sprintf(s, "DINTRS = %08lx\n", DINTRS); - s += sprintf(s, "DINTRE = %08lx\n", DINTRE); - s += sprintf(s, "DINTRCNT = %08lx\n", DINTRCNT); - s += sprintf(s, "DSIG = %08lx\n", DSIG); - s += sprintf(s, "DMCTRL = %08lx\n", DMCTRL); - s += sprintf(s, "CLIPCTRL = %08lx\n", CLIPCTRL); - s += sprintf(s, "SPOCTRL = %08lx\n", SPOCTRL); - s += sprintf(s, "SVCTRL = %08lx\n", SVCTRL); - s += sprintf(s, "DLSTS = %08lx\n", DLSTS); - s += sprintf(s, "DLLCTRL = %08lx\n", DLLCTRL); - s += sprintf(s, "DVLNUM = %08lx\n", DVLNUM); - s += sprintf(s, "DUCTRL = %08lx\n", DUCTRL); - s += sprintf(s, "DVECTRL = %08lx\n", DVECTRL); - s += sprintf(s, "DHDET = %08lx\n", DHDET); - s += sprintf(s, "DVDET = %08lx\n", DVDET); - s += sprintf(s, "DODMSK = %08lx\n", DODMSK); - s += sprintf(s, "CSC01 = %08lx\n", CSC01); - s += sprintf(s, "CSC02 = %08lx\n", CSC02); - s += sprintf(s, "CSC03 = %08lx\n", CSC03); - s += sprintf(s, "CSC04 = %08lx\n", CSC04); - s += sprintf(s, "CSC05 = %08lx\n", CSC05); + s += sprintf(s, "DSCTRL = %08x\n", readl(DSCTRL)); + s += sprintf(s, "DHT01 = %08x\n", readl(DHT01)); + s += sprintf(s, "DHT02 = %08x\n", readl(DHT02)); + s += sprintf(s, "DHT03 = %08x\n", readl(DHT03)); + s += sprintf(s, "DVT01 = %08x\n", readl(DVT01)); + s += sprintf(s, "DVT02 = %08x\n", readl(DVT02)); + s += sprintf(s, "DVT03 = %08x\n", readl(DVT03)); + s += sprintf(s, "DBCOL = %08x\n", readl(DBCOL)); + s += sprintf(s, "BGCOLOR = %08x\n", readl(BGCOLOR)); + s += sprintf(s, "DINTRS = %08x\n", readl(DINTRS)); + s += sprintf(s, "DINTRE = %08x\n", readl(DINTRE)); + s += sprintf(s, "DINTRCNT = %08x\n", readl(DINTRCNT)); + s += sprintf(s, "DSIG = %08x\n", readl(DSIG)); + s += sprintf(s, "DMCTRL = %08x\n", readl(DMCTRL)); + s += sprintf(s, "CLIPCTRL = %08x\n", readl(CLIPCTRL)); + s += sprintf(s, "SPOCTRL = %08x\n", readl(SPOCTRL)); + s += sprintf(s, "SVCTRL = %08x\n", readl(SVCTRL)); + s += sprintf(s, "DLSTS = %08x\n", readl(DLSTS)); + s += sprintf(s, "DLLCTRL = %08x\n", readl(DLLCTRL)); + s += sprintf(s, "DVLNUM = %08x\n", readl(DVLNUM)); + s += sprintf(s, "DUCTRL = %08x\n", readl(DUCTRL)); + s += sprintf(s, "DVECTRL = %08x\n", readl(DVECTRL)); + s += sprintf(s, "DHDET = %08x\n", readl(DHDET)); + s += sprintf(s, "DVDET = %08x\n", readl(DVDET)); + s += sprintf(s, "DODMSK = %08x\n", readl(DODMSK)); + s += sprintf(s, "CSC01 = %08x\n", readl(CSC01)); + s += sprintf(s, "CSC02 = %08x\n", readl(CSC02)); + s += sprintf(s, "CSC03 = %08x\n", readl(CSC03)); + s += sprintf(s, "CSC04 = %08x\n", readl(CSC04)); + s += sprintf(s, "CSC05 = %08x\n", readl(CSC05)); return simple_read_from_buffer(userbuf, count, ppos, big_buffer, s-big_buffer); @@ -113,24 +115,61 @@ static ssize_t clock_read_file(struct file *file, char __user *userbuf, { char * s = big_buffer; - s += sprintf(s, "SYSCLKSRC = %08lx\n", SYSCLKSRC); - s += sprintf(s, "PIXCLKSRC = %08lx\n", PIXCLKSRC); - s += sprintf(s, "CLKSLEEP = %08lx\n", CLKSLEEP); - s += sprintf(s, "COREPLL = %08lx\n", COREPLL); - s += sprintf(s, "DISPPLL = %08lx\n", DISPPLL); - s += sprintf(s, "PLLSTAT = %08lx\n", PLLSTAT); - s += sprintf(s, "VOVRCLK = %08lx\n", VOVRCLK); - s += sprintf(s, "PIXCLK = %08lx\n", PIXCLK); - s += sprintf(s, "MEMCLK = %08lx\n", MEMCLK); - s += sprintf(s, "M24CLK = %08lx\n", M24CLK); - s += sprintf(s, "MBXCLK = %08lx\n", MBXCLK); - s += sprintf(s, "SDCLK = %08lx\n", SDCLK); - s += sprintf(s, "PIXCLKDIV = %08lx\n", PIXCLKDIV); + s += sprintf(s, "SYSCLKSRC = %08x\n", readl(SYSCLKSRC)); + s += sprintf(s, "PIXCLKSRC = %08x\n", readl(PIXCLKSRC)); + s += sprintf(s, "CLKSLEEP = %08x\n", readl(CLKSLEEP)); + s += sprintf(s, "COREPLL = %08x\n", readl(COREPLL)); + s += sprintf(s, "DISPPLL = %08x\n", readl(DISPPLL)); + s += sprintf(s, "PLLSTAT = %08x\n", readl(PLLSTAT)); + s += sprintf(s, "VOVRCLK = %08x\n", readl(VOVRCLK)); + s += sprintf(s, "PIXCLK = %08x\n", readl(PIXCLK)); + s += sprintf(s, "MEMCLK = %08x\n", readl(MEMCLK)); + s += sprintf(s, "M24CLK = %08x\n", readl(M24CLK)); + s += sprintf(s, "MBXCLK = %08x\n", readl(MBXCLK)); + s += sprintf(s, "SDCLK = %08x\n", readl(SDCLK)); + s += sprintf(s, "PIXCLKDIV = %08x\n", readl(PIXCLKDIV)); return simple_read_from_buffer(userbuf, count, ppos, big_buffer, s-big_buffer); } +static ssize_t sdram_read_file(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + char * s = big_buffer; + + s += sprintf(s, "LMRST = %08x\n", readl(LMRST)); + s += sprintf(s, "LMCFG = %08x\n", readl(LMCFG)); + s += sprintf(s, "LMPWR = %08x\n", readl(LMPWR)); + s += sprintf(s, "LMPWRSTAT = %08x\n", readl(LMPWRSTAT)); + s += sprintf(s, "LMCEMR = %08x\n", readl(LMCEMR)); + s += sprintf(s, "LMTYPE = %08x\n", readl(LMTYPE)); + s += sprintf(s, "LMTIM = %08x\n", readl(LMTIM)); + s += sprintf(s, "LMREFRESH = %08x\n", readl(LMREFRESH)); + s += sprintf(s, "LMPROTMIN = %08x\n", readl(LMPROTMIN)); + s += sprintf(s, "LMPROTMAX = %08x\n", readl(LMPROTMAX)); + s += sprintf(s, "LMPROTCFG = %08x\n", readl(LMPROTCFG)); + s += sprintf(s, "LMPROTERR = %08x\n", readl(LMPROTERR)); + + return simple_read_from_buffer(userbuf, count, ppos, + big_buffer, s-big_buffer); +} + +static ssize_t misc_read_file(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + char * s = big_buffer; + + s += sprintf(s, "LCD_CONFIG = %08x\n", readl(LCD_CONFIG)); + s += sprintf(s, "ODFBPWR = %08x\n", readl(ODFBPWR)); + s += sprintf(s, "ODFBSTAT = %08x\n", readl(ODFBSTAT)); + s += sprintf(s, "ID = %08x\n", readl(ID)); + + return simple_read_from_buffer(userbuf, count, ppos, + big_buffer, s-big_buffer); +} + + static struct file_operations sysconf_fops = { .read = sysconf_read_file, .write = write_file_dummy, @@ -155,6 +194,17 @@ static struct file_operations gsctl_fops = { .open = open_file_generic, }; +static struct file_operations sdram_fops = { + .read = sdram_read_file, + .write = write_file_dummy, + .open = open_file_generic, +}; + +static struct file_operations misc_fops = { + .read = misc_read_file, + .write = write_file_dummy, + .open = open_file_generic, +}; static void __devinit mbxfb_debugfs_init(struct fb_info *fbi) { @@ -173,6 +223,10 @@ static void __devinit mbxfb_debugfs_init(struct fb_info *fbi) fbi, &display_fops); dbg->gsctl = debugfs_create_file("gsctl", 0444, dbg->dir, fbi, &gsctl_fops); + dbg->sdram = debugfs_create_file("sdram", 0444, dbg->dir, + fbi, &sdram_fops); + dbg->misc = debugfs_create_file("misc", 0444, dbg->dir, + fbi, &misc_fops); } static void __devexit mbxfb_debugfs_remove(struct fb_info *fbi) @@ -180,6 +234,8 @@ static void __devexit mbxfb_debugfs_remove(struct fb_info *fbi) struct mbxfb_info *mfbi = fbi->par; struct mbxfb_debugfs_data *dbg = mfbi->debugfs_data; + debugfs_remove(dbg->misc); + debugfs_remove(dbg->sdram); debugfs_remove(dbg->gsctl); debugfs_remove(dbg->display); debugfs_remove(dbg->clock); diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c index a32d1af79e0..980d5f62390 100644 --- a/drivers/video/mbx/mbxfb.c +++ b/drivers/video/mbx/mbxfb.c @@ -1,8 +1,14 @@ /* * linux/drivers/video/mbx/mbxfb.c * + * Copyright (C) 2006 8D Technologies inc + * Raphael Assenat <raph@8d.com> + * - Added video overlay support + * - Various improvements + * * Copyright (C) 2006 Compulab, Ltd. * Mike Rapoport <mike@compulab.co.il> + * - Creation of driver * * Based on pxafb.c * @@ -19,6 +25,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/uaccess.h> #include <asm/io.h> @@ -29,6 +36,14 @@ static unsigned long virt_base_2700; +#define write_reg(val, reg) do { writel((val), (reg)); } while(0) + +/* Without this delay, the graphics appears somehow scaled and + * there is a lot of jitter in scanlines. This delay is probably + * needed only after setting some specific register(s) somewhere, + * not all over the place... */ +#define write_reg_dly(val, reg) do { writel((val), reg); udelay(1000); } while(0) + #define MIN_XRES 16 #define MIN_YRES 16 #define MAX_XRES 2048 @@ -257,19 +272,17 @@ static int mbxfb_set_par(struct fb_info *info) gsctrl &= ~(FMsk(GSCTRL_GSWIDTH) | FMsk(GSCTRL_GSHEIGHT)); gsctrl |= Gsctrl_Width(info->var.xres) | Gsctrl_Height(info->var.yres); - writel(gsctrl, GSCTRL); - udelay(1000); + write_reg_dly(gsctrl, GSCTRL); gsadr &= ~(FMsk(GSADR_SRCSTRIDE)); gsadr |= Gsadr_Srcstride(info->var.xres * info->var.bits_per_pixel / (8 * 16) - 1); - writel(gsadr, GSADR); - udelay(1000); + write_reg_dly(gsadr, GSADR); /* setup timings */ var->pixclock = mbxfb_get_pixclock(info->var.pixclock, &div); - writel((Disp_Pll_M(div.m) | Disp_Pll_N(div.n) | + write_reg_dly((Disp_Pll_M(div.m) | Disp_Pll_N(div.n) | Disp_Pll_P(div.p) | DISP_PLL_EN), DISPPLL); hbps = var->hsync_len; @@ -282,18 +295,20 @@ static int mbxfb_set_par(struct fb_info *info) vfps = vas + var->yres; vt = vfps + var->lower_margin; - writel((Dht01_Hbps(hbps) | Dht01_Ht(ht)), DHT01); - writel((Dht02_Hlbs(has) | Dht02_Has(has)), DHT02); - writel((Dht03_Hfps(hfps) | Dht03_Hrbs(hfps)), DHT03); - writel((Dhdet_Hdes(has) | Dhdet_Hdef(hfps)), DHDET); + write_reg_dly((Dht01_Hbps(hbps) | Dht01_Ht(ht)), DHT01); + write_reg_dly((Dht02_Hlbs(has) | Dht02_Has(has)), DHT02); + write_reg_dly((Dht03_Hfps(hfps) | Dht03_Hrbs(hfps)), DHT03); + write_reg_dly((Dhdet_Hdes(has) | Dhdet_Hdef(hfps)), DHDET); - writel((Dvt01_Vbps(vbps) | Dvt01_Vt(vt)), DVT01); - writel((Dvt02_Vtbs(vas) | Dvt02_Vas(vas)), DVT02); - writel((Dvt03_Vfps(vfps) | Dvt03_Vbbs(vfps)), DVT03); - writel((Dvdet_Vdes(vas) | Dvdet_Vdef(vfps)), DVDET); - writel((Dvectrl_Vevent(vfps) | Dvectrl_Vfetch(vbps)), DVECTRL); + write_reg_dly((Dvt01_Vbps(vbps) | Dvt01_Vt(vt)), DVT01); + write_reg_dly((Dvt02_Vtbs(vas) | Dvt02_Vas(vas)), DVT02); + write_reg_dly((Dvt03_Vfps(vfps) | Dvt03_Vbbs(vfps)), DVT03); + write_reg_dly((Dvdet_Vdes(vas) | Dvdet_Vdef(vfps)), DVDET); + write_reg_dly((Dvectrl_Vevent(vfps) | Dvectrl_Vfetch(vbps)), DVECTRL); - writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); + write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); + + write_reg_dly(DINTRE_VEVENT0_EN, DINTRE); return 0; } @@ -305,23 +320,203 @@ static int mbxfb_blank(int blank, struct fb_info *info) case FB_BLANK_VSYNC_SUSPEND: case FB_BLANK_HSYNC_SUSPEND: case FB_BLANK_NORMAL: - writel((readl(DSCTRL) & ~DSCTRL_SYNCGEN_EN), DSCTRL); - udelay(1000); - writel((readl(PIXCLK) & ~PIXCLK_EN), PIXCLK); - udelay(1000); - writel((readl(VOVRCLK) & ~VOVRCLK_EN), VOVRCLK); - udelay(1000); + write_reg_dly((readl(DSCTRL) & ~DSCTRL_SYNCGEN_EN), DSCTRL); + write_reg_dly((readl(PIXCLK) & ~PIXCLK_EN), PIXCLK); + write_reg_dly((readl(VOVRCLK) & ~VOVRCLK_EN), VOVRCLK); break; case FB_BLANK_UNBLANK: - writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); - udelay(1000); - writel((readl(PIXCLK) | PIXCLK_EN), PIXCLK); - udelay(1000); + write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); + write_reg_dly((readl(PIXCLK) | PIXCLK_EN), PIXCLK); break; } return 0; } +static int mbxfb_setupOverlay(struct mbxfb_overlaySetup *set) +{ + u32 vsctrl, vbbase, vscadr, vsadr; + u32 sssize, spoctrl, svctrl, shctrl; + u32 vubase, vvbase; + u32 vovrclk; + + if (set->scaled_width==0 || set->scaled_height==0) + return -EINVAL; + + /* read registers which have reserved bits + * so we can write them back as-is. */ + vovrclk = readl(VOVRCLK); + vsctrl = readl(VSCTRL); + vscadr = readl(VSCADR); + vubase = readl(VUBASE); + vvbase = readl(VVBASE); + + spoctrl = readl(SPOCTRL); + sssize = readl(SSSIZE); + + + vbbase = Vbbase_Glalpha(set->alpha); + + vsctrl &= ~( FMsk(VSCTRL_VSWIDTH) | + FMsk(VSCTRL_VSHEIGHT) | + FMsk(VSCTRL_VPIXFMT) | + VSCTRL_GAMMA_EN | VSCTRL_CSC_EN | + VSCTRL_COSITED ); + vsctrl |= Vsctrl_Width(set->width) | Vsctrl_Height(set->height) | + VSCTRL_CSC_EN; + + vscadr &= ~(VSCADR_STR_EN | VSCADR_COLKEY_EN | VSCADR_COLKEYSRC | + FMsk(VSCADR_BLEND_M) | FMsk(VSCADR_BLEND_POS) | + FMsk(VSCADR_VBASE_ADR) ); + vubase &= ~(VUBASE_UVHALFSTR | FMsk(VUBASE_UBASE_ADR)); + vvbase &= ~(FMsk(VVBASE_VBASE_ADR)); + + switch (set->fmt) + { + case MBXFB_FMT_YUV12: + vsctrl |= VSCTRL_VPIXFMT_YUV12; + + set->Y_stride = ((set->width) + 0xf ) & ~0xf; + + break; + case MBXFB_FMT_UY0VY1: + vsctrl |= VSCTRL_VPIXFMT_UY0VY1; + set->Y_stride = (set->width*2 + 0xf ) & ~0xf; + break; + case MBXFB_FMT_VY0UY1: + vsctrl |= VSCTRL_VPIXFMT_VY0UY1; + set->Y_stride = (set->width*2 + 0xf ) & ~0xf; + break; + case MBXFB_FMT_Y0UY1V: + vsctrl |= VSCTRL_VPIXFMT_Y0UY1V; + set->Y_stride = (set->width*2 + 0xf ) & ~0xf; + break; + case MBXFB_FMT_Y0VY1U: + vsctrl |= VSCTRL_VPIXFMT_Y0VY1U; + set->Y_stride = (set->width*2 + 0xf ) & ~0xf; + break; + default: + return -EINVAL; + } + + /* VSCTRL has the bits which sets the Video Pixel Format. + * When passing from a packed to planar format, + * if we write VSCTRL first, VVBASE and VUBASE would + * be zero if we would not set them here. (And then, + * the chips hangs and only a reset seems to fix it). + * + * If course, the values calculated here have no meaning + * for packed formats. + */ + set->UV_stride = ((set->width/2) + 0x7 ) & ~0x7; + set->U_offset = set->height * set->Y_stride; + set->V_offset = set->U_offset + + set->height * set->UV_stride; + vubase |= Vubase_Ubase_Adr( + (0x60000 + set->mem_offset + set->U_offset)>>3); + vvbase |= Vvbase_Vbase_Adr( + (0x60000 + set->mem_offset + set->V_offset)>>3); + + + vscadr |= VSCADR_BLEND_VID | VSCADR_BLEND_GLOB | + Vscadr_Vbase_Adr((0x60000 + set->mem_offset)>>4); + + if (set->enable) + vscadr |= VSCADR_STR_EN; + + + vsadr = Vsadr_Srcstride((set->Y_stride)/16-1) | + Vsadr_Xstart(set->x) | Vsadr_Ystart(set->y); + + sssize &= ~(FMsk(SSSIZE_SC_WIDTH) | FMsk(SSSIZE_SC_HEIGHT)); + sssize = Sssize_Sc_Width(set->scaled_width-1) | + Sssize_Sc_Height(set->scaled_height-1); + + spoctrl &= ~(SPOCTRL_H_SC_BP | SPOCTRL_V_SC_BP | + SPOCTRL_HV_SC_OR | SPOCTRL_VS_UR_C | + FMsk(SPOCTRL_VORDER) | FMsk(SPOCTRL_VPITCH)); + spoctrl = Spoctrl_Vpitch((set->height<<11)/set->scaled_height) + | SPOCTRL_VORDER_2TAP; + + /* Bypass horiz/vert scaler when same size */ + if (set->scaled_width == set->width) + spoctrl |= SPOCTRL_H_SC_BP; + if (set->scaled_height == set->height) + spoctrl |= SPOCTRL_V_SC_BP; + + svctrl = Svctrl_Initial1(1<<10) | Svctrl_Initial2(1<<10); + + shctrl = Shctrl_Hinitial(4<<11) + | Shctrl_Hpitch((set->width<<11)/set->scaled_width); + + /* Video plane registers */ + write_reg(vsctrl, VSCTRL); + write_reg(vbbase, VBBASE); + write_reg(vscadr, VSCADR); + write_reg(vubase, VUBASE); + write_reg(vvbase, VVBASE); + write_reg(vsadr, VSADR); + + /* Video scaler registers */ + write_reg(sssize, SSSIZE); + write_reg(spoctrl, SPOCTRL); + write_reg(svctrl, SVCTRL); + write_reg(shctrl, SHCTRL); + + /* RAPH: Using those coefficients, the scaled + * image is quite blurry. I dont know how + * to improve them ; The chip documentation + * was not helpful.. */ + write_reg(0x21212121, VSCOEFF0); + write_reg(0x21212121, VSCOEFF1); + write_reg(0x21212121, VSCOEFF2); + write_reg(0x21212121, VSCOEFF3); + write_reg(0x21212121, VSCOEFF4); + write_reg(0x00000000, HSCOEFF0); + write_reg(0x00000000, HSCOEFF1); + write_reg(0x00000000, HSCOEFF2); + write_reg(0x03020201, HSCOEFF3); + write_reg(0x09070604, HSCOEFF4); + write_reg(0x0f0e0c0a, HSCOEFF5); + write_reg(0x15141211, HSCOEFF6); + write_reg(0x19181716, HSCOEFF7); + write_reg(0x00000019, HSCOEFF8); + + /* Clock */ + if (set->enable) + vovrclk |= 1; + else + vovrclk &= ~1; + + write_reg(vovrclk, VOVRCLK); + + return 0; +} + +static int mbxfb_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg) +{ + struct mbxfb_overlaySetup setup; + int res; + + if (cmd == MBXFB_IOCX_OVERLAY) + { + if (copy_from_user(&setup, (void __user*)arg, + sizeof(struct mbxfb_overlaySetup))) + return -EFAULT; + + res = mbxfb_setupOverlay(&setup); + if (res) + return res; + + if (copy_to_user((void __user*)arg, &setup, + sizeof(struct mbxfb_overlaySetup))) + return -EFAULT; + + return 0; + } + return -EINVAL; +} + static struct fb_ops mbxfb_ops = { .owner = THIS_MODULE, .fb_check_var = mbxfb_check_var, @@ -331,6 +526,7 @@ static struct fb_ops mbxfb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_blank = mbxfb_blank, + .fb_ioctl = mbxfb_ioctl, }; /* @@ -339,36 +535,29 @@ static struct fb_ops mbxfb_ops = { */ static void __devinit setup_memc(struct fb_info *fbi) { - struct mbxfb_info *mfbi = fbi->par; unsigned long tmp; int i; /* FIXME: use platfrom specific parameters */ /* setup SDRAM controller */ - writel((LMCFG_LMC_DS | LMCFG_LMC_TS | LMCFG_LMD_TS | + write_reg_dly((LMCFG_LMC_DS | LMCFG_LMC_TS | LMCFG_LMD_TS | LMCFG_LMA_TS), LMCFG); - udelay(1000); - writel(LMPWR_MC_PWR_ACT, LMPWR); - udelay(1000); + write_reg_dly(LMPWR_MC_PWR_ACT, LMPWR); /* setup SDRAM timings */ - writel((Lmtim_Tras(7) | Lmtim_Trp(3) | Lmtim_Trcd(3) | + write_reg_dly((Lmtim_Tras(7) | Lmtim_Trp(3) | Lmtim_Trcd(3) | Lmtim_Trc(9) | Lmtim_Tdpl(2)), LMTIM); - udelay(1000); /* setup SDRAM refresh rate */ - writel(0xc2b, LMREFRESH); - udelay(1000); + write_reg_dly(0xc2b, LMREFRESH); /* setup SDRAM type parameters */ - writel((LMTYPE_CASLAT_3 | LMTYPE_BKSZ_2 | LMTYPE_ROWSZ_11 | + write_reg_dly((LMTYPE_CASLAT_3 | LMTYPE_BKSZ_2 | LMTYPE_ROWSZ_11 | LMTYPE_COLSZ_8), LMTYPE); - udelay(1000); /* enable memory controller */ - writel(LMPWR_MC_PWR_ACT, LMPWR); - udelay(1000); + write_reg_dly(LMPWR_MC_PWR_ACT, LMPWR); /* perform dummy reads */ for ( i = 0; i < 16; i++ ) { @@ -379,34 +568,30 @@ static void __devinit setup_memc(struct fb_info *fbi) static void enable_clocks(struct fb_info *fbi) { /* enable clocks */ - writel(SYSCLKSRC_PLL_2, SYSCLKSRC); - udelay(1000); - writel(PIXCLKSRC_PLL_1, PIXCLKSRC); - udelay(1000); - writel(0x00000000, CLKSLEEP); - udelay(1000); - writel((Core_Pll_M(0x17) | Core_Pll_N(0x3) | Core_Pll_P(0x0) | + write_reg_dly(SYSCLKSRC_PLL_2, SYSCLKSRC); + write_reg_dly(PIXCLKSRC_PLL_1, PIXCLKSRC); + write_reg_dly(0x00000000, CLKSLEEP); + + /* PLL output = (Frefclk * M) / (N * 2^P ) + * + * M: 0x17, N: 0x3, P: 0x0 == 100 Mhz! + * M: 0xb, N: 0x1, P: 0x1 == 71 Mhz + * */ + write_reg_dly((Core_Pll_M(0xb) | Core_Pll_N(0x1) | Core_Pll_P(0x1) | CORE_PLL_EN), COREPLL); - udelay(1000); - writel((Disp_Pll_M(0x1b) | Disp_Pll_N(0x7) | Disp_Pll_P(0x1) | + + write_reg_dly((Disp_Pll_M(0x1b) | Disp_Pll_N(0x7) | Disp_Pll_P(0x1) | DISP_PLL_EN), DISPPLL); - writel(0x00000000, VOVRCLK); - udelay(1000); - writel(PIXCLK_EN, PIXCLK); - udelay(1000); - writel(MEMCLK_EN, MEMCLK); - udelay(1000); - writel(0x00000006, M24CLK); - udelay(1000); - writel(0x00000006, MBXCLK); - udelay(1000); - writel(SDCLK_EN, SDCLK); - udelay(1000); - writel(0x00000001, PIXCLKDIV); - udelay(1000); + write_reg_dly(0x00000000, VOVRCLK); + write_reg_dly(PIXCLK_EN, PIXCLK); + write_reg_dly(MEMCLK_EN, MEMCLK); + write_reg_dly(0x00000006, M24CLK); + write_reg_dly(0x00000006, MBXCLK); + write_reg_dly(SDCLK_EN, SDCLK); + write_reg_dly(0x00000001, PIXCLKDIV); } static void __devinit setup_graphics(struct fb_info *fbi) @@ -430,16 +615,11 @@ static void __devinit setup_graphics(struct fb_info *fbi) break; } - writel(gsctrl, GSCTRL); - udelay(1000); - writel(0x00000000, GBBASE); - udelay(1000); - writel(0x00ffffff, GDRCTRL); - udelay(1000); - writel((GSCADR_STR_EN | Gscadr_Gbase_Adr(0x6000)), GSCADR); - udelay(1000); - writel(0x00000000, GPLUT); - udelay(1000); + write_reg_dly(gsctrl, GSCTRL); + write_reg_dly(0x00000000, GBBASE); + write_reg_dly(0x00ffffff, GDRCTRL); + write_reg_dly((GSCADR_STR_EN | Gscadr_Gbase_Adr(0x6000)), GSCADR); + write_reg_dly(0x00000000, GPLUT); } static void __devinit setup_display(struct fb_info *fbi) @@ -451,17 +631,14 @@ static void __devinit setup_display(struct fb_info *fbi) dsctrl |= DSCTRL_HS_POL; if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT) dsctrl |= DSCTRL_VS_POL; - writel(dsctrl, DSCTRL); - udelay(1000); - writel(0xd0303010, DMCTRL); - udelay(1000); - writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); + write_reg_dly(dsctrl, DSCTRL); + write_reg_dly(0xd0303010, DMCTRL); + write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); } static void __devinit enable_controller(struct fb_info *fbi) { - writel(SYSRST_RST, SYSRST); - udelay(1000); + write_reg_dly(SYSRST_RST, SYSRST); enable_clocks(fbi); @@ -478,12 +655,12 @@ static void __devinit enable_controller(struct fb_info *fbi) static int mbxfb_suspend(struct platform_device *dev, pm_message_t state) { /* make frame buffer memory enter self-refresh mode */ - writel(LMPWR_MC_PWR_SRM, LMPWR); + write_reg_dly(LMPWR_MC_PWR_SRM, LMPWR); while (LMPWRSTAT != LMPWRSTAT_MC_PWR_SRM) ; /* empty statement */ /* reset the device, since it's initial state is 'mostly sleeping' */ - writel(SYSRST_RST, SYSRST); + write_reg_dly(SYSRST_RST, SYSRST); return 0; } @@ -495,7 +672,7 @@ static int mbxfb_resume(struct platform_device *dev) /* setup_graphics(fbi); */ /* setup_display(fbi); */ - writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); + write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); return 0; } #else @@ -520,6 +697,12 @@ static int __devinit mbxfb_probe(struct platform_device *dev) dev_dbg(dev, "mbxfb_probe\n"); + pdata = dev->dev.platform_data; + if (!pdata) { + dev_err(&dev->dev, "platform data is required\n"); + return -EINVAL; + } + fbi = framebuffer_alloc(sizeof(struct mbxfb_info), &dev->dev); if (fbi == NULL) { dev_err(&dev->dev, "framebuffer_alloc failed\n"); @@ -528,7 +711,8 @@ static int __devinit mbxfb_probe(struct platform_device *dev) mfbi = fbi->par; fbi->pseudo_palette = mfbi->pseudo_palette; - pdata = dev->dev.platform_data; + + if (pdata->probe) mfbi->platform_probe = pdata->probe; if (pdata->remove) @@ -578,16 +762,16 @@ static int __devinit mbxfb_probe(struct platform_device *dev) goto err4; } - /* FIXME: get from platform */ fbi->screen_base = (char __iomem *)(mfbi->fb_virt_addr + 0x60000); - fbi->screen_size = 8 * 1024 * 1024; /* 8 Megs */ + fbi->screen_size = pdata->memsize; fbi->fbops = &mbxfb_ops; fbi->var = mbxfb_default; fbi->fix = mbxfb_fix; fbi->fix.smem_start = mfbi->fb_phys_addr + 0x60000; - fbi->fix.smem_len = 8 * 1024 * 1024; - fbi->fix.line_length = 640 * 2; + fbi->fix.smem_len = pdata->memsize; + fbi->fix.line_length = mbxfb_default.xres_virtual * + mbxfb_default.bits_per_pixel / 8; ret = fb_alloc_cmap(&fbi->cmap, 256, 0); if (ret < 0) { @@ -636,8 +820,7 @@ static int __devexit mbxfb_remove(struct platform_device *dev) { struct fb_info *fbi = platform_get_drvdata(dev); - writel(SYSRST_RST, SYSRST); - udelay(1000); + write_reg_dly(SYSRST_RST, SYSRST); mbxfb_debugfs_remove(fbi); diff --git a/drivers/video/mbx/reg_bits.h b/drivers/video/mbx/reg_bits.h index c226a8e4531..9a24fb0c7d4 100644 --- a/drivers/video/mbx/reg_bits.h +++ b/drivers/video/mbx/reg_bits.h @@ -242,6 +242,67 @@ #define GPLUT_LUTDATA Fld(24,0) #define Gplut_Lutdata(x) ((x) << FShft(GPLUT_LUTDATA)) +/* VSCTRL - Video Surface Control Register */ +#define VSCTRL_VPIXFMT Fld(4,27) +#define VSCTRL_VPIXFMT_YUV12 ((0x9) << FShft(VSCTRL_VPIXFMT)) +#define VSCTRL_VPIXFMT_UY0VY1 ((0xc) << FShft(VSCTRL_VPIXFMT)) +#define VSCTRL_VPIXFMT_VY0UY1 ((0xd) << FShft(VSCTRL_VPIXFMT)) +#define VSCTRL_VPIXFMT_Y0UY1V ((0xe) << FShft(VSCTRL_VPIXFMT)) +#define VSCTRL_VPIXFMT_Y0VY1U ((0xf) << FShft(VSCTRL_VPIXFMT)) +#define VSCTRL_GAMMA_EN (1 << 26) +#define VSCTRL_CSC_EN (1 << 25) +#define VSCTRL_COSITED (1 << 22) +#define VSCTRL_VSWIDTH Fld(11,11) +#define Vsctrl_Width(Pixels) /* Video Width [1-2048] */ \ + (((Pixels) - 1) << FShft(VSCTRL_VSWIDTH)) +#define VSCTRL_VSHEIGHT Fld(11,0) +#define Vsctrl_Height(Pixels) /* Video Height [1-2048] */ \ + (((Pixels) - 1) << FShft(VSCTRL_VSHEIGHT)) + +/* VBBASE - Video Blending Base Register */ +#define VBBASE_GLALPHA Fld(8,24) +#define Vbbase_Glalpha(x) ((x) << FShft(VBBASE_GLALPHA)) + +#define VBBASE_COLKEY Fld(24,0) +#define Vbbase_Colkey(x) ((x) << FShft(VBBASE_COLKEY)) + +/* VCMSK - Video Color Key Mask Register */ +#define VCMSK_COLKEY_M Fld(24,0) +#define Vcmsk_colkey_m(x) ((x) << FShft(VCMSK_COLKEY_M)) + +/* VSCADR - Video Stream Control Rddress Register */ +#define VSCADR_STR_EN (1 << 31) +#define VSCADR_COLKEY_EN (1 << 30) +#define VSCADR_COLKEYSRC (1 << 29) +#define VSCADR_BLEND_M Fld(2,27) +#define VSCADR_BLEND_NONE ((0x0) << FShft(VSCADR_BLEND_M)) +#define VSCADR_BLEND_INV ((0x1) << FShft(VSCADR_BLEND_M)) +#define VSCADR_BLEND_GLOB ((0x2) << FShft(VSCADR_BLEND_M)) +#define VSCADR_BLEND_PIX ((0x3) << FShft(VSCADR_BLEND_M)) +#define VSCADR_BLEND_POS Fld(2,24) +#define VSCADR_BLEND_GFX ((0x0) << FShft(VSCADR_BLEND_POS)) +#define VSCADR_BLEND_VID ((0x1) << FShft(VSCADR_BLEND_POS)) +#define VSCADR_BLEND_CUR ((0x2) << FShft(VSCADR_BLEND_POS)) +#define VSCADR_VBASE_ADR Fld(23,0) +#define Vscadr_Vbase_Adr(x) ((x) << FShft(VSCADR_VBASE_ADR)) + +/* VUBASE - Video U Base Register */ +#define VUBASE_UVHALFSTR (1 << 31) +#define VUBASE_UBASE_ADR Fld(24,0) +#define Vubase_Ubase_Adr(x) ((x) << FShft(VUBASE_UBASE_ADR)) + +/* VVBASE - Video V Base Register */ +#define VVBASE_VBASE_ADR Fld(24,0) +#define Vvbase_Vbase_Adr(x) ((x) << FShft(VVBASE_VBASE_ADR)) + +/* VSADR - Video Stride Address Register */ +#define VSADR_SRCSTRIDE Fld(10,22) +#define Vsadr_Srcstride(x) ((x) << FShft(VSADR_SRCSTRIDE)) +#define VSADR_XSTART Fld(11,11) +#define Vsadr_Xstart(x) ((x) << FShft(VSADR_XSTART)) +#define VSADR_YSTART Fld(11,0) +#define Vsadr_Ystart(x) ((x) << FShft(VSADR_YSTART)) + /* HCCTRL - Hardware Cursor Register fields */ #define HCCTRL_CUR_EN (1 << 31) #define HCCTRL_COLKEY_EN (1 << 29) @@ -394,6 +455,30 @@ #define DMCTRL_BURSTLEN Fld(6,0) #define Dmctrl_Burstlen(x) ((x) << FShft(DMCTRL_BURSTLEN)) +/* DINTRS - Display Interrupt Status Register */ +#define DINTRS_CUR_OR_S (1 << 18) +#define DINTRS_STR2_OR_S (1 << 17) +#define DINTRS_STR1_OR_S (1 << 16) +#define DINTRS_CUR_UR_S (1 << 6) +#define DINTRS_STR2_UR_S (1 << 5) +#define DINTRS_STR1_UR_S (1 << 4) +#define DINTRS_VEVENT1_S (1 << 3) +#define DINTRS_VEVENT0_S (1 << 2) +#define DINTRS_HBLNK1_S (1 << 1) +#define DINTRS_HBLNK0_S (1 << 0) + +/* DINTRE - Display Interrupt Enable Register */ +#define DINTRE_CUR_OR_EN (1 << 18) +#define DINTRE_STR2_OR_EN (1 << 17) +#define DINTRE_STR1_OR_EN (1 << 16) +#define DINTRE_CUR_UR_EN (1 << 6) +#define DINTRE_STR2_UR_EN (1 << 5) +#define DINTRE_STR1_UR_EN (1 << 4) +#define DINTRE_VEVENT1_EN (1 << 3) +#define DINTRE_VEVENT0_EN (1 << 2) +#define DINTRE_HBLNK1_EN (1 << 1) +#define DINTRE_HBLNK0_EN (1 << 0) + /* DLSTS - display load status register */ #define DLSTS_RLD_ADONE (1 << 23) @@ -403,16 +488,41 @@ #define DLLCTRL_RLD_ADRLN Fld(8,24) #define Dllctrl_Rld_Adrln(x) ((x) << FShft(DLLCTRL_RLD_ADRLN)) +/* CLIPCTRL - Clipping Control Register */ +#define CLIPCTRL_HSKIP Fld(11,16) +#define Clipctrl_Hskip ((x) << FShft(CLIPCTRL_HSKIP)) +#define CLIPCTRL_VSKIP Fld(11,0) +#define Clipctrl_Vskip ((x) << FShft(CLIPCTRL_VSKIP)) + /* SPOCTRL - Scale Pitch/Order Control Register */ #define SPOCTRL_H_SC_BP (1 << 31) #define SPOCTRL_V_SC_BP (1 << 30) #define SPOCTRL_HV_SC_OR (1 << 29) #define SPOCTRL_VS_UR_C (1 << 27) -#define SPOCTRL_VORDER Fld(2,16) +#define SPOCTRL_VORDER Fld(2,16) #define SPOCTRL_VORDER_1TAP ((0x0) << FShft(SPOCTRL_VORDER)) #define SPOCTRL_VORDER_2TAP ((0x1) << FShft(SPOCTRL_VORDER)) #define SPOCTRL_VORDER_4TAP ((0x3) << FShft(SPOCTRL_VORDER)) -#define SPOCTRL_VPITCH Fld(16,0) +#define SPOCTRL_VPITCH Fld(16,0) #define Spoctrl_Vpitch(x) ((x) << FShft(SPOCTRL_VPITCH)) +/* SVCTRL - Scale Vertical Control Register */ +#define SVCTRL_INITIAL1 Fld(16,16) +#define Svctrl_Initial1(x) ((x) << FShft(SVCTRL_INITIAL1)) +#define SVCTRL_INITIAL2 Fld(16,0) +#define Svctrl_Initial2(x) ((x) << FShft(SVCTRL_INITIAL2)) + +/* SHCTRL - Scale Horizontal Control Register */ +#define SHCTRL_HINITIAL Fld(16,16) +#define Shctrl_Hinitial(x) ((x) << FShft(SHCTRL_HINITIAL)) +#define SHCTRL_HDECIM (1 << 15) +#define SHCTRL_HPITCH Fld(15,0) +#define Shctrl_Hpitch(x) ((x) << FShft(SHCTRL_HPITCH)) + +/* SSSIZE - Scale Surface Size Register */ +#define SSSIZE_SC_WIDTH Fld(11,16) +#define Sssize_Sc_Width(x) ((x) << FShft(SSSIZE_SC_WIDTH)) +#define SSSIZE_SC_HEIGHT Fld(11,0) +#define Sssize_Sc_Height(x) ((x) << FShft(SSSIZE_SC_HEIGHT)) + #endif /* __REG_BITS_2700G_ */ diff --git a/drivers/video/mbx/regs.h b/drivers/video/mbx/regs.h index ad20be07666..a7c63d865aa 100644 --- a/drivers/video/mbx/regs.h +++ b/drivers/video/mbx/regs.h @@ -127,7 +127,7 @@ #define HSCOEFF0 __REG_2700G(0x000021b4) #define HSCOEFF1 __REG_2700G(0x000021b8) #define HSCOEFF2 __REG_2700G(0x000021bc) -#define HSCOEFF3 __REG_2700G(0x000021b0) +#define HSCOEFF3 __REG_2700G(0x000021c0) #define HSCOEFF4 __REG_2700G(0x000021c4) #define HSCOEFF5 __REG_2700G(0x000021c8) #define HSCOEFF6 __REG_2700G(0x000021cc) diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c index d1267904c28..5df41f6f2b8 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c @@ -34,8 +34,6 @@ const char *global_mode_option; * Standard video mode definitions (taken from XFree86) */ -#define DEFAULT_MODEDB_INDEX 0 - static const struct fb_videomode modedb[] = { { /* 640x400 @ 70 Hz, 31.5 kHz hsync */ @@ -505,8 +503,10 @@ int fb_find_mode(struct fb_var_screeninfo *var, db = modedb; dbsize = ARRAY_SIZE(modedb); } + if (!default_mode) - default_mode = &modedb[DEFAULT_MODEDB_INDEX]; + default_mode = &db[0]; + if (!default_bpp) default_bpp = 8; diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c index 59a6f5fa5ae..deaf820cb38 100644 --- a/drivers/video/neofb.c +++ b/drivers/video/neofb.c @@ -1932,7 +1932,7 @@ static int __devinit neo_init_hw(struct fb_info *info) printk(KERN_DEBUG "--- Neo extended register dump ---\n"); for (int w = 0; w < 0x85; w++) printk(KERN_DEBUG "CR %p: %p\n", (void *) w, - (void *) vga_rcrt(NULL, w); + (void *) vga_rcrt(NULL, w)); for (int w = 0; w < 0xC7; w++) printk(KERN_DEBUG "GR %p: %p\n", (void *) w, (void *) vga_rgfx(NULL, w)); diff --git a/drivers/video/nvidia/nv_accel.c b/drivers/video/nvidia/nv_accel.c index 4aefb8f4163..9efb8a3854e 100644 --- a/drivers/video/nvidia/nv_accel.c +++ b/drivers/video/nvidia/nv_accel.c @@ -261,41 +261,6 @@ void NVResetGraphics(struct fb_info *info) NVDmaKickoff(par); } -u8 byte_rev[256] = { - 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, - 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, - 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, - 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, - 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, - 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, - 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, - 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, - 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, - 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, - 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, - 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, - 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, - 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, - 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, - 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, - 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, - 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, - 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, - 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, - 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, - 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, - 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, - 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, - 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, - 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, - 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, - 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, - 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, - 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, - 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, - 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, -}; - int nvidiafb_sync(struct fb_info *info) { struct nvidia_par *par = info->par; diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c index 19eef3a0902..442e8532834 100644 --- a/drivers/video/nvidia/nv_i2c.c +++ b/drivers/video/nvidia/nv_i2c.c @@ -210,11 +210,8 @@ int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid) /* try to get from firmware */ const u8 *e = fb_firmware_edid(info->device); - if (e != NULL) { - edid = kmalloc(EDID_LENGTH, GFP_KERNEL); - if (edid) - memcpy(edid, e, EDID_LENGTH); - } + if (e != NULL) + edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL); } *out_edid = edid; diff --git a/drivers/video/nvidia/nv_local.h b/drivers/video/nvidia/nv_local.h index 4243d7fae97..e009d242ea1 100644 --- a/drivers/video/nvidia/nv_local.h +++ b/drivers/video/nvidia/nv_local.h @@ -96,13 +96,16 @@ #define READ_GET(par) (NV_RD32(&(par)->FIFO[0x0011], 0) >> 2) #ifdef __LITTLE_ENDIAN + +#include <linux/bitrev.h> + #define reverse_order(l) \ do { \ u8 *a = (u8 *)(l); \ - *a = byte_rev[*a], a++; \ - *a = byte_rev[*a], a++; \ - *a = byte_rev[*a], a++; \ - *a = byte_rev[*a]; \ + a[0] = bitrev8(a[0]); \ + a[1] = bitrev8(a[1]); \ + a[2] = bitrev8(a[2]); \ + a[3] = bitrev8(a[3]); \ } while(0) #else #define reverse_order(l) do { } while(0) diff --git a/drivers/video/nvidia/nv_of.c b/drivers/video/nvidia/nv_of.c index d9af88c2b58..181875fe35c 100644 --- a/drivers/video/nvidia/nv_of.c +++ b/drivers/video/nvidia/nv_of.c @@ -72,10 +72,9 @@ int nvidia_probe_of_connector(struct fb_info *info, int conn, u8 **out_edid) } } if (pedid) { - *out_edid = kmalloc(EDID_LENGTH, GFP_KERNEL); + *out_edid = kmemdup(pedid, EDID_LENGTH, GFP_KERNEL); if (*out_edid == NULL) return -1; - memcpy(*out_edid, pedid, EDID_LENGTH); printk(KERN_DEBUG "nvidiafb: Found OF EDID for head %d\n", conn); return 0; } diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h index 86127101765..43058d0cf5b 100644 --- a/drivers/video/nvidia/nv_proto.h +++ b/drivers/video/nvidia/nv_proto.h @@ -62,7 +62,6 @@ extern void nvidiafb_fillrect(struct fb_info *info, extern void nvidiafb_imageblit(struct fb_info *info, const struct fb_image *image); extern int nvidiafb_sync(struct fb_info *info); -extern u8 byte_rev[256]; /* in nv_backlight.h */ #ifdef CONFIG_FB_NVIDIA_BACKLIGHT diff --git a/drivers/video/offb.c b/drivers/video/offb.c index 9a40bbecf76..9576a55eaf1 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -402,6 +402,9 @@ static void __init offb_init_fb(const char *name, const char *full_name, fb_alloc_cmap(&info->cmap, 256, 0); if (register_framebuffer(info) < 0) { + iounmap(par->cmap_adr); + par->cmap_adr = NULL; + iounmap(info->screen_base); kfree(info); release_mem_region(res_start, res_size); return; diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index cb26c6df058..23387165582 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c @@ -627,6 +627,9 @@ static int __devinit platinumfb_probe(struct of_device* odev, rc = platinum_init_fb(info); if (rc != 0) { + iounmap(pinfo->frame_buffer); + iounmap(pinfo->platinum_regs); + iounmap(pinfo->cmap_regs); dev_set_drvdata(&odev->dev, NULL); framebuffer_release(info); } diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c index 73e2d7d1660..a06a064ad75 100644 --- a/drivers/video/pmagb-b-fb.c +++ b/drivers/video/pmagb-b-fb.c @@ -186,7 +186,7 @@ static void __init pmagbbfb_screen_setup(struct fb_info *info) static void __init pmagbbfb_osc_setup(struct fb_info *info) { static unsigned int pmagbbfb_freqs[] __initdata = { - 130808, 119843, 104000, 92980, 74367, 72800, + 130808, 119843, 104000, 92980, 74370, 72800, 69197, 66000, 65000, 50350, 36000, 32000, 25175 }; struct pmagbbfb_par *par = info->par; diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c index c7bc80921f1..a93618bc9d2 100644 --- a/drivers/video/pvr2fb.c +++ b/drivers/video/pvr2fb.c @@ -905,6 +905,15 @@ static int __init pvr2fb_dc_init(void) static void pvr2fb_dc_exit(void) { + if (fb_info->screen_base) { + iounmap(fb_info->screen_base); + fb_info->screen_base = NULL; + } + if (currentpar->mmio_base) { + iounmap((void *)currentpar->mmio_base); + currentpar->mmio_base = 0; + } + free_irq(HW_EVENT_VSYNC, 0); #ifdef CONFIG_SH_DMA free_dma(pvr2dma); @@ -946,6 +955,15 @@ static int __devinit pvr2fb_pci_probe(struct pci_dev *pdev, static void __devexit pvr2fb_pci_remove(struct pci_dev *pdev) { + if (fb_info->screen_base) { + iounmap(fb_info->screen_base); + fb_info->screen_base = NULL; + } + if (currentpar->mmio_base) { + iounmap((void *)currentpar->mmio_base); + currentpar->mmio_base = 0; + } + pci_release_regions(pdev); } diff --git a/drivers/video/retz3fb.c b/drivers/video/retz3fb.c index cf41ff17764..bc7ffc84e18 100644 --- a/drivers/video/retz3fb.c +++ b/drivers/video/retz3fb.c @@ -1423,8 +1423,10 @@ int __init retz3fb_init(void) do_install_cmap(0, fb_info); - if (register_framebuffer(fb_info) < 0) + if (register_framebuffer(fb_info) < 0) { + iounmap(zinfo->base); return -EINVAL; + } printk(KERN_INFO "fb%d: %s frame buffer device, using %ldK of " "video memory\n", fb_info->node, diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c index a433cc78ef9..345e8b1c1af 100644 --- a/drivers/video/riva/fbdev.c +++ b/drivers/video/riva/fbdev.c @@ -40,6 +40,7 @@ #include <linux/init.h> #include <linux/pci.h> #include <linux/backlight.h> +#include <linux/bitrev.h> #ifdef CONFIG_MTRR #include <asm/mtrr.h> #endif @@ -521,48 +522,13 @@ static inline unsigned char MISCin(struct riva_par *par) return (VGA_RD08(par->riva.PVIO, 0x3cc)); } -static u8 byte_rev[256] = { - 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, - 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, - 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, - 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, - 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, - 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, - 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, - 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, - 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, - 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, - 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, - 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, - 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, - 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, - 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, - 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, - 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, - 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, - 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, - 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, - 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, - 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, - 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, - 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, - 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, - 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, - 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, - 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, - 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, - 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, - 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, - 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, -}; - static inline void reverse_order(u32 *l) { u8 *a = (u8 *)l; - *a = byte_rev[*a], a++; - *a = byte_rev[*a], a++; - *a = byte_rev[*a], a++; - *a = byte_rev[*a]; + a[0] = bitrev8(a[0]); + a[1] = bitrev8(a[1]); + a[2] = bitrev8(a[2]); + a[3] = bitrev8(a[3]); } /* ------------------------------------------------------------------------- * @@ -774,11 +740,12 @@ static void riva_load_state(struct riva_par *par, struct riva_regs *regs) * CALLED FROM: * rivafb_set_par() */ -static void riva_load_video_mode(struct fb_info *info) +static int riva_load_video_mode(struct fb_info *info) { int bpp, width, hDisplaySize, hDisplay, hStart, hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock; int hBlankStart, hBlankEnd, vBlankStart, vBlankEnd; + int rc; struct riva_par *par = info->par; struct riva_regs newmode; @@ -884,8 +851,10 @@ static void riva_load_video_mode(struct fb_info *info) else newmode.misc_output |= 0x80; - par->riva.CalcStateExt(&par->riva, &newmode.ext, bpp, width, - hDisplaySize, height, dotClock); + rc = CalcStateExt(&par->riva, &newmode.ext, bpp, width, + hDisplaySize, height, dotClock); + if (rc) + goto out; newmode.ext.scale = NV_RD32(par->riva.PRAMDAC, 0x00000848) & 0xfff000ff; @@ -917,8 +886,12 @@ static void riva_load_video_mode(struct fb_info *info) par->current_state = newmode; riva_load_state(par, &par->current_state); par->riva.LockUnlock(&par->riva, 0); /* important for HW cursor */ + +out: rivafb_blank(FB_BLANK_UNBLANK, info); NVTRACE_LEAVE(); + + return rc; } static void riva_update_var(struct fb_var_screeninfo *var, struct fb_videomode *modedb) @@ -1286,12 +1259,15 @@ static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) static int rivafb_set_par(struct fb_info *info) { struct riva_par *par = info->par; + int rc = 0; NVTRACE_ENTER(); /* vgaHWunlock() + riva unlock (0x7F) */ CRTCout(par, 0x11, 0xFF); par->riva.LockUnlock(&par->riva, 0); - riva_load_video_mode(info); + rc = riva_load_video_mode(info); + if (rc) + goto out; if(!(info->flags & FBINFO_HWACCEL_DISABLED)) riva_setup_accel(info); @@ -1304,8 +1280,10 @@ static int rivafb_set_par(struct fb_info *info) info->pixmap.scan_align = 1; else info->pixmap.scan_align = 4; + +out: NVTRACE_LEAVE(); - return 0; + return rc; } /** diff --git a/drivers/video/riva/riva_hw.c b/drivers/video/riva/riva_hw.c index b6f8690b96c..e0b8c521cc9 100644 --- a/drivers/video/riva/riva_hw.c +++ b/drivers/video/riva/riva_hw.c @@ -1227,7 +1227,7 @@ static int CalcVClock * Calculate extended mode parameters (SVGA) and save in a * mode state structure. */ -static void CalcStateExt +int CalcStateExt ( RIVA_HW_INST *chip, RIVA_HW_STATE *state, @@ -1249,7 +1249,8 @@ static void CalcStateExt * Extended RIVA registers. */ pixelDepth = (bpp + 1)/8; - CalcVClock(dotClock, &VClk, &m, &n, &p, chip); + if (!CalcVClock(dotClock, &VClk, &m, &n, &p, chip)) + return -EINVAL; switch (chip->Architecture) { @@ -1327,6 +1328,8 @@ static void CalcStateExt state->pitch1 = state->pitch2 = state->pitch3 = pixelDepth * width; + + return 0; } /* * Load fixed function state and pre-calculated/stored state. @@ -2026,7 +2029,6 @@ static void nv3GetConfig */ chip->Busy = nv3Busy; chip->ShowHideCursor = ShowHideCursor; - chip->CalcStateExt = CalcStateExt; chip->LoadStateExt = LoadStateExt; chip->UnloadStateExt = UnloadStateExt; chip->SetStartAddress = SetStartAddress3; @@ -2084,7 +2086,6 @@ static void nv4GetConfig */ chip->Busy = nv4Busy; chip->ShowHideCursor = ShowHideCursor; - chip->CalcStateExt = CalcStateExt; chip->LoadStateExt = LoadStateExt; chip->UnloadStateExt = UnloadStateExt; chip->SetStartAddress = SetStartAddress; @@ -2186,7 +2187,6 @@ static void nv10GetConfig */ chip->Busy = nv10Busy; chip->ShowHideCursor = ShowHideCursor; - chip->CalcStateExt = CalcStateExt; chip->LoadStateExt = LoadStateExt; chip->UnloadStateExt = UnloadStateExt; chip->SetStartAddress = SetStartAddress; diff --git a/drivers/video/riva/riva_hw.h b/drivers/video/riva/riva_hw.h index a1e71a626df..c2769f73e0b 100644 --- a/drivers/video/riva/riva_hw.h +++ b/drivers/video/riva/riva_hw.h @@ -463,7 +463,6 @@ typedef struct _riva_hw_inst * Common chip functions. */ int (*Busy)(struct _riva_hw_inst *); - void (*CalcStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *,int,int,int,int,int); void (*LoadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *); void (*UnloadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *); void (*SetStartAddress)(struct _riva_hw_inst *,U032); @@ -528,6 +527,22 @@ typedef struct _riva_hw_state U032 pitch2; U032 pitch3; } RIVA_HW_STATE; + +/* + * function prototypes + */ + +extern int CalcStateExt +( + RIVA_HW_INST *chip, + RIVA_HW_STATE *state, + int bpp, + int width, + int hDisplaySize, + int height, + int dotClock +); + /* * External routines. */ diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index 59407343cc7..ccef56d0c15 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c @@ -131,7 +131,7 @@ static void s3c2410fb_set_lcdaddr(struct s3c2410fb_info *fbi) saddr2 += (var->xres * var->yres * var->bits_per_pixel)/8; saddr2>>= 1; - saddr3 = S3C2410_OFFSIZE(0) | S3C2410_PAGEWIDTH(var->xres); + saddr3 = S3C2410_OFFSIZE(0) | S3C2410_PAGEWIDTH((var->xres * var->bits_per_pixel / 16) & 0x3ff); dprintk("LCDSADDR1 = 0x%08lx\n", saddr1); dprintk("LCDSADDR2 = 0x%08lx\n", saddr2); @@ -199,28 +199,86 @@ static int s3c2410fb_check_var(struct fb_var_screeninfo *var, var->bits_per_pixel = fbi->mach_info->bpp.min; /* set r/g/b positions */ + switch (var->bits_per_pixel) { + case 1: + case 2: + case 4: + var->red.offset = 0; + var->red.length = var->bits_per_pixel; + var->green = var->red; + var->blue = var->red; + var->transp.offset = 0; + var->transp.length = 0; + break; + case 8: + if ( fbi->mach_info->type != S3C2410_LCDCON1_TFT ) { + /* 8 bpp 332 */ + var->red.length = 3; + var->red.offset = 5; + var->green.length = 3; + var->green.offset = 2; + var->blue.length = 2; + var->blue.offset = 0; + var->transp.length = 0; + } else { + var->red.offset = 0; + var->red.length = var->bits_per_pixel; + var->green = var->red; + var->blue = var->red; + var->transp.offset = 0; + var->transp.length = 0; + } + break; + case 12: + /* 12 bpp 444 */ + var->red.length = 4; + var->red.offset = 8; + var->green.length = 4; + var->green.offset = 4; + var->blue.length = 4; + var->blue.offset = 0; + var->transp.length = 0; + break; + + default: + case 16: + if (fbi->regs.lcdcon5 & S3C2410_LCDCON5_FRM565 ) { + /* 16 bpp, 565 format */ + var->red.offset = 11; + var->green.offset = 5; + var->blue.offset = 0; + var->red.length = 5; + var->green.length = 6; + var->blue.length = 5; + var->transp.length = 0; + } else { + /* 16 bpp, 5551 format */ + var->red.offset = 11; + var->green.offset = 6; + var->blue.offset = 1; + var->red.length = 5; + var->green.length = 5; + var->blue.length = 5; + var->transp.length = 0; + } + break; + case 24: + /* 24 bpp 888 */ + var->red.length = 8; + var->red.offset = 16; + var->green.length = 8; + var->green.offset = 8; + var->blue.length = 8; + var->blue.offset = 0; + var->transp.length = 0; + break; - if (var->bits_per_pixel == 16) { - var->red.offset = 11; - var->green.offset = 5; - var->blue.offset = 0; - var->red.length = 5; - var->green.length = 6; - var->blue.length = 5; - var->transp.length = 0; - } else { - var->red.length = var->bits_per_pixel; - var->red.offset = 0; - var->green.length = var->bits_per_pixel; - var->green.offset = 0; - var->blue.length = var->bits_per_pixel; - var->blue.offset = 0; - var->transp.length = 0; - } + } return 0; } + /* s3c2410fb_activate_var * * activate (set) the controller from the given framebuffer @@ -230,29 +288,61 @@ static int s3c2410fb_check_var(struct fb_var_screeninfo *var, static void s3c2410fb_activate_var(struct s3c2410fb_info *fbi, struct fb_var_screeninfo *var) { + int hs; + fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_MODEMASK; + fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_TFT; dprintk("%s: var->xres = %d\n", __FUNCTION__, var->xres); dprintk("%s: var->yres = %d\n", __FUNCTION__, var->yres); dprintk("%s: var->bpp = %d\n", __FUNCTION__, var->bits_per_pixel); - switch (var->bits_per_pixel) { - case 1: - fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT1BPP; - break; - case 2: - fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT2BPP; - break; - case 4: - fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT4BPP; - break; - case 8: - fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT8BPP; - break; - case 16: - fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT16BPP; - break; - } + fbi->regs.lcdcon1 |= fbi->mach_info->type; + + if (fbi->mach_info->type == S3C2410_LCDCON1_TFT) + switch (var->bits_per_pixel) { + case 1: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT1BPP; + break; + case 2: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT2BPP; + break; + case 4: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT4BPP; + break; + case 8: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT8BPP; + break; + case 16: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT16BPP; + break; + + default: + /* invalid pixel depth */ + dev_err(fbi->dev, "invalid bpp %d\n", var->bits_per_pixel); + } + else + switch (var->bits_per_pixel) { + case 1: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN1BPP; + break; + case 2: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN2GREY; + break; + case 4: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN4GREY; + break; + case 8: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN8BPP; + break; + case 12: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN12BPP; + break; + + default: + /* invalid pixel depth */ + dev_err(fbi->dev, "invalid bpp %d\n", var->bits_per_pixel); + } /* check to see if we need to update sync/borders */ @@ -283,15 +373,44 @@ static void s3c2410fb_activate_var(struct s3c2410fb_info *fbi, fbi->regs.lcdcon2 &= ~S3C2410_LCDCON2_LINEVAL(0x3ff); fbi->regs.lcdcon2 |= S3C2410_LCDCON2_LINEVAL(var->yres - 1); + switch(fbi->mach_info->type) { + case S3C2410_LCDCON1_DSCAN4: + case S3C2410_LCDCON1_STN8: + hs = var->xres / 8; + break; + case S3C2410_LCDCON1_STN4: + hs = var->xres / 4; + break; + default: + case S3C2410_LCDCON1_TFT: + hs = var->xres; + break; + + } + + /* Special cases : STN color displays */ + if ( ((fbi->regs.lcdcon1 & S3C2410_LCDCON1_MODEMASK) == S3C2410_LCDCON1_STN8BPP) \ + || ((fbi->regs.lcdcon1 & S3C2410_LCDCON1_MODEMASK) == S3C2410_LCDCON1_STN12BPP) ) { + hs = hs * 3; + } + + fbi->regs.lcdcon3 &= ~S3C2410_LCDCON3_HOZVAL(0x7ff); - fbi->regs.lcdcon3 |= S3C2410_LCDCON3_HOZVAL(var->xres - 1); + fbi->regs.lcdcon3 |= S3C2410_LCDCON3_HOZVAL(hs - 1); if (var->pixclock > 0) { int clkdiv = s3c2410fb_calc_pixclk(fbi, var->pixclock); - clkdiv = (clkdiv / 2) -1; - if (clkdiv < 0) - clkdiv = 0; + if (fbi->mach_info->type == S3C2410_LCDCON1_TFT) { + clkdiv = (clkdiv / 2) -1; + if (clkdiv < 0) + clkdiv = 0; + } + else { + clkdiv = (clkdiv / 2); + if (clkdiv < 2) + clkdiv = 2; + } fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_CLKVAL(0x3ff); fbi->regs.lcdcon1 |= S3C2410_LCDCON1_CLKVAL(clkdiv); @@ -329,10 +448,18 @@ static int s3c2410fb_set_par(struct fb_info *info) struct s3c2410fb_info *fbi = info->par; struct fb_var_screeninfo *var = &info->var; - if (var->bits_per_pixel == 16) - fbi->fb->fix.visual = FB_VISUAL_TRUECOLOR; - else - fbi->fb->fix.visual = FB_VISUAL_PSEUDOCOLOR; + switch (var->bits_per_pixel) + { + case 16: + fbi->fb->fix.visual = FB_VISUAL_TRUECOLOR; + break; + case 1: + fbi->fb->fix.visual = FB_VISUAL_MONO01; + break; + default: + fbi->fb->fix.visual = FB_VISUAL_PSEUDOCOLOR; + break; + } fbi->fb->fix.line_length = (var->width*var->bits_per_pixel)/8; diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c index 3f94223b7f0..cef5bf591cd 100644 --- a/drivers/video/savage/savagefb-i2c.c +++ b/drivers/video/savage/savagefb-i2c.c @@ -227,11 +227,8 @@ int savagefb_probe_i2c_connector(struct fb_info *info, u8 **out_edid) /* try to get from firmware */ const u8 *e = fb_firmware_edid(info->device); - if (e) { - edid = kmalloc(EDID_LENGTH, GFP_KERNEL); - if (edid) - memcpy(edid, e, EDID_LENGTH); - } + if (e) + edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL); } *out_edid = edid; diff --git a/drivers/video/sis/init301.c b/drivers/video/sis/init301.c index f13faddc618..47e1896cffe 100644 --- a/drivers/video/sis/init301.c +++ b/drivers/video/sis/init301.c @@ -445,11 +445,8 @@ SiS_CR36BIOSWord23d(struct SiS_Private *SiS_Pr) void SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime) { - unsigned int i, j; - - for(i = 0; i < delaytime; i++) { - j += SiS_GetReg(SiS_Pr->SiS_P3c4,0x05); - } + while (delaytime-- > 0) + SiS_GetReg(SiS_Pr->SiS_P3c4, 0x05); } #if defined(SIS300) || defined(SIS315H) diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c index 3e16e2d9d55..69f3b264a22 100644 --- a/drivers/video/stifb.c +++ b/drivers/video/stifb.c @@ -1291,6 +1291,7 @@ out_err3: out_err2: release_mem_region(fix->smem_start, fix->smem_len); out_err1: + iounmap(info->screen_base); fb_dealloc_cmap(&info->cmap); out_err0: kfree(fb); @@ -1364,6 +1365,8 @@ stifb_cleanup(void) unregister_framebuffer(sti->info); release_mem_region(info->fix.mmio_start, info->fix.mmio_len); release_mem_region(info->fix.smem_start, info->fix.smem_len); + if (info->screen_base) + iounmap(info->screen_base); fb_dealloc_cmap(&info->cmap); kfree(info); } diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c index 94fde625a6c..4b88fab83b7 100644 --- a/drivers/video/tgafb.c +++ b/drivers/video/tgafb.c @@ -23,6 +23,7 @@ #include <linux/fb.h> #include <linux/pci.h> #include <linux/selection.h> +#include <linux/bitrev.h> #include <asm/io.h> #include <video/tgafb.h> @@ -517,41 +518,6 @@ tgafb_blank(int blank, struct fb_info *info) static void tgafb_imageblit(struct fb_info *info, const struct fb_image *image) { - static unsigned char const bitrev[256] = { - 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, - 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, - 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, - 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, - 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, - 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, - 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, - 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, - 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, - 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, - 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, - 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, - 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, - 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, - 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, - 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, - 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, - 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, - 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, - 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, - 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, - 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, - 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, - 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, - 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, - 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, - 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, - 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, - 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, - 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, - 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, - 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff - }; - struct tga_par *par = (struct tga_par *) info->par; u32 fgcolor, bgcolor, dx, dy, width, height, vxres, vyres, pixelmask; unsigned long rincr, line_length, shift, pos, is8bpp; @@ -649,7 +615,7 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image) /* The image data is bit big endian; we need little endian. */ for (j = 0; j < bwidth; ++j) - mask |= bitrev[data[j]] << (j * 8); + mask |= bitrev8(data[j]) << (j * 8); __raw_writel(mask << shift, fb_base + pos); @@ -676,10 +642,10 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image) for (i = 0; i < height; ++i) { for (j = 0; j < bwidth; j += 4) { u32 mask = 0; - mask |= bitrev[data[j+0]] << (0 * 8); - mask |= bitrev[data[j+1]] << (1 * 8); - mask |= bitrev[data[j+2]] << (2 * 8); - mask |= bitrev[data[j+3]] << (3 * 8); + mask |= bitrev8(data[j+0]) << (0 * 8); + mask |= bitrev8(data[j+1]) << (1 * 8); + mask |= bitrev8(data[j+2]) << (2 * 8); + mask |= bitrev8(data[j+3]) << (3 * 8); __raw_writel(mask, fb_base + pos + j*bincr); } pos += line_length; @@ -699,7 +665,7 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image) for (i = 0; i < height; ++i) { u32 mask = 0; for (j = 0; j < bwidth; ++j) - mask |= bitrev[data[j]] << (j * 8); + mask |= bitrev8(data[j]) << (j * 8); __raw_writel(mask, fb_base + pos); pos += line_length; data += rincr; @@ -726,8 +692,8 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image) for (i = 0; i < height; ++i) { for (j = 0; j < bwidth; j += 2) { u32 mask = 0; - mask |= bitrev[data[j+0]] << (0 * 8); - mask |= bitrev[data[j+1]] << (1 * 8); + mask |= bitrev8(data[j+0]) << (0 * 8); + mask |= bitrev8(data[j+1]) << (1 * 8); mask <<= shift; __raw_writel(mask, fb_base + pos + j*bincr); } @@ -746,9 +712,9 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image) bwidth = (width & 15) > 8; for (i = 0; i < height; ++i) { - u32 mask = bitrev[data[0]]; + u32 mask = bitrev8(data[0]); if (bwidth) - mask |= bitrev[data[1]] << 8; + mask |= bitrev8(data[1]) << 8; mask <<= shift; __raw_writel(mask, fb_base + pos); pos += line_length; @@ -1473,6 +1439,8 @@ tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; err1: + if (mem_base) + iounmap(mem_base); release_mem_region(bar0_start, bar0_len); err0: kfree(all); diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c index 14175cdb9c9..55e8aa450bf 100644 --- a/drivers/video/tridentfb.c +++ b/drivers/video/tridentfb.c @@ -1130,7 +1130,8 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de if (!request_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len, "tridentfb")) { debug("request_mem_region failed!\n"); - return -1; + err = -1; + goto out_unmap; } fb_info.screen_base = ioremap_nocache(tridentfb_fix.smem_start, @@ -1139,7 +1140,8 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de if (!fb_info.screen_base) { release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len); debug("ioremap failed\n"); - return -1; + err = -1; + goto out_unmap; } output("%s board found\n", pci_name(dev)); @@ -1162,8 +1164,10 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de #endif fb_info.pseudo_palette = pseudo_pal; - if (!fb_find_mode(&default_var,&fb_info,mode,NULL,0,NULL,bpp)) - return -EINVAL; + if (!fb_find_mode(&default_var,&fb_info,mode,NULL,0,NULL,bpp)) { + err = -EINVAL; + goto out_unmap; + } fb_alloc_cmap(&fb_info.cmap,256,0); if (defaultaccel && acc) default_var.accel_flags |= FB_ACCELF_TEXT; @@ -1174,12 +1178,20 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de fb_info.device = &dev->dev; if (register_framebuffer(&fb_info) < 0) { printk(KERN_ERR "tridentfb: could not register Trident framebuffer\n"); - return -EINVAL; + err = -EINVAL; + goto out_unmap; } output("fb%d: %s frame buffer device %dx%d-%dbpp\n", fb_info.node, fb_info.fix.id,default_var.xres, default_var.yres,default_var.bits_per_pixel); return 0; + +out_unmap: + if (default_par.io_virt) + iounmap(default_par.io_virt); + if (fb_info.screen_base) + iounmap(fb_info.screen_base); + return err; } static void __devexit trident_pci_remove(struct pci_dev * dev) diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index 2196448396e..e16322d157d 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c @@ -47,17 +47,16 @@ static struct fb_fix_screeninfo vesafb_fix __initdata = { .accel = FB_ACCEL_NONE, }; -static int inverse = 0; -static int mtrr = 0; /* disable mtrr */ -static int vram_remap __initdata = 0; /* Set amount of memory to be used */ -static int vram_total __initdata = 0; /* Set total amount of memory */ -static int pmi_setpal = 1; /* pmi for palette changes ??? */ -static int ypan = 0; /* 0..nothing, 1..ypan, 2..ywrap */ -static unsigned short *pmi_base = NULL; -static void (*pmi_start)(void); -static void (*pmi_pal)(void); -static int depth; -static int vga_compat; +static int inverse __read_mostly; +static int mtrr __read_mostly; /* disable mtrr */ +static int vram_remap __initdata; /* Set amount of memory to be used */ +static int vram_total __initdata; /* Set total amount of memory */ +static int pmi_setpal __read_mostly = 1; /* pmi for palette changes ??? */ +static int ypan __read_mostly; /* 0..nothing, 1..ypan, 2..ywrap */ +static void (*pmi_start)(void) __read_mostly; +static void (*pmi_pal) (void) __read_mostly; +static int depth __read_mostly; +static int vga_compat __read_mostly; /* --------------------------------------------------------------------- */ static int vesafb_pan_display(struct fb_var_screeninfo *var, @@ -312,6 +311,7 @@ static int __init vesafb_probe(struct platform_device *dev) ypan = pmi_setpal = 0; /* not available or some DOS TSR ... */ if (ypan || pmi_setpal) { + unsigned short *pmi_base; pmi_base = (unsigned short*)phys_to_virt(((unsigned long)screen_info.vesapm_seg << 4) + screen_info.vesapm_off); pmi_start = (void*)((char*)pmi_base + pmi_base[1]); pmi_pal = (void*)((char*)pmi_base + pmi_base[2]); @@ -456,6 +456,8 @@ static int __init vesafb_probe(struct platform_device *dev) info->node, info->fix.id); return 0; err: + if (info->screen_base) + iounmap(info->screen_base); framebuffer_release(info); release_mem_region(vesafb_fix.smem_start, size_total); return err; diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index 43d5a6d9c4a..6aff63d5b29 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c @@ -264,7 +264,7 @@ static void vga16fb_clock_chip(struct vga16fb_par *par, const struct fb_info *info, int mul, int div) { - static struct { + static const struct { u32 pixclock; u8 misc; u8 seq_clock_mode; @@ -652,7 +652,7 @@ static int vga16fb_set_par(struct fb_info *info) static void ega16_setpalette(int regno, unsigned red, unsigned green, unsigned blue) { - static unsigned char map[] = { 000, 001, 010, 011 }; + static const unsigned char map[] = { 000, 001, 010, 011 }; int val; if (regno >= 16) @@ -1139,23 +1139,19 @@ static void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *are } } -#ifdef __LITTLE_ENDIAN -static unsigned int transl_l[] = -{0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF}; -static unsigned int transl_h[] = -{0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00, - 0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00}; -#else -#ifdef __BIG_ENDIAN -static unsigned int transl_h[] = -{0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF}; -static unsigned int transl_l[] = -{0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00, - 0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00}; +#define TRANS_MASK_LOW {0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF} +#define TRANS_MASK_HIGH {0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00, \ + 0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00} + +#if defined(__LITTLE_ENDIAN) +static const u16 transl_l[] = TRANS_MASK_LOW; +static const u16 transl_h[] = TRANS_MASK_HIGH; +#elif defined(__BIG_ENDIAN) +static const u16 transl_l[] = TRANS_MASK_HIGH; +static const u16 transl_h[] = TRANS_MASK_LOW; #else #error "Only __BIG_ENDIAN and __LITTLE_ENDIAN are supported in vga-planes" #endif -#endif static void vga_8planes_imageblit(struct fb_info *info, const struct fb_image *image) { diff --git a/drivers/video/virgefb.c b/drivers/video/virgefb.c index 64378959dd7..b9fb6fb3600 100644 --- a/drivers/video/virgefb.c +++ b/drivers/video/virgefb.c @@ -1799,7 +1799,7 @@ int __init virgefb_init(void) #warning release resources printk(KERN_ERR "virgefb.c: register_framebuffer failed\n"); DPRINTK("EXIT\n"); - return -EINVAL; + goto out_unmap; } printk(KERN_INFO "fb%d: %s frame buffer device, using %ldK of video memory\n", @@ -1809,6 +1809,21 @@ int __init virgefb_init(void) DPRINTK("EXIT\n"); return 0; + +out_unmap: + if (board_addr >= 0x01000000) { + if (v_ram) + iounmap((void*)v_ram); + if (vgaio_regs) + iounmap(vgaio_regs); + if (mmio_regs) + iounmap(mmio_regs); + if (vcode_switch_base) + iounmap((void*)vcode_switch_base); + v_ram = vcode_switch_base = 0; + vgaio_regs = mmio_regs = NULL; + } + return -EINVAL; } diff --git a/drivers/zorro/proc.c b/drivers/zorro/proc.c index 7aa2d3de6d3..60b05bc1564 100644 --- a/drivers/zorro/proc.c +++ b/drivers/zorro/proc.c @@ -47,7 +47,7 @@ proc_bus_zorro_lseek(struct file *file, loff_t off, int whence) static ssize_t proc_bus_zorro_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) { - struct inode *ino = file->f_dentry->d_inode; + struct inode *ino = file->f_path.dentry->d_inode; struct proc_dir_entry *dp = PDE(ino); struct zorro_dev *z = dp->data; struct ConfigDev cd; diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c index 9dfd259a70b..cc24abf232d 100644 --- a/fs/9p/vfs_addr.c +++ b/fs/9p/vfs_addr.c @@ -54,7 +54,7 @@ static int v9fs_vfs_readpage(struct file *filp, struct page *page) int retval = -EIO; loff_t offset = page_offset(page); int count = PAGE_CACHE_SIZE; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); int rsize = v9ses->maxdata - V9FS_IOHDRSZ; struct v9fs_fid *v9f = filp->private_data; diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index 905c882f4e2..3129688143e 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c @@ -71,7 +71,7 @@ static inline int dt_type(struct v9fs_stat *mistat) static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) { struct v9fs_fcall *fcall = NULL; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); struct v9fs_fid *file = filp->private_data; unsigned int i, n, s; @@ -80,7 +80,7 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) struct v9fs_stat stat; int over = 0; - dprintk(DEBUG_VFS, "name %s\n", filp->f_dentry->d_name.name); + dprintk(DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name); fid = file->fid; diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 79e6f9cd734..e86a0715128 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -60,7 +60,7 @@ int v9fs_file_open(struct inode *inode, struct file *file) dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file); - vfid = v9fs_fid_lookup(file->f_dentry); + vfid = v9fs_fid_lookup(file->f_path.dentry); if (!vfid) { dprintk(DEBUG_ERROR, "Couldn't resolve fid from dentry\n"); return -EBADF; @@ -133,7 +133,7 @@ free_fcall: static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl) { int res = 0; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; dprintk(DEBUG_VFS, "filp: %p lock: %p\n", filp, fl); @@ -161,7 +161,7 @@ static ssize_t v9fs_file_read(struct file *filp, char __user * data, size_t count, loff_t * offset) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); struct v9fs_fid *v9f = filp->private_data; struct v9fs_fcall *fcall = NULL; @@ -225,7 +225,7 @@ static ssize_t v9fs_file_write(struct file *filp, const char __user * data, size_t count, loff_t * offset) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); struct v9fs_fid *v9fid = filp->private_data; struct v9fs_fcall *fcall; diff --git a/fs/Makefile b/fs/Makefile index 9a5ce9323bf..b9ffa63f77f 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -10,7 +10,8 @@ obj-y := open.o read_write.o file_table.o super.o \ ioctl.o readdir.o select.o fifo.o locks.o dcache.o inode.o \ attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \ seq_file.o xattr.o libfs.o fs-writeback.o \ - pnode.o drop_caches.o splice.o sync.o utimes.o + pnode.o drop_caches.o splice.o sync.o utimes.o \ + stack.o ifeq ($(CONFIG_BLOCK),y) obj-y += buffer.o bio.o block_dev.o direct-io.o mpage.o ioprio.o diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c index d3c7905b2dd..2b8903893d3 100644 --- a/fs/adfs/dir.c +++ b/fs/adfs/dir.c @@ -28,7 +28,7 @@ static DEFINE_RWLOCK(adfs_dir_lock); static int adfs_readdir(struct file *filp, void *dirent, filldir_t filldir) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct super_block *sb = inode->i_sb; struct adfs_dir_ops *ops = ADFS_SB(sb)->s_dir; struct object_info obj; diff --git a/fs/affs/dir.c b/fs/affs/dir.c index 5d9649fa181..cad3ee34006 100644 --- a/fs/affs/dir.c +++ b/fs/affs/dir.c @@ -41,7 +41,7 @@ struct inode_operations affs_dir_inode_operations = { static int affs_readdir(struct file *filp, void *dirent, filldir_t filldir) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct super_block *sb = inode->i_sb; struct buffer_head *dir_bh; struct buffer_head *fh_bh; @@ -71,7 +71,7 @@ affs_readdir(struct file *filp, void *dirent, filldir_t filldir) stored++; } if (f_pos == 1) { - if (filldir(dirent, "..", 2, f_pos, parent_ino(filp->f_dentry), DT_DIR) < 0) + if (filldir(dirent, "..", 2, f_pos, parent_ino(filp->f_path.dentry), DT_DIR) < 0) return stored; filp->f_pos = f_pos = 2; stored++; diff --git a/fs/afs/dir.c b/fs/afs/dir.c index a6ec75c56fc..4acd0413405 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c @@ -392,10 +392,10 @@ static int afs_dir_readdir(struct file *file, void *cookie, filldir_t filldir) unsigned fpos; int ret; - _enter("{%Ld,{%lu}}", file->f_pos, file->f_dentry->d_inode->i_ino); + _enter("{%Ld,{%lu}}", file->f_pos, file->f_path.dentry->d_inode->i_ino); fpos = file->f_pos; - ret = afs_dir_iterate(file->f_dentry->d_inode, &fpos, cookie, filldir); + ret = afs_dir_iterate(file->f_path.dentry->d_inode, &fpos, cookie, filldir); file->f_pos = fpos; _leave(" = %d", ret); diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c index 99785a79d04..8f74e845082 100644 --- a/fs/afs/mntpt.c +++ b/fs/afs/mntpt.c @@ -18,7 +18,7 @@ #include <linux/pagemap.h> #include <linux/mount.h> #include <linux/namei.h> -#include <linux/namespace.h> +#include <linux/mnt_namespace.h> #include "super.h" #include "cell.h" #include "volume.h" @@ -136,11 +136,11 @@ static int afs_mntpt_open(struct inode *inode, struct file *file) { kenter("%p,%p{%p{%s},%s}", inode, file, - file->f_dentry->d_parent, - file->f_dentry->d_parent ? - file->f_dentry->d_parent->d_name.name : + file->f_path.dentry->d_parent, + file->f_path.dentry->d_parent ? + file->f_path.dentry->d_parent->d_name.name : (const unsigned char *) "", - file->f_dentry->d_name.name); + file->f_path.dentry->d_name.name); return -EREMOTE; } /* end afs_mntpt_open() */ diff --git a/fs/autofs/root.c b/fs/autofs/root.c index 368a1c33a3c..e698c51d2b0 100644 --- a/fs/autofs/root.c +++ b/fs/autofs/root.c @@ -45,7 +45,7 @@ static int autofs_root_readdir(struct file *filp, void *dirent, filldir_t filldi struct autofs_dir_ent *ent = NULL; struct autofs_dirhash *dirhash; struct autofs_sb_info *sbi; - struct inode * inode = filp->f_dentry->d_inode; + struct inode * inode = filp->f_path.dentry->d_inode; off_t onr, nr; lock_kernel(); @@ -557,7 +557,7 @@ static int autofs_root_ioctl(struct inode *inode, struct file *filp, case AUTOFS_IOC_SETTIMEOUT: return autofs_get_set_timeout(sbi, argp); case AUTOFS_IOC_EXPIRE: - return autofs_expire_run(inode->i_sb, sbi, filp->f_vfsmnt, + return autofs_expire_run(inode->i_sb, sbi, filp->f_path.mnt, argp); default: return -ENOSYS; diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index b13f32c8aee..216b1a364cc 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h @@ -150,7 +150,8 @@ static inline int autofs4_ispending(struct dentry *dentry) static inline void autofs4_copy_atime(struct file *src, struct file *dst) { - dst->f_dentry->d_inode->i_atime = src->f_dentry->d_inode->i_atime; + dst->f_path.dentry->d_inode->i_atime = + src->f_path.dentry->d_inode->i_atime; return; } diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index c1493524da4..8d05b9f7578 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -74,7 +74,7 @@ struct inode_operations autofs4_dir_inode_operations = { static int autofs4_root_readdir(struct file *file, void *dirent, filldir_t filldir) { - struct autofs_sb_info *sbi = autofs4_sbi(file->f_dentry->d_sb); + struct autofs_sb_info *sbi = autofs4_sbi(file->f_path.dentry->d_sb); int oz_mode = autofs4_oz_mode(sbi); DPRINTK("called, filp->f_pos = %lld", file->f_pos); @@ -95,8 +95,8 @@ static int autofs4_root_readdir(struct file *file, void *dirent, static int autofs4_dir_open(struct inode *inode, struct file *file) { - struct dentry *dentry = file->f_dentry; - struct vfsmount *mnt = file->f_vfsmnt; + struct dentry *dentry = file->f_path.dentry; + struct vfsmount *mnt = file->f_path.mnt; struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); struct dentry *cursor; int status; @@ -172,7 +172,7 @@ out: static int autofs4_dir_close(struct inode *inode, struct file *file) { - struct dentry *dentry = file->f_dentry; + struct dentry *dentry = file->f_path.dentry; struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); struct dentry *cursor = file->private_data; int status = 0; @@ -204,7 +204,7 @@ out: static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldir) { - struct dentry *dentry = file->f_dentry; + struct dentry *dentry = file->f_path.dentry; struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); struct dentry *cursor = file->private_data; int status; @@ -858,14 +858,14 @@ static int autofs4_root_ioctl(struct inode *inode, struct file *filp, return autofs4_ask_reghost(sbi, p); case AUTOFS_IOC_ASKUMOUNT: - return autofs4_ask_umount(filp->f_vfsmnt, p); + return autofs4_ask_umount(filp->f_path.mnt, p); /* return a single thing to expire */ case AUTOFS_IOC_EXPIRE: - return autofs4_expire_run(inode->i_sb,filp->f_vfsmnt,sbi, p); + return autofs4_expire_run(inode->i_sb,filp->f_path.mnt,sbi, p); /* same as above, but can send multiple expires through pipe */ case AUTOFS_IOC_EXPIRE_MULTI: - return autofs4_expire_multi(inode->i_sb,filp->f_vfsmnt,sbi, p); + return autofs4_expire_multi(inode->i_sb,filp->f_path.mnt,sbi, p); default: return -ENOSYS; diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index bce402eee55..481e59b9d91 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -212,7 +212,7 @@ befs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) static int befs_readdir(struct file *filp, void *dirent, filldir_t filldir) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct super_block *sb = inode->i_sb; befs_data_stream *ds = &BEFS_I(inode)->i_data.ds; befs_off_t value; @@ -222,7 +222,7 @@ befs_readdir(struct file *filp, void *dirent, filldir_t filldir) char keybuf[BEFS_NAME_LEN + 1]; char *nlsname; int nlsnamelen; - const char *dirname = filp->f_dentry->d_name.name; + const char *dirname = filp->f_path.dentry->d_name.name; befs_debug(sb, "---> befs_readdir() " "name %s, inode %ld, filp->f_pos %Ld", diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c index a650f1d0b85..2a746e688df 100644 --- a/fs/bfs/dir.c +++ b/fs/bfs/dir.c @@ -27,7 +27,7 @@ static struct buffer_head * bfs_find_entry(struct inode * dir, static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir) { - struct inode * dir = f->f_dentry->d_inode; + struct inode * dir = f->f_path.dentry->d_inode; struct buffer_head * bh; struct bfs_dirent * de; unsigned int offset; diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c index 517e111bb7e..813a887cd2b 100644 --- a/fs/binfmt_aout.c +++ b/fs/binfmt_aout.c @@ -274,7 +274,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC && N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) || N_TRSIZE(ex) || N_DRSIZE(ex) || - i_size_read(bprm->file->f_dentry->d_inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) { + i_size_read(bprm->file->f_path.dentry->d_inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) { return -ENOEXEC; } @@ -389,7 +389,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) { printk(KERN_WARNING "fd_offset is not page aligned. Please convert program: %s\n", - bprm->file->f_dentry->d_name.name); + bprm->file->f_path.dentry->d_name.name); error_time = jiffies; } @@ -469,7 +469,7 @@ static int load_aout_library(struct file *file) int retval; struct exec ex; - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; retval = -ENOEXEC; error = kernel_read(file, 0, (char *) &ex, sizeof(ex)); @@ -506,7 +506,7 @@ static int load_aout_library(struct file *file) { printk(KERN_WARNING "N_TXTOFF is not page aligned. Please convert library: %s\n", - file->f_dentry->d_name.name); + file->f_path.dentry->d_name.name); error_time = jiffies; } down_write(¤t->mm->mmap_sem); diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index be5869d3499..d3adfd353ff 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1190,7 +1190,7 @@ static int maydump(struct vm_area_struct *vma) /* Dump shared memory only if mapped from an anonymous file. */ if (vma->vm_flags & VM_SHARED) - return vma->vm_file->f_dentry->d_inode->i_nlink == 0; + return vma->vm_file->f_path.dentry->d_inode->i_nlink == 0; /* If it hasn't been written to, don't write it out */ if (!vma->anon_vma) @@ -1317,7 +1317,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus, prstatus->pr_pid = p->pid; prstatus->pr_ppid = p->parent->pid; prstatus->pr_pgrp = process_group(p); - prstatus->pr_sid = p->signal->session; + prstatus->pr_sid = process_session(p); if (thread_group_leader(p)) { /* * This is the record for the group leader. Add in the @@ -1363,7 +1363,7 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, psinfo->pr_pid = p->pid; psinfo->pr_ppid = p->parent->pid; psinfo->pr_pgrp = process_group(p); - psinfo->pr_sid = p->signal->session; + psinfo->pr_sid = process_session(p); i = p->state ? ffz(~p->state) + 1 : 0; psinfo->pr_state = i; diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index ed9a61c6beb..76f06f6bc2f 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c @@ -855,7 +855,7 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params, dynamic_error: printk("ELF FDPIC %s with invalid DYNAMIC section (inode=%lu)\n", - what, file->f_dentry->d_inode->i_ino); + what, file->f_path.dentry->d_inode->i_ino); return -ELIBBAD; } @@ -1186,7 +1186,7 @@ static int maydump(struct vm_area_struct *vma) /* Dump shared memory only if mapped from an anonymous file. */ if (vma->vm_flags & VM_SHARED) { - if (vma->vm_file->f_dentry->d_inode->i_nlink == 0) { + if (vma->vm_file->f_path.dentry->d_inode->i_nlink == 0) { kdcore("%08lx: %08lx: no (share)", vma->vm_start, vma->vm_flags); return 1; } @@ -1322,7 +1322,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus, prstatus->pr_pid = p->pid; prstatus->pr_ppid = p->parent->pid; prstatus->pr_pgrp = process_group(p); - prstatus->pr_sid = p->signal->session; + prstatus->pr_sid = process_session(p); if (thread_group_leader(p)) { /* * This is the record for the group leader. Add in the @@ -1371,7 +1371,7 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, psinfo->pr_pid = p->pid; psinfo->pr_ppid = p->parent->pid; psinfo->pr_pgrp = process_group(p); - psinfo->pr_sid = p->signal->session; + psinfo->pr_sid = process_session(p); i = p->state ? ffz(~p->state) + 1 : 0; psinfo->pr_state = i; diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index a62fd4018a2..ae8595d4985 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c @@ -429,7 +429,7 @@ static int load_flat_file(struct linux_binprm * bprm, int ret; hdr = ((struct flat_hdr *) bprm->buf); /* exec-header */ - inode = bprm->file->f_dentry->d_inode; + inode = bprm->file->f_path.dentry->d_inode; text_len = ntohl(hdr->data_start); data_len = ntohl(hdr->data_end) - ntohl(hdr->data_start); diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index 1713c48fef5..00687ea6273 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -542,7 +542,7 @@ static void kill_node(Node *e) static ssize_t bm_entry_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos) { - Node *e = file->f_dentry->d_inode->i_private; + Node *e = file->f_path.dentry->d_inode->i_private; loff_t pos = *ppos; ssize_t res; char *page; @@ -576,7 +576,7 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { struct dentry *root; - Node *e = file->f_dentry->d_inode->i_private; + Node *e = file->f_path.dentry->d_inode->i_private; int res = parse_command(buffer, count); switch (res) { @@ -584,7 +584,7 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer, break; case 2: set_bit(Enabled, &e->flags); break; - case 3: root = dget(file->f_vfsmnt->mnt_sb->s_root); + case 3: root = dget(file->f_path.mnt->mnt_sb->s_root); mutex_lock(&root->d_inode->i_mutex); kill_node(e); @@ -610,7 +610,7 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer, Node *e; struct inode *inode; struct dentry *root, *dentry; - struct super_block *sb = file->f_vfsmnt->mnt_sb; + struct super_block *sb = file->f_path.mnt->mnt_sb; int err = 0; e = create_entry(buffer, count); @@ -699,7 +699,7 @@ static ssize_t bm_status_write(struct file * file, const char __user * buffer, switch (res) { case 1: enabled = 0; break; case 2: enabled = 1; break; - case 3: root = dget(file->f_vfsmnt->mnt_sb->s_root); + case 3: root = dget(file->f_path.mnt->mnt_sb->s_root); mutex_lock(&root->d_inode->i_mutex); while (!list_empty(&entries)) diff --git a/fs/block_dev.c b/fs/block_dev.c index 13816b4d76f..197f9392184 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -190,7 +190,7 @@ static int blkdev_commit_write(struct file *file, struct page *page, unsigned fr /* * private llseek: - * for a block special file file->f_dentry->d_inode->i_size is zero + * for a block special file file->f_path.dentry->d_inode->i_size is zero * so we compute the size by hand (just as in block_read/write above) */ static loff_t block_llseek(struct file *file, loff_t offset, int origin) @@ -762,7 +762,7 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder, if (!bo) return -ENOMEM; - mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION); + mutex_lock(&bdev->bd_mutex); res = bd_claim(bdev, holder); if (res == 0) { found = find_bd_holder(bdev, bo); @@ -796,7 +796,7 @@ static void bd_release_from_kobject(struct block_device *bdev, if (!kobj) return; - mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION); + mutex_lock(&bdev->bd_mutex); bd_release(bdev); if ((bo = del_bd_holder(bdev, kobj))) free_bd_holder(bo); @@ -854,22 +854,6 @@ struct block_device *open_by_devnum(dev_t dev, unsigned mode) EXPORT_SYMBOL(open_by_devnum); -static int -blkdev_get_partition(struct block_device *bdev, mode_t mode, unsigned flags); - -struct block_device *open_partition_by_devnum(dev_t dev, unsigned mode) -{ - struct block_device *bdev = bdget(dev); - int err = -ENOMEM; - int flags = mode & FMODE_WRITE ? O_RDWR : O_RDONLY; - if (bdev) - err = blkdev_get_partition(bdev, mode, flags); - return err ? ERR_PTR(err) : bdev; -} - -EXPORT_SYMBOL(open_partition_by_devnum); - - /* * This routine checks whether a removable media has been changed, * and invalidates all buffer-cache-entries in that case. This @@ -916,66 +900,11 @@ void bd_set_size(struct block_device *bdev, loff_t size) } EXPORT_SYMBOL(bd_set_size); -static int __blkdev_put(struct block_device *bdev, unsigned int subclass) -{ - int ret = 0; - struct inode *bd_inode = bdev->bd_inode; - struct gendisk *disk = bdev->bd_disk; - - mutex_lock_nested(&bdev->bd_mutex, subclass); - lock_kernel(); - if (!--bdev->bd_openers) { - sync_blockdev(bdev); - kill_bdev(bdev); - } - if (bdev->bd_contains == bdev) { - if (disk->fops->release) - ret = disk->fops->release(bd_inode, NULL); - } else { - mutex_lock_nested(&bdev->bd_contains->bd_mutex, - subclass + 1); - bdev->bd_contains->bd_part_count--; - mutex_unlock(&bdev->bd_contains->bd_mutex); - } - if (!bdev->bd_openers) { - struct module *owner = disk->fops->owner; - - put_disk(disk); - module_put(owner); - - if (bdev->bd_contains != bdev) { - kobject_put(&bdev->bd_part->kobj); - bdev->bd_part = NULL; - } - bdev->bd_disk = NULL; - bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; - if (bdev != bdev->bd_contains) - __blkdev_put(bdev->bd_contains, subclass + 1); - bdev->bd_contains = NULL; - } - unlock_kernel(); - mutex_unlock(&bdev->bd_mutex); - bdput(bdev); - return ret; -} - -int blkdev_put(struct block_device *bdev) -{ - return __blkdev_put(bdev, BD_MUTEX_NORMAL); -} -EXPORT_SYMBOL(blkdev_put); - -int blkdev_put_partition(struct block_device *bdev) -{ - return __blkdev_put(bdev, BD_MUTEX_PARTITION); -} -EXPORT_SYMBOL(blkdev_put_partition); +static int __blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags, + int for_part); +static int __blkdev_put(struct block_device *bdev, int for_part); -static int -blkdev_get_whole(struct block_device *bdev, mode_t mode, unsigned flags); - -static int -do_open(struct block_device *bdev, struct file *file, unsigned int subclass) +static int do_open(struct block_device *bdev, struct file *file, int for_part) { struct module *owner = NULL; struct gendisk *disk; @@ -992,8 +921,7 @@ do_open(struct block_device *bdev, struct file *file, unsigned int subclass) } owner = disk->fops->owner; - mutex_lock_nested(&bdev->bd_mutex, subclass); - + mutex_lock_nested(&bdev->bd_mutex, for_part); if (!bdev->bd_openers) { bdev->bd_disk = disk; bdev->bd_contains = bdev; @@ -1020,25 +948,21 @@ do_open(struct block_device *bdev, struct file *file, unsigned int subclass) ret = -ENOMEM; if (!whole) goto out_first; - ret = blkdev_get_whole(whole, file->f_mode, file->f_flags); + BUG_ON(for_part); + ret = __blkdev_get(whole, file->f_mode, file->f_flags, 1); if (ret) goto out_first; bdev->bd_contains = whole; - mutex_lock_nested(&whole->bd_mutex, BD_MUTEX_WHOLE); - whole->bd_part_count++; p = disk->part[part - 1]; bdev->bd_inode->i_data.backing_dev_info = whole->bd_inode->i_data.backing_dev_info; if (!(disk->flags & GENHD_FL_UP) || !p || !p->nr_sects) { - whole->bd_part_count--; - mutex_unlock(&whole->bd_mutex); ret = -ENXIO; goto out_first; } kobject_get(&p->kobj); bdev->bd_part = p; bd_set_size(bdev, (loff_t) p->nr_sects << 9); - mutex_unlock(&whole->bd_mutex); } } else { put_disk(disk); @@ -1051,14 +975,11 @@ do_open(struct block_device *bdev, struct file *file, unsigned int subclass) } if (bdev->bd_invalidated) rescan_partitions(bdev->bd_disk, bdev); - } else { - mutex_lock_nested(&bdev->bd_contains->bd_mutex, - BD_MUTEX_WHOLE); - bdev->bd_contains->bd_part_count++; - mutex_unlock(&bdev->bd_contains->bd_mutex); } } bdev->bd_openers++; + if (for_part) + bdev->bd_part_count++; mutex_unlock(&bdev->bd_mutex); unlock_kernel(); return 0; @@ -1067,7 +988,7 @@ out_first: bdev->bd_disk = NULL; bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; if (bdev != bdev->bd_contains) - __blkdev_put(bdev->bd_contains, BD_MUTEX_WHOLE); + __blkdev_put(bdev->bd_contains, 1); bdev->bd_contains = NULL; put_disk(disk); module_put(owner); @@ -1079,7 +1000,8 @@ out: return ret; } -int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags) +static int __blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags, + int for_part) { /* * This crockload is due to bad choice of ->open() type. @@ -1091,51 +1013,17 @@ int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags) struct dentry fake_dentry = {}; fake_file.f_mode = mode; fake_file.f_flags = flags; - fake_file.f_dentry = &fake_dentry; + fake_file.f_path.dentry = &fake_dentry; fake_dentry.d_inode = bdev->bd_inode; - return do_open(bdev, &fake_file, BD_MUTEX_NORMAL); + return do_open(bdev, &fake_file, for_part); } -EXPORT_SYMBOL(blkdev_get); - -static int -blkdev_get_whole(struct block_device *bdev, mode_t mode, unsigned flags) -{ - /* - * This crockload is due to bad choice of ->open() type. - * It will go away. - * For now, block device ->open() routine must _not_ - * examine anything in 'inode' argument except ->i_rdev. - */ - struct file fake_file = {}; - struct dentry fake_dentry = {}; - fake_file.f_mode = mode; - fake_file.f_flags = flags; - fake_file.f_dentry = &fake_dentry; - fake_dentry.d_inode = bdev->bd_inode; - - return do_open(bdev, &fake_file, BD_MUTEX_WHOLE); -} - -static int -blkdev_get_partition(struct block_device *bdev, mode_t mode, unsigned flags) +int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags) { - /* - * This crockload is due to bad choice of ->open() type. - * It will go away. - * For now, block device ->open() routine must _not_ - * examine anything in 'inode' argument except ->i_rdev. - */ - struct file fake_file = {}; - struct dentry fake_dentry = {}; - fake_file.f_mode = mode; - fake_file.f_flags = flags; - fake_file.f_dentry = &fake_dentry; - fake_dentry.d_inode = bdev->bd_inode; - - return do_open(bdev, &fake_file, BD_MUTEX_PARTITION); + return __blkdev_get(bdev, mode, flags, 0); } +EXPORT_SYMBOL(blkdev_get); static int blkdev_open(struct inode * inode, struct file * filp) { @@ -1154,7 +1042,7 @@ static int blkdev_open(struct inode * inode, struct file * filp) if (bdev == NULL) return -ENOMEM; - res = do_open(bdev, filp, BD_MUTEX_NORMAL); + res = do_open(bdev, filp, 0); if (res) return res; @@ -1168,6 +1056,56 @@ static int blkdev_open(struct inode * inode, struct file * filp) return res; } +static int __blkdev_put(struct block_device *bdev, int for_part) +{ + int ret = 0; + struct inode *bd_inode = bdev->bd_inode; + struct gendisk *disk = bdev->bd_disk; + struct block_device *victim = NULL; + + mutex_lock_nested(&bdev->bd_mutex, for_part); + lock_kernel(); + if (for_part) + bdev->bd_part_count--; + + if (!--bdev->bd_openers) { + sync_blockdev(bdev); + kill_bdev(bdev); + } + if (bdev->bd_contains == bdev) { + if (disk->fops->release) + ret = disk->fops->release(bd_inode, NULL); + } + if (!bdev->bd_openers) { + struct module *owner = disk->fops->owner; + + put_disk(disk); + module_put(owner); + + if (bdev->bd_contains != bdev) { + kobject_put(&bdev->bd_part->kobj); + bdev->bd_part = NULL; + } + bdev->bd_disk = NULL; + bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; + if (bdev != bdev->bd_contains) + victim = bdev->bd_contains; + bdev->bd_contains = NULL; + } + unlock_kernel(); + mutex_unlock(&bdev->bd_mutex); + bdput(bdev); + if (victim) + __blkdev_put(victim, 1); + return ret; +} + +int blkdev_put(struct block_device *bdev) +{ + return __blkdev_put(bdev, 0); +} +EXPORT_SYMBOL(blkdev_put); + static int blkdev_close(struct inode * inode, struct file * filp) { struct block_device *bdev = I_BDEV(filp->f_mapping->host); diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 71bc87a37fc..10c90294cd1 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -498,7 +498,7 @@ cifs_get_sb(struct file_system_type *fs_type, static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { - struct inode *inode = iocb->ki_filp->f_dentry->d_inode; + struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; ssize_t written; written = generic_file_aio_write(iocb, iov, nr_segs, pos); @@ -511,7 +511,7 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin) { /* origin == SEEK_END => we must revalidate the cached file length */ if (origin == SEEK_END) { - int retval = cifs_revalidate(file->f_dentry); + int retval = cifs_revalidate(file->f_path.dentry); if (retval < 0) return (loff_t)retval; } diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c index d91a3d44e9e..da12b482ebe 100644 --- a/fs/cifs/fcntl.c +++ b/fs/cifs/fcntl.c @@ -83,10 +83,10 @@ int cifs_dir_notify(struct file * file, unsigned long arg) return 0; xid = GetXid(); - cifs_sb = CIFS_SB(file->f_dentry->d_sb); + cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); pTcon = cifs_sb->tcon; - full_path = build_path_from_dentry(file->f_dentry); + full_path = build_path_from_dentry(file->f_path.dentry); if(full_path == NULL) { rc = -ENOMEM; diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 2436ed8fc84..1aa95a50cac 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -122,34 +122,34 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file, /* if not oplocked, invalidate inode pages if mtime or file size changed */ temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime)); - if (timespec_equal(&file->f_dentry->d_inode->i_mtime, &temp) && - (file->f_dentry->d_inode->i_size == + if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) && + (file->f_path.dentry->d_inode->i_size == (loff_t)le64_to_cpu(buf->EndOfFile))) { cFYI(1, ("inode unchanged on server")); } else { - if (file->f_dentry->d_inode->i_mapping) { + if (file->f_path.dentry->d_inode->i_mapping) { /* BB no need to lock inode until after invalidate since namei code should already have it locked? */ - filemap_write_and_wait(file->f_dentry->d_inode->i_mapping); + filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping); } cFYI(1, ("invalidating remote inode since open detected it " "changed")); - invalidate_remote_inode(file->f_dentry->d_inode); + invalidate_remote_inode(file->f_path.dentry->d_inode); } client_can_cache: if (pTcon->ses->capabilities & CAP_UNIX) - rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode, + rc = cifs_get_inode_info_unix(&file->f_path.dentry->d_inode, full_path, inode->i_sb, xid); else - rc = cifs_get_inode_info(&file->f_dentry->d_inode, + rc = cifs_get_inode_info(&file->f_path.dentry->d_inode, full_path, buf, inode->i_sb, xid); if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) { pCifsInode->clientCanCacheAll = TRUE; pCifsInode->clientCanCacheRead = TRUE; cFYI(1, ("Exclusive Oplock granted on inode %p", - file->f_dentry->d_inode)); + file->f_path.dentry->d_inode)); } else if ((*oplock & 0xF) == OPLOCK_READ) pCifsInode->clientCanCacheRead = TRUE; @@ -178,7 +178,7 @@ int cifs_open(struct inode *inode, struct file *file) if (file->f_flags & O_CREAT) { /* search inode for this file and fill in file->private_data */ - pCifsInode = CIFS_I(file->f_dentry->d_inode); + pCifsInode = CIFS_I(file->f_path.dentry->d_inode); read_lock(&GlobalSMBSeslock); list_for_each(tmp, &pCifsInode->openFileList) { pCifsFile = list_entry(tmp, struct cifsFileInfo, @@ -206,7 +206,7 @@ int cifs_open(struct inode *inode, struct file *file) } } - full_path = build_path_from_dentry(file->f_dentry); + full_path = build_path_from_dentry(file->f_path.dentry); if (full_path == NULL) { FreeXid(xid); return -ENOMEM; @@ -291,7 +291,7 @@ int cifs_open(struct inode *inode, struct file *file) write_lock(&GlobalSMBSeslock); list_add(&pCifsFile->tlist, &pTcon->openFileList); - pCifsInode = CIFS_I(file->f_dentry->d_inode); + pCifsInode = CIFS_I(file->f_path.dentry->d_inode); if (pCifsInode) { rc = cifs_open_inode_helper(inode, file, pCifsInode, pCifsFile, pTcon, @@ -366,7 +366,7 @@ static int cifs_reopen_file(struct inode *inode, struct file *file, return 0; } - if (file->f_dentry == NULL) { + if (file->f_path.dentry == NULL) { up(&pCifsFile->fh_sem); cFYI(1, ("failed file reopen, no valid name if dentry freed")); FreeXid(xid); @@ -378,7 +378,7 @@ static int cifs_reopen_file(struct inode *inode, struct file *file, those that already have the rename sem can end up causing writepage to get called and if the server was down that means we end up here, and we can never tell if the caller already has the rename_sem */ - full_path = build_path_from_dentry(file->f_dentry); + full_path = build_path_from_dentry(file->f_path.dentry); if (full_path == NULL) { up(&pCifsFile->fh_sem); FreeXid(xid); @@ -444,7 +444,7 @@ static int cifs_reopen_file(struct inode *inode, struct file *file, pCifsInode->clientCanCacheAll = TRUE; pCifsInode->clientCanCacheRead = TRUE; cFYI(1, ("Exclusive Oplock granted on inode %p", - file->f_dentry->d_inode)); + file->f_path.dentry->d_inode)); } else if ((oplock & 0xF) == OPLOCK_READ) { pCifsInode->clientCanCacheRead = TRUE; pCifsInode->clientCanCacheAll = FALSE; @@ -551,7 +551,7 @@ int cifs_closedir(struct inode *inode, struct file *file) if (pCFileStruct) { struct cifsTconInfo *pTcon; - struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_dentry->d_sb); + struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); pTcon = cifs_sb->tcon; @@ -664,7 +664,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) } else cFYI(1, ("Unknown type of lock")); - cifs_sb = CIFS_SB(file->f_dentry->d_sb); + cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); pTcon = cifs_sb->tcon; if (file->private_data == NULL) { @@ -791,10 +791,10 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, int xid, long_op; struct cifsFileInfo *open_file; - if (file->f_dentry == NULL) + if (file->f_path.dentry == NULL) return -EBADF; - cifs_sb = CIFS_SB(file->f_dentry->d_sb); + cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); if (cifs_sb == NULL) return -EBADF; @@ -802,7 +802,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, /* cFYI(1, (" write %d bytes to offset %lld of %s", write_size, - *poffset, file->f_dentry->d_name.name)); */ + *poffset, file->f_path.dentry->d_name.name)); */ if (file->private_data == NULL) return -EBADF; @@ -810,12 +810,12 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, open_file = (struct cifsFileInfo *) file->private_data; xid = GetXid(); - if (file->f_dentry->d_inode == NULL) { + if (file->f_path.dentry->d_inode == NULL) { FreeXid(xid); return -EBADF; } - if (*poffset > file->f_dentry->d_inode->i_size) + if (*poffset > file->f_path.dentry->d_inode->i_size) long_op = 2; /* writes past end of file can take a long time */ else long_op = 1; @@ -840,8 +840,8 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, return -EBADF; } if (open_file->invalidHandle) { - if ((file->f_dentry == NULL) || - (file->f_dentry->d_inode == NULL)) { + if ((file->f_path.dentry == NULL) || + (file->f_path.dentry->d_inode == NULL)) { FreeXid(xid); return total_written; } @@ -849,7 +849,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, filemap_fdatawait from here so tell reopen_file not to flush data to server now */ - rc = cifs_reopen_file(file->f_dentry->d_inode, + rc = cifs_reopen_file(file->f_path.dentry->d_inode, file, FALSE); if (rc != 0) break; @@ -878,17 +878,17 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, cifs_stats_bytes_written(pTcon, total_written); /* since the write may have blocked check these pointers again */ - if (file->f_dentry) { - if (file->f_dentry->d_inode) { - struct inode *inode = file->f_dentry->d_inode; + if (file->f_path.dentry) { + if (file->f_path.dentry->d_inode) { + struct inode *inode = file->f_path.dentry->d_inode; inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb); if (total_written > 0) { - if (*poffset > file->f_dentry->d_inode->i_size) - i_size_write(file->f_dentry->d_inode, + if (*poffset > file->f_path.dentry->d_inode->i_size) + i_size_write(file->f_path.dentry->d_inode, *poffset); } - mark_inode_dirty_sync(file->f_dentry->d_inode); + mark_inode_dirty_sync(file->f_path.dentry->d_inode); } } FreeXid(xid); @@ -906,17 +906,17 @@ static ssize_t cifs_write(struct file *file, const char *write_data, int xid, long_op; struct cifsFileInfo *open_file; - if (file->f_dentry == NULL) + if (file->f_path.dentry == NULL) return -EBADF; - cifs_sb = CIFS_SB(file->f_dentry->d_sb); + cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); if (cifs_sb == NULL) return -EBADF; pTcon = cifs_sb->tcon; cFYI(1,("write %zd bytes to offset %lld of %s", write_size, - *poffset, file->f_dentry->d_name.name)); + *poffset, file->f_path.dentry->d_name.name)); if (file->private_data == NULL) return -EBADF; @@ -924,12 +924,12 @@ static ssize_t cifs_write(struct file *file, const char *write_data, open_file = (struct cifsFileInfo *)file->private_data; xid = GetXid(); - if (file->f_dentry->d_inode == NULL) { + if (file->f_path.dentry->d_inode == NULL) { FreeXid(xid); return -EBADF; } - if (*poffset > file->f_dentry->d_inode->i_size) + if (*poffset > file->f_path.dentry->d_inode->i_size) long_op = 2; /* writes past end of file can take a long time */ else long_op = 1; @@ -955,8 +955,8 @@ static ssize_t cifs_write(struct file *file, const char *write_data, return -EBADF; } if (open_file->invalidHandle) { - if ((file->f_dentry == NULL) || - (file->f_dentry->d_inode == NULL)) { + if ((file->f_path.dentry == NULL) || + (file->f_path.dentry->d_inode == NULL)) { FreeXid(xid); return total_written; } @@ -964,7 +964,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data, filemap_fdatawait from here so tell reopen_file not to flush data to server now */ - rc = cifs_reopen_file(file->f_dentry->d_inode, + rc = cifs_reopen_file(file->f_path.dentry->d_inode, file, FALSE); if (rc != 0) break; @@ -1011,16 +1011,16 @@ static ssize_t cifs_write(struct file *file, const char *write_data, cifs_stats_bytes_written(pTcon, total_written); /* since the write may have blocked check these pointers again */ - if (file->f_dentry) { - if (file->f_dentry->d_inode) { - file->f_dentry->d_inode->i_ctime = - file->f_dentry->d_inode->i_mtime = CURRENT_TIME; + if (file->f_path.dentry) { + if (file->f_path.dentry->d_inode) { + file->f_path.dentry->d_inode->i_ctime = + file->f_path.dentry->d_inode->i_mtime = CURRENT_TIME; if (total_written > 0) { - if (*poffset > file->f_dentry->d_inode->i_size) - i_size_write(file->f_dentry->d_inode, + if (*poffset > file->f_path.dentry->d_inode->i_size) + i_size_write(file->f_path.dentry->d_inode, *poffset); } - mark_inode_dirty_sync(file->f_dentry->d_inode); + mark_inode_dirty_sync(file->f_path.dentry->d_inode); } } FreeXid(xid); @@ -1384,7 +1384,7 @@ static int cifs_commit_write(struct file *file, struct page *page, if ((open_file->invalidHandle) && (!open_file->closePend)) { rc = cifs_reopen_file( - file->f_dentry->d_inode, file); + file->f_path.dentry->d_inode, file); if (rc != 0) break; } @@ -1434,7 +1434,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync) { int xid; int rc = 0; - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; xid = GetXid(); @@ -1482,7 +1482,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync) */ int cifs_flush(struct file *file, fl_owner_t id) { - struct inode * inode = file->f_dentry->d_inode; + struct inode * inode = file->f_path.dentry->d_inode; int rc = 0; /* Rather than do the steps manually: @@ -1519,7 +1519,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, struct smb_com_read_rsp *pSMBr; xid = GetXid(); - cifs_sb = CIFS_SB(file->f_dentry->d_sb); + cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); pTcon = cifs_sb->tcon; if (file->private_data == NULL) { @@ -1542,7 +1542,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, int buf_type = CIFS_NO_BUFFER; if ((open_file->invalidHandle) && (!open_file->closePend)) { - rc = cifs_reopen_file(file->f_dentry->d_inode, + rc = cifs_reopen_file(file->f_path.dentry->d_inode, file, TRUE); if (rc != 0) break; @@ -1601,7 +1601,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, int buf_type = CIFS_NO_BUFFER; xid = GetXid(); - cifs_sb = CIFS_SB(file->f_dentry->d_sb); + cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); pTcon = cifs_sb->tcon; if (file->private_data == NULL) { @@ -1629,7 +1629,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, while (rc == -EAGAIN) { if ((open_file->invalidHandle) && (!open_file->closePend)) { - rc = cifs_reopen_file(file->f_dentry->d_inode, + rc = cifs_reopen_file(file->f_path.dentry->d_inode, file, TRUE); if (rc != 0) break; @@ -1658,7 +1658,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, int cifs_file_mmap(struct file *file, struct vm_area_struct *vma) { - struct dentry *dentry = file->f_dentry; + struct dentry *dentry = file->f_path.dentry; int rc, xid; xid = GetXid(); @@ -1744,7 +1744,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, return -EBADF; } open_file = (struct cifsFileInfo *)file->private_data; - cifs_sb = CIFS_SB(file->f_dentry->d_sb); + cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); pTcon = cifs_sb->tcon; pagevec_init(&lru_pvec, 0); @@ -1786,7 +1786,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, while (rc == -EAGAIN) { if ((open_file->invalidHandle) && (!open_file->closePend)) { - rc = cifs_reopen_file(file->f_dentry->d_inode, + rc = cifs_reopen_file(file->f_path.dentry->d_inode, file, TRUE); if (rc != 0) break; @@ -1880,8 +1880,8 @@ static int cifs_readpage_worker(struct file *file, struct page *page, else cFYI(1, ("Bytes read %d",rc)); - file->f_dentry->d_inode->i_atime = - current_fs_time(file->f_dentry->d_inode->i_sb); + file->f_path.dentry->d_inode->i_atime = + current_fs_time(file->f_path.dentry->d_inode->i_sb); if (PAGE_CACHE_SIZE > rc) memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc); diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index ed18c3965f7..99dfb5337e3 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -68,30 +68,30 @@ static int construct_dentry(struct qstr *qstring, struct file *file, int rc = 0; cFYI(1, ("For %s", qstring->name)); - cifs_sb = CIFS_SB(file->f_dentry->d_sb); + cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); pTcon = cifs_sb->tcon; qstring->hash = full_name_hash(qstring->name, qstring->len); - tmp_dentry = d_lookup(file->f_dentry, qstring); + tmp_dentry = d_lookup(file->f_path.dentry, qstring); if (tmp_dentry) { cFYI(0, ("existing dentry with inode 0x%p", tmp_dentry->d_inode)); *ptmp_inode = tmp_dentry->d_inode; /* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/ if(*ptmp_inode == NULL) { - *ptmp_inode = new_inode(file->f_dentry->d_sb); + *ptmp_inode = new_inode(file->f_path.dentry->d_sb); if(*ptmp_inode == NULL) return rc; rc = 1; } } else { - tmp_dentry = d_alloc(file->f_dentry, qstring); + tmp_dentry = d_alloc(file->f_path.dentry, qstring); if(tmp_dentry == NULL) { cERROR(1,("Failed allocating dentry")); *ptmp_inode = NULL; return rc; } - *ptmp_inode = new_inode(file->f_dentry->d_sb); + *ptmp_inode = new_inode(file->f_path.dentry->d_sb); if (pTcon->nocase) tmp_dentry->d_op = &cifs_ci_dentry_ops; else @@ -432,10 +432,10 @@ static int initiate_cifs_search(const int xid, struct file *file) cifsFile->invalidHandle = TRUE; cifsFile->srch_inf.endOfSearch = FALSE; - if(file->f_dentry == NULL) + if(file->f_path.dentry == NULL) return -ENOENT; - cifs_sb = CIFS_SB(file->f_dentry->d_sb); + cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); if(cifs_sb == NULL) return -EINVAL; @@ -443,7 +443,7 @@ static int initiate_cifs_search(const int xid, struct file *file) if(pTcon == NULL) return -EINVAL; - full_path = build_path_from_dentry(file->f_dentry); + full_path = build_path_from_dentry(file->f_path.dentry); if(full_path == NULL) { return -ENOMEM; @@ -609,10 +609,10 @@ static int is_dir_changed(struct file * file) struct inode * inode; struct cifsInodeInfo *cifsInfo; - if(file->f_dentry == NULL) + if(file->f_path.dentry == NULL) return 0; - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; if(inode == NULL) return 0; @@ -839,7 +839,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file, if((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL)) return -ENOENT; - if(file->f_dentry == NULL) + if(file->f_path.dentry == NULL) return -ENOENT; rc = cifs_entry_is_dot(pfindEntry,pCifsF); @@ -847,7 +847,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file, if(rc != 0) return 0; - cifs_sb = CIFS_SB(file->f_dentry->d_sb); + cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); qstring.name = scratch_buf; rc = cifs_get_name_from_search_buf(&qstring,pfindEntry, @@ -985,12 +985,12 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) xid = GetXid(); - if(file->f_dentry == NULL) { + if(file->f_path.dentry == NULL) { FreeXid(xid); return -EIO; } - cifs_sb = CIFS_SB(file->f_dentry->d_sb); + cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); pTcon = cifs_sb->tcon; if(pTcon == NULL) return -EINVAL; @@ -998,7 +998,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) switch ((int) file->f_pos) { case 0: if (filldir(direntry, ".", 1, file->f_pos, - file->f_dentry->d_inode->i_ino, DT_DIR) < 0) { + file->f_path.dentry->d_inode->i_ino, DT_DIR) < 0) { cERROR(1, ("Filldir for current dir failed")); rc = -ENOMEM; break; @@ -1006,7 +1006,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) file->f_pos++; case 1: if (filldir(direntry, "..", 2, file->f_pos, - file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) { + file->f_path.dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) { cERROR(1, ("Filldir for parent dir failed")); rc = -ENOMEM; break; diff --git a/fs/coda/dir.c b/fs/coda/dir.c index 0102b28a15f..0c6f7f3b3dd 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c @@ -441,7 +441,7 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry, /* file operations for directories */ int coda_readdir(struct file *coda_file, void *dirent, filldir_t filldir) { - struct dentry *coda_dentry = coda_file->f_dentry; + struct dentry *coda_dentry = coda_file->f_path.dentry; struct coda_file_info *cfi; struct file *host_file; struct inode *host_inode; @@ -453,7 +453,7 @@ int coda_readdir(struct file *coda_file, void *dirent, filldir_t filldir) coda_vfs_stat.readdir++; - host_inode = host_file->f_dentry->d_inode; + host_inode = host_file->f_path.dentry->d_inode; mutex_lock(&host_inode->i_mutex); host_file->f_pos = coda_file->f_pos; @@ -544,14 +544,14 @@ static int coda_venus_readdir(struct file *filp, filldir_t filldir, /* catch truncated reads */ if (ret < vdir_size || ret < vdir_size + vdir->d_namlen) { printk("coda_venus_readdir: short read: %ld\n", - filp->f_dentry->d_inode->i_ino); + filp->f_path.dentry->d_inode->i_ino); ret = -EBADF; break; } /* validate whether the directory file actually makes sense */ if (vdir->d_reclen < vdir_size + vdir->d_namlen) { printk("coda_venus_readdir: Invalid dir: %ld\n", - filp->f_dentry->d_inode->i_ino); + filp->f_path.dentry->d_inode->i_ino); ret = -EBADF; break; } diff --git a/fs/coda/file.c b/fs/coda/file.c index dbfbcfa5b3c..5ef2b609ec7 100644 --- a/fs/coda/file.c +++ b/fs/coda/file.c @@ -66,7 +66,7 @@ coda_file_sendfile(struct file *coda_file, loff_t *ppos, size_t count, static ssize_t coda_file_write(struct file *coda_file, const char __user *buf, size_t count, loff_t *ppos) { - struct inode *host_inode, *coda_inode = coda_file->f_dentry->d_inode; + struct inode *host_inode, *coda_inode = coda_file->f_path.dentry->d_inode; struct coda_file_info *cfi; struct file *host_file; ssize_t ret; @@ -78,7 +78,7 @@ coda_file_write(struct file *coda_file, const char __user *buf, size_t count, lo if (!host_file->f_op || !host_file->f_op->write) return -EINVAL; - host_inode = host_file->f_dentry->d_inode; + host_inode = host_file->f_path.dentry->d_inode; mutex_lock(&coda_inode->i_mutex); ret = host_file->f_op->write(host_file, buf, count, ppos); @@ -106,8 +106,8 @@ coda_file_mmap(struct file *coda_file, struct vm_area_struct *vma) if (!host_file->f_op || !host_file->f_op->mmap) return -ENODEV; - coda_inode = coda_file->f_dentry->d_inode; - host_inode = host_file->f_dentry->d_inode; + coda_inode = coda_file->f_path.dentry->d_inode; + host_inode = host_file->f_path.dentry->d_inode; coda_file->f_mapping = host_file->f_mapping; if (coda_inode->i_mapping == &coda_inode->i_data) coda_inode->i_mapping = host_inode->i_mapping; @@ -190,7 +190,7 @@ int coda_flush(struct file *coda_file, fl_owner_t id) cfi = CODA_FTOC(coda_file); BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC); - coda_inode = coda_file->f_dentry->d_inode; + coda_inode = coda_file->f_path.dentry->d_inode; err = venus_store(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags, coda_file->f_uid); @@ -233,7 +233,7 @@ int coda_release(struct inode *coda_inode, struct file *coda_file) err = venus_close(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags, coda_file->f_uid); - host_inode = cfi->cfi_container->f_dentry->d_inode; + host_inode = cfi->cfi_container->f_path.dentry->d_inode; cii = ITOC(coda_inode); /* did we mmap this file? */ @@ -270,7 +270,7 @@ int coda_fsync(struct file *coda_file, struct dentry *coda_dentry, int datasync) coda_vfs_stat.fsync++; if (host_file->f_op && host_file->f_op->fsync) { - host_dentry = host_file->f_dentry; + host_dentry = host_file->f_path.dentry; host_inode = host_dentry->d_inode; mutex_lock(&host_inode->i_mutex); err = host_file->f_op->fsync(host_file, host_dentry, datasync); diff --git a/fs/coda/inode.c b/fs/coda/inode.c index b64659fa82d..01395defed8 100644 --- a/fs/coda/inode.c +++ b/fs/coda/inode.c @@ -119,7 +119,7 @@ static int get_device_index(struct coda_mount_data *data) file = fget(data->fd); inode = NULL; if(file) - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; if(!inode || !S_ISCHR(inode->i_mode) || imajor(inode) != CODA_PSDEV_MAJOR) { diff --git a/fs/compat.c b/fs/compat.c index a7e3f162fb1..b766964a625 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -232,7 +232,7 @@ asmlinkage long compat_sys_fstatfs(unsigned int fd, struct compat_statfs __user file = fget(fd); if (!file) goto out; - error = vfs_statfs(file->f_dentry, &tmp); + error = vfs_statfs(file->f_path.dentry, &tmp); if (!error) error = put_compat_statfs(buf, &tmp); fput(file); @@ -303,7 +303,7 @@ asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct c file = fget(fd); if (!file) goto out; - error = vfs_statfs(file->f_dentry, &tmp); + error = vfs_statfs(file->f_path.dentry, &tmp); if (!error) error = put_compat_statfs64(buf, &tmp); fput(file); @@ -365,7 +365,7 @@ static void compat_ioctl_error(struct file *filp, unsigned int fd, /* find the name of the device. */ path = (char *)__get_free_page(GFP_KERNEL); if (path) { - fn = d_path(filp->f_dentry, filp->f_vfsmnt, path, PAGE_SIZE); + fn = d_path(filp->f_path.dentry, filp->f_path.mnt, path, PAGE_SIZE); if (IS_ERR(fn)) fn = "?"; } @@ -416,7 +416,7 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd, case FIBMAP: case FIGETBSZ: case FIONREAD: - if (S_ISREG(filp->f_dentry->d_inode->i_mode)) + if (S_ISREG(filp->f_path.dentry->d_inode->i_mode)) break; /*FALL THROUGH*/ @@ -438,7 +438,7 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd, goto found_handler; } - if (S_ISSOCK(filp->f_dentry->d_inode->i_mode) && + if (S_ISSOCK(filp->f_path.dentry->d_inode->i_mode) && cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) { error = siocdevprivate_ioctl(fd, cmd, arg); } else { @@ -1259,7 +1259,7 @@ out: if (iov != iovstack) kfree(iov); if ((ret + (type == READ)) > 0) { - struct dentry *dentry = file->f_dentry; + struct dentry *dentry = file->f_path.dentry; if (type == READ) fsnotify_access(dentry); else diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index bcc3caf5d82..c81c958b3e1 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -1177,7 +1177,7 @@ static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long ar static int vt_check(struct file *file) { struct tty_struct *tty; - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; if (file->f_op->ioctl != tty_ioctl) return -EINVAL; diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index c398861f78a..1814ba44680 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c @@ -980,7 +980,7 @@ int configfs_rename_dir(struct config_item * item, const char *new_name) static int configfs_dir_open(struct inode *inode, struct file *file) { - struct dentry * dentry = file->f_dentry; + struct dentry * dentry = file->f_path.dentry; struct configfs_dirent * parent_sd = dentry->d_fsdata; mutex_lock(&dentry->d_inode->i_mutex); @@ -993,7 +993,7 @@ static int configfs_dir_open(struct inode *inode, struct file *file) static int configfs_dir_close(struct inode *inode, struct file *file) { - struct dentry * dentry = file->f_dentry; + struct dentry * dentry = file->f_path.dentry; struct configfs_dirent * cursor = file->private_data; mutex_lock(&dentry->d_inode->i_mutex); @@ -1013,7 +1013,7 @@ static inline unsigned char dt_type(struct configfs_dirent *sd) static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir) { - struct dentry *dentry = filp->f_dentry; + struct dentry *dentry = filp->f_path.dentry; struct configfs_dirent * parent_sd = dentry->d_fsdata; struct configfs_dirent *cursor = filp->private_data; struct list_head *p, *q = &cursor->s_sibling; @@ -1070,7 +1070,7 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir static loff_t configfs_dir_lseek(struct file * file, loff_t offset, int origin) { - struct dentry * dentry = file->f_dentry; + struct dentry * dentry = file->f_path.dentry; mutex_lock(&dentry->d_inode->i_mutex); switch (origin) { @@ -1080,7 +1080,7 @@ static loff_t configfs_dir_lseek(struct file * file, loff_t offset, int origin) if (offset >= 0) break; default: - mutex_unlock(&file->f_dentry->d_inode->i_mutex); + mutex_unlock(&file->f_path.dentry->d_inode->i_mutex); return -EINVAL; } if (offset != file->f_pos) { diff --git a/fs/configfs/file.c b/fs/configfs/file.c index cf33fac68c8..2a7cb086e80 100644 --- a/fs/configfs/file.c +++ b/fs/configfs/file.c @@ -134,7 +134,7 @@ configfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *pp down(&buffer->sem); if (buffer->needs_read_fill) { - if ((retval = fill_read_buffer(file->f_dentry,buffer))) + if ((retval = fill_read_buffer(file->f_path.dentry,buffer))) goto out; } pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n", @@ -222,7 +222,7 @@ configfs_write_file(struct file *file, const char __user *buf, size_t count, lof down(&buffer->sem); len = fill_write_buffer(buffer, buf, count); if (len > 0) - len = flush_write_buffer(file->f_dentry, buffer, count); + len = flush_write_buffer(file->f_path.dentry, buffer, count); if (len > 0) *ppos += len; up(&buffer->sem); @@ -231,8 +231,8 @@ configfs_write_file(struct file *file, const char __user *buf, size_t count, lof static int check_perm(struct inode * inode, struct file * file) { - struct config_item *item = configfs_get_config_item(file->f_dentry->d_parent); - struct configfs_attribute * attr = to_attr(file->f_dentry); + struct config_item *item = configfs_get_config_item(file->f_path.dentry->d_parent); + struct configfs_attribute * attr = to_attr(file->f_path.dentry); struct configfs_buffer * buffer; struct configfs_item_operations * ops = NULL; int error = 0; @@ -305,8 +305,8 @@ static int configfs_open_file(struct inode * inode, struct file * filp) static int configfs_release(struct inode * inode, struct file * filp) { - struct config_item * item = to_item(filp->f_dentry->d_parent); - struct configfs_attribute * attr = to_attr(filp->f_dentry); + struct config_item * item = to_item(filp->f_path.dentry->d_parent); + struct configfs_attribute * attr = to_attr(filp->f_path.dentry); struct module * owner = attr->ca_owner; struct configfs_buffer * buffer = filp->private_data; diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index 0509cedd415..6db03fb089d 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c @@ -338,7 +338,7 @@ static int cramfs_statfs(struct dentry *dentry, struct kstatfs *buf) */ static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct super_block *sb = inode->i_sb; char *buf; unsigned int offset; diff --git a/fs/dnotify.c b/fs/dnotify.c index 1f26a2b9eee..936409fcd93 100644 --- a/fs/dnotify.c +++ b/fs/dnotify.c @@ -42,7 +42,7 @@ void dnotify_flush(struct file *filp, fl_owner_t id) struct dnotify_struct **prev; struct inode *inode; - inode = filp->f_dentry->d_inode; + inode = filp->f_path.dentry->d_inode; if (!S_ISDIR(inode->i_mode)) return; spin_lock(&inode->i_lock); @@ -74,7 +74,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg) } if (!dir_notify_enable) return -EINVAL; - inode = filp->f_dentry->d_inode; + inode = filp->f_path.dentry->d_inode; if (!S_ISDIR(inode->i_mode)) return -ENOTDIR; dn = kmem_cache_alloc(dn_cache, GFP_KERNEL); diff --git a/fs/dquot.c b/fs/dquot.c index f9cd5e23ebd..0952cc474d9 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -694,9 +694,9 @@ restart: file_list_lock(); list_for_each(p, &sb->s_files) { struct file *filp = list_entry(p, struct file, f_u.fu_list); - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; if (filp->f_mode & FMODE_WRITE && dqinit_needed(inode, type)) { - struct dentry *dentry = dget(filp->f_dentry); + struct dentry *dentry = dget(filp->f_path.dentry); file_list_unlock(); sb->dq_op->initialize(inode, type); dput(dentry); @@ -828,6 +828,7 @@ static inline int need_print_warning(struct dquot *dquot) static void print_warning(struct dquot *dquot, const char warntype) { char *msg = NULL; + struct tty_struct *tty; int flag = (warntype == BHARDWARN || warntype == BSOFTLONGWARN) ? DQ_BLKS_B : ((warntype == IHARDWARN || warntype == ISOFTLONGWARN) ? DQ_INODES_B : 0); @@ -835,14 +836,15 @@ static void print_warning(struct dquot *dquot, const char warntype) return; mutex_lock(&tty_mutex); - if (!current->signal->tty) + tty = get_current_tty(); + if (!tty) goto out_lock; - tty_write_message(current->signal->tty, dquot->dq_sb->s_id); + tty_write_message(tty, dquot->dq_sb->s_id); if (warntype == ISOFTWARN || warntype == BSOFTWARN) - tty_write_message(current->signal->tty, ": warning, "); + tty_write_message(tty, ": warning, "); else - tty_write_message(current->signal->tty, ": write failed, "); - tty_write_message(current->signal->tty, quotatypes[dquot->dq_type]); + tty_write_message(tty, ": write failed, "); + tty_write_message(tty, quotatypes[dquot->dq_type]); switch (warntype) { case IHARDWARN: msg = " file limit reached.\r\n"; @@ -863,7 +865,7 @@ static void print_warning(struct dquot *dquot, const char warntype) msg = " block quota exceeded.\r\n"; break; } - tty_write_message(current->signal->tty, msg); + tty_write_message(tty, msg); out_lock: mutex_unlock(&tty_mutex); } diff --git a/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c index 52d1e36dc74..329efcd3d8c 100644 --- a/fs/ecryptfs/dentry.c +++ b/fs/ecryptfs/dentry.c @@ -25,6 +25,7 @@ #include <linux/dcache.h> #include <linux/namei.h> #include <linux/mount.h> +#include <linux/fs_stack.h> #include "ecryptfs_kernel.h" /** @@ -61,7 +62,7 @@ static int ecryptfs_d_revalidate(struct dentry *dentry, struct nameidata *nd) struct inode *lower_inode = ecryptfs_inode_to_lower(dentry->d_inode); - ecryptfs_copy_attr_all(dentry->d_inode, lower_inode); + fsstack_copy_attr_all(dentry->d_inode, lower_inode, NULL); } out: return rc; diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index f992533d169..afb64bdbe6a 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -28,6 +28,8 @@ #include <keys/user-type.h> #include <linux/fs.h> +#include <linux/fs_stack.h> +#include <linux/namei.h> #include <linux/scatterlist.h> /* Version verification for shared data structures w/ userspace */ @@ -227,8 +229,7 @@ struct ecryptfs_inode_info { /* dentry private data. Each dentry must keep track of a lower * vfsmount too. */ struct ecryptfs_dentry_info { - struct dentry *wdi_dentry; - struct vfsmount *lower_mnt; + struct path lower_path; struct ecryptfs_crypt_stat *crypt_stat; }; @@ -355,26 +356,26 @@ ecryptfs_set_dentry_private(struct dentry *dentry, static inline struct dentry * ecryptfs_dentry_to_lower(struct dentry *dentry) { - return ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->wdi_dentry; + return ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path.dentry; } static inline void ecryptfs_set_dentry_lower(struct dentry *dentry, struct dentry *lower_dentry) { - ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->wdi_dentry = + ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path.dentry = lower_dentry; } static inline struct vfsmount * ecryptfs_dentry_to_lower_mnt(struct dentry *dentry) { - return ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_mnt; + return ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path.mnt; } static inline void ecryptfs_set_dentry_lower_mnt(struct dentry *dentry, struct vfsmount *lower_mnt) { - ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_mnt = + ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path.mnt = lower_mnt; } @@ -413,9 +414,6 @@ int ecryptfs_encode_filename(struct ecryptfs_crypt_stat *crypt_stat, const char *name, int length, char **encoded_name); struct dentry *ecryptfs_lower_dentry(struct dentry *this_dentry); -void ecryptfs_copy_attr_atime(struct inode *dest, const struct inode *src); -void ecryptfs_copy_attr_all(struct inode *dest, const struct inode *src); -void ecryptfs_copy_inode_size(struct inode *dst, const struct inode *src); void ecryptfs_dump_hex(char *data, int bytes); int virt_to_scatterlist(const void *addr, int size, struct scatterlist *sg, int sg_size); diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index 42099e779a5..c5a2e5298f1 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c @@ -30,6 +30,7 @@ #include <linux/security.h> #include <linux/smp_lock.h> #include <linux/compat.h> +#include <linux/fs_stack.h> #include "ecryptfs_kernel.h" /** @@ -75,7 +76,7 @@ static loff_t ecryptfs_llseek(struct file *file, loff_t offset, int origin) } ecryptfs_printk(KERN_DEBUG, "new_end_pos = [0x%.16x]\n", new_end_pos); if (expanding_file) { - rc = ecryptfs_truncate(file->f_dentry, new_end_pos); + rc = ecryptfs_truncate(file->f_path.dentry, new_end_pos); if (rc) { rv = rc; ecryptfs_printk(KERN_ERR, "Error on attempt to " @@ -116,8 +117,8 @@ static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb, if (-EIOCBQUEUED == rc) rc = wait_on_sync_kiocb(iocb); if (rc >= 0) { - lower_dentry = ecryptfs_dentry_to_lower(file->f_dentry); - lower_vfsmount = ecryptfs_dentry_to_lower_mnt(file->f_dentry); + lower_dentry = ecryptfs_dentry_to_lower(file->f_path.dentry); + lower_vfsmount = ecryptfs_dentry_to_lower_mnt(file->f_path.dentry); touch_atime(lower_vfsmount, lower_dentry); } return rc; @@ -176,10 +177,10 @@ static int ecryptfs_readdir(struct file *file, void *dirent, filldir_t filldir) lower_file = ecryptfs_file_to_lower(file); lower_file->f_pos = file->f_pos; - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; memset(&buf, 0, sizeof(buf)); buf.dirent = dirent; - buf.dentry = file->f_dentry; + buf.dentry = file->f_path.dentry; buf.filldir = filldir; retry: buf.filldir_called = 0; @@ -192,7 +193,7 @@ retry: goto retry; file->f_pos = lower_file->f_pos; if (rc >= 0) - ecryptfs_copy_attr_atime(inode, lower_file->f_dentry->d_inode); + fsstack_copy_attr_atime(inode, lower_file->f_path.dentry->d_inode); return rc; } @@ -239,7 +240,7 @@ static int ecryptfs_open(struct inode *inode, struct file *file) int rc = 0; struct ecryptfs_crypt_stat *crypt_stat = NULL; struct ecryptfs_mount_crypt_stat *mount_crypt_stat; - struct dentry *ecryptfs_dentry = file->f_dentry; + struct dentry *ecryptfs_dentry = file->f_path.dentry; /* Private value of ecryptfs_dentry allocated in * ecryptfs_lookup() */ struct dentry *lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 8a1945a84c3..11f5e5076ae 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -30,6 +30,7 @@ #include <linux/namei.h> #include <linux/mount.h> #include <linux/crypto.h> +#include <linux/fs_stack.h> #include "ecryptfs_kernel.h" static struct dentry *lock_parent(struct dentry *dentry) @@ -53,48 +54,6 @@ static void unlock_dir(struct dentry *dir) dput(dir); } -void ecryptfs_copy_inode_size(struct inode *dst, const struct inode *src) -{ - i_size_write(dst, i_size_read((struct inode *)src)); - dst->i_blocks = src->i_blocks; -} - -void ecryptfs_copy_attr_atime(struct inode *dest, const struct inode *src) -{ - dest->i_atime = src->i_atime; -} - -static void ecryptfs_copy_attr_times(struct inode *dest, - const struct inode *src) -{ - dest->i_atime = src->i_atime; - dest->i_mtime = src->i_mtime; - dest->i_ctime = src->i_ctime; -} - -static void ecryptfs_copy_attr_timesizes(struct inode *dest, - const struct inode *src) -{ - dest->i_atime = src->i_atime; - dest->i_mtime = src->i_mtime; - dest->i_ctime = src->i_ctime; - ecryptfs_copy_inode_size(dest, src); -} - -void ecryptfs_copy_attr_all(struct inode *dest, const struct inode *src) -{ - dest->i_mode = src->i_mode; - dest->i_nlink = src->i_nlink; - dest->i_uid = src->i_uid; - dest->i_gid = src->i_gid; - dest->i_rdev = src->i_rdev; - dest->i_atime = src->i_atime; - dest->i_mtime = src->i_mtime; - dest->i_ctime = src->i_ctime; - dest->i_blkbits = src->i_blkbits; - dest->i_flags = src->i_flags; -} - /** * ecryptfs_create_underlying_file * @lower_dir_inode: inode of the parent in the lower fs of the new file @@ -171,8 +130,8 @@ ecryptfs_do_create(struct inode *directory_inode, ecryptfs_printk(KERN_ERR, "Failure in ecryptfs_interpose\n"); goto out_lock; } - ecryptfs_copy_attr_timesizes(directory_inode, - lower_dir_dentry->d_inode); + fsstack_copy_attr_times(directory_inode, lower_dir_dentry->d_inode); + fsstack_copy_inode_size(directory_inode, lower_dir_dentry->d_inode); out_lock: unlock_dir(lower_dir_dentry); out: @@ -196,7 +155,7 @@ static int grow_file(struct dentry *ecryptfs_dentry, struct file *lower_file, struct ecryptfs_file_info tmp_file_info; memset(&fake_file, 0, sizeof(fake_file)); - fake_file.f_dentry = ecryptfs_dentry; + fake_file.f_path.dentry = ecryptfs_dentry; memset(&tmp_file_info, 0, sizeof(tmp_file_info)); ecryptfs_set_file_private(&fake_file, &tmp_file_info); ecryptfs_set_file_lower(&fake_file, lower_file); @@ -365,7 +324,7 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, "d_name.name = [%s]\n", lower_dentry, lower_dentry->d_name.name); lower_inode = lower_dentry->d_inode; - ecryptfs_copy_attr_atime(dir, lower_dir_dentry->d_inode); + fsstack_copy_attr_atime(dir, lower_dir_dentry->d_inode); BUG_ON(!atomic_read(&lower_dentry->d_count)); ecryptfs_set_dentry_private(dentry, kmem_cache_alloc(ecryptfs_dentry_info_cache, @@ -462,7 +421,8 @@ static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir, rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb, 0); if (rc) goto out_lock; - ecryptfs_copy_attr_timesizes(dir, lower_new_dentry->d_inode); + fsstack_copy_attr_times(dir, lower_new_dentry->d_inode); + fsstack_copy_inode_size(dir, lower_new_dentry->d_inode); old_dentry->d_inode->i_nlink = ecryptfs_inode_to_lower(old_dentry->d_inode)->i_nlink; i_size_write(new_dentry->d_inode, file_size_save); @@ -488,7 +448,7 @@ static int ecryptfs_unlink(struct inode *dir, struct dentry *dentry) printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc); goto out_unlock; } - ecryptfs_copy_attr_times(dir, lower_dir_inode); + fsstack_copy_attr_times(dir, lower_dir_inode); dentry->d_inode->i_nlink = ecryptfs_inode_to_lower(dentry->d_inode)->i_nlink; dentry->d_inode->i_ctime = dir->i_ctime; @@ -527,7 +487,8 @@ static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry, rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0); if (rc) goto out_lock; - ecryptfs_copy_attr_timesizes(dir, lower_dir_dentry->d_inode); + fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); + fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode); out_lock: unlock_dir(lower_dir_dentry); dput(lower_dentry); @@ -550,7 +511,8 @@ static int ecryptfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0); if (rc) goto out; - ecryptfs_copy_attr_timesizes(dir, lower_dir_dentry->d_inode); + fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); + fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode); dir->i_nlink = lower_dir_dentry->d_inode->i_nlink; out: unlock_dir(lower_dir_dentry); @@ -573,7 +535,7 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry) dput(lower_dentry); if (!rc) d_delete(lower_dentry); - ecryptfs_copy_attr_times(dir, lower_dir_dentry->d_inode); + fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); dir->i_nlink = lower_dir_dentry->d_inode->i_nlink; unlock_dir(lower_dir_dentry); if (!rc) @@ -597,7 +559,8 @@ ecryptfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0); if (rc) goto out; - ecryptfs_copy_attr_timesizes(dir, lower_dir_dentry->d_inode); + fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); + fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode); out: unlock_dir(lower_dir_dentry); if (!dentry->d_inode) @@ -626,9 +589,9 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry, lower_new_dir_dentry->d_inode, lower_new_dentry); if (rc) goto out_lock; - ecryptfs_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode); + fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode, NULL); if (new_dir != old_dir) - ecryptfs_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode); + fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode, NULL); out_lock: unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry); dput(lower_new_dentry->d_parent); @@ -684,8 +647,8 @@ ecryptfs_readlink(struct dentry *dentry, char __user * buf, int bufsiz) rc = -EFAULT; } kfree(decoded_name); - ecryptfs_copy_attr_atime(dentry->d_inode, - lower_dentry->d_inode); + fsstack_copy_attr_atime(dentry->d_inode, + lower_dentry->d_inode); } out_free_lower_buf: kfree(lower_buf); @@ -791,7 +754,7 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) * the file in the underlying filesystem so that the * truncation has an effect there as well. */ memset(&fake_ecryptfs_file, 0, sizeof(fake_ecryptfs_file)); - fake_ecryptfs_file.f_dentry = dentry; + fake_ecryptfs_file.f_path.dentry = dentry; /* Released at out_free: label */ ecryptfs_set_file_private(&fake_ecryptfs_file, kmem_cache_alloc(ecryptfs_file_info_cache, @@ -915,7 +878,7 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) } rc = notify_change(lower_dentry, ia); out: - ecryptfs_copy_attr_all(inode, lower_inode); + fsstack_copy_attr_all(inode, lower_inode, NULL); return rc; } diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 3ede12b2593..d0541ae8fab 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -35,6 +35,7 @@ #include <linux/pagemap.h> #include <linux/key.h> #include <linux/parser.h> +#include <linux/fs_stack.h> #include "ecryptfs_kernel.h" /** @@ -112,10 +113,10 @@ int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry, d_add(dentry, inode); else d_instantiate(dentry, inode); - ecryptfs_copy_attr_all(inode, lower_inode); + fsstack_copy_attr_all(inode, lower_inode, NULL); /* This size will be overwritten for real files w/ headers and * other metadata */ - ecryptfs_copy_inode_size(inode, lower_inode); + fsstack_copy_inode_size(inode, lower_inode); out: return rc; } diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 924dd90a4cf..06843d24f23 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c @@ -51,7 +51,7 @@ static struct page *ecryptfs_get1page(struct file *file, int index) struct inode *inode; struct address_space *mapping; - dentry = file->f_dentry; + dentry = file->f_path.dentry; inode = dentry->d_inode; mapping = inode->i_mapping; page = read_cache_page(mapping, index, @@ -84,7 +84,7 @@ int write_zeros(struct file *file, pgoff_t index, int start, int num_zeros); int ecryptfs_fill_zeros(struct file *file, loff_t new_length) { int rc = 0; - struct dentry *dentry = file->f_dentry; + struct dentry *dentry = file->f_path.dentry; struct inode *inode = dentry->d_inode; pgoff_t old_end_page_index = 0; pgoff_t index = old_end_page_index; @@ -218,7 +218,7 @@ int ecryptfs_do_readpage(struct file *file, struct page *page, char *lower_page_data; const struct address_space_operations *lower_a_ops; - dentry = file->f_dentry; + dentry = file->f_path.dentry; lower_file = ecryptfs_file_to_lower(file); lower_dentry = ecryptfs_dentry_to_lower(dentry); inode = dentry->d_inode; @@ -275,9 +275,9 @@ static int ecryptfs_readpage(struct file *file, struct page *page) int rc = 0; struct ecryptfs_crypt_stat *crypt_stat; - BUG_ON(!(file && file->f_dentry && file->f_dentry->d_inode)); - crypt_stat = - &ecryptfs_inode_to_private(file->f_dentry->d_inode)->crypt_stat; + BUG_ON(!(file && file->f_path.dentry && file->f_path.dentry->d_inode)); + crypt_stat = &ecryptfs_inode_to_private(file->f_path.dentry->d_inode) + ->crypt_stat; if (!crypt_stat || !ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED) || ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE)) { @@ -638,8 +638,8 @@ static int ecryptfs_commit_write(struct file *file, struct page *page, lower_inode = ecryptfs_inode_to_lower(inode); lower_file = ecryptfs_file_to_lower(file); mutex_lock(&lower_inode->i_mutex); - crypt_stat = - &ecryptfs_inode_to_private(file->f_dentry->d_inode)->crypt_stat; + crypt_stat = &ecryptfs_inode_to_private(file->f_path.dentry->d_inode) + ->crypt_stat; if (ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE)) { ecryptfs_printk(KERN_DEBUG, "ECRYPTFS_NEW_FILE flag set in " "crypt_stat at memory location [%p]\n", crypt_stat); diff --git a/fs/efs/dir.c b/fs/efs/dir.c index 17f5b2d3c16..b46c488eefc 100644 --- a/fs/efs/dir.c +++ b/fs/efs/dir.c @@ -20,7 +20,7 @@ struct inode_operations efs_dir_inode_operations = { }; static int efs_readdir(struct file *filp, void *dirent, filldir_t filldir) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct buffer_head *bh; struct efs_dir *dirblock; diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 88a6f8d0b88..3ae644e7e86 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -795,8 +795,8 @@ static int ep_getfd(int *efd, struct inode **einode, struct file **efile, goto eexit_4; dentry->d_op = &eventpollfs_dentry_operations; d_add(dentry, inode); - file->f_vfsmnt = mntget(eventpoll_mnt); - file->f_dentry = dentry; + file->f_path.mnt = mntget(eventpoll_mnt); + file->f_path.dentry = dentry; file->f_mapping = inode->i_mapping; file->f_pos = 0; diff --git a/fs/exec.c b/fs/exec.c index add0e03c3ea..12d8cd461b4 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -38,6 +38,7 @@ #include <linux/binfmts.h> #include <linux/swap.h> #include <linux/utsname.h> +#include <linux/pid_namespace.h> #include <linux/module.h> #include <linux/namei.h> #include <linux/proc_fs.h> @@ -620,8 +621,8 @@ static int de_thread(struct task_struct *tsk) * Reparenting needs write_lock on tasklist_lock, * so it is safe to do it under read_lock. */ - if (unlikely(tsk->group_leader == child_reaper)) - child_reaper = tsk; + if (unlikely(tsk->group_leader == child_reaper(tsk))) + tsk->nsproxy->pid_ns->child_reaper = tsk; zap_other_threads(tsk); read_unlock(&tasklist_lock); @@ -912,7 +913,7 @@ EXPORT_SYMBOL(flush_old_exec); int prepare_binprm(struct linux_binprm *bprm) { int mode; - struct inode * inode = bprm->file->f_dentry->d_inode; + struct inode * inode = bprm->file->f_path.dentry->d_inode; int retval; mode = inode->i_mode; @@ -922,7 +923,7 @@ int prepare_binprm(struct linux_binprm *bprm) bprm->e_uid = current->euid; bprm->e_gid = current->egid; - if(!(bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID)) { + if(!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) { /* Set-uid? */ if (mode & S_ISUID) { current->personality &= ~PER_CLEAR_ON_SETID; @@ -1519,10 +1520,10 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) 0600); if (IS_ERR(file)) goto fail_unlock; - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; if (inode->i_nlink > 1) goto close_fail; /* multiple links - don't dump */ - if (!ispipe && d_unhashed(file->f_dentry)) + if (!ispipe && d_unhashed(file->f_path.dentry)) goto close_fail; /* AK: actually i see no reason to not allow this for named pipes etc., @@ -1533,7 +1534,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) goto close_fail; if (!file->f_op->write) goto close_fail; - if (!ispipe && do_truncate(file->f_dentry, 0, 0, file) != 0) + if (!ispipe && do_truncate(file->f_path.dentry, 0, 0, file) != 0) goto close_fail; retval = binfmt->core_dump(signr, regs, file); diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c index 3e7a84a1e50..0b02ba9642d 100644 --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c @@ -248,7 +248,7 @@ static int ext2_readdir (struct file * filp, void * dirent, filldir_t filldir) { loff_t pos = filp->f_pos; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct super_block *sb = inode->i_sb; unsigned int offset = pos & ~PAGE_CACHE_MASK; unsigned long n = pos >> PAGE_CACHE_SHIFT; diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c index e3cf8c81507..4b099d31071 100644 --- a/fs/ext2/ioctl.c +++ b/fs/ext2/ioctl.c @@ -90,7 +90,7 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, #ifdef CONFIG_COMPAT long ext2_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int ret; /* These are just misnamed, they actually get/put from/to user an int */ diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 255cef5f742..6347c2dbdd8 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -597,8 +597,6 @@ static int ext2_check_descriptors (struct super_block * sb) return 1; } -#define log2(n) ffz(~(n)) - /* * Maximal file size. There is a direct, and {,double-,triple-}indirect * block limit, and also a limit of (2^32 - 1) 512-byte sectors in i_blocks. @@ -834,9 +832,9 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) sbi->s_sbh = bh; sbi->s_mount_state = le16_to_cpu(es->s_state); sbi->s_addr_per_block_bits = - log2 (EXT2_ADDR_PER_BLOCK(sb)); + ilog2 (EXT2_ADDR_PER_BLOCK(sb)); sbi->s_desc_per_block_bits = - log2 (EXT2_DESC_PER_BLOCK(sb)); + ilog2 (EXT2_DESC_PER_BLOCK(sb)); if (sb->s_magic != EXT2_SUPER_MAGIC) goto cantfind_ext2; diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index 5a9313ecd4e..665adee99b3 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c @@ -103,7 +103,7 @@ static int ext3_readdir(struct file * filp, struct ext3_dir_entry_2 *de; struct super_block *sb; int err; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; int ret = 0; sb = inode->i_sb; @@ -122,7 +122,7 @@ static int ext3_readdir(struct file * filp, * We don't set the inode dirty flag since it's not * critical that it get flushed back to the disk. */ - EXT3_I(filp->f_dentry->d_inode)->i_flags &= ~EXT3_INDEX_FL; + EXT3_I(filp->f_path.dentry->d_inode)->i_flags &= ~EXT3_INDEX_FL; } #endif stored = 0; @@ -402,7 +402,7 @@ static int call_filldir(struct file * filp, void * dirent, { struct dir_private_info *info = filp->private_data; loff_t curr_pos; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct super_block * sb; int error; @@ -432,7 +432,7 @@ static int ext3_dx_readdir(struct file * filp, void * dirent, filldir_t filldir) { struct dir_private_info *info = filp->private_data; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct fname *fname; int ret; diff --git a/fs/ext3/file.c b/fs/ext3/file.c index e96c388047e..881f6365c41 100644 --- a/fs/ext3/file.c +++ b/fs/ext3/file.c @@ -52,7 +52,7 @@ ext3_file_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { struct file *file = iocb->ki_filp; - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; ssize_t ret; int err; diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c index 12daa686957..9b8090d94e6 100644 --- a/fs/ext3/ioctl.c +++ b/fs/ext3/ioctl.c @@ -257,7 +257,7 @@ flags_err: #ifdef CONFIG_COMPAT long ext3_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int ret; /* These are just misnamed, they actually get/put from/to user an int */ diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 60d2f9dbdb0..4df39c4315e 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -602,7 +602,7 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash, dxtrace(printk("In htree_fill_tree, start hash: %x:%x\n", start_hash, start_minor_hash)); - dir = dir_file->f_dentry->d_inode; + dir = dir_file->f_path.dentry->d_inode; if (!(EXT3_I(dir)->i_flags & EXT3_INDEX_FL)) { hinfo.hash_version = EXT3_SB(dir->i_sb)->s_def_hash_version; hinfo.seed = EXT3_SB(dir->i_sb)->s_hash_seed; @@ -613,7 +613,7 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash, } hinfo.hash = start_hash; hinfo.minor_hash = 0; - frame = dx_probe(NULL, dir_file->f_dentry->d_inode, &hinfo, frames, &err); + frame = dx_probe(NULL, dir_file->f_path.dentry->d_inode, &hinfo, frames, &err); if (!frame) return err; diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 580b8a6ca97..b34886734a4 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -1347,8 +1347,6 @@ static void ext3_orphan_cleanup (struct super_block * sb, sb->s_flags = s_flags; /* Restore MS_RDONLY status */ } -#define log2(n) ffz(~(n)) - /* * Maximal file size. There is a direct, and {,double-,triple-}indirect * block limit, and also a limit of (2^32 - 1) 512-byte sectors in i_blocks. @@ -1597,8 +1595,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) sbi->s_desc_per_block = blocksize / sizeof(struct ext3_group_desc); sbi->s_sbh = bh; sbi->s_mount_state = le16_to_cpu(es->s_state); - sbi->s_addr_per_block_bits = log2(EXT3_ADDR_PER_BLOCK(sb)); - sbi->s_desc_per_block_bits = log2(EXT3_DESC_PER_BLOCK(sb)); + sbi->s_addr_per_block_bits = ilog2(EXT3_ADDR_PER_BLOCK(sb)); + sbi->s_desc_per_block_bits = ilog2(EXT3_DESC_PER_BLOCK(sb)); for (i=0; i < 4; i++) sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]); sbi->s_def_hash_version = es->s_def_hash_version; diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index f2ed3e7fb9f..da80368b66f 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c @@ -103,7 +103,7 @@ static int ext4_readdir(struct file * filp, struct ext4_dir_entry_2 *de; struct super_block *sb; int err; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; int ret = 0; sb = inode->i_sb; @@ -122,7 +122,7 @@ static int ext4_readdir(struct file * filp, * We don't set the inode dirty flag since it's not * critical that it get flushed back to the disk. */ - EXT4_I(filp->f_dentry->d_inode)->i_flags &= ~EXT4_INDEX_FL; + EXT4_I(filp->f_path.dentry->d_inode)->i_flags &= ~EXT4_INDEX_FL; } #endif stored = 0; @@ -402,7 +402,7 @@ static int call_filldir(struct file * filp, void * dirent, { struct dir_private_info *info = filp->private_data; loff_t curr_pos; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct super_block * sb; int error; @@ -432,7 +432,7 @@ static int ext4_dx_readdir(struct file * filp, void * dirent, filldir_t filldir) { struct dir_private_info *info = filp->private_data; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct fname *fname; int ret; diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 0b622c0624b..3bbc24b5878 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -52,7 +52,7 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { struct file *file = iocb->ki_filp; - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; ssize_t ret; int err; diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 1d85d4ec959..a127cc03c9f 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1232,7 +1232,7 @@ retry: from, to, NULL, do_journal_get_write_access); if (ret) /* fatal error, just put the handle and return */ - journal_stop(handle); + ext4_journal_stop(handle); } return ret; diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 22a737c306c..500567dd53b 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -256,7 +256,7 @@ flags_err: #ifdef CONFIG_COMPAT long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int ret; /* These are just misnamed, they actually get/put from/to user an int */ diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 859990eac50..e5a74a5ac26 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -602,7 +602,7 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash, dxtrace(printk("In htree_fill_tree, start hash: %x:%x\n", start_hash, start_minor_hash)); - dir = dir_file->f_dentry->d_inode; + dir = dir_file->f_path.dentry->d_inode; if (!(EXT4_I(dir)->i_flags & EXT4_INDEX_FL)) { hinfo.hash_version = EXT4_SB(dir->i_sb)->s_def_hash_version; hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed; @@ -613,7 +613,7 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash, } hinfo.hash = start_hash; hinfo.minor_hash = 0; - frame = dx_probe(NULL, dir_file->f_dentry->d_inode, &hinfo, frames, &err); + frame = dx_probe(NULL, dir_file->f_path.dentry->d_inode, &hinfo, frames, &err); if (!frame) return err; diff --git a/fs/fat/dir.c b/fs/fat/dir.c index 69c439f4438..c16af246d24 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c @@ -579,7 +579,7 @@ parse_record: if (!memcmp(de->name, MSDOS_DOT, MSDOS_NAME)) inum = inode->i_ino; else if (!memcmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) { - inum = parent_ino(filp->f_dentry); + inum = parent_ino(filp->f_path.dentry); } else { loff_t i_pos = fat_make_i_pos(sb, bh, de); struct inode *tmp = fat_iget(sb, i_pos); @@ -643,7 +643,7 @@ out: static int fat_readdir(struct file *filp, void *dirent, filldir_t filldir) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; return __fat_readdir(inode, filp, dirent, filldir, 0, 0); } @@ -782,7 +782,7 @@ static long fat_compat_dir_ioctl(struct file *file, unsigned cmd, set_fs(KERNEL_DS); lock_kernel(); - ret = fat_dir_ioctl(file->f_dentry->d_inode, file, + ret = fat_dir_ioctl(file->f_path.dentry->d_inode, file, cmd, (unsigned long) &d); unlock_kernel(); set_fs(oldfs); diff --git a/fs/fat/file.c b/fs/fat/file.c index 0aa813d944a..c1237b70c1f 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -92,7 +92,7 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp, } /* This MUST be done before doing anything irreversible... */ - err = notify_change(filp->f_dentry, &ia); + err = notify_change(filp->f_path.dentry, &ia); if (err) goto up; diff --git a/fs/fcntl.c b/fs/fcntl.c index 4740d35e52c..2bdaef35da5 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -204,7 +204,7 @@ asmlinkage long sys_dup(unsigned int fildes) static int setfl(int fd, struct file * filp, unsigned long arg) { - struct inode * inode = filp->f_dentry->d_inode; + struct inode * inode = filp->f_path.dentry->d_inode; int error = 0; /* diff --git a/fs/file_table.c b/fs/file_table.c index 24f25a057d9..4c17a18d8c1 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -152,8 +152,8 @@ EXPORT_SYMBOL(fput); */ void fastcall __fput(struct file *file) { - struct dentry *dentry = file->f_dentry; - struct vfsmount *mnt = file->f_vfsmnt; + struct dentry *dentry = file->f_path.dentry; + struct vfsmount *mnt = file->f_path.mnt; struct inode *inode = dentry->d_inode; might_sleep(); @@ -176,8 +176,8 @@ void fastcall __fput(struct file *file) put_write_access(inode); put_pid(file->f_owner.pid); file_kill(file); - file->f_dentry = NULL; - file->f_vfsmnt = NULL; + file->f_path.dentry = NULL; + file->f_path.mnt = NULL; file_free(file); dput(dentry); mntput(mnt); @@ -271,7 +271,7 @@ int fs_may_remount_ro(struct super_block *sb) file_list_lock(); list_for_each(p, &sb->s_files) { struct file *file = list_entry(p, struct file, f_u.fu_list); - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; /* File with pending delete? */ if (inode->i_nlink == 0) diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c index 43886fa00a2..3995d7fbeda 100644 --- a/fs/freevxfs/vxfs_lookup.c +++ b/fs/freevxfs/vxfs_lookup.c @@ -240,7 +240,7 @@ vxfs_lookup(struct inode *dip, struct dentry *dp, struct nameidata *nd) static int vxfs_readdir(struct file *fp, void *retp, filldir_t filler) { - struct inode *ip = fp->f_dentry->d_inode; + struct inode *ip = fp->f_path.dentry->d_inode; struct super_block *sbp = ip->i_sb; u_long bsize = sbp->s_blocksize; u_long page, npages, block, pblocks, nblocks, offset; diff --git a/fs/fuse/control.c b/fs/fuse/control.c index 16b39c053d4..8c58bd45399 100644 --- a/fs/fuse/control.c +++ b/fs/fuse/control.c @@ -23,7 +23,7 @@ static struct fuse_conn *fuse_ctl_file_conn_get(struct file *file) { struct fuse_conn *fc; mutex_lock(&fuse_mutex); - fc = file->f_dentry->d_inode->i_private; + fc = file->f_path.dentry->d_inode->i_private; if (fc) fc = fuse_conn_get(fc); mutex_unlock(&fuse_mutex); diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 1cabdb229ad..40080477ceb 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -856,7 +856,7 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) int err; size_t nbytes; struct page *page; - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_req *req; diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 128f79c4080..1387749201b 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -141,8 +141,8 @@ int fuse_release_common(struct inode *inode, struct file *file, int isdir) isdir ? FUSE_RELEASEDIR : FUSE_RELEASE); /* Hold vfsmount and dentry until release is finished */ - req->vfsmount = mntget(file->f_vfsmnt); - req->dentry = dget(file->f_dentry); + req->vfsmount = mntget(file->f_path.mnt); + req->dentry = dget(file->f_path.dentry); request_send_background(fc, req); } @@ -184,7 +184,7 @@ static u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id) static int fuse_flush(struct file *file, fl_owner_t id) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_file *ff = file->private_data; struct fuse_req *req; @@ -533,7 +533,7 @@ static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf, static ssize_t fuse_direct_io(struct file *file, const char __user *buf, size_t count, loff_t *ppos, int write) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct fuse_conn *fc = get_fuse_conn(inode); size_t nmax = write ? fc->max_write : fc->max_read; loff_t pos = *ppos; @@ -607,7 +607,7 @@ static ssize_t fuse_direct_read(struct file *file, char __user *buf, static ssize_t fuse_direct_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; ssize_t res; /* Don't allow parallel writes to the same file */ mutex_lock(&inode->i_mutex); @@ -662,7 +662,7 @@ static int convert_fuse_file_lock(const struct fuse_file_lock *ffl, static void fuse_lk_fill(struct fuse_req *req, struct file *file, const struct file_lock *fl, int opcode, pid_t pid) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_file *ff = file->private_data; struct fuse_lk_in *arg = &req->misc.lk_in; @@ -682,7 +682,7 @@ static void fuse_lk_fill(struct fuse_req *req, struct file *file, static int fuse_getlk(struct file *file, struct file_lock *fl) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_req *req; struct fuse_lk_out outarg; @@ -707,7 +707,7 @@ static int fuse_getlk(struct file *file, struct file_lock *fl) static int fuse_setlk(struct file *file, struct file_lock *fl) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_req *req; int opcode = (fl->fl_flags & FL_SLEEP) ? FUSE_SETLKW : FUSE_SETLK; @@ -734,7 +734,7 @@ static int fuse_setlk(struct file *file, struct file_lock *fl) static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct fuse_conn *fc = get_fuse_conn(inode); int err; diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c index b3f1e0349ae..faa07e4b97d 100644 --- a/fs/gfs2/ops_file.c +++ b/fs/gfs2/ops_file.c @@ -247,7 +247,7 @@ static const u32 gfs2_to_fsflags[32] = { static int gfs2_get_flags(struct file *filp, u32 __user *ptr) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_holder gh; int error; @@ -305,7 +305,7 @@ void gfs2_set_inode_flags(struct inode *inode) */ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); struct buffer_head *bh; @@ -588,7 +588,7 @@ static int do_flock(struct file *file, int cmd, struct file_lock *fl) { struct gfs2_file *fp = file->private_data; struct gfs2_holder *fl_gh = &fp->f_fl_gh; - struct gfs2_inode *ip = GFS2_I(file->f_dentry->d_inode); + struct gfs2_inode *ip = GFS2_I(file->f_path.dentry->d_inode); struct gfs2_glock *gl; unsigned int state; int flags; diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c index 37d681b4f21..e2e0358da33 100644 --- a/fs/hfs/dir.c +++ b/fs/hfs/dir.c @@ -53,7 +53,7 @@ done: */ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct super_block *sb = inode->i_sb; int len, err; char strbuf[HFS_MAX_NAMELEN]; diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index 02f5573e034..5cb7f8fee8d 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c @@ -102,7 +102,7 @@ static ssize_t hfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t offset, unsigned long nr_segs) { struct file *file = iocb->ki_filp; - struct inode *inode = file->f_dentry->d_inode->i_mapping->host; + struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host; return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, offset, nr_segs, hfs_get_block, NULL); diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index 7e309751645..e886ac8460d 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c @@ -111,7 +111,7 @@ fail: static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct super_block *sb = inode->i_sb; int len, err; char strbuf[HFSPLUS_MAX_STRLEN + 1]; diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index 9e367524963..75e8c4d8aac 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c @@ -97,7 +97,7 @@ static ssize_t hfsplus_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t offset, unsigned long nr_segs) { struct file *file = iocb->ki_filp; - struct inode *inode = file->f_dentry->d_inode->i_mapping->host; + struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host; return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, offset, nr_segs, hfsplus_get_block, NULL); diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index b6bd33ca373..1e6fc379987 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -35,7 +35,7 @@ static inline struct hostfs_inode_info *HOSTFS_I(struct inode *inode) return(list_entry(inode, struct hostfs_inode_info, vfs_inode)); } -#define FILE_HOSTFS_I(file) HOSTFS_I((file)->f_dentry->d_inode) +#define FILE_HOSTFS_I(file) HOSTFS_I((file)->f_path.dentry->d_inode) int hostfs_d_delete(struct dentry *dentry) { @@ -325,7 +325,7 @@ int hostfs_readdir(struct file *file, void *ent, filldir_t filldir) unsigned long long next, ino; int error, len; - name = dentry_name(file->f_dentry, 0); + name = dentry_name(file->f_path.dentry, 0); if(name == NULL) return(-ENOMEM); dir = open_dir(name, &error); kfree(name); @@ -366,7 +366,7 @@ int hostfs_file_open(struct inode *ino, struct file *file) if(w) r = 1; - name = dentry_name(file->f_dentry, 0); + name = dentry_name(file->f_path.dentry, 0); if(name == NULL) return(-ENOMEM); diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c index 594f9c428fc..6916c41d701 100644 --- a/fs/hpfs/dir.c +++ b/fs/hpfs/dir.c @@ -24,7 +24,7 @@ static loff_t hpfs_dir_lseek(struct file *filp, loff_t off, int whence) loff_t new_off = off + (whence == 1 ? filp->f_pos : 0); loff_t pos; struct quad_buffer_head qbh; - struct inode *i = filp->f_dentry->d_inode; + struct inode *i = filp->f_path.dentry->d_inode; struct hpfs_inode_info *hpfs_inode = hpfs_i(i); struct super_block *s = i->i_sb; @@ -52,7 +52,7 @@ fail: static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct hpfs_inode_info *hpfs_inode = hpfs_i(inode); struct quad_buffer_head qbh; struct hpfs_dirent *de; diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c index 8b94d24855f..fb4c8915010 100644 --- a/fs/hpfs/file.c +++ b/fs/hpfs/file.c @@ -115,7 +115,7 @@ static ssize_t hpfs_file_write(struct file *file, const char __user *buf, retval = do_sync_write(file, buf, count, ppos); if (retval > 0) - hpfs_i(file->f_dentry->d_inode)->i_dirty = 1; + hpfs_i(file->f_path.dentry->d_inode)->i_dirty = 1; return retval; } diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c index 642675fc394..afd340a45da 100644 --- a/fs/hppfs/hppfs_kern.c +++ b/fs/hppfs/hppfs_kern.c @@ -221,7 +221,7 @@ static ssize_t read_proc(struct file *file, char __user *buf, ssize_t count, ssize_t (*read)(struct file *, char __user *, size_t, loff_t *); ssize_t n; - read = file->f_dentry->d_inode->i_fop->read; + read = file->f_path.dentry->d_inode->i_fop->read; if(!is_user) set_fs(KERNEL_DS); @@ -320,7 +320,7 @@ static ssize_t hppfs_write(struct file *file, const char __user *buf, size_t len ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *); int err; - write = proc_file->f_dentry->d_inode->i_fop->write; + write = proc_file->f_path.dentry->d_inode->i_fop->write; proc_file->f_pos = file->f_pos; err = (*write)(proc_file, buf, len, &proc_file->f_pos); @@ -464,7 +464,7 @@ static int hppfs_open(struct inode *inode, struct file *file) if(data == NULL) goto out; - host_file = dentry_name(file->f_dentry, strlen("/rw")); + host_file = dentry_name(file->f_path.dentry, strlen("/rw")); if(host_file == NULL) goto out_free2; @@ -547,7 +547,7 @@ static loff_t hppfs_llseek(struct file *file, loff_t off, int where) loff_t (*llseek)(struct file *, loff_t, int); loff_t ret; - llseek = proc_file->f_dentry->d_inode->i_fop->llseek; + llseek = proc_file->f_path.dentry->d_inode->i_fop->llseek; if(llseek != NULL){ ret = (*llseek)(proc_file, off, where); if(ret < 0) @@ -591,10 +591,10 @@ static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir) struct hppfs_dirent dirent = ((struct hppfs_dirent) { .vfs_dirent = ent, .filldir = filldir, - .dentry = file->f_dentry } ); + .dentry = file->f_path.dentry } ); int err; - readdir = proc_file->f_dentry->d_inode->i_fop->readdir; + readdir = proc_file->f_path.dentry->d_inode->i_fop->readdir; proc_file->f_pos = file->f_pos; err = (*readdir)(proc_file, &dirent, hppfs_filldir); diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 0706f5aac6a..ed2c22340ad 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -58,7 +58,7 @@ static void huge_pagevec_release(struct pagevec *pvec) static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; loff_t len, vma_len; int ret; @@ -774,8 +774,8 @@ struct file *hugetlb_zero_setup(size_t size) d_instantiate(dentry, inode); inode->i_size = size; inode->i_nlink = 0; - file->f_vfsmnt = mntget(hugetlbfs_vfsmount); - file->f_dentry = dentry; + file->f_path.mnt = mntget(hugetlbfs_vfsmount); + file->f_path.dentry = dentry; file->f_mapping = inode->i_mapping; file->f_op = &hugetlbfs_file_operations; file->f_mode = FMODE_WRITE | FMODE_READ; diff --git a/fs/inode.c b/fs/inode.c index 9ecccab7326..d00de182ecb 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1200,7 +1200,7 @@ EXPORT_SYMBOL(touch_atime); void file_update_time(struct file *file) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct timespec now; int sync_it = 0; diff --git a/fs/inotify_user.c b/fs/inotify_user.c index e1956e6f116..55f6da55b7c 100644 --- a/fs/inotify_user.c +++ b/fs/inotify_user.c @@ -570,9 +570,9 @@ asmlinkage long sys_inotify_init(void) dev->ih = ih; filp->f_op = &inotify_fops; - filp->f_vfsmnt = mntget(inotify_mnt); - filp->f_dentry = dget(inotify_mnt->mnt_root); - filp->f_mapping = filp->f_dentry->d_inode->i_mapping; + filp->f_path.mnt = mntget(inotify_mnt); + filp->f_path.dentry = dget(inotify_mnt->mnt_root); + filp->f_mapping = filp->f_path.dentry->d_inode->i_mapping; filp->f_mode = FMODE_READ; filp->f_flags = O_RDONLY; filp->private_data = dev; diff --git a/fs/ioctl.c b/fs/ioctl.c index 4b7660b09ac..ff61772ceed 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -31,7 +31,7 @@ static long do_ioctl(struct file *filp, unsigned int cmd, goto out; } else if (filp->f_op->ioctl) { lock_kernel(); - error = filp->f_op->ioctl(filp->f_dentry->d_inode, + error = filp->f_op->ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); unlock_kernel(); } @@ -45,7 +45,7 @@ static int file_ioctl(struct file *filp, unsigned int cmd, { int error; int block; - struct inode * inode = filp->f_dentry->d_inode; + struct inode * inode = filp->f_path.dentry->d_inode; int __user *p = (int __user *)arg; switch (cmd) { @@ -137,17 +137,17 @@ int vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, unsigned lon break; case FIOQSIZE: - if (S_ISDIR(filp->f_dentry->d_inode->i_mode) || - S_ISREG(filp->f_dentry->d_inode->i_mode) || - S_ISLNK(filp->f_dentry->d_inode->i_mode)) { - loff_t res = inode_get_bytes(filp->f_dentry->d_inode); + if (S_ISDIR(filp->f_path.dentry->d_inode->i_mode) || + S_ISREG(filp->f_path.dentry->d_inode->i_mode) || + S_ISLNK(filp->f_path.dentry->d_inode->i_mode)) { + loff_t res = inode_get_bytes(filp->f_path.dentry->d_inode); error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT : 0; } else error = -ENOTTY; break; default: - if (S_ISREG(filp->f_dentry->d_inode->i_mode)) + if (S_ISREG(filp->f_path.dentry->d_inode->i_mode)) error = file_ioctl(filp, cmd, arg); else error = do_ioctl(filp, cmd, arg); diff --git a/fs/isofs/compress.c b/fs/isofs/compress.c index 731816332b1..6bbbdb53581 100644 --- a/fs/isofs/compress.c +++ b/fs/isofs/compress.c @@ -42,7 +42,7 @@ static struct semaphore zisofs_zlib_semaphore; */ static int zisofs_readpage(struct file *file, struct page *page) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct address_space *mapping = inode->i_mapping; unsigned int maxpage, xpage, fpage, blockindex; unsigned long offset; diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c index 27e276987fd..4af2548f97a 100644 --- a/fs/isofs/dir.c +++ b/fs/isofs/dir.c @@ -183,7 +183,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, /* Handle the case of the '..' directory */ if (de->name_len[0] == 1 && de->name[0] == 1) { - inode_number = parent_ino(filp->f_dentry); + inode_number = parent_ino(filp->f_path.dentry); if (filldir(dirent, "..", 2, filp->f_pos, inode_number, DT_DIR) < 0) break; filp->f_pos += de_len; @@ -255,8 +255,7 @@ static int isofs_readdir(struct file *filp, int result; char * tmpname; struct iso_directory_record * tmpde; - struct inode *inode = filp->f_dentry->d_inode; - + struct inode *inode = filp->f_path.dentry->d_inode; tmpname = (char *)__get_free_page(GFP_KERNEL); if (tmpname == NULL) diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c index 9f15bce9202..7b40c69f44e 100644 --- a/fs/jffs/inode-v23.c +++ b/fs/jffs/inode-v23.c @@ -566,7 +566,7 @@ static int jffs_readdir(struct file *filp, void *dirent, filldir_t filldir) { struct jffs_file *f; - struct dentry *dentry = filp->f_dentry; + struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; struct jffs_control *c = (struct jffs_control *)inode->i_sb->s_fs_info; int j; @@ -1372,7 +1372,7 @@ jffs_file_write(struct file *filp, const char *buf, size_t count, struct jffs_control *c; struct jffs_file *f; struct jffs_node *node; - struct dentry *dentry = filp->f_dentry; + struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; int recoverable = 0; size_t written = 0; @@ -1380,7 +1380,7 @@ jffs_file_write(struct file *filp, const char *buf, size_t count, loff_t pos = *ppos; int err; - inode = filp->f_dentry->d_inode; + inode = filp->f_path.dentry->d_inode; D2(printk("***jffs_file_write(): inode: 0x%p (ino: %lu), " "filp: 0x%p, buf: 0x%p, count: %d\n", diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 9def6adf4a5..da6034d5071 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c @@ -123,11 +123,11 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir) { struct jffs2_inode_info *f; struct jffs2_sb_info *c; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct jffs2_full_dirent *fd; unsigned long offset, curofs; - D1(printk(KERN_DEBUG "jffs2_readdir() for dir_i #%lu\n", filp->f_dentry->d_inode->i_ino)); + D1(printk(KERN_DEBUG "jffs2_readdir() for dir_i #%lu\n", filp->f_path.dentry->d_inode->i_ino)); f = JFFS2_INODE_INFO(inode); c = JFFS2_SB_INFO(inode->i_sb); @@ -141,7 +141,7 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir) offset++; } if (offset == 1) { - unsigned long pino = parent_ino(filp->f_dentry); + unsigned long pino = parent_ino(filp->f_path.dentry); D1(printk(KERN_DEBUG "Dirent 1: \"..\", ino #%lu\n", pino)); if (filldir(dirent, "..", 2, 1, pino, DT_DIR) < 0) goto out; diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c index ecb2216d881..47bc0b5d132 100644 --- a/fs/jfs/jfs_dtree.c +++ b/fs/jfs/jfs_dtree.c @@ -3009,7 +3009,7 @@ static inline struct jfs_dirent *next_jfs_dirent(struct jfs_dirent *dirent) */ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir) { - struct inode *ip = filp->f_dentry->d_inode; + struct inode *ip = filp->f_path.dentry->d_inode; struct nls_table *codepage = JFS_SBI(ip->i_sb)->nls_tab; int rc = 0; loff_t dtpos; /* legacy OS/2 style position */ diff --git a/fs/libfs.c b/fs/libfs.c index bd08e0e64a8..503898d5c4a 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -63,7 +63,7 @@ int dcache_dir_open(struct inode *inode, struct file *file) { static struct qstr cursor_name = {.len = 1, .name = "."}; - file->private_data = d_alloc(file->f_dentry, &cursor_name); + file->private_data = d_alloc(file->f_path.dentry, &cursor_name); return file->private_data ? 0 : -ENOMEM; } @@ -76,7 +76,7 @@ int dcache_dir_close(struct inode *inode, struct file *file) loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin) { - mutex_lock(&file->f_dentry->d_inode->i_mutex); + mutex_lock(&file->f_path.dentry->d_inode->i_mutex); switch (origin) { case 1: offset += file->f_pos; @@ -84,7 +84,7 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin) if (offset >= 0) break; default: - mutex_unlock(&file->f_dentry->d_inode->i_mutex); + mutex_unlock(&file->f_path.dentry->d_inode->i_mutex); return -EINVAL; } if (offset != file->f_pos) { @@ -96,8 +96,8 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin) spin_lock(&dcache_lock); list_del(&cursor->d_u.d_child); - p = file->f_dentry->d_subdirs.next; - while (n && p != &file->f_dentry->d_subdirs) { + p = file->f_path.dentry->d_subdirs.next; + while (n && p != &file->f_path.dentry->d_subdirs) { struct dentry *next; next = list_entry(p, struct dentry, d_u.d_child); if (!d_unhashed(next) && next->d_inode) @@ -108,7 +108,7 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin) spin_unlock(&dcache_lock); } } - mutex_unlock(&file->f_dentry->d_inode->i_mutex); + mutex_unlock(&file->f_path.dentry->d_inode->i_mutex); return offset; } @@ -126,7 +126,7 @@ static inline unsigned char dt_type(struct inode *inode) int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir) { - struct dentry *dentry = filp->f_dentry; + struct dentry *dentry = filp->f_path.dentry; struct dentry *cursor = filp->private_data; struct list_head *p, *q = &cursor->d_u.d_child; ino_t ino; diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index b85a0ad2cfb..92681c9e9b2 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c @@ -126,7 +126,7 @@ __be32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock continue; if (!nlm_cmp_addr(&block->b_host->h_addr, addr)) continue; - if (nfs_compare_fh(NFS_FH(fl_blocked->fl_file->f_dentry->d_inode) ,fh) != 0) + if (nfs_compare_fh(NFS_FH(fl_blocked->fl_file->f_path.dentry->d_inode) ,fh) != 0) continue; /* Alright, we found a lock. Set the return status * and wake up the caller diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 497c3cd59d5..80a1a6dccc8 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -129,7 +129,7 @@ static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl) nlmclnt_next_cookie(&argp->cookie); argp->state = nsm_local_state; - memcpy(&lock->fh, NFS_FH(fl->fl_file->f_dentry->d_inode), sizeof(struct nfs_fh)); + memcpy(&lock->fh, NFS_FH(fl->fl_file->f_path.dentry->d_inode), sizeof(struct nfs_fh)); lock->caller = utsname()->nodename; lock->oh.data = req->a_owner; lock->oh.len = snprintf(req->a_owner, sizeof(req->a_owner), "%u@%s", diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 7e219b93855..5c054b20fd5 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -343,8 +343,8 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, __be32 ret; dprintk("lockd: nlmsvc_lock(%s/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n", - file->f_file->f_dentry->d_inode->i_sb->s_id, - file->f_file->f_dentry->d_inode->i_ino, + file->f_file->f_path.dentry->d_inode->i_sb->s_id, + file->f_file->f_path.dentry->d_inode->i_ino, lock->fl.fl_type, lock->fl.fl_pid, (long long)lock->fl.fl_start, (long long)lock->fl.fl_end, @@ -420,8 +420,8 @@ nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock, struct nlm_lock *conflock) { dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n", - file->f_file->f_dentry->d_inode->i_sb->s_id, - file->f_file->f_dentry->d_inode->i_ino, + file->f_file->f_path.dentry->d_inode->i_sb->s_id, + file->f_file->f_path.dentry->d_inode->i_ino, lock->fl.fl_type, (long long)lock->fl.fl_start, (long long)lock->fl.fl_end); @@ -454,8 +454,8 @@ nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock) int error; dprintk("lockd: nlmsvc_unlock(%s/%ld, pi=%d, %Ld-%Ld)\n", - file->f_file->f_dentry->d_inode->i_sb->s_id, - file->f_file->f_dentry->d_inode->i_ino, + file->f_file->f_path.dentry->d_inode->i_sb->s_id, + file->f_file->f_path.dentry->d_inode->i_ino, lock->fl.fl_pid, (long long)lock->fl.fl_start, (long long)lock->fl.fl_end); @@ -483,8 +483,8 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock) int status = 0; dprintk("lockd: nlmsvc_cancel(%s/%ld, pi=%d, %Ld-%Ld)\n", - file->f_file->f_dentry->d_inode->i_sb->s_id, - file->f_file->f_dentry->d_inode->i_ino, + file->f_file->f_path.dentry->d_inode->i_sb->s_id, + file->f_file->f_path.dentry->d_inode->i_ino, lock->fl.fl_pid, (long long)lock->fl.fl_start, (long long)lock->fl.fl_end); diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c index e83024e1604..c0df00c74ce 100644 --- a/fs/lockd/svcsubs.c +++ b/fs/lockd/svcsubs.c @@ -43,7 +43,7 @@ static inline void nlm_debug_print_fh(char *msg, struct nfs_fh *f) static inline void nlm_debug_print_file(char *msg, struct nlm_file *file) { - struct inode *inode = file->f_file->f_dentry->d_inode; + struct inode *inode = file->f_file->f_path.dentry->d_inode; dprintk("lockd: %s %s/%ld\n", msg, inode->i_sb->s_id, inode->i_ino); diff --git a/fs/locks.c b/fs/locks.c index 1cb0c57fedb..52a81005dab 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -321,7 +321,7 @@ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl, start = filp->f_pos; break; case SEEK_END: - start = i_size_read(filp->f_dentry->d_inode); + start = i_size_read(filp->f_path.dentry->d_inode); break; default: return -EINVAL; @@ -371,7 +371,7 @@ static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl, start = filp->f_pos; break; case SEEK_END: - start = i_size_read(filp->f_dentry->d_inode); + start = i_size_read(filp->f_path.dentry->d_inode); break; default: return -EINVAL; @@ -672,7 +672,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl, struct file_lock *cfl; lock_kernel(); - for (cfl = filp->f_dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) { + for (cfl = filp->f_path.dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) { if (!IS_POSIX(cfl)) continue; if (posix_locks_conflict(cfl, fl)) @@ -734,7 +734,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *request) { struct file_lock *new_fl = NULL; struct file_lock **before; - struct inode * inode = filp->f_dentry->d_inode; + struct inode * inode = filp->f_path.dentry->d_inode; int error = 0; int found = 0; @@ -1018,7 +1018,7 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request */ int posix_lock_file(struct file *filp, struct file_lock *fl) { - return __posix_lock_file_conf(filp->f_dentry->d_inode, fl, NULL); + return __posix_lock_file_conf(filp->f_path.dentry->d_inode, fl, NULL); } EXPORT_SYMBOL(posix_lock_file); @@ -1033,7 +1033,7 @@ EXPORT_SYMBOL(posix_lock_file); int posix_lock_file_conf(struct file *filp, struct file_lock *fl, struct file_lock *conflock) { - return __posix_lock_file_conf(filp->f_dentry->d_inode, fl, conflock); + return __posix_lock_file_conf(filp->f_path.dentry->d_inode, fl, conflock); } EXPORT_SYMBOL(posix_lock_file_conf); @@ -1333,8 +1333,8 @@ int fcntl_getlease(struct file *filp) int type = F_UNLCK; lock_kernel(); - time_out_leases(filp->f_dentry->d_inode); - for (fl = filp->f_dentry->d_inode->i_flock; fl && IS_LEASE(fl); + time_out_leases(filp->f_path.dentry->d_inode); + for (fl = filp->f_path.dentry->d_inode->i_flock; fl && IS_LEASE(fl); fl = fl->fl_next) { if (fl->fl_file == filp) { type = fl->fl_type & ~F_INPROGRESS; @@ -1359,7 +1359,7 @@ int fcntl_getlease(struct file *filp) static int __setlease(struct file *filp, long arg, struct file_lock **flp) { struct file_lock *fl, **before, **my_before = NULL, *lease; - struct dentry *dentry = filp->f_dentry; + struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; int error, rdlease_count = 0, wrlease_count = 0; @@ -1448,7 +1448,7 @@ out: int setlease(struct file *filp, long arg, struct file_lock **lease) { - struct dentry *dentry = filp->f_dentry; + struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; int error; @@ -1482,7 +1482,7 @@ EXPORT_SYMBOL(setlease); int fcntl_setlease(unsigned int fd, struct file *filp, long arg) { struct file_lock fl, *flp = &fl; - struct dentry *dentry = filp->f_dentry; + struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; int error; @@ -1692,7 +1692,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd, if (copy_from_user(&flock, l, sizeof(flock))) goto out; - inode = filp->f_dentry->d_inode; + inode = filp->f_path.dentry->d_inode; /* Don't allow mandatory locks on files that may be memory mapped * and shared. @@ -1835,7 +1835,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd, if (copy_from_user(&flock, l, sizeof(flock))) goto out; - inode = filp->f_dentry->d_inode; + inode = filp->f_path.dentry->d_inode; /* Don't allow mandatory locks on files that may be memory mapped * and shared. @@ -1922,7 +1922,7 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner) * posix_lock_file(). Another process could be setting a lock on this * file at the same time, but we wouldn't remove that lock anyway. */ - if (!filp->f_dentry->d_inode->i_flock) + if (!filp->f_path.dentry->d_inode->i_flock) return; lock.fl_type = F_UNLCK; @@ -1951,7 +1951,7 @@ EXPORT_SYMBOL(locks_remove_posix); */ void locks_remove_flock(struct file *filp) { - struct inode * inode = filp->f_dentry->d_inode; + struct inode * inode = filp->f_path.dentry->d_inode; struct file_lock *fl; struct file_lock **before; @@ -2020,7 +2020,7 @@ static void lock_get_status(char* out, struct file_lock *fl, int id, char *pfx) struct inode *inode = NULL; if (fl->fl_file != NULL) - inode = fl->fl_file->f_dentry->d_inode; + inode = fl->fl_file->f_path.dentry->d_inode; out += sprintf(out, "%d:%s ", id, pfx); if (IS_POSIX(fl)) { diff --git a/fs/minix/dir.c b/fs/minix/dir.c index 2b0a389d198..ab782c4086f 100644 --- a/fs/minix/dir.c +++ b/fs/minix/dir.c @@ -82,7 +82,7 @@ static inline void *minix_next_entry(void *de, struct minix_sb_info *sbi) static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir) { unsigned long pos = filp->f_pos; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct super_block *sb = inode->i_sb; unsigned offset = pos & ~PAGE_CACHE_MASK; unsigned long n = pos >> PAGE_CACHE_SHIFT; diff --git a/fs/namei.c b/fs/namei.c index db1bca26d88..e4f108f0823 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -297,7 +297,7 @@ int vfs_permission(struct nameidata *nd, int mask) */ int file_permission(struct file *file, int mask) { - return permission(file->f_dentry->d_inode, mask, NULL); + return permission(file->f_path.dentry->d_inode, mask, NULL); } /* @@ -333,7 +333,7 @@ int get_write_access(struct inode * inode) int deny_write_access(struct file * file) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; spin_lock(&inode->i_lock); if (atomic_read(&inode->i_writecount) > 0) { @@ -368,7 +368,7 @@ void path_release_on_umount(struct nameidata *nd) */ void release_open_intent(struct nameidata *nd) { - if (nd->intent.open.file->f_dentry == NULL) + if (nd->intent.open.file->f_path.dentry == NULL) put_filp(nd->intent.open.file); else fput(nd->intent.open.file); @@ -572,11 +572,6 @@ fail: return PTR_ERR(link); } -struct path { - struct vfsmount *mnt; - struct dentry *dentry; -}; - static inline void dput_path(struct path *path, struct nameidata *nd) { dput(path->dentry); @@ -1143,7 +1138,7 @@ static int fastcall do_path_lookup(int dfd, const char *name, if (!file) goto out_fail; - dentry = file->f_dentry; + dentry = file->f_path.dentry; retval = -ENOTDIR; if (!S_ISDIR(dentry->d_inode->i_mode)) @@ -1153,7 +1148,7 @@ static int fastcall do_path_lookup(int dfd, const char *name, if (retval) goto fput_fail; - nd->mnt = mntget(file->f_vfsmnt); + nd->mnt = mntget(file->f_path.mnt); nd->dentry = dget(dentry); fput_light(file, fput_needed); diff --git a/fs/namespace.c b/fs/namespace.c index b00ac84ebbd..fde8553faa7 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -20,7 +20,7 @@ #include <linux/module.h> #include <linux/sysfs.h> #include <linux/seq_file.h> -#include <linux/namespace.h> +#include <linux/mnt_namespace.h> #include <linux/namei.h> #include <linux/security.h> #include <linux/mount.h> @@ -133,10 +133,10 @@ struct vfsmount *lookup_mnt(struct vfsmount *mnt, struct dentry *dentry) static inline int check_mnt(struct vfsmount *mnt) { - return mnt->mnt_namespace == current->nsproxy->namespace; + return mnt->mnt_ns == current->nsproxy->mnt_ns; } -static void touch_namespace(struct namespace *ns) +static void touch_mnt_namespace(struct mnt_namespace *ns) { if (ns) { ns->event = ++event; @@ -144,7 +144,7 @@ static void touch_namespace(struct namespace *ns) } } -static void __touch_namespace(struct namespace *ns) +static void __touch_mnt_namespace(struct mnt_namespace *ns) { if (ns && ns->event != event) { ns->event = event; @@ -187,19 +187,19 @@ static void commit_tree(struct vfsmount *mnt) struct vfsmount *parent = mnt->mnt_parent; struct vfsmount *m; LIST_HEAD(head); - struct namespace *n = parent->mnt_namespace; + struct mnt_namespace *n = parent->mnt_ns; BUG_ON(parent == mnt); list_add_tail(&head, &mnt->mnt_list); list_for_each_entry(m, &head, mnt_list) - m->mnt_namespace = n; + m->mnt_ns = n; list_splice(&head, n->list.prev); list_add_tail(&mnt->mnt_hash, mount_hashtable + hash(parent, mnt->mnt_mountpoint)); list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); - touch_namespace(n); + touch_mnt_namespace(n); } static struct vfsmount *next_mnt(struct vfsmount *p, struct vfsmount *root) @@ -320,7 +320,7 @@ EXPORT_SYMBOL(mnt_unpin); /* iterator */ static void *m_start(struct seq_file *m, loff_t *pos) { - struct namespace *n = m->private; + struct mnt_namespace *n = m->private; struct list_head *p; loff_t l = *pos; @@ -333,7 +333,7 @@ static void *m_start(struct seq_file *m, loff_t *pos) static void *m_next(struct seq_file *m, void *v, loff_t *pos) { - struct namespace *n = m->private; + struct mnt_namespace *n = m->private; struct list_head *p = ((struct vfsmount *)v)->mnt_list.next; (*pos)++; return p == &n->list ? NULL : list_entry(p, struct vfsmount, mnt_list); @@ -526,8 +526,8 @@ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill) list_for_each_entry(p, kill, mnt_hash) { list_del_init(&p->mnt_expire); list_del_init(&p->mnt_list); - __touch_namespace(p->mnt_namespace); - p->mnt_namespace = NULL; + __touch_mnt_namespace(p->mnt_ns); + p->mnt_ns = NULL; list_del_init(&p->mnt_child); if (p->mnt_parent != p) p->mnt_mountpoint->d_mounted--; @@ -830,7 +830,7 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt, if (parent_nd) { detach_mnt(source_mnt, parent_nd); attach_mnt(source_mnt, nd); - touch_namespace(current->nsproxy->namespace); + touch_mnt_namespace(current->nsproxy->mnt_ns); } else { mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt); commit_tree(source_mnt); @@ -1145,9 +1145,9 @@ static void expire_mount(struct vfsmount *mnt, struct list_head *mounts, */ if (!propagate_mount_busy(mnt, 2)) { /* delete from the namespace */ - touch_namespace(mnt->mnt_namespace); + touch_mnt_namespace(mnt->mnt_ns); list_del_init(&mnt->mnt_list); - mnt->mnt_namespace = NULL; + mnt->mnt_ns = NULL; umount_tree(mnt, 1, umounts); spin_unlock(&vfsmount_lock); } else { @@ -1168,7 +1168,7 @@ static void expire_mount(struct vfsmount *mnt, struct list_head *mounts, */ static void expire_mount_list(struct list_head *graveyard, struct list_head *mounts) { - struct namespace *namespace; + struct mnt_namespace *ns; struct vfsmount *mnt; while (!list_empty(graveyard)) { @@ -1178,10 +1178,10 @@ static void expire_mount_list(struct list_head *graveyard, struct list_head *mou /* don't do anything if the namespace is dead - all the * vfsmounts from it are going away anyway */ - namespace = mnt->mnt_namespace; - if (!namespace || !namespace->root) + ns = mnt->mnt_ns; + if (!ns || !ns->root) continue; - get_namespace(namespace); + get_mnt_ns(ns); spin_unlock(&vfsmount_lock); down_write(&namespace_sem); @@ -1189,7 +1189,7 @@ static void expire_mount_list(struct list_head *graveyard, struct list_head *mou up_write(&namespace_sem); release_mounts(&umounts); mntput(mnt); - put_namespace(namespace); + put_mnt_ns(ns); spin_lock(&vfsmount_lock); } } @@ -1439,14 +1439,15 @@ dput_out: * Allocate a new namespace structure and populate it with contents * copied from the namespace of the passed in task structure. */ -struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs) +struct mnt_namespace *dup_mnt_ns(struct task_struct *tsk, + struct fs_struct *fs) { - struct namespace *namespace = tsk->nsproxy->namespace; - struct namespace *new_ns; + struct mnt_namespace *mnt_ns = tsk->nsproxy->mnt_ns; + struct mnt_namespace *new_ns; struct vfsmount *rootmnt = NULL, *pwdmnt = NULL, *altrootmnt = NULL; struct vfsmount *p, *q; - new_ns = kmalloc(sizeof(struct namespace), GFP_KERNEL); + new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL); if (!new_ns) return NULL; @@ -1457,7 +1458,7 @@ struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs) down_write(&namespace_sem); /* First pass: copy the tree topology */ - new_ns->root = copy_tree(namespace->root, namespace->root->mnt_root, + new_ns->root = copy_tree(mnt_ns->root, mnt_ns->root->mnt_root, CL_COPY_ALL | CL_EXPIRE); if (!new_ns->root) { up_write(&namespace_sem); @@ -1473,10 +1474,10 @@ struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs) * as belonging to new namespace. We have already acquired a private * fs_struct, so tsk->fs->lock is not needed. */ - p = namespace->root; + p = mnt_ns->root; q = new_ns->root; while (p) { - q->mnt_namespace = new_ns; + q->mnt_ns = new_ns; if (fs) { if (p == fs->rootmnt) { rootmnt = p; @@ -1491,7 +1492,7 @@ struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs) fs->altrootmnt = mntget(q); } } - p = next_mnt(p, namespace->root); + p = next_mnt(p, mnt_ns->root); q = next_mnt(q, new_ns->root); } up_write(&namespace_sem); @@ -1506,16 +1507,16 @@ struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs) return new_ns; } -int copy_namespace(int flags, struct task_struct *tsk) +int copy_mnt_ns(int flags, struct task_struct *tsk) { - struct namespace *namespace = tsk->nsproxy->namespace; - struct namespace *new_ns; + struct mnt_namespace *ns = tsk->nsproxy->mnt_ns; + struct mnt_namespace *new_ns; int err = 0; - if (!namespace) + if (!ns) return 0; - get_namespace(namespace); + get_mnt_ns(ns); if (!(flags & CLONE_NEWNS)) return 0; @@ -1525,16 +1526,16 @@ int copy_namespace(int flags, struct task_struct *tsk) goto out; } - new_ns = dup_namespace(tsk, tsk->fs); + new_ns = dup_mnt_ns(tsk, tsk->fs); if (!new_ns) { err = -ENOMEM; goto out; } - tsk->nsproxy->namespace = new_ns; + tsk->nsproxy->mnt_ns = new_ns; out: - put_namespace(namespace); + put_mnt_ns(ns); return err; } @@ -1754,7 +1755,7 @@ asmlinkage long sys_pivot_root(const char __user * new_root, detach_mnt(user_nd.mnt, &root_parent); attach_mnt(user_nd.mnt, &old_nd); /* mount old root on put_old */ attach_mnt(new_nd.mnt, &root_parent); /* mount new_root on / */ - touch_namespace(current->nsproxy->namespace); + touch_mnt_namespace(current->nsproxy->mnt_ns); spin_unlock(&vfsmount_lock); chroot_fs_refs(&user_nd, &new_nd); security_sb_post_pivotroot(&user_nd, &new_nd); @@ -1779,27 +1780,27 @@ out3: static void __init init_mount_tree(void) { struct vfsmount *mnt; - struct namespace *namespace; + struct mnt_namespace *ns; mnt = do_kern_mount("rootfs", 0, "rootfs", NULL); if (IS_ERR(mnt)) panic("Can't create rootfs"); - namespace = kmalloc(sizeof(*namespace), GFP_KERNEL); - if (!namespace) + ns = kmalloc(sizeof(*ns), GFP_KERNEL); + if (!ns) panic("Can't allocate initial namespace"); - atomic_set(&namespace->count, 1); - INIT_LIST_HEAD(&namespace->list); - init_waitqueue_head(&namespace->poll); - namespace->event = 0; - list_add(&mnt->mnt_list, &namespace->list); - namespace->root = mnt; - mnt->mnt_namespace = namespace; - - init_task.nsproxy->namespace = namespace; - get_namespace(namespace); - - set_fs_pwd(current->fs, namespace->root, namespace->root->mnt_root); - set_fs_root(current->fs, namespace->root, namespace->root->mnt_root); + atomic_set(&ns->count, 1); + INIT_LIST_HEAD(&ns->list); + init_waitqueue_head(&ns->poll); + ns->event = 0; + list_add(&mnt->mnt_list, &ns->list); + ns->root = mnt; + mnt->mnt_ns = ns; + + init_task.nsproxy->mnt_ns = ns; + get_mnt_ns(ns); + + set_fs_pwd(current->fs, ns->root, ns->root->mnt_root); + set_fs_root(current->fs, ns->root, ns->root->mnt_root); } void __init mnt_init(unsigned long mempages) @@ -1860,11 +1861,11 @@ void __init mnt_init(unsigned long mempages) init_mount_tree(); } -void __put_namespace(struct namespace *namespace) +void __put_mnt_ns(struct mnt_namespace *ns) { - struct vfsmount *root = namespace->root; + struct vfsmount *root = ns->root; LIST_HEAD(umount_list); - namespace->root = NULL; + ns->root = NULL; spin_unlock(&vfsmount_lock); down_write(&namespace_sem); spin_lock(&vfsmount_lock); @@ -1872,5 +1873,5 @@ void __put_namespace(struct namespace *namespace) spin_unlock(&vfsmount_lock); up_write(&namespace_sem); release_mounts(&umount_list); - kfree(namespace); + kfree(ns); } diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c index 458b3b78519..73747772c3b 100644 --- a/fs/ncpfs/dir.c +++ b/fs/ncpfs/dir.c @@ -402,7 +402,7 @@ static time_t ncp_obtain_mtime(struct dentry *dentry) static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir) { - struct dentry *dentry = filp->f_dentry; + struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; struct page *page = NULL; struct ncp_server *server = NCP_SERVER(inode); @@ -554,7 +554,7 @@ static int ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir, struct ncp_cache_control *ctrl, struct ncp_entry_info *entry) { - struct dentry *newdent, *dentry = filp->f_dentry; + struct dentry *newdent, *dentry = filp->f_path.dentry; struct inode *newino, *inode = dentry->d_inode; struct ncp_cache_control ctl = *ctrl; struct qstr qname; @@ -649,7 +649,7 @@ static void ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir, struct ncp_cache_control *ctl) { - struct dentry *dentry = filp->f_dentry; + struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; struct ncp_server *server = NCP_SERVER(inode); struct ncp_volume_info info; @@ -685,7 +685,7 @@ static void ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir, struct ncp_cache_control *ctl) { - struct dentry *dentry = filp->f_dentry; + struct dentry *dentry = filp->f_path.dentry; struct inode *dir = dentry->d_inode; struct ncp_server *server = NCP_SERVER(dir); struct nw_search_sequence seq; diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c index df37524b85d..b91fea03b1c 100644 --- a/fs/ncpfs/file.c +++ b/fs/ncpfs/file.c @@ -101,7 +101,7 @@ out: static ssize_t ncp_file_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct dentry *dentry = file->f_dentry; + struct dentry *dentry = file->f_path.dentry; struct inode *inode = dentry->d_inode; size_t already_read = 0; off_t pos; @@ -182,7 +182,7 @@ outrel: static ssize_t ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - struct dentry *dentry = file->f_dentry; + struct dentry *dentry = file->f_path.dentry; struct inode *inode = dentry->d_inode; size_t already_written = 0; off_t pos; diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index fae53243bb9..47462ac9447 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -471,7 +471,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) if (!ncp_filp) goto out; error = -ENOTSOCK; - sock_inode = ncp_filp->f_dentry->d_inode; + sock_inode = ncp_filp->f_path.dentry->d_inode; if (!S_ISSOCK(sock_inode->i_mode)) goto out_fput; sock = SOCKET_I(sock_inode); @@ -504,7 +504,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) if (!server->info_filp) goto out_fput; error = -ENOTSOCK; - sock_inode = server->info_filp->f_dentry->d_inode; + sock_inode = server->info_filp->f_path.dentry->d_inode; if (!S_ISSOCK(sock_inode->i_mode)) goto out_fput2; info_sock = SOCKET_I(sock_inode); diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c index 589d1eac55c..8843a83d4ef 100644 --- a/fs/ncpfs/ioctl.c +++ b/fs/ncpfs/ioctl.c @@ -35,7 +35,7 @@ static int ncp_get_fs_info(struct ncp_server * server, struct file *file, struct ncp_fs_info __user *arg) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct ncp_fs_info info; if ((file_permission(file, MAY_WRITE) != 0) @@ -65,7 +65,7 @@ static int ncp_get_fs_info_v2(struct ncp_server * server, struct file *file, struct ncp_fs_info_v2 __user * arg) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct ncp_fs_info_v2 info2; if ((file_permission(file, MAY_WRITE) != 0) @@ -136,7 +136,7 @@ static int ncp_get_compat_fs_info_v2(struct ncp_server * server, struct file *file, struct compat_ncp_fs_info_v2 __user * arg) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct compat_ncp_fs_info_v2 info2; if ((file_permission(file, MAY_WRITE) != 0) @@ -824,7 +824,7 @@ outrel: #ifdef CONFIG_COMPAT long ncp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int ret; lock_kernel(); diff --git a/fs/ncpfs/mmap.c b/fs/ncpfs/mmap.c index e7d5a3097fe..70a69115500 100644 --- a/fs/ncpfs/mmap.c +++ b/fs/ncpfs/mmap.c @@ -29,7 +29,7 @@ static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area, unsigned long address, int *type) { struct file *file = area->vm_file; - struct dentry *dentry = file->f_dentry; + struct dentry *dentry = file->f_path.dentry; struct inode *inode = dentry->d_inode; struct page* page; char *pg_addr; @@ -106,7 +106,7 @@ static struct vm_operations_struct ncp_file_mmap = /* This is used for a general mmap of a ncp file */ int ncp_mmap(struct file *file, struct vm_area_struct *vma) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; DPRINTK("ncp_mmap: called\n"); diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index b34cd16f472..dee3d6c0f19 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -172,7 +172,7 @@ static int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page) { struct file *file = desc->file; - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct rpc_cred *cred = nfs_file_cred(file); unsigned long timestamp; int error; @@ -183,7 +183,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page) again: timestamp = jiffies; - error = NFS_PROTO(inode)->readdir(file->f_dentry, cred, desc->entry->cookie, page, + error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, desc->entry->cookie, page, NFS_SERVER(inode)->dtsize, desc->plus); if (error < 0) { /* We requested READDIRPLUS, but the server doesn't grok it */ @@ -308,7 +308,7 @@ int find_dirent_index(nfs_readdir_descriptor_t *desc) static inline int find_dirent_page(nfs_readdir_descriptor_t *desc) { - struct inode *inode = desc->file->f_dentry->d_inode; + struct inode *inode = desc->file->f_path.dentry->d_inode; struct page *page; int status; @@ -464,7 +464,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, filldir_t filldir) { struct file *file = desc->file; - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct rpc_cred *cred = nfs_file_cred(file); struct page *page = NULL; int status; @@ -477,7 +477,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, status = -ENOMEM; goto out; } - desc->error = NFS_PROTO(inode)->readdir(file->f_dentry, cred, *desc->dir_cookie, + desc->error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, *desc->dir_cookie, page, NFS_SERVER(inode)->dtsize, desc->plus); @@ -516,7 +516,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, */ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) { - struct dentry *dentry = filp->f_dentry; + struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; nfs_readdir_descriptor_t my_desc, *desc = &my_desc; @@ -599,7 +599,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin) { - mutex_lock(&filp->f_dentry->d_inode->i_mutex); + mutex_lock(&filp->f_path.dentry->d_inode->i_mutex); switch (origin) { case 1: offset += filp->f_pos; @@ -615,7 +615,7 @@ loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin) ((struct nfs_open_context *)filp->private_data)->dir_cookie = 0; } out: - mutex_unlock(&filp->f_dentry->d_inode->i_mutex); + mutex_unlock(&filp->f_path.dentry->d_inode->i_mutex); return offset; } @@ -1102,7 +1102,7 @@ no_open: static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc) { - struct dentry *parent = desc->file->f_dentry; + struct dentry *parent = desc->file->f_path.dentry; struct inode *dir = parent->d_inode; struct nfs_entry *entry = desc->entry; struct dentry *dentry, *alias; diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index f9d678f4ae0..bd21d7fde65 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -116,7 +116,7 @@ static inline int put_dreq(struct nfs_direct_req *dreq) ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t pos, unsigned long nr_segs) { dprintk("NFS: nfs_direct_IO (%s) off/no(%Ld/%lu) EINVAL\n", - iocb->ki_filp->f_dentry->d_name.name, + iocb->ki_filp->f_path.dentry->d_name.name, (long long) pos, nr_segs); return -EINVAL; @@ -734,8 +734,8 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov, size_t count = iov[0].iov_len; dprintk("nfs: direct read(%s/%s, %lu@%Ld)\n", - file->f_dentry->d_parent->d_name.name, - file->f_dentry->d_name.name, + file->f_path.dentry->d_parent->d_name.name, + file->f_path.dentry->d_name.name, (unsigned long) count, (long long) pos); if (nr_segs != 1) @@ -798,8 +798,8 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov, size_t count = iov[0].iov_len; dfprintk(VFS, "nfs: direct write(%s/%s, %lu@%Ld)\n", - file->f_dentry->d_parent->d_name.name, - file->f_dentry->d_name.name, + file->f_path.dentry->d_parent->d_name.name, + file->f_path.dentry->d_name.name, (unsigned long) count, (long long) pos); if (nr_segs != 1) diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 8e28bffc35a..0dd6be346aa 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -176,7 +176,7 @@ static int nfs_file_flush(struct file *file, fl_owner_t id) { struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data; - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int status; dfprintk(VFS, "nfs: flush(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino); @@ -201,7 +201,7 @@ static ssize_t nfs_file_read(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { - struct dentry * dentry = iocb->ki_filp->f_dentry; + struct dentry * dentry = iocb->ki_filp->f_path.dentry; struct inode * inode = dentry->d_inode; ssize_t result; size_t count = iov_length(iov, nr_segs); @@ -226,7 +226,7 @@ static ssize_t nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count, read_actor_t actor, void *target) { - struct dentry *dentry = filp->f_dentry; + struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; ssize_t res; @@ -243,7 +243,7 @@ nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count, static int nfs_file_mmap(struct file * file, struct vm_area_struct * vma) { - struct dentry *dentry = file->f_dentry; + struct dentry *dentry = file->f_path.dentry; struct inode *inode = dentry->d_inode; int status; @@ -343,7 +343,7 @@ const struct address_space_operations nfs_file_aops = { static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { - struct dentry * dentry = iocb->ki_filp->f_dentry; + struct dentry * dentry = iocb->ki_filp->f_path.dentry; struct inode * inode = dentry->d_inode; ssize_t result; size_t count = iov_length(iov, nr_segs); @@ -535,8 +535,8 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) { dprintk("NFS: nfs_flock(f=%s/%ld, t=%x, fl=%x)\n", - filp->f_dentry->d_inode->i_sb->s_id, - filp->f_dentry->d_inode->i_ino, + filp->f_path.dentry->d_inode->i_sb->s_id, + filp->f_path.dentry->d_inode->i_ino, fl->fl_type, fl->fl_flags); /* diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c index 20c6f39ea38..8391bd7a83c 100644 --- a/fs/nfs/getroot.c +++ b/fs/nfs/getroot.c @@ -31,7 +31,7 @@ #include <linux/nfs_idmap.h> #include <linux/vfs.h> #include <linux/namei.h> -#include <linux/namespace.h> +#include <linux/mnt_namespace.h> #include <linux/security.h> #include <asm/system.h> diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index 82ad7110a1c..9d4a6b2d199 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c @@ -377,7 +377,7 @@ idmap_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg, static ssize_t idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) { - struct rpc_inode *rpci = RPC_I(filp->f_dentry->d_inode); + struct rpc_inode *rpci = RPC_I(filp->f_path.dentry->d_inode); struct idmap *idmap = (struct idmap *)rpci->private; struct idmap_msg im_in, *im = &idmap->idmap_im; struct idmap_hashtable *h; diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 36680d1061b..63e47027930 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -496,7 +496,7 @@ void put_nfs_open_context(struct nfs_open_context *ctx) */ static void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct nfs_inode *nfsi = NFS_I(inode); filp->private_data = get_nfs_open_context(ctx); @@ -528,7 +528,7 @@ struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_c static void nfs_file_clear_open_context(struct file *filp) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct nfs_open_context *ctx = (struct nfs_open_context *)filp->private_data; if (ctx) { @@ -551,7 +551,7 @@ int nfs_open(struct inode *inode, struct file *filp) cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0); if (IS_ERR(cred)) return PTR_ERR(cred); - ctx = alloc_nfs_open_context(filp->f_vfsmnt, filp->f_dentry, cred); + ctx = alloc_nfs_open_context(filp->f_path.mnt, filp->f_path.dentry, cred); put_rpccred(cred); if (ctx == NULL) return -ENOMEM; diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 510ae524f3f..acd8fe9762d 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -841,7 +841,7 @@ static void nfs3_proc_commit_setup(struct nfs_write_data *data, int how) static int nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl) { - return nlmclnt_proc(filp->f_dentry->d_inode, cmd, fl); + return nlmclnt_proc(filp->f_path.dentry->d_inode, cmd, fl); } const struct nfs_rpc_ops nfs_v3_clientops = { diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index 10f5e80ca15..560536ad74a 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c @@ -651,7 +651,7 @@ nfs_proc_commit_setup(struct nfs_write_data *data, int how) static int nfs_proc_lock(struct file *filp, int cmd, struct file_lock *fl) { - return nlmclnt_proc(filp->f_dentry->d_inode, cmd, fl); + return nlmclnt_proc(filp->f_path.dentry->d_inode, cmd, fl); } diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 594eb16879e..345492e7864 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -754,8 +754,8 @@ int nfs_updatepage(struct file *file, struct page *page, nfs_inc_stats(inode, NFSIOS_VFSUPDATEPAGE); dprintk("NFS: nfs_updatepage(%s/%s %d@%Ld)\n", - file->f_dentry->d_parent->d_name.name, - file->f_dentry->d_name.name, count, + file->f_path.dentry->d_parent->d_name.name, + file->f_path.dentry->d_name.name, count, (long long)(page_offset(page) +offset)); /* If we're not using byte range locks, and we know the page diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c index e3eca081698..edde5dc5f79 100644 --- a/fs/nfsd/nfs2acl.c +++ b/fs/nfsd/nfs2acl.c @@ -222,12 +222,10 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p, { struct dentry *dentry = resp->fh.fh_dentry; struct inode *inode = dentry->d_inode; - int w = nfsacl_size( - (resp->mask & NFS_ACL) ? resp->acl_access : NULL, - (resp->mask & NFS_DFACL) ? resp->acl_default : NULL); struct kvec *head = rqstp->rq_res.head; unsigned int base; int n; + int w; if (dentry == NULL || dentry->d_inode == NULL) return 0; @@ -239,7 +237,9 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p, return 0; base = (char *)p - (char *)head->iov_base; - rqstp->rq_res.page_len = w; + rqstp->rq_res.page_len = w = nfsacl_size( + (resp->mask & NFS_ACL) ? resp->acl_access : NULL, + (resp->mask & NFS_DFACL) ? resp->acl_default : NULL); while (w > 0) { if (!rqstp->rq_respages[rqstp->rq_resused++]) return 0; diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c index fcad2895ddb..3e3f2de82c3 100644 --- a/fs/nfsd/nfs3acl.c +++ b/fs/nfsd/nfs3acl.c @@ -171,19 +171,19 @@ static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p, p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh); if (resp->status == 0 && dentry && dentry->d_inode) { struct inode *inode = dentry->d_inode; - int w = nfsacl_size( - (resp->mask & NFS_ACL) ? resp->acl_access : NULL, - (resp->mask & NFS_DFACL) ? resp->acl_default : NULL); struct kvec *head = rqstp->rq_res.head; unsigned int base; int n; + int w; *p++ = htonl(resp->mask); if (!xdr_ressize_check(rqstp, p)) return 0; base = (char *)p - (char *)head->iov_base; - rqstp->rq_res.page_len = w; + rqstp->rq_res.page_len = w = nfsacl_size( + (resp->mask & NFS_ACL) ? resp->acl_access : NULL, + (resp->mask & NFS_DFACL) ? resp->acl_default : NULL); while (w > 0) { if (!rqstp->rq_respages[rqstp->rq_resused++]) return 0; diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 81b8565d383..c7774e3a946 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c @@ -259,7 +259,7 @@ nfsd4_remove_clid_file(struct dentry *dir, struct dentry *dentry) printk("nfsd4: non-file found in client recovery directory\n"); return -EINVAL; } - mutex_lock(&dir->d_inode->i_mutex); + mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); status = vfs_unlink(dir->d_inode, dentry); mutex_unlock(&dir->d_inode->i_mutex); return status; diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 640c92b2a9f..b7179bd45a1 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1310,7 +1310,7 @@ static inline void nfs4_file_downgrade(struct file *filp, unsigned int share_access) { if (share_access & NFS4_SHARE_ACCESS_WRITE) { - put_write_access(filp->f_dentry->d_inode); + put_write_access(filp->f_path.dentry->d_inode); filp->f_mode = (filp->f_mode | FMODE_READ) & ~FMODE_WRITE; } } @@ -1623,7 +1623,7 @@ static __be32 nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_stateid *stp, struct nfsd4_open *open) { struct file *filp = stp->st_vfs_file; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; unsigned int share_access, new_writer; __be32 status; @@ -1965,7 +1965,7 @@ search_close_lru(u32 st_id, int flags) static inline int nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp) { - return fhp->fh_dentry->d_inode != stp->st_vfs_file->f_dentry->d_inode; + return fhp->fh_dentry->d_inode != stp->st_vfs_file->f_path.dentry->d_inode; } static int @@ -2862,7 +2862,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock * only the dentry:inode set. */ memset(&file, 0, sizeof (struct file)); - file.f_dentry = current_fh->fh_dentry; + file.f_path.dentry = current_fh->fh_dentry; status = nfs_ok; if (posix_test_lock(&file, &file_lock, &conflock)) { @@ -2952,7 +2952,7 @@ static int check_for_locks(struct file *filp, struct nfs4_stateowner *lowner) { struct file_lock **flpp; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; int status = 0; lock_kernel(); diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c index 6100bbe2743..f90d7047585 100644 --- a/fs/nfsd/nfscache.c +++ b/fs/nfsd/nfscache.c @@ -66,14 +66,13 @@ nfsd_cache_init(void) printk (KERN_ERR "nfsd: cannot allocate all %d cache entries, only got %d\n", CACHESIZE, CACHESIZE-i); - hash_list = kmalloc (HASHSIZE * sizeof(struct hlist_head), GFP_KERNEL); + hash_list = kcalloc (HASHSIZE, sizeof(struct hlist_head), GFP_KERNEL); if (!hash_list) { nfsd_cache_shutdown(); printk (KERN_ERR "nfsd: cannot allocate %Zd bytes for hash list\n", HASHSIZE * sizeof(struct hlist_head)); return; } - memset(hash_list, 0, HASHSIZE * sizeof(struct hlist_head)); cache_disabled = 0; } diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 39aed901514..eedf2e3990a 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -111,7 +111,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = { static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos) { - ino_t ino = file->f_dentry->d_inode->i_ino; + ino_t ino = file->f_path.dentry->d_inode->i_ino; char *data; ssize_t rv; diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index bb4d926e448..4883d758622 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -736,10 +736,10 @@ static int nfsd_sync(struct file *filp) { int err; - struct inode *inode = filp->f_dentry->d_inode; - dprintk("nfsd: sync file %s\n", filp->f_dentry->d_name.name); + struct inode *inode = filp->f_path.dentry->d_inode; + dprintk("nfsd: sync file %s\n", filp->f_path.dentry->d_name.name); mutex_lock(&inode->i_mutex); - err=nfsd_dosync(filp, filp->f_dentry, filp->f_op); + err=nfsd_dosync(filp, filp->f_path.dentry, filp->f_op); mutex_unlock(&inode->i_mutex); return err; @@ -845,7 +845,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, int host_err; err = nfserr_perm; - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; #ifdef MSNFS if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && (!lock_may_read(inode, offset, *count))) @@ -883,7 +883,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, nfsdstats.io_read += host_err; *count = host_err; err = 0; - fsnotify_access(file->f_dentry); + fsnotify_access(file->f_path.dentry); } else err = nfserrno(host_err); out: @@ -917,11 +917,11 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, err = nfserr_perm; if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && - (!lock_may_write(file->f_dentry->d_inode, offset, cnt))) + (!lock_may_write(file->f_path.dentry->d_inode, offset, cnt))) goto out; #endif - dentry = file->f_dentry; + dentry = file->f_path.dentry; inode = dentry->d_inode; exp = fhp->fh_export; @@ -950,7 +950,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, set_fs(oldfs); if (host_err >= 0) { nfsdstats.io_write += cnt; - fsnotify_modify(file->f_dentry); + fsnotify_modify(file->f_path.dentry); } /* clear setuid/setgid flag after write */ @@ -1885,28 +1885,27 @@ nfsd_racache_init(int cache_size) return 0; if (cache_size < 2*RAPARM_HASH_SIZE) cache_size = 2*RAPARM_HASH_SIZE; - raparml = kmalloc(sizeof(struct raparms) * cache_size, GFP_KERNEL); - - if (raparml != NULL) { - dprintk("nfsd: allocating %d readahead buffers.\n", - cache_size); - for (i = 0 ; i < RAPARM_HASH_SIZE ; i++) { - raparm_hash[i].pb_head = NULL; - spin_lock_init(&raparm_hash[i].pb_lock); - } - nperbucket = cache_size >> RAPARM_HASH_BITS; - memset(raparml, 0, sizeof(struct raparms) * cache_size); - for (i = 0; i < cache_size - 1; i++) { - if (i % nperbucket == 0) - raparm_hash[j++].pb_head = raparml + i; - if (i % nperbucket < nperbucket-1) - raparml[i].p_next = raparml + i + 1; - } - } else { + raparml = kcalloc(cache_size, sizeof(struct raparms), GFP_KERNEL); + + if (!raparml) { printk(KERN_WARNING - "nfsd: Could not allocate memory read-ahead cache.\n"); + "nfsd: Could not allocate memory read-ahead cache.\n"); return -ENOMEM; } + + dprintk("nfsd: allocating %d readahead buffers.\n", cache_size); + for (i = 0 ; i < RAPARM_HASH_SIZE ; i++) { + raparm_hash[i].pb_head = NULL; + spin_lock_init(&raparm_hash[i].pb_lock); + } + nperbucket = cache_size >> RAPARM_HASH_BITS; + for (i = 0; i < cache_size - 1; i++) { + if (i % nperbucket == 0) + raparm_hash[j++].pb_head = raparml + i; + if (i % nperbucket < nperbucket-1) + raparml[i].p_next = raparml + i + 1; + } + nfsdstats.ra_size = cache_size; return 0; } diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c index 85c36b8ca45..8296c29ae3b 100644 --- a/fs/ntfs/dir.c +++ b/fs/ntfs/dir.c @@ -1101,7 +1101,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) { s64 ia_pos, ia_start, prev_ia_pos, bmp_pos; loff_t fpos, i_size; - struct inode *bmp_vi, *vdir = filp->f_dentry->d_inode; + struct inode *bmp_vi, *vdir = filp->f_path.dentry->d_inode; struct super_block *sb = vdir->i_sb; ntfs_inode *ndir = NTFS_I(vdir); ntfs_volume *vol = NTFS_SB(sb); @@ -1136,9 +1136,9 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) if (fpos == 1) { ntfs_debug("Calling filldir for .. with len 2, fpos 0x1, " "inode 0x%lx, DT_DIR.", - (unsigned long)parent_ino(filp->f_dentry)); + (unsigned long)parent_ino(filp->f_path.dentry)); rc = filldir(dirent, "..", 2, fpos, - parent_ino(filp->f_dentry), DT_DIR); + parent_ino(filp->f_path.dentry), DT_DIR); if (rc) goto done; fpos++; diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index ae2fe0016d2..076c9420c25 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c @@ -2162,7 +2162,7 @@ static ssize_t ntfs_file_aio_write_nolock(struct kiocb *iocb, goto out; if (!count) goto out; - err = remove_suid(file->f_dentry); + err = remove_suid(file->f_path.dentry); if (err) goto out; file_update_time(file); diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 2f7268e8152..ef6cd30108a 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -595,7 +595,7 @@ static void ocfs2_dio_end_io(struct kiocb *iocb, ssize_t bytes, void *private) { - struct inode *inode = iocb->ki_filp->f_dentry->d_inode; + struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; /* this io's submitter should not have unlocked this before we could */ BUG_ON(!ocfs2_iocb_is_rw_locked(iocb)); @@ -611,7 +611,7 @@ static ssize_t ocfs2_direct_IO(int rw, unsigned long nr_segs) { struct file *file = iocb->ki_filp; - struct inode *inode = file->f_dentry->d_inode->i_mapping->host; + struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host; int ret; mlog_entry_void(); diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index baad2aa27c1..66821e17816 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -79,7 +79,7 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) struct buffer_head * bh, * tmp; struct ocfs2_dir_entry * de; int err; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct super_block * sb = inode->i_sb; unsigned int ra_sectors = 16; int lock_level = 0; diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c index 941acf14e61..b7f0ba97a1a 100644 --- a/fs/ocfs2/dlm/dlmfs.c +++ b/fs/ocfs2/dlm/dlmfs.c @@ -176,7 +176,7 @@ static ssize_t dlmfs_file_read(struct file *filp, int bytes_left; ssize_t readlen; char *lvb_buf; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; mlog(0, "inode %lu, count = %zu, *ppos = %llu\n", inode->i_ino, count, *ppos); @@ -220,7 +220,7 @@ static ssize_t dlmfs_file_write(struct file *filp, int bytes_left; ssize_t writelen; char *lvb_buf; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; mlog(0, "inode %lu, count = %zu, *ppos = %llu\n", inode->i_ino, count, *ppos); diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 8786b3c490a..e9a82ad95c1 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -68,7 +68,7 @@ static int ocfs2_file_open(struct inode *inode, struct file *file) struct ocfs2_inode_info *oi = OCFS2_I(inode); mlog_entry("(0x%p, 0x%p, '%.*s')\n", inode, file, - file->f_dentry->d_name.len, file->f_dentry->d_name.name); + file->f_path.dentry->d_name.len, file->f_path.dentry->d_name.name); spin_lock(&oi->ip_lock); @@ -98,8 +98,8 @@ static int ocfs2_file_release(struct inode *inode, struct file *file) struct ocfs2_inode_info *oi = OCFS2_I(inode); mlog_entry("(0x%p, 0x%p, '%.*s')\n", inode, file, - file->f_dentry->d_name.len, - file->f_dentry->d_name.name); + file->f_path.dentry->d_name.len, + file->f_path.dentry->d_name.name); spin_lock(&oi->ip_lock); if (!--oi->ip_open_count) @@ -1131,13 +1131,13 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, { int ret, rw_level, have_alloc_sem = 0; struct file *filp = iocb->ki_filp; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; int appending = filp->f_flags & O_APPEND ? 1 : 0; mlog_entry("(0x%p, %u, '%.*s')\n", filp, (unsigned int)nr_segs, - filp->f_dentry->d_name.len, - filp->f_dentry->d_name.name); + filp->f_path.dentry->d_name.len, + filp->f_path.dentry->d_name.name); /* happy write of zero bytes */ if (iocb->ki_left == 0) @@ -1159,7 +1159,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, goto out; } - ret = ocfs2_prepare_inode_for_write(filp->f_dentry, &iocb->ki_pos, + ret = ocfs2_prepare_inode_for_write(filp->f_path.dentry, &iocb->ki_pos, iocb->ki_left, appending); if (ret < 0) { mlog_errno(ret); @@ -1207,12 +1207,12 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe, unsigned int flags) { int ret; - struct inode *inode = out->f_dentry->d_inode; + struct inode *inode = out->f_path.dentry->d_inode; mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", out, pipe, (unsigned int)len, - out->f_dentry->d_name.len, - out->f_dentry->d_name.name); + out->f_path.dentry->d_name.len, + out->f_path.dentry->d_name.name); inode_double_lock(inode, pipe->inode); @@ -1222,7 +1222,7 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe, goto out; } - ret = ocfs2_prepare_inode_for_write(out->f_dentry, ppos, len, 0); + ret = ocfs2_prepare_inode_for_write(out->f_path.dentry, ppos, len, 0); if (ret < 0) { mlog_errno(ret); goto out_unlock; @@ -1247,12 +1247,12 @@ static ssize_t ocfs2_file_splice_read(struct file *in, unsigned int flags) { int ret = 0; - struct inode *inode = in->f_dentry->d_inode; + struct inode *inode = in->f_path.dentry->d_inode; mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", in, pipe, (unsigned int)len, - in->f_dentry->d_name.len, - in->f_dentry->d_name.name); + in->f_path.dentry->d_name.len, + in->f_path.dentry->d_name.name); /* * See the comment in ocfs2_file_aio_read() @@ -1278,12 +1278,12 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb, { int ret = 0, rw_level = -1, have_alloc_sem = 0, lock_level = 0; struct file *filp = iocb->ki_filp; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; mlog_entry("(0x%p, %u, '%.*s')\n", filp, (unsigned int)nr_segs, - filp->f_dentry->d_name.len, - filp->f_dentry->d_name.name); + filp->f_path.dentry->d_name.len, + filp->f_path.dentry->d_name.name); if (!inode) { ret = -EINVAL; diff --git a/fs/open.c b/fs/open.c index 89e0c237a63..0d94319e868 100644 --- a/fs/open.c +++ b/fs/open.c @@ -165,7 +165,7 @@ asmlinkage long sys_fstatfs(unsigned int fd, struct statfs __user * buf) file = fget(fd); if (!file) goto out; - error = vfs_statfs_native(file->f_dentry, &tmp); + error = vfs_statfs_native(file->f_path.dentry, &tmp); if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) error = -EFAULT; fput(file); @@ -186,7 +186,7 @@ asmlinkage long sys_fstatfs64(unsigned int fd, size_t sz, struct statfs64 __user file = fget(fd); if (!file) goto out; - error = vfs_statfs64(file->f_dentry, &tmp); + error = vfs_statfs64(file->f_path.dentry, &tmp); if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) error = -EFAULT; fput(file); @@ -302,7 +302,7 @@ static long do_sys_ftruncate(unsigned int fd, loff_t length, int small) if (file->f_flags & O_LARGEFILE) small = 0; - dentry = file->f_dentry; + dentry = file->f_path.dentry; inode = dentry->d_inode; error = -EINVAL; if (!S_ISREG(inode->i_mode) || !(file->f_mode & FMODE_WRITE)) @@ -448,8 +448,8 @@ asmlinkage long sys_fchdir(unsigned int fd) if (!file) goto out; - dentry = file->f_dentry; - mnt = file->f_vfsmnt; + dentry = file->f_path.dentry; + mnt = file->f_path.mnt; inode = dentry->d_inode; error = -ENOTDIR; @@ -503,7 +503,7 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) if (!file) goto out; - dentry = file->f_dentry; + dentry = file->f_path.dentry; inode = dentry->d_inode; audit_inode(NULL, inode); @@ -662,7 +662,7 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group) if (!file) goto out; - dentry = file->f_dentry; + dentry = file->f_path.dentry; audit_inode(NULL, dentry->d_inode); error = chown_common(dentry, user, group); fput(file); @@ -688,8 +688,8 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, } f->f_mapping = inode->i_mapping; - f->f_dentry = dentry; - f->f_vfsmnt = mnt; + f->f_path.dentry = dentry; + f->f_path.mnt = mnt; f->f_pos = 0; f->f_op = fops_get(inode->i_fop); file_move(f, &inode->i_sb->s_files); @@ -723,8 +723,8 @@ cleanup_all: if (f->f_mode & FMODE_WRITE) put_write_access(inode); file_kill(f); - f->f_dentry = NULL; - f->f_vfsmnt = NULL; + f->f_path.dentry = NULL; + f->f_path.mnt = NULL; cleanup_file: put_filp(f); dput(dentry); @@ -822,7 +822,7 @@ struct file *nameidata_to_filp(struct nameidata *nd, int flags) /* Pick up the filp from the open intent */ filp = nd->intent.open.file; /* Has the filesystem initialised the file for us? */ - if (filp->f_dentry == NULL) + if (filp->f_path.dentry == NULL) filp = __dentry_open(nd->dentry, nd->mnt, flags, filp, NULL); else path_release(nd); @@ -965,7 +965,7 @@ long do_sys_open(int dfd, const char __user *filename, int flags, int mode) put_unused_fd(fd); fd = PTR_ERR(f); } else { - fsnotify_open(f->f_dentry); + fsnotify_open(f->f_path.dentry); fd_install(fd, f); } } @@ -1087,6 +1087,7 @@ EXPORT_SYMBOL(sys_close); asmlinkage long sys_vhangup(void) { if (capable(CAP_SYS_TTY_CONFIG)) { + /* XXX: this needs locking */ tty_vhangup(current->signal->tty); return 0; } diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c index 26f44e0074e..99c0bc37ba0 100644 --- a/fs/openpromfs/inode.c +++ b/fs/openpromfs/inode.c @@ -262,7 +262,7 @@ found: static int openpromfs_readdir(struct file * filp, void * dirent, filldir_t filldir) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct op_inode_info *oi = OP_I(inode); struct device_node *dp = oi->u.node; struct device_node *child; diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 1901137f4ec..3d73d94d93a 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -276,12 +276,39 @@ static struct part_attribute part_attr_stat = { .show = part_stat_read }; +#ifdef CONFIG_FAIL_MAKE_REQUEST + +static ssize_t part_fail_store(struct hd_struct * p, + const char *buf, size_t count) +{ + int i; + + if (count > 0 && sscanf(buf, "%d", &i) > 0) + p->make_it_fail = (i == 0) ? 0 : 1; + + return count; +} +static ssize_t part_fail_read(struct hd_struct * p, char *page) +{ + return sprintf(page, "%d\n", p->make_it_fail); +} +static struct part_attribute part_attr_fail = { + .attr = {.name = "make-it-fail", .mode = S_IRUGO | S_IWUSR }, + .store = part_fail_store, + .show = part_fail_read +}; + +#endif + static struct attribute * default_attrs[] = { &part_attr_uevent.attr, &part_attr_dev.attr, &part_attr_start.attr, &part_attr_size.attr, &part_attr_stat.attr, +#ifdef CONFIG_FAIL_MAKE_REQUEST + &part_attr_fail.attr, +#endif NULL, }; diff --git a/fs/pipe.c b/fs/pipe.c index ae36b89b1a3..f8b6bdcb879 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -222,7 +222,7 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, unsigned long nr_segs, loff_t pos) { struct file *filp = iocb->ki_filp; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct pipe_inode_info *pipe; int do_wakeup; ssize_t ret; @@ -335,7 +335,7 @@ pipe_write(struct kiocb *iocb, const struct iovec *_iov, unsigned long nr_segs, loff_t ppos) { struct file *filp = iocb->ki_filp; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct pipe_inode_info *pipe; ssize_t ret; int do_wakeup; @@ -520,7 +520,7 @@ static int pipe_ioctl(struct inode *pino, struct file *filp, unsigned int cmd, unsigned long arg) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct pipe_inode_info *pipe; int count, buf, nrbufs; @@ -548,7 +548,7 @@ static unsigned int pipe_poll(struct file *filp, poll_table *wait) { unsigned int mask; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct pipe_inode_info *pipe = inode->i_pipe; int nrbufs; @@ -601,7 +601,7 @@ pipe_release(struct inode *inode, int decr, int decw) static int pipe_read_fasync(int fd, struct file *filp, int on) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; int retval; mutex_lock(&inode->i_mutex); @@ -618,7 +618,7 @@ pipe_read_fasync(int fd, struct file *filp, int on) static int pipe_write_fasync(int fd, struct file *filp, int on) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; int retval; mutex_lock(&inode->i_mutex); @@ -635,7 +635,7 @@ pipe_write_fasync(int fd, struct file *filp, int on) static int pipe_rdwr_fasync(int fd, struct file *filp, int on) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct pipe_inode_info *pipe = inode->i_pipe; int retval; @@ -914,8 +914,8 @@ struct file *create_write_pipe(void) */ dentry->d_flags &= ~DCACHE_UNHASHED; d_instantiate(dentry, inode); - f->f_vfsmnt = mntget(pipe_mnt); - f->f_dentry = dentry; + f->f_path.mnt = mntget(pipe_mnt); + f->f_path.dentry = dentry; f->f_mapping = inode->i_mapping; f->f_flags = O_WRONLY; @@ -935,8 +935,8 @@ struct file *create_write_pipe(void) void free_write_pipe(struct file *f) { - mntput(f->f_vfsmnt); - dput(f->f_dentry); + mntput(f->f_path.mnt); + dput(f->f_path.dentry); put_filp(f); } @@ -947,9 +947,9 @@ struct file *create_read_pipe(struct file *wrf) return ERR_PTR(-ENFILE); /* Grab pipe from the writer */ - f->f_vfsmnt = mntget(wrf->f_vfsmnt); - f->f_dentry = dget(wrf->f_dentry); - f->f_mapping = wrf->f_dentry->d_inode->i_mapping; + f->f_path.mnt = mntget(wrf->f_path.mnt); + f->f_path.dentry = dget(wrf->f_path.dentry); + f->f_mapping = wrf->f_path.dentry->d_inode->i_mapping; f->f_pos = 0; f->f_flags = O_RDONLY; diff --git a/fs/pnode.c b/fs/pnode.c index da42ee61c1d..56aacead836 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -6,7 +6,7 @@ * Author : Ram Pai (linuxram@us.ibm.com) * */ -#include <linux/namespace.h> +#include <linux/mnt_namespace.h> #include <linux/mount.h> #include <linux/fs.h> #include "pnode.h" diff --git a/fs/pnode.h b/fs/pnode.h index 020e1bb60fd..d45bd8ec36b 100644 --- a/fs/pnode.h +++ b/fs/pnode.h @@ -13,7 +13,7 @@ #define IS_MNT_SHARED(mnt) (mnt->mnt_flags & MNT_SHARED) #define IS_MNT_SLAVE(mnt) (mnt->mnt_master) -#define IS_MNT_NEW(mnt) (!mnt->mnt_namespace) +#define IS_MNT_NEW(mnt) (!mnt->mnt_ns) #define CLEAR_MNT_SHARED(mnt) (mnt->mnt_flags &= ~MNT_SHARED) #define IS_MNT_UNBINDABLE(mnt) (mnt->mnt_flags & MNT_UNBINDABLE) diff --git a/fs/proc/array.c b/fs/proc/array.c index 25e917fb473..70e4fab117b 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -346,20 +346,13 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) sigemptyset(&sigcatch); cutime = cstime = utime = stime = cputime_zero; - mutex_lock(&tty_mutex); rcu_read_lock(); if (lock_task_sighand(task, &flags)) { struct signal_struct *sig = task->signal; - struct tty_struct *tty = sig->tty; - - if (tty) { - /* - * sig->tty is not stable, but tty_mutex - * protects us from release_dev(tty) - */ - barrier(); - tty_pgrp = tty->pgrp; - tty_nr = new_encode_dev(tty_devnum(tty)); + + if (sig->tty) { + tty_pgrp = sig->tty->pgrp; + tty_nr = new_encode_dev(tty_devnum(sig->tty)); } num_threads = atomic_read(&sig->count); @@ -388,14 +381,13 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) stime = cputime_add(stime, sig->stime); } - sid = sig->session; + sid = signal_session(sig); pgid = process_group(task); ppid = rcu_dereference(task->real_parent)->tgid; unlock_task_sighand(task, &flags); } rcu_read_unlock(); - mutex_unlock(&tty_mutex); if (!whole || num_threads<2) wchan = get_wchan(task); diff --git a/fs/proc/base.c b/fs/proc/base.c index b859fc749c0..fd959d5b5a8 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -59,7 +59,7 @@ #include <linux/string.h> #include <linux/seq_file.h> #include <linux/namei.h> -#include <linux/namespace.h> +#include <linux/mnt_namespace.h> #include <linux/mm.h> #include <linux/smp_lock.h> #include <linux/rcupdate.h> @@ -365,33 +365,33 @@ struct proc_mounts { static int mounts_open(struct inode *inode, struct file *file) { struct task_struct *task = get_proc_task(inode); - struct namespace *namespace = NULL; + struct mnt_namespace *ns = NULL; struct proc_mounts *p; int ret = -EINVAL; if (task) { task_lock(task); - namespace = task->nsproxy->namespace; - if (namespace) - get_namespace(namespace); + ns = task->nsproxy->mnt_ns; + if (ns) + get_mnt_ns(ns); task_unlock(task); put_task_struct(task); } - if (namespace) { + if (ns) { ret = -ENOMEM; p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL); if (p) { file->private_data = &p->m; ret = seq_open(file, &mounts_op); if (!ret) { - p->m.private = namespace; - p->event = namespace->event; + p->m.private = ns; + p->event = ns->event; return 0; } kfree(p); } - put_namespace(namespace); + put_mnt_ns(ns); } return ret; } @@ -399,15 +399,15 @@ static int mounts_open(struct inode *inode, struct file *file) static int mounts_release(struct inode *inode, struct file *file) { struct seq_file *m = file->private_data; - struct namespace *namespace = m->private; - put_namespace(namespace); + struct mnt_namespace *ns = m->private; + put_mnt_ns(ns); return seq_release(inode, file); } static unsigned mounts_poll(struct file *file, poll_table *wait) { struct proc_mounts *p = file->private_data; - struct namespace *ns = p->m.private; + struct mnt_namespace *ns = p->m.private; unsigned res = 0; poll_wait(file, &ns->poll, wait); @@ -437,21 +437,21 @@ static int mountstats_open(struct inode *inode, struct file *file) if (!ret) { struct seq_file *m = file->private_data; - struct namespace *namespace = NULL; + struct mnt_namespace *mnt_ns = NULL; struct task_struct *task = get_proc_task(inode); if (task) { task_lock(task); if (task->nsproxy) - namespace = task->nsproxy->namespace; - if (namespace) - get_namespace(namespace); + mnt_ns = task->nsproxy->mnt_ns; + if (mnt_ns) + get_mnt_ns(mnt_ns); task_unlock(task); put_task_struct(task); } - if (namespace) - m->private = namespace; + if (mnt_ns) + m->private = mnt_ns; else { seq_release(inode, file); ret = -EINVAL; @@ -472,7 +472,7 @@ static struct file_operations proc_mountstats_operations = { static ssize_t proc_info_read(struct file * file, char __user * buf, size_t count, loff_t *ppos) { - struct inode * inode = file->f_dentry->d_inode; + struct inode * inode = file->f_path.dentry->d_inode; unsigned long page; ssize_t length; struct task_struct *task = get_proc_task(inode); @@ -512,7 +512,7 @@ static int mem_open(struct inode* inode, struct file* file) static ssize_t mem_read(struct file * file, char __user * buf, size_t count, loff_t *ppos) { - struct task_struct *task = get_proc_task(file->f_dentry->d_inode); + struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); char *page; unsigned long src = *ppos; int ret = -ESRCH; @@ -584,7 +584,7 @@ static ssize_t mem_write(struct file * file, const char * buf, { int copied; char *page; - struct task_struct *task = get_proc_task(file->f_dentry->d_inode); + struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); unsigned long dst = *ppos; copied = -ESRCH; @@ -654,7 +654,7 @@ static struct file_operations proc_mem_operations = { static ssize_t oom_adjust_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct task_struct *task = get_proc_task(file->f_dentry->d_inode); + struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); char buffer[PROC_NUMBUF]; size_t len; int oom_adjust; @@ -694,7 +694,7 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf, return -EINVAL; if (*end == '\n') end++; - task = get_proc_task(file->f_dentry->d_inode); + task = get_proc_task(file->f_path.dentry->d_inode); if (!task) return -ESRCH; if (oom_adjust < task->oomkilladj && !capable(CAP_SYS_RESOURCE)) { @@ -718,7 +718,7 @@ static struct file_operations proc_oom_adjust_operations = { static ssize_t proc_loginuid_read(struct file * file, char __user * buf, size_t count, loff_t *ppos) { - struct inode * inode = file->f_dentry->d_inode; + struct inode * inode = file->f_path.dentry->d_inode; struct task_struct *task = get_proc_task(inode); ssize_t length; char tmpbuf[TMPBUFLEN]; @@ -734,7 +734,7 @@ static ssize_t proc_loginuid_read(struct file * file, char __user * buf, static ssize_t proc_loginuid_write(struct file * file, const char __user * buf, size_t count, loff_t *ppos) { - struct inode * inode = file->f_dentry->d_inode; + struct inode * inode = file->f_path.dentry->d_inode; char *page, *tmp; ssize_t length; uid_t loginuid; @@ -853,6 +853,65 @@ static struct file_operations proc_seccomp_operations = { }; #endif /* CONFIG_SECCOMP */ +#ifdef CONFIG_FAULT_INJECTION +static ssize_t proc_fault_inject_read(struct file * file, char __user * buf, + size_t count, loff_t *ppos) +{ + struct task_struct *task = get_proc_task(file->f_dentry->d_inode); + char buffer[PROC_NUMBUF]; + size_t len; + int make_it_fail; + loff_t __ppos = *ppos; + + if (!task) + return -ESRCH; + make_it_fail = task->make_it_fail; + put_task_struct(task); + + len = snprintf(buffer, sizeof(buffer), "%i\n", make_it_fail); + if (__ppos >= len) + return 0; + if (count > len-__ppos) + count = len-__ppos; + if (copy_to_user(buf, buffer + __ppos, count)) + return -EFAULT; + *ppos = __ppos + count; + return count; +} + +static ssize_t proc_fault_inject_write(struct file * file, + const char __user * buf, size_t count, loff_t *ppos) +{ + struct task_struct *task; + char buffer[PROC_NUMBUF], *end; + int make_it_fail; + + if (!capable(CAP_SYS_RESOURCE)) + return -EPERM; + memset(buffer, 0, sizeof(buffer)); + if (count > sizeof(buffer) - 1) + count = sizeof(buffer) - 1; + if (copy_from_user(buffer, buf, count)) + return -EFAULT; + make_it_fail = simple_strtol(buffer, &end, 0); + if (*end == '\n') + end++; + task = get_proc_task(file->f_dentry->d_inode); + if (!task) + return -ESRCH; + task->make_it_fail = make_it_fail; + put_task_struct(task); + if (end - buffer == 0) + return -EIO; + return end - buffer; +} + +static struct file_operations proc_fault_inject_operations = { + .read = proc_fault_inject_read, + .write = proc_fault_inject_write, +}; +#endif + static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) { struct inode *inode = dentry->d_inode; @@ -1078,7 +1137,7 @@ static int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir, char *name, int len, instantiate_t instantiate, struct task_struct *task, void *ptr) { - struct dentry *child, *dir = filp->f_dentry; + struct dentry *child, *dir = filp->f_path.dentry; struct inode *inode; struct qstr qname; ino_t ino = 0; @@ -1157,8 +1216,8 @@ static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsm spin_lock(&files->file_lock); file = fcheck_files(files, fd); if (file) { - *mnt = mntget(file->f_vfsmnt); - *dentry = dget(file->f_dentry); + *mnt = mntget(file->f_path.mnt); + *dentry = dget(file->f_path.dentry); spin_unlock(&files->file_lock); put_files_struct(files); return 0; @@ -1293,7 +1352,7 @@ static int proc_fd_fill_cache(struct file *filp, void *dirent, filldir_t filldir static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) { - struct dentry *dentry = filp->f_dentry; + struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; struct task_struct *p = get_proc_task(inode); unsigned int fd, tid, ino; @@ -1440,7 +1499,7 @@ static int proc_pident_readdir(struct file *filp, { int i; int pid; - struct dentry *dentry = filp->f_dentry; + struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; struct task_struct *task = get_proc_task(inode); struct pid_entry *p, *last; @@ -1496,7 +1555,7 @@ out_no_task: static ssize_t proc_pid_attr_read(struct file * file, char __user * buf, size_t count, loff_t *ppos) { - struct inode * inode = file->f_dentry->d_inode; + struct inode * inode = file->f_path.dentry->d_inode; unsigned long page; ssize_t length; struct task_struct *task = get_proc_task(inode); @@ -1512,7 +1571,7 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf, goto out; length = security_getprocattr(task, - (char*)file->f_dentry->d_name.name, + (char*)file->f_path.dentry->d_name.name, (void*)page, count); if (length >= 0) length = simple_read_from_buffer(buf, count, ppos, (char *)page, length); @@ -1526,7 +1585,7 @@ out_no_task: static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf, size_t count, loff_t *ppos) { - struct inode * inode = file->f_dentry->d_inode; + struct inode * inode = file->f_path.dentry->d_inode; char *page; ssize_t length; struct task_struct *task = get_proc_task(inode); @@ -1552,7 +1611,7 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf, goto out_free; length = security_setprocattr(task, - (char*)file->f_dentry->d_name.name, + (char*)file->f_path.dentry->d_name.name, (void*)page, count); out_free: free_page((unsigned long) page); @@ -1793,6 +1852,9 @@ static struct pid_entry tgid_base_stuff[] = { #ifdef CONFIG_AUDITSYSCALL REG("loginuid", S_IWUSR|S_IRUGO, loginuid), #endif +#ifdef CONFIG_FAULT_INJECTION + REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject), +#endif }; static int proc_tgid_base_readdir(struct file * filp, @@ -1994,7 +2056,7 @@ static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldi int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) { unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY; - struct task_struct *reaper = get_proc_task(filp->f_dentry->d_inode); + struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode); struct task_struct *task; int tgid; @@ -2068,6 +2130,9 @@ static struct pid_entry tid_base_stuff[] = { #ifdef CONFIG_AUDITSYSCALL REG("loginuid", S_IWUSR|S_IRUGO, loginuid), #endif +#ifdef CONFIG_FAULT_INJECTION + REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject), +#endif }; static int proc_tid_base_readdir(struct file * filp, @@ -2235,7 +2300,7 @@ static int proc_task_fill_cache(struct file *filp, void *dirent, filldir_t filld /* for the /proc/TGID/task/ directories */ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldir) { - struct dentry *dentry = filp->f_dentry; + struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; struct task_struct *leader = get_proc_task(inode); struct task_struct *task; diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 4ba03009cf7..853cb877d5f 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -52,7 +52,7 @@ static ssize_t proc_file_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) { - struct inode * inode = file->f_dentry->d_inode; + struct inode * inode = file->f_path.dentry->d_inode; char *page; ssize_t retval=0; int eof=0; @@ -203,7 +203,7 @@ static ssize_t proc_file_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct proc_dir_entry * dp; dp = PDE(inode); @@ -432,7 +432,7 @@ int proc_readdir(struct file * filp, struct proc_dir_entry * de; unsigned int ino; int i; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; int ret = 0; lock_kernel(); @@ -453,7 +453,7 @@ int proc_readdir(struct file * filp, /* fall through */ case 1: if (filldir(dirent, "..", 2, i, - parent_ino(filp->f_dentry), + parent_ino(filp->f_path.dentry), DT_DIR) < 0) goto out; i++; @@ -558,7 +558,7 @@ static void proc_kill_inodes(struct proc_dir_entry *de) file_list_lock(); list_for_each(p, &sb->s_files) { struct file * filp = list_entry(p, struct file, f_u.fu_list); - struct dentry * dentry = filp->f_dentry; + struct dentry * dentry = filp->f_path.dentry; struct inode * inode; const struct file_operations *fops; diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c index d7dbdf9e0f4..5ec67257e5f 100644 --- a/fs/proc/nommu.c +++ b/fs/proc/nommu.c @@ -46,7 +46,7 @@ int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma) file = vma->vm_file; if (file) { - struct inode *inode = vma->vm_file->f_dentry->d_inode; + struct inode *inode = vma->vm_file->f_path.dentry->d_inode; dev = inode->i_sb->s_dev; ino = inode->i_ino; } @@ -67,7 +67,7 @@ int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma) if (len < 1) len = 1; seq_printf(m, "%*c", len, ' '); - seq_path(m, file->f_vfsmnt, file->f_dentry, ""); + seq_path(m, file->f_path.mnt, file->f_path.dentry, ""); } seq_putc(m, '\n'); diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index 51815cece6f..dc3e580d1dc 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c @@ -39,13 +39,14 @@ #include <linux/seq_file.h> #include <linux/times.h> #include <linux/profile.h> +#include <linux/utsname.h> #include <linux/blkdev.h> #include <linux/hugetlb.h> #include <linux/jiffies.h> #include <linux/sysrq.h> #include <linux/vmalloc.h> #include <linux/crash_dump.h> -#include <linux/pspace.h> +#include <linux/pid_namespace.h> #include <asm/uaccess.h> #include <asm/pgtable.h> #include <asm/io.h> @@ -92,7 +93,7 @@ static int loadavg_read_proc(char *page, char **start, off_t off, LOAD_INT(a), LOAD_FRAC(a), LOAD_INT(b), LOAD_FRAC(b), LOAD_INT(c), LOAD_FRAC(c), - nr_running(), nr_threads, init_pspace.last_pid); + nr_running(), nr_threads, current->nsproxy->pid_ns->last_pid); return proc_calc_metrics(page, start, off, count, eof, len); } @@ -252,8 +253,8 @@ static int version_read_proc(char *page, char **start, off_t off, { int len; - strcpy(page, linux_banner); - len = strlen(page); + len = sprintf(page, linux_banner, + utsname()->release, utsname()->version); return proc_calc_metrics(page, start, off, count, eof, len); } diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 6b769afac55..55ade0d1562 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -94,8 +94,8 @@ int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfsmount * } if (vma) { - *mnt = mntget(vma->vm_file->f_vfsmnt); - *dentry = dget(vma->vm_file->f_dentry); + *mnt = mntget(vma->vm_file->f_path.mnt); + *dentry = dget(vma->vm_file->f_path.dentry); result = 0; } @@ -135,7 +135,7 @@ static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats int len; if (file) { - struct inode *inode = vma->vm_file->f_dentry->d_inode; + struct inode *inode = vma->vm_file->f_path.dentry->d_inode; dev = inode->i_sb->s_dev; ino = inode->i_ino; } @@ -156,7 +156,7 @@ static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats */ if (file) { pad_len_spaces(m, len); - seq_path(m, file->f_vfsmnt, file->f_dentry, "\n"); + seq_path(m, file->f_path.mnt, file->f_path.dentry, "\n"); } else { const char *name = arch_vma_name(vma); if (!name) { diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c index 091aa8e48e0..fcc5caf93f5 100644 --- a/fs/proc/task_nommu.c +++ b/fs/proc/task_nommu.c @@ -126,8 +126,8 @@ int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfsmount * } if (vma) { - *mnt = mntget(vma->vm_file->f_vfsmnt); - *dentry = dget(vma->vm_file->f_dentry); + *mnt = mntget(vma->vm_file->f_path.mnt); + *dentry = dget(vma->vm_file->f_path.dentry); result = 0; } diff --git a/fs/qnx4/dir.c b/fs/qnx4/dir.c index 0d7103fa0df..c94db1db7a7 100644 --- a/fs/qnx4/dir.c +++ b/fs/qnx4/dir.c @@ -22,7 +22,7 @@ static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; unsigned int offset; struct buffer_head *bh; struct qnx4_inode_entry *de; diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index bfe5dbf1002..61cbe1ef06b 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c @@ -232,7 +232,7 @@ unsigned long ramfs_nommu_get_unmapped_area(struct file *file, unsigned long pgoff, unsigned long flags) { unsigned long maxpages, lpages, nr, loop, ret; - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct page **pages = NULL, **ptr, *page; loff_t isize; diff --git a/fs/read_write.c b/fs/read_write.c index f792000a28e..1d3dda4fa70 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -64,13 +64,13 @@ loff_t remote_llseek(struct file *file, loff_t offset, int origin) lock_kernel(); switch (origin) { case 2: - offset += i_size_read(file->f_dentry->d_inode); + offset += i_size_read(file->f_path.dentry->d_inode); break; case 1: offset += file->f_pos; } retval = -EINVAL; - if (offset>=0 && offset<=file->f_dentry->d_inode->i_sb->s_maxbytes) { + if (offset>=0 && offset<=file->f_path.dentry->d_inode->i_sb->s_maxbytes) { if (offset != file->f_pos) { file->f_pos = offset; file->f_version = 0; @@ -95,7 +95,7 @@ loff_t default_llseek(struct file *file, loff_t offset, int origin) lock_kernel(); switch (origin) { case 2: - offset += i_size_read(file->f_dentry->d_inode); + offset += i_size_read(file->f_path.dentry->d_inode); break; case 1: offset += file->f_pos; @@ -203,7 +203,7 @@ int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t count if (unlikely((pos < 0) || (loff_t) (pos + count) < 0)) goto Einval; - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; if (unlikely(inode->i_flock && MANDATORY_LOCK(inode))) { int retval = locks_mandatory_area( read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE, @@ -273,7 +273,7 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) else ret = do_sync_read(file, buf, count, pos); if (ret > 0) { - fsnotify_access(file->f_dentry); + fsnotify_access(file->f_path.dentry); current->rchar += ret; } current->syscr++; @@ -331,7 +331,7 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_ else ret = do_sync_write(file, buf, count, pos); if (ret > 0) { - fsnotify_modify(file->f_dentry); + fsnotify_modify(file->f_path.dentry); current->wchar += ret; } current->syscw++; @@ -628,9 +628,9 @@ out: kfree(iov); if ((ret + (type == READ)) > 0) { if (type == READ) - fsnotify_access(file->f_dentry); + fsnotify_access(file->f_path.dentry); else - fsnotify_modify(file->f_dentry); + fsnotify_modify(file->f_path.dentry); } return ret; } @@ -722,7 +722,7 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, if (!(in_file->f_mode & FMODE_READ)) goto fput_in; retval = -EINVAL; - in_inode = in_file->f_dentry->d_inode; + in_inode = in_file->f_path.dentry->d_inode; if (!in_inode) goto fput_in; if (!in_file->f_op || !in_file->f_op->sendfile) @@ -754,7 +754,7 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, retval = -EINVAL; if (!out_file->f_op || !out_file->f_op->sendpage) goto fput_out; - out_inode = out_file->f_dentry->d_inode; + out_inode = out_file->f_path.dentry->d_inode; retval = rw_verify_area(WRITE, out_file, &out_file->f_pos, count); if (retval < 0) goto fput_out; diff --git a/fs/readdir.c b/fs/readdir.c index bff3ee58e2f..f39f5b31325 100644 --- a/fs/readdir.c +++ b/fs/readdir.c @@ -21,7 +21,7 @@ int vfs_readdir(struct file *file, filldir_t filler, void *buf) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int res = -ENOTDIR; if (!file->f_op || !file->f_op->readdir) goto out; diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c index e3d466a228d..b286ccb0858 100644 --- a/fs/reiserfs/bitmap.c +++ b/fs/reiserfs/bitmap.c @@ -708,7 +708,7 @@ static void oid_groups(reiserfs_blocknr_hint_t * hint) */ static int get_left_neighbor(reiserfs_blocknr_hint_t * hint) { - struct path *path; + struct treepath *path; struct buffer_head *bh; struct item_head *ih; int pos_in_item; diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c index 657050ad743..96a2f8889da 100644 --- a/fs/reiserfs/dir.c +++ b/fs/reiserfs/dir.c @@ -45,7 +45,7 @@ static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry, // static int reiserfs_readdir(struct file *filp, void *dirent, filldir_t filldir) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct cpu_key pos_key; /* key of current position in the directory (key of directory entry) */ INITIALIZE_PATH(path_to_entry); struct buffer_head *bh; @@ -135,7 +135,7 @@ static int reiserfs_readdir(struct file *filp, void *dirent, filldir_t filldir) /* Ignore the .reiserfs_priv entry */ if (reiserfs_xattrs(inode->i_sb) && !old_format_only(inode->i_sb) && - filp->f_dentry == inode->i_sb->s_root && + filp->f_path.dentry == inode->i_sb->s_root && REISERFS_SB(inode->i_sb)->priv_root && REISERFS_SB(inode->i_sb)->priv_root->d_inode && deh_objectid(deh) == diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index 373d862c3f8..99b6f329ba2 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c @@ -1288,7 +1288,7 @@ static ssize_t reiserfs_file_write(struct file *file, /* the file we are going t loff_t pos; // Current position in the file. ssize_t res; // return value of various functions that we call. int err = 0; - struct inode *inode = file->f_dentry->d_inode; // Inode of the file that we are writing to. + struct inode *inode = file->f_path.dentry->d_inode; // Inode of the file that we are writing to. /* To simplify coding at this time, we store locked pages in array for now */ struct page *prepared_pages[REISERFS_WRITE_PAGES_AT_A_TIME]; @@ -1335,7 +1335,7 @@ static ssize_t reiserfs_file_write(struct file *file, /* the file we are going t if (count == 0) goto out; - res = remove_suid(file->f_dentry); + res = remove_suid(file->f_path.dentry); if (res) goto out; diff --git a/fs/reiserfs/fix_node.c b/fs/reiserfs/fix_node.c index 6d0e554daa9..0ee35c6c9b7 100644 --- a/fs/reiserfs/fix_node.c +++ b/fs/reiserfs/fix_node.c @@ -957,7 +957,7 @@ static int get_far_parent(struct tree_balance *p_s_tb, { struct buffer_head *p_s_parent; INITIALIZE_PATH(s_path_to_neighbor_father); - struct path *p_s_path = p_s_tb->tb_path; + struct treepath *p_s_path = p_s_tb->tb_path; struct cpu_key s_lr_father_key; int n_counter, n_position = INT_MAX, @@ -1074,7 +1074,7 @@ static int get_far_parent(struct tree_balance *p_s_tb, */ static int get_parents(struct tree_balance *p_s_tb, int n_h) { - struct path *p_s_path = p_s_tb->tb_path; + struct treepath *p_s_path = p_s_tb->tb_path; int n_position, n_ret_value, n_path_offset = PATH_H_PATH_OFFSET(p_s_tb->tb_path, n_h); @@ -1885,7 +1885,7 @@ static int check_balance(int mode, static int get_direct_parent(struct tree_balance *p_s_tb, int n_h) { struct buffer_head *p_s_bh; - struct path *p_s_path = p_s_tb->tb_path; + struct treepath *p_s_path = p_s_tb->tb_path; int n_position, n_path_offset = PATH_H_PATH_OFFSET(p_s_tb->tb_path, n_h); diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 254239e6f9e..f3d1c4a7797 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -207,7 +207,7 @@ static int file_capable(struct inode *inode, long block) } /*static*/ int restart_transaction(struct reiserfs_transaction_handle *th, - struct inode *inode, struct path *path) + struct inode *inode, struct treepath *path) { struct super_block *s = th->t_super; int len = th->t_blocks_allocated; @@ -570,7 +570,7 @@ static inline int _allocate_block(struct reiserfs_transaction_handle *th, long block, struct inode *inode, b_blocknr_t * allocated_block_nr, - struct path *path, int flags) + struct treepath *path, int flags) { BUG_ON(!th->t_trans_id); @@ -1107,7 +1107,7 @@ static inline ulong to_fake_used_blocks(struct inode *inode, int sd_size) // // called by read_locked_inode -static void init_inode(struct inode *inode, struct path *path) +static void init_inode(struct inode *inode, struct treepath *path) { struct buffer_head *bh; struct item_head *ih; @@ -1284,7 +1284,7 @@ static void inode2sd_v1(void *sd, struct inode *inode, loff_t size) /* NOTE, you must prepare the buffer head before sending it here, ** and then log it after the call */ -static void update_stat_data(struct path *path, struct inode *inode, +static void update_stat_data(struct treepath *path, struct inode *inode, loff_t size) { struct buffer_head *bh; @@ -1653,7 +1653,7 @@ int reiserfs_write_inode(struct inode *inode, int do_sync) containing "." and ".." entries */ static int reiserfs_new_directory(struct reiserfs_transaction_handle *th, struct inode *inode, - struct item_head *ih, struct path *path, + struct item_head *ih, struct treepath *path, struct inode *dir) { struct super_block *sb = th->t_super; @@ -1712,7 +1712,7 @@ static int reiserfs_new_directory(struct reiserfs_transaction_handle *th, containing the body of symlink */ static int reiserfs_new_symlink(struct reiserfs_transaction_handle *th, struct inode *inode, /* Inode of symlink */ struct item_head *ih, - struct path *path, const char *symname, + struct treepath *path, const char *symname, int item_len) { struct super_block *sb = th->t_super; diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c index 9c57578cb83..b484d2913c0 100644 --- a/fs/reiserfs/ioctl.c +++ b/fs/reiserfs/ioctl.c @@ -99,7 +99,7 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, long reiserfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int ret; /* These are just misnamed, they actually get/put from/to user an int */ diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index abde1edc223..23f5cd5bbf5 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c @@ -54,7 +54,7 @@ static int bin_search_in_dir_item(struct reiserfs_dir_entry *de, loff_t off) // comment? maybe something like set de to point to what the path points to? static inline void set_de_item_location(struct reiserfs_dir_entry *de, - struct path *path) + struct treepath *path) { de->de_bh = get_last_bh(path); de->de_ih = get_ih(path); @@ -113,7 +113,7 @@ entry position in the item /* The function is NOT SCHEDULE-SAFE! */ int search_by_entry_key(struct super_block *sb, const struct cpu_key *key, - struct path *path, struct reiserfs_dir_entry *de) + struct treepath *path, struct reiserfs_dir_entry *de) { int retval; @@ -282,7 +282,7 @@ static int linear_search_in_dir_item(struct cpu_key *key, // may return NAME_FOUND, NAME_FOUND_INVISIBLE, NAME_NOT_FOUND // FIXME: should add something like IOERROR static int reiserfs_find_entry(struct inode *dir, const char *name, int namelen, - struct path *path_to_entry, + struct treepath *path_to_entry, struct reiserfs_dir_entry *de) { struct cpu_key key_to_search; diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c index c533ec1bcae..ecc9943202f 100644 --- a/fs/reiserfs/procfs.c +++ b/fs/reiserfs/procfs.c @@ -295,7 +295,7 @@ static int show_oidmap(struct seq_file *m, struct super_block *sb) } #if defined( REISERFS_USE_OIDMAPF ) if (sb_info->oidmap.use_file && (sb_info->oidmap.mapf != NULL)) { - loff_t size = sb_info->oidmap.mapf->f_dentry->d_inode->i_size; + loff_t size = sb_info->oidmap.mapf->f_path.dentry->d_inode->i_size; total_used += size / sizeof(reiserfs_oidinterval_d_t); } #endif diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c index 5240abe1a70..47e7027ea39 100644 --- a/fs/reiserfs/stree.c +++ b/fs/reiserfs/stree.c @@ -244,7 +244,7 @@ static const struct reiserfs_key MAX_KEY = { of the path, and going upwards. We must check the path's validity at each step. If the key is not in the path, there is no delimiting key in the tree (buffer is first or last buffer in tree), and in this case we return a special key, either MIN_KEY or MAX_KEY. */ -static inline const struct reiserfs_key *get_lkey(const struct path +static inline const struct reiserfs_key *get_lkey(const struct treepath *p_s_chk_path, const struct super_block *p_s_sb) @@ -290,7 +290,7 @@ static inline const struct reiserfs_key *get_lkey(const struct path } /* Get delimiting key of the buffer at the path and its right neighbor. */ -inline const struct reiserfs_key *get_rkey(const struct path *p_s_chk_path, +inline const struct reiserfs_key *get_rkey(const struct treepath *p_s_chk_path, const struct super_block *p_s_sb) { int n_position, n_path_offset = p_s_chk_path->path_length; @@ -337,7 +337,7 @@ inline const struct reiserfs_key *get_rkey(const struct path *p_s_chk_path, the path. These delimiting keys are stored at least one level above that buffer in the tree. If the buffer is the first or last node in the tree order then one of the delimiting keys may be absent, and in this case get_lkey and get_rkey return a special key which is MIN_KEY or MAX_KEY. */ -static inline int key_in_buffer(struct path *p_s_chk_path, /* Path which should be checked. */ +static inline int key_in_buffer(struct treepath *p_s_chk_path, /* Path which should be checked. */ const struct cpu_key *p_s_key, /* Key which should be checked. */ struct super_block *p_s_sb /* Super block pointer. */ ) @@ -374,7 +374,7 @@ inline void decrement_bcount(struct buffer_head *p_s_bh) } /* Decrement b_count field of the all buffers in the path. */ -void decrement_counters_in_path(struct path *p_s_search_path) +void decrement_counters_in_path(struct treepath *p_s_search_path) { int n_path_offset = p_s_search_path->path_length; @@ -391,7 +391,7 @@ void decrement_counters_in_path(struct path *p_s_search_path) p_s_search_path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET; } -int reiserfs_check_path(struct path *p) +int reiserfs_check_path(struct treepath *p) { RFALSE(p->path_length != ILLEGAL_PATH_ELEMENT_OFFSET, "path not properly relsed"); @@ -403,7 +403,7 @@ int reiserfs_check_path(struct path *p) ** ** only called from fix_nodes() */ -void pathrelse_and_restore(struct super_block *s, struct path *p_s_search_path) +void pathrelse_and_restore(struct super_block *s, struct treepath *p_s_search_path) { int n_path_offset = p_s_search_path->path_length; @@ -421,7 +421,7 @@ void pathrelse_and_restore(struct super_block *s, struct path *p_s_search_path) } /* Release all buffers in the path. */ -void pathrelse(struct path *p_s_search_path) +void pathrelse(struct treepath *p_s_search_path) { int n_path_offset = p_s_search_path->path_length; @@ -602,7 +602,7 @@ static void search_by_key_reada(struct super_block *s, correctness of the bottom of the path */ /* The function is NOT SCHEDULE-SAFE! */ int search_by_key(struct super_block *p_s_sb, const struct cpu_key *p_s_key, /* Key to search. */ - struct path *p_s_search_path, /* This structure was + struct treepath *p_s_search_path,/* This structure was allocated and initialized by the calling function. It is filled up @@ -813,7 +813,7 @@ int search_by_key(struct super_block *p_s_sb, const struct cpu_key *p_s_key, /* /* The function is NOT SCHEDULE-SAFE! */ int search_for_position_by_key(struct super_block *p_s_sb, /* Pointer to the super block. */ const struct cpu_key *p_cpu_key, /* Key to search (cpu variable) */ - struct path *p_s_search_path /* Filled up by this function. */ + struct treepath *p_s_search_path /* Filled up by this function. */ ) { struct item_head *p_le_ih; /* pointer to on-disk structure */ @@ -884,7 +884,7 @@ int search_for_position_by_key(struct super_block *p_s_sb, /* Pointer to the sup } /* Compare given item and item pointed to by the path. */ -int comp_items(const struct item_head *stored_ih, const struct path *p_s_path) +int comp_items(const struct item_head *stored_ih, const struct treepath *p_s_path) { struct buffer_head *p_s_bh; struct item_head *ih; @@ -911,7 +911,7 @@ int comp_items(const struct item_head *stored_ih, const struct path *p_s_path) #define block_in_use(bh) (buffer_locked(bh) || (held_by_others(bh))) // prepare for delete or cut of direct item -static inline int prepare_for_direct_item(struct path *path, +static inline int prepare_for_direct_item(struct treepath *path, struct item_head *le_ih, struct inode *inode, loff_t new_file_length, int *cut_size) @@ -952,7 +952,7 @@ static inline int prepare_for_direct_item(struct path *path, return M_CUT; /* Cut from this item. */ } -static inline int prepare_for_direntry_item(struct path *path, +static inline int prepare_for_direntry_item(struct treepath *path, struct item_head *le_ih, struct inode *inode, loff_t new_file_length, @@ -987,7 +987,7 @@ static inline int prepare_for_direntry_item(struct path *path, In case of file truncate calculate whether this item must be deleted/truncated or last unformatted node of this item will be converted to a direct item. This function returns a determination of what balance mode the calling function should employ. */ -static char prepare_for_delete_or_cut(struct reiserfs_transaction_handle *th, struct inode *inode, struct path *p_s_path, const struct cpu_key *p_s_item_key, int *p_n_removed, /* Number of unformatted nodes which were removed +static char prepare_for_delete_or_cut(struct reiserfs_transaction_handle *th, struct inode *inode, struct treepath *p_s_path, const struct cpu_key *p_s_item_key, int *p_n_removed, /* Number of unformatted nodes which were removed from end of the file. */ int *p_n_cut_size, unsigned long long n_new_file_length /* MAX_KEY_OFFSET in case of delete. */ ) @@ -1125,7 +1125,7 @@ static int calc_deleted_bytes_number(struct tree_balance *p_s_tb, char c_mode) static void init_tb_struct(struct reiserfs_transaction_handle *th, struct tree_balance *p_s_tb, struct super_block *p_s_sb, - struct path *p_s_path, int n_size) + struct treepath *p_s_path, int n_size) { BUG_ON(!th->t_trans_id); @@ -1176,7 +1176,7 @@ char head2type(struct item_head *ih) #endif /* Delete object item. */ -int reiserfs_delete_item(struct reiserfs_transaction_handle *th, struct path *p_s_path, /* Path to the deleted item. */ +int reiserfs_delete_item(struct reiserfs_transaction_handle *th, struct treepath *p_s_path, /* Path to the deleted item. */ const struct cpu_key *p_s_item_key, /* Key to search for the deleted item. */ struct inode *p_s_inode, /* inode is here just to update i_blocks and quotas */ struct buffer_head *p_s_un_bh) @@ -1468,7 +1468,7 @@ static void unmap_buffers(struct page *page, loff_t pos) static int maybe_indirect_to_direct(struct reiserfs_transaction_handle *th, struct inode *p_s_inode, struct page *page, - struct path *p_s_path, + struct treepath *p_s_path, const struct cpu_key *p_s_item_key, loff_t n_new_file_size, char *p_c_mode) { @@ -1503,7 +1503,7 @@ static int maybe_indirect_to_direct(struct reiserfs_transaction_handle *th, pointer being converted. Therefore we have to delete inserted direct item(s) */ static void indirect_to_direct_roll_back(struct reiserfs_transaction_handle *th, - struct inode *inode, struct path *path) + struct inode *inode, struct treepath *path) { struct cpu_key tail_key; int tail_len; @@ -1545,7 +1545,7 @@ static void indirect_to_direct_roll_back(struct reiserfs_transaction_handle *th, /* (Truncate or cut entry) or delete object item. Returns < 0 on failure */ int reiserfs_cut_from_item(struct reiserfs_transaction_handle *th, - struct path *p_s_path, + struct treepath *p_s_path, struct cpu_key *p_s_item_key, struct inode *p_s_inode, struct page *page, loff_t n_new_file_size) @@ -1920,7 +1920,7 @@ int reiserfs_do_truncate(struct reiserfs_transaction_handle *th, struct inode *p #ifdef CONFIG_REISERFS_CHECK // this makes sure, that we __append__, not overwrite or add holes -static void check_research_for_paste(struct path *path, +static void check_research_for_paste(struct treepath *path, const struct cpu_key *p_s_key) { struct item_head *found_ih = get_ih(path); @@ -1954,7 +1954,7 @@ static void check_research_for_paste(struct path *path, #endif /* config reiserfs check */ /* Paste bytes to the existing item. Returns bytes number pasted into the item. */ -int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct path *p_s_search_path, /* Path to the pasted item. */ +int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct treepath *p_s_search_path, /* Path to the pasted item. */ const struct cpu_key *p_s_key, /* Key to search for the needed item. */ struct inode *inode, /* Inode item belongs to */ const char *p_c_body, /* Pointer to the bytes to paste. */ @@ -2036,7 +2036,7 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct path } /* Insert new item into the buffer at the path. */ -int reiserfs_insert_item(struct reiserfs_transaction_handle *th, struct path *p_s_path, /* Path to the inserteded item. */ +int reiserfs_insert_item(struct reiserfs_transaction_handle *th, struct treepath *p_s_path, /* Path to the inserteded item. */ const struct cpu_key *key, struct item_head *p_s_ih, /* Pointer to the item header to insert. */ struct inode *inode, const char *p_c_body) { /* Pointer to the bytes to insert. */ diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 7fb5fb036f9..58ad4551a7c 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -23,7 +23,7 @@ #include <linux/blkdev.h> #include <linux/buffer_head.h> #include <linux/vfs.h> -#include <linux/namespace.h> +#include <linux/mnt_namespace.h> #include <linux/mount.h> #include <linux/namei.h> #include <linux/quotaops.h> diff --git a/fs/reiserfs/tail_conversion.c b/fs/reiserfs/tail_conversion.c index 36f108fc1cf..f8121a1147e 100644 --- a/fs/reiserfs/tail_conversion.c +++ b/fs/reiserfs/tail_conversion.c @@ -15,7 +15,7 @@ /* path points to first direct item of the file regarless of how many of them are there */ int direct2indirect(struct reiserfs_transaction_handle *th, struct inode *inode, - struct path *path, struct buffer_head *unbh, + struct treepath *path, struct buffer_head *unbh, loff_t tail_offset) { struct super_block *sb = inode->i_sb; @@ -171,7 +171,7 @@ void reiserfs_unmap_buffer(struct buffer_head *bh) what we expect from it (number of cut bytes). But when tail remains in the unformatted node, we set mode to SKIP_BALANCING and unlock inode */ -int indirect2direct(struct reiserfs_transaction_handle *th, struct inode *p_s_inode, struct page *page, struct path *p_s_path, /* path to the indirect item. */ +int indirect2direct(struct reiserfs_transaction_handle *th, struct inode *p_s_inode, struct page *page, struct treepath *p_s_path, /* path to the indirect item. */ const struct cpu_key *p_s_item_key, /* Key to look for unformatted node pointer to be cut. */ loff_t n_new_file_size, /* New file size. */ char *p_c_mode) diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 1e4d6859017..f01389fd162 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c @@ -274,7 +274,7 @@ static struct file *open_xa_file(const struct inode *inode, const char *name, */ static int __xattr_readdir(struct file *filp, void *dirent, filldir_t filldir) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct cpu_key pos_key; /* key of current position in the directory (key of directory entry) */ INITIALIZE_PATH(path_to_entry); struct buffer_head *bh; @@ -420,7 +420,7 @@ static int __xattr_readdir(struct file *filp, void *dirent, filldir_t filldir) static int xattr_readdir(struct file *file, filldir_t filler, void *buf) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int res = -ENOTDIR; if (!file->f_op || !file->f_op->readdir) goto out; @@ -508,7 +508,7 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer, goto out; } - xinode = fp->f_dentry->d_inode; + xinode = fp->f_path.dentry->d_inode; REISERFS_I(inode)->i_flags |= i_has_xattr_dir; /* we need to copy it off.. */ @@ -527,7 +527,7 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer, newattrs.ia_size = buffer_size; newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; mutex_lock(&xinode->i_mutex); - err = notify_change(fp->f_dentry, &newattrs); + err = notify_change(fp->f_path.dentry, &newattrs); if (err) goto out_filp; @@ -626,7 +626,7 @@ reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer, goto out; } - xinode = fp->f_dentry->d_inode; + xinode = fp->f_path.dentry->d_inode; isize = xinode->i_size; REISERFS_I(inode)->i_flags |= i_has_xattr_dir; diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c index c5af088d4a4..d3e243a6f60 100644 --- a/fs/romfs/inode.c +++ b/fs/romfs/inode.c @@ -276,7 +276,7 @@ static unsigned char romfs_dtype_table[] = { static int romfs_readdir(struct file *filp, void *dirent, filldir_t filldir) { - struct inode *i = filp->f_dentry->d_inode; + struct inode *i = filp->f_path.dentry->d_inode; struct romfs_inode ri; unsigned long offset, maxoff; int j, ino, nextfh; diff --git a/fs/seq_file.c b/fs/seq_file.c index 10690aa401c..0ac22af7afe 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c @@ -269,7 +269,7 @@ EXPORT_SYMBOL(seq_lseek); /** * seq_release - free the structures associated with sequential file. * @file: file in question - * @inode: file->f_dentry->d_inode + * @inode: file->f_path.dentry->d_inode * * Frees the structures associated with sequential file; can be used * as ->f_op->release() if you don't have private data to destroy. diff --git a/fs/smbfs/cache.c b/fs/smbfs/cache.c index 74b86d9725a..8182f0542a2 100644 --- a/fs/smbfs/cache.c +++ b/fs/smbfs/cache.c @@ -125,7 +125,7 @@ smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir, struct smb_cache_control *ctrl, struct qstr *qname, struct smb_fattr *entry) { - struct dentry *newdent, *dentry = filp->f_dentry; + struct dentry *newdent, *dentry = filp->f_path.dentry; struct inode *newino, *inode = dentry->d_inode; struct smb_cache_control ctl = *ctrl; int valid = 0; diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c index 70d9c5a37f5..b1e58d1ac9c 100644 --- a/fs/smbfs/dir.c +++ b/fs/smbfs/dir.c @@ -78,7 +78,7 @@ struct inode_operations smb_dir_inode_operations_unix = static int smb_readdir(struct file *filp, void *dirent, filldir_t filldir) { - struct dentry *dentry = filp->f_dentry; + struct dentry *dentry = filp->f_path.dentry; struct inode *dir = dentry->d_inode; struct smb_sb_info *server = server_from_dentry(dentry); union smb_dir_cache *cache = NULL; @@ -238,12 +238,12 @@ out: static int smb_dir_open(struct inode *dir, struct file *file) { - struct dentry *dentry = file->f_dentry; + struct dentry *dentry = file->f_path.dentry; struct smb_sb_info *server; int error = 0; VERBOSE("(%s/%s)\n", dentry->d_parent->d_name.name, - file->f_dentry->d_name.name); + file->f_path.dentry->d_name.name); /* * Directory timestamps in the core protocol aren't updated diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c index 50784d13c87..e50533a7951 100644 --- a/fs/smbfs/file.c +++ b/fs/smbfs/file.c @@ -102,7 +102,7 @@ static int smb_readpage(struct file *file, struct page *page) { int error; - struct dentry *dentry = file->f_dentry; + struct dentry *dentry = file->f_path.dentry; page_cache_get(page); error = smb_readpage_sync(dentry, page); @@ -205,7 +205,7 @@ static int smb_updatepage(struct file *file, struct page *page, unsigned long offset, unsigned int count) { - struct dentry *dentry = file->f_dentry; + struct dentry *dentry = file->f_path.dentry; DEBUG1("(%s/%s %d@%lld)\n", DENTRY_PATH(dentry), count, ((unsigned long long)page->index << PAGE_CACHE_SHIFT) + offset); @@ -218,7 +218,7 @@ smb_file_aio_read(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { struct file * file = iocb->ki_filp; - struct dentry * dentry = file->f_dentry; + struct dentry * dentry = file->f_path.dentry; ssize_t status; VERBOSE("file %s/%s, count=%lu@%lu\n", DENTRY_PATH(dentry), @@ -243,7 +243,7 @@ out: static int smb_file_mmap(struct file * file, struct vm_area_struct * vma) { - struct dentry * dentry = file->f_dentry; + struct dentry * dentry = file->f_path.dentry; int status; VERBOSE("file %s/%s, address %lu - %lu\n", @@ -264,7 +264,7 @@ static ssize_t smb_file_sendfile(struct file *file, loff_t *ppos, size_t count, read_actor_t actor, void *target) { - struct dentry *dentry = file->f_dentry; + struct dentry *dentry = file->f_path.dentry; ssize_t status; VERBOSE("file %s/%s, pos=%Ld, count=%d\n", @@ -323,7 +323,7 @@ smb_file_aio_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { struct file * file = iocb->ki_filp; - struct dentry * dentry = file->f_dentry; + struct dentry * dentry = file->f_path.dentry; ssize_t result; VERBOSE("file %s/%s, count=%lu@%lu\n", @@ -355,7 +355,7 @@ static int smb_file_open(struct inode *inode, struct file * file) { int result; - struct dentry *dentry = file->f_dentry; + struct dentry *dentry = file->f_path.dentry; int smb_mode = (file->f_mode & O_ACCMODE) - 1; lock_kernel(); diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c index 40e174db987..a5ced9e0c6c 100644 --- a/fs/smbfs/proc.c +++ b/fs/smbfs/proc.c @@ -873,7 +873,7 @@ smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt) filp = fget(opt->fd); if (!filp) goto out; - if (!smb_valid_socket(filp->f_dentry->d_inode)) + if (!smb_valid_socket(filp->f_path.dentry->d_inode)) goto out_putf; server->sock_file = filp; @@ -898,7 +898,7 @@ smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt) /* * Store the server in sock user_data (Only used by sunrpc) */ - sk = SOCKET_I(filp->f_dentry->d_inode)->sk; + sk = SOCKET_I(filp->f_path.dentry->d_inode)->sk; sk->sk_user_data = server; /* chain into the data_ready callback */ @@ -1939,7 +1939,7 @@ static int smb_proc_readdir_short(struct file *filp, void *dirent, filldir_t filldir, struct smb_cache_control *ctl) { - struct dentry *dir = filp->f_dentry; + struct dentry *dir = filp->f_path.dentry; struct smb_sb_info *server = server_from_dentry(dir); struct qstr qname; struct smb_fattr fattr; @@ -2291,7 +2291,7 @@ static int smb_proc_readdir_long(struct file *filp, void *dirent, filldir_t filldir, struct smb_cache_control *ctl) { - struct dentry *dir = filp->f_dentry; + struct dentry *dir = filp->f_path.dentry; struct smb_sb_info *server = server_from_dentry(dir); struct qstr qname; struct smb_fattr fattr; @@ -2859,7 +2859,7 @@ static int smb_proc_readdir_null(struct file *filp, void *dirent, filldir_t filldir, struct smb_cache_control *ctl) { - struct smb_sb_info *server = server_from_dentry(filp->f_dentry); + struct smb_sb_info *server = server_from_dentry(filp->f_path.dentry); if (smb_proc_ops_wait(server) < 0) return -EIO; diff --git a/fs/smbfs/sock.c b/fs/smbfs/sock.c index 6815b1b12b6..92ea6b2367d 100644 --- a/fs/smbfs/sock.c +++ b/fs/smbfs/sock.c @@ -82,10 +82,10 @@ server_sock(struct smb_sb_info *server) if (server && (file = server->sock_file)) { #ifdef SMBFS_PARANOIA - if (!smb_valid_socket(file->f_dentry->d_inode)) + if (!smb_valid_socket(file->f_path.dentry->d_inode)) PARANOIA("bad socket!\n"); #endif - return SOCKET_I(file->f_dentry->d_inode); + return SOCKET_I(file->f_path.dentry->d_inode); } return NULL; } diff --git a/fs/splice.c b/fs/splice.c index da74583a00e..bbd0aeb3f68 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -844,7 +844,7 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out, ssize_t ret; int err; - err = remove_suid(out->f_dentry); + err = remove_suid(out->f_path.dentry); if (unlikely(err)) return err; @@ -890,10 +890,10 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, ssize_t ret; int err; - err = should_remove_suid(out->f_dentry); + err = should_remove_suid(out->f_path.dentry); if (unlikely(err)) { mutex_lock(&inode->i_mutex); - err = __remove_suid(out->f_dentry, err); + err = __remove_suid(out->f_path.dentry, err); mutex_unlock(&inode->i_mutex); if (err) return err; @@ -1008,7 +1008,7 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, * randomly drop data for eg socket -> socket splicing. Use the * piped splicing for that! */ - i_mode = in->f_dentry->d_inode->i_mode; + i_mode = in->f_path.dentry->d_inode->i_mode; if (unlikely(!S_ISREG(i_mode) && !S_ISBLK(i_mode))) return -EINVAL; @@ -1132,7 +1132,7 @@ static long do_splice(struct file *in, loff_t __user *off_in, loff_t offset, *off; long ret; - pipe = pipe_info(in->f_dentry->d_inode); + pipe = pipe_info(in->f_path.dentry->d_inode); if (pipe) { if (off_in) return -ESPIPE; @@ -1153,7 +1153,7 @@ static long do_splice(struct file *in, loff_t __user *off_in, return ret; } - pipe = pipe_info(out->f_dentry->d_inode); + pipe = pipe_info(out->f_path.dentry->d_inode); if (pipe) { if (off_out) return -ESPIPE; @@ -1321,7 +1321,7 @@ static long do_vmsplice(struct file *file, const struct iovec __user *iov, .ops = &user_page_pipe_buf_ops, }; - pipe = pipe_info(file->f_dentry->d_inode); + pipe = pipe_info(file->f_path.dentry->d_inode); if (!pipe) return -EBADF; if (unlikely(nr_segs > UIO_MAXIOV)) @@ -1549,8 +1549,8 @@ static int link_pipe(struct pipe_inode_info *ipipe, static long do_tee(struct file *in, struct file *out, size_t len, unsigned int flags) { - struct pipe_inode_info *ipipe = pipe_info(in->f_dentry->d_inode); - struct pipe_inode_info *opipe = pipe_info(out->f_dentry->d_inode); + struct pipe_inode_info *ipipe = pipe_info(in->f_path.dentry->d_inode); + struct pipe_inode_info *opipe = pipe_info(out->f_path.dentry->d_inode); int ret = -EINVAL; /* diff --git a/fs/stack.c b/fs/stack.c new file mode 100644 index 00000000000..5ddbc34535f --- /dev/null +++ b/fs/stack.c @@ -0,0 +1,40 @@ +#include <linux/module.h> +#include <linux/fs.h> +#include <linux/fs_stack.h> + +/* does _NOT_ require i_mutex to be held. + * + * This function cannot be inlined since i_size_{read,write} is rather + * heavy-weight on 32-bit systems + */ +void fsstack_copy_inode_size(struct inode *dst, const struct inode *src) +{ + i_size_write(dst, i_size_read((struct inode *)src)); + dst->i_blocks = src->i_blocks; +} +EXPORT_SYMBOL_GPL(fsstack_copy_inode_size); + +/* copy all attributes; get_nlinks is optional way to override the i_nlink + * copying + */ +void fsstack_copy_attr_all(struct inode *dest, const struct inode *src, + int (*get_nlinks)(struct inode *)) +{ + if (!get_nlinks) + dest->i_nlink = src->i_nlink; + else + dest->i_nlink = (*get_nlinks)(dest); + + dest->i_mode = src->i_mode; + dest->i_uid = src->i_uid; + dest->i_gid = src->i_gid; + dest->i_rdev = src->i_rdev; + dest->i_atime = src->i_atime; + dest->i_mtime = src->i_mtime; + dest->i_ctime = src->i_ctime; + dest->i_blkbits = src->i_blkbits; + dest->i_flags = src->i_flags; + + fsstack_copy_inode_size(dest, src); +} +EXPORT_SYMBOL_GPL(fsstack_copy_attr_all); diff --git a/fs/stat.c b/fs/stat.c index a0ebfc7f8a6..38a8cb2a28d 100644 --- a/fs/stat.c +++ b/fs/stat.c @@ -102,7 +102,7 @@ int vfs_fstat(unsigned int fd, struct kstat *stat) int error = -EBADF; if (f) { - error = vfs_getattr(f->f_vfsmnt, f->f_dentry, stat); + error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, stat); fput(f); } return error; diff --git a/fs/super.c b/fs/super.c index 84c320f6ad7..f961e030799 100644 --- a/fs/super.c +++ b/fs/super.c @@ -570,7 +570,7 @@ static void mark_files_ro(struct super_block *sb) file_list_lock(); list_for_each_entry(f, &sb->s_files, f_u.fu_list) { - if (S_ISREG(f->f_dentry->d_inode->i_mode) && file_count(f)) + if (S_ISREG(f->f_path.dentry->d_inode->i_mode) && file_count(f)) f->f_mode &= ~FMODE_WRITE; } file_list_unlock(); diff --git a/fs/sync.c b/fs/sync.c index 865f32be386..d0feff61e6a 100644 --- a/fs/sync.c +++ b/fs/sync.c @@ -94,7 +94,7 @@ long do_fsync(struct file *file, int datasync) * livelocks in fsync_buffers_list(). */ mutex_lock(&mapping->host->i_mutex); - err = file->f_op->fsync(file, file->f_dentry, datasync); + err = file->f_op->fsync(file, file->f_path.dentry, datasync); if (!ret) ret = err; mutex_unlock(&mapping->host->i_mutex); @@ -223,7 +223,7 @@ asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes, if (!file) goto out; - i_mode = file->f_dentry->d_inode->i_mode; + i_mode = file->f_path.dentry->d_inode->i_mode; ret = -ESPIPE; if (!S_ISREG(i_mode) && !S_ISBLK(i_mode) && !S_ISDIR(i_mode) && !S_ISLNK(i_mode)) diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index 98022e41cda..e8f540d38d4 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c @@ -35,7 +35,7 @@ static ssize_t read(struct file * file, char __user * userbuf, size_t count, loff_t * off) { char *buffer = file->private_data; - struct dentry *dentry = file->f_dentry; + struct dentry *dentry = file->f_path.dentry; int size = dentry->d_inode->i_size; loff_t offs = *off; int ret; @@ -81,7 +81,7 @@ static ssize_t write(struct file * file, const char __user * userbuf, size_t count, loff_t * off) { char *buffer = file->private_data; - struct dentry *dentry = file->f_dentry; + struct dentry *dentry = file->f_path.dentry; int size = dentry->d_inode->i_size; loff_t offs = *off; @@ -105,7 +105,7 @@ static ssize_t write(struct file * file, const char __user * userbuf, static int mmap(struct file *file, struct vm_area_struct *vma) { - struct dentry *dentry = file->f_dentry; + struct dentry *dentry = file->f_path.dentry; struct bin_attribute *attr = to_bin_attr(dentry); struct kobject *kobj = to_kobj(dentry->d_parent); @@ -117,8 +117,8 @@ static int mmap(struct file *file, struct vm_area_struct *vma) static int open(struct inode * inode, struct file * file) { - struct kobject *kobj = sysfs_get_kobject(file->f_dentry->d_parent); - struct bin_attribute * attr = to_bin_attr(file->f_dentry); + struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent); + struct bin_attribute * attr = to_bin_attr(file->f_path.dentry); int error = -EINVAL; if (!kobj || !attr) @@ -153,8 +153,8 @@ static int open(struct inode * inode, struct file * file) static int release(struct inode * inode, struct file * file) { - struct kobject * kobj = to_kobj(file->f_dentry->d_parent); - struct bin_attribute * attr = to_bin_attr(file->f_dentry); + struct kobject * kobj = to_kobj(file->f_path.dentry->d_parent); + struct bin_attribute * attr = to_bin_attr(file->f_path.dentry); u8 * buffer = file->private_data; if (kobj) diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index a5782e8c7f0..511edef8b32 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -419,7 +419,7 @@ out: static int sysfs_dir_open(struct inode *inode, struct file *file) { - struct dentry * dentry = file->f_dentry; + struct dentry * dentry = file->f_path.dentry; struct sysfs_dirent * parent_sd = dentry->d_fsdata; mutex_lock(&dentry->d_inode->i_mutex); @@ -432,7 +432,7 @@ static int sysfs_dir_open(struct inode *inode, struct file *file) static int sysfs_dir_close(struct inode *inode, struct file *file) { - struct dentry * dentry = file->f_dentry; + struct dentry * dentry = file->f_path.dentry; struct sysfs_dirent * cursor = file->private_data; mutex_lock(&dentry->d_inode->i_mutex); @@ -452,7 +452,7 @@ static inline unsigned char dt_type(struct sysfs_dirent *sd) static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) { - struct dentry *dentry = filp->f_dentry; + struct dentry *dentry = filp->f_path.dentry; struct sysfs_dirent * parent_sd = dentry->d_fsdata; struct sysfs_dirent *cursor = filp->private_data; struct list_head *p, *q = &cursor->s_sibling; @@ -509,7 +509,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin) { - struct dentry * dentry = file->f_dentry; + struct dentry * dentry = file->f_path.dentry; mutex_lock(&dentry->d_inode->i_mutex); switch (origin) { @@ -519,7 +519,7 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin) if (offset >= 0) break; default: - mutex_unlock(&file->f_dentry->d_inode->i_mutex); + mutex_unlock(&file->f_path.dentry->d_inode->i_mutex); return -EINVAL; } if (offset != file->f_pos) { diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 95c165101c9..9cfe53e1e00 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -154,7 +154,7 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos) down(&buffer->sem); if (buffer->needs_read_fill) { - if ((retval = fill_read_buffer(file->f_dentry,buffer))) + if ((retval = fill_read_buffer(file->f_path.dentry,buffer))) goto out; } pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n", @@ -245,7 +245,7 @@ sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t down(&buffer->sem); len = fill_write_buffer(buffer, buf, count); if (len > 0) - len = flush_write_buffer(file->f_dentry, buffer, len); + len = flush_write_buffer(file->f_path.dentry, buffer, len); if (len > 0) *ppos += len; up(&buffer->sem); @@ -254,8 +254,8 @@ sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t static int check_perm(struct inode * inode, struct file * file) { - struct kobject *kobj = sysfs_get_kobject(file->f_dentry->d_parent); - struct attribute * attr = to_attr(file->f_dentry); + struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent); + struct attribute * attr = to_attr(file->f_path.dentry); struct sysfs_buffer * buffer; struct sysfs_ops * ops = NULL; int error = 0; @@ -337,8 +337,8 @@ static int sysfs_open_file(struct inode * inode, struct file * filp) static int sysfs_release(struct inode * inode, struct file * filp) { - struct kobject * kobj = to_kobj(filp->f_dentry->d_parent); - struct attribute * attr = to_attr(filp->f_dentry); + struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent); + struct attribute * attr = to_attr(filp->f_path.dentry); struct module * owner = attr->owner; struct sysfs_buffer * buffer = filp->private_data; @@ -372,8 +372,8 @@ static int sysfs_release(struct inode * inode, struct file * filp) static unsigned int sysfs_poll(struct file *filp, poll_table *wait) { struct sysfs_buffer * buffer = filp->private_data; - struct kobject * kobj = to_kobj(filp->f_dentry->d_parent); - struct sysfs_dirent * sd = filp->f_dentry->d_fsdata; + struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent); + struct sysfs_dirent * sd = filp->f_path.dentry->d_fsdata; int res = 0; poll_wait(filp, &kobj->poll, wait); diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c index f2bef962d30..ebf7007fa16 100644 --- a/fs/sysv/dir.c +++ b/fs/sysv/dir.c @@ -70,7 +70,7 @@ fail: static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir) { unsigned long pos = filp->f_pos; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct super_block *sb = inode->i_sb; unsigned offset = pos & ~PAGE_CACHE_MASK; unsigned long n = pos >> PAGE_CACHE_SHIFT; diff --git a/fs/udf/dir.c b/fs/udf/dir.c index 8c28efa3b8f..2391c9150c4 100644 --- a/fs/udf/dir.c +++ b/fs/udf/dir.c @@ -77,7 +77,7 @@ const struct file_operations udf_dir_operations = { int udf_readdir(struct file *filp, void *dirent, filldir_t filldir) { - struct inode *dir = filp->f_dentry->d_inode; + struct inode *dir = filp->f_path.dentry->d_inode; int result; lock_kernel(); @@ -225,7 +225,7 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d if ( cfi.fileCharacteristics & FID_FILE_CHAR_PARENT ) { - iblock = parent_ino(filp->f_dentry); + iblock = parent_ino(filp->f_path.dentry); flen = 2; memcpy(fname, "..", flen); dt_type = DT_DIR; diff --git a/fs/udf/file.c b/fs/udf/file.c index 7aedd552cba..d81f2db7b0e 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -108,7 +108,7 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, { ssize_t retval; struct file *file = iocb->ki_filp; - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int err, pos; size_t count = iocb->ki_left; diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c index 7f0a0aa6358..433b6f68403 100644 --- a/fs/ufs/dir.c +++ b/fs/ufs/dir.c @@ -426,7 +426,7 @@ static int ufs_readdir(struct file *filp, void *dirent, filldir_t filldir) { loff_t pos = filp->f_pos; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct super_block *sb = inode->i_sb; unsigned int offset = pos & ~PAGE_CACHE_MASK; unsigned long n = pos >> PAGE_CACHE_SHIFT; diff --git a/fs/xattr.c b/fs/xattr.c index 0901bdc2ce2..38646132ab0 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -268,7 +268,7 @@ sys_fsetxattr(int fd, char __user *name, void __user *value, f = fget(fd); if (!f) return error; - dentry = f->f_dentry; + dentry = f->f_path.dentry; audit_inode(NULL, dentry->d_inode); error = setxattr(dentry, name, value, size, flags); fput(f); @@ -351,7 +351,7 @@ sys_fgetxattr(int fd, char __user *name, void __user *value, size_t size) f = fget(fd); if (!f) return error; - error = getxattr(f->f_dentry, name, value, size); + error = getxattr(f->f_path.dentry, name, value, size); fput(f); return error; } @@ -423,7 +423,7 @@ sys_flistxattr(int fd, char __user *list, size_t size) f = fget(fd); if (!f) return error; - error = listxattr(f->f_dentry, list, size); + error = listxattr(f->f_path.dentry, list, size); fput(f); return error; } @@ -484,7 +484,7 @@ sys_fremovexattr(int fd, char __user *name) f = fget(fd); if (!f) return error; - dentry = f->f_dentry; + dentry = f->f_path.dentry; audit_inode(NULL, dentry->d_inode); error = removexattr(dentry, name); fput(f); diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index d93d8dd1958..d26f5cd2ba7 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c @@ -55,7 +55,7 @@ __xfs_file_read( loff_t pos) { struct file *file = iocb->ki_filp; - bhv_vnode_t *vp = vn_from_inode(file->f_dentry->d_inode); + bhv_vnode_t *vp = vn_from_inode(file->f_path.dentry->d_inode); BUG_ON(iocb->ki_pos != pos); if (unlikely(file->f_flags & O_DIRECT)) @@ -131,7 +131,7 @@ xfs_file_sendfile( read_actor_t actor, void *target) { - return bhv_vop_sendfile(vn_from_inode(filp->f_dentry->d_inode), + return bhv_vop_sendfile(vn_from_inode(filp->f_path.dentry->d_inode), filp, pos, 0, count, actor, target, NULL); } @@ -143,7 +143,7 @@ xfs_file_sendfile_invis( read_actor_t actor, void *target) { - return bhv_vop_sendfile(vn_from_inode(filp->f_dentry->d_inode), + return bhv_vop_sendfile(vn_from_inode(filp->f_path.dentry->d_inode), filp, pos, IO_INVIS, count, actor, target, NULL); } @@ -155,7 +155,7 @@ xfs_file_splice_read( size_t len, unsigned int flags) { - return bhv_vop_splice_read(vn_from_inode(infilp->f_dentry->d_inode), + return bhv_vop_splice_read(vn_from_inode(infilp->f_path.dentry->d_inode), infilp, ppos, pipe, len, flags, 0, NULL); } @@ -167,7 +167,7 @@ xfs_file_splice_read_invis( size_t len, unsigned int flags) { - return bhv_vop_splice_read(vn_from_inode(infilp->f_dentry->d_inode), + return bhv_vop_splice_read(vn_from_inode(infilp->f_path.dentry->d_inode), infilp, ppos, pipe, len, flags, IO_INVIS, NULL); } @@ -180,7 +180,7 @@ xfs_file_splice_write( size_t len, unsigned int flags) { - return bhv_vop_splice_write(vn_from_inode(outfilp->f_dentry->d_inode), + return bhv_vop_splice_write(vn_from_inode(outfilp->f_path.dentry->d_inode), pipe, outfilp, ppos, len, flags, 0, NULL); } @@ -192,7 +192,7 @@ xfs_file_splice_write_invis( size_t len, unsigned int flags) { - return bhv_vop_splice_write(vn_from_inode(outfilp->f_dentry->d_inode), + return bhv_vop_splice_write(vn_from_inode(outfilp->f_path.dentry->d_inode), pipe, outfilp, ppos, len, flags, IO_INVIS, NULL); } @@ -212,7 +212,7 @@ xfs_file_close( struct file *filp, fl_owner_t id) { - return -bhv_vop_close(vn_from_inode(filp->f_dentry->d_inode), 0, + return -bhv_vop_close(vn_from_inode(filp->f_path.dentry->d_inode), 0, file_count(filp) > 1 ? L_FALSE : L_TRUE, NULL); } @@ -251,7 +251,7 @@ xfs_vm_nopage( unsigned long address, int *type) { - struct inode *inode = area->vm_file->f_dentry->d_inode; + struct inode *inode = area->vm_file->f_path.dentry->d_inode; bhv_vnode_t *vp = vn_from_inode(inode); ASSERT_ALWAYS(vp->v_vfsp->vfs_flag & VFS_DMI); @@ -268,7 +268,7 @@ xfs_file_readdir( filldir_t filldir) { int error = 0; - bhv_vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode); + bhv_vnode_t *vp = vn_from_inode(filp->f_path.dentry->d_inode); uio_t uio; iovec_t iov; int eof = 0; @@ -345,7 +345,7 @@ xfs_file_mmap( vma->vm_ops = &xfs_file_vm_ops; #ifdef CONFIG_XFS_DMAPI - if (vn_from_inode(filp->f_dentry->d_inode)->v_vfsp->vfs_flag & VFS_DMI) + if (vn_from_inode(filp->f_path.dentry->d_inode)->v_vfsp->vfs_flag & VFS_DMI) vma->vm_ops = &xfs_dmapi_file_vm_ops; #endif /* CONFIG_XFS_DMAPI */ @@ -360,7 +360,7 @@ xfs_file_ioctl( unsigned long p) { int error; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; bhv_vnode_t *vp = vn_from_inode(inode); error = bhv_vop_ioctl(vp, inode, filp, 0, cmd, (void __user *)p); @@ -382,7 +382,7 @@ xfs_file_ioctl_invis( unsigned long p) { int error; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; bhv_vnode_t *vp = vn_from_inode(inode); error = bhv_vop_ioctl(vp, inode, filp, IO_INVIS, cmd, (void __user *)p); @@ -404,7 +404,7 @@ xfs_vm_mprotect( struct vm_area_struct *vma, unsigned int newflags) { - bhv_vnode_t *vp = vn_from_inode(vma->vm_file->f_dentry->d_inode); + bhv_vnode_t *vp = vn_from_inode(vma->vm_file->f_path.dentry->d_inode); int error = 0; if (vp->v_vfsp->vfs_flag & VFS_DMI) { diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index 74d094829a4..f011c9cd0d6 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c @@ -107,9 +107,9 @@ xfs_find_handle( if (!file) return -EBADF; - ASSERT(file->f_dentry); - ASSERT(file->f_dentry->d_inode); - inode = igrab(file->f_dentry->d_inode); + ASSERT(file->f_path.dentry); + ASSERT(file->f_path.dentry->d_inode); + inode = igrab(file->f_path.dentry->d_inode); fput(file); break; } @@ -333,10 +333,10 @@ xfs_open_by_handle( } /* Ensure umount returns EBUSY on umounts while this file is open. */ - mntget(parfilp->f_vfsmnt); + mntget(parfilp->f_path.mnt); /* Create file pointer. */ - filp = dentry_open(dentry, parfilp->f_vfsmnt, hreq.oflags); + filp = dentry_open(dentry, parfilp->f_path.mnt, hreq.oflags); if (IS_ERR(filp)) { put_unused_fd(new_fd); return -XFS_ERROR(-PTR_ERR(filp)); diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c index 270db0f3861..b83cebc165f 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl32.c +++ b/fs/xfs/linux-2.6/xfs_ioctl32.c @@ -112,7 +112,7 @@ xfs_compat_ioctl( unsigned cmd, unsigned long arg) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; bhv_vnode_t *vp = vn_from_inode(inode); int error; diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index fa842f1c9fa..65e79b471d4 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c @@ -805,7 +805,7 @@ start: !capable(CAP_FSETID)) { error = xfs_write_clear_setuid(xip); if (likely(!error)) - error = -remove_suid(file->f_dentry); + error = -remove_suid(file->f_path.dentry); if (unlikely(error)) { xfs_iunlock(xip, iolock); goto out_unlock_mutex; diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index 80562b60fb9..50d0faea371 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c @@ -71,7 +71,7 @@ xfs_swapext( /* Pull information for the target fd */ if (((fp = fget((int)sxp->sx_fdtarget)) == NULL) || - ((vp = vn_from_inode(fp->f_dentry->d_inode)) == NULL)) { + ((vp = vn_from_inode(fp->f_path.dentry->d_inode)) == NULL)) { error = XFS_ERROR(EINVAL); goto error0; } @@ -83,7 +83,7 @@ xfs_swapext( } if (((tfp = fget((int)sxp->sx_fdtmp)) == NULL) || - ((tvp = vn_from_inode(tfp->f_dentry->d_inode)) == NULL)) { + ((tvp = vn_from_inode(tfp->f_path.dentry->d_inode)) == NULL)) { error = XFS_ERROR(EINVAL); goto error0; } diff --git a/include/asm-alpha/termbits.h b/include/asm-alpha/termbits.h index 5541101b58a..ad854a4a3af 100644 --- a/include/asm-alpha/termbits.h +++ b/include/asm-alpha/termbits.h @@ -25,6 +25,19 @@ struct termios { speed_t c_ospeed; /* output speed */ }; +/* Alpha has matching termios and ktermios */ + +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_cc[NCCS]; /* control characters */ + cc_t c_line; /* line discipline (== c_cc[19]) */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VEOF 0 #define VEOL 1 diff --git a/include/asm-arm/arch-s3c2410/fb.h b/include/asm-arm/arch-s3c2410/fb.h index 90894214cac..93a58e7862b 100644 --- a/include/asm-arm/arch-s3c2410/fb.h +++ b/include/asm-arm/arch-s3c2410/fb.h @@ -31,6 +31,9 @@ struct s3c2410fb_hw { struct s3c2410fb_mach_info { unsigned char fixed_syncs; /* do not update sync/border */ + /* LCD types */ + int type; + /* Screen size */ int width; int height; diff --git a/include/asm-arm/termbits.h b/include/asm-arm/termbits.h index bbc6e1d24d3..a3f4fe1742d 100644 --- a/include/asm-arm/termbits.h +++ b/include/asm-arm/termbits.h @@ -15,6 +15,18 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-arm26/termbits.h b/include/asm-arm26/termbits.h index bbc6e1d24d3..a3f4fe1742d 100644 --- a/include/asm-arm26/termbits.h +++ b/include/asm-arm26/termbits.h @@ -15,6 +15,18 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-avr32/termbits.h b/include/asm-avr32/termbits.h index 9dc6eacafa3..c215fafdae4 100644 --- a/include/asm-avr32/termbits.h +++ b/include/asm-avr32/termbits.h @@ -17,6 +17,17 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-cris/termbits.h b/include/asm-cris/termbits.h index be0836d2f28..8d8cec225fe 100644 --- a/include/asm-cris/termbits.h +++ b/include/asm-cris/termbits.h @@ -19,6 +19,17 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-frv/bitops.h b/include/asm-frv/bitops.h index 1f70d47148b..f8560edf59f 100644 --- a/include/asm-frv/bitops.h +++ b/include/asm-frv/bitops.h @@ -256,6 +256,50 @@ int __ffs(unsigned long x) return 31 - bit; } +/* + * special slimline version of fls() for calculating ilog2_u32() + * - note: no protection against n == 0 + */ +#define ARCH_HAS_ILOG2_U32 +static inline __attribute__((const)) +int __ilog2_u32(u32 n) +{ + int bit; + asm("scan %1,gr0,%0" : "=r"(bit) : "r"(n)); + return 31 - bit; +} + +/* + * special slimline version of fls64() for calculating ilog2_u64() + * - note: no protection against n == 0 + */ +#define ARCH_HAS_ILOG2_U64 +static inline __attribute__((const)) +int __ilog2_u64(u64 n) +{ + union { + u64 ll; + struct { u32 h, l; }; + } _; + int bit, x, y; + + _.ll = n; + + asm(" subcc %3,gr0,gr0,icc0 \n" + " ckeq icc0,cc4 \n" + " cscan.p %3,gr0,%0 ,cc4,0 \n" + " setlos #63,%1 \n" + " cscan.p %4,gr0,%0 ,cc4,1 \n" + " setlos #31,%2 \n" + " csub.p %1,%0,%0 ,cc4,0 \n" + " csub %2,%0,%0 ,cc4,1 \n" + : "=&r"(bit), "=r"(x), "=r"(y) + : "0r"(_.h), "r"(_.l) + : "icc0", "cc4" + ); + return bit; +} + #include <asm-generic/bitops/sched.h> #include <asm-generic/bitops/hweight.h> diff --git a/include/asm-frv/termbits.h b/include/asm-frv/termbits.h index 74f20d6e292..2d6d389cff4 100644 --- a/include/asm-frv/termbits.h +++ b/include/asm-frv/termbits.h @@ -17,6 +17,17 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index c92ae0f166f..a06eecd4829 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -4,6 +4,22 @@ #include <linux/compiler.h> #ifdef CONFIG_BUG + +#ifdef CONFIG_GENERIC_BUG +#ifndef __ASSEMBLY__ +struct bug_entry { + unsigned long bug_addr; +#ifdef CONFIG_DEBUG_BUGVERBOSE + const char *file; + unsigned short line; +#endif + unsigned short flags; +}; +#endif /* __ASSEMBLY__ */ + +#define BUGFLAG_WARNING (1<<0) +#endif /* CONFIG_GENERIC_BUG */ + #ifndef HAVE_ARCH_BUG #define BUG() do { \ printk("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __FUNCTION__); \ @@ -19,7 +35,7 @@ #define WARN_ON(condition) ({ \ typeof(condition) __ret_warn_on = (condition); \ if (unlikely(__ret_warn_on)) { \ - printk("BUG: warning at %s:%d/%s()\n", __FILE__, \ + printk("WARNING at %s:%d %s()\n", __FILE__, \ __LINE__, __FUNCTION__); \ dump_stack(); \ } \ diff --git a/include/asm-generic/page.h b/include/asm-generic/page.h index a96b5d986b6..b55052ce233 100644 --- a/include/asm-generic/page.h +++ b/include/asm-generic/page.h @@ -4,21 +4,51 @@ #ifdef __KERNEL__ #ifndef __ASSEMBLY__ -#include <linux/compiler.h> +#include <linux/log2.h> -/* Pure 2^n version of get_order */ -static __inline__ __attribute_const__ int get_order(unsigned long size) +/* + * non-const pure 2^n version of get_order + * - the arch may override these in asm/bitops.h if they can be implemented + * more efficiently than using the arch log2 routines + * - we use the non-const log2() instead if the arch has defined one suitable + */ +#ifndef ARCH_HAS_GET_ORDER +static inline __attribute__((const)) +int __get_order(unsigned long size, int page_shift) { +#if BITS_PER_LONG == 32 && defined(ARCH_HAS_ILOG2_U32) + int order = __ilog2_u32(size) - page_shift; + return order >= 0 ? order : 0; +#elif BITS_PER_LONG == 64 && defined(ARCH_HAS_ILOG2_U64) + int order = __ilog2_u64(size) - page_shift; + return order >= 0 ? order : 0; +#else int order; - size = (size - 1) >> (PAGE_SHIFT - 1); + size = (size - 1) >> (page_shift - 1); order = -1; do { size >>= 1; order++; } while (size); return order; +#endif } +#endif + +/** + * get_order - calculate log2(pages) to hold a block of the specified size + * @n - size + * + * calculate allocation order based on the current page size + * - this can be used to initialise global variables from constant data + */ +#define get_order(n) \ +( \ + __builtin_constant_p(n) ? \ + ((n < (1UL << PAGE_SHIFT)) ? 0 : ilog2(n) - PAGE_SHIFT) : \ + __get_order(n, PAGE_SHIFT) \ + ) #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ diff --git a/include/asm-generic/termios.h b/include/asm-generic/termios.h index 1e58ca39592..3769e6bd63b 100644 --- a/include/asm-generic/termios.h +++ b/include/asm-generic/termios.h @@ -11,7 +11,7 @@ /* * Translate a "termio" structure into a "termios". Ugh. */ -static inline int user_termio_to_kernel_termios(struct termios *termios, +static inline int user_termio_to_kernel_termios(struct ktermios *termios, struct termio __user *termio) { unsigned short tmp; @@ -48,7 +48,7 @@ static inline int user_termio_to_kernel_termios(struct termios *termios, * Translate a "termios" structure into a "termio". Ugh. */ static inline int kernel_termios_to_user_termio(struct termio __user *termio, - struct termios *termios) + struct ktermios *termios) { if (put_user(termios->c_iflag, &termio->c_iflag) < 0 || put_user(termios->c_oflag, &termio->c_oflag) < 0 || diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 4d4c62d1105..6e9fcebbf89 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -218,6 +218,14 @@ .stab.indexstr 0 : { *(.stab.indexstr) } \ .comment 0 : { *(.comment) } +#define BUG_TABLE \ + . = ALIGN(8); \ + __bug_table : AT(ADDR(__bug_table) - LOAD_OFFSET) { \ + __start___bug_table = .; \ + *(__bug_table) \ + __stop___bug_table = .; \ + } + #define NOTES \ .notes : { *(.note.*) } :note diff --git a/include/asm-h8300/termbits.h b/include/asm-h8300/termbits.h index fa69ae00eda..6a1f4d3807b 100644 --- a/include/asm-h8300/termbits.h +++ b/include/asm-h8300/termbits.h @@ -17,6 +17,17 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-i386/bug.h b/include/asm-i386/bug.h index 8062cdbf258..b0fd78ca261 100644 --- a/include/asm-i386/bug.h +++ b/include/asm-i386/bug.h @@ -4,20 +4,32 @@ /* * Tell the user there is some problem. - * The offending file and line are encoded after the "officially - * undefined" opcode for parsing in the trap handler. + * The offending file and line are encoded encoded in the __bug_table section. */ #ifdef CONFIG_BUG #define HAVE_ARCH_BUG + #ifdef CONFIG_DEBUG_BUGVERBOSE -#define BUG() \ - __asm__ __volatile__( "ud2\n" \ - "\t.word %c0\n" \ - "\t.long %c1\n" \ - : : "i" (__LINE__), "i" (__FILE__)) +#define BUG() \ + do { \ + asm volatile("1:\tud2\n" \ + ".pushsection __bug_table,\"a\"\n" \ + "2:\t.long 1b, %c0\n" \ + "\t.word %c1, 0\n" \ + "\t.org 2b+%c2\n" \ + ".popsection" \ + : : "i" (__FILE__), "i" (__LINE__), \ + "i" (sizeof(struct bug_entry))); \ + for(;;) ; \ + } while(0) + #else -#define BUG() __asm__ __volatile__("ud2\n") +#define BUG() \ + do { \ + asm volatile("ud2"); \ + for(;;) ; \ + } while(0) #endif #endif diff --git a/include/asm-i386/ide.h b/include/asm-i386/ide.h index 73465d2892b..0fc240c80f4 100644 --- a/include/asm-i386/ide.h +++ b/include/asm-i386/ide.h @@ -40,13 +40,14 @@ static __inline__ int ide_default_irq(unsigned long base) static __inline__ unsigned long ide_default_io_base(int index) { + struct pci_dev *pdev; /* * If PCI is present then it is not safe to poke around * the other legacy IDE ports. Only 0x1f0 and 0x170 are * defined compatibility mode ports for PCI. A user can * override this using ide= but we must default safe. */ - if (pci_find_device(PCI_ANY_ID, PCI_ANY_ID, NULL) == NULL) { + if ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL)) == NULL) { switch(index) { case 2: return 0x1e8; case 3: return 0x168; @@ -54,6 +55,7 @@ static __inline__ unsigned long ide_default_io_base(int index) case 5: return 0x160; } } + pci_dev_put(pdev); switch (index) { case 0: return 0x1f0; case 1: return 0x170; diff --git a/include/asm-i386/termbits.h b/include/asm-i386/termbits.h index 72c10e3190f..12baf1d6343 100644 --- a/include/asm-i386/termbits.h +++ b/include/asm-i386/termbits.h @@ -17,6 +17,17 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-ia64/termbits.h b/include/asm-ia64/termbits.h index b9e843f7dc4..4531a511bde 100644 --- a/include/asm-ia64/termbits.h +++ b/include/asm-ia64/termbits.h @@ -26,6 +26,17 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-m32r/ide.h b/include/asm-m32r/ide.h index 219a0f74eff..c82ebe8f250 100644 --- a/include/asm-m32r/ide.h +++ b/include/asm-m32r/ide.h @@ -32,7 +32,8 @@ static __inline__ int ide_default_irq(unsigned long base) { switch (base) { -#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_MAPPI2) +#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_MAPPI2) \ + || defined(CONFIG_PLAT_OPSPUT) case 0x1f0: return PLD_IRQ_CFIREQ; default: return 0; diff --git a/include/asm-m32r/m32102.h b/include/asm-m32r/m32102.h index a1f0d1fe9eb..52807f8db16 100644 --- a/include/asm-m32r/m32102.h +++ b/include/asm-m32r/m32102.h @@ -104,7 +104,8 @@ #define M32R_MFT5RLD_PORTL (0x0C+M32R_MFT5_OFFSET) /* MFT4 reload */ #define M32R_MFT5CMPRLD_PORTL (0x10+M32R_MFT5_OFFSET) /* MFT4 compare reload */ -#if defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32104) +#if (defined(CONFIG_CHIP_M32700) && !defined(CONFIG_PLAT_MAPPI2)) \ + || defined(CONFIG_CHIP_M32104) #define M32R_MFTCR_MFT0MSK (1UL<<31) /* b0 */ #define M32R_MFTCR_MFT1MSK (1UL<<30) /* b1 */ #define M32R_MFTCR_MFT2MSK (1UL<<29) /* b2 */ @@ -117,7 +118,7 @@ #define M32R_MFTCR_MFT3EN (1UL<<20) /* b11 */ #define M32R_MFTCR_MFT4EN (1UL<<19) /* b12 */ #define M32R_MFTCR_MFT5EN (1UL<<18) /* b13 */ -#else /* not CONFIG_CHIP_M32700 && not CONFIG_CHIP_M32104 */ +#else #define M32R_MFTCR_MFT0MSK (1UL<<15) /* b16 */ #define M32R_MFTCR_MFT1MSK (1UL<<14) /* b17 */ #define M32R_MFTCR_MFT2MSK (1UL<<13) /* b18 */ @@ -130,7 +131,7 @@ #define M32R_MFTCR_MFT3EN (1UL<<4) /* b27 */ #define M32R_MFTCR_MFT4EN (1UL<<3) /* b28 */ #define M32R_MFTCR_MFT5EN (1UL<<2) /* b29 */ -#endif /* not CONFIG_CHIP_M32700 && not CONFIG_CHIP_M32104 */ +#endif #define M32R_MFTMOD_CC_MASK (1UL<<15) /* b16 */ #define M32R_MFTMOD_TCCR (1UL<<13) /* b18 */ diff --git a/include/asm-m32r/ptrace.h b/include/asm-m32r/ptrace.h index 2d2a6c97331..632b4ce4269 100644 --- a/include/asm-m32r/ptrace.h +++ b/include/asm-m32r/ptrace.h @@ -33,21 +33,10 @@ #define PT_R15 PT_SP /* processor status and miscellaneous context registers. */ -#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2) #define PT_ACC0H 15 #define PT_ACC0L 16 -#define PT_ACC1H 17 -#define PT_ACC1L 18 -#define PT_ACCH PT_ACC0H -#define PT_ACCL PT_ACC0L -#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R) -#define PT_ACCH 15 -#define PT_ACCL 16 -#define PT_DUMMY_ACC1H 17 -#define PT_DUMMY_ACC1L 18 -#else -#error unknown isa conifiguration -#endif +#define PT_ACC1H 17 /* ISA_DSP_LEVEL2 only */ +#define PT_ACC1L 18 /* ISA_DSP_LEVEL2 only */ #define PT_PSW 19 #define PT_BPC 20 #define PT_BBPSW 21 @@ -103,19 +92,10 @@ struct pt_regs { long syscall_nr; /* Saved main processor status and miscellaneous context registers. */ -#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2) unsigned long acc0h; unsigned long acc0l; - unsigned long acc1h; - unsigned long acc1l; -#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R) - unsigned long acch; - unsigned long accl; - unsigned long dummy_acc1h; - unsigned long dummy_acc1l; -#else -#error unknown isa configuration -#endif + unsigned long acc1h; /* ISA_DSP_LEVEL2 only */ + unsigned long acc1l; /* ISA_DSP_LEVEL2 only */ unsigned long psw; unsigned long bpc; /* saved PC for TRAP syscalls */ unsigned long bbpsw; diff --git a/include/asm-m32r/sigcontext.h b/include/asm-m32r/sigcontext.h index 73025c0c41a..62537dc4dec 100644 --- a/include/asm-m32r/sigcontext.h +++ b/include/asm-m32r/sigcontext.h @@ -23,19 +23,10 @@ struct sigcontext { unsigned long sc_r12; /* Saved main processor status and miscellaneous context registers. */ -#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2) unsigned long sc_acc0h; unsigned long sc_acc0l; - unsigned long sc_acc1h; - unsigned long sc_acc1l; -#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R) - unsigned long sc_acch; - unsigned long sc_accl; - unsigned long sc_dummy_acc1h; - unsigned long sc_dummy_acc1l; -#else -#error unknown isa configuration -#endif + unsigned long sc_acc1h; /* ISA_DSP_LEVEL2 only */ + unsigned long sc_acc1l; /* ISA_DSP_LEVEL2 only */ unsigned long sc_psw; unsigned long sc_bpc; /* saved PC for TRAP syscalls */ unsigned long sc_bbpsw; diff --git a/include/asm-m32r/termbits.h b/include/asm-m32r/termbits.h index 5ace3702df7..faf2bd0504c 100644 --- a/include/asm-m32r/termbits.h +++ b/include/asm-m32r/termbits.h @@ -19,6 +19,17 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-m68k/termbits.h b/include/asm-m68k/termbits.h index e9eec3eb071..a194092240f 100644 --- a/include/asm-m68k/termbits.h +++ b/include/asm-m68k/termbits.h @@ -17,6 +17,17 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-mips/termbits.h b/include/asm-mips/termbits.h index b62ec7c521c..0bbe07b42a0 100644 --- a/include/asm-mips/termbits.h +++ b/include/asm-mips/termbits.h @@ -30,6 +30,17 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 /* Interrupt character [ISIG]. */ #define VQUIT 1 /* Quit character [ISIG]. */ diff --git a/include/asm-parisc/termbits.h b/include/asm-parisc/termbits.h index 372b634892c..a46e299a939 100644 --- a/include/asm-parisc/termbits.h +++ b/include/asm-parisc/termbits.h @@ -17,6 +17,17 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-powerpc/bitops.h b/include/asm-powerpc/bitops.h index c341063d080..0288144ea02 100644 --- a/include/asm-powerpc/bitops.h +++ b/include/asm-powerpc/bitops.h @@ -190,7 +190,8 @@ static __inline__ void set_bits(unsigned long mask, unsigned long *addr) * Return the zero-based bit position (LE, not IBM bit numbering) of * the most significant 1-bit in a double word. */ -static __inline__ int __ilog2(unsigned long x) +static __inline__ __attribute__((const)) +int __ilog2(unsigned long x) { int lz; @@ -198,6 +199,24 @@ static __inline__ int __ilog2(unsigned long x) return BITS_PER_LONG - 1 - lz; } +static inline __attribute__((const)) +int __ilog2_u32(u32 n) +{ + int bit; + asm ("cntlzw %0,%1" : "=r" (bit) : "r" (n)); + return 31 - bit; +} + +#ifdef __powerpc64__ +static inline __attribute__((const)) +int __ilog2_u64(u32 n) +{ + int bit; + asm ("cntlzd %0,%1" : "=r" (bit) : "r" (n)); + return 63 - bit; +} +#endif + /* * Determines the bit position of the least significant 0 bit in the * specified double word. The returned bit position will be diff --git a/include/asm-powerpc/page_32.h b/include/asm-powerpc/page_32.h index 2677bad70f4..07f6d3cf5e5 100644 --- a/include/asm-powerpc/page_32.h +++ b/include/asm-powerpc/page_32.h @@ -26,15 +26,7 @@ extern void clear_pages(void *page, int order); static inline void clear_page(void *page) { clear_pages(page, 0); } extern void copy_page(void *to, void *from); -/* Pure 2^n version of get_order */ -extern __inline__ int get_order(unsigned long size) -{ - int lz; - - size = (size-1) >> PAGE_SHIFT; - asm ("cntlzw %0,%1" : "=r" (lz) : "r" (size)); - return 32 - lz; -} +#include <asm-generic/page.h> #endif /* __ASSEMBLY__ */ diff --git a/include/asm-powerpc/termbits.h b/include/asm-powerpc/termbits.h index 6d533b07aaf..5e79198f7d1 100644 --- a/include/asm-powerpc/termbits.h +++ b/include/asm-powerpc/termbits.h @@ -30,6 +30,19 @@ struct termios { speed_t c_ospeed; /* output speed */ }; +/* For PowerPC the termios and ktermios are the same */ + +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_cc[NCCS]; /* control characters */ + cc_t c_line; /* line discipline (== c_cc[19]) */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-s390/termbits.h b/include/asm-s390/termbits.h index eb3f8bfabf6..585c78a6e40 100644 --- a/include/asm-s390/termbits.h +++ b/include/asm-s390/termbits.h @@ -25,6 +25,17 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-sh/termbits.h b/include/asm-sh/termbits.h index 4f9822a8e7b..f1b7b46f4e9 100644 --- a/include/asm-sh/termbits.h +++ b/include/asm-sh/termbits.h @@ -17,6 +17,17 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-sparc/termbits.h b/include/asm-sparc/termbits.h index 1794d71134b..5eb00a105d7 100644 --- a/include/asm-sparc/termbits.h +++ b/include/asm-sparc/termbits.h @@ -31,6 +31,18 @@ struct termios { #endif }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + cc_t _x_cc[2]; /* We need them to hold vmin/vtime */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-sparc64/termbits.h b/include/asm-sparc64/termbits.h index b07715273ed..705cd44b417 100644 --- a/include/asm-sparc64/termbits.h +++ b/include/asm-sparc64/termbits.h @@ -33,6 +33,18 @@ struct termios { #endif }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + cc_t _x_cc[2]; /* We need them to hold vmin/vtime */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-um/bug.h b/include/asm-um/bug.h index 1e22fa26ff0..3357c5e2468 100644 --- a/include/asm-um/bug.h +++ b/include/asm-um/bug.h @@ -1,4 +1,6 @@ #ifndef __UM_BUG_H #define __UM_BUG_H -#include <asm-generic/bug.h> + +#include <asm/arch/bug.h> + #endif diff --git a/include/asm-v850/termbits.h b/include/asm-v850/termbits.h index 212d4e27926..f3b43303208 100644 --- a/include/asm-v850/termbits.h +++ b/include/asm-v850/termbits.h @@ -17,6 +17,17 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-x86_64/bug.h b/include/asm-x86_64/bug.h index 80ac1fe966a..68260641491 100644 --- a/include/asm-x86_64/bug.h +++ b/include/asm-x86_64/bug.h @@ -1,30 +1,30 @@ #ifndef __ASM_X8664_BUG_H #define __ASM_X8664_BUG_H 1 -#include <linux/stringify.h> - -/* - * Tell the user there is some problem. The exception handler decodes - * this frame. - */ -struct bug_frame { - unsigned char ud2[2]; - unsigned char push; - signed int filename; - unsigned char ret; - unsigned short line; -} __attribute__((packed)); - #ifdef CONFIG_BUG #define HAVE_ARCH_BUG -/* We turn the bug frame into valid instructions to not confuse - the disassembler. Thanks to Jan Beulich & Suresh Siddha - for nice instruction selection. - The magic numbers generate mov $64bitimm,%eax ; ret $offset. */ -#define BUG() \ - asm volatile( \ - "ud2 ; pushq $%c1 ; ret $%c0" :: \ - "i"(__LINE__), "i" (__FILE__)) + +#ifdef CONFIG_DEBUG_BUGVERBOSE +#define BUG() \ + do { \ + asm volatile("1:\tud2\n" \ + ".pushsection __bug_table,\"a\"\n" \ + "2:\t.quad 1b, %c0\n" \ + "\t.word %c1, 0\n" \ + "\t.org 2b+%c2\n" \ + ".popsection" \ + : : "i" (__FILE__), "i" (__LINE__), \ + "i" (sizeof(struct bug_entry))); \ + for(;;) ; \ + } while(0) +#else +#define BUG() \ + do { \ + asm volatile("ud2"); \ + for(;;) ; \ + } while(0) +#endif + void out_of_line_bug(void); #else static inline void out_of_line_bug(void) { } diff --git a/include/asm-x86_64/ioctls.h b/include/asm-x86_64/ioctls.h index 62caf8b6e4e..3fc0b15a0d7 100644 --- a/include/asm-x86_64/ioctls.h +++ b/include/asm-x86_64/ioctls.h @@ -46,6 +46,10 @@ #define TIOCSBRK 0x5427 /* BSD compatibility */ #define TIOCCBRK 0x5428 /* BSD compatibility */ #define TIOCGSID 0x5429 /* Return the session ID of FD */ +#define TCGETS2 _IOR('T',0x2A, struct termios2) +#define TCSETS2 _IOW('T',0x2B, struct termios2) +#define TCSETSW2 _IOW('T',0x2C, struct termios2) +#define TCSETSF2 _IOW('T',0x2D, struct termios2) #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ diff --git a/include/asm-x86_64/termbits.h b/include/asm-x86_64/termbits.h index bd950946e52..6cfc3bb10c1 100644 --- a/include/asm-x86_64/termbits.h +++ b/include/asm-x86_64/termbits.h @@ -17,6 +17,28 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct termios2 { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 @@ -118,6 +140,7 @@ struct termios { #define HUPCL 0002000 #define CLOCAL 0004000 #define CBAUDEX 0010000 +#define BOTHER 0010000 /* non standard rate */ #define B57600 0010001 #define B115200 0010002 #define B230400 0010003 @@ -133,10 +156,12 @@ struct termios { #define B3000000 0010015 #define B3500000 0010016 #define B4000000 0010017 -#define CIBAUD 002003600000 /* input baud rate (not used) */ +#define CIBAUD 002003600000 /* input baud rate */ #define CMSPAR 010000000000 /* mark or space (stick) parity */ #define CRTSCTS 020000000000 /* flow control */ +#define IBSHIFT 8 /* Shift from CBAUD to CIBAUD */ + /* c_lflag bits */ #define ISIG 0000001 #define ICANON 0000002 diff --git a/include/asm-x86_64/termios.h b/include/asm-x86_64/termios.h index 041a91f7ddf..443b225537f 100644 --- a/include/asm-x86_64/termios.h +++ b/include/asm-x86_64/termios.h @@ -98,8 +98,10 @@ struct termio { copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \ }) -#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios)) -#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios)) +#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2)) +#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2)) +#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios)) +#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios)) #endif /* __KERNEL__ */ diff --git a/include/linux/bitrev.h b/include/linux/bitrev.h new file mode 100644 index 00000000000..05e540d6963 --- /dev/null +++ b/include/linux/bitrev.h @@ -0,0 +1,15 @@ +#ifndef _LINUX_BITREV_H +#define _LINUX_BITREV_H + +#include <linux/types.h> + +extern u8 const byte_rev_table[256]; + +static inline u8 bitrev8(u8 byte) +{ + return byte_rev_table[byte]; +} + +extern u32 bitrev32(u32 in); + +#endif /* _LINUX_BITREV_H */ diff --git a/include/linux/bug.h b/include/linux/bug.h new file mode 100644 index 00000000000..42aa0a54b6f --- /dev/null +++ b/include/linux/bug.h @@ -0,0 +1,47 @@ +#ifndef _LINUX_BUG_H +#define _LINUX_BUG_H + +#include <linux/module.h> +#include <asm/bug.h> + +enum bug_trap_type { + BUG_TRAP_TYPE_NONE = 0, + BUG_TRAP_TYPE_WARN = 1, + BUG_TRAP_TYPE_BUG = 2, +}; + +#ifdef CONFIG_GENERIC_BUG +#include <asm-generic/bug.h> + +static inline int is_warning_bug(const struct bug_entry *bug) +{ + return bug->flags & BUGFLAG_WARNING; +} + +const struct bug_entry *find_bug(unsigned long bugaddr); + +enum bug_trap_type report_bug(unsigned long bug_addr); + +int module_bug_finalize(const Elf_Ehdr *, const Elf_Shdr *, + struct module *); +void module_bug_cleanup(struct module *); + +/* These are defined by the architecture */ +int is_valid_bugaddr(unsigned long addr); + +#else /* !CONFIG_GENERIC_BUG */ + +static inline enum bug_trap_type report_bug(unsigned long bug_addr) +{ + return BUG_TRAP_TYPE_BUG; +} +static inline int module_bug_finalize(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, + struct module *mod) +{ + return 0; +} +static inline void module_bug_cleanup(struct module *mod) {} + +#endif /* CONFIG_GENERIC_BUG */ +#endif /* _LINUX_BUG_H */ diff --git a/include/linux/crc32.h b/include/linux/crc32.h index 56c0645789a..e20dd1f9b40 100644 --- a/include/linux/crc32.h +++ b/include/linux/crc32.h @@ -6,10 +6,10 @@ #define _LINUX_CRC32_H #include <linux/types.h> +#include <linux/bitrev.h> extern u32 crc32_le(u32 crc, unsigned char const *p, size_t len); extern u32 crc32_be(u32 crc, unsigned char const *p, size_t len); -extern u32 bitreverse(u32 in); #define crc32(seed, data, length) crc32_le(seed, (unsigned char const *)data, length) @@ -21,7 +21,7 @@ extern u32 bitreverse(u32 in); * is in bit nr 0], thus it must be reversed before use. Except for * nics that bit swap the result internally... */ -#define ether_crc(length, data) bitreverse(crc32_le(~0, data, length)) +#define ether_crc(length, data) bitrev32(crc32_le(~0, data, length)) #define ether_crc_le(length, data) crc32_le(~0, data, length) #endif /* _LINUX_CRC32_H */ diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 03ef41c1eaa..499f5373e21 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -39,7 +39,8 @@ typedef void (*dm_dtr_fn) (struct dm_target *ti); * The map function must return: * < 0: error * = 0: The target will handle the io by resubmitting it later - * > 0: simple remap complete + * = 1: simple remap complete + * = 2: The target wants to push back the io */ typedef int (*dm_map_fn) (struct dm_target *ti, struct bio *bio, union map_info *map_context); @@ -50,6 +51,7 @@ typedef int (*dm_map_fn) (struct dm_target *ti, struct bio *bio, * 0 : ended successfully * 1 : for some reason the io has still not completed (eg, * multipath target might want to requeue a failed io). + * 2 : The target wants to push back the io */ typedef int (*dm_endio_fn) (struct dm_target *ti, struct bio *bio, int error, @@ -173,7 +175,7 @@ void *dm_get_mdptr(struct mapped_device *md); /* * A device can still be used while suspended, but I/O is deferred. */ -int dm_suspend(struct mapped_device *md, int with_lockfs); +int dm_suspend(struct mapped_device *md, unsigned suspend_flags); int dm_resume(struct mapped_device *md); /* @@ -188,6 +190,7 @@ int dm_wait_event(struct mapped_device *md, int event_nr); const char *dm_device_name(struct mapped_device *md); struct gendisk *dm_disk(struct mapped_device *md); int dm_suspended(struct mapped_device *md); +int dm_noflush_suspending(struct dm_target *ti); /* * Geometry functions. diff --git a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h index 8853fc4d1c5..b9348610782 100644 --- a/include/linux/dm-ioctl.h +++ b/include/linux/dm-ioctl.h @@ -285,9 +285,9 @@ typedef char ioctl_struct[308]; #define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl) #define DM_VERSION_MAJOR 4 -#define DM_VERSION_MINOR 10 +#define DM_VERSION_MINOR 11 #define DM_VERSION_PATCHLEVEL 0 -#define DM_VERSION_EXTRA "-ioctl (2006-09-14)" +#define DM_VERSION_EXTRA "-ioctl (2006-10-12)" /* Status bits */ #define DM_READONLY_FLAG (1 << 0) /* In/Out */ @@ -323,4 +323,9 @@ typedef char ioctl_struct[308]; */ #define DM_SKIP_LOCKFS_FLAG (1 << 10) /* In */ +/* + * Set this to suspend without flushing queued ios. + */ +#define DM_NOFLUSH_FLAG (1 << 11) /* In */ + #endif /* _LINUX_DM_IOCTL_H */ diff --git a/include/linux/fault-inject.h b/include/linux/fault-inject.h new file mode 100644 index 00000000000..32368c4f032 --- /dev/null +++ b/include/linux/fault-inject.h @@ -0,0 +1,84 @@ +#ifndef _LINUX_FAULT_INJECT_H +#define _LINUX_FAULT_INJECT_H + +#ifdef CONFIG_FAULT_INJECTION + +#include <linux/types.h> +#include <linux/debugfs.h> +#include <asm/atomic.h> + +/* + * For explanation of the elements of this struct, see + * Documentation/fault-injection/fault-injection.txt + */ +struct fault_attr { + unsigned long probability; + unsigned long interval; + atomic_t times; + atomic_t space; + unsigned long verbose; + u32 task_filter; + unsigned long stacktrace_depth; + unsigned long require_start; + unsigned long require_end; + unsigned long reject_start; + unsigned long reject_end; + + unsigned long count; + +#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS + + struct { + struct dentry *dir; + + struct dentry *probability_file; + struct dentry *interval_file; + struct dentry *times_file; + struct dentry *space_file; + struct dentry *verbose_file; + struct dentry *task_filter_file; + struct dentry *stacktrace_depth_file; + struct dentry *require_start_file; + struct dentry *require_end_file; + struct dentry *reject_start_file; + struct dentry *reject_end_file; + } dentries; + +#endif +}; + +#define FAULT_ATTR_INITIALIZER { \ + .interval = 1, \ + .times = ATOMIC_INIT(1), \ + .require_end = ULONG_MAX, \ + .stacktrace_depth = 32, \ + .verbose = 2, \ + } + +#define DECLARE_FAULT_ATTR(name) struct fault_attr name = FAULT_ATTR_INITIALIZER +int setup_fault_attr(struct fault_attr *attr, char *str); +void should_fail_srandom(unsigned long entropy); +bool should_fail(struct fault_attr *attr, ssize_t size); + +#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS + +int init_fault_attr_dentries(struct fault_attr *attr, const char *name); +void cleanup_fault_attr_dentries(struct fault_attr *attr); + +#else /* CONFIG_FAULT_INJECTION_DEBUG_FS */ + +static inline int init_fault_attr_dentries(struct fault_attr *attr, + const char *name) +{ + return -ENODEV; +} + +static inline void cleanup_fault_attr_dentries(struct fault_attr *attr) +{ +} + +#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */ + +#endif /* CONFIG_FAULT_INJECTION */ + +#endif /* _LINUX_FAULT_INJECT_H */ diff --git a/include/linux/fb.h b/include/linux/fb.h index fa23e0671bb..6fe56aaa668 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -970,11 +970,11 @@ extern struct fb_videomode *fb_find_best_display(struct fb_monspecs *specs, /* drivers/video/fbcmap.c */ extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp); extern void fb_dealloc_cmap(struct fb_cmap *cmap); -extern int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to); -extern int fb_cmap_to_user(struct fb_cmap *from, struct fb_cmap_user *to); +extern int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to); +extern int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to); extern int fb_set_cmap(struct fb_cmap *cmap, struct fb_info *fb_info); extern int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *fb_info); -extern struct fb_cmap *fb_default_cmap(int len); +extern const struct fb_cmap *fb_default_cmap(int len); extern void fb_invert_cmaps(void); struct fb_videomode { diff --git a/include/linux/fs.h b/include/linux/fs.h index 70b99fbb560..adce6e1d70c 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -269,6 +269,7 @@ extern int dir_notify_enable; #include <linux/types.h> #include <linux/kdev_t.h> #include <linux/dcache.h> +#include <linux/namei.h> #include <linux/stat.h> #include <linux/cache.h> #include <linux/kobject.h> @@ -482,21 +483,6 @@ struct block_device { }; /* - * bdev->bd_mutex nesting subclasses for the lock validator: - * - * 0: normal - * 1: 'whole' - * 2: 'partition' - */ -enum bdev_bd_mutex_lock_class -{ - BD_MUTEX_NORMAL, - BD_MUTEX_WHOLE, - BD_MUTEX_PARTITION -}; - - -/* * Radix-tree tags, for tagging dirty and writeback pages within the pagecache * radix trees */ @@ -726,8 +712,9 @@ struct file { struct list_head fu_list; struct rcu_head fu_rcuhead; } f_u; - struct dentry *f_dentry; - struct vfsmount *f_vfsmnt; + struct path f_path; +#define f_dentry f_path.dentry +#define f_vfsmnt f_path.mnt const struct file_operations *f_op; atomic_t f_count; unsigned int f_flags; @@ -1239,7 +1226,7 @@ extern void touch_atime(struct vfsmount *mnt, struct dentry *dentry); static inline void file_accessed(struct file *file) { if (!(file->f_flags & O_NOATIME)) - touch_atime(file->f_vfsmnt, file->f_dentry); + touch_atime(file->f_path.mnt, file->f_path.dentry); } int sync_inode(struct inode *inode, struct writeback_control *wbc); @@ -1499,7 +1486,6 @@ extern void bd_set_size(struct block_device *, loff_t size); extern void bd_forget(struct inode *inode); extern void bdput(struct block_device *); extern struct block_device *open_by_devnum(dev_t, unsigned); -extern struct block_device *open_partition_by_devnum(dev_t, unsigned); extern const struct address_space_operations def_blk_aops; #else static inline void bd_forget(struct inode *inode) {} @@ -1517,7 +1503,6 @@ extern int blkdev_driver_ioctl(struct inode *inode, struct file *file, extern long compat_blkdev_ioctl(struct file *, unsigned, unsigned long); extern int blkdev_get(struct block_device *, mode_t, unsigned); extern int blkdev_put(struct block_device *); -extern int blkdev_put_partition(struct block_device *); extern int bd_claim(struct block_device *, void *); extern void bd_release(struct block_device *); #ifdef CONFIG_SYSFS @@ -1632,7 +1617,7 @@ static inline void put_write_access(struct inode * inode) static inline void allow_write_access(struct file *file) { if (file) - atomic_inc(&file->f_dentry->d_inode->i_writecount); + atomic_inc(&file->f_path.dentry->d_inode->i_writecount); } extern int do_pipe(int *); extern struct file *create_read_pipe(struct file *f); diff --git a/include/linux/fs_stack.h b/include/linux/fs_stack.h new file mode 100644 index 00000000000..bb516ceeefc --- /dev/null +++ b/include/linux/fs_stack.h @@ -0,0 +1,31 @@ +#ifndef _LINUX_FS_STACK_H +#define _LINUX_FS_STACK_H + +/* This file defines generic functions used primarily by stackable + * filesystems; none of these functions require i_mutex to be held. + */ + +#include <linux/fs.h> + +/* externs for fs/stack.c */ +extern void fsstack_copy_attr_all(struct inode *dest, const struct inode *src, + int (*get_nlinks)(struct inode *)); + +extern void fsstack_copy_inode_size(struct inode *dst, const struct inode *src); + +/* inlines */ +static inline void fsstack_copy_attr_atime(struct inode *dest, + const struct inode *src) +{ + dest->i_atime = src->i_atime; +} + +static inline void fsstack_copy_attr_times(struct inode *dest, + const struct inode *src) +{ + dest->i_atime = src->i_atime; + dest->i_mtime = src->i_mtime; + dest->i_ctime = src->i_ctime; +} + +#endif /* _LINUX_FS_STACK_H */ diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index d4f219ffaa5..dfc4e4f68da 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -164,7 +164,7 @@ static inline void fsnotify_open(struct dentry *dentry) */ static inline void fsnotify_close(struct file *file) { - struct dentry *dentry = file->f_dentry; + struct dentry *dentry = file->f_path.dentry; struct inode *inode = dentry->d_inode; const char *name = dentry->d_name.name; mode_t mode = file->f_mode; diff --git a/include/linux/generic_serial.h b/include/linux/generic_serial.h index e2538456195..5412da28fa4 100644 --- a/include/linux/generic_serial.h +++ b/include/linux/generic_serial.h @@ -91,7 +91,7 @@ void gs_hangup(struct tty_struct *tty); int gs_block_til_ready(void *port, struct file *filp); void gs_close(struct tty_struct *tty, struct file *filp); void gs_set_termios (struct tty_struct * tty, - struct termios * old_termios); + struct ktermios * old_termios); int gs_init_port(struct gs_port *port); int gs_setserial(struct gs_port *port, struct serial_struct __user *sp); int gs_getserial(struct gs_port *port, struct serial_struct __user *sp); diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 41f276fdd18..0a022b2f63f 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -83,6 +83,9 @@ struct hd_struct { struct kobject *holder_dir; unsigned ios[2], sectors[2]; /* READs and WRITEs */ int policy, partno; +#ifdef CONFIG_FAIL_MAKE_REQUEST + int make_it_fail; +#endif }; #define GENHD_FL_REMOVABLE 1 @@ -90,6 +93,7 @@ struct hd_struct { #define GENHD_FL_CD 8 #define GENHD_FL_UP 16 #define GENHD_FL_SUPPRESS_PARTITION_INFO 32 +#define GENHD_FL_FAIL 64 struct disk_stats { unsigned long sectors[2]; /* READs and WRITEs */ diff --git a/drivers/usb/input/hid-debug.h b/include/linux/hid-debug.h index f04d6d75c09..f04d6d75c09 100644 --- a/drivers/usb/input/hid-debug.h +++ b/include/linux/hid-debug.h diff --git a/drivers/usb/input/hid.h b/include/linux/hid.h index 76ad68d9edf..770120add15 100644 --- a/drivers/usb/input/hid.h +++ b/include/linux/hid.h @@ -6,6 +6,7 @@ * * Copyright (c) 1999 Andreas Gal * Copyright (c) 2000-2001 Vojtech Pavlik + * Copyright (c) 2006 Jiri Kosina */ /* @@ -33,6 +34,7 @@ #include <linux/list.h> #include <linux/timer.h> #include <linux/workqueue.h> +#include <linux/input.h> /* * USB HID (Human Interface Device) interface class code @@ -260,7 +262,7 @@ struct hid_item { #define HID_QUIRK_POWERBOOK_HAS_FN 0x00001000 #define HID_QUIRK_POWERBOOK_FN_ON 0x00002000 #define HID_QUIRK_INVERT_HWHEEL 0x00004000 -#define HID_QUIRK_POWERBOOK_ISO_KEYBOARD 0x00008000 +#define HID_QUIRK_POWERBOOK_ISO_KEYBOARD 0x00008000 #define HID_QUIRK_BAD_RELATIVE_KEYS 0x00010000 /* @@ -401,42 +403,14 @@ struct hid_device { /* device report descriptor */ unsigned collection_size; /* Number of allocated hid_collections */ unsigned maxcollection; /* Number of parsed collections */ unsigned maxapplication; /* Number of applications */ + unsigned short bus; /* BUS ID */ + unsigned short vendor; /* Vendor ID */ + unsigned short product; /* Product ID */ unsigned version; /* HID version */ unsigned country; /* HID country */ struct hid_report_enum report_enum[HID_REPORT_TYPES]; - struct usb_device *dev; /* USB device */ - struct usb_interface *intf; /* USB interface */ - int ifnum; /* USB interface number */ - - unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ - struct timer_list io_retry; /* Retry timer */ - unsigned long stop_retry; /* Time to give up, in jiffies */ - unsigned int retry_delay; /* Delay length in ms */ - struct work_struct reset_work; /* Task context for resets */ - - unsigned int bufsize; /* URB buffer size */ - - struct urb *urbin; /* Input URB */ - char *inbuf; /* Input buffer */ - dma_addr_t inbuf_dma; /* Input buffer dma */ - spinlock_t inlock; /* Input fifo spinlock */ - - struct urb *urbctrl; /* Control URB */ - struct usb_ctrlrequest *cr; /* Control request struct */ - dma_addr_t cr_dma; /* Control request struct dma */ - struct hid_control_fifo ctrl[HID_CONTROL_FIFO_SIZE]; /* Control fifo */ - unsigned char ctrlhead, ctrltail; /* Control fifo head & tail */ - char *ctrlbuf; /* Control buffer */ - dma_addr_t ctrlbuf_dma; /* Control buffer dma */ - spinlock_t ctrllock; /* Control fifo spinlock */ - - struct urb *urbout; /* Output URB */ - struct hid_report *out[HID_CONTROL_FIFO_SIZE]; /* Output pipe fifo */ - unsigned char outhead, outtail; /* Output pipe fifo head & tail */ - char *outbuf; /* Output buffer */ - dma_addr_t outbuf_dma; /* Output buffer dma */ - spinlock_t outlock; /* Output fifo spinlock */ + struct device *dev; /* device */ unsigned claimed; /* Claimed by hidinput, hiddev? */ unsigned quirks; /* Various quirks the device can pull on us */ @@ -452,7 +426,19 @@ struct hid_device { /* device report descriptor */ char phys[64]; /* Device physical location */ char uniq[64]; /* Device unique identifier (serial #) */ + void *driver_data; + + /* device-specific function pointers */ + int (*hidinput_input_event) (struct input_dev *, unsigned int, unsigned int, int); + int (*hidinput_open) (struct input_dev *); + void (*hidinput_close) (struct input_dev *); + + /* hiddev event handler */ + void (*hiddev_hid_event) (struct hid_device *, struct hid_field *field, + struct hid_usage *, __s32); + void (*hiddev_report_event) (struct hid_device *, struct hid_report *); #ifdef CONFIG_USB_HIDINPUT_POWERBOOK + unsigned int pb_fnmode; unsigned long pb_pressed_fn[NBITS(KEY_MAX)]; unsigned long pb_pressed_numlock[NBITS(KEY_MAX)]; #endif @@ -496,31 +482,23 @@ struct hid_descriptor { #define resolv_event(a,b) do { } while (0) #endif -#endif - -#ifdef CONFIG_USB_HIDINPUT /* Applications from HID Usage Tables 4/8/99 Version 1.1 */ /* We ignore a few input applications that are not widely used */ #define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001)) + +/* HID core API */ extern void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32); extern void hidinput_report_event(struct hid_device *hid, struct hid_report *report); extern int hidinput_connect(struct hid_device *); extern void hidinput_disconnect(struct hid_device *); -#else -#define IS_INPUT_APPLICATION(a) (0) -static inline void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) { } -static inline void hidinput_report_event(struct hid_device *hid, struct hid_report *report) { } -static inline int hidinput_connect(struct hid_device *hid) { return -ENODEV; } -static inline void hidinput_disconnect(struct hid_device *hid) { } -#endif -int hid_open(struct hid_device *); -void hid_close(struct hid_device *); int hid_set_field(struct hid_field *, unsigned, __s32); -void hid_submit_report(struct hid_device *, struct hid_report *, unsigned char dir); -void hid_init_reports(struct hid_device *hid); -int hid_wait_io(struct hid_device* hid); - +int hid_input_report(struct hid_device *, int type, u8 *, int, int); +int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field); +void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt); +void hid_output_report(struct hid_report *report, __u8 *data); +void hid_free_device(struct hid_device *device); +struct hid_device *hid_parse_report(__u8 *start, unsigned size); #ifdef CONFIG_HID_FF int hid_ff_init(struct hid_device *hid); @@ -537,4 +515,14 @@ static inline int hid_pidff_init(struct hid_device *hid) { return -ENODEV; } #else static inline int hid_ff_init(struct hid_device *hid) { return -1; } #endif +#ifdef DEBUG +#define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , \ + __FILE__ , ## arg) +#else +#define dbg(format, arg...) do {} while (0) +#endif + +#define err(format, arg...) printk(KERN_ERR "%s: " format "\n" , \ + __FILE__ , ## arg) +#endif diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 733790d4f7d..7272ff9ee77 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h @@ -7,6 +7,7 @@ #include <linux/utsname.h> #include <linux/lockdep.h> #include <linux/ipc.h> +#include <linux/pid_namespace.h> #define INIT_FDTABLE \ { \ @@ -57,25 +58,28 @@ .cpu_vm_mask = CPU_MASK_ALL, \ } -#define INIT_SIGNALS(sig) { \ - .count = ATOMIC_INIT(1), \ +#define INIT_SIGNALS(sig) { \ + .count = ATOMIC_INIT(1), \ .wait_chldexit = __WAIT_QUEUE_HEAD_INITIALIZER(sig.wait_chldexit),\ - .shared_pending = { \ + .shared_pending = { \ .list = LIST_HEAD_INIT(sig.shared_pending.list), \ - .signal = {{0}}}, \ + .signal = {{0}}}, \ .posix_timers = LIST_HEAD_INIT(sig.posix_timers), \ .cpu_timers = INIT_CPU_TIMERS(sig.cpu_timers), \ .rlim = INIT_RLIMITS, \ .pgrp = 1, \ - .session = 1, \ + .tty_old_pgrp = 0, \ + { .__session = 1}, \ } extern struct nsproxy init_nsproxy; #define INIT_NSPROXY(nsproxy) { \ + .pid_ns = &init_pid_ns, \ .count = ATOMIC_INIT(1), \ .nslock = __SPIN_LOCK_UNLOCKED(nsproxy.nslock), \ + .id = 0, \ .uts_ns = &init_uts_ns, \ - .namespace = NULL, \ + .mnt_ns = NULL, \ INIT_IPC_NS(ipc_ns) \ } diff --git a/include/linux/isdn.h b/include/linux/isdn.h index 62991148d5a..3c7875b7ab5 100644 --- a/include/linux/isdn.h +++ b/include/linux/isdn.h @@ -511,8 +511,8 @@ typedef struct modem_info { #endif struct tty_struct *tty; /* Pointer to corresponding tty */ atemu emu; /* AT-emulator data */ - struct termios normal_termios; /* For saving termios structs */ - struct termios callout_termios; + struct ktermios normal_termios; /* For saving termios structs */ + struct ktermios callout_termios; wait_queue_head_t open_wait, close_wait; struct semaphore write_sem; spinlock_t readlock; @@ -525,8 +525,8 @@ typedef struct _isdn_modem { int refcount; /* Number of opens */ struct tty_driver *tty_modem; /* tty-device */ struct tty_struct *modem_table[ISDN_MAX_CHANNELS]; /* ?? copied from Orig */ - struct termios *modem_termios[ISDN_MAX_CHANNELS]; - struct termios *modem_termios_locked[ISDN_MAX_CHANNELS]; + struct ktermios *modem_termios[ISDN_MAX_CHANNELS]; + struct ktermios *modem_termios_locked[ISDN_MAX_CHANNELS]; modem_info info[ISDN_MAX_CHANNELS]; /* Private data */ } isdn_modem_t; diff --git a/include/linux/istallion.h b/include/linux/istallion.h index b55e2a03560..106a5e85e5c 100644 --- a/include/linux/istallion.h +++ b/include/linux/istallion.h @@ -49,13 +49,13 @@ * communication with the slave board will always be on a per port * basis. */ -typedef struct { +struct stliport { unsigned long magic; - int portnr; - int panelnr; - int brdnr; + unsigned int portnr; + unsigned int panelnr; + unsigned int brdnr; unsigned long state; - int devnr; + unsigned int devnr; int flags; int baud_base; int custom_divisor; @@ -72,7 +72,7 @@ typedef struct { wait_queue_head_t close_wait; wait_queue_head_t raw_wait; struct work_struct tqhangup; - asysigs_t asig; + struct asysigs asig; unsigned long addr; unsigned long rxoffset; unsigned long txoffset; @@ -83,31 +83,31 @@ typedef struct { unsigned char reqbit; unsigned char portidx; unsigned char portbit; -} stliport_t; +}; /* * Use a structure of function pointers to do board level operations. * These include, enable/disable, paging shared memory, interrupting, etc. */ -typedef struct stlibrd { +struct stlibrd { unsigned long magic; - int brdnr; - int brdtype; - int state; - int nrpanels; - int nrports; - int nrdevs; + unsigned int brdnr; + unsigned int brdtype; + unsigned int state; + unsigned int nrpanels; + unsigned int nrports; + unsigned int nrdevs; unsigned int iobase; int iosize; unsigned long memaddr; void __iomem *membase; - int memsize; + unsigned long memsize; int pagesize; int hostoffset; int slaveoffset; int bitsize; int enabval; - int panels[STL_MAXPANELS]; + unsigned int panels[STL_MAXPANELS]; int panelids[STL_MAXPANELS]; void (*init)(struct stlibrd *brdp); void (*enable)(struct stlibrd *brdp); @@ -116,8 +116,8 @@ typedef struct stlibrd { void __iomem *(*getmemptr)(struct stlibrd *brdp, unsigned long offset, int line); void (*intr)(struct stlibrd *brdp); void (*reset)(struct stlibrd *brdp); - stliport_t *ports[STL_MAXPORTS]; -} stlibrd_t; + struct stliport *ports[STL_MAXPORTS]; +}; /* diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 6738283ac38..e8bfac34d2b 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -13,6 +13,7 @@ #include <linux/types.h> #include <linux/compiler.h> #include <linux/bitops.h> +#include <linux/log2.h> #include <asm/byteorder.h> #include <asm/bug.h> @@ -157,20 +158,6 @@ static inline int printk(const char *s, ...) { return 0; } unsigned long int_sqrt(unsigned long); -static inline int __attribute_pure__ long_log2(unsigned long x) -{ - int r = 0; - for (x >>= 1; x > 0; x >>= 1) - r++; - return r; -} - -static inline unsigned long -__attribute_const__ roundup_pow_of_two(unsigned long x) -{ - return 1UL << fls_long(x - 1); -} - extern int printk_ratelimit(void); extern int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst); extern bool printk_timed_ratelimit(unsigned long *caller_jiffies, diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h index 8c39654549d..0c962b82a9d 100644 --- a/include/linux/lockd/lockd.h +++ b/include/linux/lockd/lockd.h @@ -206,7 +206,7 @@ void nlmsvc_invalidate_all(void); static __inline__ struct inode * nlmsvc_file_inode(struct nlm_file *file) { - return file->f_file->f_dentry->d_inode; + return file->f_file->f_path.dentry->d_inode; } /* diff --git a/include/linux/log2.h b/include/linux/log2.h new file mode 100644 index 00000000000..d02e1a547a7 --- /dev/null +++ b/include/linux/log2.h @@ -0,0 +1,157 @@ +/* Integer base 2 logarithm calculation + * + * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@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. + */ + +#ifndef _LINUX_LOG2_H +#define _LINUX_LOG2_H + +#include <linux/types.h> +#include <linux/bitops.h> + +/* + * deal with unrepresentable constant logarithms + */ +extern __attribute__((const, noreturn)) +int ____ilog2_NaN(void); + +/* + * non-constant log of base 2 calculators + * - the arch may override these in asm/bitops.h if they can be implemented + * more efficiently than using fls() and fls64() + * - the arch is not required to handle n==0 if implementing the fallback + */ +#ifndef CONFIG_ARCH_HAS_ILOG2_U32 +static inline __attribute__((const)) +int __ilog2_u32(u32 n) +{ + return fls(n) - 1; +} +#endif + +#ifndef CONFIG_ARCH_HAS_ILOG2_U64 +static inline __attribute__((const)) +int __ilog2_u64(u64 n) +{ + return fls64(n) - 1; +} +#endif + +/* + * round up to nearest power of two + */ +static inline __attribute__((const)) +unsigned long __roundup_pow_of_two(unsigned long n) +{ + return 1UL << fls_long(n - 1); +} + +/** + * ilog2 - log of base 2 of 32-bit or a 64-bit unsigned value + * @n - parameter + * + * constant-capable log of base 2 calculation + * - this can be used to initialise global variables from constant data, hence + * the massive ternary operator construction + * + * selects the appropriately-sized optimised version depending on sizeof(n) + */ +#define ilog2(n) \ +( \ + __builtin_constant_p(n) ? ( \ + (n) < 1 ? ____ilog2_NaN() : \ + (n) & (1ULL << 63) ? 63 : \ + (n) & (1ULL << 62) ? 62 : \ + (n) & (1ULL << 61) ? 61 : \ + (n) & (1ULL << 60) ? 60 : \ + (n) & (1ULL << 59) ? 59 : \ + (n) & (1ULL << 58) ? 58 : \ + (n) & (1ULL << 57) ? 57 : \ + (n) & (1ULL << 56) ? 56 : \ + (n) & (1ULL << 55) ? 55 : \ + (n) & (1ULL << 54) ? 54 : \ + (n) & (1ULL << 53) ? 53 : \ + (n) & (1ULL << 52) ? 52 : \ + (n) & (1ULL << 51) ? 51 : \ + (n) & (1ULL << 50) ? 50 : \ + (n) & (1ULL << 49) ? 49 : \ + (n) & (1ULL << 48) ? 48 : \ + (n) & (1ULL << 47) ? 47 : \ + (n) & (1ULL << 46) ? 46 : \ + (n) & (1ULL << 45) ? 45 : \ + (n) & (1ULL << 44) ? 44 : \ + (n) & (1ULL << 43) ? 43 : \ + (n) & (1ULL << 42) ? 42 : \ + (n) & (1ULL << 41) ? 41 : \ + (n) & (1ULL << 40) ? 40 : \ + (n) & (1ULL << 39) ? 39 : \ + (n) & (1ULL << 38) ? 38 : \ + (n) & (1ULL << 37) ? 37 : \ + (n) & (1ULL << 36) ? 36 : \ + (n) & (1ULL << 35) ? 35 : \ + (n) & (1ULL << 34) ? 34 : \ + (n) & (1ULL << 33) ? 33 : \ + (n) & (1ULL << 32) ? 32 : \ + (n) & (1ULL << 31) ? 31 : \ + (n) & (1ULL << 30) ? 30 : \ + (n) & (1ULL << 29) ? 29 : \ + (n) & (1ULL << 28) ? 28 : \ + (n) & (1ULL << 27) ? 27 : \ + (n) & (1ULL << 26) ? 26 : \ + (n) & (1ULL << 25) ? 25 : \ + (n) & (1ULL << 24) ? 24 : \ + (n) & (1ULL << 23) ? 23 : \ + (n) & (1ULL << 22) ? 22 : \ + (n) & (1ULL << 21) ? 21 : \ + (n) & (1ULL << 20) ? 20 : \ + (n) & (1ULL << 19) ? 19 : \ + (n) & (1ULL << 18) ? 18 : \ + (n) & (1ULL << 17) ? 17 : \ + (n) & (1ULL << 16) ? 16 : \ + (n) & (1ULL << 15) ? 15 : \ + (n) & (1ULL << 14) ? 14 : \ + (n) & (1ULL << 13) ? 13 : \ + (n) & (1ULL << 12) ? 12 : \ + (n) & (1ULL << 11) ? 11 : \ + (n) & (1ULL << 10) ? 10 : \ + (n) & (1ULL << 9) ? 9 : \ + (n) & (1ULL << 8) ? 8 : \ + (n) & (1ULL << 7) ? 7 : \ + (n) & (1ULL << 6) ? 6 : \ + (n) & (1ULL << 5) ? 5 : \ + (n) & (1ULL << 4) ? 4 : \ + (n) & (1ULL << 3) ? 3 : \ + (n) & (1ULL << 2) ? 2 : \ + (n) & (1ULL << 1) ? 1 : \ + (n) & (1ULL << 0) ? 0 : \ + ____ilog2_NaN() \ + ) : \ + (sizeof(n) <= 4) ? \ + __ilog2_u32(n) : \ + __ilog2_u64(n) \ + ) + +/** + * roundup_pow_of_two - round the given value up to nearest power of two + * @n - parameter + * + * round the given balue up to the nearest power of two + * - the result is undefined when n == 0 + * - this can be used to initialise global variables from constant data + */ +#define roundup_pow_of_two(n) \ +( \ + __builtin_constant_p(n) ? ( \ + (n == 1) ? 0 : \ + (1UL << (ilog2((n) - 1) + 1)) \ + ) : \ + __roundup_pow_of_two(n) \ + ) + +#endif /* _LINUX_LOG2_H */ diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h new file mode 100644 index 00000000000..4af0b1fc282 --- /dev/null +++ b/include/linux/mnt_namespace.h @@ -0,0 +1,42 @@ +#ifndef _NAMESPACE_H_ +#define _NAMESPACE_H_ +#ifdef __KERNEL__ + +#include <linux/mount.h> +#include <linux/sched.h> +#include <linux/nsproxy.h> + +struct mnt_namespace { + atomic_t count; + struct vfsmount * root; + struct list_head list; + wait_queue_head_t poll; + int event; +}; + +extern int copy_mnt_ns(int, struct task_struct *); +extern void __put_mnt_ns(struct mnt_namespace *ns); +extern struct mnt_namespace *dup_mnt_ns(struct task_struct *, + struct fs_struct *); + +static inline void put_mnt_ns(struct mnt_namespace *ns) +{ + if (atomic_dec_and_lock(&ns->count, &vfsmount_lock)) + /* releases vfsmount_lock */ + __put_mnt_ns(ns); +} + +static inline void exit_mnt_ns(struct task_struct *p) +{ + struct mnt_namespace *ns = p->nsproxy->mnt_ns; + if (ns) + put_mnt_ns(ns); +} + +static inline void get_mnt_ns(struct mnt_namespace *ns) +{ + atomic_inc(&ns->count); +} + +#endif +#endif diff --git a/include/linux/module.h b/include/linux/module.h index d33df2408e0..10f771a4999 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -319,6 +319,13 @@ struct module unsigned int taints; /* same bits as kernel:tainted */ +#ifdef CONFIG_GENERIC_BUG + /* Support for BUG */ + struct list_head bug_list; + struct bug_entry *bug_table; + unsigned num_bugs; +#endif + #ifdef CONFIG_MODULE_UNLOAD /* Reference counts */ struct module_ref ref[NR_CPUS]; diff --git a/include/linux/mount.h b/include/linux/mount.h index 403d1a97c51..e357dc86a4d 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -20,7 +20,7 @@ struct super_block; struct vfsmount; struct dentry; -struct namespace; +struct mnt_namespace; #define MNT_NOSUID 0x01 #define MNT_NODEV 0x02 @@ -52,7 +52,7 @@ struct vfsmount { struct list_head mnt_slave_list;/* list of slave mounts */ struct list_head mnt_slave; /* slave list entry */ struct vfsmount *mnt_master; /* slave is on master->mnt_slave_list */ - struct namespace *mnt_namespace; /* containing namespace */ + struct mnt_namespace *mnt_ns; /* containing namespace */ int mnt_pinned; }; diff --git a/include/linux/mutex.h b/include/linux/mutex.h index b2b91c47756..a7544afd758 100644 --- a/include/linux/mutex.h +++ b/include/linux/mutex.h @@ -125,8 +125,10 @@ extern int fastcall mutex_lock_interruptible(struct mutex *lock); #ifdef CONFIG_DEBUG_LOCK_ALLOC extern void mutex_lock_nested(struct mutex *lock, unsigned int subclass); +extern int mutex_lock_interruptible_nested(struct mutex *lock, unsigned int subclass); #else # define mutex_lock_nested(lock, subclass) mutex_lock(lock) +# define mutex_lock_interruptible_nested(lock, subclass) mutex_lock_interruptible(lock) #endif /* diff --git a/include/linux/namei.h b/include/linux/namei.h index f5f19606eff..d39a5a67e97 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h @@ -29,6 +29,11 @@ struct nameidata { } intent; }; +struct path { + struct vfsmount *mnt; + struct dentry *dentry; +}; + /* * Type of the last component on LOOKUP_PARENT */ diff --git a/include/linux/namespace.h b/include/linux/namespace.h deleted file mode 100644 index d137009f0b2..00000000000 --- a/include/linux/namespace.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef _NAMESPACE_H_ -#define _NAMESPACE_H_ -#ifdef __KERNEL__ - -#include <linux/mount.h> -#include <linux/sched.h> -#include <linux/nsproxy.h> - -struct namespace { - atomic_t count; - struct vfsmount * root; - struct list_head list; - wait_queue_head_t poll; - int event; -}; - -extern int copy_namespace(int, struct task_struct *); -extern void __put_namespace(struct namespace *namespace); -extern struct namespace *dup_namespace(struct task_struct *, struct fs_struct *); - -static inline void put_namespace(struct namespace *namespace) -{ - if (atomic_dec_and_lock(&namespace->count, &vfsmount_lock)) - /* releases vfsmount_lock */ - __put_namespace(namespace); -} - -static inline void exit_namespace(struct task_struct *p) -{ - struct namespace *namespace = p->nsproxy->namespace; - if (namespace) { - put_namespace(namespace); - } -} - -static inline void get_namespace(struct namespace *namespace) -{ - atomic_inc(&namespace->count); -} - -#endif -#endif diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h index 971d1c6dfc4..fdfb0e44912 100644 --- a/include/linux/nsproxy.h +++ b/include/linux/nsproxy.h @@ -4,9 +4,10 @@ #include <linux/spinlock.h> #include <linux/sched.h> -struct namespace; +struct mnt_namespace; struct uts_namespace; struct ipc_namespace; +struct pid_namespace; /* * A structure to contain pointers to all per-process @@ -23,9 +24,11 @@ struct ipc_namespace; struct nsproxy { atomic_t count; spinlock_t nslock; + unsigned long id; struct uts_namespace *uts_ns; struct ipc_namespace *ipc_ns; - struct namespace *namespace; + struct mnt_namespace *mnt_ns; + struct pid_namespace *pid_ns; }; extern struct nsproxy init_nsproxy; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 4d972bbef31..51180dba9a9 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1785,14 +1785,17 @@ #define PCI_DEVICE_ID_MOXA_C104 0x1040 #define PCI_DEVICE_ID_MOXA_CP104U 0x1041 #define PCI_DEVICE_ID_MOXA_CP104JU 0x1042 +#define PCI_DEVICE_ID_MOXA_CP104EL 0x1043 #define PCI_DEVICE_ID_MOXA_CT114 0x1140 #define PCI_DEVICE_ID_MOXA_CP114 0x1141 #define PCI_DEVICE_ID_MOXA_CP118U 0x1180 +#define PCI_DEVICE_ID_MOXA_CP118EL 0x1181 #define PCI_DEVICE_ID_MOXA_CP132 0x1320 #define PCI_DEVICE_ID_MOXA_CP132U 0x1321 #define PCI_DEVICE_ID_MOXA_CP134U 0x1340 #define PCI_DEVICE_ID_MOXA_C168 0x1680 #define PCI_DEVICE_ID_MOXA_CP168U 0x1681 +#define PCI_DEVICE_ID_MOXA_CP168EL 0x1682 #define PCI_VENDOR_ID_CCD 0x1397 #define PCI_DEVICE_ID_CCD_2BD0 0x2bd0 diff --git a/include/linux/pid.h b/include/linux/pid.h index 2c0007d1721..4dec047b183 100644 --- a/include/linux/pid.h +++ b/include/linux/pid.h @@ -35,8 +35,9 @@ enum pid_type * * Holding a reference to struct pid solves both of these problems. * It is small so holding a reference does not consume a lot of - * resources, and since a new struct pid is allocated when the numeric - * pid value is reused we don't mistakenly refer to new processes. + * resources, and since a new struct pid is allocated when the numeric pid + * value is reused (when pids wrap around) we don't mistakenly refer to new + * processes. */ struct pid diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h new file mode 100644 index 00000000000..d2a9d419f01 --- /dev/null +++ b/include/linux/pid_namespace.h @@ -0,0 +1,45 @@ +#ifndef _LINUX_PID_NS_H +#define _LINUX_PID_NS_H + +#include <linux/sched.h> +#include <linux/mm.h> +#include <linux/threads.h> +#include <linux/pid.h> +#include <linux/nsproxy.h> +#include <linux/kref.h> + +struct pidmap { + atomic_t nr_free; + void *page; +}; + +#define PIDMAP_ENTRIES ((PID_MAX_LIMIT + 8*PAGE_SIZE - 1)/PAGE_SIZE/8) + +struct pid_namespace { + struct kref kref; + struct pidmap pidmap[PIDMAP_ENTRIES]; + int last_pid; + struct task_struct *child_reaper; +}; + +extern struct pid_namespace init_pid_ns; + +static inline void get_pid_ns(struct pid_namespace *ns) +{ + kref_get(&ns->kref); +} + +extern int copy_pid_ns(int flags, struct task_struct *tsk); +extern void free_pid_ns(struct kref *kref); + +static inline void put_pid_ns(struct pid_namespace *ns) +{ + kref_put(&ns->kref, free_pid_ns); +} + +static inline struct task_struct *child_reaper(struct task_struct *tsk) +{ + return tsk->nsproxy->pid_ns->child_reaper; +} + +#endif /* _LINUX_PID_NS_H */ diff --git a/include/linux/pktcdvd.h b/include/linux/pktcdvd.h index 8a94c717c26..5ea4f05683f 100644 --- a/include/linux/pktcdvd.h +++ b/include/linux/pktcdvd.h @@ -111,6 +111,13 @@ struct pkt_ctrl_command { #include <linux/blkdev.h> #include <linux/completion.h> #include <linux/cdrom.h> +#include <linux/kobject.h> +#include <linux/sysfs.h> + +/* default bio write queue congestion marks */ +#define PKT_WRITE_CONGESTION_ON 10000 +#define PKT_WRITE_CONGESTION_OFF 9000 + struct packet_settings { @@ -241,6 +248,14 @@ struct packet_stacked_data }; #define PSD_POOL_SIZE 64 +struct pktcdvd_kobj +{ + struct kobject kobj; + struct pktcdvd_device *pd; +}; +#define to_pktcdvdkobj(_k) \ + ((struct pktcdvd_kobj*)container_of(_k,struct pktcdvd_kobj,kobj)) + struct pktcdvd_device { struct block_device *bdev; /* dev attached */ @@ -271,6 +286,16 @@ struct pktcdvd_device struct packet_iosched iosched; struct gendisk *disk; + + int write_congestion_off; + int write_congestion_on; + + struct class_device *clsdev; /* sysfs pktcdvd[0-7] class dev */ + struct pktcdvd_kobj *kobj_stat; /* sysfs pktcdvd[0-7]/stat/ */ + struct pktcdvd_kobj *kobj_wqueue; /* sysfs pktcdvd[0-7]/write_queue/ */ + + struct dentry *dfs_d_root; /* debugfs: devname directory */ + struct dentry *dfs_f_info; /* debugfs: info file */ }; #endif /* __KERNEL__ */ diff --git a/include/linux/pspace.h b/include/linux/pspace.h deleted file mode 100644 index 91d48b8b2d9..00000000000 --- a/include/linux/pspace.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef _LINUX_PSPACE_H -#define _LINUX_PSPACE_H - -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/threads.h> -#include <linux/pid.h> - -struct pidmap { - atomic_t nr_free; - void *page; -}; - -#define PIDMAP_ENTRIES ((PID_MAX_LIMIT + 8*PAGE_SIZE - 1)/PAGE_SIZE/8) - -struct pspace { - struct pidmap pidmap[PIDMAP_ENTRIES]; - int last_pid; -}; - -extern struct pspace init_pspace; - -#endif /* _LINUX_PSPACE_H */ diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index d0e4dce33ad..c3fc6caaad3 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h @@ -1159,7 +1159,7 @@ znodes are the way! */ #define PATH_READA 0x1 /* do read ahead */ #define PATH_READA_BACK 0x2 /* read backwards */ -struct path { +struct treepath { int path_length; /* Length of the array above. */ int reada; struct path_element path_elements[EXTENDED_MAX_HEIGHT]; /* Array of the path elements. */ @@ -1169,7 +1169,7 @@ struct path { #define pos_in_item(path) ((path)->pos_in_item) #define INITIALIZE_PATH(var) \ -struct path var = {.path_length = ILLEGAL_PATH_ELEMENT_OFFSET, .reada = 0,} +struct treepath var = {.path_length = ILLEGAL_PATH_ELEMENT_OFFSET, .reada = 0,} /* Get path element by path and path position. */ #define PATH_OFFSET_PELEMENT(p_s_path,n_offset) ((p_s_path)->path_elements +(n_offset)) @@ -1327,7 +1327,7 @@ struct tree_balance { int need_balance_dirty; struct super_block *tb_sb; struct reiserfs_transaction_handle *transaction_handle; - struct path *tb_path; + struct treepath *tb_path; struct buffer_head *L[MAX_HEIGHT]; /* array of left neighbors of nodes in the path */ struct buffer_head *R[MAX_HEIGHT]; /* array of right neighbors of nodes in the path */ struct buffer_head *FL[MAX_HEIGHT]; /* array of fathers of the left neighbors */ @@ -1793,41 +1793,41 @@ static inline void copy_key(struct reiserfs_key *to, memcpy(to, from, KEY_SIZE); } -int comp_items(const struct item_head *stored_ih, const struct path *p_s_path); -const struct reiserfs_key *get_rkey(const struct path *p_s_chk_path, +int comp_items(const struct item_head *stored_ih, const struct treepath *p_s_path); +const struct reiserfs_key *get_rkey(const struct treepath *p_s_chk_path, const struct super_block *p_s_sb); int search_by_key(struct super_block *, const struct cpu_key *, - struct path *, int); + struct treepath *, int); #define search_item(s,key,path) search_by_key (s, key, path, DISK_LEAF_NODE_LEVEL) int search_for_position_by_key(struct super_block *p_s_sb, const struct cpu_key *p_s_cpu_key, - struct path *p_s_search_path); + struct treepath *p_s_search_path); extern void decrement_bcount(struct buffer_head *p_s_bh); -void decrement_counters_in_path(struct path *p_s_search_path); -void pathrelse(struct path *p_s_search_path); -int reiserfs_check_path(struct path *p); -void pathrelse_and_restore(struct super_block *s, struct path *p_s_search_path); +void decrement_counters_in_path(struct treepath *p_s_search_path); +void pathrelse(struct treepath *p_s_search_path); +int reiserfs_check_path(struct treepath *p); +void pathrelse_and_restore(struct super_block *s, struct treepath *p_s_search_path); int reiserfs_insert_item(struct reiserfs_transaction_handle *th, - struct path *path, + struct treepath *path, const struct cpu_key *key, struct item_head *ih, struct inode *inode, const char *body); int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, - struct path *path, + struct treepath *path, const struct cpu_key *key, struct inode *inode, const char *body, int paste_size); int reiserfs_cut_from_item(struct reiserfs_transaction_handle *th, - struct path *path, + struct treepath *path, struct cpu_key *key, struct inode *inode, struct page *page, loff_t new_file_size); int reiserfs_delete_item(struct reiserfs_transaction_handle *th, - struct path *path, + struct treepath *path, const struct cpu_key *key, struct inode *inode, struct buffer_head *p_s_un_bh); @@ -1858,7 +1858,7 @@ void padd_item(char *item, int total_length, int length); #define GET_BLOCK_NO_DANGLE 16 /* don't leave any transactions running */ int restart_transaction(struct reiserfs_transaction_handle *th, - struct inode *inode, struct path *path); + struct inode *inode, struct treepath *path); void reiserfs_read_locked_inode(struct inode *inode, struct reiserfs_iget_args *args); int reiserfs_find_actor(struct inode *inode, void *p); @@ -1905,7 +1905,7 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr); /* namei.c */ void set_de_name_and_namelen(struct reiserfs_dir_entry *de); int search_by_entry_key(struct super_block *sb, const struct cpu_key *key, - struct path *path, struct reiserfs_dir_entry *de); + struct treepath *path, struct reiserfs_dir_entry *de); struct dentry *reiserfs_get_parent(struct dentry *); /* procfs.c */ @@ -1956,9 +1956,9 @@ extern const struct file_operations reiserfs_dir_operations; /* tail_conversion.c */ int direct2indirect(struct reiserfs_transaction_handle *, struct inode *, - struct path *, struct buffer_head *, loff_t); + struct treepath *, struct buffer_head *, loff_t); int indirect2direct(struct reiserfs_transaction_handle *, struct inode *, - struct page *, struct path *, const struct cpu_key *, + struct page *, struct treepath *, const struct cpu_key *, loff_t, char *); void reiserfs_unmap_buffer(struct buffer_head *); @@ -2045,7 +2045,7 @@ struct __reiserfs_blocknr_hint { struct inode *inode; /* inode passed to allocator, if we allocate unf. nodes */ long block; /* file offset, in blocks */ struct in_core_key key; - struct path *path; /* search path, used by allocator to deternine search_start by + struct treepath *path; /* search path, used by allocator to deternine search_start by * various ways */ struct reiserfs_transaction_handle *th; /* transaction handle is needed to log super blocks and * bitmap blocks changes */ @@ -2101,7 +2101,7 @@ static inline int reiserfs_new_form_blocknrs(struct tree_balance *tb, static inline int reiserfs_new_unf_blocknrs(struct reiserfs_transaction_handle *th, struct inode *inode, b_blocknr_t * new_blocknrs, - struct path *path, long block) + struct treepath *path, long block) { reiserfs_blocknr_hint_t hint = { .th = th, @@ -2118,7 +2118,7 @@ static inline int reiserfs_new_unf_blocknrs(struct reiserfs_transaction_handle static inline int reiserfs_new_unf_blocknrs2(struct reiserfs_transaction_handle *th, struct inode *inode, b_blocknr_t * new_blocknrs, - struct path *path, long block) + struct treepath *path, long block) { reiserfs_blocknr_hint_t hint = { .th = th, diff --git a/include/linux/sched.h b/include/linux/sched.h index dede82c6344..ad9c46071ff 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -436,7 +436,12 @@ struct signal_struct { /* job control IDs */ pid_t pgrp; pid_t tty_old_pgrp; - pid_t session; + + union { + pid_t session __deprecated; + pid_t __session; + }; + /* boolean value for session group leader */ int leader; @@ -1040,6 +1045,9 @@ struct task_struct { #ifdef CONFIG_TASK_DELAY_ACCT struct task_delay_info *delays; #endif +#ifdef CONFIG_FAULT_INJECTION + int make_it_fail; +#endif }; static inline pid_t process_group(struct task_struct *tsk) @@ -1047,6 +1055,21 @@ static inline pid_t process_group(struct task_struct *tsk) return tsk->signal->pgrp; } +static inline pid_t signal_session(struct signal_struct *sig) +{ + return sig->__session; +} + +static inline pid_t process_session(struct task_struct *tsk) +{ + return signal_session(tsk->signal); +} + +static inline void set_signal_session(struct signal_struct *sig, pid_t session) +{ + sig->__session = session; +} + static inline struct pid *task_pid(struct task_struct *task) { return task->pids[PIDTYPE_PID].pid; @@ -1240,7 +1263,6 @@ extern struct mm_struct init_mm; #define find_task_by_pid(nr) find_task_by_pid_type(PIDTYPE_PID, nr) extern struct task_struct *find_task_by_pid_type(int type, int pid); -extern void set_special_pids(pid_t session, pid_t pgrp); extern void __set_special_pids(pid_t session, pid_t pgrp); /* per-UID process charging. */ @@ -1381,7 +1403,6 @@ extern NORET_TYPE void do_group_exit(int); extern void daemonize(const char *, ...); extern int allow_signal(int); extern int disallow_signal(int); -extern struct task_struct *child_reaper; extern int do_execve(char *, char __user * __user *, char __user * __user *, struct pt_regs *); extern long do_fork(unsigned long, unsigned long, struct pt_regs *, unsigned long, int __user *, int __user *); diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 82767213664..cf23813cbec 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -166,8 +166,8 @@ struct uart_ops { void (*break_ctl)(struct uart_port *, int ctl); int (*startup)(struct uart_port *); void (*shutdown)(struct uart_port *); - void (*set_termios)(struct uart_port *, struct termios *new, - struct termios *old); + void (*set_termios)(struct uart_port *, struct ktermios *new, + struct ktermios *old); void (*pm)(struct uart_port *, unsigned int state, unsigned int oldstate); int (*set_wake)(struct uart_port *, unsigned int state); @@ -361,8 +361,8 @@ void uart_write_wakeup(struct uart_port *port); */ void uart_update_timeout(struct uart_port *port, unsigned int cflag, unsigned int baud); -unsigned int uart_get_baud_rate(struct uart_port *port, struct termios *termios, - struct termios *old, unsigned int min, +unsigned int uart_get_baud_rate(struct uart_port *port, struct ktermios *termios, + struct ktermios *old, unsigned int min, unsigned int max); unsigned int uart_get_divisor(struct uart_port *port, unsigned int baud); diff --git a/include/linux/stallion.h b/include/linux/stallion.h index 13a37f137ea..4a0a329beaf 100644 --- a/include/linux/stallion.h +++ b/include/linux/stallion.h @@ -52,11 +52,11 @@ * protection - since "write" code only needs to change the head, and * interrupt code only needs to change the tail. */ -typedef struct { +struct stlrq { char *buf; char *head; char *tail; -} stlrq_t; +}; /* * Port, panel and board structures to hold status info about each. @@ -67,14 +67,14 @@ typedef struct { * is associated with, this makes it (fairly) easy to get back to the * board/panel info for a port. */ -typedef struct stlport { +struct stlport { unsigned long magic; - int portnr; - int panelnr; - int brdnr; + unsigned int portnr; + unsigned int panelnr; + unsigned int brdnr; int ioaddr; int uartaddr; - int pagenr; + unsigned int pagenr; long istate; int flags; int baud_base; @@ -97,31 +97,31 @@ typedef struct stlport { wait_queue_head_t close_wait; struct work_struct tqueue; comstats_t stats; - stlrq_t tx; -} stlport_t; + struct stlrq tx; +}; -typedef struct stlpanel { +struct stlpanel { unsigned long magic; - int panelnr; - int brdnr; - int pagenr; - int nrports; + unsigned int panelnr; + unsigned int brdnr; + unsigned int pagenr; + unsigned int nrports; int iobase; void *uartp; void (*isr)(struct stlpanel *panelp, unsigned int iobase); unsigned int hwid; unsigned int ackmask; - stlport_t *ports[STL_PORTSPERPANEL]; -} stlpanel_t; + struct stlport *ports[STL_PORTSPERPANEL]; +}; -typedef struct stlbrd { +struct stlbrd { unsigned long magic; - int brdnr; - int brdtype; - int state; - int nrpanels; - int nrports; - int nrbnks; + unsigned int brdnr; + unsigned int brdtype; + unsigned int state; + unsigned int nrpanels; + unsigned int nrports; + unsigned int nrbnks; int irq; int irqtype; int (*isr)(struct stlbrd *brdp); @@ -136,9 +136,9 @@ typedef struct stlbrd { unsigned long clk; unsigned int bnkpageaddr[STL_MAXBANKS]; unsigned int bnkstataddr[STL_MAXBANKS]; - stlpanel_t *bnk2panel[STL_MAXBANKS]; - stlpanel_t *panels[STL_MAXPANELS]; -} stlbrd_t; + struct stlpanel *bnk2panel[STL_MAXBANKS]; + struct stlpanel *panels[STL_MAXPANELS]; +}; /* diff --git a/include/linux/tty.h b/include/linux/tty.h index f717f089823..65cbcf22c31 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -175,7 +175,7 @@ struct tty_struct { int index; struct tty_ldisc ldisc; struct mutex termios_mutex; - struct termios *termios, *termios_locked; + struct ktermios *termios, *termios_locked; char name[64]; int pgrp; int session; @@ -258,7 +258,7 @@ struct tty_struct { extern void tty_write_flush(struct tty_struct *); -extern struct termios tty_std_termios; +extern struct ktermios tty_std_termios; extern int kmsg_redirect; @@ -293,8 +293,9 @@ extern int tty_hung_up_p(struct file * filp); extern void do_SAK(struct tty_struct *tty); extern void disassociate_ctty(int priv); extern void tty_flip_buffer_push(struct tty_struct *tty); -extern int tty_get_baud_rate(struct tty_struct *tty); -extern int tty_termios_baud_rate(struct termios *termios); +extern speed_t tty_get_baud_rate(struct tty_struct *tty); +extern speed_t tty_termios_baud_rate(struct ktermios *termios); +extern speed_t tty_termios_input_baud_rate(struct ktermios *termios); extern struct tty_ldisc *tty_ldisc_ref(struct tty_struct *); extern void tty_ldisc_deref(struct tty_ldisc *); @@ -309,6 +310,12 @@ extern void tty_ldisc_flush(struct tty_struct *tty); extern int tty_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); +extern dev_t tty_devnum(struct tty_struct *tty); +extern void proc_clear_tty(struct task_struct *p); +extern void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty); +extern void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty); +extern struct tty_struct *get_current_tty(void); + extern struct mutex tty_mutex; /* n_tty.c */ @@ -335,10 +342,5 @@ extern void console_print(const char *); extern int vt_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg); -static inline dev_t tty_devnum(struct tty_struct *tty) -{ - return MKDEV(tty->driver->major, tty->driver->minor_start) + tty->index; -} - #endif /* __KERNEL__ */ #endif diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h index 5c8473bb688..659487e3ebe 100644 --- a/include/linux/tty_driver.h +++ b/include/linux/tty_driver.h @@ -53,7 +53,7 @@ * device-specific ioctl's. If the ioctl number passed in cmd * is not recognized by the driver, it should return ENOIOCTLCMD. * - * void (*set_termios)(struct tty_struct *tty, struct termios * old); + * void (*set_termios)(struct tty_struct *tty, struct ktermios * old); * * This routine allows the tty driver to be notified when * device's termios settings have changed. Note that a @@ -132,7 +132,7 @@ struct tty_operations { int (*chars_in_buffer)(struct tty_struct *tty); int (*ioctl)(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg); - void (*set_termios)(struct tty_struct *tty, struct termios * old); + void (*set_termios)(struct tty_struct *tty, struct ktermios * old); void (*throttle)(struct tty_struct * tty); void (*unthrottle)(struct tty_struct * tty); void (*stop)(struct tty_struct *tty); @@ -165,7 +165,7 @@ struct tty_driver { int num; /* number of devices allocated */ short type; /* type of tty driver */ short subtype; /* subtype of tty driver */ - struct termios init_termios; /* Initial termios */ + struct ktermios init_termios; /* Initial termios */ int flags; /* tty driver flags */ int refcount; /* for loadable tty drivers */ struct proc_dir_entry *proc_entry; /* /proc fs entry */ @@ -175,8 +175,8 @@ struct tty_driver { * Pointer to the tty data structures */ struct tty_struct **ttys; - struct termios **termios; - struct termios **termios_locked; + struct ktermios **termios; + struct ktermios **termios_locked; void *driver_state; /* only used for the PTY driver */ /* @@ -193,7 +193,7 @@ struct tty_driver { int (*chars_in_buffer)(struct tty_struct *tty); int (*ioctl)(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg); - void (*set_termios)(struct tty_struct *tty, struct termios * old); + void (*set_termios)(struct tty_struct *tty, struct ktermios * old); void (*throttle)(struct tty_struct * tty); void (*unthrottle)(struct tty_struct * tty); void (*stop)(struct tty_struct *tty); diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h index 83c6e6c10eb..d75932e2771 100644 --- a/include/linux/tty_ldisc.h +++ b/include/linux/tty_ldisc.h @@ -59,7 +59,7 @@ * low-level driver can "grab" an ioctl request before the line * discpline has a chance to see it. * - * void (*set_termios)(struct tty_struct *tty, struct termios * old); + * void (*set_termios)(struct tty_struct *tty, struct ktermios * old); * * This function notifies the line discpline that a change has * been made to the termios structure. @@ -118,7 +118,7 @@ struct tty_ldisc { const unsigned char * buf, size_t nr); int (*ioctl)(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg); - void (*set_termios)(struct tty_struct *tty, struct termios * old); + void (*set_termios)(struct tty_struct *tty, struct ktermios * old); unsigned int (*poll)(struct tty_struct *, struct file *, struct poll_table_struct *); int (*hangup)(struct tty_struct *tty); diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 91b3ea2bbb1..10f99e5f1a9 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -218,7 +218,7 @@ struct usb_serial_driver { int (*write) (struct usb_serial_port *port, const unsigned char *buf, int count); int (*write_room) (struct usb_serial_port *port); int (*ioctl) (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); - void (*set_termios) (struct usb_serial_port *port, struct termios * old); + void (*set_termios) (struct usb_serial_port *port, struct ktermios * old); void (*break_ctl) (struct usb_serial_port *port, int break_state); int (*chars_in_buffer) (struct usb_serial_port *port); void (*throttle) (struct usb_serial_port *port); diff --git a/include/net/irda/ircomm_tty.h b/include/net/irda/ircomm_tty.h index 87699cb4ef8..8dabdd603fe 100644 --- a/include/net/irda/ircomm_tty.h +++ b/include/net/irda/ircomm_tty.h @@ -126,7 +126,7 @@ extern int ircomm_tty_tiocmset(struct tty_struct *tty, struct file *file, extern int ircomm_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); extern void ircomm_tty_set_termios(struct tty_struct *tty, - struct termios *old_termios); + struct ktermios *old_termios); extern hashbin_t *ircomm_tty; #endif diff --git a/include/video/mbxfb.h b/include/video/mbxfb.h index 3bde0f5cd55..20b9002712e 100644 --- a/include/video/mbxfb.h +++ b/include/video/mbxfb.h @@ -1,6 +1,9 @@ #ifndef __MBX_FB_H #define __MBX_FB_H +#include <asm/ioctl.h> +#include <asm/types.h> + struct mbxfb_val { unsigned int defval; unsigned int min; @@ -25,4 +28,32 @@ struct mbxfb_platform_data { int (*remove)(struct fb_info *fb); }; +/* planar */ +#define MBXFB_FMT_YUV12 0 + +/* packed */ +#define MBXFB_FMT_UY0VY1 1 +#define MBXFB_FMT_VY0UY1 2 +#define MBXFB_FMT_Y0UY1V 3 +#define MBXFB_FMT_Y0VY1U 4 +struct mbxfb_overlaySetup { + __u32 enable; + __u32 x, y; + __u32 width, height; + __u32 alpha; + __u32 fmt; + __u32 mem_offset; + __u32 scaled_width; + __u32 scaled_height; + + /* Filled by the driver */ + __u32 U_offset; + __u32 V_offset; + + __u16 Y_stride; + __u16 UV_stride; +}; + +#define MBXFB_IOCX_OVERLAY _IOWR(0xF4, 0x00,struct mbxfb_overlaySetup) + #endif /* __MBX_FB_H */ diff --git a/include/video/pm3fb.h b/include/video/pm3fb.h index ac021379ac4..94c7d2da90e 100644 --- a/include/video/pm3fb.h +++ b/include/video/pm3fb.h @@ -607,16 +607,16 @@ #define PM3FBDestReadModeOr 0xac98 #define PM3FBDestReadMode_ReadDisable 0<<0 #define PM3FBDestReadMode_ReadEnable 1<<0 - #define PM3FBDestReadMode_StripePitch(sp) (((sp)&0x7)<<2 - #define PM3FBDestReadMode_StripeHeight(sh) (((sh)&0x7)<<7 + #define PM3FBDestReadMode_StripePitch(sp) (((sp)&0x7)<<2) + #define PM3FBDestReadMode_StripeHeight(sh) (((sh)&0x7)<<7) #define PM3FBDestReadMode_Enable0 1<<8 #define PM3FBDestReadMode_Enable1 1<<9 #define PM3FBDestReadMode_Enable2 1<<10 #define PM3FBDestReadMode_Enable3 1<<11 - #define PM3FBDestReadMode_Layout0(l) (((l)&0x3)<<12 - #define PM3FBDestReadMode_Layout1(l) (((l)&0x3)<<14 - #define PM3FBDestReadMode_Layout2(l) (((l)&0x3)<<16 - #define PM3FBDestReadMode_Layout3(l) (((l)&0x3)<<18 + #define PM3FBDestReadMode_Layout0(l) (((l)&0x3)<<12) + #define PM3FBDestReadMode_Layout1(l) (((l)&0x3)<<14) + #define PM3FBDestReadMode_Layout2(l) (((l)&0x3)<<16) + #define PM3FBDestReadMode_Layout3(l) (((l)&0x3)<<18) #define PM3FBDestReadMode_Origin0 1<<20 #define PM3FBDestReadMode_Origin1 1<<21 #define PM3FBDestReadMode_Origin2 1<<22 @@ -640,16 +640,16 @@ #define PM3FBSourceReadModeOr 0xaca8 #define PM3FBSourceReadMode_ReadDisable (0<<0) #define PM3FBSourceReadMode_ReadEnable (1<<0) - #define PM3FBSourceReadMode_StripePitch(sp) (((sp)&0x7)<<2 - #define PM3FBSourceReadMode_StripeHeight(sh) (((sh)&0x7)<<7 - #define PM3FBSourceReadMode_Layout(l) (((l)&0x3)<<8 + #define PM3FBSourceReadMode_StripePitch(sp) (((sp)&0x7)<<2) + #define PM3FBSourceReadMode_StripeHeight(sh) (((sh)&0x7)<<7) + #define PM3FBSourceReadMode_Layout(l) (((l)&0x3)<<8) #define PM3FBSourceReadMode_Origin 1<<10 #define PM3FBSourceReadMode_Blocking 1<<11 #define PM3FBSourceReadMode_UserTexelCoord 1<<13 #define PM3FBSourceReadMode_WrapXEnable 1<<14 #define PM3FBSourceReadMode_WrapYEnable 1<<15 - #define PM3FBSourceReadMode_WrapX(w) (((w)&0xf)<<16 - #define PM3FBSourceReadMode_WrapY(w) (((w)&0xf)<<20 + #define PM3FBSourceReadMode_WrapX(w) (((w)&0xf)<<16) + #define PM3FBSourceReadMode_WrapY(w) (((w)&0xf)<<20) #define PM3FBSourceReadMode_ExternalSourceData 1<<24 #define PM3FBWriteBufferAddr0 0xb000 #define PM3FBWriteBufferAddr1 0xb008 @@ -942,7 +942,7 @@ #define PM3Window 0x8980 #define PM3Window_ForceLBUpdate 1<<3 #define PM3Window_LBUpdateSource 1<<4 - #define PM3Window_FrameCount(c) (((c)&0xff)<<9 + #define PM3Window_FrameCount(c) (((c)&0xff)<<9) #define PM3Window_StencilFCP 1<<17 #define PM3Window_DepthFCP 1<<18 #define PM3Window_OverrideWriteFiltering 1<<19 diff --git a/init/Makefile b/init/Makefile index 633a268d270..d6c764d0eab 100644 --- a/init/Makefile +++ b/init/Makefile @@ -15,6 +15,7 @@ clean-files := ../include/linux/compile.h # dependencies on generated files need to be listed explicitly +$(obj)/main.o: include/linux/compile.h $(obj)/version.o: include/linux/compile.h # compile.h changes depending on hostname, generation number, etc, diff --git a/init/main.c b/init/main.c index 1174ae3aec8..036f97c0c34 100644 --- a/init/main.c +++ b/init/main.c @@ -50,6 +50,9 @@ #include <linux/buffer_head.h> #include <linux/debug_locks.h> #include <linux/lockdep.h> +#include <linux/utsrelease.h> +#include <linux/pid_namespace.h> +#include <linux/compile.h> #include <asm/io.h> #include <asm/bugs.h> @@ -506,7 +509,7 @@ asmlinkage void __init start_kernel(void) boot_cpu_init(); page_address_init(); printk(KERN_NOTICE); - printk(linux_banner); + printk(linux_banner, UTS_RELEASE, UTS_VERSION); setup_arch(&command_line); unwind_setup(); setup_per_cpu_areas(); @@ -624,8 +627,6 @@ static int __init initcall_debug_setup(char *str) } __setup("initcall_debug", initcall_debug_setup); -struct task_struct *child_reaper = &init_task; - extern initcall_t __initcall_start[], __initcall_end[]; static void __init do_initcalls(void) @@ -725,7 +726,7 @@ static int init(void * unused) * assumptions about where in the task array this * can be found. */ - child_reaper = current; + init_pid_ns.child_reaper = current; cad_pid = task_pid(current); diff --git a/init/version.c b/init/version.c index 8f28344d9c7..2a5dfcd1c2e 100644 --- a/init/version.c +++ b/init/version.c @@ -35,5 +35,6 @@ struct uts_namespace init_uts_ns = { EXPORT_SYMBOL_GPL(init_uts_ns); const char linux_banner[] = - "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@" - LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n"; + "Linux version %s (" LINUX_COMPILE_BY "@" + LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") %s\n"; + diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 3acc1661e51..02717f71d8d 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -322,7 +322,7 @@ static int mqueue_unlink(struct inode *dir, struct dentry *dentry) static ssize_t mqueue_read_file(struct file *filp, char __user *u_data, size_t count, loff_t * off) { - struct mqueue_inode_info *info = MQUEUE_I(filp->f_dentry->d_inode); + struct mqueue_inode_info *info = MQUEUE_I(filp->f_path.dentry->d_inode); char buffer[FILENT_SIZE]; size_t slen; loff_t o; @@ -354,13 +354,13 @@ static ssize_t mqueue_read_file(struct file *filp, char __user *u_data, return -EFAULT; *off = o + count; - filp->f_dentry->d_inode->i_atime = filp->f_dentry->d_inode->i_ctime = CURRENT_TIME; + filp->f_path.dentry->d_inode->i_atime = filp->f_path.dentry->d_inode->i_ctime = CURRENT_TIME; return count; } static int mqueue_flush_file(struct file *filp, fl_owner_t id) { - struct mqueue_inode_info *info = MQUEUE_I(filp->f_dentry->d_inode); + struct mqueue_inode_info *info = MQUEUE_I(filp->f_path.dentry->d_inode); spin_lock(&info->lock); if (task_tgid(current) == info->notify_owner) @@ -372,7 +372,7 @@ static int mqueue_flush_file(struct file *filp, fl_owner_t id) static unsigned int mqueue_poll_file(struct file *filp, struct poll_table_struct *poll_tab) { - struct mqueue_inode_info *info = MQUEUE_I(filp->f_dentry->d_inode); + struct mqueue_inode_info *info = MQUEUE_I(filp->f_path.dentry->d_inode); int retval = 0; poll_wait(filp, &info->wait_q, poll_tab); @@ -836,7 +836,7 @@ asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr, if (unlikely(!filp)) goto out; - inode = filp->f_dentry->d_inode; + inode = filp->f_path.dentry->d_inode; if (unlikely(filp->f_op != &mqueue_file_operations)) goto out_fput; info = MQUEUE_I(inode); @@ -919,7 +919,7 @@ asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr, if (unlikely(!filp)) goto out; - inode = filp->f_dentry->d_inode; + inode = filp->f_path.dentry->d_inode; if (unlikely(filp->f_op != &mqueue_file_operations)) goto out_fput; info = MQUEUE_I(inode); @@ -1056,7 +1056,7 @@ retry: if (!filp) goto out; - inode = filp->f_dentry->d_inode; + inode = filp->f_path.dentry->d_inode; if (unlikely(filp->f_op != &mqueue_file_operations)) goto out_fput; info = MQUEUE_I(inode); @@ -1126,7 +1126,7 @@ asmlinkage long sys_mq_getsetattr(mqd_t mqdes, if (!filp) goto out; - inode = filp->f_dentry->d_inode; + inode = filp->f_path.dentry->d_inode; if (unlikely(filp->f_op != &mqueue_file_operations)) goto out_fput; info = MQUEUE_I(inode); diff --git a/ipc/shm.c b/ipc/shm.c index d1198dd07a1..6d16bb6de7d 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -168,7 +168,7 @@ static inline void shm_inc(struct ipc_namespace *ns, int id) static void shm_open(struct vm_area_struct *shmd) { shm_inc(shm_file_ns(shmd->vm_file), - shmd->vm_file->f_dentry->d_inode->i_ino); + shmd->vm_file->f_path.dentry->d_inode->i_ino); } /* @@ -187,7 +187,7 @@ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp) if (!is_file_hugepages(shp->shm_file)) shmem_lock(shp->shm_file, 0, shp->mlock_user); else - user_shm_unlock(shp->shm_file->f_dentry->d_inode->i_size, + user_shm_unlock(shp->shm_file->f_path.dentry->d_inode->i_size, shp->mlock_user); fput (shp->shm_file); security_shm_free(shp); @@ -203,7 +203,7 @@ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp) static void shm_close (struct vm_area_struct *shmd) { struct file * file = shmd->vm_file; - int id = file->f_dentry->d_inode->i_ino; + int id = file->f_path.dentry->d_inode->i_ino; struct shmid_kernel *shp; struct ipc_namespace *ns; @@ -233,7 +233,7 @@ static int shm_mmap(struct file * file, struct vm_area_struct * vma) vma->vm_ops = &shm_vm_ops; if (!(vma->vm_flags & VM_WRITE)) vma->vm_flags &= ~VM_MAYWRITE; - shm_inc(shm_file_ns(file), file->f_dentry->d_inode->i_ino); + shm_inc(shm_file_ns(file), file->f_path.dentry->d_inode->i_ino); } return ret; @@ -330,7 +330,7 @@ static int newseg (struct ipc_namespace *ns, key_t key, int shmflg, size_t size) shp->shm_nattch = 0; shp->id = shm_buildid(ns, id, shp->shm_perm.seq); shp->shm_file = file; - file->f_dentry->d_inode->i_ino = shp->id; + file->f_path.dentry->d_inode->i_ino = shp->id; shm_file_ns(file) = get_ipc_ns(ns); @@ -495,7 +495,7 @@ static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss, if(!shp) continue; - inode = shp->shm_file->f_dentry->d_inode; + inode = shp->shm_file->f_path.dentry->d_inode; if (is_file_hugepages(shp->shm_file)) { struct address_space *mapping = inode->i_mapping; @@ -843,7 +843,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) } file = shp->shm_file; - size = i_size_read(file->f_dentry->d_inode); + size = i_size_read(file->f_path.dentry->d_inode); shp->shm_nattch++; shm_unlock(shp); @@ -948,7 +948,7 @@ asmlinkage long sys_shmdt(char __user *shmaddr) (vma->vm_start - addr)/PAGE_SIZE == vma->vm_pgoff) { - size = vma->vm_file->f_dentry->d_inode->i_size; + size = vma->vm_file->f_path.dentry->d_inode->i_size; do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start); /* * We discovered the size of the shm segment, so diff --git a/kernel/acct.c b/kernel/acct.c index dc12db8600e..70d0d88e555 100644 --- a/kernel/acct.c +++ b/kernel/acct.c @@ -118,7 +118,7 @@ static int check_free_space(struct file *file) spin_unlock(&acct_globals.lock); /* May block */ - if (vfs_statfs(file->f_dentry, &sbuf)) + if (vfs_statfs(file->f_path.dentry, &sbuf)) return res; suspend = sbuf.f_blocks * SUSPEND; resume = sbuf.f_blocks * RESUME; @@ -194,7 +194,7 @@ static void acct_file_reopen(struct file *file) add_timer(&acct_globals.timer); } if (old_acct) { - mnt_unpin(old_acct->f_vfsmnt); + mnt_unpin(old_acct->f_path.mnt); spin_unlock(&acct_globals.lock); do_acct_process(old_acct); filp_close(old_acct, NULL); @@ -212,7 +212,7 @@ static int acct_on(char *name) if (IS_ERR(file)) return PTR_ERR(file); - if (!S_ISREG(file->f_dentry->d_inode->i_mode)) { + if (!S_ISREG(file->f_path.dentry->d_inode->i_mode)) { filp_close(file, NULL); return -EACCES; } @@ -229,11 +229,11 @@ static int acct_on(char *name) } spin_lock(&acct_globals.lock); - mnt_pin(file->f_vfsmnt); + mnt_pin(file->f_path.mnt); acct_file_reopen(file); spin_unlock(&acct_globals.lock); - mntput(file->f_vfsmnt); /* it's pinned, now give up active reference */ + mntput(file->f_path.mnt); /* it's pinned, now give up active reference */ return 0; } @@ -283,7 +283,7 @@ asmlinkage long sys_acct(const char __user *name) void acct_auto_close_mnt(struct vfsmount *m) { spin_lock(&acct_globals.lock); - if (acct_globals.file && acct_globals.file->f_vfsmnt == m) + if (acct_globals.file && acct_globals.file->f_path.mnt == m) acct_file_reopen(NULL); spin_unlock(&acct_globals.lock); } @@ -299,7 +299,7 @@ void acct_auto_close(struct super_block *sb) { spin_lock(&acct_globals.lock); if (acct_globals.file && - acct_globals.file->f_vfsmnt->mnt_sb == sb) { + acct_globals.file->f_path.mnt->mnt_sb == sb) { acct_file_reopen(NULL); } spin_unlock(&acct_globals.lock); @@ -428,6 +428,7 @@ static void do_acct_process(struct file *file) u64 elapsed; u64 run_time; struct timespec uptime; + struct tty_struct *tty; /* * First check to see if there is enough free_space to continue @@ -484,16 +485,9 @@ static void do_acct_process(struct file *file) ac.ac_ppid = current->parent->tgid; #endif - mutex_lock(&tty_mutex); - /* FIXME: Whoever is responsible for current->signal locking needs - to use the same locking all over the kernel and document it */ - read_lock(&tasklist_lock); - ac.ac_tty = current->signal->tty ? - old_encode_dev(tty_devnum(current->signal->tty)) : 0; - read_unlock(&tasklist_lock); - mutex_unlock(&tty_mutex); - spin_lock_irq(¤t->sighand->siglock); + tty = current->signal->tty; + ac.ac_tty = tty ? old_encode_dev(tty_devnum(tty)) : 0; ac.ac_utime = encode_comp_t(jiffies_to_AHZ(cputime_to_jiffies(pacct->ac_utime))); ac.ac_stime = encode_comp_t(jiffies_to_AHZ(cputime_to_jiffies(pacct->ac_stime))); ac.ac_flag = pacct->ac_flag; diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 40722e26de9..298897559ca 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -781,8 +781,8 @@ static void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) { audit_log_d_path(ab, "exe=", - vma->vm_file->f_dentry, - vma->vm_file->f_vfsmnt); + vma->vm_file->f_path.dentry, + vma->vm_file->f_path.mnt); break; } vma = vma->vm_next; @@ -826,10 +826,12 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts context->return_code); mutex_lock(&tty_mutex); + read_lock(&tasklist_lock); if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name) tty = tsk->signal->tty->name; else tty = "(none)"; + read_unlock(&tasklist_lock); audit_log_format(ab, " a0=%lx a1=%lx a2=%lx a3=%lx items=%d" " ppid=%d pid=%d auid=%u uid=%u gid=%u" diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 0a6b4d89f9a..2c3b4431472 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -413,8 +413,8 @@ static struct file_system_type cpuset_fs_type = { * * * When reading/writing to a file: - * - the cpuset to use in file->f_dentry->d_parent->d_fsdata - * - the 'cftype' of the file is file->f_dentry->d_fsdata + * - the cpuset to use in file->f_path.dentry->d_parent->d_fsdata + * - the 'cftype' of the file is file->f_path.dentry->d_fsdata */ struct cftype { @@ -1284,8 +1284,8 @@ static ssize_t cpuset_common_file_write(struct file *file, const char __user *userbuf, size_t nbytes, loff_t *unused_ppos) { - struct cpuset *cs = __d_cs(file->f_dentry->d_parent); - struct cftype *cft = __d_cft(file->f_dentry); + struct cpuset *cs = __d_cs(file->f_path.dentry->d_parent); + struct cftype *cft = __d_cft(file->f_path.dentry); cpuset_filetype_t type = cft->private; char *buffer; char *pathbuf = NULL; @@ -1367,7 +1367,7 @@ static ssize_t cpuset_file_write(struct file *file, const char __user *buf, size_t nbytes, loff_t *ppos) { ssize_t retval = 0; - struct cftype *cft = __d_cft(file->f_dentry); + struct cftype *cft = __d_cft(file->f_path.dentry); if (!cft) return -ENODEV; @@ -1417,8 +1417,8 @@ static int cpuset_sprintf_memlist(char *page, struct cpuset *cs) static ssize_t cpuset_common_file_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) { - struct cftype *cft = __d_cft(file->f_dentry); - struct cpuset *cs = __d_cs(file->f_dentry->d_parent); + struct cftype *cft = __d_cft(file->f_path.dentry); + struct cpuset *cs = __d_cs(file->f_path.dentry->d_parent); cpuset_filetype_t type = cft->private; char *page; ssize_t retval = 0; @@ -1476,7 +1476,7 @@ static ssize_t cpuset_file_read(struct file *file, char __user *buf, size_t nbyt loff_t *ppos) { ssize_t retval = 0; - struct cftype *cft = __d_cft(file->f_dentry); + struct cftype *cft = __d_cft(file->f_path.dentry); if (!cft) return -ENODEV; @@ -1498,7 +1498,7 @@ static int cpuset_file_open(struct inode *inode, struct file *file) if (err) return err; - cft = __d_cft(file->f_dentry); + cft = __d_cft(file->f_path.dentry); if (!cft) return -ENODEV; if (cft->open) @@ -1511,7 +1511,7 @@ static int cpuset_file_open(struct inode *inode, struct file *file) static int cpuset_file_release(struct inode *inode, struct file *file) { - struct cftype *cft = __d_cft(file->f_dentry); + struct cftype *cft = __d_cft(file->f_path.dentry); if (cft->release) return cft->release(inode, file); return 0; @@ -1700,7 +1700,7 @@ static int pid_array_to_buf(char *buf, int sz, pid_t *a, int npids) */ static int cpuset_tasks_open(struct inode *unused, struct file *file) { - struct cpuset *cs = __d_cs(file->f_dentry->d_parent); + struct cpuset *cs = __d_cs(file->f_path.dentry->d_parent); struct ctr_struct *ctr; pid_t *pidarray; int npids; diff --git a/kernel/exit.c b/kernel/exit.c index 4e3f919edc4..03e64fe4a14 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -13,7 +13,7 @@ #include <linux/completion.h> #include <linux/personality.h> #include <linux/tty.h> -#include <linux/namespace.h> +#include <linux/mnt_namespace.h> #include <linux/key.h> #include <linux/security.h> #include <linux/cpu.h> @@ -22,6 +22,7 @@ #include <linux/file.h> #include <linux/binfmts.h> #include <linux/nsproxy.h> +#include <linux/pid_namespace.h> #include <linux/ptrace.h> #include <linux/profile.h> #include <linux/mount.h> @@ -48,7 +49,6 @@ #include <asm/mmu_context.h> extern void sem_exit (void); -extern struct task_struct *child_reaper; static void exit_mm(struct task_struct * tsk); @@ -189,21 +189,18 @@ repeat: int session_of_pgrp(int pgrp) { struct task_struct *p; - int sid = -1; + int sid = 0; read_lock(&tasklist_lock); - do_each_task_pid(pgrp, PIDTYPE_PGID, p) { - if (p->signal->session > 0) { - sid = p->signal->session; - goto out; - } - } while_each_task_pid(pgrp, PIDTYPE_PGID, p); - p = find_task_by_pid(pgrp); - if (p) - sid = p->signal->session; -out: + + p = find_task_by_pid_type(PIDTYPE_PGID, pgrp); + if (p == NULL) + p = find_task_by_pid(pgrp); + if (p != NULL) + sid = process_session(p); + read_unlock(&tasklist_lock); - + return sid; } @@ -225,8 +222,8 @@ static int will_become_orphaned_pgrp(int pgrp, struct task_struct *ignored_task) || p->exit_state || is_init(p->real_parent)) continue; - if (process_group(p->real_parent) != pgrp - && p->real_parent->signal->session == p->signal->session) { + if (process_group(p->real_parent) != pgrp && + process_session(p->real_parent) == process_session(p)) { ret = 0; break; } @@ -260,7 +257,8 @@ static int has_stopped_jobs(int pgrp) } /** - * reparent_to_init - Reparent the calling kernel thread to the init task. + * reparent_to_init - Reparent the calling kernel thread to the init task + * of the pid space that the thread belongs to. * * If a kernel thread is launched as a result of a system call, or if * it ever exits, it should generally reparent itself to init so that @@ -278,8 +276,8 @@ static void reparent_to_init(void) ptrace_unlink(current); /* Reparent to init */ remove_parent(current); - current->parent = child_reaper; - current->real_parent = child_reaper; + current->parent = child_reaper(current); + current->real_parent = child_reaper(current); add_parent(current); /* Set the exit signal to SIGCHLD so we signal init on exit */ @@ -302,9 +300,9 @@ void __set_special_pids(pid_t session, pid_t pgrp) { struct task_struct *curr = current->group_leader; - if (curr->signal->session != session) { + if (process_session(curr) != session) { detach_pid(curr, PIDTYPE_SID); - curr->signal->session = session; + set_signal_session(curr->signal, session); attach_pid(curr, PIDTYPE_SID, session); } if (process_group(curr) != pgrp) { @@ -314,7 +312,7 @@ void __set_special_pids(pid_t session, pid_t pgrp) } } -void set_special_pids(pid_t session, pid_t pgrp) +static void set_special_pids(pid_t session, pid_t pgrp) { write_lock_irq(&tasklist_lock); __set_special_pids(session, pgrp); @@ -384,9 +382,7 @@ void daemonize(const char *name, ...) exit_mm(current); set_special_pids(1, 1); - mutex_lock(&tty_mutex); - current->signal->tty = NULL; - mutex_unlock(&tty_mutex); + proc_clear_tty(current); /* Block and flush all signals */ sigfillset(&blocked); @@ -649,10 +645,11 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced) * outside, so the child pgrp is now orphaned. */ if ((process_group(p) != process_group(father)) && - (p->signal->session == father->signal->session)) { + (process_session(p) == process_session(father))) { int pgrp = process_group(p); - if (will_become_orphaned_pgrp(pgrp, NULL) && has_stopped_jobs(pgrp)) { + if (will_become_orphaned_pgrp(pgrp, NULL) && + has_stopped_jobs(pgrp)) { __kill_pg_info(SIGHUP, SEND_SIG_PRIV, pgrp); __kill_pg_info(SIGCONT, SEND_SIG_PRIV, pgrp); } @@ -663,7 +660,8 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced) * When we die, we re-parent all our children. * Try to give them to another thread in our thread * group, and if no such member exists, give it to - * the global child reaper process (ie "init") + * the child reaper process (ie "init") in our pid + * space. */ static void forget_original_parent(struct task_struct *father, struct list_head *to_release) @@ -674,7 +672,7 @@ forget_original_parent(struct task_struct *father, struct list_head *to_release) do { reaper = next_thread(reaper); if (reaper == father) { - reaper = child_reaper; + reaper = child_reaper(father); break; } } while (reaper->exit_state); @@ -786,7 +784,7 @@ static void exit_notify(struct task_struct *tsk) t = tsk->real_parent; if ((process_group(t) != process_group(tsk)) && - (t->signal->session == tsk->signal->session) && + (process_session(t) == process_session(tsk)) && will_become_orphaned_pgrp(process_group(tsk), tsk) && has_stopped_jobs(process_group(tsk))) { __kill_pg_info(SIGHUP, SEND_SIG_PRIV, process_group(tsk)); @@ -860,8 +858,13 @@ fastcall NORET_TYPE void do_exit(long code) panic("Aiee, killing interrupt handler!"); if (unlikely(!tsk->pid)) panic("Attempted to kill the idle task!"); - if (unlikely(tsk == child_reaper)) - panic("Attempted to kill init!"); + if (unlikely(tsk == child_reaper(tsk))) { + if (tsk->nsproxy->pid_ns != &init_pid_ns) + tsk->nsproxy->pid_ns->child_reaper = init_pid_ns.child_reaper; + else + panic("Attempted to kill init!"); + } + if (unlikely(current->ptrace & PT_TRACE_EXIT)) { current->ptrace_message = code; diff --git a/kernel/fork.c b/kernel/fork.c index 7f2e31ba33a..8c859eef8e6 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -18,7 +18,7 @@ #include <linux/module.h> #include <linux/vmalloc.h> #include <linux/completion.h> -#include <linux/namespace.h> +#include <linux/mnt_namespace.h> #include <linux/personality.h> #include <linux/mempolicy.h> #include <linux/sem.h> @@ -252,7 +252,7 @@ static inline int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) anon_vma_link(tmp); file = tmp->vm_file; if (file) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; get_file(file); if (tmp->vm_flags & VM_DENYWRITE) atomic_dec(&inode->i_writecount); @@ -1259,9 +1259,9 @@ static struct task_struct *copy_process(unsigned long clone_flags, if (thread_group_leader(p)) { p->signal->tty = current->signal->tty; p->signal->pgrp = process_group(current); - p->signal->session = current->signal->session; + set_signal_session(p->signal, process_session(current)); attach_pid(p, PIDTYPE_PGID, process_group(p)); - attach_pid(p, PIDTYPE_SID, p->signal->session); + attach_pid(p, PIDTYPE_SID, process_session(p)); list_add_tail_rcu(&p->tasks, &init_task.tasks); __get_cpu_var(process_counts)++; @@ -1525,17 +1525,18 @@ static int unshare_fs(unsigned long unshare_flags, struct fs_struct **new_fsp) } /* - * Unshare the namespace structure if it is being shared + * Unshare the mnt_namespace structure if it is being shared */ -static int unshare_namespace(unsigned long unshare_flags, struct namespace **new_nsp, struct fs_struct *new_fs) +static int unshare_mnt_namespace(unsigned long unshare_flags, + struct mnt_namespace **new_nsp, struct fs_struct *new_fs) { - struct namespace *ns = current->nsproxy->namespace; + struct mnt_namespace *ns = current->nsproxy->mnt_ns; if ((unshare_flags & CLONE_NEWNS) && ns) { if (!capable(CAP_SYS_ADMIN)) return -EPERM; - *new_nsp = dup_namespace(current, new_fs ? new_fs : current->fs); + *new_nsp = dup_mnt_ns(current, new_fs ? new_fs : current->fs); if (!*new_nsp) return -ENOMEM; } @@ -1544,15 +1545,13 @@ static int unshare_namespace(unsigned long unshare_flags, struct namespace **new } /* - * Unsharing of sighand for tasks created with CLONE_SIGHAND is not - * supported yet + * Unsharing of sighand is not supported yet */ static int unshare_sighand(unsigned long unshare_flags, struct sighand_struct **new_sighp) { struct sighand_struct *sigh = current->sighand; - if ((unshare_flags & CLONE_SIGHAND) && - (sigh && atomic_read(&sigh->count) > 1)) + if ((unshare_flags & CLONE_SIGHAND) && atomic_read(&sigh->count) > 1) return -EINVAL; else return 0; @@ -1625,8 +1624,8 @@ asmlinkage long sys_unshare(unsigned long unshare_flags) { int err = 0; struct fs_struct *fs, *new_fs = NULL; - struct namespace *ns, *new_ns = NULL; - struct sighand_struct *sigh, *new_sigh = NULL; + struct mnt_namespace *ns, *new_ns = NULL; + struct sighand_struct *new_sigh = NULL; struct mm_struct *mm, *new_mm = NULL, *active_mm = NULL; struct files_struct *fd, *new_fd = NULL; struct sem_undo_list *new_ulist = NULL; @@ -1647,7 +1646,7 @@ asmlinkage long sys_unshare(unsigned long unshare_flags) goto bad_unshare_out; if ((err = unshare_fs(unshare_flags, &new_fs))) goto bad_unshare_cleanup_thread; - if ((err = unshare_namespace(unshare_flags, &new_ns, new_fs))) + if ((err = unshare_mnt_namespace(unshare_flags, &new_ns, new_fs))) goto bad_unshare_cleanup_fs; if ((err = unshare_sighand(unshare_flags, &new_sigh))) goto bad_unshare_cleanup_ns; @@ -1671,7 +1670,7 @@ asmlinkage long sys_unshare(unsigned long unshare_flags) } } - if (new_fs || new_ns || new_sigh || new_mm || new_fd || new_ulist || + if (new_fs || new_ns || new_mm || new_fd || new_ulist || new_uts || new_ipc) { task_lock(current); @@ -1688,17 +1687,11 @@ asmlinkage long sys_unshare(unsigned long unshare_flags) } if (new_ns) { - ns = current->nsproxy->namespace; - current->nsproxy->namespace = new_ns; + ns = current->nsproxy->mnt_ns; + current->nsproxy->mnt_ns = new_ns; new_ns = ns; } - if (new_sigh) { - sigh = current->sighand; - rcu_assign_pointer(current->sighand, new_sigh); - new_sigh = sigh; - } - if (new_mm) { mm = current->mm; active_mm = current->active_mm; @@ -1756,7 +1749,7 @@ bad_unshare_cleanup_sigh: bad_unshare_cleanup_ns: if (new_ns) - put_namespace(new_ns); + put_mnt_ns(new_ns); bad_unshare_cleanup_fs: if (new_fs) diff --git a/kernel/futex.c b/kernel/futex.c index 95989a3b416..5a737de857d 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -166,7 +166,7 @@ static inline int match_futex(union futex_key *key1, union futex_key *key2) /* * Get parameters which are the keys for a futex. * - * For shared mappings, it's (page->index, vma->vm_file->f_dentry->d_inode, + * For shared mappings, it's (page->index, vma->vm_file->f_path.dentry->d_inode, * offset_within_page). For private mappings, it's (uaddr, current->mm). * We can usually work out the index without swapping in the page. * @@ -223,7 +223,7 @@ static int get_futex_key(u32 __user *uaddr, union futex_key *key) /* * Linear file mappings are also simple. */ - key->shared.inode = vma->vm_file->f_dentry->d_inode; + key->shared.inode = vma->vm_file->f_path.dentry->d_inode; key->both.offset++; /* Bit 0 of offset indicates inode-based key. */ if (likely(!(vma->vm_flags & VM_NONLINEAR))) { key->shared.pgoff = (((address - vma->vm_start) >> PAGE_SHIFT) @@ -1528,9 +1528,9 @@ static int futex_fd(u32 __user *uaddr, int signal) goto out; } filp->f_op = &futex_fops; - filp->f_vfsmnt = mntget(futex_mnt); - filp->f_dentry = dget(futex_mnt->mnt_root); - filp->f_mapping = filp->f_dentry->d_inode->i_mapping; + filp->f_path.mnt = mntget(futex_mnt); + filp->f_path.dentry = dget(futex_mnt->mnt_root); + filp->f_mapping = filp->f_path.dentry->d_inode->i_mapping; if (signal) { err = __f_setown(filp, task_pid(current), PIDTYPE_PID, 1); diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index 9a352667007..61f5c717a8f 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c @@ -54,7 +54,8 @@ static int irq_affinity_write_proc(struct file *file, const char __user *buffer, unsigned int irq = (int)(long)data, full_count = count, err; cpumask_t new_value, tmp; - if (!irq_desc[irq].chip->set_affinity || no_irq_affinity) + if (!irq_desc[irq].chip->set_affinity || no_irq_affinity || + CHECK_IRQ_PER_CPU(irq_desc[irq].status)) return -EIO; err = cpumask_parse_user(buffer, count, new_value); diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c index ab63cfc4299..6f294ff4f9e 100644 --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c @@ -31,14 +31,14 @@ #endif /* These will be re-linked against their real values during the second link stage */ -extern unsigned long kallsyms_addresses[] __attribute__((weak)); -extern unsigned long kallsyms_num_syms __attribute__((weak,section("data"))); -extern u8 kallsyms_names[] __attribute__((weak)); +extern const unsigned long kallsyms_addresses[] __attribute__((weak)); +extern const unsigned long kallsyms_num_syms __attribute__((weak)); +extern const u8 kallsyms_names[] __attribute__((weak)); -extern u8 kallsyms_token_table[] __attribute__((weak)); -extern u16 kallsyms_token_index[] __attribute__((weak)); +extern const u8 kallsyms_token_table[] __attribute__((weak)); +extern const u16 kallsyms_token_index[] __attribute__((weak)); -extern unsigned long kallsyms_markers[] __attribute__((weak)); +extern const unsigned long kallsyms_markers[] __attribute__((weak)); static inline int is_kernel_inittext(unsigned long addr) { @@ -84,7 +84,7 @@ static int is_ksym_addr(unsigned long addr) static unsigned int kallsyms_expand_symbol(unsigned int off, char *result) { int len, skipped_first = 0; - u8 *tptr, *data; + const u8 *tptr, *data; /* get the compressed symbol length from the first symbol byte */ data = &kallsyms_names[off]; @@ -132,7 +132,7 @@ static char kallsyms_get_symbol_type(unsigned int off) * kallsyms array */ static unsigned int get_symbol_offset(unsigned long pos) { - u8 *name; + const u8 *name; int i; /* use the closest marker we have. We have markers every 256 positions, diff --git a/kernel/kmod.c b/kernel/kmod.c index 8d2bea09a4e..3a7379aa31c 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -25,7 +25,7 @@ #include <linux/kmod.h> #include <linux/smp_lock.h> #include <linux/slab.h> -#include <linux/namespace.h> +#include <linux/mnt_namespace.h> #include <linux/completion.h> #include <linux/file.h> #include <linux/workqueue.h> diff --git a/kernel/mutex.c b/kernel/mutex.c index 8c71cf72a49..e7cbbb82765 100644 --- a/kernel/mutex.c +++ b/kernel/mutex.c @@ -206,6 +206,15 @@ mutex_lock_nested(struct mutex *lock, unsigned int subclass) } EXPORT_SYMBOL_GPL(mutex_lock_nested); + +int __sched +mutex_lock_interruptible_nested(struct mutex *lock, unsigned int subclass) +{ + might_sleep(); + return __mutex_lock_common(lock, TASK_INTERRUPTIBLE, subclass); +} + +EXPORT_SYMBOL_GPL(mutex_lock_interruptible_nested); #endif /* diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c index 674aceb7335..e2ce748e96a 100644 --- a/kernel/nsproxy.c +++ b/kernel/nsproxy.c @@ -17,8 +17,9 @@ #include <linux/version.h> #include <linux/nsproxy.h> #include <linux/init_task.h> -#include <linux/namespace.h> +#include <linux/mnt_namespace.h> #include <linux/utsname.h> +#include <linux/pid_namespace.h> struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy); @@ -45,8 +46,10 @@ static inline struct nsproxy *clone_namespaces(struct nsproxy *orig) struct nsproxy *ns; ns = kmemdup(orig, sizeof(struct nsproxy), GFP_KERNEL); - if (ns) + if (ns) { atomic_set(&ns->count, 1); + ns->id = -1; + } return ns; } @@ -60,12 +63,14 @@ struct nsproxy *dup_namespaces(struct nsproxy *orig) struct nsproxy *ns = clone_namespaces(orig); if (ns) { - if (ns->namespace) - get_namespace(ns->namespace); + if (ns->mnt_ns) + get_mnt_ns(ns->mnt_ns); if (ns->uts_ns) get_uts_ns(ns->uts_ns); if (ns->ipc_ns) get_ipc_ns(ns->ipc_ns); + if (ns->pid_ns) + get_pid_ns(ns->pid_ns); } return ns; @@ -97,7 +102,7 @@ int copy_namespaces(int flags, struct task_struct *tsk) tsk->nsproxy = new_ns; - err = copy_namespace(flags, tsk); + err = copy_mnt_ns(flags, tsk); if (err) goto out_ns; @@ -109,16 +114,23 @@ int copy_namespaces(int flags, struct task_struct *tsk) if (err) goto out_ipc; + err = copy_pid_ns(flags, tsk); + if (err) + goto out_pid; + out: put_nsproxy(old_ns); return err; +out_pid: + if (new_ns->ipc_ns) + put_ipc_ns(new_ns->ipc_ns); out_ipc: if (new_ns->uts_ns) put_uts_ns(new_ns->uts_ns); out_uts: - if (new_ns->namespace) - put_namespace(new_ns->namespace); + if (new_ns->mnt_ns) + put_mnt_ns(new_ns->mnt_ns); out_ns: tsk->nsproxy = old_ns; kfree(new_ns); @@ -127,11 +139,13 @@ out_ns: void free_nsproxy(struct nsproxy *ns) { - if (ns->namespace) - put_namespace(ns->namespace); - if (ns->uts_ns) - put_uts_ns(ns->uts_ns); - if (ns->ipc_ns) - put_ipc_ns(ns->ipc_ns); - kfree(ns); + if (ns->mnt_ns) + put_mnt_ns(ns->mnt_ns); + if (ns->uts_ns) + put_uts_ns(ns->uts_ns); + if (ns->ipc_ns) + put_ipc_ns(ns->ipc_ns); + if (ns->pid_ns) + put_pid_ns(ns->pid_ns); + kfree(ns); } diff --git a/kernel/pid.c b/kernel/pid.c index a48879b0b92..2efe9d8d367 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -26,7 +26,7 @@ #include <linux/init.h> #include <linux/bootmem.h> #include <linux/hash.h> -#include <linux/pspace.h> +#include <linux/pid_namespace.h> #define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift) static struct hlist_head *pid_hash; @@ -43,9 +43,10 @@ int pid_max_max = PID_MAX_LIMIT; #define BITS_PER_PAGE (PAGE_SIZE*8) #define BITS_PER_PAGE_MASK (BITS_PER_PAGE-1) -static inline int mk_pid(struct pspace *pspace, struct pidmap *map, int off) +static inline int mk_pid(struct pid_namespace *pid_ns, + struct pidmap *map, int off) { - return (map - pspace->pidmap)*BITS_PER_PAGE + off; + return (map - pid_ns->pidmap)*BITS_PER_PAGE + off; } #define find_next_offset(map, off) \ @@ -57,11 +58,15 @@ static inline int mk_pid(struct pspace *pspace, struct pidmap *map, int off) * value does not cause lots of bitmaps to be allocated, but * the scheme scales to up to 4 million PIDs, runtime. */ -struct pspace init_pspace = { +struct pid_namespace init_pid_ns = { + .kref = { + .refcount = ATOMIC_INIT(2), + }, .pidmap = { [ 0 ... PIDMAP_ENTRIES-1] = { ATOMIC_INIT(BITS_PER_PAGE), NULL } }, - .last_pid = 0 + .last_pid = 0, + .child_reaper = &init_task }; /* @@ -80,25 +85,25 @@ struct pspace init_pspace = { static __cacheline_aligned_in_smp DEFINE_SPINLOCK(pidmap_lock); -static fastcall void free_pidmap(struct pspace *pspace, int pid) +static fastcall void free_pidmap(struct pid_namespace *pid_ns, int pid) { - struct pidmap *map = pspace->pidmap + pid / BITS_PER_PAGE; + struct pidmap *map = pid_ns->pidmap + pid / BITS_PER_PAGE; int offset = pid & BITS_PER_PAGE_MASK; clear_bit(offset, map->page); atomic_inc(&map->nr_free); } -static int alloc_pidmap(struct pspace *pspace) +static int alloc_pidmap(struct pid_namespace *pid_ns) { - int i, offset, max_scan, pid, last = pspace->last_pid; + int i, offset, max_scan, pid, last = pid_ns->last_pid; struct pidmap *map; pid = last + 1; if (pid >= pid_max) pid = RESERVED_PIDS; offset = pid & BITS_PER_PAGE_MASK; - map = &pspace->pidmap[pid/BITS_PER_PAGE]; + map = &pid_ns->pidmap[pid/BITS_PER_PAGE]; max_scan = (pid_max + BITS_PER_PAGE - 1)/BITS_PER_PAGE - !offset; for (i = 0; i <= max_scan; ++i) { if (unlikely(!map->page)) { @@ -120,11 +125,11 @@ static int alloc_pidmap(struct pspace *pspace) do { if (!test_and_set_bit(offset, map->page)) { atomic_dec(&map->nr_free); - pspace->last_pid = pid; + pid_ns->last_pid = pid; return pid; } offset = find_next_offset(map, offset); - pid = mk_pid(pspace, map, offset); + pid = mk_pid(pid_ns, map, offset); /* * find_next_offset() found a bit, the pid from it * is in-bounds, and if we fell back to the last @@ -135,34 +140,34 @@ static int alloc_pidmap(struct pspace *pspace) (i != max_scan || pid < last || !((last+1) & BITS_PER_PAGE_MASK))); } - if (map < &pspace->pidmap[(pid_max-1)/BITS_PER_PAGE]) { + if (map < &pid_ns->pidmap[(pid_max-1)/BITS_PER_PAGE]) { ++map; offset = 0; } else { - map = &pspace->pidmap[0]; + map = &pid_ns->pidmap[0]; offset = RESERVED_PIDS; if (unlikely(last == offset)) break; } - pid = mk_pid(pspace, map, offset); + pid = mk_pid(pid_ns, map, offset); } return -1; } -static int next_pidmap(struct pspace *pspace, int last) +static int next_pidmap(struct pid_namespace *pid_ns, int last) { int offset; struct pidmap *map, *end; offset = (last + 1) & BITS_PER_PAGE_MASK; - map = &pspace->pidmap[(last + 1)/BITS_PER_PAGE]; - end = &pspace->pidmap[PIDMAP_ENTRIES]; + map = &pid_ns->pidmap[(last + 1)/BITS_PER_PAGE]; + end = &pid_ns->pidmap[PIDMAP_ENTRIES]; for (; map < end; map++, offset = 0) { if (unlikely(!map->page)) continue; offset = find_next_bit((map)->page, BITS_PER_PAGE, offset); if (offset < BITS_PER_PAGE) - return mk_pid(pspace, map, offset); + return mk_pid(pid_ns, map, offset); } return -1; } @@ -192,7 +197,7 @@ fastcall void free_pid(struct pid *pid) hlist_del_rcu(&pid->pid_chain); spin_unlock_irqrestore(&pidmap_lock, flags); - free_pidmap(&init_pspace, pid->nr); + free_pidmap(current->nsproxy->pid_ns, pid->nr); call_rcu(&pid->rcu, delayed_put_pid); } @@ -206,7 +211,7 @@ struct pid *alloc_pid(void) if (!pid) goto out; - nr = alloc_pidmap(&init_pspace); + nr = alloc_pidmap(current->nsproxy->pid_ns); if (nr < 0) goto out_free; @@ -348,13 +353,33 @@ struct pid *find_ge_pid(int nr) pid = find_pid(nr); if (pid) break; - nr = next_pidmap(&init_pspace, nr); + nr = next_pidmap(current->nsproxy->pid_ns, nr); } while (nr > 0); return pid; } EXPORT_SYMBOL_GPL(find_get_pid); +int copy_pid_ns(int flags, struct task_struct *tsk) +{ + struct pid_namespace *old_ns = tsk->nsproxy->pid_ns; + int err = 0; + + if (!old_ns) + return 0; + + get_pid_ns(old_ns); + return err; +} + +void free_pid_ns(struct kref *kref) +{ + struct pid_namespace *ns; + + ns = container_of(kref, struct pid_namespace, kref); + kfree(ns); +} + /* * The pid hash table is scaled according to the amount of memory in the * machine. From a minimum of 16 slots up to 4096 slots at one gigabyte or @@ -382,10 +407,10 @@ void __init pidhash_init(void) void __init pidmap_init(void) { - init_pspace.pidmap[0].page = kzalloc(PAGE_SIZE, GFP_KERNEL); + init_pid_ns.pidmap[0].page = kzalloc(PAGE_SIZE, GFP_KERNEL); /* Reserve PID 0. We never call free_pidmap(0) */ - set_bit(0, init_pspace.pidmap[0].page); - atomic_dec(&init_pspace.pidmap[0].nr_free); + set_bit(0, init_pid_ns.pidmap[0].page); + atomic_dec(&init_pid_ns.pidmap[0].nr_free); pid_cachep = kmem_cache_create("pid", sizeof(struct pid), __alignof__(struct pid), diff --git a/kernel/relay.c b/kernel/relay.c index 75a3a9a7efc..818e514729c 100644 --- a/kernel/relay.c +++ b/kernel/relay.c @@ -959,7 +959,7 @@ static inline ssize_t relay_file_read_subbufs(struct file *filp, if (!desc->count) return 0; - mutex_lock(&filp->f_dentry->d_inode->i_mutex); + mutex_lock(&filp->f_path.dentry->d_inode->i_mutex); do { if (!relay_file_read_avail(buf, *ppos)) break; @@ -979,7 +979,7 @@ static inline ssize_t relay_file_read_subbufs(struct file *filp, *ppos = relay_file_read_end_pos(buf, read_start, ret); } } while (desc->count && ret); - mutex_unlock(&filp->f_dentry->d_inode->i_mutex); + mutex_unlock(&filp->f_path.dentry->d_inode->i_mutex); return desc->written; } diff --git a/kernel/signal.c b/kernel/signal.c index ec81defde33..1921ffdc5e7 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -24,6 +24,9 @@ #include <linux/signal.h> #include <linux/capability.h> #include <linux/freezer.h> +#include <linux/pid_namespace.h> +#include <linux/nsproxy.h> + #include <asm/param.h> #include <asm/uaccess.h> #include <asm/unistd.h> @@ -583,7 +586,7 @@ static int check_kill_permission(int sig, struct siginfo *info, error = -EPERM; if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info))) && ((sig != SIGCONT) || - (current->signal->session != t->signal->session)) + (process_session(current) != process_session(t))) && (current->euid ^ t->suid) && (current->euid ^ t->uid) && (current->uid ^ t->suid) && (current->uid ^ t->uid) && !capable(CAP_KILL)) @@ -1877,8 +1880,12 @@ relock: if (sig_kernel_ignore(signr)) /* Default is nothing. */ continue; - /* Init gets no signals it doesn't want. */ - if (current == child_reaper) + /* + * Init of a pid space gets no signals it doesn't want from + * within that pid space. It can of course get signals from + * its parent pid space. + */ + if (current == child_reaper(current)) continue; if (sig_kernel_stop(signr)) { diff --git a/kernel/sys.c b/kernel/sys.c index a0c1a29a507..c7675c1bfdf 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1381,7 +1381,7 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid) if (p->real_parent == group_leader) { err = -EPERM; - if (p->signal->session != group_leader->signal->session) + if (process_session(p) != process_session(group_leader)) goto out; err = -EACCES; if (p->did_exec) @@ -1397,16 +1397,13 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid) goto out; if (pgid != pid) { - struct task_struct *p; + struct task_struct *g = + find_task_by_pid_type(PIDTYPE_PGID, pgid); - do_each_task_pid(pgid, PIDTYPE_PGID, p) { - if (p->signal->session == group_leader->signal->session) - goto ok_pgid; - } while_each_task_pid(pgid, PIDTYPE_PGID, p); - goto out; + if (!g || process_session(g) != process_session(group_leader)) + goto out; } -ok_pgid: err = security_task_setpgid(p, pgid); if (err) goto out; @@ -1459,7 +1456,7 @@ asmlinkage long sys_getpgrp(void) asmlinkage long sys_getsid(pid_t pid) { if (!pid) - return current->signal->session; + return process_session(current); else { int retval; struct task_struct *p; @@ -1471,7 +1468,7 @@ asmlinkage long sys_getsid(pid_t pid) if (p) { retval = security_task_getsid(p); if (!retval) - retval = p->signal->session; + retval = process_session(p); } read_unlock(&tasklist_lock); return retval; @@ -1484,7 +1481,6 @@ asmlinkage long sys_setsid(void) pid_t session; int err = -EPERM; - mutex_lock(&tty_mutex); write_lock_irq(&tasklist_lock); /* Fail if I am already a session leader */ @@ -1504,12 +1500,15 @@ asmlinkage long sys_setsid(void) group_leader->signal->leader = 1; __set_special_pids(session, session); + + spin_lock(&group_leader->sighand->siglock); group_leader->signal->tty = NULL; group_leader->signal->tty_old_pgrp = 0; + spin_unlock(&group_leader->sighand->siglock); + err = process_group(group_leader); out: write_unlock_irq(&tasklist_lock); - mutex_unlock(&tty_mutex); return err; } diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 8e9f00fd6d1..025fcb3c66f 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -92,7 +92,9 @@ extern char modprobe_path[]; extern int sg_big_buff; #endif #ifdef CONFIG_SYSVIPC -static int proc_do_ipc_string(ctl_table *table, int write, struct file *filp, +static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos); +static int proc_ipc_doulongvec_minmax(ctl_table *table, int write, struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos); #endif @@ -137,6 +139,16 @@ static int parse_table(int __user *, int, void __user *, size_t __user *, static int proc_do_uts_string(ctl_table *table, int write, struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos); +static int sysctl_uts_string(ctl_table *table, int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen, void **context); + +#ifdef CONFIG_SYSVIPC +static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen, void **context); +#endif + #ifdef CONFIG_PROC_SYSCTL static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos); @@ -163,6 +175,40 @@ extern ctl_table inotify_table[]; int sysctl_legacy_va_layout; #endif +static void *get_uts(ctl_table *table, int write) +{ + char *which = table->data; +#ifdef CONFIG_UTS_NS + struct uts_namespace *uts_ns = current->nsproxy->uts_ns; + which = (which - (char *)&init_uts_ns) + (char *)uts_ns; +#endif + if (!write) + down_read(&uts_sem); + else + down_write(&uts_sem); + return which; +} + +static void put_uts(ctl_table *table, int write, void *which) +{ + if (!write) + up_read(&uts_sem); + else + up_write(&uts_sem); +} + +#ifdef CONFIG_SYSVIPC +static void *get_ipc(ctl_table *table, int write) +{ + char *which = table->data; + struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; + which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns; + return which; +} +#else +#define get_ipc(T,W) ((T)->data) +#endif + /* /proc declarations: */ #ifdef CONFIG_PROC_SYSCTL @@ -229,7 +275,6 @@ static ctl_table root_table[] = { }; static ctl_table kern_table[] = { -#ifndef CONFIG_UTS_NS { .ctl_name = KERN_OSTYPE, .procname = "ostype", @@ -237,7 +282,7 @@ static ctl_table kern_table[] = { .maxlen = sizeof(init_uts_ns.name.sysname), .mode = 0444, .proc_handler = &proc_do_uts_string, - .strategy = &sysctl_string, + .strategy = &sysctl_uts_string, }, { .ctl_name = KERN_OSRELEASE, @@ -246,7 +291,7 @@ static ctl_table kern_table[] = { .maxlen = sizeof(init_uts_ns.name.release), .mode = 0444, .proc_handler = &proc_do_uts_string, - .strategy = &sysctl_string, + .strategy = &sysctl_uts_string, }, { .ctl_name = KERN_VERSION, @@ -255,7 +300,7 @@ static ctl_table kern_table[] = { .maxlen = sizeof(init_uts_ns.name.version), .mode = 0444, .proc_handler = &proc_do_uts_string, - .strategy = &sysctl_string, + .strategy = &sysctl_uts_string, }, { .ctl_name = KERN_NODENAME, @@ -264,7 +309,7 @@ static ctl_table kern_table[] = { .maxlen = sizeof(init_uts_ns.name.nodename), .mode = 0644, .proc_handler = &proc_do_uts_string, - .strategy = &sysctl_string, + .strategy = &sysctl_uts_string, }, { .ctl_name = KERN_DOMAINNAME, @@ -273,56 +318,8 @@ static ctl_table kern_table[] = { .maxlen = sizeof(init_uts_ns.name.domainname), .mode = 0644, .proc_handler = &proc_do_uts_string, - .strategy = &sysctl_string, - }, -#else /* !CONFIG_UTS_NS */ - { - .ctl_name = KERN_OSTYPE, - .procname = "ostype", - .data = NULL, - /* could maybe use __NEW_UTS_LEN here? */ - .maxlen = FIELD_SIZEOF(struct new_utsname, sysname), - .mode = 0444, - .proc_handler = &proc_do_uts_string, - .strategy = &sysctl_string, - }, - { - .ctl_name = KERN_OSRELEASE, - .procname = "osrelease", - .data = NULL, - .maxlen = FIELD_SIZEOF(struct new_utsname, release), - .mode = 0444, - .proc_handler = &proc_do_uts_string, - .strategy = &sysctl_string, - }, - { - .ctl_name = KERN_VERSION, - .procname = "version", - .data = NULL, - .maxlen = FIELD_SIZEOF(struct new_utsname, version), - .mode = 0444, - .proc_handler = &proc_do_uts_string, - .strategy = &sysctl_string, - }, - { - .ctl_name = KERN_NODENAME, - .procname = "hostname", - .data = NULL, - .maxlen = FIELD_SIZEOF(struct new_utsname, nodename), - .mode = 0644, - .proc_handler = &proc_do_uts_string, - .strategy = &sysctl_string, - }, - { - .ctl_name = KERN_DOMAINNAME, - .procname = "domainname", - .data = NULL, - .maxlen = FIELD_SIZEOF(struct new_utsname, domainname), - .mode = 0644, - .proc_handler = &proc_do_uts_string, - .strategy = &sysctl_string, + .strategy = &sysctl_uts_string, }, -#endif /* !CONFIG_UTS_NS */ { .ctl_name = KERN_PANIC, .procname = "panic", @@ -481,58 +478,65 @@ static ctl_table kern_table[] = { { .ctl_name = KERN_SHMMAX, .procname = "shmmax", - .data = NULL, - .maxlen = sizeof (size_t), + .data = &init_ipc_ns.shm_ctlmax, + .maxlen = sizeof (init_ipc_ns.shm_ctlmax), .mode = 0644, - .proc_handler = &proc_do_ipc_string, + .proc_handler = &proc_ipc_doulongvec_minmax, + .strategy = sysctl_ipc_data, }, { .ctl_name = KERN_SHMALL, .procname = "shmall", - .data = NULL, - .maxlen = sizeof (size_t), + .data = &init_ipc_ns.shm_ctlall, + .maxlen = sizeof (init_ipc_ns.shm_ctlall), .mode = 0644, - .proc_handler = &proc_do_ipc_string, + .proc_handler = &proc_ipc_doulongvec_minmax, + .strategy = sysctl_ipc_data, }, { .ctl_name = KERN_SHMMNI, .procname = "shmmni", - .data = NULL, - .maxlen = sizeof (int), + .data = &init_ipc_ns.shm_ctlmni, + .maxlen = sizeof (init_ipc_ns.shm_ctlmni), .mode = 0644, - .proc_handler = &proc_do_ipc_string, + .proc_handler = &proc_ipc_dointvec, + .strategy = sysctl_ipc_data, }, { .ctl_name = KERN_MSGMAX, .procname = "msgmax", - .data = NULL, - .maxlen = sizeof (int), + .data = &init_ipc_ns.msg_ctlmax, + .maxlen = sizeof (init_ipc_ns.msg_ctlmax), .mode = 0644, - .proc_handler = &proc_do_ipc_string, + .proc_handler = &proc_ipc_dointvec, + .strategy = sysctl_ipc_data, }, { .ctl_name = KERN_MSGMNI, .procname = "msgmni", - .data = NULL, - .maxlen = sizeof (int), + .data = &init_ipc_ns.msg_ctlmni, + .maxlen = sizeof (init_ipc_ns.msg_ctlmni), .mode = 0644, - .proc_handler = &proc_do_ipc_string, + .proc_handler = &proc_ipc_dointvec, + .strategy = sysctl_ipc_data, }, { .ctl_name = KERN_MSGMNB, .procname = "msgmnb", - .data = NULL, - .maxlen = sizeof (int), + .data = &init_ipc_ns.msg_ctlmnb, + .maxlen = sizeof (init_ipc_ns.msg_ctlmnb), .mode = 0644, - .proc_handler = &proc_do_ipc_string, + .proc_handler = &proc_ipc_dointvec, + .strategy = sysctl_ipc_data, }, { .ctl_name = KERN_SEM, .procname = "sem", - .data = NULL, + .data = &init_ipc_ns.sem_ctls, .maxlen = 4*sizeof (int), .mode = 0644, - .proc_handler = &proc_do_ipc_string, + .proc_handler = &proc_ipc_dointvec, + .strategy = sysctl_ipc_data, }, #endif #ifdef CONFIG_MAGIC_SYSRQ @@ -1614,7 +1618,7 @@ static ssize_t do_rw_proc(int write, struct file * file, char __user * buf, size_t count, loff_t *ppos) { int op; - struct proc_dir_entry *de = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *de = PDE(file->f_path.dentry->d_inode); struct ctl_table *table; size_t res; ssize_t error = -ENOTDIR; @@ -1753,66 +1757,17 @@ int proc_dostring(ctl_table *table, int write, struct file *filp, * Special case of dostring for the UTS structure. This has locks * to observe. Should this be in kernel/sys.c ???? */ - -#ifndef CONFIG_UTS_NS -static int proc_do_uts_string(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp, loff_t *ppos) -{ - int r; - if (!write) { - down_read(&uts_sem); - r=proc_dostring(table,0,filp,buffer,lenp, ppos); - up_read(&uts_sem); - } else { - down_write(&uts_sem); - r=proc_dostring(table,1,filp,buffer,lenp, ppos); - up_write(&uts_sem); - } - return r; -} -#else /* !CONFIG_UTS_NS */ static int proc_do_uts_string(ctl_table *table, int write, struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos) { int r; - struct uts_namespace* uts_ns = current->nsproxy->uts_ns; - char* which; - - switch (table->ctl_name) { - case KERN_OSTYPE: - which = uts_ns->name.sysname; - break; - case KERN_NODENAME: - which = uts_ns->name.nodename; - break; - case KERN_OSRELEASE: - which = uts_ns->name.release; - break; - case KERN_VERSION: - which = uts_ns->name.version; - break; - case KERN_DOMAINNAME: - which = uts_ns->name.domainname; - break; - default: - r = -EINVAL; - goto out; - } - - if (!write) { - down_read(&uts_sem); - r=_proc_do_string(which,table->maxlen,0,filp,buffer,lenp, ppos); - up_read(&uts_sem); - } else { - down_write(&uts_sem); - r=_proc_do_string(which,table->maxlen,1,filp,buffer,lenp, ppos); - up_write(&uts_sem); - } - out: + void *which; + which = get_uts(table, write); + r = _proc_do_string(which, table->maxlen,write,filp,buffer,lenp, ppos); + put_uts(table, write, which); return r; } -#endif /* !CONFIG_UTS_NS */ static int do_proc_dointvec_conv(int *negp, unsigned long *lvalp, int *valp, @@ -2391,46 +2346,24 @@ int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp, } #ifdef CONFIG_SYSVIPC -static int proc_do_ipc_string(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp, loff_t *ppos) +static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) { - void *data; - struct ipc_namespace *ns; - - ns = current->nsproxy->ipc_ns; - - switch (table->ctl_name) { - case KERN_SHMMAX: - data = &ns->shm_ctlmax; - goto proc_minmax; - case KERN_SHMALL: - data = &ns->shm_ctlall; - goto proc_minmax; - case KERN_SHMMNI: - data = &ns->shm_ctlmni; - break; - case KERN_MSGMAX: - data = &ns->msg_ctlmax; - break; - case KERN_MSGMNI: - data = &ns->msg_ctlmni; - break; - case KERN_MSGMNB: - data = &ns->msg_ctlmnb; - break; - case KERN_SEM: - data = &ns->sem_ctls; - break; - default: - return -EINVAL; - } - - return __do_proc_dointvec(data, table, write, filp, buffer, + void *which; + which = get_ipc(table, write); + return __do_proc_dointvec(which, table, write, filp, buffer, lenp, ppos, NULL, NULL); -proc_minmax: - return __do_proc_doulongvec_minmax(data, table, write, filp, buffer, +} + +static int proc_ipc_doulongvec_minmax(ctl_table *table, int write, + struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos) +{ + void *which; + which = get_ipc(table, write); + return __do_proc_doulongvec_minmax(which, table, write, filp, buffer, lenp, ppos, 1l, 1l); } + #endif static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp, @@ -2674,6 +2607,64 @@ int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen, return 1; } + +/* The generic string strategy routine: */ +static int sysctl_uts_string(ctl_table *table, int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen, void **context) +{ + struct ctl_table uts_table; + int r, write; + write = newval && newlen; + memcpy(&uts_table, table, sizeof(uts_table)); + uts_table.data = get_uts(table, write); + r = sysctl_string(&uts_table, name, nlen, + oldval, oldlenp, newval, newlen, context); + put_uts(table, write, uts_table.data); + return r; +} + +#ifdef CONFIG_SYSVIPC +/* The generic sysctl ipc data routine. */ +static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen, void **context) +{ + size_t len; + void *data; + + /* Get out of I don't have a variable */ + if (!table->data || !table->maxlen) + return -ENOTDIR; + + data = get_ipc(table, 1); + if (!data) + return -ENOTDIR; + + if (oldval && oldlenp) { + if (get_user(len, oldlenp)) + return -EFAULT; + if (len) { + if (len > table->maxlen) + len = table->maxlen; + if (copy_to_user(oldval, data, len)) + return -EFAULT; + if (put_user(len, oldlenp)) + return -EFAULT; + } + } + + if (newval && newlen) { + if (newlen > table->maxlen) + newlen = table->maxlen; + + if (copy_from_user(data, newval, newlen)) + return -EFAULT; + } + return 1; +} +#endif + #else /* CONFIG_SYSCTL_SYSCALL */ @@ -2738,6 +2729,18 @@ int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen, return -ENOSYS; } +static int sysctl_uts_string(ctl_table *table, int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen, void **context) +{ + return -ENOSYS; +} +static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen, void **context) +{ + return -ENOSYS; +} #endif /* CONFIG_SYSCTL_SYSCALL */ /* diff --git a/lib/Kconfig b/lib/Kconfig index 734ce95a93d..47b172df3e3 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -4,6 +4,9 @@ menu "Library routines" +config BITREVERSE + tristate + config CRC_CCITT tristate "CRC-CCITT functions" help @@ -23,6 +26,7 @@ config CRC16 config CRC32 tristate "CRC32 functions" default y + select BITREVERSE help This option is provided for the case where no in-kernel-tree modules require CRC32 functions, but a module built outside the diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index b75fed737f2..6eccc643c32 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -285,7 +285,7 @@ config DEBUG_HIGHMEM config DEBUG_BUGVERBOSE bool "Verbose BUG() reporting (adds 70K)" if DEBUG_KERNEL && EMBEDDED depends on BUG - depends on ARM || ARM26 || AVR32 || M32R || M68K || SPARC32 || SPARC64 || X86_32 || FRV || SUPERH + depends on ARM || ARM26 || AVR32 || M32R || M68K || SPARC32 || SPARC64 || FRV || SUPERH || GENERIC_BUG default !EMBEDDED help Say Y here to make BUG() panics output the file name and line number @@ -413,3 +413,36 @@ config LKDTM Documentation on how to use the module can be found in drivers/misc/lkdtm.c + +config FAULT_INJECTION + bool "Fault-injection framework" + depends on DEBUG_KERNEL + depends on STACKTRACE + select FRAME_POINTER + help + Provide fault-injection framework. + For more details, see Documentation/fault-injection/. + +config FAILSLAB + bool "Fault-injection capability for kmalloc" + depends on FAULT_INJECTION + help + Provide fault-injection capability for kmalloc. + +config FAIL_PAGE_ALLOC + bool "Fault-injection capabilitiy for alloc_pages()" + depends on FAULT_INJECTION + help + Provide fault-injection capability for alloc_pages(). + +config FAIL_MAKE_REQUEST + bool "Fault-injection capabilitiy for disk IO" + depends on FAULT_INJECTION + help + Provide fault-injection capability for disk IO. + +config FAULT_INJECTION_DEBUG_FS + bool "Debugfs entries for fault-injection capabilities" + depends on FAULT_INJECTION && SYSFS && DEBUG_FS + help + Enable configuration of fault-injection capabilities via debugfs. diff --git a/lib/Makefile b/lib/Makefile index fea8f9035f0..2d6106af53c 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -35,6 +35,7 @@ ifneq ($(CONFIG_HAVE_DEC_LOCK),y) lib-y += dec_and_lock.o endif +obj-$(CONFIG_BITREVERSE) += bitrev.o obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o obj-$(CONFIG_CRC16) += crc16.o obj-$(CONFIG_CRC32) += crc32.o @@ -54,6 +55,9 @@ obj-$(CONFIG_SMP) += percpu_counter.o obj-$(CONFIG_AUDIT_GENERIC) += audit.o obj-$(CONFIG_SWIOTLB) += swiotlb.o +obj-$(CONFIG_FAULT_INJECTION) += fault-inject.o + +lib-$(CONFIG_GENERIC_BUG) += bug.o hostprogs-y := gen_crc32table clean-files := crc32table.h diff --git a/lib/bitrev.c b/lib/bitrev.c new file mode 100644 index 00000000000..f4e1c49c825 --- /dev/null +++ b/lib/bitrev.c @@ -0,0 +1,54 @@ +#include <linux/types.h> +#include <linux/module.h> +#include <linux/bitrev.h> + +const u8 byte_rev_table[256] = { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, +}; +EXPORT_SYMBOL_GPL(byte_rev_table); + +static __always_inline u16 bitrev16(u16 x) +{ + return (bitrev8(x & 0xff) << 8) | bitrev8(x >> 8); +} + +/** + * bitrev32 - reverse the order of bits in a u32 value + * @x: value to be bit-reversed + */ +u32 bitrev32(u32 x) +{ + return (bitrev16(x & 0xffff) << 16) | bitrev16(x >> 16); +} +EXPORT_SYMBOL(bitrev32); diff --git a/lib/bug.c b/lib/bug.c new file mode 100644 index 00000000000..014b582c5c4 --- /dev/null +++ b/lib/bug.c @@ -0,0 +1,163 @@ +/* + Generic support for BUG() + + This respects the following config options: + + CONFIG_BUG - emit BUG traps. Nothing happens without this. + CONFIG_GENERIC_BUG - enable this code. + CONFIG_DEBUG_BUGVERBOSE - emit full file+line information for each BUG + + CONFIG_BUG and CONFIG_DEBUG_BUGVERBOSE are potentially user-settable + (though they're generally always on). + + CONFIG_GENERIC_BUG is set by each architecture using this code. + + To use this, your architecture must: + + 1. Set up the config options: + - Enable CONFIG_GENERIC_BUG if CONFIG_BUG + + 2. Implement BUG (and optionally BUG_ON, WARN, WARN_ON) + - Define HAVE_ARCH_BUG + - Implement BUG() to generate a faulting instruction + - NOTE: struct bug_entry does not have "file" or "line" entries + when CONFIG_DEBUG_BUGVERBOSE is not enabled, so you must generate + the values accordingly. + + 3. Implement the trap + - In the illegal instruction trap handler (typically), verify + that the fault was in kernel mode, and call report_bug() + - report_bug() will return whether it was a false alarm, a warning, + or an actual bug. + - You must implement the is_valid_bugaddr(bugaddr) callback which + returns true if the eip is a real kernel address, and it points + to the expected BUG trap instruction. + + Jeremy Fitzhardinge <jeremy@goop.org> 2006 + */ +#include <linux/list.h> +#include <linux/module.h> +#include <linux/bug.h> + +extern const struct bug_entry __start___bug_table[], __stop___bug_table[]; + +#ifdef CONFIG_MODULES +static LIST_HEAD(module_bug_list); + +static const struct bug_entry *module_find_bug(unsigned long bugaddr) +{ + struct module *mod; + + list_for_each_entry(mod, &module_bug_list, bug_list) { + const struct bug_entry *bug = mod->bug_table; + unsigned i; + + for (i = 0; i < mod->num_bugs; ++i, ++bug) + if (bugaddr == bug->bug_addr) + return bug; + } + return NULL; +} + +int module_bug_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, + struct module *mod) +{ + char *secstrings; + unsigned int i; + + mod->bug_table = NULL; + mod->num_bugs = 0; + + /* Find the __bug_table section, if present */ + secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; + for (i = 1; i < hdr->e_shnum; i++) { + if (strcmp(secstrings+sechdrs[i].sh_name, "__bug_table")) + continue; + mod->bug_table = (void *) sechdrs[i].sh_addr; + mod->num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry); + break; + } + + /* + * Strictly speaking this should have a spinlock to protect against + * traversals, but since we only traverse on BUG()s, a spinlock + * could potentially lead to deadlock and thus be counter-productive. + */ + list_add(&mod->bug_list, &module_bug_list); + + return 0; +} + +void module_bug_cleanup(struct module *mod) +{ + list_del(&mod->bug_list); +} + +#else + +static inline const struct bug_entry *module_find_bug(unsigned long bugaddr) +{ + return NULL; +} +#endif + +const struct bug_entry *find_bug(unsigned long bugaddr) +{ + const struct bug_entry *bug; + + for (bug = __start___bug_table; bug < __stop___bug_table; ++bug) + if (bugaddr == bug->bug_addr) + return bug; + + return module_find_bug(bugaddr); +} + +enum bug_trap_type report_bug(unsigned long bugaddr) +{ + const struct bug_entry *bug; + const char *file; + unsigned line, warning; + + if (!is_valid_bugaddr(bugaddr)) + return BUG_TRAP_TYPE_NONE; + + bug = find_bug(bugaddr); + + printk(KERN_EMERG "------------[ cut here ]------------\n"); + + file = NULL; + line = 0; + warning = 0; + + if (bug) { +#ifdef CONFIG_DEBUG_BUGVERBOSE + file = bug->file; + line = bug->line; +#endif + warning = (bug->flags & BUGFLAG_WARNING) != 0; + } + + if (warning) { + /* this is a WARN_ON rather than BUG/BUG_ON */ + if (file) + printk(KERN_ERR "Badness at %s:%u\n", + file, line); + else + printk(KERN_ERR "Badness at %p " + "[verbose debug info unavailable]\n", + (void *)bugaddr); + + dump_stack(); + return BUG_TRAP_TYPE_WARN; + } + + if (file) + printk(KERN_CRIT "kernel BUG at %s:%u!\n", + file, line); + else + printk(KERN_CRIT "Kernel BUG at %p " + "[verbose debug info unavailable]\n", + (void *)bugaddr); + + return BUG_TRAP_TYPE_BUG; +} diff --git a/lib/crc32.c b/lib/crc32.c index 285fd9bc61b..bfc33314c72 100644 --- a/lib/crc32.c +++ b/lib/crc32.c @@ -235,23 +235,8 @@ u32 __attribute_pure__ crc32_be(u32 crc, unsigned char const *p, size_t len) } #endif -/** - * bitreverse - reverse the order of bits in a u32 value - * @x: value to be bit-reversed - */ -u32 bitreverse(u32 x) -{ - x = (x >> 16) | (x << 16); - x = (x >> 8 & 0x00ff00ff) | (x << 8 & 0xff00ff00); - x = (x >> 4 & 0x0f0f0f0f) | (x << 4 & 0xf0f0f0f0); - x = (x >> 2 & 0x33333333) | (x << 2 & 0xcccccccc); - x = (x >> 1 & 0x55555555) | (x << 1 & 0xaaaaaaaa); - return x; -} - EXPORT_SYMBOL(crc32_le); EXPORT_SYMBOL(crc32_be); -EXPORT_SYMBOL(bitreverse); /* * A brief CRC tutorial. @@ -400,10 +385,7 @@ buf_dump(char const *prefix, unsigned char const *buf, size_t len) static void bytereverse(unsigned char *buf, size_t len) { while (len--) { - unsigned char x = *buf; - x = (x >> 4) | (x << 4); - x = (x >> 2 & 0x33) | (x << 2 & 0xcc); - x = (x >> 1 & 0x55) | (x << 1 & 0xaa); + unsigned char x = bitrev8(*buf); *buf++ = x; } } @@ -460,11 +442,11 @@ static u32 test_step(u32 init, unsigned char *buf, size_t len) /* Now swap it around for the other test */ bytereverse(buf, len + 4); - init = bitreverse(init); - crc2 = bitreverse(crc1); - if (crc1 != bitreverse(crc2)) + init = bitrev32(init); + crc2 = bitrev32(crc1); + if (crc1 != bitrev32(crc2)) printf("\nBit reversal fail: 0x%08x -> 0x%08x -> 0x%08x\n", - crc1, crc2, bitreverse(crc2)); + crc1, crc2, bitrev32(crc2)); crc1 = crc32_le(init, buf, len); if (crc1 != crc2) printf("\nCRC endianness fail: 0x%08x != 0x%08x\n", crc1, diff --git a/lib/fault-inject.c b/lib/fault-inject.c new file mode 100644 index 00000000000..d143c0faf24 --- /dev/null +++ b/lib/fault-inject.c @@ -0,0 +1,336 @@ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/random.h> +#include <linux/stat.h> +#include <linux/types.h> +#include <linux/fs.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/unwind.h> +#include <linux/stacktrace.h> +#include <linux/kallsyms.h> +#include <linux/fault-inject.h> + +/* + * setup_fault_attr() is a helper function for various __setup handlers, so it + * returns 0 on error, because that is what __setup handlers do. + */ +int __init setup_fault_attr(struct fault_attr *attr, char *str) +{ + unsigned long probability; + unsigned long interval; + int times; + int space; + + /* "<interval>,<probability>,<space>,<times>" */ + if (sscanf(str, "%lu,%lu,%d,%d", + &interval, &probability, &space, ×) < 4) { + printk(KERN_WARNING + "FAULT_INJECTION: failed to parse arguments\n"); + return 0; + } + + attr->probability = probability; + attr->interval = interval; + atomic_set(&attr->times, times); + atomic_set(&attr->space, space); + + return 1; +} + +static void fail_dump(struct fault_attr *attr) +{ + if (attr->verbose > 0) + printk(KERN_NOTICE "FAULT_INJECTION: forcing a failure\n"); + if (attr->verbose > 1) + dump_stack(); +} + +#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0) + +static bool fail_task(struct fault_attr *attr, struct task_struct *task) +{ + return !in_interrupt() && task->make_it_fail; +} + +#define MAX_STACK_TRACE_DEPTH 32 + +#ifdef CONFIG_STACK_UNWIND + +static asmlinkage int fail_stacktrace_callback(struct unwind_frame_info *info, + void *arg) +{ + int depth; + struct fault_attr *attr = arg; + bool found = (attr->require_start == 0 && attr->require_end == ULONG_MAX); + + for (depth = 0; depth < attr->stacktrace_depth + && unwind(info) == 0 && UNW_PC(info); depth++) { + if (arch_unw_user_mode(info)) + break; + if (attr->reject_start <= UNW_PC(info) && + UNW_PC(info) < attr->reject_end) + return false; + if (attr->require_start <= UNW_PC(info) && + UNW_PC(info) < attr->require_end) + found = true; + } + return found; +} + +static bool fail_stacktrace(struct fault_attr *attr) +{ + struct unwind_frame_info info; + + return unwind_init_running(&info, fail_stacktrace_callback, attr); +} + +#elif defined(CONFIG_STACKTRACE) + +static bool fail_stacktrace(struct fault_attr *attr) +{ + struct stack_trace trace; + int depth = attr->stacktrace_depth; + unsigned long entries[MAX_STACK_TRACE_DEPTH]; + int n; + bool found = (attr->require_start == 0 && attr->require_end == ULONG_MAX); + + if (depth == 0) + return found; + + trace.nr_entries = 0; + trace.entries = entries; + trace.max_entries = depth; + trace.skip = 1; + trace.all_contexts = 0; + + save_stack_trace(&trace, NULL); + for (n = 0; n < trace.nr_entries; n++) { + if (attr->reject_start <= entries[n] && + entries[n] < attr->reject_end) + return false; + if (attr->require_start <= entries[n] && + entries[n] < attr->require_end) + found = true; + } + return found; +} + +#else + +static inline bool fail_stacktrace(struct fault_attr *attr) +{ + static bool firsttime = true; + + if (firsttime) { + printk(KERN_WARNING + "This architecture does not implement save_stack_trace()\n"); + firsttime = false; + } + return false; +} + +#endif + +/* + * This code is stolen from failmalloc-1.0 + * http://www.nongnu.org/failmalloc/ + */ + +bool should_fail(struct fault_attr *attr, ssize_t size) +{ + if (attr->task_filter && !fail_task(attr, current)) + return false; + + if (atomic_read(&attr->times) == 0) + return false; + + if (atomic_read(&attr->space) > size) { + atomic_sub(size, &attr->space); + return false; + } + + if (attr->interval > 1) { + attr->count++; + if (attr->count % attr->interval) + return false; + } + + if (attr->probability <= random32() % 100) + return false; + + if (!fail_stacktrace(attr)) + return false; + + fail_dump(attr); + + if (atomic_read(&attr->times) != -1) + atomic_dec_not_zero(&attr->times); + + return true; +} + +#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS + +static void debugfs_ul_set(void *data, u64 val) +{ + *(unsigned long *)data = val; +} + +static void debugfs_ul_set_MAX_STACK_TRACE_DEPTH(void *data, u64 val) +{ + *(unsigned long *)data = + val < MAX_STACK_TRACE_DEPTH ? + val : MAX_STACK_TRACE_DEPTH; +} + +static u64 debugfs_ul_get(void *data) +{ + return *(unsigned long *)data; +} + +DEFINE_SIMPLE_ATTRIBUTE(fops_ul, debugfs_ul_get, debugfs_ul_set, "%llu\n"); + +static struct dentry *debugfs_create_ul(const char *name, mode_t mode, + struct dentry *parent, unsigned long *value) +{ + return debugfs_create_file(name, mode, parent, value, &fops_ul); +} + +DEFINE_SIMPLE_ATTRIBUTE(fops_ul_MAX_STACK_TRACE_DEPTH, debugfs_ul_get, + debugfs_ul_set_MAX_STACK_TRACE_DEPTH, "%llu\n"); + +static struct dentry *debugfs_create_ul_MAX_STACK_TRACE_DEPTH( + const char *name, mode_t mode, + struct dentry *parent, unsigned long *value) +{ + return debugfs_create_file(name, mode, parent, value, + &fops_ul_MAX_STACK_TRACE_DEPTH); +} + +static void debugfs_atomic_t_set(void *data, u64 val) +{ + atomic_set((atomic_t *)data, val); +} + +static u64 debugfs_atomic_t_get(void *data) +{ + return atomic_read((atomic_t *)data); +} + +DEFINE_SIMPLE_ATTRIBUTE(fops_atomic_t, debugfs_atomic_t_get, + debugfs_atomic_t_set, "%lld\n"); + +static struct dentry *debugfs_create_atomic_t(const char *name, mode_t mode, + struct dentry *parent, atomic_t *value) +{ + return debugfs_create_file(name, mode, parent, value, &fops_atomic_t); +} + +void cleanup_fault_attr_dentries(struct fault_attr *attr) +{ + debugfs_remove(attr->dentries.probability_file); + attr->dentries.probability_file = NULL; + + debugfs_remove(attr->dentries.interval_file); + attr->dentries.interval_file = NULL; + + debugfs_remove(attr->dentries.times_file); + attr->dentries.times_file = NULL; + + debugfs_remove(attr->dentries.space_file); + attr->dentries.space_file = NULL; + + debugfs_remove(attr->dentries.verbose_file); + attr->dentries.verbose_file = NULL; + + debugfs_remove(attr->dentries.task_filter_file); + attr->dentries.task_filter_file = NULL; + + debugfs_remove(attr->dentries.stacktrace_depth_file); + attr->dentries.stacktrace_depth_file = NULL; + + debugfs_remove(attr->dentries.require_start_file); + attr->dentries.require_start_file = NULL; + + debugfs_remove(attr->dentries.require_end_file); + attr->dentries.require_end_file = NULL; + + debugfs_remove(attr->dentries.reject_start_file); + attr->dentries.reject_start_file = NULL; + + debugfs_remove(attr->dentries.reject_end_file); + attr->dentries.reject_end_file = NULL; + + if (attr->dentries.dir) + WARN_ON(!simple_empty(attr->dentries.dir)); + + debugfs_remove(attr->dentries.dir); + attr->dentries.dir = NULL; +} + +int init_fault_attr_dentries(struct fault_attr *attr, const char *name) +{ + mode_t mode = S_IFREG | S_IRUSR | S_IWUSR; + struct dentry *dir; + + memset(&attr->dentries, 0, sizeof(attr->dentries)); + + dir = debugfs_create_dir(name, NULL); + if (!dir) + goto fail; + attr->dentries.dir = dir; + + attr->dentries.probability_file = + debugfs_create_ul("probability", mode, dir, &attr->probability); + + attr->dentries.interval_file = + debugfs_create_ul("interval", mode, dir, &attr->interval); + + attr->dentries.times_file = + debugfs_create_atomic_t("times", mode, dir, &attr->times); + + attr->dentries.space_file = + debugfs_create_atomic_t("space", mode, dir, &attr->space); + + attr->dentries.verbose_file = + debugfs_create_ul("verbose", mode, dir, &attr->verbose); + + attr->dentries.task_filter_file = debugfs_create_bool("task-filter", + mode, dir, &attr->task_filter); + + attr->dentries.stacktrace_depth_file = + debugfs_create_ul_MAX_STACK_TRACE_DEPTH( + "stacktrace-depth", mode, dir, &attr->stacktrace_depth); + + attr->dentries.require_start_file = + debugfs_create_ul("require-start", mode, dir, &attr->require_start); + + attr->dentries.require_end_file = + debugfs_create_ul("require-end", mode, dir, &attr->require_end); + + attr->dentries.reject_start_file = + debugfs_create_ul("reject-start", mode, dir, &attr->reject_start); + + attr->dentries.reject_end_file = + debugfs_create_ul("reject-end", mode, dir, &attr->reject_end); + + + if (!attr->dentries.probability_file || !attr->dentries.interval_file + || !attr->dentries.times_file || !attr->dentries.space_file + || !attr->dentries.verbose_file || !attr->dentries.task_filter_file + || !attr->dentries.stacktrace_depth_file + || !attr->dentries.require_start_file + || !attr->dentries.require_end_file + || !attr->dentries.reject_start_file + || !attr->dentries.reject_end_file + ) + goto fail; + + return 0; +fail: + cleanup_fault_attr_dentries(attr); + return -ENOMEM; +} + +#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */ diff --git a/mm/fadvise.c b/mm/fadvise.c index 168c78a121b..0df4c899e97 100644 --- a/mm/fadvise.c +++ b/mm/fadvise.c @@ -38,7 +38,7 @@ asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice) if (!file) return -EBADF; - if (S_ISFIFO(file->f_dentry->d_inode->i_mode)) { + if (S_ISFIFO(file->f_path.dentry->d_inode->i_mode)) { ret = -ESPIPE; goto out; } diff --git a/mm/filemap.c b/mm/filemap.c index af7e2f5caea..606432f71b3 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2269,7 +2269,7 @@ __generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov, if (count == 0) goto out; - err = remove_suid(file->f_dentry); + err = remove_suid(file->f_path.dentry); if (err) goto out; diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c index b4fd0d7c9bf..8d667617f55 100644 --- a/mm/filemap_xip.c +++ b/mm/filemap_xip.c @@ -379,7 +379,7 @@ xip_file_write(struct file *filp, const char __user *buf, size_t len, if (count == 0) goto out_backing; - ret = remove_suid(filp->f_dentry); + ret = remove_suid(filp->f_path.dentry); if (ret) goto out_backing; diff --git a/mm/mempolicy.c b/mm/mempolicy.c index b917d6fdc1b..da946394655 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -1857,7 +1857,7 @@ int show_numa_map(struct seq_file *m, void *v) if (file) { seq_printf(m, " file="); - seq_path(m, file->f_vfsmnt, file->f_dentry, "\n\t= "); + seq_path(m, file->f_path.mnt, file->f_path.dentry, "\n\t= "); } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) { seq_printf(m, " heap"); } else if (vma->vm_start <= mm->start_stack && diff --git a/mm/mmap.c b/mm/mmap.c index 7be110e98d4..9717337293c 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -188,7 +188,7 @@ static void __remove_shared_vm_struct(struct vm_area_struct *vma, struct file *file, struct address_space *mapping) { if (vma->vm_flags & VM_DENYWRITE) - atomic_inc(&file->f_dentry->d_inode->i_writecount); + atomic_inc(&file->f_path.dentry->d_inode->i_writecount); if (vma->vm_flags & VM_SHARED) mapping->i_mmap_writable--; @@ -399,7 +399,7 @@ static inline void __vma_link_file(struct vm_area_struct *vma) struct address_space *mapping = file->f_mapping; if (vma->vm_flags & VM_DENYWRITE) - atomic_dec(&file->f_dentry->d_inode->i_writecount); + atomic_dec(&file->f_path.dentry->d_inode->i_writecount); if (vma->vm_flags & VM_SHARED) mapping->i_mmap_writable++; @@ -907,7 +907,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, * mounted, in which case we dont add PROT_EXEC.) */ if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC)) - if (!(file && (file->f_vfsmnt->mnt_flags & MNT_NOEXEC))) + if (!(file && (file->f_path.mnt->mnt_flags & MNT_NOEXEC))) prot |= PROT_EXEC; if (!len) @@ -960,7 +960,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, return -EAGAIN; } - inode = file ? file->f_dentry->d_inode : NULL; + inode = file ? file->f_path.dentry->d_inode : NULL; if (file) { switch (flags & MAP_TYPE) { @@ -989,7 +989,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, case MAP_PRIVATE: if (!(file->f_mode & FMODE_READ)) return -EACCES; - if (file->f_vfsmnt->mnt_flags & MNT_NOEXEC) { + if (file->f_path.mnt->mnt_flags & MNT_NOEXEC) { if (vm_flags & VM_EXEC) return -EPERM; vm_flags &= ~VM_MAYEXEC; diff --git a/mm/nommu.c b/mm/nommu.c index af874569d0f..23fb033e596 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -523,7 +523,7 @@ static int validate_mmap_request(struct file *file, */ mapping = file->f_mapping; if (!mapping) - mapping = file->f_dentry->d_inode->i_mapping; + mapping = file->f_path.dentry->d_inode->i_mapping; capabilities = 0; if (mapping && mapping->backing_dev_info) @@ -532,7 +532,7 @@ static int validate_mmap_request(struct file *file, if (!capabilities) { /* no explicit capabilities set, so assume some * defaults */ - switch (file->f_dentry->d_inode->i_mode & S_IFMT) { + switch (file->f_path.dentry->d_inode->i_mode & S_IFMT) { case S_IFREG: case S_IFBLK: capabilities = BDI_CAP_MAP_COPY; @@ -563,11 +563,11 @@ static int validate_mmap_request(struct file *file, !(file->f_mode & FMODE_WRITE)) return -EACCES; - if (IS_APPEND(file->f_dentry->d_inode) && + if (IS_APPEND(file->f_path.dentry->d_inode) && (file->f_mode & FMODE_WRITE)) return -EACCES; - if (locks_verify_locked(file->f_dentry->d_inode)) + if (locks_verify_locked(file->f_path.dentry->d_inode)) return -EAGAIN; if (!(capabilities & BDI_CAP_MAP_DIRECT)) @@ -598,7 +598,7 @@ static int validate_mmap_request(struct file *file, /* handle executable mappings and implied executable * mappings */ - if (file->f_vfsmnt->mnt_flags & MNT_NOEXEC) { + if (file->f_path.mnt->mnt_flags & MNT_NOEXEC) { if (prot & PROT_EXEC) return -EPERM; } @@ -833,7 +833,7 @@ unsigned long do_mmap_pgoff(struct file *file, continue; /* search for overlapping mappings on the same file */ - if (vma->vm_file->f_dentry->d_inode != file->f_dentry->d_inode) + if (vma->vm_file->f_path.dentry->d_inode != file->f_path.dentry->d_inode) continue; if (vma->vm_pgoff >= pgoff + pglen) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index cace22b3ac2..e6b17b2989e 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -40,6 +40,7 @@ #include <linux/sort.h> #include <linux/pfn.h> #include <linux/backing-dev.h> +#include <linux/fault-inject.h> #include <asm/tlbflush.h> #include <asm/div64.h> @@ -892,6 +893,91 @@ failed: #define ALLOC_HIGH 0x20 /* __GFP_HIGH set */ #define ALLOC_CPUSET 0x40 /* check for correct cpuset */ +#ifdef CONFIG_FAIL_PAGE_ALLOC + +static struct fail_page_alloc_attr { + struct fault_attr attr; + + u32 ignore_gfp_highmem; + u32 ignore_gfp_wait; + +#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS + + struct dentry *ignore_gfp_highmem_file; + struct dentry *ignore_gfp_wait_file; + +#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */ + +} fail_page_alloc = { + .attr = FAULT_ATTR_INITIALIZER, + .ignore_gfp_wait = 1, + .ignore_gfp_highmem = 1, +}; + +static int __init setup_fail_page_alloc(char *str) +{ + return setup_fault_attr(&fail_page_alloc.attr, str); +} +__setup("fail_page_alloc=", setup_fail_page_alloc); + +static int should_fail_alloc_page(gfp_t gfp_mask, unsigned int order) +{ + if (gfp_mask & __GFP_NOFAIL) + return 0; + if (fail_page_alloc.ignore_gfp_highmem && (gfp_mask & __GFP_HIGHMEM)) + return 0; + if (fail_page_alloc.ignore_gfp_wait && (gfp_mask & __GFP_WAIT)) + return 0; + + return should_fail(&fail_page_alloc.attr, 1 << order); +} + +#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS + +static int __init fail_page_alloc_debugfs(void) +{ + mode_t mode = S_IFREG | S_IRUSR | S_IWUSR; + struct dentry *dir; + int err; + + err = init_fault_attr_dentries(&fail_page_alloc.attr, + "fail_page_alloc"); + if (err) + return err; + dir = fail_page_alloc.attr.dentries.dir; + + fail_page_alloc.ignore_gfp_wait_file = + debugfs_create_bool("ignore-gfp-wait", mode, dir, + &fail_page_alloc.ignore_gfp_wait); + + fail_page_alloc.ignore_gfp_highmem_file = + debugfs_create_bool("ignore-gfp-highmem", mode, dir, + &fail_page_alloc.ignore_gfp_highmem); + + if (!fail_page_alloc.ignore_gfp_wait_file || + !fail_page_alloc.ignore_gfp_highmem_file) { + err = -ENOMEM; + debugfs_remove(fail_page_alloc.ignore_gfp_wait_file); + debugfs_remove(fail_page_alloc.ignore_gfp_highmem_file); + cleanup_fault_attr_dentries(&fail_page_alloc.attr); + } + + return err; +} + +late_initcall(fail_page_alloc_debugfs); + +#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */ + +#else /* CONFIG_FAIL_PAGE_ALLOC */ + +static inline int should_fail_alloc_page(gfp_t gfp_mask, unsigned int order) +{ + return 0; +} + +#endif /* CONFIG_FAIL_PAGE_ALLOC */ + /* * Return 1 if free pages are above 'mark'. This takes into account the order * of the allocation. @@ -1136,6 +1222,9 @@ __alloc_pages(gfp_t gfp_mask, unsigned int order, might_sleep_if(wait); + if (should_fail_alloc_page(gfp_mask, order)) + return NULL; + restart: z = zonelist->zones; /* the list of zones suitable for gfp_mask */ @@ -3244,7 +3333,7 @@ void *__init alloc_large_system_hash(const char *tablename, if (numentries > max) numentries = max; - log2qty = long_log2(numentries); + log2qty = ilog2(numentries); do { size = bucketsize << log2qty; @@ -3266,7 +3355,7 @@ void *__init alloc_large_system_hash(const char *tablename, printk("%s hash table entries: %d (order: %d, %lu bytes)\n", tablename, (1U << log2qty), - long_log2(size) - PAGE_SHIFT, + ilog2(size) - PAGE_SHIFT, size); if (_hash_shift) diff --git a/mm/readahead.c b/mm/readahead.c index a386f2b6b33..c0df5ed05f6 100644 --- a/mm/readahead.c +++ b/mm/readahead.c @@ -450,7 +450,7 @@ static int make_ahead_window(struct address_space *mapping, struct file *filp, * * Note that @filp is purely used for passing on to the ->readpage[s]() * handler: it may refer to a different file from @mapping (so we may not use - * @filp->f_mapping or @filp->f_dentry->d_inode here). + * @filp->f_mapping or @filp->f_path.dentry->d_inode here). * Also, @ra may not be equal to &@filp->f_ra. * */ diff --git a/mm/shmem.c b/mm/shmem.c index c820b4f77b8..4bb28d218eb 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1225,7 +1225,7 @@ failed: struct page *shmem_nopage(struct vm_area_struct *vma, unsigned long address, int *type) { - struct inode *inode = vma->vm_file->f_dentry->d_inode; + struct inode *inode = vma->vm_file->f_path.dentry->d_inode; struct page *page = NULL; unsigned long idx; int error; @@ -1248,7 +1248,7 @@ static int shmem_populate(struct vm_area_struct *vma, unsigned long addr, unsigned long len, pgprot_t prot, unsigned long pgoff, int nonblock) { - struct inode *inode = vma->vm_file->f_dentry->d_inode; + struct inode *inode = vma->vm_file->f_path.dentry->d_inode; struct mm_struct *mm = vma->vm_mm; enum sgp_type sgp = nonblock? SGP_QUICK: SGP_CACHE; unsigned long size; @@ -1293,14 +1293,14 @@ static int shmem_populate(struct vm_area_struct *vma, #ifdef CONFIG_NUMA int shmem_set_policy(struct vm_area_struct *vma, struct mempolicy *new) { - struct inode *i = vma->vm_file->f_dentry->d_inode; + struct inode *i = vma->vm_file->f_path.dentry->d_inode; return mpol_set_shared_policy(&SHMEM_I(i)->policy, vma, new); } struct mempolicy * shmem_get_policy(struct vm_area_struct *vma, unsigned long addr) { - struct inode *i = vma->vm_file->f_dentry->d_inode; + struct inode *i = vma->vm_file->f_path.dentry->d_inode; unsigned long idx; idx = ((addr - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; @@ -1310,7 +1310,7 @@ shmem_get_policy(struct vm_area_struct *vma, unsigned long addr) int shmem_lock(struct file *file, int lock, struct user_struct *user) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct shmem_inode_info *info = SHMEM_I(inode); int retval = -ENOMEM; @@ -1422,7 +1422,7 @@ shmem_prepare_write(struct file *file, struct page *page, unsigned offset, unsig static ssize_t shmem_file_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; loff_t pos; unsigned long written; ssize_t err; @@ -1442,7 +1442,7 @@ shmem_file_write(struct file *file, const char __user *buf, size_t count, loff_t if (err || !count) goto out; - err = remove_suid(file->f_dentry); + err = remove_suid(file->f_path.dentry); if (err) goto out; @@ -1524,7 +1524,7 @@ out: static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_t *desc, read_actor_t actor) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct address_space *mapping = inode->i_mapping; unsigned long index, offset; @@ -2493,8 +2493,8 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags) d_instantiate(dentry, inode); inode->i_size = size; inode->i_nlink = 0; /* It is unlinked */ - file->f_vfsmnt = mntget(shm_mnt); - file->f_dentry = dentry; + file->f_path.mnt = mntget(shm_mnt); + file->f_path.dentry = dentry; file->f_mapping = inode->i_mapping; file->f_op = &shmem_file_operations; file->f_mode = FMODE_WRITE | FMODE_READ; diff --git a/mm/slab.c b/mm/slab.c index 068cb4503c1..56af694c9e6 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -107,6 +107,7 @@ #include <linux/nodemask.h> #include <linux/mempolicy.h> #include <linux/mutex.h> +#include <linux/fault-inject.h> #include <linux/rtmutex.h> #include <asm/cacheflush.h> @@ -3088,12 +3089,89 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep, #define cache_alloc_debugcheck_after(a,b,objp,d) (objp) #endif +#ifdef CONFIG_FAILSLAB + +static struct failslab_attr { + + struct fault_attr attr; + + u32 ignore_gfp_wait; +#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS + struct dentry *ignore_gfp_wait_file; +#endif + +} failslab = { + .attr = FAULT_ATTR_INITIALIZER, + .ignore_gfp_wait = 1, +}; + +static int __init setup_failslab(char *str) +{ + return setup_fault_attr(&failslab.attr, str); +} +__setup("failslab=", setup_failslab); + +static int should_failslab(struct kmem_cache *cachep, gfp_t flags) +{ + if (cachep == &cache_cache) + return 0; + if (flags & __GFP_NOFAIL) + return 0; + if (failslab.ignore_gfp_wait && (flags & __GFP_WAIT)) + return 0; + + return should_fail(&failslab.attr, obj_size(cachep)); +} + +#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS + +static int __init failslab_debugfs(void) +{ + mode_t mode = S_IFREG | S_IRUSR | S_IWUSR; + struct dentry *dir; + int err; + + err = init_fault_attr_dentries(&failslab.attr, "failslab"); + if (err) + return err; + dir = failslab.attr.dentries.dir; + + failslab.ignore_gfp_wait_file = + debugfs_create_bool("ignore-gfp-wait", mode, dir, + &failslab.ignore_gfp_wait); + + if (!failslab.ignore_gfp_wait_file) { + err = -ENOMEM; + debugfs_remove(failslab.ignore_gfp_wait_file); + cleanup_fault_attr_dentries(&failslab.attr); + } + + return err; +} + +late_initcall(failslab_debugfs); + +#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */ + +#else /* CONFIG_FAILSLAB */ + +static inline int should_failslab(struct kmem_cache *cachep, gfp_t flags) +{ + return 0; +} + +#endif /* CONFIG_FAILSLAB */ + static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags) { void *objp; struct array_cache *ac; check_irq_off(); + + if (should_failslab(cachep, flags)) + return NULL; + ac = cpu_cache_get(cachep); if (likely(ac->avail)) { STATS_INC_ALLOCHIT(cachep); @@ -3182,7 +3260,7 @@ retry: for (z = zonelist->zones; *z && !obj; z++) { nid = zone_to_nid(*z); - if (cpuset_zone_allowed(*z, flags) && + if (cpuset_zone_allowed(*z, flags | __GFP_HARDWALL) && cache->nodelists[nid] && cache->nodelists[nid]->free_objects) obj = ____cache_alloc_node(cache, diff --git a/mm/swapfile.c b/mm/swapfile.c index c5431072f42..b9fc0e5de6d 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -1357,10 +1357,10 @@ static int swap_show(struct seq_file *swap, void *v) } file = ptr->swap_file; - len = seq_path(swap, file->f_vfsmnt, file->f_dentry, " \t\n\\"); + len = seq_path(swap, file->f_path.mnt, file->f_path.dentry, " \t\n\\"); seq_printf(swap, "%*s%s\t%u\t%u\t%d\n", len < 40 ? 40 - len : 1, " ", - S_ISBLK(file->f_dentry->d_inode->i_mode) ? + S_ISBLK(file->f_path.dentry->d_inode->i_mode) ? "partition" : "file\t", ptr->pages << (PAGE_SHIFT - 10), ptr->inuse_pages << (PAGE_SHIFT - 10), diff --git a/mm/tiny-shmem.c b/mm/tiny-shmem.c index 5f2cbf0f153..c7f6e1914bc 100644 --- a/mm/tiny-shmem.c +++ b/mm/tiny-shmem.c @@ -79,8 +79,8 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags) d_instantiate(dentry, inode); inode->i_nlink = 0; /* It is unlinked */ - file->f_vfsmnt = mntget(shm_mnt); - file->f_dentry = dentry; + file->f_path.mnt = mntget(shm_mnt); + file->f_path.dentry = dentry; file->f_mapping = inode->i_mapping; file->f_op = &ramfs_file_operations; file->f_mode = FMODE_WRITE | FMODE_READ; diff --git a/net/atm/proc.c b/net/atm/proc.c index 91fe5f53ff1..739866bfe9e 100644 --- a/net/atm/proc.c +++ b/net/atm/proc.c @@ -393,7 +393,7 @@ static ssize_t proc_dev_atm_read(struct file *file, char __user *buf, if (count == 0) return 0; page = get_zeroed_page(GFP_KERNEL); if (!page) return -ENOMEM; - dev = PDE(file->f_dentry->d_inode)->data; + dev = PDE(file->f_path.dentry->d_inode)->data; if (!dev->ops->proc_read) length = -EINVAL; else { diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index 1fb5d42f37a..e0e0d09023b 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -752,9 +752,9 @@ static int rfcomm_tty_ioctl(struct tty_struct *tty, struct file *filp, unsigned return -ENOIOCTLCMD; } -static void rfcomm_tty_set_termios(struct tty_struct *tty, struct termios *old) +static void rfcomm_tty_set_termios(struct tty_struct *tty, struct ktermios *old) { - struct termios *new = (struct termios *) tty->termios; + struct ktermios *new = tty->termios; int old_baud_rate = tty_termios_baud_rate(old); int new_baud_rate = tty_termios_baud_rate(new); diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 09836506223..fef56ae61ab 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -683,7 +683,7 @@ static ssize_t clusterip_proc_write(struct file *file, const char __user *input, { #define PROC_WRITELEN 10 char buffer[PROC_WRITELEN+1]; - struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode); struct clusterip_config *c = pde->data; unsigned long nodenum; diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c index 126db44e71a..4db0e73c56f 100644 --- a/net/ipv4/netfilter/ipt_recent.c +++ b/net/ipv4/netfilter/ipt_recent.c @@ -401,7 +401,7 @@ static int recent_seq_open(struct inode *inode, struct file *file) static ssize_t recent_proc_write(struct file *file, const char __user *input, size_t size, loff_t *loff) { - struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode); struct recent_table *t = pde->data; struct recent_entry *e; char buf[sizeof("+255.255.255.255")], *c = buf; diff --git a/net/irda/ircomm/ircomm_tty_ioctl.c b/net/irda/ircomm/ircomm_tty_ioctl.c index 197e3e7ed7e..75e39ea599d 100644 --- a/net/irda/ircomm/ircomm_tty_ioctl.c +++ b/net/irda/ircomm/ircomm_tty_ioctl.c @@ -146,7 +146,7 @@ static void ircomm_tty_change_speed(struct ircomm_tty_cb *self) * do something rational. */ void ircomm_tty_set_termios(struct tty_struct *tty, - struct termios *old_termios) + struct ktermios *old_termios) { struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; unsigned int cflag = tty->termios->c_cflag; diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 3baafb10f8f..276131fe56d 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -699,7 +699,7 @@ static struct sock *netlink_getsockbypid(struct sock *ssk, u32 pid) struct sock *netlink_getsockbyfilp(struct file *filp) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct sock *sock; if (!S_ISSOCK(inode->i_mode)) diff --git a/net/socket.c b/net/socket.c index 29ea1de43ec..4e396312f8d 100644 --- a/net/socket.c +++ b/net/socket.c @@ -362,20 +362,20 @@ static int sock_attach_fd(struct socket *sock, struct file *file) this.name = name; this.hash = 0; - file->f_dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this); - if (unlikely(!file->f_dentry)) + file->f_path.dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this); + if (unlikely(!file->f_path.dentry)) return -ENOMEM; - file->f_dentry->d_op = &sockfs_dentry_operations; + file->f_path.dentry->d_op = &sockfs_dentry_operations; /* * We dont want to push this dentry into global dentry hash table. * We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED * This permits a working /proc/$pid/fd/XXX on sockets */ - file->f_dentry->d_flags &= ~DCACHE_UNHASHED; - d_instantiate(file->f_dentry, SOCK_INODE(sock)); - file->f_vfsmnt = mntget(sock_mnt); - file->f_mapping = file->f_dentry->d_inode->i_mapping; + file->f_path.dentry->d_flags &= ~DCACHE_UNHASHED; + d_instantiate(file->f_path.dentry, SOCK_INODE(sock)); + file->f_path.mnt = mntget(sock_mnt); + file->f_mapping = file->f_path.dentry->d_inode->i_mapping; sock->file = file; file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops; @@ -413,7 +413,7 @@ static struct socket *sock_from_file(struct file *file, int *err) if (file->f_op == &socket_file_ops) return file->private_data; /* set in sock_map_fd */ - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; if (!S_ISSOCK(inode->i_mode)) { *err = -ENOTSOCK; return NULL; diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index a02ecc1f230..e1a104abb78 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -501,7 +501,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) if (!buf) goto out; - clnt = RPC_I(filp->f_dentry->d_inode)->private; + clnt = RPC_I(filp->f_path.dentry->d_inode)->private; err = -EFAULT; if (copy_from_user(buf, src, mlen)) goto err; diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index d96fd466a9a..80aff047457 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -670,7 +670,7 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { struct cache_reader *rp = filp->private_data; struct cache_request *rq; - struct cache_detail *cd = PDE(filp->f_dentry->d_inode)->data; + struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data; int err; if (count == 0) @@ -747,7 +747,7 @@ cache_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos) { int err; - struct cache_detail *cd = PDE(filp->f_dentry->d_inode)->data; + struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data; if (count == 0) return 0; @@ -778,7 +778,7 @@ cache_poll(struct file *filp, poll_table *wait) unsigned int mask; struct cache_reader *rp = filp->private_data; struct cache_queue *cq; - struct cache_detail *cd = PDE(filp->f_dentry->d_inode)->data; + struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data; poll_wait(filp, &queue_wait, wait); @@ -1254,7 +1254,7 @@ static struct file_operations content_file_operations = { static ssize_t read_flush(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct cache_detail *cd = PDE(file->f_dentry->d_inode)->data; + struct cache_detail *cd = PDE(file->f_path.dentry->d_inode)->data; char tbuf[20]; unsigned long p = *ppos; int len; @@ -1275,7 +1275,7 @@ static ssize_t read_flush(struct file *file, char __user *buf, static ssize_t write_flush(struct file * file, const char __user * buf, size_t count, loff_t *ppos) { - struct cache_detail *cd = PDE(file->f_dentry->d_inode)->data; + struct cache_detail *cd = PDE(file->f_path.dentry->d_inode)->data; char tbuf[20]; char *ep; long flushtime; diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 19703aa9659..89273d35e0c 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -214,7 +214,7 @@ out: static ssize_t rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct rpc_inode *rpci = RPC_I(inode); struct rpc_pipe_msg *msg; int res = 0; @@ -257,7 +257,7 @@ out_unlock: static ssize_t rpc_pipe_write(struct file *filp, const char __user *buf, size_t len, loff_t *offset) { - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct rpc_inode *rpci = RPC_I(inode); int res; @@ -275,7 +275,7 @@ rpc_pipe_poll(struct file *filp, struct poll_table_struct *wait) struct rpc_inode *rpci; unsigned int mask = 0; - rpci = RPC_I(filp->f_dentry->d_inode); + rpci = RPC_I(filp->f_path.dentry->d_inode); poll_wait(filp, &rpci->waitq, wait); mask = POLLOUT | POLLWRNORM; @@ -290,7 +290,7 @@ static int rpc_pipe_ioctl(struct inode *ino, struct file *filp, unsigned int cmd, unsigned long arg) { - struct rpc_inode *rpci = RPC_I(filp->f_dentry->d_inode); + struct rpc_inode *rpci = RPC_I(filp->f_path.dentry->d_inode); int len; switch (cmd) { diff --git a/net/unix/garbage.c b/net/unix/garbage.c index 746c2f4a5fa..f14ad6635fc 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c @@ -96,7 +96,7 @@ atomic_t unix_tot_inflight = ATOMIC_INIT(0); static struct sock *unix_get_socket(struct file *filp) { struct sock *u_sock = NULL; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; /* * Socket ? diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index f359b730c2c..8b809b264d1 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -265,7 +265,7 @@ static void write_src(void) printf("#define ALGN .align 4\n"); printf("#endif\n"); - printf(".data\n"); + printf("\t.section .rodata, \"a\"\n"); /* Provide proper symbols relocatability by their '_text' * relativeness. The symbol names cannot be used to construct diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 44e9cd47054..3753416eb9b 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1120,8 +1120,8 @@ static int file_has_perm(struct task_struct *tsk, { struct task_security_struct *tsec = tsk->security; struct file_security_struct *fsec = file->f_security; - struct vfsmount *mnt = file->f_vfsmnt; - struct dentry *dentry = file->f_dentry; + struct vfsmount *mnt = file->f_path.mnt; + struct dentry *dentry = file->f_path.dentry; struct inode *inode = dentry->d_inode; struct avc_audit_data ad; int rc; @@ -1581,7 +1581,7 @@ static int selinux_bprm_alloc_security(struct linux_binprm *bprm) static int selinux_bprm_set_security(struct linux_binprm *bprm) { struct task_security_struct *tsec; - struct inode *inode = bprm->file->f_dentry->d_inode; + struct inode *inode = bprm->file->f_path.dentry->d_inode; struct inode_security_struct *isec; struct bprm_security_struct *bsec; u32 newsid; @@ -1621,10 +1621,10 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm) } AVC_AUDIT_DATA_INIT(&ad, FS); - ad.u.fs.mnt = bprm->file->f_vfsmnt; - ad.u.fs.dentry = bprm->file->f_dentry; + ad.u.fs.mnt = bprm->file->f_path.mnt; + ad.u.fs.dentry = bprm->file->f_path.dentry; - if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) + if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) newsid = tsec->sid; if (tsec->sid == newsid) { @@ -1695,9 +1695,10 @@ static inline void flush_unauthorized_files(struct files_struct * files) struct tty_struct *tty; struct fdtable *fdt; long j = -1; + int drop_tty = 0; mutex_lock(&tty_mutex); - tty = current->signal->tty; + tty = get_current_tty(); if (tty) { file_list_lock(); file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list); @@ -1707,15 +1708,17 @@ static inline void flush_unauthorized_files(struct files_struct * files) than using file_has_perm, as this particular open file may belong to another process and we are only interested in the inode-based check here. */ - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; if (inode_has_perm(current, inode, FILE__READ | FILE__WRITE, NULL)) { - /* Reset controlling tty. */ - current->signal->tty = NULL; - current->signal->tty_old_pgrp = 0; + drop_tty = 1; } } file_list_unlock(); + + /* Reset controlling tty. */ + if (drop_tty) + proc_set_tty(current, NULL); } mutex_unlock(&tty_mutex); @@ -2417,7 +2420,7 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t static int selinux_file_permission(struct file *file, int mask) { int rc; - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; if (!mask) { /* No permission to check. Existence test. */ @@ -2594,7 +2597,7 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd, switch (cmd) { case F_SETFL: - if (!file->f_dentry || !file->f_dentry->d_inode) { + if (!file->f_path.dentry || !file->f_path.dentry->d_inode) { err = -EINVAL; break; } @@ -2620,7 +2623,7 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd, case F_SETLK64: case F_SETLKW64: #endif - if (!file->f_dentry || !file->f_dentry->d_inode) { + if (!file->f_path.dentry || !file->f_path.dentry->d_inode) { err = -EINVAL; break; } diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index cd244419c98..c8bf6e172f6 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -448,7 +448,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = { static ssize_t selinux_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos) { - ino_t ino = file->f_dentry->d_inode->i_ino; + ino_t ino = file->f_path.dentry->d_inode->i_ino; char *data; ssize_t rv; @@ -805,7 +805,7 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf, goto out; } - inode = filep->f_dentry->d_inode; + inode = filep->f_path.dentry->d_inode; cur_enforcing = security_get_bool_value(inode->i_ino - BOOL_INO_OFFSET); if (cur_enforcing < 0) { ret = cur_enforcing; @@ -864,7 +864,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, if (new_value) new_value = 1; - inode = filep->f_dentry->d_inode; + inode = filep->f_path.dentry->d_inode; bool_pending_values[inode->i_ino - BOOL_INO_OFFSET] = new_value; length = count; @@ -965,7 +965,7 @@ static void sel_remove_bools(struct dentry *de) file_list_lock(); list_for_each(p, &sb->s_files) { struct file * filp = list_entry(p, struct file, f_u.fu_list); - struct dentry * dentry = filp->f_dentry; + struct dentry * dentry = filp->f_path.dentry; if (dentry->d_parent != de) { continue; diff --git a/sound/core/info.c b/sound/core/info.c index 0b4aab3225e..54591e2eb6e 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -488,7 +488,7 @@ static long snd_info_entry_ioctl(struct file *file, unsigned int cmd, static int snd_info_entry_mmap(struct file *file, struct vm_area_struct *vma) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct snd_info_private_data *data; struct snd_info_entry *entry; diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 6ea67b16c67..b52e89393fa 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1604,7 +1604,7 @@ static struct file *snd_pcm_file_fd(int fd) file = fget(fd); if (!file) return NULL; - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; if (!S_ISCHR(inode->i_mode) || imajor(inode) != snd_major) { fput(file); diff --git a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c index 87bd3100aef..80b836e80d9 100644 --- a/sound/oss/dmasound/dmasound_core.c +++ b/sound/oss/dmasound/dmasound_core.c @@ -1051,7 +1051,7 @@ static int sq_release(struct inode *inode, struct file *file) if (file->f_mode & FMODE_WRITE) { if (write_sq.busy) - rc = sq_fsync(file, file->f_dentry); + rc = sq_fsync(file, file->f_path.dentry); sq_reset_output() ; /* make sure dma is stopped and all is quiet */ write_sq_release_buffers(); @@ -1217,7 +1217,7 @@ static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd, if ((file->f_mode & FMODE_READ) && dmasound.mach.record) sq_reset_input() ; if (file->f_mode & FMODE_WRITE) { - result = sq_fsync(file, file->f_dentry); + result = sq_fsync(file, file->f_path.dentry); sq_reset_output() ; } /* if we are the shared resource owner then release them */ diff --git a/sound/oss/msnd_pinnacle.c b/sound/oss/msnd_pinnacle.c index d5146790f5e..24110d63b13 100644 --- a/sound/oss/msnd_pinnacle.c +++ b/sound/oss/msnd_pinnacle.c @@ -1007,7 +1007,7 @@ static int dsp_write(const char __user *buf, size_t len) static ssize_t dev_read(struct file *file, char __user *buf, size_t count, loff_t *off) { - int minor = iminor(file->f_dentry->d_inode); + int minor = iminor(file->f_path.dentry->d_inode); if (minor == dev.dsp_minor) return dsp_read(buf, count); else @@ -1016,7 +1016,7 @@ static ssize_t dev_read(struct file *file, char __user *buf, size_t count, loff_ static ssize_t dev_write(struct file *file, const char __user *buf, size_t count, loff_t *off) { - int minor = iminor(file->f_dentry->d_inode); + int minor = iminor(file->f_path.dentry->d_inode); if (minor == dev.dsp_minor) return dsp_write(buf, count); else diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c index 8fb8e7f9955..a89108cb74e 100644 --- a/sound/oss/soundcard.c +++ b/sound/oss/soundcard.c @@ -141,7 +141,7 @@ static int get_mixer_levels(void __user * arg) static ssize_t sound_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - int dev = iminor(file->f_dentry->d_inode); + int dev = iminor(file->f_path.dentry->d_inode); int ret = -EINVAL; /* @@ -174,7 +174,7 @@ static ssize_t sound_read(struct file *file, char __user *buf, size_t count, lof static ssize_t sound_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - int dev = iminor(file->f_dentry->d_inode); + int dev = iminor(file->f_path.dentry->d_inode); int ret = -EINVAL; lock_kernel(); @@ -393,7 +393,7 @@ static int sound_ioctl(struct inode *inode, struct file *file, static unsigned int sound_poll(struct file *file, poll_table * wait) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int dev = iminor(inode); DEB(printk("sound_poll(dev=%d)\n", dev)); @@ -418,7 +418,7 @@ static int sound_mmap(struct file *file, struct vm_area_struct *vma) int dev_class; unsigned long size; struct dma_buffparms *dmap = NULL; - int dev = iminor(file->f_dentry->d_inode); + int dev = iminor(file->f_path.dentry->d_inode); dev_class = dev & 0x0f; dev >>= 4; diff --git a/sound/sound_firmware.c b/sound/sound_firmware.c index 3a181d4c0dc..3304344713a 100644 --- a/sound/sound_firmware.c +++ b/sound/sound_firmware.c @@ -19,7 +19,7 @@ static int do_mod_firmware_load(const char *fn, char **fp) printk(KERN_INFO "Unable to load '%s'.\n", fn); return 0; } - l = filp->f_dentry->d_inode->i_size; + l = filp->f_path.dentry->d_inode->i_size; if (l <= 0 || l > 131072) { printk(KERN_INFO "Invalid firmware '%s'\n", fn); |