diff options
255 files changed, 5853 insertions, 4910 deletions
diff --git a/.gitignore b/.gitignore index 9ac91060ea64..acb6afe6b7a3 100644 --- a/.gitignore +++ b/.gitignore | |||
| @@ -43,6 +43,7 @@ Module.symvers | |||
| 43 | /TAGS | 43 | /TAGS |
| 44 | /linux | 44 | /linux |
| 45 | /vmlinux | 45 | /vmlinux |
| 46 | /vmlinux-gdb.py | ||
| 46 | /vmlinuz | 47 | /vmlinuz |
| 47 | /System.map | 48 | /System.map |
| 48 | /Module.markers | 49 | /Module.markers |
diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl index f2130586ef5d..faf09d4a0ea8 100644 --- a/Documentation/DocBook/device-drivers.tmpl +++ b/Documentation/DocBook/device-drivers.tmpl | |||
| @@ -190,23 +190,6 @@ X!Edrivers/pnp/system.c | |||
| 190 | !Idrivers/message/fusion/mptfc.c | 190 | !Idrivers/message/fusion/mptfc.c |
| 191 | !Idrivers/message/fusion/mptlan.c | 191 | !Idrivers/message/fusion/mptlan.c |
| 192 | </sect1> | 192 | </sect1> |
| 193 | <sect1><title>I2O message devices</title> | ||
| 194 | !Iinclude/linux/i2o.h | ||
| 195 | !Idrivers/message/i2o/core.h | ||
| 196 | !Edrivers/message/i2o/iop.c | ||
| 197 | !Idrivers/message/i2o/iop.c | ||
| 198 | !Idrivers/message/i2o/config-osm.c | ||
| 199 | !Edrivers/message/i2o/exec-osm.c | ||
| 200 | !Idrivers/message/i2o/exec-osm.c | ||
| 201 | !Idrivers/message/i2o/bus-osm.c | ||
| 202 | !Edrivers/message/i2o/device.c | ||
| 203 | !Idrivers/message/i2o/device.c | ||
| 204 | !Idrivers/message/i2o/driver.c | ||
| 205 | !Idrivers/message/i2o/pci.c | ||
| 206 | !Idrivers/message/i2o/i2o_block.c | ||
| 207 | !Idrivers/message/i2o/i2o_scsi.c | ||
| 208 | !Idrivers/message/i2o/i2o_proc.c | ||
| 209 | </sect1> | ||
| 210 | </chapter> | 193 | </chapter> |
| 211 | 194 | ||
| 212 | <chapter id="snddev"> | 195 | <chapter id="snddev"> |
diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt index 1fe6dde98499..7d4c8eb775a5 100644 --- a/Documentation/devicetree/bindings/mtd/atmel-nand.txt +++ b/Documentation/devicetree/bindings/mtd/atmel-nand.txt | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | Atmel NAND flash | 1 | Atmel NAND flash |
| 2 | 2 | ||
| 3 | Required properties: | 3 | Required properties: |
| 4 | - compatible : "atmel,at91rm9200-nand". | 4 | - compatible : should be "atmel,at91rm9200-nand" or "atmel,sama5d4-nand". |
| 5 | - reg : should specify localbus address and size used for the chip, | 5 | - reg : should specify localbus address and size used for the chip, |
| 6 | and hardware ECC controller if available. | 6 | and hardware ECC controller if available. |
| 7 | If the hardware ECC is PMECC, it should contain address and size for | 7 | If the hardware ECC is PMECC, it should contain address and size for |
diff --git a/Documentation/devicetree/bindings/mtd/fsl-quadspi.txt b/Documentation/devicetree/bindings/mtd/fsl-quadspi.txt index 823d13412195..4461dc71cb10 100644 --- a/Documentation/devicetree/bindings/mtd/fsl-quadspi.txt +++ b/Documentation/devicetree/bindings/mtd/fsl-quadspi.txt | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | * Freescale Quad Serial Peripheral Interface(QuadSPI) | 1 | * Freescale Quad Serial Peripheral Interface(QuadSPI) |
| 2 | 2 | ||
| 3 | Required properties: | 3 | Required properties: |
| 4 | - compatible : Should be "fsl,vf610-qspi" | 4 | - compatible : Should be "fsl,vf610-qspi" or "fsl,imx6sx-qspi" |
| 5 | - reg : the first contains the register location and length, | 5 | - reg : the first contains the register location and length, |
| 6 | the second contains the memory mapping address and length | 6 | the second contains the memory mapping address and length |
| 7 | - reg-names: Should contain the reg names "QuadSPI" and "QuadSPI-memory" | 7 | - reg-names: Should contain the reg names "QuadSPI" and "QuadSPI-memory" |
diff --git a/Documentation/devicetree/bindings/mtd/gpmi-nand.txt b/Documentation/devicetree/bindings/mtd/gpmi-nand.txt index a011fdf61dbf..d02acaff3c35 100644 --- a/Documentation/devicetree/bindings/mtd/gpmi-nand.txt +++ b/Documentation/devicetree/bindings/mtd/gpmi-nand.txt | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | * Freescale General-Purpose Media Interface (GPMI) | 1 | * Freescale General-Purpose Media Interface (GPMI) |
| 2 | 2 | ||
| 3 | The GPMI nand controller provides an interface to control the | 3 | The GPMI nand controller provides an interface to control the |
| 4 | NAND flash chips. We support only one NAND chip now. | 4 | NAND flash chips. |
| 5 | 5 | ||
| 6 | Required properties: | 6 | Required properties: |
| 7 | - compatible : should be "fsl,<chip>-gpmi-nand" | 7 | - compatible : should be "fsl,<chip>-gpmi-nand" |
diff --git a/Documentation/devicetree/bindings/mtd/hisi504-nand.txt b/Documentation/devicetree/bindings/mtd/hisi504-nand.txt new file mode 100644 index 000000000000..2e35f0662912 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/hisi504-nand.txt | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | Hisilicon Hip04 Soc NAND controller DT binding | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | |||
| 5 | - compatible: Should be "hisilicon,504-nfc". | ||
| 6 | - reg: The first contains base physical address and size of | ||
| 7 | NAND controller's registers. The second contains base | ||
| 8 | physical address and size of NAND controller's buffer. | ||
| 9 | - interrupts: Interrupt number for nfc. | ||
| 10 | - nand-bus-width: See nand.txt. | ||
| 11 | - nand-ecc-mode: Support none and hw ecc mode. | ||
| 12 | - #address-cells: Partition address, should be set 1. | ||
| 13 | - #size-cells: Partition size, should be set 1. | ||
| 14 | |||
| 15 | Optional properties: | ||
| 16 | |||
| 17 | - nand-ecc-strength: Number of bits to correct per ECC step. | ||
| 18 | - nand-ecc-step-size: Number of data bytes covered by a single ECC step. | ||
| 19 | |||
| 20 | The following ECC strength and step size are currently supported: | ||
| 21 | |||
| 22 | - nand-ecc-strength = <16>, nand-ecc-step-size = <1024> | ||
| 23 | |||
| 24 | Flash chip may optionally contain additional sub-nodes describing partitions of | ||
| 25 | the address space. See partition.txt for more detail. | ||
| 26 | |||
| 27 | Example: | ||
| 28 | |||
| 29 | nand: nand@4020000 { | ||
| 30 | compatible = "hisilicon,504-nfc"; | ||
| 31 | reg = <0x4020000 0x10000>, <0x5000000 0x1000>; | ||
| 32 | interrupts = <0 379 4>; | ||
| 33 | nand-bus-width = <8>; | ||
| 34 | nand-ecc-mode = "hw"; | ||
| 35 | nand-ecc-strength = <16>; | ||
| 36 | nand-ecc-step-size = <1024>; | ||
| 37 | #address-cells = <1>; | ||
| 38 | #size-cells = <1>; | ||
| 39 | |||
| 40 | partition@0 { | ||
| 41 | label = "nand_text"; | ||
| 42 | reg = <0x00000000 0x00400000>; | ||
| 43 | }; | ||
| 44 | |||
| 45 | ... | ||
| 46 | |||
| 47 | }; | ||
diff --git a/Documentation/devicetree/bindings/mtd/mtd-physmap.txt b/Documentation/devicetree/bindings/mtd/mtd-physmap.txt index 6b9f680cb579..4a0a48bf4ecb 100644 --- a/Documentation/devicetree/bindings/mtd/mtd-physmap.txt +++ b/Documentation/devicetree/bindings/mtd/mtd-physmap.txt | |||
| @@ -36,6 +36,11 @@ are defined: | |||
| 36 | - vendor-id : Contains the flash chip's vendor id (1 byte). | 36 | - vendor-id : Contains the flash chip's vendor id (1 byte). |
| 37 | - device-id : Contains the flash chip's device id (1 byte). | 37 | - device-id : Contains the flash chip's device id (1 byte). |
| 38 | 38 | ||
| 39 | For ROM compatible devices (and ROM fallback from cfi-flash), the following | ||
| 40 | additional (optional) property is defined: | ||
| 41 | |||
| 42 | - erase-size : The chip's physical erase block size in bytes. | ||
| 43 | |||
| 39 | The device tree may optionally contain sub-nodes describing partitions of the | 44 | The device tree may optionally contain sub-nodes describing partitions of the |
| 40 | address space. See partition.txt for more detail. | 45 | address space. See partition.txt for more detail. |
| 41 | 46 | ||
diff --git a/Documentation/gdb-kernel-debugging.txt b/Documentation/gdb-kernel-debugging.txt new file mode 100644 index 000000000000..7050ce8794b9 --- /dev/null +++ b/Documentation/gdb-kernel-debugging.txt | |||
| @@ -0,0 +1,160 @@ | |||
| 1 | Debugging kernel and modules via gdb | ||
| 2 | ==================================== | ||
| 3 | |||
| 4 | The kernel debugger kgdb, hypervisors like QEMU or JTAG-based hardware | ||
| 5 | interfaces allow to debug the Linux kernel and its modules during runtime | ||
| 6 | using gdb. Gdb comes with a powerful scripting interface for python. The | ||
| 7 | kernel provides a collection of helper scripts that can simplify typical | ||
| 8 | kernel debugging steps. This is a short tutorial about how to enable and use | ||
| 9 | them. It focuses on QEMU/KVM virtual machines as target, but the examples can | ||
| 10 | be transferred to the other gdb stubs as well. | ||
| 11 | |||
| 12 | |||
| 13 | Requirements | ||
| 14 | ------------ | ||
| 15 | |||
| 16 | o gdb 7.2+ (recommended: 7.4+) with python support enabled (typically true | ||
| 17 | for distributions) | ||
| 18 | |||
| 19 | |||
| 20 | Setup | ||
| 21 | ----- | ||
| 22 | |||
| 23 | o Create a virtual Linux machine for QEMU/KVM (see www.linux-kvm.org and | ||
| 24 | www.qemu.org for more details). For cross-development, | ||
| 25 | http://landley.net/aboriginal/bin keeps a pool of machine images and | ||
| 26 | toolchains that can be helpful to start from. | ||
| 27 | |||
| 28 | o Build the kernel with CONFIG_GDB_SCRIPTS enabled, but leave | ||
| 29 | CONFIG_DEBUG_INFO_REDUCED off. If your architecture supports | ||
| 30 | CONFIG_FRAME_POINTER, keep it enabled. | ||
| 31 | |||
| 32 | o Install that kernel on the guest. | ||
| 33 | |||
| 34 | Alternatively, QEMU allows to boot the kernel directly using -kernel, | ||
| 35 | -append, -initrd command line switches. This is generally only useful if | ||
| 36 | you do not depend on modules. See QEMU documentation for more details on | ||
| 37 | this mode. | ||
| 38 | |||
| 39 | o Enable the gdb stub of QEMU/KVM, either | ||
| 40 | - at VM startup time by appending "-s" to the QEMU command line | ||
| 41 | or | ||
| 42 | - during runtime by issuing "gdbserver" from the QEMU monitor | ||
| 43 | console | ||
| 44 | |||
| 45 | o cd /path/to/linux-build | ||
| 46 | |||
| 47 | o Start gdb: gdb vmlinux | ||
| 48 | |||
| 49 | Note: Some distros may restrict auto-loading of gdb scripts to known safe | ||
| 50 | directories. In case gdb reports to refuse loading vmlinux-gdb.py, add | ||
| 51 | |||
| 52 | add-auto-load-safe-path /path/to/linux-build | ||
| 53 | |||
| 54 | to ~/.gdbinit. See gdb help for more details. | ||
| 55 | |||
| 56 | o Attach to the booted guest: | ||
| 57 | (gdb) target remote :1234 | ||
| 58 | |||
| 59 | |||
| 60 | Examples of using the Linux-provided gdb helpers | ||
| 61 | ------------------------------------------------ | ||
| 62 | |||
| 63 | o Load module (and main kernel) symbols: | ||
| 64 | (gdb) lx-symbols | ||
| 65 | loading vmlinux | ||
| 66 | scanning for modules in /home/user/linux/build | ||
| 67 | loading @0xffffffffa0020000: /home/user/linux/build/net/netfilter/xt_tcpudp.ko | ||
| 68 | loading @0xffffffffa0016000: /home/user/linux/build/net/netfilter/xt_pkttype.ko | ||
| 69 | loading @0xffffffffa0002000: /home/user/linux/build/net/netfilter/xt_limit.ko | ||
| 70 | loading @0xffffffffa00ca000: /home/user/linux/build/net/packet/af_packet.ko | ||
| 71 | loading @0xffffffffa003c000: /home/user/linux/build/fs/fuse/fuse.ko | ||
| 72 | ... | ||
| 73 | loading @0xffffffffa0000000: /home/user/linux/build/drivers/ata/ata_generic.ko | ||
| 74 | |||
| 75 | o Set a breakpoint on some not yet loaded module function, e.g.: | ||
| 76 | (gdb) b btrfs_init_sysfs | ||
| 77 | Function "btrfs_init_sysfs" not defined. | ||
| 78 | Make breakpoint pending on future shared library load? (y or [n]) y | ||
| 79 | Breakpoint 1 (btrfs_init_sysfs) pending. | ||
| 80 | |||
| 81 | o Continue the target | ||
| 82 | (gdb) c | ||
| 83 | |||
| 84 | o Load the module on the target and watch the symbols being loaded as well as | ||
| 85 | the breakpoint hit: | ||
| 86 | loading @0xffffffffa0034000: /home/user/linux/build/lib/libcrc32c.ko | ||
| 87 | loading @0xffffffffa0050000: /home/user/linux/build/lib/lzo/lzo_compress.ko | ||
| 88 | loading @0xffffffffa006e000: /home/user/linux/build/lib/zlib_deflate/zlib_deflate.ko | ||
| 89 | loading @0xffffffffa01b1000: /home/user/linux/build/fs/btrfs/btrfs.ko | ||
| 90 | |||
| 91 | Breakpoint 1, btrfs_init_sysfs () at /home/user/linux/fs/btrfs/sysfs.c:36 | ||
| 92 | 36 btrfs_kset = kset_create_and_add("btrfs", NULL, fs_kobj); | ||
| 93 | |||
| 94 | o Dump the log buffer of the target kernel: | ||
| 95 | (gdb) lx-dmesg | ||
| 96 | [ 0.000000] Initializing cgroup subsys cpuset | ||
| 97 | [ 0.000000] Initializing cgroup subsys cpu | ||
| 98 | [ 0.000000] Linux version 3.8.0-rc4-dbg+ (... | ||
| 99 | [ 0.000000] Command line: root=/dev/sda2 resume=/dev/sda1 vga=0x314 | ||
| 100 | [ 0.000000] e820: BIOS-provided physical RAM map: | ||
| 101 | [ 0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable | ||
| 102 | [ 0.000000] BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved | ||
| 103 | .... | ||
| 104 | |||
| 105 | o Examine fields of the current task struct: | ||
| 106 | (gdb) p $lx_current().pid | ||
| 107 | $1 = 4998 | ||
| 108 | (gdb) p $lx_current().comm | ||
| 109 | $2 = "modprobe\000\000\000\000\000\000\000" | ||
| 110 | |||
| 111 | o Make use of the per-cpu function for the current or a specified CPU: | ||
| 112 | (gdb) p $lx_per_cpu("runqueues").nr_running | ||
| 113 | $3 = 1 | ||
| 114 | (gdb) p $lx_per_cpu("runqueues", 2).nr_running | ||
| 115 | $4 = 0 | ||
| 116 | |||
| 117 | o Dig into hrtimers using the container_of helper: | ||
| 118 | (gdb) set $next = $lx_per_cpu("hrtimer_bases").clock_base[0].active.next | ||
| 119 | (gdb) p *$container_of($next, "struct hrtimer", "node") | ||
| 120 | $5 = { | ||
| 121 | node = { | ||
| 122 | node = { | ||
| 123 | __rb_parent_color = 18446612133355256072, | ||
| 124 | rb_right = 0x0 <irq_stack_union>, | ||
| 125 | rb_left = 0x0 <irq_stack_union> | ||
| 126 | }, | ||
| 127 | expires = { | ||
| 128 | tv64 = 1835268000000 | ||
| 129 | } | ||
| 130 | }, | ||
| 131 | _softexpires = { | ||
| 132 | tv64 = 1835268000000 | ||
| 133 | }, | ||
| 134 | function = 0xffffffff81078232 <tick_sched_timer>, | ||
| 135 | base = 0xffff88003fd0d6f0, | ||
| 136 | state = 1, | ||
| 137 | start_pid = 0, | ||
| 138 | start_site = 0xffffffff81055c1f <hrtimer_start_range_ns+20>, | ||
| 139 | start_comm = "swapper/2\000\000\000\000\000\000" | ||
| 140 | } | ||
| 141 | |||
| 142 | |||
| 143 | List of commands and functions | ||
| 144 | ------------------------------ | ||
| 145 | |||
| 146 | The number of commands and convenience functions may evolve over the time, | ||
| 147 | this is just a snapshot of the initial version: | ||
| 148 | |||
| 149 | (gdb) apropos lx | ||
| 150 | function lx_current -- Return current task | ||
| 151 | function lx_module -- Find module by name and return the module variable | ||
| 152 | function lx_per_cpu -- Return per-cpu variable | ||
| 153 | function lx_task_by_pid -- Find Linux task by PID and return the task_struct variable | ||
| 154 | function lx_thread_info -- Calculate Linux thread_info from task variable | ||
| 155 | lx-dmesg -- Print Linux kernel log buffer | ||
| 156 | lx-lsmod -- List currently loaded modules | ||
| 157 | lx-symbols -- (Re-)load symbols of Linux kernel and currently loaded modules | ||
| 158 | |||
| 159 | Detailed help can be obtained via "help <command-name>" for commands and "help | ||
| 160 | function <function-name>" for convenience functions. | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 85024e23309f..7ac95f8ba6ca 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -4092,6 +4092,12 @@ S: Maintained | |||
| 4092 | F: include/linux/platform_data/video-imxfb.h | 4092 | F: include/linux/platform_data/video-imxfb.h |
| 4093 | F: drivers/video/fbdev/imxfb.c | 4093 | F: drivers/video/fbdev/imxfb.c |
| 4094 | 4094 | ||
| 4095 | FREESCALE QUAD SPI DRIVER | ||
| 4096 | M: Han Xu <han.xu@freescale.com> | ||
| 4097 | L: linux-mtd@lists.infradead.org | ||
| 4098 | S: Maintained | ||
| 4099 | F: drivers/mtd/spi-nor/fsl-quadspi.c | ||
| 4100 | |||
| 4095 | FREESCALE SOC FS_ENET DRIVER | 4101 | FREESCALE SOC FS_ENET DRIVER |
| 4096 | M: Pantelis Antoniou <pantelis.antoniou@gmail.com> | 4102 | M: Pantelis Antoniou <pantelis.antoniou@gmail.com> |
| 4097 | M: Vitaly Bordug <vbordug@ru.mvista.com> | 4103 | M: Vitaly Bordug <vbordug@ru.mvista.com> |
| @@ -4232,6 +4238,11 @@ W: http://www.icp-vortex.com/ | |||
| 4232 | S: Supported | 4238 | S: Supported |
| 4233 | F: drivers/scsi/gdt* | 4239 | F: drivers/scsi/gdt* |
| 4234 | 4240 | ||
| 4241 | GDB KERNEL DEBUGGING HELPER SCRIPTS | ||
| 4242 | M: Jan Kiszka <jan.kiszka@siemens.com> | ||
| 4243 | S: Supported | ||
| 4244 | F: scripts/gdb/ | ||
| 4245 | |||
| 4235 | GEMTEK FM RADIO RECEIVER DRIVER | 4246 | GEMTEK FM RADIO RECEIVER DRIVER |
| 4236 | M: Hans Verkuil <hverkuil@xs4all.nl> | 4247 | M: Hans Verkuil <hverkuil@xs4all.nl> |
| 4237 | L: linux-media@vger.kernel.org | 4248 | L: linux-media@vger.kernel.org |
| @@ -6876,7 +6887,7 @@ F: drivers/scsi/nsp32* | |||
| 6876 | NIOS2 ARCHITECTURE | 6887 | NIOS2 ARCHITECTURE |
| 6877 | M: Ley Foon Tan <lftan@altera.com> | 6888 | M: Ley Foon Tan <lftan@altera.com> |
| 6878 | L: nios2-dev@lists.rocketboards.org (moderated for non-subscribers) | 6889 | L: nios2-dev@lists.rocketboards.org (moderated for non-subscribers) |
| 6879 | T: git git://git.rocketboards.org/linux-socfpga.git | 6890 | T: git git://git.rocketboards.org/linux-socfpga-next.git |
| 6880 | S: Maintained | 6891 | S: Maintained |
| 6881 | F: arch/nios2/ | 6892 | F: arch/nios2/ |
| 6882 | 6893 | ||
| @@ -927,6 +927,9 @@ endif | |||
| 927 | ifdef CONFIG_BUILD_DOCSRC | 927 | ifdef CONFIG_BUILD_DOCSRC |
| 928 | $(Q)$(MAKE) $(build)=Documentation | 928 | $(Q)$(MAKE) $(build)=Documentation |
| 929 | endif | 929 | endif |
| 930 | ifdef CONFIG_GDB_SCRIPTS | ||
| 931 | $(Q)ln -fsn `cd $(srctree) && /bin/pwd`/scripts/gdb/vmlinux-gdb.py | ||
| 932 | endif | ||
| 930 | +$(call if_changed,link-vmlinux) | 933 | +$(call if_changed,link-vmlinux) |
| 931 | 934 | ||
| 932 | # The actual objects are generated when descending, | 935 | # The actual objects are generated when descending, |
| @@ -1181,7 +1184,7 @@ MRPROPER_FILES += .config .config.old .version .old_version $(version_h) \ | |||
| 1181 | Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS \ | 1184 | Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS \ |
| 1182 | signing_key.priv signing_key.x509 x509.genkey \ | 1185 | signing_key.priv signing_key.x509 x509.genkey \ |
| 1183 | extra_certificates signing_key.x509.keyid \ | 1186 | extra_certificates signing_key.x509.keyid \ |
| 1184 | signing_key.x509.signer | 1187 | signing_key.x509.signer vmlinux-gdb.py |
| 1185 | 1188 | ||
| 1186 | # clean - Delete most, but leave enough to build external modules | 1189 | # clean - Delete most, but leave enough to build external modules |
| 1187 | # | 1190 | # |
diff --git a/arch/mips/include/asm/mach-jz4740/jz4740_nand.h b/arch/mips/include/asm/mach-jz4740/jz4740_nand.h index 986982db7c38..79cff26d8b36 100644 --- a/arch/mips/include/asm/mach-jz4740/jz4740_nand.h +++ b/arch/mips/include/asm/mach-jz4740/jz4740_nand.h | |||
| @@ -27,8 +27,6 @@ struct jz_nand_platform_data { | |||
| 27 | 27 | ||
| 28 | struct nand_ecclayout *ecc_layout; | 28 | struct nand_ecclayout *ecc_layout; |
| 29 | 29 | ||
| 30 | unsigned int busy_gpio; | ||
| 31 | |||
| 32 | unsigned char banks[JZ_NAND_NUM_BANKS]; | 30 | unsigned char banks[JZ_NAND_NUM_BANKS]; |
| 33 | 31 | ||
| 34 | void (*ident_callback)(struct platform_device *, struct nand_chip *, | 32 | void (*ident_callback)(struct platform_device *, struct nand_chip *, |
diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c index c454525e7695..9dd051edb411 100644 --- a/arch/mips/jz4740/board-qi_lb60.c +++ b/arch/mips/jz4740/board-qi_lb60.c | |||
| @@ -140,10 +140,18 @@ static void qi_lb60_nand_ident(struct platform_device *pdev, | |||
| 140 | 140 | ||
| 141 | static struct jz_nand_platform_data qi_lb60_nand_pdata = { | 141 | static struct jz_nand_platform_data qi_lb60_nand_pdata = { |
| 142 | .ident_callback = qi_lb60_nand_ident, | 142 | .ident_callback = qi_lb60_nand_ident, |
| 143 | .busy_gpio = 94, | ||
| 144 | .banks = { 1 }, | 143 | .banks = { 1 }, |
| 145 | }; | 144 | }; |
| 146 | 145 | ||
| 146 | static struct gpiod_lookup_table qi_lb60_nand_gpio_table = { | ||
| 147 | .dev_id = "jz4740-nand.0", | ||
| 148 | .table = { | ||
| 149 | GPIO_LOOKUP("Bank C", 30, "busy", 0), | ||
| 150 | { }, | ||
| 151 | }, | ||
| 152 | }; | ||
| 153 | |||
| 154 | |||
| 147 | /* Keyboard*/ | 155 | /* Keyboard*/ |
| 148 | 156 | ||
| 149 | #define KEY_QI_QI KEY_F13 | 157 | #define KEY_QI_QI KEY_F13 |
| @@ -472,6 +480,7 @@ static int __init qi_lb60_init_platform_devices(void) | |||
| 472 | jz4740_mmc_device.dev.platform_data = &qi_lb60_mmc_pdata; | 480 | jz4740_mmc_device.dev.platform_data = &qi_lb60_mmc_pdata; |
| 473 | 481 | ||
| 474 | gpiod_add_lookup_table(&qi_lb60_audio_gpio_table); | 482 | gpiod_add_lookup_table(&qi_lb60_audio_gpio_table); |
| 483 | gpiod_add_lookup_table(&qi_lb60_nand_gpio_table); | ||
| 475 | 484 | ||
| 476 | jz4740_serial_device_register(); | 485 | jz4740_serial_device_register(); |
| 477 | 486 | ||
diff --git a/arch/nios2/Kconfig b/arch/nios2/Kconfig index 2361acf6d2b1..437555424bda 100644 --- a/arch/nios2/Kconfig +++ b/arch/nios2/Kconfig | |||
| @@ -8,6 +8,7 @@ config NIOS2 | |||
| 8 | select GENERIC_IRQ_PROBE | 8 | select GENERIC_IRQ_PROBE |
| 9 | select GENERIC_IRQ_SHOW | 9 | select GENERIC_IRQ_SHOW |
| 10 | select HAVE_ARCH_TRACEHOOK | 10 | select HAVE_ARCH_TRACEHOOK |
| 11 | select HAVE_ARCH_KGDB | ||
| 11 | select IRQ_DOMAIN | 12 | select IRQ_DOMAIN |
| 12 | select MODULES_USE_ELF_RELA | 13 | select MODULES_USE_ELF_RELA |
| 13 | select OF | 14 | select OF |
| @@ -134,6 +135,14 @@ config NIOS2_PASS_CMDLINE | |||
| 134 | will override "Default kernel command string". | 135 | will override "Default kernel command string". |
| 135 | Say N if you are unsure. | 136 | Say N if you are unsure. |
| 136 | 137 | ||
| 138 | config NIOS2_BOOT_LINK_OFFSET | ||
| 139 | hex "Link address offset for booting" | ||
| 140 | default "0x00500000" | ||
| 141 | help | ||
| 142 | This option allows you to set the link address offset of the zImage. | ||
| 143 | This can be useful if you are on a board which has a small amount of | ||
| 144 | memory. | ||
| 145 | |||
| 137 | endmenu | 146 | endmenu |
| 138 | 147 | ||
| 139 | menu "Advanced setup" | 148 | menu "Advanced setup" |
diff --git a/arch/nios2/Kconfig.debug b/arch/nios2/Kconfig.debug index 8d4e6bacd997..2fd08cbfdddb 100644 --- a/arch/nios2/Kconfig.debug +++ b/arch/nios2/Kconfig.debug | |||
| @@ -14,4 +14,15 @@ config DEBUG_STACK_USAGE | |||
| 14 | 14 | ||
| 15 | This option will slow down process creation somewhat. | 15 | This option will slow down process creation somewhat. |
| 16 | 16 | ||
| 17 | config EARLY_PRINTK | ||
| 18 | bool "Activate early kernel debugging" | ||
| 19 | default y | ||
| 20 | select SERIAL_CORE_CONSOLE | ||
| 21 | depends on SERIAL_ALTERA_JTAGUART_CONSOLE || SERIAL_ALTERA_UART_CONSOLE | ||
| 22 | help | ||
| 23 | Enable early printk on console | ||
| 24 | This is useful for kernel debugging when your machine crashes very | ||
| 25 | early before the console code is initialized. | ||
| 26 | You should normally say N here, unless you want to debug such a crash. | ||
| 27 | |||
| 17 | endmenu | 28 | endmenu |
diff --git a/arch/nios2/boot/Makefile b/arch/nios2/boot/Makefile index 59392dc0bdcb..c899876320df 100644 --- a/arch/nios2/boot/Makefile +++ b/arch/nios2/boot/Makefile | |||
| @@ -24,6 +24,13 @@ $(obj)/vmImage: $(obj)/vmlinux.gz | |||
| 24 | $(call if_changed,uimage) | 24 | $(call if_changed,uimage) |
| 25 | @$(kecho) 'Kernel: $@ is ready' | 25 | @$(kecho) 'Kernel: $@ is ready' |
| 26 | 26 | ||
| 27 | $(obj)/zImage: $(obj)/compressed/vmlinux FORCE | ||
| 28 | $(call if_changed,objcopy) | ||
| 29 | @$(kecho) 'Kernel: $@ is ready' | ||
| 30 | |||
| 31 | $(obj)/compressed/vmlinux: $(obj)/vmlinux.gz FORCE | ||
| 32 | $(Q)$(MAKE) $(build)=$(obj)/compressed $@ | ||
| 33 | |||
| 27 | # Rule to build device tree blobs | 34 | # Rule to build device tree blobs |
| 28 | DTB_SRC := $(patsubst "%",%,$(CONFIG_NIOS2_DTB_SOURCE)) | 35 | DTB_SRC := $(patsubst "%",%,$(CONFIG_NIOS2_DTB_SOURCE)) |
| 29 | 36 | ||
diff --git a/arch/nios2/boot/compressed/Makefile b/arch/nios2/boot/compressed/Makefile new file mode 100644 index 000000000000..5b0fb346d888 --- /dev/null +++ b/arch/nios2/boot/compressed/Makefile | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | # | ||
| 2 | # create a compressed vmlinux image from the original vmlinux | ||
| 3 | # | ||
| 4 | |||
| 5 | targets := vmlinux head.o misc.o piggy.o vmlinux.lds | ||
| 6 | asflags-y := | ||
| 7 | |||
| 8 | OBJECTS = $(obj)/head.o $(obj)/misc.o | ||
| 9 | |||
| 10 | LDFLAGS_vmlinux := -T | ||
| 11 | |||
| 12 | $(obj)/vmlinux: $(obj)/vmlinux.lds $(OBJECTS) $(obj)/piggy.o FORCE | ||
| 13 | $(call if_changed,ld) | ||
| 14 | @: | ||
| 15 | |||
| 16 | LDFLAGS_piggy.o := -r --format binary --oformat elf32-littlenios2 -T | ||
| 17 | |||
| 18 | $(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/../vmlinux.gz FORCE | ||
| 19 | $(call if_changed,ld) | ||
diff --git a/arch/nios2/boot/compressed/console.c b/arch/nios2/boot/compressed/console.c new file mode 100644 index 000000000000..2675e879b85a --- /dev/null +++ b/arch/nios2/boot/compressed/console.c | |||
| @@ -0,0 +1,125 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2008-2010 Thomas Chou <thomas@wytron.com.tw> | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License as published by | ||
| 6 | * the Free Software Foundation; either version 2 of the License, or | ||
| 7 | * (at your option) any later version. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License | ||
| 15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | * | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include <linux/io.h> | ||
| 20 | |||
| 21 | #if (defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE) && defined(JTAG_UART_BASE))\ | ||
| 22 | || (defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) && defined(UART0_BASE)) | ||
| 23 | static void *my_ioremap(unsigned long physaddr) | ||
| 24 | { | ||
| 25 | return (void *)(physaddr | CONFIG_NIOS2_IO_REGION_BASE); | ||
| 26 | } | ||
| 27 | #endif | ||
| 28 | |||
| 29 | #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE) && defined(JTAG_UART_BASE) | ||
| 30 | |||
| 31 | #define ALTERA_JTAGUART_SIZE 8 | ||
| 32 | #define ALTERA_JTAGUART_DATA_REG 0 | ||
| 33 | #define ALTERA_JTAGUART_CONTROL_REG 4 | ||
| 34 | #define ALTERA_JTAGUART_CONTROL_AC_MSK (0x00000400) | ||
| 35 | #define ALTERA_JTAGUART_CONTROL_WSPACE_MSK (0xFFFF0000) | ||
| 36 | static void *uartbase; | ||
| 37 | |||
| 38 | #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS) | ||
| 39 | static void jtag_putc(int ch) | ||
| 40 | { | ||
| 41 | if (readl(uartbase + ALTERA_JTAGUART_CONTROL_REG) & | ||
| 42 | ALTERA_JTAGUART_CONTROL_WSPACE_MSK) | ||
| 43 | writeb(ch, uartbase + ALTERA_JTAGUART_DATA_REG); | ||
| 44 | } | ||
| 45 | #else | ||
| 46 | static void jtag_putc(int ch) | ||
| 47 | { | ||
| 48 | while ((readl(uartbase + ALTERA_JTAGUART_CONTROL_REG) & | ||
| 49 | ALTERA_JTAGUART_CONTROL_WSPACE_MSK) == 0) | ||
| 50 | ; | ||
| 51 | writeb(ch, uartbase + ALTERA_JTAGUART_DATA_REG); | ||
| 52 | } | ||
| 53 | #endif | ||
| 54 | |||
| 55 | static int putchar(int ch) | ||
| 56 | { | ||
| 57 | jtag_putc(ch); | ||
| 58 | return ch; | ||
| 59 | } | ||
| 60 | |||
| 61 | static void console_init(void) | ||
| 62 | { | ||
| 63 | uartbase = my_ioremap((unsigned long) JTAG_UART_BASE); | ||
| 64 | writel(ALTERA_JTAGUART_CONTROL_AC_MSK, | ||
| 65 | uartbase + ALTERA_JTAGUART_CONTROL_REG); | ||
| 66 | } | ||
| 67 | |||
| 68 | #elif defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) && defined(UART0_BASE) | ||
| 69 | |||
| 70 | #define ALTERA_UART_SIZE 32 | ||
| 71 | #define ALTERA_UART_TXDATA_REG 4 | ||
| 72 | #define ALTERA_UART_STATUS_REG 8 | ||
| 73 | #define ALTERA_UART_DIVISOR_REG 16 | ||
| 74 | #define ALTERA_UART_STATUS_TRDY_MSK (0x40) | ||
| 75 | static unsigned uartbase; | ||
| 76 | |||
| 77 | static void uart_putc(int ch) | ||
| 78 | { | ||
| 79 | int i; | ||
| 80 | |||
| 81 | for (i = 0; (i < 0x10000); i++) { | ||
| 82 | if (readw(uartbase + ALTERA_UART_STATUS_REG) & | ||
| 83 | ALTERA_UART_STATUS_TRDY_MSK) | ||
| 84 | break; | ||
| 85 | } | ||
| 86 | writeb(ch, uartbase + ALTERA_UART_TXDATA_REG); | ||
| 87 | } | ||
| 88 | |||
| 89 | static int putchar(int ch) | ||
| 90 | { | ||
| 91 | uart_putc(ch); | ||
| 92 | if (ch == '\n') | ||
| 93 | uart_putc('\r'); | ||
| 94 | return ch; | ||
| 95 | } | ||
| 96 | |||
| 97 | static void console_init(void) | ||
| 98 | { | ||
| 99 | unsigned int baud, baudclk; | ||
| 100 | |||
| 101 | uartbase = (unsigned long) my_ioremap((unsigned long) UART0_BASE); | ||
| 102 | baud = CONFIG_SERIAL_ALTERA_UART_BAUDRATE; | ||
| 103 | baudclk = UART0_FREQ / baud; | ||
| 104 | writew(baudclk, uartbase + ALTERA_UART_DIVISOR_REG); | ||
| 105 | } | ||
| 106 | |||
| 107 | #else | ||
| 108 | |||
| 109 | static int putchar(int ch) | ||
| 110 | { | ||
| 111 | return ch; | ||
| 112 | } | ||
| 113 | |||
| 114 | static void console_init(void) | ||
| 115 | { | ||
| 116 | } | ||
| 117 | |||
| 118 | #endif | ||
| 119 | |||
| 120 | static int puts(const char *s) | ||
| 121 | { | ||
| 122 | while (*s) | ||
| 123 | putchar(*s++); | ||
| 124 | return 0; | ||
| 125 | } | ||
diff --git a/arch/nios2/boot/compressed/head.S b/arch/nios2/boot/compressed/head.S new file mode 100644 index 000000000000..15c6c48dd909 --- /dev/null +++ b/arch/nios2/boot/compressed/head.S | |||
| @@ -0,0 +1,117 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw> | ||
| 3 | * | ||
| 4 | * Based on arch/nios2/kernel/head.S | ||
| 5 | * | ||
| 6 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 7 | * License. See the file "COPYING" in the main directory of this archive | ||
| 8 | * for more details. | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | |||
| 12 | /* | ||
| 13 | * This code can be loaded anywhere, eg FLASH ROM as reset vector, | ||
| 14 | * as long as output does not overlap it. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/linkage.h> | ||
| 18 | #include <asm/cache.h> | ||
| 19 | |||
| 20 | .text | ||
| 21 | .set noat | ||
| 22 | ENTRY(_start) | ||
| 23 | wrctl status, r0 /* disable interrupt */ | ||
| 24 | /* invalidate all instruction cache */ | ||
| 25 | movia r1, NIOS2_ICACHE_SIZE | ||
| 26 | movui r2, NIOS2_ICACHE_LINE_SIZE | ||
| 27 | 1: initi r1 | ||
| 28 | sub r1, r1, r2 | ||
| 29 | bgt r1, r0, 1b | ||
| 30 | /* invalidate all data cache */ | ||
| 31 | movia r1, NIOS2_DCACHE_SIZE | ||
| 32 | movui r2, NIOS2_DCACHE_LINE_SIZE | ||
| 33 | 1: initd 0(r1) | ||
| 34 | sub r1, r1, r2 | ||
| 35 | bgt r1, r0, 1b | ||
| 36 | |||
| 37 | nextpc r1 /* Find out where we are */ | ||
| 38 | chkadr: | ||
| 39 | movia r2, chkadr | ||
| 40 | beq r1, r2, finish_move /* We are running in correct address, | ||
| 41 | done */ | ||
| 42 | /* move code, r1: src, r2: dest, r3: last dest */ | ||
| 43 | addi r1, r1, (_start - chkadr) /* Source */ | ||
| 44 | movia r2, _start /* Destination */ | ||
| 45 | movia r3, __bss_start /* End of copy */ | ||
| 46 | 1: ldw r8, 0(r1) /* load a word from [r1] */ | ||
| 47 | stw r8, 0(r2) /* stort a word to dest [r2] */ | ||
| 48 | addi r1, r1, 4 /* inc the src addr */ | ||
| 49 | addi r2, r2, 4 /* inc the dest addr */ | ||
| 50 | blt r2, r3, 1b | ||
| 51 | /* flush the data cache after moving */ | ||
| 52 | movia r1, NIOS2_DCACHE_SIZE | ||
| 53 | movui r2, NIOS2_DCACHE_LINE_SIZE | ||
| 54 | 1: flushd 0(r1) | ||
| 55 | sub r1, r1, r2 | ||
| 56 | bgt r1, r0, 1b | ||
| 57 | movia r1, finish_move | ||
| 58 | jmp r1 /* jmp to linked address */ | ||
| 59 | |||
| 60 | finish_move: | ||
| 61 | /* zero out the .bss segment (uninitialized common data) */ | ||
| 62 | movia r2, __bss_start /* presume nothing is between */ | ||
| 63 | movia r1, _end /* the .bss and _end. */ | ||
| 64 | 1: stb r0, 0(r2) | ||
| 65 | addi r2, r2, 1 | ||
| 66 | bne r1, r2, 1b | ||
| 67 | /* | ||
| 68 | * set up the stack pointer, some where higher than _end. | ||
| 69 | * The stack space must be greater than 32K for decompress. | ||
| 70 | */ | ||
| 71 | movia sp, 0x10000 | ||
| 72 | add sp, sp, r1 | ||
| 73 | /* save args passed from u-boot, maybe */ | ||
| 74 | addi sp, sp, -16 | ||
| 75 | stw r4, 0(sp) | ||
| 76 | stw r5, 4(sp) | ||
| 77 | stw r6, 8(sp) | ||
| 78 | stw r7, 12(sp) | ||
| 79 | /* decompress the kernel */ | ||
| 80 | call decompress_kernel | ||
| 81 | /* pass saved args to kernel */ | ||
| 82 | ldw r4, 0(sp) | ||
| 83 | ldw r5, 4(sp) | ||
| 84 | ldw r6, 8(sp) | ||
| 85 | ldw r7, 12(sp) | ||
| 86 | |||
| 87 | /* flush all data cache after decompressing */ | ||
| 88 | movia r1, NIOS2_DCACHE_SIZE | ||
| 89 | movui r2, NIOS2_DCACHE_LINE_SIZE | ||
| 90 | 1: flushd 0(r1) | ||
| 91 | sub r1, r1, r2 | ||
| 92 | bgt r1, r0, 1b | ||
| 93 | /* flush all instruction cache */ | ||
| 94 | movia r1, NIOS2_ICACHE_SIZE | ||
| 95 | movui r2, NIOS2_ICACHE_LINE_SIZE | ||
| 96 | 1: flushi r1 | ||
| 97 | sub r1, r1, r2 | ||
| 98 | bgt r1, r0, 1b | ||
| 99 | flushp | ||
| 100 | /* jump to start real kernel */ | ||
| 101 | movia r1, (CONFIG_NIOS2_MEM_BASE | CONFIG_NIOS2_KERNEL_REGION_BASE) | ||
| 102 | jmp r1 | ||
| 103 | |||
| 104 | .balign 512 | ||
| 105 | fake_headers_as_bzImage: | ||
| 106 | .short 0 | ||
| 107 | .ascii "HdrS" | ||
| 108 | .short 0x0202 | ||
| 109 | .short 0 | ||
| 110 | .short 0 | ||
| 111 | .byte 0x00, 0x10 | ||
| 112 | .short 0 | ||
| 113 | .byte 0 | ||
| 114 | .byte 1 | ||
| 115 | .byte 0x00, 0x80 | ||
| 116 | .long 0 | ||
| 117 | .long 0 | ||
diff --git a/arch/nios2/boot/compressed/misc.c b/arch/nios2/boot/compressed/misc.c new file mode 100644 index 000000000000..84377825ef1a --- /dev/null +++ b/arch/nios2/boot/compressed/misc.c | |||
| @@ -0,0 +1,187 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw> | ||
| 3 | * | ||
| 4 | * This is a collection of several routines from gzip-1.0.3 | ||
| 5 | * adapted for Linux. | ||
| 6 | * | ||
| 7 | * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 | ||
| 8 | * | ||
| 9 | * Adapted for SH by Stuart Menefy, Aug 1999 | ||
| 10 | * | ||
| 11 | * Modified to use standard LinuxSH BIOS by Greg Banks 7Jul2000 | ||
| 12 | * | ||
| 13 | * Based on arch/sh/boot/compressed/misc.c | ||
| 14 | * | ||
| 15 | * This program is free software; you can redistribute it and/or modify | ||
| 16 | * it under the terms of the GNU General Public License as published by | ||
| 17 | * the Free Software Foundation; either version 2 of the License, or | ||
| 18 | * (at your option) any later version. | ||
| 19 | * | ||
| 20 | * This program is distributed in the hope that it will be useful, | ||
| 21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 23 | * GNU General Public License for more details. | ||
| 24 | * | ||
| 25 | * You should have received a copy of the GNU General Public License | ||
| 26 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 27 | * | ||
| 28 | */ | ||
| 29 | |||
| 30 | #include <linux/string.h> | ||
| 31 | |||
| 32 | /* | ||
| 33 | * gzip declarations | ||
| 34 | */ | ||
| 35 | #define OF(args) args | ||
| 36 | #define STATIC static | ||
| 37 | |||
| 38 | #undef memset | ||
| 39 | #undef memcpy | ||
| 40 | #define memzero(s, n) memset((s), 0, (n)) | ||
| 41 | |||
| 42 | typedef unsigned char uch; | ||
| 43 | typedef unsigned short ush; | ||
| 44 | typedef unsigned long ulg; | ||
| 45 | #define WSIZE 0x8000 /* Window size must be at least 32k, */ | ||
| 46 | /* and a power of two */ | ||
| 47 | |||
| 48 | static uch *inbuf; /* input buffer */ | ||
| 49 | static uch window[WSIZE]; /* Sliding window buffer */ | ||
| 50 | |||
| 51 | static unsigned insize; /* valid bytes in inbuf */ | ||
| 52 | static unsigned inptr; /* index of next byte to be processed in inbuf */ | ||
| 53 | static unsigned outcnt; /* bytes in output buffer */ | ||
| 54 | |||
| 55 | /* gzip flag byte */ | ||
| 56 | #define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ | ||
| 57 | #define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip | ||
| 58 | file */ | ||
| 59 | #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ | ||
| 60 | #define ORIG_NAME 0x08 /* bit 3 set: original file name present */ | ||
| 61 | #define COMMENT 0x10 /* bit 4 set: file comment present */ | ||
| 62 | #define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ | ||
| 63 | #define RESERVED 0xC0 /* bit 6,7: reserved */ | ||
| 64 | |||
| 65 | #define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) | ||
| 66 | |||
| 67 | #ifdef DEBUG | ||
| 68 | # define Assert(cond, msg) {if (!(cond)) error(msg); } | ||
| 69 | # define Trace(x) fprintf x | ||
| 70 | # define Tracev(x) {if (verbose) fprintf x ; } | ||
| 71 | # define Tracevv(x) {if (verbose > 1) fprintf x ; } | ||
| 72 | # define Tracec(c, x) {if (verbose && (c)) fprintf x ; } | ||
| 73 | # define Tracecv(c, x) {if (verbose > 1 && (c)) fprintf x ; } | ||
| 74 | #else | ||
| 75 | # define Assert(cond, msg) | ||
| 76 | # define Trace(x) | ||
| 77 | # define Tracev(x) | ||
| 78 | # define Tracevv(x) | ||
| 79 | # define Tracec(c, x) | ||
| 80 | # define Tracecv(c, x) | ||
| 81 | #endif | ||
| 82 | static int fill_inbuf(void); | ||
| 83 | static void flush_window(void); | ||
| 84 | static void error(char *m); | ||
| 85 | |||
| 86 | extern char input_data[]; | ||
| 87 | extern int input_len; | ||
| 88 | |||
| 89 | static long bytes_out; | ||
| 90 | static uch *output_data; | ||
| 91 | static unsigned long output_ptr; | ||
| 92 | |||
| 93 | #include "console.c" | ||
| 94 | |||
| 95 | static void error(char *m); | ||
| 96 | |||
| 97 | int puts(const char *); | ||
| 98 | |||
| 99 | extern int _end; | ||
| 100 | static unsigned long free_mem_ptr; | ||
| 101 | static unsigned long free_mem_end_ptr; | ||
| 102 | |||
| 103 | #define HEAP_SIZE 0x10000 | ||
| 104 | |||
| 105 | #include "../../../../lib/inflate.c" | ||
| 106 | |||
| 107 | void *memset(void *s, int c, size_t n) | ||
| 108 | { | ||
| 109 | int i; | ||
| 110 | char *ss = (char *)s; | ||
| 111 | |||
| 112 | for (i = 0; i < n; i++) | ||
| 113 | ss[i] = c; | ||
| 114 | return s; | ||
| 115 | } | ||
| 116 | |||
| 117 | void *memcpy(void *__dest, __const void *__src, size_t __n) | ||
| 118 | { | ||
| 119 | int i; | ||
| 120 | char *d = (char *)__dest, *s = (char *)__src; | ||
| 121 | |||
| 122 | for (i = 0; i < __n; i++) | ||
| 123 | d[i] = s[i]; | ||
| 124 | return __dest; | ||
| 125 | } | ||
| 126 | |||
| 127 | /* | ||
| 128 | * Fill the input buffer. This is called only when the buffer is empty | ||
| 129 | * and at least one byte is really needed. | ||
| 130 | */ | ||
| 131 | static int fill_inbuf(void) | ||
| 132 | { | ||
| 133 | if (insize != 0) | ||
| 134 | error("ran out of input data"); | ||
| 135 | |||
| 136 | inbuf = input_data; | ||
| 137 | insize = input_len; | ||
| 138 | inptr = 1; | ||
| 139 | return inbuf[0]; | ||
| 140 | } | ||
| 141 | |||
| 142 | /* | ||
| 143 | * Write the output window window[0..outcnt-1] and update crc and bytes_out. | ||
| 144 | * (Used for the decompressed data only.) | ||
| 145 | */ | ||
| 146 | static void flush_window(void) | ||
| 147 | { | ||
| 148 | ulg c = crc; /* temporary variable */ | ||
| 149 | unsigned n; | ||
| 150 | uch *in, *out, ch; | ||
| 151 | |||
| 152 | in = window; | ||
| 153 | out = &output_data[output_ptr]; | ||
| 154 | for (n = 0; n < outcnt; n++) { | ||
| 155 | ch = *out++ = *in++; | ||
| 156 | c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); | ||
| 157 | } | ||
| 158 | crc = c; | ||
| 159 | bytes_out += (ulg)outcnt; | ||
| 160 | output_ptr += (ulg)outcnt; | ||
| 161 | outcnt = 0; | ||
| 162 | } | ||
| 163 | |||
| 164 | static void error(char *x) | ||
| 165 | { | ||
| 166 | puts("\nERROR\n"); | ||
| 167 | puts(x); | ||
| 168 | puts("\n\n -- System halted"); | ||
| 169 | |||
| 170 | while (1) /* Halt */ | ||
| 171 | ; | ||
| 172 | } | ||
| 173 | |||
| 174 | void decompress_kernel(void) | ||
| 175 | { | ||
| 176 | output_data = (void *) (CONFIG_NIOS2_MEM_BASE | | ||
| 177 | CONFIG_NIOS2_KERNEL_REGION_BASE); | ||
| 178 | output_ptr = 0; | ||
| 179 | free_mem_ptr = (unsigned long)&_end; | ||
| 180 | free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; | ||
| 181 | |||
| 182 | console_init(); | ||
| 183 | makecrc(); | ||
| 184 | puts("Uncompressing Linux... "); | ||
| 185 | gunzip(); | ||
| 186 | puts("Ok, booting the kernel.\n"); | ||
| 187 | } | ||
diff --git a/arch/nios2/boot/compressed/vmlinux.lds.S b/arch/nios2/boot/compressed/vmlinux.lds.S new file mode 100644 index 000000000000..e867b3756059 --- /dev/null +++ b/arch/nios2/boot/compressed/vmlinux.lds.S | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw> | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License as published by | ||
| 6 | * the Free Software Foundation; either version 2 of the License, or | ||
| 7 | * (at your option) any later version. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License | ||
| 15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | * | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include <asm-generic/vmlinux.lds.h> | ||
| 20 | |||
| 21 | OUTPUT_FORMAT("elf32-littlenios2", "elf32-littlenios2", "elf32-littlenios2") | ||
| 22 | |||
| 23 | OUTPUT_ARCH(nios) | ||
| 24 | ENTRY(_start) /* Defined in head.S */ | ||
| 25 | |||
| 26 | SECTIONS | ||
| 27 | { | ||
| 28 | . = (CONFIG_NIOS2_MEM_BASE + CONFIG_NIOS2_BOOT_LINK_OFFSET) | \ | ||
| 29 | CONFIG_NIOS2_KERNEL_REGION_BASE; | ||
| 30 | |||
| 31 | _text = .; | ||
| 32 | .text : { *(.text) } = 0 | ||
| 33 | .rodata : { *(.rodata) *(.rodata.*) } | ||
| 34 | _etext = .; | ||
| 35 | |||
| 36 | . = ALIGN(32 / 8); | ||
| 37 | .data : { *(.data) } | ||
| 38 | . = ALIGN(32 / 8); | ||
| 39 | _got = .; | ||
| 40 | .got : { | ||
| 41 | *(.got.plt) | ||
| 42 | *(.igot.plt) | ||
| 43 | *(.got) | ||
| 44 | *(.igot) | ||
| 45 | } | ||
| 46 | _egot = .; | ||
| 47 | _edata = .; | ||
| 48 | |||
| 49 | . = ALIGN(32 / 8); | ||
| 50 | __bss_start = .; | ||
| 51 | .bss : { *(.bss) *(.sbss) } | ||
| 52 | . = ALIGN(32 / 8); | ||
| 53 | _ebss = .; | ||
| 54 | end = . ; | ||
| 55 | _end = . ; | ||
| 56 | |||
| 57 | got_len = (_egot - _got); | ||
| 58 | } | ||
diff --git a/arch/nios2/boot/compressed/vmlinux.scr b/arch/nios2/boot/compressed/vmlinux.scr new file mode 100644 index 000000000000..28c42f1d127e --- /dev/null +++ b/arch/nios2/boot/compressed/vmlinux.scr | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw> | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License as published by | ||
| 6 | * the Free Software Foundation; either version 2 of the License, or | ||
| 7 | * (at your option) any later version. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License | ||
| 15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | * | ||
| 17 | */ | ||
| 18 | |||
| 19 | SECTIONS | ||
| 20 | { | ||
| 21 | .data : { | ||
| 22 | input_len = .; | ||
| 23 | LONG(input_data_end - input_data) input_data = .; | ||
| 24 | *(.data) | ||
| 25 | . = ALIGN(4); | ||
| 26 | input_data_end = .; | ||
| 27 | } | ||
| 28 | } | ||
diff --git a/arch/nios2/configs/3c120_defconfig b/arch/nios2/configs/3c120_defconfig index 87541f0a5d6e..9451940678a0 100644 --- a/arch/nios2/configs/3c120_defconfig +++ b/arch/nios2/configs/3c120_defconfig | |||
| @@ -22,6 +22,7 @@ CONFIG_NIOS2_DCACHE_SIZE=0x8000 | |||
| 22 | CONFIG_NIOS2_ICACHE_SIZE=0x8000 | 22 | CONFIG_NIOS2_ICACHE_SIZE=0x8000 |
| 23 | # CONFIG_NIOS2_CMDLINE_IGNORE_DTB is not set | 23 | # CONFIG_NIOS2_CMDLINE_IGNORE_DTB is not set |
| 24 | CONFIG_NIOS2_PASS_CMDLINE=y | 24 | CONFIG_NIOS2_PASS_CMDLINE=y |
| 25 | CONFIG_NIOS2_BOOT_LINK_OFFSET=0x00800000 | ||
| 25 | CONFIG_NET=y | 26 | CONFIG_NET=y |
| 26 | CONFIG_PACKET=y | 27 | CONFIG_PACKET=y |
| 27 | CONFIG_UNIX=y | 28 | CONFIG_UNIX=y |
diff --git a/arch/nios2/include/asm/kgdb.h b/arch/nios2/include/asm/kgdb.h new file mode 100644 index 000000000000..8fd5e3b66c57 --- /dev/null +++ b/arch/nios2/include/asm/kgdb.h | |||
| @@ -0,0 +1,93 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2015 Altera Corporation | ||
| 3 | * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch> | ||
| 4 | * | ||
| 5 | * Based on the code posted by Kazuyasu on the Altera Forum at: | ||
| 6 | * http://www.alteraforum.com/forum/showpost.php?p=77003&postcount=20 | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 20 | * | ||
| 21 | */ | ||
| 22 | |||
| 23 | #ifndef _ASM_NIOS2_KGDB_H | ||
| 24 | #define _ASM_NIOS2_KGDB_H | ||
| 25 | |||
| 26 | #define CACHE_FLUSH_IS_SAFE 1 | ||
| 27 | #define BUFMAX 2048 | ||
| 28 | |||
| 29 | enum regnames { | ||
| 30 | GDB_R0 = 0, | ||
| 31 | GDB_AT, | ||
| 32 | GDB_R2, | ||
| 33 | GDB_R3, | ||
| 34 | GDB_R4, | ||
| 35 | GDB_R5, | ||
| 36 | GDB_R6, | ||
| 37 | GDB_R7, | ||
| 38 | GDB_R8, | ||
| 39 | GDB_R9, | ||
| 40 | GDB_R10, | ||
| 41 | GDB_R11, | ||
| 42 | GDB_R12, | ||
| 43 | GDB_R13, | ||
| 44 | GDB_R14, | ||
| 45 | GDB_R15, | ||
| 46 | GDB_R16, | ||
| 47 | GDB_R17, | ||
| 48 | GDB_R18, | ||
| 49 | GDB_R19, | ||
| 50 | GDB_R20, | ||
| 51 | GDB_R21, | ||
| 52 | GDB_R22, | ||
| 53 | GDB_R23, | ||
| 54 | GDB_ET, | ||
| 55 | GDB_BT, | ||
| 56 | GDB_GP, | ||
| 57 | GDB_SP, | ||
| 58 | GDB_FP, | ||
| 59 | GDB_EA, | ||
| 60 | GDB_BA, | ||
| 61 | GDB_RA, | ||
| 62 | GDB_PC, | ||
| 63 | GDB_STATUS, | ||
| 64 | GDB_ESTATUS, | ||
| 65 | GDB_BSTATUS, | ||
| 66 | GDB_IENABLE, | ||
| 67 | GDB_IPENDING, | ||
| 68 | GDB_CPUID, | ||
| 69 | GDB_CTL6, | ||
| 70 | GDB_EXCEPTION, | ||
| 71 | GDB_PTEADDR, | ||
| 72 | GDB_TLBACC, | ||
| 73 | GDB_TLBMISC, | ||
| 74 | GDB_ECCINJ, | ||
| 75 | GDB_BADADDR, | ||
| 76 | GDB_CONFIG, | ||
| 77 | GDB_MPUBASE, | ||
| 78 | GDB_MPUACC, | ||
| 79 | /* do not change the last entry or anything below! */ | ||
| 80 | GDB_NUMREGBYTES /* number of registers */ | ||
| 81 | }; | ||
| 82 | |||
| 83 | #define GDB_SIZEOF_REG sizeof(u32) | ||
| 84 | #define DBG_MAX_REG_NUM (49) | ||
| 85 | #define NUMREGBYTES (DBG_MAX_REG_NUM * sizeof(GDB_SIZEOF_REG)) | ||
| 86 | |||
| 87 | #define BREAK_INSTR_SIZE 4 | ||
| 88 | static inline void arch_kgdb_breakpoint(void) | ||
| 89 | { | ||
| 90 | __asm__ __volatile__("trap 30\n"); | ||
| 91 | } | ||
| 92 | |||
| 93 | #endif /* _ASM_NIOS2_KGDB_H */ | ||
diff --git a/arch/nios2/include/asm/processor.h b/arch/nios2/include/asm/processor.h index 3bd349473b06..c2ba45c159c7 100644 --- a/arch/nios2/include/asm/processor.h +++ b/arch/nios2/include/asm/processor.h | |||
| @@ -85,9 +85,6 @@ static inline void exit_thread(void) | |||
| 85 | 85 | ||
| 86 | extern unsigned long get_wchan(struct task_struct *p); | 86 | extern unsigned long get_wchan(struct task_struct *p); |
| 87 | 87 | ||
| 88 | /* Prepare to copy thread state - unlazy all lazy status */ | ||
| 89 | #define prepare_to_copy(tsk) do { } while (0) | ||
| 90 | |||
| 91 | #define task_pt_regs(p) \ | 88 | #define task_pt_regs(p) \ |
| 92 | ((struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1) | 89 | ((struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1) |
| 93 | 90 | ||
diff --git a/arch/nios2/include/asm/prom.h b/arch/nios2/include/asm/prom.h new file mode 100644 index 000000000000..75fffb42cfa5 --- /dev/null +++ b/arch/nios2/include/asm/prom.h | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | /* | ||
| 2 | * Copyright Altera Corporation (C) <2015>. All rights reserved | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify it | ||
| 5 | * under the terms and conditions of the GNU General Public License, | ||
| 6 | * version 2, as published by the Free Software Foundation. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 11 | * more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License along with | ||
| 14 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef __ASM_NIOS2_PROM_H__ | ||
| 18 | #define __ASM_NIOS2_PROM_H__ | ||
| 19 | |||
| 20 | extern unsigned long __init of_early_console(void); | ||
| 21 | |||
| 22 | #endif | ||
diff --git a/arch/nios2/kernel/Makefile b/arch/nios2/kernel/Makefile index 8ae76823ff93..1aae25703657 100644 --- a/arch/nios2/kernel/Makefile +++ b/arch/nios2/kernel/Makefile | |||
| @@ -20,5 +20,7 @@ obj-y += syscall_table.o | |||
| 20 | obj-y += time.o | 20 | obj-y += time.o |
| 21 | obj-y += traps.o | 21 | obj-y += traps.o |
| 22 | 22 | ||
| 23 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | ||
| 24 | obj-$(CONFIG_KGDB) += kgdb.o | ||
| 23 | obj-$(CONFIG_MODULES) += module.o | 25 | obj-$(CONFIG_MODULES) += module.o |
| 24 | obj-$(CONFIG_NIOS2_ALIGNMENT_TRAP) += misaligned.o | 26 | obj-$(CONFIG_NIOS2_ALIGNMENT_TRAP) += misaligned.o |
diff --git a/arch/nios2/kernel/early_printk.c b/arch/nios2/kernel/early_printk.c new file mode 100644 index 000000000000..c08e4c1486fc --- /dev/null +++ b/arch/nios2/kernel/early_printk.c | |||
| @@ -0,0 +1,118 @@ | |||
| 1 | /* | ||
| 2 | * Early printk for Nios2. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2015, Altera Corporation | ||
| 5 | * Copyright (C) 2010, Tobias Klauser <tklauser@distanz.ch> | ||
| 6 | * Copyright (C) 2009, Wind River Systems Inc | ||
| 7 | * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com | ||
| 8 | * | ||
| 9 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 10 | * License. See the file "COPYING" in the main directory of this archive | ||
| 11 | * for more details. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/console.h> | ||
| 15 | #include <linux/init.h> | ||
| 16 | #include <linux/kernel.h> | ||
| 17 | #include <linux/io.h> | ||
| 18 | |||
| 19 | #include <asm/prom.h> | ||
| 20 | |||
| 21 | static unsigned long base_addr; | ||
| 22 | |||
| 23 | #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE) | ||
| 24 | |||
| 25 | #define ALTERA_JTAGUART_DATA_REG 0 | ||
| 26 | #define ALTERA_JTAGUART_CONTROL_REG 4 | ||
| 27 | #define ALTERA_JTAGUART_CONTROL_WSPACE_MSK 0xFFFF0000 | ||
| 28 | #define ALTERA_JTAGUART_CONTROL_AC_MSK 0x00000400 | ||
| 29 | |||
| 30 | #define JUART_GET_CR() \ | ||
| 31 | __builtin_ldwio((void *)(base_addr + ALTERA_JTAGUART_CONTROL_REG)) | ||
| 32 | #define JUART_SET_CR(v) \ | ||
| 33 | __builtin_stwio((void *)(base_addr + ALTERA_JTAGUART_CONTROL_REG), v) | ||
| 34 | #define JUART_SET_TX(v) \ | ||
| 35 | __builtin_stwio((void *)(base_addr + ALTERA_JTAGUART_DATA_REG), v) | ||
| 36 | |||
| 37 | static void early_console_write(struct console *con, const char *s, unsigned n) | ||
| 38 | { | ||
| 39 | unsigned long status; | ||
| 40 | |||
| 41 | while (n-- && *s) { | ||
| 42 | while (((status = JUART_GET_CR()) | ||
| 43 | & ALTERA_JTAGUART_CONTROL_WSPACE_MSK) == 0) { | ||
| 44 | #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS) | ||
| 45 | if ((status & ALTERA_JTAGUART_CONTROL_AC_MSK) == 0) | ||
| 46 | return; /* no connection activity */ | ||
| 47 | #endif | ||
| 48 | } | ||
| 49 | JUART_SET_TX(*s); | ||
| 50 | s++; | ||
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 54 | #elif defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) | ||
| 55 | |||
| 56 | #define ALTERA_UART_TXDATA_REG 4 | ||
| 57 | #define ALTERA_UART_STATUS_REG 8 | ||
| 58 | #define ALTERA_UART_STATUS_TRDY 0x0040 | ||
| 59 | |||
| 60 | #define UART_GET_SR() \ | ||
| 61 | __builtin_ldwio((void *)(base_addr + ALTERA_UART_STATUS_REG)) | ||
| 62 | #define UART_SET_TX(v) \ | ||
| 63 | __builtin_stwio((void *)(base_addr + ALTERA_UART_TXDATA_REG), v) | ||
| 64 | |||
| 65 | static void early_console_putc(char c) | ||
| 66 | { | ||
| 67 | while (!(UART_GET_SR() & ALTERA_UART_STATUS_TRDY)) | ||
| 68 | ; | ||
| 69 | |||
| 70 | UART_SET_TX(c); | ||
| 71 | } | ||
| 72 | |||
| 73 | static void early_console_write(struct console *con, const char *s, unsigned n) | ||
| 74 | { | ||
| 75 | while (n-- && *s) { | ||
| 76 | early_console_putc(*s); | ||
| 77 | if (*s == '\n') | ||
| 78 | early_console_putc('\r'); | ||
| 79 | s++; | ||
| 80 | } | ||
| 81 | } | ||
| 82 | |||
| 83 | #else | ||
| 84 | # error Neither SERIAL_ALTERA_JTAGUART_CONSOLE nor SERIAL_ALTERA_UART_CONSOLE \ | ||
| 85 | selected | ||
| 86 | #endif | ||
| 87 | |||
| 88 | static struct console early_console_prom = { | ||
| 89 | .name = "early", | ||
| 90 | .write = early_console_write, | ||
| 91 | .flags = CON_PRINTBUFFER | CON_BOOT, | ||
| 92 | .index = -1 | ||
| 93 | }; | ||
| 94 | |||
| 95 | void __init setup_early_printk(void) | ||
| 96 | { | ||
| 97 | #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE) || \ | ||
| 98 | defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) | ||
| 99 | base_addr = of_early_console(); | ||
| 100 | #else | ||
| 101 | base_addr = 0; | ||
| 102 | #endif | ||
| 103 | |||
| 104 | if (!base_addr) | ||
| 105 | return; | ||
| 106 | |||
| 107 | #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS) | ||
| 108 | /* Clear activity bit so BYPASS doesn't stall if we've used JTAG for | ||
| 109 | * downloading the kernel. This might cause early data to be lost even | ||
| 110 | * if the JTAG terminal is running. | ||
| 111 | */ | ||
| 112 | JUART_SET_CR(JUART_GET_CR() | ALTERA_JTAGUART_CONTROL_AC_MSK); | ||
| 113 | #endif | ||
| 114 | |||
| 115 | early_console = &early_console_prom; | ||
| 116 | register_console(early_console); | ||
| 117 | pr_info("early_console initialized at 0x%08lx\n", base_addr); | ||
| 118 | } | ||
diff --git a/arch/nios2/kernel/entry.S b/arch/nios2/kernel/entry.S index 0bdfd13ff98b..7729bd3f2e79 100644 --- a/arch/nios2/kernel/entry.S +++ b/arch/nios2/kernel/entry.S | |||
| @@ -121,7 +121,11 @@ trap_table: | |||
| 121 | .word instruction_trap /* 27 */ | 121 | .word instruction_trap /* 27 */ |
| 122 | .word instruction_trap /* 28 */ | 122 | .word instruction_trap /* 28 */ |
| 123 | .word instruction_trap /* 29 */ | 123 | .word instruction_trap /* 29 */ |
| 124 | .word instruction_trap /* 30 */ | 124 | #ifdef CONFIG_KGDB |
| 125 | .word handle_kgdb_breakpoint /* 30 KGDB breakpoint */ | ||
| 126 | #else | ||
| 127 | .word instruction_trap /* 30 */ | ||
| 128 | #endif | ||
| 125 | .word handle_breakpoint /* 31 */ | 129 | .word handle_breakpoint /* 31 */ |
| 126 | 130 | ||
| 127 | .text | 131 | .text |
| @@ -445,6 +449,12 @@ handle_diverror: | |||
| 445 | call handle_diverror_c | 449 | call handle_diverror_c |
| 446 | br ret_from_exception | 450 | br ret_from_exception |
| 447 | 451 | ||
| 452 | #ifdef CONFIG_KGDB | ||
| 453 | handle_kgdb_breakpoint: | ||
| 454 | call kgdb_breakpoint_c | ||
| 455 | br ret_from_exception | ||
| 456 | #endif | ||
| 457 | |||
| 448 | /* | 458 | /* |
| 449 | * Beware - when entering resume, prev (the current task) is | 459 | * Beware - when entering resume, prev (the current task) is |
| 450 | * in r4, next (the new task) is in r5, don't change these | 460 | * in r4, next (the new task) is in r5, don't change these |
diff --git a/arch/nios2/kernel/kgdb.c b/arch/nios2/kernel/kgdb.c new file mode 100644 index 000000000000..117859122d1c --- /dev/null +++ b/arch/nios2/kernel/kgdb.c | |||
| @@ -0,0 +1,171 @@ | |||
| 1 | /* | ||
| 2 | * Nios2 KGDB support | ||
| 3 | * | ||
| 4 | * Copyright (C) 2015 Altera Corporation | ||
| 5 | * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch> | ||
| 6 | * | ||
| 7 | * Based on the code posted by Kazuyasu on the Altera Forum at: | ||
| 8 | * http://www.alteraforum.com/forum/showpost.php?p=77003&postcount=20 | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License as published by | ||
| 12 | * the Free Software Foundation; either version 2 of the License, or | ||
| 13 | * (at your option) any later version. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, | ||
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | * GNU General Public License for more details. | ||
| 19 | * | ||
| 20 | * You should have received a copy of the GNU General Public License | ||
| 21 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 22 | * | ||
| 23 | */ | ||
| 24 | #include <linux/ptrace.h> | ||
| 25 | #include <linux/kgdb.h> | ||
| 26 | #include <linux/kdebug.h> | ||
| 27 | #include <linux/io.h> | ||
| 28 | |||
| 29 | static int wait_for_remote_debugger; | ||
| 30 | |||
| 31 | struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = | ||
| 32 | { | ||
| 33 | { "zero", GDB_SIZEOF_REG, -1 }, | ||
| 34 | { "at", GDB_SIZEOF_REG, offsetof(struct pt_regs, r1) }, | ||
| 35 | { "r2", GDB_SIZEOF_REG, offsetof(struct pt_regs, r2) }, | ||
| 36 | { "r3", GDB_SIZEOF_REG, offsetof(struct pt_regs, r3) }, | ||
| 37 | { "r4", GDB_SIZEOF_REG, offsetof(struct pt_regs, r4) }, | ||
| 38 | { "r5", GDB_SIZEOF_REG, offsetof(struct pt_regs, r5) }, | ||
| 39 | { "r6", GDB_SIZEOF_REG, offsetof(struct pt_regs, r6) }, | ||
| 40 | { "r7", GDB_SIZEOF_REG, offsetof(struct pt_regs, r7) }, | ||
| 41 | { "r8", GDB_SIZEOF_REG, offsetof(struct pt_regs, r8) }, | ||
| 42 | { "r9", GDB_SIZEOF_REG, offsetof(struct pt_regs, r9) }, | ||
| 43 | { "r10", GDB_SIZEOF_REG, offsetof(struct pt_regs, r10) }, | ||
| 44 | { "r11", GDB_SIZEOF_REG, offsetof(struct pt_regs, r11) }, | ||
| 45 | { "r12", GDB_SIZEOF_REG, offsetof(struct pt_regs, r12) }, | ||
| 46 | { "r13", GDB_SIZEOF_REG, offsetof(struct pt_regs, r13) }, | ||
| 47 | { "r14", GDB_SIZEOF_REG, offsetof(struct pt_regs, r14) }, | ||
| 48 | { "r15", GDB_SIZEOF_REG, offsetof(struct pt_regs, r15) }, | ||
| 49 | { "r16", GDB_SIZEOF_REG, -1 }, | ||
| 50 | { "r17", GDB_SIZEOF_REG, -1 }, | ||
| 51 | { "r18", GDB_SIZEOF_REG, -1 }, | ||
| 52 | { "r19", GDB_SIZEOF_REG, -1 }, | ||
| 53 | { "r20", GDB_SIZEOF_REG, -1 }, | ||
| 54 | { "r21", GDB_SIZEOF_REG, -1 }, | ||
| 55 | { "r22", GDB_SIZEOF_REG, -1 }, | ||
| 56 | { "r23", GDB_SIZEOF_REG, -1 }, | ||
| 57 | { "et", GDB_SIZEOF_REG, -1 }, | ||
| 58 | { "bt", GDB_SIZEOF_REG, -1 }, | ||
| 59 | { "gp", GDB_SIZEOF_REG, offsetof(struct pt_regs, gp) }, | ||
| 60 | { "sp", GDB_SIZEOF_REG, offsetof(struct pt_regs, sp) }, | ||
| 61 | { "fp", GDB_SIZEOF_REG, offsetof(struct pt_regs, fp) }, | ||
| 62 | { "ea", GDB_SIZEOF_REG, -1 }, | ||
| 63 | { "ba", GDB_SIZEOF_REG, -1 }, | ||
| 64 | { "ra", GDB_SIZEOF_REG, offsetof(struct pt_regs, ra) }, | ||
| 65 | { "pc", GDB_SIZEOF_REG, offsetof(struct pt_regs, ea) }, | ||
| 66 | { "status", GDB_SIZEOF_REG, -1 }, | ||
| 67 | { "estatus", GDB_SIZEOF_REG, offsetof(struct pt_regs, estatus) }, | ||
| 68 | { "bstatus", GDB_SIZEOF_REG, -1 }, | ||
| 69 | { "ienable", GDB_SIZEOF_REG, -1 }, | ||
| 70 | { "ipending", GDB_SIZEOF_REG, -1}, | ||
| 71 | { "cpuid", GDB_SIZEOF_REG, -1 }, | ||
| 72 | { "ctl6", GDB_SIZEOF_REG, -1 }, | ||
| 73 | { "exception", GDB_SIZEOF_REG, -1 }, | ||
| 74 | { "pteaddr", GDB_SIZEOF_REG, -1 }, | ||
| 75 | { "tlbacc", GDB_SIZEOF_REG, -1 }, | ||
| 76 | { "tlbmisc", GDB_SIZEOF_REG, -1 }, | ||
| 77 | { "eccinj", GDB_SIZEOF_REG, -1 }, | ||
| 78 | { "badaddr", GDB_SIZEOF_REG, -1 }, | ||
| 79 | { "config", GDB_SIZEOF_REG, -1 }, | ||
| 80 | { "mpubase", GDB_SIZEOF_REG, -1 }, | ||
| 81 | { "mpuacc", GDB_SIZEOF_REG, -1 }, | ||
| 82 | }; | ||
| 83 | |||
| 84 | char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs) | ||
| 85 | { | ||
| 86 | if (regno >= DBG_MAX_REG_NUM || regno < 0) | ||
| 87 | return NULL; | ||
| 88 | |||
| 89 | if (dbg_reg_def[regno].offset != -1) | ||
| 90 | memcpy(mem, (void *)regs + dbg_reg_def[regno].offset, | ||
| 91 | dbg_reg_def[regno].size); | ||
| 92 | else | ||
| 93 | memset(mem, 0, dbg_reg_def[regno].size); | ||
| 94 | |||
| 95 | return dbg_reg_def[regno].name; | ||
| 96 | } | ||
| 97 | |||
| 98 | int dbg_set_reg(int regno, void *mem, struct pt_regs *regs) | ||
| 99 | { | ||
| 100 | if (regno >= DBG_MAX_REG_NUM || regno < 0) | ||
| 101 | return -EINVAL; | ||
| 102 | |||
| 103 | if (dbg_reg_def[regno].offset != -1) | ||
| 104 | memcpy((void *)regs + dbg_reg_def[regno].offset, mem, | ||
| 105 | dbg_reg_def[regno].size); | ||
| 106 | |||
| 107 | return 0; | ||
| 108 | } | ||
| 109 | |||
| 110 | void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) | ||
| 111 | { | ||
| 112 | memset((char *)gdb_regs, 0, NUMREGBYTES); | ||
| 113 | gdb_regs[GDB_SP] = p->thread.kregs->sp; | ||
| 114 | gdb_regs[GDB_PC] = p->thread.kregs->ea; | ||
| 115 | } | ||
| 116 | |||
| 117 | void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc) | ||
| 118 | { | ||
| 119 | regs->ea = pc; | ||
| 120 | } | ||
| 121 | |||
| 122 | int kgdb_arch_handle_exception(int vector, int signo, int err_code, | ||
| 123 | char *remcom_in_buffer, char *remcom_out_buffer, | ||
| 124 | struct pt_regs *regs) | ||
| 125 | { | ||
| 126 | char *ptr; | ||
| 127 | unsigned long addr; | ||
| 128 | |||
| 129 | switch (remcom_in_buffer[0]) { | ||
| 130 | case 's': | ||
| 131 | case 'c': | ||
| 132 | /* handle the optional parameters */ | ||
| 133 | ptr = &remcom_in_buffer[1]; | ||
| 134 | if (kgdb_hex2long(&ptr, &addr)) | ||
| 135 | regs->ea = addr; | ||
| 136 | |||
| 137 | return 0; | ||
| 138 | } | ||
| 139 | |||
| 140 | return -1; /* this means that we do not want to exit from the handler */ | ||
| 141 | } | ||
| 142 | |||
| 143 | asmlinkage void kgdb_breakpoint_c(struct pt_regs *regs) | ||
| 144 | { | ||
| 145 | /* | ||
| 146 | * The breakpoint entry code has moved the PC on by 4 bytes, so we must | ||
| 147 | * move it back. This could be done on the host but we do it here | ||
| 148 | */ | ||
| 149 | if (!wait_for_remote_debugger) | ||
| 150 | regs->ea -= 4; | ||
| 151 | else /* pass the first trap 30 code */ | ||
| 152 | wait_for_remote_debugger = 0; | ||
| 153 | |||
| 154 | kgdb_handle_exception(30, SIGTRAP, 0, regs); | ||
| 155 | } | ||
| 156 | |||
| 157 | int kgdb_arch_init(void) | ||
| 158 | { | ||
| 159 | wait_for_remote_debugger = 1; | ||
| 160 | return 0; | ||
| 161 | } | ||
| 162 | |||
| 163 | void kgdb_arch_exit(void) | ||
| 164 | { | ||
| 165 | /* Nothing to do */ | ||
| 166 | } | ||
| 167 | |||
| 168 | struct kgdb_arch arch_kgdb_ops = { | ||
| 169 | /* Breakpoint instruction: trap 30 */ | ||
| 170 | .gdb_bpt_instr = { 0xba, 0x6f, 0x3b, 0x00 }, | ||
| 171 | }; | ||
diff --git a/arch/nios2/kernel/prom.c b/arch/nios2/kernel/prom.c index 0522d3378e3f..718dd197909f 100644 --- a/arch/nios2/kernel/prom.c +++ b/arch/nios2/kernel/prom.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Device tree support | 2 | * Device tree support |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2013 Altera Corporation | 4 | * Copyright (C) 2013, 2015 Altera Corporation |
| 5 | * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw> | 5 | * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw> |
| 6 | * | 6 | * |
| 7 | * Based on MIPS support for CONFIG_OF device tree support | 7 | * Based on MIPS support for CONFIG_OF device tree support |
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <linux/of_fdt.h> | 30 | #include <linux/of_fdt.h> |
| 31 | #include <linux/io.h> | 31 | #include <linux/io.h> |
| 32 | 32 | ||
| 33 | #include <asm/prom.h> | ||
| 33 | #include <asm/sections.h> | 34 | #include <asm/sections.h> |
| 34 | 35 | ||
| 35 | void __init early_init_dt_add_memory_arch(u64 base, u64 size) | 36 | void __init early_init_dt_add_memory_arch(u64 base, u64 size) |
| @@ -63,3 +64,52 @@ void __init early_init_devtree(void *params) | |||
| 63 | 64 | ||
| 64 | early_init_dt_scan(params); | 65 | early_init_dt_scan(params); |
| 65 | } | 66 | } |
| 67 | |||
| 68 | #ifdef CONFIG_EARLY_PRINTK | ||
| 69 | static int __init early_init_dt_scan_serial(unsigned long node, | ||
| 70 | const char *uname, int depth, void *data) | ||
| 71 | { | ||
| 72 | u64 *addr64 = (u64 *) data; | ||
| 73 | const char *p; | ||
| 74 | |||
| 75 | /* only consider serial nodes */ | ||
| 76 | if (strncmp(uname, "serial", 6) != 0) | ||
| 77 | return 0; | ||
| 78 | |||
| 79 | p = of_get_flat_dt_prop(node, "compatible", NULL); | ||
| 80 | if (!p) | ||
| 81 | return 0; | ||
| 82 | |||
| 83 | /* | ||
| 84 | * We found an altera_jtaguart but it wasn't configured for console, so | ||
| 85 | * skip it. | ||
| 86 | */ | ||
| 87 | #ifndef CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE | ||
| 88 | if (strncmp(p, "altr,juart", 10) == 0) | ||
| 89 | return 0; | ||
| 90 | #endif | ||
| 91 | |||
| 92 | /* | ||
| 93 | * Same for altera_uart. | ||
| 94 | */ | ||
| 95 | #ifndef CONFIG_SERIAL_ALTERA_UART_CONSOLE | ||
| 96 | if (strncmp(p, "altr,uart", 9) == 0) | ||
| 97 | return 0; | ||
| 98 | #endif | ||
| 99 | |||
| 100 | *addr64 = fdt_translate_address((const void *)initial_boot_params, | ||
| 101 | node); | ||
| 102 | |||
| 103 | return *addr64 == OF_BAD_ADDR ? 0 : 1; | ||
| 104 | } | ||
| 105 | |||
| 106 | unsigned long __init of_early_console(void) | ||
| 107 | { | ||
| 108 | u64 base = 0; | ||
| 109 | |||
| 110 | if (of_scan_flat_dt(early_init_dt_scan_serial, &base)) | ||
| 111 | return (u32)ioremap(base, 32); | ||
| 112 | else | ||
| 113 | return 0; | ||
| 114 | } | ||
| 115 | #endif /* CONFIG_EARLY_PRINTK */ | ||
diff --git a/arch/nios2/kernel/setup.c b/arch/nios2/kernel/setup.c index cb3121f975d4..b101a43d3c5a 100644 --- a/arch/nios2/kernel/setup.c +++ b/arch/nios2/kernel/setup.c | |||
| @@ -139,6 +139,10 @@ void __init setup_arch(char **cmdline_p) | |||
| 139 | 139 | ||
| 140 | console_verbose(); | 140 | console_verbose(); |
| 141 | 141 | ||
| 142 | #ifdef CONFIG_EARLY_PRINTK | ||
| 143 | setup_early_printk(); | ||
| 144 | #endif | ||
| 145 | |||
| 142 | memory_start = PAGE_ALIGN((unsigned long)__pa(_end)); | 146 | memory_start = PAGE_ALIGN((unsigned long)__pa(_end)); |
| 143 | memory_end = (unsigned long) CONFIG_NIOS2_MEM_BASE + memory_size; | 147 | memory_end = (unsigned long) CONFIG_NIOS2_MEM_BASE + memory_size; |
| 144 | 148 | ||
diff --git a/arch/nios2/mm/fault.c b/arch/nios2/mm/fault.c index d194c0427b26..0d231adfe576 100644 --- a/arch/nios2/mm/fault.c +++ b/arch/nios2/mm/fault.c | |||
| @@ -47,7 +47,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long cause, | |||
| 47 | struct mm_struct *mm = tsk->mm; | 47 | struct mm_struct *mm = tsk->mm; |
| 48 | int code = SEGV_MAPERR; | 48 | int code = SEGV_MAPERR; |
| 49 | int fault; | 49 | int fault; |
| 50 | unsigned int flags = 0; | 50 | unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; |
| 51 | 51 | ||
| 52 | cause >>= 2; | 52 | cause >>= 2; |
| 53 | 53 | ||
| @@ -86,6 +86,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long cause, | |||
| 86 | if (!down_read_trylock(&mm->mmap_sem)) { | 86 | if (!down_read_trylock(&mm->mmap_sem)) { |
| 87 | if (!user_mode(regs) && !search_exception_tables(regs->ea)) | 87 | if (!user_mode(regs) && !search_exception_tables(regs->ea)) |
| 88 | goto bad_area_nosemaphore; | 88 | goto bad_area_nosemaphore; |
| 89 | retry: | ||
| 89 | down_read(&mm->mmap_sem); | 90 | down_read(&mm->mmap_sem); |
| 90 | } | 91 | } |
| 91 | 92 | ||
| @@ -132,6 +133,10 @@ survive: | |||
| 132 | * the fault. | 133 | * the fault. |
| 133 | */ | 134 | */ |
| 134 | fault = handle_mm_fault(mm, vma, address, flags); | 135 | fault = handle_mm_fault(mm, vma, address, flags); |
| 136 | |||
| 137 | if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) | ||
| 138 | return; | ||
| 139 | |||
| 135 | if (unlikely(fault & VM_FAULT_ERROR)) { | 140 | if (unlikely(fault & VM_FAULT_ERROR)) { |
| 136 | if (fault & VM_FAULT_OOM) | 141 | if (fault & VM_FAULT_OOM) |
| 137 | goto out_of_memory; | 142 | goto out_of_memory; |
| @@ -141,10 +146,32 @@ survive: | |||
| 141 | goto do_sigbus; | 146 | goto do_sigbus; |
| 142 | BUG(); | 147 | BUG(); |
| 143 | } | 148 | } |
| 144 | if (fault & VM_FAULT_MAJOR) | 149 | |
| 145 | tsk->maj_flt++; | 150 | /* |
| 146 | else | 151 | * Major/minor page fault accounting is only done on the |
| 147 | tsk->min_flt++; | 152 | * initial attempt. If we go through a retry, it is extremely |
| 153 | * likely that the page will be found in page cache at that point. | ||
| 154 | */ | ||
| 155 | if (flags & FAULT_FLAG_ALLOW_RETRY) { | ||
| 156 | if (fault & VM_FAULT_MAJOR) | ||
| 157 | current->maj_flt++; | ||
| 158 | else | ||
| 159 | current->min_flt++; | ||
| 160 | if (fault & VM_FAULT_RETRY) { | ||
| 161 | /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk | ||
| 162 | * of starvation. */ | ||
| 163 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | ||
| 164 | flags |= FAULT_FLAG_TRIED; | ||
| 165 | |||
| 166 | /* | ||
| 167 | * No need to up_read(&mm->mmap_sem) as we would | ||
| 168 | * have already released it in __lock_page_or_retry | ||
| 169 | * in mm/filemap.c. | ||
| 170 | */ | ||
| 171 | |||
| 172 | goto retry; | ||
| 173 | } | ||
| 174 | } | ||
| 148 | 175 | ||
| 149 | up_read(&mm->mmap_sem); | 176 | up_read(&mm->mmap_sem); |
| 150 | return; | 177 | return; |
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index 1554a6f2a5bb..8014727a2743 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig | |||
| @@ -291,10 +291,6 @@ config SYSVIPC_COMPAT | |||
| 291 | config AUDIT_ARCH | 291 | config AUDIT_ARCH |
| 292 | def_bool y | 292 | def_bool y |
| 293 | 293 | ||
| 294 | config HPUX | ||
| 295 | bool "Support for HP-UX binaries" | ||
| 296 | depends on !64BIT | ||
| 297 | |||
| 298 | config NR_CPUS | 294 | config NR_CPUS |
| 299 | int "Maximum number of CPUs (2-32)" | 295 | int "Maximum number of CPUs (2-32)" |
| 300 | range 2 32 | 296 | range 2 32 |
diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile index 5db8882f732c..91fbb6ee702c 100644 --- a/arch/parisc/Makefile +++ b/arch/parisc/Makefile | |||
| @@ -84,7 +84,6 @@ head-y := arch/parisc/kernel/head.o | |||
| 84 | KBUILD_CFLAGS += $(cflags-y) | 84 | KBUILD_CFLAGS += $(cflags-y) |
| 85 | 85 | ||
| 86 | kernel-y := mm/ kernel/ math-emu/ | 86 | kernel-y := mm/ kernel/ math-emu/ |
| 87 | kernel-$(CONFIG_HPUX) += hpux/ | ||
| 88 | 87 | ||
| 89 | core-y += $(addprefix arch/parisc/, $(kernel-y)) | 88 | core-y += $(addprefix arch/parisc/, $(kernel-y)) |
| 90 | libs-y += arch/parisc/lib/ $(LIBGCC) | 89 | libs-y += arch/parisc/lib/ $(LIBGCC) |
diff --git a/arch/parisc/hpux/Makefile b/arch/parisc/hpux/Makefile deleted file mode 100644 index 1048fb69f06d..000000000000 --- a/arch/parisc/hpux/Makefile +++ /dev/null | |||
| @@ -1,5 +0,0 @@ | |||
| 1 | # | ||
| 2 | # Makefile for HPUX emulation | ||
| 3 | # | ||
| 4 | |||
| 5 | obj-y := entry_hpux.o gate.o wrappers.o fs.o ioctl.o sys_hpux.o | ||
diff --git a/arch/parisc/hpux/entry_hpux.S b/arch/parisc/hpux/entry_hpux.S deleted file mode 100644 index d15a413572f0..000000000000 --- a/arch/parisc/hpux/entry_hpux.S +++ /dev/null | |||
| @@ -1,546 +0,0 @@ | |||
| 1 | /* syscall table for HPUX specific syscalls | ||
| 2 | * | ||
| 3 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 4 | * Copyright (C) 1999 Matthew Wilcox <willy at debian . org> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <asm/unistd.h> | ||
| 22 | #include <asm/assembly.h> | ||
| 23 | #include <linux/sys.h> | ||
| 24 | #include <linux/linkage.h> | ||
| 25 | |||
| 26 | #define ENTRY_NAME(_name_) ASM_ULONG_INSN _name_ | ||
| 27 | |||
| 28 | .section .rodata,"a" | ||
| 29 | .import hpux_unimplemented_wrapper | ||
| 30 | ENTRY(hpux_call_table) | ||
| 31 | ENTRY_NAME(sys_ni_syscall) /* 0 */ | ||
| 32 | ENTRY_NAME(sys_exit) | ||
| 33 | ENTRY_NAME(hpux_fork_wrapper) | ||
| 34 | ENTRY_NAME(sys_read) | ||
| 35 | ENTRY_NAME(sys_write) | ||
| 36 | ENTRY_NAME(sys_open) /* 5 */ | ||
| 37 | ENTRY_NAME(sys_close) | ||
| 38 | ENTRY_NAME(hpux_wait) | ||
| 39 | ENTRY_NAME(sys_creat) | ||
| 40 | ENTRY_NAME(sys_link) | ||
| 41 | ENTRY_NAME(sys_unlink) /* 10 */ | ||
| 42 | ENTRY_NAME(hpux_execv_wrapper) | ||
| 43 | ENTRY_NAME(sys_chdir) | ||
| 44 | ENTRY_NAME(sys_time) | ||
| 45 | ENTRY_NAME(sys_mknod) | ||
| 46 | ENTRY_NAME(sys_chmod) /* 15 */ | ||
| 47 | ENTRY_NAME(sys_chown) | ||
| 48 | ENTRY_NAME(hpux_brk) | ||
| 49 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 50 | ENTRY_NAME(sys_lseek) | ||
| 51 | ENTRY_NAME(sys_getpid) /* 20 */ | ||
| 52 | ENTRY_NAME(hpux_mount) | ||
| 53 | ENTRY_NAME(sys_oldumount) | ||
| 54 | ENTRY_NAME(sys_setuid) | ||
| 55 | ENTRY_NAME(sys_getuid) | ||
| 56 | ENTRY_NAME(sys_stime) /* 25 */ | ||
| 57 | ENTRY_NAME(hpux_ptrace) | ||
| 58 | ENTRY_NAME(sys_alarm) | ||
| 59 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 60 | ENTRY_NAME(sys_pause) | ||
| 61 | ENTRY_NAME(sys_utime) /* 30 */ | ||
| 62 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 63 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 64 | ENTRY_NAME(sys_access) | ||
| 65 | ENTRY_NAME(hpux_nice) | ||
| 66 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 35 */ | ||
| 67 | ENTRY_NAME(sys_sync) | ||
| 68 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 69 | ENTRY_NAME(sys_newstat) | ||
| 70 | ENTRY_NAME(hpux_setpgrp3) | ||
| 71 | ENTRY_NAME(sys_newlstat) /* 40 */ | ||
| 72 | ENTRY_NAME(sys_dup) | ||
| 73 | ENTRY_NAME(hpux_pipe_wrapper) | ||
| 74 | ENTRY_NAME(sys_times) | ||
| 75 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 76 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 45 */ | ||
| 77 | ENTRY_NAME(sys_setgid) | ||
| 78 | ENTRY_NAME(sys_getgid) | ||
| 79 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 80 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 81 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 50 */ | ||
| 82 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 83 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 84 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 85 | ENTRY_NAME(hpux_ioctl) | ||
| 86 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 55 */ | ||
| 87 | ENTRY_NAME(sys_symlink) | ||
| 88 | ENTRY_NAME(hpux_utssys) | ||
| 89 | ENTRY_NAME(sys_readlink) | ||
| 90 | ENTRY_NAME(hpux_execve_wrapper) | ||
| 91 | ENTRY_NAME(sys_umask) /* 60 */ | ||
| 92 | ENTRY_NAME(sys_chroot) | ||
| 93 | ENTRY_NAME(sys_fcntl) | ||
| 94 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 95 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 96 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 65 */ | ||
| 97 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 98 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 99 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 100 | ENTRY_NAME(hpux_sbrk) | ||
| 101 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 70 */ | ||
| 102 | ENTRY_NAME(sys_mmap) | ||
| 103 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 104 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 105 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 106 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 75 */ | ||
| 107 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 108 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 109 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 110 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 111 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 80 */ | ||
| 112 | ENTRY_NAME(sys_getpgid) | ||
| 113 | ENTRY_NAME(sys_setpgid) | ||
| 114 | ENTRY_NAME(sys_setitimer) | ||
| 115 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 116 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 85 */ | ||
| 117 | ENTRY_NAME(sys_getitimer) | ||
| 118 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 119 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 120 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 121 | ENTRY_NAME(sys_dup2) /* 90 */ | ||
| 122 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 123 | ENTRY_NAME(sys_newfstat) | ||
| 124 | ENTRY_NAME(sys_select) | ||
| 125 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 126 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 95 */ | ||
| 127 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 128 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 129 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 130 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 131 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 100 */ | ||
| 132 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 133 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 134 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 135 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 136 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 105 */ | ||
| 137 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 138 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 139 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 140 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 141 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 110 */ | ||
| 142 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 143 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 144 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 145 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 146 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 115 */ | ||
| 147 | ENTRY_NAME(sys_gettimeofday) | ||
| 148 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 149 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 150 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 151 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 120 */ | ||
| 152 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 153 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 154 | ENTRY_NAME(sys_fchown) | ||
| 155 | ENTRY_NAME(sys_fchmod) | ||
| 156 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 125 */ | ||
| 157 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 158 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 159 | ENTRY_NAME(sys_rename) | ||
| 160 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 161 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 130 */ | ||
| 162 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 163 | ENTRY_NAME(hpux_sysconf) | ||
| 164 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 165 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 166 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 135 */ | ||
| 167 | ENTRY_NAME(sys_mkdir) | ||
| 168 | ENTRY_NAME(sys_rmdir) | ||
| 169 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 170 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 171 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 140 */ | ||
| 172 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 173 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 174 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 175 | ENTRY_NAME(sys_getrlimit) | ||
| 176 | ENTRY_NAME(sys_setrlimit) /* 145 */ | ||
| 177 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 178 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 179 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 180 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 181 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 150 */ | ||
| 182 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 183 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 184 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 185 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 186 | ENTRY_NAME(hpux_lockf) /* 155 */ | ||
| 187 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 188 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 189 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 190 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 191 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 160 */ | ||
| 192 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 193 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 194 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 195 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 196 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 165 */ | ||
| 197 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 198 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 199 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 200 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 201 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 170 */ | ||
| 202 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 203 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 204 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 205 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 206 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 175 */ | ||
| 207 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 208 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 209 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 210 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 211 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 180 */ | ||
| 212 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 213 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 214 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 215 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 216 | ENTRY_NAME(sys_sigprocmask) /* 185 */ | ||
| 217 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 218 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 219 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 220 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 221 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 190 */ | ||
| 222 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 223 | ENTRY_NAME(hpux_getdomainname) | ||
| 224 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 225 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 226 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 195 */ | ||
| 227 | ENTRY_NAME(hpux_statfs) | ||
| 228 | ENTRY_NAME(hpux_fstatfs) | ||
| 229 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 230 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 231 | ENTRY_NAME(sys_waitpid) /* 200 */ | ||
| 232 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 233 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 234 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 235 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 236 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 205 */ | ||
| 237 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 238 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 239 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 240 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 241 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 210 */ | ||
| 242 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 243 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 244 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 245 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 246 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 215 */ | ||
| 247 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 248 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 249 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 250 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 251 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 220 */ | ||
| 252 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 253 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 254 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 255 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 256 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 225 */ | ||
| 257 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 258 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 259 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 260 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 261 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 230 */ | ||
| 262 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 263 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 264 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 265 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 266 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 235 */ | ||
| 267 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 268 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 269 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 270 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 271 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 240 */ | ||
| 272 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 273 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 274 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 275 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 276 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 245 */ | ||
| 277 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 278 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 279 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 280 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 281 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 250 */ | ||
| 282 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 283 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 284 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 285 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 286 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 255 */ | ||
| 287 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 288 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 289 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 290 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 291 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 260 */ | ||
| 292 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 293 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 294 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 295 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 296 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 265 */ | ||
| 297 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 298 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 299 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 300 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 301 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 270 */ | ||
| 302 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 303 | ENTRY_NAME(sys_fchdir) | ||
| 304 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 305 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 306 | ENTRY_NAME(sys_accept) /* 275 */ | ||
| 307 | ENTRY_NAME(sys_bind) | ||
| 308 | ENTRY_NAME(sys_connect) | ||
| 309 | ENTRY_NAME(sys_getpeername) | ||
| 310 | ENTRY_NAME(sys_getsockname) | ||
| 311 | ENTRY_NAME(sys_getsockopt) /* 280 */ | ||
| 312 | ENTRY_NAME(sys_listen) | ||
| 313 | ENTRY_NAME(sys_recv) | ||
| 314 | ENTRY_NAME(sys_recvfrom) | ||
| 315 | ENTRY_NAME(sys_recvmsg) | ||
| 316 | ENTRY_NAME(sys_send) /* 285 */ | ||
| 317 | ENTRY_NAME(sys_sendmsg) | ||
| 318 | ENTRY_NAME(sys_sendto) | ||
| 319 | ENTRY_NAME(sys_setsockopt) | ||
| 320 | ENTRY_NAME(sys_shutdown) | ||
| 321 | ENTRY_NAME(sys_socket) /* 290 */ | ||
| 322 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 323 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 324 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 325 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 326 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 295 */ | ||
| 327 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 328 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 329 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 330 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 331 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 300 */ | ||
| 332 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 333 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 334 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 335 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 336 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 305 */ | ||
| 337 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 338 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 339 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 340 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 341 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 310 */ | ||
| 342 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 343 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 344 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 345 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 346 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 315 */ | ||
| 347 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 348 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 349 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 350 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 351 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 320 */ | ||
| 352 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 353 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 354 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 355 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 356 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 325 */ | ||
| 357 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 358 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 359 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 360 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 361 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 330 */ | ||
| 362 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 363 | ENTRY_NAME(sys_lchown) | ||
| 364 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 365 | ENTRY_NAME(hpux_sysfs) | ||
| 366 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 335 */ | ||
| 367 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 368 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 369 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 370 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 371 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 340 */ | ||
| 372 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 373 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 374 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 375 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 376 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 345 */ | ||
| 377 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 378 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 379 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 380 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 381 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 350 */ | ||
| 382 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 383 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 384 | ENTRY_NAME(sys_nanosleep) | ||
| 385 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 386 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 355 */ | ||
| 387 | ENTRY_NAME(hpux_getdents) | ||
| 388 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 389 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 390 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 391 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 360 */ | ||
| 392 | ENTRY_NAME(hpux_fstat64) | ||
| 393 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 394 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 395 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 396 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 365 */ | ||
| 397 | ENTRY_NAME(hpux_lstat64) | ||
| 398 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 399 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 400 | ENTRY_NAME(hpux_stat64) | ||
| 401 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 370 */ | ||
| 402 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 403 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 404 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 405 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 406 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 375 */ | ||
| 407 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 408 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 409 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 410 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 411 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 380 */ | ||
| 412 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 413 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 414 | ENTRY_NAME(hpux_setpgrp) | ||
| 415 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 416 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 385 */ | ||
| 417 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 418 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 419 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 420 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 421 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 390 */ | ||
| 422 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 423 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 424 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 425 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 426 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 395 */ | ||
| 427 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 428 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 429 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 430 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 431 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 400 */ | ||
| 432 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 433 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 434 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 435 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 436 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 405 */ | ||
| 437 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 438 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 439 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 440 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 441 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 410 */ | ||
| 442 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 443 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 444 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 445 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 446 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 415 */ | ||
| 447 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 448 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 449 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 450 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 451 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 420 */ | ||
| 452 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 453 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 454 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 455 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 456 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 425 */ | ||
| 457 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 458 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 459 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 460 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 461 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 430 */ | ||
| 462 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 463 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 464 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 465 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 466 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 435 */ | ||
| 467 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 468 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 469 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 470 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 471 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 440 */ | ||
| 472 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 473 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 474 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 475 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 476 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 445 */ | ||
| 477 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 478 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 479 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 480 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 481 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 450 */ | ||
| 482 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 483 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 484 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 485 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 486 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 455 */ | ||
| 487 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 488 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 489 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 490 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 491 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 460 */ | ||
| 492 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 493 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 494 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 495 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 496 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 465 */ | ||
| 497 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 498 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 499 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 500 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 501 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 470 */ | ||
| 502 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 503 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 504 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 505 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 506 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 475 */ | ||
| 507 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 508 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 509 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 510 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 511 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 480 */ | ||
| 512 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 513 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 514 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 515 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 516 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 485 */ | ||
| 517 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 518 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 519 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 520 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 521 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 490 */ | ||
| 522 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 523 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 524 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 525 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 526 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 495 */ | ||
| 527 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 528 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 529 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 530 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 531 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 500 */ | ||
| 532 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 533 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 534 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 535 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 536 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 505 */ | ||
| 537 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 538 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 539 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 540 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 541 | ENTRY_NAME(hpux_unimplemented_wrapper) /* 510 */ | ||
| 542 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 543 | ENTRY_NAME(hpux_unimplemented_wrapper) | ||
| 544 | END(hpux_call_table) | ||
| 545 | .end | ||
| 546 | |||
diff --git a/arch/parisc/hpux/fs.c b/arch/parisc/hpux/fs.c deleted file mode 100644 index 97a7bf8df348..000000000000 --- a/arch/parisc/hpux/fs.c +++ /dev/null | |||
| @@ -1,192 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Implements HPUX syscalls. | ||
| 3 | * | ||
| 4 | * Copyright (C) 1999 Matthew Wilcox <willy with parisc-linux.org> | ||
| 5 | * Copyright (C) 2000 Michael Ang <mang with subcarrier.org> | ||
| 6 | * Copyright (C) 2000 John Marvin <jsm with parisc-linux.org> | ||
| 7 | * Copyright (C) 2000 Philipp Rumpf | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License as published by | ||
| 11 | * the Free Software Foundation; either version 2 of the License, or | ||
| 12 | * (at your option) any later version. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License | ||
| 20 | * along with this program; if not, write to the Free Software | ||
| 21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <linux/kernel.h> | ||
| 25 | #include <linux/mm.h> | ||
| 26 | #include <linux/fs.h> | ||
| 27 | #include <linux/sched.h> | ||
| 28 | #include <linux/file.h> | ||
| 29 | #include <linux/ptrace.h> | ||
| 30 | #include <linux/slab.h> | ||
| 31 | #include <asm/errno.h> | ||
| 32 | #include <asm/uaccess.h> | ||
| 33 | |||
| 34 | int hpux_execve(struct pt_regs *regs) | ||
| 35 | { | ||
| 36 | return do_execve(getname((const char __user *) regs->gr[26]), | ||
| 37 | (const char __user *const __user *) regs->gr[25], | ||
| 38 | (const char __user *const __user *) regs->gr[24]); | ||
| 39 | } | ||
| 40 | |||
| 41 | struct hpux_dirent { | ||
| 42 | loff_t d_off; | ||
| 43 | ino_t d_ino; | ||
| 44 | short d_reclen; | ||
| 45 | short d_namlen; | ||
| 46 | char d_name[1]; | ||
| 47 | }; | ||
| 48 | |||
| 49 | struct getdents_callback { | ||
| 50 | struct dir_context ctx; | ||
| 51 | struct hpux_dirent __user *current_dir; | ||
| 52 | struct hpux_dirent __user *previous; | ||
| 53 | int count; | ||
| 54 | int error; | ||
| 55 | }; | ||
| 56 | |||
| 57 | #define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de))) | ||
| 58 | |||
| 59 | static int filldir(struct dir_context *ctx, const char *name, int namlen, | ||
| 60 | loff_t offset, u64 ino, unsigned d_type) | ||
| 61 | { | ||
| 62 | struct hpux_dirent __user * dirent; | ||
| 63 | struct getdents_callback *buf = | ||
| 64 | container_of(ctx, struct getdents_callback, ctx); | ||
| 65 | ino_t d_ino; | ||
| 66 | int reclen = ALIGN(NAME_OFFSET(dirent) + namlen + 1, sizeof(long)); | ||
| 67 | |||
| 68 | buf->error = -EINVAL; /* only used if we fail.. */ | ||
| 69 | if (reclen > buf->count) | ||
| 70 | return -EINVAL; | ||
| 71 | d_ino = ino; | ||
| 72 | if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { | ||
| 73 | buf->error = -EOVERFLOW; | ||
| 74 | return -EOVERFLOW; | ||
| 75 | } | ||
| 76 | dirent = buf->previous; | ||
| 77 | if (dirent) | ||
| 78 | if (put_user(offset, &dirent->d_off)) | ||
| 79 | goto Efault; | ||
| 80 | dirent = buf->current_dir; | ||
| 81 | if (put_user(d_ino, &dirent->d_ino) || | ||
| 82 | put_user(reclen, &dirent->d_reclen) || | ||
| 83 | put_user(namlen, &dirent->d_namlen) || | ||
| 84 | copy_to_user(dirent->d_name, name, namlen) || | ||
| 85 | put_user(0, dirent->d_name + namlen)) | ||
| 86 | goto Efault; | ||
| 87 | buf->previous = dirent; | ||
| 88 | buf->current_dir = (void __user *)dirent + reclen; | ||
| 89 | buf->count -= reclen; | ||
| 90 | return 0; | ||
| 91 | Efault: | ||
| 92 | buf->error = -EFAULT; | ||
| 93 | return -EFAULT; | ||
| 94 | } | ||
| 95 | |||
| 96 | #undef NAME_OFFSET | ||
| 97 | |||
| 98 | int hpux_getdents(unsigned int fd, struct hpux_dirent __user *dirent, unsigned int count) | ||
| 99 | { | ||
| 100 | struct fd arg; | ||
| 101 | struct hpux_dirent __user * lastdirent; | ||
| 102 | struct getdents_callback buf = { | ||
| 103 | .ctx.actor = filldir, | ||
| 104 | .current_dir = dirent, | ||
| 105 | .count = count | ||
| 106 | }; | ||
| 107 | int error; | ||
| 108 | |||
| 109 | arg = fdget(fd); | ||
| 110 | if (!arg.file) | ||
| 111 | return -EBADF; | ||
| 112 | |||
| 113 | error = iterate_dir(arg.file, &buf.ctx); | ||
| 114 | if (error >= 0) | ||
| 115 | error = buf.error; | ||
| 116 | lastdirent = buf.previous; | ||
| 117 | if (lastdirent) { | ||
| 118 | if (put_user(buf.ctx.pos, &lastdirent->d_off)) | ||
| 119 | error = -EFAULT; | ||
| 120 | else | ||
| 121 | error = count - buf.count; | ||
| 122 | } | ||
| 123 | |||
| 124 | fdput(arg); | ||
| 125 | return error; | ||
| 126 | } | ||
| 127 | |||
| 128 | int hpux_mount(const char *fs, const char *path, int mflag, | ||
| 129 | const char *fstype, const char *dataptr, int datalen) | ||
| 130 | { | ||
| 131 | return -ENOSYS; | ||
| 132 | } | ||
| 133 | |||
| 134 | static int cp_hpux_stat(struct kstat *stat, struct hpux_stat64 __user *statbuf) | ||
| 135 | { | ||
| 136 | struct hpux_stat64 tmp; | ||
| 137 | |||
| 138 | /* we probably want a different split here - is hpux 12:20? */ | ||
| 139 | |||
| 140 | if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev)) | ||
| 141 | return -EOVERFLOW; | ||
| 142 | |||
| 143 | memset(&tmp, 0, sizeof(tmp)); | ||
| 144 | tmp.st_dev = new_encode_dev(stat->dev); | ||
| 145 | tmp.st_ino = stat->ino; | ||
| 146 | tmp.st_mode = stat->mode; | ||
| 147 | tmp.st_nlink = stat->nlink; | ||
| 148 | tmp.st_uid = from_kuid_munged(current_user_ns(), stat->uid); | ||
| 149 | tmp.st_gid = from_kgid_munged(current_user_ns(), stat->gid); | ||
| 150 | tmp.st_rdev = new_encode_dev(stat->rdev); | ||
| 151 | tmp.st_size = stat->size; | ||
| 152 | tmp.st_atime = stat->atime.tv_sec; | ||
| 153 | tmp.st_mtime = stat->mtime.tv_sec; | ||
| 154 | tmp.st_ctime = stat->ctime.tv_sec; | ||
| 155 | tmp.st_blocks = stat->blocks; | ||
| 156 | tmp.st_blksize = stat->blksize; | ||
| 157 | return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; | ||
| 158 | } | ||
| 159 | |||
| 160 | long hpux_stat64(const char __user *filename, struct hpux_stat64 __user *statbuf) | ||
| 161 | { | ||
| 162 | struct kstat stat; | ||
| 163 | int error = vfs_stat(filename, &stat); | ||
| 164 | |||
| 165 | if (!error) | ||
| 166 | error = cp_hpux_stat(&stat, statbuf); | ||
| 167 | |||
| 168 | return error; | ||
| 169 | } | ||
| 170 | |||
| 171 | long hpux_fstat64(unsigned int fd, struct hpux_stat64 __user *statbuf) | ||
| 172 | { | ||
| 173 | struct kstat stat; | ||
| 174 | int error = vfs_fstat(fd, &stat); | ||
| 175 | |||
| 176 | if (!error) | ||
| 177 | error = cp_hpux_stat(&stat, statbuf); | ||
| 178 | |||
| 179 | return error; | ||
| 180 | } | ||
| 181 | |||
| 182 | long hpux_lstat64(const char __user *filename, | ||
| 183 | struct hpux_stat64 __user *statbuf) | ||
| 184 | { | ||
| 185 | struct kstat stat; | ||
| 186 | int error = vfs_lstat(filename, &stat); | ||
| 187 | |||
| 188 | if (!error) | ||
| 189 | error = cp_hpux_stat(&stat, statbuf); | ||
| 190 | |||
| 191 | return error; | ||
| 192 | } | ||
diff --git a/arch/parisc/hpux/gate.S b/arch/parisc/hpux/gate.S deleted file mode 100644 index 011468857e98..000000000000 --- a/arch/parisc/hpux/gate.S +++ /dev/null | |||
| @@ -1,107 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * | ||
| 3 | * Linux/PARISC Project (http://www.parisc-linux.org/) | ||
| 4 | * | ||
| 5 | * System call entry code Copyright (c) Matthew Wilcox 1999 <willy@bofh.ai> | ||
| 6 | * Licensed under the GNU GPL. | ||
| 7 | * thanks to Philipp Rumpf, Mike Shaver and various others | ||
| 8 | * sorry about the wall, puffin.. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <asm/assembly.h> | ||
| 12 | #include <asm/asm-offsets.h> | ||
| 13 | #include <asm/unistd.h> | ||
| 14 | #include <asm/errno.h> | ||
| 15 | #include <linux/linkage.h> | ||
| 16 | |||
| 17 | .level LEVEL | ||
| 18 | .text | ||
| 19 | |||
| 20 | .import hpux_call_table | ||
| 21 | .import hpux_syscall_exit,code | ||
| 22 | |||
| 23 | .align PAGE_SIZE | ||
| 24 | ENTRY(hpux_gateway_page) | ||
| 25 | nop | ||
| 26 | #ifdef CONFIG_64BIT | ||
| 27 | #warning NEEDS WORK for 64-bit | ||
| 28 | #endif | ||
| 29 | ldw -64(%r30), %r29 ;! 8th argument | ||
| 30 | ldw -60(%r30), %r19 ;! 7th argument | ||
| 31 | ldw -56(%r30), %r20 ;! 6th argument | ||
| 32 | ldw -52(%r30), %r21 ;! 5th argument | ||
| 33 | gate .+8, %r0 /* become privileged */ | ||
| 34 | mtsp %r0,%sr4 /* get kernel space into sr4 */ | ||
| 35 | mtsp %r0,%sr5 /* get kernel space into sr5 */ | ||
| 36 | mtsp %r0,%sr6 /* get kernel space into sr6 */ | ||
| 37 | mfsp %sr7,%r1 /* save user sr7 */ | ||
| 38 | mtsp %r1,%sr3 /* and store it in sr3 */ | ||
| 39 | |||
| 40 | mtctl %r30,%cr28 | ||
| 41 | mfctl %cr30,%r1 | ||
| 42 | xor %r1,%r30,%r30 /* ye olde xor trick */ | ||
| 43 | xor %r1,%r30,%r1 | ||
| 44 | xor %r1,%r30,%r30 | ||
| 45 | ldo TASK_SZ_ALGN+FRAME_SIZE(%r30),%r30 /* set up kernel stack */ | ||
| 46 | |||
| 47 | /* N.B.: It is critical that we don't set sr7 to 0 until r30 | ||
| 48 | * contains a valid kernel stack pointer. It is also | ||
| 49 | * critical that we don't start using the kernel stack | ||
| 50 | * until after sr7 has been set to 0. | ||
| 51 | */ | ||
| 52 | |||
| 53 | mtsp %r0,%sr7 /* get kernel space into sr7 */ | ||
| 54 | STREG %r1,TASK_PT_GR30-TASK_SZ_ALGN-FRAME_SIZE(%r30) /* save usp */ | ||
| 55 | ldo -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr in %r1 */ | ||
| 56 | |||
| 57 | /* Save some registers for sigcontext and potential task | ||
| 58 | switch (see entry.S for the details of which ones are | ||
| 59 | saved/restored). TASK_PT_PSW is zeroed so we can see whether | ||
| 60 | a process is on a syscall or not. For an interrupt the real | ||
| 61 | PSW value is stored. This is needed for gdb and sys_ptrace. */ | ||
| 62 | STREG %r0, TASK_PT_PSW(%r1) | ||
| 63 | STREG %r2, TASK_PT_GR2(%r1) /* preserve rp */ | ||
| 64 | STREG %r19, TASK_PT_GR19(%r1) /* 7th argument */ | ||
| 65 | STREG %r20, TASK_PT_GR20(%r1) /* 6th argument */ | ||
| 66 | STREG %r21, TASK_PT_GR21(%r1) /* 5th argument */ | ||
| 67 | STREG %r22, TASK_PT_GR22(%r1) /* syscall # */ | ||
| 68 | STREG %r23, TASK_PT_GR23(%r1) /* 4th argument */ | ||
| 69 | STREG %r24, TASK_PT_GR24(%r1) /* 3rd argument */ | ||
| 70 | STREG %r25, TASK_PT_GR25(%r1) /* 2nd argument */ | ||
| 71 | STREG %r26, TASK_PT_GR26(%r1) /* 1st argument */ | ||
| 72 | STREG %r27, TASK_PT_GR27(%r1) /* user dp */ | ||
| 73 | STREG %r28, TASK_PT_GR28(%r1) /* return value 0 */ | ||
| 74 | STREG %r0, TASK_PT_ORIG_R28(%r1) /* don't prohibit restarts */ | ||
| 75 | STREG %r29, TASK_PT_GR29(%r1) /* 8th argument */ | ||
| 76 | STREG %r31, TASK_PT_GR31(%r1) /* preserve syscall return ptr */ | ||
| 77 | |||
| 78 | ldo TASK_PT_FR0(%r1), %r27 /* save fpregs from the kernel */ | ||
| 79 | save_fp %r27 /* or potential task switch */ | ||
| 80 | |||
| 81 | mfctl %cr11, %r27 /* i.e. SAR */ | ||
| 82 | STREG %r27, TASK_PT_SAR(%r1) | ||
| 83 | |||
| 84 | loadgp | ||
| 85 | |||
| 86 | stw %r21, -52(%r30) ;! 5th argument | ||
| 87 | stw %r20, -56(%r30) ;! 6th argument | ||
| 88 | stw %r19, -60(%r30) ;! 7th argument | ||
| 89 | stw %r29, -64(%r30) ;! 8th argument | ||
| 90 | |||
| 91 | ldil L%hpux_call_table, %r21 | ||
| 92 | ldo R%hpux_call_table(%r21), %r21 | ||
| 93 | comiclr,>>= __NR_HPUX_syscalls, %r22, %r0 | ||
| 94 | b,n syscall_nosys | ||
| 95 | LDREGX %r22(%r21), %r21 | ||
| 96 | ldil L%hpux_syscall_exit,%r2 | ||
| 97 | be 0(%sr7,%r21) | ||
| 98 | ldo R%hpux_syscall_exit(%r2),%r2 | ||
| 99 | |||
| 100 | syscall_nosys: | ||
| 101 | ldil L%hpux_syscall_exit,%r1 | ||
| 102 | be R%hpux_syscall_exit(%sr7,%r1) | ||
| 103 | ldo -ENOSYS(%r0),%r28 | ||
| 104 | ENDPROC(hpux_gateway_page) | ||
| 105 | |||
| 106 | .align PAGE_SIZE | ||
| 107 | ENTRY(end_hpux_gateway_page) | ||
diff --git a/arch/parisc/hpux/ioctl.c b/arch/parisc/hpux/ioctl.c deleted file mode 100644 index dede4765852e..000000000000 --- a/arch/parisc/hpux/ioctl.c +++ /dev/null | |||
| @@ -1,72 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Implements some necessary HPUX ioctls. | ||
| 3 | * | ||
| 4 | * Copyright (C) 1999-2002 Matthew Wilcox <willy with parisc-linux.org> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | /* | ||
| 22 | * Supported ioctls: | ||
| 23 | * TCGETA | ||
| 24 | * TCSETA | ||
| 25 | * TCSETAW | ||
| 26 | * TCSETAF | ||
| 27 | * TCSBRK | ||
| 28 | * TCXONC | ||
| 29 | * TCFLSH | ||
| 30 | * TIOCGWINSZ | ||
| 31 | * TIOCSWINSZ | ||
| 32 | * TIOCGPGRP | ||
| 33 | * TIOCSPGRP | ||
| 34 | */ | ||
| 35 | |||
| 36 | #include <linux/sched.h> | ||
| 37 | #include <linux/syscalls.h> | ||
| 38 | #include <asm/errno.h> | ||
| 39 | #include <asm/ioctl.h> | ||
| 40 | #include <asm/termios.h> | ||
| 41 | #include <asm/uaccess.h> | ||
| 42 | |||
| 43 | static int hpux_ioctl_t(int fd, unsigned long cmd, unsigned long arg) | ||
| 44 | { | ||
| 45 | int result = -EOPNOTSUPP; | ||
| 46 | int nr = _IOC_NR(cmd); | ||
| 47 | switch (nr) { | ||
| 48 | case 106: | ||
| 49 | result = sys_ioctl(fd, TIOCSWINSZ, arg); | ||
| 50 | break; | ||
| 51 | case 107: | ||
| 52 | result = sys_ioctl(fd, TIOCGWINSZ, arg); | ||
| 53 | break; | ||
| 54 | } | ||
| 55 | return result; | ||
| 56 | } | ||
| 57 | |||
| 58 | int hpux_ioctl(int fd, unsigned long cmd, unsigned long arg) | ||
| 59 | { | ||
| 60 | int result = -EOPNOTSUPP; | ||
| 61 | int type = _IOC_TYPE(cmd); | ||
| 62 | switch (type) { | ||
| 63 | case 'T': | ||
| 64 | /* Our structures are now compatible with HPUX's */ | ||
| 65 | result = sys_ioctl(fd, cmd, arg); | ||
| 66 | break; | ||
| 67 | case 't': | ||
| 68 | result = hpux_ioctl_t(fd, cmd, arg); | ||
| 69 | break; | ||
| 70 | } | ||
| 71 | return result; | ||
| 72 | } | ||
diff --git a/arch/parisc/hpux/sys_hpux.c b/arch/parisc/hpux/sys_hpux.c deleted file mode 100644 index e5c4da035810..000000000000 --- a/arch/parisc/hpux/sys_hpux.c +++ /dev/null | |||
| @@ -1,963 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Implements HPUX syscalls. | ||
| 3 | * | ||
| 4 | * Copyright (C) 1999 Matthew Wilcox <willy with parisc-linux.org> | ||
| 5 | * Copyright (C) 2000 Philipp Rumpf | ||
| 6 | * Copyright (C) 2000 John Marvin <jsm with parisc-linux.org> | ||
| 7 | * Copyright (C) 2000 Michael Ang <mang with subcarrier.org> | ||
| 8 | * Copyright (C) 2001 Nathan Neulinger <nneul at umr.edu> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License as published by | ||
| 12 | * the Free Software Foundation; either version 2 of the License, or | ||
| 13 | * (at your option) any later version. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, | ||
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | * GNU General Public License for more details. | ||
| 19 | * | ||
| 20 | * You should have received a copy of the GNU General Public License | ||
| 21 | * along with this program; if not, write to the Free Software | ||
| 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 23 | */ | ||
| 24 | |||
| 25 | #include <linux/capability.h> | ||
| 26 | #include <linux/file.h> | ||
| 27 | #include <linux/fs.h> | ||
| 28 | #include <linux/namei.h> | ||
| 29 | #include <linux/sched.h> | ||
| 30 | #include <linux/slab.h> | ||
| 31 | #include <linux/syscalls.h> | ||
| 32 | #include <linux/utsname.h> | ||
| 33 | #include <linux/vfs.h> | ||
| 34 | #include <linux/vmalloc.h> | ||
| 35 | |||
| 36 | #include <asm/errno.h> | ||
| 37 | #include <asm/pgalloc.h> | ||
| 38 | #include <asm/uaccess.h> | ||
| 39 | |||
| 40 | unsigned long hpux_brk(unsigned long addr) | ||
| 41 | { | ||
| 42 | /* Sigh. Looks like HP/UX libc relies on kernel bugs. */ | ||
| 43 | return sys_brk(addr + PAGE_SIZE); | ||
| 44 | } | ||
| 45 | |||
| 46 | int hpux_sbrk(void) | ||
| 47 | { | ||
| 48 | return -ENOSYS; | ||
| 49 | } | ||
| 50 | |||
| 51 | /* Random other syscalls */ | ||
| 52 | |||
| 53 | int hpux_nice(int priority_change) | ||
| 54 | { | ||
| 55 | return -ENOSYS; | ||
| 56 | } | ||
| 57 | |||
| 58 | int hpux_ptrace(void) | ||
| 59 | { | ||
| 60 | return -ENOSYS; | ||
| 61 | } | ||
| 62 | |||
| 63 | int hpux_wait(int __user *stat_loc) | ||
| 64 | { | ||
| 65 | return sys_waitpid(-1, stat_loc, 0); | ||
| 66 | } | ||
| 67 | |||
| 68 | int hpux_setpgrp(void) | ||
| 69 | { | ||
| 70 | return sys_setpgid(0,0); | ||
| 71 | } | ||
| 72 | |||
| 73 | int hpux_setpgrp3(void) | ||
| 74 | { | ||
| 75 | return hpux_setpgrp(); | ||
| 76 | } | ||
| 77 | |||
| 78 | #define _SC_CPU_VERSION 10001 | ||
| 79 | #define _SC_OPEN_MAX 4 | ||
| 80 | #define CPU_PA_RISC1_1 0x210 | ||
| 81 | |||
| 82 | int hpux_sysconf(int which) | ||
| 83 | { | ||
| 84 | switch (which) { | ||
| 85 | case _SC_CPU_VERSION: | ||
| 86 | return CPU_PA_RISC1_1; | ||
| 87 | case _SC_OPEN_MAX: | ||
| 88 | return INT_MAX; | ||
| 89 | default: | ||
| 90 | return -EINVAL; | ||
| 91 | } | ||
| 92 | } | ||
| 93 | |||
| 94 | /*****************************************************************************/ | ||
| 95 | |||
| 96 | #define HPUX_UTSLEN 9 | ||
| 97 | #define HPUX_SNLEN 15 | ||
| 98 | |||
| 99 | struct hpux_utsname { | ||
| 100 | char sysname[HPUX_UTSLEN]; | ||
| 101 | char nodename[HPUX_UTSLEN]; | ||
| 102 | char release[HPUX_UTSLEN]; | ||
| 103 | char version[HPUX_UTSLEN]; | ||
| 104 | char machine[HPUX_UTSLEN]; | ||
| 105 | char idnumber[HPUX_SNLEN]; | ||
| 106 | } ; | ||
| 107 | |||
| 108 | struct hpux_ustat { | ||
| 109 | int32_t f_tfree; /* total free (daddr_t) */ | ||
| 110 | u_int32_t f_tinode; /* total inodes free (ino_t) */ | ||
| 111 | char f_fname[6]; /* filsys name */ | ||
| 112 | char f_fpack[6]; /* filsys pack name */ | ||
| 113 | u_int32_t f_blksize; /* filsys block size (int) */ | ||
| 114 | }; | ||
| 115 | |||
| 116 | /* | ||
| 117 | * HPUX's utssys() call. It's a collection of miscellaneous functions, | ||
| 118 | * alas, so there's no nice way of splitting them up. | ||
| 119 | */ | ||
| 120 | |||
| 121 | /* This function is called from hpux_utssys(); HP-UX implements | ||
| 122 | * ustat() as an option to utssys(). | ||
| 123 | * | ||
| 124 | * Now, struct ustat on HP-UX is exactly the same as on Linux, except | ||
| 125 | * that it contains one addition field on the end, int32_t f_blksize. | ||
| 126 | * So, we could have written this function to just call the Linux | ||
| 127 | * sys_ustat(), (defined in linux/fs/super.c), and then just | ||
| 128 | * added this additional field to the user's structure. But I figure | ||
| 129 | * if we're gonna be digging through filesystem structures to get | ||
| 130 | * this, we might as well just do the whole enchilada all in one go. | ||
| 131 | * | ||
| 132 | * So, most of this function is almost identical to sys_ustat(). | ||
| 133 | * I have placed comments at the few lines changed or added, to | ||
| 134 | * aid in porting forward if and when sys_ustat() is changed from | ||
| 135 | * its form in kernel 2.2.5. | ||
| 136 | */ | ||
| 137 | static int hpux_ustat(dev_t dev, struct hpux_ustat __user *ubuf) | ||
| 138 | { | ||
| 139 | struct hpux_ustat tmp; /* Changed to hpux_ustat */ | ||
| 140 | struct kstatfs sbuf; | ||
| 141 | int err = vfs_ustat(dev, &sbuf); | ||
| 142 | if (err) | ||
| 143 | goto out; | ||
| 144 | |||
| 145 | memset(&tmp,0,sizeof(tmp)); | ||
| 146 | |||
| 147 | tmp.f_tfree = (int32_t)sbuf.f_bfree; | ||
| 148 | tmp.f_tinode = (u_int32_t)sbuf.f_ffree; | ||
| 149 | tmp.f_blksize = (u_int32_t)sbuf.f_bsize; /* Added this line */ | ||
| 150 | |||
| 151 | err = copy_to_user(ubuf, &tmp, sizeof(tmp)) ? -EFAULT : 0; | ||
| 152 | out: | ||
| 153 | return err; | ||
| 154 | } | ||
| 155 | |||
| 156 | /* | ||
| 157 | * Wrapper for hpux statfs call. At the moment, just calls the linux native one | ||
| 158 | * and ignores the extra fields at the end of the hpux statfs struct. | ||
| 159 | * | ||
| 160 | */ | ||
| 161 | |||
| 162 | typedef int32_t hpux_fsid_t[2]; /* file system ID type */ | ||
| 163 | typedef uint16_t hpux_site_t; | ||
| 164 | |||
| 165 | struct hpux_statfs { | ||
| 166 | int32_t f_type; /* type of info, zero for now */ | ||
| 167 | int32_t f_bsize; /* fundamental file system block size */ | ||
| 168 | int32_t f_blocks; /* total blocks in file system */ | ||
| 169 | int32_t f_bfree; /* free block in fs */ | ||
| 170 | int32_t f_bavail; /* free blocks avail to non-superuser */ | ||
| 171 | int32_t f_files; /* total file nodes in file system */ | ||
| 172 | int32_t f_ffree; /* free file nodes in fs */ | ||
| 173 | hpux_fsid_t f_fsid; /* file system ID */ | ||
| 174 | int32_t f_magic; /* file system magic number */ | ||
| 175 | int32_t f_featurebits; /* file system features */ | ||
| 176 | int32_t f_spare[4]; /* spare for later */ | ||
| 177 | hpux_site_t f_cnode; /* cluster node where mounted */ | ||
| 178 | int16_t f_pad; | ||
| 179 | }; | ||
| 180 | |||
| 181 | static int do_statfs_hpux(struct kstatfs *st, struct hpux_statfs __user *p) | ||
| 182 | { | ||
| 183 | struct hpux_statfs buf; | ||
| 184 | memset(&buf, 0, sizeof(buf)); | ||
| 185 | buf.f_type = st->f_type; | ||
| 186 | buf.f_bsize = st->f_bsize; | ||
| 187 | buf.f_blocks = st->f_blocks; | ||
| 188 | buf.f_bfree = st->f_bfree; | ||
| 189 | buf.f_bavail = st->f_bavail; | ||
| 190 | buf.f_files = st->f_files; | ||
| 191 | buf.f_ffree = st->f_ffree; | ||
| 192 | buf.f_fsid[0] = st->f_fsid.val[0]; | ||
| 193 | buf.f_fsid[1] = st->f_fsid.val[1]; | ||
| 194 | if (copy_to_user(p, &buf, sizeof(buf))) | ||
| 195 | return -EFAULT; | ||
| 196 | return 0; | ||
| 197 | } | ||
| 198 | |||
| 199 | /* hpux statfs */ | ||
| 200 | asmlinkage long hpux_statfs(const char __user *pathname, | ||
| 201 | struct hpux_statfs __user *buf) | ||
| 202 | { | ||
| 203 | struct kstatfs st; | ||
| 204 | int error = user_statfs(pathname, &st); | ||
| 205 | if (!error) | ||
| 206 | error = do_statfs_hpux(&st, buf); | ||
| 207 | return error; | ||
| 208 | } | ||
| 209 | |||
| 210 | asmlinkage long hpux_fstatfs(unsigned int fd, struct hpux_statfs __user * buf) | ||
| 211 | { | ||
| 212 | struct kstatfs st; | ||
| 213 | int error = fd_statfs(fd, &st); | ||
| 214 | if (!error) | ||
| 215 | error = do_statfs_hpux(&st, buf); | ||
| 216 | return error; | ||
| 217 | } | ||
| 218 | |||
| 219 | |||
| 220 | /* This function is called from hpux_utssys(); HP-UX implements | ||
| 221 | * uname() as an option to utssys(). | ||
| 222 | * | ||
| 223 | * The form of this function is pretty much copied from sys_olduname(), | ||
| 224 | * defined in linux/arch/i386/kernel/sys_i386.c. | ||
| 225 | */ | ||
| 226 | /* TODO: Are these put_user calls OK? Should they pass an int? | ||
| 227 | * (I copied it from sys_i386.c like this.) | ||
| 228 | */ | ||
| 229 | static int hpux_uname(struct hpux_utsname __user *name) | ||
| 230 | { | ||
| 231 | int error; | ||
| 232 | |||
| 233 | if (!name) | ||
| 234 | return -EFAULT; | ||
| 235 | if (!access_ok(VERIFY_WRITE,name,sizeof(struct hpux_utsname))) | ||
| 236 | return -EFAULT; | ||
| 237 | |||
| 238 | down_read(&uts_sem); | ||
| 239 | |||
| 240 | error = __copy_to_user(&name->sysname, &utsname()->sysname, | ||
| 241 | HPUX_UTSLEN - 1); | ||
| 242 | error |= __put_user(0, name->sysname + HPUX_UTSLEN - 1); | ||
| 243 | error |= __copy_to_user(&name->nodename, &utsname()->nodename, | ||
| 244 | HPUX_UTSLEN - 1); | ||
| 245 | error |= __put_user(0, name->nodename + HPUX_UTSLEN - 1); | ||
| 246 | error |= __copy_to_user(&name->release, &utsname()->release, | ||
| 247 | HPUX_UTSLEN - 1); | ||
| 248 | error |= __put_user(0, name->release + HPUX_UTSLEN - 1); | ||
| 249 | error |= __copy_to_user(&name->version, &utsname()->version, | ||
| 250 | HPUX_UTSLEN - 1); | ||
| 251 | error |= __put_user(0, name->version + HPUX_UTSLEN - 1); | ||
| 252 | error |= __copy_to_user(&name->machine, &utsname()->machine, | ||
| 253 | HPUX_UTSLEN - 1); | ||
| 254 | error |= __put_user(0, name->machine + HPUX_UTSLEN - 1); | ||
| 255 | |||
| 256 | up_read(&uts_sem); | ||
| 257 | |||
| 258 | /* HP-UX utsname has no domainname field. */ | ||
| 259 | |||
| 260 | /* TODO: Implement idnumber!!! */ | ||
| 261 | #if 0 | ||
| 262 | error |= __put_user(0,name->idnumber); | ||
| 263 | error |= __put_user(0,name->idnumber+HPUX_SNLEN-1); | ||
| 264 | #endif | ||
| 265 | |||
| 266 | error = error ? -EFAULT : 0; | ||
| 267 | |||
| 268 | return error; | ||
| 269 | } | ||
| 270 | |||
| 271 | /* Note: HP-UX just uses the old suser() function to check perms | ||
| 272 | * in this system call. We'll use capable(CAP_SYS_ADMIN). | ||
| 273 | */ | ||
| 274 | int hpux_utssys(char __user *ubuf, int n, int type) | ||
| 275 | { | ||
| 276 | int len; | ||
| 277 | int error; | ||
| 278 | switch( type ) { | ||
| 279 | case 0: | ||
| 280 | /* uname(): */ | ||
| 281 | return hpux_uname((struct hpux_utsname __user *)ubuf); | ||
| 282 | break ; | ||
| 283 | case 1: | ||
| 284 | /* Obsolete (used to be umask().) */ | ||
| 285 | return -EFAULT ; | ||
| 286 | break ; | ||
| 287 | case 2: | ||
| 288 | /* ustat(): */ | ||
| 289 | return hpux_ustat(new_decode_dev(n), | ||
| 290 | (struct hpux_ustat __user *)ubuf); | ||
| 291 | break; | ||
| 292 | case 3: | ||
| 293 | /* setuname(): | ||
| 294 | * | ||
| 295 | * On linux (unlike HP-UX), utsname.nodename | ||
| 296 | * is the same as the hostname. | ||
| 297 | * | ||
| 298 | * sys_sethostname() is defined in linux/kernel/sys.c. | ||
| 299 | */ | ||
| 300 | if (!capable(CAP_SYS_ADMIN)) | ||
| 301 | return -EPERM; | ||
| 302 | /* Unlike Linux, HP-UX returns an error if n==0: */ | ||
| 303 | if ( n <= 0 ) | ||
| 304 | return -EINVAL ; | ||
| 305 | /* Unlike Linux, HP-UX truncates it if n is too big: */ | ||
| 306 | len = (n <= __NEW_UTS_LEN) ? n : __NEW_UTS_LEN ; | ||
| 307 | return sys_sethostname(ubuf, len); | ||
| 308 | break ; | ||
| 309 | case 4: | ||
| 310 | /* sethostname(): | ||
| 311 | * | ||
| 312 | * sys_sethostname() is defined in linux/kernel/sys.c. | ||
| 313 | */ | ||
| 314 | if (!capable(CAP_SYS_ADMIN)) | ||
| 315 | return -EPERM; | ||
| 316 | /* Unlike Linux, HP-UX returns an error if n==0: */ | ||
| 317 | if ( n <= 0 ) | ||
| 318 | return -EINVAL ; | ||
| 319 | /* Unlike Linux, HP-UX truncates it if n is too big: */ | ||
| 320 | len = (n <= __NEW_UTS_LEN) ? n : __NEW_UTS_LEN ; | ||
| 321 | return sys_sethostname(ubuf, len); | ||
| 322 | break ; | ||
| 323 | case 5: | ||
| 324 | /* gethostname(): | ||
| 325 | * | ||
| 326 | * sys_gethostname() is defined in linux/kernel/sys.c. | ||
| 327 | */ | ||
| 328 | /* Unlike Linux, HP-UX returns an error if n==0: */ | ||
| 329 | if ( n <= 0 ) | ||
| 330 | return -EINVAL ; | ||
| 331 | return sys_gethostname(ubuf, n); | ||
| 332 | break ; | ||
| 333 | case 6: | ||
| 334 | /* Supposedly called from setuname() in libc. | ||
| 335 | * TODO: When and why is this called? | ||
| 336 | * Is it ever even called? | ||
| 337 | * | ||
| 338 | * This code should look a lot like sys_sethostname(), | ||
| 339 | * defined in linux/kernel/sys.c. If that gets updated, | ||
| 340 | * update this code similarly. | ||
| 341 | */ | ||
| 342 | if (!capable(CAP_SYS_ADMIN)) | ||
| 343 | return -EPERM; | ||
| 344 | /* Unlike Linux, HP-UX returns an error if n==0: */ | ||
| 345 | if ( n <= 0 ) | ||
| 346 | return -EINVAL ; | ||
| 347 | /* Unlike Linux, HP-UX truncates it if n is too big: */ | ||
| 348 | len = (n <= __NEW_UTS_LEN) ? n : __NEW_UTS_LEN ; | ||
| 349 | /**/ | ||
| 350 | /* TODO: print a warning about using this? */ | ||
| 351 | down_write(&uts_sem); | ||
| 352 | error = -EFAULT; | ||
| 353 | if (!copy_from_user(utsname()->sysname, ubuf, len)) { | ||
| 354 | utsname()->sysname[len] = 0; | ||
| 355 | error = 0; | ||
| 356 | } | ||
| 357 | up_write(&uts_sem); | ||
| 358 | return error; | ||
| 359 | break ; | ||
| 360 | case 7: | ||
| 361 | /* Sets utsname.release, if you're allowed. | ||
| 362 | * Undocumented. Used by swinstall to change the | ||
| 363 | * OS version, during OS updates. Yuck!!! | ||
| 364 | * | ||
| 365 | * This code should look a lot like sys_sethostname() | ||
| 366 | * in linux/kernel/sys.c. If that gets updated, update | ||
| 367 | * this code similarly. | ||
| 368 | */ | ||
| 369 | if (!capable(CAP_SYS_ADMIN)) | ||
| 370 | return -EPERM; | ||
| 371 | /* Unlike Linux, HP-UX returns an error if n==0: */ | ||
| 372 | if ( n <= 0 ) | ||
| 373 | return -EINVAL ; | ||
| 374 | /* Unlike Linux, HP-UX truncates it if n is too big: */ | ||
| 375 | len = (n <= __NEW_UTS_LEN) ? n : __NEW_UTS_LEN ; | ||
| 376 | /**/ | ||
| 377 | /* TODO: print a warning about this? */ | ||
| 378 | down_write(&uts_sem); | ||
| 379 | error = -EFAULT; | ||
| 380 | if (!copy_from_user(utsname()->release, ubuf, len)) { | ||
| 381 | utsname()->release[len] = 0; | ||
| 382 | error = 0; | ||
| 383 | } | ||
| 384 | up_write(&uts_sem); | ||
| 385 | return error; | ||
| 386 | break ; | ||
| 387 | default: | ||
| 388 | /* This system call returns -EFAULT if given an unknown type. | ||
| 389 | * Why not -EINVAL? I don't know, it's just not what they did. | ||
| 390 | */ | ||
| 391 | return -EFAULT ; | ||
| 392 | } | ||
| 393 | } | ||
| 394 | |||
| 395 | int hpux_getdomainname(char __user *name, int len) | ||
| 396 | { | ||
| 397 | int nlen; | ||
| 398 | int err = -EFAULT; | ||
| 399 | |||
| 400 | down_read(&uts_sem); | ||
| 401 | |||
| 402 | nlen = strlen(utsname()->domainname) + 1; | ||
| 403 | |||
| 404 | if (nlen < len) | ||
| 405 | len = nlen; | ||
| 406 | if(len > __NEW_UTS_LEN) | ||
| 407 | goto done; | ||
| 408 | if(copy_to_user(name, utsname()->domainname, len)) | ||
| 409 | goto done; | ||
| 410 | err = 0; | ||
| 411 | done: | ||
| 412 | up_read(&uts_sem); | ||
| 413 | return err; | ||
| 414 | |||
| 415 | } | ||
| 416 | |||
| 417 | int hpux_pipe(int *kstack_fildes) | ||
| 418 | { | ||
| 419 | return do_pipe_flags(kstack_fildes, 0); | ||
| 420 | } | ||
| 421 | |||
| 422 | /* lies - says it works, but it really didn't lock anything */ | ||
| 423 | int hpux_lockf(int fildes, int function, off_t size) | ||
| 424 | { | ||
| 425 | return 0; | ||
| 426 | } | ||
| 427 | |||
| 428 | int hpux_sysfs(int opcode, unsigned long arg1, unsigned long arg2) | ||
| 429 | { | ||
| 430 | char *fsname = NULL; | ||
| 431 | int len = 0; | ||
| 432 | int fstype; | ||
| 433 | |||
| 434 | /*Unimplemented HP-UX syscall emulation. Syscall #334 (sysfs) | ||
| 435 | Args: 1 80057bf4 0 400179f0 0 0 0 */ | ||
| 436 | printk(KERN_DEBUG "in hpux_sysfs\n"); | ||
| 437 | printk(KERN_DEBUG "hpux_sysfs called with opcode = %d\n", opcode); | ||
| 438 | printk(KERN_DEBUG "hpux_sysfs called with arg1='%lx'\n", arg1); | ||
| 439 | |||
| 440 | if ( opcode == 1 ) { /* GETFSIND */ | ||
| 441 | char __user *user_fsname = (char __user *)arg1; | ||
| 442 | len = strlen_user(user_fsname); | ||
| 443 | printk(KERN_DEBUG "len of arg1 = %d\n", len); | ||
| 444 | if (len == 0) | ||
| 445 | return 0; | ||
| 446 | fsname = kmalloc(len, GFP_KERNEL); | ||
| 447 | if (!fsname) { | ||
| 448 | printk(KERN_DEBUG "failed to kmalloc fsname\n"); | ||
| 449 | return 0; | ||
| 450 | } | ||
| 451 | |||
| 452 | if (copy_from_user(fsname, user_fsname, len)) { | ||
| 453 | printk(KERN_DEBUG "failed to copy_from_user fsname\n"); | ||
| 454 | kfree(fsname); | ||
| 455 | return 0; | ||
| 456 | } | ||
| 457 | |||
| 458 | /* String could be altered by userspace after strlen_user() */ | ||
| 459 | fsname[len - 1] = '\0'; | ||
| 460 | |||
| 461 | printk(KERN_DEBUG "that is '%s' as (char *)\n", fsname); | ||
| 462 | if ( !strcmp(fsname, "hfs") ) { | ||
| 463 | fstype = 0; | ||
| 464 | } else { | ||
| 465 | fstype = 0; | ||
| 466 | } | ||
| 467 | |||
| 468 | kfree(fsname); | ||
| 469 | |||
| 470 | printk(KERN_DEBUG "returning fstype=%d\n", fstype); | ||
| 471 | return fstype; /* something other than default */ | ||
| 472 | } | ||
| 473 | |||
| 474 | |||
| 475 | return 0; | ||
| 476 | } | ||
| 477 | |||
| 478 | |||
| 479 | /* Table of syscall names and handle for unimplemented routines */ | ||
| 480 | static const char * const syscall_names[] = { | ||
| 481 | "nosys", /* 0 */ | ||
| 482 | "exit", | ||
| 483 | "fork", | ||
| 484 | "read", | ||
| 485 | "write", | ||
| 486 | "open", /* 5 */ | ||
| 487 | "close", | ||
| 488 | "wait", | ||
| 489 | "creat", | ||
| 490 | "link", | ||
| 491 | "unlink", /* 10 */ | ||
| 492 | "execv", | ||
| 493 | "chdir", | ||
| 494 | "time", | ||
| 495 | "mknod", | ||
| 496 | "chmod", /* 15 */ | ||
| 497 | "chown", | ||
| 498 | "brk", | ||
| 499 | "lchmod", | ||
| 500 | "lseek", | ||
| 501 | "getpid", /* 20 */ | ||
| 502 | "mount", | ||
| 503 | "umount", | ||
| 504 | "setuid", | ||
| 505 | "getuid", | ||
| 506 | "stime", /* 25 */ | ||
| 507 | "ptrace", | ||
| 508 | "alarm", | ||
| 509 | NULL, | ||
| 510 | "pause", | ||
| 511 | "utime", /* 30 */ | ||
| 512 | "stty", | ||
| 513 | "gtty", | ||
| 514 | "access", | ||
| 515 | "nice", | ||
| 516 | "ftime", /* 35 */ | ||
| 517 | "sync", | ||
| 518 | "kill", | ||
| 519 | "stat", | ||
| 520 | "setpgrp3", | ||
| 521 | "lstat", /* 40 */ | ||
| 522 | "dup", | ||
| 523 | "pipe", | ||
| 524 | "times", | ||
| 525 | "profil", | ||
| 526 | "ki_call", /* 45 */ | ||
| 527 | "setgid", | ||
| 528 | "getgid", | ||
| 529 | NULL, | ||
| 530 | NULL, | ||
| 531 | NULL, /* 50 */ | ||
| 532 | "acct", | ||
| 533 | "set_userthreadid", | ||
| 534 | NULL, | ||
| 535 | "ioctl", | ||
| 536 | "reboot", /* 55 */ | ||
| 537 | "symlink", | ||
| 538 | "utssys", | ||
| 539 | "readlink", | ||
| 540 | "execve", | ||
| 541 | "umask", /* 60 */ | ||
| 542 | "chroot", | ||
| 543 | "fcntl", | ||
| 544 | "ulimit", | ||
| 545 | NULL, | ||
| 546 | NULL, /* 65 */ | ||
| 547 | "vfork", | ||
| 548 | NULL, | ||
| 549 | NULL, | ||
| 550 | NULL, | ||
| 551 | NULL, /* 70 */ | ||
| 552 | "mmap", | ||
| 553 | NULL, | ||
| 554 | "munmap", | ||
| 555 | "mprotect", | ||
| 556 | "madvise", /* 75 */ | ||
| 557 | "vhangup", | ||
| 558 | "swapoff", | ||
| 559 | NULL, | ||
| 560 | "getgroups", | ||
| 561 | "setgroups", /* 80 */ | ||
| 562 | "getpgrp2", | ||
| 563 | "setpgid/setpgrp2", | ||
| 564 | "setitimer", | ||
| 565 | "wait3", | ||
| 566 | "swapon", /* 85 */ | ||
| 567 | "getitimer", | ||
| 568 | NULL, | ||
| 569 | NULL, | ||
| 570 | NULL, | ||
| 571 | "dup2", /* 90 */ | ||
| 572 | NULL, | ||
| 573 | "fstat", | ||
| 574 | "select", | ||
| 575 | NULL, | ||
| 576 | "fsync", /* 95 */ | ||
| 577 | "setpriority", | ||
| 578 | NULL, | ||
| 579 | NULL, | ||
| 580 | NULL, | ||
| 581 | "getpriority", /* 100 */ | ||
| 582 | NULL, | ||
| 583 | NULL, | ||
| 584 | NULL, | ||
| 585 | NULL, | ||
| 586 | NULL, /* 105 */ | ||
| 587 | NULL, | ||
| 588 | NULL, | ||
| 589 | "sigvector", | ||
| 590 | "sigblock", | ||
| 591 | "sigsetmask", /* 110 */ | ||
| 592 | "sigpause", | ||
| 593 | "sigstack", | ||
| 594 | NULL, | ||
| 595 | NULL, | ||
| 596 | NULL, /* 115 */ | ||
| 597 | "gettimeofday", | ||
| 598 | "getrusage", | ||
| 599 | NULL, | ||
| 600 | NULL, | ||
| 601 | "readv", /* 120 */ | ||
| 602 | "writev", | ||
| 603 | "settimeofday", | ||
| 604 | "fchown", | ||
| 605 | "fchmod", | ||
| 606 | NULL, /* 125 */ | ||
| 607 | "setresuid", | ||
| 608 | "setresgid", | ||
| 609 | "rename", | ||
| 610 | "truncate", | ||
| 611 | "ftruncate", /* 130 */ | ||
| 612 | NULL, | ||
| 613 | "sysconf", | ||
| 614 | NULL, | ||
| 615 | NULL, | ||
| 616 | NULL, /* 135 */ | ||
| 617 | "mkdir", | ||
| 618 | "rmdir", | ||
| 619 | NULL, | ||
| 620 | "sigcleanup", | ||
| 621 | "setcore", /* 140 */ | ||
| 622 | NULL, | ||
| 623 | "gethostid", | ||
| 624 | "sethostid", | ||
| 625 | "getrlimit", | ||
| 626 | "setrlimit", /* 145 */ | ||
| 627 | NULL, | ||
| 628 | NULL, | ||
| 629 | "quotactl", | ||
| 630 | "get_sysinfo", | ||
| 631 | NULL, /* 150 */ | ||
| 632 | "privgrp", | ||
| 633 | "rtprio", | ||
| 634 | "plock", | ||
| 635 | NULL, | ||
| 636 | "lockf", /* 155 */ | ||
| 637 | "semget", | ||
| 638 | NULL, | ||
| 639 | "semop", | ||
| 640 | "msgget", | ||
| 641 | NULL, /* 160 */ | ||
| 642 | "msgsnd", | ||
| 643 | "msgrcv", | ||
| 644 | "shmget", | ||
| 645 | NULL, | ||
| 646 | "shmat", /* 165 */ | ||
| 647 | "shmdt", | ||
| 648 | NULL, | ||
| 649 | "csp/nsp_init", | ||
| 650 | "cluster", | ||
| 651 | "mkrnod", /* 170 */ | ||
| 652 | "test", | ||
| 653 | "unsp_open", | ||
| 654 | NULL, | ||
| 655 | "getcontext", | ||
| 656 | "osetcontext", /* 175 */ | ||
| 657 | "bigio", | ||
| 658 | "pipenode", | ||
| 659 | "lsync", | ||
| 660 | "getmachineid", | ||
| 661 | "cnodeid/mysite", /* 180 */ | ||
| 662 | "cnodes/sitels", | ||
| 663 | "swapclients", | ||
| 664 | "rmtprocess", | ||
| 665 | "dskless_stats", | ||
| 666 | "sigprocmask", /* 185 */ | ||
| 667 | "sigpending", | ||
| 668 | "sigsuspend", | ||
| 669 | "sigaction", | ||
| 670 | NULL, | ||
| 671 | "nfssvc", /* 190 */ | ||
| 672 | "getfh", | ||
| 673 | "getdomainname", | ||
| 674 | "setdomainname", | ||
| 675 | "async_daemon", | ||
| 676 | "getdirentries", /* 195 */ | ||
| 677 | NULL, | ||
| 678 | NULL, | ||
| 679 | "vfsmount", | ||
| 680 | NULL, | ||
| 681 | "waitpid", /* 200 */ | ||
| 682 | NULL, | ||
| 683 | NULL, | ||
| 684 | NULL, | ||
| 685 | NULL, | ||
| 686 | NULL, /* 205 */ | ||
| 687 | NULL, | ||
| 688 | NULL, | ||
| 689 | NULL, | ||
| 690 | NULL, | ||
| 691 | NULL, /* 210 */ | ||
| 692 | NULL, | ||
| 693 | NULL, | ||
| 694 | NULL, | ||
| 695 | NULL, | ||
| 696 | NULL, /* 215 */ | ||
| 697 | NULL, | ||
| 698 | NULL, | ||
| 699 | NULL, | ||
| 700 | NULL, | ||
| 701 | NULL, /* 220 */ | ||
| 702 | NULL, | ||
| 703 | NULL, | ||
| 704 | NULL, | ||
| 705 | "sigsetreturn", | ||
| 706 | "sigsetstatemask", /* 225 */ | ||
| 707 | "bfactl", | ||
| 708 | "cs", | ||
| 709 | "cds", | ||
| 710 | NULL, | ||
| 711 | "pathconf", /* 230 */ | ||
| 712 | "fpathconf", | ||
| 713 | NULL, | ||
| 714 | NULL, | ||
| 715 | "nfs_fcntl", | ||
| 716 | "ogetacl", /* 235 */ | ||
| 717 | "ofgetacl", | ||
| 718 | "osetacl", | ||
| 719 | "ofsetacl", | ||
| 720 | "pstat", | ||
| 721 | "getaudid", /* 240 */ | ||
| 722 | "setaudid", | ||
| 723 | "getaudproc", | ||
| 724 | "setaudproc", | ||
| 725 | "getevent", | ||
| 726 | "setevent", /* 245 */ | ||
| 727 | "audwrite", | ||
| 728 | "audswitch", | ||
| 729 | "audctl", | ||
| 730 | "ogetaccess", | ||
| 731 | "fsctl", /* 250 */ | ||
| 732 | "ulconnect", | ||
| 733 | "ulcontrol", | ||
| 734 | "ulcreate", | ||
| 735 | "uldest", | ||
| 736 | "ulrecv", /* 255 */ | ||
| 737 | "ulrecvcn", | ||
| 738 | "ulsend", | ||
| 739 | "ulshutdown", | ||
| 740 | "swapfs", | ||
| 741 | "fss", /* 260 */ | ||
| 742 | NULL, | ||
| 743 | NULL, | ||
| 744 | NULL, | ||
| 745 | NULL, | ||
| 746 | NULL, /* 265 */ | ||
| 747 | NULL, | ||
| 748 | "tsync", | ||
| 749 | "getnumfds", | ||
| 750 | "poll", | ||
| 751 | "getmsg", /* 270 */ | ||
| 752 | "putmsg", | ||
| 753 | "fchdir", | ||
| 754 | "getmount_cnt", | ||
| 755 | "getmount_entry", | ||
| 756 | "accept", /* 275 */ | ||
| 757 | "bind", | ||
| 758 | "connect", | ||
| 759 | "getpeername", | ||
| 760 | "getsockname", | ||
| 761 | "getsockopt", /* 280 */ | ||
| 762 | "listen", | ||
| 763 | "recv", | ||
| 764 | "recvfrom", | ||
| 765 | "recvmsg", | ||
| 766 | "send", /* 285 */ | ||
| 767 | "sendmsg", | ||
| 768 | "sendto", | ||
| 769 | "setsockopt", | ||
| 770 | "shutdown", | ||
| 771 | "socket", /* 290 */ | ||
| 772 | "socketpair", | ||
| 773 | "proc_open", | ||
| 774 | "proc_close", | ||
| 775 | "proc_send", | ||
| 776 | "proc_recv", /* 295 */ | ||
| 777 | "proc_sendrecv", | ||
| 778 | "proc_syscall", | ||
| 779 | "ipccreate", | ||
| 780 | "ipcname", | ||
| 781 | "ipcnamerase", /* 300 */ | ||
| 782 | "ipclookup", | ||
| 783 | "ipcselect", | ||
| 784 | "ipcconnect", | ||
| 785 | "ipcrecvcn", | ||
| 786 | "ipcsend", /* 305 */ | ||
| 787 | "ipcrecv", | ||
| 788 | "ipcgetnodename", | ||
| 789 | "ipcsetnodename", | ||
| 790 | "ipccontrol", | ||
| 791 | "ipcshutdown", /* 310 */ | ||
| 792 | "ipcdest", | ||
| 793 | "semctl", | ||
| 794 | "msgctl", | ||
| 795 | "shmctl", | ||
| 796 | "mpctl", /* 315 */ | ||
| 797 | "exportfs", | ||
| 798 | "getpmsg", | ||
| 799 | "putpmsg", | ||
| 800 | "strioctl", | ||
| 801 | "msync", /* 320 */ | ||
| 802 | "msleep", | ||
| 803 | "mwakeup", | ||
| 804 | "msem_init", | ||
| 805 | "msem_remove", | ||
| 806 | "adjtime", /* 325 */ | ||
| 807 | "kload", | ||
| 808 | "fattach", | ||
| 809 | "fdetach", | ||
| 810 | "serialize", | ||
| 811 | "statvfs", /* 330 */ | ||
| 812 | "fstatvfs", | ||
| 813 | "lchown", | ||
| 814 | "getsid", | ||
| 815 | "sysfs", | ||
| 816 | NULL, /* 335 */ | ||
| 817 | NULL, | ||
| 818 | "sched_setparam", | ||
| 819 | "sched_getparam", | ||
| 820 | "sched_setscheduler", | ||
| 821 | "sched_getscheduler", /* 340 */ | ||
| 822 | "sched_yield", | ||
| 823 | "sched_get_priority_max", | ||
| 824 | "sched_get_priority_min", | ||
| 825 | "sched_rr_get_interval", | ||
| 826 | "clock_settime", /* 345 */ | ||
| 827 | "clock_gettime", | ||
| 828 | "clock_getres", | ||
| 829 | "timer_create", | ||
| 830 | "timer_delete", | ||
| 831 | "timer_settime", /* 350 */ | ||
| 832 | "timer_gettime", | ||
| 833 | "timer_getoverrun", | ||
| 834 | "nanosleep", | ||
| 835 | "toolbox", | ||
| 836 | NULL, /* 355 */ | ||
| 837 | "getdents", | ||
| 838 | "getcontext", | ||
| 839 | "sysinfo", | ||
| 840 | "fcntl64", | ||
| 841 | "ftruncate64", /* 360 */ | ||
| 842 | "fstat64", | ||
| 843 | "getdirentries64", | ||
| 844 | "getrlimit64", | ||
| 845 | "lockf64", | ||
| 846 | "lseek64", /* 365 */ | ||
| 847 | "lstat64", | ||
| 848 | "mmap64", | ||
| 849 | "setrlimit64", | ||
| 850 | "stat64", | ||
| 851 | "truncate64", /* 370 */ | ||
| 852 | "ulimit64", | ||
| 853 | NULL, | ||
| 854 | NULL, | ||
| 855 | NULL, | ||
| 856 | NULL, /* 375 */ | ||
| 857 | NULL, | ||
| 858 | NULL, | ||
| 859 | NULL, | ||
| 860 | NULL, | ||
| 861 | "setcontext", /* 380 */ | ||
| 862 | "sigaltstack", | ||
| 863 | "waitid", | ||
| 864 | "setpgrp", | ||
| 865 | "recvmsg2", | ||
| 866 | "sendmsg2", /* 385 */ | ||
| 867 | "socket2", | ||
| 868 | "socketpair2", | ||
| 869 | "setregid", | ||
| 870 | "lwp_create", | ||
| 871 | "lwp_terminate", /* 390 */ | ||
| 872 | "lwp_wait", | ||
| 873 | "lwp_suspend", | ||
| 874 | "lwp_resume", | ||
| 875 | "lwp_self", | ||
| 876 | "lwp_abort_syscall", /* 395 */ | ||
| 877 | "lwp_info", | ||
| 878 | "lwp_kill", | ||
| 879 | "ksleep", | ||
| 880 | "kwakeup", | ||
| 881 | "ksleep_abort", /* 400 */ | ||
| 882 | "lwp_proc_info", | ||
| 883 | "lwp_exit", | ||
| 884 | "lwp_continue", | ||
| 885 | "getacl", | ||
| 886 | "fgetacl", /* 405 */ | ||
| 887 | "setacl", | ||
| 888 | "fsetacl", | ||
| 889 | "getaccess", | ||
| 890 | "lwp_mutex_init", | ||
| 891 | "lwp_mutex_lock_sys", /* 410 */ | ||
| 892 | "lwp_mutex_unlock", | ||
| 893 | "lwp_cond_init", | ||
| 894 | "lwp_cond_signal", | ||
| 895 | "lwp_cond_broadcast", | ||
| 896 | "lwp_cond_wait_sys", /* 415 */ | ||
| 897 | "lwp_getscheduler", | ||
| 898 | "lwp_setscheduler", | ||
| 899 | "lwp_getprivate", | ||
| 900 | "lwp_setprivate", | ||
| 901 | "lwp_detach", /* 420 */ | ||
| 902 | "mlock", | ||
| 903 | "munlock", | ||
| 904 | "mlockall", | ||
| 905 | "munlockall", | ||
| 906 | "shm_open", /* 425 */ | ||
| 907 | "shm_unlink", | ||
| 908 | "sigqueue", | ||
| 909 | "sigwaitinfo", | ||
| 910 | "sigtimedwait", | ||
| 911 | "sigwait", /* 430 */ | ||
| 912 | "aio_read", | ||
| 913 | "aio_write", | ||
| 914 | "lio_listio", | ||
| 915 | "aio_error", | ||
| 916 | "aio_return", /* 435 */ | ||
| 917 | "aio_cancel", | ||
| 918 | "aio_suspend", | ||
| 919 | "aio_fsync", | ||
| 920 | "mq_open", | ||
| 921 | "mq_unlink", /* 440 */ | ||
| 922 | "mq_send", | ||
| 923 | "mq_receive", | ||
| 924 | "mq_notify", | ||
| 925 | "mq_setattr", | ||
| 926 | "mq_getattr", /* 445 */ | ||
| 927 | "ksem_open", | ||
| 928 | "ksem_unlink", | ||
| 929 | "ksem_close", | ||
| 930 | "ksem_destroy", | ||
| 931 | "lw_sem_incr", /* 450 */ | ||
| 932 | "lw_sem_decr", | ||
| 933 | "lw_sem_read", | ||
| 934 | "mq_close", | ||
| 935 | }; | ||
| 936 | static const int syscall_names_max = 453; | ||
| 937 | |||
| 938 | int | ||
| 939 | hpux_unimplemented(unsigned long arg1,unsigned long arg2,unsigned long arg3, | ||
| 940 | unsigned long arg4,unsigned long arg5,unsigned long arg6, | ||
| 941 | unsigned long arg7,unsigned long sc_num) | ||
| 942 | { | ||
| 943 | /* NOTE: sc_num trashes arg8 for the few syscalls that actually | ||
| 944 | * have a valid 8th argument. | ||
| 945 | */ | ||
| 946 | const char *name = NULL; | ||
| 947 | if ( sc_num <= syscall_names_max && sc_num >= 0 ) { | ||
| 948 | name = syscall_names[sc_num]; | ||
| 949 | } | ||
| 950 | |||
| 951 | if ( name ) { | ||
| 952 | printk(KERN_DEBUG "Unimplemented HP-UX syscall emulation. Syscall #%lu (%s)\n", | ||
| 953 | sc_num, name); | ||
| 954 | } else { | ||
| 955 | printk(KERN_DEBUG "Unimplemented unknown HP-UX syscall emulation. Syscall #%lu\n", | ||
| 956 | sc_num); | ||
| 957 | } | ||
| 958 | |||
| 959 | printk(KERN_DEBUG " Args: %lx %lx %lx %lx %lx %lx %lx\n", | ||
| 960 | arg1, arg2, arg3, arg4, arg5, arg6, arg7); | ||
| 961 | |||
| 962 | return -ENOSYS; | ||
| 963 | } | ||
diff --git a/arch/parisc/hpux/wrappers.S b/arch/parisc/hpux/wrappers.S deleted file mode 100644 index 58c53c879c02..000000000000 --- a/arch/parisc/hpux/wrappers.S +++ /dev/null | |||
| @@ -1,250 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PARISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * HP-UX System Call Wrapper routines and System Call Return Path | ||
| 5 | * | ||
| 6 | * Copyright (C) 2000 Hewlett-Packard (John Marvin) | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 11 | * any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 21 | */ | ||
| 22 | |||
| 23 | #ifdef CONFIG_64BIT | ||
| 24 | #warning PA64 support needs more work...did first cut | ||
| 25 | #endif | ||
| 26 | |||
| 27 | #include <asm/asm-offsets.h> | ||
| 28 | #include <asm/assembly.h> | ||
| 29 | #include <asm/signal.h> | ||
| 30 | #include <linux/linkage.h> | ||
| 31 | |||
| 32 | .level LEVEL | ||
| 33 | .text | ||
| 34 | |||
| 35 | /* These should probably go in a header file somewhere. | ||
| 36 | * They are duplicated in kernel/wrappers.S | ||
| 37 | * Possibly we should consider consolidating these | ||
| 38 | * register save/restore macros. | ||
| 39 | */ | ||
| 40 | .macro reg_save regs | ||
| 41 | #ifdef CONFIG_64BIT | ||
| 42 | #warning NEEDS WORK for 64-bit | ||
| 43 | #endif | ||
| 44 | STREG %r3, PT_GR3(\regs) | ||
| 45 | STREG %r4, PT_GR4(\regs) | ||
| 46 | STREG %r5, PT_GR5(\regs) | ||
| 47 | STREG %r6, PT_GR6(\regs) | ||
| 48 | STREG %r7, PT_GR7(\regs) | ||
| 49 | STREG %r8, PT_GR8(\regs) | ||
| 50 | STREG %r9, PT_GR9(\regs) | ||
| 51 | STREG %r10,PT_GR10(\regs) | ||
| 52 | STREG %r11,PT_GR11(\regs) | ||
| 53 | STREG %r12,PT_GR12(\regs) | ||
| 54 | STREG %r13,PT_GR13(\regs) | ||
| 55 | STREG %r14,PT_GR14(\regs) | ||
| 56 | STREG %r15,PT_GR15(\regs) | ||
| 57 | STREG %r16,PT_GR16(\regs) | ||
| 58 | STREG %r17,PT_GR17(\regs) | ||
| 59 | STREG %r18,PT_GR18(\regs) | ||
| 60 | .endm | ||
| 61 | |||
| 62 | .macro reg_restore regs | ||
| 63 | LDREG PT_GR3(\regs), %r3 | ||
| 64 | LDREG PT_GR4(\regs), %r4 | ||
| 65 | LDREG PT_GR5(\regs), %r5 | ||
| 66 | LDREG PT_GR6(\regs), %r6 | ||
| 67 | LDREG PT_GR7(\regs), %r7 | ||
| 68 | LDREG PT_GR8(\regs), %r8 | ||
| 69 | LDREG PT_GR9(\regs), %r9 | ||
| 70 | LDREG PT_GR10(\regs),%r10 | ||
| 71 | LDREG PT_GR11(\regs),%r11 | ||
| 72 | LDREG PT_GR12(\regs),%r12 | ||
| 73 | LDREG PT_GR13(\regs),%r13 | ||
| 74 | LDREG PT_GR14(\regs),%r14 | ||
| 75 | LDREG PT_GR15(\regs),%r15 | ||
| 76 | LDREG PT_GR16(\regs),%r16 | ||
| 77 | LDREG PT_GR17(\regs),%r17 | ||
| 78 | LDREG PT_GR18(\regs),%r18 | ||
| 79 | .endm | ||
| 80 | |||
| 81 | |||
| 82 | .import sys_fork | ||
| 83 | |||
| 84 | ENTRY(hpux_fork_wrapper) | ||
| 85 | ldo TASK_REGS-TASK_SZ_ALGN-64(%r30),%r1 ;! get pt regs | ||
| 86 | ;! pointer in task | ||
| 87 | reg_save %r1 | ||
| 88 | |||
| 89 | STREG %r2,-20(%r30) | ||
| 90 | ldo 64(%r30),%r30 | ||
| 91 | STREG %r2,PT_GR19(%r1) ;! save for child | ||
| 92 | STREG %r30,PT_GR21(%r1) ;! save for child | ||
| 93 | |||
| 94 | LDREG PT_GR30(%r1),%r25 | ||
| 95 | mtctl %r25,%cr29 | ||
| 96 | copy %r1,%r24 | ||
| 97 | bl sys_clone,%r2 | ||
| 98 | ldi SIGCHLD,%r26 | ||
| 99 | |||
| 100 | LDREG -84(%r30),%r2 | ||
| 101 | fork_return: | ||
| 102 | ldo -64(%r30),%r30 | ||
| 103 | ldo TASK_REGS-TASK_SZ_ALGN-64(%r30),%r1 ;! get pt regs | ||
| 104 | |||
| 105 | reg_restore %r1 | ||
| 106 | |||
| 107 | /* | ||
| 108 | * HP-UX wants pid (child gets parent pid, parent gets child pid) | ||
| 109 | * in r28 and a flag in r29 (r29 == 1 for child, 0 for parent). | ||
| 110 | * Linux fork returns 0 for child, pid for parent. Since HP-UX | ||
| 111 | * libc stub throws away parent pid and returns 0 for child, | ||
| 112 | * we'll just return 0 for parent pid now. Only applications | ||
| 113 | * that jump directly to the gateway page (not supported) will | ||
| 114 | * know the difference. We can fix this later if necessary. | ||
| 115 | */ | ||
| 116 | |||
| 117 | ldo -1024(%r0),%r1 | ||
| 118 | comb,>>=,n %r28,%r1,fork_exit /* just let the syscall exit handle it */ | ||
| 119 | or,= %r28,%r0,%r0 | ||
| 120 | or,tr %r0,%r0,%r29 /* r28 <> 0, we are parent, set r29 to 0 */ | ||
| 121 | ldo 1(%r0),%r29 /* r28 == 0, we are child, set r29 to 1 */ | ||
| 122 | |||
| 123 | fork_exit: | ||
| 124 | bv %r0(%r2) | ||
| 125 | nop | ||
| 126 | ENDPROC(hpux_fork_wrapper) | ||
| 127 | |||
| 128 | /* Set the return value for the child */ | ||
| 129 | |||
| 130 | ENTRY(hpux_child_return) | ||
| 131 | #if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) | ||
| 132 | bl,n schedule_tail, %r2 | ||
| 133 | #endif | ||
| 134 | |||
| 135 | LDREG TASK_PT_GR19-TASK_SZ_ALGN-128(%r30),%r2 | ||
| 136 | b fork_return | ||
| 137 | copy %r0,%r28 | ||
| 138 | ENDPROC(hpux_child_return) | ||
| 139 | |||
| 140 | .import hpux_execve | ||
| 141 | |||
| 142 | ENTRY(hpux_execv_wrapper) | ||
| 143 | copy %r0,%r24 /* NULL environment */ | ||
| 144 | |||
| 145 | ENTRY(hpux_execve_wrapper) | ||
| 146 | |||
| 147 | ldo TASK_REGS-TASK_SZ_ALGN-64(%r30),%r1 ;! get pt regs | ||
| 148 | |||
| 149 | /* | ||
| 150 | * Do we need to save/restore r3-r18 here? | ||
| 151 | * I don't think so. why would new thread need old | ||
| 152 | * threads registers? | ||
| 153 | */ | ||
| 154 | |||
| 155 | /* Store arg0, arg1 and arg2 so that hpux_execve will find them */ | ||
| 156 | |||
| 157 | STREG %r26,PT_GR26(%r1) | ||
| 158 | STREG %r25,PT_GR25(%r1) | ||
| 159 | STREG %r24,PT_GR24(%r1) | ||
| 160 | |||
| 161 | STREG %r2,-20(%r30) | ||
| 162 | ldo 64(%r30),%r30 | ||
| 163 | bl hpux_execve,%r2 | ||
| 164 | copy %r1,%arg0 | ||
| 165 | |||
| 166 | ldo -64(%r30),%r30 | ||
| 167 | LDREG -20(%r30),%r2 | ||
| 168 | |||
| 169 | /* If exec succeeded we need to load the args */ | ||
| 170 | |||
| 171 | ldo -1024(%r0),%r1 | ||
| 172 | comb,>>= %r28,%r1,exec_error | ||
| 173 | copy %r2,%r19 | ||
| 174 | ldo -TASK_SZ_ALGN-64(%r30),%r1 ;! get task ptr | ||
| 175 | LDREG TASK_PT_GR26(%r1),%r26 | ||
| 176 | LDREG TASK_PT_GR25(%r1),%r25 | ||
| 177 | LDREG TASK_PT_GR24(%r1),%r24 | ||
| 178 | LDREG TASK_PT_GR23(%r1),%r23 | ||
| 179 | copy %r0,%r2 /* Flag to syscall_exit not to clear args */ | ||
| 180 | |||
| 181 | exec_error: | ||
| 182 | bv %r0(%r19) | ||
| 183 | nop | ||
| 184 | ENDPROC(hpux_execv_wrapper) | ||
| 185 | |||
| 186 | .import hpux_pipe | ||
| 187 | |||
| 188 | /* HP-UX expects pipefd's returned in r28 & r29 */ | ||
| 189 | |||
| 190 | ENTRY(hpux_pipe_wrapper) | ||
| 191 | STREG %r2,-20(%r30) | ||
| 192 | ldo 64(%r30),%r30 | ||
| 193 | bl hpux_pipe,%r2 | ||
| 194 | ldo -56(%r30),%r26 /* pass local array to hpux_pipe */ | ||
| 195 | |||
| 196 | |||
| 197 | ldo -1024(%r0),%r1 | ||
| 198 | comb,>>= %r28,%r1,pipe_exit /* let syscall exit handle it */ | ||
| 199 | LDREG -84(%r30),%r2 | ||
| 200 | |||
| 201 | /* if success, load fd's from stack array */ | ||
| 202 | |||
| 203 | LDREG -56(%r30),%r28 | ||
| 204 | LDREG -52(%r30),%r29 | ||
| 205 | |||
| 206 | pipe_exit: | ||
| 207 | bv %r0(%r2) | ||
| 208 | ldo -64(%r30),%r30 | ||
| 209 | ENDPROC(hpux_pipe_wrapper) | ||
| 210 | |||
| 211 | .import syscall_exit | ||
| 212 | |||
| 213 | ENTRY(hpux_syscall_exit) | ||
| 214 | /* | ||
| 215 | * | ||
| 216 | * HP-UX call return conventions: | ||
| 217 | * | ||
| 218 | * if error: | ||
| 219 | * r22 = 1 | ||
| 220 | * r28 = errno value | ||
| 221 | * r29 = secondary return value | ||
| 222 | * else | ||
| 223 | * r22 = 0 | ||
| 224 | * r28 = return value | ||
| 225 | * r29 = secondary return value | ||
| 226 | * | ||
| 227 | * For now, we'll just check to see if r28 is < (unsigned long)-1024 | ||
| 228 | * (to handle addresses > 2 Gb) and if so set r22 to zero. If not, | ||
| 229 | * we'll complement r28 and set r22 to 1. Wrappers will be | ||
| 230 | * needed for syscalls that care about the secondary return value. | ||
| 231 | * The wrapper may also need a way of avoiding the following code, | ||
| 232 | * but we'll deal with that when it becomes necessary. | ||
| 233 | */ | ||
| 234 | |||
| 235 | ldo -1024(%r0),%r1 | ||
| 236 | comb,<< %r28,%r1,no_error | ||
| 237 | copy %r0,%r22 | ||
| 238 | subi 0,%r28,%r28 | ||
| 239 | ldo 1(%r0),%r22 | ||
| 240 | |||
| 241 | no_error: | ||
| 242 | b,n syscall_exit | ||
| 243 | ENDPROC(hpux_syscall_exit) | ||
| 244 | |||
| 245 | .import hpux_unimplemented | ||
| 246 | |||
| 247 | ENTRY(hpux_unimplemented_wrapper) | ||
| 248 | b hpux_unimplemented | ||
| 249 | STREG %r22,-64(%r30) /* overwrite arg8 with syscall number */ | ||
| 250 | ENDPROC(hpux_unimplemented_wrapper) | ||
diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h index 689a8ade3606..54adb60c0a42 100644 --- a/arch/parisc/include/asm/processor.h +++ b/arch/parisc/include/asm/processor.h | |||
| @@ -330,8 +330,6 @@ struct mm_struct; | |||
| 330 | /* Free all resources held by a thread. */ | 330 | /* Free all resources held by a thread. */ |
| 331 | extern void release_thread(struct task_struct *); | 331 | extern void release_thread(struct task_struct *); |
| 332 | 332 | ||
| 333 | extern void map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm); | ||
| 334 | |||
| 335 | extern unsigned long get_wchan(struct task_struct *p); | 333 | extern unsigned long get_wchan(struct task_struct *p); |
| 336 | 334 | ||
| 337 | #define KSTK_EIP(tsk) ((tsk)->thread.regs.iaoq[0]) | 335 | #define KSTK_EIP(tsk) ((tsk)->thread.regs.iaoq[0]) |
diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h index a5cb070b54bf..0abdd4c607ed 100644 --- a/arch/parisc/include/asm/uaccess.h +++ b/arch/parisc/include/asm/uaccess.h | |||
| @@ -17,7 +17,7 @@ | |||
| 17 | #define KERNEL_DS ((mm_segment_t){0}) | 17 | #define KERNEL_DS ((mm_segment_t){0}) |
| 18 | #define USER_DS ((mm_segment_t){1}) | 18 | #define USER_DS ((mm_segment_t){1}) |
| 19 | 19 | ||
| 20 | #define segment_eq(a,b) ((a).seg == (b).seg) | 20 | #define segment_eq(a, b) ((a).seg == (b).seg) |
| 21 | 21 | ||
| 22 | #define get_ds() (KERNEL_DS) | 22 | #define get_ds() (KERNEL_DS) |
| 23 | #define get_fs() (current_thread_info()->addr_limit) | 23 | #define get_fs() (current_thread_info()->addr_limit) |
| @@ -42,14 +42,14 @@ static inline long access_ok(int type, const void __user * addr, | |||
| 42 | #if !defined(CONFIG_64BIT) | 42 | #if !defined(CONFIG_64BIT) |
| 43 | #define LDD_KERNEL(ptr) BUILD_BUG() | 43 | #define LDD_KERNEL(ptr) BUILD_BUG() |
| 44 | #define LDD_USER(ptr) BUILD_BUG() | 44 | #define LDD_USER(ptr) BUILD_BUG() |
| 45 | #define STD_KERNEL(x, ptr) __put_kernel_asm64(x,ptr) | 45 | #define STD_KERNEL(x, ptr) __put_kernel_asm64(x, ptr) |
| 46 | #define STD_USER(x, ptr) __put_user_asm64(x,ptr) | 46 | #define STD_USER(x, ptr) __put_user_asm64(x, ptr) |
| 47 | #define ASM_WORD_INSN ".word\t" | 47 | #define ASM_WORD_INSN ".word\t" |
| 48 | #else | 48 | #else |
| 49 | #define LDD_KERNEL(ptr) __get_kernel_asm("ldd",ptr) | 49 | #define LDD_KERNEL(ptr) __get_kernel_asm("ldd", ptr) |
| 50 | #define LDD_USER(ptr) __get_user_asm("ldd",ptr) | 50 | #define LDD_USER(ptr) __get_user_asm("ldd", ptr) |
| 51 | #define STD_KERNEL(x, ptr) __put_kernel_asm("std",x,ptr) | 51 | #define STD_KERNEL(x, ptr) __put_kernel_asm("std", x, ptr) |
| 52 | #define STD_USER(x, ptr) __put_user_asm("std",x,ptr) | 52 | #define STD_USER(x, ptr) __put_user_asm("std", x, ptr) |
| 53 | #define ASM_WORD_INSN ".dword\t" | 53 | #define ASM_WORD_INSN ".dword\t" |
| 54 | #endif | 54 | #endif |
| 55 | 55 | ||
| @@ -80,68 +80,68 @@ struct exception_data { | |||
| 80 | unsigned long fault_addr; | 80 | unsigned long fault_addr; |
| 81 | }; | 81 | }; |
| 82 | 82 | ||
| 83 | #define __get_user(x,ptr) \ | 83 | #define __get_user(x, ptr) \ |
| 84 | ({ \ | 84 | ({ \ |
| 85 | register long __gu_err __asm__ ("r8") = 0; \ | 85 | register long __gu_err __asm__ ("r8") = 0; \ |
| 86 | register long __gu_val __asm__ ("r9") = 0; \ | 86 | register long __gu_val __asm__ ("r9") = 0; \ |
| 87 | \ | 87 | \ |
| 88 | if (segment_eq(get_fs(),KERNEL_DS)) { \ | 88 | if (segment_eq(get_fs(), KERNEL_DS)) { \ |
| 89 | switch (sizeof(*(ptr))) { \ | 89 | switch (sizeof(*(ptr))) { \ |
| 90 | case 1: __get_kernel_asm("ldb",ptr); break; \ | 90 | case 1: __get_kernel_asm("ldb", ptr); break; \ |
| 91 | case 2: __get_kernel_asm("ldh",ptr); break; \ | 91 | case 2: __get_kernel_asm("ldh", ptr); break; \ |
| 92 | case 4: __get_kernel_asm("ldw",ptr); break; \ | 92 | case 4: __get_kernel_asm("ldw", ptr); break; \ |
| 93 | case 8: LDD_KERNEL(ptr); break; \ | 93 | case 8: LDD_KERNEL(ptr); break; \ |
| 94 | default: BUILD_BUG(); break; \ | 94 | default: BUILD_BUG(); break; \ |
| 95 | } \ | 95 | } \ |
| 96 | } \ | 96 | } \ |
| 97 | else { \ | 97 | else { \ |
| 98 | switch (sizeof(*(ptr))) { \ | 98 | switch (sizeof(*(ptr))) { \ |
| 99 | case 1: __get_user_asm("ldb",ptr); break; \ | 99 | case 1: __get_user_asm("ldb", ptr); break; \ |
| 100 | case 2: __get_user_asm("ldh",ptr); break; \ | 100 | case 2: __get_user_asm("ldh", ptr); break; \ |
| 101 | case 4: __get_user_asm("ldw",ptr); break; \ | 101 | case 4: __get_user_asm("ldw", ptr); break; \ |
| 102 | case 8: LDD_USER(ptr); break; \ | 102 | case 8: LDD_USER(ptr); break; \ |
| 103 | default: BUILD_BUG(); break; \ | 103 | default: BUILD_BUG(); break; \ |
| 104 | } \ | 104 | } \ |
| 105 | } \ | 105 | } \ |
| 106 | \ | 106 | \ |
| 107 | (x) = (__typeof__(*(ptr))) __gu_val; \ | 107 | (x) = (__force __typeof__(*(ptr))) __gu_val; \ |
| 108 | __gu_err; \ | 108 | __gu_err; \ |
| 109 | }) | 109 | }) |
| 110 | 110 | ||
| 111 | #define __get_kernel_asm(ldx,ptr) \ | 111 | #define __get_kernel_asm(ldx, ptr) \ |
| 112 | __asm__("\n1:\t" ldx "\t0(%2),%0\n\t" \ | 112 | __asm__("\n1:\t" ldx "\t0(%2),%0\n\t" \ |
| 113 | ASM_EXCEPTIONTABLE_ENTRY(1b, fixup_get_user_skip_1)\ | 113 | ASM_EXCEPTIONTABLE_ENTRY(1b, fixup_get_user_skip_1)\ |
| 114 | : "=r"(__gu_val), "=r"(__gu_err) \ | 114 | : "=r"(__gu_val), "=r"(__gu_err) \ |
| 115 | : "r"(ptr), "1"(__gu_err) \ | 115 | : "r"(ptr), "1"(__gu_err) \ |
| 116 | : "r1"); | 116 | : "r1"); |
| 117 | 117 | ||
| 118 | #define __get_user_asm(ldx,ptr) \ | 118 | #define __get_user_asm(ldx, ptr) \ |
| 119 | __asm__("\n1:\t" ldx "\t0(%%sr3,%2),%0\n\t" \ | 119 | __asm__("\n1:\t" ldx "\t0(%%sr3,%2),%0\n\t" \ |
| 120 | ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_get_user_skip_1)\ | 120 | ASM_EXCEPTIONTABLE_ENTRY(1b, fixup_get_user_skip_1)\ |
| 121 | : "=r"(__gu_val), "=r"(__gu_err) \ | 121 | : "=r"(__gu_val), "=r"(__gu_err) \ |
| 122 | : "r"(ptr), "1"(__gu_err) \ | 122 | : "r"(ptr), "1"(__gu_err) \ |
| 123 | : "r1"); | 123 | : "r1"); |
| 124 | 124 | ||
| 125 | #define __put_user(x,ptr) \ | 125 | #define __put_user(x, ptr) \ |
| 126 | ({ \ | 126 | ({ \ |
| 127 | register long __pu_err __asm__ ("r8") = 0; \ | 127 | register long __pu_err __asm__ ("r8") = 0; \ |
| 128 | __typeof__(*(ptr)) __x = (__typeof__(*(ptr)))(x); \ | 128 | __typeof__(*(ptr)) __x = (__typeof__(*(ptr)))(x); \ |
| 129 | \ | 129 | \ |
| 130 | if (segment_eq(get_fs(),KERNEL_DS)) { \ | 130 | if (segment_eq(get_fs(), KERNEL_DS)) { \ |
| 131 | switch (sizeof(*(ptr))) { \ | 131 | switch (sizeof(*(ptr))) { \ |
| 132 | case 1: __put_kernel_asm("stb",__x,ptr); break; \ | 132 | case 1: __put_kernel_asm("stb", __x, ptr); break; \ |
| 133 | case 2: __put_kernel_asm("sth",__x,ptr); break; \ | 133 | case 2: __put_kernel_asm("sth", __x, ptr); break; \ |
| 134 | case 4: __put_kernel_asm("stw",__x,ptr); break; \ | 134 | case 4: __put_kernel_asm("stw", __x, ptr); break; \ |
| 135 | case 8: STD_KERNEL(__x,ptr); break; \ | 135 | case 8: STD_KERNEL(__x, ptr); break; \ |
| 136 | default: BUILD_BUG(); break; \ | 136 | default: BUILD_BUG(); break; \ |
| 137 | } \ | 137 | } \ |
| 138 | } \ | 138 | } \ |
| 139 | else { \ | 139 | else { \ |
| 140 | switch (sizeof(*(ptr))) { \ | 140 | switch (sizeof(*(ptr))) { \ |
| 141 | case 1: __put_user_asm("stb",__x,ptr); break; \ | 141 | case 1: __put_user_asm("stb", __x, ptr); break; \ |
| 142 | case 2: __put_user_asm("sth",__x,ptr); break; \ | 142 | case 2: __put_user_asm("sth", __x, ptr); break; \ |
| 143 | case 4: __put_user_asm("stw",__x,ptr); break; \ | 143 | case 4: __put_user_asm("stw", __x, ptr); break; \ |
| 144 | case 8: STD_USER(__x,ptr); break; \ | 144 | case 8: STD_USER(__x, ptr); break; \ |
| 145 | default: BUILD_BUG(); break; \ | 145 | default: BUILD_BUG(); break; \ |
| 146 | } \ | 146 | } \ |
| 147 | } \ | 147 | } \ |
| @@ -159,18 +159,18 @@ struct exception_data { | |||
| 159 | * r8/r9 are already listed as err/val. | 159 | * r8/r9 are already listed as err/val. |
| 160 | */ | 160 | */ |
| 161 | 161 | ||
| 162 | #define __put_kernel_asm(stx,x,ptr) \ | 162 | #define __put_kernel_asm(stx, x, ptr) \ |
| 163 | __asm__ __volatile__ ( \ | 163 | __asm__ __volatile__ ( \ |
| 164 | "\n1:\t" stx "\t%2,0(%1)\n\t" \ | 164 | "\n1:\t" stx "\t%2,0(%1)\n\t" \ |
| 165 | ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_put_user_skip_1)\ | 165 | ASM_EXCEPTIONTABLE_ENTRY(1b, fixup_put_user_skip_1)\ |
| 166 | : "=r"(__pu_err) \ | 166 | : "=r"(__pu_err) \ |
| 167 | : "r"(ptr), "r"(x), "0"(__pu_err) \ | 167 | : "r"(ptr), "r"(x), "0"(__pu_err) \ |
| 168 | : "r1") | 168 | : "r1") |
| 169 | 169 | ||
| 170 | #define __put_user_asm(stx,x,ptr) \ | 170 | #define __put_user_asm(stx, x, ptr) \ |
| 171 | __asm__ __volatile__ ( \ | 171 | __asm__ __volatile__ ( \ |
| 172 | "\n1:\t" stx "\t%2,0(%%sr3,%1)\n\t" \ | 172 | "\n1:\t" stx "\t%2,0(%%sr3,%1)\n\t" \ |
| 173 | ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_put_user_skip_1)\ | 173 | ASM_EXCEPTIONTABLE_ENTRY(1b, fixup_put_user_skip_1)\ |
| 174 | : "=r"(__pu_err) \ | 174 | : "=r"(__pu_err) \ |
| 175 | : "r"(ptr), "r"(x), "0"(__pu_err) \ | 175 | : "r"(ptr), "r"(x), "0"(__pu_err) \ |
| 176 | : "r1") | 176 | : "r1") |
| @@ -178,23 +178,23 @@ struct exception_data { | |||
| 178 | 178 | ||
| 179 | #if !defined(CONFIG_64BIT) | 179 | #if !defined(CONFIG_64BIT) |
| 180 | 180 | ||
| 181 | #define __put_kernel_asm64(__val,ptr) do { \ | 181 | #define __put_kernel_asm64(__val, ptr) do { \ |
| 182 | __asm__ __volatile__ ( \ | 182 | __asm__ __volatile__ ( \ |
| 183 | "\n1:\tstw %2,0(%1)" \ | 183 | "\n1:\tstw %2,0(%1)" \ |
| 184 | "\n2:\tstw %R2,4(%1)\n\t" \ | 184 | "\n2:\tstw %R2,4(%1)\n\t" \ |
| 185 | ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_put_user_skip_2)\ | 185 | ASM_EXCEPTIONTABLE_ENTRY(1b, fixup_put_user_skip_2)\ |
| 186 | ASM_EXCEPTIONTABLE_ENTRY(2b,fixup_put_user_skip_1)\ | 186 | ASM_EXCEPTIONTABLE_ENTRY(2b, fixup_put_user_skip_1)\ |
| 187 | : "=r"(__pu_err) \ | 187 | : "=r"(__pu_err) \ |
| 188 | : "r"(ptr), "r"(__val), "0"(__pu_err) \ | 188 | : "r"(ptr), "r"(__val), "0"(__pu_err) \ |
| 189 | : "r1"); \ | 189 | : "r1"); \ |
| 190 | } while (0) | 190 | } while (0) |
| 191 | 191 | ||
| 192 | #define __put_user_asm64(__val,ptr) do { \ | 192 | #define __put_user_asm64(__val, ptr) do { \ |
| 193 | __asm__ __volatile__ ( \ | 193 | __asm__ __volatile__ ( \ |
| 194 | "\n1:\tstw %2,0(%%sr3,%1)" \ | 194 | "\n1:\tstw %2,0(%%sr3,%1)" \ |
| 195 | "\n2:\tstw %R2,4(%%sr3,%1)\n\t" \ | 195 | "\n2:\tstw %R2,4(%%sr3,%1)\n\t" \ |
| 196 | ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_put_user_skip_2)\ | 196 | ASM_EXCEPTIONTABLE_ENTRY(1b, fixup_put_user_skip_2)\ |
| 197 | ASM_EXCEPTIONTABLE_ENTRY(2b,fixup_put_user_skip_1)\ | 197 | ASM_EXCEPTIONTABLE_ENTRY(2b, fixup_put_user_skip_1)\ |
| 198 | : "=r"(__pu_err) \ | 198 | : "=r"(__pu_err) \ |
| 199 | : "r"(ptr), "r"(__val), "0"(__pu_err) \ | 199 | : "r"(ptr), "r"(__val), "0"(__pu_err) \ |
| 200 | : "r1"); \ | 200 | : "r1"); \ |
| @@ -211,8 +211,8 @@ extern unsigned long lcopy_to_user(void __user *, const void *, unsigned long); | |||
| 211 | extern unsigned long lcopy_from_user(void *, const void __user *, unsigned long); | 211 | extern unsigned long lcopy_from_user(void *, const void __user *, unsigned long); |
| 212 | extern unsigned long lcopy_in_user(void __user *, const void __user *, unsigned long); | 212 | extern unsigned long lcopy_in_user(void __user *, const void __user *, unsigned long); |
| 213 | extern long strncpy_from_user(char *, const char __user *, long); | 213 | extern long strncpy_from_user(char *, const char __user *, long); |
| 214 | extern unsigned lclear_user(void __user *,unsigned long); | 214 | extern unsigned lclear_user(void __user *, unsigned long); |
| 215 | extern long lstrnlen_user(const char __user *,long); | 215 | extern long lstrnlen_user(const char __user *, long); |
| 216 | /* | 216 | /* |
| 217 | * Complex access routines -- macros | 217 | * Complex access routines -- macros |
| 218 | */ | 218 | */ |
diff --git a/arch/parisc/include/uapi/asm/unistd.h b/arch/parisc/include/uapi/asm/unistd.h index 5f5c0373de63..2e639d7604f6 100644 --- a/arch/parisc/include/uapi/asm/unistd.h +++ b/arch/parisc/include/uapi/asm/unistd.h | |||
| @@ -2,480 +2,6 @@ | |||
| 2 | #define _UAPI_ASM_PARISC_UNISTD_H_ | 2 | #define _UAPI_ASM_PARISC_UNISTD_H_ |
| 3 | 3 | ||
| 4 | /* | 4 | /* |
| 5 | * This file contains the system call numbers. | ||
| 6 | */ | ||
| 7 | |||
| 8 | /* | ||
| 9 | * HP-UX system calls get their native numbers for binary compatibility. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #define __NR_HPUX_exit 1 | ||
| 13 | #define __NR_HPUX_fork 2 | ||
| 14 | #define __NR_HPUX_read 3 | ||
| 15 | #define __NR_HPUX_write 4 | ||
| 16 | #define __NR_HPUX_open 5 | ||
| 17 | #define __NR_HPUX_close 6 | ||
| 18 | #define __NR_HPUX_wait 7 | ||
| 19 | #define __NR_HPUX_creat 8 | ||
| 20 | #define __NR_HPUX_link 9 | ||
| 21 | #define __NR_HPUX_unlink 10 | ||
| 22 | #define __NR_HPUX_execv 11 | ||
| 23 | #define __NR_HPUX_chdir 12 | ||
| 24 | #define __NR_HPUX_time 13 | ||
| 25 | #define __NR_HPUX_mknod 14 | ||
| 26 | #define __NR_HPUX_chmod 15 | ||
| 27 | #define __NR_HPUX_chown 16 | ||
| 28 | #define __NR_HPUX_break 17 | ||
| 29 | #define __NR_HPUX_lchmod 18 | ||
| 30 | #define __NR_HPUX_lseek 19 | ||
| 31 | #define __NR_HPUX_getpid 20 | ||
| 32 | #define __NR_HPUX_mount 21 | ||
| 33 | #define __NR_HPUX_umount 22 | ||
| 34 | #define __NR_HPUX_setuid 23 | ||
| 35 | #define __NR_HPUX_getuid 24 | ||
| 36 | #define __NR_HPUX_stime 25 | ||
| 37 | #define __NR_HPUX_ptrace 26 | ||
| 38 | #define __NR_HPUX_alarm 27 | ||
| 39 | #define __NR_HPUX_oldfstat 28 | ||
| 40 | #define __NR_HPUX_pause 29 | ||
| 41 | #define __NR_HPUX_utime 30 | ||
| 42 | #define __NR_HPUX_stty 31 | ||
| 43 | #define __NR_HPUX_gtty 32 | ||
| 44 | #define __NR_HPUX_access 33 | ||
| 45 | #define __NR_HPUX_nice 34 | ||
| 46 | #define __NR_HPUX_ftime 35 | ||
| 47 | #define __NR_HPUX_sync 36 | ||
| 48 | #define __NR_HPUX_kill 37 | ||
| 49 | #define __NR_HPUX_stat 38 | ||
| 50 | #define __NR_HPUX_setpgrp3 39 | ||
| 51 | #define __NR_HPUX_lstat 40 | ||
| 52 | #define __NR_HPUX_dup 41 | ||
| 53 | #define __NR_HPUX_pipe 42 | ||
| 54 | #define __NR_HPUX_times 43 | ||
| 55 | #define __NR_HPUX_profil 44 | ||
| 56 | #define __NR_HPUX_ki_call 45 | ||
| 57 | #define __NR_HPUX_setgid 46 | ||
| 58 | #define __NR_HPUX_getgid 47 | ||
| 59 | #define __NR_HPUX_sigsys 48 | ||
| 60 | #define __NR_HPUX_reserved1 49 | ||
| 61 | #define __NR_HPUX_reserved2 50 | ||
| 62 | #define __NR_HPUX_acct 51 | ||
| 63 | #define __NR_HPUX_set_userthreadid 52 | ||
| 64 | #define __NR_HPUX_oldlock 53 | ||
| 65 | #define __NR_HPUX_ioctl 54 | ||
| 66 | #define __NR_HPUX_reboot 55 | ||
| 67 | #define __NR_HPUX_symlink 56 | ||
| 68 | #define __NR_HPUX_utssys 57 | ||
| 69 | #define __NR_HPUX_readlink 58 | ||
| 70 | #define __NR_HPUX_execve 59 | ||
| 71 | #define __NR_HPUX_umask 60 | ||
| 72 | #define __NR_HPUX_chroot 61 | ||
| 73 | #define __NR_HPUX_fcntl 62 | ||
| 74 | #define __NR_HPUX_ulimit 63 | ||
| 75 | #define __NR_HPUX_getpagesize 64 | ||
| 76 | #define __NR_HPUX_mremap 65 | ||
| 77 | #define __NR_HPUX_vfork 66 | ||
| 78 | #define __NR_HPUX_vread 67 | ||
| 79 | #define __NR_HPUX_vwrite 68 | ||
| 80 | #define __NR_HPUX_sbrk 69 | ||
| 81 | #define __NR_HPUX_sstk 70 | ||
| 82 | #define __NR_HPUX_mmap 71 | ||
| 83 | #define __NR_HPUX_vadvise 72 | ||
| 84 | #define __NR_HPUX_munmap 73 | ||
| 85 | #define __NR_HPUX_mprotect 74 | ||
| 86 | #define __NR_HPUX_madvise 75 | ||
| 87 | #define __NR_HPUX_vhangup 76 | ||
| 88 | #define __NR_HPUX_swapoff 77 | ||
| 89 | #define __NR_HPUX_mincore 78 | ||
| 90 | #define __NR_HPUX_getgroups 79 | ||
| 91 | #define __NR_HPUX_setgroups 80 | ||
| 92 | #define __NR_HPUX_getpgrp2 81 | ||
| 93 | #define __NR_HPUX_setpgrp2 82 | ||
| 94 | #define __NR_HPUX_setitimer 83 | ||
| 95 | #define __NR_HPUX_wait3 84 | ||
| 96 | #define __NR_HPUX_swapon 85 | ||
| 97 | #define __NR_HPUX_getitimer 86 | ||
| 98 | #define __NR_HPUX_gethostname42 87 | ||
| 99 | #define __NR_HPUX_sethostname42 88 | ||
| 100 | #define __NR_HPUX_getdtablesize 89 | ||
| 101 | #define __NR_HPUX_dup2 90 | ||
| 102 | #define __NR_HPUX_getdopt 91 | ||
| 103 | #define __NR_HPUX_fstat 92 | ||
| 104 | #define __NR_HPUX_select 93 | ||
| 105 | #define __NR_HPUX_setdopt 94 | ||
| 106 | #define __NR_HPUX_fsync 95 | ||
| 107 | #define __NR_HPUX_setpriority 96 | ||
| 108 | #define __NR_HPUX_socket_old 97 | ||
| 109 | #define __NR_HPUX_connect_old 98 | ||
| 110 | #define __NR_HPUX_accept_old 99 | ||
| 111 | #define __NR_HPUX_getpriority 100 | ||
| 112 | #define __NR_HPUX_send_old 101 | ||
| 113 | #define __NR_HPUX_recv_old 102 | ||
| 114 | #define __NR_HPUX_socketaddr_old 103 | ||
| 115 | #define __NR_HPUX_bind_old 104 | ||
| 116 | #define __NR_HPUX_setsockopt_old 105 | ||
| 117 | #define __NR_HPUX_listen_old 106 | ||
| 118 | #define __NR_HPUX_vtimes_old 107 | ||
| 119 | #define __NR_HPUX_sigvector 108 | ||
| 120 | #define __NR_HPUX_sigblock 109 | ||
| 121 | #define __NR_HPUX_siggetmask 110 | ||
| 122 | #define __NR_HPUX_sigpause 111 | ||
| 123 | #define __NR_HPUX_sigstack 112 | ||
| 124 | #define __NR_HPUX_recvmsg_old 113 | ||
| 125 | #define __NR_HPUX_sendmsg_old 114 | ||
| 126 | #define __NR_HPUX_vtrace_old 115 | ||
| 127 | #define __NR_HPUX_gettimeofday 116 | ||
| 128 | #define __NR_HPUX_getrusage 117 | ||
| 129 | #define __NR_HPUX_getsockopt_old 118 | ||
| 130 | #define __NR_HPUX_resuba_old 119 | ||
| 131 | #define __NR_HPUX_readv 120 | ||
| 132 | #define __NR_HPUX_writev 121 | ||
| 133 | #define __NR_HPUX_settimeofday 122 | ||
| 134 | #define __NR_HPUX_fchown 123 | ||
| 135 | #define __NR_HPUX_fchmod 124 | ||
| 136 | #define __NR_HPUX_recvfrom_old 125 | ||
| 137 | #define __NR_HPUX_setresuid 126 | ||
| 138 | #define __NR_HPUX_setresgid 127 | ||
| 139 | #define __NR_HPUX_rename 128 | ||
| 140 | #define __NR_HPUX_truncate 129 | ||
| 141 | #define __NR_HPUX_ftruncate 130 | ||
| 142 | #define __NR_HPUX_flock_old 131 | ||
| 143 | #define __NR_HPUX_sysconf 132 | ||
| 144 | #define __NR_HPUX_sendto_old 133 | ||
| 145 | #define __NR_HPUX_shutdown_old 134 | ||
| 146 | #define __NR_HPUX_socketpair_old 135 | ||
| 147 | #define __NR_HPUX_mkdir 136 | ||
| 148 | #define __NR_HPUX_rmdir 137 | ||
| 149 | #define __NR_HPUX_utimes_old 138 | ||
| 150 | #define __NR_HPUX_sigcleanup_old 139 | ||
| 151 | #define __NR_HPUX_setcore 140 | ||
| 152 | #define __NR_HPUX_getpeername_old 141 | ||
| 153 | #define __NR_HPUX_gethostid 142 | ||
| 154 | #define __NR_HPUX_sethostid 143 | ||
| 155 | #define __NR_HPUX_getrlimit 144 | ||
| 156 | #define __NR_HPUX_setrlimit 145 | ||
| 157 | #define __NR_HPUX_killpg_old 146 | ||
| 158 | #define __NR_HPUX_cachectl 147 | ||
| 159 | #define __NR_HPUX_quotactl 148 | ||
| 160 | #define __NR_HPUX_get_sysinfo 149 | ||
| 161 | #define __NR_HPUX_getsockname_old 150 | ||
| 162 | #define __NR_HPUX_privgrp 151 | ||
| 163 | #define __NR_HPUX_rtprio 152 | ||
| 164 | #define __NR_HPUX_plock 153 | ||
| 165 | #define __NR_HPUX_reserved3 154 | ||
| 166 | #define __NR_HPUX_lockf 155 | ||
| 167 | #define __NR_HPUX_semget 156 | ||
| 168 | #define __NR_HPUX_osemctl 157 | ||
| 169 | #define __NR_HPUX_semop 158 | ||
| 170 | #define __NR_HPUX_msgget 159 | ||
| 171 | #define __NR_HPUX_omsgctl 160 | ||
| 172 | #define __NR_HPUX_msgsnd 161 | ||
| 173 | #define __NR_HPUX_msgrecv 162 | ||
| 174 | #define __NR_HPUX_shmget 163 | ||
| 175 | #define __NR_HPUX_oshmctl 164 | ||
| 176 | #define __NR_HPUX_shmat 165 | ||
| 177 | #define __NR_HPUX_shmdt 166 | ||
| 178 | #define __NR_HPUX_m68020_advise 167 | ||
| 179 | /* [168,189] are for Discless/DUX */ | ||
| 180 | #define __NR_HPUX_csp 168 | ||
| 181 | #define __NR_HPUX_cluster 169 | ||
| 182 | #define __NR_HPUX_mkrnod 170 | ||
| 183 | #define __NR_HPUX_test 171 | ||
| 184 | #define __NR_HPUX_unsp_open 172 | ||
| 185 | #define __NR_HPUX_reserved4 173 | ||
| 186 | #define __NR_HPUX_getcontext_old 174 | ||
| 187 | #define __NR_HPUX_osetcontext 175 | ||
| 188 | #define __NR_HPUX_bigio 176 | ||
| 189 | #define __NR_HPUX_pipenode 177 | ||
| 190 | #define __NR_HPUX_lsync 178 | ||
| 191 | #define __NR_HPUX_getmachineid 179 | ||
| 192 | #define __NR_HPUX_cnodeid 180 | ||
| 193 | #define __NR_HPUX_cnodes 181 | ||
| 194 | #define __NR_HPUX_swapclients 182 | ||
| 195 | #define __NR_HPUX_rmt_process 183 | ||
| 196 | #define __NR_HPUX_dskless_stats 184 | ||
| 197 | #define __NR_HPUX_sigprocmask 185 | ||
| 198 | #define __NR_HPUX_sigpending 186 | ||
| 199 | #define __NR_HPUX_sigsuspend 187 | ||
| 200 | #define __NR_HPUX_sigaction 188 | ||
| 201 | #define __NR_HPUX_reserved5 189 | ||
| 202 | #define __NR_HPUX_nfssvc 190 | ||
| 203 | #define __NR_HPUX_getfh 191 | ||
| 204 | #define __NR_HPUX_getdomainname 192 | ||
| 205 | #define __NR_HPUX_setdomainname 193 | ||
| 206 | #define __NR_HPUX_async_daemon 194 | ||
| 207 | #define __NR_HPUX_getdirentries 195 | ||
| 208 | #define __NR_HPUX_statfs 196 | ||
| 209 | #define __NR_HPUX_fstatfs 197 | ||
| 210 | #define __NR_HPUX_vfsmount 198 | ||
| 211 | #define __NR_HPUX_reserved6 199 | ||
| 212 | #define __NR_HPUX_waitpid 200 | ||
| 213 | /* 201 - 223 missing */ | ||
| 214 | #define __NR_HPUX_sigsetreturn 224 | ||
| 215 | #define __NR_HPUX_sigsetstatemask 225 | ||
| 216 | /* 226 missing */ | ||
| 217 | #define __NR_HPUX_cs 227 | ||
| 218 | #define __NR_HPUX_cds 228 | ||
| 219 | #define __NR_HPUX_set_no_trunc 229 | ||
| 220 | #define __NR_HPUX_pathconf 230 | ||
| 221 | #define __NR_HPUX_fpathconf 231 | ||
| 222 | /* 232, 233 missing */ | ||
| 223 | #define __NR_HPUX_nfs_fcntl 234 | ||
| 224 | #define __NR_HPUX_ogetacl 235 | ||
| 225 | #define __NR_HPUX_ofgetacl 236 | ||
| 226 | #define __NR_HPUX_osetacl 237 | ||
| 227 | #define __NR_HPUX_ofsetacl 238 | ||
| 228 | #define __NR_HPUX_pstat 239 | ||
| 229 | #define __NR_HPUX_getaudid 240 | ||
| 230 | #define __NR_HPUX_setaudid 241 | ||
| 231 | #define __NR_HPUX_getaudproc 242 | ||
| 232 | #define __NR_HPUX_setaudproc 243 | ||
| 233 | #define __NR_HPUX_getevent 244 | ||
| 234 | #define __NR_HPUX_setevent 245 | ||
| 235 | #define __NR_HPUX_audwrite 246 | ||
| 236 | #define __NR_HPUX_audswitch 247 | ||
| 237 | #define __NR_HPUX_audctl 248 | ||
| 238 | #define __NR_HPUX_ogetaccess 249 | ||
| 239 | #define __NR_HPUX_fsctl 250 | ||
| 240 | /* 251 - 258 missing */ | ||
| 241 | #define __NR_HPUX_swapfs 259 | ||
| 242 | #define __NR_HPUX_fss 260 | ||
| 243 | /* 261 - 266 missing */ | ||
| 244 | #define __NR_HPUX_tsync 267 | ||
| 245 | #define __NR_HPUX_getnumfds 268 | ||
| 246 | #define __NR_HPUX_poll 269 | ||
| 247 | #define __NR_HPUX_getmsg 270 | ||
| 248 | #define __NR_HPUX_putmsg 271 | ||
| 249 | #define __NR_HPUX_fchdir 272 | ||
| 250 | #define __NR_HPUX_getmount_cnt 273 | ||
| 251 | #define __NR_HPUX_getmount_entry 274 | ||
| 252 | #define __NR_HPUX_accept 275 | ||
| 253 | #define __NR_HPUX_bind 276 | ||
| 254 | #define __NR_HPUX_connect 277 | ||
| 255 | #define __NR_HPUX_getpeername 278 | ||
| 256 | #define __NR_HPUX_getsockname 279 | ||
| 257 | #define __NR_HPUX_getsockopt 280 | ||
| 258 | #define __NR_HPUX_listen 281 | ||
| 259 | #define __NR_HPUX_recv 282 | ||
| 260 | #define __NR_HPUX_recvfrom 283 | ||
| 261 | #define __NR_HPUX_recvmsg 284 | ||
| 262 | #define __NR_HPUX_send 285 | ||
| 263 | #define __NR_HPUX_sendmsg 286 | ||
| 264 | #define __NR_HPUX_sendto 287 | ||
| 265 | #define __NR_HPUX_setsockopt 288 | ||
| 266 | #define __NR_HPUX_shutdown 289 | ||
| 267 | #define __NR_HPUX_socket 290 | ||
| 268 | #define __NR_HPUX_socketpair 291 | ||
| 269 | #define __NR_HPUX_proc_open 292 | ||
| 270 | #define __NR_HPUX_proc_close 293 | ||
| 271 | #define __NR_HPUX_proc_send 294 | ||
| 272 | #define __NR_HPUX_proc_recv 295 | ||
| 273 | #define __NR_HPUX_proc_sendrecv 296 | ||
| 274 | #define __NR_HPUX_proc_syscall 297 | ||
| 275 | /* 298 - 311 missing */ | ||
| 276 | #define __NR_HPUX_semctl 312 | ||
| 277 | #define __NR_HPUX_msgctl 313 | ||
| 278 | #define __NR_HPUX_shmctl 314 | ||
| 279 | #define __NR_HPUX_mpctl 315 | ||
| 280 | #define __NR_HPUX_exportfs 316 | ||
| 281 | #define __NR_HPUX_getpmsg 317 | ||
| 282 | #define __NR_HPUX_putpmsg 318 | ||
| 283 | /* 319 missing */ | ||
| 284 | #define __NR_HPUX_msync 320 | ||
| 285 | #define __NR_HPUX_msleep 321 | ||
| 286 | #define __NR_HPUX_mwakeup 322 | ||
| 287 | #define __NR_HPUX_msem_init 323 | ||
| 288 | #define __NR_HPUX_msem_remove 324 | ||
| 289 | #define __NR_HPUX_adjtime 325 | ||
| 290 | #define __NR_HPUX_kload 326 | ||
| 291 | #define __NR_HPUX_fattach 327 | ||
| 292 | #define __NR_HPUX_fdetach 328 | ||
| 293 | #define __NR_HPUX_serialize 329 | ||
| 294 | #define __NR_HPUX_statvfs 330 | ||
| 295 | #define __NR_HPUX_fstatvfs 331 | ||
| 296 | #define __NR_HPUX_lchown 332 | ||
| 297 | #define __NR_HPUX_getsid 333 | ||
| 298 | #define __NR_HPUX_sysfs 334 | ||
| 299 | /* 335, 336 missing */ | ||
| 300 | #define __NR_HPUX_sched_setparam 337 | ||
| 301 | #define __NR_HPUX_sched_getparam 338 | ||
| 302 | #define __NR_HPUX_sched_setscheduler 339 | ||
| 303 | #define __NR_HPUX_sched_getscheduler 340 | ||
| 304 | #define __NR_HPUX_sched_yield 341 | ||
| 305 | #define __NR_HPUX_sched_get_priority_max 342 | ||
| 306 | #define __NR_HPUX_sched_get_priority_min 343 | ||
| 307 | #define __NR_HPUX_sched_rr_get_interval 344 | ||
| 308 | #define __NR_HPUX_clock_settime 345 | ||
| 309 | #define __NR_HPUX_clock_gettime 346 | ||
| 310 | #define __NR_HPUX_clock_getres 347 | ||
| 311 | #define __NR_HPUX_timer_create 348 | ||
| 312 | #define __NR_HPUX_timer_delete 349 | ||
| 313 | #define __NR_HPUX_timer_settime 350 | ||
| 314 | #define __NR_HPUX_timer_gettime 351 | ||
| 315 | #define __NR_HPUX_timer_getoverrun 352 | ||
| 316 | #define __NR_HPUX_nanosleep 353 | ||
| 317 | #define __NR_HPUX_toolbox 354 | ||
| 318 | /* 355 missing */ | ||
| 319 | #define __NR_HPUX_getdents 356 | ||
| 320 | #define __NR_HPUX_getcontext 357 | ||
| 321 | #define __NR_HPUX_sysinfo 358 | ||
| 322 | #define __NR_HPUX_fcntl64 359 | ||
| 323 | #define __NR_HPUX_ftruncate64 360 | ||
| 324 | #define __NR_HPUX_fstat64 361 | ||
| 325 | #define __NR_HPUX_getdirentries64 362 | ||
| 326 | #define __NR_HPUX_getrlimit64 363 | ||
| 327 | #define __NR_HPUX_lockf64 364 | ||
| 328 | #define __NR_HPUX_lseek64 365 | ||
| 329 | #define __NR_HPUX_lstat64 366 | ||
| 330 | #define __NR_HPUX_mmap64 367 | ||
| 331 | #define __NR_HPUX_setrlimit64 368 | ||
| 332 | #define __NR_HPUX_stat64 369 | ||
| 333 | #define __NR_HPUX_truncate64 370 | ||
| 334 | #define __NR_HPUX_ulimit64 371 | ||
| 335 | #define __NR_HPUX_pread 372 | ||
| 336 | #define __NR_HPUX_preadv 373 | ||
| 337 | #define __NR_HPUX_pwrite 374 | ||
| 338 | #define __NR_HPUX_pwritev 375 | ||
| 339 | #define __NR_HPUX_pread64 376 | ||
| 340 | #define __NR_HPUX_preadv64 377 | ||
| 341 | #define __NR_HPUX_pwrite64 378 | ||
| 342 | #define __NR_HPUX_pwritev64 379 | ||
| 343 | #define __NR_HPUX_setcontext 380 | ||
| 344 | #define __NR_HPUX_sigaltstack 381 | ||
| 345 | #define __NR_HPUX_waitid 382 | ||
| 346 | #define __NR_HPUX_setpgrp 383 | ||
| 347 | #define __NR_HPUX_recvmsg2 384 | ||
| 348 | #define __NR_HPUX_sendmsg2 385 | ||
| 349 | #define __NR_HPUX_socket2 386 | ||
| 350 | #define __NR_HPUX_socketpair2 387 | ||
| 351 | #define __NR_HPUX_setregid 388 | ||
| 352 | #define __NR_HPUX_lwp_create 389 | ||
| 353 | #define __NR_HPUX_lwp_terminate 390 | ||
| 354 | #define __NR_HPUX_lwp_wait 391 | ||
| 355 | #define __NR_HPUX_lwp_suspend 392 | ||
| 356 | #define __NR_HPUX_lwp_resume 393 | ||
| 357 | /* 394 missing */ | ||
| 358 | #define __NR_HPUX_lwp_abort_syscall 395 | ||
| 359 | #define __NR_HPUX_lwp_info 396 | ||
| 360 | #define __NR_HPUX_lwp_kill 397 | ||
| 361 | #define __NR_HPUX_ksleep 398 | ||
| 362 | #define __NR_HPUX_kwakeup 399 | ||
| 363 | /* 400 missing */ | ||
| 364 | #define __NR_HPUX_pstat_getlwp 401 | ||
| 365 | #define __NR_HPUX_lwp_exit 402 | ||
| 366 | #define __NR_HPUX_lwp_continue 403 | ||
| 367 | #define __NR_HPUX_getacl 404 | ||
| 368 | #define __NR_HPUX_fgetacl 405 | ||
| 369 | #define __NR_HPUX_setacl 406 | ||
| 370 | #define __NR_HPUX_fsetacl 407 | ||
| 371 | #define __NR_HPUX_getaccess 408 | ||
| 372 | #define __NR_HPUX_lwp_mutex_init 409 | ||
| 373 | #define __NR_HPUX_lwp_mutex_lock_sys 410 | ||
| 374 | #define __NR_HPUX_lwp_mutex_unlock 411 | ||
| 375 | #define __NR_HPUX_lwp_cond_init 412 | ||
| 376 | #define __NR_HPUX_lwp_cond_signal 413 | ||
| 377 | #define __NR_HPUX_lwp_cond_broadcast 414 | ||
| 378 | #define __NR_HPUX_lwp_cond_wait_sys 415 | ||
| 379 | #define __NR_HPUX_lwp_getscheduler 416 | ||
| 380 | #define __NR_HPUX_lwp_setscheduler 417 | ||
| 381 | #define __NR_HPUX_lwp_getstate 418 | ||
| 382 | #define __NR_HPUX_lwp_setstate 419 | ||
| 383 | #define __NR_HPUX_lwp_detach 420 | ||
| 384 | #define __NR_HPUX_mlock 421 | ||
| 385 | #define __NR_HPUX_munlock 422 | ||
| 386 | #define __NR_HPUX_mlockall 423 | ||
| 387 | #define __NR_HPUX_munlockall 424 | ||
| 388 | #define __NR_HPUX_shm_open 425 | ||
| 389 | #define __NR_HPUX_shm_unlink 426 | ||
| 390 | #define __NR_HPUX_sigqueue 427 | ||
| 391 | #define __NR_HPUX_sigwaitinfo 428 | ||
| 392 | #define __NR_HPUX_sigtimedwait 429 | ||
| 393 | #define __NR_HPUX_sigwait 430 | ||
| 394 | #define __NR_HPUX_aio_read 431 | ||
| 395 | #define __NR_HPUX_aio_write 432 | ||
| 396 | #define __NR_HPUX_lio_listio 433 | ||
| 397 | #define __NR_HPUX_aio_error 434 | ||
| 398 | #define __NR_HPUX_aio_return 435 | ||
| 399 | #define __NR_HPUX_aio_cancel 436 | ||
| 400 | #define __NR_HPUX_aio_suspend 437 | ||
| 401 | #define __NR_HPUX_aio_fsync 438 | ||
| 402 | #define __NR_HPUX_mq_open 439 | ||
| 403 | #define __NR_HPUX_mq_close 440 | ||
| 404 | #define __NR_HPUX_mq_unlink 441 | ||
| 405 | #define __NR_HPUX_mq_send 442 | ||
| 406 | #define __NR_HPUX_mq_receive 443 | ||
| 407 | #define __NR_HPUX_mq_notify 444 | ||
| 408 | #define __NR_HPUX_mq_setattr 445 | ||
| 409 | #define __NR_HPUX_mq_getattr 446 | ||
| 410 | #define __NR_HPUX_ksem_open 447 | ||
| 411 | #define __NR_HPUX_ksem_unlink 448 | ||
| 412 | #define __NR_HPUX_ksem_close 449 | ||
| 413 | #define __NR_HPUX_ksem_post 450 | ||
| 414 | #define __NR_HPUX_ksem_wait 451 | ||
| 415 | #define __NR_HPUX_ksem_read 452 | ||
| 416 | #define __NR_HPUX_ksem_trywait 453 | ||
| 417 | #define __NR_HPUX_lwp_rwlock_init 454 | ||
| 418 | #define __NR_HPUX_lwp_rwlock_destroy 455 | ||
| 419 | #define __NR_HPUX_lwp_rwlock_rdlock_sys 456 | ||
| 420 | #define __NR_HPUX_lwp_rwlock_wrlock_sys 457 | ||
| 421 | #define __NR_HPUX_lwp_rwlock_tryrdlock 458 | ||
| 422 | #define __NR_HPUX_lwp_rwlock_trywrlock 459 | ||
| 423 | #define __NR_HPUX_lwp_rwlock_unlock 460 | ||
| 424 | #define __NR_HPUX_ttrace 461 | ||
| 425 | #define __NR_HPUX_ttrace_wait 462 | ||
| 426 | #define __NR_HPUX_lf_wire_mem 463 | ||
| 427 | #define __NR_HPUX_lf_unwire_mem 464 | ||
| 428 | #define __NR_HPUX_lf_send_pin_map 465 | ||
| 429 | #define __NR_HPUX_lf_free_buf 466 | ||
| 430 | #define __NR_HPUX_lf_wait_nq 467 | ||
| 431 | #define __NR_HPUX_lf_wakeup_conn_q 468 | ||
| 432 | #define __NR_HPUX_lf_unused 469 | ||
| 433 | #define __NR_HPUX_lwp_sema_init 470 | ||
| 434 | #define __NR_HPUX_lwp_sema_post 471 | ||
| 435 | #define __NR_HPUX_lwp_sema_wait 472 | ||
| 436 | #define __NR_HPUX_lwp_sema_trywait 473 | ||
| 437 | #define __NR_HPUX_lwp_sema_destroy 474 | ||
| 438 | #define __NR_HPUX_statvfs64 475 | ||
| 439 | #define __NR_HPUX_fstatvfs64 476 | ||
| 440 | #define __NR_HPUX_msh_register 477 | ||
| 441 | #define __NR_HPUX_ptrace64 478 | ||
| 442 | #define __NR_HPUX_sendfile 479 | ||
| 443 | #define __NR_HPUX_sendpath 480 | ||
| 444 | #define __NR_HPUX_sendfile64 481 | ||
| 445 | #define __NR_HPUX_sendpath64 482 | ||
| 446 | #define __NR_HPUX_modload 483 | ||
| 447 | #define __NR_HPUX_moduload 484 | ||
| 448 | #define __NR_HPUX_modpath 485 | ||
| 449 | #define __NR_HPUX_getksym 486 | ||
| 450 | #define __NR_HPUX_modadm 487 | ||
| 451 | #define __NR_HPUX_modstat 488 | ||
| 452 | #define __NR_HPUX_lwp_detached_exit 489 | ||
| 453 | #define __NR_HPUX_crashconf 490 | ||
| 454 | #define __NR_HPUX_siginhibit 491 | ||
| 455 | #define __NR_HPUX_sigenable 492 | ||
| 456 | #define __NR_HPUX_spuctl 493 | ||
| 457 | #define __NR_HPUX_zerokernelsum 494 | ||
| 458 | #define __NR_HPUX_nfs_kstat 495 | ||
| 459 | #define __NR_HPUX_aio_read64 496 | ||
| 460 | #define __NR_HPUX_aio_write64 497 | ||
| 461 | #define __NR_HPUX_aio_error64 498 | ||
| 462 | #define __NR_HPUX_aio_return64 499 | ||
| 463 | #define __NR_HPUX_aio_cancel64 500 | ||
| 464 | #define __NR_HPUX_aio_suspend64 501 | ||
| 465 | #define __NR_HPUX_aio_fsync64 502 | ||
| 466 | #define __NR_HPUX_lio_listio64 503 | ||
| 467 | #define __NR_HPUX_recv2 504 | ||
| 468 | #define __NR_HPUX_recvfrom2 505 | ||
| 469 | #define __NR_HPUX_send2 506 | ||
| 470 | #define __NR_HPUX_sendto2 507 | ||
| 471 | #define __NR_HPUX_acl 508 | ||
| 472 | #define __NR_HPUX___cnx_p2p_ctl 509 | ||
| 473 | #define __NR_HPUX___cnx_gsched_ctl 510 | ||
| 474 | #define __NR_HPUX___cnx_pmon_ctl 511 | ||
| 475 | |||
| 476 | #define __NR_HPUX_syscalls 512 | ||
| 477 | |||
| 478 | /* | ||
| 479 | * Linux system call numbers. | 5 | * Linux system call numbers. |
| 480 | * | 6 | * |
| 481 | * Cary Coutant says that we should just use another syscall gateway | 7 | * Cary Coutant says that we should just use another syscall gateway |
| @@ -484,9 +10,6 @@ | |||
| 484 | * very least. If we decide to change it later, we can ``just'' tweak | 10 | * very least. If we decide to change it later, we can ``just'' tweak |
| 485 | * the LINUX_GATEWAY_ADDR define at the bottom and make __NR_Linux be | 11 | * the LINUX_GATEWAY_ADDR define at the bottom and make __NR_Linux be |
| 486 | * 1024 or something. Oh, and recompile libc. =) | 12 | * 1024 or something. Oh, and recompile libc. =) |
| 487 | * | ||
| 488 | * 64-bit HPUX binaries get the syscall gateway address passed in a register | ||
| 489 | * from the kernel at startup, which seems a sane strategy. | ||
| 490 | */ | 13 | */ |
| 491 | 14 | ||
| 492 | #define __NR_Linux 0 | 15 | #define __NR_Linux 0 |
| @@ -834,15 +357,15 @@ | |||
| 834 | #define __NR_getrandom (__NR_Linux + 339) | 357 | #define __NR_getrandom (__NR_Linux + 339) |
| 835 | #define __NR_memfd_create (__NR_Linux + 340) | 358 | #define __NR_memfd_create (__NR_Linux + 340) |
| 836 | #define __NR_bpf (__NR_Linux + 341) | 359 | #define __NR_bpf (__NR_Linux + 341) |
| 360 | #define __NR_execveat (__NR_Linux + 342) | ||
| 837 | 361 | ||
| 838 | #define __NR_Linux_syscalls (__NR_bpf + 1) | 362 | #define __NR_Linux_syscalls (__NR_execveat + 1) |
| 839 | 363 | ||
| 840 | 364 | ||
| 841 | #define __IGNORE_select /* newselect */ | 365 | #define __IGNORE_select /* newselect */ |
| 842 | #define __IGNORE_fadvise64 /* fadvise64_64 */ | 366 | #define __IGNORE_fadvise64 /* fadvise64_64 */ |
| 843 | 367 | ||
| 844 | 368 | ||
| 845 | #define HPUX_GATEWAY_ADDR 0xC0000004 | ||
| 846 | #define LINUX_GATEWAY_ADDR 0x100 | 369 | #define LINUX_GATEWAY_ADDR 0x100 |
| 847 | 370 | ||
| 848 | #endif /* _UAPI_ASM_PARISC_UNISTD_H_ */ | 371 | #endif /* _UAPI_ASM_PARISC_UNISTD_H_ */ |
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index e8f07dd28401..2ab16bb160a8 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S | |||
| @@ -1774,10 +1774,6 @@ ENTRY(sys_rt_sigreturn_wrapper) | |||
| 1774 | ENDPROC(sys_rt_sigreturn_wrapper) | 1774 | ENDPROC(sys_rt_sigreturn_wrapper) |
| 1775 | 1775 | ||
| 1776 | ENTRY(syscall_exit) | 1776 | ENTRY(syscall_exit) |
| 1777 | /* NOTE: HP-UX syscalls also come through here | ||
| 1778 | * after hpux_syscall_exit fixes up return | ||
| 1779 | * values. */ | ||
| 1780 | |||
| 1781 | /* NOTE: Not all syscalls exit this way. rt_sigreturn will exit | 1777 | /* NOTE: Not all syscalls exit this way. rt_sigreturn will exit |
| 1782 | * via syscall_exit_rfi if the signal was received while the process | 1778 | * via syscall_exit_rfi if the signal was received while the process |
| 1783 | * was running. | 1779 | * was running. |
| @@ -1789,22 +1785,6 @@ ENTRY(syscall_exit) | |||
| 1789 | LDREG TI_TASK(%r1),%r1 | 1785 | LDREG TI_TASK(%r1),%r1 |
| 1790 | STREG %r28,TASK_PT_GR28(%r1) | 1786 | STREG %r28,TASK_PT_GR28(%r1) |
| 1791 | 1787 | ||
| 1792 | #ifdef CONFIG_HPUX | ||
| 1793 | /* <linux/personality.h> cannot be easily included */ | ||
| 1794 | #define PER_HPUX 0x10 | ||
| 1795 | ldw TASK_PERSONALITY(%r1),%r19 | ||
| 1796 | |||
| 1797 | /* We can't use "CMPIB<> PER_HPUX" since "im5" field is sign extended */ | ||
| 1798 | ldo -PER_HPUX(%r19), %r19 | ||
| 1799 | cmpib,COND(<>),n 0,%r19,1f | ||
| 1800 | |||
| 1801 | /* Save other hpux returns if personality is PER_HPUX */ | ||
| 1802 | STREG %r22,TASK_PT_GR22(%r1) | ||
| 1803 | STREG %r29,TASK_PT_GR29(%r1) | ||
| 1804 | 1: | ||
| 1805 | |||
| 1806 | #endif /* CONFIG_HPUX */ | ||
| 1807 | |||
| 1808 | /* Seems to me that dp could be wrong here, if the syscall involved | 1788 | /* Seems to me that dp could be wrong here, if the syscall involved |
| 1809 | * calling a module, and nothing got round to restoring dp on return. | 1789 | * calling a module, and nothing got round to restoring dp on return. |
| 1810 | */ | 1790 | */ |
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 0bbbf0d3f608..8a488c22a99f 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c | |||
| @@ -193,9 +193,7 @@ copy_thread(unsigned long clone_flags, unsigned long usp, | |||
| 193 | * Make them const so the compiler knows they live in .text */ | 193 | * Make them const so the compiler knows they live in .text */ |
| 194 | extern void * const ret_from_kernel_thread; | 194 | extern void * const ret_from_kernel_thread; |
| 195 | extern void * const child_return; | 195 | extern void * const child_return; |
| 196 | #ifdef CONFIG_HPUX | 196 | |
| 197 | extern void * const hpux_child_return; | ||
| 198 | #endif | ||
| 199 | if (unlikely(p->flags & PF_KTHREAD)) { | 197 | if (unlikely(p->flags & PF_KTHREAD)) { |
| 200 | memset(cregs, 0, sizeof(struct pt_regs)); | 198 | memset(cregs, 0, sizeof(struct pt_regs)); |
| 201 | if (!usp) /* idle thread */ | 199 | if (!usp) /* idle thread */ |
| @@ -229,15 +227,8 @@ copy_thread(unsigned long clone_flags, unsigned long usp, | |||
| 229 | cregs->gr[30] = usp; | 227 | cregs->gr[30] = usp; |
| 230 | } | 228 | } |
| 231 | cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE; | 229 | cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE; |
| 232 | if (personality(p->personality) == PER_HPUX) { | 230 | cregs->kpc = (unsigned long) &child_return; |
| 233 | #ifdef CONFIG_HPUX | 231 | |
| 234 | cregs->kpc = (unsigned long) &hpux_child_return; | ||
| 235 | #else | ||
| 236 | BUG(); | ||
| 237 | #endif | ||
| 238 | } else { | ||
| 239 | cregs->kpc = (unsigned long) &child_return; | ||
| 240 | } | ||
| 241 | /* Setup thread TLS area from the 4th parameter in clone */ | 232 | /* Setup thread TLS area from the 4th parameter in clone */ |
| 242 | if (clone_flags & CLONE_SETTLS) | 233 | if (clone_flags & CLONE_SETTLS) |
| 243 | cregs->cr27 = cregs->gr[23]; | 234 | cregs->cr27 = cregs->gr[23]; |
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c index 9b910a0251b8..dc1ea796fd60 100644 --- a/arch/parisc/kernel/signal.c +++ b/arch/parisc/kernel/signal.c | |||
| @@ -9,8 +9,7 @@ | |||
| 9 | * | 9 | * |
| 10 | * Like the IA-64, we are a recent enough port (we are *starting* | 10 | * Like the IA-64, we are a recent enough port (we are *starting* |
| 11 | * with glibc2.2) that we do not need to support the old non-realtime | 11 | * with glibc2.2) that we do not need to support the old non-realtime |
| 12 | * Linux signals. Therefore we don't. HP/UX signals will go in | 12 | * Linux signals. Therefore we don't. |
| 13 | * arch/parisc/hpux/signal.c when we figure out how to do them. | ||
| 14 | */ | 13 | */ |
| 15 | 14 | ||
| 16 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
| @@ -476,6 +475,9 @@ insert_restart_trampoline(struct pt_regs *regs) | |||
| 476 | case -ERESTART_RESTARTBLOCK: { | 475 | case -ERESTART_RESTARTBLOCK: { |
| 477 | /* Restart the system call - no handlers present */ | 476 | /* Restart the system call - no handlers present */ |
| 478 | unsigned int *usp = (unsigned int *)regs->gr[30]; | 477 | unsigned int *usp = (unsigned int *)regs->gr[30]; |
| 478 | unsigned long start = (unsigned long) &usp[2]; | ||
| 479 | unsigned long end = (unsigned long) &usp[5]; | ||
| 480 | long err = 0; | ||
| 479 | 481 | ||
| 480 | /* Setup a trampoline to restart the syscall | 482 | /* Setup a trampoline to restart the syscall |
| 481 | * with __NR_restart_syscall | 483 | * with __NR_restart_syscall |
| @@ -487,23 +489,21 @@ insert_restart_trampoline(struct pt_regs *regs) | |||
| 487 | * 16: ldi __NR_restart_syscall, %r20 | 489 | * 16: ldi __NR_restart_syscall, %r20 |
| 488 | */ | 490 | */ |
| 489 | #ifdef CONFIG_64BIT | 491 | #ifdef CONFIG_64BIT |
| 490 | put_user(regs->gr[31] >> 32, &usp[0]); | 492 | err |= put_user(regs->gr[31] >> 32, &usp[0]); |
| 491 | put_user(regs->gr[31] & 0xffffffff, &usp[1]); | 493 | err |= put_user(regs->gr[31] & 0xffffffff, &usp[1]); |
| 492 | put_user(0x0fc010df, &usp[2]); | 494 | err |= put_user(0x0fc010df, &usp[2]); |
| 493 | #else | 495 | #else |
| 494 | put_user(regs->gr[31], &usp[0]); | 496 | err |= put_user(regs->gr[31], &usp[0]); |
| 495 | put_user(0x0fc0109f, &usp[2]); | 497 | err |= put_user(0x0fc0109f, &usp[2]); |
| 496 | #endif | 498 | #endif |
| 497 | put_user(0xe0008200, &usp[3]); | 499 | err |= put_user(0xe0008200, &usp[3]); |
| 498 | put_user(0x34140000, &usp[4]); | 500 | err |= put_user(0x34140000, &usp[4]); |
| 499 | 501 | ||
| 500 | /* Stack is 64-byte aligned, and we only need | 502 | WARN_ON(err); |
| 501 | * to flush 1 cache line. | 503 | |
| 502 | * Flushing one cacheline is cheap. | 504 | /* flush data/instruction cache for new insns */ |
| 503 | * "sync" on bigger (> 4 way) boxes is not. | 505 | flush_user_dcache_range(start, end); |
| 504 | */ | 506 | flush_user_icache_range(start, end); |
| 505 | flush_user_dcache_range(regs->gr[30], regs->gr[30] + 4); | ||
| 506 | flush_user_icache_range(regs->gr[30], regs->gr[30] + 4); | ||
| 507 | 507 | ||
| 508 | regs->gr[31] = regs->gr[30] + 8; | 508 | regs->gr[31] = regs->gr[30] + 8; |
| 509 | return; | 509 | return; |
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index ceda229ea6c2..52e85973a283 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c | |||
| @@ -230,9 +230,6 @@ send_IPI_allbutself(enum ipi_message_type op) | |||
| 230 | inline void | 230 | inline void |
| 231 | smp_send_stop(void) { send_IPI_allbutself(IPI_CPU_STOP); } | 231 | smp_send_stop(void) { send_IPI_allbutself(IPI_CPU_STOP); } |
| 232 | 232 | ||
| 233 | static inline void | ||
| 234 | smp_send_start(void) { send_IPI_allbutself(IPI_CPU_START); } | ||
| 235 | |||
| 236 | void | 233 | void |
| 237 | smp_send_reschedule(int cpu) { send_IPI_single(cpu, IPI_RESCHEDULE); } | 234 | smp_send_reschedule(int cpu) { send_IPI_single(cpu, IPI_RESCHEDULE); } |
| 238 | 235 | ||
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S index fe4f0b89bf8f..5a8997d63899 100644 --- a/arch/parisc/kernel/syscall_table.S +++ b/arch/parisc/kernel/syscall_table.S | |||
| @@ -437,6 +437,7 @@ | |||
| 437 | ENTRY_SAME(getrandom) | 437 | ENTRY_SAME(getrandom) |
| 438 | ENTRY_SAME(memfd_create) /* 340 */ | 438 | ENTRY_SAME(memfd_create) /* 340 */ |
| 439 | ENTRY_SAME(bpf) | 439 | ENTRY_SAME(bpf) |
| 440 | ENTRY_COMP(execveat) | ||
| 440 | 441 | ||
| 441 | /* Nothing yet */ | 442 | /* Nothing yet */ |
| 442 | 443 | ||
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index 0bef864264c0..15dbe81cf5f3 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c | |||
| @@ -750,78 +750,6 @@ static void __init gateway_init(void) | |||
| 750 | PAGE_SIZE, PAGE_GATEWAY, 1); | 750 | PAGE_SIZE, PAGE_GATEWAY, 1); |
| 751 | } | 751 | } |
| 752 | 752 | ||
| 753 | #ifdef CONFIG_HPUX | ||
| 754 | void | ||
| 755 | map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm) | ||
| 756 | { | ||
| 757 | pgd_t *pg_dir; | ||
| 758 | pmd_t *pmd; | ||
| 759 | pte_t *pg_table; | ||
| 760 | unsigned long start_pmd; | ||
| 761 | unsigned long start_pte; | ||
| 762 | unsigned long address; | ||
| 763 | unsigned long hpux_gw_page_addr; | ||
| 764 | /* FIXME: This is 'const' in order to trick the compiler | ||
| 765 | into not treating it as DP-relative data. */ | ||
| 766 | extern void * const hpux_gateway_page; | ||
| 767 | |||
| 768 | hpux_gw_page_addr = HPUX_GATEWAY_ADDR & PAGE_MASK; | ||
| 769 | |||
| 770 | /* | ||
| 771 | * Setup HP-UX Gateway page. | ||
| 772 | * | ||
| 773 | * The HP-UX gateway page resides in the user address space, | ||
| 774 | * so it needs to be aliased into each process. | ||
| 775 | */ | ||
| 776 | |||
| 777 | pg_dir = pgd_offset(mm,hpux_gw_page_addr); | ||
| 778 | |||
| 779 | #if PTRS_PER_PMD == 1 | ||
| 780 | start_pmd = 0; | ||
| 781 | #else | ||
| 782 | start_pmd = ((hpux_gw_page_addr >> PMD_SHIFT) & (PTRS_PER_PMD - 1)); | ||
| 783 | #endif | ||
| 784 | start_pte = ((hpux_gw_page_addr >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)); | ||
| 785 | |||
| 786 | address = __pa(&hpux_gateway_page); | ||
| 787 | #if PTRS_PER_PMD == 1 | ||
| 788 | pmd = (pmd_t *)__pa(pg_dir); | ||
| 789 | #else | ||
| 790 | pmd = (pmd_t *) pgd_address(*pg_dir); | ||
| 791 | |||
| 792 | /* | ||
| 793 | * pmd is physical at this point | ||
| 794 | */ | ||
| 795 | |||
| 796 | if (!pmd) { | ||
| 797 | pmd = (pmd_t *) get_zeroed_page(GFP_KERNEL); | ||
| 798 | pmd = (pmd_t *) __pa(pmd); | ||
| 799 | } | ||
| 800 | |||
| 801 | __pgd_val_set(*pg_dir, PxD_FLAG_PRESENT | PxD_FLAG_VALID | (unsigned long) pmd); | ||
| 802 | #endif | ||
| 803 | /* now change pmd to kernel virtual addresses */ | ||
| 804 | |||
| 805 | pmd = (pmd_t *)__va(pmd) + start_pmd; | ||
| 806 | |||
| 807 | /* | ||
| 808 | * pg_table is physical at this point | ||
| 809 | */ | ||
| 810 | |||
| 811 | pg_table = (pte_t *) pmd_address(*pmd); | ||
| 812 | if (!pg_table) | ||
| 813 | pg_table = (pte_t *) __pa(get_zeroed_page(GFP_KERNEL)); | ||
| 814 | |||
| 815 | __pmd_val_set(*pmd, PxD_FLAG_PRESENT | PxD_FLAG_VALID | (unsigned long) pg_table); | ||
| 816 | |||
| 817 | /* now change pg_table to kernel virtual addresses */ | ||
| 818 | |||
| 819 | pg_table = (pte_t *) __va(pg_table) + start_pte; | ||
| 820 | set_pte(pg_table, __mk_pte(address, PAGE_GATEWAY)); | ||
| 821 | } | ||
| 822 | EXPORT_SYMBOL(map_hpux_gateway_page); | ||
| 823 | #endif | ||
| 824 | |||
| 825 | void __init paging_init(void) | 753 | void __init paging_init(void) |
| 826 | { | 754 | { |
| 827 | int i; | 755 | int i; |
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index f96d1ec24189..1a74446fd9e5 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c | |||
| @@ -96,8 +96,6 @@ int default_machine_kexec_prepare(struct kimage *image) | |||
| 96 | return 0; | 96 | return 0; |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | #define IND_FLAGS (IND_DESTINATION | IND_INDIRECTION | IND_DONE | IND_SOURCE) | ||
| 100 | |||
| 101 | static void copy_segments(unsigned long ind) | 99 | static void copy_segments(unsigned long ind) |
| 102 | { | 100 | { |
| 103 | unsigned long entry; | 101 | unsigned long entry; |
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 3be9fa69f875..3c036cb4a370 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c | |||
| @@ -152,14 +152,11 @@ static struct mce_log mcelog = { | |||
| 152 | void mce_log(struct mce *mce) | 152 | void mce_log(struct mce *mce) |
| 153 | { | 153 | { |
| 154 | unsigned next, entry; | 154 | unsigned next, entry; |
| 155 | int ret = 0; | ||
| 156 | 155 | ||
| 157 | /* Emit the trace record: */ | 156 | /* Emit the trace record: */ |
| 158 | trace_mce_record(mce); | 157 | trace_mce_record(mce); |
| 159 | 158 | ||
| 160 | ret = atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, mce); | 159 | atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, mce); |
| 161 | if (ret == NOTIFY_STOP) | ||
| 162 | return; | ||
| 163 | 160 | ||
| 164 | mce->finished = 0; | 161 | mce->finished = 0; |
| 165 | wmb(); | 162 | wmb(); |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index c256bd7fbd78..c6bb9f1257c9 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
| @@ -732,9 +732,8 @@ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index) | |||
| 732 | 732 | ||
| 733 | static bool acpi_idle_fallback_to_c1(struct acpi_processor *pr) | 733 | static bool acpi_idle_fallback_to_c1(struct acpi_processor *pr) |
| 734 | { | 734 | { |
| 735 | return IS_ENABLED(CONFIG_HOTPLUG_CPU) && num_online_cpus() > 1 && | 735 | return IS_ENABLED(CONFIG_HOTPLUG_CPU) && !pr->flags.has_cst && |
| 736 | !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED) && | 736 | !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED); |
| 737 | !pr->flags.has_cst; | ||
| 738 | } | 737 | } |
| 739 | 738 | ||
| 740 | static int c3_cpu_count; | 739 | static int c3_cpu_count; |
| @@ -744,9 +743,10 @@ static DEFINE_RAW_SPINLOCK(c3_lock); | |||
| 744 | * acpi_idle_enter_bm - enters C3 with proper BM handling | 743 | * acpi_idle_enter_bm - enters C3 with proper BM handling |
| 745 | * @pr: Target processor | 744 | * @pr: Target processor |
| 746 | * @cx: Target state context | 745 | * @cx: Target state context |
| 746 | * @timer_bc: Whether or not to change timer mode to broadcast | ||
| 747 | */ | 747 | */ |
| 748 | static void acpi_idle_enter_bm(struct acpi_processor *pr, | 748 | static void acpi_idle_enter_bm(struct acpi_processor *pr, |
| 749 | struct acpi_processor_cx *cx) | 749 | struct acpi_processor_cx *cx, bool timer_bc) |
| 750 | { | 750 | { |
| 751 | acpi_unlazy_tlb(smp_processor_id()); | 751 | acpi_unlazy_tlb(smp_processor_id()); |
| 752 | 752 | ||
| @@ -754,7 +754,8 @@ static void acpi_idle_enter_bm(struct acpi_processor *pr, | |||
| 754 | * Must be done before busmaster disable as we might need to | 754 | * Must be done before busmaster disable as we might need to |
| 755 | * access HPET ! | 755 | * access HPET ! |
| 756 | */ | 756 | */ |
| 757 | lapic_timer_state_broadcast(pr, cx, 1); | 757 | if (timer_bc) |
| 758 | lapic_timer_state_broadcast(pr, cx, 1); | ||
| 758 | 759 | ||
| 759 | /* | 760 | /* |
| 760 | * disable bus master | 761 | * disable bus master |
| @@ -784,7 +785,8 @@ static void acpi_idle_enter_bm(struct acpi_processor *pr, | |||
| 784 | raw_spin_unlock(&c3_lock); | 785 | raw_spin_unlock(&c3_lock); |
| 785 | } | 786 | } |
| 786 | 787 | ||
| 787 | lapic_timer_state_broadcast(pr, cx, 0); | 788 | if (timer_bc) |
| 789 | lapic_timer_state_broadcast(pr, cx, 0); | ||
| 788 | } | 790 | } |
| 789 | 791 | ||
| 790 | static int acpi_idle_enter(struct cpuidle_device *dev, | 792 | static int acpi_idle_enter(struct cpuidle_device *dev, |
| @@ -798,12 +800,12 @@ static int acpi_idle_enter(struct cpuidle_device *dev, | |||
| 798 | return -EINVAL; | 800 | return -EINVAL; |
| 799 | 801 | ||
| 800 | if (cx->type != ACPI_STATE_C1) { | 802 | if (cx->type != ACPI_STATE_C1) { |
| 801 | if (acpi_idle_fallback_to_c1(pr)) { | 803 | if (acpi_idle_fallback_to_c1(pr) && num_online_cpus() > 1) { |
| 802 | index = CPUIDLE_DRIVER_STATE_START; | 804 | index = CPUIDLE_DRIVER_STATE_START; |
| 803 | cx = per_cpu(acpi_cstate[index], dev->cpu); | 805 | cx = per_cpu(acpi_cstate[index], dev->cpu); |
| 804 | } else if (cx->type == ACPI_STATE_C3 && pr->flags.bm_check) { | 806 | } else if (cx->type == ACPI_STATE_C3 && pr->flags.bm_check) { |
| 805 | if (cx->bm_sts_skip || !acpi_idle_bm_check()) { | 807 | if (cx->bm_sts_skip || !acpi_idle_bm_check()) { |
| 806 | acpi_idle_enter_bm(pr, cx); | 808 | acpi_idle_enter_bm(pr, cx, true); |
| 807 | return index; | 809 | return index; |
| 808 | } else if (drv->safe_state_index >= 0) { | 810 | } else if (drv->safe_state_index >= 0) { |
| 809 | index = drv->safe_state_index; | 811 | index = drv->safe_state_index; |
| @@ -827,6 +829,27 @@ static int acpi_idle_enter(struct cpuidle_device *dev, | |||
| 827 | return index; | 829 | return index; |
| 828 | } | 830 | } |
| 829 | 831 | ||
| 832 | static void acpi_idle_enter_freeze(struct cpuidle_device *dev, | ||
| 833 | struct cpuidle_driver *drv, int index) | ||
| 834 | { | ||
| 835 | struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu); | ||
| 836 | |||
| 837 | if (cx->type == ACPI_STATE_C3) { | ||
| 838 | struct acpi_processor *pr = __this_cpu_read(processors); | ||
| 839 | |||
| 840 | if (unlikely(!pr)) | ||
| 841 | return; | ||
| 842 | |||
| 843 | if (pr->flags.bm_check) { | ||
| 844 | acpi_idle_enter_bm(pr, cx, false); | ||
| 845 | return; | ||
| 846 | } else { | ||
| 847 | ACPI_FLUSH_CPU_CACHE(); | ||
| 848 | } | ||
| 849 | } | ||
| 850 | acpi_idle_do_entry(cx); | ||
| 851 | } | ||
| 852 | |||
| 830 | struct cpuidle_driver acpi_idle_driver = { | 853 | struct cpuidle_driver acpi_idle_driver = { |
| 831 | .name = "acpi_idle", | 854 | .name = "acpi_idle", |
| 832 | .owner = THIS_MODULE, | 855 | .owner = THIS_MODULE, |
| @@ -925,6 +948,15 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr) | |||
| 925 | state->enter_dead = acpi_idle_play_dead; | 948 | state->enter_dead = acpi_idle_play_dead; |
| 926 | drv->safe_state_index = count; | 949 | drv->safe_state_index = count; |
| 927 | } | 950 | } |
| 951 | /* | ||
| 952 | * Halt-induced C1 is not good for ->enter_freeze, because it | ||
| 953 | * re-enables interrupts on exit. Moreover, C1 is generally not | ||
| 954 | * particularly interesting from the suspend-to-idle angle, so | ||
| 955 | * avoid C1 and the situations in which we may need to fall back | ||
| 956 | * to it altogether. | ||
| 957 | */ | ||
| 958 | if (cx->type != ACPI_STATE_C1 && !acpi_idle_fallback_to_c1(pr)) | ||
| 959 | state->enter_freeze = acpi_idle_enter_freeze; | ||
| 928 | 960 | ||
| 929 | count++; | 961 | count++; |
| 930 | if (count == CPUIDLE_STATE_MAX) | 962 | if (count == CPUIDLE_STATE_MAX) |
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index bf53a3771da5..e85d3416d899 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c | |||
| @@ -901,8 +901,10 @@ int tpm_pm_suspend(struct device *dev) | |||
| 901 | if (chip == NULL) | 901 | if (chip == NULL) |
| 902 | return -ENODEV; | 902 | return -ENODEV; |
| 903 | 903 | ||
| 904 | if (chip->flags & TPM_CHIP_FLAG_TPM2) | 904 | if (chip->flags & TPM_CHIP_FLAG_TPM2) { |
| 905 | return tpm2_shutdown(chip, TPM2_SU_CLEAR); | 905 | tpm2_shutdown(chip, TPM2_SU_STATE); |
| 906 | return 0; | ||
| 907 | } | ||
| 906 | 908 | ||
| 907 | /* for buggy tpm, flush pcrs with extend to selected dummy */ | 909 | /* for buggy tpm, flush pcrs with extend to selected dummy */ |
| 908 | if (tpm_suspend_pcr) { | 910 | if (tpm_suspend_pcr) { |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 7b0727c5e803..f8319a0860fd 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
| @@ -432,7 +432,8 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, | |||
| 432 | u32 *value, const char *desc); | 432 | u32 *value, const char *desc); |
| 433 | 433 | ||
| 434 | extern int tpm2_startup(struct tpm_chip *chip, u16 startup_type); | 434 | extern int tpm2_startup(struct tpm_chip *chip, u16 startup_type); |
| 435 | extern int tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type); | 435 | extern void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type); |
| 436 | extern unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *, u32); | 436 | extern unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *, u32); |
| 437 | extern int tpm2_do_selftest(struct tpm_chip *chip); | 437 | extern int tpm2_do_selftest(struct tpm_chip *chip); |
| 438 | extern int tpm2_gen_interrupt(struct tpm_chip *chip, bool quiet); | 438 | extern int tpm2_gen_interrupt(struct tpm_chip *chip); |
| 439 | extern int tpm2_probe(struct tpm_chip *chip); | ||
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 1abe6502219f..011909a9be96 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c | |||
| @@ -456,20 +456,23 @@ static const struct tpm_input_header tpm2_shutdown_header = { | |||
| 456 | * @chip: TPM chip to use. | 456 | * @chip: TPM chip to use. |
| 457 | * @shutdown_type shutdown type. The value is either | 457 | * @shutdown_type shutdown type. The value is either |
| 458 | * TPM_SU_CLEAR or TPM_SU_STATE. | 458 | * TPM_SU_CLEAR or TPM_SU_STATE. |
| 459 | * | ||
| 460 | * 0 is returned when the operation is successful. If a negative number is | ||
| 461 | * returned it remarks a POSIX error code. If a positive number is returned | ||
| 462 | * it remarks a TPM error. | ||
| 463 | */ | 459 | */ |
| 464 | int tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type) | 460 | void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type) |
| 465 | { | 461 | { |
| 466 | struct tpm2_cmd cmd; | 462 | struct tpm2_cmd cmd; |
| 463 | int rc; | ||
| 467 | 464 | ||
| 468 | cmd.header.in = tpm2_shutdown_header; | 465 | cmd.header.in = tpm2_shutdown_header; |
| 469 | |||
| 470 | cmd.params.startup_in.startup_type = cpu_to_be16(shutdown_type); | 466 | cmd.params.startup_in.startup_type = cpu_to_be16(shutdown_type); |
| 471 | return tpm_transmit_cmd(chip, &cmd, sizeof(cmd), | 467 | |
| 472 | "stopping the TPM"); | 468 | rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), "stopping the TPM"); |
| 469 | |||
| 470 | /* In places where shutdown command is sent there's no much we can do | ||
| 471 | * except print the error code on a system failure. | ||
| 472 | */ | ||
| 473 | if (rc < 0) | ||
| 474 | dev_warn(chip->pdev, "transmit returned %d while stopping the TPM", | ||
| 475 | rc); | ||
| 473 | } | 476 | } |
| 474 | EXPORT_SYMBOL_GPL(tpm2_shutdown); | 477 | EXPORT_SYMBOL_GPL(tpm2_shutdown); |
| 475 | 478 | ||
| @@ -598,20 +601,46 @@ EXPORT_SYMBOL_GPL(tpm2_do_selftest); | |||
| 598 | /** | 601 | /** |
| 599 | * tpm2_gen_interrupt() - generate an interrupt | 602 | * tpm2_gen_interrupt() - generate an interrupt |
| 600 | * @chip: TPM chip to use | 603 | * @chip: TPM chip to use |
| 601 | * @quiet: surpress the error message | ||
| 602 | * | 604 | * |
| 603 | * 0 is returned when the operation is successful. If a negative number is | 605 | * 0 is returned when the operation is successful. If a negative number is |
| 604 | * returned it remarks a POSIX error code. If a positive number is returned | 606 | * returned it remarks a POSIX error code. If a positive number is returned |
| 605 | * it remarks a TPM error. | 607 | * it remarks a TPM error. |
| 606 | */ | 608 | */ |
| 607 | int tpm2_gen_interrupt(struct tpm_chip *chip, bool quiet) | 609 | int tpm2_gen_interrupt(struct tpm_chip *chip) |
| 608 | { | 610 | { |
| 609 | const char *desc = NULL; | ||
| 610 | u32 dummy; | 611 | u32 dummy; |
| 611 | 612 | ||
| 612 | if (!quiet) | 613 | return tpm2_get_tpm_pt(chip, 0x100, &dummy, |
| 613 | desc = "attempting to generate an interrupt"; | 614 | "attempting to generate an interrupt"); |
| 614 | |||
| 615 | return tpm2_get_tpm_pt(chip, TPM2_CAP_TPM_PROPERTIES, &dummy, desc); | ||
| 616 | } | 615 | } |
| 617 | EXPORT_SYMBOL_GPL(tpm2_gen_interrupt); | 616 | EXPORT_SYMBOL_GPL(tpm2_gen_interrupt); |
| 617 | |||
| 618 | /** | ||
| 619 | * tpm2_probe() - probe TPM 2.0 | ||
| 620 | * @chip: TPM chip to use | ||
| 621 | * | ||
| 622 | * Send idempotent TPM 2.0 command and see whether TPM 2.0 chip replied based on | ||
| 623 | * the reply tag. | ||
| 624 | */ | ||
| 625 | int tpm2_probe(struct tpm_chip *chip) | ||
| 626 | { | ||
| 627 | struct tpm2_cmd cmd; | ||
| 628 | int rc; | ||
| 629 | |||
| 630 | cmd.header.in = tpm2_get_tpm_pt_header; | ||
| 631 | cmd.params.get_tpm_pt_in.cap_id = cpu_to_be32(TPM2_CAP_TPM_PROPERTIES); | ||
| 632 | cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(0x100); | ||
| 633 | cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1); | ||
| 634 | |||
| 635 | rc = tpm_transmit(chip, (const char *) &cmd, sizeof(cmd)); | ||
| 636 | if (rc < 0) | ||
| 637 | return rc; | ||
| 638 | else if (rc < TPM_HEADER_SIZE) | ||
| 639 | return -EFAULT; | ||
| 640 | |||
| 641 | if (be16_to_cpu(cmd.header.out.tag) == TPM2_ST_NO_SESSIONS) | ||
| 642 | chip->flags |= TPM_CHIP_FLAG_TPM2; | ||
| 643 | |||
| 644 | return 0; | ||
| 645 | } | ||
| 646 | EXPORT_SYMBOL_GPL(tpm2_probe); | ||
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c index 3dd23cfae4fe..b26ceee3585e 100644 --- a/drivers/char/tpm/tpm_crb.c +++ b/drivers/char/tpm/tpm_crb.c | |||
| @@ -95,21 +95,7 @@ struct crb_priv { | |||
| 95 | u8 __iomem *rsp; | 95 | u8 __iomem *rsp; |
| 96 | }; | 96 | }; |
| 97 | 97 | ||
| 98 | #ifdef CONFIG_PM_SLEEP | 98 | static SIMPLE_DEV_PM_OPS(crb_pm, tpm_pm_suspend, tpm_pm_resume); |
| 99 | static int crb_resume(struct device *dev) | ||
| 100 | { | ||
| 101 | int rc; | ||
| 102 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
| 103 | |||
| 104 | rc = tpm2_shutdown(chip, TPM2_SU_STATE); | ||
| 105 | if (!rc) | ||
| 106 | rc = tpm2_do_selftest(chip); | ||
| 107 | |||
| 108 | return rc; | ||
| 109 | } | ||
| 110 | #endif | ||
| 111 | |||
| 112 | static SIMPLE_DEV_PM_OPS(crb_pm, tpm_pm_suspend, crb_resume); | ||
| 113 | 99 | ||
| 114 | static u8 crb_status(struct tpm_chip *chip) | 100 | static u8 crb_status(struct tpm_chip *chip) |
| 115 | { | 101 | { |
| @@ -326,6 +312,10 @@ static int crb_acpi_remove(struct acpi_device *device) | |||
| 326 | struct tpm_chip *chip = dev_get_drvdata(dev); | 312 | struct tpm_chip *chip = dev_get_drvdata(dev); |
| 327 | 313 | ||
| 328 | tpm_chip_unregister(chip); | 314 | tpm_chip_unregister(chip); |
| 315 | |||
| 316 | if (chip->flags & TPM_CHIP_FLAG_TPM2) | ||
| 317 | tpm2_shutdown(chip, TPM2_SU_CLEAR); | ||
| 318 | |||
| 329 | return 0; | 319 | return 0; |
| 330 | } | 320 | } |
| 331 | 321 | ||
diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c index 0840347e251c..b1e53e3aece5 100644 --- a/drivers/char/tpm/tpm_ibmvtpm.c +++ b/drivers/char/tpm/tpm_ibmvtpm.c | |||
| @@ -148,7 +148,8 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count) | |||
| 148 | crq.len = (u16)count; | 148 | crq.len = (u16)count; |
| 149 | crq.data = ibmvtpm->rtce_dma_handle; | 149 | crq.data = ibmvtpm->rtce_dma_handle; |
| 150 | 150 | ||
| 151 | rc = ibmvtpm_send_crq(ibmvtpm->vdev, word[0], word[1]); | 151 | rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(word[0]), |
| 152 | cpu_to_be64(word[1])); | ||
| 152 | if (rc != H_SUCCESS) { | 153 | if (rc != H_SUCCESS) { |
| 153 | dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc); | 154 | dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc); |
| 154 | rc = 0; | 155 | rc = 0; |
| @@ -186,7 +187,8 @@ static int ibmvtpm_crq_get_rtce_size(struct ibmvtpm_dev *ibmvtpm) | |||
| 186 | crq.valid = (u8)IBMVTPM_VALID_CMD; | 187 | crq.valid = (u8)IBMVTPM_VALID_CMD; |
| 187 | crq.msg = (u8)VTPM_GET_RTCE_BUFFER_SIZE; | 188 | crq.msg = (u8)VTPM_GET_RTCE_BUFFER_SIZE; |
| 188 | 189 | ||
| 189 | rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]); | 190 | rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]), |
| 191 | cpu_to_be64(buf[1])); | ||
| 190 | if (rc != H_SUCCESS) | 192 | if (rc != H_SUCCESS) |
| 191 | dev_err(ibmvtpm->dev, | 193 | dev_err(ibmvtpm->dev, |
| 192 | "ibmvtpm_crq_get_rtce_size failed rc=%d\n", rc); | 194 | "ibmvtpm_crq_get_rtce_size failed rc=%d\n", rc); |
| @@ -212,7 +214,8 @@ static int ibmvtpm_crq_get_version(struct ibmvtpm_dev *ibmvtpm) | |||
| 212 | crq.valid = (u8)IBMVTPM_VALID_CMD; | 214 | crq.valid = (u8)IBMVTPM_VALID_CMD; |
| 213 | crq.msg = (u8)VTPM_GET_VERSION; | 215 | crq.msg = (u8)VTPM_GET_VERSION; |
| 214 | 216 | ||
| 215 | rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]); | 217 | rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]), |
| 218 | cpu_to_be64(buf[1])); | ||
| 216 | if (rc != H_SUCCESS) | 219 | if (rc != H_SUCCESS) |
| 217 | dev_err(ibmvtpm->dev, | 220 | dev_err(ibmvtpm->dev, |
| 218 | "ibmvtpm_crq_get_version failed rc=%d\n", rc); | 221 | "ibmvtpm_crq_get_version failed rc=%d\n", rc); |
| @@ -336,7 +339,8 @@ static int tpm_ibmvtpm_suspend(struct device *dev) | |||
| 336 | crq.valid = (u8)IBMVTPM_VALID_CMD; | 339 | crq.valid = (u8)IBMVTPM_VALID_CMD; |
| 337 | crq.msg = (u8)VTPM_PREPARE_TO_SUSPEND; | 340 | crq.msg = (u8)VTPM_PREPARE_TO_SUSPEND; |
| 338 | 341 | ||
| 339 | rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]); | 342 | rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]), |
| 343 | cpu_to_be64(buf[1])); | ||
| 340 | if (rc != H_SUCCESS) | 344 | if (rc != H_SUCCESS) |
| 341 | dev_err(ibmvtpm->dev, | 345 | dev_err(ibmvtpm->dev, |
| 342 | "tpm_ibmvtpm_suspend failed rc=%d\n", rc); | 346 | "tpm_ibmvtpm_suspend failed rc=%d\n", rc); |
| @@ -481,11 +485,11 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq, | |||
| 481 | case IBMVTPM_VALID_CMD: | 485 | case IBMVTPM_VALID_CMD: |
| 482 | switch (crq->msg) { | 486 | switch (crq->msg) { |
| 483 | case VTPM_GET_RTCE_BUFFER_SIZE_RES: | 487 | case VTPM_GET_RTCE_BUFFER_SIZE_RES: |
| 484 | if (crq->len <= 0) { | 488 | if (be16_to_cpu(crq->len) <= 0) { |
| 485 | dev_err(ibmvtpm->dev, "Invalid rtce size\n"); | 489 | dev_err(ibmvtpm->dev, "Invalid rtce size\n"); |
| 486 | return; | 490 | return; |
| 487 | } | 491 | } |
| 488 | ibmvtpm->rtce_size = crq->len; | 492 | ibmvtpm->rtce_size = be16_to_cpu(crq->len); |
| 489 | ibmvtpm->rtce_buf = kmalloc(ibmvtpm->rtce_size, | 493 | ibmvtpm->rtce_buf = kmalloc(ibmvtpm->rtce_size, |
| 490 | GFP_KERNEL); | 494 | GFP_KERNEL); |
| 491 | if (!ibmvtpm->rtce_buf) { | 495 | if (!ibmvtpm->rtce_buf) { |
| @@ -506,11 +510,11 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq, | |||
| 506 | 510 | ||
| 507 | return; | 511 | return; |
| 508 | case VTPM_GET_VERSION_RES: | 512 | case VTPM_GET_VERSION_RES: |
| 509 | ibmvtpm->vtpm_version = crq->data; | 513 | ibmvtpm->vtpm_version = be32_to_cpu(crq->data); |
| 510 | return; | 514 | return; |
| 511 | case VTPM_TPM_COMMAND_RES: | 515 | case VTPM_TPM_COMMAND_RES: |
| 512 | /* len of the data in rtce buffer */ | 516 | /* len of the data in rtce buffer */ |
| 513 | ibmvtpm->res_len = crq->len; | 517 | ibmvtpm->res_len = be16_to_cpu(crq->len); |
| 514 | wake_up_interruptible(&ibmvtpm->wq); | 518 | wake_up_interruptible(&ibmvtpm->wq); |
| 515 | return; | 519 | return; |
| 516 | default: | 520 | default: |
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 6725bef7cb96..f2dffa770b8e 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c | |||
| @@ -588,6 +588,9 @@ MODULE_PARM_DESC(interrupts, "Enable interrupts"); | |||
| 588 | 588 | ||
| 589 | static void tpm_tis_remove(struct tpm_chip *chip) | 589 | static void tpm_tis_remove(struct tpm_chip *chip) |
| 590 | { | 590 | { |
| 591 | if (chip->flags & TPM_CHIP_FLAG_TPM2) | ||
| 592 | tpm2_shutdown(chip, TPM2_SU_CLEAR); | ||
| 593 | |||
| 591 | iowrite32(~TPM_GLOBAL_INT_ENABLE & | 594 | iowrite32(~TPM_GLOBAL_INT_ENABLE & |
| 592 | ioread32(chip->vendor.iobase + | 595 | ioread32(chip->vendor.iobase + |
| 593 | TPM_INT_ENABLE(chip->vendor. | 596 | TPM_INT_ENABLE(chip->vendor. |
| @@ -639,12 +642,9 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, | |||
| 639 | goto out_err; | 642 | goto out_err; |
| 640 | } | 643 | } |
| 641 | 644 | ||
| 642 | /* Every TPM 2.x command has a higher ordinal than TPM 1.x commands. | 645 | rc = tpm2_probe(chip); |
| 643 | * Therefore, we can use an idempotent TPM 2.x command to probe TPM 2.x. | 646 | if (rc) |
| 644 | */ | 647 | goto out_err; |
| 645 | rc = tpm2_gen_interrupt(chip, true); | ||
| 646 | if (rc == 0 || rc == TPM2_RC_INITIALIZE) | ||
| 647 | chip->flags |= TPM_CHIP_FLAG_TPM2; | ||
| 648 | 648 | ||
| 649 | vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); | 649 | vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); |
| 650 | chip->vendor.manufacturer_id = vendor; | 650 | chip->vendor.manufacturer_id = vendor; |
| @@ -747,7 +747,7 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, | |||
| 747 | 747 | ||
| 748 | /* Generate Interrupts */ | 748 | /* Generate Interrupts */ |
| 749 | if (chip->flags & TPM_CHIP_FLAG_TPM2) | 749 | if (chip->flags & TPM_CHIP_FLAG_TPM2) |
| 750 | tpm2_gen_interrupt(chip, false); | 750 | tpm2_gen_interrupt(chip); |
| 751 | else | 751 | else |
| 752 | tpm_gen_interrupt(chip); | 752 | tpm_gen_interrupt(chip); |
| 753 | 753 | ||
| @@ -865,25 +865,22 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip) | |||
| 865 | static int tpm_tis_resume(struct device *dev) | 865 | static int tpm_tis_resume(struct device *dev) |
| 866 | { | 866 | { |
| 867 | struct tpm_chip *chip = dev_get_drvdata(dev); | 867 | struct tpm_chip *chip = dev_get_drvdata(dev); |
| 868 | int ret = 0; | 868 | int ret; |
| 869 | 869 | ||
| 870 | if (chip->vendor.irq) | 870 | if (chip->vendor.irq) |
| 871 | tpm_tis_reenable_interrupts(chip); | 871 | tpm_tis_reenable_interrupts(chip); |
| 872 | 872 | ||
| 873 | if (chip->flags & TPM_CHIP_FLAG_TPM2) { | 873 | ret = tpm_pm_resume(dev); |
| 874 | /* NOP if firmware properly does this. */ | 874 | if (ret) |
| 875 | tpm2_startup(chip, TPM2_SU_STATE); | 875 | return ret; |
| 876 | 876 | ||
| 877 | ret = tpm2_shutdown(chip, TPM2_SU_STATE); | 877 | /* TPM 1.2 requires self-test on resume. This function actually returns |
| 878 | if (!ret) | 878 | * an error code but for unknown reason it isn't handled. |
| 879 | ret = tpm2_do_selftest(chip); | 879 | */ |
| 880 | } else { | 880 | if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) |
| 881 | ret = tpm_pm_resume(dev); | 881 | tpm_do_selftest(chip); |
| 882 | if (!ret) | ||
| 883 | tpm_do_selftest(chip); | ||
| 884 | } | ||
| 885 | 882 | ||
| 886 | return ret; | 883 | return 0; |
| 887 | } | 884 | } |
| 888 | #endif | 885 | #endif |
| 889 | 886 | ||
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 125150dc6e81..4d534582514e 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c | |||
| @@ -19,6 +19,8 @@ | |||
| 19 | #include <linux/ktime.h> | 19 | #include <linux/ktime.h> |
| 20 | #include <linux/hrtimer.h> | 20 | #include <linux/hrtimer.h> |
| 21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
| 22 | #include <linux/suspend.h> | ||
| 23 | #include <linux/tick.h> | ||
| 22 | #include <trace/events/power.h> | 24 | #include <trace/events/power.h> |
| 23 | 25 | ||
| 24 | #include "cpuidle.h" | 26 | #include "cpuidle.h" |
| @@ -32,7 +34,6 @@ LIST_HEAD(cpuidle_detected_devices); | |||
| 32 | static int enabled_devices; | 34 | static int enabled_devices; |
| 33 | static int off __read_mostly; | 35 | static int off __read_mostly; |
| 34 | static int initialized __read_mostly; | 36 | static int initialized __read_mostly; |
| 35 | static bool use_deepest_state __read_mostly; | ||
| 36 | 37 | ||
| 37 | int cpuidle_disabled(void) | 38 | int cpuidle_disabled(void) |
| 38 | { | 39 | { |
| @@ -66,36 +67,23 @@ int cpuidle_play_dead(void) | |||
| 66 | } | 67 | } |
| 67 | 68 | ||
| 68 | /** | 69 | /** |
| 69 | * cpuidle_use_deepest_state - Enable/disable the "deepest idle" mode. | 70 | * cpuidle_find_deepest_state - Find deepest state meeting specific conditions. |
| 70 | * @enable: Whether enable or disable the feature. | 71 | * @drv: cpuidle driver for the given CPU. |
| 71 | * | 72 | * @dev: cpuidle device for the given CPU. |
| 72 | * If the "deepest idle" mode is enabled, cpuidle will ignore the governor and | 73 | * @freeze: Whether or not the state should be suitable for suspend-to-idle. |
| 73 | * always use the state with the greatest exit latency (out of the states that | ||
| 74 | * are not disabled). | ||
| 75 | * | ||
| 76 | * This function can only be called after cpuidle_pause() to avoid races. | ||
| 77 | */ | ||
| 78 | void cpuidle_use_deepest_state(bool enable) | ||
| 79 | { | ||
| 80 | use_deepest_state = enable; | ||
| 81 | } | ||
| 82 | |||
| 83 | /** | ||
| 84 | * cpuidle_find_deepest_state - Find the state of the greatest exit latency. | ||
| 85 | * @drv: cpuidle driver for a given CPU. | ||
| 86 | * @dev: cpuidle device for a given CPU. | ||
| 87 | */ | 74 | */ |
| 88 | static int cpuidle_find_deepest_state(struct cpuidle_driver *drv, | 75 | static int cpuidle_find_deepest_state(struct cpuidle_driver *drv, |
| 89 | struct cpuidle_device *dev) | 76 | struct cpuidle_device *dev, bool freeze) |
| 90 | { | 77 | { |
| 91 | unsigned int latency_req = 0; | 78 | unsigned int latency_req = 0; |
| 92 | int i, ret = CPUIDLE_DRIVER_STATE_START - 1; | 79 | int i, ret = freeze ? -1 : CPUIDLE_DRIVER_STATE_START - 1; |
| 93 | 80 | ||
| 94 | for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { | 81 | for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { |
| 95 | struct cpuidle_state *s = &drv->states[i]; | 82 | struct cpuidle_state *s = &drv->states[i]; |
| 96 | struct cpuidle_state_usage *su = &dev->states_usage[i]; | 83 | struct cpuidle_state_usage *su = &dev->states_usage[i]; |
| 97 | 84 | ||
| 98 | if (s->disabled || su->disable || s->exit_latency <= latency_req) | 85 | if (s->disabled || su->disable || s->exit_latency <= latency_req |
| 86 | || (freeze && !s->enter_freeze)) | ||
| 99 | continue; | 87 | continue; |
| 100 | 88 | ||
| 101 | latency_req = s->exit_latency; | 89 | latency_req = s->exit_latency; |
| @@ -104,6 +92,63 @@ static int cpuidle_find_deepest_state(struct cpuidle_driver *drv, | |||
| 104 | return ret; | 92 | return ret; |
| 105 | } | 93 | } |
| 106 | 94 | ||
| 95 | static void enter_freeze_proper(struct cpuidle_driver *drv, | ||
| 96 | struct cpuidle_device *dev, int index) | ||
| 97 | { | ||
| 98 | tick_freeze(); | ||
| 99 | /* | ||
| 100 | * The state used here cannot be a "coupled" one, because the "coupled" | ||
| 101 | * cpuidle mechanism enables interrupts and doing that with timekeeping | ||
| 102 | * suspended is generally unsafe. | ||
| 103 | */ | ||
| 104 | drv->states[index].enter_freeze(dev, drv, index); | ||
| 105 | WARN_ON(!irqs_disabled()); | ||
| 106 | /* | ||
| 107 | * timekeeping_resume() that will be called by tick_unfreeze() for the | ||
| 108 | * last CPU executing it calls functions containing RCU read-side | ||
| 109 | * critical sections, so tell RCU about that. | ||
| 110 | */ | ||
| 111 | RCU_NONIDLE(tick_unfreeze()); | ||
| 112 | } | ||
| 113 | |||
| 114 | /** | ||
| 115 | * cpuidle_enter_freeze - Enter an idle state suitable for suspend-to-idle. | ||
| 116 | * | ||
| 117 | * If there are states with the ->enter_freeze callback, find the deepest of | ||
| 118 | * them and enter it with frozen tick. Otherwise, find the deepest state | ||
| 119 | * available and enter it normally. | ||
| 120 | */ | ||
| 121 | void cpuidle_enter_freeze(void) | ||
| 122 | { | ||
| 123 | struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices); | ||
| 124 | struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); | ||
| 125 | int index; | ||
| 126 | |||
| 127 | /* | ||
| 128 | * Find the deepest state with ->enter_freeze present, which guarantees | ||
| 129 | * that interrupts won't be enabled when it exits and allows the tick to | ||
| 130 | * be frozen safely. | ||
| 131 | */ | ||
| 132 | index = cpuidle_find_deepest_state(drv, dev, true); | ||
| 133 | if (index >= 0) { | ||
| 134 | enter_freeze_proper(drv, dev, index); | ||
| 135 | return; | ||
| 136 | } | ||
| 137 | |||
| 138 | /* | ||
| 139 | * It is not safe to freeze the tick, find the deepest state available | ||
| 140 | * at all and try to enter it normally. | ||
| 141 | */ | ||
| 142 | index = cpuidle_find_deepest_state(drv, dev, false); | ||
| 143 | if (index >= 0) | ||
| 144 | cpuidle_enter(drv, dev, index); | ||
| 145 | else | ||
| 146 | arch_cpu_idle(); | ||
| 147 | |||
| 148 | /* Interrupts are enabled again here. */ | ||
| 149 | local_irq_disable(); | ||
| 150 | } | ||
| 151 | |||
| 107 | /** | 152 | /** |
| 108 | * cpuidle_enter_state - enter the state and update stats | 153 | * cpuidle_enter_state - enter the state and update stats |
| 109 | * @dev: cpuidle device for this cpu | 154 | * @dev: cpuidle device for this cpu |
| @@ -166,9 +211,6 @@ int cpuidle_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
| 166 | if (!drv || !dev || !dev->enabled) | 211 | if (!drv || !dev || !dev->enabled) |
| 167 | return -EBUSY; | 212 | return -EBUSY; |
| 168 | 213 | ||
| 169 | if (unlikely(use_deepest_state)) | ||
| 170 | return cpuidle_find_deepest_state(drv, dev); | ||
| 171 | |||
| 172 | return cpuidle_curr_governor->select(drv, dev); | 214 | return cpuidle_curr_governor->select(drv, dev); |
| 173 | } | 215 | } |
| 174 | 216 | ||
| @@ -200,7 +242,7 @@ int cpuidle_enter(struct cpuidle_driver *drv, struct cpuidle_device *dev, | |||
| 200 | */ | 242 | */ |
| 201 | void cpuidle_reflect(struct cpuidle_device *dev, int index) | 243 | void cpuidle_reflect(struct cpuidle_device *dev, int index) |
| 202 | { | 244 | { |
| 203 | if (cpuidle_curr_governor->reflect && !unlikely(use_deepest_state)) | 245 | if (cpuidle_curr_governor->reflect) |
| 204 | cpuidle_curr_governor->reflect(dev, index); | 246 | cpuidle_curr_governor->reflect(dev, index); |
| 205 | } | 247 | } |
| 206 | 248 | ||
diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index eb6935c8ad94..d6a09b9cd8cc 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c | |||
| @@ -1246,14 +1246,14 @@ static const u32 model_textual_descriptor[] = { | |||
| 1246 | 1246 | ||
| 1247 | static struct fw_descriptor vendor_id_descriptor = { | 1247 | static struct fw_descriptor vendor_id_descriptor = { |
| 1248 | .length = ARRAY_SIZE(vendor_textual_descriptor), | 1248 | .length = ARRAY_SIZE(vendor_textual_descriptor), |
| 1249 | .immediate = 0x03d00d1e, | 1249 | .immediate = 0x03001f11, |
| 1250 | .key = 0x81000000, | 1250 | .key = 0x81000000, |
| 1251 | .data = vendor_textual_descriptor, | 1251 | .data = vendor_textual_descriptor, |
| 1252 | }; | 1252 | }; |
| 1253 | 1253 | ||
| 1254 | static struct fw_descriptor model_id_descriptor = { | 1254 | static struct fw_descriptor model_id_descriptor = { |
| 1255 | .length = ARRAY_SIZE(model_textual_descriptor), | 1255 | .length = ARRAY_SIZE(model_textual_descriptor), |
| 1256 | .immediate = 0x17000001, | 1256 | .immediate = 0x17023901, |
| 1257 | .key = 0x81000000, | 1257 | .key = 0x81000000, |
| 1258 | .data = model_textual_descriptor, | 1258 | .data = model_textual_descriptor, |
| 1259 | }; | 1259 | }; |
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index aff9018d0658..f51d376d10ba 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c | |||
| @@ -718,11 +718,6 @@ static inline unsigned int ar_next_buffer_index(unsigned int index) | |||
| 718 | return (index + 1) % AR_BUFFERS; | 718 | return (index + 1) % AR_BUFFERS; |
| 719 | } | 719 | } |
| 720 | 720 | ||
| 721 | static inline unsigned int ar_prev_buffer_index(unsigned int index) | ||
| 722 | { | ||
| 723 | return (index - 1 + AR_BUFFERS) % AR_BUFFERS; | ||
| 724 | } | ||
| 725 | |||
| 726 | static inline unsigned int ar_first_buffer_index(struct ar_context *ctx) | 721 | static inline unsigned int ar_first_buffer_index(struct ar_context *ctx) |
| 727 | { | 722 | { |
| 728 | return ar_next_buffer_index(ctx->last_buffer_index); | 723 | return ar_next_buffer_index(ctx->last_buffer_index); |
diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index 64ac8f8f5098..c22606fe3d44 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c | |||
| @@ -1463,17 +1463,6 @@ static int sbp2_scsi_queuecommand(struct Scsi_Host *shost, | |||
| 1463 | struct sbp2_command_orb *orb; | 1463 | struct sbp2_command_orb *orb; |
| 1464 | int generation, retval = SCSI_MLQUEUE_HOST_BUSY; | 1464 | int generation, retval = SCSI_MLQUEUE_HOST_BUSY; |
| 1465 | 1465 | ||
| 1466 | /* | ||
| 1467 | * Bidirectional commands are not yet implemented, and unknown | ||
| 1468 | * transfer direction not handled. | ||
| 1469 | */ | ||
| 1470 | if (cmd->sc_data_direction == DMA_BIDIRECTIONAL) { | ||
| 1471 | dev_err(lu_dev(lu), "cannot handle bidirectional command\n"); | ||
| 1472 | cmd->result = DID_ERROR << 16; | ||
| 1473 | cmd->scsi_done(cmd); | ||
| 1474 | return 0; | ||
| 1475 | } | ||
| 1476 | |||
| 1477 | orb = kzalloc(sizeof(*orb), GFP_ATOMIC); | 1466 | orb = kzalloc(sizeof(*orb), GFP_ATOMIC); |
| 1478 | if (orb == NULL) | 1467 | if (orb == NULL) |
| 1479 | return SCSI_MLQUEUE_HOST_BUSY; | 1468 | return SCSI_MLQUEUE_HOST_BUSY; |
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 1bc0c170f12a..b0e58522780d 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c | |||
| @@ -97,6 +97,8 @@ static const struct idle_cpu *icpu; | |||
| 97 | static struct cpuidle_device __percpu *intel_idle_cpuidle_devices; | 97 | static struct cpuidle_device __percpu *intel_idle_cpuidle_devices; |
| 98 | static int intel_idle(struct cpuidle_device *dev, | 98 | static int intel_idle(struct cpuidle_device *dev, |
| 99 | struct cpuidle_driver *drv, int index); | 99 | struct cpuidle_driver *drv, int index); |
| 100 | static void intel_idle_freeze(struct cpuidle_device *dev, | ||
| 101 | struct cpuidle_driver *drv, int index); | ||
| 100 | static int intel_idle_cpu_init(int cpu); | 102 | static int intel_idle_cpu_init(int cpu); |
| 101 | 103 | ||
| 102 | static struct cpuidle_state *cpuidle_state_table; | 104 | static struct cpuidle_state *cpuidle_state_table; |
| @@ -131,28 +133,32 @@ static struct cpuidle_state nehalem_cstates[] = { | |||
| 131 | .flags = MWAIT2flg(0x00), | 133 | .flags = MWAIT2flg(0x00), |
| 132 | .exit_latency = 3, | 134 | .exit_latency = 3, |
| 133 | .target_residency = 6, | 135 | .target_residency = 6, |
| 134 | .enter = &intel_idle }, | 136 | .enter = &intel_idle, |
| 137 | .enter_freeze = intel_idle_freeze, }, | ||
| 135 | { | 138 | { |
| 136 | .name = "C1E-NHM", | 139 | .name = "C1E-NHM", |
| 137 | .desc = "MWAIT 0x01", | 140 | .desc = "MWAIT 0x01", |
| 138 | .flags = MWAIT2flg(0x01), | 141 | .flags = MWAIT2flg(0x01), |
| 139 | .exit_latency = 10, | 142 | .exit_latency = 10, |
| 140 | .target_residency = 20, | 143 | .target_residency = 20, |
| 141 | .enter = &intel_idle }, | 144 | .enter = &intel_idle, |
| 145 | .enter_freeze = intel_idle_freeze, }, | ||
| 142 | { | 146 | { |
| 143 | .name = "C3-NHM", | 147 | .name = "C3-NHM", |
| 144 | .desc = "MWAIT 0x10", | 148 | .desc = "MWAIT 0x10", |
| 145 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, | 149 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 146 | .exit_latency = 20, | 150 | .exit_latency = 20, |
| 147 | .target_residency = 80, | 151 | .target_residency = 80, |
| 148 | .enter = &intel_idle }, | 152 | .enter = &intel_idle, |
| 153 | .enter_freeze = intel_idle_freeze, }, | ||
| 149 | { | 154 | { |
| 150 | .name = "C6-NHM", | 155 | .name = "C6-NHM", |
| 151 | .desc = "MWAIT 0x20", | 156 | .desc = "MWAIT 0x20", |
| 152 | .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, | 157 | .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 153 | .exit_latency = 200, | 158 | .exit_latency = 200, |
| 154 | .target_residency = 800, | 159 | .target_residency = 800, |
| 155 | .enter = &intel_idle }, | 160 | .enter = &intel_idle, |
| 161 | .enter_freeze = intel_idle_freeze, }, | ||
| 156 | { | 162 | { |
| 157 | .enter = NULL } | 163 | .enter = NULL } |
| 158 | }; | 164 | }; |
| @@ -164,35 +170,40 @@ static struct cpuidle_state snb_cstates[] = { | |||
| 164 | .flags = MWAIT2flg(0x00), | 170 | .flags = MWAIT2flg(0x00), |
| 165 | .exit_latency = 2, | 171 | .exit_latency = 2, |
| 166 | .target_residency = 2, | 172 | .target_residency = 2, |
| 167 | .enter = &intel_idle }, | 173 | .enter = &intel_idle, |
| 174 | .enter_freeze = intel_idle_freeze, }, | ||
| 168 | { | 175 | { |
| 169 | .name = "C1E-SNB", | 176 | .name = "C1E-SNB", |
| 170 | .desc = "MWAIT 0x01", | 177 | .desc = "MWAIT 0x01", |
| 171 | .flags = MWAIT2flg(0x01), | 178 | .flags = MWAIT2flg(0x01), |
| 172 | .exit_latency = 10, | 179 | .exit_latency = 10, |
| 173 | .target_residency = 20, | 180 | .target_residency = 20, |
| 174 | .enter = &intel_idle }, | 181 | .enter = &intel_idle, |
| 182 | .enter_freeze = intel_idle_freeze, }, | ||
| 175 | { | 183 | { |
| 176 | .name = "C3-SNB", | 184 | .name = "C3-SNB", |
| 177 | .desc = "MWAIT 0x10", | 185 | .desc = "MWAIT 0x10", |
| 178 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, | 186 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 179 | .exit_latency = 80, | 187 | .exit_latency = 80, |
| 180 | .target_residency = 211, | 188 | .target_residency = 211, |
| 181 | .enter = &intel_idle }, | 189 | .enter = &intel_idle, |
| 190 | .enter_freeze = intel_idle_freeze, }, | ||
| 182 | { | 191 | { |
| 183 | .name = "C6-SNB", | 192 | .name = "C6-SNB", |
| 184 | .desc = "MWAIT 0x20", | 193 | .desc = "MWAIT 0x20", |
| 185 | .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, | 194 | .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 186 | .exit_latency = 104, | 195 | .exit_latency = 104, |
| 187 | .target_residency = 345, | 196 | .target_residency = 345, |
| 188 | .enter = &intel_idle }, | 197 | .enter = &intel_idle, |
| 198 | .enter_freeze = intel_idle_freeze, }, | ||
| 189 | { | 199 | { |
| 190 | .name = "C7-SNB", | 200 | .name = "C7-SNB", |
| 191 | .desc = "MWAIT 0x30", | 201 | .desc = "MWAIT 0x30", |
| 192 | .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED, | 202 | .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 193 | .exit_latency = 109, | 203 | .exit_latency = 109, |
| 194 | .target_residency = 345, | 204 | .target_residency = 345, |
| 195 | .enter = &intel_idle }, | 205 | .enter = &intel_idle, |
| 206 | .enter_freeze = intel_idle_freeze, }, | ||
| 196 | { | 207 | { |
| 197 | .enter = NULL } | 208 | .enter = NULL } |
| 198 | }; | 209 | }; |
| @@ -204,42 +215,48 @@ static struct cpuidle_state byt_cstates[] = { | |||
| 204 | .flags = MWAIT2flg(0x00), | 215 | .flags = MWAIT2flg(0x00), |
| 205 | .exit_latency = 1, | 216 | .exit_latency = 1, |
| 206 | .target_residency = 1, | 217 | .target_residency = 1, |
| 207 | .enter = &intel_idle }, | 218 | .enter = &intel_idle, |
| 219 | .enter_freeze = intel_idle_freeze, }, | ||
| 208 | { | 220 | { |
| 209 | .name = "C1E-BYT", | 221 | .name = "C1E-BYT", |
| 210 | .desc = "MWAIT 0x01", | 222 | .desc = "MWAIT 0x01", |
| 211 | .flags = MWAIT2flg(0x01), | 223 | .flags = MWAIT2flg(0x01), |
| 212 | .exit_latency = 15, | 224 | .exit_latency = 15, |
| 213 | .target_residency = 30, | 225 | .target_residency = 30, |
| 214 | .enter = &intel_idle }, | 226 | .enter = &intel_idle, |
| 227 | .enter_freeze = intel_idle_freeze, }, | ||
| 215 | { | 228 | { |
| 216 | .name = "C6N-BYT", | 229 | .name = "C6N-BYT", |
| 217 | .desc = "MWAIT 0x58", | 230 | .desc = "MWAIT 0x58", |
| 218 | .flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TLB_FLUSHED, | 231 | .flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 219 | .exit_latency = 40, | 232 | .exit_latency = 40, |
| 220 | .target_residency = 275, | 233 | .target_residency = 275, |
| 221 | .enter = &intel_idle }, | 234 | .enter = &intel_idle, |
| 235 | .enter_freeze = intel_idle_freeze, }, | ||
| 222 | { | 236 | { |
| 223 | .name = "C6S-BYT", | 237 | .name = "C6S-BYT", |
| 224 | .desc = "MWAIT 0x52", | 238 | .desc = "MWAIT 0x52", |
| 225 | .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED, | 239 | .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 226 | .exit_latency = 140, | 240 | .exit_latency = 140, |
| 227 | .target_residency = 560, | 241 | .target_residency = 560, |
| 228 | .enter = &intel_idle }, | 242 | .enter = &intel_idle, |
| 243 | .enter_freeze = intel_idle_freeze, }, | ||
| 229 | { | 244 | { |
| 230 | .name = "C7-BYT", | 245 | .name = "C7-BYT", |
| 231 | .desc = "MWAIT 0x60", | 246 | .desc = "MWAIT 0x60", |
| 232 | .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, | 247 | .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 233 | .exit_latency = 1200, | 248 | .exit_latency = 1200, |
| 234 | .target_residency = 1500, | 249 | .target_residency = 1500, |
| 235 | .enter = &intel_idle }, | 250 | .enter = &intel_idle, |
| 251 | .enter_freeze = intel_idle_freeze, }, | ||
| 236 | { | 252 | { |
| 237 | .name = "C7S-BYT", | 253 | .name = "C7S-BYT", |
| 238 | .desc = "MWAIT 0x64", | 254 | .desc = "MWAIT 0x64", |
| 239 | .flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED, | 255 | .flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 240 | .exit_latency = 10000, | 256 | .exit_latency = 10000, |
| 241 | .target_residency = 20000, | 257 | .target_residency = 20000, |
| 242 | .enter = &intel_idle }, | 258 | .enter = &intel_idle, |
| 259 | .enter_freeze = intel_idle_freeze, }, | ||
| 243 | { | 260 | { |
| 244 | .enter = NULL } | 261 | .enter = NULL } |
| 245 | }; | 262 | }; |
| @@ -251,35 +268,40 @@ static struct cpuidle_state ivb_cstates[] = { | |||
| 251 | .flags = MWAIT2flg(0x00), | 268 | .flags = MWAIT2flg(0x00), |
| 252 | .exit_latency = 1, | 269 | .exit_latency = 1, |
| 253 | .target_residency = 1, | 270 | .target_residency = 1, |
| 254 | .enter = &intel_idle }, | 271 | .enter = &intel_idle, |
| 272 | .enter_freeze = intel_idle_freeze, }, | ||
| 255 | { | 273 | { |
| 256 | .name = "C1E-IVB", | 274 | .name = "C1E-IVB", |
| 257 | .desc = "MWAIT 0x01", | 275 | .desc = "MWAIT 0x01", |
| 258 | .flags = MWAIT2flg(0x01), | 276 | .flags = MWAIT2flg(0x01), |
| 259 | .exit_latency = 10, | 277 | .exit_latency = 10, |
| 260 | .target_residency = 20, | 278 | .target_residency = 20, |
| 261 | .enter = &intel_idle }, | 279 | .enter = &intel_idle, |
| 280 | .enter_freeze = intel_idle_freeze, }, | ||
| 262 | { | 281 | { |
| 263 | .name = "C3-IVB", | 282 | .name = "C3-IVB", |
| 264 | .desc = "MWAIT 0x10", | 283 | .desc = "MWAIT 0x10", |
| 265 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, | 284 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 266 | .exit_latency = 59, | 285 | .exit_latency = 59, |
| 267 | .target_residency = 156, | 286 | .target_residency = 156, |
| 268 | .enter = &intel_idle }, | 287 | .enter = &intel_idle, |
| 288 | .enter_freeze = intel_idle_freeze, }, | ||
| 269 | { | 289 | { |
| 270 | .name = "C6-IVB", | 290 | .name = "C6-IVB", |
| 271 | .desc = "MWAIT 0x20", | 291 | .desc = "MWAIT 0x20", |
| 272 | .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, | 292 | .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 273 | .exit_latency = 80, | 293 | .exit_latency = 80, |
| 274 | .target_residency = 300, | 294 | .target_residency = 300, |
| 275 | .enter = &intel_idle }, | 295 | .enter = &intel_idle, |
| 296 | .enter_freeze = intel_idle_freeze, }, | ||
| 276 | { | 297 | { |
| 277 | .name = "C7-IVB", | 298 | .name = "C7-IVB", |
| 278 | .desc = "MWAIT 0x30", | 299 | .desc = "MWAIT 0x30", |
| 279 | .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED, | 300 | .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 280 | .exit_latency = 87, | 301 | .exit_latency = 87, |
| 281 | .target_residency = 300, | 302 | .target_residency = 300, |
| 282 | .enter = &intel_idle }, | 303 | .enter = &intel_idle, |
| 304 | .enter_freeze = intel_idle_freeze, }, | ||
| 283 | { | 305 | { |
| 284 | .enter = NULL } | 306 | .enter = NULL } |
| 285 | }; | 307 | }; |
| @@ -291,28 +313,32 @@ static struct cpuidle_state ivt_cstates[] = { | |||
| 291 | .flags = MWAIT2flg(0x00), | 313 | .flags = MWAIT2flg(0x00), |
| 292 | .exit_latency = 1, | 314 | .exit_latency = 1, |
| 293 | .target_residency = 1, | 315 | .target_residency = 1, |
| 294 | .enter = &intel_idle }, | 316 | .enter = &intel_idle, |
| 317 | .enter_freeze = intel_idle_freeze, }, | ||
| 295 | { | 318 | { |
| 296 | .name = "C1E-IVT", | 319 | .name = "C1E-IVT", |
| 297 | .desc = "MWAIT 0x01", | 320 | .desc = "MWAIT 0x01", |
| 298 | .flags = MWAIT2flg(0x01), | 321 | .flags = MWAIT2flg(0x01), |
| 299 | .exit_latency = 10, | 322 | .exit_latency = 10, |
| 300 | .target_residency = 80, | 323 | .target_residency = 80, |
| 301 | .enter = &intel_idle }, | 324 | .enter = &intel_idle, |
| 325 | .enter_freeze = intel_idle_freeze, }, | ||
| 302 | { | 326 | { |
| 303 | .name = "C3-IVT", | 327 | .name = "C3-IVT", |
| 304 | .desc = "MWAIT 0x10", | 328 | .desc = "MWAIT 0x10", |
| 305 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, | 329 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 306 | .exit_latency = 59, | 330 | .exit_latency = 59, |
| 307 | .target_residency = 156, | 331 | .target_residency = 156, |
| 308 | .enter = &intel_idle }, | 332 | .enter = &intel_idle, |
| 333 | .enter_freeze = intel_idle_freeze, }, | ||
| 309 | { | 334 | { |
| 310 | .name = "C6-IVT", | 335 | .name = "C6-IVT", |
| 311 | .desc = "MWAIT 0x20", | 336 | .desc = "MWAIT 0x20", |
| 312 | .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, | 337 | .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 313 | .exit_latency = 82, | 338 | .exit_latency = 82, |
| 314 | .target_residency = 300, | 339 | .target_residency = 300, |
| 315 | .enter = &intel_idle }, | 340 | .enter = &intel_idle, |
| 341 | .enter_freeze = intel_idle_freeze, }, | ||
| 316 | { | 342 | { |
| 317 | .enter = NULL } | 343 | .enter = NULL } |
| 318 | }; | 344 | }; |
| @@ -324,28 +350,32 @@ static struct cpuidle_state ivt_cstates_4s[] = { | |||
| 324 | .flags = MWAIT2flg(0x00), | 350 | .flags = MWAIT2flg(0x00), |
| 325 | .exit_latency = 1, | 351 | .exit_latency = 1, |
| 326 | .target_residency = 1, | 352 | .target_residency = 1, |
| 327 | .enter = &intel_idle }, | 353 | .enter = &intel_idle, |
| 354 | .enter_freeze = intel_idle_freeze, }, | ||
| 328 | { | 355 | { |
| 329 | .name = "C1E-IVT-4S", | 356 | .name = "C1E-IVT-4S", |
| 330 | .desc = "MWAIT 0x01", | 357 | .desc = "MWAIT 0x01", |
| 331 | .flags = MWAIT2flg(0x01), | 358 | .flags = MWAIT2flg(0x01), |
| 332 | .exit_latency = 10, | 359 | .exit_latency = 10, |
| 333 | .target_residency = 250, | 360 | .target_residency = 250, |
| 334 | .enter = &intel_idle }, | 361 | .enter = &intel_idle, |
| 362 | .enter_freeze = intel_idle_freeze, }, | ||
| 335 | { | 363 | { |
| 336 | .name = "C3-IVT-4S", | 364 | .name = "C3-IVT-4S", |
| 337 | .desc = "MWAIT 0x10", | 365 | .desc = "MWAIT 0x10", |
| 338 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, | 366 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 339 | .exit_latency = 59, | 367 | .exit_latency = 59, |
| 340 | .target_residency = 300, | 368 | .target_residency = 300, |
| 341 | .enter = &intel_idle }, | 369 | .enter = &intel_idle, |
| 370 | .enter_freeze = intel_idle_freeze, }, | ||
| 342 | { | 371 | { |
| 343 | .name = "C6-IVT-4S", | 372 | .name = "C6-IVT-4S", |
| 344 | .desc = "MWAIT 0x20", | 373 | .desc = "MWAIT 0x20", |
| 345 | .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, | 374 | .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 346 | .exit_latency = 84, | 375 | .exit_latency = 84, |
| 347 | .target_residency = 400, | 376 | .target_residency = 400, |
| 348 | .enter = &intel_idle }, | 377 | .enter = &intel_idle, |
| 378 | .enter_freeze = intel_idle_freeze, }, | ||
| 349 | { | 379 | { |
| 350 | .enter = NULL } | 380 | .enter = NULL } |
| 351 | }; | 381 | }; |
| @@ -357,28 +387,32 @@ static struct cpuidle_state ivt_cstates_8s[] = { | |||
| 357 | .flags = MWAIT2flg(0x00), | 387 | .flags = MWAIT2flg(0x00), |
| 358 | .exit_latency = 1, | 388 | .exit_latency = 1, |
| 359 | .target_residency = 1, | 389 | .target_residency = 1, |
| 360 | .enter = &intel_idle }, | 390 | .enter = &intel_idle, |
| 391 | .enter_freeze = intel_idle_freeze, }, | ||
| 361 | { | 392 | { |
| 362 | .name = "C1E-IVT-8S", | 393 | .name = "C1E-IVT-8S", |
| 363 | .desc = "MWAIT 0x01", | 394 | .desc = "MWAIT 0x01", |
| 364 | .flags = MWAIT2flg(0x01), | 395 | .flags = MWAIT2flg(0x01), |
| 365 | .exit_latency = 10, | 396 | .exit_latency = 10, |
| 366 | .target_residency = 500, | 397 | .target_residency = 500, |
| 367 | .enter = &intel_idle }, | 398 | .enter = &intel_idle, |
| 399 | .enter_freeze = intel_idle_freeze, }, | ||
| 368 | { | 400 | { |
| 369 | .name = "C3-IVT-8S", | 401 | .name = "C3-IVT-8S", |
| 370 | .desc = "MWAIT 0x10", | 402 | .desc = "MWAIT 0x10", |
| 371 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, | 403 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 372 | .exit_latency = 59, | 404 | .exit_latency = 59, |
| 373 | .target_residency = 600, | 405 | .target_residency = 600, |
| 374 | .enter = &intel_idle }, | 406 | .enter = &intel_idle, |
| 407 | .enter_freeze = intel_idle_freeze, }, | ||
| 375 | { | 408 | { |
| 376 | .name = "C6-IVT-8S", | 409 | .name = "C6-IVT-8S", |
| 377 | .desc = "MWAIT 0x20", | 410 | .desc = "MWAIT 0x20", |
| 378 | .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, | 411 | .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 379 | .exit_latency = 88, | 412 | .exit_latency = 88, |
| 380 | .target_residency = 700, | 413 | .target_residency = 700, |
| 381 | .enter = &intel_idle }, | 414 | .enter = &intel_idle, |
| 415 | .enter_freeze = intel_idle_freeze, }, | ||
| 382 | { | 416 | { |
| 383 | .enter = NULL } | 417 | .enter = NULL } |
| 384 | }; | 418 | }; |
| @@ -390,56 +424,64 @@ static struct cpuidle_state hsw_cstates[] = { | |||
| 390 | .flags = MWAIT2flg(0x00), | 424 | .flags = MWAIT2flg(0x00), |
| 391 | .exit_latency = 2, | 425 | .exit_latency = 2, |
| 392 | .target_residency = 2, | 426 | .target_residency = 2, |
| 393 | .enter = &intel_idle }, | 427 | .enter = &intel_idle, |
| 428 | .enter_freeze = intel_idle_freeze, }, | ||
| 394 | { | 429 | { |
| 395 | .name = "C1E-HSW", | 430 | .name = "C1E-HSW", |
| 396 | .desc = "MWAIT 0x01", | 431 | .desc = "MWAIT 0x01", |
| 397 | .flags = MWAIT2flg(0x01), | 432 | .flags = MWAIT2flg(0x01), |
| 398 | .exit_latency = 10, | 433 | .exit_latency = 10, |
| 399 | .target_residency = 20, | 434 | .target_residency = 20, |
| 400 | .enter = &intel_idle }, | 435 | .enter = &intel_idle, |
| 436 | .enter_freeze = intel_idle_freeze, }, | ||
| 401 | { | 437 | { |
| 402 | .name = "C3-HSW", | 438 | .name = "C3-HSW", |
| 403 | .desc = "MWAIT 0x10", | 439 | .desc = "MWAIT 0x10", |
| 404 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, | 440 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 405 | .exit_latency = 33, | 441 | .exit_latency = 33, |
| 406 | .target_residency = 100, | 442 | .target_residency = 100, |
| 407 | .enter = &intel_idle }, | 443 | .enter = &intel_idle, |
| 444 | .enter_freeze = intel_idle_freeze, }, | ||
| 408 | { | 445 | { |
| 409 | .name = "C6-HSW", | 446 | .name = "C6-HSW", |
| 410 | .desc = "MWAIT 0x20", | 447 | .desc = "MWAIT 0x20", |
| 411 | .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, | 448 | .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 412 | .exit_latency = 133, | 449 | .exit_latency = 133, |
| 413 | .target_residency = 400, | 450 | .target_residency = 400, |
| 414 | .enter = &intel_idle }, | 451 | .enter = &intel_idle, |
| 452 | .enter_freeze = intel_idle_freeze, }, | ||
| 415 | { | 453 | { |
| 416 | .name = "C7s-HSW", | 454 | .name = "C7s-HSW", |
| 417 | .desc = "MWAIT 0x32", | 455 | .desc = "MWAIT 0x32", |
| 418 | .flags = MWAIT2flg(0x32) | CPUIDLE_FLAG_TLB_FLUSHED, | 456 | .flags = MWAIT2flg(0x32) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 419 | .exit_latency = 166, | 457 | .exit_latency = 166, |
| 420 | .target_residency = 500, | 458 | .target_residency = 500, |
| 421 | .enter = &intel_idle }, | 459 | .enter = &intel_idle, |
| 460 | .enter_freeze = intel_idle_freeze, }, | ||
| 422 | { | 461 | { |
| 423 | .name = "C8-HSW", | 462 | .name = "C8-HSW", |
| 424 | .desc = "MWAIT 0x40", | 463 | .desc = "MWAIT 0x40", |
| 425 | .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED, | 464 | .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 426 | .exit_latency = 300, | 465 | .exit_latency = 300, |
| 427 | .target_residency = 900, | 466 | .target_residency = 900, |
| 428 | .enter = &intel_idle }, | 467 | .enter = &intel_idle, |
| 468 | .enter_freeze = intel_idle_freeze, }, | ||
| 429 | { | 469 | { |
| 430 | .name = "C9-HSW", | 470 | .name = "C9-HSW", |
| 431 | .desc = "MWAIT 0x50", | 471 | .desc = "MWAIT 0x50", |
| 432 | .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED, | 472 | .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 433 | .exit_latency = 600, | 473 | .exit_latency = 600, |
| 434 | .target_residency = 1800, | 474 | .target_residency = 1800, |
| 435 | .enter = &intel_idle }, | 475 | .enter = &intel_idle, |
| 476 | .enter_freeze = intel_idle_freeze, }, | ||
| 436 | { | 477 | { |
| 437 | .name = "C10-HSW", | 478 | .name = "C10-HSW", |
| 438 | .desc = "MWAIT 0x60", | 479 | .desc = "MWAIT 0x60", |
| 439 | .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, | 480 | .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 440 | .exit_latency = 2600, | 481 | .exit_latency = 2600, |
| 441 | .target_residency = 7700, | 482 | .target_residency = 7700, |
| 442 | .enter = &intel_idle }, | 483 | .enter = &intel_idle, |
| 484 | .enter_freeze = intel_idle_freeze, }, | ||
| 443 | { | 485 | { |
| 444 | .enter = NULL } | 486 | .enter = NULL } |
| 445 | }; | 487 | }; |
| @@ -450,56 +492,64 @@ static struct cpuidle_state bdw_cstates[] = { | |||
| 450 | .flags = MWAIT2flg(0x00), | 492 | .flags = MWAIT2flg(0x00), |
| 451 | .exit_latency = 2, | 493 | .exit_latency = 2, |
| 452 | .target_residency = 2, | 494 | .target_residency = 2, |
| 453 | .enter = &intel_idle }, | 495 | .enter = &intel_idle, |
| 496 | .enter_freeze = intel_idle_freeze, }, | ||
| 454 | { | 497 | { |
| 455 | .name = "C1E-BDW", | 498 | .name = "C1E-BDW", |
| 456 | .desc = "MWAIT 0x01", | 499 | .desc = "MWAIT 0x01", |
| 457 | .flags = MWAIT2flg(0x01), | 500 | .flags = MWAIT2flg(0x01), |
| 458 | .exit_latency = 10, | 501 | .exit_latency = 10, |
| 459 | .target_residency = 20, | 502 | .target_residency = 20, |
| 460 | .enter = &intel_idle }, | 503 | .enter = &intel_idle, |
| 504 | .enter_freeze = intel_idle_freeze, }, | ||
| 461 | { | 505 | { |
| 462 | .name = "C3-BDW", | 506 | .name = "C3-BDW", |
| 463 | .desc = "MWAIT 0x10", | 507 | .desc = "MWAIT 0x10", |
| 464 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, | 508 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 465 | .exit_latency = 40, | 509 | .exit_latency = 40, |
| 466 | .target_residency = 100, | 510 | .target_residency = 100, |
| 467 | .enter = &intel_idle }, | 511 | .enter = &intel_idle, |
| 512 | .enter_freeze = intel_idle_freeze, }, | ||
| 468 | { | 513 | { |
| 469 | .name = "C6-BDW", | 514 | .name = "C6-BDW", |
| 470 | .desc = "MWAIT 0x20", | 515 | .desc = "MWAIT 0x20", |
| 471 | .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, | 516 | .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 472 | .exit_latency = 133, | 517 | .exit_latency = 133, |
| 473 | .target_residency = 400, | 518 | .target_residency = 400, |
| 474 | .enter = &intel_idle }, | 519 | .enter = &intel_idle, |
| 520 | .enter_freeze = intel_idle_freeze, }, | ||
| 475 | { | 521 | { |
| 476 | .name = "C7s-BDW", | 522 | .name = "C7s-BDW", |
| 477 | .desc = "MWAIT 0x32", | 523 | .desc = "MWAIT 0x32", |
| 478 | .flags = MWAIT2flg(0x32) | CPUIDLE_FLAG_TLB_FLUSHED, | 524 | .flags = MWAIT2flg(0x32) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 479 | .exit_latency = 166, | 525 | .exit_latency = 166, |
| 480 | .target_residency = 500, | 526 | .target_residency = 500, |
| 481 | .enter = &intel_idle }, | 527 | .enter = &intel_idle, |
| 528 | .enter_freeze = intel_idle_freeze, }, | ||
| 482 | { | 529 | { |
| 483 | .name = "C8-BDW", | 530 | .name = "C8-BDW", |
| 484 | .desc = "MWAIT 0x40", | 531 | .desc = "MWAIT 0x40", |
| 485 | .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED, | 532 | .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 486 | .exit_latency = 300, | 533 | .exit_latency = 300, |
| 487 | .target_residency = 900, | 534 | .target_residency = 900, |
| 488 | .enter = &intel_idle }, | 535 | .enter = &intel_idle, |
| 536 | .enter_freeze = intel_idle_freeze, }, | ||
| 489 | { | 537 | { |
| 490 | .name = "C9-BDW", | 538 | .name = "C9-BDW", |
| 491 | .desc = "MWAIT 0x50", | 539 | .desc = "MWAIT 0x50", |
| 492 | .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED, | 540 | .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 493 | .exit_latency = 600, | 541 | .exit_latency = 600, |
| 494 | .target_residency = 1800, | 542 | .target_residency = 1800, |
| 495 | .enter = &intel_idle }, | 543 | .enter = &intel_idle, |
| 544 | .enter_freeze = intel_idle_freeze, }, | ||
| 496 | { | 545 | { |
| 497 | .name = "C10-BDW", | 546 | .name = "C10-BDW", |
| 498 | .desc = "MWAIT 0x60", | 547 | .desc = "MWAIT 0x60", |
| 499 | .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, | 548 | .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 500 | .exit_latency = 2600, | 549 | .exit_latency = 2600, |
| 501 | .target_residency = 7700, | 550 | .target_residency = 7700, |
| 502 | .enter = &intel_idle }, | 551 | .enter = &intel_idle, |
| 552 | .enter_freeze = intel_idle_freeze, }, | ||
| 503 | { | 553 | { |
| 504 | .enter = NULL } | 554 | .enter = NULL } |
| 505 | }; | 555 | }; |
| @@ -511,28 +561,32 @@ static struct cpuidle_state atom_cstates[] = { | |||
| 511 | .flags = MWAIT2flg(0x00), | 561 | .flags = MWAIT2flg(0x00), |
| 512 | .exit_latency = 10, | 562 | .exit_latency = 10, |
| 513 | .target_residency = 20, | 563 | .target_residency = 20, |
| 514 | .enter = &intel_idle }, | 564 | .enter = &intel_idle, |
| 565 | .enter_freeze = intel_idle_freeze, }, | ||
| 515 | { | 566 | { |
| 516 | .name = "C2-ATM", | 567 | .name = "C2-ATM", |
| 517 | .desc = "MWAIT 0x10", | 568 | .desc = "MWAIT 0x10", |
| 518 | .flags = MWAIT2flg(0x10), | 569 | .flags = MWAIT2flg(0x10), |
| 519 | .exit_latency = 20, | 570 | .exit_latency = 20, |
| 520 | .target_residency = 80, | 571 | .target_residency = 80, |
| 521 | .enter = &intel_idle }, | 572 | .enter = &intel_idle, |
| 573 | .enter_freeze = intel_idle_freeze, }, | ||
| 522 | { | 574 | { |
| 523 | .name = "C4-ATM", | 575 | .name = "C4-ATM", |
| 524 | .desc = "MWAIT 0x30", | 576 | .desc = "MWAIT 0x30", |
| 525 | .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED, | 577 | .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 526 | .exit_latency = 100, | 578 | .exit_latency = 100, |
| 527 | .target_residency = 400, | 579 | .target_residency = 400, |
| 528 | .enter = &intel_idle }, | 580 | .enter = &intel_idle, |
| 581 | .enter_freeze = intel_idle_freeze, }, | ||
| 529 | { | 582 | { |
| 530 | .name = "C6-ATM", | 583 | .name = "C6-ATM", |
| 531 | .desc = "MWAIT 0x52", | 584 | .desc = "MWAIT 0x52", |
| 532 | .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED, | 585 | .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 533 | .exit_latency = 140, | 586 | .exit_latency = 140, |
| 534 | .target_residency = 560, | 587 | .target_residency = 560, |
| 535 | .enter = &intel_idle }, | 588 | .enter = &intel_idle, |
| 589 | .enter_freeze = intel_idle_freeze, }, | ||
| 536 | { | 590 | { |
| 537 | .enter = NULL } | 591 | .enter = NULL } |
| 538 | }; | 592 | }; |
| @@ -543,14 +597,16 @@ static struct cpuidle_state avn_cstates[] = { | |||
| 543 | .flags = MWAIT2flg(0x00), | 597 | .flags = MWAIT2flg(0x00), |
| 544 | .exit_latency = 2, | 598 | .exit_latency = 2, |
| 545 | .target_residency = 2, | 599 | .target_residency = 2, |
| 546 | .enter = &intel_idle }, | 600 | .enter = &intel_idle, |
| 601 | .enter_freeze = intel_idle_freeze, }, | ||
| 547 | { | 602 | { |
| 548 | .name = "C6-AVN", | 603 | .name = "C6-AVN", |
| 549 | .desc = "MWAIT 0x51", | 604 | .desc = "MWAIT 0x51", |
| 550 | .flags = MWAIT2flg(0x51) | CPUIDLE_FLAG_TLB_FLUSHED, | 605 | .flags = MWAIT2flg(0x51) | CPUIDLE_FLAG_TLB_FLUSHED, |
| 551 | .exit_latency = 15, | 606 | .exit_latency = 15, |
| 552 | .target_residency = 45, | 607 | .target_residency = 45, |
| 553 | .enter = &intel_idle }, | 608 | .enter = &intel_idle, |
| 609 | .enter_freeze = intel_idle_freeze, }, | ||
| 554 | { | 610 | { |
| 555 | .enter = NULL } | 611 | .enter = NULL } |
| 556 | }; | 612 | }; |
| @@ -592,6 +648,21 @@ static int intel_idle(struct cpuidle_device *dev, | |||
| 592 | return index; | 648 | return index; |
| 593 | } | 649 | } |
| 594 | 650 | ||
| 651 | /** | ||
| 652 | * intel_idle_freeze - simplified "enter" callback routine for suspend-to-idle | ||
| 653 | * @dev: cpuidle_device | ||
| 654 | * @drv: cpuidle driver | ||
| 655 | * @index: state index | ||
| 656 | */ | ||
| 657 | static void intel_idle_freeze(struct cpuidle_device *dev, | ||
| 658 | struct cpuidle_driver *drv, int index) | ||
| 659 | { | ||
| 660 | unsigned long ecx = 1; /* break on interrupt flag */ | ||
| 661 | unsigned long eax = flg2MWAIT(drv->states[index].flags); | ||
| 662 | |||
| 663 | mwait_idle_with_hints(eax, ecx); | ||
| 664 | } | ||
| 665 | |||
| 595 | static void __setup_broadcast_timer(void *arg) | 666 | static void __setup_broadcast_timer(void *arg) |
| 596 | { | 667 | { |
| 597 | unsigned long reason = (unsigned long)arg; | 668 | unsigned long reason = (unsigned long)arg; |
diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c index aafdbcd84fc4..8fb295e4a9ab 100644 --- a/drivers/infiniband/hw/cxgb4/device.c +++ b/drivers/infiniband/hw/cxgb4/device.c | |||
| @@ -700,37 +700,24 @@ static const struct file_operations ep_debugfs_fops = { | |||
| 700 | 700 | ||
| 701 | static int setup_debugfs(struct c4iw_dev *devp) | 701 | static int setup_debugfs(struct c4iw_dev *devp) |
| 702 | { | 702 | { |
| 703 | struct dentry *de; | ||
| 704 | |||
| 705 | if (!devp->debugfs_root) | 703 | if (!devp->debugfs_root) |
| 706 | return -1; | 704 | return -1; |
| 707 | 705 | ||
| 708 | de = debugfs_create_file("qps", S_IWUSR, devp->debugfs_root, | 706 | debugfs_create_file_size("qps", S_IWUSR, devp->debugfs_root, |
| 709 | (void *)devp, &qp_debugfs_fops); | 707 | (void *)devp, &qp_debugfs_fops, 4096); |
| 710 | if (de && de->d_inode) | ||
| 711 | de->d_inode->i_size = 4096; | ||
| 712 | 708 | ||
| 713 | de = debugfs_create_file("stags", S_IWUSR, devp->debugfs_root, | 709 | debugfs_create_file_size("stags", S_IWUSR, devp->debugfs_root, |
| 714 | (void *)devp, &stag_debugfs_fops); | 710 | (void *)devp, &stag_debugfs_fops, 4096); |
| 715 | if (de && de->d_inode) | ||
| 716 | de->d_inode->i_size = 4096; | ||
| 717 | 711 | ||
| 718 | de = debugfs_create_file("stats", S_IWUSR, devp->debugfs_root, | 712 | debugfs_create_file_size("stats", S_IWUSR, devp->debugfs_root, |
| 719 | (void *)devp, &stats_debugfs_fops); | 713 | (void *)devp, &stats_debugfs_fops, 4096); |
| 720 | if (de && de->d_inode) | ||
| 721 | de->d_inode->i_size = 4096; | ||
| 722 | 714 | ||
| 723 | de = debugfs_create_file("eps", S_IWUSR, devp->debugfs_root, | 715 | debugfs_create_file_size("eps", S_IWUSR, devp->debugfs_root, |
| 724 | (void *)devp, &ep_debugfs_fops); | 716 | (void *)devp, &ep_debugfs_fops, 4096); |
| 725 | if (de && de->d_inode) | ||
| 726 | de->d_inode->i_size = 4096; | ||
| 727 | 717 | ||
| 728 | if (c4iw_wr_log) { | 718 | if (c4iw_wr_log) |
| 729 | de = debugfs_create_file("wr_log", S_IWUSR, devp->debugfs_root, | 719 | debugfs_create_file_size("wr_log", S_IWUSR, devp->debugfs_root, |
| 730 | (void *)devp, &wr_log_debugfs_fops); | 720 | (void *)devp, &wr_log_debugfs_fops, 4096); |
| 731 | if (de && de->d_inode) | ||
| 732 | de->d_inode->i_size = 4096; | ||
| 733 | } | ||
| 734 | return 0; | 721 | return 0; |
| 735 | } | 722 | } |
| 736 | 723 | ||
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 5dd0c2e59ab9..4153da5d4011 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
| @@ -2196,7 +2196,8 @@ static int narrow_write_error(struct r1bio *r1_bio, int i) | |||
| 2196 | if (rdev->badblocks.shift < 0) | 2196 | if (rdev->badblocks.shift < 0) |
| 2197 | return 0; | 2197 | return 0; |
| 2198 | 2198 | ||
| 2199 | block_sectors = 1 << rdev->badblocks.shift; | 2199 | block_sectors = roundup(1 << rdev->badblocks.shift, |
| 2200 | bdev_logical_block_size(rdev->bdev) >> 9); | ||
| 2200 | sector = r1_bio->sector; | 2201 | sector = r1_bio->sector; |
| 2201 | sectors = ((sector + block_sectors) | 2202 | sectors = ((sector + block_sectors) |
| 2202 | & ~(sector_t)(block_sectors - 1)) | 2203 | & ~(sector_t)(block_sectors - 1)) |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index b8d76b1fba64..a7196c49d15d 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
| @@ -2572,7 +2572,8 @@ static int narrow_write_error(struct r10bio *r10_bio, int i) | |||
| 2572 | if (rdev->badblocks.shift < 0) | 2572 | if (rdev->badblocks.shift < 0) |
| 2573 | return 0; | 2573 | return 0; |
| 2574 | 2574 | ||
| 2575 | block_sectors = 1 << rdev->badblocks.shift; | 2575 | block_sectors = roundup(1 << rdev->badblocks.shift, |
| 2576 | bdev_logical_block_size(rdev->bdev) >> 9); | ||
| 2576 | sector = r10_bio->sector; | 2577 | sector = r10_bio->sector; |
| 2577 | sectors = ((r10_bio->sector + block_sectors) | 2578 | sectors = ((r10_bio->sector + block_sectors) |
| 2578 | & ~(sector_t)(block_sectors - 1)) | 2579 | & ~(sector_t)(block_sectors - 1)) |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index aa76865b804b..e75d48c0421a 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
| @@ -3170,7 +3170,8 @@ static void handle_stripe_dirtying(struct r5conf *conf, | |||
| 3170 | * generate correct data from the parity. | 3170 | * generate correct data from the parity. |
| 3171 | */ | 3171 | */ |
| 3172 | if (conf->max_degraded == 2 || | 3172 | if (conf->max_degraded == 2 || |
| 3173 | (recovery_cp < MaxSector && sh->sector >= recovery_cp)) { | 3173 | (recovery_cp < MaxSector && sh->sector >= recovery_cp && |
| 3174 | s->failed == 0)) { | ||
| 3174 | /* Calculate the real rcw later - for now make it | 3175 | /* Calculate the real rcw later - for now make it |
| 3175 | * look like rcw is cheaper | 3176 | * look like rcw is cheaper |
| 3176 | */ | 3177 | */ |
diff --git a/drivers/mtd/bcm47xxpart.c b/drivers/mtd/bcm47xxpart.c index cc13ea5ce4d5..c0720c1ee4c9 100644 --- a/drivers/mtd/bcm47xxpart.c +++ b/drivers/mtd/bcm47xxpart.c | |||
| @@ -15,6 +15,8 @@ | |||
| 15 | #include <linux/mtd/mtd.h> | 15 | #include <linux/mtd/mtd.h> |
| 16 | #include <linux/mtd/partitions.h> | 16 | #include <linux/mtd/partitions.h> |
| 17 | 17 | ||
| 18 | #include <uapi/linux/magic.h> | ||
| 19 | |||
| 18 | /* | 20 | /* |
| 19 | * NAND flash on Netgear R6250 was verified to contain 15 partitions. | 21 | * NAND flash on Netgear R6250 was verified to contain 15 partitions. |
| 20 | * This will result in allocating too big array for some old devices, but the | 22 | * This will result in allocating too big array for some old devices, but the |
| @@ -39,7 +41,8 @@ | |||
| 39 | #define ML_MAGIC1 0x39685a42 | 41 | #define ML_MAGIC1 0x39685a42 |
| 40 | #define ML_MAGIC2 0x26594131 | 42 | #define ML_MAGIC2 0x26594131 |
| 41 | #define TRX_MAGIC 0x30524448 | 43 | #define TRX_MAGIC 0x30524448 |
| 42 | #define SQSH_MAGIC 0x71736873 /* shsq */ | 44 | #define SHSQ_MAGIC 0x71736873 /* shsq (weird ZTE H218N endianness) */ |
| 45 | #define UBI_EC_MAGIC 0x23494255 /* UBI# */ | ||
| 43 | 46 | ||
| 44 | struct trx_header { | 47 | struct trx_header { |
| 45 | uint32_t magic; | 48 | uint32_t magic; |
| @@ -50,7 +53,7 @@ struct trx_header { | |||
| 50 | uint32_t offset[3]; | 53 | uint32_t offset[3]; |
| 51 | } __packed; | 54 | } __packed; |
| 52 | 55 | ||
| 53 | static void bcm47xxpart_add_part(struct mtd_partition *part, char *name, | 56 | static void bcm47xxpart_add_part(struct mtd_partition *part, const char *name, |
| 54 | u64 offset, uint32_t mask_flags) | 57 | u64 offset, uint32_t mask_flags) |
| 55 | { | 58 | { |
| 56 | part->name = name; | 59 | part->name = name; |
| @@ -58,6 +61,26 @@ static void bcm47xxpart_add_part(struct mtd_partition *part, char *name, | |||
| 58 | part->mask_flags = mask_flags; | 61 | part->mask_flags = mask_flags; |
| 59 | } | 62 | } |
| 60 | 63 | ||
| 64 | static const char *bcm47xxpart_trx_data_part_name(struct mtd_info *master, | ||
| 65 | size_t offset) | ||
| 66 | { | ||
| 67 | uint32_t buf; | ||
| 68 | size_t bytes_read; | ||
| 69 | |||
| 70 | if (mtd_read(master, offset, sizeof(buf), &bytes_read, | ||
| 71 | (uint8_t *)&buf) < 0) { | ||
| 72 | pr_err("mtd_read error while parsing (offset: 0x%X)!\n", | ||
| 73 | offset); | ||
| 74 | goto out_default; | ||
| 75 | } | ||
| 76 | |||
| 77 | if (buf == UBI_EC_MAGIC) | ||
| 78 | return "ubi"; | ||
| 79 | |||
| 80 | out_default: | ||
| 81 | return "rootfs"; | ||
| 82 | } | ||
| 83 | |||
| 61 | static int bcm47xxpart_parse(struct mtd_info *master, | 84 | static int bcm47xxpart_parse(struct mtd_info *master, |
| 62 | struct mtd_partition **pparts, | 85 | struct mtd_partition **pparts, |
| 63 | struct mtd_part_parser_data *data) | 86 | struct mtd_part_parser_data *data) |
| @@ -73,8 +96,12 @@ static int bcm47xxpart_parse(struct mtd_info *master, | |||
| 73 | int last_trx_part = -1; | 96 | int last_trx_part = -1; |
| 74 | int possible_nvram_sizes[] = { 0x8000, 0xF000, 0x10000, }; | 97 | int possible_nvram_sizes[] = { 0x8000, 0xF000, 0x10000, }; |
| 75 | 98 | ||
| 76 | if (blocksize <= 0x10000) | 99 | /* |
| 77 | blocksize = 0x10000; | 100 | * Some really old flashes (like AT45DB*) had smaller erasesize-s, but |
| 101 | * partitions were aligned to at least 0x1000 anyway. | ||
| 102 | */ | ||
| 103 | if (blocksize < 0x1000) | ||
| 104 | blocksize = 0x1000; | ||
| 78 | 105 | ||
| 79 | /* Alloc */ | 106 | /* Alloc */ |
| 80 | parts = kzalloc(sizeof(struct mtd_partition) * BCM47XXPART_MAX_PARTS, | 107 | parts = kzalloc(sizeof(struct mtd_partition) * BCM47XXPART_MAX_PARTS, |
| @@ -186,8 +213,11 @@ static int bcm47xxpart_parse(struct mtd_info *master, | |||
| 186 | * we want to have jffs2 (overlay) in the same mtd. | 213 | * we want to have jffs2 (overlay) in the same mtd. |
| 187 | */ | 214 | */ |
| 188 | if (trx->offset[i]) { | 215 | if (trx->offset[i]) { |
| 216 | const char *name; | ||
| 217 | |||
| 218 | name = bcm47xxpart_trx_data_part_name(master, offset + trx->offset[i]); | ||
| 189 | bcm47xxpart_add_part(&parts[curr_part++], | 219 | bcm47xxpart_add_part(&parts[curr_part++], |
| 190 | "rootfs", | 220 | name, |
| 191 | offset + trx->offset[i], | 221 | offset + trx->offset[i], |
| 192 | 0); | 222 | 0); |
| 193 | i++; | 223 | i++; |
| @@ -205,7 +235,8 @@ static int bcm47xxpart_parse(struct mtd_info *master, | |||
| 205 | } | 235 | } |
| 206 | 236 | ||
| 207 | /* Squashfs on devices not using TRX */ | 237 | /* Squashfs on devices not using TRX */ |
| 208 | if (buf[0x000 / 4] == SQSH_MAGIC) { | 238 | if (le32_to_cpu(buf[0x000 / 4]) == SQUASHFS_MAGIC || |
| 239 | buf[0x000 / 4] == SHSQ_MAGIC) { | ||
| 209 | bcm47xxpart_add_part(&parts[curr_part++], "rootfs", | 240 | bcm47xxpart_add_part(&parts[curr_part++], "rootfs", |
| 210 | offset, 0); | 241 | offset, 0); |
| 211 | continue; | 242 | continue; |
diff --git a/drivers/mtd/chips/map_ram.c b/drivers/mtd/chips/map_ram.c index 991c2a1c05d3..afb43d5e1782 100644 --- a/drivers/mtd/chips/map_ram.c +++ b/drivers/mtd/chips/map_ram.c | |||
| @@ -68,6 +68,7 @@ static struct mtd_info *map_ram_probe(struct map_info *map) | |||
| 68 | mtd->_get_unmapped_area = mapram_unmapped_area; | 68 | mtd->_get_unmapped_area = mapram_unmapped_area; |
| 69 | mtd->_read = mapram_read; | 69 | mtd->_read = mapram_read; |
| 70 | mtd->_write = mapram_write; | 70 | mtd->_write = mapram_write; |
| 71 | mtd->_panic_write = mapram_write; | ||
| 71 | mtd->_sync = mapram_nop; | 72 | mtd->_sync = mapram_nop; |
| 72 | mtd->flags = MTD_CAP_RAM; | 73 | mtd->flags = MTD_CAP_RAM; |
| 73 | mtd->writesize = 1; | 74 | mtd->writesize = 1; |
diff --git a/drivers/mtd/chips/map_rom.c b/drivers/mtd/chips/map_rom.c index 47a43cf7e5c6..e67f73ab44c9 100644 --- a/drivers/mtd/chips/map_rom.c +++ b/drivers/mtd/chips/map_rom.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <linux/errno.h> | 11 | #include <linux/errno.h> |
| 12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| 13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
| 14 | #include <linux/of.h> | ||
| 14 | #include <linux/mtd/mtd.h> | 15 | #include <linux/mtd/mtd.h> |
| 15 | #include <linux/mtd/map.h> | 16 | #include <linux/mtd/map.h> |
| 16 | 17 | ||
| @@ -28,6 +29,15 @@ static struct mtd_chip_driver maprom_chipdrv = { | |||
| 28 | .module = THIS_MODULE | 29 | .module = THIS_MODULE |
| 29 | }; | 30 | }; |
| 30 | 31 | ||
| 32 | static unsigned int default_erasesize(struct map_info *map) | ||
| 33 | { | ||
| 34 | const __be32 *erase_size = NULL; | ||
| 35 | |||
| 36 | erase_size = of_get_property(map->device_node, "erase-size", NULL); | ||
| 37 | |||
| 38 | return !erase_size ? map->size : be32_to_cpu(*erase_size); | ||
| 39 | } | ||
| 40 | |||
| 31 | static struct mtd_info *map_rom_probe(struct map_info *map) | 41 | static struct mtd_info *map_rom_probe(struct map_info *map) |
| 32 | { | 42 | { |
| 33 | struct mtd_info *mtd; | 43 | struct mtd_info *mtd; |
| @@ -47,8 +57,9 @@ static struct mtd_info *map_rom_probe(struct map_info *map) | |||
| 47 | mtd->_sync = maprom_nop; | 57 | mtd->_sync = maprom_nop; |
| 48 | mtd->_erase = maprom_erase; | 58 | mtd->_erase = maprom_erase; |
| 49 | mtd->flags = MTD_CAP_ROM; | 59 | mtd->flags = MTD_CAP_ROM; |
| 50 | mtd->erasesize = map->size; | 60 | mtd->erasesize = default_erasesize(map); |
| 51 | mtd->writesize = 1; | 61 | mtd->writesize = 1; |
| 62 | mtd->writebufsize = 1; | ||
| 52 | 63 | ||
| 53 | __module_get(THIS_MODULE); | 64 | __module_get(THIS_MODULE); |
| 54 | return mtd; | 65 | return mtd; |
diff --git a/drivers/mtd/devices/st_spi_fsm.c b/drivers/mtd/devices/st_spi_fsm.c index 54ffe5223e64..3060025c8af4 100644 --- a/drivers/mtd/devices/st_spi_fsm.c +++ b/drivers/mtd/devices/st_spi_fsm.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
| 25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
| 26 | #include <linux/of.h> | 26 | #include <linux/of.h> |
| 27 | #include <linux/clk.h> | ||
| 27 | 28 | ||
| 28 | #include "serial_flash_cmds.h" | 29 | #include "serial_flash_cmds.h" |
| 29 | 30 | ||
| @@ -262,6 +263,7 @@ struct stfsm { | |||
| 262 | struct mtd_info mtd; | 263 | struct mtd_info mtd; |
| 263 | struct mutex lock; | 264 | struct mutex lock; |
| 264 | struct flash_info *info; | 265 | struct flash_info *info; |
| 266 | struct clk *clk; | ||
| 265 | 267 | ||
| 266 | uint32_t configuration; | 268 | uint32_t configuration; |
| 267 | uint32_t fifo_dir_delay; | 269 | uint32_t fifo_dir_delay; |
| @@ -663,6 +665,23 @@ static struct stfsm_seq stfsm_seq_write_status = { | |||
| 663 | SEQ_CFG_STARTSEQ), | 665 | SEQ_CFG_STARTSEQ), |
| 664 | }; | 666 | }; |
| 665 | 667 | ||
| 668 | /* Dummy sequence to read one byte of data from flash into the FIFO */ | ||
| 669 | static const struct stfsm_seq stfsm_seq_load_fifo_byte = { | ||
| 670 | .data_size = TRANSFER_SIZE(1), | ||
| 671 | .seq_opc[0] = (SEQ_OPC_PADS_1 | | ||
| 672 | SEQ_OPC_CYCLES(8) | | ||
| 673 | SEQ_OPC_OPCODE(SPINOR_OP_RDID)), | ||
| 674 | .seq = { | ||
| 675 | STFSM_INST_CMD1, | ||
| 676 | STFSM_INST_DATA_READ, | ||
| 677 | STFSM_INST_STOP, | ||
| 678 | }, | ||
| 679 | .seq_cfg = (SEQ_CFG_PADS_1 | | ||
| 680 | SEQ_CFG_READNOTWRITE | | ||
| 681 | SEQ_CFG_CSDEASSERT | | ||
| 682 | SEQ_CFG_STARTSEQ), | ||
| 683 | }; | ||
| 684 | |||
| 666 | static int stfsm_n25q_en_32bit_addr_seq(struct stfsm_seq *seq) | 685 | static int stfsm_n25q_en_32bit_addr_seq(struct stfsm_seq *seq) |
| 667 | { | 686 | { |
| 668 | seq->seq_opc[0] = (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | | 687 | seq->seq_opc[0] = (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | |
| @@ -695,22 +714,6 @@ static inline uint32_t stfsm_fifo_available(struct stfsm *fsm) | |||
| 695 | return (readl(fsm->base + SPI_FAST_SEQ_STA) >> 5) & 0x7f; | 714 | return (readl(fsm->base + SPI_FAST_SEQ_STA) >> 5) & 0x7f; |
| 696 | } | 715 | } |
| 697 | 716 | ||
| 698 | static void stfsm_clear_fifo(struct stfsm *fsm) | ||
| 699 | { | ||
| 700 | uint32_t avail; | ||
| 701 | |||
| 702 | for (;;) { | ||
| 703 | avail = stfsm_fifo_available(fsm); | ||
| 704 | if (!avail) | ||
| 705 | break; | ||
| 706 | |||
| 707 | while (avail) { | ||
| 708 | readl(fsm->base + SPI_FAST_SEQ_DATA_REG); | ||
| 709 | avail--; | ||
| 710 | } | ||
| 711 | } | ||
| 712 | } | ||
| 713 | |||
| 714 | static inline void stfsm_load_seq(struct stfsm *fsm, | 717 | static inline void stfsm_load_seq(struct stfsm *fsm, |
| 715 | const struct stfsm_seq *seq) | 718 | const struct stfsm_seq *seq) |
| 716 | { | 719 | { |
| @@ -772,6 +775,68 @@ static void stfsm_read_fifo(struct stfsm *fsm, uint32_t *buf, uint32_t size) | |||
| 772 | } | 775 | } |
| 773 | } | 776 | } |
| 774 | 777 | ||
| 778 | /* | ||
| 779 | * Clear the data FIFO | ||
| 780 | * | ||
| 781 | * Typically, this is only required during driver initialisation, where no | ||
| 782 | * assumptions can be made regarding the state of the FIFO. | ||
| 783 | * | ||
| 784 | * The process of clearing the FIFO is complicated by fact that while it is | ||
| 785 | * possible for the FIFO to contain an arbitrary number of bytes [1], the | ||
| 786 | * SPI_FAST_SEQ_STA register only reports the number of complete 32-bit words | ||
| 787 | * present. Furthermore, data can only be drained from the FIFO by reading | ||
| 788 | * complete 32-bit words. | ||
| 789 | * | ||
| 790 | * With this in mind, a two stage process is used to the clear the FIFO: | ||
| 791 | * | ||
| 792 | * 1. Read any complete 32-bit words from the FIFO, as reported by the | ||
| 793 | * SPI_FAST_SEQ_STA register. | ||
| 794 | * | ||
| 795 | * 2. Mop up any remaining bytes. At this point, it is not known if there | ||
| 796 | * are 0, 1, 2, or 3 bytes in the FIFO. To handle all cases, a dummy FSM | ||
| 797 | * sequence is used to load one byte at a time, until a complete 32-bit | ||
| 798 | * word is formed; at most, 4 bytes will need to be loaded. | ||
| 799 | * | ||
| 800 | * [1] It is theoretically possible for the FIFO to contain an arbitrary number | ||
| 801 | * of bits. However, since there are no known use-cases that leave | ||
| 802 | * incomplete bytes in the FIFO, only words and bytes are considered here. | ||
| 803 | */ | ||
| 804 | static void stfsm_clear_fifo(struct stfsm *fsm) | ||
| 805 | { | ||
| 806 | const struct stfsm_seq *seq = &stfsm_seq_load_fifo_byte; | ||
| 807 | uint32_t words, i; | ||
| 808 | |||
| 809 | /* 1. Clear any 32-bit words */ | ||
| 810 | words = stfsm_fifo_available(fsm); | ||
| 811 | if (words) { | ||
| 812 | for (i = 0; i < words; i++) | ||
| 813 | readl(fsm->base + SPI_FAST_SEQ_DATA_REG); | ||
| 814 | dev_dbg(fsm->dev, "cleared %d words from FIFO\n", words); | ||
| 815 | } | ||
| 816 | |||
| 817 | /* | ||
| 818 | * 2. Clear any remaining bytes | ||
| 819 | * - Load the FIFO, one byte at a time, until a complete 32-bit word | ||
| 820 | * is available. | ||
| 821 | */ | ||
| 822 | for (i = 0, words = 0; i < 4 && !words; i++) { | ||
| 823 | stfsm_load_seq(fsm, seq); | ||
| 824 | stfsm_wait_seq(fsm); | ||
| 825 | words = stfsm_fifo_available(fsm); | ||
| 826 | } | ||
| 827 | |||
| 828 | /* - A single word must be available now */ | ||
| 829 | if (words != 1) { | ||
| 830 | dev_err(fsm->dev, "failed to clear bytes from the data FIFO\n"); | ||
| 831 | return; | ||
| 832 | } | ||
| 833 | |||
| 834 | /* - Read the 32-bit word */ | ||
| 835 | readl(fsm->base + SPI_FAST_SEQ_DATA_REG); | ||
| 836 | |||
| 837 | dev_dbg(fsm->dev, "cleared %d byte(s) from the data FIFO\n", 4 - i); | ||
| 838 | } | ||
| 839 | |||
| 775 | static int stfsm_write_fifo(struct stfsm *fsm, const uint32_t *buf, | 840 | static int stfsm_write_fifo(struct stfsm *fsm, const uint32_t *buf, |
| 776 | uint32_t size) | 841 | uint32_t size) |
| 777 | { | 842 | { |
| @@ -1521,11 +1586,11 @@ static int stfsm_write(struct stfsm *fsm, const uint8_t *buf, | |||
| 1521 | uint32_t size_lb; | 1586 | uint32_t size_lb; |
| 1522 | uint32_t size_mop; | 1587 | uint32_t size_mop; |
| 1523 | uint32_t tmp[4]; | 1588 | uint32_t tmp[4]; |
| 1589 | uint32_t i; | ||
| 1524 | uint32_t page_buf[FLASH_PAGESIZE_32]; | 1590 | uint32_t page_buf[FLASH_PAGESIZE_32]; |
| 1525 | uint8_t *t = (uint8_t *)&tmp; | 1591 | uint8_t *t = (uint8_t *)&tmp; |
| 1526 | const uint8_t *p; | 1592 | const uint8_t *p; |
| 1527 | int ret; | 1593 | int ret; |
| 1528 | int i; | ||
| 1529 | 1594 | ||
| 1530 | dev_dbg(fsm->dev, "writing %d bytes to 0x%08x\n", size, offset); | 1595 | dev_dbg(fsm->dev, "writing %d bytes to 0x%08x\n", size, offset); |
| 1531 | 1596 | ||
| @@ -1843,8 +1908,7 @@ static void stfsm_set_freq(struct stfsm *fsm, uint32_t spi_freq) | |||
| 1843 | uint32_t emi_freq; | 1908 | uint32_t emi_freq; |
| 1844 | uint32_t clk_div; | 1909 | uint32_t clk_div; |
| 1845 | 1910 | ||
| 1846 | /* TODO: Make this dynamic */ | 1911 | emi_freq = clk_get_rate(fsm->clk); |
| 1847 | emi_freq = STFSM_DEFAULT_EMI_FREQ; | ||
| 1848 | 1912 | ||
| 1849 | /* | 1913 | /* |
| 1850 | * Calculate clk_div - values between 2 and 128 | 1914 | * Calculate clk_div - values between 2 and 128 |
| @@ -1994,6 +2058,18 @@ static int stfsm_probe(struct platform_device *pdev) | |||
| 1994 | return PTR_ERR(fsm->base); | 2058 | return PTR_ERR(fsm->base); |
| 1995 | } | 2059 | } |
| 1996 | 2060 | ||
| 2061 | fsm->clk = devm_clk_get(&pdev->dev, NULL); | ||
| 2062 | if (IS_ERR(fsm->clk)) { | ||
| 2063 | dev_err(fsm->dev, "Couldn't find EMI clock.\n"); | ||
| 2064 | return PTR_ERR(fsm->clk); | ||
| 2065 | } | ||
| 2066 | |||
| 2067 | ret = clk_prepare_enable(fsm->clk); | ||
| 2068 | if (ret) { | ||
| 2069 | dev_err(fsm->dev, "Failed to enable EMI clock.\n"); | ||
| 2070 | return ret; | ||
| 2071 | } | ||
| 2072 | |||
| 1997 | mutex_init(&fsm->lock); | 2073 | mutex_init(&fsm->lock); |
| 1998 | 2074 | ||
| 1999 | ret = stfsm_init(fsm); | 2075 | ret = stfsm_init(fsm); |
| @@ -2058,6 +2134,28 @@ static int stfsm_remove(struct platform_device *pdev) | |||
| 2058 | return mtd_device_unregister(&fsm->mtd); | 2134 | return mtd_device_unregister(&fsm->mtd); |
| 2059 | } | 2135 | } |
| 2060 | 2136 | ||
| 2137 | #ifdef CONFIG_PM_SLEEP | ||
| 2138 | static int stfsmfsm_suspend(struct device *dev) | ||
| 2139 | { | ||
| 2140 | struct stfsm *fsm = dev_get_drvdata(dev); | ||
| 2141 | |||
| 2142 | clk_disable_unprepare(fsm->clk); | ||
| 2143 | |||
| 2144 | return 0; | ||
| 2145 | } | ||
| 2146 | |||
| 2147 | static int stfsmfsm_resume(struct device *dev) | ||
| 2148 | { | ||
| 2149 | struct stfsm *fsm = dev_get_drvdata(dev); | ||
| 2150 | |||
| 2151 | clk_prepare_enable(fsm->clk); | ||
| 2152 | |||
| 2153 | return 0; | ||
| 2154 | } | ||
| 2155 | #endif | ||
| 2156 | |||
| 2157 | static SIMPLE_DEV_PM_OPS(stfsm_pm_ops, stfsmfsm_suspend, stfsmfsm_resume); | ||
| 2158 | |||
| 2061 | static const struct of_device_id stfsm_match[] = { | 2159 | static const struct of_device_id stfsm_match[] = { |
| 2062 | { .compatible = "st,spi-fsm", }, | 2160 | { .compatible = "st,spi-fsm", }, |
| 2063 | {}, | 2161 | {}, |
| @@ -2070,6 +2168,7 @@ static struct platform_driver stfsm_driver = { | |||
| 2070 | .driver = { | 2168 | .driver = { |
| 2071 | .name = "st-spi-fsm", | 2169 | .name = "st-spi-fsm", |
| 2072 | .of_match_table = stfsm_match, | 2170 | .of_match_table = stfsm_match, |
| 2171 | .pm = &stfsm_pm_ops, | ||
| 2073 | }, | 2172 | }, |
| 2074 | }; | 2173 | }; |
| 2075 | module_platform_driver(stfsm_driver); | 2174 | module_platform_driver(stfsm_driver); |
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index f35cd2081314..ff26e979b1a1 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c | |||
| @@ -269,6 +269,16 @@ static int of_flash_probe(struct platform_device *dev) | |||
| 269 | info->list[i].mtd = obsolete_probe(dev, | 269 | info->list[i].mtd = obsolete_probe(dev, |
| 270 | &info->list[i].map); | 270 | &info->list[i].map); |
| 271 | } | 271 | } |
| 272 | |||
| 273 | /* Fall back to mapping region as ROM */ | ||
| 274 | if (!info->list[i].mtd) { | ||
| 275 | dev_warn(&dev->dev, | ||
| 276 | "do_map_probe() failed for type %s\n", | ||
| 277 | probe_type); | ||
| 278 | |||
| 279 | info->list[i].mtd = do_map_probe("map_rom", | ||
| 280 | &info->list[i].map); | ||
| 281 | } | ||
| 272 | mtd_list[i] = info->list[i].mtd; | 282 | mtd_list[i] = info->list[i].mtd; |
| 273 | 283 | ||
| 274 | err = -ENXIO; | 284 | err = -ENXIO; |
diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c index 485ea751c7f9..bb4c14f83c75 100644 --- a/drivers/mtd/mtdblock.c +++ b/drivers/mtd/mtdblock.c | |||
| @@ -45,8 +45,6 @@ struct mtdblk_dev { | |||
| 45 | enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state; | 45 | enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state; |
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| 48 | static DEFINE_MUTEX(mtdblks_lock); | ||
| 49 | |||
| 50 | /* | 48 | /* |
| 51 | * Cache stuff... | 49 | * Cache stuff... |
| 52 | * | 50 | * |
| @@ -286,10 +284,8 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd) | |||
| 286 | 284 | ||
| 287 | pr_debug("mtdblock_open\n"); | 285 | pr_debug("mtdblock_open\n"); |
| 288 | 286 | ||
| 289 | mutex_lock(&mtdblks_lock); | ||
| 290 | if (mtdblk->count) { | 287 | if (mtdblk->count) { |
| 291 | mtdblk->count++; | 288 | mtdblk->count++; |
| 292 | mutex_unlock(&mtdblks_lock); | ||
| 293 | return 0; | 289 | return 0; |
| 294 | } | 290 | } |
| 295 | 291 | ||
| @@ -302,8 +298,6 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd) | |||
| 302 | mtdblk->cache_data = NULL; | 298 | mtdblk->cache_data = NULL; |
| 303 | } | 299 | } |
| 304 | 300 | ||
| 305 | mutex_unlock(&mtdblks_lock); | ||
| 306 | |||
| 307 | pr_debug("ok\n"); | 301 | pr_debug("ok\n"); |
| 308 | 302 | ||
| 309 | return 0; | 303 | return 0; |
| @@ -315,8 +309,6 @@ static void mtdblock_release(struct mtd_blktrans_dev *mbd) | |||
| 315 | 309 | ||
| 316 | pr_debug("mtdblock_release\n"); | 310 | pr_debug("mtdblock_release\n"); |
| 317 | 311 | ||
| 318 | mutex_lock(&mtdblks_lock); | ||
| 319 | |||
| 320 | mutex_lock(&mtdblk->cache_mutex); | 312 | mutex_lock(&mtdblk->cache_mutex); |
| 321 | write_cached_data(mtdblk); | 313 | write_cached_data(mtdblk); |
| 322 | mutex_unlock(&mtdblk->cache_mutex); | 314 | mutex_unlock(&mtdblk->cache_mutex); |
| @@ -331,8 +323,6 @@ static void mtdblock_release(struct mtd_blktrans_dev *mbd) | |||
| 331 | vfree(mtdblk->cache_data); | 323 | vfree(mtdblk->cache_data); |
| 332 | } | 324 | } |
| 333 | 325 | ||
| 334 | mutex_unlock(&mtdblks_lock); | ||
| 335 | |||
| 336 | pr_debug("ok\n"); | 326 | pr_debug("ok\n"); |
| 337 | } | 327 | } |
| 338 | 328 | ||
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c index eacc3aac7327..239a8c806b67 100644 --- a/drivers/mtd/mtdconcat.c +++ b/drivers/mtd/mtdconcat.c | |||
| @@ -311,7 +311,8 @@ concat_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops) | |||
| 311 | devops.len = subdev->size - to; | 311 | devops.len = subdev->size - to; |
| 312 | 312 | ||
| 313 | err = mtd_write_oob(subdev, to, &devops); | 313 | err = mtd_write_oob(subdev, to, &devops); |
| 314 | ops->retlen += devops.oobretlen; | 314 | ops->retlen += devops.retlen; |
| 315 | ops->oobretlen += devops.oobretlen; | ||
| 315 | if (err) | 316 | if (err) |
| 316 | return err; | 317 | return err; |
| 317 | 318 | ||
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 0ec4d6ea1e4b..11883bd26d9d 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include <linux/backing-dev.h> | 37 | #include <linux/backing-dev.h> |
| 38 | #include <linux/gfp.h> | 38 | #include <linux/gfp.h> |
| 39 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
| 40 | #include <linux/reboot.h> | ||
| 40 | 41 | ||
| 41 | #include <linux/mtd/mtd.h> | 42 | #include <linux/mtd/mtd.h> |
| 42 | #include <linux/mtd/partitions.h> | 43 | #include <linux/mtd/partitions.h> |
| @@ -356,6 +357,17 @@ unsigned mtd_mmap_capabilities(struct mtd_info *mtd) | |||
| 356 | EXPORT_SYMBOL_GPL(mtd_mmap_capabilities); | 357 | EXPORT_SYMBOL_GPL(mtd_mmap_capabilities); |
| 357 | #endif | 358 | #endif |
| 358 | 359 | ||
| 360 | static int mtd_reboot_notifier(struct notifier_block *n, unsigned long state, | ||
| 361 | void *cmd) | ||
| 362 | { | ||
| 363 | struct mtd_info *mtd; | ||
| 364 | |||
| 365 | mtd = container_of(n, struct mtd_info, reboot_notifier); | ||
| 366 | mtd->_reboot(mtd); | ||
| 367 | |||
| 368 | return NOTIFY_DONE; | ||
| 369 | } | ||
| 370 | |||
| 359 | /** | 371 | /** |
| 360 | * add_mtd_device - register an MTD device | 372 | * add_mtd_device - register an MTD device |
| 361 | * @mtd: pointer to new MTD device info structure | 373 | * @mtd: pointer to new MTD device info structure |
| @@ -544,6 +556,19 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types, | |||
| 544 | err = -ENODEV; | 556 | err = -ENODEV; |
| 545 | } | 557 | } |
| 546 | 558 | ||
| 559 | /* | ||
| 560 | * FIXME: some drivers unfortunately call this function more than once. | ||
| 561 | * So we have to check if we've already assigned the reboot notifier. | ||
| 562 | * | ||
| 563 | * Generally, we can make multiple calls work for most cases, but it | ||
| 564 | * does cause problems with parse_mtd_partitions() above (e.g., | ||
| 565 | * cmdlineparts will register partitions more than once). | ||
| 566 | */ | ||
| 567 | if (mtd->_reboot && !mtd->reboot_notifier.notifier_call) { | ||
| 568 | mtd->reboot_notifier.notifier_call = mtd_reboot_notifier; | ||
| 569 | register_reboot_notifier(&mtd->reboot_notifier); | ||
| 570 | } | ||
| 571 | |||
| 547 | return err; | 572 | return err; |
| 548 | } | 573 | } |
| 549 | EXPORT_SYMBOL_GPL(mtd_device_parse_register); | 574 | EXPORT_SYMBOL_GPL(mtd_device_parse_register); |
| @@ -558,6 +583,9 @@ int mtd_device_unregister(struct mtd_info *master) | |||
| 558 | { | 583 | { |
| 559 | int err; | 584 | int err; |
| 560 | 585 | ||
| 586 | if (master->_reboot) | ||
| 587 | unregister_reboot_notifier(&master->reboot_notifier); | ||
| 588 | |||
| 561 | err = del_mtd_partitions(master); | 589 | err = del_mtd_partitions(master); |
| 562 | if (err) | 590 | if (err) |
| 563 | return err; | 591 | return err; |
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 7d0150d20432..5b76a173cd95 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig | |||
| @@ -421,7 +421,7 @@ config MTD_NAND_ORION | |||
| 421 | 421 | ||
| 422 | config MTD_NAND_FSL_ELBC | 422 | config MTD_NAND_FSL_ELBC |
| 423 | tristate "NAND support for Freescale eLBC controllers" | 423 | tristate "NAND support for Freescale eLBC controllers" |
| 424 | depends on PPC_OF | 424 | depends on PPC |
| 425 | select FSL_LBC | 425 | select FSL_LBC |
| 426 | help | 426 | help |
| 427 | Various Freescale chips, including the 8313, include a NAND Flash | 427 | Various Freescale chips, including the 8313, include a NAND Flash |
| @@ -524,4 +524,9 @@ config MTD_NAND_SUNXI | |||
| 524 | help | 524 | help |
| 525 | Enables support for NAND Flash chips on Allwinner SoCs. | 525 | Enables support for NAND Flash chips on Allwinner SoCs. |
| 526 | 526 | ||
| 527 | config MTD_NAND_HISI504 | ||
| 528 | tristate "Support for NAND controller on Hisilicon SoC Hip04" | ||
| 529 | help | ||
| 530 | Enables support for NAND controller on Hisilicon SoC Hip04. | ||
| 531 | |||
| 527 | endif # MTD_NAND | 532 | endif # MTD_NAND |
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index bd38f21d2e28..582bbd05aff7 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile | |||
| @@ -51,5 +51,6 @@ obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi-nand/ | |||
| 51 | obj-$(CONFIG_MTD_NAND_XWAY) += xway_nand.o | 51 | obj-$(CONFIG_MTD_NAND_XWAY) += xway_nand.o |
| 52 | obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash/ | 52 | obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash/ |
| 53 | obj-$(CONFIG_MTD_NAND_SUNXI) += sunxi_nand.o | 53 | obj-$(CONFIG_MTD_NAND_SUNXI) += sunxi_nand.o |
| 54 | obj-$(CONFIG_MTD_NAND_HISI504) += hisi504_nand.o | ||
| 54 | 55 | ||
| 55 | nand-objs := nand_base.o nand_bbt.o nand_timings.o | 56 | nand-objs := nand_base.o nand_bbt.o nand_timings.o |
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c index f1d555cfb332..842f8fe91b56 100644 --- a/drivers/mtd/nand/ams-delta.c +++ b/drivers/mtd/nand/ams-delta.c | |||
| @@ -183,7 +183,7 @@ static int ams_delta_init(struct platform_device *pdev) | |||
| 183 | return -ENXIO; | 183 | return -ENXIO; |
| 184 | 184 | ||
| 185 | /* Allocate memory for MTD device structure and private data */ | 185 | /* Allocate memory for MTD device structure and private data */ |
| 186 | ams_delta_mtd = kmalloc(sizeof(struct mtd_info) + | 186 | ams_delta_mtd = kzalloc(sizeof(struct mtd_info) + |
| 187 | sizeof(struct nand_chip), GFP_KERNEL); | 187 | sizeof(struct nand_chip), GFP_KERNEL); |
| 188 | if (!ams_delta_mtd) { | 188 | if (!ams_delta_mtd) { |
| 189 | printk (KERN_WARNING "Unable to allocate E3 NAND MTD device structure.\n"); | 189 | printk (KERN_WARNING "Unable to allocate E3 NAND MTD device structure.\n"); |
| @@ -196,10 +196,6 @@ static int ams_delta_init(struct platform_device *pdev) | |||
| 196 | /* Get pointer to private data */ | 196 | /* Get pointer to private data */ |
| 197 | this = (struct nand_chip *) (&ams_delta_mtd[1]); | 197 | this = (struct nand_chip *) (&ams_delta_mtd[1]); |
| 198 | 198 | ||
| 199 | /* Initialize structures */ | ||
| 200 | memset(ams_delta_mtd, 0, sizeof(struct mtd_info)); | ||
| 201 | memset(this, 0, sizeof(struct nand_chip)); | ||
| 202 | |||
| 203 | /* Link the private data with the MTD structure */ | 199 | /* Link the private data with the MTD structure */ |
| 204 | ams_delta_mtd->priv = this; | 200 | ams_delta_mtd->priv = this; |
| 205 | 201 | ||
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index a345e7b2463a..d93c849b70b5 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c | |||
| @@ -63,6 +63,10 @@ module_param(on_flash_bbt, int, 0); | |||
| 63 | #include "atmel_nand_ecc.h" /* Hardware ECC registers */ | 63 | #include "atmel_nand_ecc.h" /* Hardware ECC registers */ |
| 64 | #include "atmel_nand_nfc.h" /* Nand Flash Controller definition */ | 64 | #include "atmel_nand_nfc.h" /* Nand Flash Controller definition */ |
| 65 | 65 | ||
| 66 | struct atmel_nand_caps { | ||
| 67 | bool pmecc_correct_erase_page; | ||
| 68 | }; | ||
| 69 | |||
| 66 | /* oob layout for large page size | 70 | /* oob layout for large page size |
| 67 | * bad block info is on bytes 0 and 1 | 71 | * bad block info is on bytes 0 and 1 |
| 68 | * the bytes have to be consecutives to avoid | 72 | * the bytes have to be consecutives to avoid |
| @@ -124,6 +128,7 @@ struct atmel_nand_host { | |||
| 124 | 128 | ||
| 125 | struct atmel_nfc *nfc; | 129 | struct atmel_nfc *nfc; |
| 126 | 130 | ||
| 131 | struct atmel_nand_caps *caps; | ||
| 127 | bool has_pmecc; | 132 | bool has_pmecc; |
| 128 | u8 pmecc_corr_cap; | 133 | u8 pmecc_corr_cap; |
| 129 | u16 pmecc_sector_size; | 134 | u16 pmecc_sector_size; |
| @@ -847,7 +852,11 @@ static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf, | |||
| 847 | struct atmel_nand_host *host = nand_chip->priv; | 852 | struct atmel_nand_host *host = nand_chip->priv; |
| 848 | int i, err_nbr; | 853 | int i, err_nbr; |
| 849 | uint8_t *buf_pos; | 854 | uint8_t *buf_pos; |
| 850 | int total_err = 0; | 855 | int max_bitflips = 0; |
| 856 | |||
| 857 | /* If can correct bitfilps from erased page, do the normal check */ | ||
| 858 | if (host->caps->pmecc_correct_erase_page) | ||
| 859 | goto normal_check; | ||
| 851 | 860 | ||
| 852 | for (i = 0; i < nand_chip->ecc.total; i++) | 861 | for (i = 0; i < nand_chip->ecc.total; i++) |
| 853 | if (ecc[i] != 0xff) | 862 | if (ecc[i] != 0xff) |
| @@ -874,13 +883,13 @@ normal_check: | |||
| 874 | pmecc_correct_data(mtd, buf_pos, ecc, i, | 883 | pmecc_correct_data(mtd, buf_pos, ecc, i, |
| 875 | nand_chip->ecc.bytes, err_nbr); | 884 | nand_chip->ecc.bytes, err_nbr); |
| 876 | mtd->ecc_stats.corrected += err_nbr; | 885 | mtd->ecc_stats.corrected += err_nbr; |
| 877 | total_err += err_nbr; | 886 | max_bitflips = max_t(int, max_bitflips, err_nbr); |
| 878 | } | 887 | } |
| 879 | } | 888 | } |
| 880 | pmecc_stat >>= 1; | 889 | pmecc_stat >>= 1; |
| 881 | } | 890 | } |
| 882 | 891 | ||
| 883 | return total_err; | 892 | return max_bitflips; |
| 884 | } | 893 | } |
| 885 | 894 | ||
| 886 | static void pmecc_enable(struct atmel_nand_host *host, int ecc_op) | 895 | static void pmecc_enable(struct atmel_nand_host *host, int ecc_op) |
| @@ -1474,6 +1483,8 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) | |||
| 1474 | ecc_writel(host->ecc, CR, ATMEL_ECC_RST); | 1483 | ecc_writel(host->ecc, CR, ATMEL_ECC_RST); |
| 1475 | } | 1484 | } |
| 1476 | 1485 | ||
| 1486 | static const struct of_device_id atmel_nand_dt_ids[]; | ||
| 1487 | |||
| 1477 | static int atmel_of_init_port(struct atmel_nand_host *host, | 1488 | static int atmel_of_init_port(struct atmel_nand_host *host, |
| 1478 | struct device_node *np) | 1489 | struct device_node *np) |
| 1479 | { | 1490 | { |
| @@ -1483,6 +1494,9 @@ static int atmel_of_init_port(struct atmel_nand_host *host, | |||
| 1483 | struct atmel_nand_data *board = &host->board; | 1494 | struct atmel_nand_data *board = &host->board; |
| 1484 | enum of_gpio_flags flags = 0; | 1495 | enum of_gpio_flags flags = 0; |
| 1485 | 1496 | ||
| 1497 | host->caps = (struct atmel_nand_caps *) | ||
| 1498 | of_match_device(atmel_nand_dt_ids, host->dev)->data; | ||
| 1499 | |||
| 1486 | if (of_property_read_u32(np, "atmel,nand-addr-offset", &val) == 0) { | 1500 | if (of_property_read_u32(np, "atmel,nand-addr-offset", &val) == 0) { |
| 1487 | if (val >= 32) { | 1501 | if (val >= 32) { |
| 1488 | dev_err(host->dev, "invalid addr-offset %u\n", val); | 1502 | dev_err(host->dev, "invalid addr-offset %u\n", val); |
| @@ -2288,8 +2302,17 @@ static int atmel_nand_remove(struct platform_device *pdev) | |||
| 2288 | return 0; | 2302 | return 0; |
| 2289 | } | 2303 | } |
| 2290 | 2304 | ||
| 2305 | static struct atmel_nand_caps at91rm9200_caps = { | ||
| 2306 | .pmecc_correct_erase_page = false, | ||
| 2307 | }; | ||
| 2308 | |||
| 2309 | static struct atmel_nand_caps sama5d4_caps = { | ||
| 2310 | .pmecc_correct_erase_page = true, | ||
| 2311 | }; | ||
| 2312 | |||
| 2291 | static const struct of_device_id atmel_nand_dt_ids[] = { | 2313 | static const struct of_device_id atmel_nand_dt_ids[] = { |
| 2292 | { .compatible = "atmel,at91rm9200-nand" }, | 2314 | { .compatible = "atmel,at91rm9200-nand", .data = &at91rm9200_caps }, |
| 2315 | { .compatible = "atmel,sama5d4-nand", .data = &sama5d4_caps }, | ||
| 2293 | { /* sentinel */ } | 2316 | { /* sentinel */ } |
| 2294 | }; | 2317 | }; |
| 2295 | 2318 | ||
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index b3b7ca1bafb8..f44c6061536a 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c | |||
| @@ -1041,7 +1041,7 @@ static void denali_setup_dma(struct denali_nand_info *denali, int op) | |||
| 1041 | index_addr(denali, mode | ((addr >> 16) << 8), 0x2200); | 1041 | index_addr(denali, mode | ((addr >> 16) << 8), 0x2200); |
| 1042 | 1042 | ||
| 1043 | /* 3. set memory low address bits 23:8 */ | 1043 | /* 3. set memory low address bits 23:8 */ |
| 1044 | index_addr(denali, mode | ((addr & 0xff) << 8), 0x2300); | 1044 | index_addr(denali, mode | ((addr & 0xffff) << 8), 0x2300); |
| 1045 | 1045 | ||
| 1046 | /* 4. interrupt when complete, burst len = 64 bytes */ | 1046 | /* 4. interrupt when complete, burst len = 64 bytes */ |
| 1047 | index_addr(denali, mode | 0x14000, 0x2400); | 1047 | index_addr(denali, mode | 0x14000, 0x2400); |
| @@ -1328,35 +1328,6 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, | |||
| 1328 | break; | 1328 | break; |
| 1329 | } | 1329 | } |
| 1330 | } | 1330 | } |
| 1331 | |||
| 1332 | /* stubs for ECC functions not used by the NAND core */ | ||
| 1333 | static int denali_ecc_calculate(struct mtd_info *mtd, const uint8_t *data, | ||
| 1334 | uint8_t *ecc_code) | ||
| 1335 | { | ||
| 1336 | struct denali_nand_info *denali = mtd_to_denali(mtd); | ||
| 1337 | |||
| 1338 | dev_err(denali->dev, "denali_ecc_calculate called unexpectedly\n"); | ||
| 1339 | BUG(); | ||
| 1340 | return -EIO; | ||
| 1341 | } | ||
| 1342 | |||
| 1343 | static int denali_ecc_correct(struct mtd_info *mtd, uint8_t *data, | ||
| 1344 | uint8_t *read_ecc, uint8_t *calc_ecc) | ||
| 1345 | { | ||
| 1346 | struct denali_nand_info *denali = mtd_to_denali(mtd); | ||
| 1347 | |||
| 1348 | dev_err(denali->dev, "denali_ecc_correct called unexpectedly\n"); | ||
| 1349 | BUG(); | ||
| 1350 | return -EIO; | ||
| 1351 | } | ||
| 1352 | |||
| 1353 | static void denali_ecc_hwctl(struct mtd_info *mtd, int mode) | ||
| 1354 | { | ||
| 1355 | struct denali_nand_info *denali = mtd_to_denali(mtd); | ||
| 1356 | |||
| 1357 | dev_err(denali->dev, "denali_ecc_hwctl called unexpectedly\n"); | ||
| 1358 | BUG(); | ||
| 1359 | } | ||
| 1360 | /* end NAND core entry points */ | 1331 | /* end NAND core entry points */ |
| 1361 | 1332 | ||
| 1362 | /* Initialization code to bring the device up to a known good state */ | 1333 | /* Initialization code to bring the device up to a known good state */ |
| @@ -1609,15 +1580,6 @@ int denali_init(struct denali_nand_info *denali) | |||
| 1609 | denali->totalblks = denali->mtd.size >> denali->nand.phys_erase_shift; | 1580 | denali->totalblks = denali->mtd.size >> denali->nand.phys_erase_shift; |
| 1610 | denali->blksperchip = denali->totalblks / denali->nand.numchips; | 1581 | denali->blksperchip = denali->totalblks / denali->nand.numchips; |
| 1611 | 1582 | ||
| 1612 | /* | ||
| 1613 | * These functions are required by the NAND core framework, otherwise, | ||
| 1614 | * the NAND core will assert. However, we don't need them, so we'll stub | ||
| 1615 | * them out. | ||
| 1616 | */ | ||
| 1617 | denali->nand.ecc.calculate = denali_ecc_calculate; | ||
| 1618 | denali->nand.ecc.correct = denali_ecc_correct; | ||
| 1619 | denali->nand.ecc.hwctl = denali_ecc_hwctl; | ||
| 1620 | |||
| 1621 | /* override the default read operations */ | 1583 | /* override the default read operations */ |
| 1622 | denali->nand.ecc.size = ECC_SECTOR_SIZE * denali->devnum; | 1584 | denali->nand.ecc.size = ECC_SECTOR_SIZE * denali->devnum; |
| 1623 | denali->nand.ecc.read_page = denali_read_page; | 1585 | denali->nand.ecc.read_page = denali_read_page; |
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index 4f3851a24bb2..33f3c3c54dbc 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c | |||
| @@ -1294,14 +1294,6 @@ exit_auxiliary: | |||
| 1294 | * ecc.read_page or ecc.read_page_raw function. Thus, the fact that MTD wants an | 1294 | * ecc.read_page or ecc.read_page_raw function. Thus, the fact that MTD wants an |
| 1295 | * ECC-based or raw view of the page is implicit in which function it calls | 1295 | * ECC-based or raw view of the page is implicit in which function it calls |
| 1296 | * (there is a similar pair of ECC-based/raw functions for writing). | 1296 | * (there is a similar pair of ECC-based/raw functions for writing). |
| 1297 | * | ||
| 1298 | * FIXME: The following paragraph is incorrect, now that there exist | ||
| 1299 | * ecc.read_oob_raw and ecc.write_oob_raw functions. | ||
| 1300 | * | ||
| 1301 | * Since MTD assumes the OOB is not covered by ECC, there is no pair of | ||
| 1302 | * ECC-based/raw functions for reading or or writing the OOB. The fact that the | ||
| 1303 | * caller wants an ECC-based or raw view of the page is not propagated down to | ||
| 1304 | * this driver. | ||
| 1305 | */ | 1297 | */ |
| 1306 | static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, | 1298 | static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, |
| 1307 | int page) | 1299 | int page) |
| @@ -2029,7 +2021,6 @@ static int gpmi_nand_probe(struct platform_device *pdev) | |||
| 2029 | exit_nfc_init: | 2021 | exit_nfc_init: |
| 2030 | release_resources(this); | 2022 | release_resources(this); |
| 2031 | exit_acquire_resources: | 2023 | exit_acquire_resources: |
| 2032 | dev_err(this->dev, "driver registration failed: %d\n", ret); | ||
| 2033 | 2024 | ||
| 2034 | return ret; | 2025 | return ret; |
| 2035 | } | 2026 | } |
diff --git a/drivers/mtd/nand/hisi504_nand.c b/drivers/mtd/nand/hisi504_nand.c new file mode 100644 index 000000000000..289ad3ac3e80 --- /dev/null +++ b/drivers/mtd/nand/hisi504_nand.c | |||
| @@ -0,0 +1,891 @@ | |||
| 1 | /* | ||
| 2 | * Hisilicon NAND Flash controller driver | ||
| 3 | * | ||
| 4 | * Copyright © 2012-2014 HiSilicon Technologies Co., Ltd. | ||
| 5 | * http://www.hisilicon.com | ||
| 6 | * | ||
| 7 | * Author: Zhou Wang <wangzhou.bry@gmail.com> | ||
| 8 | * The initial developer of the original code is Zhiyong Cai | ||
| 9 | * <caizhiyong@huawei.com> | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License as published by | ||
| 13 | * the Free Software Foundation; either version 2 of the License, or | ||
| 14 | * (at your option) any later version. | ||
| 15 | * | ||
| 16 | * This program is distributed in the hope that it will be useful, | ||
| 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | * GNU General Public License for more details. | ||
| 20 | */ | ||
| 21 | #include <linux/of.h> | ||
| 22 | #include <linux/of_mtd.h> | ||
| 23 | #include <linux/mtd/mtd.h> | ||
| 24 | #include <linux/sizes.h> | ||
| 25 | #include <linux/clk.h> | ||
| 26 | #include <linux/slab.h> | ||
| 27 | #include <linux/module.h> | ||
| 28 | #include <linux/delay.h> | ||
| 29 | #include <linux/interrupt.h> | ||
| 30 | #include <linux/mtd/nand.h> | ||
| 31 | #include <linux/dma-mapping.h> | ||
| 32 | #include <linux/platform_device.h> | ||
| 33 | #include <linux/mtd/partitions.h> | ||
| 34 | |||
| 35 | #define HINFC504_MAX_CHIP (4) | ||
| 36 | #define HINFC504_W_LATCH (5) | ||
| 37 | #define HINFC504_R_LATCH (7) | ||
| 38 | #define HINFC504_RW_LATCH (3) | ||
| 39 | |||
| 40 | #define HINFC504_NFC_TIMEOUT (2 * HZ) | ||
| 41 | #define HINFC504_NFC_PM_TIMEOUT (1 * HZ) | ||
| 42 | #define HINFC504_NFC_DMA_TIMEOUT (5 * HZ) | ||
| 43 | #define HINFC504_CHIP_DELAY (25) | ||
| 44 | |||
| 45 | #define HINFC504_REG_BASE_ADDRESS_LEN (0x100) | ||
| 46 | #define HINFC504_BUFFER_BASE_ADDRESS_LEN (2048 + 128) | ||
| 47 | |||
| 48 | #define HINFC504_ADDR_CYCLE_MASK 0x4 | ||
| 49 | |||
| 50 | #define HINFC504_CON 0x00 | ||
| 51 | #define HINFC504_CON_OP_MODE_NORMAL BIT(0) | ||
| 52 | #define HINFC504_CON_PAGEISZE_SHIFT (1) | ||
| 53 | #define HINFC504_CON_PAGESIZE_MASK (0x07) | ||
| 54 | #define HINFC504_CON_BUS_WIDTH BIT(4) | ||
| 55 | #define HINFC504_CON_READY_BUSY_SEL BIT(8) | ||
| 56 | #define HINFC504_CON_ECCTYPE_SHIFT (9) | ||
| 57 | #define HINFC504_CON_ECCTYPE_MASK (0x07) | ||
| 58 | |||
| 59 | #define HINFC504_PWIDTH 0x04 | ||
| 60 | #define SET_HINFC504_PWIDTH(_w_lcnt, _r_lcnt, _rw_hcnt) \ | ||
| 61 | ((_w_lcnt) | (((_r_lcnt) & 0x0F) << 4) | (((_rw_hcnt) & 0x0F) << 8)) | ||
| 62 | |||
| 63 | #define HINFC504_CMD 0x0C | ||
| 64 | #define HINFC504_ADDRL 0x10 | ||
| 65 | #define HINFC504_ADDRH 0x14 | ||
| 66 | #define HINFC504_DATA_NUM 0x18 | ||
| 67 | |||
| 68 | #define HINFC504_OP 0x1C | ||
| 69 | #define HINFC504_OP_READ_DATA_EN BIT(1) | ||
| 70 | #define HINFC504_OP_WAIT_READY_EN BIT(2) | ||
| 71 | #define HINFC504_OP_CMD2_EN BIT(3) | ||
| 72 | #define HINFC504_OP_WRITE_DATA_EN BIT(4) | ||
| 73 | #define HINFC504_OP_ADDR_EN BIT(5) | ||
| 74 | #define HINFC504_OP_CMD1_EN BIT(6) | ||
| 75 | #define HINFC504_OP_NF_CS_SHIFT (7) | ||
| 76 | #define HINFC504_OP_NF_CS_MASK (3) | ||
| 77 | #define HINFC504_OP_ADDR_CYCLE_SHIFT (9) | ||
| 78 | #define HINFC504_OP_ADDR_CYCLE_MASK (7) | ||
| 79 | |||
| 80 | #define HINFC504_STATUS 0x20 | ||
| 81 | #define HINFC504_READY BIT(0) | ||
| 82 | |||
| 83 | #define HINFC504_INTEN 0x24 | ||
| 84 | #define HINFC504_INTEN_DMA BIT(9) | ||
| 85 | #define HINFC504_INTEN_UE BIT(6) | ||
| 86 | #define HINFC504_INTEN_CE BIT(5) | ||
| 87 | |||
| 88 | #define HINFC504_INTS 0x28 | ||
| 89 | #define HINFC504_INTS_DMA BIT(9) | ||
| 90 | #define HINFC504_INTS_UE BIT(6) | ||
| 91 | #define HINFC504_INTS_CE BIT(5) | ||
| 92 | |||
| 93 | #define HINFC504_INTCLR 0x2C | ||
| 94 | #define HINFC504_INTCLR_DMA BIT(9) | ||
| 95 | #define HINFC504_INTCLR_UE BIT(6) | ||
| 96 | #define HINFC504_INTCLR_CE BIT(5) | ||
| 97 | |||
| 98 | #define HINFC504_ECC_STATUS 0x5C | ||
| 99 | #define HINFC504_ECC_16_BIT_SHIFT 12 | ||
| 100 | |||
| 101 | #define HINFC504_DMA_CTRL 0x60 | ||
| 102 | #define HINFC504_DMA_CTRL_DMA_START BIT(0) | ||
| 103 | #define HINFC504_DMA_CTRL_WE BIT(1) | ||
| 104 | #define HINFC504_DMA_CTRL_DATA_AREA_EN BIT(2) | ||
| 105 | #define HINFC504_DMA_CTRL_OOB_AREA_EN BIT(3) | ||
| 106 | #define HINFC504_DMA_CTRL_BURST4_EN BIT(4) | ||
| 107 | #define HINFC504_DMA_CTRL_BURST8_EN BIT(5) | ||
| 108 | #define HINFC504_DMA_CTRL_BURST16_EN BIT(6) | ||
| 109 | #define HINFC504_DMA_CTRL_ADDR_NUM_SHIFT (7) | ||
| 110 | #define HINFC504_DMA_CTRL_ADDR_NUM_MASK (1) | ||
| 111 | #define HINFC504_DMA_CTRL_CS_SHIFT (8) | ||
| 112 | #define HINFC504_DMA_CTRL_CS_MASK (0x03) | ||
| 113 | |||
| 114 | #define HINFC504_DMA_ADDR_DATA 0x64 | ||
| 115 | #define HINFC504_DMA_ADDR_OOB 0x68 | ||
| 116 | |||
| 117 | #define HINFC504_DMA_LEN 0x6C | ||
| 118 | #define HINFC504_DMA_LEN_OOB_SHIFT (16) | ||
| 119 | #define HINFC504_DMA_LEN_OOB_MASK (0xFFF) | ||
| 120 | |||
| 121 | #define HINFC504_DMA_PARA 0x70 | ||
| 122 | #define HINFC504_DMA_PARA_DATA_RW_EN BIT(0) | ||
| 123 | #define HINFC504_DMA_PARA_OOB_RW_EN BIT(1) | ||
| 124 | #define HINFC504_DMA_PARA_DATA_EDC_EN BIT(2) | ||
| 125 | #define HINFC504_DMA_PARA_OOB_EDC_EN BIT(3) | ||
| 126 | #define HINFC504_DMA_PARA_DATA_ECC_EN BIT(4) | ||
| 127 | #define HINFC504_DMA_PARA_OOB_ECC_EN BIT(5) | ||
| 128 | |||
| 129 | #define HINFC_VERSION 0x74 | ||
| 130 | #define HINFC504_LOG_READ_ADDR 0x7C | ||
| 131 | #define HINFC504_LOG_READ_LEN 0x80 | ||
| 132 | |||
| 133 | #define HINFC504_NANDINFO_LEN 0x10 | ||
| 134 | |||
| 135 | struct hinfc_host { | ||
| 136 | struct nand_chip chip; | ||
| 137 | struct mtd_info mtd; | ||
| 138 | struct device *dev; | ||
| 139 | void __iomem *iobase; | ||
| 140 | void __iomem *mmio; | ||
| 141 | struct completion cmd_complete; | ||
| 142 | unsigned int offset; | ||
| 143 | unsigned int command; | ||
| 144 | int chipselect; | ||
| 145 | unsigned int addr_cycle; | ||
| 146 | u32 addr_value[2]; | ||
| 147 | u32 cache_addr_value[2]; | ||
| 148 | char *buffer; | ||
| 149 | dma_addr_t dma_buffer; | ||
| 150 | dma_addr_t dma_oob; | ||
| 151 | int version; | ||
| 152 | unsigned int irq_status; /* interrupt status */ | ||
| 153 | }; | ||
| 154 | |||
| 155 | static inline unsigned int hinfc_read(struct hinfc_host *host, unsigned int reg) | ||
| 156 | { | ||
| 157 | return readl(host->iobase + reg); | ||
| 158 | } | ||
| 159 | |||
| 160 | static inline void hinfc_write(struct hinfc_host *host, unsigned int value, | ||
| 161 | unsigned int reg) | ||
| 162 | { | ||
| 163 | writel(value, host->iobase + reg); | ||
| 164 | } | ||
| 165 | |||
| 166 | static void wait_controller_finished(struct hinfc_host *host) | ||
| 167 | { | ||
| 168 | unsigned long timeout = jiffies + HINFC504_NFC_TIMEOUT; | ||
| 169 | int val; | ||
| 170 | |||
| 171 | while (time_before(jiffies, timeout)) { | ||
| 172 | val = hinfc_read(host, HINFC504_STATUS); | ||
| 173 | if (host->command == NAND_CMD_ERASE2) { | ||
| 174 | /* nfc is ready */ | ||
| 175 | while (!(val & HINFC504_READY)) { | ||
| 176 | usleep_range(500, 1000); | ||
| 177 | val = hinfc_read(host, HINFC504_STATUS); | ||
| 178 | } | ||
| 179 | return; | ||
| 180 | } | ||
| 181 | |||
| 182 | if (val & HINFC504_READY) | ||
| 183 | return; | ||
| 184 | } | ||
| 185 | |||
| 186 | /* wait cmd timeout */ | ||
| 187 | dev_err(host->dev, "Wait NAND controller exec cmd timeout.\n"); | ||
| 188 | } | ||
| 189 | |||
| 190 | static void hisi_nfc_dma_transfer(struct hinfc_host *host, int todev) | ||
| 191 | { | ||
| 192 | struct mtd_info *mtd = &host->mtd; | ||
| 193 | struct nand_chip *chip = mtd->priv; | ||
| 194 | unsigned long val; | ||
| 195 | int ret; | ||
| 196 | |||
| 197 | hinfc_write(host, host->dma_buffer, HINFC504_DMA_ADDR_DATA); | ||
| 198 | hinfc_write(host, host->dma_oob, HINFC504_DMA_ADDR_OOB); | ||
| 199 | |||
| 200 | if (chip->ecc.mode == NAND_ECC_NONE) { | ||
| 201 | hinfc_write(host, ((mtd->oobsize & HINFC504_DMA_LEN_OOB_MASK) | ||
| 202 | << HINFC504_DMA_LEN_OOB_SHIFT), HINFC504_DMA_LEN); | ||
| 203 | |||
| 204 | hinfc_write(host, HINFC504_DMA_PARA_DATA_RW_EN | ||
| 205 | | HINFC504_DMA_PARA_OOB_RW_EN, HINFC504_DMA_PARA); | ||
| 206 | } else { | ||
| 207 | if (host->command == NAND_CMD_READOOB) | ||
| 208 | hinfc_write(host, HINFC504_DMA_PARA_OOB_RW_EN | ||
| 209 | | HINFC504_DMA_PARA_OOB_EDC_EN | ||
| 210 | | HINFC504_DMA_PARA_OOB_ECC_EN, HINFC504_DMA_PARA); | ||
| 211 | else | ||
| 212 | hinfc_write(host, HINFC504_DMA_PARA_DATA_RW_EN | ||
| 213 | | HINFC504_DMA_PARA_OOB_RW_EN | ||
| 214 | | HINFC504_DMA_PARA_DATA_EDC_EN | ||
| 215 | | HINFC504_DMA_PARA_OOB_EDC_EN | ||
| 216 | | HINFC504_DMA_PARA_DATA_ECC_EN | ||
| 217 | | HINFC504_DMA_PARA_OOB_ECC_EN, HINFC504_DMA_PARA); | ||
| 218 | |||
| 219 | } | ||
| 220 | |||
| 221 | val = (HINFC504_DMA_CTRL_DMA_START | HINFC504_DMA_CTRL_BURST4_EN | ||
| 222 | | HINFC504_DMA_CTRL_BURST8_EN | HINFC504_DMA_CTRL_BURST16_EN | ||
| 223 | | HINFC504_DMA_CTRL_DATA_AREA_EN | HINFC504_DMA_CTRL_OOB_AREA_EN | ||
| 224 | | ((host->addr_cycle == 4 ? 1 : 0) | ||
| 225 | << HINFC504_DMA_CTRL_ADDR_NUM_SHIFT) | ||
| 226 | | ((host->chipselect & HINFC504_DMA_CTRL_CS_MASK) | ||
| 227 | << HINFC504_DMA_CTRL_CS_SHIFT)); | ||
| 228 | |||
| 229 | if (todev) | ||
| 230 | val |= HINFC504_DMA_CTRL_WE; | ||
| 231 | |||
| 232 | init_completion(&host->cmd_complete); | ||
| 233 | |||
| 234 | hinfc_write(host, val, HINFC504_DMA_CTRL); | ||
| 235 | ret = wait_for_completion_timeout(&host->cmd_complete, | ||
| 236 | HINFC504_NFC_DMA_TIMEOUT); | ||
| 237 | |||
| 238 | if (!ret) { | ||
| 239 | dev_err(host->dev, "DMA operation(irq) timeout!\n"); | ||
| 240 | /* sanity check */ | ||
| 241 | val = hinfc_read(host, HINFC504_DMA_CTRL); | ||
| 242 | if (!(val & HINFC504_DMA_CTRL_DMA_START)) | ||
| 243 | dev_err(host->dev, "DMA is already done but without irq ACK!\n"); | ||
| 244 | else | ||
| 245 | dev_err(host->dev, "DMA is really timeout!\n"); | ||
| 246 | } | ||
| 247 | } | ||
| 248 | |||
| 249 | static int hisi_nfc_send_cmd_pageprog(struct hinfc_host *host) | ||
| 250 | { | ||
| 251 | host->addr_value[0] &= 0xffff0000; | ||
| 252 | |||
| 253 | hinfc_write(host, host->addr_value[0], HINFC504_ADDRL); | ||
| 254 | hinfc_write(host, host->addr_value[1], HINFC504_ADDRH); | ||
| 255 | hinfc_write(host, NAND_CMD_PAGEPROG << 8 | NAND_CMD_SEQIN, | ||
| 256 | HINFC504_CMD); | ||
| 257 | |||
| 258 | hisi_nfc_dma_transfer(host, 1); | ||
| 259 | |||
| 260 | return 0; | ||
| 261 | } | ||
| 262 | |||
| 263 | static int hisi_nfc_send_cmd_readstart(struct hinfc_host *host) | ||
| 264 | { | ||
| 265 | struct mtd_info *mtd = &host->mtd; | ||
| 266 | |||
| 267 | if ((host->addr_value[0] == host->cache_addr_value[0]) && | ||
| 268 | (host->addr_value[1] == host->cache_addr_value[1])) | ||
| 269 | return 0; | ||
| 270 | |||
| 271 | host->addr_value[0] &= 0xffff0000; | ||
| 272 | |||
| 273 | hinfc_write(host, host->addr_value[0], HINFC504_ADDRL); | ||
| 274 | hinfc_write(host, host->addr_value[1], HINFC504_ADDRH); | ||
| 275 | hinfc_write(host, NAND_CMD_READSTART << 8 | NAND_CMD_READ0, | ||
| 276 | HINFC504_CMD); | ||
| 277 | |||
| 278 | hinfc_write(host, 0, HINFC504_LOG_READ_ADDR); | ||
| 279 | hinfc_write(host, mtd->writesize + mtd->oobsize, | ||
| 280 | HINFC504_LOG_READ_LEN); | ||
| 281 | |||
| 282 | hisi_nfc_dma_transfer(host, 0); | ||
| 283 | |||
| 284 | host->cache_addr_value[0] = host->addr_value[0]; | ||
| 285 | host->cache_addr_value[1] = host->addr_value[1]; | ||
| 286 | |||
| 287 | return 0; | ||
| 288 | } | ||
| 289 | |||
| 290 | static int hisi_nfc_send_cmd_erase(struct hinfc_host *host) | ||
| 291 | { | ||
| 292 | hinfc_write(host, host->addr_value[0], HINFC504_ADDRL); | ||
| 293 | hinfc_write(host, (NAND_CMD_ERASE2 << 8) | NAND_CMD_ERASE1, | ||
| 294 | HINFC504_CMD); | ||
| 295 | |||
| 296 | hinfc_write(host, HINFC504_OP_WAIT_READY_EN | ||
| 297 | | HINFC504_OP_CMD2_EN | ||
| 298 | | HINFC504_OP_CMD1_EN | ||
| 299 | | HINFC504_OP_ADDR_EN | ||
| 300 | | ((host->chipselect & HINFC504_OP_NF_CS_MASK) | ||
| 301 | << HINFC504_OP_NF_CS_SHIFT) | ||
| 302 | | ((host->addr_cycle & HINFC504_OP_ADDR_CYCLE_MASK) | ||
| 303 | << HINFC504_OP_ADDR_CYCLE_SHIFT), | ||
| 304 | HINFC504_OP); | ||
| 305 | |||
| 306 | wait_controller_finished(host); | ||
| 307 | |||
| 308 | return 0; | ||
| 309 | } | ||
| 310 | |||
| 311 | static int hisi_nfc_send_cmd_readid(struct hinfc_host *host) | ||
| 312 | { | ||
| 313 | hinfc_write(host, HINFC504_NANDINFO_LEN, HINFC504_DATA_NUM); | ||
| 314 | hinfc_write(host, NAND_CMD_READID, HINFC504_CMD); | ||
| 315 | hinfc_write(host, 0, HINFC504_ADDRL); | ||
| 316 | |||
| 317 | hinfc_write(host, HINFC504_OP_CMD1_EN | HINFC504_OP_ADDR_EN | ||
| 318 | | HINFC504_OP_READ_DATA_EN | ||
| 319 | | ((host->chipselect & HINFC504_OP_NF_CS_MASK) | ||
| 320 | << HINFC504_OP_NF_CS_SHIFT) | ||
| 321 | | 1 << HINFC504_OP_ADDR_CYCLE_SHIFT, HINFC504_OP); | ||
| 322 | |||
| 323 | wait_controller_finished(host); | ||
| 324 | |||
| 325 | return 0; | ||
| 326 | } | ||
| 327 | |||
| 328 | static int hisi_nfc_send_cmd_status(struct hinfc_host *host) | ||
| 329 | { | ||
| 330 | hinfc_write(host, HINFC504_NANDINFO_LEN, HINFC504_DATA_NUM); | ||
| 331 | hinfc_write(host, NAND_CMD_STATUS, HINFC504_CMD); | ||
| 332 | hinfc_write(host, HINFC504_OP_CMD1_EN | ||
| 333 | | HINFC504_OP_READ_DATA_EN | ||
| 334 | | ((host->chipselect & HINFC504_OP_NF_CS_MASK) | ||
| 335 | << HINFC504_OP_NF_CS_SHIFT), | ||
| 336 | HINFC504_OP); | ||
| 337 | |||
| 338 | wait_controller_finished(host); | ||
| 339 | |||
| 340 | return 0; | ||
| 341 | } | ||
| 342 | |||
| 343 | static int hisi_nfc_send_cmd_reset(struct hinfc_host *host, int chipselect) | ||
| 344 | { | ||
| 345 | hinfc_write(host, NAND_CMD_RESET, HINFC504_CMD); | ||
| 346 | |||
| 347 | hinfc_write(host, HINFC504_OP_CMD1_EN | ||
| 348 | | ((chipselect & HINFC504_OP_NF_CS_MASK) | ||
| 349 | << HINFC504_OP_NF_CS_SHIFT) | ||
| 350 | | HINFC504_OP_WAIT_READY_EN, | ||
| 351 | HINFC504_OP); | ||
| 352 | |||
| 353 | wait_controller_finished(host); | ||
| 354 | |||
| 355 | return 0; | ||
| 356 | } | ||
| 357 | |||
| 358 | static void hisi_nfc_select_chip(struct mtd_info *mtd, int chipselect) | ||
| 359 | { | ||
| 360 | struct nand_chip *chip = mtd->priv; | ||
| 361 | struct hinfc_host *host = chip->priv; | ||
| 362 | |||
| 363 | if (chipselect < 0) | ||
| 364 | return; | ||
| 365 | |||
| 366 | host->chipselect = chipselect; | ||
| 367 | } | ||
| 368 | |||
| 369 | static uint8_t hisi_nfc_read_byte(struct mtd_info *mtd) | ||
| 370 | { | ||
| 371 | struct nand_chip *chip = mtd->priv; | ||
| 372 | struct hinfc_host *host = chip->priv; | ||
| 373 | |||
| 374 | if (host->command == NAND_CMD_STATUS) | ||
| 375 | return *(uint8_t *)(host->mmio); | ||
| 376 | |||
| 377 | host->offset++; | ||
| 378 | |||
| 379 | if (host->command == NAND_CMD_READID) | ||
| 380 | return *(uint8_t *)(host->mmio + host->offset - 1); | ||
| 381 | |||
| 382 | return *(uint8_t *)(host->buffer + host->offset - 1); | ||
| 383 | } | ||
| 384 | |||
| 385 | static u16 hisi_nfc_read_word(struct mtd_info *mtd) | ||
| 386 | { | ||
| 387 | struct nand_chip *chip = mtd->priv; | ||
| 388 | struct hinfc_host *host = chip->priv; | ||
| 389 | |||
| 390 | host->offset += 2; | ||
| 391 | return *(u16 *)(host->buffer + host->offset - 2); | ||
| 392 | } | ||
| 393 | |||
| 394 | static void | ||
| 395 | hisi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | ||
| 396 | { | ||
| 397 | struct nand_chip *chip = mtd->priv; | ||
| 398 | struct hinfc_host *host = chip->priv; | ||
| 399 | |||
| 400 | memcpy(host->buffer + host->offset, buf, len); | ||
| 401 | host->offset += len; | ||
| 402 | } | ||
| 403 | |||
| 404 | static void hisi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | ||
| 405 | { | ||
| 406 | struct nand_chip *chip = mtd->priv; | ||
| 407 | struct hinfc_host *host = chip->priv; | ||
| 408 | |||
| 409 | memcpy(buf, host->buffer + host->offset, len); | ||
| 410 | host->offset += len; | ||
| 411 | } | ||
| 412 | |||
| 413 | static void set_addr(struct mtd_info *mtd, int column, int page_addr) | ||
| 414 | { | ||
| 415 | struct nand_chip *chip = mtd->priv; | ||
| 416 | struct hinfc_host *host = chip->priv; | ||
| 417 | unsigned int command = host->command; | ||
| 418 | |||
| 419 | host->addr_cycle = 0; | ||
| 420 | host->addr_value[0] = 0; | ||
| 421 | host->addr_value[1] = 0; | ||
| 422 | |||
| 423 | /* Serially input address */ | ||
| 424 | if (column != -1) { | ||
| 425 | /* Adjust columns for 16 bit buswidth */ | ||
| 426 | if (chip->options & NAND_BUSWIDTH_16 && | ||
| 427 | !nand_opcode_8bits(command)) | ||
| 428 | column >>= 1; | ||
| 429 | |||
| 430 | host->addr_value[0] = column & 0xffff; | ||
| 431 | host->addr_cycle = 2; | ||
| 432 | } | ||
| 433 | if (page_addr != -1) { | ||
| 434 | host->addr_value[0] |= (page_addr & 0xffff) | ||
| 435 | << (host->addr_cycle * 8); | ||
| 436 | host->addr_cycle += 2; | ||
| 437 | /* One more address cycle for devices > 128MiB */ | ||
| 438 | if (chip->chipsize > (128 << 20)) { | ||
| 439 | host->addr_cycle += 1; | ||
| 440 | if (host->command == NAND_CMD_ERASE1) | ||
| 441 | host->addr_value[0] |= ((page_addr >> 16) & 0xff) << 16; | ||
| 442 | else | ||
| 443 | host->addr_value[1] |= ((page_addr >> 16) & 0xff); | ||
| 444 | } | ||
| 445 | } | ||
| 446 | } | ||
| 447 | |||
| 448 | static void hisi_nfc_cmdfunc(struct mtd_info *mtd, unsigned command, int column, | ||
| 449 | int page_addr) | ||
| 450 | { | ||
| 451 | struct nand_chip *chip = mtd->priv; | ||
| 452 | struct hinfc_host *host = chip->priv; | ||
| 453 | int is_cache_invalid = 1; | ||
| 454 | unsigned int flag = 0; | ||
| 455 | |||
| 456 | host->command = command; | ||
| 457 | |||
| 458 | switch (command) { | ||
| 459 | case NAND_CMD_READ0: | ||
| 460 | case NAND_CMD_READOOB: | ||
| 461 | if (command == NAND_CMD_READ0) | ||
| 462 | host->offset = column; | ||
| 463 | else | ||
| 464 | host->offset = column + mtd->writesize; | ||
| 465 | |||
| 466 | is_cache_invalid = 0; | ||
| 467 | set_addr(mtd, column, page_addr); | ||
| 468 | hisi_nfc_send_cmd_readstart(host); | ||
| 469 | break; | ||
| 470 | |||
| 471 | case NAND_CMD_SEQIN: | ||
| 472 | host->offset = column; | ||
| 473 | set_addr(mtd, column, page_addr); | ||
| 474 | break; | ||
| 475 | |||
| 476 | case NAND_CMD_ERASE1: | ||
| 477 | set_addr(mtd, column, page_addr); | ||
| 478 | break; | ||
| 479 | |||
| 480 | case NAND_CMD_PAGEPROG: | ||
| 481 | hisi_nfc_send_cmd_pageprog(host); | ||
| 482 | break; | ||
| 483 | |||
| 484 | case NAND_CMD_ERASE2: | ||
| 485 | hisi_nfc_send_cmd_erase(host); | ||
| 486 | break; | ||
| 487 | |||
| 488 | case NAND_CMD_READID: | ||
| 489 | host->offset = column; | ||
| 490 | memset(host->mmio, 0, 0x10); | ||
| 491 | hisi_nfc_send_cmd_readid(host); | ||
| 492 | break; | ||
| 493 | |||
| 494 | case NAND_CMD_STATUS: | ||
| 495 | flag = hinfc_read(host, HINFC504_CON); | ||
| 496 | if (chip->ecc.mode == NAND_ECC_HW) | ||
| 497 | hinfc_write(host, | ||
| 498 | flag & ~(HINFC504_CON_ECCTYPE_MASK << | ||
| 499 | HINFC504_CON_ECCTYPE_SHIFT), HINFC504_CON); | ||
| 500 | |||
| 501 | host->offset = 0; | ||
| 502 | memset(host->mmio, 0, 0x10); | ||
| 503 | hisi_nfc_send_cmd_status(host); | ||
| 504 | hinfc_write(host, flag, HINFC504_CON); | ||
| 505 | break; | ||
| 506 | |||
| 507 | case NAND_CMD_RESET: | ||
| 508 | hisi_nfc_send_cmd_reset(host, host->chipselect); | ||
| 509 | break; | ||
| 510 | |||
| 511 | default: | ||
| 512 | dev_err(host->dev, "Error: unsupported cmd(cmd=%x, col=%x, page=%x)\n", | ||
| 513 | command, column, page_addr); | ||
| 514 | } | ||
| 515 | |||
| 516 | if (is_cache_invalid) { | ||
| 517 | host->cache_addr_value[0] = ~0; | ||
| 518 | host->cache_addr_value[1] = ~0; | ||
| 519 | } | ||
| 520 | } | ||
| 521 | |||
| 522 | static irqreturn_t hinfc_irq_handle(int irq, void *devid) | ||
| 523 | { | ||
| 524 | struct hinfc_host *host = devid; | ||
| 525 | unsigned int flag; | ||
| 526 | |||
| 527 | flag = hinfc_read(host, HINFC504_INTS); | ||
| 528 | /* store interrupts state */ | ||
| 529 | host->irq_status |= flag; | ||
| 530 | |||
| 531 | if (flag & HINFC504_INTS_DMA) { | ||
| 532 | hinfc_write(host, HINFC504_INTCLR_DMA, HINFC504_INTCLR); | ||
| 533 | complete(&host->cmd_complete); | ||
| 534 | } else if (flag & HINFC504_INTS_CE) { | ||
| 535 | hinfc_write(host, HINFC504_INTCLR_CE, HINFC504_INTCLR); | ||
| 536 | } else if (flag & HINFC504_INTS_UE) { | ||
| 537 | hinfc_write(host, HINFC504_INTCLR_UE, HINFC504_INTCLR); | ||
| 538 | } | ||
| 539 | |||
| 540 | return IRQ_HANDLED; | ||
| 541 | } | ||
| 542 | |||
| 543 | static int hisi_nand_read_page_hwecc(struct mtd_info *mtd, | ||
| 544 | struct nand_chip *chip, uint8_t *buf, int oob_required, int page) | ||
| 545 | { | ||
| 546 | struct hinfc_host *host = chip->priv; | ||
| 547 | int max_bitflips = 0, stat = 0, stat_max = 0, status_ecc; | ||
| 548 | int stat_1, stat_2; | ||
| 549 | |||
| 550 | chip->read_buf(mtd, buf, mtd->writesize); | ||
| 551 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); | ||
| 552 | |||
| 553 | /* errors which can not be corrected by ECC */ | ||
| 554 | if (host->irq_status & HINFC504_INTS_UE) { | ||
| 555 | mtd->ecc_stats.failed++; | ||
| 556 | } else if (host->irq_status & HINFC504_INTS_CE) { | ||
| 557 | /* TODO: need add other ECC modes! */ | ||
| 558 | switch (chip->ecc.strength) { | ||
| 559 | case 16: | ||
| 560 | status_ecc = hinfc_read(host, HINFC504_ECC_STATUS) >> | ||
| 561 | HINFC504_ECC_16_BIT_SHIFT & 0x0fff; | ||
| 562 | stat_2 = status_ecc & 0x3f; | ||
| 563 | stat_1 = status_ecc >> 6 & 0x3f; | ||
| 564 | stat = stat_1 + stat_2; | ||
| 565 | stat_max = max_t(int, stat_1, stat_2); | ||
| 566 | } | ||
| 567 | mtd->ecc_stats.corrected += stat; | ||
| 568 | max_bitflips = max_t(int, max_bitflips, stat_max); | ||
| 569 | } | ||
| 570 | host->irq_status = 0; | ||
| 571 | |||
| 572 | return max_bitflips; | ||
| 573 | } | ||
| 574 | |||
| 575 | static int hisi_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, | ||
| 576 | int page) | ||
| 577 | { | ||
| 578 | struct hinfc_host *host = chip->priv; | ||
| 579 | |||
| 580 | chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); | ||
| 581 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); | ||
| 582 | |||
| 583 | if (host->irq_status & HINFC504_INTS_UE) { | ||
| 584 | host->irq_status = 0; | ||
| 585 | return -EBADMSG; | ||
| 586 | } | ||
| 587 | |||
| 588 | host->irq_status = 0; | ||
| 589 | return 0; | ||
| 590 | } | ||
| 591 | |||
| 592 | static int hisi_nand_write_page_hwecc(struct mtd_info *mtd, | ||
| 593 | struct nand_chip *chip, const uint8_t *buf, int oob_required) | ||
| 594 | { | ||
| 595 | chip->write_buf(mtd, buf, mtd->writesize); | ||
| 596 | if (oob_required) | ||
| 597 | chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); | ||
| 598 | |||
| 599 | return 0; | ||
| 600 | } | ||
| 601 | |||
| 602 | static void hisi_nfc_host_init(struct hinfc_host *host) | ||
| 603 | { | ||
| 604 | struct nand_chip *chip = &host->chip; | ||
| 605 | unsigned int flag = 0; | ||
| 606 | |||
| 607 | host->version = hinfc_read(host, HINFC_VERSION); | ||
| 608 | host->addr_cycle = 0; | ||
| 609 | host->addr_value[0] = 0; | ||
| 610 | host->addr_value[1] = 0; | ||
| 611 | host->cache_addr_value[0] = ~0; | ||
| 612 | host->cache_addr_value[1] = ~0; | ||
| 613 | host->chipselect = 0; | ||
| 614 | |||
| 615 | /* default page size: 2K, ecc_none. need modify */ | ||
| 616 | flag = HINFC504_CON_OP_MODE_NORMAL | HINFC504_CON_READY_BUSY_SEL | ||
| 617 | | ((0x001 & HINFC504_CON_PAGESIZE_MASK) | ||
| 618 | << HINFC504_CON_PAGEISZE_SHIFT) | ||
| 619 | | ((0x0 & HINFC504_CON_ECCTYPE_MASK) | ||
| 620 | << HINFC504_CON_ECCTYPE_SHIFT) | ||
| 621 | | ((chip->options & NAND_BUSWIDTH_16) ? | ||
| 622 | HINFC504_CON_BUS_WIDTH : 0); | ||
| 623 | hinfc_write(host, flag, HINFC504_CON); | ||
| 624 | |||
| 625 | memset(host->mmio, 0xff, HINFC504_BUFFER_BASE_ADDRESS_LEN); | ||
| 626 | |||
| 627 | hinfc_write(host, SET_HINFC504_PWIDTH(HINFC504_W_LATCH, | ||
| 628 | HINFC504_R_LATCH, HINFC504_RW_LATCH), HINFC504_PWIDTH); | ||
| 629 | |||
| 630 | /* enable DMA irq */ | ||
| 631 | hinfc_write(host, HINFC504_INTEN_DMA, HINFC504_INTEN); | ||
| 632 | } | ||
| 633 | |||
| 634 | static struct nand_ecclayout nand_ecc_2K_16bits = { | ||
| 635 | .oobavail = 6, | ||
| 636 | .oobfree = { {2, 6} }, | ||
| 637 | }; | ||
| 638 | |||
| 639 | static int hisi_nfc_ecc_probe(struct hinfc_host *host) | ||
| 640 | { | ||
| 641 | unsigned int flag; | ||
| 642 | int size, strength, ecc_bits; | ||
| 643 | struct device *dev = host->dev; | ||
| 644 | struct nand_chip *chip = &host->chip; | ||
| 645 | struct mtd_info *mtd = &host->mtd; | ||
| 646 | struct device_node *np = host->dev->of_node; | ||
| 647 | |||
| 648 | size = of_get_nand_ecc_step_size(np); | ||
| 649 | strength = of_get_nand_ecc_strength(np); | ||
| 650 | if (size != 1024) { | ||
| 651 | dev_err(dev, "error ecc size: %d\n", size); | ||
| 652 | return -EINVAL; | ||
| 653 | } | ||
| 654 | |||
| 655 | if ((size == 1024) && ((strength != 8) && (strength != 16) && | ||
| 656 | (strength != 24) && (strength != 40))) { | ||
| 657 | dev_err(dev, "ecc size and strength do not match\n"); | ||
| 658 | return -EINVAL; | ||
| 659 | } | ||
| 660 | |||
| 661 | chip->ecc.size = size; | ||
| 662 | chip->ecc.strength = strength; | ||
| 663 | |||
| 664 | chip->ecc.read_page = hisi_nand_read_page_hwecc; | ||
| 665 | chip->ecc.read_oob = hisi_nand_read_oob; | ||
| 666 | chip->ecc.write_page = hisi_nand_write_page_hwecc; | ||
| 667 | |||
| 668 | switch (chip->ecc.strength) { | ||
| 669 | case 16: | ||
| 670 | ecc_bits = 6; | ||
| 671 | if (mtd->writesize == 2048) | ||
| 672 | chip->ecc.layout = &nand_ecc_2K_16bits; | ||
| 673 | |||
| 674 | /* TODO: add more page size support */ | ||
| 675 | break; | ||
| 676 | |||
| 677 | /* TODO: add more ecc strength support */ | ||
| 678 | default: | ||
| 679 | dev_err(dev, "not support strength: %d\n", chip->ecc.strength); | ||
| 680 | return -EINVAL; | ||
| 681 | } | ||
| 682 | |||
| 683 | flag = hinfc_read(host, HINFC504_CON); | ||
| 684 | /* add ecc type configure */ | ||
| 685 | flag |= ((ecc_bits & HINFC504_CON_ECCTYPE_MASK) | ||
| 686 | << HINFC504_CON_ECCTYPE_SHIFT); | ||
| 687 | hinfc_write(host, flag, HINFC504_CON); | ||
| 688 | |||
| 689 | /* enable ecc irq */ | ||
| 690 | flag = hinfc_read(host, HINFC504_INTEN) & 0xfff; | ||
| 691 | hinfc_write(host, flag | HINFC504_INTEN_UE | HINFC504_INTEN_CE, | ||
| 692 | HINFC504_INTEN); | ||
| 693 | |||
| 694 | return 0; | ||
| 695 | } | ||
| 696 | |||
| 697 | static int hisi_nfc_probe(struct platform_device *pdev) | ||
| 698 | { | ||
| 699 | int ret = 0, irq, buswidth, flag, max_chips = HINFC504_MAX_CHIP; | ||
| 700 | struct device *dev = &pdev->dev; | ||
| 701 | struct hinfc_host *host; | ||
| 702 | struct nand_chip *chip; | ||
| 703 | struct mtd_info *mtd; | ||
| 704 | struct resource *res; | ||
| 705 | struct device_node *np = dev->of_node; | ||
| 706 | struct mtd_part_parser_data ppdata; | ||
| 707 | |||
| 708 | host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL); | ||
| 709 | if (!host) | ||
| 710 | return -ENOMEM; | ||
| 711 | host->dev = dev; | ||
| 712 | |||
| 713 | platform_set_drvdata(pdev, host); | ||
| 714 | chip = &host->chip; | ||
| 715 | mtd = &host->mtd; | ||
| 716 | |||
| 717 | irq = platform_get_irq(pdev, 0); | ||
| 718 | if (irq < 0) { | ||
| 719 | dev_err(dev, "no IRQ resource defined\n"); | ||
| 720 | ret = -ENXIO; | ||
| 721 | goto err_res; | ||
| 722 | } | ||
| 723 | |||
| 724 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 725 | host->iobase = devm_ioremap_resource(dev, res); | ||
| 726 | if (IS_ERR(host->iobase)) { | ||
| 727 | ret = PTR_ERR(host->iobase); | ||
| 728 | goto err_res; | ||
| 729 | } | ||
| 730 | |||
| 731 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
| 732 | host->mmio = devm_ioremap_resource(dev, res); | ||
| 733 | if (IS_ERR(host->mmio)) { | ||
| 734 | ret = PTR_ERR(host->mmio); | ||
| 735 | dev_err(dev, "devm_ioremap_resource[1] fail\n"); | ||
| 736 | goto err_res; | ||
| 737 | } | ||
| 738 | |||
| 739 | mtd->priv = chip; | ||
| 740 | mtd->owner = THIS_MODULE; | ||
| 741 | mtd->name = "hisi_nand"; | ||
| 742 | mtd->dev.parent = &pdev->dev; | ||
| 743 | |||
| 744 | chip->priv = host; | ||
| 745 | chip->cmdfunc = hisi_nfc_cmdfunc; | ||
| 746 | chip->select_chip = hisi_nfc_select_chip; | ||
| 747 | chip->read_byte = hisi_nfc_read_byte; | ||
| 748 | chip->read_word = hisi_nfc_read_word; | ||
| 749 | chip->write_buf = hisi_nfc_write_buf; | ||
| 750 | chip->read_buf = hisi_nfc_read_buf; | ||
| 751 | chip->chip_delay = HINFC504_CHIP_DELAY; | ||
| 752 | |||
| 753 | chip->ecc.mode = of_get_nand_ecc_mode(np); | ||
| 754 | |||
| 755 | buswidth = of_get_nand_bus_width(np); | ||
| 756 | if (buswidth == 16) | ||
| 757 | chip->options |= NAND_BUSWIDTH_16; | ||
| 758 | |||
| 759 | hisi_nfc_host_init(host); | ||
| 760 | |||
| 761 | ret = devm_request_irq(dev, irq, hinfc_irq_handle, IRQF_DISABLED, | ||
| 762 | "nandc", host); | ||
| 763 | if (ret) { | ||
| 764 | dev_err(dev, "failed to request IRQ\n"); | ||
| 765 | goto err_res; | ||
| 766 | } | ||
| 767 | |||
| 768 | ret = nand_scan_ident(mtd, max_chips, NULL); | ||
| 769 | if (ret) { | ||
| 770 | ret = -ENODEV; | ||
| 771 | goto err_res; | ||
| 772 | } | ||
| 773 | |||
| 774 | host->buffer = dmam_alloc_coherent(dev, mtd->writesize + mtd->oobsize, | ||
| 775 | &host->dma_buffer, GFP_KERNEL); | ||
| 776 | if (!host->buffer) { | ||
| 777 | ret = -ENOMEM; | ||
| 778 | goto err_res; | ||
| 779 | } | ||
| 780 | |||
| 781 | host->dma_oob = host->dma_buffer + mtd->writesize; | ||
| 782 | memset(host->buffer, 0xff, mtd->writesize + mtd->oobsize); | ||
| 783 | |||
| 784 | flag = hinfc_read(host, HINFC504_CON); | ||
| 785 | flag &= ~(HINFC504_CON_PAGESIZE_MASK << HINFC504_CON_PAGEISZE_SHIFT); | ||
| 786 | switch (mtd->writesize) { | ||
| 787 | case 2048: | ||
| 788 | flag |= (0x001 << HINFC504_CON_PAGEISZE_SHIFT); break; | ||
| 789 | /* | ||
| 790 | * TODO: add more pagesize support, | ||
| 791 | * default pagesize has been set in hisi_nfc_host_init | ||
| 792 | */ | ||
| 793 | default: | ||
| 794 | dev_err(dev, "NON-2KB page size nand flash\n"); | ||
| 795 | ret = -EINVAL; | ||
| 796 | goto err_res; | ||
| 797 | } | ||
| 798 | hinfc_write(host, flag, HINFC504_CON); | ||
| 799 | |||
| 800 | if (chip->ecc.mode == NAND_ECC_HW) | ||
| 801 | hisi_nfc_ecc_probe(host); | ||
| 802 | |||
| 803 | ret = nand_scan_tail(mtd); | ||
| 804 | if (ret) { | ||
| 805 | dev_err(dev, "nand_scan_tail failed: %d\n", ret); | ||
| 806 | goto err_res; | ||
| 807 | } | ||
| 808 | |||
| 809 | ppdata.of_node = np; | ||
| 810 | ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); | ||
| 811 | if (ret) { | ||
| 812 | dev_err(dev, "Err MTD partition=%d\n", ret); | ||
| 813 | goto err_mtd; | ||
| 814 | } | ||
| 815 | |||
| 816 | return 0; | ||
| 817 | |||
| 818 | err_mtd: | ||
| 819 | nand_release(mtd); | ||
| 820 | err_res: | ||
| 821 | return ret; | ||
| 822 | } | ||
| 823 | |||
| 824 | static int hisi_nfc_remove(struct platform_device *pdev) | ||
| 825 | { | ||
| 826 | struct hinfc_host *host = platform_get_drvdata(pdev); | ||
| 827 | struct mtd_info *mtd = &host->mtd; | ||
| 828 | |||
| 829 | nand_release(mtd); | ||
| 830 | |||
| 831 | return 0; | ||
| 832 | } | ||
| 833 | |||
| 834 | #ifdef CONFIG_PM_SLEEP | ||
| 835 | static int hisi_nfc_suspend(struct device *dev) | ||
| 836 | { | ||
| 837 | struct hinfc_host *host = dev_get_drvdata(dev); | ||
| 838 | unsigned long timeout = jiffies + HINFC504_NFC_PM_TIMEOUT; | ||
| 839 | |||
| 840 | while (time_before(jiffies, timeout)) { | ||
| 841 | if (((hinfc_read(host, HINFC504_STATUS) & 0x1) == 0x0) && | ||
| 842 | (hinfc_read(host, HINFC504_DMA_CTRL) & | ||
| 843 | HINFC504_DMA_CTRL_DMA_START)) { | ||
| 844 | cond_resched(); | ||
| 845 | return 0; | ||
| 846 | } | ||
| 847 | } | ||
| 848 | |||
| 849 | dev_err(host->dev, "nand controller suspend timeout.\n"); | ||
| 850 | |||
| 851 | return -EAGAIN; | ||
| 852 | } | ||
| 853 | |||
| 854 | static int hisi_nfc_resume(struct device *dev) | ||
| 855 | { | ||
| 856 | int cs; | ||
| 857 | struct hinfc_host *host = dev_get_drvdata(dev); | ||
| 858 | struct nand_chip *chip = &host->chip; | ||
| 859 | |||
| 860 | for (cs = 0; cs < chip->numchips; cs++) | ||
| 861 | hisi_nfc_send_cmd_reset(host, cs); | ||
| 862 | hinfc_write(host, SET_HINFC504_PWIDTH(HINFC504_W_LATCH, | ||
| 863 | HINFC504_R_LATCH, HINFC504_RW_LATCH), HINFC504_PWIDTH); | ||
| 864 | |||
| 865 | return 0; | ||
| 866 | } | ||
| 867 | #endif | ||
| 868 | static SIMPLE_DEV_PM_OPS(hisi_nfc_pm_ops, hisi_nfc_suspend, hisi_nfc_resume); | ||
| 869 | |||
| 870 | static const struct of_device_id nfc_id_table[] = { | ||
| 871 | { .compatible = "hisilicon,504-nfc" }, | ||
| 872 | {} | ||
| 873 | }; | ||
| 874 | MODULE_DEVICE_TABLE(of, nfc_id_table); | ||
| 875 | |||
| 876 | static struct platform_driver hisi_nfc_driver = { | ||
| 877 | .driver = { | ||
| 878 | .name = "hisi_nand", | ||
| 879 | .of_match_table = nfc_id_table, | ||
| 880 | .pm = &hisi_nfc_pm_ops, | ||
| 881 | }, | ||
| 882 | .probe = hisi_nfc_probe, | ||
| 883 | .remove = hisi_nfc_remove, | ||
| 884 | }; | ||
| 885 | |||
| 886 | module_platform_driver(hisi_nfc_driver); | ||
| 887 | |||
| 888 | MODULE_LICENSE("GPL"); | ||
| 889 | MODULE_AUTHOR("Zhou Wang"); | ||
| 890 | MODULE_AUTHOR("Zhiyong Cai"); | ||
| 891 | MODULE_DESCRIPTION("Hisilicon Nand Flash Controller Driver"); | ||
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c index 1633ec9c5108..ebf2cce04cba 100644 --- a/drivers/mtd/nand/jz4740_nand.c +++ b/drivers/mtd/nand/jz4740_nand.c | |||
| @@ -69,7 +69,7 @@ struct jz_nand { | |||
| 69 | 69 | ||
| 70 | int selected_bank; | 70 | int selected_bank; |
| 71 | 71 | ||
| 72 | struct jz_nand_platform_data *pdata; | 72 | struct gpio_desc *busy_gpio; |
| 73 | bool is_reading; | 73 | bool is_reading; |
| 74 | }; | 74 | }; |
| 75 | 75 | ||
| @@ -131,7 +131,7 @@ static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) | |||
| 131 | static int jz_nand_dev_ready(struct mtd_info *mtd) | 131 | static int jz_nand_dev_ready(struct mtd_info *mtd) |
| 132 | { | 132 | { |
| 133 | struct jz_nand *nand = mtd_to_jz_nand(mtd); | 133 | struct jz_nand *nand = mtd_to_jz_nand(mtd); |
| 134 | return gpio_get_value_cansleep(nand->pdata->busy_gpio); | 134 | return gpiod_get_value_cansleep(nand->busy_gpio); |
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | static void jz_nand_hwctl(struct mtd_info *mtd, int mode) | 137 | static void jz_nand_hwctl(struct mtd_info *mtd, int mode) |
| @@ -423,14 +423,12 @@ static int jz_nand_probe(struct platform_device *pdev) | |||
| 423 | if (ret) | 423 | if (ret) |
| 424 | goto err_free; | 424 | goto err_free; |
| 425 | 425 | ||
| 426 | if (pdata && gpio_is_valid(pdata->busy_gpio)) { | 426 | nand->busy_gpio = devm_gpiod_get_optional(&pdev->dev, "busy", GPIOD_IN); |
| 427 | ret = gpio_request(pdata->busy_gpio, "NAND busy pin"); | 427 | if (IS_ERR(nand->busy_gpio)) { |
| 428 | if (ret) { | 428 | ret = PTR_ERR(nand->busy_gpio); |
| 429 | dev_err(&pdev->dev, | 429 | dev_err(&pdev->dev, "Failed to request busy gpio %d\n", |
| 430 | "Failed to request busy gpio %d: %d\n", | 430 | ret); |
| 431 | pdata->busy_gpio, ret); | 431 | goto err_iounmap_mmio; |
| 432 | goto err_iounmap_mmio; | ||
| 433 | } | ||
| 434 | } | 432 | } |
| 435 | 433 | ||
| 436 | mtd = &nand->mtd; | 434 | mtd = &nand->mtd; |
| @@ -454,10 +452,9 @@ static int jz_nand_probe(struct platform_device *pdev) | |||
| 454 | chip->cmd_ctrl = jz_nand_cmd_ctrl; | 452 | chip->cmd_ctrl = jz_nand_cmd_ctrl; |
| 455 | chip->select_chip = jz_nand_select_chip; | 453 | chip->select_chip = jz_nand_select_chip; |
| 456 | 454 | ||
| 457 | if (pdata && gpio_is_valid(pdata->busy_gpio)) | 455 | if (nand->busy_gpio) |
| 458 | chip->dev_ready = jz_nand_dev_ready; | 456 | chip->dev_ready = jz_nand_dev_ready; |
| 459 | 457 | ||
| 460 | nand->pdata = pdata; | ||
| 461 | platform_set_drvdata(pdev, nand); | 458 | platform_set_drvdata(pdev, nand); |
| 462 | 459 | ||
| 463 | /* We are going to autodetect NAND chips in the banks specified in the | 460 | /* We are going to autodetect NAND chips in the banks specified in the |
| @@ -496,7 +493,7 @@ static int jz_nand_probe(struct platform_device *pdev) | |||
| 496 | } | 493 | } |
| 497 | if (chipnr == 0) { | 494 | if (chipnr == 0) { |
| 498 | dev_err(&pdev->dev, "No NAND chips found\n"); | 495 | dev_err(&pdev->dev, "No NAND chips found\n"); |
| 499 | goto err_gpio_busy; | 496 | goto err_iounmap_mmio; |
| 500 | } | 497 | } |
| 501 | 498 | ||
| 502 | if (pdata && pdata->ident_callback) { | 499 | if (pdata && pdata->ident_callback) { |
| @@ -533,9 +530,6 @@ err_unclaim_banks: | |||
| 533 | nand->bank_base[bank - 1]); | 530 | nand->bank_base[bank - 1]); |
| 534 | } | 531 | } |
| 535 | writel(0, nand->base + JZ_REG_NAND_CTRL); | 532 | writel(0, nand->base + JZ_REG_NAND_CTRL); |
| 536 | err_gpio_busy: | ||
| 537 | if (pdata && gpio_is_valid(pdata->busy_gpio)) | ||
| 538 | gpio_free(pdata->busy_gpio); | ||
| 539 | err_iounmap_mmio: | 533 | err_iounmap_mmio: |
| 540 | jz_nand_iounmap_resource(nand->mem, nand->base); | 534 | jz_nand_iounmap_resource(nand->mem, nand->base); |
| 541 | err_free: | 535 | err_free: |
| @@ -546,7 +540,6 @@ err_free: | |||
| 546 | static int jz_nand_remove(struct platform_device *pdev) | 540 | static int jz_nand_remove(struct platform_device *pdev) |
| 547 | { | 541 | { |
| 548 | struct jz_nand *nand = platform_get_drvdata(pdev); | 542 | struct jz_nand *nand = platform_get_drvdata(pdev); |
| 549 | struct jz_nand_platform_data *pdata = dev_get_platdata(&pdev->dev); | ||
| 550 | size_t i; | 543 | size_t i; |
| 551 | 544 | ||
| 552 | nand_release(&nand->mtd); | 545 | nand_release(&nand->mtd); |
| @@ -562,8 +555,6 @@ static int jz_nand_remove(struct platform_device *pdev) | |||
| 562 | gpio_free(JZ_GPIO_MEM_CS0 + bank - 1); | 555 | gpio_free(JZ_GPIO_MEM_CS0 + bank - 1); |
| 563 | } | 556 | } |
| 564 | } | 557 | } |
| 565 | if (pdata && gpio_is_valid(pdata->busy_gpio)) | ||
| 566 | gpio_free(pdata->busy_gpio); | ||
| 567 | 558 | ||
| 568 | jz_nand_iounmap_resource(nand->mem, nand->base); | 559 | jz_nand_iounmap_resource(nand->mem, nand->base); |
| 569 | 560 | ||
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 41585dfb206f..df7eb4ff07d1 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
| @@ -157,7 +157,6 @@ static uint8_t nand_read_byte(struct mtd_info *mtd) | |||
| 157 | 157 | ||
| 158 | /** | 158 | /** |
| 159 | * nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip | 159 | * nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip |
| 160 | * nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip | ||
| 161 | * @mtd: MTD device structure | 160 | * @mtd: MTD device structure |
| 162 | * | 161 | * |
| 163 | * Default read function for 16bit buswidth with endianness conversion. | 162 | * Default read function for 16bit buswidth with endianness conversion. |
| @@ -1751,11 +1750,10 @@ static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1751 | static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | 1750 | static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, |
| 1752 | int page) | 1751 | int page) |
| 1753 | { | 1752 | { |
| 1754 | uint8_t *buf = chip->oob_poi; | ||
| 1755 | int length = mtd->oobsize; | 1753 | int length = mtd->oobsize; |
| 1756 | int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; | 1754 | int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; |
| 1757 | int eccsize = chip->ecc.size; | 1755 | int eccsize = chip->ecc.size; |
| 1758 | uint8_t *bufpoi = buf; | 1756 | uint8_t *bufpoi = chip->oob_poi; |
| 1759 | int i, toread, sndrnd = 0, pos; | 1757 | int i, toread, sndrnd = 0, pos; |
| 1760 | 1758 | ||
| 1761 | chip->cmdfunc(mtd, NAND_CMD_READ0, chip->ecc.size, page); | 1759 | chip->cmdfunc(mtd, NAND_CMD_READ0, chip->ecc.size, page); |
| @@ -2944,6 +2942,16 @@ static void nand_resume(struct mtd_info *mtd) | |||
| 2944 | __func__); | 2942 | __func__); |
| 2945 | } | 2943 | } |
| 2946 | 2944 | ||
| 2945 | /** | ||
| 2946 | * nand_shutdown - [MTD Interface] Finish the current NAND operation and | ||
| 2947 | * prevent further operations | ||
| 2948 | * @mtd: MTD device structure | ||
| 2949 | */ | ||
| 2950 | static void nand_shutdown(struct mtd_info *mtd) | ||
| 2951 | { | ||
| 2952 | nand_get_device(mtd, FL_SHUTDOWN); | ||
| 2953 | } | ||
| 2954 | |||
| 2947 | /* Set default functions */ | 2955 | /* Set default functions */ |
| 2948 | static void nand_set_defaults(struct nand_chip *chip, int busw) | 2956 | static void nand_set_defaults(struct nand_chip *chip, int busw) |
| 2949 | { | 2957 | { |
| @@ -4028,22 +4036,24 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
| 4028 | ecc->read_oob = nand_read_oob_std; | 4036 | ecc->read_oob = nand_read_oob_std; |
| 4029 | ecc->write_oob = nand_write_oob_std; | 4037 | ecc->write_oob = nand_write_oob_std; |
| 4030 | /* | 4038 | /* |
| 4031 | * Board driver should supply ecc.size and ecc.bytes values to | 4039 | * Board driver should supply ecc.size and ecc.strength values |
| 4032 | * select how many bits are correctable; see nand_bch_init() | 4040 | * to select how many bits are correctable. Otherwise, default |
| 4033 | * for details. Otherwise, default to 4 bits for large page | 4041 | * to 4 bits for large page devices. |
| 4034 | * devices. | ||
| 4035 | */ | 4042 | */ |
| 4036 | if (!ecc->size && (mtd->oobsize >= 64)) { | 4043 | if (!ecc->size && (mtd->oobsize >= 64)) { |
| 4037 | ecc->size = 512; | 4044 | ecc->size = 512; |
| 4038 | ecc->bytes = DIV_ROUND_UP(13 * ecc->strength, 8); | 4045 | ecc->strength = 4; |
| 4039 | } | 4046 | } |
| 4047 | |||
| 4048 | /* See nand_bch_init() for details. */ | ||
| 4049 | ecc->bytes = DIV_ROUND_UP( | ||
| 4050 | ecc->strength * fls(8 * ecc->size), 8); | ||
| 4040 | ecc->priv = nand_bch_init(mtd, ecc->size, ecc->bytes, | 4051 | ecc->priv = nand_bch_init(mtd, ecc->size, ecc->bytes, |
| 4041 | &ecc->layout); | 4052 | &ecc->layout); |
| 4042 | if (!ecc->priv) { | 4053 | if (!ecc->priv) { |
| 4043 | pr_warn("BCH ECC initialization failed!\n"); | 4054 | pr_warn("BCH ECC initialization failed!\n"); |
| 4044 | BUG(); | 4055 | BUG(); |
| 4045 | } | 4056 | } |
| 4046 | ecc->strength = ecc->bytes * 8 / fls(8 * ecc->size); | ||
| 4047 | break; | 4057 | break; |
| 4048 | 4058 | ||
| 4049 | case NAND_ECC_NONE: | 4059 | case NAND_ECC_NONE: |
| @@ -4146,6 +4156,7 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
| 4146 | mtd->_unlock = NULL; | 4156 | mtd->_unlock = NULL; |
| 4147 | mtd->_suspend = nand_suspend; | 4157 | mtd->_suspend = nand_suspend; |
| 4148 | mtd->_resume = nand_resume; | 4158 | mtd->_resume = nand_resume; |
| 4159 | mtd->_reboot = nand_shutdown; | ||
| 4149 | mtd->_block_isreserved = nand_block_isreserved; | 4160 | mtd->_block_isreserved = nand_block_isreserved; |
| 4150 | mtd->_block_isbad = nand_block_isbad; | 4161 | mtd->_block_isbad = nand_block_isbad; |
| 4151 | mtd->_block_markbad = nand_block_markbad; | 4162 | mtd->_block_markbad = nand_block_markbad; |
| @@ -4161,7 +4172,7 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
| 4161 | * properly set. | 4172 | * properly set. |
| 4162 | */ | 4173 | */ |
| 4163 | if (!mtd->bitflip_threshold) | 4174 | if (!mtd->bitflip_threshold) |
| 4164 | mtd->bitflip_threshold = mtd->ecc_strength; | 4175 | mtd->bitflip_threshold = DIV_ROUND_UP(mtd->ecc_strength * 3, 4); |
| 4165 | 4176 | ||
| 4166 | /* Check, if we should skip the bad block table scan */ | 4177 | /* Check, if we should skip the bad block table scan */ |
| 4167 | if (chip->options & NAND_SKIP_BBTSCAN) | 4178 | if (chip->options & NAND_SKIP_BBTSCAN) |
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index ab5bbf567439..f2324271b94e 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c | |||
| @@ -245,7 +245,6 @@ MODULE_PARM_DESC(bch, "Enable BCH ecc and set how many bits should " | |||
| 245 | #define STATE_DATAOUT 0x00001000 /* waiting for page data output */ | 245 | #define STATE_DATAOUT 0x00001000 /* waiting for page data output */ |
| 246 | #define STATE_DATAOUT_ID 0x00002000 /* waiting for ID bytes output */ | 246 | #define STATE_DATAOUT_ID 0x00002000 /* waiting for ID bytes output */ |
| 247 | #define STATE_DATAOUT_STATUS 0x00003000 /* waiting for status output */ | 247 | #define STATE_DATAOUT_STATUS 0x00003000 /* waiting for status output */ |
| 248 | #define STATE_DATAOUT_STATUS_M 0x00004000 /* waiting for multi-plane status output */ | ||
| 249 | #define STATE_DATAOUT_MASK 0x00007000 /* data output states mask */ | 248 | #define STATE_DATAOUT_MASK 0x00007000 /* data output states mask */ |
| 250 | 249 | ||
| 251 | /* Previous operation is done, ready to accept new requests */ | 250 | /* Previous operation is done, ready to accept new requests */ |
| @@ -269,7 +268,6 @@ MODULE_PARM_DESC(bch, "Enable BCH ecc and set how many bits should " | |||
| 269 | #define OPT_ANY 0xFFFFFFFF /* any chip supports this operation */ | 268 | #define OPT_ANY 0xFFFFFFFF /* any chip supports this operation */ |
| 270 | #define OPT_PAGE512 0x00000002 /* 512-byte page chips */ | 269 | #define OPT_PAGE512 0x00000002 /* 512-byte page chips */ |
| 271 | #define OPT_PAGE2048 0x00000008 /* 2048-byte page chips */ | 270 | #define OPT_PAGE2048 0x00000008 /* 2048-byte page chips */ |
| 272 | #define OPT_SMARTMEDIA 0x00000010 /* SmartMedia technology chips */ | ||
| 273 | #define OPT_PAGE512_8BIT 0x00000040 /* 512-byte page chips with 8-bit bus width */ | 271 | #define OPT_PAGE512_8BIT 0x00000040 /* 512-byte page chips with 8-bit bus width */ |
| 274 | #define OPT_PAGE4096 0x00000080 /* 4096-byte page chips */ | 272 | #define OPT_PAGE4096 0x00000080 /* 4096-byte page chips */ |
| 275 | #define OPT_LARGEPAGE (OPT_PAGE2048 | OPT_PAGE4096) /* 2048 & 4096-byte page chips */ | 273 | #define OPT_LARGEPAGE (OPT_PAGE2048 | OPT_PAGE4096) /* 2048 & 4096-byte page chips */ |
| @@ -1096,8 +1094,6 @@ static char *get_state_name(uint32_t state) | |||
| 1096 | return "STATE_DATAOUT_ID"; | 1094 | return "STATE_DATAOUT_ID"; |
| 1097 | case STATE_DATAOUT_STATUS: | 1095 | case STATE_DATAOUT_STATUS: |
| 1098 | return "STATE_DATAOUT_STATUS"; | 1096 | return "STATE_DATAOUT_STATUS"; |
| 1099 | case STATE_DATAOUT_STATUS_M: | ||
| 1100 | return "STATE_DATAOUT_STATUS_M"; | ||
| 1101 | case STATE_READY: | 1097 | case STATE_READY: |
| 1102 | return "STATE_READY"; | 1098 | return "STATE_READY"; |
| 1103 | case STATE_UNKNOWN: | 1099 | case STATE_UNKNOWN: |
| @@ -1865,7 +1861,6 @@ static void switch_state(struct nandsim *ns) | |||
| 1865 | break; | 1861 | break; |
| 1866 | 1862 | ||
| 1867 | case STATE_DATAOUT_STATUS: | 1863 | case STATE_DATAOUT_STATUS: |
| 1868 | case STATE_DATAOUT_STATUS_M: | ||
| 1869 | ns->regs.count = ns->regs.num = 0; | 1864 | ns->regs.count = ns->regs.num = 0; |
| 1870 | break; | 1865 | break; |
| 1871 | 1866 | ||
| @@ -2005,7 +2000,6 @@ static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte) | |||
| 2005 | } | 2000 | } |
| 2006 | 2001 | ||
| 2007 | if (NS_STATE(ns->state) == STATE_DATAOUT_STATUS | 2002 | if (NS_STATE(ns->state) == STATE_DATAOUT_STATUS |
| 2008 | || NS_STATE(ns->state) == STATE_DATAOUT_STATUS_M | ||
| 2009 | || NS_STATE(ns->state) == STATE_DATAOUT) { | 2003 | || NS_STATE(ns->state) == STATE_DATAOUT) { |
| 2010 | int row = ns->regs.row; | 2004 | int row = ns->regs.row; |
| 2011 | 2005 | ||
| @@ -2343,6 +2337,7 @@ static int __init ns_init_module(void) | |||
| 2343 | } | 2337 | } |
| 2344 | chip->ecc.mode = NAND_ECC_SOFT_BCH; | 2338 | chip->ecc.mode = NAND_ECC_SOFT_BCH; |
| 2345 | chip->ecc.size = 512; | 2339 | chip->ecc.size = 512; |
| 2340 | chip->ecc.strength = bch; | ||
| 2346 | chip->ecc.bytes = eccbytes; | 2341 | chip->ecc.bytes = eccbytes; |
| 2347 | NS_INFO("using %u-bit/%u bytes BCH ECC\n", bch, chip->ecc.size); | 2342 | NS_INFO("using %u-bit/%u bytes BCH ECC\n", bch, chip->ecc.size); |
| 2348 | } | 2343 | } |
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 63f858e6bf39..60fa89939c24 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c | |||
| @@ -1048,10 +1048,9 @@ static int omap_dev_ready(struct mtd_info *mtd) | |||
| 1048 | * @mtd: MTD device structure | 1048 | * @mtd: MTD device structure |
| 1049 | * @mode: Read/Write mode | 1049 | * @mode: Read/Write mode |
| 1050 | * | 1050 | * |
| 1051 | * When using BCH, sector size is hardcoded to 512 bytes. | 1051 | * When using BCH with SW correction (i.e. no ELM), sector size is set |
| 1052 | * Using wrapping mode 6 both for reading and writing if ELM module not uses | 1052 | * to 512 bytes and we use BCH_WRAPMODE_6 wrapping mode |
| 1053 | * for error correction. | 1053 | * for both reading and writing with: |
| 1054 | * On writing, | ||
| 1055 | * eccsize0 = 0 (no additional protected byte in spare area) | 1054 | * eccsize0 = 0 (no additional protected byte in spare area) |
| 1056 | * eccsize1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area) | 1055 | * eccsize1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area) |
| 1057 | */ | 1056 | */ |
| @@ -1071,15 +1070,9 @@ static void __maybe_unused omap_enable_hwecc_bch(struct mtd_info *mtd, int mode) | |||
| 1071 | case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW: | 1070 | case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW: |
| 1072 | bch_type = 0; | 1071 | bch_type = 0; |
| 1073 | nsectors = 1; | 1072 | nsectors = 1; |
| 1074 | if (mode == NAND_ECC_READ) { | 1073 | wr_mode = BCH_WRAPMODE_6; |
| 1075 | wr_mode = BCH_WRAPMODE_6; | 1074 | ecc_size0 = BCH_ECC_SIZE0; |
| 1076 | ecc_size0 = BCH_ECC_SIZE0; | 1075 | ecc_size1 = BCH_ECC_SIZE1; |
| 1077 | ecc_size1 = BCH_ECC_SIZE1; | ||
| 1078 | } else { | ||
| 1079 | wr_mode = BCH_WRAPMODE_6; | ||
| 1080 | ecc_size0 = BCH_ECC_SIZE0; | ||
| 1081 | ecc_size1 = BCH_ECC_SIZE1; | ||
| 1082 | } | ||
| 1083 | break; | 1076 | break; |
| 1084 | case OMAP_ECC_BCH4_CODE_HW: | 1077 | case OMAP_ECC_BCH4_CODE_HW: |
| 1085 | bch_type = 0; | 1078 | bch_type = 0; |
| @@ -1097,15 +1090,9 @@ static void __maybe_unused omap_enable_hwecc_bch(struct mtd_info *mtd, int mode) | |||
| 1097 | case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: | 1090 | case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: |
| 1098 | bch_type = 1; | 1091 | bch_type = 1; |
| 1099 | nsectors = 1; | 1092 | nsectors = 1; |
| 1100 | if (mode == NAND_ECC_READ) { | 1093 | wr_mode = BCH_WRAPMODE_6; |
| 1101 | wr_mode = BCH_WRAPMODE_6; | 1094 | ecc_size0 = BCH_ECC_SIZE0; |
| 1102 | ecc_size0 = BCH_ECC_SIZE0; | 1095 | ecc_size1 = BCH_ECC_SIZE1; |
| 1103 | ecc_size1 = BCH_ECC_SIZE1; | ||
| 1104 | } else { | ||
| 1105 | wr_mode = BCH_WRAPMODE_6; | ||
| 1106 | ecc_size0 = BCH_ECC_SIZE0; | ||
| 1107 | ecc_size1 = BCH_ECC_SIZE1; | ||
| 1108 | } | ||
| 1109 | break; | 1096 | break; |
| 1110 | case OMAP_ECC_BCH8_CODE_HW: | 1097 | case OMAP_ECC_BCH8_CODE_HW: |
| 1111 | bch_type = 1; | 1098 | bch_type = 1; |
diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index ccaa8e283388..6f93b2990d25 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c | |||
| @@ -1110,8 +1110,6 @@ static int sunxi_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc, | |||
| 1110 | 1110 | ||
| 1111 | switch (ecc->mode) { | 1111 | switch (ecc->mode) { |
| 1112 | case NAND_ECC_SOFT_BCH: | 1112 | case NAND_ECC_SOFT_BCH: |
| 1113 | ecc->bytes = DIV_ROUND_UP(ecc->strength * fls(8 * ecc->size), | ||
| 1114 | 8); | ||
| 1115 | break; | 1113 | break; |
| 1116 | case NAND_ECC_HW: | 1114 | case NAND_ECC_HW: |
| 1117 | ret = sunxi_nand_hw_ecc_ctrl_init(mtd, ecc, np); | 1115 | ret = sunxi_nand_hw_ecc_ctrl_init(mtd, ecc, np); |
diff --git a/drivers/mtd/nftlmount.c b/drivers/mtd/nftlmount.c index 51b9d6af307f..a5dfbfbebfca 100644 --- a/drivers/mtd/nftlmount.c +++ b/drivers/mtd/nftlmount.c | |||
| @@ -89,9 +89,10 @@ static int find_boot_record(struct NFTLrecord *nftl) | |||
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | /* To be safer with BIOS, also use erase mark as discriminant */ | 91 | /* To be safer with BIOS, also use erase mark as discriminant */ |
| 92 | if ((ret = nftl_read_oob(mtd, block * nftl->EraseSize + | 92 | ret = nftl_read_oob(mtd, block * nftl->EraseSize + |
| 93 | SECTORSIZE + 8, 8, &retlen, | 93 | SECTORSIZE + 8, 8, &retlen, |
| 94 | (char *)&h1) < 0)) { | 94 | (char *)&h1); |
| 95 | if (ret < 0) { | ||
| 95 | printk(KERN_WARNING "ANAND header found at 0x%x in mtd%d, but OOB data read failed (err %d)\n", | 96 | printk(KERN_WARNING "ANAND header found at 0x%x in mtd%d, but OOB data read failed (err %d)\n", |
| 96 | block * nftl->EraseSize, nftl->mbd.mtd->index, ret); | 97 | block * nftl->EraseSize, nftl->mbd.mtd->index, ret); |
| 97 | continue; | 98 | continue; |
| @@ -109,8 +110,9 @@ static int find_boot_record(struct NFTLrecord *nftl) | |||
| 109 | } | 110 | } |
| 110 | 111 | ||
| 111 | /* Finally reread to check ECC */ | 112 | /* Finally reread to check ECC */ |
| 112 | if ((ret = mtd->read(mtd, block * nftl->EraseSize, SECTORSIZE, | 113 | ret = mtd->read(mtd, block * nftl->EraseSize, SECTORSIZE, |
| 113 | &retlen, buf) < 0)) { | 114 | &retlen, buf); |
| 115 | if (ret < 0) { | ||
| 114 | printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but ECC read failed (err %d)\n", | 116 | printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but ECC read failed (err %d)\n", |
| 115 | block * nftl->EraseSize, nftl->mbd.mtd->index, ret); | 117 | block * nftl->EraseSize, nftl->mbd.mtd->index, ret); |
| 116 | continue; | 118 | continue; |
| @@ -228,9 +230,11 @@ device is already correct. | |||
| 228 | The new DiskOnChip driver already scanned the bad block table. Just query it. | 230 | The new DiskOnChip driver already scanned the bad block table. Just query it. |
| 229 | if ((i & (SECTORSIZE - 1)) == 0) { | 231 | if ((i & (SECTORSIZE - 1)) == 0) { |
| 230 | /* read one sector for every SECTORSIZE of blocks */ | 232 | /* read one sector for every SECTORSIZE of blocks */ |
| 231 | if ((ret = mtd->read(nftl->mbd.mtd, block * nftl->EraseSize + | 233 | ret = mtd->read(nftl->mbd.mtd, |
| 232 | i + SECTORSIZE, SECTORSIZE, &retlen, | 234 | block * nftl->EraseSize + i + |
| 233 | buf)) < 0) { | 235 | SECTORSIZE, SECTORSIZE, |
| 236 | &retlen, buf); | ||
| 237 | if (ret < 0) { | ||
| 234 | printk(KERN_NOTICE "Read of bad sector table failed (err %d)\n", | 238 | printk(KERN_NOTICE "Read of bad sector table failed (err %d)\n", |
| 235 | ret); | 239 | ret); |
| 236 | kfree(nftl->ReplUnitTable); | 240 | kfree(nftl->ReplUnitTable); |
diff --git a/drivers/mtd/spi-nor/fsl-quadspi.c b/drivers/mtd/spi-nor/fsl-quadspi.c index 39763b94f67d..1c7308c2c77d 100644 --- a/drivers/mtd/spi-nor/fsl-quadspi.c +++ b/drivers/mtd/spi-nor/fsl-quadspi.c | |||
| @@ -57,7 +57,9 @@ | |||
| 57 | 57 | ||
| 58 | #define QUADSPI_BUF3CR 0x1c | 58 | #define QUADSPI_BUF3CR 0x1c |
| 59 | #define QUADSPI_BUF3CR_ALLMST_SHIFT 31 | 59 | #define QUADSPI_BUF3CR_ALLMST_SHIFT 31 |
| 60 | #define QUADSPI_BUF3CR_ALLMST (1 << QUADSPI_BUF3CR_ALLMST_SHIFT) | 60 | #define QUADSPI_BUF3CR_ALLMST_MASK (1 << QUADSPI_BUF3CR_ALLMST_SHIFT) |
| 61 | #define QUADSPI_BUF3CR_ADATSZ_SHIFT 8 | ||
| 62 | #define QUADSPI_BUF3CR_ADATSZ_MASK (0xFF << QUADSPI_BUF3CR_ADATSZ_SHIFT) | ||
| 61 | 63 | ||
| 62 | #define QUADSPI_BFGENCR 0x20 | 64 | #define QUADSPI_BFGENCR 0x20 |
| 63 | #define QUADSPI_BFGENCR_PAR_EN_SHIFT 16 | 65 | #define QUADSPI_BFGENCR_PAR_EN_SHIFT 16 |
| @@ -198,18 +200,21 @@ struct fsl_qspi_devtype_data { | |||
| 198 | enum fsl_qspi_devtype devtype; | 200 | enum fsl_qspi_devtype devtype; |
| 199 | int rxfifo; | 201 | int rxfifo; |
| 200 | int txfifo; | 202 | int txfifo; |
| 203 | int ahb_buf_size; | ||
| 201 | }; | 204 | }; |
| 202 | 205 | ||
| 203 | static struct fsl_qspi_devtype_data vybrid_data = { | 206 | static struct fsl_qspi_devtype_data vybrid_data = { |
| 204 | .devtype = FSL_QUADSPI_VYBRID, | 207 | .devtype = FSL_QUADSPI_VYBRID, |
| 205 | .rxfifo = 128, | 208 | .rxfifo = 128, |
| 206 | .txfifo = 64 | 209 | .txfifo = 64, |
| 210 | .ahb_buf_size = 1024 | ||
| 207 | }; | 211 | }; |
| 208 | 212 | ||
| 209 | static struct fsl_qspi_devtype_data imx6sx_data = { | 213 | static struct fsl_qspi_devtype_data imx6sx_data = { |
| 210 | .devtype = FSL_QUADSPI_IMX6SX, | 214 | .devtype = FSL_QUADSPI_IMX6SX, |
| 211 | .rxfifo = 128, | 215 | .rxfifo = 128, |
| 212 | .txfifo = 512 | 216 | .txfifo = 512, |
| 217 | .ahb_buf_size = 1024 | ||
| 213 | }; | 218 | }; |
| 214 | 219 | ||
| 215 | #define FSL_QSPI_MAX_CHIP 4 | 220 | #define FSL_QSPI_MAX_CHIP 4 |
| @@ -227,6 +232,7 @@ struct fsl_qspi { | |||
| 227 | u32 nor_num; | 232 | u32 nor_num; |
| 228 | u32 clk_rate; | 233 | u32 clk_rate; |
| 229 | unsigned int chip_base_addr; /* We may support two chips. */ | 234 | unsigned int chip_base_addr; /* We may support two chips. */ |
| 235 | bool has_second_chip; | ||
| 230 | }; | 236 | }; |
| 231 | 237 | ||
| 232 | static inline int is_vybrid_qspi(struct fsl_qspi *q) | 238 | static inline int is_vybrid_qspi(struct fsl_qspi *q) |
| @@ -583,7 +589,12 @@ static void fsl_qspi_init_abh_read(struct fsl_qspi *q) | |||
| 583 | writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF0CR); | 589 | writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF0CR); |
| 584 | writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF1CR); | 590 | writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF1CR); |
| 585 | writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF2CR); | 591 | writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF2CR); |
| 586 | writel(QUADSPI_BUF3CR_ALLMST, base + QUADSPI_BUF3CR); | 592 | /* |
| 593 | * Set ADATSZ with the maximum AHB buffer size to improve the | ||
| 594 | * read performance. | ||
| 595 | */ | ||
| 596 | writel(QUADSPI_BUF3CR_ALLMST_MASK | ((q->devtype_data->ahb_buf_size / 8) | ||
| 597 | << QUADSPI_BUF3CR_ADATSZ_SHIFT), base + QUADSPI_BUF3CR); | ||
| 587 | 598 | ||
| 588 | /* We only use the buffer3 */ | 599 | /* We only use the buffer3 */ |
| 589 | writel(0, base + QUADSPI_BUF0IND); | 600 | writel(0, base + QUADSPI_BUF0IND); |
| @@ -783,7 +794,6 @@ static int fsl_qspi_probe(struct platform_device *pdev) | |||
| 783 | struct spi_nor *nor; | 794 | struct spi_nor *nor; |
| 784 | struct mtd_info *mtd; | 795 | struct mtd_info *mtd; |
| 785 | int ret, i = 0; | 796 | int ret, i = 0; |
| 786 | bool has_second_chip = false; | ||
| 787 | const struct of_device_id *of_id = | 797 | const struct of_device_id *of_id = |
| 788 | of_match_device(fsl_qspi_dt_ids, &pdev->dev); | 798 | of_match_device(fsl_qspi_dt_ids, &pdev->dev); |
| 789 | 799 | ||
| @@ -798,37 +808,30 @@ static int fsl_qspi_probe(struct platform_device *pdev) | |||
| 798 | /* find the resources */ | 808 | /* find the resources */ |
| 799 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "QuadSPI"); | 809 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "QuadSPI"); |
| 800 | q->iobase = devm_ioremap_resource(dev, res); | 810 | q->iobase = devm_ioremap_resource(dev, res); |
| 801 | if (IS_ERR(q->iobase)) { | 811 | if (IS_ERR(q->iobase)) |
| 802 | ret = PTR_ERR(q->iobase); | 812 | return PTR_ERR(q->iobase); |
| 803 | goto map_failed; | ||
| 804 | } | ||
| 805 | 813 | ||
| 806 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | 814 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, |
| 807 | "QuadSPI-memory"); | 815 | "QuadSPI-memory"); |
| 808 | q->ahb_base = devm_ioremap_resource(dev, res); | 816 | q->ahb_base = devm_ioremap_resource(dev, res); |
| 809 | if (IS_ERR(q->ahb_base)) { | 817 | if (IS_ERR(q->ahb_base)) |
| 810 | ret = PTR_ERR(q->ahb_base); | 818 | return PTR_ERR(q->ahb_base); |
| 811 | goto map_failed; | 819 | |
| 812 | } | ||
| 813 | q->memmap_phy = res->start; | 820 | q->memmap_phy = res->start; |
| 814 | 821 | ||
| 815 | /* find the clocks */ | 822 | /* find the clocks */ |
| 816 | q->clk_en = devm_clk_get(dev, "qspi_en"); | 823 | q->clk_en = devm_clk_get(dev, "qspi_en"); |
| 817 | if (IS_ERR(q->clk_en)) { | 824 | if (IS_ERR(q->clk_en)) |
| 818 | ret = PTR_ERR(q->clk_en); | 825 | return PTR_ERR(q->clk_en); |
| 819 | goto map_failed; | ||
| 820 | } | ||
| 821 | 826 | ||
| 822 | q->clk = devm_clk_get(dev, "qspi"); | 827 | q->clk = devm_clk_get(dev, "qspi"); |
| 823 | if (IS_ERR(q->clk)) { | 828 | if (IS_ERR(q->clk)) |
| 824 | ret = PTR_ERR(q->clk); | 829 | return PTR_ERR(q->clk); |
| 825 | goto map_failed; | ||
| 826 | } | ||
| 827 | 830 | ||
| 828 | ret = clk_prepare_enable(q->clk_en); | 831 | ret = clk_prepare_enable(q->clk_en); |
| 829 | if (ret) { | 832 | if (ret) { |
| 830 | dev_err(dev, "can not enable the qspi_en clock\n"); | 833 | dev_err(dev, "can not enable the qspi_en clock\n"); |
| 831 | goto map_failed; | 834 | return ret; |
| 832 | } | 835 | } |
| 833 | 836 | ||
| 834 | ret = clk_prepare_enable(q->clk); | 837 | ret = clk_prepare_enable(q->clk); |
| @@ -860,14 +863,14 @@ static int fsl_qspi_probe(struct platform_device *pdev) | |||
| 860 | goto irq_failed; | 863 | goto irq_failed; |
| 861 | 864 | ||
| 862 | if (of_get_property(np, "fsl,qspi-has-second-chip", NULL)) | 865 | if (of_get_property(np, "fsl,qspi-has-second-chip", NULL)) |
| 863 | has_second_chip = true; | 866 | q->has_second_chip = true; |
| 864 | 867 | ||
| 865 | /* iterate the subnodes. */ | 868 | /* iterate the subnodes. */ |
| 866 | for_each_available_child_of_node(dev->of_node, np) { | 869 | for_each_available_child_of_node(dev->of_node, np) { |
| 867 | char modalias[40]; | 870 | char modalias[40]; |
| 868 | 871 | ||
| 869 | /* skip the holes */ | 872 | /* skip the holes */ |
| 870 | if (!has_second_chip) | 873 | if (!q->has_second_chip) |
| 871 | i *= 2; | 874 | i *= 2; |
| 872 | 875 | ||
| 873 | nor = &q->nor[i]; | 876 | nor = &q->nor[i]; |
| @@ -890,24 +893,24 @@ static int fsl_qspi_probe(struct platform_device *pdev) | |||
| 890 | 893 | ||
| 891 | ret = of_modalias_node(np, modalias, sizeof(modalias)); | 894 | ret = of_modalias_node(np, modalias, sizeof(modalias)); |
| 892 | if (ret < 0) | 895 | if (ret < 0) |
| 893 | goto map_failed; | 896 | goto irq_failed; |
| 894 | 897 | ||
| 895 | ret = of_property_read_u32(np, "spi-max-frequency", | 898 | ret = of_property_read_u32(np, "spi-max-frequency", |
| 896 | &q->clk_rate); | 899 | &q->clk_rate); |
| 897 | if (ret < 0) | 900 | if (ret < 0) |
| 898 | goto map_failed; | 901 | goto irq_failed; |
| 899 | 902 | ||
| 900 | /* set the chip address for READID */ | 903 | /* set the chip address for READID */ |
| 901 | fsl_qspi_set_base_addr(q, nor); | 904 | fsl_qspi_set_base_addr(q, nor); |
| 902 | 905 | ||
| 903 | ret = spi_nor_scan(nor, modalias, SPI_NOR_QUAD); | 906 | ret = spi_nor_scan(nor, modalias, SPI_NOR_QUAD); |
| 904 | if (ret) | 907 | if (ret) |
| 905 | goto map_failed; | 908 | goto irq_failed; |
| 906 | 909 | ||
| 907 | ppdata.of_node = np; | 910 | ppdata.of_node = np; |
| 908 | ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); | 911 | ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); |
| 909 | if (ret) | 912 | if (ret) |
| 910 | goto map_failed; | 913 | goto irq_failed; |
| 911 | 914 | ||
| 912 | /* Set the correct NOR size now. */ | 915 | /* Set the correct NOR size now. */ |
| 913 | if (q->nor_size == 0) { | 916 | if (q->nor_size == 0) { |
| @@ -939,19 +942,19 @@ static int fsl_qspi_probe(struct platform_device *pdev) | |||
| 939 | 942 | ||
| 940 | clk_disable(q->clk); | 943 | clk_disable(q->clk); |
| 941 | clk_disable(q->clk_en); | 944 | clk_disable(q->clk_en); |
| 942 | dev_info(dev, "QuadSPI SPI NOR flash driver\n"); | ||
| 943 | return 0; | 945 | return 0; |
| 944 | 946 | ||
| 945 | last_init_failed: | 947 | last_init_failed: |
| 946 | for (i = 0; i < q->nor_num; i++) | 948 | for (i = 0; i < q->nor_num; i++) { |
| 949 | /* skip the holes */ | ||
| 950 | if (!q->has_second_chip) | ||
| 951 | i *= 2; | ||
| 947 | mtd_device_unregister(&q->mtd[i]); | 952 | mtd_device_unregister(&q->mtd[i]); |
| 948 | 953 | } | |
| 949 | irq_failed: | 954 | irq_failed: |
| 950 | clk_disable_unprepare(q->clk); | 955 | clk_disable_unprepare(q->clk); |
| 951 | clk_failed: | 956 | clk_failed: |
| 952 | clk_disable_unprepare(q->clk_en); | 957 | clk_disable_unprepare(q->clk_en); |
| 953 | map_failed: | ||
| 954 | dev_err(dev, "Freescale QuadSPI probe failed\n"); | ||
| 955 | return ret; | 958 | return ret; |
| 956 | } | 959 | } |
| 957 | 960 | ||
| @@ -960,8 +963,12 @@ static int fsl_qspi_remove(struct platform_device *pdev) | |||
| 960 | struct fsl_qspi *q = platform_get_drvdata(pdev); | 963 | struct fsl_qspi *q = platform_get_drvdata(pdev); |
| 961 | int i; | 964 | int i; |
| 962 | 965 | ||
| 963 | for (i = 0; i < q->nor_num; i++) | 966 | for (i = 0; i < q->nor_num; i++) { |
| 967 | /* skip the holes */ | ||
| 968 | if (!q->has_second_chip) | ||
| 969 | i *= 2; | ||
| 964 | mtd_device_unregister(&q->mtd[i]); | 970 | mtd_device_unregister(&q->mtd[i]); |
| 971 | } | ||
| 965 | 972 | ||
| 966 | /* disable the hardware */ | 973 | /* disable the hardware */ |
| 967 | writel(QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR); | 974 | writel(QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR); |
| @@ -972,6 +979,22 @@ static int fsl_qspi_remove(struct platform_device *pdev) | |||
| 972 | return 0; | 979 | return 0; |
| 973 | } | 980 | } |
| 974 | 981 | ||
| 982 | static int fsl_qspi_suspend(struct platform_device *pdev, pm_message_t state) | ||
| 983 | { | ||
| 984 | return 0; | ||
| 985 | } | ||
| 986 | |||
| 987 | static int fsl_qspi_resume(struct platform_device *pdev) | ||
| 988 | { | ||
| 989 | struct fsl_qspi *q = platform_get_drvdata(pdev); | ||
| 990 | |||
| 991 | fsl_qspi_nor_setup(q); | ||
| 992 | fsl_qspi_set_map_addr(q); | ||
| 993 | fsl_qspi_nor_setup_last(q); | ||
| 994 | |||
| 995 | return 0; | ||
| 996 | } | ||
| 997 | |||
| 975 | static struct platform_driver fsl_qspi_driver = { | 998 | static struct platform_driver fsl_qspi_driver = { |
| 976 | .driver = { | 999 | .driver = { |
| 977 | .name = "fsl-quadspi", | 1000 | .name = "fsl-quadspi", |
| @@ -980,6 +1003,8 @@ static struct platform_driver fsl_qspi_driver = { | |||
| 980 | }, | 1003 | }, |
| 981 | .probe = fsl_qspi_probe, | 1004 | .probe = fsl_qspi_probe, |
| 982 | .remove = fsl_qspi_remove, | 1005 | .remove = fsl_qspi_remove, |
| 1006 | .suspend = fsl_qspi_suspend, | ||
| 1007 | .resume = fsl_qspi_resume, | ||
| 983 | }; | 1008 | }; |
| 984 | module_platform_driver(fsl_qspi_driver); | 1009 | module_platform_driver(fsl_qspi_driver); |
| 985 | 1010 | ||
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 0f8ec3c2d015..b6a5a0c269e1 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c | |||
| @@ -538,6 +538,7 @@ static const struct spi_device_id spi_nor_ids[] = { | |||
| 538 | /* GigaDevice */ | 538 | /* GigaDevice */ |
| 539 | { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) }, | 539 | { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) }, |
| 540 | { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K) }, | 540 | { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K) }, |
| 541 | { "gd25q128", INFO(0xc84018, 0, 64 * 1024, 256, SECT_4K) }, | ||
| 541 | 542 | ||
| 542 | /* Intel/Numonyx -- xxxs33b */ | 543 | /* Intel/Numonyx -- xxxs33b */ |
| 543 | { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) }, | 544 | { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) }, |
| @@ -560,14 +561,14 @@ static const struct spi_device_id spi_nor_ids[] = { | |||
| 560 | { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) }, | 561 | { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) }, |
| 561 | 562 | ||
| 562 | /* Micron */ | 563 | /* Micron */ |
| 563 | { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, 0) }, | 564 | { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) }, |
| 564 | { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) }, | 565 | { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, SPI_NOR_QUAD_READ) }, |
| 565 | { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0) }, | 566 | { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, SPI_NOR_QUAD_READ) }, |
| 566 | { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) }, | 567 | { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, SPI_NOR_QUAD_READ) }, |
| 567 | { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) }, | 568 | { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ) }, |
| 568 | { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K) }, | 569 | { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, |
| 569 | { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, USE_FSR) }, | 570 | { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, |
| 570 | { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, USE_FSR) }, | 571 | { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, |
| 571 | 572 | ||
| 572 | /* PMC */ | 573 | /* PMC */ |
| 573 | { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) }, | 574 | { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) }, |
| @@ -891,6 +892,45 @@ static int spansion_quad_enable(struct spi_nor *nor) | |||
| 891 | return 0; | 892 | return 0; |
| 892 | } | 893 | } |
| 893 | 894 | ||
| 895 | static int micron_quad_enable(struct spi_nor *nor) | ||
| 896 | { | ||
| 897 | int ret; | ||
| 898 | u8 val; | ||
| 899 | |||
| 900 | ret = nor->read_reg(nor, SPINOR_OP_RD_EVCR, &val, 1); | ||
| 901 | if (ret < 0) { | ||
| 902 | dev_err(nor->dev, "error %d reading EVCR\n", ret); | ||
| 903 | return ret; | ||
| 904 | } | ||
| 905 | |||
| 906 | write_enable(nor); | ||
| 907 | |||
| 908 | /* set EVCR, enable quad I/O */ | ||
| 909 | nor->cmd_buf[0] = val & ~EVCR_QUAD_EN_MICRON; | ||
| 910 | ret = nor->write_reg(nor, SPINOR_OP_WD_EVCR, nor->cmd_buf, 1, 0); | ||
| 911 | if (ret < 0) { | ||
| 912 | dev_err(nor->dev, "error while writing EVCR register\n"); | ||
| 913 | return ret; | ||
| 914 | } | ||
| 915 | |||
| 916 | ret = spi_nor_wait_till_ready(nor); | ||
| 917 | if (ret) | ||
| 918 | return ret; | ||
| 919 | |||
| 920 | /* read EVCR and check it */ | ||
| 921 | ret = nor->read_reg(nor, SPINOR_OP_RD_EVCR, &val, 1); | ||
| 922 | if (ret < 0) { | ||
| 923 | dev_err(nor->dev, "error %d reading EVCR\n", ret); | ||
| 924 | return ret; | ||
| 925 | } | ||
| 926 | if (val & EVCR_QUAD_EN_MICRON) { | ||
| 927 | dev_err(nor->dev, "Micron EVCR Quad bit not clear\n"); | ||
| 928 | return -EINVAL; | ||
| 929 | } | ||
| 930 | |||
| 931 | return 0; | ||
| 932 | } | ||
| 933 | |||
| 894 | static int set_quad_mode(struct spi_nor *nor, struct flash_info *info) | 934 | static int set_quad_mode(struct spi_nor *nor, struct flash_info *info) |
| 895 | { | 935 | { |
| 896 | int status; | 936 | int status; |
| @@ -903,6 +943,13 @@ static int set_quad_mode(struct spi_nor *nor, struct flash_info *info) | |||
| 903 | return -EINVAL; | 943 | return -EINVAL; |
| 904 | } | 944 | } |
| 905 | return status; | 945 | return status; |
| 946 | case CFI_MFR_ST: | ||
| 947 | status = micron_quad_enable(nor); | ||
| 948 | if (status) { | ||
| 949 | dev_err(nor->dev, "Micron quad-read not enabled\n"); | ||
| 950 | return -EINVAL; | ||
| 951 | } | ||
| 952 | return status; | ||
| 906 | default: | 953 | default: |
| 907 | status = spansion_quad_enable(nor); | 954 | status = spansion_quad_enable(nor); |
| 908 | if (status) { | 955 | if (status) { |
diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index 945f532078e9..96edc1346124 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c | |||
| @@ -214,8 +214,17 @@ static struct com20020_pci_card_info card_info_sohard = { | |||
| 214 | .flags = ARC_CAN_10MBIT, | 214 | .flags = ARC_CAN_10MBIT, |
| 215 | }; | 215 | }; |
| 216 | 216 | ||
| 217 | static struct com20020_pci_card_info card_info_eae = { | 217 | static struct com20020_pci_card_info card_info_eae_arc1 = { |
| 218 | .name = "EAE PLX-PCI", | 218 | .name = "EAE PLX-PCI ARC1", |
| 219 | .devcount = 1, | ||
| 220 | .chan_map_tbl = { | ||
| 221 | { 2, 0x00, 0x08 }, | ||
| 222 | }, | ||
| 223 | .flags = ARC_CAN_10MBIT, | ||
| 224 | }; | ||
| 225 | |||
| 226 | static struct com20020_pci_card_info card_info_eae_ma1 = { | ||
| 227 | .name = "EAE PLX-PCI MA1", | ||
| 219 | .devcount = 2, | 228 | .devcount = 2, |
| 220 | .chan_map_tbl = { | 229 | .chan_map_tbl = { |
| 221 | { 2, 0x00, 0x08 }, | 230 | { 2, 0x00, 0x08 }, |
| @@ -359,9 +368,15 @@ static const struct pci_device_id com20020pci_id_table[] = { | |||
| 359 | }, | 368 | }, |
| 360 | { | 369 | { |
| 361 | 0x10B5, 0x9050, | 370 | 0x10B5, 0x9050, |
| 371 | 0x10B5, 0x3263, | ||
| 372 | 0, 0, | ||
| 373 | (kernel_ulong_t)&card_info_eae_arc1 | ||
| 374 | }, | ||
| 375 | { | ||
| 376 | 0x10B5, 0x9050, | ||
| 362 | 0x10B5, 0x3292, | 377 | 0x10B5, 0x3292, |
| 363 | 0, 0, | 378 | 0, 0, |
| 364 | (kernel_ulong_t)&card_info_eae | 379 | (kernel_ulong_t)&card_info_eae_ma1 |
| 365 | }, | 380 | }, |
| 366 | { | 381 | { |
| 367 | 0x14BA, 0x6000, | 382 | 0x14BA, 0x6000, |
diff --git a/drivers/net/ethernet/3com/3c589_cs.c b/drivers/net/ethernet/3com/3c589_cs.c index f18647c23559..c5a320507556 100644 --- a/drivers/net/ethernet/3com/3c589_cs.c +++ b/drivers/net/ethernet/3com/3c589_cs.c | |||
| @@ -518,11 +518,8 @@ static int el3_open(struct net_device *dev) | |||
| 518 | netif_start_queue(dev); | 518 | netif_start_queue(dev); |
| 519 | 519 | ||
| 520 | tc589_reset(dev); | 520 | tc589_reset(dev); |
| 521 | init_timer(&lp->media); | 521 | setup_timer(&lp->media, media_check, (unsigned long)dev); |
| 522 | lp->media.function = media_check; | 522 | mod_timer(&lp->media, jiffies + HZ); |
| 523 | lp->media.data = (unsigned long) dev; | ||
| 524 | lp->media.expires = jiffies + HZ; | ||
| 525 | add_timer(&lp->media); | ||
| 526 | 523 | ||
| 527 | dev_dbg(&link->dev, "%s: opened, status %4.4x.\n", | 524 | dev_dbg(&link->dev, "%s: opened, status %4.4x.\n", |
| 528 | dev->name, inw(dev->base_addr + EL3_STATUS)); | 525 | dev->name, inw(dev->base_addr + EL3_STATUS)); |
diff --git a/drivers/net/ethernet/agere/et131x.c b/drivers/net/ethernet/agere/et131x.c index 384dc163851b..e0f3d197e7f2 100644 --- a/drivers/net/ethernet/agere/et131x.c +++ b/drivers/net/ethernet/agere/et131x.c | |||
| @@ -3127,7 +3127,8 @@ static void et131x_error_timer_handler(unsigned long data) | |||
| 3127 | } | 3127 | } |
| 3128 | 3128 | ||
| 3129 | /* This is a periodic timer, so reschedule */ | 3129 | /* This is a periodic timer, so reschedule */ |
| 3130 | mod_timer(&adapter->error_timer, jiffies + TX_ERROR_PERIOD * HZ / 1000); | 3130 | mod_timer(&adapter->error_timer, jiffies + |
| 3131 | msecs_to_jiffies(TX_ERROR_PERIOD)); | ||
| 3131 | } | 3132 | } |
| 3132 | 3133 | ||
| 3133 | static void et131x_adapter_memory_free(struct et131x_adapter *adapter) | 3134 | static void et131x_adapter_memory_free(struct et131x_adapter *adapter) |
| @@ -3647,7 +3648,8 @@ static int et131x_open(struct net_device *netdev) | |||
| 3647 | 3648 | ||
| 3648 | /* Start the timer to track NIC errors */ | 3649 | /* Start the timer to track NIC errors */ |
| 3649 | init_timer(&adapter->error_timer); | 3650 | init_timer(&adapter->error_timer); |
| 3650 | adapter->error_timer.expires = jiffies + TX_ERROR_PERIOD * HZ / 1000; | 3651 | adapter->error_timer.expires = jiffies + |
| 3652 | msecs_to_jiffies(TX_ERROR_PERIOD); | ||
| 3651 | adapter->error_timer.function = et131x_error_timer_handler; | 3653 | adapter->error_timer.function = et131x_error_timer_handler; |
| 3652 | adapter->error_timer.data = (unsigned long)adapter; | 3654 | adapter->error_timer.data = (unsigned long)adapter; |
| 3653 | add_timer(&adapter->error_timer); | 3655 | add_timer(&adapter->error_timer); |
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c index 44b15373d6b3..4de62b210c85 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c | |||
| @@ -1030,12 +1030,14 @@ static const struct acpi_device_id xgene_enet_acpi_match[] = { | |||
| 1030 | MODULE_DEVICE_TABLE(acpi, xgene_enet_acpi_match); | 1030 | MODULE_DEVICE_TABLE(acpi, xgene_enet_acpi_match); |
| 1031 | #endif | 1031 | #endif |
| 1032 | 1032 | ||
| 1033 | #ifdef CONFIG_OF | ||
| 1033 | static struct of_device_id xgene_enet_of_match[] = { | 1034 | static struct of_device_id xgene_enet_of_match[] = { |
| 1034 | {.compatible = "apm,xgene-enet",}, | 1035 | {.compatible = "apm,xgene-enet",}, |
| 1035 | {}, | 1036 | {}, |
| 1036 | }; | 1037 | }; |
| 1037 | 1038 | ||
| 1038 | MODULE_DEVICE_TABLE(of, xgene_enet_of_match); | 1039 | MODULE_DEVICE_TABLE(of, xgene_enet_of_match); |
| 1040 | #endif | ||
| 1039 | 1041 | ||
| 1040 | static struct platform_driver xgene_enet_driver = { | 1042 | static struct platform_driver xgene_enet_driver = { |
| 1041 | .driver = { | 1043 | .driver = { |
diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c index d86d6baf9681..bd5916a60cb5 100644 --- a/drivers/net/ethernet/broadcom/b44.c +++ b/drivers/net/ethernet/broadcom/b44.c | |||
| @@ -121,7 +121,7 @@ static struct pci_driver b44_pci_driver = { | |||
| 121 | 121 | ||
| 122 | static const struct ssb_device_id b44_ssb_tbl[] = { | 122 | static const struct ssb_device_id b44_ssb_tbl[] = { |
| 123 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_ETHERNET, SSB_ANY_REV), | 123 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_ETHERNET, SSB_ANY_REV), |
| 124 | SSB_DEVTABLE_END | 124 | {}, |
| 125 | }; | 125 | }; |
| 126 | MODULE_DEVICE_TABLE(ssb, b44_ssb_tbl); | 126 | MODULE_DEVICE_TABLE(ssb, b44_ssb_tbl); |
| 127 | 127 | ||
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c index 3007d95fbb9f..676ffe093180 100644 --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c | |||
| @@ -21,7 +21,7 @@ | |||
| 21 | static const struct bcma_device_id bgmac_bcma_tbl[] = { | 21 | static const struct bcma_device_id bgmac_bcma_tbl[] = { |
| 22 | BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_4706_MAC_GBIT, BCMA_ANY_REV, BCMA_ANY_CLASS), | 22 | BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_4706_MAC_GBIT, BCMA_ANY_REV, BCMA_ANY_CLASS), |
| 23 | BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_MAC_GBIT, BCMA_ANY_REV, BCMA_ANY_CLASS), | 23 | BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_MAC_GBIT, BCMA_ANY_REV, BCMA_ANY_CLASS), |
| 24 | BCMA_CORETABLE_END | 24 | {}, |
| 25 | }; | 25 | }; |
| 26 | MODULE_DEVICE_TABLE(bcma, bgmac_bcma_tbl); | 26 | MODULE_DEVICE_TABLE(bcma, bgmac_bcma_tbl); |
| 27 | 27 | ||
| @@ -1412,6 +1412,7 @@ static void bgmac_mii_unregister(struct bgmac *bgmac) | |||
| 1412 | /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipattach */ | 1412 | /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipattach */ |
| 1413 | static int bgmac_probe(struct bcma_device *core) | 1413 | static int bgmac_probe(struct bcma_device *core) |
| 1414 | { | 1414 | { |
| 1415 | struct bcma_chipinfo *ci = &core->bus->chipinfo; | ||
| 1415 | struct net_device *net_dev; | 1416 | struct net_device *net_dev; |
| 1416 | struct bgmac *bgmac; | 1417 | struct bgmac *bgmac; |
| 1417 | struct ssb_sprom *sprom = &core->bus->sprom; | 1418 | struct ssb_sprom *sprom = &core->bus->sprom; |
| @@ -1474,8 +1475,8 @@ static int bgmac_probe(struct bcma_device *core) | |||
| 1474 | bgmac_chip_reset(bgmac); | 1475 | bgmac_chip_reset(bgmac); |
| 1475 | 1476 | ||
| 1476 | /* For Northstar, we have to take all GMAC core out of reset */ | 1477 | /* For Northstar, we have to take all GMAC core out of reset */ |
| 1477 | if (core->id.id == BCMA_CHIP_ID_BCM4707 || | 1478 | if (ci->id == BCMA_CHIP_ID_BCM4707 || |
| 1478 | core->id.id == BCMA_CHIP_ID_BCM53018) { | 1479 | ci->id == BCMA_CHIP_ID_BCM53018) { |
| 1479 | struct bcma_device *ns_core; | 1480 | struct bcma_device *ns_core; |
| 1480 | int ns_gmac; | 1481 | int ns_gmac; |
| 1481 | 1482 | ||
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 615a6dbde047..23a019cee279 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c | |||
| @@ -17855,8 +17855,10 @@ static int tg3_init_one(struct pci_dev *pdev, | |||
| 17855 | */ | 17855 | */ |
| 17856 | if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) || | 17856 | if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) || |
| 17857 | (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { | 17857 | (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { |
| 17858 | tg3_full_lock(tp, 0); | ||
| 17858 | tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); | 17859 | tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); |
| 17859 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); | 17860 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); |
| 17861 | tg3_full_unlock(tp); | ||
| 17860 | } | 17862 | } |
| 17861 | 17863 | ||
| 17862 | err = tg3_test_dma(tp); | 17864 | err = tg3_test_dma(tp); |
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c index d221f6b28fcd..78854ceb0870 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c | |||
| @@ -1950,12 +1950,9 @@ static void set_debugfs_file_size(struct dentry *de, loff_t size) | |||
| 1950 | static void add_debugfs_mem(struct adapter *adap, const char *name, | 1950 | static void add_debugfs_mem(struct adapter *adap, const char *name, |
| 1951 | unsigned int idx, unsigned int size_mb) | 1951 | unsigned int idx, unsigned int size_mb) |
| 1952 | { | 1952 | { |
| 1953 | struct dentry *de; | 1953 | debugfs_create_file_size(name, S_IRUSR, adap->debugfs_root, |
| 1954 | 1954 | (void *)adap + idx, &mem_debugfs_fops, | |
| 1955 | de = debugfs_create_file(name, S_IRUSR, adap->debugfs_root, | 1955 | size_mb << 20); |
| 1956 | (void *)adap + idx, &mem_debugfs_fops); | ||
| 1957 | if (de && de->d_inode) | ||
| 1958 | de->d_inode->i_size = size_mb << 20; | ||
| 1959 | } | 1956 | } |
| 1960 | 1957 | ||
| 1961 | /* Add an array of Debug FS files. | 1958 | /* Add an array of Debug FS files. |
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.h index b63cfee2d963..8f418ba868bd 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.h | |||
| @@ -55,7 +55,7 @@ static const struct file_operations name##_debugfs_fops = { \ | |||
| 55 | struct t4_debugfs_entry { | 55 | struct t4_debugfs_entry { |
| 56 | const char *name; | 56 | const char *name; |
| 57 | const struct file_operations *ops; | 57 | const struct file_operations *ops; |
| 58 | mode_t mode; | 58 | umode_t mode; |
| 59 | unsigned char data; | 59 | unsigned char data; |
| 60 | }; | 60 | }; |
| 61 | 61 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index d6651937d899..5394a8486558 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c | |||
| @@ -291,6 +291,7 @@ static void copy_rw_fields(void *to, struct mlx5_caps *from) | |||
| 291 | MLX5_SET(cmd_hca_cap, to, log_max_ra_req_dc, from->gen.log_max_ra_req_dc); | 291 | MLX5_SET(cmd_hca_cap, to, log_max_ra_req_dc, from->gen.log_max_ra_req_dc); |
| 292 | MLX5_SET(cmd_hca_cap, to, log_max_ra_res_dc, from->gen.log_max_ra_res_dc); | 292 | MLX5_SET(cmd_hca_cap, to, log_max_ra_res_dc, from->gen.log_max_ra_res_dc); |
| 293 | MLX5_SET(cmd_hca_cap, to, pkey_table_size, to_fw_pkey_sz(from->gen.pkey_table_size)); | 293 | MLX5_SET(cmd_hca_cap, to, pkey_table_size, to_fw_pkey_sz(from->gen.pkey_table_size)); |
| 294 | MLX5_SET(cmd_hca_cap, to, log_uar_page_sz, PAGE_SHIFT - 12); | ||
| 294 | v64 = from->gen.flags & MLX5_CAP_BITS_RW_MASK; | 295 | v64 = from->gen.flags & MLX5_CAP_BITS_RW_MASK; |
| 295 | *flags_off = cpu_to_be64(v64); | 296 | *flags_off = cpu_to_be64(v64); |
| 296 | } | 297 | } |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index e56c1bb36141..fa4317611fd6 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | |||
| @@ -848,10 +848,17 @@ struct qlcnic_cardrsp_tx_ctx { | |||
| 848 | #define QLCNIC_MAC_VLAN_ADD 3 | 848 | #define QLCNIC_MAC_VLAN_ADD 3 |
| 849 | #define QLCNIC_MAC_VLAN_DEL 4 | 849 | #define QLCNIC_MAC_VLAN_DEL 4 |
| 850 | 850 | ||
| 851 | enum qlcnic_mac_type { | ||
| 852 | QLCNIC_UNICAST_MAC, | ||
| 853 | QLCNIC_MULTICAST_MAC, | ||
| 854 | QLCNIC_BROADCAST_MAC, | ||
| 855 | }; | ||
| 856 | |||
| 851 | struct qlcnic_mac_vlan_list { | 857 | struct qlcnic_mac_vlan_list { |
| 852 | struct list_head list; | 858 | struct list_head list; |
| 853 | uint8_t mac_addr[ETH_ALEN+2]; | 859 | uint8_t mac_addr[ETH_ALEN+2]; |
| 854 | u16 vlan_id; | 860 | u16 vlan_id; |
| 861 | enum qlcnic_mac_type mac_type; | ||
| 855 | }; | 862 | }; |
| 856 | 863 | ||
| 857 | /* MAC Learn */ | 864 | /* MAC Learn */ |
| @@ -1615,7 +1622,9 @@ void qlcnic_watchdog_task(struct work_struct *work); | |||
| 1615 | void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, | 1622 | void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, |
| 1616 | struct qlcnic_host_rds_ring *rds_ring, u8 ring_id); | 1623 | struct qlcnic_host_rds_ring *rds_ring, u8 ring_id); |
| 1617 | void qlcnic_set_multi(struct net_device *netdev); | 1624 | void qlcnic_set_multi(struct net_device *netdev); |
| 1618 | int qlcnic_nic_add_mac(struct qlcnic_adapter *, const u8 *, u16); | 1625 | void qlcnic_flush_mcast_mac(struct qlcnic_adapter *); |
| 1626 | int qlcnic_nic_add_mac(struct qlcnic_adapter *, const u8 *, u16, | ||
| 1627 | enum qlcnic_mac_type); | ||
| 1619 | int qlcnic_nic_del_mac(struct qlcnic_adapter *, const u8 *); | 1628 | int qlcnic_nic_del_mac(struct qlcnic_adapter *, const u8 *); |
| 1620 | void qlcnic_82xx_free_mac_list(struct qlcnic_adapter *adapter); | 1629 | void qlcnic_82xx_free_mac_list(struct qlcnic_adapter *adapter); |
| 1621 | int qlcnic_82xx_read_phys_port_id(struct qlcnic_adapter *); | 1630 | int qlcnic_82xx_read_phys_port_id(struct qlcnic_adapter *); |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c index 69b46c051cc0..3e0f705a4311 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | |||
| @@ -487,7 +487,8 @@ int qlcnic_nic_del_mac(struct qlcnic_adapter *adapter, const u8 *addr) | |||
| 487 | return err; | 487 | return err; |
| 488 | } | 488 | } |
| 489 | 489 | ||
| 490 | int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr, u16 vlan) | 490 | int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr, u16 vlan, |
| 491 | enum qlcnic_mac_type mac_type) | ||
| 491 | { | 492 | { |
| 492 | struct qlcnic_mac_vlan_list *cur; | 493 | struct qlcnic_mac_vlan_list *cur; |
| 493 | struct list_head *head; | 494 | struct list_head *head; |
| @@ -513,10 +514,29 @@ int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr, u16 vlan) | |||
| 513 | } | 514 | } |
| 514 | 515 | ||
| 515 | cur->vlan_id = vlan; | 516 | cur->vlan_id = vlan; |
| 517 | cur->mac_type = mac_type; | ||
| 518 | |||
| 516 | list_add_tail(&cur->list, &adapter->mac_list); | 519 | list_add_tail(&cur->list, &adapter->mac_list); |
| 517 | return 0; | 520 | return 0; |
| 518 | } | 521 | } |
| 519 | 522 | ||
| 523 | void qlcnic_flush_mcast_mac(struct qlcnic_adapter *adapter) | ||
| 524 | { | ||
| 525 | struct qlcnic_mac_vlan_list *cur; | ||
| 526 | struct list_head *head, *tmp; | ||
| 527 | |||
| 528 | list_for_each_safe(head, tmp, &adapter->mac_list) { | ||
| 529 | cur = list_entry(head, struct qlcnic_mac_vlan_list, list); | ||
| 530 | if (cur->mac_type != QLCNIC_MULTICAST_MAC) | ||
| 531 | continue; | ||
| 532 | |||
| 533 | qlcnic_sre_macaddr_change(adapter, cur->mac_addr, | ||
| 534 | cur->vlan_id, QLCNIC_MAC_DEL); | ||
| 535 | list_del(&cur->list); | ||
| 536 | kfree(cur); | ||
| 537 | } | ||
| 538 | } | ||
| 539 | |||
| 520 | static void __qlcnic_set_multi(struct net_device *netdev, u16 vlan) | 540 | static void __qlcnic_set_multi(struct net_device *netdev, u16 vlan) |
| 521 | { | 541 | { |
| 522 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | 542 | struct qlcnic_adapter *adapter = netdev_priv(netdev); |
| @@ -530,8 +550,9 @@ static void __qlcnic_set_multi(struct net_device *netdev, u16 vlan) | |||
| 530 | if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) | 550 | if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) |
| 531 | return; | 551 | return; |
| 532 | 552 | ||
| 533 | qlcnic_nic_add_mac(adapter, adapter->mac_addr, vlan); | 553 | qlcnic_nic_add_mac(adapter, adapter->mac_addr, vlan, |
| 534 | qlcnic_nic_add_mac(adapter, bcast_addr, vlan); | 554 | QLCNIC_UNICAST_MAC); |
| 555 | qlcnic_nic_add_mac(adapter, bcast_addr, vlan, QLCNIC_BROADCAST_MAC); | ||
| 535 | 556 | ||
| 536 | if (netdev->flags & IFF_PROMISC) { | 557 | if (netdev->flags & IFF_PROMISC) { |
| 537 | if (!(adapter->flags & QLCNIC_PROMISC_DISABLED)) | 558 | if (!(adapter->flags & QLCNIC_PROMISC_DISABLED)) |
| @@ -540,8 +561,10 @@ static void __qlcnic_set_multi(struct net_device *netdev, u16 vlan) | |||
| 540 | (netdev_mc_count(netdev) > ahw->max_mc_count)) { | 561 | (netdev_mc_count(netdev) > ahw->max_mc_count)) { |
| 541 | mode = VPORT_MISS_MODE_ACCEPT_MULTI; | 562 | mode = VPORT_MISS_MODE_ACCEPT_MULTI; |
| 542 | } else if (!netdev_mc_empty(netdev)) { | 563 | } else if (!netdev_mc_empty(netdev)) { |
| 564 | qlcnic_flush_mcast_mac(adapter); | ||
| 543 | netdev_for_each_mc_addr(ha, netdev) | 565 | netdev_for_each_mc_addr(ha, netdev) |
| 544 | qlcnic_nic_add_mac(adapter, ha->addr, vlan); | 566 | qlcnic_nic_add_mac(adapter, ha->addr, vlan, |
| 567 | QLCNIC_MULTICAST_MAC); | ||
| 545 | } | 568 | } |
| 546 | 569 | ||
| 547 | /* configure unicast MAC address, if there is not sufficient space | 570 | /* configure unicast MAC address, if there is not sufficient space |
| @@ -551,7 +574,8 @@ static void __qlcnic_set_multi(struct net_device *netdev, u16 vlan) | |||
| 551 | mode = VPORT_MISS_MODE_ACCEPT_ALL; | 574 | mode = VPORT_MISS_MODE_ACCEPT_ALL; |
| 552 | } else if (!netdev_uc_empty(netdev)) { | 575 | } else if (!netdev_uc_empty(netdev)) { |
| 553 | netdev_for_each_uc_addr(ha, netdev) | 576 | netdev_for_each_uc_addr(ha, netdev) |
| 554 | qlcnic_nic_add_mac(adapter, ha->addr, vlan); | 577 | qlcnic_nic_add_mac(adapter, ha->addr, vlan, |
| 578 | QLCNIC_UNICAST_MAC); | ||
| 555 | } | 579 | } |
| 556 | 580 | ||
| 557 | if (mode == VPORT_MISS_MODE_ACCEPT_ALL && | 581 | if (mode == VPORT_MISS_MODE_ACCEPT_ALL && |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c index 1659c804f1d5..e6312465fe45 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c | |||
| @@ -1489,7 +1489,8 @@ out: | |||
| 1489 | return ret; | 1489 | return ret; |
| 1490 | } | 1490 | } |
| 1491 | 1491 | ||
| 1492 | static void qlcnic_vf_add_mc_list(struct net_device *netdev, const u8 *mac) | 1492 | static void qlcnic_vf_add_mc_list(struct net_device *netdev, const u8 *mac, |
| 1493 | enum qlcnic_mac_type mac_type) | ||
| 1493 | { | 1494 | { |
| 1494 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | 1495 | struct qlcnic_adapter *adapter = netdev_priv(netdev); |
| 1495 | struct qlcnic_sriov *sriov = adapter->ahw->sriov; | 1496 | struct qlcnic_sriov *sriov = adapter->ahw->sriov; |
| @@ -1500,17 +1501,18 @@ static void qlcnic_vf_add_mc_list(struct net_device *netdev, const u8 *mac) | |||
| 1500 | vf = &adapter->ahw->sriov->vf_info[0]; | 1501 | vf = &adapter->ahw->sriov->vf_info[0]; |
| 1501 | 1502 | ||
| 1502 | if (!qlcnic_sriov_check_any_vlan(vf)) { | 1503 | if (!qlcnic_sriov_check_any_vlan(vf)) { |
| 1503 | qlcnic_nic_add_mac(adapter, mac, 0); | 1504 | qlcnic_nic_add_mac(adapter, mac, 0, mac_type); |
| 1504 | } else { | 1505 | } else { |
| 1505 | spin_lock(&vf->vlan_list_lock); | 1506 | spin_lock(&vf->vlan_list_lock); |
| 1506 | for (i = 0; i < sriov->num_allowed_vlans; i++) { | 1507 | for (i = 0; i < sriov->num_allowed_vlans; i++) { |
| 1507 | vlan_id = vf->sriov_vlans[i]; | 1508 | vlan_id = vf->sriov_vlans[i]; |
| 1508 | if (vlan_id) | 1509 | if (vlan_id) |
| 1509 | qlcnic_nic_add_mac(adapter, mac, vlan_id); | 1510 | qlcnic_nic_add_mac(adapter, mac, vlan_id, |
| 1511 | mac_type); | ||
| 1510 | } | 1512 | } |
| 1511 | spin_unlock(&vf->vlan_list_lock); | 1513 | spin_unlock(&vf->vlan_list_lock); |
| 1512 | if (qlcnic_84xx_check(adapter)) | 1514 | if (qlcnic_84xx_check(adapter)) |
| 1513 | qlcnic_nic_add_mac(adapter, mac, 0); | 1515 | qlcnic_nic_add_mac(adapter, mac, 0, mac_type); |
| 1514 | } | 1516 | } |
| 1515 | } | 1517 | } |
| 1516 | 1518 | ||
| @@ -1549,10 +1551,12 @@ void qlcnic_sriov_vf_set_multi(struct net_device *netdev) | |||
| 1549 | (netdev_mc_count(netdev) > ahw->max_mc_count)) { | 1551 | (netdev_mc_count(netdev) > ahw->max_mc_count)) { |
| 1550 | mode = VPORT_MISS_MODE_ACCEPT_MULTI; | 1552 | mode = VPORT_MISS_MODE_ACCEPT_MULTI; |
| 1551 | } else { | 1553 | } else { |
| 1552 | qlcnic_vf_add_mc_list(netdev, bcast_addr); | 1554 | qlcnic_vf_add_mc_list(netdev, bcast_addr, QLCNIC_BROADCAST_MAC); |
| 1553 | if (!netdev_mc_empty(netdev)) { | 1555 | if (!netdev_mc_empty(netdev)) { |
| 1556 | qlcnic_flush_mcast_mac(adapter); | ||
| 1554 | netdev_for_each_mc_addr(ha, netdev) | 1557 | netdev_for_each_mc_addr(ha, netdev) |
| 1555 | qlcnic_vf_add_mc_list(netdev, ha->addr); | 1558 | qlcnic_vf_add_mc_list(netdev, ha->addr, |
| 1559 | QLCNIC_MULTICAST_MAC); | ||
| 1556 | } | 1560 | } |
| 1557 | } | 1561 | } |
| 1558 | 1562 | ||
| @@ -1563,7 +1567,8 @@ void qlcnic_sriov_vf_set_multi(struct net_device *netdev) | |||
| 1563 | mode = VPORT_MISS_MODE_ACCEPT_ALL; | 1567 | mode = VPORT_MISS_MODE_ACCEPT_ALL; |
| 1564 | } else if (!netdev_uc_empty(netdev)) { | 1568 | } else if (!netdev_uc_empty(netdev)) { |
| 1565 | netdev_for_each_uc_addr(ha, netdev) | 1569 | netdev_for_each_uc_addr(ha, netdev) |
| 1566 | qlcnic_vf_add_mc_list(netdev, ha->addr); | 1570 | qlcnic_vf_add_mc_list(netdev, ha->addr, |
| 1571 | QLCNIC_UNICAST_MAC); | ||
| 1567 | } | 1572 | } |
| 1568 | 1573 | ||
| 1569 | if (adapter->pdev->is_virtfn) { | 1574 | if (adapter->pdev->is_virtfn) { |
diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c index 2b10b85d8a08..22e0cad1b4b5 100644 --- a/drivers/net/ethernet/sun/sunvnet.c +++ b/drivers/net/ethernet/sun/sunvnet.c | |||
| @@ -1192,23 +1192,16 @@ static int vnet_handle_offloads(struct vnet_port *port, struct sk_buff *skb) | |||
| 1192 | skb_pull(skb, maclen); | 1192 | skb_pull(skb, maclen); |
| 1193 | 1193 | ||
| 1194 | if (port->tso && gso_size < datalen) { | 1194 | if (port->tso && gso_size < datalen) { |
| 1195 | if (skb_unclone(skb, GFP_ATOMIC)) | ||
| 1196 | goto out_dropped; | ||
| 1197 | |||
| 1195 | /* segment to TSO size */ | 1198 | /* segment to TSO size */ |
| 1196 | skb_shinfo(skb)->gso_size = datalen; | 1199 | skb_shinfo(skb)->gso_size = datalen; |
| 1197 | skb_shinfo(skb)->gso_segs = gso_segs; | 1200 | skb_shinfo(skb)->gso_segs = gso_segs; |
| 1198 | |||
| 1199 | segs = skb_gso_segment(skb, dev->features & ~NETIF_F_TSO); | ||
| 1200 | |||
| 1201 | /* restore gso_size & gso_segs */ | ||
| 1202 | skb_shinfo(skb)->gso_size = gso_size; | ||
| 1203 | skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len - hlen, | ||
| 1204 | gso_size); | ||
| 1205 | } else | ||
| 1206 | segs = skb_gso_segment(skb, dev->features & ~NETIF_F_TSO); | ||
| 1207 | if (IS_ERR(segs)) { | ||
| 1208 | dev->stats.tx_dropped++; | ||
| 1209 | dev_kfree_skb_any(skb); | ||
| 1210 | return NETDEV_TX_OK; | ||
| 1211 | } | 1201 | } |
| 1202 | segs = skb_gso_segment(skb, dev->features & ~NETIF_F_TSO); | ||
| 1203 | if (IS_ERR(segs)) | ||
| 1204 | goto out_dropped; | ||
| 1212 | 1205 | ||
| 1213 | skb_push(skb, maclen); | 1206 | skb_push(skb, maclen); |
| 1214 | skb_reset_mac_header(skb); | 1207 | skb_reset_mac_header(skb); |
| @@ -1246,6 +1239,10 @@ static int vnet_handle_offloads(struct vnet_port *port, struct sk_buff *skb) | |||
| 1246 | if (!(status & NETDEV_TX_MASK)) | 1239 | if (!(status & NETDEV_TX_MASK)) |
| 1247 | dev_kfree_skb_any(skb); | 1240 | dev_kfree_skb_any(skb); |
| 1248 | return status; | 1241 | return status; |
| 1242 | out_dropped: | ||
| 1243 | dev->stats.tx_dropped++; | ||
| 1244 | dev_kfree_skb_any(skb); | ||
| 1245 | return NETDEV_TX_OK; | ||
| 1249 | } | 1246 | } |
| 1250 | 1247 | ||
| 1251 | static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev) | 1248 | static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev) |
diff --git a/drivers/net/ipvlan/ipvlan.h b/drivers/net/ipvlan/ipvlan.h index 2729f64b3e7e..924ea98bd531 100644 --- a/drivers/net/ipvlan/ipvlan.h +++ b/drivers/net/ipvlan/ipvlan.h | |||
| @@ -67,7 +67,7 @@ struct ipvl_dev { | |||
| 67 | struct list_head addrs; | 67 | struct list_head addrs; |
| 68 | int ipv4cnt; | 68 | int ipv4cnt; |
| 69 | int ipv6cnt; | 69 | int ipv6cnt; |
| 70 | struct ipvl_pcpu_stats *pcpu_stats; | 70 | struct ipvl_pcpu_stats __percpu *pcpu_stats; |
| 71 | DECLARE_BITMAP(mac_filters, IPVLAN_MAC_FILTER_SIZE); | 71 | DECLARE_BITMAP(mac_filters, IPVLAN_MAC_FILTER_SIZE); |
| 72 | netdev_features_t sfeatures; | 72 | netdev_features_t sfeatures; |
| 73 | u32 msg_enable; | 73 | u32 msg_enable; |
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 3ad8ca76196d..1190fd8f0088 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | /* Operation Mode Strap Override */ | 32 | /* Operation Mode Strap Override */ |
| 33 | #define MII_KSZPHY_OMSO 0x16 | 33 | #define MII_KSZPHY_OMSO 0x16 |
| 34 | #define KSZPHY_OMSO_B_CAST_OFF BIT(9) | 34 | #define KSZPHY_OMSO_B_CAST_OFF BIT(9) |
| 35 | #define KSZPHY_OMSO_NAND_TREE_ON BIT(5) | ||
| 35 | #define KSZPHY_OMSO_RMII_OVERRIDE BIT(1) | 36 | #define KSZPHY_OMSO_RMII_OVERRIDE BIT(1) |
| 36 | #define KSZPHY_OMSO_MII_OVERRIDE BIT(0) | 37 | #define KSZPHY_OMSO_MII_OVERRIDE BIT(0) |
| 37 | 38 | ||
| @@ -76,6 +77,7 @@ struct kszphy_type { | |||
| 76 | u32 led_mode_reg; | 77 | u32 led_mode_reg; |
| 77 | u16 interrupt_level_mask; | 78 | u16 interrupt_level_mask; |
| 78 | bool has_broadcast_disable; | 79 | bool has_broadcast_disable; |
| 80 | bool has_nand_tree_disable; | ||
| 79 | bool has_rmii_ref_clk_sel; | 81 | bool has_rmii_ref_clk_sel; |
| 80 | }; | 82 | }; |
| 81 | 83 | ||
| @@ -89,6 +91,7 @@ struct kszphy_priv { | |||
| 89 | static const struct kszphy_type ksz8021_type = { | 91 | static const struct kszphy_type ksz8021_type = { |
| 90 | .led_mode_reg = MII_KSZPHY_CTRL_2, | 92 | .led_mode_reg = MII_KSZPHY_CTRL_2, |
| 91 | .has_broadcast_disable = true, | 93 | .has_broadcast_disable = true, |
| 94 | .has_nand_tree_disable = true, | ||
| 92 | .has_rmii_ref_clk_sel = true, | 95 | .has_rmii_ref_clk_sel = true, |
| 93 | }; | 96 | }; |
| 94 | 97 | ||
| @@ -98,11 +101,13 @@ static const struct kszphy_type ksz8041_type = { | |||
| 98 | 101 | ||
| 99 | static const struct kszphy_type ksz8051_type = { | 102 | static const struct kszphy_type ksz8051_type = { |
| 100 | .led_mode_reg = MII_KSZPHY_CTRL_2, | 103 | .led_mode_reg = MII_KSZPHY_CTRL_2, |
| 104 | .has_nand_tree_disable = true, | ||
| 101 | }; | 105 | }; |
| 102 | 106 | ||
| 103 | static const struct kszphy_type ksz8081_type = { | 107 | static const struct kszphy_type ksz8081_type = { |
| 104 | .led_mode_reg = MII_KSZPHY_CTRL_2, | 108 | .led_mode_reg = MII_KSZPHY_CTRL_2, |
| 105 | .has_broadcast_disable = true, | 109 | .has_broadcast_disable = true, |
| 110 | .has_nand_tree_disable = true, | ||
| 106 | .has_rmii_ref_clk_sel = true, | 111 | .has_rmii_ref_clk_sel = true, |
| 107 | }; | 112 | }; |
| 108 | 113 | ||
| @@ -231,6 +236,26 @@ out: | |||
| 231 | return ret; | 236 | return ret; |
| 232 | } | 237 | } |
| 233 | 238 | ||
| 239 | static int kszphy_nand_tree_disable(struct phy_device *phydev) | ||
| 240 | { | ||
| 241 | int ret; | ||
| 242 | |||
| 243 | ret = phy_read(phydev, MII_KSZPHY_OMSO); | ||
| 244 | if (ret < 0) | ||
| 245 | goto out; | ||
| 246 | |||
| 247 | if (!(ret & KSZPHY_OMSO_NAND_TREE_ON)) | ||
| 248 | return 0; | ||
| 249 | |||
| 250 | ret = phy_write(phydev, MII_KSZPHY_OMSO, | ||
| 251 | ret & ~KSZPHY_OMSO_NAND_TREE_ON); | ||
| 252 | out: | ||
| 253 | if (ret) | ||
| 254 | dev_err(&phydev->dev, "failed to disable NAND tree mode\n"); | ||
| 255 | |||
| 256 | return ret; | ||
| 257 | } | ||
| 258 | |||
| 234 | static int kszphy_config_init(struct phy_device *phydev) | 259 | static int kszphy_config_init(struct phy_device *phydev) |
| 235 | { | 260 | { |
| 236 | struct kszphy_priv *priv = phydev->priv; | 261 | struct kszphy_priv *priv = phydev->priv; |
| @@ -245,6 +270,9 @@ static int kszphy_config_init(struct phy_device *phydev) | |||
| 245 | if (type->has_broadcast_disable) | 270 | if (type->has_broadcast_disable) |
| 246 | kszphy_broadcast_disable(phydev); | 271 | kszphy_broadcast_disable(phydev); |
| 247 | 272 | ||
| 273 | if (type->has_nand_tree_disable) | ||
| 274 | kszphy_nand_tree_disable(phydev); | ||
| 275 | |||
| 248 | if (priv->rmii_ref_clk_sel) { | 276 | if (priv->rmii_ref_clk_sel) { |
| 249 | ret = kszphy_rmii_clk_sel(phydev, priv->rmii_ref_clk_sel_val); | 277 | ret = kszphy_rmii_clk_sel(phydev, priv->rmii_ref_clk_sel_val); |
| 250 | if (ret) { | 278 | if (ret) { |
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 6b8efcabb816..9cdfb3fe9c15 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c | |||
| @@ -914,7 +914,7 @@ static void packetizeRx(struct hso_net *odev, unsigned char *ip_pkt, | |||
| 914 | /* We got no receive buffer. */ | 914 | /* We got no receive buffer. */ |
| 915 | D1("could not allocate memory"); | 915 | D1("could not allocate memory"); |
| 916 | odev->rx_parse_state = WAIT_SYNC; | 916 | odev->rx_parse_state = WAIT_SYNC; |
| 917 | return; | 917 | continue; |
| 918 | } | 918 | } |
| 919 | 919 | ||
| 920 | /* Copy what we got so far. make room for iphdr | 920 | /* Copy what we got so far. make room for iphdr |
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 5980ac6c48dd..438fc6bcaef1 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | #define PLA_RXFIFO_CTRL0 0xc0a0 | 40 | #define PLA_RXFIFO_CTRL0 0xc0a0 |
| 41 | #define PLA_RXFIFO_CTRL1 0xc0a4 | 41 | #define PLA_RXFIFO_CTRL1 0xc0a4 |
| 42 | #define PLA_RXFIFO_CTRL2 0xc0a8 | 42 | #define PLA_RXFIFO_CTRL2 0xc0a8 |
| 43 | #define PLA_DMY_REG0 0xc0b0 | ||
| 43 | #define PLA_FMC 0xc0b4 | 44 | #define PLA_FMC 0xc0b4 |
| 44 | #define PLA_CFG_WOL 0xc0b6 | 45 | #define PLA_CFG_WOL 0xc0b6 |
| 45 | #define PLA_TEREDO_CFG 0xc0bc | 46 | #define PLA_TEREDO_CFG 0xc0bc |
| @@ -90,8 +91,14 @@ | |||
| 90 | #define PLA_BP_7 0xfc36 | 91 | #define PLA_BP_7 0xfc36 |
| 91 | #define PLA_BP_EN 0xfc38 | 92 | #define PLA_BP_EN 0xfc38 |
| 92 | 93 | ||
| 94 | #define USB_USB2PHY 0xb41e | ||
| 95 | #define USB_SSPHYLINK2 0xb428 | ||
| 93 | #define USB_U2P3_CTRL 0xb460 | 96 | #define USB_U2P3_CTRL 0xb460 |
| 97 | #define USB_CSR_DUMMY1 0xb464 | ||
| 98 | #define USB_CSR_DUMMY2 0xb466 | ||
| 94 | #define USB_DEV_STAT 0xb808 | 99 | #define USB_DEV_STAT 0xb808 |
| 100 | #define USB_CONNECT_TIMER 0xcbf8 | ||
| 101 | #define USB_BURST_SIZE 0xcfc0 | ||
| 95 | #define USB_USB_CTRL 0xd406 | 102 | #define USB_USB_CTRL 0xd406 |
| 96 | #define USB_PHY_CTRL 0xd408 | 103 | #define USB_PHY_CTRL 0xd408 |
| 97 | #define USB_TX_AGG 0xd40a | 104 | #define USB_TX_AGG 0xd40a |
| @@ -170,6 +177,9 @@ | |||
| 170 | #define TXFIFO_THR_NORMAL 0x00400008 | 177 | #define TXFIFO_THR_NORMAL 0x00400008 |
| 171 | #define TXFIFO_THR_NORMAL2 0x01000008 | 178 | #define TXFIFO_THR_NORMAL2 0x01000008 |
| 172 | 179 | ||
| 180 | /* PLA_DMY_REG0 */ | ||
| 181 | #define ECM_ALDPS 0x0002 | ||
| 182 | |||
| 173 | /* PLA_FMC */ | 183 | /* PLA_FMC */ |
| 174 | #define FMC_FCR_MCU_EN 0x0001 | 184 | #define FMC_FCR_MCU_EN 0x0001 |
| 175 | 185 | ||
| @@ -289,6 +299,20 @@ | |||
| 289 | /* PLA_BOOT_CTRL */ | 299 | /* PLA_BOOT_CTRL */ |
| 290 | #define AUTOLOAD_DONE 0x0002 | 300 | #define AUTOLOAD_DONE 0x0002 |
| 291 | 301 | ||
| 302 | /* USB_USB2PHY */ | ||
| 303 | #define USB2PHY_SUSPEND 0x0001 | ||
| 304 | #define USB2PHY_L1 0x0002 | ||
| 305 | |||
| 306 | /* USB_SSPHYLINK2 */ | ||
| 307 | #define pwd_dn_scale_mask 0x3ffe | ||
| 308 | #define pwd_dn_scale(x) ((x) << 1) | ||
| 309 | |||
| 310 | /* USB_CSR_DUMMY1 */ | ||
| 311 | #define DYNAMIC_BURST 0x0001 | ||
| 312 | |||
| 313 | /* USB_CSR_DUMMY2 */ | ||
| 314 | #define EP4_FULL_FC 0x0001 | ||
| 315 | |||
| 292 | /* USB_DEV_STAT */ | 316 | /* USB_DEV_STAT */ |
| 293 | #define STAT_SPEED_MASK 0x0006 | 317 | #define STAT_SPEED_MASK 0x0006 |
| 294 | #define STAT_SPEED_HIGH 0x0000 | 318 | #define STAT_SPEED_HIGH 0x0000 |
| @@ -334,9 +358,13 @@ | |||
| 334 | #define TIMER11_EN 0x0001 | 358 | #define TIMER11_EN 0x0001 |
| 335 | 359 | ||
| 336 | /* USB_LPM_CTRL */ | 360 | /* USB_LPM_CTRL */ |
| 361 | /* bit 4 ~ 5: fifo empty boundary */ | ||
| 362 | #define FIFO_EMPTY_1FB 0x30 /* 0x1fb * 64 = 32448 bytes */ | ||
| 363 | /* bit 2 ~ 3: LMP timer */ | ||
| 337 | #define LPM_TIMER_MASK 0x0c | 364 | #define LPM_TIMER_MASK 0x0c |
| 338 | #define LPM_TIMER_500MS 0x04 /* 500 ms */ | 365 | #define LPM_TIMER_500MS 0x04 /* 500 ms */ |
| 339 | #define LPM_TIMER_500US 0x0c /* 500 us */ | 366 | #define LPM_TIMER_500US 0x0c /* 500 us */ |
| 367 | #define ROK_EXIT_LPM 0x02 | ||
| 340 | 368 | ||
| 341 | /* USB_AFE_CTRL2 */ | 369 | /* USB_AFE_CTRL2 */ |
| 342 | #define SEN_VAL_MASK 0xf800 | 370 | #define SEN_VAL_MASK 0xf800 |
| @@ -3230,6 +3258,32 @@ static void r8153_init(struct r8152 *tp) | |||
| 3230 | 3258 | ||
| 3231 | r8153_u2p3en(tp, false); | 3259 | r8153_u2p3en(tp, false); |
| 3232 | 3260 | ||
| 3261 | if (tp->version == RTL_VER_04) { | ||
| 3262 | ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_SSPHYLINK2); | ||
| 3263 | ocp_data &= ~pwd_dn_scale_mask; | ||
| 3264 | ocp_data |= pwd_dn_scale(96); | ||
| 3265 | ocp_write_word(tp, MCU_TYPE_USB, USB_SSPHYLINK2, ocp_data); | ||
| 3266 | |||
| 3267 | ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_USB2PHY); | ||
| 3268 | ocp_data |= USB2PHY_L1 | USB2PHY_SUSPEND; | ||
| 3269 | ocp_write_byte(tp, MCU_TYPE_USB, USB_USB2PHY, ocp_data); | ||
| 3270 | } else if (tp->version == RTL_VER_05) { | ||
| 3271 | ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_DMY_REG0); | ||
| 3272 | ocp_data &= ~ECM_ALDPS; | ||
| 3273 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_DMY_REG0, ocp_data); | ||
| 3274 | |||
| 3275 | ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY1); | ||
| 3276 | if (ocp_read_word(tp, MCU_TYPE_USB, USB_BURST_SIZE) == 0) | ||
| 3277 | ocp_data &= ~DYNAMIC_BURST; | ||
| 3278 | else | ||
| 3279 | ocp_data |= DYNAMIC_BURST; | ||
| 3280 | ocp_write_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY1, ocp_data); | ||
| 3281 | } | ||
| 3282 | |||
| 3283 | ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY2); | ||
| 3284 | ocp_data |= EP4_FULL_FC; | ||
| 3285 | ocp_write_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY2, ocp_data); | ||
| 3286 | |||
| 3233 | ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_WDT11_CTRL); | 3287 | ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_WDT11_CTRL); |
| 3234 | ocp_data &= ~TIMER11_EN; | 3288 | ocp_data &= ~TIMER11_EN; |
| 3235 | ocp_write_word(tp, MCU_TYPE_USB, USB_WDT11_CTRL, ocp_data); | 3289 | ocp_write_word(tp, MCU_TYPE_USB, USB_WDT11_CTRL, ocp_data); |
| @@ -3238,8 +3292,7 @@ static void r8153_init(struct r8152 *tp) | |||
| 3238 | ocp_data &= ~LED_MODE_MASK; | 3292 | ocp_data &= ~LED_MODE_MASK; |
| 3239 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE, ocp_data); | 3293 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE, ocp_data); |
| 3240 | 3294 | ||
| 3241 | ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_LPM_CTRL); | 3295 | ocp_data = FIFO_EMPTY_1FB | ROK_EXIT_LPM; |
| 3242 | ocp_data &= ~LPM_TIMER_MASK; | ||
| 3243 | if (tp->version == RTL_VER_04 && tp->udev->speed != USB_SPEED_SUPER) | 3296 | if (tp->version == RTL_VER_04 && tp->udev->speed != USB_SPEED_SUPER) |
| 3244 | ocp_data |= LPM_TIMER_500MS; | 3297 | ocp_data |= LPM_TIMER_500MS; |
| 3245 | else | 3298 | else |
| @@ -3251,6 +3304,8 @@ static void r8153_init(struct r8152 *tp) | |||
| 3251 | ocp_data |= SEN_VAL_NORMAL | SEL_RXIDLE; | 3304 | ocp_data |= SEN_VAL_NORMAL | SEL_RXIDLE; |
| 3252 | ocp_write_word(tp, MCU_TYPE_USB, USB_AFE_CTRL2, ocp_data); | 3305 | ocp_write_word(tp, MCU_TYPE_USB, USB_AFE_CTRL2, ocp_data); |
| 3253 | 3306 | ||
| 3307 | ocp_write_word(tp, MCU_TYPE_USB, USB_CONNECT_TIMER, 0x0001); | ||
| 3308 | |||
| 3254 | r8153_power_cut_en(tp, false); | 3309 | r8153_power_cut_en(tp, false); |
| 3255 | r8153_u1u2en(tp, true); | 3310 | r8153_u1u2en(tp, true); |
| 3256 | 3311 | ||
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 0e57e862c399..1e0a775ea882 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c | |||
| @@ -555,12 +555,13 @@ static int vxlan_fdb_append(struct vxlan_fdb *f, | |||
| 555 | static struct vxlanhdr *vxlan_gro_remcsum(struct sk_buff *skb, | 555 | static struct vxlanhdr *vxlan_gro_remcsum(struct sk_buff *skb, |
| 556 | unsigned int off, | 556 | unsigned int off, |
| 557 | struct vxlanhdr *vh, size_t hdrlen, | 557 | struct vxlanhdr *vh, size_t hdrlen, |
| 558 | u32 data) | 558 | u32 data, struct gro_remcsum *grc, |
| 559 | bool nopartial) | ||
| 559 | { | 560 | { |
| 560 | size_t start, offset, plen; | 561 | size_t start, offset, plen; |
| 561 | 562 | ||
| 562 | if (skb->remcsum_offload) | 563 | if (skb->remcsum_offload) |
| 563 | return vh; | 564 | return NULL; |
| 564 | 565 | ||
| 565 | if (!NAPI_GRO_CB(skb)->csum_valid) | 566 | if (!NAPI_GRO_CB(skb)->csum_valid) |
| 566 | return NULL; | 567 | return NULL; |
| @@ -579,7 +580,8 @@ static struct vxlanhdr *vxlan_gro_remcsum(struct sk_buff *skb, | |||
| 579 | return NULL; | 580 | return NULL; |
| 580 | } | 581 | } |
| 581 | 582 | ||
| 582 | skb_gro_remcsum_process(skb, (void *)vh + hdrlen, start, offset); | 583 | skb_gro_remcsum_process(skb, (void *)vh + hdrlen, |
| 584 | start, offset, grc, nopartial); | ||
| 583 | 585 | ||
| 584 | skb->remcsum_offload = 1; | 586 | skb->remcsum_offload = 1; |
| 585 | 587 | ||
| @@ -597,6 +599,9 @@ static struct sk_buff **vxlan_gro_receive(struct sk_buff **head, | |||
| 597 | struct vxlan_sock *vs = container_of(uoff, struct vxlan_sock, | 599 | struct vxlan_sock *vs = container_of(uoff, struct vxlan_sock, |
| 598 | udp_offloads); | 600 | udp_offloads); |
| 599 | u32 flags; | 601 | u32 flags; |
| 602 | struct gro_remcsum grc; | ||
| 603 | |||
| 604 | skb_gro_remcsum_init(&grc); | ||
| 600 | 605 | ||
| 601 | off_vx = skb_gro_offset(skb); | 606 | off_vx = skb_gro_offset(skb); |
| 602 | hlen = off_vx + sizeof(*vh); | 607 | hlen = off_vx + sizeof(*vh); |
| @@ -614,7 +619,9 @@ static struct sk_buff **vxlan_gro_receive(struct sk_buff **head, | |||
| 614 | 619 | ||
| 615 | if ((flags & VXLAN_HF_RCO) && (vs->flags & VXLAN_F_REMCSUM_RX)) { | 620 | if ((flags & VXLAN_HF_RCO) && (vs->flags & VXLAN_F_REMCSUM_RX)) { |
| 616 | vh = vxlan_gro_remcsum(skb, off_vx, vh, sizeof(struct vxlanhdr), | 621 | vh = vxlan_gro_remcsum(skb, off_vx, vh, sizeof(struct vxlanhdr), |
| 617 | ntohl(vh->vx_vni)); | 622 | ntohl(vh->vx_vni), &grc, |
| 623 | !!(vs->flags & | ||
| 624 | VXLAN_F_REMCSUM_NOPARTIAL)); | ||
| 618 | 625 | ||
| 619 | if (!vh) | 626 | if (!vh) |
| 620 | goto out; | 627 | goto out; |
| @@ -637,6 +644,7 @@ static struct sk_buff **vxlan_gro_receive(struct sk_buff **head, | |||
| 637 | pp = eth_gro_receive(head, skb); | 644 | pp = eth_gro_receive(head, skb); |
| 638 | 645 | ||
| 639 | out: | 646 | out: |
| 647 | skb_gro_remcsum_cleanup(skb, &grc); | ||
| 640 | NAPI_GRO_CB(skb)->flush |= flush; | 648 | NAPI_GRO_CB(skb)->flush |= flush; |
| 641 | 649 | ||
| 642 | return pp; | 650 | return pp; |
| @@ -1150,16 +1158,10 @@ static void vxlan_igmp_leave(struct work_struct *work) | |||
| 1150 | } | 1158 | } |
| 1151 | 1159 | ||
| 1152 | static struct vxlanhdr *vxlan_remcsum(struct sk_buff *skb, struct vxlanhdr *vh, | 1160 | static struct vxlanhdr *vxlan_remcsum(struct sk_buff *skb, struct vxlanhdr *vh, |
| 1153 | size_t hdrlen, u32 data) | 1161 | size_t hdrlen, u32 data, bool nopartial) |
| 1154 | { | 1162 | { |
| 1155 | size_t start, offset, plen; | 1163 | size_t start, offset, plen; |
| 1156 | 1164 | ||
| 1157 | if (skb->remcsum_offload) { | ||
| 1158 | /* Already processed in GRO path */ | ||
| 1159 | skb->remcsum_offload = 0; | ||
| 1160 | return vh; | ||
| 1161 | } | ||
| 1162 | |||
| 1163 | start = (data & VXLAN_RCO_MASK) << VXLAN_RCO_SHIFT; | 1165 | start = (data & VXLAN_RCO_MASK) << VXLAN_RCO_SHIFT; |
| 1164 | offset = start + ((data & VXLAN_RCO_UDP) ? | 1166 | offset = start + ((data & VXLAN_RCO_UDP) ? |
| 1165 | offsetof(struct udphdr, check) : | 1167 | offsetof(struct udphdr, check) : |
| @@ -1172,7 +1174,8 @@ static struct vxlanhdr *vxlan_remcsum(struct sk_buff *skb, struct vxlanhdr *vh, | |||
| 1172 | 1174 | ||
| 1173 | vh = (struct vxlanhdr *)(udp_hdr(skb) + 1); | 1175 | vh = (struct vxlanhdr *)(udp_hdr(skb) + 1); |
| 1174 | 1176 | ||
| 1175 | skb_remcsum_process(skb, (void *)vh + hdrlen, start, offset); | 1177 | skb_remcsum_process(skb, (void *)vh + hdrlen, start, offset, |
| 1178 | nopartial); | ||
| 1176 | 1179 | ||
| 1177 | return vh; | 1180 | return vh; |
| 1178 | } | 1181 | } |
| @@ -1209,7 +1212,8 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) | |||
| 1209 | goto drop; | 1212 | goto drop; |
| 1210 | 1213 | ||
| 1211 | if ((flags & VXLAN_HF_RCO) && (vs->flags & VXLAN_F_REMCSUM_RX)) { | 1214 | if ((flags & VXLAN_HF_RCO) && (vs->flags & VXLAN_F_REMCSUM_RX)) { |
| 1212 | vxh = vxlan_remcsum(skb, vxh, sizeof(struct vxlanhdr), vni); | 1215 | vxh = vxlan_remcsum(skb, vxh, sizeof(struct vxlanhdr), vni, |
| 1216 | !!(vs->flags & VXLAN_F_REMCSUM_NOPARTIAL)); | ||
| 1213 | if (!vxh) | 1217 | if (!vxh) |
| 1214 | goto drop; | 1218 | goto drop; |
| 1215 | 1219 | ||
| @@ -2438,6 +2442,7 @@ static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = { | |||
| 2438 | [IFLA_VXLAN_REMCSUM_TX] = { .type = NLA_U8 }, | 2442 | [IFLA_VXLAN_REMCSUM_TX] = { .type = NLA_U8 }, |
| 2439 | [IFLA_VXLAN_REMCSUM_RX] = { .type = NLA_U8 }, | 2443 | [IFLA_VXLAN_REMCSUM_RX] = { .type = NLA_U8 }, |
| 2440 | [IFLA_VXLAN_GBP] = { .type = NLA_FLAG, }, | 2444 | [IFLA_VXLAN_GBP] = { .type = NLA_FLAG, }, |
| 2445 | [IFLA_VXLAN_REMCSUM_NOPARTIAL] = { .type = NLA_FLAG }, | ||
| 2441 | }; | 2446 | }; |
| 2442 | 2447 | ||
| 2443 | static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[]) | 2448 | static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[]) |
| @@ -2761,6 +2766,9 @@ static int vxlan_newlink(struct net *src_net, struct net_device *dev, | |||
| 2761 | if (data[IFLA_VXLAN_GBP]) | 2766 | if (data[IFLA_VXLAN_GBP]) |
| 2762 | vxlan->flags |= VXLAN_F_GBP; | 2767 | vxlan->flags |= VXLAN_F_GBP; |
| 2763 | 2768 | ||
| 2769 | if (data[IFLA_VXLAN_REMCSUM_NOPARTIAL]) | ||
| 2770 | vxlan->flags |= VXLAN_F_REMCSUM_NOPARTIAL; | ||
| 2771 | |||
| 2764 | if (vxlan_find_vni(src_net, vni, use_ipv6 ? AF_INET6 : AF_INET, | 2772 | if (vxlan_find_vni(src_net, vni, use_ipv6 ? AF_INET6 : AF_INET, |
| 2765 | vxlan->dst_port, vxlan->flags)) { | 2773 | vxlan->dst_port, vxlan->flags)) { |
| 2766 | pr_info("duplicate VNI %u\n", vni); | 2774 | pr_info("duplicate VNI %u\n", vni); |
| @@ -2910,6 +2918,10 @@ static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev) | |||
| 2910 | nla_put_flag(skb, IFLA_VXLAN_GBP)) | 2918 | nla_put_flag(skb, IFLA_VXLAN_GBP)) |
| 2911 | goto nla_put_failure; | 2919 | goto nla_put_failure; |
| 2912 | 2920 | ||
| 2921 | if (vxlan->flags & VXLAN_F_REMCSUM_NOPARTIAL && | ||
| 2922 | nla_put_flag(skb, IFLA_VXLAN_REMCSUM_NOPARTIAL)) | ||
| 2923 | goto nla_put_failure; | ||
| 2924 | |||
| 2913 | return 0; | 2925 | return 0; |
| 2914 | 2926 | ||
| 2915 | nla_put_failure: | 2927 | nla_put_failure: |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 2c9088633ec6..ccbdb05b28cd 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
| @@ -127,7 +127,7 @@ static const struct bcma_device_id b43_bcma_tbl[] = { | |||
| 127 | BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1E, BCMA_ANY_CLASS), | 127 | BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1E, BCMA_ANY_CLASS), |
| 128 | BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x28, BCMA_ANY_CLASS), | 128 | BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x28, BCMA_ANY_CLASS), |
| 129 | BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x2A, BCMA_ANY_CLASS), | 129 | BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x2A, BCMA_ANY_CLASS), |
| 130 | BCMA_CORETABLE_END | 130 | {}, |
| 131 | }; | 131 | }; |
| 132 | MODULE_DEVICE_TABLE(bcma, b43_bcma_tbl); | 132 | MODULE_DEVICE_TABLE(bcma, b43_bcma_tbl); |
| 133 | #endif | 133 | #endif |
| @@ -144,7 +144,7 @@ static const struct ssb_device_id b43_ssb_tbl[] = { | |||
| 144 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 13), | 144 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 13), |
| 145 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 15), | 145 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 15), |
| 146 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 16), | 146 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 16), |
| 147 | SSB_DEVTABLE_END | 147 | {}, |
| 148 | }; | 148 | }; |
| 149 | MODULE_DEVICE_TABLE(ssb, b43_ssb_tbl); | 149 | MODULE_DEVICE_TABLE(ssb, b43_ssb_tbl); |
| 150 | #endif | 150 | #endif |
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 1aec2146a2bf..4e58c0069830 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
| @@ -86,7 +86,7 @@ MODULE_PARM_DESC(fwpostfix, "Postfix for the firmware files to load."); | |||
| 86 | static const struct ssb_device_id b43legacy_ssb_tbl[] = { | 86 | static const struct ssb_device_id b43legacy_ssb_tbl[] = { |
| 87 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 2), | 87 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 2), |
| 88 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 4), | 88 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 4), |
| 89 | SSB_DEVTABLE_END | 89 | {}, |
| 90 | }; | 90 | }; |
| 91 | MODULE_DEVICE_TABLE(ssb, b43legacy_ssb_tbl); | 91 | MODULE_DEVICE_TABLE(ssb, b43legacy_ssb_tbl); |
| 92 | 92 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index f95b52442281..48135063347e 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | |||
| @@ -99,7 +99,7 @@ static struct bcma_device_id brcms_coreid_table[] = { | |||
| 99 | BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 17, BCMA_ANY_CLASS), | 99 | BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 17, BCMA_ANY_CLASS), |
| 100 | BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 23, BCMA_ANY_CLASS), | 100 | BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 23, BCMA_ANY_CLASS), |
| 101 | BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 24, BCMA_ANY_CLASS), | 101 | BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 24, BCMA_ANY_CLASS), |
| 102 | BCMA_CORETABLE_END | 102 | {}, |
| 103 | }; | 103 | }; |
| 104 | MODULE_DEVICE_TABLE(bcma, brcms_coreid_table); | 104 | MODULE_DEVICE_TABLE(bcma, brcms_coreid_table); |
| 105 | 105 | ||
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index ec456f0d972e..a62170ea0481 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c | |||
| @@ -822,11 +822,8 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) | |||
| 822 | 822 | ||
| 823 | /* get a new skb - if fail, old one will be reused */ | 823 | /* get a new skb - if fail, old one will be reused */ |
| 824 | new_skb = dev_alloc_skb(rtlpci->rxbuffersize); | 824 | new_skb = dev_alloc_skb(rtlpci->rxbuffersize); |
| 825 | if (unlikely(!new_skb)) { | 825 | if (unlikely(!new_skb)) |
| 826 | pr_err("Allocation of new skb failed in %s\n", | ||
| 827 | __func__); | ||
| 828 | goto no_new; | 826 | goto no_new; |
| 829 | } | ||
| 830 | if (rtlpriv->use_new_trx_flow) { | 827 | if (rtlpriv->use_new_trx_flow) { |
| 831 | buffer_desc = | 828 | buffer_desc = |
| 832 | &rtlpci->rx_ring[rxring_idx].buffer_desc | 829 | &rtlpci->rx_ring[rxring_idx].buffer_desc |
diff --git a/drivers/scsi/csiostor/csio_init.c b/drivers/scsi/csiostor/csio_init.c index 9b9794d42ffe..d9631e15f7b5 100644 --- a/drivers/scsi/csiostor/csio_init.c +++ b/drivers/scsi/csiostor/csio_init.c | |||
| @@ -113,12 +113,9 @@ static const struct file_operations csio_mem_debugfs_fops = { | |||
| 113 | void csio_add_debugfs_mem(struct csio_hw *hw, const char *name, | 113 | void csio_add_debugfs_mem(struct csio_hw *hw, const char *name, |
| 114 | unsigned int idx, unsigned int size_mb) | 114 | unsigned int idx, unsigned int size_mb) |
| 115 | { | 115 | { |
| 116 | struct dentry *de; | 116 | debugfs_create_file_size(name, S_IRUSR, hw->debugfs_root, |
| 117 | 117 | (void *)hw + idx, &csio_mem_debugfs_fops, | |
| 118 | de = debugfs_create_file(name, S_IRUSR, hw->debugfs_root, | 118 | size_mb << 20); |
| 119 | (void *)hw + idx, &csio_mem_debugfs_fops); | ||
| 120 | if (de && de->d_inode) | ||
| 121 | de->d_inode->i_size = size_mb << 20; | ||
| 122 | } | 119 | } |
| 123 | 120 | ||
| 124 | static int csio_setup_debugfs(struct csio_hw *hw) | 121 | static int csio_setup_debugfs(struct csio_hw *hw) |
diff --git a/drivers/spi/spi-bcm53xx.c b/drivers/spi/spi-bcm53xx.c index 17b34cbadc03..3fb91c81015a 100644 --- a/drivers/spi/spi-bcm53xx.c +++ b/drivers/spi/spi-bcm53xx.c | |||
| @@ -216,7 +216,7 @@ static struct spi_board_info bcm53xx_info = { | |||
| 216 | 216 | ||
| 217 | static const struct bcma_device_id bcm53xxspi_bcma_tbl[] = { | 217 | static const struct bcma_device_id bcm53xxspi_bcma_tbl[] = { |
| 218 | BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_QSPI, BCMA_ANY_REV, BCMA_ANY_CLASS), | 218 | BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_QSPI, BCMA_ANY_REV, BCMA_ANY_CLASS), |
| 219 | BCMA_CORETABLE_END | 219 | {}, |
| 220 | }; | 220 | }; |
| 221 | MODULE_DEVICE_TABLE(bcma, bcm53xxspi_bcma_tbl); | 221 | MODULE_DEVICE_TABLE(bcma, bcm53xxspi_bcma_tbl); |
| 222 | 222 | ||
diff --git a/drivers/ssb/driver_gige.c b/drivers/ssb/driver_gige.c index 21f71a1581fa..e9734051e3c4 100644 --- a/drivers/ssb/driver_gige.c +++ b/drivers/ssb/driver_gige.c | |||
| @@ -24,7 +24,7 @@ MODULE_LICENSE("GPL"); | |||
| 24 | 24 | ||
| 25 | static const struct ssb_device_id ssb_gige_tbl[] = { | 25 | static const struct ssb_device_id ssb_gige_tbl[] = { |
| 26 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_ETHERNET_GBIT, SSB_ANY_REV), | 26 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_ETHERNET_GBIT, SSB_ANY_REV), |
| 27 | SSB_DEVTABLE_END | 27 | {}, |
| 28 | }; | 28 | }; |
| 29 | /* MODULE_DEVICE_TABLE(ssb, ssb_gige_tbl); */ | 29 | /* MODULE_DEVICE_TABLE(ssb, ssb_gige_tbl); */ |
| 30 | 30 | ||
diff --git a/drivers/staging/lustre/lustre/llite/dcache.c b/drivers/staging/lustre/lustre/llite/dcache.c index 5bb9c85cec81..88614b71cf6d 100644 --- a/drivers/staging/lustre/lustre/llite/dcache.c +++ b/drivers/staging/lustre/lustre/llite/dcache.c | |||
| @@ -263,14 +263,6 @@ void ll_invalidate_aliases(struct inode *inode) | |||
| 263 | dentry, dentry, dentry->d_parent, | 263 | dentry, dentry, dentry->d_parent, |
| 264 | dentry->d_inode, dentry->d_flags); | 264 | dentry->d_inode, dentry->d_flags); |
| 265 | 265 | ||
| 266 | if (unlikely(dentry == dentry->d_sb->s_root)) { | ||
| 267 | CERROR("%s: called on root dentry=%p, fid="DFID"\n", | ||
| 268 | ll_get_fsname(dentry->d_sb, NULL, 0), | ||
| 269 | dentry, PFID(ll_inode2fid(inode))); | ||
| 270 | lustre_dump_dentry(dentry, 1); | ||
| 271 | dump_stack(); | ||
| 272 | } | ||
| 273 | |||
| 274 | d_lustre_invalidate(dentry, 0); | 266 | d_lustre_invalidate(dentry, 0); |
| 275 | } | 267 | } |
| 276 | ll_unlock_dcache(inode); | 268 | ll_unlock_dcache(inode); |
diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 37306e0c7aad..d032c2b086cc 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h | |||
| @@ -816,7 +816,6 @@ int ll_show_options(struct seq_file *seq, struct dentry *dentry); | |||
| 816 | void ll_dirty_page_discard_warn(struct page *page, int ioret); | 816 | void ll_dirty_page_discard_warn(struct page *page, int ioret); |
| 817 | int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, | 817 | int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, |
| 818 | struct super_block *, struct lookup_intent *); | 818 | struct super_block *, struct lookup_intent *); |
| 819 | void lustre_dump_dentry(struct dentry *, int recur); | ||
| 820 | int ll_obd_statfs(struct inode *inode, void *arg); | 819 | int ll_obd_statfs(struct inode *inode, void *arg); |
| 821 | int ll_get_max_mdsize(struct ll_sb_info *sbi, int *max_mdsize); | 820 | int ll_get_max_mdsize(struct ll_sb_info *sbi, int *max_mdsize); |
| 822 | int ll_get_default_mdsize(struct ll_sb_info *sbi, int *default_mdsize); | 821 | int ll_get_default_mdsize(struct ll_sb_info *sbi, int *default_mdsize); |
diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 45aaa1cc56bc..0c1b583a4ea1 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c | |||
| @@ -665,48 +665,6 @@ int ll_get_default_cookiesize(struct ll_sb_info *sbi, int *lmmsize) | |||
| 665 | return rc; | 665 | return rc; |
| 666 | } | 666 | } |
| 667 | 667 | ||
| 668 | static void ll_dump_inode(struct inode *inode) | ||
| 669 | { | ||
| 670 | struct ll_d_hlist_node *tmp; | ||
| 671 | int dentry_count = 0; | ||
| 672 | |||
| 673 | LASSERT(inode != NULL); | ||
| 674 | |||
| 675 | ll_d_hlist_for_each(tmp, &inode->i_dentry) | ||
| 676 | dentry_count++; | ||
| 677 | |||
| 678 | CERROR("inode %p dump: dev=%s ino=%lu mode=%o count=%u, %d dentries\n", | ||
| 679 | inode, ll_i2mdexp(inode)->exp_obd->obd_name, inode->i_ino, | ||
| 680 | inode->i_mode, atomic_read(&inode->i_count), dentry_count); | ||
| 681 | } | ||
| 682 | |||
| 683 | void lustre_dump_dentry(struct dentry *dentry, int recur) | ||
| 684 | { | ||
| 685 | struct list_head *tmp; | ||
| 686 | int subdirs = 0; | ||
| 687 | |||
| 688 | LASSERT(dentry != NULL); | ||
| 689 | |||
| 690 | list_for_each(tmp, &dentry->d_subdirs) | ||
| 691 | subdirs++; | ||
| 692 | |||
| 693 | CERROR("dentry %p dump: name=%pd parent=%pd (%p), inode=%p, count=%u, flags=0x%x, fsdata=%p, %d subdirs\n", | ||
| 694 | dentry, dentry, dentry->d_parent, dentry->d_parent, | ||
| 695 | dentry->d_inode, d_count(dentry), | ||
| 696 | dentry->d_flags, dentry->d_fsdata, subdirs); | ||
| 697 | if (dentry->d_inode != NULL) | ||
| 698 | ll_dump_inode(dentry->d_inode); | ||
| 699 | |||
| 700 | if (recur == 0) | ||
| 701 | return; | ||
| 702 | |||
| 703 | list_for_each(tmp, &dentry->d_subdirs) { | ||
| 704 | struct dentry *d = list_entry(tmp, struct dentry, d_child); | ||
| 705 | |||
| 706 | lustre_dump_dentry(d, recur - 1); | ||
| 707 | } | ||
| 708 | } | ||
| 709 | |||
| 710 | static void client_common_put_super(struct super_block *sb) | 668 | static void client_common_put_super(struct super_block *sb) |
| 711 | { | 669 | { |
| 712 | struct ll_sb_info *sbi = ll_s2sbi(sb); | 670 | struct ll_sb_info *sbi = ll_s2sbi(sb); |
diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index c0410862c2a1..d79cb35dbf8a 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c | |||
| @@ -265,14 +265,17 @@ static void usba_init_debugfs(struct usba_udc *udc) | |||
| 265 | goto err_root; | 265 | goto err_root; |
| 266 | udc->debugfs_root = root; | 266 | udc->debugfs_root = root; |
| 267 | 267 | ||
| 268 | regs = debugfs_create_file("regs", 0400, root, udc, ®s_dbg_fops); | ||
| 269 | if (!regs) | ||
| 270 | goto err_regs; | ||
| 271 | |||
| 272 | regs_resource = platform_get_resource(udc->pdev, IORESOURCE_MEM, | 268 | regs_resource = platform_get_resource(udc->pdev, IORESOURCE_MEM, |
| 273 | CTRL_IOMEM_ID); | 269 | CTRL_IOMEM_ID); |
| 274 | regs->d_inode->i_size = resource_size(regs_resource); | 270 | |
| 275 | udc->debugfs_regs = regs; | 271 | if (regs_resource) { |
| 272 | regs = debugfs_create_file_size("regs", 0400, root, udc, | ||
| 273 | ®s_dbg_fops, | ||
| 274 | resource_size(regs_resource)); | ||
| 275 | if (!regs) | ||
| 276 | goto err_regs; | ||
| 277 | udc->debugfs_regs = regs; | ||
| 278 | } | ||
| 276 | 279 | ||
| 277 | usba_ep_init_debugfs(udc, to_usba_ep(udc->gadget.ep0)); | 280 | usba_ep_init_debugfs(udc, to_usba_ep(udc->gadget.ep0)); |
| 278 | 281 | ||
diff --git a/drivers/usb/host/bcma-hcd.c b/drivers/usb/host/bcma-hcd.c index cd6d0afb6b8f..526cfab41d5f 100644 --- a/drivers/usb/host/bcma-hcd.c +++ b/drivers/usb/host/bcma-hcd.c | |||
| @@ -306,7 +306,7 @@ static int bcma_hcd_resume(struct bcma_device *dev) | |||
| 306 | 306 | ||
| 307 | static const struct bcma_device_id bcma_hcd_table[] = { | 307 | static const struct bcma_device_id bcma_hcd_table[] = { |
| 308 | BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS), | 308 | BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS), |
| 309 | BCMA_CORETABLE_END | 309 | {}, |
| 310 | }; | 310 | }; |
| 311 | MODULE_DEVICE_TABLE(bcma, bcma_hcd_table); | 311 | MODULE_DEVICE_TABLE(bcma, bcma_hcd_table); |
| 312 | 312 | ||
diff --git a/drivers/usb/host/ssb-hcd.c b/drivers/usb/host/ssb-hcd.c index 0196f766df73..ffc32f4b1b1b 100644 --- a/drivers/usb/host/ssb-hcd.c +++ b/drivers/usb/host/ssb-hcd.c | |||
| @@ -251,7 +251,7 @@ static const struct ssb_device_id ssb_hcd_table[] = { | |||
| 251 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV), | 251 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV), |
| 252 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV), | 252 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV), |
| 253 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV), | 253 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV), |
| 254 | SSB_DEVTABLE_END | 254 | {}, |
| 255 | }; | 255 | }; |
| 256 | MODULE_DEVICE_TABLE(ssb, ssb_hcd_table); | 256 | MODULE_DEVICE_TABLE(ssb, ssb_hcd_table); |
| 257 | 257 | ||
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 8dccca9013ed..afa06d28725d 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c | |||
| @@ -528,9 +528,9 @@ static void handle_rx(struct vhost_net *net) | |||
| 528 | .msg_controllen = 0, | 528 | .msg_controllen = 0, |
| 529 | .msg_flags = MSG_DONTWAIT, | 529 | .msg_flags = MSG_DONTWAIT, |
| 530 | }; | 530 | }; |
| 531 | struct virtio_net_hdr_mrg_rxbuf hdr = { | 531 | struct virtio_net_hdr hdr = { |
| 532 | .hdr.flags = 0, | 532 | .flags = 0, |
| 533 | .hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE | 533 | .gso_type = VIRTIO_NET_HDR_GSO_NONE |
| 534 | }; | 534 | }; |
| 535 | size_t total_len = 0; | 535 | size_t total_len = 0; |
| 536 | int err, mergeable; | 536 | int err, mergeable; |
| @@ -539,6 +539,7 @@ static void handle_rx(struct vhost_net *net) | |||
| 539 | size_t vhost_len, sock_len; | 539 | size_t vhost_len, sock_len; |
| 540 | struct socket *sock; | 540 | struct socket *sock; |
| 541 | struct iov_iter fixup; | 541 | struct iov_iter fixup; |
| 542 | __virtio16 num_buffers; | ||
| 542 | 543 | ||
| 543 | mutex_lock(&vq->mutex); | 544 | mutex_lock(&vq->mutex); |
| 544 | sock = vq->private_data; | 545 | sock = vq->private_data; |
| @@ -616,9 +617,9 @@ static void handle_rx(struct vhost_net *net) | |||
| 616 | } | 617 | } |
| 617 | /* TODO: Should check and handle checksum. */ | 618 | /* TODO: Should check and handle checksum. */ |
| 618 | 619 | ||
| 619 | hdr.num_buffers = cpu_to_vhost16(vq, headcount); | 620 | num_buffers = cpu_to_vhost16(vq, headcount); |
| 620 | if (likely(mergeable) && | 621 | if (likely(mergeable) && |
| 621 | copy_to_iter(&hdr.num_buffers, 2, &fixup) != 2) { | 622 | copy_to_iter(&num_buffers, 2, &fixup) != 2) { |
| 622 | vq_err(vq, "Failed num_buffers write"); | 623 | vq_err(vq, "Failed num_buffers write"); |
| 623 | vhost_discard_vq_desc(vq, headcount); | 624 | vhost_discard_vq_desc(vq, headcount); |
| 624 | break; | 625 | break; |
diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt index c055d56ec63d..270c48148f79 100644 --- a/fs/Kconfig.binfmt +++ b/fs/Kconfig.binfmt | |||
| @@ -149,13 +149,6 @@ config BINFMT_EM86 | |||
| 149 | later load the module when you want to use a Linux/Intel binary. The | 149 | later load the module when you want to use a Linux/Intel binary. The |
| 150 | module will be called binfmt_em86. If unsure, say Y. | 150 | module will be called binfmt_em86. If unsure, say Y. |
| 151 | 151 | ||
| 152 | config BINFMT_SOM | ||
| 153 | tristate "Kernel support for SOM binaries" | ||
| 154 | depends on PARISC && HPUX | ||
| 155 | help | ||
| 156 | SOM is a binary executable format inherited from HP/UX. Say | ||
| 157 | Y here to be able to load and execute SOM binaries directly. | ||
| 158 | |||
| 159 | config BINFMT_MISC | 152 | config BINFMT_MISC |
| 160 | tristate "Kernel support for MISC binaries" | 153 | tristate "Kernel support for MISC binaries" |
| 161 | ---help--- | 154 | ---help--- |
diff --git a/fs/Makefile b/fs/Makefile index 0f4635f7c49c..a88ac4838c9e 100644 --- a/fs/Makefile +++ b/fs/Makefile | |||
| @@ -38,7 +38,6 @@ obj-$(CONFIG_BINFMT_SCRIPT) += binfmt_script.o | |||
| 38 | obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o | 38 | obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o |
| 39 | obj-$(CONFIG_COMPAT_BINFMT_ELF) += compat_binfmt_elf.o | 39 | obj-$(CONFIG_COMPAT_BINFMT_ELF) += compat_binfmt_elf.o |
| 40 | obj-$(CONFIG_BINFMT_ELF_FDPIC) += binfmt_elf_fdpic.o | 40 | obj-$(CONFIG_BINFMT_ELF_FDPIC) += binfmt_elf_fdpic.o |
| 41 | obj-$(CONFIG_BINFMT_SOM) += binfmt_som.o | ||
| 42 | obj-$(CONFIG_BINFMT_FLAT) += binfmt_flat.o | 41 | obj-$(CONFIG_BINFMT_FLAT) += binfmt_flat.o |
| 43 | 42 | ||
| 44 | obj-$(CONFIG_FS_MBCACHE) += mbcache.o | 43 | obj-$(CONFIG_FS_MBCACHE) += mbcache.o |
diff --git a/fs/affs/affs.h b/fs/affs/affs.h index ff44ff3ff015..c8764bd7497d 100644 --- a/fs/affs/affs.h +++ b/fs/affs/affs.h | |||
| @@ -30,6 +30,8 @@ | |||
| 30 | #define AFFS_AC_SIZE (AFFS_CACHE_SIZE/sizeof(struct affs_ext_key)/2) | 30 | #define AFFS_AC_SIZE (AFFS_CACHE_SIZE/sizeof(struct affs_ext_key)/2) |
| 31 | #define AFFS_AC_MASK (AFFS_AC_SIZE-1) | 31 | #define AFFS_AC_MASK (AFFS_AC_SIZE-1) |
| 32 | 32 | ||
| 33 | #define AFFSNAMEMAX 30U | ||
| 34 | |||
| 33 | struct affs_ext_key { | 35 | struct affs_ext_key { |
| 34 | u32 ext; /* idx of the extended block */ | 36 | u32 ext; /* idx of the extended block */ |
| 35 | u32 key; /* block number */ | 37 | u32 key; /* block number */ |
diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c index c852f2fa1710..388da1ea815d 100644 --- a/fs/affs/amigaffs.c +++ b/fs/affs/amigaffs.c | |||
| @@ -30,7 +30,7 @@ affs_insert_hash(struct inode *dir, struct buffer_head *bh) | |||
| 30 | ino = bh->b_blocknr; | 30 | ino = bh->b_blocknr; |
| 31 | offset = affs_hash_name(sb, AFFS_TAIL(sb, bh)->name + 1, AFFS_TAIL(sb, bh)->name[0]); | 31 | offset = affs_hash_name(sb, AFFS_TAIL(sb, bh)->name + 1, AFFS_TAIL(sb, bh)->name[0]); |
| 32 | 32 | ||
| 33 | pr_debug("%s(dir=%u, ino=%d)\n", __func__, (u32)dir->i_ino, ino); | 33 | pr_debug("%s(dir=%lu, ino=%d)\n", __func__, dir->i_ino, ino); |
| 34 | 34 | ||
| 35 | dir_bh = affs_bread(sb, dir->i_ino); | 35 | dir_bh = affs_bread(sb, dir->i_ino); |
| 36 | if (!dir_bh) | 36 | if (!dir_bh) |
| @@ -80,8 +80,8 @@ affs_remove_hash(struct inode *dir, struct buffer_head *rem_bh) | |||
| 80 | sb = dir->i_sb; | 80 | sb = dir->i_sb; |
| 81 | rem_ino = rem_bh->b_blocknr; | 81 | rem_ino = rem_bh->b_blocknr; |
| 82 | offset = affs_hash_name(sb, AFFS_TAIL(sb, rem_bh)->name+1, AFFS_TAIL(sb, rem_bh)->name[0]); | 82 | offset = affs_hash_name(sb, AFFS_TAIL(sb, rem_bh)->name+1, AFFS_TAIL(sb, rem_bh)->name[0]); |
| 83 | pr_debug("%s(dir=%d, ino=%d, hashval=%d)\n", | 83 | pr_debug("%s(dir=%lu, ino=%d, hashval=%d)\n", __func__, dir->i_ino, |
| 84 | __func__, (u32)dir->i_ino, rem_ino, offset); | 84 | rem_ino, offset); |
| 85 | 85 | ||
| 86 | bh = affs_bread(sb, dir->i_ino); | 86 | bh = affs_bread(sb, dir->i_ino); |
| 87 | if (!bh) | 87 | if (!bh) |
| @@ -483,11 +483,10 @@ affs_check_name(const unsigned char *name, int len, bool notruncate) | |||
| 483 | { | 483 | { |
| 484 | int i; | 484 | int i; |
| 485 | 485 | ||
| 486 | if (len > 30) { | 486 | if (len > AFFSNAMEMAX) { |
| 487 | if (notruncate) | 487 | if (notruncate) |
| 488 | return -ENAMETOOLONG; | 488 | return -ENAMETOOLONG; |
| 489 | else | 489 | len = AFFSNAMEMAX; |
| 490 | len = 30; | ||
| 491 | } | 490 | } |
| 492 | for (i = 0; i < len; i++) { | 491 | for (i = 0; i < len; i++) { |
| 493 | if (name[i] < ' ' || name[i] == ':' | 492 | if (name[i] < ' ' || name[i] == ':' |
| @@ -508,7 +507,7 @@ affs_check_name(const unsigned char *name, int len, bool notruncate) | |||
| 508 | int | 507 | int |
| 509 | affs_copy_name(unsigned char *bstr, struct dentry *dentry) | 508 | affs_copy_name(unsigned char *bstr, struct dentry *dentry) |
| 510 | { | 509 | { |
| 511 | int len = min(dentry->d_name.len, 30u); | 510 | u32 len = min(dentry->d_name.len, AFFSNAMEMAX); |
| 512 | 511 | ||
| 513 | *bstr++ = len; | 512 | *bstr++ = len; |
| 514 | memcpy(bstr, dentry->d_name.name, len); | 513 | memcpy(bstr, dentry->d_name.name, len); |
diff --git a/fs/affs/bitmap.c b/fs/affs/bitmap.c index c8de51185c23..675148950fed 100644 --- a/fs/affs/bitmap.c +++ b/fs/affs/bitmap.c | |||
| @@ -99,7 +99,6 @@ err_bh_read: | |||
| 99 | 99 | ||
| 100 | err_range: | 100 | err_range: |
| 101 | affs_error(sb, "affs_free_block","Block %u outside partition", block); | 101 | affs_error(sb, "affs_free_block","Block %u outside partition", block); |
| 102 | return; | ||
| 103 | } | 102 | } |
| 104 | 103 | ||
| 105 | /* | 104 | /* |
diff --git a/fs/affs/dir.c b/fs/affs/dir.c index 59f07bec92a6..ac4f318aafba 100644 --- a/fs/affs/dir.c +++ b/fs/affs/dir.c | |||
| @@ -54,8 +54,7 @@ affs_readdir(struct file *file, struct dir_context *ctx) | |||
| 54 | u32 ino; | 54 | u32 ino; |
| 55 | int error = 0; | 55 | int error = 0; |
| 56 | 56 | ||
| 57 | pr_debug("%s(ino=%lu,f_pos=%lx)\n", | 57 | pr_debug("%s(ino=%lu,f_pos=%llx)\n", __func__, inode->i_ino, ctx->pos); |
| 58 | __func__, inode->i_ino, (unsigned long)ctx->pos); | ||
| 59 | 58 | ||
| 60 | if (ctx->pos < 2) { | 59 | if (ctx->pos < 2) { |
| 61 | file->private_data = (void *)0; | 60 | file->private_data = (void *)0; |
| @@ -115,11 +114,11 @@ inside: | |||
| 115 | break; | 114 | break; |
| 116 | } | 115 | } |
| 117 | 116 | ||
| 118 | namelen = min(AFFS_TAIL(sb, fh_bh)->name[0], (u8)30); | 117 | namelen = min(AFFS_TAIL(sb, fh_bh)->name[0], |
| 118 | (u8)AFFSNAMEMAX); | ||
| 119 | name = AFFS_TAIL(sb, fh_bh)->name + 1; | 119 | name = AFFS_TAIL(sb, fh_bh)->name + 1; |
| 120 | pr_debug("readdir(): dir_emit(\"%.*s\", " | 120 | pr_debug("readdir(): dir_emit(\"%.*s\", ino=%u), hash=%d, f_pos=%llx\n", |
| 121 | "ino=%u), hash=%d, f_pos=%x\n", | 121 | namelen, name, ino, hash_pos, ctx->pos); |
| 122 | namelen, name, ino, hash_pos, (u32)ctx->pos); | ||
| 123 | 122 | ||
| 124 | if (!dir_emit(ctx, name, namelen, ino, DT_UNKNOWN)) | 123 | if (!dir_emit(ctx, name, namelen, ino, DT_UNKNOWN)) |
| 125 | goto done; | 124 | goto done; |
diff --git a/fs/affs/file.c b/fs/affs/file.c index 8faa6593ca6d..d2468bf95669 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c | |||
| @@ -180,8 +180,7 @@ affs_get_extblock_slow(struct inode *inode, u32 ext) | |||
| 180 | ext_key = be32_to_cpu(AFFS_TAIL(sb, bh)->extension); | 180 | ext_key = be32_to_cpu(AFFS_TAIL(sb, bh)->extension); |
| 181 | if (ext < AFFS_I(inode)->i_extcnt) | 181 | if (ext < AFFS_I(inode)->i_extcnt) |
| 182 | goto read_ext; | 182 | goto read_ext; |
| 183 | if (ext > AFFS_I(inode)->i_extcnt) | 183 | BUG_ON(ext > AFFS_I(inode)->i_extcnt); |
| 184 | BUG(); | ||
| 185 | bh = affs_alloc_extblock(inode, bh, ext); | 184 | bh = affs_alloc_extblock(inode, bh, ext); |
| 186 | if (IS_ERR(bh)) | 185 | if (IS_ERR(bh)) |
| 187 | return bh; | 186 | return bh; |
| @@ -198,8 +197,7 @@ affs_get_extblock_slow(struct inode *inode, u32 ext) | |||
| 198 | struct buffer_head *prev_bh; | 197 | struct buffer_head *prev_bh; |
| 199 | 198 | ||
| 200 | /* allocate a new extended block */ | 199 | /* allocate a new extended block */ |
| 201 | if (ext > AFFS_I(inode)->i_extcnt) | 200 | BUG_ON(ext > AFFS_I(inode)->i_extcnt); |
| 202 | BUG(); | ||
| 203 | 201 | ||
| 204 | /* get previous extended block */ | 202 | /* get previous extended block */ |
| 205 | prev_bh = affs_get_extblock(inode, ext - 1); | 203 | prev_bh = affs_get_extblock(inode, ext - 1); |
| @@ -299,8 +297,8 @@ affs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh_resul | |||
| 299 | struct buffer_head *ext_bh; | 297 | struct buffer_head *ext_bh; |
| 300 | u32 ext; | 298 | u32 ext; |
| 301 | 299 | ||
| 302 | pr_debug("%s(%u, %lu)\n", | 300 | pr_debug("%s(%lu, %llu)\n", __func__, inode->i_ino, |
| 303 | __func__, (u32)inode->i_ino, (unsigned long)block); | 301 | (unsigned long long)block); |
| 304 | 302 | ||
| 305 | BUG_ON(block > (sector_t)0x7fffffffUL); | 303 | BUG_ON(block > (sector_t)0x7fffffffUL); |
| 306 | 304 | ||
| @@ -330,8 +328,9 @@ affs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh_resul | |||
| 330 | 328 | ||
| 331 | /* store new block */ | 329 | /* store new block */ |
| 332 | if (bh_result->b_blocknr) | 330 | if (bh_result->b_blocknr) |
| 333 | affs_warning(sb, "get_block", "block already set (%lx)", | 331 | affs_warning(sb, "get_block", |
| 334 | (unsigned long)bh_result->b_blocknr); | 332 | "block already set (%llx)", |
| 333 | (unsigned long long)bh_result->b_blocknr); | ||
| 335 | AFFS_BLOCK(sb, ext_bh, block) = cpu_to_be32(blocknr); | 334 | AFFS_BLOCK(sb, ext_bh, block) = cpu_to_be32(blocknr); |
| 336 | AFFS_HEAD(ext_bh)->block_count = cpu_to_be32(block + 1); | 335 | AFFS_HEAD(ext_bh)->block_count = cpu_to_be32(block + 1); |
| 337 | affs_adjust_checksum(ext_bh, blocknr - bh_result->b_blocknr + 1); | 336 | affs_adjust_checksum(ext_bh, blocknr - bh_result->b_blocknr + 1); |
| @@ -353,8 +352,8 @@ affs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh_resul | |||
| 353 | return 0; | 352 | return 0; |
| 354 | 353 | ||
| 355 | err_big: | 354 | err_big: |
| 356 | affs_error(inode->i_sb, "get_block", "strange block request %d", | 355 | affs_error(inode->i_sb, "get_block", "strange block request %llu", |
| 357 | (int)block); | 356 | (unsigned long long)block); |
| 358 | return -EIO; | 357 | return -EIO; |
| 359 | err_ext: | 358 | err_ext: |
| 360 | // unlock cache | 359 | // unlock cache |
| @@ -399,6 +398,13 @@ affs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, | |||
| 399 | size_t count = iov_iter_count(iter); | 398 | size_t count = iov_iter_count(iter); |
| 400 | ssize_t ret; | 399 | ssize_t ret; |
| 401 | 400 | ||
| 401 | if (rw == WRITE) { | ||
| 402 | loff_t size = offset + count; | ||
| 403 | |||
| 404 | if (AFFS_I(inode)->mmu_private < size) | ||
| 405 | return 0; | ||
| 406 | } | ||
| 407 | |||
| 402 | ret = blockdev_direct_IO(rw, iocb, inode, iter, offset, affs_get_block); | 408 | ret = blockdev_direct_IO(rw, iocb, inode, iter, offset, affs_get_block); |
| 403 | if (ret < 0 && (rw & WRITE)) | 409 | if (ret < 0 && (rw & WRITE)) |
| 404 | affs_write_failed(mapping, offset + count); | 410 | affs_write_failed(mapping, offset + count); |
| @@ -503,7 +509,7 @@ affs_do_readpage_ofs(struct page *page, unsigned to) | |||
| 503 | u32 bidx, boff, bsize; | 509 | u32 bidx, boff, bsize; |
| 504 | u32 tmp; | 510 | u32 tmp; |
| 505 | 511 | ||
| 506 | pr_debug("%s(%u, %ld, 0, %d)\n", __func__, (u32)inode->i_ino, | 512 | pr_debug("%s(%lu, %ld, 0, %d)\n", __func__, inode->i_ino, |
| 507 | page->index, to); | 513 | page->index, to); |
| 508 | BUG_ON(to > PAGE_CACHE_SIZE); | 514 | BUG_ON(to > PAGE_CACHE_SIZE); |
| 509 | kmap(page); | 515 | kmap(page); |
| @@ -539,7 +545,7 @@ affs_extent_file_ofs(struct inode *inode, u32 newsize) | |||
| 539 | u32 size, bsize; | 545 | u32 size, bsize; |
| 540 | u32 tmp; | 546 | u32 tmp; |
| 541 | 547 | ||
| 542 | pr_debug("%s(%u, %d)\n", __func__, (u32)inode->i_ino, newsize); | 548 | pr_debug("%s(%lu, %d)\n", __func__, inode->i_ino, newsize); |
| 543 | bsize = AFFS_SB(sb)->s_data_blksize; | 549 | bsize = AFFS_SB(sb)->s_data_blksize; |
| 544 | bh = NULL; | 550 | bh = NULL; |
| 545 | size = AFFS_I(inode)->mmu_private; | 551 | size = AFFS_I(inode)->mmu_private; |
| @@ -608,7 +614,7 @@ affs_readpage_ofs(struct file *file, struct page *page) | |||
| 608 | u32 to; | 614 | u32 to; |
| 609 | int err; | 615 | int err; |
| 610 | 616 | ||
| 611 | pr_debug("%s(%u, %ld)\n", __func__, (u32)inode->i_ino, page->index); | 617 | pr_debug("%s(%lu, %ld)\n", __func__, inode->i_ino, page->index); |
| 612 | to = PAGE_CACHE_SIZE; | 618 | to = PAGE_CACHE_SIZE; |
| 613 | if (((page->index + 1) << PAGE_CACHE_SHIFT) > inode->i_size) { | 619 | if (((page->index + 1) << PAGE_CACHE_SHIFT) > inode->i_size) { |
| 614 | to = inode->i_size & ~PAGE_CACHE_MASK; | 620 | to = inode->i_size & ~PAGE_CACHE_MASK; |
| @@ -631,8 +637,8 @@ static int affs_write_begin_ofs(struct file *file, struct address_space *mapping | |||
| 631 | pgoff_t index; | 637 | pgoff_t index; |
| 632 | int err = 0; | 638 | int err = 0; |
| 633 | 639 | ||
| 634 | pr_debug("%s(%u, %llu, %llu)\n", __func__, (u32)inode->i_ino, | 640 | pr_debug("%s(%lu, %llu, %llu)\n", __func__, inode->i_ino, pos, |
| 635 | (unsigned long long)pos, (unsigned long long)pos + len); | 641 | pos + len); |
| 636 | if (pos > AFFS_I(inode)->mmu_private) { | 642 | if (pos > AFFS_I(inode)->mmu_private) { |
| 637 | /* XXX: this probably leaves a too-big i_size in case of | 643 | /* XXX: this probably leaves a too-big i_size in case of |
| 638 | * failure. Should really be updating i_size at write_end time | 644 | * failure. Should really be updating i_size at write_end time |
| @@ -681,9 +687,8 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping, | |||
| 681 | * due to write_begin. | 687 | * due to write_begin. |
| 682 | */ | 688 | */ |
| 683 | 689 | ||
| 684 | pr_debug("%s(%u, %llu, %llu)\n", | 690 | pr_debug("%s(%lu, %llu, %llu)\n", __func__, inode->i_ino, pos, |
| 685 | __func__, (u32)inode->i_ino, (unsigned long long)pos, | 691 | pos + len); |
| 686 | (unsigned long long)pos + len); | ||
| 687 | bsize = AFFS_SB(sb)->s_data_blksize; | 692 | bsize = AFFS_SB(sb)->s_data_blksize; |
| 688 | data = page_address(page); | 693 | data = page_address(page); |
| 689 | 694 | ||
| @@ -831,8 +836,8 @@ affs_truncate(struct inode *inode) | |||
| 831 | struct buffer_head *ext_bh; | 836 | struct buffer_head *ext_bh; |
| 832 | int i; | 837 | int i; |
| 833 | 838 | ||
| 834 | pr_debug("truncate(inode=%d, oldsize=%u, newsize=%u)\n", | 839 | pr_debug("truncate(inode=%lu, oldsize=%llu, newsize=%llu)\n", |
| 835 | (u32)inode->i_ino, (u32)AFFS_I(inode)->mmu_private, (u32)inode->i_size); | 840 | inode->i_ino, AFFS_I(inode)->mmu_private, inode->i_size); |
| 836 | 841 | ||
| 837 | last_blk = 0; | 842 | last_blk = 0; |
| 838 | ext = 0; | 843 | ext = 0; |
| @@ -863,7 +868,7 @@ affs_truncate(struct inode *inode) | |||
| 863 | if (IS_ERR(ext_bh)) { | 868 | if (IS_ERR(ext_bh)) { |
| 864 | affs_warning(sb, "truncate", | 869 | affs_warning(sb, "truncate", |
| 865 | "unexpected read error for ext block %u (%ld)", | 870 | "unexpected read error for ext block %u (%ld)", |
| 866 | (unsigned int)ext, PTR_ERR(ext_bh)); | 871 | ext, PTR_ERR(ext_bh)); |
| 867 | return; | 872 | return; |
| 868 | } | 873 | } |
| 869 | if (AFFS_I(inode)->i_lc) { | 874 | if (AFFS_I(inode)->i_lc) { |
| @@ -911,7 +916,7 @@ affs_truncate(struct inode *inode) | |||
| 911 | if (IS_ERR(bh)) { | 916 | if (IS_ERR(bh)) { |
| 912 | affs_warning(sb, "truncate", | 917 | affs_warning(sb, "truncate", |
| 913 | "unexpected read error for last block %u (%ld)", | 918 | "unexpected read error for last block %u (%ld)", |
| 914 | (unsigned int)ext, PTR_ERR(bh)); | 919 | ext, PTR_ERR(bh)); |
| 915 | return; | 920 | return; |
| 916 | } | 921 | } |
| 917 | tmp = be32_to_cpu(AFFS_DATA_HEAD(bh)->next); | 922 | tmp = be32_to_cpu(AFFS_DATA_HEAD(bh)->next); |
diff --git a/fs/affs/inode.c b/fs/affs/inode.c index d0609a282e1d..6f34510449e8 100644 --- a/fs/affs/inode.c +++ b/fs/affs/inode.c | |||
| @@ -13,8 +13,6 @@ | |||
| 13 | #include <linux/gfp.h> | 13 | #include <linux/gfp.h> |
| 14 | #include "affs.h" | 14 | #include "affs.h" |
| 15 | 15 | ||
| 16 | extern const struct inode_operations affs_symlink_inode_operations; | ||
| 17 | |||
| 18 | struct inode *affs_iget(struct super_block *sb, unsigned long ino) | 16 | struct inode *affs_iget(struct super_block *sb, unsigned long ino) |
| 19 | { | 17 | { |
| 20 | struct affs_sb_info *sbi = AFFS_SB(sb); | 18 | struct affs_sb_info *sbi = AFFS_SB(sb); |
| @@ -348,9 +346,8 @@ affs_add_entry(struct inode *dir, struct inode *inode, struct dentry *dentry, s3 | |||
| 348 | u32 block = 0; | 346 | u32 block = 0; |
| 349 | int retval; | 347 | int retval; |
| 350 | 348 | ||
| 351 | pr_debug("%s(dir=%u, inode=%u, \"%pd\", type=%d)\n", | 349 | pr_debug("%s(dir=%lu, inode=%lu, \"%pd\", type=%d)\n", __func__, |
| 352 | __func__, (u32)dir->i_ino, | 350 | dir->i_ino, inode->i_ino, dentry, type); |
| 353 | (u32)inode->i_ino, dentry, type); | ||
| 354 | 351 | ||
| 355 | retval = -EIO; | 352 | retval = -EIO; |
| 356 | bh = affs_bread(sb, inode->i_ino); | 353 | bh = affs_bread(sb, inode->i_ino); |
diff --git a/fs/affs/namei.c b/fs/affs/namei.c index bbc38530e924..ffb7bd82c2a5 100644 --- a/fs/affs/namei.c +++ b/fs/affs/namei.c | |||
| @@ -64,15 +64,16 @@ __affs_hash_dentry(struct qstr *qstr, toupper_t toupper, bool notruncate) | |||
| 64 | { | 64 | { |
| 65 | const u8 *name = qstr->name; | 65 | const u8 *name = qstr->name; |
| 66 | unsigned long hash; | 66 | unsigned long hash; |
| 67 | int i; | 67 | int retval; |
| 68 | u32 len; | ||
| 68 | 69 | ||
| 69 | i = affs_check_name(qstr->name, qstr->len, notruncate); | 70 | retval = affs_check_name(qstr->name, qstr->len, notruncate); |
| 70 | if (i) | 71 | if (retval) |
| 71 | return i; | 72 | return retval; |
| 72 | 73 | ||
| 73 | hash = init_name_hash(); | 74 | hash = init_name_hash(); |
| 74 | i = min(qstr->len, 30u); | 75 | len = min(qstr->len, AFFSNAMEMAX); |
| 75 | for (; i > 0; name++, i--) | 76 | for (; len > 0; name++, len--) |
| 76 | hash = partial_name_hash(toupper(*name), hash); | 77 | hash = partial_name_hash(toupper(*name), hash); |
| 77 | qstr->hash = end_name_hash(hash); | 78 | qstr->hash = end_name_hash(hash); |
| 78 | 79 | ||
| @@ -114,10 +115,10 @@ static inline int __affs_compare_dentry(unsigned int len, | |||
| 114 | * If the names are longer than the allowed 30 chars, | 115 | * If the names are longer than the allowed 30 chars, |
| 115 | * the excess is ignored, so their length may differ. | 116 | * the excess is ignored, so their length may differ. |
| 116 | */ | 117 | */ |
| 117 | if (len >= 30) { | 118 | if (len >= AFFSNAMEMAX) { |
| 118 | if (name->len < 30) | 119 | if (name->len < AFFSNAMEMAX) |
| 119 | return 1; | 120 | return 1; |
| 120 | len = 30; | 121 | len = AFFSNAMEMAX; |
| 121 | } else if (len != name->len) | 122 | } else if (len != name->len) |
| 122 | return 1; | 123 | return 1; |
| 123 | 124 | ||
| @@ -156,10 +157,10 @@ affs_match(struct dentry *dentry, const u8 *name2, toupper_t toupper) | |||
| 156 | const u8 *name = dentry->d_name.name; | 157 | const u8 *name = dentry->d_name.name; |
| 157 | int len = dentry->d_name.len; | 158 | int len = dentry->d_name.len; |
| 158 | 159 | ||
| 159 | if (len >= 30) { | 160 | if (len >= AFFSNAMEMAX) { |
| 160 | if (*name2 < 30) | 161 | if (*name2 < AFFSNAMEMAX) |
| 161 | return 0; | 162 | return 0; |
| 162 | len = 30; | 163 | len = AFFSNAMEMAX; |
| 163 | } else if (len != *name2) | 164 | } else if (len != *name2) |
| 164 | return 0; | 165 | return 0; |
| 165 | 166 | ||
| @@ -173,9 +174,9 @@ int | |||
| 173 | affs_hash_name(struct super_block *sb, const u8 *name, unsigned int len) | 174 | affs_hash_name(struct super_block *sb, const u8 *name, unsigned int len) |
| 174 | { | 175 | { |
| 175 | toupper_t toupper = affs_get_toupper(sb); | 176 | toupper_t toupper = affs_get_toupper(sb); |
| 176 | int hash; | 177 | u32 hash; |
| 177 | 178 | ||
| 178 | hash = len = min(len, 30u); | 179 | hash = len = min(len, AFFSNAMEMAX); |
| 179 | for (; len > 0; len--) | 180 | for (; len > 0; len--) |
| 180 | hash = (hash * 13 + toupper(*name++)) & 0x7ff; | 181 | hash = (hash * 13 + toupper(*name++)) & 0x7ff; |
| 181 | 182 | ||
| @@ -248,9 +249,8 @@ affs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) | |||
| 248 | int | 249 | int |
| 249 | affs_unlink(struct inode *dir, struct dentry *dentry) | 250 | affs_unlink(struct inode *dir, struct dentry *dentry) |
| 250 | { | 251 | { |
| 251 | pr_debug("%s(dir=%d, %lu \"%pd\")\n", | 252 | pr_debug("%s(dir=%lu, %lu \"%pd\")\n", __func__, dir->i_ino, |
| 252 | __func__, (u32)dir->i_ino, dentry->d_inode->i_ino, | 253 | dentry->d_inode->i_ino, dentry); |
| 253 | dentry); | ||
| 254 | 254 | ||
| 255 | return affs_remove_header(dentry); | 255 | return affs_remove_header(dentry); |
| 256 | } | 256 | } |
| @@ -317,9 +317,8 @@ affs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
| 317 | int | 317 | int |
| 318 | affs_rmdir(struct inode *dir, struct dentry *dentry) | 318 | affs_rmdir(struct inode *dir, struct dentry *dentry) |
| 319 | { | 319 | { |
| 320 | pr_debug("%s(dir=%u, %lu \"%pd\")\n", | 320 | pr_debug("%s(dir=%lu, %lu \"%pd\")\n", __func__, dir->i_ino, |
| 321 | __func__, (u32)dir->i_ino, dentry->d_inode->i_ino, | 321 | dentry->d_inode->i_ino, dentry); |
| 322 | dentry); | ||
| 323 | 322 | ||
| 324 | return affs_remove_header(dentry); | 323 | return affs_remove_header(dentry); |
| 325 | } | 324 | } |
| @@ -404,8 +403,7 @@ affs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) | |||
| 404 | { | 403 | { |
| 405 | struct inode *inode = old_dentry->d_inode; | 404 | struct inode *inode = old_dentry->d_inode; |
| 406 | 405 | ||
| 407 | pr_debug("%s(%u, %u, \"%pd\")\n", | 406 | pr_debug("%s(%lu, %lu, \"%pd\")\n", __func__, inode->i_ino, dir->i_ino, |
| 408 | __func__, (u32)inode->i_ino, (u32)dir->i_ino, | ||
| 409 | dentry); | 407 | dentry); |
| 410 | 408 | ||
| 411 | return affs_add_entry(dir, inode, dentry, ST_LINKFILE); | 409 | return affs_add_entry(dir, inode, dentry, ST_LINKFILE); |
| @@ -419,9 +417,8 @@ affs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 419 | struct buffer_head *bh = NULL; | 417 | struct buffer_head *bh = NULL; |
| 420 | int retval; | 418 | int retval; |
| 421 | 419 | ||
| 422 | pr_debug("%s(old=%u,\"%pd\" to new=%u,\"%pd\")\n", | 420 | pr_debug("%s(old=%lu,\"%pd\" to new=%lu,\"%pd\")\n", __func__, |
| 423 | __func__, (u32)old_dir->i_ino, old_dentry, | 421 | old_dir->i_ino, old_dentry, new_dir->i_ino, new_dentry); |
| 424 | (u32)new_dir->i_ino, new_dentry); | ||
| 425 | 422 | ||
| 426 | retval = affs_check_name(new_dentry->d_name.name, | 423 | retval = affs_check_name(new_dentry->d_name.name, |
| 427 | new_dentry->d_name.len, | 424 | new_dentry->d_name.len, |
diff --git a/fs/affs/super.c b/fs/affs/super.c index f754ab68a840..4cf0e9113fb6 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c | |||
| @@ -432,39 +432,39 @@ got_root: | |||
| 432 | sb->s_flags |= MS_RDONLY; | 432 | sb->s_flags |= MS_RDONLY; |
| 433 | } | 433 | } |
| 434 | switch (chksum) { | 434 | switch (chksum) { |
| 435 | case MUFS_FS: | 435 | case MUFS_FS: |
| 436 | case MUFS_INTLFFS: | 436 | case MUFS_INTLFFS: |
| 437 | case MUFS_DCFFS: | 437 | case MUFS_DCFFS: |
| 438 | sbi->s_flags |= SF_MUFS; | 438 | sbi->s_flags |= SF_MUFS; |
| 439 | /* fall thru */ | 439 | /* fall thru */ |
| 440 | case FS_INTLFFS: | 440 | case FS_INTLFFS: |
| 441 | case FS_DCFFS: | 441 | case FS_DCFFS: |
| 442 | sbi->s_flags |= SF_INTL; | 442 | sbi->s_flags |= SF_INTL; |
| 443 | break; | 443 | break; |
| 444 | case MUFS_FFS: | 444 | case MUFS_FFS: |
| 445 | sbi->s_flags |= SF_MUFS; | 445 | sbi->s_flags |= SF_MUFS; |
| 446 | break; | 446 | break; |
| 447 | case FS_FFS: | 447 | case FS_FFS: |
| 448 | break; | 448 | break; |
| 449 | case MUFS_OFS: | 449 | case MUFS_OFS: |
| 450 | sbi->s_flags |= SF_MUFS; | 450 | sbi->s_flags |= SF_MUFS; |
| 451 | /* fall thru */ | 451 | /* fall thru */ |
| 452 | case FS_OFS: | 452 | case FS_OFS: |
| 453 | sbi->s_flags |= SF_OFS; | 453 | sbi->s_flags |= SF_OFS; |
| 454 | sb->s_flags |= MS_NOEXEC; | 454 | sb->s_flags |= MS_NOEXEC; |
| 455 | break; | 455 | break; |
| 456 | case MUFS_DCOFS: | 456 | case MUFS_DCOFS: |
| 457 | case MUFS_INTLOFS: | 457 | case MUFS_INTLOFS: |
| 458 | sbi->s_flags |= SF_MUFS; | 458 | sbi->s_flags |= SF_MUFS; |
| 459 | case FS_DCOFS: | 459 | case FS_DCOFS: |
| 460 | case FS_INTLOFS: | 460 | case FS_INTLOFS: |
| 461 | sbi->s_flags |= SF_INTL | SF_OFS; | 461 | sbi->s_flags |= SF_INTL | SF_OFS; |
| 462 | sb->s_flags |= MS_NOEXEC; | 462 | sb->s_flags |= MS_NOEXEC; |
| 463 | break; | 463 | break; |
| 464 | default: | 464 | default: |
| 465 | pr_err("Unknown filesystem on device %s: %08X\n", | 465 | pr_err("Unknown filesystem on device %s: %08X\n", |
| 466 | sb->s_id, chksum); | 466 | sb->s_id, chksum); |
| 467 | return -EINVAL; | 467 | return -EINVAL; |
| 468 | } | 468 | } |
| 469 | 469 | ||
| 470 | if (mount_flags & SF_VERBOSE) { | 470 | if (mount_flags & SF_VERBOSE) { |
| @@ -584,7 +584,7 @@ affs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
| 584 | buf->f_bavail = free; | 584 | buf->f_bavail = free; |
| 585 | buf->f_fsid.val[0] = (u32)id; | 585 | buf->f_fsid.val[0] = (u32)id; |
| 586 | buf->f_fsid.val[1] = (u32)(id >> 32); | 586 | buf->f_fsid.val[1] = (u32)(id >> 32); |
| 587 | buf->f_namelen = 30; | 587 | buf->f_namelen = AFFSNAMEMAX; |
| 588 | return 0; | 588 | return 0; |
| 589 | } | 589 | } |
| 590 | 590 | ||
| @@ -602,6 +602,7 @@ static void affs_kill_sb(struct super_block *sb) | |||
| 602 | affs_free_bitmap(sb); | 602 | affs_free_bitmap(sb); |
| 603 | affs_brelse(sbi->s_root_bh); | 603 | affs_brelse(sbi->s_root_bh); |
| 604 | kfree(sbi->s_prefix); | 604 | kfree(sbi->s_prefix); |
| 605 | mutex_destroy(&sbi->s_bmlock); | ||
| 605 | kfree(sbi); | 606 | kfree(sbi); |
| 606 | } | 607 | } |
| 607 | } | 608 | } |
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index edf47774b03d..e089f1985fca 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c | |||
| @@ -274,9 +274,9 @@ more: | |||
| 274 | static struct inode * | 274 | static struct inode * |
| 275 | befs_alloc_inode(struct super_block *sb) | 275 | befs_alloc_inode(struct super_block *sb) |
| 276 | { | 276 | { |
| 277 | struct befs_inode_info *bi; | 277 | struct befs_inode_info *bi; |
| 278 | bi = (struct befs_inode_info *)kmem_cache_alloc(befs_inode_cachep, | 278 | |
| 279 | GFP_KERNEL); | 279 | bi = kmem_cache_alloc(befs_inode_cachep, GFP_KERNEL); |
| 280 | if (!bi) | 280 | if (!bi) |
| 281 | return NULL; | 281 | return NULL; |
| 282 | return &bi->vfs_inode; | 282 | return &bi->vfs_inode; |
diff --git a/fs/binfmt_som.c b/fs/binfmt_som.c deleted file mode 100644 index 4e00ed68d4a6..000000000000 --- a/fs/binfmt_som.c +++ /dev/null | |||
| @@ -1,299 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * linux/fs/binfmt_som.c | ||
| 3 | * | ||
| 4 | * These are the functions used to load SOM format executables as used | ||
| 5 | * by HP-UX. | ||
| 6 | * | ||
| 7 | * Copyright 1999 Matthew Wilcox <willy@bofh.ai> | ||
| 8 | * based on binfmt_elf which is | ||
| 9 | * Copyright 1993, 1994: Eric Youngdale (ericy@cais.com). | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/module.h> | ||
| 13 | |||
| 14 | #include <linux/fs.h> | ||
| 15 | #include <linux/stat.h> | ||
| 16 | #include <linux/sched.h> | ||
| 17 | #include <linux/mm.h> | ||
| 18 | #include <linux/mman.h> | ||
| 19 | #include <linux/errno.h> | ||
| 20 | #include <linux/signal.h> | ||
| 21 | #include <linux/binfmts.h> | ||
| 22 | #include <linux/som.h> | ||
| 23 | #include <linux/string.h> | ||
| 24 | #include <linux/file.h> | ||
| 25 | #include <linux/fcntl.h> | ||
| 26 | #include <linux/ptrace.h> | ||
| 27 | #include <linux/slab.h> | ||
| 28 | #include <linux/shm.h> | ||
| 29 | #include <linux/personality.h> | ||
| 30 | #include <linux/init.h> | ||
| 31 | |||
| 32 | #include <asm/uaccess.h> | ||
| 33 | #include <asm/pgtable.h> | ||
| 34 | |||
| 35 | |||
| 36 | #include <linux/elf.h> | ||
| 37 | |||
| 38 | static int load_som_binary(struct linux_binprm * bprm); | ||
| 39 | static int load_som_library(struct file *); | ||
| 40 | |||
| 41 | /* | ||
| 42 | * If we don't support core dumping, then supply a NULL so we | ||
| 43 | * don't even try. | ||
| 44 | */ | ||
| 45 | #if 0 | ||
| 46 | static int som_core_dump(struct coredump_params *cprm); | ||
| 47 | #else | ||
| 48 | #define som_core_dump NULL | ||
| 49 | #endif | ||
| 50 | |||
| 51 | #define SOM_PAGESTART(_v) ((_v) & ~(unsigned long)(SOM_PAGESIZE-1)) | ||
| 52 | #define SOM_PAGEOFFSET(_v) ((_v) & (SOM_PAGESIZE-1)) | ||
| 53 | #define SOM_PAGEALIGN(_v) (((_v) + SOM_PAGESIZE - 1) & ~(SOM_PAGESIZE - 1)) | ||
| 54 | |||
| 55 | static struct linux_binfmt som_format = { | ||
| 56 | .module = THIS_MODULE, | ||
| 57 | .load_binary = load_som_binary, | ||
| 58 | .load_shlib = load_som_library, | ||
| 59 | .core_dump = som_core_dump, | ||
| 60 | .min_coredump = SOM_PAGESIZE | ||
| 61 | }; | ||
| 62 | |||
| 63 | /* | ||
| 64 | * create_som_tables() parses the env- and arg-strings in new user | ||
| 65 | * memory and creates the pointer tables from them, and puts their | ||
| 66 | * addresses on the "stack", returning the new stack pointer value. | ||
| 67 | */ | ||
| 68 | static void create_som_tables(struct linux_binprm *bprm) | ||
| 69 | { | ||
| 70 | char **argv, **envp; | ||
| 71 | int argc = bprm->argc; | ||
| 72 | int envc = bprm->envc; | ||
| 73 | unsigned long p; | ||
| 74 | unsigned long *sp; | ||
| 75 | |||
| 76 | /* Word-align the stack pointer */ | ||
| 77 | sp = (unsigned long *)((bprm->p + 3) & ~3); | ||
| 78 | |||
| 79 | envp = (char **) sp; | ||
| 80 | sp += envc + 1; | ||
| 81 | argv = (char **) sp; | ||
| 82 | sp += argc + 1; | ||
| 83 | |||
| 84 | __put_user((unsigned long) envp,++sp); | ||
| 85 | __put_user((unsigned long) argv,++sp); | ||
| 86 | |||
| 87 | __put_user(argc, ++sp); | ||
| 88 | |||
| 89 | bprm->p = (unsigned long) sp; | ||
| 90 | |||
| 91 | p = current->mm->arg_start; | ||
| 92 | while (argc-- > 0) { | ||
| 93 | __put_user((char *)p,argv++); | ||
| 94 | p += strlen_user((char *)p); | ||
| 95 | } | ||
| 96 | __put_user(NULL, argv); | ||
| 97 | current->mm->arg_end = current->mm->env_start = p; | ||
| 98 | while (envc-- > 0) { | ||
| 99 | __put_user((char *)p,envp++); | ||
| 100 | p += strlen_user((char *)p); | ||
| 101 | } | ||
| 102 | __put_user(NULL, envp); | ||
| 103 | current->mm->env_end = p; | ||
| 104 | } | ||
| 105 | |||
| 106 | static int check_som_header(struct som_hdr *som_ex) | ||
| 107 | { | ||
| 108 | int *buf = (int *)som_ex; | ||
| 109 | int i, ck; | ||
| 110 | |||
| 111 | if (som_ex->system_id != SOM_SID_PARISC_1_0 && | ||
| 112 | som_ex->system_id != SOM_SID_PARISC_1_1 && | ||
| 113 | som_ex->system_id != SOM_SID_PARISC_2_0) | ||
| 114 | return -ENOEXEC; | ||
| 115 | |||
| 116 | if (som_ex->a_magic != SOM_EXEC_NONSHARE && | ||
| 117 | som_ex->a_magic != SOM_EXEC_SHARE && | ||
| 118 | som_ex->a_magic != SOM_EXEC_DEMAND) | ||
| 119 | return -ENOEXEC; | ||
| 120 | |||
| 121 | if (som_ex->version_id != SOM_ID_OLD && | ||
| 122 | som_ex->version_id != SOM_ID_NEW) | ||
| 123 | return -ENOEXEC; | ||
| 124 | |||
| 125 | ck = 0; | ||
| 126 | for (i=0; i<32; i++) | ||
| 127 | ck ^= buf[i]; | ||
| 128 | if (ck != 0) | ||
| 129 | return -ENOEXEC; | ||
| 130 | |||
| 131 | return 0; | ||
| 132 | } | ||
| 133 | |||
| 134 | static int map_som_binary(struct file *file, | ||
| 135 | const struct som_exec_auxhdr *hpuxhdr) | ||
| 136 | { | ||
| 137 | unsigned long code_start, code_size, data_start, data_size; | ||
| 138 | unsigned long bss_start, som_brk; | ||
| 139 | int retval; | ||
| 140 | int prot = PROT_READ | PROT_EXEC; | ||
| 141 | int flags = MAP_FIXED|MAP_PRIVATE|MAP_DENYWRITE|MAP_EXECUTABLE; | ||
| 142 | |||
| 143 | mm_segment_t old_fs = get_fs(); | ||
| 144 | set_fs(get_ds()); | ||
| 145 | |||
| 146 | code_start = SOM_PAGESTART(hpuxhdr->exec_tmem); | ||
| 147 | code_size = SOM_PAGEALIGN(hpuxhdr->exec_tsize); | ||
| 148 | current->mm->start_code = code_start; | ||
| 149 | current->mm->end_code = code_start + code_size; | ||
| 150 | retval = vm_mmap(file, code_start, code_size, prot, | ||
| 151 | flags, SOM_PAGESTART(hpuxhdr->exec_tfile)); | ||
| 152 | if (retval < 0 && retval > -1024) | ||
| 153 | goto out; | ||
| 154 | |||
| 155 | data_start = SOM_PAGESTART(hpuxhdr->exec_dmem); | ||
| 156 | data_size = SOM_PAGEALIGN(hpuxhdr->exec_dsize); | ||
| 157 | current->mm->start_data = data_start; | ||
| 158 | current->mm->end_data = bss_start = data_start + data_size; | ||
| 159 | retval = vm_mmap(file, data_start, data_size, | ||
| 160 | prot | PROT_WRITE, flags, | ||
| 161 | SOM_PAGESTART(hpuxhdr->exec_dfile)); | ||
| 162 | if (retval < 0 && retval > -1024) | ||
| 163 | goto out; | ||
| 164 | |||
| 165 | som_brk = bss_start + SOM_PAGEALIGN(hpuxhdr->exec_bsize); | ||
| 166 | current->mm->start_brk = current->mm->brk = som_brk; | ||
| 167 | retval = vm_mmap(NULL, bss_start, som_brk - bss_start, | ||
| 168 | prot | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, 0); | ||
| 169 | if (retval > 0 || retval < -1024) | ||
| 170 | retval = 0; | ||
| 171 | out: | ||
| 172 | set_fs(old_fs); | ||
| 173 | return retval; | ||
| 174 | } | ||
| 175 | |||
| 176 | |||
| 177 | /* | ||
| 178 | * These are the functions used to load SOM executables and shared | ||
| 179 | * libraries. There is no binary dependent code anywhere else. | ||
| 180 | */ | ||
| 181 | |||
| 182 | static int | ||
| 183 | load_som_binary(struct linux_binprm * bprm) | ||
| 184 | { | ||
| 185 | int retval; | ||
| 186 | unsigned int size; | ||
| 187 | unsigned long som_entry; | ||
| 188 | struct som_hdr *som_ex; | ||
| 189 | struct som_exec_auxhdr *hpuxhdr; | ||
| 190 | struct pt_regs *regs = current_pt_regs(); | ||
| 191 | |||
| 192 | /* Get the exec-header */ | ||
| 193 | som_ex = (struct som_hdr *) bprm->buf; | ||
| 194 | |||
| 195 | retval = check_som_header(som_ex); | ||
| 196 | if (retval != 0) | ||
| 197 | goto out; | ||
| 198 | |||
| 199 | /* Now read in the auxiliary header information */ | ||
| 200 | |||
| 201 | retval = -ENOMEM; | ||
| 202 | size = som_ex->aux_header_size; | ||
| 203 | if (size > SOM_PAGESIZE) | ||
| 204 | goto out; | ||
| 205 | hpuxhdr = kmalloc(size, GFP_KERNEL); | ||
| 206 | if (!hpuxhdr) | ||
| 207 | goto out; | ||
| 208 | |||
| 209 | retval = kernel_read(bprm->file, som_ex->aux_header_location, | ||
| 210 | (char *) hpuxhdr, size); | ||
| 211 | if (retval != size) { | ||
| 212 | if (retval >= 0) | ||
| 213 | retval = -EIO; | ||
| 214 | goto out_free; | ||
| 215 | } | ||
| 216 | |||
| 217 | /* Flush all traces of the currently running executable */ | ||
| 218 | retval = flush_old_exec(bprm); | ||
| 219 | if (retval) | ||
| 220 | goto out_free; | ||
| 221 | |||
| 222 | /* OK, This is the point of no return */ | ||
| 223 | current->personality = PER_HPUX; | ||
| 224 | setup_new_exec(bprm); | ||
| 225 | |||
| 226 | /* Set the task size for HP-UX processes such that | ||
| 227 | * the gateway page is outside the address space. | ||
| 228 | * This can be fixed later, but for now, this is much | ||
| 229 | * easier. | ||
| 230 | */ | ||
| 231 | |||
| 232 | current->thread.task_size = 0xc0000000; | ||
| 233 | |||
| 234 | /* Set map base to allow enough room for hp-ux heap growth */ | ||
| 235 | |||
| 236 | current->thread.map_base = 0x80000000; | ||
| 237 | |||
| 238 | retval = map_som_binary(bprm->file, hpuxhdr); | ||
| 239 | if (retval < 0) | ||
| 240 | goto out_free; | ||
| 241 | |||
| 242 | som_entry = hpuxhdr->exec_entry; | ||
| 243 | kfree(hpuxhdr); | ||
| 244 | |||
| 245 | set_binfmt(&som_format); | ||
| 246 | install_exec_creds(bprm); | ||
| 247 | setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT); | ||
| 248 | |||
| 249 | create_som_tables(bprm); | ||
| 250 | |||
| 251 | current->mm->start_stack = bprm->p; | ||
| 252 | |||
| 253 | #if 0 | ||
| 254 | printk("(start_brk) %08lx\n" , (unsigned long) current->mm->start_brk); | ||
| 255 | printk("(end_code) %08lx\n" , (unsigned long) current->mm->end_code); | ||
| 256 | printk("(start_code) %08lx\n" , (unsigned long) current->mm->start_code); | ||
| 257 | printk("(end_data) %08lx\n" , (unsigned long) current->mm->end_data); | ||
| 258 | printk("(start_stack) %08lx\n" , (unsigned long) current->mm->start_stack); | ||
| 259 | printk("(brk) %08lx\n" , (unsigned long) current->mm->brk); | ||
| 260 | #endif | ||
| 261 | |||
| 262 | map_hpux_gateway_page(current,current->mm); | ||
| 263 | |||
| 264 | start_thread_som(regs, som_entry, bprm->p); | ||
| 265 | return 0; | ||
| 266 | |||
| 267 | /* error cleanup */ | ||
| 268 | out_free: | ||
| 269 | kfree(hpuxhdr); | ||
| 270 | out: | ||
| 271 | return retval; | ||
| 272 | } | ||
| 273 | |||
| 274 | static int load_som_library(struct file *f) | ||
| 275 | { | ||
| 276 | /* No lib support in SOM yet. gizza chance.. */ | ||
| 277 | return -ENOEXEC; | ||
| 278 | } | ||
| 279 | /* Install the SOM loader. | ||
| 280 | * N.B. We *rely* on the table being the right size with the | ||
| 281 | * right number of free slots... | ||
| 282 | */ | ||
| 283 | |||
| 284 | static int __init init_som_binfmt(void) | ||
| 285 | { | ||
| 286 | register_binfmt(&som_format); | ||
| 287 | return 0; | ||
| 288 | } | ||
| 289 | |||
| 290 | static void __exit exit_som_binfmt(void) | ||
| 291 | { | ||
| 292 | /* Remove the SOM loader. */ | ||
| 293 | unregister_binfmt(&som_format); | ||
| 294 | } | ||
| 295 | |||
| 296 | core_initcall(init_som_binfmt); | ||
| 297 | module_exit(exit_som_binfmt); | ||
| 298 | |||
| 299 | MODULE_LICENSE("GPL"); | ||
diff --git a/fs/coda/dir.c b/fs/coda/dir.c index 86c893884eb9..281ee011bb6a 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c | |||
| @@ -28,29 +28,6 @@ | |||
| 28 | 28 | ||
| 29 | #include "coda_int.h" | 29 | #include "coda_int.h" |
| 30 | 30 | ||
| 31 | /* dir inode-ops */ | ||
| 32 | static int coda_create(struct inode *dir, struct dentry *new, umode_t mode, bool excl); | ||
| 33 | static struct dentry *coda_lookup(struct inode *dir, struct dentry *target, unsigned int flags); | ||
| 34 | static int coda_link(struct dentry *old_dentry, struct inode *dir_inode, | ||
| 35 | struct dentry *entry); | ||
| 36 | static int coda_unlink(struct inode *dir_inode, struct dentry *entry); | ||
| 37 | static int coda_symlink(struct inode *dir_inode, struct dentry *entry, | ||
| 38 | const char *symname); | ||
| 39 | static int coda_mkdir(struct inode *dir_inode, struct dentry *entry, umode_t mode); | ||
| 40 | static int coda_rmdir(struct inode *dir_inode, struct dentry *entry); | ||
| 41 | static int coda_rename(struct inode *old_inode, struct dentry *old_dentry, | ||
| 42 | struct inode *new_inode, struct dentry *new_dentry); | ||
| 43 | |||
| 44 | /* dir file-ops */ | ||
| 45 | static int coda_readdir(struct file *file, struct dir_context *ctx); | ||
| 46 | |||
| 47 | /* dentry ops */ | ||
| 48 | static int coda_dentry_revalidate(struct dentry *de, unsigned int flags); | ||
| 49 | static int coda_dentry_delete(const struct dentry *); | ||
| 50 | |||
| 51 | /* support routines */ | ||
| 52 | static int coda_venus_readdir(struct file *, struct dir_context *); | ||
| 53 | |||
| 54 | /* same as fs/bad_inode.c */ | 31 | /* same as fs/bad_inode.c */ |
| 55 | static int coda_return_EIO(void) | 32 | static int coda_return_EIO(void) |
| 56 | { | 33 | { |
| @@ -58,38 +35,6 @@ static int coda_return_EIO(void) | |||
| 58 | } | 35 | } |
| 59 | #define CODA_EIO_ERROR ((void *) (coda_return_EIO)) | 36 | #define CODA_EIO_ERROR ((void *) (coda_return_EIO)) |
| 60 | 37 | ||
| 61 | const struct dentry_operations coda_dentry_operations = | ||
| 62 | { | ||
| 63 | .d_revalidate = coda_dentry_revalidate, | ||
| 64 | .d_delete = coda_dentry_delete, | ||
| 65 | }; | ||
| 66 | |||
| 67 | const struct inode_operations coda_dir_inode_operations = | ||
| 68 | { | ||
| 69 | .create = coda_create, | ||
| 70 | .lookup = coda_lookup, | ||
| 71 | .link = coda_link, | ||
| 72 | .unlink = coda_unlink, | ||
| 73 | .symlink = coda_symlink, | ||
| 74 | .mkdir = coda_mkdir, | ||
| 75 | .rmdir = coda_rmdir, | ||
| 76 | .mknod = CODA_EIO_ERROR, | ||
| 77 | .rename = coda_rename, | ||
| 78 | .permission = coda_permission, | ||
| 79 | .getattr = coda_getattr, | ||
| 80 | .setattr = coda_setattr, | ||
| 81 | }; | ||
| 82 | |||
| 83 | const struct file_operations coda_dir_operations = { | ||
| 84 | .llseek = generic_file_llseek, | ||
| 85 | .read = generic_read_dir, | ||
| 86 | .iterate = coda_readdir, | ||
| 87 | .open = coda_open, | ||
| 88 | .release = coda_release, | ||
| 89 | .fsync = coda_fsync, | ||
| 90 | }; | ||
| 91 | |||
| 92 | |||
| 93 | /* inode operations for directories */ | 38 | /* inode operations for directories */ |
| 94 | /* access routines: lookup, readlink, permission */ | 39 | /* access routines: lookup, readlink, permission */ |
| 95 | static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, unsigned int flags) | 40 | static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, unsigned int flags) |
| @@ -374,33 +319,6 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 374 | return error; | 319 | return error; |
| 375 | } | 320 | } |
| 376 | 321 | ||
| 377 | |||
| 378 | /* file operations for directories */ | ||
| 379 | static int coda_readdir(struct file *coda_file, struct dir_context *ctx) | ||
| 380 | { | ||
| 381 | struct coda_file_info *cfi; | ||
| 382 | struct file *host_file; | ||
| 383 | int ret; | ||
| 384 | |||
| 385 | cfi = CODA_FTOC(coda_file); | ||
| 386 | BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC); | ||
| 387 | host_file = cfi->cfi_container; | ||
| 388 | |||
| 389 | if (host_file->f_op->iterate) { | ||
| 390 | struct inode *host_inode = file_inode(host_file); | ||
| 391 | mutex_lock(&host_inode->i_mutex); | ||
| 392 | ret = -ENOENT; | ||
| 393 | if (!IS_DEADDIR(host_inode)) { | ||
| 394 | ret = host_file->f_op->iterate(host_file, ctx); | ||
| 395 | file_accessed(host_file); | ||
| 396 | } | ||
| 397 | mutex_unlock(&host_inode->i_mutex); | ||
| 398 | return ret; | ||
| 399 | } | ||
| 400 | /* Venus: we must read Venus dirents from a file */ | ||
| 401 | return coda_venus_readdir(coda_file, ctx); | ||
| 402 | } | ||
| 403 | |||
| 404 | static inline unsigned int CDT2DT(unsigned char cdt) | 322 | static inline unsigned int CDT2DT(unsigned char cdt) |
| 405 | { | 323 | { |
| 406 | unsigned int dt; | 324 | unsigned int dt; |
| @@ -495,6 +413,33 @@ out: | |||
| 495 | return 0; | 413 | return 0; |
| 496 | } | 414 | } |
| 497 | 415 | ||
| 416 | /* file operations for directories */ | ||
| 417 | static int coda_readdir(struct file *coda_file, struct dir_context *ctx) | ||
| 418 | { | ||
| 419 | struct coda_file_info *cfi; | ||
| 420 | struct file *host_file; | ||
| 421 | int ret; | ||
| 422 | |||
| 423 | cfi = CODA_FTOC(coda_file); | ||
| 424 | BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC); | ||
| 425 | host_file = cfi->cfi_container; | ||
| 426 | |||
| 427 | if (host_file->f_op->iterate) { | ||
| 428 | struct inode *host_inode = file_inode(host_file); | ||
| 429 | |||
| 430 | mutex_lock(&host_inode->i_mutex); | ||
| 431 | ret = -ENOENT; | ||
| 432 | if (!IS_DEADDIR(host_inode)) { | ||
| 433 | ret = host_file->f_op->iterate(host_file, ctx); | ||
| 434 | file_accessed(host_file); | ||
| 435 | } | ||
| 436 | mutex_unlock(&host_inode->i_mutex); | ||
| 437 | return ret; | ||
| 438 | } | ||
| 439 | /* Venus: we must read Venus dirents from a file */ | ||
| 440 | return coda_venus_readdir(coda_file, ctx); | ||
| 441 | } | ||
| 442 | |||
| 498 | /* called when a cache lookup succeeds */ | 443 | /* called when a cache lookup succeeds */ |
| 499 | static int coda_dentry_revalidate(struct dentry *de, unsigned int flags) | 444 | static int coda_dentry_revalidate(struct dentry *de, unsigned int flags) |
| 500 | { | 445 | { |
| @@ -603,3 +548,32 @@ int coda_revalidate_inode(struct inode *inode) | |||
| 603 | } | 548 | } |
| 604 | return 0; | 549 | return 0; |
| 605 | } | 550 | } |
| 551 | |||
| 552 | const struct dentry_operations coda_dentry_operations = { | ||
| 553 | .d_revalidate = coda_dentry_revalidate, | ||
| 554 | .d_delete = coda_dentry_delete, | ||
| 555 | }; | ||
| 556 | |||
| 557 | const struct inode_operations coda_dir_inode_operations = { | ||
| 558 | .create = coda_create, | ||
| 559 | .lookup = coda_lookup, | ||
| 560 | .link = coda_link, | ||
| 561 | .unlink = coda_unlink, | ||
| 562 | .symlink = coda_symlink, | ||
| 563 | .mkdir = coda_mkdir, | ||
| 564 | .rmdir = coda_rmdir, | ||
| 565 | .mknod = CODA_EIO_ERROR, | ||
| 566 | .rename = coda_rename, | ||
| 567 | .permission = coda_permission, | ||
| 568 | .getattr = coda_getattr, | ||
| 569 | .setattr = coda_setattr, | ||
| 570 | }; | ||
| 571 | |||
| 572 | const struct file_operations coda_dir_operations = { | ||
| 573 | .llseek = generic_file_llseek, | ||
| 574 | .read = generic_read_dir, | ||
| 575 | .iterate = coda_readdir, | ||
| 576 | .open = coda_open, | ||
| 577 | .release = coda_release, | ||
| 578 | .fsync = coda_fsync, | ||
| 579 | }; | ||
diff --git a/fs/dcache.c b/fs/dcache.c index 7d34f04ec7aa..dc400fd29f4d 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
| @@ -511,7 +511,7 @@ static void __dentry_kill(struct dentry *dentry) | |||
| 511 | * dentry_iput drops the locks, at which point nobody (except | 511 | * dentry_iput drops the locks, at which point nobody (except |
| 512 | * transient RCU lookups) can reach this dentry. | 512 | * transient RCU lookups) can reach this dentry. |
| 513 | */ | 513 | */ |
| 514 | BUG_ON((int)dentry->d_lockref.count > 0); | 514 | BUG_ON(dentry->d_lockref.count > 0); |
| 515 | this_cpu_dec(nr_dentry); | 515 | this_cpu_dec(nr_dentry); |
| 516 | if (dentry->d_op && dentry->d_op->d_release) | 516 | if (dentry->d_op && dentry->d_op->d_release) |
| 517 | dentry->d_op->d_release(dentry); | 517 | dentry->d_op->d_release(dentry); |
| @@ -564,7 +564,7 @@ static inline struct dentry *lock_parent(struct dentry *dentry) | |||
| 564 | struct dentry *parent = dentry->d_parent; | 564 | struct dentry *parent = dentry->d_parent; |
| 565 | if (IS_ROOT(dentry)) | 565 | if (IS_ROOT(dentry)) |
| 566 | return NULL; | 566 | return NULL; |
| 567 | if (unlikely((int)dentry->d_lockref.count < 0)) | 567 | if (unlikely(dentry->d_lockref.count < 0)) |
| 568 | return NULL; | 568 | return NULL; |
| 569 | if (likely(spin_trylock(&parent->d_lock))) | 569 | if (likely(spin_trylock(&parent->d_lock))) |
| 570 | return parent; | 570 | return parent; |
| @@ -593,6 +593,110 @@ again: | |||
| 593 | return parent; | 593 | return parent; |
| 594 | } | 594 | } |
| 595 | 595 | ||
| 596 | /* | ||
| 597 | * Try to do a lockless dput(), and return whether that was successful. | ||
| 598 | * | ||
| 599 | * If unsuccessful, we return false, having already taken the dentry lock. | ||
| 600 | * | ||
| 601 | * The caller needs to hold the RCU read lock, so that the dentry is | ||
| 602 | * guaranteed to stay around even if the refcount goes down to zero! | ||
| 603 | */ | ||
| 604 | static inline bool fast_dput(struct dentry *dentry) | ||
| 605 | { | ||
| 606 | int ret; | ||
| 607 | unsigned int d_flags; | ||
| 608 | |||
| 609 | /* | ||
| 610 | * If we have a d_op->d_delete() operation, we sould not | ||
| 611 | * let the dentry count go to zero, so use "put__or_lock". | ||
| 612 | */ | ||
| 613 | if (unlikely(dentry->d_flags & DCACHE_OP_DELETE)) | ||
| 614 | return lockref_put_or_lock(&dentry->d_lockref); | ||
| 615 | |||
| 616 | /* | ||
| 617 | * .. otherwise, we can try to just decrement the | ||
| 618 | * lockref optimistically. | ||
| 619 | */ | ||
| 620 | ret = lockref_put_return(&dentry->d_lockref); | ||
| 621 | |||
| 622 | /* | ||
| 623 | * If the lockref_put_return() failed due to the lock being held | ||
| 624 | * by somebody else, the fast path has failed. We will need to | ||
| 625 | * get the lock, and then check the count again. | ||
| 626 | */ | ||
| 627 | if (unlikely(ret < 0)) { | ||
| 628 | spin_lock(&dentry->d_lock); | ||
| 629 | if (dentry->d_lockref.count > 1) { | ||
| 630 | dentry->d_lockref.count--; | ||
| 631 | spin_unlock(&dentry->d_lock); | ||
| 632 | return 1; | ||
| 633 | } | ||
| 634 | return 0; | ||
| 635 | } | ||
| 636 | |||
| 637 | /* | ||
| 638 | * If we weren't the last ref, we're done. | ||
| 639 | */ | ||
| 640 | if (ret) | ||
| 641 | return 1; | ||
| 642 | |||
| 643 | /* | ||
| 644 | * Careful, careful. The reference count went down | ||
| 645 | * to zero, but we don't hold the dentry lock, so | ||
| 646 | * somebody else could get it again, and do another | ||
| 647 | * dput(), and we need to not race with that. | ||
| 648 | * | ||
| 649 | * However, there is a very special and common case | ||
| 650 | * where we don't care, because there is nothing to | ||
| 651 | * do: the dentry is still hashed, it does not have | ||
| 652 | * a 'delete' op, and it's referenced and already on | ||
| 653 | * the LRU list. | ||
| 654 | * | ||
| 655 | * NOTE! Since we aren't locked, these values are | ||
| 656 | * not "stable". However, it is sufficient that at | ||
| 657 | * some point after we dropped the reference the | ||
| 658 | * dentry was hashed and the flags had the proper | ||
| 659 | * value. Other dentry users may have re-gotten | ||
| 660 | * a reference to the dentry and change that, but | ||
| 661 | * our work is done - we can leave the dentry | ||
| 662 | * around with a zero refcount. | ||
| 663 | */ | ||
| 664 | smp_rmb(); | ||
| 665 | d_flags = ACCESS_ONCE(dentry->d_flags); | ||
| 666 | d_flags &= DCACHE_REFERENCED | DCACHE_LRU_LIST; | ||
| 667 | |||
| 668 | /* Nothing to do? Dropping the reference was all we needed? */ | ||
| 669 | if (d_flags == (DCACHE_REFERENCED | DCACHE_LRU_LIST) && !d_unhashed(dentry)) | ||
| 670 | return 1; | ||
| 671 | |||
| 672 | /* | ||
| 673 | * Not the fast normal case? Get the lock. We've already decremented | ||
| 674 | * the refcount, but we'll need to re-check the situation after | ||
| 675 | * getting the lock. | ||
| 676 | */ | ||
| 677 | spin_lock(&dentry->d_lock); | ||
| 678 | |||
| 679 | /* | ||
| 680 | * Did somebody else grab a reference to it in the meantime, and | ||
| 681 | * we're no longer the last user after all? Alternatively, somebody | ||
| 682 | * else could have killed it and marked it dead. Either way, we | ||
| 683 | * don't need to do anything else. | ||
| 684 | */ | ||
| 685 | if (dentry->d_lockref.count) { | ||
| 686 | spin_unlock(&dentry->d_lock); | ||
| 687 | return 1; | ||
| 688 | } | ||
| 689 | |||
| 690 | /* | ||
| 691 | * Re-get the reference we optimistically dropped. We hold the | ||
| 692 | * lock, and we just tested that it was zero, so we can just | ||
| 693 | * set it to 1. | ||
| 694 | */ | ||
| 695 | dentry->d_lockref.count = 1; | ||
| 696 | return 0; | ||
| 697 | } | ||
| 698 | |||
| 699 | |||
| 596 | /* | 700 | /* |
| 597 | * This is dput | 701 | * This is dput |
| 598 | * | 702 | * |
| @@ -625,8 +729,14 @@ void dput(struct dentry *dentry) | |||
| 625 | return; | 729 | return; |
| 626 | 730 | ||
| 627 | repeat: | 731 | repeat: |
| 628 | if (lockref_put_or_lock(&dentry->d_lockref)) | 732 | rcu_read_lock(); |
| 733 | if (likely(fast_dput(dentry))) { | ||
| 734 | rcu_read_unlock(); | ||
| 629 | return; | 735 | return; |
| 736 | } | ||
| 737 | |||
| 738 | /* Slow case: now with the dentry lock held */ | ||
| 739 | rcu_read_unlock(); | ||
| 630 | 740 | ||
| 631 | /* Unreachable? Get rid of it */ | 741 | /* Unreachable? Get rid of it */ |
| 632 | if (unlikely(d_unhashed(dentry))) | 742 | if (unlikely(d_unhashed(dentry))) |
| @@ -813,7 +923,7 @@ static void shrink_dentry_list(struct list_head *list) | |||
| 813 | * We found an inuse dentry which was not removed from | 923 | * We found an inuse dentry which was not removed from |
| 814 | * the LRU because of laziness during lookup. Do not free it. | 924 | * the LRU because of laziness during lookup. Do not free it. |
| 815 | */ | 925 | */ |
| 816 | if ((int)dentry->d_lockref.count > 0) { | 926 | if (dentry->d_lockref.count > 0) { |
| 817 | spin_unlock(&dentry->d_lock); | 927 | spin_unlock(&dentry->d_lock); |
| 818 | if (parent) | 928 | if (parent) |
| 819 | spin_unlock(&parent->d_lock); | 929 | spin_unlock(&parent->d_lock); |
| @@ -2191,37 +2301,6 @@ struct dentry *d_hash_and_lookup(struct dentry *dir, struct qstr *name) | |||
| 2191 | } | 2301 | } |
| 2192 | EXPORT_SYMBOL(d_hash_and_lookup); | 2302 | EXPORT_SYMBOL(d_hash_and_lookup); |
| 2193 | 2303 | ||
| 2194 | /** | ||
| 2195 | * d_validate - verify dentry provided from insecure source (deprecated) | ||
| 2196 | * @dentry: The dentry alleged to be valid child of @dparent | ||
| 2197 | * @dparent: The parent dentry (known to be valid) | ||
| 2198 | * | ||
| 2199 | * An insecure source has sent us a dentry, here we verify it and dget() it. | ||
| 2200 | * This is used by ncpfs in its readdir implementation. | ||
| 2201 | * Zero is returned in the dentry is invalid. | ||
| 2202 | * | ||
| 2203 | * This function is slow for big directories, and deprecated, do not use it. | ||
| 2204 | */ | ||
| 2205 | int d_validate(struct dentry *dentry, struct dentry *dparent) | ||
| 2206 | { | ||
| 2207 | struct dentry *child; | ||
| 2208 | |||
| 2209 | spin_lock(&dparent->d_lock); | ||
| 2210 | list_for_each_entry(child, &dparent->d_subdirs, d_child) { | ||
| 2211 | if (dentry == child) { | ||
| 2212 | spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); | ||
| 2213 | __dget_dlock(dentry); | ||
| 2214 | spin_unlock(&dentry->d_lock); | ||
| 2215 | spin_unlock(&dparent->d_lock); | ||
| 2216 | return 1; | ||
| 2217 | } | ||
| 2218 | } | ||
| 2219 | spin_unlock(&dparent->d_lock); | ||
| 2220 | |||
| 2221 | return 0; | ||
| 2222 | } | ||
| 2223 | EXPORT_SYMBOL(d_validate); | ||
| 2224 | |||
| 2225 | /* | 2304 | /* |
| 2226 | * When a file is deleted, we have two options: | 2305 | * When a file is deleted, we have two options: |
| 2227 | * - turn this dentry into a negative dentry | 2306 | * - turn this dentry into a negative dentry |
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 05f2960ed7c3..45b18a5e225c 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c | |||
| @@ -34,93 +34,16 @@ static struct vfsmount *debugfs_mount; | |||
| 34 | static int debugfs_mount_count; | 34 | static int debugfs_mount_count; |
| 35 | static bool debugfs_registered; | 35 | static bool debugfs_registered; |
| 36 | 36 | ||
| 37 | static struct inode *debugfs_get_inode(struct super_block *sb, umode_t mode, dev_t dev, | 37 | static struct inode *debugfs_get_inode(struct super_block *sb) |
| 38 | void *data, const struct file_operations *fops) | ||
| 39 | |||
| 40 | { | 38 | { |
| 41 | struct inode *inode = new_inode(sb); | 39 | struct inode *inode = new_inode(sb); |
| 42 | |||
| 43 | if (inode) { | 40 | if (inode) { |
| 44 | inode->i_ino = get_next_ino(); | 41 | inode->i_ino = get_next_ino(); |
| 45 | inode->i_mode = mode; | ||
| 46 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | 42 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; |
| 47 | switch (mode & S_IFMT) { | ||
| 48 | default: | ||
| 49 | init_special_inode(inode, mode, dev); | ||
| 50 | break; | ||
| 51 | case S_IFREG: | ||
| 52 | inode->i_fop = fops ? fops : &debugfs_file_operations; | ||
| 53 | inode->i_private = data; | ||
| 54 | break; | ||
| 55 | case S_IFLNK: | ||
| 56 | inode->i_op = &debugfs_link_operations; | ||
| 57 | inode->i_private = data; | ||
| 58 | break; | ||
| 59 | case S_IFDIR: | ||
| 60 | inode->i_op = &simple_dir_inode_operations; | ||
| 61 | inode->i_fop = &simple_dir_operations; | ||
| 62 | |||
| 63 | /* directory inodes start off with i_nlink == 2 | ||
| 64 | * (for "." entry) */ | ||
| 65 | inc_nlink(inode); | ||
| 66 | break; | ||
| 67 | } | ||
| 68 | } | 43 | } |
| 69 | return inode; | 44 | return inode; |
| 70 | } | 45 | } |
| 71 | 46 | ||
| 72 | /* SMP-safe */ | ||
| 73 | static int debugfs_mknod(struct inode *dir, struct dentry *dentry, | ||
| 74 | umode_t mode, dev_t dev, void *data, | ||
| 75 | const struct file_operations *fops) | ||
| 76 | { | ||
| 77 | struct inode *inode; | ||
| 78 | int error = -EPERM; | ||
| 79 | |||
| 80 | if (dentry->d_inode) | ||
| 81 | return -EEXIST; | ||
| 82 | |||
| 83 | inode = debugfs_get_inode(dir->i_sb, mode, dev, data, fops); | ||
| 84 | if (inode) { | ||
| 85 | d_instantiate(dentry, inode); | ||
| 86 | dget(dentry); | ||
| 87 | error = 0; | ||
| 88 | } | ||
| 89 | return error; | ||
| 90 | } | ||
| 91 | |||
| 92 | static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | ||
| 93 | { | ||
| 94 | int res; | ||
| 95 | |||
| 96 | mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR; | ||
| 97 | res = debugfs_mknod(dir, dentry, mode, 0, NULL, NULL); | ||
| 98 | if (!res) { | ||
| 99 | inc_nlink(dir); | ||
| 100 | fsnotify_mkdir(dir, dentry); | ||
| 101 | } | ||
| 102 | return res; | ||
| 103 | } | ||
| 104 | |||
| 105 | static int debugfs_link(struct inode *dir, struct dentry *dentry, umode_t mode, | ||
| 106 | void *data) | ||
| 107 | { | ||
| 108 | mode = (mode & S_IALLUGO) | S_IFLNK; | ||
| 109 | return debugfs_mknod(dir, dentry, mode, 0, data, NULL); | ||
| 110 | } | ||
| 111 | |||
| 112 | static int debugfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | ||
| 113 | void *data, const struct file_operations *fops) | ||
| 114 | { | ||
| 115 | int res; | ||
| 116 | |||
| 117 | mode = (mode & S_IALLUGO) | S_IFREG; | ||
| 118 | res = debugfs_mknod(dir, dentry, mode, 0, data, fops); | ||
| 119 | if (!res) | ||
| 120 | fsnotify_create(dir, dentry); | ||
| 121 | return res; | ||
| 122 | } | ||
| 123 | |||
| 124 | static inline int debugfs_positive(struct dentry *dentry) | 47 | static inline int debugfs_positive(struct dentry *dentry) |
| 125 | { | 48 | { |
| 126 | return dentry->d_inode && !d_unhashed(dentry); | 49 | return dentry->d_inode && !d_unhashed(dentry); |
| @@ -252,6 +175,18 @@ static const struct super_operations debugfs_super_operations = { | |||
| 252 | .show_options = debugfs_show_options, | 175 | .show_options = debugfs_show_options, |
| 253 | }; | 176 | }; |
| 254 | 177 | ||
| 178 | static struct vfsmount *debugfs_automount(struct path *path) | ||
| 179 | { | ||
| 180 | struct vfsmount *(*f)(void *); | ||
| 181 | f = (struct vfsmount *(*)(void *))path->dentry->d_fsdata; | ||
| 182 | return f(path->dentry->d_inode->i_private); | ||
| 183 | } | ||
| 184 | |||
| 185 | static const struct dentry_operations debugfs_dops = { | ||
| 186 | .d_delete = always_delete_dentry, | ||
| 187 | .d_automount = debugfs_automount, | ||
| 188 | }; | ||
| 189 | |||
| 255 | static int debug_fill_super(struct super_block *sb, void *data, int silent) | 190 | static int debug_fill_super(struct super_block *sb, void *data, int silent) |
| 256 | { | 191 | { |
| 257 | static struct tree_descr debug_files[] = {{""}}; | 192 | static struct tree_descr debug_files[] = {{""}}; |
| @@ -276,6 +211,7 @@ static int debug_fill_super(struct super_block *sb, void *data, int silent) | |||
| 276 | goto fail; | 211 | goto fail; |
| 277 | 212 | ||
| 278 | sb->s_op = &debugfs_super_operations; | 213 | sb->s_op = &debugfs_super_operations; |
| 214 | sb->s_d_op = &debugfs_dops; | ||
| 279 | 215 | ||
| 280 | debugfs_apply_options(sb); | 216 | debugfs_apply_options(sb); |
| 281 | 217 | ||
| @@ -302,11 +238,9 @@ static struct file_system_type debug_fs_type = { | |||
| 302 | }; | 238 | }; |
| 303 | MODULE_ALIAS_FS("debugfs"); | 239 | MODULE_ALIAS_FS("debugfs"); |
| 304 | 240 | ||
| 305 | static struct dentry *__create_file(const char *name, umode_t mode, | 241 | static struct dentry *start_creating(const char *name, struct dentry *parent) |
| 306 | struct dentry *parent, void *data, | ||
| 307 | const struct file_operations *fops) | ||
| 308 | { | 242 | { |
| 309 | struct dentry *dentry = NULL; | 243 | struct dentry *dentry; |
| 310 | int error; | 244 | int error; |
| 311 | 245 | ||
| 312 | pr_debug("debugfs: creating file '%s'\n",name); | 246 | pr_debug("debugfs: creating file '%s'\n",name); |
| @@ -314,7 +248,7 @@ static struct dentry *__create_file(const char *name, umode_t mode, | |||
| 314 | error = simple_pin_fs(&debug_fs_type, &debugfs_mount, | 248 | error = simple_pin_fs(&debug_fs_type, &debugfs_mount, |
| 315 | &debugfs_mount_count); | 249 | &debugfs_mount_count); |
| 316 | if (error) | 250 | if (error) |
| 317 | goto exit; | 251 | return ERR_PTR(error); |
| 318 | 252 | ||
| 319 | /* If the parent is not specified, we create it in the root. | 253 | /* If the parent is not specified, we create it in the root. |
| 320 | * We need the root dentry to do this, which is in the super | 254 | * We need the root dentry to do this, which is in the super |
| @@ -326,31 +260,26 @@ static struct dentry *__create_file(const char *name, umode_t mode, | |||
| 326 | 260 | ||
| 327 | mutex_lock(&parent->d_inode->i_mutex); | 261 | mutex_lock(&parent->d_inode->i_mutex); |
| 328 | dentry = lookup_one_len(name, parent, strlen(name)); | 262 | dentry = lookup_one_len(name, parent, strlen(name)); |
| 329 | if (!IS_ERR(dentry)) { | 263 | if (!IS_ERR(dentry) && dentry->d_inode) { |
| 330 | switch (mode & S_IFMT) { | ||
| 331 | case S_IFDIR: | ||
| 332 | error = debugfs_mkdir(parent->d_inode, dentry, mode); | ||
| 333 | |||
| 334 | break; | ||
| 335 | case S_IFLNK: | ||
| 336 | error = debugfs_link(parent->d_inode, dentry, mode, | ||
| 337 | data); | ||
| 338 | break; | ||
| 339 | default: | ||
| 340 | error = debugfs_create(parent->d_inode, dentry, mode, | ||
| 341 | data, fops); | ||
| 342 | break; | ||
| 343 | } | ||
| 344 | dput(dentry); | 264 | dput(dentry); |
| 345 | } else | 265 | dentry = ERR_PTR(-EEXIST); |
| 346 | error = PTR_ERR(dentry); | ||
| 347 | mutex_unlock(&parent->d_inode->i_mutex); | ||
| 348 | |||
| 349 | if (error) { | ||
| 350 | dentry = NULL; | ||
| 351 | simple_release_fs(&debugfs_mount, &debugfs_mount_count); | ||
| 352 | } | 266 | } |
| 353 | exit: | 267 | if (IS_ERR(dentry)) |
| 268 | mutex_unlock(&parent->d_inode->i_mutex); | ||
| 269 | return dentry; | ||
| 270 | } | ||
| 271 | |||
| 272 | static struct dentry *failed_creating(struct dentry *dentry) | ||
| 273 | { | ||
| 274 | mutex_unlock(&dentry->d_parent->d_inode->i_mutex); | ||
| 275 | dput(dentry); | ||
| 276 | simple_release_fs(&debugfs_mount, &debugfs_mount_count); | ||
| 277 | return NULL; | ||
| 278 | } | ||
| 279 | |||
| 280 | static struct dentry *end_creating(struct dentry *dentry) | ||
| 281 | { | ||
| 282 | mutex_unlock(&dentry->d_parent->d_inode->i_mutex); | ||
| 354 | return dentry; | 283 | return dentry; |
| 355 | } | 284 | } |
| 356 | 285 | ||
| @@ -384,19 +313,71 @@ struct dentry *debugfs_create_file(const char *name, umode_t mode, | |||
| 384 | struct dentry *parent, void *data, | 313 | struct dentry *parent, void *data, |
| 385 | const struct file_operations *fops) | 314 | const struct file_operations *fops) |
| 386 | { | 315 | { |
| 387 | switch (mode & S_IFMT) { | 316 | struct dentry *dentry; |
| 388 | case S_IFREG: | 317 | struct inode *inode; |
| 389 | case 0: | 318 | |
| 390 | break; | 319 | if (!(mode & S_IFMT)) |
| 391 | default: | 320 | mode |= S_IFREG; |
| 392 | BUG(); | 321 | BUG_ON(!S_ISREG(mode)); |
| 393 | } | 322 | dentry = start_creating(name, parent); |
| 323 | |||
| 324 | if (IS_ERR(dentry)) | ||
| 325 | return NULL; | ||
| 394 | 326 | ||
| 395 | return __create_file(name, mode, parent, data, fops); | 327 | inode = debugfs_get_inode(dentry->d_sb); |
| 328 | if (unlikely(!inode)) | ||
| 329 | return failed_creating(dentry); | ||
| 330 | |||
| 331 | inode->i_mode = mode; | ||
| 332 | inode->i_fop = fops ? fops : &debugfs_file_operations; | ||
| 333 | inode->i_private = data; | ||
| 334 | d_instantiate(dentry, inode); | ||
| 335 | fsnotify_create(dentry->d_parent->d_inode, dentry); | ||
| 336 | return end_creating(dentry); | ||
| 396 | } | 337 | } |
| 397 | EXPORT_SYMBOL_GPL(debugfs_create_file); | 338 | EXPORT_SYMBOL_GPL(debugfs_create_file); |
| 398 | 339 | ||
| 399 | /** | 340 | /** |
| 341 | * debugfs_create_file_size - create a file in the debugfs filesystem | ||
| 342 | * @name: a pointer to a string containing the name of the file to create. | ||
| 343 | * @mode: the permission that the file should have. | ||
| 344 | * @parent: a pointer to the parent dentry for this file. This should be a | ||
| 345 | * directory dentry if set. If this parameter is NULL, then the | ||
| 346 | * file will be created in the root of the debugfs filesystem. | ||
| 347 | * @data: a pointer to something that the caller will want to get to later | ||
| 348 | * on. The inode.i_private pointer will point to this value on | ||
| 349 | * the open() call. | ||
| 350 | * @fops: a pointer to a struct file_operations that should be used for | ||
| 351 | * this file. | ||
| 352 | * @file_size: initial file size | ||
| 353 | * | ||
| 354 | * This is the basic "create a file" function for debugfs. It allows for a | ||
| 355 | * wide range of flexibility in creating a file, or a directory (if you want | ||
| 356 | * to create a directory, the debugfs_create_dir() function is | ||
| 357 | * recommended to be used instead.) | ||
| 358 | * | ||
| 359 | * This function will return a pointer to a dentry if it succeeds. This | ||
| 360 | * pointer must be passed to the debugfs_remove() function when the file is | ||
| 361 | * to be removed (no automatic cleanup happens if your module is unloaded, | ||
| 362 | * you are responsible here.) If an error occurs, %NULL will be returned. | ||
| 363 | * | ||
| 364 | * If debugfs is not enabled in the kernel, the value -%ENODEV will be | ||
| 365 | * returned. | ||
| 366 | */ | ||
| 367 | struct dentry *debugfs_create_file_size(const char *name, umode_t mode, | ||
| 368 | struct dentry *parent, void *data, | ||
| 369 | const struct file_operations *fops, | ||
| 370 | loff_t file_size) | ||
| 371 | { | ||
| 372 | struct dentry *de = debugfs_create_file(name, mode, parent, data, fops); | ||
| 373 | |||
| 374 | if (de) | ||
| 375 | de->d_inode->i_size = file_size; | ||
| 376 | return de; | ||
| 377 | } | ||
| 378 | EXPORT_SYMBOL_GPL(debugfs_create_file_size); | ||
| 379 | |||
| 380 | /** | ||
| 400 | * debugfs_create_dir - create a directory in the debugfs filesystem | 381 | * debugfs_create_dir - create a directory in the debugfs filesystem |
| 401 | * @name: a pointer to a string containing the name of the directory to | 382 | * @name: a pointer to a string containing the name of the directory to |
| 402 | * create. | 383 | * create. |
| @@ -416,12 +397,65 @@ EXPORT_SYMBOL_GPL(debugfs_create_file); | |||
| 416 | */ | 397 | */ |
| 417 | struct dentry *debugfs_create_dir(const char *name, struct dentry *parent) | 398 | struct dentry *debugfs_create_dir(const char *name, struct dentry *parent) |
| 418 | { | 399 | { |
| 419 | return __create_file(name, S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, | 400 | struct dentry *dentry = start_creating(name, parent); |
| 420 | parent, NULL, NULL); | 401 | struct inode *inode; |
| 402 | |||
| 403 | if (IS_ERR(dentry)) | ||
| 404 | return NULL; | ||
| 405 | |||
| 406 | inode = debugfs_get_inode(dentry->d_sb); | ||
| 407 | if (unlikely(!inode)) | ||
| 408 | return failed_creating(dentry); | ||
| 409 | |||
| 410 | inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO; | ||
| 411 | inode->i_op = &simple_dir_inode_operations; | ||
| 412 | inode->i_fop = &simple_dir_operations; | ||
| 413 | |||
| 414 | /* directory inodes start off with i_nlink == 2 (for "." entry) */ | ||
| 415 | inc_nlink(inode); | ||
| 416 | d_instantiate(dentry, inode); | ||
| 417 | inc_nlink(dentry->d_parent->d_inode); | ||
| 418 | fsnotify_mkdir(dentry->d_parent->d_inode, dentry); | ||
| 419 | return end_creating(dentry); | ||
| 421 | } | 420 | } |
| 422 | EXPORT_SYMBOL_GPL(debugfs_create_dir); | 421 | EXPORT_SYMBOL_GPL(debugfs_create_dir); |
| 423 | 422 | ||
| 424 | /** | 423 | /** |
| 424 | * debugfs_create_automount - create automount point in the debugfs filesystem | ||
| 425 | * @name: a pointer to a string containing the name of the file to create. | ||
| 426 | * @parent: a pointer to the parent dentry for this file. This should be a | ||
| 427 | * directory dentry if set. If this parameter is NULL, then the | ||
| 428 | * file will be created in the root of the debugfs filesystem. | ||
| 429 | * @f: function to be called when pathname resolution steps on that one. | ||
| 430 | * @data: opaque argument to pass to f(). | ||
| 431 | * | ||
| 432 | * @f should return what ->d_automount() would. | ||
| 433 | */ | ||
| 434 | struct dentry *debugfs_create_automount(const char *name, | ||
| 435 | struct dentry *parent, | ||
| 436 | struct vfsmount *(*f)(void *), | ||
| 437 | void *data) | ||
| 438 | { | ||
| 439 | struct dentry *dentry = start_creating(name, parent); | ||
| 440 | struct inode *inode; | ||
| 441 | |||
| 442 | if (IS_ERR(dentry)) | ||
| 443 | return NULL; | ||
| 444 | |||
| 445 | inode = debugfs_get_inode(dentry->d_sb); | ||
| 446 | if (unlikely(!inode)) | ||
| 447 | return failed_creating(dentry); | ||
| 448 | |||
| 449 | inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO; | ||
| 450 | inode->i_flags |= S_AUTOMOUNT; | ||
| 451 | inode->i_private = data; | ||
| 452 | dentry->d_fsdata = (void *)f; | ||
| 453 | d_instantiate(dentry, inode); | ||
| 454 | return end_creating(dentry); | ||
| 455 | } | ||
| 456 | EXPORT_SYMBOL(debugfs_create_automount); | ||
| 457 | |||
| 458 | /** | ||
| 425 | * debugfs_create_symlink- create a symbolic link in the debugfs filesystem | 459 | * debugfs_create_symlink- create a symbolic link in the debugfs filesystem |
| 426 | * @name: a pointer to a string containing the name of the symbolic link to | 460 | * @name: a pointer to a string containing the name of the symbolic link to |
| 427 | * create. | 461 | * create. |
| @@ -447,17 +481,28 @@ EXPORT_SYMBOL_GPL(debugfs_create_dir); | |||
| 447 | struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, | 481 | struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, |
| 448 | const char *target) | 482 | const char *target) |
| 449 | { | 483 | { |
| 450 | struct dentry *result; | 484 | struct dentry *dentry; |
| 451 | char *link; | 485 | struct inode *inode; |
| 452 | 486 | char *link = kstrdup(target, GFP_KERNEL); | |
| 453 | link = kstrdup(target, GFP_KERNEL); | ||
| 454 | if (!link) | 487 | if (!link) |
| 455 | return NULL; | 488 | return NULL; |
| 456 | 489 | ||
| 457 | result = __create_file(name, S_IFLNK | S_IRWXUGO, parent, link, NULL); | 490 | dentry = start_creating(name, parent); |
| 458 | if (!result) | 491 | if (IS_ERR(dentry)) { |
| 459 | kfree(link); | 492 | kfree(link); |
| 460 | return result; | 493 | return NULL; |
| 494 | } | ||
| 495 | |||
| 496 | inode = debugfs_get_inode(dentry->d_sb); | ||
| 497 | if (unlikely(!inode)) { | ||
| 498 | kfree(link); | ||
| 499 | return failed_creating(dentry); | ||
| 500 | } | ||
| 501 | inode->i_mode = S_IFLNK | S_IRWXUGO; | ||
| 502 | inode->i_op = &debugfs_link_operations; | ||
| 503 | inode->i_private = link; | ||
| 504 | d_instantiate(dentry, inode); | ||
| 505 | return end_creating(dentry); | ||
| 461 | } | 506 | } |
| 462 | EXPORT_SYMBOL_GPL(debugfs_create_symlink); | 507 | EXPORT_SYMBOL_GPL(debugfs_create_symlink); |
| 463 | 508 | ||
diff --git a/fs/eventfd.c b/fs/eventfd.c index 4b0a226024fa..8d0c0df01854 100644 --- a/fs/eventfd.c +++ b/fs/eventfd.c | |||
| @@ -118,18 +118,18 @@ static unsigned int eventfd_poll(struct file *file, poll_table *wait) | |||
| 118 | { | 118 | { |
| 119 | struct eventfd_ctx *ctx = file->private_data; | 119 | struct eventfd_ctx *ctx = file->private_data; |
| 120 | unsigned int events = 0; | 120 | unsigned int events = 0; |
| 121 | unsigned long flags; | 121 | u64 count; |
| 122 | 122 | ||
| 123 | poll_wait(file, &ctx->wqh, wait); | 123 | poll_wait(file, &ctx->wqh, wait); |
| 124 | smp_rmb(); | ||
| 125 | count = ctx->count; | ||
| 124 | 126 | ||
| 125 | spin_lock_irqsave(&ctx->wqh.lock, flags); | 127 | if (count > 0) |
| 126 | if (ctx->count > 0) | ||
| 127 | events |= POLLIN; | 128 | events |= POLLIN; |
| 128 | if (ctx->count == ULLONG_MAX) | 129 | if (count == ULLONG_MAX) |
| 129 | events |= POLLERR; | 130 | events |= POLLERR; |
| 130 | if (ULLONG_MAX - 1 > ctx->count) | 131 | if (ULLONG_MAX - 1 > count) |
| 131 | events |= POLLOUT; | 132 | events |= POLLOUT; |
| 132 | spin_unlock_irqrestore(&ctx->wqh.lock, flags); | ||
| 133 | 133 | ||
| 134 | return events; | 134 | return events; |
| 135 | } | 135 | } |
| @@ -794,8 +794,14 @@ exit: | |||
| 794 | 794 | ||
| 795 | struct file *open_exec(const char *name) | 795 | struct file *open_exec(const char *name) |
| 796 | { | 796 | { |
| 797 | struct filename tmp = { .name = name }; | 797 | struct filename *filename = getname_kernel(name); |
| 798 | return do_open_execat(AT_FDCWD, &tmp, 0); | 798 | struct file *f = ERR_CAST(filename); |
| 799 | |||
| 800 | if (!IS_ERR(filename)) { | ||
| 801 | f = do_open_execat(AT_FDCWD, filename, 0); | ||
| 802 | putname(filename); | ||
| 803 | } | ||
| 804 | return f; | ||
| 799 | } | 805 | } |
| 800 | EXPORT_SYMBOL(open_exec); | 806 | EXPORT_SYMBOL(open_exec); |
| 801 | 807 | ||
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 28555f191b62..85404f15e53a 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
| @@ -4174,6 +4174,65 @@ static int ext4_inode_blocks_set(handle_t *handle, | |||
| 4174 | return 0; | 4174 | return 0; |
| 4175 | } | 4175 | } |
| 4176 | 4176 | ||
| 4177 | struct other_inode { | ||
| 4178 | unsigned long orig_ino; | ||
| 4179 | struct ext4_inode *raw_inode; | ||
| 4180 | }; | ||
| 4181 | |||
| 4182 | static int other_inode_match(struct inode * inode, unsigned long ino, | ||
| 4183 | void *data) | ||
| 4184 | { | ||
| 4185 | struct other_inode *oi = (struct other_inode *) data; | ||
| 4186 | |||
| 4187 | if ((inode->i_ino != ino) || | ||
| 4188 | (inode->i_state & (I_FREEING | I_WILL_FREE | I_NEW | | ||
| 4189 | I_DIRTY_SYNC | I_DIRTY_DATASYNC)) || | ||
| 4190 | ((inode->i_state & I_DIRTY_TIME) == 0)) | ||
| 4191 | return 0; | ||
| 4192 | spin_lock(&inode->i_lock); | ||
| 4193 | if (((inode->i_state & (I_FREEING | I_WILL_FREE | I_NEW | | ||
| 4194 | I_DIRTY_SYNC | I_DIRTY_DATASYNC)) == 0) && | ||
| 4195 | (inode->i_state & I_DIRTY_TIME)) { | ||
| 4196 | struct ext4_inode_info *ei = EXT4_I(inode); | ||
| 4197 | |||
| 4198 | inode->i_state &= ~(I_DIRTY_TIME | I_DIRTY_TIME_EXPIRED); | ||
| 4199 | spin_unlock(&inode->i_lock); | ||
| 4200 | |||
| 4201 | spin_lock(&ei->i_raw_lock); | ||
| 4202 | EXT4_INODE_SET_XTIME(i_ctime, inode, oi->raw_inode); | ||
| 4203 | EXT4_INODE_SET_XTIME(i_mtime, inode, oi->raw_inode); | ||
| 4204 | EXT4_INODE_SET_XTIME(i_atime, inode, oi->raw_inode); | ||
| 4205 | ext4_inode_csum_set(inode, oi->raw_inode, ei); | ||
| 4206 | spin_unlock(&ei->i_raw_lock); | ||
| 4207 | trace_ext4_other_inode_update_time(inode, oi->orig_ino); | ||
| 4208 | return -1; | ||
| 4209 | } | ||
| 4210 | spin_unlock(&inode->i_lock); | ||
| 4211 | return -1; | ||
| 4212 | } | ||
| 4213 | |||
| 4214 | /* | ||
| 4215 | * Opportunistically update the other time fields for other inodes in | ||
| 4216 | * the same inode table block. | ||
| 4217 | */ | ||
| 4218 | static void ext4_update_other_inodes_time(struct super_block *sb, | ||
| 4219 | unsigned long orig_ino, char *buf) | ||
| 4220 | { | ||
| 4221 | struct other_inode oi; | ||
| 4222 | unsigned long ino; | ||
| 4223 | int i, inodes_per_block = EXT4_SB(sb)->s_inodes_per_block; | ||
| 4224 | int inode_size = EXT4_INODE_SIZE(sb); | ||
| 4225 | |||
| 4226 | oi.orig_ino = orig_ino; | ||
| 4227 | ino = orig_ino & ~(inodes_per_block - 1); | ||
| 4228 | for (i = 0; i < inodes_per_block; i++, ino++, buf += inode_size) { | ||
| 4229 | if (ino == orig_ino) | ||
| 4230 | continue; | ||
| 4231 | oi.raw_inode = (struct ext4_inode *) buf; | ||
| 4232 | (void) find_inode_nowait(sb, ino, other_inode_match, &oi); | ||
| 4233 | } | ||
| 4234 | } | ||
| 4235 | |||
| 4177 | /* | 4236 | /* |
| 4178 | * Post the struct inode info into an on-disk inode location in the | 4237 | * Post the struct inode info into an on-disk inode location in the |
| 4179 | * buffer-cache. This gobbles the caller's reference to the | 4238 | * buffer-cache. This gobbles the caller's reference to the |
| @@ -4283,10 +4342,11 @@ static int ext4_do_update_inode(handle_t *handle, | |||
| 4283 | cpu_to_le16(ei->i_extra_isize); | 4342 | cpu_to_le16(ei->i_extra_isize); |
| 4284 | } | 4343 | } |
| 4285 | } | 4344 | } |
| 4286 | |||
| 4287 | ext4_inode_csum_set(inode, raw_inode, ei); | 4345 | ext4_inode_csum_set(inode, raw_inode, ei); |
| 4288 | |||
| 4289 | spin_unlock(&ei->i_raw_lock); | 4346 | spin_unlock(&ei->i_raw_lock); |
| 4347 | if (inode->i_sb->s_flags & MS_LAZYTIME) | ||
| 4348 | ext4_update_other_inodes_time(inode->i_sb, inode->i_ino, | ||
| 4349 | bh->b_data); | ||
| 4290 | 4350 | ||
| 4291 | BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); | 4351 | BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); |
| 4292 | rc = ext4_handle_dirty_metadata(handle, NULL, bh); | 4352 | rc = ext4_handle_dirty_metadata(handle, NULL, bh); |
| @@ -4875,11 +4935,17 @@ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode) | |||
| 4875 | * If the inode is marked synchronous, we don't honour that here - doing | 4935 | * If the inode is marked synchronous, we don't honour that here - doing |
| 4876 | * so would cause a commit on atime updates, which we don't bother doing. | 4936 | * so would cause a commit on atime updates, which we don't bother doing. |
| 4877 | * We handle synchronous inodes at the highest possible level. | 4937 | * We handle synchronous inodes at the highest possible level. |
| 4938 | * | ||
| 4939 | * If only the I_DIRTY_TIME flag is set, we can skip everything. If | ||
| 4940 | * I_DIRTY_TIME and I_DIRTY_SYNC is set, the only inode fields we need | ||
| 4941 | * to copy into the on-disk inode structure are the timestamp files. | ||
| 4878 | */ | 4942 | */ |
| 4879 | void ext4_dirty_inode(struct inode *inode, int flags) | 4943 | void ext4_dirty_inode(struct inode *inode, int flags) |
| 4880 | { | 4944 | { |
| 4881 | handle_t *handle; | 4945 | handle_t *handle; |
| 4882 | 4946 | ||
| 4947 | if (flags == I_DIRTY_TIME) | ||
| 4948 | return; | ||
| 4883 | handle = ext4_journal_start(inode, EXT4_HT_INODE, 2); | 4949 | handle = ext4_journal_start(inode, EXT4_HT_INODE, 2); |
| 4884 | if (IS_ERR(handle)) | 4950 | if (IS_ERR(handle)) |
| 4885 | goto out; | 4951 | goto out; |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 10e8c6b7ca08..1adac6868e6f 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
| @@ -1126,6 +1126,7 @@ enum { | |||
| 1126 | Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err, | 1126 | Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err, |
| 1127 | Opt_usrquota, Opt_grpquota, Opt_i_version, Opt_dax, | 1127 | Opt_usrquota, Opt_grpquota, Opt_i_version, Opt_dax, |
| 1128 | Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_mblk_io_submit, | 1128 | Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_mblk_io_submit, |
| 1129 | Opt_lazytime, Opt_nolazytime, | ||
| 1129 | Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity, | 1130 | Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity, |
| 1130 | Opt_inode_readahead_blks, Opt_journal_ioprio, | 1131 | Opt_inode_readahead_blks, Opt_journal_ioprio, |
| 1131 | Opt_dioread_nolock, Opt_dioread_lock, | 1132 | Opt_dioread_nolock, Opt_dioread_lock, |
| @@ -1190,6 +1191,8 @@ static const match_table_t tokens = { | |||
| 1190 | {Opt_dax, "dax"}, | 1191 | {Opt_dax, "dax"}, |
| 1191 | {Opt_stripe, "stripe=%u"}, | 1192 | {Opt_stripe, "stripe=%u"}, |
| 1192 | {Opt_delalloc, "delalloc"}, | 1193 | {Opt_delalloc, "delalloc"}, |
| 1194 | {Opt_lazytime, "lazytime"}, | ||
| 1195 | {Opt_nolazytime, "nolazytime"}, | ||
| 1193 | {Opt_nodelalloc, "nodelalloc"}, | 1196 | {Opt_nodelalloc, "nodelalloc"}, |
| 1194 | {Opt_removed, "mblk_io_submit"}, | 1197 | {Opt_removed, "mblk_io_submit"}, |
| 1195 | {Opt_removed, "nomblk_io_submit"}, | 1198 | {Opt_removed, "nomblk_io_submit"}, |
| @@ -1448,6 +1451,12 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token, | |||
| 1448 | case Opt_i_version: | 1451 | case Opt_i_version: |
| 1449 | sb->s_flags |= MS_I_VERSION; | 1452 | sb->s_flags |= MS_I_VERSION; |
| 1450 | return 1; | 1453 | return 1; |
| 1454 | case Opt_lazytime: | ||
| 1455 | sb->s_flags |= MS_LAZYTIME; | ||
| 1456 | return 1; | ||
| 1457 | case Opt_nolazytime: | ||
| 1458 | sb->s_flags &= ~MS_LAZYTIME; | ||
| 1459 | return 1; | ||
| 1451 | } | 1460 | } |
| 1452 | 1461 | ||
| 1453 | for (m = ext4_mount_opts; m->token != Opt_err; m++) | 1462 | for (m = ext4_mount_opts; m->token != Opt_err; m++) |
| @@ -5044,6 +5053,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) | |||
| 5044 | } | 5053 | } |
| 5045 | #endif | 5054 | #endif |
| 5046 | 5055 | ||
| 5056 | *flags = (*flags & ~MS_LAZYTIME) | (sb->s_flags & MS_LAZYTIME); | ||
| 5047 | ext4_msg(sb, KERN_INFO, "re-mounted. Opts: %s", orig_data); | 5057 | ext4_msg(sb, KERN_INFO, "re-mounted. Opts: %s", orig_data); |
| 5048 | kfree(orig_data); | 5058 | kfree(orig_data); |
| 5049 | return 0; | 5059 | return 0; |
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 7b41a2dcdd76..497c7c5263c7 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
| @@ -580,7 +580,7 @@ static void fat_set_state(struct super_block *sb, | |||
| 580 | { | 580 | { |
| 581 | struct buffer_head *bh; | 581 | struct buffer_head *bh; |
| 582 | struct fat_boot_sector *b; | 582 | struct fat_boot_sector *b; |
| 583 | struct msdos_sb_info *sbi = sb->s_fs_info; | 583 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
| 584 | 584 | ||
| 585 | /* do not change any thing if mounted read only */ | 585 | /* do not change any thing if mounted read only */ |
| 586 | if ((sb->s_flags & MS_RDONLY) && !force) | 586 | if ((sb->s_flags & MS_RDONLY) && !force) |
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index c399152de397..073657f755d4 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
| @@ -253,14 +253,19 @@ static bool inode_dirtied_after(struct inode *inode, unsigned long t) | |||
| 253 | return ret; | 253 | return ret; |
| 254 | } | 254 | } |
| 255 | 255 | ||
| 256 | #define EXPIRE_DIRTY_ATIME 0x0001 | ||
| 257 | |||
| 256 | /* | 258 | /* |
| 257 | * Move expired (dirtied before work->older_than_this) dirty inodes from | 259 | * Move expired (dirtied before work->older_than_this) dirty inodes from |
| 258 | * @delaying_queue to @dispatch_queue. | 260 | * @delaying_queue to @dispatch_queue. |
| 259 | */ | 261 | */ |
| 260 | static int move_expired_inodes(struct list_head *delaying_queue, | 262 | static int move_expired_inodes(struct list_head *delaying_queue, |
| 261 | struct list_head *dispatch_queue, | 263 | struct list_head *dispatch_queue, |
| 264 | int flags, | ||
| 262 | struct wb_writeback_work *work) | 265 | struct wb_writeback_work *work) |
| 263 | { | 266 | { |
| 267 | unsigned long *older_than_this = NULL; | ||
| 268 | unsigned long expire_time; | ||
| 264 | LIST_HEAD(tmp); | 269 | LIST_HEAD(tmp); |
| 265 | struct list_head *pos, *node; | 270 | struct list_head *pos, *node; |
| 266 | struct super_block *sb = NULL; | 271 | struct super_block *sb = NULL; |
| @@ -268,13 +273,21 @@ static int move_expired_inodes(struct list_head *delaying_queue, | |||
| 268 | int do_sb_sort = 0; | 273 | int do_sb_sort = 0; |
| 269 | int moved = 0; | 274 | int moved = 0; |
| 270 | 275 | ||
| 276 | if ((flags & EXPIRE_DIRTY_ATIME) == 0) | ||
| 277 | older_than_this = work->older_than_this; | ||
| 278 | else if ((work->reason == WB_REASON_SYNC) == 0) { | ||
| 279 | expire_time = jiffies - (HZ * 86400); | ||
| 280 | older_than_this = &expire_time; | ||
| 281 | } | ||
| 271 | while (!list_empty(delaying_queue)) { | 282 | while (!list_empty(delaying_queue)) { |
| 272 | inode = wb_inode(delaying_queue->prev); | 283 | inode = wb_inode(delaying_queue->prev); |
| 273 | if (work->older_than_this && | 284 | if (older_than_this && |
| 274 | inode_dirtied_after(inode, *work->older_than_this)) | 285 | inode_dirtied_after(inode, *older_than_this)) |
| 275 | break; | 286 | break; |
| 276 | list_move(&inode->i_wb_list, &tmp); | 287 | list_move(&inode->i_wb_list, &tmp); |
| 277 | moved++; | 288 | moved++; |
| 289 | if (flags & EXPIRE_DIRTY_ATIME) | ||
| 290 | set_bit(__I_DIRTY_TIME_EXPIRED, &inode->i_state); | ||
| 278 | if (sb_is_blkdev_sb(inode->i_sb)) | 291 | if (sb_is_blkdev_sb(inode->i_sb)) |
| 279 | continue; | 292 | continue; |
| 280 | if (sb && sb != inode->i_sb) | 293 | if (sb && sb != inode->i_sb) |
| @@ -315,9 +328,12 @@ out: | |||
| 315 | static void queue_io(struct bdi_writeback *wb, struct wb_writeback_work *work) | 328 | static void queue_io(struct bdi_writeback *wb, struct wb_writeback_work *work) |
| 316 | { | 329 | { |
| 317 | int moved; | 330 | int moved; |
| 331 | |||
| 318 | assert_spin_locked(&wb->list_lock); | 332 | assert_spin_locked(&wb->list_lock); |
| 319 | list_splice_init(&wb->b_more_io, &wb->b_io); | 333 | list_splice_init(&wb->b_more_io, &wb->b_io); |
| 320 | moved = move_expired_inodes(&wb->b_dirty, &wb->b_io, work); | 334 | moved = move_expired_inodes(&wb->b_dirty, &wb->b_io, 0, work); |
| 335 | moved += move_expired_inodes(&wb->b_dirty_time, &wb->b_io, | ||
| 336 | EXPIRE_DIRTY_ATIME, work); | ||
| 321 | trace_writeback_queue_io(wb, work, moved); | 337 | trace_writeback_queue_io(wb, work, moved); |
| 322 | } | 338 | } |
| 323 | 339 | ||
| @@ -441,6 +457,8 @@ static void requeue_inode(struct inode *inode, struct bdi_writeback *wb, | |||
| 441 | * updates after data IO completion. | 457 | * updates after data IO completion. |
| 442 | */ | 458 | */ |
| 443 | redirty_tail(inode, wb); | 459 | redirty_tail(inode, wb); |
| 460 | } else if (inode->i_state & I_DIRTY_TIME) { | ||
| 461 | list_move(&inode->i_wb_list, &wb->b_dirty_time); | ||
| 444 | } else { | 462 | } else { |
| 445 | /* The inode is clean. Remove from writeback lists. */ | 463 | /* The inode is clean. Remove from writeback lists. */ |
| 446 | list_del_init(&inode->i_wb_list); | 464 | list_del_init(&inode->i_wb_list); |
| @@ -487,7 +505,13 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc) | |||
| 487 | spin_lock(&inode->i_lock); | 505 | spin_lock(&inode->i_lock); |
| 488 | 506 | ||
| 489 | dirty = inode->i_state & I_DIRTY; | 507 | dirty = inode->i_state & I_DIRTY; |
| 490 | inode->i_state &= ~I_DIRTY; | 508 | if (((dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) && |
| 509 | (inode->i_state & I_DIRTY_TIME)) || | ||
| 510 | (inode->i_state & I_DIRTY_TIME_EXPIRED)) { | ||
| 511 | dirty |= I_DIRTY_TIME | I_DIRTY_TIME_EXPIRED; | ||
| 512 | trace_writeback_lazytime(inode); | ||
| 513 | } | ||
| 514 | inode->i_state &= ~dirty; | ||
| 491 | 515 | ||
| 492 | /* | 516 | /* |
| 493 | * Paired with smp_mb() in __mark_inode_dirty(). This allows | 517 | * Paired with smp_mb() in __mark_inode_dirty(). This allows |
| @@ -507,8 +531,10 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc) | |||
| 507 | 531 | ||
| 508 | spin_unlock(&inode->i_lock); | 532 | spin_unlock(&inode->i_lock); |
| 509 | 533 | ||
| 534 | if (dirty & I_DIRTY_TIME) | ||
| 535 | mark_inode_dirty_sync(inode); | ||
| 510 | /* Don't write the inode if only I_DIRTY_PAGES was set */ | 536 | /* Don't write the inode if only I_DIRTY_PAGES was set */ |
| 511 | if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) { | 537 | if (dirty & ~I_DIRTY_PAGES) { |
| 512 | int err = write_inode(inode, wbc); | 538 | int err = write_inode(inode, wbc); |
| 513 | if (ret == 0) | 539 | if (ret == 0) |
| 514 | ret = err; | 540 | ret = err; |
| @@ -556,7 +582,7 @@ writeback_single_inode(struct inode *inode, struct bdi_writeback *wb, | |||
| 556 | * make sure inode is on some writeback list and leave it there unless | 582 | * make sure inode is on some writeback list and leave it there unless |
| 557 | * we have completely cleaned the inode. | 583 | * we have completely cleaned the inode. |
| 558 | */ | 584 | */ |
| 559 | if (!(inode->i_state & I_DIRTY) && | 585 | if (!(inode->i_state & I_DIRTY_ALL) && |
| 560 | (wbc->sync_mode != WB_SYNC_ALL || | 586 | (wbc->sync_mode != WB_SYNC_ALL || |
| 561 | !mapping_tagged(inode->i_mapping, PAGECACHE_TAG_WRITEBACK))) | 587 | !mapping_tagged(inode->i_mapping, PAGECACHE_TAG_WRITEBACK))) |
| 562 | goto out; | 588 | goto out; |
| @@ -571,7 +597,7 @@ writeback_single_inode(struct inode *inode, struct bdi_writeback *wb, | |||
| 571 | * If inode is clean, remove it from writeback lists. Otherwise don't | 597 | * If inode is clean, remove it from writeback lists. Otherwise don't |
| 572 | * touch it. See comment above for explanation. | 598 | * touch it. See comment above for explanation. |
| 573 | */ | 599 | */ |
| 574 | if (!(inode->i_state & I_DIRTY)) | 600 | if (!(inode->i_state & I_DIRTY_ALL)) |
| 575 | list_del_init(&inode->i_wb_list); | 601 | list_del_init(&inode->i_wb_list); |
| 576 | spin_unlock(&wb->list_lock); | 602 | spin_unlock(&wb->list_lock); |
| 577 | inode_sync_complete(inode); | 603 | inode_sync_complete(inode); |
| @@ -713,7 +739,7 @@ static long writeback_sb_inodes(struct super_block *sb, | |||
| 713 | wrote += write_chunk - wbc.nr_to_write; | 739 | wrote += write_chunk - wbc.nr_to_write; |
| 714 | spin_lock(&wb->list_lock); | 740 | spin_lock(&wb->list_lock); |
| 715 | spin_lock(&inode->i_lock); | 741 | spin_lock(&inode->i_lock); |
| 716 | if (!(inode->i_state & I_DIRTY)) | 742 | if (!(inode->i_state & I_DIRTY_ALL)) |
| 717 | wrote++; | 743 | wrote++; |
| 718 | requeue_inode(inode, wb, &wbc); | 744 | requeue_inode(inode, wb, &wbc); |
| 719 | inode_sync_complete(inode); | 745 | inode_sync_complete(inode); |
| @@ -1151,16 +1177,20 @@ static noinline void block_dump___mark_inode_dirty(struct inode *inode) | |||
| 1151 | * page->mapping->host, so the page-dirtying time is recorded in the internal | 1177 | * page->mapping->host, so the page-dirtying time is recorded in the internal |
| 1152 | * blockdev inode. | 1178 | * blockdev inode. |
| 1153 | */ | 1179 | */ |
| 1180 | #define I_DIRTY_INODE (I_DIRTY_SYNC | I_DIRTY_DATASYNC) | ||
| 1154 | void __mark_inode_dirty(struct inode *inode, int flags) | 1181 | void __mark_inode_dirty(struct inode *inode, int flags) |
| 1155 | { | 1182 | { |
| 1156 | struct super_block *sb = inode->i_sb; | 1183 | struct super_block *sb = inode->i_sb; |
| 1157 | struct backing_dev_info *bdi = NULL; | 1184 | struct backing_dev_info *bdi = NULL; |
| 1185 | int dirtytime; | ||
| 1186 | |||
| 1187 | trace_writeback_mark_inode_dirty(inode, flags); | ||
| 1158 | 1188 | ||
| 1159 | /* | 1189 | /* |
| 1160 | * Don't do this for I_DIRTY_PAGES - that doesn't actually | 1190 | * Don't do this for I_DIRTY_PAGES - that doesn't actually |
| 1161 | * dirty the inode itself | 1191 | * dirty the inode itself |
| 1162 | */ | 1192 | */ |
| 1163 | if (flags & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) { | 1193 | if (flags & (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_TIME)) { |
| 1164 | trace_writeback_dirty_inode_start(inode, flags); | 1194 | trace_writeback_dirty_inode_start(inode, flags); |
| 1165 | 1195 | ||
| 1166 | if (sb->s_op->dirty_inode) | 1196 | if (sb->s_op->dirty_inode) |
| @@ -1168,6 +1198,9 @@ void __mark_inode_dirty(struct inode *inode, int flags) | |||
| 1168 | 1198 | ||
| 1169 | trace_writeback_dirty_inode(inode, flags); | 1199 | trace_writeback_dirty_inode(inode, flags); |
| 1170 | } | 1200 | } |
| 1201 | if (flags & I_DIRTY_INODE) | ||
| 1202 | flags &= ~I_DIRTY_TIME; | ||
| 1203 | dirtytime = flags & I_DIRTY_TIME; | ||
| 1171 | 1204 | ||
| 1172 | /* | 1205 | /* |
| 1173 | * Paired with smp_mb() in __writeback_single_inode() for the | 1206 | * Paired with smp_mb() in __writeback_single_inode() for the |
| @@ -1175,16 +1208,21 @@ void __mark_inode_dirty(struct inode *inode, int flags) | |||
| 1175 | */ | 1208 | */ |
| 1176 | smp_mb(); | 1209 | smp_mb(); |
| 1177 | 1210 | ||
| 1178 | if ((inode->i_state & flags) == flags) | 1211 | if (((inode->i_state & flags) == flags) || |
| 1212 | (dirtytime && (inode->i_state & I_DIRTY_INODE))) | ||
| 1179 | return; | 1213 | return; |
| 1180 | 1214 | ||
| 1181 | if (unlikely(block_dump)) | 1215 | if (unlikely(block_dump)) |
| 1182 | block_dump___mark_inode_dirty(inode); | 1216 | block_dump___mark_inode_dirty(inode); |
| 1183 | 1217 | ||
| 1184 | spin_lock(&inode->i_lock); | 1218 | spin_lock(&inode->i_lock); |
| 1219 | if (dirtytime && (inode->i_state & I_DIRTY_INODE)) | ||
| 1220 | goto out_unlock_inode; | ||
| 1185 | if ((inode->i_state & flags) != flags) { | 1221 | if ((inode->i_state & flags) != flags) { |
| 1186 | const int was_dirty = inode->i_state & I_DIRTY; | 1222 | const int was_dirty = inode->i_state & I_DIRTY; |
| 1187 | 1223 | ||
| 1224 | if (flags & I_DIRTY_INODE) | ||
| 1225 | inode->i_state &= ~I_DIRTY_TIME; | ||
| 1188 | inode->i_state |= flags; | 1226 | inode->i_state |= flags; |
| 1189 | 1227 | ||
| 1190 | /* | 1228 | /* |
| @@ -1231,8 +1269,10 @@ void __mark_inode_dirty(struct inode *inode, int flags) | |||
| 1231 | } | 1269 | } |
| 1232 | 1270 | ||
| 1233 | inode->dirtied_when = jiffies; | 1271 | inode->dirtied_when = jiffies; |
| 1234 | list_move(&inode->i_wb_list, &bdi->wb.b_dirty); | 1272 | list_move(&inode->i_wb_list, dirtytime ? |
| 1273 | &bdi->wb.b_dirty_time : &bdi->wb.b_dirty); | ||
| 1235 | spin_unlock(&bdi->wb.list_lock); | 1274 | spin_unlock(&bdi->wb.list_lock); |
| 1275 | trace_writeback_dirty_inode_enqueue(inode); | ||
| 1236 | 1276 | ||
| 1237 | if (wakeup_bdi) | 1277 | if (wakeup_bdi) |
| 1238 | bdi_wakeup_thread_delayed(bdi); | 1278 | bdi_wakeup_thread_delayed(bdi); |
diff --git a/fs/fs_pin.c b/fs/fs_pin.c index 9368236ca100..b06c98796afb 100644 --- a/fs/fs_pin.c +++ b/fs/fs_pin.c | |||
| @@ -1,78 +1,102 @@ | |||
| 1 | #include <linux/fs.h> | 1 | #include <linux/fs.h> |
| 2 | #include <linux/sched.h> | ||
| 2 | #include <linux/slab.h> | 3 | #include <linux/slab.h> |
| 3 | #include <linux/fs_pin.h> | ||
| 4 | #include "internal.h" | 4 | #include "internal.h" |
| 5 | #include "mount.h" | 5 | #include "mount.h" |
| 6 | 6 | ||
| 7 | static void pin_free_rcu(struct rcu_head *head) | ||
| 8 | { | ||
| 9 | kfree(container_of(head, struct fs_pin, rcu)); | ||
| 10 | } | ||
| 11 | |||
| 12 | static DEFINE_SPINLOCK(pin_lock); | 7 | static DEFINE_SPINLOCK(pin_lock); |
| 13 | 8 | ||
| 14 | void pin_put(struct fs_pin *p) | ||
| 15 | { | ||
| 16 | if (atomic_long_dec_and_test(&p->count)) | ||
| 17 | call_rcu(&p->rcu, pin_free_rcu); | ||
| 18 | } | ||
| 19 | |||
| 20 | void pin_remove(struct fs_pin *pin) | 9 | void pin_remove(struct fs_pin *pin) |
| 21 | { | 10 | { |
| 22 | spin_lock(&pin_lock); | 11 | spin_lock(&pin_lock); |
| 23 | hlist_del(&pin->m_list); | 12 | hlist_del(&pin->m_list); |
| 24 | hlist_del(&pin->s_list); | 13 | hlist_del(&pin->s_list); |
| 25 | spin_unlock(&pin_lock); | 14 | spin_unlock(&pin_lock); |
| 15 | spin_lock_irq(&pin->wait.lock); | ||
| 16 | pin->done = 1; | ||
| 17 | wake_up_locked(&pin->wait); | ||
| 18 | spin_unlock_irq(&pin->wait.lock); | ||
| 26 | } | 19 | } |
| 27 | 20 | ||
| 28 | void pin_insert(struct fs_pin *pin, struct vfsmount *m) | 21 | void pin_insert_group(struct fs_pin *pin, struct vfsmount *m, struct hlist_head *p) |
| 29 | { | 22 | { |
| 30 | spin_lock(&pin_lock); | 23 | spin_lock(&pin_lock); |
| 31 | hlist_add_head(&pin->s_list, &m->mnt_sb->s_pins); | 24 | if (p) |
| 25 | hlist_add_head(&pin->s_list, p); | ||
| 32 | hlist_add_head(&pin->m_list, &real_mount(m)->mnt_pins); | 26 | hlist_add_head(&pin->m_list, &real_mount(m)->mnt_pins); |
| 33 | spin_unlock(&pin_lock); | 27 | spin_unlock(&pin_lock); |
| 34 | } | 28 | } |
| 35 | 29 | ||
| 30 | void pin_insert(struct fs_pin *pin, struct vfsmount *m) | ||
| 31 | { | ||
| 32 | pin_insert_group(pin, m, &m->mnt_sb->s_pins); | ||
| 33 | } | ||
| 34 | |||
| 35 | void pin_kill(struct fs_pin *p) | ||
| 36 | { | ||
| 37 | wait_queue_t wait; | ||
| 38 | |||
| 39 | if (!p) { | ||
| 40 | rcu_read_unlock(); | ||
| 41 | return; | ||
| 42 | } | ||
| 43 | init_wait(&wait); | ||
| 44 | spin_lock_irq(&p->wait.lock); | ||
| 45 | if (likely(!p->done)) { | ||
| 46 | p->done = -1; | ||
| 47 | spin_unlock_irq(&p->wait.lock); | ||
| 48 | rcu_read_unlock(); | ||
| 49 | p->kill(p); | ||
| 50 | return; | ||
| 51 | } | ||
| 52 | if (p->done > 0) { | ||
| 53 | spin_unlock_irq(&p->wait.lock); | ||
| 54 | rcu_read_unlock(); | ||
| 55 | return; | ||
| 56 | } | ||
| 57 | __add_wait_queue(&p->wait, &wait); | ||
| 58 | while (1) { | ||
| 59 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
| 60 | spin_unlock_irq(&p->wait.lock); | ||
| 61 | rcu_read_unlock(); | ||
| 62 | schedule(); | ||
| 63 | rcu_read_lock(); | ||
| 64 | if (likely(list_empty(&wait.task_list))) | ||
| 65 | break; | ||
| 66 | /* OK, we know p couldn't have been freed yet */ | ||
| 67 | spin_lock_irq(&p->wait.lock); | ||
| 68 | if (p->done > 0) { | ||
| 69 | spin_unlock_irq(&p->wait.lock); | ||
| 70 | break; | ||
| 71 | } | ||
| 72 | } | ||
| 73 | rcu_read_unlock(); | ||
| 74 | } | ||
| 75 | |||
| 36 | void mnt_pin_kill(struct mount *m) | 76 | void mnt_pin_kill(struct mount *m) |
| 37 | { | 77 | { |
| 38 | while (1) { | 78 | while (1) { |
| 39 | struct hlist_node *p; | 79 | struct hlist_node *p; |
| 40 | struct fs_pin *pin; | ||
| 41 | rcu_read_lock(); | 80 | rcu_read_lock(); |
| 42 | p = ACCESS_ONCE(m->mnt_pins.first); | 81 | p = ACCESS_ONCE(m->mnt_pins.first); |
| 43 | if (!p) { | 82 | if (!p) { |
| 44 | rcu_read_unlock(); | 83 | rcu_read_unlock(); |
| 45 | break; | 84 | break; |
| 46 | } | 85 | } |
| 47 | pin = hlist_entry(p, struct fs_pin, m_list); | 86 | pin_kill(hlist_entry(p, struct fs_pin, m_list)); |
| 48 | if (!atomic_long_inc_not_zero(&pin->count)) { | ||
| 49 | rcu_read_unlock(); | ||
| 50 | cpu_relax(); | ||
| 51 | continue; | ||
| 52 | } | ||
| 53 | rcu_read_unlock(); | ||
| 54 | pin->kill(pin); | ||
| 55 | } | 87 | } |
| 56 | } | 88 | } |
| 57 | 89 | ||
| 58 | void sb_pin_kill(struct super_block *sb) | 90 | void group_pin_kill(struct hlist_head *p) |
| 59 | { | 91 | { |
| 60 | while (1) { | 92 | while (1) { |
| 61 | struct hlist_node *p; | 93 | struct hlist_node *q; |
| 62 | struct fs_pin *pin; | ||
| 63 | rcu_read_lock(); | 94 | rcu_read_lock(); |
| 64 | p = ACCESS_ONCE(sb->s_pins.first); | 95 | q = ACCESS_ONCE(p->first); |
| 65 | if (!p) { | 96 | if (!q) { |
| 66 | rcu_read_unlock(); | 97 | rcu_read_unlock(); |
| 67 | break; | 98 | break; |
| 68 | } | 99 | } |
| 69 | pin = hlist_entry(p, struct fs_pin, s_list); | 100 | pin_kill(hlist_entry(q, struct fs_pin, s_list)); |
| 70 | if (!atomic_long_inc_not_zero(&pin->count)) { | ||
| 71 | rcu_read_unlock(); | ||
| 72 | cpu_relax(); | ||
| 73 | continue; | ||
| 74 | } | ||
| 75 | rcu_read_unlock(); | ||
| 76 | pin->kill(pin); | ||
| 77 | } | 101 | } |
| 78 | } | 102 | } |
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index ec9c2d33477a..3e32bb8e2d7e 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c | |||
| @@ -654,7 +654,7 @@ static int gfs2_fsync(struct file *file, loff_t start, loff_t end, | |||
| 654 | { | 654 | { |
| 655 | struct address_space *mapping = file->f_mapping; | 655 | struct address_space *mapping = file->f_mapping; |
| 656 | struct inode *inode = mapping->host; | 656 | struct inode *inode = mapping->host; |
| 657 | int sync_state = inode->i_state & I_DIRTY; | 657 | int sync_state = inode->i_state & I_DIRTY_ALL; |
| 658 | struct gfs2_inode *ip = GFS2_I(inode); | 658 | struct gfs2_inode *ip = GFS2_I(inode); |
| 659 | int ret = 0, ret1 = 0; | 659 | int ret = 0, ret1 = 0; |
| 660 | 660 | ||
| @@ -667,7 +667,7 @@ static int gfs2_fsync(struct file *file, loff_t start, loff_t end, | |||
| 667 | if (!gfs2_is_jdata(ip)) | 667 | if (!gfs2_is_jdata(ip)) |
| 668 | sync_state &= ~I_DIRTY_PAGES; | 668 | sync_state &= ~I_DIRTY_PAGES; |
| 669 | if (datasync) | 669 | if (datasync) |
| 670 | sync_state &= ~I_DIRTY_SYNC; | 670 | sync_state &= ~(I_DIRTY_SYNC | I_DIRTY_TIME); |
| 671 | 671 | ||
| 672 | if (sync_state) { | 672 | if (sync_state) { |
| 673 | ret = sync_inode_metadata(inode, 1); | 673 | ret = sync_inode_metadata(inode, 1); |
diff --git a/fs/inode.c b/fs/inode.c index 86bfaca724db..f00b16f45507 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/buffer_head.h> /* for inode_has_buffers */ | 18 | #include <linux/buffer_head.h> /* for inode_has_buffers */ |
| 19 | #include <linux/ratelimit.h> | 19 | #include <linux/ratelimit.h> |
| 20 | #include <linux/list_lru.h> | 20 | #include <linux/list_lru.h> |
| 21 | #include <trace/events/writeback.h> | ||
| 21 | #include "internal.h" | 22 | #include "internal.h" |
| 22 | 23 | ||
| 23 | /* | 24 | /* |
| @@ -30,7 +31,7 @@ | |||
| 30 | * inode_sb_list_lock protects: | 31 | * inode_sb_list_lock protects: |
| 31 | * sb->s_inodes, inode->i_sb_list | 32 | * sb->s_inodes, inode->i_sb_list |
| 32 | * bdi->wb.list_lock protects: | 33 | * bdi->wb.list_lock protects: |
| 33 | * bdi->wb.b_{dirty,io,more_io}, inode->i_wb_list | 34 | * bdi->wb.b_{dirty,io,more_io,dirty_time}, inode->i_wb_list |
| 34 | * inode_hash_lock protects: | 35 | * inode_hash_lock protects: |
| 35 | * inode_hashtable, inode->i_hash | 36 | * inode_hashtable, inode->i_hash |
| 36 | * | 37 | * |
| @@ -403,7 +404,8 @@ static void inode_lru_list_add(struct inode *inode) | |||
| 403 | */ | 404 | */ |
| 404 | void inode_add_lru(struct inode *inode) | 405 | void inode_add_lru(struct inode *inode) |
| 405 | { | 406 | { |
| 406 | if (!(inode->i_state & (I_DIRTY | I_SYNC | I_FREEING | I_WILL_FREE)) && | 407 | if (!(inode->i_state & (I_DIRTY_ALL | I_SYNC | |
| 408 | I_FREEING | I_WILL_FREE)) && | ||
| 407 | !atomic_read(&inode->i_count) && inode->i_sb->s_flags & MS_ACTIVE) | 409 | !atomic_read(&inode->i_count) && inode->i_sb->s_flags & MS_ACTIVE) |
| 408 | inode_lru_list_add(inode); | 410 | inode_lru_list_add(inode); |
| 409 | } | 411 | } |
| @@ -634,7 +636,7 @@ int invalidate_inodes(struct super_block *sb, bool kill_dirty) | |||
| 634 | spin_unlock(&inode->i_lock); | 636 | spin_unlock(&inode->i_lock); |
| 635 | continue; | 637 | continue; |
| 636 | } | 638 | } |
| 637 | if (inode->i_state & I_DIRTY && !kill_dirty) { | 639 | if (inode->i_state & I_DIRTY_ALL && !kill_dirty) { |
| 638 | spin_unlock(&inode->i_lock); | 640 | spin_unlock(&inode->i_lock); |
| 639 | busy = 1; | 641 | busy = 1; |
| 640 | continue; | 642 | continue; |
| @@ -1268,6 +1270,56 @@ struct inode *ilookup(struct super_block *sb, unsigned long ino) | |||
| 1268 | } | 1270 | } |
| 1269 | EXPORT_SYMBOL(ilookup); | 1271 | EXPORT_SYMBOL(ilookup); |
| 1270 | 1272 | ||
| 1273 | /** | ||
| 1274 | * find_inode_nowait - find an inode in the inode cache | ||
| 1275 | * @sb: super block of file system to search | ||
| 1276 | * @hashval: hash value (usually inode number) to search for | ||
| 1277 | * @match: callback used for comparisons between inodes | ||
| 1278 | * @data: opaque data pointer to pass to @match | ||
| 1279 | * | ||
| 1280 | * Search for the inode specified by @hashval and @data in the inode | ||
| 1281 | * cache, where the helper function @match will return 0 if the inode | ||
| 1282 | * does not match, 1 if the inode does match, and -1 if the search | ||
| 1283 | * should be stopped. The @match function must be responsible for | ||
| 1284 | * taking the i_lock spin_lock and checking i_state for an inode being | ||
| 1285 | * freed or being initialized, and incrementing the reference count | ||
| 1286 | * before returning 1. It also must not sleep, since it is called with | ||
| 1287 | * the inode_hash_lock spinlock held. | ||
| 1288 | * | ||
| 1289 | * This is a even more generalized version of ilookup5() when the | ||
| 1290 | * function must never block --- find_inode() can block in | ||
| 1291 | * __wait_on_freeing_inode() --- or when the caller can not increment | ||
| 1292 | * the reference count because the resulting iput() might cause an | ||
| 1293 | * inode eviction. The tradeoff is that the @match funtion must be | ||
| 1294 | * very carefully implemented. | ||
| 1295 | */ | ||
| 1296 | struct inode *find_inode_nowait(struct super_block *sb, | ||
| 1297 | unsigned long hashval, | ||
| 1298 | int (*match)(struct inode *, unsigned long, | ||
| 1299 | void *), | ||
| 1300 | void *data) | ||
| 1301 | { | ||
| 1302 | struct hlist_head *head = inode_hashtable + hash(sb, hashval); | ||
| 1303 | struct inode *inode, *ret_inode = NULL; | ||
| 1304 | int mval; | ||
| 1305 | |||
| 1306 | spin_lock(&inode_hash_lock); | ||
| 1307 | hlist_for_each_entry(inode, head, i_hash) { | ||
| 1308 | if (inode->i_sb != sb) | ||
| 1309 | continue; | ||
| 1310 | mval = match(inode, hashval, data); | ||
| 1311 | if (mval == 0) | ||
| 1312 | continue; | ||
| 1313 | if (mval == 1) | ||
| 1314 | ret_inode = inode; | ||
| 1315 | goto out; | ||
| 1316 | } | ||
| 1317 | out: | ||
| 1318 | spin_unlock(&inode_hash_lock); | ||
| 1319 | return ret_inode; | ||
| 1320 | } | ||
| 1321 | EXPORT_SYMBOL(find_inode_nowait); | ||
| 1322 | |||
| 1271 | int insert_inode_locked(struct inode *inode) | 1323 | int insert_inode_locked(struct inode *inode) |
| 1272 | { | 1324 | { |
| 1273 | struct super_block *sb = inode->i_sb; | 1325 | struct super_block *sb = inode->i_sb; |
| @@ -1418,11 +1470,20 @@ static void iput_final(struct inode *inode) | |||
| 1418 | */ | 1470 | */ |
| 1419 | void iput(struct inode *inode) | 1471 | void iput(struct inode *inode) |
| 1420 | { | 1472 | { |
| 1421 | if (inode) { | 1473 | if (!inode) |
| 1422 | BUG_ON(inode->i_state & I_CLEAR); | 1474 | return; |
| 1423 | 1475 | BUG_ON(inode->i_state & I_CLEAR); | |
| 1424 | if (atomic_dec_and_lock(&inode->i_count, &inode->i_lock)) | 1476 | retry: |
| 1425 | iput_final(inode); | 1477 | if (atomic_dec_and_lock(&inode->i_count, &inode->i_lock)) { |
| 1478 | if (inode->i_nlink && (inode->i_state & I_DIRTY_TIME)) { | ||
| 1479 | atomic_inc(&inode->i_count); | ||
| 1480 | inode->i_state &= ~I_DIRTY_TIME; | ||
| 1481 | spin_unlock(&inode->i_lock); | ||
| 1482 | trace_writeback_lazytime_iput(inode); | ||
| 1483 | mark_inode_dirty_sync(inode); | ||
| 1484 | goto retry; | ||
| 1485 | } | ||
| 1486 | iput_final(inode); | ||
| 1426 | } | 1487 | } |
| 1427 | } | 1488 | } |
| 1428 | EXPORT_SYMBOL(iput); | 1489 | EXPORT_SYMBOL(iput); |
| @@ -1481,14 +1542,9 @@ static int relatime_need_update(struct vfsmount *mnt, struct inode *inode, | |||
| 1481 | return 0; | 1542 | return 0; |
| 1482 | } | 1543 | } |
| 1483 | 1544 | ||
| 1484 | /* | 1545 | int generic_update_time(struct inode *inode, struct timespec *time, int flags) |
| 1485 | * This does the actual work of updating an inodes time or version. Must have | ||
| 1486 | * had called mnt_want_write() before calling this. | ||
| 1487 | */ | ||
| 1488 | static int update_time(struct inode *inode, struct timespec *time, int flags) | ||
| 1489 | { | 1546 | { |
| 1490 | if (inode->i_op->update_time) | 1547 | int iflags = I_DIRTY_TIME; |
| 1491 | return inode->i_op->update_time(inode, time, flags); | ||
| 1492 | 1548 | ||
| 1493 | if (flags & S_ATIME) | 1549 | if (flags & S_ATIME) |
| 1494 | inode->i_atime = *time; | 1550 | inode->i_atime = *time; |
| @@ -1498,9 +1554,27 @@ static int update_time(struct inode *inode, struct timespec *time, int flags) | |||
| 1498 | inode->i_ctime = *time; | 1554 | inode->i_ctime = *time; |
| 1499 | if (flags & S_MTIME) | 1555 | if (flags & S_MTIME) |
| 1500 | inode->i_mtime = *time; | 1556 | inode->i_mtime = *time; |
| 1501 | mark_inode_dirty_sync(inode); | 1557 | |
| 1558 | if (!(inode->i_sb->s_flags & MS_LAZYTIME) || (flags & S_VERSION)) | ||
| 1559 | iflags |= I_DIRTY_SYNC; | ||
| 1560 | __mark_inode_dirty(inode, iflags); | ||
| 1502 | return 0; | 1561 | return 0; |
| 1503 | } | 1562 | } |
| 1563 | EXPORT_SYMBOL(generic_update_time); | ||
| 1564 | |||
| 1565 | /* | ||
| 1566 | * This does the actual work of updating an inodes time or version. Must have | ||
| 1567 | * had called mnt_want_write() before calling this. | ||
| 1568 | */ | ||
| 1569 | static int update_time(struct inode *inode, struct timespec *time, int flags) | ||
| 1570 | { | ||
| 1571 | int (*update_time)(struct inode *, struct timespec *, int); | ||
| 1572 | |||
| 1573 | update_time = inode->i_op->update_time ? inode->i_op->update_time : | ||
| 1574 | generic_update_time; | ||
| 1575 | |||
| 1576 | return update_time(inode, time, flags); | ||
| 1577 | } | ||
| 1504 | 1578 | ||
| 1505 | /** | 1579 | /** |
| 1506 | * touch_atime - update the access time | 1580 | * touch_atime - update the access time |
diff --git a/fs/internal.h b/fs/internal.h index d92c346a793d..30459dab409d 100644 --- a/fs/internal.h +++ b/fs/internal.h | |||
| @@ -144,7 +144,7 @@ extern const struct file_operations pipefifo_fops; | |||
| 144 | /* | 144 | /* |
| 145 | * fs_pin.c | 145 | * fs_pin.c |
| 146 | */ | 146 | */ |
| 147 | extern void sb_pin_kill(struct super_block *sb); | 147 | extern void group_pin_kill(struct hlist_head *p); |
| 148 | extern void mnt_pin_kill(struct mount *m); | 148 | extern void mnt_pin_kill(struct mount *m); |
| 149 | 149 | ||
| 150 | /* | 150 | /* |
diff --git a/fs/jffs2/compr_rubin.c b/fs/jffs2/compr_rubin.c index 92e0644bf867..556de100ebd5 100644 --- a/fs/jffs2/compr_rubin.c +++ b/fs/jffs2/compr_rubin.c | |||
| @@ -84,11 +84,6 @@ static inline int pullbit(struct pushpull *pp) | |||
| 84 | return bit; | 84 | return bit; |
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | static inline int pulledbits(struct pushpull *pp) | ||
| 88 | { | ||
| 89 | return pp->ofs; | ||
| 90 | } | ||
| 91 | |||
| 92 | 87 | ||
| 93 | static void init_rubin(struct rubin_state *rs, int div, int *bits) | 88 | static void init_rubin(struct rubin_state *rs, int div, int *bits) |
| 94 | { | 89 | { |
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 7654e87b0428..9ad5ba4b299b 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c | |||
| @@ -510,6 +510,10 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo | |||
| 510 | sumlen = c->sector_size - je32_to_cpu(sm->offset); | 510 | sumlen = c->sector_size - je32_to_cpu(sm->offset); |
| 511 | sumptr = buf + buf_size - sumlen; | 511 | sumptr = buf + buf_size - sumlen; |
| 512 | 512 | ||
| 513 | /* sm->offset maybe wrong but MAGIC maybe right */ | ||
| 514 | if (sumlen > c->sector_size) | ||
| 515 | goto full_scan; | ||
| 516 | |||
| 513 | /* Now, make sure the summary itself is available */ | 517 | /* Now, make sure the summary itself is available */ |
| 514 | if (sumlen > buf_size) { | 518 | if (sumlen > buf_size) { |
| 515 | /* Need to kmalloc for this. */ | 519 | /* Need to kmalloc for this. */ |
| @@ -544,6 +548,7 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo | |||
| 544 | } | 548 | } |
| 545 | } | 549 | } |
| 546 | 550 | ||
| 551 | full_scan: | ||
| 547 | buf_ofs = jeb->offset; | 552 | buf_ofs = jeb->offset; |
| 548 | 553 | ||
| 549 | if (!buf_size) { | 554 | if (!buf_size) { |
diff --git a/fs/jfs/file.c b/fs/jfs/file.c index 33aa0cc1f8b8..10815f8dfd8b 100644 --- a/fs/jfs/file.c +++ b/fs/jfs/file.c | |||
| @@ -39,7 +39,7 @@ int jfs_fsync(struct file *file, loff_t start, loff_t end, int datasync) | |||
| 39 | return rc; | 39 | return rc; |
| 40 | 40 | ||
| 41 | mutex_lock(&inode->i_mutex); | 41 | mutex_lock(&inode->i_mutex); |
| 42 | if (!(inode->i_state & I_DIRTY) || | 42 | if (!(inode->i_state & I_DIRTY_ALL) || |
| 43 | (datasync && !(inode->i_state & I_DIRTY_DATASYNC))) { | 43 | (datasync && !(inode->i_state & I_DIRTY_DATASYNC))) { |
| 44 | /* Make sure committed changes hit the disk */ | 44 | /* Make sure committed changes hit the disk */ |
| 45 | jfs_flush_journal(JFS_SBI(inode->i_sb)->log, 1); | 45 | jfs_flush_journal(JFS_SBI(inode->i_sb)->log, 1); |
diff --git a/fs/libfs.c b/fs/libfs.c index 005843ce5dbd..b2ffdb045be4 100644 --- a/fs/libfs.c +++ b/fs/libfs.c | |||
| @@ -948,7 +948,7 @@ int __generic_file_fsync(struct file *file, loff_t start, loff_t end, | |||
| 948 | 948 | ||
| 949 | mutex_lock(&inode->i_mutex); | 949 | mutex_lock(&inode->i_mutex); |
| 950 | ret = sync_mapping_buffers(inode->i_mapping); | 950 | ret = sync_mapping_buffers(inode->i_mapping); |
| 951 | if (!(inode->i_state & I_DIRTY)) | 951 | if (!(inode->i_state & I_DIRTY_ALL)) |
| 952 | goto out; | 952 | goto out; |
| 953 | if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) | 953 | if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) |
| 954 | goto out; | 954 | goto out; |
diff --git a/fs/mount.h b/fs/mount.h index 0ad6f760ce52..6a61c2b3e385 100644 --- a/fs/mount.h +++ b/fs/mount.h | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | #include <linux/seq_file.h> | 2 | #include <linux/seq_file.h> |
| 3 | #include <linux/poll.h> | 3 | #include <linux/poll.h> |
| 4 | #include <linux/ns_common.h> | 4 | #include <linux/ns_common.h> |
| 5 | #include <linux/fs_pin.h> | ||
| 5 | 6 | ||
| 6 | struct mnt_namespace { | 7 | struct mnt_namespace { |
| 7 | atomic_t count; | 8 | atomic_t count; |
| @@ -62,7 +63,8 @@ struct mount { | |||
| 62 | int mnt_group_id; /* peer group identifier */ | 63 | int mnt_group_id; /* peer group identifier */ |
| 63 | int mnt_expiry_mark; /* true if marked for expiry */ | 64 | int mnt_expiry_mark; /* true if marked for expiry */ |
| 64 | struct hlist_head mnt_pins; | 65 | struct hlist_head mnt_pins; |
| 65 | struct path mnt_ex_mountpoint; | 66 | struct fs_pin mnt_umount; |
| 67 | struct dentry *mnt_ex_mountpoint; | ||
| 66 | }; | 68 | }; |
| 67 | 69 | ||
| 68 | #define MNT_NS_INTERNAL ERR_PTR(-EINVAL) /* distinct from any mnt_namespace */ | 70 | #define MNT_NS_INTERNAL ERR_PTR(-EINVAL) /* distinct from any mnt_namespace */ |
diff --git a/fs/namei.c b/fs/namei.c index bc35b02883bb..96ca11dea4a2 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -118,15 +118,6 @@ | |||
| 118 | * POSIX.1 2.4: an empty pathname is invalid (ENOENT). | 118 | * POSIX.1 2.4: an empty pathname is invalid (ENOENT). |
| 119 | * PATH_MAX includes the nul terminator --RR. | 119 | * PATH_MAX includes the nul terminator --RR. |
| 120 | */ | 120 | */ |
| 121 | void final_putname(struct filename *name) | ||
| 122 | { | ||
| 123 | if (name->separate) { | ||
| 124 | __putname(name->name); | ||
| 125 | kfree(name); | ||
| 126 | } else { | ||
| 127 | __putname(name); | ||
| 128 | } | ||
| 129 | } | ||
| 130 | 121 | ||
| 131 | #define EMBEDDED_NAME_MAX (PATH_MAX - sizeof(struct filename)) | 122 | #define EMBEDDED_NAME_MAX (PATH_MAX - sizeof(struct filename)) |
| 132 | 123 | ||
| @@ -145,6 +136,7 @@ getname_flags(const char __user *filename, int flags, int *empty) | |||
| 145 | result = __getname(); | 136 | result = __getname(); |
| 146 | if (unlikely(!result)) | 137 | if (unlikely(!result)) |
| 147 | return ERR_PTR(-ENOMEM); | 138 | return ERR_PTR(-ENOMEM); |
| 139 | result->refcnt = 1; | ||
| 148 | 140 | ||
| 149 | /* | 141 | /* |
| 150 | * First, try to embed the struct filename inside the names_cache | 142 | * First, try to embed the struct filename inside the names_cache |
| @@ -179,6 +171,7 @@ recopy: | |||
| 179 | } | 171 | } |
| 180 | result->name = kname; | 172 | result->name = kname; |
| 181 | result->separate = true; | 173 | result->separate = true; |
| 174 | result->refcnt = 1; | ||
| 182 | max = PATH_MAX; | 175 | max = PATH_MAX; |
| 183 | goto recopy; | 176 | goto recopy; |
| 184 | } | 177 | } |
| @@ -202,7 +195,7 @@ recopy: | |||
| 202 | return result; | 195 | return result; |
| 203 | 196 | ||
| 204 | error: | 197 | error: |
| 205 | final_putname(result); | 198 | putname(result); |
| 206 | return err; | 199 | return err; |
| 207 | } | 200 | } |
| 208 | 201 | ||
| @@ -212,43 +205,56 @@ getname(const char __user * filename) | |||
| 212 | return getname_flags(filename, 0, NULL); | 205 | return getname_flags(filename, 0, NULL); |
| 213 | } | 206 | } |
| 214 | 207 | ||
| 215 | /* | ||
| 216 | * The "getname_kernel()" interface doesn't do pathnames longer | ||
| 217 | * than EMBEDDED_NAME_MAX. Deal with it - you're a kernel user. | ||
| 218 | */ | ||
| 219 | struct filename * | 208 | struct filename * |
| 220 | getname_kernel(const char * filename) | 209 | getname_kernel(const char * filename) |
| 221 | { | 210 | { |
| 222 | struct filename *result; | 211 | struct filename *result; |
| 223 | char *kname; | 212 | int len = strlen(filename) + 1; |
| 224 | int len; | ||
| 225 | |||
| 226 | len = strlen(filename); | ||
| 227 | if (len >= EMBEDDED_NAME_MAX) | ||
| 228 | return ERR_PTR(-ENAMETOOLONG); | ||
| 229 | 213 | ||
| 230 | result = __getname(); | 214 | result = __getname(); |
| 231 | if (unlikely(!result)) | 215 | if (unlikely(!result)) |
| 232 | return ERR_PTR(-ENOMEM); | 216 | return ERR_PTR(-ENOMEM); |
| 233 | 217 | ||
| 234 | kname = (char *)result + sizeof(*result); | 218 | if (len <= EMBEDDED_NAME_MAX) { |
| 235 | result->name = kname; | 219 | result->name = (char *)(result) + sizeof(*result); |
| 220 | result->separate = false; | ||
| 221 | } else if (len <= PATH_MAX) { | ||
| 222 | struct filename *tmp; | ||
| 223 | |||
| 224 | tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); | ||
| 225 | if (unlikely(!tmp)) { | ||
| 226 | __putname(result); | ||
| 227 | return ERR_PTR(-ENOMEM); | ||
| 228 | } | ||
| 229 | tmp->name = (char *)result; | ||
| 230 | tmp->separate = true; | ||
| 231 | result = tmp; | ||
| 232 | } else { | ||
| 233 | __putname(result); | ||
| 234 | return ERR_PTR(-ENAMETOOLONG); | ||
| 235 | } | ||
| 236 | memcpy((char *)result->name, filename, len); | ||
| 236 | result->uptr = NULL; | 237 | result->uptr = NULL; |
| 237 | result->aname = NULL; | 238 | result->aname = NULL; |
| 238 | result->separate = false; | 239 | result->refcnt = 1; |
| 240 | audit_getname(result); | ||
| 239 | 241 | ||
| 240 | strlcpy(kname, filename, EMBEDDED_NAME_MAX); | ||
| 241 | return result; | 242 | return result; |
| 242 | } | 243 | } |
| 243 | 244 | ||
| 244 | #ifdef CONFIG_AUDITSYSCALL | ||
| 245 | void putname(struct filename *name) | 245 | void putname(struct filename *name) |
| 246 | { | 246 | { |
| 247 | if (unlikely(!audit_dummy_context())) | 247 | BUG_ON(name->refcnt <= 0); |
| 248 | return audit_putname(name); | 248 | |
| 249 | final_putname(name); | 249 | if (--name->refcnt > 0) |
| 250 | return; | ||
| 251 | |||
| 252 | if (name->separate) { | ||
| 253 | __putname(name->name); | ||
| 254 | kfree(name); | ||
| 255 | } else | ||
| 256 | __putname(name); | ||
| 250 | } | 257 | } |
| 251 | #endif | ||
| 252 | 258 | ||
| 253 | static int check_acl(struct inode *inode, int mask) | 259 | static int check_acl(struct inode *inode, int mask) |
| 254 | { | 260 | { |
| @@ -2036,31 +2042,47 @@ static int filename_lookup(int dfd, struct filename *name, | |||
| 2036 | static int do_path_lookup(int dfd, const char *name, | 2042 | static int do_path_lookup(int dfd, const char *name, |
| 2037 | unsigned int flags, struct nameidata *nd) | 2043 | unsigned int flags, struct nameidata *nd) |
| 2038 | { | 2044 | { |
| 2039 | struct filename filename = { .name = name }; | 2045 | struct filename *filename = getname_kernel(name); |
| 2046 | int retval = PTR_ERR(filename); | ||
| 2040 | 2047 | ||
| 2041 | return filename_lookup(dfd, &filename, flags, nd); | 2048 | if (!IS_ERR(filename)) { |
| 2049 | retval = filename_lookup(dfd, filename, flags, nd); | ||
| 2050 | putname(filename); | ||
| 2051 | } | ||
| 2052 | return retval; | ||
| 2042 | } | 2053 | } |
| 2043 | 2054 | ||
| 2044 | /* does lookup, returns the object with parent locked */ | 2055 | /* does lookup, returns the object with parent locked */ |
| 2045 | struct dentry *kern_path_locked(const char *name, struct path *path) | 2056 | struct dentry *kern_path_locked(const char *name, struct path *path) |
| 2046 | { | 2057 | { |
| 2058 | struct filename *filename = getname_kernel(name); | ||
| 2047 | struct nameidata nd; | 2059 | struct nameidata nd; |
| 2048 | struct dentry *d; | 2060 | struct dentry *d; |
| 2049 | int err = do_path_lookup(AT_FDCWD, name, LOOKUP_PARENT, &nd); | 2061 | int err; |
| 2050 | if (err) | 2062 | |
| 2051 | return ERR_PTR(err); | 2063 | if (IS_ERR(filename)) |
| 2064 | return ERR_CAST(filename); | ||
| 2065 | |||
| 2066 | err = filename_lookup(AT_FDCWD, filename, LOOKUP_PARENT, &nd); | ||
| 2067 | if (err) { | ||
| 2068 | d = ERR_PTR(err); | ||
| 2069 | goto out; | ||
| 2070 | } | ||
| 2052 | if (nd.last_type != LAST_NORM) { | 2071 | if (nd.last_type != LAST_NORM) { |
| 2053 | path_put(&nd.path); | 2072 | path_put(&nd.path); |
| 2054 | return ERR_PTR(-EINVAL); | 2073 | d = ERR_PTR(-EINVAL); |
| 2074 | goto out; | ||
| 2055 | } | 2075 | } |
| 2056 | mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); | 2076 | mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); |
| 2057 | d = __lookup_hash(&nd.last, nd.path.dentry, 0); | 2077 | d = __lookup_hash(&nd.last, nd.path.dentry, 0); |
| 2058 | if (IS_ERR(d)) { | 2078 | if (IS_ERR(d)) { |
| 2059 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 2079 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
| 2060 | path_put(&nd.path); | 2080 | path_put(&nd.path); |
| 2061 | return d; | 2081 | goto out; |
| 2062 | } | 2082 | } |
| 2063 | *path = nd.path; | 2083 | *path = nd.path; |
| 2084 | out: | ||
| 2085 | putname(filename); | ||
| 2064 | return d; | 2086 | return d; |
| 2065 | } | 2087 | } |
| 2066 | 2088 | ||
| @@ -2351,13 +2373,17 @@ static int | |||
| 2351 | filename_mountpoint(int dfd, struct filename *s, struct path *path, | 2373 | filename_mountpoint(int dfd, struct filename *s, struct path *path, |
| 2352 | unsigned int flags) | 2374 | unsigned int flags) |
| 2353 | { | 2375 | { |
| 2354 | int error = path_mountpoint(dfd, s->name, path, flags | LOOKUP_RCU); | 2376 | int error; |
| 2377 | if (IS_ERR(s)) | ||
| 2378 | return PTR_ERR(s); | ||
| 2379 | error = path_mountpoint(dfd, s->name, path, flags | LOOKUP_RCU); | ||
| 2355 | if (unlikely(error == -ECHILD)) | 2380 | if (unlikely(error == -ECHILD)) |
| 2356 | error = path_mountpoint(dfd, s->name, path, flags); | 2381 | error = path_mountpoint(dfd, s->name, path, flags); |
| 2357 | if (unlikely(error == -ESTALE)) | 2382 | if (unlikely(error == -ESTALE)) |
| 2358 | error = path_mountpoint(dfd, s->name, path, flags | LOOKUP_REVAL); | 2383 | error = path_mountpoint(dfd, s->name, path, flags | LOOKUP_REVAL); |
| 2359 | if (likely(!error)) | 2384 | if (likely(!error)) |
| 2360 | audit_inode(s, path->dentry, 0); | 2385 | audit_inode(s, path->dentry, 0); |
| 2386 | putname(s); | ||
| 2361 | return error; | 2387 | return error; |
| 2362 | } | 2388 | } |
| 2363 | 2389 | ||
| @@ -2379,21 +2405,14 @@ int | |||
| 2379 | user_path_mountpoint_at(int dfd, const char __user *name, unsigned int flags, | 2405 | user_path_mountpoint_at(int dfd, const char __user *name, unsigned int flags, |
| 2380 | struct path *path) | 2406 | struct path *path) |
| 2381 | { | 2407 | { |
| 2382 | struct filename *s = getname(name); | 2408 | return filename_mountpoint(dfd, getname(name), path, flags); |
| 2383 | int error; | ||
| 2384 | if (IS_ERR(s)) | ||
| 2385 | return PTR_ERR(s); | ||
| 2386 | error = filename_mountpoint(dfd, s, path, flags); | ||
| 2387 | putname(s); | ||
| 2388 | return error; | ||
| 2389 | } | 2409 | } |
| 2390 | 2410 | ||
| 2391 | int | 2411 | int |
| 2392 | kern_path_mountpoint(int dfd, const char *name, struct path *path, | 2412 | kern_path_mountpoint(int dfd, const char *name, struct path *path, |
| 2393 | unsigned int flags) | 2413 | unsigned int flags) |
| 2394 | { | 2414 | { |
| 2395 | struct filename s = {.name = name}; | 2415 | return filename_mountpoint(dfd, getname_kernel(name), path, flags); |
| 2396 | return filename_mountpoint(dfd, &s, path, flags); | ||
| 2397 | } | 2416 | } |
| 2398 | EXPORT_SYMBOL(kern_path_mountpoint); | 2417 | EXPORT_SYMBOL(kern_path_mountpoint); |
| 2399 | 2418 | ||
| @@ -3273,7 +3292,7 @@ struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt, | |||
| 3273 | { | 3292 | { |
| 3274 | struct nameidata nd; | 3293 | struct nameidata nd; |
| 3275 | struct file *file; | 3294 | struct file *file; |
| 3276 | struct filename filename = { .name = name }; | 3295 | struct filename *filename; |
| 3277 | int flags = op->lookup_flags | LOOKUP_ROOT; | 3296 | int flags = op->lookup_flags | LOOKUP_ROOT; |
| 3278 | 3297 | ||
| 3279 | nd.root.mnt = mnt; | 3298 | nd.root.mnt = mnt; |
| @@ -3282,15 +3301,20 @@ struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt, | |||
| 3282 | if (d_is_symlink(dentry) && op->intent & LOOKUP_OPEN) | 3301 | if (d_is_symlink(dentry) && op->intent & LOOKUP_OPEN) |
| 3283 | return ERR_PTR(-ELOOP); | 3302 | return ERR_PTR(-ELOOP); |
| 3284 | 3303 | ||
| 3285 | file = path_openat(-1, &filename, &nd, op, flags | LOOKUP_RCU); | 3304 | filename = getname_kernel(name); |
| 3305 | if (unlikely(IS_ERR(filename))) | ||
| 3306 | return ERR_CAST(filename); | ||
| 3307 | |||
| 3308 | file = path_openat(-1, filename, &nd, op, flags | LOOKUP_RCU); | ||
| 3286 | if (unlikely(file == ERR_PTR(-ECHILD))) | 3309 | if (unlikely(file == ERR_PTR(-ECHILD))) |
| 3287 | file = path_openat(-1, &filename, &nd, op, flags); | 3310 | file = path_openat(-1, filename, &nd, op, flags); |
| 3288 | if (unlikely(file == ERR_PTR(-ESTALE))) | 3311 | if (unlikely(file == ERR_PTR(-ESTALE))) |
| 3289 | file = path_openat(-1, &filename, &nd, op, flags | LOOKUP_REVAL); | 3312 | file = path_openat(-1, filename, &nd, op, flags | LOOKUP_REVAL); |
| 3313 | putname(filename); | ||
| 3290 | return file; | 3314 | return file; |
| 3291 | } | 3315 | } |
| 3292 | 3316 | ||
| 3293 | struct dentry *kern_path_create(int dfd, const char *pathname, | 3317 | static struct dentry *filename_create(int dfd, struct filename *name, |
| 3294 | struct path *path, unsigned int lookup_flags) | 3318 | struct path *path, unsigned int lookup_flags) |
| 3295 | { | 3319 | { |
| 3296 | struct dentry *dentry = ERR_PTR(-EEXIST); | 3320 | struct dentry *dentry = ERR_PTR(-EEXIST); |
| @@ -3305,7 +3329,7 @@ struct dentry *kern_path_create(int dfd, const char *pathname, | |||
| 3305 | */ | 3329 | */ |
| 3306 | lookup_flags &= LOOKUP_REVAL; | 3330 | lookup_flags &= LOOKUP_REVAL; |
| 3307 | 3331 | ||
| 3308 | error = do_path_lookup(dfd, pathname, LOOKUP_PARENT|lookup_flags, &nd); | 3332 | error = filename_lookup(dfd, name, LOOKUP_PARENT|lookup_flags, &nd); |
| 3309 | if (error) | 3333 | if (error) |
| 3310 | return ERR_PTR(error); | 3334 | return ERR_PTR(error); |
| 3311 | 3335 | ||
| @@ -3359,6 +3383,19 @@ out: | |||
| 3359 | path_put(&nd.path); | 3383 | path_put(&nd.path); |
| 3360 | return dentry; | 3384 | return dentry; |
| 3361 | } | 3385 | } |
| 3386 | |||
| 3387 | struct dentry *kern_path_create(int dfd, const char *pathname, | ||
| 3388 | struct path *path, unsigned int lookup_flags) | ||
| 3389 | { | ||
| 3390 | struct filename *filename = getname_kernel(pathname); | ||
| 3391 | struct dentry *res; | ||
| 3392 | |||
| 3393 | if (IS_ERR(filename)) | ||
| 3394 | return ERR_CAST(filename); | ||
| 3395 | res = filename_create(dfd, filename, path, lookup_flags); | ||
| 3396 | putname(filename); | ||
| 3397 | return res; | ||
| 3398 | } | ||
| 3362 | EXPORT_SYMBOL(kern_path_create); | 3399 | EXPORT_SYMBOL(kern_path_create); |
| 3363 | 3400 | ||
| 3364 | void done_path_create(struct path *path, struct dentry *dentry) | 3401 | void done_path_create(struct path *path, struct dentry *dentry) |
| @@ -3377,7 +3414,7 @@ struct dentry *user_path_create(int dfd, const char __user *pathname, | |||
| 3377 | struct dentry *res; | 3414 | struct dentry *res; |
| 3378 | if (IS_ERR(tmp)) | 3415 | if (IS_ERR(tmp)) |
| 3379 | return ERR_CAST(tmp); | 3416 | return ERR_CAST(tmp); |
| 3380 | res = kern_path_create(dfd, tmp->name, path, lookup_flags); | 3417 | res = filename_create(dfd, tmp, path, lookup_flags); |
| 3381 | putname(tmp); | 3418 | putname(tmp); |
| 3382 | return res; | 3419 | return res; |
| 3383 | } | 3420 | } |
diff --git a/fs/namespace.c b/fs/namespace.c index 6dae553dd69c..72a286e0d33e 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
| @@ -190,6 +190,14 @@ unsigned int mnt_get_count(struct mount *mnt) | |||
| 190 | #endif | 190 | #endif |
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | static void drop_mountpoint(struct fs_pin *p) | ||
| 194 | { | ||
| 195 | struct mount *m = container_of(p, struct mount, mnt_umount); | ||
| 196 | dput(m->mnt_ex_mountpoint); | ||
| 197 | pin_remove(p); | ||
| 198 | mntput(&m->mnt); | ||
| 199 | } | ||
| 200 | |||
| 193 | static struct mount *alloc_vfsmnt(const char *name) | 201 | static struct mount *alloc_vfsmnt(const char *name) |
| 194 | { | 202 | { |
| 195 | struct mount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL); | 203 | struct mount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL); |
| @@ -229,6 +237,7 @@ static struct mount *alloc_vfsmnt(const char *name) | |||
| 229 | #ifdef CONFIG_FSNOTIFY | 237 | #ifdef CONFIG_FSNOTIFY |
| 230 | INIT_HLIST_HEAD(&mnt->mnt_fsnotify_marks); | 238 | INIT_HLIST_HEAD(&mnt->mnt_fsnotify_marks); |
| 231 | #endif | 239 | #endif |
| 240 | init_fs_pin(&mnt->mnt_umount, drop_mountpoint); | ||
| 232 | } | 241 | } |
| 233 | return mnt; | 242 | return mnt; |
| 234 | 243 | ||
| @@ -1289,7 +1298,6 @@ static HLIST_HEAD(unmounted); /* protected by namespace_sem */ | |||
| 1289 | 1298 | ||
| 1290 | static void namespace_unlock(void) | 1299 | static void namespace_unlock(void) |
| 1291 | { | 1300 | { |
| 1292 | struct mount *mnt; | ||
| 1293 | struct hlist_head head = unmounted; | 1301 | struct hlist_head head = unmounted; |
| 1294 | 1302 | ||
| 1295 | if (likely(hlist_empty(&head))) { | 1303 | if (likely(hlist_empty(&head))) { |
| @@ -1299,23 +1307,11 @@ static void namespace_unlock(void) | |||
| 1299 | 1307 | ||
| 1300 | head.first->pprev = &head.first; | 1308 | head.first->pprev = &head.first; |
| 1301 | INIT_HLIST_HEAD(&unmounted); | 1309 | INIT_HLIST_HEAD(&unmounted); |
| 1302 | |||
| 1303 | /* undo decrements we'd done in umount_tree() */ | ||
| 1304 | hlist_for_each_entry(mnt, &head, mnt_hash) | ||
| 1305 | if (mnt->mnt_ex_mountpoint.mnt) | ||
| 1306 | mntget(mnt->mnt_ex_mountpoint.mnt); | ||
| 1307 | |||
| 1308 | up_write(&namespace_sem); | 1310 | up_write(&namespace_sem); |
| 1309 | 1311 | ||
| 1310 | synchronize_rcu(); | 1312 | synchronize_rcu(); |
| 1311 | 1313 | ||
| 1312 | while (!hlist_empty(&head)) { | 1314 | group_pin_kill(&head); |
| 1313 | mnt = hlist_entry(head.first, struct mount, mnt_hash); | ||
| 1314 | hlist_del_init(&mnt->mnt_hash); | ||
| 1315 | if (mnt->mnt_ex_mountpoint.mnt) | ||
| 1316 | path_put(&mnt->mnt_ex_mountpoint); | ||
| 1317 | mntput(&mnt->mnt); | ||
| 1318 | } | ||
| 1319 | } | 1315 | } |
| 1320 | 1316 | ||
| 1321 | static inline void namespace_lock(void) | 1317 | static inline void namespace_lock(void) |
| @@ -1334,7 +1330,6 @@ void umount_tree(struct mount *mnt, int how) | |||
| 1334 | { | 1330 | { |
| 1335 | HLIST_HEAD(tmp_list); | 1331 | HLIST_HEAD(tmp_list); |
| 1336 | struct mount *p; | 1332 | struct mount *p; |
| 1337 | struct mount *last = NULL; | ||
| 1338 | 1333 | ||
| 1339 | for (p = mnt; p; p = next_mnt(p, mnt)) { | 1334 | for (p = mnt; p; p = next_mnt(p, mnt)) { |
| 1340 | hlist_del_init_rcu(&p->mnt_hash); | 1335 | hlist_del_init_rcu(&p->mnt_hash); |
| @@ -1347,33 +1342,28 @@ void umount_tree(struct mount *mnt, int how) | |||
| 1347 | if (how) | 1342 | if (how) |
| 1348 | propagate_umount(&tmp_list); | 1343 | propagate_umount(&tmp_list); |
| 1349 | 1344 | ||
| 1350 | hlist_for_each_entry(p, &tmp_list, mnt_hash) { | 1345 | while (!hlist_empty(&tmp_list)) { |
| 1346 | p = hlist_entry(tmp_list.first, struct mount, mnt_hash); | ||
| 1347 | hlist_del_init_rcu(&p->mnt_hash); | ||
| 1351 | list_del_init(&p->mnt_expire); | 1348 | list_del_init(&p->mnt_expire); |
| 1352 | list_del_init(&p->mnt_list); | 1349 | list_del_init(&p->mnt_list); |
| 1353 | __touch_mnt_namespace(p->mnt_ns); | 1350 | __touch_mnt_namespace(p->mnt_ns); |
| 1354 | p->mnt_ns = NULL; | 1351 | p->mnt_ns = NULL; |
| 1355 | if (how < 2) | 1352 | if (how < 2) |
| 1356 | p->mnt.mnt_flags |= MNT_SYNC_UMOUNT; | 1353 | p->mnt.mnt_flags |= MNT_SYNC_UMOUNT; |
| 1354 | |||
| 1355 | pin_insert_group(&p->mnt_umount, &p->mnt_parent->mnt, &unmounted); | ||
| 1357 | if (mnt_has_parent(p)) { | 1356 | if (mnt_has_parent(p)) { |
| 1358 | hlist_del_init(&p->mnt_mp_list); | 1357 | hlist_del_init(&p->mnt_mp_list); |
| 1359 | put_mountpoint(p->mnt_mp); | 1358 | put_mountpoint(p->mnt_mp); |
| 1360 | mnt_add_count(p->mnt_parent, -1); | 1359 | mnt_add_count(p->mnt_parent, -1); |
| 1361 | /* move the reference to mountpoint into ->mnt_ex_mountpoint */ | 1360 | /* old mountpoint will be dropped when we can do that */ |
| 1362 | p->mnt_ex_mountpoint.dentry = p->mnt_mountpoint; | 1361 | p->mnt_ex_mountpoint = p->mnt_mountpoint; |
| 1363 | p->mnt_ex_mountpoint.mnt = &p->mnt_parent->mnt; | ||
| 1364 | p->mnt_mountpoint = p->mnt.mnt_root; | 1362 | p->mnt_mountpoint = p->mnt.mnt_root; |
| 1365 | p->mnt_parent = p; | 1363 | p->mnt_parent = p; |
| 1366 | p->mnt_mp = NULL; | 1364 | p->mnt_mp = NULL; |
| 1367 | } | 1365 | } |
| 1368 | change_mnt_propagation(p, MS_PRIVATE); | 1366 | change_mnt_propagation(p, MS_PRIVATE); |
| 1369 | last = p; | ||
| 1370 | } | ||
| 1371 | if (last) { | ||
| 1372 | last->mnt_hash.next = unmounted.first; | ||
| 1373 | if (unmounted.first) | ||
| 1374 | unmounted.first->pprev = &last->mnt_hash.next; | ||
| 1375 | unmounted.first = tmp_list.first; | ||
| 1376 | unmounted.first->pprev = &unmounted.first; | ||
| 1377 | } | 1367 | } |
| 1378 | } | 1368 | } |
| 1379 | 1369 | ||
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c index 008960101520..e7ca827d7694 100644 --- a/fs/ncpfs/dir.c +++ b/fs/ncpfs/dir.c | |||
| @@ -77,6 +77,7 @@ static int ncp_hash_dentry(const struct dentry *, struct qstr *); | |||
| 77 | static int ncp_compare_dentry(const struct dentry *, const struct dentry *, | 77 | static int ncp_compare_dentry(const struct dentry *, const struct dentry *, |
| 78 | unsigned int, const char *, const struct qstr *); | 78 | unsigned int, const char *, const struct qstr *); |
| 79 | static int ncp_delete_dentry(const struct dentry *); | 79 | static int ncp_delete_dentry(const struct dentry *); |
| 80 | static void ncp_d_prune(struct dentry *dentry); | ||
| 80 | 81 | ||
| 81 | const struct dentry_operations ncp_dentry_operations = | 82 | const struct dentry_operations ncp_dentry_operations = |
| 82 | { | 83 | { |
| @@ -84,6 +85,7 @@ const struct dentry_operations ncp_dentry_operations = | |||
| 84 | .d_hash = ncp_hash_dentry, | 85 | .d_hash = ncp_hash_dentry, |
| 85 | .d_compare = ncp_compare_dentry, | 86 | .d_compare = ncp_compare_dentry, |
| 86 | .d_delete = ncp_delete_dentry, | 87 | .d_delete = ncp_delete_dentry, |
| 88 | .d_prune = ncp_d_prune, | ||
| 87 | }; | 89 | }; |
| 88 | 90 | ||
| 89 | #define ncp_namespace(i) (NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber]) | 91 | #define ncp_namespace(i) (NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber]) |
| @@ -384,42 +386,6 @@ finished: | |||
| 384 | return val; | 386 | return val; |
| 385 | } | 387 | } |
| 386 | 388 | ||
| 387 | static struct dentry * | ||
| 388 | ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos) | ||
| 389 | { | ||
| 390 | struct dentry *dent = dentry; | ||
| 391 | |||
| 392 | if (d_validate(dent, parent)) { | ||
| 393 | if (dent->d_name.len <= NCP_MAXPATHLEN && | ||
| 394 | (unsigned long)dent->d_fsdata == fpos) { | ||
| 395 | if (!dent->d_inode) { | ||
| 396 | dput(dent); | ||
| 397 | dent = NULL; | ||
| 398 | } | ||
| 399 | return dent; | ||
| 400 | } | ||
| 401 | dput(dent); | ||
| 402 | } | ||
| 403 | |||
| 404 | /* If a pointer is invalid, we search the dentry. */ | ||
| 405 | spin_lock(&parent->d_lock); | ||
| 406 | list_for_each_entry(dent, &parent->d_subdirs, d_child) { | ||
| 407 | if ((unsigned long)dent->d_fsdata == fpos) { | ||
| 408 | if (dent->d_inode) | ||
| 409 | dget(dent); | ||
| 410 | else | ||
| 411 | dent = NULL; | ||
| 412 | spin_unlock(&parent->d_lock); | ||
| 413 | goto out; | ||
| 414 | } | ||
| 415 | } | ||
| 416 | spin_unlock(&parent->d_lock); | ||
| 417 | return NULL; | ||
| 418 | |||
| 419 | out: | ||
| 420 | return dent; | ||
| 421 | } | ||
| 422 | |||
| 423 | static time_t ncp_obtain_mtime(struct dentry *dentry) | 389 | static time_t ncp_obtain_mtime(struct dentry *dentry) |
| 424 | { | 390 | { |
| 425 | struct inode *inode = dentry->d_inode; | 391 | struct inode *inode = dentry->d_inode; |
| @@ -435,6 +401,20 @@ static time_t ncp_obtain_mtime(struct dentry *dentry) | |||
| 435 | return ncp_date_dos2unix(i.modifyTime, i.modifyDate); | 401 | return ncp_date_dos2unix(i.modifyTime, i.modifyDate); |
| 436 | } | 402 | } |
| 437 | 403 | ||
| 404 | static inline void | ||
| 405 | ncp_invalidate_dircache_entries(struct dentry *parent) | ||
| 406 | { | ||
| 407 | struct ncp_server *server = NCP_SERVER(parent->d_inode); | ||
| 408 | struct dentry *dentry; | ||
| 409 | |||
| 410 | spin_lock(&parent->d_lock); | ||
| 411 | list_for_each_entry(dentry, &parent->d_subdirs, d_child) { | ||
| 412 | dentry->d_fsdata = NULL; | ||
| 413 | ncp_age_dentry(server, dentry); | ||
| 414 | } | ||
| 415 | spin_unlock(&parent->d_lock); | ||
| 416 | } | ||
| 417 | |||
| 438 | static int ncp_readdir(struct file *file, struct dir_context *ctx) | 418 | static int ncp_readdir(struct file *file, struct dir_context *ctx) |
| 439 | { | 419 | { |
| 440 | struct dentry *dentry = file->f_path.dentry; | 420 | struct dentry *dentry = file->f_path.dentry; |
| @@ -500,10 +480,21 @@ static int ncp_readdir(struct file *file, struct dir_context *ctx) | |||
| 500 | struct dentry *dent; | 480 | struct dentry *dent; |
| 501 | bool over; | 481 | bool over; |
| 502 | 482 | ||
| 503 | dent = ncp_dget_fpos(ctl.cache->dentry[ctl.idx], | 483 | spin_lock(&dentry->d_lock); |
| 504 | dentry, ctx->pos); | 484 | if (!(NCP_FINFO(inode)->flags & NCPI_DIR_CACHE)) { |
| 505 | if (!dent) | 485 | spin_unlock(&dentry->d_lock); |
| 486 | goto invalid_cache; | ||
| 487 | } | ||
| 488 | dent = ctl.cache->dentry[ctl.idx]; | ||
| 489 | if (unlikely(!lockref_get_not_dead(&dent->d_lockref))) { | ||
| 490 | spin_unlock(&dentry->d_lock); | ||
| 491 | goto invalid_cache; | ||
| 492 | } | ||
| 493 | spin_unlock(&dentry->d_lock); | ||
| 494 | if (!dent->d_inode) { | ||
| 495 | dput(dent); | ||
| 506 | goto invalid_cache; | 496 | goto invalid_cache; |
| 497 | } | ||
| 507 | over = !dir_emit(ctx, dent->d_name.name, | 498 | over = !dir_emit(ctx, dent->d_name.name, |
| 508 | dent->d_name.len, | 499 | dent->d_name.len, |
| 509 | dent->d_inode->i_ino, DT_UNKNOWN); | 500 | dent->d_inode->i_ino, DT_UNKNOWN); |
| @@ -548,6 +539,9 @@ init_cache: | |||
| 548 | ctl.filled = 0; | 539 | ctl.filled = 0; |
| 549 | ctl.valid = 1; | 540 | ctl.valid = 1; |
| 550 | read_really: | 541 | read_really: |
| 542 | spin_lock(&dentry->d_lock); | ||
| 543 | NCP_FINFO(inode)->flags |= NCPI_DIR_CACHE; | ||
| 544 | spin_unlock(&dentry->d_lock); | ||
| 551 | if (ncp_is_server_root(inode)) { | 545 | if (ncp_is_server_root(inode)) { |
| 552 | ncp_read_volume_list(file, ctx, &ctl); | 546 | ncp_read_volume_list(file, ctx, &ctl); |
| 553 | } else { | 547 | } else { |
| @@ -573,6 +567,13 @@ out: | |||
| 573 | return result; | 567 | return result; |
| 574 | } | 568 | } |
| 575 | 569 | ||
| 570 | static void ncp_d_prune(struct dentry *dentry) | ||
| 571 | { | ||
| 572 | if (!dentry->d_fsdata) /* not referenced from page cache */ | ||
| 573 | return; | ||
| 574 | NCP_FINFO(dentry->d_parent->d_inode)->flags &= ~NCPI_DIR_CACHE; | ||
| 575 | } | ||
| 576 | |||
| 576 | static int | 577 | static int |
| 577 | ncp_fill_cache(struct file *file, struct dir_context *ctx, | 578 | ncp_fill_cache(struct file *file, struct dir_context *ctx, |
| 578 | struct ncp_cache_control *ctrl, struct ncp_entry_info *entry, | 579 | struct ncp_cache_control *ctrl, struct ncp_entry_info *entry, |
| @@ -630,6 +631,10 @@ ncp_fill_cache(struct file *file, struct dir_context *ctx, | |||
| 630 | d_instantiate(newdent, inode); | 631 | d_instantiate(newdent, inode); |
| 631 | if (!hashed) | 632 | if (!hashed) |
| 632 | d_rehash(newdent); | 633 | d_rehash(newdent); |
| 634 | } else { | ||
| 635 | spin_lock(&dentry->d_lock); | ||
| 636 | NCP_FINFO(inode)->flags &= ~NCPI_DIR_CACHE; | ||
| 637 | spin_unlock(&dentry->d_lock); | ||
| 633 | } | 638 | } |
| 634 | } else { | 639 | } else { |
| 635 | struct inode *inode = newdent->d_inode; | 640 | struct inode *inode = newdent->d_inode; |
| @@ -639,12 +644,6 @@ ncp_fill_cache(struct file *file, struct dir_context *ctx, | |||
| 639 | mutex_unlock(&inode->i_mutex); | 644 | mutex_unlock(&inode->i_mutex); |
| 640 | } | 645 | } |
| 641 | 646 | ||
| 642 | if (newdent->d_inode) { | ||
| 643 | ino = newdent->d_inode->i_ino; | ||
| 644 | newdent->d_fsdata = (void *) ctl.fpos; | ||
| 645 | ncp_new_dentry(newdent); | ||
| 646 | } | ||
| 647 | |||
| 648 | if (ctl.idx >= NCP_DIRCACHE_SIZE) { | 647 | if (ctl.idx >= NCP_DIRCACHE_SIZE) { |
| 649 | if (ctl.page) { | 648 | if (ctl.page) { |
| 650 | kunmap(ctl.page); | 649 | kunmap(ctl.page); |
| @@ -660,8 +659,13 @@ ncp_fill_cache(struct file *file, struct dir_context *ctx, | |||
| 660 | ctl.cache = kmap(ctl.page); | 659 | ctl.cache = kmap(ctl.page); |
| 661 | } | 660 | } |
| 662 | if (ctl.cache) { | 661 | if (ctl.cache) { |
| 663 | ctl.cache->dentry[ctl.idx] = newdent; | 662 | if (newdent->d_inode) { |
| 664 | valid = 1; | 663 | newdent->d_fsdata = newdent; |
| 664 | ctl.cache->dentry[ctl.idx] = newdent; | ||
| 665 | ino = newdent->d_inode->i_ino; | ||
| 666 | ncp_new_dentry(newdent); | ||
| 667 | } | ||
| 668 | valid = 1; | ||
| 665 | } | 669 | } |
| 666 | dput(newdent); | 670 | dput(newdent); |
| 667 | end_advance: | 671 | end_advance: |
diff --git a/fs/ncpfs/ncp_fs_i.h b/fs/ncpfs/ncp_fs_i.h index 4b0bec477846..c4794504f843 100644 --- a/fs/ncpfs/ncp_fs_i.h +++ b/fs/ncpfs/ncp_fs_i.h | |||
| @@ -22,6 +22,7 @@ struct ncp_inode_info { | |||
| 22 | int access; | 22 | int access; |
| 23 | int flags; | 23 | int flags; |
| 24 | #define NCPI_KLUDGE_SYMLINK 0x0001 | 24 | #define NCPI_KLUDGE_SYMLINK 0x0001 |
| 25 | #define NCPI_DIR_CACHE 0x0002 | ||
| 25 | __u8 file_handle[6]; | 26 | __u8 file_handle[6]; |
| 26 | struct inode vfs_inode; | 27 | struct inode vfs_inode; |
| 27 | }; | 28 | }; |
diff --git a/fs/ncpfs/ncplib_kernel.h b/fs/ncpfs/ncplib_kernel.h index b785f74bfe3c..250e443a07f3 100644 --- a/fs/ncpfs/ncplib_kernel.h +++ b/fs/ncpfs/ncplib_kernel.h | |||
| @@ -184,36 +184,6 @@ ncp_new_dentry(struct dentry* dentry) | |||
| 184 | dentry->d_time = jiffies; | 184 | dentry->d_time = jiffies; |
| 185 | } | 185 | } |
| 186 | 186 | ||
| 187 | static inline void | ||
| 188 | ncp_renew_dentries(struct dentry *parent) | ||
| 189 | { | ||
| 190 | struct ncp_server *server = NCP_SERVER(parent->d_inode); | ||
| 191 | struct dentry *dentry; | ||
| 192 | |||
| 193 | spin_lock(&parent->d_lock); | ||
| 194 | list_for_each_entry(dentry, &parent->d_subdirs, d_child) { | ||
| 195 | if (dentry->d_fsdata == NULL) | ||
| 196 | ncp_age_dentry(server, dentry); | ||
| 197 | else | ||
| 198 | ncp_new_dentry(dentry); | ||
| 199 | } | ||
| 200 | spin_unlock(&parent->d_lock); | ||
| 201 | } | ||
| 202 | |||
| 203 | static inline void | ||
| 204 | ncp_invalidate_dircache_entries(struct dentry *parent) | ||
| 205 | { | ||
| 206 | struct ncp_server *server = NCP_SERVER(parent->d_inode); | ||
| 207 | struct dentry *dentry; | ||
| 208 | |||
| 209 | spin_lock(&parent->d_lock); | ||
| 210 | list_for_each_entry(dentry, &parent->d_subdirs, d_child) { | ||
| 211 | dentry->d_fsdata = NULL; | ||
| 212 | ncp_age_dentry(server, dentry); | ||
| 213 | } | ||
| 214 | spin_unlock(&parent->d_lock); | ||
| 215 | } | ||
| 216 | |||
| 217 | struct ncp_cache_head { | 187 | struct ncp_cache_head { |
| 218 | time_t mtime; | 188 | time_t mtime; |
| 219 | unsigned long time; /* cache age */ | 189 | unsigned long time; /* cache age */ |
diff --git a/fs/nfsd/nfsfh.h b/fs/nfsd/nfsfh.h index 84cae2079d21..f22920442172 100644 --- a/fs/nfsd/nfsfh.h +++ b/fs/nfsd/nfsfh.h | |||
| @@ -200,7 +200,7 @@ static inline bool fh_fsid_match(struct knfsd_fh *fh1, struct knfsd_fh *fh2) | |||
| 200 | { | 200 | { |
| 201 | if (fh1->fh_fsid_type != fh2->fh_fsid_type) | 201 | if (fh1->fh_fsid_type != fh2->fh_fsid_type) |
| 202 | return false; | 202 | return false; |
| 203 | if (memcmp(fh1->fh_fsid, fh2->fh_fsid, key_len(fh1->fh_fsid_type) != 0)) | 203 | if (memcmp(fh1->fh_fsid, fh2->fh_fsid, key_len(fh1->fh_fsid_type)) != 0) |
| 204 | return false; | 204 | return false; |
| 205 | return true; | 205 | return true; |
| 206 | } | 206 | } |
diff --git a/fs/nfsd/pnfs.h b/fs/nfsd/pnfs.h index fedb4d620a81..d4c4453674c6 100644 --- a/fs/nfsd/pnfs.h +++ b/fs/nfsd/pnfs.h | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #ifndef _FS_NFSD_PNFS_H | 1 | #ifndef _FS_NFSD_PNFS_H |
| 2 | #define _FS_NFSD_PNFS_H 1 | 2 | #define _FS_NFSD_PNFS_H 1 |
| 3 | 3 | ||
| 4 | #ifdef CONFIG_NFSD_V4 | ||
| 4 | #include <linux/exportfs.h> | 5 | #include <linux/exportfs.h> |
| 5 | #include <linux/nfsd/export.h> | 6 | #include <linux/nfsd/export.h> |
| 6 | 7 | ||
| @@ -50,6 +51,7 @@ __be32 nfsd4_return_client_layouts(struct svc_rqst *rqstp, | |||
| 50 | int nfsd4_set_deviceid(struct nfsd4_deviceid *id, const struct svc_fh *fhp, | 51 | int nfsd4_set_deviceid(struct nfsd4_deviceid *id, const struct svc_fh *fhp, |
| 51 | u32 device_generation); | 52 | u32 device_generation); |
| 52 | struct nfsd4_deviceid_map *nfsd4_find_devid_map(int idx); | 53 | struct nfsd4_deviceid_map *nfsd4_find_devid_map(int idx); |
| 54 | #endif /* CONFIG_NFSD_V4 */ | ||
| 53 | 55 | ||
| 54 | #ifdef CONFIG_NFSD_PNFS | 56 | #ifdef CONFIG_NFSD_PNFS |
| 55 | void nfsd4_setup_layout_type(struct svc_export *exp); | 57 | void nfsd4_setup_layout_type(struct svc_export *exp); |
| @@ -59,6 +61,9 @@ void nfsd4_return_all_file_layouts(struct nfs4_client *clp, | |||
| 59 | int nfsd4_init_pnfs(void); | 61 | int nfsd4_init_pnfs(void); |
| 60 | void nfsd4_exit_pnfs(void); | 62 | void nfsd4_exit_pnfs(void); |
| 61 | #else | 63 | #else |
| 64 | struct nfs4_client; | ||
| 65 | struct nfs4_file; | ||
| 66 | |||
| 62 | static inline void nfsd4_setup_layout_type(struct svc_export *exp) | 67 | static inline void nfsd4_setup_layout_type(struct svc_export *exp) |
| 63 | { | 68 | { |
| 64 | } | 69 | } |
| @@ -968,8 +968,14 @@ struct file *file_open_name(struct filename *name, int flags, umode_t mode) | |||
| 968 | */ | 968 | */ |
| 969 | struct file *filp_open(const char *filename, int flags, umode_t mode) | 969 | struct file *filp_open(const char *filename, int flags, umode_t mode) |
| 970 | { | 970 | { |
| 971 | struct filename name = {.name = filename}; | 971 | struct filename *name = getname_kernel(filename); |
| 972 | return file_open_name(&name, flags, mode); | 972 | struct file *file = ERR_CAST(name); |
| 973 | |||
| 974 | if (!IS_ERR(name)) { | ||
| 975 | file = file_open_name(name, flags, mode); | ||
| 976 | putname(name); | ||
| 977 | } | ||
| 978 | return file; | ||
| 973 | } | 979 | } |
| 974 | EXPORT_SYMBOL(filp_open); | 980 | EXPORT_SYMBOL(filp_open); |
| 975 | 981 | ||
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index de14e46fd807..3309f59d421b 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
| @@ -350,29 +350,12 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp | |||
| 350 | if (ret) | 350 | if (ret) |
| 351 | return ret; | 351 | return ret; |
| 352 | 352 | ||
| 353 | if (S_ISDIR(dp->mode)) { | ||
| 354 | dp->proc_fops = &proc_dir_operations; | ||
| 355 | dp->proc_iops = &proc_dir_inode_operations; | ||
| 356 | dir->nlink++; | ||
| 357 | } else if (S_ISLNK(dp->mode)) { | ||
| 358 | dp->proc_iops = &proc_link_inode_operations; | ||
| 359 | } else if (S_ISREG(dp->mode)) { | ||
| 360 | BUG_ON(dp->proc_fops == NULL); | ||
| 361 | dp->proc_iops = &proc_file_inode_operations; | ||
| 362 | } else { | ||
| 363 | WARN_ON(1); | ||
| 364 | proc_free_inum(dp->low_ino); | ||
| 365 | return -EINVAL; | ||
| 366 | } | ||
| 367 | |||
| 368 | spin_lock(&proc_subdir_lock); | 353 | spin_lock(&proc_subdir_lock); |
| 369 | dp->parent = dir; | 354 | dp->parent = dir; |
| 370 | if (pde_subdir_insert(dir, dp) == false) { | 355 | if (pde_subdir_insert(dir, dp) == false) { |
| 371 | WARN(1, "proc_dir_entry '%s/%s' already registered\n", | 356 | WARN(1, "proc_dir_entry '%s/%s' already registered\n", |
| 372 | dir->name, dp->name); | 357 | dir->name, dp->name); |
| 373 | spin_unlock(&proc_subdir_lock); | 358 | spin_unlock(&proc_subdir_lock); |
| 374 | if (S_ISDIR(dp->mode)) | ||
| 375 | dir->nlink--; | ||
| 376 | proc_free_inum(dp->low_ino); | 359 | proc_free_inum(dp->low_ino); |
| 377 | return -EEXIST; | 360 | return -EEXIST; |
| 378 | } | 361 | } |
| @@ -431,6 +414,7 @@ struct proc_dir_entry *proc_symlink(const char *name, | |||
| 431 | ent->data = kmalloc((ent->size=strlen(dest))+1, GFP_KERNEL); | 414 | ent->data = kmalloc((ent->size=strlen(dest))+1, GFP_KERNEL); |
| 432 | if (ent->data) { | 415 | if (ent->data) { |
| 433 | strcpy((char*)ent->data,dest); | 416 | strcpy((char*)ent->data,dest); |
| 417 | ent->proc_iops = &proc_link_inode_operations; | ||
| 434 | if (proc_register(parent, ent) < 0) { | 418 | if (proc_register(parent, ent) < 0) { |
| 435 | kfree(ent->data); | 419 | kfree(ent->data); |
| 436 | kfree(ent); | 420 | kfree(ent); |
| @@ -456,8 +440,12 @@ struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode, | |||
| 456 | ent = __proc_create(&parent, name, S_IFDIR | mode, 2); | 440 | ent = __proc_create(&parent, name, S_IFDIR | mode, 2); |
| 457 | if (ent) { | 441 | if (ent) { |
| 458 | ent->data = data; | 442 | ent->data = data; |
| 443 | ent->proc_fops = &proc_dir_operations; | ||
| 444 | ent->proc_iops = &proc_dir_inode_operations; | ||
| 445 | parent->nlink++; | ||
| 459 | if (proc_register(parent, ent) < 0) { | 446 | if (proc_register(parent, ent) < 0) { |
| 460 | kfree(ent); | 447 | kfree(ent); |
| 448 | parent->nlink--; | ||
| 461 | ent = NULL; | 449 | ent = NULL; |
| 462 | } | 450 | } |
| 463 | } | 451 | } |
| @@ -493,6 +481,8 @@ struct proc_dir_entry *proc_create_data(const char *name, umode_t mode, | |||
| 493 | return NULL; | 481 | return NULL; |
| 494 | } | 482 | } |
| 495 | 483 | ||
| 484 | BUG_ON(proc_fops == NULL); | ||
| 485 | |||
| 496 | if ((mode & S_IALLUGO) == 0) | 486 | if ((mode & S_IALLUGO) == 0) |
| 497 | mode |= S_IRUGO; | 487 | mode |= S_IRUGO; |
| 498 | pde = __proc_create(&parent, name, mode, 1); | 488 | pde = __proc_create(&parent, name, mode, 1); |
| @@ -500,6 +490,7 @@ struct proc_dir_entry *proc_create_data(const char *name, umode_t mode, | |||
| 500 | goto out; | 490 | goto out; |
| 501 | pde->proc_fops = proc_fops; | 491 | pde->proc_fops = proc_fops; |
| 502 | pde->data = data; | 492 | pde->data = data; |
| 493 | pde->proc_iops = &proc_file_inode_operations; | ||
| 503 | if (proc_register(parent, pde) < 0) | 494 | if (proc_register(parent, pde) < 0) |
| 504 | goto out_free; | 495 | goto out_free; |
| 505 | return pde; | 496 | return pde; |
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c index a90d6d354199..4e61388ec03d 100644 --- a/fs/proc/vmcore.c +++ b/fs/proc/vmcore.c | |||
| @@ -546,8 +546,8 @@ static int __init update_note_header_size_elf64(const Elf64_Ehdr *ehdr_ptr) | |||
| 546 | nhdr_ptr = notes_section; | 546 | nhdr_ptr = notes_section; |
| 547 | while (nhdr_ptr->n_namesz != 0) { | 547 | while (nhdr_ptr->n_namesz != 0) { |
| 548 | sz = sizeof(Elf64_Nhdr) + | 548 | sz = sizeof(Elf64_Nhdr) + |
| 549 | ((nhdr_ptr->n_namesz + 3) & ~3) + | 549 | (((u64)nhdr_ptr->n_namesz + 3) & ~3) + |
| 550 | ((nhdr_ptr->n_descsz + 3) & ~3); | 550 | (((u64)nhdr_ptr->n_descsz + 3) & ~3); |
| 551 | if ((real_sz + sz) > max_sz) { | 551 | if ((real_sz + sz) > max_sz) { |
| 552 | pr_warn("Warning: Exceeded p_memsz, dropping PT_NOTE entry n_namesz=0x%x, n_descsz=0x%x\n", | 552 | pr_warn("Warning: Exceeded p_memsz, dropping PT_NOTE entry n_namesz=0x%x, n_descsz=0x%x\n", |
| 553 | nhdr_ptr->n_namesz, nhdr_ptr->n_descsz); | 553 | nhdr_ptr->n_namesz, nhdr_ptr->n_descsz); |
| @@ -732,8 +732,8 @@ static int __init update_note_header_size_elf32(const Elf32_Ehdr *ehdr_ptr) | |||
| 732 | nhdr_ptr = notes_section; | 732 | nhdr_ptr = notes_section; |
| 733 | while (nhdr_ptr->n_namesz != 0) { | 733 | while (nhdr_ptr->n_namesz != 0) { |
| 734 | sz = sizeof(Elf32_Nhdr) + | 734 | sz = sizeof(Elf32_Nhdr) + |
| 735 | ((nhdr_ptr->n_namesz + 3) & ~3) + | 735 | (((u64)nhdr_ptr->n_namesz + 3) & ~3) + |
| 736 | ((nhdr_ptr->n_descsz + 3) & ~3); | 736 | (((u64)nhdr_ptr->n_descsz + 3) & ~3); |
| 737 | if ((real_sz + sz) > max_sz) { | 737 | if ((real_sz + sz) > max_sz) { |
| 738 | pr_warn("Warning: Exceeded p_memsz, dropping PT_NOTE entry n_namesz=0x%x, n_descsz=0x%x\n", | 738 | pr_warn("Warning: Exceeded p_memsz, dropping PT_NOTE entry n_namesz=0x%x, n_descsz=0x%x\n", |
| 739 | nhdr_ptr->n_namesz, nhdr_ptr->n_descsz); | 739 | nhdr_ptr->n_namesz, nhdr_ptr->n_descsz); |
diff --git a/fs/proc_namespace.c b/fs/proc_namespace.c index 0f96f71ab32b..8db932da4009 100644 --- a/fs/proc_namespace.c +++ b/fs/proc_namespace.c | |||
| @@ -44,6 +44,7 @@ static int show_sb_opts(struct seq_file *m, struct super_block *sb) | |||
| 44 | { MS_SYNCHRONOUS, ",sync" }, | 44 | { MS_SYNCHRONOUS, ",sync" }, |
| 45 | { MS_DIRSYNC, ",dirsync" }, | 45 | { MS_DIRSYNC, ",dirsync" }, |
| 46 | { MS_MANDLOCK, ",mand" }, | 46 | { MS_MANDLOCK, ",mand" }, |
| 47 | { MS_LAZYTIME, ",lazytime" }, | ||
| 47 | { 0, NULL } | 48 | { 0, NULL } |
| 48 | }; | 49 | }; |
| 49 | const struct proc_fs_info *fs_infop; | 50 | const struct proc_fs_info *fs_infop; |
diff --git a/fs/read_write.c b/fs/read_write.c index 4060691e78f7..8e1b68786d66 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
| @@ -333,6 +333,52 @@ out_putf: | |||
| 333 | } | 333 | } |
| 334 | #endif | 334 | #endif |
| 335 | 335 | ||
| 336 | ssize_t vfs_iter_read(struct file *file, struct iov_iter *iter, loff_t *ppos) | ||
| 337 | { | ||
| 338 | struct kiocb kiocb; | ||
| 339 | ssize_t ret; | ||
| 340 | |||
| 341 | if (!file->f_op->read_iter) | ||
| 342 | return -EINVAL; | ||
| 343 | |||
| 344 | init_sync_kiocb(&kiocb, file); | ||
| 345 | kiocb.ki_pos = *ppos; | ||
| 346 | kiocb.ki_nbytes = iov_iter_count(iter); | ||
| 347 | |||
| 348 | iter->type |= READ; | ||
| 349 | ret = file->f_op->read_iter(&kiocb, iter); | ||
| 350 | if (ret == -EIOCBQUEUED) | ||
| 351 | ret = wait_on_sync_kiocb(&kiocb); | ||
| 352 | |||
| 353 | if (ret > 0) | ||
| 354 | *ppos = kiocb.ki_pos; | ||
| 355 | return ret; | ||
| 356 | } | ||
| 357 | EXPORT_SYMBOL(vfs_iter_read); | ||
| 358 | |||
| 359 | ssize_t vfs_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos) | ||
| 360 | { | ||
| 361 | struct kiocb kiocb; | ||
| 362 | ssize_t ret; | ||
| 363 | |||
| 364 | if (!file->f_op->write_iter) | ||
| 365 | return -EINVAL; | ||
| 366 | |||
| 367 | init_sync_kiocb(&kiocb, file); | ||
| 368 | kiocb.ki_pos = *ppos; | ||
| 369 | kiocb.ki_nbytes = iov_iter_count(iter); | ||
| 370 | |||
| 371 | iter->type |= WRITE; | ||
| 372 | ret = file->f_op->write_iter(&kiocb, iter); | ||
| 373 | if (ret == -EIOCBQUEUED) | ||
| 374 | ret = wait_on_sync_kiocb(&kiocb); | ||
| 375 | |||
| 376 | if (ret > 0) | ||
| 377 | *ppos = kiocb.ki_pos; | ||
| 378 | return ret; | ||
| 379 | } | ||
| 380 | EXPORT_SYMBOL(vfs_iter_write); | ||
| 381 | |||
| 336 | /* | 382 | /* |
| 337 | * rw_verify_area doesn't like huge counts. We limit | 383 | * rw_verify_area doesn't like huge counts. We limit |
| 338 | * them to something that fits in "int" so that others | 384 | * them to something that fits in "int" so that others |
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index a7eec9888f10..e72401e1f995 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c | |||
| @@ -2766,7 +2766,7 @@ static int reiserfs_write_begin(struct file *file, | |||
| 2766 | int old_ref = 0; | 2766 | int old_ref = 0; |
| 2767 | 2767 | ||
| 2768 | inode = mapping->host; | 2768 | inode = mapping->host; |
| 2769 | *fsdata = 0; | 2769 | *fsdata = NULL; |
| 2770 | if (flags & AOP_FLAG_CONT_EXPAND && | 2770 | if (flags & AOP_FLAG_CONT_EXPAND && |
| 2771 | (pos & (inode->i_sb->s_blocksize - 1)) == 0) { | 2771 | (pos & (inode->i_sb->s_blocksize - 1)) == 0) { |
| 2772 | pos ++; | 2772 | pos ++; |
diff --git a/fs/splice.c b/fs/splice.c index 75c6058eabf2..7968da96bebb 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
| @@ -961,7 +961,6 @@ iter_file_splice_write(struct pipe_inode_info *pipe, struct file *out, | |||
| 961 | splice_from_pipe_begin(&sd); | 961 | splice_from_pipe_begin(&sd); |
| 962 | while (sd.total_len) { | 962 | while (sd.total_len) { |
| 963 | struct iov_iter from; | 963 | struct iov_iter from; |
| 964 | struct kiocb kiocb; | ||
| 965 | size_t left; | 964 | size_t left; |
| 966 | int n, idx; | 965 | int n, idx; |
| 967 | 966 | ||
| @@ -1005,29 +1004,15 @@ iter_file_splice_write(struct pipe_inode_info *pipe, struct file *out, | |||
| 1005 | left -= this_len; | 1004 | left -= this_len; |
| 1006 | } | 1005 | } |
| 1007 | 1006 | ||
| 1008 | /* ... iov_iter */ | 1007 | iov_iter_bvec(&from, ITER_BVEC | WRITE, array, n, |
| 1009 | from.type = ITER_BVEC | WRITE; | 1008 | sd.total_len - left); |
| 1010 | from.bvec = array; | 1009 | ret = vfs_iter_write(out, &from, &sd.pos); |
| 1011 | from.nr_segs = n; | ||
| 1012 | from.count = sd.total_len - left; | ||
| 1013 | from.iov_offset = 0; | ||
| 1014 | |||
| 1015 | /* ... and iocb */ | ||
| 1016 | init_sync_kiocb(&kiocb, out); | ||
| 1017 | kiocb.ki_pos = sd.pos; | ||
| 1018 | kiocb.ki_nbytes = sd.total_len - left; | ||
| 1019 | |||
| 1020 | /* now, send it */ | ||
| 1021 | ret = out->f_op->write_iter(&kiocb, &from); | ||
| 1022 | if (-EIOCBQUEUED == ret) | ||
| 1023 | ret = wait_on_sync_kiocb(&kiocb); | ||
| 1024 | |||
| 1025 | if (ret <= 0) | 1010 | if (ret <= 0) |
| 1026 | break; | 1011 | break; |
| 1027 | 1012 | ||
| 1028 | sd.num_spliced += ret; | 1013 | sd.num_spliced += ret; |
| 1029 | sd.total_len -= ret; | 1014 | sd.total_len -= ret; |
| 1030 | *ppos = sd.pos = kiocb.ki_pos; | 1015 | *ppos = sd.pos; |
| 1031 | 1016 | ||
| 1032 | /* dismiss the fully eaten buffers, adjust the partial one */ | 1017 | /* dismiss the fully eaten buffers, adjust the partial one */ |
| 1033 | while (ret) { | 1018 | while (ret) { |
diff --git a/fs/super.c b/fs/super.c index 1facd2c282e5..65a53efc1cf4 100644 --- a/fs/super.c +++ b/fs/super.c | |||
| @@ -715,9 +715,9 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) | |||
| 715 | remount_ro = (flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY); | 715 | remount_ro = (flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY); |
| 716 | 716 | ||
| 717 | if (remount_ro) { | 717 | if (remount_ro) { |
| 718 | if (sb->s_pins.first) { | 718 | if (!hlist_empty(&sb->s_pins)) { |
| 719 | up_write(&sb->s_umount); | 719 | up_write(&sb->s_umount); |
| 720 | sb_pin_kill(sb); | 720 | group_pin_kill(&sb->s_pins); |
| 721 | down_write(&sb->s_umount); | 721 | down_write(&sb->s_umount); |
| 722 | if (!sb->s_root) | 722 | if (!sb->s_root) |
| 723 | return 0; | 723 | return 0; |
| @@ -177,8 +177,16 @@ SYSCALL_DEFINE1(syncfs, int, fd) | |||
| 177 | */ | 177 | */ |
| 178 | int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync) | 178 | int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync) |
| 179 | { | 179 | { |
| 180 | struct inode *inode = file->f_mapping->host; | ||
| 181 | |||
| 180 | if (!file->f_op->fsync) | 182 | if (!file->f_op->fsync) |
| 181 | return -EINVAL; | 183 | return -EINVAL; |
| 184 | if (!datasync && (inode->i_state & I_DIRTY_TIME)) { | ||
| 185 | spin_lock(&inode->i_lock); | ||
| 186 | inode->i_state &= ~I_DIRTY_TIME; | ||
| 187 | spin_unlock(&inode->i_lock); | ||
| 188 | mark_inode_dirty_sync(inode); | ||
| 189 | } | ||
| 182 | return file->f_op->fsync(file, start, end, datasync); | 190 | return file->f_op->fsync(file, start, end, datasync); |
| 183 | } | 191 | } |
| 184 | EXPORT_SYMBOL(vfs_fsync_range); | 192 | EXPORT_SYMBOL(vfs_fsync_range); |
diff --git a/fs/ufs/super.c b/fs/ufs/super.c index da73801301d5..8092d3759a5e 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c | |||
| @@ -95,22 +95,18 @@ | |||
| 95 | 95 | ||
| 96 | void lock_ufs(struct super_block *sb) | 96 | void lock_ufs(struct super_block *sb) |
| 97 | { | 97 | { |
| 98 | #if defined(CONFIG_SMP) || defined (CONFIG_PREEMPT) | ||
| 99 | struct ufs_sb_info *sbi = UFS_SB(sb); | 98 | struct ufs_sb_info *sbi = UFS_SB(sb); |
| 100 | 99 | ||
| 101 | mutex_lock(&sbi->mutex); | 100 | mutex_lock(&sbi->mutex); |
| 102 | sbi->mutex_owner = current; | 101 | sbi->mutex_owner = current; |
| 103 | #endif | ||
| 104 | } | 102 | } |
| 105 | 103 | ||
| 106 | void unlock_ufs(struct super_block *sb) | 104 | void unlock_ufs(struct super_block *sb) |
| 107 | { | 105 | { |
| 108 | #if defined(CONFIG_SMP) || defined (CONFIG_PREEMPT) | ||
| 109 | struct ufs_sb_info *sbi = UFS_SB(sb); | 106 | struct ufs_sb_info *sbi = UFS_SB(sb); |
| 110 | 107 | ||
| 111 | sbi->mutex_owner = NULL; | 108 | sbi->mutex_owner = NULL; |
| 112 | mutex_unlock(&sbi->mutex); | 109 | mutex_unlock(&sbi->mutex); |
| 113 | #endif | ||
| 114 | } | 110 | } |
| 115 | 111 | ||
| 116 | static struct inode *ufs_nfs_get_inode(struct super_block *sb, u64 ino, u32 generation) | 112 | static struct inode *ufs_nfs_get_inode(struct super_block *sb, u64 ino, u32 generation) |
| @@ -1415,9 +1411,11 @@ static struct kmem_cache * ufs_inode_cachep; | |||
| 1415 | static struct inode *ufs_alloc_inode(struct super_block *sb) | 1411 | static struct inode *ufs_alloc_inode(struct super_block *sb) |
| 1416 | { | 1412 | { |
| 1417 | struct ufs_inode_info *ei; | 1413 | struct ufs_inode_info *ei; |
| 1418 | ei = (struct ufs_inode_info *)kmem_cache_alloc(ufs_inode_cachep, GFP_NOFS); | 1414 | |
| 1415 | ei = kmem_cache_alloc(ufs_inode_cachep, GFP_NOFS); | ||
| 1419 | if (!ei) | 1416 | if (!ei) |
| 1420 | return NULL; | 1417 | return NULL; |
| 1418 | |||
| 1421 | ei->vfs_inode.i_version = 1; | 1419 | ei->vfs_inode.i_version = 1; |
| 1422 | return &ei->vfs_inode; | 1420 | return &ei->vfs_inode; |
| 1423 | } | 1421 | } |
diff --git a/include/linux/audit.h b/include/linux/audit.h index 599f3bd2d6c5..c2e7e3a83965 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h | |||
| @@ -127,7 +127,6 @@ extern void __audit_syscall_entry(int major, unsigned long a0, unsigned long a1, | |||
| 127 | extern void __audit_syscall_exit(int ret_success, long ret_value); | 127 | extern void __audit_syscall_exit(int ret_success, long ret_value); |
| 128 | extern struct filename *__audit_reusename(const __user char *uptr); | 128 | extern struct filename *__audit_reusename(const __user char *uptr); |
| 129 | extern void __audit_getname(struct filename *name); | 129 | extern void __audit_getname(struct filename *name); |
| 130 | extern void audit_putname(struct filename *name); | ||
| 131 | 130 | ||
| 132 | #define AUDIT_INODE_PARENT 1 /* dentry represents the parent */ | 131 | #define AUDIT_INODE_PARENT 1 /* dentry represents the parent */ |
| 133 | #define AUDIT_INODE_HIDDEN 2 /* audit record should be hidden */ | 132 | #define AUDIT_INODE_HIDDEN 2 /* audit record should be hidden */ |
| @@ -352,8 +351,6 @@ static inline struct filename *audit_reusename(const __user char *name) | |||
| 352 | } | 351 | } |
| 353 | static inline void audit_getname(struct filename *name) | 352 | static inline void audit_getname(struct filename *name) |
| 354 | { } | 353 | { } |
| 355 | static inline void audit_putname(struct filename *name) | ||
| 356 | { } | ||
| 357 | static inline void __audit_inode(struct filename *name, | 354 | static inline void __audit_inode(struct filename *name, |
| 358 | const struct dentry *dentry, | 355 | const struct dentry *dentry, |
| 359 | unsigned int flags) | 356 | unsigned int flags) |
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index d94077fea1f8..aff923ae8c4b 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h | |||
| @@ -55,6 +55,7 @@ struct bdi_writeback { | |||
| 55 | struct list_head b_dirty; /* dirty inodes */ | 55 | struct list_head b_dirty; /* dirty inodes */ |
| 56 | struct list_head b_io; /* parked for writeback */ | 56 | struct list_head b_io; /* parked for writeback */ |
| 57 | struct list_head b_more_io; /* parked for more writeback */ | 57 | struct list_head b_more_io; /* parked for more writeback */ |
| 58 | struct list_head b_dirty_time; /* time stamps are dirty */ | ||
| 58 | spinlock_t list_lock; /* protects the b_* lists */ | 59 | spinlock_t list_lock; /* protects the b_* lists */ |
| 59 | }; | 60 | }; |
| 60 | 61 | ||
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index ab70f3bc44ad..f551a9299ac9 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h | |||
| @@ -50,6 +50,15 @@ struct cpuidle_state { | |||
| 50 | int index); | 50 | int index); |
| 51 | 51 | ||
| 52 | int (*enter_dead) (struct cpuidle_device *dev, int index); | 52 | int (*enter_dead) (struct cpuidle_device *dev, int index); |
| 53 | |||
| 54 | /* | ||
| 55 | * CPUs execute ->enter_freeze with the local tick or entire timekeeping | ||
| 56 | * suspended, so it must not re-enable interrupts at any point (even | ||
| 57 | * temporarily) or attempt to change states of clock event devices. | ||
| 58 | */ | ||
| 59 | void (*enter_freeze) (struct cpuidle_device *dev, | ||
| 60 | struct cpuidle_driver *drv, | ||
| 61 | int index); | ||
| 53 | }; | 62 | }; |
| 54 | 63 | ||
| 55 | /* Idle State Flags */ | 64 | /* Idle State Flags */ |
| @@ -141,7 +150,7 @@ extern void cpuidle_resume(void); | |||
| 141 | extern int cpuidle_enable_device(struct cpuidle_device *dev); | 150 | extern int cpuidle_enable_device(struct cpuidle_device *dev); |
| 142 | extern void cpuidle_disable_device(struct cpuidle_device *dev); | 151 | extern void cpuidle_disable_device(struct cpuidle_device *dev); |
| 143 | extern int cpuidle_play_dead(void); | 152 | extern int cpuidle_play_dead(void); |
| 144 | extern void cpuidle_use_deepest_state(bool enable); | 153 | extern void cpuidle_enter_freeze(void); |
| 145 | 154 | ||
| 146 | extern struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev); | 155 | extern struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev); |
| 147 | #else | 156 | #else |
| @@ -174,7 +183,7 @@ static inline int cpuidle_enable_device(struct cpuidle_device *dev) | |||
| 174 | {return -ENODEV; } | 183 | {return -ENODEV; } |
| 175 | static inline void cpuidle_disable_device(struct cpuidle_device *dev) { } | 184 | static inline void cpuidle_disable_device(struct cpuidle_device *dev) { } |
| 176 | static inline int cpuidle_play_dead(void) {return -ENODEV; } | 185 | static inline int cpuidle_play_dead(void) {return -ENODEV; } |
| 177 | static inline void cpuidle_use_deepest_state(bool enable) {} | 186 | static inline void cpuidle_enter_freeze(void) { } |
| 178 | static inline struct cpuidle_driver *cpuidle_get_cpu_driver( | 187 | static inline struct cpuidle_driver *cpuidle_get_cpu_driver( |
| 179 | struct cpuidle_device *dev) {return NULL; } | 188 | struct cpuidle_device *dev) {return NULL; } |
| 180 | #endif | 189 | #endif |
diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 5a813988e6d4..92c08cf7670e 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h | |||
| @@ -319,9 +319,6 @@ static inline unsigned d_count(const struct dentry *dentry) | |||
| 319 | return dentry->d_lockref.count; | 319 | return dentry->d_lockref.count; |
| 320 | } | 320 | } |
| 321 | 321 | ||
| 322 | /* validate "insecure" dentry pointer */ | ||
| 323 | extern int d_validate(struct dentry *, struct dentry *); | ||
| 324 | |||
| 325 | /* | 322 | /* |
| 326 | * helper function for dentry_operations.d_dname() members | 323 | * helper function for dentry_operations.d_dname() members |
| 327 | */ | 324 | */ |
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index da4c4983adbe..cb25af461054 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h | |||
| @@ -51,11 +51,21 @@ struct dentry *debugfs_create_file(const char *name, umode_t mode, | |||
| 51 | struct dentry *parent, void *data, | 51 | struct dentry *parent, void *data, |
| 52 | const struct file_operations *fops); | 52 | const struct file_operations *fops); |
| 53 | 53 | ||
| 54 | struct dentry *debugfs_create_file_size(const char *name, umode_t mode, | ||
| 55 | struct dentry *parent, void *data, | ||
| 56 | const struct file_operations *fops, | ||
| 57 | loff_t file_size); | ||
| 58 | |||
| 54 | struct dentry *debugfs_create_dir(const char *name, struct dentry *parent); | 59 | struct dentry *debugfs_create_dir(const char *name, struct dentry *parent); |
| 55 | 60 | ||
| 56 | struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, | 61 | struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, |
| 57 | const char *dest); | 62 | const char *dest); |
| 58 | 63 | ||
| 64 | struct dentry *debugfs_create_automount(const char *name, | ||
| 65 | struct dentry *parent, | ||
| 66 | struct vfsmount *(*f)(void *), | ||
| 67 | void *data); | ||
| 68 | |||
| 59 | void debugfs_remove(struct dentry *dentry); | 69 | void debugfs_remove(struct dentry *dentry); |
| 60 | void debugfs_remove_recursive(struct dentry *dentry); | 70 | void debugfs_remove_recursive(struct dentry *dentry); |
| 61 | 71 | ||
| @@ -124,6 +134,14 @@ static inline struct dentry *debugfs_create_file(const char *name, umode_t mode, | |||
| 124 | return ERR_PTR(-ENODEV); | 134 | return ERR_PTR(-ENODEV); |
| 125 | } | 135 | } |
| 126 | 136 | ||
| 137 | static inline struct dentry *debugfs_create_file_size(const char *name, umode_t mode, | ||
| 138 | struct dentry *parent, void *data, | ||
| 139 | const struct file_operations *fops, | ||
| 140 | loff_t file_size) | ||
| 141 | { | ||
| 142 | return ERR_PTR(-ENODEV); | ||
| 143 | } | ||
| 144 | |||
| 127 | static inline struct dentry *debugfs_create_dir(const char *name, | 145 | static inline struct dentry *debugfs_create_dir(const char *name, |
| 128 | struct dentry *parent) | 146 | struct dentry *parent) |
| 129 | { | 147 | { |
diff --git a/include/linux/fs.h b/include/linux/fs.h index ed5a0900b94d..447932aed1e1 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -1790,8 +1790,12 @@ struct super_operations { | |||
| 1790 | #define __I_DIO_WAKEUP 9 | 1790 | #define __I_DIO_WAKEUP 9 |
| 1791 | #define I_DIO_WAKEUP (1 << I_DIO_WAKEUP) | 1791 | #define I_DIO_WAKEUP (1 << I_DIO_WAKEUP) |
| 1792 | #define I_LINKABLE (1 << 10) | 1792 | #define I_LINKABLE (1 << 10) |
| 1793 | #define I_DIRTY_TIME (1 << 11) | ||
| 1794 | #define __I_DIRTY_TIME_EXPIRED 12 | ||
| 1795 | #define I_DIRTY_TIME_EXPIRED (1 << __I_DIRTY_TIME_EXPIRED) | ||
| 1793 | 1796 | ||
| 1794 | #define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES) | 1797 | #define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES) |
| 1798 | #define I_DIRTY_ALL (I_DIRTY | I_DIRTY_TIME) | ||
| 1795 | 1799 | ||
| 1796 | extern void __mark_inode_dirty(struct inode *, int); | 1800 | extern void __mark_inode_dirty(struct inode *, int); |
| 1797 | static inline void mark_inode_dirty(struct inode *inode) | 1801 | static inline void mark_inode_dirty(struct inode *inode) |
| @@ -1954,6 +1958,7 @@ extern int current_umask(void); | |||
| 1954 | 1958 | ||
| 1955 | extern void ihold(struct inode * inode); | 1959 | extern void ihold(struct inode * inode); |
| 1956 | extern void iput(struct inode *); | 1960 | extern void iput(struct inode *); |
| 1961 | extern int generic_update_time(struct inode *, struct timespec *, int); | ||
| 1957 | 1962 | ||
| 1958 | static inline struct inode *file_inode(const struct file *f) | 1963 | static inline struct inode *file_inode(const struct file *f) |
| 1959 | { | 1964 | { |
| @@ -2141,6 +2146,7 @@ struct filename { | |||
| 2141 | const char *name; /* pointer to actual string */ | 2146 | const char *name; /* pointer to actual string */ |
| 2142 | const __user char *uptr; /* original userland pointer */ | 2147 | const __user char *uptr; /* original userland pointer */ |
| 2143 | struct audit_names *aname; | 2148 | struct audit_names *aname; |
| 2149 | int refcnt; | ||
| 2144 | bool separate; /* should "name" be freed? */ | 2150 | bool separate; /* should "name" be freed? */ |
| 2145 | }; | 2151 | }; |
| 2146 | 2152 | ||
| @@ -2162,6 +2168,7 @@ extern int filp_close(struct file *, fl_owner_t id); | |||
| 2162 | extern struct filename *getname_flags(const char __user *, int, int *); | 2168 | extern struct filename *getname_flags(const char __user *, int, int *); |
| 2163 | extern struct filename *getname(const char __user *); | 2169 | extern struct filename *getname(const char __user *); |
| 2164 | extern struct filename *getname_kernel(const char *); | 2170 | extern struct filename *getname_kernel(const char *); |
| 2171 | extern void putname(struct filename *name); | ||
| 2165 | 2172 | ||
| 2166 | enum { | 2173 | enum { |
| 2167 | FILE_CREATED = 1, | 2174 | FILE_CREATED = 1, |
| @@ -2182,15 +2189,8 @@ extern void __init vfs_caches_init(unsigned long); | |||
| 2182 | 2189 | ||
| 2183 | extern struct kmem_cache *names_cachep; | 2190 | extern struct kmem_cache *names_cachep; |
| 2184 | 2191 | ||
| 2185 | extern void final_putname(struct filename *name); | ||
| 2186 | |||
| 2187 | #define __getname() kmem_cache_alloc(names_cachep, GFP_KERNEL) | 2192 | #define __getname() kmem_cache_alloc(names_cachep, GFP_KERNEL) |
| 2188 | #define __putname(name) kmem_cache_free(names_cachep, (void *)(name)) | 2193 | #define __putname(name) kmem_cache_free(names_cachep, (void *)(name)) |
| 2189 | #ifndef CONFIG_AUDITSYSCALL | ||
| 2190 | #define putname(name) final_putname(name) | ||
| 2191 | #else | ||
| 2192 | extern void putname(struct filename *name); | ||
| 2193 | #endif | ||
| 2194 | 2194 | ||
| 2195 | #ifdef CONFIG_BLOCK | 2195 | #ifdef CONFIG_BLOCK |
| 2196 | extern int register_blkdev(unsigned int, const char *); | 2196 | extern int register_blkdev(unsigned int, const char *); |
| @@ -2497,6 +2497,11 @@ extern struct inode *ilookup(struct super_block *sb, unsigned long ino); | |||
| 2497 | 2497 | ||
| 2498 | extern struct inode * iget5_locked(struct super_block *, unsigned long, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *); | 2498 | extern struct inode * iget5_locked(struct super_block *, unsigned long, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *); |
| 2499 | extern struct inode * iget_locked(struct super_block *, unsigned long); | 2499 | extern struct inode * iget_locked(struct super_block *, unsigned long); |
| 2500 | extern struct inode *find_inode_nowait(struct super_block *, | ||
| 2501 | unsigned long, | ||
| 2502 | int (*match)(struct inode *, | ||
| 2503 | unsigned long, void *), | ||
| 2504 | void *data); | ||
| 2500 | extern int insert_inode_locked4(struct inode *, unsigned long, int (*test)(struct inode *, void *), void *); | 2505 | extern int insert_inode_locked4(struct inode *, unsigned long, int (*test)(struct inode *, void *), void *); |
| 2501 | extern int insert_inode_locked(struct inode *); | 2506 | extern int insert_inode_locked(struct inode *); |
| 2502 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 2507 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
| @@ -2553,6 +2558,9 @@ extern ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t l | |||
| 2553 | extern ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos); | 2558 | extern ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos); |
| 2554 | extern ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos); | 2559 | extern ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos); |
| 2555 | 2560 | ||
| 2561 | ssize_t vfs_iter_read(struct file *file, struct iov_iter *iter, loff_t *ppos); | ||
| 2562 | ssize_t vfs_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos); | ||
| 2563 | |||
| 2556 | /* fs/block_dev.c */ | 2564 | /* fs/block_dev.c */ |
| 2557 | extern ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to); | 2565 | extern ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to); |
| 2558 | extern ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from); | 2566 | extern ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from); |
diff --git a/include/linux/fs_pin.h b/include/linux/fs_pin.h index f66525e72ccf..9dc4e0384bfb 100644 --- a/include/linux/fs_pin.h +++ b/include/linux/fs_pin.h | |||
| @@ -1,17 +1,22 @@ | |||
| 1 | #include <linux/fs.h> | 1 | #include <linux/wait.h> |
| 2 | 2 | ||
| 3 | struct fs_pin { | 3 | struct fs_pin { |
| 4 | atomic_long_t count; | 4 | wait_queue_head_t wait; |
| 5 | union { | 5 | int done; |
| 6 | struct { | 6 | struct hlist_node s_list; |
| 7 | struct hlist_node s_list; | 7 | struct hlist_node m_list; |
| 8 | struct hlist_node m_list; | ||
| 9 | }; | ||
| 10 | struct rcu_head rcu; | ||
| 11 | }; | ||
| 12 | void (*kill)(struct fs_pin *); | 8 | void (*kill)(struct fs_pin *); |
| 13 | }; | 9 | }; |
| 14 | 10 | ||
| 15 | void pin_put(struct fs_pin *); | 11 | struct vfsmount; |
| 12 | |||
| 13 | static inline void init_fs_pin(struct fs_pin *p, void (*kill)(struct fs_pin *)) | ||
| 14 | { | ||
| 15 | init_waitqueue_head(&p->wait); | ||
| 16 | p->kill = kill; | ||
| 17 | } | ||
| 18 | |||
| 16 | void pin_remove(struct fs_pin *); | 19 | void pin_remove(struct fs_pin *); |
| 20 | void pin_insert_group(struct fs_pin *, struct vfsmount *, struct hlist_head *); | ||
| 17 | void pin_insert(struct fs_pin *, struct vfsmount *); | 21 | void pin_insert(struct fs_pin *, struct vfsmount *); |
| 22 | void pin_kill(struct fs_pin *); | ||
diff --git a/include/linux/kexec.h b/include/linux/kexec.h index 9d957b7ae095..e60a745ac198 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h | |||
| @@ -1,6 +1,19 @@ | |||
| 1 | #ifndef LINUX_KEXEC_H | 1 | #ifndef LINUX_KEXEC_H |
| 2 | #define LINUX_KEXEC_H | 2 | #define LINUX_KEXEC_H |
| 3 | 3 | ||
| 4 | #define IND_DESTINATION_BIT 0 | ||
| 5 | #define IND_INDIRECTION_BIT 1 | ||
| 6 | #define IND_DONE_BIT 2 | ||
| 7 | #define IND_SOURCE_BIT 3 | ||
| 8 | |||
| 9 | #define IND_DESTINATION (1 << IND_DESTINATION_BIT) | ||
| 10 | #define IND_INDIRECTION (1 << IND_INDIRECTION_BIT) | ||
| 11 | #define IND_DONE (1 << IND_DONE_BIT) | ||
| 12 | #define IND_SOURCE (1 << IND_SOURCE_BIT) | ||
| 13 | #define IND_FLAGS (IND_DESTINATION | IND_INDIRECTION | IND_DONE | IND_SOURCE) | ||
| 14 | |||
| 15 | #if !defined(__ASSEMBLY__) | ||
| 16 | |||
| 4 | #include <uapi/linux/kexec.h> | 17 | #include <uapi/linux/kexec.h> |
| 5 | 18 | ||
| 6 | #ifdef CONFIG_KEXEC | 19 | #ifdef CONFIG_KEXEC |
| @@ -64,10 +77,6 @@ | |||
| 64 | */ | 77 | */ |
| 65 | 78 | ||
| 66 | typedef unsigned long kimage_entry_t; | 79 | typedef unsigned long kimage_entry_t; |
| 67 | #define IND_DESTINATION 0x1 | ||
| 68 | #define IND_INDIRECTION 0x2 | ||
| 69 | #define IND_DONE 0x4 | ||
| 70 | #define IND_SOURCE 0x8 | ||
| 71 | 80 | ||
| 72 | struct kexec_segment { | 81 | struct kexec_segment { |
| 73 | /* | 82 | /* |
| @@ -122,8 +131,6 @@ struct kimage { | |||
| 122 | kimage_entry_t *entry; | 131 | kimage_entry_t *entry; |
| 123 | kimage_entry_t *last_entry; | 132 | kimage_entry_t *last_entry; |
| 124 | 133 | ||
| 125 | unsigned long destination; | ||
| 126 | |||
| 127 | unsigned long start; | 134 | unsigned long start; |
| 128 | struct page *control_code_page; | 135 | struct page *control_code_page; |
| 129 | struct page *swap_page; | 136 | struct page *swap_page; |
| @@ -313,4 +320,7 @@ struct task_struct; | |||
| 313 | static inline void crash_kexec(struct pt_regs *regs) { } | 320 | static inline void crash_kexec(struct pt_regs *regs) { } |
| 314 | static inline int kexec_should_crash(struct task_struct *p) { return 0; } | 321 | static inline int kexec_should_crash(struct task_struct *p) { return 0; } |
| 315 | #endif /* CONFIG_KEXEC */ | 322 | #endif /* CONFIG_KEXEC */ |
| 323 | |||
| 324 | #endif /* !defined(__ASSEBMLY__) */ | ||
| 325 | |||
| 316 | #endif /* LINUX_KEXEC_H */ | 326 | #endif /* LINUX_KEXEC_H */ |
diff --git a/include/linux/lockref.h b/include/linux/lockref.h index 4bfde0e99ed5..b10b122dd099 100644 --- a/include/linux/lockref.h +++ b/include/linux/lockref.h | |||
| @@ -28,12 +28,13 @@ struct lockref { | |||
| 28 | #endif | 28 | #endif |
| 29 | struct { | 29 | struct { |
| 30 | spinlock_t lock; | 30 | spinlock_t lock; |
| 31 | unsigned int count; | 31 | int count; |
| 32 | }; | 32 | }; |
| 33 | }; | 33 | }; |
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | extern void lockref_get(struct lockref *); | 36 | extern void lockref_get(struct lockref *); |
| 37 | extern int lockref_put_return(struct lockref *); | ||
| 37 | extern int lockref_get_not_zero(struct lockref *); | 38 | extern int lockref_get_not_zero(struct lockref *); |
| 38 | extern int lockref_get_or_lock(struct lockref *); | 39 | extern int lockref_get_or_lock(struct lockref *); |
| 39 | extern int lockref_put_or_lock(struct lockref *); | 40 | extern int lockref_put_or_lock(struct lockref *); |
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 2e75ab00dbf2..e530533b94be 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h | |||
| @@ -364,8 +364,6 @@ struct ssb_device_id { | |||
| 364 | } __attribute__((packed, aligned(2))); | 364 | } __attribute__((packed, aligned(2))); |
| 365 | #define SSB_DEVICE(_vendor, _coreid, _revision) \ | 365 | #define SSB_DEVICE(_vendor, _coreid, _revision) \ |
| 366 | { .vendor = _vendor, .coreid = _coreid, .revision = _revision, } | 366 | { .vendor = _vendor, .coreid = _coreid, .revision = _revision, } |
| 367 | #define SSB_DEVTABLE_END \ | ||
| 368 | { 0, }, | ||
| 369 | 367 | ||
| 370 | #define SSB_ANY_VENDOR 0xFFFF | 368 | #define SSB_ANY_VENDOR 0xFFFF |
| 371 | #define SSB_ANY_ID 0xFFFF | 369 | #define SSB_ANY_ID 0xFFFF |
| @@ -380,8 +378,6 @@ struct bcma_device_id { | |||
| 380 | } __attribute__((packed,aligned(2))); | 378 | } __attribute__((packed,aligned(2))); |
| 381 | #define BCMA_CORE(_manuf, _id, _rev, _class) \ | 379 | #define BCMA_CORE(_manuf, _id, _rev, _class) \ |
| 382 | { .manuf = _manuf, .id = _id, .rev = _rev, .class = _class, } | 380 | { .manuf = _manuf, .id = _id, .rev = _rev, .class = _class, } |
| 383 | #define BCMA_CORETABLE_END \ | ||
| 384 | { 0, }, | ||
| 385 | 381 | ||
| 386 | #define BCMA_ANY_MANUF 0xFFFF | 382 | #define BCMA_ANY_MANUF 0xFFFF |
| 387 | #define BCMA_ANY_ID 0xFFFF | 383 | #define BCMA_ANY_ID 0xFFFF |
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 3301c4c289d6..f17fa75809aa 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h | |||
| @@ -227,6 +227,7 @@ struct mtd_info { | |||
| 227 | int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs); | 227 | int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs); |
| 228 | int (*_suspend) (struct mtd_info *mtd); | 228 | int (*_suspend) (struct mtd_info *mtd); |
| 229 | void (*_resume) (struct mtd_info *mtd); | 229 | void (*_resume) (struct mtd_info *mtd); |
| 230 | void (*_reboot) (struct mtd_info *mtd); | ||
| 230 | /* | 231 | /* |
| 231 | * If the driver is something smart, like UBI, it may need to maintain | 232 | * If the driver is something smart, like UBI, it may need to maintain |
| 232 | * its own reference counting. The below functions are only for driver. | 233 | * its own reference counting. The below functions are only for driver. |
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 63aeccf9ddc8..4720b86ee73d 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h | |||
| @@ -56,6 +56,10 @@ | |||
| 56 | /* Used for Spansion flashes only. */ | 56 | /* Used for Spansion flashes only. */ |
| 57 | #define SPINOR_OP_BRWR 0x17 /* Bank register write */ | 57 | #define SPINOR_OP_BRWR 0x17 /* Bank register write */ |
| 58 | 58 | ||
| 59 | /* Used for Micron flashes only. */ | ||
| 60 | #define SPINOR_OP_RD_EVCR 0x65 /* Read EVCR register */ | ||
| 61 | #define SPINOR_OP_WD_EVCR 0x61 /* Write EVCR register */ | ||
| 62 | |||
| 59 | /* Status Register bits. */ | 63 | /* Status Register bits. */ |
| 60 | #define SR_WIP 1 /* Write in progress */ | 64 | #define SR_WIP 1 /* Write in progress */ |
| 61 | #define SR_WEL 2 /* Write enable latch */ | 65 | #define SR_WEL 2 /* Write enable latch */ |
| @@ -67,6 +71,9 @@ | |||
| 67 | 71 | ||
| 68 | #define SR_QUAD_EN_MX 0x40 /* Macronix Quad I/O */ | 72 | #define SR_QUAD_EN_MX 0x40 /* Macronix Quad I/O */ |
| 69 | 73 | ||
| 74 | /* Enhanced Volatile Configuration Register bits */ | ||
| 75 | #define EVCR_QUAD_EN_MICRON 0x80 /* Micron Quad I/O */ | ||
| 76 | |||
| 70 | /* Flag Status Register bits */ | 77 | /* Flag Status Register bits */ |
| 71 | #define FSR_READY 0x80 | 78 | #define FSR_READY 0x80 |
| 72 | 79 | ||
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index d115256ed5a2..5897b4ea5a3f 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
| @@ -1923,13 +1923,8 @@ struct napi_gro_cb { | |||
| 1923 | /* Number of segments aggregated. */ | 1923 | /* Number of segments aggregated. */ |
| 1924 | u16 count; | 1924 | u16 count; |
| 1925 | 1925 | ||
| 1926 | /* This is non-zero if the packet may be of the same flow. */ | 1926 | /* Start offset for remote checksum offload */ |
| 1927 | u8 same_flow; | 1927 | u16 gro_remcsum_start; |
| 1928 | |||
| 1929 | /* Free the skb? */ | ||
| 1930 | u8 free; | ||
| 1931 | #define NAPI_GRO_FREE 1 | ||
| 1932 | #define NAPI_GRO_FREE_STOLEN_HEAD 2 | ||
| 1933 | 1928 | ||
| 1934 | /* jiffies when first packet was created/queued */ | 1929 | /* jiffies when first packet was created/queued */ |
| 1935 | unsigned long age; | 1930 | unsigned long age; |
| @@ -1937,6 +1932,9 @@ struct napi_gro_cb { | |||
| 1937 | /* Used in ipv6_gro_receive() and foo-over-udp */ | 1932 | /* Used in ipv6_gro_receive() and foo-over-udp */ |
| 1938 | u16 proto; | 1933 | u16 proto; |
| 1939 | 1934 | ||
| 1935 | /* This is non-zero if the packet may be of the same flow. */ | ||
| 1936 | u8 same_flow:1; | ||
| 1937 | |||
| 1940 | /* Used in udp_gro_receive */ | 1938 | /* Used in udp_gro_receive */ |
| 1941 | u8 udp_mark:1; | 1939 | u8 udp_mark:1; |
| 1942 | 1940 | ||
| @@ -1946,9 +1944,16 @@ struct napi_gro_cb { | |||
| 1946 | /* Number of checksums via CHECKSUM_UNNECESSARY */ | 1944 | /* Number of checksums via CHECKSUM_UNNECESSARY */ |
| 1947 | u8 csum_cnt:3; | 1945 | u8 csum_cnt:3; |
| 1948 | 1946 | ||
| 1947 | /* Free the skb? */ | ||
| 1948 | u8 free:2; | ||
| 1949 | #define NAPI_GRO_FREE 1 | ||
| 1950 | #define NAPI_GRO_FREE_STOLEN_HEAD 2 | ||
| 1951 | |||
| 1949 | /* Used in foo-over-udp, set in udp[46]_gro_receive */ | 1952 | /* Used in foo-over-udp, set in udp[46]_gro_receive */ |
| 1950 | u8 is_ipv6:1; | 1953 | u8 is_ipv6:1; |
| 1951 | 1954 | ||
| 1955 | /* 7 bit hole */ | ||
| 1956 | |||
| 1952 | /* used to support CHECKSUM_COMPLETE for tunneling protocols */ | 1957 | /* used to support CHECKSUM_COMPLETE for tunneling protocols */ |
| 1953 | __wsum csum; | 1958 | __wsum csum; |
| 1954 | 1959 | ||
| @@ -2242,11 +2247,20 @@ static inline void skb_gro_postpull_rcsum(struct sk_buff *skb, | |||
| 2242 | 2247 | ||
| 2243 | __sum16 __skb_gro_checksum_complete(struct sk_buff *skb); | 2248 | __sum16 __skb_gro_checksum_complete(struct sk_buff *skb); |
| 2244 | 2249 | ||
| 2250 | static inline bool skb_at_gro_remcsum_start(struct sk_buff *skb) | ||
| 2251 | { | ||
| 2252 | return (NAPI_GRO_CB(skb)->gro_remcsum_start - skb_headroom(skb) == | ||
| 2253 | skb_gro_offset(skb)); | ||
| 2254 | } | ||
| 2255 | |||
| 2245 | static inline bool __skb_gro_checksum_validate_needed(struct sk_buff *skb, | 2256 | static inline bool __skb_gro_checksum_validate_needed(struct sk_buff *skb, |
| 2246 | bool zero_okay, | 2257 | bool zero_okay, |
| 2247 | __sum16 check) | 2258 | __sum16 check) |
| 2248 | { | 2259 | { |
| 2249 | return (skb->ip_summed != CHECKSUM_PARTIAL && | 2260 | return ((skb->ip_summed != CHECKSUM_PARTIAL || |
| 2261 | skb_checksum_start_offset(skb) < | ||
| 2262 | skb_gro_offset(skb)) && | ||
| 2263 | !skb_at_gro_remcsum_start(skb) && | ||
| 2250 | NAPI_GRO_CB(skb)->csum_cnt == 0 && | 2264 | NAPI_GRO_CB(skb)->csum_cnt == 0 && |
| 2251 | (!zero_okay || check)); | 2265 | (!zero_okay || check)); |
| 2252 | } | 2266 | } |
| @@ -2321,20 +2335,48 @@ do { \ | |||
| 2321 | compute_pseudo(skb, proto)); \ | 2335 | compute_pseudo(skb, proto)); \ |
| 2322 | } while (0) | 2336 | } while (0) |
| 2323 | 2337 | ||
| 2338 | struct gro_remcsum { | ||
| 2339 | int offset; | ||
| 2340 | __wsum delta; | ||
| 2341 | }; | ||
| 2342 | |||
| 2343 | static inline void skb_gro_remcsum_init(struct gro_remcsum *grc) | ||
| 2344 | { | ||
| 2345 | grc->delta = 0; | ||
| 2346 | } | ||
| 2347 | |||
| 2324 | static inline void skb_gro_remcsum_process(struct sk_buff *skb, void *ptr, | 2348 | static inline void skb_gro_remcsum_process(struct sk_buff *skb, void *ptr, |
| 2325 | int start, int offset) | 2349 | int start, int offset, |
| 2350 | struct gro_remcsum *grc, | ||
| 2351 | bool nopartial) | ||
| 2326 | { | 2352 | { |
| 2327 | __wsum delta; | 2353 | __wsum delta; |
| 2328 | 2354 | ||
| 2329 | BUG_ON(!NAPI_GRO_CB(skb)->csum_valid); | 2355 | BUG_ON(!NAPI_GRO_CB(skb)->csum_valid); |
| 2330 | 2356 | ||
| 2357 | if (!nopartial) { | ||
| 2358 | NAPI_GRO_CB(skb)->gro_remcsum_start = | ||
| 2359 | ((unsigned char *)ptr + start) - skb->head; | ||
| 2360 | return; | ||
| 2361 | } | ||
| 2362 | |||
| 2331 | delta = remcsum_adjust(ptr, NAPI_GRO_CB(skb)->csum, start, offset); | 2363 | delta = remcsum_adjust(ptr, NAPI_GRO_CB(skb)->csum, start, offset); |
| 2332 | 2364 | ||
| 2333 | /* Adjust skb->csum since we changed the packet */ | 2365 | /* Adjust skb->csum since we changed the packet */ |
| 2334 | skb->csum = csum_add(skb->csum, delta); | ||
| 2335 | NAPI_GRO_CB(skb)->csum = csum_add(NAPI_GRO_CB(skb)->csum, delta); | 2366 | NAPI_GRO_CB(skb)->csum = csum_add(NAPI_GRO_CB(skb)->csum, delta); |
| 2367 | |||
| 2368 | grc->offset = (ptr + offset) - (void *)skb->head; | ||
| 2369 | grc->delta = delta; | ||
| 2336 | } | 2370 | } |
| 2337 | 2371 | ||
| 2372 | static inline void skb_gro_remcsum_cleanup(struct sk_buff *skb, | ||
| 2373 | struct gro_remcsum *grc) | ||
| 2374 | { | ||
| 2375 | if (!grc->delta) | ||
| 2376 | return; | ||
| 2377 | |||
| 2378 | remcsum_unadjust((__sum16 *)(skb->head + grc->offset), grc->delta); | ||
| 2379 | } | ||
| 2338 | 2380 | ||
| 2339 | static inline int dev_hard_header(struct sk_buff *skb, struct net_device *dev, | 2381 | static inline int dev_hard_header(struct sk_buff *skb, struct net_device *dev, |
| 2340 | unsigned short type, | 2382 | unsigned short type, |
diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h index b9cf6c51b181..918b117a7cd3 100644 --- a/include/linux/pid_namespace.h +++ b/include/linux/pid_namespace.h | |||
| @@ -19,7 +19,7 @@ struct pidmap { | |||
| 19 | #define BITS_PER_PAGE_MASK (BITS_PER_PAGE-1) | 19 | #define BITS_PER_PAGE_MASK (BITS_PER_PAGE-1) |
| 20 | #define PIDMAP_ENTRIES ((PID_MAX_LIMIT+BITS_PER_PAGE-1)/BITS_PER_PAGE) | 20 | #define PIDMAP_ENTRIES ((PID_MAX_LIMIT+BITS_PER_PAGE-1)/BITS_PER_PAGE) |
| 21 | 21 | ||
| 22 | struct bsd_acct_struct; | 22 | struct fs_pin; |
| 23 | 23 | ||
| 24 | struct pid_namespace { | 24 | struct pid_namespace { |
| 25 | struct kref kref; | 25 | struct kref kref; |
| @@ -37,7 +37,7 @@ struct pid_namespace { | |||
| 37 | struct dentry *proc_thread_self; | 37 | struct dentry *proc_thread_self; |
| 38 | #endif | 38 | #endif |
| 39 | #ifdef CONFIG_BSD_PROCESS_ACCT | 39 | #ifdef CONFIG_BSD_PROCESS_ACCT |
| 40 | struct bsd_acct_struct *bacct; | 40 | struct fs_pin *bacct; |
| 41 | #endif | 41 | #endif |
| 42 | struct user_namespace *user_ns; | 42 | struct user_namespace *user_ns; |
| 43 | struct work_struct proc_work; | 43 | struct work_struct proc_work; |
diff --git a/include/linux/rbtree.h b/include/linux/rbtree.h index 57e75ae9910f..fb31765e935a 100644 --- a/include/linux/rbtree.h +++ b/include/linux/rbtree.h | |||
| @@ -51,7 +51,7 @@ struct rb_root { | |||
| 51 | 51 | ||
| 52 | #define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) | 52 | #define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) |
| 53 | 53 | ||
| 54 | /* 'empty' nodes are nodes that are known not to be inserted in an rbree */ | 54 | /* 'empty' nodes are nodes that are known not to be inserted in an rbtree */ |
| 55 | #define RB_EMPTY_NODE(node) \ | 55 | #define RB_EMPTY_NODE(node) \ |
| 56 | ((node)->__rb_parent_color == (unsigned long)(node)) | 56 | ((node)->__rb_parent_color == (unsigned long)(node)) |
| 57 | #define RB_CLEAR_NODE(node) \ | 57 | #define RB_CLEAR_NODE(node) \ |
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 1bb36edb66b9..30007afe70b3 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
| @@ -83,11 +83,15 @@ | |||
| 83 | * | 83 | * |
| 84 | * CHECKSUM_PARTIAL: | 84 | * CHECKSUM_PARTIAL: |
| 85 | * | 85 | * |
| 86 | * This is identical to the case for output below. This may occur on a packet | 86 | * A checksum is set up to be offloaded to a device as described in the |
| 87 | * output description for CHECKSUM_PARTIAL. This may occur on a packet | ||
| 87 | * received directly from another Linux OS, e.g., a virtualized Linux kernel | 88 | * received directly from another Linux OS, e.g., a virtualized Linux kernel |
| 88 | * on the same host. The packet can be treated in the same way as | 89 | * on the same host, or it may be set in the input path in GRO or remote |
| 89 | * CHECKSUM_UNNECESSARY, except that on output (i.e., forwarding) the | 90 | * checksum offload. For the purposes of checksum verification, the checksum |
| 90 | * checksum must be filled in by the OS or the hardware. | 91 | * referred to by skb->csum_start + skb->csum_offset and any preceding |
| 92 | * checksums in the packet are considered verified. Any checksums in the | ||
| 93 | * packet that are after the checksum being offloaded are not considered to | ||
| 94 | * be verified. | ||
| 91 | * | 95 | * |
| 92 | * B. Checksumming on output. | 96 | * B. Checksumming on output. |
| 93 | * | 97 | * |
| @@ -2915,7 +2919,10 @@ __sum16 __skb_checksum_complete(struct sk_buff *skb); | |||
| 2915 | 2919 | ||
| 2916 | static inline int skb_csum_unnecessary(const struct sk_buff *skb) | 2920 | static inline int skb_csum_unnecessary(const struct sk_buff *skb) |
| 2917 | { | 2921 | { |
| 2918 | return ((skb->ip_summed & CHECKSUM_UNNECESSARY) || skb->csum_valid); | 2922 | return ((skb->ip_summed == CHECKSUM_UNNECESSARY) || |
| 2923 | skb->csum_valid || | ||
| 2924 | (skb->ip_summed == CHECKSUM_PARTIAL && | ||
| 2925 | skb_checksum_start_offset(skb) >= 0)); | ||
| 2919 | } | 2926 | } |
| 2920 | 2927 | ||
| 2921 | /** | 2928 | /** |
| @@ -3097,16 +3104,29 @@ do { \ | |||
| 3097 | compute_pseudo(skb, proto)); \ | 3104 | compute_pseudo(skb, proto)); \ |
| 3098 | } while (0) | 3105 | } while (0) |
| 3099 | 3106 | ||
| 3107 | static inline void skb_remcsum_adjust_partial(struct sk_buff *skb, void *ptr, | ||
| 3108 | u16 start, u16 offset) | ||
| 3109 | { | ||
| 3110 | skb->ip_summed = CHECKSUM_PARTIAL; | ||
| 3111 | skb->csum_start = ((unsigned char *)ptr + start) - skb->head; | ||
| 3112 | skb->csum_offset = offset - start; | ||
| 3113 | } | ||
| 3114 | |||
| 3100 | /* Update skbuf and packet to reflect the remote checksum offload operation. | 3115 | /* Update skbuf and packet to reflect the remote checksum offload operation. |
| 3101 | * When called, ptr indicates the starting point for skb->csum when | 3116 | * When called, ptr indicates the starting point for skb->csum when |
| 3102 | * ip_summed is CHECKSUM_COMPLETE. If we need create checksum complete | 3117 | * ip_summed is CHECKSUM_COMPLETE. If we need create checksum complete |
| 3103 | * here, skb_postpull_rcsum is done so skb->csum start is ptr. | 3118 | * here, skb_postpull_rcsum is done so skb->csum start is ptr. |
| 3104 | */ | 3119 | */ |
| 3105 | static inline void skb_remcsum_process(struct sk_buff *skb, void *ptr, | 3120 | static inline void skb_remcsum_process(struct sk_buff *skb, void *ptr, |
| 3106 | int start, int offset) | 3121 | int start, int offset, bool nopartial) |
| 3107 | { | 3122 | { |
| 3108 | __wsum delta; | 3123 | __wsum delta; |
| 3109 | 3124 | ||
| 3125 | if (!nopartial) { | ||
| 3126 | skb_remcsum_adjust_partial(skb, ptr, start, offset); | ||
| 3127 | return; | ||
| 3128 | } | ||
| 3129 | |||
| 3110 | if (unlikely(skb->ip_summed != CHECKSUM_COMPLETE)) { | 3130 | if (unlikely(skb->ip_summed != CHECKSUM_COMPLETE)) { |
| 3111 | __skb_checksum_complete(skb); | 3131 | __skb_checksum_complete(skb); |
| 3112 | skb_postpull_rcsum(skb, skb->data, ptr - (void *)skb->data); | 3132 | skb_postpull_rcsum(skb, skb->data, ptr - (void *)skb->data); |
diff --git a/include/linux/suspend.h b/include/linux/suspend.h index 3388c1b6f7d8..5efe743ce1e8 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h | |||
| @@ -201,6 +201,21 @@ struct platform_freeze_ops { | |||
| 201 | */ | 201 | */ |
| 202 | extern void suspend_set_ops(const struct platform_suspend_ops *ops); | 202 | extern void suspend_set_ops(const struct platform_suspend_ops *ops); |
| 203 | extern int suspend_valid_only_mem(suspend_state_t state); | 203 | extern int suspend_valid_only_mem(suspend_state_t state); |
| 204 | |||
| 205 | /* Suspend-to-idle state machnine. */ | ||
| 206 | enum freeze_state { | ||
| 207 | FREEZE_STATE_NONE, /* Not suspended/suspending. */ | ||
| 208 | FREEZE_STATE_ENTER, /* Enter suspend-to-idle. */ | ||
| 209 | FREEZE_STATE_WAKE, /* Wake up from suspend-to-idle. */ | ||
| 210 | }; | ||
| 211 | |||
| 212 | extern enum freeze_state __read_mostly suspend_freeze_state; | ||
| 213 | |||
| 214 | static inline bool idle_should_freeze(void) | ||
| 215 | { | ||
| 216 | return unlikely(suspend_freeze_state == FREEZE_STATE_ENTER); | ||
| 217 | } | ||
| 218 | |||
| 204 | extern void freeze_set_ops(const struct platform_freeze_ops *ops); | 219 | extern void freeze_set_ops(const struct platform_freeze_ops *ops); |
| 205 | extern void freeze_wake(void); | 220 | extern void freeze_wake(void); |
| 206 | 221 | ||
| @@ -228,6 +243,7 @@ extern int pm_suspend(suspend_state_t state); | |||
| 228 | 243 | ||
| 229 | static inline void suspend_set_ops(const struct platform_suspend_ops *ops) {} | 244 | static inline void suspend_set_ops(const struct platform_suspend_ops *ops) {} |
| 230 | static inline int pm_suspend(suspend_state_t state) { return -ENOSYS; } | 245 | static inline int pm_suspend(suspend_state_t state) { return -ENOSYS; } |
| 246 | static inline bool idle_should_freeze(void) { return false; } | ||
| 231 | static inline void freeze_set_ops(const struct platform_freeze_ops *ops) {} | 247 | static inline void freeze_set_ops(const struct platform_freeze_ops *ops) {} |
| 232 | static inline void freeze_wake(void) {} | 248 | static inline void freeze_wake(void) {} |
| 233 | #endif /* !CONFIG_SUSPEND */ | 249 | #endif /* !CONFIG_SUSPEND */ |
diff --git a/include/linux/tick.h b/include/linux/tick.h index eda850ca757a..9c085dc12ae9 100644 --- a/include/linux/tick.h +++ b/include/linux/tick.h | |||
| @@ -79,6 +79,9 @@ extern void __init tick_init(void); | |||
| 79 | extern int tick_is_oneshot_available(void); | 79 | extern int tick_is_oneshot_available(void); |
| 80 | extern struct tick_device *tick_get_device(int cpu); | 80 | extern struct tick_device *tick_get_device(int cpu); |
| 81 | 81 | ||
| 82 | extern void tick_freeze(void); | ||
| 83 | extern void tick_unfreeze(void); | ||
| 84 | |||
| 82 | # ifdef CONFIG_HIGH_RES_TIMERS | 85 | # ifdef CONFIG_HIGH_RES_TIMERS |
| 83 | extern int tick_init_highres(void); | 86 | extern int tick_init_highres(void); |
| 84 | extern int tick_program_event(ktime_t expires, int force); | 87 | extern int tick_program_event(ktime_t expires, int force); |
| @@ -119,6 +122,8 @@ static inline int tick_oneshot_mode_active(void) { return 0; } | |||
| 119 | 122 | ||
| 120 | #else /* CONFIG_GENERIC_CLOCKEVENTS */ | 123 | #else /* CONFIG_GENERIC_CLOCKEVENTS */ |
| 121 | static inline void tick_init(void) { } | 124 | static inline void tick_init(void) { } |
| 125 | static inline void tick_freeze(void) { } | ||
| 126 | static inline void tick_unfreeze(void) { } | ||
| 122 | static inline void tick_cancel_sched_timer(int cpu) { } | 127 | static inline void tick_cancel_sched_timer(int cpu) { } |
| 123 | static inline void tick_clock_notify(void) { } | 128 | static inline void tick_clock_notify(void) { } |
| 124 | static inline int tick_check_oneshot_change(int allow_nohz) { return 0; } | 129 | static inline int tick_check_oneshot_change(int allow_nohz) { return 0; } |
| @@ -226,5 +231,4 @@ static inline void tick_nohz_task_switch(struct task_struct *tsk) | |||
| 226 | __tick_nohz_task_switch(tsk); | 231 | __tick_nohz_task_switch(tsk); |
| 227 | } | 232 | } |
| 228 | 233 | ||
| 229 | |||
| 230 | #endif | 234 | #endif |
diff --git a/include/linux/uio.h b/include/linux/uio.h index 3e0cb4ea3905..07a022641996 100644 --- a/include/linux/uio.h +++ b/include/linux/uio.h | |||
| @@ -88,7 +88,9 @@ size_t iov_iter_zero(size_t bytes, struct iov_iter *); | |||
| 88 | unsigned long iov_iter_alignment(const struct iov_iter *i); | 88 | unsigned long iov_iter_alignment(const struct iov_iter *i); |
| 89 | void iov_iter_init(struct iov_iter *i, int direction, const struct iovec *iov, | 89 | void iov_iter_init(struct iov_iter *i, int direction, const struct iovec *iov, |
| 90 | unsigned long nr_segs, size_t count); | 90 | unsigned long nr_segs, size_t count); |
| 91 | void iov_iter_kvec(struct iov_iter *i, int direction, const struct kvec *iov, | 91 | void iov_iter_kvec(struct iov_iter *i, int direction, const struct kvec *kvec, |
| 92 | unsigned long nr_segs, size_t count); | ||
| 93 | void iov_iter_bvec(struct iov_iter *i, int direction, const struct bio_vec *bvec, | ||
| 92 | unsigned long nr_segs, size_t count); | 94 | unsigned long nr_segs, size_t count); |
| 93 | ssize_t iov_iter_get_pages(struct iov_iter *i, struct page **pages, | 95 | ssize_t iov_iter_get_pages(struct iov_iter *i, struct page **pages, |
| 94 | size_t maxsize, unsigned maxpages, size_t *start); | 96 | size_t maxsize, unsigned maxpages, size_t *start); |
diff --git a/include/net/checksum.h b/include/net/checksum.h index e339a9513e29..0a55ac715077 100644 --- a/include/net/checksum.h +++ b/include/net/checksum.h | |||
| @@ -167,4 +167,9 @@ static inline __wsum remcsum_adjust(void *ptr, __wsum csum, | |||
| 167 | return delta; | 167 | return delta; |
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | static inline void remcsum_unadjust(__sum16 *psum, __wsum delta) | ||
| 171 | { | ||
| 172 | *psum = csum_fold(csum_sub(delta, *psum)); | ||
| 173 | } | ||
| 174 | |||
| 170 | #endif | 175 | #endif |
diff --git a/include/net/vxlan.h b/include/net/vxlan.h index 2927d6244481..eabd3a038674 100644 --- a/include/net/vxlan.h +++ b/include/net/vxlan.h | |||
| @@ -128,13 +128,15 @@ struct vxlan_sock { | |||
| 128 | #define VXLAN_F_REMCSUM_TX 0x200 | 128 | #define VXLAN_F_REMCSUM_TX 0x200 |
| 129 | #define VXLAN_F_REMCSUM_RX 0x400 | 129 | #define VXLAN_F_REMCSUM_RX 0x400 |
| 130 | #define VXLAN_F_GBP 0x800 | 130 | #define VXLAN_F_GBP 0x800 |
| 131 | #define VXLAN_F_REMCSUM_NOPARTIAL 0x1000 | ||
| 131 | 132 | ||
| 132 | /* Flags that are used in the receive patch. These flags must match in | 133 | /* Flags that are used in the receive patch. These flags must match in |
| 133 | * order for a socket to be shareable | 134 | * order for a socket to be shareable |
| 134 | */ | 135 | */ |
| 135 | #define VXLAN_F_RCV_FLAGS (VXLAN_F_GBP | \ | 136 | #define VXLAN_F_RCV_FLAGS (VXLAN_F_GBP | \ |
| 136 | VXLAN_F_UDP_ZERO_CSUM6_RX | \ | 137 | VXLAN_F_UDP_ZERO_CSUM6_RX | \ |
| 137 | VXLAN_F_REMCSUM_RX) | 138 | VXLAN_F_REMCSUM_RX | \ |
| 139 | VXLAN_F_REMCSUM_NOPARTIAL) | ||
| 138 | 140 | ||
| 139 | struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port, | 141 | struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port, |
| 140 | vxlan_rcv_t *rcv, void *data, | 142 | vxlan_rcv_t *rcv, void *data, |
diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h index 6cfb841fea7c..6e5abd6d38a2 100644 --- a/include/trace/events/ext4.h +++ b/include/trace/events/ext4.h | |||
| @@ -73,6 +73,36 @@ struct extent_status; | |||
| 73 | { FALLOC_FL_ZERO_RANGE, "ZERO_RANGE"}) | 73 | { FALLOC_FL_ZERO_RANGE, "ZERO_RANGE"}) |
| 74 | 74 | ||
| 75 | 75 | ||
| 76 | TRACE_EVENT(ext4_other_inode_update_time, | ||
| 77 | TP_PROTO(struct inode *inode, ino_t orig_ino), | ||
| 78 | |||
| 79 | TP_ARGS(inode, orig_ino), | ||
| 80 | |||
| 81 | TP_STRUCT__entry( | ||
| 82 | __field( dev_t, dev ) | ||
| 83 | __field( ino_t, ino ) | ||
| 84 | __field( ino_t, orig_ino ) | ||
| 85 | __field( uid_t, uid ) | ||
| 86 | __field( gid_t, gid ) | ||
| 87 | __field( __u16, mode ) | ||
| 88 | ), | ||
| 89 | |||
| 90 | TP_fast_assign( | ||
| 91 | __entry->orig_ino = orig_ino; | ||
| 92 | __entry->dev = inode->i_sb->s_dev; | ||
| 93 | __entry->ino = inode->i_ino; | ||
| 94 | __entry->uid = i_uid_read(inode); | ||
| 95 | __entry->gid = i_gid_read(inode); | ||
| 96 | __entry->mode = inode->i_mode; | ||
| 97 | ), | ||
| 98 | |||
| 99 | TP_printk("dev %d,%d orig_ino %lu ino %lu mode 0%o uid %u gid %u", | ||
| 100 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
| 101 | (unsigned long) __entry->orig_ino, | ||
| 102 | (unsigned long) __entry->ino, __entry->mode, | ||
| 103 | __entry->uid, __entry->gid) | ||
| 104 | ); | ||
| 105 | |||
| 76 | TRACE_EVENT(ext4_free_inode, | 106 | TRACE_EVENT(ext4_free_inode, |
| 77 | TP_PROTO(struct inode *inode), | 107 | TP_PROTO(struct inode *inode), |
| 78 | 108 | ||
diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h index 0e9310905413..5a14ead59696 100644 --- a/include/trace/events/writeback.h +++ b/include/trace/events/writeback.h | |||
| @@ -18,6 +18,8 @@ | |||
| 18 | {I_FREEING, "I_FREEING"}, \ | 18 | {I_FREEING, "I_FREEING"}, \ |
| 19 | {I_CLEAR, "I_CLEAR"}, \ | 19 | {I_CLEAR, "I_CLEAR"}, \ |
| 20 | {I_SYNC, "I_SYNC"}, \ | 20 | {I_SYNC, "I_SYNC"}, \ |
| 21 | {I_DIRTY_TIME, "I_DIRTY_TIME"}, \ | ||
| 22 | {I_DIRTY_TIME_EXPIRED, "I_DIRTY_TIME_EXPIRED"}, \ | ||
| 21 | {I_REFERENCED, "I_REFERENCED"} \ | 23 | {I_REFERENCED, "I_REFERENCED"} \ |
| 22 | ) | 24 | ) |
| 23 | 25 | ||
| @@ -68,6 +70,7 @@ DECLARE_EVENT_CLASS(writeback_dirty_inode_template, | |||
| 68 | TP_STRUCT__entry ( | 70 | TP_STRUCT__entry ( |
| 69 | __array(char, name, 32) | 71 | __array(char, name, 32) |
| 70 | __field(unsigned long, ino) | 72 | __field(unsigned long, ino) |
| 73 | __field(unsigned long, state) | ||
| 71 | __field(unsigned long, flags) | 74 | __field(unsigned long, flags) |
| 72 | ), | 75 | ), |
| 73 | 76 | ||
| @@ -78,16 +81,25 @@ DECLARE_EVENT_CLASS(writeback_dirty_inode_template, | |||
| 78 | strncpy(__entry->name, | 81 | strncpy(__entry->name, |
| 79 | bdi->dev ? dev_name(bdi->dev) : "(unknown)", 32); | 82 | bdi->dev ? dev_name(bdi->dev) : "(unknown)", 32); |
| 80 | __entry->ino = inode->i_ino; | 83 | __entry->ino = inode->i_ino; |
| 84 | __entry->state = inode->i_state; | ||
| 81 | __entry->flags = flags; | 85 | __entry->flags = flags; |
| 82 | ), | 86 | ), |
| 83 | 87 | ||
| 84 | TP_printk("bdi %s: ino=%lu flags=%s", | 88 | TP_printk("bdi %s: ino=%lu state=%s flags=%s", |
| 85 | __entry->name, | 89 | __entry->name, |
| 86 | __entry->ino, | 90 | __entry->ino, |
| 91 | show_inode_state(__entry->state), | ||
| 87 | show_inode_state(__entry->flags) | 92 | show_inode_state(__entry->flags) |
| 88 | ) | 93 | ) |
| 89 | ); | 94 | ); |
| 90 | 95 | ||
| 96 | DEFINE_EVENT(writeback_dirty_inode_template, writeback_mark_inode_dirty, | ||
| 97 | |||
| 98 | TP_PROTO(struct inode *inode, int flags), | ||
| 99 | |||
| 100 | TP_ARGS(inode, flags) | ||
| 101 | ); | ||
| 102 | |||
| 91 | DEFINE_EVENT(writeback_dirty_inode_template, writeback_dirty_inode_start, | 103 | DEFINE_EVENT(writeback_dirty_inode_template, writeback_dirty_inode_start, |
| 92 | 104 | ||
| 93 | TP_PROTO(struct inode *inode, int flags), | 105 | TP_PROTO(struct inode *inode, int flags), |
| @@ -596,6 +608,52 @@ DEFINE_EVENT(writeback_single_inode_template, writeback_single_inode, | |||
| 596 | TP_ARGS(inode, wbc, nr_to_write) | 608 | TP_ARGS(inode, wbc, nr_to_write) |
| 597 | ); | 609 | ); |
| 598 | 610 | ||
| 611 | DECLARE_EVENT_CLASS(writeback_lazytime_template, | ||
| 612 | TP_PROTO(struct inode *inode), | ||
| 613 | |||
| 614 | TP_ARGS(inode), | ||
| 615 | |||
| 616 | TP_STRUCT__entry( | ||
| 617 | __field( dev_t, dev ) | ||
| 618 | __field(unsigned long, ino ) | ||
| 619 | __field(unsigned long, state ) | ||
| 620 | __field( __u16, mode ) | ||
| 621 | __field(unsigned long, dirtied_when ) | ||
| 622 | ), | ||
| 623 | |||
| 624 | TP_fast_assign( | ||
| 625 | __entry->dev = inode->i_sb->s_dev; | ||
| 626 | __entry->ino = inode->i_ino; | ||
| 627 | __entry->state = inode->i_state; | ||
| 628 | __entry->mode = inode->i_mode; | ||
| 629 | __entry->dirtied_when = inode->dirtied_when; | ||
| 630 | ), | ||
| 631 | |||
| 632 | TP_printk("dev %d,%d ino %lu dirtied %lu state %s mode 0%o", | ||
| 633 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
| 634 | __entry->ino, __entry->dirtied_when, | ||
| 635 | show_inode_state(__entry->state), __entry->mode) | ||
| 636 | ); | ||
| 637 | |||
| 638 | DEFINE_EVENT(writeback_lazytime_template, writeback_lazytime, | ||
| 639 | TP_PROTO(struct inode *inode), | ||
| 640 | |||
| 641 | TP_ARGS(inode) | ||
| 642 | ); | ||
| 643 | |||
| 644 | DEFINE_EVENT(writeback_lazytime_template, writeback_lazytime_iput, | ||
| 645 | TP_PROTO(struct inode *inode), | ||
| 646 | |||
| 647 | TP_ARGS(inode) | ||
| 648 | ); | ||
| 649 | |||
| 650 | DEFINE_EVENT(writeback_lazytime_template, writeback_dirty_inode_enqueue, | ||
| 651 | |||
| 652 | TP_PROTO(struct inode *inode), | ||
| 653 | |||
| 654 | TP_ARGS(inode) | ||
| 655 | ); | ||
| 656 | |||
| 599 | #endif /* _TRACE_WRITEBACK_H */ | 657 | #endif /* _TRACE_WRITEBACK_H */ |
| 600 | 658 | ||
| 601 | /* This part must be outside protection */ | 659 | /* This part must be outside protection */ |
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild index 7b8141bf59a7..68ceb97c458c 100644 --- a/include/uapi/linux/Kbuild +++ b/include/uapi/linux/Kbuild | |||
| @@ -370,7 +370,6 @@ header-y += snmp.h | |||
| 370 | header-y += sock_diag.h | 370 | header-y += sock_diag.h |
| 371 | header-y += socket.h | 371 | header-y += socket.h |
| 372 | header-y += sockios.h | 372 | header-y += sockios.h |
| 373 | header-y += som.h | ||
| 374 | header-y += sonet.h | 373 | header-y += sonet.h |
| 375 | header-y += sonypi.h | 374 | header-y += sonypi.h |
| 376 | header-y += soundcard.h | 375 | header-y += soundcard.h |
diff --git a/include/uapi/linux/fou.h b/include/uapi/linux/fou.h index 8df06894da23..c303588bb767 100644 --- a/include/uapi/linux/fou.h +++ b/include/uapi/linux/fou.h | |||
| @@ -14,6 +14,7 @@ enum { | |||
| 14 | FOU_ATTR_AF, /* u8 */ | 14 | FOU_ATTR_AF, /* u8 */ |
| 15 | FOU_ATTR_IPPROTO, /* u8 */ | 15 | FOU_ATTR_IPPROTO, /* u8 */ |
| 16 | FOU_ATTR_TYPE, /* u8 */ | 16 | FOU_ATTR_TYPE, /* u8 */ |
| 17 | FOU_ATTR_REMCSUM_NOPARTIAL, /* flag */ | ||
| 17 | 18 | ||
| 18 | __FOU_ATTR_MAX, | 19 | __FOU_ATTR_MAX, |
| 19 | }; | 20 | }; |
diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h index 3735fa0a6784..9b964a5920af 100644 --- a/include/uapi/linux/fs.h +++ b/include/uapi/linux/fs.h | |||
| @@ -90,6 +90,7 @@ struct inodes_stat_t { | |||
| 90 | #define MS_KERNMOUNT (1<<22) /* this is a kern_mount call */ | 90 | #define MS_KERNMOUNT (1<<22) /* this is a kern_mount call */ |
| 91 | #define MS_I_VERSION (1<<23) /* Update inode I_version field */ | 91 | #define MS_I_VERSION (1<<23) /* Update inode I_version field */ |
| 92 | #define MS_STRICTATIME (1<<24) /* Always perform atime updates */ | 92 | #define MS_STRICTATIME (1<<24) /* Always perform atime updates */ |
| 93 | #define MS_LAZYTIME (1<<25) /* Update the on-disk [acm]times lazily */ | ||
| 93 | 94 | ||
| 94 | /* These sb flags are internal to the kernel */ | 95 | /* These sb flags are internal to the kernel */ |
| 95 | #define MS_NOSEC (1<<28) | 96 | #define MS_NOSEC (1<<28) |
| @@ -100,7 +101,8 @@ struct inodes_stat_t { | |||
| 100 | /* | 101 | /* |
| 101 | * Superblock flags that can be altered by MS_REMOUNT | 102 | * Superblock flags that can be altered by MS_REMOUNT |
| 102 | */ | 103 | */ |
| 103 | #define MS_RMT_MASK (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_I_VERSION) | 104 | #define MS_RMT_MASK (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_I_VERSION|\ |
| 105 | MS_LAZYTIME) | ||
| 104 | 106 | ||
| 105 | /* | 107 | /* |
| 106 | * Old magic mount flag and mask | 108 | * Old magic mount flag and mask |
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index 0deee3eeddbf..dfd0bb22e554 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h | |||
| @@ -374,6 +374,7 @@ enum { | |||
| 374 | IFLA_VXLAN_REMCSUM_TX, | 374 | IFLA_VXLAN_REMCSUM_TX, |
| 375 | IFLA_VXLAN_REMCSUM_RX, | 375 | IFLA_VXLAN_REMCSUM_RX, |
| 376 | IFLA_VXLAN_GBP, | 376 | IFLA_VXLAN_GBP, |
| 377 | IFLA_VXLAN_REMCSUM_NOPARTIAL, | ||
| 377 | __IFLA_VXLAN_MAX | 378 | __IFLA_VXLAN_MAX |
| 378 | }; | 379 | }; |
| 379 | #define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) | 380 | #define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) |
diff --git a/include/uapi/linux/kexec.h b/include/uapi/linux/kexec.h index 6925f5b42f89..99048e501b88 100644 --- a/include/uapi/linux/kexec.h +++ b/include/uapi/linux/kexec.h | |||
| @@ -55,12 +55,6 @@ struct kexec_segment { | |||
| 55 | size_t memsz; | 55 | size_t memsz; |
| 56 | }; | 56 | }; |
| 57 | 57 | ||
| 58 | /* Load a new kernel image as described by the kexec_segment array | ||
| 59 | * consisting of passed number of segments at the entry-point address. | ||
| 60 | * The flags allow different useage types. | ||
| 61 | */ | ||
| 62 | extern int kexec_load(void *, size_t, struct kexec_segment *, | ||
| 63 | unsigned long int); | ||
| 64 | #endif /* __KERNEL__ */ | 58 | #endif /* __KERNEL__ */ |
| 65 | 59 | ||
| 66 | #endif /* _UAPILINUX_KEXEC_H */ | 60 | #endif /* _UAPILINUX_KEXEC_H */ |
diff --git a/include/uapi/linux/som.h b/include/uapi/linux/som.h deleted file mode 100644 index 166594e4e7be..000000000000 --- a/include/uapi/linux/som.h +++ /dev/null | |||
| @@ -1,154 +0,0 @@ | |||
| 1 | #ifndef _LINUX_SOM_H | ||
| 2 | #define _LINUX_SOM_H | ||
| 3 | |||
| 4 | /* File format definition for SOM executables / shared libraries */ | ||
| 5 | |||
| 6 | /* we need struct timespec */ | ||
| 7 | #include <linux/time.h> | ||
| 8 | |||
| 9 | #define SOM_PAGESIZE 4096 | ||
| 10 | |||
| 11 | /* this is the SOM header */ | ||
| 12 | struct som_hdr { | ||
| 13 | short system_id; /* magic number - system */ | ||
| 14 | short a_magic; /* magic number - file type */ | ||
| 15 | unsigned int version_id; /* versiod ID: YYMMDDHH */ | ||
| 16 | struct timespec file_time; /* system clock */ | ||
| 17 | unsigned int entry_space; /* space for entry point */ | ||
| 18 | unsigned int entry_subspace; /* subspace for entry point */ | ||
| 19 | unsigned int entry_offset; /* offset of entry point */ | ||
| 20 | unsigned int aux_header_location; /* auxiliary header location */ | ||
| 21 | unsigned int aux_header_size; /* auxiliary header size */ | ||
| 22 | unsigned int som_length; /* length of entire SOM */ | ||
| 23 | unsigned int presumed_dp; /* compiler's DP value */ | ||
| 24 | unsigned int space_location; /* space dictionary location */ | ||
| 25 | unsigned int space_total; /* number of space entries */ | ||
| 26 | unsigned int subspace_location; /* subspace entries location */ | ||
| 27 | unsigned int subspace_total; /* number of subspace entries */ | ||
| 28 | unsigned int loader_fixup_location; /* MPE/iX loader fixup */ | ||
| 29 | unsigned int loader_fixup_total; /* number of fixup records */ | ||
| 30 | unsigned int space_strings_location; /* (sub)space names */ | ||
| 31 | unsigned int space_strings_size; /* size of strings area */ | ||
| 32 | unsigned int init_array_location; /* reserved */ | ||
| 33 | unsigned int init_array_total; /* reserved */ | ||
| 34 | unsigned int compiler_location; /* module dictionary */ | ||
| 35 | unsigned int compiler_total; /* number of modules */ | ||
| 36 | unsigned int symbol_location; /* symbol dictionary */ | ||
| 37 | unsigned int symbol_total; /* number of symbols */ | ||
| 38 | unsigned int fixup_request_location; /* fixup requests */ | ||
| 39 | unsigned int fixup_request_total; /* number of fixup requests */ | ||
| 40 | unsigned int symbol_strings_location;/* module & symbol names area */ | ||
| 41 | unsigned int symbol_strings_size; /* size of strings area */ | ||
| 42 | unsigned int unloadable_sp_location; /* unloadable spaces location */ | ||
| 43 | unsigned int unloadable_sp_size; /* size of data */ | ||
| 44 | unsigned int checksum; | ||
| 45 | }; | ||
| 46 | |||
| 47 | /* values for system_id */ | ||
| 48 | |||
| 49 | #define SOM_SID_PARISC_1_0 0x020b | ||
| 50 | #define SOM_SID_PARISC_1_1 0x0210 | ||
| 51 | #define SOM_SID_PARISC_2_0 0x0214 | ||
| 52 | |||
| 53 | /* values for a_magic */ | ||
| 54 | |||
| 55 | #define SOM_LIB_EXEC 0x0104 | ||
| 56 | #define SOM_RELOCATABLE 0x0106 | ||
| 57 | #define SOM_EXEC_NONSHARE 0x0107 | ||
| 58 | #define SOM_EXEC_SHARE 0x0108 | ||
| 59 | #define SOM_EXEC_DEMAND 0x010B | ||
| 60 | #define SOM_LIB_DYN 0x010D | ||
| 61 | #define SOM_LIB_SHARE 0x010E | ||
| 62 | #define SOM_LIB_RELOC 0x0619 | ||
| 63 | |||
| 64 | /* values for version_id. Decimal not hex, yes. Grr. */ | ||
| 65 | |||
| 66 | #define SOM_ID_OLD 85082112 | ||
| 67 | #define SOM_ID_NEW 87102412 | ||
| 68 | |||
| 69 | struct aux_id { | ||
| 70 | unsigned int mandatory :1; /* the linker must understand this */ | ||
| 71 | unsigned int copy :1; /* Must be copied by the linker */ | ||
| 72 | unsigned int append :1; /* Must be merged by the linker */ | ||
| 73 | unsigned int ignore :1; /* Discard section if unknown */ | ||
| 74 | unsigned int reserved :12; | ||
| 75 | unsigned int type :16; /* Header type */ | ||
| 76 | unsigned int length; /* length of _following_ data */ | ||
| 77 | }; | ||
| 78 | |||
| 79 | /* The Exec Auxiliary Header. Called The HP-UX Header within HP apparently. */ | ||
| 80 | struct som_exec_auxhdr { | ||
| 81 | struct aux_id som_auxhdr; | ||
| 82 | int exec_tsize; /* Text size in bytes */ | ||
| 83 | int exec_tmem; /* Address to load text at */ | ||
| 84 | int exec_tfile; /* Location of text in file */ | ||
| 85 | int exec_dsize; /* Data size in bytes */ | ||
| 86 | int exec_dmem; /* Address to load data at */ | ||
| 87 | int exec_dfile; /* Location of data in file */ | ||
| 88 | int exec_bsize; /* Uninitialised data (bss) */ | ||
| 89 | int exec_entry; /* Address to start executing */ | ||
| 90 | int exec_flags; /* loader flags */ | ||
| 91 | int exec_bfill; /* initialisation value for bss */ | ||
| 92 | }; | ||
| 93 | |||
| 94 | /* Oh, the things people do to avoid casts. Shame it'll break with gcc's | ||
| 95 | * new aliasing rules really. | ||
| 96 | */ | ||
| 97 | union name_pt { | ||
| 98 | char * n_name; | ||
| 99 | unsigned int n_strx; | ||
| 100 | }; | ||
| 101 | |||
| 102 | /* The Space Dictionary */ | ||
| 103 | struct space_dictionary_record { | ||
| 104 | union name_pt name; /* index to subspace name */ | ||
| 105 | unsigned int is_loadable :1; /* loadable */ | ||
| 106 | unsigned int is_defined :1; /* defined within file */ | ||
| 107 | unsigned int is_private :1; /* not sharable */ | ||
| 108 | unsigned int has_intermediate_code :1; /* contains intermediate code */ | ||
| 109 | unsigned int is_tspecific :1; /* thread specific */ | ||
| 110 | unsigned int reserved :11; /* for future expansion */ | ||
| 111 | unsigned int sort_key :8; /* for linker */ | ||
| 112 | unsigned int reserved2 :8; /* for future expansion */ | ||
| 113 | |||
| 114 | int space_number; /* index */ | ||
| 115 | int subspace_index; /* index into subspace dict */ | ||
| 116 | unsigned int subspace_quantity; /* number of subspaces */ | ||
| 117 | int loader_fix_index; /* for loader */ | ||
| 118 | unsigned int loader_fix_quantity; /* for loader */ | ||
| 119 | int init_pointer_index; /* data pointer array index */ | ||
| 120 | unsigned int init_pointer_quantity; /* number of data pointers */ | ||
| 121 | }; | ||
| 122 | |||
| 123 | /* The Subspace Dictionary */ | ||
| 124 | struct subspace_dictionary_record { | ||
| 125 | int space_index; | ||
| 126 | unsigned int access_control_bits :7; | ||
| 127 | unsigned int memory_resident :1; | ||
| 128 | unsigned int dup_common :1; | ||
| 129 | unsigned int is_common :1; | ||
| 130 | unsigned int quadrant :2; | ||
| 131 | unsigned int initially_frozen :1; | ||
| 132 | unsigned int is_first :1; | ||
| 133 | unsigned int code_only :1; | ||
| 134 | unsigned int sort_key :8; | ||
| 135 | unsigned int replicate_init :1; | ||
| 136 | unsigned int continuation :1; | ||
| 137 | unsigned int is_tspecific :1; | ||
| 138 | unsigned int is_comdat :1; | ||
| 139 | unsigned int reserved :4; | ||
| 140 | |||
| 141 | int file_loc_init_value; | ||
| 142 | unsigned int initialization_length; | ||
| 143 | unsigned int subspace_start; | ||
| 144 | unsigned int subspace_length; | ||
| 145 | |||
| 146 | unsigned int reserved2 :5; | ||
| 147 | unsigned int alignment :27; | ||
| 148 | |||
| 149 | union name_pt name; | ||
| 150 | int fixup_request_index; | ||
| 151 | unsigned int fixup_request_quantity; | ||
| 152 | }; | ||
| 153 | |||
| 154 | #endif /* _LINUX_SOM_H */ | ||
| @@ -1941,7 +1941,7 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, | |||
| 1941 | queue.sleeper = current; | 1941 | queue.sleeper = current; |
| 1942 | 1942 | ||
| 1943 | sleep_again: | 1943 | sleep_again: |
| 1944 | current->state = TASK_INTERRUPTIBLE; | 1944 | __set_current_state(TASK_INTERRUPTIBLE); |
| 1945 | sem_unlock(sma, locknum); | 1945 | sem_unlock(sma, locknum); |
| 1946 | rcu_read_unlock(); | 1946 | rcu_read_unlock(); |
| 1947 | 1947 | ||
diff --git a/kernel/acct.c b/kernel/acct.c index 33738ef972f3..e6c10d1a4058 100644 --- a/kernel/acct.c +++ b/kernel/acct.c | |||
| @@ -76,10 +76,11 @@ int acct_parm[3] = {4, 2, 30}; | |||
| 76 | /* | 76 | /* |
| 77 | * External references and all of the globals. | 77 | * External references and all of the globals. |
| 78 | */ | 78 | */ |
| 79 | static void do_acct_process(struct bsd_acct_struct *acct); | ||
| 80 | 79 | ||
| 81 | struct bsd_acct_struct { | 80 | struct bsd_acct_struct { |
| 82 | struct fs_pin pin; | 81 | struct fs_pin pin; |
| 82 | atomic_long_t count; | ||
| 83 | struct rcu_head rcu; | ||
| 83 | struct mutex lock; | 84 | struct mutex lock; |
| 84 | int active; | 85 | int active; |
| 85 | unsigned long needcheck; | 86 | unsigned long needcheck; |
| @@ -89,6 +90,8 @@ struct bsd_acct_struct { | |||
| 89 | struct completion done; | 90 | struct completion done; |
| 90 | }; | 91 | }; |
| 91 | 92 | ||
| 93 | static void do_acct_process(struct bsd_acct_struct *acct); | ||
| 94 | |||
| 92 | /* | 95 | /* |
| 93 | * Check the amount of free space and suspend/resume accordingly. | 96 | * Check the amount of free space and suspend/resume accordingly. |
| 94 | */ | 97 | */ |
| @@ -124,32 +127,56 @@ out: | |||
| 124 | return acct->active; | 127 | return acct->active; |
| 125 | } | 128 | } |
| 126 | 129 | ||
| 130 | static void acct_put(struct bsd_acct_struct *p) | ||
| 131 | { | ||
| 132 | if (atomic_long_dec_and_test(&p->count)) | ||
| 133 | kfree_rcu(p, rcu); | ||
| 134 | } | ||
| 135 | |||
| 136 | static inline struct bsd_acct_struct *to_acct(struct fs_pin *p) | ||
| 137 | { | ||
| 138 | return p ? container_of(p, struct bsd_acct_struct, pin) : NULL; | ||
| 139 | } | ||
| 140 | |||
| 127 | static struct bsd_acct_struct *acct_get(struct pid_namespace *ns) | 141 | static struct bsd_acct_struct *acct_get(struct pid_namespace *ns) |
| 128 | { | 142 | { |
| 129 | struct bsd_acct_struct *res; | 143 | struct bsd_acct_struct *res; |
| 130 | again: | 144 | again: |
| 131 | smp_rmb(); | 145 | smp_rmb(); |
| 132 | rcu_read_lock(); | 146 | rcu_read_lock(); |
| 133 | res = ACCESS_ONCE(ns->bacct); | 147 | res = to_acct(ACCESS_ONCE(ns->bacct)); |
| 134 | if (!res) { | 148 | if (!res) { |
| 135 | rcu_read_unlock(); | 149 | rcu_read_unlock(); |
| 136 | return NULL; | 150 | return NULL; |
| 137 | } | 151 | } |
| 138 | if (!atomic_long_inc_not_zero(&res->pin.count)) { | 152 | if (!atomic_long_inc_not_zero(&res->count)) { |
| 139 | rcu_read_unlock(); | 153 | rcu_read_unlock(); |
| 140 | cpu_relax(); | 154 | cpu_relax(); |
| 141 | goto again; | 155 | goto again; |
| 142 | } | 156 | } |
| 143 | rcu_read_unlock(); | 157 | rcu_read_unlock(); |
| 144 | mutex_lock(&res->lock); | 158 | mutex_lock(&res->lock); |
| 145 | if (!res->ns) { | 159 | if (res != to_acct(ACCESS_ONCE(ns->bacct))) { |
| 146 | mutex_unlock(&res->lock); | 160 | mutex_unlock(&res->lock); |
| 147 | pin_put(&res->pin); | 161 | acct_put(res); |
| 148 | goto again; | 162 | goto again; |
| 149 | } | 163 | } |
| 150 | return res; | 164 | return res; |
| 151 | } | 165 | } |
| 152 | 166 | ||
| 167 | static void acct_pin_kill(struct fs_pin *pin) | ||
| 168 | { | ||
| 169 | struct bsd_acct_struct *acct = to_acct(pin); | ||
| 170 | mutex_lock(&acct->lock); | ||
| 171 | do_acct_process(acct); | ||
| 172 | schedule_work(&acct->work); | ||
| 173 | wait_for_completion(&acct->done); | ||
| 174 | cmpxchg(&acct->ns->bacct, pin, NULL); | ||
| 175 | mutex_unlock(&acct->lock); | ||
| 176 | pin_remove(pin); | ||
| 177 | acct_put(acct); | ||
| 178 | } | ||
| 179 | |||
| 153 | static void close_work(struct work_struct *work) | 180 | static void close_work(struct work_struct *work) |
| 154 | { | 181 | { |
| 155 | struct bsd_acct_struct *acct = container_of(work, struct bsd_acct_struct, work); | 182 | struct bsd_acct_struct *acct = container_of(work, struct bsd_acct_struct, work); |
| @@ -160,44 +187,13 @@ static void close_work(struct work_struct *work) | |||
| 160 | complete(&acct->done); | 187 | complete(&acct->done); |
| 161 | } | 188 | } |
| 162 | 189 | ||
| 163 | static void acct_kill(struct bsd_acct_struct *acct, | ||
| 164 | struct bsd_acct_struct *new) | ||
| 165 | { | ||
| 166 | if (acct) { | ||
| 167 | struct pid_namespace *ns = acct->ns; | ||
| 168 | do_acct_process(acct); | ||
| 169 | INIT_WORK(&acct->work, close_work); | ||
| 170 | init_completion(&acct->done); | ||
| 171 | schedule_work(&acct->work); | ||
| 172 | wait_for_completion(&acct->done); | ||
| 173 | pin_remove(&acct->pin); | ||
| 174 | ns->bacct = new; | ||
| 175 | acct->ns = NULL; | ||
| 176 | atomic_long_dec(&acct->pin.count); | ||
| 177 | mutex_unlock(&acct->lock); | ||
| 178 | pin_put(&acct->pin); | ||
| 179 | } | ||
| 180 | } | ||
| 181 | |||
| 182 | static void acct_pin_kill(struct fs_pin *pin) | ||
| 183 | { | ||
| 184 | struct bsd_acct_struct *acct; | ||
| 185 | acct = container_of(pin, struct bsd_acct_struct, pin); | ||
| 186 | mutex_lock(&acct->lock); | ||
| 187 | if (!acct->ns) { | ||
| 188 | mutex_unlock(&acct->lock); | ||
| 189 | pin_put(pin); | ||
| 190 | acct = NULL; | ||
| 191 | } | ||
| 192 | acct_kill(acct, NULL); | ||
| 193 | } | ||
| 194 | |||
| 195 | static int acct_on(struct filename *pathname) | 190 | static int acct_on(struct filename *pathname) |
| 196 | { | 191 | { |
| 197 | struct file *file; | 192 | struct file *file; |
| 198 | struct vfsmount *mnt, *internal; | 193 | struct vfsmount *mnt, *internal; |
| 199 | struct pid_namespace *ns = task_active_pid_ns(current); | 194 | struct pid_namespace *ns = task_active_pid_ns(current); |
| 200 | struct bsd_acct_struct *acct, *old; | 195 | struct bsd_acct_struct *acct; |
| 196 | struct fs_pin *old; | ||
| 201 | int err; | 197 | int err; |
| 202 | 198 | ||
| 203 | acct = kzalloc(sizeof(struct bsd_acct_struct), GFP_KERNEL); | 199 | acct = kzalloc(sizeof(struct bsd_acct_struct), GFP_KERNEL); |
| @@ -238,21 +234,21 @@ static int acct_on(struct filename *pathname) | |||
| 238 | mnt = file->f_path.mnt; | 234 | mnt = file->f_path.mnt; |
| 239 | file->f_path.mnt = internal; | 235 | file->f_path.mnt = internal; |
| 240 | 236 | ||
| 241 | atomic_long_set(&acct->pin.count, 1); | 237 | atomic_long_set(&acct->count, 1); |
| 242 | acct->pin.kill = acct_pin_kill; | 238 | init_fs_pin(&acct->pin, acct_pin_kill); |
| 243 | acct->file = file; | 239 | acct->file = file; |
| 244 | acct->needcheck = jiffies; | 240 | acct->needcheck = jiffies; |
| 245 | acct->ns = ns; | 241 | acct->ns = ns; |
| 246 | mutex_init(&acct->lock); | 242 | mutex_init(&acct->lock); |
| 243 | INIT_WORK(&acct->work, close_work); | ||
| 244 | init_completion(&acct->done); | ||
| 247 | mutex_lock_nested(&acct->lock, 1); /* nobody has seen it yet */ | 245 | mutex_lock_nested(&acct->lock, 1); /* nobody has seen it yet */ |
| 248 | pin_insert(&acct->pin, mnt); | 246 | pin_insert(&acct->pin, mnt); |
| 249 | 247 | ||
| 250 | old = acct_get(ns); | 248 | rcu_read_lock(); |
| 251 | if (old) | 249 | old = xchg(&ns->bacct, &acct->pin); |
| 252 | acct_kill(old, acct); | ||
| 253 | else | ||
| 254 | ns->bacct = acct; | ||
| 255 | mutex_unlock(&acct->lock); | 250 | mutex_unlock(&acct->lock); |
| 251 | pin_kill(old); | ||
| 256 | mnt_drop_write(mnt); | 252 | mnt_drop_write(mnt); |
| 257 | mntput(mnt); | 253 | mntput(mnt); |
| 258 | return 0; | 254 | return 0; |
| @@ -288,7 +284,8 @@ SYSCALL_DEFINE1(acct, const char __user *, name) | |||
| 288 | mutex_unlock(&acct_on_mutex); | 284 | mutex_unlock(&acct_on_mutex); |
| 289 | putname(tmp); | 285 | putname(tmp); |
| 290 | } else { | 286 | } else { |
| 291 | acct_kill(acct_get(task_active_pid_ns(current)), NULL); | 287 | rcu_read_lock(); |
| 288 | pin_kill(task_active_pid_ns(current)->bacct); | ||
| 292 | } | 289 | } |
| 293 | 290 | ||
| 294 | return error; | 291 | return error; |
| @@ -296,7 +293,8 @@ SYSCALL_DEFINE1(acct, const char __user *, name) | |||
| 296 | 293 | ||
| 297 | void acct_exit_ns(struct pid_namespace *ns) | 294 | void acct_exit_ns(struct pid_namespace *ns) |
| 298 | { | 295 | { |
| 299 | acct_kill(acct_get(ns), NULL); | 296 | rcu_read_lock(); |
| 297 | pin_kill(ns->bacct); | ||
| 300 | } | 298 | } |
| 301 | 299 | ||
| 302 | /* | 300 | /* |
| @@ -576,7 +574,7 @@ static void slow_acct_process(struct pid_namespace *ns) | |||
| 576 | if (acct) { | 574 | if (acct) { |
| 577 | do_acct_process(acct); | 575 | do_acct_process(acct); |
| 578 | mutex_unlock(&acct->lock); | 576 | mutex_unlock(&acct->lock); |
| 579 | pin_put(&acct->pin); | 577 | acct_put(acct); |
| 580 | } | 578 | } |
| 581 | } | 579 | } |
| 582 | } | 580 | } |
diff --git a/kernel/audit.h b/kernel/audit.h index 3cdffad5a1d9..1caa0d345d90 100644 --- a/kernel/audit.h +++ b/kernel/audit.h | |||
| @@ -24,12 +24,6 @@ | |||
| 24 | #include <linux/skbuff.h> | 24 | #include <linux/skbuff.h> |
| 25 | #include <uapi/linux/mqueue.h> | 25 | #include <uapi/linux/mqueue.h> |
| 26 | 26 | ||
| 27 | /* 0 = no checking | ||
| 28 | 1 = put_count checking | ||
| 29 | 2 = verbose put_count checking | ||
| 30 | */ | ||
| 31 | #define AUDIT_DEBUG 0 | ||
| 32 | |||
| 33 | /* AUDIT_NAMES is the number of slots we reserve in the audit_context | 27 | /* AUDIT_NAMES is the number of slots we reserve in the audit_context |
| 34 | * for saving names from getname(). If we get more names we will allocate | 28 | * for saving names from getname(). If we get more names we will allocate |
| 35 | * a name dynamically and also add those to the list anchored by names_list. */ | 29 | * a name dynamically and also add those to the list anchored by names_list. */ |
| @@ -74,9 +68,8 @@ struct audit_cap_data { | |||
| 74 | }; | 68 | }; |
| 75 | }; | 69 | }; |
| 76 | 70 | ||
| 77 | /* When fs/namei.c:getname() is called, we store the pointer in name and | 71 | /* When fs/namei.c:getname() is called, we store the pointer in name and bump |
| 78 | * we don't let putname() free it (instead we free all of the saved | 72 | * the refcnt in the associated filename struct. |
| 79 | * pointers at syscall exit time). | ||
| 80 | * | 73 | * |
| 81 | * Further, in fs/namei.c:path_lookup() we store the inode and device. | 74 | * Further, in fs/namei.c:path_lookup() we store the inode and device. |
| 82 | */ | 75 | */ |
| @@ -86,7 +79,6 @@ struct audit_names { | |||
| 86 | struct filename *name; | 79 | struct filename *name; |
| 87 | int name_len; /* number of chars to log */ | 80 | int name_len; /* number of chars to log */ |
| 88 | bool hidden; /* don't log this record */ | 81 | bool hidden; /* don't log this record */ |
| 89 | bool name_put; /* call __putname()? */ | ||
| 90 | 82 | ||
| 91 | unsigned long ino; | 83 | unsigned long ino; |
| 92 | dev_t dev; | 84 | dev_t dev; |
| @@ -208,11 +200,6 @@ struct audit_context { | |||
| 208 | }; | 200 | }; |
| 209 | int fds[2]; | 201 | int fds[2]; |
| 210 | struct audit_proctitle proctitle; | 202 | struct audit_proctitle proctitle; |
| 211 | |||
| 212 | #if AUDIT_DEBUG | ||
| 213 | int put_count; | ||
| 214 | int ino_count; | ||
| 215 | #endif | ||
| 216 | }; | 203 | }; |
| 217 | 204 | ||
| 218 | extern u32 audit_ever_enabled; | 205 | extern u32 audit_ever_enabled; |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 072566dd0caf..dc4ae70a7413 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
| @@ -866,33 +866,10 @@ static inline void audit_free_names(struct audit_context *context) | |||
| 866 | { | 866 | { |
| 867 | struct audit_names *n, *next; | 867 | struct audit_names *n, *next; |
| 868 | 868 | ||
| 869 | #if AUDIT_DEBUG == 2 | ||
| 870 | if (context->put_count + context->ino_count != context->name_count) { | ||
| 871 | int i = 0; | ||
| 872 | |||
| 873 | pr_err("%s:%d(:%d): major=%d in_syscall=%d" | ||
| 874 | " name_count=%d put_count=%d ino_count=%d" | ||
| 875 | " [NOT freeing]\n", __FILE__, __LINE__, | ||
| 876 | context->serial, context->major, context->in_syscall, | ||
| 877 | context->name_count, context->put_count, | ||
| 878 | context->ino_count); | ||
| 879 | list_for_each_entry(n, &context->names_list, list) { | ||
| 880 | pr_err("names[%d] = %p = %s\n", i++, n->name, | ||
| 881 | n->name->name ?: "(null)"); | ||
| 882 | } | ||
| 883 | dump_stack(); | ||
| 884 | return; | ||
| 885 | } | ||
| 886 | #endif | ||
| 887 | #if AUDIT_DEBUG | ||
| 888 | context->put_count = 0; | ||
| 889 | context->ino_count = 0; | ||
| 890 | #endif | ||
| 891 | |||
| 892 | list_for_each_entry_safe(n, next, &context->names_list, list) { | 869 | list_for_each_entry_safe(n, next, &context->names_list, list) { |
| 893 | list_del(&n->list); | 870 | list_del(&n->list); |
| 894 | if (n->name && n->name_put) | 871 | if (n->name) |
| 895 | final_putname(n->name); | 872 | putname(n->name); |
| 896 | if (n->should_free) | 873 | if (n->should_free) |
| 897 | kfree(n); | 874 | kfree(n); |
| 898 | } | 875 | } |
| @@ -1711,9 +1688,6 @@ static struct audit_names *audit_alloc_name(struct audit_context *context, | |||
| 1711 | list_add_tail(&aname->list, &context->names_list); | 1688 | list_add_tail(&aname->list, &context->names_list); |
| 1712 | 1689 | ||
| 1713 | context->name_count++; | 1690 | context->name_count++; |
| 1714 | #if AUDIT_DEBUG | ||
| 1715 | context->ino_count++; | ||
| 1716 | #endif | ||
| 1717 | return aname; | 1691 | return aname; |
| 1718 | } | 1692 | } |
| 1719 | 1693 | ||
| @@ -1734,8 +1708,10 @@ __audit_reusename(const __user char *uptr) | |||
| 1734 | list_for_each_entry(n, &context->names_list, list) { | 1708 | list_for_each_entry(n, &context->names_list, list) { |
| 1735 | if (!n->name) | 1709 | if (!n->name) |
| 1736 | continue; | 1710 | continue; |
| 1737 | if (n->name->uptr == uptr) | 1711 | if (n->name->uptr == uptr) { |
| 1712 | n->name->refcnt++; | ||
| 1738 | return n->name; | 1713 | return n->name; |
| 1714 | } | ||
| 1739 | } | 1715 | } |
| 1740 | return NULL; | 1716 | return NULL; |
| 1741 | } | 1717 | } |
| @@ -1752,19 +1728,8 @@ void __audit_getname(struct filename *name) | |||
| 1752 | struct audit_context *context = current->audit_context; | 1728 | struct audit_context *context = current->audit_context; |
| 1753 | struct audit_names *n; | 1729 | struct audit_names *n; |
| 1754 | 1730 | ||
| 1755 | if (!context->in_syscall) { | 1731 | if (!context->in_syscall) |
| 1756 | #if AUDIT_DEBUG == 2 | ||
| 1757 | pr_err("%s:%d(:%d): ignoring getname(%p)\n", | ||
| 1758 | __FILE__, __LINE__, context->serial, name); | ||
| 1759 | dump_stack(); | ||
| 1760 | #endif | ||
| 1761 | return; | 1732 | return; |
| 1762 | } | ||
| 1763 | |||
| 1764 | #if AUDIT_DEBUG | ||
| 1765 | /* The filename _must_ have a populated ->name */ | ||
| 1766 | BUG_ON(!name->name); | ||
| 1767 | #endif | ||
| 1768 | 1733 | ||
| 1769 | n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN); | 1734 | n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN); |
| 1770 | if (!n) | 1735 | if (!n) |
| @@ -1772,56 +1737,13 @@ void __audit_getname(struct filename *name) | |||
| 1772 | 1737 | ||
| 1773 | n->name = name; | 1738 | n->name = name; |
| 1774 | n->name_len = AUDIT_NAME_FULL; | 1739 | n->name_len = AUDIT_NAME_FULL; |
| 1775 | n->name_put = true; | ||
| 1776 | name->aname = n; | 1740 | name->aname = n; |
| 1741 | name->refcnt++; | ||
| 1777 | 1742 | ||
| 1778 | if (!context->pwd.dentry) | 1743 | if (!context->pwd.dentry) |
| 1779 | get_fs_pwd(current->fs, &context->pwd); | 1744 | get_fs_pwd(current->fs, &context->pwd); |
| 1780 | } | 1745 | } |
| 1781 | 1746 | ||
| 1782 | /* audit_putname - intercept a putname request | ||
| 1783 | * @name: name to intercept and delay for putname | ||
| 1784 | * | ||
| 1785 | * If we have stored the name from getname in the audit context, | ||
| 1786 | * then we delay the putname until syscall exit. | ||
| 1787 | * Called from include/linux/fs.h:putname(). | ||
| 1788 | */ | ||
| 1789 | void audit_putname(struct filename *name) | ||
| 1790 | { | ||
| 1791 | struct audit_context *context = current->audit_context; | ||
| 1792 | |||
| 1793 | BUG_ON(!context); | ||
| 1794 | if (!name->aname || !context->in_syscall) { | ||
| 1795 | #if AUDIT_DEBUG == 2 | ||
| 1796 | pr_err("%s:%d(:%d): final_putname(%p)\n", | ||
| 1797 | __FILE__, __LINE__, context->serial, name); | ||
| 1798 | if (context->name_count) { | ||
| 1799 | struct audit_names *n; | ||
| 1800 | int i = 0; | ||
| 1801 | |||
| 1802 | list_for_each_entry(n, &context->names_list, list) | ||
| 1803 | pr_err("name[%d] = %p = %s\n", i++, n->name, | ||
| 1804 | n->name->name ?: "(null)"); | ||
| 1805 | } | ||
| 1806 | #endif | ||
| 1807 | final_putname(name); | ||
| 1808 | } | ||
| 1809 | #if AUDIT_DEBUG | ||
| 1810 | else { | ||
| 1811 | ++context->put_count; | ||
| 1812 | if (context->put_count > context->name_count) { | ||
| 1813 | pr_err("%s:%d(:%d): major=%d in_syscall=%d putname(%p)" | ||
| 1814 | " name_count=%d put_count=%d\n", | ||
| 1815 | __FILE__, __LINE__, | ||
| 1816 | context->serial, context->major, | ||
| 1817 | context->in_syscall, name->name, | ||
| 1818 | context->name_count, context->put_count); | ||
| 1819 | dump_stack(); | ||
| 1820 | } | ||
| 1821 | } | ||
| 1822 | #endif | ||
| 1823 | } | ||
| 1824 | |||
| 1825 | /** | 1747 | /** |
| 1826 | * __audit_inode - store the inode and device from a lookup | 1748 | * __audit_inode - store the inode and device from a lookup |
| 1827 | * @name: name being audited | 1749 | * @name: name being audited |
| @@ -1842,10 +1764,6 @@ void __audit_inode(struct filename *name, const struct dentry *dentry, | |||
| 1842 | if (!name) | 1764 | if (!name) |
| 1843 | goto out_alloc; | 1765 | goto out_alloc; |
| 1844 | 1766 | ||
| 1845 | #if AUDIT_DEBUG | ||
| 1846 | /* The struct filename _must_ have a populated ->name */ | ||
| 1847 | BUG_ON(!name->name); | ||
| 1848 | #endif | ||
| 1849 | /* | 1767 | /* |
| 1850 | * If we have a pointer to an audit_names entry already, then we can | 1768 | * If we have a pointer to an audit_names entry already, then we can |
| 1851 | * just use it directly if the type is correct. | 1769 | * just use it directly if the type is correct. |
| @@ -1863,7 +1781,17 @@ void __audit_inode(struct filename *name, const struct dentry *dentry, | |||
| 1863 | } | 1781 | } |
| 1864 | 1782 | ||
| 1865 | list_for_each_entry_reverse(n, &context->names_list, list) { | 1783 | list_for_each_entry_reverse(n, &context->names_list, list) { |
| 1866 | if (!n->name || strcmp(n->name->name, name->name)) | 1784 | if (n->ino) { |
| 1785 | /* valid inode number, use that for the comparison */ | ||
| 1786 | if (n->ino != inode->i_ino || | ||
| 1787 | n->dev != inode->i_sb->s_dev) | ||
| 1788 | continue; | ||
| 1789 | } else if (n->name) { | ||
| 1790 | /* inode number has not been set, check the name */ | ||
| 1791 | if (strcmp(n->name->name, name->name)) | ||
| 1792 | continue; | ||
| 1793 | } else | ||
| 1794 | /* no inode and no name (?!) ... this is odd ... */ | ||
| 1867 | continue; | 1795 | continue; |
| 1868 | 1796 | ||
| 1869 | /* match the correct record type */ | 1797 | /* match the correct record type */ |
| @@ -1882,44 +1810,11 @@ out_alloc: | |||
| 1882 | n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN); | 1810 | n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN); |
| 1883 | if (!n) | 1811 | if (!n) |
| 1884 | return; | 1812 | return; |
| 1885 | /* unfortunately, while we may have a path name to record with the | ||
| 1886 | * inode, we can't always rely on the string lasting until the end of | ||
| 1887 | * the syscall so we need to create our own copy, it may fail due to | ||
| 1888 | * memory allocation issues, but we do our best */ | ||
| 1889 | if (name) { | 1813 | if (name) { |
| 1890 | /* we can't use getname_kernel() due to size limits */ | 1814 | n->name = name; |
| 1891 | size_t len = strlen(name->name) + 1; | 1815 | name->refcnt++; |
| 1892 | struct filename *new = __getname(); | ||
| 1893 | |||
| 1894 | if (unlikely(!new)) | ||
| 1895 | goto out; | ||
| 1896 | |||
| 1897 | if (len <= (PATH_MAX - sizeof(*new))) { | ||
| 1898 | new->name = (char *)(new) + sizeof(*new); | ||
| 1899 | new->separate = false; | ||
| 1900 | } else if (len <= PATH_MAX) { | ||
| 1901 | /* this looks odd, but is due to final_putname() */ | ||
| 1902 | struct filename *new2; | ||
| 1903 | |||
| 1904 | new2 = kmalloc(sizeof(*new2), GFP_KERNEL); | ||
| 1905 | if (unlikely(!new2)) { | ||
| 1906 | __putname(new); | ||
| 1907 | goto out; | ||
| 1908 | } | ||
| 1909 | new2->name = (char *)new; | ||
| 1910 | new2->separate = true; | ||
| 1911 | new = new2; | ||
| 1912 | } else { | ||
| 1913 | /* we should never get here, but let's be safe */ | ||
| 1914 | __putname(new); | ||
| 1915 | goto out; | ||
| 1916 | } | ||
| 1917 | strlcpy((char *)new->name, name->name, len); | ||
| 1918 | new->uptr = NULL; | ||
| 1919 | new->aname = n; | ||
| 1920 | n->name = new; | ||
| 1921 | n->name_put = true; | ||
| 1922 | } | 1816 | } |
| 1817 | |||
| 1923 | out: | 1818 | out: |
| 1924 | if (parent) { | 1819 | if (parent) { |
| 1925 | n->name_len = n->name ? parent_len(n->name->name) : AUDIT_NAME_FULL; | 1820 | n->name_len = n->name ? parent_len(n->name->name) : AUDIT_NAME_FULL; |
| @@ -1970,11 +1865,16 @@ void __audit_inode_child(const struct inode *parent, | |||
| 1970 | 1865 | ||
| 1971 | /* look for a parent entry first */ | 1866 | /* look for a parent entry first */ |
| 1972 | list_for_each_entry(n, &context->names_list, list) { | 1867 | list_for_each_entry(n, &context->names_list, list) { |
| 1973 | if (!n->name || n->type != AUDIT_TYPE_PARENT) | 1868 | if (!n->name || |
| 1869 | (n->type != AUDIT_TYPE_PARENT && | ||
| 1870 | n->type != AUDIT_TYPE_UNKNOWN)) | ||
| 1974 | continue; | 1871 | continue; |
| 1975 | 1872 | ||
| 1976 | if (n->ino == parent->i_ino && | 1873 | if (n->ino == parent->i_ino && n->dev == parent->i_sb->s_dev && |
| 1977 | !audit_compare_dname_path(dname, n->name->name, n->name_len)) { | 1874 | !audit_compare_dname_path(dname, |
| 1875 | n->name->name, n->name_len)) { | ||
| 1876 | if (n->type == AUDIT_TYPE_UNKNOWN) | ||
| 1877 | n->type = AUDIT_TYPE_PARENT; | ||
| 1978 | found_parent = n; | 1878 | found_parent = n; |
| 1979 | break; | 1879 | break; |
| 1980 | } | 1880 | } |
| @@ -1983,11 +1883,8 @@ void __audit_inode_child(const struct inode *parent, | |||
| 1983 | /* is there a matching child entry? */ | 1883 | /* is there a matching child entry? */ |
| 1984 | list_for_each_entry(n, &context->names_list, list) { | 1884 | list_for_each_entry(n, &context->names_list, list) { |
| 1985 | /* can only match entries that have a name */ | 1885 | /* can only match entries that have a name */ |
| 1986 | if (!n->name || n->type != type) | 1886 | if (!n->name || |
| 1987 | continue; | 1887 | (n->type != type && n->type != AUDIT_TYPE_UNKNOWN)) |
| 1988 | |||
| 1989 | /* if we found a parent, make sure this one is a child of it */ | ||
| 1990 | if (found_parent && (n->name != found_parent->name)) | ||
| 1991 | continue; | 1888 | continue; |
| 1992 | 1889 | ||
| 1993 | if (!strcmp(dname, n->name->name) || | 1890 | if (!strcmp(dname, n->name->name) || |
| @@ -1995,6 +1892,8 @@ void __audit_inode_child(const struct inode *parent, | |||
| 1995 | found_parent ? | 1892 | found_parent ? |
| 1996 | found_parent->name_len : | 1893 | found_parent->name_len : |
| 1997 | AUDIT_NAME_FULL)) { | 1894 | AUDIT_NAME_FULL)) { |
| 1895 | if (n->type == AUDIT_TYPE_UNKNOWN) | ||
| 1896 | n->type = type; | ||
| 1998 | found_child = n; | 1897 | found_child = n; |
| 1999 | break; | 1898 | break; |
| 2000 | } | 1899 | } |
| @@ -2019,10 +1918,10 @@ void __audit_inode_child(const struct inode *parent, | |||
| 2019 | if (found_parent) { | 1918 | if (found_parent) { |
| 2020 | found_child->name = found_parent->name; | 1919 | found_child->name = found_parent->name; |
| 2021 | found_child->name_len = AUDIT_NAME_FULL; | 1920 | found_child->name_len = AUDIT_NAME_FULL; |
| 2022 | /* don't call __putname() */ | 1921 | found_child->name->refcnt++; |
| 2023 | found_child->name_put = false; | ||
| 2024 | } | 1922 | } |
| 2025 | } | 1923 | } |
| 1924 | |||
| 2026 | if (inode) | 1925 | if (inode) |
| 2027 | audit_copy_inode(found_child, dentry, inode); | 1926 | audit_copy_inode(found_child, dentry, inode); |
| 2028 | else | 1927 | else |
| @@ -2405,7 +2304,6 @@ int __audit_log_bprm_fcaps(struct linux_binprm *bprm, | |||
| 2405 | struct audit_aux_data_bprm_fcaps *ax; | 2304 | struct audit_aux_data_bprm_fcaps *ax; |
| 2406 | struct audit_context *context = current->audit_context; | 2305 | struct audit_context *context = current->audit_context; |
| 2407 | struct cpu_vfs_cap_data vcaps; | 2306 | struct cpu_vfs_cap_data vcaps; |
| 2408 | struct dentry *dentry; | ||
| 2409 | 2307 | ||
| 2410 | ax = kmalloc(sizeof(*ax), GFP_KERNEL); | 2308 | ax = kmalloc(sizeof(*ax), GFP_KERNEL); |
| 2411 | if (!ax) | 2309 | if (!ax) |
| @@ -2415,9 +2313,7 @@ int __audit_log_bprm_fcaps(struct linux_binprm *bprm, | |||
| 2415 | ax->d.next = context->aux; | 2313 | ax->d.next = context->aux; |
| 2416 | context->aux = (void *)ax; | 2314 | context->aux = (void *)ax; |
| 2417 | 2315 | ||
| 2418 | dentry = dget(bprm->file->f_path.dentry); | 2316 | get_vfs_caps_from_disk(bprm->file->f_path.dentry, &vcaps); |
| 2419 | get_vfs_caps_from_disk(dentry, &vcaps); | ||
| 2420 | dput(dentry); | ||
| 2421 | 2317 | ||
| 2422 | ax->fcap.permitted = vcaps.permitted; | 2318 | ax->fcap.permitted = vcaps.permitted; |
| 2423 | ax->fcap.inheritable = vcaps.inheritable; | 2319 | ax->fcap.inheritable = vcaps.inheritable; |
diff --git a/kernel/kexec.c b/kernel/kexec.c index c85277639b34..38c25b1f2fd5 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c | |||
| @@ -444,7 +444,7 @@ arch_kexec_apply_relocations(const Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, | |||
| 444 | } | 444 | } |
| 445 | 445 | ||
| 446 | /* | 446 | /* |
| 447 | * Free up memory used by kernel, initrd, and comand line. This is temporary | 447 | * Free up memory used by kernel, initrd, and command line. This is temporary |
| 448 | * memory allocation which is not needed any more after these buffers have | 448 | * memory allocation which is not needed any more after these buffers have |
| 449 | * been loaded into separate segments and have been copied elsewhere. | 449 | * been loaded into separate segments and have been copied elsewhere. |
| 450 | */ | 450 | */ |
| @@ -856,8 +856,6 @@ static int kimage_set_destination(struct kimage *image, | |||
| 856 | 856 | ||
| 857 | destination &= PAGE_MASK; | 857 | destination &= PAGE_MASK; |
| 858 | result = kimage_add_entry(image, destination | IND_DESTINATION); | 858 | result = kimage_add_entry(image, destination | IND_DESTINATION); |
| 859 | if (result == 0) | ||
| 860 | image->destination = destination; | ||
| 861 | 859 | ||
| 862 | return result; | 860 | return result; |
| 863 | } | 861 | } |
| @@ -869,8 +867,6 @@ static int kimage_add_page(struct kimage *image, unsigned long page) | |||
| 869 | 867 | ||
| 870 | page &= PAGE_MASK; | 868 | page &= PAGE_MASK; |
| 871 | result = kimage_add_entry(image, page | IND_SOURCE); | 869 | result = kimage_add_entry(image, page | IND_SOURCE); |
| 872 | if (result == 0) | ||
| 873 | image->destination += PAGE_SIZE; | ||
| 874 | 870 | ||
| 875 | return result; | 871 | return result; |
| 876 | } | 872 | } |
| @@ -1288,19 +1284,22 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments, | |||
| 1288 | if (nr_segments > 0) { | 1284 | if (nr_segments > 0) { |
| 1289 | unsigned long i; | 1285 | unsigned long i; |
| 1290 | 1286 | ||
| 1291 | /* Loading another kernel to reboot into */ | 1287 | if (flags & KEXEC_ON_CRASH) { |
| 1292 | if ((flags & KEXEC_ON_CRASH) == 0) | 1288 | /* |
| 1293 | result = kimage_alloc_init(&image, entry, nr_segments, | 1289 | * Loading another kernel to switch to if this one |
| 1294 | segments, flags); | 1290 | * crashes. Free any current crash dump kernel before |
| 1295 | /* Loading another kernel to switch to if this one crashes */ | ||
| 1296 | else if (flags & KEXEC_ON_CRASH) { | ||
| 1297 | /* Free any current crash dump kernel before | ||
| 1298 | * we corrupt it. | 1291 | * we corrupt it. |
| 1299 | */ | 1292 | */ |
| 1293 | |||
| 1300 | kimage_free(xchg(&kexec_crash_image, NULL)); | 1294 | kimage_free(xchg(&kexec_crash_image, NULL)); |
| 1301 | result = kimage_alloc_init(&image, entry, nr_segments, | 1295 | result = kimage_alloc_init(&image, entry, nr_segments, |
| 1302 | segments, flags); | 1296 | segments, flags); |
| 1303 | crash_map_reserved_pages(); | 1297 | crash_map_reserved_pages(); |
| 1298 | } else { | ||
| 1299 | /* Loading another kernel to reboot into. */ | ||
| 1300 | |||
| 1301 | result = kimage_alloc_init(&image, entry, nr_segments, | ||
| 1302 | segments, flags); | ||
| 1304 | } | 1303 | } |
| 1305 | if (result) | 1304 | if (result) |
| 1306 | goto out; | 1305 | goto out; |
diff --git a/kernel/module.c b/kernel/module.c index 8426ad48362c..b34813f725e9 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -3025,8 +3025,13 @@ static void do_free_init(struct rcu_head *head) | |||
| 3025 | kfree(m); | 3025 | kfree(m); |
| 3026 | } | 3026 | } |
| 3027 | 3027 | ||
| 3028 | /* This is where the real work happens */ | 3028 | /* |
| 3029 | static int do_init_module(struct module *mod) | 3029 | * This is where the real work happens. |
| 3030 | * | ||
| 3031 | * Keep it uninlined to provide a reliable breakpoint target, e.g. for the gdb | ||
| 3032 | * helper command 'lx-symbols'. | ||
| 3033 | */ | ||
| 3034 | static noinline int do_init_module(struct module *mod) | ||
| 3030 | { | 3035 | { |
| 3031 | int ret = 0; | 3036 | int ret = 0; |
| 3032 | struct mod_initfree *freeinit; | 3037 | struct mod_initfree *freeinit; |
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index c347e3ce3a55..b7d6b3a721b1 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c | |||
| @@ -37,7 +37,9 @@ const char *pm_states[PM_SUSPEND_MAX]; | |||
| 37 | static const struct platform_suspend_ops *suspend_ops; | 37 | static const struct platform_suspend_ops *suspend_ops; |
| 38 | static const struct platform_freeze_ops *freeze_ops; | 38 | static const struct platform_freeze_ops *freeze_ops; |
| 39 | static DECLARE_WAIT_QUEUE_HEAD(suspend_freeze_wait_head); | 39 | static DECLARE_WAIT_QUEUE_HEAD(suspend_freeze_wait_head); |
| 40 | static bool suspend_freeze_wake; | 40 | |
| 41 | enum freeze_state __read_mostly suspend_freeze_state; | ||
| 42 | static DEFINE_SPINLOCK(suspend_freeze_lock); | ||
| 41 | 43 | ||
| 42 | void freeze_set_ops(const struct platform_freeze_ops *ops) | 44 | void freeze_set_ops(const struct platform_freeze_ops *ops) |
| 43 | { | 45 | { |
| @@ -48,22 +50,49 @@ void freeze_set_ops(const struct platform_freeze_ops *ops) | |||
| 48 | 50 | ||
| 49 | static void freeze_begin(void) | 51 | static void freeze_begin(void) |
| 50 | { | 52 | { |
| 51 | suspend_freeze_wake = false; | 53 | suspend_freeze_state = FREEZE_STATE_NONE; |
| 52 | } | 54 | } |
| 53 | 55 | ||
| 54 | static void freeze_enter(void) | 56 | static void freeze_enter(void) |
| 55 | { | 57 | { |
| 56 | cpuidle_use_deepest_state(true); | 58 | spin_lock_irq(&suspend_freeze_lock); |
| 59 | if (pm_wakeup_pending()) | ||
| 60 | goto out; | ||
| 61 | |||
| 62 | suspend_freeze_state = FREEZE_STATE_ENTER; | ||
| 63 | spin_unlock_irq(&suspend_freeze_lock); | ||
| 64 | |||
| 65 | get_online_cpus(); | ||
| 57 | cpuidle_resume(); | 66 | cpuidle_resume(); |
| 58 | wait_event(suspend_freeze_wait_head, suspend_freeze_wake); | 67 | |
| 68 | /* Push all the CPUs into the idle loop. */ | ||
| 69 | wake_up_all_idle_cpus(); | ||
| 70 | pr_debug("PM: suspend-to-idle\n"); | ||
| 71 | /* Make the current CPU wait so it can enter the idle loop too. */ | ||
| 72 | wait_event(suspend_freeze_wait_head, | ||
| 73 | suspend_freeze_state == FREEZE_STATE_WAKE); | ||
| 74 | pr_debug("PM: resume from suspend-to-idle\n"); | ||
| 75 | |||
| 59 | cpuidle_pause(); | 76 | cpuidle_pause(); |
| 60 | cpuidle_use_deepest_state(false); | 77 | put_online_cpus(); |
| 78 | |||
| 79 | spin_lock_irq(&suspend_freeze_lock); | ||
| 80 | |||
| 81 | out: | ||
| 82 | suspend_freeze_state = FREEZE_STATE_NONE; | ||
| 83 | spin_unlock_irq(&suspend_freeze_lock); | ||
| 61 | } | 84 | } |
| 62 | 85 | ||
| 63 | void freeze_wake(void) | 86 | void freeze_wake(void) |
| 64 | { | 87 | { |
| 65 | suspend_freeze_wake = true; | 88 | unsigned long flags; |
| 66 | wake_up(&suspend_freeze_wait_head); | 89 | |
| 90 | spin_lock_irqsave(&suspend_freeze_lock, flags); | ||
| 91 | if (suspend_freeze_state > FREEZE_STATE_NONE) { | ||
| 92 | suspend_freeze_state = FREEZE_STATE_WAKE; | ||
| 93 | wake_up(&suspend_freeze_wait_head); | ||
| 94 | } | ||
| 95 | spin_unlock_irqrestore(&suspend_freeze_lock, flags); | ||
| 67 | } | 96 | } |
| 68 | EXPORT_SYMBOL_GPL(freeze_wake); | 97 | EXPORT_SYMBOL_GPL(freeze_wake); |
| 69 | 98 | ||
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 1eb9d90c3af9..227fec36b12a 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
| @@ -1077,7 +1077,6 @@ int generic_ptrace_pokedata(struct task_struct *tsk, unsigned long addr, | |||
| 1077 | } | 1077 | } |
| 1078 | 1078 | ||
| 1079 | #if defined CONFIG_COMPAT | 1079 | #if defined CONFIG_COMPAT |
| 1080 | #include <linux/compat.h> | ||
| 1081 | 1080 | ||
| 1082 | int compat_ptrace_request(struct task_struct *child, compat_long_t request, | 1081 | int compat_ptrace_request(struct task_struct *child, compat_long_t request, |
| 1083 | compat_ulong_t addr, compat_ulong_t data) | 1082 | compat_ulong_t addr, compat_ulong_t data) |
diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c index aaf1c1d5cf5d..94b2d7b88a27 100644 --- a/kernel/sched/idle.c +++ b/kernel/sched/idle.c | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <linux/tick.h> | 7 | #include <linux/tick.h> |
| 8 | #include <linux/mm.h> | 8 | #include <linux/mm.h> |
| 9 | #include <linux/stackprotector.h> | 9 | #include <linux/stackprotector.h> |
| 10 | #include <linux/suspend.h> | ||
| 10 | 11 | ||
| 11 | #include <asm/tlb.h> | 12 | #include <asm/tlb.h> |
| 12 | 13 | ||
| @@ -105,6 +106,21 @@ static void cpuidle_idle_call(void) | |||
| 105 | rcu_idle_enter(); | 106 | rcu_idle_enter(); |
| 106 | 107 | ||
| 107 | /* | 108 | /* |
| 109 | * Suspend-to-idle ("freeze") is a system state in which all user space | ||
| 110 | * has been frozen, all I/O devices have been suspended and the only | ||
| 111 | * activity happens here and in iterrupts (if any). In that case bypass | ||
| 112 | * the cpuidle governor and go stratight for the deepest idle state | ||
| 113 | * available. Possibly also suspend the local tick and the entire | ||
| 114 | * timekeeping to prevent timer interrupts from kicking us out of idle | ||
| 115 | * until a proper wakeup interrupt happens. | ||
| 116 | */ | ||
| 117 | if (idle_should_freeze()) { | ||
| 118 | cpuidle_enter_freeze(); | ||
| 119 | local_irq_enable(); | ||
| 120 | goto exit_idle; | ||
| 121 | } | ||
| 122 | |||
| 123 | /* | ||
| 108 | * Ask the cpuidle framework to choose a convenient idle state. | 124 | * Ask the cpuidle framework to choose a convenient idle state. |
| 109 | * Fall back to the default arch idle method on errors. | 125 | * Fall back to the default arch idle method on errors. |
| 110 | */ | 126 | */ |
diff --git a/kernel/seccomp.c b/kernel/seccomp.c index 4ef9687ac115..4f44028943e6 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c | |||
| @@ -629,7 +629,9 @@ static u32 __seccomp_phase1_filter(int this_syscall, struct seccomp_data *sd) | |||
| 629 | 629 | ||
| 630 | switch (action) { | 630 | switch (action) { |
| 631 | case SECCOMP_RET_ERRNO: | 631 | case SECCOMP_RET_ERRNO: |
| 632 | /* Set the low-order 16-bits as a errno. */ | 632 | /* Set low-order bits as an errno, capped at MAX_ERRNO. */ |
| 633 | if (data > MAX_ERRNO) | ||
| 634 | data = MAX_ERRNO; | ||
| 633 | syscall_set_return_value(current, task_pt_regs(current), | 635 | syscall_set_return_value(current, task_pt_regs(current), |
| 634 | -data, 0); | 636 | -data, 0); |
| 635 | goto skip; | 637 | goto skip; |
diff --git a/kernel/signal.c b/kernel/signal.c index 33a52759cc0e..a390499943e4 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
| @@ -3550,7 +3550,7 @@ SYSCALL_DEFINE2(signal, int, sig, __sighandler_t, handler) | |||
| 3550 | SYSCALL_DEFINE0(pause) | 3550 | SYSCALL_DEFINE0(pause) |
| 3551 | { | 3551 | { |
| 3552 | while (!signal_pending(current)) { | 3552 | while (!signal_pending(current)) { |
| 3553 | current->state = TASK_INTERRUPTIBLE; | 3553 | __set_current_state(TASK_INTERRUPTIBLE); |
| 3554 | schedule(); | 3554 | schedule(); |
| 3555 | } | 3555 | } |
| 3556 | return -ERESTARTNOHAND; | 3556 | return -ERESTARTNOHAND; |
| @@ -3563,7 +3563,7 @@ int sigsuspend(sigset_t *set) | |||
| 3563 | current->saved_sigmask = current->blocked; | 3563 | current->saved_sigmask = current->blocked; |
| 3564 | set_current_blocked(set); | 3564 | set_current_blocked(set); |
| 3565 | 3565 | ||
| 3566 | current->state = TASK_INTERRUPTIBLE; | 3566 | __set_current_state(TASK_INTERRUPTIBLE); |
| 3567 | schedule(); | 3567 | schedule(); |
| 3568 | set_restore_sigmask(); | 3568 | set_restore_sigmask(); |
| 3569 | return -ERESTARTNOHAND; | 3569 | return -ERESTARTNOHAND; |
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index 7efeedf53ebd..f7c515595b42 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c | |||
| @@ -394,6 +394,56 @@ void tick_resume(void) | |||
| 394 | } | 394 | } |
| 395 | } | 395 | } |
| 396 | 396 | ||
| 397 | static DEFINE_RAW_SPINLOCK(tick_freeze_lock); | ||
| 398 | static unsigned int tick_freeze_depth; | ||
| 399 | |||
| 400 | /** | ||
| 401 | * tick_freeze - Suspend the local tick and (possibly) timekeeping. | ||
| 402 | * | ||
| 403 | * Check if this is the last online CPU executing the function and if so, | ||
| 404 | * suspend timekeeping. Otherwise suspend the local tick. | ||
| 405 | * | ||
| 406 | * Call with interrupts disabled. Must be balanced with %tick_unfreeze(). | ||
| 407 | * Interrupts must not be enabled before the subsequent %tick_unfreeze(). | ||
| 408 | */ | ||
| 409 | void tick_freeze(void) | ||
| 410 | { | ||
| 411 | raw_spin_lock(&tick_freeze_lock); | ||
| 412 | |||
| 413 | tick_freeze_depth++; | ||
| 414 | if (tick_freeze_depth == num_online_cpus()) { | ||
| 415 | timekeeping_suspend(); | ||
| 416 | } else { | ||
| 417 | tick_suspend(); | ||
| 418 | tick_suspend_broadcast(); | ||
| 419 | } | ||
| 420 | |||
| 421 | raw_spin_unlock(&tick_freeze_lock); | ||
| 422 | } | ||
| 423 | |||
| 424 | /** | ||
| 425 | * tick_unfreeze - Resume the local tick and (possibly) timekeeping. | ||
| 426 | * | ||
| 427 | * Check if this is the first CPU executing the function and if so, resume | ||
| 428 | * timekeeping. Otherwise resume the local tick. | ||
| 429 | * | ||
| 430 | * Call with interrupts disabled. Must be balanced with %tick_freeze(). | ||
| 431 | * Interrupts must not be enabled after the preceding %tick_freeze(). | ||
| 432 | */ | ||
| 433 | void tick_unfreeze(void) | ||
| 434 | { | ||
| 435 | raw_spin_lock(&tick_freeze_lock); | ||
| 436 | |||
| 437 | if (tick_freeze_depth == num_online_cpus()) | ||
| 438 | timekeeping_resume(); | ||
| 439 | else | ||
| 440 | tick_resume(); | ||
| 441 | |||
| 442 | tick_freeze_depth--; | ||
| 443 | |||
| 444 | raw_spin_unlock(&tick_freeze_lock); | ||
| 445 | } | ||
| 446 | |||
| 397 | /** | 447 | /** |
| 398 | * tick_init - initialize the tick control | 448 | * tick_init - initialize the tick control |
| 399 | */ | 449 | */ |
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index b124af259800..91db94136c10 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
| @@ -230,9 +230,7 @@ static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk) | |||
| 230 | 230 | ||
| 231 | /** | 231 | /** |
| 232 | * update_fast_timekeeper - Update the fast and NMI safe monotonic timekeeper. | 232 | * update_fast_timekeeper - Update the fast and NMI safe monotonic timekeeper. |
| 233 | * @tk: The timekeeper from which we take the update | 233 | * @tkr: Timekeeping readout base from which we take the update |
| 234 | * @tkf: The fast timekeeper to update | ||
| 235 | * @tbase: The time base for the fast timekeeper (mono/raw) | ||
| 236 | * | 234 | * |
| 237 | * We want to use this from any context including NMI and tracing / | 235 | * We want to use this from any context including NMI and tracing / |
| 238 | * instrumenting the timekeeping code itself. | 236 | * instrumenting the timekeeping code itself. |
| @@ -244,11 +242,11 @@ static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk) | |||
| 244 | * smp_wmb(); <- Ensure that the last base[1] update is visible | 242 | * smp_wmb(); <- Ensure that the last base[1] update is visible |
| 245 | * tkf->seq++; | 243 | * tkf->seq++; |
| 246 | * smp_wmb(); <- Ensure that the seqcount update is visible | 244 | * smp_wmb(); <- Ensure that the seqcount update is visible |
| 247 | * update(tkf->base[0], tk); | 245 | * update(tkf->base[0], tkr); |
| 248 | * smp_wmb(); <- Ensure that the base[0] update is visible | 246 | * smp_wmb(); <- Ensure that the base[0] update is visible |
| 249 | * tkf->seq++; | 247 | * tkf->seq++; |
| 250 | * smp_wmb(); <- Ensure that the seqcount update is visible | 248 | * smp_wmb(); <- Ensure that the seqcount update is visible |
| 251 | * update(tkf->base[1], tk); | 249 | * update(tkf->base[1], tkr); |
| 252 | * | 250 | * |
| 253 | * The reader side does: | 251 | * The reader side does: |
| 254 | * | 252 | * |
| @@ -269,7 +267,7 @@ static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk) | |||
| 269 | * slightly wrong timestamp (a few nanoseconds). See | 267 | * slightly wrong timestamp (a few nanoseconds). See |
| 270 | * @ktime_get_mono_fast_ns. | 268 | * @ktime_get_mono_fast_ns. |
| 271 | */ | 269 | */ |
| 272 | static void update_fast_timekeeper(struct timekeeper *tk) | 270 | static void update_fast_timekeeper(struct tk_read_base *tkr) |
| 273 | { | 271 | { |
| 274 | struct tk_read_base *base = tk_fast_mono.base; | 272 | struct tk_read_base *base = tk_fast_mono.base; |
| 275 | 273 | ||
| @@ -277,7 +275,7 @@ static void update_fast_timekeeper(struct timekeeper *tk) | |||
| 277 | raw_write_seqcount_latch(&tk_fast_mono.seq); | 275 | raw_write_seqcount_latch(&tk_fast_mono.seq); |
| 278 | 276 | ||
| 279 | /* Update base[0] */ | 277 | /* Update base[0] */ |
| 280 | memcpy(base, &tk->tkr, sizeof(*base)); | 278 | memcpy(base, tkr, sizeof(*base)); |
| 281 | 279 | ||
| 282 | /* Force readers back to base[0] */ | 280 | /* Force readers back to base[0] */ |
| 283 | raw_write_seqcount_latch(&tk_fast_mono.seq); | 281 | raw_write_seqcount_latch(&tk_fast_mono.seq); |
| @@ -334,6 +332,35 @@ u64 notrace ktime_get_mono_fast_ns(void) | |||
| 334 | } | 332 | } |
| 335 | EXPORT_SYMBOL_GPL(ktime_get_mono_fast_ns); | 333 | EXPORT_SYMBOL_GPL(ktime_get_mono_fast_ns); |
| 336 | 334 | ||
| 335 | /* Suspend-time cycles value for halted fast timekeeper. */ | ||
| 336 | static cycle_t cycles_at_suspend; | ||
| 337 | |||
| 338 | static cycle_t dummy_clock_read(struct clocksource *cs) | ||
| 339 | { | ||
| 340 | return cycles_at_suspend; | ||
| 341 | } | ||
| 342 | |||
| 343 | /** | ||
| 344 | * halt_fast_timekeeper - Prevent fast timekeeper from accessing clocksource. | ||
| 345 | * @tk: Timekeeper to snapshot. | ||
| 346 | * | ||
| 347 | * It generally is unsafe to access the clocksource after timekeeping has been | ||
| 348 | * suspended, so take a snapshot of the readout base of @tk and use it as the | ||
| 349 | * fast timekeeper's readout base while suspended. It will return the same | ||
| 350 | * number of cycles every time until timekeeping is resumed at which time the | ||
| 351 | * proper readout base for the fast timekeeper will be restored automatically. | ||
| 352 | */ | ||
| 353 | static void halt_fast_timekeeper(struct timekeeper *tk) | ||
| 354 | { | ||
| 355 | static struct tk_read_base tkr_dummy; | ||
| 356 | struct tk_read_base *tkr = &tk->tkr; | ||
| 357 | |||
| 358 | memcpy(&tkr_dummy, tkr, sizeof(tkr_dummy)); | ||
| 359 | cycles_at_suspend = tkr->read(tkr->clock); | ||
| 360 | tkr_dummy.read = dummy_clock_read; | ||
| 361 | update_fast_timekeeper(&tkr_dummy); | ||
| 362 | } | ||
| 363 | |||
| 337 | #ifdef CONFIG_GENERIC_TIME_VSYSCALL_OLD | 364 | #ifdef CONFIG_GENERIC_TIME_VSYSCALL_OLD |
| 338 | 365 | ||
| 339 | static inline void update_vsyscall(struct timekeeper *tk) | 366 | static inline void update_vsyscall(struct timekeeper *tk) |
| @@ -462,7 +489,7 @@ static void timekeeping_update(struct timekeeper *tk, unsigned int action) | |||
| 462 | memcpy(&shadow_timekeeper, &tk_core.timekeeper, | 489 | memcpy(&shadow_timekeeper, &tk_core.timekeeper, |
| 463 | sizeof(tk_core.timekeeper)); | 490 | sizeof(tk_core.timekeeper)); |
| 464 | 491 | ||
| 465 | update_fast_timekeeper(tk); | 492 | update_fast_timekeeper(&tk->tkr); |
| 466 | } | 493 | } |
| 467 | 494 | ||
| 468 | /** | 495 | /** |
| @@ -1170,7 +1197,7 @@ void timekeeping_inject_sleeptime64(struct timespec64 *delta) | |||
| 1170 | * xtime/wall_to_monotonic/jiffies/etc are | 1197 | * xtime/wall_to_monotonic/jiffies/etc are |
| 1171 | * still managed by arch specific suspend/resume code. | 1198 | * still managed by arch specific suspend/resume code. |
| 1172 | */ | 1199 | */ |
| 1173 | static void timekeeping_resume(void) | 1200 | void timekeeping_resume(void) |
| 1174 | { | 1201 | { |
| 1175 | struct timekeeper *tk = &tk_core.timekeeper; | 1202 | struct timekeeper *tk = &tk_core.timekeeper; |
| 1176 | struct clocksource *clock = tk->tkr.clock; | 1203 | struct clocksource *clock = tk->tkr.clock; |
| @@ -1251,7 +1278,7 @@ static void timekeeping_resume(void) | |||
| 1251 | hrtimers_resume(); | 1278 | hrtimers_resume(); |
| 1252 | } | 1279 | } |
| 1253 | 1280 | ||
| 1254 | static int timekeeping_suspend(void) | 1281 | int timekeeping_suspend(void) |
| 1255 | { | 1282 | { |
| 1256 | struct timekeeper *tk = &tk_core.timekeeper; | 1283 | struct timekeeper *tk = &tk_core.timekeeper; |
| 1257 | unsigned long flags; | 1284 | unsigned long flags; |
| @@ -1296,6 +1323,7 @@ static int timekeeping_suspend(void) | |||
| 1296 | } | 1323 | } |
| 1297 | 1324 | ||
| 1298 | timekeeping_update(tk, TK_MIRROR); | 1325 | timekeeping_update(tk, TK_MIRROR); |
| 1326 | halt_fast_timekeeper(tk); | ||
| 1299 | write_seqcount_end(&tk_core.seq); | 1327 | write_seqcount_end(&tk_core.seq); |
| 1300 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); | 1328 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); |
| 1301 | 1329 | ||
diff --git a/kernel/time/timekeeping.h b/kernel/time/timekeeping.h index adc1fc98bde3..1d91416055d5 100644 --- a/kernel/time/timekeeping.h +++ b/kernel/time/timekeeping.h | |||
| @@ -16,5 +16,7 @@ extern int timekeeping_inject_offset(struct timespec *ts); | |||
| 16 | extern s32 timekeeping_get_tai_offset(void); | 16 | extern s32 timekeeping_get_tai_offset(void); |
| 17 | extern void timekeeping_set_tai_offset(s32 tai_offset); | 17 | extern void timekeeping_set_tai_offset(s32 tai_offset); |
| 18 | extern void timekeeping_clocktai(struct timespec *ts); | 18 | extern void timekeeping_clocktai(struct timespec *ts); |
| 19 | extern int timekeeping_suspend(void); | ||
| 20 | extern void timekeeping_resume(void); | ||
| 19 | 21 | ||
| 20 | #endif | 22 | #endif |
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index ecb3516f6546..c5cefb3c009c 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
| @@ -167,6 +167,17 @@ config DEBUG_INFO_DWARF4 | |||
| 167 | But it significantly improves the success of resolving | 167 | But it significantly improves the success of resolving |
| 168 | variables in gdb on optimized code. | 168 | variables in gdb on optimized code. |
| 169 | 169 | ||
| 170 | config GDB_SCRIPTS | ||
| 171 | bool "Provide GDB scripts for kernel debugging" | ||
| 172 | depends on DEBUG_INFO | ||
| 173 | help | ||
| 174 | This creates the required links to GDB helper scripts in the | ||
| 175 | build directory. If you load vmlinux into gdb, the helper | ||
| 176 | scripts will be automatically imported by gdb as well, and | ||
| 177 | additional functions are available to analyze a Linux kernel | ||
| 178 | instance. See Documentation/gdb-kernel-debugging.txt for further | ||
| 179 | details. | ||
| 180 | |||
| 170 | config ENABLE_WARN_DEPRECATED | 181 | config ENABLE_WARN_DEPRECATED |
| 171 | bool "Enable __deprecated logic" | 182 | bool "Enable __deprecated logic" |
| 172 | default y | 183 | default y |
diff --git a/lib/lockref.c b/lib/lockref.c index d2233de9a86e..ecb9a665ec19 100644 --- a/lib/lockref.c +++ b/lib/lockref.c | |||
| @@ -60,7 +60,7 @@ void lockref_get(struct lockref *lockref) | |||
| 60 | EXPORT_SYMBOL(lockref_get); | 60 | EXPORT_SYMBOL(lockref_get); |
| 61 | 61 | ||
| 62 | /** | 62 | /** |
| 63 | * lockref_get_not_zero - Increments count unless the count is 0 | 63 | * lockref_get_not_zero - Increments count unless the count is 0 or dead |
| 64 | * @lockref: pointer to lockref structure | 64 | * @lockref: pointer to lockref structure |
| 65 | * Return: 1 if count updated successfully or 0 if count was zero | 65 | * Return: 1 if count updated successfully or 0 if count was zero |
| 66 | */ | 66 | */ |
| @@ -70,7 +70,7 @@ int lockref_get_not_zero(struct lockref *lockref) | |||
| 70 | 70 | ||
| 71 | CMPXCHG_LOOP( | 71 | CMPXCHG_LOOP( |
| 72 | new.count++; | 72 | new.count++; |
| 73 | if (!old.count) | 73 | if (old.count <= 0) |
| 74 | return 0; | 74 | return 0; |
| 75 | , | 75 | , |
| 76 | return 1; | 76 | return 1; |
| @@ -78,7 +78,7 @@ int lockref_get_not_zero(struct lockref *lockref) | |||
| 78 | 78 | ||
| 79 | spin_lock(&lockref->lock); | 79 | spin_lock(&lockref->lock); |
| 80 | retval = 0; | 80 | retval = 0; |
| 81 | if (lockref->count) { | 81 | if (lockref->count > 0) { |
| 82 | lockref->count++; | 82 | lockref->count++; |
| 83 | retval = 1; | 83 | retval = 1; |
| 84 | } | 84 | } |
| @@ -88,7 +88,7 @@ int lockref_get_not_zero(struct lockref *lockref) | |||
| 88 | EXPORT_SYMBOL(lockref_get_not_zero); | 88 | EXPORT_SYMBOL(lockref_get_not_zero); |
| 89 | 89 | ||
| 90 | /** | 90 | /** |
| 91 | * lockref_get_or_lock - Increments count unless the count is 0 | 91 | * lockref_get_or_lock - Increments count unless the count is 0 or dead |
| 92 | * @lockref: pointer to lockref structure | 92 | * @lockref: pointer to lockref structure |
| 93 | * Return: 1 if count updated successfully or 0 if count was zero | 93 | * Return: 1 if count updated successfully or 0 if count was zero |
| 94 | * and we got the lock instead. | 94 | * and we got the lock instead. |
| @@ -97,14 +97,14 @@ int lockref_get_or_lock(struct lockref *lockref) | |||
| 97 | { | 97 | { |
| 98 | CMPXCHG_LOOP( | 98 | CMPXCHG_LOOP( |
| 99 | new.count++; | 99 | new.count++; |
| 100 | if (!old.count) | 100 | if (old.count <= 0) |
| 101 | break; | 101 | break; |
| 102 | , | 102 | , |
| 103 | return 1; | 103 | return 1; |
| 104 | ); | 104 | ); |
| 105 | 105 | ||
| 106 | spin_lock(&lockref->lock); | 106 | spin_lock(&lockref->lock); |
| 107 | if (!lockref->count) | 107 | if (lockref->count <= 0) |
| 108 | return 0; | 108 | return 0; |
| 109 | lockref->count++; | 109 | lockref->count++; |
| 110 | spin_unlock(&lockref->lock); | 110 | spin_unlock(&lockref->lock); |
| @@ -113,6 +113,26 @@ int lockref_get_or_lock(struct lockref *lockref) | |||
| 113 | EXPORT_SYMBOL(lockref_get_or_lock); | 113 | EXPORT_SYMBOL(lockref_get_or_lock); |
| 114 | 114 | ||
| 115 | /** | 115 | /** |
| 116 | * lockref_put_return - Decrement reference count if possible | ||
| 117 | * @lockref: pointer to lockref structure | ||
| 118 | * | ||
| 119 | * Decrement the reference count and return the new value. | ||
| 120 | * If the lockref was dead or locked, return an error. | ||
| 121 | */ | ||
| 122 | int lockref_put_return(struct lockref *lockref) | ||
| 123 | { | ||
| 124 | CMPXCHG_LOOP( | ||
| 125 | new.count--; | ||
| 126 | if (old.count <= 0) | ||
| 127 | return -1; | ||
| 128 | , | ||
| 129 | return new.count; | ||
| 130 | ); | ||
| 131 | return -1; | ||
| 132 | } | ||
| 133 | EXPORT_SYMBOL(lockref_put_return); | ||
| 134 | |||
| 135 | /** | ||
| 116 | * lockref_put_or_lock - decrements count unless count <= 1 before decrement | 136 | * lockref_put_or_lock - decrements count unless count <= 1 before decrement |
| 117 | * @lockref: pointer to lockref structure | 137 | * @lockref: pointer to lockref structure |
| 118 | * Return: 1 if count updated successfully or 0 if count <= 1 and lock taken | 138 | * Return: 1 if count updated successfully or 0 if count <= 1 and lock taken |
| @@ -158,7 +178,7 @@ int lockref_get_not_dead(struct lockref *lockref) | |||
| 158 | 178 | ||
| 159 | CMPXCHG_LOOP( | 179 | CMPXCHG_LOOP( |
| 160 | new.count++; | 180 | new.count++; |
| 161 | if ((int)old.count < 0) | 181 | if (old.count < 0) |
| 162 | return 0; | 182 | return 0; |
| 163 | , | 183 | , |
| 164 | return 1; | 184 | return 1; |
| @@ -166,7 +186,7 @@ int lockref_get_not_dead(struct lockref *lockref) | |||
| 166 | 186 | ||
| 167 | spin_lock(&lockref->lock); | 187 | spin_lock(&lockref->lock); |
| 168 | retval = 0; | 188 | retval = 0; |
| 169 | if ((int) lockref->count >= 0) { | 189 | if (lockref->count >= 0) { |
| 170 | lockref->count++; | 190 | lockref->count++; |
| 171 | retval = 1; | 191 | retval = 1; |
| 172 | } | 192 | } |
diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 7690ec77c722..6dc4580df2af 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c | |||
| @@ -49,10 +49,10 @@ static int bdi_debug_stats_show(struct seq_file *m, void *v) | |||
| 49 | unsigned long background_thresh; | 49 | unsigned long background_thresh; |
| 50 | unsigned long dirty_thresh; | 50 | unsigned long dirty_thresh; |
| 51 | unsigned long bdi_thresh; | 51 | unsigned long bdi_thresh; |
| 52 | unsigned long nr_dirty, nr_io, nr_more_io; | 52 | unsigned long nr_dirty, nr_io, nr_more_io, nr_dirty_time; |
| 53 | struct inode *inode; | 53 | struct inode *inode; |
| 54 | 54 | ||
| 55 | nr_dirty = nr_io = nr_more_io = 0; | 55 | nr_dirty = nr_io = nr_more_io = nr_dirty_time = 0; |
| 56 | spin_lock(&wb->list_lock); | 56 | spin_lock(&wb->list_lock); |
| 57 | list_for_each_entry(inode, &wb->b_dirty, i_wb_list) | 57 | list_for_each_entry(inode, &wb->b_dirty, i_wb_list) |
| 58 | nr_dirty++; | 58 | nr_dirty++; |
| @@ -60,6 +60,9 @@ static int bdi_debug_stats_show(struct seq_file *m, void *v) | |||
| 60 | nr_io++; | 60 | nr_io++; |
| 61 | list_for_each_entry(inode, &wb->b_more_io, i_wb_list) | 61 | list_for_each_entry(inode, &wb->b_more_io, i_wb_list) |
| 62 | nr_more_io++; | 62 | nr_more_io++; |
| 63 | list_for_each_entry(inode, &wb->b_dirty_time, i_wb_list) | ||
| 64 | if (inode->i_state & I_DIRTY_TIME) | ||
| 65 | nr_dirty_time++; | ||
| 63 | spin_unlock(&wb->list_lock); | 66 | spin_unlock(&wb->list_lock); |
| 64 | 67 | ||
| 65 | global_dirty_limits(&background_thresh, &dirty_thresh); | 68 | global_dirty_limits(&background_thresh, &dirty_thresh); |
| @@ -78,6 +81,7 @@ static int bdi_debug_stats_show(struct seq_file *m, void *v) | |||
| 78 | "b_dirty: %10lu\n" | 81 | "b_dirty: %10lu\n" |
| 79 | "b_io: %10lu\n" | 82 | "b_io: %10lu\n" |
| 80 | "b_more_io: %10lu\n" | 83 | "b_more_io: %10lu\n" |
| 84 | "b_dirty_time: %10lu\n" | ||
| 81 | "bdi_list: %10u\n" | 85 | "bdi_list: %10u\n" |
| 82 | "state: %10lx\n", | 86 | "state: %10lx\n", |
| 83 | (unsigned long) K(bdi_stat(bdi, BDI_WRITEBACK)), | 87 | (unsigned long) K(bdi_stat(bdi, BDI_WRITEBACK)), |
| @@ -91,6 +95,7 @@ static int bdi_debug_stats_show(struct seq_file *m, void *v) | |||
| 91 | nr_dirty, | 95 | nr_dirty, |
| 92 | nr_io, | 96 | nr_io, |
| 93 | nr_more_io, | 97 | nr_more_io, |
| 98 | nr_dirty_time, | ||
| 94 | !list_empty(&bdi->bdi_list), bdi->state); | 99 | !list_empty(&bdi->bdi_list), bdi->state); |
| 95 | #undef K | 100 | #undef K |
| 96 | 101 | ||
| @@ -380,6 +385,7 @@ static void bdi_wb_init(struct bdi_writeback *wb, struct backing_dev_info *bdi) | |||
| 380 | INIT_LIST_HEAD(&wb->b_dirty); | 385 | INIT_LIST_HEAD(&wb->b_dirty); |
| 381 | INIT_LIST_HEAD(&wb->b_io); | 386 | INIT_LIST_HEAD(&wb->b_io); |
| 382 | INIT_LIST_HEAD(&wb->b_more_io); | 387 | INIT_LIST_HEAD(&wb->b_more_io); |
| 388 | INIT_LIST_HEAD(&wb->b_dirty_time); | ||
| 383 | spin_lock_init(&wb->list_lock); | 389 | spin_lock_init(&wb->list_lock); |
| 384 | INIT_DELAYED_WORK(&wb->dwork, bdi_writeback_workfn); | 390 | INIT_DELAYED_WORK(&wb->dwork, bdi_writeback_workfn); |
| 385 | } | 391 | } |
diff --git a/mm/iov_iter.c b/mm/iov_iter.c index a1599ca4ab0e..827732047da1 100644 --- a/mm/iov_iter.c +++ b/mm/iov_iter.c | |||
| @@ -501,18 +501,31 @@ size_t iov_iter_single_seg_count(const struct iov_iter *i) | |||
| 501 | EXPORT_SYMBOL(iov_iter_single_seg_count); | 501 | EXPORT_SYMBOL(iov_iter_single_seg_count); |
| 502 | 502 | ||
| 503 | void iov_iter_kvec(struct iov_iter *i, int direction, | 503 | void iov_iter_kvec(struct iov_iter *i, int direction, |
| 504 | const struct kvec *iov, unsigned long nr_segs, | 504 | const struct kvec *kvec, unsigned long nr_segs, |
| 505 | size_t count) | 505 | size_t count) |
| 506 | { | 506 | { |
| 507 | BUG_ON(!(direction & ITER_KVEC)); | 507 | BUG_ON(!(direction & ITER_KVEC)); |
| 508 | i->type = direction; | 508 | i->type = direction; |
| 509 | i->kvec = (struct kvec *)iov; | 509 | i->kvec = kvec; |
| 510 | i->nr_segs = nr_segs; | 510 | i->nr_segs = nr_segs; |
| 511 | i->iov_offset = 0; | 511 | i->iov_offset = 0; |
| 512 | i->count = count; | 512 | i->count = count; |
| 513 | } | 513 | } |
| 514 | EXPORT_SYMBOL(iov_iter_kvec); | 514 | EXPORT_SYMBOL(iov_iter_kvec); |
| 515 | 515 | ||
| 516 | void iov_iter_bvec(struct iov_iter *i, int direction, | ||
| 517 | const struct bio_vec *bvec, unsigned long nr_segs, | ||
| 518 | size_t count) | ||
| 519 | { | ||
| 520 | BUG_ON(!(direction & ITER_BVEC)); | ||
| 521 | i->type = direction; | ||
| 522 | i->bvec = bvec; | ||
| 523 | i->nr_segs = nr_segs; | ||
| 524 | i->iov_offset = 0; | ||
| 525 | i->count = count; | ||
| 526 | } | ||
| 527 | EXPORT_SYMBOL(iov_iter_bvec); | ||
| 528 | |||
| 516 | unsigned long iov_iter_alignment(const struct iov_iter *i) | 529 | unsigned long iov_iter_alignment(const struct iov_iter *i) |
| 517 | { | 530 | { |
| 518 | unsigned long res = 0; | 531 | unsigned long res = 0; |
diff --git a/mm/page_io.c b/mm/page_io.c index 955db8b0d497..e6045804c8d8 100644 --- a/mm/page_io.c +++ b/mm/page_io.c | |||
| @@ -269,14 +269,9 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc, | |||
| 269 | .bv_len = PAGE_SIZE, | 269 | .bv_len = PAGE_SIZE, |
| 270 | .bv_offset = 0 | 270 | .bv_offset = 0 |
| 271 | }; | 271 | }; |
| 272 | struct iov_iter from = { | 272 | struct iov_iter from; |
| 273 | .type = ITER_BVEC | WRITE, | ||
| 274 | .count = PAGE_SIZE, | ||
| 275 | .iov_offset = 0, | ||
| 276 | .nr_segs = 1, | ||
| 277 | }; | ||
| 278 | from.bvec = &bv; /* older gcc versions are broken */ | ||
| 279 | 273 | ||
| 274 | iov_iter_bvec(&from, ITER_BVEC | WRITE, &bv, 1, PAGE_SIZE); | ||
| 280 | init_sync_kiocb(&kiocb, swap_file); | 275 | init_sync_kiocb(&kiocb, swap_file); |
| 281 | kiocb.ki_pos = page_file_offset(page); | 276 | kiocb.ki_pos = page_file_offset(page); |
| 282 | kiocb.ki_nbytes = PAGE_SIZE; | 277 | kiocb.ki_nbytes = PAGE_SIZE; |
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 65728e0dc4ff..0ee453fad3de 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
| @@ -987,15 +987,12 @@ static int __init br_netfilter_init(void) | |||
| 987 | if (brnf_sysctl_header == NULL) { | 987 | if (brnf_sysctl_header == NULL) { |
| 988 | printk(KERN_WARNING | 988 | printk(KERN_WARNING |
| 989 | "br_netfilter: can't register to sysctl.\n"); | 989 | "br_netfilter: can't register to sysctl.\n"); |
| 990 | ret = -ENOMEM; | 990 | nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops)); |
| 991 | goto err1; | 991 | return -ENOMEM; |
| 992 | } | 992 | } |
| 993 | #endif | 993 | #endif |
| 994 | printk(KERN_NOTICE "Bridge firewalling registered\n"); | 994 | printk(KERN_NOTICE "Bridge firewalling registered\n"); |
| 995 | return 0; | 995 | return 0; |
| 996 | err1: | ||
| 997 | nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops)); | ||
| 998 | return ret; | ||
| 999 | } | 996 | } |
| 1000 | 997 | ||
| 1001 | static void __exit br_netfilter_fini(void) | 998 | static void __exit br_netfilter_fini(void) |
diff --git a/net/core/dev.c b/net/core/dev.c index d030575532a2..8f9710c62e20 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -4024,6 +4024,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff | |||
| 4024 | NAPI_GRO_CB(skb)->flush = 0; | 4024 | NAPI_GRO_CB(skb)->flush = 0; |
| 4025 | NAPI_GRO_CB(skb)->free = 0; | 4025 | NAPI_GRO_CB(skb)->free = 0; |
| 4026 | NAPI_GRO_CB(skb)->udp_mark = 0; | 4026 | NAPI_GRO_CB(skb)->udp_mark = 0; |
| 4027 | NAPI_GRO_CB(skb)->gro_remcsum_start = 0; | ||
| 4027 | 4028 | ||
| 4028 | /* Setup for GRO checksum validation */ | 4029 | /* Setup for GRO checksum validation */ |
| 4029 | switch (skb->ip_summed) { | 4030 | switch (skb->ip_summed) { |
| @@ -5335,7 +5336,7 @@ EXPORT_SYMBOL(netdev_upper_dev_unlink); | |||
| 5335 | /** | 5336 | /** |
| 5336 | * netdev_bonding_info_change - Dispatch event about slave change | 5337 | * netdev_bonding_info_change - Dispatch event about slave change |
| 5337 | * @dev: device | 5338 | * @dev: device |
| 5338 | * @netdev_bonding_info: info to dispatch | 5339 | * @bonding_info: info to dispatch |
| 5339 | * | 5340 | * |
| 5340 | * Send NETDEV_BONDING_INFO to netdev notifiers with info. | 5341 | * Send NETDEV_BONDING_INFO to netdev notifiers with info. |
| 5341 | * The caller must hold the RTNL lock. | 5342 | * The caller must hold the RTNL lock. |
diff --git a/net/core/filter.c b/net/core/filter.c index ec9baea10c16..f6bdc2b1ba01 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
| @@ -531,7 +531,7 @@ do_pass: | |||
| 531 | *insn = BPF_LDX_MEM(BPF_W, BPF_REG_A, BPF_REG_CTX, fp->k); | 531 | *insn = BPF_LDX_MEM(BPF_W, BPF_REG_A, BPF_REG_CTX, fp->k); |
| 532 | break; | 532 | break; |
| 533 | 533 | ||
| 534 | /* Unkown instruction. */ | 534 | /* Unknown instruction. */ |
| 535 | default: | 535 | default: |
| 536 | goto err; | 536 | goto err; |
| 537 | } | 537 | } |
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 9fa25b0ea145..b4899f5b7388 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
| @@ -97,7 +97,7 @@ | |||
| 97 | * New xmit() return, do_div and misc clean up by Stephen Hemminger | 97 | * New xmit() return, do_div and misc clean up by Stephen Hemminger |
| 98 | * <shemminger@osdl.org> 040923 | 98 | * <shemminger@osdl.org> 040923 |
| 99 | * | 99 | * |
| 100 | * Randy Dunlap fixed u64 printk compiler waring | 100 | * Randy Dunlap fixed u64 printk compiler warning |
| 101 | * | 101 | * |
| 102 | * Remove FCS from BW calculation. Lennert Buytenhek <buytenh@wantstofly.org> | 102 | * Remove FCS from BW calculation. Lennert Buytenhek <buytenh@wantstofly.org> |
| 103 | * New time handling. Lennert Buytenhek <buytenh@wantstofly.org> 041213 | 103 | * New time handling. Lennert Buytenhek <buytenh@wantstofly.org> 041213 |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 5be499b6a2d2..ab293a3066b3 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
| @@ -2162,7 +2162,14 @@ replay: | |||
| 2162 | } | 2162 | } |
| 2163 | err = rtnl_configure_link(dev, ifm); | 2163 | err = rtnl_configure_link(dev, ifm); |
| 2164 | if (err < 0) { | 2164 | if (err < 0) { |
| 2165 | unregister_netdevice(dev); | 2165 | if (ops->newlink) { |
| 2166 | LIST_HEAD(list_kill); | ||
| 2167 | |||
| 2168 | ops->dellink(dev, &list_kill); | ||
| 2169 | unregister_netdevice_many(&list_kill); | ||
| 2170 | } else { | ||
| 2171 | unregister_netdevice(dev); | ||
| 2172 | } | ||
| 2166 | goto out; | 2173 | goto out; |
| 2167 | } | 2174 | } |
| 2168 | 2175 | ||
diff --git a/net/dsa/slave.c b/net/dsa/slave.c index d104ae15836f..f23deadf42a0 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c | |||
| @@ -521,10 +521,13 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p, | |||
| 521 | struct device_node *phy_dn, *port_dn; | 521 | struct device_node *phy_dn, *port_dn; |
| 522 | bool phy_is_fixed = false; | 522 | bool phy_is_fixed = false; |
| 523 | u32 phy_flags = 0; | 523 | u32 phy_flags = 0; |
| 524 | int ret; | 524 | int mode, ret; |
| 525 | 525 | ||
| 526 | port_dn = cd->port_dn[p->port]; | 526 | port_dn = cd->port_dn[p->port]; |
| 527 | p->phy_interface = of_get_phy_mode(port_dn); | 527 | mode = of_get_phy_mode(port_dn); |
| 528 | if (mode < 0) | ||
| 529 | mode = PHY_INTERFACE_MODE_NA; | ||
| 530 | p->phy_interface = mode; | ||
| 528 | 531 | ||
| 529 | phy_dn = of_parse_phandle(port_dn, "phy-handle", 0); | 532 | phy_dn = of_parse_phandle(port_dn, "phy-handle", 0); |
| 530 | if (of_phy_is_fixed_link(port_dn)) { | 533 | if (of_phy_is_fixed_link(port_dn)) { |
| @@ -559,6 +562,8 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p, | |||
| 559 | if (!p->phy) | 562 | if (!p->phy) |
| 560 | return -ENODEV; | 563 | return -ENODEV; |
| 561 | 564 | ||
| 565 | /* Use already configured phy mode */ | ||
| 566 | p->phy_interface = p->phy->interface; | ||
| 562 | phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link, | 567 | phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link, |
| 563 | p->phy_interface); | 568 | p->phy_interface); |
| 564 | } else { | 569 | } else { |
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index f0b4a31d7bd6..3a8985c94581 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
| @@ -1186,7 +1186,7 @@ __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope) | |||
| 1186 | no_in_dev: | 1186 | no_in_dev: |
| 1187 | 1187 | ||
| 1188 | /* Not loopback addresses on loopback should be preferred | 1188 | /* Not loopback addresses on loopback should be preferred |
| 1189 | in this case. It is importnat that lo is the first interface | 1189 | in this case. It is important that lo is the first interface |
| 1190 | in dev_base list. | 1190 | in dev_base list. |
| 1191 | */ | 1191 | */ |
| 1192 | for_each_netdev_rcu(net, dev) { | 1192 | for_each_netdev_rcu(net, dev) { |
diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c index 92ddea1e6457..ff069f6597ac 100644 --- a/net/ipv4/fou.c +++ b/net/ipv4/fou.c | |||
| @@ -22,14 +22,18 @@ static LIST_HEAD(fou_list); | |||
| 22 | struct fou { | 22 | struct fou { |
| 23 | struct socket *sock; | 23 | struct socket *sock; |
| 24 | u8 protocol; | 24 | u8 protocol; |
| 25 | u8 flags; | ||
| 25 | u16 port; | 26 | u16 port; |
| 26 | struct udp_offload udp_offloads; | 27 | struct udp_offload udp_offloads; |
| 27 | struct list_head list; | 28 | struct list_head list; |
| 28 | }; | 29 | }; |
| 29 | 30 | ||
| 31 | #define FOU_F_REMCSUM_NOPARTIAL BIT(0) | ||
| 32 | |||
| 30 | struct fou_cfg { | 33 | struct fou_cfg { |
| 31 | u16 type; | 34 | u16 type; |
| 32 | u8 protocol; | 35 | u8 protocol; |
| 36 | u8 flags; | ||
| 33 | struct udp_port_cfg udp_config; | 37 | struct udp_port_cfg udp_config; |
| 34 | }; | 38 | }; |
| 35 | 39 | ||
| @@ -64,24 +68,20 @@ static int fou_udp_recv(struct sock *sk, struct sk_buff *skb) | |||
| 64 | } | 68 | } |
| 65 | 69 | ||
| 66 | static struct guehdr *gue_remcsum(struct sk_buff *skb, struct guehdr *guehdr, | 70 | static struct guehdr *gue_remcsum(struct sk_buff *skb, struct guehdr *guehdr, |
| 67 | void *data, size_t hdrlen, u8 ipproto) | 71 | void *data, size_t hdrlen, u8 ipproto, |
| 72 | bool nopartial) | ||
| 68 | { | 73 | { |
| 69 | __be16 *pd = data; | 74 | __be16 *pd = data; |
| 70 | size_t start = ntohs(pd[0]); | 75 | size_t start = ntohs(pd[0]); |
| 71 | size_t offset = ntohs(pd[1]); | 76 | size_t offset = ntohs(pd[1]); |
| 72 | size_t plen = hdrlen + max_t(size_t, offset + sizeof(u16), start); | 77 | size_t plen = hdrlen + max_t(size_t, offset + sizeof(u16), start); |
| 73 | 78 | ||
| 74 | if (skb->remcsum_offload) { | ||
| 75 | /* Already processed in GRO path */ | ||
| 76 | skb->remcsum_offload = 0; | ||
| 77 | return guehdr; | ||
| 78 | } | ||
| 79 | |||
| 80 | if (!pskb_may_pull(skb, plen)) | 79 | if (!pskb_may_pull(skb, plen)) |
| 81 | return NULL; | 80 | return NULL; |
| 82 | guehdr = (struct guehdr *)&udp_hdr(skb)[1]; | 81 | guehdr = (struct guehdr *)&udp_hdr(skb)[1]; |
| 83 | 82 | ||
| 84 | skb_remcsum_process(skb, (void *)guehdr + hdrlen, start, offset); | 83 | skb_remcsum_process(skb, (void *)guehdr + hdrlen, |
| 84 | start, offset, nopartial); | ||
| 85 | 85 | ||
| 86 | return guehdr; | 86 | return guehdr; |
| 87 | } | 87 | } |
| @@ -142,7 +142,9 @@ static int gue_udp_recv(struct sock *sk, struct sk_buff *skb) | |||
| 142 | 142 | ||
| 143 | if (flags & GUE_PFLAG_REMCSUM) { | 143 | if (flags & GUE_PFLAG_REMCSUM) { |
| 144 | guehdr = gue_remcsum(skb, guehdr, data + doffset, | 144 | guehdr = gue_remcsum(skb, guehdr, data + doffset, |
| 145 | hdrlen, guehdr->proto_ctype); | 145 | hdrlen, guehdr->proto_ctype, |
| 146 | !!(fou->flags & | ||
| 147 | FOU_F_REMCSUM_NOPARTIAL)); | ||
| 146 | if (!guehdr) | 148 | if (!guehdr) |
| 147 | goto drop; | 149 | goto drop; |
| 148 | 150 | ||
| @@ -214,7 +216,8 @@ out_unlock: | |||
| 214 | 216 | ||
| 215 | static struct guehdr *gue_gro_remcsum(struct sk_buff *skb, unsigned int off, | 217 | static struct guehdr *gue_gro_remcsum(struct sk_buff *skb, unsigned int off, |
| 216 | struct guehdr *guehdr, void *data, | 218 | struct guehdr *guehdr, void *data, |
| 217 | size_t hdrlen, u8 ipproto) | 219 | size_t hdrlen, u8 ipproto, |
| 220 | struct gro_remcsum *grc, bool nopartial) | ||
| 218 | { | 221 | { |
| 219 | __be16 *pd = data; | 222 | __be16 *pd = data; |
| 220 | size_t start = ntohs(pd[0]); | 223 | size_t start = ntohs(pd[0]); |
| @@ -222,7 +225,7 @@ static struct guehdr *gue_gro_remcsum(struct sk_buff *skb, unsigned int off, | |||
| 222 | size_t plen = hdrlen + max_t(size_t, offset + sizeof(u16), start); | 225 | size_t plen = hdrlen + max_t(size_t, offset + sizeof(u16), start); |
| 223 | 226 | ||
| 224 | if (skb->remcsum_offload) | 227 | if (skb->remcsum_offload) |
| 225 | return guehdr; | 228 | return NULL; |
| 226 | 229 | ||
| 227 | if (!NAPI_GRO_CB(skb)->csum_valid) | 230 | if (!NAPI_GRO_CB(skb)->csum_valid) |
| 228 | return NULL; | 231 | return NULL; |
| @@ -234,7 +237,8 @@ static struct guehdr *gue_gro_remcsum(struct sk_buff *skb, unsigned int off, | |||
| 234 | return NULL; | 237 | return NULL; |
| 235 | } | 238 | } |
| 236 | 239 | ||
| 237 | skb_gro_remcsum_process(skb, (void *)guehdr + hdrlen, start, offset); | 240 | skb_gro_remcsum_process(skb, (void *)guehdr + hdrlen, |
| 241 | start, offset, grc, nopartial); | ||
| 238 | 242 | ||
| 239 | skb->remcsum_offload = 1; | 243 | skb->remcsum_offload = 1; |
| 240 | 244 | ||
| @@ -254,6 +258,10 @@ static struct sk_buff **gue_gro_receive(struct sk_buff **head, | |||
| 254 | void *data; | 258 | void *data; |
| 255 | u16 doffset = 0; | 259 | u16 doffset = 0; |
| 256 | int flush = 1; | 260 | int flush = 1; |
| 261 | struct fou *fou = container_of(uoff, struct fou, udp_offloads); | ||
| 262 | struct gro_remcsum grc; | ||
| 263 | |||
| 264 | skb_gro_remcsum_init(&grc); | ||
| 257 | 265 | ||
| 258 | off = skb_gro_offset(skb); | 266 | off = skb_gro_offset(skb); |
| 259 | len = off + sizeof(*guehdr); | 267 | len = off + sizeof(*guehdr); |
| @@ -295,7 +303,9 @@ static struct sk_buff **gue_gro_receive(struct sk_buff **head, | |||
| 295 | if (flags & GUE_PFLAG_REMCSUM) { | 303 | if (flags & GUE_PFLAG_REMCSUM) { |
| 296 | guehdr = gue_gro_remcsum(skb, off, guehdr, | 304 | guehdr = gue_gro_remcsum(skb, off, guehdr, |
| 297 | data + doffset, hdrlen, | 305 | data + doffset, hdrlen, |
| 298 | guehdr->proto_ctype); | 306 | guehdr->proto_ctype, &grc, |
| 307 | !!(fou->flags & | ||
| 308 | FOU_F_REMCSUM_NOPARTIAL)); | ||
| 299 | if (!guehdr) | 309 | if (!guehdr) |
| 300 | goto out; | 310 | goto out; |
| 301 | 311 | ||
| @@ -345,6 +355,7 @@ out_unlock: | |||
| 345 | rcu_read_unlock(); | 355 | rcu_read_unlock(); |
| 346 | out: | 356 | out: |
| 347 | NAPI_GRO_CB(skb)->flush |= flush; | 357 | NAPI_GRO_CB(skb)->flush |= flush; |
| 358 | skb_gro_remcsum_cleanup(skb, &grc); | ||
| 348 | 359 | ||
| 349 | return pp; | 360 | return pp; |
| 350 | } | 361 | } |
| @@ -455,6 +466,7 @@ static int fou_create(struct net *net, struct fou_cfg *cfg, | |||
| 455 | 466 | ||
| 456 | sk = sock->sk; | 467 | sk = sock->sk; |
| 457 | 468 | ||
| 469 | fou->flags = cfg->flags; | ||
| 458 | fou->port = cfg->udp_config.local_udp_port; | 470 | fou->port = cfg->udp_config.local_udp_port; |
| 459 | 471 | ||
| 460 | /* Initial for fou type */ | 472 | /* Initial for fou type */ |
| @@ -541,6 +553,7 @@ static struct nla_policy fou_nl_policy[FOU_ATTR_MAX + 1] = { | |||
| 541 | [FOU_ATTR_AF] = { .type = NLA_U8, }, | 553 | [FOU_ATTR_AF] = { .type = NLA_U8, }, |
| 542 | [FOU_ATTR_IPPROTO] = { .type = NLA_U8, }, | 554 | [FOU_ATTR_IPPROTO] = { .type = NLA_U8, }, |
| 543 | [FOU_ATTR_TYPE] = { .type = NLA_U8, }, | 555 | [FOU_ATTR_TYPE] = { .type = NLA_U8, }, |
| 556 | [FOU_ATTR_REMCSUM_NOPARTIAL] = { .type = NLA_FLAG, }, | ||
| 544 | }; | 557 | }; |
| 545 | 558 | ||
| 546 | static int parse_nl_config(struct genl_info *info, | 559 | static int parse_nl_config(struct genl_info *info, |
| @@ -571,6 +584,9 @@ static int parse_nl_config(struct genl_info *info, | |||
| 571 | if (info->attrs[FOU_ATTR_TYPE]) | 584 | if (info->attrs[FOU_ATTR_TYPE]) |
| 572 | cfg->type = nla_get_u8(info->attrs[FOU_ATTR_TYPE]); | 585 | cfg->type = nla_get_u8(info->attrs[FOU_ATTR_TYPE]); |
| 573 | 586 | ||
| 587 | if (info->attrs[FOU_ATTR_REMCSUM_NOPARTIAL]) | ||
| 588 | cfg->flags |= FOU_F_REMCSUM_NOPARTIAL; | ||
| 589 | |||
| 574 | return 0; | 590 | return 0; |
| 575 | } | 591 | } |
| 576 | 592 | ||
diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c index 53db2c309572..ea82fd492c1b 100644 --- a/net/ipv4/tcp_fastopen.c +++ b/net/ipv4/tcp_fastopen.c | |||
| @@ -134,6 +134,7 @@ static bool tcp_fastopen_create_child(struct sock *sk, | |||
| 134 | struct tcp_sock *tp; | 134 | struct tcp_sock *tp; |
| 135 | struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue; | 135 | struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue; |
| 136 | struct sock *child; | 136 | struct sock *child; |
| 137 | u32 end_seq; | ||
| 137 | 138 | ||
| 138 | req->num_retrans = 0; | 139 | req->num_retrans = 0; |
| 139 | req->num_timeout = 0; | 140 | req->num_timeout = 0; |
| @@ -185,20 +186,35 @@ static bool tcp_fastopen_create_child(struct sock *sk, | |||
| 185 | 186 | ||
| 186 | /* Queue the data carried in the SYN packet. We need to first | 187 | /* Queue the data carried in the SYN packet. We need to first |
| 187 | * bump skb's refcnt because the caller will attempt to free it. | 188 | * bump skb's refcnt because the caller will attempt to free it. |
| 189 | * Note that IPv6 might also have used skb_get() trick | ||
| 190 | * in tcp_v6_conn_request() to keep this SYN around (treq->pktopts) | ||
| 191 | * So we need to eventually get a clone of the packet, | ||
| 192 | * before inserting it in sk_receive_queue. | ||
| 188 | * | 193 | * |
| 189 | * XXX (TFO) - we honor a zero-payload TFO request for now, | 194 | * XXX (TFO) - we honor a zero-payload TFO request for now, |
| 190 | * (any reason not to?) but no need to queue the skb since | 195 | * (any reason not to?) but no need to queue the skb since |
| 191 | * there is no data. How about SYN+FIN? | 196 | * there is no data. How about SYN+FIN? |
| 192 | */ | 197 | */ |
| 193 | if (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq + 1) { | 198 | end_seq = TCP_SKB_CB(skb)->end_seq; |
| 194 | skb = skb_get(skb); | 199 | if (end_seq != TCP_SKB_CB(skb)->seq + 1) { |
| 195 | skb_dst_drop(skb); | 200 | struct sk_buff *skb2; |
| 196 | __skb_pull(skb, tcp_hdr(skb)->doff * 4); | 201 | |
| 197 | skb_set_owner_r(skb, child); | 202 | if (unlikely(skb_shared(skb))) |
| 198 | __skb_queue_tail(&child->sk_receive_queue, skb); | 203 | skb2 = skb_clone(skb, GFP_ATOMIC); |
| 199 | tp->syn_data_acked = 1; | 204 | else |
| 205 | skb2 = skb_get(skb); | ||
| 206 | |||
| 207 | if (likely(skb2)) { | ||
| 208 | skb_dst_drop(skb2); | ||
| 209 | __skb_pull(skb2, tcp_hdrlen(skb)); | ||
| 210 | skb_set_owner_r(skb2, child); | ||
| 211 | __skb_queue_tail(&child->sk_receive_queue, skb2); | ||
| 212 | tp->syn_data_acked = 1; | ||
| 213 | } else { | ||
| 214 | end_seq = TCP_SKB_CB(skb)->seq + 1; | ||
| 215 | } | ||
| 200 | } | 216 | } |
| 201 | tcp_rsk(req)->rcv_nxt = tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq; | 217 | tcp_rsk(req)->rcv_nxt = tp->rcv_nxt = end_seq; |
| 202 | sk->sk_data_ready(sk); | 218 | sk->sk_data_ready(sk); |
| 203 | bh_unlock_sock(child); | 219 | bh_unlock_sock(child); |
| 204 | sock_put(child); | 220 | sock_put(child); |
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index d10f6f4ead27..4915d8284a86 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c | |||
| @@ -402,6 +402,13 @@ int udp_gro_complete(struct sk_buff *skb, int nhoff) | |||
| 402 | } | 402 | } |
| 403 | 403 | ||
| 404 | rcu_read_unlock(); | 404 | rcu_read_unlock(); |
| 405 | |||
| 406 | if (skb->remcsum_offload) | ||
| 407 | skb_shinfo(skb)->gso_type |= SKB_GSO_TUNNEL_REMCSUM; | ||
| 408 | |||
| 409 | skb->encapsulation = 1; | ||
| 410 | skb_set_inner_mac_header(skb, nhoff + sizeof(struct udphdr)); | ||
| 411 | |||
| 405 | return err; | 412 | return err; |
| 406 | } | 413 | } |
| 407 | 414 | ||
| @@ -410,9 +417,13 @@ static int udp4_gro_complete(struct sk_buff *skb, int nhoff) | |||
| 410 | const struct iphdr *iph = ip_hdr(skb); | 417 | const struct iphdr *iph = ip_hdr(skb); |
| 411 | struct udphdr *uh = (struct udphdr *)(skb->data + nhoff); | 418 | struct udphdr *uh = (struct udphdr *)(skb->data + nhoff); |
| 412 | 419 | ||
| 413 | if (uh->check) | 420 | if (uh->check) { |
| 421 | skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL_CSUM; | ||
| 414 | uh->check = ~udp_v4_check(skb->len - nhoff, iph->saddr, | 422 | uh->check = ~udp_v4_check(skb->len - nhoff, iph->saddr, |
| 415 | iph->daddr, 0); | 423 | iph->daddr, 0); |
| 424 | } else { | ||
| 425 | skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL; | ||
| 426 | } | ||
| 416 | 427 | ||
| 417 | return udp_gro_complete(skb, nhoff); | 428 | return udp_gro_complete(skb, nhoff); |
| 418 | } | 429 | } |
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 2f780cba6e12..f45d6db50a45 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c | |||
| @@ -172,7 +172,7 @@ static void __net_exit ip6_fl_purge(struct net *net) | |||
| 172 | { | 172 | { |
| 173 | int i; | 173 | int i; |
| 174 | 174 | ||
| 175 | spin_lock(&ip6_fl_lock); | 175 | spin_lock_bh(&ip6_fl_lock); |
| 176 | for (i = 0; i <= FL_HASH_MASK; i++) { | 176 | for (i = 0; i <= FL_HASH_MASK; i++) { |
| 177 | struct ip6_flowlabel *fl; | 177 | struct ip6_flowlabel *fl; |
| 178 | struct ip6_flowlabel __rcu **flp; | 178 | struct ip6_flowlabel __rcu **flp; |
| @@ -190,7 +190,7 @@ static void __net_exit ip6_fl_purge(struct net *net) | |||
| 190 | flp = &fl->next; | 190 | flp = &fl->next; |
| 191 | } | 191 | } |
| 192 | } | 192 | } |
| 193 | spin_unlock(&ip6_fl_lock); | 193 | spin_unlock_bh(&ip6_fl_lock); |
| 194 | } | 194 | } |
| 195 | 195 | ||
| 196 | static struct ip6_flowlabel *fl_intern(struct net *net, | 196 | static struct ip6_flowlabel *fl_intern(struct net *net, |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index d33df4cbd872..7deebf102cba 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
| @@ -1273,7 +1273,7 @@ emsgsize: | |||
| 1273 | /* If this is the first and only packet and device | 1273 | /* If this is the first and only packet and device |
| 1274 | * supports checksum offloading, let's use it. | 1274 | * supports checksum offloading, let's use it. |
| 1275 | */ | 1275 | */ |
| 1276 | if (!skb && | 1276 | if (!skb && sk->sk_protocol == IPPROTO_UDP && |
| 1277 | length + fragheaderlen < mtu && | 1277 | length + fragheaderlen < mtu && |
| 1278 | rt->dst.dev->features & NETIF_F_V6_CSUM && | 1278 | rt->dst.dev->features & NETIF_F_V6_CSUM && |
| 1279 | !exthdrlen) | 1279 | !exthdrlen) |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 98565ce0ebcd..4688bd4d7f59 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
| @@ -141,7 +141,7 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old) | |||
| 141 | u32 *p = NULL; | 141 | u32 *p = NULL; |
| 142 | 142 | ||
| 143 | if (!(rt->dst.flags & DST_HOST)) | 143 | if (!(rt->dst.flags & DST_HOST)) |
| 144 | return NULL; | 144 | return dst_cow_metrics_generic(dst, old); |
| 145 | 145 | ||
| 146 | peer = rt6_get_peer_create(rt); | 146 | peer = rt6_get_peer_create(rt); |
| 147 | if (peer) { | 147 | if (peer) { |
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c index a56276996b72..ab889bb16b3c 100644 --- a/net/ipv6/udp_offload.c +++ b/net/ipv6/udp_offload.c | |||
| @@ -161,9 +161,13 @@ static int udp6_gro_complete(struct sk_buff *skb, int nhoff) | |||
| 161 | const struct ipv6hdr *ipv6h = ipv6_hdr(skb); | 161 | const struct ipv6hdr *ipv6h = ipv6_hdr(skb); |
| 162 | struct udphdr *uh = (struct udphdr *)(skb->data + nhoff); | 162 | struct udphdr *uh = (struct udphdr *)(skb->data + nhoff); |
| 163 | 163 | ||
| 164 | if (uh->check) | 164 | if (uh->check) { |
| 165 | skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL_CSUM; | ||
| 165 | uh->check = ~udp_v6_check(skb->len - nhoff, &ipv6h->saddr, | 166 | uh->check = ~udp_v6_check(skb->len - nhoff, &ipv6h->saddr, |
| 166 | &ipv6h->daddr, 0); | 167 | &ipv6h->daddr, 0); |
| 168 | } else { | ||
| 169 | skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL; | ||
| 170 | } | ||
| 167 | 171 | ||
| 168 | return udp_gro_complete(skb, nhoff); | 172 | return udp_gro_complete(skb, nhoff); |
| 169 | } | 173 | } |
diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c index 265e190f2218..c598f74063a1 100644 --- a/net/netfilter/nft_compat.c +++ b/net/netfilter/nft_compat.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/netfilter/x_tables.h> | 19 | #include <linux/netfilter/x_tables.h> |
| 20 | #include <linux/netfilter_ipv4/ip_tables.h> | 20 | #include <linux/netfilter_ipv4/ip_tables.h> |
| 21 | #include <linux/netfilter_ipv6/ip6_tables.h> | 21 | #include <linux/netfilter_ipv6/ip6_tables.h> |
| 22 | #include <linux/netfilter_bridge/ebtables.h> | ||
| 22 | #include <net/netfilter/nf_tables.h> | 23 | #include <net/netfilter/nf_tables.h> |
| 23 | 24 | ||
| 24 | static int nft_compat_chain_validate_dependency(const char *tablename, | 25 | static int nft_compat_chain_validate_dependency(const char *tablename, |
| @@ -40,6 +41,7 @@ static int nft_compat_chain_validate_dependency(const char *tablename, | |||
| 40 | union nft_entry { | 41 | union nft_entry { |
| 41 | struct ipt_entry e4; | 42 | struct ipt_entry e4; |
| 42 | struct ip6t_entry e6; | 43 | struct ip6t_entry e6; |
| 44 | struct ebt_entry ebt; | ||
| 43 | }; | 45 | }; |
| 44 | 46 | ||
| 45 | static inline void | 47 | static inline void |
| @@ -50,9 +52,9 @@ nft_compat_set_par(struct xt_action_param *par, void *xt, const void *xt_info) | |||
| 50 | par->hotdrop = false; | 52 | par->hotdrop = false; |
| 51 | } | 53 | } |
| 52 | 54 | ||
| 53 | static void nft_target_eval(const struct nft_expr *expr, | 55 | static void nft_target_eval_xt(const struct nft_expr *expr, |
| 54 | struct nft_data data[NFT_REG_MAX + 1], | 56 | struct nft_data data[NFT_REG_MAX + 1], |
| 55 | const struct nft_pktinfo *pkt) | 57 | const struct nft_pktinfo *pkt) |
| 56 | { | 58 | { |
| 57 | void *info = nft_expr_priv(expr); | 59 | void *info = nft_expr_priv(expr); |
| 58 | struct xt_target *target = expr->ops->data; | 60 | struct xt_target *target = expr->ops->data; |
| @@ -66,7 +68,7 @@ static void nft_target_eval(const struct nft_expr *expr, | |||
| 66 | if (pkt->xt.hotdrop) | 68 | if (pkt->xt.hotdrop) |
| 67 | ret = NF_DROP; | 69 | ret = NF_DROP; |
| 68 | 70 | ||
| 69 | switch(ret) { | 71 | switch (ret) { |
| 70 | case XT_CONTINUE: | 72 | case XT_CONTINUE: |
| 71 | data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; | 73 | data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; |
| 72 | break; | 74 | break; |
| @@ -74,7 +76,41 @@ static void nft_target_eval(const struct nft_expr *expr, | |||
| 74 | data[NFT_REG_VERDICT].verdict = ret; | 76 | data[NFT_REG_VERDICT].verdict = ret; |
| 75 | break; | 77 | break; |
| 76 | } | 78 | } |
| 77 | return; | 79 | } |
| 80 | |||
| 81 | static void nft_target_eval_bridge(const struct nft_expr *expr, | ||
| 82 | struct nft_data data[NFT_REG_MAX + 1], | ||
| 83 | const struct nft_pktinfo *pkt) | ||
| 84 | { | ||
| 85 | void *info = nft_expr_priv(expr); | ||
| 86 | struct xt_target *target = expr->ops->data; | ||
| 87 | struct sk_buff *skb = pkt->skb; | ||
| 88 | int ret; | ||
| 89 | |||
| 90 | nft_compat_set_par((struct xt_action_param *)&pkt->xt, target, info); | ||
| 91 | |||
| 92 | ret = target->target(skb, &pkt->xt); | ||
| 93 | |||
| 94 | if (pkt->xt.hotdrop) | ||
| 95 | ret = NF_DROP; | ||
| 96 | |||
| 97 | switch (ret) { | ||
| 98 | case EBT_ACCEPT: | ||
| 99 | data[NFT_REG_VERDICT].verdict = NF_ACCEPT; | ||
| 100 | break; | ||
| 101 | case EBT_DROP: | ||
| 102 | data[NFT_REG_VERDICT].verdict = NF_DROP; | ||
| 103 | break; | ||
| 104 | case EBT_CONTINUE: | ||
| 105 | data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; | ||
| 106 | break; | ||
| 107 | case EBT_RETURN: | ||
| 108 | data[NFT_REG_VERDICT].verdict = NFT_RETURN; | ||
| 109 | break; | ||
| 110 | default: | ||
| 111 | data[NFT_REG_VERDICT].verdict = ret; | ||
| 112 | break; | ||
| 113 | } | ||
| 78 | } | 114 | } |
| 79 | 115 | ||
| 80 | static const struct nla_policy nft_target_policy[NFTA_TARGET_MAX + 1] = { | 116 | static const struct nla_policy nft_target_policy[NFTA_TARGET_MAX + 1] = { |
| @@ -100,6 +136,10 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par, | |||
| 100 | entry->e6.ipv6.proto = proto; | 136 | entry->e6.ipv6.proto = proto; |
| 101 | entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0; | 137 | entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0; |
| 102 | break; | 138 | break; |
| 139 | case NFPROTO_BRIDGE: | ||
| 140 | entry->ebt.ethproto = proto; | ||
| 141 | entry->ebt.invflags = inv ? EBT_IPROTO : 0; | ||
| 142 | break; | ||
| 103 | } | 143 | } |
| 104 | par->entryinfo = entry; | 144 | par->entryinfo = entry; |
| 105 | par->target = target; | 145 | par->target = target; |
| @@ -307,6 +347,10 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx, | |||
| 307 | entry->e6.ipv6.proto = proto; | 347 | entry->e6.ipv6.proto = proto; |
| 308 | entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0; | 348 | entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0; |
| 309 | break; | 349 | break; |
| 350 | case NFPROTO_BRIDGE: | ||
| 351 | entry->ebt.ethproto = proto; | ||
| 352 | entry->ebt.invflags = inv ? EBT_IPROTO : 0; | ||
| 353 | break; | ||
| 310 | } | 354 | } |
| 311 | par->entryinfo = entry; | 355 | par->entryinfo = entry; |
| 312 | par->match = match; | 356 | par->match = match; |
| @@ -490,6 +534,9 @@ nfnl_compat_get(struct sock *nfnl, struct sk_buff *skb, | |||
| 490 | case AF_INET6: | 534 | case AF_INET6: |
| 491 | fmt = "ip6t_%s"; | 535 | fmt = "ip6t_%s"; |
| 492 | break; | 536 | break; |
| 537 | case NFPROTO_BRIDGE: | ||
| 538 | fmt = "ebt_%s"; | ||
| 539 | break; | ||
| 493 | default: | 540 | default: |
| 494 | pr_err("nft_compat: unsupported protocol %d\n", | 541 | pr_err("nft_compat: unsupported protocol %d\n", |
| 495 | nfmsg->nfgen_family); | 542 | nfmsg->nfgen_family); |
| @@ -663,13 +710,17 @@ nft_target_select_ops(const struct nft_ctx *ctx, | |||
| 663 | 710 | ||
| 664 | nft_target->ops.type = &nft_target_type; | 711 | nft_target->ops.type = &nft_target_type; |
| 665 | nft_target->ops.size = NFT_EXPR_SIZE(XT_ALIGN(target->targetsize)); | 712 | nft_target->ops.size = NFT_EXPR_SIZE(XT_ALIGN(target->targetsize)); |
| 666 | nft_target->ops.eval = nft_target_eval; | ||
| 667 | nft_target->ops.init = nft_target_init; | 713 | nft_target->ops.init = nft_target_init; |
| 668 | nft_target->ops.destroy = nft_target_destroy; | 714 | nft_target->ops.destroy = nft_target_destroy; |
| 669 | nft_target->ops.dump = nft_target_dump; | 715 | nft_target->ops.dump = nft_target_dump; |
| 670 | nft_target->ops.validate = nft_target_validate; | 716 | nft_target->ops.validate = nft_target_validate; |
| 671 | nft_target->ops.data = target; | 717 | nft_target->ops.data = target; |
| 672 | 718 | ||
| 719 | if (family == NFPROTO_BRIDGE) | ||
| 720 | nft_target->ops.eval = nft_target_eval_bridge; | ||
| 721 | else | ||
| 722 | nft_target->ops.eval = nft_target_eval_xt; | ||
| 723 | |||
| 673 | list_add(&nft_target->head, &nft_target_list); | 724 | list_add(&nft_target->head, &nft_target_list); |
| 674 | 725 | ||
| 675 | return &nft_target->ops; | 726 | return &nft_target->ops; |
diff --git a/net/netfilter/nft_lookup.c b/net/netfilter/nft_lookup.c index 6404a726d17b..9615b8b9fb37 100644 --- a/net/netfilter/nft_lookup.c +++ b/net/netfilter/nft_lookup.c | |||
| @@ -39,6 +39,7 @@ static void nft_lookup_eval(const struct nft_expr *expr, | |||
| 39 | 39 | ||
| 40 | static const struct nla_policy nft_lookup_policy[NFTA_LOOKUP_MAX + 1] = { | 40 | static const struct nla_policy nft_lookup_policy[NFTA_LOOKUP_MAX + 1] = { |
| 41 | [NFTA_LOOKUP_SET] = { .type = NLA_STRING }, | 41 | [NFTA_LOOKUP_SET] = { .type = NLA_STRING }, |
| 42 | [NFTA_LOOKUP_SET_ID] = { .type = NLA_U32 }, | ||
| 42 | [NFTA_LOOKUP_SREG] = { .type = NLA_U32 }, | 43 | [NFTA_LOOKUP_SREG] = { .type = NLA_U32 }, |
| 43 | [NFTA_LOOKUP_DREG] = { .type = NLA_U32 }, | 44 | [NFTA_LOOKUP_DREG] = { .type = NLA_U32 }, |
| 44 | }; | 45 | }; |
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c index e2c348b8baca..50ec42f170a0 100644 --- a/net/openvswitch/flow.c +++ b/net/openvswitch/flow.c | |||
| @@ -717,6 +717,8 @@ int ovs_flow_key_extract_userspace(const struct nlattr *attr, | |||
| 717 | { | 717 | { |
| 718 | int err; | 718 | int err; |
| 719 | 719 | ||
| 720 | memset(key, 0, OVS_SW_FLOW_KEY_METADATA_SIZE); | ||
| 721 | |||
| 720 | /* Extract metadata from netlink attributes. */ | 722 | /* Extract metadata from netlink attributes. */ |
| 721 | err = ovs_nla_get_flow_metadata(attr, key, log); | 723 | err = ovs_nla_get_flow_metadata(attr, key, log); |
| 722 | if (err) | 724 | if (err) |
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c index 993281e6278d..216f20b90aa5 100644 --- a/net/openvswitch/flow_netlink.c +++ b/net/openvswitch/flow_netlink.c | |||
| @@ -1516,7 +1516,7 @@ int ovs_nla_put_identifier(const struct sw_flow *flow, struct sk_buff *skb) | |||
| 1516 | /* Called with ovs_mutex or RCU read lock. */ | 1516 | /* Called with ovs_mutex or RCU read lock. */ |
| 1517 | int ovs_nla_put_masked_key(const struct sw_flow *flow, struct sk_buff *skb) | 1517 | int ovs_nla_put_masked_key(const struct sw_flow *flow, struct sk_buff *skb) |
| 1518 | { | 1518 | { |
| 1519 | return ovs_nla_put_key(&flow->mask->key, &flow->key, | 1519 | return ovs_nla_put_key(&flow->key, &flow->key, |
| 1520 | OVS_FLOW_ATTR_KEY, false, skb); | 1520 | OVS_FLOW_ATTR_KEY, false, skb); |
| 1521 | } | 1521 | } |
| 1522 | 1522 | ||
| @@ -1746,7 +1746,7 @@ static int validate_and_copy_set_tun(const struct nlattr *attr, | |||
| 1746 | struct sw_flow_key key; | 1746 | struct sw_flow_key key; |
| 1747 | struct ovs_tunnel_info *tun_info; | 1747 | struct ovs_tunnel_info *tun_info; |
| 1748 | struct nlattr *a; | 1748 | struct nlattr *a; |
| 1749 | int err, start, opts_type; | 1749 | int err = 0, start, opts_type; |
| 1750 | 1750 | ||
| 1751 | ovs_match_init(&match, &key, NULL); | 1751 | ovs_match_init(&match, &key, NULL); |
| 1752 | opts_type = ipv4_tun_from_nlattr(nla_data(attr), &match, false, log); | 1752 | opts_type = ipv4_tun_from_nlattr(nla_data(attr), &match, false, log); |
diff --git a/net/rds/cong.c b/net/rds/cong.c index e5b65acd650b..e6144b8246fd 100644 --- a/net/rds/cong.c +++ b/net/rds/cong.c | |||
| @@ -221,7 +221,21 @@ void rds_cong_queue_updates(struct rds_cong_map *map) | |||
| 221 | list_for_each_entry(conn, &map->m_conn_list, c_map_item) { | 221 | list_for_each_entry(conn, &map->m_conn_list, c_map_item) { |
| 222 | if (!test_and_set_bit(0, &conn->c_map_queued)) { | 222 | if (!test_and_set_bit(0, &conn->c_map_queued)) { |
| 223 | rds_stats_inc(s_cong_update_queued); | 223 | rds_stats_inc(s_cong_update_queued); |
| 224 | rds_send_xmit(conn); | 224 | /* We cannot inline the call to rds_send_xmit() here |
| 225 | * for two reasons (both pertaining to a TCP transport): | ||
| 226 | * 1. When we get here from the receive path, we | ||
| 227 | * are already holding the sock_lock (held by | ||
| 228 | * tcp_v4_rcv()). So inlining calls to | ||
| 229 | * tcp_setsockopt and/or tcp_sendmsg will deadlock | ||
| 230 | * when it tries to get the sock_lock()) | ||
| 231 | * 2. Interrupts are masked so that we can mark the | ||
| 232 | * the port congested from both send and recv paths. | ||
| 233 | * (See comment around declaration of rdc_cong_lock). | ||
| 234 | * An attempt to get the sock_lock() here will | ||
| 235 | * therefore trigger warnings. | ||
| 236 | * Defer the xmit to rds_send_worker() instead. | ||
| 237 | */ | ||
| 238 | queue_delayed_work(rds_wq, &conn->c_send_w, 0); | ||
| 225 | } | 239 | } |
| 226 | } | 240 | } |
| 227 | 241 | ||
diff --git a/samples/seccomp/bpf-fancy.c b/samples/seccomp/bpf-fancy.c index 8eb483aaec46..e8b24f443709 100644 --- a/samples/seccomp/bpf-fancy.c +++ b/samples/seccomp/bpf-fancy.c | |||
| @@ -25,7 +25,9 @@ | |||
| 25 | 25 | ||
| 26 | int main(int argc, char **argv) | 26 | int main(int argc, char **argv) |
| 27 | { | 27 | { |
| 28 | struct bpf_labels l; | 28 | struct bpf_labels l = { |
| 29 | .count = 0, | ||
| 30 | }; | ||
| 29 | static const char msg1[] = "Please type something: "; | 31 | static const char msg1[] = "Please type something: "; |
| 30 | static const char msg2[] = "You typed: "; | 32 | static const char msg2[] = "You typed: "; |
| 31 | char buf[256]; | 33 | char buf[256]; |
diff --git a/samples/seccomp/bpf-helper.c b/samples/seccomp/bpf-helper.c index 579cfe331886..05cb4d5ff9f5 100644 --- a/samples/seccomp/bpf-helper.c +++ b/samples/seccomp/bpf-helper.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #include <stdio.h> | 12 | #include <stdio.h> |
| 13 | #include <stdlib.h> | ||
| 13 | #include <string.h> | 14 | #include <string.h> |
| 14 | 15 | ||
| 15 | #include "bpf-helper.h" | 16 | #include "bpf-helper.h" |
| @@ -63,6 +64,11 @@ __u32 seccomp_bpf_label(struct bpf_labels *labels, const char *label) | |||
| 63 | { | 64 | { |
| 64 | struct __bpf_label *begin = labels->labels, *end; | 65 | struct __bpf_label *begin = labels->labels, *end; |
| 65 | int id; | 66 | int id; |
| 67 | |||
| 68 | if (labels->count == BPF_LABELS_MAX) { | ||
| 69 | fprintf(stderr, "Too many labels\n"); | ||
| 70 | exit(1); | ||
| 71 | } | ||
| 66 | if (labels->count == 0) { | 72 | if (labels->count == 0) { |
| 67 | begin->label = label; | 73 | begin->label = label; |
| 68 | begin->location = 0xffffffff; | 74 | begin->location = 0xffffffff; |
diff --git a/scripts/Makefile b/scripts/Makefile index 72902b5f2721..2016a64497ab 100644 --- a/scripts/Makefile +++ b/scripts/Makefile | |||
| @@ -36,6 +36,7 @@ subdir-$(CONFIG_MODVERSIONS) += genksyms | |||
| 36 | subdir-y += mod | 36 | subdir-y += mod |
| 37 | subdir-$(CONFIG_SECURITY_SELINUX) += selinux | 37 | subdir-$(CONFIG_SECURITY_SELINUX) += selinux |
| 38 | subdir-$(CONFIG_DTC) += dtc | 38 | subdir-$(CONFIG_DTC) += dtc |
| 39 | subdir-$(CONFIG_GDB_SCRIPTS) += gdb | ||
| 39 | 40 | ||
| 40 | # Let clean descend into subdirs | 41 | # Let clean descend into subdirs |
| 41 | subdir- += basic kconfig package | 42 | subdir- += basic kconfig package |
diff --git a/scripts/gdb/Makefile b/scripts/gdb/Makefile new file mode 100644 index 000000000000..62f5f65becfd --- /dev/null +++ b/scripts/gdb/Makefile | |||
| @@ -0,0 +1 @@ | |||
| subdir-y := linux | |||
diff --git a/scripts/gdb/linux/.gitignore b/scripts/gdb/linux/.gitignore new file mode 100644 index 000000000000..52e4e61140d1 --- /dev/null +++ b/scripts/gdb/linux/.gitignore | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | *.pyc | ||
| 2 | *.pyo | ||
diff --git a/scripts/gdb/linux/Makefile b/scripts/gdb/linux/Makefile new file mode 100644 index 000000000000..6cf1ecf61057 --- /dev/null +++ b/scripts/gdb/linux/Makefile | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | always := gdb-scripts | ||
| 2 | |||
| 3 | SRCTREE := $(shell cd $(srctree) && /bin/pwd) | ||
| 4 | |||
| 5 | $(obj)/gdb-scripts: | ||
| 6 | ifneq ($(KBUILD_SRC),) | ||
| 7 | $(Q)ln -fsn $(SRCTREE)/$(obj)/*.py $(objtree)/$(obj) | ||
| 8 | endif | ||
| 9 | @: | ||
| 10 | |||
| 11 | clean-files := *.pyc *.pyo $(if $(KBUILD_SRC),*.py) | ||
diff --git a/scripts/gdb/linux/cpus.py b/scripts/gdb/linux/cpus.py new file mode 100644 index 000000000000..4297b83fedef --- /dev/null +++ b/scripts/gdb/linux/cpus.py | |||
| @@ -0,0 +1,135 @@ | |||
| 1 | # | ||
| 2 | # gdb helper commands and functions for Linux kernel debugging | ||
| 3 | # | ||
| 4 | # per-cpu tools | ||
| 5 | # | ||
| 6 | # Copyright (c) Siemens AG, 2011-2013 | ||
| 7 | # | ||
| 8 | # Authors: | ||
| 9 | # Jan Kiszka <jan.kiszka@siemens.com> | ||
| 10 | # | ||
| 11 | # This work is licensed under the terms of the GNU GPL version 2. | ||
| 12 | # | ||
| 13 | |||
| 14 | import gdb | ||
| 15 | |||
| 16 | from linux import tasks, utils | ||
| 17 | |||
| 18 | |||
| 19 | MAX_CPUS = 4096 | ||
| 20 | |||
| 21 | |||
| 22 | def get_current_cpu(): | ||
| 23 | if utils.get_gdbserver_type() == utils.GDBSERVER_QEMU: | ||
| 24 | return gdb.selected_thread().num - 1 | ||
| 25 | elif utils.get_gdbserver_type() == utils.GDBSERVER_KGDB: | ||
| 26 | tid = gdb.selected_thread().ptid[2] | ||
| 27 | if tid > (0x100000000 - MAX_CPUS - 2): | ||
| 28 | return 0x100000000 - tid - 2 | ||
| 29 | else: | ||
| 30 | return tasks.get_thread_info(tasks.get_task_by_pid(tid))['cpu'] | ||
| 31 | else: | ||
| 32 | raise gdb.GdbError("Sorry, obtaining the current CPU is not yet " | ||
| 33 | "supported with this gdb server.") | ||
| 34 | |||
| 35 | |||
| 36 | def per_cpu(var_ptr, cpu): | ||
| 37 | if cpu == -1: | ||
| 38 | cpu = get_current_cpu() | ||
| 39 | if utils.is_target_arch("sparc:v9"): | ||
| 40 | offset = gdb.parse_and_eval( | ||
| 41 | "trap_block[{0}].__per_cpu_base".format(str(cpu))) | ||
| 42 | else: | ||
| 43 | try: | ||
| 44 | offset = gdb.parse_and_eval( | ||
| 45 | "__per_cpu_offset[{0}]".format(str(cpu))) | ||
| 46 | except gdb.error: | ||
| 47 | # !CONFIG_SMP case | ||
| 48 | offset = 0 | ||
| 49 | pointer = var_ptr.cast(utils.get_long_type()) + offset | ||
| 50 | return pointer.cast(var_ptr.type).dereference() | ||
| 51 | |||
| 52 | |||
| 53 | cpu_mask = {} | ||
| 54 | |||
| 55 | |||
| 56 | def cpu_mask_invalidate(event): | ||
| 57 | global cpu_mask | ||
| 58 | cpu_mask = {} | ||
| 59 | gdb.events.stop.disconnect(cpu_mask_invalidate) | ||
| 60 | if hasattr(gdb.events, 'new_objfile'): | ||
| 61 | gdb.events.new_objfile.disconnect(cpu_mask_invalidate) | ||
| 62 | |||
| 63 | |||
| 64 | def cpu_list(mask_name): | ||
| 65 | global cpu_mask | ||
| 66 | mask = None | ||
| 67 | if mask_name in cpu_mask: | ||
| 68 | mask = cpu_mask[mask_name] | ||
| 69 | if mask is None: | ||
| 70 | mask = gdb.parse_and_eval(mask_name + ".bits") | ||
| 71 | if hasattr(gdb, 'events'): | ||
| 72 | cpu_mask[mask_name] = mask | ||
| 73 | gdb.events.stop.connect(cpu_mask_invalidate) | ||
| 74 | if hasattr(gdb.events, 'new_objfile'): | ||
| 75 | gdb.events.new_objfile.connect(cpu_mask_invalidate) | ||
| 76 | bits_per_entry = mask[0].type.sizeof * 8 | ||
| 77 | num_entries = mask.type.sizeof * 8 / bits_per_entry | ||
| 78 | entry = -1 | ||
| 79 | bits = 0 | ||
| 80 | |||
| 81 | while True: | ||
| 82 | while bits == 0: | ||
| 83 | entry += 1 | ||
| 84 | if entry == num_entries: | ||
| 85 | return | ||
| 86 | bits = mask[entry] | ||
| 87 | if bits != 0: | ||
| 88 | bit = 0 | ||
| 89 | break | ||
| 90 | |||
| 91 | while bits & 1 == 0: | ||
| 92 | bits >>= 1 | ||
| 93 | bit += 1 | ||
| 94 | |||
| 95 | cpu = entry * bits_per_entry + bit | ||
| 96 | |||
| 97 | bits >>= 1 | ||
| 98 | bit += 1 | ||
| 99 | |||
| 100 | yield cpu | ||
| 101 | |||
| 102 | |||
| 103 | class PerCpu(gdb.Function): | ||
| 104 | """Return per-cpu variable. | ||
| 105 | |||
| 106 | $lx_per_cpu("VAR"[, CPU]): Return the per-cpu variable called VAR for the | ||
| 107 | given CPU number. If CPU is omitted, the CPU of the current context is used. | ||
| 108 | Note that VAR has to be quoted as string.""" | ||
| 109 | |||
| 110 | def __init__(self): | ||
| 111 | super(PerCpu, self).__init__("lx_per_cpu") | ||
| 112 | |||
| 113 | def invoke(self, var_name, cpu=-1): | ||
| 114 | var_ptr = gdb.parse_and_eval("&" + var_name.string()) | ||
| 115 | return per_cpu(var_ptr, cpu) | ||
| 116 | |||
| 117 | |||
| 118 | PerCpu() | ||
| 119 | |||
| 120 | |||
| 121 | class LxCurrentFunc(gdb.Function): | ||
| 122 | """Return current task. | ||
| 123 | |||
| 124 | $lx_current([CPU]): Return the per-cpu task variable for the given CPU | ||
| 125 | number. If CPU is omitted, the CPU of the current context is used.""" | ||
| 126 | |||
| 127 | def __init__(self): | ||
| 128 | super(LxCurrentFunc, self).__init__("lx_current") | ||
| 129 | |||
| 130 | def invoke(self, cpu=-1): | ||
| 131 | var_ptr = gdb.parse_and_eval("¤t_task") | ||
| 132 | return per_cpu(var_ptr, cpu).dereference() | ||
| 133 | |||
| 134 | |||
| 135 | LxCurrentFunc() | ||
diff --git a/scripts/gdb/linux/dmesg.py b/scripts/gdb/linux/dmesg.py new file mode 100644 index 000000000000..3c947f0c5dad --- /dev/null +++ b/scripts/gdb/linux/dmesg.py | |||
| @@ -0,0 +1,65 @@ | |||
| 1 | # | ||
| 2 | # gdb helper commands and functions for Linux kernel debugging | ||
| 3 | # | ||
| 4 | # kernel log buffer dump | ||
| 5 | # | ||
| 6 | # Copyright (c) Siemens AG, 2011, 2012 | ||
| 7 | # | ||
| 8 | # Authors: | ||
| 9 | # Jan Kiszka <jan.kiszka@siemens.com> | ||
| 10 | # | ||
| 11 | # This work is licensed under the terms of the GNU GPL version 2. | ||
| 12 | # | ||
| 13 | |||
| 14 | import gdb | ||
| 15 | import string | ||
| 16 | |||
| 17 | from linux import utils | ||
| 18 | |||
| 19 | |||
| 20 | class LxDmesg(gdb.Command): | ||
| 21 | """Print Linux kernel log buffer.""" | ||
| 22 | |||
| 23 | def __init__(self): | ||
| 24 | super(LxDmesg, self).__init__("lx-dmesg", gdb.COMMAND_DATA) | ||
| 25 | |||
| 26 | def invoke(self, arg, from_tty): | ||
| 27 | log_buf_addr = int(str(gdb.parse_and_eval("log_buf")).split()[0], 16) | ||
| 28 | log_first_idx = int(gdb.parse_and_eval("log_first_idx")) | ||
| 29 | log_next_idx = int(gdb.parse_and_eval("log_next_idx")) | ||
| 30 | log_buf_len = int(gdb.parse_and_eval("log_buf_len")) | ||
| 31 | |||
| 32 | inf = gdb.inferiors()[0] | ||
| 33 | start = log_buf_addr + log_first_idx | ||
| 34 | if log_first_idx < log_next_idx: | ||
| 35 | log_buf_2nd_half = -1 | ||
| 36 | length = log_next_idx - log_first_idx | ||
| 37 | log_buf = inf.read_memory(start, length) | ||
| 38 | else: | ||
| 39 | log_buf_2nd_half = log_buf_len - log_first_idx | ||
| 40 | log_buf = inf.read_memory(start, log_buf_2nd_half) + \ | ||
| 41 | inf.read_memory(log_buf_addr, log_next_idx) | ||
| 42 | |||
| 43 | pos = 0 | ||
| 44 | while pos < log_buf.__len__(): | ||
| 45 | length = utils.read_u16(log_buf[pos + 8:pos + 10]) | ||
| 46 | if length == 0: | ||
| 47 | if log_buf_2nd_half == -1: | ||
| 48 | gdb.write("Corrupted log buffer!\n") | ||
| 49 | break | ||
| 50 | pos = log_buf_2nd_half | ||
| 51 | continue | ||
| 52 | |||
| 53 | text_len = utils.read_u16(log_buf[pos + 10:pos + 12]) | ||
| 54 | text = log_buf[pos + 16:pos + 16 + text_len] | ||
| 55 | time_stamp = utils.read_u64(log_buf[pos:pos + 8]) | ||
| 56 | |||
| 57 | for line in memoryview(text).tobytes().splitlines(): | ||
| 58 | gdb.write("[{time:12.6f}] {line}\n".format( | ||
| 59 | time=time_stamp / 1000000000.0, | ||
| 60 | line=line)) | ||
| 61 | |||
| 62 | pos += length | ||
| 63 | |||
| 64 | |||
| 65 | LxDmesg() | ||
diff --git a/scripts/gdb/linux/modules.py b/scripts/gdb/linux/modules.py new file mode 100644 index 000000000000..a1504c4f1900 --- /dev/null +++ b/scripts/gdb/linux/modules.py | |||
| @@ -0,0 +1,103 @@ | |||
| 1 | # | ||
| 2 | # gdb helper commands and functions for Linux kernel debugging | ||
| 3 | # | ||
| 4 | # module tools | ||
| 5 | # | ||
| 6 | # Copyright (c) Siemens AG, 2013 | ||
| 7 | # | ||
| 8 | # Authors: | ||
| 9 | # Jan Kiszka <jan.kiszka@siemens.com> | ||
| 10 | # | ||
| 11 | # This work is licensed under the terms of the GNU GPL version 2. | ||
| 12 | # | ||
| 13 | |||
| 14 | import gdb | ||
| 15 | |||
| 16 | from linux import cpus, utils | ||
| 17 | |||
| 18 | |||
| 19 | module_type = utils.CachedType("struct module") | ||
| 20 | |||
| 21 | |||
| 22 | def module_list(): | ||
| 23 | global module_type | ||
| 24 | module_ptr_type = module_type.get_type().pointer() | ||
| 25 | modules = gdb.parse_and_eval("modules") | ||
| 26 | entry = modules['next'] | ||
| 27 | end_of_list = modules.address | ||
| 28 | |||
| 29 | while entry != end_of_list: | ||
| 30 | yield utils.container_of(entry, module_ptr_type, "list") | ||
| 31 | entry = entry['next'] | ||
| 32 | |||
| 33 | |||
| 34 | def find_module_by_name(name): | ||
| 35 | for module in module_list(): | ||
| 36 | if module['name'].string() == name: | ||
| 37 | return module | ||
| 38 | return None | ||
| 39 | |||
| 40 | |||
| 41 | class LxModule(gdb.Function): | ||
| 42 | """Find module by name and return the module variable. | ||
| 43 | |||
| 44 | $lx_module("MODULE"): Given the name MODULE, iterate over all loaded modules | ||
| 45 | of the target and return that module variable which MODULE matches.""" | ||
| 46 | |||
| 47 | def __init__(self): | ||
| 48 | super(LxModule, self).__init__("lx_module") | ||
| 49 | |||
| 50 | def invoke(self, mod_name): | ||
| 51 | mod_name = mod_name.string() | ||
| 52 | module = find_module_by_name(mod_name) | ||
| 53 | if module: | ||
| 54 | return module.dereference() | ||
| 55 | else: | ||
| 56 | raise gdb.GdbError("Unable to find MODULE " + mod_name) | ||
| 57 | |||
| 58 | |||
| 59 | LxModule() | ||
| 60 | |||
| 61 | |||
| 62 | class LxLsmod(gdb.Command): | ||
| 63 | """List currently loaded modules.""" | ||
| 64 | |||
| 65 | _module_use_type = utils.CachedType("struct module_use") | ||
| 66 | |||
| 67 | def __init__(self): | ||
| 68 | super(LxLsmod, self).__init__("lx-lsmod", gdb.COMMAND_DATA) | ||
| 69 | |||
| 70 | def invoke(self, arg, from_tty): | ||
| 71 | gdb.write( | ||
| 72 | "Address{0} Module Size Used by\n".format( | ||
| 73 | " " if utils.get_long_type().sizeof == 8 else "")) | ||
| 74 | |||
| 75 | for module in module_list(): | ||
| 76 | ref = 0 | ||
| 77 | module_refptr = module['refptr'] | ||
| 78 | for cpu in cpus.cpu_list("cpu_possible_mask"): | ||
| 79 | refptr = cpus.per_cpu(module_refptr, cpu) | ||
| 80 | ref += refptr['incs'] | ||
| 81 | ref -= refptr['decs'] | ||
| 82 | |||
| 83 | gdb.write("{address} {name:<19} {size:>8} {ref}".format( | ||
| 84 | address=str(module['module_core']).split()[0], | ||
| 85 | name=module['name'].string(), | ||
| 86 | size=str(module['core_size']), | ||
| 87 | ref=str(ref))) | ||
| 88 | |||
| 89 | source_list = module['source_list'] | ||
| 90 | t = self._module_use_type.get_type().pointer() | ||
| 91 | entry = source_list['next'] | ||
| 92 | first = True | ||
| 93 | while entry != source_list.address: | ||
| 94 | use = utils.container_of(entry, t, "source_list") | ||
| 95 | gdb.write("{separator}{name}".format( | ||
| 96 | separator=" " if first else ",", | ||
| 97 | name=use['source']['name'].string())) | ||
| 98 | first = False | ||
| 99 | entry = entry['next'] | ||
| 100 | gdb.write("\n") | ||
| 101 | |||
| 102 | |||
| 103 | LxLsmod() | ||
diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py new file mode 100644 index 000000000000..cd5bea965d4e --- /dev/null +++ b/scripts/gdb/linux/symbols.py | |||
| @@ -0,0 +1,177 @@ | |||
| 1 | # | ||
| 2 | # gdb helper commands and functions for Linux kernel debugging | ||
| 3 | # | ||
| 4 | # load kernel and module symbols | ||
| 5 | # | ||
| 6 | # Copyright (c) Siemens AG, 2011-2013 | ||
| 7 | # | ||
| 8 | # Authors: | ||
| 9 | # Jan Kiszka <jan.kiszka@siemens.com> | ||
| 10 | # | ||
| 11 | # This work is licensed under the terms of the GNU GPL version 2. | ||
| 12 | # | ||
| 13 | |||
| 14 | import gdb | ||
| 15 | import os | ||
| 16 | import re | ||
| 17 | import string | ||
| 18 | |||
| 19 | from linux import modules, utils | ||
| 20 | |||
| 21 | |||
| 22 | if hasattr(gdb, 'Breakpoint'): | ||
| 23 | class LoadModuleBreakpoint(gdb.Breakpoint): | ||
| 24 | def __init__(self, spec, gdb_command): | ||
| 25 | super(LoadModuleBreakpoint, self).__init__(spec, internal=True) | ||
| 26 | self.silent = True | ||
| 27 | self.gdb_command = gdb_command | ||
| 28 | |||
| 29 | def stop(self): | ||
| 30 | module = gdb.parse_and_eval("mod") | ||
| 31 | module_name = module['name'].string() | ||
| 32 | cmd = self.gdb_command | ||
| 33 | |||
| 34 | # enforce update if object file is not found | ||
| 35 | cmd.module_files_updated = False | ||
| 36 | |||
| 37 | # Disable pagination while reporting symbol (re-)loading. | ||
| 38 | # The console input is blocked in this context so that we would | ||
| 39 | # get stuck waiting for the user to acknowledge paged output. | ||
| 40 | show_pagination = gdb.execute("show pagination", to_string=True) | ||
| 41 | pagination = show_pagination.endswith("on.\n") | ||
| 42 | gdb.execute("set pagination off") | ||
| 43 | |||
| 44 | if module_name in cmd.loaded_modules: | ||
| 45 | gdb.write("refreshing all symbols to reload module " | ||
| 46 | "'{0}'\n".format(module_name)) | ||
| 47 | cmd.load_all_symbols() | ||
| 48 | else: | ||
| 49 | cmd.load_module_symbols(module) | ||
| 50 | |||
| 51 | # restore pagination state | ||
| 52 | gdb.execute("set pagination %s" % ("on" if pagination else "off")) | ||
| 53 | |||
| 54 | return False | ||
| 55 | |||
| 56 | |||
| 57 | class LxSymbols(gdb.Command): | ||
| 58 | """(Re-)load symbols of Linux kernel and currently loaded modules. | ||
| 59 | |||
| 60 | The kernel (vmlinux) is taken from the current working directly. Modules (.ko) | ||
| 61 | are scanned recursively, starting in the same directory. Optionally, the module | ||
| 62 | search path can be extended by a space separated list of paths passed to the | ||
| 63 | lx-symbols command.""" | ||
| 64 | |||
| 65 | module_paths = [] | ||
| 66 | module_files = [] | ||
| 67 | module_files_updated = False | ||
| 68 | loaded_modules = [] | ||
| 69 | breakpoint = None | ||
| 70 | |||
| 71 | def __init__(self): | ||
| 72 | super(LxSymbols, self).__init__("lx-symbols", gdb.COMMAND_FILES, | ||
| 73 | gdb.COMPLETE_FILENAME) | ||
| 74 | |||
| 75 | def _update_module_files(self): | ||
| 76 | self.module_files = [] | ||
| 77 | for path in self.module_paths: | ||
| 78 | gdb.write("scanning for modules in {0}\n".format(path)) | ||
| 79 | for root, dirs, files in os.walk(path): | ||
| 80 | for name in files: | ||
| 81 | if name.endswith(".ko"): | ||
| 82 | self.module_files.append(root + "/" + name) | ||
| 83 | self.module_files_updated = True | ||
| 84 | |||
| 85 | def _get_module_file(self, module_name): | ||
| 86 | module_pattern = ".*/{0}\.ko$".format( | ||
| 87 | module_name.replace("_", r"[_\-]")) | ||
| 88 | for name in self.module_files: | ||
| 89 | if re.match(module_pattern, name) and os.path.exists(name): | ||
| 90 | return name | ||
| 91 | return None | ||
| 92 | |||
| 93 | def _section_arguments(self, module): | ||
| 94 | try: | ||
| 95 | sect_attrs = module['sect_attrs'].dereference() | ||
| 96 | except gdb.error: | ||
| 97 | return "" | ||
| 98 | attrs = sect_attrs['attrs'] | ||
| 99 | section_name_to_address = { | ||
| 100 | attrs[n]['name'].string() : attrs[n]['address'] | ||
| 101 | for n in range(int(sect_attrs['nsections']))} | ||
| 102 | args = [] | ||
| 103 | for section_name in [".data", ".data..read_mostly", ".rodata", ".bss"]: | ||
| 104 | address = section_name_to_address.get(section_name) | ||
| 105 | if address: | ||
| 106 | args.append(" -s {name} {addr}".format( | ||
| 107 | name=section_name, addr=str(address))) | ||
| 108 | return "".join(args) | ||
| 109 | |||
| 110 | def load_module_symbols(self, module): | ||
| 111 | module_name = module['name'].string() | ||
| 112 | module_addr = str(module['module_core']).split()[0] | ||
| 113 | |||
| 114 | module_file = self._get_module_file(module_name) | ||
| 115 | if not module_file and not self.module_files_updated: | ||
| 116 | self._update_module_files() | ||
| 117 | module_file = self._get_module_file(module_name) | ||
| 118 | |||
| 119 | if module_file: | ||
| 120 | gdb.write("loading @{addr}: {filename}\n".format( | ||
| 121 | addr=module_addr, filename=module_file)) | ||
| 122 | cmdline = "add-symbol-file {filename} {addr}{sections}".format( | ||
| 123 | filename=module_file, | ||
| 124 | addr=module_addr, | ||
| 125 | sections=self._section_arguments(module)) | ||
| 126 | gdb.execute(cmdline, to_string=True) | ||
| 127 | if not module_name in self.loaded_modules: | ||
| 128 | self.loaded_modules.append(module_name) | ||
| 129 | else: | ||
| 130 | gdb.write("no module object found for '{0}'\n".format(module_name)) | ||
| 131 | |||
| 132 | def load_all_symbols(self): | ||
| 133 | gdb.write("loading vmlinux\n") | ||
| 134 | |||
| 135 | # Dropping symbols will disable all breakpoints. So save their states | ||
| 136 | # and restore them afterward. | ||
| 137 | saved_states = [] | ||
| 138 | if hasattr(gdb, 'breakpoints') and not gdb.breakpoints() is None: | ||
| 139 | for bp in gdb.breakpoints(): | ||
| 140 | saved_states.append({'breakpoint': bp, 'enabled': bp.enabled}) | ||
| 141 | |||
| 142 | # drop all current symbols and reload vmlinux | ||
| 143 | gdb.execute("symbol-file", to_string=True) | ||
| 144 | gdb.execute("symbol-file vmlinux") | ||
| 145 | |||
| 146 | self.loaded_modules = [] | ||
| 147 | module_list = modules.module_list() | ||
| 148 | if not module_list: | ||
| 149 | gdb.write("no modules found\n") | ||
| 150 | else: | ||
| 151 | [self.load_module_symbols(module) for module in module_list] | ||
| 152 | |||
| 153 | for saved_state in saved_states: | ||
| 154 | saved_state['breakpoint'].enabled = saved_state['enabled'] | ||
| 155 | |||
| 156 | def invoke(self, arg, from_tty): | ||
| 157 | self.module_paths = arg.split() | ||
| 158 | self.module_paths.append(os.getcwd()) | ||
| 159 | |||
| 160 | # enforce update | ||
| 161 | self.module_files = [] | ||
| 162 | self.module_files_updated = False | ||
| 163 | |||
| 164 | self.load_all_symbols() | ||
| 165 | |||
| 166 | if hasattr(gdb, 'Breakpoint'): | ||
| 167 | if not self.breakpoint is None: | ||
| 168 | self.breakpoint.delete() | ||
| 169 | self.breakpoint = None | ||
| 170 | self.breakpoint = LoadModuleBreakpoint( | ||
| 171 | "kernel/module.c:do_init_module", self) | ||
| 172 | else: | ||
| 173 | gdb.write("Note: symbol update on module loading not supported " | ||
| 174 | "with this gdb version\n") | ||
| 175 | |||
| 176 | |||
| 177 | LxSymbols() | ||
diff --git a/scripts/gdb/linux/tasks.py b/scripts/gdb/linux/tasks.py new file mode 100644 index 000000000000..e2037d9bb7eb --- /dev/null +++ b/scripts/gdb/linux/tasks.py | |||
| @@ -0,0 +1,100 @@ | |||
| 1 | # | ||
| 2 | # gdb helper commands and functions for Linux kernel debugging | ||
| 3 | # | ||
| 4 | # task & thread tools | ||
| 5 | # | ||
| 6 | # Copyright (c) Siemens AG, 2011-2013 | ||
| 7 | # | ||
| 8 | # Authors: | ||
| 9 | # Jan Kiszka <jan.kiszka@siemens.com> | ||
| 10 | # | ||
| 11 | # This work is licensed under the terms of the GNU GPL version 2. | ||
| 12 | # | ||
| 13 | |||
| 14 | import gdb | ||
| 15 | |||
| 16 | from linux import utils | ||
| 17 | |||
| 18 | |||
| 19 | task_type = utils.CachedType("struct task_struct") | ||
| 20 | |||
| 21 | def task_lists(): | ||
| 22 | global task_type | ||
| 23 | task_ptr_type = task_type.get_type().pointer() | ||
| 24 | init_task = gdb.parse_and_eval("init_task").address | ||
| 25 | t = g = init_task | ||
| 26 | |||
| 27 | while True: | ||
| 28 | while True: | ||
| 29 | yield t | ||
| 30 | |||
| 31 | t = utils.container_of(t['thread_group']['next'], | ||
| 32 | task_ptr_type, "thread_group") | ||
| 33 | if t == g: | ||
| 34 | break | ||
| 35 | |||
| 36 | t = g = utils.container_of(g['tasks']['next'], | ||
| 37 | task_ptr_type, "tasks") | ||
| 38 | if t == init_task: | ||
| 39 | return | ||
| 40 | |||
| 41 | def get_task_by_pid(pid): | ||
| 42 | for task in task_lists(): | ||
| 43 | if int(task['pid']) == pid: | ||
| 44 | return task | ||
| 45 | return None | ||
| 46 | |||
| 47 | |||
| 48 | class LxTaskByPidFunc(gdb.Function): | ||
| 49 | """Find Linux task by PID and return the task_struct variable. | ||
| 50 | |||
| 51 | $lx_task_by_pid(PID): Given PID, iterate over all tasks of the target and | ||
| 52 | return that task_struct variable which PID matches.""" | ||
| 53 | |||
| 54 | def __init__(self): | ||
| 55 | super(LxTaskByPidFunc, self).__init__("lx_task_by_pid") | ||
| 56 | |||
| 57 | def invoke(self, pid): | ||
| 58 | task = get_task_by_pid(pid) | ||
| 59 | if task: | ||
| 60 | return task.dereference() | ||
| 61 | else: | ||
| 62 | raise gdb.GdbError("No task of PID " + str(pid)) | ||
| 63 | |||
| 64 | |||
| 65 | LxTaskByPidFunc() | ||
| 66 | |||
| 67 | |||
| 68 | thread_info_type = utils.CachedType("struct thread_info") | ||
| 69 | |||
| 70 | ia64_task_size = None | ||
| 71 | |||
| 72 | |||
| 73 | def get_thread_info(task): | ||
| 74 | global thread_info_type | ||
| 75 | thread_info_ptr_type = thread_info_type.get_type().pointer() | ||
| 76 | if utils.is_target_arch("ia64"): | ||
| 77 | global ia64_task_size | ||
| 78 | if ia64_task_size is None: | ||
| 79 | ia64_task_size = gdb.parse_and_eval("sizeof(struct task_struct)") | ||
| 80 | thread_info_addr = task.address + ia64_task_size | ||
| 81 | thread_info = thread_info_addr.cast(thread_info_ptr_type) | ||
| 82 | else: | ||
| 83 | thread_info = task['stack'].cast(thread_info_ptr_type) | ||
| 84 | return thread_info.dereference() | ||
| 85 | |||
| 86 | |||
| 87 | class LxThreadInfoFunc (gdb.Function): | ||
| 88 | """Calculate Linux thread_info from task variable. | ||
| 89 | |||
| 90 | $lx_thread_info(TASK): Given TASK, return the corresponding thread_info | ||
| 91 | variable.""" | ||
| 92 | |||
| 93 | def __init__(self): | ||
| 94 | super(LxThreadInfoFunc, self).__init__("lx_thread_info") | ||
| 95 | |||
| 96 | def invoke(self, task): | ||
| 97 | return get_thread_info(task) | ||
| 98 | |||
| 99 | |||
| 100 | LxThreadInfoFunc() | ||
diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py new file mode 100644 index 000000000000..128c306db3ee --- /dev/null +++ b/scripts/gdb/linux/utils.py | |||
| @@ -0,0 +1,156 @@ | |||
| 1 | # | ||
| 2 | # gdb helper commands and functions for Linux kernel debugging | ||
| 3 | # | ||
| 4 | # common utilities | ||
| 5 | # | ||
| 6 | # Copyright (c) Siemens AG, 2011-2013 | ||
| 7 | # | ||
| 8 | # Authors: | ||
| 9 | # Jan Kiszka <jan.kiszka@siemens.com> | ||
| 10 | # | ||
| 11 | # This work is licensed under the terms of the GNU GPL version 2. | ||
| 12 | # | ||
| 13 | |||
| 14 | import gdb | ||
| 15 | |||
| 16 | |||
| 17 | class CachedType: | ||
| 18 | def __init__(self, name): | ||
| 19 | self._type = None | ||
| 20 | self._name = name | ||
| 21 | |||
| 22 | def _new_objfile_handler(self, event): | ||
| 23 | self._type = None | ||
| 24 | gdb.events.new_objfile.disconnect(self._new_objfile_handler) | ||
| 25 | |||
| 26 | def get_type(self): | ||
| 27 | if self._type is None: | ||
| 28 | self._type = gdb.lookup_type(self._name) | ||
| 29 | if self._type is None: | ||
| 30 | raise gdb.GdbError( | ||
| 31 | "cannot resolve type '{0}'".format(self._name)) | ||
| 32 | if hasattr(gdb, 'events') and hasattr(gdb.events, 'new_objfile'): | ||
| 33 | gdb.events.new_objfile.connect(self._new_objfile_handler) | ||
| 34 | return self._type | ||
| 35 | |||
| 36 | |||
| 37 | long_type = CachedType("long") | ||
| 38 | |||
| 39 | |||
| 40 | def get_long_type(): | ||
| 41 | global long_type | ||
| 42 | return long_type.get_type() | ||
| 43 | |||
| 44 | |||
| 45 | def offset_of(typeobj, field): | ||
| 46 | element = gdb.Value(0).cast(typeobj) | ||
| 47 | return int(str(element[field].address).split()[0], 16) | ||
| 48 | |||
| 49 | |||
| 50 | def container_of(ptr, typeobj, member): | ||
| 51 | return (ptr.cast(get_long_type()) - | ||
| 52 | offset_of(typeobj, member)).cast(typeobj) | ||
| 53 | |||
| 54 | |||
| 55 | class ContainerOf(gdb.Function): | ||
| 56 | """Return pointer to containing data structure. | ||
| 57 | |||
| 58 | $container_of(PTR, "TYPE", "ELEMENT"): Given PTR, return a pointer to the | ||
| 59 | data structure of the type TYPE in which PTR is the address of ELEMENT. | ||
| 60 | Note that TYPE and ELEMENT have to be quoted as strings.""" | ||
| 61 | |||
| 62 | def __init__(self): | ||
| 63 | super(ContainerOf, self).__init__("container_of") | ||
| 64 | |||
| 65 | def invoke(self, ptr, typename, elementname): | ||
| 66 | return container_of(ptr, gdb.lookup_type(typename.string()).pointer(), | ||
| 67 | elementname.string()) | ||
| 68 | |||
| 69 | ContainerOf() | ||
| 70 | |||
| 71 | |||
| 72 | BIG_ENDIAN = 0 | ||
| 73 | LITTLE_ENDIAN = 1 | ||
| 74 | target_endianness = None | ||
| 75 | |||
| 76 | |||
| 77 | def get_target_endianness(): | ||
| 78 | global target_endianness | ||
| 79 | if target_endianness is None: | ||
| 80 | endian = gdb.execute("show endian", to_string=True) | ||
| 81 | if "little endian" in endian: | ||
| 82 | target_endianness = LITTLE_ENDIAN | ||
| 83 | elif "big endian" in endian: | ||
| 84 | target_endianness = BIG_ENDIAN | ||
| 85 | else: | ||
| 86 | raise gdb.GdgError("unknown endianness '{0}'".format(str(endian))) | ||
| 87 | return target_endianness | ||
| 88 | |||
| 89 | |||
| 90 | def read_u16(buffer): | ||
| 91 | if get_target_endianness() == LITTLE_ENDIAN: | ||
| 92 | return ord(buffer[0]) + (ord(buffer[1]) << 8) | ||
| 93 | else: | ||
| 94 | return ord(buffer[1]) + (ord(buffer[0]) << 8) | ||
| 95 | |||
| 96 | |||
| 97 | def read_u32(buffer): | ||
| 98 | if get_target_endianness() == LITTLE_ENDIAN: | ||
| 99 | return read_u16(buffer[0:2]) + (read_u16(buffer[2:4]) << 16) | ||
| 100 | else: | ||
| 101 | return read_u16(buffer[2:4]) + (read_u16(buffer[0:2]) << 16) | ||
| 102 | |||
| 103 | |||
| 104 | def read_u64(buffer): | ||
| 105 | if get_target_endianness() == LITTLE_ENDIAN: | ||
| 106 | return read_u32(buffer[0:4]) + (read_u32(buffer[4:8]) << 32) | ||
| 107 | else: | ||
| 108 | return read_u32(buffer[4:8]) + (read_u32(buffer[0:4]) << 32) | ||
| 109 | |||
| 110 | |||
| 111 | target_arch = None | ||
| 112 | |||
| 113 | |||
| 114 | def is_target_arch(arch): | ||
| 115 | if hasattr(gdb.Frame, 'architecture'): | ||
| 116 | return arch in gdb.newest_frame().architecture().name() | ||
| 117 | else: | ||
| 118 | global target_arch | ||
| 119 | if target_arch is None: | ||
| 120 | target_arch = gdb.execute("show architecture", to_string=True) | ||
| 121 | return arch in target_arch | ||
| 122 | |||
| 123 | |||
| 124 | GDBSERVER_QEMU = 0 | ||
| 125 | GDBSERVER_KGDB = 1 | ||
| 126 | gdbserver_type = None | ||
| 127 | |||
| 128 | |||
| 129 | def get_gdbserver_type(): | ||
| 130 | def exit_handler(event): | ||
| 131 | global gdbserver_type | ||
| 132 | gdbserver_type = None | ||
| 133 | gdb.events.exited.disconnect(exit_handler) | ||
| 134 | |||
| 135 | def probe_qemu(): | ||
| 136 | try: | ||
| 137 | return gdb.execute("monitor info version", to_string=True) != "" | ||
| 138 | except: | ||
| 139 | return False | ||
| 140 | |||
| 141 | def probe_kgdb(): | ||
| 142 | try: | ||
| 143 | thread_info = gdb.execute("info thread 2", to_string=True) | ||
| 144 | return "shadowCPU0" in thread_info | ||
| 145 | except: | ||
| 146 | return False | ||
| 147 | |||
| 148 | global gdbserver_type | ||
| 149 | if gdbserver_type is None: | ||
| 150 | if probe_qemu(): | ||
| 151 | gdbserver_type = GDBSERVER_QEMU | ||
| 152 | elif probe_kgdb(): | ||
| 153 | gdbserver_type = GDBSERVER_KGDB | ||
| 154 | if not gdbserver_type is None and hasattr(gdb, 'events'): | ||
| 155 | gdb.events.exited.connect(exit_handler) | ||
| 156 | return gdbserver_type | ||
diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py new file mode 100644 index 000000000000..48489285f119 --- /dev/null +++ b/scripts/gdb/vmlinux-gdb.py | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | # | ||
| 2 | # gdb helper commands and functions for Linux kernel debugging | ||
| 3 | # | ||
| 4 | # loader module | ||
| 5 | # | ||
| 6 | # Copyright (c) Siemens AG, 2012, 2013 | ||
| 7 | # | ||
| 8 | # Authors: | ||
| 9 | # Jan Kiszka <jan.kiszka@siemens.com> | ||
| 10 | # | ||
| 11 | # This work is licensed under the terms of the GNU GPL version 2. | ||
| 12 | # | ||
| 13 | |||
| 14 | import os | ||
| 15 | |||
| 16 | sys.path.insert(0, os.path.dirname(__file__) + "/scripts/gdb") | ||
| 17 | |||
| 18 | try: | ||
| 19 | gdb.parse_and_eval("0") | ||
| 20 | gdb.execute("", to_string=True) | ||
| 21 | except: | ||
| 22 | gdb.write("NOTE: gdb 7.2 or later required for Linux helper scripts to " | ||
| 23 | "work.\n") | ||
| 24 | else: | ||
| 25 | import linux.utils | ||
| 26 | import linux.symbols | ||
| 27 | import linux.modules | ||
| 28 | import linux.dmesg | ||
| 29 | import linux.tasks | ||
| 30 | import linux.cpus | ||
diff --git a/security/commoncap.c b/security/commoncap.c index 2915d8503054..f66713bd7450 100644 --- a/security/commoncap.c +++ b/security/commoncap.c | |||
| @@ -434,7 +434,6 @@ int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data | |||
| 434 | */ | 434 | */ |
| 435 | static int get_file_caps(struct linux_binprm *bprm, bool *effective, bool *has_cap) | 435 | static int get_file_caps(struct linux_binprm *bprm, bool *effective, bool *has_cap) |
| 436 | { | 436 | { |
| 437 | struct dentry *dentry; | ||
| 438 | int rc = 0; | 437 | int rc = 0; |
| 439 | struct cpu_vfs_cap_data vcaps; | 438 | struct cpu_vfs_cap_data vcaps; |
| 440 | 439 | ||
| @@ -446,9 +445,7 @@ static int get_file_caps(struct linux_binprm *bprm, bool *effective, bool *has_c | |||
| 446 | if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) | 445 | if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) |
| 447 | return 0; | 446 | return 0; |
| 448 | 447 | ||
| 449 | dentry = dget(bprm->file->f_path.dentry); | 448 | rc = get_vfs_caps_from_disk(bprm->file->f_path.dentry, &vcaps); |
| 450 | |||
| 451 | rc = get_vfs_caps_from_disk(dentry, &vcaps); | ||
| 452 | if (rc < 0) { | 449 | if (rc < 0) { |
| 453 | if (rc == -EINVAL) | 450 | if (rc == -EINVAL) |
| 454 | printk(KERN_NOTICE "%s: get_vfs_caps_from_disk returned %d for %s\n", | 451 | printk(KERN_NOTICE "%s: get_vfs_caps_from_disk returned %d for %s\n", |
| @@ -464,7 +461,6 @@ static int get_file_caps(struct linux_binprm *bprm, bool *effective, bool *has_c | |||
| 464 | __func__, rc, bprm->filename); | 461 | __func__, rc, bprm->filename); |
| 465 | 462 | ||
| 466 | out: | 463 | out: |
| 467 | dput(dentry); | ||
| 468 | if (rc) | 464 | if (rc) |
| 469 | bprm_clear_caps(bprm); | 465 | bprm_clear_caps(bprm); |
| 470 | 466 | ||
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 0c7aea4dea54..486ef6fa393b 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
| @@ -414,6 +414,7 @@ link_check_failed: | |||
| 414 | 414 | ||
| 415 | link_prealloc_failed: | 415 | link_prealloc_failed: |
| 416 | mutex_unlock(&user->cons_lock); | 416 | mutex_unlock(&user->cons_lock); |
| 417 | key_put(key); | ||
| 417 | kleave(" = %d [prelink]", ret); | 418 | kleave(" = %d [prelink]", ret); |
| 418 | return ret; | 419 | return ret; |
| 419 | 420 | ||
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 33db1ad4fd10..1684bcc78b34 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
| @@ -1195,30 +1195,8 @@ static const struct file_operations sel_commit_bools_ops = { | |||
| 1195 | 1195 | ||
| 1196 | static void sel_remove_entries(struct dentry *de) | 1196 | static void sel_remove_entries(struct dentry *de) |
| 1197 | { | 1197 | { |
| 1198 | struct list_head *node; | 1198 | d_genocide(de); |
| 1199 | 1199 | shrink_dcache_parent(de); | |
| 1200 | spin_lock(&de->d_lock); | ||
| 1201 | node = de->d_subdirs.next; | ||
| 1202 | while (node != &de->d_subdirs) { | ||
| 1203 | struct dentry *d = list_entry(node, struct dentry, d_child); | ||
| 1204 | |||
| 1205 | spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED); | ||
| 1206 | list_del_init(node); | ||
| 1207 | |||
| 1208 | if (d->d_inode) { | ||
| 1209 | dget_dlock(d); | ||
| 1210 | spin_unlock(&de->d_lock); | ||
| 1211 | spin_unlock(&d->d_lock); | ||
| 1212 | d_delete(d); | ||
| 1213 | simple_unlink(de->d_inode, d); | ||
| 1214 | dput(d); | ||
| 1215 | spin_lock(&de->d_lock); | ||
| 1216 | } else | ||
| 1217 | spin_unlock(&d->d_lock); | ||
| 1218 | node = de->d_subdirs.next; | ||
| 1219 | } | ||
| 1220 | |||
| 1221 | spin_unlock(&de->d_lock); | ||
| 1222 | } | 1200 | } |
| 1223 | 1201 | ||
| 1224 | #define BOOL_DIR_NAME "booleans" | 1202 | #define BOOL_DIR_NAME "booleans" |
| @@ -1668,37 +1646,13 @@ static int sel_make_class_dir_entries(char *classname, int index, | |||
| 1668 | return rc; | 1646 | return rc; |
| 1669 | } | 1647 | } |
| 1670 | 1648 | ||
| 1671 | static void sel_remove_classes(void) | ||
| 1672 | { | ||
| 1673 | struct list_head *class_node; | ||
| 1674 | |||
| 1675 | list_for_each(class_node, &class_dir->d_subdirs) { | ||
| 1676 | struct dentry *class_subdir = list_entry(class_node, | ||
| 1677 | struct dentry, d_child); | ||
| 1678 | struct list_head *class_subdir_node; | ||
| 1679 | |||
| 1680 | list_for_each(class_subdir_node, &class_subdir->d_subdirs) { | ||
| 1681 | struct dentry *d = list_entry(class_subdir_node, | ||
| 1682 | struct dentry, d_child); | ||
| 1683 | |||
| 1684 | if (d->d_inode) | ||
| 1685 | if (d->d_inode->i_mode & S_IFDIR) | ||
| 1686 | sel_remove_entries(d); | ||
| 1687 | } | ||
| 1688 | |||
| 1689 | sel_remove_entries(class_subdir); | ||
| 1690 | } | ||
| 1691 | |||
| 1692 | sel_remove_entries(class_dir); | ||
| 1693 | } | ||
| 1694 | |||
| 1695 | static int sel_make_classes(void) | 1649 | static int sel_make_classes(void) |
| 1696 | { | 1650 | { |
| 1697 | int rc, nclasses, i; | 1651 | int rc, nclasses, i; |
| 1698 | char **classes; | 1652 | char **classes; |
| 1699 | 1653 | ||
| 1700 | /* delete any existing entries */ | 1654 | /* delete any existing entries */ |
| 1701 | sel_remove_classes(); | 1655 | sel_remove_entries(class_dir); |
| 1702 | 1656 | ||
| 1703 | rc = security_get_classes(&classes, &nclasses); | 1657 | rc = security_get_classes(&classes, &nclasses); |
| 1704 | if (rc) | 1658 | if (rc) |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index a0ccce4e46f8..ed94f6f836e7 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
| @@ -3818,6 +3818,18 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
| 3818 | } | 3818 | } |
| 3819 | #endif /* CONFIG_IPV6 */ | 3819 | #endif /* CONFIG_IPV6 */ |
| 3820 | 3820 | ||
| 3821 | #ifdef CONFIG_SECURITY_SMACK_NETFILTER | ||
| 3822 | /* | ||
| 3823 | * If there is a secmark use it rather than the CIPSO label. | ||
| 3824 | * If there is no secmark fall back to CIPSO. | ||
| 3825 | * The secmark is assumed to reflect policy better. | ||
| 3826 | */ | ||
| 3827 | if (skb && skb->secmark != 0) { | ||
| 3828 | skp = smack_from_secid(skb->secmark); | ||
| 3829 | goto access_check; | ||
| 3830 | } | ||
| 3831 | #endif /* CONFIG_SECURITY_SMACK_NETFILTER */ | ||
| 3832 | |||
| 3821 | netlbl_secattr_init(&secattr); | 3833 | netlbl_secattr_init(&secattr); |
| 3822 | rc = netlbl_skbuff_getattr(skb, family, &secattr); | 3834 | rc = netlbl_skbuff_getattr(skb, family, &secattr); |
| 3823 | if (rc == 0) | 3835 | if (rc == 0) |
| @@ -3826,6 +3838,10 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
| 3826 | skp = &smack_known_huh; | 3838 | skp = &smack_known_huh; |
| 3827 | netlbl_secattr_destroy(&secattr); | 3839 | netlbl_secattr_destroy(&secattr); |
| 3828 | 3840 | ||
| 3841 | #ifdef CONFIG_SECURITY_SMACK_NETFILTER | ||
| 3842 | access_check: | ||
| 3843 | #endif | ||
| 3844 | |||
| 3829 | #ifdef CONFIG_AUDIT | 3845 | #ifdef CONFIG_AUDIT |
| 3830 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); | 3846 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); |
| 3831 | ad.a.u.net->family = family; | 3847 | ad.a.u.net->family = family; |
