Merge tags 'omap-devel-gpmc-fixed-for-v3.7' and 'cleanup-omap-tags-for-v3.7' into cleanup-sparseirq
Changes for GPMC (General Purpose Memory Controller) that take it
closer for being just a regular device driver.
Remove the ancient omap specific atags that are no longer needed.
At some point we were planning to pass the bootloader information
with custom atags that did not work out too well.
There's no need for these any longer as the kernel has been booting
fine without them for quite some time. And Now we have device tree
support that can be used instead.
diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci
index 34f5110..dff1f48 100644
--- a/Documentation/ABI/testing/sysfs-bus-pci
+++ b/Documentation/ABI/testing/sysfs-bus-pci
@@ -210,3 +210,15 @@
firmware assigned instance number of the PCI
device that can help in understanding the firmware
intended order of the PCI device.
+
+What: /sys/bus/pci/devices/.../d3cold_allowed
+Date: July 2012
+Contact: Huang Ying <ying.huang@intel.com>
+Description:
+ d3cold_allowed is bit to control whether the corresponding PCI
+ device can be put into D3Cold state. If it is cleared, the
+ device will never be put into D3Cold state. If it is set, the
+ device may be put into D3Cold state if other requirements are
+ satisfied too. Reading this attribute will show the current
+ value of d3cold_allowed bit. Writing this attribute will set
+ the value of d3cold_allowed bit.
diff --git a/Documentation/ABI/testing/sysfs-tty b/Documentation/ABI/testing/sysfs-tty
index b138b66..0c43015 100644
--- a/Documentation/ABI/testing/sysfs-tty
+++ b/Documentation/ABI/testing/sysfs-tty
@@ -17,3 +17,12 @@
device, like 'tty1'.
The file supports poll() to detect virtual
console switches.
+
+What: /sys/class/tty/ttyS0/uartclk
+Date: Sep 2012
+Contact: Tomas Hlavacek <tmshlvck@gmail.com>
+Description:
+ Shows the current uartclk value associated with the
+ UART port in serial_core, that is bound to TTY like ttyS0.
+ uartclk = 16 * baud_base
+
diff --git a/Documentation/block/00-INDEX b/Documentation/block/00-INDEX
index d111e3b..d18ecd8 100644
--- a/Documentation/block/00-INDEX
+++ b/Documentation/block/00-INDEX
@@ -3,15 +3,21 @@
biodoc.txt
- Notes on the Generic Block Layer Rewrite in Linux 2.5
capability.txt
- - Generic Block Device Capability (/sys/block/<disk>/capability)
+ - Generic Block Device Capability (/sys/block/<device>/capability)
+cfq-iosched.txt
+ - CFQ IO scheduler tunables
+data-integrity.txt
+ - Block data integrity
deadline-iosched.txt
- Deadline IO scheduler tunables
ioprio.txt
- Block io priorities (in CFQ scheduler)
+queue-sysfs.txt
+ - Queue's sysfs entries
request.txt
- The members of struct request (in include/linux/blkdev.h)
stat.txt
- - Block layer statistics in /sys/block/<dev>/stat
+ - Block layer statistics in /sys/block/<device>/stat
switching-sched.txt
- Switching I/O schedulers at runtime
writeback_cache_control.txt
diff --git a/Documentation/block/cfq-iosched.txt b/Documentation/block/cfq-iosched.txt
index 6d670f5..d89b4fe 100644
--- a/Documentation/block/cfq-iosched.txt
+++ b/Documentation/block/cfq-iosched.txt
@@ -1,3 +1,14 @@
+CFQ (Complete Fairness Queueing)
+===============================
+
+The main aim of CFQ scheduler is to provide a fair allocation of the disk
+I/O bandwidth for all the processes which requests an I/O operation.
+
+CFQ maintains the per process queue for the processes which request I/O
+operation(syncronous requests). In case of asynchronous requests, all the
+requests from all the processes are batched together according to their
+process's I/O priority.
+
CFQ ioscheduler tunables
========================
@@ -25,6 +36,72 @@
controller or for storage arrays), setting slice_idle=0 might end up in better
throughput and acceptable latencies.
+back_seek_max
+-------------
+This specifies, given in Kbytes, the maximum "distance" for backward seeking.
+The distance is the amount of space from the current head location to the
+sectors that are backward in terms of distance.
+
+This parameter allows the scheduler to anticipate requests in the "backward"
+direction and consider them as being the "next" if they are within this
+distance from the current head location.
+
+back_seek_penalty
+-----------------
+This parameter is used to compute the cost of backward seeking. If the
+backward distance of request is just 1/back_seek_penalty from a "front"
+request, then the seeking cost of two requests is considered equivalent.
+
+So scheduler will not bias toward one or the other request (otherwise scheduler
+will bias toward front request). Default value of back_seek_penalty is 2.
+
+fifo_expire_async
+-----------------
+This parameter is used to set the timeout of asynchronous requests. Default
+value of this is 248ms.
+
+fifo_expire_sync
+----------------
+This parameter is used to set the timeout of synchronous requests. Default
+value of this is 124ms. In case to favor synchronous requests over asynchronous
+one, this value should be decreased relative to fifo_expire_async.
+
+slice_async
+-----------
+This parameter is same as of slice_sync but for asynchronous queue. The
+default value is 40ms.
+
+slice_async_rq
+--------------
+This parameter is used to limit the dispatching of asynchronous request to
+device request queue in queue's slice time. The maximum number of request that
+are allowed to be dispatched also depends upon the io priority. Default value
+for this is 2.
+
+slice_sync
+----------
+When a queue is selected for execution, the queues IO requests are only
+executed for a certain amount of time(time_slice) before switching to another
+queue. This parameter is used to calculate the time slice of synchronous
+queue.
+
+time_slice is computed using the below equation:-
+time_slice = slice_sync + (slice_sync/5 * (4 - prio)). To increase the
+time_slice of synchronous queue, increase the value of slice_sync. Default
+value is 100ms.
+
+quantum
+-------
+This specifies the number of request dispatched to the device queue. In a
+queue's time slice, a request will not be dispatched if the number of request
+in the device exceeds this parameter. This parameter is used for synchronous
+request.
+
+In case of storage with several disk, this setting can limit the parallel
+processing of request. Therefore, increasing the value can imporve the
+performace although this can cause the latency of some I/O to increase due
+to more number of requests.
+
CFQ IOPS Mode for group scheduling
===================================
Basic CFQ design is to provide priority based time slices. Higher priority
diff --git a/Documentation/block/queue-sysfs.txt b/Documentation/block/queue-sysfs.txt
index 6518a55..e54ac1d 100644
--- a/Documentation/block/queue-sysfs.txt
+++ b/Documentation/block/queue-sysfs.txt
@@ -9,20 +9,71 @@
Files denoted with a RO postfix are readonly and the RW postfix means
read-write.
+add_random (RW)
+----------------
+This file allows to trun off the disk entropy contribution. Default
+value of this file is '1'(on).
+
+discard_granularity (RO)
+-----------------------
+This shows the size of internal allocation of the device in bytes, if
+reported by the device. A value of '0' means device does not support
+the discard functionality.
+
+discard_max_bytes (RO)
+----------------------
+Devices that support discard functionality may have internal limits on
+the number of bytes that can be trimmed or unmapped in a single operation.
+The discard_max_bytes parameter is set by the device driver to the maximum
+number of bytes that can be discarded in a single operation. Discard
+requests issued to the device must not exceed this limit. A discard_max_bytes
+value of 0 means that the device does not support discard functionality.
+
+discard_zeroes_data (RO)
+------------------------
+When read, this file will show if the discarded block are zeroed by the
+device or not. If its value is '1' the blocks are zeroed otherwise not.
+
hw_sector_size (RO)
-------------------
This is the hardware sector size of the device, in bytes.
+iostats (RW)
+-------------
+This file is used to control (on/off) the iostats accounting of the
+disk.
+
+logical_block_size (RO)
+-----------------------
+This is the logcal block size of the device, in bytes.
+
max_hw_sectors_kb (RO)
----------------------
This is the maximum number of kilobytes supported in a single data transfer.
+max_integrity_segments (RO)
+---------------------------
+When read, this file shows the max limit of integrity segments as
+set by block layer which a hardware controller can handle.
+
max_sectors_kb (RW)
-------------------
This is the maximum number of kilobytes that the block layer will allow
for a filesystem request. Must be smaller than or equal to the maximum
size allowed by the hardware.
+max_segments (RO)
+-----------------
+Maximum number of segments of the device.
+
+max_segment_size (RO)
+---------------------
+Maximum segment size of the device.
+
+minimum_io_size (RO)
+--------------------
+This is the smallest preferred io size reported by the device.
+
nomerges (RW)
-------------
This enables the user to disable the lookup logic involved with IO
@@ -45,11 +96,24 @@
each request queue may have upto N request pools, each independently
regulated by nr_requests.
+optimal_io_size (RO)
+--------------------
+This is the optimal io size reported by the device.
+
+physical_block_size (RO)
+------------------------
+This is the physical block size of device, in bytes.
+
read_ahead_kb (RW)
------------------
Maximum number of kilobytes to read-ahead for filesystems on this block
device.
+rotational (RW)
+---------------
+This file is used to stat if the device is of rotational type or
+non-rotational type.
+
rq_affinity (RW)
----------------
If this option is '1', the block layer will migrate request completions to the
diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
index 70cd49b..1dd6225 100644
--- a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
+++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
@@ -10,8 +10,8 @@
- compatible : Should be "fsl,<chip>-esdhc"
Optional properties:
-- fsl,cd-internal : Indicate to use controller internal card detection
-- fsl,wp-internal : Indicate to use controller internal write protection
+- fsl,cd-controller : Indicate to use controller internal card detection
+- fsl,wp-controller : Indicate to use controller internal write protection
Examples:
@@ -19,8 +19,8 @@
compatible = "fsl,imx51-esdhc";
reg = <0x70004000 0x4000>;
interrupts = <1>;
- fsl,cd-internal;
- fsl,wp-internal;
+ fsl,cd-controller;
+ fsl,wp-controller;
};
esdhc@70008000 {
diff --git a/Documentation/devicetree/bindings/tty/serial/nxp-lpc32xx-hsuart.txt b/Documentation/devicetree/bindings/tty/serial/nxp-lpc32xx-hsuart.txt
new file mode 100644
index 0000000..0d439df
--- /dev/null
+++ b/Documentation/devicetree/bindings/tty/serial/nxp-lpc32xx-hsuart.txt
@@ -0,0 +1,14 @@
+* NXP LPC32xx SoC High Speed UART
+
+Required properties:
+- compatible: Should be "nxp,lpc3220-hsuart"
+- reg: Should contain registers location and length
+- interrupts: Should contain interrupt
+
+Example:
+
+ uart1: serial@40014000 {
+ compatible = "nxp,lpc3220-hsuart";
+ reg = <0x40014000 0x1000>;
+ interrupts = <26 0>;
+ };
diff --git a/Documentation/devicetree/bindings/tty/serial/of-serial.txt b/Documentation/devicetree/bindings/tty/serial/of-serial.txt
index 0847fde..ba385f2 100644
--- a/Documentation/devicetree/bindings/tty/serial/of-serial.txt
+++ b/Documentation/devicetree/bindings/tty/serial/of-serial.txt
@@ -25,6 +25,8 @@
accesses to the UART (e.g. TI davinci).
- used-by-rtas : set to indicate that the port is in use by the OpenFirmware
RTAS and should not be registered.
+- no-loopback-test: set to indicate that the port does not implements loopback
+ test mode
Example:
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index afaff31..f4d8c71 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -579,7 +579,7 @@
----------------------------
What: at91-mci driver ("CONFIG_MMC_AT91")
-When: 3.7
+When: 3.8
Why: There are two mci drivers: at91-mci and atmel-mci. The PDC support
was added to atmel-mci as a first step to support more chips.
Then at91-mci was kept only for old IP versions (on at91rm9200 and
diff --git a/Documentation/serial/00-INDEX b/Documentation/serial/00-INDEX
index e09468a..f7b0c7d 100644
--- a/Documentation/serial/00-INDEX
+++ b/Documentation/serial/00-INDEX
@@ -2,8 +2,6 @@
- this file.
README.cycladesZ
- info on Cyclades-Z firmware loading.
-computone.txt
- - info on Computone Intelliport II/Plus Multiport Serial Driver.
digiepca.txt
- info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards.
hayes-esp.txt
diff --git a/Documentation/serial/computone.txt b/Documentation/serial/computone.txt
deleted file mode 100644
index a6a1158..0000000
--- a/Documentation/serial/computone.txt
+++ /dev/null
@@ -1,520 +0,0 @@
-NOTE: This is an unmaintained driver. It is not guaranteed to work due to
-changes made in the tty layer in 2.6. If you wish to take over maintenance of
-this driver, contact Michael Warfield <mhw@wittsend.com>.
-
-Changelog:
-----------
-11-01-2001: Original Document
-
-10-29-2004: Minor misspelling & format fix, update status of driver.
- James Nelson <james4765@gmail.com>
-
-Computone Intelliport II/Plus Multiport Serial Driver
------------------------------------------------------
-
-Release Notes For Linux Kernel 2.2 and higher.
-These notes are for the drivers which have already been integrated into the
-kernel and have been tested on Linux kernels 2.0, 2.2, 2.3, and 2.4.
-
-Version: 1.2.14
-Date: 11/01/2001
-Historical Author: Andrew Manison <amanison@america.net>
-Primary Author: Doug McNash
-
-This file assumes that you are using the Computone drivers which are
-integrated into the kernel sources. For updating the drivers or installing
-drivers into kernels which do not already have Computone drivers, please
-refer to the instructions in the README.computone file in the driver patch.
-
-
-1. INTRODUCTION
-
-This driver supports the entire family of Intelliport II/Plus controllers
-with the exception of the MicroChannel controllers. It does not support
-products previous to the Intelliport II.
-
-This driver was developed on the v2.0.x Linux tree and has been tested up
-to v2.4.14; it will probably not work with earlier v1.X kernels,.
-
-
-2. QUICK INSTALLATION
-
-Hardware - If you have an ISA card, find a free interrupt and io port.
- List those in use with `cat /proc/interrupts` and
- `cat /proc/ioports`. Set the card dip switches to a free
- address. You may need to configure your BIOS to reserve an
- irq for an ISA card. PCI and EISA parameters are set
- automagically. Insert card into computer with the power off
- before or after drivers installation.
-
- Note the hardware address from the Computone ISA cards installed into
- the system. These are required for editing ip2.c or editing
- /etc/modprobe.d/*.conf, or for specification on the modprobe
- command line.
-
- Note that the /etc/modules.conf should be used for older (pre-2.6)
- kernels.
-
-Software -
-
-Module installation:
-
-a) Determine free irq/address to use if any (configure BIOS if need be)
-b) Run "make config" or "make menuconfig" or "make xconfig"
- Select (m) module for CONFIG_COMPUTONE under character
- devices. CONFIG_PCI and CONFIG_MODULES also may need to be set.
-c) Set address on ISA cards then:
- edit /usr/src/linux/drivers/char/ip2.c if needed
- or
- edit config file in /etc/modprobe.d/ if needed (module).
- or both to match this setting.
-d) Run "make modules"
-e) Run "make modules_install"
-f) Run "/sbin/depmod -a"
-g) install driver using `modprobe ip2 <options>` (options listed below)
-h) run ip2mkdev (either the script below or the binary version)
-
-
-Kernel installation:
-
-a) Determine free irq/address to use if any (configure BIOS if need be)
-b) Run "make config" or "make menuconfig" or "make xconfig"
- Select (y) kernel for CONFIG_COMPUTONE under character
- devices. CONFIG_PCI may need to be set if you have PCI bus.
-c) Set address on ISA cards then:
- edit /usr/src/linux/drivers/char/ip2.c
- (Optional - may be specified on kernel command line now)
-d) Run "make zImage" or whatever target you prefer.
-e) mv /usr/src/linux/arch/x86/boot/zImage to /boot.
-f) Add new config for this kernel into /etc/lilo.conf, run "lilo"
- or copy to a floppy disk and boot from that floppy disk.
-g) Reboot using this kernel
-h) run ip2mkdev (either the script below or the binary version)
-
-Kernel command line options:
-
-When compiling the driver into the kernel, io and irq may be
-compiled into the driver by editing ip2.c and setting the values for
-io and irq in the appropriate array. An alternative is to specify
-a command line parameter to the kernel at boot up.
-
- ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3
-
-Note that this order is very different from the specifications for the
-modload parameters which have separate IRQ and IO specifiers.
-
-The io port also selects PCI (1) and EISA (2) boards.
-
- io=0 No board
- io=1 PCI board
- io=2 EISA board
- else ISA board io address
-
-You only need to specify the boards which are present.
-
- Examples:
-
- 2 PCI boards:
-
- ip2=1,0,1,0
-
- 1 ISA board at 0x310 irq 5:
-
- ip2=0x310,5
-
-This can be added to and "append" option in lilo.conf similar to this:
-
- append="ip2=1,0,1,0"
-
-
-3. INSTALLATION
-
-Previously, the driver sources were packaged with a set of patch files
-to update the character drivers' makefile and configuration file, and other
-kernel source files. A build script (ip2build) was included which applies
-the patches if needed, and build any utilities needed.
-What you receive may be a single patch file in conventional kernel
-patch format build script. That form can also be applied by
-running patch -p1 < ThePatchFile. Otherwise run ip2build.
-
-The driver can be installed as a module (recommended) or built into the
-kernel. This is selected as for other drivers through the `make config`
-command from the root of the Linux source tree. If the driver is built
-into the kernel you will need to edit the file ip2.c to match the boards
-you are installing. See that file for instructions. If the driver is
-installed as a module the configuration can also be specified on the
-modprobe command line as follows:
-
- modprobe ip2 irq=irq1,irq2,irq3,irq4 io=addr1,addr2,addr3,addr4
-
-where irqnum is one of the valid Intelliport II interrupts (3,4,5,7,10,11,
-12,15) and addr1-4 are the base addresses for up to four controllers. If
-the irqs are not specified the driver uses the default in ip2.c (which
-selects polled mode). If no base addresses are specified the defaults in
-ip2.c are used. If you are autoloading the driver module with kerneld or
-kmod the base addresses and interrupt number must also be set in ip2.c
-and recompile or just insert and options line in /etc/modprobe.d/*.conf or both.
-The options line is equivalent to the command line and takes precedence over
-what is in ip2.c.
-
-config sample to put /etc/modprobe.d/*.conf:
- options ip2 io=1,0x328 irq=1,10
- alias char-major-71 ip2
- alias char-major-72 ip2
- alias char-major-73 ip2
-
-The equivalent in ip2.c:
-
-static int io[IP2_MAX_BOARDS]= { 1, 0x328, 0, 0 };
-static int irq[IP2_MAX_BOARDS] = { 1, 10, -1, -1 };
-
-The equivalent for the kernel command line (in lilo.conf):
-
- append="ip2=1,1,0x328,10"
-
-
-Note: Both io and irq should be updated to reflect YOUR system. An "io"
- address of 1 or 2 indicates a PCI or EISA card in the board table.
- The PCI or EISA irq will be assigned automatically.
-
-Specifying an invalid or in-use irq will default the driver into
-running in polled mode for that card. If all irq entries are 0 then
-all cards will operate in polled mode.
-
-If you select the driver as part of the kernel run :
-
- make zlilo (or whatever you do to create a bootable kernel)
-
-If you selected a module run :
-
- make modules && make modules_install
-
-The utility ip2mkdev (see 5 and 7 below) creates all the device nodes
-required by the driver. For a device to be created it must be configured
-in the driver and the board must be installed. Only devices corresponding
-to real IntelliPort II ports are created. With multiple boards and expansion
-boxes this will leave gaps in the sequence of device names. ip2mkdev uses
-Linux tty naming conventions: ttyF0 - ttyF255 for normal devices, and
-cuf0 - cuf255 for callout devices.
-
-
-4. USING THE DRIVERS
-
-As noted above, the driver implements the ports in accordance with Linux
-conventions, and the devices should be interchangeable with the standard
-serial devices. (This is a key point for problem reporting: please make
-sure that what you are trying do works on the ttySx/cuax ports first; then
-tell us what went wrong with the ip2 ports!)
-
-Higher speeds can be obtained using the setserial utility which remaps
-38,400 bps (extb) to 57,600 bps, 115,200 bps, or a custom speed.
-Intelliport II installations using the PowerPort expansion module can
-use the custom speed setting to select the highest speeds: 153,600 bps,
-230,400 bps, 307,200 bps, 460,800bps and 921,600 bps. The base for
-custom baud rate configuration is fixed at 921,600 for cards/expansion
-modules with ST654's and 115200 for those with Cirrus CD1400's. This
-corresponds to the maximum bit rates those chips are capable.
-For example if the baud base is 921600 and the baud divisor is 18 then
-the custom rate is 921600/18 = 51200 bps. See the setserial man page for
-complete details. Of course if stty accepts the higher rates now you can
-use that as well as the standard ioctls().
-
-
-5. ip2mkdev and assorted utilities...
-
-Several utilities, including the source for a binary ip2mkdev utility are
-available under .../drivers/char/ip2. These can be build by changing to
-that directory and typing "make" after the kernel has be built. If you do
-not wish to compile the binary utilities, the shell script below can be
-cut out and run as "ip2mkdev" to create the necessary device files. To
-use the ip2mkdev script, you must have procfs enabled and the proc file
-system mounted on /proc.
-
-
-6. NOTES
-
-This is a release version of the driver, but it is impossible to test it
-in all configurations of Linux. If there is any anomalous behaviour that
-does not match the standard serial port's behaviour please let us know.
-
-
-7. ip2mkdev shell script
-
-Previously, this script was simply attached here. It is now attached as a
-shar archive to make it easier to extract the script from the documentation.
-To create the ip2mkdev shell script change to a convenient directory (/tmp
-works just fine) and run the following command:
-
- unshar Documentation/serial/computone.txt
- (This file)
-
-You should now have a file ip2mkdev in your current working directory with
-permissions set to execute. Running that script with then create the
-necessary devices for the Computone boards, interfaces, and ports which
-are present on you system at the time it is run.
-
-
-#!/bin/sh
-# This is a shell archive (produced by GNU sharutils 4.2.1).
-# To extract the files from this archive, save it to some FILE, remove
-# everything before the `!/bin/sh' line above, then type `sh FILE'.
-#
-# Made on 2001-10-29 10:32 EST by <mhw@alcove.wittsend.com>.
-# Source directory was `/home2/src/tmp'.
-#
-# Existing files will *not* be overwritten unless `-c' is specified.
-#
-# This shar contains:
-# length mode name
-# ------ ---------- ------------------------------------------
-# 4251 -rwxr-xr-x ip2mkdev
-#
-save_IFS="${IFS}"
-IFS="${IFS}:"
-gettext_dir=FAILED
-locale_dir=FAILED
-first_param="$1"
-for dir in $PATH
-do
- if test "$gettext_dir" = FAILED && test -f $dir/gettext \
- && ($dir/gettext --version >/dev/null 2>&1)
- then
- set `$dir/gettext --version 2>&1`
- if test "$3" = GNU
- then
- gettext_dir=$dir
- fi
- fi
- if test "$locale_dir" = FAILED && test -f $dir/shar \
- && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
- then
- locale_dir=`$dir/shar --print-text-domain-dir`
- fi
-done
-IFS="$save_IFS"
-if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
-then
- echo=echo
-else
- TEXTDOMAINDIR=$locale_dir
- export TEXTDOMAINDIR
- TEXTDOMAIN=sharutils
- export TEXTDOMAIN
- echo="$gettext_dir/gettext -s"
-fi
-if touch -am -t 200112312359.59 $$.touch >/dev/null 2>&1 && test ! -f 200112312359.59 -a -f $$.touch; then
- shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"'
-elif touch -am 123123592001.59 $$.touch >/dev/null 2>&1 && test ! -f 123123592001.59 -a ! -f 123123592001.5 -a -f $$.touch; then
- shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"'
-elif touch -am 1231235901 $$.touch >/dev/null 2>&1 && test ! -f 1231235901 -a -f $$.touch; then
- shar_touch='touch -am $3$4$5$6$2 "$8"'
-else
- shar_touch=:
- echo
- $echo 'WARNING: not restoring timestamps. Consider getting and'
- $echo "installing GNU \`touch', distributed in GNU File Utilities..."
- echo
-fi
-rm -f 200112312359.59 123123592001.59 123123592001.5 1231235901 $$.touch
-#
-if mkdir _sh17581; then
- $echo 'x -' 'creating lock directory'
-else
- $echo 'failed to create lock directory'
- exit 1
-fi
-# ============= ip2mkdev ==============
-if test -f 'ip2mkdev' && test "$first_param" != -c; then
- $echo 'x -' SKIPPING 'ip2mkdev' '(file already exists)'
-else
- $echo 'x -' extracting 'ip2mkdev' '(text)'
- sed 's/^X//' << 'SHAR_EOF' > 'ip2mkdev' &&
-#!/bin/sh -
-#
-# ip2mkdev
-#
-# Make or remove devices as needed for Computone Intelliport drivers
-#
-# First rule! If the dev file exists and you need it, don't mess
-# with it. That prevents us from screwing up open ttys, ownership
-# and permissions on a running system!
-#
-# This script will NOT remove devices that no longer exist if their
-# board or interface box has been removed. If you want to get rid
-# of them, you can manually do an "rm -f /dev/ttyF* /dev/cuaf*"
-# before running this script. Running this script will then recreate
-# all the valid devices.
-#
-# Michael H. Warfield
-# /\/\|=mhw=|\/\/
-# mhw@wittsend.com
-#
-# Updated 10/29/2000 for version 1.2.13 naming convention
-# under devfs. /\/\|=mhw=|\/\/
-#
-# Updated 03/09/2000 for devfs support in ip2 drivers. /\/\|=mhw=|\/\/
-#
-X
-if test -d /dev/ip2 ; then
-# This is devfs mode... We don't do anything except create symlinks
-# from the real devices to the old names!
-X cd /dev
-X echo "Creating symbolic links to devfs devices"
-X for i in `ls ip2` ; do
-X if test ! -L ip2$i ; then
-X # Remove it incase it wasn't a symlink (old device)
-X rm -f ip2$i
-X ln -s ip2/$i ip2$i
-X fi
-X done
-X for i in `( cd tts ; ls F* )` ; do
-X if test ! -L tty$i ; then
-X # Remove it incase it wasn't a symlink (old device)
-X rm -f tty$i
-X ln -s tts/$i tty$i
-X fi
-X done
-X for i in `( cd cua ; ls F* )` ; do
-X DEVNUMBER=`expr $i : 'F\(.*\)'`
-X if test ! -L cuf$DEVNUMBER ; then
-X # Remove it incase it wasn't a symlink (old device)
-X rm -f cuf$DEVNUMBER
-X ln -s cua/$i cuf$DEVNUMBER
-X fi
-X done
-X exit 0
-fi
-X
-if test ! -f /proc/tty/drivers
-then
-X echo "\
-Unable to check driver status.
-Make sure proc file system is mounted."
-X
-X exit 255
-fi
-X
-if test ! -f /proc/tty/driver/ip2
-then
-X echo "\
-Unable to locate ip2 proc file.
-Attempting to load driver"
-X
-X if /sbin/insmod ip2
-X then
-X if test ! -f /proc/tty/driver/ip2
-X then
-X echo "\
-Unable to locate ip2 proc file after loading driver.
-Driver initialization failure or driver version error.
-"
-X exit 255
-X fi
-X else
-X echo "Unable to load ip2 driver."
-X exit 255
-X fi
-fi
-X
-# Ok... So we got the driver loaded and we can locate the procfs files.
-# Next we need our major numbers.
-X
-TTYMAJOR=`sed -e '/^ip2/!d' -e '/\/dev\/tt/!d' -e 's/.*tt[^ ]*[ ]*\([0-9]*\)[ ]*.*/\1/' < /proc/tty/drivers`
-CUAMAJOR=`sed -e '/^ip2/!d' -e '/\/dev\/cu/!d' -e 's/.*cu[^ ]*[ ]*\([0-9]*\)[ ]*.*/\1/' < /proc/tty/drivers`
-BRDMAJOR=`sed -e '/^Driver: /!d' -e 's/.*IMajor=\([0-9]*\)[ ]*.*/\1/' < /proc/tty/driver/ip2`
-X
-echo "\
-TTYMAJOR = $TTYMAJOR
-CUAMAJOR = $CUAMAJOR
-BRDMAJOR = $BRDMAJOR
-"
-X
-# Ok... Now we should know our major numbers, if appropriate...
-# Now we need our boards and start the device loops.
-X
-grep '^Board [0-9]:' /proc/tty/driver/ip2 | while read token number type alltherest
-do
-X # The test for blank "type" will catch the stats lead-in lines
-X # if they exist in the file
-X if test "$type" = "vacant" -o "$type" = "Vacant" -o "$type" = ""
-X then
-X continue
-X fi
-X
-X BOARDNO=`expr "$number" : '\([0-9]\):'`
-X PORTS=`expr "$alltherest" : '.*ports=\([0-9]*\)' | tr ',' ' '`
-X MINORS=`expr "$alltherest" : '.*minors=\([0-9,]*\)' | tr ',' ' '`
-X
-X if test "$BOARDNO" = "" -o "$PORTS" = ""
-X then
-# This may be a bug. We should at least get this much information
-X echo "Unable to process board line"
-X continue
-X fi
-X
-X if test "$MINORS" = ""
-X then
-# Silently skip this one. This board seems to have no boxes
-X continue
-X fi
-X
-X echo "board $BOARDNO: $type ports = $PORTS; port numbers = $MINORS"
-X
-X if test "$BRDMAJOR" != ""
-X then
-X BRDMINOR=`expr $BOARDNO \* 4`
-X STSMINOR=`expr $BRDMINOR + 1`
-X if test ! -c /dev/ip2ipl$BOARDNO ; then
-X mknod /dev/ip2ipl$BOARDNO c $BRDMAJOR $BRDMINOR
-X fi
-X if test ! -c /dev/ip2stat$BOARDNO ; then
-X mknod /dev/ip2stat$BOARDNO c $BRDMAJOR $STSMINOR
-X fi
-X fi
-X
-X if test "$TTYMAJOR" != ""
-X then
-X PORTNO=$BOARDBASE
-X
-X for PORTNO in $MINORS
-X do
-X if test ! -c /dev/ttyF$PORTNO ; then
-X # We got the hardware but no device - make it
-X mknod /dev/ttyF$PORTNO c $TTYMAJOR $PORTNO
-X fi
-X done
-X fi
-X
-X if test "$CUAMAJOR" != ""
-X then
-X PORTNO=$BOARDBASE
-X
-X for PORTNO in $MINORS
-X do
-X if test ! -c /dev/cuf$PORTNO ; then
-X # We got the hardware but no device - make it
-X mknod /dev/cuf$PORTNO c $CUAMAJOR $PORTNO
-X fi
-X done
-X fi
-done
-X
-Xexit 0
-SHAR_EOF
- (set 20 01 10 29 10 32 01 'ip2mkdev'; eval "$shar_touch") &&
- chmod 0755 'ip2mkdev' ||
- $echo 'restore of' 'ip2mkdev' 'failed'
- if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
- && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
- md5sum -c << SHAR_EOF >/dev/null 2>&1 \
- || $echo 'ip2mkdev:' 'MD5 check failed'
-cb5717134509f38bad9fde6b1f79b4a4 ip2mkdev
-SHAR_EOF
- else
- shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'ip2mkdev'`"
- test 4251 -eq "$shar_count" ||
- $echo 'ip2mkdev:' 'original size' '4251,' 'current size' "$shar_count!"
- fi
-fi
-rm -fr _sh17581
-exit 0
diff --git a/Documentation/watchdog/src/watchdog-test.c b/Documentation/watchdog/src/watchdog-test.c
index 73ff5cc..3da8229 100644
--- a/Documentation/watchdog/src/watchdog-test.c
+++ b/Documentation/watchdog/src/watchdog-test.c
@@ -31,7 +31,7 @@
* or "-e" to enable the card.
*/
-void term(int sig)
+static void term(int sig)
{
close(fd);
fprintf(stderr, "Stopping watchdog ticks...\n");
diff --git a/Makefile b/Makefile
index 3540268..0f66f14 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 3
PATCHLEVEL = 6
SUBLEVEL = 0
-EXTRAVERSION = -rc3
+EXTRAVERSION = -rc5
NAME = Saber-toothed Squirrel
# *DOCUMENTATION*
diff --git a/arch/alpha/kernel/srmcons.c b/arch/alpha/kernel/srmcons.c
index 3ea8094..5d58652 100644
--- a/arch/alpha/kernel/srmcons.c
+++ b/arch/alpha/kernel/srmcons.c
@@ -223,6 +223,7 @@
driver->subtype = SYSTEM_TYPE_SYSCONS;
driver->init_termios = tty_std_termios;
tty_set_operations(driver, &srmcons_ops);
+ tty_port_link_device(&srmcons_singleton.port, driver, 0);
err = tty_register_driver(driver);
if (err) {
put_tty_driver(driver);
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 6d6e18f..2f88d8d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -6,7 +6,7 @@
select HAVE_DMA_API_DEBUG
select HAVE_IDE if PCI || ISA || PCMCIA
select HAVE_DMA_ATTRS
- select HAVE_DMA_CONTIGUOUS if (CPU_V6 || CPU_V6K || CPU_V7)
+ select HAVE_DMA_CONTIGUOUS if MMU
select HAVE_MEMBLOCK
select RTC_LIB
select SYS_SUPPORTS_APM_EMULATION
@@ -2144,6 +2144,7 @@
config CPU_FREQ_IMX
tristate "CPUfreq driver for i.MX CPUs"
depends on ARCH_MXC && CPU_FREQ
+ select CPU_FREQ_TABLE
help
This enables the CPUfreq driver for i.MX CPUs.
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index 59509c4..bd0cff3 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -154,5 +154,10 @@
#size-cells = <0>;
ti,hwmods = "i2c3";
};
+
+ wdt2: wdt@44e35000 {
+ compatible = "ti,omap3-wdt";
+ ti,hwmods = "wd_timer2";
+ };
};
};
diff --git a/arch/arm/boot/dts/at91sam9g25ek.dts b/arch/arm/boot/dts/at91sam9g25ek.dts
index 7829a4d..96514c1 100644
--- a/arch/arm/boot/dts/at91sam9g25ek.dts
+++ b/arch/arm/boot/dts/at91sam9g25ek.dts
@@ -15,7 +15,7 @@
compatible = "atmel,at91sam9g25ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
chosen {
- bootargs = "128M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs";
+ bootargs = "console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs";
};
ahb {
diff --git a/arch/arm/boot/dts/imx51-babbage.dts b/arch/arm/boot/dts/imx51-babbage.dts
index cd86177..59d9789 100644
--- a/arch/arm/boot/dts/imx51-babbage.dts
+++ b/arch/arm/boot/dts/imx51-babbage.dts
@@ -25,8 +25,8 @@
aips@70000000 { /* aips-1 */
spba@70000000 {
esdhc@70004000 { /* ESDHC1 */
- fsl,cd-internal;
- fsl,wp-internal;
+ fsl,cd-controller;
+ fsl,wp-controller;
status = "okay";
};
diff --git a/arch/arm/boot/dts/kirkwood-iconnect.dts b/arch/arm/boot/dts/kirkwood-iconnect.dts
index 52d9470..f8ca6fa 100644
--- a/arch/arm/boot/dts/kirkwood-iconnect.dts
+++ b/arch/arm/boot/dts/kirkwood-iconnect.dts
@@ -41,9 +41,13 @@
};
power-blue {
label = "power:blue";
- gpios = <&gpio1 11 0>;
+ gpios = <&gpio1 10 0>;
linux,default-trigger = "timer";
};
+ power-red {
+ label = "power:red";
+ gpios = <&gpio1 11 0>;
+ };
usb1 {
label = "usb1:blue";
gpios = <&gpio1 12 0>;
diff --git a/arch/arm/boot/dts/twl6030.dtsi b/arch/arm/boot/dts/twl6030.dtsi
index 3b2f351..d351b27 100644
--- a/arch/arm/boot/dts/twl6030.dtsi
+++ b/arch/arm/boot/dts/twl6030.dtsi
@@ -66,6 +66,7 @@
vcxio: regulator@8 {
compatible = "ti,twl6030-vcxio";
+ regulator-always-on;
};
vusb: regulator@9 {
@@ -74,10 +75,12 @@
v1v8: regulator@10 {
compatible = "ti,twl6030-v1v8";
+ regulator-always-on;
};
v2v1: regulator@11 {
compatible = "ti,twl6030-v2v1";
+ regulator-always-on;
};
clk32kg: regulator@12 {
diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig
index 7d87184..90610c7 100644
--- a/arch/arm/configs/armadillo800eva_defconfig
+++ b/arch/arm/configs/armadillo800eva_defconfig
@@ -33,7 +33,7 @@
CONFIG_FORCE_MAX_ZONEORDER=13
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096"
+CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096 rw"
CONFIG_CMDLINE_FORCE=y
CONFIG_KEXEC=y
CONFIG_VFP=y
diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig
index 2d4f661..da68454 100644
--- a/arch/arm/configs/u8500_defconfig
+++ b/arch/arm/configs/u8500_defconfig
@@ -86,6 +86,7 @@
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_LM3530=y
CONFIG_LEDS_LP5521=y
+CONFIG_LEDS_GPIO=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_AB8500=y
CONFIG_RTC_DRV_PL031=y
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index 2ae842d..5c44dcb 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -203,6 +203,13 @@
}
/*
+ * This can be called during early boot to increase the size of the atomic
+ * coherent DMA pool above the default value of 256KiB. It must be called
+ * before postcore_initcall.
+ */
+extern void __init init_dma_coherent_pool_size(unsigned long size);
+
+/*
* This can be called during boot to increase the size of the consistent
* DMA region above it's default value of 2MB. It must be called before the
* memory allocator is initialised, i.e. before any core_initcall.
diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c
index 104ca40..aaa443b 100644
--- a/arch/arm/mach-at91/at91rm9200_time.c
+++ b/arch/arm/mach-at91/at91rm9200_time.c
@@ -197,7 +197,7 @@
at91_st_read(AT91_ST_SR);
/* Make IRQs happen for the system timer */
- setup_irq(AT91_ID_SYS, &at91rm9200_timer_irq);
+ setup_irq(NR_IRQS_LEGACY + AT91_ID_SYS, &at91rm9200_timer_irq);
/* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used
* directly for the clocksource and all clockevents, after adjusting
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index 7b9c2ba..bce572a 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -726,6 +726,8 @@
.flags = IORESOURCE_MEM,
}, {
.flags = IORESOURCE_MEM,
+ }, {
+ .flags = IORESOURCE_IRQ,
},
};
@@ -744,10 +746,12 @@
* The second resource is needed:
* GPBR will serve as the storage for RTC time offset
*/
- at91sam9260_rtt_device.num_resources = 2;
+ at91sam9260_rtt_device.num_resources = 3;
rtt_resources[1].start = AT91SAM9260_BASE_GPBR +
4 * CONFIG_RTC_DRV_AT91SAM9_GPBR;
rtt_resources[1].end = rtt_resources[1].start + 3;
+ rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS;
+ rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS;
}
#else
static void __init at91_add_device_rtt_rtc(void)
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index 8df5c1bd..bc2590d 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -609,6 +609,8 @@
.flags = IORESOURCE_MEM,
}, {
.flags = IORESOURCE_MEM,
+ }, {
+ .flags = IORESOURCE_IRQ,
}
};
@@ -626,10 +628,12 @@
* The second resource is needed:
* GPBR will serve as the storage for RTC time offset
*/
- at91sam9261_rtt_device.num_resources = 2;
+ at91sam9261_rtt_device.num_resources = 3;
rtt_resources[1].start = AT91SAM9261_BASE_GPBR +
4 * CONFIG_RTC_DRV_AT91SAM9_GPBR;
rtt_resources[1].end = rtt_resources[1].start + 3;
+ rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS;
+ rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS;
}
#else
static void __init at91_add_device_rtt_rtc(void)
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index eb6bbf8..9b6ca73 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -990,6 +990,8 @@
.flags = IORESOURCE_MEM,
}, {
.flags = IORESOURCE_MEM,
+ }, {
+ .flags = IORESOURCE_IRQ,
}
};
@@ -1006,6 +1008,8 @@
.flags = IORESOURCE_MEM,
}, {
.flags = IORESOURCE_MEM,
+ }, {
+ .flags = IORESOURCE_IRQ,
}
};
@@ -1027,14 +1031,14 @@
* The second resource is needed only for the chosen RTT:
* GPBR will serve as the storage for RTC time offset
*/
- at91sam9263_rtt0_device.num_resources = 2;
+ at91sam9263_rtt0_device.num_resources = 3;
at91sam9263_rtt1_device.num_resources = 1;
pdev = &at91sam9263_rtt0_device;
r = rtt0_resources;
break;
case 1:
at91sam9263_rtt0_device.num_resources = 1;
- at91sam9263_rtt1_device.num_resources = 2;
+ at91sam9263_rtt1_device.num_resources = 3;
pdev = &at91sam9263_rtt1_device;
r = rtt1_resources;
break;
@@ -1047,6 +1051,8 @@
pdev->name = "rtc-at91sam9";
r[1].start = AT91SAM9263_BASE_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR;
r[1].end = r[1].start + 3;
+ r[2].start = NR_IRQS_LEGACY + AT91_ID_SYS;
+ r[2].end = NR_IRQS_LEGACY + AT91_ID_SYS;
}
#else
static void __init at91_add_device_rtt_rtc(void)
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 0607399..1b47319 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -1293,6 +1293,8 @@
.flags = IORESOURCE_MEM,
}, {
.flags = IORESOURCE_MEM,
+ }, {
+ .flags = IORESOURCE_IRQ,
}
};
@@ -1310,10 +1312,12 @@
* The second resource is needed:
* GPBR will serve as the storage for RTC time offset
*/
- at91sam9g45_rtt_device.num_resources = 2;
+ at91sam9g45_rtt_device.num_resources = 3;
rtt_resources[1].start = AT91SAM9G45_BASE_GPBR +
4 * CONFIG_RTC_DRV_AT91SAM9_GPBR;
rtt_resources[1].end = rtt_resources[1].start + 3;
+ rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS;
+ rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS;
}
#else
static void __init at91_add_device_rtt_rtc(void)
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index f09fff9..b3d365d 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -688,6 +688,8 @@
.flags = IORESOURCE_MEM,
}, {
.flags = IORESOURCE_MEM,
+ }, {
+ .flags = IORESOURCE_IRQ,
}
};
@@ -705,10 +707,12 @@
* The second resource is needed:
* GPBR will serve as the storage for RTC time offset
*/
- at91sam9rl_rtt_device.num_resources = 2;
+ at91sam9rl_rtt_device.num_resources = 3;
rtt_resources[1].start = AT91SAM9RL_BASE_GPBR +
4 * CONFIG_RTC_DRV_AT91SAM9_GPBR;
rtt_resources[1].end = rtt_resources[1].start + 3;
+ rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS;
+ rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS;
}
#else
static void __init at91_add_device_rtt_rtc(void)
diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c
index de2ec6b..188c829 100644
--- a/arch/arm/mach-at91/clock.c
+++ b/arch/arm/mach-at91/clock.c
@@ -63,6 +63,12 @@
#define cpu_has_300M_plla() (cpu_is_at91sam9g10())
+#define cpu_has_240M_plla() (cpu_is_at91sam9261() \
+ || cpu_is_at91sam9263() \
+ || cpu_is_at91sam9rl())
+
+#define cpu_has_210M_plla() (cpu_is_at91sam9260())
+
#define cpu_has_pllb() (!(cpu_is_at91sam9rl() \
|| cpu_is_at91sam9g45() \
|| cpu_is_at91sam9x5() \
@@ -706,6 +712,12 @@
} else if (cpu_has_800M_plla()) {
if (plla.rate_hz > 800000000)
pll_overclock = true;
+ } else if (cpu_has_240M_plla()) {
+ if (plla.rate_hz > 240000000)
+ pll_overclock = true;
+ } else if (cpu_has_210M_plla()) {
+ if (plla.rate_hz > 210000000)
+ pll_overclock = true;
} else {
if (plla.rate_hz > 209000000)
pll_overclock = true;
diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c
index 4db5de5..6321567 100644
--- a/arch/arm/mach-dove/common.c
+++ b/arch/arm/mach-dove/common.c
@@ -102,7 +102,8 @@
void __init dove_ge00_init(struct mv643xx_eth_platform_data *eth_data)
{
orion_ge00_init(eth_data, DOVE_GE00_PHYS_BASE,
- IRQ_DOVE_GE00_SUM, IRQ_DOVE_GE00_ERR);
+ IRQ_DOVE_GE00_SUM, IRQ_DOVE_GE00_ERR,
+ 1600);
}
/*****************************************************************************
diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c
index 5ca8030..4e574c2 100644
--- a/arch/arm/mach-exynos/mach-origen.c
+++ b/arch/arm/mach-exynos/mach-origen.c
@@ -42,6 +42,7 @@
#include <plat/backlight.h>
#include <plat/fb.h>
#include <plat/mfc.h>
+#include <plat/hdmi.h>
#include <mach/ohci.h>
#include <mach/map.h>
@@ -734,6 +735,11 @@
s3c_gpio_setpull(EXYNOS4_GPX2(2), S3C_GPIO_PULL_NONE);
}
+/* I2C module and id for HDMIPHY */
+static struct i2c_board_info hdmiphy_info = {
+ I2C_BOARD_INFO("hdmiphy-exynos4210", 0x38),
+};
+
static void s5p_tv_setup(void)
{
/* Direct HPD to HDMI chip */
@@ -781,6 +787,7 @@
s5p_tv_setup();
s5p_i2c_hdmiphy_set_platdata(NULL);
+ s5p_hdmi_set_platdata(&hdmiphy_info, NULL, 0);
#ifdef CONFIG_DRM_EXYNOS
s5p_device_fimd0.dev.platform_data = &drm_fimd_pdata;
diff --git a/arch/arm/mach-exynos/mach-smdkv310.c b/arch/arm/mach-exynos/mach-smdkv310.c
index 3cfa688..73f2bce 100644
--- a/arch/arm/mach-exynos/mach-smdkv310.c
+++ b/arch/arm/mach-exynos/mach-smdkv310.c
@@ -40,6 +40,7 @@
#include <plat/mfc.h>
#include <plat/ehci.h>
#include <plat/clock.h>
+#include <plat/hdmi.h>
#include <mach/map.h>
#include <mach/ohci.h>
@@ -354,6 +355,11 @@
.pwm_period_ns = 1000,
};
+/* I2C module and id for HDMIPHY */
+static struct i2c_board_info hdmiphy_info = {
+ I2C_BOARD_INFO("hdmiphy-exynos4210", 0x38),
+};
+
static void s5p_tv_setup(void)
{
/* direct HPD to HDMI chip */
@@ -388,6 +394,7 @@
s5p_tv_setup();
s5p_i2c_hdmiphy_set_platdata(NULL);
+ s5p_hdmi_set_platdata(&hdmiphy_info, NULL, 0);
samsung_keypad_set_platdata(&smdkv310_keypad_data);
diff --git a/arch/arm/mach-gemini/irq.c b/arch/arm/mach-gemini/irq.c
index ca70e5f..020852d 100644
--- a/arch/arm/mach-gemini/irq.c
+++ b/arch/arm/mach-gemini/irq.c
@@ -17,6 +17,7 @@
#include <linux/sched.h>
#include <asm/irq.h>
#include <asm/mach/irq.h>
+#include <asm/system_misc.h>
#include <mach/hardware.h>
#define IRQ_SOURCE(base_addr) (base_addr + 0x00)
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 07f7c22..d004d37 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -9,7 +9,8 @@
obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clk-imx31.o iomux-imx31.o ehci-imx31.o pm-imx3.o
obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clk-imx35.o ehci-imx35.o pm-imx3.o
-obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clk-imx51-imx53.o ehci-imx5.o pm-imx5.o cpu_op-mx51.o
+imx5-pm-$(CONFIG_PM) += pm-imx5.o
+obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clk-imx51-imx53.o ehci-imx5.o $(imx5-pm-y) cpu_op-mx51.o
obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o \
clk-pfd.o clk-busy.o
@@ -70,14 +71,13 @@
obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o
obj-$(CONFIG_HAVE_IMX_SRC) += src.o
-obj-$(CONFIG_CPU_V7) += head-v7.o
-AFLAGS_head-v7.o :=-Wa,-march=armv7-a
-obj-$(CONFIG_SMP) += platsmp.o
+AFLAGS_headsmp.o :=-Wa,-march=armv7-a
+obj-$(CONFIG_SMP) += headsmp.o platsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o mach-imx6q.o
ifeq ($(CONFIG_PM),y)
-obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o
+obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o headsmp.o
endif
# i.MX5 based machines
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index ea89520..4233d9e 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -152,7 +152,7 @@
ssi2, ssi3, uart_ipg, uart_serial, usboh3, usdhc1, usdhc2, usdhc3,
usdhc4, vdo_axi, vpu_axi, cko1, pll1_sys, pll2_bus, pll3_usb_otg,
pll4_audio, pll5_video, pll6_mlb, pll7_usb_host, pll8_enet, ssi1_ipg,
- ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2,
+ ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2, ldb_di0_div_3_5, ldb_di1_div_3_5,
clk_max
};
@@ -288,8 +288,10 @@
clk[gpu3d_shader] = imx_clk_divider("gpu3d_shader", "gpu3d_shader_sel", base + 0x18, 29, 3);
clk[ipu1_podf] = imx_clk_divider("ipu1_podf", "ipu1_sel", base + 0x3c, 11, 3);
clk[ipu2_podf] = imx_clk_divider("ipu2_podf", "ipu2_sel", base + 0x3c, 16, 3);
- clk[ldb_di0_podf] = imx_clk_divider("ldb_di0_podf", "ldb_di0_sel", base + 0x20, 10, 1);
- clk[ldb_di1_podf] = imx_clk_divider("ldb_di1_podf", "ldb_di1_sel", base + 0x20, 11, 1);
+ clk[ldb_di0_div_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
+ clk[ldb_di0_podf] = imx_clk_divider("ldb_di0_podf", "ldb_di0_div_3_5", base + 0x20, 10, 1);
+ clk[ldb_di1_div_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
+ clk[ldb_di1_podf] = imx_clk_divider("ldb_di1_podf", "ldb_di1_div_3_5", base + 0x20, 11, 1);
clk[ipu1_di0_pre] = imx_clk_divider("ipu1_di0_pre", "ipu1_di0_pre_sel", base + 0x34, 3, 3);
clk[ipu1_di1_pre] = imx_clk_divider("ipu1_di1_pre", "ipu1_di1_pre_sel", base + 0x34, 12, 3);
clk[ipu2_di0_pre] = imx_clk_divider("ipu2_di0_pre", "ipu2_di0_pre_sel", base + 0x38, 3, 3);
diff --git a/arch/arm/mach-imx/head-v7.S b/arch/arm/mach-imx/headsmp.S
similarity index 100%
rename from arch/arm/mach-imx/head-v7.S
rename to arch/arm/mach-imx/headsmp.S
diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c
index 20ed2d5..f8f7437 100644
--- a/arch/arm/mach-imx/hotplug.c
+++ b/arch/arm/mach-imx/hotplug.c
@@ -42,22 +42,6 @@
: "cc");
}
-static inline void cpu_leave_lowpower(void)
-{
- unsigned int v;
-
- asm volatile(
- "mrc p15, 0, %0, c1, c0, 0\n"
- " orr %0, %0, %1\n"
- " mcr p15, 0, %0, c1, c0, 0\n"
- " mrc p15, 0, %0, c1, c0, 1\n"
- " orr %0, %0, %2\n"
- " mcr p15, 0, %0, c1, c0, 1\n"
- : "=&r" (v)
- : "Ir" (CR_C), "Ir" (0x40)
- : "cc");
-}
-
/*
* platform-specific code to shutdown a CPU
*
@@ -67,11 +51,10 @@
{
cpu_enter_lowpower();
imx_enable_cpu(cpu, false);
- cpu_do_idle();
- cpu_leave_lowpower();
- /* We should never return from idle */
- panic("cpu %d unexpectedly exit from shutdown\n", cpu);
+ /* spin here until hardware takes it down */
+ while (1)
+ ;
}
int platform_cpu_disable(unsigned int cpu)
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index 5ec0608..045b3f6 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -71,7 +71,7 @@
/* For imx6q sabrelite board: set KSZ9021RN RGMII pad skew */
static int ksz9021rn_phy_fixup(struct phy_device *phydev)
{
- if (IS_ENABLED(CONFIG_PHYLIB)) {
+ if (IS_BUILTIN(CONFIG_PHYLIB)) {
/* min rx data delay */
phy_write(phydev, 0x0b, 0x8105);
phy_write(phydev, 0x0c, 0x0000);
@@ -112,7 +112,7 @@
static void __init imx6q_sabrelite_init(void)
{
- if (IS_ENABLED(CONFIG_PHYLIB))
+ if (IS_BUILTIN(CONFIG_PHYLIB))
phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK,
ksz9021rn_phy_fixup);
imx6q_sabrelite_cko1_setup();
diff --git a/arch/arm/mach-kirkwood/Makefile.boot b/arch/arm/mach-kirkwood/Makefile.boot
index a571755..a13299d 100644
--- a/arch/arm/mach-kirkwood/Makefile.boot
+++ b/arch/arm/mach-kirkwood/Makefile.boot
@@ -7,7 +7,8 @@
dtb-$(CONFIG_MACH_DLINK_KIRKWOOD_DT) += kirkwood-dns325.dtb
dtb-$(CONFIG_MACH_ICONNECT_DT) += kirkwood-iconnect.dtb
dtb-$(CONFIG_MACH_IB62X0_DT) += kirkwood-ib62x0.dtb
-dtb-$(CONFIG_MACH_TS219_DT) += kirkwood-qnap-ts219.dtb
+dtb-$(CONFIG_MACH_TS219_DT) += kirkwood-ts219-6281.dtb
+dtb-$(CONFIG_MACH_TS219_DT) += kirkwood-ts219-6282.dtb
dtb-$(CONFIG_MACH_GOFLEXNET_DT) += kirkwood-goflexnet.dtb
dtb-$(CONFIG_MACH_LSXL_DT) += kirkwood-lschlv2.dtb
dtb-$(CONFIG_MACH_LSXL_DT) += kirkwood-lsxhl.dtb
diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c
index c4b64ad..1201191 100644
--- a/arch/arm/mach-kirkwood/common.c
+++ b/arch/arm/mach-kirkwood/common.c
@@ -301,7 +301,7 @@
{
orion_ge00_init(eth_data,
GE00_PHYS_BASE, IRQ_KIRKWOOD_GE00_SUM,
- IRQ_KIRKWOOD_GE00_ERR);
+ IRQ_KIRKWOOD_GE00_ERR, 1600);
/* The interface forgets the MAC address assigned by u-boot if
the clock is turned off, so claim the clk now. */
clk_prepare_enable(ge0);
@@ -315,7 +315,7 @@
{
orion_ge01_init(eth_data,
GE01_PHYS_BASE, IRQ_KIRKWOOD_GE01_SUM,
- IRQ_KIRKWOOD_GE01_ERR);
+ IRQ_KIRKWOOD_GE01_ERR, 1600);
clk_prepare_enable(ge1);
}
@@ -517,6 +517,13 @@
void __init kirkwood_init_early(void)
{
orion_time_set_base(TIMER_VIRT_BASE);
+
+ /*
+ * Some Kirkwood devices allocate their coherent buffers from atomic
+ * context. Increase size of atomic coherent pool to make sure such
+ * the allocations won't fail.
+ */
+ init_dma_coherent_pool_size(SZ_1M);
}
int kirkwood_tclk;
diff --git a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
index d933593..be90b7d 100644
--- a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
+++ b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
@@ -10,6 +10,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/sizes.h>
#include <linux/platform_device.h>
#include <linux/mtd/partitions.h>
#include <linux/ata_platform.h>
diff --git a/arch/arm/mach-mmp/sram.c b/arch/arm/mach-mmp/sram.c
index 4304f95..7e8a5a2 100644
--- a/arch/arm/mach-mmp/sram.c
+++ b/arch/arm/mach-mmp/sram.c
@@ -68,7 +68,7 @@
struct resource *res;
int ret = 0;
- if (!pdata && !pdata->pool_name)
+ if (!pdata || !pdata->pool_name)
return -ENODEV;
info = kzalloc(sizeof(*info), GFP_KERNEL);
diff --git a/arch/arm/mach-mv78xx0/addr-map.c b/arch/arm/mach-mv78xx0/addr-map.c
index 62b53d7..a9bc841 100644
--- a/arch/arm/mach-mv78xx0/addr-map.c
+++ b/arch/arm/mach-mv78xx0/addr-map.c
@@ -37,7 +37,7 @@
#define WIN0_OFF(n) (BRIDGE_VIRT_BASE + 0x0000 + ((n) << 4))
#define WIN8_OFF(n) (BRIDGE_VIRT_BASE + 0x0900 + (((n) - 8) << 4))
-static void __init __iomem *win_cfg_base(int win)
+static void __init __iomem *win_cfg_base(const struct orion_addr_map_cfg *cfg, int win)
{
/*
* Find the control register base address for this window.
diff --git a/arch/arm/mach-mv78xx0/common.c b/arch/arm/mach-mv78xx0/common.c
index b4c53b8..3057f7d 100644
--- a/arch/arm/mach-mv78xx0/common.c
+++ b/arch/arm/mach-mv78xx0/common.c
@@ -213,7 +213,8 @@
{
orion_ge00_init(eth_data,
GE00_PHYS_BASE, IRQ_MV78XX0_GE00_SUM,
- IRQ_MV78XX0_GE_ERR);
+ IRQ_MV78XX0_GE_ERR,
+ MV643XX_TX_CSUM_DEFAULT_LIMIT);
}
@@ -224,7 +225,8 @@
{
orion_ge01_init(eth_data,
GE01_PHYS_BASE, IRQ_MV78XX0_GE01_SUM,
- NO_IRQ);
+ NO_IRQ,
+ MV643XX_TX_CSUM_DEFAULT_LIMIT);
}
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index c534698..c162369 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -37,7 +37,6 @@
#include <plat/board-ams-delta.h>
#include <plat/keypad.h>
#include <plat/mux.h>
-#include <plat/board.h>
#include <mach/hardware.h>
#include <mach/ams-delta-fiq.h>
diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c
index 6872f3f..6d98552 100644
--- a/arch/arm/mach-omap1/board-fsample.c
+++ b/arch/arm/mach-omap1/board-fsample.c
@@ -32,7 +32,6 @@
#include <plat/flash.h>
#include <plat/fpga.h>
#include <plat/keypad.h>
-#include <plat/board.h>
#include <mach/hardware.h>
diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c
index 6ec385e..04b5fda 100644
--- a/arch/arm/mach-omap1/board-generic.c
+++ b/arch/arm/mach-omap1/board-generic.c
@@ -23,7 +23,6 @@
#include <asm/mach/map.h>
#include <plat/mux.h>
-#include <plat/board.h>
#include <mach/usb.h>
@@ -52,9 +51,6 @@
};
#endif
-static struct omap_board_config_kernel generic_config[] __initdata = {
-};
-
static void __init omap_generic_init(void)
{
#ifdef CONFIG_ARCH_OMAP15XX
@@ -76,8 +72,6 @@
}
#endif
- omap_board_config = generic_config;
- omap_board_config_size = ARRAY_SIZE(generic_config);
omap_serial_init();
omap_register_i2c_bus(1, 100, NULL, 0);
}
diff --git a/arch/arm/mach-omap1/board-htcherald.c b/arch/arm/mach-omap1/board-htcherald.c
index b3f6e94..b9771b5 100644
--- a/arch/arm/mach-omap1/board-htcherald.c
+++ b/arch/arm/mach-omap1/board-htcherald.c
@@ -42,7 +42,6 @@
#include <asm/mach/arch.h>
#include <plat/omap7xx.h>
-#include <plat/board.h>
#include <plat/keypad.h>
#include <plat/mmc.h>
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
index 2c0ca8f..ec01f03 100644
--- a/arch/arm/mach-omap1/board-nokia770.c
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -26,7 +26,6 @@
#include <asm/mach/map.h>
#include <plat/mux.h>
-#include <plat/board.h>
#include <plat/keypad.h>
#include <plat/lcd_mipid.h>
#include <plat/mmc.h>
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index 8784705..569b687 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -39,6 +39,7 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
#include <linux/i2c/tps65010.h>
+#include <linux/platform_data/omap1_bl.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index 26bcb9d..49f8d74 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -28,6 +28,7 @@
#include <linux/interrupt.h>
#include <linux/apm-emulation.h>
#include <linux/omapfb.h>
+#include <linux/platform_data/omap1_bl.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -37,7 +38,6 @@
#include <plat/mux.h>
#include <plat/tc.h>
#include <plat/dma.h>
-#include <plat/board.h>
#include <plat/irda.h>
#include <plat/keypad.h>
diff --git a/arch/arm/mach-omap1/board-palmtt.c b/arch/arm/mach-omap1/board-palmtt.c
index 4d09944..01523cd 100644
--- a/arch/arm/mach-omap1/board-palmtt.c
+++ b/arch/arm/mach-omap1/board-palmtt.c
@@ -27,6 +27,7 @@
#include <linux/omapfb.h>
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
+#include <linux/platform_data/omap1_bl.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -37,7 +38,6 @@
#include <plat/mux.h>
#include <plat/dma.h>
#include <plat/tc.h>
-#include <plat/board.h>
#include <plat/irda.h>
#include <plat/keypad.h>
diff --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c
index 3559803..a7abce6 100644
--- a/arch/arm/mach-omap1/board-palmz71.c
+++ b/arch/arm/mach-omap1/board-palmz71.c
@@ -30,6 +30,7 @@
#include <linux/omapfb.h>
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
+#include <linux/platform_data/omap1_bl.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -39,7 +40,6 @@
#include <plat/mux.h>
#include <plat/dma.h>
#include <plat/tc.h>
-#include <plat/board.h>
#include <plat/irda.h>
#include <plat/keypad.h>
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index 703d55e..277e0bc 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -32,7 +32,6 @@
#include <plat/fpga.h>
#include <plat/flash.h>
#include <plat/keypad.h>
-#include <plat/board.h>
#include <mach/hardware.h>
diff --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c
index 8c665bd..2e1fff2 100644
--- a/arch/arm/mach-omap1/board-sx1.c
+++ b/arch/arm/mach-omap1/board-sx1.c
@@ -38,7 +38,6 @@
#include <plat/dma.h>
#include <plat/irda.h>
#include <plat/tc.h>
-#include <plat/board.h>
#include <plat/keypad.h>
#include <plat/board-sx1.h>
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
index 3497769..1668af3 100644
--- a/arch/arm/mach-omap1/board-voiceblue.c
+++ b/arch/arm/mach-omap1/board-voiceblue.c
@@ -35,7 +35,6 @@
#include <plat/flash.h>
#include <plat/mux.h>
#include <plat/tc.h>
-#include <plat/board.h>
#include <mach/hardware.h>
#include <mach/usb.h>
@@ -155,9 +154,6 @@
.pins[2] = 6,
};
-static struct omap_board_config_kernel voiceblue_config[] = {
-};
-
#define MACHINE_PANICED 1
#define MACHINE_REBOOTING 2
#define MACHINE_REBOOT 4
@@ -275,8 +271,6 @@
voiceblue_smc91x_resources[1].start = gpio_to_irq(8);
voiceblue_smc91x_resources[1].end = gpio_to_irq(8);
platform_add_devices(voiceblue_devices, ARRAY_SIZE(voiceblue_devices));
- omap_board_config = voiceblue_config;
- omap_board_config_size = ARRAY_SIZE(voiceblue_config);
omap_serial_init();
omap1_usb_init(&voiceblue_usb_config);
omap_register_i2c_bus(1, 100, NULL, 0);
diff --git a/arch/arm/mach-omap1/clock_data.c b/arch/arm/mach-omap1/clock_data.c
index c007d80..6a32b9b 100644
--- a/arch/arm/mach-omap1/clock_data.c
+++ b/arch/arm/mach-omap1/clock_data.c
@@ -25,7 +25,6 @@
#include <plat/clock.h>
#include <plat/cpu.h>
#include <plat/clkdev_omap.h>
-#include <plat/board.h>
#include <plat/sram.h> /* for omap_sram_reprogram_clock() */
#include <mach/hardware.h>
@@ -788,7 +787,6 @@
int __init omap1_clk_init(void)
{
struct omap_clk *c;
- const struct omap_clock_config *info;
int crystal_type = 0; /* Default 12 MHz */
u32 reg;
@@ -837,12 +835,6 @@
ck_dpll1_p = clk_get(NULL, "ck_dpll1");
ck_ref_p = clk_get(NULL, "ck_ref");
- info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config);
- if (info != NULL) {
- if (!cpu_is_omap15xx())
- crystal_type = info->system_clock_type;
- }
-
if (cpu_is_omap7xx())
ck_ref.rate = 13000000;
if (cpu_is_omap16xx() && crystal_type == 2)
diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c
index fa1fa4d..1feca35 100644
--- a/arch/arm/mach-omap1/devices.c
+++ b/arch/arm/mach-omap1/devices.c
@@ -20,7 +20,6 @@
#include <asm/mach/map.h>
#include <plat/tc.h>
-#include <plat/board.h>
#include <plat/mux.h>
#include <plat/dma.h>
#include <plat/mmc.h>
diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c
index 6809c9e..0d1709b 100644
--- a/arch/arm/mach-omap1/serial.c
+++ b/arch/arm/mach-omap1/serial.c
@@ -22,7 +22,6 @@
#include <asm/mach-types.h>
-#include <plat/board.h>
#include <plat/mux.h>
#include <plat/fpga.h>
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index dd2db02..fcd4e85 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -62,13 +62,14 @@
select PM_OPP if PM
select USB_ARCH_HAS_EHCI if USB_SUPPORT
select ARM_CPU_SUSPEND if PM
- select ARCH_NEEDS_CPU_IDLE_COUPLED
+ select ARCH_NEEDS_CPU_IDLE_COUPLED if SMP
config SOC_OMAP5
bool "TI OMAP5"
select CPU_V7
select ARM_GIC
select HAVE_SMP
+ select ARM_CPU_SUSPEND if PM
comment "OMAP Core Type"
depends on ARCH_OMAP2
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index 9511584..36eee4b 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -33,7 +33,6 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
-#include <plat/board.h>
#include "common.h"
#include <plat/gpmc.h>
#include <plat/usb.h>
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index a98c688..0f78cdb 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -31,7 +31,6 @@
#include <asm/mach/map.h>
#include <plat/mcspi.h>
-#include <plat/board.h>
#include <plat/usb.h>
#include "common.h"
#include <plat/dma.h>
@@ -191,9 +190,6 @@
.default_device = &sdp3430_lcd_device,
};
-static struct omap_board_config_kernel sdp3430_config[] __initdata = {
-};
-
static struct omap2_hsmmc_info mmc[] = {
{
.mmc = 1,
@@ -576,8 +572,6 @@
int gpio_pendown;
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
- omap_board_config = sdp3430_config;
- omap_board_config_size = ARRAY_SIZE(sdp3430_config);
omap_hsmmc_init(mmc);
omap3430_i2c_init();
omap_display_init(&sdp3430_dss_data);
diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index 2dc9ba5..8518b13 100644
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -17,7 +17,6 @@
#include <asm/mach/arch.h>
#include "common.h"
-#include <plat/board.h>
#include <plat/gpmc-smc91x.h>
#include <plat/usb.h>
@@ -67,9 +66,6 @@
.reset_gpio_port[2] = -EINVAL
};
-static struct omap_board_config_kernel sdp_config[] __initdata = {
-};
-
#ifdef CONFIG_OMAP_MUX
static struct omap_board_mux board_mux[] __initdata = {
{ .reg_offset = OMAP_MUX_TERMINATOR },
@@ -197,8 +193,6 @@
static void __init omap_sdp_init(void)
{
omap3_mux_init(board_mux, OMAP_PACKAGE_CBP);
- omap_board_config = sdp_config;
- omap_board_config_size = ARRAY_SIZE(sdp_config);
zoom_peripherals_init();
omap_sdrc_init(h8mbx00u0mer0em_sdrc_params,
h8mbx00u0mer0em_sdrc_params);
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index ad8a7d9..04e8574 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -34,7 +34,6 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
-#include <plat/board.h>
#include "common.h"
#include <plat/usb.h>
#include <plat/mmc.h>
diff --git a/arch/arm/mach-omap2/board-am3517crane.c b/arch/arm/mach-omap2/board-am3517crane.c
index 92432c2..de92b08 100644
--- a/arch/arm/mach-omap2/board-am3517crane.c
+++ b/arch/arm/mach-omap2/board-am3517crane.c
@@ -26,7 +26,6 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
-#include <plat/board.h>
#include "common.h"
#include <plat/usb.h>
@@ -37,11 +36,6 @@
#define GPIO_USB_POWER 35
#define GPIO_USB_NRESET 38
-
-/* Board initialization */
-static struct omap_board_config_kernel am3517_crane_config[] __initdata = {
-};
-
#ifdef CONFIG_OMAP_MUX
static struct omap_board_mux board_mux[] __initdata = {
{ .reg_offset = OMAP_MUX_TERMINATOR },
@@ -67,9 +61,6 @@
omap_serial_init();
omap_sdrc_init(NULL, NULL);
- omap_board_config = am3517_crane_config;
- omap_board_config_size = ARRAY_SIZE(am3517_crane_config);
-
/* Configure GPIO for EHCI port */
if (omap_mux_init_gpio(GPIO_USB_NRESET, OMAP_PIN_OUTPUT)) {
pr_err("Can not configure mux for GPIO_USB_NRESET %d\n",
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index 18f6010..00abda1 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -32,7 +32,6 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
-#include <plat/board.h>
#include "common.h"
#include <plat/usb.h>
#include <video/omapdss.h>
@@ -324,9 +323,6 @@
platform_device_register(&am3517_hecc_device);
}
-static struct omap_board_config_kernel am3517_evm_config[] __initdata = {
-};
-
static struct omap2_hsmmc_info mmc[] = {
{
.mmc = 1,
@@ -346,8 +342,6 @@
static void __init am3517_evm_init(void)
{
- omap_board_config = am3517_evm_config;
- omap_board_config_size = ARRAY_SIZE(am3517_evm_config);
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
am3517_evm_i2c_init();
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
index e5fa46b..a6a1b48 100644
--- a/arch/arm/mach-omap2/board-apollon.c
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -35,7 +35,6 @@
#include <asm/mach/flash.h>
#include <plat/led.h>
-#include <plat/board.h>
#include "common.h"
#include <plat/gpmc.h>
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index 97d7190..d94a640 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -37,7 +37,6 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
-#include <plat/board.h>
#include "common.h"
#include <plat/nand.h>
#include <plat/gpmc.h>
@@ -714,13 +713,8 @@
static inline void cm_t3730_init_mux(void) {}
#endif
-static struct omap_board_config_kernel cm_t35_config[] __initdata = {
-};
-
static void __init cm_t3x_common_init(void)
{
- omap_board_config = cm_t35_config;
- omap_board_config_size = ARRAY_SIZE(cm_t35_config);
omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);
omap_serial_init();
omap_sdrc_init(mt46h32m32lf6_sdrc_params,
diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c
index a33ad46..57204f8 100644
--- a/arch/arm/mach-omap2/board-cm-t3517.c
+++ b/arch/arm/mach-omap2/board-cm-t3517.c
@@ -38,7 +38,6 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
-#include <plat/board.h>
#include "common.h"
#include <plat/usb.h>
#include <plat/nand.h>
@@ -249,9 +248,6 @@
static inline void cm_t3517_init_nand(void) {}
#endif
-static struct omap_board_config_kernel cm_t3517_config[] __initdata = {
-};
-
#ifdef CONFIG_OMAP_MUX
static struct omap_board_mux board_mux[] __initdata = {
/* GPIO186 - Green LED */
@@ -285,8 +281,6 @@
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
omap_serial_init();
omap_sdrc_init(NULL, NULL);
- omap_board_config = cm_t3517_config;
- omap_board_config_size = ARRAY_SIZE(cm_t3517_config);
cm_t3517_init_leds();
cm_t3517_init_nand();
cm_t3517_init_rtc();
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index 6567c1c..870a2a5 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -40,7 +40,6 @@
#include <asm/mach/map.h>
#include <asm/mach/flash.h>
-#include <plat/board.h>
#include "common.h"
#include <plat/gpmc.h>
#include <plat/nand.h>
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 6f93a20..38024a5 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -20,7 +20,6 @@
#include <asm/hardware/gic.h>
#include <asm/mach/arch.h>
-#include <plat/board.h>
#include "common.h"
#include "common-board-devices.h"
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index ace2048..5be30e6 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -32,11 +32,11 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
-#include <plat/board.h>
#include "common.h"
#include <plat/menelaus.h>
#include <plat/dma.h>
#include <plat/gpmc.h>
+#include <plat/debug-devices.h>
#include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h>
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 7491529..01103b3 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -29,7 +29,6 @@
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
-#include <plat/board.h>
#include "common.h"
#include <plat/gpmc.h>
#include <plat/usb.h>
@@ -554,6 +553,8 @@
#ifdef CONFIG_OMAP_MUX
static struct omap_board_mux board_mux[] __initdata = {
+ /* SMSC9221 LAN Controller ETH IRQ (GPIO_176) */
+ OMAP3_MUX(MCSPI1_CS2, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
{ .reg_offset = OMAP_MUX_TERMINATOR },
};
#endif
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index ef9e829..c37c2a1 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -35,7 +35,6 @@
#include <asm/mach/map.h>
#include <plat/mcspi.h>
-#include <plat/board.h>
#include "common.h"
#include <plat/gpmc.h>
#include <mach/board-zoom.h>
diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index 677357f..5397209 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -25,7 +25,6 @@
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
-#include <plat/board.h>
#include "common.h"
#include <plat/menelaus.h>
#include <mach/irqs.h>
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 6202fc7..293e3b2 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -39,7 +39,6 @@
#include <asm/mach/map.h>
#include <asm/mach/flash.h>
-#include <plat/board.h>
#include "common.h"
#include <video/omapdss.h>
#include <video/omap-panel-tfp410.h>
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index ef230a0..851aec6 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -45,7 +45,6 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
-#include <plat/board.h>
#include <plat/usb.h>
#include <plat/nand.h>
#include "common.h"
@@ -58,6 +57,7 @@
#include "hsmmc.h"
#include "common-board-devices.h"
+#define OMAP3_EVM_TS_GPIO 175
#define OMAP3_EVM_EHCI_VBUS 22
#define OMAP3_EVM_EHCI_SELECT 61
@@ -74,6 +74,18 @@
#define OMAP3EVM_GEN1_ETHR_GPIO_RST 64
#define OMAP3EVM_GEN2_ETHR_GPIO_RST 7
+/*
+ * OMAP35x EVM revision
+ * Run time detection of EVM revision is done by reading Ethernet
+ * PHY ID -
+ * GEN_1 = 0x01150000
+ * GEN_2 = 0x92200000
+ */
+enum {
+ OMAP3EVM_BOARD_GEN_1 = 0, /* EVM Rev between A - D */
+ OMAP3EVM_BOARD_GEN_2, /* EVM Rev >= Rev E */
+};
+
static u8 omap3_evm_version;
u8 get_omap3_evm_rev(void)
@@ -525,9 +537,6 @@
return 0;
}
-static struct omap_board_config_kernel omap3_evm_config[] __initdata = {
-};
-
static struct usbhs_omap_board_data usbhs_bdata __initdata = {
.port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
@@ -687,9 +696,6 @@
obm = (cpu_is_omap3630()) ? omap36x_board_mux : omap35x_board_mux;
omap3_mux_init(obm, OMAP_PACKAGE_CBB);
- omap_board_config = omap3_evm_config;
- omap_board_config_size = ARRAY_SIZE(omap3_evm_config);
-
omap_mux_init_gpio(63, OMAP_PIN_INPUT);
omap_hsmmc_init(mmc);
diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
index fca93d1..a63a49d 100644
--- a/arch/arm/mach-omap2/board-omap3logic.c
+++ b/arch/arm/mach-omap2/board-omap3logic.c
@@ -41,7 +41,6 @@
#include "common-board-devices.h"
#include <plat/mux.h>
-#include <plat/board.h>
#include "common.h"
#include <plat/gpmc-smsc911x.h>
#include <plat/gpmc.h>
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index 57aebee..633c445 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -40,7 +40,6 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
-#include <plat/board.h>
#include "common.h"
#include <mach/hardware.h>
#include <plat/mcspi.h>
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index b318f56..421fb8e 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -35,7 +35,6 @@
#include <asm/mach/map.h>
#include <asm/mach/flash.h>
-#include <plat/board.h>
#include "common.h"
#include <plat/gpmc.h>
#include <plat/nand.h>
@@ -362,9 +361,6 @@
#define OMAP3_STALKER_TS_GPIO 175
-static struct omap_board_config_kernel omap3_stalker_config[] __initdata = {
-};
-
static struct platform_device *omap3_stalker_devices[] __initdata = {
&keys_gpio,
};
@@ -399,8 +395,6 @@
{
regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);
- omap_board_config = omap3_stalker_config;
- omap_board_config_size = ARRAY_SIZE(omap3_stalker_config);
omap_mux_init_gpio(23, OMAP_PIN_INPUT);
omap_hsmmc_init(mmc);
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index 485d14d..d3556c9 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -44,7 +44,6 @@
#include <asm/mach/flash.h>
#include <asm/system_info.h>
-#include <plat/board.h>
#include "common.h"
#include <plat/gpmc.h>
#include <plat/nand.h>
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 70f6d1d..3911c13 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -39,7 +39,6 @@
#include <asm/mach/map.h>
#include <video/omapdss.h>
-#include <plat/board.h>
#include "common.h"
#include <plat/usb.h>
#include <plat/mmc.h>
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 779734d..193d160 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -42,7 +42,6 @@
#include <asm/mach/flash.h>
#include <asm/mach/map.h>
-#include <plat/board.h>
#include "common.h"
#include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h>
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index df2534d..3b9fc61 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -28,7 +28,6 @@
#include <asm/system_info.h>
#include <plat/mcspi.h>
-#include <plat/board.h>
#include "common.h"
#include <plat/dma.h>
#include <plat/gpmc.h>
diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c
index 345dd93..92924eb 100644
--- a/arch/arm/mach-omap2/board-rx51.c
+++ b/arch/arm/mach-omap2/board-rx51.c
@@ -24,7 +24,6 @@
#include <asm/mach/map.h>
#include <plat/mcspi.h>
-#include <plat/board.h>
#include "common.h"
#include <plat/dma.h>
#include <plat/gpmc.h>
diff --git a/arch/arm/mach-omap2/board-ti8168evm.c b/arch/arm/mach-omap2/board-ti8168evm.c
index d4c8392..da4679d 100644
--- a/arch/arm/mach-omap2/board-ti8168evm.c
+++ b/arch/arm/mach-omap2/board-ti8168evm.c
@@ -21,7 +21,6 @@
#include <asm/mach/map.h>
#include <plat/irqs.h>
-#include <plat/board.h>
#include "common.h"
#include <plat/usb.h>
@@ -32,15 +31,10 @@
.power = 500,
};
-static struct omap_board_config_kernel ti81xx_evm_config[] __initdata = {
-};
-
static void __init ti81xx_evm_init(void)
{
omap_serial_init();
omap_sdrc_init(NULL, NULL);
- omap_board_config = ti81xx_evm_config;
- omap_board_config_size = ARRAY_SIZE(ti81xx_evm_config);
usb_musb_init(&musb_board_data);
}
diff --git a/arch/arm/mach-omap2/board-zoom.c b/arch/arm/mach-omap2/board-zoom.c
index 4e7e561..4994438 100644
--- a/arch/arm/mach-omap2/board-zoom.c
+++ b/arch/arm/mach-omap2/board-zoom.c
@@ -22,7 +22,6 @@
#include <asm/mach/arch.h>
#include "common.h"
-#include <plat/board.h>
#include <plat/usb.h>
#include <mach/board-zoom.h>
diff --git a/arch/arm/mach-omap2/common-board-devices.c b/arch/arm/mach-omap2/common-board-devices.c
index 1473474..c187586 100644
--- a/arch/arm/mach-omap2/common-board-devices.c
+++ b/arch/arm/mach-omap2/common-board-devices.c
@@ -35,16 +35,6 @@
.turbo_mode = 0,
};
-/*
- * ADS7846 driver maybe request a gpio according to the value
- * of pdata->get_pendown_state, but we have done this. So set
- * get_pendown_state to avoid twice gpio requesting.
- */
-static int omap3_get_pendown_state(void)
-{
- return !gpio_get_value(OMAP3_EVM_TS_GPIO);
-}
-
static struct ads7846_platform_data ads7846_config = {
.x_max = 0x0fff,
.y_max = 0x0fff,
@@ -55,7 +45,6 @@
.debounce_rep = 1,
.gpio_pendown = -EINVAL,
.keep_vref_on = 1,
- .get_pendown_state = &omap3_get_pendown_state,
};
static struct spi_board_info ads7846_spi_board_info __initdata = {
diff --git a/arch/arm/mach-omap2/common-board-devices.h b/arch/arm/mach-omap2/common-board-devices.h
index 4c4ef6a..a0b4a428 100644
--- a/arch/arm/mach-omap2/common-board-devices.h
+++ b/arch/arm/mach-omap2/common-board-devices.h
@@ -4,7 +4,6 @@
#include "twl-common.h"
#define NAND_BLOCK_SIZE SZ_128K
-#define OMAP3_EVM_TS_GPIO 175
struct mtd_partition;
struct ads7846_platform_data;
diff --git a/arch/arm/mach-omap2/common.c b/arch/arm/mach-omap2/common.c
index 069f972..6c2ff4f 100644
--- a/arch/arm/mach-omap2/common.c
+++ b/arch/arm/mach-omap2/common.c
@@ -18,7 +18,6 @@
#include <linux/io.h>
#include <plat/hardware.h>
-#include <plat/board.h>
#include <plat/mux.h>
#include <plat/clock.h>
diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
index ee05e19..288bee6 100644
--- a/arch/arm/mach-omap2/cpuidle44xx.c
+++ b/arch/arm/mach-omap2/cpuidle44xx.c
@@ -238,8 +238,9 @@
for_each_cpu(cpu_id, cpu_online_mask) {
dev = &per_cpu(omap4_idle_dev, cpu_id);
dev->cpu = cpu_id;
+#ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED
dev->coupled_cpus = *cpu_online_mask;
-
+#endif
cpuidle_register_driver(&omap4_idle_driver);
if (cpuidle_register_device(dev)) {
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index c00c689..56dfa2df 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -26,7 +26,6 @@
#include <asm/pmu.h>
#include "iomap.h"
-#include <plat/board.h>
#include <plat/dma.h>
#include <plat/omap_hwmod.h>
#include <plat/omap_device.h>
diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index 045596a..96fcc641 100644
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -18,7 +18,6 @@
#include <plat/cpu.h>
#include <plat/nand.h>
-#include <plat/board.h>
#include <plat/gpmc.h>
static struct resource gpmc_nand_resource[] = {
diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
index 71d7c07..b12a39e 100644
--- a/arch/arm/mach-omap2/gpmc-onenand.c
+++ b/arch/arm/mach-omap2/gpmc-onenand.c
@@ -20,7 +20,6 @@
#include <plat/cpu.h>
#include <plat/onenand.h>
-#include <plat/board.h>
#include <plat/gpmc.h>
#define ONENAND_IO_SIZE SZ_128K
diff --git a/arch/arm/mach-omap2/gpmc-smc91x.c b/arch/arm/mach-omap2/gpmc-smc91x.c
index ba10c24..3f75ff0 100644
--- a/arch/arm/mach-omap2/gpmc-smc91x.c
+++ b/arch/arm/mach-omap2/gpmc-smc91x.c
@@ -17,7 +17,6 @@
#include <linux/io.h>
#include <linux/smc91x.h>
-#include <plat/board.h>
#include <plat/gpmc.h>
#include <plat/gpmc-smc91x.h>
diff --git a/arch/arm/mach-omap2/gpmc-smsc911x.c b/arch/arm/mach-omap2/gpmc-smsc911x.c
index b6c77be..a3a2887 100644
--- a/arch/arm/mach-omap2/gpmc-smsc911x.c
+++ b/arch/arm/mach-omap2/gpmc-smsc911x.c
@@ -20,7 +20,6 @@
#include <linux/io.h>
#include <linux/smsc911x.h>
-#include <plat/board.h>
#include <plat/gpmc.h>
#include <plat/gpmc-smsc911x.h>
diff --git a/arch/arm/mach-omap2/mux.h b/arch/arm/mach-omap2/mux.h
index 471e62a7..76f9b3c 100644
--- a/arch/arm/mach-omap2/mux.h
+++ b/arch/arm/mach-omap2/mux.h
@@ -127,7 +127,6 @@
* @gpio: GPIO number
* @muxnames: available signal modes for a ball
* @balls: available balls on the package
- * @partition: mux partition
*/
struct omap_mux {
u16 reg_offset;
diff --git a/arch/arm/mach-omap2/opp4xxx_data.c b/arch/arm/mach-omap2/opp4xxx_data.c
index 2293ba2..c95415d 100644
--- a/arch/arm/mach-omap2/opp4xxx_data.c
+++ b/arch/arm/mach-omap2/opp4xxx_data.c
@@ -94,7 +94,7 @@
{
int r = -ENODEV;
- if (!cpu_is_omap44xx())
+ if (!cpu_is_omap443x())
return r;
r = omap_init_opp_table(omap44xx_opp_def_list,
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 814bcd9..3e1345f 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -28,7 +28,6 @@
#include <linux/slab.h>
#include <plat/clock.h>
-#include <plat/board.h>
#include "powerdomain.h"
#include "clockdomain.h"
#include <plat/dmtimer.h>
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index 2edeffc..de1caf1 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -38,7 +38,6 @@
#include <plat/clock.h>
#include <plat/sram.h>
#include <plat/dma.h>
-#include <plat/board.h>
#include <mach/irqs.h>
@@ -352,16 +351,6 @@
prcm_setup_regs();
- /* Hack to prevent MPU retention when STI console is enabled. */
- {
- const struct omap_sti_console_config *sti;
-
- sti = omap_get_config(OMAP_TAG_STI_CONSOLE,
- struct omap_sti_console_config);
- if (sti != NULL && sti->enable)
- sti_console_enabled = 1;
- }
-
/*
* We copy the assembler sleep/wakeup routines to SRAM.
* These routines need to be in SRAM as that's the only
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index e4fc88c..05bd8f0 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -272,21 +272,16 @@
per_next_state = pwrdm_read_next_pwrst(per_pwrdm);
core_next_state = pwrdm_read_next_pwrst(core_pwrdm);
- if (mpu_next_state < PWRDM_POWER_ON) {
- pwrdm_pre_transition(mpu_pwrdm);
- pwrdm_pre_transition(neon_pwrdm);
- }
+ pwrdm_pre_transition(NULL);
/* PER */
if (per_next_state < PWRDM_POWER_ON) {
- pwrdm_pre_transition(per_pwrdm);
per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0;
omap2_gpio_prepare_for_idle(per_going_off);
}
/* CORE */
if (core_next_state < PWRDM_POWER_ON) {
- pwrdm_pre_transition(core_pwrdm);
if (core_next_state == PWRDM_POWER_OFF) {
omap3_core_save_context();
omap3_cm_save_context();
@@ -339,20 +334,14 @@
omap2_prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF_MASK,
OMAP3430_GR_MOD,
OMAP3_PRM_VOLTCTRL_OFFSET);
- pwrdm_post_transition(core_pwrdm);
}
omap3_intc_resume_idle();
- /* PER */
- if (per_next_state < PWRDM_POWER_ON) {
- omap2_gpio_resume_after_idle();
- pwrdm_post_transition(per_pwrdm);
- }
+ pwrdm_post_transition(NULL);
- if (mpu_next_state < PWRDM_POWER_ON) {
- pwrdm_post_transition(mpu_pwrdm);
- pwrdm_post_transition(neon_pwrdm);
- }
+ /* PER */
+ if (per_next_state < PWRDM_POWER_ON)
+ omap2_gpio_resume_after_idle();
}
static void omap3_pm_idle(void)
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index c1b93c7..d77f018 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -29,7 +29,6 @@
#include <plat/omap-serial.h>
#include "common.h"
-#include <plat/board.h>
#include <plat/dma.h>
#include <plat/omap_hwmod.h>
#include <plat/omap_device.h>
@@ -81,8 +80,9 @@
};
#ifdef CONFIG_PM
-static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable)
+static void omap_uart_enable_wakeup(struct device *dev, bool enable)
{
+ struct platform_device *pdev = to_platform_device(dev);
struct omap_device *od = to_omap_device(pdev);
if (!od)
@@ -99,15 +99,17 @@
* in Smartidle Mode When Configured for DMA Operations.
* WA: configure uart in force idle mode.
*/
-static void omap_uart_set_noidle(struct platform_device *pdev)
+static void omap_uart_set_noidle(struct device *dev)
{
+ struct platform_device *pdev = to_platform_device(dev);
struct omap_device *od = to_omap_device(pdev);
omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_NO);
}
-static void omap_uart_set_smartidle(struct platform_device *pdev)
+static void omap_uart_set_smartidle(struct device *dev)
{
+ struct platform_device *pdev = to_platform_device(dev);
struct omap_device *od = to_omap_device(pdev);
u8 idlemode;
@@ -120,10 +122,10 @@
}
#else
-static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable)
+static void omap_uart_enable_wakeup(struct device *dev, bool enable)
{}
-static void omap_uart_set_noidle(struct platform_device *pdev) {}
-static void omap_uart_set_smartidle(struct platform_device *pdev) {}
+static void omap_uart_set_noidle(struct device *dev) {}
+static void omap_uart_set_smartidle(struct device *dev) {}
#endif /* CONFIG_PM */
#ifdef CONFIG_OMAP_MUX
@@ -304,6 +306,9 @@
omap_up.dma_rx_timeout = info->dma_rx_timeout;
omap_up.dma_rx_poll_rate = info->dma_rx_poll_rate;
omap_up.autosuspend_timeout = info->autosuspend_timeout;
+ omap_up.DTR_gpio = info->DTR_gpio;
+ omap_up.DTR_inverted = info->DTR_inverted;
+ omap_up.DTR_present = info->DTR_present;
pdata = &omap_up;
pdata_size = sizeof(struct omap_uart_port_info);
diff --git a/arch/arm/mach-omap2/sleep44xx.S b/arch/arm/mach-omap2/sleep44xx.S
index 9f6b83d..91e71d8 100644
--- a/arch/arm/mach-omap2/sleep44xx.S
+++ b/arch/arm/mach-omap2/sleep44xx.S
@@ -56,9 +56,13 @@
* The restore function pointer is stored at CPUx_WAKEUP_NS_PA_ADDR_OFFSET.
* It returns to the caller for CPU INACTIVE and ON power states or in case
* CPU failed to transition to targeted OFF/DORMANT state.
+ *
+ * omap4_finish_suspend() calls v7_flush_dcache_all() which doesn't save
+ * stack frame and it expects the caller to take care of it. Hence the entire
+ * stack frame is saved to avoid possible stack corruption.
*/
ENTRY(omap4_finish_suspend)
- stmfd sp!, {lr}
+ stmfd sp!, {r4-r12, lr}
cmp r0, #0x0
beq do_WFI @ No lowpower state, jump to WFI
@@ -226,7 +230,7 @@
skip_scu_gp_clear:
isb
dsb
- ldmfd sp!, {pc}
+ ldmfd sp!, {r4-r12, pc}
ENDPROC(omap4_finish_suspend)
/*
diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c
index de47f17..db5ff66 100644
--- a/arch/arm/mach-omap2/twl-common.c
+++ b/arch/arm/mach-omap2/twl-common.c
@@ -67,6 +67,7 @@
const char *pmic_type, int pmic_irq,
struct twl4030_platform_data *pmic_data)
{
+ omap_mux_init_signal("sys_nirq", OMAP_PIN_INPUT_PULLUP | OMAP_PIN_OFF_WAKEUPENABLE);
strncpy(pmic_i2c_board_info.type, pmic_type,
sizeof(pmic_i2c_board_info.type));
pmic_i2c_board_info.irq = pmic_irq;
diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c
index 9148b22..410291c 100644
--- a/arch/arm/mach-orion5x/common.c
+++ b/arch/arm/mach-orion5x/common.c
@@ -109,7 +109,8 @@
{
orion_ge00_init(eth_data,
ORION5X_ETH_PHYS_BASE, IRQ_ORION5X_ETH_SUM,
- IRQ_ORION5X_ETH_ERR);
+ IRQ_ORION5X_ETH_ERR,
+ MV643XX_TX_CSUM_DEFAULT_LIMIT);
}
diff --git a/arch/arm/mach-s3c24xx/include/mach/dma.h b/arch/arm/mach-s3c24xx/include/mach/dma.h
index 454831b..ee99fd5 100644
--- a/arch/arm/mach-s3c24xx/include/mach/dma.h
+++ b/arch/arm/mach-s3c24xx/include/mach/dma.h
@@ -24,7 +24,8 @@
*/
enum dma_ch {
- DMACH_XD0,
+ DMACH_DT_PROP = -1, /* not yet supported, do not use */
+ DMACH_XD0 = 0,
DMACH_XD1,
DMACH_SDI,
DMACH_SPI0,
diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
index cf10f92..453a6e5 100644
--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
@@ -520,13 +520,14 @@
};
/* GPIO KEY */
-#define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 }
+#define GPIO_KEY(c, g, d, ...) \
+ { .code = c, .gpio = g, .desc = d, .active_low = 1, __VA_ARGS__ }
static struct gpio_keys_button gpio_buttons[] = {
- GPIO_KEY(KEY_POWER, GPIO_PORT99, "SW1"),
- GPIO_KEY(KEY_BACK, GPIO_PORT100, "SW2"),
- GPIO_KEY(KEY_MENU, GPIO_PORT97, "SW3"),
- GPIO_KEY(KEY_HOME, GPIO_PORT98, "SW4"),
+ GPIO_KEY(KEY_POWER, GPIO_PORT99, "SW3", .wakeup = 1),
+ GPIO_KEY(KEY_BACK, GPIO_PORT100, "SW4"),
+ GPIO_KEY(KEY_MENU, GPIO_PORT97, "SW5"),
+ GPIO_KEY(KEY_HOME, GPIO_PORT98, "SW6"),
};
static struct gpio_keys_platform_data gpio_key_info = {
@@ -901,8 +902,8 @@
&camera_device,
&ceu0_device,
&fsi_device,
- &fsi_hdmi_device,
&fsi_wm8978_device,
+ &fsi_hdmi_device,
};
static void __init eva_clock_init(void)
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index 7ea2b31..c129542 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -695,6 +695,7 @@
* - J30 "open"
* - modify usbhs1_get_id() USBHS_HOST -> USBHS_GADGET
* - add .get_vbus = usbhs_get_vbus in usbhs1_private
+ * - check usbhs0_device(pio)/usbhs1_device(irq) order in mackerel_devices.
*/
#define IRQ8 evt2irq(0x0300)
#define USB_PHY_MODE (1 << 4)
@@ -1325,8 +1326,8 @@
&nor_flash_device,
&smc911x_device,
&lcdc_device,
- &usbhs1_device,
&usbhs0_device,
+ &usbhs1_device,
&leds_device,
&fsi_device,
&fsi_ak4643_device,
diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c
index 3a528cf..fcf5a47 100644
--- a/arch/arm/mach-shmobile/board-marzen.c
+++ b/arch/arm/mach-shmobile/board-marzen.c
@@ -67,7 +67,7 @@
static struct platform_device eth_device = {
.name = "smsc911x",
- .id = 0,
+ .id = -1,
.dev = {
.platform_data = &smsc911x_platdata,
},
diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c
index ee44740..588555a 100644
--- a/arch/arm/mach-shmobile/intc-sh73a0.c
+++ b/arch/arm/mach-shmobile/intc-sh73a0.c
@@ -259,9 +259,9 @@
return 0; /* always allow wakeup */
}
-#define RELOC_BASE 0x1000
+#define RELOC_BASE 0x1200
-/* INTCA IRQ pins at INTCS + 0x1000 to make space for GIC+INTC handling */
+/* INTCA IRQ pins at INTCS + RELOC_BASE to make space for GIC+INTC handling */
#define INTCS_VECT_RELOC(n, vect) INTCS_VECT((n), (vect) + RELOC_BASE)
INTC_IRQ_PINS_32(intca_irq_pins, 0xe6900000,
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig
index c013bbf..53d3d46 100644
--- a/arch/arm/mach-ux500/Kconfig
+++ b/arch/arm/mach-ux500/Kconfig
@@ -41,7 +41,6 @@
config MACH_SNOWBALL
bool "U8500 Snowball platform"
select MACH_MOP500
- select LEDS_GPIO
help
Include support for the snowball development platform.
diff --git a/arch/arm/mach-ux500/board-mop500-msp.c b/arch/arm/mach-ux500/board-mop500-msp.c
index 9960480..df15646 100644
--- a/arch/arm/mach-ux500/board-mop500-msp.c
+++ b/arch/arm/mach-ux500/board-mop500-msp.c
@@ -191,9 +191,9 @@
return pdev;
}
-/* Platform device for ASoC U8500 machine */
-static struct platform_device snd_soc_u8500 = {
- .name = "snd-soc-u8500",
+/* Platform device for ASoC MOP500 machine */
+static struct platform_device snd_soc_mop500 = {
+ .name = "snd-soc-mop500",
.id = 0,
.dev = {
.platform_data = NULL,
@@ -227,8 +227,8 @@
{
struct platform_device *msp1;
- pr_info("%s: Register platform-device 'snd-soc-u8500'.\n", __func__);
- platform_device_register(&snd_soc_u8500);
+ pr_info("%s: Register platform-device 'snd-soc-mop500'.\n", __func__);
+ platform_device_register(&snd_soc_mop500);
pr_info("Initialize MSP I2S-devices.\n");
db8500_add_msp_i2s(parent, 0, U8500_MSP0_BASE, IRQ_DB8500_MSP0,
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index 8674a89..1d2e3c6 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -524,33 +524,12 @@
};
#endif
-#define PRCC_K_SOFTRST_SET 0x18
-#define PRCC_K_SOFTRST_CLEAR 0x1C
-static void ux500_uart0_reset(void)
-{
- void __iomem *prcc_rst_set, *prcc_rst_clr;
-
- prcc_rst_set = (void __iomem *)IO_ADDRESS(U8500_CLKRST1_BASE +
- PRCC_K_SOFTRST_SET);
- prcc_rst_clr = (void __iomem *)IO_ADDRESS(U8500_CLKRST1_BASE +
- PRCC_K_SOFTRST_CLEAR);
-
- /* Activate soft reset PRCC_K_SOFTRST_CLEAR */
- writel((readl(prcc_rst_clr) | 0x1), prcc_rst_clr);
- udelay(1);
-
- /* Release soft reset PRCC_K_SOFTRST_SET */
- writel((readl(prcc_rst_set) | 0x1), prcc_rst_set);
- udelay(1);
-}
-
static struct amba_pl011_data uart0_plat = {
#ifdef CONFIG_STE_DMA40
.dma_filter = stedma40_filter,
.dma_rx_param = &uart0_dma_cfg_rx,
.dma_tx_param = &uart0_dma_cfg_tx,
#endif
- .reset = ux500_uart0_reset,
};
static struct amba_pl011_data uart1_plat = {
@@ -797,6 +776,7 @@
ARRAY_SIZE(mop500_platform_devs));
mop500_sdi_init(parent);
+ mop500_msp_init(parent);
i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs);
i2c_register_board_info(2, mop500_i2c2_devices,
@@ -804,6 +784,8 @@
mop500_uib_init();
+ } else if (of_machine_is_compatible("calaosystems,snowball-a9500")) {
+ mop500_msp_init(parent);
} else if (of_machine_is_compatible("st-ericsson,hrefv60+")) {
/*
* The HREFv60 board removed a GPIO expander and routed
@@ -815,6 +797,7 @@
ARRAY_SIZE(mop500_platform_devs));
hrefv60_sdi_init(parent);
+ mop500_msp_init(parent);
i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES;
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 4e7d118..051204f 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -267,17 +267,19 @@
vunmap(cpu_addr);
}
+#define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_256K
+
struct dma_pool {
size_t size;
spinlock_t lock;
unsigned long *bitmap;
unsigned long nr_pages;
void *vaddr;
- struct page *page;
+ struct page **pages;
};
static struct dma_pool atomic_pool = {
- .size = SZ_256K,
+ .size = DEFAULT_DMA_COHERENT_POOL_SIZE,
};
static int __init early_coherent_pool(char *p)
@@ -287,6 +289,21 @@
}
early_param("coherent_pool", early_coherent_pool);
+void __init init_dma_coherent_pool_size(unsigned long size)
+{
+ /*
+ * Catch any attempt to set the pool size too late.
+ */
+ BUG_ON(atomic_pool.vaddr);
+
+ /*
+ * Set architecture specific coherent pool size only if
+ * it has not been changed by kernel command line parameter.
+ */
+ if (atomic_pool.size == DEFAULT_DMA_COHERENT_POOL_SIZE)
+ atomic_pool.size = size;
+}
+
/*
* Initialise the coherent pool for atomic allocations.
*/
@@ -297,6 +314,7 @@
unsigned long nr_pages = pool->size >> PAGE_SHIFT;
unsigned long *bitmap;
struct page *page;
+ struct page **pages;
void *ptr;
int bitmap_size = BITS_TO_LONGS(nr_pages) * sizeof(long);
@@ -304,21 +322,31 @@
if (!bitmap)
goto no_bitmap;
+ pages = kzalloc(nr_pages * sizeof(struct page *), GFP_KERNEL);
+ if (!pages)
+ goto no_pages;
+
if (IS_ENABLED(CONFIG_CMA))
ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page);
else
ptr = __alloc_remap_buffer(NULL, pool->size, GFP_KERNEL, prot,
&page, NULL);
if (ptr) {
+ int i;
+
+ for (i = 0; i < nr_pages; i++)
+ pages[i] = page + i;
+
spin_lock_init(&pool->lock);
pool->vaddr = ptr;
- pool->page = page;
+ pool->pages = pages;
pool->bitmap = bitmap;
pool->nr_pages = nr_pages;
pr_info("DMA: preallocated %u KiB pool for atomic coherent allocations\n",
(unsigned)pool->size / 1024);
return 0;
}
+no_pages:
kfree(bitmap);
no_bitmap:
pr_err("DMA: failed to allocate %u KiB pool for atomic coherent allocation\n",
@@ -443,27 +471,45 @@
if (pageno < pool->nr_pages) {
bitmap_set(pool->bitmap, pageno, count);
ptr = pool->vaddr + PAGE_SIZE * pageno;
- *ret_page = pool->page + pageno;
+ *ret_page = pool->pages[pageno];
+ } else {
+ pr_err_once("ERROR: %u KiB atomic DMA coherent pool is too small!\n"
+ "Please increase it with coherent_pool= kernel parameter!\n",
+ (unsigned)pool->size / 1024);
}
spin_unlock_irqrestore(&pool->lock, flags);
return ptr;
}
+static bool __in_atomic_pool(void *start, size_t size)
+{
+ struct dma_pool *pool = &atomic_pool;
+ void *end = start + size;
+ void *pool_start = pool->vaddr;
+ void *pool_end = pool->vaddr + pool->size;
+
+ if (start < pool_start || start > pool_end)
+ return false;
+
+ if (end <= pool_end)
+ return true;
+
+ WARN(1, "Wrong coherent size(%p-%p) from atomic pool(%p-%p)\n",
+ start, end - 1, pool_start, pool_end - 1);
+
+ return false;
+}
+
static int __free_from_pool(void *start, size_t size)
{
struct dma_pool *pool = &atomic_pool;
unsigned long pageno, count;
unsigned long flags;
- if (start < pool->vaddr || start > pool->vaddr + pool->size)
+ if (!__in_atomic_pool(start, size))
return 0;
- if (start + size > pool->vaddr + pool->size) {
- WARN(1, "freeing wrong coherent size from pool\n");
- return 0;
- }
-
pageno = (start - pool->vaddr) >> PAGE_SHIFT;
count = size >> PAGE_SHIFT;
@@ -1090,10 +1136,22 @@
return 0;
}
+static struct page **__atomic_get_pages(void *addr)
+{
+ struct dma_pool *pool = &atomic_pool;
+ struct page **pages = pool->pages;
+ int offs = (addr - pool->vaddr) >> PAGE_SHIFT;
+
+ return pages + offs;
+}
+
static struct page **__iommu_get_pages(void *cpu_addr, struct dma_attrs *attrs)
{
struct vm_struct *area;
+ if (__in_atomic_pool(cpu_addr, PAGE_SIZE))
+ return __atomic_get_pages(cpu_addr);
+
if (dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs))
return cpu_addr;
@@ -1103,6 +1161,34 @@
return NULL;
}
+static void *__iommu_alloc_atomic(struct device *dev, size_t size,
+ dma_addr_t *handle)
+{
+ struct page *page;
+ void *addr;
+
+ addr = __alloc_from_pool(size, &page);
+ if (!addr)
+ return NULL;
+
+ *handle = __iommu_create_mapping(dev, &page, size);
+ if (*handle == DMA_ERROR_CODE)
+ goto err_mapping;
+
+ return addr;
+
+err_mapping:
+ __free_from_pool(addr, size);
+ return NULL;
+}
+
+static void __iommu_free_atomic(struct device *dev, struct page **pages,
+ dma_addr_t handle, size_t size)
+{
+ __iommu_remove_mapping(dev, handle, size);
+ __free_from_pool(page_address(pages[0]), size);
+}
+
static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
{
@@ -1113,6 +1199,9 @@
*handle = DMA_ERROR_CODE;
size = PAGE_ALIGN(size);
+ if (gfp & GFP_ATOMIC)
+ return __iommu_alloc_atomic(dev, size, handle);
+
pages = __iommu_alloc_buffer(dev, size, gfp);
if (!pages)
return NULL;
@@ -1179,6 +1268,11 @@
return;
}
+ if (__in_atomic_pool(cpu_addr, size)) {
+ __iommu_free_atomic(dev, pages, handle, size);
+ return;
+ }
+
if (!dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs)) {
unmap_kernel_range((unsigned long)cpu_addr, size);
vunmap(cpu_addr);
diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c
index 89a3723..e5778ed 100644
--- a/arch/arm/plat-omap/common.c
+++ b/arch/arm/plat-omap/common.c
@@ -17,52 +17,12 @@
#include <linux/dma-mapping.h>
#include <plat/common.h>
-#include <plat/board.h>
#include <plat/vram.h>
#include <plat/dsp.h>
#include <plat/dma.h>
#include <plat/omap-secure.h>
-
-#define NO_LENGTH_CHECK 0xffffffff
-
-struct omap_board_config_kernel *omap_board_config __initdata;
-int omap_board_config_size;
-
-static const void *__init get_config(u16 tag, size_t len,
- int skip, size_t *len_out)
-{
- struct omap_board_config_kernel *kinfo = NULL;
- int i;
-
- /* Try to find the config from the board-specific structures
- * in the kernel. */
- for (i = 0; i < omap_board_config_size; i++) {
- if (omap_board_config[i].tag == tag) {
- if (skip == 0) {
- kinfo = &omap_board_config[i];
- break;
- } else {
- skip--;
- }
- }
- }
- if (kinfo == NULL)
- return NULL;
- return kinfo->data;
-}
-
-const void *__init __omap_get_config(u16 tag, size_t len, int nr)
-{
- return get_config(tag, len, nr, NULL);
-}
-
-const void *__init omap_get_var_config(u16 tag, size_t *len)
-{
- return get_config(tag, NO_LENGTH_CHECK, 0, len);
-}
-
void __init omap_reserve(void)
{
omap_vram_reserve_sdram_memblock();
diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c
index dbf1e03..902d2ff 100644
--- a/arch/arm/plat-omap/counter_32k.c
+++ b/arch/arm/plat-omap/counter_32k.c
@@ -24,7 +24,6 @@
#include <plat/hardware.h>
#include <plat/common.h>
-#include <plat/board.h>
#include <plat/clock.h>
diff --git a/arch/arm/plat-omap/debug-devices.c b/arch/arm/plat-omap/debug-devices.c
index caa1f7b..c7a4c09 100644
--- a/arch/arm/plat-omap/debug-devices.c
+++ b/arch/arm/plat-omap/debug-devices.c
@@ -17,9 +17,6 @@
#include <mach/hardware.h>
-#include <plat/board.h>
-
-
/* Many OMAP development platforms reuse the same "debug board"; these
* platforms include H2, H3, H4, and Perseus2.
*/
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
index 1cba927..287ac37 100644
--- a/arch/arm/plat-omap/devices.c
+++ b/arch/arm/plat-omap/devices.c
@@ -23,7 +23,6 @@
#include <asm/memblock.h>
#include <plat/tc.h>
-#include <plat/board.h>
#include <plat/mmc.h>
#include <plat/menelaus.h>
#include <plat/omap44xx.h>
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 626ad8c..938b50a 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -189,6 +189,7 @@
timer->reserved = 1;
break;
}
+ spin_unlock_irqrestore(&dm_timer_lock, flags);
if (timer) {
ret = omap_dm_timer_prepare(timer);
@@ -197,7 +198,6 @@
timer = NULL;
}
}
- spin_unlock_irqrestore(&dm_timer_lock, flags);
if (!timer)
pr_debug("%s: timer request failed!\n", __func__);
@@ -220,6 +220,7 @@
break;
}
}
+ spin_unlock_irqrestore(&dm_timer_lock, flags);
if (timer) {
ret = omap_dm_timer_prepare(timer);
@@ -228,7 +229,6 @@
timer = NULL;
}
}
- spin_unlock_irqrestore(&dm_timer_lock, flags);
if (!timer)
pr_debug("%s: timer%d request failed!\n", __func__, id);
@@ -258,7 +258,7 @@
void omap_dm_timer_disable(struct omap_dm_timer *timer)
{
- pm_runtime_put(&timer->pdev->dev);
+ pm_runtime_put_sync(&timer->pdev->dev);
}
EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
index dd6f92c..bcbb9d5 100644
--- a/arch/arm/plat-omap/fb.c
+++ b/arch/arm/plat-omap/fb.c
@@ -33,8 +33,6 @@
#include <mach/hardware.h>
#include <asm/mach/map.h>
-#include <plat/board.h>
-
#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
static bool omapfb_lcd_configured;
diff --git a/arch/arm/plat-omap/include/plat/board.h b/arch/arm/plat-omap/include/plat/board.h
deleted file mode 100644
index e62f20a..0000000
--- a/arch/arm/plat-omap/include/plat/board.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/board.h
- *
- * Information structures for board-specific data
- *
- * Copyright (C) 2004 Nokia Corporation
- * Written by Juha Yrjölä <juha.yrjola@nokia.com>
- */
-
-#ifndef _OMAP_BOARD_H
-#define _OMAP_BOARD_H
-
-#include <linux/types.h>
-
-#include <plat/gpio-switch.h>
-
-/*
- * OMAP35x EVM revision
- * Run time detection of EVM revision is done by reading Ethernet
- * PHY ID -
- * GEN_1 = 0x01150000
- * GEN_2 = 0x92200000
- */
-enum {
- OMAP3EVM_BOARD_GEN_1 = 0, /* EVM Rev between A - D */
- OMAP3EVM_BOARD_GEN_2, /* EVM Rev >= Rev E */
-};
-
-/* Different peripheral ids */
-#define OMAP_TAG_CLOCK 0x4f01
-#define OMAP_TAG_GPIO_SWITCH 0x4f06
-#define OMAP_TAG_STI_CONSOLE 0x4f09
-#define OMAP_TAG_CAMERA_SENSOR 0x4f0a
-
-#define OMAP_TAG_BOOT_REASON 0x4f80
-#define OMAP_TAG_FLASH_PART 0x4f81
-#define OMAP_TAG_VERSION_STR 0x4f82
-
-struct omap_clock_config {
- /* 0 for 12 MHz, 1 for 13 MHz and 2 for 19.2 MHz */
- u8 system_clock_type;
-};
-
-struct omap_serial_console_config {
- u8 console_uart;
- u32 console_speed;
-};
-
-struct omap_sti_console_config {
- unsigned enable:1;
- u8 channel;
-};
-
-struct omap_camera_sensor_config {
- u16 reset_gpio;
- int (*power_on)(void * data);
- int (*power_off)(void * data);
-};
-
-struct omap_lcd_config {
- char panel_name[16];
- char ctrl_name[16];
- s16 nreset_gpio;
- u8 data_lines;
-};
-
-struct device;
-struct fb_info;
-struct omap_backlight_config {
- int default_intensity;
- int (*set_power)(struct device *dev, int state);
-};
-
-struct omap_fbmem_config {
- u32 start;
- u32 size;
-};
-
-struct omap_pwm_led_platform_data {
- const char *name;
- int intensity_timer;
- int blink_timer;
- void (*set_power)(struct omap_pwm_led_platform_data *self, int on_off);
-};
-
-struct omap_uart_config {
- /* Bit field of UARTs present; bit 0 --> UART1 */
- unsigned int enabled_uarts;
-};
-
-
-struct omap_flash_part_config {
- char part_table[0];
-};
-
-struct omap_boot_reason_config {
- char reason_str[12];
-};
-
-struct omap_version_config {
- char component[12];
- char version[12];
-};
-
-struct omap_board_config_entry {
- u16 tag;
- u16 len;
- u8 data[0];
-};
-
-struct omap_board_config_kernel {
- u16 tag;
- const void *data;
-};
-
-extern const void *__init __omap_get_config(u16 tag, size_t len, int nr);
-
-#define omap_get_config(tag, type) \
- ((const type *) __omap_get_config((tag), sizeof(type), 0))
-#define omap_get_nr_config(tag, type, nr) \
- ((const type *) __omap_get_config((tag), sizeof(type), (nr)))
-
-extern const void *__init omap_get_var_config(u16 tag, size_t *len);
-
-extern struct omap_board_config_kernel *omap_board_config;
-extern int omap_board_config_size;
-
-
-/* for TI reference platforms sharing the same debug card */
-extern int debug_card_init(u32 addr, unsigned gpio);
-
-/* OMAP3EVM revision */
-#if defined(CONFIG_MACH_OMAP3EVM)
-u8 get_omap3_evm_rev(void);
-#else
-#define get_omap3_evm_rev() (-EINVAL)
-#endif
-#endif
diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h
index 68b180e..bb5d08a 100644
--- a/arch/arm/plat-omap/include/plat/cpu.h
+++ b/arch/arm/plat-omap/include/plat/cpu.h
@@ -372,7 +372,8 @@
#define cpu_class_is_omap1() (cpu_is_omap7xx() || cpu_is_omap15xx() || \
cpu_is_omap16xx())
#define cpu_class_is_omap2() (cpu_is_omap24xx() || cpu_is_omap34xx() || \
- cpu_is_omap44xx() || soc_is_omap54xx())
+ cpu_is_omap44xx() || soc_is_omap54xx() || \
+ soc_is_am33xx())
/* Various silicon revisions for omap2 */
#define OMAP242X_CLASS 0x24200024
diff --git a/arch/arm/plat-omap/include/plat/debug-devices.h b/arch/arm/plat-omap/include/plat/debug-devices.h
new file mode 100644
index 0000000..a4edbd2
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/debug-devices.h
@@ -0,0 +1,9 @@
+#ifndef _OMAP_DEBUG_DEVICES_H
+#define _OMAP_DEBUG_DEVICES_H
+
+#include <linux/types.h>
+
+/* for TI reference platforms sharing the same debug card */
+extern int debug_card_init(u32 addr, unsigned gpio);
+
+#endif
diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h
index eb3e4d5..8b4e4f2 100644
--- a/arch/arm/plat-omap/include/plat/mmc.h
+++ b/arch/arm/plat-omap/include/plat/mmc.h
@@ -15,7 +15,6 @@
#include <linux/device.h>
#include <linux/mmc/host.h>
-#include <plat/board.h>
#include <plat/omap_hwmod.h>
#define OMAP15XX_NR_MMC 1
diff --git a/arch/arm/plat-omap/include/plat/multi.h b/arch/arm/plat-omap/include/plat/multi.h
index 045e320..324d31b 100644
--- a/arch/arm/plat-omap/include/plat/multi.h
+++ b/arch/arm/plat-omap/include/plat/multi.h
@@ -108,4 +108,13 @@
# endif
#endif
+#ifdef CONFIG_SOC_AM33XX
+# ifdef OMAP_NAME
+# undef MULTI_OMAP2
+# define MULTI_OMAP2
+# else
+# define OMAP_NAME am33xx
+# endif
+#endif
+
#endif /* __PLAT_OMAP_MULTI_H */
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h
index 1a52725..a531149 100644
--- a/arch/arm/plat-omap/include/plat/omap-serial.h
+++ b/arch/arm/plat-omap/include/plat/omap-serial.h
@@ -18,7 +18,7 @@
#define __OMAP_SERIAL_H__
#include <linux/serial_core.h>
-#include <linux/platform_device.h>
+#include <linux/device.h>
#include <linux/pm_qos.h>
#include <plat/mux.h>
@@ -42,10 +42,10 @@
#define OMAP_UART_WER_MOD_WKUP 0X7F
/* Enable XON/XOFF flow control on output */
-#define OMAP_UART_SW_TX 0x04
+#define OMAP_UART_SW_TX 0x8
/* Enable XON/XOFF flow control on input */
-#define OMAP_UART_SW_RX 0x04
+#define OMAP_UART_SW_RX 0x2
#define OMAP_UART_SYSC_RESET 0X07
#define OMAP_UART_TCR_TRIG 0X0F
@@ -69,11 +69,14 @@
unsigned int dma_rx_timeout;
unsigned int autosuspend_timeout;
unsigned int dma_rx_poll_rate;
+ int DTR_gpio;
+ int DTR_inverted;
+ int DTR_present;
int (*get_context_loss_count)(struct device *);
- void (*set_forceidle)(struct platform_device *);
- void (*set_noidle)(struct platform_device *);
- void (*enable_wakeup)(struct platform_device *, bool);
+ void (*set_forceidle)(struct device *);
+ void (*set_noidle)(struct device *);
+ void (*enable_wakeup)(struct device *, bool);
};
struct uart_omap_dma {
@@ -102,39 +105,4 @@
unsigned int rx_timeout;
};
-struct uart_omap_port {
- struct uart_port port;
- struct uart_omap_dma uart_dma;
- struct platform_device *pdev;
-
- unsigned char ier;
- unsigned char lcr;
- unsigned char mcr;
- unsigned char fcr;
- unsigned char efr;
- unsigned char dll;
- unsigned char dlh;
- unsigned char mdr1;
- unsigned char scr;
-
- int use_dma;
- /*
- * Some bits in registers are cleared on a read, so they must
- * be saved whenever the register is read but the bits will not
- * be immediately processed.
- */
- unsigned int lsr_break_flag;
- unsigned char msr_saved_flags;
- char name[20];
- unsigned long port_activity;
- u32 context_loss_cnt;
- u32 errata;
- u8 wakeups_enabled;
-
- struct pm_qos_request pm_qos_request;
- u32 latency;
- u32 calc_latency;
- struct work_struct qos_work;
-};
-
#endif /* __OMAP_SERIAL_H__ */
diff --git a/arch/arm/plat-omap/include/plat/uncompress.h b/arch/arm/plat-omap/include/plat/uncompress.h
index b8d19a1..7f7b112 100644
--- a/arch/arm/plat-omap/include/plat/uncompress.h
+++ b/arch/arm/plat-omap/include/plat/uncompress.h
@@ -110,7 +110,7 @@
_DEBUG_LL_ENTRY(mach, AM33XX_UART##p##_BASE, OMAP_PORT_SHIFT, \
AM33XXUART##p)
-static inline void __arch_decomp_setup(unsigned long arch_id)
+static inline void arch_decomp_setup(void)
{
int port = 0;
@@ -198,8 +198,6 @@
} while (0);
}
-#define arch_decomp_setup() __arch_decomp_setup(arch_id)
-
/*
* nothing to do
*/
diff --git a/arch/arm/plat-omap/include/plat/usb.h b/arch/arm/plat-omap/include/plat/usb.h
index 548a4c8..bd20588 100644
--- a/arch/arm/plat-omap/include/plat/usb.h
+++ b/arch/arm/plat-omap/include/plat/usb.h
@@ -5,7 +5,6 @@
#include <linux/io.h>
#include <linux/usb/musb.h>
-#include <plat/board.h>
#define OMAP3_HS_USB_PORTS 3
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index 766181c..d861aa7 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -26,7 +26,6 @@
#include <asm/mach/map.h>
#include <plat/sram.h>
-#include <plat/board.h>
#include <plat/cpu.h>
#include "sram.h"
diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c
index d245a87..b8b747a 100644
--- a/arch/arm/plat-orion/common.c
+++ b/arch/arm/plat-orion/common.c
@@ -291,10 +291,12 @@
void __init orion_ge00_init(struct mv643xx_eth_platform_data *eth_data,
unsigned long mapbase,
unsigned long irq,
- unsigned long irq_err)
+ unsigned long irq_err,
+ unsigned int tx_csum_limit)
{
fill_resources(&orion_ge00_shared, orion_ge00_shared_resources,
mapbase + 0x2000, SZ_16K - 1, irq_err);
+ orion_ge00_shared_data.tx_csum_limit = tx_csum_limit;
ge_complete(&orion_ge00_shared_data,
orion_ge00_resources, irq, &orion_ge00_shared,
eth_data, &orion_ge00);
@@ -343,10 +345,12 @@
void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data,
unsigned long mapbase,
unsigned long irq,
- unsigned long irq_err)
+ unsigned long irq_err,
+ unsigned int tx_csum_limit)
{
fill_resources(&orion_ge01_shared, orion_ge01_shared_resources,
mapbase + 0x2000, SZ_16K - 1, irq_err);
+ orion_ge01_shared_data.tx_csum_limit = tx_csum_limit;
ge_complete(&orion_ge01_shared_data,
orion_ge01_resources, irq, &orion_ge01_shared,
eth_data, &orion_ge01);
diff --git a/arch/arm/plat-orion/include/plat/common.h b/arch/arm/plat-orion/include/plat/common.h
index e00fdb2..ae2377e 100644
--- a/arch/arm/plat-orion/include/plat/common.h
+++ b/arch/arm/plat-orion/include/plat/common.h
@@ -39,12 +39,14 @@
void __init orion_ge00_init(struct mv643xx_eth_platform_data *eth_data,
unsigned long mapbase,
unsigned long irq,
- unsigned long irq_err);
+ unsigned long irq_err,
+ unsigned int tx_csum_limit);
void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data,
unsigned long mapbase,
unsigned long irq,
- unsigned long irq_err);
+ unsigned long irq_err,
+ unsigned int tx_csum_limit);
void __init orion_ge10_init(struct mv643xx_eth_platform_data *eth_data,
unsigned long mapbase,
diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c
index 28f898f..db98e70 100644
--- a/arch/arm/plat-s3c24xx/dma.c
+++ b/arch/arm/plat-s3c24xx/dma.c
@@ -430,7 +430,7 @@
* when necessary.
*/
-int s3c2410_dma_enqueue(unsigned int channel, void *id,
+int s3c2410_dma_enqueue(enum dma_ch channel, void *id,
dma_addr_t data, int size)
{
struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
index 74e31ce..fc49f3d 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -32,6 +32,8 @@
#include <linux/platform_data/s3c-hsudc.h>
#include <linux/platform_data/s3c-hsotg.h>
+#include <media/s5p_hdmi.h>
+
#include <asm/irq.h>
#include <asm/pmu.h>
#include <asm/mach/arch.h>
@@ -748,7 +750,8 @@
if (!pd) {
pd = &default_i2c_data;
- if (soc_is_exynos4210())
+ if (soc_is_exynos4210() ||
+ soc_is_exynos4212() || soc_is_exynos4412())
pd->bus_num = 8;
else if (soc_is_s5pv210())
pd->bus_num = 3;
@@ -759,6 +762,30 @@
npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
&s5p_device_i2c_hdmiphy);
}
+
+struct s5p_hdmi_platform_data s5p_hdmi_def_platdata;
+
+void __init s5p_hdmi_set_platdata(struct i2c_board_info *hdmiphy_info,
+ struct i2c_board_info *mhl_info, int mhl_bus)
+{
+ struct s5p_hdmi_platform_data *pd = &s5p_hdmi_def_platdata;
+
+ if (soc_is_exynos4210() ||
+ soc_is_exynos4212() || soc_is_exynos4412())
+ pd->hdmiphy_bus = 8;
+ else if (soc_is_s5pv210())
+ pd->hdmiphy_bus = 3;
+ else
+ pd->hdmiphy_bus = 0;
+
+ pd->hdmiphy_info = hdmiphy_info;
+ pd->mhl_info = mhl_info;
+ pd->mhl_bus = mhl_bus;
+
+ s3c_set_platdata(pd, sizeof(struct s5p_hdmi_platform_data),
+ &s5p_device_hdmi);
+}
+
#endif /* CONFIG_S5P_DEV_I2C_HDMIPHY */
/* I2S */
diff --git a/arch/arm/plat-samsung/include/plat/hdmi.h b/arch/arm/plat-samsung/include/plat/hdmi.h
new file mode 100644
index 0000000..331d046
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/hdmi.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics Co.Ltd
+ *
+ * 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 __PLAT_SAMSUNG_HDMI_H
+#define __PLAT_SAMSUNG_HDMI_H __FILE__
+
+extern void s5p_hdmi_set_platdata(struct i2c_board_info *hdmiphy_info,
+ struct i2c_board_info *mhl_info, int mhl_bus);
+
+#endif /* __PLAT_SAMSUNG_HDMI_H */
diff --git a/arch/arm/plat-samsung/pm.c b/arch/arm/plat-samsung/pm.c
index 64ab65f..1507028 100644
--- a/arch/arm/plat-samsung/pm.c
+++ b/arch/arm/plat-samsung/pm.c
@@ -74,7 +74,7 @@
#ifdef CONFIG_SAMSUNG_PM_DEBUG
-struct pm_uart_save uart_save[CONFIG_SERIAL_SAMSUNG_UARTS];
+static struct pm_uart_save uart_save[CONFIG_SERIAL_SAMSUNG_UARTS];
static void s3c_pm_save_uart(unsigned int uart, struct pm_uart_save *save)
{
diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
index c34785d..ec536e4 100644
--- a/arch/ia64/hp/sim/simserial.c
+++ b/arch/ia64/hp/sim/simserial.c
@@ -338,7 +338,7 @@
{
/* Handle turning off CRTSCTS */
if ((old_termios->c_cflag & CRTSCTS) &&
- !(tty->termios->c_cflag & CRTSCTS)) {
+ !(tty->termios.c_cflag & CRTSCTS)) {
tty->hw_stopped = 0;
}
}
@@ -545,6 +545,7 @@
/* the port is imaginary */
printk(KERN_INFO "ttyS0 at 0x03f8 (irq = %d) is a 16550\n", state->irq);
+ tty_port_link_device(&state->port, hp_simserial_driver, 0);
retval = tty_register_driver(hp_simserial_driver);
if (retval) {
printk(KERN_ERR "Couldn't register simserial driver\n");
diff --git a/arch/m68k/emu/nfcon.c b/arch/m68k/emu/nfcon.c
index 8db25e8..16d170f 100644
--- a/arch/m68k/emu/nfcon.c
+++ b/arch/m68k/emu/nfcon.c
@@ -19,6 +19,7 @@
#include <asm/natfeat.h>
static int stderr_id;
+static struct tty_port nfcon_tty_port;
static struct tty_driver *nfcon_tty_driver;
static void nfputs(const char *str, unsigned int count)
@@ -119,6 +120,8 @@
{
int res;
+ tty_port_init(&nfcon_tty_port);
+
stderr_id = nf_get_id("NF_STDERR");
if (!stderr_id)
return -ENODEV;
@@ -135,6 +138,7 @@
nfcon_tty_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(nfcon_tty_driver, &nfcon_tty_ops);
+ tty_port_link_device(&nfcon_tty_port, nfcon_tty_driver, 0);
res = tty_register_driver(nfcon_tty_driver);
if (res) {
pr_err("failed to register nfcon tty driver\n");
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 331d574..faf6528 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -89,6 +89,7 @@
select CEVT_R4K
select CSRC_R4K
select DMA_NONCOHERENT
+ select HAVE_CLK
select IRQ_CPU
select MIPS_MACHINE
select SYS_HAS_CPU_MIPS32_R2
diff --git a/arch/mips/alchemy/board-mtx1.c b/arch/mips/alchemy/board-mtx1.c
index 9996948..a124c25 100644
--- a/arch/mips/alchemy/board-mtx1.c
+++ b/arch/mips/alchemy/board-mtx1.c
@@ -228,6 +228,8 @@
* adapter on the mtx-1 "singleboard" variant. It triggers a custom
* logic chip connected to EXT_IO3 (GPIO1) to suppress IDSEL signals.
*/
+ udelay(1);
+
if (assert && devsel != 0)
/* Suppress signal to Cardbus */
alchemy_gpio_set_value(1, 0); /* set EXT_IO3 OFF */
diff --git a/arch/mips/ath79/dev-usb.c b/arch/mips/ath79/dev-usb.c
index 36e9570..b2a2311 100644
--- a/arch/mips/ath79/dev-usb.c
+++ b/arch/mips/ath79/dev-usb.c
@@ -145,6 +145,8 @@
ath79_ohci_resources[0].start = AR7240_OHCI_BASE;
ath79_ohci_resources[0].end = AR7240_OHCI_BASE + AR7240_OHCI_SIZE - 1;
+ ath79_ohci_resources[1].start = ATH79_CPU_IRQ_USB;
+ ath79_ohci_resources[1].end = ATH79_CPU_IRQ_USB;
platform_device_register(&ath79_ohci_device);
}
diff --git a/arch/mips/ath79/gpio.c b/arch/mips/ath79/gpio.c
index 29054f2..48fe762 100644
--- a/arch/mips/ath79/gpio.c
+++ b/arch/mips/ath79/gpio.c
@@ -188,8 +188,10 @@
if (soc_is_ar71xx())
ath79_gpio_count = AR71XX_GPIO_COUNT;
- else if (soc_is_ar724x())
- ath79_gpio_count = AR724X_GPIO_COUNT;
+ else if (soc_is_ar7240())
+ ath79_gpio_count = AR7240_GPIO_COUNT;
+ else if (soc_is_ar7241() || soc_is_ar7242())
+ ath79_gpio_count = AR7241_GPIO_COUNT;
else if (soc_is_ar913x())
ath79_gpio_count = AR913X_GPIO_COUNT;
else if (soc_is_ar933x())
diff --git a/arch/mips/bcm63xx/dev-spi.c b/arch/mips/bcm63xx/dev-spi.c
index e39f730..f1c9c3e 100644
--- a/arch/mips/bcm63xx/dev-spi.c
+++ b/arch/mips/bcm63xx/dev-spi.c
@@ -106,11 +106,15 @@
if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) {
spi_resources[0].end += BCM_6338_RSET_SPI_SIZE - 1;
spi_pdata.fifo_size = SPI_6338_MSG_DATA_SIZE;
+ spi_pdata.msg_type_shift = SPI_6338_MSG_TYPE_SHIFT;
+ spi_pdata.msg_ctl_width = SPI_6338_MSG_CTL_WIDTH;
}
if (BCMCPU_IS_6358() || BCMCPU_IS_6368()) {
spi_resources[0].end += BCM_6358_RSET_SPI_SIZE - 1;
spi_pdata.fifo_size = SPI_6358_MSG_DATA_SIZE;
+ spi_pdata.msg_type_shift = SPI_6358_MSG_TYPE_SHIFT;
+ spi_pdata.msg_ctl_width = SPI_6358_MSG_CTL_WIDTH;
}
bcm63xx_spi_regs_init();
diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c
index 7fb1f22..274cd4f 100644
--- a/arch/mips/cavium-octeon/octeon-irq.c
+++ b/arch/mips/cavium-octeon/octeon-irq.c
@@ -61,6 +61,12 @@
octeon_irq_ciu_to_irq[line][bit] = irq;
}
+static void octeon_irq_force_ciu_mapping(struct irq_domain *domain,
+ int irq, int line, int bit)
+{
+ irq_domain_associate(domain, irq, line << 6 | bit);
+}
+
static int octeon_coreid_for_cpu(int cpu)
{
#ifdef CONFIG_SMP
@@ -183,19 +189,9 @@
mutex_init(&cd->core_irq_mutex);
irq = OCTEON_IRQ_SW0 + i;
- switch (irq) {
- case OCTEON_IRQ_TIMER:
- case OCTEON_IRQ_SW0:
- case OCTEON_IRQ_SW1:
- case OCTEON_IRQ_5:
- case OCTEON_IRQ_PERF:
- irq_set_chip_data(irq, cd);
- irq_set_chip_and_handler(irq, &octeon_irq_chip_core,
- handle_percpu_irq);
- break;
- default:
- break;
- }
+ irq_set_chip_data(irq, cd);
+ irq_set_chip_and_handler(irq, &octeon_irq_chip_core,
+ handle_percpu_irq);
}
}
@@ -890,7 +886,6 @@
unsigned int type;
unsigned int pin;
unsigned int trigger;
- struct octeon_irq_gpio_domain_data *gpiod;
if (d->of_node != node)
return -EINVAL;
@@ -925,8 +920,7 @@
break;
}
*out_type = type;
- gpiod = d->host_data;
- *out_hwirq = gpiod->base_hwirq + pin;
+ *out_hwirq = pin;
return 0;
}
@@ -996,19 +990,21 @@
static int octeon_irq_gpio_map(struct irq_domain *d,
unsigned int virq, irq_hw_number_t hw)
{
- unsigned int line = hw >> 6;
- unsigned int bit = hw & 63;
+ struct octeon_irq_gpio_domain_data *gpiod = d->host_data;
+ unsigned int line, bit;
if (!octeon_irq_virq_in_range(virq))
return -EINVAL;
+ hw += gpiod->base_hwirq;
+ line = hw >> 6;
+ bit = hw & 63;
if (line > 1 || octeon_irq_ciu_to_irq[line][bit] != 0)
return -EINVAL;
octeon_irq_set_ciu_mapping(virq, line, bit,
octeon_irq_gpio_chip,
octeon_irq_handle_gpio);
-
return 0;
}
@@ -1149,6 +1145,7 @@
struct irq_chip *chip_wd;
struct device_node *gpio_node;
struct device_node *ciu_node;
+ struct irq_domain *ciu_domain = NULL;
octeon_irq_init_ciu_percpu();
octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu;
@@ -1177,31 +1174,6 @@
/* Mips internal */
octeon_irq_init_core();
- /* CIU_0 */
- for (i = 0; i < 16; i++)
- octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WORKQ0, 0, i + 0, chip, handle_level_irq);
-
- octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32, chip_mbox, handle_percpu_irq);
- octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33, chip_mbox, handle_percpu_irq);
-
- for (i = 0; i < 4; i++)
- octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_INT0, 0, i + 36, chip, handle_level_irq);
- for (i = 0; i < 4; i++)
- octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_MSI0, 0, i + 40, chip, handle_level_irq);
-
- octeon_irq_set_ciu_mapping(OCTEON_IRQ_RML, 0, 46, chip, handle_level_irq);
- for (i = 0; i < 4; i++)
- octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_TIMER0, 0, i + 52, chip, handle_edge_irq);
-
- octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB0, 0, 56, chip, handle_level_irq);
- octeon_irq_set_ciu_mapping(OCTEON_IRQ_BOOTDMA, 0, 63, chip, handle_level_irq);
-
- /* CIU_1 */
- for (i = 0; i < 16; i++)
- octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i + 0, chip_wd, handle_level_irq);
-
- octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB1, 1, 17, chip, handle_level_irq);
-
gpio_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-gpio");
if (gpio_node) {
struct octeon_irq_gpio_domain_data *gpiod;
@@ -1219,10 +1191,35 @@
ciu_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-ciu");
if (ciu_node) {
- irq_domain_add_tree(ciu_node, &octeon_irq_domain_ciu_ops, NULL);
+ ciu_domain = irq_domain_add_tree(ciu_node, &octeon_irq_domain_ciu_ops, NULL);
of_node_put(ciu_node);
} else
- pr_warn("Cannot find device node for cavium,octeon-3860-ciu.\n");
+ panic("Cannot find device node for cavium,octeon-3860-ciu.");
+
+ /* CIU_0 */
+ for (i = 0; i < 16; i++)
+ octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_WORKQ0, 0, i + 0);
+
+ octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32, chip_mbox, handle_percpu_irq);
+ octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33, chip_mbox, handle_percpu_irq);
+
+ for (i = 0; i < 4; i++)
+ octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_PCI_INT0, 0, i + 36);
+ for (i = 0; i < 4; i++)
+ octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_PCI_MSI0, 0, i + 40);
+
+ octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_RML, 0, 46);
+ for (i = 0; i < 4; i++)
+ octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_TIMER0, 0, i + 52);
+
+ octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_USB0, 0, 56);
+ octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_BOOTDMA, 0, 63);
+
+ /* CIU_1 */
+ for (i = 0; i < 16; i++)
+ octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i + 0, chip_wd, handle_level_irq);
+
+ octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_USB1, 1, 17);
/* Enable the CIU lines */
set_c0_status(STATUSF_IP3 | STATUSF_IP2);
diff --git a/arch/mips/cavium-octeon/serial.c b/arch/mips/cavium-octeon/serial.c
index 138b221..569f41b 100644
--- a/arch/mips/cavium-octeon/serial.c
+++ b/arch/mips/cavium-octeon/serial.c
@@ -47,40 +47,40 @@
{
int irq, res;
struct resource *res_mem;
- struct uart_port port;
+ struct uart_8250_port up;
/* All adaptors have an irq. */
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
- memset(&port, 0, sizeof(port));
+ memset(&up, 0, sizeof(up));
- port.flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
- port.type = PORT_OCTEON;
- port.iotype = UPIO_MEM;
- port.regshift = 3;
- port.dev = &pdev->dev;
+ up.port.flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
+ up.port.type = PORT_OCTEON;
+ up.port.iotype = UPIO_MEM;
+ up.port.regshift = 3;
+ up.port.dev = &pdev->dev;
if (octeon_is_simulation())
/* Make simulator output fast*/
- port.uartclk = 115200 * 16;
+ up.port.uartclk = 115200 * 16;
else
- port.uartclk = octeon_get_io_clock_rate();
+ up.port.uartclk = octeon_get_io_clock_rate();
- port.serial_in = octeon_serial_in;
- port.serial_out = octeon_serial_out;
- port.irq = irq;
+ up.port.serial_in = octeon_serial_in;
+ up.port.serial_out = octeon_serial_out;
+ up.port.irq = irq;
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res_mem == NULL) {
dev_err(&pdev->dev, "found no memory resource\n");
return -ENXIO;
}
- port.mapbase = res_mem->start;
- port.membase = ioremap(res_mem->start, resource_size(res_mem));
+ up.port.mapbase = res_mem->start;
+ up.port.membase = ioremap(res_mem->start, resource_size(res_mem));
- res = serial8250_register_port(&port);
+ res = serial8250_register_8250_port(&up);
return res >= 0 ? 0 : res;
}
diff --git a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
index 1caa78a..dde5044 100644
--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
+++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
@@ -393,7 +393,8 @@
#define AR71XX_GPIO_REG_FUNC 0x28
#define AR71XX_GPIO_COUNT 16
-#define AR724X_GPIO_COUNT 18
+#define AR7240_GPIO_COUNT 18
+#define AR7241_GPIO_COUNT 20
#define AR913X_GPIO_COUNT 22
#define AR933X_GPIO_COUNT 30
#define AR934X_GPIO_COUNT 23
diff --git a/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h
index 4476fa0..6ddae92 100644
--- a/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h
+++ b/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h
@@ -42,7 +42,6 @@
#define cpu_has_mips64r1 0
#define cpu_has_mips64r2 0
-#define cpu_has_dsp 0
#define cpu_has_mipsmt 0
#define cpu_has_64bits 0
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h
index 7d98dbe..c9bae13 100644
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h
@@ -9,6 +9,8 @@
struct bcm63xx_spi_pdata {
unsigned int fifo_size;
+ unsigned int msg_type_shift;
+ unsigned int msg_ctl_width;
int bus_num;
int num_chipselect;
u32 speed_hz;
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
index 4ccc2a7..61f2a2a 100644
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -1054,7 +1054,8 @@
#define SPI_6338_FILL_BYTE 0x07
#define SPI_6338_MSG_TAIL 0x09
#define SPI_6338_RX_TAIL 0x0b
-#define SPI_6338_MSG_CTL 0x40
+#define SPI_6338_MSG_CTL 0x40 /* 8-bits register */
+#define SPI_6338_MSG_CTL_WIDTH 8
#define SPI_6338_MSG_DATA 0x41
#define SPI_6338_MSG_DATA_SIZE 0x3f
#define SPI_6338_RX_DATA 0x80
@@ -1070,7 +1071,8 @@
#define SPI_6348_FILL_BYTE 0x07
#define SPI_6348_MSG_TAIL 0x09
#define SPI_6348_RX_TAIL 0x0b
-#define SPI_6348_MSG_CTL 0x40
+#define SPI_6348_MSG_CTL 0x40 /* 8-bits register */
+#define SPI_6348_MSG_CTL_WIDTH 8
#define SPI_6348_MSG_DATA 0x41
#define SPI_6348_MSG_DATA_SIZE 0x3f
#define SPI_6348_RX_DATA 0x80
@@ -1078,6 +1080,7 @@
/* BCM 6358 SPI core */
#define SPI_6358_MSG_CTL 0x00 /* 16-bits register */
+#define SPI_6358_MSG_CTL_WIDTH 16
#define SPI_6358_MSG_DATA 0x02
#define SPI_6358_MSG_DATA_SIZE 0x21e
#define SPI_6358_RX_DATA 0x400
@@ -1094,6 +1097,7 @@
/* BCM 6358 SPI core */
#define SPI_6368_MSG_CTL 0x00 /* 16-bits register */
+#define SPI_6368_MSG_CTL_WIDTH 16
#define SPI_6368_MSG_DATA 0x02
#define SPI_6368_MSG_DATA_SIZE 0x21e
#define SPI_6368_RX_DATA 0x400
@@ -1115,7 +1119,10 @@
#define SPI_HD_W 0x01
#define SPI_HD_R 0x02
#define SPI_BYTE_CNT_SHIFT 0
-#define SPI_MSG_TYPE_SHIFT 14
+#define SPI_6338_MSG_TYPE_SHIFT 6
+#define SPI_6348_MSG_TYPE_SHIFT 6
+#define SPI_6358_MSG_TYPE_SHIFT 14
+#define SPI_6368_MSG_TYPE_SHIFT 14
/* Command */
#define SPI_CMD_NOOP 0x00
diff --git a/arch/mips/include/asm/mach-cavium-octeon/irq.h b/arch/mips/include/asm/mach-cavium-octeon/irq.h
index 4189920..c22a307 100644
--- a/arch/mips/include/asm/mach-cavium-octeon/irq.h
+++ b/arch/mips/include/asm/mach-cavium-octeon/irq.h
@@ -21,14 +21,10 @@
OCTEON_IRQ_TIMER,
/* sources in CIU_INTX_EN0 */
OCTEON_IRQ_WORKQ0,
- OCTEON_IRQ_GPIO0 = OCTEON_IRQ_WORKQ0 + 16,
- OCTEON_IRQ_WDOG0 = OCTEON_IRQ_GPIO0 + 16,
+ OCTEON_IRQ_WDOG0 = OCTEON_IRQ_WORKQ0 + 16,
OCTEON_IRQ_WDOG15 = OCTEON_IRQ_WDOG0 + 15,
OCTEON_IRQ_MBOX0 = OCTEON_IRQ_WDOG0 + 16,
OCTEON_IRQ_MBOX1,
- OCTEON_IRQ_UART0,
- OCTEON_IRQ_UART1,
- OCTEON_IRQ_UART2,
OCTEON_IRQ_PCI_INT0,
OCTEON_IRQ_PCI_INT1,
OCTEON_IRQ_PCI_INT2,
@@ -38,8 +34,6 @@
OCTEON_IRQ_PCI_MSI2,
OCTEON_IRQ_PCI_MSI3,
- OCTEON_IRQ_TWSI,
- OCTEON_IRQ_TWSI2,
OCTEON_IRQ_RML,
OCTEON_IRQ_TIMER0,
OCTEON_IRQ_TIMER1,
@@ -47,8 +41,6 @@
OCTEON_IRQ_TIMER3,
OCTEON_IRQ_USB0,
OCTEON_IRQ_USB1,
- OCTEON_IRQ_MII0,
- OCTEON_IRQ_MII1,
OCTEON_IRQ_BOOTDMA,
#ifndef CONFIG_PCI_MSI
OCTEON_IRQ_LAST = 127
diff --git a/arch/mips/include/asm/module.h b/arch/mips/include/asm/module.h
index 7531ecd..dca8bce 100644
--- a/arch/mips/include/asm/module.h
+++ b/arch/mips/include/asm/module.h
@@ -10,6 +10,7 @@
struct list_head dbe_list;
const struct exception_table_entry *dbe_start;
const struct exception_table_entry *dbe_end;
+ struct mips_hi16 *r_mips_hi16_list;
};
typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */
diff --git a/arch/mips/include/asm/r4k-timer.h b/arch/mips/include/asm/r4k-timer.h
index a37d12b..afe9e0e 100644
--- a/arch/mips/include/asm/r4k-timer.h
+++ b/arch/mips/include/asm/r4k-timer.h
@@ -12,16 +12,16 @@
#ifdef CONFIG_SYNC_R4K
-extern void synchronise_count_master(void);
-extern void synchronise_count_slave(void);
+extern void synchronise_count_master(int cpu);
+extern void synchronise_count_slave(int cpu);
#else
-static inline void synchronise_count_master(void)
+static inline void synchronise_count_master(int cpu)
{
}
-static inline void synchronise_count_slave(void)
+static inline void synchronise_count_slave(int cpu)
{
}
diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c
index a5066b1..4f8c3cb 100644
--- a/arch/mips/kernel/module.c
+++ b/arch/mips/kernel/module.c
@@ -39,8 +39,6 @@
Elf_Addr value;
};
-static struct mips_hi16 *mips_hi16_list;
-
static LIST_HEAD(dbe_list);
static DEFINE_SPINLOCK(dbe_lock);
@@ -128,8 +126,8 @@
n->addr = (Elf_Addr *)location;
n->value = v;
- n->next = mips_hi16_list;
- mips_hi16_list = n;
+ n->next = me->arch.r_mips_hi16_list;
+ me->arch.r_mips_hi16_list = n;
return 0;
}
@@ -142,18 +140,28 @@
return 0;
}
+static void free_relocation_chain(struct mips_hi16 *l)
+{
+ struct mips_hi16 *next;
+
+ while (l) {
+ next = l->next;
+ kfree(l);
+ l = next;
+ }
+}
+
static int apply_r_mips_lo16_rel(struct module *me, u32 *location, Elf_Addr v)
{
unsigned long insnlo = *location;
+ struct mips_hi16 *l;
Elf_Addr val, vallo;
/* Sign extend the addend we extract from the lo insn. */
vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
- if (mips_hi16_list != NULL) {
- struct mips_hi16 *l;
-
- l = mips_hi16_list;
+ if (me->arch.r_mips_hi16_list != NULL) {
+ l = me->arch.r_mips_hi16_list;
while (l != NULL) {
struct mips_hi16 *next;
unsigned long insn;
@@ -188,7 +196,7 @@
l = next;
}
- mips_hi16_list = NULL;
+ me->arch.r_mips_hi16_list = NULL;
}
/*
@@ -201,6 +209,9 @@
return 0;
out_danger:
+ free_relocation_chain(l);
+ me->arch.r_mips_hi16_list = NULL;
+
pr_err("module %s: dangerous R_MIPS_LO16 REL relocation\n", me->name);
return -ENOEXEC;
@@ -273,6 +284,7 @@
pr_debug("Applying relocate section %u to %u\n", relsec,
sechdrs[relsec].sh_info);
+ me->arch.r_mips_hi16_list = NULL;
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
/* This is where to make the change */
location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
@@ -296,6 +308,19 @@
return res;
}
+ /*
+ * Normally the hi16 list should be deallocated at this point. A
+ * malformed binary however could contain a series of R_MIPS_HI16
+ * relocations not followed by a R_MIPS_LO16 relocation. In that
+ * case, free up the list and return an error.
+ */
+ if (me->arch.r_mips_hi16_list) {
+ free_relocation_chain(me->arch.r_mips_hi16_list);
+ me->arch.r_mips_hi16_list = NULL;
+
+ return -ENOEXEC;
+ }
+
return 0;
}
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 31637d8..9005bf9 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -130,7 +130,7 @@
cpu_set(cpu, cpu_callin_map);
- synchronise_count_slave();
+ synchronise_count_slave(cpu);
/*
* irq will be enabled in ->smp_finish(), enabling it too early
@@ -173,7 +173,6 @@
void __init smp_cpus_done(unsigned int max_cpus)
{
mp_ops->cpus_done();
- synchronise_count_master();
}
/* called from main before smp_init() */
@@ -206,6 +205,7 @@
while (!cpu_isset(cpu, cpu_callin_map))
udelay(100);
+ synchronise_count_master(cpu);
return 0;
}
diff --git a/arch/mips/kernel/sync-r4k.c b/arch/mips/kernel/sync-r4k.c
index 842d55e..7f1eca3 100644
--- a/arch/mips/kernel/sync-r4k.c
+++ b/arch/mips/kernel/sync-r4k.c
@@ -28,12 +28,11 @@
#define COUNTON 100
#define NR_LOOPS 5
-void __cpuinit synchronise_count_master(void)
+void __cpuinit synchronise_count_master(int cpu)
{
int i;
unsigned long flags;
unsigned int initcount;
- int nslaves;
#ifdef CONFIG_MIPS_MT_SMTC
/*
@@ -43,8 +42,7 @@
return;
#endif
- printk(KERN_INFO "Synchronize counters across %u CPUs: ",
- num_online_cpus());
+ printk(KERN_INFO "Synchronize counters for CPU %u: ", cpu);
local_irq_save(flags);
@@ -52,7 +50,7 @@
* Notify the slaves that it's time to start
*/
atomic_set(&count_reference, read_c0_count());
- atomic_set(&count_start_flag, 1);
+ atomic_set(&count_start_flag, cpu);
smp_wmb();
/* Count will be initialised to current timer for all CPU's */
@@ -69,10 +67,9 @@
* two CPUs.
*/
- nslaves = num_online_cpus()-1;
for (i = 0; i < NR_LOOPS; i++) {
- /* slaves loop on '!= ncpus' */
- while (atomic_read(&count_count_start) != nslaves)
+ /* slaves loop on '!= 2' */
+ while (atomic_read(&count_count_start) != 1)
mb();
atomic_set(&count_count_stop, 0);
smp_wmb();
@@ -89,7 +86,7 @@
/*
* Wait for all slaves to leave the synchronization point:
*/
- while (atomic_read(&count_count_stop) != nslaves)
+ while (atomic_read(&count_count_stop) != 1)
mb();
atomic_set(&count_count_start, 0);
smp_wmb();
@@ -97,6 +94,7 @@
}
/* Arrange for an interrupt in a short while */
write_c0_compare(read_c0_count() + COUNTON);
+ atomic_set(&count_start_flag, 0);
local_irq_restore(flags);
@@ -108,11 +106,10 @@
printk("done.\n");
}
-void __cpuinit synchronise_count_slave(void)
+void __cpuinit synchronise_count_slave(int cpu)
{
int i;
unsigned int initcount;
- int ncpus;
#ifdef CONFIG_MIPS_MT_SMTC
/*
@@ -127,16 +124,15 @@
* so we first wait for the master to say everyone is ready
*/
- while (!atomic_read(&count_start_flag))
+ while (atomic_read(&count_start_flag) != cpu)
mb();
/* Count will be initialised to next expire for all CPU's */
initcount = atomic_read(&count_reference);
- ncpus = num_online_cpus();
for (i = 0; i < NR_LOOPS; i++) {
atomic_inc(&count_count_start);
- while (atomic_read(&count_count_start) != ncpus)
+ while (atomic_read(&count_count_start) != 2)
mb();
/*
@@ -146,7 +142,7 @@
write_c0_count(initcount);
atomic_inc(&count_count_stop);
- while (atomic_read(&count_count_stop) != ncpus)
+ while (atomic_read(&count_count_stop) != 2)
mb();
}
/* Arrange for an interrupt in a short while */
diff --git a/arch/mips/mti-malta/malta-pci.c b/arch/mips/mti-malta/malta-pci.c
index 284dea5..2147cb3 100644
--- a/arch/mips/mti-malta/malta-pci.c
+++ b/arch/mips/mti-malta/malta-pci.c
@@ -252,16 +252,3 @@
register_pci_controller(controller);
}
-
-/* Enable PCI 2.1 compatibility in PIIX4 */
-static void __devinit quirk_dlcsetup(struct pci_dev *dev)
-{
- u8 odlc, ndlc;
- (void) pci_read_config_byte(dev, 0x82, &odlc);
- /* Enable passive releases and delayed transaction */
- ndlc = odlc | 7;
- (void) pci_write_config_byte(dev, 0x82, ndlc);
-}
-
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
- quirk_dlcsetup);
diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c
index 414a745..86d77a6 100644
--- a/arch/mips/pci/pci-ar724x.c
+++ b/arch/mips/pci/pci-ar724x.c
@@ -23,9 +23,12 @@
#define AR724X_PCI_MEM_BASE 0x10000000
#define AR724X_PCI_MEM_SIZE 0x08000000
+#define AR724X_PCI_REG_RESET 0x18
#define AR724X_PCI_REG_INT_STATUS 0x4c
#define AR724X_PCI_REG_INT_MASK 0x50
+#define AR724X_PCI_RESET_LINK_UP BIT(0)
+
#define AR724X_PCI_INT_DEV0 BIT(14)
#define AR724X_PCI_IRQ_COUNT 1
@@ -38,6 +41,15 @@
static u32 ar724x_pci_bar0_value;
static bool ar724x_pci_bar0_is_cached;
+static bool ar724x_pci_link_up;
+
+static inline bool ar724x_pci_check_link(void)
+{
+ u32 reset;
+
+ reset = __raw_readl(ar724x_pci_ctrl_base + AR724X_PCI_REG_RESET);
+ return reset & AR724X_PCI_RESET_LINK_UP;
+}
static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,
int size, uint32_t *value)
@@ -46,6 +58,9 @@
void __iomem *base;
u32 data;
+ if (!ar724x_pci_link_up)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
if (devfn)
return PCIBIOS_DEVICE_NOT_FOUND;
@@ -96,6 +111,9 @@
u32 data;
int s;
+ if (!ar724x_pci_link_up)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
if (devfn)
return PCIBIOS_DEVICE_NOT_FOUND;
@@ -280,6 +298,10 @@
if (ar724x_pci_ctrl_base == NULL)
goto err_unmap_devcfg;
+ ar724x_pci_link_up = ar724x_pci_check_link();
+ if (!ar724x_pci_link_up)
+ pr_warn("ar724x: PCIe link is down\n");
+
ar724x_pci_irq_init(irq);
register_pci_controller(&ar724x_pci_controller);
diff --git a/arch/mips/sni/a20r.c b/arch/mips/sni/a20r.c
index c48194c..b2d4f49 100644
--- a/arch/mips/sni/a20r.c
+++ b/arch/mips/sni/a20r.c
@@ -133,6 +133,38 @@
}
};
+#warning "Please try migrate to use new driver SCCNXP and report the status" \
+ "in the linux-serial mailing list."
+
+/* The code bellow is a replacement of SC26XX to SCCNXP */
+#if 0
+#include <linux/platform_data/sccnxp.h>
+
+static struct sccnxp_pdata sccnxp_data = {
+ .reg_shift = 2,
+ .frequency = 3686400,
+ .mctrl_cfg[0] = MCTRL_SIG(DTR_OP, LINE_OP7) |
+ MCTRL_SIG(RTS_OP, LINE_OP3) |
+ MCTRL_SIG(DSR_IP, LINE_IP5) |
+ MCTRL_SIG(DCD_IP, LINE_IP6),
+ .mctrl_cfg[1] = MCTRL_SIG(DTR_OP, LINE_OP2) |
+ MCTRL_SIG(RTS_OP, LINE_OP1) |
+ MCTRL_SIG(DSR_IP, LINE_IP0) |
+ MCTRL_SIG(CTS_IP, LINE_IP1) |
+ MCTRL_SIG(DCD_IP, LINE_IP2) |
+ MCTRL_SIG(RNG_IP, LINE_IP3),
+};
+
+static struct platform_device sc2681_pdev = {
+ .name = "sc2681",
+ .resource = sc2xxx_rsrc,
+ .num_resources = ARRAY_SIZE(sc2xxx_rsrc),
+ .dev = {
+ .platform_data = &sccnxp_data,
+ },
+};
+#endif
+
static u32 a20r_ack_hwint(void)
{
u32 status = read_c0_status();
diff --git a/arch/parisc/include/asm/atomic.h b/arch/parisc/include/asm/atomic.h
index 6c6defc..af9cf30 100644
--- a/arch/parisc/include/asm/atomic.h
+++ b/arch/parisc/include/asm/atomic.h
@@ -141,7 +141,7 @@
#define atomic_sub_and_test(i,v) (atomic_sub_return((i),(v)) == 0)
-#define ATOMIC_INIT(i) ((atomic_t) { (i) })
+#define ATOMIC_INIT(i) { (i) }
#define smp_mb__before_atomic_dec() smp_mb()
#define smp_mb__after_atomic_dec() smp_mb()
@@ -150,7 +150,7 @@
#ifdef CONFIG_64BIT
-#define ATOMIC64_INIT(i) ((atomic64_t) { (i) })
+#define ATOMIC64_INIT(i) { (i) }
static __inline__ s64
__atomic64_add_return(s64 i, atomic64_t *v)
diff --git a/arch/parisc/kernel/pdc_cons.c b/arch/parisc/kernel/pdc_cons.c
index 47341aa..8823863 100644
--- a/arch/parisc/kernel/pdc_cons.c
+++ b/arch/parisc/kernel/pdc_cons.c
@@ -202,6 +202,7 @@
pdc_console_tty_driver->flags = TTY_DRIVER_REAL_RAW |
TTY_DRIVER_RESET_TERMIOS;
tty_set_operations(pdc_console_tty_driver, &pdc_console_tty_ops);
+ tty_port_link_device(&tty_port, pdc_console_tty_driver, 0);
err = tty_register_driver(pdc_console_tty_driver);
if (err) {
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
index d4b94b3..2c05a929 100644
--- a/arch/parisc/kernel/process.c
+++ b/arch/parisc/kernel/process.c
@@ -309,7 +309,7 @@
cregs->ksp = (unsigned long)stack
+ (pregs->gr[21] & (THREAD_SIZE - 1));
cregs->gr[30] = usp;
- if (p->personality == PER_HPUX) {
+ if (personality(p->personality) == PER_HPUX) {
#ifdef CONFIG_HPUX
cregs->kpc = (unsigned long) &hpux_child_return;
#else
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
index c9b9322..7426e40 100644
--- a/arch/parisc/kernel/sys_parisc.c
+++ b/arch/parisc/kernel/sys_parisc.c
@@ -225,12 +225,12 @@
long err;
if (personality(current->personality) == PER_LINUX32
- && personality == PER_LINUX)
- personality = PER_LINUX32;
+ && personality(personality) == PER_LINUX)
+ personality = (personality & ~PER_MASK) | PER_LINUX32;
err = sys_personality(personality);
- if (err == PER_LINUX32)
- err = PER_LINUX;
+ if (personality(err) == PER_LINUX32)
+ err = (err & ~PER_MASK) | PER_LINUX;
return err;
}
diff --git a/arch/powerpc/boot/dts/fsl/p4080si-post.dtsi b/arch/powerpc/boot/dts/fsl/p4080si-post.dtsi
index 8d35d2c..4f9c9f6 100644
--- a/arch/powerpc/boot/dts/fsl/p4080si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p4080si-post.dtsi
@@ -345,6 +345,13 @@
/include/ "qoriq-duart-1.dtsi"
/include/ "qoriq-gpio-0.dtsi"
/include/ "qoriq-usb2-mph-0.dtsi"
+ usb@210000 {
+ compatible = "fsl-usb2-mph-v1.6", "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
+ port0;
+ };
/include/ "qoriq-usb2-dr-0.dtsi"
+ usb@211000 {
+ compatible = "fsl-usb2-dr-v1.6", "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
+ };
/include/ "qoriq-sec4.0-0.dtsi"
};
diff --git a/arch/powerpc/configs/85xx/p1023rds_defconfig b/arch/powerpc/configs/85xx/p1023rds_defconfig
index f4337ba..26e541c 100644
--- a/arch/powerpc/configs/85xx/p1023rds_defconfig
+++ b/arch/powerpc/configs/85xx/p1023rds_defconfig
@@ -6,28 +6,27 @@
CONFIG_POSIX_MQUEUE=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_AUDIT=y
-CONFIG_SPARSE_IRQ=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
CONFIG_EMBEDDED=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MAC_PARTITION=y
CONFIG_P1023_RDS=y
CONFIG_QUICC_ENGINE=y
CONFIG_QE_GPIO=y
CONFIG_CPM2=y
-CONFIG_GPIO_MPC8XXX=y
CONFIG_HIGHMEM=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_BINFMT_MISC=m
CONFIG_MATH_EMULATION=y
@@ -63,11 +62,11 @@
CONFIG_IPV6=y
CONFIG_IP_SCTP=m
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
CONFIG_PROC_DEVICETREE=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=131072
-CONFIG_MISC_DEVICES=y
CONFIG_EEPROM_LEGACY=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=y
@@ -80,15 +79,14 @@
CONFIG_SATA_SIL24=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
+CONFIG_FS_ENET=y
+CONFIG_FSL_PQ_MDIO=y
+CONFIG_E1000E=y
CONFIG_MARVELL_PHY=y
CONFIG_DAVICOM_PHY=y
CONFIG_CICADA_PHY=y
CONFIG_VITESSE_PHY=y
CONFIG_FIXED_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_FS_ENET=y
-CONFIG_E1000E=y
-CONFIG_FSL_PQ_MDIO=y
CONFIG_INPUT_FF_MEMLESS=m
# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_KEYBOARD is not set
@@ -98,16 +96,15 @@
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_NR_UARTS=2
CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_MANY_PORTS=y
CONFIG_SERIAL_8250_DETECT_IRQ=y
CONFIG_SERIAL_8250_RSA=y
CONFIG_SERIAL_QE=m
-CONFIG_HW_RANDOM=y
CONFIG_NVRAM=y
CONFIG_I2C=y
CONFIG_I2C_CPM=m
CONFIG_I2C_MPC=y
+CONFIG_GPIO_MPC8XXX=y
# CONFIG_HWMON is not set
CONFIG_VIDEO_OUTPUT_CONTROL=y
CONFIG_SOUND=y
@@ -123,7 +120,6 @@
CONFIG_FSL_DMA=y
# CONFIG_NET_DMA is not set
CONFIG_STAGING=y
-# CONFIG_STAGING_EXCLUDE_BUILD is not set
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
@@ -150,22 +146,15 @@
CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
CONFIG_NFS_V4=y
CONFIG_ROOT_NFS=y
CONFIG_NFSD=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAC_PARTITION=y
CONFIG_CRC_T10DIF=y
CONFIG_FRAME_WARN=8092
CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_HUNG_TASK=y
# CONFIG_DEBUG_BUGVERBOSE is not set
CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_SHA512=y
diff --git a/arch/powerpc/configs/corenet32_smp_defconfig b/arch/powerpc/configs/corenet32_smp_defconfig
index cbb98c1..8b3d57c 100644
--- a/arch/powerpc/configs/corenet32_smp_defconfig
+++ b/arch/powerpc/configs/corenet32_smp_defconfig
@@ -6,8 +6,8 @@
CONFIG_POSIX_MQUEUE=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_AUDIT=y
-CONFIG_SPARSE_IRQ=y
-CONFIG_RCU_TRACE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
@@ -21,23 +21,22 @@
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MAC_PARTITION=y
CONFIG_P2041_RDB=y
CONFIG_P3041_DS=y
CONFIG_P4080_DS=y
CONFIG_P5020_DS=y
CONFIG_HIGHMEM=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_BINFMT_MISC=m
CONFIG_KEXEC=y
CONFIG_IRQ_ALL_CPUS=y
CONFIG_FORCE_MAX_ZONEORDER=13
-CONFIG_FSL_LBC=y
CONFIG_PCI=y
CONFIG_PCIEPORTBUS=y
-CONFIG_PCI_MSI=y
# CONFIG_PCIEASPM is not set
+CONFIG_PCI_MSI=y
CONFIG_RAPIDIO=y
CONFIG_FSL_RIO=y
CONFIG_NET=y
@@ -70,6 +69,7 @@
CONFIG_IPV6=y
CONFIG_IP_SCTP=m
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
CONFIG_MTD=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_CHAR=y
@@ -77,17 +77,14 @@
CONFIG_MTD_CFI=y
CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_PHYSMAP_OF=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ECC=y
-CONFIG_MTD_NAND_IDS=y
-CONFIG_MTD_NAND_FSL_IFC=y
-CONFIG_MTD_NAND_FSL_ELBC=y
CONFIG_MTD_M25P80=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_FSL_ELBC=y
+CONFIG_MTD_NAND_FSL_IFC=y
CONFIG_PROC_DEVICETREE=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=131072
-CONFIG_MISC_DEVICES=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=y
CONFIG_BLK_DEV_SR=y
@@ -115,11 +112,9 @@
CONFIG_PPC_EPAPR_HV_BYTECHAN=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_MANY_PORTS=y
CONFIG_SERIAL_8250_DETECT_IRQ=y
CONFIG_SERIAL_8250_RSA=y
-CONFIG_HW_RANDOM=y
CONFIG_NVRAM=y
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
@@ -132,7 +127,6 @@
CONFIG_VIDEO_OUTPUT_CONTROL=y
CONFIG_USB_HID=m
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_FSL=y
@@ -142,8 +136,6 @@
CONFIG_USB_STORAGE=y
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
-CONFIG_MMC_SDHCI_OF=y
-CONFIG_MMC_SDHCI_OF_ESDHC=y
CONFIG_EDAC=y
CONFIG_EDAC_MM_EDAC=y
CONFIG_EDAC_MPC85XX=y
@@ -170,19 +162,16 @@
CONFIG_JFFS2_FS=y
CONFIG_CRAMFS=y
CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
CONFIG_NFS_V4=y
CONFIG_ROOT_NFS=y
CONFIG_NFSD=m
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAC_PARTITION=y
CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_UTF8=m
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_SHIRQ=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_DEBUG_INFO=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_RCU_TRACE=y
CONFIG_CRYPTO_NULL=y
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_MD4=y
diff --git a/arch/powerpc/configs/corenet64_smp_defconfig b/arch/powerpc/configs/corenet64_smp_defconfig
index dd89de8..0516e22 100644
--- a/arch/powerpc/configs/corenet64_smp_defconfig
+++ b/arch/powerpc/configs/corenet64_smp_defconfig
@@ -56,6 +56,7 @@
CONFIG_IPV6=y
CONFIG_IP_SCTP=m
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
CONFIG_MTD=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_CHAR=y
diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig
index 1513006..07b7f2a 100644
--- a/arch/powerpc/configs/g5_defconfig
+++ b/arch/powerpc/configs/g5_defconfig
@@ -1,8 +1,10 @@
+CONFIG_PPC64=y
+CONFIG_ALTIVEC=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=4
CONFIG_EXPERIMENTAL=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_BLK_DEV_INITRD=y
@@ -13,15 +15,16 @@
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAC_PARTITION=y
-CONFIG_SMP=y
-CONFIG_NR_CPUS=4
-CONFIG_KEXEC=y
-# CONFIG_RELOCATABLE is not set
+# CONFIG_PPC_PSERIES is not set
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_PMAC64=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_KEXEC=y
+CONFIG_IRQ_ALL_CPUS=y
+# CONFIG_MIGRATION is not set
CONFIG_PCI_MSI=y
CONFIG_NET=y
CONFIG_PACKET=y
@@ -49,6 +52,7 @@
CONFIG_NF_CONNTRACK_IPV4=m
CONFIG_IP_NF_QUEUE=m
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_PROC_DEVICETREE=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
@@ -56,6 +60,8 @@
CONFIG_CDROM_PKTCDVD=m
CONFIG_IDE=y
CONFIG_BLK_DEV_IDECD=y
+CONFIG_BLK_DEV_IDE_PMAC=y
+CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=y
CONFIG_BLK_DEV_SR=y
@@ -79,24 +85,33 @@
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_MIRROR=m
CONFIG_DM_ZERO=m
-CONFIG_MACINTOSH_DRIVERS=y
+CONFIG_IEEE1394=y
+CONFIG_IEEE1394_OHCI1394=y
+CONFIG_IEEE1394_SBP2=m
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_RAWIO=y
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_ADB_PMU=y
+CONFIG_PMAC_SMU=y
CONFIG_MAC_EMUMOUSEBTN=y
+CONFIG_THERM_PM72=y
+CONFIG_WINDFARM=y
+CONFIG_WINDFARM_PM81=y
+CONFIG_WINDFARM_PM91=y
+CONFIG_WINDFARM_PM112=y
+CONFIG_WINDFARM_PM121=y
CONFIG_NETDEVICES=y
-CONFIG_BONDING=m
CONFIG_DUMMY=m
-CONFIG_MII=y
+CONFIG_BONDING=m
CONFIG_TUN=m
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_SUNGEM=y
CONFIG_ACENIC=m
CONFIG_ACENIC_OMIT_TIGON_I=y
-CONFIG_TIGON3=y
CONFIG_E1000=y
-CONFIG_SUNGEM=y
-CONFIG_PPP=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPPOE=m
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
+CONFIG_TIGON3=y
CONFIG_USB_CATC=m
CONFIG_USB_KAWETH=m
CONFIG_USB_PEGASUS=m
@@ -106,24 +121,36 @@
# CONFIG_USB_NET_NET1080 is not set
# CONFIG_USB_NET_CDC_SUBSET is not set
# CONFIG_USB_NET_ZAURUS is not set
+CONFIG_PPP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPPOE=m
# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
CONFIG_INPUT_JOYDEV=m
CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_ATKBD is not set
# CONFIG_MOUSE_PS2 is not set
+# CONFIG_SERIO_I8042 is not set
# CONFIG_SERIO_SERPORT is not set
-CONFIG_VT_HW_CONSOLE_BINDING=y
# CONFIG_HW_RANDOM is not set
CONFIG_GEN_RTC=y
CONFIG_RAW_DRIVER=y
CONFIG_I2C_CHARDEV=y
# CONFIG_HWMON is not set
-CONFIG_AGP=y
-CONFIG_DRM=y
-CONFIG_DRM_NOUVEAU=y
+CONFIG_AGP=m
+CONFIG_AGP_UNINORTH=m
CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
CONFIG_FIRMWARE_EDID=y
CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_OF=y
+CONFIG_FB_NVIDIA=y
+CONFIG_FB_NVIDIA_I2C=y
CONFIG_FB_RADEON=y
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_LOGO=y
CONFIG_SOUND=m
CONFIG_SND=m
@@ -131,7 +158,15 @@
CONFIG_SND_MIXER_OSS=m
CONFIG_SND_PCM_OSS=m
CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_POWERMAC=m
+CONFIG_SND_AOA=m
+CONFIG_SND_AOA_FABRIC_LAYOUT=m
+CONFIG_SND_AOA_ONYX=m
+CONFIG_SND_AOA_TAS=m
+CONFIG_SND_AOA_TOONIE=m
CONFIG_SND_USB_AUDIO=m
+CONFIG_HID_PID=y
+CONFIG_USB_HIDDEV=y
CONFIG_HID_GYRATION=y
CONFIG_LOGITECH_FF=y
CONFIG_HID_PANTHERLORD=y
@@ -139,12 +174,13 @@
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
-CONFIG_HID_PID=y
-CONFIG_USB_HIDDEV=y
CONFIG_USB=y
+CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_HCD_PPC_OF is not set
CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
CONFIG_USB_ACM=m
CONFIG_USB_PRINTER=y
CONFIG_USB_STORAGE=y
@@ -208,6 +244,8 @@
CONFIG_REISERFS_FS_SECURITY=y
CONFIG_XFS_FS=m
CONFIG_XFS_POSIX_ACL=y
+CONFIG_INOTIFY=y
+CONFIG_AUTOFS_FS=m
CONFIG_ISO9660_FS=y
CONFIG_JOLIET=y
CONFIG_ZISOFS=y
@@ -221,12 +259,14 @@
CONFIG_HFSPLUS_FS=m
CONFIG_CRAMFS=y
CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
CONFIG_NFS_V3_ACL=y
CONFIG_NFS_V4=y
CONFIG_NFSD=y
CONFIG_NFSD_V3_ACL=y
CONFIG_NFSD_V4=y
CONFIG_CIFS=m
+CONFIG_PARTITION_ADVANCED=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_CODEPAGE_1250=y
CONFIG_NLS_CODEPAGE_1251=y
@@ -234,23 +274,29 @@
CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_ISO8859_15=y
CONFIG_NLS_UTF8=y
+CONFIG_CRC_T10DIF=y
+CONFIG_LIBCRC32C=m
CONFIG_MAGIC_SYSRQ=y
-# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_MUTEXES=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_LATENCYTOP=y
-CONFIG_STRICT_DEVMEM=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_BOOTX_TEXT=y
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_MD4=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_AES=m
CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAST5=m
CONFIG_CRYPTO_CAST6=m
@@ -260,6 +306,3 @@
CONFIG_CRYPTO_TWOFISH=m
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
-# CONFIG_VIRTUALIZATION is not set
-CONFIG_CRC_T10DIF=y
-CONFIG_LIBCRC32C=m
diff --git a/arch/powerpc/configs/mpc83xx_defconfig b/arch/powerpc/configs/mpc83xx_defconfig
index 5aac9a8..9352e44 100644
--- a/arch/powerpc/configs/mpc83xx_defconfig
+++ b/arch/powerpc/configs/mpc83xx_defconfig
@@ -2,12 +2,12 @@
CONFIG_SYSVIPC=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EXPERT=y
CONFIG_SLAB=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
# CONFIG_PPC_CHRP is not set
# CONFIG_PPC_PMAC is not set
CONFIG_PPC_83xx=y
@@ -25,7 +25,6 @@
CONFIG_QUICC_ENGINE=y
CONFIG_QE_GPIO=y
CONFIG_MATH_EMULATION=y
-CONFIG_SPARSE_IRQ=y
CONFIG_PCI=y
CONFIG_NET=y
CONFIG_PACKET=y
@@ -42,10 +41,9 @@
# CONFIG_INET_LRO is not set
# CONFIG_IPV6 is not set
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
# CONFIG_FW_LOADER is not set
CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_OF_PARTS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
@@ -64,15 +62,14 @@
CONFIG_SATA_FSL=y
CONFIG_SATA_SIL=y
CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_UCC_GETH=y
+CONFIG_GIANFAR=y
CONFIG_MARVELL_PHY=y
CONFIG_DAVICOM_PHY=y
CONFIG_VITESSE_PHY=y
CONFIG_ICPLUS_PHY=y
CONFIG_FIXED_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_GIANFAR=y
-CONFIG_UCC_GETH=y
CONFIG_INPUT_FF_MEMLESS=m
# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_KEYBOARD is not set
@@ -112,17 +109,12 @@
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_INOTIFY=y
CONFIG_PROC_KCORE=y
CONFIG_TMPFS=y
CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
CONFIG_NFS_V4=y
CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
CONFIG_CRC_T10DIF=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_SHA256=y
diff --git a/arch/powerpc/configs/mpc85xx_defconfig b/arch/powerpc/configs/mpc85xx_defconfig
index 03ee911c..8b5bda2 100644
--- a/arch/powerpc/configs/mpc85xx_defconfig
+++ b/arch/powerpc/configs/mpc85xx_defconfig
@@ -5,7 +5,9 @@
CONFIG_POSIX_MQUEUE=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_AUDIT=y
-CONFIG_SPARSE_IRQ=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
@@ -17,6 +19,8 @@
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MAC_PARTITION=y
CONFIG_MPC8540_ADS=y
CONFIG_MPC8560_ADS=y
CONFIG_MPC85xx_CDS=y
@@ -40,8 +44,6 @@
CONFIG_QUICC_ENGINE=y
CONFIG_QE_GPIO=y
CONFIG_HIGHMEM=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
CONFIG_BINFMT_MISC=m
CONFIG_MATH_EMULATION=y
CONFIG_FORCE_MAX_ZONEORDER=12
@@ -74,36 +76,25 @@
CONFIG_IPV6=y
CONFIG_IP_SCTP=m
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
CONFIG_MTD=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
CONFIG_FTL=y
-CONFIG_MTD_GEN_PROBE=y
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
+CONFIG_MTD_CFI=y
CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_UTIL=y
CONFIG_MTD_PHYSMAP_OF=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_OF_PARTS=y
+CONFIG_MTD_M25P80=y
CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_FSL_ELBC=y
CONFIG_MTD_NAND_FSL_IFC=y
-CONFIG_MTD_NAND_IDS=y
-CONFIG_MTD_NAND_ECC=y
-CONFIG_MTD_M25P80=y
CONFIG_PROC_DEVICETREE=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_NBD=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=131072
-CONFIG_MISC_DEVICES=y
CONFIG_EEPROM_LEGACY=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=y
@@ -115,6 +106,7 @@
CONFIG_SATA_AHCI=y
CONFIG_SATA_FSL=y
CONFIG_PATA_ALI=y
+CONFIG_PATA_VIA=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
CONFIG_FS_ENET=y
@@ -134,7 +126,6 @@
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_NR_UARTS=2
CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_MANY_PORTS=y
CONFIG_SERIAL_8250_DETECT_IRQ=y
CONFIG_SERIAL_8250_RSA=y
@@ -183,7 +174,6 @@
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_FSL=y
@@ -229,18 +219,13 @@
CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
CONFIG_NFS_V4=y
CONFIG_ROOT_NFS=y
CONFIG_NFSD=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAC_PARTITION=y
CONFIG_CRC_T10DIF=y
CONFIG_DEBUG_FS=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_DEBUG_INFO=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_SHA512=y
diff --git a/arch/powerpc/configs/mpc85xx_smp_defconfig b/arch/powerpc/configs/mpc85xx_smp_defconfig
index fdfa84d..b0974e7 100644
--- a/arch/powerpc/configs/mpc85xx_smp_defconfig
+++ b/arch/powerpc/configs/mpc85xx_smp_defconfig
@@ -7,7 +7,9 @@
CONFIG_POSIX_MQUEUE=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_AUDIT=y
-CONFIG_SPARSE_IRQ=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
@@ -19,6 +21,8 @@
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MAC_PARTITION=y
CONFIG_MPC8540_ADS=y
CONFIG_MPC8560_ADS=y
CONFIG_MPC85xx_CDS=y
@@ -42,8 +46,6 @@
CONFIG_QUICC_ENGINE=y
CONFIG_QE_GPIO=y
CONFIG_HIGHMEM=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
CONFIG_BINFMT_MISC=m
CONFIG_MATH_EMULATION=y
CONFIG_IRQ_ALL_CPUS=y
@@ -77,36 +79,25 @@
CONFIG_IPV6=y
CONFIG_IP_SCTP=m
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
CONFIG_MTD=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
CONFIG_FTL=y
-CONFIG_MTD_GEN_PROBE=y
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
+CONFIG_MTD_CFI=y
CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_UTIL=y
CONFIG_MTD_PHYSMAP_OF=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_OF_PARTS=y
+CONFIG_MTD_M25P80=y
CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_FSL_ELBC=y
CONFIG_MTD_NAND_FSL_IFC=y
-CONFIG_MTD_NAND_IDS=y
-CONFIG_MTD_NAND_ECC=y
-CONFIG_MTD_M25P80=y
CONFIG_PROC_DEVICETREE=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_NBD=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=131072
-CONFIG_MISC_DEVICES=y
CONFIG_EEPROM_LEGACY=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=y
@@ -137,7 +128,6 @@
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_NR_UARTS=2
CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_MANY_PORTS=y
CONFIG_SERIAL_8250_DETECT_IRQ=y
CONFIG_SERIAL_8250_RSA=y
@@ -186,7 +176,6 @@
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_FSL=y
@@ -232,18 +221,13 @@
CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
CONFIG_NFS_V4=y
CONFIG_ROOT_NFS=y
CONFIG_NFSD=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAC_PARTITION=y
CONFIG_CRC_T10DIF=y
CONFIG_DEBUG_FS=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_DEBUG_INFO=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_SHA512=y
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index 50d82c8..b3c083d 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -553,9 +553,7 @@
& feature);
}
-#ifdef CONFIG_HAVE_HW_BREAKPOINT
#define HBP_NUM 1
-#endif /* CONFIG_HAVE_HW_BREAKPOINT */
#endif /* !__ASSEMBLY__ */
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 50ea12f..a8bf5c6 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -33,6 +33,7 @@
#include <asm/kvm_asm.h>
#include <asm/processor.h>
#include <asm/page.h>
+#include <asm/cacheflush.h>
#define KVM_MAX_VCPUS NR_CPUS
#define KVM_MAX_VCORES NR_CPUS
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 0124937..e006f0b 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -219,4 +219,16 @@
void kvmppc_free_lpid(long lpid);
void kvmppc_init_lpid(unsigned long nr_lpids);
+static inline void kvmppc_mmu_flush_icache(pfn_t pfn)
+{
+ /* Clear i-cache for new pages */
+ struct page *page;
+ page = pfn_to_page(pfn);
+ if (!test_bit(PG_arch_1, &page->flags)) {
+ flush_dcache_icache_page(page);
+ set_bit(PG_arch_1, &page->flags);
+ }
+}
+
+
#endif /* __POWERPC_KVM_PPC_H__ */
diff --git a/arch/powerpc/include/asm/mpic_msgr.h b/arch/powerpc/include/asm/mpic_msgr.h
index 326d33c..d4f471f 100644
--- a/arch/powerpc/include/asm/mpic_msgr.h
+++ b/arch/powerpc/include/asm/mpic_msgr.h
@@ -14,6 +14,7 @@
#include <linux/types.h>
#include <linux/spinlock.h>
#include <asm/smp.h>
+#include <asm/io.h>
struct mpic_msgr {
u32 __iomem *base;
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index 53b6dfa..54b73a2 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -386,6 +386,7 @@
enum idle_boot_override {IDLE_NO_OVERRIDE = 0, IDLE_POWERSAVE_OFF};
extern int powersave_nap; /* set if nap mode can be used in idle loop */
+extern void power7_nap(void);
#ifdef CONFIG_PSERIES_IDLE
extern void update_smt_snooze_delay(int snooze);
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 85b05c4..e899572 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -76,6 +76,7 @@
DEFINE(SIGSEGV, SIGSEGV);
DEFINE(NMI_MASK, NMI_MASK);
DEFINE(THREAD_DSCR, offsetof(struct thread_struct, dscr));
+ DEFINE(THREAD_DSCR_INHERIT, offsetof(struct thread_struct, dscr_inherit));
#else
DEFINE(THREAD_INFO, offsetof(struct task_struct, stack));
#endif /* CONFIG_PPC64 */
diff --git a/arch/powerpc/kernel/dbell.c b/arch/powerpc/kernel/dbell.c
index 5b25c80..a892680 100644
--- a/arch/powerpc/kernel/dbell.c
+++ b/arch/powerpc/kernel/dbell.c
@@ -28,6 +28,8 @@
void doorbell_cause_ipi(int cpu, unsigned long data)
{
+ /* Order previous accesses vs. msgsnd, which is treated as a store */
+ mb();
ppc_msgsnd(PPC_DBELL, 0, data);
}
diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c
index 2d7bb8c..e489752 100644
--- a/arch/powerpc/kernel/dma-iommu.c
+++ b/arch/powerpc/kernel/dma-iommu.c
@@ -83,11 +83,10 @@
return 0;
}
- if ((tbl->it_offset + tbl->it_size) > (mask >> IOMMU_PAGE_SHIFT)) {
- dev_info(dev, "Warning: IOMMU window too big for device mask\n");
- dev_info(dev, "mask: 0x%08llx, table end: 0x%08lx\n",
- mask, (tbl->it_offset + tbl->it_size) <<
- IOMMU_PAGE_SHIFT);
+ if (tbl->it_offset > (mask >> IOMMU_PAGE_SHIFT)) {
+ dev_info(dev, "Warning: IOMMU offset too big for device mask\n");
+ dev_info(dev, "mask: 0x%08llx, table offset: 0x%08lx\n",
+ mask, tbl->it_offset << IOMMU_PAGE_SHIFT);
return 0;
} else
return 1;
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 4b01a25..b40e0b4 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -370,6 +370,12 @@
li r3,0
b syscall_exit
+ .section ".toc","aw"
+DSCR_DEFAULT:
+ .tc dscr_default[TC],dscr_default
+
+ .section ".text"
+
/*
* This routine switches between two different tasks. The process
* state of one is saved on its kernel stack. Then the state
@@ -509,9 +515,6 @@
mr r1,r8 /* start using new stack pointer */
std r7,PACAKSAVE(r13)
- ld r6,_CCR(r1)
- mtcrf 0xFF,r6
-
#ifdef CONFIG_ALTIVEC
BEGIN_FTR_SECTION
ld r0,THREAD_VRSAVE(r4)
@@ -520,14 +523,22 @@
#endif /* CONFIG_ALTIVEC */
#ifdef CONFIG_PPC64
BEGIN_FTR_SECTION
+ lwz r6,THREAD_DSCR_INHERIT(r4)
+ ld r7,DSCR_DEFAULT@toc(2)
ld r0,THREAD_DSCR(r4)
- cmpd r0,r25
- beq 1f
+ cmpwi r6,0
+ bne 1f
+ ld r0,0(r7)
+1: cmpd r0,r25
+ beq 2f
mtspr SPRN_DSCR,r0
-1:
+2:
END_FTR_SECTION_IFSET(CPU_FTR_DSCR)
#endif
+ ld r6,_CCR(r1)
+ mtcrf 0xFF,r6
+
/* r3-r13 are destroyed -- Cort */
REST_8GPRS(14, r1)
REST_10GPRS(22, r1)
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index e894515..39aa97d 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -186,7 +186,7 @@
KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x800)
MASKABLE_EXCEPTION_PSERIES(0x900, 0x900, decrementer)
- MASKABLE_EXCEPTION_HV(0x980, 0x982, decrementer)
+ STD_EXCEPTION_HV(0x980, 0x982, hdecrementer)
STD_EXCEPTION_PSERIES(0xa00, 0xa00, trap_0a)
KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xa00)
@@ -486,6 +486,7 @@
STD_EXCEPTION_COMMON_ASYNC(0x500, hardware_interrupt, do_IRQ)
STD_EXCEPTION_COMMON_ASYNC(0x900, decrementer, .timer_interrupt)
+ STD_EXCEPTION_COMMON(0x980, hdecrementer, .hdec_interrupt)
STD_EXCEPTION_COMMON(0xa00, trap_0a, .unknown_exception)
STD_EXCEPTION_COMMON(0xb00, trap_0b, .unknown_exception)
STD_EXCEPTION_COMMON(0xd00, single_step, .single_step_exception)
diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c
index f3a82dd..956a4c4 100644
--- a/arch/powerpc/kernel/hw_breakpoint.c
+++ b/arch/powerpc/kernel/hw_breakpoint.c
@@ -253,7 +253,7 @@
/* Do not emulate user-space instructions, instead single-step them */
if (user_mode(regs)) {
- bp->ctx->task->thread.last_hit_ubp = bp;
+ current->thread.last_hit_ubp = bp;
regs->msr |= MSR_SE;
goto out;
}
diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S
index 7140d83..e11863f 100644
--- a/arch/powerpc/kernel/idle_power7.S
+++ b/arch/powerpc/kernel/idle_power7.S
@@ -28,7 +28,9 @@
lwz r4,ADDROFF(powersave_nap)(r3)
cmpwi 0,r4,0
beqlr
+ /* fall through */
+_GLOBAL(power7_nap)
/* NAP is a state loss, we create a regs frame on the
* stack, fill it up with the state we care about and
* stick a pointer to it in PACAR1. We really only
diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c
index 782bd0a..c470a40 100644
--- a/arch/powerpc/kernel/kgdb.c
+++ b/arch/powerpc/kernel/kgdb.c
@@ -25,6 +25,7 @@
#include <asm/processor.h>
#include <asm/machdep.h>
#include <asm/debug.h>
+#include <linux/slab.h>
/*
* This table contains the mapping between PowerPC hardware trap types, and
@@ -101,6 +102,21 @@
return SIGHUP; /* default for things we don't know about */
}
+/**
+ *
+ * kgdb_skipexception - Bail out of KGDB when we've been triggered.
+ * @exception: Exception vector number
+ * @regs: Current &struct pt_regs.
+ *
+ * On some architectures we need to skip a breakpoint exception when
+ * it occurs after a breakpoint has been removed.
+ *
+ */
+int kgdb_skipexception(int exception, struct pt_regs *regs)
+{
+ return kgdb_isremovedbreak(regs->nip);
+}
+
static int kgdb_call_nmi_hook(struct pt_regs *regs)
{
kgdb_nmicallback(raw_smp_processor_id(), regs);
@@ -138,6 +154,8 @@
static int kgdb_singlestep(struct pt_regs *regs)
{
struct thread_info *thread_info, *exception_thread_info;
+ struct thread_info *backup_current_thread_info = \
+ (struct thread_info *)kmalloc(sizeof(struct thread_info), GFP_KERNEL);
if (user_mode(regs))
return 0;
@@ -155,13 +173,17 @@
thread_info = (struct thread_info *)(regs->gpr[1] & ~(THREAD_SIZE-1));
exception_thread_info = current_thread_info();
- if (thread_info != exception_thread_info)
+ if (thread_info != exception_thread_info) {
+ /* Save the original current_thread_info. */
+ memcpy(backup_current_thread_info, exception_thread_info, sizeof *thread_info);
memcpy(exception_thread_info, thread_info, sizeof *thread_info);
+ }
kgdb_handle_exception(0, SIGTRAP, 0, regs);
if (thread_info != exception_thread_info)
- memcpy(thread_info, exception_thread_info, sizeof *thread_info);
+ /* Restore current_thread_info lastly. */
+ memcpy(exception_thread_info, backup_current_thread_info, sizeof *thread_info);
return 1;
}
@@ -410,7 +432,6 @@
#else
linux_regs->msr |= MSR_SE;
#endif
- kgdb_single_step = 1;
atomic_set(&kgdb_cpu_doing_single_step,
raw_smp_processor_id());
}
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 710f400..1a1f2dd 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -802,16 +802,8 @@
#endif /* CONFIG_PPC_STD_MMU_64 */
#ifdef CONFIG_PPC64
if (cpu_has_feature(CPU_FTR_DSCR)) {
- if (current->thread.dscr_inherit) {
- p->thread.dscr_inherit = 1;
- p->thread.dscr = current->thread.dscr;
- } else if (0 != dscr_default) {
- p->thread.dscr_inherit = 1;
- p->thread.dscr = dscr_default;
- } else {
- p->thread.dscr_inherit = 0;
- p->thread.dscr = 0;
- }
+ p->thread.dscr_inherit = current->thread.dscr_inherit;
+ p->thread.dscr = current->thread.dscr;
}
#endif
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 0321007..8d4214a 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -198,8 +198,15 @@
struct cpu_messages *info = &per_cpu(ipi_message, cpu);
char *message = (char *)&info->messages;
+ /*
+ * Order previous accesses before accesses in the IPI handler.
+ */
+ smp_mb();
message[msg] = 1;
- mb();
+ /*
+ * cause_ipi functions are required to include a full barrier
+ * before doing whatever causes the IPI.
+ */
smp_ops->cause_ipi(cpu, info->data);
}
@@ -211,7 +218,7 @@
mb(); /* order any irq clear */
do {
- all = xchg_local(&info->messages, 0);
+ all = xchg(&info->messages, 0);
#ifdef __BIG_ENDIAN
if (all & (1 << (24 - 8 * PPC_MSG_CALL_FUNCTION)))
diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c
index f2496f2..4e3cc47 100644
--- a/arch/powerpc/kernel/syscalls.c
+++ b/arch/powerpc/kernel/syscalls.c
@@ -107,11 +107,11 @@
long ret;
if (personality(current->personality) == PER_LINUX32
- && personality == PER_LINUX)
- personality = PER_LINUX32;
+ && personality(personality) == PER_LINUX)
+ personality = (personality & ~PER_MASK) | PER_LINUX32;
ret = sys_personality(personality);
- if (ret == PER_LINUX32)
- ret = PER_LINUX;
+ if (personality(ret) == PER_LINUX32)
+ ret = (ret & ~PER_MASK) | PER_LINUX;
return ret;
}
#endif
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 3529446..8302af6 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -194,6 +194,14 @@
return sprintf(buf, "%lx\n", dscr_default);
}
+static void update_dscr(void *dummy)
+{
+ if (!current->thread.dscr_inherit) {
+ current->thread.dscr = dscr_default;
+ mtspr(SPRN_DSCR, dscr_default);
+ }
+}
+
static ssize_t __used store_dscr_default(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
@@ -206,6 +214,8 @@
return -EINVAL;
dscr_default = val;
+ on_each_cpu(update_dscr, NULL, 1);
+
return count;
}
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index be171ee..e49e931 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -535,6 +535,15 @@
trace_timer_interrupt_exit(regs);
}
+/*
+ * Hypervisor decrementer interrupts shouldn't occur but are sometimes
+ * left pending on exit from a KVM guest. We don't need to do anything
+ * to clear them, as they are edge-triggered.
+ */
+void hdec_interrupt(struct pt_regs *regs)
+{
+}
+
#ifdef CONFIG_SUSPEND
static void generic_suspend_disable_irqs(void)
{
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 1589723..ae0843f 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -972,8 +972,9 @@
cpu_has_feature(CPU_FTR_DSCR)) {
PPC_WARN_EMULATED(mtdscr, regs);
rd = (instword >> 21) & 0x1f;
- mtspr(SPRN_DSCR, regs->gpr[rd]);
+ current->thread.dscr = regs->gpr[rd];
current->thread.dscr_inherit = 1;
+ mtspr(SPRN_DSCR, current->thread.dscr);
return 0;
}
#endif
diff --git a/arch/powerpc/kvm/book3s_32_mmu_host.c b/arch/powerpc/kvm/book3s_32_mmu_host.c
index f922c29..837f13e 100644
--- a/arch/powerpc/kvm/book3s_32_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_32_mmu_host.c
@@ -211,6 +211,9 @@
pteg1 |= PP_RWRX;
}
+ if (orig_pte->may_execute)
+ kvmppc_mmu_flush_icache(hpaddr >> PAGE_SHIFT);
+
local_irq_disable();
if (pteg[rr]) {
diff --git a/arch/powerpc/kvm/book3s_64_mmu_host.c b/arch/powerpc/kvm/book3s_64_mmu_host.c
index 10fc8ec..0688b6b 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_host.c
@@ -126,6 +126,8 @@
if (!orig_pte->may_execute)
rflags |= HPTE_R_N;
+ else
+ kvmppc_mmu_flush_icache(hpaddr >> PAGE_SHIFT);
hash = hpt_hash(va, PTE_SIZE, MMU_SEGSIZE_256M);
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 5a84c8d..44b72fe 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -1421,13 +1421,13 @@
sync /* order setting ceded vs. testing prodded */
lbz r5,VCPU_PRODDED(r3)
cmpwi r5,0
- bne 1f
+ bne kvm_cede_prodded
li r0,0 /* set trap to 0 to say hcall is handled */
stw r0,VCPU_TRAP(r3)
li r0,H_SUCCESS
std r0,VCPU_GPR(R3)(r3)
BEGIN_FTR_SECTION
- b 2f /* just send it up to host on 970 */
+ b kvm_cede_exit /* just send it up to host on 970 */
END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
/*
@@ -1446,7 +1446,7 @@
or r4,r4,r0
PPC_POPCNTW(R7,R4)
cmpw r7,r8
- bge 2f
+ bge kvm_cede_exit
stwcx. r4,0,r6
bne 31b
li r0,1
@@ -1555,7 +1555,8 @@
b hcall_real_fallback
/* cede when already previously prodded case */
-1: li r0,0
+kvm_cede_prodded:
+ li r0,0
stb r0,VCPU_PRODDED(r3)
sync /* order testing prodded vs. clearing ceded */
stb r0,VCPU_CEDED(r3)
@@ -1563,7 +1564,8 @@
blr
/* we've ceded but we want to give control to the host */
-2: li r3,H_TOO_HARD
+kvm_cede_exit:
+ li r3,H_TOO_HARD
blr
secondary_too_late:
diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c
index c510fc9..a2b6671 100644
--- a/arch/powerpc/kvm/e500_tlb.c
+++ b/arch/powerpc/kvm/e500_tlb.c
@@ -322,11 +322,11 @@
static void clear_tlb1_bitmap(struct kvmppc_vcpu_e500 *vcpu_e500)
{
if (vcpu_e500->g2h_tlb1_map)
- memset(vcpu_e500->g2h_tlb1_map,
- sizeof(u64) * vcpu_e500->gtlb_params[1].entries, 0);
+ memset(vcpu_e500->g2h_tlb1_map, 0,
+ sizeof(u64) * vcpu_e500->gtlb_params[1].entries);
if (vcpu_e500->h2g_tlb1_rmap)
- memset(vcpu_e500->h2g_tlb1_rmap,
- sizeof(unsigned int) * host_tlb_params[1].entries, 0);
+ memset(vcpu_e500->h2g_tlb1_rmap, 0,
+ sizeof(unsigned int) * host_tlb_params[1].entries);
}
static void clear_tlb_privs(struct kvmppc_vcpu_e500 *vcpu_e500)
@@ -539,6 +539,9 @@
kvmppc_e500_setup_stlbe(&vcpu_e500->vcpu, gtlbe, tsize,
ref, gvaddr, stlbe);
+
+ /* Clear i-cache for new pages */
+ kvmppc_mmu_flush_icache(pfn);
}
/* XXX only map the one-one case, for now use TLB0 */
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index dd223b3..17e5b23 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -20,7 +20,7 @@
{
int err;
- err = __put_user(instr, addr);
+ __put_user_size(instr, addr, 4, err);
if (err)
return err;
asm ("dcbst 0, %0; sync; icbi 0,%0; sync; isync" : : "r" (addr));
diff --git a/arch/powerpc/lib/copyuser_power7.S b/arch/powerpc/lib/copyuser_power7.S
index f9ede7c..0d24ff1 100644
--- a/arch/powerpc/lib/copyuser_power7.S
+++ b/arch/powerpc/lib/copyuser_power7.S
@@ -288,7 +288,7 @@
std r0,16(r1)
stdu r1,-STACKFRAMESIZE(r1)
bl .enter_vmx_usercopy
- cmpwi r3,0
+ cmpwi cr1,r3,0
ld r0,STACKFRAMESIZE+16(r1)
ld r3,STACKFRAMESIZE+48(r1)
ld r4,STACKFRAMESIZE+56(r1)
@@ -326,38 +326,7 @@
dcbt r0,r8,0b01010 /* GO */
.machine pop
- /*
- * We prefetch both the source and destination using enhanced touch
- * instructions. We use a stream ID of 0 for the load side and
- * 1 for the store side.
- */
- clrrdi r6,r4,7
- clrrdi r9,r3,7
- ori r9,r9,1 /* stream=1 */
-
- srdi r7,r5,7 /* length in cachelines, capped at 0x3FF */
- cmpldi cr1,r7,0x3FF
- ble cr1,1f
- li r7,0x3FF
-1: lis r0,0x0E00 /* depth=7 */
- sldi r7,r7,7
- or r7,r7,r0
- ori r10,r7,1 /* stream=1 */
-
- lis r8,0x8000 /* GO=1 */
- clrldi r8,r8,32
-
-.machine push
-.machine "power4"
- dcbt r0,r6,0b01000
- dcbt r0,r7,0b01010
- dcbtst r0,r9,0b01000
- dcbtst r0,r10,0b01010
- eieio
- dcbt r0,r8,0b01010 /* GO */
-.machine pop
-
- beq .Lunwind_stack_nonvmx_copy
+ beq cr1,.Lunwind_stack_nonvmx_copy
/*
* If source and destination are not relatively aligned we use a
diff --git a/arch/powerpc/lib/memcpy_power7.S b/arch/powerpc/lib/memcpy_power7.S
index 0efdc51..7ba6c96 100644
--- a/arch/powerpc/lib/memcpy_power7.S
+++ b/arch/powerpc/lib/memcpy_power7.S
@@ -222,7 +222,7 @@
std r0,16(r1)
stdu r1,-STACKFRAMESIZE(r1)
bl .enter_vmx_copy
- cmpwi r3,0
+ cmpwi cr1,r3,0
ld r0,STACKFRAMESIZE+16(r1)
ld r3,STACKFRAMESIZE+48(r1)
ld r4,STACKFRAMESIZE+56(r1)
@@ -260,7 +260,7 @@
dcbt r0,r8,0b01010 /* GO */
.machine pop
- beq .Lunwind_stack_nonvmx_copy
+ beq cr1,.Lunwind_stack_nonvmx_copy
/*
* If source and destination are not relatively aligned we use a
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index baaafde..fbdad0e 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -469,6 +469,7 @@
__flush_dcache_icache_phys(page_to_pfn(page) << PAGE_SHIFT);
#endif
}
+EXPORT_SYMBOL(flush_dcache_icache_page);
void clear_user_page(void *page, unsigned long vaddr, struct page *pg)
{
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 39b1597..59213cf 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -1436,11 +1436,11 @@
/*
* Update the node maps and sysfs entries for each cpu whose home node
- * has changed.
+ * has changed. Returns 1 when the topology has changed, and 0 otherwise.
*/
int arch_update_cpu_topology(void)
{
- int cpu, nid, old_nid;
+ int cpu, nid, old_nid, changed = 0;
unsigned int associativity[VPHN_ASSOC_BUFSIZE] = {0};
struct device *dev;
@@ -1466,9 +1466,10 @@
dev = get_cpu_device(cpu);
if (dev)
kobject_uevent(&dev->kobj, KOBJ_CHANGE);
+ changed = 1;
}
- return 1;
+ return changed;
}
static void topology_work_fn(struct work_struct *work)
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 77b49dd..7cd2dbd 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -1431,7 +1431,7 @@
if (!event->hw.idx || is_limited_pmc(event->hw.idx))
continue;
val = read_pmc(event->hw.idx);
- if ((int)val < 0) {
+ if (pmc_overflow(val)) {
/* event has overflowed */
found = 1;
record_and_restart(event, val, regs);
diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c
index 3ef4625..7698b6e 100644
--- a/arch/powerpc/platforms/powernv/smp.c
+++ b/arch/powerpc/platforms/powernv/smp.c
@@ -106,14 +106,6 @@
{
unsigned int cpu;
- /* If powersave_nap is enabled, use NAP mode, else just
- * spin aimlessly
- */
- if (!powersave_nap) {
- generic_mach_cpu_die();
- return;
- }
-
/* Standard hot unplug procedure */
local_irq_disable();
idle_task_exit();
@@ -128,7 +120,7 @@
*/
mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~(u64)LPCR_PECE1);
while (!generic_check_cpu_restart(cpu)) {
- power7_idle();
+ power7_nap();
if (!generic_check_cpu_restart(cpu)) {
DBG("CPU%d Unexpected exit while offline !\n", cpu);
/* We may be getting an IPI, so we re-enable
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index a7b2a60..c37f461 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -465,7 +465,7 @@
iounmap(hose->cfg_data);
iounmap(hose->cfg_addr);
pcibios_free_controller(hose);
- return 0;
+ return -ENODEV;
}
setup_pci_cmd(hose);
@@ -827,6 +827,7 @@
void __devinit fsl_pci_init(void)
{
+ int ret;
struct device_node *node;
struct pci_controller *hose;
dma_addr_t max = 0xffffffff;
@@ -855,10 +856,12 @@
if (!fsl_pci_primary)
fsl_pci_primary = node;
- fsl_add_bridge(node, fsl_pci_primary == node);
- hose = pci_find_hose_for_OF_device(node);
- max = min(max, hose->dma_window_base_cur +
- hose->dma_window_size);
+ ret = fsl_add_bridge(node, fsl_pci_primary == node);
+ if (ret == 0) {
+ hose = pci_find_hose_for_OF_device(node);
+ max = min(max, hose->dma_window_base_cur +
+ hose->dma_window_size);
+ }
}
}
diff --git a/arch/powerpc/sysdev/mpic_msgr.c b/arch/powerpc/sysdev/mpic_msgr.c
index 483d8fa..e961f8c 100644
--- a/arch/powerpc/sysdev/mpic_msgr.c
+++ b/arch/powerpc/sysdev/mpic_msgr.c
@@ -14,6 +14,9 @@
#include <linux/list.h>
#include <linux/of_platform.h>
#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/slab.h>
#include <asm/prom.h>
#include <asm/hw_irq.h>
#include <asm/ppc-pci.h>
diff --git a/arch/powerpc/sysdev/xics/icp-hv.c b/arch/powerpc/sysdev/xics/icp-hv.c
index 14469cf..df0fc58 100644
--- a/arch/powerpc/sysdev/xics/icp-hv.c
+++ b/arch/powerpc/sysdev/xics/icp-hv.c
@@ -65,7 +65,11 @@
static inline void icp_hv_set_qirr(int n_cpu , u8 value)
{
int hw_cpu = get_hard_smp_processor_id(n_cpu);
- long rc = plpar_hcall_norets(H_IPI, hw_cpu, value);
+ long rc;
+
+ /* Make sure all previous accesses are ordered before IPI sending */
+ mb();
+ rc = plpar_hcall_norets(H_IPI, hw_cpu, value);
if (rc != H_SUCCESS) {
pr_err("%s: bad return code qirr cpu=%d hw_cpu=%d mfrr=0x%x "
"returned %ld\n", __func__, n_cpu, hw_cpu, value, rc);
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index eab3492..9b49c65e 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -17,6 +17,7 @@
#include <linux/reboot.h>
#include <linux/delay.h>
#include <linux/kallsyms.h>
+#include <linux/kmsg_dump.h>
#include <linux/cpumask.h>
#include <linux/export.h>
#include <linux/sysrq.h>
@@ -894,13 +895,13 @@
#endif
default:
printf("Unrecognized command: ");
- do {
+ do {
if (' ' < cmd && cmd <= '~')
putchar(cmd);
else
printf("\\x%x", cmd);
cmd = inchar();
- } while (cmd != '\n');
+ } while (cmd != '\n');
printf(" (type ? for help)\n");
break;
}
@@ -1097,7 +1098,7 @@
return 1;
}
-static char *breakpoint_help_string =
+static char *breakpoint_help_string =
"Breakpoint command usage:\n"
"b show breakpoints\n"
"b <addr> [cnt] set breakpoint at given instr addr\n"
@@ -1193,7 +1194,7 @@
default:
termch = cmd;
- cmd = skipbl();
+ cmd = skipbl();
if (cmd == '?') {
printf(breakpoint_help_string);
break;
@@ -1359,7 +1360,7 @@
sp + REGS_OFFSET);
break;
}
- printf("--- Exception: %lx %s at ", regs.trap,
+ printf("--- Exception: %lx %s at ", regs.trap,
getvecname(TRAP(®s)));
pc = regs.nip;
lr = regs.link;
@@ -1623,14 +1624,14 @@
cmd = skipbl();
if (cmd == '\n') {
- unsigned long sp, toc;
+ unsigned long sp, toc;
asm("mr %0,1" : "=r" (sp) :);
asm("mr %0,2" : "=r" (toc) :);
printf("msr = "REG" sprg0= "REG"\n",
mfmsr(), mfspr(SPRN_SPRG0));
printf("pvr = "REG" sprg1= "REG"\n",
- mfspr(SPRN_PVR), mfspr(SPRN_SPRG1));
+ mfspr(SPRN_PVR), mfspr(SPRN_SPRG1));
printf("dec = "REG" sprg2= "REG"\n",
mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));
printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3));
@@ -1783,7 +1784,7 @@
static int brev;
static int mnoread;
-static char *memex_help_string =
+static char *memex_help_string =
"Memory examine command usage:\n"
"m [addr] [flags] examine/change memory\n"
" addr is optional. will start where left off.\n"
@@ -1798,7 +1799,7 @@
"NOTE: flags are saved as defaults\n"
"";
-static char *memex_subcmd_help_string =
+static char *memex_subcmd_help_string =
"Memory examine subcommands:\n"
" hexval write this val to current location\n"
" 'string' write chars from string to this location\n"
@@ -2064,7 +2065,7 @@
nr = mread(adrs, temp, r);
adrs += nr;
for (m = 0; m < r; ++m) {
- if ((m & (sizeof(long) - 1)) == 0 && m > 0)
+ if ((m & (sizeof(long) - 1)) == 0 && m > 0)
putchar(' ');
if (m < nr)
printf("%.2x", temp[m]);
@@ -2072,7 +2073,7 @@
printf("%s", fault_chars[fault_type]);
}
for (; m < 16; ++m) {
- if ((m & (sizeof(long) - 1)) == 0)
+ if ((m & (sizeof(long) - 1)) == 0)
putchar(' ');
printf(" ");
}
@@ -2148,45 +2149,28 @@
void
dump_log_buf(void)
{
- const unsigned long size = 128;
- unsigned long end, addr;
- unsigned char buf[size + 1];
+ struct kmsg_dumper dumper = { .active = 1 };
+ unsigned char buf[128];
+ size_t len;
- addr = 0;
- buf[size] = '\0';
+ if (setjmp(bus_error_jmp) != 0) {
+ printf("Error dumping printk buffer!\n");
+ return;
+ }
- if (setjmp(bus_error_jmp) != 0) {
- printf("Unable to lookup symbol __log_buf!\n");
- return;
- }
+ catch_memory_errors = 1;
+ sync();
- catch_memory_errors = 1;
- sync();
- addr = kallsyms_lookup_name("__log_buf");
+ kmsg_dump_rewind_nolock(&dumper);
+ while (kmsg_dump_get_line_nolock(&dumper, false, buf, sizeof(buf), &len)) {
+ buf[len] = '\0';
+ printf("%s", buf);
+ }
- if (! addr)
- printf("Symbol __log_buf not found!\n");
- else {
- end = addr + (1 << CONFIG_LOG_BUF_SHIFT);
- while (addr < end) {
- if (! mread(addr, buf, size)) {
- printf("Can't read memory at address 0x%lx\n", addr);
- break;
- }
-
- printf("%s", buf);
-
- if (strlen(buf) < size)
- break;
-
- addr += size;
- }
- }
-
- sync();
- /* wait a little while to see if we get a machine check */
- __delay(200);
- catch_memory_errors = 0;
+ sync();
+ /* wait a little while to see if we get a machine check */
+ __delay(200);
+ catch_memory_errors = 0;
}
/*
diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h
index 32e8449..9b94a16 100644
--- a/arch/s390/include/asm/elf.h
+++ b/arch/s390/include/asm/elf.h
@@ -180,7 +180,8 @@
#define ELF_PLATFORM (elf_platform)
#ifndef CONFIG_64BIT
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex) \
+ set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
#else /* CONFIG_64BIT */
#define SET_PERSONALITY(ex) \
do { \
diff --git a/arch/s390/include/asm/posix_types.h b/arch/s390/include/asm/posix_types.h
index 7bcc14e..bf2a2ad 100644
--- a/arch/s390/include/asm/posix_types.h
+++ b/arch/s390/include/asm/posix_types.h
@@ -13,6 +13,7 @@
*/
typedef unsigned long __kernel_size_t;
+typedef long __kernel_ssize_t;
#define __kernel_size_t __kernel_size_t
typedef unsigned short __kernel_old_dev_t;
@@ -25,7 +26,6 @@
typedef unsigned short __kernel_ipc_pid_t;
typedef unsigned short __kernel_uid_t;
typedef unsigned short __kernel_gid_t;
-typedef int __kernel_ssize_t;
typedef int __kernel_ptrdiff_t;
#else /* __s390x__ */
@@ -35,7 +35,6 @@
typedef int __kernel_ipc_pid_t;
typedef unsigned int __kernel_uid_t;
typedef unsigned int __kernel_gid_t;
-typedef long __kernel_ssize_t;
typedef long __kernel_ptrdiff_t;
typedef unsigned long __kernel_sigset_t; /* at least 32 bits */
diff --git a/arch/s390/include/asm/smp.h b/arch/s390/include/asm/smp.h
index a0a8340..ce26ac3 100644
--- a/arch/s390/include/asm/smp.h
+++ b/arch/s390/include/asm/smp.h
@@ -44,6 +44,7 @@
}
static inline int smp_find_processor_id(int address) { return 0; }
+static inline int smp_store_status(int cpu) { return 0; }
static inline int smp_vcpu_scheduled(int cpu) { return 1; }
static inline void smp_yield_cpu(int cpu) { }
static inline void smp_yield(void) { }
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index bbaf2c5..457475f 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -409,7 +409,8 @@
line->valid = 1;
err = parse_chan_pair(new, line, n, opts, error_out);
if (!err) {
- struct device *d = tty_register_device(driver, n, NULL);
+ struct device *d = tty_port_register_device(&line->port,
+ driver, n, NULL);
if (IS_ERR(d)) {
*error_out = "Failed to register device";
err = PTR_ERR(d);
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c
index f602385..0748fe0 100644
--- a/arch/um/os-Linux/time.c
+++ b/arch/um/os-Linux/time.c
@@ -114,7 +114,7 @@
skew += this_tick - last_tick;
while (skew >= one_tick) {
- alarm_handler(SIGVTALRM, NULL);
+ alarm_handler(SIGVTALRM, NULL, NULL);
skew -= one_tick;
}
diff --git a/arch/x86/include/asm/spinlock.h b/arch/x86/include/asm/spinlock.h
index b315a33..33692ea 100644
--- a/arch/x86/include/asm/spinlock.h
+++ b/arch/x86/include/asm/spinlock.h
@@ -12,8 +12,7 @@
* Simple spin lock operations. There are two variants, one clears IRQ's
* on the local processor, one does not.
*
- * These are fair FIFO ticket locks, which are currently limited to 256
- * CPUs.
+ * These are fair FIFO ticket locks, which support up to 2^16 CPUs.
*
* (the type definitions are in asm/spinlock_types.h)
*/
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index afb7ff7..ced4534 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -165,7 +165,7 @@
#endif
#ifdef P6_NOP1
-static const unsigned char __initconst_or_module p6nops[] =
+static const unsigned char p6nops[] =
{
P6_NOP1,
P6_NOP2,
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
index 7ad683d..d44f782 100644
--- a/arch/x86/kernel/irq.c
+++ b/arch/x86/kernel/irq.c
@@ -270,7 +270,7 @@
if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
break_affinity = 1;
- affinity = cpu_all_mask;
+ affinity = cpu_online_mask;
}
chip = irq_data_get_irq_chip(data);
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
index 8a2ce8f..82746f9 100644
--- a/arch/x86/kernel/microcode_amd.c
+++ b/arch/x86/kernel/microcode_amd.c
@@ -143,11 +143,12 @@
unsigned int *current_size)
{
struct microcode_header_amd *mc_hdr;
- unsigned int actual_size;
+ unsigned int actual_size, patch_size;
u16 equiv_cpu_id;
/* size of the current patch we're staring at */
- *current_size = *(u32 *)(ucode_ptr + 4) + SECTION_HDR_SIZE;
+ patch_size = *(u32 *)(ucode_ptr + 4);
+ *current_size = patch_size + SECTION_HDR_SIZE;
equiv_cpu_id = find_equiv_id();
if (!equiv_cpu_id)
@@ -174,7 +175,7 @@
/*
* now that the header looks sane, verify its size
*/
- actual_size = verify_ucode_size(cpu, *current_size, leftover_size);
+ actual_size = verify_ucode_size(cpu, patch_size, leftover_size);
if (!actual_size)
return 0;
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 97d9a99..a3b57a2 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -475,13 +475,26 @@
return address_mask(ctxt, reg);
}
+static void masked_increment(ulong *reg, ulong mask, int inc)
+{
+ assign_masked(reg, *reg + inc, mask);
+}
+
static inline void
register_address_increment(struct x86_emulate_ctxt *ctxt, unsigned long *reg, int inc)
{
+ ulong mask;
+
if (ctxt->ad_bytes == sizeof(unsigned long))
- *reg += inc;
+ mask = ~0UL;
else
- *reg = (*reg & ~ad_mask(ctxt)) | ((*reg + inc) & ad_mask(ctxt));
+ mask = ad_mask(ctxt);
+ masked_increment(reg, mask, inc);
+}
+
+static void rsp_increment(struct x86_emulate_ctxt *ctxt, int inc)
+{
+ masked_increment(&ctxt->regs[VCPU_REGS_RSP], stack_mask(ctxt), inc);
}
static inline void jmp_rel(struct x86_emulate_ctxt *ctxt, int rel)
@@ -1522,8 +1535,8 @@
{
struct segmented_address addr;
- register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RSP], -bytes);
- addr.ea = register_address(ctxt, ctxt->regs[VCPU_REGS_RSP]);
+ rsp_increment(ctxt, -bytes);
+ addr.ea = ctxt->regs[VCPU_REGS_RSP] & stack_mask(ctxt);
addr.seg = VCPU_SREG_SS;
return segmented_write(ctxt, addr, data, bytes);
@@ -1542,13 +1555,13 @@
int rc;
struct segmented_address addr;
- addr.ea = register_address(ctxt, ctxt->regs[VCPU_REGS_RSP]);
+ addr.ea = ctxt->regs[VCPU_REGS_RSP] & stack_mask(ctxt);
addr.seg = VCPU_SREG_SS;
rc = segmented_read(ctxt, addr, dest, len);
if (rc != X86EMUL_CONTINUE)
return rc;
- register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RSP], len);
+ rsp_increment(ctxt, len);
return rc;
}
@@ -1688,8 +1701,7 @@
while (reg >= VCPU_REGS_RAX) {
if (reg == VCPU_REGS_RSP) {
- register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RSP],
- ctxt->op_bytes);
+ rsp_increment(ctxt, ctxt->op_bytes);
--reg;
}
@@ -2825,7 +2837,7 @@
rc = emulate_pop(ctxt, &ctxt->dst.val, ctxt->op_bytes);
if (rc != X86EMUL_CONTINUE)
return rc;
- register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RSP], ctxt->src.val);
+ rsp_increment(ctxt, ctxt->src.val);
return X86EMUL_CONTINUE;
}
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 01ca004..7fbd0d2 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -4113,16 +4113,21 @@
LIST_HEAD(invalid_list);
/*
+ * Never scan more than sc->nr_to_scan VM instances.
+ * Will not hit this condition practically since we do not try
+ * to shrink more than one VM and it is very unlikely to see
+ * !n_used_mmu_pages so many times.
+ */
+ if (!nr_to_scan--)
+ break;
+ /*
* n_used_mmu_pages is accessed without holding kvm->mmu_lock
* here. We may skip a VM instance errorneosly, but we do not
* want to shrink a VM that only started to populate its MMU
* anyway.
*/
- if (kvm->arch.n_used_mmu_pages > 0) {
- if (!nr_to_scan--)
- break;
+ if (!kvm->arch.n_used_mmu_pages)
continue;
- }
idx = srcu_read_lock(&kvm->srcu);
spin_lock(&kvm->mmu_lock);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 42bce48..148ed66 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -806,7 +806,7 @@
* kvm-specific. Those are put in the beginning of the list.
*/
-#define KVM_SAVE_MSRS_BEGIN 9
+#define KVM_SAVE_MSRS_BEGIN 10
static u32 msrs_to_save[] = {
MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK,
MSR_KVM_SYSTEM_TIME_NEW, MSR_KVM_WALL_CLOCK_NEW,
@@ -2000,6 +2000,9 @@
case MSR_KVM_STEAL_TIME:
data = vcpu->arch.st.msr_val;
break;
+ case MSR_KVM_PV_EOI_EN:
+ data = vcpu->arch.pv_eoi.msr_val;
+ break;
case MSR_IA32_P5_MC_ADDR:
case MSR_IA32_P5_MC_TYPE:
case MSR_IA32_MCG_CAP:
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index bf4bda6..9642d4a 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -31,7 +31,6 @@
#include <linux/pci.h>
#include <linux/gfp.h>
#include <linux/memblock.h>
-#include <linux/syscore_ops.h>
#include <xen/xen.h>
#include <xen/interface/xen.h>
@@ -1470,130 +1469,38 @@
#endif
}
-#ifdef CONFIG_XEN_PVHVM
-/*
- * The pfn containing the shared_info is located somewhere in RAM. This
- * will cause trouble if the current kernel is doing a kexec boot into a
- * new kernel. The new kernel (and its startup code) can not know where
- * the pfn is, so it can not reserve the page. The hypervisor will
- * continue to update the pfn, and as a result memory corruption occours
- * in the new kernel.
- *
- * One way to work around this issue is to allocate a page in the
- * xen-platform pci device's BAR memory range. But pci init is done very
- * late and the shared_info page is already in use very early to read
- * the pvclock. So moving the pfn from RAM to MMIO is racy because some
- * code paths on other vcpus could access the pfn during the small
- * window when the old pfn is moved to the new pfn. There is even a
- * small window were the old pfn is not backed by a mfn, and during that
- * time all reads return -1.
- *
- * Because it is not known upfront where the MMIO region is located it
- * can not be used right from the start in xen_hvm_init_shared_info.
- *
- * To minimise trouble the move of the pfn is done shortly before kexec.
- * This does not eliminate the race because all vcpus are still online
- * when the syscore_ops will be called. But hopefully there is no work
- * pending at this point in time. Also the syscore_op is run last which
- * reduces the risk further.
- */
-
-static struct shared_info *xen_hvm_shared_info;
-
-static void xen_hvm_connect_shared_info(unsigned long pfn)
+void __ref xen_hvm_init_shared_info(void)
{
+ int cpu;
struct xen_add_to_physmap xatp;
+ static struct shared_info *shared_info_page = 0;
+ if (!shared_info_page)
+ shared_info_page = (struct shared_info *)
+ extend_brk(PAGE_SIZE, PAGE_SIZE);
xatp.domid = DOMID_SELF;
xatp.idx = 0;
xatp.space = XENMAPSPACE_shared_info;
- xatp.gpfn = pfn;
+ xatp.gpfn = __pa(shared_info_page) >> PAGE_SHIFT;
if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
BUG();
-}
-static void xen_hvm_set_shared_info(struct shared_info *sip)
-{
- int cpu;
-
- HYPERVISOR_shared_info = sip;
+ HYPERVISOR_shared_info = (struct shared_info *)shared_info_page;
/* xen_vcpu is a pointer to the vcpu_info struct in the shared_info
* page, we use it in the event channel upcall and in some pvclock
* related functions. We don't need the vcpu_info placement
* optimizations because we don't use any pv_mmu or pv_irq op on
* HVM.
- * When xen_hvm_set_shared_info is run at boot time only vcpu 0 is
- * online but xen_hvm_set_shared_info is run at resume time too and
+ * When xen_hvm_init_shared_info is run at boot time only vcpu 0 is
+ * online but xen_hvm_init_shared_info is run at resume time too and
* in that case multiple vcpus might be online. */
for_each_online_cpu(cpu) {
per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
}
}
-/* Reconnect the shared_info pfn to a mfn */
-void xen_hvm_resume_shared_info(void)
-{
- xen_hvm_connect_shared_info(__pa(xen_hvm_shared_info) >> PAGE_SHIFT);
-}
-
-#ifdef CONFIG_KEXEC
-static struct shared_info *xen_hvm_shared_info_kexec;
-static unsigned long xen_hvm_shared_info_pfn_kexec;
-
-/* Remember a pfn in MMIO space for kexec reboot */
-void __devinit xen_hvm_prepare_kexec(struct shared_info *sip, unsigned long pfn)
-{
- xen_hvm_shared_info_kexec = sip;
- xen_hvm_shared_info_pfn_kexec = pfn;
-}
-
-static void xen_hvm_syscore_shutdown(void)
-{
- struct xen_memory_reservation reservation = {
- .domid = DOMID_SELF,
- .nr_extents = 1,
- };
- unsigned long prev_pfn;
- int rc;
-
- if (!xen_hvm_shared_info_kexec)
- return;
-
- prev_pfn = __pa(xen_hvm_shared_info) >> PAGE_SHIFT;
- set_xen_guest_handle(reservation.extent_start, &prev_pfn);
-
- /* Move pfn to MMIO, disconnects previous pfn from mfn */
- xen_hvm_connect_shared_info(xen_hvm_shared_info_pfn_kexec);
-
- /* Update pointers, following hypercall is also a memory barrier */
- xen_hvm_set_shared_info(xen_hvm_shared_info_kexec);
-
- /* Allocate new mfn for previous pfn */
- do {
- rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation);
- if (rc == 0)
- msleep(123);
- } while (rc == 0);
-
- /* Make sure the previous pfn is really connected to a (new) mfn */
- BUG_ON(rc != 1);
-}
-
-static struct syscore_ops xen_hvm_syscore_ops = {
- .shutdown = xen_hvm_syscore_shutdown,
-};
-#endif
-
-/* Use a pfn in RAM, may move to MMIO before kexec. */
-static void __init xen_hvm_init_shared_info(void)
-{
- /* Remember pointer for resume */
- xen_hvm_shared_info = extend_brk(PAGE_SIZE, PAGE_SIZE);
- xen_hvm_connect_shared_info(__pa(xen_hvm_shared_info) >> PAGE_SHIFT);
- xen_hvm_set_shared_info(xen_hvm_shared_info);
-}
-
+#ifdef CONFIG_XEN_PVHVM
static void __init init_hvm_pv_info(void)
{
int major, minor;
@@ -1644,9 +1551,6 @@
init_hvm_pv_info();
xen_hvm_init_shared_info();
-#ifdef CONFIG_KEXEC
- register_syscore_ops(&xen_hvm_syscore_ops);
-#endif
if (xen_feature(XENFEAT_hvm_callback_vector))
xen_have_vector_callback = 1;
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index b65a761..5141d80 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -1283,7 +1283,7 @@
cpumask_clear_cpu(smp_processor_id(), to_cpumask(args->mask));
args->op.cmd = MMUEXT_TLB_FLUSH_MULTI;
- if (start != TLB_FLUSH_ALL && (end - start) <= PAGE_SIZE) {
+ if (end != TLB_FLUSH_ALL && (end - start) <= PAGE_SIZE) {
args->op.cmd = MMUEXT_INVLPG_MULTI;
args->op.arg1.linear_addr = start;
}
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c
index b2e91d4..76ba0e9 100644
--- a/arch/x86/xen/p2m.c
+++ b/arch/x86/xen/p2m.c
@@ -196,9 +196,11 @@
/* When we populate back during bootup, the amount of pages can vary. The
* max we have is seen is 395979, but that does not mean it can't be more.
- * But some machines can have 3GB I/O holes even. So lets reserve enough
- * for 4GB of I/O and E820 holes. */
-RESERVE_BRK(p2m_populated, PMD_SIZE * 4);
+ * Some machines can have 3GB I/O holes even. With early_can_reuse_p2m_middle
+ * it can re-use Xen provided mfn_list array, so we only need to allocate at
+ * most three P2M top nodes. */
+RESERVE_BRK(p2m_populated, PAGE_SIZE * 3);
+
static inline unsigned p2m_top_index(unsigned long pfn)
{
BUG_ON(pfn >= MAX_P2M_PFN);
@@ -575,12 +577,99 @@
}
return true;
}
+
+/*
+ * Skim over the P2M tree looking at pages that are either filled with
+ * INVALID_P2M_ENTRY or with 1:1 PFNs. If found, re-use that page and
+ * replace the P2M leaf with a p2m_missing or p2m_identity.
+ * Stick the old page in the new P2M tree location.
+ */
+bool __init early_can_reuse_p2m_middle(unsigned long set_pfn, unsigned long set_mfn)
+{
+ unsigned topidx;
+ unsigned mididx;
+ unsigned ident_pfns;
+ unsigned inv_pfns;
+ unsigned long *p2m;
+ unsigned long *mid_mfn_p;
+ unsigned idx;
+ unsigned long pfn;
+
+ /* We only look when this entails a P2M middle layer */
+ if (p2m_index(set_pfn))
+ return false;
+
+ for (pfn = 0; pfn < MAX_DOMAIN_PAGES; pfn += P2M_PER_PAGE) {
+ topidx = p2m_top_index(pfn);
+
+ if (!p2m_top[topidx])
+ continue;
+
+ if (p2m_top[topidx] == p2m_mid_missing)
+ continue;
+
+ mididx = p2m_mid_index(pfn);
+ p2m = p2m_top[topidx][mididx];
+ if (!p2m)
+ continue;
+
+ if ((p2m == p2m_missing) || (p2m == p2m_identity))
+ continue;
+
+ if ((unsigned long)p2m == INVALID_P2M_ENTRY)
+ continue;
+
+ ident_pfns = 0;
+ inv_pfns = 0;
+ for (idx = 0; idx < P2M_PER_PAGE; idx++) {
+ /* IDENTITY_PFNs are 1:1 */
+ if (p2m[idx] == IDENTITY_FRAME(pfn + idx))
+ ident_pfns++;
+ else if (p2m[idx] == INVALID_P2M_ENTRY)
+ inv_pfns++;
+ else
+ break;
+ }
+ if ((ident_pfns == P2M_PER_PAGE) || (inv_pfns == P2M_PER_PAGE))
+ goto found;
+ }
+ return false;
+found:
+ /* Found one, replace old with p2m_identity or p2m_missing */
+ p2m_top[topidx][mididx] = (ident_pfns ? p2m_identity : p2m_missing);
+ /* And the other for save/restore.. */
+ mid_mfn_p = p2m_top_mfn_p[topidx];
+ /* NOTE: Even if it is a p2m_identity it should still be point to
+ * a page filled with INVALID_P2M_ENTRY entries. */
+ mid_mfn_p[mididx] = virt_to_mfn(p2m_missing);
+
+ /* Reset where we want to stick the old page in. */
+ topidx = p2m_top_index(set_pfn);
+ mididx = p2m_mid_index(set_pfn);
+
+ /* This shouldn't happen */
+ if (WARN_ON(p2m_top[topidx] == p2m_mid_missing))
+ early_alloc_p2m(set_pfn);
+
+ if (WARN_ON(p2m_top[topidx][mididx] != p2m_missing))
+ return false;
+
+ p2m_init(p2m);
+ p2m_top[topidx][mididx] = p2m;
+ mid_mfn_p = p2m_top_mfn_p[topidx];
+ mid_mfn_p[mididx] = virt_to_mfn(p2m);
+
+ return true;
+}
bool __init early_set_phys_to_machine(unsigned long pfn, unsigned long mfn)
{
if (unlikely(!__set_phys_to_machine(pfn, mfn))) {
if (!early_alloc_p2m(pfn))
return false;
+ if (early_can_reuse_p2m_middle(pfn, mfn))
+ return __set_phys_to_machine(pfn, mfn);
+
if (!early_alloc_p2m_middle(pfn, false /* boundary crossover OK!*/))
return false;
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index ead8557..d11ca11 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -78,9 +78,16 @@
memblock_reserve(start, size);
xen_max_p2m_pfn = PFN_DOWN(start + size);
+ for (pfn = PFN_DOWN(start); pfn < xen_max_p2m_pfn; pfn++) {
+ unsigned long mfn = pfn_to_mfn(pfn);
- for (pfn = PFN_DOWN(start); pfn <= xen_max_p2m_pfn; pfn++)
+ if (WARN(mfn == pfn, "Trying to over-write 1-1 mapping (pfn: %lx)\n", pfn))
+ continue;
+ WARN(mfn != INVALID_P2M_ENTRY, "Trying to remove %lx which has %lx mfn!\n",
+ pfn, mfn);
+
__set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
+ }
}
static unsigned long __init xen_do_chunk(unsigned long start,
diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c
index ae8a00c..45329c8 100644
--- a/arch/x86/xen/suspend.c
+++ b/arch/x86/xen/suspend.c
@@ -30,7 +30,7 @@
{
#ifdef CONFIG_XEN_PVHVM
int cpu;
- xen_hvm_resume_shared_info();
+ xen_hvm_init_shared_info();
xen_callback_vector();
xen_unplug_emulated_devices();
if (xen_feature(XENFEAT_hvm_safe_pvclock)) {
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index 1e4329e..202d4c1 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -41,7 +41,7 @@
void xen_vcpu_restore(void);
void xen_callback_vector(void);
-void xen_hvm_resume_shared_info(void);
+void xen_hvm_init_shared_info(void);
void xen_unplug_emulated_devices(void);
void __init xen_build_dynamic_phys_to_machine(void);
diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c
index f9726f6..2cd3d3a 100644
--- a/arch/xtensa/platforms/iss/console.c
+++ b/arch/xtensa/platforms/iss/console.c
@@ -223,6 +223,7 @@
serial_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(serial_driver, &serial_ops);
+ tty_port_link_device(&serial_port, serial_driver, 0);
if (tty_register_driver(serial_driver))
panic("Couldn't register serial driver\n");
diff --git a/block/blk-lib.c b/block/blk-lib.c
index 2b461b4..19cc761 100644
--- a/block/blk-lib.c
+++ b/block/blk-lib.c
@@ -44,6 +44,7 @@
struct request_queue *q = bdev_get_queue(bdev);
int type = REQ_WRITE | REQ_DISCARD;
unsigned int max_discard_sectors;
+ unsigned int granularity, alignment, mask;
struct bio_batch bb;
struct bio *bio;
int ret = 0;
@@ -54,18 +55,20 @@
if (!blk_queue_discard(q))
return -EOPNOTSUPP;
+ /* Zero-sector (unknown) and one-sector granularities are the same. */
+ granularity = max(q->limits.discard_granularity >> 9, 1U);
+ mask = granularity - 1;
+ alignment = (bdev_discard_alignment(bdev) >> 9) & mask;
+
/*
* Ensure that max_discard_sectors is of the proper
- * granularity
+ * granularity, so that requests stay aligned after a split.
*/
max_discard_sectors = min(q->limits.max_discard_sectors, UINT_MAX >> 9);
+ max_discard_sectors = round_down(max_discard_sectors, granularity);
if (unlikely(!max_discard_sectors)) {
/* Avoid infinite loop below. Being cautious never hurts. */
return -EOPNOTSUPP;
- } else if (q->limits.discard_granularity) {
- unsigned int disc_sects = q->limits.discard_granularity >> 9;
-
- max_discard_sectors &= ~(disc_sects - 1);
}
if (flags & BLKDEV_DISCARD_SECURE) {
@@ -79,25 +82,37 @@
bb.wait = &wait;
while (nr_sects) {
+ unsigned int req_sects;
+ sector_t end_sect;
+
bio = bio_alloc(gfp_mask, 1);
if (!bio) {
ret = -ENOMEM;
break;
}
+ req_sects = min_t(sector_t, nr_sects, max_discard_sectors);
+
+ /*
+ * If splitting a request, and the next starting sector would be
+ * misaligned, stop the discard at the previous aligned sector.
+ */
+ end_sect = sector + req_sects;
+ if (req_sects < nr_sects && (end_sect & mask) != alignment) {
+ end_sect =
+ round_down(end_sect - alignment, granularity)
+ + alignment;
+ req_sects = end_sect - sector;
+ }
+
bio->bi_sector = sector;
bio->bi_end_io = bio_batch_end_io;
bio->bi_bdev = bdev;
bio->bi_private = &bb;
- if (nr_sects > max_discard_sectors) {
- bio->bi_size = max_discard_sectors << 9;
- nr_sects -= max_discard_sectors;
- sector += max_discard_sectors;
- } else {
- bio->bi_size = nr_sects << 9;
- nr_sects = 0;
- }
+ bio->bi_size = req_sects << 9;
+ nr_sects -= req_sects;
+ sector = end_sect;
atomic_inc(&bb.done);
submit_bio(type, bio);
diff --git a/block/blk-merge.c b/block/blk-merge.c
index 160035f..e76279e 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -110,6 +110,49 @@
return 0;
}
+static void
+__blk_segment_map_sg(struct request_queue *q, struct bio_vec *bvec,
+ struct scatterlist *sglist, struct bio_vec **bvprv,
+ struct scatterlist **sg, int *nsegs, int *cluster)
+{
+
+ int nbytes = bvec->bv_len;
+
+ if (*bvprv && *cluster) {
+ if ((*sg)->length + nbytes > queue_max_segment_size(q))
+ goto new_segment;
+
+ if (!BIOVEC_PHYS_MERGEABLE(*bvprv, bvec))
+ goto new_segment;
+ if (!BIOVEC_SEG_BOUNDARY(q, *bvprv, bvec))
+ goto new_segment;
+
+ (*sg)->length += nbytes;
+ } else {
+new_segment:
+ if (!*sg)
+ *sg = sglist;
+ else {
+ /*
+ * If the driver previously mapped a shorter
+ * list, we could see a termination bit
+ * prematurely unless it fully inits the sg
+ * table on each mapping. We KNOW that there
+ * must be more entries here or the driver
+ * would be buggy, so force clear the
+ * termination bit to avoid doing a full
+ * sg_init_table() in drivers for each command.
+ */
+ (*sg)->page_link &= ~0x02;
+ *sg = sg_next(*sg);
+ }
+
+ sg_set_page(*sg, bvec->bv_page, nbytes, bvec->bv_offset);
+ (*nsegs)++;
+ }
+ *bvprv = bvec;
+}
+
/*
* map a request to scatterlist, return number of sg entries setup. Caller
* must make sure sg can hold rq->nr_phys_segments entries
@@ -131,41 +174,8 @@
bvprv = NULL;
sg = NULL;
rq_for_each_segment(bvec, rq, iter) {
- int nbytes = bvec->bv_len;
-
- if (bvprv && cluster) {
- if (sg->length + nbytes > queue_max_segment_size(q))
- goto new_segment;
-
- if (!BIOVEC_PHYS_MERGEABLE(bvprv, bvec))
- goto new_segment;
- if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bvec))
- goto new_segment;
-
- sg->length += nbytes;
- } else {
-new_segment:
- if (!sg)
- sg = sglist;
- else {
- /*
- * If the driver previously mapped a shorter
- * list, we could see a termination bit
- * prematurely unless it fully inits the sg
- * table on each mapping. We KNOW that there
- * must be more entries here or the driver
- * would be buggy, so force clear the
- * termination bit to avoid doing a full
- * sg_init_table() in drivers for each command.
- */
- sg->page_link &= ~0x02;
- sg = sg_next(sg);
- }
-
- sg_set_page(sg, bvec->bv_page, nbytes, bvec->bv_offset);
- nsegs++;
- }
- bvprv = bvec;
+ __blk_segment_map_sg(q, bvec, sglist, &bvprv, &sg,
+ &nsegs, &cluster);
} /* segments in rq */
@@ -199,6 +209,43 @@
}
EXPORT_SYMBOL(blk_rq_map_sg);
+/**
+ * blk_bio_map_sg - map a bio to a scatterlist
+ * @q: request_queue in question
+ * @bio: bio being mapped
+ * @sglist: scatterlist being mapped
+ *
+ * Note:
+ * Caller must make sure sg can hold bio->bi_phys_segments entries
+ *
+ * Will return the number of sg entries setup
+ */
+int blk_bio_map_sg(struct request_queue *q, struct bio *bio,
+ struct scatterlist *sglist)
+{
+ struct bio_vec *bvec, *bvprv;
+ struct scatterlist *sg;
+ int nsegs, cluster;
+ unsigned long i;
+
+ nsegs = 0;
+ cluster = blk_queue_cluster(q);
+
+ bvprv = NULL;
+ sg = NULL;
+ bio_for_each_segment(bvec, bio, i) {
+ __blk_segment_map_sg(q, bvec, sglist, &bvprv, &sg,
+ &nsegs, &cluster);
+ } /* segments in bio */
+
+ if (sg)
+ sg_mark_end(sg);
+
+ BUG_ON(bio->bi_phys_segments && nsegs > bio->bi_phys_segments);
+ return nsegs;
+}
+EXPORT_SYMBOL(blk_bio_map_sg);
+
static inline int ll_new_hw_segment(struct request_queue *q,
struct request *req,
struct bio *bio)
diff --git a/block/genhd.c b/block/genhd.c
index cac7366..d839723 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -835,7 +835,7 @@
static void *show_partition_start(struct seq_file *seqf, loff_t *pos)
{
- static void *p;
+ void *p;
p = disk_seqf_start(seqf, pos);
if (!IS_ERR_OR_NULL(p) && !*pos)
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 2be8ef1..27cecd3 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -115,7 +115,7 @@
If unsure, say N.
config ATA_SFF
- bool "ATA SFF support"
+ bool "ATA SFF support (for legacy IDE and PATA)"
default y
help
This option adds support for ATA controllers with SFF
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 062e6a1..50d5dea 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -256,6 +256,14 @@
{ PCI_VDEVICE(INTEL, 0x8c07), board_ahci }, /* Lynx Point RAID */
{ PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */
{ PCI_VDEVICE(INTEL, 0x8c0f), board_ahci }, /* Lynx Point RAID */
+ { PCI_VDEVICE(INTEL, 0x9c02), board_ahci }, /* Lynx Point-LP AHCI */
+ { PCI_VDEVICE(INTEL, 0x9c03), board_ahci }, /* Lynx Point-LP AHCI */
+ { PCI_VDEVICE(INTEL, 0x9c04), board_ahci }, /* Lynx Point-LP RAID */
+ { PCI_VDEVICE(INTEL, 0x9c05), board_ahci }, /* Lynx Point-LP RAID */
+ { PCI_VDEVICE(INTEL, 0x9c06), board_ahci }, /* Lynx Point-LP RAID */
+ { PCI_VDEVICE(INTEL, 0x9c07), board_ahci }, /* Lynx Point-LP RAID */
+ { PCI_VDEVICE(INTEL, 0x9c0e), board_ahci }, /* Lynx Point-LP RAID */
+ { PCI_VDEVICE(INTEL, 0x9c0f), board_ahci }, /* Lynx Point-LP RAID */
/* JMicron 360/1/3/5/6, match class to avoid IDE function */
{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index c2594dd..57eb1c2 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -320,6 +320,7 @@
extern struct ata_port_operations ahci_ops;
extern struct ata_port_operations ahci_pmp_retry_srst_ops;
+unsigned int ahci_dev_classify(struct ata_port *ap);
void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
u32 opts);
void ahci_save_initial_config(struct device *dev,
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 3c809bf..ef773e1 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -329,6 +329,14 @@
{ 0x8086, 0x8c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
/* SATA Controller IDE (Lynx Point) */
{ 0x8086, 0x8c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+ /* SATA Controller IDE (Lynx Point-LP) */
+ { 0x8086, 0x9c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
+ /* SATA Controller IDE (Lynx Point-LP) */
+ { 0x8086, 0x9c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
+ /* SATA Controller IDE (Lynx Point-LP) */
+ { 0x8086, 0x9c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+ /* SATA Controller IDE (Lynx Point-LP) */
+ { 0x8086, 0x9c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
/* SATA Controller IDE (DH89xxCC) */
{ 0x8086, 0x2326, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
{ } /* terminate list */
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index f9eaa82..555c07a 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -1139,7 +1139,7 @@
}
}
-static unsigned int ahci_dev_classify(struct ata_port *ap)
+unsigned int ahci_dev_classify(struct ata_port *ap)
{
void __iomem *port_mmio = ahci_port_base(ap);
struct ata_taskfile tf;
@@ -1153,6 +1153,7 @@
return ata_dev_classify(&tf);
}
+EXPORT_SYMBOL_GPL(ahci_dev_classify);
void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
u32 opts)
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 902b5a4..fd9ecf7 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -60,17 +60,7 @@
if (ap->flags & ATA_FLAG_ACPI_SATA)
return NULL;
- /*
- * If acpi bind operation has already happened, we can get the handle
- * for the port by checking the corresponding scsi_host device's
- * firmware node, otherwise we will need to find out the handle from
- * its parent's acpi node.
- */
- if (ap->scsi_host)
- return DEVICE_ACPI_HANDLE(&ap->scsi_host->shost_gendev);
- else
- return acpi_get_child(DEVICE_ACPI_HANDLE(ap->host->dev),
- ap->port_no);
+ return acpi_get_child(DEVICE_ACPI_HANDLE(ap->host->dev), ap->port_no);
}
EXPORT_SYMBOL(ata_ap_acpi_handle);
@@ -1101,6 +1091,9 @@
if (!*handle)
return -ENODEV;
+ if (ata_acpi_gtm(ap, &ap->__acpi_init_gtm) == 0)
+ ap->pflags |= ATA_PFLAG_INIT_GTM_VALID;
+
return 0;
}
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index fadd586..8e1039c 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4062,7 +4062,7 @@
{ "_NEC DV5800A", NULL, ATA_HORKAGE_NODMA },
{ "SAMSUNG CD-ROM SN-124", "N001", ATA_HORKAGE_NODMA },
{ "Seagate STT20000A", NULL, ATA_HORKAGE_NODMA },
- { "2GB ATA Flash Disk", "ADMA428M", ATA_HORKAGE_NODMA },
+ { " 2GB ATA Flash Disk", "ADMA428M", ATA_HORKAGE_NODMA },
/* Odd clown on sil3726/4726 PMPs */
{ "Config Disk", NULL, ATA_HORKAGE_DISABLE },
@@ -4128,6 +4128,7 @@
/* Devices that do not need bridging limits applied */
{ "MTRON MSP-SATA*", NULL, ATA_HORKAGE_BRIDGE_OK, },
+ { "BUFFALO HD-QSU2/R5", NULL, ATA_HORKAGE_BRIDGE_OK, },
/* Devices which aren't very happy with higher link speeds */
{ "WD My Book", NULL, ATA_HORKAGE_1_5_GBPS, },
diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c
index 361c75c..24e5105 100644
--- a/drivers/ata/pata_atiixp.c
+++ b/drivers/ata/pata_atiixp.c
@@ -20,6 +20,7 @@
#include <linux/delay.h>
#include <scsi/scsi_host.h>
#include <linux/libata.h>
+#include <linux/dmi.h>
#define DRV_NAME "pata_atiixp"
#define DRV_VERSION "0.4.6"
@@ -33,11 +34,26 @@
ATIIXP_IDE_UDMA_MODE = 0x56
};
+static const struct dmi_system_id attixp_cable_override_dmi_table[] = {
+ {
+ /* Board has onboard PATA<->SATA converters */
+ .ident = "MSI E350DM-E33",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
+ DMI_MATCH(DMI_BOARD_NAME, "E350DM-E33(MS-7720)"),
+ },
+ },
+ { }
+};
+
static int atiixp_cable_detect(struct ata_port *ap)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
u8 udma;
+ if (dmi_check_system(attixp_cable_override_dmi_table))
+ return ATA_CBL_PATA40_SHORT;
+
/* Hack from drivers/ide/pci. Really we want to know how to do the
raw detection not play follow the bios mode guess */
pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ap->port_no, &udma);
diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c
index 78efb03..34d94c7 100644
--- a/drivers/base/dma-contiguous.c
+++ b/drivers/base/dma-contiguous.c
@@ -250,7 +250,7 @@
return -EINVAL;
/* Sanitise input arguments */
- alignment = PAGE_SIZE << max(MAX_ORDER, pageblock_order);
+ alignment = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order);
base = ALIGN(base, alignment);
size = ALIGN(size, alignment);
limit &= ~(alignment - 1);
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
index ba91b40..d845664 100644
--- a/drivers/block/drbd/drbd_bitmap.c
+++ b/drivers/block/drbd/drbd_bitmap.c
@@ -889,6 +889,7 @@
unsigned int done;
unsigned flags;
#define BM_AIO_COPY_PAGES 1
+#define BM_WRITE_ALL_PAGES 2
int error;
struct kref kref;
};
@@ -1059,7 +1060,8 @@
if (lazy_writeout_upper_idx && i == lazy_writeout_upper_idx)
break;
if (rw & WRITE) {
- if (bm_test_page_unchanged(b->bm_pages[i])) {
+ if (!(flags & BM_WRITE_ALL_PAGES) &&
+ bm_test_page_unchanged(b->bm_pages[i])) {
dynamic_dev_dbg(DEV, "skipped bm write for idx %u\n", i);
continue;
}
@@ -1141,6 +1143,17 @@
}
/**
+ * drbd_bm_write_all() - Write the whole bitmap to its on disk location.
+ * @mdev: DRBD device.
+ *
+ * Will write all pages.
+ */
+int drbd_bm_write_all(struct drbd_conf *mdev) __must_hold(local)
+{
+ return bm_rw(mdev, WRITE, BM_WRITE_ALL_PAGES, 0);
+}
+
+/**
* drbd_bm_lazy_write_out() - Write bitmap pages 0 to @upper_idx-1, if they have changed.
* @mdev: DRBD device.
* @upper_idx: 0: write all changed pages; +ve: page index to stop scanning for changed pages
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index b2ca143..b953cc7 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -1469,6 +1469,7 @@
extern int drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(local);
extern int drbd_bm_read(struct drbd_conf *mdev) __must_hold(local);
extern int drbd_bm_write(struct drbd_conf *mdev) __must_hold(local);
+extern int drbd_bm_write_all(struct drbd_conf *mdev) __must_hold(local);
extern int drbd_bm_write_copy_pages(struct drbd_conf *mdev) __must_hold(local);
extern unsigned long drbd_bm_ALe_set_all(struct drbd_conf *mdev,
unsigned long al_enr);
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index dbe6135..f93a032 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -79,6 +79,7 @@
static void md_sync_timer_fn(unsigned long data);
static int w_bitmap_io(struct drbd_conf *mdev, struct drbd_work *w, int unused);
static int w_go_diskless(struct drbd_conf *mdev, struct drbd_work *w, int unused);
+static void _tl_clear(struct drbd_conf *mdev);
MODULE_AUTHOR("Philipp Reisner <phil@linbit.com>, "
"Lars Ellenberg <lars@linbit.com>");
@@ -432,19 +433,10 @@
/* Actions operating on the disk state, also want to work on
requests that got barrier acked. */
- switch (what) {
- case fail_frozen_disk_io:
- case restart_frozen_disk_io:
- list_for_each_safe(le, tle, &mdev->barrier_acked_requests) {
- req = list_entry(le, struct drbd_request, tl_requests);
- _req_mod(req, what);
- }
- case connection_lost_while_pending:
- case resend:
- break;
- default:
- dev_err(DEV, "what = %d in _tl_restart()\n", what);
+ list_for_each_safe(le, tle, &mdev->barrier_acked_requests) {
+ req = list_entry(le, struct drbd_request, tl_requests);
+ _req_mod(req, what);
}
}
@@ -459,11 +451,16 @@
*/
void tl_clear(struct drbd_conf *mdev)
{
+ spin_lock_irq(&mdev->req_lock);
+ _tl_clear(mdev);
+ spin_unlock_irq(&mdev->req_lock);
+}
+
+static void _tl_clear(struct drbd_conf *mdev)
+{
struct list_head *le, *tle;
struct drbd_request *r;
- spin_lock_irq(&mdev->req_lock);
-
_tl_restart(mdev, connection_lost_while_pending);
/* we expect this list to be empty. */
@@ -482,7 +479,6 @@
memset(mdev->app_reads_hash, 0, APP_R_HSIZE*sizeof(void *));
- spin_unlock_irq(&mdev->req_lock);
}
void tl_restart(struct drbd_conf *mdev, enum drbd_req_event what)
@@ -1476,12 +1472,12 @@
if (ns.susp_fen) {
/* case1: The outdate peer handler is successful: */
if (os.pdsk > D_OUTDATED && ns.pdsk <= D_OUTDATED) {
- tl_clear(mdev);
if (test_bit(NEW_CUR_UUID, &mdev->flags)) {
drbd_uuid_new_current(mdev);
clear_bit(NEW_CUR_UUID, &mdev->flags);
}
spin_lock_irq(&mdev->req_lock);
+ _tl_clear(mdev);
_drbd_set_state(_NS(mdev, susp_fen, 0), CS_VERBOSE, NULL);
spin_unlock_irq(&mdev->req_lock);
}
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index fb9dce8..edb490a 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -674,8 +674,8 @@
la_size_changed && md_moved ? "size changed and md moved" :
la_size_changed ? "size changed" : "md moved");
/* next line implicitly does drbd_suspend_io()+drbd_resume_io() */
- err = drbd_bitmap_io(mdev, &drbd_bm_write,
- "size changed", BM_LOCKED_MASK);
+ err = drbd_bitmap_io(mdev, md_moved ? &drbd_bm_write_all : &drbd_bm_write,
+ "size changed", BM_LOCKED_MASK);
if (err) {
rv = dev_size_error;
goto out;
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index 910335c..01b2ac6 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -695,6 +695,12 @@
break;
case resend:
+ /* Simply complete (local only) READs. */
+ if (!(req->rq_state & RQ_WRITE) && !req->w.cb) {
+ _req_may_be_done(req, m);
+ break;
+ }
+
/* If RQ_NET_OK is already set, we got a P_WRITE_ACK or P_RECV_ACK
before the connection loss (B&C only); only P_BARRIER_ACK was missing.
Trowing them out of the TL here by pretending we got a BARRIER_ACK
@@ -834,7 +840,15 @@
req->private_bio = NULL;
}
if (rw == WRITE) {
- remote = 1;
+ /* Need to replicate writes. Unless it is an empty flush,
+ * which is better mapped to a DRBD P_BARRIER packet,
+ * also for drbd wire protocol compatibility reasons. */
+ if (unlikely(size == 0)) {
+ /* The only size==0 bios we expect are empty flushes. */
+ D_ASSERT(bio->bi_rw & REQ_FLUSH);
+ remote = 0;
+ } else
+ remote = 1;
} else {
/* READ || READA */
if (local) {
@@ -870,8 +884,11 @@
* extent. This waits for any resync activity in the corresponding
* resync extent to finish, and, if necessary, pulls in the target
* extent into the activity log, which involves further disk io because
- * of transactional on-disk meta data updates. */
- if (rw == WRITE && local && !test_bit(AL_SUSPENDED, &mdev->flags)) {
+ * of transactional on-disk meta data updates.
+ * Empty flushes don't need to go into the activity log, they can only
+ * flush data for pending writes which are already in there. */
+ if (rw == WRITE && local && size
+ && !test_bit(AL_SUSPENDED, &mdev->flags)) {
req->rq_state |= RQ_IN_ACT_LOG;
drbd_al_begin_io(mdev, sector);
}
@@ -994,7 +1011,10 @@
if (rw == WRITE && _req_conflicts(req))
goto fail_conflicting;
- list_add_tail(&req->tl_requests, &mdev->newest_tle->requests);
+ /* no point in adding empty flushes to the transfer log,
+ * they are mapped to drbd barriers already. */
+ if (likely(size!=0))
+ list_add_tail(&req->tl_requests, &mdev->newest_tle->requests);
/* NOTE remote first: to get the concurrent write detection right,
* we must register the request before start of local IO. */
@@ -1014,6 +1034,14 @@
mdev->net_conf->on_congestion != OC_BLOCK && mdev->agreed_pro_version >= 96)
maybe_pull_ahead(mdev);
+ /* If this was a flush, queue a drbd barrier/start a new epoch.
+ * Unless the current epoch was empty anyways, or we are not currently
+ * replicating, in which case there is no point. */
+ if (unlikely(bio->bi_rw & REQ_FLUSH)
+ && mdev->newest_tle->n_writes
+ && drbd_should_do_remote(mdev->state))
+ queue_barrier(mdev);
+
spin_unlock_irq(&mdev->req_lock);
kfree(b); /* if someone else has beaten us to it... */
diff --git a/drivers/bluetooth/hci_ath.c b/drivers/bluetooth/hci_ath.c
index 12172a6..0bc8a6a 100644
--- a/drivers/bluetooth/hci_ath.c
+++ b/drivers/bluetooth/hci_ath.c
@@ -58,7 +58,7 @@
return status;
/* Disable Automatic RTSCTS */
- memcpy(&ktermios, tty->termios, sizeof(ktermios));
+ ktermios = tty->termios;
ktermios.c_cflag &= ~CRTSCTS;
tty_set_termios(tty, &ktermios);
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c
index 1d82d58..164544a 100644
--- a/drivers/char/mwave/mwavedd.c
+++ b/drivers/char/mwave/mwavedd.c
@@ -430,7 +430,7 @@
static int register_serial_portandirq(unsigned int port, int irq)
{
- struct uart_port uart;
+ struct uart_8250_port uart;
switch ( port ) {
case 0x3f8:
@@ -462,14 +462,14 @@
} /* switch */
/* irq is okay */
- memset(&uart, 0, sizeof(struct uart_port));
+ memset(&uart, 0, sizeof(uart));
- uart.uartclk = 1843200;
- uart.iobase = port;
- uart.irq = irq;
- uart.iotype = UPIO_PORT;
- uart.flags = UPF_SHARE_IRQ;
- return serial8250_register_port(&uart);
+ uart.port.uartclk = 1843200;
+ uart.port.iobase = port;
+ uart.port.irq = irq;
+ uart.port.iotype = UPIO_PORT;
+ uart.port.flags = UPF_SHARE_IRQ;
+ return serial8250_register_8250_port(&uart);
}
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 0a484b4..3f57d5de 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -1050,7 +1050,7 @@
wake_up_interruptible(&info->status_event_wait_q);
wake_up_interruptible(&info->event_wait_q);
- if (info->port.flags & ASYNC_CTS_FLOW) {
+ if (tty_port_cts_enabled(&info->port)) {
if (tty->hw_stopped) {
if (info->serial_signals & SerialSignal_CTS) {
if (debug_level >= DEBUG_LEVEL_ISR)
@@ -1344,7 +1344,7 @@
/* TODO:disable interrupts instead of reset to preserve signal states */
reset_device(info);
- if (!tty || tty->termios->c_cflag & HUPCL) {
+ if (!tty || tty->termios.c_cflag & HUPCL) {
info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
set_signals(info);
}
@@ -1385,7 +1385,7 @@
port_irq_enable(info, (unsigned char) PVR_DSR | PVR_RI);
get_signals(info);
- if (info->netcount || (tty && (tty->termios->c_cflag & CREAD)))
+ if (info->netcount || (tty && (tty->termios.c_cflag & CREAD)))
rx_start(info);
spin_unlock_irqrestore(&info->lock,flags);
@@ -1398,14 +1398,14 @@
unsigned cflag;
int bits_per_char;
- if (!tty || !tty->termios)
+ if (!tty)
return;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_change_params(%s)\n",
__FILE__,__LINE__, info->device_name );
- cflag = tty->termios->c_cflag;
+ cflag = tty->termios.c_cflag;
/* if B0 rate (hangup) specified then negate DTR and RTS */
/* otherwise assert DTR and RTS */
@@ -1728,7 +1728,7 @@
if (I_IXOFF(tty))
mgslpc_send_xchar(tty, STOP_CHAR(tty));
- if (tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios.c_cflag & CRTSCTS) {
spin_lock_irqsave(&info->lock,flags);
info->serial_signals &= ~SerialSignal_RTS;
set_signals(info);
@@ -1757,7 +1757,7 @@
mgslpc_send_xchar(tty, START_CHAR(tty));
}
- if (tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios.c_cflag & CRTSCTS) {
spin_lock_irqsave(&info->lock,flags);
info->serial_signals |= SerialSignal_RTS;
set_signals(info);
@@ -2293,8 +2293,8 @@
tty->driver->name );
/* just return if nothing has changed */
- if ((tty->termios->c_cflag == old_termios->c_cflag)
- && (RELEVANT_IFLAG(tty->termios->c_iflag)
+ if ((tty->termios.c_cflag == old_termios->c_cflag)
+ && (RELEVANT_IFLAG(tty->termios.c_iflag)
== RELEVANT_IFLAG(old_termios->c_iflag)))
return;
@@ -2302,7 +2302,7 @@
/* Handle transition to B0 status */
if (old_termios->c_cflag & CBAUD &&
- !(tty->termios->c_cflag & CBAUD)) {
+ !(tty->termios.c_cflag & CBAUD)) {
info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
spin_lock_irqsave(&info->lock,flags);
set_signals(info);
@@ -2311,9 +2311,9 @@
/* Handle transition away from B0 status */
if (!(old_termios->c_cflag & CBAUD) &&
- tty->termios->c_cflag & CBAUD) {
+ tty->termios.c_cflag & CBAUD) {
info->serial_signals |= SerialSignal_DTR;
- if (!(tty->termios->c_cflag & CRTSCTS) ||
+ if (!(tty->termios.c_cflag & CRTSCTS) ||
!test_bit(TTY_THROTTLED, &tty->flags)) {
info->serial_signals |= SerialSignal_RTS;
}
@@ -2324,7 +2324,7 @@
/* Handle turning off CRTSCTS */
if (old_termios->c_cflag & CRTSCTS &&
- !(tty->termios->c_cflag & CRTSCTS)) {
+ !(tty->termios.c_cflag & CRTSCTS)) {
tty->hw_stopped = 0;
tx_release(tty);
}
@@ -2731,6 +2731,8 @@
#if SYNCLINK_GENERIC_HDLC
hdlcdev_init(info);
#endif
+ tty_port_register_device(&info->port, serial_driver, info->line,
+ &info->p_dev->dev);
}
static void mgslpc_remove_device(MGSLPC_INFO *remove_info)
@@ -2744,6 +2746,7 @@
last->next_device = info->next_device;
else
mgslpc_device_list = info->next_device;
+ tty_unregister_device(serial_driver, info->line);
#if SYNCLINK_GENERIC_HDLC
hdlcdev_exit(info);
#endif
@@ -2798,77 +2801,63 @@
.proc_fops = &mgslpc_proc_fops,
};
-static void synclink_cs_cleanup(void)
+static int __init synclink_cs_init(void)
{
int rc;
- while(mgslpc_device_list)
- mgslpc_remove_device(mgslpc_device_list);
-
- if (serial_driver) {
- if ((rc = tty_unregister_driver(serial_driver)))
- printk("%s(%d) failed to unregister tty driver err=%d\n",
- __FILE__,__LINE__,rc);
- put_tty_driver(serial_driver);
+ if (break_on_load) {
+ mgslpc_get_text_ptr();
+ BREAKPOINT();
}
- pcmcia_unregister_driver(&mgslpc_driver);
-}
+ serial_driver = tty_alloc_driver(MAX_DEVICE_COUNT,
+ TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_DYNAMIC_DEV);
+ if (IS_ERR(serial_driver)) {
+ rc = PTR_ERR(serial_driver);
+ goto err;
+ }
-static int __init synclink_cs_init(void)
-{
- int rc;
+ /* Initialize the tty_driver structure */
+ serial_driver->driver_name = "synclink_cs";
+ serial_driver->name = "ttySLP";
+ serial_driver->major = ttymajor;
+ serial_driver->minor_start = 64;
+ serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+ serial_driver->subtype = SERIAL_TYPE_NORMAL;
+ serial_driver->init_termios = tty_std_termios;
+ serial_driver->init_termios.c_cflag =
+ B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ tty_set_operations(serial_driver, &mgslpc_ops);
- if (break_on_load) {
- mgslpc_get_text_ptr();
- BREAKPOINT();
- }
+ rc = tty_register_driver(serial_driver);
+ if (rc < 0) {
+ printk(KERN_ERR "%s(%d):Couldn't register serial driver\n",
+ __FILE__, __LINE__);
+ goto err_put_tty;
+ }
- if ((rc = pcmcia_register_driver(&mgslpc_driver)) < 0)
- return rc;
+ rc = pcmcia_register_driver(&mgslpc_driver);
+ if (rc < 0)
+ goto err_unreg_tty;
- serial_driver = alloc_tty_driver(MAX_DEVICE_COUNT);
- if (!serial_driver) {
- rc = -ENOMEM;
- goto error;
- }
+ printk(KERN_INFO "%s %s, tty major#%d\n", driver_name, driver_version,
+ serial_driver->major);
- /* Initialize the tty_driver structure */
-
- serial_driver->driver_name = "synclink_cs";
- serial_driver->name = "ttySLP";
- serial_driver->major = ttymajor;
- serial_driver->minor_start = 64;
- serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
- serial_driver->subtype = SERIAL_TYPE_NORMAL;
- serial_driver->init_termios = tty_std_termios;
- serial_driver->init_termios.c_cflag =
- B9600 | CS8 | CREAD | HUPCL | CLOCAL;
- serial_driver->flags = TTY_DRIVER_REAL_RAW;
- tty_set_operations(serial_driver, &mgslpc_ops);
-
- if ((rc = tty_register_driver(serial_driver)) < 0) {
- printk("%s(%d):Couldn't register serial driver\n",
- __FILE__,__LINE__);
- put_tty_driver(serial_driver);
- serial_driver = NULL;
- goto error;
- }
-
- printk("%s %s, tty major#%d\n",
- driver_name, driver_version,
- serial_driver->major);
-
- return 0;
-
-error:
- synclink_cs_cleanup();
- return rc;
+ return 0;
+err_unreg_tty:
+ tty_unregister_driver(serial_driver);
+err_put_tty:
+ put_tty_driver(serial_driver);
+err:
+ return rc;
}
static void __exit synclink_cs_exit(void)
{
- synclink_cs_cleanup();
+ pcmcia_unregister_driver(&mgslpc_driver);
+ tty_unregister_driver(serial_driver);
+ put_tty_driver(serial_driver);
}
module_init(synclink_cs_init);
diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c
index 46b77ed..af98f6d 100644
--- a/drivers/char/ttyprintk.c
+++ b/drivers/char/ttyprintk.c
@@ -67,7 +67,7 @@
tmp[tpk_curr + 1] = '\0';
printk(KERN_INFO "%s%s", tpk_tag, tmp);
tpk_curr = 0;
- if (buf[i + 1] == '\n')
+ if ((i + 1) < count && buf[i + 1] == '\n')
i++;
break;
case '\n':
@@ -178,11 +178,17 @@
static int __init ttyprintk_init(void)
{
int ret = -ENOMEM;
- void *rp;
- ttyprintk_driver = alloc_tty_driver(1);
- if (!ttyprintk_driver)
- return ret;
+ tty_port_init(&tpk_port.port);
+ tpk_port.port.ops = &null_ops;
+ mutex_init(&tpk_port.port_write_mutex);
+
+ ttyprintk_driver = tty_alloc_driver(1,
+ TTY_DRIVER_RESET_TERMIOS |
+ TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_UNNUMBERED_NODE);
+ if (IS_ERR(ttyprintk_driver))
+ return PTR_ERR(ttyprintk_driver);
ttyprintk_driver->driver_name = "ttyprintk";
ttyprintk_driver->name = "ttyprintk";
@@ -191,9 +197,8 @@
ttyprintk_driver->type = TTY_DRIVER_TYPE_CONSOLE;
ttyprintk_driver->init_termios = tty_std_termios;
ttyprintk_driver->init_termios.c_oflag = OPOST | OCRNL | ONOCR | ONLRET;
- ttyprintk_driver->flags = TTY_DRIVER_RESET_TERMIOS |
- TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
tty_set_operations(ttyprintk_driver, &ttyprintk_ops);
+ tty_port_link_device(&tpk_port.port, ttyprintk_driver, 0);
ret = tty_register_driver(ttyprintk_driver);
if (ret < 0) {
@@ -201,22 +206,10 @@
goto error;
}
- /* create our unnumbered device */
- rp = device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 3), NULL,
- ttyprintk_driver->name);
- if (IS_ERR(rp)) {
- printk(KERN_ERR "Couldn't create ttyprintk device\n");
- ret = PTR_ERR(rp);
- goto error;
- }
-
- tty_port_init(&tpk_port.port);
- tpk_port.port.ops = &null_ops;
- mutex_init(&tpk_port.port_write_mutex);
-
return 0;
error:
+ tty_unregister_driver(ttyprintk_driver);
put_tty_driver(ttyprintk_driver);
ttyprintk_driver = NULL;
return ret;
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
index 17fa04d0..b47034e 100644
--- a/drivers/cpufreq/omap-cpufreq.c
+++ b/drivers/cpufreq/omap-cpufreq.c
@@ -218,7 +218,7 @@
policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu);
- if (atomic_inc_return(&freq_table_users) == 1)
+ if (!freq_table)
result = opp_init_cpufreq_table(mpu_dev, &freq_table);
if (result) {
@@ -227,6 +227,8 @@
goto fail_ck;
}
+ atomic_inc_return(&freq_table_users);
+
result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
if (result)
goto fail_table;
diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
index 53c8c51..93d1407 100644
--- a/drivers/crypto/caam/jr.c
+++ b/drivers/crypto/caam/jr.c
@@ -63,7 +63,7 @@
head = ACCESS_ONCE(jrp->head);
- spin_lock_bh(&jrp->outlock);
+ spin_lock(&jrp->outlock);
sw_idx = tail = jrp->tail;
hw_idx = jrp->out_ring_read_index;
@@ -115,7 +115,7 @@
jrp->tail = tail;
}
- spin_unlock_bh(&jrp->outlock);
+ spin_unlock(&jrp->outlock);
/* Finally, execute user's callback */
usercall(dev, userdesc, userstatus, userarg);
@@ -236,14 +236,14 @@
return -EIO;
}
- spin_lock(&jrp->inplock);
+ spin_lock_bh(&jrp->inplock);
head = jrp->head;
tail = ACCESS_ONCE(jrp->tail);
if (!rd_reg32(&jrp->rregs->inpring_avail) ||
CIRC_SPACE(head, tail, JOBR_DEPTH) <= 0) {
- spin_unlock(&jrp->inplock);
+ spin_unlock_bh(&jrp->inplock);
dma_unmap_single(dev, desc_dma, desc_size, DMA_TO_DEVICE);
return -EBUSY;
}
@@ -265,7 +265,7 @@
wr_reg32(&jrp->rregs->inpring_jobadd, 1);
- spin_unlock(&jrp->inplock);
+ spin_unlock_bh(&jrp->inplock);
return 0;
}
diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c
index c9c4bef..df14358 100644
--- a/drivers/crypto/hifn_795x.c
+++ b/drivers/crypto/hifn_795x.c
@@ -821,8 +821,8 @@
/*
* We must wait at least 256 Pk_clk cycles between two reads of the rng.
*/
- dev->rng_wait_time = DIV_ROUND_UP(NSEC_PER_SEC, dev->pk_clk_freq) *
- 256;
+ dev->rng_wait_time = DIV_ROUND_UP_ULL(NSEC_PER_SEC,
+ dev->pk_clk_freq) * 256;
dev->rng.name = dev->name;
dev->rng.data_present = hifn_rng_data_present,
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index b16c8a7..ba7926f5 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -294,7 +294,7 @@
config GPIO_MC9S08DZ60
bool "MX35 3DS BOARD MC9S08DZ60 GPIO functions"
- depends on I2C && MACH_MX35_3DS
+ depends on I2C=y && MACH_MX35_3DS
help
Select this to enable the MC9S08DZ60 GPIO driver
diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c
index ae37181..ec48ed5 100644
--- a/drivers/gpio/gpio-em.c
+++ b/drivers/gpio/gpio-em.c
@@ -247,9 +247,9 @@
p->irq_base = irq_alloc_descs(pdata->irq_base, 0,
pdata->number_of_pins, numa_node_id());
- if (IS_ERR_VALUE(p->irq_base)) {
+ if (p->irq_base < 0) {
dev_err(&pdev->dev, "cannot get irq_desc\n");
- return -ENXIO;
+ return p->irq_base;
}
pr_debug("gio: hw base = %d, nr = %d, sw base = %d\n",
pdata->gpio_base, pdata->number_of_pins, p->irq_base);
diff --git a/drivers/gpio/gpio-rdc321x.c b/drivers/gpio/gpio-rdc321x.c
index e97016a..b62d443 100644
--- a/drivers/gpio/gpio-rdc321x.c
+++ b/drivers/gpio/gpio-rdc321x.c
@@ -170,6 +170,7 @@
rdc321x_gpio_dev->reg2_data_base = r->start + 0x4;
rdc321x_gpio_dev->chip.label = "rdc321x-gpio";
+ rdc321x_gpio_dev->chip.owner = THIS_MODULE;
rdc321x_gpio_dev->chip.direction_input = rdc_gpio_direction_input;
rdc321x_gpio_dev->chip.direction_output = rdc_gpio_config;
rdc321x_gpio_dev->chip.get = rdc_gpio_get_value;
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index a18c4aa..f1a4599 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -82,7 +82,7 @@
gpiochip_find(&gg_data, of_gpiochip_find_and_xlate);
of_node_put(gg_data.gpiospec.np);
- pr_debug("%s exited with status %d\n", __func__, ret);
+ pr_debug("%s exited with status %d\n", __func__, gg_data.out_gpio);
return gg_data.out_gpio;
}
EXPORT_SYMBOL(of_get_named_gpio_flags);
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 08a7aa7..6fbfc24 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1981,7 +1981,7 @@
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
- if (!req->flags)
+ if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags))
return -EINVAL;
mutex_lock(&dev->mode_config.mutex);
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index a8743c3..b7ee230 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -87,6 +87,9 @@
int product_id;
u32 quirks;
} edid_quirk_list[] = {
+ /* ASUS VW222S */
+ { "ACI", 0x22a2, EDID_QUIRK_FORCE_REDUCED_BLANKING },
+
/* Acer AL1706 */
{ "ACR", 44358, EDID_QUIRK_PREFER_LARGE_60 },
/* Acer F51 */
diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c
index 30dc22a..8033526 100644
--- a/drivers/gpu/drm/gma500/psb_intel_display.c
+++ b/drivers/gpu/drm/gma500/psb_intel_display.c
@@ -1362,6 +1362,9 @@
(struct drm_connector **) (psb_intel_crtc + 1);
psb_intel_crtc->mode_set.num_connectors = 0;
psb_intel_cursor_init(dev, psb_intel_crtc);
+
+ /* Set to true so that the pipe is forced off on initial config. */
+ psb_intel_crtc->active = true;
}
int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index d9a5372..60815b8 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -72,7 +72,7 @@
/* ppgtt PDEs reside in the global gtt pagetable, which has 512*1024
* entries. For aliasing ppgtt support we just steal them at the end for
* now. */
- first_pd_entry_in_global_pt = 512*1024 - I915_PPGTT_PD_ENTRIES;
+ first_pd_entry_in_global_pt = dev_priv->mm.gtt->gtt_total_entries - I915_PPGTT_PD_ENTRIES;
ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL);
if (!ppgtt)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index a69a3d0..2dfa6cf 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1384,7 +1384,7 @@
enum pipe pipe, int reg)
{
u32 val = I915_READ(reg);
- WARN(hdmi_pipe_enabled(dev_priv, val, pipe),
+ WARN(hdmi_pipe_enabled(dev_priv, pipe, val),
"PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n",
reg, pipe_name(pipe));
@@ -1404,13 +1404,13 @@
reg = PCH_ADPA;
val = I915_READ(reg);
- WARN(adpa_pipe_enabled(dev_priv, val, pipe),
+ WARN(adpa_pipe_enabled(dev_priv, pipe, val),
"PCH VGA enabled on transcoder %c, should be disabled\n",
pipe_name(pipe));
reg = PCH_LVDS;
val = I915_READ(reg);
- WARN(lvds_pipe_enabled(dev_priv, val, pipe),
+ WARN(lvds_pipe_enabled(dev_priv, pipe, val),
"PCH LVDS enabled on transcoder %c, should be disabled\n",
pipe_name(pipe));
@@ -1872,7 +1872,7 @@
enum pipe pipe, int reg)
{
u32 val = I915_READ(reg);
- if (hdmi_pipe_enabled(dev_priv, val, pipe)) {
+ if (hdmi_pipe_enabled(dev_priv, pipe, val)) {
DRM_DEBUG_KMS("Disabling pch HDMI %x on pipe %d\n",
reg, pipe);
I915_WRITE(reg, val & ~PORT_ENABLE);
@@ -1894,12 +1894,12 @@
reg = PCH_ADPA;
val = I915_READ(reg);
- if (adpa_pipe_enabled(dev_priv, val, pipe))
+ if (adpa_pipe_enabled(dev_priv, pipe, val))
I915_WRITE(reg, val & ~ADPA_DAC_ENABLE);
reg = PCH_LVDS;
val = I915_READ(reg);
- if (lvds_pipe_enabled(dev_priv, val, pipe)) {
+ if (lvds_pipe_enabled(dev_priv, pipe, val)) {
DRM_DEBUG_KMS("disable lvds on pipe %d val 0x%08x\n", pipe, val);
I915_WRITE(reg, val & ~LVDS_PORT_EN);
POSTING_READ(reg);
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index e05c0d3..e9a6f6a 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -780,6 +780,14 @@
DMI_MATCH(DMI_BOARD_NAME, "ZBOXSD-ID12/ID13"),
},
},
+ {
+ .callback = intel_no_lvds_dmi_callback,
+ .ident = "Gigabyte GA-D525TUD",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),
+ DMI_MATCH(DMI_BOARD_NAME, "D525TUD"),
+ },
+ },
{ } /* terminating entry */
};
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index cc8df4d..7644f31 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -60,11 +60,11 @@
switch (fb->pixel_format) {
case DRM_FORMAT_XBGR8888:
- sprctl |= SPRITE_FORMAT_RGBX888;
+ sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
pixel_size = 4;
break;
case DRM_FORMAT_XRGB8888:
- sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
+ sprctl |= SPRITE_FORMAT_RGBX888;
pixel_size = 4;
break;
case DRM_FORMAT_YUYV:
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
index 1866dbb..c610144 100644
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -736,9 +736,11 @@
}
break;
case NV_C0:
- nvc0_copy_create(dev, 1);
+ if (!(nv_rd32(dev, 0x022500) & 0x00000200))
+ nvc0_copy_create(dev, 1);
case NV_D0:
- nvc0_copy_create(dev, 0);
+ if (!(nv_rd32(dev, 0x022500) & 0x00000100))
+ nvc0_copy_create(dev, 0);
break;
default:
break;
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index f4d4505..2817101 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -258,7 +258,6 @@
radeon_crtc->enabled = true;
/* adjust pm to dpms changes BEFORE enabling crtcs */
radeon_pm_compute_clocks(rdev);
- /* disable crtc pair power gating before programming */
if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set)
atombios_powergate_crtc(crtc, ATOM_DISABLE);
atombios_enable_crtc(crtc, ATOM_ENABLE);
@@ -278,25 +277,8 @@
atombios_enable_crtc_memreq(crtc, ATOM_DISABLE);
atombios_enable_crtc(crtc, ATOM_DISABLE);
radeon_crtc->enabled = false;
- /* power gating is per-pair */
- if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) {
- struct drm_crtc *other_crtc;
- struct radeon_crtc *other_radeon_crtc;
- list_for_each_entry(other_crtc, &rdev->ddev->mode_config.crtc_list, head) {
- other_radeon_crtc = to_radeon_crtc(other_crtc);
- if (((radeon_crtc->crtc_id == 0) && (other_radeon_crtc->crtc_id == 1)) ||
- ((radeon_crtc->crtc_id == 1) && (other_radeon_crtc->crtc_id == 0)) ||
- ((radeon_crtc->crtc_id == 2) && (other_radeon_crtc->crtc_id == 3)) ||
- ((radeon_crtc->crtc_id == 3) && (other_radeon_crtc->crtc_id == 2)) ||
- ((radeon_crtc->crtc_id == 4) && (other_radeon_crtc->crtc_id == 5)) ||
- ((radeon_crtc->crtc_id == 5) && (other_radeon_crtc->crtc_id == 4))) {
- /* if both crtcs in the pair are off, enable power gating */
- if (other_radeon_crtc->enabled == false)
- atombios_powergate_crtc(crtc, ATOM_ENABLE);
- break;
- }
- }
- }
+ if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set)
+ atombios_powergate_crtc(crtc, ATOM_ENABLE);
/* adjust pm to dpms changes AFTER disabling crtcs */
radeon_pm_compute_clocks(rdev);
break;
@@ -1682,9 +1664,22 @@
struct drm_device *dev = crtc->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_atom_ss ss;
+ int i;
atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+ for (i = 0; i < rdev->num_crtc; i++) {
+ if (rdev->mode_info.crtcs[i] &&
+ rdev->mode_info.crtcs[i]->enabled &&
+ i != radeon_crtc->crtc_id &&
+ radeon_crtc->pll_id == rdev->mode_info.crtcs[i]->pll_id) {
+ /* one other crtc is using this pll don't turn
+ * off the pll
+ */
+ goto done;
+ }
+ }
+
switch (radeon_crtc->pll_id) {
case ATOM_PPLL1:
case ATOM_PPLL2:
@@ -1701,6 +1696,7 @@
default:
break;
}
+done:
radeon_crtc->pll_id = -1;
}
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c
index 7712cf5..3623b98 100644
--- a/drivers/gpu/drm/radeon/atombios_dp.c
+++ b/drivers/gpu/drm/radeon/atombios_dp.c
@@ -577,30 +577,25 @@
struct radeon_device *rdev = dev->dev_private;
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
+ u16 dp_bridge = radeon_connector_encoder_get_dp_bridge_encoder_id(connector);
+ u8 tmp;
if (!ASIC_IS_DCE4(rdev))
return panel_mode;
- if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
- ENCODER_OBJECT_ID_NUTMEG)
- panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
- else if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
- ENCODER_OBJECT_ID_TRAVIS) {
- u8 id[6];
- int i;
- for (i = 0; i < 6; i++)
- id[i] = radeon_read_dpcd_reg(radeon_connector, 0x503 + i);
- if (id[0] == 0x73 &&
- id[1] == 0x69 &&
- id[2] == 0x76 &&
- id[3] == 0x61 &&
- id[4] == 0x72 &&
- id[5] == 0x54)
+ if (dp_bridge != ENCODER_OBJECT_ID_NONE) {
+ /* DP bridge chips */
+ tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP);
+ if (tmp & 1)
+ panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
+ else if ((dp_bridge == ENCODER_OBJECT_ID_NUTMEG) ||
+ (dp_bridge == ENCODER_OBJECT_ID_TRAVIS))
panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
else
- panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
+ panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
} else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
- u8 tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP);
+ /* eDP */
+ tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP);
if (tmp & 1)
panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
}
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c
index f9bc27f..6e8803a 100644
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c
@@ -1379,6 +1379,8 @@
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+ struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
+ struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
struct radeon_connector *radeon_connector = NULL;
struct radeon_connector_atom_dig *radeon_dig_connector = NULL;
@@ -1390,19 +1392,37 @@
switch (mode) {
case DRM_MODE_DPMS_ON:
- /* some early dce3.2 boards have a bug in their transmitter control table */
- if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730) ||
- ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
- if (ASIC_IS_DCE6(rdev)) {
- /* It seems we need to call ATOM_ENCODER_CMD_SETUP again
- * before reenabling encoder on DPMS ON, otherwise we never
- * get picture
- */
- atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
+ if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
+ if (!connector)
+ dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
+ else
+ dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector);
+
+ /* setup and enable the encoder */
+ atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
+ atombios_dig_encoder_setup(encoder,
+ ATOM_ENCODER_CMD_SETUP_PANEL_MODE,
+ dig->panel_mode);
+ if (ext_encoder) {
+ if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev))
+ atombios_external_encoder_setup(encoder, ext_encoder,
+ EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
}
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
- } else {
+ } else if (ASIC_IS_DCE4(rdev)) {
+ /* setup and enable the encoder */
+ atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
+ /* enable the transmitter */
+ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
+ } else {
+ /* setup and enable the encoder and transmitter */
+ atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0);
+ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
+ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
+ /* some early dce3.2 boards have a bug in their transmitter control table */
+ if ((rdev->family != CHIP_RV710) || (rdev->family != CHIP_RV730))
+ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
}
if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
@@ -1420,10 +1440,19 @@
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
case DRM_MODE_DPMS_OFF:
- if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev))
+ if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
+ /* disable the transmitter */
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
- else
+ } else if (ASIC_IS_DCE4(rdev)) {
+ /* disable the transmitter */
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
+ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+ } else {
+ /* disable the encoder and transmitter */
+ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
+ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+ atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
+ }
if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
if (ASIC_IS_DCE4(rdev))
atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
@@ -1740,13 +1769,34 @@
struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct drm_encoder *test_encoder;
- struct radeon_encoder_atom_dig *dig;
+ struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
uint32_t dig_enc_in_use = 0;
- /* DCE4/5 */
- if (ASIC_IS_DCE4(rdev)) {
- dig = radeon_encoder->enc_priv;
- if (ASIC_IS_DCE41(rdev)) {
+ if (ASIC_IS_DCE6(rdev)) {
+ /* DCE6 */
+ switch (radeon_encoder->encoder_id) {
+ case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+ if (dig->linkb)
+ return 1;
+ else
+ return 0;
+ break;
+ case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+ if (dig->linkb)
+ return 3;
+ else
+ return 2;
+ break;
+ case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+ if (dig->linkb)
+ return 5;
+ else
+ return 4;
+ break;
+ }
+ } else if (ASIC_IS_DCE4(rdev)) {
+ /* DCE4/5 */
+ if (ASIC_IS_DCE41(rdev) && !ASIC_IS_DCE61(rdev)) {
/* ontario follows DCE4 */
if (rdev->family == CHIP_PALM) {
if (dig->linkb)
@@ -1848,10 +1898,12 @@
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
- struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
radeon_encoder->pixel_clock = adjusted_mode->clock;
+ /* need to call this here rather than in prepare() since we need some crtc info */
+ radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
+
if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) {
if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
atombios_yuv_setup(encoder, true);
@@ -1870,38 +1922,7 @@
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
- if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
- struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
- struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-
- if (!connector)
- dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
- else
- dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector);
-
- /* setup and enable the encoder */
- atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
- atombios_dig_encoder_setup(encoder,
- ATOM_ENCODER_CMD_SETUP_PANEL_MODE,
- dig->panel_mode);
- } else if (ASIC_IS_DCE4(rdev)) {
- /* disable the transmitter */
- atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
- /* setup and enable the encoder */
- atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
-
- /* enable the transmitter */
- atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
- } else {
- /* disable the encoder and transmitter */
- atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
- atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
-
- /* setup and enable the encoder and transmitter */
- atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0);
- atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
- atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
- }
+ /* handled in dpms */
break;
case ENCODER_OBJECT_ID_INTERNAL_DDI:
case ENCODER_OBJECT_ID_INTERNAL_DVO1:
@@ -1922,14 +1943,6 @@
break;
}
- if (ext_encoder) {
- if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev))
- atombios_external_encoder_setup(encoder, ext_encoder,
- EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
- else
- atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
- }
-
atombios_apply_encoder_quirks(encoder, adjusted_mode);
if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
@@ -2116,7 +2129,6 @@
}
radeon_atom_output_lock(encoder, true);
- radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
if (connector) {
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
@@ -2137,6 +2149,7 @@
static void radeon_atom_encoder_commit(struct drm_encoder *encoder)
{
+ /* need to call this here as we need the crtc set up */
radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
radeon_atom_output_lock(encoder, false);
}
@@ -2177,14 +2190,7 @@
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
- if (ASIC_IS_DCE4(rdev))
- /* disable the transmitter */
- atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
- else {
- /* disable the encoder and transmitter */
- atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
- atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
- }
+ /* handled in dpms */
break;
case ENCODER_OBJECT_ID_INTERNAL_DDI:
case ENCODER_OBJECT_ID_INTERNAL_DVO1:
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c
index ab74e6b..f37676d 100644
--- a/drivers/gpu/drm/radeon/r600_cs.c
+++ b/drivers/gpu/drm/radeon/r600_cs.c
@@ -63,6 +63,7 @@
u32 cb_color_size_idx[8]; /* unused */
u32 cb_target_mask;
u32 cb_shader_mask; /* unused */
+ bool is_resolve;
u32 cb_color_size[8];
u32 vgt_strmout_en;
u32 vgt_strmout_buffer_en;
@@ -315,7 +316,15 @@
track->cb_color_bo[i] = NULL;
track->cb_color_bo_offset[i] = 0xFFFFFFFF;
track->cb_color_bo_mc[i] = 0xFFFFFFFF;
+ track->cb_color_frag_bo[i] = NULL;
+ track->cb_color_frag_offset[i] = 0xFFFFFFFF;
+ track->cb_color_tile_bo[i] = NULL;
+ track->cb_color_tile_offset[i] = 0xFFFFFFFF;
+ track->cb_color_mask[i] = 0xFFFFFFFF;
}
+ track->is_resolve = false;
+ track->nsamples = 16;
+ track->log_nsamples = 4;
track->cb_target_mask = 0xFFFFFFFF;
track->cb_shader_mask = 0xFFFFFFFF;
track->cb_dirty = true;
@@ -352,6 +361,8 @@
volatile u32 *ib = p->ib.ptr;
unsigned array_mode;
u32 format;
+ /* When resolve is used, the second colorbuffer has always 1 sample. */
+ unsigned nsamples = track->is_resolve && i == 1 ? 1 : track->nsamples;
size = radeon_bo_size(track->cb_color_bo[i]) - track->cb_color_bo_offset[i];
format = G_0280A0_FORMAT(track->cb_color_info[i]);
@@ -375,7 +386,7 @@
array_check.group_size = track->group_size;
array_check.nbanks = track->nbanks;
array_check.npipes = track->npipes;
- array_check.nsamples = track->nsamples;
+ array_check.nsamples = nsamples;
array_check.blocksize = r600_fmt_get_blocksize(format);
if (r600_get_array_mode_alignment(&array_check,
&pitch_align, &height_align, &depth_align, &base_align)) {
@@ -421,7 +432,7 @@
/* check offset */
tmp = r600_fmt_get_nblocksy(format, height) * r600_fmt_get_nblocksx(format, pitch) *
- r600_fmt_get_blocksize(format) * track->nsamples;
+ r600_fmt_get_blocksize(format) * nsamples;
switch (array_mode) {
default:
case V_0280A0_ARRAY_LINEAR_GENERAL:
@@ -792,6 +803,12 @@
*/
if (track->cb_dirty) {
tmp = track->cb_target_mask;
+
+ /* We must check both colorbuffers for RESOLVE. */
+ if (track->is_resolve) {
+ tmp |= 0xff;
+ }
+
for (i = 0; i < 8; i++) {
if ((tmp >> (i * 4)) & 0xF) {
/* at least one component is enabled */
@@ -1281,6 +1298,11 @@
track->nsamples = 1 << tmp;
track->cb_dirty = true;
break;
+ case R_028808_CB_COLOR_CONTROL:
+ tmp = G_028808_SPECIAL_OP(radeon_get_ib_value(p, idx));
+ track->is_resolve = tmp == V_028808_SPECIAL_RESOLVE_BOX;
+ track->cb_dirty = true;
+ break;
case R_0280A0_CB_COLOR0_INFO:
case R_0280A4_CB_COLOR1_INFO:
case R_0280A8_CB_COLOR2_INFO:
@@ -1416,7 +1438,7 @@
case R_028118_CB_COLOR6_MASK:
case R_02811C_CB_COLOR7_MASK:
tmp = (reg - R_028100_CB_COLOR0_MASK) / 4;
- track->cb_color_mask[tmp] = ib[idx];
+ track->cb_color_mask[tmp] = radeon_get_ib_value(p, idx);
if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) {
track->cb_dirty = true;
}
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h
index bdb69a6..fa6f370 100644
--- a/drivers/gpu/drm/radeon/r600d.h
+++ b/drivers/gpu/drm/radeon/r600d.h
@@ -66,6 +66,14 @@
#define CC_RB_BACKEND_DISABLE 0x98F4
#define BACKEND_DISABLE(x) ((x) << 16)
+#define R_028808_CB_COLOR_CONTROL 0x28808
+#define S_028808_SPECIAL_OP(x) (((x) & 0x7) << 4)
+#define G_028808_SPECIAL_OP(x) (((x) >> 4) & 0x7)
+#define C_028808_SPECIAL_OP 0xFFFFFF8F
+#define V_028808_SPECIAL_NORMAL 0x00
+#define V_028808_SPECIAL_DISABLE 0x01
+#define V_028808_SPECIAL_RESOLVE_BOX 0x07
+
#define CB_COLOR0_BASE 0x28040
#define CB_COLOR1_BASE 0x28044
#define CB_COLOR2_BASE 0x28048
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index d2e2438..7a3daeb 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -1051,7 +1051,7 @@
if (rdev->flags & RADEON_IS_AGP)
rdev->need_dma32 = true;
if ((rdev->flags & RADEON_IS_PCI) &&
- (rdev->family < CHIP_RS400))
+ (rdev->family <= CHIP_RS740))
rdev->need_dma32 = true;
dma_bits = rdev->need_dma32 ? 32 : 40;
@@ -1346,12 +1346,15 @@
for (i = 0; i < RADEON_NUM_RINGS; ++i) {
radeon_ring_restore(rdev, &rdev->ring[i],
ring_sizes[i], ring_data[i]);
+ ring_sizes[i] = 0;
+ ring_data[i] = NULL;
}
r = radeon_ib_ring_tests(rdev);
if (r) {
dev_err(rdev->dev, "ib ring test failed (%d).\n", r);
if (saved) {
+ saved = false;
radeon_suspend(rdev);
goto retry;
}
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 27d22d7..8c593ea 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -63,9 +63,10 @@
* 2.19.0 - r600-eg: MSAA textures
* 2.20.0 - r600-si: RADEON_INFO_TIMESTAMP query
* 2.21.0 - r600-r700: FMASK and CMASK
+ * 2.22.0 - r600 only: RESOLVE_BOX allowed
*/
#define KMS_DRIVER_MAJOR 2
-#define KMS_DRIVER_MINOR 21
+#define KMS_DRIVER_MINOR 22
#define KMS_DRIVER_PATCHLEVEL 0
int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
int radeon_driver_unload_kms(struct drm_device *dev);
diff --git a/drivers/gpu/drm/radeon/reg_srcs/r600 b/drivers/gpu/drm/radeon/reg_srcs/r600
index f93e45d..20bfbda 100644
--- a/drivers/gpu/drm/radeon/reg_srcs/r600
+++ b/drivers/gpu/drm/radeon/reg_srcs/r600
@@ -744,7 +744,6 @@
0x00028C38 CB_CLRCMP_DST
0x00028C3C CB_CLRCMP_MSK
0x00028C34 CB_CLRCMP_SRC
-0x00028808 CB_COLOR_CONTROL
0x0002842C CB_FOG_BLUE
0x00028428 CB_FOG_GREEN
0x00028424 CB_FOG_RED
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 60ea284..8bcd168 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -996,7 +996,8 @@
struct hid_driver *hdrv = hid->driver;
int ret;
- hid_dump_input(hid, usage, value);
+ if (!list_empty(&hid->debug_list))
+ hid_dump_input(hid, usage, value);
if (hdrv && hdrv->event && hid_match_usage(hid, usage)) {
ret = hdrv->event(hid, field, usage, value);
@@ -1558,7 +1559,9 @@
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) },
- { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
+#if IS_ENABLED(CONFIG_HID_LENOVO_TPKBD)
+ { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
+#endif
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) },
@@ -1624,7 +1627,6 @@
{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) },
- { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) },
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
index 0f9c146..4d524b5 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
@@ -439,7 +439,7 @@
struct dj_report *dj_report;
int retval;
- dj_report = kzalloc(sizeof(dj_report), GFP_KERNEL);
+ dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);
if (!dj_report)
return -ENOMEM;
dj_report->report_id = REPORT_ID_DJ_SHORT;
@@ -456,7 +456,7 @@
struct dj_report *dj_report;
int retval;
- dj_report = kzalloc(sizeof(dj_report), GFP_KERNEL);
+ dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);
if (!dj_report)
return -ENOMEM;
dj_report->report_id = REPORT_ID_DJ_SHORT;
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 903eef3..991e85c 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -70,6 +70,7 @@
{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2, HID_QUIRK_NO_INIT_REPORTS },
diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c
index 351d1f4..4ee5789 100644
--- a/drivers/hwmon/asus_atk0110.c
+++ b/drivers/hwmon/asus_atk0110.c
@@ -34,6 +34,12 @@
.matches = {
DMI_MATCH(DMI_BOARD_NAME, "SABERTOOTH X58")
}
+ }, {
+ /* Old interface reads the same sensor for fan0 and fan1 */
+ .ident = "Asus M5A78L",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "M5A78L")
+ }
},
{ }
};
diff --git a/drivers/ide/ide-pm.c b/drivers/ide/ide-pm.c
index 9240609..8d1e32d 100644
--- a/drivers/ide/ide-pm.c
+++ b/drivers/ide/ide-pm.c
@@ -4,7 +4,7 @@
int generic_ide_suspend(struct device *dev, pm_message_t mesg)
{
- ide_drive_t *drive = dev_get_drvdata(dev);
+ ide_drive_t *drive = to_ide_device(dev);
ide_drive_t *pair = ide_get_pair_dev(drive);
ide_hwif_t *hwif = drive->hwif;
struct request *rq;
@@ -40,7 +40,7 @@
int generic_ide_resume(struct device *dev)
{
- ide_drive_t *drive = dev_get_drvdata(dev);
+ ide_drive_t *drive = to_ide_device(dev);
ide_drive_t *pair = ide_get_pair_dev(drive);
ide_hwif_t *hwif = drive->hwif;
struct request *rq;
diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c
index ff4c0a8..ce68e36 100644
--- a/drivers/input/keyboard/imx_keypad.c
+++ b/drivers/input/keyboard/imx_keypad.c
@@ -358,6 +358,7 @@
/* Inhibit KDI and KRI interrupts. */
reg_val = readw(keypad->mmio_base + KPSR);
reg_val &= ~(KBD_STAT_KRIE | KBD_STAT_KDIE);
+ reg_val |= KBD_STAT_KPKR | KBD_STAT_KPKD;
writew(reg_val, keypad->mmio_base + KPSR);
/* Colums as open drain and disable all rows */
@@ -515,7 +516,9 @@
input_set_drvdata(input_dev, keypad);
/* Ensure that the keypad will stay dormant until opened */
+ clk_enable(keypad->clk);
imx_keypad_inhibit(keypad);
+ clk_disable(keypad->clk);
error = request_irq(irq, imx_keypad_irq_handler, 0,
pdev->name, keypad);
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 5ec774d..6918773 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -177,6 +177,20 @@
},
},
{
+ /* Gigabyte T1005 - defines wrong chassis type ("Other") */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "T1005"),
+ },
+ },
+ {
+ /* Gigabyte T1005M/P - defines wrong chassis type ("Other") */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "T1005M/P"),
+ },
+ },
+ {
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv9700"),
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 0020419..532d067 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -1848,7 +1848,10 @@
{ "Wacom Intuos5 M", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047,
63, INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
static const struct wacom_features wacom_features_0xF4 =
- { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047,
+ { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047,
+ 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0xF8 =
+ { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047,
63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
static const struct wacom_features wacom_features_0x3F =
{ "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023,
@@ -2091,6 +2094,7 @@
{ USB_DEVICE_WACOM(0xEF) },
{ USB_DEVICE_WACOM(0x47) },
{ USB_DEVICE_WACOM(0xF4) },
+ { USB_DEVICE_WACOM(0xF8) },
{ USB_DEVICE_WACOM(0xFA) },
{ USB_DEVICE_LENOVO(0x6004) },
{ }
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index 9afc777..b06a5e3 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -602,6 +602,7 @@
{
if (tsdata->debug_dir)
debugfs_remove_recursive(tsdata->debug_dir);
+ kfree(tsdata->raw_buffer);
}
#else
@@ -843,7 +844,6 @@
if (gpio_is_valid(pdata->reset_pin))
gpio_free(pdata->reset_pin);
- kfree(tsdata->raw_buffer);
kfree(tsdata);
return 0;
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 38c4bd8..c679867 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -234,7 +234,8 @@
mp->minor = minor;
- dev = tty_register_device(capinc_tty_driver, minor, NULL);
+ dev = tty_port_register_device(&mp->port, capinc_tty_driver, minor,
+ NULL);
if (IS_ERR(dev))
goto err_out2;
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c
index a6d9fd2..67abf3f 100644
--- a/drivers/isdn/gigaset/interface.c
+++ b/drivers/isdn/gigaset/interface.c
@@ -446,8 +446,8 @@
goto out;
}
- iflag = tty->termios->c_iflag;
- cflag = tty->termios->c_cflag;
+ iflag = tty->termios.c_iflag;
+ cflag = tty->termios.c_cflag;
old_cflag = old ? old->c_cflag : cflag;
gig_dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x",
cs->minor_index, iflag, cflag, old_cflag);
@@ -524,7 +524,8 @@
tasklet_init(&cs->if_wake_tasklet, if_wake, (unsigned long) cs);
mutex_lock(&cs->mutex);
- cs->tty_dev = tty_register_device(drv->tty, cs->minor_index, NULL);
+ cs->tty_dev = tty_port_register_device(&cs->port, drv->tty,
+ cs->minor_index, NULL);
if (!IS_ERR(cs->tty_dev))
dev_set_drvdata(cs->tty_dev, cs);
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index 7bc5067..b817809 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -1009,15 +1009,15 @@
quot;
int i;
- if (!port->tty || !port->tty->termios)
+ if (!port->tty)
return;
- cflag = port->tty->termios->c_cflag;
+ cflag = port->tty->termios.c_cflag;
quot = i = cflag & CBAUD;
if (i & CBAUDEX) {
i &= ~CBAUDEX;
if (i < 1 || i > 2)
- port->tty->termios->c_cflag &= ~CBAUDEX;
+ port->tty->termios.c_cflag &= ~CBAUDEX;
else
i += 15;
}
@@ -1097,7 +1097,7 @@
#endif
isdn_unlock_drivers();
info->msr &= ~UART_MSR_RI;
- if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) {
+ if (!info->port.tty || (info->port.tty->termios.c_cflag & HUPCL)) {
info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS);
if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
isdn_tty_modem_reset_regs(info, 0);
@@ -1469,13 +1469,13 @@
if (!old_termios)
isdn_tty_change_speed(info);
else {
- if (tty->termios->c_cflag == old_termios->c_cflag &&
- tty->termios->c_ispeed == old_termios->c_ispeed &&
- tty->termios->c_ospeed == old_termios->c_ospeed)
+ if (tty->termios.c_cflag == old_termios->c_cflag &&
+ tty->termios.c_ispeed == old_termios->c_ispeed &&
+ tty->termios.c_ospeed == old_termios->c_ospeed)
return;
isdn_tty_change_speed(info);
if ((old_termios->c_cflag & CRTSCTS) &&
- !(tty->termios->c_cflag & CRTSCTS))
+ !(tty->termios.c_cflag & CRTSCTS))
tty->hw_stopped = 0;
}
}
@@ -1486,6 +1486,18 @@
* ------------------------------------------------------------
*/
+static int isdn_tty_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+ modem_info *info = &dev->mdm.info[tty->index];
+
+ if (isdn_tty_paranoia_check(info, tty->name, __func__))
+ return -ENODEV;
+
+ tty->driver_data = info;
+
+ return tty_port_install(&info->port, driver, tty);
+}
+
/*
* This routine is called whenever a serial port is opened. It
* enables interrupts for a serial port, linking in its async structure into
@@ -1495,22 +1507,16 @@
static int
isdn_tty_open(struct tty_struct *tty, struct file *filp)
{
- struct tty_port *port;
- modem_info *info;
+ modem_info *info = tty->driver_data;
+ struct tty_port *port = &info->port;
int retval;
- info = &dev->mdm.info[tty->index];
- if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_open"))
- return -ENODEV;
- port = &info->port;
#ifdef ISDN_DEBUG_MODEM_OPEN
printk(KERN_DEBUG "isdn_tty_open %s, count = %d\n", tty->name,
port->count);
#endif
port->count++;
- tty->driver_data = info;
port->tty = tty;
- tty->port = port;
/*
* Start up serial port
*/
@@ -1738,6 +1744,7 @@
}
static const struct tty_operations modem_ops = {
+ .install = isdn_tty_install,
.open = isdn_tty_open,
.close = isdn_tty_close,
.write = isdn_tty_write,
@@ -1782,7 +1789,7 @@
m->tty_modem->subtype = SERIAL_TYPE_NORMAL;
m->tty_modem->init_termios = tty_std_termios;
m->tty_modem->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
- m->tty_modem->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+ m->tty_modem->flags = TTY_DRIVER_REAL_RAW;
m->tty_modem->driver_name = "isdn_tty";
tty_set_operations(m->tty_modem, &modem_ops);
retval = tty_register_driver(m->tty_modem);
diff --git a/drivers/misc/ibmasm/uart.c b/drivers/misc/ibmasm/uart.c
index 1dcb9ae..01e2b0d 100644
--- a/drivers/misc/ibmasm/uart.c
+++ b/drivers/misc/ibmasm/uart.c
@@ -33,7 +33,7 @@
void ibmasm_register_uart(struct service_processor *sp)
{
- struct uart_port uport;
+ struct uart_8250_port uart;
void __iomem *iomem_base;
iomem_base = sp->base_address + SCOUT_COM_B_BASE;
@@ -47,14 +47,14 @@
return;
}
- memset(&uport, 0, sizeof(struct uart_port));
- uport.irq = sp->irq;
- uport.uartclk = 3686400;
- uport.flags = UPF_SHARE_IRQ;
- uport.iotype = UPIO_MEM;
- uport.membase = iomem_base;
+ memset(&uart, 0, sizeof(uart));
+ uart.port.irq = sp->irq;
+ uart.port.uartclk = 3686400;
+ uart.port.flags = UPF_SHARE_IRQ;
+ uart.port.iotype = UPIO_MEM;
+ uart.port.membase = iomem_base;
- sp->serial_line = serial8250_register_port(&uport);
+ sp->serial_line = serial8250_register_8250_port(&uart);
if (sp->serial_line < 0) {
dev_err(sp->dev, "Failed to register serial port\n");
return;
diff --git a/drivers/misc/pti.c b/drivers/misc/pti.c
index b7eb545..4999b34 100644
--- a/drivers/misc/pti.c
+++ b/drivers/misc/pti.c
@@ -60,7 +60,7 @@
};
struct pti_dev {
- struct tty_port port;
+ struct tty_port port[PTITTY_MINOR_NUM];
unsigned long pti_addr;
unsigned long aperture_base;
void __iomem *pti_ioaddr;
@@ -76,7 +76,7 @@
*/
static DEFINE_MUTEX(alloclock);
-static struct pci_device_id pci_ids[] __devinitconst = {
+static const struct pci_device_id pci_ids[] __devinitconst = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x82B)},
{0}
};
@@ -393,25 +393,6 @@
}
EXPORT_SYMBOL_GPL(pti_writedata);
-/**
- * pti_pci_remove()- Driver exit method to remove PTI from
- * PCI bus.
- * @pdev: variable containing pci info of PTI.
- */
-static void __devexit pti_pci_remove(struct pci_dev *pdev)
-{
- struct pti_dev *drv_data;
-
- drv_data = pci_get_drvdata(pdev);
- if (drv_data != NULL) {
- pci_iounmap(pdev, drv_data->pti_ioaddr);
- pci_set_drvdata(pdev, NULL);
- kfree(drv_data);
- pci_release_region(pdev, 1);
- pci_disable_device(pdev);
- }
-}
-
/*
* for the tty_driver_*() basic function descriptions, see tty_driver.h.
* Specific header comments made for PTI-related specifics.
@@ -446,7 +427,7 @@
* also removes a locking requirement for the actual write
* procedure.
*/
- return tty_port_open(&drv_data->port, tty, filp);
+ return tty_port_open(tty->port, tty, filp);
}
/**
@@ -462,7 +443,7 @@
*/
static void pti_tty_driver_close(struct tty_struct *tty, struct file *filp)
{
- tty_port_close(&drv_data->port, tty, filp);
+ tty_port_close(tty->port, tty, filp);
}
/**
@@ -818,6 +799,7 @@
static int __devinit pti_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
+ unsigned int a;
int retval = -EINVAL;
int pci_bar = 1;
@@ -830,7 +812,7 @@
__func__, __LINE__);
pr_err("%s(%d): Error value returned: %d\n",
__func__, __LINE__, retval);
- return retval;
+ goto err;
}
retval = pci_enable_device(pdev);
@@ -838,17 +820,16 @@
dev_err(&pdev->dev,
"%s: pci_enable_device() returned error %d\n",
__func__, retval);
- return retval;
+ goto err_unreg_misc;
}
drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
-
if (drv_data == NULL) {
retval = -ENOMEM;
dev_err(&pdev->dev,
"%s(%d): kmalloc() returned NULL memory.\n",
__func__, __LINE__);
- return retval;
+ goto err_disable_pci;
}
drv_data->pti_addr = pci_resource_start(pdev, pci_bar);
@@ -857,33 +838,65 @@
dev_err(&pdev->dev,
"%s(%d): pci_request_region() returned error %d\n",
__func__, __LINE__, retval);
- kfree(drv_data);
- return retval;
+ goto err_free_dd;
}
drv_data->aperture_base = drv_data->pti_addr+APERTURE_14;
drv_data->pti_ioaddr =
ioremap_nocache((u32)drv_data->aperture_base,
APERTURE_LEN);
if (!drv_data->pti_ioaddr) {
- pci_release_region(pdev, pci_bar);
retval = -ENOMEM;
- kfree(drv_data);
- return retval;
+ goto err_rel_reg;
}
pci_set_drvdata(pdev, drv_data);
- tty_port_init(&drv_data->port);
- drv_data->port.ops = &tty_port_ops;
+ for (a = 0; a < PTITTY_MINOR_NUM; a++) {
+ struct tty_port *port = &drv_data->port[a];
+ tty_port_init(port);
+ port->ops = &tty_port_ops;
- tty_register_device(pti_tty_driver, 0, &pdev->dev);
- tty_register_device(pti_tty_driver, 1, &pdev->dev);
+ tty_port_register_device(port, pti_tty_driver, a, &pdev->dev);
+ }
register_console(&pti_console);
+ return 0;
+err_rel_reg:
+ pci_release_region(pdev, pci_bar);
+err_free_dd:
+ kfree(drv_data);
+err_disable_pci:
+ pci_disable_device(pdev);
+err_unreg_misc:
+ misc_deregister(&pti_char_driver);
+err:
return retval;
}
+/**
+ * pti_pci_remove()- Driver exit method to remove PTI from
+ * PCI bus.
+ * @pdev: variable containing pci info of PTI.
+ */
+static void __devexit pti_pci_remove(struct pci_dev *pdev)
+{
+ struct pti_dev *drv_data = pci_get_drvdata(pdev);
+
+ unregister_console(&pti_console);
+
+ tty_unregister_device(pti_tty_driver, 0);
+ tty_unregister_device(pti_tty_driver, 1);
+
+ iounmap(drv_data->pti_ioaddr);
+ pci_set_drvdata(pdev, NULL);
+ kfree(drv_data);
+ pci_release_region(pdev, 1);
+ pci_disable_device(pdev);
+
+ misc_deregister(&pti_char_driver);
+}
+
static struct pci_driver pti_pci_driver = {
.name = PCINAME,
.id_table = pci_ids,
@@ -933,25 +946,24 @@
pr_err("%s(%d): Error value returned: %d\n",
__func__, __LINE__, retval);
- pti_tty_driver = NULL;
- return retval;
+ goto put_tty;
}
retval = pci_register_driver(&pti_pci_driver);
-
if (retval) {
pr_err("%s(%d): PCI registration failed of pti driver\n",
__func__, __LINE__);
pr_err("%s(%d): Error value returned: %d\n",
__func__, __LINE__, retval);
-
- tty_unregister_driver(pti_tty_driver);
- pr_err("%s(%d): Unregistering TTY part of pti driver\n",
- __func__, __LINE__);
- pti_tty_driver = NULL;
- return retval;
+ goto unreg_tty;
}
+ return 0;
+unreg_tty:
+ tty_unregister_driver(pti_tty_driver);
+put_tty:
+ put_tty_driver(pti_tty_driver);
+ pti_tty_driver = NULL;
return retval;
}
@@ -960,31 +972,9 @@
*/
static void __exit pti_exit(void)
{
- int retval;
-
- tty_unregister_device(pti_tty_driver, 0);
- tty_unregister_device(pti_tty_driver, 1);
-
- retval = tty_unregister_driver(pti_tty_driver);
- if (retval) {
- pr_err("%s(%d): TTY unregistration failed of pti driver\n",
- __func__, __LINE__);
- pr_err("%s(%d): Error value returned: %d\n",
- __func__, __LINE__, retval);
- }
-
+ tty_unregister_driver(pti_tty_driver);
pci_unregister_driver(&pti_pci_driver);
-
- retval = misc_deregister(&pti_char_driver);
- if (retval) {
- pr_err("%s(%d): CHAR unregistration failed of pti driver\n",
- __func__, __LINE__);
- pr_err("%s(%d): Error value returned: %d\n",
- __func__, __LINE__, retval);
- }
-
- unregister_console(&pti_console);
- return;
+ put_tty_driver(pti_tty_driver);
}
module_init(pti_init);
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index f1c84de..172a768 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1411,7 +1411,8 @@
/* complete ongoing async transfer before issuing discard */
if (card->host->areq)
mmc_blk_issue_rw_rq(mq, NULL);
- if (req->cmd_flags & REQ_SECURE)
+ if (req->cmd_flags & REQ_SECURE &&
+ !(card->quirks & MMC_QUIRK_SEC_ERASE_TRIM_BROKEN))
ret = mmc_blk_issue_secdiscard_rq(mq, req);
else
ret = mmc_blk_issue_discard_rq(mq, req);
@@ -1716,6 +1717,7 @@
#define CID_MANFID_SANDISK 0x2
#define CID_MANFID_TOSHIBA 0x11
#define CID_MANFID_MICRON 0x13
+#define CID_MANFID_SAMSUNG 0x15
static const struct mmc_fixup blk_fixups[] =
{
@@ -1752,6 +1754,28 @@
MMC_FIXUP(CID_NAME_ANY, CID_MANFID_MICRON, 0x200, add_quirk_mmc,
MMC_QUIRK_LONG_READ_TIME),
+ /*
+ * On these Samsung MoviNAND parts, performing secure erase or
+ * secure trim can result in unrecoverable corruption due to a
+ * firmware bug.
+ */
+ MMC_FIXUP("M8G2FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+ MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+ MMC_FIXUP("MAG4FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+ MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+ MMC_FIXUP("MBG8FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+ MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+ MMC_FIXUP("MCGAFA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+ MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+ MMC_FIXUP("VAL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+ MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+ MMC_FIXUP("VYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+ MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+ MMC_FIXUP("KYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+ MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+ MMC_FIXUP("VZL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+ MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+
END_FIXUP
};
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c
index 5a2cbfa..d2339ea 100644
--- a/drivers/mmc/card/sdio_uart.c
+++ b/drivers/mmc/card/sdio_uart.c
@@ -518,7 +518,7 @@
if (status & UART_MSR_DCTS) {
port->icount.cts++;
tty = tty_port_tty_get(&port->port);
- if (tty && (tty->termios->c_cflag & CRTSCTS)) {
+ if (tty && (tty->termios.c_cflag & CRTSCTS)) {
int cts = (status & UART_MSR_CTS);
if (tty->hw_stopped) {
if (cts) {
@@ -671,12 +671,12 @@
port->ier = UART_IER_RLSI|UART_IER_RDI|UART_IER_RTOIE|UART_IER_UUE;
port->mctrl = TIOCM_OUT2;
- sdio_uart_change_speed(port, tty->termios, NULL);
+ sdio_uart_change_speed(port, &tty->termios, NULL);
- if (tty->termios->c_cflag & CBAUD)
+ if (tty->termios.c_cflag & CBAUD)
sdio_uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR);
- if (tty->termios->c_cflag & CRTSCTS)
+ if (tty->termios.c_cflag & CRTSCTS)
if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS))
tty->hw_stopped = 1;
@@ -850,7 +850,7 @@
{
struct sdio_uart_port *port = tty->driver_data;
- if (!I_IXOFF(tty) && !(tty->termios->c_cflag & CRTSCTS))
+ if (!I_IXOFF(tty) && !(tty->termios.c_cflag & CRTSCTS))
return;
if (sdio_uart_claim_func(port) != 0)
@@ -861,7 +861,7 @@
sdio_uart_start_tx(port);
}
- if (tty->termios->c_cflag & CRTSCTS)
+ if (tty->termios.c_cflag & CRTSCTS)
sdio_uart_clear_mctrl(port, TIOCM_RTS);
sdio_uart_irq(port->func);
@@ -872,7 +872,7 @@
{
struct sdio_uart_port *port = tty->driver_data;
- if (!I_IXOFF(tty) && !(tty->termios->c_cflag & CRTSCTS))
+ if (!I_IXOFF(tty) && !(tty->termios.c_cflag & CRTSCTS))
return;
if (sdio_uart_claim_func(port) != 0)
@@ -887,7 +887,7 @@
}
}
- if (tty->termios->c_cflag & CRTSCTS)
+ if (tty->termios.c_cflag & CRTSCTS)
sdio_uart_set_mctrl(port, TIOCM_RTS);
sdio_uart_irq(port->func);
@@ -898,12 +898,12 @@
struct ktermios *old_termios)
{
struct sdio_uart_port *port = tty->driver_data;
- unsigned int cflag = tty->termios->c_cflag;
+ unsigned int cflag = tty->termios.c_cflag;
if (sdio_uart_claim_func(port) != 0)
return;
- sdio_uart_change_speed(port, tty->termios, old_termios);
+ sdio_uart_change_speed(port, &tty->termios, old_termios);
/* Handle transition to B0 status */
if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
@@ -1132,8 +1132,8 @@
kfree(port);
} else {
struct device *dev;
- dev = tty_register_device(sdio_uart_tty_driver,
- port->index, &func->dev);
+ dev = tty_port_register_device(&port->port,
+ sdio_uart_tty_driver, port->index, &func->dev);
if (IS_ERR(dev)) {
sdio_uart_port_remove(port);
ret = PTR_ERR(dev);
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index 322412c..a53c7c4 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -81,6 +81,7 @@
bool has_bad_data_ordering;
bool need_reset_after_xfer;
bool need_blksz_mul_4;
+ bool need_notbusy_for_read_ops;
};
struct atmel_mci_dma {
@@ -1625,7 +1626,8 @@
__func__);
atmci_set_completed(host, EVENT_XFER_COMPLETE);
- if (host->data->flags & MMC_DATA_WRITE) {
+ if (host->caps.need_notbusy_for_read_ops ||
+ (host->data->flags & MMC_DATA_WRITE)) {
atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
state = STATE_WAITING_NOTBUSY;
} else if (host->mrq->stop) {
@@ -2218,6 +2220,7 @@
host->caps.has_bad_data_ordering = 1;
host->caps.need_reset_after_xfer = 1;
host->caps.need_blksz_mul_4 = 1;
+ host->caps.need_notbusy_for_read_ops = 0;
/* keep only major version number */
switch (version & 0xf00) {
@@ -2238,6 +2241,7 @@
case 0x200:
host->caps.has_rwproof = 1;
host->caps.need_blksz_mul_4 = 0;
+ host->caps.need_notbusy_for_read_ops = 1;
case 0x100:
host->caps.has_bad_data_ordering = 0;
host->caps.need_reset_after_xfer = 0;
diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c
index 0366617..a17dd73 100644
--- a/drivers/mmc/host/bfin_sdh.c
+++ b/drivers/mmc/host/bfin_sdh.c
@@ -49,13 +49,6 @@
#define bfin_write_SDH_CFG bfin_write_RSI_CFG
#endif
-struct dma_desc_array {
- unsigned long start_addr;
- unsigned short cfg;
- unsigned short x_count;
- short x_modify;
-} __packed;
-
struct sdh_host {
struct mmc_host *mmc;
spinlock_t lock;
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 72dc3cd..af40d22 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -627,6 +627,7 @@
{
struct dw_mci *host = slot->host;
u32 div;
+ u32 clk_en_a;
if (slot->clock != host->current_speed) {
div = host->bus_hz / slot->clock;
@@ -659,9 +660,11 @@
mci_send_cmd(slot,
SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0);
- /* enable clock */
- mci_writel(host, CLKENA, ((SDMMC_CLKEN_ENABLE |
- SDMMC_CLKEN_LOW_PWR) << slot->id));
+ /* enable clock; only low power if no SDIO */
+ clk_en_a = SDMMC_CLKEN_ENABLE << slot->id;
+ if (!(mci_readl(host, INTMASK) & SDMMC_INT_SDIO(slot->id)))
+ clk_en_a |= SDMMC_CLKEN_LOW_PWR << slot->id;
+ mci_writel(host, CLKENA, clk_en_a);
/* inform CIU */
mci_send_cmd(slot,
@@ -862,6 +865,30 @@
return present;
}
+/*
+ * Disable lower power mode.
+ *
+ * Low power mode will stop the card clock when idle. According to the
+ * description of the CLKENA register we should disable low power mode
+ * for SDIO cards if we need SDIO interrupts to work.
+ *
+ * This function is fast if low power mode is already disabled.
+ */
+static void dw_mci_disable_low_power(struct dw_mci_slot *slot)
+{
+ struct dw_mci *host = slot->host;
+ u32 clk_en_a;
+ const u32 clken_low_pwr = SDMMC_CLKEN_LOW_PWR << slot->id;
+
+ clk_en_a = mci_readl(host, CLKENA);
+
+ if (clk_en_a & clken_low_pwr) {
+ mci_writel(host, CLKENA, clk_en_a & ~clken_low_pwr);
+ mci_send_cmd(slot, SDMMC_CMD_UPD_CLK |
+ SDMMC_CMD_PRV_DAT_WAIT, 0);
+ }
+}
+
static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
{
struct dw_mci_slot *slot = mmc_priv(mmc);
@@ -871,6 +898,14 @@
/* Enable/disable Slot Specific SDIO interrupt */
int_mask = mci_readl(host, INTMASK);
if (enb) {
+ /*
+ * Turn off low power mode if it was enabled. This is a bit of
+ * a heavy operation and we disable / enable IRQs a lot, so
+ * we'll leave low power mode disabled and it will get
+ * re-enabled again in dw_mci_setup_bus().
+ */
+ dw_mci_disable_low_power(slot);
+
mci_writel(host, INTMASK,
(int_mask | SDMMC_INT_SDIO(slot->id)));
} else {
@@ -1429,22 +1464,10 @@
nbytes += len;
remain -= len;
} while (remain);
- sg_miter->consumed = offset;
+ sg_miter->consumed = offset;
status = mci_readl(host, MINTSTS);
mci_writel(host, RINTSTS, SDMMC_INT_RXDR);
- if (status & DW_MCI_DATA_ERROR_FLAGS) {
- host->data_status = status;
- data->bytes_xfered += nbytes;
- sg_miter_stop(sg_miter);
- host->sg = NULL;
- smp_wmb();
-
- set_bit(EVENT_DATA_ERROR, &host->pending_events);
-
- tasklet_schedule(&host->tasklet);
- return;
- }
} while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/
data->bytes_xfered += nbytes;
@@ -1497,23 +1520,10 @@
nbytes += len;
remain -= len;
} while (remain);
- sg_miter->consumed = offset;
+ sg_miter->consumed = offset;
status = mci_readl(host, MINTSTS);
mci_writel(host, RINTSTS, SDMMC_INT_TXDR);
- if (status & DW_MCI_DATA_ERROR_FLAGS) {
- host->data_status = status;
- data->bytes_xfered += nbytes;
- sg_miter_stop(sg_miter);
- host->sg = NULL;
-
- smp_wmb();
-
- set_bit(EVENT_DATA_ERROR, &host->pending_events);
-
- tasklet_schedule(&host->tasklet);
- return;
- }
} while (status & SDMMC_INT_TXDR); /* if TXDR write again */
data->bytes_xfered += nbytes;
@@ -1547,12 +1557,11 @@
static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
{
struct dw_mci *host = dev_id;
- u32 status, pending;
+ u32 pending;
unsigned int pass_count = 0;
int i;
do {
- status = mci_readl(host, RINTSTS);
pending = mci_readl(host, MINTSTS); /* read-only mask reg */
/*
@@ -1570,7 +1579,7 @@
if (pending & DW_MCI_CMD_ERROR_FLAGS) {
mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS);
- host->cmd_status = status;
+ host->cmd_status = pending;
smp_wmb();
set_bit(EVENT_CMD_COMPLETE, &host->pending_events);
}
@@ -1578,18 +1587,16 @@
if (pending & DW_MCI_DATA_ERROR_FLAGS) {
/* if there is an error report DATA_ERROR */
mci_writel(host, RINTSTS, DW_MCI_DATA_ERROR_FLAGS);
- host->data_status = status;
+ host->data_status = pending;
smp_wmb();
set_bit(EVENT_DATA_ERROR, &host->pending_events);
- if (!(pending & (SDMMC_INT_DTO | SDMMC_INT_DCRC |
- SDMMC_INT_SBE | SDMMC_INT_EBE)))
- tasklet_schedule(&host->tasklet);
+ tasklet_schedule(&host->tasklet);
}
if (pending & SDMMC_INT_DATA_OVER) {
mci_writel(host, RINTSTS, SDMMC_INT_DATA_OVER);
if (!host->data_status)
- host->data_status = status;
+ host->data_status = pending;
smp_wmb();
if (host->dir_status == DW_MCI_RECV_STATUS) {
if (host->sg != NULL)
@@ -1613,7 +1620,7 @@
if (pending & SDMMC_INT_CMD_DONE) {
mci_writel(host, RINTSTS, SDMMC_INT_CMD_DONE);
- dw_mci_cmd_interrupt(host, status);
+ dw_mci_cmd_interrupt(host, pending);
}
if (pending & SDMMC_INT_CD) {
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
index a51f930..ad3fcea 100644
--- a/drivers/mmc/host/mxs-mmc.c
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -285,11 +285,11 @@
writel(stat & MXS_MMC_IRQ_BITS,
host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_CLR);
+ spin_unlock(&host->lock);
+
if ((stat & BM_SSP_CTRL1_SDIO_IRQ) && (stat & BM_SSP_CTRL1_SDIO_IRQ_EN))
mmc_signal_sdio_irq(host->mmc);
- spin_unlock(&host->lock);
-
if (stat & BM_SSP_CTRL1_RESP_TIMEOUT_IRQ)
cmd->error = -ETIMEDOUT;
else if (stat & BM_SSP_CTRL1_RESP_ERR_IRQ)
@@ -644,11 +644,6 @@
host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
writel(BM_SSP_CTRL1_SDIO_IRQ_EN,
host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_SET);
-
- if (readl(host->base + HW_SSP_STATUS(host)) &
- BM_SSP_STATUS_SDIO_IRQ)
- mmc_signal_sdio_irq(host->mmc);
-
} else {
writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK,
host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
@@ -657,6 +652,11 @@
}
spin_unlock_irqrestore(&host->lock, flags);
+
+ if (enable && readl(host->base + HW_SSP_STATUS(host)) &
+ BM_SSP_STATUS_SDIO_IRQ)
+ mmc_signal_sdio_irq(host->mmc);
+
}
static const struct mmc_host_ops mxs_mmc_ops = {
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 50e08f0..87c0293 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -33,7 +33,6 @@
#include <asm/io.h>
#include <asm/irq.h>
-#include <plat/board.h>
#include <plat/mmc.h>
#include <asm/gpio.h>
#include <plat/dma.h>
@@ -668,7 +667,7 @@
static void
mmc_omap_xfer_data(struct mmc_omap_host *host, int write)
{
- int n;
+ int n, nwords;
if (host->buffer_bytes_left == 0) {
host->sg_idx++;
@@ -678,15 +677,23 @@
n = 64;
if (n > host->buffer_bytes_left)
n = host->buffer_bytes_left;
+
+ nwords = n / 2;
+ nwords += n & 1; /* handle odd number of bytes to transfer */
+
host->buffer_bytes_left -= n;
host->total_bytes_left -= n;
host->data->bytes_xfered += n;
if (write) {
- __raw_writesw(host->virt_base + OMAP_MMC_REG(host, DATA), host->buffer, n);
+ __raw_writesw(host->virt_base + OMAP_MMC_REG(host, DATA),
+ host->buffer, nwords);
} else {
- __raw_readsw(host->virt_base + OMAP_MMC_REG(host, DATA), host->buffer, n);
+ __raw_readsw(host->virt_base + OMAP_MMC_REG(host, DATA),
+ host->buffer, nwords);
}
+
+ host->buffer += nwords;
}
static inline void mmc_omap_report_irq(u16 status)
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 3a09f93..f871b31 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -40,7 +40,6 @@
#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
#include <mach/hardware.h>
-#include <plat/board.h>
#include <plat/mmc.h>
#include <plat/cpu.h>
diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h
index b97b2f5..d25f9ab 100644
--- a/drivers/mmc/host/sdhci-esdhc.h
+++ b/drivers/mmc/host/sdhci-esdhc.h
@@ -48,14 +48,14 @@
int div = 1;
u32 temp;
+ if (clock == 0)
+ goto out;
+
temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN
| ESDHC_CLOCK_MASK);
sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
- if (clock == 0)
- goto out;
-
while (host->max_clk / pre_div / 16 > clock && pre_div < 256)
pre_div *= 2;
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index 3ff893d..108ab1a 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -44,8 +44,6 @@
#include <plat/dma.h>
-#include <plat/board.h>
-
#define DRIVER_NAME "omap2-onenand"
#define ONENAND_BUFRAM_SIZE (1024 * 5)
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
index 437bc19..568307c 100644
--- a/drivers/mtd/ubi/vtbl.c
+++ b/drivers/mtd/ubi/vtbl.c
@@ -340,7 +340,7 @@
* of this LEB as it will be deleted and freed in 'ubi_add_to_av()'.
*/
err = ubi_add_to_av(ubi, ai, new_aeb->pnum, new_aeb->ec, vid_hdr, 0);
- kfree(new_aeb);
+ kmem_cache_free(ai->aeb_slab_cache, new_aeb);
ubi_free_vid_hdr(ubi, vid_hdr);
return err;
@@ -353,7 +353,7 @@
list_add(&new_aeb->u.list, &ai->erase);
goto retry;
}
- kfree(new_aeb);
+ kmem_cache_free(ai->aeb_slab_cache, new_aeb);
out_free:
ubi_free_vid_hdr(ubi, vid_hdr);
return err;
diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c
index 4f50145..662c5f7 100644
--- a/drivers/net/can/sja1000/sja1000_platform.c
+++ b/drivers/net/can/sja1000/sja1000_platform.c
@@ -109,7 +109,9 @@
priv = netdev_priv(dev);
dev->irq = res_irq->start;
- priv->irq_flags = res_irq->flags & (IRQF_TRIGGER_MASK | IRQF_SHARED);
+ priv->irq_flags = res_irq->flags & IRQF_TRIGGER_MASK;
+ if (res_irq->flags & IORESOURCE_IRQ_SHAREABLE)
+ priv->irq_flags |= IRQF_SHARED;
priv->reg_base = addr;
/* The CAN clock frequency is half the oscillator clock frequency */
priv->can.clock.freq = pdata->osc_freq / 2;
diff --git a/drivers/net/can/softing/softing_fw.c b/drivers/net/can/softing/softing_fw.c
index 3105961..b595d34 100644
--- a/drivers/net/can/softing/softing_fw.c
+++ b/drivers/net/can/softing/softing_fw.c
@@ -150,7 +150,7 @@
const uint8_t *mem, *end, *dat;
uint16_t type, len;
uint32_t addr;
- uint8_t *buf = NULL;
+ uint8_t *buf = NULL, *new_buf;
int buflen = 0;
int8_t type_end = 0;
@@ -199,11 +199,12 @@
if (len > buflen) {
/* align buflen */
buflen = (len + (1024-1)) & ~(1024-1);
- buf = krealloc(buf, buflen, GFP_KERNEL);
- if (!buf) {
+ new_buf = krealloc(buf, buflen, GFP_KERNEL);
+ if (!new_buf) {
ret = -ENOMEM;
goto failed;
}
+ buf = new_buf;
}
/* verify record data */
memcpy_fromio(buf, &dpram[addr + offset], len);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index 463b9ec..6d1a24a 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1708,9 +1708,6 @@
continue; \
else
-#define for_each_napi_rx_queue(bp, var) \
- for ((var) = 0; (var) < bp->num_napi_queues; (var)++)
-
/* Skip OOO FP */
#define for_each_tx_queue(bp, var) \
for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index e879e19..af20c6e 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -2046,6 +2046,8 @@
*/
bnx2x_setup_tc(bp->dev, bp->max_cos);
+ /* Add all NAPI objects */
+ bnx2x_add_all_napi(bp);
bnx2x_napi_enable(bp);
/* set pf load just before approaching the MCP */
@@ -2408,6 +2410,8 @@
/* Disable HW interrupts, NAPI */
bnx2x_netif_stop(bp, 1);
+ /* Delete all NAPI objects */
+ bnx2x_del_all_napi(bp);
/* Release IRQs */
bnx2x_free_irq(bp);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
index dfa757e..21b5532 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
@@ -792,7 +792,7 @@
bp->num_napi_queues = bp->num_queues;
/* Add NAPI objects */
- for_each_napi_rx_queue(bp, i)
+ for_each_rx_queue(bp, i)
netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
bnx2x_poll, BNX2X_NAPI_WEIGHT);
}
@@ -801,7 +801,7 @@
{
int i;
- for_each_napi_rx_queue(bp, i)
+ for_each_rx_queue(bp, i)
netif_napi_del(&bnx2x_fp(bp, i, napi));
}
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index fc4e0e3..c37a68d 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -2888,11 +2888,9 @@
*/
static void bnx2x_change_num_queues(struct bnx2x *bp, int num_rss)
{
- bnx2x_del_all_napi(bp);
bnx2x_disable_msi(bp);
BNX2X_NUM_QUEUES(bp) = num_rss + NON_ETH_CONTEXT_USE;
bnx2x_set_int_mode(bp);
- bnx2x_add_all_napi(bp);
}
/**
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 02b5a34..2105498 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -8427,6 +8427,8 @@
/* Disable HW interrupts, NAPI */
bnx2x_netif_stop(bp, 1);
+ /* Delete all NAPI objects */
+ bnx2x_del_all_napi(bp);
/* Release IRQs */
bnx2x_free_irq(bp);
@@ -11229,10 +11231,12 @@
static void poll_bnx2x(struct net_device *dev)
{
struct bnx2x *bp = netdev_priv(dev);
+ int i;
- disable_irq(bp->pdev->irq);
- bnx2x_interrupt(bp->pdev->irq, dev);
- enable_irq(bp->pdev->irq);
+ for_each_eth_queue(bp, i) {
+ struct bnx2x_fastpath *fp = &bp->fp[i];
+ napi_schedule(&bnx2x_fp(bp, fp->index, napi));
+ }
}
#endif
@@ -11899,9 +11903,6 @@
*/
bnx2x_set_int_mode(bp);
- /* Add all NAPI objects */
- bnx2x_add_all_napi(bp);
-
rc = register_netdev(dev);
if (rc) {
dev_err(&pdev->dev, "Cannot register net device\n");
@@ -11976,9 +11977,6 @@
unregister_netdev(dev);
- /* Delete all NAPI objects */
- bnx2x_del_all_napi(bp);
-
/* Power on: we can't let PCI layer write to us while we are in D3 */
bnx2x_set_power_state(bp, PCI_D0);
@@ -12025,6 +12023,8 @@
bnx2x_tx_disable(bp);
bnx2x_netif_stop(bp, 0);
+ /* Delete all NAPI objects */
+ bnx2x_del_all_napi(bp);
del_timer_sync(&bp->timer);
diff --git a/drivers/net/ethernet/cirrus/cs89x0.c b/drivers/net/ethernet/cirrus/cs89x0.c
index 845b202..1384469 100644
--- a/drivers/net/ethernet/cirrus/cs89x0.c
+++ b/drivers/net/ethernet/cirrus/cs89x0.c
@@ -1243,6 +1243,7 @@
{
struct net_local *lp = netdev_priv(dev);
unsigned long flags;
+ u16 cfg;
spin_lock_irqsave(&lp->lock, flags);
if (dev->flags & IFF_PROMISC)
@@ -1260,11 +1261,10 @@
/* in promiscuous mode, we accept errored packets,
* so we have to enable interrupts on them also
*/
- writereg(dev, PP_RxCFG,
- (lp->curr_rx_cfg |
- (lp->rx_mode == RX_ALL_ACCEPT)
- ? (RX_CRC_ERROR_ENBL | RX_RUNT_ENBL | RX_EXTRA_DATA_ENBL)
- : 0));
+ cfg = lp->curr_rx_cfg;
+ if (lp->rx_mode == RX_ALL_ACCEPT)
+ cfg |= RX_CRC_ERROR_ENBL | RX_RUNT_ENBL | RX_EXTRA_DATA_ENBL;
+ writereg(dev, PP_RxCFG, cfg);
spin_unlock_irqrestore(&lp->lock, flags);
}
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index 7fac97b..8c63d06 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -259,7 +259,7 @@
int num = 0, status = 0;
struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
- spin_lock_bh(&adapter->mcc_cq_lock);
+ spin_lock(&adapter->mcc_cq_lock);
while ((compl = be_mcc_compl_get(adapter))) {
if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
/* Interpret flags as an async trailer */
@@ -280,7 +280,7 @@
if (num)
be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num);
- spin_unlock_bh(&adapter->mcc_cq_lock);
+ spin_unlock(&adapter->mcc_cq_lock);
return status;
}
@@ -295,7 +295,9 @@
if (be_error(adapter))
return -EIO;
+ local_bh_disable();
status = be_process_mcc(adapter);
+ local_bh_enable();
if (atomic_read(&mcc_obj->q.used) == 0)
break;
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 90a903d8..78b8aa8 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -3763,7 +3763,9 @@
/* when interrupts are not yet enabled, just reap any pending
* mcc completions */
if (!netif_running(adapter->netdev)) {
+ local_bh_disable();
be_process_mcc(adapter);
+ local_bh_enable();
goto reschedule;
}
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 4605f72..d3233f5 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -1041,7 +1041,7 @@
if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) {
dev->hw_features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
- dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+ dev->features |= NETIF_F_HW_VLAN_RX;
}
if (priv->device_flags & FSL_GIANFAR_DEV_HAS_EXTENDED_HASH) {
diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h
index cd15332..cb3356c 100644
--- a/drivers/net/ethernet/intel/e1000e/e1000.h
+++ b/drivers/net/ethernet/intel/e1000e/e1000.h
@@ -310,6 +310,7 @@
*/
struct e1000_ring *tx_ring /* One per active queue */
____cacheline_aligned_in_smp;
+ u32 tx_fifo_limit;
struct napi_struct napi;
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 46c3b1f..d01a099 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -3517,6 +3517,15 @@
}
/*
+ * Alignment of Tx data is on an arbitrary byte boundary with the
+ * maximum size per Tx descriptor limited only to the transmit
+ * allocation of the packet buffer minus 96 bytes with an upper
+ * limit of 24KB due to receive synchronization limitations.
+ */
+ adapter->tx_fifo_limit = min_t(u32, ((er32(PBA) >> 16) << 10) - 96,
+ 24 << 10);
+
+ /*
* Disable Adaptive Interrupt Moderation if 2 full packets cannot
* fit in receive buffer.
*/
@@ -4785,12 +4794,9 @@
return 1;
}
-#define E1000_MAX_PER_TXD 8192
-#define E1000_MAX_TXD_PWR 12
-
static int e1000_tx_map(struct e1000_ring *tx_ring, struct sk_buff *skb,
unsigned int first, unsigned int max_per_txd,
- unsigned int nr_frags, unsigned int mss)
+ unsigned int nr_frags)
{
struct e1000_adapter *adapter = tx_ring->adapter;
struct pci_dev *pdev = adapter->pdev;
@@ -5023,20 +5029,19 @@
static int e1000_maybe_stop_tx(struct e1000_ring *tx_ring, int size)
{
+ BUG_ON(size > tx_ring->count);
+
if (e1000_desc_unused(tx_ring) >= size)
return 0;
return __e1000_maybe_stop_tx(tx_ring, size);
}
-#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1)
static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_ring *tx_ring = adapter->tx_ring;
unsigned int first;
- unsigned int max_per_txd = E1000_MAX_PER_TXD;
- unsigned int max_txd_pwr = E1000_MAX_TXD_PWR;
unsigned int tx_flags = 0;
unsigned int len = skb_headlen(skb);
unsigned int nr_frags;
@@ -5056,18 +5061,8 @@
}
mss = skb_shinfo(skb)->gso_size;
- /*
- * The controller does a simple calculation to
- * make sure there is enough room in the FIFO before
- * initiating the DMA for each buffer. The calc is:
- * 4 = ceil(buffer len/mss). To make sure we don't
- * overrun the FIFO, adjust the max buffer len if mss
- * drops.
- */
if (mss) {
u8 hdr_len;
- max_per_txd = min(mss << 2, max_per_txd);
- max_txd_pwr = fls(max_per_txd) - 1;
/*
* TSO Workaround for 82571/2/3 Controllers -- if skb->data
@@ -5097,12 +5092,12 @@
count++;
count++;
- count += TXD_USE_COUNT(len, max_txd_pwr);
+ count += DIV_ROUND_UP(len, adapter->tx_fifo_limit);
nr_frags = skb_shinfo(skb)->nr_frags;
for (f = 0; f < nr_frags; f++)
- count += TXD_USE_COUNT(skb_frag_size(&skb_shinfo(skb)->frags[f]),
- max_txd_pwr);
+ count += DIV_ROUND_UP(skb_frag_size(&skb_shinfo(skb)->frags[f]),
+ adapter->tx_fifo_limit);
if (adapter->hw.mac.tx_pkt_filtering)
e1000_transfer_dhcp_info(adapter, skb);
@@ -5144,15 +5139,18 @@
tx_flags |= E1000_TX_FLAGS_NO_FCS;
/* if count is 0 then mapping error has occurred */
- count = e1000_tx_map(tx_ring, skb, first, max_per_txd, nr_frags, mss);
+ count = e1000_tx_map(tx_ring, skb, first, adapter->tx_fifo_limit,
+ nr_frags);
if (count) {
skb_tx_timestamp(skb);
netdev_sent_queue(netdev, skb->len);
e1000_tx_queue(tx_ring, tx_flags, count);
/* Make sure there is space in the ring for the next send. */
- e1000_maybe_stop_tx(tx_ring, MAX_SKB_FRAGS + 2);
-
+ e1000_maybe_stop_tx(tx_ring,
+ (MAX_SKB_FRAGS *
+ DIV_ROUND_UP(PAGE_SIZE,
+ adapter->tx_fifo_limit) + 2));
} else {
dev_kfree_skb_any(skb);
tx_ring->buffer_info[first].time_stamp = 0;
@@ -6327,8 +6325,8 @@
adapter->hw.phy.autoneg_advertised = 0x2f;
/* ring size defaults */
- adapter->rx_ring->count = 256;
- adapter->tx_ring->count = 256;
+ adapter->rx_ring->count = E1000_DEFAULT_RXD;
+ adapter->tx_ring->count = E1000_DEFAULT_TXD;
/*
* Initial Wake on LAN setting - If APM wake is enabled in
diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c
index 8cba2df..5faedd8 100644
--- a/drivers/net/ethernet/sfc/ethtool.c
+++ b/drivers/net/ethernet/sfc/ethtool.c
@@ -863,8 +863,8 @@
&ip_entry->ip4dst, &ip_entry->pdst);
if (rc != 0) {
rc = efx_filter_get_ipv4_full(
- &spec, &proto, &ip_entry->ip4src, &ip_entry->psrc,
- &ip_entry->ip4dst, &ip_entry->pdst);
+ &spec, &proto, &ip_entry->ip4dst, &ip_entry->pdst,
+ &ip_entry->ip4src, &ip_entry->psrc);
EFX_WARN_ON_PARANOID(rc);
ip_mask->ip4src = ~0;
ip_mask->psrc = ~0;
diff --git a/drivers/net/ethernet/sgi/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c
index b5ba308..3e5519a 100644
--- a/drivers/net/ethernet/sgi/ioc3-eth.c
+++ b/drivers/net/ethernet/sgi/ioc3-eth.c
@@ -1147,15 +1147,17 @@
{
#define COSMISC_CONSTANT 6
- struct uart_port port = {
- .irq = 0,
- .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
- .iotype = UPIO_MEM,
- .regshift = 0,
- .uartclk = (22000000 << 1) / COSMISC_CONSTANT,
+ struct uart_8250_port port = {
+ .port = {
+ .irq = 0,
+ .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
+ .iotype = UPIO_MEM,
+ .regshift = 0,
+ .uartclk = (22000000 << 1) / COSMISC_CONSTANT,
- .membase = (unsigned char __iomem *) uart,
- .mapbase = (unsigned long) uart,
+ .membase = (unsigned char __iomem *) uart,
+ .mapbase = (unsigned long) uart,
+ }
};
unsigned char lcr;
@@ -1164,7 +1166,7 @@
uart->iu_scr = COSMISC_CONSTANT,
uart->iu_lcr = lcr;
uart->iu_lcr;
- serial8250_register_port(&port);
+ serial8250_register_8250_port(&port);
}
static void __devinit ioc3_serial_probe(struct pci_dev *pdev, struct ioc3 *ioc3)
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index e2d0832..719be39 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -22,6 +22,9 @@
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*******************************************************************************/
+#ifndef __COMMON_H__
+#define __COMMON_H__
+
#include <linux/etherdevice.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
@@ -366,3 +369,5 @@
extern void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr);
extern const struct stmmac_ring_mode_ops ring_mode_ops;
+
+#endif /* __COMMON_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/descs.h b/drivers/net/ethernet/stmicro/stmmac/descs.h
index 9820ec8..223adf9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/descs.h
+++ b/drivers/net/ethernet/stmicro/stmmac/descs.h
@@ -20,6 +20,10 @@
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*******************************************************************************/
+
+#ifndef __DESCS_H__
+#define __DESCS_H__
+
struct dma_desc {
/* Receive descriptor */
union {
@@ -166,3 +170,5 @@
* is not calculated */
cic_full = 3, /* IP header and pseudoheader */
};
+
+#endif /* __DESCS_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/descs_com.h b/drivers/net/ethernet/stmicro/stmmac/descs_com.h
index dd8d6e1..7ee9499 100644
--- a/drivers/net/ethernet/stmicro/stmmac/descs_com.h
+++ b/drivers/net/ethernet/stmicro/stmmac/descs_com.h
@@ -27,6 +27,9 @@
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*******************************************************************************/
+#ifndef __DESC_COM_H__
+#define __DESC_COM_H__
+
#if defined(CONFIG_STMMAC_RING)
static inline void ehn_desc_rx_set_on_ring_chain(struct dma_desc *p, int end)
{
@@ -124,3 +127,5 @@
p->des01.tx.buffer1_size = len;
}
#endif
+
+#endif /* __DESC_COM_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100.h b/drivers/net/ethernet/stmicro/stmmac/dwmac100.h
index 7c6d857..2ec6aea 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100.h
@@ -22,6 +22,9 @@
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*******************************************************************************/
+#ifndef __DWMAC100_H__
+#define __DWMAC100_H__
+
#include <linux/phy.h>
#include "common.h"
@@ -119,3 +122,5 @@
#define DMA_MISSED_FRAME_M_CNTR 0x0000ffff /* Missed Frame Couinter */
extern const struct stmmac_dma_ops dwmac100_dma_ops;
+
+#endif /* __DWMAC100_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
index f90fcb5..0e4cace 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
@@ -19,6 +19,8 @@
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*******************************************************************************/
+#ifndef __DWMAC1000_H__
+#define __DWMAC1000_H__
#include <linux/phy.h>
#include "common.h"
@@ -229,6 +231,7 @@
#define GMAC_MMC_RX_CSUM_OFFLOAD 0x208
/* Synopsys Core versions */
-#define DWMAC_CORE_3_40 34
+#define DWMAC_CORE_3_40 0x34
extern const struct stmmac_dma_ops dwmac1000_dma_ops;
+#endif /* __DWMAC1000_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
index e678ce3..e49c9a0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
@@ -22,6 +22,9 @@
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*******************************************************************************/
+#ifndef __DWMAC_DMA_H__
+#define __DWMAC_DMA_H__
+
/* DMA CRS Control and Status Register Mapping */
#define DMA_BUS_MODE 0x00001000 /* Bus Mode */
#define DMA_XMT_POLL_DEMAND 0x00001004 /* Transmit Poll Demand */
@@ -109,3 +112,5 @@
extern void dwmac_dma_stop_rx(void __iomem *ioaddr);
extern int dwmac_dma_interrupt(void __iomem *ioaddr,
struct stmmac_extra_stats *x);
+
+#endif /* __DWMAC_DMA_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/mmc.h b/drivers/net/ethernet/stmicro/stmmac/mmc.h
index a3835202..67995ef 100644
--- a/drivers/net/ethernet/stmicro/stmmac/mmc.h
+++ b/drivers/net/ethernet/stmicro/stmmac/mmc.h
@@ -22,6 +22,9 @@
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*******************************************************************************/
+#ifndef __MMC_H__
+#define __MMC_H__
+
/* MMC control register */
/* When set, all counter are reset */
#define MMC_CNTRL_COUNTER_RESET 0x1
@@ -129,3 +132,5 @@
extern void dwmac_mmc_ctrl(void __iomem *ioaddr, unsigned int mode);
extern void dwmac_mmc_intr_all_mask(void __iomem *ioaddr);
extern void dwmac_mmc_read(void __iomem *ioaddr, struct stmmac_counters *mmc);
+
+#endif /* __MMC_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c
index c07cfe9..0c74a70 100644
--- a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c
@@ -33,7 +33,7 @@
#define MMC_TX_INTR 0x00000108 /* MMC TX Interrupt */
#define MMC_RX_INTR_MASK 0x0000010c /* MMC Interrupt Mask */
#define MMC_TX_INTR_MASK 0x00000110 /* MMC Interrupt Mask */
-#define MMC_DEFAUL_MASK 0xffffffff
+#define MMC_DEFAULT_MASK 0xffffffff
/* MMC TX counter registers */
@@ -147,8 +147,8 @@
/* To mask all all interrupts.*/
void dwmac_mmc_intr_all_mask(void __iomem *ioaddr)
{
- writel(MMC_DEFAUL_MASK, ioaddr + MMC_RX_INTR_MASK);
- writel(MMC_DEFAUL_MASK, ioaddr + MMC_TX_INTR_MASK);
+ writel(MMC_DEFAULT_MASK, ioaddr + MMC_RX_INTR_MASK);
+ writel(MMC_DEFAULT_MASK, ioaddr + MMC_TX_INTR_MASK);
}
/* This reads the MAC core counters (if actaully supported).
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index f2d3665..e872e1d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -20,6 +20,9 @@
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*******************************************************************************/
+#ifndef __STMMAC_H__
+#define __STMMAC_H__
+
#define STMMAC_RESOURCE_NAME "stmmaceth"
#define DRV_MODULE_VERSION "March_2012"
@@ -166,3 +169,5 @@
{
}
#endif /* CONFIG_STMMAC_PCI */
+
+#endif /* __STMMAC_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h
index 6863590..aea9b14 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h
@@ -21,6 +21,8 @@
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*******************************************************************************/
+#ifndef __STMMAC_TIMER_H__
+#define __STMMAC_TIMER_H__
struct stmmac_timer {
void (*timer_start) (unsigned int new_freq);
@@ -40,3 +42,5 @@
extern int tmu2_register_user(void *fnt, void *data);
extern void tmu2_unregister_user(void);
#endif
+
+#endif /* __STMMAC_TIMER_H__ */
diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c
index cd7ee20..a9ca4a0 100644
--- a/drivers/net/ethernet/ti/davinci_mdio.c
+++ b/drivers/net/ethernet/ti/davinci_mdio.c
@@ -394,8 +394,10 @@
struct device *dev = &pdev->dev;
struct davinci_mdio_data *data = dev_get_drvdata(dev);
- if (data->bus)
+ if (data->bus) {
+ mdiobus_unregister(data->bus);
mdiobus_free(data->bus);
+ }
if (data->clk)
clk_put(data->clk);
diff --git a/drivers/net/fddi/skfp/pmf.c b/drivers/net/fddi/skfp/pmf.c
index 24d8566..441b4dc 100644
--- a/drivers/net/fddi/skfp/pmf.c
+++ b/drivers/net/fddi/skfp/pmf.c
@@ -673,7 +673,7 @@
sm_pm_get_ls(smc,port_to_mib(smc,port))) ;
break ;
case SMT_P_REASON :
- * (u_long *) to = 0 ;
+ *(u32 *)to = 0 ;
sp_len = 4 ;
goto sp_done ;
case SMT_P1033 : /* time stamp */
diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c
index 3352b24..30087ca 100644
--- a/drivers/net/irda/irtty-sir.c
+++ b/drivers/net/irda/irtty-sir.c
@@ -124,8 +124,8 @@
tty = priv->tty;
mutex_lock(&tty->termios_mutex);
- old_termios = *(tty->termios);
- cflag = tty->termios->c_cflag;
+ old_termios = tty->termios;
+ cflag = tty->termios.c_cflag;
tty_encode_baud_rate(tty, speed, speed);
if (tty->ops->set_termios)
tty->ops->set_termios(tty, &old_termios);
@@ -281,15 +281,15 @@
int cflag;
mutex_lock(&tty->termios_mutex);
- old_termios = *(tty->termios);
- cflag = tty->termios->c_cflag;
+ old_termios = tty->termios;
+ cflag = tty->termios.c_cflag;
if (stop)
cflag &= ~CREAD;
else
cflag |= CREAD;
- tty->termios->c_cflag = cflag;
+ tty->termios.c_cflag = cflag;
if (tty->ops->set_termios)
tty->ops->set_termios(tty, &old_termios);
mutex_unlock(&tty->termios_mutex);
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index 62f30b4..605a4ba 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -1107,7 +1107,6 @@
struct ktermios *old)
{
struct hso_serial *serial = tty->driver_data;
- struct ktermios *termios;
if (!serial) {
printk(KERN_ERR "%s: no tty structures", __func__);
@@ -1119,16 +1118,15 @@
/*
* Fix up unsupported bits
*/
- termios = tty->termios;
- termios->c_iflag &= ~IXON; /* disable enable XON/XOFF flow control */
+ tty->termios.c_iflag &= ~IXON; /* disable enable XON/XOFF flow control */
- termios->c_cflag &=
+ tty->termios.c_cflag &=
~(CSIZE /* no size */
| PARENB /* disable parity bit */
| CBAUD /* clear current baud rate */
| CBAUDEX); /* clear current buad rate */
- termios->c_cflag |= CS8; /* character size 8 bits */
+ tty->termios.c_cflag |= CS8; /* character size 8 bits */
/* baud rate 115200 */
tty_encode_baud_rate(tty, 115200, 115200);
@@ -1425,14 +1423,14 @@
if (old)
D5("Termios called with: cflags new[%d] - old[%d]",
- tty->termios->c_cflag, old->c_cflag);
+ tty->termios.c_cflag, old->c_cflag);
/* the actual setup */
spin_lock_irqsave(&serial->serial_lock, flags);
if (serial->port.count)
_hso_serial_set_termios(tty, old);
else
- tty->termios = old;
+ tty->termios = *old;
spin_unlock_irqrestore(&serial->serial_lock, flags);
/* done */
@@ -2289,9 +2287,11 @@
if (minor < 0)
goto exit;
+ tty_port_init(&serial->port);
+
/* register our minor number */
- serial->parent->dev = tty_register_device(tty_drv, minor,
- &serial->parent->interface->dev);
+ serial->parent->dev = tty_port_register_device(&serial->port, tty_drv,
+ minor, &serial->parent->interface->dev);
dev = serial->parent->dev;
dev_set_drvdata(dev, serial->parent);
i = device_create_file(dev, &dev_attr_hsotype);
@@ -2300,7 +2300,6 @@
serial->minor = minor;
serial->magic = HSO_SERIAL_MAGIC;
spin_lock_init(&serial->serial_lock);
- tty_port_init(&serial->port);
serial->num_rx_urbs = num_urbs;
/* RX, allocate urb and initialize */
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 328397c..adfab3f 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -413,7 +413,9 @@
/* 5. Gobi 2000 and 3000 devices */
{QMI_GOBI_DEVICE(0x413c, 0x8186)}, /* Dell Gobi 2000 Modem device (N0218, VU936) */
+ {QMI_GOBI_DEVICE(0x413c, 0x8194)}, /* Dell Gobi 3000 Composite */
{QMI_GOBI_DEVICE(0x05c6, 0x920b)}, /* Generic Gobi 2000 Modem device */
+ {QMI_GOBI_DEVICE(0x05c6, 0x920d)}, /* Gobi 3000 Composite */
{QMI_GOBI_DEVICE(0x05c6, 0x9225)}, /* Sony Gobi 2000 Modem device (N0279, VU730) */
{QMI_GOBI_DEVICE(0x05c6, 0x9245)}, /* Samsung Gobi 2000 Modem device (VL176) */
{QMI_GOBI_DEVICE(0x03f0, 0x251d)}, /* HP Gobi 2000 Modem device (VP412) */
@@ -441,6 +443,8 @@
{QMI_GOBI_DEVICE(0x1199, 0x9015)}, /* Sierra Wireless Gobi 3000 Modem device */
{QMI_GOBI_DEVICE(0x1199, 0x9019)}, /* Sierra Wireless Gobi 3000 Modem device */
{QMI_GOBI_DEVICE(0x1199, 0x901b)}, /* Sierra Wireless MC7770 */
+ {QMI_GOBI_DEVICE(0x12d1, 0x14f1)}, /* Sony Gobi 3000 Composite */
+ {QMI_GOBI_DEVICE(0x1410, 0xa021)}, /* Foxconn Gobi 3000 Modem device (Novatel E396) */
{ } /* END */
};
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 8531c1c..fd4b26d 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1573,7 +1573,7 @@
netif_device_present(dev->net) &&
!timer_pending(&dev->delay) &&
!test_bit(EVENT_RX_HALT, &dev->flags))
- rx_alloc_submit(dev, GFP_KERNEL);
+ rx_alloc_submit(dev, GFP_NOIO);
if (!(dev->txq.qlen >= TX_QLEN(dev)))
netif_tx_wake_all_queues(dev->net);
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
index 4026c90..b7e0258 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath/ath5k/eeprom.c
@@ -1482,7 +1482,7 @@
case AR5K_EEPROM_MODE_11A:
offset += AR5K_EEPROM_TARGET_PWR_OFF_11A(ee->ee_version);
rate_pcal_info = ee->ee_rate_tpwr_a;
- ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_5GHZ_CHAN;
+ ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_5GHZ_RATE_CHAN;
break;
case AR5K_EEPROM_MODE_11B:
offset += AR5K_EEPROM_TARGET_PWR_OFF_11B(ee->ee_version);
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h
index dc2bcfe..94a9bbe 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.h
+++ b/drivers/net/wireless/ath/ath5k/eeprom.h
@@ -182,6 +182,7 @@
#define AR5K_EEPROM_EEP_DELTA 10
#define AR5K_EEPROM_N_MODES 3
#define AR5K_EEPROM_N_5GHZ_CHAN 10
+#define AR5K_EEPROM_N_5GHZ_RATE_CHAN 8
#define AR5K_EEPROM_N_2GHZ_CHAN 3
#define AR5K_EEPROM_N_2GHZ_CHAN_2413 4
#define AR5K_EEPROM_N_2GHZ_CHAN_MAX 4
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index 192ad5c..a5edebe 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -1233,6 +1233,9 @@
/* dpc will not be rescheduled */
wl->resched = false;
+ /* inform publicly that interface is down */
+ wl->pub->up = false;
+
return 0;
}
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index 95aa8e1..83324b3 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -2042,7 +2042,8 @@
return;
}
len = ETH_ALEN;
- ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_AP_BSSID, &bssid, &len);
+ ret = ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_AP_BSSID, bssid,
+ &len);
if (ret) {
IPW_DEBUG_INFO("failed querying ordinals at line %d\n",
__LINE__);
diff --git a/drivers/net/wireless/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/iwlwifi/dvm/debugfs.c
index 46782f1..a47b306 100644
--- a/drivers/net/wireless/iwlwifi/dvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c
@@ -124,6 +124,9 @@
const struct fw_img *img;
size_t bufsz;
+ if (!iwl_is_ready_rf(priv))
+ return -EAGAIN;
+
/* default is to dump the entire data segment */
if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) {
priv->dbgfs_sram_offset = 0x800000;
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h
index d9694c5..4ffc18d 100644
--- a/drivers/net/wireless/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/iwlwifi/pcie/internal.h
@@ -350,7 +350,7 @@
/*****************************************************
* Error handling
******************************************************/
-int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display);
+int iwl_dump_fh(struct iwl_trans *trans, char **buf);
void iwl_dump_csr(struct iwl_trans *trans);
/*****************************************************
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index 39a6ca1..d1a61ba 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -555,7 +555,7 @@
}
iwl_dump_csr(trans);
- iwl_dump_fh(trans, NULL, false);
+ iwl_dump_fh(trans, NULL);
iwl_op_mode_nic_error(trans->op_mode);
}
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index 939c2f7..1e86ea2 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -1649,13 +1649,9 @@
#undef IWL_CMD
}
-int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display)
+int iwl_dump_fh(struct iwl_trans *trans, char **buf)
{
int i;
-#ifdef CONFIG_IWLWIFI_DEBUG
- int pos = 0;
- size_t bufsz = 0;
-#endif
static const u32 fh_tbl[] = {
FH_RSCSR_CHNL0_STTS_WPTR_REG,
FH_RSCSR_CHNL0_RBDCB_BASE_REG,
@@ -1667,29 +1663,35 @@
FH_TSSR_TX_STATUS_REG,
FH_TSSR_TX_ERROR_REG
};
-#ifdef CONFIG_IWLWIFI_DEBUG
- if (display) {
- bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+ if (buf) {
+ int pos = 0;
+ size_t bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
+
*buf = kmalloc(bufsz, GFP_KERNEL);
if (!*buf)
return -ENOMEM;
+
pos += scnprintf(*buf + pos, bufsz - pos,
"FH register values:\n");
- for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
+
+ for (i = 0; i < ARRAY_SIZE(fh_tbl); i++)
pos += scnprintf(*buf + pos, bufsz - pos,
" %34s: 0X%08x\n",
get_fh_string(fh_tbl[i]),
iwl_read_direct32(trans, fh_tbl[i]));
- }
+
return pos;
}
#endif
+
IWL_ERR(trans, "FH register values:\n");
- for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
+ for (i = 0; i < ARRAY_SIZE(fh_tbl); i++)
IWL_ERR(trans, " %34s: 0X%08x\n",
get_fh_string(fh_tbl[i]),
iwl_read_direct32(trans, fh_tbl[i]));
- }
+
return 0;
}
@@ -1982,11 +1984,11 @@
size_t count, loff_t *ppos)
{
struct iwl_trans *trans = file->private_data;
- char *buf;
+ char *buf = NULL;
int pos = 0;
ssize_t ret = -EFAULT;
- ret = pos = iwl_dump_fh(trans, &buf, true);
+ ret = pos = iwl_dump_fh(trans, &buf);
if (buf) {
ret = simple_read_from_buffer(user_buf,
count, ppos, buf, pos);
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 3089990..650f79a 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -57,8 +57,7 @@
static const struct ethtool_ops xennet_ethtool_ops;
struct netfront_cb {
- struct page *page;
- unsigned offset;
+ int pull_to;
};
#define NETFRONT_SKB_CB(skb) ((struct netfront_cb *)((skb)->cb))
@@ -867,15 +866,9 @@
struct sk_buff *skb;
while ((skb = __skb_dequeue(rxq)) != NULL) {
- struct page *page = NETFRONT_SKB_CB(skb)->page;
- void *vaddr = page_address(page);
- unsigned offset = NETFRONT_SKB_CB(skb)->offset;
+ int pull_to = NETFRONT_SKB_CB(skb)->pull_to;
- memcpy(skb->data, vaddr + offset,
- skb_headlen(skb));
-
- if (page != skb_frag_page(&skb_shinfo(skb)->frags[0]))
- __free_page(page);
+ __pskb_pull_tail(skb, pull_to - skb_headlen(skb));
/* Ethernet work: Delayed to here as it peeks the header. */
skb->protocol = eth_type_trans(skb, dev);
@@ -913,7 +906,6 @@
struct sk_buff_head errq;
struct sk_buff_head tmpq;
unsigned long flags;
- unsigned int len;
int err;
spin_lock(&np->rx_lock);
@@ -955,24 +947,13 @@
}
}
- NETFRONT_SKB_CB(skb)->page =
- skb_frag_page(&skb_shinfo(skb)->frags[0]);
- NETFRONT_SKB_CB(skb)->offset = rx->offset;
+ NETFRONT_SKB_CB(skb)->pull_to = rx->status;
+ if (NETFRONT_SKB_CB(skb)->pull_to > RX_COPY_THRESHOLD)
+ NETFRONT_SKB_CB(skb)->pull_to = RX_COPY_THRESHOLD;
- len = rx->status;
- if (len > RX_COPY_THRESHOLD)
- len = RX_COPY_THRESHOLD;
- skb_put(skb, len);
-
- if (rx->status > len) {
- skb_shinfo(skb)->frags[0].page_offset =
- rx->offset + len;
- skb_frag_size_set(&skb_shinfo(skb)->frags[0], rx->status - len);
- skb->data_len = rx->status - len;
- } else {
- __skb_fill_page_desc(skb, 0, NULL, 0, 0);
- skb_shinfo(skb)->nr_frags = 0;
- }
+ skb_shinfo(skb)->frags[0].page_offset = rx->offset;
+ skb_frag_size_set(&skb_shinfo(skb)->frags[0], rx->status);
+ skb->data_len = rx->status;
i = xennet_fill_frags(np, skb, &tmpq);
@@ -999,7 +980,7 @@
* receive throughout using the standard receive
* buffer size was cut by 25%(!!!).
*/
- skb->truesize += skb->data_len - (RX_COPY_THRESHOLD - len);
+ skb->truesize += skb->data_len - RX_COPY_THRESHOLD;
skb->len += skb->data_len;
if (rx->flags & XEN_NETRXF_csum_blank)
diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c
index 5d6de38..352f961 100644
--- a/drivers/parport/parport_gsc.c
+++ b/drivers/parport/parport_gsc.c
@@ -271,6 +271,7 @@
if (!parport_SPP_supported (p)) {
/* No port. */
kfree (priv);
+ kfree(ops);
return NULL;
}
parport_PS2_supported (p);
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index e9c3227..1631eeaf 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -62,6 +62,7 @@
timedia_9079a,
timedia_9079b,
timedia_9079c,
+ wch_ch353_2s1p,
};
/* each element directly indexed from enum list, above */
@@ -145,6 +146,7 @@
/* timedia_9079a */ { 1, { { 2, 3 }, } },
/* timedia_9079b */ { 1, { { 2, 3 }, } },
/* timedia_9079c */ { 1, { { 2, 3 }, } },
+ /* wch_ch353_2s1p*/ { 1, { { 2, -1}, } },
};
static struct pci_device_id parport_serial_pci_tbl[] = {
@@ -243,7 +245,8 @@
{ 0x1409, 0x7168, 0x1409, 0xb079, 0, 0, timedia_9079a },
{ 0x1409, 0x7168, 0x1409, 0xc079, 0, 0, timedia_9079b },
{ 0x1409, 0x7168, 0x1409, 0xd079, 0, 0, timedia_9079c },
-
+ /* WCH CARDS */
+ { 0x4348, 0x7053, 0x4348, 0x3253, 0, 0, wch_ch353_2s1p},
{ 0, } /* terminate list */
};
MODULE_DEVICE_TABLE(pci,parport_serial_pci_tbl);
@@ -460,6 +463,12 @@
.base_baud = 921600,
.uart_offset = 8,
},
+ [wch_ch353_2s1p] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 2,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
};
struct parport_serial_private {
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 5270f1a..d6fd6b6 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -280,8 +280,12 @@
{
struct drv_dev_and_id *ddi = _ddi;
struct device *dev = &ddi->dev->dev;
+ struct device *parent = dev->parent;
int rc;
+ /* The parent bridge must be in active state when probing */
+ if (parent)
+ pm_runtime_get_sync(parent);
/* Unbound PCI devices are always set to disabled and suspended.
* During probe, the device is set to enabled and active and the
* usage count is incremented. If the driver supports runtime PM,
@@ -298,6 +302,8 @@
pm_runtime_set_suspended(dev);
pm_runtime_put_noidle(dev);
}
+ if (parent)
+ pm_runtime_put(parent);
return rc;
}
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 6869009..02d107b 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -458,6 +458,40 @@
}
struct device_attribute vga_attr = __ATTR_RO(boot_vga);
+static void
+pci_config_pm_runtime_get(struct pci_dev *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device *parent = dev->parent;
+
+ if (parent)
+ pm_runtime_get_sync(parent);
+ pm_runtime_get_noresume(dev);
+ /*
+ * pdev->current_state is set to PCI_D3cold during suspending,
+ * so wait until suspending completes
+ */
+ pm_runtime_barrier(dev);
+ /*
+ * Only need to resume devices in D3cold, because config
+ * registers are still accessible for devices suspended but
+ * not in D3cold.
+ */
+ if (pdev->current_state == PCI_D3cold)
+ pm_runtime_resume(dev);
+}
+
+static void
+pci_config_pm_runtime_put(struct pci_dev *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device *parent = dev->parent;
+
+ pm_runtime_put(dev);
+ if (parent)
+ pm_runtime_put_sync(parent);
+}
+
static ssize_t
pci_read_config(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr,
@@ -484,6 +518,8 @@
size = count;
}
+ pci_config_pm_runtime_get(dev);
+
if ((off & 1) && size) {
u8 val;
pci_user_read_config_byte(dev, off, &val);
@@ -529,6 +565,8 @@
--size;
}
+ pci_config_pm_runtime_put(dev);
+
return count;
}
@@ -549,6 +587,8 @@
count = size;
}
+ pci_config_pm_runtime_get(dev);
+
if ((off & 1) && size) {
pci_user_write_config_byte(dev, off, data[off - init_off]);
off++;
@@ -587,6 +627,8 @@
--size;
}
+ pci_config_pm_runtime_put(dev);
+
return count;
}
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index f3ea977..ab4bf5a 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1941,6 +1941,7 @@
dev->pm_cap = pm;
dev->d3_delay = PCI_PM_D3_WAIT;
dev->d3cold_delay = PCI_PM_D3COLD_WAIT;
+ dev->d3cold_allowed = true;
dev->d1_support = false;
dev->d2_support = false;
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index 3a7eefc..e76b447 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -140,9 +140,17 @@
{
return 0;
}
+
+static int pcie_port_runtime_idle(struct device *dev)
+{
+ /* Delay for a short while to prevent too frequent suspend/resume */
+ pm_schedule_suspend(dev, 10);
+ return -EBUSY;
+}
#else
#define pcie_port_runtime_suspend NULL
#define pcie_port_runtime_resume NULL
+#define pcie_port_runtime_idle NULL
#endif
static const struct dev_pm_ops pcie_portdrv_pm_ops = {
@@ -155,6 +163,7 @@
.resume_noirq = pcie_port_resume_noirq,
.runtime_suspend = pcie_port_runtime_suspend,
.runtime_resume = pcie_port_runtime_resume,
+ .runtime_idle = pcie_port_runtime_idle,
};
#define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops)
@@ -200,6 +209,11 @@
return status;
pci_save_state(dev);
+ /*
+ * D3cold may not work properly on some PCIe port, so disable
+ * it by default.
+ */
+ dev->d3cold_allowed = false;
if (!pci_match_id(port_runtime_pm_black_list, dev))
pm_runtime_put_noidle(&dev->dev);
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 6c143b4..9f8a6b7 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -144,15 +144,13 @@
case PCI_BASE_ADDRESS_MEM_TYPE_32:
break;
case PCI_BASE_ADDRESS_MEM_TYPE_1M:
- dev_info(&dev->dev, "1M mem BAR treated as 32-bit BAR\n");
+ /* 1M mem BAR treated as 32-bit BAR */
break;
case PCI_BASE_ADDRESS_MEM_TYPE_64:
flags |= IORESOURCE_MEM_64;
break;
default:
- dev_warn(&dev->dev,
- "mem unknown type %x treated as 32-bit BAR\n",
- mem_type);
+ /* mem unknown type treated as 32-bit BAR */
break;
}
return flags;
@@ -173,9 +171,11 @@
u32 l, sz, mask;
u16 orig_cmd;
struct pci_bus_region region;
+ bool bar_too_big = false, bar_disabled = false;
mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
+ /* No printks while decoding is disabled! */
if (!dev->mmio_always_on) {
pci_read_config_word(dev, PCI_COMMAND, &orig_cmd);
pci_write_config_word(dev, PCI_COMMAND,
@@ -240,8 +240,7 @@
goto fail;
if ((sizeof(resource_size_t) < 8) && (sz64 > 0x100000000ULL)) {
- dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n",
- pos);
+ bar_too_big = true;
goto fail;
}
@@ -252,12 +251,11 @@
region.start = 0;
region.end = sz64;
pcibios_bus_to_resource(dev, res, ®ion);
+ bar_disabled = true;
} else {
region.start = l64;
region.end = l64 + sz64;
pcibios_bus_to_resource(dev, res, ®ion);
- dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n",
- pos, res);
}
} else {
sz = pci_size(l, sz, mask);
@@ -268,18 +266,23 @@
region.start = l;
region.end = l + sz;
pcibios_bus_to_resource(dev, res, ®ion);
-
- dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res);
}
- out:
+ goto out;
+
+
+fail:
+ res->flags = 0;
+out:
if (!dev->mmio_always_on)
pci_write_config_word(dev, PCI_COMMAND, orig_cmd);
+ if (bar_too_big)
+ dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n", pos);
+ if (res->flags && !bar_disabled)
+ dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res);
+
return (res->flags & IORESOURCE_MEM_64) ? 1 : 0;
- fail:
- res->flags = 0;
- goto out;
}
static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index 8318689..1dd61f4 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -58,6 +58,7 @@
struct rtc_device *rtcdev;
u32 imr;
void __iomem *gpbr;
+ int irq;
};
#define rtt_readl(rtc, field) \
@@ -292,7 +293,7 @@
{
struct resource *r, *r_gpbr;
struct sam9_rtc *rtc;
- int ret;
+ int ret, irq;
u32 mr;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -302,10 +303,18 @@
return -ENODEV;
}
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "failed to get interrupt resource\n");
+ return irq;
+ }
+
rtc = kzalloc(sizeof *rtc, GFP_KERNEL);
if (!rtc)
return -ENOMEM;
+ rtc->irq = irq;
+
/* platform setup code should have handled this; sigh */
if (!device_can_wakeup(&pdev->dev))
device_init_wakeup(&pdev->dev, 1);
@@ -345,11 +354,10 @@
}
/* register irq handler after we know what name we'll use */
- ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt,
- IRQF_SHARED,
+ ret = request_irq(rtc->irq, at91_rtc_interrupt, IRQF_SHARED,
dev_name(&rtc->rtcdev->dev), rtc);
if (ret) {
- dev_dbg(&pdev->dev, "can't share IRQ %d?\n", AT91_ID_SYS);
+ dev_dbg(&pdev->dev, "can't share IRQ %d?\n", rtc->irq);
rtc_device_unregister(rtc->rtcdev);
goto fail_register;
}
@@ -386,7 +394,7 @@
/* disable all interrupts */
rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN));
- free_irq(AT91_ID_SYS, rtc);
+ free_irq(rtc->irq, rtc);
rtc_device_unregister(rtc->rtcdev);
@@ -423,7 +431,7 @@
rtc->imr = mr & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN);
if (rtc->imr) {
if (device_may_wakeup(&pdev->dev) && (mr & AT91_RTT_ALMIEN)) {
- enable_irq_wake(AT91_ID_SYS);
+ enable_irq_wake(rtc->irq);
/* don't let RTTINC cause wakeups */
if (mr & AT91_RTT_RTTINCIEN)
rtt_writel(rtc, MR, mr & ~AT91_RTT_RTTINCIEN);
@@ -441,7 +449,7 @@
if (rtc->imr) {
if (device_may_wakeup(&pdev->dev))
- disable_irq_wake(AT91_ID_SYS);
+ disable_irq_wake(rtc->irq);
mr = rtt_readl(rtc, MR);
rtt_writel(rtc, MR, mr | rtc->imr);
}
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 40a826a..2fb2b9e 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -3804,7 +3804,7 @@
case BIODASDSYMMIO:
return dasd_symm_io(device, argp);
default:
- return -ENOIOCTLCMD;
+ return -ENOTTY;
}
}
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index cceae70..654c692 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -498,12 +498,9 @@
break;
default:
/* if the discipline has an ioctl method try it. */
- if (base->discipline->ioctl) {
+ rc = -ENOTTY;
+ if (base->discipline->ioctl)
rc = base->discipline->ioctl(block, cmd, argp);
- if (rc == -ENOIOCTLCMD)
- rc = -EINVAL;
- } else
- rc = -EINVAL;
}
dasd_put_device(base);
return rc;
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 6c0116d..9ffb6d5 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -716,10 +716,17 @@
static void raw3215_remove (struct ccw_device *cdev)
{
struct raw3215_info *raw;
+ unsigned int line;
ccw_device_set_offline(cdev);
raw = dev_get_drvdata(&cdev->dev);
if (raw) {
+ spin_lock(&raw3215_device_lock);
+ for (line = 0; line < NR_3215; line++)
+ if (raw3215[line] == raw)
+ break;
+ raw3215[line] = NULL;
+ spin_unlock(&raw3215_device_lock);
dev_set_drvdata(&cdev->dev, NULL);
raw3215_free_info(raw);
}
@@ -935,6 +942,19 @@
console_initcall(con3215_init);
#endif
+static int tty3215_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+ struct raw3215_info *raw;
+
+ raw = raw3215[tty->index];
+ if (raw == NULL)
+ return -ENODEV;
+
+ tty->driver_data = raw;
+
+ return tty_port_install(&raw->port, driver, tty);
+}
+
/*
* tty3215_open
*
@@ -942,14 +962,9 @@
*/
static int tty3215_open(struct tty_struct *tty, struct file * filp)
{
- struct raw3215_info *raw;
+ struct raw3215_info *raw = tty->driver_data;
int retval;
- raw = raw3215[tty->index];
- if (raw == NULL)
- return -ENODEV;
-
- tty->driver_data = raw;
tty_port_tty_set(&raw->port, tty);
tty->low_latency = 0; /* don't use bottom half for pushing chars */
@@ -1110,6 +1125,7 @@
}
static const struct tty_operations tty3215_ops = {
+ .install = tty3215_install,
.open = tty3215_open,
.close = tty3215_close,
.write = tty3215_write,
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
index 0792c85..30ec09e 100644
--- a/drivers/s390/char/sclp_tty.c
+++ b/drivers/s390/char/sclp_tty.c
@@ -567,6 +567,7 @@
driver->init_termios.c_lflag = ISIG | ECHO;
driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(driver, &sclp_ops);
+ tty_port_link_device(&sclp_port, driver, 0);
rc = tty_register_driver(driver);
if (rc) {
put_tty_driver(driver);
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index edfc0fd..7e60f3d 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -691,6 +691,7 @@
driver->init_termios = tty_std_termios;
driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(driver, &sclp_vt220_ops);
+ tty_port_link_device(&sclp_vt220_port, driver, 0);
rc = tty_register_driver(driver);
if (rc)
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index 1928f34..482ee02 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -842,17 +842,14 @@
};
/*
- * This routine is called whenever a 3270 tty is opened.
+ * This routine is called whenever a 3270 tty is opened first time.
*/
-static int
-tty3270_open(struct tty_struct *tty, struct file * filp)
+static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty)
{
struct raw3270_view *view;
struct tty3270 *tp;
int i, rc;
- if (tty->count > 1)
- return 0;
/* Check if the tty3270 is already there. */
view = raw3270_find_view(&tty3270_fn,
tty->index + RAW3270_FIRSTMINOR);
@@ -865,7 +862,7 @@
/* why to reassign? */
tty_port_tty_set(&tp->port, tty);
tp->inattr = TF_INPUT;
- return 0;
+ return tty_port_install(&tp->port, driver, tty);
}
if (tty3270_max_index < tty->index + 1)
tty3270_max_index = tty->index + 1;
@@ -895,7 +892,6 @@
tty_port_tty_set(&tp->port, tty);
tty->low_latency = 0;
- tty->driver_data = tp;
tty->winsize.ws_row = tp->view.rows - 2;
tty->winsize.ws_col = tp->view.cols;
@@ -915,6 +911,15 @@
kbd_ascebc(tp->kbd, tp->view.ascebc);
raw3270_activate_view(&tp->view);
+
+ rc = tty_port_install(&tp->port, driver, tty);
+ if (rc) {
+ raw3270_put_view(&tp->view);
+ return rc;
+ }
+
+ tty->driver_data = tp;
+
return 0;
}
@@ -932,10 +937,17 @@
if (tp) {
tty->driver_data = NULL;
tty_port_tty_set(&tp->port, NULL);
- raw3270_put_view(&tp->view);
}
}
+static void tty3270_cleanup(struct tty_struct *tty)
+{
+ struct tty3270 *tp = tty->driver_data;
+
+ if (tp)
+ raw3270_put_view(&tp->view);
+}
+
/*
* We always have room.
*/
@@ -1737,7 +1749,8 @@
#endif
static const struct tty_operations tty3270_ops = {
- .open = tty3270_open,
+ .install = tty3270_install,
+ .cleanup = tty3270_cleanup,
.close = tty3270_close,
.write = tty3270_write,
.put_char = tty3270_put_char,
@@ -1781,7 +1794,7 @@
driver->type = TTY_DRIVER_TYPE_SYSTEM;
driver->subtype = SYSTEM_TYPE_TTY;
driver->init_termios = tty_std_termios;
- driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_DYNAMIC_DEV;
+ driver->flags = TTY_DRIVER_RESET_TERMIOS;
tty_set_operations(driver, &tty3270_ops);
ret = tty_register_driver(driver);
if (ret) {
@@ -1800,6 +1813,7 @@
driver = tty3270_driver;
tty3270_driver = NULL;
tty_unregister_driver(driver);
+ put_tty_driver(driver);
tty3270_del_views();
}
diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c
index ea0aaa3..a9f4049 100644
--- a/drivers/spi/spi-bcm63xx.c
+++ b/drivers/spi/spi-bcm63xx.c
@@ -47,6 +47,8 @@
/* Platform data */
u32 speed_hz;
unsigned fifo_size;
+ unsigned int msg_type_shift;
+ unsigned int msg_ctl_width;
/* Data buffers */
const unsigned char *tx_ptr;
@@ -221,13 +223,20 @@
msg_ctl = (t->len << SPI_BYTE_CNT_SHIFT);
if (t->rx_buf && t->tx_buf)
- msg_ctl |= (SPI_FD_RW << SPI_MSG_TYPE_SHIFT);
+ msg_ctl |= (SPI_FD_RW << bs->msg_type_shift);
else if (t->rx_buf)
- msg_ctl |= (SPI_HD_R << SPI_MSG_TYPE_SHIFT);
+ msg_ctl |= (SPI_HD_R << bs->msg_type_shift);
else if (t->tx_buf)
- msg_ctl |= (SPI_HD_W << SPI_MSG_TYPE_SHIFT);
+ msg_ctl |= (SPI_HD_W << bs->msg_type_shift);
- bcm_spi_writew(bs, msg_ctl, SPI_MSG_CTL);
+ switch (bs->msg_ctl_width) {
+ case 8:
+ bcm_spi_writeb(bs, msg_ctl, SPI_MSG_CTL);
+ break;
+ case 16:
+ bcm_spi_writew(bs, msg_ctl, SPI_MSG_CTL);
+ break;
+ }
/* Issue the transfer */
cmd = SPI_CMD_START_IMMEDIATE;
@@ -406,9 +415,21 @@
master->transfer_one_message = bcm63xx_spi_transfer_one;
master->mode_bits = MODEBITS;
bs->speed_hz = pdata->speed_hz;
+ bs->msg_type_shift = pdata->msg_type_shift;
+ bs->msg_ctl_width = pdata->msg_ctl_width;
bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA));
bs->rx_io = (const u8 *)(bs->regs + bcm63xx_spireg(SPI_RX_DATA));
+ switch (bs->msg_ctl_width) {
+ case 8:
+ case 16:
+ break;
+ default:
+ dev_err(dev, "unsupported MSG_CTL width: %d\n",
+ bs->msg_ctl_width);
+ goto out_clk_disable;
+ }
+
/* Initialize hardware */
clk_enable(bs->clk);
bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS);
diff --git a/drivers/staging/ipack/devices/ipoctal.c b/drivers/staging/ipack/devices/ipoctal.c
index fd0e301..a68d981 100644
--- a/drivers/staging/ipack/devices/ipoctal.c
+++ b/drivers/staging/ipack/devices/ipoctal.c
@@ -502,7 +502,7 @@
ipoctal->pointer_read[i] = 0;
ipoctal->pointer_write[i] = 0;
ipoctal->nb_bytes[i] = 0;
- tty_register_device(tty, i, NULL);
+ tty_port_register_device(&ipoctal->tty_port[i], tty, i, NULL);
/*
* Enable again the RX. TX will be enabled when
@@ -617,7 +617,7 @@
struct ipoctal *ipoctal = tty->driver_data;
speed_t baud;
- cflag = tty->termios->c_cflag;
+ cflag = tty->termios.c_cflag;
/* Disable and reset everything before change the setup */
ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].u.w.cr,
@@ -643,7 +643,7 @@
default:
mr1 |= MR1_CHRL_8_BITS;
/* By default, select CS8 */
- tty->termios->c_cflag = (cflag & ~CSIZE) | CS8;
+ tty->termios.c_cflag = (cflag & ~CSIZE) | CS8;
break;
}
@@ -657,7 +657,7 @@
mr1 |= MR1_PARITY_OFF;
/* Mark or space parity is not supported */
- tty->termios->c_cflag &= ~CMSPAR;
+ tty->termios.c_cflag &= ~CMSPAR;
/* Set stop bits */
if (cflag & CSTOPB)
@@ -690,10 +690,10 @@
}
baud = tty_get_baud_rate(tty);
- tty_termios_encode_baud_rate(tty->termios, baud, baud);
+ tty_termios_encode_baud_rate(&tty->termios, baud, baud);
/* Set baud rate */
- switch (tty->termios->c_ospeed) {
+ switch (baud) {
case 75:
csr |= TX_CLK_75 | RX_CLK_75;
break;
@@ -734,7 +734,7 @@
default:
csr |= TX_CLK_38400 | RX_CLK_38400;
/* In case of default, we establish 38400 bps */
- tty_termios_encode_baud_rate(tty->termios, 38400, 38400);
+ tty_termios_encode_baud_rate(&tty->termios, 38400, 38400);
break;
}
diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c
index 8a362f7..c90de96 100644
--- a/drivers/staging/serqt_usb2/serqt_usb2.c
+++ b/drivers/staging/serqt_usb2/serqt_usb2.c
@@ -315,10 +315,8 @@
}
tty = tty_port_tty_get(&port->port);
- if (!tty) {
- dbg("%s - bad tty pointer - exiting", __func__);
+ if (!tty)
return;
- }
data = urb->transfer_buffer;
@@ -364,7 +362,7 @@
goto exit;
}
- if (tty && RxCount) {
+ if (RxCount) {
flag_data = 0;
for (i = 0; i < RxCount; ++i) {
/* Look ahead code here */
@@ -428,7 +426,7 @@
dbg("%s - failed resubmitting read urb, error %d",
__func__, result);
else {
- if (tty && RxCount) {
+ if (RxCount) {
tty_flip_buffer_push(tty);
tty_schedule_flip(tty);
}
@@ -897,8 +895,6 @@
* Put this here to make it responsive to stty and defaults set by
* the tty layer
*/
- /* FIXME: is this needed? */
- /* qt_set_termios(tty, port, NULL); */
/* Check to see if we've set up our endpoint info yet */
if (port0->open_ports == 1) {
@@ -1195,7 +1191,7 @@
struct usb_serial_port *port,
struct ktermios *old_termios)
{
- struct ktermios *termios = tty->termios;
+ struct ktermios *termios = &tty->termios;
unsigned char new_LCR = 0;
unsigned int cflag = termios->c_cflag;
unsigned int index;
@@ -1204,7 +1200,7 @@
index = tty->index - port->serial->minor;
- switch (cflag) {
+ switch (cflag & CSIZE) {
case CS5:
new_LCR |= SERIAL_5_DATA;
break;
@@ -1215,6 +1211,8 @@
new_LCR |= SERIAL_7_DATA;
break;
default:
+ termios->c_cflag &= ~CSIZE;
+ termios->c_cflag |= CS8;
case CS8:
new_LCR |= SERIAL_8_DATA;
break;
@@ -1301,7 +1299,7 @@
dbg(__FILE__ "BoxSetSW_FlowCtrl (diabling) failed\n");
}
- tty->termios->c_cflag &= ~CMSPAR;
+ termios->c_cflag &= ~CMSPAR;
/* FIXME: Error cases should be returning the actual bits changed only */
}
diff --git a/drivers/staging/speakup/serialio.h b/drivers/staging/speakup/serialio.h
index 614271f..55d68b5 100644
--- a/drivers/staging/speakup/serialio.h
+++ b/drivers/staging/speakup/serialio.h
@@ -1,8 +1,7 @@
#ifndef _SPEAKUP_SERIAL_H
#define _SPEAKUP_SERIAL_H
-#include <linux/serial.h> /* for rs_table, serial constants &
- serial_uart_config */
+#include <linux/serial.h> /* for rs_table, serial constants */
#include <linux/serial_reg.h> /* for more serial constants */
#ifndef __sparc__
#include <asm/serial.h>
diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c
index 6cc4358..42d0a25 100644
--- a/drivers/tty/amiserial.c
+++ b/drivers/tty/amiserial.c
@@ -420,7 +420,7 @@
tty_hangup(port->tty);
}
}
- if (port->flags & ASYNC_CTS_FLOW) {
+ if (tty_port_cts_enabled(port)) {
if (port->tty->hw_stopped) {
if (!(status & SER_CTS)) {
#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
@@ -646,7 +646,7 @@
custom.adkcon = AC_UARTBRK;
mb();
- if (tty->termios->c_cflag & HUPCL)
+ if (tty->termios.c_cflag & HUPCL)
info->MCR &= ~(SER_DTR|SER_RTS);
rtsdtr_ctrl(info->MCR);
@@ -670,7 +670,7 @@
int bits;
unsigned long flags;
- cflag = tty->termios->c_cflag;
+ cflag = tty->termios.c_cflag;
/* Byte size is always 8 bits plus parity bit if requested */
@@ -707,8 +707,8 @@
/* If the quotient is zero refuse the change */
if (!quot && old_termios) {
/* FIXME: Will need updating for new tty in the end */
- tty->termios->c_cflag &= ~CBAUD;
- tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
+ tty->termios.c_cflag &= ~CBAUD;
+ tty->termios.c_cflag |= (old_termios->c_cflag & CBAUD);
baud = tty_get_baud_rate(tty);
if (!baud)
baud = 9600;
@@ -984,7 +984,7 @@
if (I_IXOFF(tty))
rs_send_xchar(tty, STOP_CHAR(tty));
- if (tty->termios->c_cflag & CRTSCTS)
+ if (tty->termios.c_cflag & CRTSCTS)
info->MCR &= ~SER_RTS;
local_irq_save(flags);
@@ -1012,7 +1012,7 @@
else
rs_send_xchar(tty, START_CHAR(tty));
}
- if (tty->termios->c_cflag & CRTSCTS)
+ if (tty->termios.c_cflag & CRTSCTS)
info->MCR |= SER_RTS;
local_irq_save(flags);
rtsdtr_ctrl(info->MCR);
@@ -1033,7 +1033,7 @@
if (!retinfo)
return -EFAULT;
memset(&tmp, 0, sizeof(tmp));
- tty_lock();
+ tty_lock(tty);
tmp.line = tty->index;
tmp.port = state->port;
tmp.flags = state->tport.flags;
@@ -1042,7 +1042,7 @@
tmp.close_delay = state->tport.close_delay;
tmp.closing_wait = state->tport.closing_wait;
tmp.custom_divisor = state->custom_divisor;
- tty_unlock();
+ tty_unlock(tty);
if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
return -EFAULT;
return 0;
@@ -1059,12 +1059,12 @@
if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
return -EFAULT;
- tty_lock();
+ tty_lock(tty);
change_spd = ((new_serial.flags ^ port->flags) & ASYNC_SPD_MASK) ||
new_serial.custom_divisor != state->custom_divisor;
if (new_serial.irq || new_serial.port != state->port ||
new_serial.xmit_fifo_size != state->xmit_fifo_size) {
- tty_unlock();
+ tty_unlock(tty);
return -EINVAL;
}
@@ -1074,7 +1074,7 @@
(new_serial.xmit_fifo_size != state->xmit_fifo_size) ||
((new_serial.flags & ~ASYNC_USR_MASK) !=
(port->flags & ~ASYNC_USR_MASK))) {
- tty_unlock();
+ tty_unlock(tty);
return -EPERM;
}
port->flags = ((port->flags & ~ASYNC_USR_MASK) |
@@ -1084,7 +1084,7 @@
}
if (new_serial.baud_base < 9600) {
- tty_unlock();
+ tty_unlock(tty);
return -EINVAL;
}
@@ -1116,7 +1116,7 @@
}
} else
retval = startup(tty, state);
- tty_unlock();
+ tty_unlock(tty);
return retval;
}
@@ -1330,7 +1330,7 @@
{
struct serial_state *info = tty->driver_data;
unsigned long flags;
- unsigned int cflag = tty->termios->c_cflag;
+ unsigned int cflag = tty->termios.c_cflag;
change_speed(tty, info, old_termios);
@@ -1347,7 +1347,7 @@
if (!(old_termios->c_cflag & CBAUD) &&
(cflag & CBAUD)) {
info->MCR |= SER_DTR;
- if (!(tty->termios->c_cflag & CRTSCTS) ||
+ if (!(tty->termios.c_cflag & CRTSCTS) ||
!test_bit(TTY_THROTTLED, &tty->flags)) {
info->MCR |= SER_RTS;
}
@@ -1358,7 +1358,7 @@
/* Handle turning off CRTSCTS */
if ((old_termios->c_cflag & CRTSCTS) &&
- !(tty->termios->c_cflag & CRTSCTS)) {
+ !(tty->termios.c_cflag & CRTSCTS)) {
tty->hw_stopped = 0;
rs_start(tty);
}
@@ -1371,7 +1371,7 @@
* or not. Hence, this may change.....
*/
if (!(old_termios->c_cflag & CLOCAL) &&
- (tty->termios->c_cflag & CLOCAL))
+ (tty->termios.c_cflag & CLOCAL))
wake_up_interruptible(&info->open_wait);
#endif
}
@@ -1710,10 +1710,6 @@
serial_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(serial_driver, &serial_ops);
- error = tty_register_driver(serial_driver);
- if (error)
- goto fail_put_tty_driver;
-
state = rs_table;
state->port = (int)&custom.serdatr; /* Just to give it a value */
state->custom_divisor = 0;
@@ -1724,6 +1720,11 @@
state->icount.overrun = state->icount.brk = 0;
tty_port_init(&state->tport);
state->tport.ops = &amiga_port_ops;
+ tty_port_link_device(&state->tport, serial_driver, 0);
+
+ error = tty_register_driver(serial_driver);
+ if (error)
+ goto fail_put_tty_driver;
printk(KERN_INFO "ttyS0 is the amiga builtin serial port\n");
diff --git a/drivers/tty/bfin_jtag_comm.c b/drivers/tty/bfin_jtag_comm.c
index 61fc74f..02b7d3a 100644
--- a/drivers/tty/bfin_jtag_comm.c
+++ b/drivers/tty/bfin_jtag_comm.c
@@ -263,6 +263,7 @@
bfin_jc_driver->subtype = SERIAL_TYPE_NORMAL;
bfin_jc_driver->init_termios = tty_std_termios;
tty_set_operations(bfin_jc_driver, &bfin_jc_ops);
+ tty_port_link_device(&port, bfin_jc_driver, 0);
ret = tty_register_driver(bfin_jc_driver);
if (ret)
diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c
index e61cabd..0a6a0bc 100644
--- a/drivers/tty/cyclades.c
+++ b/drivers/tty/cyclades.c
@@ -727,7 +727,7 @@
else
tty_hangup(tty);
}
- if ((mdm_change & CyCTS) && (info->port.flags & ASYNC_CTS_FLOW)) {
+ if ((mdm_change & CyCTS) && tty_port_cts_enabled(&info->port)) {
if (tty->hw_stopped) {
if (mdm_status & CyCTS) {
/* cy_start isn't used
@@ -1459,7 +1459,7 @@
info->port.xmit_buf = NULL;
free_page((unsigned long)temp);
}
- if (tty->termios->c_cflag & HUPCL)
+ if (tty->termios.c_cflag & HUPCL)
cyy_change_rts_dtr(info, 0, TIOCM_RTS | TIOCM_DTR);
cyy_issue_cmd(info, CyCHAN_CTL | CyDIS_RCVR);
@@ -1488,7 +1488,7 @@
free_page((unsigned long)temp);
}
- if (tty->termios->c_cflag & HUPCL)
+ if (tty->termios.c_cflag & HUPCL)
tty_port_lower_dtr_rts(&info->port);
set_bit(TTY_IO_ERROR, &tty->flags);
@@ -1599,7 +1599,7 @@
* If the port is the middle of closing, bail out now
*/
if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) {
- wait_event_interruptible_tty(info->port.close_wait,
+ wait_event_interruptible_tty(tty, info->port.close_wait,
!(info->port.flags & ASYNC_CLOSING));
return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
}
@@ -1999,14 +1999,11 @@
int baud, baud_rate = 0;
int i;
- if (!tty->termios) /* XXX can this happen at all? */
- return;
-
if (info->line == -1)
return;
- cflag = tty->termios->c_cflag;
- iflag = tty->termios->c_iflag;
+ cflag = tty->termios.c_cflag;
+ iflag = tty->termios.c_iflag;
/*
* Set up the tty->alt_speed kludge
@@ -2825,7 +2822,7 @@
cy_set_line_char(info, tty);
if ((old_termios->c_cflag & CRTSCTS) &&
- !(tty->termios->c_cflag & CRTSCTS)) {
+ !(tty->termios.c_cflag & CRTSCTS)) {
tty->hw_stopped = 0;
cy_start(tty);
}
@@ -2837,7 +2834,7 @@
* or not. Hence, this may change.....
*/
if (!(old_termios->c_cflag & CLOCAL) &&
- (tty->termios->c_cflag & CLOCAL))
+ (tty->termios.c_cflag & CLOCAL))
wake_up_interruptible(&info->port.open_wait);
#endif
} /* cy_set_termios */
@@ -2899,7 +2896,7 @@
info->throttle = 1;
}
- if (tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios.c_cflag & CRTSCTS) {
if (!cy_is_Z(card)) {
spin_lock_irqsave(&card->card_lock, flags);
cyy_change_rts_dtr(info, 0, TIOCM_RTS);
@@ -2938,7 +2935,7 @@
cy_send_xchar(tty, START_CHAR(tty));
}
- if (tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios.c_cflag & CRTSCTS) {
card = info->card;
if (!cy_is_Z(card)) {
spin_lock_irqsave(&card->card_lock, flags);
@@ -3289,9 +3286,10 @@
static int __init cy_detect_isa(void)
{
#ifdef CONFIG_ISA
+ struct cyclades_card *card;
unsigned short cy_isa_irq, nboard;
void __iomem *cy_isa_address;
- unsigned short i, j, cy_isa_nchan;
+ unsigned short i, j, k, cy_isa_nchan;
int isparam = 0;
nboard = 0;
@@ -3349,7 +3347,8 @@
}
/* fill the next cy_card structure available */
for (j = 0; j < NR_CARDS; j++) {
- if (cy_card[j].base_addr == NULL)
+ card = &cy_card[j];
+ if (card->base_addr == NULL)
break;
}
if (j == NR_CARDS) { /* no more cy_cards available */
@@ -3363,7 +3362,7 @@
/* allocate IRQ */
if (request_irq(cy_isa_irq, cyy_interrupt,
- 0, "Cyclom-Y", &cy_card[j])) {
+ 0, "Cyclom-Y", card)) {
printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but "
"could not allocate IRQ#%d.\n",
(unsigned long)cy_isa_address, cy_isa_irq);
@@ -3372,16 +3371,16 @@
}
/* set cy_card */
- cy_card[j].base_addr = cy_isa_address;
- cy_card[j].ctl_addr.p9050 = 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 / CyPORTS_PER_CHIP;
- cy_card[j].nports = cy_isa_nchan;
- if (cy_init_card(&cy_card[j])) {
- cy_card[j].base_addr = NULL;
- free_irq(cy_isa_irq, &cy_card[j]);
+ card->base_addr = cy_isa_address;
+ card->ctl_addr.p9050 = NULL;
+ card->irq = (int)cy_isa_irq;
+ card->bus_index = 0;
+ card->first_line = cy_next_channel;
+ card->num_chips = cy_isa_nchan / CyPORTS_PER_CHIP;
+ card->nports = cy_isa_nchan;
+ if (cy_init_card(card)) {
+ card->base_addr = NULL;
+ free_irq(cy_isa_irq, card);
iounmap(cy_isa_address);
continue;
}
@@ -3393,9 +3392,10 @@
(unsigned long)(cy_isa_address + (CyISA_Ywin - 1)),
cy_isa_irq, cy_isa_nchan, cy_next_channel);
- for (j = cy_next_channel;
- j < cy_next_channel + cy_isa_nchan; j++)
- tty_register_device(cy_serial_driver, j, NULL);
+ for (k = 0, j = cy_next_channel;
+ j < cy_next_channel + cy_isa_nchan; j++, k++)
+ tty_port_register_device(&card->ports[k].port,
+ cy_serial_driver, j, NULL);
cy_next_channel += cy_isa_nchan;
}
return nboard;
@@ -3695,10 +3695,11 @@
static int __devinit cy_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
+ struct cyclades_card *card;
void __iomem *addr0 = NULL, *addr2 = NULL;
char *card_name = NULL;
u32 uninitialized_var(mailbox);
- unsigned int device_id, nchan = 0, card_no, i;
+ unsigned int device_id, nchan = 0, card_no, i, j;
unsigned char plx_ver;
int retval, irq;
@@ -3829,7 +3830,8 @@
}
/* fill the next cy_card structure available */
for (card_no = 0; card_no < NR_CARDS; card_no++) {
- if (cy_card[card_no].base_addr == NULL)
+ card = &cy_card[card_no];
+ if (card->base_addr == NULL)
break;
}
if (card_no == NR_CARDS) { /* no more cy_cards available */
@@ -3843,27 +3845,26 @@
device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
/* allocate IRQ */
retval = request_irq(irq, cyy_interrupt,
- IRQF_SHARED, "Cyclom-Y", &cy_card[card_no]);
+ IRQF_SHARED, "Cyclom-Y", card);
if (retval) {
dev_err(&pdev->dev, "could not allocate IRQ\n");
goto err_unmap;
}
- cy_card[card_no].num_chips = nchan / CyPORTS_PER_CHIP;
+ card->num_chips = nchan / CyPORTS_PER_CHIP;
} else {
struct FIRM_ID __iomem *firm_id = addr2 + ID_ADDRESS;
struct ZFW_CTRL __iomem *zfw_ctrl;
zfw_ctrl = addr2 + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
- cy_card[card_no].hw_ver = mailbox;
- cy_card[card_no].num_chips = (unsigned int)-1;
- cy_card[card_no].board_ctrl = &zfw_ctrl->board_ctrl;
+ card->hw_ver = mailbox;
+ card->num_chips = (unsigned int)-1;
+ card->board_ctrl = &zfw_ctrl->board_ctrl;
#ifdef CONFIG_CYZ_INTR
/* allocate IRQ only if board has an IRQ */
if (irq != 0 && irq != 255) {
retval = request_irq(irq, cyz_interrupt,
- IRQF_SHARED, "Cyclades-Z",
- &cy_card[card_no]);
+ IRQF_SHARED, "Cyclades-Z", card);
if (retval) {
dev_err(&pdev->dev, "could not allocate IRQ\n");
goto err_unmap;
@@ -3873,17 +3874,17 @@
}
/* set cy_card */
- cy_card[card_no].base_addr = addr2;
- cy_card[card_no].ctl_addr.p9050 = addr0;
- cy_card[card_no].irq = irq;
- cy_card[card_no].bus_index = 1;
- cy_card[card_no].first_line = cy_next_channel;
- cy_card[card_no].nports = nchan;
- retval = cy_init_card(&cy_card[card_no]);
+ card->base_addr = addr2;
+ card->ctl_addr.p9050 = addr0;
+ card->irq = irq;
+ card->bus_index = 1;
+ card->first_line = cy_next_channel;
+ card->nports = nchan;
+ retval = cy_init_card(card);
if (retval)
goto err_null;
- pci_set_drvdata(pdev, &cy_card[card_no]);
+ pci_set_drvdata(pdev, card);
if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
@@ -3909,14 +3910,15 @@
dev_info(&pdev->dev, "%s/PCI #%d found: %d channels starting from "
"port %d.\n", card_name, card_no + 1, nchan, cy_next_channel);
- for (i = cy_next_channel; i < cy_next_channel + nchan; i++)
- tty_register_device(cy_serial_driver, i, &pdev->dev);
+ for (j = 0, i = cy_next_channel; i < cy_next_channel + nchan; i++, j++)
+ tty_port_register_device(&card->ports[j].port,
+ cy_serial_driver, i, &pdev->dev);
cy_next_channel += nchan;
return 0;
err_null:
- cy_card[card_no].base_addr = NULL;
- free_irq(irq, &cy_card[card_no]);
+ card->base_addr = NULL;
+ free_irq(irq, card);
err_unmap:
iounmap(addr0);
if (addr2)
diff --git a/drivers/tty/ehv_bytechan.c b/drivers/tty/ehv_bytechan.c
index 4813684..4ab936b 100644
--- a/drivers/tty/ehv_bytechan.c
+++ b/drivers/tty/ehv_bytechan.c
@@ -738,16 +738,17 @@
goto error;
}
- bc->dev = tty_register_device(ehv_bc_driver, i, &pdev->dev);
+ tty_port_init(&bc->port);
+ bc->port.ops = &ehv_bc_tty_port_ops;
+
+ bc->dev = tty_port_register_device(&bc->port, ehv_bc_driver, i,
+ &pdev->dev);
if (IS_ERR(bc->dev)) {
ret = PTR_ERR(bc->dev);
dev_err(&pdev->dev, "could not register tty (ret=%i)\n", ret);
goto error;
}
- tty_port_init(&bc->port);
- bc->port.ops = &ehv_bc_tty_port_ops;
-
dev_set_drvdata(&pdev->dev, bc);
dev_info(&pdev->dev, "registered /dev/%s%u for byte channel %u\n",
diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
index 2d691eb..7f80f15 100644
--- a/drivers/tty/hvc/hvc_console.c
+++ b/drivers/tty/hvc/hvc_console.c
@@ -299,20 +299,33 @@
hvc_kick();
}
+static int hvc_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+ struct hvc_struct *hp;
+ int rc;
+
+ /* Auto increments kref reference if found. */
+ if (!(hp = hvc_get_by_index(tty->index)))
+ return -ENODEV;
+
+ tty->driver_data = hp;
+
+ rc = tty_port_install(&hp->port, driver, tty);
+ if (rc)
+ tty_port_put(&hp->port);
+ return rc;
+}
+
/*
* The TTY interface won't be used until after the vio layer has exposed the vty
* adapter to the kernel.
*/
static int hvc_open(struct tty_struct *tty, struct file * filp)
{
- struct hvc_struct *hp;
+ struct hvc_struct *hp = tty->driver_data;
unsigned long flags;
int rc = 0;
- /* Auto increments kref reference if found. */
- if (!(hp = hvc_get_by_index(tty->index)))
- return -ENODEV;
-
spin_lock_irqsave(&hp->port.lock, flags);
/* Check and then increment for fast path open. */
if (hp->port.count++ > 0) {
@@ -322,7 +335,6 @@
} /* else count == 0 */
spin_unlock_irqrestore(&hp->port.lock, flags);
- tty->driver_data = hp;
tty_port_tty_set(&hp->port, tty);
if (hp->ops->notifier_add)
@@ -389,6 +401,11 @@
hp->vtermno, hp->port.count);
spin_unlock_irqrestore(&hp->port.lock, flags);
}
+}
+
+static void hvc_cleanup(struct tty_struct *tty)
+{
+ struct hvc_struct *hp = tty->driver_data;
tty_port_put(&hp->port);
}
@@ -792,8 +809,10 @@
#endif
static const struct tty_operations hvc_ops = {
+ .install = hvc_install,
.open = hvc_open,
.close = hvc_close,
+ .cleanup = hvc_cleanup,
.write = hvc_write,
.hangup = hvc_hangup,
.unthrottle = hvc_unthrottle,
diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c
index d56788c..cab5c7a 100644
--- a/drivers/tty/hvc/hvcs.c
+++ b/drivers/tty/hvc/hvcs.c
@@ -1102,27 +1102,20 @@
return NULL;
}
-/*
- * This is invoked via the tty_open interface when a user app connects to the
- * /dev node.
- */
-static int hvcs_open(struct tty_struct *tty, struct file *filp)
+static int hvcs_install(struct tty_driver *driver, struct tty_struct *tty)
{
struct hvcs_struct *hvcsd;
- int rc, retval = 0;
- unsigned long flags;
- unsigned int irq;
struct vio_dev *vdev;
- unsigned long unit_address;
-
- if (tty->driver_data)
- goto fast_open;
+ unsigned long unit_address, flags;
+ unsigned int irq;
+ int retval;
/*
* Is there a vty-server that shares the same index?
* This function increments the kref index.
*/
- if (!(hvcsd = hvcs_get_by_index(tty->index))) {
+ hvcsd = hvcs_get_by_index(tty->index);
+ if (!hvcsd) {
printk(KERN_WARNING "HVCS: open failed, no device associated"
" with tty->index %d.\n", tty->index);
return -ENODEV;
@@ -1130,11 +1123,16 @@
spin_lock_irqsave(&hvcsd->lock, flags);
- if (hvcsd->connected == 0)
- if ((retval = hvcs_partner_connect(hvcsd)))
- goto error_release;
+ if (hvcsd->connected == 0) {
+ retval = hvcs_partner_connect(hvcsd);
+ if (retval) {
+ spin_unlock_irqrestore(&hvcsd->lock, flags);
+ printk(KERN_WARNING "HVCS: partner connect failed.\n");
+ goto err_put;
+ }
+ }
- hvcsd->port.count = 1;
+ hvcsd->port.count = 0;
hvcsd->port.tty = tty;
tty->driver_data = hvcsd;
@@ -1155,37 +1153,48 @@
* This must be done outside of the spinlock because it requests irqs
* and will grab the spinlock and free the connection if it fails.
*/
- if (((rc = hvcs_enable_device(hvcsd, unit_address, irq, vdev)))) {
- tty_port_put(&hvcsd->port);
+ retval = hvcs_enable_device(hvcsd, unit_address, irq, vdev);
+ if (retval) {
printk(KERN_WARNING "HVCS: enable device failed.\n");
- return rc;
+ goto err_put;
}
- goto open_success;
+ retval = tty_port_install(&hvcsd->port, driver, tty);
+ if (retval)
+ goto err_irq;
-fast_open:
- hvcsd = tty->driver_data;
+ return 0;
+err_irq:
+ spin_lock_irqsave(&hvcsd->lock, flags);
+ vio_disable_interrupts(hvcsd->vdev);
+ spin_unlock_irqrestore(&hvcsd->lock, flags);
+ free_irq(irq, hvcsd);
+err_put:
+ tty_port_put(&hvcsd->port);
+
+ return retval;
+}
+
+/*
+ * This is invoked via the tty_open interface when a user app connects to the
+ * /dev node.
+ */
+static int hvcs_open(struct tty_struct *tty, struct file *filp)
+{
+ struct hvcs_struct *hvcsd = tty->driver_data;
+ unsigned long flags;
spin_lock_irqsave(&hvcsd->lock, flags);
- tty_port_get(&hvcsd->port);
hvcsd->port.count++;
hvcsd->todo_mask |= HVCS_SCHED_READ;
spin_unlock_irqrestore(&hvcsd->lock, flags);
-open_success:
hvcs_kick();
printk(KERN_INFO "HVCS: vty-server@%X connection opened.\n",
hvcsd->vdev->unit_address );
return 0;
-
-error_release:
- spin_unlock_irqrestore(&hvcsd->lock, flags);
- tty_port_put(&hvcsd->port);
-
- printk(KERN_WARNING "HVCS: partner connect failed.\n");
- return retval;
}
static void hvcs_close(struct tty_struct *tty, struct file *filp)
@@ -1236,7 +1245,6 @@
tty->driver_data = NULL;
free_irq(irq, hvcsd);
- tty_port_put(&hvcsd->port);
return;
} else if (hvcsd->port.count < 0) {
printk(KERN_ERR "HVCS: vty-server@%X open_count: %d"
@@ -1245,6 +1253,12 @@
}
spin_unlock_irqrestore(&hvcsd->lock, flags);
+}
+
+static void hvcs_cleanup(struct tty_struct * tty)
+{
+ struct hvcs_struct *hvcsd = tty->driver_data;
+
tty_port_put(&hvcsd->port);
}
@@ -1431,8 +1445,10 @@
}
static const struct tty_operations hvcs_ops = {
+ .install = hvcs_install,
.open = hvcs_open,
.close = hvcs_close,
+ .cleanup = hvcs_cleanup,
.hangup = hvcs_hangup,
.write = hvcs_write,
.write_room = hvcs_write_room,
diff --git a/drivers/tty/hvc/hvsi.c b/drivers/tty/hvc/hvsi.c
index 6f5bc49..0083bc1 100644
--- a/drivers/tty/hvc/hvsi.c
+++ b/drivers/tty/hvc/hvsi.c
@@ -1080,6 +1080,8 @@
struct hvsi_struct *hp = &hvsi_ports[i];
int ret = 1;
+ tty_port_link_device(&hp->port, hvsi_driver, i);
+
ret = request_irq(hp->virq, hvsi_interrupt, 0, "hvsi", hp);
if (ret)
printk(KERN_ERR "HVSI: couldn't reserve irq 0x%x (error %i)\n",
diff --git a/drivers/tty/hvc/hvsi_lib.c b/drivers/tty/hvc/hvsi_lib.c
index 59c135d..3396eb9 100644
--- a/drivers/tty/hvc/hvsi_lib.c
+++ b/drivers/tty/hvc/hvsi_lib.c
@@ -400,7 +400,7 @@
spin_unlock_irqrestore(&hp->lock, flags);
/* Clear our own DTR */
- if (!pv->tty || (pv->tty->termios->c_cflag & HUPCL))
+ if (!pv->tty || (pv->tty->termios.c_cflag & HUPCL))
hvsilib_write_mctrl(pv, 0);
/* Tear down the connection */
diff --git a/drivers/tty/ipwireless/tty.c b/drivers/tty/ipwireless/tty.c
index f8b5fa0..160f0ad 100644
--- a/drivers/tty/ipwireless/tty.c
+++ b/drivers/tty/ipwireless/tty.c
@@ -476,7 +476,7 @@
mutex_init(&ttys[j]->ipw_tty_mutex);
tty_port_init(&ttys[j]->port);
- tty_register_device(ipw_tty_driver, j, NULL);
+ tty_port_register_device(&ttys[j]->port, ipw_tty_driver, j, NULL);
ipwireless_associate_network_tty(network, channel_idx, ttys[j]);
if (secondary_channel_idx != -1)
diff --git a/drivers/tty/isicom.c b/drivers/tty/isicom.c
index e1235ac..d7492e1 100644
--- a/drivers/tty/isicom.c
+++ b/drivers/tty/isicom.c
@@ -600,7 +600,7 @@
port->status &= ~ISI_DCD;
}
- if (port->port.flags & ASYNC_CTS_FLOW) {
+ if (tty_port_cts_enabled(&port->port)) {
if (tty->hw_stopped) {
if (header & ISI_CTS) {
port->port.tty->hw_stopped = 0;
@@ -702,7 +702,7 @@
/* 1,2,3,4 => 57.6, 115.2, 230, 460 kbps resp. */
if (baud < 1 || baud > 4)
- tty->termios->c_cflag &= ~CBAUDEX;
+ tty->termios.c_cflag &= ~CBAUDEX;
else
baud += 15;
}
@@ -1196,8 +1196,8 @@
if (isicom_paranoia_check(port, tty->name, "isicom_set_termios"))
return;
- if (tty->termios->c_cflag == old_termios->c_cflag &&
- tty->termios->c_iflag == old_termios->c_iflag)
+ if (tty->termios.c_cflag == old_termios->c_cflag &&
+ tty->termios.c_iflag == old_termios->c_iflag)
return;
spin_lock_irqsave(&port->card->card_lock, flags);
@@ -1205,7 +1205,7 @@
spin_unlock_irqrestore(&port->card->card_lock, flags);
if ((old_termios->c_cflag & CRTSCTS) &&
- !(tty->termios->c_cflag & CRTSCTS)) {
+ !(tty->termios.c_cflag & CRTSCTS)) {
tty->hw_stopped = 0;
isicom_start(tty);
}
@@ -1611,7 +1611,8 @@
goto errunri;
for (index = 0; index < board->port_count; index++)
- tty_register_device(isicom_normal, board->index * 16 + index,
+ tty_port_register_device(&board->ports[index].port,
+ isicom_normal, board->index * 16 + index,
&pdev->dev);
return 0;
diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c
index 324467d..56e616b 100644
--- a/drivers/tty/moxa.c
+++ b/drivers/tty/moxa.c
@@ -169,6 +169,7 @@
static unsigned long baseaddr[MAX_BOARDS];
static unsigned int type[MAX_BOARDS];
static unsigned int numports[MAX_BOARDS];
+static struct tty_port moxa_service_port;
MODULE_AUTHOR("William Chen");
MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver");
@@ -367,10 +368,10 @@
tmp.dcd = 1;
ttyp = tty_port_tty_get(&p->port);
- if (!ttyp || !ttyp->termios)
+ if (!ttyp)
tmp.cflag = p->cflag;
else
- tmp.cflag = ttyp->termios->c_cflag;
+ tmp.cflag = ttyp->termios.c_cflag;
tty_kref_put(ttyp);
copy:
if (copy_to_user(argm, &tmp, sizeof(tmp)))
@@ -834,7 +835,7 @@
const struct firmware *fw;
const char *file;
struct moxa_port *p;
- unsigned int i;
+ unsigned int i, first_idx;
int ret;
brd->ports = kcalloc(MAX_PORTS_PER_BOARD, sizeof(*brd->ports),
@@ -887,6 +888,11 @@
mod_timer(&moxaTimer, jiffies + HZ / 50);
spin_unlock_bh(&moxa_lock);
+ first_idx = (brd - moxa_boards) * MAX_PORTS_PER_BOARD;
+ for (i = 0; i < brd->numPorts; i++)
+ tty_port_register_device(&brd->ports[i].port, moxaDriver,
+ first_idx + i, dev);
+
return 0;
err_free:
kfree(brd->ports);
@@ -896,7 +902,7 @@
static void moxa_board_deinit(struct moxa_board_conf *brd)
{
- unsigned int a, opened;
+ unsigned int a, opened, first_idx;
mutex_lock(&moxa_openlock);
spin_lock_bh(&moxa_lock);
@@ -925,6 +931,10 @@
mutex_lock(&moxa_openlock);
}
+ first_idx = (brd - moxa_boards) * MAX_PORTS_PER_BOARD;
+ for (a = 0; a < brd->numPorts; a++)
+ tty_unregister_device(moxaDriver, first_idx + a);
+
iounmap(brd->basemem);
brd->basemem = NULL;
kfree(brd->ports);
@@ -967,6 +977,7 @@
board->basemem = ioremap_nocache(pci_resource_start(pdev, 2), 0x4000);
if (board->basemem == NULL) {
dev_err(&pdev->dev, "can't remap io space 2\n");
+ retval = -ENOMEM;
goto err_reg;
}
@@ -1031,9 +1042,14 @@
printk(KERN_INFO "MOXA Intellio family driver version %s\n",
MOXA_VERSION);
- moxaDriver = alloc_tty_driver(MAX_PORTS + 1);
- if (!moxaDriver)
- return -ENOMEM;
+
+ tty_port_init(&moxa_service_port);
+
+ moxaDriver = tty_alloc_driver(MAX_PORTS + 1,
+ TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_DYNAMIC_DEV);
+ if (IS_ERR(moxaDriver))
+ return PTR_ERR(moxaDriver);
moxaDriver->name = "ttyMX";
moxaDriver->major = ttymajor;
@@ -1044,8 +1060,9 @@
moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
moxaDriver->init_termios.c_ispeed = 9600;
moxaDriver->init_termios.c_ospeed = 9600;
- moxaDriver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(moxaDriver, &moxa_ops);
+ /* Having one more port only for ioctls is ugly */
+ tty_port_link_device(&moxa_service_port, moxaDriver, MAX_PORTS);
if (tty_register_driver(moxaDriver)) {
printk(KERN_ERR "can't register MOXA Smartio tty driver!\n");
@@ -1178,7 +1195,7 @@
mutex_lock(&ch->port.mutex);
if (!(ch->port.flags & ASYNC_INITIALIZED)) {
ch->statusflags = 0;
- moxa_set_tty_param(tty, tty->termios);
+ moxa_set_tty_param(tty, &tty->termios);
MoxaPortLineCtrl(ch, 1, 1);
MoxaPortEnable(ch);
MoxaSetFifo(ch, ch->type == PORT_16550A);
@@ -1193,7 +1210,7 @@
static void moxa_close(struct tty_struct *tty, struct file *filp)
{
struct moxa_port *ch = tty->driver_data;
- ch->cflag = tty->termios->c_cflag;
+ ch->cflag = tty->termios.c_cflag;
tty_port_close(&ch->port, tty, filp);
}
@@ -1464,7 +1481,7 @@
static void moxa_set_tty_param(struct tty_struct *tty, struct ktermios *old_termios)
{
- register struct ktermios *ts = tty->termios;
+ register struct ktermios *ts = &tty->termios;
struct moxa_port *ch = tty->driver_data;
int rts, cts, txflow, rxflow, xany, baud;
diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c
index 90cc680..cfda47d 100644
--- a/drivers/tty/mxser.c
+++ b/drivers/tty/mxser.c
@@ -643,7 +643,7 @@
int ret = 0;
unsigned char status;
- cflag = tty->termios->c_cflag;
+ cflag = tty->termios.c_cflag;
if (!info->ioaddr)
return ret;
@@ -830,7 +830,7 @@
wake_up_interruptible(&port->port.open_wait);
}
- if (port->port.flags & ASYNC_CTS_FLOW) {
+ if (tty_port_cts_enabled(&port->port)) {
if (tty->hw_stopped) {
if (status & UART_MSR_CTS) {
tty->hw_stopped = 0;
@@ -1520,10 +1520,10 @@
tty = tty_port_tty_get(port);
- if (!tty || !tty->termios)
+ if (!tty)
ms.cflag = ip->normal_termios.c_cflag;
else
- ms.cflag = tty->termios->c_cflag;
+ ms.cflag = tty->termios.c_cflag;
tty_kref_put(tty);
spin_lock_irq(&ip->slock);
status = inb(ip->ioaddr + UART_MSR);
@@ -1589,13 +1589,13 @@
tty = tty_port_tty_get(&ip->port);
- if (!tty || !tty->termios) {
+ if (!tty) {
cflag = ip->normal_termios.c_cflag;
iflag = ip->normal_termios.c_iflag;
me->baudrate[p] = tty_termios_baud_rate(&ip->normal_termios);
} else {
- cflag = tty->termios->c_cflag;
- iflag = tty->termios->c_iflag;
+ cflag = tty->termios.c_cflag;
+ iflag = tty->termios.c_iflag;
me->baudrate[p] = tty_get_baud_rate(tty);
}
tty_kref_put(tty);
@@ -1853,7 +1853,7 @@
}
}
- if (tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios.c_cflag & CRTSCTS) {
info->MCR &= ~UART_MCR_RTS;
outb(info->MCR, info->ioaddr + UART_MCR);
}
@@ -1890,7 +1890,7 @@
}
}
- if (tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios.c_cflag & CRTSCTS) {
info->MCR |= UART_MCR_RTS;
outb(info->MCR, info->ioaddr + UART_MCR);
}
@@ -1939,14 +1939,14 @@
spin_unlock_irqrestore(&info->slock, flags);
if ((old_termios->c_cflag & CRTSCTS) &&
- !(tty->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->termios.c_iflag & IXON)) {
tty->stopped = 0;
if (info->board->chip_flag) {
@@ -2337,11 +2337,36 @@
* The MOXA Smartio/Industio serial driver boot-time initialization code!
*/
+static bool allow_overlapping_vector;
+module_param(allow_overlapping_vector, bool, S_IRUGO);
+MODULE_PARM_DESC(allow_overlapping_vector, "whether we allow ISA cards to be configured such that vector overlabs IO ports (default=no)");
+
+static bool mxser_overlapping_vector(struct mxser_board *brd)
+{
+ return allow_overlapping_vector &&
+ brd->vector >= brd->ports[0].ioaddr &&
+ brd->vector < brd->ports[0].ioaddr + 8 * brd->info->nports;
+}
+
+static int mxser_request_vector(struct mxser_board *brd)
+{
+ if (mxser_overlapping_vector(brd))
+ return 0;
+ return request_region(brd->vector, 1, "mxser(vector)") ? 0 : -EIO;
+}
+
+static void mxser_release_vector(struct mxser_board *brd)
+{
+ if (mxser_overlapping_vector(brd))
+ return;
+ release_region(brd->vector, 1);
+}
+
static void mxser_release_ISA_res(struct mxser_board *brd)
{
free_irq(brd->irq, brd);
release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
- release_region(brd->vector, 1);
+ mxser_release_vector(brd);
}
static int __devinit mxser_initbrd(struct mxser_board *brd,
@@ -2396,7 +2421,7 @@
static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd)
{
- int id, i, bits;
+ int id, i, bits, ret;
unsigned short regs[16], irq;
unsigned char scratch, scratch2;
@@ -2492,13 +2517,15 @@
8 * brd->info->nports - 1);
return -EIO;
}
- if (!request_region(brd->vector, 1, "mxser(vector)")) {
+
+ ret = mxser_request_vector(brd);
+ if (ret) {
release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
printk(KERN_ERR "mxser: can't request interrupt vector region: "
"0x%.8lx-0x%.8lx\n",
brd->ports[0].ioaddr, brd->ports[0].ioaddr +
8 * brd->info->nports - 1);
- return -EIO;
+ return ret;
}
return brd->info->nports;
@@ -2598,7 +2625,8 @@
goto err_rel3;
for (i = 0; i < brd->info->nports; i++)
- tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev);
+ tty_port_register_device(&brd->ports[i].port, mxvar_sdriver,
+ brd->idx + i, &pdev->dev);
pci_set_drvdata(pdev, brd);
@@ -2695,7 +2723,8 @@
brd->idx = m * MXSER_PORTS_PER_BOARD;
for (i = 0; i < brd->info->nports; i++)
- tty_register_device(mxvar_sdriver, brd->idx + i, NULL);
+ tty_port_register_device(&brd->ports[i].port,
+ mxvar_sdriver, brd->idx + i, NULL);
m++;
}
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index c43b683..3e210a4 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -108,7 +108,7 @@
*/
struct gsm_msg {
- struct gsm_msg *next;
+ struct list_head list;
u8 addr; /* DLCI address + flags */
u8 ctrl; /* Control byte + flags */
unsigned int len; /* Length of data block (can be zero) */
@@ -245,8 +245,7 @@
unsigned int tx_bytes; /* TX data outstanding */
#define TX_THRESH_HI 8192
#define TX_THRESH_LO 2048
- struct gsm_msg *tx_head; /* Pending data packets */
- struct gsm_msg *tx_tail;
+ struct list_head tx_list; /* Pending data packets */
/* Control messages */
struct timer_list t2_timer; /* Retransmit timer for commands */
@@ -663,7 +662,7 @@
m->len = len;
m->addr = addr;
m->ctrl = ctrl;
- m->next = NULL;
+ INIT_LIST_HEAD(&m->list);
return m;
}
@@ -673,22 +672,21 @@
*
* The tty device has called us to indicate that room has appeared in
* the transmit queue. Ram more data into the pipe if we have any
+ * If we have been flow-stopped by a CMD_FCOFF, then we can only
+ * send messages on DLCI0 until CMD_FCON
*
* FIXME: lock against link layer control transmissions
*/
static void gsm_data_kick(struct gsm_mux *gsm)
{
- struct gsm_msg *msg = gsm->tx_head;
+ struct gsm_msg *msg, *nmsg;
int len;
int skip_sof = 0;
- /* FIXME: We need to apply this solely to data messages */
- if (gsm->constipated)
- return;
-
- while (gsm->tx_head != NULL) {
- msg = gsm->tx_head;
+ list_for_each_entry_safe(msg, nmsg, &gsm->tx_list, list) {
+ if (gsm->constipated && msg->addr)
+ continue;
if (gsm->encoding != 0) {
gsm->txframe[0] = GSM1_SOF;
len = gsm_stuff_frame(msg->data,
@@ -711,14 +709,13 @@
len - skip_sof) < 0)
break;
/* FIXME: Can eliminate one SOF in many more cases */
- gsm->tx_head = msg->next;
- if (gsm->tx_head == NULL)
- gsm->tx_tail = NULL;
gsm->tx_bytes -= msg->len;
- kfree(msg);
/* For a burst of frames skip the extra SOF within the
burst */
skip_sof = 1;
+
+ list_del(&msg->list);
+ kfree(msg);
}
}
@@ -768,11 +765,7 @@
msg->data = dp;
/* Add to the actual output queue */
- if (gsm->tx_tail)
- gsm->tx_tail->next = msg;
- else
- gsm->tx_head = msg;
- gsm->tx_tail = msg;
+ list_add_tail(&msg->list, &gsm->tx_list);
gsm->tx_bytes += msg->len;
gsm_data_kick(gsm);
}
@@ -875,7 +868,7 @@
/* dlci->skb is locked by tx_lock */
if (dlci->skb == NULL) {
- dlci->skb = skb_dequeue(&dlci->skb_list);
+ dlci->skb = skb_dequeue_tail(&dlci->skb_list);
if (dlci->skb == NULL)
return 0;
first = 1;
@@ -886,7 +879,7 @@
if (len > gsm->mtu) {
if (dlci->adaption == 3) {
/* Over long frame, bin it */
- kfree_skb(dlci->skb);
+ dev_kfree_skb_any(dlci->skb);
dlci->skb = NULL;
return 0;
}
@@ -899,8 +892,11 @@
/* FIXME: need a timer or something to kick this so it can't
get stuck with no work outstanding and no buffer free */
- if (msg == NULL)
+ if (msg == NULL) {
+ skb_queue_tail(&dlci->skb_list, dlci->skb);
+ dlci->skb = NULL;
return -ENOMEM;
+ }
dp = msg->data;
if (dlci->adaption == 4) { /* Interruptible framed (Packetised Data) */
@@ -912,7 +908,7 @@
skb_pull(dlci->skb, len);
__gsm_data_queue(dlci, msg);
if (last) {
- kfree_skb(dlci->skb);
+ dev_kfree_skb_any(dlci->skb);
dlci->skb = NULL;
}
return size;
@@ -971,16 +967,22 @@
static void gsm_dlci_data_kick(struct gsm_dlci *dlci)
{
unsigned long flags;
+ int sweep;
+
+ if (dlci->constipated)
+ return;
spin_lock_irqsave(&dlci->gsm->tx_lock, flags);
/* If we have nothing running then we need to fire up */
+ sweep = (dlci->gsm->tx_bytes < TX_THRESH_LO);
if (dlci->gsm->tx_bytes == 0) {
if (dlci->net)
gsm_dlci_data_output_framed(dlci->gsm, dlci);
else
gsm_dlci_data_output(dlci->gsm, dlci);
- } else if (dlci->gsm->tx_bytes < TX_THRESH_LO)
- gsm_dlci_data_sweep(dlci->gsm);
+ }
+ if (sweep)
+ gsm_dlci_data_sweep(dlci->gsm);
spin_unlock_irqrestore(&dlci->gsm->tx_lock, flags);
}
@@ -1027,6 +1029,7 @@
{
int mlines = 0;
u8 brk = 0;
+ int fc;
/* The modem status command can either contain one octet (v.24 signals)
or two octets (v.24 signals + break signals). The length field will
@@ -1038,19 +1041,21 @@
else {
brk = modem & 0x7f;
modem = (modem >> 7) & 0x7f;
- };
+ }
/* Flow control/ready to communicate */
- if (modem & MDM_FC) {
+ fc = (modem & MDM_FC) || !(modem & MDM_RTR);
+ if (fc && !dlci->constipated) {
/* Need to throttle our output on this device */
dlci->constipated = 1;
- }
- if (modem & MDM_RTC) {
- mlines |= TIOCM_DSR | TIOCM_DTR;
+ } else if (!fc && dlci->constipated) {
dlci->constipated = 0;
gsm_dlci_data_kick(dlci);
}
+
/* Map modem bits */
+ if (modem & MDM_RTC)
+ mlines |= TIOCM_DSR | TIOCM_DTR;
if (modem & MDM_RTR)
mlines |= TIOCM_RTS | TIOCM_CTS;
if (modem & MDM_IC)
@@ -1061,7 +1066,7 @@
/* Carrier drop -> hangup */
if (tty) {
if ((mlines & TIOCM_CD) == 0 && (dlci->modem_rx & TIOCM_CD))
- if (!(tty->termios->c_cflag & CLOCAL))
+ if (!(tty->termios.c_cflag & CLOCAL))
tty_hangup(tty);
if (brk & 0x01)
tty_insert_flip_char(tty, 0, TTY_BREAK);
@@ -1190,6 +1195,8 @@
u8 *data, int clen)
{
u8 buf[1];
+ unsigned long flags;
+
switch (command) {
case CMD_CLD: {
struct gsm_dlci *dlci = gsm->dlci[0];
@@ -1206,16 +1213,18 @@
gsm_control_reply(gsm, CMD_TEST, data, clen);
break;
case CMD_FCON:
- /* Modem wants us to STFU */
- gsm->constipated = 1;
- gsm_control_reply(gsm, CMD_FCON, NULL, 0);
- break;
- case CMD_FCOFF:
/* Modem can accept data again */
gsm->constipated = 0;
- gsm_control_reply(gsm, CMD_FCOFF, NULL, 0);
+ gsm_control_reply(gsm, CMD_FCON, NULL, 0);
/* Kick the link in case it is idling */
+ spin_lock_irqsave(&gsm->tx_lock, flags);
gsm_data_kick(gsm);
+ spin_unlock_irqrestore(&gsm->tx_lock, flags);
+ break;
+ case CMD_FCOFF:
+ /* Modem wants us to STFU */
+ gsm->constipated = 1;
+ gsm_control_reply(gsm, CMD_FCOFF, NULL, 0);
break;
case CMD_MSC:
/* Out of band modem line change indicator for a DLCI */
@@ -1668,7 +1677,7 @@
dlci->gsm->dlci[dlci->addr] = NULL;
kfifo_free(dlci->fifo);
while ((dlci->skb = skb_dequeue(&dlci->skb_list)))
- kfree_skb(dlci->skb);
+ dev_kfree_skb(dlci->skb);
kfree(dlci);
}
@@ -2007,7 +2016,7 @@
{
int i;
struct gsm_dlci *dlci = gsm->dlci[0];
- struct gsm_msg *txq;
+ struct gsm_msg *txq, *ntxq;
struct gsm_control *gc;
gsm->dead = 1;
@@ -2042,11 +2051,9 @@
if (gsm->dlci[i])
gsm_dlci_release(gsm->dlci[i]);
/* Now wipe the queues */
- for (txq = gsm->tx_head; txq != NULL; txq = gsm->tx_head) {
- gsm->tx_head = txq->next;
+ list_for_each_entry_safe(txq, ntxq, &gsm->tx_list, list)
kfree(txq);
- }
- gsm->tx_tail = NULL;
+ INIT_LIST_HEAD(&gsm->tx_list);
}
EXPORT_SYMBOL_GPL(gsm_cleanup_mux);
@@ -2157,6 +2164,7 @@
}
spin_lock_init(&gsm->lock);
kref_init(&gsm->ref);
+ INIT_LIST_HEAD(&gsm->tx_list);
gsm->t1 = T1;
gsm->t2 = T2;
@@ -2273,7 +2281,7 @@
gsm->error(gsm, *dp, flags);
break;
default:
- WARN_ONCE("%s: unknown flag %d\n",
+ WARN_ONCE(1, "%s: unknown flag %d\n",
tty_name(tty, buf), flags);
break;
}
@@ -2377,12 +2385,12 @@
/* Queue poll */
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+ spin_lock_irqsave(&gsm->tx_lock, flags);
gsm_data_kick(gsm);
if (gsm->tx_bytes < TX_THRESH_LO) {
- spin_lock_irqsave(&gsm->tx_lock, flags);
gsm_dlci_data_sweep(gsm);
- spin_unlock_irqrestore(&gsm->tx_lock, flags);
}
+ spin_unlock_irqrestore(&gsm->tx_lock, flags);
}
/**
@@ -2868,14 +2876,14 @@
.dtr_rts = gsm_dtr_rts,
};
-
-static int gsmtty_open(struct tty_struct *tty, struct file *filp)
+static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty)
{
struct gsm_mux *gsm;
struct gsm_dlci *dlci;
- struct tty_port *port;
unsigned int line = tty->index;
unsigned int mux = line >> 6;
+ bool alloc = false;
+ int ret;
line = line & 0x3F;
@@ -2889,14 +2897,35 @@
gsm = gsm_mux[mux];
if (gsm->dead)
return -EL2HLT;
+ /* If DLCI 0 is not yet fully open return an error. This is ok from a locking
+ perspective as we don't have to worry about this if DLCI0 is lost */
+ if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN)
+ return -EL2NSYNC;
dlci = gsm->dlci[line];
- if (dlci == NULL)
+ if (dlci == NULL) {
+ alloc = true;
dlci = gsm_dlci_alloc(gsm, line);
+ }
if (dlci == NULL)
return -ENOMEM;
- port = &dlci->port;
- port->count++;
+ ret = tty_port_install(&dlci->port, driver, tty);
+ if (ret) {
+ if (alloc)
+ dlci_put(dlci);
+ return ret;
+ }
+
tty->driver_data = dlci;
+
+ return 0;
+}
+
+static int gsmtty_open(struct tty_struct *tty, struct file *filp)
+{
+ struct gsm_dlci *dlci = tty->driver_data;
+ struct tty_port *port = &dlci->port;
+
+ port->count++;
dlci_get(dlci);
dlci_get(dlci->gsm->dlci[0]);
mux_get(dlci->gsm);
@@ -3043,13 +3072,13 @@
the RPN control message. This however rapidly gets nasty as we
then have to remap modem signals each way according to whether
our virtual cable is null modem etc .. */
- tty_termios_copy_hw(tty->termios, old);
+ tty_termios_copy_hw(&tty->termios, old);
}
static void gsmtty_throttle(struct tty_struct *tty)
{
struct gsm_dlci *dlci = tty->driver_data;
- if (tty->termios->c_cflag & CRTSCTS)
+ if (tty->termios.c_cflag & CRTSCTS)
dlci->modem_tx &= ~TIOCM_DTR;
dlci->throttled = 1;
/* Send an MSC with DTR cleared */
@@ -3059,7 +3088,7 @@
static void gsmtty_unthrottle(struct tty_struct *tty)
{
struct gsm_dlci *dlci = tty->driver_data;
- if (tty->termios->c_cflag & CRTSCTS)
+ if (tty->termios.c_cflag & CRTSCTS)
dlci->modem_tx |= TIOCM_DTR;
dlci->throttled = 0;
/* Send an MSC with DTR set */
@@ -3085,6 +3114,7 @@
/* Virtual ttys for the demux */
static const struct tty_operations gsmtty_ops = {
+ .install = gsmtty_install,
.open = gsmtty_open,
.close = gsmtty_close,
.write = gsmtty_write,
diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c
index 5c6c314..1e64050 100644
--- a/drivers/tty/n_r3964.c
+++ b/drivers/tty/n_r3964.c
@@ -1065,7 +1065,7 @@
TRACE_L("read()");
- tty_lock();
+ tty_lock(tty);
pClient = findClient(pInfo, task_pid(current));
if (pClient) {
@@ -1077,7 +1077,7 @@
goto unlock;
}
/* block until there is a message: */
- wait_event_interruptible_tty(pInfo->read_wait,
+ wait_event_interruptible_tty(tty, pInfo->read_wait,
(pMsg = remove_msg(pInfo, pClient)));
}
@@ -1107,7 +1107,7 @@
}
ret = -EPERM;
unlock:
- tty_unlock();
+ tty_unlock(tty);
return ret;
}
@@ -1156,7 +1156,7 @@
pHeader->locks = 0;
pHeader->owner = NULL;
- tty_lock();
+ tty_lock(tty);
pClient = findClient(pInfo, task_pid(current));
if (pClient) {
@@ -1175,7 +1175,7 @@
add_tx_queue(pInfo, pHeader);
trigger_transmit(pInfo);
- tty_unlock();
+ tty_unlock(tty);
return 0;
}
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index ee1c268..8c0b7b4 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -92,10 +92,18 @@
static void n_tty_set_room(struct tty_struct *tty)
{
- /* tty->read_cnt is not read locked ? */
- int left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
+ int left;
int old_left;
+ /* tty->read_cnt is not read locked ? */
+ if (I_PARMRK(tty)) {
+ /* Multiply read_cnt by 3, since each byte might take up to
+ * three times as many spaces when PARMRK is set (depending on
+ * its flags, e.g. parity error). */
+ left = N_TTY_BUF_SIZE - tty->read_cnt * 3 - 1;
+ } else
+ left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
+
/*
* If we are doing input canonicalization, and there are no
* pending newlines, let characters through without limit, so
@@ -1432,6 +1440,12 @@
*/
if (tty->receive_room < TTY_THRESHOLD_THROTTLE)
tty_throttle(tty);
+
+ /* FIXME: there is a tiny race here if the receive room check runs
+ before the other work executes and empties the buffer (upping
+ the receiving room and unthrottling. We then throttle and get
+ stuck. This has been observed and traced down by Vincent Pillet/
+ We need to address this when we sort out out the rx path locking */
}
int is_ignored(int sig)
@@ -1460,7 +1474,7 @@
BUG_ON(!tty);
if (old)
- canon_change = (old->c_lflag ^ tty->termios->c_lflag) & ICANON;
+ canon_change = (old->c_lflag ^ tty->termios.c_lflag) & ICANON;
if (canon_change) {
memset(&tty->read_flags, 0, sizeof tty->read_flags);
tty->canon_head = tty->read_tail;
@@ -1728,7 +1742,8 @@
do_it_again:
- BUG_ON(!tty->read_buf);
+ if (WARN_ON(!tty->read_buf))
+ return -EAGAIN;
c = job_control(tty, file);
if (c < 0)
@@ -1832,13 +1847,13 @@
if (tty->icanon && !L_EXTPROC(tty)) {
/* N.B. avoid overrun if nr == 0 */
+ spin_lock_irqsave(&tty->read_lock, flags);
while (nr && tty->read_cnt) {
int eol;
eol = test_and_clear_bit(tty->read_tail,
tty->read_flags);
c = tty->read_buf[tty->read_tail];
- spin_lock_irqsave(&tty->read_lock, flags);
tty->read_tail = ((tty->read_tail+1) &
(N_TTY_BUF_SIZE-1));
tty->read_cnt--;
@@ -1856,15 +1871,19 @@
if (tty_put_user(tty, c, b++)) {
retval = -EFAULT;
b--;
+ spin_lock_irqsave(&tty->read_lock, flags);
break;
}
nr--;
}
if (eol) {
tty_audit_push(tty);
+ spin_lock_irqsave(&tty->read_lock, flags);
break;
}
+ spin_lock_irqsave(&tty->read_lock, flags);
}
+ spin_unlock_irqrestore(&tty->read_lock, flags);
if (retval)
break;
} else {
diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c
index e7592f9..b917c94 100644
--- a/drivers/tty/nozomi.c
+++ b/drivers/tty/nozomi.c
@@ -1473,8 +1473,8 @@
port->dc = dc;
tty_port_init(&port->port);
port->port.ops = &noz_tty_port_ops;
- tty_dev = tty_register_device(ntty_driver, dc->index_start + i,
- &pdev->dev);
+ tty_dev = tty_port_register_device(&port->port, ntty_driver,
+ dc->index_start + i, &pdev->dev);
if (IS_ERR(tty_dev)) {
ret = PTR_ERR(tty_dev);
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 5505ffc..2bace84 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -47,6 +47,7 @@
wake_up_interruptible(&tty->read_wait);
wake_up_interruptible(&tty->write_wait);
tty->packet = 0;
+ /* Review - krefs on tty_link ?? */
if (!tty->link)
return;
tty->link->packet = 0;
@@ -62,9 +63,9 @@
mutex_unlock(&devpts_mutex);
}
#endif
- tty_unlock();
+ tty_unlock(tty);
tty_vhangup(tty->link);
- tty_lock();
+ tty_lock(tty);
}
}
@@ -231,8 +232,8 @@
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);
+ tty->termios.c_cflag &= ~(CSIZE | PARENB);
+ tty->termios.c_cflag |= (CS8 | CREAD);
}
/**
@@ -282,60 +283,110 @@
return 0;
}
-/* Traditional BSD devices */
-#ifdef CONFIG_LEGACY_PTYS
-
-static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
+/**
+ * pty_common_install - set up the pty pair
+ * @driver: the pty driver
+ * @tty: the tty being instantiated
+ * @bool: legacy, true if this is BSD style
+ *
+ * Perform the initial set up for the tty/pty pair. Called from the
+ * tty layer when the port is first opened.
+ *
+ * Locking: the caller must hold the tty_mutex
+ */
+static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty,
+ bool legacy)
{
struct tty_struct *o_tty;
+ struct tty_port *ports[2];
int idx = tty->index;
- int retval;
+ int retval = -ENOMEM;
o_tty = alloc_tty_struct();
if (!o_tty)
- return -ENOMEM;
+ goto err;
+ ports[0] = kmalloc(sizeof **ports, GFP_KERNEL);
+ ports[1] = kmalloc(sizeof **ports, GFP_KERNEL);
+ if (!ports[0] || !ports[1])
+ goto err_free_tty;
if (!try_module_get(driver->other->owner)) {
/* This cannot in fact currently happen */
- retval = -ENOMEM;
goto err_free_tty;
}
initialize_tty_struct(o_tty, driver->other, idx);
- /* We always use new tty termios data so we can do this
- the easy way .. */
- retval = tty_init_termios(tty);
- if (retval)
- goto err_deinit_tty;
+ if (legacy) {
+ /* We always use new tty termios data so we can do this
+ the easy way .. */
+ retval = tty_init_termios(tty);
+ if (retval)
+ goto err_deinit_tty;
- retval = tty_init_termios(o_tty);
- if (retval)
- goto err_free_termios;
+ retval = tty_init_termios(o_tty);
+ if (retval)
+ goto err_free_termios;
+
+ driver->other->ttys[idx] = o_tty;
+ driver->ttys[idx] = tty;
+ } else {
+ memset(&tty->termios_locked, 0, sizeof(tty->termios_locked));
+ tty->termios = driver->init_termios;
+ memset(&o_tty->termios_locked, 0, sizeof(tty->termios_locked));
+ o_tty->termios = driver->other->init_termios;
+ }
/*
* Everything allocated ... set up the o_tty structure.
*/
- driver->other->ttys[idx] = o_tty;
tty_driver_kref_get(driver->other);
if (driver->subtype == PTY_TYPE_MASTER)
o_tty->count++;
/* Establish the links in both directions */
tty->link = o_tty;
o_tty->link = tty;
+ tty_port_init(ports[0]);
+ tty_port_init(ports[1]);
+ o_tty->port = ports[0];
+ tty->port = ports[1];
tty_driver_kref_get(driver);
tty->count++;
- driver->ttys[idx] = tty;
return 0;
err_free_termios:
- tty_free_termios(tty);
+ if (legacy)
+ tty_free_termios(tty);
err_deinit_tty:
deinitialize_tty_struct(o_tty);
module_put(o_tty->driver->owner);
err_free_tty:
+ kfree(ports[0]);
+ kfree(ports[1]);
free_tty_struct(o_tty);
+err:
return retval;
}
+static void pty_cleanup(struct tty_struct *tty)
+{
+ kfree(tty->port);
+}
+
+/* Traditional BSD devices */
+#ifdef CONFIG_LEGACY_PTYS
+
+static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+ return pty_common_install(driver, tty, true);
+}
+
+static void pty_remove(struct tty_driver *driver, struct tty_struct *tty)
+{
+ struct tty_struct *pair = tty->link;
+ driver->ttys[tty->index] = NULL;
+ if (pair)
+ pair->driver->ttys[pair->index] = NULL;
+}
+
static int pty_bsd_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
@@ -366,7 +417,9 @@
.unthrottle = pty_unthrottle,
.set_termios = pty_set_termios,
.ioctl = pty_bsd_ioctl,
- .resize = pty_resize
+ .cleanup = pty_cleanup,
+ .resize = pty_resize,
+ .remove = pty_remove
};
static const struct tty_operations slave_pty_ops_bsd = {
@@ -379,7 +432,9 @@
.chars_in_buffer = pty_chars_in_buffer,
.unthrottle = pty_unthrottle,
.set_termios = pty_set_termios,
- .resize = pty_resize
+ .cleanup = pty_cleanup,
+ .resize = pty_resize,
+ .remove = pty_remove
};
static void __init legacy_pty_init(void)
@@ -389,12 +444,18 @@
if (legacy_count <= 0)
return;
- pty_driver = alloc_tty_driver(legacy_count);
- if (!pty_driver)
+ pty_driver = tty_alloc_driver(legacy_count,
+ TTY_DRIVER_RESET_TERMIOS |
+ TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_DYNAMIC_ALLOC);
+ if (IS_ERR(pty_driver))
panic("Couldn't allocate pty driver");
- pty_slave_driver = alloc_tty_driver(legacy_count);
- if (!pty_slave_driver)
+ pty_slave_driver = tty_alloc_driver(legacy_count,
+ TTY_DRIVER_RESET_TERMIOS |
+ TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_DYNAMIC_ALLOC);
+ if (IS_ERR(pty_slave_driver))
panic("Couldn't allocate pty slave driver");
pty_driver->driver_name = "pty_master";
@@ -410,7 +471,6 @@
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, &master_pty_ops_bsd);
@@ -424,8 +484,6 @@
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;
tty_set_operations(pty_slave_driver, &slave_pty_ops_bsd);
@@ -497,78 +555,22 @@
return tty;
}
-static void pty_unix98_shutdown(struct tty_struct *tty)
-{
- tty_driver_remove_tty(tty->driver, tty);
- /* We have our own method as we don't use the tty index */
- kfree(tty->termios);
-}
-
/* We have no need to install and remove our tty objects as devpts does all
the work for us */
static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty)
{
- struct tty_struct *o_tty;
- int idx = tty->index;
-
- o_tty = alloc_tty_struct();
- if (!o_tty)
- return -ENOMEM;
- if (!try_module_get(driver->other->owner)) {
- /* This cannot in fact currently happen */
- goto err_free_tty;
- }
- initialize_tty_struct(o_tty, driver->other, idx);
-
- tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
- if (tty->termios == NULL)
- goto err_free_mem;
- *tty->termios = driver->init_termios;
- tty->termios_locked = tty->termios + 1;
-
- o_tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
- if (o_tty->termios == NULL)
- goto err_free_mem;
- *o_tty->termios = driver->other->init_termios;
- o_tty->termios_locked = o_tty->termios + 1;
-
- tty_driver_kref_get(driver->other);
- if (driver->subtype == PTY_TYPE_MASTER)
- o_tty->count++;
- /* Establish the links in both directions */
- tty->link = o_tty;
- o_tty->link = tty;
- /*
- * All structures have been allocated, so now we install them.
- * Failures after this point use release_tty to clean up, so
- * there's no need to null out the local pointers.
- */
- tty_driver_kref_get(driver);
- tty->count++;
- return 0;
-err_free_mem:
- deinitialize_tty_struct(o_tty);
- kfree(o_tty->termios);
- kfree(tty->termios);
- module_put(o_tty->driver->owner);
-err_free_tty:
- free_tty_struct(o_tty);
- return -ENOMEM;
+ return pty_common_install(driver, tty, false);
}
-static void ptm_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
-{
-}
-
-static void pts_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
+static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
{
}
static const struct tty_operations ptm_unix98_ops = {
.lookup = ptm_unix98_lookup,
.install = pty_unix98_install,
- .remove = ptm_unix98_remove,
+ .remove = pty_unix98_remove,
.open = pty_open,
.close = pty_close,
.write = pty_write,
@@ -578,14 +580,14 @@
.unthrottle = pty_unthrottle,
.set_termios = pty_set_termios,
.ioctl = pty_unix98_ioctl,
- .shutdown = pty_unix98_shutdown,
- .resize = pty_resize
+ .resize = pty_resize,
+ .cleanup = pty_cleanup
};
static const struct tty_operations pty_unix98_ops = {
.lookup = pts_unix98_lookup,
.install = pty_unix98_install,
- .remove = pts_unix98_remove,
+ .remove = pty_unix98_remove,
.open = pty_open,
.close = pty_close,
.write = pty_write,
@@ -594,7 +596,7 @@
.chars_in_buffer = pty_chars_in_buffer,
.unthrottle = pty_unthrottle,
.set_termios = pty_set_termios,
- .shutdown = pty_unix98_shutdown
+ .cleanup = pty_cleanup,
};
/**
@@ -622,26 +624,27 @@
return retval;
/* find a device that is not in use. */
- tty_lock();
+ mutex_lock(&devpts_mutex);
index = devpts_new_index(inode);
- tty_unlock();
if (index < 0) {
retval = index;
goto err_file;
}
- mutex_lock(&tty_mutex);
- mutex_lock(&devpts_mutex);
- tty = tty_init_dev(ptm_driver, index);
mutex_unlock(&devpts_mutex);
- tty_lock();
- mutex_unlock(&tty_mutex);
+
+ mutex_lock(&tty_mutex);
+ tty = tty_init_dev(ptm_driver, index);
if (IS_ERR(tty)) {
retval = PTR_ERR(tty);
goto out;
}
+ /* The tty returned here is locked so we can safely
+ drop the mutex */
+ mutex_unlock(&tty_mutex);
+
set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
tty_add_file(tty, filp);
@@ -654,16 +657,17 @@
if (retval)
goto err_release;
- tty_unlock();
+ tty_unlock(tty);
return 0;
err_release:
- tty_unlock();
+ tty_unlock(tty);
tty_release(inode, filp);
return retval;
out:
+ mutex_unlock(&tty_mutex);
devpts_kill_index(inode, index);
- tty_unlock();
err_file:
+ mutex_unlock(&devpts_mutex);
tty_free_file(filp);
return retval;
}
@@ -672,11 +676,21 @@
static void __init unix98_pty_init(void)
{
- ptm_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX);
- if (!ptm_driver)
+ ptm_driver = tty_alloc_driver(NR_UNIX98_PTY_MAX,
+ TTY_DRIVER_RESET_TERMIOS |
+ TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_DYNAMIC_DEV |
+ TTY_DRIVER_DEVPTS_MEM |
+ TTY_DRIVER_DYNAMIC_ALLOC);
+ if (IS_ERR(ptm_driver))
panic("Couldn't allocate Unix98 ptm driver");
- pts_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX);
- if (!pts_driver)
+ pts_driver = tty_alloc_driver(NR_UNIX98_PTY_MAX,
+ TTY_DRIVER_RESET_TERMIOS |
+ TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_DYNAMIC_DEV |
+ TTY_DRIVER_DEVPTS_MEM |
+ TTY_DRIVER_DYNAMIC_ALLOC);
+ if (IS_ERR(pts_driver))
panic("Couldn't allocate Unix98 pts driver");
ptm_driver->driver_name = "pty_master";
@@ -692,8 +706,6 @@
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;
tty_set_operations(ptm_driver, &ptm_unix98_ops);
@@ -707,8 +719,6 @@
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;
tty_set_operations(pts_driver, &pty_unix98_ops);
diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c
index 777d5f9..9700d34 100644
--- a/drivers/tty/rocket.c
+++ b/drivers/tty/rocket.c
@@ -704,8 +704,8 @@
spin_lock_init(&info->slock);
mutex_init(&info->write_mtx);
rp_table[line] = info;
- tty_register_device(rocket_driver, line, pci_dev ? &pci_dev->dev :
- NULL);
+ tty_port_register_device(&info->port, rocket_driver, line,
+ pci_dev ? &pci_dev->dev : NULL);
}
/*
@@ -720,7 +720,7 @@
unsigned rocketMode;
int bits, baud, divisor;
CHANNEL_t *cp;
- struct ktermios *t = tty->termios;
+ struct ktermios *t = &tty->termios;
cp = &info->channel;
cflag = t->c_cflag;
@@ -978,7 +978,7 @@
tty->alt_speed = 460800;
configure_r_port(tty, info, NULL);
- if (tty->termios->c_cflag & CBAUD) {
+ if (tty->termios.c_cflag & CBAUD) {
sSetDTR(cp);
sSetRTS(cp);
}
@@ -1089,35 +1089,35 @@
if (rocket_paranoia_check(info, "rp_set_termios"))
return;
- cflag = tty->termios->c_cflag;
+ cflag = tty->termios.c_cflag;
/*
* This driver doesn't support CS5 or CS6
*/
if (((cflag & CSIZE) == CS5) || ((cflag & CSIZE) == CS6))
- tty->termios->c_cflag =
+ tty->termios.c_cflag =
((cflag & ~CSIZE) | (old_termios->c_cflag & CSIZE));
/* Or CMSPAR */
- tty->termios->c_cflag &= ~CMSPAR;
+ tty->termios.c_cflag &= ~CMSPAR;
configure_r_port(tty, info, old_termios);
cp = &info->channel;
/* Handle transition to B0 status */
- if ((old_termios->c_cflag & CBAUD) && !(tty->termios->c_cflag & CBAUD)) {
+ if ((old_termios->c_cflag & CBAUD) && !(tty->termios.c_cflag & CBAUD)) {
sClrDTR(cp);
sClrRTS(cp);
}
/* Handle transition away from B0 status */
- if (!(old_termios->c_cflag & CBAUD) && (tty->termios->c_cflag & CBAUD)) {
- if (!tty->hw_stopped || !(tty->termios->c_cflag & CRTSCTS))
+ if (!(old_termios->c_cflag & CBAUD) && (tty->termios.c_cflag & CBAUD)) {
+ if (!tty->hw_stopped || !(tty->termios.c_cflag & CRTSCTS))
sSetRTS(cp);
sSetDTR(cp);
}
- if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) {
+ if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios.c_cflag & CRTSCTS)) {
tty->hw_stopped = 0;
rp_start(tty);
}
diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c
index 3ed20e4..66c38a3 100644
--- a/drivers/tty/serial/68328serial.c
+++ b/drivers/tty/serial/68328serial.c
@@ -515,7 +515,7 @@
unsigned cflag;
int i;
- cflag = tty->termios->c_cflag;
+ cflag = tty->termios.c_cflag;
if (!(port = info->port))
return;
@@ -617,7 +617,7 @@
if (serial_paranoia_check(info, tty->name, "rs_set_ldisc"))
return;
- info->is_cons = (tty->termios->c_line == N_TTY);
+ info->is_cons = (tty->termios.c_line == N_TTY);
printk("ttyS%d console mode %s\n", info->line, info->is_cons ? "on" : "off");
}
@@ -985,7 +985,7 @@
change_speed(info, tty);
if ((old_termios->c_cflag & CRTSCTS) &&
- !(tty->termios->c_cflag & CRTSCTS)) {
+ !(tty->termios.c_cflag & CRTSCTS)) {
tty->hw_stopped = 0;
rs_start(tty);
}
@@ -1070,7 +1070,7 @@
if (tty->ldisc.close)
(tty->ldisc.close)(tty);
tty->ldisc = ldiscs[N_TTY];
- tty->termios->c_line = N_TTY;
+ tty->termios.c_line = N_TTY;
if (tty->ldisc.open)
(tty->ldisc.open)(tty);
}
@@ -1189,12 +1189,6 @@
serial_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(serial_driver, &rs_ops);
- if (tty_register_driver(serial_driver)) {
- put_tty_driver(serial_driver);
- printk(KERN_ERR "Couldn't register serial driver\n");
- return -ENOMEM;
- }
-
local_irq_save(flags);
for(i=0;i<NR_PORTS;i++) {
@@ -1224,8 +1218,17 @@
0,
"M68328_UART", info))
panic("Unable to attach 68328 serial interrupt\n");
+
+ tty_port_link_device(&info->tport, serial_driver, i);
}
local_irq_restore(flags);
+
+ if (tty_register_driver(serial_driver)) {
+ put_tty_driver(serial_driver);
+ printk(KERN_ERR "Couldn't register serial driver\n");
+ return -ENOMEM;
+ }
+
return 0;
}
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
index 8123f78..d4e0b07 100644
--- a/drivers/tty/serial/8250/8250.c
+++ b/drivers/tty/serial/8250/8250.c
@@ -2202,6 +2202,7 @@
unsigned char cval, fcr = 0;
unsigned long flags;
unsigned int baud, quot;
+ int fifo_bug = 0;
switch (termios->c_cflag & CSIZE) {
case CS5:
@@ -2221,8 +2222,11 @@
if (termios->c_cflag & CSTOPB)
cval |= UART_LCR_STOP;
- if (termios->c_cflag & PARENB)
+ if (termios->c_cflag & PARENB) {
cval |= UART_LCR_PARITY;
+ if (up->bugs & UART_BUG_PARITY)
+ fifo_bug = 1;
+ }
if (!(termios->c_cflag & PARODD))
cval |= UART_LCR_EPAR;
#ifdef CMSPAR
@@ -2246,7 +2250,7 @@
if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) {
fcr = uart_config[port->type].fcr;
- if (baud < 2400) {
+ if (baud < 2400 || fifo_bug) {
fcr &= ~UART_FCR_TRIGGER_MASK;
fcr |= UART_FCR_TRIGGER_1;
}
@@ -2336,7 +2340,7 @@
serial_port_out(port, UART_EFR, efr);
}
-#ifdef CONFIG_ARCH_OMAP
+#ifdef CONFIG_ARCH_OMAP1
/* Workaround to enable 115200 baud on OMAP1510 internal ports */
if (cpu_is_omap1510() && is_omap_port(up)) {
if (baud == 115200) {
@@ -2426,7 +2430,7 @@
{
if (pt->port.iotype == UPIO_AU)
return 0x1000;
-#ifdef CONFIG_ARCH_OMAP
+#ifdef CONFIG_ARCH_OMAP1
if (is_omap_port(pt))
return 0x16 << pt->port.regshift;
#endif
@@ -2979,36 +2983,36 @@
static int __devinit serial8250_probe(struct platform_device *dev)
{
struct plat_serial8250_port *p = dev->dev.platform_data;
- struct uart_port port;
+ struct uart_8250_port uart;
int ret, i, irqflag = 0;
- memset(&port, 0, sizeof(struct uart_port));
+ memset(&uart, 0, sizeof(uart));
if (share_irqs)
irqflag = IRQF_SHARED;
for (i = 0; p && p->flags != 0; p++, i++) {
- port.iobase = p->iobase;
- port.membase = p->membase;
- port.irq = p->irq;
- port.irqflags = p->irqflags;
- port.uartclk = p->uartclk;
- port.regshift = p->regshift;
- port.iotype = p->iotype;
- port.flags = p->flags;
- port.mapbase = p->mapbase;
- port.hub6 = p->hub6;
- port.private_data = p->private_data;
- port.type = p->type;
- port.serial_in = p->serial_in;
- port.serial_out = p->serial_out;
- port.handle_irq = p->handle_irq;
- port.handle_break = p->handle_break;
- port.set_termios = p->set_termios;
- port.pm = p->pm;
- port.dev = &dev->dev;
- port.irqflags |= irqflag;
- ret = serial8250_register_port(&port);
+ uart.port.iobase = p->iobase;
+ uart.port.membase = p->membase;
+ uart.port.irq = p->irq;
+ uart.port.irqflags = p->irqflags;
+ uart.port.uartclk = p->uartclk;
+ uart.port.regshift = p->regshift;
+ uart.port.iotype = p->iotype;
+ uart.port.flags = p->flags;
+ uart.port.mapbase = p->mapbase;
+ uart.port.hub6 = p->hub6;
+ uart.port.private_data = p->private_data;
+ uart.port.type = p->type;
+ uart.port.serial_in = p->serial_in;
+ uart.port.serial_out = p->serial_out;
+ uart.port.handle_irq = p->handle_irq;
+ uart.port.handle_break = p->handle_break;
+ uart.port.set_termios = p->set_termios;
+ uart.port.pm = p->pm;
+ uart.port.dev = &dev->dev;
+ uart.port.irqflags |= irqflag;
+ ret = serial8250_register_8250_port(&uart);
if (ret < 0) {
dev_err(&dev->dev, "unable to register port at index %d "
"(IO%lx MEM%llx IRQ%d): %d\n", i,
@@ -3081,7 +3085,7 @@
static struct platform_device *serial8250_isa_devs;
/*
- * serial8250_register_port and serial8250_unregister_port allows for
+ * serial8250_register_8250_port and serial8250_unregister_port allows for
* 16x50 serial ports to be configured at run-time, to support PCMCIA
* modems and PCI multiport cards.
*/
@@ -3155,6 +3159,7 @@
uart->port.regshift = up->port.regshift;
uart->port.iotype = up->port.iotype;
uart->port.flags = up->port.flags | UPF_BOOT_AUTOCONF;
+ uart->bugs = up->bugs;
uart->port.mapbase = up->port.mapbase;
uart->port.private_data = up->port.private_data;
if (up->port.dev)
@@ -3198,29 +3203,6 @@
EXPORT_SYMBOL(serial8250_register_8250_port);
/**
- * serial8250_register_port - register a serial port
- * @port: serial port template
- *
- * Configure the serial port specified by the request. If the
- * port exists and is in use, it is hung up and unregistered
- * first.
- *
- * The port is then probed and if necessary the IRQ is autodetected
- * If this fails an error is returned.
- *
- * On success the port is ready to use and the line number is returned.
- */
-int serial8250_register_port(struct uart_port *port)
-{
- struct uart_8250_port up;
-
- memset(&up, 0, sizeof(up));
- memcpy(&up.port, port, sizeof(*port));
- return serial8250_register_8250_port(&up);
-}
-EXPORT_SYMBOL(serial8250_register_port);
-
-/**
* serial8250_unregister_port - remove a 16x50 serial port at runtime
* @line: serial line number
*
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index f9719d1..0c5e908 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -13,36 +13,6 @@
#include <linux/serial_8250.h>
-struct uart_8250_port {
- struct uart_port port;
- struct timer_list timer; /* "no irq" timer */
- struct list_head list; /* ports on this IRQ */
- unsigned short capabilities; /* port capabilities */
- unsigned short bugs; /* port bugs */
- unsigned int tx_loadsz; /* transmit fifo load size */
- unsigned char acr;
- unsigned char ier;
- unsigned char lcr;
- unsigned char mcr;
- unsigned char mcr_mask; /* mask of user bits */
- unsigned char mcr_force; /* mask of forced bits */
- unsigned char cur_iotype; /* Running I/O type */
-
- /*
- * Some bits in registers are cleared on a read, so they must
- * be saved whenever the register is read but the bits will not
- * be immediately processed.
- */
-#define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS
- unsigned char lsr_saved_flags;
-#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
- unsigned char msr_saved_flags;
-
- /* 8250 specific callbacks */
- int (*dl_read)(struct uart_8250_port *);
- void (*dl_write)(struct uart_8250_port *, int);
-};
-
struct old_serial_port {
unsigned int uart;
unsigned int baud_base;
@@ -56,9 +26,6 @@
unsigned long irqflags;
};
-/*
- * This replaces serial_uart_config in include/linux/serial.h
- */
struct serial8250_config {
const char *name;
unsigned short fifo_size;
@@ -78,6 +45,7 @@
#define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */
#define UART_BUG_NOMSR (1 << 2) /* UART has buggy MSR status bits (Au1x00) */
#define UART_BUG_THRE (1 << 3) /* UART has buggy THRE reassertion */
+#define UART_BUG_PARITY (1 << 4) /* UART mishandles parity if FIFO enabled */
#define PROBE_RSA (1 << 0)
#define PROBE_ANY (~0)
diff --git a/drivers/tty/serial/8250/8250_acorn.c b/drivers/tty/serial/8250/8250_acorn.c
index b0ce8c5..8574983 100644
--- a/drivers/tty/serial/8250/8250_acorn.c
+++ b/drivers/tty/serial/8250/8250_acorn.c
@@ -43,7 +43,7 @@
{
struct serial_card_info *info;
struct serial_card_type *type = id->data;
- struct uart_port port;
+ struct uart_8250_port uart;
unsigned long bus_addr;
unsigned int i;
@@ -62,19 +62,19 @@
ecard_set_drvdata(ec, info);
- memset(&port, 0, sizeof(struct uart_port));
- port.irq = ec->irq;
- port.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
- port.uartclk = type->uartclk;
- port.iotype = UPIO_MEM;
- port.regshift = 2;
- port.dev = &ec->dev;
+ memset(&uart, 0, sizeof(struct uart_8250_port));
+ uart.port.irq = ec->irq;
+ uart.port.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+ uart.port.uartclk = type->uartclk;
+ uart.port.iotype = UPIO_MEM;
+ uart.port.regshift = 2;
+ uart.port.dev = &ec->dev;
for (i = 0; i < info->num_ports; i ++) {
- port.membase = info->vaddr + type->offset[i];
- port.mapbase = bus_addr + type->offset[i];
+ uart.port.membase = info->vaddr + type->offset[i];
+ uart.port.mapbase = bus_addr + type->offset[i];
- info->ports[i] = serial8250_register_port(&port);
+ info->ports[i] = serial8250_register_8250_port(&uart);
}
return 0;
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index f574eef..c3b2ec0 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -89,7 +89,7 @@
static int __devinit dw8250_probe(struct platform_device *pdev)
{
- struct uart_port port = {};
+ struct uart_8250_port uart = {};
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
struct device_node *np = pdev->dev.of_node;
@@ -104,28 +104,28 @@
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- port.private_data = data;
+ uart.port.private_data = data;
- spin_lock_init(&port.lock);
- port.mapbase = regs->start;
- port.irq = irq->start;
- port.handle_irq = dw8250_handle_irq;
- port.type = PORT_8250;
- port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP |
+ spin_lock_init(&uart.port.lock);
+ uart.port.mapbase = regs->start;
+ uart.port.irq = irq->start;
+ uart.port.handle_irq = dw8250_handle_irq;
+ uart.port.type = PORT_8250;
+ uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP |
UPF_FIXED_PORT | UPF_FIXED_TYPE;
- port.dev = &pdev->dev;
+ uart.port.dev = &pdev->dev;
- port.iotype = UPIO_MEM;
- port.serial_in = dw8250_serial_in;
- port.serial_out = dw8250_serial_out;
+ uart.port.iotype = UPIO_MEM;
+ uart.port.serial_in = dw8250_serial_in;
+ uart.port.serial_out = dw8250_serial_out;
if (!of_property_read_u32(np, "reg-io-width", &val)) {
switch (val) {
case 1:
break;
case 4:
- port.iotype = UPIO_MEM32;
- port.serial_in = dw8250_serial_in32;
- port.serial_out = dw8250_serial_out32;
+ uart.port.iotype = UPIO_MEM32;
+ uart.port.serial_in = dw8250_serial_in32;
+ uart.port.serial_out = dw8250_serial_out32;
break;
default:
dev_err(&pdev->dev, "unsupported reg-io-width (%u)\n",
@@ -135,15 +135,15 @@
}
if (!of_property_read_u32(np, "reg-shift", &val))
- port.regshift = val;
+ uart.port.regshift = val;
if (of_property_read_u32(np, "clock-frequency", &val)) {
dev_err(&pdev->dev, "no clock-frequency property set\n");
return -EINVAL;
}
- port.uartclk = val;
+ uart.port.uartclk = val;
- data->line = serial8250_register_port(&port);
+ data->line = serial8250_register_8250_port(&uart);
if (data->line < 0)
return data->line;
diff --git a/drivers/tty/serial/8250/8250_gsc.c b/drivers/tty/serial/8250/8250_gsc.c
index d8c0ffb..097dff9 100644
--- a/drivers/tty/serial/8250/8250_gsc.c
+++ b/drivers/tty/serial/8250/8250_gsc.c
@@ -26,7 +26,7 @@
static int __init serial_init_chip(struct parisc_device *dev)
{
- struct uart_port port;
+ struct uart_8250_port uart;
unsigned long address;
int err;
@@ -48,21 +48,21 @@
if (dev->id.sversion != 0x8d)
address += 0x800;
- memset(&port, 0, sizeof(port));
- port.iotype = UPIO_MEM;
+ memset(&uart, 0, sizeof(uart));
+ uart.port.iotype = UPIO_MEM;
/* 7.272727MHz on Lasi. Assumed the same for Dino, Wax and Timi. */
- port.uartclk = 7272727;
- port.mapbase = address;
- port.membase = ioremap_nocache(address, 16);
- port.irq = dev->irq;
- port.flags = UPF_BOOT_AUTOCONF;
- port.dev = &dev->dev;
+ uart.port.uartclk = 7272727;
+ uart.port.mapbase = address;
+ uart.port.membase = ioremap_nocache(address, 16);
+ uart.port.irq = dev->irq;
+ uart.port.flags = UPF_BOOT_AUTOCONF;
+ uart.port.dev = &dev->dev;
- err = serial8250_register_port(&port);
+ err = serial8250_register_8250_port(&uart);
if (err < 0) {
printk(KERN_WARNING
- "serial8250_register_port returned error %d\n", err);
- iounmap(port.membase);
+ "serial8250_register_8250_port returned error %d\n", err);
+ iounmap(uart.port.membase);
return err;
}
diff --git a/drivers/tty/serial/8250/8250_hp300.c b/drivers/tty/serial/8250/8250_hp300.c
index c13438c..8f1dd2c 100644
--- a/drivers/tty/serial/8250/8250_hp300.c
+++ b/drivers/tty/serial/8250/8250_hp300.c
@@ -171,7 +171,7 @@
return 0;
}
#endif
- memset(&port, 0, sizeof(struct uart_port));
+ memset(&uart, 0, sizeof(uart));
/* Memory mapped I/O */
port.iotype = UPIO_MEM;
@@ -182,7 +182,7 @@
port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
port.regshift = 1;
port.dev = &d->dev;
- line = serial8250_register_port(&port);
+ line = serial8250_register_8250_port(&uart);
if (line < 0) {
printk(KERN_NOTICE "8250_hp300: register_serial() DCA scode %d"
@@ -210,7 +210,7 @@
#ifdef CONFIG_HPAPCI
int line;
unsigned long base;
- struct uart_port uport;
+ struct uart_8250_port uart;
struct hp300_port *port;
int i;
#endif
@@ -248,26 +248,26 @@
if (!port)
return -ENOMEM;
- memset(&uport, 0, sizeof(struct uart_port));
+ memset(&uart, 0, sizeof(uart));
base = (FRODO_BASE + FRODO_APCI_OFFSET(i));
/* Memory mapped I/O */
- uport.iotype = UPIO_MEM;
- uport.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ \
+ uart.port.iotype = UPIO_MEM;
+ uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ \
| UPF_BOOT_AUTOCONF;
/* XXX - no interrupt support yet */
- uport.irq = 0;
- uport.uartclk = HPAPCI_BAUD_BASE * 16;
- uport.mapbase = base;
- uport.membase = (char *)(base + DIO_VIRADDRBASE);
- uport.regshift = 2;
+ uart.port.irq = 0;
+ uart.port.uartclk = HPAPCI_BAUD_BASE * 16;
+ uart.port.mapbase = base;
+ uart.port.membase = (char *)(base + DIO_VIRADDRBASE);
+ uart.port.regshift = 2;
- line = serial8250_register_port(&uport);
+ line = serial8250_register_8250_port(&uart);
if (line < 0) {
printk(KERN_NOTICE "8250_hp300: register_serial() APCI"
- " %d irq %d failed\n", i, uport.irq);
+ " %d irq %d failed\n", i, uart.port.irq);
kfree(port);
continue;
}
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 28e7c7c..fdab80a 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -44,7 +44,7 @@
int (*init)(struct pci_dev *dev);
int (*setup)(struct serial_private *,
const struct pciserial_board *,
- struct uart_port *, int);
+ struct uart_8250_port *, int);
void (*exit)(struct pci_dev *dev);
};
@@ -59,7 +59,7 @@
};
static int pci_default_setup(struct serial_private*,
- const struct pciserial_board*, struct uart_port*, int);
+ const struct pciserial_board*, struct uart_8250_port *, int);
static void moan_device(const char *str, struct pci_dev *dev)
{
@@ -74,7 +74,7 @@
}
static int
-setup_port(struct serial_private *priv, struct uart_port *port,
+setup_port(struct serial_private *priv, struct uart_8250_port *port,
int bar, int offset, int regshift)
{
struct pci_dev *dev = priv->dev;
@@ -93,17 +93,17 @@
if (!priv->remapped_bar[bar])
return -ENOMEM;
- port->iotype = UPIO_MEM;
- port->iobase = 0;
- port->mapbase = base + offset;
- port->membase = priv->remapped_bar[bar] + offset;
- port->regshift = regshift;
+ port->port.iotype = UPIO_MEM;
+ port->port.iobase = 0;
+ port->port.mapbase = base + offset;
+ port->port.membase = priv->remapped_bar[bar] + offset;
+ port->port.regshift = regshift;
} else {
- port->iotype = UPIO_PORT;
- port->iobase = base + offset;
- port->mapbase = 0;
- port->membase = NULL;
- port->regshift = 0;
+ port->port.iotype = UPIO_PORT;
+ port->port.iobase = base + offset;
+ port->port.mapbase = 0;
+ port->port.membase = NULL;
+ port->port.regshift = 0;
}
return 0;
}
@@ -113,7 +113,7 @@
*/
static int addidata_apci7800_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
unsigned int bar = 0, offset = board->first_offset;
bar = FL_GET_BASE(board->flags);
@@ -140,7 +140,7 @@
*/
static int
afavlab_setup(struct serial_private *priv, const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
unsigned int bar, offset = board->first_offset;
@@ -195,7 +195,7 @@
static int
pci_hp_diva_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
unsigned int offset = board->first_offset;
unsigned int bar = FL_GET_BASE(board->flags);
@@ -370,7 +370,7 @@
/* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */
static int
sbs_setup(struct serial_private *priv, const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
unsigned int bar, offset = board->first_offset;
@@ -525,7 +525,7 @@
static int pci_siig_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
unsigned int bar = FL_GET_BASE(board->flags) + idx, offset = 0;
@@ -619,7 +619,7 @@
static int
pci_timedia_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
unsigned int bar = 0, offset = board->first_offset;
@@ -653,7 +653,7 @@
static int
titan_400l_800l_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
unsigned int bar, offset = board->first_offset;
@@ -754,7 +754,7 @@
static int
pci_ni8430_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
void __iomem *p;
unsigned long base, len;
@@ -781,7 +781,7 @@
static int pci_netmos_9900_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
unsigned int bar;
@@ -1032,10 +1032,17 @@
return number_uarts;
}
-static int
-pci_default_setup(struct serial_private *priv,
+static int pci_asix_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
+{
+ port->bugs |= UART_BUG_PARITY;
+ return pci_default_setup(priv, board, port, idx);
+}
+
+static int pci_default_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
+ struct uart_8250_port *port, int idx)
{
unsigned int bar, offset = board->first_offset, maxnr;
@@ -1057,15 +1064,15 @@
static int
ce4100_serial_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
int ret;
ret = setup_port(priv, port, 0, 0, board->reg_shift);
- port->iotype = UPIO_MEM32;
- port->type = PORT_XSCALE;
- port->flags = (port->flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
- port->regshift = 2;
+ port->port.iotype = UPIO_MEM32;
+ port->port.type = PORT_XSCALE;
+ port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
+ port->port.regshift = 2;
return ret;
}
@@ -1073,16 +1080,16 @@
static int
pci_omegapci_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
return setup_port(priv, port, 2, idx * 8, 0);
}
static int skip_tx_en_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
- port->flags |= UPF_NO_TXEN_TEST;
+ port->port.flags |= UPF_NO_TXEN_TEST;
printk(KERN_DEBUG "serial8250: skipping TxEn test for device "
"[%04x:%04x] subsystem [%04x:%04x]\n",
priv->dev->vendor,
@@ -1131,11 +1138,11 @@
static int kt_serial_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
- port->flags |= UPF_BUG_THRE;
- port->serial_in = kt_serial_in;
- port->handle_break = kt_handle_break;
+ port->port.flags |= UPF_BUG_THRE;
+ port->port.serial_in = kt_serial_in;
+ port->port.handle_break = kt_handle_break;
return skip_tx_en_setup(priv, board, port, idx);
}
@@ -1151,9 +1158,19 @@
static int
pci_xr17c154_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
- port->flags |= UPF_EXAR_EFR;
+ port->port.flags |= UPF_EXAR_EFR;
+ return pci_default_setup(priv, board, port, idx);
+}
+
+static int
+pci_wch_ch353_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
+ struct uart_8250_port *port, int idx)
+{
+ port->port.flags |= UPF_FIXED_TYPE;
+ port->port.type = PORT_16550A;
return pci_default_setup(priv, board, port, idx);
}
@@ -1187,6 +1204,13 @@
#define PCIE_DEVICE_ID_NEO_2_OX_IBM 0x00F6
#define PCI_DEVICE_ID_PLX_CRONYX_OMEGA 0xc001
#define PCI_DEVICE_ID_INTEL_PATSBURG_KT 0x1d3d
+#define PCI_VENDOR_ID_WCH 0x4348
+#define PCI_DEVICE_ID_WCH_CH353_4S 0x3453
+#define PCI_DEVICE_ID_WCH_CH353_2S1PF 0x5046
+#define PCI_DEVICE_ID_WCH_CH353_2S1P 0x7053
+#define PCI_VENDOR_ID_AGESTAR 0x5372
+#define PCI_DEVICE_ID_AGESTAR_9375 0x6872
+#define PCI_VENDOR_ID_ASIX 0x9710
/* Unknown vendors/cards - this should not be in linux/pci_ids.h */
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
@@ -1726,7 +1750,41 @@
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_omegapci_setup,
- },
+ },
+ /* WCH CH353 2S1P card (16550 clone) */
+ {
+ .vendor = PCI_VENDOR_ID_WCH,
+ .device = PCI_DEVICE_ID_WCH_CH353_2S1P,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_wch_ch353_setup,
+ },
+ /* WCH CH353 4S card (16550 clone) */
+ {
+ .vendor = PCI_VENDOR_ID_WCH,
+ .device = PCI_DEVICE_ID_WCH_CH353_4S,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_wch_ch353_setup,
+ },
+ /* WCH CH353 2S1PF card (16550 clone) */
+ {
+ .vendor = PCI_VENDOR_ID_WCH,
+ .device = PCI_DEVICE_ID_WCH_CH353_2S1PF,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_wch_ch353_setup,
+ },
+ /*
+ * ASIX devices with FIFO bug
+ */
+ {
+ .vendor = PCI_VENDOR_ID_ASIX,
+ .device = PCI_ANY_ID,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_asix_setup,
+ },
/*
* Default "match everything" terminator entry
*/
@@ -1887,7 +1945,6 @@
pbn_panacom,
pbn_panacom2,
pbn_panacom4,
- pbn_exsys_4055,
pbn_plx_romulus,
pbn_oxsemi,
pbn_oxsemi_1_4000000,
@@ -2393,13 +2450,6 @@
.reg_shift = 7,
},
- [pbn_exsys_4055] = {
- .flags = FL_BASE2,
- .num_ports = 4,
- .base_baud = 115200,
- .uart_offset = 8,
- },
-
/* I think this entry is broken - the first_offset looks wrong --rmk */
[pbn_plx_romulus] = {
.flags = FL_BASE2,
@@ -2624,10 +2674,14 @@
},
};
-static const struct pci_device_id softmodem_blacklist[] = {
+static const struct pci_device_id blacklist[] = {
+ /* softmodems */
{ PCI_VDEVICE(AL, 0x5457), }, /* ALi Corporation M5457 AC'97 Modem */
{ PCI_VDEVICE(MOTOROLA, 0x3052), }, /* Motorola Si3052-based modem */
{ PCI_DEVICE(0x1543, 0x3052), }, /* Si3052-based modem, default IDs */
+
+ /* multi-io cards handled by parport_serial */
+ { PCI_DEVICE(0x4348, 0x7053), }, /* WCH CH353 2S1P */
};
/*
@@ -2638,7 +2692,7 @@
static int __devinit
serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
{
- const struct pci_device_id *blacklist;
+ const struct pci_device_id *bldev;
int num_iomem, num_port, first_port = -1, i;
/*
@@ -2655,13 +2709,13 @@
/*
* Do not access blacklisted devices that are known not to
- * feature serial ports.
+ * feature serial ports or are handled by other modules.
*/
- for (blacklist = softmodem_blacklist;
- blacklist < softmodem_blacklist + ARRAY_SIZE(softmodem_blacklist);
- blacklist++) {
- if (dev->vendor == blacklist->vendor &&
- dev->device == blacklist->device)
+ for (bldev = blacklist;
+ bldev < blacklist + ARRAY_SIZE(blacklist);
+ bldev++) {
+ if (dev->vendor == bldev->vendor &&
+ dev->device == bldev->device)
return -ENODEV;
}
@@ -2728,7 +2782,7 @@
struct serial_private *
pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
{
- struct uart_port serial_port;
+ struct uart_8250_port uart;
struct serial_private *priv;
struct pci_serial_quirk *quirk;
int rc, nr_ports, i;
@@ -2768,22 +2822,22 @@
priv->dev = dev;
priv->quirk = quirk;
- memset(&serial_port, 0, sizeof(struct uart_port));
- serial_port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
- serial_port.uartclk = board->base_baud * 16;
- serial_port.irq = get_pci_irq(dev, board);
- serial_port.dev = &dev->dev;
+ memset(&uart, 0, sizeof(uart));
+ uart.port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+ uart.port.uartclk = board->base_baud * 16;
+ uart.port.irq = get_pci_irq(dev, board);
+ uart.port.dev = &dev->dev;
for (i = 0; i < nr_ports; i++) {
- if (quirk->setup(priv, board, &serial_port, i))
+ if (quirk->setup(priv, board, &uart, i))
break;
#ifdef SERIAL_DEBUG_PCI
printk(KERN_DEBUG "Setup PCI port: port %lx, irq %d, type %d\n",
- serial_port.iobase, serial_port.irq, serial_port.iotype);
+ uart.port.iobase, uart.port.irq, uart.port.iotype);
#endif
- priv->line[i] = serial8250_register_port(&serial_port);
+ priv->line[i] = serial8250_register_8250_port(&uart);
if (priv->line[i] < 0) {
printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), priv->line[i]);
break;
@@ -3193,7 +3247,7 @@
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
PCI_SUBVENDOR_ID_EXSYS,
PCI_SUBDEVICE_ID_EXSYS_4055, 0, 0,
- pbn_exsys_4055 },
+ pbn_b2_4_115200 },
/*
* Megawolf Romulus PCI Serial Card, from Mike Hudson
* (Exoray@isys.ca)
@@ -4179,6 +4233,25 @@
pbn_omegapci },
/*
+ * AgeStar as-prs2-009
+ */
+ { PCI_VENDOR_ID_AGESTAR, PCI_DEVICE_ID_AGESTAR_9375,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0, pbn_b0_bt_2_115200 },
+
+ /*
+ * WCH CH353 series devices: The 2S1P is handled by parport_serial
+ * so not listed here.
+ */
+ { PCI_VENDOR_ID_WCH, PCI_DEVICE_ID_WCH_CH353_4S,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0, pbn_b0_bt_4_115200 },
+
+ { PCI_VENDOR_ID_WCH, PCI_DEVICE_ID_WCH_CH353_2S1PF,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0, pbn_b0_bt_2_115200 },
+
+ /*
* These entries match devices with class COMMUNICATION_SERIAL,
* COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
*/
diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c
index a2f2365..fde5aa6 100644
--- a/drivers/tty/serial/8250/8250_pnp.c
+++ b/drivers/tty/serial/8250/8250_pnp.c
@@ -424,7 +424,7 @@
static int __devinit
serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
{
- struct uart_port port;
+ struct uart_8250_port uart;
int ret, line, flags = dev_id->driver_data;
if (flags & UNKNOWN_DEV) {
@@ -433,32 +433,32 @@
return ret;
}
- memset(&port, 0, sizeof(struct uart_port));
+ memset(&uart, 0, sizeof(uart));
if (pnp_irq_valid(dev, 0))
- port.irq = pnp_irq(dev, 0);
+ uart.port.irq = pnp_irq(dev, 0);
if (pnp_port_valid(dev, 0)) {
- port.iobase = pnp_port_start(dev, 0);
- port.iotype = UPIO_PORT;
+ uart.port.iobase = pnp_port_start(dev, 0);
+ uart.port.iotype = UPIO_PORT;
} else if (pnp_mem_valid(dev, 0)) {
- port.mapbase = pnp_mem_start(dev, 0);
- port.iotype = UPIO_MEM;
- port.flags = UPF_IOREMAP;
+ uart.port.mapbase = pnp_mem_start(dev, 0);
+ uart.port.iotype = UPIO_MEM;
+ uart.port.flags = UPF_IOREMAP;
} else
return -ENODEV;
#ifdef SERIAL_DEBUG_PNP
printk(KERN_DEBUG
"Setup PNP port: port %x, mem 0x%lx, irq %d, type %d\n",
- port.iobase, port.mapbase, port.irq, port.iotype);
+ uart.port.iobase, uart.port.mapbase, uart.port.irq, uart.port.iotype);
#endif
- port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
+ uart.port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
if (pnp_irq_flags(dev, 0) & IORESOURCE_IRQ_SHAREABLE)
- port.flags |= UPF_SHARE_IRQ;
- port.uartclk = 1843200;
- port.dev = &dev->dev;
+ uart.port.flags |= UPF_SHARE_IRQ;
+ uart.port.uartclk = 1843200;
+ uart.port.dev = &dev->dev;
- line = serial8250_register_port(&port);
+ line = serial8250_register_8250_port(&uart);
if (line < 0)
return -ENODEV;
diff --git a/drivers/tty/serial/8250/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c
index 29b695d..b7d48b3 100644
--- a/drivers/tty/serial/8250/serial_cs.c
+++ b/drivers/tty/serial/8250/serial_cs.c
@@ -73,7 +73,7 @@
unsigned int prodid;
int multi; /* 1 = multifunction, > 1 = # ports */
void (*config)(struct pcmcia_device *);
- void (*setup)(struct pcmcia_device *, struct uart_port *);
+ void (*setup)(struct pcmcia_device *, struct uart_8250_port *);
void (*wakeup)(struct pcmcia_device *);
int (*post)(struct pcmcia_device *);
};
@@ -105,9 +105,9 @@
* Elan VPU16551 UART with 14.7456MHz oscillator
* manfid 0x015D, 0x4C45
*/
-static void quirk_setup_brainboxes_0104(struct pcmcia_device *link, struct uart_port *port)
+static void quirk_setup_brainboxes_0104(struct pcmcia_device *link, struct uart_8250_port *uart)
{
- port->uartclk = 14745600;
+ uart->port.uartclk = 14745600;
}
static int quirk_post_ibm(struct pcmcia_device *link)
@@ -343,25 +343,25 @@
static int setup_serial(struct pcmcia_device *handle, struct serial_info * info,
unsigned int iobase, int irq)
{
- struct uart_port port;
+ struct uart_8250_port uart;
int line;
- memset(&port, 0, sizeof (struct uart_port));
- port.iobase = iobase;
- port.irq = irq;
- port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
- port.uartclk = 1843200;
- port.dev = &handle->dev;
+ memset(&uart, 0, sizeof(uart));
+ uart.port.iobase = iobase;
+ uart.port.irq = irq;
+ uart.port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
+ uart.port.uartclk = 1843200;
+ uart.port.dev = &handle->dev;
if (buggy_uart)
- port.flags |= UPF_BUGGY_UART;
+ uart.port.flags |= UPF_BUGGY_UART;
if (info->quirk && info->quirk->setup)
- info->quirk->setup(handle, &port);
+ info->quirk->setup(handle, &uart);
- line = serial8250_register_port(&port);
+ line = serial8250_register_8250_port(&uart);
if (line < 0) {
- printk(KERN_NOTICE "serial_cs: serial8250_register_port() at "
- "0x%04lx, irq %d failed\n", (u_long)iobase, irq);
+ pr_err("serial_cs: serial8250_register_8250_port() at 0x%04lx, irq %d failed\n",
+ (unsigned long)iobase, irq);
return -EINVAL;
}
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 4720b4b..26907cf 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -257,12 +257,19 @@
help
MAX3100 chip support
-config SERIAL_MAX3107
- tristate "MAX3107 support"
+config SERIAL_MAX310X
+ bool "MAX310X support"
depends on SPI
select SERIAL_CORE
+ select REGMAP_SPI if SPI
+ default n
help
- MAX3107 chip support
+ This selects support for an advanced UART from Maxim (Dallas).
+ Supported ICs are MAX3107, MAX3108.
+ Each IC contains 128 words each of receive and transmit FIFO
+ that can be controlled through I2C or high-speed SPI.
+
+ Say Y here if you want to support this ICs.
config SERIAL_DZ
bool "DECstation DZ serial driver"
@@ -704,6 +711,25 @@
If you have a MIPS-based Philips SoC such as PNX8550 or PNX8330
and you want to use serial console, say Y. Otherwise, say N.
+config SERIAL_HS_LPC32XX
+ tristate "LPC32XX high speed serial port support"
+ depends on ARCH_LPC32XX && OF
+ select SERIAL_CORE
+ help
+ Support for the LPC32XX high speed serial ports (up to 900kbps).
+ Those are UARTs completely different from the Standard UARTs on the
+ LPC32XX SoC.
+ Choose M or Y here to build this driver.
+
+config SERIAL_HS_LPC32XX_CONSOLE
+ bool "Enable LPC32XX high speed UART serial console"
+ depends on SERIAL_HS_LPC32XX
+ select SERIAL_CORE_CONSOLE
+ help
+ If you would like to be able to use one of the high speed serial
+ ports on the LPC32XX as the console, you can do so by answering
+ Y to this option.
+
config SERIAL_CORE
tristate
@@ -1104,6 +1130,24 @@
help
Support for Console on SC2681/SC2692 serial ports.
+config SERIAL_SCCNXP
+ bool "SCCNXP serial port support"
+ depends on !SERIAL_SC26XX
+ select SERIAL_CORE
+ default n
+ help
+ This selects support for an advanced UART from NXP (Philips).
+ Supported ICs are SCC2681, SCC2691, SCC2692, SC28L91, SC28L92,
+ SC28L202, SCC68681 and SCC68692.
+ Positioned as a replacement for the driver SC26XX.
+
+config SERIAL_SCCNXP_CONSOLE
+ bool "Console on SCCNXP serial port"
+ depends on SERIAL_SCCNXP
+ select SERIAL_CORE_CONSOLE
+ help
+ Support for console on SCCNXP serial ports.
+
config SERIAL_BFIN_SPORT
tristate "Blackfin SPORT emulate UART"
depends on BLACKFIN
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 7257c5d..ce88667 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -28,12 +28,13 @@
obj-$(CONFIG_SERIAL_BFIN_SPORT) += bfin_sport_uart.o
obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o
obj-$(CONFIG_SERIAL_MAX3100) += max3100.o
-obj-$(CONFIG_SERIAL_MAX3107) += max3107.o
+obj-$(CONFIG_SERIAL_MAX310X) += max310x.o
obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
obj-$(CONFIG_SERIAL_MUX) += mux.o
obj-$(CONFIG_SERIAL_68328) += 68328serial.o
obj-$(CONFIG_SERIAL_MCF) += mcf.o
obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o
+obj-$(CONFIG_SERIAL_HS_LPC32XX) += lpc32xx_hs.o
obj-$(CONFIG_SERIAL_DZ) += dz.o
obj-$(CONFIG_SERIAL_ZS) += zs.o
obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o
@@ -47,6 +48,7 @@
obj-$(CONFIG_SERIAL_SB1250_DUART) += sb1250-duart.o
obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o
obj-$(CONFIG_SERIAL_SC26XX) += sc26xx.o
+obj-$(CONFIG_SERIAL_SCCNXP) += sccnxp.o
obj-$(CONFIG_SERIAL_JSM) += jsm/
obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c
index 1f03309..15d80b9 100644
--- a/drivers/tty/serial/altera_uart.c
+++ b/drivers/tty/serial/altera_uart.c
@@ -591,7 +591,7 @@
port->ops = &altera_uart_ops;
port->flags = UPF_BOOT_AUTOCONF;
- dev_set_drvdata(&pdev->dev, port);
+ platform_set_drvdata(pdev, port);
uart_add_one_port(&altera_uart_driver, port);
@@ -600,11 +600,11 @@
static int __devexit altera_uart_remove(struct platform_device *pdev)
{
- struct uart_port *port = dev_get_drvdata(&pdev->dev);
+ struct uart_port *port = platform_get_drvdata(pdev);
if (port) {
uart_remove_one_port(&altera_uart_driver, port);
- dev_set_drvdata(&pdev->dev, NULL);
+ platform_set_drvdata(pdev, NULL);
port->mapbase = 0;
}
diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c
index 0d91a54..22317dd 100644
--- a/drivers/tty/serial/amba-pl010.c
+++ b/drivers/tty/serial/amba-pl010.c
@@ -312,16 +312,12 @@
struct uart_amba_port *uap = (struct uart_amba_port *)port;
int retval;
- retval = clk_prepare(uap->clk);
- if (retval)
- goto out;
-
/*
* Try to enable the clock producer.
*/
- retval = clk_enable(uap->clk);
+ retval = clk_prepare_enable(uap->clk);
if (retval)
- goto clk_unprep;
+ goto out;
uap->port.uartclk = clk_get_rate(uap->clk);
@@ -346,9 +342,7 @@
return 0;
clk_dis:
- clk_disable(uap->clk);
- clk_unprep:
- clk_unprepare(uap->clk);
+ clk_disable_unprepare(uap->clk);
out:
return retval;
}
@@ -375,8 +369,7 @@
/*
* Shut down the clock producer
*/
- clk_disable(uap->clk);
- clk_unprepare(uap->clk);
+ clk_disable_unprepare(uap->clk);
}
static void
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index d3553b5..cede938 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -52,6 +52,8 @@
#include <linux/scatterlist.h>
#include <linux/delay.h>
#include <linux/types.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/sizes.h>
@@ -75,7 +77,6 @@
unsigned int lcrh_tx;
unsigned int lcrh_rx;
bool oversampling;
- bool interrupt_may_hang; /* vendor-specific */
bool dma_threshold;
bool cts_event_workaround;
};
@@ -96,7 +97,6 @@
.lcrh_tx = ST_UART011_LCRH_TX,
.lcrh_rx = ST_UART011_LCRH_RX,
.oversampling = true,
- .interrupt_may_hang = true,
.dma_threshold = true,
.cts_event_workaround = true,
};
@@ -147,7 +147,6 @@
unsigned int old_cr; /* state during shutdown */
bool autorts;
char type[12];
- bool interrupt_may_hang; /* vendor-specific */
#ifdef CONFIG_DMA_ENGINE
/* DMA stuff */
bool using_tx_dma;
@@ -1215,14 +1214,14 @@
return IRQ_RETVAL(handled);
}
-static unsigned int pl01x_tx_empty(struct uart_port *port)
+static unsigned int pl011_tx_empty(struct uart_port *port)
{
struct uart_amba_port *uap = (struct uart_amba_port *)port;
unsigned int status = readw(uap->port.membase + UART01x_FR);
return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT;
}
-static unsigned int pl01x_get_mctrl(struct uart_port *port)
+static unsigned int pl011_get_mctrl(struct uart_port *port)
{
struct uart_amba_port *uap = (struct uart_amba_port *)port;
unsigned int result = 0;
@@ -1285,7 +1284,7 @@
}
#ifdef CONFIG_CONSOLE_POLL
-static int pl010_get_poll_char(struct uart_port *port)
+static int pl011_get_poll_char(struct uart_port *port)
{
struct uart_amba_port *uap = (struct uart_amba_port *)port;
unsigned int status;
@@ -1297,7 +1296,7 @@
return readw(uap->port.membase + UART01x_DR);
}
-static void pl010_put_poll_char(struct uart_port *port,
+static void pl011_put_poll_char(struct uart_port *port,
unsigned char ch)
{
struct uart_amba_port *uap = (struct uart_amba_port *)port;
@@ -1324,16 +1323,12 @@
"could not set default pins\n");
}
- retval = clk_prepare(uap->clk);
- if (retval)
- goto out;
-
/*
* Try to enable the clock producer.
*/
- retval = clk_enable(uap->clk);
+ retval = clk_prepare_enable(uap->clk);
if (retval)
- goto clk_unprep;
+ goto out;
uap->port.uartclk = clk_get_rate(uap->clk);
@@ -1411,9 +1406,7 @@
return 0;
clk_dis:
- clk_disable(uap->clk);
- clk_unprep:
- clk_unprepare(uap->clk);
+ clk_disable_unprepare(uap->clk);
out:
return retval;
}
@@ -1473,8 +1466,7 @@
/*
* Shut down the clock producer
*/
- clk_disable(uap->clk);
- clk_unprepare(uap->clk);
+ clk_disable_unprepare(uap->clk);
/* Optionally let pins go into sleep states */
if (!IS_ERR(uap->pins_sleep)) {
retval = pinctrl_select_state(uap->pinctrl, uap->pins_sleep);
@@ -1637,7 +1629,7 @@
/*
* Release the memory region(s) being used by 'port'
*/
-static void pl010_release_port(struct uart_port *port)
+static void pl011_release_port(struct uart_port *port)
{
release_mem_region(port->mapbase, SZ_4K);
}
@@ -1645,7 +1637,7 @@
/*
* Request the memory region(s) being used by 'port'
*/
-static int pl010_request_port(struct uart_port *port)
+static int pl011_request_port(struct uart_port *port)
{
return request_mem_region(port->mapbase, SZ_4K, "uart-pl011")
!= NULL ? 0 : -EBUSY;
@@ -1654,18 +1646,18 @@
/*
* Configure/autoconfigure the port.
*/
-static void pl010_config_port(struct uart_port *port, int flags)
+static void pl011_config_port(struct uart_port *port, int flags)
{
if (flags & UART_CONFIG_TYPE) {
port->type = PORT_AMBA;
- pl010_request_port(port);
+ pl011_request_port(port);
}
}
/*
* verify the new serial_struct (for TIOCSSERIAL).
*/
-static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser)
+static int pl011_verify_port(struct uart_port *port, struct serial_struct *ser)
{
int ret = 0;
if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
@@ -1678,9 +1670,9 @@
}
static struct uart_ops amba_pl011_pops = {
- .tx_empty = pl01x_tx_empty,
+ .tx_empty = pl011_tx_empty,
.set_mctrl = pl011_set_mctrl,
- .get_mctrl = pl01x_get_mctrl,
+ .get_mctrl = pl011_get_mctrl,
.stop_tx = pl011_stop_tx,
.start_tx = pl011_start_tx,
.stop_rx = pl011_stop_rx,
@@ -1691,13 +1683,13 @@
.flush_buffer = pl011_dma_flush_buffer,
.set_termios = pl011_set_termios,
.type = pl011_type,
- .release_port = pl010_release_port,
- .request_port = pl010_request_port,
- .config_port = pl010_config_port,
- .verify_port = pl010_verify_port,
+ .release_port = pl011_release_port,
+ .request_port = pl011_request_port,
+ .config_port = pl011_config_port,
+ .verify_port = pl011_verify_port,
#ifdef CONFIG_CONSOLE_POLL
- .poll_get_char = pl010_get_poll_char,
- .poll_put_char = pl010_put_poll_char,
+ .poll_get_char = pl011_get_poll_char,
+ .poll_put_char = pl011_put_poll_char,
#endif
};
@@ -1869,6 +1861,38 @@
.cons = AMBA_CONSOLE,
};
+static int pl011_probe_dt_alias(int index, struct device *dev)
+{
+ struct device_node *np;
+ static bool seen_dev_with_alias = false;
+ static bool seen_dev_without_alias = false;
+ int ret = index;
+
+ if (!IS_ENABLED(CONFIG_OF))
+ return ret;
+
+ np = dev->of_node;
+ if (!np)
+ return ret;
+
+ ret = of_alias_get_id(np, "serial");
+ if (IS_ERR_VALUE(ret)) {
+ seen_dev_without_alias = true;
+ ret = index;
+ } else {
+ seen_dev_with_alias = true;
+ if (ret >= ARRAY_SIZE(amba_ports) || amba_ports[ret] != NULL) {
+ dev_warn(dev, "requested serial port %d not available.\n", ret);
+ ret = index;
+ }
+ }
+
+ if (seen_dev_with_alias && seen_dev_without_alias)
+ dev_warn(dev, "aliased and non-aliased serial devices found in device tree. Serial port enumeration may be unpredictable.\n");
+
+ return ret;
+}
+
static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
{
struct uart_amba_port *uap;
@@ -1891,6 +1915,8 @@
goto out;
}
+ i = pl011_probe_dt_alias(i, &dev->dev);
+
base = ioremap(dev->res.start, resource_size(&dev->res));
if (!base) {
ret = -ENOMEM;
@@ -1923,7 +1949,6 @@
uap->lcrh_tx = vendor->lcrh_tx;
uap->old_cr = 0;
uap->fifosize = vendor->fifosize;
- uap->interrupt_may_hang = vendor->interrupt_may_hang;
uap->port.dev = &dev->dev;
uap->port.mapbase = dev->res.start;
uap->port.membase = base;
diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c
index bd97db2..9242d56 100644
--- a/drivers/tty/serial/bfin_uart.c
+++ b/drivers/tty/serial/bfin_uart.c
@@ -182,7 +182,7 @@
* To avoid losting RX interrupt, we reset IR function
* before sending data.
*/
- if (tty->termios->c_line == N_IRDA)
+ if (tty->termios.c_line == N_IRDA)
bfin_serial_reset_irda(port);
#ifdef CONFIG_SERIAL_BFIN_DMA
diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c
index 80b6b1b..35ee6a2 100644
--- a/drivers/tty/serial/crisv10.c
+++ b/drivers/tty/serial/crisv10.c
@@ -955,7 +955,7 @@
/* Calculate the chartime depending on baudrate, numbor of bits etc. */
static void update_char_time(struct e100_serial * info)
{
- tcflag_t cflags = info->port.tty->termios->c_cflag;
+ tcflag_t cflags = info->port.tty->termios.c_cflag;
int bits;
/* calc. number of bits / data byte */
@@ -1473,7 +1473,7 @@
xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char,
STOP_CHAR(info->port.tty));
xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, stop);
- if (tty->termios->c_iflag & IXON ) {
+ if (tty->termios.c_iflag & IXON ) {
xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable);
}
@@ -1496,7 +1496,7 @@
info->xmit.tail,SERIAL_XMIT_SIZE)));
xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(tty));
xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, enable);
- if (tty->termios->c_iflag & IXON ) {
+ if (tty->termios.c_iflag & IXON ) {
xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable);
}
@@ -2929,7 +2929,7 @@
descr[i].buf = 0;
}
- if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) {
+ if (!info->port.tty || (info->port.tty->termios.c_cflag & HUPCL)) {
/* hang up DTR and RTS if HUPCL is enabled */
e100_dtr(info, 0);
e100_rts(info, 0); /* could check CRTSCTS before doing this */
@@ -2953,12 +2953,12 @@
unsigned long flags;
/* first some safety checks */
- if (!info->port.tty || !info->port.tty->termios)
+ if (!info->port.tty)
return;
if (!info->ioport)
return;
- cflag = info->port.tty->termios->c_cflag;
+ cflag = info->port.tty->termios.c_cflag;
/* possibly, the tx/rx should be disabled first to do this safely */
@@ -3088,7 +3088,7 @@
info->ioport[REG_REC_CTRL] = info->rx_ctrl;
xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(info->port.tty));
xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, enable);
- if (info->port.tty->termios->c_iflag & IXON ) {
+ if (info->port.tty->termios.c_iflag & IXON ) {
DFLOW(DEBUG_LOG(info->line, "FLOW XOFF enabled 0x%02X\n",
STOP_CHAR(info->port.tty)));
xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable);
@@ -3355,7 +3355,7 @@
DFLOW(DEBUG_LOG(info->line,"rs_throttle %lu\n", tty->ldisc.chars_in_buffer(tty)));
/* Do RTS before XOFF since XOFF might take some time */
- if (tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios.c_cflag & CRTSCTS) {
/* Turn off RTS line */
e100_rts(info, 0);
}
@@ -3377,7 +3377,7 @@
DFLOW(DEBUG_LOG(info->line,"rs_unthrottle ldisc %d\n", tty->ldisc.chars_in_buffer(tty)));
DFLOW(DEBUG_LOG(info->line,"rs_unthrottle flip.count: %i\n", tty->flip.count));
/* Do RTS before XOFF since XOFF might take some time */
- if (tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios.c_cflag & CRTSCTS) {
/* Assert RTS line */
e100_rts(info, 1);
}
@@ -3748,7 +3748,7 @@
/* Handle turning off CRTSCTS */
if ((old_termios->c_cflag & CRTSCTS) &&
- !(tty->termios->c_cflag & CRTSCTS)) {
+ !(tty->termios.c_cflag & CRTSCTS)) {
tty->hw_stopped = 0;
rs_start(tty);
}
@@ -3815,7 +3815,7 @@
* separate termios for callout and dialin.
*/
if (info->flags & ASYNC_NORMAL_ACTIVE)
- info->normal_termios = *tty->termios;
+ 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.
@@ -3976,7 +3976,7 @@
*/
if (tty_hung_up_p(filp) ||
(info->flags & ASYNC_CLOSING)) {
- wait_event_interruptible_tty(info->close_wait,
+ wait_event_interruptible_tty(tty, info->close_wait,
!(info->flags & ASYNC_CLOSING));
#ifdef SERIAL_DO_RESTART
if (info->flags & ASYNC_HUP_NOTIFY)
@@ -3998,7 +3998,7 @@
return 0;
}
- if (tty->termios->c_cflag & CLOCAL) {
+ if (tty->termios.c_cflag & CLOCAL) {
do_clocal = 1;
}
@@ -4052,9 +4052,9 @@
printk("block_til_ready blocking: ttyS%d, count = %d\n",
info->line, info->count);
#endif
- tty_unlock();
+ tty_unlock(tty);
schedule();
- tty_lock();
+ tty_lock(tty);
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&info->open_wait, &wait);
@@ -4115,7 +4115,7 @@
*/
if (tty_hung_up_p(filp) ||
(info->flags & ASYNC_CLOSING)) {
- wait_event_interruptible_tty(info->close_wait,
+ wait_event_interruptible_tty(tty, info->close_wait,
!(info->flags & ASYNC_CLOSING));
#ifdef SERIAL_DO_RESTART
return ((info->flags & ASYNC_HUP_NOTIFY) ?
@@ -4219,7 +4219,7 @@
}
if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
- *tty->termios = info->normal_termios;
+ tty->termios = info->normal_termios;
change_speed(info);
}
@@ -4443,14 +4443,12 @@
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->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(driver, &rs_ops);
serial_driver = driver;
- if (tty_register_driver(driver))
- panic("Couldn't register serial driver\n");
- /* do some initializing for the separate ports */
+ /* do some initializing for the separate ports */
for (i = 0, info = rs_table; i < NR_PORTS; i++,info++) {
if (info->enabled) {
if (cris_request_io_interface(info->io_if,
@@ -4502,7 +4500,12 @@
printk(KERN_INFO "%s%d at %p is a builtin UART with DMA\n",
serial_driver->name, info->line, info->ioport);
}
+ tty_port_link_device(&info->port, driver, i);
}
+
+ if (tty_register_driver(driver))
+ panic("Couldn't register serial driver\n");
+
#ifdef CONFIG_ETRAX_FAST_TIMER
#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER
memset(fast_timers, 0, sizeof(fast_timers));
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c
index 3ad079f..5b9bc19 100644
--- a/drivers/tty/serial/ifx6x60.c
+++ b/drivers/tty/serial/ifx6x60.c
@@ -800,8 +800,8 @@
tty_port_init(pport);
pport->ops = &ifx_tty_port_ops;
ifx_dev->minor = IFX_SPI_TTY_ID;
- ifx_dev->tty_dev = tty_register_device(tty_drv, ifx_dev->minor,
- &ifx_dev->spi_dev->dev);
+ ifx_dev->tty_dev = tty_port_register_device(pport, tty_drv,
+ ifx_dev->minor, &ifx_dev->spi_dev->dev);
if (IS_ERR(ifx_dev->tty_dev)) {
dev_dbg(&ifx_dev->spi_dev->dev,
"%s: registering tty device failed", __func__);
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index d5c689d6..72ec56e 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -206,7 +206,7 @@
unsigned short trcv_delay; /* transceiver delay */
struct clk *clk_ipg;
struct clk *clk_per;
- struct imx_uart_data *devdata;
+ const struct imx_uart_data *devdata;
};
struct imx_port_ucrs {
@@ -1505,18 +1505,21 @@
pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
if (IS_ERR(pinctrl)) {
ret = PTR_ERR(pinctrl);
+ dev_err(&pdev->dev, "failed to get default pinctrl: %d\n", ret);
goto unmap;
}
sport->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
if (IS_ERR(sport->clk_ipg)) {
ret = PTR_ERR(sport->clk_ipg);
+ dev_err(&pdev->dev, "failed to get ipg clk: %d\n", ret);
goto unmap;
}
sport->clk_per = devm_clk_get(&pdev->dev, "per");
if (IS_ERR(sport->clk_per)) {
ret = PTR_ERR(sport->clk_per);
+ dev_err(&pdev->dev, "failed to get per clk: %d\n", ret);
goto unmap;
}
diff --git a/drivers/tty/serial/ioc3_serial.c b/drivers/tty/serial/ioc3_serial.c
index 758ff310..5ac5289 100644
--- a/drivers/tty/serial/ioc3_serial.c
+++ b/drivers/tty/serial/ioc3_serial.c
@@ -1120,13 +1120,14 @@
struct ioc3_port *port = get_ioc3_port(the_port);
struct ring *inring;
struct ring_entry *entry;
- struct port_hooks *hooks = port->ip_hooks;
+ struct port_hooks *hooks;
int byte_num;
char *sc;
int loop_counter;
BUG_ON(!(len >= 0));
BUG_ON(!port);
+ hooks = port->ip_hooks;
/* There is a nasty timing issue in the IOC3. When the rx_timer
* expires or the rx_high condition arises, we take an interrupt.
diff --git a/drivers/tty/serial/ioc4_serial.c b/drivers/tty/serial/ioc4_serial.c
index e16894f..3e7da10 100644
--- a/drivers/tty/serial/ioc4_serial.c
+++ b/drivers/tty/serial/ioc4_serial.c
@@ -1803,7 +1803,7 @@
ioc4_set_proto(port, the_port->mapbase);
/* set the speed of the serial port */
- ioc4_change_speed(the_port, state->port.tty->termios,
+ ioc4_change_speed(the_port, &state->port.tty->termios,
(struct ktermios *)0);
return 0;
@@ -2069,13 +2069,14 @@
struct ioc4_port *port = get_ioc4_port(the_port, 0);
struct ring *inring;
struct ring_entry *entry;
- struct hooks *hooks = port->ip_hooks;
+ struct hooks *hooks;
int byte_num;
char *sc;
int loop_counter;
BUG_ON(!(len >= 0));
BUG_ON(!port);
+ hooks = port->ip_hooks;
/* There is a nasty timing issue in the IOC4. When the rx_timer
* expires or the rx_high condition arises, we take an interrupt.
diff --git a/drivers/tty/serial/jsm/jsm_tty.c b/drivers/tty/serial/jsm/jsm_tty.c
index 434bd88..7139796 100644
--- a/drivers/tty/serial/jsm/jsm_tty.c
+++ b/drivers/tty/serial/jsm/jsm_tty.c
@@ -161,7 +161,7 @@
struct ktermios *termios;
spin_lock_irqsave(&port->lock, lock_flags);
- termios = port->state->port.tty->termios;
+ termios = &port->state->port.tty->termios;
if (ch == termios->c_cc[VSTART])
channel->ch_bd->bd_ops->send_start_character(channel);
@@ -250,7 +250,7 @@
channel->ch_cached_lsr = 0;
channel->ch_stops_sent = 0;
- termios = port->state->port.tty->termios;
+ termios = &port->state->port.tty->termios;
channel->ch_c_cflag = termios->c_cflag;
channel->ch_c_iflag = termios->c_iflag;
channel->ch_c_oflag = termios->c_oflag;
@@ -283,7 +283,7 @@
jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "start\n");
bd = channel->ch_bd;
- ts = port->state->port.tty->termios;
+ ts = &port->state->port.tty->termios;
channel->ch_flags &= ~(CH_STOPI);
@@ -567,7 +567,7 @@
*input data and return immediately.
*/
if (!tp ||
- !(tp->termios->c_cflag & CREAD) ) {
+ !(tp->termios.c_cflag & CREAD) ) {
jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
"input. dropping %d bytes on port %d...\n", data_len, ch->ch_portnum);
diff --git a/drivers/tty/serial/lpc32xx_hs.c b/drivers/tty/serial/lpc32xx_hs.c
new file mode 100644
index 0000000..ba3af3b
--- /dev/null
+++ b/drivers/tty/serial/lpc32xx_hs.c
@@ -0,0 +1,823 @@
+/*
+ * High Speed Serial Ports on NXP LPC32xx SoC
+ *
+ * Authors: Kevin Wells <kevin.wells@nxp.com>
+ * Roland Stigge <stigge@antcom.de>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ * Copyright (C) 2012 Roland Stigge
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/nmi.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <mach/platform.h>
+#include <mach/hardware.h>
+
+/*
+ * High Speed UART register offsets
+ */
+#define LPC32XX_HSUART_FIFO(x) ((x) + 0x00)
+#define LPC32XX_HSUART_LEVEL(x) ((x) + 0x04)
+#define LPC32XX_HSUART_IIR(x) ((x) + 0x08)
+#define LPC32XX_HSUART_CTRL(x) ((x) + 0x0C)
+#define LPC32XX_HSUART_RATE(x) ((x) + 0x10)
+
+#define LPC32XX_HSU_BREAK_DATA (1 << 10)
+#define LPC32XX_HSU_ERROR_DATA (1 << 9)
+#define LPC32XX_HSU_RX_EMPTY (1 << 8)
+
+#define LPC32XX_HSU_TX_LEV(n) (((n) >> 8) & 0xFF)
+#define LPC32XX_HSU_RX_LEV(n) ((n) & 0xFF)
+
+#define LPC32XX_HSU_TX_INT_SET (1 << 6)
+#define LPC32XX_HSU_RX_OE_INT (1 << 5)
+#define LPC32XX_HSU_BRK_INT (1 << 4)
+#define LPC32XX_HSU_FE_INT (1 << 3)
+#define LPC32XX_HSU_RX_TIMEOUT_INT (1 << 2)
+#define LPC32XX_HSU_RX_TRIG_INT (1 << 1)
+#define LPC32XX_HSU_TX_INT (1 << 0)
+
+#define LPC32XX_HSU_HRTS_INV (1 << 21)
+#define LPC32XX_HSU_HRTS_TRIG_8B (0x0 << 19)
+#define LPC32XX_HSU_HRTS_TRIG_16B (0x1 << 19)
+#define LPC32XX_HSU_HRTS_TRIG_32B (0x2 << 19)
+#define LPC32XX_HSU_HRTS_TRIG_48B (0x3 << 19)
+#define LPC32XX_HSU_HRTS_EN (1 << 18)
+#define LPC32XX_HSU_TMO_DISABLED (0x0 << 16)
+#define LPC32XX_HSU_TMO_INACT_4B (0x1 << 16)
+#define LPC32XX_HSU_TMO_INACT_8B (0x2 << 16)
+#define LPC32XX_HSU_TMO_INACT_16B (0x3 << 16)
+#define LPC32XX_HSU_HCTS_INV (1 << 15)
+#define LPC32XX_HSU_HCTS_EN (1 << 14)
+#define LPC32XX_HSU_OFFSET(n) ((n) << 9)
+#define LPC32XX_HSU_BREAK (1 << 8)
+#define LPC32XX_HSU_ERR_INT_EN (1 << 7)
+#define LPC32XX_HSU_RX_INT_EN (1 << 6)
+#define LPC32XX_HSU_TX_INT_EN (1 << 5)
+#define LPC32XX_HSU_RX_TL1B (0x0 << 2)
+#define LPC32XX_HSU_RX_TL4B (0x1 << 2)
+#define LPC32XX_HSU_RX_TL8B (0x2 << 2)
+#define LPC32XX_HSU_RX_TL16B (0x3 << 2)
+#define LPC32XX_HSU_RX_TL32B (0x4 << 2)
+#define LPC32XX_HSU_RX_TL48B (0x5 << 2)
+#define LPC32XX_HSU_TX_TLEMPTY (0x0 << 0)
+#define LPC32XX_HSU_TX_TL0B (0x0 << 0)
+#define LPC32XX_HSU_TX_TL4B (0x1 << 0)
+#define LPC32XX_HSU_TX_TL8B (0x2 << 0)
+#define LPC32XX_HSU_TX_TL16B (0x3 << 0)
+
+#define MODNAME "lpc32xx_hsuart"
+
+struct lpc32xx_hsuart_port {
+ struct uart_port port;
+};
+
+#define FIFO_READ_LIMIT 128
+#define MAX_PORTS 3
+#define LPC32XX_TTY_NAME "ttyTX"
+static struct lpc32xx_hsuart_port lpc32xx_hs_ports[MAX_PORTS];
+
+#ifdef CONFIG_SERIAL_HS_LPC32XX_CONSOLE
+static void wait_for_xmit_empty(struct uart_port *port)
+{
+ unsigned int timeout = 10000;
+
+ do {
+ if (LPC32XX_HSU_TX_LEV(readl(LPC32XX_HSUART_LEVEL(
+ port->membase))) == 0)
+ break;
+ if (--timeout == 0)
+ break;
+ udelay(1);
+ } while (1);
+}
+
+static void wait_for_xmit_ready(struct uart_port *port)
+{
+ unsigned int timeout = 10000;
+
+ while (1) {
+ if (LPC32XX_HSU_TX_LEV(readl(LPC32XX_HSUART_LEVEL(
+ port->membase))) < 32)
+ break;
+ if (--timeout == 0)
+ break;
+ udelay(1);
+ }
+}
+
+static void lpc32xx_hsuart_console_putchar(struct uart_port *port, int ch)
+{
+ wait_for_xmit_ready(port);
+ writel((u32)ch, LPC32XX_HSUART_FIFO(port->membase));
+}
+
+static void lpc32xx_hsuart_console_write(struct console *co, const char *s,
+ unsigned int count)
+{
+ struct lpc32xx_hsuart_port *up = &lpc32xx_hs_ports[co->index];
+ unsigned long flags;
+ int locked = 1;
+
+ touch_nmi_watchdog();
+ local_irq_save(flags);
+ if (up->port.sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+ locked = spin_trylock(&up->port.lock);
+ else
+ spin_lock(&up->port.lock);
+
+ uart_console_write(&up->port, s, count, lpc32xx_hsuart_console_putchar);
+ wait_for_xmit_empty(&up->port);
+
+ if (locked)
+ spin_unlock(&up->port.lock);
+ local_irq_restore(flags);
+}
+
+static int __init lpc32xx_hsuart_console_setup(struct console *co,
+ char *options)
+{
+ struct uart_port *port;
+ int baud = 115200;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+
+ if (co->index >= MAX_PORTS)
+ co->index = 0;
+
+ port = &lpc32xx_hs_ports[co->index].port;
+ if (!port->membase)
+ return -ENODEV;
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+ return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+static struct uart_driver lpc32xx_hsuart_reg;
+static struct console lpc32xx_hsuart_console = {
+ .name = LPC32XX_TTY_NAME,
+ .write = lpc32xx_hsuart_console_write,
+ .device = uart_console_device,
+ .setup = lpc32xx_hsuart_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &lpc32xx_hsuart_reg,
+};
+
+static int __init lpc32xx_hsuart_console_init(void)
+{
+ register_console(&lpc32xx_hsuart_console);
+ return 0;
+}
+console_initcall(lpc32xx_hsuart_console_init);
+
+#define LPC32XX_HSUART_CONSOLE (&lpc32xx_hsuart_console)
+#else
+#define LPC32XX_HSUART_CONSOLE NULL
+#endif
+
+static struct uart_driver lpc32xx_hs_reg = {
+ .owner = THIS_MODULE,
+ .driver_name = MODNAME,
+ .dev_name = LPC32XX_TTY_NAME,
+ .nr = MAX_PORTS,
+ .cons = LPC32XX_HSUART_CONSOLE,
+};
+static int uarts_registered;
+
+static unsigned int __serial_get_clock_div(unsigned long uartclk,
+ unsigned long rate)
+{
+ u32 div, goodrate, hsu_rate, l_hsu_rate, comprate;
+ u32 rate_diff;
+
+ /* Find the closest divider to get the desired clock rate */
+ div = uartclk / rate;
+ goodrate = hsu_rate = (div / 14) - 1;
+ if (hsu_rate != 0)
+ hsu_rate--;
+
+ /* Tweak divider */
+ l_hsu_rate = hsu_rate + 3;
+ rate_diff = 0xFFFFFFFF;
+
+ while (hsu_rate < l_hsu_rate) {
+ comprate = uartclk / ((hsu_rate + 1) * 14);
+ if (abs(comprate - rate) < rate_diff) {
+ goodrate = hsu_rate;
+ rate_diff = abs(comprate - rate);
+ }
+
+ hsu_rate++;
+ }
+ if (hsu_rate > 0xFF)
+ hsu_rate = 0xFF;
+
+ return goodrate;
+}
+
+static void __serial_uart_flush(struct uart_port *port)
+{
+ u32 tmp;
+ int cnt = 0;
+
+ while ((readl(LPC32XX_HSUART_LEVEL(port->membase)) > 0) &&
+ (cnt++ < FIFO_READ_LIMIT))
+ tmp = readl(LPC32XX_HSUART_FIFO(port->membase));
+}
+
+static void __serial_lpc32xx_rx(struct uart_port *port)
+{
+ unsigned int tmp, flag;
+ struct tty_struct *tty = tty_port_tty_get(&port->state->port);
+
+ if (!tty) {
+ /* Discard data: no tty available */
+ while (!(readl(LPC32XX_HSUART_FIFO(port->membase)) &
+ LPC32XX_HSU_RX_EMPTY))
+ ;
+
+ return;
+ }
+
+ /* Read data from FIFO and push into terminal */
+ tmp = readl(LPC32XX_HSUART_FIFO(port->membase));
+ while (!(tmp & LPC32XX_HSU_RX_EMPTY)) {
+ flag = TTY_NORMAL;
+ port->icount.rx++;
+
+ if (tmp & LPC32XX_HSU_ERROR_DATA) {
+ /* Framing error */
+ writel(LPC32XX_HSU_FE_INT,
+ LPC32XX_HSUART_IIR(port->membase));
+ port->icount.frame++;
+ flag = TTY_FRAME;
+ tty_insert_flip_char(tty, 0, TTY_FRAME);
+ }
+
+ tty_insert_flip_char(tty, (tmp & 0xFF), flag);
+
+ tmp = readl(LPC32XX_HSUART_FIFO(port->membase));
+ }
+ tty_flip_buffer_push(tty);
+ tty_kref_put(tty);
+}
+
+static void __serial_lpc32xx_tx(struct uart_port *port)
+{
+ struct circ_buf *xmit = &port->state->xmit;
+ unsigned int tmp;
+
+ if (port->x_char) {
+ writel((u32)port->x_char, LPC32XX_HSUART_FIFO(port->membase));
+ port->icount.tx++;
+ port->x_char = 0;
+ return;
+ }
+
+ if (uart_circ_empty(xmit) || uart_tx_stopped(port))
+ goto exit_tx;
+
+ /* Transfer data */
+ while (LPC32XX_HSU_TX_LEV(readl(
+ LPC32XX_HSUART_LEVEL(port->membase))) < 64) {
+ writel((u32) xmit->buf[xmit->tail],
+ LPC32XX_HSUART_FIFO(port->membase));
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ port->icount.tx++;
+ if (uart_circ_empty(xmit))
+ break;
+ }
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+
+exit_tx:
+ if (uart_circ_empty(xmit)) {
+ tmp = readl(LPC32XX_HSUART_CTRL(port->membase));
+ tmp &= ~LPC32XX_HSU_TX_INT_EN;
+ writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
+ }
+}
+
+static irqreturn_t serial_lpc32xx_interrupt(int irq, void *dev_id)
+{
+ struct uart_port *port = dev_id;
+ struct tty_struct *tty = tty_port_tty_get(&port->state->port);
+ u32 status;
+
+ spin_lock(&port->lock);
+
+ /* Read UART status and clear latched interrupts */
+ status = readl(LPC32XX_HSUART_IIR(port->membase));
+
+ if (status & LPC32XX_HSU_BRK_INT) {
+ /* Break received */
+ writel(LPC32XX_HSU_BRK_INT, LPC32XX_HSUART_IIR(port->membase));
+ port->icount.brk++;
+ uart_handle_break(port);
+ }
+
+ /* Framing error */
+ if (status & LPC32XX_HSU_FE_INT)
+ writel(LPC32XX_HSU_FE_INT, LPC32XX_HSUART_IIR(port->membase));
+
+ if (status & LPC32XX_HSU_RX_OE_INT) {
+ /* Receive FIFO overrun */
+ writel(LPC32XX_HSU_RX_OE_INT,
+ LPC32XX_HSUART_IIR(port->membase));
+ port->icount.overrun++;
+ if (tty) {
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ tty_schedule_flip(tty);
+ }
+ }
+
+ /* Data received? */
+ if (status & (LPC32XX_HSU_RX_TIMEOUT_INT | LPC32XX_HSU_RX_TRIG_INT)) {
+ __serial_lpc32xx_rx(port);
+ if (tty)
+ tty_flip_buffer_push(tty);
+ }
+
+ /* Transmit data request? */
+ if ((status & LPC32XX_HSU_TX_INT) && (!uart_tx_stopped(port))) {
+ writel(LPC32XX_HSU_TX_INT, LPC32XX_HSUART_IIR(port->membase));
+ __serial_lpc32xx_tx(port);
+ }
+
+ spin_unlock(&port->lock);
+ tty_kref_put(tty);
+
+ return IRQ_HANDLED;
+}
+
+/* port->lock is not held. */
+static unsigned int serial_lpc32xx_tx_empty(struct uart_port *port)
+{
+ unsigned int ret = 0;
+
+ if (LPC32XX_HSU_TX_LEV(readl(LPC32XX_HSUART_LEVEL(port->membase))) == 0)
+ ret = TIOCSER_TEMT;
+
+ return ret;
+}
+
+/* port->lock held by caller. */
+static void serial_lpc32xx_set_mctrl(struct uart_port *port,
+ unsigned int mctrl)
+{
+ /* No signals are supported on HS UARTs */
+}
+
+/* port->lock is held by caller and interrupts are disabled. */
+static unsigned int serial_lpc32xx_get_mctrl(struct uart_port *port)
+{
+ /* No signals are supported on HS UARTs */
+ return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+}
+
+/* port->lock held by caller. */
+static void serial_lpc32xx_stop_tx(struct uart_port *port)
+{
+ u32 tmp;
+
+ tmp = readl(LPC32XX_HSUART_CTRL(port->membase));
+ tmp &= ~LPC32XX_HSU_TX_INT_EN;
+ writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
+}
+
+/* port->lock held by caller. */
+static void serial_lpc32xx_start_tx(struct uart_port *port)
+{
+ u32 tmp;
+
+ __serial_lpc32xx_tx(port);
+ tmp = readl(LPC32XX_HSUART_CTRL(port->membase));
+ tmp |= LPC32XX_HSU_TX_INT_EN;
+ writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
+}
+
+/* port->lock held by caller. */
+static void serial_lpc32xx_stop_rx(struct uart_port *port)
+{
+ u32 tmp;
+
+ tmp = readl(LPC32XX_HSUART_CTRL(port->membase));
+ tmp &= ~(LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN);
+ writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
+
+ writel((LPC32XX_HSU_BRK_INT | LPC32XX_HSU_RX_OE_INT |
+ LPC32XX_HSU_FE_INT), LPC32XX_HSUART_IIR(port->membase));
+}
+
+/* port->lock held by caller. */
+static void serial_lpc32xx_enable_ms(struct uart_port *port)
+{
+ /* Modem status is not supported */
+}
+
+/* port->lock is not held. */
+static void serial_lpc32xx_break_ctl(struct uart_port *port,
+ int break_state)
+{
+ unsigned long flags;
+ u32 tmp;
+
+ spin_lock_irqsave(&port->lock, flags);
+ tmp = readl(LPC32XX_HSUART_CTRL(port->membase));
+ if (break_state != 0)
+ tmp |= LPC32XX_HSU_BREAK;
+ else
+ tmp &= ~LPC32XX_HSU_BREAK;
+ writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/* LPC3250 Errata HSUART.1: Hang workaround via loopback mode on inactivity */
+static void lpc32xx_loopback_set(resource_size_t mapbase, int state)
+{
+ int bit;
+ u32 tmp;
+
+ switch (mapbase) {
+ case LPC32XX_HS_UART1_BASE:
+ bit = 0;
+ break;
+ case LPC32XX_HS_UART2_BASE:
+ bit = 1;
+ break;
+ case LPC32XX_HS_UART7_BASE:
+ bit = 6;
+ break;
+ default:
+ WARN(1, "lpc32xx_hs: Warning: Unknown port at %08x\n", mapbase);
+ return;
+ }
+
+ tmp = readl(LPC32XX_UARTCTL_CLOOP);
+ if (state)
+ tmp |= (1 << bit);
+ else
+ tmp &= ~(1 << bit);
+ writel(tmp, LPC32XX_UARTCTL_CLOOP);
+}
+
+/* port->lock is not held. */
+static int serial_lpc32xx_startup(struct uart_port *port)
+{
+ int retval;
+ unsigned long flags;
+ u32 tmp;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ __serial_uart_flush(port);
+
+ writel((LPC32XX_HSU_TX_INT | LPC32XX_HSU_FE_INT |
+ LPC32XX_HSU_BRK_INT | LPC32XX_HSU_RX_OE_INT),
+ LPC32XX_HSUART_IIR(port->membase));
+
+ writel(0xFF, LPC32XX_HSUART_RATE(port->membase));
+
+ /*
+ * Set receiver timeout, HSU offset of 20, no break, no interrupts,
+ * and default FIFO trigger levels
+ */
+ tmp = LPC32XX_HSU_TX_TL8B | LPC32XX_HSU_RX_TL32B |
+ LPC32XX_HSU_OFFSET(20) | LPC32XX_HSU_TMO_INACT_4B;
+ writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
+
+ lpc32xx_loopback_set(port->mapbase, 0); /* get out of loopback mode */
+
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ retval = request_irq(port->irq, serial_lpc32xx_interrupt,
+ 0, MODNAME, port);
+ if (!retval)
+ writel((tmp | LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN),
+ LPC32XX_HSUART_CTRL(port->membase));
+
+ return retval;
+}
+
+/* port->lock is not held. */
+static void serial_lpc32xx_shutdown(struct uart_port *port)
+{
+ u32 tmp;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ tmp = LPC32XX_HSU_TX_TL8B | LPC32XX_HSU_RX_TL32B |
+ LPC32XX_HSU_OFFSET(20) | LPC32XX_HSU_TMO_INACT_4B;
+ writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
+
+ lpc32xx_loopback_set(port->mapbase, 1); /* go to loopback mode */
+
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ free_irq(port->irq, port);
+}
+
+/* port->lock is not held. */
+static void serial_lpc32xx_set_termios(struct uart_port *port,
+ struct ktermios *termios,
+ struct ktermios *old)
+{
+ unsigned long flags;
+ unsigned int baud, quot;
+ u32 tmp;
+
+ /* Always 8-bit, no parity, 1 stop bit */
+ termios->c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD);
+ termios->c_cflag |= CS8;
+
+ termios->c_cflag &= ~(HUPCL | CMSPAR | CLOCAL | CRTSCTS);
+
+ baud = uart_get_baud_rate(port, termios, old, 0,
+ port->uartclk / 14);
+
+ quot = __serial_get_clock_div(port->uartclk, baud);
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ /* Ignore characters? */
+ tmp = readl(LPC32XX_HSUART_CTRL(port->membase));
+ if ((termios->c_cflag & CREAD) == 0)
+ tmp &= ~(LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN);
+ else
+ tmp |= LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN;
+ writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
+
+ writel(quot, LPC32XX_HSUART_RATE(port->membase));
+
+ uart_update_timeout(port, termios->c_cflag, baud);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ /* Don't rewrite B0 */
+ if (tty_termios_baud_rate(termios))
+ tty_termios_encode_baud_rate(termios, baud, baud);
+}
+
+static const char *serial_lpc32xx_type(struct uart_port *port)
+{
+ return MODNAME;
+}
+
+static void serial_lpc32xx_release_port(struct uart_port *port)
+{
+ if ((port->iotype == UPIO_MEM32) && (port->mapbase)) {
+ if (port->flags & UPF_IOREMAP) {
+ iounmap(port->membase);
+ port->membase = NULL;
+ }
+
+ release_mem_region(port->mapbase, SZ_4K);
+ }
+}
+
+static int serial_lpc32xx_request_port(struct uart_port *port)
+{
+ int ret = -ENODEV;
+
+ if ((port->iotype == UPIO_MEM32) && (port->mapbase)) {
+ ret = 0;
+
+ if (!request_mem_region(port->mapbase, SZ_4K, MODNAME))
+ ret = -EBUSY;
+ else if (port->flags & UPF_IOREMAP) {
+ port->membase = ioremap(port->mapbase, SZ_4K);
+ if (!port->membase) {
+ release_mem_region(port->mapbase, SZ_4K);
+ ret = -ENOMEM;
+ }
+ }
+ }
+
+ return ret;
+}
+
+static void serial_lpc32xx_config_port(struct uart_port *port, int uflags)
+{
+ int ret;
+
+ ret = serial_lpc32xx_request_port(port);
+ if (ret < 0)
+ return;
+ port->type = PORT_UART00;
+ port->fifosize = 64;
+
+ __serial_uart_flush(port);
+
+ writel((LPC32XX_HSU_TX_INT | LPC32XX_HSU_FE_INT |
+ LPC32XX_HSU_BRK_INT | LPC32XX_HSU_RX_OE_INT),
+ LPC32XX_HSUART_IIR(port->membase));
+
+ writel(0xFF, LPC32XX_HSUART_RATE(port->membase));
+
+ /* Set receiver timeout, HSU offset of 20, no break, no interrupts,
+ and default FIFO trigger levels */
+ writel(LPC32XX_HSU_TX_TL8B | LPC32XX_HSU_RX_TL32B |
+ LPC32XX_HSU_OFFSET(20) | LPC32XX_HSU_TMO_INACT_4B,
+ LPC32XX_HSUART_CTRL(port->membase));
+}
+
+static int serial_lpc32xx_verify_port(struct uart_port *port,
+ struct serial_struct *ser)
+{
+ int ret = 0;
+
+ if (ser->type != PORT_UART00)
+ ret = -EINVAL;
+
+ return ret;
+}
+
+static struct uart_ops serial_lpc32xx_pops = {
+ .tx_empty = serial_lpc32xx_tx_empty,
+ .set_mctrl = serial_lpc32xx_set_mctrl,
+ .get_mctrl = serial_lpc32xx_get_mctrl,
+ .stop_tx = serial_lpc32xx_stop_tx,
+ .start_tx = serial_lpc32xx_start_tx,
+ .stop_rx = serial_lpc32xx_stop_rx,
+ .enable_ms = serial_lpc32xx_enable_ms,
+ .break_ctl = serial_lpc32xx_break_ctl,
+ .startup = serial_lpc32xx_startup,
+ .shutdown = serial_lpc32xx_shutdown,
+ .set_termios = serial_lpc32xx_set_termios,
+ .type = serial_lpc32xx_type,
+ .release_port = serial_lpc32xx_release_port,
+ .request_port = serial_lpc32xx_request_port,
+ .config_port = serial_lpc32xx_config_port,
+ .verify_port = serial_lpc32xx_verify_port,
+};
+
+/*
+ * Register a set of serial devices attached to a platform device
+ */
+static int __devinit serial_hs_lpc32xx_probe(struct platform_device *pdev)
+{
+ struct lpc32xx_hsuart_port *p = &lpc32xx_hs_ports[uarts_registered];
+ int ret = 0;
+ struct resource *res;
+
+ if (uarts_registered >= MAX_PORTS) {
+ dev_err(&pdev->dev,
+ "Error: Number of possible ports exceeded (%d)!\n",
+ uarts_registered + 1);
+ return -ENXIO;
+ }
+
+ memset(p, 0, sizeof(*p));
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev,
+ "Error getting mem resource for HS UART port %d\n",
+ uarts_registered);
+ return -ENXIO;
+ }
+ p->port.mapbase = res->start;
+ p->port.membase = NULL;
+
+ p->port.irq = platform_get_irq(pdev, 0);
+ if (p->port.irq < 0) {
+ dev_err(&pdev->dev, "Error getting irq for HS UART port %d\n",
+ uarts_registered);
+ return p->port.irq;
+ }
+
+ p->port.iotype = UPIO_MEM32;
+ p->port.uartclk = LPC32XX_MAIN_OSC_FREQ;
+ p->port.regshift = 2;
+ p->port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP;
+ p->port.dev = &pdev->dev;
+ p->port.ops = &serial_lpc32xx_pops;
+ p->port.line = uarts_registered++;
+ spin_lock_init(&p->port.lock);
+
+ /* send port to loopback mode by default */
+ lpc32xx_loopback_set(p->port.mapbase, 1);
+
+ ret = uart_add_one_port(&lpc32xx_hs_reg, &p->port);
+
+ platform_set_drvdata(pdev, p);
+
+ return ret;
+}
+
+/*
+ * Remove serial ports registered against a platform device.
+ */
+static int __devexit serial_hs_lpc32xx_remove(struct platform_device *pdev)
+{
+ struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev);
+
+ uart_remove_one_port(&lpc32xx_hs_reg, &p->port);
+
+ return 0;
+}
+
+
+#ifdef CONFIG_PM
+static int serial_hs_lpc32xx_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev);
+
+ uart_suspend_port(&lpc32xx_hs_reg, &p->port);
+
+ return 0;
+}
+
+static int serial_hs_lpc32xx_resume(struct platform_device *pdev)
+{
+ struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev);
+
+ uart_resume_port(&lpc32xx_hs_reg, &p->port);
+
+ return 0;
+}
+#else
+#define serial_hs_lpc32xx_suspend NULL
+#define serial_hs_lpc32xx_resume NULL
+#endif
+
+static const struct of_device_id serial_hs_lpc32xx_dt_ids[] = {
+ { .compatible = "nxp,lpc3220-hsuart" },
+ { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, serial_hs_lpc32xx_dt_ids);
+
+static struct platform_driver serial_hs_lpc32xx_driver = {
+ .probe = serial_hs_lpc32xx_probe,
+ .remove = __devexit_p(serial_hs_lpc32xx_remove),
+ .suspend = serial_hs_lpc32xx_suspend,
+ .resume = serial_hs_lpc32xx_resume,
+ .driver = {
+ .name = MODNAME,
+ .owner = THIS_MODULE,
+ .of_match_table = serial_hs_lpc32xx_dt_ids,
+ },
+};
+
+static int __init lpc32xx_hsuart_init(void)
+{
+ int ret;
+
+ ret = uart_register_driver(&lpc32xx_hs_reg);
+ if (ret)
+ return ret;
+
+ ret = platform_driver_register(&serial_hs_lpc32xx_driver);
+ if (ret)
+ uart_unregister_driver(&lpc32xx_hs_reg);
+
+ return ret;
+}
+
+static void __exit lpc32xx_hsuart_exit(void)
+{
+ platform_driver_unregister(&serial_hs_lpc32xx_driver);
+ uart_unregister_driver(&lpc32xx_hs_reg);
+}
+
+module_init(lpc32xx_hsuart_init);
+module_exit(lpc32xx_hsuart_exit);
+
+MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com>");
+MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
+MODULE_DESCRIPTION("NXP LPC32XX High Speed UART driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/m32r_sio.c b/drivers/tty/serial/m32r_sio.c
index a070362..b13949a 100644
--- a/drivers/tty/serial/m32r_sio.c
+++ b/drivers/tty/serial/m32r_sio.c
@@ -44,8 +44,6 @@
#include <asm/io.h>
#include <asm/irq.h>
-#define PORT_M32R_BASE PORT_M32R_SIO
-#define PORT_INDEX(x) (x - PORT_M32R_BASE + 1)
#define BAUD_RATE 115200
#include <linux/serial_core.h>
@@ -132,22 +130,6 @@
static struct irq_info irq_lists[NR_IRQS];
-/*
- * Here we define the default xmit fifo size used for each type of UART.
- */
-static const struct serial_uart_config uart_config[] = {
- [PORT_UNKNOWN] = {
- .name = "unknown",
- .dfl_xmit_fifo_size = 1,
- .flags = 0,
- },
- [PORT_INDEX(PORT_M32R_SIO)] = {
- .name = "M32RSIO",
- .dfl_xmit_fifo_size = 1,
- .flags = 0,
- },
-};
-
#ifdef CONFIG_SERIAL_M32R_PLDSIO
#define __sio_in(x) inw((unsigned long)(x))
@@ -907,8 +889,7 @@
spin_lock_irqsave(&up->port.lock, flags);
- up->port.type = (PORT_M32R_SIO - PORT_M32R_BASE + 1);
- up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size;
+ up->port.fifosize = 1;
spin_unlock_irqrestore(&up->port.lock, flags);
}
@@ -916,23 +897,11 @@
static int
m32r_sio_verify_port(struct uart_port *port, struct serial_struct *ser)
{
- if (ser->irq >= nr_irqs || ser->irq < 0 ||
- ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
- ser->type >= ARRAY_SIZE(uart_config))
+ if (ser->irq >= nr_irqs || ser->irq < 0 || ser->baud_base < 9600)
return -EINVAL;
return 0;
}
-static const char *
-m32r_sio_type(struct uart_port *port)
-{
- int type = port->type;
-
- if (type >= ARRAY_SIZE(uart_config))
- type = 0;
- return uart_config[type].name;
-}
-
static struct uart_ops m32r_sio_pops = {
.tx_empty = m32r_sio_tx_empty,
.set_mctrl = m32r_sio_set_mctrl,
@@ -946,7 +915,6 @@
.shutdown = m32r_sio_shutdown,
.set_termios = m32r_sio_set_termios,
.pm = m32r_sio_pm,
- .type = m32r_sio_type,
.release_port = m32r_sio_release_port,
.request_port = m32r_sio_request_port,
.config_port = m32r_sio_config_port,
diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c
index b4902b9..46043c2 100644
--- a/drivers/tty/serial/max3100.c
+++ b/drivers/tty/serial/max3100.c
@@ -910,17 +910,7 @@
.resume = max3100_resume,
};
-static int __init max3100_init(void)
-{
- return spi_register_driver(&max3100_driver);
-}
-module_init(max3100_init);
-
-static void __exit max3100_exit(void)
-{
- spi_unregister_driver(&max3100_driver);
-}
-module_exit(max3100_exit);
+module_spi_driver(max3100_driver);
MODULE_DESCRIPTION("MAX3100 driver");
MODULE_AUTHOR("Christian Pellegrin <chripell@evolware.org>");
diff --git a/drivers/tty/serial/max3107.c b/drivers/tty/serial/max3107.c
deleted file mode 100644
index 17c7ba8..0000000
--- a/drivers/tty/serial/max3107.c
+++ /dev/null
@@ -1,1215 +0,0 @@
-/*
- * max3107.c - spi uart protocol driver for Maxim 3107
- * Based on max3100.c
- * by Christian Pellegrin <chripell@evolware.org>
- * and max3110.c
- * by Feng Tang <feng.tang@intel.com>
- *
- * Copyright (C) Aavamobile 2009
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * 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/delay.h>
-#include <linux/device.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/gpio.h>
-#include <linux/spi/spi.h>
-#include <linux/freezer.h>
-#include <linux/module.h>
-#include "max3107.h"
-
-static const struct baud_table brg26_ext[] = {
- { 300, MAX3107_BRG26_B300 },
- { 600, MAX3107_BRG26_B600 },
- { 1200, MAX3107_BRG26_B1200 },
- { 2400, MAX3107_BRG26_B2400 },
- { 4800, MAX3107_BRG26_B4800 },
- { 9600, MAX3107_BRG26_B9600 },
- { 19200, MAX3107_BRG26_B19200 },
- { 57600, MAX3107_BRG26_B57600 },
- { 115200, MAX3107_BRG26_B115200 },
- { 230400, MAX3107_BRG26_B230400 },
- { 460800, MAX3107_BRG26_B460800 },
- { 921600, MAX3107_BRG26_B921600 },
- { 0, 0 }
-};
-
-static const struct baud_table brg13_int[] = {
- { 300, MAX3107_BRG13_IB300 },
- { 600, MAX3107_BRG13_IB600 },
- { 1200, MAX3107_BRG13_IB1200 },
- { 2400, MAX3107_BRG13_IB2400 },
- { 4800, MAX3107_BRG13_IB4800 },
- { 9600, MAX3107_BRG13_IB9600 },
- { 19200, MAX3107_BRG13_IB19200 },
- { 57600, MAX3107_BRG13_IB57600 },
- { 115200, MAX3107_BRG13_IB115200 },
- { 230400, MAX3107_BRG13_IB230400 },
- { 460800, MAX3107_BRG13_IB460800 },
- { 921600, MAX3107_BRG13_IB921600 },
- { 0, 0 }
-};
-
-static u32 get_new_brg(int baud, struct max3107_port *s)
-{
- int i;
- const struct baud_table *baud_tbl = s->baud_tbl;
-
- for (i = 0; i < 13; i++) {
- if (baud == baud_tbl[i].baud)
- return baud_tbl[i].new_brg;
- }
-
- return 0;
-}
-
-/* Perform SPI transfer for write/read of device register(s) */
-int max3107_rw(struct max3107_port *s, u8 *tx, u8 *rx, int len)
-{
- struct spi_message spi_msg;
- struct spi_transfer spi_xfer;
-
- /* Initialize SPI ,message */
- spi_message_init(&spi_msg);
-
- /* Initialize SPI transfer */
- memset(&spi_xfer, 0, sizeof spi_xfer);
- spi_xfer.len = len;
- spi_xfer.tx_buf = tx;
- spi_xfer.rx_buf = rx;
- spi_xfer.speed_hz = MAX3107_SPI_SPEED;
-
- /* Add SPI transfer to SPI message */
- spi_message_add_tail(&spi_xfer, &spi_msg);
-
-#ifdef DBG_TRACE_SPI_DATA
- {
- int i;
- pr_info("tx len %d:\n", spi_xfer.len);
- for (i = 0 ; i < spi_xfer.len && i < 32 ; i++)
- pr_info(" %x", ((u8 *)spi_xfer.tx_buf)[i]);
- pr_info("\n");
- }
-#endif
-
- /* Perform synchronous SPI transfer */
- if (spi_sync(s->spi, &spi_msg)) {
- dev_err(&s->spi->dev, "spi_sync failure\n");
- return -EIO;
- }
-
-#ifdef DBG_TRACE_SPI_DATA
- if (spi_xfer.rx_buf) {
- int i;
- pr_info("rx len %d:\n", spi_xfer.len);
- for (i = 0 ; i < spi_xfer.len && i < 32 ; i++)
- pr_info(" %x", ((u8 *)spi_xfer.rx_buf)[i]);
- pr_info("\n");
- }
-#endif
- return 0;
-}
-EXPORT_SYMBOL_GPL(max3107_rw);
-
-/* Puts received data to circular buffer */
-static void put_data_to_circ_buf(struct max3107_port *s, unsigned char *data,
- int len)
-{
- struct uart_port *port = &s->port;
- struct tty_struct *tty;
-
- if (!port->state)
- return;
-
- tty = port->state->port.tty;
- if (!tty)
- return;
-
- /* Insert received data */
- tty_insert_flip_string(tty, data, len);
- /* Update RX counter */
- port->icount.rx += len;
-}
-
-/* Handle data receiving */
-static void max3107_handlerx(struct max3107_port *s, u16 rxlvl)
-{
- int i;
- int j;
- int len; /* SPI transfer buffer length */
- u16 *buf;
- u8 *valid_str;
-
- if (!s->rx_enabled)
- /* RX is disabled */
- return;
-
- if (rxlvl == 0) {
- /* RX fifo is empty */
- return;
- } else if (rxlvl >= MAX3107_RX_FIFO_SIZE) {
- dev_warn(&s->spi->dev, "Possible RX FIFO overrun %d\n", rxlvl);
- /* Ensure sanity of RX level */
- rxlvl = MAX3107_RX_FIFO_SIZE;
- }
- if ((s->rxbuf == 0) || (s->rxstr == 0)) {
- dev_warn(&s->spi->dev, "Rx buffer/str isn't ready\n");
- return;
- }
- buf = s->rxbuf;
- valid_str = s->rxstr;
- while (rxlvl) {
- pr_debug("rxlvl %d\n", rxlvl);
- /* Clear buffer */
- memset(buf, 0, sizeof(u16) * (MAX3107_RX_FIFO_SIZE + 2));
- len = 0;
- if (s->irqen_reg & MAX3107_IRQ_RXFIFO_BIT) {
- /* First disable RX FIFO interrupt */
- pr_debug("Disabling RX INT\n");
- buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG);
- s->irqen_reg &= ~MAX3107_IRQ_RXFIFO_BIT;
- buf[0] |= s->irqen_reg;
- len++;
- }
- /* Just increase the length by amount of words in FIFO since
- * buffer was zeroed and SPI transfer of 0x0000 means reading
- * from RX FIFO
- */
- len += rxlvl;
- /* Append RX level query */
- buf[len] = MAX3107_RXFIFOLVL_REG;
- len++;
-
- /* Perform the SPI transfer */
- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, len * 2)) {
- dev_err(&s->spi->dev, "SPI transfer for RX h failed\n");
- return;
- }
-
- /* Skip RX FIFO interrupt disabling word if it was added */
- j = ((len - 1) - rxlvl);
- /* Read received words */
- for (i = 0; i < rxlvl; i++, j++)
- valid_str[i] = (u8)buf[j];
- put_data_to_circ_buf(s, valid_str, rxlvl);
- /* Get new RX level */
- rxlvl = (buf[len - 1] & MAX3107_SPI_RX_DATA_MASK);
- }
-
- if (s->rx_enabled) {
- /* RX still enabled, re-enable RX FIFO interrupt */
- pr_debug("Enabling RX INT\n");
- buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG);
- s->irqen_reg |= MAX3107_IRQ_RXFIFO_BIT;
- buf[0] |= s->irqen_reg;
- if (max3107_rw(s, (u8 *)buf, NULL, 2))
- dev_err(&s->spi->dev, "RX FIFO INT enabling failed\n");
- }
-
- /* Push the received data to receivers */
- if (s->port.state->port.tty)
- tty_flip_buffer_push(s->port.state->port.tty);
-}
-
-
-/* Handle data sending */
-static void max3107_handletx(struct max3107_port *s)
-{
- struct circ_buf *xmit = &s->port.state->xmit;
- int i;
- unsigned long flags;
- int len; /* SPI transfer buffer length */
- u16 *buf;
-
- if (!s->tx_fifo_empty)
- /* Don't send more data before previous data is sent */
- return;
-
- if (uart_circ_empty(xmit) || uart_tx_stopped(&s->port))
- /* No data to send or TX is stopped */
- return;
-
- if (!s->txbuf) {
- dev_warn(&s->spi->dev, "Txbuf isn't ready\n");
- return;
- }
- buf = s->txbuf;
- /* Get length of data pending in circular buffer */
- len = uart_circ_chars_pending(xmit);
- if (len) {
- /* Limit to size of TX FIFO */
- if (len > MAX3107_TX_FIFO_SIZE)
- len = MAX3107_TX_FIFO_SIZE;
-
- pr_debug("txlen %d\n", len);
-
- /* Update TX counter */
- s->port.icount.tx += len;
-
- /* TX FIFO will no longer be empty */
- s->tx_fifo_empty = 0;
-
- i = 0;
- if (s->irqen_reg & MAX3107_IRQ_TXEMPTY_BIT) {
- /* First disable TX empty interrupt */
- pr_debug("Disabling TE INT\n");
- buf[i] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG);
- s->irqen_reg &= ~MAX3107_IRQ_TXEMPTY_BIT;
- buf[i] |= s->irqen_reg;
- i++;
- len++;
- }
- /* Add data to send */
- spin_lock_irqsave(&s->port.lock, flags);
- for ( ; i < len ; i++) {
- buf[i] = (MAX3107_WRITE_BIT | MAX3107_THR_REG);
- buf[i] |= ((u16)xmit->buf[xmit->tail] &
- MAX3107_SPI_TX_DATA_MASK);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- }
- spin_unlock_irqrestore(&s->port.lock, flags);
- if (!(s->irqen_reg & MAX3107_IRQ_TXEMPTY_BIT)) {
- /* Enable TX empty interrupt */
- pr_debug("Enabling TE INT\n");
- buf[i] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG);
- s->irqen_reg |= MAX3107_IRQ_TXEMPTY_BIT;
- buf[i] |= s->irqen_reg;
- i++;
- len++;
- }
- if (!s->tx_enabled) {
- /* Enable TX */
- pr_debug("Enable TX\n");
- buf[i] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG);
- spin_lock_irqsave(&s->data_lock, flags);
- s->mode1_reg &= ~MAX3107_MODE1_TXDIS_BIT;
- buf[i] |= s->mode1_reg;
- spin_unlock_irqrestore(&s->data_lock, flags);
- s->tx_enabled = 1;
- i++;
- len++;
- }
-
- /* Perform the SPI transfer */
- if (max3107_rw(s, (u8 *)buf, NULL, len*2)) {
- dev_err(&s->spi->dev,
- "SPI transfer TX handling failed\n");
- return;
- }
- }
-
- /* Indicate wake up if circular buffer is getting low on data */
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&s->port);
-
-}
-
-/* Handle interrupts
- * Also reads and returns current RX FIFO level
- */
-static u16 handle_interrupt(struct max3107_port *s)
-{
- u16 buf[4]; /* Buffer for SPI transfers */
- u8 irq_status;
- u16 rx_level;
- unsigned long flags;
-
- /* Read IRQ status register */
- buf[0] = MAX3107_IRQSTS_REG;
- /* Read status IRQ status register */
- buf[1] = MAX3107_STS_IRQSTS_REG;
- /* Read LSR IRQ status register */
- buf[2] = MAX3107_LSR_IRQSTS_REG;
- /* Query RX level */
- buf[3] = MAX3107_RXFIFOLVL_REG;
-
- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 8)) {
- dev_err(&s->spi->dev,
- "SPI transfer for INTR handling failed\n");
- return 0;
- }
-
- irq_status = (u8)buf[0];
- pr_debug("IRQSTS %x\n", irq_status);
- rx_level = (buf[3] & MAX3107_SPI_RX_DATA_MASK);
-
- if (irq_status & MAX3107_IRQ_LSR_BIT) {
- /* LSR interrupt */
- if (buf[2] & MAX3107_LSR_RXTO_BIT)
- /* RX timeout interrupt,
- * handled by normal RX handling
- */
- pr_debug("RX TO INT\n");
- }
-
- if (irq_status & MAX3107_IRQ_TXEMPTY_BIT) {
- /* Tx empty interrupt,
- * disable TX and set tx_fifo_empty flag
- */
- pr_debug("TE INT, disabling TX\n");
- buf[0] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG);
- spin_lock_irqsave(&s->data_lock, flags);
- s->mode1_reg |= MAX3107_MODE1_TXDIS_BIT;
- buf[0] |= s->mode1_reg;
- spin_unlock_irqrestore(&s->data_lock, flags);
- if (max3107_rw(s, (u8 *)buf, NULL, 2))
- dev_err(&s->spi->dev, "SPI transfer TX dis failed\n");
- s->tx_enabled = 0;
- s->tx_fifo_empty = 1;
- }
-
- if (irq_status & MAX3107_IRQ_RXFIFO_BIT)
- /* RX FIFO interrupt,
- * handled by normal RX handling
- */
- pr_debug("RFIFO INT\n");
-
- /* Return RX level */
- return rx_level;
-}
-
-/* Trigger work thread*/
-static void max3107_dowork(struct max3107_port *s)
-{
- if (!work_pending(&s->work) && !freezing(current) && !s->suspended)
- queue_work(s->workqueue, &s->work);
- else
- dev_warn(&s->spi->dev, "interrup isn't serviced normally!\n");
-}
-
-/* Work thread */
-static void max3107_work(struct work_struct *w)
-{
- struct max3107_port *s = container_of(w, struct max3107_port, work);
- u16 rxlvl = 0;
- int len; /* SPI transfer buffer length */
- u16 buf[5]; /* Buffer for SPI transfers */
- unsigned long flags;
-
- /* Start by reading current RX FIFO level */
- buf[0] = MAX3107_RXFIFOLVL_REG;
- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
- dev_err(&s->spi->dev, "SPI transfer RX lev failed\n");
- rxlvl = 0;
- } else {
- rxlvl = (buf[0] & MAX3107_SPI_RX_DATA_MASK);
- }
-
- do {
- pr_debug("rxlvl %d\n", rxlvl);
-
- /* Handle RX */
- max3107_handlerx(s, rxlvl);
- rxlvl = 0;
-
- if (s->handle_irq) {
- /* Handle pending interrupts
- * We also get new RX FIFO level since new data may
- * have been received while pushing received data to
- * receivers
- */
- s->handle_irq = 0;
- rxlvl = handle_interrupt(s);
- }
-
- /* Handle TX */
- max3107_handletx(s);
-
- /* Handle configuration changes */
- len = 0;
- spin_lock_irqsave(&s->data_lock, flags);
- if (s->mode1_commit) {
- pr_debug("mode1_commit\n");
- buf[len] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG);
- buf[len++] |= s->mode1_reg;
- s->mode1_commit = 0;
- }
- if (s->lcr_commit) {
- pr_debug("lcr_commit\n");
- buf[len] = (MAX3107_WRITE_BIT | MAX3107_LCR_REG);
- buf[len++] |= s->lcr_reg;
- s->lcr_commit = 0;
- }
- if (s->brg_commit) {
- pr_debug("brg_commit\n");
- buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVMSB_REG);
- buf[len++] |= ((s->brg_cfg >> 16) &
- MAX3107_SPI_TX_DATA_MASK);
- buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVLSB_REG);
- buf[len++] |= ((s->brg_cfg >> 8) &
- MAX3107_SPI_TX_DATA_MASK);
- buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGCFG_REG);
- buf[len++] |= ((s->brg_cfg) & 0xff);
- s->brg_commit = 0;
- }
- spin_unlock_irqrestore(&s->data_lock, flags);
-
- if (len > 0) {
- if (max3107_rw(s, (u8 *)buf, NULL, len * 2))
- dev_err(&s->spi->dev,
- "SPI transfer config failed\n");
- }
-
- /* Reloop if interrupt handling indicated data in RX FIFO */
- } while (rxlvl);
-
-}
-
-/* Set sleep mode */
-static void max3107_set_sleep(struct max3107_port *s, int mode)
-{
- u16 buf[1]; /* Buffer for SPI transfer */
- unsigned long flags;
- pr_debug("enter, mode %d\n", mode);
-
- buf[0] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG);
- spin_lock_irqsave(&s->data_lock, flags);
- switch (mode) {
- case MAX3107_DISABLE_FORCED_SLEEP:
- s->mode1_reg &= ~MAX3107_MODE1_FORCESLEEP_BIT;
- break;
- case MAX3107_ENABLE_FORCED_SLEEP:
- s->mode1_reg |= MAX3107_MODE1_FORCESLEEP_BIT;
- break;
- case MAX3107_DISABLE_AUTOSLEEP:
- s->mode1_reg &= ~MAX3107_MODE1_AUTOSLEEP_BIT;
- break;
- case MAX3107_ENABLE_AUTOSLEEP:
- s->mode1_reg |= MAX3107_MODE1_AUTOSLEEP_BIT;
- break;
- default:
- spin_unlock_irqrestore(&s->data_lock, flags);
- dev_warn(&s->spi->dev, "invalid sleep mode\n");
- return;
- }
- buf[0] |= s->mode1_reg;
- spin_unlock_irqrestore(&s->data_lock, flags);
-
- if (max3107_rw(s, (u8 *)buf, NULL, 2))
- dev_err(&s->spi->dev, "SPI transfer sleep mode failed\n");
-
- if (mode == MAX3107_DISABLE_AUTOSLEEP ||
- mode == MAX3107_DISABLE_FORCED_SLEEP)
- msleep(MAX3107_WAKEUP_DELAY);
-}
-
-/* Perform full register initialization */
-static void max3107_register_init(struct max3107_port *s)
-{
- u16 buf[11]; /* Buffer for SPI transfers */
-
- /* 1. Configure baud rate, 9600 as default */
- s->baud = 9600;
- /* the below is default*/
- if (s->ext_clk) {
- s->brg_cfg = MAX3107_BRG26_B9600;
- s->baud_tbl = (struct baud_table *)brg26_ext;
- } else {
- s->brg_cfg = MAX3107_BRG13_IB9600;
- s->baud_tbl = (struct baud_table *)brg13_int;
- }
-
- if (s->pdata->init)
- s->pdata->init(s);
-
- buf[0] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVMSB_REG)
- | ((s->brg_cfg >> 16) & MAX3107_SPI_TX_DATA_MASK);
- buf[1] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVLSB_REG)
- | ((s->brg_cfg >> 8) & MAX3107_SPI_TX_DATA_MASK);
- buf[2] = (MAX3107_WRITE_BIT | MAX3107_BRGCFG_REG)
- | ((s->brg_cfg) & 0xff);
-
- /* 2. Configure LCR register, 8N1 mode by default */
- s->lcr_reg = MAX3107_LCR_WORD_LEN_8;
- buf[3] = (MAX3107_WRITE_BIT | MAX3107_LCR_REG)
- | s->lcr_reg;
-
- /* 3. Configure MODE 1 register */
- s->mode1_reg = 0;
- /* Enable IRQ pin */
- s->mode1_reg |= MAX3107_MODE1_IRQSEL_BIT;
- /* Disable TX */
- s->mode1_reg |= MAX3107_MODE1_TXDIS_BIT;
- s->tx_enabled = 0;
- /* RX is enabled */
- s->rx_enabled = 1;
- buf[4] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG)
- | s->mode1_reg;
-
- /* 4. Configure MODE 2 register */
- buf[5] = (MAX3107_WRITE_BIT | MAX3107_MODE2_REG);
- if (s->loopback) {
- /* Enable loopback */
- buf[5] |= MAX3107_MODE2_LOOPBACK_BIT;
- }
- /* Reset FIFOs */
- buf[5] |= MAX3107_MODE2_FIFORST_BIT;
- s->tx_fifo_empty = 1;
-
- /* 5. Configure FIFO trigger level register */
- buf[6] = (MAX3107_WRITE_BIT | MAX3107_FIFOTRIGLVL_REG);
- /* RX FIFO trigger for 16 words, TX FIFO trigger not used */
- buf[6] |= (MAX3107_FIFOTRIGLVL_RX(16) | MAX3107_FIFOTRIGLVL_TX(0));
-
- /* 6. Configure flow control levels */
- buf[7] = (MAX3107_WRITE_BIT | MAX3107_FLOWLVL_REG);
- /* Flow control halt level 96, resume level 48 */
- buf[7] |= (MAX3107_FLOWLVL_RES(48) | MAX3107_FLOWLVL_HALT(96));
-
- /* 7. Configure flow control */
- buf[8] = (MAX3107_WRITE_BIT | MAX3107_FLOWCTRL_REG);
- /* Enable auto CTS and auto RTS flow control */
- buf[8] |= (MAX3107_FLOWCTRL_AUTOCTS_BIT | MAX3107_FLOWCTRL_AUTORTS_BIT);
-
- /* 8. Configure RX timeout register */
- buf[9] = (MAX3107_WRITE_BIT | MAX3107_RXTO_REG);
- /* Timeout after 48 character intervals */
- buf[9] |= 0x0030;
-
- /* 9. Configure LSR interrupt enable register */
- buf[10] = (MAX3107_WRITE_BIT | MAX3107_LSR_IRQEN_REG);
- /* Enable RX timeout interrupt */
- buf[10] |= MAX3107_LSR_RXTO_BIT;
-
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, NULL, 22))
- dev_err(&s->spi->dev, "SPI transfer for init failed\n");
-
- /* 10. Clear IRQ status register by reading it */
- buf[0] = MAX3107_IRQSTS_REG;
-
- /* 11. Configure interrupt enable register */
- /* Enable LSR interrupt */
- s->irqen_reg = MAX3107_IRQ_LSR_BIT;
- /* Enable RX FIFO interrupt */
- s->irqen_reg |= MAX3107_IRQ_RXFIFO_BIT;
- buf[1] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG)
- | s->irqen_reg;
-
- /* 12. Clear FIFO reset that was set in step 6 */
- buf[2] = (MAX3107_WRITE_BIT | MAX3107_MODE2_REG);
- if (s->loopback) {
- /* Keep loopback enabled */
- buf[2] |= MAX3107_MODE2_LOOPBACK_BIT;
- }
-
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 6))
- dev_err(&s->spi->dev, "SPI transfer for init failed\n");
-
-}
-
-/* IRQ handler */
-static irqreturn_t max3107_irq(int irqno, void *dev_id)
-{
- struct max3107_port *s = dev_id;
-
- if (irqno != s->spi->irq) {
- /* Unexpected IRQ */
- return IRQ_NONE;
- }
-
- /* Indicate irq */
- s->handle_irq = 1;
-
- /* Trigger work thread */
- max3107_dowork(s);
-
- return IRQ_HANDLED;
-}
-
-/* HW suspension function
- *
- * Currently autosleep is used to decrease current consumption, alternative
- * approach would be to set the chip to reset mode if UART is not being
- * used but that would mess the GPIOs
- *
- */
-void max3107_hw_susp(struct max3107_port *s, int suspend)
-{
- pr_debug("enter, suspend %d\n", suspend);
-
- if (suspend) {
- /* Suspend requested,
- * enable autosleep to decrease current consumption
- */
- s->suspended = 1;
- max3107_set_sleep(s, MAX3107_ENABLE_AUTOSLEEP);
- } else {
- /* Resume requested,
- * disable autosleep
- */
- s->suspended = 0;
- max3107_set_sleep(s, MAX3107_DISABLE_AUTOSLEEP);
- }
-}
-EXPORT_SYMBOL_GPL(max3107_hw_susp);
-
-/* Modem status IRQ enabling */
-static void max3107_enable_ms(struct uart_port *port)
-{
- /* Modem status not supported */
-}
-
-/* Data send function */
-static void max3107_start_tx(struct uart_port *port)
-{
- struct max3107_port *s = container_of(port, struct max3107_port, port);
-
- /* Trigger work thread for sending data */
- max3107_dowork(s);
-}
-
-/* Function for checking that there is no pending transfers */
-static unsigned int max3107_tx_empty(struct uart_port *port)
-{
- struct max3107_port *s = container_of(port, struct max3107_port, port);
-
- pr_debug("returning %d\n",
- (s->tx_fifo_empty && uart_circ_empty(&s->port.state->xmit)));
- return s->tx_fifo_empty && uart_circ_empty(&s->port.state->xmit);
-}
-
-/* Function for stopping RX */
-static void max3107_stop_rx(struct uart_port *port)
-{
- struct max3107_port *s = container_of(port, struct max3107_port, port);
- unsigned long flags;
-
- /* Set RX disabled in MODE 1 register */
- spin_lock_irqsave(&s->data_lock, flags);
- s->mode1_reg |= MAX3107_MODE1_RXDIS_BIT;
- s->mode1_commit = 1;
- spin_unlock_irqrestore(&s->data_lock, flags);
- /* Set RX disabled */
- s->rx_enabled = 0;
- /* Trigger work thread for doing the actual configuration change */
- max3107_dowork(s);
-}
-
-/* Function for returning control pin states */
-static unsigned int max3107_get_mctrl(struct uart_port *port)
-{
- /* DCD and DSR are not wired and CTS/RTS is handled automatically
- * so just indicate DSR and CAR asserted
- */
- return TIOCM_DSR | TIOCM_CAR;
-}
-
-/* Function for setting control pin states */
-static void max3107_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- /* DCD and DSR are not wired and CTS/RTS is hadnled automatically
- * so do nothing
- */
-}
-
-/* Function for configuring UART parameters */
-static void max3107_set_termios(struct uart_port *port,
- struct ktermios *termios,
- struct ktermios *old)
-{
- struct max3107_port *s = container_of(port, struct max3107_port, port);
- struct tty_struct *tty;
- int baud;
- u16 new_lcr = 0;
- u32 new_brg = 0;
- unsigned long flags;
-
- if (!port->state)
- return;
-
- tty = port->state->port.tty;
- if (!tty)
- return;
-
- /* Get new LCR register values */
- /* Word size */
- if ((termios->c_cflag & CSIZE) == CS7)
- new_lcr |= MAX3107_LCR_WORD_LEN_7;
- else
- new_lcr |= MAX3107_LCR_WORD_LEN_8;
-
- /* Parity */
- if (termios->c_cflag & PARENB) {
- new_lcr |= MAX3107_LCR_PARITY_BIT;
- if (!(termios->c_cflag & PARODD))
- new_lcr |= MAX3107_LCR_EVENPARITY_BIT;
- }
-
- /* Stop bits */
- if (termios->c_cflag & CSTOPB) {
- /* 2 stop bits */
- new_lcr |= MAX3107_LCR_STOPLEN_BIT;
- }
-
- /* Mask termios capabilities we don't support */
- termios->c_cflag &= ~CMSPAR;
-
- /* Set status ignore mask */
- s->port.ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- s->port.ignore_status_mask |= MAX3107_ALL_ERRORS;
-
- /* Set low latency to immediately handle pushed data */
- s->port.state->port.tty->low_latency = 1;
-
- /* Get new baud rate generator configuration */
- baud = tty_get_baud_rate(tty);
-
- spin_lock_irqsave(&s->data_lock, flags);
- new_brg = get_new_brg(baud, s);
- /* if can't find the corrent config, use previous */
- if (!new_brg) {
- baud = s->baud;
- new_brg = s->brg_cfg;
- }
- spin_unlock_irqrestore(&s->data_lock, flags);
- tty_termios_encode_baud_rate(termios, baud, baud);
- s->baud = baud;
-
- /* Update timeout according to new baud rate */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- spin_lock_irqsave(&s->data_lock, flags);
- if (s->lcr_reg != new_lcr) {
- s->lcr_reg = new_lcr;
- s->lcr_commit = 1;
- }
- if (s->brg_cfg != new_brg) {
- s->brg_cfg = new_brg;
- s->brg_commit = 1;
- }
- spin_unlock_irqrestore(&s->data_lock, flags);
-
- /* Trigger work thread for doing the actual configuration change */
- max3107_dowork(s);
-}
-
-/* Port shutdown function */
-static void max3107_shutdown(struct uart_port *port)
-{
- struct max3107_port *s = container_of(port, struct max3107_port, port);
-
- if (s->suspended && s->pdata->hw_suspend)
- s->pdata->hw_suspend(s, 0);
-
- /* Free the interrupt */
- free_irq(s->spi->irq, s);
-
- if (s->workqueue) {
- /* Flush and destroy work queue */
- flush_workqueue(s->workqueue);
- destroy_workqueue(s->workqueue);
- s->workqueue = NULL;
- }
-
- /* Suspend HW */
- if (s->pdata->hw_suspend)
- s->pdata->hw_suspend(s, 1);
-}
-
-/* Port startup function */
-static int max3107_startup(struct uart_port *port)
-{
- struct max3107_port *s = container_of(port, struct max3107_port, port);
-
- /* Initialize work queue */
- s->workqueue = create_freezable_workqueue("max3107");
- if (!s->workqueue) {
- dev_err(&s->spi->dev, "Workqueue creation failed\n");
- return -EBUSY;
- }
- INIT_WORK(&s->work, max3107_work);
-
- /* Setup IRQ */
- if (request_irq(s->spi->irq, max3107_irq, IRQF_TRIGGER_FALLING,
- "max3107", s)) {
- dev_err(&s->spi->dev, "IRQ reguest failed\n");
- destroy_workqueue(s->workqueue);
- s->workqueue = NULL;
- return -EBUSY;
- }
-
- /* Resume HW */
- if (s->pdata->hw_suspend)
- s->pdata->hw_suspend(s, 0);
-
- /* Init registers */
- max3107_register_init(s);
-
- return 0;
-}
-
-/* Port type function */
-static const char *max3107_type(struct uart_port *port)
-{
- struct max3107_port *s = container_of(port, struct max3107_port, port);
- return s->spi->modalias;
-}
-
-/* Port release function */
-static void max3107_release_port(struct uart_port *port)
-{
- /* Do nothing */
-}
-
-/* Port request function */
-static int max3107_request_port(struct uart_port *port)
-{
- /* Do nothing */
- return 0;
-}
-
-/* Port config function */
-static void max3107_config_port(struct uart_port *port, int flags)
-{
- struct max3107_port *s = container_of(port, struct max3107_port, port);
- s->port.type = PORT_MAX3107;
-}
-
-/* Port verify function */
-static int max3107_verify_port(struct uart_port *port,
- struct serial_struct *ser)
-{
- if (ser->type == PORT_UNKNOWN || ser->type == PORT_MAX3107)
- return 0;
-
- return -EINVAL;
-}
-
-/* Port stop TX function */
-static void max3107_stop_tx(struct uart_port *port)
-{
- /* Do nothing */
-}
-
-/* Port break control function */
-static void max3107_break_ctl(struct uart_port *port, int break_state)
-{
- /* We don't support break control, do nothing */
-}
-
-
-/* Port functions */
-static struct uart_ops max3107_ops = {
- .tx_empty = max3107_tx_empty,
- .set_mctrl = max3107_set_mctrl,
- .get_mctrl = max3107_get_mctrl,
- .stop_tx = max3107_stop_tx,
- .start_tx = max3107_start_tx,
- .stop_rx = max3107_stop_rx,
- .enable_ms = max3107_enable_ms,
- .break_ctl = max3107_break_ctl,
- .startup = max3107_startup,
- .shutdown = max3107_shutdown,
- .set_termios = max3107_set_termios,
- .type = max3107_type,
- .release_port = max3107_release_port,
- .request_port = max3107_request_port,
- .config_port = max3107_config_port,
- .verify_port = max3107_verify_port,
-};
-
-/* UART driver data */
-static struct uart_driver max3107_uart_driver = {
- .owner = THIS_MODULE,
- .driver_name = "ttyMAX",
- .dev_name = "ttyMAX",
- .nr = 1,
-};
-
-static int driver_registered = 0;
-
-
-
-/* 'Generic' platform data */
-static struct max3107_plat generic_plat_data = {
- .loopback = 0,
- .ext_clk = 1,
- .hw_suspend = max3107_hw_susp,
- .polled_mode = 0,
- .poll_time = 0,
-};
-
-
-/*******************************************************************/
-
-/**
- * max3107_probe - SPI bus probe entry point
- * @spi: the spi device
- *
- * SPI wants us to probe this device and if appropriate claim it.
- * Perform any platform specific requirements and then initialise
- * the device.
- */
-
-int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata)
-{
- struct max3107_port *s;
- u16 buf[2]; /* Buffer for SPI transfers */
- int retval;
-
- pr_info("enter max3107 probe\n");
-
- /* Allocate port structure */
- s = kzalloc(sizeof(*s), GFP_KERNEL);
- if (!s) {
- pr_err("Allocating port structure failed\n");
- return -ENOMEM;
- }
-
- s->pdata = pdata;
-
- /* SPI Rx buffer
- * +2 for RX FIFO interrupt
- * disabling and RX level query
- */
- s->rxbuf = kzalloc(sizeof(u16) * (MAX3107_RX_FIFO_SIZE+2), GFP_KERNEL);
- if (!s->rxbuf) {
- pr_err("Allocating RX buffer failed\n");
- retval = -ENOMEM;
- goto err_free4;
- }
- s->rxstr = kzalloc(sizeof(u8) * MAX3107_RX_FIFO_SIZE, GFP_KERNEL);
- if (!s->rxstr) {
- pr_err("Allocating RX buffer failed\n");
- retval = -ENOMEM;
- goto err_free3;
- }
- /* SPI Tx buffer
- * SPI transfer buffer
- * +3 for TX FIFO empty
- * interrupt disabling and
- * enabling and TX enabling
- */
- s->txbuf = kzalloc(sizeof(u16) * MAX3107_TX_FIFO_SIZE + 3, GFP_KERNEL);
- if (!s->txbuf) {
- pr_err("Allocating TX buffer failed\n");
- retval = -ENOMEM;
- goto err_free2;
- }
- /* Initialize shared data lock */
- spin_lock_init(&s->data_lock);
-
- /* SPI intializations */
- dev_set_drvdata(&spi->dev, s);
- spi->mode = SPI_MODE_0;
- spi->dev.platform_data = pdata;
- spi->bits_per_word = 16;
- s->ext_clk = pdata->ext_clk;
- s->loopback = pdata->loopback;
- spi_setup(spi);
- s->spi = spi;
-
- /* Check REV ID to ensure we are talking to what we expect */
- buf[0] = MAX3107_REVID_REG;
- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
- dev_err(&s->spi->dev, "SPI transfer for REVID read failed\n");
- retval = -EIO;
- goto err_free1;
- }
- if ((buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID1 &&
- (buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID2) {
- dev_err(&s->spi->dev, "REVID %x does not match\n",
- (buf[0] & MAX3107_SPI_RX_DATA_MASK));
- retval = -ENODEV;
- goto err_free1;
- }
-
- /* Disable all interrupts */
- buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG | 0x0000);
- buf[0] |= 0x0000;
-
- /* Configure clock source */
- buf[1] = (MAX3107_WRITE_BIT | MAX3107_CLKSRC_REG);
- if (s->ext_clk) {
- /* External clock */
- buf[1] |= MAX3107_CLKSRC_EXTCLK_BIT;
- }
-
- /* PLL bypass ON */
- buf[1] |= MAX3107_CLKSRC_PLLBYP_BIT;
-
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, NULL, 4)) {
- dev_err(&s->spi->dev, "SPI transfer for init failed\n");
- retval = -EIO;
- goto err_free1;
- }
-
- /* Register UART driver */
- if (!driver_registered) {
- retval = uart_register_driver(&max3107_uart_driver);
- if (retval) {
- dev_err(&s->spi->dev, "Registering UART driver failed\n");
- goto err_free1;
- }
- driver_registered = 1;
- }
-
- /* Initialize UART port data */
- s->port.fifosize = 128;
- s->port.ops = &max3107_ops;
- s->port.line = 0;
- s->port.dev = &spi->dev;
- s->port.uartclk = 9600;
- s->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
- s->port.irq = s->spi->irq;
- s->port.type = PORT_MAX3107;
-
- /* Add UART port */
- retval = uart_add_one_port(&max3107_uart_driver, &s->port);
- if (retval < 0) {
- dev_err(&s->spi->dev, "Adding UART port failed\n");
- goto err_free1;
- }
-
- if (pdata->configure) {
- retval = pdata->configure(s);
- if (retval < 0)
- goto err_free1;
- }
-
- /* Go to suspend mode */
- if (pdata->hw_suspend)
- pdata->hw_suspend(s, 1);
-
- return 0;
-
-err_free1:
- kfree(s->txbuf);
-err_free2:
- kfree(s->rxstr);
-err_free3:
- kfree(s->rxbuf);
-err_free4:
- kfree(s);
- return retval;
-}
-EXPORT_SYMBOL_GPL(max3107_probe);
-
-/* Driver remove function */
-int max3107_remove(struct spi_device *spi)
-{
- struct max3107_port *s = dev_get_drvdata(&spi->dev);
-
- pr_info("enter max3107 remove\n");
-
- /* Remove port */
- if (uart_remove_one_port(&max3107_uart_driver, &s->port))
- dev_warn(&s->spi->dev, "Removing UART port failed\n");
-
-
- /* Free TxRx buffer */
- kfree(s->rxbuf);
- kfree(s->rxstr);
- kfree(s->txbuf);
-
- /* Free port structure */
- kfree(s);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(max3107_remove);
-
-/* Driver suspend function */
-int max3107_suspend(struct spi_device *spi, pm_message_t state)
-{
-#ifdef CONFIG_PM
- struct max3107_port *s = dev_get_drvdata(&spi->dev);
-
- pr_debug("enter suspend\n");
-
- /* Suspend UART port */
- uart_suspend_port(&max3107_uart_driver, &s->port);
-
- /* Go to suspend mode */
- if (s->pdata->hw_suspend)
- s->pdata->hw_suspend(s, 1);
-#endif /* CONFIG_PM */
- return 0;
-}
-EXPORT_SYMBOL_GPL(max3107_suspend);
-
-/* Driver resume function */
-int max3107_resume(struct spi_device *spi)
-{
-#ifdef CONFIG_PM
- struct max3107_port *s = dev_get_drvdata(&spi->dev);
-
- pr_debug("enter resume\n");
-
- /* Resume from suspend */
- if (s->pdata->hw_suspend)
- s->pdata->hw_suspend(s, 0);
-
- /* Resume UART port */
- uart_resume_port(&max3107_uart_driver, &s->port);
-#endif /* CONFIG_PM */
- return 0;
-}
-EXPORT_SYMBOL_GPL(max3107_resume);
-
-static int max3107_probe_generic(struct spi_device *spi)
-{
- return max3107_probe(spi, &generic_plat_data);
-}
-
-/* Spi driver data */
-static struct spi_driver max3107_driver = {
- .driver = {
- .name = "max3107",
- .owner = THIS_MODULE,
- },
- .probe = max3107_probe_generic,
- .remove = __devexit_p(max3107_remove),
- .suspend = max3107_suspend,
- .resume = max3107_resume,
-};
-
-/* Driver init function */
-static int __init max3107_init(void)
-{
- pr_info("enter max3107 init\n");
- return spi_register_driver(&max3107_driver);
-}
-
-/* Driver exit function */
-static void __exit max3107_exit(void)
-{
- pr_info("enter max3107 exit\n");
- /* Unregister UART driver */
- if (driver_registered)
- uart_unregister_driver(&max3107_uart_driver);
- spi_unregister_driver(&max3107_driver);
-}
-
-module_init(max3107_init);
-module_exit(max3107_exit);
-
-MODULE_DESCRIPTION("MAX3107 driver");
-MODULE_AUTHOR("Aavamobile");
-MODULE_ALIAS("spi:max3107");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/tty/serial/max3107.h b/drivers/tty/serial/max3107.h
deleted file mode 100644
index 8415fc7..0000000
--- a/drivers/tty/serial/max3107.h
+++ /dev/null
@@ -1,441 +0,0 @@
-/*
- * max3107.h - spi uart protocol driver header for Maxim 3107
- *
- * Copyright (C) Aavamobile 2009
- * Based on serial_max3100.h by Christian Pellegrin
- *
- * 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 _MAX3107_H
-#define _MAX3107_H
-
-/* Serial error status definitions */
-#define MAX3107_PARITY_ERROR 1
-#define MAX3107_FRAME_ERROR 2
-#define MAX3107_OVERRUN_ERROR 4
-#define MAX3107_ALL_ERRORS (MAX3107_PARITY_ERROR | \
- MAX3107_FRAME_ERROR | \
- MAX3107_OVERRUN_ERROR)
-
-/* GPIO definitions */
-#define MAX3107_GPIO_BASE 88
-#define MAX3107_GPIO_COUNT 4
-
-
-/* GPIO connected to chip's reset pin */
-#define MAX3107_RESET_GPIO 87
-
-
-/* Chip reset delay */
-#define MAX3107_RESET_DELAY 10
-
-/* Chip wakeup delay */
-#define MAX3107_WAKEUP_DELAY 50
-
-
-/* Sleep mode definitions */
-#define MAX3107_DISABLE_FORCED_SLEEP 0
-#define MAX3107_ENABLE_FORCED_SLEEP 1
-#define MAX3107_DISABLE_AUTOSLEEP 2
-#define MAX3107_ENABLE_AUTOSLEEP 3
-
-
-/* Definitions for register access with SPI transfers
- *
- * SPI transfer format:
- *
- * Master to slave bits xzzzzzzzyyyyyyyy
- * Slave to master bits aaaaaaaabbbbbbbb
- *
- * where:
- * x = 0 for reads, 1 for writes
- * z = register address
- * y = new register value if write, 0 if read
- * a = unspecified
- * b = register value if read, unspecified if write
- */
-
-/* SPI speed */
-#define MAX3107_SPI_SPEED (3125000 * 2)
-
-/* Write bit */
-#define MAX3107_WRITE_BIT (1 << 15)
-
-/* SPI TX data mask */
-#define MAX3107_SPI_RX_DATA_MASK (0x00ff)
-
-/* SPI RX data mask */
-#define MAX3107_SPI_TX_DATA_MASK (0x00ff)
-
-/* Register access masks */
-#define MAX3107_RHR_REG (0x0000) /* RX FIFO */
-#define MAX3107_THR_REG (0x0000) /* TX FIFO */
-#define MAX3107_IRQEN_REG (0x0100) /* IRQ enable */
-#define MAX3107_IRQSTS_REG (0x0200) /* IRQ status */
-#define MAX3107_LSR_IRQEN_REG (0x0300) /* LSR IRQ enable */
-#define MAX3107_LSR_IRQSTS_REG (0x0400) /* LSR IRQ status */
-#define MAX3107_SPCHR_IRQEN_REG (0x0500) /* Special char IRQ enable */
-#define MAX3107_SPCHR_IRQSTS_REG (0x0600) /* Special char IRQ status */
-#define MAX3107_STS_IRQEN_REG (0x0700) /* Status IRQ enable */
-#define MAX3107_STS_IRQSTS_REG (0x0800) /* Status IRQ status */
-#define MAX3107_MODE1_REG (0x0900) /* MODE1 */
-#define MAX3107_MODE2_REG (0x0a00) /* MODE2 */
-#define MAX3107_LCR_REG (0x0b00) /* LCR */
-#define MAX3107_RXTO_REG (0x0c00) /* RX timeout */
-#define MAX3107_HDPIXDELAY_REG (0x0d00) /* Auto transceiver delays */
-#define MAX3107_IRDA_REG (0x0e00) /* IRDA settings */
-#define MAX3107_FLOWLVL_REG (0x0f00) /* Flow control levels */
-#define MAX3107_FIFOTRIGLVL_REG (0x1000) /* FIFO IRQ trigger levels */
-#define MAX3107_TXFIFOLVL_REG (0x1100) /* TX FIFO level */
-#define MAX3107_RXFIFOLVL_REG (0x1200) /* RX FIFO level */
-#define MAX3107_FLOWCTRL_REG (0x1300) /* Flow control */
-#define MAX3107_XON1_REG (0x1400) /* XON1 character */
-#define MAX3107_XON2_REG (0x1500) /* XON2 character */
-#define MAX3107_XOFF1_REG (0x1600) /* XOFF1 character */
-#define MAX3107_XOFF2_REG (0x1700) /* XOFF2 character */
-#define MAX3107_GPIOCFG_REG (0x1800) /* GPIO config */
-#define MAX3107_GPIODATA_REG (0x1900) /* GPIO data */
-#define MAX3107_PLLCFG_REG (0x1a00) /* PLL config */
-#define MAX3107_BRGCFG_REG (0x1b00) /* Baud rate generator conf */
-#define MAX3107_BRGDIVLSB_REG (0x1c00) /* Baud rate divisor LSB */
-#define MAX3107_BRGDIVMSB_REG (0x1d00) /* Baud rate divisor MSB */
-#define MAX3107_CLKSRC_REG (0x1e00) /* Clock source */
-#define MAX3107_REVID_REG (0x1f00) /* Revision identification */
-
-/* IRQ register bits */
-#define MAX3107_IRQ_LSR_BIT (1 << 0) /* LSR interrupt */
-#define MAX3107_IRQ_SPCHR_BIT (1 << 1) /* Special char interrupt */
-#define MAX3107_IRQ_STS_BIT (1 << 2) /* Status interrupt */
-#define MAX3107_IRQ_RXFIFO_BIT (1 << 3) /* RX FIFO interrupt */
-#define MAX3107_IRQ_TXFIFO_BIT (1 << 4) /* TX FIFO interrupt */
-#define MAX3107_IRQ_TXEMPTY_BIT (1 << 5) /* TX FIFO empty interrupt */
-#define MAX3107_IRQ_RXEMPTY_BIT (1 << 6) /* RX FIFO empty interrupt */
-#define MAX3107_IRQ_CTS_BIT (1 << 7) /* CTS interrupt */
-
-/* LSR register bits */
-#define MAX3107_LSR_RXTO_BIT (1 << 0) /* RX timeout */
-#define MAX3107_LSR_RXOVR_BIT (1 << 1) /* RX overrun */
-#define MAX3107_LSR_RXPAR_BIT (1 << 2) /* RX parity error */
-#define MAX3107_LSR_FRERR_BIT (1 << 3) /* Frame error */
-#define MAX3107_LSR_RXBRK_BIT (1 << 4) /* RX break */
-#define MAX3107_LSR_RXNOISE_BIT (1 << 5) /* RX noise */
-#define MAX3107_LSR_UNDEF6_BIT (1 << 6) /* Undefined/not used */
-#define MAX3107_LSR_CTS_BIT (1 << 7) /* CTS pin state */
-
-/* Special character register bits */
-#define MAX3107_SPCHR_XON1_BIT (1 << 0) /* XON1 character */
-#define MAX3107_SPCHR_XON2_BIT (1 << 1) /* XON2 character */
-#define MAX3107_SPCHR_XOFF1_BIT (1 << 2) /* XOFF1 character */
-#define MAX3107_SPCHR_XOFF2_BIT (1 << 3) /* XOFF2 character */
-#define MAX3107_SPCHR_BREAK_BIT (1 << 4) /* RX break */
-#define MAX3107_SPCHR_MULTIDROP_BIT (1 << 5) /* 9-bit multidrop addr char */
-#define MAX3107_SPCHR_UNDEF6_BIT (1 << 6) /* Undefined/not used */
-#define MAX3107_SPCHR_UNDEF7_BIT (1 << 7) /* Undefined/not used */
-
-/* Status register bits */
-#define MAX3107_STS_GPIO0_BIT (1 << 0) /* GPIO 0 interrupt */
-#define MAX3107_STS_GPIO1_BIT (1 << 1) /* GPIO 1 interrupt */
-#define MAX3107_STS_GPIO2_BIT (1 << 2) /* GPIO 2 interrupt */
-#define MAX3107_STS_GPIO3_BIT (1 << 3) /* GPIO 3 interrupt */
-#define MAX3107_STS_UNDEF4_BIT (1 << 4) /* Undefined/not used */
-#define MAX3107_STS_CLKREADY_BIT (1 << 5) /* Clock ready */
-#define MAX3107_STS_SLEEP_BIT (1 << 6) /* Sleep interrupt */
-#define MAX3107_STS_UNDEF7_BIT (1 << 7) /* Undefined/not used */
-
-/* MODE1 register bits */
-#define MAX3107_MODE1_RXDIS_BIT (1 << 0) /* RX disable */
-#define MAX3107_MODE1_TXDIS_BIT (1 << 1) /* TX disable */
-#define MAX3107_MODE1_TXHIZ_BIT (1 << 2) /* TX pin three-state */
-#define MAX3107_MODE1_RTSHIZ_BIT (1 << 3) /* RTS pin three-state */
-#define MAX3107_MODE1_TRNSCVCTRL_BIT (1 << 4) /* Transceiver ctrl enable */
-#define MAX3107_MODE1_FORCESLEEP_BIT (1 << 5) /* Force sleep mode */
-#define MAX3107_MODE1_AUTOSLEEP_BIT (1 << 6) /* Auto sleep enable */
-#define MAX3107_MODE1_IRQSEL_BIT (1 << 7) /* IRQ pin enable */
-
-/* MODE2 register bits */
-#define MAX3107_MODE2_RST_BIT (1 << 0) /* Chip reset */
-#define MAX3107_MODE2_FIFORST_BIT (1 << 1) /* FIFO reset */
-#define MAX3107_MODE2_RXTRIGINV_BIT (1 << 2) /* RX FIFO INT invert */
-#define MAX3107_MODE2_RXEMPTINV_BIT (1 << 3) /* RX FIFO empty INT invert */
-#define MAX3107_MODE2_SPCHR_BIT (1 << 4) /* Special chr detect enable */
-#define MAX3107_MODE2_LOOPBACK_BIT (1 << 5) /* Internal loopback enable */
-#define MAX3107_MODE2_MULTIDROP_BIT (1 << 6) /* 9-bit multidrop enable */
-#define MAX3107_MODE2_ECHOSUPR_BIT (1 << 7) /* ECHO suppression enable */
-
-/* LCR register bits */
-#define MAX3107_LCR_LENGTH0_BIT (1 << 0) /* Word length bit 0 */
-#define MAX3107_LCR_LENGTH1_BIT (1 << 1) /* Word length bit 1
- *
- * Word length bits table:
- * 00 -> 5 bit words
- * 01 -> 6 bit words
- * 10 -> 7 bit words
- * 11 -> 8 bit words
- */
-#define MAX3107_LCR_STOPLEN_BIT (1 << 2) /* STOP length bit
- *
- * STOP length bit table:
- * 0 -> 1 stop bit
- * 1 -> 1-1.5 stop bits if
- * word length is 5,
- * 2 stop bits otherwise
- */
-#define MAX3107_LCR_PARITY_BIT (1 << 3) /* Parity bit enable */
-#define MAX3107_LCR_EVENPARITY_BIT (1 << 4) /* Even parity bit enable */
-#define MAX3107_LCR_FORCEPARITY_BIT (1 << 5) /* 9-bit multidrop parity */
-#define MAX3107_LCR_TXBREAK_BIT (1 << 6) /* TX break enable */
-#define MAX3107_LCR_RTS_BIT (1 << 7) /* RTS pin control */
-#define MAX3107_LCR_WORD_LEN_5 (0x0000)
-#define MAX3107_LCR_WORD_LEN_6 (0x0001)
-#define MAX3107_LCR_WORD_LEN_7 (0x0002)
-#define MAX3107_LCR_WORD_LEN_8 (0x0003)
-
-
-/* IRDA register bits */
-#define MAX3107_IRDA_IRDAEN_BIT (1 << 0) /* IRDA mode enable */
-#define MAX3107_IRDA_SIR_BIT (1 << 1) /* SIR mode enable */
-#define MAX3107_IRDA_SHORTIR_BIT (1 << 2) /* Short SIR mode enable */
-#define MAX3107_IRDA_MIR_BIT (1 << 3) /* MIR mode enable */
-#define MAX3107_IRDA_RXINV_BIT (1 << 4) /* RX logic inversion enable */
-#define MAX3107_IRDA_TXINV_BIT (1 << 5) /* TX logic inversion enable */
-#define MAX3107_IRDA_UNDEF6_BIT (1 << 6) /* Undefined/not used */
-#define MAX3107_IRDA_UNDEF7_BIT (1 << 7) /* Undefined/not used */
-
-/* Flow control trigger level register masks */
-#define MAX3107_FLOWLVL_HALT_MASK (0x000f) /* Flow control halt level */
-#define MAX3107_FLOWLVL_RES_MASK (0x00f0) /* Flow control resume level */
-#define MAX3107_FLOWLVL_HALT(words) ((words/8) & 0x000f)
-#define MAX3107_FLOWLVL_RES(words) (((words/8) & 0x000f) << 4)
-
-/* FIFO interrupt trigger level register masks */
-#define MAX3107_FIFOTRIGLVL_TX_MASK (0x000f) /* TX FIFO trigger level */
-#define MAX3107_FIFOTRIGLVL_RX_MASK (0x00f0) /* RX FIFO trigger level */
-#define MAX3107_FIFOTRIGLVL_TX(words) ((words/8) & 0x000f)
-#define MAX3107_FIFOTRIGLVL_RX(words) (((words/8) & 0x000f) << 4)
-
-/* Flow control register bits */
-#define MAX3107_FLOWCTRL_AUTORTS_BIT (1 << 0) /* Auto RTS flow ctrl enable */
-#define MAX3107_FLOWCTRL_AUTOCTS_BIT (1 << 1) /* Auto CTS flow ctrl enable */
-#define MAX3107_FLOWCTRL_GPIADDR_BIT (1 << 2) /* Enables that GPIO inputs
- * are used in conjunction with
- * XOFF2 for definition of
- * special character */
-#define MAX3107_FLOWCTRL_SWFLOWEN_BIT (1 << 3) /* Auto SW flow ctrl enable */
-#define MAX3107_FLOWCTRL_SWFLOW0_BIT (1 << 4) /* SWFLOW bit 0 */
-#define MAX3107_FLOWCTRL_SWFLOW1_BIT (1 << 5) /* SWFLOW bit 1
- *
- * SWFLOW bits 1 & 0 table:
- * 00 -> no transmitter flow
- * control
- * 01 -> receiver compares
- * XON2 and XOFF2
- * and controls
- * transmitter
- * 10 -> receiver compares
- * XON1 and XOFF1
- * and controls
- * transmitter
- * 11 -> receiver compares
- * XON1, XON2, XOFF1 and
- * XOFF2 and controls
- * transmitter
- */
-#define MAX3107_FLOWCTRL_SWFLOW2_BIT (1 << 6) /* SWFLOW bit 2 */
-#define MAX3107_FLOWCTRL_SWFLOW3_BIT (1 << 7) /* SWFLOW bit 3
- *
- * SWFLOW bits 3 & 2 table:
- * 00 -> no received flow
- * control
- * 01 -> transmitter generates
- * XON2 and XOFF2
- * 10 -> transmitter generates
- * XON1 and XOFF1
- * 11 -> transmitter generates
- * XON1, XON2, XOFF1 and
- * XOFF2
- */
-
-/* GPIO configuration register bits */
-#define MAX3107_GPIOCFG_GP0OUT_BIT (1 << 0) /* GPIO 0 output enable */
-#define MAX3107_GPIOCFG_GP1OUT_BIT (1 << 1) /* GPIO 1 output enable */
-#define MAX3107_GPIOCFG_GP2OUT_BIT (1 << 2) /* GPIO 2 output enable */
-#define MAX3107_GPIOCFG_GP3OUT_BIT (1 << 3) /* GPIO 3 output enable */
-#define MAX3107_GPIOCFG_GP0OD_BIT (1 << 4) /* GPIO 0 open-drain enable */
-#define MAX3107_GPIOCFG_GP1OD_BIT (1 << 5) /* GPIO 1 open-drain enable */
-#define MAX3107_GPIOCFG_GP2OD_BIT (1 << 6) /* GPIO 2 open-drain enable */
-#define MAX3107_GPIOCFG_GP3OD_BIT (1 << 7) /* GPIO 3 open-drain enable */
-
-/* GPIO DATA register bits */
-#define MAX3107_GPIODATA_GP0OUT_BIT (1 << 0) /* GPIO 0 output value */
-#define MAX3107_GPIODATA_GP1OUT_BIT (1 << 1) /* GPIO 1 output value */
-#define MAX3107_GPIODATA_GP2OUT_BIT (1 << 2) /* GPIO 2 output value */
-#define MAX3107_GPIODATA_GP3OUT_BIT (1 << 3) /* GPIO 3 output value */
-#define MAX3107_GPIODATA_GP0IN_BIT (1 << 4) /* GPIO 0 input value */
-#define MAX3107_GPIODATA_GP1IN_BIT (1 << 5) /* GPIO 1 input value */
-#define MAX3107_GPIODATA_GP2IN_BIT (1 << 6) /* GPIO 2 input value */
-#define MAX3107_GPIODATA_GP3IN_BIT (1 << 7) /* GPIO 3 input value */
-
-/* PLL configuration register masks */
-#define MAX3107_PLLCFG_PREDIV_MASK (0x003f) /* PLL predivision value */
-#define MAX3107_PLLCFG_PLLFACTOR_MASK (0x00c0) /* PLL multiplication factor */
-
-/* Baud rate generator configuration register masks and bits */
-#define MAX3107_BRGCFG_FRACT_MASK (0x000f) /* Fractional portion of
- * Baud rate generator divisor
- */
-#define MAX3107_BRGCFG_2XMODE_BIT (1 << 4) /* Double baud rate */
-#define MAX3107_BRGCFG_4XMODE_BIT (1 << 5) /* Quadruple baud rate */
-#define MAX3107_BRGCFG_UNDEF6_BIT (1 << 6) /* Undefined/not used */
-#define MAX3107_BRGCFG_UNDEF7_BIT (1 << 7) /* Undefined/not used */
-
-/* Clock source register bits */
-#define MAX3107_CLKSRC_INTOSC_BIT (1 << 0) /* Internal osc enable */
-#define MAX3107_CLKSRC_CRYST_BIT (1 << 1) /* Crystal osc enable */
-#define MAX3107_CLKSRC_PLL_BIT (1 << 2) /* PLL enable */
-#define MAX3107_CLKSRC_PLLBYP_BIT (1 << 3) /* PLL bypass */
-#define MAX3107_CLKSRC_EXTCLK_BIT (1 << 4) /* External clock enable */
-#define MAX3107_CLKSRC_UNDEF5_BIT (1 << 5) /* Undefined/not used */
-#define MAX3107_CLKSRC_UNDEF6_BIT (1 << 6) /* Undefined/not used */
-#define MAX3107_CLKSRC_CLK2RTS_BIT (1 << 7) /* Baud clk to RTS pin */
-
-
-/* HW definitions */
-#define MAX3107_RX_FIFO_SIZE 128
-#define MAX3107_TX_FIFO_SIZE 128
-#define MAX3107_REVID1 0x00a0
-#define MAX3107_REVID2 0x00a1
-
-
-/* Baud rate generator configuration values for external clock 13MHz */
-#define MAX3107_BRG13_B300 (0x0A9400 | 0x05)
-#define MAX3107_BRG13_B600 (0x054A00 | 0x03)
-#define MAX3107_BRG13_B1200 (0x02A500 | 0x01)
-#define MAX3107_BRG13_B2400 (0x015200 | 0x09)
-#define MAX3107_BRG13_B4800 (0x00A900 | 0x04)
-#define MAX3107_BRG13_B9600 (0x005400 | 0x0A)
-#define MAX3107_BRG13_B19200 (0x002A00 | 0x05)
-#define MAX3107_BRG13_B38400 (0x001500 | 0x03)
-#define MAX3107_BRG13_B57600 (0x000E00 | 0x02)
-#define MAX3107_BRG13_B115200 (0x000700 | 0x01)
-#define MAX3107_BRG13_B230400 (0x000300 | 0x08)
-#define MAX3107_BRG13_B460800 (0x000100 | 0x0c)
-#define MAX3107_BRG13_B921600 (0x000100 | 0x1c)
-
-/* Baud rate generator configuration values for external clock 26MHz */
-#define MAX3107_BRG26_B300 (0x152800 | 0x0A)
-#define MAX3107_BRG26_B600 (0x0A9400 | 0x05)
-#define MAX3107_BRG26_B1200 (0x054A00 | 0x03)
-#define MAX3107_BRG26_B2400 (0x02A500 | 0x01)
-#define MAX3107_BRG26_B4800 (0x015200 | 0x09)
-#define MAX3107_BRG26_B9600 (0x00A900 | 0x04)
-#define MAX3107_BRG26_B19200 (0x005400 | 0x0A)
-#define MAX3107_BRG26_B38400 (0x002A00 | 0x05)
-#define MAX3107_BRG26_B57600 (0x001C00 | 0x03)
-#define MAX3107_BRG26_B115200 (0x000E00 | 0x02)
-#define MAX3107_BRG26_B230400 (0x000700 | 0x01)
-#define MAX3107_BRG26_B460800 (0x000300 | 0x08)
-#define MAX3107_BRG26_B921600 (0x000100 | 0x0C)
-
-/* Baud rate generator configuration values for internal clock */
-#define MAX3107_BRG13_IB300 (0x008000 | 0x00)
-#define MAX3107_BRG13_IB600 (0x004000 | 0x00)
-#define MAX3107_BRG13_IB1200 (0x002000 | 0x00)
-#define MAX3107_BRG13_IB2400 (0x001000 | 0x00)
-#define MAX3107_BRG13_IB4800 (0x000800 | 0x00)
-#define MAX3107_BRG13_IB9600 (0x000400 | 0x00)
-#define MAX3107_BRG13_IB19200 (0x000200 | 0x00)
-#define MAX3107_BRG13_IB38400 (0x000100 | 0x00)
-#define MAX3107_BRG13_IB57600 (0x000000 | 0x0B)
-#define MAX3107_BRG13_IB115200 (0x000000 | 0x05)
-#define MAX3107_BRG13_IB230400 (0x000000 | 0x03)
-#define MAX3107_BRG13_IB460800 (0x000000 | 0x00)
-#define MAX3107_BRG13_IB921600 (0x000000 | 0x00)
-
-
-struct baud_table {
- int baud;
- u32 new_brg;
-};
-
-struct max3107_port {
- /* UART port structure */
- struct uart_port port;
-
- /* SPI device structure */
- struct spi_device *spi;
-
-#if defined(CONFIG_GPIOLIB)
- /* GPIO chip structure */
- struct gpio_chip chip;
-#endif
-
- /* Workqueue that does all the magic */
- struct workqueue_struct *workqueue;
- struct work_struct work;
-
- /* Lock for shared data */
- spinlock_t data_lock;
-
- /* Device configuration */
- int ext_clk; /* 1 if external clock used */
- int loopback; /* Current loopback mode state */
- int baud; /* Current baud rate */
-
- /* State flags */
- int suspended; /* Indicates suspend mode */
- int tx_fifo_empty; /* Flag for TX FIFO state */
- int rx_enabled; /* Flag for receiver state */
- int tx_enabled; /* Flag for transmitter state */
-
- u16 irqen_reg; /* Current IRQ enable register value */
- /* Shared data */
- u16 mode1_reg; /* Current mode1 register value*/
- int mode1_commit; /* Flag for setting new mode1 register value */
- u16 lcr_reg; /* Current LCR register value */
- int lcr_commit; /* Flag for setting new LCR register value */
- u32 brg_cfg; /* Current Baud rate generator config */
- int brg_commit; /* Flag for setting new baud rate generator
- * config
- */
- struct baud_table *baud_tbl;
- int handle_irq; /* Indicates that IRQ should be handled */
-
- /* Rx buffer and str*/
- u16 *rxbuf;
- u8 *rxstr;
- /* Tx buffer*/
- u16 *txbuf;
-
- struct max3107_plat *pdata; /* Platform data */
-};
-
-/* Platform data structure */
-struct max3107_plat {
- /* Loopback mode enable */
- int loopback;
- /* External clock enable */
- int ext_clk;
- /* Called during the register initialisation */
- void (*init)(struct max3107_port *s);
- /* Called when the port is found and configured */
- int (*configure)(struct max3107_port *s);
- /* HW suspend function */
- void (*hw_suspend) (struct max3107_port *s, int suspend);
- /* Polling mode enable */
- int polled_mode;
- /* Polling period if polling mode enabled */
- int poll_time;
-};
-
-extern int max3107_rw(struct max3107_port *s, u8 *tx, u8 *rx, int len);
-extern void max3107_hw_susp(struct max3107_port *s, int suspend);
-extern int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata);
-extern int max3107_remove(struct spi_device *spi);
-extern int max3107_suspend(struct spi_device *spi, pm_message_t state);
-extern int max3107_resume(struct spi_device *spi);
-
-#endif /* _LINUX_SERIAL_MAX3107_H */
diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
new file mode 100644
index 0000000..2bc28a5
--- /dev/null
+++ b/drivers/tty/serial/max310x.c
@@ -0,0 +1,1260 @@
+/*
+ * Maxim (Dallas) MAX3107/8 serial driver
+ *
+ * Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
+ *
+ * Based on max3100.c, by Christian Pellegrin <chripell@evolware.org>
+ * Based on max3110.c, by Feng Tang <feng.tang@intel.com>
+ * Based on max3107.c, by Aavamobile
+ *
+ * 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.
+ */
+
+/* TODO: MAX3109 support (Dual) */
+/* TODO: MAX14830 support (Quad) */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/regmap.h>
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/platform_data/max310x.h>
+
+#define MAX310X_MAJOR 204
+#define MAX310X_MINOR 209
+
+/* MAX310X register definitions */
+#define MAX310X_RHR_REG (0x00) /* RX FIFO */
+#define MAX310X_THR_REG (0x00) /* TX FIFO */
+#define MAX310X_IRQEN_REG (0x01) /* IRQ enable */
+#define MAX310X_IRQSTS_REG (0x02) /* IRQ status */
+#define MAX310X_LSR_IRQEN_REG (0x03) /* LSR IRQ enable */
+#define MAX310X_LSR_IRQSTS_REG (0x04) /* LSR IRQ status */
+#define MAX310X_SPCHR_IRQEN_REG (0x05) /* Special char IRQ enable */
+#define MAX310X_SPCHR_IRQSTS_REG (0x06) /* Special char IRQ status */
+#define MAX310X_STS_IRQEN_REG (0x07) /* Status IRQ enable */
+#define MAX310X_STS_IRQSTS_REG (0x08) /* Status IRQ status */
+#define MAX310X_MODE1_REG (0x09) /* MODE1 */
+#define MAX310X_MODE2_REG (0x0a) /* MODE2 */
+#define MAX310X_LCR_REG (0x0b) /* LCR */
+#define MAX310X_RXTO_REG (0x0c) /* RX timeout */
+#define MAX310X_HDPIXDELAY_REG (0x0d) /* Auto transceiver delays */
+#define MAX310X_IRDA_REG (0x0e) /* IRDA settings */
+#define MAX310X_FLOWLVL_REG (0x0f) /* Flow control levels */
+#define MAX310X_FIFOTRIGLVL_REG (0x10) /* FIFO IRQ trigger levels */
+#define MAX310X_TXFIFOLVL_REG (0x11) /* TX FIFO level */
+#define MAX310X_RXFIFOLVL_REG (0x12) /* RX FIFO level */
+#define MAX310X_FLOWCTRL_REG (0x13) /* Flow control */
+#define MAX310X_XON1_REG (0x14) /* XON1 character */
+#define MAX310X_XON2_REG (0x15) /* XON2 character */
+#define MAX310X_XOFF1_REG (0x16) /* XOFF1 character */
+#define MAX310X_XOFF2_REG (0x17) /* XOFF2 character */
+#define MAX310X_GPIOCFG_REG (0x18) /* GPIO config */
+#define MAX310X_GPIODATA_REG (0x19) /* GPIO data */
+#define MAX310X_PLLCFG_REG (0x1a) /* PLL config */
+#define MAX310X_BRGCFG_REG (0x1b) /* Baud rate generator conf */
+#define MAX310X_BRGDIVLSB_REG (0x1c) /* Baud rate divisor LSB */
+#define MAX310X_BRGDIVMSB_REG (0x1d) /* Baud rate divisor MSB */
+#define MAX310X_CLKSRC_REG (0x1e) /* Clock source */
+/* Only present in MAX3107 */
+#define MAX3107_REVID_REG (0x1f) /* Revision identification */
+
+/* IRQ register bits */
+#define MAX310X_IRQ_LSR_BIT (1 << 0) /* LSR interrupt */
+#define MAX310X_IRQ_SPCHR_BIT (1 << 1) /* Special char interrupt */
+#define MAX310X_IRQ_STS_BIT (1 << 2) /* Status interrupt */
+#define MAX310X_IRQ_RXFIFO_BIT (1 << 3) /* RX FIFO interrupt */
+#define MAX310X_IRQ_TXFIFO_BIT (1 << 4) /* TX FIFO interrupt */
+#define MAX310X_IRQ_TXEMPTY_BIT (1 << 5) /* TX FIFO empty interrupt */
+#define MAX310X_IRQ_RXEMPTY_BIT (1 << 6) /* RX FIFO empty interrupt */
+#define MAX310X_IRQ_CTS_BIT (1 << 7) /* CTS interrupt */
+
+/* LSR register bits */
+#define MAX310X_LSR_RXTO_BIT (1 << 0) /* RX timeout */
+#define MAX310X_LSR_RXOVR_BIT (1 << 1) /* RX overrun */
+#define MAX310X_LSR_RXPAR_BIT (1 << 2) /* RX parity error */
+#define MAX310X_LSR_FRERR_BIT (1 << 3) /* Frame error */
+#define MAX310X_LSR_RXBRK_BIT (1 << 4) /* RX break */
+#define MAX310X_LSR_RXNOISE_BIT (1 << 5) /* RX noise */
+#define MAX310X_LSR_CTS_BIT (1 << 7) /* CTS pin state */
+
+/* Special character register bits */
+#define MAX310X_SPCHR_XON1_BIT (1 << 0) /* XON1 character */
+#define MAX310X_SPCHR_XON2_BIT (1 << 1) /* XON2 character */
+#define MAX310X_SPCHR_XOFF1_BIT (1 << 2) /* XOFF1 character */
+#define MAX310X_SPCHR_XOFF2_BIT (1 << 3) /* XOFF2 character */
+#define MAX310X_SPCHR_BREAK_BIT (1 << 4) /* RX break */
+#define MAX310X_SPCHR_MULTIDROP_BIT (1 << 5) /* 9-bit multidrop addr char */
+
+/* Status register bits */
+#define MAX310X_STS_GPIO0_BIT (1 << 0) /* GPIO 0 interrupt */
+#define MAX310X_STS_GPIO1_BIT (1 << 1) /* GPIO 1 interrupt */
+#define MAX310X_STS_GPIO2_BIT (1 << 2) /* GPIO 2 interrupt */
+#define MAX310X_STS_GPIO3_BIT (1 << 3) /* GPIO 3 interrupt */
+#define MAX310X_STS_CLKREADY_BIT (1 << 5) /* Clock ready */
+#define MAX310X_STS_SLEEP_BIT (1 << 6) /* Sleep interrupt */
+
+/* MODE1 register bits */
+#define MAX310X_MODE1_RXDIS_BIT (1 << 0) /* RX disable */
+#define MAX310X_MODE1_TXDIS_BIT (1 << 1) /* TX disable */
+#define MAX310X_MODE1_TXHIZ_BIT (1 << 2) /* TX pin three-state */
+#define MAX310X_MODE1_RTSHIZ_BIT (1 << 3) /* RTS pin three-state */
+#define MAX310X_MODE1_TRNSCVCTRL_BIT (1 << 4) /* Transceiver ctrl enable */
+#define MAX310X_MODE1_FORCESLEEP_BIT (1 << 5) /* Force sleep mode */
+#define MAX310X_MODE1_AUTOSLEEP_BIT (1 << 6) /* Auto sleep enable */
+#define MAX310X_MODE1_IRQSEL_BIT (1 << 7) /* IRQ pin enable */
+
+/* MODE2 register bits */
+#define MAX310X_MODE2_RST_BIT (1 << 0) /* Chip reset */
+#define MAX310X_MODE2_FIFORST_BIT (1 << 1) /* FIFO reset */
+#define MAX310X_MODE2_RXTRIGINV_BIT (1 << 2) /* RX FIFO INT invert */
+#define MAX310X_MODE2_RXEMPTINV_BIT (1 << 3) /* RX FIFO empty INT invert */
+#define MAX310X_MODE2_SPCHR_BIT (1 << 4) /* Special chr detect enable */
+#define MAX310X_MODE2_LOOPBACK_BIT (1 << 5) /* Internal loopback enable */
+#define MAX310X_MODE2_MULTIDROP_BIT (1 << 6) /* 9-bit multidrop enable */
+#define MAX310X_MODE2_ECHOSUPR_BIT (1 << 7) /* ECHO suppression enable */
+
+/* LCR register bits */
+#define MAX310X_LCR_LENGTH0_BIT (1 << 0) /* Word length bit 0 */
+#define MAX310X_LCR_LENGTH1_BIT (1 << 1) /* Word length bit 1
+ *
+ * Word length bits table:
+ * 00 -> 5 bit words
+ * 01 -> 6 bit words
+ * 10 -> 7 bit words
+ * 11 -> 8 bit words
+ */
+#define MAX310X_LCR_STOPLEN_BIT (1 << 2) /* STOP length bit
+ *
+ * STOP length bit table:
+ * 0 -> 1 stop bit
+ * 1 -> 1-1.5 stop bits if
+ * word length is 5,
+ * 2 stop bits otherwise
+ */
+#define MAX310X_LCR_PARITY_BIT (1 << 3) /* Parity bit enable */
+#define MAX310X_LCR_EVENPARITY_BIT (1 << 4) /* Even parity bit enable */
+#define MAX310X_LCR_FORCEPARITY_BIT (1 << 5) /* 9-bit multidrop parity */
+#define MAX310X_LCR_TXBREAK_BIT (1 << 6) /* TX break enable */
+#define MAX310X_LCR_RTS_BIT (1 << 7) /* RTS pin control */
+#define MAX310X_LCR_WORD_LEN_5 (0x00)
+#define MAX310X_LCR_WORD_LEN_6 (0x01)
+#define MAX310X_LCR_WORD_LEN_7 (0x02)
+#define MAX310X_LCR_WORD_LEN_8 (0x03)
+
+/* IRDA register bits */
+#define MAX310X_IRDA_IRDAEN_BIT (1 << 0) /* IRDA mode enable */
+#define MAX310X_IRDA_SIR_BIT (1 << 1) /* SIR mode enable */
+#define MAX310X_IRDA_SHORTIR_BIT (1 << 2) /* Short SIR mode enable */
+#define MAX310X_IRDA_MIR_BIT (1 << 3) /* MIR mode enable */
+#define MAX310X_IRDA_RXINV_BIT (1 << 4) /* RX logic inversion enable */
+#define MAX310X_IRDA_TXINV_BIT (1 << 5) /* TX logic inversion enable */
+
+/* Flow control trigger level register masks */
+#define MAX310X_FLOWLVL_HALT_MASK (0x000f) /* Flow control halt level */
+#define MAX310X_FLOWLVL_RES_MASK (0x00f0) /* Flow control resume level */
+#define MAX310X_FLOWLVL_HALT(words) ((words / 8) & 0x0f)
+#define MAX310X_FLOWLVL_RES(words) (((words / 8) & 0x0f) << 4)
+
+/* FIFO interrupt trigger level register masks */
+#define MAX310X_FIFOTRIGLVL_TX_MASK (0x0f) /* TX FIFO trigger level */
+#define MAX310X_FIFOTRIGLVL_RX_MASK (0xf0) /* RX FIFO trigger level */
+#define MAX310X_FIFOTRIGLVL_TX(words) ((words / 8) & 0x0f)
+#define MAX310X_FIFOTRIGLVL_RX(words) (((words / 8) & 0x0f) << 4)
+
+/* Flow control register bits */
+#define MAX310X_FLOWCTRL_AUTORTS_BIT (1 << 0) /* Auto RTS flow ctrl enable */
+#define MAX310X_FLOWCTRL_AUTOCTS_BIT (1 << 1) /* Auto CTS flow ctrl enable */
+#define MAX310X_FLOWCTRL_GPIADDR_BIT (1 << 2) /* Enables that GPIO inputs
+ * are used in conjunction with
+ * XOFF2 for definition of
+ * special character */
+#define MAX310X_FLOWCTRL_SWFLOWEN_BIT (1 << 3) /* Auto SW flow ctrl enable */
+#define MAX310X_FLOWCTRL_SWFLOW0_BIT (1 << 4) /* SWFLOW bit 0 */
+#define MAX310X_FLOWCTRL_SWFLOW1_BIT (1 << 5) /* SWFLOW bit 1
+ *
+ * SWFLOW bits 1 & 0 table:
+ * 00 -> no transmitter flow
+ * control
+ * 01 -> receiver compares
+ * XON2 and XOFF2
+ * and controls
+ * transmitter
+ * 10 -> receiver compares
+ * XON1 and XOFF1
+ * and controls
+ * transmitter
+ * 11 -> receiver compares
+ * XON1, XON2, XOFF1 and
+ * XOFF2 and controls
+ * transmitter
+ */
+#define MAX310X_FLOWCTRL_SWFLOW2_BIT (1 << 6) /* SWFLOW bit 2 */
+#define MAX310X_FLOWCTRL_SWFLOW3_BIT (1 << 7) /* SWFLOW bit 3
+ *
+ * SWFLOW bits 3 & 2 table:
+ * 00 -> no received flow
+ * control
+ * 01 -> transmitter generates
+ * XON2 and XOFF2
+ * 10 -> transmitter generates
+ * XON1 and XOFF1
+ * 11 -> transmitter generates
+ * XON1, XON2, XOFF1 and
+ * XOFF2
+ */
+
+/* GPIO configuration register bits */
+#define MAX310X_GPIOCFG_GP0OUT_BIT (1 << 0) /* GPIO 0 output enable */
+#define MAX310X_GPIOCFG_GP1OUT_BIT (1 << 1) /* GPIO 1 output enable */
+#define MAX310X_GPIOCFG_GP2OUT_BIT (1 << 2) /* GPIO 2 output enable */
+#define MAX310X_GPIOCFG_GP3OUT_BIT (1 << 3) /* GPIO 3 output enable */
+#define MAX310X_GPIOCFG_GP0OD_BIT (1 << 4) /* GPIO 0 open-drain enable */
+#define MAX310X_GPIOCFG_GP1OD_BIT (1 << 5) /* GPIO 1 open-drain enable */
+#define MAX310X_GPIOCFG_GP2OD_BIT (1 << 6) /* GPIO 2 open-drain enable */
+#define MAX310X_GPIOCFG_GP3OD_BIT (1 << 7) /* GPIO 3 open-drain enable */
+
+/* GPIO DATA register bits */
+#define MAX310X_GPIODATA_GP0OUT_BIT (1 << 0) /* GPIO 0 output value */
+#define MAX310X_GPIODATA_GP1OUT_BIT (1 << 1) /* GPIO 1 output value */
+#define MAX310X_GPIODATA_GP2OUT_BIT (1 << 2) /* GPIO 2 output value */
+#define MAX310X_GPIODATA_GP3OUT_BIT (1 << 3) /* GPIO 3 output value */
+#define MAX310X_GPIODATA_GP0IN_BIT (1 << 4) /* GPIO 0 input value */
+#define MAX310X_GPIODATA_GP1IN_BIT (1 << 5) /* GPIO 1 input value */
+#define MAX310X_GPIODATA_GP2IN_BIT (1 << 6) /* GPIO 2 input value */
+#define MAX310X_GPIODATA_GP3IN_BIT (1 << 7) /* GPIO 3 input value */
+
+/* PLL configuration register masks */
+#define MAX310X_PLLCFG_PREDIV_MASK (0x3f) /* PLL predivision value */
+#define MAX310X_PLLCFG_PLLFACTOR_MASK (0xc0) /* PLL multiplication factor */
+
+/* Baud rate generator configuration register bits */
+#define MAX310X_BRGCFG_2XMODE_BIT (1 << 4) /* Double baud rate */
+#define MAX310X_BRGCFG_4XMODE_BIT (1 << 5) /* Quadruple baud rate */
+
+/* Clock source register bits */
+#define MAX310X_CLKSRC_CRYST_BIT (1 << 1) /* Crystal osc enable */
+#define MAX310X_CLKSRC_PLL_BIT (1 << 2) /* PLL enable */
+#define MAX310X_CLKSRC_PLLBYP_BIT (1 << 3) /* PLL bypass */
+#define MAX310X_CLKSRC_EXTCLK_BIT (1 << 4) /* External clock enable */
+#define MAX310X_CLKSRC_CLK2RTS_BIT (1 << 7) /* Baud clk to RTS pin */
+
+/* Misc definitions */
+#define MAX310X_FIFO_SIZE (128)
+
+/* MAX3107 specific */
+#define MAX3107_REV_ID (0xa0)
+#define MAX3107_REV_MASK (0xfe)
+
+/* IRQ status bits definitions */
+#define MAX310X_IRQ_TX (MAX310X_IRQ_TXFIFO_BIT | \
+ MAX310X_IRQ_TXEMPTY_BIT)
+#define MAX310X_IRQ_RX (MAX310X_IRQ_RXFIFO_BIT | \
+ MAX310X_IRQ_RXEMPTY_BIT)
+
+/* Supported chip types */
+enum {
+ MAX310X_TYPE_MAX3107 = 3107,
+ MAX310X_TYPE_MAX3108 = 3108,
+};
+
+struct max310x_port {
+ struct uart_driver uart;
+ struct uart_port port;
+
+ const char *name;
+ int uartclk;
+
+ unsigned int nr_gpio;
+#ifdef CONFIG_GPIOLIB
+ struct gpio_chip gpio;
+#endif
+
+ struct regmap *regmap;
+ struct regmap_config regcfg;
+
+ struct workqueue_struct *wq;
+ struct work_struct tx_work;
+
+ struct mutex max310x_mutex;
+
+ struct max310x_pdata *pdata;
+};
+
+static bool max3107_8_reg_writeable(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case MAX310X_IRQSTS_REG:
+ case MAX310X_LSR_IRQSTS_REG:
+ case MAX310X_SPCHR_IRQSTS_REG:
+ case MAX310X_STS_IRQSTS_REG:
+ case MAX310X_TXFIFOLVL_REG:
+ case MAX310X_RXFIFOLVL_REG:
+ case MAX3107_REVID_REG: /* Only available on MAX3107 */
+ return false;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+static bool max310x_reg_volatile(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case MAX310X_RHR_REG:
+ case MAX310X_IRQSTS_REG:
+ case MAX310X_LSR_IRQSTS_REG:
+ case MAX310X_SPCHR_IRQSTS_REG:
+ case MAX310X_STS_IRQSTS_REG:
+ case MAX310X_TXFIFOLVL_REG:
+ case MAX310X_RXFIFOLVL_REG:
+ case MAX310X_GPIODATA_REG:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+static bool max310x_reg_precious(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case MAX310X_RHR_REG:
+ case MAX310X_IRQSTS_REG:
+ case MAX310X_SPCHR_IRQSTS_REG:
+ case MAX310X_STS_IRQSTS_REG:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+static void max310x_set_baud(struct max310x_port *s, int baud)
+{
+ unsigned int mode = 0, div = s->uartclk / baud;
+
+ if (!(div / 16)) {
+ /* Mode x2 */
+ mode = MAX310X_BRGCFG_2XMODE_BIT;
+ div = (s->uartclk * 2) / baud;
+ }
+
+ if (!(div / 16)) {
+ /* Mode x4 */
+ mode = MAX310X_BRGCFG_4XMODE_BIT;
+ div = (s->uartclk * 4) / baud;
+ }
+
+ regmap_write(s->regmap, MAX310X_BRGDIVMSB_REG,
+ ((div / 16) >> 8) & 0xff);
+ regmap_write(s->regmap, MAX310X_BRGDIVLSB_REG, (div / 16) & 0xff);
+ regmap_write(s->regmap, MAX310X_BRGCFG_REG, (div % 16) | mode);
+}
+
+static void max310x_wait_pll(struct max310x_port *s)
+{
+ int tryes = 1000;
+
+ /* Wait for PLL only if crystal is used */
+ if (!(s->pdata->driver_flags & MAX310X_EXT_CLK)) {
+ unsigned int sts = 0;
+
+ while (tryes--) {
+ regmap_read(s->regmap, MAX310X_STS_IRQSTS_REG, &sts);
+ if (sts & MAX310X_STS_CLKREADY_BIT)
+ break;
+ }
+ }
+}
+
+static int __devinit max310x_update_best_err(unsigned long f, long *besterr)
+{
+ /* Use baudrate 115200 for calculate error */
+ long err = f % (115200 * 16);
+
+ if ((*besterr < 0) || (*besterr > err)) {
+ *besterr = err;
+ return 0;
+ }
+
+ return 1;
+}
+
+static int __devinit max310x_set_ref_clk(struct max310x_port *s)
+{
+ unsigned int div, clksrc, pllcfg = 0;
+ long besterr = -1;
+ unsigned long fdiv, fmul, bestfreq = s->pdata->frequency;
+
+ /* First, update error without PLL */
+ max310x_update_best_err(s->pdata->frequency, &besterr);
+
+ /* Try all possible PLL dividers */
+ for (div = 1; (div <= 63) && besterr; div++) {
+ fdiv = DIV_ROUND_CLOSEST(s->pdata->frequency, div);
+
+ /* Try multiplier 6 */
+ fmul = fdiv * 6;
+ if ((fdiv >= 500000) && (fdiv <= 800000))
+ if (!max310x_update_best_err(fmul, &besterr)) {
+ pllcfg = (0 << 6) | div;
+ bestfreq = fmul;
+ }
+ /* Try multiplier 48 */
+ fmul = fdiv * 48;
+ if ((fdiv >= 850000) && (fdiv <= 1200000))
+ if (!max310x_update_best_err(fmul, &besterr)) {
+ pllcfg = (1 << 6) | div;
+ bestfreq = fmul;
+ }
+ /* Try multiplier 96 */
+ fmul = fdiv * 96;
+ if ((fdiv >= 425000) && (fdiv <= 1000000))
+ if (!max310x_update_best_err(fmul, &besterr)) {
+ pllcfg = (2 << 6) | div;
+ bestfreq = fmul;
+ }
+ /* Try multiplier 144 */
+ fmul = fdiv * 144;
+ if ((fdiv >= 390000) && (fdiv <= 667000))
+ if (!max310x_update_best_err(fmul, &besterr)) {
+ pllcfg = (3 << 6) | div;
+ bestfreq = fmul;
+ }
+ }
+
+ /* Configure clock source */
+ if (s->pdata->driver_flags & MAX310X_EXT_CLK)
+ clksrc = MAX310X_CLKSRC_EXTCLK_BIT;
+ else
+ clksrc = MAX310X_CLKSRC_CRYST_BIT;
+
+ /* Configure PLL */
+ if (pllcfg) {
+ clksrc |= MAX310X_CLKSRC_PLL_BIT;
+ regmap_write(s->regmap, MAX310X_PLLCFG_REG, pllcfg);
+ } else
+ clksrc |= MAX310X_CLKSRC_PLLBYP_BIT;
+
+ regmap_write(s->regmap, MAX310X_CLKSRC_REG, clksrc);
+
+ if (pllcfg)
+ max310x_wait_pll(s);
+
+ dev_dbg(s->port.dev, "Reference clock set to %lu Hz\n", bestfreq);
+
+ return (int)bestfreq;
+}
+
+static void max310x_handle_rx(struct max310x_port *s, unsigned int rxlen)
+{
+ unsigned int sts = 0, ch = 0, flag;
+ struct tty_struct *tty = tty_port_tty_get(&s->port.state->port);
+
+ if (!tty)
+ return;
+
+ if (unlikely(rxlen >= MAX310X_FIFO_SIZE)) {
+ dev_warn(s->port.dev, "Possible RX FIFO overrun %d\n", rxlen);
+ /* Ensure sanity of RX level */
+ rxlen = MAX310X_FIFO_SIZE;
+ }
+
+ dev_dbg(s->port.dev, "RX Len = %u\n", rxlen);
+
+ while (rxlen--) {
+ regmap_read(s->regmap, MAX310X_RHR_REG, &ch);
+ regmap_read(s->regmap, MAX310X_LSR_IRQSTS_REG, &sts);
+
+ sts &= MAX310X_LSR_RXPAR_BIT | MAX310X_LSR_FRERR_BIT |
+ MAX310X_LSR_RXOVR_BIT | MAX310X_LSR_RXBRK_BIT;
+
+ s->port.icount.rx++;
+ flag = TTY_NORMAL;
+
+ if (unlikely(sts)) {
+ if (sts & MAX310X_LSR_RXBRK_BIT) {
+ s->port.icount.brk++;
+ if (uart_handle_break(&s->port))
+ continue;
+ } else if (sts & MAX310X_LSR_RXPAR_BIT)
+ s->port.icount.parity++;
+ else if (sts & MAX310X_LSR_FRERR_BIT)
+ s->port.icount.frame++;
+ else if (sts & MAX310X_LSR_RXOVR_BIT)
+ s->port.icount.overrun++;
+
+ sts &= s->port.read_status_mask;
+ if (sts & MAX310X_LSR_RXBRK_BIT)
+ flag = TTY_BREAK;
+ else if (sts & MAX310X_LSR_RXPAR_BIT)
+ flag = TTY_PARITY;
+ else if (sts & MAX310X_LSR_FRERR_BIT)
+ flag = TTY_FRAME;
+ else if (sts & MAX310X_LSR_RXOVR_BIT)
+ flag = TTY_OVERRUN;
+ }
+
+ if (uart_handle_sysrq_char(s->port, ch))
+ continue;
+
+ if (sts & s->port.ignore_status_mask)
+ continue;
+
+ uart_insert_char(&s->port, sts, MAX310X_LSR_RXOVR_BIT,
+ ch, flag);
+ }
+
+ tty_flip_buffer_push(tty);
+
+ tty_kref_put(tty);
+}
+
+static void max310x_handle_tx(struct max310x_port *s)
+{
+ struct circ_buf *xmit = &s->port.state->xmit;
+ unsigned int txlen = 0, to_send;
+
+ if (unlikely(s->port.x_char)) {
+ regmap_write(s->regmap, MAX310X_THR_REG, s->port.x_char);
+ s->port.icount.tx++;
+ s->port.x_char = 0;
+ return;
+ }
+
+ if (uart_circ_empty(xmit) || uart_tx_stopped(&s->port))
+ return;
+
+ /* Get length of data pending in circular buffer */
+ to_send = uart_circ_chars_pending(xmit);
+ if (likely(to_send)) {
+ /* Limit to size of TX FIFO */
+ regmap_read(s->regmap, MAX310X_TXFIFOLVL_REG, &txlen);
+ txlen = MAX310X_FIFO_SIZE - txlen;
+ to_send = (to_send > txlen) ? txlen : to_send;
+
+ dev_dbg(s->port.dev, "TX Len = %u\n", to_send);
+
+ /* Add data to send */
+ s->port.icount.tx += to_send;
+ while (to_send--) {
+ regmap_write(s->regmap, MAX310X_THR_REG,
+ xmit->buf[xmit->tail]);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ };
+ }
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(&s->port);
+}
+
+static irqreturn_t max310x_ist(int irq, void *dev_id)
+{
+ struct max310x_port *s = (struct max310x_port *)dev_id;
+ unsigned int ists = 0, lsr = 0, rxlen = 0;
+
+ mutex_lock(&s->max310x_mutex);
+
+ for (;;) {
+ /* Read IRQ status & RX FIFO level */
+ regmap_read(s->regmap, MAX310X_IRQSTS_REG, &ists);
+ regmap_read(s->regmap, MAX310X_LSR_IRQSTS_REG, &lsr);
+ regmap_read(s->regmap, MAX310X_RXFIFOLVL_REG, &rxlen);
+ if (!ists && !(lsr & MAX310X_LSR_RXTO_BIT) && !rxlen)
+ break;
+
+ dev_dbg(s->port.dev, "IRQ status: 0x%02x\n", ists);
+
+ if (rxlen)
+ max310x_handle_rx(s, rxlen);
+ if (ists & MAX310X_IRQ_TX)
+ max310x_handle_tx(s);
+ if (ists & MAX310X_IRQ_CTS_BIT)
+ uart_handle_cts_change(&s->port,
+ !!(lsr & MAX310X_LSR_CTS_BIT));
+ }
+
+ mutex_unlock(&s->max310x_mutex);
+
+ return IRQ_HANDLED;
+}
+
+static void max310x_wq_proc(struct work_struct *ws)
+{
+ struct max310x_port *s = container_of(ws, struct max310x_port, tx_work);
+
+ mutex_lock(&s->max310x_mutex);
+ max310x_handle_tx(s);
+ mutex_unlock(&s->max310x_mutex);
+}
+
+static void max310x_start_tx(struct uart_port *port)
+{
+ struct max310x_port *s = container_of(port, struct max310x_port, port);
+
+ queue_work(s->wq, &s->tx_work);
+}
+
+static void max310x_stop_tx(struct uart_port *port)
+{
+ /* Do nothing */
+}
+
+static void max310x_stop_rx(struct uart_port *port)
+{
+ /* Do nothing */
+}
+
+static unsigned int max310x_tx_empty(struct uart_port *port)
+{
+ unsigned int val = 0;
+ struct max310x_port *s = container_of(port, struct max310x_port, port);
+
+ mutex_lock(&s->max310x_mutex);
+ regmap_read(s->regmap, MAX310X_TXFIFOLVL_REG, &val);
+ mutex_unlock(&s->max310x_mutex);
+
+ return val ? 0 : TIOCSER_TEMT;
+}
+
+static void max310x_enable_ms(struct uart_port *port)
+{
+ /* Modem status not supported */
+}
+
+static unsigned int max310x_get_mctrl(struct uart_port *port)
+{
+ /* DCD and DSR are not wired and CTS/RTS is handled automatically
+ * so just indicate DSR and CAR asserted
+ */
+ return TIOCM_DSR | TIOCM_CAR;
+}
+
+static void max310x_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ /* DCD and DSR are not wired and CTS/RTS is hadnled automatically
+ * so do nothing
+ */
+}
+
+static void max310x_break_ctl(struct uart_port *port, int break_state)
+{
+ struct max310x_port *s = container_of(port, struct max310x_port, port);
+
+ mutex_lock(&s->max310x_mutex);
+ regmap_update_bits(s->regmap, MAX310X_LCR_REG,
+ MAX310X_LCR_TXBREAK_BIT,
+ break_state ? MAX310X_LCR_TXBREAK_BIT : 0);
+ mutex_unlock(&s->max310x_mutex);
+}
+
+static void max310x_set_termios(struct uart_port *port,
+ struct ktermios *termios,
+ struct ktermios *old)
+{
+ struct max310x_port *s = container_of(port, struct max310x_port, port);
+ unsigned int lcr, flow = 0;
+ int baud;
+
+ mutex_lock(&s->max310x_mutex);
+
+ /* Mask termios capabilities we don't support */
+ termios->c_cflag &= ~CMSPAR;
+ termios->c_iflag &= ~IXANY;
+
+ /* Word size */
+ switch (termios->c_cflag & CSIZE) {
+ case CS5:
+ lcr = MAX310X_LCR_WORD_LEN_5;
+ break;
+ case CS6:
+ lcr = MAX310X_LCR_WORD_LEN_6;
+ break;
+ case CS7:
+ lcr = MAX310X_LCR_WORD_LEN_7;
+ break;
+ case CS8:
+ default:
+ lcr = MAX310X_LCR_WORD_LEN_8;
+ break;
+ }
+
+ /* Parity */
+ if (termios->c_cflag & PARENB) {
+ lcr |= MAX310X_LCR_PARITY_BIT;
+ if (!(termios->c_cflag & PARODD))
+ lcr |= MAX310X_LCR_EVENPARITY_BIT;
+ }
+
+ /* Stop bits */
+ if (termios->c_cflag & CSTOPB)
+ lcr |= MAX310X_LCR_STOPLEN_BIT; /* 2 stops */
+
+ /* Update LCR register */
+ regmap_write(s->regmap, MAX310X_LCR_REG, lcr);
+
+ /* Set read status mask */
+ port->read_status_mask = MAX310X_LSR_RXOVR_BIT;
+ if (termios->c_iflag & INPCK)
+ port->read_status_mask |= MAX310X_LSR_RXPAR_BIT |
+ MAX310X_LSR_FRERR_BIT;
+ if (termios->c_iflag & (BRKINT | PARMRK))
+ port->read_status_mask |= MAX310X_LSR_RXBRK_BIT;
+
+ /* Set status ignore mask */
+ port->ignore_status_mask = 0;
+ if (termios->c_iflag & IGNBRK)
+ port->ignore_status_mask |= MAX310X_LSR_RXBRK_BIT;
+ if (!(termios->c_cflag & CREAD))
+ port->ignore_status_mask |= MAX310X_LSR_RXPAR_BIT |
+ MAX310X_LSR_RXOVR_BIT |
+ MAX310X_LSR_FRERR_BIT |
+ MAX310X_LSR_RXBRK_BIT;
+
+ /* Configure flow control */
+ regmap_write(s->regmap, MAX310X_XON1_REG, termios->c_cc[VSTART]);
+ regmap_write(s->regmap, MAX310X_XOFF1_REG, termios->c_cc[VSTOP]);
+ if (termios->c_cflag & CRTSCTS)
+ flow |= MAX310X_FLOWCTRL_AUTOCTS_BIT |
+ MAX310X_FLOWCTRL_AUTORTS_BIT;
+ if (termios->c_iflag & IXON)
+ flow |= MAX310X_FLOWCTRL_SWFLOW3_BIT |
+ MAX310X_FLOWCTRL_SWFLOWEN_BIT;
+ if (termios->c_iflag & IXOFF)
+ flow |= MAX310X_FLOWCTRL_SWFLOW1_BIT |
+ MAX310X_FLOWCTRL_SWFLOWEN_BIT;
+ regmap_write(s->regmap, MAX310X_FLOWCTRL_REG, flow);
+
+ /* Get baud rate generator configuration */
+ baud = uart_get_baud_rate(port, termios, old,
+ port->uartclk / 16 / 0xffff,
+ port->uartclk / 4);
+
+ /* Setup baudrate generator */
+ max310x_set_baud(s, baud);
+
+ /* Update timeout according to new baud rate */
+ uart_update_timeout(port, termios->c_cflag, baud);
+
+ mutex_unlock(&s->max310x_mutex);
+}
+
+static int max310x_startup(struct uart_port *port)
+{
+ unsigned int val, line = port->line;
+ struct max310x_port *s = container_of(port, struct max310x_port, port);
+
+ if (s->pdata->suspend)
+ s->pdata->suspend(0);
+
+ mutex_lock(&s->max310x_mutex);
+
+ /* Configure baud rate, 9600 as default */
+ max310x_set_baud(s, 9600);
+
+ /* Configure LCR register, 8N1 mode by default */
+ val = MAX310X_LCR_WORD_LEN_8;
+ regmap_write(s->regmap, MAX310X_LCR_REG, val);
+
+ /* Configure MODE1 register */
+ regmap_update_bits(s->regmap, MAX310X_MODE1_REG,
+ MAX310X_MODE1_TRNSCVCTRL_BIT,
+ (s->pdata->uart_flags[line] & MAX310X_AUTO_DIR_CTRL)
+ ? MAX310X_MODE1_TRNSCVCTRL_BIT : 0);
+
+ /* Configure MODE2 register */
+ val = MAX310X_MODE2_RXEMPTINV_BIT;
+ if (s->pdata->uart_flags[line] & MAX310X_LOOPBACK)
+ val |= MAX310X_MODE2_LOOPBACK_BIT;
+ if (s->pdata->uart_flags[line] & MAX310X_ECHO_SUPRESS)
+ val |= MAX310X_MODE2_ECHOSUPR_BIT;
+
+ /* Reset FIFOs */
+ val |= MAX310X_MODE2_FIFORST_BIT;
+ regmap_write(s->regmap, MAX310X_MODE2_REG, val);
+
+ /* Configure FIFO trigger level register */
+ /* RX FIFO trigger for 16 words, TX FIFO trigger for 64 words */
+ val = MAX310X_FIFOTRIGLVL_RX(16) | MAX310X_FIFOTRIGLVL_TX(64);
+ regmap_write(s->regmap, MAX310X_FIFOTRIGLVL_REG, val);
+
+ /* Configure flow control levels */
+ /* Flow control halt level 96, resume level 48 */
+ val = MAX310X_FLOWLVL_RES(48) | MAX310X_FLOWLVL_HALT(96);
+ regmap_write(s->regmap, MAX310X_FLOWLVL_REG, val);
+
+ /* Clear timeout register */
+ regmap_write(s->regmap, MAX310X_RXTO_REG, 0);
+
+ /* Configure LSR interrupt enable register */
+ /* Enable RX timeout interrupt */
+ val = MAX310X_LSR_RXTO_BIT;
+ regmap_write(s->regmap, MAX310X_LSR_IRQEN_REG, val);
+
+ /* Clear FIFO reset */
+ regmap_update_bits(s->regmap, MAX310X_MODE2_REG,
+ MAX310X_MODE2_FIFORST_BIT, 0);
+
+ /* Clear IRQ status register by reading it */
+ regmap_read(s->regmap, MAX310X_IRQSTS_REG, &val);
+
+ /* Configure interrupt enable register */
+ /* Enable CTS change interrupt */
+ val = MAX310X_IRQ_CTS_BIT;
+ /* Enable RX, TX interrupts */
+ val |= MAX310X_IRQ_RX | MAX310X_IRQ_TX;
+ regmap_write(s->regmap, MAX310X_IRQEN_REG, val);
+
+ mutex_unlock(&s->max310x_mutex);
+
+ return 0;
+}
+
+static void max310x_shutdown(struct uart_port *port)
+{
+ struct max310x_port *s = container_of(port, struct max310x_port, port);
+
+ /* Disable all interrupts */
+ mutex_lock(&s->max310x_mutex);
+ regmap_write(s->regmap, MAX310X_IRQEN_REG, 0);
+ mutex_unlock(&s->max310x_mutex);
+
+ if (s->pdata->suspend)
+ s->pdata->suspend(1);
+}
+
+static const char *max310x_type(struct uart_port *port)
+{
+ struct max310x_port *s = container_of(port, struct max310x_port, port);
+
+ return (port->type == PORT_MAX310X) ? s->name : NULL;
+}
+
+static int max310x_request_port(struct uart_port *port)
+{
+ /* Do nothing */
+ return 0;
+}
+
+static void max310x_release_port(struct uart_port *port)
+{
+ /* Do nothing */
+}
+
+static void max310x_config_port(struct uart_port *port, int flags)
+{
+ if (flags & UART_CONFIG_TYPE)
+ port->type = PORT_MAX310X;
+}
+
+static int max310x_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+ if ((ser->type == PORT_UNKNOWN) || (ser->type == PORT_MAX310X))
+ return 0;
+ if (ser->irq == port->irq)
+ return 0;
+
+ return -EINVAL;
+}
+
+static struct uart_ops max310x_ops = {
+ .tx_empty = max310x_tx_empty,
+ .set_mctrl = max310x_set_mctrl,
+ .get_mctrl = max310x_get_mctrl,
+ .stop_tx = max310x_stop_tx,
+ .start_tx = max310x_start_tx,
+ .stop_rx = max310x_stop_rx,
+ .enable_ms = max310x_enable_ms,
+ .break_ctl = max310x_break_ctl,
+ .startup = max310x_startup,
+ .shutdown = max310x_shutdown,
+ .set_termios = max310x_set_termios,
+ .type = max310x_type,
+ .request_port = max310x_request_port,
+ .release_port = max310x_release_port,
+ .config_port = max310x_config_port,
+ .verify_port = max310x_verify_port,
+};
+
+static int max310x_suspend(struct spi_device *spi, pm_message_t state)
+{
+ int ret;
+ struct max310x_port *s = dev_get_drvdata(&spi->dev);
+
+ dev_dbg(&spi->dev, "Suspend\n");
+
+ ret = uart_suspend_port(&s->uart, &s->port);
+
+ mutex_lock(&s->max310x_mutex);
+
+ /* Enable sleep mode */
+ regmap_update_bits(s->regmap, MAX310X_MODE1_REG,
+ MAX310X_MODE1_FORCESLEEP_BIT,
+ MAX310X_MODE1_FORCESLEEP_BIT);
+
+ mutex_unlock(&s->max310x_mutex);
+
+ if (s->pdata->suspend)
+ s->pdata->suspend(1);
+
+ return ret;
+}
+
+static int max310x_resume(struct spi_device *spi)
+{
+ struct max310x_port *s = dev_get_drvdata(&spi->dev);
+
+ dev_dbg(&spi->dev, "Resume\n");
+
+ if (s->pdata->suspend)
+ s->pdata->suspend(0);
+
+ mutex_lock(&s->max310x_mutex);
+
+ /* Disable sleep mode */
+ regmap_update_bits(s->regmap, MAX310X_MODE1_REG,
+ MAX310X_MODE1_FORCESLEEP_BIT,
+ 0);
+
+ max310x_wait_pll(s);
+
+ mutex_unlock(&s->max310x_mutex);
+
+ return uart_resume_port(&s->uart, &s->port);
+}
+
+#ifdef CONFIG_GPIOLIB
+static int max310x_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ unsigned int val = 0;
+ struct max310x_port *s = container_of(chip, struct max310x_port, gpio);
+
+ mutex_lock(&s->max310x_mutex);
+ regmap_read(s->regmap, MAX310X_GPIODATA_REG, &val);
+ mutex_unlock(&s->max310x_mutex);
+
+ return !!((val >> 4) & (1 << offset));
+}
+
+static void max310x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct max310x_port *s = container_of(chip, struct max310x_port, gpio);
+
+ mutex_lock(&s->max310x_mutex);
+ regmap_update_bits(s->regmap, MAX310X_GPIODATA_REG, 1 << offset, value ?
+ 1 << offset : 0);
+ mutex_unlock(&s->max310x_mutex);
+}
+
+static int max310x_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ struct max310x_port *s = container_of(chip, struct max310x_port, gpio);
+
+ mutex_lock(&s->max310x_mutex);
+
+ regmap_update_bits(s->regmap, MAX310X_GPIOCFG_REG, 1 << offset, 0);
+
+ mutex_unlock(&s->max310x_mutex);
+
+ return 0;
+}
+
+static int max310x_gpio_direction_output(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ struct max310x_port *s = container_of(chip, struct max310x_port, gpio);
+
+ mutex_lock(&s->max310x_mutex);
+
+ regmap_update_bits(s->regmap, MAX310X_GPIOCFG_REG, 1 << offset,
+ 1 << offset);
+ regmap_update_bits(s->regmap, MAX310X_GPIODATA_REG, 1 << offset, value ?
+ 1 << offset : 0);
+
+ mutex_unlock(&s->max310x_mutex);
+
+ return 0;
+}
+#endif
+
+/* Generic platform data */
+static struct max310x_pdata generic_plat_data = {
+ .driver_flags = MAX310X_EXT_CLK,
+ .uart_flags[0] = MAX310X_ECHO_SUPRESS,
+ .frequency = 26000000,
+};
+
+static int __devinit max310x_probe(struct spi_device *spi)
+{
+ struct max310x_port *s;
+ struct device *dev = &spi->dev;
+ int chiptype = spi_get_device_id(spi)->driver_data;
+ struct max310x_pdata *pdata = dev->platform_data;
+ unsigned int val = 0;
+ int ret;
+
+ /* Check for IRQ */
+ if (spi->irq <= 0) {
+ dev_err(dev, "No IRQ specified\n");
+ return -ENOTSUPP;
+ }
+
+ /* Alloc port structure */
+ s = devm_kzalloc(dev, sizeof(struct max310x_port), GFP_KERNEL);
+ if (!s) {
+ dev_err(dev, "Error allocating port structure\n");
+ return -ENOMEM;
+ }
+ dev_set_drvdata(dev, s);
+
+ if (!pdata) {
+ dev_warn(dev, "No platform data supplied, using defaults\n");
+ pdata = &generic_plat_data;
+ }
+ s->pdata = pdata;
+
+ /* Individual chip settings */
+ switch (chiptype) {
+ case MAX310X_TYPE_MAX3107:
+ s->name = "MAX3107";
+ s->nr_gpio = 4;
+ s->uart.nr = 1;
+ s->regcfg.max_register = 0x1f;
+ break;
+ case MAX310X_TYPE_MAX3108:
+ s->name = "MAX3108";
+ s->nr_gpio = 4;
+ s->uart.nr = 1;
+ s->regcfg.max_register = 0x1e;
+ break;
+ default:
+ dev_err(dev, "Unsupported chip type %i\n", chiptype);
+ return -ENOTSUPP;
+ }
+
+ /* Check input frequency */
+ if ((pdata->driver_flags & MAX310X_EXT_CLK) &&
+ ((pdata->frequency < 500000) || (pdata->frequency > 35000000)))
+ goto err_freq;
+ /* Check frequency for quartz */
+ if (!(pdata->driver_flags & MAX310X_EXT_CLK) &&
+ ((pdata->frequency < 1000000) || (pdata->frequency > 4000000)))
+ goto err_freq;
+
+ mutex_init(&s->max310x_mutex);
+
+ /* Setup SPI bus */
+ spi->mode = SPI_MODE_0;
+ spi->bits_per_word = 8;
+ spi->max_speed_hz = 26000000;
+ spi_setup(spi);
+
+ /* Setup regmap */
+ s->regcfg.reg_bits = 8;
+ s->regcfg.val_bits = 8;
+ s->regcfg.read_flag_mask = 0x00;
+ s->regcfg.write_flag_mask = 0x80;
+ s->regcfg.cache_type = REGCACHE_RBTREE;
+ s->regcfg.writeable_reg = max3107_8_reg_writeable;
+ s->regcfg.volatile_reg = max310x_reg_volatile;
+ s->regcfg.precious_reg = max310x_reg_precious;
+ s->regmap = devm_regmap_init_spi(spi, &s->regcfg);
+ if (IS_ERR(s->regmap)) {
+ ret = PTR_ERR(s->regmap);
+ dev_err(dev, "Failed to initialize register map\n");
+ goto err_out;
+ }
+
+ /* Reset chip & check SPI function */
+ ret = regmap_write(s->regmap, MAX310X_MODE2_REG, MAX310X_MODE2_RST_BIT);
+ if (ret) {
+ dev_err(dev, "SPI transfer failed\n");
+ goto err_out;
+ }
+ /* Clear chip reset */
+ regmap_write(s->regmap, MAX310X_MODE2_REG, 0);
+
+ switch (chiptype) {
+ case MAX310X_TYPE_MAX3107:
+ /* Check REV ID to ensure we are talking to what we expect */
+ regmap_read(s->regmap, MAX3107_REVID_REG, &val);
+ if (((val & MAX3107_REV_MASK) != MAX3107_REV_ID)) {
+ dev_err(dev, "%s ID 0x%02x does not match\n",
+ s->name, val);
+ ret = -ENODEV;
+ goto err_out;
+ }
+ break;
+ case MAX310X_TYPE_MAX3108:
+ /* MAX3108 have not REV ID register, we just check default value
+ * from clocksource register to make sure everything works.
+ */
+ regmap_read(s->regmap, MAX310X_CLKSRC_REG, &val);
+ if (val != (MAX310X_CLKSRC_EXTCLK_BIT |
+ MAX310X_CLKSRC_PLLBYP_BIT)) {
+ dev_err(dev, "%s not present\n", s->name);
+ ret = -ENODEV;
+ goto err_out;
+ }
+ break;
+ }
+
+ /* Board specific configure */
+ if (pdata->init)
+ pdata->init();
+ if (pdata->suspend)
+ pdata->suspend(0);
+
+ /* Calculate referecne clock */
+ s->uartclk = max310x_set_ref_clk(s);
+
+ /* Disable all interrupts */
+ regmap_write(s->regmap, MAX310X_IRQEN_REG, 0);
+
+ /* Setup MODE1 register */
+ val = MAX310X_MODE1_IRQSEL_BIT; /* Enable IRQ pin */
+ if (pdata->driver_flags & MAX310X_AUTOSLEEP)
+ val = MAX310X_MODE1_AUTOSLEEP_BIT;
+ regmap_write(s->regmap, MAX310X_MODE1_REG, val);
+
+ /* Setup interrupt */
+ ret = devm_request_threaded_irq(dev, spi->irq, NULL, max310x_ist,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ dev_name(dev), s);
+ if (ret) {
+ dev_err(dev, "Unable to reguest IRQ %i\n", spi->irq);
+ goto err_out;
+ }
+
+ /* Register UART driver */
+ s->uart.owner = THIS_MODULE;
+ s->uart.driver_name = dev_name(dev);
+ s->uart.dev_name = "ttyMAX";
+ s->uart.major = MAX310X_MAJOR;
+ s->uart.minor = MAX310X_MINOR;
+ ret = uart_register_driver(&s->uart);
+ if (ret) {
+ dev_err(dev, "Registering UART driver failed\n");
+ goto err_out;
+ }
+
+ /* Initialize workqueue for start TX */
+ s->wq = create_freezable_workqueue(dev_name(dev));
+ INIT_WORK(&s->tx_work, max310x_wq_proc);
+
+ /* Initialize UART port data */
+ s->port.line = 0;
+ s->port.dev = dev;
+ s->port.irq = spi->irq;
+ s->port.type = PORT_MAX310X;
+ s->port.fifosize = MAX310X_FIFO_SIZE;
+ s->port.flags = UPF_SKIP_TEST | UPF_FIXED_TYPE;
+ s->port.iotype = UPIO_PORT;
+ s->port.membase = (void __iomem *)0xffffffff; /* Bogus value */
+ s->port.uartclk = s->uartclk;
+ s->port.ops = &max310x_ops;
+ uart_add_one_port(&s->uart, &s->port);
+
+#ifdef CONFIG_GPIOLIB
+ /* Setup GPIO cotroller */
+ if (pdata->gpio_base) {
+ s->gpio.owner = THIS_MODULE;
+ s->gpio.dev = dev;
+ s->gpio.label = dev_name(dev);
+ s->gpio.direction_input = max310x_gpio_direction_input;
+ s->gpio.get = max310x_gpio_get;
+ s->gpio.direction_output= max310x_gpio_direction_output;
+ s->gpio.set = max310x_gpio_set;
+ s->gpio.base = pdata->gpio_base;
+ s->gpio.ngpio = s->nr_gpio;
+ if (gpiochip_add(&s->gpio)) {
+ /* Indicate that we should not call gpiochip_remove */
+ s->gpio.base = 0;
+ }
+ } else
+ dev_info(dev, "GPIO support not enabled\n");
+#endif
+
+ /* Go to suspend mode */
+ if (pdata->suspend)
+ pdata->suspend(1);
+
+ return 0;
+
+err_freq:
+ dev_err(dev, "Frequency parameter incorrect\n");
+ ret = -EINVAL;
+
+err_out:
+ dev_set_drvdata(dev, NULL);
+
+ return ret;
+}
+
+static int __devexit max310x_remove(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
+ struct max310x_port *s = dev_get_drvdata(dev);
+ int ret = 0;
+
+ dev_dbg(dev, "Removing port\n");
+
+ devm_free_irq(dev, s->port.irq, s);
+
+ destroy_workqueue(s->wq);
+
+ uart_remove_one_port(&s->uart, &s->port);
+
+ uart_unregister_driver(&s->uart);
+
+#ifdef CONFIG_GPIOLIB
+ if (s->pdata->gpio_base) {
+ ret = gpiochip_remove(&s->gpio);
+ if (ret)
+ dev_err(dev, "Failed to remove gpio chip: %d\n", ret);
+ }
+#endif
+
+ dev_set_drvdata(dev, NULL);
+
+ if (s->pdata->suspend)
+ s->pdata->suspend(1);
+ if (s->pdata->exit)
+ s->pdata->exit();
+
+ return ret;
+}
+
+static const struct spi_device_id max310x_id_table[] = {
+ { "max3107", MAX310X_TYPE_MAX3107 },
+ { "max3108", MAX310X_TYPE_MAX3108 },
+};
+MODULE_DEVICE_TABLE(spi, max310x_id_table);
+
+static struct spi_driver max310x_driver = {
+ .driver = {
+ .name = "max310x",
+ .owner = THIS_MODULE,
+ },
+ .probe = max310x_probe,
+ .remove = __devexit_p(max310x_remove),
+ .suspend = max310x_suspend,
+ .resume = max310x_resume,
+ .id_table = max310x_id_table,
+};
+module_spi_driver(max310x_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
+MODULE_DESCRIPTION("MAX310X serial driver");
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index bedac0d..f19d04e 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -775,11 +775,15 @@
}
if (new->c_cflag & PARENB) {
+ if (new->c_cflag & CMSPAR)
+ mr1 |= MPC52xx_PSC_MODE_PARFORCE;
+
+ /* With CMSPAR, PARODD also means high parity (same as termios) */
mr1 |= (new->c_cflag & PARODD) ?
MPC52xx_PSC_MODE_PARODD : MPC52xx_PSC_MODE_PAREVEN;
- } else
+ } else {
mr1 |= MPC52xx_PSC_MODE_PARNONE;
-
+ }
mr2 = 0;
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index 8131e2c..033e0bc 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -896,7 +896,7 @@
return PTR_ERR(msm_port->clk);
if (msm_port->is_uartdm)
- clk_set_rate(msm_port->clk, 7372800);
+ clk_set_rate(msm_port->clk, 1843200);
port->uartclk = clk_get_rate(msm_port->clk);
printk(KERN_INFO "uartclk = %d\n", port->uartclk);
diff --git a/drivers/tty/serial/msm_smd_tty.c b/drivers/tty/serial/msm_smd_tty.c
index b25e6ee..925d1fa 100644
--- a/drivers/tty/serial/msm_smd_tty.c
+++ b/drivers/tty/serial/msm_smd_tty.c
@@ -223,9 +223,11 @@
return ret;
for (i = 0; i < smd_tty_channels_len; i++) {
- tty_port_init(&smd_tty[smd_tty_channels[i].id].port);
- smd_tty[smd_tty_channels[i].id].port.ops = &smd_tty_port_ops;
- tty_register_device(smd_tty_driver, smd_tty_channels[i].id, 0);
+ struct tty_port *port = &smd_tty[smd_tty_channels[i].id].port;
+ tty_port_init(port);
+ port->ops = &smd_tty_port_ops;
+ tty_port_register_device(port, smd_tty_driver,
+ smd_tty_channels[i].id, NULL);
}
return 0;
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index 3a667ee..6898413 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -262,7 +262,7 @@
ctrl &= ~AUART_CTRL2_RTSEN;
if (mctrl & TIOCM_RTS) {
- if (u->state->port.flags & ASYNC_CTS_FLOW)
+ if (tty_port_cts_enabled(&u->state->port))
ctrl |= AUART_CTRL2_RTSEN;
}
@@ -457,11 +457,11 @@
writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR);
- writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET);
-
writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN,
u->membase + AUART_INTR_CLR);
+ writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET);
+
clk_disable_unprepare(s->clk);
}
@@ -796,6 +796,7 @@
auart_port[pdev->id] = NULL;
+ put_device(s->dev);
clk_put(s->clk);
free_irq(s->irq, s);
kfree(s);
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
index 34e7187..df443b9 100644
--- a/drivers/tty/serial/of_serial.c
+++ b/drivers/tty/serial/of_serial.c
@@ -105,6 +105,10 @@
port->uartclk = clk;
port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
| UPF_FIXED_PORT | UPF_FIXED_TYPE;
+
+ if (of_find_property(np, "no-loopback-test", NULL))
+ port->flags |= UPF_SKIP_TEST;
+
port->dev = &ofdev->dev;
if (type == PORT_TEGRA)
@@ -144,8 +148,15 @@
switch (port_type) {
#ifdef CONFIG_SERIAL_8250
case PORT_8250 ... PORT_MAX_8250:
- ret = serial8250_register_port(&port);
+ {
+ /* For now the of bindings don't support the extra
+ 8250 specific bits */
+ struct uart_8250_port port8250;
+ memset(&port8250, 0, sizeof(port8250));
+ port8250.port = port;
+ ret = serial8250_register_8250_port(&port8250);
break;
+ }
#endif
#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL
case PORT_NWPSERIAL:
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index d3cda0c..f175385 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -32,16 +32,16 @@
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
+#include <linux/platform_device.h>
#include <linux/io.h>
-#include <linux/dma-mapping.h>
#include <linux/clk.h>
#include <linux/serial_core.h>
#include <linux/irq.h>
#include <linux/pm_runtime.h>
#include <linux/of.h>
+#include <linux/gpio.h>
+#include <linux/pinctrl/consumer.h>
-#include <plat/dma.h>
-#include <plat/dmtimer.h>
#include <plat/omap-serial.h>
#define UART_BUILD_REVISION(x, y) (((x) << 8) | (y))
@@ -57,8 +57,8 @@
#define OMAP_UART_SCR_RX_TRIG_GRANU1_MASK (1 << 7)
/* FCR register bitmasks */
-#define OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT 6
#define OMAP_UART_FCR_RX_FIFO_TRIG_MASK (0x3 << 6)
+#define OMAP_UART_FCR_TX_FIFO_TRIG_MASK (0x3 << 4)
/* MVR register bitmasks */
#define OMAP_UART_MVR_SCHEME_SHIFT 30
@@ -71,12 +71,52 @@
#define OMAP_UART_MVR_MAJ_SHIFT 8
#define OMAP_UART_MVR_MIN_MASK 0x3f
+struct uart_omap_port {
+ struct uart_port port;
+ struct uart_omap_dma uart_dma;
+ struct device *dev;
+
+ unsigned char ier;
+ unsigned char lcr;
+ unsigned char mcr;
+ unsigned char fcr;
+ unsigned char efr;
+ unsigned char dll;
+ unsigned char dlh;
+ unsigned char mdr1;
+ unsigned char scr;
+
+ int use_dma;
+ /*
+ * Some bits in registers are cleared on a read, so they must
+ * be saved whenever the register is read but the bits will not
+ * be immediately processed.
+ */
+ unsigned int lsr_break_flag;
+ unsigned char msr_saved_flags;
+ char name[20];
+ unsigned long port_activity;
+ u32 context_loss_cnt;
+ u32 errata;
+ u8 wakeups_enabled;
+ unsigned int irq_pending:1;
+
+ int DTR_gpio;
+ int DTR_inverted;
+ int DTR_active;
+
+ struct pm_qos_request pm_qos_request;
+ u32 latency;
+ u32 calc_latency;
+ struct work_struct qos_work;
+ struct pinctrl *pins;
+};
+
+#define to_uart_omap_port(p) ((container_of((p), struct uart_omap_port, port)))
+
static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
/* Forward declaration of functions */
-static void uart_tx_dma_callback(int lch, u16 ch_status, void *data);
-static void serial_omap_rxdma_poll(unsigned long uart_no);
-static int serial_omap_start_rxdma(struct uart_omap_port *up);
static void serial_omap_mdr1_errataset(struct uart_omap_port *up, u8 mdr1);
static struct workqueue_struct *serial_omap_uart_wq;
@@ -101,6 +141,46 @@
serial_out(up, UART_FCR, 0);
}
+static int serial_omap_get_context_loss_count(struct uart_omap_port *up)
+{
+ struct omap_uart_port_info *pdata = up->dev->platform_data;
+
+ if (!pdata || !pdata->get_context_loss_count)
+ return 0;
+
+ return pdata->get_context_loss_count(up->dev);
+}
+
+static void serial_omap_set_forceidle(struct uart_omap_port *up)
+{
+ struct omap_uart_port_info *pdata = up->dev->platform_data;
+
+ if (!pdata || !pdata->set_forceidle)
+ return;
+
+ pdata->set_forceidle(up->dev);
+}
+
+static void serial_omap_set_noidle(struct uart_omap_port *up)
+{
+ struct omap_uart_port_info *pdata = up->dev->platform_data;
+
+ if (!pdata || !pdata->set_noidle)
+ return;
+
+ pdata->set_noidle(up->dev);
+}
+
+static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable)
+{
+ struct omap_uart_port_info *pdata = up->dev->platform_data;
+
+ if (!pdata || !pdata->enable_wakeup)
+ return;
+
+ pdata->enable_wakeup(up->dev, enable);
+}
+
/*
* serial_omap_get_divisor - calculate divisor value
* @port: uart port info
@@ -126,151 +206,55 @@
return port->uartclk/(baud * divisor);
}
-static void serial_omap_stop_rxdma(struct uart_omap_port *up)
-{
- if (up->uart_dma.rx_dma_used) {
- del_timer(&up->uart_dma.rx_timer);
- omap_stop_dma(up->uart_dma.rx_dma_channel);
- omap_free_dma(up->uart_dma.rx_dma_channel);
- up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
- up->uart_dma.rx_dma_used = false;
- pm_runtime_mark_last_busy(&up->pdev->dev);
- pm_runtime_put_autosuspend(&up->pdev->dev);
- }
-}
-
static void serial_omap_enable_ms(struct uart_port *port)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
dev_dbg(up->port.dev, "serial_omap_enable_ms+%d\n", up->port.line);
- pm_runtime_get_sync(&up->pdev->dev);
+ pm_runtime_get_sync(up->dev);
up->ier |= UART_IER_MSI;
serial_out(up, UART_IER, up->ier);
- pm_runtime_put(&up->pdev->dev);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
}
static void serial_omap_stop_tx(struct uart_port *port)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
- struct omap_uart_port_info *pdata = up->pdev->dev.platform_data;
+ struct uart_omap_port *up = to_uart_omap_port(port);
- if (up->use_dma &&
- up->uart_dma.tx_dma_channel != OMAP_UART_DMA_CH_FREE) {
- /*
- * Check if dma is still active. If yes do nothing,
- * return. Else stop dma
- */
- if (omap_get_dma_active_status(up->uart_dma.tx_dma_channel))
- return;
- omap_stop_dma(up->uart_dma.tx_dma_channel);
- omap_free_dma(up->uart_dma.tx_dma_channel);
- up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
- pm_runtime_mark_last_busy(&up->pdev->dev);
- pm_runtime_put_autosuspend(&up->pdev->dev);
- }
-
- pm_runtime_get_sync(&up->pdev->dev);
+ pm_runtime_get_sync(up->dev);
if (up->ier & UART_IER_THRI) {
up->ier &= ~UART_IER_THRI;
serial_out(up, UART_IER, up->ier);
}
- if (!up->use_dma && pdata && pdata->set_forceidle)
- pdata->set_forceidle(up->pdev);
+ serial_omap_set_forceidle(up);
- pm_runtime_mark_last_busy(&up->pdev->dev);
- pm_runtime_put_autosuspend(&up->pdev->dev);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
}
static void serial_omap_stop_rx(struct uart_port *port)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
- pm_runtime_get_sync(&up->pdev->dev);
- if (up->use_dma)
- serial_omap_stop_rxdma(up);
+ pm_runtime_get_sync(up->dev);
up->ier &= ~UART_IER_RLSI;
up->port.read_status_mask &= ~UART_LSR_DR;
serial_out(up, UART_IER, up->ier);
- pm_runtime_mark_last_busy(&up->pdev->dev);
- pm_runtime_put_autosuspend(&up->pdev->dev);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
}
-static inline void receive_chars(struct uart_omap_port *up,
- unsigned int *status)
-{
- struct tty_struct *tty = up->port.state->port.tty;
- unsigned int flag, lsr = *status;
- unsigned char ch = 0;
- int max_count = 256;
-
- do {
- if (likely(lsr & UART_LSR_DR))
- ch = serial_in(up, UART_RX);
- flag = TTY_NORMAL;
- up->port.icount.rx++;
-
- if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
- /*
- * For statistics only
- */
- if (lsr & UART_LSR_BI) {
- lsr &= ~(UART_LSR_FE | UART_LSR_PE);
- up->port.icount.brk++;
- /*
- * We do the SysRQ and SAK checking
- * here because otherwise the break
- * may get masked by ignore_status_mask
- * or read_status_mask.
- */
- if (uart_handle_break(&up->port))
- goto ignore_char;
- } else if (lsr & UART_LSR_PE) {
- up->port.icount.parity++;
- } else if (lsr & UART_LSR_FE) {
- up->port.icount.frame++;
- }
-
- if (lsr & UART_LSR_OE)
- up->port.icount.overrun++;
-
- /*
- * Mask off conditions which should be ignored.
- */
- lsr &= up->port.read_status_mask;
-
-#ifdef CONFIG_SERIAL_OMAP_CONSOLE
- if (up->port.line == up->port.cons->index) {
- /* Recover the break flag from console xmit */
- lsr |= up->lsr_break_flag;
- }
-#endif
- if (lsr & UART_LSR_BI)
- flag = TTY_BREAK;
- else if (lsr & UART_LSR_PE)
- flag = TTY_PARITY;
- else if (lsr & UART_LSR_FE)
- flag = TTY_FRAME;
- }
-
- if (uart_handle_sysrq_char(&up->port, ch))
- goto ignore_char;
- uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag);
-ignore_char:
- lsr = serial_in(up, UART_LSR);
- } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));
- spin_unlock(&up->port.lock);
- tty_flip_buffer_push(tty);
- spin_lock(&up->port.lock);
-}
-
-static void transmit_chars(struct uart_omap_port *up)
+static void transmit_chars(struct uart_omap_port *up, unsigned int lsr)
{
struct circ_buf *xmit = &up->port.state->xmit;
int count;
+ if (!(lsr & UART_LSR_THRE))
+ return;
+
if (up->port.x_char) {
serial_out(up, UART_TX, up->port.x_char);
up->port.icount.tx++;
@@ -290,8 +274,11 @@
break;
} while (--count > 0);
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
+ spin_unlock(&up->port.lock);
uart_write_wakeup(&up->port);
+ spin_lock(&up->port.lock);
+ }
if (uart_circ_empty(xmit))
serial_omap_stop_tx(&up->port);
@@ -307,70 +294,13 @@
static void serial_omap_start_tx(struct uart_port *port)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
- struct omap_uart_port_info *pdata = up->pdev->dev.platform_data;
- struct circ_buf *xmit;
- unsigned int start;
- int ret = 0;
+ struct uart_omap_port *up = to_uart_omap_port(port);
- if (!up->use_dma) {
- pm_runtime_get_sync(&up->pdev->dev);
- serial_omap_enable_ier_thri(up);
- if (pdata && pdata->set_noidle)
- pdata->set_noidle(up->pdev);
- pm_runtime_mark_last_busy(&up->pdev->dev);
- pm_runtime_put_autosuspend(&up->pdev->dev);
- return;
- }
-
- if (up->uart_dma.tx_dma_used)
- return;
-
- xmit = &up->port.state->xmit;
-
- if (up->uart_dma.tx_dma_channel == OMAP_UART_DMA_CH_FREE) {
- pm_runtime_get_sync(&up->pdev->dev);
- ret = omap_request_dma(up->uart_dma.uart_dma_tx,
- "UART Tx DMA",
- (void *)uart_tx_dma_callback, up,
- &(up->uart_dma.tx_dma_channel));
-
- if (ret < 0) {
- serial_omap_enable_ier_thri(up);
- return;
- }
- }
- spin_lock(&(up->uart_dma.tx_lock));
- up->uart_dma.tx_dma_used = true;
- spin_unlock(&(up->uart_dma.tx_lock));
-
- start = up->uart_dma.tx_buf_dma_phys +
- (xmit->tail & (UART_XMIT_SIZE - 1));
-
- up->uart_dma.tx_buf_size = uart_circ_chars_pending(xmit);
- /*
- * It is a circular buffer. See if the buffer has wounded back.
- * If yes it will have to be transferred in two separate dma
- * transfers
- */
- if (start + up->uart_dma.tx_buf_size >=
- up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE)
- up->uart_dma.tx_buf_size =
- (up->uart_dma.tx_buf_dma_phys +
- UART_XMIT_SIZE) - start;
-
- omap_set_dma_dest_params(up->uart_dma.tx_dma_channel, 0,
- OMAP_DMA_AMODE_CONSTANT,
- up->uart_dma.uart_base, 0, 0);
- omap_set_dma_src_params(up->uart_dma.tx_dma_channel, 0,
- OMAP_DMA_AMODE_POST_INC, start, 0, 0);
- omap_set_dma_transfer_params(up->uart_dma.tx_dma_channel,
- OMAP_DMA_DATA_TYPE_S8,
- up->uart_dma.tx_buf_size, 1,
- OMAP_DMA_SYNC_ELEMENT,
- up->uart_dma.uart_dma_tx, 0);
- /* FIXME: Cache maintenance needed here? */
- omap_start_dma(up->uart_dma.tx_dma_channel);
+ pm_runtime_get_sync(up->dev);
+ serial_omap_enable_ier_thri(up);
+ serial_omap_set_noidle(up);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
}
static unsigned int check_modem_status(struct uart_omap_port *up)
@@ -401,76 +331,158 @@
return status;
}
+static void serial_omap_rlsi(struct uart_omap_port *up, unsigned int lsr)
+{
+ unsigned int flag;
+
+ up->port.icount.rx++;
+ flag = TTY_NORMAL;
+
+ if (lsr & UART_LSR_BI) {
+ flag = TTY_BREAK;
+ lsr &= ~(UART_LSR_FE | UART_LSR_PE);
+ up->port.icount.brk++;
+ /*
+ * We do the SysRQ and SAK checking
+ * here because otherwise the break
+ * may get masked by ignore_status_mask
+ * or read_status_mask.
+ */
+ if (uart_handle_break(&up->port))
+ return;
+
+ }
+
+ if (lsr & UART_LSR_PE) {
+ flag = TTY_PARITY;
+ up->port.icount.parity++;
+ }
+
+ if (lsr & UART_LSR_FE) {
+ flag = TTY_FRAME;
+ up->port.icount.frame++;
+ }
+
+ if (lsr & UART_LSR_OE)
+ up->port.icount.overrun++;
+
+#ifdef CONFIG_SERIAL_OMAP_CONSOLE
+ if (up->port.line == up->port.cons->index) {
+ /* Recover the break flag from console xmit */
+ lsr |= up->lsr_break_flag;
+ }
+#endif
+ uart_insert_char(&up->port, lsr, UART_LSR_OE, 0, flag);
+}
+
+static void serial_omap_rdi(struct uart_omap_port *up, unsigned int lsr)
+{
+ unsigned char ch = 0;
+ unsigned int flag;
+
+ if (!(lsr & UART_LSR_DR))
+ return;
+
+ ch = serial_in(up, UART_RX);
+ flag = TTY_NORMAL;
+ up->port.icount.rx++;
+
+ if (uart_handle_sysrq_char(&up->port, ch))
+ return;
+
+ uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag);
+}
+
/**
* serial_omap_irq() - This handles the interrupt from one port
* @irq: uart port irq number
* @dev_id: uart port info
*/
-static inline irqreturn_t serial_omap_irq(int irq, void *dev_id)
+static irqreturn_t serial_omap_irq(int irq, void *dev_id)
{
struct uart_omap_port *up = dev_id;
+ struct tty_struct *tty = up->port.state->port.tty;
unsigned int iir, lsr;
- unsigned long flags;
+ unsigned int type;
+ irqreturn_t ret = IRQ_NONE;
+ int max_count = 256;
- pm_runtime_get_sync(&up->pdev->dev);
- iir = serial_in(up, UART_IIR);
- if (iir & UART_IIR_NO_INT) {
- pm_runtime_mark_last_busy(&up->pdev->dev);
- pm_runtime_put_autosuspend(&up->pdev->dev);
- return IRQ_NONE;
- }
+ spin_lock(&up->port.lock);
+ pm_runtime_get_sync(up->dev);
- spin_lock_irqsave(&up->port.lock, flags);
- lsr = serial_in(up, UART_LSR);
- if (iir & UART_IIR_RLSI) {
- if (!up->use_dma) {
- if (lsr & UART_LSR_DR)
- receive_chars(up, &lsr);
- } else {
- up->ier &= ~(UART_IER_RDI | UART_IER_RLSI);
- serial_out(up, UART_IER, up->ier);
- if ((serial_omap_start_rxdma(up) != 0) &&
- (lsr & UART_LSR_DR))
- receive_chars(up, &lsr);
+ do {
+ iir = serial_in(up, UART_IIR);
+ if (iir & UART_IIR_NO_INT)
+ break;
+
+ ret = IRQ_HANDLED;
+ lsr = serial_in(up, UART_LSR);
+
+ /* extract IRQ type from IIR register */
+ type = iir & 0x3e;
+
+ switch (type) {
+ case UART_IIR_MSI:
+ check_modem_status(up);
+ break;
+ case UART_IIR_THRI:
+ transmit_chars(up, lsr);
+ break;
+ case UART_IIR_RX_TIMEOUT:
+ /* FALLTHROUGH */
+ case UART_IIR_RDI:
+ serial_omap_rdi(up, lsr);
+ break;
+ case UART_IIR_RLSI:
+ serial_omap_rlsi(up, lsr);
+ break;
+ case UART_IIR_CTS_RTS_DSR:
+ /* simply try again */
+ break;
+ case UART_IIR_XOFF:
+ /* FALLTHROUGH */
+ default:
+ break;
}
- }
+ } while (!(iir & UART_IIR_NO_INT) && max_count--);
- check_modem_status(up);
- if ((lsr & UART_LSR_THRE) && (iir & UART_IIR_THRI))
- transmit_chars(up);
+ spin_unlock(&up->port.lock);
- spin_unlock_irqrestore(&up->port.lock, flags);
- pm_runtime_mark_last_busy(&up->pdev->dev);
- pm_runtime_put_autosuspend(&up->pdev->dev);
+ tty_flip_buffer_push(tty);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
up->port_activity = jiffies;
- return IRQ_HANDLED;
+
+ return ret;
}
static unsigned int serial_omap_tx_empty(struct uart_port *port)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
unsigned long flags = 0;
unsigned int ret = 0;
- pm_runtime_get_sync(&up->pdev->dev);
+ pm_runtime_get_sync(up->dev);
dev_dbg(up->port.dev, "serial_omap_tx_empty+%d\n", up->port.line);
spin_lock_irqsave(&up->port.lock, flags);
ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
spin_unlock_irqrestore(&up->port.lock, flags);
- pm_runtime_put(&up->pdev->dev);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
return ret;
}
static unsigned int serial_omap_get_mctrl(struct uart_port *port)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
unsigned int status;
unsigned int ret = 0;
- pm_runtime_get_sync(&up->pdev->dev);
+ pm_runtime_get_sync(up->dev);
status = check_modem_status(up);
- pm_runtime_put(&up->pdev->dev);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
dev_dbg(up->port.dev, "serial_omap_get_mctrl+%d\n", up->port.line);
@@ -487,7 +499,7 @@
static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
unsigned char mcr = 0;
dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->port.line);
@@ -502,20 +514,31 @@
if (mctrl & TIOCM_LOOP)
mcr |= UART_MCR_LOOP;
- pm_runtime_get_sync(&up->pdev->dev);
+ pm_runtime_get_sync(up->dev);
up->mcr = serial_in(up, UART_MCR);
up->mcr |= mcr;
serial_out(up, UART_MCR, up->mcr);
- pm_runtime_put(&up->pdev->dev);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
+
+ if (gpio_is_valid(up->DTR_gpio) &&
+ !!(mctrl & TIOCM_DTR) != up->DTR_active) {
+ up->DTR_active = !up->DTR_active;
+ if (gpio_cansleep(up->DTR_gpio))
+ schedule_work(&up->qos_work);
+ else
+ gpio_set_value(up->DTR_gpio,
+ up->DTR_active != up->DTR_inverted);
+ }
}
static void serial_omap_break_ctl(struct uart_port *port, int break_state)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
unsigned long flags = 0;
dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->port.line);
- pm_runtime_get_sync(&up->pdev->dev);
+ pm_runtime_get_sync(up->dev);
spin_lock_irqsave(&up->port.lock, flags);
if (break_state == -1)
up->lcr |= UART_LCR_SBC;
@@ -523,12 +546,13 @@
up->lcr &= ~UART_LCR_SBC;
serial_out(up, UART_LCR, up->lcr);
spin_unlock_irqrestore(&up->port.lock, flags);
- pm_runtime_put(&up->pdev->dev);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
}
static int serial_omap_startup(struct uart_port *port)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
unsigned long flags = 0;
int retval;
@@ -542,7 +566,7 @@
dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->port.line);
- pm_runtime_get_sync(&up->pdev->dev);
+ pm_runtime_get_sync(up->dev);
/*
* Clear the FIFO buffers and disable them.
* (they will be reenabled in set_termios())
@@ -573,20 +597,6 @@
spin_unlock_irqrestore(&up->port.lock, flags);
up->msr_saved_flags = 0;
- if (up->use_dma) {
- free_page((unsigned long)up->port.state->xmit.buf);
- up->port.state->xmit.buf = dma_alloc_coherent(NULL,
- UART_XMIT_SIZE,
- (dma_addr_t *)&(up->uart_dma.tx_buf_dma_phys),
- 0);
- init_timer(&(up->uart_dma.rx_timer));
- up->uart_dma.rx_timer.function = serial_omap_rxdma_poll;
- up->uart_dma.rx_timer.data = up->port.line;
- /* Currently the buffer size is 4KB. Can increase it */
- up->uart_dma.rx_buf = dma_alloc_coherent(NULL,
- up->uart_dma.rx_buf_size,
- (dma_addr_t *)&(up->uart_dma.rx_buf_dma_phys), 0);
- }
/*
* Finally, enable interrupts. Note: Modem status interrupts
* are set via set_termios(), which will be occurring imminently
@@ -598,20 +608,20 @@
/* Enable module level wake up */
serial_out(up, UART_OMAP_WER, OMAP_UART_WER_MOD_WKUP);
- pm_runtime_mark_last_busy(&up->pdev->dev);
- pm_runtime_put_autosuspend(&up->pdev->dev);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
up->port_activity = jiffies;
return 0;
}
static void serial_omap_shutdown(struct uart_port *port)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
unsigned long flags = 0;
dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->port.line);
- pm_runtime_get_sync(&up->pdev->dev);
+ pm_runtime_get_sync(up->dev);
/*
* Disable interrupts from this port
*/
@@ -634,19 +644,9 @@
*/
if (serial_in(up, UART_LSR) & UART_LSR_DR)
(void) serial_in(up, UART_RX);
- if (up->use_dma) {
- dma_free_coherent(up->port.dev,
- UART_XMIT_SIZE, up->port.state->xmit.buf,
- up->uart_dma.tx_buf_dma_phys);
- up->port.state->xmit.buf = NULL;
- serial_omap_stop_rx(port);
- dma_free_coherent(up->port.dev,
- up->uart_dma.rx_buf_size, up->uart_dma.rx_buf,
- up->uart_dma.rx_buf_dma_phys);
- up->uart_dma.rx_buf = NULL;
- }
- pm_runtime_put(&up->pdev->dev);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
free_irq(up->port.irq, up);
}
@@ -667,19 +667,19 @@
/*
* IXON Flag:
- * Enable XON/XOFF flow control on output.
- * Transmit XON1, XOFF1
+ * Flow control for OMAP.TX
+ * OMAP.RX should listen for XON/XOFF
*/
if (termios->c_iflag & IXON)
- up->efr |= OMAP_UART_SW_TX;
+ up->efr |= OMAP_UART_SW_RX;
/*
* IXOFF Flag:
- * Enable XON/XOFF flow control on input.
- * Receiver compares XON1, XOFF1.
+ * Flow control for OMAP.RX
+ * OMAP.TX should send XON/XOFF
*/
if (termios->c_iflag & IXOFF)
- up->efr |= OMAP_UART_SW_RX;
+ up->efr |= OMAP_UART_SW_TX;
serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
@@ -715,13 +715,16 @@
qos_work);
pm_qos_update_request(&up->pm_qos_request, up->latency);
+ if (gpio_is_valid(up->DTR_gpio))
+ gpio_set_value_cansleep(up->DTR_gpio,
+ up->DTR_active != up->DTR_inverted);
}
static void
serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
unsigned char cval = 0;
unsigned char efr = 0;
unsigned long flags = 0;
@@ -768,14 +771,12 @@
up->fcr = UART_FCR_R_TRIG_01 | UART_FCR_T_TRIG_01 |
UART_FCR_ENABLE_FIFO;
- if (up->use_dma)
- up->fcr |= UART_FCR_DMA_SELECT;
/*
* Ok, we're now changing the port state. Do it with
* interrupts disabled.
*/
- pm_runtime_get_sync(&up->pdev->dev);
+ pm_runtime_get_sync(up->dev);
spin_lock_irqsave(&up->port.lock, flags);
/*
@@ -845,14 +846,13 @@
up->scr |= OMAP_UART_SCR_RX_TRIG_GRANU1_MASK;
- if (up->use_dma) {
- serial_out(up, UART_TI752_TLR, 0);
- up->scr |= UART_FCR_TRIGGER_4;
- } else {
- /* Set receive FIFO threshold to 1 byte */
- up->fcr &= ~OMAP_UART_FCR_RX_FIFO_TRIG_MASK;
- up->fcr |= (0x1 << OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT);
- }
+ /* Set receive FIFO threshold to 16 characters and
+ * transmit FIFO threshold to 16 spaces
+ */
+ up->fcr &= ~OMAP_UART_FCR_RX_FIFO_TRIG_MASK;
+ up->fcr &= ~OMAP_UART_FCR_TX_FIFO_TRIG_MASK;
+ up->fcr |= UART_FCR6_R_TRIGGER_16 | UART_FCR6_T_TRIGGER_24 |
+ UART_FCR_ENABLE_FIFO;
serial_out(up, UART_FCR, up->fcr);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
@@ -924,20 +924,30 @@
serial_omap_configure_xonxoff(up, termios);
spin_unlock_irqrestore(&up->port.lock, flags);
- pm_runtime_put(&up->pdev->dev);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->port.line);
}
+static int serial_omap_set_wake(struct uart_port *port, unsigned int state)
+{
+ struct uart_omap_port *up = to_uart_omap_port(port);
+
+ serial_omap_enable_wakeup(up, state);
+
+ return 0;
+}
+
static void
serial_omap_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
unsigned char efr;
dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->port.line);
- pm_runtime_get_sync(&up->pdev->dev);
+ pm_runtime_get_sync(up->dev);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
efr = serial_in(up, UART_EFR);
serial_out(up, UART_EFR, efr | UART_EFR_ECB);
@@ -948,14 +958,15 @@
serial_out(up, UART_EFR, efr);
serial_out(up, UART_LCR, 0);
- if (!device_may_wakeup(&up->pdev->dev)) {
+ if (!device_may_wakeup(up->dev)) {
if (!state)
- pm_runtime_forbid(&up->pdev->dev);
+ pm_runtime_forbid(up->dev);
else
- pm_runtime_allow(&up->pdev->dev);
+ pm_runtime_allow(up->dev);
}
- pm_runtime_put(&up->pdev->dev);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
}
static void serial_omap_release_port(struct uart_port *port)
@@ -971,7 +982,7 @@
static void serial_omap_config_port(struct uart_port *port, int flags)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
dev_dbg(up->port.dev, "serial_omap_config_port+%d\n",
up->port.line);
@@ -989,7 +1000,7 @@
static const char *
serial_omap_type(struct uart_port *port)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
dev_dbg(up->port.dev, "serial_omap_type+%d\n", up->port.line);
return up->name;
@@ -1032,26 +1043,33 @@
static void serial_omap_poll_put_char(struct uart_port *port, unsigned char ch)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
- pm_runtime_get_sync(&up->pdev->dev);
+ pm_runtime_get_sync(up->dev);
wait_for_xmitr(up);
serial_out(up, UART_TX, ch);
- pm_runtime_put(&up->pdev->dev);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
}
static int serial_omap_poll_get_char(struct uart_port *port)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
unsigned int status;
- pm_runtime_get_sync(&up->pdev->dev);
+ pm_runtime_get_sync(up->dev);
status = serial_in(up, UART_LSR);
- if (!(status & UART_LSR_DR))
- return NO_POLL_CHAR;
+ if (!(status & UART_LSR_DR)) {
+ status = NO_POLL_CHAR;
+ goto out;
+ }
status = serial_in(up, UART_RX);
- pm_runtime_put(&up->pdev->dev);
+
+out:
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
+
return status;
}
@@ -1065,7 +1083,7 @@
static void serial_omap_console_putchar(struct uart_port *port, int ch)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
wait_for_xmitr(up);
serial_out(up, UART_TX, ch);
@@ -1080,7 +1098,7 @@
unsigned int ier;
int locked = 1;
- pm_runtime_get_sync(&up->pdev->dev);
+ pm_runtime_get_sync(up->dev);
local_irq_save(flags);
if (up->port.sysrq)
@@ -1114,8 +1132,8 @@
if (up->msr_saved_flags)
check_modem_status(up);
- pm_runtime_mark_last_busy(&up->pdev->dev);
- pm_runtime_put_autosuspend(&up->pdev->dev);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
if (locked)
spin_unlock(&up->port.lock);
local_irq_restore(flags);
@@ -1179,6 +1197,7 @@
.shutdown = serial_omap_shutdown,
.set_termios = serial_omap_set_termios,
.pm = serial_omap_pm,
+ .set_wake = serial_omap_set_wake,
.type = serial_omap_type,
.release_port = serial_omap_release_port,
.request_port = serial_omap_request_port,
@@ -1221,150 +1240,7 @@
}
#endif
-static void serial_omap_rxdma_poll(unsigned long uart_no)
-{
- struct uart_omap_port *up = ui[uart_no];
- unsigned int curr_dma_pos, curr_transmitted_size;
- int ret = 0;
-
- curr_dma_pos = omap_get_dma_dst_pos(up->uart_dma.rx_dma_channel);
- if ((curr_dma_pos == up->uart_dma.prev_rx_dma_pos) ||
- (curr_dma_pos == 0)) {
- if (jiffies_to_msecs(jiffies - up->port_activity) <
- up->uart_dma.rx_timeout) {
- mod_timer(&up->uart_dma.rx_timer, jiffies +
- usecs_to_jiffies(up->uart_dma.rx_poll_rate));
- } else {
- serial_omap_stop_rxdma(up);
- up->ier |= (UART_IER_RDI | UART_IER_RLSI);
- serial_out(up, UART_IER, up->ier);
- }
- return;
- }
-
- curr_transmitted_size = curr_dma_pos -
- up->uart_dma.prev_rx_dma_pos;
- up->port.icount.rx += curr_transmitted_size;
- tty_insert_flip_string(up->port.state->port.tty,
- up->uart_dma.rx_buf +
- (up->uart_dma.prev_rx_dma_pos -
- up->uart_dma.rx_buf_dma_phys),
- curr_transmitted_size);
- tty_flip_buffer_push(up->port.state->port.tty);
- up->uart_dma.prev_rx_dma_pos = curr_dma_pos;
- if (up->uart_dma.rx_buf_size +
- up->uart_dma.rx_buf_dma_phys == curr_dma_pos) {
- ret = serial_omap_start_rxdma(up);
- if (ret < 0) {
- serial_omap_stop_rxdma(up);
- up->ier |= (UART_IER_RDI | UART_IER_RLSI);
- serial_out(up, UART_IER, up->ier);
- }
- } else {
- mod_timer(&up->uart_dma.rx_timer, jiffies +
- usecs_to_jiffies(up->uart_dma.rx_poll_rate));
- }
- up->port_activity = jiffies;
-}
-
-static void uart_rx_dma_callback(int lch, u16 ch_status, void *data)
-{
- return;
-}
-
-static int serial_omap_start_rxdma(struct uart_omap_port *up)
-{
- int ret = 0;
-
- if (up->uart_dma.rx_dma_channel == -1) {
- pm_runtime_get_sync(&up->pdev->dev);
- ret = omap_request_dma(up->uart_dma.uart_dma_rx,
- "UART Rx DMA",
- (void *)uart_rx_dma_callback, up,
- &(up->uart_dma.rx_dma_channel));
- if (ret < 0)
- return ret;
-
- omap_set_dma_src_params(up->uart_dma.rx_dma_channel, 0,
- OMAP_DMA_AMODE_CONSTANT,
- up->uart_dma.uart_base, 0, 0);
- omap_set_dma_dest_params(up->uart_dma.rx_dma_channel, 0,
- OMAP_DMA_AMODE_POST_INC,
- up->uart_dma.rx_buf_dma_phys, 0, 0);
- omap_set_dma_transfer_params(up->uart_dma.rx_dma_channel,
- OMAP_DMA_DATA_TYPE_S8,
- up->uart_dma.rx_buf_size, 1,
- OMAP_DMA_SYNC_ELEMENT,
- up->uart_dma.uart_dma_rx, 0);
- }
- up->uart_dma.prev_rx_dma_pos = up->uart_dma.rx_buf_dma_phys;
- /* FIXME: Cache maintenance needed here? */
- omap_start_dma(up->uart_dma.rx_dma_channel);
- mod_timer(&up->uart_dma.rx_timer, jiffies +
- usecs_to_jiffies(up->uart_dma.rx_poll_rate));
- up->uart_dma.rx_dma_used = true;
- return ret;
-}
-
-static void serial_omap_continue_tx(struct uart_omap_port *up)
-{
- struct circ_buf *xmit = &up->port.state->xmit;
- unsigned int start = up->uart_dma.tx_buf_dma_phys
- + (xmit->tail & (UART_XMIT_SIZE - 1));
-
- if (uart_circ_empty(xmit))
- return;
-
- up->uart_dma.tx_buf_size = uart_circ_chars_pending(xmit);
- /*
- * It is a circular buffer. See if the buffer has wounded back.
- * If yes it will have to be transferred in two separate dma
- * transfers
- */
- if (start + up->uart_dma.tx_buf_size >=
- up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE)
- up->uart_dma.tx_buf_size =
- (up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) - start;
- omap_set_dma_dest_params(up->uart_dma.tx_dma_channel, 0,
- OMAP_DMA_AMODE_CONSTANT,
- up->uart_dma.uart_base, 0, 0);
- omap_set_dma_src_params(up->uart_dma.tx_dma_channel, 0,
- OMAP_DMA_AMODE_POST_INC, start, 0, 0);
- omap_set_dma_transfer_params(up->uart_dma.tx_dma_channel,
- OMAP_DMA_DATA_TYPE_S8,
- up->uart_dma.tx_buf_size, 1,
- OMAP_DMA_SYNC_ELEMENT,
- up->uart_dma.uart_dma_tx, 0);
- /* FIXME: Cache maintenance needed here? */
- omap_start_dma(up->uart_dma.tx_dma_channel);
-}
-
-static void uart_tx_dma_callback(int lch, u16 ch_status, void *data)
-{
- struct uart_omap_port *up = (struct uart_omap_port *)data;
- struct circ_buf *xmit = &up->port.state->xmit;
-
- xmit->tail = (xmit->tail + up->uart_dma.tx_buf_size) & \
- (UART_XMIT_SIZE - 1);
- up->port.icount.tx += up->uart_dma.tx_buf_size;
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&up->port);
-
- if (uart_circ_empty(xmit)) {
- spin_lock(&(up->uart_dma.tx_lock));
- serial_omap_stop_tx(&up->port);
- up->uart_dma.tx_dma_used = false;
- spin_unlock(&(up->uart_dma.tx_lock));
- } else {
- omap_stop_dma(up->uart_dma.tx_dma_channel);
- serial_omap_continue_tx(up);
- }
- up->port_activity = jiffies;
- return;
-}
-
-static void omap_serial_fill_features_erratas(struct uart_omap_port *up)
+static void __devinit omap_serial_fill_features_erratas(struct uart_omap_port *up)
{
u32 mvr, scheme;
u16 revision, major, minor;
@@ -1389,7 +1265,7 @@
minor = (mvr & OMAP_UART_MVR_MIN_MASK);
break;
default:
- dev_warn(&up->pdev->dev,
+ dev_warn(up->dev,
"Unknown %s revision, defaulting to highest\n",
up->name);
/* highest possible revision */
@@ -1417,7 +1293,7 @@
}
}
-static struct omap_uart_port_info *of_get_uart_port_info(struct device *dev)
+static __devinit struct omap_uart_port_info *of_get_uart_port_info(struct device *dev)
{
struct omap_uart_port_info *omap_up_info;
@@ -1430,12 +1306,12 @@
return omap_up_info;
}
-static int serial_omap_probe(struct platform_device *pdev)
+static int __devinit serial_omap_probe(struct platform_device *pdev)
{
struct uart_omap_port *up;
- struct resource *mem, *irq, *dma_tx, *dma_rx;
+ struct resource *mem, *irq;
struct omap_uart_port_info *omap_up_info = pdev->dev.platform_data;
- int ret = -ENOSPC;
+ int ret;
if (pdev->dev.of_node)
omap_up_info = of_get_uart_port_info(&pdev->dev);
@@ -1458,19 +1334,30 @@
return -EBUSY;
}
- dma_rx = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
- if (!dma_rx)
- return -ENXIO;
-
- dma_tx = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
- if (!dma_tx)
- return -ENXIO;
+ if (gpio_is_valid(omap_up_info->DTR_gpio) &&
+ omap_up_info->DTR_present) {
+ ret = gpio_request(omap_up_info->DTR_gpio, "omap-serial");
+ if (ret < 0)
+ return ret;
+ ret = gpio_direction_output(omap_up_info->DTR_gpio,
+ omap_up_info->DTR_inverted);
+ if (ret < 0)
+ return ret;
+ }
up = devm_kzalloc(&pdev->dev, sizeof(*up), GFP_KERNEL);
if (!up)
return -ENOMEM;
- up->pdev = pdev;
+ if (gpio_is_valid(omap_up_info->DTR_gpio) &&
+ omap_up_info->DTR_present) {
+ up->DTR_gpio = omap_up_info->DTR_gpio;
+ up->DTR_inverted = omap_up_info->DTR_inverted;
+ } else
+ up->DTR_gpio = -EINVAL;
+ up->DTR_active = 0;
+
+ up->dev = &pdev->dev;
up->port.dev = &pdev->dev;
up->port.type = PORT_OMAP;
up->port.iotype = UPIO_MEM;
@@ -1492,6 +1379,13 @@
goto err_port_line;
}
+ up->pins = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(up->pins)) {
+ dev_warn(&pdev->dev, "did not get pins for uart%i error: %li\n",
+ up->port.line, PTR_ERR(up->pins));
+ up->pins = NULL;
+ }
+
sprintf(up->name, "OMAP UART%d", up->port.line);
up->port.mapbase = mem->start;
up->port.membase = devm_ioremap(&pdev->dev, mem->start,
@@ -1509,20 +1403,6 @@
dev_warn(&pdev->dev, "No clock speed specified: using default:"
"%d\n", DEFAULT_CLK_SPEED);
}
- up->uart_dma.uart_base = mem->start;
-
- if (omap_up_info->dma_enabled) {
- up->uart_dma.uart_dma_tx = dma_tx->start;
- up->uart_dma.uart_dma_rx = dma_rx->start;
- up->use_dma = 1;
- up->uart_dma.rx_buf_size = omap_up_info->dma_rx_buf_size;
- up->uart_dma.rx_timeout = omap_up_info->dma_rx_timeout;
- up->uart_dma.rx_poll_rate = omap_up_info->dma_rx_poll_rate;
- spin_lock_init(&(up->uart_dma.tx_lock));
- spin_lock_init(&(up->uart_dma.rx_lock));
- up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
- up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
- }
up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
up->calc_latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
@@ -1531,12 +1411,13 @@
serial_omap_uart_wq = create_singlethread_workqueue(up->name);
INIT_WORK(&up->qos_work, serial_omap_uart_qos_work);
+ platform_set_drvdata(pdev, up);
+ pm_runtime_enable(&pdev->dev);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev,
omap_up_info->autosuspend_timeout);
pm_runtime_irq_safe(&pdev->dev);
- pm_runtime_enable(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
omap_serial_fill_features_erratas(up);
@@ -1548,8 +1429,8 @@
if (ret != 0)
goto err_add_port;
- pm_runtime_put(&pdev->dev);
- platform_set_drvdata(pdev, up);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
return 0;
err_add_port:
@@ -1562,17 +1443,15 @@
return ret;
}
-static int serial_omap_remove(struct platform_device *dev)
+static int __devexit serial_omap_remove(struct platform_device *dev)
{
struct uart_omap_port *up = platform_get_drvdata(dev);
- if (up) {
- pm_runtime_disable(&up->pdev->dev);
- uart_remove_one_port(&serial_omap_reg, &up->port);
- pm_qos_remove_request(&up->pm_qos_request);
- }
+ pm_runtime_put_sync(up->dev);
+ pm_runtime_disable(up->dev);
+ uart_remove_one_port(&serial_omap_reg, &up->port);
+ pm_qos_remove_request(&up->pm_qos_request);
- platform_set_drvdata(dev, NULL);
return 0;
}
@@ -1602,7 +1481,7 @@
timeout--;
if (!timeout) {
/* Should *never* happen. we warn and carry on */
- dev_crit(&up->pdev->dev, "Errata i202: timedout %x\n",
+ dev_crit(up->dev, "Errata i202: timedout %x\n",
serial_in(up, UART_LSR));
break;
}
@@ -1648,29 +1527,23 @@
if (!up)
return -EINVAL;
- if (!pdata || !pdata->enable_wakeup)
+ if (!pdata)
return 0;
- if (pdata->get_context_loss_count)
- up->context_loss_cnt = pdata->get_context_loss_count(dev);
+ up->context_loss_cnt = serial_omap_get_context_loss_count(up);
if (device_may_wakeup(dev)) {
if (!up->wakeups_enabled) {
- pdata->enable_wakeup(up->pdev, true);
+ serial_omap_enable_wakeup(up, true);
up->wakeups_enabled = true;
}
} else {
if (up->wakeups_enabled) {
- pdata->enable_wakeup(up->pdev, false);
+ serial_omap_enable_wakeup(up, false);
up->wakeups_enabled = false;
}
}
- /* Errata i291 */
- if (up->use_dma && pdata->set_forceidle &&
- (up->errata & UART_ERRATA_i291_DMA_FORCEIDLE))
- pdata->set_forceidle(up->pdev);
-
up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
schedule_work(&up->qos_work);
@@ -1683,17 +1556,10 @@
struct omap_uart_port_info *pdata = dev->platform_data;
if (up && pdata) {
- if (pdata->get_context_loss_count) {
- u32 loss_cnt = pdata->get_context_loss_count(dev);
+ u32 loss_cnt = serial_omap_get_context_loss_count(up);
if (up->context_loss_cnt != loss_cnt)
serial_omap_restore_context(up);
- }
-
- /* Errata i291 */
- if (up->use_dma && pdata->set_noidle &&
- (up->errata & UART_ERRATA_i291_DMA_FORCEIDLE))
- pdata->set_noidle(up->pdev);
up->latency = up->calc_latency;
schedule_work(&up->qos_work);
@@ -1721,7 +1587,7 @@
static struct platform_driver serial_omap_driver = {
.probe = serial_omap_probe,
- .remove = serial_omap_remove,
+ .remove = __devexit_p(serial_omap_remove),
.driver = {
.name = DRIVER_NAME,
.pm = &serial_omap_dev_pm_ops,
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index 558ce85..4cd6c23 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -979,6 +979,10 @@
priv->tx_dma_use = 1;
priv->sg_tx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC);
+ if (!priv->sg_tx_p) {
+ dev_err(priv->port.dev, "%s:kzalloc Failed\n", __func__);
+ return 0;
+ }
sg_init_table(priv->sg_tx_p, num); /* Initialize SG table */
sg = priv->sg_tx_p;
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
index 5847a4b..9033fc6 100644
--- a/drivers/tty/serial/pxa.c
+++ b/drivers/tty/serial/pxa.c
@@ -670,9 +670,19 @@
{
struct uart_pxa_port *up = serial_pxa_ports[co->index];
unsigned int ier;
+ unsigned long flags;
+ int locked = 1;
clk_prepare_enable(up->clk);
+ local_irq_save(flags);
+ if (up->port.sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+ locked = spin_trylock(&up->port.lock);
+ else
+ spin_lock(&up->port.lock);
+
/*
* First save the IER then disable the interrupts
*/
@@ -688,6 +698,10 @@
wait_for_xmitr(up);
serial_out(up, UART_IER, ier);
+ if (locked)
+ spin_unlock(&up->port.lock);
+ local_irq_restore(flags);
+
clk_disable_unprepare(up->clk);
}
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 02d07bf..bdaa06f 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -82,7 +82,7 @@
static int s3c24xx_serial_txempty_nofifo(struct uart_port *port)
{
- return (rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE);
+ return rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE;
}
/*
@@ -268,7 +268,7 @@
dbg("break!\n");
port->icount.brk++;
if (uart_handle_break(port))
- goto ignore_char;
+ goto ignore_char;
}
if (uerstat & S3C2410_UERSTAT_FRAME)
@@ -459,7 +459,7 @@
s3c24xx_serial_portname(port), ourport);
if (ret != 0) {
- printk(KERN_ERR "cannot get irq %d\n", ourport->rx_irq);
+ dev_err(port->dev, "cannot get irq %d\n", ourport->rx_irq);
return ret;
}
@@ -473,7 +473,7 @@
s3c24xx_serial_portname(port), ourport);
if (ret) {
- printk(KERN_ERR "cannot get irq %d\n", ourport->tx_irq);
+ dev_err(port->dev, "cannot get irq %d\n", ourport->tx_irq);
goto err;
}
@@ -502,7 +502,7 @@
ret = request_irq(port->irq, s3c64xx_serial_handle_irq, IRQF_SHARED,
s3c24xx_serial_portname(port), ourport);
if (ret) {
- printk(KERN_ERR "cannot get irq %d\n", port->irq);
+ dev_err(port->dev, "cannot get irq %d\n", port->irq);
return ret;
}
@@ -529,7 +529,7 @@
switch (level) {
case 3:
- if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL)
+ if (!IS_ERR(ourport->baudclk))
clk_disable(ourport->baudclk);
clk_disable(ourport->clk);
@@ -538,12 +538,12 @@
case 0:
clk_enable(ourport->clk);
- if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL)
+ if (!IS_ERR(ourport->baudclk))
clk_enable(ourport->baudclk);
break;
default:
- printk(KERN_ERR "s3c24xx_serial: unknown pm %d\n", level);
+ dev_err(port->dev, "s3c24xx_serial: unknown pm %d\n", level);
}
}
@@ -604,7 +604,6 @@
char clkname[MAX_CLK_NAME_LENGTH];
int calc_deviation, deviation = (1 << 30) - 1;
- *best_clk = NULL;
clk_sel = (ourport->cfg->clk_sel) ? ourport->cfg->clk_sel :
ourport->info->def_clk_sel;
for (cnt = 0; cnt < info->num_clks; cnt++) {
@@ -613,7 +612,7 @@
sprintf(clkname, "clk_uart_baud%d", cnt);
clk = clk_get(ourport->port.dev, clkname);
- if (IS_ERR_OR_NULL(clk))
+ if (IS_ERR(clk))
continue;
rate = clk_get_rate(clk);
@@ -684,7 +683,7 @@
{
struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
struct s3c24xx_uart_port *ourport = to_ourport(port);
- struct clk *clk = NULL;
+ struct clk *clk = ERR_PTR(-EINVAL);
unsigned long flags;
unsigned int baud, quot, clk_sel = 0;
unsigned int ulcon;
@@ -705,7 +704,7 @@
quot = s3c24xx_serial_getclk(ourport, baud, &clk, &clk_sel);
if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
quot = port->custom_divisor;
- if (!clk)
+ if (IS_ERR(clk))
return;
/* check to see if we need to change clock source */
@@ -713,9 +712,9 @@
if (ourport->baudclk != clk) {
s3c24xx_serial_setsource(port, clk_sel);
- if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) {
+ if (!IS_ERR(ourport->baudclk)) {
clk_disable(ourport->baudclk);
- ourport->baudclk = NULL;
+ ourport->baudclk = ERR_PTR(-EINVAL);
}
clk_enable(clk);
@@ -1036,10 +1035,10 @@
if (tty == NULL)
goto exit;
- termios = tty->termios;
+ termios = &tty->termios;
if (termios == NULL) {
- printk(KERN_WARNING "%s: no termios?\n", __func__);
+ dev_warn(uport->dev, "%s: no termios?\n", __func__);
goto exit;
}
@@ -1114,7 +1113,7 @@
res = platform_get_resource(platdev, IORESOURCE_MEM, 0);
if (res == NULL) {
- printk(KERN_ERR "failed to find memory resource for uart\n");
+ dev_err(port->dev, "failed to find memory resource for uart\n");
return -EINVAL;
}
@@ -1130,7 +1129,7 @@
ourport->rx_irq = ret;
ourport->tx_irq = ret + 1;
}
-
+
ret = platform_get_irq(platdev, 1);
if (ret > 0)
ourport->tx_irq = ret;
@@ -1160,7 +1159,11 @@
struct uart_port *port = s3c24xx_dev_to_port(dev);
struct s3c24xx_uart_port *ourport = to_ourport(port);
- return snprintf(buf, PAGE_SIZE, "* %s\n", ourport->baudclk->name);
+ if (IS_ERR(ourport->baudclk))
+ return -EINVAL;
+
+ return snprintf(buf, PAGE_SIZE, "* %s\n",
+ ourport->baudclk->name ?: "(null)");
}
static DEVICE_ATTR(clock_source, S_IRUGO, s3c24xx_serial_show_clksrc, NULL);
@@ -1200,6 +1203,7 @@
return -ENODEV;
}
+ ourport->baudclk = ERR_PTR(-EINVAL);
ourport->info = ourport->drv_data->info;
ourport->cfg = (pdev->dev.platform_data) ?
(struct s3c2410_uartcfg *)pdev->dev.platform_data :
@@ -1387,7 +1391,7 @@
sprintf(clk_name, "clk_uart_baud%d", clk_sel);
clk = clk_get(port->dev, clk_name);
- if (!IS_ERR(clk) && clk != NULL)
+ if (!IS_ERR(clk))
rate = clk_get_rate(clk);
else
rate = 1;
@@ -1679,7 +1683,7 @@
ret = uart_register_driver(&s3c24xx_uart_drv);
if (ret < 0) {
- printk(KERN_ERR "failed to register UART driver\n");
+ pr_err("Failed to register Samsung UART driver\n");
return -1;
}
diff --git a/drivers/tty/serial/sc26xx.c b/drivers/tty/serial/sc26xx.c
index e0b4b0a..9d66424 100644
--- a/drivers/tty/serial/sc26xx.c
+++ b/drivers/tty/serial/sc26xx.c
@@ -20,6 +20,10 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/irq.h>
+#include <linux/io.h>
+
+#warning "Please try migrate to use new driver SCCNXP and report the status" \
+ "in the linux-serial mailing list."
#if defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c
new file mode 100644
index 0000000..05d767c
--- /dev/null
+++ b/drivers/tty/serial/sccnxp.c
@@ -0,0 +1,985 @@
+/*
+ * NXP (Philips) SCC+++(SCN+++) serial driver
+ *
+ * Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
+ *
+ * Based on sc26xx.c, by Thomas Bogendörfer (tsbogend@alpha.franken.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#if defined(CONFIG_SERIAL_SCCNXP_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/console.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/io.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/sccnxp.h>
+
+#define SCCNXP_NAME "uart-sccnxp"
+#define SCCNXP_MAJOR 204
+#define SCCNXP_MINOR 205
+
+#define SCCNXP_MR_REG (0x00)
+# define MR0_BAUD_NORMAL (0 << 0)
+# define MR0_BAUD_EXT1 (1 << 0)
+# define MR0_BAUD_EXT2 (5 << 0)
+# define MR0_FIFO (1 << 3)
+# define MR0_TXLVL (1 << 4)
+# define MR1_BITS_5 (0 << 0)
+# define MR1_BITS_6 (1 << 0)
+# define MR1_BITS_7 (2 << 0)
+# define MR1_BITS_8 (3 << 0)
+# define MR1_PAR_EVN (0 << 2)
+# define MR1_PAR_ODD (1 << 2)
+# define MR1_PAR_NO (4 << 2)
+# define MR2_STOP1 (7 << 0)
+# define MR2_STOP2 (0xf << 0)
+#define SCCNXP_SR_REG (0x01)
+#define SCCNXP_CSR_REG SCCNXP_SR_REG
+# define SR_RXRDY (1 << 0)
+# define SR_FULL (1 << 1)
+# define SR_TXRDY (1 << 2)
+# define SR_TXEMT (1 << 3)
+# define SR_OVR (1 << 4)
+# define SR_PE (1 << 5)
+# define SR_FE (1 << 6)
+# define SR_BRK (1 << 7)
+#define SCCNXP_CR_REG (0x02)
+# define CR_RX_ENABLE (1 << 0)
+# define CR_RX_DISABLE (1 << 1)
+# define CR_TX_ENABLE (1 << 2)
+# define CR_TX_DISABLE (1 << 3)
+# define CR_CMD_MRPTR1 (0x01 << 4)
+# define CR_CMD_RX_RESET (0x02 << 4)
+# define CR_CMD_TX_RESET (0x03 << 4)
+# define CR_CMD_STATUS_RESET (0x04 << 4)
+# define CR_CMD_BREAK_RESET (0x05 << 4)
+# define CR_CMD_START_BREAK (0x06 << 4)
+# define CR_CMD_STOP_BREAK (0x07 << 4)
+# define CR_CMD_MRPTR0 (0x0b << 4)
+#define SCCNXP_RHR_REG (0x03)
+#define SCCNXP_THR_REG SCCNXP_RHR_REG
+#define SCCNXP_IPCR_REG (0x04)
+#define SCCNXP_ACR_REG SCCNXP_IPCR_REG
+# define ACR_BAUD0 (0 << 7)
+# define ACR_BAUD1 (1 << 7)
+# define ACR_TIMER_MODE (6 << 4)
+#define SCCNXP_ISR_REG (0x05)
+#define SCCNXP_IMR_REG SCCNXP_ISR_REG
+# define IMR_TXRDY (1 << 0)
+# define IMR_RXRDY (1 << 1)
+# define ISR_TXRDY(x) (1 << ((x * 4) + 0))
+# define ISR_RXRDY(x) (1 << ((x * 4) + 1))
+#define SCCNXP_IPR_REG (0x0d)
+#define SCCNXP_OPCR_REG SCCNXP_IPR_REG
+#define SCCNXP_SOP_REG (0x0e)
+#define SCCNXP_ROP_REG (0x0f)
+
+/* Route helpers */
+#define MCTRL_MASK(sig) (0xf << (sig))
+#define MCTRL_IBIT(cfg, sig) ((((cfg) >> (sig)) & 0xf) - LINE_IP0)
+#define MCTRL_OBIT(cfg, sig) ((((cfg) >> (sig)) & 0xf) - LINE_OP0)
+
+/* Supported chip types */
+enum {
+ SCCNXP_TYPE_SC2681 = 2681,
+ SCCNXP_TYPE_SC2691 = 2691,
+ SCCNXP_TYPE_SC2692 = 2692,
+ SCCNXP_TYPE_SC2891 = 2891,
+ SCCNXP_TYPE_SC2892 = 2892,
+ SCCNXP_TYPE_SC28202 = 28202,
+ SCCNXP_TYPE_SC68681 = 68681,
+ SCCNXP_TYPE_SC68692 = 68692,
+};
+
+struct sccnxp_port {
+ struct uart_driver uart;
+ struct uart_port port[SCCNXP_MAX_UARTS];
+
+ const char *name;
+ int irq;
+
+ u8 imr;
+ u8 addr_mask;
+ int freq_std;
+
+ int flags;
+#define SCCNXP_HAVE_IO 0x00000001
+#define SCCNXP_HAVE_MR0 0x00000002
+
+#ifdef CONFIG_SERIAL_SCCNXP_CONSOLE
+ struct console console;
+#endif
+
+ struct mutex sccnxp_mutex;
+
+ struct sccnxp_pdata pdata;
+};
+
+static inline u8 sccnxp_raw_read(void __iomem *base, u8 reg, u8 shift)
+{
+ return readb(base + (reg << shift));
+}
+
+static inline void sccnxp_raw_write(void __iomem *base, u8 reg, u8 shift, u8 v)
+{
+ writeb(v, base + (reg << shift));
+}
+
+static inline u8 sccnxp_read(struct uart_port *port, u8 reg)
+{
+ struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
+ return sccnxp_raw_read(port->membase, reg & s->addr_mask,
+ port->regshift);
+}
+
+static inline void sccnxp_write(struct uart_port *port, u8 reg, u8 v)
+{
+ struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
+ sccnxp_raw_write(port->membase, reg & s->addr_mask, port->regshift, v);
+}
+
+static inline u8 sccnxp_port_read(struct uart_port *port, u8 reg)
+{
+ return sccnxp_read(port, (port->line << 3) + reg);
+}
+
+static inline void sccnxp_port_write(struct uart_port *port, u8 reg, u8 v)
+{
+ sccnxp_write(port, (port->line << 3) + reg, v);
+}
+
+static int sccnxp_update_best_err(int a, int b, int *besterr)
+{
+ int err = abs(a - b);
+
+ if ((*besterr < 0) || (*besterr > err)) {
+ *besterr = err;
+ return 0;
+ }
+
+ return 1;
+}
+
+struct baud_table {
+ u8 csr;
+ u8 acr;
+ u8 mr0;
+ int baud;
+};
+
+const struct baud_table baud_std[] = {
+ { 0, ACR_BAUD0, MR0_BAUD_NORMAL, 50, },
+ { 0, ACR_BAUD1, MR0_BAUD_NORMAL, 75, },
+ { 1, ACR_BAUD0, MR0_BAUD_NORMAL, 110, },
+ { 2, ACR_BAUD0, MR0_BAUD_NORMAL, 134, },
+ { 3, ACR_BAUD1, MR0_BAUD_NORMAL, 150, },
+ { 3, ACR_BAUD0, MR0_BAUD_NORMAL, 200, },
+ { 4, ACR_BAUD0, MR0_BAUD_NORMAL, 300, },
+ { 0, ACR_BAUD1, MR0_BAUD_EXT1, 450, },
+ { 1, ACR_BAUD0, MR0_BAUD_EXT2, 880, },
+ { 3, ACR_BAUD1, MR0_BAUD_EXT1, 900, },
+ { 5, ACR_BAUD0, MR0_BAUD_NORMAL, 600, },
+ { 7, ACR_BAUD0, MR0_BAUD_NORMAL, 1050, },
+ { 2, ACR_BAUD0, MR0_BAUD_EXT2, 1076, },
+ { 6, ACR_BAUD0, MR0_BAUD_NORMAL, 1200, },
+ { 10, ACR_BAUD1, MR0_BAUD_NORMAL, 1800, },
+ { 7, ACR_BAUD1, MR0_BAUD_NORMAL, 2000, },
+ { 8, ACR_BAUD0, MR0_BAUD_NORMAL, 2400, },
+ { 5, ACR_BAUD1, MR0_BAUD_EXT1, 3600, },
+ { 9, ACR_BAUD0, MR0_BAUD_NORMAL, 4800, },
+ { 10, ACR_BAUD0, MR0_BAUD_NORMAL, 7200, },
+ { 11, ACR_BAUD0, MR0_BAUD_NORMAL, 9600, },
+ { 8, ACR_BAUD0, MR0_BAUD_EXT1, 14400, },
+ { 12, ACR_BAUD1, MR0_BAUD_NORMAL, 19200, },
+ { 9, ACR_BAUD0, MR0_BAUD_EXT1, 28800, },
+ { 12, ACR_BAUD0, MR0_BAUD_NORMAL, 38400, },
+ { 11, ACR_BAUD0, MR0_BAUD_EXT1, 57600, },
+ { 12, ACR_BAUD1, MR0_BAUD_EXT1, 115200, },
+ { 12, ACR_BAUD0, MR0_BAUD_EXT1, 230400, },
+ { 0, 0, 0, 0 }
+};
+
+static void sccnxp_set_baud(struct uart_port *port, int baud)
+{
+ struct sccnxp_port *s = dev_get_drvdata(port->dev);
+ int div_std, tmp_baud, bestbaud = baud, besterr = -1;
+ u8 i, acr = 0, csr = 0, mr0 = 0;
+
+ /* Find best baud from table */
+ for (i = 0; baud_std[i].baud && besterr; i++) {
+ if (baud_std[i].mr0 && !(s->flags & SCCNXP_HAVE_MR0))
+ continue;
+ div_std = DIV_ROUND_CLOSEST(s->freq_std, baud_std[i].baud);
+ tmp_baud = DIV_ROUND_CLOSEST(port->uartclk, div_std);
+ if (!sccnxp_update_best_err(baud, tmp_baud, &besterr)) {
+ acr = baud_std[i].acr;
+ csr = baud_std[i].csr;
+ mr0 = baud_std[i].mr0;
+ bestbaud = tmp_baud;
+ }
+ }
+
+ if (s->flags & SCCNXP_HAVE_MR0) {
+ /* Enable FIFO, set half level for TX */
+ mr0 |= MR0_FIFO | MR0_TXLVL;
+ /* Update MR0 */
+ sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_MRPTR0);
+ sccnxp_port_write(port, SCCNXP_MR_REG, mr0);
+ }
+
+ sccnxp_port_write(port, SCCNXP_ACR_REG, acr | ACR_TIMER_MODE);
+ sccnxp_port_write(port, SCCNXP_CSR_REG, (csr << 4) | csr);
+
+ dev_dbg(port->dev, "Baudrate desired: %i, calculated: %i\n",
+ baud, bestbaud);
+}
+
+static void sccnxp_enable_irq(struct uart_port *port, int mask)
+{
+ struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
+ s->imr |= mask << (port->line * 4);
+ sccnxp_write(port, SCCNXP_IMR_REG, s->imr);
+}
+
+static void sccnxp_disable_irq(struct uart_port *port, int mask)
+{
+ struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
+ s->imr &= ~(mask << (port->line * 4));
+ sccnxp_write(port, SCCNXP_IMR_REG, s->imr);
+}
+
+static void sccnxp_set_bit(struct uart_port *port, int sig, int state)
+{
+ u8 bitmask;
+ struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
+ if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(sig)) {
+ bitmask = 1 << MCTRL_OBIT(s->pdata.mctrl_cfg[port->line], sig);
+ if (state)
+ sccnxp_write(port, SCCNXP_SOP_REG, bitmask);
+ else
+ sccnxp_write(port, SCCNXP_ROP_REG, bitmask);
+ }
+}
+
+static void sccnxp_handle_rx(struct uart_port *port)
+{
+ u8 sr;
+ unsigned int ch, flag;
+ struct tty_struct *tty = tty_port_tty_get(&port->state->port);
+
+ if (!tty)
+ return;
+
+ for (;;) {
+ sr = sccnxp_port_read(port, SCCNXP_SR_REG);
+ if (!(sr & SR_RXRDY))
+ break;
+ sr &= SR_PE | SR_FE | SR_OVR | SR_BRK;
+
+ ch = sccnxp_port_read(port, SCCNXP_RHR_REG);
+
+ port->icount.rx++;
+ flag = TTY_NORMAL;
+
+ if (unlikely(sr)) {
+ if (sr & SR_BRK) {
+ port->icount.brk++;
+ if (uart_handle_break(port))
+ continue;
+ } else if (sr & SR_PE)
+ port->icount.parity++;
+ else if (sr & SR_FE)
+ port->icount.frame++;
+ else if (sr & SR_OVR)
+ port->icount.overrun++;
+
+ sr &= port->read_status_mask;
+ if (sr & SR_BRK)
+ flag = TTY_BREAK;
+ else if (sr & SR_PE)
+ flag = TTY_PARITY;
+ else if (sr & SR_FE)
+ flag = TTY_FRAME;
+ else if (sr & SR_OVR)
+ flag = TTY_OVERRUN;
+ }
+
+ if (uart_handle_sysrq_char(port, ch))
+ continue;
+
+ if (sr & port->ignore_status_mask)
+ continue;
+
+ uart_insert_char(port, sr, SR_OVR, ch, flag);
+ }
+
+ tty_flip_buffer_push(tty);
+
+ tty_kref_put(tty);
+}
+
+static void sccnxp_handle_tx(struct uart_port *port)
+{
+ u8 sr;
+ struct circ_buf *xmit = &port->state->xmit;
+ struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
+ if (unlikely(port->x_char)) {
+ sccnxp_port_write(port, SCCNXP_THR_REG, port->x_char);
+ port->icount.tx++;
+ port->x_char = 0;
+ return;
+ }
+
+ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+ /* Disable TX if FIFO is empty */
+ if (sccnxp_port_read(port, SCCNXP_SR_REG) & SR_TXEMT) {
+ sccnxp_disable_irq(port, IMR_TXRDY);
+
+ /* Set direction to input */
+ if (s->flags & SCCNXP_HAVE_IO)
+ sccnxp_set_bit(port, DIR_OP, 0);
+ }
+ return;
+ }
+
+ while (!uart_circ_empty(xmit)) {
+ sr = sccnxp_port_read(port, SCCNXP_SR_REG);
+ if (!(sr & SR_TXRDY))
+ break;
+
+ sccnxp_port_write(port, SCCNXP_THR_REG, xmit->buf[xmit->tail]);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ port->icount.tx++;
+ }
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+}
+
+static irqreturn_t sccnxp_ist(int irq, void *dev_id)
+{
+ int i;
+ u8 isr;
+ struct sccnxp_port *s = (struct sccnxp_port *)dev_id;
+
+ mutex_lock(&s->sccnxp_mutex);
+
+ for (;;) {
+ isr = sccnxp_read(&s->port[0], SCCNXP_ISR_REG);
+ isr &= s->imr;
+ if (!isr)
+ break;
+
+ dev_dbg(s->port[0].dev, "IRQ status: 0x%02x\n", isr);
+
+ for (i = 0; i < s->uart.nr; i++) {
+ if (isr & ISR_RXRDY(i))
+ sccnxp_handle_rx(&s->port[i]);
+ if (isr & ISR_TXRDY(i))
+ sccnxp_handle_tx(&s->port[i]);
+ }
+ }
+
+ mutex_unlock(&s->sccnxp_mutex);
+
+ return IRQ_HANDLED;
+}
+
+static void sccnxp_start_tx(struct uart_port *port)
+{
+ struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
+ mutex_lock(&s->sccnxp_mutex);
+
+ /* Set direction to output */
+ if (s->flags & SCCNXP_HAVE_IO)
+ sccnxp_set_bit(port, DIR_OP, 1);
+
+ sccnxp_enable_irq(port, IMR_TXRDY);
+
+ mutex_unlock(&s->sccnxp_mutex);
+}
+
+static void sccnxp_stop_tx(struct uart_port *port)
+{
+ /* Do nothing */
+}
+
+static void sccnxp_stop_rx(struct uart_port *port)
+{
+ struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
+ mutex_lock(&s->sccnxp_mutex);
+ sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_DISABLE);
+ mutex_unlock(&s->sccnxp_mutex);
+}
+
+static unsigned int sccnxp_tx_empty(struct uart_port *port)
+{
+ u8 val;
+ struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
+ mutex_lock(&s->sccnxp_mutex);
+ val = sccnxp_port_read(port, SCCNXP_SR_REG);
+ mutex_unlock(&s->sccnxp_mutex);
+
+ return (val & SR_TXEMT) ? TIOCSER_TEMT : 0;
+}
+
+static void sccnxp_enable_ms(struct uart_port *port)
+{
+ /* Do nothing */
+}
+
+static void sccnxp_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
+ if (!(s->flags & SCCNXP_HAVE_IO))
+ return;
+
+ mutex_lock(&s->sccnxp_mutex);
+
+ sccnxp_set_bit(port, DTR_OP, mctrl & TIOCM_DTR);
+ sccnxp_set_bit(port, RTS_OP, mctrl & TIOCM_RTS);
+
+ mutex_unlock(&s->sccnxp_mutex);
+}
+
+static unsigned int sccnxp_get_mctrl(struct uart_port *port)
+{
+ u8 bitmask, ipr;
+ struct sccnxp_port *s = dev_get_drvdata(port->dev);
+ unsigned int mctrl = TIOCM_DSR | TIOCM_CTS | TIOCM_CAR;
+
+ if (!(s->flags & SCCNXP_HAVE_IO))
+ return mctrl;
+
+ mutex_lock(&s->sccnxp_mutex);
+
+ ipr = ~sccnxp_read(port, SCCNXP_IPCR_REG);
+
+ if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(DSR_IP)) {
+ bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line],
+ DSR_IP);
+ mctrl &= ~TIOCM_DSR;
+ mctrl |= (ipr & bitmask) ? TIOCM_DSR : 0;
+ }
+ if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(CTS_IP)) {
+ bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line],
+ CTS_IP);
+ mctrl &= ~TIOCM_CTS;
+ mctrl |= (ipr & bitmask) ? TIOCM_CTS : 0;
+ }
+ if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(DCD_IP)) {
+ bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line],
+ DCD_IP);
+ mctrl &= ~TIOCM_CAR;
+ mctrl |= (ipr & bitmask) ? TIOCM_CAR : 0;
+ }
+ if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(RNG_IP)) {
+ bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line],
+ RNG_IP);
+ mctrl &= ~TIOCM_RNG;
+ mctrl |= (ipr & bitmask) ? TIOCM_RNG : 0;
+ }
+
+ mutex_unlock(&s->sccnxp_mutex);
+
+ return mctrl;
+}
+
+static void sccnxp_break_ctl(struct uart_port *port, int break_state)
+{
+ struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
+ mutex_lock(&s->sccnxp_mutex);
+ sccnxp_port_write(port, SCCNXP_CR_REG, break_state ?
+ CR_CMD_START_BREAK : CR_CMD_STOP_BREAK);
+ mutex_unlock(&s->sccnxp_mutex);
+}
+
+static void sccnxp_set_termios(struct uart_port *port,
+ struct ktermios *termios, struct ktermios *old)
+{
+ struct sccnxp_port *s = dev_get_drvdata(port->dev);
+ u8 mr1, mr2;
+ int baud;
+
+ mutex_lock(&s->sccnxp_mutex);
+
+ /* Mask termios capabilities we don't support */
+ termios->c_cflag &= ~CMSPAR;
+ termios->c_iflag &= ~(IXON | IXOFF | IXANY);
+
+ /* Disable RX & TX, reset break condition, status and FIFOs */
+ sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_RX_RESET |
+ CR_RX_DISABLE | CR_TX_DISABLE);
+ sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_TX_RESET);
+ sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_STATUS_RESET);
+ sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_BREAK_RESET);
+
+ /* Word size */
+ switch (termios->c_cflag & CSIZE) {
+ case CS5:
+ mr1 = MR1_BITS_5;
+ break;
+ case CS6:
+ mr1 = MR1_BITS_6;
+ break;
+ case CS7:
+ mr1 = MR1_BITS_7;
+ break;
+ default:
+ case CS8:
+ mr1 = MR1_BITS_8;
+ break;
+ }
+
+ /* Parity */
+ if (termios->c_cflag & PARENB) {
+ if (termios->c_cflag & PARODD)
+ mr1 |= MR1_PAR_ODD;
+ } else
+ mr1 |= MR1_PAR_NO;
+
+ /* Stop bits */
+ mr2 = (termios->c_cflag & CSTOPB) ? MR2_STOP2 : MR2_STOP1;
+
+ /* Update desired format */
+ sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_MRPTR1);
+ sccnxp_port_write(port, SCCNXP_MR_REG, mr1);
+ sccnxp_port_write(port, SCCNXP_MR_REG, mr2);
+
+ /* Set read status mask */
+ port->read_status_mask = SR_OVR;
+ if (termios->c_iflag & INPCK)
+ port->read_status_mask |= SR_PE | SR_FE;
+ if (termios->c_iflag & (BRKINT | PARMRK))
+ port->read_status_mask |= SR_BRK;
+
+ /* Set status ignore mask */
+ port->ignore_status_mask = 0;
+ if (termios->c_iflag & IGNBRK)
+ port->ignore_status_mask |= SR_BRK;
+ if (!(termios->c_cflag & CREAD))
+ port->ignore_status_mask |= SR_PE | SR_OVR | SR_FE | SR_BRK;
+
+ /* Setup baudrate */
+ baud = uart_get_baud_rate(port, termios, old, 50,
+ (s->flags & SCCNXP_HAVE_MR0) ?
+ 230400 : 38400);
+ sccnxp_set_baud(port, baud);
+
+ /* Update timeout according to new baud rate */
+ uart_update_timeout(port, termios->c_cflag, baud);
+
+ /* Enable RX & TX */
+ sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_ENABLE | CR_TX_ENABLE);
+
+ mutex_unlock(&s->sccnxp_mutex);
+}
+
+static int sccnxp_startup(struct uart_port *port)
+{
+ struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
+ mutex_lock(&s->sccnxp_mutex);
+
+ if (s->flags & SCCNXP_HAVE_IO) {
+ /* Outputs are controlled manually */
+ sccnxp_write(port, SCCNXP_OPCR_REG, 0);
+ }
+
+ /* Reset break condition, status and FIFOs */
+ sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_RX_RESET);
+ sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_TX_RESET);
+ sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_STATUS_RESET);
+ sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_BREAK_RESET);
+
+ /* Enable RX & TX */
+ sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_ENABLE | CR_TX_ENABLE);
+
+ /* Enable RX interrupt */
+ sccnxp_enable_irq(port, IMR_RXRDY);
+
+ mutex_unlock(&s->sccnxp_mutex);
+
+ return 0;
+}
+
+static void sccnxp_shutdown(struct uart_port *port)
+{
+ struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
+ mutex_lock(&s->sccnxp_mutex);
+
+ /* Disable interrupts */
+ sccnxp_disable_irq(port, IMR_TXRDY | IMR_RXRDY);
+
+ /* Disable TX & RX */
+ sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_DISABLE | CR_TX_DISABLE);
+
+ /* Leave direction to input */
+ if (s->flags & SCCNXP_HAVE_IO)
+ sccnxp_set_bit(port, DIR_OP, 0);
+
+ mutex_unlock(&s->sccnxp_mutex);
+}
+
+static const char *sccnxp_type(struct uart_port *port)
+{
+ struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
+ return (port->type == PORT_SC26XX) ? s->name : NULL;
+}
+
+static void sccnxp_release_port(struct uart_port *port)
+{
+ /* Do nothing */
+}
+
+static int sccnxp_request_port(struct uart_port *port)
+{
+ /* Do nothing */
+ return 0;
+}
+
+static void sccnxp_config_port(struct uart_port *port, int flags)
+{
+ if (flags & UART_CONFIG_TYPE)
+ port->type = PORT_SC26XX;
+}
+
+static int sccnxp_verify_port(struct uart_port *port, struct serial_struct *s)
+{
+ if ((s->type == PORT_UNKNOWN) || (s->type == PORT_SC26XX))
+ return 0;
+ if (s->irq == port->irq)
+ return 0;
+
+ return -EINVAL;
+}
+
+static const struct uart_ops sccnxp_ops = {
+ .tx_empty = sccnxp_tx_empty,
+ .set_mctrl = sccnxp_set_mctrl,
+ .get_mctrl = sccnxp_get_mctrl,
+ .stop_tx = sccnxp_stop_tx,
+ .start_tx = sccnxp_start_tx,
+ .stop_rx = sccnxp_stop_rx,
+ .enable_ms = sccnxp_enable_ms,
+ .break_ctl = sccnxp_break_ctl,
+ .startup = sccnxp_startup,
+ .shutdown = sccnxp_shutdown,
+ .set_termios = sccnxp_set_termios,
+ .type = sccnxp_type,
+ .release_port = sccnxp_release_port,
+ .request_port = sccnxp_request_port,
+ .config_port = sccnxp_config_port,
+ .verify_port = sccnxp_verify_port,
+};
+
+#ifdef CONFIG_SERIAL_SCCNXP_CONSOLE
+static void sccnxp_console_putchar(struct uart_port *port, int c)
+{
+ int tryes = 100000;
+
+ while (tryes--) {
+ if (sccnxp_port_read(port, SCCNXP_SR_REG) & SR_TXRDY) {
+ sccnxp_port_write(port, SCCNXP_THR_REG, c);
+ break;
+ }
+ barrier();
+ }
+}
+
+static void sccnxp_console_write(struct console *co, const char *c, unsigned n)
+{
+ struct sccnxp_port *s = (struct sccnxp_port *)co->data;
+ struct uart_port *port = &s->port[co->index];
+
+ mutex_lock(&s->sccnxp_mutex);
+ uart_console_write(port, c, n, sccnxp_console_putchar);
+ mutex_unlock(&s->sccnxp_mutex);
+}
+
+static int sccnxp_console_setup(struct console *co, char *options)
+{
+ struct sccnxp_port *s = (struct sccnxp_port *)co->data;
+ struct uart_port *port = &s->port[(co->index > 0) ? co->index : 0];
+ int baud = 9600, bits = 8, parity = 'n', flow = 'n';
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+ return uart_set_options(port, co, baud, parity, bits, flow);
+}
+#endif
+
+static int __devinit sccnxp_probe(struct platform_device *pdev)
+{
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ int chiptype = pdev->id_entry->driver_data;
+ struct sccnxp_pdata *pdata = dev_get_platdata(&pdev->dev);
+ int i, ret, fifosize, freq_min, freq_max;
+ struct sccnxp_port *s;
+ void __iomem *membase;
+
+ if (!res) {
+ dev_err(&pdev->dev, "Missing memory resource data\n");
+ return -EADDRNOTAVAIL;
+ }
+
+ dev_set_name(&pdev->dev, SCCNXP_NAME);
+
+ s = devm_kzalloc(&pdev->dev, sizeof(struct sccnxp_port), GFP_KERNEL);
+ if (!s) {
+ dev_err(&pdev->dev, "Error allocating port structure\n");
+ return -ENOMEM;
+ }
+ platform_set_drvdata(pdev, s);
+
+ mutex_init(&s->sccnxp_mutex);
+
+ /* Individual chip settings */
+ switch (chiptype) {
+ case SCCNXP_TYPE_SC2681:
+ s->name = "SC2681";
+ s->uart.nr = 2;
+ s->freq_std = 3686400;
+ s->addr_mask = 0x0f;
+ s->flags = SCCNXP_HAVE_IO;
+ fifosize = 3;
+ freq_min = 1000000;
+ freq_max = 4000000;
+ break;
+ case SCCNXP_TYPE_SC2691:
+ s->name = "SC2691";
+ s->uart.nr = 1;
+ s->freq_std = 3686400;
+ s->addr_mask = 0x07;
+ s->flags = 0;
+ fifosize = 3;
+ freq_min = 1000000;
+ freq_max = 4000000;
+ break;
+ case SCCNXP_TYPE_SC2692:
+ s->name = "SC2692";
+ s->uart.nr = 2;
+ s->freq_std = 3686400;
+ s->addr_mask = 0x0f;
+ s->flags = SCCNXP_HAVE_IO;
+ fifosize = 3;
+ freq_min = 1000000;
+ freq_max = 4000000;
+ break;
+ case SCCNXP_TYPE_SC2891:
+ s->name = "SC2891";
+ s->uart.nr = 1;
+ s->freq_std = 3686400;
+ s->addr_mask = 0x0f;
+ s->flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0;
+ fifosize = 16;
+ freq_min = 100000;
+ freq_max = 8000000;
+ break;
+ case SCCNXP_TYPE_SC2892:
+ s->name = "SC2892";
+ s->uart.nr = 2;
+ s->freq_std = 3686400;
+ s->addr_mask = 0x0f;
+ s->flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0;
+ fifosize = 16;
+ freq_min = 100000;
+ freq_max = 8000000;
+ break;
+ case SCCNXP_TYPE_SC28202:
+ s->name = "SC28202";
+ s->uart.nr = 2;
+ s->freq_std = 14745600;
+ s->addr_mask = 0x7f;
+ s->flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0;
+ fifosize = 256;
+ freq_min = 1000000;
+ freq_max = 50000000;
+ break;
+ case SCCNXP_TYPE_SC68681:
+ s->name = "SC68681";
+ s->uart.nr = 2;
+ s->freq_std = 3686400;
+ s->addr_mask = 0x0f;
+ s->flags = SCCNXP_HAVE_IO;
+ fifosize = 3;
+ freq_min = 1000000;
+ freq_max = 4000000;
+ break;
+ case SCCNXP_TYPE_SC68692:
+ s->name = "SC68692";
+ s->uart.nr = 2;
+ s->freq_std = 3686400;
+ s->addr_mask = 0x0f;
+ s->flags = SCCNXP_HAVE_IO;
+ fifosize = 3;
+ freq_min = 1000000;
+ freq_max = 4000000;
+ break;
+ default:
+ dev_err(&pdev->dev, "Unsupported chip type %i\n", chiptype);
+ ret = -ENOTSUPP;
+ goto err_out;
+ }
+
+ if (!pdata) {
+ dev_warn(&pdev->dev,
+ "No platform data supplied, using defaults\n");
+ s->pdata.frequency = s->freq_std;
+ } else
+ memcpy(&s->pdata, pdata, sizeof(struct sccnxp_pdata));
+
+ s->irq = platform_get_irq(pdev, 0);
+ if (s->irq <= 0) {
+ dev_err(&pdev->dev, "Missing irq resource data\n");
+ ret = -ENXIO;
+ goto err_out;
+ }
+
+ /* Check input frequency */
+ if ((s->pdata.frequency < freq_min) ||
+ (s->pdata.frequency > freq_max)) {
+ dev_err(&pdev->dev, "Frequency out of bounds\n");
+ ret = -EINVAL;
+ goto err_out;
+ }
+
+ membase = devm_request_and_ioremap(&pdev->dev, res);
+ if (!membase) {
+ dev_err(&pdev->dev, "Failed to ioremap\n");
+ ret = -EIO;
+ goto err_out;
+ }
+
+ s->uart.owner = THIS_MODULE;
+ s->uart.dev_name = "ttySC";
+ s->uart.major = SCCNXP_MAJOR;
+ s->uart.minor = SCCNXP_MINOR;
+#ifdef CONFIG_SERIAL_SCCNXP_CONSOLE
+ s->uart.cons = &s->console;
+ s->uart.cons->device = uart_console_device;
+ s->uart.cons->write = sccnxp_console_write;
+ s->uart.cons->setup = sccnxp_console_setup;
+ s->uart.cons->flags = CON_PRINTBUFFER;
+ s->uart.cons->index = -1;
+ s->uart.cons->data = s;
+ strcpy(s->uart.cons->name, "ttySC");
+#endif
+ ret = uart_register_driver(&s->uart);
+ if (ret) {
+ dev_err(&pdev->dev, "Registering UART driver failed\n");
+ goto err_out;
+ }
+
+ for (i = 0; i < s->uart.nr; i++) {
+ s->port[i].line = i;
+ s->port[i].dev = &pdev->dev;
+ s->port[i].irq = s->irq;
+ s->port[i].type = PORT_SC26XX;
+ s->port[i].fifosize = fifosize;
+ s->port[i].flags = UPF_SKIP_TEST | UPF_FIXED_TYPE;
+ s->port[i].iotype = UPIO_MEM;
+ s->port[i].mapbase = res->start;
+ s->port[i].membase = membase;
+ s->port[i].regshift = s->pdata.reg_shift;
+ s->port[i].uartclk = s->pdata.frequency;
+ s->port[i].ops = &sccnxp_ops;
+ uart_add_one_port(&s->uart, &s->port[i]);
+ /* Set direction to input */
+ if (s->flags & SCCNXP_HAVE_IO)
+ sccnxp_set_bit(&s->port[i], DIR_OP, 0);
+ }
+
+ /* Disable interrupts */
+ s->imr = 0;
+ sccnxp_write(&s->port[0], SCCNXP_IMR_REG, 0);
+
+ /* Board specific configure */
+ if (s->pdata.init)
+ s->pdata.init();
+
+ ret = devm_request_threaded_irq(&pdev->dev, s->irq, NULL, sccnxp_ist,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ dev_name(&pdev->dev), s);
+ if (!ret)
+ return 0;
+
+ dev_err(&pdev->dev, "Unable to reguest IRQ %i\n", s->irq);
+
+err_out:
+ platform_set_drvdata(pdev, NULL);
+
+ return ret;
+}
+
+static int __devexit sccnxp_remove(struct platform_device *pdev)
+{
+ int i;
+ struct sccnxp_port *s = platform_get_drvdata(pdev);
+
+ devm_free_irq(&pdev->dev, s->irq, s);
+
+ for (i = 0; i < s->uart.nr; i++)
+ uart_remove_one_port(&s->uart, &s->port[i]);
+
+ uart_unregister_driver(&s->uart);
+ platform_set_drvdata(pdev, NULL);
+
+ if (s->pdata.exit)
+ s->pdata.exit();
+
+ return 0;
+}
+
+static const struct platform_device_id sccnxp_id_table[] = {
+ { "sc2681", SCCNXP_TYPE_SC2681 },
+ { "sc2691", SCCNXP_TYPE_SC2691 },
+ { "sc2692", SCCNXP_TYPE_SC2692 },
+ { "sc2891", SCCNXP_TYPE_SC2891 },
+ { "sc2892", SCCNXP_TYPE_SC2892 },
+ { "sc28202", SCCNXP_TYPE_SC28202 },
+ { "sc68681", SCCNXP_TYPE_SC68681 },
+ { "sc68692", SCCNXP_TYPE_SC68692 },
+};
+MODULE_DEVICE_TABLE(platform, sccnxp_id_table);
+
+static struct platform_driver sccnxp_uart_driver = {
+ .driver = {
+ .name = SCCNXP_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = sccnxp_probe,
+ .remove = __devexit_p(sccnxp_remove),
+ .id_table = sccnxp_id_table,
+};
+module_platform_driver(sccnxp_uart_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
+MODULE_DESCRIPTION("SCCNXP serial driver");
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index a21dc8e..046279c 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -159,7 +159,7 @@
retval = uport->ops->startup(uport);
if (retval == 0) {
if (uart_console(uport) && uport->cons->cflag) {
- tty->termios->c_cflag = uport->cons->cflag;
+ tty->termios.c_cflag = uport->cons->cflag;
uport->cons->cflag = 0;
}
/*
@@ -172,11 +172,11 @@
* Setup the RTS and DTR signals once the
* port is open and ready to respond.
*/
- if (tty->termios->c_cflag & CBAUD)
+ if (tty->termios.c_cflag & CBAUD)
uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR);
}
- if (port->flags & ASYNC_CTS_FLOW) {
+ if (tty_port_cts_enabled(port)) {
spin_lock_irq(&uport->lock);
if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS))
tty->hw_stopped = 1;
@@ -240,7 +240,7 @@
/*
* Turn off DTR and RTS early.
*/
- if (!tty || (tty->termios->c_cflag & HUPCL))
+ if (!tty || (tty->termios.c_cflag & HUPCL))
uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
uart_port_shutdown(port);
@@ -440,10 +440,10 @@
* If we have no tty, termios, or the port does not exist,
* then we can't set the parameters for this port.
*/
- if (!tty || !tty->termios || uport->type == PORT_UNKNOWN)
+ if (!tty || uport->type == PORT_UNKNOWN)
return;
- termios = tty->termios;
+ termios = &tty->termios;
/*
* Set flags based on termios cflag
@@ -614,7 +614,7 @@
if (I_IXOFF(tty))
uart_send_xchar(tty, STOP_CHAR(tty));
- if (tty->termios->c_cflag & CRTSCTS)
+ if (tty->termios.c_cflag & CRTSCTS)
uart_clear_mctrl(state->uart_port, TIOCM_RTS);
}
@@ -630,42 +630,48 @@
uart_send_xchar(tty, START_CHAR(tty));
}
- if (tty->termios->c_cflag & CRTSCTS)
+ if (tty->termios.c_cflag & CRTSCTS)
uart_set_mctrl(port, TIOCM_RTS);
}
-static int uart_get_info(struct uart_state *state,
- struct serial_struct __user *retinfo)
+static void uart_get_info(struct tty_port *port,
+ struct uart_state *state,
+ struct serial_struct *retinfo)
{
struct uart_port *uport = state->uart_port;
+
+ memset(retinfo, 0, sizeof(*retinfo));
+
+ retinfo->type = uport->type;
+ retinfo->line = uport->line;
+ retinfo->port = uport->iobase;
+ if (HIGH_BITS_OFFSET)
+ retinfo->port_high = (long) uport->iobase >> HIGH_BITS_OFFSET;
+ retinfo->irq = uport->irq;
+ retinfo->flags = uport->flags;
+ retinfo->xmit_fifo_size = uport->fifosize;
+ retinfo->baud_base = uport->uartclk / 16;
+ retinfo->close_delay = jiffies_to_msecs(port->close_delay) / 10;
+ retinfo->closing_wait = port->closing_wait == ASYNC_CLOSING_WAIT_NONE ?
+ ASYNC_CLOSING_WAIT_NONE :
+ jiffies_to_msecs(port->closing_wait) / 10;
+ retinfo->custom_divisor = uport->custom_divisor;
+ retinfo->hub6 = uport->hub6;
+ retinfo->io_type = uport->iotype;
+ retinfo->iomem_reg_shift = uport->regshift;
+ retinfo->iomem_base = (void *)(unsigned long)uport->mapbase;
+}
+
+static int uart_get_info_user(struct uart_state *state,
+ struct serial_struct __user *retinfo)
+{
struct tty_port *port = &state->port;
struct serial_struct tmp;
- memset(&tmp, 0, sizeof(tmp));
-
/* Ensure the state we copy is consistent and no hardware changes
occur as we go */
mutex_lock(&port->mutex);
-
- tmp.type = uport->type;
- tmp.line = uport->line;
- tmp.port = uport->iobase;
- if (HIGH_BITS_OFFSET)
- tmp.port_high = (long) uport->iobase >> HIGH_BITS_OFFSET;
- tmp.irq = uport->irq;
- tmp.flags = uport->flags;
- tmp.xmit_fifo_size = uport->fifosize;
- tmp.baud_base = uport->uartclk / 16;
- tmp.close_delay = jiffies_to_msecs(port->close_delay) / 10;
- tmp.closing_wait = port->closing_wait == ASYNC_CLOSING_WAIT_NONE ?
- ASYNC_CLOSING_WAIT_NONE :
- jiffies_to_msecs(port->closing_wait) / 10;
- tmp.custom_divisor = uport->custom_divisor;
- tmp.hub6 = uport->hub6;
- tmp.io_type = uport->iotype;
- tmp.iomem_reg_shift = uport->regshift;
- tmp.iomem_base = (void *)(unsigned long)uport->mapbase;
-
+ uart_get_info(port, state, &tmp);
mutex_unlock(&port->mutex);
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
@@ -673,42 +679,30 @@
return 0;
}
-static int uart_set_info(struct tty_struct *tty, struct uart_state *state,
- struct serial_struct __user *newinfo)
+static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
+ struct uart_state *state,
+ struct serial_struct *new_info)
{
- struct serial_struct new_serial;
struct uart_port *uport = state->uart_port;
- struct tty_port *port = &state->port;
unsigned long new_port;
unsigned int change_irq, change_port, closing_wait;
unsigned int old_custom_divisor, close_delay;
upf_t old_flags, new_flags;
int retval = 0;
- if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
- return -EFAULT;
-
- new_port = new_serial.port;
+ new_port = new_info->port;
if (HIGH_BITS_OFFSET)
- new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;
+ new_port += (unsigned long) new_info->port_high << HIGH_BITS_OFFSET;
- new_serial.irq = irq_canonicalize(new_serial.irq);
- close_delay = msecs_to_jiffies(new_serial.close_delay * 10);
- closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
+ new_info->irq = irq_canonicalize(new_info->irq);
+ close_delay = msecs_to_jiffies(new_info->close_delay * 10);
+ closing_wait = new_info->closing_wait == ASYNC_CLOSING_WAIT_NONE ?
ASYNC_CLOSING_WAIT_NONE :
- msecs_to_jiffies(new_serial.closing_wait * 10);
+ msecs_to_jiffies(new_info->closing_wait * 10);
- /*
- * This semaphore protects port->count. It is also
- * very useful to prevent opens. Also, take the
- * port configuration semaphore to make sure that a
- * module insertion/removal doesn't change anything
- * under us.
- */
- mutex_lock(&port->mutex);
change_irq = !(uport->flags & UPF_FIXED_PORT)
- && new_serial.irq != uport->irq;
+ && new_info->irq != uport->irq;
/*
* Since changing the 'type' of the port changes its resource
@@ -717,29 +711,29 @@
*/
change_port = !(uport->flags & UPF_FIXED_PORT)
&& (new_port != uport->iobase ||
- (unsigned long)new_serial.iomem_base != uport->mapbase ||
- new_serial.hub6 != uport->hub6 ||
- new_serial.io_type != uport->iotype ||
- new_serial.iomem_reg_shift != uport->regshift ||
- new_serial.type != uport->type);
+ (unsigned long)new_info->iomem_base != uport->mapbase ||
+ new_info->hub6 != uport->hub6 ||
+ new_info->io_type != uport->iotype ||
+ new_info->iomem_reg_shift != uport->regshift ||
+ new_info->type != uport->type);
old_flags = uport->flags;
- new_flags = new_serial.flags;
+ new_flags = new_info->flags;
old_custom_divisor = uport->custom_divisor;
if (!capable(CAP_SYS_ADMIN)) {
retval = -EPERM;
if (change_irq || change_port ||
- (new_serial.baud_base != uport->uartclk / 16) ||
+ (new_info->baud_base != uport->uartclk / 16) ||
(close_delay != port->close_delay) ||
(closing_wait != port->closing_wait) ||
- (new_serial.xmit_fifo_size &&
- new_serial.xmit_fifo_size != uport->fifosize) ||
+ (new_info->xmit_fifo_size &&
+ new_info->xmit_fifo_size != uport->fifosize) ||
(((new_flags ^ old_flags) & ~UPF_USR_MASK) != 0))
goto exit;
uport->flags = ((uport->flags & ~UPF_USR_MASK) |
(new_flags & UPF_USR_MASK));
- uport->custom_divisor = new_serial.custom_divisor;
+ uport->custom_divisor = new_info->custom_divisor;
goto check_and_exit;
}
@@ -747,10 +741,10 @@
* Ask the low level driver to verify the settings.
*/
if (uport->ops->verify_port)
- retval = uport->ops->verify_port(uport, &new_serial);
+ retval = uport->ops->verify_port(uport, new_info);
- if ((new_serial.irq >= nr_irqs) || (new_serial.irq < 0) ||
- (new_serial.baud_base < 9600))
+ if ((new_info->irq >= nr_irqs) || (new_info->irq < 0) ||
+ (new_info->baud_base < 9600))
retval = -EINVAL;
if (retval)
@@ -790,11 +784,11 @@
uport->ops->release_port(uport);
uport->iobase = new_port;
- uport->type = new_serial.type;
- uport->hub6 = new_serial.hub6;
- uport->iotype = new_serial.io_type;
- uport->regshift = new_serial.iomem_reg_shift;
- uport->mapbase = (unsigned long)new_serial.iomem_base;
+ uport->type = new_info->type;
+ uport->hub6 = new_info->hub6;
+ uport->iotype = new_info->io_type;
+ uport->regshift = new_info->iomem_reg_shift;
+ uport->mapbase = (unsigned long)new_info->iomem_base;
/*
* Claim and map the new regions
@@ -835,16 +829,16 @@
}
if (change_irq)
- uport->irq = new_serial.irq;
+ uport->irq = new_info->irq;
if (!(uport->flags & UPF_FIXED_PORT))
- uport->uartclk = new_serial.baud_base * 16;
+ uport->uartclk = new_info->baud_base * 16;
uport->flags = (uport->flags & ~UPF_CHANGE_MASK) |
(new_flags & UPF_CHANGE_MASK);
- uport->custom_divisor = new_serial.custom_divisor;
+ uport->custom_divisor = new_info->custom_divisor;
port->close_delay = close_delay;
port->closing_wait = closing_wait;
- if (new_serial.xmit_fifo_size)
- uport->fifosize = new_serial.xmit_fifo_size;
+ if (new_info->xmit_fifo_size)
+ uport->fifosize = new_info->xmit_fifo_size;
if (port->tty)
port->tty->low_latency =
(uport->flags & UPF_LOW_LATENCY) ? 1 : 0;
@@ -873,6 +867,28 @@
} else
retval = uart_startup(tty, state, 1);
exit:
+ return retval;
+}
+
+static int uart_set_info_user(struct tty_struct *tty, struct uart_state *state,
+ struct serial_struct __user *newinfo)
+{
+ struct serial_struct new_serial;
+ struct tty_port *port = &state->port;
+ int retval;
+
+ if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
+ return -EFAULT;
+
+ /*
+ * This semaphore protects port->count. It is also
+ * very useful to prevent opens. Also, take the
+ * port configuration semaphore to make sure that a
+ * module insertion/removal doesn't change anything
+ * under us.
+ */
+ mutex_lock(&port->mutex);
+ retval = uart_set_info(tty, port, state, &new_serial);
mutex_unlock(&port->mutex);
return retval;
}
@@ -1115,11 +1131,11 @@
*/
switch (cmd) {
case TIOCGSERIAL:
- ret = uart_get_info(state, uarg);
+ ret = uart_get_info_user(state, uarg);
break;
case TIOCSSERIAL:
- ret = uart_set_info(tty, state, uarg);
+ ret = uart_set_info_user(tty, state, uarg);
break;
case TIOCSERCONFIG:
@@ -1187,7 +1203,7 @@
struct uart_port *uport = state->uart_port;
if (uport->ops->set_ldisc)
- uport->ops->set_ldisc(uport, tty->termios->c_line);
+ uport->ops->set_ldisc(uport, tty->termios.c_line);
}
static void uart_set_termios(struct tty_struct *tty,
@@ -1195,7 +1211,7 @@
{
struct uart_state *state = tty->driver_data;
unsigned long flags;
- unsigned int cflag = tty->termios->c_cflag;
+ unsigned int cflag = tty->termios.c_cflag;
/*
@@ -1206,9 +1222,9 @@
*/
#define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
if ((cflag ^ old_termios->c_cflag) == 0 &&
- tty->termios->c_ospeed == old_termios->c_ospeed &&
- tty->termios->c_ispeed == old_termios->c_ispeed &&
- RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0) {
+ tty->termios.c_ospeed == old_termios->c_ospeed &&
+ tty->termios.c_ispeed == old_termios->c_ispeed &&
+ RELEVANT_IFLAG(tty->termios.c_iflag ^ old_termios->c_iflag) == 0) {
return;
}
@@ -1960,8 +1976,8 @@
/*
* If that's unset, use the tty termios setting.
*/
- if (port->tty && port->tty->termios && termios.c_cflag == 0)
- termios = *(port->tty->termios);
+ if (port->tty && termios.c_cflag == 0)
+ termios = port->tty->termios;
if (console_suspend_enabled)
uart_change_pm(state, 0);
@@ -2293,6 +2309,36 @@
return p->tty_driver;
}
+static ssize_t uart_get_attr_uartclk(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int ret;
+ struct tty_port *port = dev_get_drvdata(dev);
+ struct uart_state *state = container_of(port, struct uart_state, port);
+
+ mutex_lock(&state->port.mutex);
+ ret = snprintf(buf, PAGE_SIZE, "%d\n", state->uart_port->uartclk);
+ mutex_unlock(&state->port.mutex);
+
+ return ret;
+}
+
+static DEVICE_ATTR(uartclk, S_IRUSR | S_IRGRP, uart_get_attr_uartclk, NULL);
+
+static struct attribute *tty_dev_attrs[] = {
+ &dev_attr_uartclk.attr,
+ NULL,
+ };
+
+static const struct attribute_group tty_dev_attr_group = {
+ .attrs = tty_dev_attrs,
+ };
+
+static const struct attribute_group *tty_dev_attr_groups[] = {
+ &tty_dev_attr_group,
+ NULL
+ };
+
/**
* uart_add_one_port - attach a driver-defined port structure
* @drv: pointer to the uart low level driver structure for this port
@@ -2346,7 +2392,8 @@
* Register the port whether it's detected or not. This allows
* setserial to be used to alter this ports parameters.
*/
- tty_dev = tty_register_device(drv->tty_driver, uport->line, uport->dev);
+ tty_dev = tty_port_register_device_attr(port, drv->tty_driver,
+ uport->line, uport->dev, port, tty_dev_attr_groups);
if (likely(!IS_ERR(tty_dev))) {
device_set_wakeup_capable(tty_dev, 1);
} else {
@@ -2492,7 +2539,7 @@
uport->icount.cts++;
- if (port->flags & ASYNC_CTS_FLOW) {
+ if (tty_port_cts_enabled(port)) {
if (tty->hw_stopped) {
if (status) {
tty->hw_stopped = 0;
diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c
index 5b3eda2..a9e2bd1 100644
--- a/drivers/tty/serial/sirfsoc_uart.c
+++ b/drivers/tty/serial/sirfsoc_uart.c
@@ -668,7 +668,7 @@
if (res == NULL) {
dev_err(&pdev->dev, "Insufficient resources.\n");
ret = -EFAULT;
- goto irq_err;
+ goto err;
}
port->irq = res->start;
@@ -676,7 +676,7 @@
sirfport->p = pinctrl_get_select_default(&pdev->dev);
ret = IS_ERR(sirfport->p);
if (ret)
- goto pin_err;
+ goto err;
}
port->ops = &sirfsoc_uart_ops;
@@ -695,9 +695,6 @@
platform_set_drvdata(pdev, NULL);
if (sirfport->hw_flow_ctrl)
pinctrl_put(sirfport->p);
-pin_err:
-irq_err:
- devm_iounmap(&pdev->dev, port->membase);
err:
return ret;
}
@@ -709,7 +706,6 @@
platform_set_drvdata(pdev, NULL);
if (sirfport->hw_flow_ctrl)
pinctrl_put(sirfport->p);
- devm_iounmap(&pdev->dev, port->membase);
uart_remove_one_port(&sirfsoc_uart_drv, port);
return 0;
}
diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c
index 675303b..b97913d 100644
--- a/drivers/tty/serial/sunsu.c
+++ b/drivers/tty/serial/sunsu.c
@@ -58,10 +58,16 @@
enum su_type { SU_PORT_NONE, SU_PORT_MS, SU_PORT_KBD, SU_PORT_PORT };
static char *su_typev[] = { "su(???)", "su(mouse)", "su(kbd)", "su(serial)" };
+struct serial_uart_config {
+ char *name;
+ int dfl_xmit_fifo_size;
+ int flags;
+};
+
/*
* Here we define the default xmit fifo size used for each type of UART.
*/
-static const struct serial_uart_config uart_config[PORT_MAX_8250+1] = {
+static const struct serial_uart_config uart_config[] = {
{ "unknown", 1, 0 },
{ "8250", 1, 0 },
{ "16450", 1, 0 },
diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c
index 593d40a..70e3a52 100644
--- a/drivers/tty/synclink.c
+++ b/drivers/tty/synclink.c
@@ -1359,7 +1359,7 @@
}
}
- if ( (info->port.flags & ASYNC_CTS_FLOW) &&
+ if (tty_port_cts_enabled(&info->port) &&
(status & MISCSTATUS_CTS_LATCHED) ) {
if (info->port.tty->hw_stopped) {
if (status & MISCSTATUS_CTS) {
@@ -1840,22 +1840,22 @@
usc_DisableInterrupts(info,RECEIVE_DATA + RECEIVE_STATUS +
TRANSMIT_DATA + TRANSMIT_STATUS + IO_PIN + MISC );
usc_DisableDmaInterrupts(info,DICR_MASTER + DICR_TRANSMIT + DICR_RECEIVE);
-
+
/* Disable DMAEN (Port 7, Bit 14) */
/* This disconnects the DMA request signal from the ISA bus */
/* on the ISA adapter. This has no effect for the PCI adapter */
usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT15) | BIT14));
-
+
/* Disable INTEN (Port 6, Bit12) */
/* This disconnects the IRQ request signal to the ISA bus */
/* on the ISA adapter. This has no effect for the PCI adapter */
usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) | BIT12));
-
- if (!info->port.tty || info->port.tty->termios->c_cflag & HUPCL) {
+
+ if (!info->port.tty || info->port.tty->termios.c_cflag & HUPCL) {
info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
usc_set_serial_signals(info);
}
-
+
spin_unlock_irqrestore(&info->irq_spinlock,flags);
mgsl_release_resources(info);
@@ -1895,7 +1895,7 @@
usc_EnableInterrupts(info, IO_PIN);
usc_get_serial_signals(info);
- if (info->netcount || info->port.tty->termios->c_cflag & CREAD)
+ if (info->netcount || info->port.tty->termios.c_cflag & CREAD)
usc_start_receiver(info);
spin_unlock_irqrestore(&info->irq_spinlock,flags);
@@ -1908,14 +1908,14 @@
unsigned cflag;
int bits_per_char;
- if (!info->port.tty || !info->port.tty->termios)
+ if (!info->port.tty)
return;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgsl_change_params(%s)\n",
__FILE__,__LINE__, info->device_name );
- cflag = info->port.tty->termios->c_cflag;
+ cflag = info->port.tty->termios.c_cflag;
/* if B0 rate (hangup) specified then negate DTR and RTS */
/* otherwise assert DTR and RTS */
@@ -2367,8 +2367,8 @@
if (I_IXOFF(tty))
mgsl_send_xchar(tty, STOP_CHAR(tty));
-
- if (tty->termios->c_cflag & CRTSCTS) {
+
+ if (tty->termios.c_cflag & CRTSCTS) {
spin_lock_irqsave(&info->irq_spinlock,flags);
info->serial_signals &= ~SerialSignal_RTS;
usc_set_serial_signals(info);
@@ -2401,8 +2401,8 @@
else
mgsl_send_xchar(tty, START_CHAR(tty));
}
-
- if (tty->termios->c_cflag & CRTSCTS) {
+
+ if (tty->termios.c_cflag & CRTSCTS) {
spin_lock_irqsave(&info->irq_spinlock,flags);
info->serial_signals |= SerialSignal_RTS;
usc_set_serial_signals(info);
@@ -3045,7 +3045,7 @@
/* Handle transition to B0 status */
if (old_termios->c_cflag & CBAUD &&
- !(tty->termios->c_cflag & CBAUD)) {
+ !(tty->termios.c_cflag & CBAUD)) {
info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
spin_lock_irqsave(&info->irq_spinlock,flags);
usc_set_serial_signals(info);
@@ -3054,9 +3054,9 @@
/* Handle transition away from B0 status */
if (!(old_termios->c_cflag & CBAUD) &&
- tty->termios->c_cflag & CBAUD) {
+ tty->termios.c_cflag & CBAUD) {
info->serial_signals |= SerialSignal_DTR;
- if (!(tty->termios->c_cflag & CRTSCTS) ||
+ if (!(tty->termios.c_cflag & CRTSCTS) ||
!test_bit(TTY_THROTTLED, &tty->flags)) {
info->serial_signals |= SerialSignal_RTS;
}
@@ -3067,7 +3067,7 @@
/* Handle turning off CRTSCTS */
if (old_termios->c_cflag & CRTSCTS &&
- !(tty->termios->c_cflag & CRTSCTS)) {
+ !(tty->termios.c_cflag & CRTSCTS)) {
tty->hw_stopped = 0;
mgsl_start(tty);
}
@@ -3287,7 +3287,7 @@
return 0;
}
- if (tty->termios->c_cflag & CLOCAL)
+ if (tty->termios.c_cflag & CLOCAL)
do_clocal = true;
/* Wait for carrier detect and the line to become
@@ -3313,7 +3313,7 @@
port->blocked_open++;
while (1) {
- if (tty->termios->c_cflag & CBAUD)
+ if (tty->termios.c_cflag & CBAUD)
tty_port_raise_dtr_rts(port);
set_current_state(TASK_INTERRUPTIBLE);
@@ -3338,9 +3338,9 @@
printk("%s(%d):block_til_ready blocking on %s count=%d\n",
__FILE__,__LINE__, tty->driver->name, port->count );
- tty_unlock();
+ tty_unlock(tty);
schedule();
- tty_lock();
+ tty_lock(tty);
}
set_current_state(TASK_RUNNING);
@@ -3362,6 +3362,29 @@
} /* end of block_til_ready() */
+static int mgsl_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+ struct mgsl_struct *info;
+ int line = tty->index;
+
+ /* verify range of specified line number */
+ if (line >= mgsl_device_count) {
+ printk("%s(%d):mgsl_open with invalid line #%d.\n",
+ __FILE__, __LINE__, line);
+ return -ENODEV;
+ }
+
+ /* find the info structure for the specified line */
+ info = mgsl_device_list;
+ while (info && info->line != line)
+ info = info->next_device;
+ if (mgsl_paranoia_check(info, tty->name, "mgsl_open"))
+ return -ENODEV;
+ tty->driver_data = info;
+
+ return tty_port_install(&info->port, driver, tty);
+}
+
/* mgsl_open()
*
* Called when a port is opened. Init and enable port.
@@ -3374,26 +3397,10 @@
*/
static int mgsl_open(struct tty_struct *tty, struct file * filp)
{
- struct mgsl_struct *info;
- int retval, line;
+ struct mgsl_struct *info = tty->driver_data;
unsigned long flags;
+ int retval;
- /* verify range of specified line number */
- line = tty->index;
- if (line >= mgsl_device_count) {
- printk("%s(%d):mgsl_open with invalid line #%d.\n",
- __FILE__,__LINE__,line);
- return -ENODEV;
- }
-
- /* find the info structure for the specified line */
- info = mgsl_device_list;
- while(info && info->line != line)
- info = info->next_device;
- if (mgsl_paranoia_check(info, tty->name, "mgsl_open"))
- return -ENODEV;
-
- tty->driver_data = info;
info->port.tty = tty;
if (debug_level >= DEBUG_LEVEL_INFO)
@@ -4297,6 +4304,7 @@
} /* end of mgsl_allocate_device()*/
static const struct tty_operations mgsl_ops = {
+ .install = mgsl_install,
.open = mgsl_open,
.close = mgsl_close,
.write = mgsl_write,
diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c
index aa1debf..b38e954 100644
--- a/drivers/tty/synclink_gt.c
+++ b/drivers/tty/synclink_gt.c
@@ -785,7 +785,7 @@
/* Handle transition to B0 status */
if (old_termios->c_cflag & CBAUD &&
- !(tty->termios->c_cflag & CBAUD)) {
+ !(tty->termios.c_cflag & CBAUD)) {
info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
spin_lock_irqsave(&info->lock,flags);
set_signals(info);
@@ -794,9 +794,9 @@
/* Handle transition away from B0 status */
if (!(old_termios->c_cflag & CBAUD) &&
- tty->termios->c_cflag & CBAUD) {
+ tty->termios.c_cflag & CBAUD) {
info->signals |= SerialSignal_DTR;
- if (!(tty->termios->c_cflag & CRTSCTS) ||
+ if (!(tty->termios.c_cflag & CRTSCTS) ||
!test_bit(TTY_THROTTLED, &tty->flags)) {
info->signals |= SerialSignal_RTS;
}
@@ -807,7 +807,7 @@
/* Handle turning off CRTSCTS */
if (old_termios->c_cflag & CRTSCTS &&
- !(tty->termios->c_cflag & CRTSCTS)) {
+ !(tty->termios.c_cflag & CRTSCTS)) {
tty->hw_stopped = 0;
tx_release(tty);
}
@@ -1372,7 +1372,7 @@
DBGINFO(("%s throttle\n", info->device_name));
if (I_IXOFF(tty))
send_xchar(tty, STOP_CHAR(tty));
- if (tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios.c_cflag & CRTSCTS) {
spin_lock_irqsave(&info->lock,flags);
info->signals &= ~SerialSignal_RTS;
set_signals(info);
@@ -1397,7 +1397,7 @@
else
send_xchar(tty, START_CHAR(tty));
}
- if (tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios.c_cflag & CRTSCTS) {
spin_lock_irqsave(&info->lock,flags);
info->signals |= SerialSignal_RTS;
set_signals(info);
@@ -2053,7 +2053,7 @@
wake_up_interruptible(&info->event_wait_q);
info->pending_bh |= BH_STATUS;
- if (info->port.flags & ASYNC_CTS_FLOW) {
+ if (tty_port_cts_enabled(&info->port)) {
if (info->port.tty) {
if (info->port.tty->hw_stopped) {
if (info->signals & SerialSignal_CTS) {
@@ -2493,7 +2493,7 @@
slgt_irq_off(info, IRQ_ALL | IRQ_MASTER);
- if (!info->port.tty || info->port.tty->termios->c_cflag & HUPCL) {
+ if (!info->port.tty || info->port.tty->termios.c_cflag & HUPCL) {
info->signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
set_signals(info);
}
@@ -2534,7 +2534,7 @@
get_signals(info);
if (info->netcount ||
- (info->port.tty && info->port.tty->termios->c_cflag & CREAD))
+ (info->port.tty && info->port.tty->termios.c_cflag & CREAD))
rx_start(info);
spin_unlock_irqrestore(&info->lock,flags);
@@ -2548,11 +2548,11 @@
unsigned cflag;
int bits_per_char;
- if (!info->port.tty || !info->port.tty->termios)
+ if (!info->port.tty)
return;
DBGINFO(("%s change_params\n", info->device_name));
- cflag = info->port.tty->termios->c_cflag;
+ cflag = info->port.tty->termios.c_cflag;
/* if B0 rate (hangup) specified then negate DTR and RTS */
/* otherwise assert DTR and RTS */
@@ -3292,7 +3292,7 @@
return 0;
}
- if (tty->termios->c_cflag & CLOCAL)
+ if (tty->termios.c_cflag & CLOCAL)
do_clocal = true;
/* Wait for carrier detect and the line to become
@@ -3314,7 +3314,7 @@
port->blocked_open++;
while (1) {
- if ((tty->termios->c_cflag & CBAUD))
+ if ((tty->termios.c_cflag & CBAUD))
tty_port_raise_dtr_rts(port);
set_current_state(TASK_INTERRUPTIBLE);
@@ -3336,9 +3336,9 @@
}
DBGINFO(("%s block_til_ready wait\n", tty->driver->name));
- tty_unlock();
+ tty_unlock(tty);
schedule();
- tty_lock();
+ tty_lock(tty);
}
set_current_state(TASK_RUNNING);
@@ -3689,8 +3689,11 @@
}
}
- for (i=0; i < port_count; ++i)
- tty_register_device(serial_driver, port_array[i]->line, &(port_array[i]->pdev->dev));
+ for (i = 0; i < port_count; ++i) {
+ struct slgt_info *info = port_array[i];
+ tty_port_register_device(&info->port, serial_driver, info->line,
+ &info->pdev->dev);
+ }
}
static int __devinit init_one(struct pci_dev *dev,
diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c
index a3dddc1..f17d9f3 100644
--- a/drivers/tty/synclinkmp.c
+++ b/drivers/tty/synclinkmp.c
@@ -711,15 +711,11 @@
/* tty callbacks */
-/* Called when a port is opened. Init and enable port.
- */
-static int open(struct tty_struct *tty, struct file *filp)
+static int install(struct tty_driver *driver, struct tty_struct *tty)
{
SLMP_INFO *info;
- int retval, line;
- unsigned long flags;
+ int line = tty->index;
- line = tty->index;
if (line >= synclinkmp_device_count) {
printk("%s(%d): open with invalid line #%d.\n",
__FILE__,__LINE__,line);
@@ -727,17 +723,30 @@
}
info = synclinkmp_device_list;
- while(info && info->line != line)
+ while (info && info->line != line)
info = info->next_device;
if (sanity_check(info, tty->name, "open"))
return -ENODEV;
- if ( info->init_error ) {
+ if (info->init_error) {
printk("%s(%d):%s device is not allocated, init error=%d\n",
- __FILE__,__LINE__,info->device_name,info->init_error);
+ __FILE__, __LINE__, info->device_name,
+ info->init_error);
return -ENODEV;
}
tty->driver_data = info;
+
+ return tty_port_install(&info->port, driver, tty);
+}
+
+/* Called when a port is opened. Init and enable port.
+ */
+static int open(struct tty_struct *tty, struct file *filp)
+{
+ SLMP_INFO *info = tty->driver_data;
+ unsigned long flags;
+ int retval;
+
info->port.tty = tty;
if (debug_level >= DEBUG_LEVEL_INFO)
@@ -873,7 +882,7 @@
/* Handle transition to B0 status */
if (old_termios->c_cflag & CBAUD &&
- !(tty->termios->c_cflag & CBAUD)) {
+ !(tty->termios.c_cflag & CBAUD)) {
info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
spin_lock_irqsave(&info->lock,flags);
set_signals(info);
@@ -882,9 +891,9 @@
/* Handle transition away from B0 status */
if (!(old_termios->c_cflag & CBAUD) &&
- tty->termios->c_cflag & CBAUD) {
+ tty->termios.c_cflag & CBAUD) {
info->serial_signals |= SerialSignal_DTR;
- if (!(tty->termios->c_cflag & CRTSCTS) ||
+ if (!(tty->termios.c_cflag & CRTSCTS) ||
!test_bit(TTY_THROTTLED, &tty->flags)) {
info->serial_signals |= SerialSignal_RTS;
}
@@ -895,7 +904,7 @@
/* Handle turning off CRTSCTS */
if (old_termios->c_cflag & CRTSCTS &&
- !(tty->termios->c_cflag & CRTSCTS)) {
+ !(tty->termios.c_cflag & CRTSCTS)) {
tty->hw_stopped = 0;
tx_release(tty);
}
@@ -1473,7 +1482,7 @@
if (I_IXOFF(tty))
send_xchar(tty, STOP_CHAR(tty));
- if (tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios.c_cflag & CRTSCTS) {
spin_lock_irqsave(&info->lock,flags);
info->serial_signals &= ~SerialSignal_RTS;
set_signals(info);
@@ -1502,7 +1511,7 @@
send_xchar(tty, START_CHAR(tty));
}
- if (tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios.c_cflag & CRTSCTS) {
spin_lock_irqsave(&info->lock,flags);
info->serial_signals |= SerialSignal_RTS;
set_signals(info);
@@ -2491,7 +2500,7 @@
}
}
- if ( (info->port.flags & ASYNC_CTS_FLOW) &&
+ if (tty_port_cts_enabled(&info->port) &&
(status & MISCSTATUS_CTS_LATCHED) ) {
if ( info->port.tty ) {
if (info->port.tty->hw_stopped) {
@@ -2708,7 +2717,7 @@
reset_port(info);
- if (!info->port.tty || info->port.tty->termios->c_cflag & HUPCL) {
+ if (!info->port.tty || info->port.tty->termios.c_cflag & HUPCL) {
info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
set_signals(info);
}
@@ -2749,7 +2758,7 @@
get_signals(info);
- if (info->netcount || (info->port.tty && info->port.tty->termios->c_cflag & CREAD) )
+ if (info->netcount || (info->port.tty && info->port.tty->termios.c_cflag & CREAD) )
rx_start(info);
spin_unlock_irqrestore(&info->lock,flags);
@@ -2762,14 +2771,14 @@
unsigned cflag;
int bits_per_char;
- if (!info->port.tty || !info->port.tty->termios)
+ if (!info->port.tty)
return;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):%s change_params()\n",
__FILE__,__LINE__, info->device_name );
- cflag = info->port.tty->termios->c_cflag;
+ cflag = info->port.tty->termios.c_cflag;
/* if B0 rate (hangup) specified then negate DTR and RTS */
/* otherwise assert DTR and RTS */
@@ -3306,7 +3315,7 @@
return 0;
}
- if (tty->termios->c_cflag & CLOCAL)
+ if (tty->termios.c_cflag & CLOCAL)
do_clocal = true;
/* Wait for carrier detect and the line to become
@@ -3332,7 +3341,7 @@
port->blocked_open++;
while (1) {
- if (tty->termios->c_cflag & CBAUD)
+ if (tty->termios.c_cflag & CBAUD)
tty_port_raise_dtr_rts(port);
set_current_state(TASK_INTERRUPTIBLE);
@@ -3357,9 +3366,9 @@
printk("%s(%d):%s block_til_ready() count=%d\n",
__FILE__,__LINE__, tty->driver->name, port->count );
- tty_unlock();
+ tty_unlock(tty);
schedule();
- tty_lock();
+ tty_lock(tty);
}
set_current_state(TASK_RUNNING);
@@ -3881,6 +3890,7 @@
}
static const struct tty_operations ops = {
+ .install = install,
.open = open,
.close = close,
.write = write,
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index b425c79..8a5a8b0 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -181,10 +181,13 @@
void free_tty_struct(struct tty_struct *tty)
{
+ if (!tty)
+ return;
if (tty->dev)
put_device(tty->dev);
kfree(tty->write_buf);
tty_buffer_free_all(tty);
+ tty->magic = 0xDEADDEAD;
kfree(tty);
}
@@ -573,7 +576,7 @@
}
spin_unlock(&redirect_lock);
- tty_lock();
+ tty_lock(tty);
/* some functions below drop BTM, so we need this bit */
set_bit(TTY_HUPPING, &tty->flags);
@@ -666,7 +669,7 @@
clear_bit(TTY_HUPPING, &tty->flags);
tty_ldisc_enable(tty);
- tty_unlock();
+ tty_unlock(tty);
if (f)
fput(f);
@@ -1103,12 +1106,12 @@
{
if (tty) {
mutex_lock(&tty->atomic_write_lock);
- tty_lock();
+ tty_lock(tty);
if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) {
- tty_unlock();
+ tty_unlock(tty);
tty->ops->write(tty, msg, strlen(msg));
} else
- tty_unlock();
+ tty_unlock(tty);
tty_write_unlock(tty);
}
return;
@@ -1213,7 +1216,10 @@
*/
static void tty_line_name(struct tty_driver *driver, int index, char *p)
{
- sprintf(p, "%s%d", driver->name, index + driver->name_base);
+ if (driver->flags & TTY_DRIVER_UNNUMBERED_NODE)
+ strcpy(p, driver->name);
+ else
+ sprintf(p, "%s%d", driver->name, index + driver->name_base);
}
/**
@@ -1249,21 +1255,19 @@
struct ktermios *tp;
int idx = tty->index;
- tp = tty->driver->termios[idx];
- if (tp == NULL) {
- tp = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
- if (tp == NULL)
- return -ENOMEM;
- memcpy(tp, &tty->driver->init_termios,
- sizeof(struct ktermios));
- tty->driver->termios[idx] = tp;
+ if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS)
+ tty->termios = tty->driver->init_termios;
+ else {
+ /* Check for lazy saved data */
+ tp = tty->driver->termios[idx];
+ if (tp != NULL)
+ tty->termios = *tp;
+ else
+ tty->termios = tty->driver->init_termios;
}
- tty->termios = tp;
- tty->termios_locked = tp + 1;
-
/* 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);
+ tty->termios.c_ispeed = tty_termios_input_baud_rate(&tty->termios);
+ tty->termios.c_ospeed = tty_termios_baud_rate(&tty->termios);
return 0;
}
EXPORT_SYMBOL_GPL(tty_init_termios);
@@ -1403,10 +1407,18 @@
}
initialize_tty_struct(tty, driver, idx);
+ tty_lock(tty);
retval = tty_driver_install_tty(driver, tty);
if (retval < 0)
goto err_deinit_tty;
+ if (!tty->port)
+ tty->port = driver->ports[idx];
+
+ WARN_RATELIMIT(!tty->port,
+ "%s: %s driver does not set tty->port. This will crash the kernel later. Fix the driver!\n",
+ __func__, tty->driver->name);
+
/*
* Structures all installed ... call the ldisc open routines.
* If we fail here just call release_tty to clean up. No need
@@ -1415,9 +1427,11 @@
retval = tty_ldisc_setup(tty, tty->link);
if (retval)
goto err_release_tty;
+ /* Return the tty locked so that it cannot vanish under the caller */
return tty;
err_deinit_tty:
+ tty_unlock(tty);
deinitialize_tty_struct(tty);
free_tty_struct(tty);
err_module_put:
@@ -1426,6 +1440,7 @@
/* call the tty release_tty routine to clean out this slot */
err_release_tty:
+ tty_unlock(tty);
printk_ratelimited(KERN_INFO "tty_init_dev: ldisc open failed, "
"clearing slot %d\n", idx);
release_tty(tty, idx);
@@ -1436,22 +1451,25 @@
{
struct ktermios *tp;
int idx = tty->index;
- /* Kill this flag and push into drivers for locking etc */
- if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
- /* FIXME: Locking on ->termios array */
- tp = tty->termios;
- tty->driver->termios[idx] = NULL;
- kfree(tp);
+
+ /* If the port is going to reset then it has no termios to save */
+ if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS)
+ return;
+
+ /* Stash the termios data */
+ tp = tty->driver->termios[idx];
+ if (tp == NULL) {
+ tp = kmalloc(sizeof(struct ktermios), GFP_KERNEL);
+ if (tp == NULL) {
+ pr_warn("tty: no memory to save termios state.\n");
+ return;
+ }
+ tty->driver->termios[idx] = tp;
}
+ *tp = tty->termios;
}
EXPORT_SYMBOL(tty_free_termios);
-void tty_shutdown(struct tty_struct *tty)
-{
- tty_driver_remove_tty(tty->driver, tty);
- tty_free_termios(tty);
-}
-EXPORT_SYMBOL(tty_shutdown);
/**
* release_one_tty - release tty structure memory
@@ -1462,7 +1480,6 @@
* in use. It also gets called when setup of a device fails.
*
* Locking:
- * tty_mutex - sometimes only
* takes the file list lock internally when working on the list
* of ttys that the driver keeps.
*
@@ -1495,11 +1512,6 @@
{
struct tty_struct *tty = container_of(kref, struct tty_struct, kref);
- if (tty->ops->shutdown)
- tty->ops->shutdown(tty);
- else
- tty_shutdown(tty);
-
/* The hangup queue is now free so we can reuse it rather than
waste a chunk of memory for each port */
INIT_WORK(&tty->hangup_work, release_one_tty);
@@ -1528,16 +1540,20 @@
* and decrement the refcount of the backing module.
*
* Locking:
- * tty_mutex - sometimes only
+ * tty_mutex
* takes the file list lock internally when working on the list
* of ttys that the driver keeps.
- * FIXME: should we require tty_mutex is held here ??
*
*/
static void release_tty(struct tty_struct *tty, int idx)
{
/* This should always be true but check for the moment */
WARN_ON(tty->index != idx);
+ WARN_ON(!mutex_is_locked(&tty_mutex));
+ if (tty->ops->shutdown)
+ tty->ops->shutdown(tty);
+ tty_free_termios(tty);
+ tty_driver_remove_tty(tty->driver, tty);
if (tty->link)
tty_kref_put(tty->link);
@@ -1572,22 +1588,12 @@
__func__, idx, tty->name);
return -1;
}
- if (tty->termios != tty->driver->termios[idx]) {
- printk(KERN_DEBUG "%s: driver.termios[%d] not termios for (%s)\n",
- __func__, idx, tty->name);
- return -1;
- }
if (tty->driver->other) {
if (o_tty != tty->driver->other->ttys[idx]) {
printk(KERN_DEBUG "%s: other->table[%d] not o_tty for (%s)\n",
__func__, idx, tty->name);
return -1;
}
- if (o_tty->termios != tty->driver->other->termios[idx]) {
- printk(KERN_DEBUG "%s: other->termios[%d] not o_termios for (%s)\n",
- __func__, idx, tty->name);
- return -1;
- }
if (o_tty->link != tty) {
printk(KERN_DEBUG "%s: bad pty pointers\n", __func__);
return -1;
@@ -1628,7 +1634,7 @@
if (tty_paranoia_check(tty, inode, __func__))
return 0;
- tty_lock();
+ tty_lock(tty);
check_tty_count(tty, __func__);
__tty_fasync(-1, filp, 0);
@@ -1637,10 +1643,11 @@
pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
tty->driver->subtype == PTY_TYPE_MASTER);
devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0;
+ /* Review: parallel close */
o_tty = tty->link;
if (tty_release_checks(tty, o_tty, idx)) {
- tty_unlock();
+ tty_unlock(tty);
return 0;
}
@@ -1652,7 +1659,7 @@
if (tty->ops->close)
tty->ops->close(tty, filp);
- tty_unlock();
+ tty_unlock(tty);
/*
* Sanity check: if tty->count is going to zero, there shouldn't be
* any waiters on tty->read_wait or tty->write_wait. We test the
@@ -1675,7 +1682,7 @@
opens on /dev/tty */
mutex_lock(&tty_mutex);
- tty_lock();
+ tty_lock_pair(tty, o_tty);
tty_closing = tty->count <= 1;
o_tty_closing = o_tty &&
(o_tty->count <= (pty_master ? 1 : 0));
@@ -1706,7 +1713,7 @@
printk(KERN_WARNING "%s: %s: read/write wait queue active!\n",
__func__, tty_name(tty, buf));
- tty_unlock();
+ tty_unlock_pair(tty, o_tty);
mutex_unlock(&tty_mutex);
schedule();
}
@@ -1715,6 +1722,9 @@
* The closing flags are now consistent with the open counts on
* both sides, and we've completed the last operation that could
* block, so it's safe to proceed with closing.
+ *
+ * We must *not* drop the tty_mutex until we ensure that a further
+ * entry into tty_open can not pick up this tty.
*/
if (pty_master) {
if (--o_tty->count < 0) {
@@ -1766,12 +1776,13 @@
}
mutex_unlock(&tty_mutex);
+ tty_unlock_pair(tty, o_tty);
+ /* At this point the TTY_CLOSING flag should ensure a dead tty
+ cannot be re-opened by a racing opener */
/* check whether both sides are closing ... */
- if (!tty_closing || (o_tty && !o_tty_closing)) {
- tty_unlock();
+ if (!tty_closing || (o_tty && !o_tty_closing))
return 0;
- }
#ifdef TTY_DEBUG_HANGUP
printk(KERN_DEBUG "%s: freeing tty structure...\n", __func__);
@@ -1782,14 +1793,17 @@
tty_ldisc_release(tty, o_tty);
/*
* The release_tty function takes care of the details of clearing
- * the slots and preserving the termios structure.
+ * the slots and preserving the termios structure. The tty_unlock_pair
+ * should be safe as we keep a kref while the tty is locked (so the
+ * unlock never unlocks a freed tty).
*/
+ mutex_lock(&tty_mutex);
release_tty(tty, idx);
+ mutex_unlock(&tty_mutex);
/* Make this pty number available for reallocation */
if (devpts)
devpts_kill_index(inode, idx);
- tty_unlock();
return 0;
}
@@ -1893,6 +1907,9 @@
* Locking: tty_mutex protects tty, tty_lookup_driver and tty_init_dev.
* tty->count should protect the rest.
* ->siglock protects ->signal/->sighand
+ *
+ * Note: the tty_unlock/lock cases without a ref are only safe due to
+ * tty_mutex
*/
static int tty_open(struct inode *inode, struct file *filp)
@@ -1916,8 +1933,7 @@
retval = 0;
mutex_lock(&tty_mutex);
- tty_lock();
-
+ /* This is protected by the tty_mutex */
tty = tty_open_current_tty(device, filp);
if (IS_ERR(tty)) {
retval = PTR_ERR(tty);
@@ -1938,17 +1954,19 @@
}
if (tty) {
+ tty_lock(tty);
retval = tty_reopen(tty);
- if (retval)
+ if (retval < 0) {
+ tty_unlock(tty);
tty = ERR_PTR(retval);
- } else
+ }
+ } else /* Returns with the tty_lock held for now */
tty = tty_init_dev(driver, index);
mutex_unlock(&tty_mutex);
if (driver)
tty_driver_kref_put(driver);
if (IS_ERR(tty)) {
- tty_unlock();
retval = PTR_ERR(tty);
goto err_file;
}
@@ -1977,7 +1995,7 @@
printk(KERN_DEBUG "%s: error %d in opening %s...\n", __func__,
retval, tty->name);
#endif
- tty_unlock(); /* need to call tty_release without BTM */
+ tty_unlock(tty); /* need to call tty_release without BTM */
tty_release(inode, filp);
if (retval != -ERESTARTSYS)
return retval;
@@ -1989,17 +2007,15 @@
/*
* Need to reset f_op in case a hangup happened.
*/
- tty_lock();
if (filp->f_op == &hung_up_tty_fops)
filp->f_op = &tty_fops;
- tty_unlock();
goto retry_open;
}
- tty_unlock();
+ tty_unlock(tty);
mutex_lock(&tty_mutex);
- tty_lock();
+ tty_lock(tty);
spin_lock_irq(¤t->sighand->siglock);
if (!noctty &&
current->signal->leader &&
@@ -2007,11 +2023,10 @@
tty->session == NULL)
__proc_set_tty(current, tty);
spin_unlock_irq(¤t->sighand->siglock);
- tty_unlock();
+ tty_unlock(tty);
mutex_unlock(&tty_mutex);
return 0;
err_unlock:
- tty_unlock();
mutex_unlock(&tty_mutex);
/* after locks to avoid deadlock */
if (!IS_ERR_OR_NULL(driver))
@@ -2094,10 +2109,13 @@
static int tty_fasync(int fd, struct file *filp, int on)
{
+ struct tty_struct *tty = file_tty(filp);
int retval;
- tty_lock();
+
+ tty_lock(tty);
retval = __tty_fasync(fd, filp, on);
- tty_unlock();
+ tty_unlock(tty);
+
return retval;
}
@@ -2756,7 +2774,7 @@
if (ld->ops->ioctl) {
retval = ld->ops->ioctl(tty, file, cmd, arg);
if (retval == -ENOIOCTLCMD)
- retval = -EINVAL;
+ retval = -ENOTTY;
}
tty_ldisc_deref(ld);
return retval;
@@ -2934,6 +2952,7 @@
tty->pgrp = NULL;
tty->overrun_time = jiffies;
tty_buffer_init(tty);
+ mutex_init(&tty->legacy_mutex);
mutex_init(&tty->termios_mutex);
mutex_init(&tty->ldisc_mutex);
init_waitqueue_head(&tty->write_wait);
@@ -2991,6 +3010,15 @@
struct class *tty_class;
+static int tty_cdev_add(struct tty_driver *driver, dev_t dev,
+ unsigned int index, unsigned int count)
+{
+ /* init here, since reused cdevs cause crashes */
+ cdev_init(&driver->cdevs[index], &tty_fops);
+ driver->cdevs[index].owner = driver->owner;
+ return cdev_add(&driver->cdevs[index], dev, count);
+}
+
/**
* tty_register_device - register a tty device
* @driver: the tty driver that describes the tty device
@@ -3013,8 +3041,46 @@
struct device *tty_register_device(struct tty_driver *driver, unsigned index,
struct device *device)
{
+ return tty_register_device_attr(driver, index, device, NULL, NULL);
+}
+EXPORT_SYMBOL(tty_register_device);
+
+static void tty_device_create_release(struct device *dev)
+{
+ pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
+ kfree(dev);
+}
+
+/**
+ * tty_register_device_attr - register a tty device
+ * @driver: the tty driver that describes the tty device
+ * @index: the index in the tty driver for this tty device
+ * @device: a struct device that is associated with this tty device.
+ * This field is optional, if there is no known struct device
+ * for this tty device it can be set to NULL safely.
+ * @drvdata: Driver data to be set to device.
+ * @attr_grp: Attribute group to be set on device.
+ *
+ * Returns a pointer to the struct device for this tty device
+ * (or ERR_PTR(-EFOO) on error).
+ *
+ * This call is required to be made to register an individual tty device
+ * if the tty driver's flags have the TTY_DRIVER_DYNAMIC_DEV bit set. If
+ * that bit is not set, this function should not be called by a tty
+ * driver.
+ *
+ * Locking: ??
+ */
+struct device *tty_register_device_attr(struct tty_driver *driver,
+ unsigned index, struct device *device,
+ void *drvdata,
+ const struct attribute_group **attr_grp)
+{
char name[64];
- dev_t dev = MKDEV(driver->major, driver->minor_start) + index;
+ dev_t devt = MKDEV(driver->major, driver->minor_start) + index;
+ struct device *dev = NULL;
+ int retval = -ENODEV;
+ bool cdev = false;
if (index >= driver->num) {
printk(KERN_ERR "Attempt to register invalid tty line number "
@@ -3027,9 +3093,40 @@
else
tty_line_name(driver, index, name);
- return device_create(tty_class, device, dev, NULL, name);
+ if (!(driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)) {
+ retval = tty_cdev_add(driver, devt, index, 1);
+ if (retval)
+ goto error;
+ cdev = true;
+ }
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev) {
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ dev->devt = devt;
+ dev->class = tty_class;
+ dev->parent = device;
+ dev->release = tty_device_create_release;
+ dev_set_name(dev, "%s", name);
+ dev->groups = attr_grp;
+ dev_set_drvdata(dev, drvdata);
+
+ retval = device_register(dev);
+ if (retval)
+ goto error;
+
+ return dev;
+
+error:
+ put_device(dev);
+ if (cdev)
+ cdev_del(&driver->cdevs[index]);
+ return ERR_PTR(retval);
}
-EXPORT_SYMBOL(tty_register_device);
+EXPORT_SYMBOL_GPL(tty_register_device_attr);
/**
* tty_unregister_device - unregister a tty device
@@ -3046,31 +3143,82 @@
{
device_destroy(tty_class,
MKDEV(driver->major, driver->minor_start) + index);
+ if (!(driver->flags & TTY_DRIVER_DYNAMIC_ALLOC))
+ cdev_del(&driver->cdevs[index]);
}
EXPORT_SYMBOL(tty_unregister_device);
-struct tty_driver *__alloc_tty_driver(int lines, struct module *owner)
+/**
+ * __tty_alloc_driver -- allocate tty driver
+ * @lines: count of lines this driver can handle at most
+ * @owner: module which is repsonsible for this driver
+ * @flags: some of TTY_DRIVER_* flags, will be set in driver->flags
+ *
+ * This should not be called directly, some of the provided macros should be
+ * used instead. Use IS_ERR and friends on @retval.
+ */
+struct tty_driver *__tty_alloc_driver(unsigned int lines, struct module *owner,
+ unsigned long flags)
{
struct tty_driver *driver;
+ unsigned int cdevs = 1;
+ int err;
+
+ if (!lines || (flags & TTY_DRIVER_UNNUMBERED_NODE && lines > 1))
+ return ERR_PTR(-EINVAL);
driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL);
- if (driver) {
- kref_init(&driver->kref);
- driver->magic = TTY_DRIVER_MAGIC;
- driver->num = lines;
- driver->owner = owner;
- /* later we'll move allocation of tables here */
+ if (!driver)
+ return ERR_PTR(-ENOMEM);
+
+ kref_init(&driver->kref);
+ driver->magic = TTY_DRIVER_MAGIC;
+ driver->num = lines;
+ driver->owner = owner;
+ driver->flags = flags;
+
+ if (!(flags & TTY_DRIVER_DEVPTS_MEM)) {
+ driver->ttys = kcalloc(lines, sizeof(*driver->ttys),
+ GFP_KERNEL);
+ driver->termios = kcalloc(lines, sizeof(*driver->termios),
+ GFP_KERNEL);
+ if (!driver->ttys || !driver->termios) {
+ err = -ENOMEM;
+ goto err_free_all;
+ }
}
+
+ if (!(flags & TTY_DRIVER_DYNAMIC_ALLOC)) {
+ driver->ports = kcalloc(lines, sizeof(*driver->ports),
+ GFP_KERNEL);
+ if (!driver->ports) {
+ err = -ENOMEM;
+ goto err_free_all;
+ }
+ cdevs = lines;
+ }
+
+ driver->cdevs = kcalloc(cdevs, sizeof(*driver->cdevs), GFP_KERNEL);
+ if (!driver->cdevs) {
+ err = -ENOMEM;
+ goto err_free_all;
+ }
+
return driver;
+err_free_all:
+ kfree(driver->ports);
+ kfree(driver->ttys);
+ kfree(driver->termios);
+ kfree(driver);
+ return ERR_PTR(err);
}
-EXPORT_SYMBOL(__alloc_tty_driver);
+EXPORT_SYMBOL(__tty_alloc_driver);
static void destruct_tty_driver(struct kref *kref)
{
struct tty_driver *driver = container_of(kref, struct tty_driver, kref);
int i;
struct ktermios *tp;
- void *p;
if (driver->flags & TTY_DRIVER_INSTALLED) {
/*
@@ -3087,13 +3235,14 @@
if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV))
tty_unregister_device(driver, i);
}
- p = driver->ttys;
proc_tty_unregister_driver(driver);
- driver->ttys = NULL;
- driver->termios = NULL;
- kfree(p);
- cdev_del(&driver->cdev);
+ if (driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)
+ cdev_del(&driver->cdevs[0]);
}
+ kfree(driver->cdevs);
+ kfree(driver->ports);
+ kfree(driver->termios);
+ kfree(driver->ttys);
kfree(driver);
}
@@ -3124,15 +3273,8 @@
int error;
int i;
dev_t dev;
- void **p = NULL;
struct device *d;
- if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) {
- p = kzalloc(driver->num * 2 * sizeof(void *), GFP_KERNEL);
- if (!p)
- return -ENOMEM;
- }
-
if (!driver->major) {
error = alloc_chrdev_region(&dev, driver->minor_start,
driver->num, driver->name);
@@ -3144,28 +3286,13 @@
dev = MKDEV(driver->major, driver->minor_start);
error = register_chrdev_region(dev, driver->num, driver->name);
}
- if (error < 0) {
- kfree(p);
- return error;
- }
+ if (error < 0)
+ goto err;
- if (p) {
- driver->ttys = (struct tty_struct **)p;
- driver->termios = (struct ktermios **)(p + driver->num);
- } else {
- driver->ttys = NULL;
- driver->termios = NULL;
- }
-
- cdev_init(&driver->cdev, &tty_fops);
- driver->cdev.owner = driver->owner;
- error = cdev_add(&driver->cdev, dev, driver->num);
- if (error) {
- unregister_chrdev_region(dev, driver->num);
- driver->ttys = NULL;
- driver->termios = NULL;
- kfree(p);
- return error;
+ if (driver->flags & TTY_DRIVER_DYNAMIC_ALLOC) {
+ error = tty_cdev_add(driver, dev, 0, driver->num);
+ if (error)
+ goto err_unreg_char;
}
mutex_lock(&tty_mutex);
@@ -3177,7 +3304,7 @@
d = tty_register_device(driver, i, NULL);
if (IS_ERR(d)) {
error = PTR_ERR(d);
- goto err;
+ goto err_unreg_devs;
}
}
}
@@ -3185,7 +3312,7 @@
driver->flags |= TTY_DRIVER_INSTALLED;
return 0;
-err:
+err_unreg_devs:
for (i--; i >= 0; i--)
tty_unregister_device(driver, i);
@@ -3193,13 +3320,11 @@
list_del(&driver->tty_drivers);
mutex_unlock(&tty_mutex);
+err_unreg_char:
unregister_chrdev_region(dev, driver->num);
- driver->ttys = NULL;
- driver->termios = NULL;
- kfree(p);
+err:
return error;
}
-
EXPORT_SYMBOL(tty_register_driver);
/*
diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c
index a1b9a2f..12b1fa0 100644
--- a/drivers/tty/tty_ioctl.c
+++ b/drivers/tty/tty_ioctl.c
@@ -410,7 +410,7 @@
void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
{
- tty_termios_encode_baud_rate(tty->termios, ibaud, obaud);
+ tty_termios_encode_baud_rate(&tty->termios, ibaud, obaud);
}
EXPORT_SYMBOL_GPL(tty_encode_baud_rate);
@@ -427,7 +427,7 @@
speed_t tty_get_baud_rate(struct tty_struct *tty)
{
- speed_t baud = tty_termios_baud_rate(tty->termios);
+ speed_t baud = tty_termios_baud_rate(&tty->termios);
if (baud == 38400 && tty->alt_speed) {
if (!tty->warned) {
@@ -509,14 +509,14 @@
/* FIXME: we need to decide on some locking/ordering semantics
for the set_termios notification eventually */
mutex_lock(&tty->termios_mutex);
- old_termios = *tty->termios;
- *tty->termios = *new_termios;
- unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
+ old_termios = tty->termios;
+ tty->termios = *new_termios;
+ unset_locked_termios(&tty->termios, &old_termios, &tty->termios_locked);
/* See if packet mode change of state. */
if (tty->link && tty->link->packet) {
int extproc = (old_termios.c_lflag & EXTPROC) |
- (tty->termios->c_lflag & EXTPROC);
+ (tty->termios.c_lflag & EXTPROC);
int old_flow = ((old_termios.c_iflag & IXON) &&
(old_termios.c_cc[VSTOP] == '\023') &&
(old_termios.c_cc[VSTART] == '\021'));
@@ -542,7 +542,7 @@
if (tty->ops->set_termios)
(*tty->ops->set_termios)(tty, &old_termios);
else
- tty_termios_copy_hw(tty->termios, &old_termios);
+ tty_termios_copy_hw(&tty->termios, &old_termios);
ld = tty_ldisc_ref(tty);
if (ld != NULL) {
@@ -578,7 +578,7 @@
return retval;
mutex_lock(&tty->termios_mutex);
- memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
+ tmp_termios = tty->termios;
mutex_unlock(&tty->termios_mutex);
if (opt & TERMIOS_TERMIO) {
@@ -632,14 +632,14 @@
static void copy_termios(struct tty_struct *tty, struct ktermios *kterm)
{
mutex_lock(&tty->termios_mutex);
- memcpy(kterm, tty->termios, sizeof(struct ktermios));
+ *kterm = tty->termios;
mutex_unlock(&tty->termios_mutex);
}
static void copy_termios_locked(struct tty_struct *tty, struct ktermios *kterm)
{
mutex_lock(&tty->termios_mutex);
- memcpy(kterm, tty->termios_locked, sizeof(struct ktermios));
+ *kterm = tty->termios_locked;
mutex_unlock(&tty->termios_mutex);
}
@@ -707,16 +707,16 @@
{
int flags = 0;
- if (!(tty->termios->c_lflag & ICANON)) {
- if (tty->termios->c_lflag & ISIG)
+ if (!(tty->termios.c_lflag & ICANON)) {
+ if (tty->termios.c_lflag & ISIG)
flags |= 0x02; /* cbreak */
else
flags |= 0x20; /* raw */
}
- if (tty->termios->c_lflag & ECHO)
+ if (tty->termios.c_lflag & ECHO)
flags |= 0x08; /* echo */
- if (tty->termios->c_oflag & OPOST)
- if (tty->termios->c_oflag & ONLCR)
+ if (tty->termios.c_oflag & OPOST)
+ if (tty->termios.c_oflag & ONLCR)
flags |= 0x10; /* crmod */
return flags;
}
@@ -726,10 +726,10 @@
struct sgttyb tmp;
mutex_lock(&tty->termios_mutex);
- 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_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);
mutex_unlock(&tty->termios_mutex);
@@ -787,7 +787,7 @@
return -EFAULT;
mutex_lock(&tty->termios_mutex);
- termios = *tty->termios;
+ termios = tty->termios;
termios.c_cc[VERASE] = tmp.sg_erase;
termios.c_cc[VKILL] = tmp.sg_kill;
set_sgflags(&termios, tmp.sg_flags);
@@ -808,12 +808,12 @@
struct tchars tmp;
mutex_lock(&tty->termios_mutex);
- tmp.t_intrc = tty->termios->c_cc[VINTR];
- tmp.t_quitc = tty->termios->c_cc[VQUIT];
- tmp.t_startc = tty->termios->c_cc[VSTART];
- tmp.t_stopc = tty->termios->c_cc[VSTOP];
- tmp.t_eofc = tty->termios->c_cc[VEOF];
- tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */
+ tmp.t_intrc = tty->termios.c_cc[VINTR];
+ tmp.t_quitc = tty->termios.c_cc[VQUIT];
+ tmp.t_startc = tty->termios.c_cc[VSTART];
+ tmp.t_stopc = tty->termios.c_cc[VSTOP];
+ tmp.t_eofc = tty->termios.c_cc[VEOF];
+ tmp.t_brkc = tty->termios.c_cc[VEOL2]; /* what is brkc anyway? */
mutex_unlock(&tty->termios_mutex);
return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
}
@@ -825,12 +825,12 @@
if (copy_from_user(&tmp, tchars, sizeof(tmp)))
return -EFAULT;
mutex_lock(&tty->termios_mutex);
- tty->termios->c_cc[VINTR] = tmp.t_intrc;
- tty->termios->c_cc[VQUIT] = tmp.t_quitc;
- tty->termios->c_cc[VSTART] = tmp.t_startc;
- tty->termios->c_cc[VSTOP] = tmp.t_stopc;
- tty->termios->c_cc[VEOF] = tmp.t_eofc;
- tty->termios->c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */
+ tty->termios.c_cc[VINTR] = tmp.t_intrc;
+ tty->termios.c_cc[VQUIT] = tmp.t_quitc;
+ tty->termios.c_cc[VSTART] = tmp.t_startc;
+ tty->termios.c_cc[VSTOP] = tmp.t_stopc;
+ tty->termios.c_cc[VEOF] = tmp.t_eofc;
+ tty->termios.c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */
mutex_unlock(&tty->termios_mutex);
return 0;
}
@@ -842,14 +842,14 @@
struct ltchars tmp;
mutex_lock(&tty->termios_mutex);
- tmp.t_suspc = tty->termios->c_cc[VSUSP];
+ tmp.t_suspc = tty->termios.c_cc[VSUSP];
/* what is dsuspc anyway? */
- tmp.t_dsuspc = tty->termios->c_cc[VSUSP];
- tmp.t_rprntc = tty->termios->c_cc[VREPRINT];
+ tmp.t_dsuspc = tty->termios.c_cc[VSUSP];
+ tmp.t_rprntc = tty->termios.c_cc[VREPRINT];
/* what is flushc anyway? */
- tmp.t_flushc = tty->termios->c_cc[VEOL2];
- tmp.t_werasc = tty->termios->c_cc[VWERASE];
- tmp.t_lnextc = tty->termios->c_cc[VLNEXT];
+ tmp.t_flushc = tty->termios.c_cc[VEOL2];
+ tmp.t_werasc = tty->termios.c_cc[VWERASE];
+ tmp.t_lnextc = tty->termios.c_cc[VLNEXT];
mutex_unlock(&tty->termios_mutex);
return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
}
@@ -862,14 +862,14 @@
return -EFAULT;
mutex_lock(&tty->termios_mutex);
- tty->termios->c_cc[VSUSP] = tmp.t_suspc;
+ tty->termios.c_cc[VSUSP] = tmp.t_suspc;
/* what is dsuspc anyway? */
- tty->termios->c_cc[VEOL2] = tmp.t_dsuspc;
- tty->termios->c_cc[VREPRINT] = tmp.t_rprntc;
+ tty->termios.c_cc[VEOL2] = tmp.t_dsuspc;
+ tty->termios.c_cc[VREPRINT] = tmp.t_rprntc;
/* what is flushc anyway? */
- tty->termios->c_cc[VEOL2] = tmp.t_flushc;
- tty->termios->c_cc[VWERASE] = tmp.t_werasc;
- tty->termios->c_cc[VLNEXT] = tmp.t_lnextc;
+ tty->termios.c_cc[VEOL2] = tmp.t_flushc;
+ tty->termios.c_cc[VWERASE] = tmp.t_werasc;
+ tty->termios.c_cc[VLNEXT] = tmp.t_lnextc;
mutex_unlock(&tty->termios_mutex);
return 0;
}
@@ -920,12 +920,12 @@
struct ktermios old;
mutex_lock(&tty->termios_mutex);
- old = *tty->termios;
- tty->termios->c_cflag &= ~CLOCAL;
- tty->termios->c_cflag |= bit;
+ old = tty->termios;
+ tty->termios.c_cflag &= ~CLOCAL;
+ tty->termios.c_cflag |= bit;
if (tty->ops->set_termios)
tty->ops->set_termios(tty, &old);
- if ((tty->termios->c_cflag & CLOCAL) != bit)
+ if ((tty->termios.c_cflag & CLOCAL) != bit)
ret = -EINVAL;
mutex_unlock(&tty->termios_mutex);
return ret;
@@ -1031,7 +1031,7 @@
(struct termios __user *) arg))
return -EFAULT;
mutex_lock(&real_tty->termios_mutex);
- memcpy(real_tty->termios_locked, &kterm, sizeof(struct ktermios));
+ real_tty->termios_locked = kterm;
mutex_unlock(&real_tty->termios_mutex);
return 0;
#else
@@ -1048,7 +1048,7 @@
(struct termios __user *) arg))
return -EFAULT;
mutex_lock(&real_tty->termios_mutex);
- memcpy(real_tty->termios_locked, &kterm, sizeof(struct ktermios));
+ real_tty->termios_locked = kterm;
mutex_unlock(&real_tty->termios_mutex);
return ret;
#endif
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index 6f99c99..4d7b562 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -413,7 +413,7 @@
static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
{
mutex_lock(&tty->termios_mutex);
- tty->termios->c_line = num;
+ tty->termios.c_line = num;
mutex_unlock(&tty->termios_mutex);
}
@@ -568,7 +568,7 @@
if (IS_ERR(new_ldisc))
return PTR_ERR(new_ldisc);
- tty_lock();
+ tty_lock(tty);
/*
* We need to look at the tty locking here for pty/tty pairs
* when both sides try to change in parallel.
@@ -582,12 +582,12 @@
*/
if (tty->ldisc->ops->num == ldisc) {
- tty_unlock();
+ tty_unlock(tty);
tty_ldisc_put(new_ldisc);
return 0;
}
- tty_unlock();
+ tty_unlock(tty);
/*
* Problem: What do we do if this blocks ?
* We could deadlock here
@@ -595,7 +595,7 @@
tty_wait_until_sent(tty, 0);
- tty_lock();
+ tty_lock(tty);
mutex_lock(&tty->ldisc_mutex);
/*
@@ -605,10 +605,10 @@
while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) {
mutex_unlock(&tty->ldisc_mutex);
- tty_unlock();
+ tty_unlock(tty);
wait_event(tty_ldisc_wait,
test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0);
- tty_lock();
+ tty_lock(tty);
mutex_lock(&tty->ldisc_mutex);
}
@@ -623,7 +623,7 @@
o_ldisc = tty->ldisc;
- tty_unlock();
+ tty_unlock(tty);
/*
* Make sure we don't change while someone holds a
* reference to the line discipline. The TTY_LDISC bit
@@ -650,7 +650,7 @@
retval = tty_ldisc_wait_idle(tty, 5 * HZ);
- tty_lock();
+ tty_lock(tty);
mutex_lock(&tty->ldisc_mutex);
/* handle wait idle failure locked */
@@ -665,7 +665,7 @@
clear_bit(TTY_LDISC_CHANGING, &tty->flags);
mutex_unlock(&tty->ldisc_mutex);
tty_ldisc_put(new_ldisc);
- tty_unlock();
+ tty_unlock(tty);
return -EIO;
}
@@ -708,7 +708,7 @@
if (o_work)
schedule_work(&o_tty->buf.work);
mutex_unlock(&tty->ldisc_mutex);
- tty_unlock();
+ tty_unlock(tty);
return retval;
}
@@ -722,9 +722,9 @@
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);
+ 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);
}
@@ -816,11 +816,11 @@
* need to wait for another function taking the BTM
*/
clear_bit(TTY_LDISC, &tty->flags);
- tty_unlock();
+ tty_unlock(tty);
cancel_work_sync(&tty->buf.work);
mutex_unlock(&tty->ldisc_mutex);
retry:
- tty_lock();
+ tty_lock(tty);
mutex_lock(&tty->ldisc_mutex);
/* At this point we have a closed ldisc and we want to
@@ -831,7 +831,7 @@
if (atomic_read(&tty->ldisc->users) != 1) {
char cur_n[TASK_COMM_LEN], tty_n[64];
long timeout = 3 * HZ;
- tty_unlock();
+ tty_unlock(tty);
while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) {
timeout = MAX_SCHEDULE_TIMEOUT;
@@ -846,7 +846,7 @@
if (reset == 0) {
- if (!tty_ldisc_reinit(tty, tty->termios->c_line))
+ if (!tty_ldisc_reinit(tty, tty->termios.c_line))
err = tty_ldisc_open(tty, tty->ldisc);
else
err = 1;
@@ -894,6 +894,23 @@
tty_ldisc_enable(tty);
return 0;
}
+
+static void tty_ldisc_kill(struct tty_struct *tty)
+{
+ mutex_lock(&tty->ldisc_mutex);
+ /*
+ * Now kill off the ldisc
+ */
+ tty_ldisc_close(tty, tty->ldisc);
+ tty_ldisc_put(tty->ldisc);
+ /* Force an oops if we mess this up */
+ tty->ldisc = NULL;
+
+ /* Ensure the next open requests the N_TTY ldisc */
+ tty_set_termios_ldisc(tty, N_TTY);
+ mutex_unlock(&tty->ldisc_mutex);
+}
+
/**
* tty_ldisc_release - release line discipline
* @tty: tty being shut down
@@ -912,28 +929,21 @@
* race with the set_ldisc code path.
*/
- tty_unlock();
+ tty_lock_pair(tty, o_tty);
tty_ldisc_halt(tty);
tty_ldisc_flush_works(tty);
- tty_lock();
-
- mutex_lock(&tty->ldisc_mutex);
- /*
- * Now kill off the ldisc
- */
- tty_ldisc_close(tty, tty->ldisc);
- tty_ldisc_put(tty->ldisc);
- /* Force an oops if we mess this up */
- tty->ldisc = NULL;
-
- /* Ensure the next open requests the N_TTY ldisc */
- tty_set_termios_ldisc(tty, N_TTY);
- mutex_unlock(&tty->ldisc_mutex);
+ if (o_tty) {
+ tty_ldisc_halt(o_tty);
+ tty_ldisc_flush_works(o_tty);
+ }
/* This will need doing differently if we need to lock */
- if (o_tty)
- tty_ldisc_release(o_tty, NULL);
+ tty_ldisc_kill(tty);
+ if (o_tty)
+ tty_ldisc_kill(o_tty);
+
+ tty_unlock_pair(tty, o_tty);
/* And the memory resources remaining (buffers, termios) will be
disposed of when the kref hits zero */
}
diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c
index 9ff986c..67feac9 100644
--- a/drivers/tty/tty_mutex.c
+++ b/drivers/tty/tty_mutex.c
@@ -4,29 +4,70 @@
#include <linux/semaphore.h>
#include <linux/sched.h>
-/*
- * The 'big tty mutex'
- *
- * This mutex is taken and released by tty_lock() and tty_unlock(),
- * replacing the older big kernel lock.
- * It can no longer be taken recursively, and does not get
- * released implicitly while sleeping.
- *
- * Don't use in new code.
- */
-static DEFINE_MUTEX(big_tty_mutex);
+/* Legacy tty mutex glue */
+
+enum {
+ TTY_MUTEX_NORMAL,
+ TTY_MUTEX_NESTED,
+};
/*
* Getting the big tty mutex.
*/
-void __lockfunc tty_lock(void)
+
+static void __lockfunc tty_lock_nested(struct tty_struct *tty,
+ unsigned int subclass)
{
- mutex_lock(&big_tty_mutex);
+ if (tty->magic != TTY_MAGIC) {
+ printk(KERN_ERR "L Bad %p\n", tty);
+ WARN_ON(1);
+ return;
+ }
+ tty_kref_get(tty);
+ mutex_lock_nested(&tty->legacy_mutex, subclass);
+}
+
+void __lockfunc tty_lock(struct tty_struct *tty)
+{
+ return tty_lock_nested(tty, TTY_MUTEX_NORMAL);
}
EXPORT_SYMBOL(tty_lock);
-void __lockfunc tty_unlock(void)
+void __lockfunc tty_unlock(struct tty_struct *tty)
{
- mutex_unlock(&big_tty_mutex);
+ if (tty->magic != TTY_MAGIC) {
+ printk(KERN_ERR "U Bad %p\n", tty);
+ WARN_ON(1);
+ return;
+ }
+ mutex_unlock(&tty->legacy_mutex);
+ tty_kref_put(tty);
}
EXPORT_SYMBOL(tty_unlock);
+
+/*
+ * Getting the big tty mutex for a pair of ttys with lock ordering
+ * On a non pty/tty pair tty2 can be NULL which is just fine.
+ */
+void __lockfunc tty_lock_pair(struct tty_struct *tty,
+ struct tty_struct *tty2)
+{
+ if (tty < tty2) {
+ tty_lock(tty);
+ tty_lock_nested(tty2, TTY_MUTEX_NESTED);
+ } else {
+ if (tty2 && tty2 != tty)
+ tty_lock(tty2);
+ tty_lock_nested(tty, TTY_MUTEX_NESTED);
+ }
+}
+EXPORT_SYMBOL(tty_lock_pair);
+
+void __lockfunc tty_unlock_pair(struct tty_struct *tty,
+ struct tty_struct *tty2)
+{
+ tty_unlock(tty);
+ if (tty2 && tty2 != tty)
+ tty_unlock(tty2);
+}
+EXPORT_SYMBOL(tty_unlock_pair);
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index bf6e238..d7bdd8d 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -33,6 +33,70 @@
}
EXPORT_SYMBOL(tty_port_init);
+/**
+ * tty_port_link_device - link tty and tty_port
+ * @port: tty_port of the device
+ * @driver: tty_driver for this device
+ * @index: index of the tty
+ *
+ * Provide the tty layer wit ha link from a tty (specified by @index) to a
+ * tty_port (@port). Use this only if neither tty_port_register_device nor
+ * tty_port_install is used in the driver. If used, this has to be called before
+ * tty_register_driver.
+ */
+void tty_port_link_device(struct tty_port *port,
+ struct tty_driver *driver, unsigned index)
+{
+ if (WARN_ON(index >= driver->num))
+ return;
+ driver->ports[index] = port;
+}
+EXPORT_SYMBOL_GPL(tty_port_link_device);
+
+/**
+ * tty_port_register_device - register tty device
+ * @port: tty_port of the device
+ * @driver: tty_driver for this device
+ * @index: index of the tty
+ * @device: parent if exists, otherwise NULL
+ *
+ * It is the same as tty_register_device except the provided @port is linked to
+ * a concrete tty specified by @index. Use this or tty_port_install (or both).
+ * Call tty_port_link_device as a last resort.
+ */
+struct device *tty_port_register_device(struct tty_port *port,
+ struct tty_driver *driver, unsigned index,
+ struct device *device)
+{
+ tty_port_link_device(port, driver, index);
+ return tty_register_device(driver, index, device);
+}
+EXPORT_SYMBOL_GPL(tty_port_register_device);
+
+/**
+ * tty_port_register_device_attr - register tty device
+ * @port: tty_port of the device
+ * @driver: tty_driver for this device
+ * @index: index of the tty
+ * @device: parent if exists, otherwise NULL
+ * @drvdata: Driver data to be set to device.
+ * @attr_grp: Attribute group to be set on device.
+ *
+ * It is the same as tty_register_device_attr except the provided @port is
+ * linked to a concrete tty specified by @index. Use this or tty_port_install
+ * (or both). Call tty_port_link_device as a last resort.
+ */
+struct device *tty_port_register_device_attr(struct tty_port *port,
+ struct tty_driver *driver, unsigned index,
+ struct device *device, void *drvdata,
+ const struct attribute_group **attr_grp)
+{
+ tty_port_link_device(port, driver, index);
+ return tty_register_device_attr(driver, index, device, drvdata,
+ attr_grp);
+}
+EXPORT_SYMBOL_GPL(tty_port_register_device_attr);
+
int tty_port_alloc_xmit_buf(struct tty_port *port)
{
/* We may sleep in get_zeroed_page() */
@@ -230,7 +294,7 @@
/* block if port is in the process of being closed */
if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
- wait_event_interruptible_tty(port->close_wait,
+ wait_event_interruptible_tty(tty, port->close_wait,
!(port->flags & ASYNC_CLOSING));
if (port->flags & ASYNC_HUP_NOTIFY)
return -EAGAIN;
@@ -246,7 +310,7 @@
}
if (filp->f_flags & O_NONBLOCK) {
/* Indicate we are open */
- if (tty->termios->c_cflag & CBAUD)
+ if (tty->termios.c_cflag & CBAUD)
tty_port_raise_dtr_rts(port);
port->flags |= ASYNC_NORMAL_ACTIVE;
return 0;
@@ -270,7 +334,7 @@
while (1) {
/* Indicate we are open */
- if (tty->termios->c_cflag & CBAUD)
+ if (tty->termios.c_cflag & CBAUD)
tty_port_raise_dtr_rts(port);
prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE);
@@ -296,9 +360,9 @@
retval = -ERESTARTSYS;
break;
}
- tty_unlock();
+ tty_unlock(tty);
schedule();
- tty_lock();
+ tty_lock(tty);
}
finish_wait(&port->open_wait, &wait);
@@ -369,7 +433,7 @@
/* Drop DTR/RTS if HUPCL is set. This causes any attached modem to
hang up the line */
- if (tty->termios->c_cflag & HUPCL)
+ if (tty->termios.c_cflag & HUPCL)
tty_port_lower_dtr_rts(port);
/* Don't call port->drop for the last reference. Callers will want
@@ -413,6 +477,24 @@
}
EXPORT_SYMBOL(tty_port_close);
+/**
+ * tty_port_install - generic tty->ops->install handler
+ * @port: tty_port of the device
+ * @driver: tty_driver for this device
+ * @tty: tty to be installed
+ *
+ * It is the same as tty_standard_install except the provided @port is linked
+ * to a concrete tty specified by @tty. Use this or tty_port_register_device
+ * (or both). Call tty_port_link_device as a last resort.
+ */
+int tty_port_install(struct tty_port *port, struct tty_driver *driver,
+ struct tty_struct *tty)
+{
+ tty->port = port;
+ return tty_standard_install(driver, tty);
+}
+EXPORT_SYMBOL_GPL(tty_port_install);
+
int tty_port_open(struct tty_port *port, struct tty_struct *tty,
struct file *filp)
{
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index 48cc6f2..681765b 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -119,6 +119,7 @@
static struct input_handler kbd_handler;
static DEFINE_SPINLOCK(kbd_event_lock);
+static DEFINE_SPINLOCK(led_lock);
static unsigned long key_down[BITS_TO_LONGS(KEY_CNT)]; /* keyboard key bitmap */
static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */
static bool dead_key_next;
@@ -310,7 +311,7 @@
if (tty) {
tty_insert_flip_char(tty, ch, 0);
- con_schedule_flip(tty);
+ tty_schedule_flip(tty);
}
}
@@ -325,7 +326,7 @@
tty_insert_flip_char(tty, *cp, 0);
cp++;
}
- con_schedule_flip(tty);
+ tty_schedule_flip(tty);
}
static void applkey(struct vc_data *vc, int key, char mode)
@@ -586,7 +587,7 @@
if (!tty)
return;
tty_insert_flip_char(tty, 0, TTY_BREAK);
- con_schedule_flip(tty);
+ tty_schedule_flip(tty);
}
static void fn_scroll_forw(struct vc_data *vc)
@@ -984,7 +985,7 @@
* or (ii) whatever pattern of lights people want to show using KDSETLED,
* or (iii) specified bits of specified words in kernel memory.
*/
-unsigned char getledstate(void)
+static unsigned char getledstate(void)
{
return ledstate;
}
@@ -992,7 +993,7 @@
void setledstate(struct kbd_struct *kbd, unsigned int led)
{
unsigned long flags;
- spin_lock_irqsave(&kbd_event_lock, flags);
+ spin_lock_irqsave(&led_lock, flags);
if (!(led & ~7)) {
ledioctl = led;
kbd->ledmode = LED_SHOW_IOCTL;
@@ -1000,7 +1001,7 @@
kbd->ledmode = LED_SHOW_FLAGS;
set_leds();
- spin_unlock_irqrestore(&kbd_event_lock, flags);
+ spin_unlock_irqrestore(&led_lock, flags);
}
static inline unsigned char getleds(void)
@@ -1049,13 +1050,13 @@
*/
int vt_get_leds(int console, int flag)
{
- unsigned long flags;
struct kbd_struct * kbd = kbd_table + console;
int ret;
+ unsigned long flags;
- spin_lock_irqsave(&kbd_event_lock, flags);
+ spin_lock_irqsave(&led_lock, flags);
ret = vc_kbd_led(kbd, flag);
- spin_unlock_irqrestore(&kbd_event_lock, flags);
+ spin_unlock_irqrestore(&led_lock, flags);
return ret;
}
@@ -1091,11 +1092,11 @@
void vt_kbd_con_start(int console)
{
struct kbd_struct * kbd = kbd_table + console;
-/* unsigned long flags; */
-/* spin_lock_irqsave(&kbd_event_lock, flags); */
+ unsigned long flags;
+ spin_lock_irqsave(&led_lock, flags);
clr_vc_kbd_led(kbd, VC_SCROLLOCK);
set_leds();
-/* spin_unlock_irqrestore(&kbd_event_lock, flags); */
+ spin_unlock_irqrestore(&led_lock, flags);
}
/**
@@ -1104,21 +1105,15 @@
*
* Handle console stop. This is a wrapper for the VT layer
* so that we can keep kbd knowledge internal
- *
- * FIXME: We eventually need to hold the kbd lock here to protect
- * the LED updating. We can't do it yet because fn_hold calls stop_tty
- * and start_tty under the kbd_event_lock, while normal tty paths
- * don't hold the lock. We probably need to split out an LED lock
- * but not during an -rc release!
*/
void vt_kbd_con_stop(int console)
{
struct kbd_struct * kbd = kbd_table + console;
-/* unsigned long flags; */
-/* spin_lock_irqsave(&kbd_event_lock, flags); */
+ unsigned long flags;
+ spin_lock_irqsave(&led_lock, flags);
set_vc_kbd_led(kbd, VC_SCROLLOCK);
set_leds();
-/* spin_unlock_irqrestore(&kbd_event_lock, flags); */
+ spin_unlock_irqrestore(&led_lock, flags);
}
/*
@@ -1130,7 +1125,12 @@
*/
static void kbd_bh(unsigned long dummy)
{
- unsigned char leds = getleds();
+ unsigned char leds;
+ unsigned long flags;
+
+ spin_lock_irqsave(&led_lock, flags);
+ leds = getleds();
+ spin_unlock_irqrestore(&led_lock, flags);
if (leds != ledstate) {
input_handler_for_each_handle(&kbd_handler, &leds,
@@ -2035,11 +2035,11 @@
return -EPERM;
if (arg & ~0x77)
return -EINVAL;
- spin_lock_irqsave(&kbd_event_lock, flags);
+ spin_lock_irqsave(&led_lock, flags);
kbd->ledflagstate = (arg & 7);
kbd->default_ledflagstate = ((arg >> 4) & 7);
set_leds();
- spin_unlock_irqrestore(&kbd_event_lock, flags);
+ spin_unlock_irqrestore(&led_lock, flags);
return 0;
/* the ioctls below only set the lights, not the functions */
@@ -2134,8 +2134,10 @@
clr_vc_kbd_mode(kbd, VC_CRLF);
kbd->lockstate = 0;
kbd->slockstate = 0;
+ spin_lock(&led_lock);
kbd->ledmode = LED_SHOW_FLAGS;
kbd->ledflagstate = kbd->default_ledflagstate;
+ spin_unlock(&led_lock);
/* do not do set_leds here because this causes an endless tasklet loop
when the keyboard hasn't been initialized yet */
spin_unlock_irqrestore(&kbd_event_lock, flags);
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 84cbf29..999ca63 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -537,45 +537,27 @@
static void insert_char(struct vc_data *vc, unsigned int nr)
{
- unsigned short *p, *q = (unsigned short *)vc->vc_pos;
+ unsigned short *p = (unsigned short *) vc->vc_pos;
- p = q + vc->vc_cols - nr - vc->vc_x;
- while (--p >= q)
- scr_writew(scr_readw(p), p + nr);
- scr_memsetw(q, vc->vc_video_erase_char, nr * 2);
+ scr_memmovew(p + nr, p, vc->vc_cols - vc->vc_x);
+ scr_memsetw(p, vc->vc_video_erase_char, nr * 2);
vc->vc_need_wrap = 0;
- if (DO_UPDATE(vc)) {
- unsigned short oldattr = vc->vc_attr;
- vc->vc_sw->con_bmove(vc, vc->vc_y, vc->vc_x, vc->vc_y, vc->vc_x + nr, 1,
- vc->vc_cols - vc->vc_x - nr);
- vc->vc_attr = vc->vc_video_erase_char >> 8;
- while (nr--)
- vc->vc_sw->con_putc(vc, vc->vc_video_erase_char, vc->vc_y, vc->vc_x + nr);
- vc->vc_attr = oldattr;
- }
+ if (DO_UPDATE(vc))
+ do_update_region(vc, (unsigned long) p,
+ (vc->vc_cols - vc->vc_x) / 2 + 1);
}
static void delete_char(struct vc_data *vc, unsigned int nr)
{
- unsigned int i = vc->vc_x;
- unsigned short *p = (unsigned short *)vc->vc_pos;
+ unsigned short *p = (unsigned short *) vc->vc_pos;
- while (++i <= vc->vc_cols - nr) {
- scr_writew(scr_readw(p+nr), p);
- p++;
- }
- scr_memsetw(p, vc->vc_video_erase_char, nr * 2);
+ scr_memcpyw(p, p + nr, vc->vc_cols - vc->vc_x - nr);
+ scr_memsetw(p + vc->vc_cols - vc->vc_x - nr, vc->vc_video_erase_char,
+ nr * 2);
vc->vc_need_wrap = 0;
- if (DO_UPDATE(vc)) {
- unsigned short oldattr = vc->vc_attr;
- vc->vc_sw->con_bmove(vc, vc->vc_y, vc->vc_x + nr, vc->vc_y, vc->vc_x, 1,
- vc->vc_cols - vc->vc_x - nr);
- vc->vc_attr = vc->vc_video_erase_char >> 8;
- while (nr--)
- vc->vc_sw->con_putc(vc, vc->vc_video_erase_char, vc->vc_y,
- vc->vc_cols - 1 - nr);
- vc->vc_attr = oldattr;
- }
+ if (DO_UPDATE(vc))
+ do_update_region(vc, (unsigned long) p,
+ (vc->vc_cols - vc->vc_x) / 2);
}
static int softcursor_original;
@@ -1172,45 +1154,26 @@
case 0: /* erase from cursor to end of display */
count = (vc->vc_scr_end - vc->vc_pos) >> 1;
start = (unsigned short *)vc->vc_pos;
- if (DO_UPDATE(vc)) {
- /* do in two stages */
- vc->vc_sw->con_clear(vc, vc->vc_y, vc->vc_x, 1,
- vc->vc_cols - vc->vc_x);
- vc->vc_sw->con_clear(vc, vc->vc_y + 1, 0,
- vc->vc_rows - vc->vc_y - 1,
- vc->vc_cols);
- }
break;
case 1: /* erase from start to cursor */
count = ((vc->vc_pos - vc->vc_origin) >> 1) + 1;
start = (unsigned short *)vc->vc_origin;
- if (DO_UPDATE(vc)) {
- /* do in two stages */
- vc->vc_sw->con_clear(vc, 0, 0, vc->vc_y,
- vc->vc_cols);
- vc->vc_sw->con_clear(vc, vc->vc_y, 0, 1,
- vc->vc_x + 1);
- }
break;
case 3: /* erase scroll-back buffer (and whole display) */
scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
vc->vc_screenbuf_size >> 1);
set_origin(vc);
- if (CON_IS_VISIBLE(vc))
- update_screen(vc);
/* fall through */
case 2: /* erase whole display */
count = vc->vc_cols * vc->vc_rows;
start = (unsigned short *)vc->vc_origin;
- if (DO_UPDATE(vc))
- vc->vc_sw->con_clear(vc, 0, 0,
- vc->vc_rows,
- vc->vc_cols);
break;
default:
return;
}
scr_memsetw(start, vc->vc_video_erase_char, 2 * count);
+ if (DO_UPDATE(vc))
+ do_update_region(vc, (unsigned long) start, count);
vc->vc_need_wrap = 0;
}
@@ -1223,29 +1186,22 @@
case 0: /* erase from cursor to end of line */
count = vc->vc_cols - vc->vc_x;
start = (unsigned short *)vc->vc_pos;
- if (DO_UPDATE(vc))
- vc->vc_sw->con_clear(vc, vc->vc_y, vc->vc_x, 1,
- vc->vc_cols - vc->vc_x);
break;
case 1: /* erase from start of line to cursor */
start = (unsigned short *)(vc->vc_pos - (vc->vc_x << 1));
count = vc->vc_x + 1;
- if (DO_UPDATE(vc))
- vc->vc_sw->con_clear(vc, vc->vc_y, 0, 1,
- vc->vc_x + 1);
break;
case 2: /* erase whole line */
start = (unsigned short *)(vc->vc_pos - (vc->vc_x << 1));
count = vc->vc_cols;
- if (DO_UPDATE(vc))
- vc->vc_sw->con_clear(vc, vc->vc_y, 0, 1,
- vc->vc_cols);
break;
default:
return;
}
scr_memsetw(start, vc->vc_video_erase_char, 2 * count);
vc->vc_need_wrap = 0;
+ if (DO_UPDATE(vc))
+ do_update_region(vc, (unsigned long) start, count);
}
static void csi_X(struct vc_data *vc, int vpar) /* erase the following vpar positions */
@@ -1380,7 +1336,7 @@
tty_insert_flip_char(tty, *p, 0);
p++;
}
- con_schedule_flip(tty);
+ tty_schedule_flip(tty);
}
static void cursor_report(struct vc_data *vc, struct tty_struct *tty)
@@ -2792,41 +2748,52 @@
/*
* Allocate the console screen memory.
*/
-static int con_open(struct tty_struct *tty, struct file *filp)
+static int con_install(struct tty_driver *driver, struct tty_struct *tty)
{
unsigned int currcons = tty->index;
- int ret = 0;
+ struct vc_data *vc;
+ int ret;
console_lock();
- if (tty->driver_data == NULL) {
- ret = vc_allocate(currcons);
- if (ret == 0) {
- struct vc_data *vc = vc_cons[currcons].d;
+ ret = vc_allocate(currcons);
+ if (ret)
+ goto unlock;
- /* Still being freed */
- if (vc->port.tty) {
- console_unlock();
- return -ERESTARTSYS;
- }
- tty->driver_data = vc;
- vc->port.tty = tty;
+ vc = vc_cons[currcons].d;
- if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
- tty->winsize.ws_row = vc_cons[currcons].d->vc_rows;
- tty->winsize.ws_col = vc_cons[currcons].d->vc_cols;
- }
- if (vc->vc_utf)
- tty->termios->c_iflag |= IUTF8;
- else
- tty->termios->c_iflag &= ~IUTF8;
- console_unlock();
- return ret;
- }
+ /* Still being freed */
+ if (vc->port.tty) {
+ ret = -ERESTARTSYS;
+ goto unlock;
}
+
+ ret = tty_port_install(&vc->port, driver, tty);
+ if (ret)
+ goto unlock;
+
+ tty->driver_data = vc;
+ vc->port.tty = tty;
+
+ if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
+ tty->winsize.ws_row = vc_cons[currcons].d->vc_rows;
+ tty->winsize.ws_col = vc_cons[currcons].d->vc_cols;
+ }
+ if (vc->vc_utf)
+ tty->termios.c_iflag |= IUTF8;
+ else
+ tty->termios.c_iflag &= ~IUTF8;
+unlock:
console_unlock();
return ret;
}
+static int con_open(struct tty_struct *tty, struct file *filp)
+{
+ /* everything done in install */
+ return 0;
+}
+
+
static void con_close(struct tty_struct *tty, struct file *filp)
{
/* Nothing to do - we defer to shutdown */
@@ -2839,7 +2806,6 @@
console_lock();
vc->port.tty = NULL;
console_unlock();
- tty_shutdown(tty);
}
static int default_italic_color = 2; // green (ASCII)
@@ -2947,6 +2913,7 @@
console_initcall(con_init);
static const struct tty_operations con_ops = {
+ .install = con_install,
.open = con_open,
.close = con_close,
.write = con_write,
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index f763ed7..ff7b5a8 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -826,7 +826,7 @@
struct ktermios *termios_old)
{
struct acm *acm = tty->driver_data;
- struct ktermios *termios = tty->termios;
+ struct ktermios *termios = &tty->termios;
struct usb_cdc_line_coding newline;
int newctrl = acm->ctrlout;
@@ -1299,7 +1299,8 @@
usb_set_intfdata(data_interface, acm);
usb_get_intf(control_interface);
- tty_register_device(acm_tty_driver, minor, &control_interface->dev);
+ tty_port_register_device(&acm->port, acm_tty_driver, minor,
+ &control_interface->dev);
return 0;
alloc_fail7:
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index 5b3f5ff..2b5534c2 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -1129,7 +1129,8 @@
for (i = 0; i < count; i++) {
struct device *tty_dev;
- tty_dev = tty_register_device(gs_tty_driver, i, &g->dev);
+ tty_dev = tty_port_register_device(&ports[i].port->port,
+ gs_tty_driver, i, &g->dev);
if (IS_ERR(tty_dev))
pr_warning("%s: no classdev for port %d, err %ld\n",
__func__, i, PTR_ERR(tty_dev));
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index f8ce97d..3b98fb7 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -215,7 +215,7 @@
static void ark3116_init_termios(struct tty_struct *tty)
{
- struct ktermios *termios = tty->termios;
+ struct ktermios *termios = &tty->termios;
*termios = tty_std_termios;
termios->c_cflag = B9600 | CS8
| CREAD | HUPCL | CLOCAL;
@@ -229,7 +229,7 @@
{
struct usb_serial *serial = port->serial;
struct ark3116_private *priv = usb_get_serial_port_data(port);
- struct ktermios *termios = tty->termios;
+ struct ktermios *termios = &tty->termios;
unsigned int cflag = termios->c_cflag;
int bps = tty_get_baud_rate(tty);
int quot;
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index 6b73656..a46df73 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -307,7 +307,7 @@
unsigned long control_state;
int bad_flow_control;
speed_t baud;
- struct ktermios *termios = tty->termios;
+ struct ktermios *termios = &tty->termios;
iflag = termios->c_iflag;
cflag = termios->c_cflag;
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index b9cca6d..9a56428 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -165,8 +165,8 @@
}
if (serial->type->set_termios) {
- tty->termios->c_cflag = cflag;
- tty_termios_encode_baud_rate(tty->termios, baud, baud);
+ tty->termios.c_cflag = cflag;
+ tty_termios_encode_baud_rate(&tty->termios, baud, baud);
memset(&dummy, 0, sizeof(struct ktermios));
serial->type->set_termios(tty, port, &dummy);
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 1e71079..ba5e07e1 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -469,7 +469,7 @@
if (tty) {
cp210x_get_termios_port(tty->driver_data,
- &tty->termios->c_cflag, &baud);
+ &tty->termios.c_cflag, &baud);
tty_encode_baud_rate(tty, baud, baud);
}
@@ -631,7 +631,7 @@
{
u32 baud;
- baud = tty->termios->c_ospeed;
+ baud = tty->termios.c_ospeed;
/* This maps the requested rate to a rate valid on cp2102 or cp2103,
* or to an arbitrary rate in [1M,2M].
@@ -665,10 +665,10 @@
if (!tty)
return;
- cflag = tty->termios->c_cflag;
+ cflag = tty->termios.c_cflag;
old_cflag = old_termios->c_cflag;
- if (tty->termios->c_ospeed != old_termios->c_ospeed)
+ if (tty->termios.c_ospeed != old_termios->c_ospeed)
cp210x_change_speed(tty, port, old_termios);
/* If the number of data bits is to be updated */
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index b78c34e..be34f15 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -922,38 +922,38 @@
early enough */
if (!priv->termios_initialized) {
if (priv->chiptype == CT_EARTHMATE) {
- *(tty->termios) = tty_std_termios;
- tty->termios->c_cflag = B4800 | CS8 | CREAD | HUPCL |
+ tty->termios = tty_std_termios;
+ tty->termios.c_cflag = B4800 | CS8 | CREAD | HUPCL |
CLOCAL;
- tty->termios->c_ispeed = 4800;
- tty->termios->c_ospeed = 4800;
+ tty->termios.c_ispeed = 4800;
+ tty->termios.c_ospeed = 4800;
} else if (priv->chiptype == CT_CYPHIDCOM) {
- *(tty->termios) = tty_std_termios;
- tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL |
+ tty->termios = tty_std_termios;
+ tty->termios.c_cflag = B9600 | CS8 | CREAD | HUPCL |
CLOCAL;
- tty->termios->c_ispeed = 9600;
- tty->termios->c_ospeed = 9600;
+ tty->termios.c_ispeed = 9600;
+ tty->termios.c_ospeed = 9600;
} else if (priv->chiptype == CT_CA42V2) {
- *(tty->termios) = tty_std_termios;
- tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL |
+ tty->termios = tty_std_termios;
+ tty->termios.c_cflag = B9600 | CS8 | CREAD | HUPCL |
CLOCAL;
- tty->termios->c_ispeed = 9600;
- tty->termios->c_ospeed = 9600;
+ tty->termios.c_ispeed = 9600;
+ tty->termios.c_ospeed = 9600;
}
priv->termios_initialized = 1;
}
spin_unlock_irqrestore(&priv->lock, flags);
/* Unsupported features need clearing */
- tty->termios->c_cflag &= ~(CMSPAR|CRTSCTS);
+ tty->termios.c_cflag &= ~(CMSPAR|CRTSCTS);
- cflag = tty->termios->c_cflag;
- iflag = tty->termios->c_iflag;
+ cflag = tty->termios.c_cflag;
+ iflag = tty->termios.c_iflag;
/* check if there are new settings */
if (old_termios) {
spin_lock_irqsave(&priv->lock, flags);
- priv->tmp_termios = *(tty->termios);
+ priv->tmp_termios = tty->termios;
spin_unlock_irqrestore(&priv->lock, flags);
}
@@ -1021,7 +1021,7 @@
"4800bps.");
/* define custom termios settings for NMEA protocol */
- tty->termios->c_iflag /* input modes - */
+ tty->termios.c_iflag /* input modes - */
&= ~(IGNBRK /* disable ignore break */
| BRKINT /* disable break causes interrupt */
| PARMRK /* disable mark parity errors */
@@ -1031,10 +1031,10 @@
| ICRNL /* disable translate CR to NL */
| IXON); /* disable enable XON/XOFF flow control */
- tty->termios->c_oflag /* output modes */
+ tty->termios.c_oflag /* output modes */
&= ~OPOST; /* disable postprocess output char */
- tty->termios->c_lflag /* line discipline modes */
+ tty->termios.c_lflag /* line discipline modes */
&= ~(ECHO /* disable echo input characters */
| ECHONL /* disable echo new line */
| ICANON /* disable erase, kill, werase, and rprnt
@@ -1200,7 +1200,7 @@
/* hangup, as defined in acm.c... this might be a bad place for it
* though */
- if (tty && !(tty->termios->c_cflag & CLOCAL) &&
+ if (tty && !(tty->termios.c_cflag & CLOCAL) &&
!(priv->current_status & UART_CD)) {
dbg("%s - calling hangup", __func__);
tty_hangup(tty);
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index b5cd838..afd9d2e 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -687,8 +687,8 @@
struct usb_serial_port *port, struct ktermios *old_termios)
{
struct digi_port *priv = usb_get_serial_port_data(port);
- unsigned int iflag = tty->termios->c_iflag;
- unsigned int cflag = tty->termios->c_cflag;
+ unsigned int iflag = tty->termios.c_iflag;
+ unsigned int cflag = tty->termios.c_cflag;
unsigned int old_iflag = old_termios->c_iflag;
unsigned int old_cflag = old_termios->c_cflag;
unsigned char buf[32];
@@ -709,7 +709,7 @@
/* don't set RTS if using hardware flow control */
/* and throttling input */
modem_signals = TIOCM_DTR;
- if (!(tty->termios->c_cflag & CRTSCTS) ||
+ if (!(tty->termios.c_cflag & CRTSCTS) ||
!test_bit(TTY_THROTTLED, &tty->flags))
modem_signals |= TIOCM_RTS;
digi_set_modem_signals(port, modem_signals, 1);
@@ -748,7 +748,7 @@
}
}
/* set parity */
- tty->termios->c_cflag &= ~CMSPAR;
+ tty->termios.c_cflag &= ~CMSPAR;
if ((cflag&(PARENB|PARODD)) != (old_cflag&(PARENB|PARODD))) {
if (cflag&PARENB) {
@@ -1124,8 +1124,8 @@
/* set termios settings */
if (tty) {
- not_termios.c_cflag = ~tty->termios->c_cflag;
- not_termios.c_iflag = ~tty->termios->c_iflag;
+ not_termios.c_cflag = ~tty->termios.c_cflag;
+ not_termios.c_iflag = ~tty->termios.c_iflag;
digi_set_termios(tty, port, ¬_termios);
}
return 0;
@@ -1500,7 +1500,7 @@
rts = 0;
if (tty)
- rts = tty->termios->c_cflag & CRTSCTS;
+ rts = tty->termios.c_cflag & CRTSCTS;
if (tty && opcode == DIGI_CMD_READ_INPUT_SIGNALS) {
spin_lock(&priv->dp_port_lock);
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index cdf61dd..34e8638 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -87,7 +87,7 @@
static void empeg_init_termios(struct tty_struct *tty)
{
- struct ktermios *termios = tty->termios;
+ struct ktermios *termios = &tty->termios;
/*
* The empeg-car player wants these particular tty settings.
diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c
index 499b15f..79451ee 100644
--- a/drivers/usb/serial/f81232.c
+++ b/drivers/usb/serial/f81232.c
@@ -173,10 +173,11 @@
/* FIXME - Stubbed out for now */
/* Don't change anything if nothing has changed */
- if (!tty_termios_hw_change(tty->termios, old_termios))
+ if (!tty_termios_hw_change(&tty->termios, old_termios))
return;
/* Do the real work here... */
+ tty_termios_copy_hw(&tty->termios, old_termios);
}
static int f81232_tiocmget(struct tty_struct *tty)
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 5620db6..24e3e19 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -2082,7 +2082,7 @@
{
struct usb_device *dev = port->serial->dev;
struct ftdi_private *priv = usb_get_serial_port_data(port);
- struct ktermios *termios = tty->termios;
+ struct ktermios *termios = &tty->termios;
unsigned int cflag = termios->c_cflag;
__u16 urb_value; /* will hold the new flags */
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index e1f5ccd..f435575 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -1458,7 +1458,7 @@
}
/* if we are implementing RTS/CTS, toggle that line */
- if (tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios.c_cflag & CRTSCTS) {
edge_port->shadowMCR &= ~MCR_RTS;
status = send_cmd_write_uart_register(edge_port, MCR,
edge_port->shadowMCR);
@@ -1497,7 +1497,7 @@
return;
}
/* if we are implementing RTS/CTS, toggle that line */
- if (tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios.c_cflag & CRTSCTS) {
edge_port->shadowMCR |= MCR_RTS;
send_cmd_write_uart_register(edge_port, MCR,
edge_port->shadowMCR);
@@ -1516,9 +1516,9 @@
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
unsigned int cflag;
- cflag = tty->termios->c_cflag;
+ cflag = tty->termios.c_cflag;
dbg("%s - clfag %08x iflag %08x", __func__,
- tty->termios->c_cflag, tty->termios->c_iflag);
+ tty->termios.c_cflag, tty->termios.c_iflag);
dbg("%s - old clfag %08x old iflag %08x", __func__,
old_termios->c_cflag, old_termios->c_iflag);
@@ -1987,7 +1987,7 @@
tty = tty_port_tty_get(&edge_port->port->port);
if (tty) {
change_port_settings(tty,
- edge_port, tty->termios);
+ edge_port, &tty->termios);
tty_kref_put(tty);
}
@@ -2570,7 +2570,7 @@
return;
}
- cflag = tty->termios->c_cflag;
+ cflag = tty->termios.c_cflag;
switch (cflag & CSIZE) {
case CS5:
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 3936904..765978a 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -1870,7 +1870,7 @@
/* set up the port settings */
if (tty)
- edge_set_termios(tty, port, tty->termios);
+ edge_set_termios(tty, port, &tty->termios);
/* open up the port */
@@ -2272,13 +2272,13 @@
config = kmalloc (sizeof (*config), GFP_KERNEL);
if (!config) {
- *tty->termios = *old_termios;
+ tty->termios = *old_termios;
dev_err(&edge_port->port->dev, "%s - out of memory\n",
__func__);
return;
}
- cflag = tty->termios->c_cflag;
+ cflag = tty->termios.c_cflag;
config->wFlags = 0;
@@ -2362,7 +2362,7 @@
} else
dbg("%s - OUTBOUND XON/XOFF is disabled", __func__);
- tty->termios->c_cflag &= ~CMSPAR;
+ tty->termios.c_cflag &= ~CMSPAR;
/* Round the baud rate */
baud = tty_get_baud_rate(tty);
@@ -2408,10 +2408,10 @@
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
unsigned int cflag;
- cflag = tty->termios->c_cflag;
+ cflag = tty->termios.c_cflag;
dbg("%s - clfag %08x iflag %08x", __func__,
- tty->termios->c_cflag, tty->termios->c_iflag);
+ tty->termios.c_cflag, tty->termios.c_iflag);
dbg("%s - old clfag %08x old iflag %08x", __func__,
old_termios->c_cflag, old_termios->c_iflag);
dbg("%s - port %d", __func__, port->number);
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index fc09414..5a96692 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -381,7 +381,7 @@
ir_xbof = ir_xbof_change(xbof) ;
/* Only speed changes are supported */
- tty_termios_copy_hw(tty->termios, old_termios);
+ tty_termios_copy_hw(&tty->termios, old_termios);
tty_encode_baud_rate(tty, baud, baud);
/*
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
index 22b1eb5..bf38640 100644
--- a/drivers/usb/serial/iuu_phoenix.c
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -921,7 +921,7 @@
{
const u32 supported_mask = CMSPAR|PARENB|PARODD;
struct iuu_private *priv = usb_get_serial_port_data(port);
- unsigned int cflag = tty->termios->c_cflag;
+ unsigned int cflag = tty->termios.c_cflag;
int status;
u32 actual;
u32 parity;
@@ -930,7 +930,7 @@
u32 newval = cflag & supported_mask;
/* Just use the ospeed. ispeed should be the same. */
- baud = tty->termios->c_ospeed;
+ baud = tty->termios.c_ospeed;
dbg("%s - enter c_ospeed or baud=%d", __func__, baud);
@@ -961,13 +961,13 @@
* settings back over and then adjust them
*/
if (old_termios)
- tty_termios_copy_hw(tty->termios, old_termios);
+ tty_termios_copy_hw(&tty->termios, old_termios);
if (status != 0) /* Set failed - return old bits */
return;
/* Re-encode speed, parity and csize */
tty_encode_baud_rate(tty, baud, baud);
- tty->termios->c_cflag &= ~(supported_mask|CSIZE);
- tty->termios->c_cflag |= newval | csize;
+ tty->termios.c_cflag &= ~(supported_mask|CSIZE);
+ tty->termios.c_cflag |= newval | csize;
}
static void iuu_close(struct usb_serial_port *port)
@@ -993,14 +993,14 @@
static void iuu_init_termios(struct tty_struct *tty)
{
- *(tty->termios) = tty_std_termios;
- tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600
+ tty->termios = tty_std_termios;
+ tty->termios.c_cflag = CLOCAL | CREAD | CS8 | B9600
| TIOCM_CTS | CSTOPB | PARENB;
- tty->termios->c_ispeed = 9600;
- tty->termios->c_ospeed = 9600;
- tty->termios->c_lflag = 0;
- tty->termios->c_oflag = 0;
- tty->termios->c_iflag = 0;
+ tty->termios.c_ispeed = 9600;
+ tty->termios.c_ospeed = 9600;
+ tty->termios.c_lflag = 0;
+ tty->termios.c_oflag = 0;
+ tty->termios.c_iflag = 0;
}
static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port)
@@ -1012,8 +1012,8 @@
u32 actual;
struct iuu_private *priv = usb_get_serial_port_data(port);
- baud = tty->termios->c_ospeed;
- tty->termios->c_ispeed = baud;
+ baud = tty->termios.c_ospeed;
+ tty->termios.c_ispeed = baud;
/* Re-encode speed */
tty_encode_baud_rate(tty, baud, baud);
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index af0b70e..7bcbb47 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -158,7 +158,7 @@
p_priv = usb_get_serial_port_data(port);
d_details = p_priv->device_details;
- cflag = tty->termios->c_cflag;
+ cflag = tty->termios.c_cflag;
device_port = port->number - port->serial->minor;
/* Baud rate calculation takes baud rate as an integer
@@ -179,7 +179,7 @@
p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none;
/* Mark/Space not supported */
- tty->termios->c_cflag &= ~CMSPAR;
+ tty->termios.c_cflag &= ~CMSPAR;
keyspan_send_setup(port, 0);
}
@@ -1086,7 +1086,7 @@
device_port = port->number - port->serial->minor;
if (tty) {
- cflag = tty->termios->c_cflag;
+ cflag = tty->termios.c_cflag;
/* Baud rate calculation takes baud rate as an integer
so other rates can be generated if desired. */
baud_rate = tty_get_baud_rate(tty);
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index a4ac3cf..dcada86 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -338,7 +338,7 @@
7[EOMS]1: 10 bit, b0/b7 is parity
7[EOMS]2: 11 bit, b0/b7 is parity, extra bit always (mark?)
- HW flow control is dictated by the tty->termios->c_cflags & CRTSCTS
+ HW flow control is dictated by the tty->termios.c_cflags & CRTSCTS
bit.
For now, just do baud. */
@@ -353,7 +353,7 @@
}
/* Only speed can change so copy the old h/w parameters
then encode the new speed */
- tty_termios_copy_hw(tty->termios, old_termios);
+ tty_termios_copy_hw(&tty->termios, old_termios);
tty_encode_baud_rate(tty, speed, speed);
}
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 5bed59c..def9ad2 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -311,12 +311,12 @@
/* set up termios structure */
spin_lock_irqsave(&priv->lock, flags);
- priv->termios.c_iflag = tty->termios->c_iflag;
- priv->termios.c_oflag = tty->termios->c_oflag;
- priv->termios.c_cflag = tty->termios->c_cflag;
- priv->termios.c_lflag = tty->termios->c_lflag;
+ priv->termios.c_iflag = tty->termios.c_iflag;
+ priv->termios.c_oflag = tty->termios.c_oflag;
+ priv->termios.c_cflag = tty->termios.c_cflag;
+ priv->termios.c_lflag = tty->termios.c_lflag;
for (i = 0; i < NCCS; i++)
- priv->termios.c_cc[i] = tty->termios->c_cc[i];
+ priv->termios.c_cc[i] = tty->termios.c_cc[i];
priv->cfg.pktlen = cfg->pktlen;
priv->cfg.baudrate = cfg->baudrate;
priv->cfg.databits = cfg->databits;
@@ -445,9 +445,9 @@
struct ktermios *old_termios)
{
struct klsi_105_private *priv = usb_get_serial_port_data(port);
- unsigned int iflag = tty->termios->c_iflag;
+ unsigned int iflag = tty->termios.c_iflag;
unsigned int old_iflag = old_termios->c_iflag;
- unsigned int cflag = tty->termios->c_cflag;
+ unsigned int cflag = tty->termios.c_cflag;
unsigned int old_cflag = old_termios->c_cflag;
struct klsi_105_port_settings *cfg;
unsigned long flags;
@@ -560,7 +560,7 @@
if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))
|| (cflag & CSTOPB) != (old_cflag & CSTOPB)) {
/* Not currently supported */
- tty->termios->c_cflag &= ~(PARENB|PARODD|CSTOPB);
+ tty->termios.c_cflag &= ~(PARENB|PARODD|CSTOPB);
#if 0
priv->last_lcr = 0;
@@ -587,7 +587,7 @@
|| (iflag & IXON) != (old_iflag & IXON)
|| (cflag & CRTSCTS) != (old_cflag & CRTSCTS)) {
/* Not currently supported */
- tty->termios->c_cflag &= ~CRTSCTS;
+ tty->termios.c_cflag &= ~CRTSCTS;
/* Drop DTR/RTS if no flow control otherwise assert */
#if 0
if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS))
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index fafeabb..bf5c749 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -191,11 +191,11 @@
static void kobil_init_termios(struct tty_struct *tty)
{
/* Default to echo off and other sane device settings */
- tty->termios->c_lflag = 0;
- tty->termios->c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN | XCASE);
- tty->termios->c_iflag = IGNBRK | IGNPAR | IXOFF;
+ tty->termios.c_lflag = 0;
+ tty->termios.c_iflag &= ~(ISIG | ICANON | ECHO | IEXTEN | XCASE);
+ tty->termios.c_iflag |= IGNBRK | IGNPAR | IXOFF;
/* do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D) */
- tty->termios->c_oflag &= ~ONLCR;
+ tty->termios.c_oflag &= ~ONLCR;
}
static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port)
@@ -581,14 +581,14 @@
struct kobil_private *priv;
int result;
unsigned short urb_val = 0;
- int c_cflag = tty->termios->c_cflag;
+ int c_cflag = tty->termios.c_cflag;
speed_t speed;
priv = usb_get_serial_port_data(port);
if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID ||
priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
/* This device doesn't support ioctl calls */
- *tty->termios = *old;
+ tty_termios_copy_hw(&tty->termios, old);
return;
}
@@ -612,7 +612,7 @@
urb_val |= SUSBCR_SPASB_EvenParity;
} else
urb_val |= SUSBCR_SPASB_NoParity;
- tty->termios->c_cflag &= ~CMSPAR;
+ tty->termios.c_cflag &= ~CMSPAR;
tty_encode_baud_rate(tty, speed, speed);
result = usb_control_msg(port->serial->dev,
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index a71fa0a..df98cff 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -454,7 +454,7 @@
* either.
*/
spin_lock_irqsave(&priv->lock, flags);
- if (tty && (tty->termios->c_cflag & CBAUD))
+ if (tty && (tty->termios.c_cflag & CBAUD))
priv->control_state = TIOCM_DTR | TIOCM_RTS;
else
priv->control_state = 0;
@@ -634,7 +634,7 @@
{
struct usb_serial *serial = port->serial;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
- struct ktermios *termios = tty->termios;
+ struct ktermios *termios = &tty->termios;
unsigned int cflag = termios->c_cflag;
unsigned int old_cflag = old_termios->c_cflag;
unsigned long flags;
diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c
index d47eb06..2b0627b 100644
--- a/drivers/usb/serial/metro-usb.c
+++ b/drivers/usb/serial/metro-usb.c
@@ -130,12 +130,6 @@
/* Set the data read from the usb port into the serial port buffer. */
tty = tty_port_tty_get(&port->port);
- if (!tty) {
- dev_err(&port->dev, "%s - bad tty pointer - exiting\n",
- __func__);
- return;
- }
-
if (tty && urb->actual_length) {
/* Loop through the data copying each byte to the tty layer. */
tty_insert_flip_string(tty, data, urb->actual_length);
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index a07dd3c..012f67b 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -1349,7 +1349,7 @@
}
/* if we are implementing RTS/CTS, toggle that line */
- if (tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios.c_cflag & CRTSCTS) {
mos7720_port->shadowMCR &= ~UART_MCR_RTS;
write_mos_reg(port->serial, port->number - port->serial->minor,
MCR, mos7720_port->shadowMCR);
@@ -1383,7 +1383,7 @@
}
/* if we are implementing RTS/CTS, toggle that line */
- if (tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios.c_cflag & CRTSCTS) {
mos7720_port->shadowMCR |= UART_MCR_RTS;
write_mos_reg(port->serial, port->number - port->serial->minor,
MCR, mos7720_port->shadowMCR);
@@ -1604,8 +1604,8 @@
lStop = 0x00; /* 1 stop bit */
lParity = 0x00; /* No parity */
- cflag = tty->termios->c_cflag;
- iflag = tty->termios->c_iflag;
+ cflag = tty->termios.c_cflag;
+ iflag = tty->termios.c_iflag;
/* Change the number of bits */
switch (cflag & CSIZE) {
@@ -1753,11 +1753,11 @@
dbg("%s\n", "setting termios - ASPIRE");
- cflag = tty->termios->c_cflag;
+ cflag = tty->termios.c_cflag;
dbg("%s - cflag %08x iflag %08x", __func__,
- tty->termios->c_cflag,
- RELEVANT_IFLAG(tty->termios->c_iflag));
+ tty->termios.c_cflag,
+ RELEVANT_IFLAG(tty->termios.c_iflag));
dbg("%s - old cflag %08x old iflag %08x", __func__,
old_termios->c_cflag,
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 2f6da1e..402c32d 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -1651,7 +1651,7 @@
return;
}
/* if we are implementing RTS/CTS, toggle that line */
- if (tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios.c_cflag & CRTSCTS) {
mos7840_port->shadowMCR &= ~MCR_RTS;
status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
mos7840_port->shadowMCR);
@@ -1694,7 +1694,7 @@
}
/* if we are implementing RTS/CTS, toggle that line */
- if (tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios.c_cflag & CRTSCTS) {
mos7840_port->shadowMCR |= MCR_RTS;
status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
mos7840_port->shadowMCR);
@@ -2000,8 +2000,8 @@
lStop = LCR_STOP_1;
lParity = LCR_PAR_NONE;
- cflag = tty->termios->c_cflag;
- iflag = tty->termios->c_iflag;
+ cflag = tty->termios.c_cflag;
+ iflag = tty->termios.c_iflag;
/* Change the number of bits */
if (cflag & CSIZE) {
@@ -2161,10 +2161,10 @@
dbg("%s", "setting termios - ");
- cflag = tty->termios->c_cflag;
+ cflag = tty->termios.c_cflag;
dbg("%s - clfag %08x iflag %08x", __func__,
- tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag));
+ tty->termios.c_cflag, RELEVANT_IFLAG(tty->termios.c_iflag));
dbg("%s - old clfag %08x old iflag %08x", __func__,
old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag));
dbg("%s - port %d", __func__, port->number);
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index 5976b65..9f55556 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -404,10 +404,10 @@
static void oti6858_init_termios(struct tty_struct *tty)
{
- *(tty->termios) = tty_std_termios;
- tty->termios->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
- tty->termios->c_ispeed = 38400;
- tty->termios->c_ospeed = 38400;
+ tty->termios = tty_std_termios;
+ tty->termios.c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
+ tty->termios.c_ispeed = 38400;
+ tty->termios.c_ospeed = 38400;
}
static void oti6858_set_termios(struct tty_struct *tty,
@@ -425,7 +425,7 @@
return;
}
- cflag = tty->termios->c_cflag;
+ cflag = tty->termios.c_cflag;
spin_lock_irqsave(&priv->lock, flags);
divisor = priv->pending_setup.divisor;
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 13b8dd6..2b9108a 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -260,16 +260,16 @@
serial settings even to the same values as before. Thus
we actually need to filter in this specific case */
- if (!tty_termios_hw_change(tty->termios, old_termios))
+ if (!tty_termios_hw_change(&tty->termios, old_termios))
return;
- cflag = tty->termios->c_cflag;
+ cflag = tty->termios.c_cflag;
buf = kzalloc(7, GFP_KERNEL);
if (!buf) {
dev_err(&port->dev, "%s - out of memory.\n", __func__);
/* Report back no change occurred */
- *tty->termios = *old_termios;
+ tty->termios = *old_termios;
return;
}
diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c
index 151670b..7df9cdb 100644
--- a/drivers/usb/serial/quatech2.c
+++ b/drivers/usb/serial/quatech2.c
@@ -275,7 +275,7 @@
{
struct usb_device *dev = port->serial->dev;
struct qt2_port_private *port_priv;
- struct ktermios *termios = tty->termios;
+ struct ktermios *termios = &tty->termios;
u16 baud;
unsigned int cflag = termios->c_cflag;
u16 new_lcr = 0;
@@ -406,7 +406,7 @@
port_priv->device_port = (u8) device_port;
if (tty)
- qt2_set_termios(tty, port, tty->termios);
+ qt2_set_termios(tty, port, &tty->termios);
return 0;
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index 0274710..b14ebbd 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -382,7 +382,7 @@
static void sierra_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
- tty_termios_copy_hw(tty->termios, old_termios);
+ tty_termios_copy_hw(&tty->termios, old_termios);
sierra_send_setup(port);
}
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index cad6089..ab68a4d 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -316,10 +316,10 @@
static void spcp8x5_init_termios(struct tty_struct *tty)
{
/* for the 1st time call this function */
- *(tty->termios) = tty_std_termios;
- tty->termios->c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
- tty->termios->c_ispeed = 115200;
- tty->termios->c_ospeed = 115200;
+ tty->termios = tty_std_termios;
+ tty->termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
+ tty->termios.c_ispeed = 115200;
+ tty->termios.c_ospeed = 115200;
}
/* set the serial param for transfer. we should check if we really need to
@@ -330,7 +330,7 @@
struct usb_serial *serial = port->serial;
struct spcp8x5_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
- unsigned int cflag = tty->termios->c_cflag;
+ unsigned int cflag = tty->termios.c_cflag;
unsigned int old_cflag = old_termios->c_cflag;
unsigned short uartdata;
unsigned char buf[2] = {0, 0};
@@ -340,7 +340,7 @@
/* check that they really want us to change something */
- if (!tty_termios_hw_change(tty->termios, old_termios))
+ if (!tty_termios_hw_change(&tty->termios, old_termios))
return;
/* set DTR/RTS active */
diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
index 3fee23b..cf2d30c 100644
--- a/drivers/usb/serial/ssu100.c
+++ b/drivers/usb/serial/ssu100.c
@@ -216,7 +216,7 @@
struct ktermios *old_termios)
{
struct usb_device *dev = port->serial->dev;
- struct ktermios *termios = tty->termios;
+ struct ktermios *termios = &tty->termios;
u16 baud, divisor, remainder;
unsigned int cflag = termios->c_cflag;
u16 urb_value = 0; /* will hold the new flags */
@@ -322,7 +322,7 @@
dbg("%s - set uart failed", __func__);
if (tty)
- ssu100_set_termios(tty, port, tty->termios);
+ ssu100_set_termios(tty, port, &tty->termios);
return usb_serial_generic_open(tty, port);
}
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index a4404f5..f502a16 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -520,7 +520,7 @@
}
if (tty)
- ti_set_termios(tty, port, tty->termios);
+ ti_set_termios(tty, port, &tty->termios);
dbg("%s - sending TI_OPEN_PORT", __func__);
status = ti_command_out_sync(tdev, TI_OPEN_PORT,
@@ -562,7 +562,7 @@
usb_clear_halt(dev, port->read_urb->pipe);
if (tty)
- ti_set_termios(tty, port, tty->termios);
+ ti_set_termios(tty, port, &tty->termios);
dbg("%s - sending TI_OPEN_PORT (2)", __func__);
status = ti_command_out_sync(tdev, TI_OPEN_PORT,
@@ -831,8 +831,8 @@
int port_number = port->number - port->serial->minor;
unsigned int mcr;
- cflag = tty->termios->c_cflag;
- iflag = tty->termios->c_iflag;
+ cflag = tty->termios.c_cflag;
+ iflag = tty->termios.c_iflag;
dbg("%s - cflag %08x, iflag %08x", __func__, cflag, iflag);
dbg("%s - old clfag %08x, old iflag %08x", __func__,
@@ -871,7 +871,7 @@
}
/* CMSPAR isn't supported by this driver */
- tty->termios->c_cflag &= ~CMSPAR;
+ tty->termios.c_cflag &= ~CMSPAR;
if (cflag & PARENB) {
if (cflag & PARODD) {
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 27483f9..aa4b0d7 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -207,7 +207,7 @@
if (retval)
goto error_get_interface;
- retval = tty_standard_install(driver, tty);
+ retval = tty_port_install(&port->port, driver, tty);
if (retval)
goto error_init_termios;
@@ -305,8 +305,7 @@
* Do the resource freeing and refcount dropping for the port.
* Avoid freeing the console.
*
- * Called asynchronously after the last tty kref is dropped,
- * and the tty layer has already done the tty_shutdown(tty);
+ * Called asynchronously after the last tty kref is dropped.
*/
static void serial_cleanup(struct tty_struct *tty)
{
@@ -423,7 +422,7 @@
if (port->serial->type->set_termios)
port->serial->type->set_termios(tty, port, old);
else
- tty_termios_copy_hw(tty->termios, old);
+ tty_termios_copy_hw(&tty->termios, old);
}
static int serial_break(struct tty_struct *tty, int break_state)
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
index 6855d5e..72b678d 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -67,7 +67,7 @@
struct usb_wwan_intf_private *intfdata = port->serial->private;
/* Doesn't support option setting */
- tty_termios_copy_hw(tty->termios, old_termios);
+ tty_termios_copy_hw(&tty->termios, old_termios);
if (intfdata->send_setup)
intfdata->send_setup(port);
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 473635e..b36077d 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -724,7 +724,7 @@
{
struct usb_serial_port *port = tty->driver_data;
struct whiteheat_port_settings port_settings;
- unsigned int cflag = tty->termios->c_cflag;
+ unsigned int cflag = tty->termios.c_cflag;
port_settings.port = port->number + 1;
diff --git a/drivers/video/auo_k190x.c b/drivers/video/auo_k190x.c
index 77da6a2..c03ecdd 100644
--- a/drivers/video/auo_k190x.c
+++ b/drivers/video/auo_k190x.c
@@ -987,7 +987,6 @@
fb_dealloc_cmap(&info->cmap);
err_cmap:
fb_deferred_io_cleanup(info);
- kfree(info->fbdefio);
err_defio:
vfree((void *)info->screen_base);
err_irq:
@@ -1022,7 +1021,6 @@
fb_dealloc_cmap(&info->cmap);
fb_deferred_io_cleanup(info);
- kfree(info->fbdefio);
vfree((void *)info->screen_base);
diff --git a/drivers/video/backlight/omap1_bl.c b/drivers/video/backlight/omap1_bl.c
index bfdc5fb..92257ef 100644
--- a/drivers/video/backlight/omap1_bl.c
+++ b/drivers/video/backlight/omap1_bl.c
@@ -27,9 +27,9 @@
#include <linux/fb.h>
#include <linux/backlight.h>
#include <linux/slab.h>
+#include <linux/platform_data/omap1_bl.h>
#include <mach/hardware.h>
-#include <plat/board.h>
#include <plat/mux.h>
#define OMAPBL_MAX_INTENSITY 0xff
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
index 28b1a83..61b182b 100644
--- a/drivers/video/console/bitblit.c
+++ b/drivers/video/console/bitblit.c
@@ -162,7 +162,7 @@
image.depth = 1;
if (attribute) {
- buf = kmalloc(cellsize, GFP_KERNEL);
+ buf = kmalloc(cellsize, GFP_ATOMIC);
if (!buf)
return;
}
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 88e9204..fdefa8f 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -449,7 +449,7 @@
while ((options = strsep(&this_opt, ",")) != NULL) {
if (!strncmp(options, "font:", 5))
- strcpy(fontname, options + 5);
+ strlcpy(fontname, options + 5, sizeof(fontname));
if (!strncmp(options, "scrollback:", 11)) {
options += 11;
diff --git a/drivers/video/mb862xx/mb862xxfbdrv.c b/drivers/video/mb862xx/mb862xxfbdrv.c
index 00ce1f3..57d940b 100644
--- a/drivers/video/mb862xx/mb862xxfbdrv.c
+++ b/drivers/video/mb862xx/mb862xxfbdrv.c
@@ -328,6 +328,8 @@
case MB862XX_L1_SET_CFG:
if (copy_from_user(l1_cfg, argp, sizeof(*l1_cfg)))
return -EFAULT;
+ if (l1_cfg->dh == 0 || l1_cfg->dw == 0)
+ return -EINVAL;
if ((l1_cfg->sw >= l1_cfg->dw) && (l1_cfg->sh >= l1_cfg->dh)) {
/* downscaling */
outreg(cap, GC_CAP_CSC,
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index 5d31699..f43bfe1 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -105,6 +105,20 @@
sdi_config_lcd_manager(dssdev);
+ /*
+ * LCLK and PCLK divisors are located in shadow registers, and we
+ * normally write them to DISPC registers when enabling the output.
+ * However, SDI uses pck-free as source clock for its PLL, and pck-free
+ * is affected by the divisors. And as we need the PLL before enabling
+ * the output, we need to write the divisors early.
+ *
+ * It seems just writing to the DISPC register is enough, and we don't
+ * need to care about the shadow register mechanism for pck-free. The
+ * exact reason for this is unknown.
+ */
+ dispc_mgr_set_clock_div(dssdev->manager->id,
+ &sdi.mgr_config.clock_info);
+
dss_sdi_init(dssdev->phy.sdi.datapairs);
r = dss_sdi_enable();
if (r)
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 08ec1a7..fc671d3 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -1192,7 +1192,7 @@
break;
if (regno < 16) {
- u16 pal;
+ u32 pal;
pal = ((red >> (16 - var->red.length)) <<
var->red.offset) |
((green >> (16 - var->green.length)) <<
diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c
index 3fe82d0..5b06d31 100644
--- a/drivers/watchdog/booke_wdt.c
+++ b/drivers/watchdog/booke_wdt.c
@@ -166,18 +166,17 @@
switch (cmd) {
case WDIOC_GETSUPPORT:
- if (copy_to_user((void *)arg, &ident, sizeof(ident)))
- return -EFAULT;
+ return copy_to_user(p, &ident, sizeof(ident)) ? -EFAULT : 0;
case WDIOC_GETSTATUS:
return put_user(0, p);
case WDIOC_GETBOOTSTATUS:
/* XXX: something is clearing TSR */
tmp = mfspr(SPRN_TSR) & TSR_WRS(3);
/* returns CARDRESET if last reset was caused by the WDT */
- return (tmp ? WDIOF_CARDRESET : 0);
+ return put_user((tmp ? WDIOF_CARDRESET : 0), p);
case WDIOC_SETOPTIONS:
if (get_user(tmp, p))
- return -EINVAL;
+ return -EFAULT;
if (tmp == WDIOS_ENABLECARD) {
booke_wdt_ping();
break;
diff --git a/drivers/watchdog/da9052_wdt.c b/drivers/watchdog/da9052_wdt.c
index 3f75129..f7abbae 100644
--- a/drivers/watchdog/da9052_wdt.c
+++ b/drivers/watchdog/da9052_wdt.c
@@ -21,7 +21,6 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
-#include <linux/delay.h>
#include <linux/mfd/da9052/reg.h>
#include <linux/mfd/da9052/da9052.h>
diff --git a/drivers/xen/platform-pci.c b/drivers/xen/platform-pci.c
index d4c50d6..97ca359 100644
--- a/drivers/xen/platform-pci.c
+++ b/drivers/xen/platform-pci.c
@@ -101,19 +101,6 @@
return 0;
}
-static void __devinit prepare_shared_info(void)
-{
-#ifdef CONFIG_KEXEC
- unsigned long addr;
- struct shared_info *hvm_shared_info;
-
- addr = alloc_xen_mmio(PAGE_SIZE);
- hvm_shared_info = ioremap(addr, PAGE_SIZE);
- memset(hvm_shared_info, 0, PAGE_SIZE);
- xen_hvm_prepare_kexec(hvm_shared_info, addr >> PAGE_SHIFT);
-#endif
-}
-
static int __devinit platform_pci_init(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -151,8 +138,6 @@
platform_mmio = mmio_addr;
platform_mmiolen = mmio_len;
- prepare_shared_info();
-
if (!xen_have_vector_callback) {
ret = xen_allocate_irq(pdev);
if (ret) {
diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
index 1afb4fb..4d51948 100644
--- a/drivers/xen/swiotlb-xen.c
+++ b/drivers/xen/swiotlb-xen.c
@@ -232,7 +232,7 @@
return ret;
if (hwdev && hwdev->coherent_dma_mask)
- dma_mask = hwdev->coherent_dma_mask;
+ dma_mask = dma_alloc_coherent_mask(hwdev, flags);
phys = virt_to_phys(ret);
dev_addr = xen_phys_to_bus(phys);
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c
index 097e536..0334272 100644
--- a/drivers/xen/xen-pciback/pci_stub.c
+++ b/drivers/xen/xen-pciback/pci_stub.c
@@ -353,16 +353,16 @@
if (err)
goto config_release;
- dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n");
- __pci_reset_function_locked(dev);
-
/* We need the device active to save the state. */
dev_dbg(&dev->dev, "save state of device\n");
pci_save_state(dev);
dev_data->pci_saved_state = pci_store_saved_state(dev);
if (!dev_data->pci_saved_state)
dev_err(&dev->dev, "Could not store PCI conf saved state!\n");
-
+ else {
+ dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n");
+ __pci_reset_function_locked(dev);
+ }
/* Now disable the device (this also ensures some private device
* data is setup before we export)
*/
diff --git a/firmware/Makefile b/firmware/Makefile
index 344713b..fdc9ff0 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -40,7 +40,6 @@
bnx2/bnx2-mips-06-6.2.1.fw \
bnx2/bnx2-rv2p-06-6.0.15.fw
fw-shipped-$(CONFIG_CASSINI) += sun/cassini.bin
-fw-shipped-$(CONFIG_COMPUTONE) += intelliport2.bin
fw-shipped-$(CONFIG_CHELSIO_T3) += cxgb3/t3b_psram-1.1.0.bin \
cxgb3/t3c_psram-1.1.0.bin \
cxgb3/t3fw-7.10.0.bin \
diff --git a/firmware/intelliport2.bin.ihex b/firmware/intelliport2.bin.ihex
deleted file mode 100644
index e9cfe8c..0000000
--- a/firmware/intelliport2.bin.ihex
+++ /dev/null
@@ -1,2147 +0,0 @@
-:100000003C4237180201030000000000000000001D
-:10001000576564204465632030312031323A3234F0
-:100020003A33302031393939000000000000000037
-:10003000E96C0F426547694E6E496E47206F462056
-:10004000634F6445CC135A15E8167618041A921BB0
-:10005000201DAE1E3C20CA215823E6247426022807
-:1000600090291E2BAC2C3A2EC82F5631E432723414
-:1000700000368E371C39AA3A383CC63D543FE24020
-:100080007042FE438C451A47A848364AC44B524D2D
-:10009000E04E6E50FC518A531855A6563458C2593A
-:1000A000505BDE5C6C5EFA5F88611663A464326646
-:1000B000C0674E69DC6A6A6CF86D866F1471A27253
-:1000C0003074BE754C776C778C77AC7733DB8ADC19
-:1000D0005333DB250700750A8A1E080183E30CEB06
-:1000E00020903C01750A8A1E080180E3C0EB129043
-:1000F0008A1E0D013C02750680E30CEB049080E340
-:10010000C053508B1EBA138EDBE86A65558BEC53D7
-:100110001E2BC08ED88B5E04C1E304035E06D1E3C0
-:100120002E8B9F44008D472A1E5A1F5B5DC3558B43
-:10013000EC531E2BC08ED88B5E04C1E304035E0615
-:10014000D1E32E8B9F44008D47341E5A1F5B5DC345
-:10015000FB558BEC53515256571E061E0733C08E6B
-:10016000D88B5E04268A47592503008BF0D1E62EF2
-:100170008BB4C400C1E0042602471AD1E08BE82EFC
-:100180008BAE4400892C268A471C88440F268A4758
-:100190001D884410268A471E884411268A471F88D6
-:1001A0004412268A4720884413268A472388441409
-:1001B000268A4724884415268A475A88440E33C025
-:1001C00089440689440888440B88440AB021B464F1
-:1001D000894404894402B05588440D88440CE86A77
-:1001E00000725BE8C900E8C110894408807C0F01F7
-:1001F0007429E82B02E87F02807C0F03741DE8A9B4
-:10020000108BF82B44083DA00F7210897C0833C076
-:1002100087440685C07504C6440AFF8A440A84C020
-:10022000750BB80800E86A4AE8A90173BFE84F01F6
-:100230008166487FFF83667ABFB002E8040E8A4475
-:100240000A98071F5F5E5A595B5DC3814E48800064
-:10025000B040E83D4AE88940732AE84D108BD8B099
-:1002600005E82E4AF6462702751AE83D102BC33DD5
-:10027000581B72EB8166487FFFB002E8C40DC6448C
-:100280000A01F9C3834E7A40F8C3FBB001E8024A81
-:10029000FAE8991EE40A84C075F0B04EE60AFBB095
-:1002A00001E8EE49FAE8851EE40A84C075F0C3FA55
-:1002B000E87A1EE4EC884416E4E4884417E4F888FD
-:1002C0004418E4F0884419E41088441AE41288447D
-:1002D0001BE41488441CE43488441DE43688441E1E
-:1002E000E4D824018AE0E4DA24020AC488441F8A9C
-:1002F0004410E8CD1F8A4411E835218A4412E88968
-:10030000218A4413E84321C686A10000E414241086
-:10031000E614E412243DE6128A44153C01721E776D
-:1003200016B011E634B013E636E4140C10E614E40B
-:10033000120C40E612EB06E4120C02E6128A440F9D
-:100340003C0174063C02740AEB0EE4120C08E6123F
-:10035000EB06E4120C10E612E82FFF8A44143C026C
-:100360007508B05588440C88440DB021B4648944A4
-:1003700004894402E40C0C10E60CE8ED39FBC3E8F8
-:100380005F3F7308FBB00AE80849EBF3FAE89D1DEC
-:100390008A64168A441789869400E6E48AC4E6ECE7
-:1003A0008A64188A441989869600E6F08AC4E6F8B9
-:1003B0008A441AE6108A441BE6128A441CE6148A10
-:1003C000441DE6348A441EE6368A441FE6D8E6DA3F
-:1003D000E9B7FE90FA8A440EE6FEE402A80175052C
-:1003E00033C0FBF8C333C0E400FBF9C38A64148054
-:1003F000FC02742BFEC0FEC780FF4E721C74098085
-:10040000FF507308B00AEB17B00DEB1302DC32FF9C
-:1004100080FB7F7C02B3218AC33C7F7C02B021C376
-:10042000FA807C0B047602FBC38B46243D080072E5
-:10043000F68E46028B7E228A440C8B5C02AAE8ABC5
-:10044000FFAAE8A7FFAAE8A3FFAAE89FFF88440C39
-:10045000895C0280440B04897E22836E24048346D7
-:100460001A04807E26027406806626FDFBC360B0F7
-:10047000FDE8023F61FBC3FA807C0F037509C644A7
-:100480000B00E8E538FBC3C47E148B4E3A85C97572
-:1004900035268B0D4747E3EA3B7E047622B80200FF
-:1004A00039462E7707C7462E0000EB138B5E2C894A
-:1004B0005E0426C70700004343895E2C29462E852B
-:1004C000C978CE894E3A8A440D8B5C04268A25472A
-:1004D0003AC47516FE4C0BFF4406E80FFFE2ED88A8
-:1004E000440D895C04894E3AEBA7C6440AFEE879BC
-:1004F00038FBC390E8B30D8AE88A0ECB13B3078AA2
-:10050000C1EEEB00EC3AC1750902CDFECB75F0EB04
-:100510000C90880ECB138AE8BBFFFFF9C3880ECB83
-:1005200013F8C390BB3F3F8A8E9E00BAFE00EC8A50
-:10053000E832C122C37502F8C3F9C390E8E5FF733E
-:1005400001C3BAD000BB03038A8E9F00EC8AE83255
-:10055000C122C37502F8C3F9C39033C08ED88EC0D0
-:10056000803EC813007507B00AE82647EBF2FB335C
-:10057000DB8A1EC913434383FB7E760733DBB0025D
-:10058000E80F472E8BAF4400837E080074E7881E77
-:10059000C913B002E8FB46FAF7463840007414E885
-:1005A000961BE87FFF721C33D28A969F0083C20E8F
-:1005B000EB0C90E8771BE883FF7208BA4800E83339
-:1005C000FF73AB23CB898E9A0089969C00FE86B57B
-:1005D00000C606C81300B00AE8670AFBEB891018CA
-:1005E000082833C0A005018AC824407524C7067CAA
-:1005F000128E45C70642120100C606541202B00808
-:10060000F6C1017402B004A34612A24C12A29412C5
-:10061000C3C7067C12B645A00F0184C0750E6A00E0
-:100620001FC60693121E9C0EE8B10C90C70644121A
-:100630000100A342128BD8C1E304881E9412BEE2CB
-:10064000052BF08BC833DB8BFB2EAC888548128AD8
-:10065000D80C05E6FE8AE0EB00E4FE32C4A83F7445
-:1006600003E99E00E400888550128AE02430BA1025
-:10067000FF3C30741280FC04740ABA0403F60608C6
-:1006800001FE7403BA080F88954C1202FA32C0F6C4
-:10069000C4087402B001888558128AC43C35745B62
-:1006A0003C3674573C3474533C04744F3C14744BC4
-:1006B0003C157447A8407425C685541204D1E7B48C
-:1006C000038AC389855C128AC38AE380CC01898549
-:1006D0006412D1EF47E203EB1A90E96CFFC6855430
-:1006E0001202D1E78AE68AC30C0489855C12D1EF35
-:1006F00047E2E733C08AC7A34612C3C68554120631
-:10070000EBBBC68554120033C08885501288854CD7
-:100710001288855812EBA6C7462602128B461E8900
-:1007200046008946228B4620894624C7461A000087
-:10073000C3C7463C8000C7463801001E568B763042
-:100740008976048976148E5E0633C089044646890C
-:10075000762C89463A8B4632484889462E5E1FC31E
-:1007600033C089464889464AC74646AE0189464E47
-:100770008B46448946508B4642894640894608C389
-:1007800033C0894676894678C7467A1000561E8B54
-:10079000767089761089760C8E5E12C70400008B05
-:1007A00046728946741F5EC3895618895602895657
-:1007B0000689560A89560E8956128956168BD84BC9
-:1007C0004BC1E302BF0200897E1E03FB897E30031A
-:1007D000FB897E4203FB897E7083EB08895E20895A
-:1007E0005E32895E44895E7250E82BFFE871FFE853
-:1007F0003FFFE88BFF58C3B83075C1E8040E5B03B8
-:10080000C3A3BA13833E4212007407803E941200C1
-:10081000750E6A001FC60693121E9C0EE8BD0A9054
-:10082000B8307AC1E80440A3C0132B061201F7D8F0
-:1008300033D28BCA8A0E9412F7F13D8000770E6A8C
-:10084000001FC6069312259C0EE8900A90483DFFB3
-:10085000077203B8FF07A3C21333C98A0E94123379
-:10086000F6B800092E8BAC440089464C404646E25F
-:10087000F38A0E941233F68B16C013A1C2132E8B7B
-:10088000AC4400E822FF03D04646E2F2C333C02E58
-:100890008BAD44008946084747E2F4C35133C00A90
-:1008A000C22E8BAD440089869E00814E38002047C1
-:1008B00047FEC480FC04720432E4FEC0E2E35983C4
-:1008C000E9107405F7D9E8C4FFC35133C00AC22E3A
-:1008D0008BAD440089869E00834E3840474780C4D4
-:1008E00010790432E4FEC0E2E65983E9107405F79A
-:1008F000D9E899FFC3E8D2FFC38D089C08CA08F560
-:10090000088B0E421233F6515633DB8BCB8A944858
-:10091000128A8C4C128A9C54128BFEC1E70585DB2F
-:100920007502B1102EFF97F9085E5946E2D9C3014E
-:10093000CC03D000E802D000E801D000E800D000ED
-:10094000E804D0A8DA00DC00DE01D803CC03CC0335
-:10095000CC04D0A8DA20DC00DE03CC03CC03CC002E
-:10096000D803CC03CC03CC03CC03CC03CC03CC0303
-:10097000CC03CC03CC03CC03CC03CC03CC03CC03FF
-:10098000CC04D000DA20DC03DE01D803CC03CC0396
-:10099000CC03CC00D800CC00D0000056521E0E1F55
-:1009A000BE2F0933D2FCAD85C0740D8AD4EEAD855F
-:1009B000C074058AD4EEEBEE1F5A5EC3E48084C097
-:1009C00074167814B027E6FCB011E634E4FC3C273A
-:1009D0007506E4117502F8C3F9C383C206B0BFEE11
-:1009E00083EA02B010EE8886AF00B01183C204EE35
-:1009F00083C202EEB01383C202EE83C202EE2EA1C6
-:100A00004C2D8986940083EA0EEE83C2028AC4EEDE
-:100A100083C204B003EE8886A80083EA0432C0EEE5
-:100A200083C202B089EE8886A6000C06EEB040B400
-:100A30003889461CC74636380083C20432C0EE8867
-:100A400086A700C383C206B0BFEE83EA02EC3A86F3
-:100A5000AF00752483C204EC3C11751C83C206EC04
-:100A60003C13751483EA088A86A800EE83EA02EC38
-:100A700024C03CC07502F8C3F9C333C98BD18BF1D4
-:100A80008A0E9412C1E9022E8BAC4400F74638005E
-:100A900020740E8A869E00E6FE32C0E68042E8FAA6
-:100AA000FE83C608E2E185D27403E80508C333C9B2
-:100AB0008BF18A0E94122E8BAC4400F7463840001E
-:100AC0007406E87316E812FF4646E2EAC333C98BA0
-:100AD000F18A0E9412C1E9022E8BAC4400F746381D
-:100AE00000207416E84616E8D2FE730E6A001FC690
-:100AF0000693121C9C0EE8E3079083C608E2D9C354
-:100B000033C98BF18A0E94122E8BAC4400F7463811
-:100B100040007416E82116E82AFF730E6A001FC60B
-:100B20000693121C9C0EE8B307904646E2DAC30C0B
-:100B300000001000131200001400283C001B3E00AF
-:100B4000002A00002C0000420014D80000DA000047
-:100B50003400113600133800113A001300005650CB
-:100B600052BE2F0B2EAD85C07406922EACEEEBF468
-:100B70005A585EC3532EA16022E6E4E6F08AC4E62A
-:100B8000ECE6F8E8D8FFB04BE610B050E612B0380B
-:100B9000E614E8AE15B046E60AE8A715B01AE60A6C
-:100BA000E8A015B022E60AE89915E8FD068BD8E41E
-:100BB00016A8047518E8F2062BC33D320072F06ADD
-:100BC000001FC6069312239C0EE8100790E8DA0671
-:100BD0002BC33D2400771BB031E6FC565155B910AC
-:100BE000002E8BAC4400814E3880004646E2F25D18
-:100BF000595EE869FFE84B15B046E60AE844155B24
-:100C0000C333F68B0E42122E8BAC4400F7463800ED
-:100C1000207406E81715E85BFF83C620E2E9C38B62
-:100C2000C20504008946282EA14C2D89868E008994
-:100C300086900089869200C686A3000AC686C300F5
-:100C4000035283C2048A86A6000C06EE5A83C202AF
-:100C5000B005EE8886A500C3E803FFE8E514B042BE
-:100C6000E60AF74638800074062EA19C22EB042E7B
-:100C7000A16C22C7461C0C008986940089869600C8
-:100C800089868E008986900089869200E6F0E6E4E7
-:100C90008AC4E6F8E6ECC686C30003E8A514B01AD9
-:100CA000E60AB0108886A500E60CC333C98BF18A2A
-:100CB0000E94122E8BAC4400F7463840007406E8C0
-:100CC0007614E85AFF4646E2EAC333C98BF18A0E2E
-:100CD00094122E8BAC4400F7463800207406E84C82
-:100CE00014E874FF4646E2EAC390833E441200755E
-:100CF00014B001BA0601EE2AC0EEB002EEB004EE66
-:100D0000B80002EB0FBA0601B040EEB801008A0E3F
-:100D10000E01D3E0A38812C3A18812A384122D2050
-:100D200000A38A122D2000A38212C706861220007B
-:100D3000C70680123200C3833E44120074768B0EC5
-:100D4000421233F68AA4541284E4745F8A844812EF
-:100D50000C04E6FEF6C4047425B01BBA0000EEEBEA
-:100D6000002AC0BA0200EEEB00B003EEEB0032C086
-:100D7000BA0200EEEB00BA0000B000EEEB2DB01F9F
-:100D8000BA0000EEEB002AC0BA0200EEEB00B0039E
-:100D9000EEEB00D1E68A845D12D1EEF6D0BA020005
-:100DA000EEEB00BA0000B00AEEEB00E404EB00E466
-:100DB0000446E290C390B81400BA3EFFEFB80600B4
-:100DC000BA32FFEFB80F00BA34FFEFBA36FFEF8345
-:100DD0003E4412007516B81100BA38FFEFB8120081
-:100DE000BA3AFFEFB81B00BA3CFFEFC3B81100BA24
-:100DF00038FFEFB81200BA3AFFEFB81B00BA3CFF59
-:100E0000EFC3B8FC00BA28FFEFFB833E4412007426
-:100E100007B8CC00BA28FFEFC300FFFF202428FF4B
-:100E20002CFFFF303438FFFF3C903C0F770EBB198E
-:100E30000E2ED73CFF74058AD8F8C3902ADBF9C37D
-:100E4000833E4412007427A00601802606013080EC
-:100E50003E0601307518B90200BFC413BA0601EC92
-:100E6000A82075F8BA0401EDABE2F1EB1690B904D5
-:100E700000BFC413BA0601ECA82075F8BA0401EC4F
-:100E8000AAE2F1FA90BEC413AD80E43F80FC027484
-:100E90000E6A001FC60693120A9C0EE83E0490AD2F
-:100EA0003C0F75ED8AC4E881FF72E6881E1A01C600
-:100EB000068E1200B0000A061A01BA0001EEC6063C
-:100EC0008F1240833E4412007506B80C00EB04906C
-:100ED000B84C00BA28FFEFC3833E4412007501C32B
-:100EE000A150120B0652120AC4A80874F2A00F01F6
-:100EF0002AE450FF36BA131FE8505683C4026A0032
-:100F00001F33C0A3BC13A00F01A3BE138B1EBC13C1
-:100F10008A875012F687501208740D24078AE0BEA3
-:100F2000CC00A0BC13E8943DFF06BC13FF0EBE131B
-:100F300075DAC3901E33C08ED8B001E8543D1FC38C
-:100F400033C98BF18A0E94122E8BAC4400C74662D3
-:100F50003844C7467CFC3BC7467EE23BC7868000E0
-:100F6000EC3CE8AB16C686C00011837E080074070F
-:100F70005156E833335E594646E2CDC333C98BF14F
-:100F80008BF98A0E9412C1E902E3132E8BAC440054
-:100F90008A869E0088856C1283C60847E2EDC3FAF4
-:100FA000FCB0C0BA0001EE33C08ED88EC08ED0BF68
-:100FB0001601B9CC772BCFD1E9F3ABBC4012E8D9FD
-:100FC00002E8703CBECC0FE8F23CF49033C08ED8FF
-:100FD0008EC08ED0F6060A0180740BBE3555E8DB54
-:100FE0003CB001E8AC3CE8B300E8F6F5E808F8E806
-:100FF0000FF9E885FAE8B6FAE8EFFCE8C210E80372
-:101000003CE8B2FDE830FDE85402C6068F12C0E8A5
-:10101000BBFAE8EBFAE8E9FBE8AFFCE88DFCE81F77
-:10102000FFE858FFE8DBFDE816FE33C0BE5A05E8CE
-:101030008A3CE8A3FEE8E0FCFBBEA444E87D3CE972
-:10104000CA2D56988BF08B425285C07527C74252E5
-:10105000010053368B9C2C01F6C301750C36896850
-:10106000523689AC2C015B5EC33689AC2C013689C3
-:10107000AC1C015B5EC356988BF033ED368B841C41
-:1010800001A80175158BE833C08742523689841C4C
-:1010900001A80174053689842C015EC3565133F6CC
-:1010A000B80100B9080089841C0189842C014646D6
-:1010B000E2F4595EC390BB01008BE8FF4E6E740AE8
-:1010C0008BDD8B4658A80174F0C38B4648A90800F5
-:1010D0007445F7463840007427E85C1080C2068AE1
-:1010E00086A80024BF8886A800EE60B0FEE886329D
-:1010F00061B002E84CFF8B464824F7894648EB175D
-:10110000E82A10814E2600408A86A5000C028886B7
-:10111000A500E60C8B4648A904007414B002E8212F
-:10112000FF8B464824FB89464860B0DFE8473261C0
-:1011300033C0874658F6C301750B36894758A80156
-:10114000750DE974FFA32201A8017503E96AFF89FF
-:101150001E3201C3BB01008BE8F74638400074150E
-:10116000E8D50F80C20AECA840750A8BDD8B465685
-:10117000A80174E3C38B462680E4FE80CC02894636
-:1011800026B002E8BCFE33C0874656F6C301750A96
-:1011900036894756A801750BEBBDA32001A8017540
-:1011A00002EBB4891E3001C3601E062BC08ED8A08E
-:1011B000901284C07549A12201A8017503E8F6FECA
-:1011C000A12001A8017503E88AFFA1AC13487805A6
-:1011D0007445A3AC13A1AE134878057451A3AE13A4
-:1011E000A1B0134878057463A3B013A17E124078B0
-:1011F00003A37E12B80080BA22FFEF071F61CFA0C1
-:101200009112403C02720B33C0A29112FF167C1265
-:10121000EBA4A29112EB9FA08E1232068F12A28E27
-:10122000120A061A01BA0001EEB82C01EBA4833EA3
-:101230008412107211BA28FFED0C81EFE85337BA0F
-:1012400028FFED247EEFB80400EB92C6068D120154
-:10125000E83F37C6068D1200A1B213EB8B908A1EB1
-:101260000B012AFF6BC319BA62FFEFB80A00BA601C
-:10127000FFEFB801E0BA66FFEFB8FFFFBA52FFEF29
-:10128000B809C0BA56FFEFC706AC132C01C706AEAB
-:10129000130400C606911200C3908A1E0B012AFF98
-:1012A0006BC305D1E8A31801C39052BA50FFED5AA1
-:1012B000C39053518B1E1801B9320590E2FE4B7555
-:1012C000F7595BC3B080BA00010A061A01EEC39059
-:1012D000B040EBF2B0C0EBEEB000EBEAFA60061EF5
-:1012E000162BDB8EDB2EA1BA4C2EA3924CA09312B0
-:1012F000988BE889262D7A803ECA13007403E96B27
-:1013000042E8C0FFE8ABFFE8A8FFB020C606901295
-:1013100000FF167C128BFD83FF0A7211E8B9FFE80B
-:1013200090FFE8ABFFE88AFF83EF0AEBEA0BFF745C
-:101330000FE8A4FFE87BFFE89AFFE875FF4F75F11F
-:10134000E895FFE86CFFEBB98A86A50024FDEE88DE
-:1013500086A500C38A86A6000C02EEC38B7638F7FA
-:10136000C6010074EF8B4E368B462E3BC173028B49
-:10137000C82BC189462E014E34C47E0426010D8B34
-:101380007E2C83EA04F36C8EC1897E2C3B463C7232
-:1013900012F7C62000750B83CE20897638B000E89E
-:1013A000A0FCC3F7C60400741B8BD883CE108976CB
-:1013B000388A86A70024FE8886A70083C208EE83A9
-:1013C000EA088BC33D40007201C3814E380004839C
-:1013D000C2028A86A50024FA8886A500EEC38A8602
-:1013E000A6000C02EEC3F74638010074F18B4E2EB6
-:1013F00032DB8ABEA30083C206C476048B7E2C83B4
-:10140000F908722CECA80174168AE083EA0AEC83CE
-:10141000C20A84E77551AAFEC34983F90873E5320D
-:10142000FF26011C015E34897604894E2E897E2CAC
-:101430003B4E3C7211F64638207401C3834E38206F
-:10144000B000E8FDFBC3F64638047415834E38102F
-:101450008A86A70024FE8886A70083EA02EE83C25C
-:10146000023D4000725DC332FF26031C85DB740918
-:1014700026891C8BF74747494980E41E80CCC0264B
-:101480008904F6C41074278B7638F7C60010740BE5
-:1014900050FE86B200B00AE8A8FB58F7C6000174F7
-:1014A0000DE882268B76388B4E2E8B7E04AB8BF725
-:1014B00033C0AB32DB8ABEA300494983F9087217F7
-:1014C000E941FF814E38000483C2F88A86A50024D2
-:1014D000FA8886A500EEC3E945FF83C208EC88863A
-:1014E000AA00C0E8048AE08AC88686A90032E08B98
-:1014F0005E3E84E3744F8AC18B4E26F6C504740C9D
-:10150000A808740580E1BFEB0380C940F6C50874E4
-:101510000CA802740580E17FEB0380C980884E2609
-:101520008BF08A86A50084C97408A802741524FD6E
-:10153000EB06A802750D0C028886A50083EA0AEE68
-:1015400083C20A8BC684E77501C3C686BA0001B0A0
-:101550000EE8EEFAF74638000274EE837E2E06722D
-:10156000E88AA6AA00C45E048B7E2CB0FFAAB00253
-:10157000AB26830703836E2E03897E2CF646382024
-:101580007401C3834E3820B000E8B6FAC39083EAF2
-:1015900008E9B4FD83C2068B5E26F6C3C075EF8BE7
-:1015A0004E1CEC8886A40083EA0AA82075028ACD26
-:1015B00032ED8B461A3BC87318014E2A2BC189465F
-:1015C0001AC57600F36E8ED98976003D2000723000
-:1015D000C385C074318BC801462AC57600F36E8E70
-:1015E000D980CB02895E26E832F1F6C701751683F1
-:1015F000C202E853FDF6C710750BB002E843FAC308
-:10160000F6C70174F0C380CB02895E26F6C7017469
-:10161000DE83C202E831FDF686A40040740B80E749
-:10162000FE80CF02895E26EBCCB004E814FAC3C07A
-:10163000C2C8CAC4C6CCCED0D2D8DAD4D6DCDE90EA
-:10164000E90E01E4C48AE0E4C48BD083F90872F0A7
-:1016500026833F0074048BDF49498BFB8ADE83E3DA
-:101660000F2E8AA72F16ABF6C4107424F7C60010ED
-:10167000740B50FE86B200B00AE8C6F958F7C600EF
-:1016800001740DE8A0248B76388B4E2E8B7E04AB34
-:10169000897E0433C0AB4949894E2E897E2C8BC18B
-:1016A000EB4E90EB9E90E4D684C07963E6D08AC876
-:1016B00025030003D8D1E32E8BAF4400888EAE0003
-:1016C0008B4E2EC45E048B7E2C8B7638E4862407EA
-:1016D0003C0375CFE41C913BC173028BC82BC189BD
-:1016E000462E014E3426010FBAC400F36C897E2CBD
-:1016F0003B463C721CF7C62000750B83CE208976D2
-:1017000038B000E83CF98A86AE00243FE6D6C3F93B
-:10171000C3F7C60A007435F7C61000752F83CE10C4
-:10172000897638F7C60200740E50E4D824FEE6D855
-:1017300058F7C6080074155051B9E803E40A84C08C
-:10174000E0FA84C07504B024E60A59583D4000739D
-:10175000B58A86A50024EF8886A500E60C81CE1008
-:1017600004897638EBA00008040C0109050D020A73
-:10177000060E030B070F004080C02060A0E0105051
-:1017800090D03070B0F0E4D2E6D08AC825030003D0
-:10179000D8D1E32E8BAF4400888EAE00E4D8C0E8E9
-:1017A000048BD82E8A8766178AE08AC88686A900A5
-:1017B00032E0E4988B5E3E84E374548AC18B4E26FB
-:1017C000F6C504740CA808740580E1BFEB0380C95A
-:1017D00040F6C508740CA802740580E17FEB038015
-:1017E000C980884E268BF08A86A500F6C1FD740854
-:1017F000A806741924F9EB0FA8067511F6C5017532
-:10180000040C04EB020C028886A500E60C8BC6844F
-:10181000E775098A86AE00243FE6D2C3C686BA00C1
-:1018200001B00EE81CF8F74638000274E6837E2EFD
-:101830000672E08A86A9008AE08686AA008AC832F3
-:10184000C480C90B22C1C0E4040AE0C45E048B7EDC
-:101850002CB0FFAAB002AB26830703836E2E038948
-:101860007E2CF646382075AB834E3820B000E8D188
-:10187000F7EBA090E41224DFE61281E3FE9F895E7D
-:1018800026836648F7EB7390F6C72075E7E4120CE1
-:1018900020E61232C0E6C6B083E6C680CF20895E5D
-:1018A000268A86A5000C028886A500E60CEB7490BB
-:1018B000F6C74075D3E4120C20E61232C0E6C6B07B
-:1018C00081E6C680E7DF80CB01895E26B006E8713D
-:1018D000F7908A86A50024F9E60C8886A500EB43DC
-:1018E000E4D4E6D08BF825030003D8D1E32E8BAFE8
-:1018F00044008B5E26F6C76075B6F6C3C075D3BAD2
-:10190000C6008B4E1C8B461A3BC8731E014E2A2BF9
-:10191000C189461AC57600F36E8ED98976003D20BE
-:1019200000723D8BC7243FE6D4C385C074398BC891
-:1019300001462AC57600F36E8ED983CB02895E26D6
-:10194000E8D9EDF6C70175398A86A50024F9E60CB9
-:101950008886A500F6C71075CAB002E8E4F6EBC3A6
-:10196000F6C70174EFEBBCF6C70174DC8A86A500EC
-:10197000A802741181E3FFFE81CB0002895E26EB91
-:10198000C78A86A50024FB0C02E60C8886A500EB1E
-:101990009290FDF7DF7FFEFBEFBF0004000405041B
-:1019A00005040104000405040504060406040504F6
-:1019B00005040604060405040504020400040504E5
-:1019C00005040104000405040504060406040504D6
-:1019D00005040604060405040504070407040504B9
-:1019E00005040704070405040504060406040504A9
-:1019F0000504060406040504050407040704050499
-:101A00000504070407040504050406040604050488
-:101A10000504060406040504050403040004050483
-:101A20000504010400040504050406040604050475
-:101A30000504060406040504050402040004050464
-:101A40000504010400040504050406040604050455
-:101A50000504060406040504050407040704050438
-:101A60000504070407040504050406040604050428
-:101A70000504060406040504050407040704050418
-:101A80000504070407040504050406040604050408
-:101A90000504060406040504050433DB8AD88A8796
-:101AA0006C12E6FEC1E302E4CEA8047509A8027434
-:101AB00003E92CFEF9C35053E8CBFC5B58A8027431
-:101AC00003E91CFEF8C333DB8AD88A876C12E6FE72
-:101AD000C1E302E9D0FB9A1AC61A00000200040012
-:101AE00002000600020004000200080002000400D8
-:101AF000020006000200040002000A0002000400C6
-:101B000002000600020004000200080002000400B7
-:101B1000020006000200040002000C0002000400A3
-:101B20000200060002000400020008000200040097
-:101B3000020006000200040002000A000200040085
-:101B40000200060002000400020008000200040077
-:101B5000020006000200040002000E000200040061
-:101B60000200060002000400020008000200040057
-:101B7000020006000200040002000A000200040045
-:101B80000200060002000400020008000200040037
-:101B9000020006000200040002000C000200040023
-:101BA0000200060002000400020008000200040017
-:101BB000020006000200040002000A000200040005
-:101BC00002000600020004000200080002000400F7
-:101BD00002000600020004000200C390DA1494150B
-:101BE0005C13E613DA1BDA1BE613DA1B8B94641220
-:101BF000C1E604A80174355033C08AC2E6FEE4A0F1
-:101C000085C074278BD82E8A9FDA1A52562E8BA83D
-:101C100044008B5628ECA801750D8886AD00240E73
-:101C20008AD82EFF97DC1B5E5AEBCD58A80274367B
-:101C300083C61033C08AC6E6FEE4A085C074278B35
-:101C4000D82E8A9FDA1A52562E8BA844008B56281B
-:101C5000ECA801750D8886AD00240E8AD82EFF975A
-:101C6000DC1B5E5AEBCDC39032E48BD88BD02E8A2E
-:101C70009F9A192E2297921956528AC3240303C69B
-:101C800080E304D0EB2EFF97D61A585EA955007555
-:101C9000D9C3601E062BC08ED8A15C12E6FEE400FC
-:101CA00022C4740833F6E8BFFFEBEE90E40407E4C7
-:101CB000041FB80080BA22FFEF61CF90601E062B90
-:101CC000C08ED8A15E12E6FEE40022C47408BE04F1
-:101CD00000E894FFEBEDE40407E4041FB80080BAC9
-:101CE00022FFEF61CF90601E062BC08ED8A15C1240
-:101CF000E6FEE40022C4741833F6E86BFFA160121C
-:101D0000E6FEE40022C474E5BE0800E85AFFEBDDFD
-:101D1000A16012E6FEE40022C475EDE40407E404C9
-:101D2000A15C12E6FEE4041FE404B80080BA22FFBE
-:101D3000EF61CF90601E062BC08ED8A15E12E6FE2A
-:101D4000E40022C47419BE0400E81CFFA16212E67C
-:101D5000FEE40022C474E4BE0C00E80BFFEBDCA13F
-:101D60006212E6FEE40022C475EDE40407E404A177
-:101D70005E12E6FEE4041FE404B80080BA22FFEF1E
-:101D800061CF601E062BC08ED8A15C12E6FEE480F7
-:101D900084C4740833F6E853FEEBEE90B80080BAC2
-:101DA00022FFEF071F61CF90601E062BC08ED8A1C7
-:101DB0005E12E6FEE48084C47408BE0200E82CFED5
-:101DC000EBEDB80080BA22FFEF071F61CF90601ED5
-:101DD000062BC08ED8A16012E6FEE48084C474088D
-:101DE000BE0400E806FEEBEDB80080BA22FFEF0764
-:101DF0001F61CF90601E062BC08ED8A16212E6FE36
-:101E0000E48084C47408BE0600E8E0FDEBEDB80091
-:101E100080BA22FFEF071F61CF90601E062BC08E95
-:101E2000D8A15C12E6FEE40022C4741833F6E83749
-:101E3000FEA16012E6FEE48084C474E5BE0400E8FE
-:101E4000AAFDEBDDA16012E6FEE48084C475EDA17D
-:101E50005C12E6FEE40407E4041FB80080BA22FF27
-:101E6000EF61CF90601E062BC08ED8A15E12E6FEF9
-:101E7000E40022C47419BE0400E8ECFDA16212E67D
-:101E8000FEE48084C474E4BE0600E85FFDEBDCA1E0
-:101E90006212E6FEE48084C475EDA15E12E6FEE403
-:101EA0000407E4041FB80080BA22FFEF61CF601E70
-:101EB000062BC08ED8A15C12E6FEE48084C47418A0
-:101EC00033F6E827FDA16012E6FEE40022C474E5C3
-:101ED000BE0800E892FDEBDDA16012E6FEE4002200
-:101EE000C475EDE40407E4041FB80080BA22FFEFD4
-:101EF00061CF601E062BC08ED8A15E12E6FEE48084
-:101F000084C47419BE0200E8E2FCA16212E6FEE499
-:101F10000022C474E4BE0C00E84DFDEBDCA16212AB
-:101F2000E6FEE40022C475EDE40407E4041FB800F3
-:101F300080BA22FFEF61CF90601E062BC08ED8A121
-:101F40005C12E6FEE48084C4741833F6E89DFCA1BC
-:101F50006012E6FEE48084C474E5BE0400E88CFCF4
-:101F6000EBDDA16012E6FEE48084C475ED071FB8C6
-:101F70000080BA22FFEF61CF601E062BC08ED8A171
-:101F80005E12E6FEE48084C47419BE0200E85CFCC4
-:101F9000A16212E6FEE48084C474E4BE0600E84B4D
-:101FA000FCEBDCA16212E6FEE48084C475ED071F41
-:101FB000B80080BA22FFEF61CF90601E062BC08E62
-:101FC000D8902AC0E6FEE4CEA801741433DBE8D52D
-:101FD000F6EBEF90B80080BA22FFEF071F61CF90B9
-:101FE000F60605010175EDB001E6FEE4CEA8017428
-:101FF000E3BB0400E8AFF6EBC990601E062BC08E71
-:10200000D890FB90FA2AC0E6FEE4CEA802741333FF
-:10201000DBE8CCF8EBECB80080BA22FFEF071F61D9
-:10202000CF90A80474F033DBE85BF7EBD590601E2B
-:10203000062BC08ED890FB90FAB001E6FEE4CEA845
-:10204000027415BB0400E897F8EBEB90B80080BA77
-:1020500022FFEF071F61CF90A80474F0BB0400E8D3
-:1020600024F7EBD26A001FC6069312099C0EE86B98
-:10207000F2906A001FC6069312299C0EE85DF2904A
-:10208000722072207220CE1D921CE61C1A1E722035
-:10209000821DAE1E381F7220821D72207220381FD2
-:1020A000722072207220F41DBC1C341D641E72202C
-:1020B000A81DF21E781F7220A81D72207220781FA2
-:1020C000FCB940008CCBB864202BFFAB93AB93E200
-:1020D000FAC7064C00A811833E4412007520C706BB
-:1020E0003C00084BC7063000BA1FC7063400FA1F71
-:1020F000F6060501017506C70638002E20C3C7067F
-:102100003C00564B33DB8A1E5412C1E302021E56BA
-:10211000122E8B878020A330008A1E5512C1E30245
-:10212000021E57122E8B87A020A33400C38B869EDD
-:1021300000E6FE86C4E6D0C38B869E00E6FE33D260
-:102140008AD4C351B91027E40A909084C07405E280
-:10215000F659F9C359F8C384C0781E518AE88AC871
-:10216000B80100D3E0098698003AAEA00059751076
-:10217000E8A9E5834E2602F9C39889869800EBF01A
-:10218000F8C384C07812518AE08AC8B80100D3E04D
-:1021900059F7D021869800C3C78698000000C383F2
-:1021A000C2048A86A6000C04EE83EA04C3E893FF07
-:1021B0007204B082E60AC38B4626A8FD74118A8693
-:1021C000A500A806740824F98886A500E60CC3F6C5
-:1021D000C401740A8A86A50024FB0C02EB0CA80239
-:1021E000750F8A86A50024FD0C043A86A50075D8D3
-:1021F000C38A86A500EBCFE4D833DB8AD8C0EB04D2
-:102200002E8A9F6617889EA9008B5E2680E33FF684
-:10221000C7047407A810750380CB40F6C70874077D
-:10222000A880750380CB40885E268A86A500F6C309
-:10223000FD740DA806740824F98886A500E60CC371
-:10224000F6C70174040C02EBF0F6C30275E90C0446
-:10225000EBE7C404C4048504590448044104C303DF
-:10226000820341038202570241028201410182003E
-:1022700041004E02AD0157012D002B002700210027
-:102280001600F404F404A3046F045B045104F40383
-:10229000A3035103A3026D025102A3015101A30044
-:1022A00051006202D9016D01380036003100290069
-:1022B0001B005157BF0200EB0F905156BF0100EBBE
-:1022C00007905156BF0300903C197602B017988BC7
-:1022D000F08A82C4002AE48BF083FE187346D1E6AC
-:1022E0002E8B8C5222F74638800074052E8B8C8200
-:1022F00022F7C7020074123B8E9400740C898E94EE
-:10230000008AC5E6EC8AC1E6E4F7C7010074123B17
-:102310008E9600740C898E96008AC5E6F88AC1E60E
-:10232000F05E59C377068B8E8E00EBC58B8E9000C6
-:10233000EBBFD503F6003E0010000400CA043301D1
-:102340004D00140005000103050709000102030404
-:1023500080841E00A02526000000608BF033FF2E35
-:10236000A150232E8B165223BB3223F74638800010
-:10237000740C2EA154232E8B165623BB3C23B90577
-:10238000002E3B31730A4747E2F7B8FFFFEB1D9081
-:10239000D1EF2E8A8D46232AEDD1EAD1D8E2FAF781
-:1023A000F6050200C1E8022E8AA54B232EA358236E
-:1023B000612EA15823C3080020008000000260099C
-:1023C0000800200080000002000800000100020058
-:1023D0000300040052565785C074053D0109760379
-:1023E000B80109BF5B01F7463880007403BFB20132
-:1023F00033F62E3B84B62376044646EBF5F7E72EFC
-:102400008BBCC02303C783D200D1E7F7F72E8AA481
-:10241000CA235F5E5AC3E43E80BEC30003750CF757
-:10242000467A200074050C80E63EC3247FE63EC356
-:1024300024038886C3008AE0E41024FC0AC4E61062
-:10244000808EA10042E8CEFFC390568BF083E60752
-:10245000D1E62EFFA458249068246C2470247424A0
-:102460007824872487248724B400EB0EB4C0EB0AB9
-:10247000B440EB06B420EB02B4A0E410241F0AC45D
-:10248000E610808EA100425EC3903C0277128AE083
-:10249000E41024F3C0E4020AC4E610808EA10042D6
-:1024A000C3908B5E3884C0741F3C02742083CB08B9
-:1024B0008B462E3B463C770CE888FC7207B024E63E
-:1024C0000A83CB10895E38C383E3F7EBF7F7C310B9
-:1024D0000074F5E86DFC72EC8A86C000E638B02323
-:1024E000E60AEBE08B5E388B462E3B463CE4D87721
-:1024F0000B24FE80CB12E6D8895E38C30C0180CB5A
-:1025000002EBF35033DBC1E804250F0F8AD82E8A83
-:102510008766178ADC2E8AA7661709463E58C3507D
-:1025200033DBC1E804250F0F8AD82E8A8766178A05
-:10253000DC2E8AA76617F7D021463E58C38B463E4D
-:1025400033DB8AD80ADC2E8A877617E62C8AE0E409
-:102550002A240F0AC4E62A8A86A50084E4750DA8F9
-:10256000807411247F8886A500E60CC3A8807504BA
-:102570000C80EBF1C31E6033C933D233F68ED98D94
-:10258000BEFD00578B0584C074168BD1428BFE4F65
-:10259000780938A3E40074084F79F788A2E400466C
-:1025A0005F83C7094183F91072D989B6860089967D
-:1025B0008400611FC353C7466600008B4664A94070
-:1025C00000740DB300A980007402B37F889EC1001F
-:1025D00032DBA90200740380CB40A9004074038061
-:1025E000CB02A90080740380CB01A9301E74038044
-:1025F000CBBCA90020740380CB08A904017403801C
-:10260000CB10A90800740380CB20889EC2005BC356
-:102610000651575016078DBEC400B91F0033C0AA1B
-:1026200040E2FC8B86920089868E00898690005855
-:102630005F5907C3E4D8C0E80453250F008BD82E98
-:102640008A8766178886A9005AC30886AC00C686A2
-:10265000BA0001B00EE8EAE9C3AD36A3B413AD3653
-:10266000A3B613AD36A3B81383E90636F706B6133F
-:102670000F00C38A4626F74648800074020C108873
-:1026800086BD0032C0837E1A00750E8B5E4043808B
-:10269000E3FE3B5E0875020C01837E3A00750D1E59
-:1026A000C55E148B1F1F85DB75020C02F7463810C0
-:1026B0000074020C048B5E7AF7C3020074020C08EB
-:1026C000F7C3040074020C10F7C3080074020C2056
-:1026D000F7C3400074020C408886BF00C3906A00B4
-:1026E0001FC60693120D9C0EE8F1EB90B002E6DADD
-:1026F000F8C333C0E6DAF8C3B001E6D8F8C333C094
-:10270000E6D8F8C3B0FFE84EFAE8A1FAF8C3AC493E
-:10271000E8AFFBF8C390AC49E815FDF8C390AC49AD
-:10272000E867FDF8C390AC49E81FFDF8C390AC49D9
-:10273000E634F8C3AC49E636F8C3AC493C02771F2F
-:1027400084C0751DE41424EFE614E412243FE6125D
-:10275000E416A8047409E8EAF97204B018E60AF865
-:10276000C38AE0E4140C10E614E4120CC0F6C401B1
-:102770007402247FE612F8C3AC49E825FDF8C39043
-:10278000B80040E87DFDE8B4FDE8A8FEB001E8B976
-:10279000FEF8C390B80040E885FDE8A0FDF8C390BE
-:1027A000B80010E85DFDE894FDE888FEB008E899FF
-:1027B000FEF8C390B80010E865FDE880FDF8C3900E
-:1027C000B80080E83DFDE874FDE868FEB002E879F5
-:1027D000FEF8C390B80080E845FDE860FDF8C390BE
-:1027E000B80020E81DFDE854FDE848FEB004E859B3
-:1027F000FEF8C390B80020E825FDE840FDF8C3903E
-:10280000AC49E84814E43C24E70AC4E63CF8C39029
-:10281000B8FC3B89467CE43C0C18E63CF8C3E41267
-:102820000C02E612F8C3E41224FDEBF6E8B5FCF85E
-:10283000C390836638FDF8C3AC49A8017406834E83
-:102840007A20EB0483667ADFE8CBFBF8C3908A86B4
-:10285000A5000C0224FB8886A500E60C814E26010B
-:1028600020AC4932E489466E834E48084946F9C394
-:102870008A86A5000C0224FB8886A500E60C814E02
-:10288000260120ACB40AF6E4EBD8E8FA13E43C24C1
-:10289000F80AC4E63CF8C390AD4949894664A901E9
-:1028A00000741B8BD883E3FA751AA90400740FE433
-:1028B0003E0C02E63EB83844894662F8C390E43ED6
-:1028C00024FCEBEFE43E24FCE63EE8E8FCB8AA403A
-:1028D000EBE6E86EF87205B018E60AF8C390AC496A
-:1028E000E8CFF9F8C390AC49E8CFF9F8C390E868AD
-:1028F000FD750632C0E6DAF8C3B002E6DA36A0B4F7
-:102900001324103410E8160136A1B413A901007481
-:1029100005E8FCFEEB0EA90200740432C0EB02B025
-:1029200001E8DEFE36A1B413E8B513E43C24F80A4E
-:10293000C4E63C36A1B413C1E805250100E8FAFE5F
-:1029400036A0B5132410E859FB32C0368A26B513D9
-:10295000F6C4047409FEC0F6C4087402FEC0E8DBC5
-:10296000FD36A1B613250F00E857F936A1B613C1FD
-:10297000E804250300E8B8FA36A1B613C1E8052536
-:102980000200E805FB36A1B613F6C401750432C097
-:10299000EB0980E402D0ECB0022AC4E8ACFA36F6C7
-:1029A00006B713407405E883FEEB03E884FE36F6B1
-:1029B00006B713207405E865FEEB03E868FEF8C36C
-:1029C000E4120C01E612F8C3E41224FEEBF6E41460
-:1029D00024F00C05E614E42A24F00C06E62AF8C3D9
-:1029E000E42A24F0E62AE41424F00C07E614F8C3E1
-:1029F000AD4949E864F989868E00F8C3AD4949E8D4
-:102A000058F989869000F8C3834E2604E8A8F7F8A1
-:102A1000C390836626FBE89EF7F8C390AC4984C058
-:102A2000750DE41024EFE610808EA10042F8C3E497
-:102A3000100C10EBF190AC493C02760232C0C0E0C1
-:102A400004A82074020C0824188AE0E41224E70A7F
-:102A5000C4E612808EA10044F8C3AC498886C00049
-:102A6000F8C3AC49E63AF8C3AC4984C07408E41230
-:102A70000C04E612F8C3E41224FBEBF6AC49E8D6EA
-:102A8000F67303E827F7F8C3E412A802740424FDE0
-:102A9000E612B8F000E887FA816626FFF3E857F7F8
-:102AA000E89AFAF8C390B88000E857FA804E2708F1
-:102AB000E844F7E887FAF8C3B88000E861FA81666D
-:102AC00026FFF7E831F7E874FAF8C390B81000E889
-:102AD00031FA804E2704E81EF7E861FAF8C3B8100F
-:102AE00000E83BFA816626FFFBE80BF7E84EFAF8B0
-:102AF000C39033C0AC493C017304B001EB063C0CFD
-:102B00007602B00C89461CF8C390814E2600208ABC
-:102B100086A5000C0224FB8886A500E60C834E26C1
-:102B200001F8C390814E2600408A86A5000C0288D9
-:102B300086A500E60CF8C390AC4950E805F658723B
-:102B400008E638B023E60AF8C3F9C390AC50ADE804
-:102B500082F85AF6C201741239869600740C89867E
-:102B60009600E6F086E0E6F886E0F6C202741039D8
-:102B7000869400740A89869400E6E486E0E6EC8395
-:102B8000E903C390E4168886BC00E8E6FA33DBE488
-:102B90000CA806740380CB01A810740380CB02A894
-:102BA00080740380CB04E4128AE024180AD8E4DAA3
-:102BB000F6C4027407A840750380CB20A8027509EB
-:102BC000E42AA80F740380CB40F74638020074094A
-:102BD000E4D8A801750380CB80889EBE00FE86B431
-:102BE00000B00AE85CE4F8C3AC493C027441771FCA
-:102BF00050E84FF558720C84C0740AB012E60A808F
-:102C00004E3801F8C3B011E60A806638FEF8C38B6F
-:102C1000463825FFF7894638A9000475E68A86A557
-:102C200000A81075DE0C108886A500E60CF8C3819C
-:102C30004E3800088A86A500A81074C724EFEBE779
-:102C4000AD49493C0172113C0C770D508AE0E41407
-:102C500025F00F0AC4E614588AC484C07402E64200
-:102C6000F8C3E8CFF9FE86B900B00EE8D4E3F8C3A4
-:102C70003A86AF00741F8886AF008AE080C206B033
-:102C8000BFEE80EA028AC4EE8A86A80080C202EE05
-:102C900080EA068AC4C38B463E85C08A86A5007436
-:102CA00012A808750D0C088886A50080C202EE8067
-:102CB000EA02C3A80874FB24F7EBEC8B462684C019
-:102CC00074168A86A500A802740D24FD8886A500C6
-:102CD00083C202EE83EA02C38A86A500A80275F7C2
-:102CE0000C02EBE85283C20CECC0E8048886A90011
-:102CF0008B5E2680E33FF6C7047407A8087503803F
-:102D0000CB40F6C7087407A802750380CB80885EA5
-:102D1000268A86A50084DB7410A802740A24FD8824
-:102D200086A50083EA0AEE5AC3A80275FA0C02EBE4
-:102D3000EE90FFFF00480030BA20C41A00180012BD
-:102D4000000C0006000300028001C000600030009B
-:102D50001800CD0100018000100010000E000C00D2
-:102D6000080000000000060004000300020001004B
-:102D70005251563C1E7747988BF08A82C40032E449
-:102D800083FE18743D83FE19743E83FE1E772FD197
-:102D9000E62E8B8C322D3B8E94007422898E94000B
-:102DA00083C2068A86A8008AE00C80EE83EA068A3F
-:102DB000C1EE83C2028AC5EE83C2048AC4EE5E59A4
-:102DC0005AC38B8E8E00EBCE8B8E9000EBC8525187
-:102DD0003D05007703B805008BC8BA0200B800D0E3
-:102DE000F7F1050100D1E8595AC38B467AA820743F
-:102DF0000B80BEC3000375040C01EB0224FE894660
-:102E00007AC324038886C3008AA6A8008ADC80E4EB
-:102E1000FC0AC43AC3740B8886A80083C206EE83FA
-:102E2000EA06E8C5FFC30008183828903C04772359
-:102E300032E48BD82E8A87262E8AA6A8008ADC80C8
-:102E4000E4C70AC43AC3740B8886A80083C206EE9E
-:102E500083EA06C384C07402B0048AA6A8008ADC90
-:102E600080E4FB0AC43AC3740B8886A80083C206B8
-:102E7000EE83EA06C3908B5E3884C074343C0274DF
-:102E80003B8A86AF000C04E8E6FD8B462E3B463CB1
-:102E9000771BF7C30004751581CB000483C2028A37
-:102EA00086A50024FA8886A500EE83EA02895E38AA
-:102EB000C38A86AF0024FBE8B6FDEBF1F7C3100030
-:102EC00074EFEBED83C20CEC83EA0CC0E804888657
-:102ED000A900C3908A86A7000C018886A7008BDA18
-:102EE00080C208EE8BD3F8C38A86A70024FEEBEAE3
-:102EF0008A86A7000C02EBE28A86A70024FDEBDAA3
-:102F0000B0FFE852F2E897F2F8C3AC49E861FEF886
-:102F1000C390AC49E8EBFEF8C390AC49E835FFF844
-:102F2000C390AC49E805FFF8C3905283C206B0BF16
-:102F3000EE5283C202AC49EE5A8A86A800EE5AF8D5
-:102F4000C3905283C206B0BFEE5283C206EBE69036
-:102F5000AC493C02770D84C0750B8A86AF0024FD16
-:102F6000E80DFDF8C3508A86AF000C02E801FD5B56
-:102F700083C2088A86A700F6C301740C24DF888602
-:102F8000A700EE83EA08F8C30C20EBF2AC49E8E5B1
-:102F9000FEF8C390B80040E869F5E8F9FCE824FFC2
-:102FA000B001E8A5F6F8C390B80040E871F5E8E58F
-:102FB000FCF8C390B80010E849F5E8D9FCE804FF34
-:102FC000B008E885F6F8C390B80010E851F5E8C5F8
-:102FD000FCF8C390B80080E829F5E8B9FCE8E4FE05
-:102FE000B002E865F6F8C390B80080E831F5E8A5CE
-:102FF000FCF8C390B80020E809F5E899FCE8C4FEA5
-:10300000B004E845F6F8C390B80020E811F5E8856B
-:10301000FCF8C390AC49E8340CF8C390B8FC3B8989
-:10302000467CF8C38A86AF000C80E843FCF8C39066
-:103030008A86AF00247FEBF28A86AF000C40E82F2F
-:10304000FCF8C3908A86AF0024BFEBF2AC49A8011C
-:103050007407834E7A20EB059083667ADFE88AFD59
-:10306000F8C383C2068A86A8000C408886A800EEB2
-:1030700083EA06AC4932E489466E834E2601834ECC
-:103080004808B006E8BBDF4946F9C39083C2068A08
-:1030900086A8000C408886A800EE83EA06ACB40A35
-:1030A000F6E4EBD0E8E00BF8C390AD4949894664FB
-:1030B000A9010074198BD883E3FA750AA904007476
-:1030C0000DB8E23FEB0BE8ECF4B8AA40EB03B838DC
-:1030D00044894662F8C38A86AF00A802740A24FDB8
-:1030E000E88DFB0C02E888FBF8C3AC49E881FCF8EA
-:1030F000C390AC49E879FCF8C390E85CF57505E845
-:10310000E6FDF8C3E8CDFD36A0B41324103410E872
-:10311000260136A1B413A901007405E8FEFEEB0EEA
-:10312000A90200740432C0EB02B001E8E8FE36A147
-:10313000B413E8AB0B36A1B413C1E805250100E8D0
-:103140000CFF36A0B5132410E82BFD32C0368A26BA
-:10315000B513F6C4047409FEC0F6C4087402FEC0B8
-:10316000E8EFFD36A1B613250F00E803FC36A1B643
-:1031700013C1E804250300E888FC36A1B613C1E8B2
-:1031800005250200E8CDFC36A1B613F6C40175048E
-:1031900032C0EB0980E402D0ECB0022AC4E88CFC17
-:1031A00036F606B713407405E88DFEEB03E894FE8F
-:1031B00036F606B713207405E869FEEB03E870FEE7
-:1031C000F8C3F8C38B4638A9040075230D040089A1
-:1031D000463883C2088B462E3B463C7314834E38D8
-:1031E000108A86A70024FE8886A700EE83EA08F8E6
-:1031F000C38A86A7000C01EBEE908B4638A9040029
-:10320000740625FBFF894638F8C3AD4949E8BEFB83
-:1032100089868E00F8C3AD4949E8B2FB89869000E3
-:10322000F8C3834E2604E892FAF8C390836626FB1F
-:10323000E888FAF8C390AC4984C07507808EA30073
-:1032400004F8C380A6A300FBF8C3AC4983C2083CC2
-:1032500002760232C03C017412770B8A86A70024E2
-:10326000EF8886A700EE83EA08F8C38A86A7000CD9
-:1032700010EBEE905283C206B0BFEE5283C204AC94
-:1032800049EE5A8A86A800EE5AF8C3905283C206C5
-:10329000B0BFEE5283C208EBE690AC49F8C3AC492C
-:1032A000E8B4EE7303E8F7EEF8C38A86AF00247F34
-:1032B000E8BDF9B8F000E866F2816626FFF3E8237E
-:1032C000FAE8D2F9F8C3B88000E837F2804E270850
-:1032D000E811FAE8C0F9F8C3B88000E841F2816665
-:1032E00026FFF7E8FEF9E8ADF9F8C390B81000E85A
-:1032F00011F2804E2704E8EBF9E89AF9F8C3B81008
-:1033000000E8FFF1816626FFFBE8D8F9F8C3AC4975
-:10331000F8C383C2068A86A8000C408886A800EEFF
-:1033200083EA06F8C39083C2068A86A80024BFEB0E
-:10333000EA90AC498AE080C20AEC80EA0AA82074CC
-:10334000058AC4EEF8C30651578B4E24E3344989ED
-:103350004E24FF461A8E46028B7E228AC4AA897E9C
-:10336000228B462624FD89462675298A86A500A833
-:1033700002752180C2020C028886A500EE80EA0256
-:10338000EB12C47E003B7E1E760A4F268825897E7E
-:1033900000FF461A5F5907F8C390ACAD83E9038577
-:1033A000C074053D00207205B8FFFFEB03C1E003C8
-:1033B0003B8694007426898694008BD85283C2067B
-:1033C0008A86A8008AE00C80EE83EA068AC3EE8330
-:1033D000C2028AC7EE83C2048AC4EE5AF8C3B08818
-:1033E0008886BC00E88CF233DB8A86A500A80274CC
-:1033F0000380CB01A805740380CB02A80874038066
-:10340000CB04F686A70010740380CB108A86A9002F
-:10341000F6C304750A83C20CEC83EA0CC0E8048A84
-:10342000E08A86AF00A8807408F6C401750380CBDB
-:1034300020F686A70002750AF74638040074038058
-:10344000CB40889EBE00FE86B400B00AE8F3DBF8ED
-:10345000C3FE86B400B00AE8E8DBF8C3AC493C021E
-:103460007437771084C07406804E3801F8C38066C4
-:1034700038FEF8C38B463825FFF7894638A9000483
-:1034800075EA8A86A500A80175E20C0583C2028848
-:1034900086A500EE83EA02F8C3814E3800088A86CA
-:1034A000A500A80174C624FAEBE2AD4949F8C3901F
-:1034B000E811FAFE86B900B00EE886DBF8C3B0FF6B
-:1034C000E8BFECF8C39083667AFBB000E873DBF8E2
-:1034D000C390AC49E853D9721136881E1A0136A040
-:1034E0008E120AC352BA0001EE5AF8C3AC4932E454
-:1034F00036A38612050600368B1E88122BD8368915
-:103500001E8A12F8C390AD8BD8AD83E90403C32B98
-:103510004676894678F7467A0200740A83667AFD11
-:10352000B80000E81CDBF8C3061607AC49250F00FD
-:103530006BC0098DBEFD0003F8AC49250F00AA85BC
-:10354000C074082BC8518BC8F3A459E827F0E8448D
-:103550000307F8C333C0AC4936A3B21336A3B01384
-:10356000F8C383667AEFE82C03F8C390834E7A1091
-:10357000EBF4E89BF0F8C390AD3C19770E3C19775B
-:103580000A8BF881E7FF0088A6C400F8C390834E39
-:103590002620AC4932E4D1E08BD8C1E30203C389D1
-:1035A000466E834E4804B006E897DA4946F9C39060
-:1035B000FE86B300B00AE889DAF8C39033C0AC499C
-:1035C0006BC00A89868A00F8C390AC4932E43D0A90
-:1035D000007705B80A00EB083D5A007203B85A009C
-:1035E00051F7D80564008BC88B4644F7E1B96400F5
-:1035F000F7F189464659F8C3AC49E885EBF8C39022
-:10360000AC4984C07507816638FFFDF8C3814E3828
-:103610000002F74638400075088A86A9008886AA05
-:1036200000F8C3905156E87F0C5E59F8C390FE86AF
-:10363000B600B00AE80BDAF8C390FE86B700B00A0D
-:10364000E8FFD9F8C390FE86B800B00AE8F3D9F8CD
-:10365000C39000905155AC2EA2523633C9AD8BF9B0
-:10366000C1E705A9010074232E8BAD4400837E08B9
-:103670000074182E803E523601740960B004E8BB15
-:103680000C61EB0760B0FBE8EC0C614747D1E875D3
-:10369000D24183F90472C65D5983E905F746384083
-:1036A000007405E887EAF8C3E88DEAF8C39036C6E7
-:1036B00006C81301F8C333C0AC4936A38012AC4925
-:1036C000362B068812F7D836A38212F8C390DE266E
-:1036D000DE26EC26F226F826FE2604270E271627DD
-:1036E0001E2726272E273427BE34C634D2343A2745
-:1036F000782780279427A027B427C027D427E0273E
-:10370000F42700281028EC34DE261E2826282C2832
-:10371000322838284E288A28063528359828BE2889
-:10372000D228DE28E628543562356C35EE28C029CB
-:10373000C829CE29E02972357835F029FC298E3543
-:10374000082A122A1C2AB035362ABC355A2A622A7F
-:10375000682ACA357C2AF835882AA62AB82ACC2AAB
-:10376000DE2AF22A00360A2B242B2436382B4C2B47
-:10377000842B2E363A3646365436E82BAE36402C5D
-:10378000622CB6367028DE26DE26D42EE82EF02EE9
-:10379000F82E002F0A2F122F1A2F222F2A2F422FF6
-:1037A000BE34C634D234502F8C2F942FA82FB42F70
-:1037B000C82FD42FE82FF42F083014301C30EC34ED
-:1037C000DE2624303030383044304C306230A43083
-:1037D00006352835AA30CE30D630EA30F2305435AE
-:1037E00062356C35FA30C231C231C431FA317235CA
-:1037F00078350A3216328E3522322C323632B035D6
-:103800004A32BC3574328C329A32CA359E32F8351F
-:10381000AA32C632D832EC32FE320E3300361233C0
-:103820002633243632339A33DE332E363A36463652
-:1038300054365C34AE36AA34B034B6368C30E32815
-:10384000F7463840007532E8E3E833C0AC493D5BE9
-:103850000077198BD8D1E32EFF97CE36720B85C92E
-:1038600075E88B4648E81A0CC34E41C36A001FC670
-:103870000693120C9C0EE863DAE8BCE833C0AC494E
-:103880003D5B0077E78BD8D1E32EFF97863772D95F
-:1038900085C975E8C3F7467A1000750F83BE8400AA
-:1038A000007408B8483A89868000C381BE8000EC65
-:1038B0003C74F783BE8800007505B8EC3CEBE7F775
-:1038C000467A080075401E608B8E88003B4E7477E8
-:1038D000333B4E78772EC47E108BDF26033D47475F
-:1038E00033C08ED88DB6F4008BC1F7467A010075CF
-:1038F0001DF3A4260107294678014676294674B0AF
-:103900000CE83ED7611FC78688000000EBACE3E3FC
-:103910005090AC247FAAE2FA58EBD8908B8E8800A6
-:10392000E3468B9E8A0085DB743EBA50FFED2B8602
-:1039300082003BC372378DB6F400C47E108BDF2645
-:10394000033D47478BC1161FF7467A01007524F3E4
-:10395000A4260107294678014676294674C7868839
-:10396000000000B00CE8DAD683667AF7C3B000E84E
-:10397000D0D6C3E3DC50AC247FAAE2FA58EBD29055
-:103980001E6033C08ED88DB6FD008B8688008B9666
-:1039900084003A0475108BDE468BC88DBEF400F3AC
-:1039A000A674668BF39083C6094A75E68DB6FD0052
-:1039B0008B9684003A0473108BDE468BC88DBEF460
-:1039C00000F3A674768BF39083C6094A75E68DB62C
-:1039D000F400ACF7467A01007402247F1EC55E1025
-:1039E0008B37884002468937FF4E78FF4676FF4E78
-:1039F000741F8B8E880049898E8800E3438DB6F44E
-:103A0000008BFE46F3A4E97DFFC576108B1C85DB99
-:103A1000740803F383C60383E6FE8B8684002BC2FF
-:103A2000B48089044646C7040000897610834E7A24
-:103A300004C78688000000611FF9C333C0611FC33B
-:103A4000B08084C0611FC3908B4E782B8E88007627
-:103A50002789B68C008B5E743BCB72028BCB3BC844
-:103A600072028BC88BC1E34433D28EC28BD183BE2A
-:103A70008800007406E98E0033C0C38B5E10031FFC
-:103A8000434352F7467A0100752AAC8DBEE4008BA1
-:103A90008E8600F2AE74348807434A75ED588B5E0B
-:103AA0001001072946780146762946748BC62B8675
-:103AB0008C00C390AC8DBEE4008B8E8600F2AE7499
-:103AC0000A247F8807434A75EBEBD28886F400C747
-:103AD0008688000100582BC2740E8B5E10010729E6
-:103AE000467801467629467440E894FE72BE4A75CF
-:103AF0001583BE8A000074B4BA50FFED8986820037
-:103B0000834E7A08EBA68DBEF40003BE8800A4FFA6
-:103B1000868800E86AFE729479064A748FE95BFF32
-:103B20004A74CEEBE19050E811CC8B467439467262
-:103B300074271E565133C9C5760CAD74107809032D
-:103B4000C805010024FE03F03B761076ED294E7681
-:103B5000014E78E837CC595E1F58C390C47E1026BA
-:103B60008B1D83C30326891D4B03FBAB91AAB803AE
-:103B700000294678014676294674C390C47E1026F3
-:103B80008B1D4326891D4303FBAAFF4E78FF467613
-:103B9000FF4E74C3E8E5FFC38081848582838687F6
-:103BA00050538ADC83E30ED1EB2E8A87983B08863C
-:103BB000B000FE86B100B00AE887D45B58C3508AD3
-:103BC000C8B8FF00E895FF58C3908A86BB00E8ABF1
-:103BD000FFC3E8CBFFE8F2FFC390E8C3FFE8B4FF00
-:103BE000C39033C0E895FFC3B8FF0033C9E86CFF4A
-:103BF000C390B8FF01B110E862FFC390C3FC3BE281
-:103C00003BF23BF23BFC3BE23BE83BE83BFC3BE26C
-:103C10003BE83BE83BFC3BE23BE23BE23B00100085
-:103C20000000100000001000000010000000100054
-:103C3000000010000000100000001000000008004C
-:103C40000000080000000800000008000051538B2D
-:103C50004E3881E1FFEEA804740481C900018AE0B6
-:103C600080E4032418D0E40AC433DB8AD82E8B877F
-:103C7000FD3B89467C2E0B8F1D3C894E38D1EB2EA7
-:103C80008AA73D3C5B59C3AC493C01721D74203C82
-:103C900003722374283C08722B74303C20723774F2
-:103CA0003ABBDA3B32E4895E7EC3BBA03BEBF5BB9B
-:103CB000943BB401EBF0BBFC3BB402EBE9BBE23B51
-:103CC000B403EBE2BBBE3BB404EBDBBBCA3BAC4989
-:103CD0008886BB00EBCEBBD23BEBF3BBFC3BEBC41B
-:103CE000A9040075D1A9080075DAEBD18B5E748B3D
-:103CF0004E783BCB72028BCB3BC872028BC88BC118
-:103D0000E32CC47E108BDF26033D4747F7467A013C
-:103D100000751CF7C70100740249A4D1E9F3A5732B
-:103D200001A4260107294678014676294674C35026
-:103D300053BB7F7FF7C70100740549AC22C3AAD1EA
-:103D4000E9E31D9CAD23C3AB497414AD23C3AB4958
-:103D5000740DAD23C3AB497406AD23C3ABE2E59D3F
-:103D60007304AC22C3AB5B58EBB8E8CEC98B5E38AA
-:103D7000F7C310047501C3F7C340007405E8B8E346
-:103D8000EB03E8A8E3816638EFFBF6C310743CF65A
-:103D9000C3027406E4D80C01E6D8F6C30474118398
-:103DA000C2088A86A7000C01EE8886A70083EA086D
-:103DB000F6C308740FE88BE3720A8A86C000E638FF
-:103DC000B023E60AF7C300047501C3F7C300087502
-:103DD000F98A86A500F6C340750DA81075EC0C1085
-:103DE0008886A500E60CC3A80175DF83C2020C0516
-:103DF000EE8886A500C3B000E847D2EB0FB002E81A
-:103E0000900EEB08836638DF834E7A0233C08ED87B
-:103E1000FAA0921240A292123C05721EC60692129D
-:103E200000FBB001E86B0EFAA1260123062A01A8C7
-:103E3000017507E8E207E8610990B000E837D2FBB6
-:103E400085ED74B9FAF7467A460075C08B46783D21
-:103E50000A0072B08B4E7483F950729A836638DF11
-:103E6000C576148B463A85C07558AD85C0750FE888
-:103E7000F8FEF7467A08007493E8A0FAEB8E3B76DA
-:103E8000047621B90200394E2E7705C7462E000070
-:103E9000568B762C897604C7040000464689762C1A
-:103EA000294E2E5E85C07917F6C4107405FF567C26
-:103EB000EB03FF567E897614B00CE885D1EB86893A
-:103EC000463AFF96800029463A897614B00CE8718C
-:103ED000D1E971FF0000000000000000080410029A
-:103EE00001200000000000000000000000000000B1
-:103EF00000000000808080808080808080808080C2
-:103F000080808080808080808080808080808080B1
-:103F100080808080808080808080808080808080A1
-:103F20008080808080808080808080808080808091
-:103F30008080808080C0C0C0C0C0C0C0C0C0C0C0C1
-:103F4000C0C0C0C0C0C0C0C0C0C0C0C0C0C0C080B1
-:103F500080808000808080808080808080808080E1
-:103F60008080808080808080808080808080808051
-:103F70008080808080808080808080808080808041
-:103F80008080808080808080808080808080808031
-:103F90008080808080808080808080808080808021
-:103FA0008080808080808080808080808080808011
-:103FB0008080808080808080808080808080808001
-:103FC00080808080808080808080808080808080F1
-:103FD000808080804E417841D041F44106421842B1
-:103FE000C3908E46028B7E22897E6C806627FD8B75
-:103FF000562483FA0472E983EA028BD93BCA76021B
-:104000008BCAB00A57518BFEF2AE8BC1595F751E39
-:1040100050402BC874062BD12BD9F3A4594B4A4AD4
-:10402000B00DAAA43BCA76028BCAE313EBD42BD9FA
-:10403000F7C601007402A449D1E9F3A57301A4896C
-:104040007E222B7E6C297E24017E1A8BCB807E26DD
-:10405000027405806626FDC360B0FDE8180361C3E5
-:10406000C390E87C0272F990834E26208B466A89C1
-:10407000466E8B46480D040025BFFF894648B006B2
-:10408000E8BFCFC3897E222B7E6C017E1A297E2455
-:10409000807E26027405836626FDC360B0FDE8D5E8
-:1040A0000261C3908ABEC200EB24F7464840007507
-:1040B000B18E46028B7E22897E6C8B562483EA0A5F
-:1040C000789E03D7806627FD33C08ABEC200E3B462
-:1040D0003BFA77B0AC49932E8A87D43E9322DF75A2
-:1040E00017AAE3A03BFA779CAC49932E8A87D43E6B
-:1040F0009322DF7503AAEBD6F6C37F7505FF4666EC
-:10410000EBDFF6C340750C8BD883EB08D1E32EFFB1
-:10411000A7D43FFF46662C20EBC785C0742C894688
-:104120006A834E4840897E222B7E6C017E1A297E4E
-:1041300024807E26027408836626FDE8A301C360FE
-:10414000B0FDE8310261E89801C3E957FF908B5E4A
-:10415000664B7803895E66AA8B5E64F7C3002075A0
-:1041600003E940FFF7C3400074088A86C100AAE94A
-:1041700032FFB83200EBA3908B5E66895E6883C322
-:104180000880E3F8895E668B5E6481E3001881FB3A
-:104190000018742DAA85DB7425F746644000751855
-:1041A00081FB0010740C8B46662B4668C1E004E965
-:1041B00068FFB86400E962FF8A86C100AAAAE9E341
-:1041C000FE518B4E662B4E68B020F3AA59E9D4FEFF
-:1041D0008B5E66895E688B5E64F7C324007410C7CB
-:1041E00046660000F7C304007405B00DAAB00AAA21
-:1041F000EB489090AAF7466400407406B8D007E9EF
-:1042000018FFE99FFE90AAF7466400807406B8D0B4
-:1042100007E906FFE98DFE908B5E66895E6885DBA7
-:10422000750C8B5E64F7C310007406E976FE8B5E36
-:1042300064F7C308007427B00AAAF7C32000751FEB
-:10424000F7C300017503E95BFEF7C340007506B8CC
-:104250006400E9C5FE8A86C100AAAAE946FEAAC78B
-:1042600046660000F7C3000674F1F7C340007419F6
-:104270008A86C10081E3000681FB00047206760293
-:10428000AAAAAAAAAAAAE91BFE81E3000681FB004A
-:1042900004720E7606B89600E97FFEB86400E979EC
-:1042A000FE8B4668E973FE90368B0EDA1283F93284
-:1042B000731D1E0633C08ED88EC08D764CBFDC12A7
-:1042C00003F9A5A5A583C106890EDA12071FC3B09D
-:1042D00008E86ECDC390836648FEE893C4E8C8FF43
-:1042E000C3F6462702750F9CFA837E1A0074098074
-:1042F0004E27019DF9C3F8C35052F7463840007469
-:104300001DE834DE83C20AECA840752783EA088AD8
-:1043100086A5000C028886A500EE5A58EBD1E80C61
-:10432000DE8A86A50024FB0C028886A500E60C5ACE
-:1043300058EBBC804E27025A589DF8C30846269C6D
-:10434000FA8A8EA500F7463840007514F6C1067447
-:1043500023E8D9DD8AC124F98886A500E60C9DC32F
-:10436000F6C102740FE8D0DD83C2028AC124FD8841
-:1043700086A500EE9DC38B5E2622C3884626740167
-:10438000C3806627FD9CFA8A8EA500F74638400058
-:104390007516F6C104750FE893DD8AC124FD0C047F
-:1043A0008886A500E60C9DC3F6C10275F9E888DD94
-:1043B00083C20AECA820750E83EA088AC10C028821
-:1043C00086A500EE9DC383EA0A33C98A4E1C8B463C
-:1043D0001A3BC8731B014E2A2BC189461A1EC5768B
-:1043E00000F36E1F89760083C2028A86A500EBCD9A
-:1043F00085C0741201462A8BC81EC57600F36E1F55
-:10440000897600894E1AF6C701752380CB02895E32
-:1044100026E808C383C2028A86A50024FDEE8886AA
-:10442000A500F6C7107505B002E816CC9DC383C27F
-:10443000028A86A500EB86908BD18B46243BC876FA
-:10444000028BC82BD12BC18BD9E322806627FD8E2E
-:1044500046028B7E22F7C601007402A449D1E9F31B
-:10446000A57301A4897E22894624015E1A8BCA8025
-:104470007E26027405806626FDC360B0FDE8F6FE68
-:1044800061C350E40A84C0750A8686A10084C074A2
-:104490000AE60A580C20894648F9C35824DF8946A1
-:1044A00048F8C390FBB002E8E807FAE82E01FBB039
-:1044B00001E8DE07FAB002E8BCCBFB85ED74E5FA53
-:1044C0008E5E0AFB90FA8B46488B7640A88C75DE90
-:1044D000A820741A50E855DC58E8A6FF7310B00203
-:1044E000E85FCBEBC99025FF008BC8EB3690A801A5
-:1044F00075224683E6FE3B76087479AD8AFCB3F0FC
-:1045000022FB3AFB74E03ABEA000742EE8D2FD73A1
-:1045100077EB9B908AE024FC8846488B4E4AF6C491
-:1045200002741DE8BBFD7286E813F3897640E393BD
-:10453000834E4803894E4AE974FF25FF0F8BC890CC
-:104540008B86980085C0741A518A8EA000C0E90439
-:10455000BA0100D3E25923C2740803F1897640E915
-:1045600061FFFF5662E3F5834E4801894E4A897622
-:1045700040E93AFF814E2600108B46503B46467775
-:1045800003E852FDE927FF9088BEA000EBAC0A06C5
-:1045900090128AE0BA0601B004EEEC84C07512B045
-:1045A00004EE8AC4EE32E4A8807406C706841200C2
-:1045B0000088269012C30A0690128AE0BA0601EC1F
-:1045C000A80175EDBA08018AC4EE32E4A88074E14E
-:1045D000C7068412000088269012C39036F706247E
-:1045E0000101007530368B0EDA1280F936732633EE
-:1045F000C08EC08ED8BFDC1203F9B008E877CA8538
-:10460000ED740E8D764CA5A5A580C10680F9367295
-:10461000E9890EDA12C3C390F7062601010075F688
-:104620008B0E201385C975EE33C08EC08ED8BF2483
-:1046300013B93600B00AE83DCA85ED7506E91201E6
-:10464000E90A0133DB8A464C8AA6B300FECC780E19
-:1046500088A6B3000ADCB40AAB83E90276E28AA634
-:10466000B200FECC780E88A6B2000ADCB408AB8398
-:10467000E90276CC8AA6B100FECC78188ABEB000DA
-:10468000750488A6B00088A6B1000ADC8AE7AB836F
-:10469000E90276AC8AA6B400FECC781F88A6B400E6
-:1046A0000ADCB40BAB8A86BC008AA6BD00AB8B8645
-:1046B000BE00AB83E90676888A464C8AA6B600FE21
-:1046C000CC781988A6B6000ADCB40CABE8DBCBAB1F
-:1046D0008B462AAB83E90676748A464C8AA6B700D5
-:1046E000FECC781988A6B7000ADCB40DABE8BACBCB
-:1046F000AB8B4634AB83E90676538A464C8AA6B820
-:1047000000FECC781988A6B8000ADCB40EABA15024
-:1047100012ABA15212AB83E90676328A464C8AA6C6
-:10472000B500FECC781888A6B5000ADCB40FAB8BB8
-:10473000869A00AB8B869C00AB83E906760F84DB00
-:104740007503E9EFFEB00AE8F8C8E9E7FEB00AE849
-:10475000F0C8F7D983C1368BC10D800086C4A3226F
-:10476000134141890E2013C3A184122BC17211A3DE
-:104770008412BE2213D1E9F36F90890E2013F8C37F
-:10478000F9C3C381EF6A1374F98BC70D800086C427
-:10479000A368134747893E6613C3F7062A01010041
-:1047A00075E08B0E6613E30780F92077D54949330E
-:1047B000C08EC08ED8BF6A138BF703F983C6343B13
-:1047C000FE77C0B00EE8AEC885ED74B78A464C8A55
-:1047D000B6B900FECE781588B6B9008AA6A90080C1
-:1047E000CCC0AB84F67405B00EE856C88AB6BA00E1
-:1047F000FECE78CB8A9EA9008ABEAB008A563F8A3D
-:10480000F332F70AB6AC00C686AC000022F2744B55
-:10481000F6C608740FB402F6C3087502B403AB8081
-:10482000E6F77437F6C601740FB400F6C3017502DB
-:10483000B401AB80E6FE7423F6C602740FB404F62E
-:10484000C3027502B405AB80E6FD740FF6C60474AE
-:104850000AB406F6C3047502B407ABC686BA0000F4
-:10486000889EAB00E958FF90A184122BC17211A35E
-:104870008412BE6813D1E9F36F90890E6613F8C3F2
-:10488000F9C3A1841241412BC17223A384128BC1AD
-:10489000484832E40C8086C4EF9090909090BEDC43
-:1048A000124949D1E9F36F90890EDA12F8C3F9C3BE
-:1048B0008AC88A464CB40183EB06EF9090909090A2
-:1048C000B80100EF90909090908AC1EF90909090F6
-:1048D00090E99700E9AC0033C08ED8891E8412C3DA
-:1048E000368B1E8412FB90FAB00CE889C785ED74F4
-:1048F000E6C5760C83FB1472DBFB90FAAD85C078BD
-:10490000AF74E28BFE03F8368B0E86123BC1770242
-:104910008BC883EB043BD977028BCB33C08A464CE0
-:10492000EF90909090908BC1EF90909090904180FC
-:10493000E1FE2BD951D1E9F36F90598BC74024FE8A
-:104940003BC674272BFE4E4E538B5E103BF3721307
-:10495000031F83C30380E3FEC7070000836E740256
-:10496000895E105B893C89760CEB8989760C3976F7
-:104970001077817208833C007403E977FFE80DBE6D
-:10498000E962FF36891E8412B00CE8B5C633C08ECA
-:10499000D8C3A184123D10007277BA04013B068887
-:1049A000127506C7067E1200008B0EDA12E30BE8C2
-:1049B000D0FE7257C7067E12FF7F8B0E2013E30BCB
-:1049C000E8A5FD7246C7067E12FF7F8B0E6613E3D5
-:1049D0000BE894FE7235C7067E12FF7FA12801A95D
-:1049E00001007503E8F9FE803E8D1200751DA1845B
-:1049F000123D200076153B0682127609A17E123BFD
-:104A0000068012720C800E901280C3B080FF167C5C
-:104A100012C3800E901240C36A001FC6069312177D
-:104A20009C0EE8B7C86A001FC6069312209C0EE8C9
-:104A3000AAC86A001FC6069312169C0EE89DC8906D
-:104A4000BA0601ECA82075CAFB90FABA0401ED90F1
-:104A5000909090903A06941277BE33DB8AD8D1E3D7
-:104A60002E8BAF4400C47E0885FF74B9F6C4C075B0
-:104A70005532C0C1E00280E4F08BF0ED9090909050
-:104A80009085C074BB8BC84180E1FE0BC68B5E5025
-:104A90004B4B2BD9789CAB8BC1404001464ED1E9A2
-:104AA000F36D90895E50897E088B462680E4EF89FD
-:104AB0004626F6C401750CF746480C007505B00291
-:104AC000E87FC5E97AFF86C48BC883E13F4180E176
-:104AD000FEE30A3C807209243FB4F0EBB0E960FFCA
-:104AE000253F0033FF8EC7BF96128BF7D1E9F36DD8
-:104AF000908BC8E848EDE947FF906A001FC606930F
-:104B0000121B9C0EE8D5C790601E0633C08ED88E4F
-:104B1000C0BA0601ECA80474E1B006EEECA28C1257
-:104B2000A8407411A18812A38412C6068D1200E851
-:104B300060FEA08C12A8807403E804FFB80080BA5D
-:104B400022FFEF071F61CF906A001FC60693121B5A
-:104B50009C0EE887C790601E0633C08ED88EC0BA00
-:104B60000601ECA80474E1BA0801ECA28C12A8407A
-:104B70007411A18812A38412C6068D1200E812FED9
-:104B8000A08C12A8807403E8B6FEB80080BA22FF99
-:104B9000EF071F61CF90EE86E0EE86E0EC86E0EC5A
-:104BA00086E080E1FEF36C9080E1FEF36E900500FC
-:104BB0007547A84B05007548A84B0500A348A84BAE
-:104BC00005003549A84B06009848964B0600BA48A0
-:104BD000964B0600C348964B0600CB48964B060002
-:104BE0002049964B06002849964B06004E4A9C4B9E
-:104BF00006007B4A9C4B05009E4AA24B0500EC4AEE
-:104C0000A24B00001E06833E4412007409A0060158
-:104C100024303C30741A8CC88ED88EC0BBAE4B8BFF
-:104C20000FE30D8B7F028B7704F3A483C306EBEFB6
-:104C3000071FC39033C0A33E01B90C01BE40018BD6
-:104C4000FE81C6B40F89048BC62BF13BC777F6A350
-:104C50003C01C3901E0660368B2E3E018B5E003BEE
-:104C6000EB742B8B7602891C89770236A13C018973
-:104C7000460036892E3C018BEBFF4E0674088B6E86
-:104C800000FF4E0675F836892E3E018B66046107DB
-:104C90001FC31E0660368B2E3E0198894606896624
-:104CA000043B6E0074108B6E00FF4E0675F836895B
-:104CB0002E3E018B660461071FC3C3901E06609CD5
-:104CC000FA33ED8EDD8B2E3C0185ED743D8B4E006D
-:104CD000890E3C018BCC8DA60A01561E06608966A2
-:104CE00004C746080F1AC7460601008B1E3E018501
-:104CF000DB741D8BC58707894600895E028BD889C6
-:104D00006F028BE19D61071FF8C39D61071FF9C307
-:104D1000892E3E01896E00896E0287E19D8BE1EB51
-:104D2000E4000D0A5465726D696E616C73207375D1
-:104D300070706F727465643A0D0A312920414E53C8
-:104D40004920636F6D70617469626C650D0A322968
-:104D500020577973652033300D0A506C6561736597
-:104D60002073656C6563743A20000D0A636F646597
-:104D7000207365676D656E743D000D0A4D6F6E6939
-:104D8000746F722076322E350A0D0A3E000D0A50DD
-:104D90006172646F6E3F000D0A4E6F206164647231
-:104DA00065737320737065636966696564000D0AD5
-:104DB0003A000D0A004C6F633D000D0A4641544114
-:104DC0004C204552524F523D000D0A4D6F6E697492
-:104DD0006F7220636F6D6D616E64733A2D0D0A20E2
-:104DE0002020442C645B5B787878783A5D7878781A
-:104DF000785D202D2064756D70206D656D6F727902
-:104E00000D0A2020204C2C6C5B5B787878783A5D1A
-:104E1000787878785D202D2064756D702073696EC8
-:104E2000676C65206C696E650D0A202020452C6535
-:104E30005B5B787878783A5D787878785D202D209B
-:104E400065646974206D656D6F72790D0A2020208C
-:104E5000462C665B5B78787878205D787878785D2A
-:104E6000202D2066696C6C206D656D6F72792070E5
-:104E70006172616772617068730D0A202020495B5E
-:104E8000787878785D202020202020202020202D78
-:104E900020776F726420696E7075742066726F6D12
-:104EA00020706F72740D0A202020695B7878787802
-:104EB0005D202020202020202020202D20627974B9
-:104EC0006520696E7075742066726F6D20706F72E8
-:104ED000740D0A2020204F78787878207878202068
-:104EE000202020202020202D206F757470757420C4
-:104EF000776F726420746F20706F72740D0A2020B7
-:104F0000206F787878782078782020202020202042
-:104F100020202D206F75747075742062797465205F
-:104F2000746F20706F72740D0A202020475B5B78CD
-:104F30007878783A5D787878785D2020202D206721
-:104F40006F746F20616464726573730D0A20202092
-:104F5000575B5B787878783A5D787878785D202050
-:104F6000202D207761746368206120776F72640D53
-:104F70000A20202043202020202020202020202024
-:104F800020202020202D20696E7465727275707447
-:104F900073206F66660D0A202020532020202020D9
-:104FA00020202020202020202020202D20696E7409
-:104FB00065727275707473206F6E0D0A20202073F5
-:104FC00020202020202020202020202020202020E1
-:104FD0002D2073696E676C6520737465700D0A20EF
-:104FE000202042787878782020202020202020203F
-:104FF0002020202D20627265616B706F696E7420B5
-:105000007365740D0A20202062202020202020209B
-:105010002020202020202020202D20627265616B1E
-:10502000706F696E7420636C6561720D0A202020B8
-:10503000522020202020202020202020202020203E
-:10504000202D207265737461727420627265616BC9
-:10505000706F696E740D0A2020207220202020209D
-:1050600020202020202020202020202D2072656755
-:105070006973746572732061742062726B70740D51
-:105080000A202020582C78206E202020202020204C
-:1050900020202020202D206578616D696E652063B9
-:1050A00068616E6E656C206E0D0A202020482C3FD2
-:1050B00020202020202020202020202020202D20E3
-:1050C00074686973206D657373616765001B5B327B
-:1050D0004A1B5B313B3148414E5349205465726D48
-:1050E000696E616C0D0A0A001B5B4B001B5B4A007A
-:1050F0001B5B324A1B5B313B3148001B5B44201B6E
-:105100005B44001B5B313B373248001B5B003B00BC
-:1051100048001B5B73001B5B75001B7A2B0B7F1B0E
-:105120007A2E0C7F1B7A2D087F1B7A2C0A7F1B7A24
-:1051300022087F1A57797365203330205465726DC9
-:10514000696E616C0D0A001B54001B59001A001E89
-:105150000008200800001B3D0000001B46000D0059
-:105160003F4464456546664767486849694F6F43F1
-:1051700063537342625272577758784C6C3C60D4D8
-:1051800057D45750585058D659D659B459B4593C99
-:10519000603C606C57485726570657905790579871
-:1051A00057485F0C5F585F335F405FA057A057FEC2
-:1051B00059FE59DC57DC5788619861C061CC61D8D1
-:1051C00061F66102622262F8564A625862605920B2
-:1051D00020666C6167733D00202061783D002020CF
-:1051E00062783D00202063783D00202064783D00F7
-:1051F000202063733D00202064733D0020206573F0
-:105200003D00202073733D00202064693D00202074
-:1052100073693D00202062703D00202073703D00C6
-:10522000202069703D00206368616E656C3D002040
-:105230002020207365673D002074695F7374723DA0
-:10524000002074695F746F733D002074695F6D6145
-:10525000783D002074695F6261733D002074695F6E
-:1052600073697A3D002074695F7374663D00207431
-:10527000695F726F6F3D002074695F666C673D0007
-:105280002074695F746F743D002072695F70636E93
-:105290003D002072695F7374723D002072695F7314
-:1052A00074663D002072695F726F6F3D0020726905
-:1052B0005F6261733D002072695F73697A3D00200F
-:1052C00072695F746F743D002072695F6D696E3D35
-:1052D000002072695F666C673D002072695F746FC1
-:1052E000733D002072695F7468723D002074685FCE
-:1052F0007374663D002074685F7374723D0020749F
-:10530000685F6261733D002074685F73697A3D0075
-:105310002074685F7472673D002074685F666C6714
-:105320003D002074685F636E743D002072685F7397
-:1053300074723D002072685F7374663D002072686D
-:105340005F6261733D002072685F73697A3D00207F
-:1053500072685F7370613D002072685F61736F3DBA
-:10536000002072685F726F6F3D002072685F666C2C
-:10537000673D00206D5F636172653D002070745F62
-:10538000666C6F3D002061735F666C6F3D0020723C
-:105390006D5F666C6F3D00202020715F696E3D007F
-:1053A0002020715F6F75743D0020715F6472616EC3
-:1053B0003D002020715F74696D3D00202020715FE9
-:1053C00066633D0020715F737461743D0020715FFE
-:1053D000646174613D0020715F6D6F646D3D0020FC
-:1053E00068616E645F6F3D002068616E645F623D5E
-:1053F000002068616E645F653D002068616E645FD7
-:10540000693D0020206F706F73743D002020746927
-:105410006D656F3D0020637573746D313D002063D1
-:105420007573746D323D0020637573746D643D0057
-:10543000207478726174653D0020727872617465C1
-:105440003D002020635F6D61703D0020635F6164FB
-:1054500064723D0020635F616973723D0020635F89
-:10546000787461673D0020635F646566723D00206B
-:10547000635F666C73683D002074786D6178733D7E
-:10548000002072695F656D733D002020635F6C735F
-:10549000723D002020635F6965723D002020635FDC
-:1054A0006663723D002020635F6D63723D002020C3
-:1054B000635F6C63723D002020635F6473733D0023
-:1054C00020635F647373693D0020635F647373726C
-:1054D0003D002020635F6973723D002020635F639D
-:1054E00061723D002020635F6566723D0020635F4E
-:1054F000657273743D0020635F65636E743D0020C8
-:10550000635F62726B633D0020635F626F6B633D3C
-:105510000020635F7265706C3D0020635F6363739E
-:10552000723D0020635F737474313D0020635F73CC
-:105530007474323D002BC08ED88EC0E8C200E8E5FE
-:1055400000FABF8400C705DC568C4D02BF0C00C7B3
-:10555000056E5E8C4D02BF0400C705BA5E8C4D021D
-:10556000E8F10090E84901E81600F490E8E500BE93
-:10557000BA4DE8090CA09312E85D0CE8C209EBE40F
-:10558000E8D50CE8C40C0AC074F68B1EF8793C0D03
-:10559000742E3C0874173C7F741383FB207FE188D2
-:1055A00087D67943891EF879E8770CEBD30BDB7447
-:1055B000CF4B891EF8798B36167AE8C10BEBC19078
-:1055C000E80200EBBBC687D679000BDB741EA0D6C1
-:1055D00079BF6051B91D008BD9060E07F2AE077571
-:1055E00017412BD9D1E32EFF977D519033C0A3F8FB
-:1055F00079BE894DE8870BC3BE8D4DE8800BEBEC7F
-:10560000BA0002B093EEB055EEBA1002B093EEB00D
-:10561000AAEEBA0002EC3C557508BA1002EC3CAA9E
-:105620007403E82FF6C3BA0402B01AEEB020EEB04D
-:1056300030EEB040EEB080EEBA0002B013EEB0072C
-:10564000EEBA0802B080EEBA0202B0BBEEBA0402B3
-:10565000B005EEC3C606CA1301C706F8790000C636
-:1056600006F67901C706D0790000C706D279000096
-:10567000C706D4790000C706FA790000C706FC798E
-:105680000000C706FE790000C706007A0000C706C2
-:10569000027ACE598C0E047AC706067A0000C70635
-:1056A000277A0000C606297A00C6062A7A00C39027
-:1056B000BE224DE8C80AE83F002C313C0177F7E8EC
-:1056C00081098B360C7AE8B50ABE6A4DE8AF0A0E3E
-:1056D00058E8F80ABE7A4DE8A40AC39060D1E38383
-:1056E000FB1873111EBA00008EDA2EFF97B7518B8C
-:1056F000EC8946101F61CF90E84F0B0AC07505E892
-:10570000560BEBF4C390833EF879017416BED7793B
-:10571000E8310A8BD0AC3C2C74043C207505E8239E
-:105720000AEEC3E9D2FE833EF8790174F6BED7795A
-:10573000E8110A8BD0AC3C2C74083C207404E9B707
-:10574000FE90E8FF09EFC3908B16067A833EF87946
-:1057500001740BBED779E8EB098BD0A3067AB02091
-:10576000E8570B8B16067AECE86F0BC38B16067A9C
-:10577000833EF87901740BBED779E8C7098BD0A3B3
-:10578000067AB020E8330B8B16067AEDE8670BC378
-:10579000FAC606F67900C390C606F67901FBC390F7
-:1057A00006E85809B020E8110B268B05E8470BB036
-:1057B00008E8060BE8030BE8000BE8FD0AB8010057
-:1057C000E8CFF4BA0202EC24017502EBDCBA06025F
-:1057D000EC07C390C706087A1000EB06C706087AE4
-:1057E0000100068E06FC798B3EFA79E80E09E80B7B
-:1057F00000893EFA798C06FC7907C390BEB24DE869
-:105800007C098B16087A52E82A09E80F0AE80C0A84
-:1058100033DBB9100090268A01E8BC09E8FD094392
-:10582000E2F4E8F709E8F40933DBB9100090268ABE
-:10583000013C2072053C7E760390B02EE8E30943DC
-:10584000E2ECBEB24DE8360983C7105A4A75B7C3B9
-:10585000068E06007A8B3EFE79E8A008893EFE7926
-:105860008C06007A578B360E7AE81209C706087A3A
-:105870001000BA0002E8E800E881FF5FBA0000E823
-:10588000DE00BEB54DE8F6088CC0E83F09B03AE846
-:1058900090098BC7E83509E87E08E8C30090E8B7AF
-:1058A00009E8A6090AC074F63C0B750683EF10EBF5
-:1058B00019903C0A750683C710EB0F903C0C7504D9
-:1058C00047EB07903C0875244F908B36FE798BC7C9
-:1058D0002BC63D000172A53D1001720483EE20909D
-:1058E00083C6108936FE79578BFEEB803C2E7508F7
-:1058F000BA0113E86A0007C3C6060A7A0232C990E1
-:105900003C30724C3C39760C245F3C4172423C4640
-:10591000773E2C072C3050E8CC085802C8FE0E0AFF
-:105920007A740FC0E104E82F09E81E090AC074F672
-:10593000EBCE26880DE8E0078AD0E823008AC13C38
-:105940002072053C7E760390B02EE8D508E970FF02
-:10595000E8C507E80A00268A05E87C08E91DFF90EB
-:10596000F606267A02750286F2528B361A7AE80D0E
-:10597000085A528AC60206247AF606267A01750665
-:10598000E89F08EB0D9032E4E80D088B361C7AE8AE
-:10599000EC075A8AC20206257AF606267A017506AF
-:1059A000E87F08EB069032E4E8ED078B361E7AE8D4
-:1059B000CC07C390068E06047A8B3E027AE83C0739
-:1059C000893E027A8C06047A07FF1E027AC3BE97CC
-:1059D0004DE8AA07CB900657BED779E866078BD863
-:1059E000E861078BC82BCB78118EC3BF0000B8FFCE
-:1059F000FF51B90800F3AB59E2F75F07C39006BE49
-:105A0000D779E83F078BD8D1E32E8B9F4400BE2681
-:105A100052E8F1088BC3E8DD08B80100E873F2E84A
-:105A2000E008BE2F52E8DD088B4718E8C808BE77AB
-:105A300052E8D1088B4726E8BC08BE5352E8C50897
-:105A40008B471EE8B008BE5C52E8B9088B4720E8D7
-:105A5000A408BE6E52E8AD088B4724E89808BE80C3
-:105A600052E8A1088B472AE88C08E89508BE38520E
-:105A7000E892088B07E87E08BE4152E887088B470A
-:105A80001AE87208BE4A52E87B088B471CE8660891
-:105A9000BE6552E86F088B4722E85A08E86308BEE3
-:105AA000D152E860088B4738E84B08BEAD52E85445
-:105AB000088B4730E83F08BEB652E848088B4732AB
-:105AC000E83308BEA452E83C088B472EE82708BEFE
-:105AD000BF52E830088B4734E81B08E82408BE8929
-:105AE00052E821088B4704E80C08BE9252E81508DA
-:105AF0008B4714E80008BE9B52E809088B472CE846
-:105B0000F407BEC852E8FD078B4736E8E807BEDA5F
-:105B100052E8F1078B473AE8DC07BEE352E8E507B5
-:105B20008B473CE8D007E8D907BE1953E8D6078B66
-:105B30004748E8C107BEFE52E8CA078B4742E8B5AE
-:105B400007BE0753E8BE078B4744E8A907BE7C534E
-:105B5000E8B2078B474CE89D07BE8553E8A6078B44
-:105B6000474EE89107BE8E53E89A078B4750E88569
-:105B700007E88E07BE2253E88B078B474AE8760773
-:105B8000BEEC52E87F078B4708E86A07BEF552E88B
-:105B900073078B4740E85E07BE1053E867078B47E3
-:105BA00046E85207E85B07BE6A53E858078B477A16
-:105BB000E84307BE3D53E84C078B4770E83707BE04
-:105BC0004653E840078B4772E82B07BE4F53E83433
-:105BD000078B4774E81F07E82807BE2B53E8250703
-:105BE0008B470CE81007BE3453E819078B4710E8C1
-:105BF0000407BE5853E80D078B4776E8F806BE61E8
-:105C000053E801078B4778E8EC06BE7353E8F506C6
-:105C10008B473EE8E006E8E906BE9753E8E6068BC8
-:105C20004752E8D106BEA053E8DA068B4754E8C5D0
-:105C300006BEA953E8CE068B4756E8B906BEB25356
-:105C4000E8C2068B4758E8AD06BEBB53E8B6068BE4
-:105C5000475AE8A106BEC453E8AA068B475CE895FC
-:105C600006E89E06BECD53E89B068B475EE8860697
-:105C7000BED653E88F068B4760E87A06BEDF53E84E
-:105C800083068B4762E86E06BEE853E877068B47CB
-:105C90007CE86206BEF153E86B068B477EE8560649
-:105CA000BEFA53E85F068B878000E84906E8520693
-:105CB000BE4254E84F068B879E00E83906BE035467
-:105CC000E842068B4764E82D06BE0C54E836068B86
-:105CD000476EE82106BE1554E82A068B878E00E839
-:105CE0001406BE1E54E81D068B879000E80706BE0A
-:105CF0002754E810068B879200E8FA05E80306BEF1
-:105D00003054E800068B879400E8EA05BE3954E871
-:105D1000F3058B879600E8DD05BE6F54E8E6058B3A
-:105D2000879800E8D005BE5D54E8D9058A87A000B1
-:105D3000E8A705BE5454E8CC058A4728E89B05BE71
-:105D40006654E8C0058A87A100E88E05E8B305BE61
-:105D50007854E8B0058A87A200E87E05BE8154E841
-:105D6000A3058A87A300E87105BE8A54E896058AD0
-:105D700087A400E86405BE9354E889058A87A500D6
-:105D8000E85705BE9C54E87C058A87A600E84A05CA
-:105D9000BEA554E86F058A87A700E83D05BEAE544E
-:105DA000E862058A87A800E83005E85505BEB754C3
-:105DB000E852058A87A900E82005BEC054E84505D9
-:105DC0008A87AA00E81305BEC954E838058A87AB5C
-:105DD00000E80605BED254E82B058A87AD00E8F935
-:105DE00004BEDB54E81E058A87AE00E8EC04BEE47E
-:105DF00054E811058A87AF00E8DF04BEED54E804DB
-:105E0000058A87B000E8D204E8F704BEF654E8F447
-:105E1000048A87B100E8C204BEFF54E8E7048A8719
-:105E2000B200E8B504BE0855E8DA048A87B300E892
-:105E3000A804BE1155E8CD048A87BB00E89B04E89E
-:105E4000C004BE1A55E8BD048A87BC00E88B04BEB6
-:105E50002355E8B0048A87BE00E87E04BE2C55E8CE
-:105E6000A3048A87BF00E87104E8960407C36006AC
-:105E70001E168BECFF4E16F7461A00027401FBB893
-:105E800000008ED88EC0892E2D7AE8CB0081661A4C
-:105E9000FFFEC6062A7A00E8D800B8005FA32B7A76
-:105EA000E85D00803E2A7A00740A814E1A0001C61D
-:105EB000062A7A00171F0761CF9060061E168BEC2A
-:105EC000F7461A00027401FBB800008ED88EC08914
-:105ED0002E2D7A81661AFFFEC6062A7A00E8920005
-:105EE000B8005FA32B7AE81700803E2A7A00740A74
-:105EF000814E1A0001C6062A7A00171F0761CF904B
-:105F0000B8F000E88CEDFF262B7AC390065356803C
-:105F10003E297A007403E83F00BED779E825028B5A
-:105F2000D8A3277A2E8A07A2297AB0CC2E88075EBA
-:105F30005B07C3C6062A7A00B80A5FA32B7AC39010
-:105F40008B2E2D7AE82B00C3C6062A7A01E80800BA
-:105F5000B80A5FA32B7AC39057803E297A00740F4A
-:105F60008B3E277AA0297A2E8805C606297A005FFB
-:105F7000C390BEB24DE80602BED851E80002FF76DB
-:105F80001458E84702BEDE51E8F301FF760E58E8E8
-:105F90003A02BEE451E8E601FF761258E82D02BE4F
-:105FA000EA51E8D901FF761058E82002BE1452E801
-:105FB000CC01FF760A58E81302BE1A52E8BF01FF6F
-:105FC000760C58E80602BECF51E8B201FF761A58A7
-:105FD000E8F901BEB24DE8A501BEF051E89F01FF0E
-:105FE000761858E8E601BEF651E89201FF760258AD
-:105FF000E8D901BEFC51E88501FF760458E8CC01E0
-:10600000BE0252E87801FF760058E8BF01BE085290
-:10601000E86B01FF760658E8B201BE0E52E85E0159
-:10602000FF760858E8A501BE2052E85101FF761618
-:1060300058E89801BE894DE84401C390BEC94DE8B7
-:106040003C01C33C0074053C017459C3C7060C7A7B
-:10605000CD50C7060E7AF050C706107AE850C70632
-:10606000127AEC50C706147AF450C706167AFB5021
-:10607000C706187A0351C7061A7A0B51C7061C7A4D
-:106080000E51C7061E7A1051C706207A1251C70654
-:10609000227A1651C606247A01C606257A01C6065A
-:1060A000267A03C3C7060C7A1A51C7060E7A4D51D9
-:1060B000C706107A4751C706127A4A51C706147AA2
-:1060C0004F51C706167A5151C706187A5551C7065F
-:1060D0001A7A5651C7061C7A5951C7061E7A5A5168
-:1060E000C706207A5B51C706227A5E51C606247A1B
-:1060F00020C606257A20C606267A02C3A1F879486A
-:106100007414BED779E83C008BF8AC3C3A75078E26
-:10611000C7E830008BF8C3908BC72B06FE798AF056
-:10612000240F8AD002D002D080C20BC0EE0480C6F9
-:1061300003043DC38CC0E89300B03AE8E4008BC789
-:10614000E88900C35133C990AC3C2074FB900AC06D
-:1061500074262C3072223C0976143C11721A2C07DA
-:106160003C0F760A3C2A72102C203C0F770A98C10B
-:10617000E10403C8ACEBD7904E8BC159C390068C99
-:10618000C88EC0E8020007C3268A04460AC0740607
-:10619000E88F00EBF390C3900BC0747A5133D2B9FF
-:1061A000E803F7F18BCAE803008BC159BA6400F623
-:1061B000F2E80C008AC498B20AF6F2E802008AC437
-:1061C000500AF074050430E8580058C386C4E80744
-:1061D0000086C4E80200C390C1C804E80800C1C03A
-:1061E00004E80200C3905350240FBBCA622ED7E8C4
-:1061F0003000585BC39086C4E8070086C4E80200FC
-:10620000C39050B908008AE032C0D1C00430E81110
-:1062100000E2F558C390B030E80700C3B020E801B1
-:1062200000C3568B36D0798884D0774681E6FF014B
-:10623000FF06D4798936D079813ED479FE0175087C
-:1062400056E814005EEBF1905EC3BA0202EC240142
-:106250007404BA0602ECC390803EF67900740960BB
-:10626000B80100E82CEA6190BA0202ECA804742894
-:106270008B36D279833ED47900741D8A84D07746D8
-:1062800081E6FF018936D279FF0ED479BA0602EE93
-:10629000BA0202ECA80475DCA1D479C352BA060292
-:1062A000EE5AC3905250BA0202ECA8047408585A2D
-:1062B000E8E9FFF9C390585AF8C35250BA0202EC09
-:1062C000A80474FB585AE8D3FFC330313233343555
-:1062D0003637383941424344454653508AE080E4DA
-:1062E0000FBBCA62C0E8042ED7E8CEFF8AC42ED7FF
-:1062F000E8C7FF585BC386E0E8DFFF86E0E8DAFF27
-:10630000C390BEB24D502EAC3C007405E8ABFFEB21
-:10631000F558C390C808000056578B7604BF040098
-:10632000C746FC0000C746FA0000C746F8000083D5
-:106330007E0600750E56E8B60E590BC075058BC764
-:10634000E95B018B46FC8946FE0BFF7505B8010031
-:10635000EB0233C05056E8A40D5959B4008946FCED
-:106360008B5EFC83FB087603E92B01D1E32EFFA7AC
-:10637000B264B80300E92601837EFA007414C746AC
-:10638000FA00008A445898508A44599850E8C20F3D
-:106390005959837EF800740AC746F8000056E89BF6
-:1063A0000859837E060075058BC7E9F10083FF0459
-:1063B0007503E9E6008BC7E9E400837EFE00750300
-:1063C000BF0200E9D500837EFE007503BF0100E92E
-:1063D000C9008B5EFE83FB077603E98600D1E32EBE
-:1063E000FFA7A26433FFE97F00BF0400807C580F41
-:1063F0007422837EF800751CFE44586A0856E87EB5
-:106400000C59598A445804805056E8720C5959C79F
-:1064100046FA0100837EF800740AC746F800005669
-:10642000E8190859EB42BF0400807C5800742283AD
-:106430007EF800751CFE4C586A0856E8410C595904
-:106440008A445804805056E8350C5959C746FA0119
-:1064500000837EF800740AC746F8000056E8DC079F
-:1064600059EB05BF0400EB00EB31BF0400EB2CC778
-:1064700046F801006A0856E8050C5959807C58090D
-:106480007D04B00FEB02B00004805056E8F00B59C9
-:1064900059BF0400EB05BF0400EB00E9A5FE5F5EF9
-:1064A000C9C3E4636364636463646364E963266427
-:1064B00051647863BA63C6639664D2636A646A643B
-:1064C0006F647263C808000056578B76048B7E0891
-:1064D0006A0156E8A90B59598A4606C0E0060480AD
-:1064E0005056E89A0B5959C746FE0000897EF8EBD2
-:1064F00003FF46FE8B5EF8FF46F8803F0075F2838F
-:106500007EFE107D25B810002B46FED1F88946FC92
-:10651000C746FA0000EB0B6A2056E8620B5959FF98
-:1065200046FA8B46FA3B46FC7CEDEB0C8BDF478A48
-:10653000075056E8490B5959803D0075EF6A0256DD
-:10654000E83C0B5959EB005F5EC9C3C80400005614
-:10655000578B7E04C746FE0000BE1400E909018B7C
-:106560005EFE83C3042BDF8A87AC0B88445AC64483
-:1065700058088A46FE884459C744060000C6441994
-:1065800000C6441A00C6441B00C6441D0DC6441E66
-:1065900003C6441F00C6442000C6442100C6445B15
-:1065A00000C6445D00C6445E00C6445F00C6446049
-:1065B00000C746FC0000EB0D8B5EFCD1E3C740300A
-:1065C0000000FF46FC837EFC107CEDC746FC00000B
-:1065D000EB0A8B5EFCC6405000FF46FC837EFC0449
-:1065E0007CF0C744540000C7445600008A445A98BF
-:1065F000BAF80023D0B805000BC28946FC9CFA8A81
-:1066000046FCBAFE00EEBA0000EC9D24088846FC69
-:10661000837EFC007502EB4AFF76FEE87A0C59682F
-:10662000350256E8320A59590BC07534683802569B
-:10663000E8250A59590BC0752768420256E8180A1E
-:1066400059590BC0751A684C0256E80B0A59590B78
-:10665000C0750D68560256E8FE0959590BC0740200
-:10666000EB00FF46FE83C662397EFE7D03E9EFFE46
-:10667000EB005F5EC9C3C808000056578B4604BADA
-:106680006200F7EA0514008BF0837E06007405B8FB
-:106690001000EB03B808008944048A460888445C6B
-:1066A00056E85904598BF88BC78944568944548A53
-:1066B000445D88442F0BFF751D68C20F6A0156E8C0
-:1066C00002FE83C406EB006A0156E847FC59590BE9
-:1066D000C075F4BF0100897EFAB90500BBE96A2ED6
-:1066E0008B073B46FA74074343E2F4E9A4032EFF09
-:1066F000670AC744060200C74408F4088B5E04D149
-:10670000E38B87FC0889440A33C08BF8894454E939
-:10671000800356E8BB0559BF01008A445D88446088
-:10672000E96F03837C04087530807C5C0175158AF1
-:10673000445DB400D1E08BD8FFB7E40856E8F70811
-:106740005959EB138A445DB400D1E08BD8FFB7C42C
-:106750000856E8E2085959EB2E807C5C0175158AD1
-:10676000445DB400D1E08BD8FFB7D40856E8C70821
-:106770005959EB138A445DB400D1E08BD8FFB7B40C
-:106780000856E8B20859596A0156E887FB59598BEF
-:10679000D883FB03772AD1E32EFFA7E16ABF01006C
-:1067A0008A445D88445EEB188A445D04FF240788B0
-:1067B000445DEB0C8A445DFEC0240788445DEB0019
-:1067C000E9CF028A445DB400D1E08BD8FFB7FD0267
-:1067D00056E863085959681D0356E85A0859596A1A
-:1067E0000156E82FFB59598BD883FB037736D1E349
-:1067F0002EFFA7D96ABF01008A445D88445FEB245D
-:106800008A445D04FF8A540480C2FF22C288445D2A
-:10681000EB128A445DFEC08A540480C2FF22C28803
-:10682000445DEB00E96B028B5C0683C3FED1E38B16
-:10683000400889048B1CFF77066A0056E885FC83B4
-:10684000C4068B5C064BD1E38B40088944028B5C09
-:1068500002FF77066A0156E86AFC83C4066A01569D
-:10686000E8B1FA59598BD883FB037603E91F02D1AB
-:10687000E32EFFA7D16A8B5C028B47048944028B0D
-:106880005C02803F44750D8B5C028A4701B4003B7B
-:1068900044047DE28B4604D1E08B1C03D88B440278
-:1068A0008947088B5C064BD1E38B4402894008E999
-:1068B000DE018B5C028B47028944028B5C02803FC5
-:1068C00044750D8B5C028A4701B4003B44047DE2B1
-:1068D0008B4604D1E08B1C03D88B44028947088B7C
-:1068E0005C064BD1E38B4402894008E9A201BF0159
-:1068F00000E99C018B5C028A07B4008946F8B90C58
-:1069000000BBA16A2E8B073B46F874074343E2F4B1
-:10691000E977012EFF67188B4604D1E08B5C0203F8
-:10692000D88B47088B5C06FF4406D1E38940088B6F
-:106930001C807F010074128B5C028A47018B1C8AC9
-:106940005701B6008BDA884018E94001FF4C06E990
-:106950003A018B5C028A47018B1C8A5701B6008B77
-:10696000DA884018E925018B5C028A47018B1C8A72
-:106970005701B6008BDA884018FF4C06E90D018BF1
-:106980005C028A47018B1C8A5701B6008BDA3040C3
-:1069900018E9F800B8F0108BF88944548A445F88ED
-:1069A000445DE9E7008A441C983D020074073D03FA
-:1069B000007402EB07C746FE0000EB2B8A441C98CC
-:1069C000D1E08BD8FFB7690256E86B0659596A01C6
-:1069D00056E840F959598946FE837EFE00740683C5
-:1069E0007EFE0375E9EB00837EFE0374628A441C1D
-:1069F00098D1E08BD8FFB76D0256E83A0659595640
-:106A0000E84D97598946FC8B5EFC83EBFE83FB03C4
-:106A10007733D1E32EFFA7996A68AC0256E81706D0
-:106A20005959EB23688F0256E80C065959EB186840
-:106A3000750256E801065959EB0D68C60256E8F68C
-:106A4000055959EB02EB006A0156E8C7F85959BFDE
-:106A50000100EB3868DD0256E8DC0559596A015639
-:106A6000E8B1F85959BF0100EB22B8D0308BF88952
-:106A700044548A446088445DEB12B8E0208BF88966
-:106A800044548A445E88445DEB02EB00EB02EB0069
-:106A9000EB00E941FC5F5EC9C3196A246A2F6A3AB8
-:106AA0006A0000010002000400410042004300446B
-:106AB00000800081008200FF001769546A7A6AA58D
-:106AC00069526994696A6A676952697F6967694C42
-:106AD00069F4687668B268EE68F56700681268F570
-:106AE000679D67A867B4679D6700000100F010E02C
-:106AF00020D0302768F266C36723671267C8040096
-:106B00000056578B76048A4459988946FC6A098B4B
-:106B100046FC05840150E8930859598BF88BC7252A
-:106B200000F03D001075558BC725F0003DF0007555
-:106B30004B8BC725000FC1F8088946FE8B44043BE8
-:106B400046FE7D0533C0E9EF008BC7250F00BA0F65
-:106B5000002BD03B56FE740533C0E9DB00C744026E
-:106B600004098A46FE88445F88445D8B5EFCD1E35D
-:106B7000C787FC080409B8F010E9BC008BC72500E2
-:106B8000F03D002075528BC725F0003DE0007548B0
-:106B90008BC725000FC1F8088946FE837EFE087E5C
-:106BA0000533C0E992008BC7250F00BA0F002BD028
-:106BB0003B56FE740533C0EB7F90C744020C098A34
-:106BC00046FE88445E88445D8B5EFCD1E3C787FC4B
-:106BD000080C09B8E020EB608BC72500F03D0030C1
-:106BE00075528BC725F0003DD00075488BC7250036
-:106BF0000FC1F8088946FE8B44043B46FE7D0433F2
-:106C0000C0EB358BC7250F00BA0F002BD03B56FECB
-:106C1000740433C0EB22C7440214098A46FE884438
-:106C20006088445D8B5EFCD1E3C787FC081409B81B
-:106C3000D030EB0433C0EB005F5EC9C3C806000070
-:106C4000568B76046A0856E8350459598A44580424
-:106C5000805056E8290459598B44543B4456750AD0
-:106C60008A445D3A442F7502EB648B445489445640
-:106C70008B5C028A470188442F8A445DB400C1E0DE
-:106C8000088B54540BD08A445DB400BB0F002BD842
-:106C90000BD38956FE6A108A445998050400990559
-:106CA000400183D2005250E8540883C4068956FC40
-:106CB0008946FA8B46FE0946FA834EFC006A19FFA4
-:106CC00076FCFF76FAE8730783C406E8FE075EC920
-:106CD000C3C81C000056578B5E048A4759988BF036
-:106CE0008B5E048A475DB4008946E6837EE6007DBC
-:106CF0000A8B5E048B4704488946E68B5E048B470B
-:106D0000043B46E67F05C746E600008B5E048A46E4
-:106D1000E688475D8BDED1E38B9F5902C647022090
-:106D20008BDED1E38B9F5902C64703308BDED1E364
-:106D30008B9F6102C64702208BDED1E38B9F6102ED
-:106D4000C64703308B46E68946FA837EFA007418FC
-:106D50008B46FABB0A0033D2F7F380C2308BDED108
-:106D6000E38B9F5902885703BB0A008B46FA33D244
-:106D7000F7F38946FA837EFA0074188B46FABB0A49
-:106D80000033D2F7F380C2308BDED1E38B9F590200
-:106D90008857028B46E68946FA837EFA0074188B80
-:106DA00046FABB0A0033D2F7F380C2308BDED1E360
-:106DB0008B9F6102885703BB0A008B46FA33D2F7D8
-:106DC000F38946FA837EFA0074188B46FABB0A00F0
-:106DD00033D2F7F380C2308BDED1E38B9F61028820
-:106DE00057028B5EE6D1E3FFB712026A00FF76041A
-:106DF000E8D1F683C40668D30F6A01FF7604E8C3BE
-:106E0000F683C406FF76E656E8019359598956F28F
-:106E10008946F0FF76E656E8149359598956EE896B
-:106E200046EC9CFAC45EF0268B078946EAC45EEC09
-:106E3000268B078946E8BA50FFED8946FE9DC74676
-:106E4000E40100E8EEA0BA50FFED8946FC8B46FC59
-:106E50002B46FE3DE8037303E980019CFABA50FF1C
-:106E6000ED8946FC8B46FC2B46FE8946F8C45EF055
-:106E7000268B072B46EA8946F6C45EF0268B0789E7
-:106E800046EAC45EEC268B072B46E88946F4C45ECE
-:106E9000EC268B078946E8BA50FFED8946FE9D81B6
-:106EA0007EF8E803761CFF76F8FF76F6E87601595F
-:106EB000598946F6FF76F8FF76F4E8680159598952
-:106EC00046F4BF0E00EB178BDED1E38B9F5902C651
-:106ED00001208BDED1E38B9F6102C601204783FF37
-:106EE0001176E48BDED1E38B9F5902C6470D308BC0
-:106EF000DED1E38B9F6102C6470D30837EF60977B2
-:106F000005B80D00EB26837EF6637705B80E00EB1F
-:106F10001B817EF6E7037705B80F00EB0F817EF645
-:106F20000F277705B81000EB03B811008BF8EB259D
-:106F30008B46F6BB0A0033D2F7F380C2308BDED12A
-:106F4000E38B9F590288114FBB0A008B46F633D260
-:106F5000F7F38946F6837EF60075D5837EF40977CC
-:106F600005B80D00EB26837EF4637705B80E00EBC1
-:106F70001B817EF4E7037705B80F00EB0F817EF4E9
-:106F80000F277705B81000EB03B811008BF8EB253D
-:106F90008B46F4BB0A0033D2F7F380C2308BDED1CC
-:106FA000E38B9F610288114FBB0A008B46F433D2FA
-:106FB000F7F38946F4837EF40075D58BDED1E3FFC9
-:106FC000B75902FF7604E86E0059598BDED1E3FF12
-:106FD000B76102FF7604E85E0059596A00FF760443
-:106FE000E831F359598BD883FB04771FD1E32EFF87
-:106FF000A71B70EB22C746E40000FF4EE6EB0CC770
-:1070000046E40000FF46E6EB02EB00837EE40074FA
-:1070100003E92AFEE9D4FC5F5EC9C3F36FF56FFF95
-:107020006FF36F0970558BEC8B4604B9E803F7E1F9
-:107030008B4E06F7F15DC3558BEC568B7606EB0E47
-:107040008BDE468A0750FF7604E833005959803CAE
-:107050000075EDEB005E5DC3558BEC568B7606EB51
-:10706000148BDE468A0750FF7604E8450059590B19
-:10707000C07402EB07803C0075E7EB005E5DC3C89F
-:10708000020000568B76048A445A988946FE9CFA80
-:107090008A46FEBAFE00EEBA0200ECA80274069D13
-:1070A000E8919EEBE9BA00008A4606EE9DEB005E91
-:1070B000C9C3C8040000568B76048A445A9889468E
-:1070C000FEE8E6A18946FCE8E0A12B46FC3DB80BB2
-:1070D0007605B80100EB239CFA8A46FEBAFE00EE64
-:1070E000BA0200ECA80274069DE8489EEBD9BA00EB
-:1070F000008A4606EE9D33C0EB005EC9C3C804009B
-:107100000056578B7604837E0600740756E8030109
-:1071100059EB0556E8A200598846FF807EFF0877A4
-:10712000068A46FFE98400807EFF0F7603EB7990A4
-:107130008A46FFB4002D0A008BD883FB047767D101
-:10714000E32EFFA7AF71B000EB6156E86B0059B4B6
-:1071500000250F008946FC56E85E0059B4008BF804
-:1071600056E8550059B400C1E0088BD703D08BFA1C
-:107170008B5EFCD1E3897830EB2E56E83B005988D2
-:10718000445BEB2456E831005988445056E8290006
-:107190005988445156E821005988445256E819004C
-:1071A00059884453EB02EB00E95BFF5F5EC9C346BD
-:1071B00071A6714A717A718471C8040000568B7689
-:1071C000048A445A988946FE9CFA8A46FEBAFE0012
-:1071D000EEBA0200ECA80175069DE8579DEBE9BAEE
-:1071E0000000EC8846FD9D8A46FDEB005EC9C3C8E1
-:1071F000020000568B76048A445A988946FE9CFA0F
-:107200008A46FEBAFE00EEBA0200EC32E424019D8A
-:107210005EC9C3C8060000568B76048A445A988912
-:1072200046FEE885A08946FAE87FA02B46FA3DB8DD
-:107230000B7604B008EB249CFA8A46FEBAFE00EEF8
-:10724000BA0200ECA80175069DE8E89CEBDABA00EA
-:1072500000EC8846FD9D8A46FDEB005EC9C3558B58
-:10726000EC568B56048A4606EE33F6EB035058462E
-:1072700083FE147CF85E5DC3C8020000568B560482
-:10728000EC8846FF33F6EB0350584683FE147CF837
-:107290008A46FFEB005EC9C3C802000056578B76D2
-:1072A00004833EB00B00751FBA8801B000EEBA86A9
-:1072B00001B000EE6A096A00683001E87D0183C40C
-:1072C00006C706B00B01006A098BC605800150E8AD
-:1072D000DA0059598BF88BC7C1E80C250F00894695
-:1072E000FE8BC7C1E808250F008B56FE83F20C3BCE
-:1072F000C275218BC7C1E804250F008B56FE83F2AF
-:10730000063BC2750F8BC7250F008B56FE83F20913
-:107310003BC2740D6A0756E838005959C746FE0744
-:10732000008A46FE0480A233028BC6BA6200F7EAE6
-:107330008A56FE8BD888976C006832028BC6BA6278
-:1073400000F7EA05140050E80EFD5959EB005F5EA6
-:10735000C9C3C8020000568B760683E60F8BC6C1F0
-:10736000E00C8BD683F20CC1E2080BC28BD683F201
-:1073700006C1E2040BC28BD683F2090BC28946FE1A
-:107380006A196A108B46049905400183D200525055
-:10739000E86B0183C4060B46FE83CA005250E89A8C
-:1073A0000083C406E82501EB005EC9C3558BEC568B
-:1073B0005733FF6A01688601E8A3FE5959B1102AC4
-:1073C0004E06D3660433F6EB2E817E0400807204F1
-:1073D000B001EB02B00050688801E881FE59596A9B
-:1073E00003688601E877FE59596A01688601E86DED
-:1073F000FE5959D16604463B76067CCD33F6EB2424
-:10740000D1E76A03688601E854FE59596A01688623
-:1074100001E84AFE5959688801E85CFE599825013F
-:10742000000BF84683FE107CD76A00688601E82DC1
-:10743000FE59598BC7EB005F5E5DC3558BEC565709
-:107440008B7E086A01688601E813FE5959B820004E
-:107450002BC750FF7606FF7604E8A20083C4068996
-:10746000560689460433F6EB47817E060080720C8F
-:107470007506837E04007204B001EB02B000506810
-:107480008801E8D9FD59596A03688601E8CFFD599A
-:10749000596A01688601E8C5FD59596A01FF7606F7
-:1074A000FF7604E8580083C40689560689460446D8
-:1074B0003BF77CB56A00688601E8A2FD59596A006D
-:1074C000688601E898FD59595F5E5DC3558BEC569F
-:1074D0006A01688601E886FD595933F6EB00688831
-:1074E00001E894FD59A80175088BC6463D64007CEF
-:1074F000ED6A00688601E865FD59595E5DC3C80400
-:1075000000008B46048B56068B4E08E306D1E0D173
-:10751000D2E2FA8946FC8956FE8B56FE8B46FCEB7E
-:1075200000C9C300000000000000000000000000CF
-:1075300050726576696F7573204D656E7500426592
-:1075400067696E00000000000000000000000000FD
-:10755000000000000000000000000000000000002B
-:10756000000000000000000000000000000000001B
-:10757000000000000000000000000000000000000B
-:1075800000000000000000000000000000000000FB
-:1075900000000000000000000000000000000000EB
-:1075A00000000000000000000000000000000000DB
-:1075B00000000000000000000000000000000000CB
-:1075C00000000000000000000000000000000000BB
-:1075D00000000000000000000000000000000000AB
-:1075E000000000000000000000000000000000009B
-:1075F000000000000000000000000000000000008B
-:10760000000000000000000000000000000000007A
-:10761000000000000000000000000000000000006A
-:10762000000000000000000000000000000000005A
-:10763000000000000000000000000000000000004A
-:10764000000000000000000000000000000000003A
-:10765000000000000000000000000000000000002A
-:10766000000000000000000000000000000000001A
-:10767000000000000000000000000000000000000A
-:1076800000000000000000000000000000000000FA
-:1076900000000000000000000000000000000000EA
-:1076A00000000000000000000000000000000000DA
-:1076B00000000000000000000000000000000000CA
-:1076C000000000000000000000000000506F727415
-:1076D000203000506F7274203100506F727420326D
-:1076E00000506F7274203300506F72742034005059
-:1076F0006F7274203500506F7274203600506F72B4
-:1077000074203700506F7274203800506F727420EC
-:107710003900506F727420313000506F7274203114
-:107720003100506F727420313200506F727420310A
-:107730003300506F727420313400506F72742031F6
-:1077400035009C01A301AA01B101B801BF01C60126
-:10775000CD01D401DB01E201EA01F201FA010202EA
-:107760000A02080000078100038080809F919591A4
-:107770009F000381848E95848484840003828484A2
-:107780008484958E8400048800B20BC60BDA0BEE5D
-:107790000B020C160C2A0C3E0C520C770C9C0CBEE7
-:1077A0000CE00C020D01802054657374205061734D
-:1077B000736564201F20507265737320800200017E
-:1077C00080204D697373696E67205278204461741C
-:1077D000611F205072657373208002000180204277
-:1077E00061642052782044617461201F20507265CA
-:1077F000737320800200018020586D7472204275DE
-:1078000073791F20507265737320800200018020FD
-:107810006E6F742063757272656E746C791F2020B0
-:10782000696D706C656D656E7465640200240D2F62
-:107830000D3A0D450D500D5B0D660D710D7C0D87DC
-:107840000D920D9D0DA80DB30DBE0DC90D53802CCD
-:107850003254442053862C334454522053822C33C8
-:10786000525453201F53812C3252442053852C32C2
-:1078700043442053832C334354532053842C3344A8
-:1078800053522053872C3252492702000180202076
-:10789000444344202D2070696E2032301F275385C9
-:1078A0002E31818263908081828384858687888956
-:1078B0008A8B8C8D8E8F27020001802020445352AA
-:1078C000202D2070696E2031311F2753842E318185
-:1078D000826390808182838485868788898A8B8C65
-:1078E0008D8E8F27020001802020435453202D20AD
-:1078F00070696E20341F2753832E318182639080FC
-:107900008182838485868788898A8B8C8D8E8F2758
-:107910000200018020205249202D2070696E203203
-:10792000321F2753872E3181826390808182838426
-:1079300085868788898A8B8C8D8E8F2702000180AF
-:107940002020445452202D2070696E20362F381F7D
-:107950002753862E3181826390808182838485863D
-:107960008788898A8B8C8D8E8F270200018020204A
-:10797000525453202D2070696E20351F2753822EBC
-:107980003181826390808182838485868788898A19
-:107990008B8C8D8E8F27020001802020527844200E
-:1079A0002D2070696E20321F2753812E30534D8158
-:1079B000826390808182838485868788898A8B8C84
-:1079C0008D8E8F27020001802020547844202D20A6
-:1079D00070696E20331F2753802E30534D81826390
-:1079E00090808182838485868788898A8B8C8D8E1E
-:1079F0008F27020001802020444344202D207069FD
-:107A00006E20351F2753852E3181826390808182BD
-:107A1000838485868788898A8B8C8D8E8F27020048
-:107A200001802020445352202D2070696E20351F84
-:107A30002753842E3181826390808182838485865E
-:107A40008788898A8B8C8D8E8F2702000180202069
-:107A5000435453202D2070696E20311F2753832EED
-:107A60003181826390808182838485868788898A38
-:107A70008B8C8D8E8F270200018020205249202D73
-:107A800020286E2E632E291F2753872E3181826373
-:107A900090808182838485868788898A8B8C8D8E6D
-:107AA0008F27020001802020445452202D2070692D
-:107AB0006E20321F2753862E31818263908081820F
-:107AC000838485868788898A8B8C8D8E8F27020098
-:107AD00001802020525453202D2070696E20371FC2
-:107AE0002753822E318182639080818283848586B0
-:107AF0008788898A8B8C8D8E8F27020001802020B9
-:107B0000527844202D2070696E20361F2753812E15
-:107B100030534D81826390808182838485868788FB
-:107B2000898A8B8C8D8E8F270200018020205478CB
-:107B300044202D2070696E20331F2753802E305330
-:107B40004D81826390808182838485868788898A3B
-:107B50008B8C8D8E8F27020001802020444344208F
-:107B60002D2070696E20351F202020202753852E60
-:107B700031818263888081828384858687270200A1
-:107B800001802020445352202D2070696E20351F23
-:107B9000202020202753842E318182638880818297
-:107BA0008384858687270200018020204354532048
-:107BB0002D2070696E20311F202020202753832E16
-:107BC0003181826388808182838485868727020051
-:107BD000018020205249202D20286E2E632E291F3F
-:107BE000202020202753872E318182638880818244
-:107BF00083848586872702000180202044545220F8
-:107C00002D2070696E20321F202020202753862EC1
-:107C10003181826388808182838485868727020000
-:107C200001802020525453202D2070696E20371F70
-:107C3000202020202753822E3181826388808182F8
-:107C40008384858687270200018020205278442083
-:107C50002D2070696E20361F202020202753812E72
-:107C600030534D8182638880818283848586872713
-:107C7000020001802020547844202D2070696E205D
-:107C8000331F202020202753802E30534D818263C4
-:107C90008880818283848586872702000180202056
-:107CA000444344202D2070696E2032301F20202054
-:107CB000202753852E318182638880818283848549
-:107CC000868727020001802020445352202D2070F7
-:107CD000696E2031311F202020202753842E3181CE
-:107CE0008263888081828384858687270200018061
-:107CF0002020435453202D2070696E20341F2020F3
-:107D000020202753832E318182638880818283845F
-:107D1000858687270200018020205249202D20706F
-:107D2000696E2032321F202020202753872E318178
-:107D30008263888081828384858687270200018010
-:107D40002020445452202D2070696E20362F381F79
-:107D5000202020202753862E3181826388808182D3
-:107D60008384858687270200018020205254532077
-:107D70002D2070696E20351F202020202753822E51
-:107D8000318182638880818283848586872702008F
-:107D900001802020527844202D2070696E20321FEF
-:107DA000202020202753812E30534D8182638880EC
-:107DB0008182838485868727020001802020547871
-:107DC00044202D2070696E20331F2020202027534F
-:107DD000802E30534D8182638880818283848586A2
-:107DE0008727020068049604B6033C040E04890346
-:107DF0005C03E20360088A08BE0738080E0895078E
-:107E00006C07E6071C057405FA05C404F004CC05EC
-:107E1000A00548057806C806420728065006180738
-:107E2000F006A0060000F408F408D40D04090409C3
-:107E30000409040942000C091C09E50D020014099B
-:107E40000409F40D43001C090C09050E0004040983
-:107E50001409120E2C092C092C092C0900003C09CC
-:107E60006C091E0E740974097409740900014C0927
-:107E70002C092D0E740974097409740900025C0937
-:107E80003C093D0E740974097409740900036C09F6
-:107E90004C094D0E7409740974097409FF002C090A
-:107EA0005C09000000058409EC095E0EF409F40980
-:107EB000F409F409000694097409680EAC0AAC0AC6
-:107EC000AC0AAC0A0007A4098409720EBC0ABC0AF9
-:107ED000BC0ABC0A0008B40994097C0ED40AD40A6E
-:107EE000D40AD40A000BC409A409830EFC0AFC0AB4
-:107EF000FC0AFC0A000CD409B409900E140B140BF4
-:107F0000140B140B0002E409C409A00E2C0B2C0B5B
-:107F10002C0B2C0B0400EC09D4090E00FF00740993
-:107F2000E40900008201FC09A40AAC0E8202040AE2
-:107F3000F409AF0E82030C0AFC09B20E8204140A83
-:107F4000040AB60E82051C0A0C0ABC0E8206240A1C
-:107F5000140AC00E82072C0A1C0AC40E8208340AB6
-:107F6000240AC80E82093C0A2C0ACC0E820A440A52
-:107F7000340AD10E82104C0A3C0AD60E820B540AE7
-:107F8000440ADB0E82115C0A4C0AE00E820C640A81
-:107F9000540AE50E82126C0A5C0AEA0E820D740A1B
-:107FA000640AEF0E820E7C0A6C0AF40E820F840AB9
-:107FB000740AFB0E82138C0A7C0A020F8214940A44
-:107FC000840A090F82159C0A8C0A100F8216A40AD3
-:107FD000940A170F8217F4099C0A1E0F8202B40A32
-:107FE000B40A260F8203AC0AAC0A2D0F8200C40A21
-:107FF000CC0A340F8201CC0ABC0A3F0F8202BC0AB1
-:10800000C40A4D0F8200DC0AF40A590F8201E40A07
-:10801000D40A630F8202EC0ADC0A6E0F8203F40AB0
-:10802000E40A7A0F8204D40AEC0A870F8200040B58
-:108030000C0B930F82010C0BFC0A9B0F8202FC0AB3
-:10804000040BA70F82001C0B240BB00F8201240B22
-:10805000140BB50F8202140B1C0BBE0F4400340B23
-:10806000A40B9C0144013C0B2C0BA3014402440BC8
-:10807000340BAA0144034C0B3C0BB1014404540BD8
-:10808000440BB80144055C0B4C0BBF014406640B68
-:10809000540BC60144076C0B5C0BCD014408740BF8
-:1080A000640BD40144097C0B6C0BDB01440A840B88
-:1080B000740BE201440B8C0B7C0BEA01440C940B17
-:1080C000840BF201440D9C0B8C0BFA01440EA40BA3
-:1080D000940B0202440F2C0B9C0B0A02171F0F2F4C
-:1080E0000000018078783A20747820637073202A29
-:1080F0002A2A2A2A0200018078783A20747820639C
-:108100007073202A2A2A2A2A0200018078783A20CD
-:10811000747820637073202A2A2A2A2A0200018098
-:1081200078783A20747820637073202A2A2A2A2AC1
-:10813000020001C078783A20726320637073202AAD
-:108140002A2A2A2A020001C078783A207263206322
-:108150007073202A2A2A2A2A020001C078783A203D
-:10816000726320637073202A2A2A2A2A020001C01F
-:1081700078783A20726320637073202A2A2A2A2A88
-:1081800002000180496E7374616C6C204C6F6F70DB
-:108190006261636B1F5072657373208020746F205F
-:1081A000737461727402000180204361626C652007
-:1081B000746F2052656D6F74651F50726573732004
-:1081C0008020746F20737461727402000180204CEF
-:1081D0006F63616C204C6F6F706261636B201F2056
-:1081E0002052756E6E696E67202E2E2E0200018061
-:1081F00052656D6F7465204C6F6F706261636B20A8
-:108200001F202052756E6E696E67202E2E2E020082
-:10821000018020496E74726E6C204C6F6F706261C9
-:10822000636B1F202052756E6E696E67202E2E2E96
-:10823000020001805472616E736D69742050617424
-:108240007465726E1F202052756E6E696E67202EE7
-:108250002E2E020001802020303A2027438000018A
-:10826000802020313A202743810001802020323AAB
-:10827000202743820001802020333A2027438300B7
-:1082800001802020343A20274384000180202035BB
-:108290003A202743850001802020363A2027438654
-:1082A0000001802020373A202743870001802020CA
-:1082B000383A202743880001802020393A2027437C
-:1082C000890001802031303A2027438A0001802034
-:1082D00031313A2027438B0001802031323A202768
-:1082E000438C0001802031333A2027438D000180E8
-:1082F0002031343A2027438E0001802031353A2046
-:1083000027438F002A2A204D61696E20204D656E1B
-:1083100075202A2A004D6F6E69746F72206120509B
-:108320006F7274004D6F6E69746F722061205369B3
-:10833000676E616C00457374696D617465204350AC
-:108340005300446961676E6F7374696373004C6FA7
-:1083500063616C204C6F6F706261636B0052656D7E
-:108360006F7465204C6F6F706261636B00496E744F
-:10837000726E6C204C6F6F706261636B005472613F
-:108380006E736D6974205061747465726E00426121
-:10839000756420526174650044617461204269749F
-:1083A000730053746F702042697473005061726976
-:1083B00074790044617461205061747465726E0058
-:1083C000547820466C6F7720436F6E74726F6C0028
-:1083D000506F7274204E756D6265720035300037D3
-:1083E0003500313130003133342E35003135300035
-:1083F00032303000333030003630300031323030FF
-:10840000003138303000323030300032343030001B
-:1084100033363030003438303000373230300039C5
-:108420003630300031392C3230300033382C343093
-:10843000300035362C3030300035372C36303000B7
-:1084400036342C3030300037362C38303000313173
-:10845000352C323030003720626974730038206266
-:1084600069747300312073746F7020626974003115
-:108470002E352073746F702062697473003220731C
-:10848000746F702062697473006E6F20706172691E
-:108490007479006F64642070617269747900657624
-:1084A000656E207061726974790073706163652014
-:1084B000706172697479006D61726B2070617269AC
-:1084C000747900436F6C756D6E7300426172626502
-:1084D0007220506F6C650055555555552E2E2E0047
-:1084E0004E6F6E6500586F6E2F586F66660043546E
-:1084F00053005072657373208020666F72206D6523
-:108500006E750028636F756E74696E672E2E2E2946
-:108510000000654E64204F6620436F4465000000F4
-:10852000000000000000000000000000000000004B
-:10853000000000000000000000000000000000003B
-:10854000000000000000000000000000000000002B
-:10855000000000000000000000000000000000001B
-:10856000000000000000000000000000000000000B
-:1085700000000000000000000000000000000000FB
-:1085800000000000000000000000000000000000EB
-:1085900000000000000000000000000000000000DB
-:1085A00000000000000000000000000000000000CB
-:1085B00000000000000000000000000000000000BB
-:1085C00000000000000000000000000000000000AB
-:1085D000000000000000000000000000000000009B
-:1085E000000000000000000000000000000000008B
-:1085F000000000000000000000000000000000007B
-:00000001FF
-/* Intelliport II loadware */
-/* -31232 bytes read from ff.lod */
diff --git a/fs/bio.c b/fs/bio.c
index 5eaa70c..71072ab 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -73,7 +73,7 @@
{
unsigned int sz = sizeof(struct bio) + extra_size;
struct kmem_cache *slab = NULL;
- struct bio_slab *bslab;
+ struct bio_slab *bslab, *new_bio_slabs;
unsigned int i, entry = -1;
mutex_lock(&bio_slab_lock);
@@ -97,11 +97,12 @@
if (bio_slab_nr == bio_slab_max && entry == -1) {
bio_slab_max <<= 1;
- bio_slabs = krealloc(bio_slabs,
- bio_slab_max * sizeof(struct bio_slab),
- GFP_KERNEL);
- if (!bio_slabs)
+ new_bio_slabs = krealloc(bio_slabs,
+ bio_slab_max * sizeof(struct bio_slab),
+ GFP_KERNEL);
+ if (!new_bio_slabs)
goto out_unlock;
+ bio_slabs = new_bio_slabs;
}
if (entry == -1)
entry = bio_slab_nr++;
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 1e51919..38e721b 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1578,10 +1578,12 @@
unsigned long nr_segs, loff_t pos)
{
struct file *file = iocb->ki_filp;
+ struct blk_plug plug;
ssize_t ret;
BUG_ON(iocb->ki_pos != pos);
+ blk_start_plug(&plug);
ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos);
if (ret > 0 || ret == -EIOCBQUEUED) {
ssize_t err;
@@ -1590,6 +1592,7 @@
if (err < 0 && ret > 0)
ret = err;
}
+ blk_finish_plug(&plug);
return ret;
}
EXPORT_SYMBOL_GPL(blkdev_aio_write);
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index a256f3b..ff6475f 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -1438,10 +1438,10 @@
ret = extent_from_logical(fs_info, logical, path,
&found_key);
btrfs_release_path(path);
- if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK)
- ret = -EINVAL;
if (ret < 0)
return ret;
+ if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK)
+ return -EINVAL;
extent_item_pos = logical - found_key.objectid;
ret = iterate_extent_inodes(fs_info, found_key.objectid,
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
index 86eff48..43d1c5a 100644
--- a/fs/btrfs/compression.c
+++ b/fs/btrfs/compression.c
@@ -818,6 +818,7 @@
btrfs_compress_op[idx]->free_workspace(workspace);
atomic_dec(alloc_workspace);
wake:
+ smp_mb();
if (waitqueue_active(workspace_wait))
wake_up(workspace_wait);
}
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 9d7621f..6d183f6 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -421,12 +421,6 @@
spin_unlock(&fs_info->tree_mod_seq_lock);
/*
- * we removed the lowest blocker from the blocker list, so there may be
- * more processible delayed refs.
- */
- wake_up(&fs_info->tree_mod_seq_wait);
-
- /*
* anything that's lower than the lowest existing (read: blocked)
* sequence number can be removed from the tree.
*/
@@ -631,6 +625,9 @@
u32 nritems;
int ret;
+ if (btrfs_header_level(eb) == 0)
+ return;
+
nritems = btrfs_header_nritems(eb);
for (i = nritems - 1; i >= 0; i--) {
ret = tree_mod_log_insert_key_locked(fs_info, eb, i,
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 4bab807..0d195b5 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1252,7 +1252,6 @@
atomic_t tree_mod_seq;
struct list_head tree_mod_seq_list;
struct seq_list tree_mod_seq_elem;
- wait_queue_head_t tree_mod_seq_wait;
/* this protects tree_mod_log */
rwlock_t tree_mod_log_lock;
@@ -3192,7 +3191,7 @@
int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode,
struct bio *bio, u32 *dst);
int btrfs_lookup_bio_sums_dio(struct btrfs_root *root, struct inode *inode,
- struct bio *bio, u64 logical_offset, u32 *dst);
+ struct bio *bio, u64 logical_offset);
int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
u64 objectid, u64 pos,
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
index 335605c..07d5eeb 100644
--- a/fs/btrfs/delayed-inode.c
+++ b/fs/btrfs/delayed-inode.c
@@ -512,8 +512,8 @@
rb_erase(&delayed_item->rb_node, root);
delayed_item->delayed_node->count--;
- atomic_dec(&delayed_root->items);
- if (atomic_read(&delayed_root->items) < BTRFS_DELAYED_BACKGROUND &&
+ if (atomic_dec_return(&delayed_root->items) <
+ BTRFS_DELAYED_BACKGROUND &&
waitqueue_active(&delayed_root->wait))
wake_up(&delayed_root->wait);
}
@@ -1028,9 +1028,10 @@
btrfs_release_delayed_item(prev);
ret = 0;
btrfs_release_path(path);
- if (curr)
+ if (curr) {
+ mutex_unlock(&node->mutex);
goto do_again;
- else
+ } else
goto delete_fail;
}
@@ -1055,8 +1056,7 @@
delayed_node->count--;
delayed_root = delayed_node->root->fs_info->delayed_root;
- atomic_dec(&delayed_root->items);
- if (atomic_read(&delayed_root->items) <
+ if (atomic_dec_return(&delayed_root->items) <
BTRFS_DELAYED_BACKGROUND &&
waitqueue_active(&delayed_root->wait))
wake_up(&delayed_root->wait);
diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c
index da7419e..ae94117 100644
--- a/fs/btrfs/delayed-ref.c
+++ b/fs/btrfs/delayed-ref.c
@@ -38,17 +38,14 @@
static int comp_tree_refs(struct btrfs_delayed_tree_ref *ref2,
struct btrfs_delayed_tree_ref *ref1)
{
- if (ref1->node.type == BTRFS_TREE_BLOCK_REF_KEY) {
- if (ref1->root < ref2->root)
- return -1;
- if (ref1->root > ref2->root)
- return 1;
- } else {
- if (ref1->parent < ref2->parent)
- return -1;
- if (ref1->parent > ref2->parent)
- return 1;
- }
+ if (ref1->root < ref2->root)
+ return -1;
+ if (ref1->root > ref2->root)
+ return 1;
+ if (ref1->parent < ref2->parent)
+ return -1;
+ if (ref1->parent > ref2->parent)
+ return 1;
return 0;
}
@@ -85,7 +82,8 @@
* type of the delayed backrefs and content of delayed backrefs.
*/
static int comp_entry(struct btrfs_delayed_ref_node *ref2,
- struct btrfs_delayed_ref_node *ref1)
+ struct btrfs_delayed_ref_node *ref1,
+ bool compare_seq)
{
if (ref1->bytenr < ref2->bytenr)
return -1;
@@ -102,10 +100,12 @@
if (ref1->type > ref2->type)
return 1;
/* merging of sequenced refs is not allowed */
- if (ref1->seq < ref2->seq)
- return -1;
- if (ref1->seq > ref2->seq)
- return 1;
+ if (compare_seq) {
+ if (ref1->seq < ref2->seq)
+ return -1;
+ if (ref1->seq > ref2->seq)
+ return 1;
+ }
if (ref1->type == BTRFS_TREE_BLOCK_REF_KEY ||
ref1->type == BTRFS_SHARED_BLOCK_REF_KEY) {
return comp_tree_refs(btrfs_delayed_node_to_tree_ref(ref2),
@@ -139,7 +139,7 @@
entry = rb_entry(parent_node, struct btrfs_delayed_ref_node,
rb_node);
- cmp = comp_entry(entry, ins);
+ cmp = comp_entry(entry, ins, 1);
if (cmp < 0)
p = &(*p)->rb_left;
else if (cmp > 0)
@@ -233,6 +233,114 @@
return 0;
}
+static void inline drop_delayed_ref(struct btrfs_trans_handle *trans,
+ struct btrfs_delayed_ref_root *delayed_refs,
+ struct btrfs_delayed_ref_node *ref)
+{
+ rb_erase(&ref->rb_node, &delayed_refs->root);
+ ref->in_tree = 0;
+ btrfs_put_delayed_ref(ref);
+ delayed_refs->num_entries--;
+ if (trans->delayed_ref_updates)
+ trans->delayed_ref_updates--;
+}
+
+static int merge_ref(struct btrfs_trans_handle *trans,
+ struct btrfs_delayed_ref_root *delayed_refs,
+ struct btrfs_delayed_ref_node *ref, u64 seq)
+{
+ struct rb_node *node;
+ int merged = 0;
+ int mod = 0;
+ int done = 0;
+
+ node = rb_prev(&ref->rb_node);
+ while (node) {
+ struct btrfs_delayed_ref_node *next;
+
+ next = rb_entry(node, struct btrfs_delayed_ref_node, rb_node);
+ node = rb_prev(node);
+ if (next->bytenr != ref->bytenr)
+ break;
+ if (seq && next->seq >= seq)
+ break;
+ if (comp_entry(ref, next, 0))
+ continue;
+
+ if (ref->action == next->action) {
+ mod = next->ref_mod;
+ } else {
+ if (ref->ref_mod < next->ref_mod) {
+ struct btrfs_delayed_ref_node *tmp;
+
+ tmp = ref;
+ ref = next;
+ next = tmp;
+ done = 1;
+ }
+ mod = -next->ref_mod;
+ }
+
+ merged++;
+ drop_delayed_ref(trans, delayed_refs, next);
+ ref->ref_mod += mod;
+ if (ref->ref_mod == 0) {
+ drop_delayed_ref(trans, delayed_refs, ref);
+ break;
+ } else {
+ /*
+ * You can't have multiples of the same ref on a tree
+ * block.
+ */
+ WARN_ON(ref->type == BTRFS_TREE_BLOCK_REF_KEY ||
+ ref->type == BTRFS_SHARED_BLOCK_REF_KEY);
+ }
+
+ if (done)
+ break;
+ node = rb_prev(&ref->rb_node);
+ }
+
+ return merged;
+}
+
+void btrfs_merge_delayed_refs(struct btrfs_trans_handle *trans,
+ struct btrfs_fs_info *fs_info,
+ struct btrfs_delayed_ref_root *delayed_refs,
+ struct btrfs_delayed_ref_head *head)
+{
+ struct rb_node *node;
+ u64 seq = 0;
+
+ spin_lock(&fs_info->tree_mod_seq_lock);
+ if (!list_empty(&fs_info->tree_mod_seq_list)) {
+ struct seq_list *elem;
+
+ elem = list_first_entry(&fs_info->tree_mod_seq_list,
+ struct seq_list, list);
+ seq = elem->seq;
+ }
+ spin_unlock(&fs_info->tree_mod_seq_lock);
+
+ node = rb_prev(&head->node.rb_node);
+ while (node) {
+ struct btrfs_delayed_ref_node *ref;
+
+ ref = rb_entry(node, struct btrfs_delayed_ref_node,
+ rb_node);
+ if (ref->bytenr != head->node.bytenr)
+ break;
+
+ /* We can't merge refs that are outside of our seq count */
+ if (seq && ref->seq >= seq)
+ break;
+ if (merge_ref(trans, delayed_refs, ref, seq))
+ node = rb_prev(&head->node.rb_node);
+ else
+ node = rb_prev(node);
+ }
+}
+
int btrfs_check_delayed_seq(struct btrfs_fs_info *fs_info,
struct btrfs_delayed_ref_root *delayed_refs,
u64 seq)
@@ -336,18 +444,11 @@
* every changing the extent allocation tree.
*/
existing->ref_mod--;
- if (existing->ref_mod == 0) {
- rb_erase(&existing->rb_node,
- &delayed_refs->root);
- existing->in_tree = 0;
- btrfs_put_delayed_ref(existing);
- delayed_refs->num_entries--;
- if (trans->delayed_ref_updates)
- trans->delayed_ref_updates--;
- } else {
+ if (existing->ref_mod == 0)
+ drop_delayed_ref(trans, delayed_refs, existing);
+ else
WARN_ON(existing->type == BTRFS_TREE_BLOCK_REF_KEY ||
existing->type == BTRFS_SHARED_BLOCK_REF_KEY);
- }
} else {
WARN_ON(existing->type == BTRFS_TREE_BLOCK_REF_KEY ||
existing->type == BTRFS_SHARED_BLOCK_REF_KEY);
@@ -662,9 +763,6 @@
add_delayed_tree_ref(fs_info, trans, &ref->node, bytenr,
num_bytes, parent, ref_root, level, action,
for_cow);
- if (!need_ref_seq(for_cow, ref_root) &&
- waitqueue_active(&fs_info->tree_mod_seq_wait))
- wake_up(&fs_info->tree_mod_seq_wait);
spin_unlock(&delayed_refs->lock);
if (need_ref_seq(for_cow, ref_root))
btrfs_qgroup_record_ref(trans, &ref->node, extent_op);
@@ -713,9 +811,6 @@
add_delayed_data_ref(fs_info, trans, &ref->node, bytenr,
num_bytes, parent, ref_root, owner, offset,
action, for_cow);
- if (!need_ref_seq(for_cow, ref_root) &&
- waitqueue_active(&fs_info->tree_mod_seq_wait))
- wake_up(&fs_info->tree_mod_seq_wait);
spin_unlock(&delayed_refs->lock);
if (need_ref_seq(for_cow, ref_root))
btrfs_qgroup_record_ref(trans, &ref->node, extent_op);
@@ -744,8 +839,6 @@
num_bytes, BTRFS_UPDATE_DELAYED_HEAD,
extent_op->is_data);
- if (waitqueue_active(&fs_info->tree_mod_seq_wait))
- wake_up(&fs_info->tree_mod_seq_wait);
spin_unlock(&delayed_refs->lock);
return 0;
}
diff --git a/fs/btrfs/delayed-ref.h b/fs/btrfs/delayed-ref.h
index 0d7c90c..ab53005 100644
--- a/fs/btrfs/delayed-ref.h
+++ b/fs/btrfs/delayed-ref.h
@@ -167,6 +167,10 @@
struct btrfs_trans_handle *trans,
u64 bytenr, u64 num_bytes,
struct btrfs_delayed_extent_op *extent_op);
+void btrfs_merge_delayed_refs(struct btrfs_trans_handle *trans,
+ struct btrfs_fs_info *fs_info,
+ struct btrfs_delayed_ref_root *delayed_refs,
+ struct btrfs_delayed_ref_head *head);
struct btrfs_delayed_ref_head *
btrfs_find_delayed_ref_head(struct btrfs_trans_handle *trans, u64 bytenr);
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 62e0caf..22e98e0 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -377,9 +377,13 @@
ret = read_extent_buffer_pages(io_tree, eb, start,
WAIT_COMPLETE,
btree_get_extent, mirror_num);
- if (!ret && !verify_parent_transid(io_tree, eb,
+ if (!ret) {
+ if (!verify_parent_transid(io_tree, eb,
parent_transid, 0))
- break;
+ break;
+ else
+ ret = -EIO;
+ }
/*
* This buffer's crc is fine, but its contents are corrupted, so
@@ -754,9 +758,7 @@
limit = btrfs_async_submit_limit(fs_info);
limit = limit * 2 / 3;
- atomic_dec(&fs_info->nr_async_submits);
-
- if (atomic_read(&fs_info->nr_async_submits) < limit &&
+ if (atomic_dec_return(&fs_info->nr_async_submits) < limit &&
waitqueue_active(&fs_info->async_submit_wait))
wake_up(&fs_info->async_submit_wait);
@@ -2032,8 +2034,6 @@
fs_info->free_chunk_space = 0;
fs_info->tree_mod_log = RB_ROOT;
- init_waitqueue_head(&fs_info->tree_mod_seq_wait);
-
/* readahead state */
INIT_RADIX_TREE(&fs_info->reada_tree, GFP_NOFS & ~__GFP_WAIT);
spin_lock_init(&fs_info->reada_lock);
@@ -2528,8 +2528,7 @@
goto fail_trans_kthread;
/* do not make disk changes in broken FS */
- if (btrfs_super_log_root(disk_super) != 0 &&
- !(fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR)) {
+ if (btrfs_super_log_root(disk_super) != 0) {
u64 bytenr = btrfs_super_log_root(disk_super);
if (fs_devices->rw_devices == 0) {
@@ -3189,30 +3188,14 @@
/* clear out the rbtree of defraggable inodes */
btrfs_run_defrag_inodes(fs_info);
- /*
- * Here come 2 situations when btrfs is broken to flip readonly:
- *
- * 1. when btrfs flips readonly somewhere else before
- * btrfs_commit_super, sb->s_flags has MS_RDONLY flag,
- * and btrfs will skip to write sb directly to keep
- * ERROR state on disk.
- *
- * 2. when btrfs flips readonly just in btrfs_commit_super,
- * and in such case, btrfs cannot write sb via btrfs_commit_super,
- * and since fs_state has been set BTRFS_SUPER_FLAG_ERROR flag,
- * btrfs will cleanup all FS resources first and write sb then.
- */
if (!(fs_info->sb->s_flags & MS_RDONLY)) {
ret = btrfs_commit_super(root);
if (ret)
printk(KERN_ERR "btrfs: commit super ret %d\n", ret);
}
- if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) {
- ret = btrfs_error_commit_super(root);
- if (ret)
- printk(KERN_ERR "btrfs: commit super ret %d\n", ret);
- }
+ if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR)
+ btrfs_error_commit_super(root);
btrfs_put_block_group_cache(fs_info);
@@ -3434,18 +3417,11 @@
if (read_only)
return 0;
- if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) {
- printk(KERN_WARNING "warning: mount fs with errors, "
- "running btrfsck is recommended\n");
- }
-
return 0;
}
-int btrfs_error_commit_super(struct btrfs_root *root)
+void btrfs_error_commit_super(struct btrfs_root *root)
{
- int ret;
-
mutex_lock(&root->fs_info->cleaner_mutex);
btrfs_run_delayed_iputs(root);
mutex_unlock(&root->fs_info->cleaner_mutex);
@@ -3455,10 +3431,6 @@
/* cleanup FS via transaction */
btrfs_cleanup_transaction(root);
-
- ret = write_ctree_super(NULL, root, 0);
-
- return ret;
}
static void btrfs_destroy_ordered_operations(struct btrfs_root *root)
@@ -3782,14 +3754,17 @@
/* FIXME: cleanup wait for commit */
t->in_commit = 1;
t->blocked = 1;
+ smp_mb();
if (waitqueue_active(&root->fs_info->transaction_blocked_wait))
wake_up(&root->fs_info->transaction_blocked_wait);
t->blocked = 0;
+ smp_mb();
if (waitqueue_active(&root->fs_info->transaction_wait))
wake_up(&root->fs_info->transaction_wait);
t->commit_done = 1;
+ smp_mb();
if (waitqueue_active(&t->commit_wait))
wake_up(&t->commit_wait);
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index 95e147e..c5b00a7 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -54,7 +54,7 @@
struct btrfs_root *root, int max_mirrors);
struct buffer_head *btrfs_read_dev_super(struct block_device *bdev);
int btrfs_commit_super(struct btrfs_root *root);
-int btrfs_error_commit_super(struct btrfs_root *root);
+void btrfs_error_commit_super(struct btrfs_root *root);
struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root,
u64 bytenr, u32 blocksize);
struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root,
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 4e1b153..ba58024 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2252,6 +2252,16 @@
}
/*
+ * We need to try and merge add/drops of the same ref since we
+ * can run into issues with relocate dropping the implicit ref
+ * and then it being added back again before the drop can
+ * finish. If we merged anything we need to re-loop so we can
+ * get a good ref.
+ */
+ btrfs_merge_delayed_refs(trans, fs_info, delayed_refs,
+ locked_ref);
+
+ /*
* locked_ref is the head node, so we have to go one
* node back for any delayed ref updates
*/
@@ -2318,12 +2328,23 @@
ref->in_tree = 0;
rb_erase(&ref->rb_node, &delayed_refs->root);
delayed_refs->num_entries--;
- /*
- * we modified num_entries, but as we're currently running
- * delayed refs, skip
- * wake_up(&delayed_refs->seq_wait);
- * here.
- */
+ if (locked_ref) {
+ /*
+ * when we play the delayed ref, also correct the
+ * ref_mod on head
+ */
+ switch (ref->action) {
+ case BTRFS_ADD_DELAYED_REF:
+ case BTRFS_ADD_DELAYED_EXTENT:
+ locked_ref->node.ref_mod -= ref->ref_mod;
+ break;
+ case BTRFS_DROP_DELAYED_REF:
+ locked_ref->node.ref_mod += ref->ref_mod;
+ break;
+ default:
+ WARN_ON(1);
+ }
+ }
spin_unlock(&delayed_refs->lock);
ret = run_one_delayed_ref(trans, root, ref, extent_op,
@@ -2350,22 +2371,6 @@
return count;
}
-static void wait_for_more_refs(struct btrfs_fs_info *fs_info,
- struct btrfs_delayed_ref_root *delayed_refs,
- unsigned long num_refs,
- struct list_head *first_seq)
-{
- spin_unlock(&delayed_refs->lock);
- pr_debug("waiting for more refs (num %ld, first %p)\n",
- num_refs, first_seq);
- wait_event(fs_info->tree_mod_seq_wait,
- num_refs != delayed_refs->num_entries ||
- fs_info->tree_mod_seq_list.next != first_seq);
- pr_debug("done waiting for more refs (num %ld, first %p)\n",
- delayed_refs->num_entries, fs_info->tree_mod_seq_list.next);
- spin_lock(&delayed_refs->lock);
-}
-
#ifdef SCRAMBLE_DELAYED_REFS
/*
* Normally delayed refs get processed in ascending bytenr order. This
@@ -2460,13 +2465,11 @@
struct btrfs_delayed_ref_root *delayed_refs;
struct btrfs_delayed_ref_node *ref;
struct list_head cluster;
- struct list_head *first_seq = NULL;
int ret;
u64 delayed_start;
int run_all = count == (unsigned long)-1;
int run_most = 0;
- unsigned long num_refs = 0;
- int consider_waiting;
+ int loops;
/* We'll clean this up in btrfs_cleanup_transaction */
if (trans->aborted)
@@ -2484,7 +2487,7 @@
delayed_refs = &trans->transaction->delayed_refs;
INIT_LIST_HEAD(&cluster);
again:
- consider_waiting = 0;
+ loops = 0;
spin_lock(&delayed_refs->lock);
#ifdef SCRAMBLE_DELAYED_REFS
@@ -2512,31 +2515,6 @@
if (ret)
break;
- if (delayed_start >= delayed_refs->run_delayed_start) {
- if (consider_waiting == 0) {
- /*
- * btrfs_find_ref_cluster looped. let's do one
- * more cycle. if we don't run any delayed ref
- * during that cycle (because we can't because
- * all of them are blocked) and if the number of
- * refs doesn't change, we avoid busy waiting.
- */
- consider_waiting = 1;
- num_refs = delayed_refs->num_entries;
- first_seq = root->fs_info->tree_mod_seq_list.next;
- } else {
- wait_for_more_refs(root->fs_info, delayed_refs,
- num_refs, first_seq);
- /*
- * after waiting, things have changed. we
- * dropped the lock and someone else might have
- * run some refs, built new clusters and so on.
- * therefore, we restart staleness detection.
- */
- consider_waiting = 0;
- }
- }
-
ret = run_clustered_refs(trans, root, &cluster);
if (ret < 0) {
spin_unlock(&delayed_refs->lock);
@@ -2549,9 +2527,26 @@
if (count == 0)
break;
- if (ret || delayed_refs->run_delayed_start == 0) {
+ if (delayed_start >= delayed_refs->run_delayed_start) {
+ if (loops == 0) {
+ /*
+ * btrfs_find_ref_cluster looped. let's do one
+ * more cycle. if we don't run any delayed ref
+ * during that cycle (because we can't because
+ * all of them are blocked), bail out.
+ */
+ loops = 1;
+ } else {
+ /*
+ * no runnable refs left, stop trying
+ */
+ BUG_ON(run_all);
+ break;
+ }
+ }
+ if (ret) {
/* refs were run, let's reset staleness detection */
- consider_waiting = 0;
+ loops = 0;
}
}
@@ -3007,17 +3002,16 @@
}
spin_unlock(&block_group->lock);
- num_pages = (int)div64_u64(block_group->key.offset, 1024 * 1024 * 1024);
+ /*
+ * Try to preallocate enough space based on how big the block group is.
+ * Keep in mind this has to include any pinned space which could end up
+ * taking up quite a bit since it's not folded into the other space
+ * cache.
+ */
+ num_pages = (int)div64_u64(block_group->key.offset, 256 * 1024 * 1024);
if (!num_pages)
num_pages = 1;
- /*
- * Just to make absolutely sure we have enough space, we're going to
- * preallocate 12 pages worth of space for each block group. In
- * practice we ought to use at most 8, but we need extra space so we can
- * add our header and have a terminator between the extents and the
- * bitmaps.
- */
num_pages *= 16;
num_pages *= PAGE_CACHE_SIZE;
@@ -4571,8 +4565,10 @@
if (root->fs_info->quota_enabled) {
ret = btrfs_qgroup_reserve(root, num_bytes +
nr_extents * root->leafsize);
- if (ret)
+ if (ret) {
+ mutex_unlock(&BTRFS_I(inode)->delalloc_mutex);
return ret;
+ }
}
ret = reserve_metadata_bytes(root, block_rsv, to_reserve, flush);
@@ -5294,9 +5290,6 @@
rb_erase(&head->node.rb_node, &delayed_refs->root);
delayed_refs->num_entries--;
- smp_mb();
- if (waitqueue_active(&root->fs_info->tree_mod_seq_wait))
- wake_up(&root->fs_info->tree_mod_seq_wait);
/*
* we don't take a ref on the node because we're removing it from the
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 45c81bb..4c87847 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -2330,23 +2330,10 @@
if (uptodate && tree->ops && tree->ops->readpage_end_io_hook) {
ret = tree->ops->readpage_end_io_hook(page, start, end,
state, mirror);
- if (ret) {
- /* no IO indicated but software detected errors
- * in the block, either checksum errors or
- * issues with the contents */
- struct btrfs_root *root =
- BTRFS_I(page->mapping->host)->root;
- struct btrfs_device *device;
-
+ if (ret)
uptodate = 0;
- device = btrfs_find_device_for_logical(
- root, start, mirror);
- if (device)
- btrfs_dev_stat_inc_and_print(device,
- BTRFS_DEV_STAT_CORRUPTION_ERRS);
- } else {
+ else
clean_io_failure(start, page);
- }
}
if (!uptodate && tree->ops && tree->ops->readpage_io_failed_hook) {
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
index b45b9de..857d93c 100644
--- a/fs/btrfs/file-item.c
+++ b/fs/btrfs/file-item.c
@@ -272,9 +272,9 @@
}
int btrfs_lookup_bio_sums_dio(struct btrfs_root *root, struct inode *inode,
- struct bio *bio, u64 offset, u32 *dst)
+ struct bio *bio, u64 offset)
{
- return __btrfs_lookup_bio_sums(root, inode, bio, offset, dst, 1);
+ return __btrfs_lookup_bio_sums(root, inode, bio, offset, NULL, 1);
}
int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 6e8f416..ec154f9 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1008,9 +1008,7 @@
nr_pages = (async_cow->end - async_cow->start + PAGE_CACHE_SIZE) >>
PAGE_CACHE_SHIFT;
- atomic_sub(nr_pages, &root->fs_info->async_delalloc_pages);
-
- if (atomic_read(&root->fs_info->async_delalloc_pages) <
+ if (atomic_sub_return(nr_pages, &root->fs_info->async_delalloc_pages) <
5 * 1024 * 1024 &&
waitqueue_active(&root->fs_info->async_submit_wait))
wake_up(&root->fs_info->async_submit_wait);
@@ -1885,8 +1883,11 @@
trans = btrfs_join_transaction_nolock(root);
else
trans = btrfs_join_transaction(root);
- if (IS_ERR(trans))
- return PTR_ERR(trans);
+ if (IS_ERR(trans)) {
+ ret = PTR_ERR(trans);
+ trans = NULL;
+ goto out;
+ }
trans->block_rsv = &root->fs_info->delalloc_block_rsv;
ret = btrfs_update_inode_fallback(trans, root, inode);
if (ret) /* -ENOMEM or corruption */
@@ -3174,7 +3175,7 @@
btrfs_i_size_write(dir, dir->i_size - name_len * 2);
inode_inc_iversion(dir);
dir->i_mtime = dir->i_ctime = CURRENT_TIME;
- ret = btrfs_update_inode(trans, root, dir);
+ ret = btrfs_update_inode_fallback(trans, root, dir);
if (ret)
btrfs_abort_transaction(trans, root, ret);
out:
@@ -5774,18 +5775,112 @@
return ret;
}
+static int lock_extent_direct(struct inode *inode, u64 lockstart, u64 lockend,
+ struct extent_state **cached_state, int writing)
+{
+ struct btrfs_ordered_extent *ordered;
+ int ret = 0;
+
+ while (1) {
+ lock_extent_bits(&BTRFS_I(inode)->io_tree, lockstart, lockend,
+ 0, cached_state);
+ /*
+ * We're concerned with the entire range that we're going to be
+ * doing DIO to, so we need to make sure theres no ordered
+ * extents in this range.
+ */
+ ordered = btrfs_lookup_ordered_range(inode, lockstart,
+ lockend - lockstart + 1);
+
+ /*
+ * We need to make sure there are no buffered pages in this
+ * range either, we could have raced between the invalidate in
+ * generic_file_direct_write and locking the extent. The
+ * invalidate needs to happen so that reads after a write do not
+ * get stale data.
+ */
+ if (!ordered && (!writing ||
+ !test_range_bit(&BTRFS_I(inode)->io_tree,
+ lockstart, lockend, EXTENT_UPTODATE, 0,
+ *cached_state)))
+ break;
+
+ unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart, lockend,
+ cached_state, GFP_NOFS);
+
+ if (ordered) {
+ btrfs_start_ordered_extent(inode, ordered, 1);
+ btrfs_put_ordered_extent(ordered);
+ } else {
+ /* Screw you mmap */
+ ret = filemap_write_and_wait_range(inode->i_mapping,
+ lockstart,
+ lockend);
+ if (ret)
+ break;
+
+ /*
+ * If we found a page that couldn't be invalidated just
+ * fall back to buffered.
+ */
+ ret = invalidate_inode_pages2_range(inode->i_mapping,
+ lockstart >> PAGE_CACHE_SHIFT,
+ lockend >> PAGE_CACHE_SHIFT);
+ if (ret)
+ break;
+ }
+
+ cond_resched();
+ }
+
+ return ret;
+}
+
static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
struct buffer_head *bh_result, int create)
{
struct extent_map *em;
struct btrfs_root *root = BTRFS_I(inode)->root;
+ struct extent_state *cached_state = NULL;
u64 start = iblock << inode->i_blkbits;
+ u64 lockstart, lockend;
u64 len = bh_result->b_size;
struct btrfs_trans_handle *trans;
+ int unlock_bits = EXTENT_LOCKED;
+ int ret;
+
+ if (create) {
+ ret = btrfs_delalloc_reserve_space(inode, len);
+ if (ret)
+ return ret;
+ unlock_bits |= EXTENT_DELALLOC | EXTENT_DIRTY;
+ } else {
+ len = min_t(u64, len, root->sectorsize);
+ }
+
+ lockstart = start;
+ lockend = start + len - 1;
+
+ /*
+ * If this errors out it's because we couldn't invalidate pagecache for
+ * this range and we need to fallback to buffered.
+ */
+ if (lock_extent_direct(inode, lockstart, lockend, &cached_state, create))
+ return -ENOTBLK;
+
+ if (create) {
+ ret = set_extent_bit(&BTRFS_I(inode)->io_tree, lockstart,
+ lockend, EXTENT_DELALLOC, NULL,
+ &cached_state, GFP_NOFS);
+ if (ret)
+ goto unlock_err;
+ }
em = btrfs_get_extent(inode, NULL, 0, start, len, 0);
- if (IS_ERR(em))
- return PTR_ERR(em);
+ if (IS_ERR(em)) {
+ ret = PTR_ERR(em);
+ goto unlock_err;
+ }
/*
* Ok for INLINE and COMPRESSED extents we need to fallback on buffered
@@ -5804,17 +5899,16 @@
if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags) ||
em->block_start == EXTENT_MAP_INLINE) {
free_extent_map(em);
- return -ENOTBLK;
+ ret = -ENOTBLK;
+ goto unlock_err;
}
/* Just a good old fashioned hole, return */
if (!create && (em->block_start == EXTENT_MAP_HOLE ||
test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) {
free_extent_map(em);
- /* DIO will do one hole at a time, so just unlock a sector */
- unlock_extent(&BTRFS_I(inode)->io_tree, start,
- start + root->sectorsize - 1);
- return 0;
+ ret = 0;
+ goto unlock_err;
}
/*
@@ -5827,8 +5921,9 @@
*
*/
if (!create) {
- len = em->len - (start - em->start);
- goto map;
+ len = min(len, em->len - (start - em->start));
+ lockstart = start + len;
+ goto unlock;
}
if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags) ||
@@ -5860,7 +5955,7 @@
btrfs_end_transaction(trans, root);
if (ret) {
free_extent_map(em);
- return ret;
+ goto unlock_err;
}
goto unlock;
}
@@ -5873,14 +5968,12 @@
*/
len = bh_result->b_size;
em = btrfs_new_extent_direct(inode, em, start, len);
- if (IS_ERR(em))
- return PTR_ERR(em);
+ if (IS_ERR(em)) {
+ ret = PTR_ERR(em);
+ goto unlock_err;
+ }
len = min(len, em->len - (start - em->start));
unlock:
- clear_extent_bit(&BTRFS_I(inode)->io_tree, start, start + len - 1,
- EXTENT_LOCKED | EXTENT_DELALLOC | EXTENT_DIRTY, 1,
- 0, NULL, GFP_NOFS);
-map:
bh_result->b_blocknr = (em->block_start + (start - em->start)) >>
inode->i_blkbits;
bh_result->b_size = len;
@@ -5898,9 +5991,44 @@
i_size_write(inode, start + len);
}
+ /*
+ * In the case of write we need to clear and unlock the entire range,
+ * in the case of read we need to unlock only the end area that we
+ * aren't using if there is any left over space.
+ */
+ if (lockstart < lockend) {
+ if (create && len < lockend - lockstart) {
+ clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart,
+ lockstart + len - 1, unlock_bits, 1, 0,
+ &cached_state, GFP_NOFS);
+ /*
+ * Beside unlock, we also need to cleanup reserved space
+ * for the left range by attaching EXTENT_DO_ACCOUNTING.
+ */
+ clear_extent_bit(&BTRFS_I(inode)->io_tree,
+ lockstart + len, lockend,
+ unlock_bits | EXTENT_DO_ACCOUNTING,
+ 1, 0, NULL, GFP_NOFS);
+ } else {
+ clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart,
+ lockend, unlock_bits, 1, 0,
+ &cached_state, GFP_NOFS);
+ }
+ } else {
+ free_extent_state(cached_state);
+ }
+
free_extent_map(em);
return 0;
+
+unlock_err:
+ if (create)
+ unlock_bits |= EXTENT_DO_ACCOUNTING;
+
+ clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, lockend,
+ unlock_bits, 1, 0, &cached_state, GFP_NOFS);
+ return ret;
}
struct btrfs_dio_private {
@@ -5908,7 +6036,6 @@
u64 logical_offset;
u64 disk_bytenr;
u64 bytes;
- u32 *csums;
void *private;
/* number of bios pending for this dio */
@@ -5928,7 +6055,6 @@
struct inode *inode = dip->inode;
struct btrfs_root *root = BTRFS_I(inode)->root;
u64 start;
- u32 *private = dip->csums;
start = dip->logical_offset;
do {
@@ -5936,8 +6062,12 @@
struct page *page = bvec->bv_page;
char *kaddr;
u32 csum = ~(u32)0;
+ u64 private = ~(u32)0;
unsigned long flags;
+ if (get_state_private(&BTRFS_I(inode)->io_tree,
+ start, &private))
+ goto failed;
local_irq_save(flags);
kaddr = kmap_atomic(page);
csum = btrfs_csum_data(root, kaddr + bvec->bv_offset,
@@ -5947,18 +6077,18 @@
local_irq_restore(flags);
flush_dcache_page(bvec->bv_page);
- if (csum != *private) {
+ if (csum != private) {
+failed:
printk(KERN_ERR "btrfs csum failed ino %llu off"
" %llu csum %u private %u\n",
(unsigned long long)btrfs_ino(inode),
(unsigned long long)start,
- csum, *private);
+ csum, (unsigned)private);
err = -EIO;
}
}
start += bvec->bv_len;
- private++;
bvec++;
} while (bvec <= bvec_end);
@@ -5966,7 +6096,6 @@
dip->logical_offset + dip->bytes - 1);
bio->bi_private = dip->private;
- kfree(dip->csums);
kfree(dip);
/* If we had a csum failure make sure to clear the uptodate flag */
@@ -6072,7 +6201,7 @@
static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode,
int rw, u64 file_offset, int skip_sum,
- u32 *csums, int async_submit)
+ int async_submit)
{
int write = rw & REQ_WRITE;
struct btrfs_root *root = BTRFS_I(inode)->root;
@@ -6105,8 +6234,7 @@
if (ret)
goto err;
} else if (!skip_sum) {
- ret = btrfs_lookup_bio_sums_dio(root, inode, bio,
- file_offset, csums);
+ ret = btrfs_lookup_bio_sums_dio(root, inode, bio, file_offset);
if (ret)
goto err;
}
@@ -6132,10 +6260,8 @@
u64 submit_len = 0;
u64 map_length;
int nr_pages = 0;
- u32 *csums = dip->csums;
int ret = 0;
int async_submit = 0;
- int write = rw & REQ_WRITE;
map_length = orig_bio->bi_size;
ret = btrfs_map_block(map_tree, READ, start_sector << 9,
@@ -6171,16 +6297,13 @@
atomic_inc(&dip->pending_bios);
ret = __btrfs_submit_dio_bio(bio, inode, rw,
file_offset, skip_sum,
- csums, async_submit);
+ async_submit);
if (ret) {
bio_put(bio);
atomic_dec(&dip->pending_bios);
goto out_err;
}
- /* Write's use the ordered csums */
- if (!write && !skip_sum)
- csums = csums + nr_pages;
start_sector += submit_len >> 9;
file_offset += submit_len;
@@ -6210,7 +6333,7 @@
submit:
ret = __btrfs_submit_dio_bio(bio, inode, rw, file_offset, skip_sum,
- csums, async_submit);
+ async_submit);
if (!ret)
return 0;
@@ -6246,17 +6369,6 @@
ret = -ENOMEM;
goto free_ordered;
}
- dip->csums = NULL;
-
- /* Write's use the ordered csum stuff, so we don't need dip->csums */
- if (!write && !skip_sum) {
- dip->csums = kmalloc(sizeof(u32) * bio->bi_vcnt, GFP_NOFS);
- if (!dip->csums) {
- kfree(dip);
- ret = -ENOMEM;
- goto free_ordered;
- }
- }
dip->private = bio->bi_private;
dip->inode = inode;
@@ -6341,132 +6453,22 @@
out:
return retval;
}
+
static ssize_t btrfs_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_mapping->host;
- struct btrfs_ordered_extent *ordered;
- struct extent_state *cached_state = NULL;
- u64 lockstart, lockend;
- ssize_t ret;
- int writing = rw & WRITE;
- int write_bits = 0;
- size_t count = iov_length(iov, nr_segs);
if (check_direct_IO(BTRFS_I(inode)->root, rw, iocb, iov,
- offset, nr_segs)) {
+ offset, nr_segs))
return 0;
- }
- lockstart = offset;
- lockend = offset + count - 1;
-
- if (writing) {
- ret = btrfs_delalloc_reserve_space(inode, count);
- if (ret)
- goto out;
- }
-
- while (1) {
- lock_extent_bits(&BTRFS_I(inode)->io_tree, lockstart, lockend,
- 0, &cached_state);
- /*
- * We're concerned with the entire range that we're going to be
- * doing DIO to, so we need to make sure theres no ordered
- * extents in this range.
- */
- ordered = btrfs_lookup_ordered_range(inode, lockstart,
- lockend - lockstart + 1);
-
- /*
- * We need to make sure there are no buffered pages in this
- * range either, we could have raced between the invalidate in
- * generic_file_direct_write and locking the extent. The
- * invalidate needs to happen so that reads after a write do not
- * get stale data.
- */
- if (!ordered && (!writing ||
- !test_range_bit(&BTRFS_I(inode)->io_tree,
- lockstart, lockend, EXTENT_UPTODATE, 0,
- cached_state)))
- break;
-
- unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart, lockend,
- &cached_state, GFP_NOFS);
-
- if (ordered) {
- btrfs_start_ordered_extent(inode, ordered, 1);
- btrfs_put_ordered_extent(ordered);
- } else {
- /* Screw you mmap */
- ret = filemap_write_and_wait_range(file->f_mapping,
- lockstart,
- lockend);
- if (ret)
- goto out;
-
- /*
- * If we found a page that couldn't be invalidated just
- * fall back to buffered.
- */
- ret = invalidate_inode_pages2_range(file->f_mapping,
- lockstart >> PAGE_CACHE_SHIFT,
- lockend >> PAGE_CACHE_SHIFT);
- if (ret) {
- if (ret == -EBUSY)
- ret = 0;
- goto out;
- }
- }
-
- cond_resched();
- }
-
- /*
- * we don't use btrfs_set_extent_delalloc because we don't want
- * the dirty or uptodate bits
- */
- if (writing) {
- write_bits = EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING;
- ret = set_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, lockend,
- EXTENT_DELALLOC, NULL, &cached_state,
- GFP_NOFS);
- if (ret) {
- clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart,
- lockend, EXTENT_LOCKED | write_bits,
- 1, 0, &cached_state, GFP_NOFS);
- goto out;
- }
- }
-
- free_extent_state(cached_state);
- cached_state = NULL;
-
- ret = __blockdev_direct_IO(rw, iocb, inode,
+ return __blockdev_direct_IO(rw, iocb, inode,
BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev,
iov, offset, nr_segs, btrfs_get_blocks_direct, NULL,
btrfs_submit_direct, 0);
-
- if (ret < 0 && ret != -EIOCBQUEUED) {
- clear_extent_bit(&BTRFS_I(inode)->io_tree, offset,
- offset + iov_length(iov, nr_segs) - 1,
- EXTENT_LOCKED | write_bits, 1, 0,
- &cached_state, GFP_NOFS);
- } else if (ret >= 0 && ret < iov_length(iov, nr_segs)) {
- /*
- * We're falling back to buffered, unlock the section we didn't
- * do IO on.
- */
- clear_extent_bit(&BTRFS_I(inode)->io_tree, offset + ret,
- offset + iov_length(iov, nr_segs) - 1,
- EXTENT_LOCKED | write_bits, 1, 0,
- &cached_state, GFP_NOFS);
- }
-out:
- free_extent_state(cached_state);
- return ret;
}
static int btrfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 7bb7556..9df50fa 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -424,7 +424,7 @@
uuid_le_gen(&new_uuid);
memcpy(root_item.uuid, new_uuid.b, BTRFS_UUID_SIZE);
root_item.otime.sec = cpu_to_le64(cur_time.tv_sec);
- root_item.otime.nsec = cpu_to_le64(cur_time.tv_nsec);
+ root_item.otime.nsec = cpu_to_le32(cur_time.tv_nsec);
root_item.ctime = root_item.otime;
btrfs_set_root_ctransid(&root_item, trans->transid);
btrfs_set_root_otransid(&root_item, trans->transid);
diff --git a/fs/btrfs/locking.c b/fs/btrfs/locking.c
index a44eff074..2a1762c 100644
--- a/fs/btrfs/locking.c
+++ b/fs/btrfs/locking.c
@@ -67,7 +67,7 @@
{
if (eb->lock_nested) {
read_lock(&eb->lock);
- if (&eb->lock_nested && current->pid == eb->lock_owner) {
+ if (eb->lock_nested && current->pid == eb->lock_owner) {
read_unlock(&eb->lock);
return;
}
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index bc424ae..38b42e7 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -1364,13 +1364,17 @@
spin_lock(&fs_info->qgroup_lock);
dstgroup = add_qgroup_rb(fs_info, objectid);
- if (!dstgroup)
+ if (IS_ERR(dstgroup)) {
+ ret = PTR_ERR(dstgroup);
goto unlock;
+ }
if (srcid) {
srcgroup = find_qgroup_rb(fs_info, srcid);
- if (!srcgroup)
+ if (!srcgroup) {
+ ret = -EINVAL;
goto unlock;
+ }
dstgroup->rfer = srcgroup->rfer - level_size;
dstgroup->rfer_cmpr = srcgroup->rfer_cmpr - level_size;
srcgroup->excl = level_size;
@@ -1379,8 +1383,10 @@
qgroup_dirty(fs_info, srcgroup);
}
- if (!inherit)
+ if (!inherit) {
+ ret = -EINVAL;
goto unlock;
+ }
i_qgroups = (u64 *)(inherit + 1);
for (i = 0; i < inherit->num_qgroups; ++i) {
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c
index 6bb465c..10d8e4d 100644
--- a/fs/btrfs/root-tree.c
+++ b/fs/btrfs/root-tree.c
@@ -544,8 +544,8 @@
struct timespec ct = CURRENT_TIME;
spin_lock(&root->root_times_lock);
- item->ctransid = trans->transid;
+ item->ctransid = cpu_to_le64(trans->transid);
item->ctime.sec = cpu_to_le64(ct.tv_sec);
- item->ctime.nsec = cpu_to_le64(ct.tv_nsec);
+ item->ctime.nsec = cpu_to_le32(ct.tv_nsec);
spin_unlock(&root->root_times_lock);
}
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index f2eb24c..83d6f9f 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -838,7 +838,6 @@
struct btrfs_trans_handle *trans;
struct btrfs_fs_info *fs_info = btrfs_sb(sb);
struct btrfs_root *root = fs_info->tree_root;
- int ret;
trace_btrfs_sync_fs(wait);
@@ -849,11 +848,17 @@
btrfs_wait_ordered_extents(root, 0, 0);
- trans = btrfs_start_transaction(root, 0);
+ spin_lock(&fs_info->trans_lock);
+ if (!fs_info->running_transaction) {
+ spin_unlock(&fs_info->trans_lock);
+ return 0;
+ }
+ spin_unlock(&fs_info->trans_lock);
+
+ trans = btrfs_join_transaction(root);
if (IS_ERR(trans))
return PTR_ERR(trans);
- ret = btrfs_commit_transaction(trans, root);
- return ret;
+ return btrfs_commit_transaction(trans, root);
}
static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry)
@@ -1530,6 +1535,8 @@
while (cur_devices) {
head = &cur_devices->devices;
list_for_each_entry(dev, head, dev_list) {
+ if (dev->missing)
+ continue;
if (!first_dev || dev->devid < first_dev->devid)
first_dev = dev;
}
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 17be3de..27c2600 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -1031,6 +1031,7 @@
btrfs_i_size_write(parent_inode, parent_inode->i_size +
dentry->d_name.len * 2);
+ parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME;
ret = btrfs_update_inode(trans, parent_root, parent_inode);
if (ret)
goto abort_trans_dput;
@@ -1066,7 +1067,7 @@
memcpy(new_root_item->parent_uuid, root->root_item.uuid,
BTRFS_UUID_SIZE);
new_root_item->otime.sec = cpu_to_le64(cur_time.tv_sec);
- new_root_item->otime.nsec = cpu_to_le64(cur_time.tv_nsec);
+ new_root_item->otime.nsec = cpu_to_le32(cur_time.tv_nsec);
btrfs_set_root_otransid(new_root_item, trans->transid);
memset(&new_root_item->stime, 0, sizeof(new_root_item->stime));
memset(&new_root_item->rtime, 0, sizeof(new_root_item->rtime));
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index e86ae04..88b969a 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -227,9 +227,8 @@
cur = pending;
pending = pending->bi_next;
cur->bi_next = NULL;
- atomic_dec(&fs_info->nr_async_bios);
- if (atomic_read(&fs_info->nr_async_bios) < limit &&
+ if (atomic_dec_return(&fs_info->nr_async_bios) < limit &&
waitqueue_active(&fs_info->async_submit_wait))
wake_up(&fs_info->async_submit_wait);
@@ -569,9 +568,11 @@
memcpy(new_device, device, sizeof(*new_device));
/* Safe because we are under uuid_mutex */
- name = rcu_string_strdup(device->name->str, GFP_NOFS);
- BUG_ON(device->name && !name); /* -ENOMEM */
- rcu_assign_pointer(new_device->name, name);
+ if (device->name) {
+ name = rcu_string_strdup(device->name->str, GFP_NOFS);
+ BUG_ON(device->name && !name); /* -ENOMEM */
+ rcu_assign_pointer(new_device->name, name);
+ }
new_device->bdev = NULL;
new_device->writeable = 0;
new_device->in_fs_metadata = 0;
@@ -4605,28 +4606,6 @@
return ret;
}
-struct btrfs_device *btrfs_find_device_for_logical(struct btrfs_root *root,
- u64 logical, int mirror_num)
-{
- struct btrfs_mapping_tree *map_tree = &root->fs_info->mapping_tree;
- int ret;
- u64 map_length = 0;
- struct btrfs_bio *bbio = NULL;
- struct btrfs_device *device;
-
- BUG_ON(mirror_num == 0);
- ret = btrfs_map_block(map_tree, WRITE, logical, &map_length, &bbio,
- mirror_num);
- if (ret) {
- BUG_ON(bbio != NULL);
- return NULL;
- }
- BUG_ON(mirror_num != bbio->mirror_num);
- device = bbio->stripes[mirror_num - 1].dev;
- kfree(bbio);
- return device;
-}
-
int btrfs_read_chunk_tree(struct btrfs_root *root)
{
struct btrfs_path *path;
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 5479325..53c06af 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -289,8 +289,6 @@
int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset);
int find_free_dev_extent(struct btrfs_device *device, u64 num_bytes,
u64 *start, u64 *max_avail);
-struct btrfs_device *btrfs_find_device_for_logical(struct btrfs_root *root,
- u64 logical, int mirror_num);
void btrfs_dev_stat_print_on_error(struct btrfs_device *device);
void btrfs_dev_stat_inc_and_print(struct btrfs_device *dev, int index);
int btrfs_get_dev_stats(struct btrfs_root *root,
diff --git a/fs/buffer.c b/fs/buffer.c
index 9f6d2e4..58e2e7b 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -914,7 +914,7 @@
/*
* Initialise the state of a blockdev page's buffers.
*/
-static void
+static sector_t
init_page_buffers(struct page *page, struct block_device *bdev,
sector_t block, int size)
{
@@ -936,33 +936,41 @@
block++;
bh = bh->b_this_page;
} while (bh != head);
+
+ /*
+ * Caller needs to validate requested block against end of device.
+ */
+ return end_block;
}
/*
* Create the page-cache page that contains the requested block.
*
- * This is user purely for blockdev mappings.
+ * This is used purely for blockdev mappings.
*/
-static struct page *
+static int
grow_dev_page(struct block_device *bdev, sector_t block,
- pgoff_t index, int size)
+ pgoff_t index, int size, int sizebits)
{
struct inode *inode = bdev->bd_inode;
struct page *page;
struct buffer_head *bh;
+ sector_t end_block;
+ int ret = 0; /* Will call free_more_memory() */
page = find_or_create_page(inode->i_mapping, index,
(mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS)|__GFP_MOVABLE);
if (!page)
- return NULL;
+ return ret;
BUG_ON(!PageLocked(page));
if (page_has_buffers(page)) {
bh = page_buffers(page);
if (bh->b_size == size) {
- init_page_buffers(page, bdev, block, size);
- return page;
+ end_block = init_page_buffers(page, bdev,
+ index << sizebits, size);
+ goto done;
}
if (!try_to_free_buffers(page))
goto failed;
@@ -982,14 +990,14 @@
*/
spin_lock(&inode->i_mapping->private_lock);
link_dev_buffers(page, bh);
- init_page_buffers(page, bdev, block, size);
+ end_block = init_page_buffers(page, bdev, index << sizebits, size);
spin_unlock(&inode->i_mapping->private_lock);
- return page;
-
+done:
+ ret = (block < end_block) ? 1 : -ENXIO;
failed:
unlock_page(page);
page_cache_release(page);
- return NULL;
+ return ret;
}
/*
@@ -999,7 +1007,6 @@
static int
grow_buffers(struct block_device *bdev, sector_t block, int size)
{
- struct page *page;
pgoff_t index;
int sizebits;
@@ -1023,22 +1030,14 @@
bdevname(bdev, b));
return -EIO;
}
- block = index << sizebits;
+
/* Create a page with the proper size buffers.. */
- page = grow_dev_page(bdev, block, index, size);
- if (!page)
- return 0;
- unlock_page(page);
- page_cache_release(page);
- return 1;
+ return grow_dev_page(bdev, block, index, size, sizebits);
}
static struct buffer_head *
__getblk_slow(struct block_device *bdev, sector_t block, int size)
{
- int ret;
- struct buffer_head *bh;
-
/* Size must be multiple of hard sectorsize */
if (unlikely(size & (bdev_logical_block_size(bdev)-1) ||
(size < 512 || size > PAGE_SIZE))) {
@@ -1051,21 +1050,20 @@
return NULL;
}
-retry:
- bh = __find_get_block(bdev, block, size);
- if (bh)
- return bh;
+ for (;;) {
+ struct buffer_head *bh;
+ int ret;
- ret = grow_buffers(bdev, block, size);
- if (ret == 0) {
- free_more_memory();
- goto retry;
- } else if (ret > 0) {
bh = __find_get_block(bdev, block, size);
if (bh)
return bh;
+
+ ret = grow_buffers(bdev, block, size);
+ if (ret < 0)
+ return NULL;
+ if (ret == 0)
+ free_more_memory();
}
- return NULL;
}
/*
@@ -1321,10 +1319,6 @@
* which corresponds to the passed block_device, block and size. The
* returned buffer has its reference count incremented.
*
- * __getblk() cannot fail - it just keeps trying. If you pass it an
- * illegal block number, __getblk() will happily return a buffer_head
- * which represents the non-existent block. Very weird.
- *
* __getblk() will lock up the machine if grow_dev_page's try_to_free_buffers()
* attempt is failing. FIXME, perhaps?
*/
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 074923c..f0cf934 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1576,9 +1576,14 @@
/* result already set, check signature */
if (server->sec_mode &
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
- if (cifs_verify_signature(rdata->iov, rdata->nr_iov,
- server, mid->sequence_number + 1))
- cERROR(1, "Unexpected SMB signature");
+ int rc = 0;
+
+ rc = cifs_verify_signature(rdata->iov, rdata->nr_iov,
+ server,
+ mid->sequence_number + 1);
+ if (rc)
+ cERROR(1, "SMB signature verification returned "
+ "error = %d", rc);
}
/* FIXME: should this be counted toward the initiating task? */
task_io_account_read(rdata->bytes);
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index cbe709a..781025b 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -356,19 +356,12 @@
cifs_create_set_dentry:
if (rc != 0) {
cFYI(1, "Create worked, get_inode_info failed rc = %d", rc);
+ CIFSSMBClose(xid, tcon, *fileHandle);
goto out;
}
d_drop(direntry);
d_add(direntry, newinode);
- /* ENOENT for create? How weird... */
- rc = -ENOENT;
- if (!newinode) {
- CIFSSMBClose(xid, tcon, *fileHandle);
- goto out;
- }
- rc = 0;
-
out:
kfree(buf);
kfree(full_path);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 7354877..cb79c7e 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -124,10 +124,10 @@
{
struct cifsInodeInfo *cifs_i = CIFS_I(inode);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- unsigned long oldtime = cifs_i->time;
cifs_revalidate_cache(inode, fattr);
+ spin_lock(&inode->i_lock);
inode->i_atime = fattr->cf_atime;
inode->i_mtime = fattr->cf_mtime;
inode->i_ctime = fattr->cf_ctime;
@@ -148,9 +148,6 @@
else
cifs_i->time = jiffies;
- cFYI(1, "inode 0x%p old_time=%ld new_time=%ld", inode,
- oldtime, cifs_i->time);
-
cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING;
cifs_i->server_eof = fattr->cf_eof;
@@ -158,7 +155,6 @@
* Can't safely change the file size here if the client is writing to
* it due to potential races.
*/
- spin_lock(&inode->i_lock);
if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) {
i_size_write(inode, fattr->cf_eof);
@@ -859,12 +855,14 @@
if (rc && tcon->ipc) {
cFYI(1, "ipc connection - fake read inode");
+ spin_lock(&inode->i_lock);
inode->i_mode |= S_IFDIR;
set_nlink(inode, 2);
inode->i_op = &cifs_ipc_inode_ops;
inode->i_fop = &simple_dir_operations;
inode->i_uid = cifs_sb->mnt_uid;
inode->i_gid = cifs_sb->mnt_gid;
+ spin_unlock(&inode->i_lock);
} else if (rc) {
iget_failed(inode);
inode = ERR_PTR(rc);
@@ -1110,6 +1108,15 @@
goto out_close;
}
+/* copied from fs/nfs/dir.c with small changes */
+static void
+cifs_drop_nlink(struct inode *inode)
+{
+ spin_lock(&inode->i_lock);
+ if (inode->i_nlink > 0)
+ drop_nlink(inode);
+ spin_unlock(&inode->i_lock);
+}
/*
* If dentry->d_inode is null (usually meaning the cached dentry
@@ -1166,13 +1173,13 @@
psx_del_no_retry:
if (!rc) {
if (inode)
- drop_nlink(inode);
+ cifs_drop_nlink(inode);
} else if (rc == -ENOENT) {
d_drop(dentry);
} else if (rc == -ETXTBSY) {
rc = cifs_rename_pending_delete(full_path, dentry, xid);
if (rc == 0)
- drop_nlink(inode);
+ cifs_drop_nlink(inode);
} else if ((rc == -EACCES) && (dosattr == 0) && inode) {
attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
if (attrs == NULL) {
@@ -1241,9 +1248,10 @@
* setting nlink not necessary except in cases where we failed to get it
* from the server or was set bogus
*/
+ spin_lock(&dentry->d_inode->i_lock);
if ((dentry->d_inode) && (dentry->d_inode->i_nlink < 2))
set_nlink(dentry->d_inode, 2);
-
+ spin_unlock(&dentry->d_inode->i_lock);
mode &= ~current_umask();
/* must turn on setgid bit if parent dir has it */
if (inode->i_mode & S_ISGID)
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 09e4b3a..e6ce3b1 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -433,7 +433,9 @@
if (old_file->d_inode) {
cifsInode = CIFS_I(old_file->d_inode);
if (rc == 0) {
+ spin_lock(&old_file->d_inode->i_lock);
inc_nlink(old_file->d_inode);
+ spin_unlock(&old_file->d_inode->i_lock);
/* BB should we make this contingent on superblock flag NOATIME? */
/* old_file->d_inode->i_ctime = CURRENT_TIME;*/
/* parent dir timestamps will update from srv
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
index a4ff5d5..e4d3b99 100644
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
@@ -52,7 +52,8 @@
cERROR(1, "Bad protocol string signature header %x",
*(unsigned int *) hdr->ProtocolId);
if (mid != hdr->MessageId)
- cERROR(1, "Mids do not match");
+ cERROR(1, "Mids do not match: %llu and %llu", mid,
+ hdr->MessageId);
}
cERROR(1, "Bad SMB detected. The Mid=%llu", hdr->MessageId);
return 1;
@@ -107,7 +108,7 @@
* ie Validate the wct via smb2_struct_sizes table above
*/
- if (length < 2 + sizeof(struct smb2_hdr)) {
+ if (length < sizeof(struct smb2_pdu)) {
if ((length >= sizeof(struct smb2_hdr)) && (hdr->Status != 0)) {
pdu->StructureSize2 = 0;
/*
@@ -121,15 +122,15 @@
return 1;
}
if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE - 4) {
- cERROR(1, "SMB length greater than maximum, mid=%lld", mid);
+ cERROR(1, "SMB length greater than maximum, mid=%llu", mid);
return 1;
}
if (check_smb2_hdr(hdr, mid))
return 1;
- if (hdr->StructureSize != SMB2_HEADER_SIZE) {
- cERROR(1, "Illegal structure size %d",
+ if (hdr->StructureSize != SMB2_HEADER_STRUCTURE_SIZE) {
+ cERROR(1, "Illegal structure size %u",
le16_to_cpu(hdr->StructureSize));
return 1;
}
@@ -161,8 +162,9 @@
if (4 + len != clc_len) {
cFYI(1, "Calculated size %u length %u mismatch mid %llu",
clc_len, 4 + len, mid);
- if (clc_len == 4 + len + 1) /* BB FIXME (fix samba) */
- return 0; /* BB workaround Samba 3 bug SessSetup rsp */
+ /* server can return one byte more */
+ if (clc_len == 4 + len + 1)
+ return 0;
return 1;
}
return 0;
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index f37a1b4..c5fbfac 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -87,10 +87,6 @@
#define SMB2_PROTO_NUMBER __constant_cpu_to_le32(0x424d53fe)
-#define SMB2_HEADER_SIZE __constant_le16_to_cpu(64)
-
-#define SMB2_ERROR_STRUCTURE_SIZE2 __constant_le16_to_cpu(9)
-
/*
* SMB2 Header Definition
*
@@ -99,6 +95,9 @@
* "PDU" : "Protocol Data Unit" (ie a network "frame")
*
*/
+
+#define SMB2_HEADER_STRUCTURE_SIZE __constant_le16_to_cpu(64)
+
struct smb2_hdr {
__be32 smb2_buf_length; /* big endian on wire */
/* length is only two or three bytes - with
@@ -140,6 +139,9 @@
* command code name for the struct. Note that structures must be packed.
*
*/
+
+#define SMB2_ERROR_STRUCTURE_SIZE2 __constant_le16_to_cpu(9)
+
struct smb2_err_rsp {
struct smb2_hdr hdr;
__le16 StructureSize;
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 83867ef..d9b639b 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -503,13 +503,16 @@
/* convert the length into a more usable form */
if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
struct kvec iov;
+ int rc = 0;
iov.iov_base = mid->resp_buf;
iov.iov_len = len;
/* FIXME: add code to kill session */
- if (cifs_verify_signature(&iov, 1, server,
- mid->sequence_number + 1) != 0)
- cERROR(1, "Unexpected SMB signature");
+ rc = cifs_verify_signature(&iov, 1, server,
+ mid->sequence_number + 1);
+ if (rc)
+ cERROR(1, "SMB signature verification returned error = "
+ "%d", rc);
}
/* BB special case reconnect tid and uid here? */
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 1faf4cb..f86c720 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -1062,6 +1062,7 @@
unsigned long user_addr;
size_t bytes;
struct buffer_head map_bh = { 0, };
+ struct blk_plug plug;
if (rw & WRITE)
rw = WRITE_ODIRECT;
@@ -1177,6 +1178,8 @@
PAGE_SIZE - user_addr / PAGE_SIZE);
}
+ blk_start_plug(&plug);
+
for (seg = 0; seg < nr_segs; seg++) {
user_addr = (unsigned long)iov[seg].iov_base;
sdio.size += bytes = iov[seg].iov_len;
@@ -1235,6 +1238,8 @@
if (sdio.bio)
dio_bio_submit(dio, &sdio);
+ blk_finish_plug(&plug);
+
/*
* It is possible that, we return short IO due to end of file.
* In that case, we need to release all the pages we got hold on.
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index 0935750..a286233 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -1113,6 +1113,11 @@
BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex));
spin_lock(&journal->j_state_lock);
+ /* Is it already empty? */
+ if (sb->s_start == 0) {
+ spin_unlock(&journal->j_state_lock);
+ return;
+ }
jbd_debug(1, "JBD: Marking journal as empty (seq %d)\n",
journal->j_tail_sequence);
diff --git a/fs/logfs/dev_bdev.c b/fs/logfs/dev_bdev.c
index df0de27..e784a21 100644
--- a/fs/logfs/dev_bdev.c
+++ b/fs/logfs/dev_bdev.c
@@ -26,6 +26,7 @@
struct completion complete;
bio_init(&bio);
+ bio.bi_max_vecs = 1;
bio.bi_io_vec = &bio_vec;
bio_vec.bv_page = page;
bio_vec.bv_len = PAGE_SIZE;
@@ -95,12 +96,11 @@
struct address_space *mapping = super->s_mapping_inode->i_mapping;
struct bio *bio;
struct page *page;
- struct request_queue *q = bdev_get_queue(sb->s_bdev);
- unsigned int max_pages = queue_max_hw_sectors(q) >> (PAGE_SHIFT - 9);
+ unsigned int max_pages;
int i;
- if (max_pages > BIO_MAX_PAGES)
- max_pages = BIO_MAX_PAGES;
+ max_pages = min(nr_pages, (size_t) bio_get_nr_vecs(super->s_bdev));
+
bio = bio_alloc(GFP_NOFS, max_pages);
BUG_ON(!bio);
@@ -190,12 +190,11 @@
{
struct logfs_super *super = logfs_super(sb);
struct bio *bio;
- struct request_queue *q = bdev_get_queue(sb->s_bdev);
- unsigned int max_pages = queue_max_hw_sectors(q) >> (PAGE_SHIFT - 9);
+ unsigned int max_pages;
int i;
- if (max_pages > BIO_MAX_PAGES)
- max_pages = BIO_MAX_PAGES;
+ max_pages = min(nr_pages, (size_t) bio_get_nr_vecs(super->s_bdev));
+
bio = bio_alloc(GFP_NOFS, max_pages);
BUG_ON(!bio);
diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c
index a422f42..6984562 100644
--- a/fs/logfs/inode.c
+++ b/fs/logfs/inode.c
@@ -156,10 +156,26 @@
call_rcu(&inode->i_rcu, logfs_i_callback);
}
+static void __logfs_destroy_meta_inode(struct inode *inode)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+ BUG_ON(li->li_block);
+ call_rcu(&inode->i_rcu, logfs_i_callback);
+}
+
static void logfs_destroy_inode(struct inode *inode)
{
struct logfs_inode *li = logfs_inode(inode);
+ if (inode->i_ino < LOGFS_RESERVED_INOS) {
+ /*
+ * The reserved inodes are never destroyed unless we are in
+ * unmont path.
+ */
+ __logfs_destroy_meta_inode(inode);
+ return;
+ }
+
BUG_ON(list_empty(&li->li_freeing_list));
spin_lock(&logfs_inode_lock);
li->li_refcount--;
@@ -373,8 +389,8 @@
{
struct logfs_super *super = logfs_super(sb);
/* kill the meta-inodes */
- iput(super->s_master_inode);
iput(super->s_segfile_inode);
+ iput(super->s_master_inode);
iput(super->s_mapping_inode);
}
diff --git a/fs/logfs/journal.c b/fs/logfs/journal.c
index 1e1c369..2a09b8d 100644
--- a/fs/logfs/journal.c
+++ b/fs/logfs/journal.c
@@ -565,7 +565,7 @@
index = ofs >> PAGE_SHIFT;
page_ofs = ofs & (PAGE_SIZE - 1);
- page = find_lock_page(mapping, index);
+ page = find_or_create_page(mapping, index, GFP_NOFS);
BUG_ON(!page);
memcpy(wbuf, page_address(page) + page_ofs, super->s_writesize);
unlock_page(page);
diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c
index f1cb512..5be0abe 100644
--- a/fs/logfs/readwrite.c
+++ b/fs/logfs/readwrite.c
@@ -2189,7 +2189,6 @@
return;
}
- BUG_ON(inode->i_ino < LOGFS_RESERVED_INOS);
page = inode_to_page(inode);
BUG_ON(!page); /* FIXME: Use emergency page */
logfs_put_write_page(page);
diff --git a/fs/logfs/segment.c b/fs/logfs/segment.c
index e28d090..038da09 100644
--- a/fs/logfs/segment.c
+++ b/fs/logfs/segment.c
@@ -886,7 +886,7 @@
static void map_invalidatepage(struct page *page, unsigned long l)
{
- BUG();
+ return;
}
static int map_releasepage(struct page *page, gfp_t g)
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index cbaf4f8..4c7bd35 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -651,12 +651,12 @@
if (clp->cl_minorversion == 0) {
if (!clp->cl_cred.cr_principal &&
- (clp->cl_flavor >= RPC_AUTH_GSS_KRB5))
+ (clp->cl_cred.cr_flavor >= RPC_AUTH_GSS_KRB5))
return -EINVAL;
args.client_name = clp->cl_cred.cr_principal;
args.prognumber = conn->cb_prog,
args.protocol = XPRT_TRANSPORT_TCP;
- args.authflavor = clp->cl_flavor;
+ args.authflavor = clp->cl_cred.cr_flavor;
clp->cl_cb_ident = conn->cb_ident;
} else {
if (!conn->cb_xprt)
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index e617314..22bd0a6 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -231,7 +231,6 @@
nfs4_verifier cl_verifier; /* generated by client */
time_t cl_time; /* time of last lease renewal */
struct sockaddr_storage cl_addr; /* client ipaddress */
- u32 cl_flavor; /* setclientid pseudoflavor */
struct svc_cred cl_cred; /* setclientid principal */
clientid_t cl_clientid; /* generated by server */
nfs4_verifier cl_confirm; /* generated by server */
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index 36a29b7..c495a30 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -1589,10 +1589,10 @@
goto out;
}
- down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
warn[cnt].w_type = QUOTA_NL_NOWARN;
+ down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
spin_lock(&dq_data_lock);
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
if (!dquots[cnt])
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
index 4c0c7d1..a98b774 100644
--- a/fs/reiserfs/bitmap.c
+++ b/fs/reiserfs/bitmap.c
@@ -1334,9 +1334,7 @@
else if (bitmap == 0)
block = (REISERFS_DISK_OFFSET_IN_BYTES >> sb->s_blocksize_bits) + 1;
- reiserfs_write_unlock(sb);
bh = sb_bread(sb, block);
- reiserfs_write_lock(sb);
if (bh == NULL)
reiserfs_warning(sb, "sh-2029: %s: bitmap block (#%u) "
"reading failed", __func__, block);
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index a6d4268..855da58 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -76,10 +76,10 @@
;
}
out:
+ reiserfs_write_unlock_once(inode->i_sb, depth);
clear_inode(inode); /* note this must go after the journal_end to prevent deadlock */
dquot_drop(inode);
inode->i_blocks = 0;
- reiserfs_write_unlock_once(inode->i_sb, depth);
return;
no_delete:
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h
index 8b8cc4e..760de72 100644
--- a/fs/ubifs/debug.h
+++ b/fs/ubifs/debug.h
@@ -167,7 +167,7 @@
#define ubifs_dbg_msg(type, fmt, ...) \
pr_debug("UBIFS DBG " type ": " fmt "\n", ##__VA_ARGS__)
-#define DBG_KEY_BUF_LEN 32
+#define DBG_KEY_BUF_LEN 48
#define ubifs_dbg_msg_key(type, key, fmt, ...) do { \
char __tmp_key_buf[DBG_KEY_BUF_LEN]; \
pr_debug("UBIFS DBG " type ": " fmt "%s\n", ##__VA_ARGS__, \
diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c
index ce33b2b..8640920 100644
--- a/fs/ubifs/lpt.c
+++ b/fs/ubifs/lpt.c
@@ -1749,7 +1749,10 @@
return 0;
out_err:
- ubifs_lpt_free(c, 0);
+ if (wr)
+ ubifs_lpt_free(c, 1);
+ if (rd)
+ ubifs_lpt_free(c, 0);
return err;
}
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c
index c30d976b..edeec49 100644
--- a/fs/ubifs/recovery.c
+++ b/fs/ubifs/recovery.c
@@ -788,7 +788,7 @@
corrupted_rescan:
/* Re-scan the corrupted data with verbose messages */
- ubifs_err("corruptio %d", ret);
+ ubifs_err("corruption %d", ret);
ubifs_scan_a_node(c, buf, len, lnum, offs, 1);
corrupted:
ubifs_scanned_corruption(c, lnum, offs, buf);
diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c
index eba46d4..94d78fc 100644
--- a/fs/ubifs/replay.c
+++ b/fs/ubifs/replay.c
@@ -1026,7 +1026,6 @@
c->replaying = 1;
lnum = c->ltail_lnum = c->lhead_lnum;
- lnum = UBIFS_LOG_LNUM;
do {
err = replay_log_leb(c, lnum, 0, c->sbuf);
if (err == 1)
@@ -1035,7 +1034,7 @@
if (err)
goto out;
lnum = ubifs_next_log_lnum(c, lnum);
- } while (lnum != UBIFS_LOG_LNUM);
+ } while (lnum != c->ltail_lnum);
err = replay_buds(c);
if (err)
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index c3fa6c5..71a197f 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -1157,9 +1157,6 @@
*
* This function mounts UBIFS file system. Returns zero in case of success and
* a negative error code in case of failure.
- *
- * Note, the function does not de-allocate resources it it fails half way
- * through, and the caller has to do this instead.
*/
static int mount_ubifs(struct ubifs_info *c)
{
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index fafaad7..aa23346 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -1124,14 +1124,17 @@
if (err)
return err;
down_write(&iinfo->i_data_sem);
- } else
+ } else {
iinfo->i_lenAlloc = newsize;
+ goto set_size;
+ }
}
err = udf_extend_file(inode, newsize);
if (err) {
up_write(&iinfo->i_data_sem);
return err;
}
+set_size:
truncate_setsize(inode, newsize);
up_write(&iinfo->i_data_sem);
} else {
diff --git a/fs/udf/super.c b/fs/udf/super.c
index dcbf987..18fc038 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -1344,6 +1344,7 @@
udf_err(sb, "error loading logical volume descriptor: "
"Partition table too long (%u > %lu)\n", table_len,
sb->s_blocksize - sizeof(*lvd));
+ ret = 1;
goto out_bh;
}
@@ -1388,8 +1389,10 @@
UDF_ID_SPARABLE,
strlen(UDF_ID_SPARABLE))) {
if (udf_load_sparable_map(sb, map,
- (struct sparablePartitionMap *)gpm) < 0)
+ (struct sparablePartitionMap *)gpm) < 0) {
+ ret = 1;
goto out_bh;
+ }
} else if (!strncmp(upm2->partIdent.ident,
UDF_ID_METADATA,
strlen(UDF_ID_METADATA))) {
@@ -2000,6 +2003,8 @@
if (!silent)
pr_notice("Rescanning with blocksize %d\n",
UDF_DEFAULT_BLOCKSIZE);
+ brelse(sbi->s_lvid_bh);
+ sbi->s_lvid_bh = NULL;
uopt.blocksize = UDF_DEFAULT_BLOCKSIZE;
ret = udf_load_vrs(sb, &uopt, silent, &fileset);
}
diff --git a/fs/xfs/xfs_discard.c b/fs/xfs/xfs_discard.c
index f9c3fe3..69cf4fc 100644
--- a/fs/xfs/xfs_discard.c
+++ b/fs/xfs/xfs_discard.c
@@ -179,12 +179,14 @@
* used by the fstrim application. In the end it really doesn't
* matter as trimming blocks is an advisory interface.
*/
+ if (range.start >= XFS_FSB_TO_B(mp, mp->m_sb.sb_dblocks) ||
+ range.minlen > XFS_FSB_TO_B(mp, XFS_ALLOC_AG_MAX_USABLE(mp)))
+ return -XFS_ERROR(EINVAL);
+
start = BTOBB(range.start);
end = start + BTOBBT(range.len) - 1;
minlen = BTOBB(max_t(u64, granularity, range.minlen));
- if (XFS_BB_TO_FSB(mp, start) >= mp->m_sb.sb_dblocks)
- return -XFS_ERROR(EINVAL);
if (end > XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks) - 1)
end = XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)- 1;
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index 21e37b5..5aceb3f 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -962,23 +962,22 @@
if (!pag->pagi_freecount && !okalloc)
goto nextag;
+ /*
+ * Then read in the AGI buffer and recheck with the AGI buffer
+ * lock held.
+ */
error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
if (error)
goto out_error;
- /*
- * Once the AGI has been read in we have to recheck
- * pagi_freecount with the AGI buffer lock held.
- */
if (pag->pagi_freecount) {
xfs_perag_put(pag);
goto out_alloc;
}
- if (!okalloc) {
- xfs_trans_brelse(tp, agbp);
- goto nextag;
- }
+ if (!okalloc)
+ goto nextag_relse_buffer;
+
error = xfs_ialloc_ag_alloc(tp, agbp, &ialloced);
if (error) {
@@ -1007,6 +1006,8 @@
return 0;
}
+nextag_relse_buffer:
+ xfs_trans_brelse(tp, agbp);
nextag:
xfs_perag_put(pag);
if (++agno == mp->m_sb.sb_agcount)
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 92d4331..ca28a4b 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -857,7 +857,7 @@
xfs_buf_t *bp; /* block buffer, result */
xfs_inode_t *ip; /* bitmap or summary inode */
xfs_bmbt_irec_t map;
- int nmap;
+ int nmap = 1;
int error; /* error value */
ip = issum ? mp->m_rsumip : mp->m_rbmip;
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index ced3625..bfacf0d 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -118,7 +118,8 @@
.hdisplay = (hd), .hsync_start = (hss), .hsync_end = (hse), \
.htotal = (ht), .hskew = (hsk), .vdisplay = (vd), \
.vsync_start = (vss), .vsync_end = (vse), .vtotal = (vt), \
- .vscan = (vs), .flags = (f), .vrefresh = 0
+ .vscan = (vs), .flags = (f), .vrefresh = 0, \
+ .base.type = DRM_MODE_OBJECT_MODE
#define CRTC_INTERLACE_HALVE_V 0x1 /* halve V values for interlacing */
diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h
index 5581980..3d6301b 100644
--- a/include/drm/drm_mode.h
+++ b/include/drm/drm_mode.h
@@ -359,8 +359,9 @@
struct drm_mode_modeinfo mode;
};
-#define DRM_MODE_CURSOR_BO (1<<0)
-#define DRM_MODE_CURSOR_MOVE (1<<1)
+#define DRM_MODE_CURSOR_BO 0x01
+#define DRM_MODE_CURSOR_MOVE 0x02
+#define DRM_MODE_CURSOR_FLAGS 0x03
/*
* depending on the value in flags different members are used.
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index fa21760..c57e064 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -84,7 +84,6 @@
header-y += capi.h
header-y += cciss_defs.h
header-y += cciss_ioctl.h
-header-y += cdk.h
header-y += cdrom.h
header-y += cgroupstats.h
header-y += chio.h
@@ -93,7 +92,6 @@
header-y += coda.h
header-y += coda_psdev.h
header-y += coff.h
-header-y += comstats.h
header-y += connector.h
header-y += const.h
header-y += cramfs_fs.h
@@ -140,7 +138,6 @@
header-y += futex.h
header-y += gameport.h
header-y += gen_stats.h
-header-y += generic_serial.h
header-y += genetlink.h
header-y += gfs2_ondisk.h
header-y += gigaset_dev.h
@@ -372,6 +369,7 @@
header-y += tipc_config.h
header-y += toshiba.h
header-y += tty.h
+header-y += tty_flags.h
header-y += types.h
header-y += udf_fs_i.h
header-y += udp.h
diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h
index d117b29..f612c78 100644
--- a/include/linux/amba/serial.h
+++ b/include/linux/amba/serial.h
@@ -205,7 +205,6 @@
void *dma_tx_param;
void (*init) (void);
void (*exit) (void);
- void (*reset) (void);
};
#endif
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 4e72a9d..4a2ab7c 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -601,7 +601,7 @@
* it already be started by driver.
*/
#define RQ_NOMERGE_FLAGS \
- (REQ_NOMERGE | REQ_STARTED | REQ_SOFTBARRIER | REQ_FLUSH | REQ_FUA)
+ (REQ_NOMERGE | REQ_STARTED | REQ_SOFTBARRIER | REQ_FLUSH | REQ_FUA | REQ_DISCARD)
#define rq_mergeable(rq) \
(!((rq)->cmd_flags & RQ_NOMERGE_FLAGS) && \
(((rq)->cmd_flags & REQ_DISCARD) || \
@@ -894,6 +894,8 @@
extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev);
extern int blk_rq_map_sg(struct request_queue *, struct request *, struct scatterlist *);
+extern int blk_bio_map_sg(struct request_queue *q, struct bio *bio,
+ struct scatterlist *sglist);
extern void blk_dump_rq_flags(struct request *, char *);
extern long nr_blockdev_pages(void);
@@ -1139,6 +1141,16 @@
& (lim->discard_granularity - 1);
}
+static inline int bdev_discard_alignment(struct block_device *bdev)
+{
+ struct request_queue *q = bdev_get_queue(bdev);
+
+ if (bdev != bdev->bd_contains)
+ return bdev->bd_part->discard_alignment;
+
+ return q->limits.discard_alignment;
+}
+
static inline unsigned int queue_discard_zeroes_data(struct request_queue *q)
{
if (q->limits.max_discard_sectors && q->limits.discard_zeroes_data == 1)
diff --git a/include/linux/cd1400.h b/include/linux/cd1400.h
deleted file mode 100644
index 1dc3ab0..0000000
--- a/include/linux/cd1400.h
+++ /dev/null
@@ -1,292 +0,0 @@
-/*****************************************************************************/
-
-/*
- * cd1400.h -- cd1400 UART hardware info.
- *
- * Copyright (C) 1996-1998 Stallion Technologies
- * Copyright (C) 1994-1996 Greg Ungerer.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*****************************************************************************/
-#ifndef _CD1400_H
-#define _CD1400_H
-/*****************************************************************************/
-
-/*
- * Define the number of async ports per cd1400 uart chip.
- */
-#define CD1400_PORTS 4
-
-/*
- * Define the cd1400 uarts internal FIFO sizes.
- */
-#define CD1400_TXFIFOSIZE 12
-#define CD1400_RXFIFOSIZE 12
-
-/*
- * Local RX FIFO thresh hold level. Also define the RTS thresh hold
- * based on the RX thresh hold.
- */
-#define FIFO_RXTHRESHOLD 6
-#define FIFO_RTSTHRESHOLD 7
-
-/*****************************************************************************/
-
-/*
- * Define the cd1400 register addresses. These are all the valid
- * registers with the cd1400. Some are global, some virtual, some
- * per port.
- */
-#define GFRCR 0x40
-#define CAR 0x68
-#define GCR 0x4b
-#define SVRR 0x67
-#define RICR 0x44
-#define TICR 0x45
-#define MICR 0x46
-#define RIR 0x6b
-#define TIR 0x6a
-#define MIR 0x69
-#define PPR 0x7e
-
-#define RIVR 0x43
-#define TIVR 0x42
-#define MIVR 0x41
-#define TDR 0x63
-#define RDSR 0x62
-#define MISR 0x4c
-#define EOSRR 0x60
-
-#define LIVR 0x18
-#define CCR 0x05
-#define SRER 0x06
-#define COR1 0x08
-#define COR2 0x09
-#define COR3 0x0a
-#define COR4 0x1e
-#define COR5 0x1f
-#define CCSR 0x0b
-#define RDCR 0x0e
-#define SCHR1 0x1a
-#define SCHR2 0x1b
-#define SCHR3 0x1c
-#define SCHR4 0x1d
-#define SCRL 0x22
-#define SCRH 0x23
-#define LNC 0x24
-#define MCOR1 0x15
-#define MCOR2 0x16
-#define RTPR 0x21
-#define MSVR1 0x6c
-#define MSVR2 0x6d
-#define PSVR 0x6f
-#define RBPR 0x78
-#define RCOR 0x7c
-#define TBPR 0x72
-#define TCOR 0x76
-
-/*****************************************************************************/
-
-/*
- * Define the set of baud rate clock divisors.
- */
-#define CD1400_CLK0 8
-#define CD1400_CLK1 32
-#define CD1400_CLK2 128
-#define CD1400_CLK3 512
-#define CD1400_CLK4 2048
-
-#define CD1400_NUMCLKS 5
-
-/*****************************************************************************/
-
-/*
- * Define the clock pre-scalar value to be a 5 ms clock. This should be
- * OK for now. It would probably be better to make it 10 ms, but we
- * can't fit that divisor into 8 bits!
- */
-#define PPR_SCALAR 244
-
-/*****************************************************************************/
-
-/*
- * Define values used to set character size options.
- */
-#define COR1_CHL5 0x00
-#define COR1_CHL6 0x01
-#define COR1_CHL7 0x02
-#define COR1_CHL8 0x03
-
-/*
- * Define values used to set the number of stop bits.
- */
-#define COR1_STOP1 0x00
-#define COR1_STOP15 0x04
-#define COR1_STOP2 0x08
-
-/*
- * Define values used to set the parity scheme in use.
- */
-#define COR1_PARNONE 0x00
-#define COR1_PARFORCE 0x20
-#define COR1_PARENB 0x40
-#define COR1_PARIGNORE 0x10
-
-#define COR1_PARODD 0x80
-#define COR1_PAREVEN 0x00
-
-#define COR2_IXM 0x80
-#define COR2_TXIBE 0x40
-#define COR2_ETC 0x20
-#define COR2_LLM 0x10
-#define COR2_RLM 0x08
-#define COR2_RTSAO 0x04
-#define COR2_CTSAE 0x02
-
-#define COR3_SCDRNG 0x80
-#define COR3_SCD34 0x40
-#define COR3_FCT 0x20
-#define COR3_SCD12 0x10
-
-/*
- * Define values used by COR4.
- */
-#define COR4_BRKINT 0x08
-#define COR4_IGNBRK 0x18
-
-/*****************************************************************************/
-
-/*
- * Define the modem control register values.
- * Note that the actual hardware is a little different to the conventional
- * pin names on the cd1400.
- */
-#define MSVR1_DTR 0x01
-#define MSVR1_DSR 0x10
-#define MSVR1_RI 0x20
-#define MSVR1_CTS 0x40
-#define MSVR1_DCD 0x80
-
-#define MSVR2_RTS 0x02
-#define MSVR2_DSR 0x10
-#define MSVR2_RI 0x20
-#define MSVR2_CTS 0x40
-#define MSVR2_DCD 0x80
-
-#define MCOR1_DCD 0x80
-#define MCOR1_CTS 0x40
-#define MCOR1_RI 0x20
-#define MCOR1_DSR 0x10
-
-#define MCOR2_DCD 0x80
-#define MCOR2_CTS 0x40
-#define MCOR2_RI 0x20
-#define MCOR2_DSR 0x10
-
-/*****************************************************************************/
-
-/*
- * Define the bits used with the service (interrupt) enable register.
- */
-#define SRER_NNDT 0x01
-#define SRER_TXEMPTY 0x02
-#define SRER_TXDATA 0x04
-#define SRER_RXDATA 0x10
-#define SRER_MODEM 0x80
-
-/*****************************************************************************/
-
-/*
- * Define operational commands for the command register.
- */
-#define CCR_RESET 0x80
-#define CCR_CORCHANGE 0x4e
-#define CCR_SENDCH 0x20
-#define CCR_CHANCTRL 0x10
-
-#define CCR_TXENABLE (CCR_CHANCTRL | 0x08)
-#define CCR_TXDISABLE (CCR_CHANCTRL | 0x04)
-#define CCR_RXENABLE (CCR_CHANCTRL | 0x02)
-#define CCR_RXDISABLE (CCR_CHANCTRL | 0x01)
-
-#define CCR_SENDSCHR1 (CCR_SENDCH | 0x01)
-#define CCR_SENDSCHR2 (CCR_SENDCH | 0x02)
-#define CCR_SENDSCHR3 (CCR_SENDCH | 0x03)
-#define CCR_SENDSCHR4 (CCR_SENDCH | 0x04)
-
-#define CCR_RESETCHAN (CCR_RESET | 0x00)
-#define CCR_RESETFULL (CCR_RESET | 0x01)
-#define CCR_TXFLUSHFIFO (CCR_RESET | 0x02)
-
-#define CCR_MAXWAIT 10000
-
-/*****************************************************************************/
-
-/*
- * Define the valid acknowledgement types (for hw ack cycle).
- */
-#define ACK_TYPMASK 0x07
-#define ACK_TYPTX 0x02
-#define ACK_TYPMDM 0x01
-#define ACK_TYPRXGOOD 0x03
-#define ACK_TYPRXBAD 0x07
-
-#define SVRR_RX 0x01
-#define SVRR_TX 0x02
-#define SVRR_MDM 0x04
-
-#define ST_OVERRUN 0x01
-#define ST_FRAMING 0x02
-#define ST_PARITY 0x04
-#define ST_BREAK 0x08
-#define ST_SCHAR1 0x10
-#define ST_SCHAR2 0x20
-#define ST_SCHAR3 0x30
-#define ST_SCHAR4 0x40
-#define ST_RANGE 0x70
-#define ST_SCHARMASK 0x70
-#define ST_TIMEOUT 0x80
-
-#define MISR_DCD 0x80
-#define MISR_CTS 0x40
-#define MISR_RI 0x20
-#define MISR_DSR 0x10
-
-/*****************************************************************************/
-
-/*
- * Defines for the CCSR status register.
- */
-#define CCSR_RXENABLED 0x80
-#define CCSR_RXFLOWON 0x40
-#define CCSR_RXFLOWOFF 0x20
-#define CCSR_TXENABLED 0x08
-#define CCSR_TXFLOWON 0x04
-#define CCSR_TXFLOWOFF 0x02
-
-/*****************************************************************************/
-
-/*
- * Define the embedded commands.
- */
-#define ETC_CMD 0x00
-#define ETC_STARTBREAK 0x81
-#define ETC_DELAY 0x82
-#define ETC_STOPBREAK 0x83
-
-/*****************************************************************************/
-#endif
diff --git a/include/linux/cdk.h b/include/linux/cdk.h
deleted file mode 100644
index 80093a8..0000000
--- a/include/linux/cdk.h
+++ /dev/null
@@ -1,486 +0,0 @@
-/*****************************************************************************/
-
-/*
- * cdk.h -- CDK interface definitions.
- *
- * Copyright (C) 1996-1998 Stallion Technologies
- * Copyright (C) 1994-1996 Greg Ungerer.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*****************************************************************************/
-#ifndef _CDK_H
-#define _CDK_H
-/*****************************************************************************/
-
-#pragma pack(2)
-
-/*
- * The following set of definitions is used to communicate with the
- * shared memory interface of the Stallion intelligent multiport serial
- * boards. The definitions in this file are taken directly from the
- * document titled "Generic Stackable Interface, Downloader and
- * Communications Development Kit".
- */
-
-/*
- * Define the set of important shared memory addresses. These are
- * required to initialize the board and get things started. All of these
- * addresses are relative to the start of the shared memory.
- */
-#define CDK_SIGADDR 0x200
-#define CDK_FEATADDR 0x280
-#define CDK_CDKADDR 0x300
-#define CDK_RDYADDR 0x262
-
-#define CDK_ALIVEMARKER 13
-
-/*
- * On hardware power up the ROMs located on the EasyConnection 8/64 will
- * fill out the following signature information into shared memory. This
- * way the host system can quickly determine that the board is present
- * and is operational.
- */
-typedef struct cdkecpsig {
- unsigned long magic;
- unsigned short romver;
- unsigned short cputype;
- unsigned char panelid[8];
-} cdkecpsig_t;
-
-#define ECP_MAGIC 0x21504345
-
-/*
- * On hardware power up the ROMs located on the ONboard, Stallion and
- * Brumbys will fill out the following signature information into shared
- * memory. This way the host system can quickly determine that the board
- * is present and is operational.
- */
-typedef struct cdkonbsig {
- unsigned short magic0;
- unsigned short magic1;
- unsigned short magic2;
- unsigned short magic3;
- unsigned short romver;
- unsigned short memoff;
- unsigned short memseg;
- unsigned short amask0;
- unsigned short pic;
- unsigned short status;
- unsigned short btype;
- unsigned short clkticks;
- unsigned short clkspeed;
- unsigned short amask1;
- unsigned short amask2;
-} cdkonbsig_t;
-
-#define ONB_MAGIC0 0xf2a7
-#define ONB_MAGIC1 0xa149
-#define ONB_MAGIC2 0x6352
-#define ONB_MAGIC3 0xf121
-
-/*
- * Define the feature area structure. The feature area is the set of
- * startup parameters used by the slave image when it starts executing.
- * They allow for the specification of buffer sizes, debug trace, etc.
- */
-typedef struct cdkfeature {
- unsigned long debug;
- unsigned long banner;
- unsigned long etype;
- unsigned long nrdevs;
- unsigned long brdspec;
- unsigned long txrqsize;
- unsigned long rxrqsize;
- unsigned long flags;
-} cdkfeature_t;
-
-#define ETYP_DDK 0
-#define ETYP_CDK 1
-
-/*
- * Define the CDK header structure. This is the info that the slave
- * environment sets up after it has been downloaded and started. It
- * essentially provides a memory map for the shared memory interface.
- */
-typedef struct cdkhdr {
- unsigned short command;
- unsigned short status;
- unsigned short port;
- unsigned short mode;
- unsigned long cmd_buf[14];
- unsigned short alive_cnt;
- unsigned short intrpt_mode;
- unsigned char intrpt_id[8];
- unsigned char ver_release;
- unsigned char ver_modification;
- unsigned char ver_fix;
- unsigned char deadman_restart;
- unsigned short deadman;
- unsigned short nrdevs;
- unsigned long memp;
- unsigned long hostp;
- unsigned long slavep;
- unsigned char hostreq;
- unsigned char slavereq;
- unsigned char cmd_reserved[30];
-} cdkhdr_t;
-
-#define MODE_DDK 0
-#define MODE_CDK 1
-
-#define IMD_INTR 0x0
-#define IMD_PPINTR 0x1
-#define IMD_POLL 0xff
-
-/*
- * Define the memory mapping structure. This structure is pointed to by
- * the memp field in the stlcdkhdr struct. As many as these structures
- * as required are laid out in shared memory to define how the rest of
- * shared memory is divided up. There will be one for each port.
- */
-typedef struct cdkmem {
- unsigned short dtype;
- unsigned long offset;
-} cdkmem_t;
-
-#define TYP_UNDEFINED 0x0
-#define TYP_ASYNCTRL 0x1
-#define TYP_ASYNC 0x20
-#define TYP_PARALLEL 0x40
-#define TYP_SYNCX21 0x60
-
-/*****************************************************************************/
-
-/*
- * Following is a set of defines and structures used to actually deal
- * with the serial ports on the board. Firstly is the set of commands
- * that can be applied to ports.
- */
-#define ASYCMD (((unsigned long) 'a') << 8)
-
-#define A_NULL (ASYCMD | 0)
-#define A_FLUSH (ASYCMD | 1)
-#define A_BREAK (ASYCMD | 2)
-#define A_GETPORT (ASYCMD | 3)
-#define A_SETPORT (ASYCMD | 4)
-#define A_SETPORTF (ASYCMD | 5)
-#define A_SETPORTFTX (ASYCMD | 6)
-#define A_SETPORTFRX (ASYCMD | 7)
-#define A_GETSIGNALS (ASYCMD | 8)
-#define A_SETSIGNALS (ASYCMD | 9)
-#define A_SETSIGNALSF (ASYCMD | 10)
-#define A_SETSIGNALSFTX (ASYCMD | 11)
-#define A_SETSIGNALSFRX (ASYCMD | 12)
-#define A_GETNOTIFY (ASYCMD | 13)
-#define A_SETNOTIFY (ASYCMD | 14)
-#define A_NOTIFY (ASYCMD | 15)
-#define A_PORTCTRL (ASYCMD | 16)
-#define A_GETSTATS (ASYCMD | 17)
-#define A_RQSTATE (ASYCMD | 18)
-#define A_FLOWSTATE (ASYCMD | 19)
-#define A_CLEARSTATS (ASYCMD | 20)
-
-/*
- * Define those arguments used for simple commands.
- */
-#define FLUSHRX 0x1
-#define FLUSHTX 0x2
-
-#define BREAKON -1
-#define BREAKOFF -2
-
-/*
- * Define the port setting structure, and all those defines that go along
- * with it. Basically this structure defines the characteristics of this
- * port: baud rate, chars, parity, input/output char cooking etc.
- */
-typedef struct asyport {
- unsigned long baudout;
- unsigned long baudin;
- unsigned long iflag;
- unsigned long oflag;
- unsigned long lflag;
- unsigned long pflag;
- unsigned long flow;
- unsigned long spare1;
- unsigned short vtime;
- unsigned short vmin;
- unsigned short txlo;
- unsigned short txhi;
- unsigned short rxlo;
- unsigned short rxhi;
- unsigned short rxhog;
- unsigned short spare2;
- unsigned char csize;
- unsigned char stopbs;
- unsigned char parity;
- unsigned char stopin;
- unsigned char startin;
- unsigned char stopout;
- unsigned char startout;
- unsigned char parmark;
- unsigned char brkmark;
- unsigned char cc[11];
-} asyport_t;
-
-#define PT_STOP1 0x0
-#define PT_STOP15 0x1
-#define PT_STOP2 0x2
-
-#define PT_NOPARITY 0x0
-#define PT_ODDPARITY 0x1
-#define PT_EVENPARITY 0x2
-#define PT_MARKPARITY 0x3
-#define PT_SPACEPARITY 0x4
-
-#define F_NONE 0x0
-#define F_IXON 0x1
-#define F_IXOFF 0x2
-#define F_IXANY 0x4
-#define F_IOXANY 0x8
-#define F_RTSFLOW 0x10
-#define F_CTSFLOW 0x20
-#define F_DTRFLOW 0x40
-#define F_DCDFLOW 0x80
-#define F_DSROFLOW 0x100
-#define F_DSRIFLOW 0x200
-
-#define FI_NORX 0x1
-#define FI_RAW 0x2
-#define FI_ISTRIP 0x4
-#define FI_UCLC 0x8
-#define FI_INLCR 0x10
-#define FI_ICRNL 0x20
-#define FI_IGNCR 0x40
-#define FI_IGNBREAK 0x80
-#define FI_DSCRDBREAK 0x100
-#define FI_1MARKBREAK 0x200
-#define FI_2MARKBREAK 0x400
-#define FI_XCHNGBREAK 0x800
-#define FI_IGNRXERRS 0x1000
-#define FI_DSCDRXERRS 0x2000
-#define FI_1MARKRXERRS 0x4000
-#define FI_2MARKRXERRS 0x8000
-#define FI_XCHNGRXERRS 0x10000
-#define FI_DSCRDNULL 0x20000
-
-#define FO_OLCUC 0x1
-#define FO_ONLCR 0x2
-#define FO_OOCRNL 0x4
-#define FO_ONOCR 0x8
-#define FO_ONLRET 0x10
-#define FO_ONL 0x20
-#define FO_OBS 0x40
-#define FO_OVT 0x80
-#define FO_OFF 0x100
-#define FO_OTAB1 0x200
-#define FO_OTAB2 0x400
-#define FO_OTAB3 0x800
-#define FO_OCR1 0x1000
-#define FO_OCR2 0x2000
-#define FO_OCR3 0x4000
-#define FO_OFILL 0x8000
-#define FO_ODELL 0x10000
-
-#define P_RTSLOCK 0x1
-#define P_CTSLOCK 0x2
-#define P_MAPRTS 0x4
-#define P_MAPCTS 0x8
-#define P_LOOPBACK 0x10
-#define P_DTRFOLLOW 0x20
-#define P_FAKEDCD 0x40
-
-#define P_RXIMIN 0x10000
-#define P_RXITIME 0x20000
-#define P_RXTHOLD 0x40000
-
-/*
- * Define a structure to communicate serial port signal and data state
- * information.
- */
-typedef struct asysigs {
- unsigned long data;
- unsigned long signal;
- unsigned long sigvalue;
-} asysigs_t;
-
-#define DT_TXBUSY 0x1
-#define DT_TXEMPTY 0x2
-#define DT_TXLOW 0x4
-#define DT_TXHIGH 0x8
-#define DT_TXFULL 0x10
-#define DT_TXHOG 0x20
-#define DT_TXFLOWED 0x40
-#define DT_TXBREAK 0x80
-
-#define DT_RXBUSY 0x100
-#define DT_RXEMPTY 0x200
-#define DT_RXLOW 0x400
-#define DT_RXHIGH 0x800
-#define DT_RXFULL 0x1000
-#define DT_RXHOG 0x2000
-#define DT_RXFLOWED 0x4000
-#define DT_RXBREAK 0x8000
-
-#define SG_DTR 0x1
-#define SG_DCD 0x2
-#define SG_RTS 0x4
-#define SG_CTS 0x8
-#define SG_DSR 0x10
-#define SG_RI 0x20
-
-/*
- * Define the notification setting structure. This is used to tell the
- * port what events we want to be informed about. Fields here use the
- * same defines as for the asysigs structure above.
- */
-typedef struct asynotify {
- unsigned long ctrl;
- unsigned long data;
- unsigned long signal;
- unsigned long sigvalue;
-} asynotify_t;
-
-/*
- * Define the port control structure. It is used to do fine grain
- * control operations on the port.
- */
-typedef struct {
- unsigned long rxctrl;
- unsigned long txctrl;
- char rximdch;
- char tximdch;
- char spare1;
- char spare2;
-} asyctrl_t;
-
-#define CT_ENABLE 0x1
-#define CT_DISABLE 0x2
-#define CT_STOP 0x4
-#define CT_START 0x8
-#define CT_STARTFLOW 0x10
-#define CT_STOPFLOW 0x20
-#define CT_SENDCHR 0x40
-
-/*
- * Define the stats structure kept for each port. This is a useful set
- * of data collected for each port on the slave. The A_GETSTATS command
- * is used to retrieve this data from the slave.
- */
-typedef struct asystats {
- unsigned long opens;
- unsigned long txchars;
- unsigned long rxchars;
- unsigned long txringq;
- unsigned long rxringq;
- unsigned long txmsgs;
- unsigned long rxmsgs;
- unsigned long txflushes;
- unsigned long rxflushes;
- unsigned long overruns;
- unsigned long framing;
- unsigned long parity;
- unsigned long ringover;
- unsigned long lost;
- unsigned long rxstart;
- unsigned long rxstop;
- unsigned long txstart;
- unsigned long txstop;
- unsigned long dcdcnt;
- unsigned long dtrcnt;
- unsigned long ctscnt;
- unsigned long rtscnt;
- unsigned long dsrcnt;
- unsigned long ricnt;
- unsigned long txbreaks;
- unsigned long rxbreaks;
- unsigned long signals;
- unsigned long state;
- unsigned long hwid;
-} asystats_t;
-
-/*****************************************************************************/
-
-/*
- * All command and control communication with a device on the slave is
- * via a control block in shared memory. Each device has its own control
- * block, defined by the following structure. The control block allows
- * the host to open, close and control the device on the slave.
- */
-typedef struct cdkctrl {
- unsigned char open;
- unsigned char close;
- unsigned long openarg;
- unsigned long closearg;
- unsigned long cmd;
- unsigned long status;
- unsigned long args[32];
-} cdkctrl_t;
-
-/*
- * Each device on the slave passes data to and from the host via a ring
- * queue in shared memory. Define a ring queue structure to hold the
- * vital information about each ring queue. Two ring queues will be
- * allocated for each port, one for receive data and one for transmit
- * data.
- */
-typedef struct cdkasyrq {
- unsigned long offset;
- unsigned short size;
- unsigned short head;
- unsigned short tail;
-} cdkasyrq_t;
-
-/*
- * Each asynchronous port is defined in shared memory by the following
- * structure. It contains a control block to command a device, and also
- * the necessary data channel information as well.
- */
-typedef struct cdkasy {
- cdkctrl_t ctrl;
- unsigned short notify;
- asynotify_t changed;
- unsigned short receive;
- cdkasyrq_t rxq;
- unsigned short transmit;
- cdkasyrq_t txq;
-} cdkasy_t;
-
-#pragma pack()
-
-/*****************************************************************************/
-
-/*
- * Define the set of ioctls used by the driver to do special things
- * to the board. These include interrupting it, and initializing
- * the driver after board startup and shutdown.
- */
-#include <linux/ioctl.h>
-
-#define STL_BINTR _IO('s',20)
-#define STL_BSTART _IO('s',21)
-#define STL_BSTOP _IO('s',22)
-#define STL_BRESET _IO('s',23)
-
-/*
- * Define a set of ioctl extensions, used to get at special stuff.
- */
-#define STL_GETPFLAG _IO('s',80)
-#define STL_SETPFLAG _IO('s',81)
-
-/*****************************************************************************/
-#endif
diff --git a/include/linux/comstats.h b/include/linux/comstats.h
deleted file mode 100644
index 3f5ea8e..0000000
--- a/include/linux/comstats.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*****************************************************************************/
-
-/*
- * comstats.h -- Serial Port Stats.
- *
- * Copyright (C) 1996-1998 Stallion Technologies
- * Copyright (C) 1994-1996 Greg Ungerer.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*****************************************************************************/
-#ifndef _COMSTATS_H
-#define _COMSTATS_H
-/*****************************************************************************/
-
-/*
- * Serial port stats structure. The structure itself is UART
- * independent, but some fields may be UART/driver specific (for
- * example state).
- */
-
-typedef struct {
- unsigned long brd;
- unsigned long panel;
- unsigned long port;
- unsigned long hwid;
- unsigned long type;
- unsigned long txtotal;
- unsigned long rxtotal;
- unsigned long txbuffered;
- unsigned long rxbuffered;
- unsigned long rxoverrun;
- unsigned long rxparity;
- unsigned long rxframing;
- unsigned long rxlost;
- unsigned long txbreaks;
- unsigned long rxbreaks;
- unsigned long txxon;
- unsigned long txxoff;
- unsigned long rxxon;
- unsigned long rxxoff;
- unsigned long txctson;
- unsigned long txctsoff;
- unsigned long rxrtson;
- unsigned long rxrtsoff;
- unsigned long modem;
- unsigned long state;
- unsigned long flags;
- unsigned long ttystate;
- unsigned long cflags;
- unsigned long iflags;
- unsigned long oflags;
- unsigned long lflags;
- unsigned long signals;
-} comstats_t;
-
-
-/*
- * Board stats structure. Returns useful info about the board.
- */
-
-#define COM_MAXPANELS 8
-
-typedef struct {
- unsigned long panel;
- unsigned long type;
- unsigned long hwid;
- unsigned long nrports;
-} companel_t;
-
-typedef struct {
- unsigned long brd;
- unsigned long type;
- unsigned long hwid;
- unsigned long state;
- unsigned long ioaddr;
- unsigned long ioaddr2;
- unsigned long memaddr;
- unsigned long irq;
- unsigned long nrpanels;
- unsigned long nrports;
- companel_t panels[COM_MAXPANELS];
-} combrd_t;
-
-
-/*
- * Define the ioctl operations for stats stuff.
- */
-#include <linux/ioctl.h>
-
-#define COM_GETPORTSTATS _IO('c',30)
-#define COM_CLRPORTSTATS _IO('c',31)
-#define COM_GETBRDSTATS _IO('c',32)
-
-
-/*
- * Define the set of ioctls that give user level access to the
- * private port, panel and board structures. The argument required
- * will be driver dependent!
- */
-#define COM_READPORT _IO('c',40)
-#define COM_READBOARD _IO('c',41)
-#define COM_READPANEL _IO('c',42)
-
-/*****************************************************************************/
-#endif
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
index 040b13b..279b1ea 100644
--- a/include/linux/cpuidle.h
+++ b/include/linux/cpuidle.h
@@ -194,6 +194,10 @@
#ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED
void cpuidle_coupled_parallel_barrier(struct cpuidle_device *dev, atomic_t *a);
+#else
+static inline void cpuidle_coupled_parallel_barrier(struct cpuidle_device *dev, atomic_t *a)
+{
+}
#endif
/******************************
diff --git a/include/linux/generic_serial.h b/include/linux/generic_serial.h
deleted file mode 100644
index 79b3eb3..0000000
--- a/include/linux/generic_serial.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * generic_serial.h
- *
- * Copyright (C) 1998 R.E.Wolff@BitWizard.nl
- *
- * written for the SX serial driver.
- *
- * Version 0.1 -- December, 1998.
- */
-
-#ifndef GENERIC_SERIAL_H
-#define GENERIC_SERIAL_H
-
-#warning Use of this header is deprecated.
-#warning Since nobody sets the constants defined here for you, you should not, in any case, use them. Including the header is thus pointless.
-
-/* Flags */
-/* Warning: serial.h defines some ASYNC_ flags, they say they are "only"
- used in serial.c, but they are also used in all other serial drivers.
- Make sure they don't clash with these here... */
-#define GS_TX_INTEN 0x00800000
-#define GS_RX_INTEN 0x00400000
-#define GS_ACTIVE 0x00200000
-
-#define GS_TYPE_NORMAL 1
-
-#define GS_DEBUG_FLUSH 0x00000001
-#define GS_DEBUG_BTR 0x00000002
-#define GS_DEBUG_TERMIOS 0x00000004
-#define GS_DEBUG_STUFF 0x00000008
-#define GS_DEBUG_CLOSE 0x00000010
-#define GS_DEBUG_FLOW 0x00000020
-#define GS_DEBUG_WRITE 0x00000040
-
-#endif
diff --git a/include/linux/istallion.h b/include/linux/istallion.h
deleted file mode 100644
index ad700a6..0000000
--- a/include/linux/istallion.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*****************************************************************************/
-
-/*
- * istallion.h -- stallion intelligent multiport serial driver.
- *
- * Copyright (C) 1996-1998 Stallion Technologies
- * Copyright (C) 1994-1996 Greg Ungerer.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*****************************************************************************/
-#ifndef _ISTALLION_H
-#define _ISTALLION_H
-/*****************************************************************************/
-
-/*
- * Define important driver constants here.
- */
-#define STL_MAXBRDS 4
-#define STL_MAXPANELS 4
-#define STL_MAXPORTS 64
-#define STL_MAXCHANS (STL_MAXPORTS + 1)
-#define STL_MAXDEVS (STL_MAXBRDS * STL_MAXPORTS)
-
-
-/*
- * Define a set of structures to hold all the board/panel/port info
- * for our ports. These will be dynamically allocated as required at
- * driver initialization time.
- */
-
-/*
- * Port and board structures to hold status info about each object.
- * The board structure contains pointers to structures for each port
- * connected to it. Panels are not distinguished here, since
- * communication with the slave board will always be on a per port
- * basis.
- */
-struct stliport {
- unsigned long magic;
- struct tty_port port;
- unsigned int portnr;
- unsigned int panelnr;
- unsigned int brdnr;
- unsigned long state;
- unsigned int devnr;
- int baud_base;
- int custom_divisor;
- int closing_wait;
- int rc;
- int argsize;
- void *argp;
- unsigned int rxmarkmsk;
- wait_queue_head_t raw_wait;
- struct asysigs asig;
- unsigned long addr;
- unsigned long rxoffset;
- unsigned long txoffset;
- unsigned long sigs;
- unsigned long pflag;
- unsigned int rxsize;
- unsigned int txsize;
- unsigned char reqbit;
- unsigned char portidx;
- unsigned char portbit;
-};
-
-/*
- * Use a structure of function pointers to do board level operations.
- * These include, enable/disable, paging shared memory, interrupting, etc.
- */
-struct stlibrd {
- unsigned long magic;
- unsigned int brdnr;
- unsigned int brdtype;
- unsigned long state;
- unsigned int nrpanels;
- unsigned int nrports;
- unsigned int nrdevs;
- unsigned int iobase;
- int iosize;
- unsigned long memaddr;
- void __iomem *membase;
- unsigned long memsize;
- int pagesize;
- int hostoffset;
- int slaveoffset;
- int bitsize;
- int enabval;
- unsigned int panels[STL_MAXPANELS];
- int panelids[STL_MAXPANELS];
- void (*init)(struct stlibrd *brdp);
- void (*enable)(struct stlibrd *brdp);
- void (*reenable)(struct stlibrd *brdp);
- void (*disable)(struct stlibrd *brdp);
- void __iomem *(*getmemptr)(struct stlibrd *brdp, unsigned long offset, int line);
- void (*intr)(struct stlibrd *brdp);
- void (*reset)(struct stlibrd *brdp);
- struct stliport *ports[STL_MAXPORTS];
-};
-
-
-/*
- * Define MAGIC numbers used for above structures.
- */
-#define STLI_PORTMAGIC 0xe671c7a1
-#define STLI_BOARDMAGIC 0x4bc6c825
-
-/*****************************************************************************/
-#endif
diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h
index daf4a3a..b7c8cdc 100644
--- a/include/linux/kbd_kern.h
+++ b/include/linux/kbd_kern.h
@@ -65,7 +65,6 @@
extern int kbd_init(void);
-extern unsigned char getledstate(void);
extern void setledstate(struct kbd_struct *kbd, unsigned int led);
extern int do_poke_blanked_console;
@@ -145,16 +144,4 @@
extern unsigned int keymap_count;
-/* console.c */
-
-static inline void con_schedule_flip(struct tty_struct *t)
-{
- unsigned long flags;
- spin_lock_irqsave(&t->buf.lock, flags);
- if (t->buf.tail != NULL)
- t->buf.tail->commit = t->buf.tail->used;
- spin_unlock_irqrestore(&t->buf.lock, flags);
- schedule_work(&t->buf.work);
-}
-
#endif
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 6043821..594b419 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -82,10 +82,18 @@
__x - (__x % (y)); \
} \
)
+
+/*
+ * Divide positive or negative dividend by positive divisor and round
+ * to closest integer. Result is undefined for negative divisors.
+ */
#define DIV_ROUND_CLOSEST(x, divisor)( \
{ \
- typeof(divisor) __divisor = divisor; \
- (((x) + ((__divisor) / 2)) / (__divisor)); \
+ typeof(x) __x = x; \
+ typeof(divisor) __d = divisor; \
+ (((typeof(x))-1) >= 0 || (__x) >= 0) ? \
+ (((__x) + ((__d) / 2)) / (__d)) : \
+ (((__x) - ((__d) / 2)) / (__d)); \
} \
)
diff --git a/include/linux/ktime.h b/include/linux/ktime.h
index 603bec2..06177ba10 100644
--- a/include/linux/ktime.h
+++ b/include/linux/ktime.h
@@ -58,13 +58,6 @@
typedef union ktime ktime_t; /* Kill this */
-#define KTIME_MAX ((s64)~((u64)1 << 63))
-#if (BITS_PER_LONG == 64)
-# define KTIME_SEC_MAX (KTIME_MAX / NSEC_PER_SEC)
-#else
-# define KTIME_SEC_MAX LONG_MAX
-#endif
-
/*
* ktime_t definitions when using the 64-bit scalar representation:
*/
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 111aca5..4b27f9f 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -239,6 +239,7 @@
#define MMC_QUIRK_BLK_NO_CMD23 (1<<7) /* Avoid CMD23 for regular multiblock */
#define MMC_QUIRK_BROKEN_BYTE_MODE_512 (1<<8) /* Avoid sending 512 bytes in */
#define MMC_QUIRK_LONG_READ_TIME (1<<9) /* Data read time > CSD says */
+#define MMC_QUIRK_SEC_ERASE_TRIM_BROKEN (1<<10) /* Skip secure for erase/trim */
/* byte mode */
unsigned int poweroff_notify_state; /* eMMC4.5 notify feature */
#define MMC_NO_POWER_NOTIFICATION 0
diff --git a/include/linux/mv643xx_eth.h b/include/linux/mv643xx_eth.h
index 51bf8ad..49258e0 100644
--- a/include/linux/mv643xx_eth.h
+++ b/include/linux/mv643xx_eth.h
@@ -15,6 +15,8 @@
#define MV643XX_ETH_SIZE_REG_4 0x2224
#define MV643XX_ETH_BASE_ADDR_ENABLE_REG 0x2290
+#define MV643XX_TX_CSUM_DEFAULT_LIMIT 0
+
struct mv643xx_eth_shared_platform_data {
struct mbus_dram_target_info *dram;
struct platform_device *shared_smi;
diff --git a/include/linux/omapfb.h b/include/linux/omapfb.h
index 4ff57e8..85af818 100644
--- a/include/linux/omapfb.h
+++ b/include/linux/omapfb.h
@@ -220,7 +220,12 @@
#ifdef __KERNEL__
-#include <plat/board.h>
+struct omap_lcd_config {
+ char panel_name[16];
+ char ctrl_name[16];
+ s16 nreset_gpio;
+ u8 data_lines;
+};
struct omapfb_platform_data {
struct omap_lcd_config lcd;
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index fc35260..6b4565c 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2149,7 +2149,7 @@
#define PCI_DEVICE_ID_TIGON3_5704S 0x16a8
#define PCI_DEVICE_ID_NX2_57800_VF 0x16a9
#define PCI_DEVICE_ID_NX2_5706S 0x16aa
-#define PCI_DEVICE_ID_NX2_57840_MF 0x16ab
+#define PCI_DEVICE_ID_NX2_57840_MF 0x16a4
#define PCI_DEVICE_ID_NX2_5708S 0x16ac
#define PCI_DEVICE_ID_NX2_57840_VF 0x16ad
#define PCI_DEVICE_ID_NX2_57810_MF 0x16ae
diff --git a/include/linux/platform_data/max310x.h b/include/linux/platform_data/max310x.h
new file mode 100644
index 0000000..91648bf
--- /dev/null
+++ b/include/linux/platform_data/max310x.h
@@ -0,0 +1,67 @@
+/*
+ * Maxim (Dallas) MAX3107/8 serial driver
+ *
+ * Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
+ *
+ * Based on max3100.c, by Christian Pellegrin <chripell@evolware.org>
+ * Based on max3110.c, by Feng Tang <feng.tang@intel.com>
+ * Based on max3107.c, by Aavamobile
+ *
+ * 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 _MAX310X_H_
+#define _MAX310X_H_
+
+/*
+ * Example board initialization data:
+ *
+ * static struct max310x_pdata max3107_pdata = {
+ * .driver_flags = MAX310X_EXT_CLK,
+ * .uart_flags[0] = MAX310X_ECHO_SUPRESS | MAX310X_AUTO_DIR_CTRL,
+ * .frequency = 3686400,
+ * .gpio_base = -1,
+ * };
+ *
+ * static struct spi_board_info spi_device_max3107[] = {
+ * {
+ * .modalias = "max3107",
+ * .irq = IRQ_EINT3,
+ * .bus_num = 1,
+ * .chip_select = 1,
+ * .platform_data = &max3107_pdata,
+ * },
+ * };
+ */
+
+#define MAX310X_MAX_UARTS 1
+
+/* MAX310X platform data structure */
+struct max310x_pdata {
+ /* Flags global to driver */
+ const u8 driver_flags:2;
+#define MAX310X_EXT_CLK (0x00000001) /* External clock enable */
+#define MAX310X_AUTOSLEEP (0x00000002) /* Enable AutoSleep mode */
+ /* Flags global to UART port */
+ const u8 uart_flags[MAX310X_MAX_UARTS];
+#define MAX310X_LOOPBACK (0x00000001) /* Loopback mode enable */
+#define MAX310X_ECHO_SUPRESS (0x00000002) /* Enable echo supress */
+#define MAX310X_AUTO_DIR_CTRL (0x00000004) /* Enable Auto direction
+ * control (RS-485)
+ */
+ /* Frequency (extrenal clock or crystal) */
+ const int frequency;
+ /* GPIO base number (can be negative) */
+ const int gpio_base;
+ /* Called during startup */
+ void (*init)(void);
+ /* Called before finish */
+ void (*exit)(void);
+ /* Suspend callback */
+ void (*suspend)(int do_suspend);
+};
+
+#endif
diff --git a/include/linux/platform_data/omap1_bl.h b/include/linux/platform_data/omap1_bl.h
new file mode 100644
index 0000000..881a8e9
--- /dev/null
+++ b/include/linux/platform_data/omap1_bl.h
@@ -0,0 +1,11 @@
+#ifndef __OMAP1_BL_H__
+#define __OMAP1_BL_H__
+
+#include <linux/device.h>
+
+struct omap_backlight_config {
+ int default_intensity;
+ int (*set_power)(struct device *dev, int state);
+};
+
+#endif
diff --git a/include/linux/platform_data/sccnxp.h b/include/linux/platform_data/sccnxp.h
new file mode 100644
index 0000000..7311ccd
--- /dev/null
+++ b/include/linux/platform_data/sccnxp.h
@@ -0,0 +1,93 @@
+/*
+ * NXP (Philips) SCC+++(SCN+++) serial driver
+ *
+ * Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
+ *
+ * Based on sc26xx.c, by Thomas Bogendörfer (tsbogend@alpha.franken.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __SCCNXP_H
+#define __SCCNXP_H
+
+#define SCCNXP_MAX_UARTS 2
+
+/* Output lines */
+#define LINE_OP0 1
+#define LINE_OP1 2
+#define LINE_OP2 3
+#define LINE_OP3 4
+#define LINE_OP4 5
+#define LINE_OP5 6
+#define LINE_OP6 7
+#define LINE_OP7 8
+
+/* Input lines */
+#define LINE_IP0 9
+#define LINE_IP1 10
+#define LINE_IP2 11
+#define LINE_IP3 12
+#define LINE_IP4 13
+#define LINE_IP5 14
+#define LINE_IP6 15
+
+/* Signals */
+#define DTR_OP 0 /* DTR */
+#define RTS_OP 4 /* RTS */
+#define DSR_IP 8 /* DSR */
+#define CTS_IP 12 /* CTS */
+#define DCD_IP 16 /* DCD */
+#define RNG_IP 20 /* RNG */
+
+#define DIR_OP 24 /* Special signal for control RS-485.
+ * Goes high when transmit,
+ * then goes low.
+ */
+
+/* Routing control signal 'sig' to line 'line' */
+#define MCTRL_SIG(sig, line) ((line) << (sig))
+
+/*
+ * Example board initialization data:
+ *
+ * static struct resource sc2892_resources[] = {
+ * DEFINE_RES_MEM(UART_PHYS_START, 0x10),
+ * DEFINE_RES_IRQ(IRQ_EXT2),
+ * };
+ *
+ * static struct sccnxp_pdata sc2892_info = {
+ * .frequency = 3686400,
+ * .mctrl_cfg[0] = MCTRL_SIG(DIR_OP, LINE_OP0),
+ * .mctrl_cfg[1] = MCTRL_SIG(DIR_OP, LINE_OP1),
+ * };
+ *
+ * static struct platform_device sc2892 = {
+ * .name = "sc2892",
+ * .id = -1,
+ * .resource = sc2892_resources,
+ * .num_resources = ARRAY_SIZE(sc2892_resources),
+ * .dev = {
+ * .platform_data = &sc2892_info,
+ * },
+ * };
+ */
+
+/* SCCNXP platform data structure */
+struct sccnxp_pdata {
+ /* Frequency (extrenal clock or crystal) */
+ int frequency;
+ /* Shift for A0 line */
+ const u8 reg_shift;
+ /* Modem control lines configuration */
+ const u32 mctrl_cfg[SCCNXP_MAX_UARTS];
+ /* Called during startup */
+ void (*init)(void);
+ /* Called before finish */
+ void (*exit)(void);
+};
+
+#endif
diff --git a/include/linux/sc26198.h b/include/linux/sc26198.h
deleted file mode 100644
index 7ca35ab..0000000
--- a/include/linux/sc26198.h
+++ /dev/null
@@ -1,533 +0,0 @@
-/*****************************************************************************/
-
-/*
- * sc26198.h -- SC26198 UART hardware info.
- *
- * Copyright (C) 1995-1998 Stallion Technologies
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*****************************************************************************/
-#ifndef _SC26198_H
-#define _SC26198_H
-/*****************************************************************************/
-
-/*
- * Define the number of async ports per sc26198 uart device.
- */
-#define SC26198_PORTS 8
-
-/*
- * Baud rate timing clocks. All derived from a master 14.7456 MHz clock.
- */
-#define SC26198_MASTERCLOCK 14745600L
-#define SC26198_DCLK (SC26198_MASTERCLOCK)
-#define SC26198_CCLK (SC26198_MASTERCLOCK / 2)
-#define SC26198_BCLK (SC26198_MASTERCLOCK / 4)
-
-/*
- * Define internal FIFO sizes for the 26198 ports.
- */
-#define SC26198_TXFIFOSIZE 16
-#define SC26198_RXFIFOSIZE 16
-
-/*****************************************************************************/
-
-/*
- * Global register definitions. These registers are global to each 26198
- * device, not specific ports on it.
- */
-#define TSTR 0x0d
-#define GCCR 0x0f
-#define ICR 0x1b
-#define WDTRCR 0x1d
-#define IVR 0x1f
-#define BRGTRUA 0x84
-#define GPOSR 0x87
-#define GPOC 0x8b
-#define UCIR 0x8c
-#define CIR 0x8c
-#define BRGTRUB 0x8d
-#define GRXFIFO 0x8e
-#define GTXFIFO 0x8e
-#define GCCR2 0x8f
-#define BRGTRLA 0x94
-#define GPOR 0x97
-#define GPOD 0x9b
-#define BRGTCR 0x9c
-#define GICR 0x9c
-#define BRGTRLB 0x9d
-#define GIBCR 0x9d
-#define GITR 0x9f
-
-/*
- * Per port channel registers. These are the register offsets within
- * the port address space, so need to have the port address (0 to 7)
- * inserted in bit positions 4:6.
- */
-#define MR0 0x00
-#define MR1 0x01
-#define IOPCR 0x02
-#define BCRBRK 0x03
-#define BCRCOS 0x04
-#define BCRX 0x06
-#define BCRA 0x07
-#define XONCR 0x08
-#define XOFFCR 0x09
-#define ARCR 0x0a
-#define RXCSR 0x0c
-#define TXCSR 0x0e
-#define MR2 0x80
-#define SR 0x81
-#define SCCR 0x81
-#define ISR 0x82
-#define IMR 0x82
-#define TXFIFO 0x83
-#define RXFIFO 0x83
-#define IPR 0x84
-#define IOPIOR 0x85
-#define XISR 0x86
-
-/*
- * For any given port calculate the address to use to access a specified
- * register. This is only used for unusual access, mostly this is done
- * through the assembler access routines.
- */
-#define SC26198_PORTREG(port,reg) ((((port) & 0x07) << 4) | (reg))
-
-/*****************************************************************************/
-
-/*
- * Global configuration control register bit definitions.
- */
-#define GCCR_NOACK 0x00
-#define GCCR_IVRACK 0x02
-#define GCCR_IVRCHANACK 0x04
-#define GCCR_IVRTYPCHANACK 0x06
-#define GCCR_ASYNCCYCLE 0x00
-#define GCCR_SYNCCYCLE 0x40
-
-/*****************************************************************************/
-
-/*
- * Mode register 0 bit definitions.
- */
-#define MR0_ADDRNONE 0x00
-#define MR0_AUTOWAKE 0x01
-#define MR0_AUTODOZE 0x02
-#define MR0_AUTOWAKEDOZE 0x03
-#define MR0_SWFNONE 0x00
-#define MR0_SWFTX 0x04
-#define MR0_SWFRX 0x08
-#define MR0_SWFRXTX 0x0c
-#define MR0_TXMASK 0x30
-#define MR0_TXEMPTY 0x00
-#define MR0_TXHIGH 0x10
-#define MR0_TXHALF 0x20
-#define MR0_TXRDY 0x00
-#define MR0_ADDRNT 0x00
-#define MR0_ADDRT 0x40
-#define MR0_SWFNT 0x00
-#define MR0_SWFT 0x80
-
-/*
- * Mode register 1 bit definitions.
- */
-#define MR1_CS5 0x00
-#define MR1_CS6 0x01
-#define MR1_CS7 0x02
-#define MR1_CS8 0x03
-#define MR1_PAREVEN 0x00
-#define MR1_PARODD 0x04
-#define MR1_PARENB 0x00
-#define MR1_PARFORCE 0x08
-#define MR1_PARNONE 0x10
-#define MR1_PARSPECIAL 0x18
-#define MR1_ERRCHAR 0x00
-#define MR1_ERRBLOCK 0x20
-#define MR1_ISRUNMASKED 0x00
-#define MR1_ISRMASKED 0x40
-#define MR1_AUTORTS 0x80
-
-/*
- * Mode register 2 bit definitions.
- */
-#define MR2_STOP1 0x00
-#define MR2_STOP15 0x01
-#define MR2_STOP2 0x02
-#define MR2_STOP916 0x03
-#define MR2_RXFIFORDY 0x00
-#define MR2_RXFIFOHALF 0x04
-#define MR2_RXFIFOHIGH 0x08
-#define MR2_RXFIFOFULL 0x0c
-#define MR2_AUTOCTS 0x10
-#define MR2_TXRTS 0x20
-#define MR2_MODENORM 0x00
-#define MR2_MODEAUTOECHO 0x40
-#define MR2_MODELOOP 0x80
-#define MR2_MODEREMECHO 0xc0
-
-/*****************************************************************************/
-
-/*
- * Baud Rate Generator (BRG) selector values.
- */
-#define BRG_50 0x00
-#define BRG_75 0x01
-#define BRG_150 0x02
-#define BRG_200 0x03
-#define BRG_300 0x04
-#define BRG_450 0x05
-#define BRG_600 0x06
-#define BRG_900 0x07
-#define BRG_1200 0x08
-#define BRG_1800 0x09
-#define BRG_2400 0x0a
-#define BRG_3600 0x0b
-#define BRG_4800 0x0c
-#define BRG_7200 0x0d
-#define BRG_9600 0x0e
-#define BRG_14400 0x0f
-#define BRG_19200 0x10
-#define BRG_28200 0x11
-#define BRG_38400 0x12
-#define BRG_57600 0x13
-#define BRG_115200 0x14
-#define BRG_230400 0x15
-#define BRG_GIN0 0x16
-#define BRG_GIN1 0x17
-#define BRG_CT0 0x18
-#define BRG_CT1 0x19
-#define BRG_RX2TX316 0x1b
-#define BRG_RX2TX31 0x1c
-
-#define SC26198_MAXBAUD 921600
-
-/*****************************************************************************/
-
-/*
- * Command register command definitions.
- */
-#define CR_NULL 0x04
-#define CR_ADDRNORMAL 0x0c
-#define CR_RXRESET 0x14
-#define CR_TXRESET 0x1c
-#define CR_CLEARRXERR 0x24
-#define CR_BREAKRESET 0x2c
-#define CR_TXSTARTBREAK 0x34
-#define CR_TXSTOPBREAK 0x3c
-#define CR_RTSON 0x44
-#define CR_RTSOFF 0x4c
-#define CR_ADDRINIT 0x5c
-#define CR_RXERRBLOCK 0x6c
-#define CR_TXSENDXON 0x84
-#define CR_TXSENDXOFF 0x8c
-#define CR_GANGXONSET 0x94
-#define CR_GANGXOFFSET 0x9c
-#define CR_GANGXONINIT 0xa4
-#define CR_GANGXOFFINIT 0xac
-#define CR_HOSTXON 0xb4
-#define CR_HOSTXOFF 0xbc
-#define CR_CANCELXOFF 0xc4
-#define CR_ADDRRESET 0xdc
-#define CR_RESETALLPORTS 0xf4
-#define CR_RESETALL 0xfc
-
-#define CR_RXENABLE 0x01
-#define CR_TXENABLE 0x02
-
-/*****************************************************************************/
-
-/*
- * Channel status register.
- */
-#define SR_RXRDY 0x01
-#define SR_RXFULL 0x02
-#define SR_TXRDY 0x04
-#define SR_TXEMPTY 0x08
-#define SR_RXOVERRUN 0x10
-#define SR_RXPARITY 0x20
-#define SR_RXFRAMING 0x40
-#define SR_RXBREAK 0x80
-
-#define SR_RXERRS (SR_RXPARITY | SR_RXFRAMING | SR_RXOVERRUN)
-
-/*****************************************************************************/
-
-/*
- * Interrupt status register and interrupt mask register bit definitions.
- */
-#define IR_TXRDY 0x01
-#define IR_RXRDY 0x02
-#define IR_RXBREAK 0x04
-#define IR_XONXOFF 0x10
-#define IR_ADDRRECOG 0x20
-#define IR_RXWATCHDOG 0x40
-#define IR_IOPORT 0x80
-
-/*****************************************************************************/
-
-/*
- * Interrupt vector register field definitions.
- */
-#define IVR_CHANMASK 0x07
-#define IVR_TYPEMASK 0x18
-#define IVR_CONSTMASK 0xc0
-
-#define IVR_RXDATA 0x10
-#define IVR_RXBADDATA 0x18
-#define IVR_TXDATA 0x08
-#define IVR_OTHER 0x00
-
-/*****************************************************************************/
-
-/*
- * BRG timer control register bit definitions.
- */
-#define BRGCTCR_DISABCLK0 0x00
-#define BRGCTCR_ENABCLK0 0x08
-#define BRGCTCR_DISABCLK1 0x00
-#define BRGCTCR_ENABCLK1 0x80
-
-#define BRGCTCR_0SCLK16 0x00
-#define BRGCTCR_0SCLK32 0x01
-#define BRGCTCR_0SCLK64 0x02
-#define BRGCTCR_0SCLK128 0x03
-#define BRGCTCR_0X1 0x04
-#define BRGCTCR_0X12 0x05
-#define BRGCTCR_0IO1A 0x06
-#define BRGCTCR_0GIN0 0x07
-
-#define BRGCTCR_1SCLK16 0x00
-#define BRGCTCR_1SCLK32 0x10
-#define BRGCTCR_1SCLK64 0x20
-#define BRGCTCR_1SCLK128 0x30
-#define BRGCTCR_1X1 0x40
-#define BRGCTCR_1X12 0x50
-#define BRGCTCR_1IO1B 0x60
-#define BRGCTCR_1GIN1 0x70
-
-/*****************************************************************************/
-
-/*
- * Watch dog timer enable register.
- */
-#define WDTRCR_ENABALL 0xff
-
-/*****************************************************************************/
-
-/*
- * XON/XOFF interrupt status register.
- */
-#define XISR_TXCHARMASK 0x03
-#define XISR_TXCHARNORMAL 0x00
-#define XISR_TXWAIT 0x01
-#define XISR_TXXOFFPEND 0x02
-#define XISR_TXXONPEND 0x03
-
-#define XISR_TXFLOWMASK 0x0c
-#define XISR_TXNORMAL 0x00
-#define XISR_TXSTOPPEND 0x04
-#define XISR_TXSTARTED 0x08
-#define XISR_TXSTOPPED 0x0c
-
-#define XISR_RXFLOWMASK 0x30
-#define XISR_RXFLOWNONE 0x00
-#define XISR_RXXONSENT 0x10
-#define XISR_RXXOFFSENT 0x20
-
-#define XISR_RXXONGOT 0x40
-#define XISR_RXXOFFGOT 0x80
-
-/*****************************************************************************/
-
-/*
- * Current interrupt register.
- */
-#define CIR_TYPEMASK 0xc0
-#define CIR_TYPEOTHER 0x00
-#define CIR_TYPETX 0x40
-#define CIR_TYPERXGOOD 0x80
-#define CIR_TYPERXBAD 0xc0
-
-#define CIR_RXDATA 0x80
-#define CIR_RXBADDATA 0x40
-#define CIR_TXDATA 0x40
-
-#define CIR_CHANMASK 0x07
-#define CIR_CNTMASK 0x38
-
-#define CIR_SUBTYPEMASK 0x38
-#define CIR_SUBNONE 0x00
-#define CIR_SUBCOS 0x08
-#define CIR_SUBADDR 0x10
-#define CIR_SUBXONXOFF 0x18
-#define CIR_SUBBREAK 0x28
-
-/*****************************************************************************/
-
-/*
- * Global interrupting channel register.
- */
-#define GICR_CHANMASK 0x07
-
-/*****************************************************************************/
-
-/*
- * Global interrupting byte count register.
- */
-#define GICR_COUNTMASK 0x0f
-
-/*****************************************************************************/
-
-/*
- * Global interrupting type register.
- */
-#define GITR_RXMASK 0xc0
-#define GITR_RXNONE 0x00
-#define GITR_RXBADDATA 0x80
-#define GITR_RXGOODDATA 0xc0
-#define GITR_TXDATA 0x20
-
-#define GITR_SUBTYPEMASK 0x07
-#define GITR_SUBNONE 0x00
-#define GITR_SUBCOS 0x01
-#define GITR_SUBADDR 0x02
-#define GITR_SUBXONXOFF 0x03
-#define GITR_SUBBREAK 0x05
-
-/*****************************************************************************/
-
-/*
- * Input port change register.
- */
-#define IPR_CTS 0x01
-#define IPR_DTR 0x02
-#define IPR_RTS 0x04
-#define IPR_DCD 0x08
-#define IPR_CTSCHANGE 0x10
-#define IPR_DTRCHANGE 0x20
-#define IPR_RTSCHANGE 0x40
-#define IPR_DCDCHANGE 0x80
-
-#define IPR_CHANGEMASK 0xf0
-
-/*****************************************************************************/
-
-/*
- * IO port interrupt and output register.
- */
-#define IOPR_CTS 0x01
-#define IOPR_DTR 0x02
-#define IOPR_RTS 0x04
-#define IOPR_DCD 0x08
-#define IOPR_CTSCOS 0x10
-#define IOPR_DTRCOS 0x20
-#define IOPR_RTSCOS 0x40
-#define IOPR_DCDCOS 0x80
-
-/*****************************************************************************/
-
-/*
- * IO port configuration register.
- */
-#define IOPCR_SETCTS 0x00
-#define IOPCR_SETDTR 0x04
-#define IOPCR_SETRTS 0x10
-#define IOPCR_SETDCD 0x00
-
-#define IOPCR_SETSIGS (IOPCR_SETRTS | IOPCR_SETRTS | IOPCR_SETDTR | IOPCR_SETDCD)
-
-/*****************************************************************************/
-
-/*
- * General purpose output select register.
- */
-#define GPORS_TXC1XA 0x08
-#define GPORS_TXC16XA 0x09
-#define GPORS_RXC16XA 0x0a
-#define GPORS_TXC16XB 0x0b
-#define GPORS_GPOR3 0x0c
-#define GPORS_GPOR2 0x0d
-#define GPORS_GPOR1 0x0e
-#define GPORS_GPOR0 0x0f
-
-/*****************************************************************************/
-
-/*
- * General purpose output register.
- */
-#define GPOR_0 0x01
-#define GPOR_1 0x02
-#define GPOR_2 0x04
-#define GPOR_3 0x08
-
-/*****************************************************************************/
-
-/*
- * General purpose output clock register.
- */
-#define GPORC_0NONE 0x00
-#define GPORC_0GIN0 0x01
-#define GPORC_0GIN1 0x02
-#define GPORC_0IO3A 0x02
-
-#define GPORC_1NONE 0x00
-#define GPORC_1GIN0 0x04
-#define GPORC_1GIN1 0x08
-#define GPORC_1IO3C 0x0c
-
-#define GPORC_2NONE 0x00
-#define GPORC_2GIN0 0x10
-#define GPORC_2GIN1 0x20
-#define GPORC_2IO3E 0x20
-
-#define GPORC_3NONE 0x00
-#define GPORC_3GIN0 0x40
-#define GPORC_3GIN1 0x80
-#define GPORC_3IO3G 0xc0
-
-/*****************************************************************************/
-
-/*
- * General purpose output data register.
- */
-#define GPOD_0MASK 0x03
-#define GPOD_0SET1 0x00
-#define GPOD_0SET0 0x01
-#define GPOD_0SETR0 0x02
-#define GPOD_0SETIO3B 0x03
-
-#define GPOD_1MASK 0x0c
-#define GPOD_1SET1 0x00
-#define GPOD_1SET0 0x04
-#define GPOD_1SETR0 0x08
-#define GPOD_1SETIO3D 0x0c
-
-#define GPOD_2MASK 0x30
-#define GPOD_2SET1 0x00
-#define GPOD_2SET0 0x10
-#define GPOD_2SETR0 0x20
-#define GPOD_2SETIO3F 0x30
-
-#define GPOD_3MASK 0xc0
-#define GPOD_3SET1 0x00
-#define GPOD_3SET0 0x40
-#define GPOD_3SETR0 0x80
-#define GPOD_3SETIO3H 0xc0
-
-/*****************************************************************************/
-#endif
diff --git a/include/linux/serial.h b/include/linux/serial.h
index 90e9f98..861e51d 100644
--- a/include/linux/serial.h
+++ b/include/linux/serial.h
@@ -12,9 +12,12 @@
#include <linux/types.h>
+#include <linux/tty_flags.h>
+
#ifdef __KERNEL__
#include <asm/page.h>
+
/*
* Counters of the input lines (CTS, DSR, RI, CD) interrupts
*/
@@ -83,89 +86,11 @@
#define SERIAL_IO_HUB6 1
#define SERIAL_IO_MEM 2
-struct serial_uart_config {
- char *name;
- int dfl_xmit_fifo_size;
- int flags;
-};
-
#define UART_CLEAR_FIFO 0x01
#define UART_USE_FIFO 0x02
#define UART_STARTECH 0x04
#define UART_NATSEMI 0x08
-/*
- * Definitions for async_struct (and serial_struct) flags field
- *
- * Define ASYNCB_* for convenient use with {test,set,clear}_bit.
- */
-#define ASYNCB_HUP_NOTIFY 0 /* Notify getty on hangups and closes
- * on the callout port */
-#define ASYNCB_FOURPORT 1 /* Set OU1, OUT2 per AST Fourport settings */
-#define ASYNCB_SAK 2 /* Secure Attention Key (Orange book) */
-#define ASYNCB_SPLIT_TERMIOS 3 /* Separate termios for dialin/callout */
-#define ASYNCB_SPD_HI 4 /* Use 56000 instead of 38400 bps */
-#define ASYNCB_SPD_VHI 5 /* Use 115200 instead of 38400 bps */
-#define ASYNCB_SKIP_TEST 6 /* Skip UART test during autoconfiguration */
-#define ASYNCB_AUTO_IRQ 7 /* Do automatic IRQ during
- * autoconfiguration */
-#define ASYNCB_SESSION_LOCKOUT 8 /* Lock out cua opens based on session */
-#define ASYNCB_PGRP_LOCKOUT 9 /* Lock out cua opens based on pgrp */
-#define ASYNCB_CALLOUT_NOHUP 10 /* Don't do hangups for cua device */
-#define ASYNCB_HARDPPS_CD 11 /* Call hardpps when CD goes high */
-#define ASYNCB_SPD_SHI 12 /* Use 230400 instead of 38400 bps */
-#define ASYNCB_LOW_LATENCY 13 /* Request low latency behaviour */
-#define ASYNCB_BUGGY_UART 14 /* This is a buggy UART, skip some safety
- * checks. Note: can be dangerous! */
-#define ASYNCB_AUTOPROBE 15 /* Port was autoprobed by PCI or PNP code */
-#define ASYNCB_LAST_USER 15
-
-/* Internal flags used only by kernel */
-#define ASYNCB_INITIALIZED 31 /* Serial port was initialized */
-#define ASYNCB_SUSPENDED 30 /* Serial port is suspended */
-#define ASYNCB_NORMAL_ACTIVE 29 /* Normal device is active */
-#define ASYNCB_BOOT_AUTOCONF 28 /* Autoconfigure port on bootup */
-#define ASYNCB_CLOSING 27 /* Serial port is closing */
-#define ASYNCB_CTS_FLOW 26 /* Do CTS flow control */
-#define ASYNCB_CHECK_CD 25 /* i.e., CLOCAL */
-#define ASYNCB_SHARE_IRQ 24 /* for multifunction cards, no longer used */
-#define ASYNCB_CONS_FLOW 23 /* flow control for console */
-#define ASYNCB_FIRST_KERNEL 22
-
-#define ASYNC_HUP_NOTIFY (1U << ASYNCB_HUP_NOTIFY)
-#define ASYNC_SUSPENDED (1U << ASYNCB_SUSPENDED)
-#define ASYNC_FOURPORT (1U << ASYNCB_FOURPORT)
-#define ASYNC_SAK (1U << ASYNCB_SAK)
-#define ASYNC_SPLIT_TERMIOS (1U << ASYNCB_SPLIT_TERMIOS)
-#define ASYNC_SPD_HI (1U << ASYNCB_SPD_HI)
-#define ASYNC_SPD_VHI (1U << ASYNCB_SPD_VHI)
-#define ASYNC_SKIP_TEST (1U << ASYNCB_SKIP_TEST)
-#define ASYNC_AUTO_IRQ (1U << ASYNCB_AUTO_IRQ)
-#define ASYNC_SESSION_LOCKOUT (1U << ASYNCB_SESSION_LOCKOUT)
-#define ASYNC_PGRP_LOCKOUT (1U << ASYNCB_PGRP_LOCKOUT)
-#define ASYNC_CALLOUT_NOHUP (1U << ASYNCB_CALLOUT_NOHUP)
-#define ASYNC_HARDPPS_CD (1U << ASYNCB_HARDPPS_CD)
-#define ASYNC_SPD_SHI (1U << ASYNCB_SPD_SHI)
-#define ASYNC_LOW_LATENCY (1U << ASYNCB_LOW_LATENCY)
-#define ASYNC_BUGGY_UART (1U << ASYNCB_BUGGY_UART)
-#define ASYNC_AUTOPROBE (1U << ASYNCB_AUTOPROBE)
-
-#define ASYNC_FLAGS ((1U << (ASYNCB_LAST_USER + 1)) - 1)
-#define ASYNC_USR_MASK (ASYNC_SPD_MASK|ASYNC_CALLOUT_NOHUP| \
- ASYNC_LOW_LATENCY)
-#define ASYNC_SPD_CUST (ASYNC_SPD_HI|ASYNC_SPD_VHI)
-#define ASYNC_SPD_WARP (ASYNC_SPD_HI|ASYNC_SPD_SHI)
-#define ASYNC_SPD_MASK (ASYNC_SPD_HI|ASYNC_SPD_VHI|ASYNC_SPD_SHI)
-
-#define ASYNC_INITIALIZED (1U << ASYNCB_INITIALIZED)
-#define ASYNC_NORMAL_ACTIVE (1U << ASYNCB_NORMAL_ACTIVE)
-#define ASYNC_BOOT_AUTOCONF (1U << ASYNCB_BOOT_AUTOCONF)
-#define ASYNC_CLOSING (1U << ASYNCB_CLOSING)
-#define ASYNC_CTS_FLOW (1U << ASYNCB_CTS_FLOW)
-#define ASYNC_CHECK_CD (1U << ASYNCB_CHECK_CD)
-#define ASYNC_SHARE_IRQ (1U << ASYNCB_SHARE_IRQ)
-#define ASYNC_CONS_FLOW (1U << ASYNCB_CONS_FLOW)
-#define ASYNC_INTERNAL_FLAGS (~((1U << ASYNCB_FIRST_KERNEL) - 1))
/*
* Multiport serial configuration structure --- external structure
diff --git a/include/linux/serial167.h b/include/linux/serial167.h
deleted file mode 100644
index 59c81b7..0000000
--- a/include/linux/serial167.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * serial167.h
- *
- * Richard Hirst [richard@sleepie.demon.co.uk]
- *
- * Based on cyclades.h
- */
-
-struct cyclades_monitor {
- unsigned long int_count;
- unsigned long char_count;
- unsigned long char_max;
- unsigned long char_last;
-};
-
-/*
- * This is our internal structure for each serial port's state.
- *
- * Many fields are paralleled by the structure used by the serial_struct
- * structure.
- *
- * For definitions of the flags field, see tty.h
- */
-
-struct cyclades_port {
- int magic;
- int type;
- int card;
- int line;
- int flags; /* defined in tty.h */
- struct tty_struct *tty;
- int read_status_mask;
- int timeout;
- int xmit_fifo_size;
- int cor1,cor2,cor3,cor4,cor5,cor6,cor7;
- int tbpr,tco,rbpr,rco;
- int ignore_status_mask;
- int close_delay;
- int IER; /* Interrupt Enable Register */
- unsigned long last_active;
- int count; /* # of fd on device */
- int x_char; /* to be pushed out ASAP */
- int x_break;
- int blocked_open; /* # of blocked opens */
- unsigned char *xmit_buf;
- int xmit_head;
- int xmit_tail;
- int xmit_cnt;
- int default_threshold;
- int default_timeout;
- wait_queue_head_t open_wait;
- wait_queue_head_t close_wait;
- struct cyclades_monitor mon;
-};
-
-#define CYCLADES_MAGIC 0x4359
-
-#define CYGETMON 0x435901
-#define CYGETTHRESH 0x435902
-#define CYSETTHRESH 0x435903
-#define CYGETDEFTHRESH 0x435904
-#define CYSETDEFTHRESH 0x435905
-#define CYGETTIMEOUT 0x435906
-#define CYSETTIMEOUT 0x435907
-#define CYGETDEFTIMEOUT 0x435908
-#define CYSETDEFTIMEOUT 0x435909
-
-#define CyMaxChipsPerCard 1
-
-/**** cd2401 registers ****/
-
-#define CyGFRCR (0x81)
-#define CyCCR (0x13)
-#define CyCLR_CHAN (0x40)
-#define CyINIT_CHAN (0x20)
-#define CyCHIP_RESET (0x10)
-#define CyENB_XMTR (0x08)
-#define CyDIS_XMTR (0x04)
-#define CyENB_RCVR (0x02)
-#define CyDIS_RCVR (0x01)
-#define CyCAR (0xee)
-#define CyIER (0x11)
-#define CyMdmCh (0x80)
-#define CyRxExc (0x20)
-#define CyRxData (0x08)
-#define CyTxMpty (0x02)
-#define CyTxRdy (0x01)
-#define CyLICR (0x26)
-#define CyRISR (0x89)
-#define CyTIMEOUT (0x80)
-#define CySPECHAR (0x70)
-#define CyOVERRUN (0x08)
-#define CyPARITY (0x04)
-#define CyFRAME (0x02)
-#define CyBREAK (0x01)
-#define CyREOIR (0x84)
-#define CyTEOIR (0x85)
-#define CyMEOIR (0x86)
-#define CyNOTRANS (0x08)
-#define CyRFOC (0x30)
-#define CyRDR (0xf8)
-#define CyTDR (0xf8)
-#define CyMISR (0x8b)
-#define CyRISR (0x89)
-#define CyTISR (0x8a)
-#define CyMSVR1 (0xde)
-#define CyMSVR2 (0xdf)
-#define CyDSR (0x80)
-#define CyDCD (0x40)
-#define CyCTS (0x20)
-#define CyDTR (0x02)
-#define CyRTS (0x01)
-#define CyRTPRL (0x25)
-#define CyRTPRH (0x24)
-#define CyCOR1 (0x10)
-#define CyPARITY_NONE (0x00)
-#define CyPARITY_E (0x40)
-#define CyPARITY_O (0xC0)
-#define Cy_5_BITS (0x04)
-#define Cy_6_BITS (0x05)
-#define Cy_7_BITS (0x06)
-#define Cy_8_BITS (0x07)
-#define CyCOR2 (0x17)
-#define CyETC (0x20)
-#define CyCtsAE (0x02)
-#define CyCOR3 (0x16)
-#define Cy_1_STOP (0x02)
-#define Cy_2_STOP (0x04)
-#define CyCOR4 (0x15)
-#define CyREC_FIFO (0x0F) /* Receive FIFO threshold */
-#define CyCOR5 (0x14)
-#define CyCOR6 (0x18)
-#define CyCOR7 (0x07)
-#define CyRBPR (0xcb)
-#define CyRCOR (0xc8)
-#define CyTBPR (0xc3)
-#define CyTCOR (0xc0)
-#define CySCHR1 (0x1f)
-#define CySCHR2 (0x1e)
-#define CyTPR (0xda)
-#define CyPILR1 (0xe3)
-#define CyPILR2 (0xe0)
-#define CyPILR3 (0xe1)
-#define CyCMR (0x1b)
-#define CyASYNC (0x02)
-#define CyLICR (0x26)
-#define CyLIVR (0x09)
-#define CySCRL (0x23)
-#define CySCRH (0x22)
-#define CyTFTC (0x80)
-
-
-/* max number of chars in the FIFO */
-
-#define CyMAX_CHAR_FIFO 12
-
-/***************************************************************************/
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index a416e92..c174c90 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -65,11 +65,38 @@
* platform device. Using these will make your driver
* dependent on the 8250 driver.
*/
-struct uart_port;
-struct uart_8250_port;
+
+struct uart_8250_port {
+ struct uart_port port;
+ struct timer_list timer; /* "no irq" timer */
+ struct list_head list; /* ports on this IRQ */
+ unsigned short capabilities; /* port capabilities */
+ unsigned short bugs; /* port bugs */
+ unsigned int tx_loadsz; /* transmit fifo load size */
+ unsigned char acr;
+ unsigned char ier;
+ unsigned char lcr;
+ unsigned char mcr;
+ unsigned char mcr_mask; /* mask of user bits */
+ unsigned char mcr_force; /* mask of forced bits */
+ unsigned char cur_iotype; /* Running I/O type */
+
+ /*
+ * Some bits in registers are cleared on a read, so they must
+ * be saved whenever the register is read but the bits will not
+ * be immediately processed.
+ */
+#define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS
+ unsigned char lsr_saved_flags;
+#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
+ unsigned char msr_saved_flags;
+
+ /* 8250 specific callbacks */
+ int (*dl_read)(struct uart_8250_port *);
+ void (*dl_write)(struct uart_8250_port *, int);
+};
int serial8250_register_8250_port(struct uart_8250_port *);
-int serial8250_register_port(struct uart_port *);
void serial8250_unregister_port(int line);
void serial8250_suspend_port(int line);
void serial8250_resume_port(int line);
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 0253c20..7cf0b68 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -193,8 +193,8 @@
/* SH-SCI */
#define PORT_SCIFB 93
-/* MAX3107 */
-#define PORT_MAX3107 94
+/* MAX310X */
+#define PORT_MAX310X 94
/* High Speed UART for Medfield */
#define PORT_MFD 95
diff --git a/include/linux/serial_reg.h b/include/linux/serial_reg.h
index 8ce70d7..5ed325e 100644
--- a/include/linux/serial_reg.h
+++ b/include/linux/serial_reg.h
@@ -40,6 +40,10 @@
#define UART_IIR_BUSY 0x07 /* DesignWare APB Busy Detect */
+#define UART_IIR_RX_TIMEOUT 0x0c /* OMAP RX Timeout interrupt */
+#define UART_IIR_XOFF 0x10 /* OMAP XOFF/Special Character */
+#define UART_IIR_CTS_RTS_DSR 0x20 /* OMAP CTS/RTS/DSR Change */
+
#define UART_FCR 2 /* Out: FIFO Control Register */
#define UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */
#define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */
diff --git a/include/linux/stallion.h b/include/linux/stallion.h
deleted file mode 100644
index 336af33c..0000000
--- a/include/linux/stallion.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*****************************************************************************/
-
-/*
- * stallion.h -- stallion multiport serial driver.
- *
- * Copyright (C) 1996-1998 Stallion Technologies
- * Copyright (C) 1994-1996 Greg Ungerer.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*****************************************************************************/
-#ifndef _STALLION_H
-#define _STALLION_H
-/*****************************************************************************/
-
-/*
- * Define important driver constants here.
- */
-#define STL_MAXBRDS 4
-#define STL_MAXPANELS 4
-#define STL_MAXBANKS 8
-#define STL_PORTSPERPANEL 16
-#define STL_MAXPORTS 64
-#define STL_MAXDEVS (STL_MAXBRDS * STL_MAXPORTS)
-
-
-/*
- * Define a set of structures to hold all the board/panel/port info
- * for our ports. These will be dynamically allocated as required.
- */
-
-/*
- * Define a ring queue structure for each port. This will hold the
- * TX data waiting to be output. Characters are fed into this buffer
- * from the line discipline (or even direct from user space!) and
- * then fed into the UARTs during interrupts. Will use a classic ring
- * queue here for this. The good thing about this type of ring queue
- * is that the head and tail pointers can be updated without interrupt
- * protection - since "write" code only needs to change the head, and
- * interrupt code only needs to change the tail.
- */
-struct stlrq {
- char *buf;
- char *head;
- char *tail;
-};
-
-/*
- * Port, panel and board structures to hold status info about each.
- * The board structure contains pointers to structures for each panel
- * connected to it, and in turn each panel structure contains pointers
- * for each port structure for each port on that panel. Note that
- * the port structure also contains the board and panel number that it
- * is associated with, this makes it (fairly) easy to get back to the
- * board/panel info for a port.
- */
-struct stlport {
- unsigned long magic;
- struct tty_port port;
- unsigned int portnr;
- unsigned int panelnr;
- unsigned int brdnr;
- int ioaddr;
- int uartaddr;
- unsigned int pagenr;
- unsigned long istate;
- int baud_base;
- int custom_divisor;
- int close_delay;
- int closing_wait;
- int openwaitcnt;
- int brklen;
- unsigned int sigs;
- unsigned int rxignoremsk;
- unsigned int rxmarkmsk;
- unsigned int imr;
- unsigned int crenable;
- unsigned long clk;
- unsigned long hwid;
- void *uartp;
- comstats_t stats;
- struct stlrq tx;
-};
-
-struct stlpanel {
- unsigned long magic;
- 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;
- struct stlport *ports[STL_PORTSPERPANEL];
-};
-
-struct stlbrd {
- unsigned long magic;
- 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);
- unsigned int ioaddr1;
- unsigned int ioaddr2;
- unsigned int iosize1;
- unsigned int iosize2;
- unsigned int iostatus;
- unsigned int ioctrl;
- unsigned int ioctrlval;
- unsigned int hwid;
- unsigned long clk;
- unsigned int bnkpageaddr[STL_MAXBANKS];
- unsigned int bnkstataddr[STL_MAXBANKS];
- struct stlpanel *bnk2panel[STL_MAXBANKS];
- struct stlpanel *panels[STL_MAXPANELS];
-};
-
-
-/*
- * Define MAGIC numbers used for above structures.
- */
-#define STL_PORTMAGIC 0x5a7182c9
-#define STL_PANELMAGIC 0x7ef621a1
-#define STL_BOARDMAGIC 0xa2267f52
-
-/*****************************************************************************/
-#endif
diff --git a/include/linux/time.h b/include/linux/time.h
index c81c5e4..b51e664 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -107,11 +107,36 @@
return ts_delta;
}
+#define KTIME_MAX ((s64)~((u64)1 << 63))
+#if (BITS_PER_LONG == 64)
+# define KTIME_SEC_MAX (KTIME_MAX / NSEC_PER_SEC)
+#else
+# define KTIME_SEC_MAX LONG_MAX
+#endif
+
/*
* Returns true if the timespec is norm, false if denorm:
*/
-#define timespec_valid(ts) \
- (((ts)->tv_sec >= 0) && (((unsigned long) (ts)->tv_nsec) < NSEC_PER_SEC))
+static inline bool timespec_valid(const struct timespec *ts)
+{
+ /* Dates before 1970 are bogus */
+ if (ts->tv_sec < 0)
+ return false;
+ /* Can't have more nanoseconds then a second */
+ if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC)
+ return false;
+ return true;
+}
+
+static inline bool timespec_valid_strict(const struct timespec *ts)
+{
+ if (!timespec_valid(ts))
+ return false;
+ /* Disallow values that could overflow ktime_t */
+ if ((unsigned long long)ts->tv_sec >= KTIME_SEC_MAX)
+ return false;
+ return true;
+}
extern void read_persistent_clock(struct timespec *ts);
extern void read_boot_clock(struct timespec *ts);
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 9f47ab5..1509b86 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -43,6 +43,7 @@
#include <linux/tty_driver.h>
#include <linux/tty_ldisc.h>
#include <linux/mutex.h>
+#include <linux/tty_flags.h>
@@ -103,28 +104,28 @@
#define TTY_PARITY 3
#define TTY_OVERRUN 4
-#define INTR_CHAR(tty) ((tty)->termios->c_cc[VINTR])
-#define QUIT_CHAR(tty) ((tty)->termios->c_cc[VQUIT])
-#define ERASE_CHAR(tty) ((tty)->termios->c_cc[VERASE])
-#define KILL_CHAR(tty) ((tty)->termios->c_cc[VKILL])
-#define EOF_CHAR(tty) ((tty)->termios->c_cc[VEOF])
-#define TIME_CHAR(tty) ((tty)->termios->c_cc[VTIME])
-#define MIN_CHAR(tty) ((tty)->termios->c_cc[VMIN])
-#define SWTC_CHAR(tty) ((tty)->termios->c_cc[VSWTC])
-#define START_CHAR(tty) ((tty)->termios->c_cc[VSTART])
-#define STOP_CHAR(tty) ((tty)->termios->c_cc[VSTOP])
-#define SUSP_CHAR(tty) ((tty)->termios->c_cc[VSUSP])
-#define EOL_CHAR(tty) ((tty)->termios->c_cc[VEOL])
-#define REPRINT_CHAR(tty) ((tty)->termios->c_cc[VREPRINT])
-#define DISCARD_CHAR(tty) ((tty)->termios->c_cc[VDISCARD])
-#define WERASE_CHAR(tty) ((tty)->termios->c_cc[VWERASE])
-#define LNEXT_CHAR(tty) ((tty)->termios->c_cc[VLNEXT])
-#define EOL2_CHAR(tty) ((tty)->termios->c_cc[VEOL2])
+#define INTR_CHAR(tty) ((tty)->termios.c_cc[VINTR])
+#define QUIT_CHAR(tty) ((tty)->termios.c_cc[VQUIT])
+#define ERASE_CHAR(tty) ((tty)->termios.c_cc[VERASE])
+#define KILL_CHAR(tty) ((tty)->termios.c_cc[VKILL])
+#define EOF_CHAR(tty) ((tty)->termios.c_cc[VEOF])
+#define TIME_CHAR(tty) ((tty)->termios.c_cc[VTIME])
+#define MIN_CHAR(tty) ((tty)->termios.c_cc[VMIN])
+#define SWTC_CHAR(tty) ((tty)->termios.c_cc[VSWTC])
+#define START_CHAR(tty) ((tty)->termios.c_cc[VSTART])
+#define STOP_CHAR(tty) ((tty)->termios.c_cc[VSTOP])
+#define SUSP_CHAR(tty) ((tty)->termios.c_cc[VSUSP])
+#define EOL_CHAR(tty) ((tty)->termios.c_cc[VEOL])
+#define REPRINT_CHAR(tty) ((tty)->termios.c_cc[VREPRINT])
+#define DISCARD_CHAR(tty) ((tty)->termios.c_cc[VDISCARD])
+#define WERASE_CHAR(tty) ((tty)->termios.c_cc[VWERASE])
+#define LNEXT_CHAR(tty) ((tty)->termios.c_cc[VLNEXT])
+#define EOL2_CHAR(tty) ((tty)->termios.c_cc[VEOL2])
-#define _I_FLAG(tty, f) ((tty)->termios->c_iflag & (f))
-#define _O_FLAG(tty, f) ((tty)->termios->c_oflag & (f))
-#define _C_FLAG(tty, f) ((tty)->termios->c_cflag & (f))
-#define _L_FLAG(tty, f) ((tty)->termios->c_lflag & (f))
+#define _I_FLAG(tty, f) ((tty)->termios.c_iflag & (f))
+#define _O_FLAG(tty, f) ((tty)->termios.c_oflag & (f))
+#define _C_FLAG(tty, f) ((tty)->termios.c_cflag & (f))
+#define _L_FLAG(tty, f) ((tty)->termios.c_lflag & (f))
#define I_IGNBRK(tty) _I_FLAG((tty), IGNBRK)
#define I_BRKINT(tty) _I_FLAG((tty), BRKINT)
@@ -268,10 +269,11 @@
struct mutex ldisc_mutex;
struct tty_ldisc *ldisc;
+ struct mutex legacy_mutex;
struct mutex termios_mutex;
spinlock_t ctrl_lock;
/* Termios values are protected by the termios mutex */
- struct ktermios *termios, *termios_locked;
+ struct ktermios termios, termios_locked;
struct termiox *termiox; /* May be NULL for unsupported */
char name[64];
struct pid *pgrp; /* Protected by ctrl lock */
@@ -410,6 +412,10 @@
extern int tty_unregister_driver(struct tty_driver *driver);
extern struct device *tty_register_device(struct tty_driver *driver,
unsigned index, struct device *dev);
+extern struct device *tty_register_device_attr(struct tty_driver *driver,
+ unsigned index, struct device *device,
+ void *drvdata,
+ const struct attribute_group **attr_grp);
extern void tty_unregister_device(struct tty_driver *driver, unsigned index);
extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp,
int buflen);
@@ -423,7 +429,6 @@
extern int tty_do_resize(struct tty_struct *tty, struct winsize *ws);
extern void tty_driver_remove_tty(struct tty_driver *driver,
struct tty_struct *tty);
-extern void tty_shutdown(struct tty_struct *tty);
extern void tty_free_termios(struct tty_struct *tty);
extern int is_current_pgrp_orphaned(void);
extern struct pid *tty_get_pgrp(struct tty_struct *tty);
@@ -497,6 +502,15 @@
#define tty_is_writelocked(tty) (mutex_is_locked(&tty->atomic_write_lock))
extern void tty_port_init(struct tty_port *port);
+extern void tty_port_link_device(struct tty_port *port,
+ struct tty_driver *driver, unsigned index);
+extern struct device *tty_port_register_device(struct tty_port *port,
+ struct tty_driver *driver, unsigned index,
+ struct device *device);
+extern struct device *tty_port_register_device_attr(struct tty_port *port,
+ struct tty_driver *driver, unsigned index,
+ struct device *device, void *drvdata,
+ const struct attribute_group **attr_grp);
extern int tty_port_alloc_xmit_buf(struct tty_port *port);
extern void tty_port_free_xmit_buf(struct tty_port *port);
extern void tty_port_put(struct tty_port *port);
@@ -508,6 +522,12 @@
return port;
}
+/* If the cts flow control is enabled, return true. */
+static inline bool tty_port_cts_enabled(struct tty_port *port)
+{
+ return port->flags & ASYNC_CTS_FLOW;
+}
+
extern struct tty_struct *tty_port_tty_get(struct tty_port *port);
extern void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty);
extern int tty_port_carrier_raised(struct tty_port *port);
@@ -521,6 +541,8 @@
extern void tty_port_close_end(struct tty_port *port, struct tty_struct *tty);
extern void tty_port_close(struct tty_port *port,
struct tty_struct *tty, struct file *filp);
+extern int tty_port_install(struct tty_port *port, struct tty_driver *driver,
+ struct tty_struct *tty);
extern int tty_port_open(struct tty_port *port,
struct tty_struct *tty, struct file *filp);
static inline int tty_port_users(struct tty_port *port)
@@ -605,8 +627,12 @@
/* tty_mutex.c */
/* functions for preparation of BKL removal */
-extern void __lockfunc tty_lock(void) __acquires(tty_lock);
-extern void __lockfunc tty_unlock(void) __releases(tty_lock);
+extern void __lockfunc tty_lock(struct tty_struct *tty);
+extern void __lockfunc tty_unlock(struct tty_struct *tty);
+extern void __lockfunc tty_lock_pair(struct tty_struct *tty,
+ struct tty_struct *tty2);
+extern void __lockfunc tty_unlock_pair(struct tty_struct *tty,
+ struct tty_struct *tty2);
/*
* this shall be called only from where BTM is held (like close)
@@ -621,9 +647,9 @@
static inline void tty_wait_until_sent_from_close(struct tty_struct *tty,
long timeout)
{
- tty_unlock(); /* tty->ops->close holds the BTM, drop it while waiting */
+ tty_unlock(tty); /* tty->ops->close holds the BTM, drop it while waiting */
tty_wait_until_sent(tty, timeout);
- tty_lock();
+ tty_lock(tty);
}
/*
@@ -638,16 +664,16 @@
*
* Do not use in new code.
*/
-#define wait_event_interruptible_tty(wq, condition) \
+#define wait_event_interruptible_tty(tty, wq, condition) \
({ \
int __ret = 0; \
if (!(condition)) { \
- __wait_event_interruptible_tty(wq, condition, __ret); \
+ __wait_event_interruptible_tty(tty, wq, condition, __ret); \
} \
__ret; \
})
-#define __wait_event_interruptible_tty(wq, condition, ret) \
+#define __wait_event_interruptible_tty(tty, wq, condition, ret) \
do { \
DEFINE_WAIT(__wait); \
\
@@ -656,9 +682,9 @@
if (condition) \
break; \
if (!signal_pending(current)) { \
- tty_unlock(); \
+ tty_unlock(tty); \
schedule(); \
- tty_lock(); \
+ tty_lock(tty); \
continue; \
} \
ret = -ERESTARTSYS; \
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index 6e6dbb7..dd976cf 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -45,14 +45,9 @@
*
* void (*shutdown)(struct tty_struct * tty);
*
- * This routine is called synchronously when a particular tty device
- * is closed for the last time freeing up the resources.
- * Note that tty_shutdown() is not called if ops->shutdown is defined.
- * This means one is responsible to take care of calling ops->remove (e.g.
- * via tty_driver_remove_tty) and releasing tty->termios.
- * Note that this hook may be called from *all* the contexts where one
- * uses tty refcounting (e.g. tty_port_tty_get).
- *
+ * This routine is called under the tty lock when a particular tty device
+ * is closed for the last time. It executes before the tty resources
+ * are freed so may execute while another function holds a tty kref.
*
* void (*cleanup)(struct tty_struct * tty);
*
@@ -294,18 +289,18 @@
struct tty_driver {
int magic; /* magic number for this structure */
struct kref kref; /* Reference management */
- struct cdev cdev;
+ struct cdev *cdevs;
struct module *owner;
const char *driver_name;
const char *name;
int name_base; /* offset of printed name */
int major; /* major device number */
int minor_start; /* start of minor device number */
- int num; /* number of devices allocated */
+ unsigned int num; /* number of devices allocated */
short type; /* type of tty driver */
short subtype; /* subtype of tty driver */
struct ktermios init_termios; /* Initial termios */
- int flags; /* tty driver flags */
+ unsigned long flags; /* tty driver flags */
struct proc_dir_entry *proc_entry; /* /proc fs entry */
struct tty_driver *other; /* only used for the PTY driver */
@@ -313,6 +308,7 @@
* Pointer to the tty data structures
*/
struct tty_struct **ttys;
+ struct tty_port **ports;
struct ktermios **termios;
void *driver_state;
@@ -326,7 +322,8 @@
extern struct list_head tty_drivers;
-extern struct tty_driver *__alloc_tty_driver(int lines, struct module *owner);
+extern struct tty_driver *__tty_alloc_driver(unsigned int lines,
+ struct module *owner, unsigned long flags);
extern void put_tty_driver(struct tty_driver *driver);
extern void tty_set_operations(struct tty_driver *driver,
const struct tty_operations *op);
@@ -334,7 +331,21 @@
extern void tty_driver_kref_put(struct tty_driver *driver);
-#define alloc_tty_driver(lines) __alloc_tty_driver(lines, THIS_MODULE)
+/* Use TTY_DRIVER_* flags below */
+#define tty_alloc_driver(lines, flags) \
+ __tty_alloc_driver(lines, THIS_MODULE, flags)
+
+/*
+ * DEPRECATED Do not use this in new code, use tty_alloc_driver instead.
+ * (And change the return value checks.)
+ */
+static inline struct tty_driver *alloc_tty_driver(unsigned int lines)
+{
+ struct tty_driver *ret = tty_alloc_driver(lines, 0);
+ if (IS_ERR(ret))
+ return NULL;
+ return ret;
+}
static inline struct tty_driver *tty_driver_kref_get(struct tty_driver *d)
{
@@ -380,6 +391,14 @@
* the requested timeout to the caller instead of using a simple
* on/off interface.
*
+ * TTY_DRIVER_DYNAMIC_ALLOC -- do not allocate structures which are
+ * needed per line for this driver as it would waste memory.
+ * The driver will take care.
+ *
+ * TTY_DRIVER_UNNUMBERED_NODE -- do not create numbered /dev nodes. In
+ * other words create /dev/ttyprintk and not /dev/ttyprintk0.
+ * Applicable only when a driver for a single tty device is
+ * being allocated.
*/
#define TTY_DRIVER_INSTALLED 0x0001
#define TTY_DRIVER_RESET_TERMIOS 0x0002
@@ -387,6 +406,8 @@
#define TTY_DRIVER_DYNAMIC_DEV 0x0008
#define TTY_DRIVER_DEVPTS_MEM 0x0010
#define TTY_DRIVER_HARDWARE_BREAK 0x0020
+#define TTY_DRIVER_DYNAMIC_ALLOC 0x0040
+#define TTY_DRIVER_UNNUMBERED_NODE 0x0080
/* tty driver types */
#define TTY_DRIVER_TYPE_SYSTEM 0x0001
diff --git a/include/linux/tty_flags.h b/include/linux/tty_flags.h
new file mode 100644
index 0000000..eefcb48
--- /dev/null
+++ b/include/linux/tty_flags.h
@@ -0,0 +1,78 @@
+#ifndef _LINUX_TTY_FLAGS_H
+#define _LINUX_TTY_FLAGS_H
+
+/*
+ * Definitions for async_struct (and serial_struct) flags field also
+ * shared by the tty_port flags structures.
+ *
+ * Define ASYNCB_* for convenient use with {test,set,clear}_bit.
+ */
+#define ASYNCB_HUP_NOTIFY 0 /* Notify getty on hangups and closes
+ * on the callout port */
+#define ASYNCB_FOURPORT 1 /* Set OU1, OUT2 per AST Fourport settings */
+#define ASYNCB_SAK 2 /* Secure Attention Key (Orange book) */
+#define ASYNCB_SPLIT_TERMIOS 3 /* Separate termios for dialin/callout */
+#define ASYNCB_SPD_HI 4 /* Use 56000 instead of 38400 bps */
+#define ASYNCB_SPD_VHI 5 /* Use 115200 instead of 38400 bps */
+#define ASYNCB_SKIP_TEST 6 /* Skip UART test during autoconfiguration */
+#define ASYNCB_AUTO_IRQ 7 /* Do automatic IRQ during
+ * autoconfiguration */
+#define ASYNCB_SESSION_LOCKOUT 8 /* Lock out cua opens based on session */
+#define ASYNCB_PGRP_LOCKOUT 9 /* Lock out cua opens based on pgrp */
+#define ASYNCB_CALLOUT_NOHUP 10 /* Don't do hangups for cua device */
+#define ASYNCB_HARDPPS_CD 11 /* Call hardpps when CD goes high */
+#define ASYNCB_SPD_SHI 12 /* Use 230400 instead of 38400 bps */
+#define ASYNCB_LOW_LATENCY 13 /* Request low latency behaviour */
+#define ASYNCB_BUGGY_UART 14 /* This is a buggy UART, skip some safety
+ * checks. Note: can be dangerous! */
+#define ASYNCB_AUTOPROBE 15 /* Port was autoprobed by PCI or PNP code */
+#define ASYNCB_LAST_USER 15
+
+/* Internal flags used only by kernel */
+#define ASYNCB_INITIALIZED 31 /* Serial port was initialized */
+#define ASYNCB_SUSPENDED 30 /* Serial port is suspended */
+#define ASYNCB_NORMAL_ACTIVE 29 /* Normal device is active */
+#define ASYNCB_BOOT_AUTOCONF 28 /* Autoconfigure port on bootup */
+#define ASYNCB_CLOSING 27 /* Serial port is closing */
+#define ASYNCB_CTS_FLOW 26 /* Do CTS flow control */
+#define ASYNCB_CHECK_CD 25 /* i.e., CLOCAL */
+#define ASYNCB_SHARE_IRQ 24 /* for multifunction cards, no longer used */
+#define ASYNCB_CONS_FLOW 23 /* flow control for console */
+#define ASYNCB_FIRST_KERNEL 22
+
+#define ASYNC_HUP_NOTIFY (1U << ASYNCB_HUP_NOTIFY)
+#define ASYNC_SUSPENDED (1U << ASYNCB_SUSPENDED)
+#define ASYNC_FOURPORT (1U << ASYNCB_FOURPORT)
+#define ASYNC_SAK (1U << ASYNCB_SAK)
+#define ASYNC_SPLIT_TERMIOS (1U << ASYNCB_SPLIT_TERMIOS)
+#define ASYNC_SPD_HI (1U << ASYNCB_SPD_HI)
+#define ASYNC_SPD_VHI (1U << ASYNCB_SPD_VHI)
+#define ASYNC_SKIP_TEST (1U << ASYNCB_SKIP_TEST)
+#define ASYNC_AUTO_IRQ (1U << ASYNCB_AUTO_IRQ)
+#define ASYNC_SESSION_LOCKOUT (1U << ASYNCB_SESSION_LOCKOUT)
+#define ASYNC_PGRP_LOCKOUT (1U << ASYNCB_PGRP_LOCKOUT)
+#define ASYNC_CALLOUT_NOHUP (1U << ASYNCB_CALLOUT_NOHUP)
+#define ASYNC_HARDPPS_CD (1U << ASYNCB_HARDPPS_CD)
+#define ASYNC_SPD_SHI (1U << ASYNCB_SPD_SHI)
+#define ASYNC_LOW_LATENCY (1U << ASYNCB_LOW_LATENCY)
+#define ASYNC_BUGGY_UART (1U << ASYNCB_BUGGY_UART)
+#define ASYNC_AUTOPROBE (1U << ASYNCB_AUTOPROBE)
+
+#define ASYNC_FLAGS ((1U << (ASYNCB_LAST_USER + 1)) - 1)
+#define ASYNC_USR_MASK (ASYNC_SPD_MASK|ASYNC_CALLOUT_NOHUP| \
+ ASYNC_LOW_LATENCY)
+#define ASYNC_SPD_CUST (ASYNC_SPD_HI|ASYNC_SPD_VHI)
+#define ASYNC_SPD_WARP (ASYNC_SPD_HI|ASYNC_SPD_SHI)
+#define ASYNC_SPD_MASK (ASYNC_SPD_HI|ASYNC_SPD_VHI|ASYNC_SPD_SHI)
+
+#define ASYNC_INITIALIZED (1U << ASYNCB_INITIALIZED)
+#define ASYNC_NORMAL_ACTIVE (1U << ASYNCB_NORMAL_ACTIVE)
+#define ASYNC_BOOT_AUTOCONF (1U << ASYNCB_BOOT_AUTOCONF)
+#define ASYNC_CLOSING (1U << ASYNCB_CLOSING)
+#define ASYNC_CTS_FLOW (1U << ASYNCB_CTS_FLOW)
+#define ASYNC_CHECK_CD (1U << ASYNCB_CHECK_CD)
+#define ASYNC_SHARE_IRQ (1U << ASYNCB_SHARE_IRQ)
+#define ASYNC_CONS_FLOW (1U << ASYNCB_CONS_FLOW)
+#define ASYNC_INTERNAL_FLAGS (~((1U << ASYNCB_FIRST_KERNEL) - 1))
+
+#endif
diff --git a/include/net/irda/ircomm_tty.h b/include/net/irda/ircomm_tty.h
index 59ba38bc..80ffde3 100644
--- a/include/net/irda/ircomm_tty.h
+++ b/include/net/irda/ircomm_tty.h
@@ -52,21 +52,16 @@
/* Same for payload size. See qos.c for the smallest max data size */
#define IRCOMM_TTY_DATA_UNINITIALISED (64 - IRCOMM_TTY_HDR_UNINITIALISED)
-/* Those are really defined in include/linux/serial.h - Jean II */
-#define ASYNC_B_INITIALIZED 31 /* Serial port was initialized */
-#define ASYNC_B_NORMAL_ACTIVE 29 /* Normal device is active */
-#define ASYNC_B_CLOSING 27 /* Serial port is closing */
-
/*
* IrCOMM TTY driver state
*/
struct ircomm_tty_cb {
irda_queue_t queue; /* Must be first */
+ struct tty_port port;
magic_t magic;
int state; /* Connect state */
- struct tty_struct *tty;
struct ircomm_cb *ircomm; /* IrCOMM layer instance */
struct sk_buff *tx_skb; /* Transmit buffer */
@@ -80,7 +75,6 @@
LOCAL_FLOW flow; /* IrTTP flow status */
int line;
- unsigned long flags;
__u8 dlsap_sel;
__u8 slsap_sel;
@@ -97,19 +91,10 @@
void *skey;
void *ckey;
- wait_queue_head_t open_wait;
- wait_queue_head_t close_wait;
struct timer_list watchdog_timer;
struct work_struct tqueue;
- unsigned short close_delay;
- unsigned short closing_wait; /* time to wait before closing */
-
- int open_count;
- int blocked_open; /* # of blocked opens */
-
/* Protect concurent access to :
- * o self->open_count
* o self->ctrl_skb
* o self->tx_skb
* Maybe other things may gain to be protected as well...
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h
index e1ce104..4a045cd 100644
--- a/include/net/netfilter/nf_conntrack_ecache.h
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -18,6 +18,7 @@
u16 ctmask; /* bitmask of ct events to be delivered */
u16 expmask; /* bitmask of expect events to be delivered */
u32 pid; /* netlink pid of destroyer */
+ struct timer_list timeout;
};
static inline struct nf_conntrack_ecache *
diff --git a/include/xen/events.h b/include/xen/events.h
index 9c641de..04399b2 100644
--- a/include/xen/events.h
+++ b/include/xen/events.h
@@ -58,8 +58,6 @@
void xen_irq_resume(void);
-void xen_hvm_prepare_kexec(struct shared_info *sip, unsigned long pfn);
-
/* Clear an irq's pending state, in preparation for polling on it */
void xen_clear_irq_pending(int irq);
void xen_set_irq_pending(int irq);
diff --git a/kernel/fork.c b/kernel/fork.c
index 3bd2280..2c8857e 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -455,8 +455,8 @@
if (retval)
goto out;
- if (file && uprobe_mmap(tmp))
- goto out;
+ if (file)
+ uprobe_mmap(tmp);
}
/* a new mm has just been created */
arch_dup_mmap(oldmm, mm);
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index e16af19..34e5eac 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -115,6 +115,7 @@
{
tk->xtime_sec += ts->tv_sec;
tk->xtime_nsec += (u64)ts->tv_nsec << tk->shift;
+ tk_normalize_xtime(tk);
}
static void tk_set_wall_to_mono(struct timekeeper *tk, struct timespec wtm)
@@ -276,7 +277,7 @@
tk->xtime_nsec += cycle_delta * tk->mult;
/* If arch requires, add in gettimeoffset() */
- tk->xtime_nsec += arch_gettimeoffset() << tk->shift;
+ tk->xtime_nsec += (u64)arch_gettimeoffset() << tk->shift;
tk_normalize_xtime(tk);
@@ -427,7 +428,7 @@
struct timespec ts_delta, xt;
unsigned long flags;
- if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+ if (!timespec_valid_strict(tv))
return -EINVAL;
write_seqlock_irqsave(&tk->lock, flags);
@@ -463,6 +464,8 @@
{
struct timekeeper *tk = &timekeeper;
unsigned long flags;
+ struct timespec tmp;
+ int ret = 0;
if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC)
return -EINVAL;
@@ -471,10 +474,17 @@
timekeeping_forward_now(tk);
+ /* Make sure the proposed value is valid */
+ tmp = timespec_add(tk_xtime(tk), *ts);
+ if (!timespec_valid_strict(&tmp)) {
+ ret = -EINVAL;
+ goto error;
+ }
tk_xtime_add(tk, ts);
tk_set_wall_to_mono(tk, timespec_sub(tk->wall_to_monotonic, *ts));
+error: /* even if we error out, we forwarded the time, so call update */
timekeeping_update(tk, true);
write_sequnlock_irqrestore(&tk->lock, flags);
@@ -482,7 +492,7 @@
/* signal hrtimers about time change */
clock_was_set();
- return 0;
+ return ret;
}
EXPORT_SYMBOL(timekeeping_inject_offset);
@@ -649,7 +659,20 @@
struct timespec now, boot, tmp;
read_persistent_clock(&now);
+ if (!timespec_valid_strict(&now)) {
+ pr_warn("WARNING: Persistent clock returned invalid value!\n"
+ " Check your CMOS/BIOS settings.\n");
+ now.tv_sec = 0;
+ now.tv_nsec = 0;
+ }
+
read_boot_clock(&boot);
+ if (!timespec_valid_strict(&boot)) {
+ pr_warn("WARNING: Boot clock returned invalid value!\n"
+ " Check your CMOS/BIOS settings.\n");
+ boot.tv_sec = 0;
+ boot.tv_nsec = 0;
+ }
seqlock_init(&tk->lock);
@@ -690,7 +713,7 @@
static void __timekeeping_inject_sleeptime(struct timekeeper *tk,
struct timespec *delta)
{
- if (!timespec_valid(delta)) {
+ if (!timespec_valid_strict(delta)) {
printk(KERN_WARNING "__timekeeping_inject_sleeptime: Invalid "
"sleep delta value!\n");
return;
@@ -1129,6 +1152,10 @@
offset = (clock->read(clock) - clock->cycle_last) & clock->mask;
#endif
+ /* Check if there's really nothing to do */
+ if (offset < tk->cycle_interval)
+ goto out;
+
/*
* With NO_HZ we may have to accumulate many cycle_intervals
* (think "ticks") worth of time at once. To do this efficiently,
@@ -1161,9 +1188,9 @@
* the vsyscall implementations are converted to use xtime_nsec
* (shifted nanoseconds), this can be killed.
*/
- remainder = tk->xtime_nsec & ((1 << tk->shift) - 1);
+ remainder = tk->xtime_nsec & ((1ULL << tk->shift) - 1);
tk->xtime_nsec -= remainder;
- tk->xtime_nsec += 1 << tk->shift;
+ tk->xtime_nsec += 1ULL << tk->shift;
tk->ntp_error += remainder << tk->ntp_error_shift;
/*
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
index 60e4d78..6b245f64 100644
--- a/kernel/trace/trace_syscalls.c
+++ b/kernel/trace/trace_syscalls.c
@@ -506,6 +506,8 @@
int size;
syscall_nr = syscall_get_nr(current, regs);
+ if (syscall_nr < 0)
+ return;
if (!test_bit(syscall_nr, enabled_perf_enter_syscalls))
return;
@@ -580,6 +582,8 @@
int size;
syscall_nr = syscall_get_nr(current, regs);
+ if (syscall_nr < 0)
+ return;
if (!test_bit(syscall_nr, enabled_perf_exit_syscalls))
return;
diff --git a/mm/filemap.c b/mm/filemap.c
index fa5ca30..3843445 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1412,12 +1412,8 @@
retval = filemap_write_and_wait_range(mapping, pos,
pos + iov_length(iov, nr_segs) - 1);
if (!retval) {
- struct blk_plug plug;
-
- blk_start_plug(&plug);
retval = mapping->a_ops->direct_IO(READ, iocb,
iov, pos, nr_segs);
- blk_finish_plug(&plug);
}
if (retval > 0) {
*ppos = pos + retval;
@@ -2527,14 +2523,12 @@
{
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
- struct blk_plug plug;
ssize_t ret;
BUG_ON(iocb->ki_pos != pos);
sb_start_write(inode->i_sb);
mutex_lock(&inode->i_mutex);
- blk_start_plug(&plug);
ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos);
mutex_unlock(&inode->i_mutex);
@@ -2545,7 +2539,6 @@
if (err < 0 && ret > 0)
ret = err;
}
- blk_finish_plug(&plug);
sb_end_write(inode->i_sb);
return ret;
}
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index bd92431..4ada3be 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -2562,7 +2562,7 @@
break;
default:
- BUG();
+ return -EINVAL;
}
l = strlen(policy_modes[mode]);
diff --git a/mm/mmap.c b/mm/mmap.c
index 9adee9f..ae18a48 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1356,9 +1356,8 @@
} else if ((flags & MAP_POPULATE) && !(flags & MAP_NONBLOCK))
make_pages_present(addr, addr + len);
- if (file && uprobe_mmap(vma))
- /* matching probes but cannot insert */
- goto unmap_and_free_vma;
+ if (file)
+ uprobe_mmap(vma);
return addr;
diff --git a/mm/slab.c b/mm/slab.c
index f8b0d53..811af03 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -3260,6 +3260,7 @@
/* cache_grow can reenable interrupts, then ac could change. */
ac = cpu_cache_get(cachep);
+ node = numa_mem_id();
/* no objects in sight? abort */
if (!x && (ac->avail == 0 || force_refill))
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 56f1823..ccc2487 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -278,8 +278,8 @@
if (err < 0)
goto free;
- dev->tty_dev = tty_register_device(rfcomm_tty_driver, dev->id, NULL);
-
+ dev->tty_dev = tty_port_register_device(&dev->port, rfcomm_tty_driver,
+ dev->id, NULL);
if (IS_ERR(dev->tty_dev)) {
err = PTR_ERR(dev->tty_dev);
list_del(&dev->list);
@@ -705,9 +705,9 @@
break;
}
- tty_unlock();
+ tty_unlock(tty);
schedule();
- tty_lock();
+ tty_lock(tty);
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&dev->wait, &wait);
@@ -861,7 +861,7 @@
static void rfcomm_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
{
- struct ktermios *new = 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/core/netpoll.c b/net/core/netpoll.c
index 346b1eb..e4ba3e7 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -168,24 +168,16 @@
struct napi_struct *napi;
int budget = 16;
- WARN_ON_ONCE(!irqs_disabled());
-
list_for_each_entry(napi, &dev->napi_list, dev_list) {
- local_irq_enable();
if (napi->poll_owner != smp_processor_id() &&
spin_trylock(&napi->poll_lock)) {
- rcu_read_lock_bh();
budget = poll_one_napi(rcu_dereference_bh(dev->npinfo),
napi, budget);
- rcu_read_unlock_bh();
spin_unlock(&napi->poll_lock);
- if (!budget) {
- local_irq_disable();
+ if (!budget)
break;
- }
}
- local_irq_disable();
}
}
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 8eec8f4..ebdf06f 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -124,6 +124,8 @@
static struct kmem_cache *mrt_cachep __read_mostly;
static struct mr_table *ipmr_new_table(struct net *net, u32 id);
+static void ipmr_free_table(struct mr_table *mrt);
+
static int ip_mr_forward(struct net *net, struct mr_table *mrt,
struct sk_buff *skb, struct mfc_cache *cache,
int local);
@@ -131,6 +133,7 @@
struct sk_buff *pkt, vifi_t vifi, int assert);
static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
struct mfc_cache *c, struct rtmsg *rtm);
+static void mroute_clean_tables(struct mr_table *mrt);
static void ipmr_expire_process(unsigned long arg);
#ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES
@@ -271,7 +274,7 @@
list_for_each_entry_safe(mrt, next, &net->ipv4.mr_tables, list) {
list_del(&mrt->list);
- kfree(mrt);
+ ipmr_free_table(mrt);
}
fib_rules_unregister(net->ipv4.mr_rules_ops);
}
@@ -299,7 +302,7 @@
static void __net_exit ipmr_rules_exit(struct net *net)
{
- kfree(net->ipv4.mrt);
+ ipmr_free_table(net->ipv4.mrt);
}
#endif
@@ -336,6 +339,13 @@
return mrt;
}
+static void ipmr_free_table(struct mr_table *mrt)
+{
+ del_timer_sync(&mrt->ipmr_expire_timer);
+ mroute_clean_tables(mrt);
+ kfree(mrt);
+}
+
/* Service routines creating virtual interfaces: DVMRP tunnels and PIMREG */
static void ipmr_del_tunnel(struct net_device *dev, struct vifctl *v)
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c
index 4ad9cf1..9c87cde 100644
--- a/net/ipv4/netfilter/nf_nat_sip.c
+++ b/net/ipv4/netfilter/nf_nat_sip.c
@@ -502,7 +502,10 @@
ret = nf_ct_expect_related(rtcp_exp);
if (ret == 0)
break;
- else if (ret != -EBUSY) {
+ else if (ret == -EBUSY) {
+ nf_ct_unexpect_related(rtp_exp);
+ continue;
+ } else if (ret < 0) {
nf_ct_unexpect_related(rtp_exp);
port = 0;
break;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index fd9ecb5..82cf2a7 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -934,12 +934,14 @@
if (mtu < ip_rt_min_pmtu)
mtu = ip_rt_min_pmtu;
+ rcu_read_lock();
if (fib_lookup(dev_net(rt->dst.dev), fl4, &res) == 0) {
struct fib_nh *nh = &FIB_RES_NH(res);
update_or_create_fnhe(nh, fl4->daddr, 0, mtu,
jiffies + ip_rt_mtu_expires);
}
+ rcu_read_unlock();
return mtu;
}
@@ -956,7 +958,7 @@
dst->obsolete = DST_OBSOLETE_KILL;
} else {
rt->rt_pmtu = mtu;
- dst_set_expires(&rt->dst, ip_rt_mtu_expires);
+ rt->dst.expires = max(1UL, jiffies + ip_rt_mtu_expires);
}
}
@@ -1263,7 +1265,7 @@
{
struct rtable *rt = (struct rtable *) dst;
- if (dst->flags & DST_NOCACHE) {
+ if (!list_empty(&rt->rt_uncached)) {
spin_lock_bh(&rt_uncached_lock);
list_del(&rt->rt_uncached);
spin_unlock_bh(&rt_uncached_lock);
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 85308b9..6e38c6c 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -2926,13 +2926,14 @@
* tcp_xmit_retransmit_queue().
*/
static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked,
- int newly_acked_sacked, bool is_dupack,
+ int prior_sacked, bool is_dupack,
int flag)
{
struct inet_connection_sock *icsk = inet_csk(sk);
struct tcp_sock *tp = tcp_sk(sk);
int do_lost = is_dupack || ((flag & FLAG_DATA_SACKED) &&
(tcp_fackets_out(tp) > tp->reordering));
+ int newly_acked_sacked = 0;
int fast_rexmit = 0;
if (WARN_ON(!tp->packets_out && tp->sacked_out))
@@ -2992,6 +2993,7 @@
tcp_add_reno_sack(sk);
} else
do_lost = tcp_try_undo_partial(sk, pkts_acked);
+ newly_acked_sacked = pkts_acked + tp->sacked_out - prior_sacked;
break;
case TCP_CA_Loss:
if (flag & FLAG_DATA_ACKED)
@@ -3013,6 +3015,7 @@
if (is_dupack)
tcp_add_reno_sack(sk);
}
+ newly_acked_sacked = pkts_acked + tp->sacked_out - prior_sacked;
if (icsk->icsk_ca_state <= TCP_CA_Disorder)
tcp_try_undo_dsack(sk);
@@ -3590,7 +3593,6 @@
int prior_packets;
int prior_sacked = tp->sacked_out;
int pkts_acked = 0;
- int newly_acked_sacked = 0;
bool frto_cwnd = false;
/* If the ack is older than previous acks
@@ -3666,8 +3668,6 @@
flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una);
pkts_acked = prior_packets - tp->packets_out;
- newly_acked_sacked = (prior_packets - prior_sacked) -
- (tp->packets_out - tp->sacked_out);
if (tp->frto_counter)
frto_cwnd = tcp_process_frto(sk, flag);
@@ -3681,7 +3681,7 @@
tcp_may_raise_cwnd(sk, flag))
tcp_cong_avoid(sk, ack, prior_in_flight);
is_dupack = !(flag & (FLAG_SND_UNA_ADVANCED | FLAG_NOT_DUP));
- tcp_fastretrans_alert(sk, pkts_acked, newly_acked_sacked,
+ tcp_fastretrans_alert(sk, pkts_acked, prior_sacked,
is_dupack, flag);
} else {
if ((flag & FLAG_DATA_ACKED) && !frto_cwnd)
@@ -3698,7 +3698,7 @@
no_queue:
/* If data was DSACKed, see if we can undo a cwnd reduction. */
if (flag & FLAG_DSACKING_ACK)
- tcp_fastretrans_alert(sk, pkts_acked, newly_acked_sacked,
+ tcp_fastretrans_alert(sk, pkts_acked, prior_sacked,
is_dupack, flag);
/* If this ack opens up a zero window, clear backoff. It was
* being used to time the probes, and is probably far higher than
@@ -3718,8 +3718,7 @@
*/
if (TCP_SKB_CB(skb)->sacked) {
flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una);
- newly_acked_sacked = tp->sacked_out - prior_sacked;
- tcp_fastretrans_alert(sk, pkts_acked, newly_acked_sacked,
+ tcp_fastretrans_alert(sk, pkts_acked, prior_sacked,
is_dupack, flag);
}
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 6dc7fd3..282f372 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -167,8 +167,6 @@
struct esp_data *esp = x->data;
/* skb is pure payload to encrypt */
- err = -ENOMEM;
-
aead = esp->aead;
alen = crypto_aead_authsize(aead);
@@ -203,8 +201,10 @@
}
tmp = esp_alloc_tmp(aead, nfrags + sglists, seqhilen);
- if (!tmp)
+ if (!tmp) {
+ err = -ENOMEM;
goto error;
+ }
seqhi = esp_tmp_seqhi(tmp);
iv = esp_tmp_iv(aead, tmp, seqhilen);
diff --git a/net/irda/ircomm/ircomm_param.c b/net/irda/ircomm/ircomm_param.c
index 8b915f3..3089391 100644
--- a/net/irda/ircomm/ircomm_param.c
+++ b/net/irda/ircomm/ircomm_param.c
@@ -99,7 +99,6 @@
*/
int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush)
{
- struct tty_struct *tty;
unsigned long flags;
struct sk_buff *skb;
int count;
@@ -109,10 +108,6 @@
IRDA_ASSERT(self != NULL, return -1;);
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
- tty = self->tty;
- if (!tty)
- return 0;
-
/* Make sure we don't send parameters for raw mode */
if (self->service_type == IRCOMM_3_WIRE_RAW)
return 0;
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
index 6b9d5a0..95a3a7a 100644
--- a/net/irda/ircomm/ircomm_tty.c
+++ b/net/irda/ircomm/ircomm_tty.c
@@ -52,6 +52,8 @@
#include <net/irda/ircomm_tty_attach.h>
#include <net/irda/ircomm_tty.h>
+static int ircomm_tty_install(struct tty_driver *driver,
+ struct tty_struct *tty);
static int ircomm_tty_open(struct tty_struct *tty, struct file *filp);
static void ircomm_tty_close(struct tty_struct * tty, struct file *filp);
static int ircomm_tty_write(struct tty_struct * tty,
@@ -82,6 +84,7 @@
static hashbin_t *ircomm_tty = NULL;
static const struct tty_operations ops = {
+ .install = ircomm_tty_install,
.open = ircomm_tty_open,
.close = ircomm_tty_close,
.write = ircomm_tty_write,
@@ -104,6 +107,35 @@
#endif /* CONFIG_PROC_FS */
};
+static void ircomm_port_raise_dtr_rts(struct tty_port *port, int raise)
+{
+ struct ircomm_tty_cb *self = container_of(port, struct ircomm_tty_cb,
+ port);
+ /*
+ * Here, we use to lock those two guys, but as ircomm_param_request()
+ * does it itself, I don't see the point (and I see the deadlock).
+ * Jean II
+ */
+ if (raise)
+ self->settings.dte |= IRCOMM_RTS | IRCOMM_DTR;
+ else
+ self->settings.dte &= ~(IRCOMM_RTS | IRCOMM_DTR);
+
+ ircomm_param_request(self, IRCOMM_DTE, TRUE);
+}
+
+static int ircomm_port_carrier_raised(struct tty_port *port)
+{
+ struct ircomm_tty_cb *self = container_of(port, struct ircomm_tty_cb,
+ port);
+ return self->settings.dce & IRCOMM_CD;
+}
+
+static const struct tty_port_operations ircomm_port_ops = {
+ .dtr_rts = ircomm_port_raise_dtr_rts,
+ .carrier_raised = ircomm_port_carrier_raised,
+};
+
/*
* Function ircomm_tty_init()
*
@@ -194,7 +226,7 @@
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
/* Check if already open */
- if (test_and_set_bit(ASYNC_B_INITIALIZED, &self->flags)) {
+ if (test_and_set_bit(ASYNCB_INITIALIZED, &self->port.flags)) {
IRDA_DEBUG(2, "%s(), already open so break out!\n", __func__ );
return 0;
}
@@ -231,7 +263,7 @@
return 0;
err:
- clear_bit(ASYNC_B_INITIALIZED, &self->flags);
+ clear_bit(ASYNCB_INITIALIZED, &self->port.flags);
return ret;
}
@@ -242,72 +274,62 @@
*
*/
static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
- struct file *filp)
+ struct tty_struct *tty, struct file *filp)
{
+ struct tty_port *port = &self->port;
DECLARE_WAITQUEUE(wait, current);
int retval;
int do_clocal = 0, extra_count = 0;
unsigned long flags;
- struct tty_struct *tty;
IRDA_DEBUG(2, "%s()\n", __func__ );
- tty = self->tty;
-
/*
* 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 || tty->flags & (1 << TTY_IO_ERROR)){
/* nonblock mode is set or port is not enabled */
- self->flags |= ASYNC_NORMAL_ACTIVE;
+ port->flags |= ASYNC_NORMAL_ACTIVE;
IRDA_DEBUG(1, "%s(), O_NONBLOCK requested!\n", __func__ );
return 0;
}
- if (tty->termios->c_cflag & CLOCAL) {
+ if (tty->termios.c_cflag & CLOCAL) {
IRDA_DEBUG(1, "%s(), doing CLOCAL!\n", __func__ );
do_clocal = 1;
}
/* Wait for carrier detect and the line to become
* free (i.e., not in use by the callout). While we are in
- * this loop, self->open_count is dropped by one, so that
+ * this loop, port->count is dropped by one, so that
* mgsl_close() knows when to free things. We restore it upon
* exit, either normal or abnormal.
*/
retval = 0;
- add_wait_queue(&self->open_wait, &wait);
+ add_wait_queue(&port->open_wait, &wait);
IRDA_DEBUG(2, "%s(%d):block_til_ready before block on %s open_count=%d\n",
- __FILE__,__LINE__, tty->driver->name, self->open_count );
+ __FILE__, __LINE__, tty->driver->name, port->count);
- /* As far as I can see, we protect open_count - Jean II */
- spin_lock_irqsave(&self->spinlock, flags);
+ spin_lock_irqsave(&port->lock, flags);
if (!tty_hung_up_p(filp)) {
extra_count = 1;
- self->open_count--;
+ port->count--;
}
- spin_unlock_irqrestore(&self->spinlock, flags);
- self->blocked_open++;
+ spin_unlock_irqrestore(&port->lock, flags);
+ port->blocked_open++;
while (1) {
- if (tty->termios->c_cflag & CBAUD) {
- /* Here, we use to lock those two guys, but
- * as ircomm_param_request() does it itself,
- * I don't see the point (and I see the deadlock).
- * Jean II */
- self->settings.dte |= IRCOMM_RTS + IRCOMM_DTR;
-
- ircomm_param_request(self, IRCOMM_DTE, TRUE);
- }
+ if (tty->termios.c_cflag & CBAUD)
+ tty_port_raise_dtr_rts(port);
current->state = TASK_INTERRUPTIBLE;
if (tty_hung_up_p(filp) ||
- !test_bit(ASYNC_B_INITIALIZED, &self->flags)) {
- retval = (self->flags & ASYNC_HUP_NOTIFY) ?
+ !test_bit(ASYNCB_INITIALIZED, &port->flags)) {
+ retval = (port->flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS;
break;
}
@@ -317,8 +339,8 @@
* specified, we cannot return before the IrCOMM link is
* ready
*/
- if (!test_bit(ASYNC_B_CLOSING, &self->flags) &&
- (do_clocal || (self->settings.dce & IRCOMM_CD)) &&
+ if (!test_bit(ASYNCB_CLOSING, &port->flags) &&
+ (do_clocal || tty_port_carrier_raised(port)) &&
self->state == IRCOMM_TTY_READY)
{
break;
@@ -330,46 +352,36 @@
}
IRDA_DEBUG(1, "%s(%d):block_til_ready blocking on %s open_count=%d\n",
- __FILE__,__LINE__, tty->driver->name, self->open_count );
+ __FILE__, __LINE__, tty->driver->name, port->count);
schedule();
}
__set_current_state(TASK_RUNNING);
- remove_wait_queue(&self->open_wait, &wait);
+ remove_wait_queue(&port->open_wait, &wait);
if (extra_count) {
/* ++ is not atomic, so this should be protected - Jean II */
- spin_lock_irqsave(&self->spinlock, flags);
- self->open_count++;
- spin_unlock_irqrestore(&self->spinlock, flags);
+ spin_lock_irqsave(&port->lock, flags);
+ port->count++;
+ spin_unlock_irqrestore(&port->lock, flags);
}
- self->blocked_open--;
+ port->blocked_open--;
IRDA_DEBUG(1, "%s(%d):block_til_ready after blocking on %s open_count=%d\n",
- __FILE__,__LINE__, tty->driver->name, self->open_count);
+ __FILE__, __LINE__, tty->driver->name, port->count);
if (!retval)
- self->flags |= ASYNC_NORMAL_ACTIVE;
+ port->flags |= ASYNC_NORMAL_ACTIVE;
return retval;
}
-/*
- * Function ircomm_tty_open (tty, filp)
- *
- * This routine is called when a particular tty device is opened. This
- * routine is mandatory; if this routine is not filled in, the attempted
- * open will fail with ENODEV.
- */
-static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
+
+static int ircomm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
{
struct ircomm_tty_cb *self;
unsigned int line = tty->index;
- unsigned long flags;
- int ret;
-
- IRDA_DEBUG(2, "%s()\n", __func__ );
/* Check if instance already exists */
self = hashbin_lock_find(ircomm_tty, line, NULL);
@@ -381,6 +393,8 @@
return -ENOMEM;
}
+ tty_port_init(&self->port);
+ self->port.ops = &ircomm_port_ops;
self->magic = IRCOMM_TTY_MAGIC;
self->flow = FLOW_STOP;
@@ -388,13 +402,9 @@
INIT_WORK(&self->tqueue, ircomm_tty_do_softint);
self->max_header_size = IRCOMM_TTY_HDR_UNINITIALISED;
self->max_data_size = IRCOMM_TTY_DATA_UNINITIALISED;
- self->close_delay = 5*HZ/10;
- self->closing_wait = 30*HZ;
/* Init some important stuff */
init_timer(&self->watchdog_timer);
- init_waitqueue_head(&self->open_wait);
- init_waitqueue_head(&self->close_wait);
spin_lock_init(&self->spinlock);
/*
@@ -404,31 +414,48 @@
*
* Note this is completely usafe and doesn't work properly
*/
- tty->termios->c_iflag = 0;
- tty->termios->c_oflag = 0;
+ tty->termios.c_iflag = 0;
+ tty->termios.c_oflag = 0;
/* Insert into hash */
hashbin_insert(ircomm_tty, (irda_queue_t *) self, line, NULL);
}
- /* ++ is not atomic, so this should be protected - Jean II */
- spin_lock_irqsave(&self->spinlock, flags);
- self->open_count++;
- tty->driver_data = self;
- self->tty = tty;
- spin_unlock_irqrestore(&self->spinlock, flags);
+ return tty_port_install(&self->port, driver, tty);
+}
+
+/*
+ * Function ircomm_tty_open (tty, filp)
+ *
+ * This routine is called when a particular tty device is opened. This
+ * routine is mandatory; if this routine is not filled in, the attempted
+ * open will fail with ENODEV.
+ */
+static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
+{
+ struct ircomm_tty_cb *self = tty->driver_data;
+ unsigned long flags;
+ int ret;
+
+ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ /* ++ is not atomic, so this should be protected - Jean II */
+ spin_lock_irqsave(&self->port.lock, flags);
+ self->port.count++;
+ spin_unlock_irqrestore(&self->port.lock, flags);
+ tty_port_tty_set(&self->port, tty);
IRDA_DEBUG(1, "%s(), %s%d, count = %d\n", __func__ , tty->driver->name,
- self->line, self->open_count);
+ self->line, self->port.count);
/* Not really used by us, but lets do it anyway */
- self->tty->low_latency = (self->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+ tty->low_latency = (self->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
/*
* If the port is the middle of closing, bail out now
*/
if (tty_hung_up_p(filp) ||
- test_bit(ASYNC_B_CLOSING, &self->flags)) {
+ test_bit(ASYNCB_CLOSING, &self->port.flags)) {
/* Hm, why are we blocking on ASYNC_CLOSING if we
* do return -EAGAIN/-ERESTARTSYS below anyway?
@@ -438,14 +465,15 @@
* probably better sleep uninterruptible?
*/
- if (wait_event_interruptible(self->close_wait, !test_bit(ASYNC_B_CLOSING, &self->flags))) {
+ if (wait_event_interruptible(self->port.close_wait,
+ !test_bit(ASYNCB_CLOSING, &self->port.flags))) {
IRDA_WARNING("%s - got signal while blocking on ASYNC_CLOSING!\n",
__func__);
return -ERESTARTSYS;
}
#ifdef SERIAL_DO_RESTART
- return (self->flags & ASYNC_HUP_NOTIFY) ?
+ return (self->port.flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS;
#else
return -EAGAIN;
@@ -453,7 +481,7 @@
}
/* Check if this is a "normal" ircomm device, or an irlpt device */
- if (line < 0x10) {
+ if (self->line < 0x10) {
self->service_type = IRCOMM_3_WIRE | IRCOMM_9_WIRE;
self->settings.service_type = IRCOMM_9_WIRE; /* 9 wire as default */
/* Jan Kiszka -> add DSR/RI -> Conform to IrCOMM spec */
@@ -469,7 +497,7 @@
if (ret)
return ret;
- ret = ircomm_tty_block_til_ready(self, filp);
+ ret = ircomm_tty_block_til_ready(self, tty, filp);
if (ret) {
IRDA_DEBUG(2,
"%s(), returning after block_til_ready with %d\n", __func__ ,
@@ -489,81 +517,22 @@
static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
- unsigned long flags;
+ struct tty_port *port = &self->port;
IRDA_DEBUG(0, "%s()\n", __func__ );
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
- spin_lock_irqsave(&self->spinlock, flags);
-
- if (tty_hung_up_p(filp)) {
- spin_unlock_irqrestore(&self->spinlock, flags);
-
- IRDA_DEBUG(0, "%s(), returning 1\n", __func__ );
+ if (tty_port_close_start(port, tty, filp) == 0)
return;
- }
-
- if ((tty->count == 1) && (self->open_count != 1)) {
- /*
- * Uh, oh. tty->count is 1, which means that the tty
- * structure will be freed. state->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.
- */
- IRDA_DEBUG(0, "%s(), bad serial port count; "
- "tty->count is 1, state->count is %d\n", __func__ ,
- self->open_count);
- self->open_count = 1;
- }
-
- if (--self->open_count < 0) {
- IRDA_ERROR("%s(), bad serial port count for ttys%d: %d\n",
- __func__, self->line, self->open_count);
- self->open_count = 0;
- }
- if (self->open_count) {
- spin_unlock_irqrestore(&self->spinlock, flags);
-
- IRDA_DEBUG(0, "%s(), open count > 0\n", __func__ );
- return;
- }
-
- /* Hum... Should be test_and_set_bit ??? - Jean II */
- set_bit(ASYNC_B_CLOSING, &self->flags);
-
- /* We need to unlock here (we were unlocking at the end of this
- * function), because tty_wait_until_sent() may schedule.
- * I don't know if the rest should be protected somehow,
- * so someone should check. - Jean II */
- spin_unlock_irqrestore(&self->spinlock, 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;
- if (self->closing_wait != ASYNC_CLOSING_WAIT_NONE)
- tty_wait_until_sent_from_close(tty, self->closing_wait);
ircomm_tty_shutdown(self);
tty_driver_flush_buffer(tty);
- tty_ldisc_flush(tty);
- tty->closing = 0;
- self->tty = NULL;
-
- if (self->blocked_open) {
- if (self->close_delay)
- schedule_timeout_interruptible(self->close_delay);
- wake_up_interruptible(&self->open_wait);
- }
-
- self->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
- wake_up_interruptible(&self->close_wait);
+ tty_port_close_end(port, tty);
+ tty_port_tty_set(port, NULL);
}
/*
@@ -606,7 +575,7 @@
if (!self || self->magic != IRCOMM_TTY_MAGIC)
return;
- tty = self->tty;
+ tty = tty_port_tty_get(&self->port);
if (!tty)
return;
@@ -627,7 +596,7 @@
}
if (tty->hw_stopped)
- return;
+ goto put;
/* Unlink transmit buffer */
spin_lock_irqsave(&self->spinlock, flags);
@@ -646,6 +615,8 @@
/* Check if user (still) wants to be waken up */
tty_wakeup(tty);
+put:
+ tty_kref_put(tty);
}
/*
@@ -880,7 +851,7 @@
ircomm_tty_send_xchar(tty, STOP_CHAR(tty));
/* Hardware flow control? */
- if (tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios.c_cflag & CRTSCTS) {
self->settings.dte &= ~IRCOMM_RTS;
self->settings.dte |= IRCOMM_DELTA_RTS;
@@ -912,7 +883,7 @@
}
/* Using hardware flow control? */
- if (tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios.c_cflag & CRTSCTS) {
self->settings.dte |= (IRCOMM_RTS|IRCOMM_DELTA_RTS);
ircomm_param_request(self, IRCOMM_DTE, TRUE);
@@ -955,7 +926,7 @@
IRDA_DEBUG(0, "%s()\n", __func__ );
- if (!test_and_clear_bit(ASYNC_B_INITIALIZED, &self->flags))
+ if (!test_and_clear_bit(ASYNCB_INITIALIZED, &self->port.flags))
return;
ircomm_tty_detach_cable(self);
@@ -994,6 +965,7 @@
static void ircomm_tty_hangup(struct tty_struct *tty)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+ struct tty_port *port = &self->port;
unsigned long flags;
IRDA_DEBUG(0, "%s()\n", __func__ );
@@ -1004,14 +976,17 @@
/* ircomm_tty_flush_buffer(tty); */
ircomm_tty_shutdown(self);
- /* I guess we need to lock here - Jean II */
- spin_lock_irqsave(&self->spinlock, flags);
- self->flags &= ~ASYNC_NORMAL_ACTIVE;
- self->tty = NULL;
- self->open_count = 0;
- spin_unlock_irqrestore(&self->spinlock, flags);
+ spin_lock_irqsave(&port->lock, flags);
+ port->flags &= ~ASYNC_NORMAL_ACTIVE;
+ if (port->tty) {
+ set_bit(TTY_IO_ERROR, &port->tty->flags);
+ tty_kref_put(port->tty);
+ }
+ port->tty = NULL;
+ port->count = 0;
+ spin_unlock_irqrestore(&port->lock, flags);
- wake_up_interruptible(&self->open_wait);
+ wake_up_interruptible(&port->open_wait);
}
/*
@@ -1071,20 +1046,20 @@
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
- tty = self->tty;
+ tty = tty_port_tty_get(&self->port);
status = self->settings.dce;
if (status & IRCOMM_DCE_DELTA_ANY) {
/*wake_up_interruptible(&self->delta_msr_wait);*/
}
- if ((self->flags & ASYNC_CHECK_CD) && (status & IRCOMM_DELTA_CD)) {
+ if ((self->port.flags & ASYNC_CHECK_CD) && (status & IRCOMM_DELTA_CD)) {
IRDA_DEBUG(2,
"%s(), ircomm%d CD now %s...\n", __func__ , self->line,
(status & IRCOMM_CD) ? "on" : "off");
if (status & IRCOMM_CD) {
- wake_up_interruptible(&self->open_wait);
+ wake_up_interruptible(&self->port.open_wait);
} else {
IRDA_DEBUG(2,
"%s(), Doing serial hangup..\n", __func__ );
@@ -1092,10 +1067,10 @@
tty_hangup(tty);
/* Hangup will remote the tty, so better break out */
- return;
+ goto put;
}
}
- if (self->flags & ASYNC_CTS_FLOW) {
+ if (tty && tty_port_cts_enabled(&self->port)) {
if (tty->hw_stopped) {
if (status & IRCOMM_CTS) {
IRDA_DEBUG(2,
@@ -1103,10 +1078,10 @@
tty->hw_stopped = 0;
/* Wake up processes blocked on open */
- wake_up_interruptible(&self->open_wait);
+ wake_up_interruptible(&self->port.open_wait);
schedule_work(&self->tqueue);
- return;
+ goto put;
}
} else {
if (!(status & IRCOMM_CTS)) {
@@ -1116,6 +1091,8 @@
}
}
}
+put:
+ tty_kref_put(tty);
}
/*
@@ -1128,6 +1105,7 @@
struct sk_buff *skb)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+ struct tty_struct *tty;
IRDA_DEBUG(2, "%s()\n", __func__ );
@@ -1135,7 +1113,8 @@
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
IRDA_ASSERT(skb != NULL, return -1;);
- if (!self->tty) {
+ tty = tty_port_tty_get(&self->port);
+ if (!tty) {
IRDA_DEBUG(0, "%s(), no tty!\n", __func__ );
return 0;
}
@@ -1146,7 +1125,7 @@
* Devices like WinCE can do this, and since they don't send any
* params, we can just as well declare the hardware for running.
*/
- if (self->tty->hw_stopped && (self->flow == FLOW_START)) {
+ if (tty->hw_stopped && (self->flow == FLOW_START)) {
IRDA_DEBUG(0, "%s(), polling for line settings!\n", __func__ );
ircomm_param_request(self, IRCOMM_POLL, TRUE);
@@ -1159,8 +1138,9 @@
* Use flip buffer functions since the code may be called from interrupt
* context
*/
- tty_insert_flip_string(self->tty, skb->data, skb->len);
- tty_flip_buffer_push(self->tty);
+ tty_insert_flip_string(tty, skb->data, skb->len);
+ tty_flip_buffer_push(tty);
+ tty_kref_put(tty);
/* No need to kfree_skb - see ircomm_ttp_data_indication() */
@@ -1211,12 +1191,13 @@
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
- tty = self->tty;
+ tty = tty_port_tty_get(&self->port);
switch (cmd) {
case FLOW_START:
IRDA_DEBUG(2, "%s(), hw start!\n", __func__ );
- tty->hw_stopped = 0;
+ if (tty)
+ tty->hw_stopped = 0;
/* ircomm_tty_do_softint will take care of the rest */
schedule_work(&self->tqueue);
@@ -1224,15 +1205,19 @@
default: /* If we get here, something is very wrong, better stop */
case FLOW_STOP:
IRDA_DEBUG(2, "%s(), hw stopped!\n", __func__ );
- tty->hw_stopped = 1;
+ if (tty)
+ tty->hw_stopped = 1;
break;
}
+
+ tty_kref_put(tty);
self->flow = cmd;
}
#ifdef CONFIG_PROC_FS
static void ircomm_tty_line_info(struct ircomm_tty_cb *self, struct seq_file *m)
{
+ struct tty_struct *tty;
char sep;
seq_printf(m, "State: %s\n", ircomm_tty_state[self->state]);
@@ -1328,40 +1313,43 @@
seq_puts(m, "Flags:");
sep = ' ';
- if (self->flags & ASYNC_CTS_FLOW) {
+ if (tty_port_cts_enabled(&self->port)) {
seq_printf(m, "%cASYNC_CTS_FLOW", sep);
sep = '|';
}
- if (self->flags & ASYNC_CHECK_CD) {
+ if (self->port.flags & ASYNC_CHECK_CD) {
seq_printf(m, "%cASYNC_CHECK_CD", sep);
sep = '|';
}
- if (self->flags & ASYNC_INITIALIZED) {
+ if (self->port.flags & ASYNC_INITIALIZED) {
seq_printf(m, "%cASYNC_INITIALIZED", sep);
sep = '|';
}
- if (self->flags & ASYNC_LOW_LATENCY) {
+ if (self->port.flags & ASYNC_LOW_LATENCY) {
seq_printf(m, "%cASYNC_LOW_LATENCY", sep);
sep = '|';
}
- if (self->flags & ASYNC_CLOSING) {
+ if (self->port.flags & ASYNC_CLOSING) {
seq_printf(m, "%cASYNC_CLOSING", sep);
sep = '|';
}
- if (self->flags & ASYNC_NORMAL_ACTIVE) {
+ if (self->port.flags & ASYNC_NORMAL_ACTIVE) {
seq_printf(m, "%cASYNC_NORMAL_ACTIVE", sep);
sep = '|';
}
seq_putc(m, '\n');
seq_printf(m, "Role: %s\n", self->client ? "client" : "server");
- seq_printf(m, "Open count: %d\n", self->open_count);
+ seq_printf(m, "Open count: %d\n", self->port.count);
seq_printf(m, "Max data size: %d\n", self->max_data_size);
seq_printf(m, "Max header size: %d\n", self->max_header_size);
- if (self->tty)
+ tty = tty_port_tty_get(&self->port);
+ if (tty) {
seq_printf(m, "Hardware: %s\n",
- self->tty->hw_stopped ? "Stopped" : "Running");
+ tty->hw_stopped ? "Stopped" : "Running");
+ tty_kref_put(tty);
+ }
}
static int ircomm_tty_proc_show(struct seq_file *m, void *v)
diff --git a/net/irda/ircomm/ircomm_tty_attach.c b/net/irda/ircomm/ircomm_tty_attach.c
index b65d66e..edab393 100644
--- a/net/irda/ircomm/ircomm_tty_attach.c
+++ b/net/irda/ircomm/ircomm_tty_attach.c
@@ -130,6 +130,8 @@
*/
int ircomm_tty_attach_cable(struct ircomm_tty_cb *self)
{
+ struct tty_struct *tty;
+
IRDA_DEBUG(0, "%s()\n", __func__ );
IRDA_ASSERT(self != NULL, return -1;);
@@ -142,7 +144,11 @@
}
/* Make sure nobody tries to write before the link is up */
- self->tty->hw_stopped = 1;
+ tty = tty_port_tty_get(&self->port);
+ if (tty) {
+ tty->hw_stopped = 1;
+ tty_kref_put(tty);
+ }
ircomm_tty_ias_register(self);
@@ -398,23 +404,26 @@
struct sk_buff *skb)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+ struct tty_struct *tty;
IRDA_DEBUG(2, "%s()\n", __func__ );
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
- if (!self->tty)
+ tty = tty_port_tty_get(&self->port);
+ if (!tty)
return;
/* This will stop control data transfers */
self->flow = FLOW_STOP;
/* Stop data transfers */
- self->tty->hw_stopped = 1;
+ tty->hw_stopped = 1;
ircomm_tty_do_event(self, IRCOMM_TTY_DISCONNECT_INDICATION, NULL,
NULL);
+ tty_kref_put(tty);
}
/*
@@ -550,12 +559,15 @@
*/
void ircomm_tty_link_established(struct ircomm_tty_cb *self)
{
+ struct tty_struct *tty;
+
IRDA_DEBUG(2, "%s()\n", __func__ );
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
- if (!self->tty)
+ tty = tty_port_tty_get(&self->port);
+ if (!tty)
return;
del_timer(&self->watchdog_timer);
@@ -566,19 +578,22 @@
* will have to wait for the peer device (DCE) to raise the CTS
* line.
*/
- if ((self->flags & ASYNC_CTS_FLOW) && ((self->settings.dce & IRCOMM_CTS) == 0)) {
+ if (tty_port_cts_enabled(&self->port) &&
+ ((self->settings.dce & IRCOMM_CTS) == 0)) {
IRDA_DEBUG(0, "%s(), waiting for CTS ...\n", __func__ );
- return;
+ goto put;
} else {
IRDA_DEBUG(1, "%s(), starting hardware!\n", __func__ );
- self->tty->hw_stopped = 0;
+ tty->hw_stopped = 0;
/* Wake up processes blocked on open */
- wake_up_interruptible(&self->open_wait);
+ wake_up_interruptible(&self->port.open_wait);
}
schedule_work(&self->tqueue);
+put:
+ tty_kref_put(tty);
}
/*
@@ -977,14 +992,17 @@
ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH);
ircomm_tty_start_watchdog_timer(self, 3*HZ);
- if (self->flags & ASYNC_CHECK_CD) {
+ if (self->port.flags & ASYNC_CHECK_CD) {
/* Drop carrier */
self->settings.dce = IRCOMM_DELTA_CD;
ircomm_tty_check_modem_status(self);
} else {
+ struct tty_struct *tty = tty_port_tty_get(&self->port);
IRDA_DEBUG(0, "%s(), hanging up!\n", __func__ );
- if (self->tty)
- tty_hangup(self->tty);
+ if (tty) {
+ tty_hangup(tty);
+ tty_kref_put(tty);
+ }
}
break;
default:
diff --git a/net/irda/ircomm/ircomm_tty_ioctl.c b/net/irda/ircomm/ircomm_tty_ioctl.c
index d0667d6..b343f50 100644
--- a/net/irda/ircomm/ircomm_tty_ioctl.c
+++ b/net/irda/ircomm/ircomm_tty_ioctl.c
@@ -52,17 +52,18 @@
* Change speed of the driver. If the remote device is a DCE, then this
* should make it change the speed of its serial port
*/
-static void ircomm_tty_change_speed(struct ircomm_tty_cb *self)
+static void ircomm_tty_change_speed(struct ircomm_tty_cb *self,
+ struct tty_struct *tty)
{
unsigned int cflag, cval;
int baud;
IRDA_DEBUG(2, "%s()\n", __func__ );
- if (!self->tty || !self->tty->termios || !self->ircomm)
+ if (!self->ircomm)
return;
- cflag = self->tty->termios->c_cflag;
+ cflag = tty->termios.c_cflag;
/* byte size and parity */
switch (cflag & CSIZE) {
@@ -81,7 +82,7 @@
cval |= IRCOMM_PARITY_EVEN;
/* Determine divisor based on baud rate */
- baud = tty_get_baud_rate(self->tty);
+ baud = tty_get_baud_rate(tty);
if (!baud)
baud = 9600; /* B0 transition handled in rs_set_termios */
@@ -90,19 +91,19 @@
/* CTS flow control flag and modem status interrupts */
if (cflag & CRTSCTS) {
- self->flags |= ASYNC_CTS_FLOW;
+ self->port.flags |= ASYNC_CTS_FLOW;
self->settings.flow_control |= IRCOMM_RTS_CTS_IN;
/* This got me. Bummer. Jean II */
if (self->service_type == IRCOMM_3_WIRE_RAW)
IRDA_WARNING("%s(), enabling RTS/CTS on link that doesn't support it (3-wire-raw)\n", __func__);
} else {
- self->flags &= ~ASYNC_CTS_FLOW;
+ self->port.flags &= ~ASYNC_CTS_FLOW;
self->settings.flow_control &= ~IRCOMM_RTS_CTS_IN;
}
if (cflag & CLOCAL)
- self->flags &= ~ASYNC_CHECK_CD;
+ self->port.flags &= ~ASYNC_CHECK_CD;
else
- self->flags |= ASYNC_CHECK_CD;
+ self->port.flags |= ASYNC_CHECK_CD;
#if 0
/*
* Set up parity check flag
@@ -148,18 +149,18 @@
struct ktermios *old_termios)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
- unsigned int cflag = tty->termios->c_cflag;
+ unsigned int cflag = tty->termios.c_cflag;
IRDA_DEBUG(2, "%s()\n", __func__ );
if ((cflag == old_termios->c_cflag) &&
- (RELEVANT_IFLAG(tty->termios->c_iflag) ==
+ (RELEVANT_IFLAG(tty->termios.c_iflag) ==
RELEVANT_IFLAG(old_termios->c_iflag)))
{
return;
}
- ircomm_tty_change_speed(self);
+ ircomm_tty_change_speed(self, tty);
/* Handle transition to B0 status */
if ((old_termios->c_cflag & CBAUD) &&
@@ -172,7 +173,7 @@
if (!(old_termios->c_cflag & CBAUD) &&
(cflag & CBAUD)) {
self->settings.dte |= IRCOMM_DTR;
- if (!(tty->termios->c_cflag & CRTSCTS) ||
+ if (!(tty->termios.c_cflag & CRTSCTS) ||
!test_bit(TTY_THROTTLED, &tty->flags)) {
self->settings.dte |= IRCOMM_RTS;
}
@@ -181,7 +182,7 @@
/* Handle turning off CRTSCTS */
if ((old_termios->c_cflag & CRTSCTS) &&
- !(tty->termios->c_cflag & CRTSCTS))
+ !(tty->termios.c_cflag & CRTSCTS))
{
tty->hw_stopped = 0;
ircomm_tty_start(tty);
@@ -270,10 +271,10 @@
memset(&info, 0, sizeof(info));
info.line = self->line;
- info.flags = self->flags;
+ info.flags = self->port.flags;
info.baud_base = self->settings.data_rate;
- info.close_delay = self->close_delay;
- info.closing_wait = self->closing_wait;
+ info.close_delay = self->port.close_delay;
+ info.closing_wait = self->port.closing_wait;
/* For compatibility */
info.type = PORT_16550A;
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index 393355d..513cab0 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -1347,11 +1347,10 @@
/* Remove from tunnel list */
spin_lock_bh(&pn->l2tp_tunnel_list_lock);
list_del_rcu(&tunnel->list);
+ kfree_rcu(tunnel, rcu);
spin_unlock_bh(&pn->l2tp_tunnel_list_lock);
- synchronize_rcu();
atomic_dec(&l2tp_tunnel_count);
- kfree(tunnel);
}
/* Create a socket for the tunnel, if one isn't set up by
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
index a38ec6c..56d583e 100644
--- a/net/l2tp/l2tp_core.h
+++ b/net/l2tp/l2tp_core.h
@@ -163,6 +163,7 @@
struct l2tp_tunnel {
int magic; /* Should be L2TP_TUNNEL_MAGIC */
+ struct rcu_head rcu;
rwlock_t hlist_lock; /* protect session_hlist */
struct hlist_head session_hlist[L2TP_HASH_SIZE];
/* hashed list of sessions,
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index acf712f..c5e8c9c 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1811,37 +1811,31 @@
meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr,
sdata, NULL, NULL);
} else {
- int is_mesh_mcast = 1;
- const u8 *mesh_da;
+ /* DS -> MBSS (802.11-2012 13.11.3.3).
+ * For unicast with unknown forwarding information,
+ * destination might be in the MBSS or if that fails
+ * forwarded to another mesh gate. In either case
+ * resolution will be handled in ieee80211_xmit(), so
+ * leave the original DA. This also works for mcast */
+ const u8 *mesh_da = skb->data;
- if (is_multicast_ether_addr(skb->data))
- /* DA TA mSA AE:SA */
- mesh_da = skb->data;
- else {
- static const u8 bcast[ETH_ALEN] =
- { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
- if (mppath) {
- /* RA TA mDA mSA AE:DA SA */
- mesh_da = mppath->mpp;
- is_mesh_mcast = 0;
- } else if (mpath) {
- mesh_da = mpath->dst;
- is_mesh_mcast = 0;
- } else {
- /* DA TA mSA AE:SA */
- mesh_da = bcast;
- }
- }
+ if (mppath)
+ mesh_da = mppath->mpp;
+ else if (mpath)
+ mesh_da = mpath->dst;
+ rcu_read_unlock();
+
hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
mesh_da, sdata->vif.addr);
- rcu_read_unlock();
- if (is_mesh_mcast)
+ if (is_multicast_ether_addr(mesh_da))
+ /* DA TA mSA AE:SA */
meshhdrlen =
ieee80211_new_mesh_header(&mesh_hdr,
sdata,
skb->data + ETH_ALEN,
NULL);
else
+ /* RA TA mDA mSA AE:DA SA */
meshhdrlen =
ieee80211_new_mesh_header(&mesh_hdr,
sdata,
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 72bf32a..f51013c 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -1171,8 +1171,10 @@
goto out_err;
}
svc->stats.cpustats = alloc_percpu(struct ip_vs_cpu_stats);
- if (!svc->stats.cpustats)
+ if (!svc->stats.cpustats) {
+ ret = -ENOMEM;
goto out_err;
+ }
/* I'm the first user of the service */
atomic_set(&svc->usecnt, 0);
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index cf48755..2ceec64 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -249,12 +249,15 @@
{
struct nf_conn *ct = (void *)ul_conntrack;
struct net *net = nf_ct_net(ct);
+ struct nf_conntrack_ecache *ecache = nf_ct_ecache_find(ct);
+
+ BUG_ON(ecache == NULL);
if (nf_conntrack_event(IPCT_DESTROY, ct) < 0) {
/* bad luck, let's retry again */
- ct->timeout.expires = jiffies +
+ ecache->timeout.expires = jiffies +
(random32() % net->ct.sysctl_events_retry_timeout);
- add_timer(&ct->timeout);
+ add_timer(&ecache->timeout);
return;
}
/* we've got the event delivered, now it's dying */
@@ -268,6 +271,9 @@
void nf_ct_insert_dying_list(struct nf_conn *ct)
{
struct net *net = nf_ct_net(ct);
+ struct nf_conntrack_ecache *ecache = nf_ct_ecache_find(ct);
+
+ BUG_ON(ecache == NULL);
/* add this conntrack to the dying list */
spin_lock_bh(&nf_conntrack_lock);
@@ -275,10 +281,10 @@
&net->ct.dying);
spin_unlock_bh(&nf_conntrack_lock);
/* set a new timer to retry event delivery */
- setup_timer(&ct->timeout, death_by_event, (unsigned long)ct);
- ct->timeout.expires = jiffies +
+ setup_timer(&ecache->timeout, death_by_event, (unsigned long)ct);
+ ecache->timeout.expires = jiffies +
(random32() % net->ct.sysctl_events_retry_timeout);
- add_timer(&ct->timeout);
+ add_timer(&ecache->timeout);
}
EXPORT_SYMBOL_GPL(nf_ct_insert_dying_list);
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index da4fc37..9807f32 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -2790,7 +2790,8 @@
goto err_unreg_subsys;
}
- if (register_pernet_subsys(&ctnetlink_net_ops)) {
+ ret = register_pernet_subsys(&ctnetlink_net_ops);
+ if (ret < 0) {
pr_err("ctnetlink_init: cannot register pernet operations\n");
goto err_unreg_exp_subsys;
}
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 169ab59..14e2f39 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -480,7 +480,7 @@
}
if (indev && skb_mac_header_was_set(skb)) {
- if (nla_put_be32(inst->skb, NFULA_HWTYPE, htons(skb->dev->type)) ||
+ if (nla_put_be16(inst->skb, NFULA_HWTYPE, htons(skb->dev->type)) ||
nla_put_be16(inst->skb, NFULA_HWLEN,
htons(skb->dev->hard_header_len)) ||
nla_put(inst->skb, NFULA_HWHEADER, skb->dev->hard_header_len,
@@ -996,8 +996,10 @@
#ifdef CONFIG_PROC_FS
if (!proc_create("nfnetlink_log", 0440,
- proc_net_netfilter, &nful_file_ops))
+ proc_net_netfilter, &nful_file_ops)) {
+ status = -ENOMEM;
goto cleanup_logger;
+ }
#endif
return status;
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 1445d73..5270238 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1373,7 +1373,8 @@
dst_pid = addr->nl_pid;
dst_group = ffs(addr->nl_groups);
err = -EPERM;
- if (dst_group && !netlink_capable(sock, NL_NONROOT_SEND))
+ if ((dst_group || dst_pid) &&
+ !netlink_capable(sock, NL_NONROOT_SEND))
goto out;
} else {
dst_pid = nlk->dst_pid;
@@ -2147,6 +2148,7 @@
rcu_assign_pointer(nl_table[NETLINK_USERSOCK].listeners, listeners);
nl_table[NETLINK_USERSOCK].module = THIS_MODULE;
nl_table[NETLINK_USERSOCK].registered = 1;
+ nl_table[NETLINK_USERSOCK].nl_nonroot = NL_NONROOT_SEND;
netlink_table_ungrab();
}
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index aee7196..c5c9e2a 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1273,7 +1273,7 @@
spin_unlock(&f->lock);
}
-bool match_fanout_group(struct packet_type *ptype, struct sock * sk)
+static bool match_fanout_group(struct packet_type *ptype, struct sock * sk)
{
if (ptype->af_packet_priv == (void*)((struct packet_sock *)sk)->fanout)
return true;
diff --git a/net/socket.c b/net/socket.c
index a5471f8..edc3c4a 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -2604,7 +2604,7 @@
err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
set_fs(old_fs);
if (!err)
- err = compat_put_timeval(up, &ktv);
+ err = compat_put_timeval(&ktv, up);
return err;
}
@@ -2620,7 +2620,7 @@
err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
set_fs(old_fs);
if (!err)
- err = compat_put_timespec(up, &kts);
+ err = compat_put_timespec(&kts, up);
return err;
}
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index 88f2bf6..bac973a 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -316,7 +316,6 @@
*/
void svc_xprt_enqueue(struct svc_xprt *xprt)
{
- struct svc_serv *serv = xprt->xpt_server;
struct svc_pool *pool;
struct svc_rqst *rqstp;
int cpu;
@@ -362,8 +361,6 @@
rqstp, rqstp->rq_xprt);
rqstp->rq_xprt = xprt;
svc_xprt_get(xprt);
- rqstp->rq_reserved = serv->sv_max_mesg;
- atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved);
pool->sp_stats.threads_woken++;
wake_up(&rqstp->rq_wait);
} else {
@@ -640,8 +637,6 @@
if (xprt) {
rqstp->rq_xprt = xprt;
svc_xprt_get(xprt);
- rqstp->rq_reserved = serv->sv_max_mesg;
- atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved);
/* As there is a shortage of threads and this request
* had to be queued, don't allow the thread to wait so
@@ -738,6 +733,8 @@
else
len = xprt->xpt_ops->xpo_recvfrom(rqstp);
dprintk("svc: got len=%d\n", len);
+ rqstp->rq_reserved = serv->sv_max_mesg;
+ atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved);
}
svc_xprt_received(xprt);
@@ -794,7 +791,8 @@
/* Grab mutex to serialize outgoing data. */
mutex_lock(&xprt->xpt_mutex);
- if (test_bit(XPT_DEAD, &xprt->xpt_flags))
+ if (test_bit(XPT_DEAD, &xprt->xpt_flags)
+ || test_bit(XPT_CLOSE, &xprt->xpt_flags))
len = -ENOTCONN;
else
len = xprt->xpt_ops->xpo_sendto(rqstp);
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 18bc130..998aa8c 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -1129,9 +1129,9 @@
if (len >= 0)
svsk->sk_tcplen += len;
if (len != want) {
+ svc_tcp_save_pages(svsk, rqstp);
if (len < 0 && len != -EAGAIN)
goto err_other;
- svc_tcp_save_pages(svsk, rqstp);
dprintk("svc: incomplete TCP record (%d of %d)\n",
svsk->sk_tcplen, svsk->sk_reclen);
goto err_noclose;
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 87cd0e4..210be48 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -1994,8 +1994,10 @@
goto error;
x->outer_mode = xfrm_get_mode(x->props.mode, family);
- if (x->outer_mode == NULL)
+ if (x->outer_mode == NULL) {
+ err = -EPROTONOSUPPORT;
goto error;
+ }
if (init_replay) {
err = xfrm_init_replay(x);
diff --git a/scripts/Makefile.fwinst b/scripts/Makefile.fwinst
index 6bf8e87..c3f69ae2 100644
--- a/scripts/Makefile.fwinst
+++ b/scripts/Makefile.fwinst
@@ -42,7 +42,7 @@
$(installed-fw-dirs):
$(call cmd,mkdir)
-$(installed-fw): $(INSTALL_FW_PATH)/%: $(obj)/% | $(INSTALL_FW_PATH)/$$(dir %)
+$(installed-fw): $(INSTALL_FW_PATH)/%: $(obj)/% | $$(dir $(INSTALL_FW_PATH)/%)
$(call cmd,install)
PHONY += __fw_install __fw_modinst FORCE
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index 4629038c..4235a63 100644
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -211,7 +211,7 @@
if ! cmp -s System.map .tmp_System.map; then
echo >&2 Inconsistent kallsyms data
- echo >&2 echo Try "make KALLSYMS_EXTRA_PASS=1" as a workaround
+ echo >&2 Try "make KALLSYMS_EXTRA_PASS=1" as a workaround
cleanup
exit 1
fi
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index f560051..f25c24c 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1209,6 +1209,9 @@
kfree(codec);
}
+static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec,
+ hda_nid_t fg, unsigned int power_state);
+
static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
unsigned int power_state);
@@ -1317,6 +1320,10 @@
AC_VERB_GET_SUBSYSTEM_ID, 0);
}
+ codec->epss = snd_hda_codec_get_supported_ps(codec,
+ codec->afg ? codec->afg : codec->mfg,
+ AC_PWRST_EPSS);
+
/* power-up all before initialization */
hda_set_power_state(codec,
codec->afg ? codec->afg : codec->mfg,
@@ -3543,8 +3550,7 @@
/* this delay seems necessary to avoid click noise at power-down */
if (power_state == AC_PWRST_D3) {
/* transition time less than 10ms for power down */
- bool epss = snd_hda_codec_get_supported_ps(codec, fg, AC_PWRST_EPSS);
- msleep(epss ? 10 : 100);
+ msleep(codec->epss ? 10 : 100);
}
/* repeat power states setting at most 10 times*/
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 7fbc1bc..e5a7e19 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -862,6 +862,7 @@
unsigned int ignore_misc_bit:1; /* ignore MISC_NO_PRESENCE bit */
unsigned int no_jack_detect:1; /* Machine has no jack-detection */
unsigned int pcm_format_first:1; /* PCM format must be set first */
+ unsigned int epss:1; /* supporting EPSS? */
#ifdef CONFIG_SND_HDA_POWER_SAVE
unsigned int power_on :1; /* current (global) power-state */
int power_transition; /* power-state in transition */
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index ea5775a..6f806d3 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -4543,6 +4543,9 @@
struct auto_pin_cfg *cfg = &spec->autocfg;
int i;
+ if (cfg->speaker_outs == 0)
+ return;
+
for (i = 0; i < cfg->line_outs; i++) {
if (presence)
break;
@@ -5531,6 +5534,7 @@
snd_hda_codec_set_pincfg(codec, 0xf, 0x2181205e);
}
+ codec->epss = 0; /* longer delay needed for D3 */
codec->no_trigger_sense = 1;
codec->spec = spec;
diff --git a/sound/usb/card.c b/sound/usb/card.c
index d5b5c33..4a469f0 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -553,7 +553,7 @@
struct snd_usb_audio *chip)
{
struct snd_card *card;
- struct list_head *p;
+ struct list_head *p, *n;
if (chip == (void *)-1L)
return;
@@ -570,7 +570,7 @@
snd_usb_stream_disconnect(p);
}
/* release the endpoint resources */
- list_for_each(p, &chip->ep_list) {
+ list_for_each_safe(p, n, &chip->ep_list) {
snd_usb_endpoint_free(p);
}
/* release the midi resources */
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index c411812..d6e2bb4 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -141,7 +141,7 @@
*
* For implicit feedback, next_packet_size() is unused.
*/
-static int next_packet_size(struct snd_usb_endpoint *ep)
+int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep)
{
unsigned long flags;
int ret;
@@ -177,15 +177,6 @@
ep->retire_data_urb(ep->data_subs, urb);
}
-static void prepare_outbound_urb_sizes(struct snd_usb_endpoint *ep,
- struct snd_urb_ctx *ctx)
-{
- int i;
-
- for (i = 0; i < ctx->packets; ++i)
- ctx->packet_size[i] = next_packet_size(ep);
-}
-
/*
* Prepare a PLAYBACK urb for submission to the bus.
*/
@@ -370,7 +361,6 @@
goto exit_clear;
}
- prepare_outbound_urb_sizes(ep, ctx);
prepare_outbound_urb(ep, ctx);
} else {
retire_inbound_urb(ep, ctx);
@@ -799,7 +789,9 @@
/**
* snd_usb_endpoint_start: start an snd_usb_endpoint
*
- * @ep: the endpoint to start
+ * @ep: the endpoint to start
+ * @can_sleep: flag indicating whether the operation is executed in
+ * non-atomic context
*
* A call to this function will increment the use count of the endpoint.
* In case it is not already running, the URBs for this endpoint will be
@@ -809,7 +801,7 @@
*
* Returns an error if the URB submission failed, 0 in all other cases.
*/
-int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
+int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep)
{
int err;
unsigned int i;
@@ -821,6 +813,11 @@
if (++ep->use_count != 1)
return 0;
+ /* just to be sure */
+ deactivate_urbs(ep, 0, can_sleep);
+ if (can_sleep)
+ wait_clear_urbs(ep);
+
ep->active_mask = 0;
ep->unlink_mask = 0;
ep->phase = 0;
@@ -850,7 +847,6 @@
goto __error;
if (usb_pipeout(ep->pipe)) {
- prepare_outbound_urb_sizes(ep, urb->context);
prepare_outbound_urb(ep, urb->context);
} else {
prepare_inbound_urb(ep, urb->context);
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
index ee2723f..cbbbdf2 100644
--- a/sound/usb/endpoint.h
+++ b/sound/usb/endpoint.h
@@ -13,7 +13,7 @@
struct audioformat *fmt,
struct snd_usb_endpoint *sync_ep);
-int snd_usb_endpoint_start(struct snd_usb_endpoint *ep);
+int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep);
void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
int force, int can_sleep, int wait);
int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep);
@@ -21,6 +21,7 @@
void snd_usb_endpoint_free(struct list_head *head);
int snd_usb_endpoint_implict_feedback_sink(struct snd_usb_endpoint *ep);
+int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep);
void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
struct snd_usb_endpoint *sender,
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 62ec808..fd5e982 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -212,7 +212,7 @@
}
}
-static int start_endpoints(struct snd_usb_substream *subs)
+static int start_endpoints(struct snd_usb_substream *subs, int can_sleep)
{
int err;
@@ -225,7 +225,7 @@
snd_printdd(KERN_DEBUG "Starting data EP @%p\n", ep);
ep->data_subs = subs;
- err = snd_usb_endpoint_start(ep);
+ err = snd_usb_endpoint_start(ep, can_sleep);
if (err < 0) {
clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags);
return err;
@@ -236,10 +236,25 @@
!test_and_set_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) {
struct snd_usb_endpoint *ep = subs->sync_endpoint;
+ if (subs->data_endpoint->iface != subs->sync_endpoint->iface ||
+ subs->data_endpoint->alt_idx != subs->sync_endpoint->alt_idx) {
+ err = usb_set_interface(subs->dev,
+ subs->sync_endpoint->iface,
+ subs->sync_endpoint->alt_idx);
+ if (err < 0) {
+ snd_printk(KERN_ERR
+ "%d:%d:%d: cannot set interface (%d)\n",
+ subs->dev->devnum,
+ subs->sync_endpoint->iface,
+ subs->sync_endpoint->alt_idx, err);
+ return -EIO;
+ }
+ }
+
snd_printdd(KERN_DEBUG "Starting sync EP @%p\n", ep);
ep->sync_slave = subs->data_endpoint;
- err = snd_usb_endpoint_start(ep);
+ err = snd_usb_endpoint_start(ep, can_sleep);
if (err < 0) {
clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags);
return err;
@@ -544,13 +559,10 @@
subs->last_frame_number = 0;
runtime->delay = 0;
- /* clear the pending deactivation on the target EPs */
- deactivate_endpoints(subs);
-
/* for playback, submit the URBs now; otherwise, the first hwptr_done
* updates for all URBs would happen at the same time when starting */
if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK)
- return start_endpoints(subs);
+ return start_endpoints(subs, 1);
return 0;
}
@@ -1032,6 +1044,7 @@
struct urb *urb)
{
struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
+ struct snd_usb_endpoint *ep = subs->data_endpoint;
struct snd_urb_ctx *ctx = urb->context;
unsigned int counts, frames, bytes;
int i, stride, period_elapsed = 0;
@@ -1043,7 +1056,11 @@
urb->number_of_packets = 0;
spin_lock_irqsave(&subs->lock, flags);
for (i = 0; i < ctx->packets; i++) {
- counts = ctx->packet_size[i];
+ if (ctx->packet_size[i])
+ counts = ctx->packet_size[i];
+ else
+ counts = snd_usb_endpoint_next_packet_size(ep);
+
/* set up descriptor */
urb->iso_frame_desc[i].offset = frames * stride;
urb->iso_frame_desc[i].length = counts * stride;
@@ -1094,7 +1111,16 @@
subs->hwptr_done += bytes;
if (subs->hwptr_done >= runtime->buffer_size * stride)
subs->hwptr_done -= runtime->buffer_size * stride;
+
+ /* update delay with exact number of samples queued */
+ runtime->delay = subs->last_delay;
runtime->delay += frames;
+ subs->last_delay = runtime->delay;
+
+ /* realign last_frame_number */
+ subs->last_frame_number = usb_get_current_frame_number(subs->dev);
+ subs->last_frame_number &= 0xFF; /* keep 8 LSBs */
+
spin_unlock_irqrestore(&subs->lock, flags);
urb->transfer_buffer_length = bytes;
if (period_elapsed)
@@ -1112,12 +1138,26 @@
struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
int stride = runtime->frame_bits >> 3;
int processed = urb->transfer_buffer_length / stride;
+ int est_delay;
spin_lock_irqsave(&subs->lock, flags);
- if (processed > runtime->delay)
- runtime->delay = 0;
+ est_delay = snd_usb_pcm_delay(subs, runtime->rate);
+ /* update delay with exact number of samples played */
+ if (processed > subs->last_delay)
+ subs->last_delay = 0;
else
- runtime->delay -= processed;
+ subs->last_delay -= processed;
+ runtime->delay = subs->last_delay;
+
+ /*
+ * Report when delay estimate is off by more than 2ms.
+ * The error should be lower than 2ms since the estimate relies
+ * on two reads of a counter updated every ms.
+ */
+ if (abs(est_delay - subs->last_delay) * 1000 > runtime->rate * 2)
+ snd_printk(KERN_DEBUG "delay: estimated %d, actual %d\n",
+ est_delay, subs->last_delay);
+
spin_unlock_irqrestore(&subs->lock, flags);
}
@@ -1175,7 +1215,7 @@
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
- err = start_endpoints(subs);
+ err = start_endpoints(subs, 0);
if (err < 0)
return err;
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index 2884e67..2133628 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -10,10 +10,12 @@
util/evlist.c
util/evsel.c
util/cpumap.c
+util/hweight.c
util/thread_map.c
util/util.c
util/xyarray.c
util/cgroup.c
util/debugfs.c
+util/rblist.c
util/strlist.c
../../lib/rbtree.c
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 2468523..d617f69 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1976,9 +1976,10 @@
if (copy_from_user(&csigset, sigmask_arg->sigset,
sizeof csigset))
goto out;
- }
- sigset_from_compat(&sigset, &csigset);
- r = kvm_vcpu_ioctl_set_sigmask(vcpu, &sigset);
+ sigset_from_compat(&sigset, &csigset);
+ r = kvm_vcpu_ioctl_set_sigmask(vcpu, &sigset);
+ } else
+ r = kvm_vcpu_ioctl_set_sigmask(vcpu, NULL);
break;
}
default: